staging: comedi: addi_apci_3501: simplify reading the eeprom
The only value in the eeprom that is used by this driver is the number of analog output channels. Copy the necessary code from addi_eeprom.c to this driver and refactor it so that we can get the value needed. Signed-off-by: H Hartley Sweeten <hsweeten@visionengravers.com> Cc: Ian Abbott <abbotti@mev.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
87c38fbed5
commit
25b9b873d3
1 changed files with 109 additions and 22 deletions
|
@ -4,9 +4,28 @@
|
||||||
|
|
||||||
#include "addi-data/addi_common.h"
|
#include "addi-data/addi_common.h"
|
||||||
|
|
||||||
#include "addi-data/addi_eeprom.c"
|
|
||||||
#include "addi-data/hwdrv_apci3501.c"
|
#include "addi-data/hwdrv_apci3501.c"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* AMCC S5933 NVRAM
|
||||||
|
*/
|
||||||
|
#define NVRAM_USER_DATA_START 0x100
|
||||||
|
|
||||||
|
#define NVCMD_BEGIN_READ (0x7 << 5)
|
||||||
|
#define NVCMD_LOAD_LOW (0x4 << 5)
|
||||||
|
#define NVCMD_LOAD_HIGH (0x5 << 5)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Function types stored in the eeprom
|
||||||
|
*/
|
||||||
|
#define EEPROM_DIGITALINPUT 0
|
||||||
|
#define EEPROM_DIGITALOUTPUT 1
|
||||||
|
#define EEPROM_ANALOGINPUT 2
|
||||||
|
#define EEPROM_ANALOGOUTPUT 3
|
||||||
|
#define EEPROM_TIMER 4
|
||||||
|
#define EEPROM_WATCHDOG 5
|
||||||
|
#define EEPROM_TIMER_WATCHDOG_COUNTER 10
|
||||||
|
|
||||||
static const struct addi_board apci3501_boardtypes[] = {
|
static const struct addi_board apci3501_boardtypes[] = {
|
||||||
{
|
{
|
||||||
.pc_DriverName = "apci3501",
|
.pc_DriverName = "apci3501",
|
||||||
|
@ -50,19 +69,90 @@ static int apci3501_do_insn_bits(struct comedi_device *dev,
|
||||||
return insn->n;
|
return insn->n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void apci3501_eeprom_wait(unsigned long iobase)
|
||||||
|
{
|
||||||
|
unsigned char val;
|
||||||
|
|
||||||
|
do {
|
||||||
|
val = inb(iobase + AMCC_OP_REG_MCSR_NVCMD);
|
||||||
|
} while (val & 0x80);
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned short apci3501_eeprom_readw(unsigned long iobase,
|
||||||
|
unsigned short addr)
|
||||||
|
{
|
||||||
|
unsigned short val = 0;
|
||||||
|
unsigned char tmp;
|
||||||
|
unsigned char i;
|
||||||
|
|
||||||
|
/* Add the offset to the start of the user data */
|
||||||
|
addr += NVRAM_USER_DATA_START;
|
||||||
|
|
||||||
|
for (i = 0; i < 2; i++) {
|
||||||
|
/* Load the low 8 bit address */
|
||||||
|
outb(NVCMD_LOAD_LOW, iobase + AMCC_OP_REG_MCSR_NVCMD);
|
||||||
|
apci3501_eeprom_wait(iobase);
|
||||||
|
outb((addr + i) & 0xff, iobase + AMCC_OP_REG_MCSR_NVDATA);
|
||||||
|
apci3501_eeprom_wait(iobase);
|
||||||
|
|
||||||
|
/* Load the high 8 bit address */
|
||||||
|
outb(NVCMD_LOAD_HIGH, iobase + AMCC_OP_REG_MCSR_NVCMD);
|
||||||
|
apci3501_eeprom_wait(iobase);
|
||||||
|
outb(((addr + i) >> 8) & 0xff,
|
||||||
|
iobase + AMCC_OP_REG_MCSR_NVDATA);
|
||||||
|
apci3501_eeprom_wait(iobase);
|
||||||
|
|
||||||
|
/* Read the eeprom data byte */
|
||||||
|
outb(NVCMD_BEGIN_READ, iobase + AMCC_OP_REG_MCSR_NVCMD);
|
||||||
|
apci3501_eeprom_wait(iobase);
|
||||||
|
tmp = inb(iobase + AMCC_OP_REG_MCSR_NVDATA);
|
||||||
|
apci3501_eeprom_wait(iobase);
|
||||||
|
|
||||||
|
if (i == 0)
|
||||||
|
val |= tmp;
|
||||||
|
else
|
||||||
|
val |= (tmp << 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int apci3501_eeprom_get_ao_n_chan(struct comedi_device *dev)
|
||||||
|
{
|
||||||
|
struct addi_private *devpriv = dev->private;
|
||||||
|
unsigned long iobase = devpriv->i_IobaseAmcc;
|
||||||
|
unsigned char nfuncs;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
nfuncs = apci3501_eeprom_readw(iobase, 10) & 0xff;
|
||||||
|
|
||||||
|
/* Read functionality details */
|
||||||
|
for (i = 0; i < nfuncs; i++) {
|
||||||
|
unsigned short offset = i * 4;
|
||||||
|
unsigned short addr;
|
||||||
|
unsigned char func;
|
||||||
|
unsigned short val;
|
||||||
|
|
||||||
|
func = apci3501_eeprom_readw(iobase, 12 + offset) & 0x3f;
|
||||||
|
addr = apci3501_eeprom_readw(iobase, 14 + offset);
|
||||||
|
|
||||||
|
if (func == EEPROM_ANALOGOUTPUT) {
|
||||||
|
val = apci3501_eeprom_readw(iobase, addr + 10);
|
||||||
|
return (val >> 4) & 0x3ff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int apci3501_eeprom_insn_read(struct comedi_device *dev,
|
static int apci3501_eeprom_insn_read(struct comedi_device *dev,
|
||||||
struct comedi_subdevice *s,
|
struct comedi_subdevice *s,
|
||||||
struct comedi_insn *insn,
|
struct comedi_insn *insn,
|
||||||
unsigned int *data)
|
unsigned int *data)
|
||||||
{
|
{
|
||||||
const struct addi_board *this_board = comedi_board(dev);
|
|
||||||
struct addi_private *devpriv = dev->private;
|
struct addi_private *devpriv = dev->private;
|
||||||
unsigned short w_Address = CR_CHAN(insn->chanspec);
|
unsigned short addr = CR_CHAN(insn->chanspec);
|
||||||
unsigned short w_Data;
|
|
||||||
|
|
||||||
w_Data = addi_eeprom_readw(devpriv->i_IobaseAmcc,
|
data[0] = apci3501_eeprom_readw(devpriv->i_IobaseAmcc, 2 * addr);
|
||||||
this_board->pc_EepromChip, 2 * w_Address);
|
|
||||||
data[0] = w_Data;
|
|
||||||
|
|
||||||
return insn->n;
|
return insn->n;
|
||||||
}
|
}
|
||||||
|
@ -164,6 +254,7 @@ static int apci3501_auto_attach(struct comedi_device *dev,
|
||||||
const struct addi_board *this_board;
|
const struct addi_board *this_board;
|
||||||
struct addi_private *devpriv;
|
struct addi_private *devpriv;
|
||||||
struct comedi_subdevice *s;
|
struct comedi_subdevice *s;
|
||||||
|
int ao_n_chan;
|
||||||
int ret, n_subdevices;
|
int ret, n_subdevices;
|
||||||
|
|
||||||
this_board = addi_find_boardinfo(dev, pcidev);
|
this_board = addi_find_boardinfo(dev, pcidev);
|
||||||
|
@ -184,8 +275,7 @@ static int apci3501_auto_attach(struct comedi_device *dev,
|
||||||
dev->iobase = pci_resource_start(pcidev, 1);
|
dev->iobase = pci_resource_start(pcidev, 1);
|
||||||
devpriv->i_IobaseAmcc = pci_resource_start(pcidev, 0);
|
devpriv->i_IobaseAmcc = pci_resource_start(pcidev, 0);
|
||||||
|
|
||||||
/* Initialize parameters that can be overridden in EEPROM */
|
ao_n_chan = apci3501_eeprom_get_ao_n_chan(dev);
|
||||||
devpriv->s_EeParameters.i_NbrAoChannel = this_board->i_NbrAoChannel;
|
|
||||||
|
|
||||||
if (pcidev->irq > 0) {
|
if (pcidev->irq > 0) {
|
||||||
ret = request_irq(pcidev->irq, apci3501_interrupt, IRQF_SHARED,
|
ret = request_irq(pcidev->irq, apci3501_interrupt, IRQF_SHARED,
|
||||||
|
@ -194,8 +284,6 @@ static int apci3501_auto_attach(struct comedi_device *dev,
|
||||||
dev->irq = pcidev->irq;
|
dev->irq = pcidev->irq;
|
||||||
}
|
}
|
||||||
|
|
||||||
addi_eeprom_read_info(dev, pci_resource_start(pcidev, 0));
|
|
||||||
|
|
||||||
n_subdevices = 7;
|
n_subdevices = 7;
|
||||||
ret = comedi_alloc_subdevices(dev, n_subdevices);
|
ret = comedi_alloc_subdevices(dev, n_subdevices);
|
||||||
if (ret)
|
if (ret)
|
||||||
|
@ -207,19 +295,18 @@ static int apci3501_auto_attach(struct comedi_device *dev,
|
||||||
|
|
||||||
/* Allocate and Initialise AO Subdevice Structures */
|
/* Allocate and Initialise AO Subdevice Structures */
|
||||||
s = &dev->subdevices[1];
|
s = &dev->subdevices[1];
|
||||||
if (devpriv->s_EeParameters.i_NbrAoChannel) {
|
if (ao_n_chan) {
|
||||||
s->type = COMEDI_SUBD_AO;
|
s->type = COMEDI_SUBD_AO;
|
||||||
s->subdev_flags = SDF_WRITEABLE | SDF_GROUND | SDF_COMMON;
|
s->subdev_flags = SDF_WRITEABLE | SDF_GROUND | SDF_COMMON;
|
||||||
s->n_chan = devpriv->s_EeParameters.i_NbrAoChannel;
|
s->n_chan = ao_n_chan;
|
||||||
s->maxdata = 0x3fff;
|
s->maxdata = 0x3fff;
|
||||||
s->len_chanlist =
|
s->range_table = &range_apci3501_ao;
|
||||||
devpriv->s_EeParameters.i_NbrAoChannel;
|
s->insn_config = i_APCI3501_ConfigAnalogOutput;
|
||||||
s->range_table = &range_apci3501_ao;
|
s->insn_write = i_APCI3501_WriteAnalogOutput;
|
||||||
s->insn_config = i_APCI3501_ConfigAnalogOutput;
|
|
||||||
s->insn_write = i_APCI3501_WriteAnalogOutput;
|
|
||||||
} else {
|
} else {
|
||||||
s->type = COMEDI_SUBD_UNUSED;
|
s->type = COMEDI_SUBD_UNUSED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate and Initialise DI Subdevice Structures */
|
/* Allocate and Initialise DI Subdevice Structures */
|
||||||
s = &dev->subdevices[2];
|
s = &dev->subdevices[2];
|
||||||
s->type = COMEDI_SUBD_DI;
|
s->type = COMEDI_SUBD_DI;
|
||||||
|
|
Loading…
Add table
Reference in a new issue