The regmap API supports IO port accessors so we can take advantage of regmap abstractions rather than handling access to the device registers directly in the driver. By leveraging the regmap API, the idio-16 library is reduced to simply a devm_idio_16_regmap_register() function and a configuration structure struct idio_16_regmap_config. Legacy functions and code will be removed once all consumers have migrated to the new idio-16 library interface. For IDIO-16 devices we have the following IRQ registers: Base Address +1 (Write): Clear Interrupt Base Address +2 (Read): Enable Interrupt Base Address +2 (Write): Disable Interrupt An interrupt is asserted whenever a change-of-state is detected on any of the inputs. Any write to 0x2 will disable interrupts, while any read will enable interrupts. Interrupts are cleared by a write to 0x1. For 104-IDIO-16 devices, there is no IRQ status register, so software has to assume that if an interrupt is raised then it was for the 104-IDIO-16 device. For PCI-IDIO-16 devices, there is an additional IRQ register: Base Address +6 (Read): Interrupt Status Interrupt status can be read from 0x6 where bit 2 set indicates that an IRQ has been generated. Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Link: https://lore.kernel.org/r/b45081958ab53dfa697f4a8b15f1bfba46718068.1680618405.git.william.gray@linaro.org/ Signed-off-by: William Breathitt Gray <william.gray@linaro.org> Reviewed-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
98 lines
2.7 KiB
C
98 lines
2.7 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
/* Copyright 2022 William Breathitt Gray */
|
|
#ifndef _IDIO_16_H_
|
|
#define _IDIO_16_H_
|
|
|
|
#include <linux/spinlock.h>
|
|
#include <linux/types.h>
|
|
|
|
struct device;
|
|
struct regmap;
|
|
struct regmap_irq;
|
|
|
|
/**
|
|
* struct idio_16_regmap_config - Configuration for the IDIO-16 register map
|
|
* @parent: parent device
|
|
* @map: regmap for the IDIO-16 device
|
|
* @regmap_irqs: descriptors for individual IRQs
|
|
* @num_regmap_irqs: number of IRQ descriptors
|
|
* @irq: IRQ number for the IDIO-16 device
|
|
* @no_status: device has no status register
|
|
* @filters: device has input filters
|
|
*/
|
|
struct idio_16_regmap_config {
|
|
struct device *parent;
|
|
struct regmap *map;
|
|
const struct regmap_irq *regmap_irqs;
|
|
int num_regmap_irqs;
|
|
unsigned int irq;
|
|
bool no_status;
|
|
bool filters;
|
|
};
|
|
|
|
/**
|
|
* struct idio_16 - IDIO-16 registers structure
|
|
* @out0_7: Read: FET Drive Outputs 0-7
|
|
* Write: FET Drive Outputs 0-7
|
|
* @in0_7: Read: Isolated Inputs 0-7
|
|
* Write: Clear Interrupt
|
|
* @irq_ctl: Read: Enable IRQ
|
|
* Write: Disable IRQ
|
|
* @filter_ctl: Read: Activate Input Filters 0-15
|
|
* Write: Deactivate Input Filters 0-15
|
|
* @out8_15: Read: FET Drive Outputs 8-15
|
|
* Write: FET Drive Outputs 8-15
|
|
* @in8_15: Read: Isolated Inputs 8-15
|
|
* Write: Unused
|
|
* @irq_status: Read: Interrupt status
|
|
* Write: Unused
|
|
*/
|
|
struct idio_16 {
|
|
u8 out0_7;
|
|
u8 in0_7;
|
|
u8 irq_ctl;
|
|
u8 filter_ctl;
|
|
u8 out8_15;
|
|
u8 in8_15;
|
|
u8 irq_status;
|
|
};
|
|
|
|
#define IDIO_16_NOUT 16
|
|
|
|
/**
|
|
* struct idio_16_state - IDIO-16 state structure
|
|
* @lock: synchronization lock for accessing device state
|
|
* @out_state: output signals state
|
|
*/
|
|
struct idio_16_state {
|
|
spinlock_t lock;
|
|
DECLARE_BITMAP(out_state, IDIO_16_NOUT);
|
|
};
|
|
|
|
/**
|
|
* idio_16_get_direction - get the I/O direction for a signal offset
|
|
* @offset: offset of signal to get direction
|
|
*
|
|
* Returns the signal direction (0=output, 1=input) for the signal at @offset.
|
|
*/
|
|
static inline int idio_16_get_direction(const unsigned long offset)
|
|
{
|
|
return (offset >= IDIO_16_NOUT) ? 1 : 0;
|
|
}
|
|
|
|
int idio_16_get(struct idio_16 __iomem *reg, struct idio_16_state *state,
|
|
unsigned long offset);
|
|
void idio_16_get_multiple(struct idio_16 __iomem *reg,
|
|
struct idio_16_state *state,
|
|
const unsigned long *mask, unsigned long *bits);
|
|
void idio_16_set(struct idio_16 __iomem *reg, struct idio_16_state *state,
|
|
unsigned long offset, unsigned long value);
|
|
void idio_16_set_multiple(struct idio_16 __iomem *reg,
|
|
struct idio_16_state *state,
|
|
const unsigned long *mask, const unsigned long *bits);
|
|
void idio_16_state_init(struct idio_16_state *state);
|
|
|
|
int devm_idio_16_regmap_register(struct device *dev, const struct idio_16_regmap_config *config);
|
|
|
|
#endif /* _IDIO_16_H_ */
|