aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/atm/solos-pci.c
diff options
context:
space:
mode:
authorSimon Farnsworth <simon@farnz.org.uk>2009-01-21 15:45:49 -0500
committerDavid Woodhouse <David.Woodhouse@intel.com>2009-01-26 22:18:32 -0500
commit7c4015bdffed7c961b6df46c6326cc65962e6594 (patch)
treeb5b043ac75cb9bd696f8a563919f14eb8394d429 /drivers/atm/solos-pci.c
parent4306cad6fe02e2946183ab29e510f94190b8fff3 (diff)
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>
Diffstat (limited to 'drivers/atm/solos-pci.c')
-rw-r--r--drivers/atm/solos-pci.c171
1 files changed, 169 insertions, 2 deletions
diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c
index 3daa3a374313..2b472c898c85 100644
--- a/drivers/atm/solos-pci.c
+++ b/drivers/atm/solos-pci.c
@@ -9,6 +9,7 @@
9 * 9 *
10 * Authors: Nathan Williams <nathan@traverse.com.au> 10 * Authors: Nathan Williams <nathan@traverse.com.au>
11 * David Woodhouse <dwmw2@infradead.org> 11 * David Woodhouse <dwmw2@infradead.org>
12 * Treker Chen <treker@xrio.com>
12 * 13 *
13 * This program is free software; you can redistribute it and/or 14 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License 15 * modify it under the terms of the GNU General Public License
@@ -36,8 +37,9 @@
36#include <linux/sysfs.h> 37#include <linux/sysfs.h>
37#include <linux/device.h> 38#include <linux/device.h>
38#include <linux/kobject.h> 39#include <linux/kobject.h>
40#include <linux/firmware.h>
39 41
40#define VERSION "0.04" 42#define VERSION "0.07"
41#define PTAG "solos-pci" 43#define PTAG "solos-pci"
42 44
43#define CONFIG_RAM_SIZE 128 45#define CONFIG_RAM_SIZE 128
@@ -45,16 +47,27 @@
45#define IRQ_EN_ADDR 0x78 47#define IRQ_EN_ADDR 0x78
46#define FPGA_VER 0x74 48#define FPGA_VER 0x74
47#define IRQ_CLEAR 0x70 49#define IRQ_CLEAR 0x70
48#define BUG_FLAG 0x6C 50#define WRITE_FLASH 0x6C
51#define PORTS 0x68
52#define FLASH_BLOCK 0x64
53#define FLASH_BUSY 0x60
54#define FPGA_MODE 0x5C
55#define FLASH_MODE 0x58
49 56
50#define DATA_RAM_SIZE 32768 57#define DATA_RAM_SIZE 32768
51#define BUF_SIZE 4096 58#define BUF_SIZE 4096
59#define FPGA_PAGE 528 /* FPGA flash page size*/
60#define SOLOS_PAGE 512 /* Solos flash page size*/
61#define FPGA_BLOCK (FPGA_PAGE * 8) /* FPGA flash block size*/
62#define SOLOS_BLOCK (SOLOS_PAGE * 8) /* Solos flash block size*/
52 63
53#define RX_BUF(card, nr) ((card->buffers) + (nr)*BUF_SIZE*2) 64#define RX_BUF(card, nr) ((card->buffers) + (nr)*BUF_SIZE*2)
54#define TX_BUF(card, nr) ((card->buffers) + (nr)*BUF_SIZE*2 + BUF_SIZE) 65#define TX_BUF(card, nr) ((card->buffers) + (nr)*BUF_SIZE*2 + BUF_SIZE)
55 66
56static int debug = 0; 67static int debug = 0;
57static int atmdebug = 0; 68static int atmdebug = 0;
69static int firmware_upgrade = 0;
70static int fpga_upgrade = 0;
58 71
59struct pkt_hdr { 72struct pkt_hdr {
60 __le16 size; 73 __le16 size;
@@ -80,6 +93,7 @@ struct solos_card {
80 spinlock_t cli_queue_lock; 93 spinlock_t cli_queue_lock;
81 struct sk_buff_head tx_queue[4]; 94 struct sk_buff_head tx_queue[4];
82 struct sk_buff_head cli_queue[4]; 95 struct sk_buff_head cli_queue[4];
96 int flash_chip;
83}; 97};
84 98
85#define SOLOS_CHAN(atmdev) ((int)(unsigned long)(atmdev)->phy_data) 99#define SOLOS_CHAN(atmdev) ((int)(unsigned long)(atmdev)->phy_data)
@@ -90,11 +104,19 @@ MODULE_VERSION(VERSION);
90MODULE_LICENSE("GPL"); 104MODULE_LICENSE("GPL");
91MODULE_PARM_DESC(debug, "Enable Loopback"); 105MODULE_PARM_DESC(debug, "Enable Loopback");
92MODULE_PARM_DESC(atmdebug, "Print ATM data"); 106MODULE_PARM_DESC(atmdebug, "Print ATM data");
107MODULE_PARM_DESC(firmware_upgrade, "Initiate Solos firmware upgrade");
108MODULE_PARM_DESC(fpga_upgrade, "Initiate FPGA upgrade");
93module_param(debug, int, 0444); 109module_param(debug, int, 0444);
94module_param(atmdebug, int, 0644); 110module_param(atmdebug, int, 0644);
111module_param(firmware_upgrade, int, 0444);
112module_param(fpga_upgrade, int, 0444);
95 113
96static int opens; 114static int opens;
115static struct firmware *fw;
116static int flash_offset;
97 117
118void flash_upgrade(struct solos_card *);
119void flash_write(struct solos_card *);
98static void fpga_queue(struct solos_card *card, int port, struct sk_buff *skb, 120static void fpga_queue(struct solos_card *card, int port, struct sk_buff *skb,
99 struct atm_vcc *vcc); 121 struct atm_vcc *vcc);
100static int fpga_tx(struct solos_card *); 122static int fpga_tx(struct solos_card *);
@@ -180,6 +202,131 @@ static ssize_t console_store(struct device *dev, struct device_attribute *attr,
180 202
181static DEVICE_ATTR(console, 0644, console_show, console_store); 203static DEVICE_ATTR(console, 0644, console_show, console_store);
182 204
205void flash_upgrade(struct solos_card *card){
206 uint32_t data32 = 0;
207 int blocksize = 0;
208 int numblocks = 0;
209 dev_info(&card->dev->dev, "Flash upgrade started\n");
210 if (card->flash_chip == 0) {
211 if (request_firmware((const struct firmware **)&fw,
212 "solos-FPGA.bin",&card->dev->dev))
213 {
214 dev_info(&card->dev->dev,
215 "Failed to find firmware\n");
216 return;
217 }
218 blocksize = FPGA_BLOCK;
219 } else {
220 if (request_firmware((const struct firmware **)&fw,
221 "solos-Firmware.bin",&card->dev->dev))
222 {
223 dev_info(&card->dev->dev,
224 "Failed to find firmware\n");
225 return;
226 }
227 blocksize = SOLOS_BLOCK;
228 }
229 numblocks = fw->size/blocksize;
230 dev_info(&card->dev->dev, "Firmware size: %d\n", fw->size);
231 dev_info(&card->dev->dev, "Number of blocks: %d\n", numblocks);
232
233
234 dev_info(&card->dev->dev, "Changing FPGA to Update mode\n");
235 iowrite32(1, card->config_regs + FPGA_MODE);
236 data32 = ioread32(card->config_regs + FPGA_MODE);
237 /*Set mode to Chip Erase*/
238 if (card->flash_chip == 0) {
239 dev_info(&card->dev->dev,
240 "Set FPGA Flash mode to FPGA Chip Erase\n");
241 } else {
242 dev_info(&card->dev->dev,
243 "Set FPGA Flash mode to Solos Chip Erase\n");
244 }
245 iowrite32((card->flash_chip * 2), card->config_regs + FLASH_MODE);
246 flash_offset = 0;
247 iowrite32(1, card->config_regs + WRITE_FLASH);
248 return;
249}
250
251void flash_write(struct solos_card *card){
252 int block;
253 int block_num;
254 int blocksize;
255 int i;
256 uint32_t data32 = 0;
257
258 /*Clear write flag*/
259 iowrite32(0, card->config_regs + WRITE_FLASH);
260 /*Set mode to Block Write*/
261 /*dev_info(&card->dev->dev, "Set FPGA Flash mode to Block Write\n");*/
262 iowrite32(((card->flash_chip * 2) + 1), card->config_regs + FLASH_MODE);
263
264 /*When finished programming flash, release firmware and exit*/
265 if (fw->size - flash_offset == 0) {
266 //release_firmware(fw); /* This crashes for some reason */
267 iowrite32(0, card->config_regs + WRITE_FLASH);
268 iowrite32(0, card->config_regs + FPGA_MODE);
269 iowrite32(0, card->config_regs + FLASH_MODE);
270 dev_info(&card->dev->dev, "Returning FPGA to Data mode\n");
271 return;
272 }
273 if (card->flash_chip == 0) {
274 blocksize = FPGA_BLOCK;
275 } else {
276 blocksize = SOLOS_BLOCK;
277 }
278
279 /*Calculate block size*/
280 if ((fw->size - flash_offset) > blocksize) {
281 block = blocksize;
282 } else {
283 block = fw->size - flash_offset;
284 }
285 block_num = flash_offset / blocksize;
286 //dev_info(&card->dev->dev, "block %d/%d\n",block_num + 1,(fw->size/512/8));
287
288 /*Copy block into RAM*/
289 for(i=0;i<block;i++){
290 if(i%4 == 0){
291 //dev_info(&card->dev->dev, "i: %d\n", i);
292 data32=0x00000000;
293 }
294
295 switch(i%4){
296 case 0:
297 data32 |= 0x0000FF00 &
298 (*(fw->data + i + flash_offset) << 8);
299 break;
300 case 1:
301 data32 |= 0x000000FF & *(fw->data + i + flash_offset);
302 break;
303 case 2:
304 data32 |= 0xFF000000 &
305 (*(fw->data + i + flash_offset) << 24);
306 break;
307 case 3:
308 data32 |= 0x00FF0000 &
309 (*(fw->data + i + flash_offset) << 16);
310 break;
311 }
312
313 if (i%4 == 3) {
314 iowrite32(data32, RX_BUF(card, 3) + i - 3);
315 }
316 }
317 i--;
318 if (i%4 != 3) {
319 iowrite32(data32, RX_BUF(card, 3) + i - (i%4));
320 }
321
322 /*Specify block number and then trigger flash write*/
323 iowrite32(block_num, card->config_regs + FLASH_BLOCK);
324 iowrite32(1, card->config_regs + WRITE_FLASH);
325// iowrite32(0, card->config_regs + WRITE_FLASH);
326 flash_offset += block;
327 return;
328}
329
183static irqreturn_t solos_irq(int irq, void *dev_id) 330static irqreturn_t solos_irq(int irq, void *dev_id)
184{ 331{
185 struct solos_card *card = dev_id; 332 struct solos_card *card = dev_id;
@@ -207,6 +354,17 @@ void solos_bh(unsigned long card_arg)
207 uint32_t card_flags; 354 uint32_t card_flags;
208 uint32_t tx_mask; 355 uint32_t tx_mask;
209 uint32_t rx_done = 0; 356 uint32_t rx_done = 0;
357 uint32_t data32;
358
359 data32 = ioread32(card->config_regs + FPGA_MODE);
360 if (data32 != 0) {
361 data32 = ioread32(card->config_regs + FLASH_BUSY);
362 if (data32 == 0) {
363 flash_write(card);
364 }
365 return;
366 }
367
210 368
211 card_flags = ioread32(card->config_regs + FLAGS_ADDR); 369 card_flags = ioread32(card->config_regs + FLAGS_ADDR);
212 370
@@ -680,6 +838,15 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id)
680 // Enable IRQs 838 // Enable IRQs
681 iowrite32(1, card->config_regs + IRQ_EN_ADDR); 839 iowrite32(1, card->config_regs + IRQ_EN_ADDR);
682 840
841 if(firmware_upgrade != 0){
842 card->flash_chip = 1;
843 flash_upgrade(card);
844 } else {
845 if(fpga_upgrade != 0){
846 card->flash_chip = 0;
847 flash_upgrade(card);
848 }
849 }
683 return 0; 850 return 0;
684 851
685 out_unmap_both: 852 out_unmap_both: