mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-13 00:29:50 +00:00
staging: comedi: daqboard2000: check CPLD status before writing firmware data
According to an old GPL'ed driver at <ftp://ftp.mccdaq.com/downloads/iotech_software/DaqBoard_1000_2000_Series/Linux_driver_kernelv2.4.x/>, The CPLD status register can be checked to make sure that it is ready to accept the next 16-bit word of FPGA firmware data, but that doesn't work on older versions of the CPLD, where a simple delay should be used between successive writes. The current version of the Comedi driver just uses a delay between successive writes. Change it to check for the newer CPLD in the `daqboard2000_load_firmware()`, and change the firmware word writing function `daqboard2000_write_cpld()` to wait for the status bit (`DB2K_CPLD_STATUS_TXREADY`, previously called `DB2K_CPLD_TXDONE`) to be set for newer CPLD, or just delay for older CPLD. Return an error if it times out waiting for the status bit. The wait for the `DB2K_CPLD_STATUS_TXREADY` status bit to be set is performed by new function `daqboard2000_wait_cpld_txready()`, which returns 0 if the status bit is set within 100 microseconds, or `-ETIMEDOUT` if not. 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>
This commit is contained in:
parent
f8d7b3b2f9
commit
fba4e898b9
@ -240,7 +240,10 @@ static const struct comedi_lrange range_daqboard2000_ai = {
|
||||
|
||||
/* CPLD status bits */
|
||||
#define DB2K_CPLD_STATUS_INIT 0x0002
|
||||
#define DB2K_CPLD_STATUS_TXDONE 0x0004
|
||||
#define DB2K_CPLD_STATUS_TXREADY 0x0004
|
||||
#define DB2K_CPLD_VERSION_MASK 0xf000
|
||||
/* "New CPLD" signature. */
|
||||
#define DB2K_CPLD_VERSION_NEW 0x5000
|
||||
|
||||
struct daq200_boardtype {
|
||||
const char *name;
|
||||
@ -489,14 +492,35 @@ static int daqboard2000_wait_cpld_init(struct comedi_device *dev)
|
||||
return result;
|
||||
}
|
||||
|
||||
static int daqboard2000_write_cpld(struct comedi_device *dev, u16 data)
|
||||
static int daqboard2000_wait_cpld_txready(struct comedi_device *dev)
|
||||
{
|
||||
int result = -EIO;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 100; i++) {
|
||||
if (readw(dev->mmio + DB2K_REG_CPLD_STATUS) &
|
||||
DB2K_CPLD_STATUS_TXREADY) {
|
||||
return 0;
|
||||
}
|
||||
udelay(1);
|
||||
}
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static int daqboard2000_write_cpld(struct comedi_device *dev, u16 data,
|
||||
bool new_cpld)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
if (new_cpld) {
|
||||
result = daqboard2000_wait_cpld_txready(dev);
|
||||
if (result)
|
||||
return result;
|
||||
} else {
|
||||
usleep_range(10, 20);
|
||||
}
|
||||
writew(data, dev->mmio + DB2K_REG_CPLD_WDATA);
|
||||
if (readw(dev->mmio + DB2K_REG_CPLD_STATUS) & DB2K_CPLD_STATUS_INIT)
|
||||
result = 0;
|
||||
if (!(readw(dev->mmio + DB2K_REG_CPLD_STATUS) & DB2K_CPLD_STATUS_INIT))
|
||||
result = -EIO;
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -527,6 +551,7 @@ static int daqboard2000_load_firmware(struct comedi_device *dev,
|
||||
u32 cntrl;
|
||||
int retry;
|
||||
size_t i;
|
||||
bool new_cpld;
|
||||
|
||||
/* Look for FPGA start sequence in firmware. */
|
||||
for (i = 0; i + 1 < len; i++) {
|
||||
@ -561,10 +586,12 @@ static int daqboard2000_load_firmware(struct comedi_device *dev,
|
||||
if (result)
|
||||
continue;
|
||||
|
||||
new_cpld = (readw(dev->mmio + DB2K_REG_CPLD_STATUS) &
|
||||
DB2K_CPLD_VERSION_MASK) == DB2K_CPLD_VERSION_NEW;
|
||||
for (; i < len; i += 2) {
|
||||
u16 data = (cpld_array[i] << 8) + cpld_array[i + 1];
|
||||
|
||||
result = daqboard2000_write_cpld(dev, data);
|
||||
result = daqboard2000_write_cpld(dev, data, new_cpld);
|
||||
if (result)
|
||||
break;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user