forked from mirrors/linux
		
	gpio: idio-16: Introduce the ACCES IDIO-16 GPIO library module
Exposes consumer library functions to facilitate communication with devices within the ACCES IDIO-16 family such as the 104-IDIO-16 and the PCI-IDIO-16. A CONFIG_GPIO_IDIO_16 Kconfig option is introduced by this patch. Modules wanting access to these idio-16 library functions should select this Kconfig option and import the GPIO_IDIO_16 symbol namespace. Cc: Andy Shevchenko <andriy.shevchenko@intel.com> Signed-off-by: William Breathitt Gray <william.gray@linaro.org> Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
This commit is contained in:
		
							parent
							
								
									6de0cb80e6
								
							
						
					
					
						commit
						b9b1fc1ae1
					
				
					 5 changed files with 234 additions and 0 deletions
				
			
		|  | @ -312,6 +312,13 @@ L:	linux-iio@vger.kernel.org | ||||||
| S:	Maintained | S:	Maintained | ||||||
| F:	drivers/counter/104-quad-8.c | F:	drivers/counter/104-quad-8.c | ||||||
| 
 | 
 | ||||||
|  | ACCES IDIO-16 GPIO LIBRARY | ||||||
|  | M:	William Breathitt Gray <william.gray@linaro.org> | ||||||
|  | L:	linux-gpio@vger.kernel.org | ||||||
|  | S:	Maintained | ||||||
|  | F:	drivers/gpio/gpio-idio-16.c | ||||||
|  | F:	drivers/gpio/gpio-idio-16.h | ||||||
|  | 
 | ||||||
| ACCES PCI-IDIO-16 GPIO DRIVER | ACCES PCI-IDIO-16 GPIO DRIVER | ||||||
| M:	William Breathitt Gray <william.gray@linaro.org> | M:	William Breathitt Gray <william.gray@linaro.org> | ||||||
| L:	linux-gpio@vger.kernel.org | L:	linux-gpio@vger.kernel.org | ||||||
|  |  | ||||||
|  | @ -109,6 +109,15 @@ config GPIO_REGMAP | ||||||
| config GPIO_MAX730X | config GPIO_MAX730X | ||||||
| 	tristate | 	tristate | ||||||
| 
 | 
 | ||||||
|  | config GPIO_IDIO_16 | ||||||
|  | 	tristate | ||||||
|  | 	help | ||||||
|  | 	  Enables support for the idio-16 library functions. The idio-16 library | ||||||
|  | 	  provides functions to facilitate communication with devices within the | ||||||
|  | 	  ACCES IDIO-16 family such as the 104-IDIO-16 and the PCI-IDIO-16. | ||||||
|  | 
 | ||||||
|  | 	  If built as a module its name will be gpio-idio-16. | ||||||
|  | 
 | ||||||
| menu "Memory mapped GPIO drivers" | menu "Memory mapped GPIO drivers" | ||||||
| 	depends on HAS_IOMEM | 	depends on HAS_IOMEM | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -68,6 +68,7 @@ obj-$(CONFIG_GPIO_HLWD)			+= gpio-hlwd.o | ||||||
| obj-$(CONFIG_HTC_EGPIO)			+= gpio-htc-egpio.o | obj-$(CONFIG_HTC_EGPIO)			+= gpio-htc-egpio.o | ||||||
| obj-$(CONFIG_GPIO_I8255)		+= gpio-i8255.o | obj-$(CONFIG_GPIO_I8255)		+= gpio-i8255.o | ||||||
| obj-$(CONFIG_GPIO_ICH)			+= gpio-ich.o | obj-$(CONFIG_GPIO_ICH)			+= gpio-ich.o | ||||||
|  | obj-$(CONFIG_GPIO_IDIO_16)		+= gpio-idio-16.o | ||||||
| obj-$(CONFIG_GPIO_IDT3243X)		+= gpio-idt3243x.o | obj-$(CONFIG_GPIO_IDT3243X)		+= gpio-idt3243x.o | ||||||
| obj-$(CONFIG_GPIO_IMX_SCU)		+= gpio-imx-scu.o | obj-$(CONFIG_GPIO_IMX_SCU)		+= gpio-imx-scu.o | ||||||
| obj-$(CONFIG_GPIO_IOP)			+= gpio-iop.o | obj-$(CONFIG_GPIO_IOP)			+= gpio-iop.o | ||||||
|  |  | ||||||
							
								
								
									
										146
									
								
								drivers/gpio/gpio-idio-16.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										146
									
								
								drivers/gpio/gpio-idio-16.c
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,146 @@ | ||||||
|  | // SPDX-License-Identifier: GPL-2.0
 | ||||||
|  | /*
 | ||||||
|  |  * GPIO library for the ACCES IDIO-16 family | ||||||
|  |  * Copyright (C) 2022 William Breathitt Gray | ||||||
|  |  */ | ||||||
|  | #include <linux/bitmap.h> | ||||||
|  | #include <linux/export.h> | ||||||
|  | #include <linux/io.h> | ||||||
|  | #include <linux/module.h> | ||||||
|  | #include <linux/spinlock.h> | ||||||
|  | #include <linux/types.h> | ||||||
|  | 
 | ||||||
|  | #include "gpio-idio-16.h" | ||||||
|  | 
 | ||||||
|  | #define DEFAULT_SYMBOL_NAMESPACE GPIO_IDIO_16 | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * idio_16_get - get signal value at signal offset | ||||||
|  |  * @reg:	ACCES IDIO-16 device registers | ||||||
|  |  * @state:	ACCES IDIO-16 device state | ||||||
|  |  * @offset:	offset of signal to get | ||||||
|  |  * | ||||||
|  |  * Returns the signal value (0=low, 1=high) for the signal at @offset. | ||||||
|  |  */ | ||||||
|  | int idio_16_get(struct idio_16 __iomem *const reg, | ||||||
|  | 		struct idio_16_state *const state, const unsigned long offset) | ||||||
|  | { | ||||||
|  | 	const unsigned long mask = BIT(offset); | ||||||
|  | 
 | ||||||
|  | 	if (offset < IDIO_16_NOUT) | ||||||
|  | 		return test_bit(offset, state->out_state); | ||||||
|  | 
 | ||||||
|  | 	if (offset < 24) | ||||||
|  | 		return !!(ioread8(®->in0_7) & (mask >> IDIO_16_NOUT)); | ||||||
|  | 
 | ||||||
|  | 	if (offset < 32) | ||||||
|  | 		return !!(ioread8(®->in8_15) & (mask >> 24)); | ||||||
|  | 
 | ||||||
|  | 	return -EINVAL; | ||||||
|  | } | ||||||
|  | EXPORT_SYMBOL_GPL(idio_16_get); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * idio_16_get_multiple - get multiple signal values at multiple signal offsets | ||||||
|  |  * @reg:	ACCES IDIO-16 device registers | ||||||
|  |  * @state:	ACCES IDIO-16 device state | ||||||
|  |  * @mask:	mask of signals to get | ||||||
|  |  * @bits:	bitmap to store signal values | ||||||
|  |  * | ||||||
|  |  * Stores in @bits the values (0=low, 1=high) for the signals defined by @mask. | ||||||
|  |  */ | ||||||
|  | void idio_16_get_multiple(struct idio_16 __iomem *const reg, | ||||||
|  | 			  struct idio_16_state *const state, | ||||||
|  | 			  const unsigned long *const mask, | ||||||
|  | 			  unsigned long *const bits) | ||||||
|  | { | ||||||
|  | 	unsigned long flags; | ||||||
|  | 	const unsigned long out_mask = GENMASK(IDIO_16_NOUT - 1, 0); | ||||||
|  | 
 | ||||||
|  | 	spin_lock_irqsave(&state->lock, flags); | ||||||
|  | 
 | ||||||
|  | 	bitmap_replace(bits, bits, state->out_state, &out_mask, IDIO_16_NOUT); | ||||||
|  | 	if (*mask & GENMASK(23, 16)) | ||||||
|  | 		bitmap_set_value8(bits, ioread8(®->in0_7), 16); | ||||||
|  | 	if (*mask & GENMASK(31, 24)) | ||||||
|  | 		bitmap_set_value8(bits, ioread8(®->in8_15), 24); | ||||||
|  | 
 | ||||||
|  | 	spin_unlock_irqrestore(&state->lock, flags); | ||||||
|  | } | ||||||
|  | EXPORT_SYMBOL_GPL(idio_16_get_multiple); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * idio_16_set - set signal value at signal offset | ||||||
|  |  * @reg:	ACCES IDIO-16 device registers | ||||||
|  |  * @state:	ACCES IDIO-16 device state | ||||||
|  |  * @offset:	offset of signal to set | ||||||
|  |  * @value:	value of signal to set | ||||||
|  |  * | ||||||
|  |  * Assigns output @value for the signal at @offset. | ||||||
|  |  */ | ||||||
|  | void idio_16_set(struct idio_16 __iomem *const reg, | ||||||
|  | 		 struct idio_16_state *const state, const unsigned long offset, | ||||||
|  | 		 const unsigned long value) | ||||||
|  | { | ||||||
|  | 	unsigned long flags; | ||||||
|  | 
 | ||||||
|  | 	if (offset >= IDIO_16_NOUT) | ||||||
|  | 		return; | ||||||
|  | 
 | ||||||
|  | 	spin_lock_irqsave(&state->lock, flags); | ||||||
|  | 
 | ||||||
|  | 	__assign_bit(offset, state->out_state, value); | ||||||
|  | 	if (offset < 8) | ||||||
|  | 		iowrite8(bitmap_get_value8(state->out_state, 0), ®->out0_7); | ||||||
|  | 	else | ||||||
|  | 		iowrite8(bitmap_get_value8(state->out_state, 8), ®->out8_15); | ||||||
|  | 
 | ||||||
|  | 	spin_unlock_irqrestore(&state->lock, flags); | ||||||
|  | } | ||||||
|  | EXPORT_SYMBOL_GPL(idio_16_set); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * idio_16_set_multiple - set signal values at multiple signal offsets | ||||||
|  |  * @reg:	ACCES IDIO-16 device registers | ||||||
|  |  * @state:	ACCES IDIO-16 device state | ||||||
|  |  * @mask:	mask of signals to set | ||||||
|  |  * @bits:	bitmap of signal output values | ||||||
|  |  * | ||||||
|  |  * Assigns output values defined by @bits for the signals defined by @mask. | ||||||
|  |  */ | ||||||
|  | void idio_16_set_multiple(struct idio_16 __iomem *const reg, | ||||||
|  | 			  struct idio_16_state *const state, | ||||||
|  | 			  const unsigned long *const mask, | ||||||
|  | 			  const unsigned long *const bits) | ||||||
|  | { | ||||||
|  | 	unsigned long flags; | ||||||
|  | 
 | ||||||
|  | 	spin_lock_irqsave(&state->lock, flags); | ||||||
|  | 
 | ||||||
|  | 	bitmap_replace(state->out_state, state->out_state, bits, mask, | ||||||
|  | 		       IDIO_16_NOUT); | ||||||
|  | 	if (*mask & GENMASK(7, 0)) | ||||||
|  | 		iowrite8(bitmap_get_value8(state->out_state, 0), ®->out0_7); | ||||||
|  | 	if (*mask & GENMASK(15, 8)) | ||||||
|  | 		iowrite8(bitmap_get_value8(state->out_state, 8), ®->out8_15); | ||||||
|  | 
 | ||||||
|  | 	spin_unlock_irqrestore(&state->lock, flags); | ||||||
|  | } | ||||||
|  | EXPORT_SYMBOL_GPL(idio_16_set_multiple); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * idio_16_state_init - initialize idio_16_state structure | ||||||
|  |  * @state:	ACCES IDIO-16 device state | ||||||
|  |  * | ||||||
|  |  * Initializes the ACCES IDIO-16 device @state for use in idio-16 library | ||||||
|  |  * functions. | ||||||
|  |  */ | ||||||
|  | void idio_16_state_init(struct idio_16_state *const state) | ||||||
|  | { | ||||||
|  | 	spin_lock_init(&state->lock); | ||||||
|  | } | ||||||
|  | EXPORT_SYMBOL_GPL(idio_16_state_init); | ||||||
|  | 
 | ||||||
|  | MODULE_AUTHOR("William Breathitt Gray"); | ||||||
|  | MODULE_DESCRIPTION("ACCES IDIO-16 GPIO Library"); | ||||||
|  | MODULE_LICENSE("GPL"); | ||||||
							
								
								
									
										71
									
								
								drivers/gpio/gpio-idio-16.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								drivers/gpio/gpio-idio-16.h
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,71 @@ | ||||||
|  | /* 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 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); | ||||||
|  | 
 | ||||||
|  | #endif /* _IDIO_16_H_ */ | ||||||
		Loading…
	
		Reference in a new issue
	
	 William Breathitt Gray
						William Breathitt Gray