solos: FPGA and firmware update support.
This is just a straight pull in of changes, syncing us up to 0.07 from openadsl.sf.net Signed-off-by: Nathan Williams <nathan@traverse.com.au> Signed-off-by: Simon Farnsworth <simon@farnz.org.uk> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
This commit is contained in:
parent
4306cad6fe
commit
7c4015bdff
@ -9,6 +9,7 @@
|
|||||||
*
|
*
|
||||||
* Authors: Nathan Williams <nathan@traverse.com.au>
|
* Authors: Nathan Williams <nathan@traverse.com.au>
|
||||||
* David Woodhouse <dwmw2@infradead.org>
|
* David Woodhouse <dwmw2@infradead.org>
|
||||||
|
* Treker Chen <treker@xrio.com>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
@ -36,8 +37,9 @@
|
|||||||
#include <linux/sysfs.h>
|
#include <linux/sysfs.h>
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
#include <linux/kobject.h>
|
#include <linux/kobject.h>
|
||||||
|
#include <linux/firmware.h>
|
||||||
|
|
||||||
#define VERSION "0.04"
|
#define VERSION "0.07"
|
||||||
#define PTAG "solos-pci"
|
#define PTAG "solos-pci"
|
||||||
|
|
||||||
#define CONFIG_RAM_SIZE 128
|
#define CONFIG_RAM_SIZE 128
|
||||||
@ -45,16 +47,27 @@
|
|||||||
#define IRQ_EN_ADDR 0x78
|
#define IRQ_EN_ADDR 0x78
|
||||||
#define FPGA_VER 0x74
|
#define FPGA_VER 0x74
|
||||||
#define IRQ_CLEAR 0x70
|
#define IRQ_CLEAR 0x70
|
||||||
#define BUG_FLAG 0x6C
|
#define WRITE_FLASH 0x6C
|
||||||
|
#define PORTS 0x68
|
||||||
|
#define FLASH_BLOCK 0x64
|
||||||
|
#define FLASH_BUSY 0x60
|
||||||
|
#define FPGA_MODE 0x5C
|
||||||
|
#define FLASH_MODE 0x58
|
||||||
|
|
||||||
#define DATA_RAM_SIZE 32768
|
#define DATA_RAM_SIZE 32768
|
||||||
#define BUF_SIZE 4096
|
#define BUF_SIZE 4096
|
||||||
|
#define FPGA_PAGE 528 /* FPGA flash page size*/
|
||||||
|
#define SOLOS_PAGE 512 /* Solos flash page size*/
|
||||||
|
#define FPGA_BLOCK (FPGA_PAGE * 8) /* FPGA flash block size*/
|
||||||
|
#define SOLOS_BLOCK (SOLOS_PAGE * 8) /* Solos flash block size*/
|
||||||
|
|
||||||
#define RX_BUF(card, nr) ((card->buffers) + (nr)*BUF_SIZE*2)
|
#define RX_BUF(card, nr) ((card->buffers) + (nr)*BUF_SIZE*2)
|
||||||
#define TX_BUF(card, nr) ((card->buffers) + (nr)*BUF_SIZE*2 + BUF_SIZE)
|
#define TX_BUF(card, nr) ((card->buffers) + (nr)*BUF_SIZE*2 + BUF_SIZE)
|
||||||
|
|
||||||
static int debug = 0;
|
static int debug = 0;
|
||||||
static int atmdebug = 0;
|
static int atmdebug = 0;
|
||||||
|
static int firmware_upgrade = 0;
|
||||||
|
static int fpga_upgrade = 0;
|
||||||
|
|
||||||
struct pkt_hdr {
|
struct pkt_hdr {
|
||||||
__le16 size;
|
__le16 size;
|
||||||
@ -80,6 +93,7 @@ struct solos_card {
|
|||||||
spinlock_t cli_queue_lock;
|
spinlock_t cli_queue_lock;
|
||||||
struct sk_buff_head tx_queue[4];
|
struct sk_buff_head tx_queue[4];
|
||||||
struct sk_buff_head cli_queue[4];
|
struct sk_buff_head cli_queue[4];
|
||||||
|
int flash_chip;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SOLOS_CHAN(atmdev) ((int)(unsigned long)(atmdev)->phy_data)
|
#define SOLOS_CHAN(atmdev) ((int)(unsigned long)(atmdev)->phy_data)
|
||||||
@ -90,11 +104,19 @@ MODULE_VERSION(VERSION);
|
|||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
MODULE_PARM_DESC(debug, "Enable Loopback");
|
MODULE_PARM_DESC(debug, "Enable Loopback");
|
||||||
MODULE_PARM_DESC(atmdebug, "Print ATM data");
|
MODULE_PARM_DESC(atmdebug, "Print ATM data");
|
||||||
|
MODULE_PARM_DESC(firmware_upgrade, "Initiate Solos firmware upgrade");
|
||||||
|
MODULE_PARM_DESC(fpga_upgrade, "Initiate FPGA upgrade");
|
||||||
module_param(debug, int, 0444);
|
module_param(debug, int, 0444);
|
||||||
module_param(atmdebug, int, 0644);
|
module_param(atmdebug, int, 0644);
|
||||||
|
module_param(firmware_upgrade, int, 0444);
|
||||||
|
module_param(fpga_upgrade, int, 0444);
|
||||||
|
|
||||||
static int opens;
|
static int opens;
|
||||||
|
static struct firmware *fw;
|
||||||
|
static int flash_offset;
|
||||||
|
|
||||||
|
void flash_upgrade(struct solos_card *);
|
||||||
|
void flash_write(struct solos_card *);
|
||||||
static void fpga_queue(struct solos_card *card, int port, struct sk_buff *skb,
|
static void fpga_queue(struct solos_card *card, int port, struct sk_buff *skb,
|
||||||
struct atm_vcc *vcc);
|
struct atm_vcc *vcc);
|
||||||
static int fpga_tx(struct solos_card *);
|
static int fpga_tx(struct solos_card *);
|
||||||
@ -180,6 +202,131 @@ static ssize_t console_store(struct device *dev, struct device_attribute *attr,
|
|||||||
|
|
||||||
static DEVICE_ATTR(console, 0644, console_show, console_store);
|
static DEVICE_ATTR(console, 0644, console_show, console_store);
|
||||||
|
|
||||||
|
void flash_upgrade(struct solos_card *card){
|
||||||
|
uint32_t data32 = 0;
|
||||||
|
int blocksize = 0;
|
||||||
|
int numblocks = 0;
|
||||||
|
dev_info(&card->dev->dev, "Flash upgrade started\n");
|
||||||
|
if (card->flash_chip == 0) {
|
||||||
|
if (request_firmware((const struct firmware **)&fw,
|
||||||
|
"solos-FPGA.bin",&card->dev->dev))
|
||||||
|
{
|
||||||
|
dev_info(&card->dev->dev,
|
||||||
|
"Failed to find firmware\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
blocksize = FPGA_BLOCK;
|
||||||
|
} else {
|
||||||
|
if (request_firmware((const struct firmware **)&fw,
|
||||||
|
"solos-Firmware.bin",&card->dev->dev))
|
||||||
|
{
|
||||||
|
dev_info(&card->dev->dev,
|
||||||
|
"Failed to find firmware\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
blocksize = SOLOS_BLOCK;
|
||||||
|
}
|
||||||
|
numblocks = fw->size/blocksize;
|
||||||
|
dev_info(&card->dev->dev, "Firmware size: %d\n", fw->size);
|
||||||
|
dev_info(&card->dev->dev, "Number of blocks: %d\n", numblocks);
|
||||||
|
|
||||||
|
|
||||||
|
dev_info(&card->dev->dev, "Changing FPGA to Update mode\n");
|
||||||
|
iowrite32(1, card->config_regs + FPGA_MODE);
|
||||||
|
data32 = ioread32(card->config_regs + FPGA_MODE);
|
||||||
|
/*Set mode to Chip Erase*/
|
||||||
|
if (card->flash_chip == 0) {
|
||||||
|
dev_info(&card->dev->dev,
|
||||||
|
"Set FPGA Flash mode to FPGA Chip Erase\n");
|
||||||
|
} else {
|
||||||
|
dev_info(&card->dev->dev,
|
||||||
|
"Set FPGA Flash mode to Solos Chip Erase\n");
|
||||||
|
}
|
||||||
|
iowrite32((card->flash_chip * 2), card->config_regs + FLASH_MODE);
|
||||||
|
flash_offset = 0;
|
||||||
|
iowrite32(1, card->config_regs + WRITE_FLASH);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void flash_write(struct solos_card *card){
|
||||||
|
int block;
|
||||||
|
int block_num;
|
||||||
|
int blocksize;
|
||||||
|
int i;
|
||||||
|
uint32_t data32 = 0;
|
||||||
|
|
||||||
|
/*Clear write flag*/
|
||||||
|
iowrite32(0, card->config_regs + WRITE_FLASH);
|
||||||
|
/*Set mode to Block Write*/
|
||||||
|
/*dev_info(&card->dev->dev, "Set FPGA Flash mode to Block Write\n");*/
|
||||||
|
iowrite32(((card->flash_chip * 2) + 1), card->config_regs + FLASH_MODE);
|
||||||
|
|
||||||
|
/*When finished programming flash, release firmware and exit*/
|
||||||
|
if (fw->size - flash_offset == 0) {
|
||||||
|
//release_firmware(fw); /* This crashes for some reason */
|
||||||
|
iowrite32(0, card->config_regs + WRITE_FLASH);
|
||||||
|
iowrite32(0, card->config_regs + FPGA_MODE);
|
||||||
|
iowrite32(0, card->config_regs + FLASH_MODE);
|
||||||
|
dev_info(&card->dev->dev, "Returning FPGA to Data mode\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (card->flash_chip == 0) {
|
||||||
|
blocksize = FPGA_BLOCK;
|
||||||
|
} else {
|
||||||
|
blocksize = SOLOS_BLOCK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*Calculate block size*/
|
||||||
|
if ((fw->size - flash_offset) > blocksize) {
|
||||||
|
block = blocksize;
|
||||||
|
} else {
|
||||||
|
block = fw->size - flash_offset;
|
||||||
|
}
|
||||||
|
block_num = flash_offset / blocksize;
|
||||||
|
//dev_info(&card->dev->dev, "block %d/%d\n",block_num + 1,(fw->size/512/8));
|
||||||
|
|
||||||
|
/*Copy block into RAM*/
|
||||||
|
for(i=0;i<block;i++){
|
||||||
|
if(i%4 == 0){
|
||||||
|
//dev_info(&card->dev->dev, "i: %d\n", i);
|
||||||
|
data32=0x00000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(i%4){
|
||||||
|
case 0:
|
||||||
|
data32 |= 0x0000FF00 &
|
||||||
|
(*(fw->data + i + flash_offset) << 8);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
data32 |= 0x000000FF & *(fw->data + i + flash_offset);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
data32 |= 0xFF000000 &
|
||||||
|
(*(fw->data + i + flash_offset) << 24);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
data32 |= 0x00FF0000 &
|
||||||
|
(*(fw->data + i + flash_offset) << 16);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i%4 == 3) {
|
||||||
|
iowrite32(data32, RX_BUF(card, 3) + i - 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i--;
|
||||||
|
if (i%4 != 3) {
|
||||||
|
iowrite32(data32, RX_BUF(card, 3) + i - (i%4));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*Specify block number and then trigger flash write*/
|
||||||
|
iowrite32(block_num, card->config_regs + FLASH_BLOCK);
|
||||||
|
iowrite32(1, card->config_regs + WRITE_FLASH);
|
||||||
|
// iowrite32(0, card->config_regs + WRITE_FLASH);
|
||||||
|
flash_offset += block;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
static irqreturn_t solos_irq(int irq, void *dev_id)
|
static irqreturn_t solos_irq(int irq, void *dev_id)
|
||||||
{
|
{
|
||||||
struct solos_card *card = dev_id;
|
struct solos_card *card = dev_id;
|
||||||
@ -207,6 +354,17 @@ void solos_bh(unsigned long card_arg)
|
|||||||
uint32_t card_flags;
|
uint32_t card_flags;
|
||||||
uint32_t tx_mask;
|
uint32_t tx_mask;
|
||||||
uint32_t rx_done = 0;
|
uint32_t rx_done = 0;
|
||||||
|
uint32_t data32;
|
||||||
|
|
||||||
|
data32 = ioread32(card->config_regs + FPGA_MODE);
|
||||||
|
if (data32 != 0) {
|
||||||
|
data32 = ioread32(card->config_regs + FLASH_BUSY);
|
||||||
|
if (data32 == 0) {
|
||||||
|
flash_write(card);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
card_flags = ioread32(card->config_regs + FLAGS_ADDR);
|
card_flags = ioread32(card->config_regs + FLAGS_ADDR);
|
||||||
|
|
||||||
@ -680,6 +838,15 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
|||||||
// Enable IRQs
|
// Enable IRQs
|
||||||
iowrite32(1, card->config_regs + IRQ_EN_ADDR);
|
iowrite32(1, card->config_regs + IRQ_EN_ADDR);
|
||||||
|
|
||||||
|
if(firmware_upgrade != 0){
|
||||||
|
card->flash_chip = 1;
|
||||||
|
flash_upgrade(card);
|
||||||
|
} else {
|
||||||
|
if(fpga_upgrade != 0){
|
||||||
|
card->flash_chip = 0;
|
||||||
|
flash_upgrade(card);
|
||||||
|
}
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
out_unmap_both:
|
out_unmap_both:
|
||||||
|
Loading…
Reference in New Issue
Block a user