From 0561373030bac4dab2562355fd40225d7dcf1da6 Mon Sep 17 00:00:00 2001 From: Frank Mori Hess Date: Fri, 15 Dec 2006 20:54:27 +0000 Subject: [PATCH] Added support for x2 prescaling on ni general-purpose counters. --- comedi/drivers/ni_tio.c | 50 ++++++++++++++++++++++++++++++++++------- include/linux/comedi.h | 8 ++++--- 2 files changed, 47 insertions(+), 11 deletions(-) diff --git a/comedi/drivers/ni_tio.c b/comedi/drivers/ni_tio.c index d0077270..8dde74c3 100644 --- a/comedi/drivers/ni_tio.c +++ b/comedi/drivers/ni_tio.c @@ -375,6 +375,25 @@ static inline unsigned Gi_Alternate_Sync_Bit(enum ni_gpct_variant variant) } return 0; } +static inline unsigned Gi_Prescale_X2_Bit(enum ni_gpct_variant variant) +{ + switch(variant) + { + case ni_gpct_variant_e_series: + return 0; + break; + case ni_gpct_variant_m_series: + return Gi_M_Series_Prescale_X2_Bit; + break; + case ni_gpct_variant_660x: + return Gi_660x_Prescale_X2_Bit; + break; + default: + BUG(); + break; + } + return 0; +} static inline unsigned Gi_Prescale_X8_Bit(enum ni_gpct_variant variant) { switch(variant) @@ -495,7 +514,6 @@ static inline unsigned NI_M_Series_PFI_Gate_Select(unsigned n) #define Gi_Source_Select_Shift 2 #define Gi_Gate_Select_Shift 7 -/*FIXME: these gates are 660x specific. See m-series example code for its gates/sources*/ enum Gi_Input_Select_Bits { Gi_Source_Select_Mask = 0x7c, @@ -975,7 +993,7 @@ static void ni_tio_update_clock_period(struct ni_gpct *counter, lsampl_t clock_s } } -static void ni_tio_set_second_source_select(struct ni_gpct *counter, lsampl_t clock_source) +static void ni_tio_set_source_subselect(struct ni_gpct *counter, lsampl_t clock_source) { const unsigned second_gate_reg = NITIO_Gi_Second_Gate_Reg(counter->counter_index); @@ -1006,7 +1024,7 @@ static int ni_tio_set_clock_src(struct ni_gpct *counter, lsampl_t clock_source, /*FIXME: add support for prescale in counting mode register */ /*FIXME: add support for prescale x2*/ -/*FIXME: is clock period specified before or after prescaling? */ +/*FIXME: is clock period specified before or after prescaling? I'm going to say after. */ /*FIXME: validate clock source */ counter->regs[input_select_reg] &= ~Gi_Source_Select_Mask; switch(counter->variant) @@ -1027,15 +1045,29 @@ static int ni_tio_set_clock_src(struct ni_gpct *counter, lsampl_t clock_source, else counter->regs[input_select_reg] &= ~Gi_Source_Polarity_Bit; counter->write_register(counter, counter->regs[input_select_reg], input_select_reg); - ni_tio_set_second_source_select(counter, clock_source); + ni_tio_set_source_subselect(counter, clock_source); if(ni_tio_counting_mode_registers_present(counter)) { const unsigned counting_mode_reg = NITIO_Gi_Counting_Mode_Reg(counter->counter_index); + const unsigned prescaling_mode = clock_source & NI_GPCT_PRESCALE_MODE_CLOCK_SRC_MASK; - if(clock_source & NI_GPCT_PRESCALE_CLOCK_SRC_BIT) - counter->regs[counting_mode_reg] |= Gi_Prescale_X8_Bit(counter->variant); - else + switch(prescaling_mode) + { + case NI_GPCT_NO_PRESCALE_CLOCK_SRC_BITS: + counter->regs[counting_mode_reg] &= ~(Gi_Prescale_X2_Bit(counter->variant) | Gi_Prescale_X8_Bit(counter->variant)); + break; + case NI_GPCT_PRESCALE_X2_CLOCK_SRC_BITS: + counter->regs[counting_mode_reg] |= Gi_Prescale_X2_Bit(counter->variant); counter->regs[counting_mode_reg] &= ~Gi_Prescale_X8_Bit(counter->variant); + break; + case NI_GPCT_PRESCALE_X8_CLOCK_SRC_BITS: + counter->regs[counting_mode_reg] |= Gi_Prescale_X8_Bit(counter->variant); + counter->regs[counting_mode_reg] &= ~Gi_Prescale_X2_Bit(counter->variant); + break; + default: + return -EINVAL; + break; + } counter->write_register(counter, counter->regs[counting_mode_reg], counting_mode_reg); } ni_tio_update_clock_period(counter, clock_source, period_ns); @@ -1051,8 +1083,10 @@ static unsigned ni_tio_clock_src_modifiers(struct ni_gpct *counter) if(counter->regs[input_select_reg] & Gi_Source_Polarity_Bit) bits |= NI_GPCT_INVERT_CLOCK_SRC_BIT; + if(counter->regs[counting_mode_reg] & Gi_Prescale_X2_Bit(counter->variant)) + bits |= NI_GPCT_PRESCALE_X2_CLOCK_SRC_BITS; if(counter->regs[counting_mode_reg] & Gi_Prescale_X8_Bit(counter->variant)) - bits |= NI_GPCT_PRESCALE_CLOCK_SRC_BIT; + bits |= NI_GPCT_PRESCALE_X8_CLOCK_SRC_BITS; return bits; } diff --git a/include/linux/comedi.h b/include/linux/comedi.h index 3c4059c5..fededd4a 100644 --- a/include/linux/comedi.h +++ b/include/linux/comedi.h @@ -566,7 +566,7 @@ enum ni_gpct_mode_bits * INSN_CONFIG_SET_CLOCK_SRC when using NI general-purpose counters. */ enum ni_gpct_clock_source_bits { - NI_GPCT_CLOCK_SRC_SELECT_MASK = 0x2f, + NI_GPCT_CLOCK_SRC_SELECT_MASK = 0x1f, NI_GPCT_TIMEBASE_1_CLOCK_SRC_BITS = 0x0, NI_GPCT_TIMEBASE_2_CLOCK_SRC_BITS = 0x1, NI_GPCT_TIMEBASE_3_CLOCK_SRC_BITS = 0x2, @@ -577,8 +577,10 @@ enum ni_gpct_clock_source_bits NI_GPCT_PXI10_CLOCK_SRC_BITS = 0x7, NI_GPCT_PXI_STAR_TRIGGER_CLOCK_SRC_BITS = 0x8, NI_GPCT_ANALOG_TRIGGER_OUT_CLOCK_SRC_BITS = 0x9, - /* modifier bits */ - NI_GPCT_PRESCALE_CLOCK_SRC_BIT = 0x20000000, /* divide source by 8 */ + NI_GPCT_PRESCALE_MODE_CLOCK_SRC_MASK = 0x30000000, + NI_GPCT_NO_PRESCALE_CLOCK_SRC_BITS = 0x0, + NI_GPCT_PRESCALE_X2_CLOCK_SRC_BITS = 0x10000000, /* divide source by 2 */ + NI_GPCT_PRESCALE_X8_CLOCK_SRC_BITS = 0x20000000, /* divide source by 8 */ NI_GPCT_INVERT_CLOCK_SRC_BIT = 0x80000000 }; static inline unsigned NI_GPCT_SOURCE_PIN_CLOCK_SRC_BITS(unsigned n) /* NI 660x-specific */ -- 2.26.2