diff options
author | Ian Abbott <abbotti@mev.co.uk> | 2012-09-14 17:34:16 +0100 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-09-17 05:09:06 -0700 |
commit | 9fb5c14ceba8841ece02b5185501e1d999a2bcf6 (patch) | |
tree | 85ab8f81c0bba43a961d63ff5ace8cb5acbdafa8 /drivers | |
parent | 6b26ecf0479e660e878014030b1f6e53d3787d75 (diff) | |
download | linux-3.10-9fb5c14ceba8841ece02b5185501e1d999a2bcf6.tar.gz linux-3.10-9fb5c14ceba8841ece02b5185501e1d999a2bcf6.tar.bz2 linux-3.10-9fb5c14ceba8841ece02b5185501e1d999a2bcf6.zip |
staging: comedi: ni_pcidio: use request_firmware()
The PCI-6534 needs three firmware files loading to work with the driver.
That is currently done by passing the firmware data using the
`COMEDI_DEVCONFIG` ioctl that uses the comedi `attach()` hook in the
driver. This doesn't work for auto-configured PCI devices (which also
currently use the `attach()` hook in this driver, but doesn't have the
firmware-loading options set in the `struct comedi_devconfig *`
parameter).
Change the driver to request the firmware files using
`request_firmware()`, ignoring any firmware-loading options set in the
`struct comedi_devconfig`.
The PCI-6534 has a main FPGA which needs to be loaded first, and two
"scarabs". Scarab A is loaded with firmware to support digital input
mode, and scarab B is loaded with firmware to support digital output
mode.
I don't think the order of loading the scarab firmwares matters as long
as they are loaded with the correct firmware files. This update loads
scarab B first, whereas the original code loaded scarab A first. The
firmware files are loaded in the following order:
A) main FPGA: "ni6534a.bin" (FW_PCI_6534_MAIN)
B) scarab B: "niscrb02.bin" (FW_PCI_6534_SCARAB_DO)
C) scarab A: "niscrb01.bin" (FW_PCI_6534_SCARAB_DI)
The required firmware files can be found in the
"comedi-nonfree-firmware" tar-ball at
<http://www.comedi.org/download/comedi-nonfree-firmware-2007.06.22.tar.gz>.
Signed-off-by: Ian Abbott <abbotti@mev.co.uk>
Reviewed-by: H Hartley Sweeten <hsweeten@visionengravers.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/staging/comedi/drivers/ni_pcidio.c | 61 |
1 files changed, 36 insertions, 25 deletions
diff --git a/drivers/staging/comedi/drivers/ni_pcidio.c b/drivers/staging/comedi/drivers/ni_pcidio.c index 4f76daf76ff..a655ab9ecc7 100644 --- a/drivers/staging/comedi/drivers/ni_pcidio.c +++ b/drivers/staging/comedi/drivers/ni_pcidio.c @@ -57,6 +57,7 @@ comedi_nonfree_firmware tarball available from http://www.comedi.org #include <linux/interrupt.h> #include <linux/sched.h> +#include <linux/firmware.h> #include "../comedidev.h" #include "mite.h" @@ -230,6 +231,14 @@ static inline unsigned secondary_DMAChannel_bits(unsigned channel) #define Protocol_Register_8 88 /* 32 bit */ #define StartDelay Protocol_Register_8 +/* Firmware files for PCI-6524 */ +#define FW_PCI_6534_MAIN "ni6534a.bin" +#define FW_PCI_6534_SCARAB_DI "niscrb01.bin" +#define FW_PCI_6534_SCARAB_DO "niscrb02.bin" +MODULE_FIRMWARE(FW_PCI_6534_MAIN); +MODULE_FIRMWARE(FW_PCI_6534_SCARAB_DI); +MODULE_FIRMWARE(FW_PCI_6534_SCARAB_DO); + enum pci_6534_firmware_registers { /* 16 bit */ Firmware_Control_Register = 0x100, Firmware_Status_Register = 0x104, @@ -977,10 +986,12 @@ static int ni_pcidio_change(struct comedi_device *dev, } static int pci_6534_load_fpga(struct comedi_device *dev, int fpga_index, - u8 *data, int data_len) + const u8 *data, size_t data_len) { static const int timeout = 1000; - int i, j; + int i; + size_t j; + writew(0x80 | fpga_index, devpriv->mite->daq_io_addr + Firmware_Control_Register); writew(0xc0 | fpga_index, @@ -1062,34 +1073,34 @@ static void pci_6534_init_main_fpga(struct comedi_device *dev) writel(0, devpriv->mite->daq_io_addr + FPGA_SCBMS_Counter_Register); } -static int pci_6534_upload_firmware(struct comedi_device *dev, int options[]) +static int pci_6534_upload_firmware(struct comedi_device *dev) { int ret; - void *main_fpga_data, *scarab_a_data, *scarab_b_data; - int main_fpga_data_len, scarab_a_data_len, scarab_b_data_len; + const struct firmware *fw; + static const char *const fw_file[3] = { + FW_PCI_6534_SCARAB_DI, /* loaded into scarab A for DI */ + FW_PCI_6534_SCARAB_DO, /* loaded into scarab B for DO */ + FW_PCI_6534_MAIN, /* loaded into main FPGA */ + }; + int n; - if (options[COMEDI_DEVCONF_AUX_DATA_LENGTH] == 0) - return 0; ret = pci_6534_reset_fpgas(dev); if (ret < 0) return ret; - main_fpga_data = comedi_aux_data(options, 0); - main_fpga_data_len = options[COMEDI_DEVCONF_AUX_DATA0_LENGTH]; - ret = pci_6534_load_fpga(dev, 2, main_fpga_data, main_fpga_data_len); - if (ret < 0) - return ret; - pci_6534_init_main_fpga(dev); - scarab_a_data = comedi_aux_data(options, 1); - scarab_a_data_len = options[COMEDI_DEVCONF_AUX_DATA1_LENGTH]; - ret = pci_6534_load_fpga(dev, 0, scarab_a_data, scarab_a_data_len); - if (ret < 0) - return ret; - scarab_b_data = comedi_aux_data(options, 2); - scarab_b_data_len = options[COMEDI_DEVCONF_AUX_DATA2_LENGTH]; - ret = pci_6534_load_fpga(dev, 1, scarab_b_data, scarab_b_data_len); - if (ret < 0) - return ret; - return 0; + /* load main FPGA first, then the two scarabs */ + for (n = 2; n >= 0; n--) { + ret = request_firmware(&fw, fw_file[n], + &devpriv->mite->pcidev->dev); + if (ret == 0) { + ret = pci_6534_load_fpga(dev, n, fw->data, fw->size); + if (ret == 0 && n == 2) + pci_6534_init_main_fpga(dev); + release_firmware(fw); + } + if (ret < 0) + break; + } + return ret; } static int nidio_find_device(struct comedi_device *dev, int bus, int slot) @@ -1147,7 +1158,7 @@ static int nidio_attach(struct comedi_device *dev, struct comedi_devconfig *it) dev->board_name = this_board->name; irq = mite_irq(devpriv->mite); if (this_board->uses_firmware) { - ret = pci_6534_upload_firmware(dev, it->options); + ret = pci_6534_upload_firmware(dev); if (ret < 0) return ret; } |