staging: comedi: me4000: fix firmware downloading
Convert this driver to use comedi_load_firmware() to download the firmware to the board. Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com> Reviewed-by: Ian Abbott <abbotti@mev.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
0cf5efaa4b
commit
ac584af599
@ -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.
|
|||||||
#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 = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#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)
|
|||||||
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,
|
|||||||
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);
|
|||||||
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);
|
||||||
|
Loading…
Reference in New Issue
Block a user