Lines Matching +full:quad +full:- +full:channel
1 // SPDX-License-Identifier: GPL-2.0
3 * Counter driver for the ACCES 104-QUAD-8
6 * This driver supports the ACCES 104-QUAD-8 and ACCES 104-QUAD-4.
28 MODULE_PARM_DESC(base, "ACCES 104-QUAD-8 base addresses");
33 MODULE_PARM_DESC(irq, "ACCES 104-QUAD-8 interrupt line numbers");
38 * struct channel_reg - channel register structure
40 * @control: Channel flags and control
48 * struct quad8_reg - device register structure
49 * @channel: quadrature counter data and control
50 * @interrupt_status: channel interrupt status
52 * @index_interrupt: enable channel interrupts
58 struct channel_reg channel[QUAD8_NUM_COUNTERS]; member
68 * struct quad8 - device private data structure
100 /* Borrow Toggle flip-flop */
102 /* Carry Toggle flip-flop */
144 if (signal->id < 16) in quad8_signal_read()
145 return -EINVAL; in quad8_signal_read()
147 state = ioread8(&priv->reg->index_input_levels) & BIT(signal->id - 16); in quad8_signal_read()
158 struct channel_reg __iomem *const chan = priv->reg->channel + count->id; in quad8_count_read()
165 flags = ioread8(&chan->control); in quad8_count_read()
172 spin_lock_irqsave(&priv->lock, irqflags); in quad8_count_read()
176 &chan->control); in quad8_count_read()
179 *val |= (unsigned long)ioread8(&chan->data) << (8 * i); in quad8_count_read()
181 spin_unlock_irqrestore(&priv->lock, irqflags); in quad8_count_read()
190 struct channel_reg __iomem *const chan = priv->reg->channel + count->id; in quad8_count_write()
194 /* Only 24-bit values are supported */ in quad8_count_write()
196 return -ERANGE; in quad8_count_write()
198 spin_lock_irqsave(&priv->lock, irqflags); in quad8_count_write()
201 iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control); in quad8_count_write()
205 iowrite8(val >> (8 * i), &chan->data); in quad8_count_write()
208 iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_PRESET_CNTR, &chan->control); in quad8_count_write()
211 iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control); in quad8_count_write()
214 val = priv->preset[count->id]; in quad8_count_write()
216 iowrite8(val >> (8 * i), &chan->data); in quad8_count_write()
219 iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_FLAGS, &chan->control); in quad8_count_write()
221 iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_E, &chan->control); in quad8_count_write()
223 spin_unlock_irqrestore(&priv->lock, irqflags); in quad8_count_write()
238 if (!priv->quadrature_mode[id]) { in quad8_function_get()
243 switch (priv->quadrature_scale[id]) { in quad8_function_get()
255 return -EINVAL; in quad8_function_get()
267 spin_lock_irqsave(&priv->lock, irqflags); in quad8_function_read()
269 retval = quad8_function_get(priv, count->id, function); in quad8_function_read()
271 spin_unlock_irqrestore(&priv->lock, irqflags); in quad8_function_read()
281 const int id = count->id; in quad8_function_write()
282 unsigned int *const quadrature_mode = priv->quadrature_mode + id; in quad8_function_write()
283 unsigned int *const scale = priv->quadrature_scale + id; in quad8_function_write()
284 unsigned int *const synchronous_mode = priv->synchronous_mode + id; in quad8_function_write()
285 u8 __iomem *const control = &priv->reg->channel[id].control; in quad8_function_write()
290 spin_lock_irqsave(&priv->lock, irqflags); in quad8_function_write()
292 mode_cfg = priv->count_mode[id] << 1; in quad8_function_write()
293 idr_cfg = priv->index_polarity[id] << 1; in quad8_function_write()
301 /* Synchronous function not supported in non-quadrature mode */ in quad8_function_write()
325 spin_unlock_irqrestore(&priv->lock, irqflags); in quad8_function_write()
326 return -EINVAL; in quad8_function_write()
333 spin_unlock_irqrestore(&priv->lock, irqflags); in quad8_function_write()
344 u8 __iomem *const flag_addr = &priv->reg->channel[count->id].control; in quad8_direction_read()
376 const size_t signal_a_id = count->synapses[0].signal->id; in quad8_action_read()
380 if (synapse->signal->id >= 16) { in quad8_action_read()
381 if (priv->preset_enable[count->id]) in quad8_action_read()
389 spin_lock_irqsave(&priv->lock, irqflags); in quad8_action_read()
392 err = quad8_function_get(priv, count->id, &function); in quad8_action_read()
394 spin_unlock_irqrestore(&priv->lock, irqflags); in quad8_action_read()
399 spin_unlock_irqrestore(&priv->lock, irqflags); in quad8_action_read()
403 spin_unlock_irqrestore(&priv->lock, irqflags); in quad8_action_read()
411 if (synapse->signal->id == signal_a_id) in quad8_action_read()
415 if (synapse->signal->id == signal_a_id) { in quad8_action_read()
423 if (synapse->signal->id == signal_a_id) in quad8_action_read()
431 return -EINVAL; in quad8_action_read()
451 spin_lock_irqsave(&priv->lock, irqflags); in quad8_events_configure()
453 list_for_each_entry(event_node, &counter->events_list, l) { in quad8_events_configure()
454 switch (event_node->event) { in quad8_events_configure()
469 spin_unlock_irqrestore(&priv->lock, irqflags); in quad8_events_configure()
470 return -EINVAL; in quad8_events_configure()
474 irq_enabled |= BIT(event_node->channel); in quad8_events_configure()
477 if (priv->irq_trigger[event_node->channel] == next_irq_trigger) in quad8_events_configure()
481 priv->irq_trigger[event_node->channel] = next_irq_trigger; in quad8_events_configure()
484 ior_cfg = priv->ab_enable[event_node->channel] | in quad8_events_configure()
485 priv->preset_enable[event_node->channel] << 1 | in quad8_events_configure()
486 priv->irq_trigger[event_node->channel] << 3; in quad8_events_configure()
488 &priv->reg->channel[event_node->channel].control); in quad8_events_configure()
491 iowrite8(irq_enabled, &priv->reg->index_interrupt); in quad8_events_configure()
493 spin_unlock_irqrestore(&priv->lock, irqflags); in quad8_events_configure()
503 if (watch->channel > QUAD8_NUM_COUNTERS - 1) in quad8_watch_validate()
504 return -EINVAL; in quad8_watch_validate()
506 switch (watch->event) { in quad8_watch_validate()
511 list_for_each_entry(event_node, &counter->next_events_list, l) in quad8_watch_validate()
512 if (watch->channel == event_node->channel && in quad8_watch_validate()
513 watch->event != event_node->event) in quad8_watch_validate()
514 return -EINVAL; in quad8_watch_validate()
517 return -EINVAL; in quad8_watch_validate()
542 const size_t channel_id = signal->id - 16; in quad8_index_polarity_get()
544 *index_polarity = priv->index_polarity[channel_id]; in quad8_index_polarity_get()
554 const size_t channel_id = signal->id - 16; in quad8_index_polarity_set()
555 u8 __iomem *const control = &priv->reg->channel[channel_id].control; in quad8_index_polarity_set()
559 spin_lock_irqsave(&priv->lock, irqflags); in quad8_index_polarity_set()
561 idr_cfg |= priv->synchronous_mode[channel_id]; in quad8_index_polarity_set()
563 priv->index_polarity[channel_id] = index_polarity; in quad8_index_polarity_set()
568 spin_unlock_irqrestore(&priv->lock, irqflags); in quad8_index_polarity_set()
600 "non-synchronous",
609 const size_t channel_id = signal->id - 16; in quad8_synchronous_mode_get()
611 *synchronous_mode = priv->synchronous_mode[channel_id]; in quad8_synchronous_mode_get()
621 const size_t channel_id = signal->id - 16; in quad8_synchronous_mode_set()
622 u8 __iomem *const control = &priv->reg->channel[channel_id].control; in quad8_synchronous_mode_set()
626 spin_lock_irqsave(&priv->lock, irqflags); in quad8_synchronous_mode_set()
628 idr_cfg |= priv->index_polarity[channel_id] << 1; in quad8_synchronous_mode_set()
630 /* Index function must be non-synchronous in non-quadrature mode */ in quad8_synchronous_mode_set()
631 if (synchronous_mode && !priv->quadrature_mode[channel_id]) { in quad8_synchronous_mode_set()
632 spin_unlock_irqrestore(&priv->lock, irqflags); in quad8_synchronous_mode_set()
633 return -EINVAL; in quad8_synchronous_mode_set()
636 priv->synchronous_mode[channel_id] = synchronous_mode; in quad8_synchronous_mode_set()
641 spin_unlock_irqrestore(&priv->lock, irqflags); in quad8_synchronous_mode_set()
661 /* Map 104-QUAD-8 count mode to Generic Counter count mode */ in quad8_count_mode_read()
662 switch (priv->count_mode[count->id]) { in quad8_count_mode_read()
687 u8 __iomem *const control = &priv->reg->channel[count->id].control; in quad8_count_mode_write()
690 /* Map Generic Counter count mode to 104-QUAD-8 count mode */ in quad8_count_mode_write()
706 return -EINVAL; in quad8_count_mode_write()
709 spin_lock_irqsave(&priv->lock, irqflags); in quad8_count_mode_write()
711 priv->count_mode[count->id] = count_mode; in quad8_count_mode_write()
717 if (priv->quadrature_mode[count->id]) in quad8_count_mode_write()
718 mode_cfg |= (priv->quadrature_scale[count->id] + 1) << 3; in quad8_count_mode_write()
723 spin_unlock_irqrestore(&priv->lock, irqflags); in quad8_count_mode_write()
733 *enable = priv->ab_enable[count->id]; in quad8_count_enable_read()
742 u8 __iomem *const control = &priv->reg->channel[count->id].control; in quad8_count_enable_write()
746 spin_lock_irqsave(&priv->lock, irqflags); in quad8_count_enable_write()
748 priv->ab_enable[count->id] = enable; in quad8_count_enable_write()
750 ior_cfg = enable | priv->preset_enable[count->id] << 1 | in quad8_count_enable_write()
751 priv->irq_trigger[count->id] << 3; in quad8_count_enable_write()
756 spin_unlock_irqrestore(&priv->lock, irqflags); in quad8_count_enable_write()
770 u8 __iomem *const flag_addr = &priv->reg->channel[count->id].control; in quad8_error_noise_get()
782 *preset = priv->preset[count->id]; in quad8_count_preset_read()
790 struct channel_reg __iomem *const chan = priv->reg->channel + id; in quad8_preset_register_set()
793 priv->preset[id] = preset; in quad8_preset_register_set()
796 iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control); in quad8_preset_register_set()
800 iowrite8(preset >> (8 * i), &chan->data); in quad8_preset_register_set()
809 /* Only 24-bit values are supported */ in quad8_count_preset_write()
811 return -ERANGE; in quad8_count_preset_write()
813 spin_lock_irqsave(&priv->lock, irqflags); in quad8_count_preset_write()
815 quad8_preset_register_set(priv, count->id, preset); in quad8_count_preset_write()
817 spin_unlock_irqrestore(&priv->lock, irqflags); in quad8_count_preset_write()
828 spin_lock_irqsave(&priv->lock, irqflags); in quad8_count_ceiling_read()
830 /* Range Limit and Modulo-N count modes use preset value as ceiling */ in quad8_count_ceiling_read()
831 switch (priv->count_mode[count->id]) { in quad8_count_ceiling_read()
834 *ceiling = priv->preset[count->id]; in quad8_count_ceiling_read()
842 spin_unlock_irqrestore(&priv->lock, irqflags); in quad8_count_ceiling_read()
853 /* Only 24-bit values are supported */ in quad8_count_ceiling_write()
855 return -ERANGE; in quad8_count_ceiling_write()
857 spin_lock_irqsave(&priv->lock, irqflags); in quad8_count_ceiling_write()
859 /* Range Limit and Modulo-N count modes use preset value as ceiling */ in quad8_count_ceiling_write()
860 switch (priv->count_mode[count->id]) { in quad8_count_ceiling_write()
863 quad8_preset_register_set(priv, count->id, ceiling); in quad8_count_ceiling_write()
864 spin_unlock_irqrestore(&priv->lock, irqflags); in quad8_count_ceiling_write()
868 spin_unlock_irqrestore(&priv->lock, irqflags); in quad8_count_ceiling_write()
870 return -EINVAL; in quad8_count_ceiling_write()
879 *preset_enable = !priv->preset_enable[count->id]; in quad8_count_preset_enable_read()
889 u8 __iomem *const control = &priv->reg->channel[count->id].control; in quad8_count_preset_enable_write()
896 spin_lock_irqsave(&priv->lock, irqflags); in quad8_count_preset_enable_write()
898 priv->preset_enable[count->id] = preset_enable; in quad8_count_preset_enable_write()
900 ior_cfg = priv->ab_enable[count->id] | preset_enable << 1 | in quad8_count_preset_enable_write()
901 priv->irq_trigger[count->id] << 3; in quad8_count_preset_enable_write()
906 spin_unlock_irqrestore(&priv->lock, irqflags); in quad8_count_preset_enable_write()
916 const size_t channel_id = signal->id / 2; in quad8_signal_cable_fault_read()
921 spin_lock_irqsave(&priv->lock, irqflags); in quad8_signal_cable_fault_read()
923 disabled = !(priv->cable_fault_enable & BIT(channel_id)); in quad8_signal_cable_fault_read()
926 spin_unlock_irqrestore(&priv->lock, irqflags); in quad8_signal_cable_fault_read()
927 return -EINVAL; in quad8_signal_cable_fault_read()
931 status = ioread8(&priv->reg->cable_status); in quad8_signal_cable_fault_read()
933 spin_unlock_irqrestore(&priv->lock, irqflags); in quad8_signal_cable_fault_read()
935 /* Mask respective channel and invert logic */ in quad8_signal_cable_fault_read()
946 const size_t channel_id = signal->id / 2; in quad8_signal_cable_fault_enable_read()
948 *enable = !!(priv->cable_fault_enable & BIT(channel_id)); in quad8_signal_cable_fault_enable_read()
958 const size_t channel_id = signal->id / 2; in quad8_signal_cable_fault_enable_write()
962 spin_lock_irqsave(&priv->lock, irqflags); in quad8_signal_cable_fault_enable_write()
965 priv->cable_fault_enable |= BIT(channel_id); in quad8_signal_cable_fault_enable_write()
967 priv->cable_fault_enable &= ~BIT(channel_id); in quad8_signal_cable_fault_enable_write()
970 cable_fault_enable = ~priv->cable_fault_enable; in quad8_signal_cable_fault_enable_write()
972 iowrite8(cable_fault_enable, &priv->reg->cable_status); in quad8_signal_cable_fault_enable_write()
974 spin_unlock_irqrestore(&priv->lock, irqflags); in quad8_signal_cable_fault_enable_write()
985 *prescaler = priv->fck_prescaler[signal->id / 2]; in quad8_signal_fck_prescaler_read()
995 const size_t channel_id = signal->id / 2; in quad8_signal_fck_prescaler_write()
996 struct channel_reg __iomem *const chan = priv->reg->channel + channel_id; in quad8_signal_fck_prescaler_write()
999 spin_lock_irqsave(&priv->lock, irqflags); in quad8_signal_fck_prescaler_write()
1001 priv->fck_prescaler[channel_id] = prescaler; in quad8_signal_fck_prescaler_write()
1004 iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control); in quad8_signal_fck_prescaler_write()
1007 iowrite8(prescaler, &chan->data); in quad8_signal_fck_prescaler_write()
1009 &chan->control); in quad8_signal_fck_prescaler_write()
1011 spin_unlock_irqrestore(&priv->lock, irqflags); in quad8_signal_fck_prescaler_write()
1063 QUAD8_QUAD_SIGNAL(0, "Channel 1 Quadrature A"),
1064 QUAD8_QUAD_SIGNAL(1, "Channel 1 Quadrature B"),
1065 QUAD8_QUAD_SIGNAL(2, "Channel 2 Quadrature A"),
1066 QUAD8_QUAD_SIGNAL(3, "Channel 2 Quadrature B"),
1067 QUAD8_QUAD_SIGNAL(4, "Channel 3 Quadrature A"),
1068 QUAD8_QUAD_SIGNAL(5, "Channel 3 Quadrature B"),
1069 QUAD8_QUAD_SIGNAL(6, "Channel 4 Quadrature A"),
1070 QUAD8_QUAD_SIGNAL(7, "Channel 4 Quadrature B"),
1071 QUAD8_QUAD_SIGNAL(8, "Channel 5 Quadrature A"),
1072 QUAD8_QUAD_SIGNAL(9, "Channel 5 Quadrature B"),
1073 QUAD8_QUAD_SIGNAL(10, "Channel 6 Quadrature A"),
1074 QUAD8_QUAD_SIGNAL(11, "Channel 6 Quadrature B"),
1075 QUAD8_QUAD_SIGNAL(12, "Channel 7 Quadrature A"),
1076 QUAD8_QUAD_SIGNAL(13, "Channel 7 Quadrature B"),
1077 QUAD8_QUAD_SIGNAL(14, "Channel 8 Quadrature A"),
1078 QUAD8_QUAD_SIGNAL(15, "Channel 8 Quadrature B"),
1079 QUAD8_INDEX_SIGNAL(16, "Channel 1 Index"),
1080 QUAD8_INDEX_SIGNAL(17, "Channel 2 Index"),
1081 QUAD8_INDEX_SIGNAL(18, "Channel 3 Index"),
1082 QUAD8_INDEX_SIGNAL(19, "Channel 4 Index"),
1083 QUAD8_INDEX_SIGNAL(20, "Channel 5 Index"),
1084 QUAD8_INDEX_SIGNAL(21, "Channel 6 Index"),
1085 QUAD8_INDEX_SIGNAL(22, "Channel 7 Index"),
1086 QUAD8_INDEX_SIGNAL(23, "Channel 8 Index")
1152 QUAD8_COUNT(0, "Channel 1 Count"),
1153 QUAD8_COUNT(1, "Channel 2 Count"),
1154 QUAD8_COUNT(2, "Channel 3 Count"),
1155 QUAD8_COUNT(3, "Channel 4 Count"),
1156 QUAD8_COUNT(4, "Channel 5 Count"),
1157 QUAD8_COUNT(5, "Channel 6 Count"),
1158 QUAD8_COUNT(6, "Channel 7 Count"),
1159 QUAD8_COUNT(7, "Channel 8 Count")
1167 unsigned long channel; in quad8_irq_handler() local
1170 irq_status = ioread8(&priv->reg->interrupt_status); in quad8_irq_handler()
1174 for_each_set_bit(channel, &irq_status, QUAD8_NUM_COUNTERS) { in quad8_irq_handler()
1175 switch (priv->irq_trigger[channel]) { in quad8_irq_handler()
1190 WARN_ONCE(true, "invalid interrupt trigger function %u configured for channel %lu\n", in quad8_irq_handler()
1191 priv->irq_trigger[channel], channel); in quad8_irq_handler()
1195 counter_push_event(counter, event, channel); in quad8_irq_handler()
1199 iowrite8(QUAD8_CHAN_OP_ENABLE_INTERRUPT_FUNC, &priv->reg->channel_oper); in quad8_irq_handler()
1209 iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control); in quad8_init_counter()
1211 iowrite8(0, &chan->data); in quad8_init_counter()
1213 &chan->control); in quad8_init_counter()
1215 iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_BP, &chan->control); in quad8_init_counter()
1218 iowrite8(0x00, &chan->data); in quad8_init_counter()
1220 iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_FLAGS, &chan->control); in quad8_init_counter()
1222 iowrite8(QUAD8_CTR_RLD | QUAD8_RLD_RESET_E, &chan->control); in quad8_init_counter()
1223 /* Binary encoding; Normal count; non-quadrature mode */ in quad8_init_counter()
1224 iowrite8(QUAD8_CTR_CMR, &chan->control); in quad8_init_counter()
1226 iowrite8(QUAD8_CTR_IOR, &chan->control); in quad8_init_counter()
1228 iowrite8(QUAD8_CTR_IDR, &chan->control); in quad8_init_counter()
1239 dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n", in quad8_probe()
1241 return -EBUSY; in quad8_probe()
1246 return -ENOMEM; in quad8_probe()
1249 priv->reg = devm_ioport_map(dev, base[id], QUAD8_EXTENT); in quad8_probe()
1250 if (!priv->reg) in quad8_probe()
1251 return -ENOMEM; in quad8_probe()
1254 counter->name = dev_name(dev); in quad8_probe()
1255 counter->parent = dev; in quad8_probe()
1256 counter->ops = &quad8_ops; in quad8_probe()
1257 counter->counts = quad8_counts; in quad8_probe()
1258 counter->num_counts = ARRAY_SIZE(quad8_counts); in quad8_probe()
1259 counter->signals = quad8_signals; in quad8_probe()
1260 counter->num_signals = ARRAY_SIZE(quad8_signals); in quad8_probe()
1262 spin_lock_init(&priv->lock); in quad8_probe()
1265 iowrite8(0x00, &priv->reg->index_interrupt); in quad8_probe()
1267 iowrite8(QUAD8_CHAN_OP_RESET_COUNTERS, &priv->reg->channel_oper); in quad8_probe()
1270 quad8_init_counter(priv->reg->channel + i); in quad8_probe()
1272 iowrite8(0xFF, &priv->reg->cable_status); in quad8_probe()
1274 iowrite8(QUAD8_CHAN_OP_ENABLE_INTERRUPT_FUNC, &priv->reg->channel_oper); in quad8_probe()
1276 err = devm_request_irq(&counter->dev, irq[id], quad8_irq_handler, in quad8_probe()
1277 IRQF_SHARED, counter->name, counter); in quad8_probe()
1291 .name = "104-quad-8"
1298 MODULE_DESCRIPTION("ACCES 104-QUAD-8 driver");