static void ni_tio_set_sync_mode(struct ni_gpct *counter, int force_alt_sync) { struct ni_gpct_device *counter_dev = counter->counter_dev; const unsigned counting_mode_reg = NITIO_Gi_Counting_Mode_Reg(counter->counter_index); static const uint64_t min_normal_sync_period_ps = 25000; const uint64_t clock_period_ps = ni_tio_clock_period_ps(counter, ni_tio_generic_clock_src_select (counter)); if (ni_tio_counting_mode_registers_present(counter_dev) == 0) return; switch (ni_tio_get_soft_copy(counter, counting_mode_reg) & Gi_Counting_Mode_Mask) { case Gi_Counting_Mode_QuadratureX1_Bits: case Gi_Counting_Mode_QuadratureX2_Bits: case Gi_Counting_Mode_QuadratureX4_Bits: case Gi_Counting_Mode_Sync_Source_Bits: force_alt_sync = 1; break; default: break; } if (force_alt_sync || (clock_period_ps && clock_period_ps < min_normal_sync_period_ps)) { ni_tio_set_bits(counter, counting_mode_reg, Gi_Alternate_Sync_Bit(counter_dev->variant), Gi_Alternate_Sync_Bit(counter_dev->variant)); } else { ni_tio_set_bits(counter, counting_mode_reg, Gi_Alternate_Sync_Bit(counter_dev->variant), 0x0); } }
static void ni_tio_set_first_gate_modifiers(struct ni_gpct *counter, unsigned int gate_source) { const unsigned mode_mask = Gi_Gate_Polarity_Bit | Gi_Gating_Mode_Mask; unsigned mode_values = 0; if (gate_source & CR_INVERT) mode_values |= Gi_Gate_Polarity_Bit; if (gate_source & CR_EDGE) mode_values |= Gi_Rising_Edge_Gating_Bits; else mode_values |= Gi_Level_Gating_Bits; ni_tio_set_bits(counter, NITIO_Gi_Mode_Reg(counter->counter_index), mode_mask, mode_values); }
static int ni_m_series_set_first_gate(struct ni_gpct *counter, lsampl_t gate_source) { const unsigned selected_gate = CR_CHAN(gate_source); /* bits of selected_gate that may be meaningful to input select register */ const unsigned selected_gate_mask = 0x1f; unsigned ni_m_series_gate_select; unsigned i; switch (selected_gate) { case NI_GPCT_TIMESTAMP_MUX_GATE_SELECT: case NI_GPCT_AI_START2_GATE_SELECT: case NI_GPCT_PXI_STAR_TRIGGER_GATE_SELECT: case NI_GPCT_NEXT_OUT_GATE_SELECT: case NI_GPCT_AI_START1_GATE_SELECT: case NI_GPCT_NEXT_SOURCE_GATE_SELECT: case NI_GPCT_ANALOG_TRIGGER_OUT_GATE_SELECT: case NI_GPCT_LOGIC_LOW_GATE_SELECT: ni_m_series_gate_select = selected_gate & selected_gate_mask; break; default: for (i = 0; i <= ni_m_series_max_rtsi_channel; ++i) { if (selected_gate == NI_GPCT_RTSI_GATE_SELECT(i)) { ni_m_series_gate_select = selected_gate & selected_gate_mask; break; } } if (i <= ni_m_series_max_rtsi_channel) break; for (i = 0; i <= ni_m_series_max_pfi_channel; ++i) { if (selected_gate == NI_GPCT_PFI_GATE_SELECT(i)) { ni_m_series_gate_select = selected_gate & selected_gate_mask; break; } } if (i <= ni_m_series_max_pfi_channel) break; return -EINVAL; break; } ni_tio_set_bits(counter, NITIO_Gi_Input_Select_Reg(counter->counter_index), Gi_Gate_Select_Mask, Gi_Gate_Select_Bits(ni_m_series_gate_select)); return 0; }
static int ni_tio_input_cmd(struct ni_gpct *counter, struct comedi_async *async) { struct ni_gpct_device *counter_dev = counter->counter_dev; unsigned cidx = counter->counter_index; struct comedi_cmd *cmd = &async->cmd; int retval = 0; /* write alloc the entire buffer */ comedi_buf_write_alloc(async, async->prealloc_bufsz); counter->mite_chan->dir = COMEDI_INPUT; switch (counter_dev->variant) { case ni_gpct_variant_m_series: case ni_gpct_variant_660x: mite_prep_dma(counter->mite_chan, 32, 32); break; case ni_gpct_variant_e_series: mite_prep_dma(counter->mite_chan, 16, 32); break; default: BUG(); break; } ni_tio_set_bits(counter, NITIO_CMD_REG(cidx), Gi_Save_Trace_Bit, 0); ni_tio_configure_dma(counter, 1, 1); switch (cmd->start_src) { case TRIG_NOW: async->inttrig = NULL; mite_dma_arm(counter->mite_chan); retval = ni_tio_arm(counter, 1, NI_GPCT_ARM_IMMEDIATE); break; case TRIG_INT: async->inttrig = &ni_tio_input_inttrig; break; case TRIG_EXT: async->inttrig = NULL; mite_dma_arm(counter->mite_chan); retval = ni_tio_arm(counter, 1, cmd->start_arg); break; case TRIG_OTHER: async->inttrig = NULL; mite_dma_arm(counter->mite_chan); break; default: BUG(); break; } return retval; }
int ni_tio_cancel(struct ni_gpct *counter) { unsigned int cidx = counter->counter_index; unsigned long flags; ni_tio_arm(counter, false, 0); spin_lock_irqsave(&counter->lock, flags); if (counter->mite_chan) mite_dma_disarm(counter->mite_chan); spin_unlock_irqrestore(&counter->lock, flags); ni_tio_configure_dma(counter, false, false); ni_tio_set_bits(counter, NITIO_INT_ENA_REG(cidx), GI_GATE_INTERRUPT_ENABLE(cidx), 0x0); return 0; }
int ni_tio_cancel(struct ni_gpct *counter) { unsigned cidx = counter->counter_index; unsigned long flags; ni_tio_arm(counter, 0, 0); spin_lock_irqsave(&counter->lock, flags); if (counter->mite_chan) mite_dma_disarm(counter->mite_chan); spin_unlock_irqrestore(&counter->lock, flags); ni_tio_configure_dma(counter, 0, 0); ni_tio_set_bits(counter, NITIO_INT_ENA_REG(cidx), Gi_Gate_Interrupt_Enable_Bit(cidx), 0x0); return 0; }
static int ni_660x_set_first_gate(struct ni_gpct *counter, unsigned int gate_source) { const unsigned selected_gate = CR_CHAN(gate_source); /* bits of selected_gate that may be meaningful to input select register */ const unsigned selected_gate_mask = 0x1f; unsigned ni_660x_gate_select; unsigned i; switch (selected_gate) { case NI_GPCT_NEXT_SOURCE_GATE_SELECT: ni_660x_gate_select = NI_660x_Next_SRC_Gate_Select; break; case NI_GPCT_NEXT_OUT_GATE_SELECT: case NI_GPCT_LOGIC_LOW_GATE_SELECT: case NI_GPCT_SOURCE_PIN_i_GATE_SELECT: case NI_GPCT_GATE_PIN_i_GATE_SELECT: ni_660x_gate_select = selected_gate & selected_gate_mask; break; default: for (i = 0; i <= ni_660x_max_rtsi_channel; ++i) { if (selected_gate == NI_GPCT_RTSI_GATE_SELECT(i)) { ni_660x_gate_select = selected_gate & selected_gate_mask; break; } } if (i <= ni_660x_max_rtsi_channel) break; for (i = 0; i <= ni_660x_max_gate_pin; ++i) { if (selected_gate == NI_GPCT_GATE_PIN_GATE_SELECT(i)) { ni_660x_gate_select = selected_gate & selected_gate_mask; break; } } if (i <= ni_660x_max_gate_pin) break; return -EINVAL; break; } ni_tio_set_bits(counter, NITIO_Gi_Input_Select_Reg(counter->counter_index), Gi_Gate_Select_Mask, Gi_Gate_Select_Bits(ni_660x_gate_select)); return 0; }
int ni_tio_cancel(struct ni_gpct *counter) { unsigned long flags; ni_tio_arm(counter, 0, 0); comedi_spin_lock_irqsave(&counter->lock, flags); if (counter->mite_chan) { mite_dma_disarm(counter->mite_chan); } comedi_spin_unlock_irqrestore(&counter->lock, flags); ni_tio_configure_dma(counter, 0, 0); ni_tio_set_bits(counter, NITIO_Gi_Interrupt_Enable_Reg(counter->counter_index), Gi_Gate_Interrupt_Enable_Bit(counter->counter_index), 0x0); return 0; }
void ni_tio_init_counter(struct ni_gpct *counter) { struct ni_gpct_device *counter_dev = counter->counter_dev; ni_tio_reset_count_and_disarm(counter); /* initialize counter registers */ counter_dev->regs[NITIO_Gi_Autoincrement_Reg(counter->counter_index)] = 0x0; write_register(counter, counter_dev-> regs[NITIO_Gi_Autoincrement_Reg(counter->counter_index)], NITIO_Gi_Autoincrement_Reg(counter->counter_index)); ni_tio_set_bits(counter, NITIO_Gi_Command_Reg(counter->counter_index), ~0, Gi_Synchronize_Gate_Bit); ni_tio_set_bits(counter, NITIO_Gi_Mode_Reg(counter->counter_index), ~0, 0); counter_dev->regs[NITIO_Gi_LoadA_Reg(counter->counter_index)] = 0x0; write_register(counter, counter_dev-> regs[NITIO_Gi_LoadA_Reg(counter->counter_index)], NITIO_Gi_LoadA_Reg(counter->counter_index)); counter_dev->regs[NITIO_Gi_LoadB_Reg(counter->counter_index)] = 0x0; write_register(counter, counter_dev-> regs[NITIO_Gi_LoadB_Reg(counter->counter_index)], NITIO_Gi_LoadB_Reg(counter->counter_index)); ni_tio_set_bits(counter, NITIO_Gi_Input_Select_Reg(counter->counter_index), ~0, 0); if (ni_tio_counting_mode_registers_present(counter_dev)) { ni_tio_set_bits(counter, NITIO_Gi_Counting_Mode_Reg(counter-> counter_index), ~0, 0); } if (ni_tio_second_gate_registers_present(counter_dev)) { counter_dev-> regs[NITIO_Gi_Second_Gate_Reg(counter->counter_index)] = 0x0; write_register(counter, counter_dev-> regs[NITIO_Gi_Second_Gate_Reg (counter->counter_index)], NITIO_Gi_Second_Gate_Reg(counter-> counter_index)); } ni_tio_set_bits(counter, NITIO_Gi_DMA_Config_Reg(counter->counter_index), ~0, 0x0); ni_tio_set_bits(counter, NITIO_Gi_Interrupt_Enable_Reg(counter->counter_index), ~0, 0x0); }
static int ni_tio_input_cmd(struct comedi_subdevice *s) { struct ni_gpct *counter = s->private; struct ni_gpct_device *counter_dev = counter->counter_dev; unsigned cidx = counter->counter_index; struct comedi_async *async = s->async; struct comedi_cmd *cmd = &async->cmd; int ret = 0; /* write alloc the entire buffer */ comedi_buf_write_alloc(s, async->prealloc_bufsz); counter->mite_chan->dir = COMEDI_INPUT; switch (counter_dev->variant) { case ni_gpct_variant_m_series: case ni_gpct_variant_660x: mite_prep_dma(counter->mite_chan, 32, 32); break; case ni_gpct_variant_e_series: mite_prep_dma(counter->mite_chan, 16, 32); break; default: BUG(); break; } ni_tio_set_bits(counter, NITIO_CMD_REG(cidx), GI_SAVE_TRACE, 0); ni_tio_configure_dma(counter, true, true); if (cmd->start_src == TRIG_INT) { async->inttrig = &ni_tio_input_inttrig; } else { /* TRIG_NOW || TRIG_EXT || TRIG_OTHER */ async->inttrig = NULL; mite_dma_arm(counter->mite_chan); if (cmd->start_src == TRIG_NOW) ret = ni_tio_arm(counter, 1, NI_GPCT_ARM_IMMEDIATE); else if (cmd->start_src == TRIG_EXT) ret = ni_tio_arm(counter, 1, cmd->start_arg); } return ret; }
static int ni_tio_cmd_setup(struct ni_gpct *counter, struct comedi_async *async) { struct comedi_cmd *cmd = &async->cmd; unsigned cidx = counter->counter_index; int set_gate_source = 0; unsigned gate_source; int retval = 0; if (cmd->scan_begin_src == TRIG_EXT) { set_gate_source = 1; gate_source = cmd->scan_begin_arg; } else if (cmd->convert_src == TRIG_EXT) { set_gate_source = 1; gate_source = cmd->convert_arg; } if (set_gate_source) retval = ni_tio_set_gate_src(counter, 0, gate_source); if (cmd->flags & TRIG_WAKE_EOS) { ni_tio_set_bits(counter, NITIO_INT_ENA_REG(cidx), Gi_Gate_Interrupt_Enable_Bit(cidx), Gi_Gate_Interrupt_Enable_Bit(cidx)); } return retval; }
static int ni_tio_set_counter_mode(struct ni_gpct *counter, unsigned mode) { struct ni_gpct_device *counter_dev = counter->counter_dev; unsigned mode_reg_mask; unsigned mode_reg_values; unsigned input_select_bits = 0; /* these bits map directly on to the mode register */ static const unsigned mode_reg_direct_mask = NI_GPCT_GATE_ON_BOTH_EDGES_BIT | NI_GPCT_EDGE_GATE_MODE_MASK | NI_GPCT_STOP_MODE_MASK | NI_GPCT_OUTPUT_MODE_MASK | NI_GPCT_HARDWARE_DISARM_MASK | NI_GPCT_LOADING_ON_TC_BIT | NI_GPCT_LOADING_ON_GATE_BIT | NI_GPCT_LOAD_B_SELECT_BIT; mode_reg_mask = mode_reg_direct_mask | Gi_Reload_Source_Switching_Bit; mode_reg_values = mode & mode_reg_direct_mask; switch (mode & NI_GPCT_RELOAD_SOURCE_MASK) { case NI_GPCT_RELOAD_SOURCE_FIXED_BITS: break; case NI_GPCT_RELOAD_SOURCE_SWITCHING_BITS: mode_reg_values |= Gi_Reload_Source_Switching_Bit; break; case NI_GPCT_RELOAD_SOURCE_GATE_SELECT_BITS: input_select_bits |= Gi_Gate_Select_Load_Source_Bit; mode_reg_mask |= Gi_Gating_Mode_Mask; mode_reg_values |= Gi_Level_Gating_Bits; break; default: break; } ni_tio_set_bits(counter, NITIO_Gi_Mode_Reg(counter->counter_index), mode_reg_mask, mode_reg_values); if (ni_tio_counting_mode_registers_present(counter_dev)) { unsigned counting_mode_bits = 0; counting_mode_bits |= (mode >> NI_GPCT_COUNTING_MODE_SHIFT) & Gi_Counting_Mode_Mask; counting_mode_bits |= ((mode >> NI_GPCT_INDEX_PHASE_BITSHIFT) << Gi_Index_Phase_Bitshift) & Gi_Index_Phase_Mask; if (mode & NI_GPCT_INDEX_ENABLE_BIT) { counting_mode_bits |= Gi_Index_Mode_Bit; } ni_tio_set_bits(counter, NITIO_Gi_Counting_Mode_Reg(counter->counter_index), Gi_Counting_Mode_Mask | Gi_Index_Phase_Mask | Gi_Index_Mode_Bit, counting_mode_bits); ni_tio_set_sync_mode(counter, 0); } ni_tio_set_bits(counter, NITIO_Gi_Command_Reg(counter->counter_index), Gi_Up_Down_Mask, (mode >> NI_GPCT_COUNTING_DIRECTION_SHIFT) << Gi_Up_Down_Shift); if (mode & NI_GPCT_OR_GATE_BIT) { input_select_bits |= Gi_Or_Gate_Bit; } if (mode & NI_GPCT_INVERT_OUTPUT_BIT) { input_select_bits |= Gi_Output_Polarity_Bit; } ni_tio_set_bits(counter, NITIO_Gi_Input_Select_Reg(counter->counter_index), Gi_Gate_Select_Load_Source_Bit | Gi_Or_Gate_Bit | Gi_Output_Polarity_Bit, input_select_bits); return 0; }
int ni_tio_set_gate_src(struct ni_gpct *counter, unsigned gate_index, lsampl_t gate_source) { struct ni_gpct_device *counter_dev = counter->counter_dev; const unsigned second_gate_reg = NITIO_Gi_Second_Gate_Reg(counter->counter_index); switch (gate_index) { case 0: if (CR_CHAN(gate_source) == NI_GPCT_DISABLED_GATE_SELECT) { ni_tio_set_bits(counter, NITIO_Gi_Mode_Reg(counter->counter_index), Gi_Gating_Mode_Mask, Gi_Gating_Disabled_Bits); return 0; } ni_tio_set_first_gate_modifiers(counter, gate_source); switch (counter_dev->variant) { case ni_gpct_variant_e_series: case ni_gpct_variant_m_series: return ni_m_series_set_first_gate(counter, gate_source); break; case ni_gpct_variant_660x: return ni_660x_set_first_gate(counter, gate_source); break; default: BUG(); break; } break; case 1: if (ni_tio_second_gate_registers_present(counter_dev) == 0) return -EINVAL; if (CR_CHAN(gate_source) == NI_GPCT_DISABLED_GATE_SELECT) { counter_dev->regs[second_gate_reg] &= ~Gi_Second_Gate_Mode_Bit; write_register(counter, counter_dev->regs[second_gate_reg], second_gate_reg); return 0; } if (gate_source & CR_INVERT) { counter_dev->regs[second_gate_reg] |= Gi_Second_Gate_Polarity_Bit; } else { counter_dev->regs[second_gate_reg] &= ~Gi_Second_Gate_Polarity_Bit; } switch (counter_dev->variant) { case ni_gpct_variant_m_series: return ni_m_series_set_second_gate(counter, gate_source); break; case ni_gpct_variant_660x: return ni_660x_set_second_gate(counter, gate_source); break; default: BUG(); break; } break; default: return -EINVAL; break; } return 0; }