Commit 100b4edc authored by H Hartley Sweeten's avatar H Hartley Sweeten Committed by Greg Kroah-Hartman
Browse files

staging: comedi: s626: simplify dio register access



This driver has three dio subdevices, each with 16 channels. These
subdevices use hardware registers that are spaced 0x10 bytes apart
for each "group" of 16 channels.

Create new macros to get the correct addresses for each register
based on the dio "group". Use the s->private (void *) to hold the
"group" number to use in the subdevice functions.

This allows removing struct dio_private and all its uses. It also
removes the ugly casts used to get the register address.
Signed-off-by: default avatarH Hartley Sweeten <hsweeten@visionengravers.com>
Cc: Ian Abbott <abbotti@mev.co.uk>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 1330af4c
......@@ -106,64 +106,6 @@ struct s626_private {
unsigned int ao_readback[S626_DAC_CHANNELS];
};
struct dio_private {
uint16_t RDDIn;
uint16_t WRDOut;
uint16_t RDEdgSel;
uint16_t WREdgSel;
uint16_t RDCapSel;
uint16_t WRCapSel;
uint16_t RDCapFlg;
uint16_t RDIntSel;
uint16_t WRIntSel;
};
static struct dio_private dio_private_A = {
.RDDIn = LP_RDDINA,
.WRDOut = LP_WRDOUTA,
.RDEdgSel = LP_RDEDGSELA,
.WREdgSel = LP_WREDGSELA,
.RDCapSel = LP_RDCAPSELA,
.WRCapSel = LP_WRCAPSELA,
.RDCapFlg = LP_RDCAPFLGA,
.RDIntSel = LP_RDINTSELA,
.WRIntSel = LP_WRINTSELA,
};
static struct dio_private dio_private_B = {
.RDDIn = LP_RDDINB,
.WRDOut = LP_WRDOUTB,
.RDEdgSel = LP_RDEDGSELB,
.WREdgSel = LP_WREDGSELB,
.RDCapSel = LP_RDCAPSELB,
.WRCapSel = LP_WRCAPSELB,
.RDCapFlg = LP_RDCAPFLGB,
.RDIntSel = LP_RDINTSELB,
.WRIntSel = LP_WRINTSELB,
};
static struct dio_private dio_private_C = {
.RDDIn = LP_RDDINC,
.WRDOut = LP_WRDOUTC,
.RDEdgSel = LP_RDEDGSELC,
.WREdgSel = LP_WREDGSELC,
.RDCapSel = LP_RDCAPSELC,
.WRCapSel = LP_WRCAPSELC,
.RDCapFlg = LP_RDCAPFLGC,
.RDIntSel = LP_RDINTSELC,
.WRIntSel = LP_WRINTSELC,
};
/* to group dio devices (48 bits mask and data are not allowed ???)
static struct dio_private *dio_private_word[]={
&dio_private_A,
&dio_private_B,
&dio_private_C,
};
*/
#define diopriv ((struct dio_private *)s->private)
/* COUNTER OBJECT ------------------------------------------------ */
struct enc_private {
/* Pointers to functions that differ for A and B counters: */
......@@ -670,43 +612,24 @@ static unsigned int s626_ai_reg_to_uint(int data)
static int s626_dio_set_irq(struct comedi_device *dev, unsigned int chan)
{
unsigned int group;
unsigned int bitmask;
unsigned int group = chan / 16;
unsigned int mask = 1 << (chan - (16 * group));
unsigned int status;
/* select dio bank */
group = chan / 16;
bitmask = 1 << (chan - (16 * group));
/* set channel to capture positive edge */
status = DEBIread(dev,
((struct dio_private *)(dev->subdevices + 2 +
group)->private)->RDEdgSel);
DEBIwrite(dev,
((struct dio_private *)(dev->subdevices + 2 +
group)->private)->WREdgSel,
bitmask | status);
status = DEBIread(dev, LP_RDEDGSEL(group));
DEBIwrite(dev, LP_WREDGSEL(group), mask | status);
/* enable interrupt on selected channel */
status = DEBIread(dev,
((struct dio_private *)(dev->subdevices + 2 +
group)->private)->RDIntSel);
DEBIwrite(dev,
((struct dio_private *)(dev->subdevices + 2 +
group)->private)->WRIntSel,
bitmask | status);
status = DEBIread(dev, LP_RDINTSEL(group));
DEBIwrite(dev, LP_WRINTSEL(group), mask | status);
/* enable edge capture write command */
DEBIwrite(dev, LP_MISC1, MISC1_EDCAP);
/* enable edge capture on selected channel */
status = DEBIread(dev,
((struct dio_private *)(dev->subdevices + 2 +
group)->private)->RDCapSel);
DEBIwrite(dev,
((struct dio_private *)(dev->subdevices + 2 +
group)->private)->WRCapSel,
bitmask | status);
status = DEBIread(dev, LP_RDCAPSEL(group));
DEBIwrite(dev, LP_WRCAPSEL(group), mask | status);
return 0;
}
......@@ -718,9 +641,7 @@ static int s626_dio_reset_irq(struct comedi_device *dev, unsigned int group,
DEBIwrite(dev, LP_MISC1, MISC1_NOEDCAP);
/* enable edge capture on selected channel */
DEBIwrite(dev,
((struct dio_private *)(dev->subdevices + 2 +
group)->private)->WRCapSel, mask);
DEBIwrite(dev, LP_WRCAPSEL(group), mask);
return 0;
}
......@@ -732,13 +653,9 @@ static int s626_dio_clear_irq(struct comedi_device *dev)
/* disable edge capture write command */
DEBIwrite(dev, LP_MISC1, MISC1_NOEDCAP);
for (group = 0; group < S626_DIO_BANKS; group++) {
/* clear pending events and interrupt */
DEBIwrite(dev,
((struct dio_private *)(dev->subdevices + 2 +
group)->private)->WRCapSel,
0xffff);
}
/* clear all dio pending events and interrupt */
for (group = 0; group < S626_DIO_BANKS; group++)
DEBIwrite(dev, LP_WRCAPSEL(group), 0xffff);
return 0;
}
......@@ -834,12 +751,7 @@ static irqreturn_t s626_irq_handler(int irq, void *d)
for (group = 0; group < S626_DIO_BANKS; group++) {
irqbit = 0;
/* read interrupt type */
irqbit = DEBIread(dev,
((struct dio_private *)(dev->
subdevices +
2 +
group)->
private)->RDCapFlg);
irqbit = DEBIread(dev, LP_RDCAPFLG(group));
/* check if interrupt is generated from dio channels */
if (irqbit) {
......@@ -1679,22 +1591,20 @@ static int s626_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
static void s626_dio_init(struct comedi_device *dev)
{
uint16_t group;
struct comedi_subdevice *s;
/* Prepare to treat writes to WRCapSel as capture disables. */
DEBIwrite(dev, LP_MISC1, MISC1_NOEDCAP);
/* For each group of sixteen channels ... */
for (group = 0; group < S626_DIO_BANKS; group++) {
s = dev->subdevices + 2 + group;
DEBIwrite(dev, diopriv->WRIntSel, 0); /* Disable all interrupts. */
DEBIwrite(dev, diopriv->WRCapSel, 0xFFFF); /* Disable all event */
/* captures. */
DEBIwrite(dev, diopriv->WREdgSel, 0); /* Init all DIOs to */
/* default edge */
/* polarity. */
DEBIwrite(dev, diopriv->WRDOut, 0); /* Program all outputs */
/* to inactive state. */
/* Disable all interrupts */
DEBIwrite(dev, LP_WRINTSEL(group), 0);
/* Disable all event captures */
DEBIwrite(dev, LP_WRCAPSEL(group), 0xffff);
/* Init all DIOs to default edge polarity */
DEBIwrite(dev, LP_WREDGSEL(group), 0);
/* Program all outputs to inactive state */
DEBIwrite(dev, LP_WRDOUT(group), 0);
}
}
......@@ -1708,6 +1618,8 @@ static int s626_dio_insn_bits(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
unsigned long group = (unsigned long)s->private;
/*
* The insn data consists of a mask in data[0] and the new data in
* data[1]. The mask defines which bits we are concerning about.
......@@ -1724,9 +1636,9 @@ static int s626_dio_insn_bits(struct comedi_device *dev,
/* Write out the new digital output lines */
DEBIwrite(dev, diopriv->WRDOut, s->state);
DEBIwrite(dev, LP_WRDOUT(group), s->state);
}
data[1] = DEBIread(dev, diopriv->RDDIn);
data[1] = DEBIread(dev, LP_RDDIN(group));
return insn->n;
}
......@@ -1735,6 +1647,7 @@ static int s626_dio_insn_config(struct comedi_device *dev,
struct comedi_subdevice *s,
struct comedi_insn *insn, unsigned int *data)
{
unsigned long group = (unsigned long)s->private;
switch (data[0]) {
case INSN_CONFIG_DIO_QUERY:
......@@ -1754,7 +1667,7 @@ static int s626_dio_insn_config(struct comedi_device *dev,
return -EINVAL;
break;
}
DEBIwrite(dev, diopriv->WRDOut, s->io_bits);
DEBIwrite(dev, LP_WRDOUT(group), s->io_bits);
return 1;
}
......@@ -2739,7 +2652,7 @@ static int s626_auto_attach(struct comedi_device *dev,
s->n_chan = 16;
s->maxdata = 1;
s->io_bits = 0xffff;
s->private = &dio_private_A;
s->private = (void *)0; /* DIO group 0 */
s->range_table = &range_digital;
s->insn_config = s626_dio_insn_config;
s->insn_bits = s626_dio_insn_bits;
......@@ -2751,7 +2664,7 @@ static int s626_auto_attach(struct comedi_device *dev,
s->n_chan = 16;
s->maxdata = 1;
s->io_bits = 0xffff;
s->private = &dio_private_B;
s->private = (void *)1; /* DIO group 1 */
s->range_table = &range_digital;
s->insn_config = s626_dio_insn_config;
s->insn_bits = s626_dio_insn_bits;
......@@ -2763,7 +2676,7 @@ static int s626_auto_attach(struct comedi_device *dev,
s->n_chan = 16;
s->maxdata = 1;
s->io_bits = 0xffff;
s->private = &dio_private_C;
s->private = (void *)2; /* DIO group 2 */
s->range_table = &range_digital;
s->insn_config = s626_dio_insn_config;
s->insn_bits = s626_dio_insn_bits;
......
......@@ -267,36 +267,17 @@
#define LP_DACPOL 0x0082 /* Write DAC polarity. */
#define LP_GSEL 0x0084 /* Write ADC gain. */
#define LP_ISEL 0x0086 /* Write ADC channel select. */
/* Digital I/O (write only): */
#define LP_WRINTSELA 0x0042 /* Write A interrupt enable. */
#define LP_WREDGSELA 0x0044 /* Write A edge selection. */
#define LP_WRCAPSELA 0x0046 /* Write A capture enable. */
#define LP_WRDOUTA 0x0048 /* Write A digital output. */
#define LP_WRINTSELB 0x0052 /* Write B interrupt enable. */
#define LP_WREDGSELB 0x0054 /* Write B edge selection. */
#define LP_WRCAPSELB 0x0056 /* Write B capture enable. */
#define LP_WRDOUTB 0x0058 /* Write B digital output. */
#define LP_WRINTSELC 0x0062 /* Write C interrupt enable. */
#define LP_WREDGSELC 0x0064 /* Write C edge selection. */
#define LP_WRCAPSELC 0x0066 /* Write C capture enable. */
#define LP_WRDOUTC 0x0068 /* Write C digital output. */
/* Digital I/O (read only): */
#define LP_RDDINA 0x0040 /* Read digital input. */
#define LP_RDCAPFLGA 0x0048 /* Read edges captured. */
#define LP_RDINTSELA 0x004A /* Read interrupt enable register. */
#define LP_RDEDGSELA 0x004C /* Read edge selection register. */
#define LP_RDCAPSELA 0x004E /* Read capture enable register. */
#define LP_RDDINB 0x0050 /* Read digital input. */
#define LP_RDCAPFLGB 0x0058 /* Read edges captured. */
#define LP_RDINTSELB 0x005A /* Read interrupt enable register. */
#define LP_RDEDGSELB 0x005C /* Read edge selection register. */
#define LP_RDCAPSELB 0x005E /* Read capture enable register. */
#define LP_RDDINC 0x0060 /* Read digital input. */
#define LP_RDCAPFLGC 0x0068 /* Read edges captured. */
#define LP_RDINTSELC 0x006A /* Read interrupt enable register. */
#define LP_RDEDGSELC 0x006C /* Read edge selection register. */
#define LP_RDCAPSELC 0x006E /* Read capture enable register. */
/* Digital I/O registers */
#define LP_RDDIN(x) (0x0040 + (x) * 0x10) /* R: digital input */
#define LP_WRINTSEL(x) (0x0042 + (x) * 0x10) /* W: int enable */
#define LP_WREDGSEL(x) (0x0044 + (x) * 0x10) /* W: edge selection */
#define LP_WRCAPSEL(x) (0x0046 + (x) * 0x10) /* W: capture enable */
#define LP_RDCAPFLG(x) (0x0048 + (x) * 0x10) /* R: edges captured */
#define LP_WRDOUT(x) (0x0048 + (x) * 0x10) /* W: digital output */
#define LP_RDINTSEL(x) (0x004a + (x) * 0x10) /* R: int enable */
#define LP_RDEDGSEL(x) (0x004c + (x) * 0x10) /* R: edge selection */
#define LP_RDCAPSEL(x) (0x004e + (x) * 0x10) /* R: capture enable */
/* Counter Registers (read/write): */
#define LP_CR0A 0x0000 /* 0A setup register. */
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment