staging: comedi: addi_apci_1564: detect PLD revision for I/O mapping

The APCI-1564 has different I/O mapping depending on if the PLD revision is
Rev 1.0 or Rev 2.x. The revision can be determined by reading the EEPROM
register at offset 0x00 of PCI BAR 0 and checking the value of bits 7 to 4.

Add this check to apci1564_auto_attach(). Currently this driver is coded
to work with the Rev 2.x I/O mapping. For now, fail the attach if a Rev 1.0
PLD is detected. Document the I/O mapping for both revisions.

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:
H Hartley Sweeten
2014-11-10 16:20:11 -07:00
committed by Greg Kroah-Hartman
parent 4484a23907
commit 951fd40b28

View File

@@ -30,7 +30,44 @@
#include "comedi_fc.h"
#include "addi_watchdog.h"
/*
* PCI BAR 0
*
* PLD Revision 1.0 I/O Mapping
* 0x00 93C76 EEPROM
* 0x04 - 0x18 Timer 12-Bit
*
* PLD Revision 2.x I/O Mapping
* 0x00 93C76 EEPROM
* 0x04 - 0x14 Digital Input
* 0x18 - 0x25 Digital Output
* 0x28 - 0x44 Watchdog 8-Bit
* 0x48 - 0x64 Timer 12-Bit
*/
#define APCI1564_EEPROM_REG 0x00
#define APCI1564_EEPROM_VCC_STATUS (1 << 8)
#define APCI1564_EEPROM_TO_REV(x) (((x) >> 4) & 0xf)
#define APCI1564_EEPROM_DI (1 << 3)
#define APCI1564_EEPROM_DO (1 << 2)
#define APCI1564_EEPROM_CS (1 << 1)
#define APCI1564_EEPROM_CLK (1 << 0)
/*
* PCI BAR 1
*
* PLD Revision 1.0 I/O Mapping
* 0x00 - 0x10 Digital Input
* 0x14 - 0x20 Digital Output
* 0x24 - 0x3c Watchdog 8-Bit
*
* PLD Revision 2.x I/O Mapping
* 0x00 Counter_0
* 0x20 Counter_1
* 0x30 Counter_3
*/
struct apci1564_private {
unsigned long eeprom; /* base address of EEPROM register */
unsigned long counters; /* base address of 32-bit counters */
unsigned int mode1; /* riding-edge/high level channels */
unsigned int mode2; /* falling-edge/low level channels */
@@ -352,6 +389,7 @@ static int apci1564_auto_attach(struct comedi_device *dev,
struct pci_dev *pcidev = comedi_to_pci_dev(dev);
struct apci1564_private *devpriv;
struct comedi_subdevice *s;
unsigned int val;
int ret;
devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
@@ -362,9 +400,19 @@ static int apci1564_auto_attach(struct comedi_device *dev,
if (ret)
return ret;
/* PLD Revision 2.x I/O Mapping */
dev->iobase = pci_resource_start(pcidev, 0);
devpriv->counters = pci_resource_start(pcidev, 1);
/* read the EEPROM register and check the I/O map revision */
devpriv->eeprom = pci_resource_start(pcidev, 0);
val = inl(devpriv->eeprom + APCI1564_EEPROM_REG);
if (APCI1564_EEPROM_TO_REV(val) == 0) {
/* PLD Revision 1.0 I/O Mapping */
dev_err(dev->class_dev,
"PLD Revision 1.0 detected, not yet supported\n");
return -ENXIO;
} else {
/* PLD Revision 2.x I/O Mapping */
dev->iobase = devpriv->eeprom;
devpriv->counters = pci_resource_start(pcidev, 1);
}
apci1564_reset(dev);