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

Merge tag 'counter-updates-for-6.5a' of git://git.kernel.org/pub/scm/linux/kernel/git/wbg/counter into char-misc-next

William writes:

First set of Counter updates for the 6.5 cycle

Biggest changes in this set include the introduction of a new Intel 8254
interface library module and the refactoring of the existing 104-quad-8
modules to migrate it to the regmap API. Some other minor cleanups
touching tools/counter and stm32-timer-cnt are also present.

Changes
* 104-quad-8
- Remove reference in Kconfig to 25-bit counter value
- Utilize bitfield access macros
- Refactor to buffer states for CMR, IOR, and IDR
- Utilize helper functions to handle PR, FLAG and PSC
- Migrate to the regmap API
* i8254
- Introduce the Intel 8254 interface library module
* stm32-timer-cnt
- Reset TIM_TISEL to its default value in probe
* tools/counter
- Add .gitignore
- Remove lingering 'include' directories on make clean

* tag 'counter-updates-for-6.5a' of git://git.kernel.org/pub/scm/linux/kernel/git/wbg/counter:
counter: i8254: Introduce the Intel 8254 interface library module
counter: 104-quad-8: Migrate to the regmap API
counter: 104-quad-8: Utilize helper functions to handle PR, FLAG and PSC
counter: 104-quad-8: Refactor to buffer states for CMR, IOR, and IDR
counter: 104-quad-8: Utilize bitfield access macros
tools/counter: Makefile: Remove lingering 'include' directories on make clean
tools/counter: Add .gitignore
counter: stm32-timer-cnt: Reset TIM_TISEL to its default value in probe
counter: 104-quad-8: Remove reference in Kconfig to 25-bit counter value

+1007 -367
+54
Documentation/ABI/testing/sysfs-bus-counter
··· 90 90 counter does not freeze at the boundary points, but 91 91 counts continuously throughout. 92 92 93 + interrupt on terminal count: 94 + The output signal is initially low, and will remain low 95 + until the counter reaches zero. The output signal then 96 + goes high and remains high until a new preset value is 97 + set. 98 + 99 + hardware retriggerable one-shot: 100 + The output signal is initially high. The output signal 101 + will go low by a trigger input signal, and will remain 102 + low until the counter reaches zero. The output will then 103 + go high and remain high until the next trigger. A 104 + trigger results in loading the counter to the preset 105 + value and setting the output signal low, thus starting 106 + the one-shot pulse. 107 + 108 + rate generator: 109 + The output signal is initially high. When the counter 110 + has decremented to 1, the output signal goes low for one 111 + clock pulse. The output signal then goes high again, the 112 + counter is reloaded to the preset value, and the process 113 + repeats in a periodic manner as such. 114 + 115 + square wave mode: 116 + The output signal is initially high. 117 + 118 + If the initial count is even, the counter is decremented 119 + by two on succeeding clock pulses. When the count 120 + expires, the output signal changes value and the 121 + counter is reloaded to the preset value. The process 122 + repeats in periodic manner as such. 123 + 124 + If the initial count is odd, the initial count minus one 125 + (an even number) is loaded and then is decremented by 126 + two on succeeding clock pulses. One clock pulse after 127 + the count expires, the output signal goes low and the 128 + counter is reloaded to the preset value minus one. 129 + Succeeding clock pulses decrement the count by two. When 130 + the count expires, the output goes high again and the 131 + counter is reloaded to the preset value minus one. The 132 + process repeats in a periodic manner as such. 133 + 134 + software triggered strobe: 135 + The output signal is initially high. When the count 136 + expires, the output will go low for one clock pulse and 137 + then go high again. The counting sequence is "triggered" 138 + by setting the preset value. 139 + 140 + hardware triggered strobe: 141 + The output signal is initially high. Counting is started 142 + by a trigger input signal. When the count expires, the 143 + output signal will go low for one clock pulse and then 144 + go high again. A trigger results in loading the counter 145 + to the preset value. 146 + 93 147 What: /sys/bus/counter/devices/counterX/countY/count_mode_available 94 148 What: /sys/bus/counter/devices/counterX/countY/error_noise_available 95 149 What: /sys/bus/counter/devices/counterX/countY/function_available
+7
MAINTAINERS
··· 10260 10260 S: Maintained 10261 10261 F: drivers/video/fbdev/i810/ 10262 10262 10263 + INTEL 8254 COUNTER DRIVER 10264 + M: William Breathitt Gray <william.gray@linaro.org> 10265 + L: linux-iio@vger.kernel.org 10266 + S: Maintained 10267 + F: drivers/counter/i8254.c 10268 + F: include/linux/i8254.h 10269 + 10263 10270 INTEL 8255 GPIO DRIVER 10264 10271 M: William Breathitt Gray <william.gray@linaro.org> 10265 10272 L: linux-gpio@vger.kernel.org
+439 -363
drivers/counter/104-quad-8.c
··· 5 5 * 6 6 * This driver supports the ACCES 104-QUAD-8 and ACCES 104-QUAD-4. 7 7 */ 8 - #include <linux/bitops.h> 8 + #include <linux/bitfield.h> 9 + #include <linux/bits.h> 9 10 #include <linux/counter.h> 10 11 #include <linux/device.h> 11 - #include <linux/errno.h> 12 + #include <linux/err.h> 12 13 #include <linux/io.h> 13 14 #include <linux/ioport.h> 14 15 #include <linux/interrupt.h> ··· 18 17 #include <linux/list.h> 19 18 #include <linux/module.h> 20 19 #include <linux/moduleparam.h> 21 - #include <linux/types.h> 20 + #include <linux/regmap.h> 22 21 #include <linux/spinlock.h> 22 + #include <linux/types.h> 23 + 24 + #include <asm/unaligned.h> 23 25 24 26 #define QUAD8_EXTENT 32 25 27 ··· 38 34 39 35 #define QUAD8_NUM_COUNTERS 8 40 36 41 - /** 42 - * struct channel_reg - channel register structure 43 - * @data: Count data 44 - * @control: Channel flags and control 45 - */ 46 - struct channel_reg { 47 - u8 data; 48 - u8 control; 49 - }; 50 - 51 - /** 52 - * struct quad8_reg - device register structure 53 - * @channel: quadrature counter data and control 54 - * @interrupt_status: channel interrupt status 55 - * @channel_oper: enable/reset counters and interrupt functions 56 - * @index_interrupt: enable channel interrupts 57 - * @reserved: reserved for Factory Use 58 - * @index_input_levels: index signal logical input level 59 - * @cable_status: differential encoder cable status 60 - */ 61 - struct quad8_reg { 62 - struct channel_reg channel[QUAD8_NUM_COUNTERS]; 63 - u8 interrupt_status; 64 - u8 channel_oper; 65 - u8 index_interrupt; 66 - u8 reserved[3]; 67 - u8 index_input_levels; 68 - u8 cable_status; 69 - }; 37 + #define QUAD8_DATA(_channel) ((_channel) * 2) 38 + #define QUAD8_CONTROL(_channel) (QUAD8_DATA(_channel) + 1) 39 + #define QUAD8_INTERRUPT_STATUS 0x10 40 + #define QUAD8_CHANNEL_OPERATION 0x11 41 + #define QUAD8_INDEX_INTERRUPT 0x12 42 + #define QUAD8_INDEX_INPUT_LEVELS 0x16 43 + #define QUAD8_CABLE_STATUS 0x17 70 44 71 45 /** 72 46 * struct quad8 - device private data structure 73 47 * @lock: lock to prevent clobbering device states during R/W ops 74 - * @counter: instance of the counter_device 48 + * @cmr: array of Counter Mode Register states 49 + * @ior: array of Input / Output Control Register states 50 + * @idr: array of Index Control Register states 75 51 * @fck_prescaler: array of filter clock prescaler configurations 76 52 * @preset: array of preset values 77 - * @count_mode: array of count mode configurations 78 - * @quadrature_mode: array of quadrature mode configurations 79 - * @quadrature_scale: array of quadrature mode scale configurations 80 - * @ab_enable: array of A and B inputs enable configurations 81 - * @preset_enable: array of set_to_preset_on_index attribute configurations 82 - * @irq_trigger: array of current IRQ trigger function configurations 83 - * @synchronous_mode: array of index function synchronous mode configurations 84 - * @index_polarity: array of index function polarity configurations 85 53 * @cable_fault_enable: differential encoder cable status enable configurations 86 - * @reg: I/O address offset for the device registers 54 + * @map: regmap for the device 87 55 */ 88 56 struct quad8 { 89 57 spinlock_t lock; 58 + u8 cmr[QUAD8_NUM_COUNTERS]; 59 + u8 ior[QUAD8_NUM_COUNTERS]; 60 + u8 idr[QUAD8_NUM_COUNTERS]; 90 61 unsigned int fck_prescaler[QUAD8_NUM_COUNTERS]; 91 62 unsigned int preset[QUAD8_NUM_COUNTERS]; 92 - unsigned int count_mode[QUAD8_NUM_COUNTERS]; 93 - unsigned int quadrature_mode[QUAD8_NUM_COUNTERS]; 94 - unsigned int quadrature_scale[QUAD8_NUM_COUNTERS]; 95 - unsigned int ab_enable[QUAD8_NUM_COUNTERS]; 96 - unsigned int preset_enable[QUAD8_NUM_COUNTERS]; 97 - unsigned int irq_trigger[QUAD8_NUM_COUNTERS]; 98 - unsigned int synchronous_mode[QUAD8_NUM_COUNTERS]; 99 - unsigned int index_polarity[QUAD8_NUM_COUNTERS]; 100 63 unsigned int cable_fault_enable; 101 - struct quad8_reg __iomem *reg; 64 + struct regmap *map; 65 + }; 66 + 67 + static const struct regmap_range quad8_wr_ranges[] = { 68 + regmap_reg_range(0x0, 0xF), regmap_reg_range(0x11, 0x12), regmap_reg_range(0x17, 0x17), 69 + }; 70 + static const struct regmap_range quad8_rd_ranges[] = { 71 + regmap_reg_range(0x0, 0x12), regmap_reg_range(0x16, 0x18), 72 + }; 73 + static const struct regmap_access_table quad8_wr_table = { 74 + .yes_ranges = quad8_wr_ranges, 75 + .n_yes_ranges = ARRAY_SIZE(quad8_wr_ranges), 76 + }; 77 + static const struct regmap_access_table quad8_rd_table = { 78 + .yes_ranges = quad8_rd_ranges, 79 + .n_yes_ranges = ARRAY_SIZE(quad8_rd_ranges), 80 + }; 81 + static const struct regmap_config quad8_regmap_config = { 82 + .reg_bits = 8, 83 + .reg_stride = 1, 84 + .val_bits = 8, 85 + .io_port = true, 86 + .wr_table = &quad8_wr_table, 87 + .rd_table = &quad8_rd_table, 102 88 }; 103 89 104 90 /* Error flag */ 105 - #define QUAD8_FLAG_E BIT(4) 91 + #define FLAG_E BIT(4) 106 92 /* Up/Down flag */ 107 - #define QUAD8_FLAG_UD BIT(5) 93 + #define FLAG_UD BIT(5) 94 + /* Counting up */ 95 + #define UP 0x1 96 + 97 + #define REGISTER_SELECTION GENMASK(6, 5) 98 + 108 99 /* Reset and Load Signal Decoders */ 109 - #define QUAD8_CTR_RLD 0x00 100 + #define SELECT_RLD u8_encode_bits(0x0, REGISTER_SELECTION) 110 101 /* Counter Mode Register */ 111 - #define QUAD8_CTR_CMR 0x20 102 + #define SELECT_CMR u8_encode_bits(0x1, REGISTER_SELECTION) 112 103 /* Input / Output Control Register */ 113 - #define QUAD8_CTR_IOR 0x40 104 + #define SELECT_IOR u8_encode_bits(0x2, REGISTER_SELECTION) 114 105 /* Index Control Register */ 115 - #define QUAD8_CTR_IDR 0x60 106 + #define SELECT_IDR u8_encode_bits(0x3, REGISTER_SELECTION) 107 + 108 + /* 109 + * Reset and Load Signal Decoders 110 + */ 111 + #define RESETS GENMASK(2, 1) 112 + #define LOADS GENMASK(4, 3) 116 113 /* Reset Byte Pointer (three byte data pointer) */ 117 - #define QUAD8_RLD_RESET_BP 0x01 118 - /* Reset Counter */ 119 - #define QUAD8_RLD_RESET_CNTR 0x02 120 - /* Reset Borrow Toggle, Carry Toggle, Compare Toggle, and Sign flags */ 121 - #define QUAD8_RLD_RESET_FLAGS 0x04 114 + #define RESET_BP BIT(0) 115 + /* Reset Borrow Toggle, Carry toggle, Compare toggle, Sign, and Index flags */ 116 + #define RESET_BT_CT_CPT_S_IDX u8_encode_bits(0x2, RESETS) 122 117 /* Reset Error flag */ 123 - #define QUAD8_RLD_RESET_E 0x06 118 + #define RESET_E u8_encode_bits(0x3, RESETS) 124 119 /* Preset Register to Counter */ 125 - #define QUAD8_RLD_PRESET_CNTR 0x08 120 + #define TRANSFER_PR_TO_CNTR u8_encode_bits(0x1, LOADS) 126 121 /* Transfer Counter to Output Latch */ 127 - #define QUAD8_RLD_CNTR_OUT 0x10 122 + #define TRANSFER_CNTR_TO_OL u8_encode_bits(0x2, LOADS) 128 123 /* Transfer Preset Register LSB to FCK Prescaler */ 129 - #define QUAD8_RLD_PRESET_PSC 0x18 130 - #define QUAD8_CHAN_OP_RESET_COUNTERS 0x01 131 - #define QUAD8_CHAN_OP_ENABLE_INTERRUPT_FUNC 0x04 132 - #define QUAD8_CMR_QUADRATURE_X1 0x08 133 - #define QUAD8_CMR_QUADRATURE_X2 0x10 134 - #define QUAD8_CMR_QUADRATURE_X4 0x18 124 + #define TRANSFER_PR0_TO_PSC u8_encode_bits(0x3, LOADS) 125 + 126 + /* 127 + * Counter Mode Registers 128 + */ 129 + #define COUNT_ENCODING BIT(0) 130 + #define COUNT_MODE GENMASK(2, 1) 131 + #define QUADRATURE_MODE GENMASK(4, 3) 132 + /* Binary count */ 133 + #define BINARY u8_encode_bits(0x0, COUNT_ENCODING) 134 + /* Normal count */ 135 + #define NORMAL_COUNT 0x0 136 + /* Range Limit */ 137 + #define RANGE_LIMIT 0x1 138 + /* Non-recycle count */ 139 + #define NON_RECYCLE_COUNT 0x2 140 + /* Modulo-N */ 141 + #define MODULO_N 0x3 142 + /* Non-quadrature */ 143 + #define NON_QUADRATURE 0x0 144 + /* Quadrature X1 */ 145 + #define QUADRATURE_X1 0x1 146 + /* Quadrature X2 */ 147 + #define QUADRATURE_X2 0x2 148 + /* Quadrature X4 */ 149 + #define QUADRATURE_X4 0x3 150 + 151 + /* 152 + * Input/Output Control Register 153 + */ 154 + #define AB_GATE BIT(0) 155 + #define LOAD_PIN BIT(1) 156 + #define FLG_PINS GENMASK(4, 3) 157 + /* Disable inputs A and B */ 158 + #define DISABLE_AB u8_encode_bits(0x0, AB_GATE) 159 + /* Load Counter input */ 160 + #define LOAD_CNTR 0x0 161 + /* FLG1 = CARRY(active low); FLG2 = BORROW(active low) */ 162 + #define FLG1_CARRY_FLG2_BORROW 0x0 163 + /* FLG1 = COMPARE(active low); FLG2 = BORROW(active low) */ 164 + #define FLG1_COMPARE_FLG2_BORROW 0x1 165 + /* FLG1 = Carry(active low)/Borrow(active low); FLG2 = U/D(active low) flag */ 166 + #define FLG1_CARRYBORROW_FLG2_UD 0x2 167 + /* FLG1 = INDX (low pulse at INDEX pin active level); FLG2 = E flag */ 168 + #define FLG1_INDX_FLG2_E 0x3 169 + 170 + /* 171 + * INDEX CONTROL REGISTERS 172 + */ 173 + #define INDEX_MODE BIT(0) 174 + #define INDEX_POLARITY BIT(1) 175 + /* Disable Index mode */ 176 + #define DISABLE_INDEX_MODE 0x0 177 + /* Enable Index mode */ 178 + #define ENABLE_INDEX_MODE 0x1 179 + /* Negative Index Polarity */ 180 + #define NEGATIVE_INDEX_POLARITY 0x0 181 + /* Positive Index Polarity */ 182 + #define POSITIVE_INDEX_POLARITY 0x1 183 + 184 + /* 185 + * Channel Operation Register 186 + */ 187 + #define COUNTERS_OPERATION BIT(0) 188 + #define INTERRUPT_FUNCTION BIT(2) 189 + /* Enable all Counters */ 190 + #define ENABLE_COUNTERS u8_encode_bits(0x0, COUNTERS_OPERATION) 191 + /* Reset all Counters */ 192 + #define RESET_COUNTERS u8_encode_bits(0x1, COUNTERS_OPERATION) 193 + /* Disable the interrupt function */ 194 + #define DISABLE_INTERRUPT_FUNCTION u8_encode_bits(0x0, INTERRUPT_FUNCTION) 195 + /* Enable the interrupt function */ 196 + #define ENABLE_INTERRUPT_FUNCTION u8_encode_bits(0x1, INTERRUPT_FUNCTION) 197 + /* Any write to the Channel Operation register clears any pending interrupts */ 198 + #define CLEAR_PENDING_INTERRUPTS (ENABLE_COUNTERS | ENABLE_INTERRUPT_FUNCTION) 135 199 136 200 /* Each Counter is 24 bits wide */ 137 201 #define LS7267_CNTR_MAX GENMASK(23, 0) 202 + 203 + static __always_inline int quad8_control_register_update(struct regmap *const map, u8 *const buf, 204 + const size_t channel, const u8 val, 205 + const u8 field) 206 + { 207 + u8p_replace_bits(&buf[channel], val, field); 208 + return regmap_write(map, QUAD8_CONTROL(channel), buf[channel]); 209 + } 138 210 139 211 static int quad8_signal_read(struct counter_device *counter, 140 212 struct counter_signal *signal, 141 213 enum counter_signal_level *level) 142 214 { 143 215 const struct quad8 *const priv = counter_priv(counter); 144 - unsigned int state; 216 + int ret; 145 217 146 218 /* Only Index signal levels can be read */ 147 219 if (signal->id < 16) 148 220 return -EINVAL; 149 221 150 - state = ioread8(&priv->reg->index_input_levels) & BIT(signal->id - 16); 222 + ret = regmap_test_bits(priv->map, QUAD8_INDEX_INPUT_LEVELS, BIT(signal->id - 16)); 223 + if (ret < 0) 224 + return ret; 151 225 152 - *level = (state) ? COUNTER_SIGNAL_LEVEL_HIGH : COUNTER_SIGNAL_LEVEL_LOW; 226 + *level = (ret) ? COUNTER_SIGNAL_LEVEL_HIGH : COUNTER_SIGNAL_LEVEL_LOW; 153 227 154 228 return 0; 155 229 } ··· 236 154 struct counter_count *count, u64 *val) 237 155 { 238 156 struct quad8 *const priv = counter_priv(counter); 239 - struct channel_reg __iomem *const chan = priv->reg->channel + count->id; 240 157 unsigned long irqflags; 241 - int i; 242 - 243 - *val = 0; 158 + u8 value[3]; 159 + int ret; 244 160 245 161 spin_lock_irqsave(&priv->lock, irqflags); 246 162 247 - /* Reset Byte Pointer; transfer Counter to Output Latch */ 248 - iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_CNTR_OUT, 249 - &chan->control); 163 + ret = regmap_write(priv->map, QUAD8_CONTROL(count->id), 164 + SELECT_RLD | RESET_BP | TRANSFER_CNTR_TO_OL); 165 + if (ret) 166 + goto exit_unlock; 167 + ret = regmap_noinc_read(priv->map, QUAD8_DATA(count->id), value, sizeof(value)); 250 168 251 - for (i = 0; i < 3; i++) 252 - *val |= (unsigned long)ioread8(&chan->data) << (8 * i); 253 - 169 + exit_unlock: 254 170 spin_unlock_irqrestore(&priv->lock, irqflags); 255 171 256 - return 0; 172 + *val = get_unaligned_le24(value); 173 + 174 + return ret; 175 + } 176 + 177 + static int quad8_preset_register_set(struct quad8 *const priv, const size_t id, 178 + const unsigned long preset) 179 + { 180 + u8 value[3]; 181 + int ret; 182 + 183 + put_unaligned_le24(preset, value); 184 + 185 + ret = regmap_write(priv->map, QUAD8_CONTROL(id), SELECT_RLD | RESET_BP); 186 + if (ret) 187 + return ret; 188 + return regmap_noinc_write(priv->map, QUAD8_DATA(id), value, sizeof(value)); 189 + } 190 + 191 + static int quad8_flag_register_reset(struct quad8 *const priv, const size_t id) 192 + { 193 + int ret; 194 + 195 + ret = regmap_write(priv->map, QUAD8_CONTROL(id), SELECT_RLD | RESET_BT_CT_CPT_S_IDX); 196 + if (ret) 197 + return ret; 198 + return regmap_write(priv->map, QUAD8_CONTROL(id), SELECT_RLD | RESET_E); 257 199 } 258 200 259 201 static int quad8_count_write(struct counter_device *counter, 260 202 struct counter_count *count, u64 val) 261 203 { 262 204 struct quad8 *const priv = counter_priv(counter); 263 - struct channel_reg __iomem *const chan = priv->reg->channel + count->id; 264 205 unsigned long irqflags; 265 - int i; 206 + int ret; 266 207 267 208 if (val > LS7267_CNTR_MAX) 268 209 return -ERANGE; 269 210 270 211 spin_lock_irqsave(&priv->lock, irqflags); 271 212 272 - /* Reset Byte Pointer */ 273 - iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control); 274 - 275 213 /* Counter can only be set via Preset Register */ 276 - for (i = 0; i < 3; i++) 277 - iowrite8(val >> (8 * i), &chan->data); 214 + ret = quad8_preset_register_set(priv, count->id, val); 215 + if (ret) 216 + goto exit_unlock; 217 + ret = regmap_write(priv->map, QUAD8_CONTROL(count->id), SELECT_RLD | TRANSFER_PR_TO_CNTR); 218 + if (ret) 219 + goto exit_unlock; 278 220 279 - /* Transfer Preset Register to Counter */ 280 - iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_PRESET_CNTR, &chan->control); 281 - 282 - /* Reset Byte Pointer */ 283 - iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control); 221 + ret = quad8_flag_register_reset(priv, count->id); 222 + if (ret) 223 + goto exit_unlock; 284 224 285 225 /* Set Preset Register back to original value */ 286 - val = priv->preset[count->id]; 287 - for (i = 0; i < 3; i++) 288 - iowrite8(val >> (8 * i), &chan->data); 226 + ret = quad8_preset_register_set(priv, count->id, priv->preset[count->id]); 289 227 290 - /* Reset Borrow, Carry, Compare, and Sign flags */ 291 - iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_FLAGS, &chan->control); 292 - /* Reset Error flag */ 293 - iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_E, &chan->control); 294 - 228 + exit_unlock: 295 229 spin_unlock_irqrestore(&priv->lock, irqflags); 296 230 297 - return 0; 231 + return ret; 298 232 } 299 233 300 234 static const enum counter_function quad8_count_functions_list[] = { ··· 323 225 static int quad8_function_get(const struct quad8 *const priv, const size_t id, 324 226 enum counter_function *const function) 325 227 { 326 - if (!priv->quadrature_mode[id]) { 228 + switch (u8_get_bits(priv->cmr[id], QUADRATURE_MODE)) { 229 + case NON_QUADRATURE: 327 230 *function = COUNTER_FUNCTION_PULSE_DIRECTION; 328 231 return 0; 329 - } 330 - 331 - switch (priv->quadrature_scale[id]) { 332 - case 0: 232 + case QUADRATURE_X1: 333 233 *function = COUNTER_FUNCTION_QUADRATURE_X1_A; 334 234 return 0; 335 - case 1: 235 + case QUADRATURE_X2: 336 236 *function = COUNTER_FUNCTION_QUADRATURE_X2_A; 337 237 return 0; 338 - case 2: 238 + case QUADRATURE_X4: 339 239 *function = COUNTER_FUNCTION_QUADRATURE_X4; 340 240 return 0; 341 241 default: ··· 365 269 { 366 270 struct quad8 *const priv = counter_priv(counter); 367 271 const int id = count->id; 368 - unsigned int *const quadrature_mode = priv->quadrature_mode + id; 369 - unsigned int *const scale = priv->quadrature_scale + id; 370 - unsigned int *const synchronous_mode = priv->synchronous_mode + id; 371 - u8 __iomem *const control = &priv->reg->channel[id].control; 372 272 unsigned long irqflags; 373 273 unsigned int mode_cfg; 374 - unsigned int idr_cfg; 274 + bool synchronous_mode; 275 + int ret; 276 + 277 + switch (function) { 278 + case COUNTER_FUNCTION_PULSE_DIRECTION: 279 + mode_cfg = NON_QUADRATURE; 280 + break; 281 + case COUNTER_FUNCTION_QUADRATURE_X1_A: 282 + mode_cfg = QUADRATURE_X1; 283 + break; 284 + case COUNTER_FUNCTION_QUADRATURE_X2_A: 285 + mode_cfg = QUADRATURE_X2; 286 + break; 287 + case COUNTER_FUNCTION_QUADRATURE_X4: 288 + mode_cfg = QUADRATURE_X4; 289 + break; 290 + default: 291 + /* should never reach this path */ 292 + return -EINVAL; 293 + } 375 294 376 295 spin_lock_irqsave(&priv->lock, irqflags); 377 296 378 - mode_cfg = priv->count_mode[id] << 1; 379 - idr_cfg = priv->index_polarity[id] << 1; 380 - 381 - if (function == COUNTER_FUNCTION_PULSE_DIRECTION) { 382 - *quadrature_mode = 0; 383 - 384 - /* Quadrature scaling only available in quadrature mode */ 385 - *scale = 0; 386 - 387 - /* Synchronous function not supported in non-quadrature mode */ 388 - if (*synchronous_mode) { 389 - *synchronous_mode = 0; 390 - /* Disable synchronous function mode */ 391 - iowrite8(QUAD8_CTR_IDR | idr_cfg, control); 392 - } 393 - } else { 394 - *quadrature_mode = 1; 395 - 396 - switch (function) { 397 - case COUNTER_FUNCTION_QUADRATURE_X1_A: 398 - *scale = 0; 399 - mode_cfg |= QUAD8_CMR_QUADRATURE_X1; 400 - break; 401 - case COUNTER_FUNCTION_QUADRATURE_X2_A: 402 - *scale = 1; 403 - mode_cfg |= QUAD8_CMR_QUADRATURE_X2; 404 - break; 405 - case COUNTER_FUNCTION_QUADRATURE_X4: 406 - *scale = 2; 407 - mode_cfg |= QUAD8_CMR_QUADRATURE_X4; 408 - break; 409 - default: 410 - /* should never reach this path */ 411 - spin_unlock_irqrestore(&priv->lock, irqflags); 412 - return -EINVAL; 413 - } 297 + /* Synchronous function not supported in non-quadrature mode */ 298 + synchronous_mode = u8_get_bits(priv->idr[id], INDEX_MODE) == ENABLE_INDEX_MODE; 299 + if (synchronous_mode && mode_cfg == NON_QUADRATURE) { 300 + ret = quad8_control_register_update(priv->map, priv->idr, id, DISABLE_INDEX_MODE, 301 + INDEX_MODE); 302 + if (ret) 303 + goto exit_unlock; 414 304 } 415 305 416 - /* Load mode configuration to Counter Mode Register */ 417 - iowrite8(QUAD8_CTR_CMR | mode_cfg, control); 306 + ret = quad8_control_register_update(priv->map, priv->cmr, id, mode_cfg, QUADRATURE_MODE); 418 307 308 + exit_unlock: 419 309 spin_unlock_irqrestore(&priv->lock, irqflags); 420 310 421 - return 0; 311 + return ret; 422 312 } 423 313 424 314 static int quad8_direction_read(struct counter_device *counter, ··· 412 330 enum counter_count_direction *direction) 413 331 { 414 332 const struct quad8 *const priv = counter_priv(counter); 415 - unsigned int ud_flag; 416 - u8 __iomem *const flag_addr = &priv->reg->channel[count->id].control; 333 + unsigned int flag; 334 + int ret; 417 335 418 - /* U/D flag: nonzero = up, zero = down */ 419 - ud_flag = ioread8(flag_addr) & QUAD8_FLAG_UD; 420 - 421 - *direction = (ud_flag) ? COUNTER_COUNT_DIRECTION_FORWARD : 336 + ret = regmap_read(priv->map, QUAD8_CONTROL(count->id), &flag); 337 + if (ret) 338 + return ret; 339 + *direction = (u8_get_bits(flag, FLAG_UD) == UP) ? COUNTER_COUNT_DIRECTION_FORWARD : 422 340 COUNTER_COUNT_DIRECTION_BACKWARD; 423 341 424 342 return 0; ··· 448 366 const size_t signal_a_id = count->synapses[0].signal->id; 449 367 enum counter_count_direction direction; 450 368 369 + /* Default action mode */ 370 + *action = COUNTER_SYNAPSE_ACTION_NONE; 371 + 451 372 /* Handle Index signals */ 452 373 if (synapse->signal->id >= 16) { 453 - if (!priv->preset_enable[count->id]) 374 + if (u8_get_bits(priv->ior[count->id], LOAD_PIN) == LOAD_CNTR) 454 375 *action = COUNTER_SYNAPSE_ACTION_RISING_EDGE; 455 - else 456 - *action = COUNTER_SYNAPSE_ACTION_NONE; 457 - 458 376 return 0; 459 377 } 460 378 ··· 473 391 } 474 392 475 393 spin_unlock_irqrestore(&priv->lock, irqflags); 476 - 477 - /* Default action mode */ 478 - *action = COUNTER_SYNAPSE_ACTION_NONE; 479 394 480 395 /* Determine action mode based on current count function mode */ 481 396 switch (function) { ··· 501 422 } 502 423 } 503 424 504 - enum { 505 - QUAD8_EVENT_CARRY = 0, 506 - QUAD8_EVENT_COMPARE = 1, 507 - QUAD8_EVENT_CARRY_BORROW = 2, 508 - QUAD8_EVENT_INDEX = 3, 509 - }; 510 - 511 425 static int quad8_events_configure(struct counter_device *counter) 512 426 { 513 427 struct quad8 *const priv = counter_priv(counter); 514 428 unsigned long irq_enabled = 0; 515 429 unsigned long irqflags; 516 430 struct counter_event_node *event_node; 517 - unsigned int next_irq_trigger; 518 - unsigned long ior_cfg; 431 + u8 flg_pins; 432 + int ret; 519 433 520 434 spin_lock_irqsave(&priv->lock, irqflags); 521 435 522 436 list_for_each_entry(event_node, &counter->events_list, l) { 523 437 switch (event_node->event) { 524 438 case COUNTER_EVENT_OVERFLOW: 525 - next_irq_trigger = QUAD8_EVENT_CARRY; 439 + flg_pins = FLG1_CARRY_FLG2_BORROW; 526 440 break; 527 441 case COUNTER_EVENT_THRESHOLD: 528 - next_irq_trigger = QUAD8_EVENT_COMPARE; 442 + flg_pins = FLG1_COMPARE_FLG2_BORROW; 529 443 break; 530 444 case COUNTER_EVENT_OVERFLOW_UNDERFLOW: 531 - next_irq_trigger = QUAD8_EVENT_CARRY_BORROW; 445 + flg_pins = FLG1_CARRYBORROW_FLG2_UD; 532 446 break; 533 447 case COUNTER_EVENT_INDEX: 534 - next_irq_trigger = QUAD8_EVENT_INDEX; 448 + flg_pins = FLG1_INDX_FLG2_E; 535 449 break; 536 450 default: 537 451 /* should never reach this path */ 538 - spin_unlock_irqrestore(&priv->lock, irqflags); 539 - return -EINVAL; 452 + ret = -EINVAL; 453 + goto exit_unlock; 540 454 } 541 455 542 456 /* Enable IRQ line */ 543 457 irq_enabled |= BIT(event_node->channel); 544 458 545 459 /* Skip configuration if it is the same as previously set */ 546 - if (priv->irq_trigger[event_node->channel] == next_irq_trigger) 460 + if (flg_pins == u8_get_bits(priv->ior[event_node->channel], FLG_PINS)) 547 461 continue; 548 462 549 463 /* Save new IRQ function configuration */ 550 - priv->irq_trigger[event_node->channel] = next_irq_trigger; 551 - 552 - /* Load configuration to I/O Control Register */ 553 - ior_cfg = priv->ab_enable[event_node->channel] | 554 - priv->preset_enable[event_node->channel] << 1 | 555 - priv->irq_trigger[event_node->channel] << 3; 556 - iowrite8(QUAD8_CTR_IOR | ior_cfg, 557 - &priv->reg->channel[event_node->channel].control); 464 + ret = quad8_control_register_update(priv->map, priv->ior, event_node->channel, 465 + flg_pins, FLG_PINS); 466 + if (ret) 467 + goto exit_unlock; 558 468 } 559 469 560 - iowrite8(irq_enabled, &priv->reg->index_interrupt); 470 + ret = regmap_write(priv->map, QUAD8_INDEX_INTERRUPT, irq_enabled); 561 471 472 + exit_unlock: 562 473 spin_unlock_irqrestore(&priv->lock, irqflags); 563 474 564 - return 0; 475 + return ret; 565 476 } 566 477 567 478 static int quad8_watch_validate(struct counter_device *counter, ··· 600 531 const struct quad8 *const priv = counter_priv(counter); 601 532 const size_t channel_id = signal->id - 16; 602 533 603 - *index_polarity = priv->index_polarity[channel_id]; 534 + *index_polarity = u8_get_bits(priv->idr[channel_id], INDEX_POLARITY); 604 535 605 536 return 0; 606 537 } ··· 611 542 { 612 543 struct quad8 *const priv = counter_priv(counter); 613 544 const size_t channel_id = signal->id - 16; 614 - u8 __iomem *const control = &priv->reg->channel[channel_id].control; 615 545 unsigned long irqflags; 616 - unsigned int idr_cfg = index_polarity << 1; 546 + int ret; 617 547 618 548 spin_lock_irqsave(&priv->lock, irqflags); 619 549 620 - idr_cfg |= priv->synchronous_mode[channel_id]; 621 - 622 - priv->index_polarity[channel_id] = index_polarity; 623 - 624 - /* Load Index Control configuration to Index Control Register */ 625 - iowrite8(QUAD8_CTR_IDR | idr_cfg, control); 550 + ret = quad8_control_register_update(priv->map, priv->idr, channel_id, index_polarity, 551 + INDEX_POLARITY); 626 552 627 553 spin_unlock_irqrestore(&priv->lock, irqflags); 628 554 629 - return 0; 555 + return ret; 630 556 } 631 557 632 558 static int quad8_polarity_read(struct counter_device *counter, ··· 635 571 if (err) 636 572 return err; 637 573 638 - *polarity = (index_polarity) ? COUNTER_SIGNAL_POLARITY_POSITIVE : 574 + *polarity = (index_polarity == POSITIVE_INDEX_POLARITY) ? COUNTER_SIGNAL_POLARITY_POSITIVE : 639 575 COUNTER_SIGNAL_POLARITY_NEGATIVE; 640 576 641 577 return 0; ··· 645 581 struct counter_signal *signal, 646 582 enum counter_signal_polarity polarity) 647 583 { 648 - const u32 pol = (polarity == COUNTER_SIGNAL_POLARITY_POSITIVE) ? 1 : 0; 584 + const u32 pol = (polarity == COUNTER_SIGNAL_POLARITY_POSITIVE) ? POSITIVE_INDEX_POLARITY : 585 + NEGATIVE_INDEX_POLARITY; 649 586 650 587 return quad8_index_polarity_set(counter, signal, pol); 651 588 } ··· 663 598 const struct quad8 *const priv = counter_priv(counter); 664 599 const size_t channel_id = signal->id - 16; 665 600 666 - *synchronous_mode = priv->synchronous_mode[channel_id]; 601 + *synchronous_mode = u8_get_bits(priv->idr[channel_id], INDEX_MODE); 667 602 668 603 return 0; 669 604 } ··· 674 609 { 675 610 struct quad8 *const priv = counter_priv(counter); 676 611 const size_t channel_id = signal->id - 16; 677 - u8 __iomem *const control = &priv->reg->channel[channel_id].control; 612 + u8 quadrature_mode; 678 613 unsigned long irqflags; 679 - unsigned int idr_cfg = synchronous_mode; 614 + int ret; 680 615 681 616 spin_lock_irqsave(&priv->lock, irqflags); 682 617 683 - idr_cfg |= priv->index_polarity[channel_id] << 1; 684 - 685 618 /* Index function must be non-synchronous in non-quadrature mode */ 686 - if (synchronous_mode && !priv->quadrature_mode[channel_id]) { 687 - spin_unlock_irqrestore(&priv->lock, irqflags); 688 - return -EINVAL; 619 + quadrature_mode = u8_get_bits(priv->idr[channel_id], QUADRATURE_MODE); 620 + if (synchronous_mode && quadrature_mode == NON_QUADRATURE) { 621 + ret = -EINVAL; 622 + goto exit_unlock; 689 623 } 690 624 691 - priv->synchronous_mode[channel_id] = synchronous_mode; 625 + ret = quad8_control_register_update(priv->map, priv->idr, channel_id, synchronous_mode, 626 + INDEX_MODE); 692 627 693 - /* Load Index Control configuration to Index Control Register */ 694 - iowrite8(QUAD8_CTR_IDR | idr_cfg, control); 695 - 628 + exit_unlock: 696 629 spin_unlock_irqrestore(&priv->lock, irqflags); 697 630 698 - return 0; 631 + return ret; 699 632 } 700 633 701 634 static int quad8_count_floor_read(struct counter_device *counter, ··· 711 648 { 712 649 const struct quad8 *const priv = counter_priv(counter); 713 650 714 - /* Map 104-QUAD-8 count mode to Generic Counter count mode */ 715 - switch (priv->count_mode[count->id]) { 716 - case 0: 651 + switch (u8_get_bits(priv->cmr[count->id], COUNT_MODE)) { 652 + case NORMAL_COUNT: 717 653 *cnt_mode = COUNTER_COUNT_MODE_NORMAL; 718 654 break; 719 - case 1: 655 + case RANGE_LIMIT: 720 656 *cnt_mode = COUNTER_COUNT_MODE_RANGE_LIMIT; 721 657 break; 722 - case 2: 658 + case NON_RECYCLE_COUNT: 723 659 *cnt_mode = COUNTER_COUNT_MODE_NON_RECYCLE; 724 660 break; 725 - case 3: 661 + case MODULO_N: 726 662 *cnt_mode = COUNTER_COUNT_MODE_MODULO_N; 727 663 break; 728 664 } ··· 735 673 { 736 674 struct quad8 *const priv = counter_priv(counter); 737 675 unsigned int count_mode; 738 - unsigned int mode_cfg; 739 - u8 __iomem *const control = &priv->reg->channel[count->id].control; 740 676 unsigned long irqflags; 677 + int ret; 741 678 742 - /* Map Generic Counter count mode to 104-QUAD-8 count mode */ 743 679 switch (cnt_mode) { 744 680 case COUNTER_COUNT_MODE_NORMAL: 745 - count_mode = 0; 681 + count_mode = NORMAL_COUNT; 746 682 break; 747 683 case COUNTER_COUNT_MODE_RANGE_LIMIT: 748 - count_mode = 1; 684 + count_mode = RANGE_LIMIT; 749 685 break; 750 686 case COUNTER_COUNT_MODE_NON_RECYCLE: 751 - count_mode = 2; 687 + count_mode = NON_RECYCLE_COUNT; 752 688 break; 753 689 case COUNTER_COUNT_MODE_MODULO_N: 754 - count_mode = 3; 690 + count_mode = MODULO_N; 755 691 break; 756 692 default: 757 693 /* should never reach this path */ ··· 758 698 759 699 spin_lock_irqsave(&priv->lock, irqflags); 760 700 761 - priv->count_mode[count->id] = count_mode; 762 - 763 - /* Set count mode configuration value */ 764 - mode_cfg = count_mode << 1; 765 - 766 - /* Add quadrature mode configuration */ 767 - if (priv->quadrature_mode[count->id]) 768 - mode_cfg |= (priv->quadrature_scale[count->id] + 1) << 3; 769 - 770 - /* Load mode configuration to Counter Mode Register */ 771 - iowrite8(QUAD8_CTR_CMR | mode_cfg, control); 701 + ret = quad8_control_register_update(priv->map, priv->cmr, count->id, count_mode, 702 + COUNT_MODE); 772 703 773 704 spin_unlock_irqrestore(&priv->lock, irqflags); 774 705 775 - return 0; 706 + return ret; 776 707 } 777 708 778 709 static int quad8_count_enable_read(struct counter_device *counter, ··· 771 720 { 772 721 const struct quad8 *const priv = counter_priv(counter); 773 722 774 - *enable = priv->ab_enable[count->id]; 723 + *enable = u8_get_bits(priv->ior[count->id], AB_GATE); 775 724 776 725 return 0; 777 726 } ··· 780 729 struct counter_count *count, u8 enable) 781 730 { 782 731 struct quad8 *const priv = counter_priv(counter); 783 - u8 __iomem *const control = &priv->reg->channel[count->id].control; 784 732 unsigned long irqflags; 785 - unsigned int ior_cfg; 733 + int ret; 786 734 787 735 spin_lock_irqsave(&priv->lock, irqflags); 788 736 789 - priv->ab_enable[count->id] = enable; 790 - 791 - ior_cfg = enable | priv->preset_enable[count->id] << 1 | 792 - priv->irq_trigger[count->id] << 3; 793 - 794 - /* Load I/O control configuration */ 795 - iowrite8(QUAD8_CTR_IOR | ior_cfg, control); 737 + ret = quad8_control_register_update(priv->map, priv->ior, count->id, enable, AB_GATE); 796 738 797 739 spin_unlock_irqrestore(&priv->lock, irqflags); 798 740 799 - return 0; 741 + return ret; 800 742 } 801 743 802 744 static const char *const quad8_noise_error_states[] = { ··· 801 757 struct counter_count *count, u32 *noise_error) 802 758 { 803 759 const struct quad8 *const priv = counter_priv(counter); 804 - u8 __iomem *const flag_addr = &priv->reg->channel[count->id].control; 760 + unsigned int flag; 761 + int ret; 805 762 806 - *noise_error = !!(ioread8(flag_addr) & QUAD8_FLAG_E); 763 + ret = regmap_read(priv->map, QUAD8_CONTROL(count->id), &flag); 764 + if (ret) 765 + return ret; 766 + *noise_error = u8_get_bits(flag, FLAG_E); 807 767 808 768 return 0; 809 769 } ··· 822 774 return 0; 823 775 } 824 776 825 - static void quad8_preset_register_set(struct quad8 *const priv, const int id, 826 - const unsigned int preset) 827 - { 828 - struct channel_reg __iomem *const chan = priv->reg->channel + id; 829 - int i; 830 - 831 - priv->preset[id] = preset; 832 - 833 - /* Reset Byte Pointer */ 834 - iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control); 835 - 836 - /* Set Preset Register */ 837 - for (i = 0; i < 3; i++) 838 - iowrite8(preset >> (8 * i), &chan->data); 839 - } 840 - 841 777 static int quad8_count_preset_write(struct counter_device *counter, 842 778 struct counter_count *count, u64 preset) 843 779 { 844 780 struct quad8 *const priv = counter_priv(counter); 845 781 unsigned long irqflags; 782 + int ret; 846 783 847 784 if (preset > LS7267_CNTR_MAX) 848 785 return -ERANGE; 849 786 850 787 spin_lock_irqsave(&priv->lock, irqflags); 851 788 852 - quad8_preset_register_set(priv, count->id, preset); 789 + priv->preset[count->id] = preset; 790 + ret = quad8_preset_register_set(priv, count->id, preset); 853 791 854 792 spin_unlock_irqrestore(&priv->lock, irqflags); 855 793 856 - return 0; 794 + return ret; 857 795 } 858 796 859 797 static int quad8_count_ceiling_read(struct counter_device *counter, ··· 851 817 spin_lock_irqsave(&priv->lock, irqflags); 852 818 853 819 /* Range Limit and Modulo-N count modes use preset value as ceiling */ 854 - switch (priv->count_mode[count->id]) { 855 - case 1: 856 - case 3: 820 + switch (u8_get_bits(priv->cmr[count->id], COUNT_MODE)) { 821 + case RANGE_LIMIT: 822 + case MODULO_N: 857 823 *ceiling = priv->preset[count->id]; 858 824 break; 859 825 default: ··· 871 837 { 872 838 struct quad8 *const priv = counter_priv(counter); 873 839 unsigned long irqflags; 840 + int ret; 874 841 875 842 if (ceiling > LS7267_CNTR_MAX) 876 843 return -ERANGE; ··· 879 844 spin_lock_irqsave(&priv->lock, irqflags); 880 845 881 846 /* Range Limit and Modulo-N count modes use preset value as ceiling */ 882 - switch (priv->count_mode[count->id]) { 883 - case 1: 884 - case 3: 885 - quad8_preset_register_set(priv, count->id, ceiling); 886 - spin_unlock_irqrestore(&priv->lock, irqflags); 887 - return 0; 847 + switch (u8_get_bits(priv->cmr[count->id], COUNT_MODE)) { 848 + case RANGE_LIMIT: 849 + case MODULO_N: 850 + priv->preset[count->id] = ceiling; 851 + ret = quad8_preset_register_set(priv, count->id, ceiling); 852 + break; 853 + default: 854 + ret = -EINVAL; 855 + break; 888 856 } 889 857 890 858 spin_unlock_irqrestore(&priv->lock, irqflags); 891 859 892 - return -EINVAL; 860 + return ret; 893 861 } 894 862 895 863 static int quad8_count_preset_enable_read(struct counter_device *counter, ··· 901 863 { 902 864 const struct quad8 *const priv = counter_priv(counter); 903 865 904 - *preset_enable = !priv->preset_enable[count->id]; 866 + /* Preset enable is active low in Input/Output Control register */ 867 + *preset_enable = !u8_get_bits(priv->ior[count->id], LOAD_PIN); 905 868 906 869 return 0; 907 870 } ··· 912 873 u8 preset_enable) 913 874 { 914 875 struct quad8 *const priv = counter_priv(counter); 915 - u8 __iomem *const control = &priv->reg->channel[count->id].control; 916 876 unsigned long irqflags; 917 - unsigned int ior_cfg; 918 - 919 - /* Preset enable is active low in Input/Output Control register */ 920 - preset_enable = !preset_enable; 877 + int ret; 921 878 922 879 spin_lock_irqsave(&priv->lock, irqflags); 923 880 924 - priv->preset_enable[count->id] = preset_enable; 925 - 926 - ior_cfg = priv->ab_enable[count->id] | preset_enable << 1 | 927 - priv->irq_trigger[count->id] << 3; 928 - 929 - /* Load I/O control configuration to Input / Output Control Register */ 930 - iowrite8(QUAD8_CTR_IOR | ior_cfg, control); 881 + /* Preset enable is active low in Input/Output Control register */ 882 + ret = quad8_control_register_update(priv->map, priv->ior, count->id, !preset_enable, 883 + LOAD_PIN); 931 884 932 885 spin_unlock_irqrestore(&priv->lock, irqflags); 933 886 934 - return 0; 887 + return ret; 935 888 } 936 889 937 890 static int quad8_signal_cable_fault_read(struct counter_device *counter, ··· 934 903 const size_t channel_id = signal->id / 2; 935 904 unsigned long irqflags; 936 905 bool disabled; 937 - unsigned int status; 906 + int ret; 938 907 939 908 spin_lock_irqsave(&priv->lock, irqflags); 940 909 ··· 945 914 return -EINVAL; 946 915 } 947 916 948 - /* Logic 0 = cable fault */ 949 - status = ioread8(&priv->reg->cable_status); 917 + ret = regmap_test_bits(priv->map, QUAD8_CABLE_STATUS, BIT(channel_id)); 918 + if (ret < 0) { 919 + spin_unlock_irqrestore(&priv->lock, irqflags); 920 + return ret; 921 + } 950 922 951 923 spin_unlock_irqrestore(&priv->lock, irqflags); 952 924 953 - /* Mask respective channel and invert logic */ 954 - *cable_fault = !(status & BIT(channel_id)); 925 + /* Logic 0 = cable fault */ 926 + *cable_fault = !ret; 955 927 956 928 return 0; 957 929 } ··· 979 945 const size_t channel_id = signal->id / 2; 980 946 unsigned long irqflags; 981 947 unsigned int cable_fault_enable; 948 + int ret; 982 949 983 950 spin_lock_irqsave(&priv->lock, irqflags); 984 951 ··· 991 956 /* Enable is active low in Differential Encoder Cable Status register */ 992 957 cable_fault_enable = ~priv->cable_fault_enable; 993 958 994 - iowrite8(cable_fault_enable, &priv->reg->cable_status); 959 + ret = regmap_write(priv->map, QUAD8_CABLE_STATUS, cable_fault_enable); 995 960 996 961 spin_unlock_irqrestore(&priv->lock, irqflags); 997 962 998 - return 0; 963 + return ret; 999 964 } 1000 965 1001 966 static int quad8_signal_fck_prescaler_read(struct counter_device *counter, ··· 1009 974 return 0; 1010 975 } 1011 976 977 + static int quad8_filter_clock_prescaler_set(struct quad8 *const priv, const size_t id, 978 + const u8 prescaler) 979 + { 980 + int ret; 981 + 982 + ret = regmap_write(priv->map, QUAD8_CONTROL(id), SELECT_RLD | RESET_BP); 983 + if (ret) 984 + return ret; 985 + ret = regmap_write(priv->map, QUAD8_DATA(id), prescaler); 986 + if (ret) 987 + return ret; 988 + return regmap_write(priv->map, QUAD8_CONTROL(id), SELECT_RLD | TRANSFER_PR0_TO_PSC); 989 + } 990 + 1012 991 static int quad8_signal_fck_prescaler_write(struct counter_device *counter, 1013 992 struct counter_signal *signal, 1014 993 u8 prescaler) 1015 994 { 1016 995 struct quad8 *const priv = counter_priv(counter); 1017 996 const size_t channel_id = signal->id / 2; 1018 - struct channel_reg __iomem *const chan = priv->reg->channel + channel_id; 1019 997 unsigned long irqflags; 998 + int ret; 1020 999 1021 1000 spin_lock_irqsave(&priv->lock, irqflags); 1022 1001 1023 1002 priv->fck_prescaler[channel_id] = prescaler; 1024 - 1025 - /* Reset Byte Pointer */ 1026 - iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control); 1027 - 1028 - /* Set filter clock factor */ 1029 - iowrite8(prescaler, &chan->data); 1030 - iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_PRESET_PSC, 1031 - &chan->control); 1003 + ret = quad8_filter_clock_prescaler_set(priv, channel_id, prescaler); 1032 1004 1033 1005 spin_unlock_irqrestore(&priv->lock, irqflags); 1034 1006 1035 - return 0; 1007 + return ret; 1036 1008 } 1037 1009 1038 1010 static struct counter_comp quad8_signal_ext[] = { ··· 1192 1150 { 1193 1151 struct counter_device *counter = private; 1194 1152 struct quad8 *const priv = counter_priv(counter); 1153 + unsigned int status; 1195 1154 unsigned long irq_status; 1196 1155 unsigned long channel; 1156 + unsigned int flg_pins; 1197 1157 u8 event; 1158 + int ret; 1198 1159 1199 - irq_status = ioread8(&priv->reg->interrupt_status); 1200 - if (!irq_status) 1160 + ret = regmap_read(priv->map, QUAD8_INTERRUPT_STATUS, &status); 1161 + if (ret) 1162 + return ret; 1163 + if (!status) 1201 1164 return IRQ_NONE; 1202 1165 1166 + irq_status = status; 1203 1167 for_each_set_bit(channel, &irq_status, QUAD8_NUM_COUNTERS) { 1204 - switch (priv->irq_trigger[channel]) { 1205 - case QUAD8_EVENT_CARRY: 1168 + flg_pins = u8_get_bits(priv->ior[channel], FLG_PINS); 1169 + switch (flg_pins) { 1170 + case FLG1_CARRY_FLG2_BORROW: 1206 1171 event = COUNTER_EVENT_OVERFLOW; 1207 1172 break; 1208 - case QUAD8_EVENT_COMPARE: 1173 + case FLG1_COMPARE_FLG2_BORROW: 1209 1174 event = COUNTER_EVENT_THRESHOLD; 1210 1175 break; 1211 - case QUAD8_EVENT_CARRY_BORROW: 1176 + case FLG1_CARRYBORROW_FLG2_UD: 1212 1177 event = COUNTER_EVENT_OVERFLOW_UNDERFLOW; 1213 1178 break; 1214 - case QUAD8_EVENT_INDEX: 1179 + case FLG1_INDX_FLG2_E: 1215 1180 event = COUNTER_EVENT_INDEX; 1216 1181 break; 1217 1182 default: 1218 1183 /* should never reach this path */ 1219 1184 WARN_ONCE(true, "invalid interrupt trigger function %u configured for channel %lu\n", 1220 - priv->irq_trigger[channel], channel); 1185 + flg_pins, channel); 1221 1186 continue; 1222 1187 } 1223 1188 1224 1189 counter_push_event(counter, event, channel); 1225 1190 } 1226 1191 1227 - /* Clear pending interrupts on device */ 1228 - iowrite8(QUAD8_CHAN_OP_ENABLE_INTERRUPT_FUNC, &priv->reg->channel_oper); 1192 + ret = regmap_write(priv->map, QUAD8_CHANNEL_OPERATION, CLEAR_PENDING_INTERRUPTS); 1193 + if (ret) 1194 + return ret; 1229 1195 1230 1196 return IRQ_HANDLED; 1231 1197 } 1232 1198 1233 - static void quad8_init_counter(struct channel_reg __iomem *const chan) 1199 + static int quad8_init_counter(struct quad8 *const priv, const size_t channel) 1234 1200 { 1235 - unsigned long i; 1201 + int ret; 1236 1202 1237 - /* Reset Byte Pointer */ 1238 - iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control); 1239 - /* Reset filter clock factor */ 1240 - iowrite8(0, &chan->data); 1241 - iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP | QUAD8_RLD_PRESET_PSC, 1242 - &chan->control); 1243 - /* Reset Byte Pointer */ 1244 - iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control); 1245 - /* Reset Preset Register */ 1246 - for (i = 0; i < 3; i++) 1247 - iowrite8(0x00, &chan->data); 1248 - /* Reset Borrow, Carry, Compare, and Sign flags */ 1249 - iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_FLAGS, &chan->control); 1250 - /* Reset Error flag */ 1251 - iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_E, &chan->control); 1203 + ret = quad8_filter_clock_prescaler_set(priv, channel, 0); 1204 + if (ret) 1205 + return ret; 1206 + ret = quad8_preset_register_set(priv, channel, 0); 1207 + if (ret) 1208 + return ret; 1209 + ret = quad8_flag_register_reset(priv, channel); 1210 + if (ret) 1211 + return ret; 1212 + 1252 1213 /* Binary encoding; Normal count; non-quadrature mode */ 1253 - iowrite8(QUAD8_CTR_CMR, &chan->control); 1214 + priv->cmr[channel] = SELECT_CMR | BINARY | u8_encode_bits(NORMAL_COUNT, COUNT_MODE) | 1215 + u8_encode_bits(NON_QUADRATURE, QUADRATURE_MODE); 1216 + ret = regmap_write(priv->map, QUAD8_CONTROL(channel), priv->cmr[channel]); 1217 + if (ret) 1218 + return ret; 1219 + 1254 1220 /* Disable A and B inputs; preset on index; FLG1 as Carry */ 1255 - iowrite8(QUAD8_CTR_IOR, &chan->control); 1221 + priv->ior[channel] = SELECT_IOR | DISABLE_AB | u8_encode_bits(LOAD_CNTR, LOAD_PIN) | 1222 + u8_encode_bits(FLG1_CARRY_FLG2_BORROW, FLG_PINS); 1223 + ret = regmap_write(priv->map, QUAD8_CONTROL(channel), priv->ior[channel]); 1224 + if (ret) 1225 + return ret; 1226 + 1256 1227 /* Disable index function; negative index polarity */ 1257 - iowrite8(QUAD8_CTR_IDR, &chan->control); 1228 + priv->idr[channel] = SELECT_IDR | u8_encode_bits(DISABLE_INDEX_MODE, INDEX_MODE) | 1229 + u8_encode_bits(NEGATIVE_INDEX_POLARITY, INDEX_POLARITY); 1230 + return regmap_write(priv->map, QUAD8_CONTROL(channel), priv->idr[channel]); 1258 1231 } 1259 1232 1260 1233 static int quad8_probe(struct device *dev, unsigned int id) 1261 1234 { 1262 1235 struct counter_device *counter; 1263 1236 struct quad8 *priv; 1237 + void __iomem *regs; 1264 1238 unsigned long i; 1265 - int err; 1239 + int ret; 1266 1240 1267 1241 if (!devm_request_region(dev, base[id], QUAD8_EXTENT, dev_name(dev))) { 1268 1242 dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n", ··· 1291 1233 return -ENOMEM; 1292 1234 priv = counter_priv(counter); 1293 1235 1294 - priv->reg = devm_ioport_map(dev, base[id], QUAD8_EXTENT); 1295 - if (!priv->reg) 1236 + regs = devm_ioport_map(dev, base[id], QUAD8_EXTENT); 1237 + if (!regs) 1296 1238 return -ENOMEM; 1239 + 1240 + priv->map = devm_regmap_init_mmio(dev, regs, &quad8_regmap_config); 1241 + if (IS_ERR(priv->map)) 1242 + return dev_err_probe(dev, PTR_ERR(priv->map), 1243 + "Unable to initialize register map\n"); 1297 1244 1298 1245 /* Initialize Counter device and driver data */ 1299 1246 counter->name = dev_name(dev); ··· 1312 1249 spin_lock_init(&priv->lock); 1313 1250 1314 1251 /* Reset Index/Interrupt Register */ 1315 - iowrite8(0x00, &priv->reg->index_interrupt); 1252 + ret = regmap_write(priv->map, QUAD8_INDEX_INTERRUPT, 0x00); 1253 + if (ret) 1254 + return ret; 1316 1255 /* Reset all counters and disable interrupt function */ 1317 - iowrite8(QUAD8_CHAN_OP_RESET_COUNTERS, &priv->reg->channel_oper); 1256 + ret = regmap_write(priv->map, QUAD8_CHANNEL_OPERATION, 1257 + RESET_COUNTERS | DISABLE_INTERRUPT_FUNCTION); 1258 + if (ret) 1259 + return ret; 1318 1260 /* Set initial configuration for all counters */ 1319 - for (i = 0; i < QUAD8_NUM_COUNTERS; i++) 1320 - quad8_init_counter(priv->reg->channel + i); 1261 + for (i = 0; i < QUAD8_NUM_COUNTERS; i++) { 1262 + ret = quad8_init_counter(priv, i); 1263 + if (ret) 1264 + return ret; 1265 + } 1321 1266 /* Disable Differential Encoder Cable Status for all channels */ 1322 - iowrite8(0xFF, &priv->reg->cable_status); 1267 + ret = regmap_write(priv->map, QUAD8_CABLE_STATUS, GENMASK(7, 0)); 1268 + if (ret) 1269 + return ret; 1323 1270 /* Enable all counters and enable interrupt function */ 1324 - iowrite8(QUAD8_CHAN_OP_ENABLE_INTERRUPT_FUNC, &priv->reg->channel_oper); 1271 + ret = regmap_write(priv->map, QUAD8_CHANNEL_OPERATION, 1272 + ENABLE_COUNTERS | ENABLE_INTERRUPT_FUNCTION); 1273 + if (ret) 1274 + return ret; 1325 1275 1326 - err = devm_request_irq(&counter->dev, irq[id], quad8_irq_handler, 1276 + ret = devm_request_irq(&counter->dev, irq[id], quad8_irq_handler, 1327 1277 IRQF_SHARED, counter->name, counter); 1328 - if (err) 1329 - return err; 1278 + if (ret) 1279 + return ret; 1330 1280 1331 - err = devm_counter_add(dev, counter); 1332 - if (err < 0) 1333 - return dev_err_probe(dev, err, "Failed to add counter\n"); 1281 + ret = devm_counter_add(dev, counter); 1282 + if (ret < 0) 1283 + return dev_err_probe(dev, ret, "Failed to add counter\n"); 1334 1284 1335 1285 return 0; 1336 1286 }
+19 -3
drivers/counter/Kconfig
··· 10 10 interface. You only need to enable this, if you also want to enable 11 11 one or more of the counter device drivers below. 12 12 13 + config I8254 14 + tristate 15 + select COUNTER 16 + select REGMAP 17 + help 18 + Enables support for the i8254 interface library functions. The i8254 19 + interface library provides functions to facilitate communication with 20 + interfaces compatible with the venerable Intel 8254 Programmable 21 + Interval Timer (PIT). The Intel 825x family of chips was first 22 + released in the early 1980s but compatible interfaces are nowadays 23 + typically found embedded in larger VLSI processing chips and FPGA 24 + components. 25 + 26 + If built as a module its name will be i8254. 27 + 13 28 if COUNTER 14 29 15 30 config 104_QUAD_8 ··· 32 17 depends on (PC104 && X86) || COMPILE_TEST 33 18 depends on HAS_IOPORT_MAP 34 19 select ISA_BUS_API 20 + select REGMAP_MMIO 35 21 help 36 22 Say yes here to build support for the ACCES 104-QUAD-8 quadrature 37 23 encoder counter/interface device family (104-QUAD-8, 104-QUAD-4). 38 24 39 25 A counter's respective error flag may be cleared by performing a write 40 - operation on the respective count value attribute. Although the 41 - 104-QUAD-8 counters have a 25-bit range, only the lower 24 bits may be 42 - set, either directly or via the counter's preset attribute. 26 + operation on the respective count value attribute. The 104-QUAD-8 27 + counters may be set either directly or via the counter's preset 28 + attribute. 43 29 44 30 The base port addresses for the devices may be configured via the base 45 31 array module parameter. The interrupt line numbers for the devices may
+1
drivers/counter/Makefile
··· 6 6 obj-$(CONFIG_COUNTER) += counter.o 7 7 counter-y := counter-core.o counter-sysfs.o counter-chrdev.o 8 8 9 + obj-$(CONFIG_I8254) += i8254.o 9 10 obj-$(CONFIG_104_QUAD_8) += 104-quad-8.o 10 11 obj-$(CONFIG_INTERRUPT_CNT) += interrupt-cnt.o 11 12 obj-$(CONFIG_RZ_MTU3_CNT) += rz-mtu3-cnt.o
+7 -1
drivers/counter/counter-sysfs.c
··· 88 88 [COUNTER_COUNT_MODE_NORMAL] = "normal", 89 89 [COUNTER_COUNT_MODE_RANGE_LIMIT] = "range limit", 90 90 [COUNTER_COUNT_MODE_NON_RECYCLE] = "non-recycle", 91 - [COUNTER_COUNT_MODE_MODULO_N] = "modulo-n" 91 + [COUNTER_COUNT_MODE_MODULO_N] = "modulo-n", 92 + [COUNTER_COUNT_MODE_INTERRUPT_ON_TERMINAL_COUNT] = "interrupt on terminal count", 93 + [COUNTER_COUNT_MODE_HARDWARE_RETRIGGERABLE_ONESHOT] = "hardware retriggerable one-shot", 94 + [COUNTER_COUNT_MODE_RATE_GENERATOR] = "rate generator", 95 + [COUNTER_COUNT_MODE_SQUARE_WAVE_MODE] = "square wave mode", 96 + [COUNTER_COUNT_MODE_SOFTWARE_TRIGGERED_STROBE] = "software triggered strobe", 97 + [COUNTER_COUNT_MODE_HARDWARE_TRIGGERED_STROBE] = "hardware triggered strobe", 92 98 }; 93 99 94 100 static const char *const counter_signal_polarity_str[] = {
+447
drivers/counter/i8254.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Intel 8254 Programmable Interval Timer 4 + * Copyright (C) William Breathitt Gray 5 + */ 6 + #include <linux/bitfield.h> 7 + #include <linux/bits.h> 8 + #include <linux/counter.h> 9 + #include <linux/device.h> 10 + #include <linux/err.h> 11 + #include <linux/export.h> 12 + #include <linux/i8254.h> 13 + #include <linux/limits.h> 14 + #include <linux/module.h> 15 + #include <linux/mutex.h> 16 + #include <linux/regmap.h> 17 + 18 + #include <asm/unaligned.h> 19 + 20 + #define I8254_COUNTER_REG(_counter) (_counter) 21 + #define I8254_CONTROL_REG 0x3 22 + 23 + #define I8254_SC GENMASK(7, 6) 24 + #define I8254_RW GENMASK(5, 4) 25 + #define I8254_M GENMASK(3, 1) 26 + #define I8254_CONTROL(_sc, _rw, _m) \ 27 + (u8_encode_bits(_sc, I8254_SC) | u8_encode_bits(_rw, I8254_RW) | \ 28 + u8_encode_bits(_m, I8254_M)) 29 + 30 + #define I8254_RW_TWO_BYTE 0x3 31 + #define I8254_MODE_INTERRUPT_ON_TERMINAL_COUNT 0 32 + #define I8254_MODE_HARDWARE_RETRIGGERABLE_ONESHOT 1 33 + #define I8254_MODE_RATE_GENERATOR 2 34 + #define I8254_MODE_SQUARE_WAVE_MODE 3 35 + #define I8254_MODE_SOFTWARE_TRIGGERED_STROBE 4 36 + #define I8254_MODE_HARDWARE_TRIGGERED_STROBE 5 37 + 38 + #define I8254_COUNTER_LATCH(_counter) I8254_CONTROL(_counter, 0x0, 0x0) 39 + #define I8254_PROGRAM_COUNTER(_counter, _mode) I8254_CONTROL(_counter, I8254_RW_TWO_BYTE, _mode) 40 + 41 + #define I8254_NUM_COUNTERS 3 42 + 43 + /** 44 + * struct i8254 - I8254 device private data structure 45 + * @lock: synchronization lock to prevent I/O race conditions 46 + * @preset: array of Counter Register states 47 + * @out_mode: array of mode configuration states 48 + * @map: Regmap for the device 49 + */ 50 + struct i8254 { 51 + struct mutex lock; 52 + u16 preset[I8254_NUM_COUNTERS]; 53 + u8 out_mode[I8254_NUM_COUNTERS]; 54 + struct regmap *map; 55 + }; 56 + 57 + static int i8254_count_read(struct counter_device *const counter, struct counter_count *const count, 58 + u64 *const val) 59 + { 60 + struct i8254 *const priv = counter_priv(counter); 61 + int ret; 62 + u8 value[2]; 63 + 64 + mutex_lock(&priv->lock); 65 + 66 + ret = regmap_write(priv->map, I8254_CONTROL_REG, I8254_COUNTER_LATCH(count->id)); 67 + if (ret) { 68 + mutex_unlock(&priv->lock); 69 + return ret; 70 + } 71 + ret = regmap_noinc_read(priv->map, I8254_COUNTER_REG(count->id), value, sizeof(value)); 72 + if (ret) { 73 + mutex_unlock(&priv->lock); 74 + return ret; 75 + } 76 + 77 + mutex_unlock(&priv->lock); 78 + 79 + *val = get_unaligned_le16(value); 80 + 81 + return ret; 82 + } 83 + 84 + static int i8254_function_read(struct counter_device *const counter, 85 + struct counter_count *const count, 86 + enum counter_function *const function) 87 + { 88 + *function = COUNTER_FUNCTION_DECREASE; 89 + return 0; 90 + } 91 + 92 + #define I8254_SYNAPSES_PER_COUNT 2 93 + #define I8254_SIGNAL_ID_CLK 0 94 + #define I8254_SIGNAL_ID_GATE 1 95 + 96 + static int i8254_action_read(struct counter_device *const counter, 97 + struct counter_count *const count, 98 + struct counter_synapse *const synapse, 99 + enum counter_synapse_action *const action) 100 + { 101 + struct i8254 *const priv = counter_priv(counter); 102 + 103 + switch (synapse->signal->id % I8254_SYNAPSES_PER_COUNT) { 104 + case I8254_SIGNAL_ID_CLK: 105 + *action = COUNTER_SYNAPSE_ACTION_FALLING_EDGE; 106 + return 0; 107 + case I8254_SIGNAL_ID_GATE: 108 + switch (priv->out_mode[count->id]) { 109 + case I8254_MODE_HARDWARE_RETRIGGERABLE_ONESHOT: 110 + case I8254_MODE_RATE_GENERATOR: 111 + case I8254_MODE_SQUARE_WAVE_MODE: 112 + case I8254_MODE_HARDWARE_TRIGGERED_STROBE: 113 + *action = COUNTER_SYNAPSE_ACTION_RISING_EDGE; 114 + return 0; 115 + default: 116 + *action = COUNTER_SYNAPSE_ACTION_NONE; 117 + return 0; 118 + } 119 + default: 120 + /* should never reach this path */ 121 + return -EINVAL; 122 + } 123 + } 124 + 125 + static int i8254_count_ceiling_read(struct counter_device *const counter, 126 + struct counter_count *const count, u64 *const ceiling) 127 + { 128 + struct i8254 *const priv = counter_priv(counter); 129 + 130 + mutex_lock(&priv->lock); 131 + 132 + switch (priv->out_mode[count->id]) { 133 + case I8254_MODE_RATE_GENERATOR: 134 + /* Rate Generator decrements 0 by one and the counter "wraps around" */ 135 + *ceiling = (priv->preset[count->id] == 0) ? U16_MAX : priv->preset[count->id]; 136 + break; 137 + case I8254_MODE_SQUARE_WAVE_MODE: 138 + if (priv->preset[count->id] % 2) 139 + *ceiling = priv->preset[count->id] - 1; 140 + else if (priv->preset[count->id] == 0) 141 + /* Square Wave Mode decrements 0 by two and the counter "wraps around" */ 142 + *ceiling = U16_MAX - 1; 143 + else 144 + *ceiling = priv->preset[count->id]; 145 + break; 146 + default: 147 + *ceiling = U16_MAX; 148 + break; 149 + } 150 + 151 + mutex_unlock(&priv->lock); 152 + 153 + return 0; 154 + } 155 + 156 + static int i8254_count_mode_read(struct counter_device *const counter, 157 + struct counter_count *const count, 158 + enum counter_count_mode *const count_mode) 159 + { 160 + const struct i8254 *const priv = counter_priv(counter); 161 + 162 + switch (priv->out_mode[count->id]) { 163 + case I8254_MODE_INTERRUPT_ON_TERMINAL_COUNT: 164 + *count_mode = COUNTER_COUNT_MODE_INTERRUPT_ON_TERMINAL_COUNT; 165 + return 0; 166 + case I8254_MODE_HARDWARE_RETRIGGERABLE_ONESHOT: 167 + *count_mode = COUNTER_COUNT_MODE_HARDWARE_RETRIGGERABLE_ONESHOT; 168 + return 0; 169 + case I8254_MODE_RATE_GENERATOR: 170 + *count_mode = COUNTER_COUNT_MODE_RATE_GENERATOR; 171 + return 0; 172 + case I8254_MODE_SQUARE_WAVE_MODE: 173 + *count_mode = COUNTER_COUNT_MODE_SQUARE_WAVE_MODE; 174 + return 0; 175 + case I8254_MODE_SOFTWARE_TRIGGERED_STROBE: 176 + *count_mode = COUNTER_COUNT_MODE_SOFTWARE_TRIGGERED_STROBE; 177 + return 0; 178 + case I8254_MODE_HARDWARE_TRIGGERED_STROBE: 179 + *count_mode = COUNTER_COUNT_MODE_HARDWARE_TRIGGERED_STROBE; 180 + return 0; 181 + default: 182 + /* should never reach this path */ 183 + return -EINVAL; 184 + } 185 + } 186 + 187 + static int i8254_count_mode_write(struct counter_device *const counter, 188 + struct counter_count *const count, 189 + const enum counter_count_mode count_mode) 190 + { 191 + struct i8254 *const priv = counter_priv(counter); 192 + u8 out_mode; 193 + int ret; 194 + 195 + switch (count_mode) { 196 + case COUNTER_COUNT_MODE_INTERRUPT_ON_TERMINAL_COUNT: 197 + out_mode = I8254_MODE_INTERRUPT_ON_TERMINAL_COUNT; 198 + break; 199 + case COUNTER_COUNT_MODE_HARDWARE_RETRIGGERABLE_ONESHOT: 200 + out_mode = I8254_MODE_HARDWARE_RETRIGGERABLE_ONESHOT; 201 + break; 202 + case COUNTER_COUNT_MODE_RATE_GENERATOR: 203 + out_mode = I8254_MODE_RATE_GENERATOR; 204 + break; 205 + case COUNTER_COUNT_MODE_SQUARE_WAVE_MODE: 206 + out_mode = I8254_MODE_SQUARE_WAVE_MODE; 207 + break; 208 + case COUNTER_COUNT_MODE_SOFTWARE_TRIGGERED_STROBE: 209 + out_mode = I8254_MODE_SOFTWARE_TRIGGERED_STROBE; 210 + break; 211 + case COUNTER_COUNT_MODE_HARDWARE_TRIGGERED_STROBE: 212 + out_mode = I8254_MODE_HARDWARE_TRIGGERED_STROBE; 213 + break; 214 + default: 215 + /* should never reach this path */ 216 + return -EINVAL; 217 + } 218 + 219 + mutex_lock(&priv->lock); 220 + 221 + /* Counter Register is cleared when the counter is programmed */ 222 + priv->preset[count->id] = 0; 223 + priv->out_mode[count->id] = out_mode; 224 + ret = regmap_write(priv->map, I8254_CONTROL_REG, 225 + I8254_PROGRAM_COUNTER(count->id, out_mode)); 226 + 227 + mutex_unlock(&priv->lock); 228 + 229 + return ret; 230 + } 231 + 232 + static int i8254_count_floor_read(struct counter_device *const counter, 233 + struct counter_count *const count, u64 *const floor) 234 + { 235 + struct i8254 *const priv = counter_priv(counter); 236 + 237 + mutex_lock(&priv->lock); 238 + 239 + switch (priv->out_mode[count->id]) { 240 + case I8254_MODE_RATE_GENERATOR: 241 + /* counter is always reloaded after 1, but 0 is a possible reload value */ 242 + *floor = (priv->preset[count->id] == 0) ? 0 : 1; 243 + break; 244 + case I8254_MODE_SQUARE_WAVE_MODE: 245 + /* counter is always reloaded after 2 for even preset values */ 246 + *floor = (priv->preset[count->id] % 2 || priv->preset[count->id] == 0) ? 0 : 2; 247 + break; 248 + default: 249 + *floor = 0; 250 + break; 251 + } 252 + 253 + mutex_unlock(&priv->lock); 254 + 255 + return 0; 256 + } 257 + 258 + static int i8254_count_preset_read(struct counter_device *const counter, 259 + struct counter_count *const count, u64 *const preset) 260 + { 261 + const struct i8254 *const priv = counter_priv(counter); 262 + 263 + *preset = priv->preset[count->id]; 264 + 265 + return 0; 266 + } 267 + 268 + static int i8254_count_preset_write(struct counter_device *const counter, 269 + struct counter_count *const count, const u64 preset) 270 + { 271 + struct i8254 *const priv = counter_priv(counter); 272 + int ret; 273 + u8 value[2]; 274 + 275 + if (preset > U16_MAX) 276 + return -ERANGE; 277 + 278 + mutex_lock(&priv->lock); 279 + 280 + if (priv->out_mode[count->id] == I8254_MODE_RATE_GENERATOR || 281 + priv->out_mode[count->id] == I8254_MODE_SQUARE_WAVE_MODE) { 282 + if (preset == 1) { 283 + mutex_unlock(&priv->lock); 284 + return -EINVAL; 285 + } 286 + } 287 + 288 + priv->preset[count->id] = preset; 289 + 290 + put_unaligned_le16(preset, value); 291 + ret = regmap_noinc_write(priv->map, I8254_COUNTER_REG(count->id), value, 2); 292 + 293 + mutex_unlock(&priv->lock); 294 + 295 + return ret; 296 + } 297 + 298 + static int i8254_init_hw(struct regmap *const map) 299 + { 300 + unsigned long i; 301 + int ret; 302 + 303 + for (i = 0; i < I8254_NUM_COUNTERS; i++) { 304 + /* Initialize each counter to Mode 0 */ 305 + ret = regmap_write(map, I8254_CONTROL_REG, 306 + I8254_PROGRAM_COUNTER(i, I8254_MODE_INTERRUPT_ON_TERMINAL_COUNT)); 307 + if (ret) 308 + return ret; 309 + } 310 + 311 + return 0; 312 + } 313 + 314 + static const struct counter_ops i8254_ops = { 315 + .count_read = i8254_count_read, 316 + .function_read = i8254_function_read, 317 + .action_read = i8254_action_read, 318 + }; 319 + 320 + #define I8254_SIGNAL(_id, _name) { \ 321 + .id = (_id), \ 322 + .name = (_name), \ 323 + } 324 + 325 + static struct counter_signal i8254_signals[] = { 326 + I8254_SIGNAL(0, "CLK 0"), I8254_SIGNAL(1, "GATE 0"), 327 + I8254_SIGNAL(2, "CLK 1"), I8254_SIGNAL(3, "GATE 1"), 328 + I8254_SIGNAL(4, "CLK 2"), I8254_SIGNAL(5, "GATE 2"), 329 + }; 330 + 331 + static const enum counter_synapse_action i8254_clk_actions[] = { 332 + COUNTER_SYNAPSE_ACTION_FALLING_EDGE, 333 + }; 334 + static const enum counter_synapse_action i8254_gate_actions[] = { 335 + COUNTER_SYNAPSE_ACTION_NONE, 336 + COUNTER_SYNAPSE_ACTION_RISING_EDGE, 337 + }; 338 + 339 + #define I8254_SYNAPSES_BASE(_id) ((_id) * I8254_SYNAPSES_PER_COUNT) 340 + #define I8254_SYNAPSE_CLK(_id) { \ 341 + .actions_list = i8254_clk_actions, \ 342 + .num_actions = ARRAY_SIZE(i8254_clk_actions), \ 343 + .signal = &i8254_signals[I8254_SYNAPSES_BASE(_id) + 0], \ 344 + } 345 + #define I8254_SYNAPSE_GATE(_id) { \ 346 + .actions_list = i8254_gate_actions, \ 347 + .num_actions = ARRAY_SIZE(i8254_gate_actions), \ 348 + .signal = &i8254_signals[I8254_SYNAPSES_BASE(_id) + 1], \ 349 + } 350 + 351 + static struct counter_synapse i8254_synapses[] = { 352 + I8254_SYNAPSE_CLK(0), I8254_SYNAPSE_GATE(0), 353 + I8254_SYNAPSE_CLK(1), I8254_SYNAPSE_GATE(1), 354 + I8254_SYNAPSE_CLK(2), I8254_SYNAPSE_GATE(2), 355 + }; 356 + 357 + static const enum counter_function i8254_functions_list[] = { 358 + COUNTER_FUNCTION_DECREASE, 359 + }; 360 + 361 + static const enum counter_count_mode i8254_count_modes[] = { 362 + COUNTER_COUNT_MODE_INTERRUPT_ON_TERMINAL_COUNT, 363 + COUNTER_COUNT_MODE_HARDWARE_RETRIGGERABLE_ONESHOT, 364 + COUNTER_COUNT_MODE_RATE_GENERATOR, 365 + COUNTER_COUNT_MODE_SQUARE_WAVE_MODE, 366 + COUNTER_COUNT_MODE_SOFTWARE_TRIGGERED_STROBE, 367 + COUNTER_COUNT_MODE_HARDWARE_TRIGGERED_STROBE, 368 + }; 369 + 370 + static DEFINE_COUNTER_AVAILABLE(i8254_count_modes_available, i8254_count_modes); 371 + 372 + static struct counter_comp i8254_count_ext[] = { 373 + COUNTER_COMP_CEILING(i8254_count_ceiling_read, NULL), 374 + COUNTER_COMP_COUNT_MODE(i8254_count_mode_read, i8254_count_mode_write, 375 + i8254_count_modes_available), 376 + COUNTER_COMP_FLOOR(i8254_count_floor_read, NULL), 377 + COUNTER_COMP_PRESET(i8254_count_preset_read, i8254_count_preset_write), 378 + }; 379 + 380 + #define I8254_COUNT(_id, _name) { \ 381 + .id = (_id), \ 382 + .name = (_name), \ 383 + .functions_list = i8254_functions_list, \ 384 + .num_functions = ARRAY_SIZE(i8254_functions_list), \ 385 + .synapses = &i8254_synapses[I8254_SYNAPSES_BASE(_id)], \ 386 + .num_synapses = I8254_SYNAPSES_PER_COUNT, \ 387 + .ext = i8254_count_ext, \ 388 + .num_ext = ARRAY_SIZE(i8254_count_ext) \ 389 + } 390 + 391 + static struct counter_count i8254_counts[I8254_NUM_COUNTERS] = { 392 + I8254_COUNT(0, "Counter 0"), I8254_COUNT(1, "Counter 1"), I8254_COUNT(2, "Counter 2"), 393 + }; 394 + 395 + /** 396 + * devm_i8254_regmap_register - Register an i8254 Counter device 397 + * @dev: device that is registering this i8254 Counter device 398 + * @config: configuration for i8254_regmap_config 399 + * 400 + * Registers an Intel 8254 Programmable Interval Timer Counter device. Returns 0 on success and 401 + * negative error number on failure. 402 + */ 403 + int devm_i8254_regmap_register(struct device *const dev, 404 + const struct i8254_regmap_config *const config) 405 + { 406 + struct counter_device *counter; 407 + struct i8254 *priv; 408 + int err; 409 + 410 + if (!config->parent) 411 + return -EINVAL; 412 + 413 + if (!config->map) 414 + return -EINVAL; 415 + 416 + counter = devm_counter_alloc(dev, sizeof(*priv)); 417 + if (!counter) 418 + return -ENOMEM; 419 + priv = counter_priv(counter); 420 + priv->map = config->map; 421 + 422 + counter->name = dev_name(config->parent); 423 + counter->parent = config->parent; 424 + counter->ops = &i8254_ops; 425 + counter->counts = i8254_counts; 426 + counter->num_counts = ARRAY_SIZE(i8254_counts); 427 + counter->signals = i8254_signals; 428 + counter->num_signals = ARRAY_SIZE(i8254_signals); 429 + 430 + mutex_init(&priv->lock); 431 + 432 + err = i8254_init_hw(priv->map); 433 + if (err) 434 + return err; 435 + 436 + err = devm_counter_add(dev, counter); 437 + if (err < 0) 438 + return dev_err_probe(dev, err, "Failed to add counter\n"); 439 + 440 + return 0; 441 + } 442 + EXPORT_SYMBOL_NS_GPL(devm_i8254_regmap_register, I8254); 443 + 444 + MODULE_AUTHOR("William Breathitt Gray"); 445 + MODULE_DESCRIPTION("Intel 8254 Programmable Interval Timer"); 446 + MODULE_LICENSE("GPL"); 447 + MODULE_IMPORT_NS(COUNTER);
+3
drivers/counter/stm32-timer-cnt.c
··· 342 342 343 343 platform_set_drvdata(pdev, priv); 344 344 345 + /* Reset input selector to its default input */ 346 + regmap_write(priv->regmap, TIM_TISEL, 0x0); 347 + 345 348 /* Register Counter device */ 346 349 ret = devm_counter_add(dev, counter); 347 350 if (ret < 0)
+21
include/linux/i8254.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* Copyright (C) William Breathitt Gray */ 3 + #ifndef _I8254_H_ 4 + #define _I8254_H_ 5 + 6 + struct device; 7 + struct regmap; 8 + 9 + /** 10 + * struct i8254_regmap_config - Configuration for the register map of an i8254 11 + * @parent: parent device 12 + * @map: regmap for the i8254 13 + */ 14 + struct i8254_regmap_config { 15 + struct device *parent; 16 + struct regmap *map; 17 + }; 18 + 19 + int devm_i8254_regmap_register(struct device *dev, const struct i8254_regmap_config *config); 20 + 21 + #endif /* _I8254_H_ */
+6
include/uapi/linux/counter.h
··· 127 127 COUNTER_COUNT_MODE_RANGE_LIMIT, 128 128 COUNTER_COUNT_MODE_NON_RECYCLE, 129 129 COUNTER_COUNT_MODE_MODULO_N, 130 + COUNTER_COUNT_MODE_INTERRUPT_ON_TERMINAL_COUNT, 131 + COUNTER_COUNT_MODE_HARDWARE_RETRIGGERABLE_ONESHOT, 132 + COUNTER_COUNT_MODE_RATE_GENERATOR, 133 + COUNTER_COUNT_MODE_SQUARE_WAVE_MODE, 134 + COUNTER_COUNT_MODE_SOFTWARE_TRIGGERED_STROBE, 135 + COUNTER_COUNT_MODE_HARDWARE_TRIGGERED_STROBE, 130 136 }; 131 137 132 138 /* Count function values */
+2
tools/counter/.gitignore
··· 1 + /counter_example 2 + /include/linux/counter.h
+1
tools/counter/Makefile
··· 40 40 clean: 41 41 rm -f $(ALL_PROGRAMS) 42 42 rm -rf $(OUTPUT)include/linux/counter.h 43 + rmdir -p $(OUTPUT)include/linux 43 44 find $(or $(OUTPUT),.) -name '*.o' -delete -o -name '\.*.d' -delete 44 45 45 46 install: $(ALL_PROGRAMS)