1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * GPIO library for the ACCES IDIO-16 family 4 * Copyright (C) 2022 William Breathitt Gray 5 */ 6 #include <linux/bitmap.h> 7 #include <linux/export.h> 8 #include <linux/io.h> 9 #include <linux/module.h> 10 #include <linux/spinlock.h> 11 #include <linux/types.h> 12 13 #include "gpio-idio-16.h" 14 15 #define DEFAULT_SYMBOL_NAMESPACE GPIO_IDIO_16 16 17 /** 18 * idio_16_get - get signal value at signal offset 19 * @reg: ACCES IDIO-16 device registers 20 * @state: ACCES IDIO-16 device state 21 * @offset: offset of signal to get 22 * 23 * Returns the signal value (0=low, 1=high) for the signal at @offset. 24 */ 25 int idio_16_get(struct idio_16 __iomem *const reg, 26 struct idio_16_state *const state, const unsigned long offset) 27 { 28 const unsigned long mask = BIT(offset); 29 30 if (offset < IDIO_16_NOUT) 31 return test_bit(offset, state->out_state); 32 33 if (offset < 24) 34 return !!(ioread8(®->in0_7) & (mask >> IDIO_16_NOUT)); 35 36 if (offset < 32) 37 return !!(ioread8(®->in8_15) & (mask >> 24)); 38 39 return -EINVAL; 40 } 41 EXPORT_SYMBOL_GPL(idio_16_get); 42 43 /** 44 * idio_16_get_multiple - get multiple signal values at multiple signal offsets 45 * @reg: ACCES IDIO-16 device registers 46 * @state: ACCES IDIO-16 device state 47 * @mask: mask of signals to get 48 * @bits: bitmap to store signal values 49 * 50 * Stores in @bits the values (0=low, 1=high) for the signals defined by @mask. 51 */ 52 void idio_16_get_multiple(struct idio_16 __iomem *const reg, 53 struct idio_16_state *const state, 54 const unsigned long *const mask, 55 unsigned long *const bits) 56 { 57 unsigned long flags; 58 const unsigned long out_mask = GENMASK(IDIO_16_NOUT - 1, 0); 59 60 spin_lock_irqsave(&state->lock, flags); 61 62 bitmap_replace(bits, bits, state->out_state, &out_mask, IDIO_16_NOUT); 63 if (*mask & GENMASK(23, 16)) 64 bitmap_set_value8(bits, ioread8(®->in0_7), 16); 65 if (*mask & GENMASK(31, 24)) 66 bitmap_set_value8(bits, ioread8(®->in8_15), 24); 67 68 spin_unlock_irqrestore(&state->lock, flags); 69 } 70 EXPORT_SYMBOL_GPL(idio_16_get_multiple); 71 72 /** 73 * idio_16_set - set signal value at signal offset 74 * @reg: ACCES IDIO-16 device registers 75 * @state: ACCES IDIO-16 device state 76 * @offset: offset of signal to set 77 * @value: value of signal to set 78 * 79 * Assigns output @value for the signal at @offset. 80 */ 81 void idio_16_set(struct idio_16 __iomem *const reg, 82 struct idio_16_state *const state, const unsigned long offset, 83 const unsigned long value) 84 { 85 unsigned long flags; 86 87 if (offset >= IDIO_16_NOUT) 88 return; 89 90 spin_lock_irqsave(&state->lock, flags); 91 92 __assign_bit(offset, state->out_state, value); 93 if (offset < 8) 94 iowrite8(bitmap_get_value8(state->out_state, 0), ®->out0_7); 95 else 96 iowrite8(bitmap_get_value8(state->out_state, 8), ®->out8_15); 97 98 spin_unlock_irqrestore(&state->lock, flags); 99 } 100 EXPORT_SYMBOL_GPL(idio_16_set); 101 102 /** 103 * idio_16_set_multiple - set signal values at multiple signal offsets 104 * @reg: ACCES IDIO-16 device registers 105 * @state: ACCES IDIO-16 device state 106 * @mask: mask of signals to set 107 * @bits: bitmap of signal output values 108 * 109 * Assigns output values defined by @bits for the signals defined by @mask. 110 */ 111 void idio_16_set_multiple(struct idio_16 __iomem *const reg, 112 struct idio_16_state *const state, 113 const unsigned long *const mask, 114 const unsigned long *const bits) 115 { 116 unsigned long flags; 117 118 spin_lock_irqsave(&state->lock, flags); 119 120 bitmap_replace(state->out_state, state->out_state, bits, mask, 121 IDIO_16_NOUT); 122 if (*mask & GENMASK(7, 0)) 123 iowrite8(bitmap_get_value8(state->out_state, 0), ®->out0_7); 124 if (*mask & GENMASK(15, 8)) 125 iowrite8(bitmap_get_value8(state->out_state, 8), ®->out8_15); 126 127 spin_unlock_irqrestore(&state->lock, flags); 128 } 129 EXPORT_SYMBOL_GPL(idio_16_set_multiple); 130 131 /** 132 * idio_16_state_init - initialize idio_16_state structure 133 * @state: ACCES IDIO-16 device state 134 * 135 * Initializes the ACCES IDIO-16 device @state for use in idio-16 library 136 * functions. 137 */ 138 void idio_16_state_init(struct idio_16_state *const state) 139 { 140 spin_lock_init(&state->lock); 141 } 142 EXPORT_SYMBOL_GPL(idio_16_state_init); 143 144 MODULE_AUTHOR("William Breathitt Gray"); 145 MODULE_DESCRIPTION("ACCES IDIO-16 GPIO Library"); 146 MODULE_LICENSE("GPL"); 147