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. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with this program; if not, write to the Free Software | |
19 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
20 | */ | |
21 | ||
22 | /* | |
23 | Driver: ni_tio | |
24 | Description: National Instruments general purpose counters | |
25 | Devices: | |
26 | Author: J.P. Mellor <jpmellor@rose-hulman.edu>, | |
27 | Herman.Bruyninckx@mech.kuleuven.ac.be, | |
28 | Wim.Meeussen@mech.kuleuven.ac.be, | |
29 | Klaas.Gadeyne@mech.kuleuven.ac.be, | |
30 | Frank Mori Hess <fmhess@users.sourceforge.net> | |
31 | Updated: Thu Nov 16 09:50:32 EST 2006 | |
32 | Status: works | |
33 | ||
34 | This module is not used directly by end-users. Rather, it | |
35 | is used by other drivers (for example ni_660x and ni_pcimio) | |
36 | to provide support for NI's general purpose counters. It was | |
37 | originally based on the counter code from ni_660x.c and | |
38 | ni_mio_common.c. | |
39 | ||
40 | References: | |
41 | DAQ 660x Register-Level Programmer Manual (NI 370505A-01) | |
42 | DAQ 6601/6602 User Manual (NI 322137B-01) | |
43 | 340934b.pdf DAQ-STC reference manual | |
44 | ||
45 | */ | |
46 | /* | |
47 | TODO: | |
48 | Support use of both banks X and Y | |
49 | */ | |
50 | ||
51 | #include "ni_tio_internal.h" | |
52 | ||
53 | static uint64_t ni_tio_clock_period_ps(const struct ni_gpct *counter, | |
0a85b6f0 | 54 | unsigned generic_clock_source); |
cb7859a9 FMH |
55 | static unsigned ni_tio_generic_clock_src_select(const struct ni_gpct *counter); |
56 | ||
57 | MODULE_AUTHOR("Comedi <comedi@comedi.org>"); | |
58 | MODULE_DESCRIPTION("Comedi support for NI general-purpose counters"); | |
59 | MODULE_LICENSE("GPL"); | |
60 | ||
61 | static inline enum Gi_Counting_Mode_Reg_Bits Gi_Alternate_Sync_Bit(enum | |
0a85b6f0 MT |
62 | ni_gpct_variant |
63 | variant) | |
cb7859a9 FMH |
64 | { |
65 | switch (variant) { | |
66 | case ni_gpct_variant_e_series: | |
67 | return 0; | |
68 | break; | |
69 | case ni_gpct_variant_m_series: | |
70 | return Gi_M_Series_Alternate_Sync_Bit; | |
71 | break; | |
72 | case ni_gpct_variant_660x: | |
73 | return Gi_660x_Alternate_Sync_Bit; | |
74 | break; | |
75 | default: | |
76 | BUG(); | |
77 | break; | |
78 | } | |
79 | return 0; | |
80 | } | |
0a85b6f0 | 81 | |
cb7859a9 | 82 | static inline enum Gi_Counting_Mode_Reg_Bits Gi_Prescale_X2_Bit(enum |
0a85b6f0 MT |
83 | ni_gpct_variant |
84 | variant) | |
cb7859a9 FMH |
85 | { |
86 | switch (variant) { | |
87 | case ni_gpct_variant_e_series: | |
88 | return 0; | |
89 | break; | |
90 | case ni_gpct_variant_m_series: | |
91 | return Gi_M_Series_Prescale_X2_Bit; | |
92 | break; | |
93 | case ni_gpct_variant_660x: | |
94 | return Gi_660x_Prescale_X2_Bit; | |
95 | break; | |
96 | default: | |
97 | BUG(); | |
98 | break; | |
99 | } | |
100 | return 0; | |
101 | } | |
0a85b6f0 | 102 | |
cb7859a9 | 103 | static inline enum Gi_Counting_Mode_Reg_Bits Gi_Prescale_X8_Bit(enum |
0a85b6f0 MT |
104 | ni_gpct_variant |
105 | variant) | |
cb7859a9 FMH |
106 | { |
107 | switch (variant) { | |
108 | case ni_gpct_variant_e_series: | |
109 | return 0; | |
110 | break; | |
111 | case ni_gpct_variant_m_series: | |
112 | return Gi_M_Series_Prescale_X8_Bit; | |
113 | break; | |
114 | case ni_gpct_variant_660x: | |
115 | return Gi_660x_Prescale_X8_Bit; | |
116 | break; | |
117 | default: | |
118 | BUG(); | |
119 | break; | |
120 | } | |
121 | return 0; | |
122 | } | |
0a85b6f0 | 123 | |
cb7859a9 | 124 | static inline enum Gi_Counting_Mode_Reg_Bits Gi_HW_Arm_Select_Mask(enum |
0a85b6f0 MT |
125 | ni_gpct_variant |
126 | variant) | |
cb7859a9 FMH |
127 | { |
128 | switch (variant) { | |
129 | case ni_gpct_variant_e_series: | |
130 | return 0; | |
131 | break; | |
132 | case ni_gpct_variant_m_series: | |
133 | return Gi_M_Series_HW_Arm_Select_Mask; | |
134 | break; | |
135 | case ni_gpct_variant_660x: | |
136 | return Gi_660x_HW_Arm_Select_Mask; | |
137 | break; | |
138 | default: | |
139 | BUG(); | |
140 | break; | |
141 | } | |
142 | return 0; | |
143 | } | |
144 | ||
145 | /* clock sources for ni_660x boards, get bits with Gi_Source_Select_Bits() */ | |
146 | enum ni_660x_clock_source { | |
147 | NI_660x_Timebase_1_Clock = 0x0, /* 20MHz */ | |
148 | NI_660x_Source_Pin_i_Clock = 0x1, | |
149 | NI_660x_Next_Gate_Clock = 0xa, | |
150 | NI_660x_Timebase_2_Clock = 0x12, /* 100KHz */ | |
151 | NI_660x_Next_TC_Clock = 0x13, | |
152 | NI_660x_Timebase_3_Clock = 0x1e, /* 80MHz */ | |
153 | NI_660x_Logic_Low_Clock = 0x1f, | |
154 | }; | |
155 | static const unsigned ni_660x_max_rtsi_channel = 6; | |
156 | static inline unsigned NI_660x_RTSI_Clock(unsigned n) | |
157 | { | |
158 | BUG_ON(n > ni_660x_max_rtsi_channel); | |
dae0dc30 | 159 | return 0xb + n; |
cb7859a9 | 160 | } |
0a85b6f0 | 161 | |
cb7859a9 FMH |
162 | static const unsigned ni_660x_max_source_pin = 7; |
163 | static inline unsigned NI_660x_Source_Pin_Clock(unsigned n) | |
164 | { | |
165 | BUG_ON(n > ni_660x_max_source_pin); | |
dae0dc30 | 166 | return 0x2 + n; |
cb7859a9 FMH |
167 | } |
168 | ||
169 | /* clock sources for ni e and m series boards, get bits with Gi_Source_Select_Bits() */ | |
170 | enum ni_m_series_clock_source { | |
171 | NI_M_Series_Timebase_1_Clock = 0x0, /* 20MHz */ | |
172 | NI_M_Series_Timebase_2_Clock = 0x12, /* 100KHz */ | |
173 | NI_M_Series_Next_TC_Clock = 0x13, | |
174 | NI_M_Series_Next_Gate_Clock = 0x14, /* when Gi_Src_SubSelect = 0 */ | |
175 | NI_M_Series_PXI_Star_Trigger_Clock = 0x14, /* when Gi_Src_SubSelect = 1 */ | |
176 | NI_M_Series_PXI10_Clock = 0x1d, | |
177 | NI_M_Series_Timebase_3_Clock = 0x1e, /* 80MHz, when Gi_Src_SubSelect = 0 */ | |
178 | NI_M_Series_Analog_Trigger_Out_Clock = 0x1e, /* when Gi_Src_SubSelect = 1 */ | |
179 | NI_M_Series_Logic_Low_Clock = 0x1f, | |
180 | }; | |
181 | static const unsigned ni_m_series_max_pfi_channel = 15; | |
182 | static inline unsigned NI_M_Series_PFI_Clock(unsigned n) | |
183 | { | |
184 | BUG_ON(n > ni_m_series_max_pfi_channel); | |
185 | if (n < 10) | |
186 | return 1 + n; | |
187 | else | |
188 | return 0xb + n; | |
189 | } | |
0a85b6f0 | 190 | |
cb7859a9 FMH |
191 | static const unsigned ni_m_series_max_rtsi_channel = 7; |
192 | static inline unsigned NI_M_Series_RTSI_Clock(unsigned n) | |
193 | { | |
194 | BUG_ON(n > ni_m_series_max_rtsi_channel); | |
195 | if (n == 7) | |
196 | return 0x1b; | |
197 | else | |
198 | return 0xb + n; | |
199 | } | |
200 | ||
201 | enum ni_660x_gate_select { | |
202 | NI_660x_Source_Pin_i_Gate_Select = 0x0, | |
203 | NI_660x_Gate_Pin_i_Gate_Select = 0x1, | |
204 | NI_660x_Next_SRC_Gate_Select = 0xa, | |
205 | NI_660x_Next_Out_Gate_Select = 0x14, | |
206 | NI_660x_Logic_Low_Gate_Select = 0x1f, | |
207 | }; | |
208 | static const unsigned ni_660x_max_gate_pin = 7; | |
209 | static inline unsigned NI_660x_Gate_Pin_Gate_Select(unsigned n) | |
210 | { | |
211 | BUG_ON(n > ni_660x_max_gate_pin); | |
212 | return 0x2 + n; | |
213 | } | |
0a85b6f0 | 214 | |
cb7859a9 FMH |
215 | static inline unsigned NI_660x_RTSI_Gate_Select(unsigned n) |
216 | { | |
217 | BUG_ON(n > ni_660x_max_rtsi_channel); | |
218 | return 0xb + n; | |
219 | } | |
220 | ||
221 | enum ni_m_series_gate_select { | |
222 | NI_M_Series_Timestamp_Mux_Gate_Select = 0x0, | |
223 | NI_M_Series_AI_START2_Gate_Select = 0x12, | |
224 | NI_M_Series_PXI_Star_Trigger_Gate_Select = 0x13, | |
225 | NI_M_Series_Next_Out_Gate_Select = 0x14, | |
226 | NI_M_Series_AI_START1_Gate_Select = 0x1c, | |
227 | NI_M_Series_Next_SRC_Gate_Select = 0x1d, | |
228 | NI_M_Series_Analog_Trigger_Out_Gate_Select = 0x1e, | |
229 | NI_M_Series_Logic_Low_Gate_Select = 0x1f, | |
230 | }; | |
231 | static inline unsigned NI_M_Series_RTSI_Gate_Select(unsigned n) | |
232 | { | |
233 | BUG_ON(n > ni_m_series_max_rtsi_channel); | |
234 | if (n == 7) | |
235 | return 0x1b; | |
236 | return 0xb + n; | |
237 | } | |
0a85b6f0 | 238 | |
cb7859a9 FMH |
239 | static inline unsigned NI_M_Series_PFI_Gate_Select(unsigned n) |
240 | { | |
241 | BUG_ON(n > ni_m_series_max_pfi_channel); | |
242 | if (n < 10) | |
243 | return 1 + n; | |
244 | return 0xb + n; | |
245 | } | |
246 | ||
247 | static inline unsigned Gi_Source_Select_Bits(unsigned source) | |
248 | { | |
249 | return (source << Gi_Source_Select_Shift) & Gi_Source_Select_Mask; | |
250 | } | |
0a85b6f0 | 251 | |
cb7859a9 FMH |
252 | static inline unsigned Gi_Gate_Select_Bits(unsigned gate_select) |
253 | { | |
254 | return (gate_select << Gi_Gate_Select_Shift) & Gi_Gate_Select_Mask; | |
255 | } | |
256 | ||
257 | enum ni_660x_second_gate_select { | |
258 | NI_660x_Source_Pin_i_Second_Gate_Select = 0x0, | |
259 | NI_660x_Up_Down_Pin_i_Second_Gate_Select = 0x1, | |
260 | NI_660x_Next_SRC_Second_Gate_Select = 0xa, | |
261 | NI_660x_Next_Out_Second_Gate_Select = 0x14, | |
262 | NI_660x_Selected_Gate_Second_Gate_Select = 0x1e, | |
263 | NI_660x_Logic_Low_Second_Gate_Select = 0x1f, | |
264 | }; | |
265 | static const unsigned ni_660x_max_up_down_pin = 7; | |
266 | static inline unsigned NI_660x_Up_Down_Pin_Second_Gate_Select(unsigned n) | |
267 | { | |
268 | BUG_ON(n > ni_660x_max_up_down_pin); | |
269 | return 0x2 + n; | |
270 | } | |
0a85b6f0 | 271 | |
cb7859a9 FMH |
272 | static inline unsigned NI_660x_RTSI_Second_Gate_Select(unsigned n) |
273 | { | |
274 | BUG_ON(n > ni_660x_max_rtsi_channel); | |
275 | return 0xb + n; | |
276 | } | |
277 | ||
790c5541 | 278 | static const unsigned int counter_status_mask = |
0a85b6f0 | 279 | COMEDI_COUNTER_ARMED | COMEDI_COUNTER_COUNTING; |
cb7859a9 FMH |
280 | |
281 | static int __init ni_tio_init_module(void) | |
282 | { | |
283 | return 0; | |
284 | } | |
285 | ||
286 | module_init(ni_tio_init_module); | |
287 | ||
288 | static void __exit ni_tio_cleanup_module(void) | |
289 | { | |
290 | } | |
291 | ||
292 | module_exit(ni_tio_cleanup_module); | |
293 | ||
0a85b6f0 MT |
294 | struct ni_gpct_device *ni_gpct_device_construct(struct comedi_device *dev, |
295 | void (*write_register) (struct | |
296 | ni_gpct | |
297 | * | |
298 | counter, | |
299 | unsigned | |
300 | bits, | |
301 | enum | |
302 | ni_gpct_register | |
303 | reg), | |
304 | unsigned (*read_register) | |
3d34023a | 305 | (struct ni_gpct *counter, |
0a85b6f0 MT |
306 | enum ni_gpct_register reg), |
307 | enum ni_gpct_variant variant, | |
308 | unsigned num_counters) | |
cb7859a9 FMH |
309 | { |
310 | unsigned i; | |
311 | ||
312 | struct ni_gpct_device *counter_dev = | |
0a85b6f0 | 313 | kzalloc(sizeof(struct ni_gpct_device), GFP_KERNEL); |
cb7859a9 FMH |
314 | if (counter_dev == NULL) |
315 | return NULL; | |
316 | counter_dev->dev = dev; | |
317 | counter_dev->write_register = write_register; | |
318 | counter_dev->read_register = read_register; | |
319 | counter_dev->variant = variant; | |
320 | spin_lock_init(&counter_dev->regs_lock); | |
321 | BUG_ON(num_counters == 0); | |
322 | counter_dev->counters = | |
0a85b6f0 | 323 | kzalloc(sizeof(struct ni_gpct) * num_counters, GFP_KERNEL); |
cb7859a9 FMH |
324 | if (counter_dev->counters == NULL) { |
325 | kfree(counter_dev); | |
326 | return NULL; | |
327 | } | |
328 | for (i = 0; i < num_counters; ++i) { | |
329 | counter_dev->counters[i].counter_dev = counter_dev; | |
330 | spin_lock_init(&counter_dev->counters[i].lock); | |
331 | } | |
332 | counter_dev->num_counters = num_counters; | |
333 | return counter_dev; | |
334 | } | |
3d34023a | 335 | EXPORT_SYMBOL_GPL(ni_gpct_device_construct); |
cb7859a9 FMH |
336 | |
337 | void ni_gpct_device_destroy(struct ni_gpct_device *counter_dev) | |
338 | { | |
339 | if (counter_dev->counters == NULL) | |
340 | return; | |
341 | kfree(counter_dev->counters); | |
342 | kfree(counter_dev); | |
343 | } | |
3d34023a | 344 | EXPORT_SYMBOL_GPL(ni_gpct_device_destroy); |
cb7859a9 FMH |
345 | |
346 | static int ni_tio_second_gate_registers_present(const struct ni_gpct_device | |
0a85b6f0 | 347 | *counter_dev) |
cb7859a9 FMH |
348 | { |
349 | switch (counter_dev->variant) { | |
350 | case ni_gpct_variant_e_series: | |
351 | return 0; | |
352 | break; | |
353 | case ni_gpct_variant_m_series: | |
354 | case ni_gpct_variant_660x: | |
355 | return 1; | |
356 | break; | |
357 | default: | |
358 | BUG(); | |
359 | break; | |
360 | } | |
361 | return 0; | |
362 | } | |
363 | ||
364 | static void ni_tio_reset_count_and_disarm(struct ni_gpct *counter) | |
365 | { | |
366 | write_register(counter, Gi_Reset_Bit(counter->counter_index), | |
0a85b6f0 | 367 | NITIO_Gxx_Joint_Reset_Reg(counter->counter_index)); |
cb7859a9 FMH |
368 | } |
369 | ||
370 | void ni_tio_init_counter(struct ni_gpct *counter) | |
371 | { | |
372 | struct ni_gpct_device *counter_dev = counter->counter_dev; | |
373 | ||
374 | ni_tio_reset_count_and_disarm(counter); | |
375 | /* initialize counter registers */ | |
376 | counter_dev->regs[NITIO_Gi_Autoincrement_Reg(counter->counter_index)] = | |
0a85b6f0 | 377 | 0x0; |
cb7859a9 | 378 | write_register(counter, |
0a85b6f0 MT |
379 | counter_dev-> |
380 | regs[NITIO_Gi_Autoincrement_Reg(counter->counter_index)], | |
381 | NITIO_Gi_Autoincrement_Reg(counter->counter_index)); | |
cb7859a9 | 382 | ni_tio_set_bits(counter, NITIO_Gi_Command_Reg(counter->counter_index), |
0a85b6f0 | 383 | ~0, Gi_Synchronize_Gate_Bit); |
cb7859a9 | 384 | ni_tio_set_bits(counter, NITIO_Gi_Mode_Reg(counter->counter_index), ~0, |
0a85b6f0 | 385 | 0); |
cb7859a9 FMH |
386 | counter_dev->regs[NITIO_Gi_LoadA_Reg(counter->counter_index)] = 0x0; |
387 | write_register(counter, | |
0a85b6f0 MT |
388 | counter_dev-> |
389 | regs[NITIO_Gi_LoadA_Reg(counter->counter_index)], | |
390 | NITIO_Gi_LoadA_Reg(counter->counter_index)); | |
cb7859a9 FMH |
391 | counter_dev->regs[NITIO_Gi_LoadB_Reg(counter->counter_index)] = 0x0; |
392 | write_register(counter, | |
0a85b6f0 MT |
393 | counter_dev-> |
394 | regs[NITIO_Gi_LoadB_Reg(counter->counter_index)], | |
395 | NITIO_Gi_LoadB_Reg(counter->counter_index)); | |
cb7859a9 | 396 | ni_tio_set_bits(counter, |
0a85b6f0 MT |
397 | NITIO_Gi_Input_Select_Reg(counter->counter_index), ~0, |
398 | 0); | |
cb7859a9 FMH |
399 | if (ni_tio_counting_mode_registers_present(counter_dev)) { |
400 | ni_tio_set_bits(counter, | |
0a85b6f0 MT |
401 | NITIO_Gi_Counting_Mode_Reg(counter-> |
402 | counter_index), ~0, | |
403 | 0); | |
cb7859a9 FMH |
404 | } |
405 | if (ni_tio_second_gate_registers_present(counter_dev)) { | |
0a85b6f0 MT |
406 | counter_dev-> |
407 | regs[NITIO_Gi_Second_Gate_Reg(counter->counter_index)] = | |
408 | 0x0; | |
cb7859a9 | 409 | write_register(counter, |
0a85b6f0 MT |
410 | counter_dev-> |
411 | regs[NITIO_Gi_Second_Gate_Reg | |
412 | (counter->counter_index)], | |
413 | NITIO_Gi_Second_Gate_Reg(counter-> | |
414 | counter_index)); | |
cb7859a9 FMH |
415 | } |
416 | ni_tio_set_bits(counter, | |
0a85b6f0 MT |
417 | NITIO_Gi_DMA_Config_Reg(counter->counter_index), ~0, |
418 | 0x0); | |
cb7859a9 | 419 | ni_tio_set_bits(counter, |
0a85b6f0 MT |
420 | NITIO_Gi_Interrupt_Enable_Reg(counter->counter_index), |
421 | ~0, 0x0); | |
cb7859a9 | 422 | } |
3d34023a | 423 | EXPORT_SYMBOL_GPL(ni_tio_init_counter); |
cb7859a9 | 424 | |
790c5541 | 425 | static unsigned int ni_tio_counter_status(struct ni_gpct *counter) |
cb7859a9 | 426 | { |
790c5541 | 427 | unsigned int status = 0; |
cb7859a9 | 428 | const unsigned bits = read_register(counter, |
0a85b6f0 MT |
429 | NITIO_Gxx_Status_Reg(counter-> |
430 | counter_index)); | |
cb7859a9 FMH |
431 | if (bits & Gi_Armed_Bit(counter->counter_index)) { |
432 | status |= COMEDI_COUNTER_ARMED; | |
433 | if (bits & Gi_Counting_Bit(counter->counter_index)) | |
434 | status |= COMEDI_COUNTER_COUNTING; | |
435 | } | |
436 | return status; | |
437 | } | |
438 | ||
439 | static void ni_tio_set_sync_mode(struct ni_gpct *counter, int force_alt_sync) | |
440 | { | |
441 | struct ni_gpct_device *counter_dev = counter->counter_dev; | |
442 | const unsigned counting_mode_reg = | |
0a85b6f0 | 443 | NITIO_Gi_Counting_Mode_Reg(counter->counter_index); |
cb7859a9 FMH |
444 | static const uint64_t min_normal_sync_period_ps = 25000; |
445 | const uint64_t clock_period_ps = ni_tio_clock_period_ps(counter, | |
0a85b6f0 MT |
446 | ni_tio_generic_clock_src_select |
447 | (counter)); | |
cb7859a9 FMH |
448 | |
449 | if (ni_tio_counting_mode_registers_present(counter_dev) == 0) | |
450 | return; | |
451 | ||
3d34023a | 452 | switch (ni_tio_get_soft_copy(counter, counting_mode_reg) & Gi_Counting_Mode_Mask) { |
cb7859a9 FMH |
453 | case Gi_Counting_Mode_QuadratureX1_Bits: |
454 | case Gi_Counting_Mode_QuadratureX2_Bits: | |
455 | case Gi_Counting_Mode_QuadratureX4_Bits: | |
456 | case Gi_Counting_Mode_Sync_Source_Bits: | |
457 | force_alt_sync = 1; | |
458 | break; | |
459 | default: | |
460 | break; | |
461 | } | |
462 | /* It's not clear what we should do if clock_period is unknown, so we are not | |
463 | using the alt sync bit in that case, but allow the caller to decide by using the | |
464 | force_alt_sync parameter. */ | |
465 | if (force_alt_sync || | |
0a85b6f0 | 466 | (clock_period_ps && clock_period_ps < min_normal_sync_period_ps)) { |
cb7859a9 | 467 | ni_tio_set_bits(counter, counting_mode_reg, |
0a85b6f0 MT |
468 | Gi_Alternate_Sync_Bit(counter_dev->variant), |
469 | Gi_Alternate_Sync_Bit(counter_dev->variant)); | |
cb7859a9 FMH |
470 | } else { |
471 | ni_tio_set_bits(counter, counting_mode_reg, | |
0a85b6f0 MT |
472 | Gi_Alternate_Sync_Bit(counter_dev->variant), |
473 | 0x0); | |
cb7859a9 FMH |
474 | } |
475 | } | |
476 | ||
477 | static int ni_tio_set_counter_mode(struct ni_gpct *counter, unsigned mode) | |
478 | { | |
479 | struct ni_gpct_device *counter_dev = counter->counter_dev; | |
480 | unsigned mode_reg_mask; | |
481 | unsigned mode_reg_values; | |
482 | unsigned input_select_bits = 0; | |
483 | /* these bits map directly on to the mode register */ | |
484 | static const unsigned mode_reg_direct_mask = | |
0a85b6f0 MT |
485 | NI_GPCT_GATE_ON_BOTH_EDGES_BIT | NI_GPCT_EDGE_GATE_MODE_MASK | |
486 | NI_GPCT_STOP_MODE_MASK | NI_GPCT_OUTPUT_MODE_MASK | | |
487 | NI_GPCT_HARDWARE_DISARM_MASK | NI_GPCT_LOADING_ON_TC_BIT | | |
488 | NI_GPCT_LOADING_ON_GATE_BIT | NI_GPCT_LOAD_B_SELECT_BIT; | |
cb7859a9 FMH |
489 | |
490 | mode_reg_mask = mode_reg_direct_mask | Gi_Reload_Source_Switching_Bit; | |
491 | mode_reg_values = mode & mode_reg_direct_mask; | |
492 | switch (mode & NI_GPCT_RELOAD_SOURCE_MASK) { | |
493 | case NI_GPCT_RELOAD_SOURCE_FIXED_BITS: | |
494 | break; | |
495 | case NI_GPCT_RELOAD_SOURCE_SWITCHING_BITS: | |
496 | mode_reg_values |= Gi_Reload_Source_Switching_Bit; | |
497 | break; | |
498 | case NI_GPCT_RELOAD_SOURCE_GATE_SELECT_BITS: | |
499 | input_select_bits |= Gi_Gate_Select_Load_Source_Bit; | |
500 | mode_reg_mask |= Gi_Gating_Mode_Mask; | |
501 | mode_reg_values |= Gi_Level_Gating_Bits; | |
502 | break; | |
503 | default: | |
504 | break; | |
505 | } | |
506 | ni_tio_set_bits(counter, NITIO_Gi_Mode_Reg(counter->counter_index), | |
0a85b6f0 | 507 | mode_reg_mask, mode_reg_values); |
cb7859a9 FMH |
508 | |
509 | if (ni_tio_counting_mode_registers_present(counter_dev)) { | |
510 | unsigned counting_mode_bits = 0; | |
511 | counting_mode_bits |= | |
0a85b6f0 MT |
512 | (mode >> NI_GPCT_COUNTING_MODE_SHIFT) & |
513 | Gi_Counting_Mode_Mask; | |
cb7859a9 | 514 | counting_mode_bits |= |
0a85b6f0 MT |
515 | ((mode >> NI_GPCT_INDEX_PHASE_BITSHIFT) << |
516 | Gi_Index_Phase_Bitshift) & Gi_Index_Phase_Mask; | |
3d34023a | 517 | if (mode & NI_GPCT_INDEX_ENABLE_BIT) |
cb7859a9 | 518 | counting_mode_bits |= Gi_Index_Mode_Bit; |
cb7859a9 | 519 | ni_tio_set_bits(counter, |
0a85b6f0 MT |
520 | NITIO_Gi_Counting_Mode_Reg(counter-> |
521 | counter_index), | |
522 | Gi_Counting_Mode_Mask | Gi_Index_Phase_Mask | | |
523 | Gi_Index_Mode_Bit, counting_mode_bits); | |
cb7859a9 FMH |
524 | ni_tio_set_sync_mode(counter, 0); |
525 | } | |
526 | ||
527 | ni_tio_set_bits(counter, NITIO_Gi_Command_Reg(counter->counter_index), | |
0a85b6f0 MT |
528 | Gi_Up_Down_Mask, |
529 | (mode >> NI_GPCT_COUNTING_DIRECTION_SHIFT) << | |
530 | Gi_Up_Down_Shift); | |
cb7859a9 | 531 | |
3d34023a | 532 | if (mode & NI_GPCT_OR_GATE_BIT) |
cb7859a9 | 533 | input_select_bits |= Gi_Or_Gate_Bit; |
3d34023a | 534 | if (mode & NI_GPCT_INVERT_OUTPUT_BIT) |
cb7859a9 | 535 | input_select_bits |= Gi_Output_Polarity_Bit; |
cb7859a9 | 536 | ni_tio_set_bits(counter, |
0a85b6f0 MT |
537 | NITIO_Gi_Input_Select_Reg(counter->counter_index), |
538 | Gi_Gate_Select_Load_Source_Bit | Gi_Or_Gate_Bit | | |
539 | Gi_Output_Polarity_Bit, input_select_bits); | |
cb7859a9 FMH |
540 | |
541 | return 0; | |
542 | } | |
543 | ||
544 | int ni_tio_arm(struct ni_gpct *counter, int arm, unsigned start_trigger) | |
545 | { | |
546 | struct ni_gpct_device *counter_dev = counter->counter_dev; | |
547 | ||
548 | unsigned command_transient_bits = 0; | |
549 | ||
550 | if (arm) { | |
551 | switch (start_trigger) { | |
552 | case NI_GPCT_ARM_IMMEDIATE: | |
553 | command_transient_bits |= Gi_Arm_Bit; | |
554 | break; | |
555 | case NI_GPCT_ARM_PAIRED_IMMEDIATE: | |
556 | command_transient_bits |= Gi_Arm_Bit | Gi_Arm_Copy_Bit; | |
557 | break; | |
558 | default: | |
559 | break; | |
560 | } | |
561 | if (ni_tio_counting_mode_registers_present(counter_dev)) { | |
562 | unsigned counting_mode_bits = 0; | |
563 | ||
564 | switch (start_trigger) { | |
565 | case NI_GPCT_ARM_IMMEDIATE: | |
566 | case NI_GPCT_ARM_PAIRED_IMMEDIATE: | |
567 | break; | |
568 | default: | |
569 | if (start_trigger & NI_GPCT_ARM_UNKNOWN) { | |
570 | /* pass-through the least significant bits so we can figure out what select later */ | |
571 | unsigned hw_arm_select_bits = | |
0a85b6f0 MT |
572 | (start_trigger << |
573 | Gi_HW_Arm_Select_Shift) & | |
574 | Gi_HW_Arm_Select_Mask | |
575 | (counter_dev->variant); | |
cb7859a9 FMH |
576 | |
577 | counting_mode_bits |= | |
0a85b6f0 MT |
578 | Gi_HW_Arm_Enable_Bit | |
579 | hw_arm_select_bits; | |
cb7859a9 FMH |
580 | } else { |
581 | return -EINVAL; | |
582 | } | |
583 | break; | |
584 | } | |
585 | ni_tio_set_bits(counter, | |
0a85b6f0 MT |
586 | NITIO_Gi_Counting_Mode_Reg |
587 | (counter->counter_index), | |
588 | Gi_HW_Arm_Select_Mask | |
589 | (counter_dev->variant) | | |
590 | Gi_HW_Arm_Enable_Bit, | |
591 | counting_mode_bits); | |
cb7859a9 FMH |
592 | } |
593 | } else { | |
594 | command_transient_bits |= Gi_Disarm_Bit; | |
595 | } | |
596 | ni_tio_set_bits_transient(counter, | |
0a85b6f0 MT |
597 | NITIO_Gi_Command_Reg(counter->counter_index), |
598 | 0, 0, command_transient_bits); | |
cb7859a9 FMH |
599 | return 0; |
600 | } | |
3d34023a | 601 | EXPORT_SYMBOL_GPL(ni_tio_arm); |
cb7859a9 | 602 | |
790c5541 | 603 | static unsigned ni_660x_source_select_bits(unsigned int clock_source) |
cb7859a9 FMH |
604 | { |
605 | unsigned ni_660x_clock; | |
606 | unsigned i; | |
607 | const unsigned clock_select_bits = | |
0a85b6f0 | 608 | clock_source & NI_GPCT_CLOCK_SRC_SELECT_MASK; |
cb7859a9 FMH |
609 | |
610 | switch (clock_select_bits) { | |
611 | case NI_GPCT_TIMEBASE_1_CLOCK_SRC_BITS: | |
612 | ni_660x_clock = NI_660x_Timebase_1_Clock; | |
613 | break; | |
614 | case NI_GPCT_TIMEBASE_2_CLOCK_SRC_BITS: | |
615 | ni_660x_clock = NI_660x_Timebase_2_Clock; | |
616 | break; | |
617 | case NI_GPCT_TIMEBASE_3_CLOCK_SRC_BITS: | |
618 | ni_660x_clock = NI_660x_Timebase_3_Clock; | |
619 | break; | |
620 | case NI_GPCT_LOGIC_LOW_CLOCK_SRC_BITS: | |
621 | ni_660x_clock = NI_660x_Logic_Low_Clock; | |
622 | break; | |
623 | case NI_GPCT_SOURCE_PIN_i_CLOCK_SRC_BITS: | |
624 | ni_660x_clock = NI_660x_Source_Pin_i_Clock; | |
625 | break; | |
626 | case NI_GPCT_NEXT_GATE_CLOCK_SRC_BITS: | |
627 | ni_660x_clock = NI_660x_Next_Gate_Clock; | |
628 | break; | |
629 | case NI_GPCT_NEXT_TC_CLOCK_SRC_BITS: | |
630 | ni_660x_clock = NI_660x_Next_TC_Clock; | |
631 | break; | |
632 | default: | |
633 | for (i = 0; i <= ni_660x_max_rtsi_channel; ++i) { | |
634 | if (clock_select_bits == NI_GPCT_RTSI_CLOCK_SRC_BITS(i)) { | |
635 | ni_660x_clock = NI_660x_RTSI_Clock(i); | |
636 | break; | |
637 | } | |
638 | } | |
639 | if (i <= ni_660x_max_rtsi_channel) | |
640 | break; | |
641 | for (i = 0; i <= ni_660x_max_source_pin; ++i) { | |
642 | if (clock_select_bits == | |
0a85b6f0 | 643 | NI_GPCT_SOURCE_PIN_CLOCK_SRC_BITS(i)) { |
cb7859a9 FMH |
644 | ni_660x_clock = NI_660x_Source_Pin_Clock(i); |
645 | break; | |
646 | } | |
647 | } | |
648 | if (i <= ni_660x_max_source_pin) | |
649 | break; | |
650 | ni_660x_clock = 0; | |
651 | BUG(); | |
652 | break; | |
653 | } | |
654 | return Gi_Source_Select_Bits(ni_660x_clock); | |
655 | } | |
656 | ||
790c5541 | 657 | static unsigned ni_m_series_source_select_bits(unsigned int clock_source) |
cb7859a9 FMH |
658 | { |
659 | unsigned ni_m_series_clock; | |
660 | unsigned i; | |
661 | const unsigned clock_select_bits = | |
0a85b6f0 | 662 | clock_source & NI_GPCT_CLOCK_SRC_SELECT_MASK; |
cb7859a9 FMH |
663 | switch (clock_select_bits) { |
664 | case NI_GPCT_TIMEBASE_1_CLOCK_SRC_BITS: | |
665 | ni_m_series_clock = NI_M_Series_Timebase_1_Clock; | |
666 | break; | |
667 | case NI_GPCT_TIMEBASE_2_CLOCK_SRC_BITS: | |
668 | ni_m_series_clock = NI_M_Series_Timebase_2_Clock; | |
669 | break; | |
670 | case NI_GPCT_TIMEBASE_3_CLOCK_SRC_BITS: | |
671 | ni_m_series_clock = NI_M_Series_Timebase_3_Clock; | |
672 | break; | |
673 | case NI_GPCT_LOGIC_LOW_CLOCK_SRC_BITS: | |
674 | ni_m_series_clock = NI_M_Series_Logic_Low_Clock; | |
675 | break; | |
676 | case NI_GPCT_NEXT_GATE_CLOCK_SRC_BITS: | |
677 | ni_m_series_clock = NI_M_Series_Next_Gate_Clock; | |
678 | break; | |
679 | case NI_GPCT_NEXT_TC_CLOCK_SRC_BITS: | |
680 | ni_m_series_clock = NI_M_Series_Next_TC_Clock; | |
681 | break; | |
682 | case NI_GPCT_PXI10_CLOCK_SRC_BITS: | |
683 | ni_m_series_clock = NI_M_Series_PXI10_Clock; | |
684 | break; | |
685 | case NI_GPCT_PXI_STAR_TRIGGER_CLOCK_SRC_BITS: | |
686 | ni_m_series_clock = NI_M_Series_PXI_Star_Trigger_Clock; | |
687 | break; | |
688 | case NI_GPCT_ANALOG_TRIGGER_OUT_CLOCK_SRC_BITS: | |
689 | ni_m_series_clock = NI_M_Series_Analog_Trigger_Out_Clock; | |
690 | break; | |
691 | default: | |
692 | for (i = 0; i <= ni_m_series_max_rtsi_channel; ++i) { | |
693 | if (clock_select_bits == NI_GPCT_RTSI_CLOCK_SRC_BITS(i)) { | |
694 | ni_m_series_clock = NI_M_Series_RTSI_Clock(i); | |
695 | break; | |
696 | } | |
697 | } | |
698 | if (i <= ni_m_series_max_rtsi_channel) | |
699 | break; | |
700 | for (i = 0; i <= ni_m_series_max_pfi_channel; ++i) { | |
701 | if (clock_select_bits == NI_GPCT_PFI_CLOCK_SRC_BITS(i)) { | |
702 | ni_m_series_clock = NI_M_Series_PFI_Clock(i); | |
703 | break; | |
704 | } | |
705 | } | |
706 | if (i <= ni_m_series_max_pfi_channel) | |
707 | break; | |
3d34023a | 708 | printk(KERN_ERR "invalid clock source 0x%lx\n", |
0a85b6f0 | 709 | (unsigned long)clock_source); |
cb7859a9 FMH |
710 | BUG(); |
711 | ni_m_series_clock = 0; | |
712 | break; | |
713 | } | |
714 | return Gi_Source_Select_Bits(ni_m_series_clock); | |
715 | }; | |
716 | ||
717 | static void ni_tio_set_source_subselect(struct ni_gpct *counter, | |
0a85b6f0 | 718 | unsigned int clock_source) |
cb7859a9 FMH |
719 | { |
720 | struct ni_gpct_device *counter_dev = counter->counter_dev; | |
721 | const unsigned second_gate_reg = | |
0a85b6f0 | 722 | NITIO_Gi_Second_Gate_Reg(counter->counter_index); |
cb7859a9 FMH |
723 | |
724 | if (counter_dev->variant != ni_gpct_variant_m_series) | |
725 | return; | |
726 | switch (clock_source & NI_GPCT_CLOCK_SRC_SELECT_MASK) { | |
727 | /* Gi_Source_Subselect is zero */ | |
728 | case NI_GPCT_NEXT_GATE_CLOCK_SRC_BITS: | |
729 | case NI_GPCT_TIMEBASE_3_CLOCK_SRC_BITS: | |
730 | counter_dev->regs[second_gate_reg] &= ~Gi_Source_Subselect_Bit; | |
731 | break; | |
732 | /* Gi_Source_Subselect is one */ | |
733 | case NI_GPCT_ANALOG_TRIGGER_OUT_CLOCK_SRC_BITS: | |
734 | case NI_GPCT_PXI_STAR_TRIGGER_CLOCK_SRC_BITS: | |
735 | counter_dev->regs[second_gate_reg] |= Gi_Source_Subselect_Bit; | |
736 | break; | |
737 | /* Gi_Source_Subselect doesn't matter */ | |
738 | default: | |
739 | return; | |
740 | break; | |
741 | } | |
742 | write_register(counter, counter_dev->regs[second_gate_reg], | |
0a85b6f0 | 743 | second_gate_reg); |
cb7859a9 FMH |
744 | } |
745 | ||
746 | static int ni_tio_set_clock_src(struct ni_gpct *counter, | |
0a85b6f0 MT |
747 | unsigned int clock_source, |
748 | unsigned int period_ns) | |
cb7859a9 FMH |
749 | { |
750 | struct ni_gpct_device *counter_dev = counter->counter_dev; | |
751 | unsigned input_select_bits = 0; | |
752 | static const uint64_t pico_per_nano = 1000; | |
753 | ||
754 | /*FIXME: validate clock source */ | |
755 | switch (counter_dev->variant) { | |
756 | case ni_gpct_variant_660x: | |
757 | input_select_bits |= ni_660x_source_select_bits(clock_source); | |
758 | break; | |
759 | case ni_gpct_variant_e_series: | |
760 | case ni_gpct_variant_m_series: | |
761 | input_select_bits |= | |
0a85b6f0 | 762 | ni_m_series_source_select_bits(clock_source); |
cb7859a9 FMH |
763 | break; |
764 | default: | |
765 | BUG(); | |
766 | break; | |
767 | } | |
768 | if (clock_source & NI_GPCT_INVERT_CLOCK_SRC_BIT) | |
769 | input_select_bits |= Gi_Source_Polarity_Bit; | |
770 | ni_tio_set_bits(counter, | |
0a85b6f0 MT |
771 | NITIO_Gi_Input_Select_Reg(counter->counter_index), |
772 | Gi_Source_Select_Mask | Gi_Source_Polarity_Bit, | |
773 | input_select_bits); | |
cb7859a9 FMH |
774 | ni_tio_set_source_subselect(counter, clock_source); |
775 | if (ni_tio_counting_mode_registers_present(counter_dev)) { | |
776 | const unsigned prescaling_mode = | |
0a85b6f0 | 777 | clock_source & NI_GPCT_PRESCALE_MODE_CLOCK_SRC_MASK; |
cb7859a9 FMH |
778 | unsigned counting_mode_bits = 0; |
779 | ||
780 | switch (prescaling_mode) { | |
781 | case NI_GPCT_NO_PRESCALE_CLOCK_SRC_BITS: | |
782 | break; | |
783 | case NI_GPCT_PRESCALE_X2_CLOCK_SRC_BITS: | |
784 | counting_mode_bits |= | |
0a85b6f0 | 785 | Gi_Prescale_X2_Bit(counter_dev->variant); |
cb7859a9 FMH |
786 | break; |
787 | case NI_GPCT_PRESCALE_X8_CLOCK_SRC_BITS: | |
788 | counting_mode_bits |= | |
0a85b6f0 | 789 | Gi_Prescale_X8_Bit(counter_dev->variant); |
cb7859a9 FMH |
790 | break; |
791 | default: | |
792 | return -EINVAL; | |
793 | break; | |
794 | } | |
795 | ni_tio_set_bits(counter, | |
0a85b6f0 MT |
796 | NITIO_Gi_Counting_Mode_Reg(counter-> |
797 | counter_index), | |
798 | Gi_Prescale_X2_Bit(counter_dev->variant) | | |
799 | Gi_Prescale_X8_Bit(counter_dev->variant), | |
800 | counting_mode_bits); | |
cb7859a9 FMH |
801 | } |
802 | counter->clock_period_ps = pico_per_nano * period_ns; | |
803 | ni_tio_set_sync_mode(counter, 0); | |
804 | return 0; | |
805 | } | |
806 | ||
807 | static unsigned ni_tio_clock_src_modifiers(const struct ni_gpct *counter) | |
808 | { | |
809 | struct ni_gpct_device *counter_dev = counter->counter_dev; | |
810 | const unsigned counting_mode_bits = ni_tio_get_soft_copy(counter, | |
0a85b6f0 MT |
811 | NITIO_Gi_Counting_Mode_Reg |
812 | (counter-> | |
813 | counter_index)); | |
cb7859a9 FMH |
814 | unsigned bits = 0; |
815 | ||
816 | if (ni_tio_get_soft_copy(counter, | |
0a85b6f0 MT |
817 | NITIO_Gi_Input_Select_Reg |
818 | (counter->counter_index)) & | |
819 | Gi_Source_Polarity_Bit) | |
cb7859a9 FMH |
820 | bits |= NI_GPCT_INVERT_CLOCK_SRC_BIT; |
821 | if (counting_mode_bits & Gi_Prescale_X2_Bit(counter_dev->variant)) | |
822 | bits |= NI_GPCT_PRESCALE_X2_CLOCK_SRC_BITS; | |
823 | if (counting_mode_bits & Gi_Prescale_X8_Bit(counter_dev->variant)) | |
824 | bits |= NI_GPCT_PRESCALE_X8_CLOCK_SRC_BITS; | |
825 | return bits; | |
826 | } | |
827 | ||
828 | static unsigned ni_m_series_clock_src_select(const struct ni_gpct *counter) | |
829 | { | |
830 | struct ni_gpct_device *counter_dev = counter->counter_dev; | |
831 | const unsigned second_gate_reg = | |
0a85b6f0 | 832 | NITIO_Gi_Second_Gate_Reg(counter->counter_index); |
cb7859a9 FMH |
833 | unsigned clock_source = 0; |
834 | unsigned i; | |
835 | const unsigned input_select = (ni_tio_get_soft_copy(counter, | |
0a85b6f0 MT |
836 | NITIO_Gi_Input_Select_Reg |
837 | (counter->counter_index)) | |
838 | & Gi_Source_Select_Mask) >> | |
839 | Gi_Source_Select_Shift; | |
cb7859a9 FMH |
840 | |
841 | switch (input_select) { | |
842 | case NI_M_Series_Timebase_1_Clock: | |
843 | clock_source = NI_GPCT_TIMEBASE_1_CLOCK_SRC_BITS; | |
844 | break; | |
845 | case NI_M_Series_Timebase_2_Clock: | |
846 | clock_source = NI_GPCT_TIMEBASE_2_CLOCK_SRC_BITS; | |
847 | break; | |
848 | case NI_M_Series_Timebase_3_Clock: | |
0a85b6f0 MT |
849 | if (counter_dev->regs[second_gate_reg] & |
850 | Gi_Source_Subselect_Bit) | |
cb7859a9 | 851 | clock_source = |
0a85b6f0 | 852 | NI_GPCT_ANALOG_TRIGGER_OUT_CLOCK_SRC_BITS; |
cb7859a9 FMH |
853 | else |
854 | clock_source = NI_GPCT_TIMEBASE_3_CLOCK_SRC_BITS; | |
855 | break; | |
856 | case NI_M_Series_Logic_Low_Clock: | |
857 | clock_source = NI_GPCT_LOGIC_LOW_CLOCK_SRC_BITS; | |
858 | break; | |
859 | case NI_M_Series_Next_Gate_Clock: | |
0a85b6f0 MT |
860 | if (counter_dev->regs[second_gate_reg] & |
861 | Gi_Source_Subselect_Bit) | |
cb7859a9 FMH |
862 | clock_source = NI_GPCT_PXI_STAR_TRIGGER_CLOCK_SRC_BITS; |
863 | else | |
864 | clock_source = NI_GPCT_NEXT_GATE_CLOCK_SRC_BITS; | |
865 | break; | |
866 | case NI_M_Series_PXI10_Clock: | |
867 | clock_source = NI_GPCT_PXI10_CLOCK_SRC_BITS; | |
868 | break; | |
869 | case NI_M_Series_Next_TC_Clock: | |
870 | clock_source = NI_GPCT_NEXT_TC_CLOCK_SRC_BITS; | |
871 | break; | |
872 | default: | |
873 | for (i = 0; i <= ni_m_series_max_rtsi_channel; ++i) { | |
874 | if (input_select == NI_M_Series_RTSI_Clock(i)) { | |
875 | clock_source = NI_GPCT_RTSI_CLOCK_SRC_BITS(i); | |
876 | break; | |
877 | } | |
878 | } | |
879 | if (i <= ni_m_series_max_rtsi_channel) | |
880 | break; | |
881 | for (i = 0; i <= ni_m_series_max_pfi_channel; ++i) { | |
882 | if (input_select == NI_M_Series_PFI_Clock(i)) { | |
883 | clock_source = NI_GPCT_PFI_CLOCK_SRC_BITS(i); | |
884 | break; | |
885 | } | |
886 | } | |
887 | if (i <= ni_m_series_max_pfi_channel) | |
888 | break; | |
889 | BUG(); | |
890 | break; | |
891 | } | |
892 | clock_source |= ni_tio_clock_src_modifiers(counter); | |
893 | return clock_source; | |
894 | } | |
895 | ||
896 | static unsigned ni_660x_clock_src_select(const struct ni_gpct *counter) | |
897 | { | |
898 | unsigned clock_source = 0; | |
899 | unsigned i; | |
900 | const unsigned input_select = (ni_tio_get_soft_copy(counter, | |
0a85b6f0 MT |
901 | NITIO_Gi_Input_Select_Reg |
902 | (counter->counter_index)) | |
903 | & Gi_Source_Select_Mask) >> | |
904 | Gi_Source_Select_Shift; | |
cb7859a9 FMH |
905 | |
906 | switch (input_select) { | |
907 | case NI_660x_Timebase_1_Clock: | |
908 | clock_source = NI_GPCT_TIMEBASE_1_CLOCK_SRC_BITS; | |
909 | break; | |
910 | case NI_660x_Timebase_2_Clock: | |
911 | clock_source = NI_GPCT_TIMEBASE_2_CLOCK_SRC_BITS; | |
912 | break; | |
913 | case NI_660x_Timebase_3_Clock: | |
914 | clock_source = NI_GPCT_TIMEBASE_3_CLOCK_SRC_BITS; | |
915 | break; | |
916 | case NI_660x_Logic_Low_Clock: | |
917 | clock_source = NI_GPCT_LOGIC_LOW_CLOCK_SRC_BITS; | |
918 | break; | |
919 | case NI_660x_Source_Pin_i_Clock: | |
920 | clock_source = NI_GPCT_SOURCE_PIN_i_CLOCK_SRC_BITS; | |
921 | break; | |
922 | case NI_660x_Next_Gate_Clock: | |
923 | clock_source = NI_GPCT_NEXT_GATE_CLOCK_SRC_BITS; | |
924 | break; | |
925 | case NI_660x_Next_TC_Clock: | |
926 | clock_source = NI_GPCT_NEXT_TC_CLOCK_SRC_BITS; | |
927 | break; | |
928 | default: | |
929 | for (i = 0; i <= ni_660x_max_rtsi_channel; ++i) { | |
930 | if (input_select == NI_660x_RTSI_Clock(i)) { | |
931 | clock_source = NI_GPCT_RTSI_CLOCK_SRC_BITS(i); | |
932 | break; | |
933 | } | |
934 | } | |
935 | if (i <= ni_660x_max_rtsi_channel) | |
936 | break; | |
937 | for (i = 0; i <= ni_660x_max_source_pin; ++i) { | |
938 | if (input_select == NI_660x_Source_Pin_Clock(i)) { | |
939 | clock_source = | |
0a85b6f0 | 940 | NI_GPCT_SOURCE_PIN_CLOCK_SRC_BITS(i); |
cb7859a9 FMH |
941 | break; |
942 | } | |
943 | } | |
944 | if (i <= ni_660x_max_source_pin) | |
945 | break; | |
946 | BUG(); | |
947 | break; | |
948 | } | |
949 | clock_source |= ni_tio_clock_src_modifiers(counter); | |
950 | return clock_source; | |
951 | } | |
952 | ||
953 | static unsigned ni_tio_generic_clock_src_select(const struct ni_gpct *counter) | |
954 | { | |
955 | switch (counter->counter_dev->variant) { | |
956 | case ni_gpct_variant_e_series: | |
957 | case ni_gpct_variant_m_series: | |
958 | return ni_m_series_clock_src_select(counter); | |
959 | break; | |
960 | case ni_gpct_variant_660x: | |
961 | return ni_660x_clock_src_select(counter); | |
962 | break; | |
963 | default: | |
964 | BUG(); | |
965 | break; | |
966 | } | |
967 | return 0; | |
968 | } | |
969 | ||
970 | static uint64_t ni_tio_clock_period_ps(const struct ni_gpct *counter, | |
0a85b6f0 | 971 | unsigned generic_clock_source) |
cb7859a9 FMH |
972 | { |
973 | uint64_t clock_period_ps; | |
974 | ||
975 | switch (generic_clock_source & NI_GPCT_CLOCK_SRC_SELECT_MASK) { | |
976 | case NI_GPCT_TIMEBASE_1_CLOCK_SRC_BITS: | |
977 | clock_period_ps = 50000; | |
978 | break; | |
979 | case NI_GPCT_TIMEBASE_2_CLOCK_SRC_BITS: | |
980 | clock_period_ps = 10000000; | |
981 | break; | |
982 | case NI_GPCT_TIMEBASE_3_CLOCK_SRC_BITS: | |
983 | clock_period_ps = 12500; | |
984 | break; | |
985 | case NI_GPCT_PXI10_CLOCK_SRC_BITS: | |
986 | clock_period_ps = 100000; | |
987 | break; | |
988 | default: | |
989 | /* clock period is specified by user with prescaling already taken into account. */ | |
990 | return counter->clock_period_ps; | |
991 | break; | |
992 | } | |
993 | ||
994 | switch (generic_clock_source & NI_GPCT_PRESCALE_MODE_CLOCK_SRC_MASK) { | |
995 | case NI_GPCT_NO_PRESCALE_CLOCK_SRC_BITS: | |
996 | break; | |
997 | case NI_GPCT_PRESCALE_X2_CLOCK_SRC_BITS: | |
998 | clock_period_ps *= 2; | |
999 | break; | |
1000 | case NI_GPCT_PRESCALE_X8_CLOCK_SRC_BITS: | |
1001 | clock_period_ps *= 8; | |
1002 | break; | |
1003 | default: | |
1004 | BUG(); | |
1005 | break; | |
1006 | } | |
1007 | return clock_period_ps; | |
1008 | } | |
1009 | ||
1010 | static void ni_tio_get_clock_src(struct ni_gpct *counter, | |
0a85b6f0 MT |
1011 | unsigned int *clock_source, |
1012 | unsigned int *period_ns) | |
cb7859a9 FMH |
1013 | { |
1014 | static const unsigned pico_per_nano = 1000; | |
1015 | uint64_t temp64; | |
1016 | *clock_source = ni_tio_generic_clock_src_select(counter); | |
1017 | temp64 = ni_tio_clock_period_ps(counter, *clock_source); | |
1018 | do_div(temp64, pico_per_nano); | |
1019 | *period_ns = temp64; | |
1020 | } | |
1021 | ||
1022 | static void ni_tio_set_first_gate_modifiers(struct ni_gpct *counter, | |
0a85b6f0 | 1023 | unsigned int gate_source) |
cb7859a9 FMH |
1024 | { |
1025 | const unsigned mode_mask = Gi_Gate_Polarity_Bit | Gi_Gating_Mode_Mask; | |
1026 | unsigned mode_values = 0; | |
1027 | ||
3d34023a | 1028 | if (gate_source & CR_INVERT) |
cb7859a9 | 1029 | mode_values |= Gi_Gate_Polarity_Bit; |
3d34023a | 1030 | if (gate_source & CR_EDGE) |
cb7859a9 | 1031 | mode_values |= Gi_Rising_Edge_Gating_Bits; |
3d34023a | 1032 | else |
cb7859a9 | 1033 | mode_values |= Gi_Level_Gating_Bits; |
cb7859a9 | 1034 | ni_tio_set_bits(counter, NITIO_Gi_Mode_Reg(counter->counter_index), |
0a85b6f0 | 1035 | mode_mask, mode_values); |
cb7859a9 FMH |
1036 | } |
1037 | ||
0a85b6f0 MT |
1038 | static int ni_660x_set_first_gate(struct ni_gpct *counter, |
1039 | unsigned int gate_source) | |
cb7859a9 FMH |
1040 | { |
1041 | const unsigned selected_gate = CR_CHAN(gate_source); | |
1042 | /* bits of selected_gate that may be meaningful to input select register */ | |
1043 | const unsigned selected_gate_mask = 0x1f; | |
1044 | unsigned ni_660x_gate_select; | |
1045 | unsigned i; | |
1046 | ||
1047 | switch (selected_gate) { | |
1048 | case NI_GPCT_NEXT_SOURCE_GATE_SELECT: | |
1049 | ni_660x_gate_select = NI_660x_Next_SRC_Gate_Select; | |
1050 | break; | |
1051 | case NI_GPCT_NEXT_OUT_GATE_SELECT: | |
1052 | case NI_GPCT_LOGIC_LOW_GATE_SELECT: | |
1053 | case NI_GPCT_SOURCE_PIN_i_GATE_SELECT: | |
1054 | case NI_GPCT_GATE_PIN_i_GATE_SELECT: | |
1055 | ni_660x_gate_select = selected_gate & selected_gate_mask; | |
1056 | break; | |
1057 | default: | |
1058 | for (i = 0; i <= ni_660x_max_rtsi_channel; ++i) { | |
1059 | if (selected_gate == NI_GPCT_RTSI_GATE_SELECT(i)) { | |
1060 | ni_660x_gate_select = | |
0a85b6f0 | 1061 | selected_gate & selected_gate_mask; |
cb7859a9 FMH |
1062 | break; |
1063 | } | |
1064 | } | |
1065 | if (i <= ni_660x_max_rtsi_channel) | |
1066 | break; | |
1067 | for (i = 0; i <= ni_660x_max_gate_pin; ++i) { | |
1068 | if (selected_gate == NI_GPCT_GATE_PIN_GATE_SELECT(i)) { | |
1069 | ni_660x_gate_select = | |
0a85b6f0 | 1070 | selected_gate & selected_gate_mask; |
cb7859a9 FMH |
1071 | break; |
1072 | } | |
1073 | } | |
1074 | if (i <= ni_660x_max_gate_pin) | |
1075 | break; | |
1076 | return -EINVAL; | |
1077 | break; | |
1078 | } | |
1079 | ni_tio_set_bits(counter, | |
0a85b6f0 MT |
1080 | NITIO_Gi_Input_Select_Reg(counter->counter_index), |
1081 | Gi_Gate_Select_Mask, | |
1082 | Gi_Gate_Select_Bits(ni_660x_gate_select)); | |
cb7859a9 FMH |
1083 | return 0; |
1084 | } | |
1085 | ||
1086 | static int ni_m_series_set_first_gate(struct ni_gpct *counter, | |
0a85b6f0 | 1087 | unsigned int gate_source) |
cb7859a9 FMH |
1088 | { |
1089 | const unsigned selected_gate = CR_CHAN(gate_source); | |
1090 | /* bits of selected_gate that may be meaningful to input select register */ | |
1091 | const unsigned selected_gate_mask = 0x1f; | |
1092 | unsigned ni_m_series_gate_select; | |
1093 | unsigned i; | |
1094 | ||
1095 | switch (selected_gate) { | |
1096 | case NI_GPCT_TIMESTAMP_MUX_GATE_SELECT: | |
1097 | case NI_GPCT_AI_START2_GATE_SELECT: | |
1098 | case NI_GPCT_PXI_STAR_TRIGGER_GATE_SELECT: | |
1099 | case NI_GPCT_NEXT_OUT_GATE_SELECT: | |
1100 | case NI_GPCT_AI_START1_GATE_SELECT: | |
1101 | case NI_GPCT_NEXT_SOURCE_GATE_SELECT: | |
1102 | case NI_GPCT_ANALOG_TRIGGER_OUT_GATE_SELECT: | |
1103 | case NI_GPCT_LOGIC_LOW_GATE_SELECT: | |
1104 | ni_m_series_gate_select = selected_gate & selected_gate_mask; | |
1105 | break; | |
1106 | default: | |
1107 | for (i = 0; i <= ni_m_series_max_rtsi_channel; ++i) { | |
1108 | if (selected_gate == NI_GPCT_RTSI_GATE_SELECT(i)) { | |
1109 | ni_m_series_gate_select = | |
0a85b6f0 | 1110 | selected_gate & selected_gate_mask; |
cb7859a9 FMH |
1111 | break; |
1112 | } | |
1113 | } | |
1114 | if (i <= ni_m_series_max_rtsi_channel) | |
1115 | break; | |
1116 | for (i = 0; i <= ni_m_series_max_pfi_channel; ++i) { | |
1117 | if (selected_gate == NI_GPCT_PFI_GATE_SELECT(i)) { | |
1118 | ni_m_series_gate_select = | |
0a85b6f0 | 1119 | selected_gate & selected_gate_mask; |
cb7859a9 FMH |
1120 | break; |
1121 | } | |
1122 | } | |
1123 | if (i <= ni_m_series_max_pfi_channel) | |
1124 | break; | |
1125 | return -EINVAL; | |
1126 | break; | |
1127 | } | |
1128 | ni_tio_set_bits(counter, | |
0a85b6f0 MT |
1129 | NITIO_Gi_Input_Select_Reg(counter->counter_index), |
1130 | Gi_Gate_Select_Mask, | |
1131 | Gi_Gate_Select_Bits(ni_m_series_gate_select)); | |
cb7859a9 FMH |
1132 | return 0; |
1133 | } | |
1134 | ||
1135 | static int ni_660x_set_second_gate(struct ni_gpct *counter, | |
0a85b6f0 | 1136 | unsigned int gate_source) |
cb7859a9 FMH |
1137 | { |
1138 | struct ni_gpct_device *counter_dev = counter->counter_dev; | |
1139 | const unsigned second_gate_reg = | |
0a85b6f0 | 1140 | NITIO_Gi_Second_Gate_Reg(counter->counter_index); |
cb7859a9 FMH |
1141 | const unsigned selected_second_gate = CR_CHAN(gate_source); |
1142 | /* bits of second_gate that may be meaningful to second gate register */ | |
1143 | static const unsigned selected_second_gate_mask = 0x1f; | |
1144 | unsigned ni_660x_second_gate_select; | |
1145 | unsigned i; | |
1146 | ||
1147 | switch (selected_second_gate) { | |
1148 | case NI_GPCT_SOURCE_PIN_i_GATE_SELECT: | |
1149 | case NI_GPCT_UP_DOWN_PIN_i_GATE_SELECT: | |
1150 | case NI_GPCT_SELECTED_GATE_GATE_SELECT: | |
1151 | case NI_GPCT_NEXT_OUT_GATE_SELECT: | |
1152 | case NI_GPCT_LOGIC_LOW_GATE_SELECT: | |
1153 | ni_660x_second_gate_select = | |
0a85b6f0 | 1154 | selected_second_gate & selected_second_gate_mask; |
cb7859a9 FMH |
1155 | break; |
1156 | case NI_GPCT_NEXT_SOURCE_GATE_SELECT: | |
1157 | ni_660x_second_gate_select = | |
0a85b6f0 | 1158 | NI_660x_Next_SRC_Second_Gate_Select; |
cb7859a9 FMH |
1159 | break; |
1160 | default: | |
1161 | for (i = 0; i <= ni_660x_max_rtsi_channel; ++i) { | |
1162 | if (selected_second_gate == NI_GPCT_RTSI_GATE_SELECT(i)) { | |
1163 | ni_660x_second_gate_select = | |
0a85b6f0 MT |
1164 | selected_second_gate & |
1165 | selected_second_gate_mask; | |
cb7859a9 FMH |
1166 | break; |
1167 | } | |
1168 | } | |
1169 | if (i <= ni_660x_max_rtsi_channel) | |
1170 | break; | |
1171 | for (i = 0; i <= ni_660x_max_up_down_pin; ++i) { | |
1172 | if (selected_second_gate == | |
0a85b6f0 | 1173 | NI_GPCT_UP_DOWN_PIN_GATE_SELECT(i)) { |
cb7859a9 | 1174 | ni_660x_second_gate_select = |
0a85b6f0 MT |
1175 | selected_second_gate & |
1176 | selected_second_gate_mask; | |
cb7859a9 FMH |
1177 | break; |
1178 | } | |
1179 | } | |
1180 | if (i <= ni_660x_max_up_down_pin) | |
1181 | break; | |
1182 | return -EINVAL; | |
1183 | break; | |
1184 | }; | |
1185 | counter_dev->regs[second_gate_reg] |= Gi_Second_Gate_Mode_Bit; | |
1186 | counter_dev->regs[second_gate_reg] &= ~Gi_Second_Gate_Select_Mask; | |
1187 | counter_dev->regs[second_gate_reg] |= | |
0a85b6f0 | 1188 | Gi_Second_Gate_Select_Bits(ni_660x_second_gate_select); |
cb7859a9 | 1189 | write_register(counter, counter_dev->regs[second_gate_reg], |
0a85b6f0 | 1190 | second_gate_reg); |
cb7859a9 FMH |
1191 | return 0; |
1192 | } | |
1193 | ||
1194 | static int ni_m_series_set_second_gate(struct ni_gpct *counter, | |
0a85b6f0 | 1195 | unsigned int gate_source) |
cb7859a9 FMH |
1196 | { |
1197 | struct ni_gpct_device *counter_dev = counter->counter_dev; | |
1198 | const unsigned second_gate_reg = | |
0a85b6f0 | 1199 | NITIO_Gi_Second_Gate_Reg(counter->counter_index); |
cb7859a9 FMH |
1200 | const unsigned selected_second_gate = CR_CHAN(gate_source); |
1201 | /* bits of second_gate that may be meaningful to second gate register */ | |
1202 | static const unsigned selected_second_gate_mask = 0x1f; | |
1203 | unsigned ni_m_series_second_gate_select; | |
1204 | ||
1205 | /* FIXME: We don't know what the m-series second gate codes are, so we'll just pass | |
1206 | the bits through for now. */ | |
1207 | switch (selected_second_gate) { | |
1208 | default: | |
1209 | ni_m_series_second_gate_select = | |
0a85b6f0 | 1210 | selected_second_gate & selected_second_gate_mask; |
cb7859a9 FMH |
1211 | break; |
1212 | }; | |
1213 | counter_dev->regs[second_gate_reg] |= Gi_Second_Gate_Mode_Bit; | |
1214 | counter_dev->regs[second_gate_reg] &= ~Gi_Second_Gate_Select_Mask; | |
1215 | counter_dev->regs[second_gate_reg] |= | |
0a85b6f0 | 1216 | Gi_Second_Gate_Select_Bits(ni_m_series_second_gate_select); |
cb7859a9 | 1217 | write_register(counter, counter_dev->regs[second_gate_reg], |
0a85b6f0 | 1218 | second_gate_reg); |
cb7859a9 FMH |
1219 | return 0; |
1220 | } | |
1221 | ||
1222 | int ni_tio_set_gate_src(struct ni_gpct *counter, unsigned gate_index, | |
0a85b6f0 | 1223 | unsigned int gate_source) |
cb7859a9 FMH |
1224 | { |
1225 | struct ni_gpct_device *counter_dev = counter->counter_dev; | |
1226 | const unsigned second_gate_reg = | |
0a85b6f0 | 1227 | NITIO_Gi_Second_Gate_Reg(counter->counter_index); |
cb7859a9 FMH |
1228 | |
1229 | switch (gate_index) { | |
1230 | case 0: | |
1231 | if (CR_CHAN(gate_source) == NI_GPCT_DISABLED_GATE_SELECT) { | |
1232 | ni_tio_set_bits(counter, | |
0a85b6f0 MT |
1233 | NITIO_Gi_Mode_Reg(counter-> |
1234 | counter_index), | |
1235 | Gi_Gating_Mode_Mask, | |
1236 | Gi_Gating_Disabled_Bits); | |
cb7859a9 FMH |
1237 | return 0; |
1238 | } | |
1239 | ni_tio_set_first_gate_modifiers(counter, gate_source); | |
1240 | switch (counter_dev->variant) { | |
1241 | case ni_gpct_variant_e_series: | |
1242 | case ni_gpct_variant_m_series: | |
1243 | return ni_m_series_set_first_gate(counter, gate_source); | |
1244 | break; | |
1245 | case ni_gpct_variant_660x: | |
1246 | return ni_660x_set_first_gate(counter, gate_source); | |
1247 | break; | |
1248 | default: | |
1249 | BUG(); | |
1250 | break; | |
1251 | } | |
1252 | break; | |
1253 | case 1: | |
1254 | if (ni_tio_second_gate_registers_present(counter_dev) == 0) | |
1255 | return -EINVAL; | |
1256 | if (CR_CHAN(gate_source) == NI_GPCT_DISABLED_GATE_SELECT) { | |
1257 | counter_dev->regs[second_gate_reg] &= | |
0a85b6f0 | 1258 | ~Gi_Second_Gate_Mode_Bit; |
cb7859a9 | 1259 | write_register(counter, |
0a85b6f0 MT |
1260 | counter_dev->regs[second_gate_reg], |
1261 | second_gate_reg); | |
cb7859a9 FMH |
1262 | return 0; |
1263 | } | |
1264 | if (gate_source & CR_INVERT) { | |
1265 | counter_dev->regs[second_gate_reg] |= | |
0a85b6f0 | 1266 | Gi_Second_Gate_Polarity_Bit; |
cb7859a9 FMH |
1267 | } else { |
1268 | counter_dev->regs[second_gate_reg] &= | |
0a85b6f0 | 1269 | ~Gi_Second_Gate_Polarity_Bit; |
cb7859a9 FMH |
1270 | } |
1271 | switch (counter_dev->variant) { | |
1272 | case ni_gpct_variant_m_series: | |
1273 | return ni_m_series_set_second_gate(counter, | |
0a85b6f0 | 1274 | gate_source); |
cb7859a9 FMH |
1275 | break; |
1276 | case ni_gpct_variant_660x: | |
1277 | return ni_660x_set_second_gate(counter, gate_source); | |
1278 | break; | |
1279 | default: | |
1280 | BUG(); | |
1281 | break; | |
1282 | } | |
1283 | break; | |
1284 | default: | |
1285 | return -EINVAL; | |
1286 | break; | |
1287 | } | |
1288 | return 0; | |
1289 | } | |
3d34023a | 1290 | EXPORT_SYMBOL_GPL(ni_tio_set_gate_src); |
cb7859a9 FMH |
1291 | |
1292 | static int ni_tio_set_other_src(struct ni_gpct *counter, unsigned index, | |
0a85b6f0 | 1293 | unsigned int source) |
cb7859a9 FMH |
1294 | { |
1295 | struct ni_gpct_device *counter_dev = counter->counter_dev; | |
1296 | ||
1297 | if (counter_dev->variant == ni_gpct_variant_m_series) { | |
1298 | unsigned int abz_reg, shift, mask; | |
1299 | ||
1300 | abz_reg = NITIO_Gi_ABZ_Reg(counter->counter_index); | |
1301 | switch (index) { | |
1302 | case NI_GPCT_SOURCE_ENCODER_A: | |
1303 | shift = 10; | |
1304 | break; | |
1305 | case NI_GPCT_SOURCE_ENCODER_B: | |
1306 | shift = 5; | |
1307 | break; | |
1308 | case NI_GPCT_SOURCE_ENCODER_Z: | |
1309 | shift = 0; | |
1310 | break; | |
1311 | default: | |
1312 | return -EINVAL; | |
1313 | break; | |
1314 | } | |
1315 | mask = 0x1f << shift; | |
1316 | if (source > 0x1f) { | |
1317 | /* Disable gate */ | |
1318 | source = 0x1f; | |
1319 | } | |
1320 | counter_dev->regs[abz_reg] &= ~mask; | |
1321 | counter_dev->regs[abz_reg] |= (source << shift) & mask; | |
1322 | write_register(counter, counter_dev->regs[abz_reg], abz_reg); | |
5f74ea14 | 1323 | /* printk("%s %x %d %d\n", __func__, counter_dev->regs[abz_reg], index, source); */ |
cb7859a9 FMH |
1324 | return 0; |
1325 | } | |
1326 | return -EINVAL; | |
1327 | } | |
1328 | ||
1329 | static unsigned ni_660x_first_gate_to_generic_gate_source(unsigned | |
0a85b6f0 | 1330 | ni_660x_gate_select) |
cb7859a9 FMH |
1331 | { |
1332 | unsigned i; | |
1333 | ||
1334 | switch (ni_660x_gate_select) { | |
1335 | case NI_660x_Source_Pin_i_Gate_Select: | |
1336 | return NI_GPCT_SOURCE_PIN_i_GATE_SELECT; | |
1337 | break; | |
1338 | case NI_660x_Gate_Pin_i_Gate_Select: | |
1339 | return NI_GPCT_GATE_PIN_i_GATE_SELECT; | |
1340 | break; | |
1341 | case NI_660x_Next_SRC_Gate_Select: | |
1342 | return NI_GPCT_NEXT_SOURCE_GATE_SELECT; | |
1343 | break; | |
1344 | case NI_660x_Next_Out_Gate_Select: | |
1345 | return NI_GPCT_NEXT_OUT_GATE_SELECT; | |
1346 | break; | |
1347 | case NI_660x_Logic_Low_Gate_Select: | |
1348 | return NI_GPCT_LOGIC_LOW_GATE_SELECT; | |
1349 | break; | |
1350 | default: | |
1351 | for (i = 0; i <= ni_660x_max_rtsi_channel; ++i) { | |
1352 | if (ni_660x_gate_select == NI_660x_RTSI_Gate_Select(i)) { | |
1353 | return NI_GPCT_RTSI_GATE_SELECT(i); | |
1354 | break; | |
1355 | } | |
1356 | } | |
1357 | if (i <= ni_660x_max_rtsi_channel) | |
1358 | break; | |
1359 | for (i = 0; i <= ni_660x_max_gate_pin; ++i) { | |
1360 | if (ni_660x_gate_select == | |
0a85b6f0 | 1361 | NI_660x_Gate_Pin_Gate_Select(i)) { |
cb7859a9 FMH |
1362 | return NI_GPCT_GATE_PIN_GATE_SELECT(i); |
1363 | break; | |
1364 | } | |
1365 | } | |
1366 | if (i <= ni_660x_max_gate_pin) | |
1367 | break; | |
1368 | BUG(); | |
1369 | break; | |
1370 | } | |
1371 | return 0; | |
1372 | }; | |
1373 | ||
1374 | static unsigned ni_m_series_first_gate_to_generic_gate_source(unsigned | |
0a85b6f0 | 1375 | ni_m_series_gate_select) |
cb7859a9 FMH |
1376 | { |
1377 | unsigned i; | |
1378 | ||
1379 | switch (ni_m_series_gate_select) { | |
1380 | case NI_M_Series_Timestamp_Mux_Gate_Select: | |
1381 | return NI_GPCT_TIMESTAMP_MUX_GATE_SELECT; | |
1382 | break; | |
1383 | case NI_M_Series_AI_START2_Gate_Select: | |
1384 | return NI_GPCT_AI_START2_GATE_SELECT; | |
1385 | break; | |
1386 | case NI_M_Series_PXI_Star_Trigger_Gate_Select: | |
1387 | return NI_GPCT_PXI_STAR_TRIGGER_GATE_SELECT; | |
1388 | break; | |
1389 | case NI_M_Series_Next_Out_Gate_Select: | |
1390 | return NI_GPCT_NEXT_OUT_GATE_SELECT; | |
1391 | break; | |
1392 | case NI_M_Series_AI_START1_Gate_Select: | |
1393 | return NI_GPCT_AI_START1_GATE_SELECT; | |
1394 | break; | |
1395 | case NI_M_Series_Next_SRC_Gate_Select: | |
1396 | return NI_GPCT_NEXT_SOURCE_GATE_SELECT; | |
1397 | break; | |
1398 | case NI_M_Series_Analog_Trigger_Out_Gate_Select: | |
1399 | return NI_GPCT_ANALOG_TRIGGER_OUT_GATE_SELECT; | |
1400 | break; | |
1401 | case NI_M_Series_Logic_Low_Gate_Select: | |
1402 | return NI_GPCT_LOGIC_LOW_GATE_SELECT; | |
1403 | break; | |
1404 | default: | |
1405 | for (i = 0; i <= ni_m_series_max_rtsi_channel; ++i) { | |
1406 | if (ni_m_series_gate_select == | |
0a85b6f0 | 1407 | NI_M_Series_RTSI_Gate_Select(i)) { |
cb7859a9 FMH |
1408 | return NI_GPCT_RTSI_GATE_SELECT(i); |
1409 | break; | |
1410 | } | |
1411 | } | |
1412 | if (i <= ni_m_series_max_rtsi_channel) | |
1413 | break; | |
1414 | for (i = 0; i <= ni_m_series_max_pfi_channel; ++i) { | |
1415 | if (ni_m_series_gate_select == | |
0a85b6f0 | 1416 | NI_M_Series_PFI_Gate_Select(i)) { |
cb7859a9 FMH |
1417 | return NI_GPCT_PFI_GATE_SELECT(i); |
1418 | break; | |
1419 | } | |
1420 | } | |
1421 | if (i <= ni_m_series_max_pfi_channel) | |
1422 | break; | |
1423 | BUG(); | |
1424 | break; | |
1425 | } | |
1426 | return 0; | |
1427 | }; | |
1428 | ||
1429 | static unsigned ni_660x_second_gate_to_generic_gate_source(unsigned | |
0a85b6f0 | 1430 | ni_660x_gate_select) |
cb7859a9 FMH |
1431 | { |
1432 | unsigned i; | |
1433 | ||
1434 | switch (ni_660x_gate_select) { | |
1435 | case NI_660x_Source_Pin_i_Second_Gate_Select: | |
1436 | return NI_GPCT_SOURCE_PIN_i_GATE_SELECT; | |
1437 | break; | |
1438 | case NI_660x_Up_Down_Pin_i_Second_Gate_Select: | |
1439 | return NI_GPCT_UP_DOWN_PIN_i_GATE_SELECT; | |
1440 | break; | |
1441 | case NI_660x_Next_SRC_Second_Gate_Select: | |
1442 | return NI_GPCT_NEXT_SOURCE_GATE_SELECT; | |
1443 | break; | |
1444 | case NI_660x_Next_Out_Second_Gate_Select: | |
1445 | return NI_GPCT_NEXT_OUT_GATE_SELECT; | |
1446 | break; | |
1447 | case NI_660x_Selected_Gate_Second_Gate_Select: | |
1448 | return NI_GPCT_SELECTED_GATE_GATE_SELECT; | |
1449 | break; | |
1450 | case NI_660x_Logic_Low_Second_Gate_Select: | |
1451 | return NI_GPCT_LOGIC_LOW_GATE_SELECT; | |
1452 | break; | |
1453 | default: | |
1454 | for (i = 0; i <= ni_660x_max_rtsi_channel; ++i) { | |
1455 | if (ni_660x_gate_select == | |
0a85b6f0 | 1456 | NI_660x_RTSI_Second_Gate_Select(i)) { |
cb7859a9 FMH |
1457 | return NI_GPCT_RTSI_GATE_SELECT(i); |
1458 | break; | |
1459 | } | |
1460 | } | |
1461 | if (i <= ni_660x_max_rtsi_channel) | |
1462 | break; | |
1463 | for (i = 0; i <= ni_660x_max_up_down_pin; ++i) { | |
1464 | if (ni_660x_gate_select == | |
0a85b6f0 | 1465 | NI_660x_Up_Down_Pin_Second_Gate_Select(i)) { |
cb7859a9 FMH |
1466 | return NI_GPCT_UP_DOWN_PIN_GATE_SELECT(i); |
1467 | break; | |
1468 | } | |
1469 | } | |
1470 | if (i <= ni_660x_max_up_down_pin) | |
1471 | break; | |
1472 | BUG(); | |
1473 | break; | |
1474 | } | |
1475 | return 0; | |
1476 | }; | |
1477 | ||
1478 | static unsigned ni_m_series_second_gate_to_generic_gate_source(unsigned | |
0a85b6f0 | 1479 | ni_m_series_gate_select) |
cb7859a9 FMH |
1480 | { |
1481 | /*FIXME: the second gate sources for the m series are undocumented, so we just return | |
1482 | * the raw bits for now. */ | |
1483 | switch (ni_m_series_gate_select) { | |
1484 | default: | |
1485 | return ni_m_series_gate_select; | |
1486 | break; | |
1487 | } | |
1488 | return 0; | |
1489 | }; | |
1490 | ||
1491 | static int ni_tio_get_gate_src(struct ni_gpct *counter, unsigned gate_index, | |
0a85b6f0 | 1492 | unsigned int *gate_source) |
cb7859a9 FMH |
1493 | { |
1494 | struct ni_gpct_device *counter_dev = counter->counter_dev; | |
1495 | const unsigned mode_bits = ni_tio_get_soft_copy(counter, | |
0a85b6f0 MT |
1496 | NITIO_Gi_Mode_Reg |
1497 | (counter-> | |
1498 | counter_index)); | |
cb7859a9 | 1499 | const unsigned second_gate_reg = |
0a85b6f0 | 1500 | NITIO_Gi_Second_Gate_Reg(counter->counter_index); |
cb7859a9 FMH |
1501 | unsigned gate_select_bits; |
1502 | ||
1503 | switch (gate_index) { | |
1504 | case 0: | |
1505 | if ((mode_bits & Gi_Gating_Mode_Mask) == | |
0a85b6f0 | 1506 | Gi_Gating_Disabled_Bits) { |
cb7859a9 FMH |
1507 | *gate_source = NI_GPCT_DISABLED_GATE_SELECT; |
1508 | return 0; | |
1509 | } else { | |
1510 | gate_select_bits = | |
0a85b6f0 MT |
1511 | (ni_tio_get_soft_copy(counter, |
1512 | NITIO_Gi_Input_Select_Reg | |
1513 | (counter->counter_index)) & | |
1514 | Gi_Gate_Select_Mask) >> Gi_Gate_Select_Shift; | |
cb7859a9 FMH |
1515 | } |
1516 | switch (counter_dev->variant) { | |
1517 | case ni_gpct_variant_e_series: | |
1518 | case ni_gpct_variant_m_series: | |
1519 | *gate_source = | |
0a85b6f0 MT |
1520 | ni_m_series_first_gate_to_generic_gate_source |
1521 | (gate_select_bits); | |
cb7859a9 FMH |
1522 | break; |
1523 | case ni_gpct_variant_660x: | |
1524 | *gate_source = | |
0a85b6f0 MT |
1525 | ni_660x_first_gate_to_generic_gate_source |
1526 | (gate_select_bits); | |
cb7859a9 FMH |
1527 | break; |
1528 | default: | |
1529 | BUG(); | |
1530 | break; | |
1531 | } | |
3d34023a | 1532 | if (mode_bits & Gi_Gate_Polarity_Bit) |
cb7859a9 | 1533 | *gate_source |= CR_INVERT; |
3d34023a | 1534 | if ((mode_bits & Gi_Gating_Mode_Mask) != Gi_Level_Gating_Bits) |
cb7859a9 | 1535 | *gate_source |= CR_EDGE; |
cb7859a9 FMH |
1536 | break; |
1537 | case 1: | |
1538 | if ((mode_bits & Gi_Gating_Mode_Mask) == Gi_Gating_Disabled_Bits | |
0a85b6f0 MT |
1539 | || (counter_dev->regs[second_gate_reg] & |
1540 | Gi_Second_Gate_Mode_Bit) | |
1541 | == 0) { | |
cb7859a9 FMH |
1542 | *gate_source = NI_GPCT_DISABLED_GATE_SELECT; |
1543 | return 0; | |
1544 | } else { | |
1545 | gate_select_bits = | |
0a85b6f0 MT |
1546 | (counter_dev->regs[second_gate_reg] & |
1547 | Gi_Second_Gate_Select_Mask) >> | |
1548 | Gi_Second_Gate_Select_Shift; | |
cb7859a9 FMH |
1549 | } |
1550 | switch (counter_dev->variant) { | |
1551 | case ni_gpct_variant_e_series: | |
1552 | case ni_gpct_variant_m_series: | |
1553 | *gate_source = | |
0a85b6f0 MT |
1554 | ni_m_series_second_gate_to_generic_gate_source |
1555 | (gate_select_bits); | |
cb7859a9 FMH |
1556 | break; |
1557 | case ni_gpct_variant_660x: | |
1558 | *gate_source = | |
0a85b6f0 MT |
1559 | ni_660x_second_gate_to_generic_gate_source |
1560 | (gate_select_bits); | |
cb7859a9 FMH |
1561 | break; |
1562 | default: | |
1563 | BUG(); | |
1564 | break; | |
1565 | } | |
0a85b6f0 MT |
1566 | if (counter_dev->regs[second_gate_reg] & |
1567 | Gi_Second_Gate_Polarity_Bit) { | |
cb7859a9 FMH |
1568 | *gate_source |= CR_INVERT; |
1569 | } | |
1570 | /* second gate can't have edge/level mode set independently */ | |
3d34023a | 1571 | if ((mode_bits & Gi_Gating_Mode_Mask) != Gi_Level_Gating_Bits) |
cb7859a9 | 1572 | *gate_source |= CR_EDGE; |
cb7859a9 FMH |
1573 | break; |
1574 | default: | |
1575 | return -EINVAL; | |
1576 | break; | |
1577 | } | |
1578 | return 0; | |
1579 | } | |
1580 | ||
1581 | int ni_tio_insn_config(struct ni_gpct *counter, | |
0a85b6f0 | 1582 | struct comedi_insn *insn, unsigned int *data) |
cb7859a9 FMH |
1583 | { |
1584 | switch (data[0]) { | |
1585 | case INSN_CONFIG_SET_COUNTER_MODE: | |
1586 | return ni_tio_set_counter_mode(counter, data[1]); | |
1587 | break; | |
1588 | case INSN_CONFIG_ARM: | |
1589 | return ni_tio_arm(counter, 1, data[1]); | |
1590 | break; | |
1591 | case INSN_CONFIG_DISARM: | |
1592 | ni_tio_arm(counter, 0, 0); | |
1593 | return 0; | |
1594 | break; | |
1595 | case INSN_CONFIG_GET_COUNTER_STATUS: | |
1596 | data[1] = ni_tio_counter_status(counter); | |
1597 | data[2] = counter_status_mask; | |
1598 | return 0; | |
1599 | break; | |
1600 | case INSN_CONFIG_SET_CLOCK_SRC: | |
1601 | return ni_tio_set_clock_src(counter, data[1], data[2]); | |
1602 | break; | |
1603 | case INSN_CONFIG_GET_CLOCK_SRC: | |
1604 | ni_tio_get_clock_src(counter, &data[1], &data[2]); | |
1605 | return 0; | |
1606 | break; | |
1607 | case INSN_CONFIG_SET_GATE_SRC: | |
1608 | return ni_tio_set_gate_src(counter, data[1], data[2]); | |
1609 | break; | |
1610 | case INSN_CONFIG_GET_GATE_SRC: | |
1611 | return ni_tio_get_gate_src(counter, data[1], &data[2]); | |
1612 | break; | |
1613 | case INSN_CONFIG_SET_OTHER_SRC: | |
1614 | return ni_tio_set_other_src(counter, data[1], data[2]); | |
1615 | break; | |
1616 | case INSN_CONFIG_RESET: | |
1617 | ni_tio_reset_count_and_disarm(counter); | |
1618 | return 0; | |
1619 | break; | |
1620 | default: | |
1621 | break; | |
1622 | } | |
1623 | return -EINVAL; | |
1624 | } | |
3d34023a | 1625 | EXPORT_SYMBOL_GPL(ni_tio_insn_config); |
cb7859a9 | 1626 | |
0a85b6f0 MT |
1627 | int ni_tio_rinsn(struct ni_gpct *counter, struct comedi_insn *insn, |
1628 | unsigned int *data) | |
cb7859a9 FMH |
1629 | { |
1630 | struct ni_gpct_device *counter_dev = counter->counter_dev; | |
1631 | const unsigned channel = CR_CHAN(insn->chanspec); | |
1632 | unsigned first_read; | |
1633 | unsigned second_read; | |
1634 | unsigned correct_read; | |
1635 | ||
1636 | if (insn->n < 1) | |
1637 | return 0; | |
1638 | switch (channel) { | |
1639 | case 0: | |
1640 | ni_tio_set_bits(counter, | |
0a85b6f0 MT |
1641 | NITIO_Gi_Command_Reg(counter->counter_index), |
1642 | Gi_Save_Trace_Bit, 0); | |
cb7859a9 | 1643 | ni_tio_set_bits(counter, |
0a85b6f0 MT |
1644 | NITIO_Gi_Command_Reg(counter->counter_index), |
1645 | Gi_Save_Trace_Bit, Gi_Save_Trace_Bit); | |
cb7859a9 FMH |
1646 | /* The count doesn't get latched until the next clock edge, so it is possible the count |
1647 | may change (once) while we are reading. Since the read of the SW_Save_Reg isn't | |
1648 | atomic (apparently even when it's a 32 bit register according to 660x docs), | |
1649 | we need to read twice and make sure the reading hasn't changed. If it has, | |
1650 | a third read will be correct since the count value will definitely have latched by then. */ | |
1651 | first_read = | |
0a85b6f0 MT |
1652 | read_register(counter, |
1653 | NITIO_Gi_SW_Save_Reg(counter->counter_index)); | |
cb7859a9 | 1654 | second_read = |
0a85b6f0 MT |
1655 | read_register(counter, |
1656 | NITIO_Gi_SW_Save_Reg(counter->counter_index)); | |
cb7859a9 FMH |
1657 | if (first_read != second_read) |
1658 | correct_read = | |
0a85b6f0 MT |
1659 | read_register(counter, |
1660 | NITIO_Gi_SW_Save_Reg(counter-> | |
1661 | counter_index)); | |
cb7859a9 FMH |
1662 | else |
1663 | correct_read = first_read; | |
1664 | data[0] = correct_read; | |
1665 | return 0; | |
1666 | break; | |
1667 | case 1: | |
1668 | data[0] = | |
0a85b6f0 MT |
1669 | counter_dev-> |
1670 | regs[NITIO_Gi_LoadA_Reg(counter->counter_index)]; | |
cb7859a9 FMH |
1671 | break; |
1672 | case 2: | |
1673 | data[0] = | |
0a85b6f0 MT |
1674 | counter_dev-> |
1675 | regs[NITIO_Gi_LoadB_Reg(counter->counter_index)]; | |
cb7859a9 FMH |
1676 | break; |
1677 | }; | |
1678 | return 0; | |
1679 | } | |
3d34023a | 1680 | EXPORT_SYMBOL_GPL(ni_tio_rinsn); |
cb7859a9 FMH |
1681 | |
1682 | static unsigned ni_tio_next_load_register(struct ni_gpct *counter) | |
1683 | { | |
1684 | const unsigned bits = read_register(counter, | |
0a85b6f0 MT |
1685 | NITIO_Gxx_Status_Reg(counter-> |
1686 | counter_index)); | |
cb7859a9 | 1687 | |
091b4242 | 1688 | if (bits & Gi_Next_Load_Source_Bit(counter->counter_index)) |
cb7859a9 | 1689 | return NITIO_Gi_LoadB_Reg(counter->counter_index); |
091b4242 | 1690 | else |
cb7859a9 | 1691 | return NITIO_Gi_LoadA_Reg(counter->counter_index); |
cb7859a9 FMH |
1692 | } |
1693 | ||
0a85b6f0 MT |
1694 | int ni_tio_winsn(struct ni_gpct *counter, struct comedi_insn *insn, |
1695 | unsigned int *data) | |
cb7859a9 FMH |
1696 | { |
1697 | struct ni_gpct_device *counter_dev = counter->counter_dev; | |
1698 | const unsigned channel = CR_CHAN(insn->chanspec); | |
1699 | unsigned load_reg; | |
1700 | ||
1701 | if (insn->n < 1) | |
1702 | return 0; | |
1703 | switch (channel) { | |
1704 | case 0: | |
1705 | /* Unsafe if counter is armed. Should probably check status and return -EBUSY if armed. */ | |
1706 | /* Don't disturb load source select, just use whichever load register is already selected. */ | |
1707 | load_reg = ni_tio_next_load_register(counter); | |
1708 | write_register(counter, data[0], load_reg); | |
1709 | ni_tio_set_bits_transient(counter, | |
0a85b6f0 MT |
1710 | NITIO_Gi_Command_Reg(counter-> |
1711 | counter_index), | |
1712 | 0, 0, Gi_Load_Bit); | |
cb7859a9 FMH |
1713 | /* restore state of load reg to whatever the user set last set it to */ |
1714 | write_register(counter, counter_dev->regs[load_reg], load_reg); | |
1715 | break; | |
1716 | case 1: | |
1717 | counter_dev->regs[NITIO_Gi_LoadA_Reg(counter->counter_index)] = | |
0a85b6f0 | 1718 | data[0]; |
cb7859a9 | 1719 | write_register(counter, data[0], |
0a85b6f0 | 1720 | NITIO_Gi_LoadA_Reg(counter->counter_index)); |
cb7859a9 FMH |
1721 | break; |
1722 | case 2: | |
1723 | counter_dev->regs[NITIO_Gi_LoadB_Reg(counter->counter_index)] = | |
0a85b6f0 | 1724 | data[0]; |
cb7859a9 | 1725 | write_register(counter, data[0], |
0a85b6f0 | 1726 | NITIO_Gi_LoadB_Reg(counter->counter_index)); |
cb7859a9 FMH |
1727 | break; |
1728 | default: | |
1729 | return -EINVAL; | |
1730 | break; | |
1731 | } | |
1732 | return 0; | |
1733 | } | |
cb7859a9 | 1734 | EXPORT_SYMBOL_GPL(ni_tio_winsn); |