Lines Matching +full:ext +full:- +full:irq +full:- +full:range
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.
32 MODULE_PARM_DESC(base, "ACCES 104-QUAD-8 base addresses");
34 static unsigned int irq[max_num_isa_dev(QUAD8_EXTENT)]; variable
36 module_param_hw_array(irq, uint, irq, &num_irq, 0);
37 MODULE_PARM_DESC(irq, "ACCES 104-QUAD-8 interrupt line numbers");
50 * struct quad8 - device private data structure
140 /* Range Limit */
142 /* Non-recycle count */
144 /* Modulo-N */
146 /* Non-quadrature */
223 if (signal->id < 16) in quad8_signal_read()
224 return -EINVAL; in quad8_signal_read()
226 ret = regmap_test_bits(priv->map, QUAD8_INDEX_INPUT_LEVELS, BIT(signal->id - 16)); in quad8_signal_read()
243 spin_lock_irqsave(&priv->lock, irqflags); in quad8_count_read()
245 ret = regmap_write(priv->map, QUAD8_CONTROL(count->id), in quad8_count_read()
249 ret = regmap_noinc_read(priv->map, QUAD8_DATA(count->id), value, sizeof(value)); in quad8_count_read()
252 spin_unlock_irqrestore(&priv->lock, irqflags); in quad8_count_read()
267 ret = regmap_write(priv->map, QUAD8_CONTROL(id), SELECT_RLD | RESET_BP); in quad8_preset_register_set()
270 return regmap_noinc_write(priv->map, QUAD8_DATA(id), value, sizeof(value)); in quad8_preset_register_set()
277 ret = regmap_write(priv->map, QUAD8_CONTROL(id), SELECT_RLD | RESET_BT_CT_CPT_S_IDX); in quad8_flag_register_reset()
280 return regmap_write(priv->map, QUAD8_CONTROL(id), SELECT_RLD | RESET_E); in quad8_flag_register_reset()
291 return -ERANGE; in quad8_count_write()
293 spin_lock_irqsave(&priv->lock, irqflags); in quad8_count_write()
296 ret = quad8_preset_register_set(priv, count->id, val); in quad8_count_write()
299 ret = regmap_write(priv->map, QUAD8_CONTROL(count->id), SELECT_RLD | TRANSFER_PR_TO_CNTR); in quad8_count_write()
303 ret = quad8_flag_register_reset(priv, count->id); in quad8_count_write()
308 ret = quad8_preset_register_set(priv, count->id, priv->preset[count->id]); in quad8_count_write()
311 spin_unlock_irqrestore(&priv->lock, irqflags); in quad8_count_write()
326 switch (u8_get_bits(priv->cmr[id], QUADRATURE_MODE)) { in quad8_function_get()
341 return -EINVAL; in quad8_function_get()
353 spin_lock_irqsave(&priv->lock, irqflags); in quad8_function_read()
355 retval = quad8_function_get(priv, count->id, function); in quad8_function_read()
357 spin_unlock_irqrestore(&priv->lock, irqflags); in quad8_function_read()
367 const int id = count->id; in quad8_function_write()
388 return -EINVAL; in quad8_function_write()
391 spin_lock_irqsave(&priv->lock, irqflags); in quad8_function_write()
393 /* Synchronous function not supported in non-quadrature mode */ in quad8_function_write()
394 synchronous_mode = u8_get_bits(priv->idr[id], INDEX_MODE) == ENABLE_INDEX_MODE; in quad8_function_write()
396 ret = quad8_control_register_update(priv->map, priv->idr, id, DISABLE_INDEX_MODE, in quad8_function_write()
402 ret = quad8_control_register_update(priv->map, priv->cmr, id, mode_cfg, QUADRATURE_MODE); in quad8_function_write()
405 spin_unlock_irqrestore(&priv->lock, irqflags); in quad8_function_write()
418 ret = regmap_read(priv->map, QUAD8_CONTROL(count->id), &flag); in quad8_direction_read()
448 const size_t signal_a_id = count->synapses[0].signal->id; in quad8_action_read()
455 if (synapse->signal->id >= 16) { in quad8_action_read()
456 if (u8_get_bits(priv->ior[count->id], LOAD_PIN) == LOAD_CNTR) in quad8_action_read()
461 spin_lock_irqsave(&priv->lock, irqflags); in quad8_action_read()
464 err = quad8_function_get(priv, count->id, &function); in quad8_action_read()
466 spin_unlock_irqrestore(&priv->lock, irqflags); in quad8_action_read()
471 spin_unlock_irqrestore(&priv->lock, irqflags); in quad8_action_read()
475 spin_unlock_irqrestore(&priv->lock, irqflags); in quad8_action_read()
480 if (synapse->signal->id == signal_a_id) in quad8_action_read()
484 if (synapse->signal->id == signal_a_id) { in quad8_action_read()
492 if (synapse->signal->id == signal_a_id) in quad8_action_read()
500 return -EINVAL; in quad8_action_read()
513 spin_lock_irqsave(&priv->lock, irqflags); in quad8_events_configure()
515 list_for_each_entry(event_node, &counter->events_list, l) { in quad8_events_configure()
516 switch (event_node->event) { in quad8_events_configure()
531 ret = -EINVAL; in quad8_events_configure()
535 /* Enable IRQ line */ in quad8_events_configure()
536 irq_enabled |= BIT(event_node->channel); in quad8_events_configure()
539 if (flg_pins == u8_get_bits(priv->ior[event_node->channel], FLG_PINS)) in quad8_events_configure()
542 /* Save new IRQ function configuration */ in quad8_events_configure()
543 ret = quad8_control_register_update(priv->map, priv->ior, event_node->channel, in quad8_events_configure()
549 ret = regmap_write(priv->map, QUAD8_INDEX_INTERRUPT, irq_enabled); in quad8_events_configure()
552 spin_unlock_irqrestore(&priv->lock, irqflags); in quad8_events_configure()
562 if (watch->channel > QUAD8_NUM_COUNTERS - 1) in quad8_watch_validate()
563 return -EINVAL; in quad8_watch_validate()
565 switch (watch->event) { in quad8_watch_validate()
570 list_for_each_entry(event_node, &counter->next_events_list, l) in quad8_watch_validate()
571 if (watch->channel == event_node->channel && in quad8_watch_validate()
572 watch->event != event_node->event) in quad8_watch_validate()
573 return -EINVAL; in quad8_watch_validate()
576 return -EINVAL; in quad8_watch_validate()
601 const size_t channel_id = signal->id - 16; in quad8_index_polarity_get()
603 *index_polarity = u8_get_bits(priv->idr[channel_id], INDEX_POLARITY); in quad8_index_polarity_get()
613 const size_t channel_id = signal->id - 16; in quad8_index_polarity_set()
617 spin_lock_irqsave(&priv->lock, irqflags); in quad8_index_polarity_set()
619 ret = quad8_control_register_update(priv->map, priv->idr, channel_id, index_polarity, in quad8_index_polarity_set()
622 spin_unlock_irqrestore(&priv->lock, irqflags); in quad8_index_polarity_set()
655 "non-synchronous",
664 const size_t channel_id = signal->id - 16; in quad8_synchronous_mode_get()
666 *synchronous_mode = u8_get_bits(priv->idr[channel_id], INDEX_MODE); in quad8_synchronous_mode_get()
676 const size_t channel_id = signal->id - 16; in quad8_synchronous_mode_set()
681 spin_lock_irqsave(&priv->lock, irqflags); in quad8_synchronous_mode_set()
683 /* Index function must be non-synchronous in non-quadrature mode */ in quad8_synchronous_mode_set()
684 quadrature_mode = u8_get_bits(priv->idr[channel_id], QUADRATURE_MODE); in quad8_synchronous_mode_set()
686 ret = -EINVAL; in quad8_synchronous_mode_set()
690 ret = quad8_control_register_update(priv->map, priv->idr, channel_id, synchronous_mode, in quad8_synchronous_mode_set()
694 spin_unlock_irqrestore(&priv->lock, irqflags); in quad8_synchronous_mode_set()
714 switch (u8_get_bits(priv->cmr[count->id], COUNT_MODE)) { in quad8_count_mode_read()
756 return -EINVAL; in quad8_count_mode_write()
759 spin_lock_irqsave(&priv->lock, irqflags); in quad8_count_mode_write()
761 ret = quad8_control_register_update(priv->map, priv->cmr, count->id, count_mode, in quad8_count_mode_write()
764 spin_unlock_irqrestore(&priv->lock, irqflags); in quad8_count_mode_write()
774 *enable = u8_get_bits(priv->ior[count->id], AB_GATE); in quad8_count_enable_read()
786 spin_lock_irqsave(&priv->lock, irqflags); in quad8_count_enable_write()
788 ret = quad8_control_register_update(priv->map, priv->ior, count->id, enable, AB_GATE); in quad8_count_enable_write()
790 spin_unlock_irqrestore(&priv->lock, irqflags); in quad8_count_enable_write()
807 ret = regmap_read(priv->map, QUAD8_CONTROL(count->id), &flag); in quad8_error_noise_get()
820 *preset = priv->preset[count->id]; in quad8_count_preset_read()
833 return -ERANGE; in quad8_count_preset_write()
835 spin_lock_irqsave(&priv->lock, irqflags); in quad8_count_preset_write()
837 priv->preset[count->id] = preset; in quad8_count_preset_write()
838 ret = quad8_preset_register_set(priv, count->id, preset); in quad8_count_preset_write()
840 spin_unlock_irqrestore(&priv->lock, irqflags); in quad8_count_preset_write()
851 spin_lock_irqsave(&priv->lock, irqflags); in quad8_count_ceiling_read()
853 /* Range Limit and Modulo-N count modes use preset value as ceiling */ in quad8_count_ceiling_read()
854 switch (u8_get_bits(priv->cmr[count->id], COUNT_MODE)) { in quad8_count_ceiling_read()
857 *ceiling = priv->preset[count->id]; in quad8_count_ceiling_read()
864 spin_unlock_irqrestore(&priv->lock, irqflags); in quad8_count_ceiling_read()
877 return -ERANGE; in quad8_count_ceiling_write()
879 spin_lock_irqsave(&priv->lock, irqflags); in quad8_count_ceiling_write()
881 /* Range Limit and Modulo-N count modes use preset value as ceiling */ in quad8_count_ceiling_write()
882 switch (u8_get_bits(priv->cmr[count->id], COUNT_MODE)) { in quad8_count_ceiling_write()
885 priv->preset[count->id] = ceiling; in quad8_count_ceiling_write()
886 ret = quad8_preset_register_set(priv, count->id, ceiling); in quad8_count_ceiling_write()
889 ret = -EINVAL; in quad8_count_ceiling_write()
893 spin_unlock_irqrestore(&priv->lock, irqflags); in quad8_count_ceiling_write()
905 *preset_enable = !u8_get_bits(priv->ior[count->id], LOAD_PIN); in quad8_count_preset_enable_read()
918 spin_lock_irqsave(&priv->lock, irqflags); in quad8_count_preset_enable_write()
921 ret = quad8_control_register_update(priv->map, priv->ior, count->id, !preset_enable, in quad8_count_preset_enable_write()
924 spin_unlock_irqrestore(&priv->lock, irqflags); in quad8_count_preset_enable_write()
934 const size_t channel_id = signal->id / 2; in quad8_signal_cable_fault_read()
939 spin_lock_irqsave(&priv->lock, irqflags); in quad8_signal_cable_fault_read()
941 disabled = !(priv->cable_fault_enable & BIT(channel_id)); in quad8_signal_cable_fault_read()
944 spin_unlock_irqrestore(&priv->lock, irqflags); in quad8_signal_cable_fault_read()
945 return -EINVAL; in quad8_signal_cable_fault_read()
948 ret = regmap_test_bits(priv->map, QUAD8_CABLE_STATUS, BIT(channel_id)); in quad8_signal_cable_fault_read()
950 spin_unlock_irqrestore(&priv->lock, irqflags); in quad8_signal_cable_fault_read()
954 spin_unlock_irqrestore(&priv->lock, irqflags); in quad8_signal_cable_fault_read()
967 const size_t channel_id = signal->id / 2; in quad8_signal_cable_fault_enable_read()
969 *enable = !!(priv->cable_fault_enable & BIT(channel_id)); in quad8_signal_cable_fault_enable_read()
979 const size_t channel_id = signal->id / 2; in quad8_signal_cable_fault_enable_write()
984 spin_lock_irqsave(&priv->lock, irqflags); in quad8_signal_cable_fault_enable_write()
987 priv->cable_fault_enable |= BIT(channel_id); in quad8_signal_cable_fault_enable_write()
989 priv->cable_fault_enable &= ~BIT(channel_id); in quad8_signal_cable_fault_enable_write()
992 cable_fault_enable = ~priv->cable_fault_enable; in quad8_signal_cable_fault_enable_write()
994 ret = regmap_write(priv->map, QUAD8_CABLE_STATUS, cable_fault_enable); in quad8_signal_cable_fault_enable_write()
996 spin_unlock_irqrestore(&priv->lock, irqflags); in quad8_signal_cable_fault_enable_write()
1007 *prescaler = priv->fck_prescaler[signal->id / 2]; in quad8_signal_fck_prescaler_read()
1017 ret = regmap_write(priv->map, QUAD8_CONTROL(id), SELECT_RLD | RESET_BP); in quad8_filter_clock_prescaler_set()
1020 ret = regmap_write(priv->map, QUAD8_DATA(id), prescaler); in quad8_filter_clock_prescaler_set()
1023 return regmap_write(priv->map, QUAD8_CONTROL(id), SELECT_RLD | TRANSFER_PR0_TO_PSC); in quad8_filter_clock_prescaler_set()
1031 const size_t channel_id = signal->id / 2; in quad8_signal_fck_prescaler_write()
1035 spin_lock_irqsave(&priv->lock, irqflags); in quad8_signal_fck_prescaler_write()
1037 priv->fck_prescaler[channel_id] = prescaler; in quad8_signal_fck_prescaler_write()
1040 spin_unlock_irqrestore(&priv->lock, irqflags); in quad8_signal_fck_prescaler_write()
1080 .ext = quad8_signal_ext, \
1087 .ext = quad8_index_ext, \
1176 .ext = quad8_count_ext, \
1191 static irqreturn_t quad8_irq_handler(int irq, void *private) in quad8_irq_handler() argument
1202 ret = regmap_read(priv->map, QUAD8_INTERRUPT_STATUS, &status); in quad8_irq_handler()
1210 flg_pins = u8_get_bits(priv->ior[channel], FLG_PINS); in quad8_irq_handler()
1234 ret = regmap_write(priv->map, QUAD8_CHANNEL_OPERATION, CLEAR_PENDING_INTERRUPTS); in quad8_irq_handler()
1255 /* Binary encoding; Normal count; non-quadrature mode */ in quad8_init_counter()
1256 priv->cmr[channel] = SELECT_CMR | BINARY | u8_encode_bits(NORMAL_COUNT, COUNT_MODE) | in quad8_init_counter()
1258 ret = regmap_write(priv->map, QUAD8_CONTROL(channel), priv->cmr[channel]); in quad8_init_counter()
1263 priv->ior[channel] = SELECT_IOR | DISABLE_AB | u8_encode_bits(LOAD_CNTR, LOAD_PIN) | in quad8_init_counter()
1265 ret = regmap_write(priv->map, QUAD8_CONTROL(channel), priv->ior[channel]); in quad8_init_counter()
1270 priv->idr[channel] = SELECT_IDR | u8_encode_bits(DISABLE_INDEX_MODE, INDEX_MODE) | in quad8_init_counter()
1272 return regmap_write(priv->map, QUAD8_CONTROL(channel), priv->idr[channel]); in quad8_init_counter()
1284 dev_err(dev, "Unable to lock port addresses (0x%X-0x%X)\n", in quad8_probe()
1286 return -EBUSY; in quad8_probe()
1291 return -ENOMEM; in quad8_probe()
1296 return -ENOMEM; in quad8_probe()
1298 priv->map = devm_regmap_init_mmio(dev, regs, &quad8_regmap_config); in quad8_probe()
1299 if (IS_ERR(priv->map)) in quad8_probe()
1300 return dev_err_probe(dev, PTR_ERR(priv->map), in quad8_probe()
1304 counter->name = dev_name(dev); in quad8_probe()
1305 counter->parent = dev; in quad8_probe()
1306 counter->ops = &quad8_ops; in quad8_probe()
1307 counter->counts = quad8_counts; in quad8_probe()
1308 counter->num_counts = ARRAY_SIZE(quad8_counts); in quad8_probe()
1309 counter->signals = quad8_signals; in quad8_probe()
1310 counter->num_signals = ARRAY_SIZE(quad8_signals); in quad8_probe()
1312 spin_lock_init(&priv->lock); in quad8_probe()
1315 ret = regmap_write(priv->map, QUAD8_INDEX_INTERRUPT, 0x00); in quad8_probe()
1319 ret = regmap_write(priv->map, QUAD8_CHANNEL_OPERATION, in quad8_probe()
1330 ret = regmap_write(priv->map, QUAD8_CABLE_STATUS, GENMASK(7, 0)); in quad8_probe()
1334 ret = regmap_write(priv->map, QUAD8_CHANNEL_OPERATION, in quad8_probe()
1339 ret = devm_request_irq(&counter->dev, irq[id], quad8_irq_handler, in quad8_probe()
1340 IRQF_SHARED, counter->name, counter); in quad8_probe()
1354 .name = "104-quad-8"
1361 MODULE_DESCRIPTION("ACCES 104-QUAD-8 driver");