[PATCH 08/14] staging: comedi: daqboard2000: check CPLD status before writing firmware data

Ian Abbott abbotti at mev.co.uk
Wed Jan 4 10:55:41 UTC 2017


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 at mev.co.uk>
---
 drivers/staging/comedi/drivers/daqboard2000.c | 41 ++++++++++++++++++++++-----
 1 file changed, 34 insertions(+), 7 deletions(-)

diff --git a/drivers/staging/comedi/drivers/daqboard2000.c b/drivers/staging/comedi/drivers/daqboard2000.c
index 4e3e81186bc3..626571fc1c01 100644
--- a/drivers/staging/comedi/drivers/daqboard2000.c
+++ b/drivers/staging/comedi/drivers/daqboard2000.c
@@ -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;
 
-	usleep_range(10, 20);
+	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;
 		}
-- 
2.11.0



More information about the devel mailing list