Commit ac584af5 authored by H Hartley Sweeten's avatar H Hartley Sweeten Committed by Greg Kroah-Hartman

staging: comedi: me4000: fix firmware downloading

Convert this driver to use comedi_load_firmware() to download the firmware
to the board.
Signed-off-by: default avatarH Hartley Sweeten <hsweeten@visionengravers.com>
Reviewed-by: default avatarIan Abbott <abbotti@mev.co.uk>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 0cf5efaa
...@@ -44,8 +44,6 @@ broken. ...@@ -44,8 +44,6 @@ broken.
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/list.h>
#include <linux/spinlock.h>
#include "../comedidev.h" #include "../comedidev.h"
...@@ -53,10 +51,7 @@ broken. ...@@ -53,10 +51,7 @@ broken.
#include "8253.h" #include "8253.h"
#include "plx9052.h" #include "plx9052.h"
#if 0 #define ME4000_FIRMWARE "me4000_firmware.bin"
/* file removed due to GPL incompatibility */
#include "me4000_fw.h"
#endif
/* /*
* ME4000 Register map and bit defines * ME4000 Register map and bit defines
...@@ -333,27 +328,20 @@ static const struct comedi_lrange me4000_ai_range = { ...@@ -333,27 +328,20 @@ static const struct comedi_lrange me4000_ai_range = {
} }
}; };
#define FIRMWARE_NOT_AVAILABLE 1 static int me4000_xilinx_download(struct comedi_device *dev,
#if FIRMWARE_NOT_AVAILABLE const u8 *data, size_t size,
extern unsigned char *xilinx_firm; unsigned long context)
#endif
static int xilinx_download(struct comedi_device *dev)
{ {
struct pci_dev *pcidev = comedi_to_pci_dev(dev); struct pci_dev *pcidev = comedi_to_pci_dev(dev);
struct me4000_info *info = dev->private; struct me4000_info *info = dev->private;
unsigned long xilinx_iobase = pci_resource_start(pcidev, 5); unsigned long xilinx_iobase = pci_resource_start(pcidev, 5);
u32 value = 0; unsigned int file_length;
wait_queue_head_t queue; unsigned int val;
int idx = 0; unsigned int i;
int size = 0;
unsigned int intcsr;
if (!xilinx_iobase) if (!xilinx_iobase)
return -ENODEV; return -ENODEV;
init_waitqueue_head(&queue);
/* /*
* Set PLX local interrupt 2 polarity to high. * Set PLX local interrupt 2 polarity to high.
* Interrupt is thrown by init pin of xilinx. * Interrupt is thrown by init pin of xilinx.
...@@ -361,61 +349,58 @@ static int xilinx_download(struct comedi_device *dev) ...@@ -361,61 +349,58 @@ static int xilinx_download(struct comedi_device *dev)
outl(PLX9052_INTCSR_LI2POL, info->plx_regbase + PLX9052_INTCSR); outl(PLX9052_INTCSR_LI2POL, info->plx_regbase + PLX9052_INTCSR);
/* Set /CS and /WRITE of the Xilinx */ /* Set /CS and /WRITE of the Xilinx */
value = inl(info->plx_regbase + PLX9052_CNTRL); val = inl(info->plx_regbase + PLX9052_CNTRL);
value |= PLX9052_CNTRL_UIO2_DATA; val |= PLX9052_CNTRL_UIO2_DATA;
outl(value, info->plx_regbase + PLX9052_CNTRL); outl(val, info->plx_regbase + PLX9052_CNTRL);
/* Init Xilinx with CS1 */ /* Init Xilinx with CS1 */
inb(xilinx_iobase + 0xC8); inb(xilinx_iobase + 0xC8);
/* Wait until /INIT pin is set */ /* Wait until /INIT pin is set */
udelay(20); udelay(20);
intcsr = inl(info->plx_regbase + PLX9052_INTCSR); val = inl(info->plx_regbase + PLX9052_INTCSR);
if (!(intcsr & PLX9052_INTCSR_LI2STAT)) { if (!(val & PLX9052_INTCSR_LI2STAT)) {
dev_err(dev->class_dev, "Can't init Xilinx\n"); dev_err(dev->class_dev, "Can't init Xilinx\n");
return -EIO; return -EIO;
} }
/* Reset /CS and /WRITE of the Xilinx */ /* Reset /CS and /WRITE of the Xilinx */
value = inl(info->plx_regbase + PLX9052_CNTRL); val = inl(info->plx_regbase + PLX9052_CNTRL);
value &= ~PLX9052_CNTRL_UIO2_DATA; val &= ~PLX9052_CNTRL_UIO2_DATA;
outl(value, info->plx_regbase + PLX9052_CNTRL); outl(val, info->plx_regbase + PLX9052_CNTRL);
if (FIRMWARE_NOT_AVAILABLE) {
dev_err(dev->class_dev,
"xilinx firmware unavailable due to licensing, aborting");
return -EIO;
} else {
/* Download Xilinx firmware */ /* Download Xilinx firmware */
size = (xilinx_firm[0] << 24) + (xilinx_firm[1] << 16) + file_length = (((unsigned int)data[0] & 0xff) << 24) +
(xilinx_firm[2] << 8) + xilinx_firm[3]; (((unsigned int)data[1] & 0xff) << 16) +
(((unsigned int)data[2] & 0xff) << 8) +
((unsigned int)data[3] & 0xff);
udelay(10); udelay(10);
for (idx = 0; idx < size; idx++) { for (i = 0; i < file_length; i++) {
outb(xilinx_firm[16 + idx], xilinx_iobase); outb(data[16 + i], xilinx_iobase);
udelay(10); udelay(10);
/* Check if BUSY flag is low */ /* Check if BUSY flag is low */
if (inl(info->plx_regbase + PLX9052_CNTRL) & PLX9052_CNTRL_UIO1_DATA) { val = inl(info->plx_regbase + PLX9052_CNTRL);
if (val & PLX9052_CNTRL_UIO1_DATA) {
dev_err(dev->class_dev, dev_err(dev->class_dev,
"Xilinx is still busy (idx = %d)\n", "Xilinx is still busy (i = %d)\n", i);
idx);
return -EIO; return -EIO;
} }
} }
}
/* If done flag is high download was successful */ /* If done flag is high download was successful */
if (inl(info->plx_regbase + PLX9052_CNTRL) & PLX9052_CNTRL_UIO0_DATA) { val = inl(info->plx_regbase + PLX9052_CNTRL);
} else { if (!(val & PLX9052_CNTRL_UIO0_DATA)) {
dev_err(dev->class_dev, "DONE flag is not set\n"); dev_err(dev->class_dev, "DONE flag is not set\n");
dev_err(dev->class_dev, "Download not successful\n"); dev_err(dev->class_dev, "Download not successful\n");
return -EIO; return -EIO;
} }
/* Set /CS and /WRITE */ /* Set /CS and /WRITE */
value = inl(info->plx_regbase + PLX9052_CNTRL); val = inl(info->plx_regbase + PLX9052_CNTRL);
value |= PLX9052_CNTRL_UIO2_DATA; val |= PLX9052_CNTRL_UIO2_DATA;
outl(value, info->plx_regbase + PLX9052_CNTRL); outl(val, info->plx_regbase + PLX9052_CNTRL);
return 0; return 0;
} }
...@@ -1386,8 +1371,9 @@ static int me4000_auto_attach(struct comedi_device *dev, ...@@ -1386,8 +1371,9 @@ static int me4000_auto_attach(struct comedi_device *dev,
if (!info->plx_regbase || !dev->iobase || !info->timer_regbase) if (!info->plx_regbase || !dev->iobase || !info->timer_regbase)
return -ENODEV; return -ENODEV;
result = xilinx_download(dev); result = comedi_load_firmware(dev, &pcidev->dev, ME4000_FIRMWARE,
if (result) me4000_xilinx_download, 0);
if (result < 0)
return result; return result;
me4000_reset(dev); me4000_reset(dev);
...@@ -1550,3 +1536,4 @@ module_comedi_pci_driver(me4000_driver, me4000_pci_driver); ...@@ -1550,3 +1536,4 @@ module_comedi_pci_driver(me4000_driver, me4000_pci_driver);
MODULE_AUTHOR("Comedi http://www.comedi.org"); MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver"); MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_FIRMWARE(ME4000_FIRMWARE);
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment