Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

comedi: comedi_8254: Use a call-back function for register access

Rework the comedi_8254 module to use a call-back function for register
access. This will make it easier to isolate the parts that will depend
on the `CONFIG_HAS_IOPORT` macro being defined and also allows the
possibility of supplying an external callback function during
initialization by a variant of the `comedi_8254_init()` and
`comedi_8254_mm_init()` functions, although that has not been
implemented yet.

The `struct comedi_8254` members have been changed to use a pointer to a
callback function and a context of type `unsigned long`. The
`comedi_8254_init()` and `comedi_8254_mm_init()` functions use an
internal callback function and set the context to the base address of
the registers (for `comedi_8254_mm_init()` that involves converting a
`void __iomem *` to `unsigned long`).

A minor change to `dio200_subdev_8254_offset()` in the
amplc_dio200_common module has been made due to the changes in `struct
comedi_8254`.

Cc: Arnd Bergmann <arnd@kernel.org>
Cc: Niklas Schnelle <schnelle@linux.ibm.com>
Signed-off-by: Ian Abbott <abbotti@mev.co.uk>
Link: https://lore.kernel.org/r/20230913170712.111719-3-abbotti@mev.co.uk
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Ian Abbott and committed by
Greg Kroah-Hartman
c62f5032 7b79e3d2

+145 -60
+2 -2
drivers/comedi/drivers/amplc_dio200_common.c
··· 149 149 150 150 /* get the offset that was passed to comedi_8254_*_init() */ 151 151 if (dev->mmio) 152 - offset = i8254->mmio - dev->mmio; 152 + offset = (void __iomem *)i8254->context - dev->mmio; 153 153 else 154 - offset = i8254->iobase - dev->iobase; 154 + offset = i8254->context - dev->iobase; 155 155 156 156 /* remove the shift that was added for PCIe boards */ 157 157 if (board->is_pcie)
+125 -54
drivers/comedi/drivers/comedi_8254.c
··· 119 119 #include <linux/comedi/comedidev.h> 120 120 #include <linux/comedi/comedi_8254.h> 121 121 122 + static unsigned int i8254_io8_cb(struct comedi_8254 *i8254, int dir, 123 + unsigned int reg, unsigned int val) 124 + { 125 + unsigned long iobase = i8254->context; 126 + unsigned int reg_offset = (reg * I8254_IO8) << i8254->regshift; 127 + 128 + if (dir) { 129 + outb(val, iobase + reg_offset); 130 + return 0; 131 + } else { 132 + return inb(iobase + reg_offset); 133 + } 134 + } 135 + 136 + static unsigned int i8254_io16_cb(struct comedi_8254 *i8254, int dir, 137 + unsigned int reg, unsigned int val) 138 + { 139 + unsigned long iobase = i8254->context; 140 + unsigned int reg_offset = (reg * I8254_IO16) << i8254->regshift; 141 + 142 + if (dir) { 143 + outw(val, iobase + reg_offset); 144 + return 0; 145 + } else { 146 + return inw(iobase + reg_offset); 147 + } 148 + } 149 + 150 + static unsigned int i8254_io32_cb(struct comedi_8254 *i8254, int dir, 151 + unsigned int reg, unsigned int val) 152 + { 153 + unsigned long iobase = i8254->context; 154 + unsigned int reg_offset = (reg * I8254_IO32) << i8254->regshift; 155 + 156 + if (dir) { 157 + outl(val, iobase + reg_offset); 158 + return 0; 159 + } else { 160 + return inl(iobase + reg_offset); 161 + } 162 + } 163 + 164 + static unsigned int i8254_mmio8_cb(struct comedi_8254 *i8254, int dir, 165 + unsigned int reg, unsigned int val) 166 + { 167 + void __iomem *mmiobase = (void __iomem *)i8254->context; 168 + unsigned int reg_offset = (reg * I8254_IO8) << i8254->regshift; 169 + 170 + if (dir) { 171 + writeb(val, mmiobase + reg_offset); 172 + return 0; 173 + } else { 174 + return readb(mmiobase + reg_offset); 175 + } 176 + } 177 + 178 + static unsigned int i8254_mmio16_cb(struct comedi_8254 *i8254, int dir, 179 + unsigned int reg, unsigned int val) 180 + { 181 + void __iomem *mmiobase = (void __iomem *)i8254->context; 182 + unsigned int reg_offset = (reg * I8254_IO16) << i8254->regshift; 183 + 184 + if (dir) { 185 + writew(val, mmiobase + reg_offset); 186 + return 0; 187 + } else { 188 + return readw(mmiobase + reg_offset); 189 + } 190 + } 191 + 192 + static unsigned int i8254_mmio32_cb(struct comedi_8254 *i8254, int dir, 193 + unsigned int reg, unsigned int val) 194 + { 195 + void __iomem *mmiobase = (void __iomem *)i8254->context; 196 + unsigned int reg_offset = (reg * I8254_IO32) << i8254->regshift; 197 + 198 + if (dir) { 199 + writel(val, mmiobase + reg_offset); 200 + return 0; 201 + } else { 202 + return readl(mmiobase + reg_offset); 203 + } 204 + } 205 + 122 206 static unsigned int __i8254_read(struct comedi_8254 *i8254, unsigned int reg) 123 207 { 124 - unsigned int reg_offset = (reg * i8254->iosize) << i8254->regshift; 125 - unsigned int val; 126 - 127 - switch (i8254->iosize) { 128 - default: 129 - case I8254_IO8: 130 - if (i8254->mmio) 131 - val = readb(i8254->mmio + reg_offset); 132 - else 133 - val = inb(i8254->iobase + reg_offset); 134 - break; 135 - case I8254_IO16: 136 - if (i8254->mmio) 137 - val = readw(i8254->mmio + reg_offset); 138 - else 139 - val = inw(i8254->iobase + reg_offset); 140 - break; 141 - case I8254_IO32: 142 - if (i8254->mmio) 143 - val = readl(i8254->mmio + reg_offset); 144 - else 145 - val = inl(i8254->iobase + reg_offset); 146 - break; 147 - } 148 - return val & 0xff; 208 + return 0xff & i8254->iocb(i8254, 0, reg, 0); 149 209 } 150 210 151 211 static void __i8254_write(struct comedi_8254 *i8254, 152 212 unsigned int val, unsigned int reg) 153 213 { 154 - unsigned int reg_offset = (reg * i8254->iosize) << i8254->regshift; 155 - 156 - switch (i8254->iosize) { 157 - default: 158 - case I8254_IO8: 159 - if (i8254->mmio) 160 - writeb(val, i8254->mmio + reg_offset); 161 - else 162 - outb(val, i8254->iobase + reg_offset); 163 - break; 164 - case I8254_IO16: 165 - if (i8254->mmio) 166 - writew(val, i8254->mmio + reg_offset); 167 - else 168 - outw(val, i8254->iobase + reg_offset); 169 - break; 170 - case I8254_IO32: 171 - if (i8254->mmio) 172 - writel(val, i8254->mmio + reg_offset); 173 - else 174 - outl(val, i8254->iobase + reg_offset); 175 - break; 176 - } 214 + i8254->iocb(i8254, 1, reg, val); 177 215 } 178 216 179 217 /** ··· 609 571 } 610 572 EXPORT_SYMBOL_GPL(comedi_8254_subdevice_init); 611 573 612 - static struct comedi_8254 *__i8254_init(unsigned long iobase, 613 - void __iomem *mmio, 574 + static struct comedi_8254 *__i8254_init(comedi_8254_iocb_fn *iocb, 575 + unsigned long context, 614 576 unsigned int osc_base, 615 577 unsigned int iosize, 616 578 unsigned int regshift) ··· 623 585 iosize == I8254_IO32)) 624 586 return NULL; 625 587 588 + if (!iocb) 589 + return NULL; 590 + 626 591 i8254 = kzalloc(sizeof(*i8254), GFP_KERNEL); 627 592 if (!i8254) 628 593 return NULL; 629 594 630 - i8254->iobase = iobase; 631 - i8254->mmio = mmio; 595 + i8254->iocb = iocb; 596 + i8254->context = context; 632 597 i8254->iosize = iosize; 633 598 i8254->regshift = regshift; 634 599 ··· 658 617 unsigned int iosize, 659 618 unsigned int regshift) 660 619 { 661 - return __i8254_init(iobase, NULL, osc_base, iosize, regshift); 620 + comedi_8254_iocb_fn *iocb; 621 + 622 + switch (iosize) { 623 + case I8254_IO8: 624 + iocb = i8254_io8_cb; 625 + break; 626 + case I8254_IO16: 627 + iocb = i8254_io16_cb; 628 + break; 629 + case I8254_IO32: 630 + iocb = i8254_io32_cb; 631 + break; 632 + default: 633 + return NULL; 634 + } 635 + return __i8254_init(iocb, iobase, osc_base, iosize, regshift); 662 636 } 663 637 EXPORT_SYMBOL_GPL(comedi_8254_init); 664 638 ··· 690 634 unsigned int iosize, 691 635 unsigned int regshift) 692 636 { 693 - return __i8254_init(0, mmio, osc_base, iosize, regshift); 637 + comedi_8254_iocb_fn *iocb; 638 + 639 + switch (iosize) { 640 + case I8254_IO8: 641 + iocb = i8254_mmio8_cb; 642 + break; 643 + case I8254_IO16: 644 + iocb = i8254_mmio16_cb; 645 + break; 646 + case I8254_IO32: 647 + iocb = i8254_mmio32_cb; 648 + break; 649 + default: 650 + return NULL; 651 + } 652 + return __i8254_init(iocb, (unsigned long)mmio, osc_base, iosize, regshift); 694 653 } 695 654 EXPORT_SYMBOL_GPL(comedi_8254_mm_init); 696 655
+18 -4
include/linux/comedi/comedi_8254.h
··· 57 57 /* counter maps zero to 0x10000 */ 58 58 #define I8254_MAX_COUNT 0x10000 59 59 60 + struct comedi_8254; 61 + 62 + /** 63 + * typedef comedi_8254_iocb_fn - call-back function type for 8254 register access 64 + * @i8254: pointer to struct comedi_8254 65 + * @dir: direction (0 = read, 1 = write) 66 + * @reg: register number 67 + * @val: value to write 68 + * 69 + * Return: Register value when reading, 0 when writing. 70 + */ 71 + typedef unsigned int comedi_8254_iocb_fn(struct comedi_8254 *i8254, int dir, 72 + unsigned int reg, unsigned int val); 73 + 60 74 /** 61 75 * struct comedi_8254 - private data used by this module 62 - * @iobase: PIO base address of the registers (in/out) 63 - * @mmio: MMIO base address of the registers (read/write) 76 + * @iocb: I/O call-back function for register access 77 + * @context: context for register access (e.g. a base address) 64 78 * @iosize: I/O size used to access the registers (b/w/l) 65 79 * @regshift: register gap shift 66 80 * @osc_base: cascaded oscillator speed in ns ··· 90 76 * @insn_config: driver specific (*insn_config) callback 91 77 */ 92 78 struct comedi_8254 { 93 - unsigned long iobase; 94 - void __iomem *mmio; 79 + comedi_8254_iocb_fn *iocb; 80 + unsigned long context; 95 81 unsigned int iosize; 96 82 unsigned int regshift; 97 83 unsigned int osc_base;