Commit | Line | Data |
---|---|---|
cb7859a9 FMH |
1 | /* |
2 | comedi/drivers/ni_tio.c | |
3 | Support for NI general purpose counters | |
4 | ||
5 | Copyright (C) 2006 Frank Mori Hess <fmhess@users.sourceforge.net> | |
6 | ||
7 | This program is free software; you can redistribute it and/or modify | |
8 | it under the terms of the GNU General Public License as published by | |
9 | the Free Software Foundation; either version 2 of the License, or | |
10 | (at your option) any later version. | |
11 | ||
12 | This program is distributed in the hope that it will be useful, | |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
cb7859a9 FMH |
16 | */ |
17 | ||
18 | /* | |
9ade47ab IA |
19 | * Module: ni_tio |
20 | * Description: National Instruments general purpose counters | |
21 | * Author: J.P. Mellor <jpmellor@rose-hulman.edu>, | |
22 | * Herman.Bruyninckx@mech.kuleuven.ac.be, | |
23 | * Wim.Meeussen@mech.kuleuven.ac.be, | |
24 | * Klaas.Gadeyne@mech.kuleuven.ac.be, | |
25 | * Frank Mori Hess <fmhess@users.sourceforge.net> | |
26 | * Updated: Thu Nov 16 09:50:32 EST 2006 | |
27 | * Status: works | |
28 | * | |
29 | * This module is not used directly by end-users. Rather, it | |
30 | * is used by other drivers (for example ni_660x and ni_pcimio) | |
31 | * to provide support for NI's general purpose counters. It was | |
32 | * originally based on the counter code from ni_660x.c and | |
33 | * ni_mio_common.c. | |
34 | * | |
35 | * References: | |
36 | * DAQ 660x Register-Level Programmer Manual (NI 370505A-01) | |
37 | * DAQ 6601/6602 User Manual (NI 322137B-01) | |
38 | * 340934b.pdf DAQ-STC reference manual | |
39 | */ | |
cb7859a9 | 40 | |
cb7859a9 FMH |
41 | /* |
42 | TODO: | |
43 | Support use of both banks X and Y | |
44 | */ | |
45 | ||
ce157f80 | 46 | #include <linux/module.h> |
0bdab509 HS |
47 | #include <linux/slab.h> |
48 | ||
cb7859a9 FMH |
49 | #include "ni_tio_internal.h" |
50 | ||
9ff506ec HS |
51 | /* |
52 | * clock sources for ni e and m series boards, | |
c2c6c288 | 53 | * get bits with GI_SRC_SEL() |
9ff506ec HS |
54 | */ |
55 | #define NI_M_TIMEBASE_1_CLK 0x0 /* 20MHz */ | |
56 | #define NI_M_PFI_CLK(x) (((x) < 10) ? (1 + (x)) : (0xb + (x))) | |
57 | #define NI_M_RTSI_CLK(x) (((x) == 7) ? 0x1b : (0xb + (x))) | |
58 | #define NI_M_TIMEBASE_2_CLK 0x12 /* 100KHz */ | |
59 | #define NI_M_NEXT_TC_CLK 0x13 | |
60 | #define NI_M_NEXT_GATE_CLK 0x14 /* Gi_Src_SubSelect=0 */ | |
61 | #define NI_M_PXI_STAR_TRIGGER_CLK 0x14 /* Gi_Src_SubSelect=1 */ | |
62 | #define NI_M_PXI10_CLK 0x1d | |
63 | #define NI_M_TIMEBASE_3_CLK 0x1e /* 80MHz, Gi_Src_SubSelect=0 */ | |
64 | #define NI_M_ANALOG_TRIGGER_OUT_CLK 0x1e /* Gi_Src_SubSelect=1 */ | |
65 | #define NI_M_LOGIC_LOW_CLK 0x1f | |
66 | #define NI_M_MAX_PFI_CHAN 15 | |
67 | #define NI_M_MAX_RTSI_CHAN 7 | |
68 | ||
69 | /* | |
70 | * clock sources for ni_660x boards, | |
c2c6c288 | 71 | * get bits with GI_SRC_SEL() |
9ff506ec HS |
72 | */ |
73 | #define NI_660X_TIMEBASE_1_CLK 0x0 /* 20MHz */ | |
74 | #define NI_660X_SRC_PIN_I_CLK 0x1 | |
75 | #define NI_660X_SRC_PIN_CLK(x) (0x2 + (x)) | |
76 | #define NI_660X_NEXT_GATE_CLK 0xa | |
77 | #define NI_660X_RTSI_CLK(x) (0xb + (x)) | |
78 | #define NI_660X_TIMEBASE_2_CLK 0x12 /* 100KHz */ | |
79 | #define NI_660X_NEXT_TC_CLK 0x13 | |
80 | #define NI_660X_TIMEBASE_3_CLK 0x1e /* 80MHz */ | |
81 | #define NI_660X_LOGIC_LOW_CLK 0x1f | |
82 | #define NI_660X_MAX_SRC_PIN 7 | |
83 | #define NI_660X_MAX_RTSI_CHAN 6 | |
84 | ||
85 | /* ni m series gate_select */ | |
86 | #define NI_M_TIMESTAMP_MUX_GATE_SEL 0x0 | |
87 | #define NI_M_PFI_GATE_SEL(x) (((x) < 10) ? (1 + (x)) : (0xb + (x))) | |
88 | #define NI_M_RTSI_GATE_SEL(x) (((x) == 7) ? 0x1b : (0xb + (x))) | |
89 | #define NI_M_AI_START2_GATE_SEL 0x12 | |
90 | #define NI_M_PXI_STAR_TRIGGER_GATE_SEL 0x13 | |
91 | #define NI_M_NEXT_OUT_GATE_SEL 0x14 | |
92 | #define NI_M_AI_START1_GATE_SEL 0x1c | |
93 | #define NI_M_NEXT_SRC_GATE_SEL 0x1d | |
94 | #define NI_M_ANALOG_TRIG_OUT_GATE_SEL 0x1e | |
95 | #define NI_M_LOGIC_LOW_GATE_SEL 0x1f | |
96 | ||
97 | /* ni_660x gate select */ | |
98 | #define NI_660X_SRC_PIN_I_GATE_SEL 0x0 | |
99 | #define NI_660X_GATE_PIN_I_GATE_SEL 0x1 | |
100 | #define NI_660X_PIN_GATE_SEL(x) (0x2 + (x)) | |
101 | #define NI_660X_NEXT_SRC_GATE_SEL 0xa | |
102 | #define NI_660X_RTSI_GATE_SEL(x) (0xb + (x)) | |
103 | #define NI_660X_NEXT_OUT_GATE_SEL 0x14 | |
104 | #define NI_660X_LOGIC_LOW_GATE_SEL 0x1f | |
105 | #define NI_660X_MAX_GATE_PIN 7 | |
106 | ||
107 | /* ni_660x second gate select */ | |
108 | #define NI_660X_SRC_PIN_I_GATE2_SEL 0x0 | |
109 | #define NI_660X_UD_PIN_I_GATE2_SEL 0x1 | |
110 | #define NI_660X_UD_PIN_GATE2_SEL(x) (0x2 + (x)) | |
111 | #define NI_660X_NEXT_SRC_GATE2_SEL 0xa | |
112 | #define NI_660X_RTSI_GATE2_SEL(x) (0xb + (x)) | |
113 | #define NI_660X_NEXT_OUT_GATE2_SEL 0x14 | |
114 | #define NI_660X_SELECTED_GATE2_SEL 0x1e | |
115 | #define NI_660X_LOGIC_LOW_GATE2_SEL 0x1f | |
116 | #define NI_660X_MAX_UP_DOWN_PIN 7 | |
117 | ||
ed404871 | 118 | static inline unsigned GI_ALT_SYNC(enum ni_gpct_variant variant) |
cb7859a9 FMH |
119 | { |
120 | switch (variant) { | |
121 | case ni_gpct_variant_e_series: | |
85603161 | 122 | default: |
cb7859a9 | 123 | return 0; |
cb7859a9 | 124 | case ni_gpct_variant_m_series: |
ed404871 | 125 | return GI_M_ALT_SYNC; |
cb7859a9 | 126 | case ni_gpct_variant_660x: |
ed404871 | 127 | return GI_660X_ALT_SYNC; |
cb7859a9 | 128 | } |
cb7859a9 | 129 | } |
0a85b6f0 | 130 | |
ed404871 | 131 | static inline unsigned GI_PRESCALE_X2(enum ni_gpct_variant variant) |
cb7859a9 FMH |
132 | { |
133 | switch (variant) { | |
134 | case ni_gpct_variant_e_series: | |
85603161 | 135 | default: |
cb7859a9 | 136 | return 0; |
cb7859a9 | 137 | case ni_gpct_variant_m_series: |
ed404871 | 138 | return GI_M_PRESCALE_X2; |
cb7859a9 | 139 | case ni_gpct_variant_660x: |
ed404871 | 140 | return GI_660X_PRESCALE_X2; |
cb7859a9 | 141 | } |
cb7859a9 | 142 | } |
0a85b6f0 | 143 | |
ed404871 | 144 | static inline unsigned GI_PRESCALE_X8(enum ni_gpct_variant variant) |
cb7859a9 FMH |
145 | { |
146 | switch (variant) { | |
147 | case ni_gpct_variant_e_series: | |
85603161 | 148 | default: |
cb7859a9 | 149 | return 0; |
cb7859a9 | 150 | case ni_gpct_variant_m_series: |
ed404871 | 151 | return GI_M_PRESCALE_X8; |
cb7859a9 | 152 | case ni_gpct_variant_660x: |
ed404871 | 153 | return GI_660X_PRESCALE_X8; |
cb7859a9 | 154 | } |
cb7859a9 | 155 | } |
0a85b6f0 | 156 | |
ed404871 | 157 | static inline unsigned GI_HW_ARM_SEL_MASK(enum ni_gpct_variant variant) |
cb7859a9 FMH |
158 | { |
159 | switch (variant) { | |
160 | case ni_gpct_variant_e_series: | |
85603161 | 161 | default: |
cb7859a9 | 162 | return 0; |
cb7859a9 | 163 | case ni_gpct_variant_m_series: |
ed404871 | 164 | return GI_M_HW_ARM_SEL_MASK; |
cb7859a9 | 165 | case ni_gpct_variant_660x: |
ed404871 | 166 | return GI_660X_HW_ARM_SEL_MASK; |
cb7859a9 | 167 | } |
cb7859a9 FMH |
168 | } |
169 | ||
abfe2196 | 170 | static bool ni_tio_has_gate2_registers(const struct ni_gpct_device *counter_dev) |
cb7859a9 FMH |
171 | { |
172 | switch (counter_dev->variant) { | |
173 | case ni_gpct_variant_e_series: | |
85603161 | 174 | default: |
abfe2196 | 175 | return false; |
cb7859a9 FMH |
176 | case ni_gpct_variant_m_series: |
177 | case ni_gpct_variant_660x: | |
abfe2196 | 178 | return true; |
cb7859a9 | 179 | } |
cb7859a9 FMH |
180 | } |
181 | ||
182 | static void ni_tio_reset_count_and_disarm(struct ni_gpct *counter) | |
183 | { | |
fca7c1d7 HS |
184 | unsigned cidx = counter->counter_index; |
185 | ||
dc613766 | 186 | write_register(counter, GI_RESET(cidx), NITIO_RESET_REG(cidx)); |
cb7859a9 FMH |
187 | } |
188 | ||
099286dc HS |
189 | static uint64_t ni_tio_clock_period_ps(const struct ni_gpct *counter, |
190 | unsigned generic_clock_source) | |
191 | { | |
192 | uint64_t clock_period_ps; | |
193 | ||
194 | switch (generic_clock_source & NI_GPCT_CLOCK_SRC_SELECT_MASK) { | |
195 | case NI_GPCT_TIMEBASE_1_CLOCK_SRC_BITS: | |
196 | clock_period_ps = 50000; | |
197 | break; | |
198 | case NI_GPCT_TIMEBASE_2_CLOCK_SRC_BITS: | |
199 | clock_period_ps = 10000000; | |
200 | break; | |
201 | case NI_GPCT_TIMEBASE_3_CLOCK_SRC_BITS: | |
202 | clock_period_ps = 12500; | |
203 | break; | |
204 | case NI_GPCT_PXI10_CLOCK_SRC_BITS: | |
205 | clock_period_ps = 100000; | |
206 | break; | |
207 | default: | |
208 | /* | |
209 | * clock period is specified by user with prescaling | |
210 | * already taken into account. | |
211 | */ | |
212 | return counter->clock_period_ps; | |
213 | } | |
214 | ||
215 | switch (generic_clock_source & NI_GPCT_PRESCALE_MODE_CLOCK_SRC_MASK) { | |
216 | case NI_GPCT_NO_PRESCALE_CLOCK_SRC_BITS: | |
217 | break; | |
218 | case NI_GPCT_PRESCALE_X2_CLOCK_SRC_BITS: | |
219 | clock_period_ps *= 2; | |
220 | break; | |
221 | case NI_GPCT_PRESCALE_X8_CLOCK_SRC_BITS: | |
222 | clock_period_ps *= 8; | |
223 | break; | |
224 | default: | |
225 | BUG(); | |
226 | break; | |
227 | } | |
228 | return clock_period_ps; | |
229 | } | |
230 | ||
231 | static unsigned ni_tio_clock_src_modifiers(const struct ni_gpct *counter) | |
232 | { | |
233 | struct ni_gpct_device *counter_dev = counter->counter_dev; | |
234 | unsigned cidx = counter->counter_index; | |
235 | const unsigned counting_mode_bits = | |
236 | ni_tio_get_soft_copy(counter, NITIO_CNT_MODE_REG(cidx)); | |
237 | unsigned bits = 0; | |
238 | ||
239 | if (ni_tio_get_soft_copy(counter, NITIO_INPUT_SEL_REG(cidx)) & | |
c2c6c288 | 240 | GI_SRC_POL_INVERT) |
099286dc | 241 | bits |= NI_GPCT_INVERT_CLOCK_SRC_BIT; |
ed404871 | 242 | if (counting_mode_bits & GI_PRESCALE_X2(counter_dev->variant)) |
099286dc | 243 | bits |= NI_GPCT_PRESCALE_X2_CLOCK_SRC_BITS; |
ed404871 | 244 | if (counting_mode_bits & GI_PRESCALE_X8(counter_dev->variant)) |
099286dc HS |
245 | bits |= NI_GPCT_PRESCALE_X8_CLOCK_SRC_BITS; |
246 | return bits; | |
247 | } | |
248 | ||
249 | static unsigned ni_m_series_clock_src_select(const struct ni_gpct *counter) | |
250 | { | |
251 | struct ni_gpct_device *counter_dev = counter->counter_dev; | |
252 | unsigned cidx = counter->counter_index; | |
253 | const unsigned second_gate_reg = NITIO_GATE2_REG(cidx); | |
254 | unsigned clock_source = 0; | |
c2c6c288 | 255 | unsigned src; |
099286dc | 256 | unsigned i; |
099286dc | 257 | |
c2c6c288 HS |
258 | src = GI_BITS_TO_SRC(ni_tio_get_soft_copy(counter, |
259 | NITIO_INPUT_SEL_REG(cidx))); | |
260 | ||
261 | switch (src) { | |
099286dc HS |
262 | case NI_M_TIMEBASE_1_CLK: |
263 | clock_source = NI_GPCT_TIMEBASE_1_CLOCK_SRC_BITS; | |
264 | break; | |
265 | case NI_M_TIMEBASE_2_CLK: | |
266 | clock_source = NI_GPCT_TIMEBASE_2_CLOCK_SRC_BITS; | |
267 | break; | |
268 | case NI_M_TIMEBASE_3_CLK: | |
4359dcf3 | 269 | if (counter_dev->regs[second_gate_reg] & GI_SRC_SUBSEL) |
099286dc HS |
270 | clock_source = |
271 | NI_GPCT_ANALOG_TRIGGER_OUT_CLOCK_SRC_BITS; | |
272 | else | |
273 | clock_source = NI_GPCT_TIMEBASE_3_CLOCK_SRC_BITS; | |
274 | break; | |
275 | case NI_M_LOGIC_LOW_CLK: | |
276 | clock_source = NI_GPCT_LOGIC_LOW_CLOCK_SRC_BITS; | |
277 | break; | |
278 | case NI_M_NEXT_GATE_CLK: | |
4359dcf3 | 279 | if (counter_dev->regs[second_gate_reg] & GI_SRC_SUBSEL) |
099286dc HS |
280 | clock_source = NI_GPCT_PXI_STAR_TRIGGER_CLOCK_SRC_BITS; |
281 | else | |
282 | clock_source = NI_GPCT_NEXT_GATE_CLOCK_SRC_BITS; | |
283 | break; | |
284 | case NI_M_PXI10_CLK: | |
285 | clock_source = NI_GPCT_PXI10_CLOCK_SRC_BITS; | |
286 | break; | |
287 | case NI_M_NEXT_TC_CLK: | |
288 | clock_source = NI_GPCT_NEXT_TC_CLOCK_SRC_BITS; | |
289 | break; | |
290 | default: | |
291 | for (i = 0; i <= NI_M_MAX_RTSI_CHAN; ++i) { | |
c2c6c288 | 292 | if (src == NI_M_RTSI_CLK(i)) { |
099286dc HS |
293 | clock_source = NI_GPCT_RTSI_CLOCK_SRC_BITS(i); |
294 | break; | |
295 | } | |
296 | } | |
297 | if (i <= NI_M_MAX_RTSI_CHAN) | |
298 | break; | |
299 | for (i = 0; i <= NI_M_MAX_PFI_CHAN; ++i) { | |
c2c6c288 | 300 | if (src == NI_M_PFI_CLK(i)) { |
099286dc HS |
301 | clock_source = NI_GPCT_PFI_CLOCK_SRC_BITS(i); |
302 | break; | |
303 | } | |
304 | } | |
305 | if (i <= NI_M_MAX_PFI_CHAN) | |
306 | break; | |
307 | BUG(); | |
308 | break; | |
309 | } | |
310 | clock_source |= ni_tio_clock_src_modifiers(counter); | |
311 | return clock_source; | |
312 | } | |
313 | ||
314 | static unsigned ni_660x_clock_src_select(const struct ni_gpct *counter) | |
315 | { | |
316 | unsigned clock_source = 0; | |
317 | unsigned cidx = counter->counter_index; | |
c2c6c288 | 318 | unsigned src; |
099286dc HS |
319 | unsigned i; |
320 | ||
c2c6c288 HS |
321 | src = GI_BITS_TO_SRC(ni_tio_get_soft_copy(counter, |
322 | NITIO_INPUT_SEL_REG(cidx))); | |
323 | ||
324 | switch (src) { | |
099286dc HS |
325 | case NI_660X_TIMEBASE_1_CLK: |
326 | clock_source = NI_GPCT_TIMEBASE_1_CLOCK_SRC_BITS; | |
327 | break; | |
328 | case NI_660X_TIMEBASE_2_CLK: | |
329 | clock_source = NI_GPCT_TIMEBASE_2_CLOCK_SRC_BITS; | |
330 | break; | |
331 | case NI_660X_TIMEBASE_3_CLK: | |
332 | clock_source = NI_GPCT_TIMEBASE_3_CLOCK_SRC_BITS; | |
333 | break; | |
334 | case NI_660X_LOGIC_LOW_CLK: | |
335 | clock_source = NI_GPCT_LOGIC_LOW_CLOCK_SRC_BITS; | |
336 | break; | |
337 | case NI_660X_SRC_PIN_I_CLK: | |
338 | clock_source = NI_GPCT_SOURCE_PIN_i_CLOCK_SRC_BITS; | |
339 | break; | |
340 | case NI_660X_NEXT_GATE_CLK: | |
341 | clock_source = NI_GPCT_NEXT_GATE_CLOCK_SRC_BITS; | |
342 | break; | |
343 | case NI_660X_NEXT_TC_CLK: | |
344 | clock_source = NI_GPCT_NEXT_TC_CLOCK_SRC_BITS; | |
345 | break; | |
346 | default: | |
347 | for (i = 0; i <= NI_660X_MAX_RTSI_CHAN; ++i) { | |
c2c6c288 | 348 | if (src == NI_660X_RTSI_CLK(i)) { |
099286dc HS |
349 | clock_source = NI_GPCT_RTSI_CLOCK_SRC_BITS(i); |
350 | break; | |
351 | } | |
352 | } | |
353 | if (i <= NI_660X_MAX_RTSI_CHAN) | |
354 | break; | |
355 | for (i = 0; i <= NI_660X_MAX_SRC_PIN; ++i) { | |
c2c6c288 | 356 | if (src == NI_660X_SRC_PIN_CLK(i)) { |
099286dc HS |
357 | clock_source = |
358 | NI_GPCT_SOURCE_PIN_CLOCK_SRC_BITS(i); | |
359 | break; | |
360 | } | |
361 | } | |
362 | if (i <= NI_660X_MAX_SRC_PIN) | |
363 | break; | |
364 | BUG(); | |
365 | break; | |
366 | } | |
367 | clock_source |= ni_tio_clock_src_modifiers(counter); | |
368 | return clock_source; | |
369 | } | |
370 | ||
371 | static unsigned ni_tio_generic_clock_src_select(const struct ni_gpct *counter) | |
372 | { | |
373 | switch (counter->counter_dev->variant) { | |
374 | case ni_gpct_variant_e_series: | |
375 | case ni_gpct_variant_m_series: | |
376 | default: | |
377 | return ni_m_series_clock_src_select(counter); | |
378 | case ni_gpct_variant_660x: | |
379 | return ni_660x_clock_src_select(counter); | |
380 | } | |
381 | } | |
382 | ||
cb7859a9 FMH |
383 | static void ni_tio_set_sync_mode(struct ni_gpct *counter, int force_alt_sync) |
384 | { | |
385 | struct ni_gpct_device *counter_dev = counter->counter_dev; | |
fca7c1d7 HS |
386 | unsigned cidx = counter->counter_index; |
387 | const unsigned counting_mode_reg = NITIO_CNT_MODE_REG(cidx); | |
cb7859a9 | 388 | static const uint64_t min_normal_sync_period_ps = 25000; |
ed404871 | 389 | unsigned mode; |
f6e22783 | 390 | uint64_t clock_period_ps; |
cb7859a9 FMH |
391 | |
392 | if (ni_tio_counting_mode_registers_present(counter_dev) == 0) | |
393 | return; | |
394 | ||
ed404871 HS |
395 | mode = ni_tio_get_soft_copy(counter, counting_mode_reg); |
396 | switch (mode & GI_CNT_MODE_MASK) { | |
397 | case GI_CNT_MODE_QUADX1: | |
398 | case GI_CNT_MODE_QUADX2: | |
399 | case GI_CNT_MODE_QUADX4: | |
400 | case GI_CNT_MODE_SYNC_SRC: | |
cb7859a9 FMH |
401 | force_alt_sync = 1; |
402 | break; | |
403 | default: | |
404 | break; | |
405 | } | |
f6e22783 HS |
406 | |
407 | clock_period_ps = ni_tio_clock_period_ps(counter, | |
408 | ni_tio_generic_clock_src_select(counter)); | |
409 | ||
14f194a9 HS |
410 | /* |
411 | * It's not clear what we should do if clock_period is unknown, so we | |
412 | * are not using the alt sync bit in that case, but allow the caller | |
413 | * to decide by using the force_alt_sync parameter. | |
414 | */ | |
cb7859a9 | 415 | if (force_alt_sync || |
0a85b6f0 | 416 | (clock_period_ps && clock_period_ps < min_normal_sync_period_ps)) { |
cb7859a9 | 417 | ni_tio_set_bits(counter, counting_mode_reg, |
ed404871 HS |
418 | GI_ALT_SYNC(counter_dev->variant), |
419 | GI_ALT_SYNC(counter_dev->variant)); | |
cb7859a9 FMH |
420 | } else { |
421 | ni_tio_set_bits(counter, counting_mode_reg, | |
ed404871 | 422 | GI_ALT_SYNC(counter_dev->variant), |
0a85b6f0 | 423 | 0x0); |
cb7859a9 FMH |
424 | } |
425 | } | |
426 | ||
427 | static int ni_tio_set_counter_mode(struct ni_gpct *counter, unsigned mode) | |
428 | { | |
429 | struct ni_gpct_device *counter_dev = counter->counter_dev; | |
fca7c1d7 | 430 | unsigned cidx = counter->counter_index; |
cb7859a9 FMH |
431 | unsigned mode_reg_mask; |
432 | unsigned mode_reg_values; | |
433 | unsigned input_select_bits = 0; | |
434 | /* these bits map directly on to the mode register */ | |
435 | static const unsigned mode_reg_direct_mask = | |
0a85b6f0 MT |
436 | NI_GPCT_GATE_ON_BOTH_EDGES_BIT | NI_GPCT_EDGE_GATE_MODE_MASK | |
437 | NI_GPCT_STOP_MODE_MASK | NI_GPCT_OUTPUT_MODE_MASK | | |
438 | NI_GPCT_HARDWARE_DISARM_MASK | NI_GPCT_LOADING_ON_TC_BIT | | |
439 | NI_GPCT_LOADING_ON_GATE_BIT | NI_GPCT_LOAD_B_SELECT_BIT; | |
cb7859a9 | 440 | |
36d80f4a | 441 | mode_reg_mask = mode_reg_direct_mask | GI_RELOAD_SRC_SWITCHING; |
cb7859a9 FMH |
442 | mode_reg_values = mode & mode_reg_direct_mask; |
443 | switch (mode & NI_GPCT_RELOAD_SOURCE_MASK) { | |
444 | case NI_GPCT_RELOAD_SOURCE_FIXED_BITS: | |
445 | break; | |
446 | case NI_GPCT_RELOAD_SOURCE_SWITCHING_BITS: | |
36d80f4a | 447 | mode_reg_values |= GI_RELOAD_SRC_SWITCHING; |
cb7859a9 FMH |
448 | break; |
449 | case NI_GPCT_RELOAD_SOURCE_GATE_SELECT_BITS: | |
c2c6c288 | 450 | input_select_bits |= GI_GATE_SEL_LOAD_SRC; |
36d80f4a HS |
451 | mode_reg_mask |= GI_GATING_MODE_MASK; |
452 | mode_reg_values |= GI_LEVEL_GATING; | |
cb7859a9 FMH |
453 | break; |
454 | default: | |
455 | break; | |
456 | } | |
fca7c1d7 | 457 | ni_tio_set_bits(counter, NITIO_MODE_REG(cidx), |
0a85b6f0 | 458 | mode_reg_mask, mode_reg_values); |
cb7859a9 FMH |
459 | |
460 | if (ni_tio_counting_mode_registers_present(counter_dev)) { | |
ed404871 HS |
461 | unsigned bits = 0; |
462 | ||
463 | bits |= GI_CNT_MODE(mode >> NI_GPCT_COUNTING_MODE_SHIFT); | |
464 | bits |= GI_INDEX_PHASE((mode >> NI_GPCT_INDEX_PHASE_BITSHIFT)); | |
3d34023a | 465 | if (mode & NI_GPCT_INDEX_ENABLE_BIT) |
ed404871 | 466 | bits |= GI_INDEX_MODE; |
fca7c1d7 | 467 | ni_tio_set_bits(counter, NITIO_CNT_MODE_REG(cidx), |
ed404871 HS |
468 | GI_CNT_MODE_MASK | GI_INDEX_PHASE_MASK | |
469 | GI_INDEX_MODE, bits); | |
cb7859a9 FMH |
470 | ni_tio_set_sync_mode(counter, 0); |
471 | } | |
472 | ||
b9a09764 HS |
473 | ni_tio_set_bits(counter, NITIO_CMD_REG(cidx), GI_CNT_DIR_MASK, |
474 | GI_CNT_DIR(mode >> NI_GPCT_COUNTING_DIRECTION_SHIFT)); | |
cb7859a9 | 475 | |
3d34023a | 476 | if (mode & NI_GPCT_OR_GATE_BIT) |
c2c6c288 | 477 | input_select_bits |= GI_OR_GATE; |
3d34023a | 478 | if (mode & NI_GPCT_INVERT_OUTPUT_BIT) |
c2c6c288 | 479 | input_select_bits |= GI_OUTPUT_POL_INVERT; |
fca7c1d7 | 480 | ni_tio_set_bits(counter, NITIO_INPUT_SEL_REG(cidx), |
c2c6c288 HS |
481 | GI_GATE_SEL_LOAD_SRC | GI_OR_GATE | |
482 | GI_OUTPUT_POL_INVERT, input_select_bits); | |
cb7859a9 FMH |
483 | |
484 | return 0; | |
485 | } | |
486 | ||
487 | int ni_tio_arm(struct ni_gpct *counter, int arm, unsigned start_trigger) | |
488 | { | |
489 | struct ni_gpct_device *counter_dev = counter->counter_dev; | |
fca7c1d7 | 490 | unsigned cidx = counter->counter_index; |
cb7859a9 FMH |
491 | unsigned command_transient_bits = 0; |
492 | ||
493 | if (arm) { | |
494 | switch (start_trigger) { | |
495 | case NI_GPCT_ARM_IMMEDIATE: | |
b9a09764 | 496 | command_transient_bits |= GI_ARM; |
cb7859a9 FMH |
497 | break; |
498 | case NI_GPCT_ARM_PAIRED_IMMEDIATE: | |
b9a09764 | 499 | command_transient_bits |= GI_ARM | GI_ARM_COPY; |
cb7859a9 FMH |
500 | break; |
501 | default: | |
502 | break; | |
503 | } | |
504 | if (ni_tio_counting_mode_registers_present(counter_dev)) { | |
ed404871 HS |
505 | unsigned bits = 0; |
506 | unsigned sel_mask; | |
507 | ||
508 | sel_mask = GI_HW_ARM_SEL_MASK(counter_dev->variant); | |
cb7859a9 FMH |
509 | |
510 | switch (start_trigger) { | |
511 | case NI_GPCT_ARM_IMMEDIATE: | |
512 | case NI_GPCT_ARM_PAIRED_IMMEDIATE: | |
513 | break; | |
514 | default: | |
515 | if (start_trigger & NI_GPCT_ARM_UNKNOWN) { | |
14f194a9 HS |
516 | /* |
517 | * pass-through the least significant | |
518 | * bits so we can figure out what | |
519 | * select later | |
520 | */ | |
ed404871 HS |
521 | bits |= GI_HW_ARM_ENA | |
522 | (GI_HW_ARM_SEL(start_trigger) & | |
523 | sel_mask); | |
cb7859a9 FMH |
524 | } else { |
525 | return -EINVAL; | |
526 | } | |
527 | break; | |
528 | } | |
fca7c1d7 | 529 | ni_tio_set_bits(counter, NITIO_CNT_MODE_REG(cidx), |
ed404871 | 530 | GI_HW_ARM_ENA | sel_mask, bits); |
cb7859a9 FMH |
531 | } |
532 | } else { | |
b9a09764 | 533 | command_transient_bits |= GI_DISARM; |
cb7859a9 | 534 | } |
fca7c1d7 | 535 | ni_tio_set_bits_transient(counter, NITIO_CMD_REG(cidx), |
0a85b6f0 | 536 | 0, 0, command_transient_bits); |
cb7859a9 FMH |
537 | return 0; |
538 | } | |
3d34023a | 539 | EXPORT_SYMBOL_GPL(ni_tio_arm); |
cb7859a9 | 540 | |
3e90b1c7 | 541 | static unsigned ni_660x_clk_src(unsigned int clock_source) |
cb7859a9 | 542 | { |
463daa7f | 543 | unsigned clk_src = clock_source & NI_GPCT_CLOCK_SRC_SELECT_MASK; |
cb7859a9 FMH |
544 | unsigned ni_660x_clock; |
545 | unsigned i; | |
cb7859a9 | 546 | |
463daa7f | 547 | switch (clk_src) { |
cb7859a9 | 548 | case NI_GPCT_TIMEBASE_1_CLOCK_SRC_BITS: |
b8e58af6 | 549 | ni_660x_clock = NI_660X_TIMEBASE_1_CLK; |
cb7859a9 FMH |
550 | break; |
551 | case NI_GPCT_TIMEBASE_2_CLOCK_SRC_BITS: | |
b8e58af6 | 552 | ni_660x_clock = NI_660X_TIMEBASE_2_CLK; |
cb7859a9 FMH |
553 | break; |
554 | case NI_GPCT_TIMEBASE_3_CLOCK_SRC_BITS: | |
b8e58af6 | 555 | ni_660x_clock = NI_660X_TIMEBASE_3_CLK; |
cb7859a9 FMH |
556 | break; |
557 | case NI_GPCT_LOGIC_LOW_CLOCK_SRC_BITS: | |
b8e58af6 | 558 | ni_660x_clock = NI_660X_LOGIC_LOW_CLK; |
cb7859a9 FMH |
559 | break; |
560 | case NI_GPCT_SOURCE_PIN_i_CLOCK_SRC_BITS: | |
b8e58af6 | 561 | ni_660x_clock = NI_660X_SRC_PIN_I_CLK; |
cb7859a9 FMH |
562 | break; |
563 | case NI_GPCT_NEXT_GATE_CLOCK_SRC_BITS: | |
b8e58af6 | 564 | ni_660x_clock = NI_660X_NEXT_GATE_CLK; |
cb7859a9 FMH |
565 | break; |
566 | case NI_GPCT_NEXT_TC_CLOCK_SRC_BITS: | |
b8e58af6 | 567 | ni_660x_clock = NI_660X_NEXT_TC_CLK; |
cb7859a9 FMH |
568 | break; |
569 | default: | |
eca7d872 | 570 | for (i = 0; i <= NI_660X_MAX_RTSI_CHAN; ++i) { |
463daa7f | 571 | if (clk_src == NI_GPCT_RTSI_CLOCK_SRC_BITS(i)) { |
288cb1a8 | 572 | ni_660x_clock = NI_660X_RTSI_CLK(i); |
cb7859a9 FMH |
573 | break; |
574 | } | |
575 | } | |
eca7d872 | 576 | if (i <= NI_660X_MAX_RTSI_CHAN) |
cb7859a9 | 577 | break; |
eca7d872 | 578 | for (i = 0; i <= NI_660X_MAX_SRC_PIN; ++i) { |
463daa7f | 579 | if (clk_src == NI_GPCT_SOURCE_PIN_CLOCK_SRC_BITS(i)) { |
cdf4fce4 | 580 | ni_660x_clock = NI_660X_SRC_PIN_CLK(i); |
cb7859a9 FMH |
581 | break; |
582 | } | |
583 | } | |
eca7d872 | 584 | if (i <= NI_660X_MAX_SRC_PIN) |
cb7859a9 FMH |
585 | break; |
586 | ni_660x_clock = 0; | |
587 | BUG(); | |
588 | break; | |
589 | } | |
c2c6c288 | 590 | return GI_SRC_SEL(ni_660x_clock); |
cb7859a9 FMH |
591 | } |
592 | ||
3e90b1c7 | 593 | static unsigned ni_m_clk_src(unsigned int clock_source) |
cb7859a9 | 594 | { |
99065954 | 595 | unsigned clk_src = clock_source & NI_GPCT_CLOCK_SRC_SELECT_MASK; |
cb7859a9 FMH |
596 | unsigned ni_m_series_clock; |
597 | unsigned i; | |
99065954 HS |
598 | |
599 | switch (clk_src) { | |
cb7859a9 | 600 | case NI_GPCT_TIMEBASE_1_CLOCK_SRC_BITS: |
c93a7406 | 601 | ni_m_series_clock = NI_M_TIMEBASE_1_CLK; |
cb7859a9 FMH |
602 | break; |
603 | case NI_GPCT_TIMEBASE_2_CLOCK_SRC_BITS: | |
c93a7406 | 604 | ni_m_series_clock = NI_M_TIMEBASE_2_CLK; |
cb7859a9 FMH |
605 | break; |
606 | case NI_GPCT_TIMEBASE_3_CLOCK_SRC_BITS: | |
c93a7406 | 607 | ni_m_series_clock = NI_M_TIMEBASE_3_CLK; |
cb7859a9 FMH |
608 | break; |
609 | case NI_GPCT_LOGIC_LOW_CLOCK_SRC_BITS: | |
c93a7406 | 610 | ni_m_series_clock = NI_M_LOGIC_LOW_CLK; |
cb7859a9 FMH |
611 | break; |
612 | case NI_GPCT_NEXT_GATE_CLOCK_SRC_BITS: | |
c93a7406 | 613 | ni_m_series_clock = NI_M_NEXT_GATE_CLK; |
cb7859a9 FMH |
614 | break; |
615 | case NI_GPCT_NEXT_TC_CLOCK_SRC_BITS: | |
c93a7406 | 616 | ni_m_series_clock = NI_M_NEXT_TC_CLK; |
cb7859a9 FMH |
617 | break; |
618 | case NI_GPCT_PXI10_CLOCK_SRC_BITS: | |
c93a7406 | 619 | ni_m_series_clock = NI_M_PXI10_CLK; |
cb7859a9 FMH |
620 | break; |
621 | case NI_GPCT_PXI_STAR_TRIGGER_CLOCK_SRC_BITS: | |
c93a7406 | 622 | ni_m_series_clock = NI_M_PXI_STAR_TRIGGER_CLK; |
cb7859a9 FMH |
623 | break; |
624 | case NI_GPCT_ANALOG_TRIGGER_OUT_CLOCK_SRC_BITS: | |
c93a7406 | 625 | ni_m_series_clock = NI_M_ANALOG_TRIGGER_OUT_CLK; |
cb7859a9 FMH |
626 | break; |
627 | default: | |
eca7d872 | 628 | for (i = 0; i <= NI_M_MAX_RTSI_CHAN; ++i) { |
99065954 | 629 | if (clk_src == NI_GPCT_RTSI_CLOCK_SRC_BITS(i)) { |
9f9d6446 | 630 | ni_m_series_clock = NI_M_RTSI_CLK(i); |
cb7859a9 FMH |
631 | break; |
632 | } | |
633 | } | |
eca7d872 | 634 | if (i <= NI_M_MAX_RTSI_CHAN) |
cb7859a9 | 635 | break; |
eca7d872 | 636 | for (i = 0; i <= NI_M_MAX_PFI_CHAN; ++i) { |
99065954 | 637 | if (clk_src == NI_GPCT_PFI_CLOCK_SRC_BITS(i)) { |
1649d56d | 638 | ni_m_series_clock = NI_M_PFI_CLK(i); |
cb7859a9 FMH |
639 | break; |
640 | } | |
641 | } | |
eca7d872 | 642 | if (i <= NI_M_MAX_PFI_CHAN) |
cb7859a9 | 643 | break; |
0748e362 | 644 | pr_err("invalid clock source 0x%lx\n", |
0a85b6f0 | 645 | (unsigned long)clock_source); |
cb7859a9 FMH |
646 | BUG(); |
647 | ni_m_series_clock = 0; | |
648 | break; | |
649 | } | |
c2c6c288 | 650 | return GI_SRC_SEL(ni_m_series_clock); |
cb7859a9 FMH |
651 | }; |
652 | ||
653 | static void ni_tio_set_source_subselect(struct ni_gpct *counter, | |
0a85b6f0 | 654 | unsigned int clock_source) |
cb7859a9 FMH |
655 | { |
656 | struct ni_gpct_device *counter_dev = counter->counter_dev; | |
fca7c1d7 HS |
657 | unsigned cidx = counter->counter_index; |
658 | const unsigned second_gate_reg = NITIO_GATE2_REG(cidx); | |
cb7859a9 FMH |
659 | |
660 | if (counter_dev->variant != ni_gpct_variant_m_series) | |
661 | return; | |
662 | switch (clock_source & NI_GPCT_CLOCK_SRC_SELECT_MASK) { | |
663 | /* Gi_Source_Subselect is zero */ | |
664 | case NI_GPCT_NEXT_GATE_CLOCK_SRC_BITS: | |
665 | case NI_GPCT_TIMEBASE_3_CLOCK_SRC_BITS: | |
4359dcf3 | 666 | counter_dev->regs[second_gate_reg] &= ~GI_SRC_SUBSEL; |
cb7859a9 FMH |
667 | break; |
668 | /* Gi_Source_Subselect is one */ | |
669 | case NI_GPCT_ANALOG_TRIGGER_OUT_CLOCK_SRC_BITS: | |
670 | case NI_GPCT_PXI_STAR_TRIGGER_CLOCK_SRC_BITS: | |
4359dcf3 | 671 | counter_dev->regs[second_gate_reg] |= GI_SRC_SUBSEL; |
cb7859a9 FMH |
672 | break; |
673 | /* Gi_Source_Subselect doesn't matter */ | |
674 | default: | |
675 | return; | |
cb7859a9 FMH |
676 | } |
677 | write_register(counter, counter_dev->regs[second_gate_reg], | |
0a85b6f0 | 678 | second_gate_reg); |
cb7859a9 FMH |
679 | } |
680 | ||
681 | static int ni_tio_set_clock_src(struct ni_gpct *counter, | |
0a85b6f0 MT |
682 | unsigned int clock_source, |
683 | unsigned int period_ns) | |
cb7859a9 FMH |
684 | { |
685 | struct ni_gpct_device *counter_dev = counter->counter_dev; | |
fca7c1d7 | 686 | unsigned cidx = counter->counter_index; |
3e90b1c7 | 687 | unsigned bits = 0; |
cb7859a9 | 688 | |
3e90b1c7 | 689 | /* FIXME: validate clock source */ |
cb7859a9 FMH |
690 | switch (counter_dev->variant) { |
691 | case ni_gpct_variant_660x: | |
3e90b1c7 | 692 | bits |= ni_660x_clk_src(clock_source); |
cb7859a9 FMH |
693 | break; |
694 | case ni_gpct_variant_e_series: | |
695 | case ni_gpct_variant_m_series: | |
85603161 | 696 | default: |
3e90b1c7 | 697 | bits |= ni_m_clk_src(clock_source); |
cb7859a9 | 698 | break; |
cb7859a9 FMH |
699 | } |
700 | if (clock_source & NI_GPCT_INVERT_CLOCK_SRC_BIT) | |
c2c6c288 | 701 | bits |= GI_SRC_POL_INVERT; |
fca7c1d7 | 702 | ni_tio_set_bits(counter, NITIO_INPUT_SEL_REG(cidx), |
c2c6c288 | 703 | GI_SRC_SEL_MASK | GI_SRC_POL_INVERT, bits); |
cb7859a9 | 704 | ni_tio_set_source_subselect(counter, clock_source); |
cb7859a9 | 705 | |
3e90b1c7 HS |
706 | if (ni_tio_counting_mode_registers_present(counter_dev)) { |
707 | bits = 0; | |
708 | switch (clock_source & NI_GPCT_PRESCALE_MODE_CLOCK_SRC_MASK) { | |
cb7859a9 FMH |
709 | case NI_GPCT_NO_PRESCALE_CLOCK_SRC_BITS: |
710 | break; | |
711 | case NI_GPCT_PRESCALE_X2_CLOCK_SRC_BITS: | |
ed404871 | 712 | bits |= GI_PRESCALE_X2(counter_dev->variant); |
cb7859a9 FMH |
713 | break; |
714 | case NI_GPCT_PRESCALE_X8_CLOCK_SRC_BITS: | |
ed404871 | 715 | bits |= GI_PRESCALE_X8(counter_dev->variant); |
cb7859a9 FMH |
716 | break; |
717 | default: | |
718 | return -EINVAL; | |
cb7859a9 | 719 | } |
fca7c1d7 | 720 | ni_tio_set_bits(counter, NITIO_CNT_MODE_REG(cidx), |
ed404871 HS |
721 | GI_PRESCALE_X2(counter_dev->variant) | |
722 | GI_PRESCALE_X8(counter_dev->variant), bits); | |
cb7859a9 | 723 | } |
3e90b1c7 | 724 | counter->clock_period_ps = period_ns * 1000; |
cb7859a9 FMH |
725 | ni_tio_set_sync_mode(counter, 0); |
726 | return 0; | |
727 | } | |
728 | ||
cb7859a9 | 729 | static void ni_tio_get_clock_src(struct ni_gpct *counter, |
0a85b6f0 MT |
730 | unsigned int *clock_source, |
731 | unsigned int *period_ns) | |
cb7859a9 | 732 | { |
cb7859a9 | 733 | uint64_t temp64; |
f68d10c4 | 734 | |
cb7859a9 FMH |
735 | *clock_source = ni_tio_generic_clock_src_select(counter); |
736 | temp64 = ni_tio_clock_period_ps(counter, *clock_source); | |
f68d10c4 | 737 | do_div(temp64, 1000); /* ps to ns */ |
cb7859a9 FMH |
738 | *period_ns = temp64; |
739 | } | |
740 | ||
d54bb5a7 | 741 | static int ni_660x_set_gate(struct ni_gpct *counter, unsigned int gate_source) |
cb7859a9 | 742 | { |
e09dd2c3 | 743 | unsigned int chan = CR_CHAN(gate_source); |
fca7c1d7 | 744 | unsigned cidx = counter->counter_index; |
e09dd2c3 | 745 | unsigned gate_sel; |
cb7859a9 FMH |
746 | unsigned i; |
747 | ||
e09dd2c3 | 748 | switch (chan) { |
cb7859a9 | 749 | case NI_GPCT_NEXT_SOURCE_GATE_SELECT: |
5a3d1ed8 | 750 | gate_sel = NI_660X_NEXT_SRC_GATE_SEL; |
cb7859a9 FMH |
751 | break; |
752 | case NI_GPCT_NEXT_OUT_GATE_SELECT: | |
753 | case NI_GPCT_LOGIC_LOW_GATE_SELECT: | |
754 | case NI_GPCT_SOURCE_PIN_i_GATE_SELECT: | |
755 | case NI_GPCT_GATE_PIN_i_GATE_SELECT: | |
e09dd2c3 | 756 | gate_sel = chan & 0x1f; |
cb7859a9 FMH |
757 | break; |
758 | default: | |
eca7d872 | 759 | for (i = 0; i <= NI_660X_MAX_RTSI_CHAN; ++i) { |
e09dd2c3 HS |
760 | if (chan == NI_GPCT_RTSI_GATE_SELECT(i)) { |
761 | gate_sel = chan & 0x1f; | |
cb7859a9 FMH |
762 | break; |
763 | } | |
764 | } | |
eca7d872 | 765 | if (i <= NI_660X_MAX_RTSI_CHAN) |
cb7859a9 | 766 | break; |
eca7d872 | 767 | for (i = 0; i <= NI_660X_MAX_GATE_PIN; ++i) { |
e09dd2c3 HS |
768 | if (chan == NI_GPCT_GATE_PIN_GATE_SELECT(i)) { |
769 | gate_sel = chan & 0x1f; | |
cb7859a9 FMH |
770 | break; |
771 | } | |
772 | } | |
eca7d872 | 773 | if (i <= NI_660X_MAX_GATE_PIN) |
cb7859a9 FMH |
774 | break; |
775 | return -EINVAL; | |
cb7859a9 | 776 | } |
fca7c1d7 | 777 | ni_tio_set_bits(counter, NITIO_INPUT_SEL_REG(cidx), |
c2c6c288 | 778 | GI_GATE_SEL_MASK, GI_GATE_SEL(gate_sel)); |
cb7859a9 FMH |
779 | return 0; |
780 | } | |
781 | ||
d54bb5a7 | 782 | static int ni_m_set_gate(struct ni_gpct *counter, unsigned int gate_source) |
cb7859a9 | 783 | { |
7d2a6e54 | 784 | unsigned int chan = CR_CHAN(gate_source); |
fca7c1d7 | 785 | unsigned cidx = counter->counter_index; |
7d2a6e54 | 786 | unsigned gate_sel; |
cb7859a9 FMH |
787 | unsigned i; |
788 | ||
7d2a6e54 | 789 | switch (chan) { |
cb7859a9 FMH |
790 | case NI_GPCT_TIMESTAMP_MUX_GATE_SELECT: |
791 | case NI_GPCT_AI_START2_GATE_SELECT: | |
792 | case NI_GPCT_PXI_STAR_TRIGGER_GATE_SELECT: | |
793 | case NI_GPCT_NEXT_OUT_GATE_SELECT: | |
794 | case NI_GPCT_AI_START1_GATE_SELECT: | |
795 | case NI_GPCT_NEXT_SOURCE_GATE_SELECT: | |
796 | case NI_GPCT_ANALOG_TRIGGER_OUT_GATE_SELECT: | |
797 | case NI_GPCT_LOGIC_LOW_GATE_SELECT: | |
7d2a6e54 | 798 | gate_sel = chan & 0x1f; |
cb7859a9 FMH |
799 | break; |
800 | default: | |
eca7d872 | 801 | for (i = 0; i <= NI_M_MAX_RTSI_CHAN; ++i) { |
7d2a6e54 HS |
802 | if (chan == NI_GPCT_RTSI_GATE_SELECT(i)) { |
803 | gate_sel = chan & 0x1f; | |
cb7859a9 FMH |
804 | break; |
805 | } | |
806 | } | |
eca7d872 | 807 | if (i <= NI_M_MAX_RTSI_CHAN) |
cb7859a9 | 808 | break; |
eca7d872 | 809 | for (i = 0; i <= NI_M_MAX_PFI_CHAN; ++i) { |
7d2a6e54 HS |
810 | if (chan == NI_GPCT_PFI_GATE_SELECT(i)) { |
811 | gate_sel = chan & 0x1f; | |
cb7859a9 FMH |
812 | break; |
813 | } | |
814 | } | |
eca7d872 | 815 | if (i <= NI_M_MAX_PFI_CHAN) |
cb7859a9 FMH |
816 | break; |
817 | return -EINVAL; | |
cb7859a9 | 818 | } |
fca7c1d7 | 819 | ni_tio_set_bits(counter, NITIO_INPUT_SEL_REG(cidx), |
c2c6c288 | 820 | GI_GATE_SEL_MASK, GI_GATE_SEL(gate_sel)); |
cb7859a9 FMH |
821 | return 0; |
822 | } | |
823 | ||
d54bb5a7 | 824 | static int ni_660x_set_gate2(struct ni_gpct *counter, unsigned int gate_source) |
cb7859a9 FMH |
825 | { |
826 | struct ni_gpct_device *counter_dev = counter->counter_dev; | |
fca7c1d7 | 827 | unsigned cidx = counter->counter_index; |
55205053 HS |
828 | unsigned int chan = CR_CHAN(gate_source); |
829 | unsigned gate2_reg = NITIO_GATE2_REG(cidx); | |
830 | unsigned gate2_sel; | |
cb7859a9 FMH |
831 | unsigned i; |
832 | ||
55205053 | 833 | switch (chan) { |
cb7859a9 FMH |
834 | case NI_GPCT_SOURCE_PIN_i_GATE_SELECT: |
835 | case NI_GPCT_UP_DOWN_PIN_i_GATE_SELECT: | |
836 | case NI_GPCT_SELECTED_GATE_GATE_SELECT: | |
837 | case NI_GPCT_NEXT_OUT_GATE_SELECT: | |
838 | case NI_GPCT_LOGIC_LOW_GATE_SELECT: | |
55205053 | 839 | gate2_sel = chan & 0x1f; |
cb7859a9 FMH |
840 | break; |
841 | case NI_GPCT_NEXT_SOURCE_GATE_SELECT: | |
7e3e7591 | 842 | gate2_sel = NI_660X_NEXT_SRC_GATE2_SEL; |
cb7859a9 FMH |
843 | break; |
844 | default: | |
eca7d872 | 845 | for (i = 0; i <= NI_660X_MAX_RTSI_CHAN; ++i) { |
55205053 HS |
846 | if (chan == NI_GPCT_RTSI_GATE_SELECT(i)) { |
847 | gate2_sel = chan & 0x1f; | |
cb7859a9 FMH |
848 | break; |
849 | } | |
850 | } | |
eca7d872 | 851 | if (i <= NI_660X_MAX_RTSI_CHAN) |
cb7859a9 | 852 | break; |
eca7d872 | 853 | for (i = 0; i <= NI_660X_MAX_UP_DOWN_PIN; ++i) { |
55205053 HS |
854 | if (chan == NI_GPCT_UP_DOWN_PIN_GATE_SELECT(i)) { |
855 | gate2_sel = chan & 0x1f; | |
cb7859a9 FMH |
856 | break; |
857 | } | |
858 | } | |
eca7d872 | 859 | if (i <= NI_660X_MAX_UP_DOWN_PIN) |
cb7859a9 FMH |
860 | break; |
861 | return -EINVAL; | |
95cd17c9 | 862 | } |
4359dcf3 HS |
863 | counter_dev->regs[gate2_reg] |= GI_GATE2_MODE; |
864 | counter_dev->regs[gate2_reg] &= ~GI_GATE2_SEL_MASK; | |
865 | counter_dev->regs[gate2_reg] |= GI_GATE2_SEL(gate2_sel); | |
55205053 | 866 | write_register(counter, counter_dev->regs[gate2_reg], gate2_reg); |
cb7859a9 FMH |
867 | return 0; |
868 | } | |
869 | ||
d54bb5a7 | 870 | static int ni_m_set_gate2(struct ni_gpct *counter, unsigned int gate_source) |
cb7859a9 FMH |
871 | { |
872 | struct ni_gpct_device *counter_dev = counter->counter_dev; | |
fca7c1d7 | 873 | unsigned cidx = counter->counter_index; |
d54bb5a7 HS |
874 | unsigned int chan = CR_CHAN(gate_source); |
875 | unsigned gate2_reg = NITIO_GATE2_REG(cidx); | |
876 | unsigned gate2_sel; | |
cb7859a9 | 877 | |
14f194a9 HS |
878 | /* |
879 | * FIXME: We don't know what the m-series second gate codes are, | |
880 | * so we'll just pass the bits through for now. | |
881 | */ | |
d54bb5a7 | 882 | switch (chan) { |
cb7859a9 | 883 | default: |
d54bb5a7 | 884 | gate2_sel = chan & 0x1f; |
cb7859a9 | 885 | break; |
95cd17c9 | 886 | } |
4359dcf3 HS |
887 | counter_dev->regs[gate2_reg] |= GI_GATE2_MODE; |
888 | counter_dev->regs[gate2_reg] &= ~GI_GATE2_SEL_MASK; | |
889 | counter_dev->regs[gate2_reg] |= GI_GATE2_SEL(gate2_sel); | |
d54bb5a7 | 890 | write_register(counter, counter_dev->regs[gate2_reg], gate2_reg); |
cb7859a9 FMH |
891 | return 0; |
892 | } | |
893 | ||
894 | int ni_tio_set_gate_src(struct ni_gpct *counter, unsigned gate_index, | |
0a85b6f0 | 895 | unsigned int gate_source) |
cb7859a9 FMH |
896 | { |
897 | struct ni_gpct_device *counter_dev = counter->counter_dev; | |
fca7c1d7 | 898 | unsigned cidx = counter->counter_index; |
d54bb5a7 HS |
899 | unsigned int chan = CR_CHAN(gate_source); |
900 | unsigned gate2_reg = NITIO_GATE2_REG(cidx); | |
7d9e68d3 | 901 | unsigned mode = 0; |
cb7859a9 FMH |
902 | |
903 | switch (gate_index) { | |
904 | case 0: | |
d54bb5a7 | 905 | if (chan == NI_GPCT_DISABLED_GATE_SELECT) { |
fca7c1d7 | 906 | ni_tio_set_bits(counter, NITIO_MODE_REG(cidx), |
36d80f4a HS |
907 | GI_GATING_MODE_MASK, |
908 | GI_GATING_DISABLED); | |
cb7859a9 FMH |
909 | return 0; |
910 | } | |
7d9e68d3 | 911 | if (gate_source & CR_INVERT) |
36d80f4a | 912 | mode |= GI_GATE_POL_INVERT; |
7d9e68d3 | 913 | if (gate_source & CR_EDGE) |
36d80f4a | 914 | mode |= GI_RISING_EDGE_GATING; |
7d9e68d3 | 915 | else |
36d80f4a | 916 | mode |= GI_LEVEL_GATING; |
7d9e68d3 | 917 | ni_tio_set_bits(counter, NITIO_MODE_REG(cidx), |
36d80f4a | 918 | GI_GATE_POL_INVERT | GI_GATING_MODE_MASK, |
7d9e68d3 | 919 | mode); |
cb7859a9 FMH |
920 | switch (counter_dev->variant) { |
921 | case ni_gpct_variant_e_series: | |
922 | case ni_gpct_variant_m_series: | |
85603161 | 923 | default: |
d54bb5a7 | 924 | return ni_m_set_gate(counter, gate_source); |
cb7859a9 | 925 | case ni_gpct_variant_660x: |
d54bb5a7 | 926 | return ni_660x_set_gate(counter, gate_source); |
cb7859a9 FMH |
927 | } |
928 | break; | |
929 | case 1: | |
dba0f57f | 930 | if (!ni_tio_has_gate2_registers(counter_dev)) |
cb7859a9 | 931 | return -EINVAL; |
dba0f57f | 932 | |
d54bb5a7 | 933 | if (chan == NI_GPCT_DISABLED_GATE_SELECT) { |
4359dcf3 | 934 | counter_dev->regs[gate2_reg] &= ~GI_GATE2_MODE; |
d54bb5a7 HS |
935 | write_register(counter, counter_dev->regs[gate2_reg], |
936 | gate2_reg); | |
cb7859a9 FMH |
937 | return 0; |
938 | } | |
4359dcf3 HS |
939 | if (gate_source & CR_INVERT) |
940 | counter_dev->regs[gate2_reg] |= GI_GATE2_POL_INVERT; | |
941 | else | |
942 | counter_dev->regs[gate2_reg] &= ~GI_GATE2_POL_INVERT; | |
cb7859a9 FMH |
943 | switch (counter_dev->variant) { |
944 | case ni_gpct_variant_m_series: | |
d54bb5a7 | 945 | return ni_m_set_gate2(counter, gate_source); |
cb7859a9 | 946 | case ni_gpct_variant_660x: |
d54bb5a7 | 947 | return ni_660x_set_gate2(counter, gate_source); |
cb7859a9 FMH |
948 | default: |
949 | BUG(); | |
950 | break; | |
951 | } | |
952 | break; | |
953 | default: | |
954 | return -EINVAL; | |
cb7859a9 FMH |
955 | } |
956 | return 0; | |
957 | } | |
3d34023a | 958 | EXPORT_SYMBOL_GPL(ni_tio_set_gate_src); |
cb7859a9 FMH |
959 | |
960 | static int ni_tio_set_other_src(struct ni_gpct *counter, unsigned index, | |
0a85b6f0 | 961 | unsigned int source) |
cb7859a9 FMH |
962 | { |
963 | struct ni_gpct_device *counter_dev = counter->counter_dev; | |
fca7c1d7 | 964 | unsigned cidx = counter->counter_index; |
bf4ec095 | 965 | unsigned int abz_reg, shift, mask; |
cb7859a9 | 966 | |
bf4ec095 HS |
967 | if (counter_dev->variant != ni_gpct_variant_m_series) |
968 | return -EINVAL; | |
cb7859a9 | 969 | |
bf4ec095 HS |
970 | abz_reg = NITIO_ABZ_REG(cidx); |
971 | switch (index) { | |
972 | case NI_GPCT_SOURCE_ENCODER_A: | |
973 | shift = 10; | |
974 | break; | |
975 | case NI_GPCT_SOURCE_ENCODER_B: | |
976 | shift = 5; | |
977 | break; | |
978 | case NI_GPCT_SOURCE_ENCODER_Z: | |
979 | shift = 0; | |
980 | break; | |
981 | default: | |
982 | return -EINVAL; | |
cb7859a9 | 983 | } |
bf4ec095 HS |
984 | mask = 0x1f << shift; |
985 | if (source > 0x1f) | |
986 | source = 0x1f; /* Disable gate */ | |
987 | ||
988 | counter_dev->regs[abz_reg] &= ~mask; | |
989 | counter_dev->regs[abz_reg] |= (source << shift) & mask; | |
990 | write_register(counter, counter_dev->regs[abz_reg], abz_reg); | |
991 | return 0; | |
cb7859a9 FMH |
992 | } |
993 | ||
d00193be | 994 | static unsigned ni_660x_gate_to_generic_gate(unsigned gate) |
cb7859a9 FMH |
995 | { |
996 | unsigned i; | |
997 | ||
d00193be | 998 | switch (gate) { |
5a3d1ed8 | 999 | case NI_660X_SRC_PIN_I_GATE_SEL: |
cb7859a9 | 1000 | return NI_GPCT_SOURCE_PIN_i_GATE_SELECT; |
5a3d1ed8 | 1001 | case NI_660X_GATE_PIN_I_GATE_SEL: |
cb7859a9 | 1002 | return NI_GPCT_GATE_PIN_i_GATE_SELECT; |
5a3d1ed8 | 1003 | case NI_660X_NEXT_SRC_GATE_SEL: |
cb7859a9 | 1004 | return NI_GPCT_NEXT_SOURCE_GATE_SELECT; |
5a3d1ed8 | 1005 | case NI_660X_NEXT_OUT_GATE_SEL: |
cb7859a9 | 1006 | return NI_GPCT_NEXT_OUT_GATE_SELECT; |
5a3d1ed8 | 1007 | case NI_660X_LOGIC_LOW_GATE_SEL: |
cb7859a9 | 1008 | return NI_GPCT_LOGIC_LOW_GATE_SELECT; |
cb7859a9 | 1009 | default: |
eca7d872 | 1010 | for (i = 0; i <= NI_660X_MAX_RTSI_CHAN; ++i) { |
d00193be | 1011 | if (gate == NI_660X_RTSI_GATE_SEL(i)) |
cb7859a9 | 1012 | return NI_GPCT_RTSI_GATE_SELECT(i); |
cb7859a9 | 1013 | } |
eca7d872 | 1014 | for (i = 0; i <= NI_660X_MAX_GATE_PIN; ++i) { |
d00193be | 1015 | if (gate == NI_660X_PIN_GATE_SEL(i)) |
cb7859a9 | 1016 | return NI_GPCT_GATE_PIN_GATE_SELECT(i); |
cb7859a9 | 1017 | } |
cb7859a9 FMH |
1018 | BUG(); |
1019 | break; | |
1020 | } | |
1021 | return 0; | |
1022 | }; | |
1023 | ||
d00193be | 1024 | static unsigned ni_m_gate_to_generic_gate(unsigned gate) |
cb7859a9 FMH |
1025 | { |
1026 | unsigned i; | |
1027 | ||
d00193be | 1028 | switch (gate) { |
390db7a3 | 1029 | case NI_M_TIMESTAMP_MUX_GATE_SEL: |
cb7859a9 | 1030 | return NI_GPCT_TIMESTAMP_MUX_GATE_SELECT; |
390db7a3 | 1031 | case NI_M_AI_START2_GATE_SEL: |
cb7859a9 | 1032 | return NI_GPCT_AI_START2_GATE_SELECT; |
390db7a3 | 1033 | case NI_M_PXI_STAR_TRIGGER_GATE_SEL: |
cb7859a9 | 1034 | return NI_GPCT_PXI_STAR_TRIGGER_GATE_SELECT; |
390db7a3 | 1035 | case NI_M_NEXT_OUT_GATE_SEL: |
cb7859a9 | 1036 | return NI_GPCT_NEXT_OUT_GATE_SELECT; |
390db7a3 | 1037 | case NI_M_AI_START1_GATE_SEL: |
cb7859a9 | 1038 | return NI_GPCT_AI_START1_GATE_SELECT; |
390db7a3 | 1039 | case NI_M_NEXT_SRC_GATE_SEL: |
cb7859a9 | 1040 | return NI_GPCT_NEXT_SOURCE_GATE_SELECT; |
390db7a3 | 1041 | case NI_M_ANALOG_TRIG_OUT_GATE_SEL: |
cb7859a9 | 1042 | return NI_GPCT_ANALOG_TRIGGER_OUT_GATE_SELECT; |
390db7a3 | 1043 | case NI_M_LOGIC_LOW_GATE_SEL: |
cb7859a9 | 1044 | return NI_GPCT_LOGIC_LOW_GATE_SELECT; |
cb7859a9 | 1045 | default: |
eca7d872 | 1046 | for (i = 0; i <= NI_M_MAX_RTSI_CHAN; ++i) { |
d00193be | 1047 | if (gate == NI_M_RTSI_GATE_SEL(i)) |
cb7859a9 | 1048 | return NI_GPCT_RTSI_GATE_SELECT(i); |
cb7859a9 | 1049 | } |
eca7d872 | 1050 | for (i = 0; i <= NI_M_MAX_PFI_CHAN; ++i) { |
d00193be | 1051 | if (gate == NI_M_PFI_GATE_SEL(i)) |
cb7859a9 | 1052 | return NI_GPCT_PFI_GATE_SELECT(i); |
cb7859a9 | 1053 | } |
cb7859a9 FMH |
1054 | BUG(); |
1055 | break; | |
1056 | } | |
1057 | return 0; | |
1058 | }; | |
1059 | ||
d00193be | 1060 | static unsigned ni_660x_gate2_to_generic_gate(unsigned gate) |
cb7859a9 FMH |
1061 | { |
1062 | unsigned i; | |
1063 | ||
d00193be | 1064 | switch (gate) { |
7e3e7591 | 1065 | case NI_660X_SRC_PIN_I_GATE2_SEL: |
cb7859a9 | 1066 | return NI_GPCT_SOURCE_PIN_i_GATE_SELECT; |
7e3e7591 | 1067 | case NI_660X_UD_PIN_I_GATE2_SEL: |
cb7859a9 | 1068 | return NI_GPCT_UP_DOWN_PIN_i_GATE_SELECT; |
7e3e7591 | 1069 | case NI_660X_NEXT_SRC_GATE2_SEL: |
cb7859a9 | 1070 | return NI_GPCT_NEXT_SOURCE_GATE_SELECT; |
7e3e7591 | 1071 | case NI_660X_NEXT_OUT_GATE2_SEL: |
cb7859a9 | 1072 | return NI_GPCT_NEXT_OUT_GATE_SELECT; |
7e3e7591 | 1073 | case NI_660X_SELECTED_GATE2_SEL: |
cb7859a9 | 1074 | return NI_GPCT_SELECTED_GATE_GATE_SELECT; |
7e3e7591 | 1075 | case NI_660X_LOGIC_LOW_GATE2_SEL: |
cb7859a9 | 1076 | return NI_GPCT_LOGIC_LOW_GATE_SELECT; |
cb7859a9 | 1077 | default: |
eca7d872 | 1078 | for (i = 0; i <= NI_660X_MAX_RTSI_CHAN; ++i) { |
d00193be | 1079 | if (gate == NI_660X_RTSI_GATE2_SEL(i)) |
cb7859a9 | 1080 | return NI_GPCT_RTSI_GATE_SELECT(i); |
cb7859a9 | 1081 | } |
eca7d872 | 1082 | for (i = 0; i <= NI_660X_MAX_UP_DOWN_PIN; ++i) { |
d00193be | 1083 | if (gate == NI_660X_UD_PIN_GATE2_SEL(i)) |
cb7859a9 | 1084 | return NI_GPCT_UP_DOWN_PIN_GATE_SELECT(i); |
cb7859a9 | 1085 | } |
cb7859a9 FMH |
1086 | BUG(); |
1087 | break; | |
1088 | } | |
1089 | return 0; | |
1090 | }; | |
1091 | ||
d00193be | 1092 | static unsigned ni_m_gate2_to_generic_gate(unsigned gate) |
cb7859a9 | 1093 | { |
14f194a9 HS |
1094 | /* |
1095 | * FIXME: the second gate sources for the m series are undocumented, | |
1096 | * so we just return the raw bits for now. | |
1097 | */ | |
d00193be | 1098 | switch (gate) { |
cb7859a9 | 1099 | default: |
d00193be | 1100 | return gate; |
cb7859a9 FMH |
1101 | } |
1102 | return 0; | |
1103 | }; | |
1104 | ||
1105 | static int ni_tio_get_gate_src(struct ni_gpct *counter, unsigned gate_index, | |
0a85b6f0 | 1106 | unsigned int *gate_source) |
cb7859a9 FMH |
1107 | { |
1108 | struct ni_gpct_device *counter_dev = counter->counter_dev; | |
fca7c1d7 | 1109 | unsigned cidx = counter->counter_index; |
d00193be HS |
1110 | unsigned mode = ni_tio_get_soft_copy(counter, NITIO_MODE_REG(cidx)); |
1111 | unsigned gate2_reg = NITIO_GATE2_REG(cidx); | |
c2c6c288 | 1112 | unsigned gate; |
cb7859a9 FMH |
1113 | |
1114 | switch (gate_index) { | |
1115 | case 0: | |
36d80f4a | 1116 | if ((mode & GI_GATING_MODE_MASK) == GI_GATING_DISABLED) { |
cb7859a9 FMH |
1117 | *gate_source = NI_GPCT_DISABLED_GATE_SELECT; |
1118 | return 0; | |
cb7859a9 | 1119 | } |
89660697 | 1120 | |
c2c6c288 HS |
1121 | gate = GI_BITS_TO_GATE(ni_tio_get_soft_copy(counter, |
1122 | NITIO_INPUT_SEL_REG(cidx))); | |
89660697 | 1123 | |
cb7859a9 FMH |
1124 | switch (counter_dev->variant) { |
1125 | case ni_gpct_variant_e_series: | |
1126 | case ni_gpct_variant_m_series: | |
85603161 | 1127 | default: |
c2c6c288 | 1128 | *gate_source = ni_m_gate_to_generic_gate(gate); |
cb7859a9 FMH |
1129 | break; |
1130 | case ni_gpct_variant_660x: | |
c2c6c288 | 1131 | *gate_source = ni_660x_gate_to_generic_gate(gate); |
cb7859a9 | 1132 | break; |
cb7859a9 | 1133 | } |
36d80f4a | 1134 | if (mode & GI_GATE_POL_INVERT) |
cb7859a9 | 1135 | *gate_source |= CR_INVERT; |
36d80f4a | 1136 | if ((mode & GI_GATING_MODE_MASK) != GI_LEVEL_GATING) |
cb7859a9 | 1137 | *gate_source |= CR_EDGE; |
cb7859a9 FMH |
1138 | break; |
1139 | case 1: | |
36d80f4a | 1140 | if ((mode & GI_GATING_MODE_MASK) == GI_GATING_DISABLED || |
4359dcf3 | 1141 | !(counter_dev->regs[gate2_reg] & GI_GATE2_MODE)) { |
cb7859a9 FMH |
1142 | *gate_source = NI_GPCT_DISABLED_GATE_SELECT; |
1143 | return 0; | |
cb7859a9 | 1144 | } |
89660697 | 1145 | |
4359dcf3 | 1146 | gate = GI_BITS_TO_GATE2(counter_dev->regs[gate2_reg]); |
d00193be | 1147 | |
cb7859a9 FMH |
1148 | switch (counter_dev->variant) { |
1149 | case ni_gpct_variant_e_series: | |
1150 | case ni_gpct_variant_m_series: | |
85603161 | 1151 | default: |
c2c6c288 | 1152 | *gate_source = ni_m_gate2_to_generic_gate(gate); |
cb7859a9 FMH |
1153 | break; |
1154 | case ni_gpct_variant_660x: | |
c2c6c288 | 1155 | *gate_source = ni_660x_gate2_to_generic_gate(gate); |
cb7859a9 | 1156 | break; |
cb7859a9 | 1157 | } |
4359dcf3 | 1158 | if (counter_dev->regs[gate2_reg] & GI_GATE2_POL_INVERT) |
cb7859a9 | 1159 | *gate_source |= CR_INVERT; |
cb7859a9 | 1160 | /* second gate can't have edge/level mode set independently */ |
36d80f4a | 1161 | if ((mode & GI_GATING_MODE_MASK) != GI_LEVEL_GATING) |
cb7859a9 | 1162 | *gate_source |= CR_EDGE; |
cb7859a9 FMH |
1163 | break; |
1164 | default: | |
1165 | return -EINVAL; | |
cb7859a9 FMH |
1166 | } |
1167 | return 0; | |
1168 | } | |
1169 | ||
cac04c0f HS |
1170 | int ni_tio_insn_config(struct comedi_device *dev, |
1171 | struct comedi_subdevice *s, | |
1172 | struct comedi_insn *insn, | |
1173 | unsigned int *data) | |
cb7859a9 | 1174 | { |
cac04c0f | 1175 | struct ni_gpct *counter = s->private; |
704c6dba HS |
1176 | unsigned cidx = counter->counter_index; |
1177 | unsigned status; | |
cac04c0f | 1178 | |
cb7859a9 FMH |
1179 | switch (data[0]) { |
1180 | case INSN_CONFIG_SET_COUNTER_MODE: | |
1181 | return ni_tio_set_counter_mode(counter, data[1]); | |
cb7859a9 FMH |
1182 | case INSN_CONFIG_ARM: |
1183 | return ni_tio_arm(counter, 1, data[1]); | |
cb7859a9 FMH |
1184 | case INSN_CONFIG_DISARM: |
1185 | ni_tio_arm(counter, 0, 0); | |
1186 | return 0; | |
cb7859a9 | 1187 | case INSN_CONFIG_GET_COUNTER_STATUS: |
704c6dba HS |
1188 | data[1] = 0; |
1189 | status = read_register(counter, NITIO_SHARED_STATUS_REG(cidx)); | |
24a675c5 | 1190 | if (status & GI_ARMED(cidx)) { |
704c6dba | 1191 | data[1] |= COMEDI_COUNTER_ARMED; |
24a675c5 | 1192 | if (status & GI_COUNTING(cidx)) |
704c6dba HS |
1193 | data[1] |= COMEDI_COUNTER_COUNTING; |
1194 | } | |
01ca8f97 | 1195 | data[2] = COMEDI_COUNTER_ARMED | COMEDI_COUNTER_COUNTING; |
cb7859a9 | 1196 | return 0; |
cb7859a9 FMH |
1197 | case INSN_CONFIG_SET_CLOCK_SRC: |
1198 | return ni_tio_set_clock_src(counter, data[1], data[2]); | |
cb7859a9 FMH |
1199 | case INSN_CONFIG_GET_CLOCK_SRC: |
1200 | ni_tio_get_clock_src(counter, &data[1], &data[2]); | |
1201 | return 0; | |
cb7859a9 FMH |
1202 | case INSN_CONFIG_SET_GATE_SRC: |
1203 | return ni_tio_set_gate_src(counter, data[1], data[2]); | |
cb7859a9 FMH |
1204 | case INSN_CONFIG_GET_GATE_SRC: |
1205 | return ni_tio_get_gate_src(counter, data[1], &data[2]); | |
cb7859a9 FMH |
1206 | case INSN_CONFIG_SET_OTHER_SRC: |
1207 | return ni_tio_set_other_src(counter, data[1], data[2]); | |
cb7859a9 FMH |
1208 | case INSN_CONFIG_RESET: |
1209 | ni_tio_reset_count_and_disarm(counter); | |
1210 | return 0; | |
cb7859a9 FMH |
1211 | default: |
1212 | break; | |
1213 | } | |
1214 | return -EINVAL; | |
1215 | } | |
3d34023a | 1216 | EXPORT_SYMBOL_GPL(ni_tio_insn_config); |
cb7859a9 | 1217 | |
27c4d23c HS |
1218 | static unsigned int ni_tio_read_sw_save_reg(struct comedi_device *dev, |
1219 | struct comedi_subdevice *s) | |
1220 | { | |
1221 | struct ni_gpct *counter = s->private; | |
1222 | unsigned cidx = counter->counter_index; | |
56bd1ac7 | 1223 | unsigned int val; |
27c4d23c | 1224 | |
b9a09764 | 1225 | ni_tio_set_bits(counter, NITIO_CMD_REG(cidx), GI_SAVE_TRACE, 0); |
27c4d23c | 1226 | ni_tio_set_bits(counter, NITIO_CMD_REG(cidx), |
b9a09764 | 1227 | GI_SAVE_TRACE, GI_SAVE_TRACE); |
27c4d23c HS |
1228 | |
1229 | /* | |
1230 | * The count doesn't get latched until the next clock edge, so it is | |
1231 | * possible the count may change (once) while we are reading. Since | |
1232 | * the read of the SW_Save_Reg isn't atomic (apparently even when it's | |
1233 | * a 32 bit register according to 660x docs), we need to read twice | |
1234 | * and make sure the reading hasn't changed. If it has, a third read | |
1235 | * will be correct since the count value will definitely have latched | |
1236 | * by then. | |
1237 | */ | |
56bd1ac7 HS |
1238 | val = read_register(counter, NITIO_SW_SAVE_REG(cidx)); |
1239 | if (val != read_register(counter, NITIO_SW_SAVE_REG(cidx))) | |
1240 | val = read_register(counter, NITIO_SW_SAVE_REG(cidx)); | |
1241 | ||
1242 | return val; | |
27c4d23c HS |
1243 | } |
1244 | ||
9014d816 HS |
1245 | int ni_tio_insn_read(struct comedi_device *dev, |
1246 | struct comedi_subdevice *s, | |
1247 | struct comedi_insn *insn, | |
1248 | unsigned int *data) | |
cb7859a9 | 1249 | { |
9014d816 | 1250 | struct ni_gpct *counter = s->private; |
cb7859a9 | 1251 | struct ni_gpct_device *counter_dev = counter->counter_dev; |
27c4d23c | 1252 | unsigned int channel = CR_CHAN(insn->chanspec); |
fca7c1d7 | 1253 | unsigned cidx = counter->counter_index; |
27c4d23c | 1254 | int i; |
cb7859a9 | 1255 | |
27c4d23c HS |
1256 | for (i = 0; i < insn->n; i++) { |
1257 | switch (channel) { | |
1258 | case 0: | |
1259 | data[i] = ni_tio_read_sw_save_reg(dev, s); | |
1260 | break; | |
1261 | case 1: | |
1262 | data[i] = counter_dev->regs[NITIO_LOADA_REG(cidx)]; | |
1263 | break; | |
1264 | case 2: | |
1265 | data[i] = counter_dev->regs[NITIO_LOADB_REG(cidx)]; | |
1266 | break; | |
1267 | } | |
95cd17c9 | 1268 | } |
27c4d23c | 1269 | return insn->n; |
cb7859a9 | 1270 | } |
9014d816 | 1271 | EXPORT_SYMBOL_GPL(ni_tio_insn_read); |
cb7859a9 FMH |
1272 | |
1273 | static unsigned ni_tio_next_load_register(struct ni_gpct *counter) | |
1274 | { | |
fca7c1d7 HS |
1275 | unsigned cidx = counter->counter_index; |
1276 | const unsigned bits = | |
1277 | read_register(counter, NITIO_SHARED_STATUS_REG(cidx)); | |
cb7859a9 | 1278 | |
24a675c5 | 1279 | return (bits & GI_NEXT_LOAD_SRC(cidx)) |
89660697 HS |
1280 | ? NITIO_LOADB_REG(cidx) |
1281 | : NITIO_LOADA_REG(cidx); | |
cb7859a9 FMH |
1282 | } |
1283 | ||
10f74377 HS |
1284 | int ni_tio_insn_write(struct comedi_device *dev, |
1285 | struct comedi_subdevice *s, | |
1286 | struct comedi_insn *insn, | |
1287 | unsigned int *data) | |
cb7859a9 | 1288 | { |
10f74377 | 1289 | struct ni_gpct *counter = s->private; |
cb7859a9 FMH |
1290 | struct ni_gpct_device *counter_dev = counter->counter_dev; |
1291 | const unsigned channel = CR_CHAN(insn->chanspec); | |
fca7c1d7 | 1292 | unsigned cidx = counter->counter_index; |
cb7859a9 FMH |
1293 | unsigned load_reg; |
1294 | ||
1295 | if (insn->n < 1) | |
1296 | return 0; | |
1297 | switch (channel) { | |
1298 | case 0: | |
14f194a9 HS |
1299 | /* |
1300 | * Unsafe if counter is armed. | |
1301 | * Should probably check status and return -EBUSY if armed. | |
1302 | */ | |
1303 | ||
1304 | /* | |
1305 | * Don't disturb load source select, just use whichever | |
1306 | * load register is already selected. | |
1307 | */ | |
cb7859a9 FMH |
1308 | load_reg = ni_tio_next_load_register(counter); |
1309 | write_register(counter, data[0], load_reg); | |
fca7c1d7 | 1310 | ni_tio_set_bits_transient(counter, NITIO_CMD_REG(cidx), |
b9a09764 | 1311 | 0, 0, GI_LOAD); |
14f194a9 | 1312 | /* restore load reg */ |
cb7859a9 FMH |
1313 | write_register(counter, counter_dev->regs[load_reg], load_reg); |
1314 | break; | |
1315 | case 1: | |
fca7c1d7 HS |
1316 | counter_dev->regs[NITIO_LOADA_REG(cidx)] = data[0]; |
1317 | write_register(counter, data[0], NITIO_LOADA_REG(cidx)); | |
cb7859a9 FMH |
1318 | break; |
1319 | case 2: | |
fca7c1d7 HS |
1320 | counter_dev->regs[NITIO_LOADB_REG(cidx)] = data[0]; |
1321 | write_register(counter, data[0], NITIO_LOADB_REG(cidx)); | |
cb7859a9 FMH |
1322 | break; |
1323 | default: | |
1324 | return -EINVAL; | |
cb7859a9 FMH |
1325 | } |
1326 | return 0; | |
1327 | } | |
10f74377 | 1328 | EXPORT_SYMBOL_GPL(ni_tio_insn_write); |
f688d4a7 | 1329 | |
25e529b0 HS |
1330 | void ni_tio_init_counter(struct ni_gpct *counter) |
1331 | { | |
1332 | struct ni_gpct_device *counter_dev = counter->counter_dev; | |
1333 | unsigned cidx = counter->counter_index; | |
1334 | ||
1335 | ni_tio_reset_count_and_disarm(counter); | |
1336 | ||
1337 | /* initialize counter registers */ | |
1338 | counter_dev->regs[NITIO_AUTO_INC_REG(cidx)] = 0x0; | |
1339 | write_register(counter, 0x0, NITIO_AUTO_INC_REG(cidx)); | |
1340 | ||
1341 | ni_tio_set_bits(counter, NITIO_CMD_REG(cidx), | |
b9a09764 | 1342 | ~0, GI_SYNC_GATE); |
25e529b0 HS |
1343 | |
1344 | ni_tio_set_bits(counter, NITIO_MODE_REG(cidx), ~0, 0); | |
1345 | ||
1346 | counter_dev->regs[NITIO_LOADA_REG(cidx)] = 0x0; | |
1347 | write_register(counter, 0x0, NITIO_LOADA_REG(cidx)); | |
1348 | ||
1349 | counter_dev->regs[NITIO_LOADB_REG(cidx)] = 0x0; | |
1350 | write_register(counter, 0x0, NITIO_LOADB_REG(cidx)); | |
1351 | ||
1352 | ni_tio_set_bits(counter, NITIO_INPUT_SEL_REG(cidx), ~0, 0); | |
1353 | ||
1354 | if (ni_tio_counting_mode_registers_present(counter_dev)) | |
1355 | ni_tio_set_bits(counter, NITIO_CNT_MODE_REG(cidx), ~0, 0); | |
1356 | ||
dba0f57f | 1357 | if (ni_tio_has_gate2_registers(counter_dev)) { |
25e529b0 HS |
1358 | counter_dev->regs[NITIO_GATE2_REG(cidx)] = 0x0; |
1359 | write_register(counter, 0x0, NITIO_GATE2_REG(cidx)); | |
1360 | } | |
1361 | ||
1362 | ni_tio_set_bits(counter, NITIO_DMA_CFG_REG(cidx), ~0, 0x0); | |
1363 | ||
1364 | ni_tio_set_bits(counter, NITIO_INT_ENA_REG(cidx), ~0, 0x0); | |
1365 | } | |
1366 | EXPORT_SYMBOL_GPL(ni_tio_init_counter); | |
1367 | ||
8477c5d4 HS |
1368 | struct ni_gpct_device * |
1369 | ni_gpct_device_construct(struct comedi_device *dev, | |
1370 | void (*write_register)(struct ni_gpct *counter, | |
1371 | unsigned bits, | |
1372 | enum ni_gpct_register reg), | |
1373 | unsigned (*read_register)(struct ni_gpct *counter, | |
1374 | enum ni_gpct_register reg), | |
1375 | enum ni_gpct_variant variant, | |
1376 | unsigned num_counters) | |
1377 | { | |
1378 | struct ni_gpct_device *counter_dev; | |
1379 | struct ni_gpct *counter; | |
1380 | unsigned i; | |
1381 | ||
1382 | if (num_counters == 0) | |
1383 | return NULL; | |
1384 | ||
1385 | counter_dev = kzalloc(sizeof(*counter_dev), GFP_KERNEL); | |
1386 | if (!counter_dev) | |
1387 | return NULL; | |
1388 | ||
1389 | counter_dev->dev = dev; | |
1390 | counter_dev->write_register = write_register; | |
1391 | counter_dev->read_register = read_register; | |
1392 | counter_dev->variant = variant; | |
1393 | ||
1394 | spin_lock_init(&counter_dev->regs_lock); | |
1395 | ||
1396 | counter_dev->counters = kcalloc(num_counters, sizeof(*counter), | |
1397 | GFP_KERNEL); | |
1398 | if (!counter_dev->counters) { | |
1399 | kfree(counter_dev); | |
1400 | return NULL; | |
1401 | } | |
1402 | ||
1403 | for (i = 0; i < num_counters; ++i) { | |
1404 | counter = &counter_dev->counters[i]; | |
1405 | counter->counter_dev = counter_dev; | |
1406 | spin_lock_init(&counter->lock); | |
1407 | } | |
1408 | counter_dev->num_counters = num_counters; | |
1409 | ||
1410 | return counter_dev; | |
1411 | } | |
1412 | EXPORT_SYMBOL_GPL(ni_gpct_device_construct); | |
1413 | ||
1414 | void ni_gpct_device_destroy(struct ni_gpct_device *counter_dev) | |
1415 | { | |
1416 | if (!counter_dev->counters) | |
1417 | return; | |
1418 | kfree(counter_dev->counters); | |
1419 | kfree(counter_dev); | |
1420 | } | |
1421 | EXPORT_SYMBOL_GPL(ni_gpct_device_destroy); | |
1422 | ||
f688d4a7 HS |
1423 | static int __init ni_tio_init_module(void) |
1424 | { | |
1425 | return 0; | |
1426 | } | |
1427 | module_init(ni_tio_init_module); | |
1428 | ||
1429 | static void __exit ni_tio_cleanup_module(void) | |
1430 | { | |
1431 | } | |
1432 | module_exit(ni_tio_cleanup_module); | |
1433 | ||
1434 | MODULE_AUTHOR("Comedi <comedi@comedi.org>"); | |
1435 | MODULE_DESCRIPTION("Comedi support for NI general-purpose counters"); | |
1436 | MODULE_LICENSE("GPL"); |