aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/atm
diff options
context:
space:
mode:
authorDavid Woodhouse <David.Woodhouse@intel.com>2009-01-26 22:16:12 -0500
committerDavid Woodhouse <David.Woodhouse@intel.com>2009-01-26 22:19:26 -0500
commitfa755b9f2b03df1e0fa6d01b8949bbc778705973 (patch)
tree703a48b707c2f4350e624bac0891e128da9c7f77 /drivers/atm
parent7c4015bdffed7c961b6df46c6326cc65962e6594 (diff)
solos: Clean up firmware loading code
We no longer try to load firmware while the ATM is up and running. However, this means that we _do_ make init_module() wait for it, and it takes a long time for now (since we're using ultra-conservative code in the FPGA for that too). The inner loop which uses swahb32p() was by Simon Farnsworth. Simon has patches which migrate us to request_firmware_nowait(), for which we'll actually need to take down the ATM devices, do the upgrade, then reregister them. Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'drivers/atm')
-rw-r--r--drivers/atm/solos-pci.c209
1 files changed, 73 insertions, 136 deletions
diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c
index 2b472c898c85..89bdf733af90 100644
--- a/drivers/atm/solos-pci.c
+++ b/drivers/atm/solos-pci.c
@@ -93,7 +93,7 @@ struct solos_card {
93 spinlock_t cli_queue_lock; 93 spinlock_t cli_queue_lock;
94 struct sk_buff_head tx_queue[4]; 94 struct sk_buff_head tx_queue[4];
95 struct sk_buff_head cli_queue[4]; 95 struct sk_buff_head cli_queue[4];
96 int flash_chip; 96 wait_queue_head_t fw_wq;
97}; 97};
98 98
99#define SOLOS_CHAN(atmdev) ((int)(unsigned long)(atmdev)->phy_data) 99#define SOLOS_CHAN(atmdev) ((int)(unsigned long)(atmdev)->phy_data)
@@ -112,11 +112,7 @@ module_param(firmware_upgrade, int, 0444);
112module_param(fpga_upgrade, int, 0444); 112module_param(fpga_upgrade, int, 0444);
113 113
114static int opens; 114static int opens;
115static struct firmware *fw;
116static int flash_offset;
117 115
118void flash_upgrade(struct solos_card *);
119void flash_write(struct solos_card *);
120static void fpga_queue(struct solos_card *card, int port, struct sk_buff *skb, 116static void fpga_queue(struct solos_card *card, int port, struct sk_buff *skb,
121 struct atm_vcc *vcc); 117 struct atm_vcc *vcc);
122static int fpga_tx(struct solos_card *); 118static int fpga_tx(struct solos_card *);
@@ -202,129 +198,73 @@ static ssize_t console_store(struct device *dev, struct device_attribute *attr,
202 198
203static DEVICE_ATTR(console, 0644, console_show, console_store); 199static DEVICE_ATTR(console, 0644, console_show, console_store);
204 200
205void flash_upgrade(struct solos_card *card){ 201static int flash_upgrade(struct solos_card *card, int chip)
202{
203 const struct firmware *fw;
204 const char *fw_name;
206 uint32_t data32 = 0; 205 uint32_t data32 = 0;
207 int blocksize = 0; 206 int blocksize = 0;
208 int numblocks = 0; 207 int numblocks = 0;
209 dev_info(&card->dev->dev, "Flash upgrade started\n"); 208 int offset;
210 if (card->flash_chip == 0) { 209
211 if (request_firmware((const struct firmware **)&fw, 210 if (chip == 0) {
212 "solos-FPGA.bin",&card->dev->dev)) 211 fw_name = "solos-FPGA.bin";
213 {
214 dev_info(&card->dev->dev,
215 "Failed to find firmware\n");
216 return;
217 }
218 blocksize = FPGA_BLOCK; 212 blocksize = FPGA_BLOCK;
219 } else { 213 } else {
220 if (request_firmware((const struct firmware **)&fw, 214 fw_name = "solos-Firmware.bin";
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; 215 blocksize = SOLOS_BLOCK;
228 } 216 }
229 numblocks = fw->size/blocksize; 217
230 dev_info(&card->dev->dev, "Firmware size: %d\n", fw->size); 218 if (request_firmware(&fw, fw_name, &card->dev->dev))
219 return -ENOENT;
220
221 dev_info(&card->dev->dev, "Flash upgrade starting\n");
222
223 numblocks = fw->size / blocksize;
224 dev_info(&card->dev->dev, "Firmware size: %zd\n", fw->size);
231 dev_info(&card->dev->dev, "Number of blocks: %d\n", numblocks); 225 dev_info(&card->dev->dev, "Number of blocks: %d\n", numblocks);
232 226
233
234 dev_info(&card->dev->dev, "Changing FPGA to Update mode\n"); 227 dev_info(&card->dev->dev, "Changing FPGA to Update mode\n");
235 iowrite32(1, card->config_regs + FPGA_MODE); 228 iowrite32(1, card->config_regs + FPGA_MODE);
236 data32 = ioread32(card->config_regs + FPGA_MODE); 229 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 230
251void flash_write(struct solos_card *card){ 231 /* Set mode to Chip Erase */
252 int block; 232 dev_info(&card->dev->dev, "Set FPGA Flash mode to %s Chip Erase\n",
253 int block_num; 233 chip?"Solos":"FPGA");
254 int blocksize; 234 iowrite32((chip * 2), card->config_regs + FLASH_MODE);
255 int i;
256 uint32_t data32 = 0;
257 235
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 236
264 /*When finished programming flash, release firmware and exit*/ 237 iowrite32(1, card->config_regs + WRITE_FLASH);
265 if (fw->size - flash_offset == 0) { 238 wait_event(card->fw_wq, !ioread32(card->config_regs + FLASH_BUSY));
266 //release_firmware(fw); /* This crashes for some reason */ 239
240 for (offset = 0; offset < fw->size; offset += blocksize) {
241 int i;
242
243 /* Clear write flag */
267 iowrite32(0, card->config_regs + WRITE_FLASH); 244 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 245
313 if (i%4 == 3) { 246 /* Set mode to Block Write */
314 iowrite32(data32, RX_BUF(card, 3) + i - 3); 247 /* dev_info(&card->dev->dev, "Set FPGA Flash mode to Block Write\n"); */
248 iowrite32(((chip * 2) + 1), card->config_regs + FLASH_MODE);
249
250 /* Copy block to buffer, swapping each 16 bits */
251 for(i = 0; i < blocksize; i += 4) {
252 uint32_t word = swahb32p((uint32_t *)(fw->data + offset + i));
253 iowrite32(word, RX_BUF(card, 3) + i);
315 } 254 }
316 } 255
317 i--; 256 /* Specify block number and then trigger flash write */
318 if (i%4 != 3) { 257 iowrite32(offset / blocksize, card->config_regs + FLASH_BLOCK);
319 iowrite32(data32, RX_BUF(card, 3) + i - (i%4)); 258 iowrite32(1, card->config_regs + WRITE_FLASH);
259 wait_event(card->fw_wq, !ioread32(card->config_regs + FLASH_BUSY));
320 } 260 }
321 261
322 /*Specify block number and then trigger flash write*/ 262 release_firmware(fw);
323 iowrite32(block_num, card->config_regs + FLASH_BLOCK); 263 iowrite32(0, card->config_regs + WRITE_FLASH);
324 iowrite32(1, card->config_regs + WRITE_FLASH); 264 iowrite32(0, card->config_regs + FPGA_MODE);
325// iowrite32(0, card->config_regs + WRITE_FLASH); 265 iowrite32(0, card->config_regs + FLASH_MODE);
326 flash_offset += block; 266 dev_info(&card->dev->dev, "Returning FPGA to Data mode\n");
327 return; 267 return 0;
328} 268}
329 269
330static irqreturn_t solos_irq(int irq, void *dev_id) 270static irqreturn_t solos_irq(int irq, void *dev_id)
@@ -337,10 +277,10 @@ static irqreturn_t solos_irq(int irq, void *dev_id)
337 //Disable IRQs from FPGA 277 //Disable IRQs from FPGA
338 iowrite32(0, card->config_regs + IRQ_EN_ADDR); 278 iowrite32(0, card->config_regs + IRQ_EN_ADDR);
339 279
340 /* If we only do it when the device is open, we lose console 280 if (card->atmdev[0])
341 messages */
342 if (1 || opens)
343 tasklet_schedule(&card->tlet); 281 tasklet_schedule(&card->tlet);
282 else
283 wake_up(&card->fw_wq);
344 284
345 //Enable IRQs from FPGA 285 //Enable IRQs from FPGA
346 iowrite32(1, card->config_regs + IRQ_EN_ADDR); 286 iowrite32(1, card->config_regs + IRQ_EN_ADDR);
@@ -354,17 +294,6 @@ void solos_bh(unsigned long card_arg)
354 uint32_t card_flags; 294 uint32_t card_flags;
355 uint32_t tx_mask; 295 uint32_t tx_mask;
356 uint32_t rx_done = 0; 296 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
368 297
369 card_flags = ioread32(card->config_regs + FLAGS_ADDR); 298 card_flags = ioread32(card->config_regs + FLAGS_ADDR);
370 299
@@ -749,6 +678,7 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id)
749 return -ENOMEM; 678 return -ENOMEM;
750 679
751 card->dev = dev; 680 card->dev = dev;
681 init_waitqueue_head(&card->fw_wq);
752 682
753 err = pci_enable_device(dev); 683 err = pci_enable_device(dev);
754 if (err) { 684 if (err) {
@@ -794,15 +724,13 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id)
794 724
795 card->nr_ports = 2; /* FIXME: Detect daughterboard */ 725 card->nr_ports = 2; /* FIXME: Detect daughterboard */
796 726
797 err = atm_init(card);
798 if (err)
799 goto out_unmap_both;
800
801 pci_set_drvdata(dev, card); 727 pci_set_drvdata(dev, card);
728
802 tasklet_init(&card->tlet, solos_bh, (unsigned long)card); 729 tasklet_init(&card->tlet, solos_bh, (unsigned long)card);
803 spin_lock_init(&card->tx_lock); 730 spin_lock_init(&card->tx_lock);
804 spin_lock_init(&card->tx_queue_lock); 731 spin_lock_init(&card->tx_queue_lock);
805 spin_lock_init(&card->cli_queue_lock); 732 spin_lock_init(&card->cli_queue_lock);
733
806/* 734/*
807 // Set Loopback mode 735 // Set Loopback mode
808 data32 = 0x00010000; 736 data32 = 0x00010000;
@@ -832,24 +760,33 @@ static int fpga_probe(struct pci_dev *dev, const struct pci_device_id *id)
832 //dev_dbg(&card->dev->dev, "Requesting IRQ: %d\n",dev->irq); 760 //dev_dbg(&card->dev->dev, "Requesting IRQ: %d\n",dev->irq);
833 err = request_irq(dev->irq, solos_irq, IRQF_DISABLED|IRQF_SHARED, 761 err = request_irq(dev->irq, solos_irq, IRQF_DISABLED|IRQF_SHARED,
834 "solos-pci", card); 762 "solos-pci", card);
835 if (err) 763 if (err) {
836 dev_dbg(&card->dev->dev, "Failed to request interrupt IRQ: %d\n", dev->irq); 764 dev_dbg(&card->dev->dev, "Failed to request interrupt IRQ: %d\n", dev->irq);
765 goto out_unmap_both;
766 }
837 767
838 // Enable IRQs 768 // Enable IRQs
839 iowrite32(1, card->config_regs + IRQ_EN_ADDR); 769 iowrite32(1, card->config_regs + IRQ_EN_ADDR);
840 770
841 if(firmware_upgrade != 0){ 771 if (fpga_upgrade)
842 card->flash_chip = 1; 772 flash_upgrade(card, 0);
843 flash_upgrade(card); 773
844 } else { 774 if (firmware_upgrade)
845 if(fpga_upgrade != 0){ 775 flash_upgrade(card, 1);
846 card->flash_chip = 0; 776
847 flash_upgrade(card); 777 err = atm_init(card);
848 } 778 if (err)
849 } 779 goto out_free_irq;
780
850 return 0; 781 return 0;
851 782
783 out_free_irq:
784 iowrite32(0, card->config_regs + IRQ_EN_ADDR);
785 free_irq(dev->irq, card);
786 tasklet_kill(&card->tlet);
787
852 out_unmap_both: 788 out_unmap_both:
789 pci_set_drvdata(dev, NULL);
853 pci_iounmap(dev, card->config_regs); 790 pci_iounmap(dev, card->config_regs);
854 out_unmap_config: 791 out_unmap_config:
855 pci_iounmap(dev, card->buffers); 792 pci_iounmap(dev, card->buffers);