Commit 5c57b1cc authored by Ian Abbott's avatar Ian Abbott Committed by Greg Kroah-Hartman

comedi: comedi_8255: Rework subdevice initialization functions

Comedi drivers can initialize an 8255 subdevice in I/O space by calling
`subdev_8255_init()`, or in memory-mapped I/O space by calling
`subdev_8255_mm_init()`, or by supplying a call-back function pointer
and context to either of those functions.  Change it so that a new
function `subdev_8255_cb_init()` shall be called instead when supplying
a callback function and context, and remove the call-back function
parameter from `subdev_8255_init()` and `subdev_8255_mm_init()`.

Also rename `subdev_8255_init()` to `subdev_8255_io_init()`.  The
parameters are changing, so might as well rename it at the same time.

Also rename the `regbase` member of `struct subdev_8255_private` to
`context` since this holds the context for the call-back function call.

Cc: Arnd Bergmann <arnd@kernel.org>
Cc: Niklas Schnelle <schnelle@linux.ibm.com>
Signed-off-by: default avatarIan Abbott <abbotti@mev.co.uk>
Link: https://lore.kernel.org/r/20230913170712.111719-7-abbotti@mev.co.ukSigned-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 0ccb86a6
......@@ -80,7 +80,7 @@ static int dev_8255_attach(struct comedi_device *dev,
if (ret) {
s->type = COMEDI_SUBD_UNUSED;
} else {
ret = subdev_8255_init(dev, s, NULL, iobase);
ret = subdev_8255_io_init(dev, s, iobase);
if (ret) {
/*
* Release the I/O port region here, as the
......
......@@ -242,9 +242,9 @@ static int pci_8255_auto_attach(struct comedi_device *dev,
for (i = 0; i < board->n_8255; i++) {
s = &dev->subdevices[i];
if (dev->mmio)
ret = subdev_8255_mm_init(dev, s, NULL, i * I8255_SIZE);
ret = subdev_8255_mm_init(dev, s, i * I8255_SIZE);
else
ret = subdev_8255_init(dev, s, NULL, i * I8255_SIZE);
ret = subdev_8255_io_init(dev, s, i * I8255_SIZE);
if (ret)
return ret;
}
......
......@@ -642,8 +642,8 @@ static int pci_dio_auto_attach(struct comedi_device *dev,
for (j = 0; j < d->chans; j++) {
s = &dev->subdevices[subdev++];
ret = subdev_8255_init(dev, s, NULL,
d->addr + j * I8255_SIZE);
ret = subdev_8255_io_init(dev, s,
d->addr + j * I8255_SIZE);
if (ret)
return ret;
}
......
......@@ -247,7 +247,7 @@ static int aio_aio12_8_attach(struct comedi_device *dev,
/* Digital I/O subdevice (8255) */
s = &dev->subdevices[2];
ret = subdev_8255_init(dev, s, NULL, AIO12_8_8255_BASE_REG);
ret = subdev_8255_io_init(dev, s, AIO12_8_8255_BASE_REG);
if (ret)
return ret;
......
......@@ -147,7 +147,7 @@ int amplc_pc236_common_attach(struct comedi_device *dev, unsigned long iobase,
s = &dev->subdevices[0];
/* digital i/o subdevice (8255) */
ret = subdev_8255_init(dev, s, NULL, 0x00);
ret = subdev_8255_io_init(dev, s, 0x00);
if (ret)
return ret;
......
......@@ -2529,7 +2529,7 @@ static int pci230_auto_attach(struct comedi_device *dev,
s = &dev->subdevices[2];
/* digital i/o subdevice */
if (board->have_dio) {
rc = subdev_8255_init(dev, s, NULL, PCI230_PPI_X_BASE);
rc = subdev_8255_io_init(dev, s, PCI230_PPI_X_BASE);
if (rc)
return rc;
} else {
......
......@@ -1352,7 +1352,7 @@ static int cb_pcidas_auto_attach(struct comedi_device *dev,
/* 8255 */
s = &dev->subdevices[2];
ret = subdev_8255_init(dev, s, NULL, PCIDAS_8255_BASE);
ret = subdev_8255_io_init(dev, s, PCIDAS_8255_BASE);
if (ret)
return ret;
......
......@@ -3877,11 +3877,10 @@ static int setup_subdevices(struct comedi_device *dev)
s = &dev->subdevices[4];
if (board->has_8255) {
if (board->layout == LAYOUT_4020) {
ret = subdev_8255_init(dev, s, dio_callback_4020,
I8255_4020_REG);
ret = subdev_8255_cb_init(dev, s, dio_callback_4020,
I8255_4020_REG);
} else {
ret = subdev_8255_mm_init(dev, s, NULL,
DIO_8255_OFFSET);
ret = subdev_8255_mm_init(dev, s, DIO_8255_OFFSET);
}
if (ret)
return ret;
......
......@@ -365,7 +365,7 @@ static int cb_pcidda_auto_attach(struct comedi_device *dev,
/* two 8255 digital io subdevices */
for (i = 0; i < 2; i++) {
s = &dev->subdevices[1 + i];
ret = subdev_8255_init(dev, s, NULL, i * I8255_SIZE);
ret = subdev_8255_io_init(dev, s, i * I8255_SIZE);
if (ret)
return ret;
}
......
......@@ -405,7 +405,7 @@ static int cb_pcimdas_auto_attach(struct comedi_device *dev,
/* Digital I/O subdevice */
s = &dev->subdevices[2];
ret = subdev_8255_init(dev, s, NULL, PCIMDAS_8255_BASE);
ret = subdev_8255_io_init(dev, s, PCIMDAS_8255_BASE);
if (ret)
return ret;
......
......@@ -154,7 +154,7 @@ static int cb_pcimdda_auto_attach(struct comedi_device *dev,
s = &dev->subdevices[1];
/* digital i/o subdevice */
return subdev_8255_init(dev, s, NULL, PCIMDDA_8255_BASE_REG);
return subdev_8255_io_init(dev, s, PCIMDDA_8255_BASE_REG);
}
static struct comedi_driver cb_pcimdda_driver = {
......
......@@ -33,9 +33,9 @@
#include <linux/comedi/comedi_8255.h>
struct subdev_8255_private {
unsigned long regbase;
unsigned long context;
int (*io)(struct comedi_device *dev, int dir, int port, int data,
unsigned long regbase);
unsigned long context);
};
static int subdev_8255_io(struct comedi_device *dev,
......@@ -64,7 +64,7 @@ static int subdev_8255_insn(struct comedi_device *dev,
unsigned int *data)
{
struct subdev_8255_private *spriv = s->private;
unsigned long regbase = spriv->regbase;
unsigned long context = spriv->context;
unsigned int mask;
unsigned int v;
......@@ -72,18 +72,18 @@ static int subdev_8255_insn(struct comedi_device *dev,
if (mask) {
if (mask & 0xff)
spriv->io(dev, 1, I8255_DATA_A_REG,
s->state & 0xff, regbase);
s->state & 0xff, context);
if (mask & 0xff00)
spriv->io(dev, 1, I8255_DATA_B_REG,
(s->state >> 8) & 0xff, regbase);
(s->state >> 8) & 0xff, context);
if (mask & 0xff0000)
spriv->io(dev, 1, I8255_DATA_C_REG,
(s->state >> 16) & 0xff, regbase);
(s->state >> 16) & 0xff, context);
}
v = spriv->io(dev, 0, I8255_DATA_A_REG, 0, regbase);
v |= (spriv->io(dev, 0, I8255_DATA_B_REG, 0, regbase) << 8);
v |= (spriv->io(dev, 0, I8255_DATA_C_REG, 0, regbase) << 16);
v = spriv->io(dev, 0, I8255_DATA_A_REG, 0, context);
v |= (spriv->io(dev, 0, I8255_DATA_B_REG, 0, context) << 8);
v |= (spriv->io(dev, 0, I8255_DATA_C_REG, 0, context) << 16);
data[1] = v;
......@@ -94,7 +94,7 @@ static void subdev_8255_do_config(struct comedi_device *dev,
struct comedi_subdevice *s)
{
struct subdev_8255_private *spriv = s->private;
unsigned long regbase = spriv->regbase;
unsigned long context = spriv->context;
int config;
config = I8255_CTRL_CW;
......@@ -108,7 +108,7 @@ static void subdev_8255_do_config(struct comedi_device *dev,
if (!(s->io_bits & 0xf00000))
config |= I8255_CTRL_C_HI_IO;
spriv->io(dev, 1, I8255_CTRL_REG, config, regbase);
spriv->io(dev, 1, I8255_CTRL_REG, config, context);
}
static int subdev_8255_insn_config(struct comedi_device *dev,
......@@ -142,23 +142,19 @@ static int __subdev_8255_init(struct comedi_device *dev,
struct comedi_subdevice *s,
int (*io)(struct comedi_device *dev,
int dir, int port, int data,
unsigned long regbase),
unsigned long regbase,
bool is_mmio)
unsigned long context),
unsigned long context)
{
struct subdev_8255_private *spriv;
if (!io)
return -EINVAL;
spriv = comedi_alloc_spriv(s, sizeof(*spriv));
if (!spriv)
return -ENOMEM;
if (io)
spriv->io = io;
else if (is_mmio)
spriv->io = subdev_8255_mmio;
else
spriv->io = subdev_8255_io;
spriv->regbase = regbase;
spriv->context = context;
s->type = COMEDI_SUBD_DIO;
s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
......@@ -174,88 +170,83 @@ static int __subdev_8255_init(struct comedi_device *dev,
}
/**
* subdev_8255_init - initialize DIO subdevice for driving I/O mapped 8255
* subdev_8255_io_init - initialize DIO subdevice for driving I/O mapped 8255
* @dev: comedi device owning subdevice
* @s: comedi subdevice to initialize
* @io: (optional) register I/O call-back function
* @regbase: offset of 8255 registers from dev->iobase, or call-back context
* @regbase: offset of 8255 registers from dev->iobase
*
* Initializes a comedi subdevice as a DIO subdevice driving an 8255 chip.
*
* If the optional I/O call-back function is provided, its prototype is of
* the following form:
*
* int my_8255_callback(struct comedi_device *dev, int dir, int port,
* int data, unsigned long regbase);
*
* where 'dev', and 'regbase' match the values passed to this function,
* 'port' is the 8255 port number 0 to 3 (including the control port), 'dir'
* is the direction (0 for read, 1 for write) and 'data' is the value to be
* written. It should return 0 if writing or the value read if reading.
*
* If the optional I/O call-back function is not provided, an internal
* call-back function is used which uses consecutive I/O port addresses
* starting at dev->iobase + regbase.
*
* Return: -ENOMEM if failed to allocate memory, zero on success.
*/
int subdev_8255_init(struct comedi_device *dev, struct comedi_subdevice *s,
int (*io)(struct comedi_device *dev, int dir, int port,
int data, unsigned long regbase),
int subdev_8255_io_init(struct comedi_device *dev, struct comedi_subdevice *s,
unsigned long regbase)
{
return __subdev_8255_init(dev, s, io, regbase, false);
return __subdev_8255_init(dev, s, subdev_8255_io, regbase);
}
EXPORT_SYMBOL_GPL(subdev_8255_init);
EXPORT_SYMBOL_GPL(subdev_8255_io_init);
/**
* subdev_8255_mm_init - initialize DIO subdevice for driving mmio-mapped 8255
* @dev: comedi device owning subdevice
* @s: comedi subdevice to initialize
* @io: (optional) register I/O call-back function
* @regbase: offset of 8255 registers from dev->mmio, or call-back context
* @regbase: offset of 8255 registers from dev->mmio
*
* Initializes a comedi subdevice as a DIO subdevice driving an 8255 chip.
*
* If the optional I/O call-back function is provided, its prototype is of
* the following form:
* Return: -ENOMEM if failed to allocate memory, zero on success.
*/
int subdev_8255_mm_init(struct comedi_device *dev, struct comedi_subdevice *s,
unsigned long regbase)
{
return __subdev_8255_init(dev, s, subdev_8255_mmio, regbase);
}
EXPORT_SYMBOL_GPL(subdev_8255_mm_init);
/**
* subdev_8255_cb_init - initialize DIO subdevice for driving callback-mapped 8255
* @dev: comedi device owning subdevice
* @s: comedi subdevice to initialize
* @io: register I/O call-back function
* @context: call-back context
*
* Initializes a comedi subdevice as a DIO subdevice driving an 8255 chip.
*
* The prototype of the I/O call-back function is of the following form:
*
* int my_8255_callback(struct comedi_device *dev, int dir, int port,
* int data, unsigned long regbase);
* int data, unsigned long context);
*
* where 'dev', and 'regbase' match the values passed to this function,
* where 'dev', and 'context' match the values passed to this function,
* 'port' is the 8255 port number 0 to 3 (including the control port), 'dir'
* is the direction (0 for read, 1 for write) and 'data' is the value to be
* written. It should return 0 if writing or the value read if reading.
*
* If the optional I/O call-back function is not provided, an internal
* call-back function is used which uses consecutive MMIO virtual addresses
* starting at dev->mmio + regbase.
*
* Return: -ENOMEM if failed to allocate memory, zero on success.
*/
int subdev_8255_mm_init(struct comedi_device *dev, struct comedi_subdevice *s,
int subdev_8255_cb_init(struct comedi_device *dev, struct comedi_subdevice *s,
int (*io)(struct comedi_device *dev, int dir, int port,
int data, unsigned long regbase),
unsigned long regbase)
int data, unsigned long context),
unsigned long context)
{
return __subdev_8255_init(dev, s, io, regbase, true);
return __subdev_8255_init(dev, s, io, context);
}
EXPORT_SYMBOL_GPL(subdev_8255_mm_init);
EXPORT_SYMBOL_GPL(subdev_8255_cb_init);
/**
* subdev_8255_regbase - get offset of 8255 registers or call-back context
* @s: comedi subdevice
*
* Returns the 'regbase' parameter that was previously passed to
* subdev_8255_init() or subdev_8255_mm_init() to set up the subdevice.
* Only valid if the subdevice was set up successfully.
* Returns the 'regbase' or 'context' parameter that was previously passed to
* subdev_8255_io_init(), subdev_8255_mm_init(), or subdev_8255_cb_init() to
* set up the subdevice. Only valid if the subdevice was set up successfully.
*/
unsigned long subdev_8255_regbase(struct comedi_subdevice *s)
{
struct subdev_8255_private *spriv = s->private;
return spriv->regbase;
return spriv->context;
}
EXPORT_SYMBOL_GPL(subdev_8255_regbase);
......
......@@ -738,8 +738,8 @@ static int db2k_auto_attach(struct comedi_device *dev, unsigned long context)
return result;
s = &dev->subdevices[2];
return subdev_8255_init(dev, s, db2k_8255_cb,
DB2K_REG_DIO_P2_EXP_IO_8_BIT);
return subdev_8255_cb_init(dev, s, db2k_8255_cb,
DB2K_REG_DIO_P2_EXP_IO_8_BIT);
}
static void db2k_detach(struct comedi_device *dev)
......
......@@ -429,7 +429,7 @@ int das08_common_attach(struct comedi_device *dev, unsigned long iobase)
s = &dev->subdevices[4];
/* 8255 */
if (board->i8255_offset != 0) {
ret = subdev_8255_init(dev, s, NULL, board->i8255_offset);
ret = subdev_8255_io_init(dev, s, board->i8255_offset);
if (ret)
return ret;
} else {
......
......@@ -1145,7 +1145,7 @@ static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it)
/* 8255 Digital I/O subdevice */
if (board->has_8255) {
s = &dev->subdevices[4];
ret = subdev_8255_init(dev, s, NULL, board->i8255_offset);
ret = subdev_8255_io_init(dev, s, board->i8255_offset);
if (ret)
return ret;
}
......
......@@ -583,7 +583,7 @@ static int das16m1_attach(struct comedi_device *dev,
/* Digital I/O subdevice (8255) */
s = &dev->subdevices[3];
ret = subdev_8255_init(dev, s, NULL, DAS16M1_8255_IOBASE);
ret = subdev_8255_io_init(dev, s, DAS16M1_8255_IOBASE);
if (ret)
return ret;
......
......@@ -599,7 +599,8 @@ static int dmm32at_attach(struct comedi_device *dev,
/* Digital I/O subdevice */
s = &dev->subdevices[2];
return subdev_8255_init(dev, s, dmm32at_8255_io, DMM32AT_8255_IOBASE);
return subdev_8255_cb_init(dev, s, dmm32at_8255_io,
DMM32AT_8255_IOBASE);
}
static struct comedi_driver dmm32at_driver = {
......
......@@ -677,7 +677,7 @@ static int atmio16d_attach(struct comedi_device *dev,
/* 8255 subdevice */
s = &dev->subdevices[3];
if (board->has_8255) {
ret = subdev_8255_init(dev, s, NULL, 0x00);
ret = subdev_8255_io_init(dev, s, 0x00);
if (ret)
return ret;
} else {
......
......@@ -45,7 +45,7 @@ static int dio24_auto_attach(struct comedi_device *dev,
/* 8255 dio */
s = &dev->subdevices[0];
return subdev_8255_init(dev, s, NULL, 0x00);
return subdev_8255_io_init(dev, s, 0x00);
}
static struct comedi_driver driver_dio24 = {
......
......@@ -1287,9 +1287,9 @@ int labpc_common_attach(struct comedi_device *dev,
/* 8255 dio */
s = &dev->subdevices[2];
if (dev->mmio)
ret = subdev_8255_mm_init(dev, s, NULL, DIO_BASE_REG);
ret = subdev_8255_mm_init(dev, s, DIO_BASE_REG);
else
ret = subdev_8255_init(dev, s, NULL, DIO_BASE_REG);
ret = subdev_8255_io_init(dev, s, DIO_BASE_REG);
if (ret)
return ret;
......
......@@ -6137,8 +6137,8 @@ static int ni_E_init(struct comedi_device *dev,
/* 8255 device */
s = &dev->subdevices[NI_8255_DIO_SUBDEV];
if (board->has_8255) {
ret = subdev_8255_init(dev, s, ni_8255_callback,
NI_E_8255_BASE);
ret = subdev_8255_cb_init(dev, s, ni_8255_callback,
NI_E_8255_BASE);
if (ret)
return ret;
} else {
......
......@@ -124,10 +124,10 @@ static int pcl724_attach(struct comedi_device *dev,
s = &dev->subdevices[i];
if (board->is_pet48) {
iobase = dev->iobase + (i * 0x1000);
ret = subdev_8255_init(dev, s, pcl724_8255mapped_io,
iobase);
ret = subdev_8255_cb_init(dev, s, pcl724_8255mapped_io,
iobase);
} else {
ret = subdev_8255_init(dev, s, NULL, i * I8255_SIZE);
ret = subdev_8255_io_init(dev, s, i * I8255_SIZE);
}
if (ret)
return ret;
......
......@@ -204,7 +204,7 @@ static int pcm3724_attach(struct comedi_device *dev,
for (i = 0; i < dev->n_subdevices; i++) {
s = &dev->subdevices[i];
ret = subdev_8255_init(dev, s, NULL, i * I8255_SIZE);
ret = subdev_8255_io_init(dev, s, i * I8255_SIZE);
if (ret)
return ret;
s->insn_config = subdev_3724_insn_config;
......
......@@ -27,16 +27,17 @@
struct comedi_device;
struct comedi_subdevice;
int subdev_8255_init(struct comedi_device *dev, struct comedi_subdevice *s,
int (*io)(struct comedi_device *dev, int dir, int port,
int data, unsigned long regbase),
unsigned long regbase);
int subdev_8255_io_init(struct comedi_device *dev, struct comedi_subdevice *s,
unsigned long regbase);
int subdev_8255_mm_init(struct comedi_device *dev, struct comedi_subdevice *s,
int (*io)(struct comedi_device *dev, int dir, int port,
int data, unsigned long regbase),
unsigned long regbase);
int subdev_8255_cb_init(struct comedi_device *dev, struct comedi_subdevice *s,
int (*io)(struct comedi_device *dev, int dir, int port,
int data, unsigned long context),
unsigned long context);
unsigned long subdev_8255_regbase(struct comedi_subdevice *s);
#endif
Markdown is supported
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