1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* |
3 | * Hardware driver for DAQ-STC based boards |
4 | * |
5 | * COMEDI - Linux Control and Measurement Device Interface |
6 | * Copyright (C) 1997-2001 David A. Schleef <ds@schleef.org> |
7 | * Copyright (C) 2002-2006 Frank Mori Hess <fmhess@users.sourceforge.net> |
8 | */ |
9 | |
10 | /* |
11 | * This file is meant to be included by another file, e.g., |
12 | * ni_atmio.c or ni_pcimio.c. |
13 | * |
14 | * Interrupt support originally added by Truxton Fulton <trux@truxton.com> |
15 | * |
16 | * References (ftp://ftp.natinst.com/support/manuals): |
17 | * 340747b.pdf AT-MIO E series Register Level Programmer Manual |
18 | * 341079b.pdf PCI E Series RLPM |
19 | * 340934b.pdf DAQ-STC reference manual |
20 | * |
21 | * 67xx and 611x registers (ftp://ftp.ni.com/support/daq/mhddk/documentation/) |
22 | * release_ni611x.pdf |
23 | * release_ni67xx.pdf |
24 | * |
25 | * Other possibly relevant info: |
26 | * 320517c.pdf User manual (obsolete) |
27 | * 320517f.pdf User manual (new) |
28 | * 320889a.pdf delete |
29 | * 320906c.pdf maximum signal ratings |
30 | * 321066a.pdf about 16x |
31 | * 321791a.pdf discontinuation of at-mio-16e-10 rev. c |
32 | * 321808a.pdf about at-mio-16e-10 rev P |
33 | * 321837a.pdf discontinuation of at-mio-16de-10 rev d |
34 | * 321838a.pdf about at-mio-16de-10 rev N |
35 | * |
36 | * ISSUES: |
37 | * - the interrupt routine needs to be cleaned up |
38 | * |
39 | * 2006-02-07: S-Series PCI-6143: Support has been added but is not |
40 | * fully tested as yet. Terry Barnaby, BEAM Ltd. |
41 | */ |
42 | |
43 | #include <linux/interrupt.h> |
44 | #include <linux/sched.h> |
45 | #include <linux/delay.h> |
46 | #include <linux/comedi/comedi_8255.h> |
47 | #include "mite.h" |
48 | |
49 | #ifdef PCIDMA |
50 | #define IS_PCIMIO 1 |
51 | #else |
52 | #define IS_PCIMIO 0 |
53 | #endif |
54 | |
55 | /* A timeout count */ |
56 | #define NI_TIMEOUT 1000 |
57 | |
58 | /* Note: this table must match the ai_gain_* definitions */ |
59 | static const short ni_gainlkup[][16] = { |
60 | [ai_gain_16] = {0, 1, 2, 3, 4, 5, 6, 7, |
61 | 0x100, 0x101, 0x102, 0x103, 0x104, 0x105, 0x106, 0x107}, |
62 | [ai_gain_8] = {1, 2, 4, 7, 0x101, 0x102, 0x104, 0x107}, |
63 | [ai_gain_14] = {1, 2, 3, 4, 5, 6, 7, |
64 | 0x101, 0x102, 0x103, 0x104, 0x105, 0x106, 0x107}, |
65 | [ai_gain_4] = {0, 1, 4, 7}, |
66 | [ai_gain_611x] = {0x00a, 0x00b, 0x001, 0x002, |
67 | 0x003, 0x004, 0x005, 0x006}, |
68 | [ai_gain_622x] = {0, 1, 4, 5}, |
69 | [ai_gain_628x] = {1, 2, 3, 4, 5, 6, 7}, |
70 | [ai_gain_6143] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, |
71 | }; |
72 | |
73 | static const struct comedi_lrange range_ni_E_ai = { |
74 | 16, { |
75 | BIP_RANGE(10), |
76 | BIP_RANGE(5), |
77 | BIP_RANGE(2.5), |
78 | BIP_RANGE(1), |
79 | BIP_RANGE(0.5), |
80 | BIP_RANGE(0.25), |
81 | BIP_RANGE(0.1), |
82 | BIP_RANGE(0.05), |
83 | UNI_RANGE(20), |
84 | UNI_RANGE(10), |
85 | UNI_RANGE(5), |
86 | UNI_RANGE(2), |
87 | UNI_RANGE(1), |
88 | UNI_RANGE(0.5), |
89 | UNI_RANGE(0.2), |
90 | UNI_RANGE(0.1) |
91 | } |
92 | }; |
93 | |
94 | static const struct comedi_lrange range_ni_E_ai_limited = { |
95 | 8, { |
96 | BIP_RANGE(10), |
97 | BIP_RANGE(5), |
98 | BIP_RANGE(1), |
99 | BIP_RANGE(0.1), |
100 | UNI_RANGE(10), |
101 | UNI_RANGE(5), |
102 | UNI_RANGE(1), |
103 | UNI_RANGE(0.1) |
104 | } |
105 | }; |
106 | |
107 | static const struct comedi_lrange range_ni_E_ai_limited14 = { |
108 | 14, { |
109 | BIP_RANGE(10), |
110 | BIP_RANGE(5), |
111 | BIP_RANGE(2), |
112 | BIP_RANGE(1), |
113 | BIP_RANGE(0.5), |
114 | BIP_RANGE(0.2), |
115 | BIP_RANGE(0.1), |
116 | UNI_RANGE(10), |
117 | UNI_RANGE(5), |
118 | UNI_RANGE(2), |
119 | UNI_RANGE(1), |
120 | UNI_RANGE(0.5), |
121 | UNI_RANGE(0.2), |
122 | UNI_RANGE(0.1) |
123 | } |
124 | }; |
125 | |
126 | static const struct comedi_lrange range_ni_E_ai_bipolar4 = { |
127 | 4, { |
128 | BIP_RANGE(10), |
129 | BIP_RANGE(5), |
130 | BIP_RANGE(0.5), |
131 | BIP_RANGE(0.05) |
132 | } |
133 | }; |
134 | |
135 | static const struct comedi_lrange range_ni_E_ai_611x = { |
136 | 8, { |
137 | BIP_RANGE(50), |
138 | BIP_RANGE(20), |
139 | BIP_RANGE(10), |
140 | BIP_RANGE(5), |
141 | BIP_RANGE(2), |
142 | BIP_RANGE(1), |
143 | BIP_RANGE(0.5), |
144 | BIP_RANGE(0.2) |
145 | } |
146 | }; |
147 | |
148 | static const struct comedi_lrange range_ni_M_ai_622x = { |
149 | 4, { |
150 | BIP_RANGE(10), |
151 | BIP_RANGE(5), |
152 | BIP_RANGE(1), |
153 | BIP_RANGE(0.2) |
154 | } |
155 | }; |
156 | |
157 | static const struct comedi_lrange range_ni_M_ai_628x = { |
158 | 7, { |
159 | BIP_RANGE(10), |
160 | BIP_RANGE(5), |
161 | BIP_RANGE(2), |
162 | BIP_RANGE(1), |
163 | BIP_RANGE(0.5), |
164 | BIP_RANGE(0.2), |
165 | BIP_RANGE(0.1) |
166 | } |
167 | }; |
168 | |
169 | static const struct comedi_lrange range_ni_E_ao_ext = { |
170 | 4, { |
171 | BIP_RANGE(10), |
172 | UNI_RANGE(10), |
173 | RANGE_ext(-1, 1), |
174 | RANGE_ext(0, 1) |
175 | } |
176 | }; |
177 | |
178 | static const struct comedi_lrange *const ni_range_lkup[] = { |
179 | [ai_gain_16] = &range_ni_E_ai, |
180 | [ai_gain_8] = &range_ni_E_ai_limited, |
181 | [ai_gain_14] = &range_ni_E_ai_limited14, |
182 | [ai_gain_4] = &range_ni_E_ai_bipolar4, |
183 | [ai_gain_611x] = &range_ni_E_ai_611x, |
184 | [ai_gain_622x] = &range_ni_M_ai_622x, |
185 | [ai_gain_628x] = &range_ni_M_ai_628x, |
186 | [ai_gain_6143] = &range_bipolar5 |
187 | }; |
188 | |
189 | enum aimodes { |
190 | AIMODE_NONE = 0, |
191 | AIMODE_HALF_FULL = 1, |
192 | AIMODE_SCAN = 2, |
193 | AIMODE_SAMPLE = 3, |
194 | }; |
195 | |
196 | enum ni_common_subdevices { |
197 | NI_AI_SUBDEV, |
198 | NI_AO_SUBDEV, |
199 | NI_DIO_SUBDEV, |
200 | NI_8255_DIO_SUBDEV, |
201 | NI_UNUSED_SUBDEV, |
202 | NI_CALIBRATION_SUBDEV, |
203 | NI_EEPROM_SUBDEV, |
204 | NI_PFI_DIO_SUBDEV, |
205 | NI_CS5529_CALIBRATION_SUBDEV, |
206 | NI_SERIAL_SUBDEV, |
207 | NI_RTSI_SUBDEV, |
208 | NI_GPCT0_SUBDEV, |
209 | NI_GPCT1_SUBDEV, |
210 | NI_FREQ_OUT_SUBDEV, |
211 | NI_NUM_SUBDEVICES |
212 | }; |
213 | |
214 | #define NI_GPCT_SUBDEV(x) (NI_GPCT0_SUBDEV + (x)) |
215 | |
216 | enum timebase_nanoseconds { |
217 | TIMEBASE_1_NS = 50, |
218 | TIMEBASE_2_NS = 10000 |
219 | }; |
220 | |
221 | #define SERIAL_DISABLED 0 |
222 | #define SERIAL_600NS 600 |
223 | #define SERIAL_1_2US 1200 |
224 | #define SERIAL_10US 10000 |
225 | |
226 | static const int num_adc_stages_611x = 3; |
227 | |
228 | #ifdef PCIDMA |
229 | |
230 | static void ni_writel(struct comedi_device *dev, unsigned int data, int reg) |
231 | { |
232 | writel(data, dev->mmio + reg); |
233 | } |
234 | |
235 | static void ni_writew(struct comedi_device *dev, unsigned int data, int reg) |
236 | { |
237 | writew(data, dev->mmio + reg); |
238 | } |
239 | |
240 | static void ni_writeb(struct comedi_device *dev, unsigned int data, int reg) |
241 | { |
242 | writeb(data, dev->mmio + reg); |
243 | } |
244 | |
245 | static unsigned int ni_readl(struct comedi_device *dev, int reg) |
246 | { |
247 | return readl(dev->mmio + reg); |
248 | } |
249 | |
250 | static unsigned int ni_readw(struct comedi_device *dev, int reg) |
251 | { |
252 | return readw(dev->mmio + reg); |
253 | } |
254 | |
255 | static unsigned int ni_readb(struct comedi_device *dev, int reg) |
256 | { |
257 | return readb(dev->mmio + reg); |
258 | } |
259 | |
260 | #else /* PCIDMA */ |
261 | |
262 | static void ni_writel(struct comedi_device *dev, unsigned int data, int reg) |
263 | { |
264 | outl(value: data, port: dev->iobase + reg); |
265 | } |
266 | |
267 | static void ni_writew(struct comedi_device *dev, unsigned int data, int reg) |
268 | { |
269 | outw(value: data, port: dev->iobase + reg); |
270 | } |
271 | |
272 | static void ni_writeb(struct comedi_device *dev, unsigned int data, int reg) |
273 | { |
274 | outb(value: data, port: dev->iobase + reg); |
275 | } |
276 | |
277 | static unsigned int ni_readl(struct comedi_device *dev, int reg) |
278 | { |
279 | return inl(port: dev->iobase + reg); |
280 | } |
281 | |
282 | static unsigned int ni_readw(struct comedi_device *dev, int reg) |
283 | { |
284 | return inw(port: dev->iobase + reg); |
285 | } |
286 | |
287 | static unsigned int ni_readb(struct comedi_device *dev, int reg) |
288 | { |
289 | return inb(port: dev->iobase + reg); |
290 | } |
291 | |
292 | #endif /* PCIDMA */ |
293 | |
294 | /* |
295 | * We automatically take advantage of STC registers that can be |
296 | * read/written directly in the I/O space of the board. |
297 | * |
298 | * The AT-MIO and DAQCard devices map the low 8 STC registers to |
299 | * iobase+reg*2. |
300 | * |
301 | * Most PCIMIO devices also map the low 8 STC registers but the |
302 | * 611x devices map the read registers to iobase+(addr-1)*2. |
303 | * For now non-windowed STC access is disabled if a PCIMIO device |
304 | * is detected (devpriv->mite has been initialized). |
305 | * |
306 | * The M series devices do not used windowed registers for the |
307 | * STC registers. The functions below handle the mapping of the |
308 | * windowed STC registers to the m series register offsets. |
309 | */ |
310 | |
311 | struct mio_regmap { |
312 | unsigned int mio_reg; |
313 | int size; |
314 | }; |
315 | |
316 | static const struct mio_regmap m_series_stc_write_regmap[] = { |
317 | [NISTC_INTA_ACK_REG] = { 0x104, 2 }, |
318 | [NISTC_INTB_ACK_REG] = { 0x106, 2 }, |
319 | [NISTC_AI_CMD2_REG] = { 0x108, 2 }, |
320 | [NISTC_AO_CMD2_REG] = { 0x10a, 2 }, |
321 | [NISTC_G0_CMD_REG] = { 0x10c, 2 }, |
322 | [NISTC_G1_CMD_REG] = { 0x10e, 2 }, |
323 | [NISTC_AI_CMD1_REG] = { 0x110, 2 }, |
324 | [NISTC_AO_CMD1_REG] = { 0x112, 2 }, |
325 | /* |
326 | * NISTC_DIO_OUT_REG maps to: |
327 | * { NI_M_DIO_REG, 4 } and { NI_M_SCXI_SER_DO_REG, 1 } |
328 | */ |
329 | [NISTC_DIO_OUT_REG] = { 0, 0 }, /* DOES NOT MAP CLEANLY */ |
330 | [NISTC_DIO_CTRL_REG] = { 0, 0 }, /* DOES NOT MAP CLEANLY */ |
331 | [NISTC_AI_MODE1_REG] = { 0x118, 2 }, |
332 | [NISTC_AI_MODE2_REG] = { 0x11a, 2 }, |
333 | [NISTC_AI_SI_LOADA_REG] = { 0x11c, 4 }, |
334 | [NISTC_AI_SI_LOADB_REG] = { 0x120, 4 }, |
335 | [NISTC_AI_SC_LOADA_REG] = { 0x124, 4 }, |
336 | [NISTC_AI_SC_LOADB_REG] = { 0x128, 4 }, |
337 | [NISTC_AI_SI2_LOADA_REG] = { 0x12c, 4 }, |
338 | [NISTC_AI_SI2_LOADB_REG] = { 0x130, 4 }, |
339 | [NISTC_G0_MODE_REG] = { 0x134, 2 }, |
340 | [NISTC_G1_MODE_REG] = { 0x136, 2 }, |
341 | [NISTC_G0_LOADA_REG] = { 0x138, 4 }, |
342 | [NISTC_G0_LOADB_REG] = { 0x13c, 4 }, |
343 | [NISTC_G1_LOADA_REG] = { 0x140, 4 }, |
344 | [NISTC_G1_LOADB_REG] = { 0x144, 4 }, |
345 | [NISTC_G0_INPUT_SEL_REG] = { 0x148, 2 }, |
346 | [NISTC_G1_INPUT_SEL_REG] = { 0x14a, 2 }, |
347 | [NISTC_AO_MODE1_REG] = { 0x14c, 2 }, |
348 | [NISTC_AO_MODE2_REG] = { 0x14e, 2 }, |
349 | [NISTC_AO_UI_LOADA_REG] = { 0x150, 4 }, |
350 | [NISTC_AO_UI_LOADB_REG] = { 0x154, 4 }, |
351 | [NISTC_AO_BC_LOADA_REG] = { 0x158, 4 }, |
352 | [NISTC_AO_BC_LOADB_REG] = { 0x15c, 4 }, |
353 | [NISTC_AO_UC_LOADA_REG] = { 0x160, 4 }, |
354 | [NISTC_AO_UC_LOADB_REG] = { 0x164, 4 }, |
355 | [NISTC_CLK_FOUT_REG] = { 0x170, 2 }, |
356 | [NISTC_IO_BIDIR_PIN_REG] = { 0x172, 2 }, |
357 | [NISTC_RTSI_TRIG_DIR_REG] = { 0x174, 2 }, |
358 | [NISTC_INT_CTRL_REG] = { 0x176, 2 }, |
359 | [NISTC_AI_OUT_CTRL_REG] = { 0x178, 2 }, |
360 | [NISTC_ATRIG_ETC_REG] = { 0x17a, 2 }, |
361 | [NISTC_AI_START_STOP_REG] = { 0x17c, 2 }, |
362 | [NISTC_AI_TRIG_SEL_REG] = { 0x17e, 2 }, |
363 | [NISTC_AI_DIV_LOADA_REG] = { 0x180, 4 }, |
364 | [NISTC_AO_START_SEL_REG] = { 0x184, 2 }, |
365 | [NISTC_AO_TRIG_SEL_REG] = { 0x186, 2 }, |
366 | [NISTC_G0_AUTOINC_REG] = { 0x188, 2 }, |
367 | [NISTC_G1_AUTOINC_REG] = { 0x18a, 2 }, |
368 | [NISTC_AO_MODE3_REG] = { 0x18c, 2 }, |
369 | [NISTC_RESET_REG] = { 0x190, 2 }, |
370 | [NISTC_INTA_ENA_REG] = { 0x192, 2 }, |
371 | [NISTC_INTA2_ENA_REG] = { 0, 0 }, /* E-Series only */ |
372 | [NISTC_INTB_ENA_REG] = { 0x196, 2 }, |
373 | [NISTC_INTB2_ENA_REG] = { 0, 0 }, /* E-Series only */ |
374 | [NISTC_AI_PERSONAL_REG] = { 0x19a, 2 }, |
375 | [NISTC_AO_PERSONAL_REG] = { 0x19c, 2 }, |
376 | [NISTC_RTSI_TRIGA_OUT_REG] = { 0x19e, 2 }, |
377 | [NISTC_RTSI_TRIGB_OUT_REG] = { 0x1a0, 2 }, |
378 | /* doc for following line: mhddk/nimseries/ChipObjects/tMSeries.h */ |
379 | [NISTC_RTSI_BOARD_REG] = { 0x1a2, 2 }, |
380 | [NISTC_CFG_MEM_CLR_REG] = { 0x1a4, 2 }, |
381 | [NISTC_ADC_FIFO_CLR_REG] = { 0x1a6, 2 }, |
382 | [NISTC_DAC_FIFO_CLR_REG] = { 0x1a8, 2 }, |
383 | [NISTC_AO_OUT_CTRL_REG] = { 0x1ac, 2 }, |
384 | [NISTC_AI_MODE3_REG] = { 0x1ae, 2 }, |
385 | }; |
386 | |
387 | static void m_series_stc_write(struct comedi_device *dev, |
388 | unsigned int data, unsigned int reg) |
389 | { |
390 | const struct mio_regmap *regmap; |
391 | |
392 | if (reg < ARRAY_SIZE(m_series_stc_write_regmap)) { |
393 | regmap = &m_series_stc_write_regmap[reg]; |
394 | } else { |
395 | dev_warn(dev->class_dev, "%s: unhandled register=0x%x\n" , |
396 | __func__, reg); |
397 | return; |
398 | } |
399 | |
400 | switch (regmap->size) { |
401 | case 4: |
402 | ni_writel(dev, data, reg: regmap->mio_reg); |
403 | break; |
404 | case 2: |
405 | ni_writew(dev, data, reg: regmap->mio_reg); |
406 | break; |
407 | default: |
408 | dev_warn(dev->class_dev, "%s: unmapped register=0x%x\n" , |
409 | __func__, reg); |
410 | break; |
411 | } |
412 | } |
413 | |
414 | static const struct mio_regmap m_series_stc_read_regmap[] = { |
415 | [NISTC_AI_STATUS1_REG] = { 0x104, 2 }, |
416 | [NISTC_AO_STATUS1_REG] = { 0x106, 2 }, |
417 | [NISTC_G01_STATUS_REG] = { 0x108, 2 }, |
418 | [NISTC_AI_STATUS2_REG] = { 0, 0 }, /* Unknown */ |
419 | [NISTC_AO_STATUS2_REG] = { 0x10c, 2 }, |
420 | [NISTC_DIO_IN_REG] = { 0, 0 }, /* Unknown */ |
421 | [NISTC_G0_HW_SAVE_REG] = { 0x110, 4 }, |
422 | [NISTC_G1_HW_SAVE_REG] = { 0x114, 4 }, |
423 | [NISTC_G0_SAVE_REG] = { 0x118, 4 }, |
424 | [NISTC_G1_SAVE_REG] = { 0x11c, 4 }, |
425 | [NISTC_AO_UI_SAVE_REG] = { 0x120, 4 }, |
426 | [NISTC_AO_BC_SAVE_REG] = { 0x124, 4 }, |
427 | [NISTC_AO_UC_SAVE_REG] = { 0x128, 4 }, |
428 | [NISTC_STATUS1_REG] = { 0x136, 2 }, |
429 | [NISTC_DIO_SERIAL_IN_REG] = { 0x009, 1 }, |
430 | [NISTC_STATUS2_REG] = { 0x13a, 2 }, |
431 | [NISTC_AI_SI_SAVE_REG] = { 0x180, 4 }, |
432 | [NISTC_AI_SC_SAVE_REG] = { 0x184, 4 }, |
433 | }; |
434 | |
435 | static unsigned int m_series_stc_read(struct comedi_device *dev, |
436 | unsigned int reg) |
437 | { |
438 | const struct mio_regmap *regmap; |
439 | |
440 | if (reg < ARRAY_SIZE(m_series_stc_read_regmap)) { |
441 | regmap = &m_series_stc_read_regmap[reg]; |
442 | } else { |
443 | dev_warn(dev->class_dev, "%s: unhandled register=0x%x\n" , |
444 | __func__, reg); |
445 | return 0; |
446 | } |
447 | |
448 | switch (regmap->size) { |
449 | case 4: |
450 | return ni_readl(dev, reg: regmap->mio_reg); |
451 | case 2: |
452 | return ni_readw(dev, reg: regmap->mio_reg); |
453 | case 1: |
454 | return ni_readb(dev, reg: regmap->mio_reg); |
455 | default: |
456 | dev_warn(dev->class_dev, "%s: unmapped register=0x%x\n" , |
457 | __func__, reg); |
458 | return 0; |
459 | } |
460 | } |
461 | |
462 | static void ni_stc_writew(struct comedi_device *dev, |
463 | unsigned int data, int reg) |
464 | { |
465 | struct ni_private *devpriv = dev->private; |
466 | unsigned long flags; |
467 | |
468 | if (devpriv->is_m_series) { |
469 | m_series_stc_write(dev, data, reg); |
470 | } else { |
471 | spin_lock_irqsave(&devpriv->window_lock, flags); |
472 | if (!devpriv->mite && reg < 8) { |
473 | ni_writew(dev, data, reg: reg * 2); |
474 | } else { |
475 | ni_writew(dev, data: reg, NI_E_STC_WINDOW_ADDR_REG); |
476 | ni_writew(dev, data, NI_E_STC_WINDOW_DATA_REG); |
477 | } |
478 | spin_unlock_irqrestore(lock: &devpriv->window_lock, flags); |
479 | } |
480 | } |
481 | |
482 | static void ni_stc_writel(struct comedi_device *dev, |
483 | unsigned int data, int reg) |
484 | { |
485 | struct ni_private *devpriv = dev->private; |
486 | |
487 | if (devpriv->is_m_series) { |
488 | m_series_stc_write(dev, data, reg); |
489 | } else { |
490 | ni_stc_writew(dev, data: data >> 16, reg); |
491 | ni_stc_writew(dev, data: data & 0xffff, reg: reg + 1); |
492 | } |
493 | } |
494 | |
495 | static unsigned int ni_stc_readw(struct comedi_device *dev, int reg) |
496 | { |
497 | struct ni_private *devpriv = dev->private; |
498 | unsigned long flags; |
499 | unsigned int val; |
500 | |
501 | if (devpriv->is_m_series) { |
502 | val = m_series_stc_read(dev, reg); |
503 | } else { |
504 | spin_lock_irqsave(&devpriv->window_lock, flags); |
505 | if (!devpriv->mite && reg < 8) { |
506 | val = ni_readw(dev, reg: reg * 2); |
507 | } else { |
508 | ni_writew(dev, data: reg, NI_E_STC_WINDOW_ADDR_REG); |
509 | val = ni_readw(dev, NI_E_STC_WINDOW_DATA_REG); |
510 | } |
511 | spin_unlock_irqrestore(lock: &devpriv->window_lock, flags); |
512 | } |
513 | return val; |
514 | } |
515 | |
516 | static unsigned int ni_stc_readl(struct comedi_device *dev, int reg) |
517 | { |
518 | struct ni_private *devpriv = dev->private; |
519 | unsigned int val; |
520 | |
521 | if (devpriv->is_m_series) { |
522 | val = m_series_stc_read(dev, reg); |
523 | } else { |
524 | val = ni_stc_readw(dev, reg) << 16; |
525 | val |= ni_stc_readw(dev, reg: reg + 1); |
526 | } |
527 | return val; |
528 | } |
529 | |
530 | static inline void ni_set_bitfield(struct comedi_device *dev, int reg, |
531 | unsigned int bit_mask, |
532 | unsigned int bit_values) |
533 | { |
534 | struct ni_private *devpriv = dev->private; |
535 | unsigned long flags; |
536 | |
537 | spin_lock_irqsave(&devpriv->soft_reg_copy_lock, flags); |
538 | switch (reg) { |
539 | case NISTC_INTA_ENA_REG: |
540 | devpriv->int_a_enable_reg &= ~bit_mask; |
541 | devpriv->int_a_enable_reg |= bit_values & bit_mask; |
542 | ni_stc_writew(dev, data: devpriv->int_a_enable_reg, reg); |
543 | break; |
544 | case NISTC_INTB_ENA_REG: |
545 | devpriv->int_b_enable_reg &= ~bit_mask; |
546 | devpriv->int_b_enable_reg |= bit_values & bit_mask; |
547 | ni_stc_writew(dev, data: devpriv->int_b_enable_reg, reg); |
548 | break; |
549 | case NISTC_IO_BIDIR_PIN_REG: |
550 | devpriv->io_bidirection_pin_reg &= ~bit_mask; |
551 | devpriv->io_bidirection_pin_reg |= bit_values & bit_mask; |
552 | ni_stc_writew(dev, data: devpriv->io_bidirection_pin_reg, reg); |
553 | break; |
554 | case NI_E_DMA_AI_AO_SEL_REG: |
555 | devpriv->ai_ao_select_reg &= ~bit_mask; |
556 | devpriv->ai_ao_select_reg |= bit_values & bit_mask; |
557 | ni_writeb(dev, data: devpriv->ai_ao_select_reg, reg); |
558 | break; |
559 | case NI_E_DMA_G0_G1_SEL_REG: |
560 | devpriv->g0_g1_select_reg &= ~bit_mask; |
561 | devpriv->g0_g1_select_reg |= bit_values & bit_mask; |
562 | ni_writeb(dev, data: devpriv->g0_g1_select_reg, reg); |
563 | break; |
564 | case NI_M_CDIO_DMA_SEL_REG: |
565 | devpriv->cdio_dma_select_reg &= ~bit_mask; |
566 | devpriv->cdio_dma_select_reg |= bit_values & bit_mask; |
567 | ni_writeb(dev, data: devpriv->cdio_dma_select_reg, reg); |
568 | break; |
569 | default: |
570 | dev_err(dev->class_dev, "called with invalid register %d\n" , |
571 | reg); |
572 | break; |
573 | } |
574 | spin_unlock_irqrestore(lock: &devpriv->soft_reg_copy_lock, flags); |
575 | } |
576 | |
577 | #ifdef PCIDMA |
578 | |
579 | /* selects the MITE channel to use for DMA */ |
580 | #define NI_STC_DMA_CHAN_SEL(x) (((x) < 4) ? BIT(x) : \ |
581 | ((x) == 4) ? 0x3 : \ |
582 | ((x) == 5) ? 0x5 : 0x0) |
583 | |
584 | /* DMA channel setup */ |
585 | static int ni_request_ai_mite_channel(struct comedi_device *dev) |
586 | { |
587 | struct ni_private *devpriv = dev->private; |
588 | struct mite_channel *mite_chan; |
589 | unsigned long flags; |
590 | unsigned int bits; |
591 | |
592 | spin_lock_irqsave(&devpriv->mite_channel_lock, flags); |
593 | mite_chan = mite_request_channel(devpriv->mite, devpriv->ai_mite_ring); |
594 | if (!mite_chan) { |
595 | spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); |
596 | dev_err(dev->class_dev, |
597 | "failed to reserve mite dma channel for analog input\n" ); |
598 | return -EBUSY; |
599 | } |
600 | mite_chan->dir = COMEDI_INPUT; |
601 | devpriv->ai_mite_chan = mite_chan; |
602 | |
603 | bits = NI_STC_DMA_CHAN_SEL(mite_chan->channel); |
604 | ni_set_bitfield(dev, NI_E_DMA_AI_AO_SEL_REG, |
605 | NI_E_DMA_AI_SEL_MASK, NI_E_DMA_AI_SEL(bits)); |
606 | |
607 | spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); |
608 | return 0; |
609 | } |
610 | |
611 | static int ni_request_ao_mite_channel(struct comedi_device *dev) |
612 | { |
613 | struct ni_private *devpriv = dev->private; |
614 | struct mite_channel *mite_chan; |
615 | unsigned long flags; |
616 | unsigned int bits; |
617 | |
618 | spin_lock_irqsave(&devpriv->mite_channel_lock, flags); |
619 | mite_chan = mite_request_channel(devpriv->mite, devpriv->ao_mite_ring); |
620 | if (!mite_chan) { |
621 | spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); |
622 | dev_err(dev->class_dev, |
623 | "failed to reserve mite dma channel for analog output\n" ); |
624 | return -EBUSY; |
625 | } |
626 | mite_chan->dir = COMEDI_OUTPUT; |
627 | devpriv->ao_mite_chan = mite_chan; |
628 | |
629 | bits = NI_STC_DMA_CHAN_SEL(mite_chan->channel); |
630 | ni_set_bitfield(dev, NI_E_DMA_AI_AO_SEL_REG, |
631 | NI_E_DMA_AO_SEL_MASK, NI_E_DMA_AO_SEL(bits)); |
632 | |
633 | spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); |
634 | return 0; |
635 | } |
636 | |
637 | static int ni_request_gpct_mite_channel(struct comedi_device *dev, |
638 | unsigned int gpct_index, |
639 | enum comedi_io_direction direction) |
640 | { |
641 | struct ni_private *devpriv = dev->private; |
642 | struct ni_gpct *counter = &devpriv->counter_dev->counters[gpct_index]; |
643 | struct mite_channel *mite_chan; |
644 | unsigned long flags; |
645 | unsigned int bits; |
646 | |
647 | spin_lock_irqsave(&devpriv->mite_channel_lock, flags); |
648 | mite_chan = mite_request_channel(devpriv->mite, |
649 | devpriv->gpct_mite_ring[gpct_index]); |
650 | if (!mite_chan) { |
651 | spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); |
652 | dev_err(dev->class_dev, |
653 | "failed to reserve mite dma channel for counter\n" ); |
654 | return -EBUSY; |
655 | } |
656 | mite_chan->dir = direction; |
657 | ni_tio_set_mite_channel(counter, mite_chan); |
658 | |
659 | bits = NI_STC_DMA_CHAN_SEL(mite_chan->channel); |
660 | ni_set_bitfield(dev, NI_E_DMA_G0_G1_SEL_REG, |
661 | NI_E_DMA_G0_G1_SEL_MASK(gpct_index), |
662 | NI_E_DMA_G0_G1_SEL(gpct_index, bits)); |
663 | |
664 | spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); |
665 | return 0; |
666 | } |
667 | |
668 | static int ni_request_cdo_mite_channel(struct comedi_device *dev) |
669 | { |
670 | struct ni_private *devpriv = dev->private; |
671 | struct mite_channel *mite_chan; |
672 | unsigned long flags; |
673 | unsigned int bits; |
674 | |
675 | spin_lock_irqsave(&devpriv->mite_channel_lock, flags); |
676 | mite_chan = mite_request_channel(devpriv->mite, devpriv->cdo_mite_ring); |
677 | if (!mite_chan) { |
678 | spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); |
679 | dev_err(dev->class_dev, |
680 | "failed to reserve mite dma channel for correlated digital output\n" ); |
681 | return -EBUSY; |
682 | } |
683 | mite_chan->dir = COMEDI_OUTPUT; |
684 | devpriv->cdo_mite_chan = mite_chan; |
685 | |
686 | /* |
687 | * XXX just guessing NI_STC_DMA_CHAN_SEL() |
688 | * returns the right bits, under the assumption the cdio dma |
689 | * selection works just like ai/ao/gpct. |
690 | * Definitely works for dma channels 0 and 1. |
691 | */ |
692 | bits = NI_STC_DMA_CHAN_SEL(mite_chan->channel); |
693 | ni_set_bitfield(dev, NI_M_CDIO_DMA_SEL_REG, |
694 | NI_M_CDIO_DMA_SEL_CDO_MASK, |
695 | NI_M_CDIO_DMA_SEL_CDO(bits)); |
696 | |
697 | spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); |
698 | return 0; |
699 | } |
700 | #endif /* PCIDMA */ |
701 | |
702 | static void ni_release_ai_mite_channel(struct comedi_device *dev) |
703 | { |
704 | #ifdef PCIDMA |
705 | struct ni_private *devpriv = dev->private; |
706 | unsigned long flags; |
707 | |
708 | spin_lock_irqsave(&devpriv->mite_channel_lock, flags); |
709 | if (devpriv->ai_mite_chan) { |
710 | ni_set_bitfield(dev, NI_E_DMA_AI_AO_SEL_REG, |
711 | NI_E_DMA_AI_SEL_MASK, 0); |
712 | mite_release_channel(devpriv->ai_mite_chan); |
713 | devpriv->ai_mite_chan = NULL; |
714 | } |
715 | spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); |
716 | #endif /* PCIDMA */ |
717 | } |
718 | |
719 | static void ni_release_ao_mite_channel(struct comedi_device *dev) |
720 | { |
721 | #ifdef PCIDMA |
722 | struct ni_private *devpriv = dev->private; |
723 | unsigned long flags; |
724 | |
725 | spin_lock_irqsave(&devpriv->mite_channel_lock, flags); |
726 | if (devpriv->ao_mite_chan) { |
727 | ni_set_bitfield(dev, NI_E_DMA_AI_AO_SEL_REG, |
728 | NI_E_DMA_AO_SEL_MASK, 0); |
729 | mite_release_channel(devpriv->ao_mite_chan); |
730 | devpriv->ao_mite_chan = NULL; |
731 | } |
732 | spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); |
733 | #endif /* PCIDMA */ |
734 | } |
735 | |
736 | #ifdef PCIDMA |
737 | static void ni_release_gpct_mite_channel(struct comedi_device *dev, |
738 | unsigned int gpct_index) |
739 | { |
740 | struct ni_private *devpriv = dev->private; |
741 | unsigned long flags; |
742 | |
743 | spin_lock_irqsave(&devpriv->mite_channel_lock, flags); |
744 | if (devpriv->counter_dev->counters[gpct_index].mite_chan) { |
745 | struct mite_channel *mite_chan = |
746 | devpriv->counter_dev->counters[gpct_index].mite_chan; |
747 | |
748 | ni_set_bitfield(dev, NI_E_DMA_G0_G1_SEL_REG, |
749 | NI_E_DMA_G0_G1_SEL_MASK(gpct_index), 0); |
750 | ni_tio_set_mite_channel(&devpriv->counter_dev->counters[gpct_index], |
751 | NULL); |
752 | mite_release_channel(mite_chan); |
753 | } |
754 | spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); |
755 | } |
756 | |
757 | static void ni_release_cdo_mite_channel(struct comedi_device *dev) |
758 | { |
759 | struct ni_private *devpriv = dev->private; |
760 | unsigned long flags; |
761 | |
762 | spin_lock_irqsave(&devpriv->mite_channel_lock, flags); |
763 | if (devpriv->cdo_mite_chan) { |
764 | ni_set_bitfield(dev, NI_M_CDIO_DMA_SEL_REG, |
765 | NI_M_CDIO_DMA_SEL_CDO_MASK, 0); |
766 | mite_release_channel(devpriv->cdo_mite_chan); |
767 | devpriv->cdo_mite_chan = NULL; |
768 | } |
769 | spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); |
770 | } |
771 | |
772 | static void ni_e_series_enable_second_irq(struct comedi_device *dev, |
773 | unsigned int gpct_index, short enable) |
774 | { |
775 | struct ni_private *devpriv = dev->private; |
776 | unsigned int val = 0; |
777 | int reg; |
778 | |
779 | if (devpriv->is_m_series || gpct_index > 1) |
780 | return; |
781 | |
782 | /* |
783 | * e-series boards use the second irq signals to generate |
784 | * dma requests for their counters |
785 | */ |
786 | if (gpct_index == 0) { |
787 | reg = NISTC_INTA2_ENA_REG; |
788 | if (enable) |
789 | val = NISTC_INTA_ENA_G0_GATE; |
790 | } else { |
791 | reg = NISTC_INTB2_ENA_REG; |
792 | if (enable) |
793 | val = NISTC_INTB_ENA_G1_GATE; |
794 | } |
795 | ni_stc_writew(dev, val, reg); |
796 | } |
797 | #endif /* PCIDMA */ |
798 | |
799 | static void ni_clear_ai_fifo(struct comedi_device *dev) |
800 | { |
801 | struct ni_private *devpriv = dev->private; |
802 | static const int timeout = 10000; |
803 | int i; |
804 | |
805 | if (devpriv->is_6143) { |
806 | /* Flush the 6143 data FIFO */ |
807 | ni_writel(dev, data: 0x10, NI6143_AI_FIFO_CTRL_REG); |
808 | ni_writel(dev, data: 0x00, NI6143_AI_FIFO_CTRL_REG); |
809 | /* Wait for complete */ |
810 | for (i = 0; i < timeout; i++) { |
811 | if (!(ni_readl(dev, NI6143_AI_FIFO_STATUS_REG) & 0x10)) |
812 | break; |
813 | udelay(1); |
814 | } |
815 | if (i == timeout) |
816 | dev_err(dev->class_dev, "FIFO flush timeout\n" ); |
817 | } else { |
818 | ni_stc_writew(dev, data: 1, NISTC_ADC_FIFO_CLR_REG); |
819 | if (devpriv->is_625x) { |
820 | ni_writeb(dev, data: 0, NI_M_STATIC_AI_CTRL_REG(0)); |
821 | ni_writeb(dev, data: 1, NI_M_STATIC_AI_CTRL_REG(0)); |
822 | #if 0 |
823 | /* |
824 | * The NI example code does 3 convert pulses for 625x |
825 | * boards, But that appears to be wrong in practice. |
826 | */ |
827 | ni_stc_writew(dev, NISTC_AI_CMD1_CONVERT_PULSE, |
828 | NISTC_AI_CMD1_REG); |
829 | ni_stc_writew(dev, NISTC_AI_CMD1_CONVERT_PULSE, |
830 | NISTC_AI_CMD1_REG); |
831 | ni_stc_writew(dev, NISTC_AI_CMD1_CONVERT_PULSE, |
832 | NISTC_AI_CMD1_REG); |
833 | #endif |
834 | } |
835 | } |
836 | } |
837 | |
838 | static inline void ni_ao_win_outw(struct comedi_device *dev, |
839 | unsigned int data, int addr) |
840 | { |
841 | struct ni_private *devpriv = dev->private; |
842 | unsigned long flags; |
843 | |
844 | spin_lock_irqsave(&devpriv->window_lock, flags); |
845 | ni_writew(dev, data: addr, NI611X_AO_WINDOW_ADDR_REG); |
846 | ni_writew(dev, data, NI611X_AO_WINDOW_DATA_REG); |
847 | spin_unlock_irqrestore(lock: &devpriv->window_lock, flags); |
848 | } |
849 | |
850 | static inline void ni_ao_win_outl(struct comedi_device *dev, |
851 | unsigned int data, int addr) |
852 | { |
853 | struct ni_private *devpriv = dev->private; |
854 | unsigned long flags; |
855 | |
856 | spin_lock_irqsave(&devpriv->window_lock, flags); |
857 | ni_writew(dev, data: addr, NI611X_AO_WINDOW_ADDR_REG); |
858 | ni_writel(dev, data, NI611X_AO_WINDOW_DATA_REG); |
859 | spin_unlock_irqrestore(lock: &devpriv->window_lock, flags); |
860 | } |
861 | |
862 | static inline unsigned short ni_ao_win_inw(struct comedi_device *dev, int addr) |
863 | { |
864 | struct ni_private *devpriv = dev->private; |
865 | unsigned long flags; |
866 | unsigned short data; |
867 | |
868 | spin_lock_irqsave(&devpriv->window_lock, flags); |
869 | ni_writew(dev, data: addr, NI611X_AO_WINDOW_ADDR_REG); |
870 | data = ni_readw(dev, NI611X_AO_WINDOW_DATA_REG); |
871 | spin_unlock_irqrestore(lock: &devpriv->window_lock, flags); |
872 | return data; |
873 | } |
874 | |
875 | /* |
876 | * ni_set_bits( ) allows different parts of the ni_mio_common driver to |
877 | * share registers (such as Interrupt_A_Register) without interfering with |
878 | * each other. |
879 | * |
880 | * NOTE: the switch/case statements are optimized out for a constant argument |
881 | * so this is actually quite fast--- If you must wrap another function around |
882 | * this make it inline to avoid a large speed penalty. |
883 | * |
884 | * value should only be 1 or 0. |
885 | */ |
886 | static inline void ni_set_bits(struct comedi_device *dev, int reg, |
887 | unsigned int bits, unsigned int value) |
888 | { |
889 | unsigned int bit_values; |
890 | |
891 | if (value) |
892 | bit_values = bits; |
893 | else |
894 | bit_values = 0; |
895 | ni_set_bitfield(dev, reg, bit_mask: bits, bit_values); |
896 | } |
897 | |
898 | #ifdef PCIDMA |
899 | static void ni_sync_ai_dma(struct comedi_device *dev) |
900 | { |
901 | struct ni_private *devpriv = dev->private; |
902 | struct comedi_subdevice *s = dev->read_subdev; |
903 | unsigned long flags; |
904 | |
905 | spin_lock_irqsave(&devpriv->mite_channel_lock, flags); |
906 | if (devpriv->ai_mite_chan) |
907 | mite_sync_dma(devpriv->ai_mite_chan, s); |
908 | spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); |
909 | } |
910 | |
911 | static int ni_ai_drain_dma(struct comedi_device *dev) |
912 | { |
913 | struct ni_private *devpriv = dev->private; |
914 | int i; |
915 | static const int timeout = 10000; |
916 | unsigned long flags; |
917 | int retval = 0; |
918 | |
919 | spin_lock_irqsave(&devpriv->mite_channel_lock, flags); |
920 | if (devpriv->ai_mite_chan) { |
921 | for (i = 0; i < timeout; i++) { |
922 | if ((ni_stc_readw(dev, NISTC_AI_STATUS1_REG) & |
923 | NISTC_AI_STATUS1_FIFO_E) && |
924 | mite_bytes_in_transit(devpriv->ai_mite_chan) == 0) |
925 | break; |
926 | udelay(5); |
927 | } |
928 | if (i == timeout) { |
929 | dev_err(dev->class_dev, "timed out\n" ); |
930 | dev_err(dev->class_dev, |
931 | "mite_bytes_in_transit=%i, AI_Status1_Register=0x%x\n" , |
932 | mite_bytes_in_transit(devpriv->ai_mite_chan), |
933 | ni_stc_readw(dev, NISTC_AI_STATUS1_REG)); |
934 | retval = -1; |
935 | } |
936 | } |
937 | spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); |
938 | |
939 | ni_sync_ai_dma(dev); |
940 | |
941 | return retval; |
942 | } |
943 | |
944 | static int ni_ao_wait_for_dma_load(struct comedi_device *dev) |
945 | { |
946 | static const int timeout = 10000; |
947 | int i; |
948 | |
949 | for (i = 0; i < timeout; i++) { |
950 | unsigned short b_status; |
951 | |
952 | b_status = ni_stc_readw(dev, NISTC_AO_STATUS1_REG); |
953 | if (b_status & NISTC_AO_STATUS1_FIFO_HF) |
954 | break; |
955 | /* |
956 | * If we poll too often, the pci bus activity seems |
957 | * to slow the dma transfer down. |
958 | */ |
959 | usleep_range(10, 100); |
960 | } |
961 | if (i == timeout) { |
962 | dev_err(dev->class_dev, "timed out waiting for dma load\n" ); |
963 | return -EPIPE; |
964 | } |
965 | return 0; |
966 | } |
967 | #endif /* PCIDMA */ |
968 | |
969 | #ifndef PCIDMA |
970 | |
971 | static void ni_ao_fifo_load(struct comedi_device *dev, |
972 | struct comedi_subdevice *s, int n) |
973 | { |
974 | struct ni_private *devpriv = dev->private; |
975 | int i; |
976 | unsigned short d; |
977 | unsigned int packed_data; |
978 | |
979 | for (i = 0; i < n; i++) { |
980 | comedi_buf_read_samples(s, data: &d, nsamples: 1); |
981 | |
982 | if (devpriv->is_6xxx) { |
983 | packed_data = d & 0xffff; |
984 | /* 6711 only has 16 bit wide ao fifo */ |
985 | if (!devpriv->is_6711) { |
986 | comedi_buf_read_samples(s, data: &d, nsamples: 1); |
987 | i++; |
988 | packed_data |= (d << 16) & 0xffff0000; |
989 | } |
990 | ni_writel(dev, data: packed_data, NI611X_AO_FIFO_DATA_REG); |
991 | } else { |
992 | ni_writew(dev, data: d, NI_E_AO_FIFO_DATA_REG); |
993 | } |
994 | } |
995 | } |
996 | |
997 | /* |
998 | * There's a small problem if the FIFO gets really low and we |
999 | * don't have the data to fill it. Basically, if after we fill |
1000 | * the FIFO with all the data available, the FIFO is _still_ |
1001 | * less than half full, we never clear the interrupt. If the |
1002 | * IRQ is in edge mode, we never get another interrupt, because |
1003 | * this one wasn't cleared. If in level mode, we get flooded |
1004 | * with interrupts that we can't fulfill, because nothing ever |
1005 | * gets put into the buffer. |
1006 | * |
1007 | * This kind of situation is recoverable, but it is easier to |
1008 | * just pretend we had a FIFO underrun, since there is a good |
1009 | * chance it will happen anyway. This is _not_ the case for |
1010 | * RT code, as RT code might purposely be running close to the |
1011 | * metal. Needs to be fixed eventually. |
1012 | */ |
1013 | static int ni_ao_fifo_half_empty(struct comedi_device *dev, |
1014 | struct comedi_subdevice *s) |
1015 | { |
1016 | const struct ni_board_struct *board = dev->board_ptr; |
1017 | unsigned int nbytes; |
1018 | unsigned int nsamples; |
1019 | |
1020 | nbytes = comedi_buf_read_n_available(s); |
1021 | if (nbytes == 0) { |
1022 | s->async->events |= COMEDI_CB_OVERFLOW; |
1023 | return 0; |
1024 | } |
1025 | |
1026 | nsamples = comedi_bytes_to_samples(s, nbytes); |
1027 | if (nsamples > board->ao_fifo_depth / 2) |
1028 | nsamples = board->ao_fifo_depth / 2; |
1029 | |
1030 | ni_ao_fifo_load(dev, s, n: nsamples); |
1031 | |
1032 | return 1; |
1033 | } |
1034 | |
1035 | static int ni_ao_prep_fifo(struct comedi_device *dev, |
1036 | struct comedi_subdevice *s) |
1037 | { |
1038 | const struct ni_board_struct *board = dev->board_ptr; |
1039 | struct ni_private *devpriv = dev->private; |
1040 | unsigned int nbytes; |
1041 | unsigned int nsamples; |
1042 | |
1043 | /* reset fifo */ |
1044 | ni_stc_writew(dev, data: 1, NISTC_DAC_FIFO_CLR_REG); |
1045 | if (devpriv->is_6xxx) |
1046 | ni_ao_win_outl(dev, data: 0x6, NI611X_AO_FIFO_OFFSET_LOAD_REG); |
1047 | |
1048 | /* load some data */ |
1049 | nbytes = comedi_buf_read_n_available(s); |
1050 | if (nbytes == 0) |
1051 | return 0; |
1052 | |
1053 | nsamples = comedi_bytes_to_samples(s, nbytes); |
1054 | if (nsamples > board->ao_fifo_depth) |
1055 | nsamples = board->ao_fifo_depth; |
1056 | |
1057 | ni_ao_fifo_load(dev, s, n: nsamples); |
1058 | |
1059 | return nsamples; |
1060 | } |
1061 | |
1062 | static void ni_ai_fifo_read(struct comedi_device *dev, |
1063 | struct comedi_subdevice *s, int n) |
1064 | { |
1065 | struct ni_private *devpriv = dev->private; |
1066 | struct comedi_async *async = s->async; |
1067 | unsigned int dl; |
1068 | unsigned short data; |
1069 | int i; |
1070 | |
1071 | if (devpriv->is_611x) { |
1072 | for (i = 0; i < n / 2; i++) { |
1073 | dl = ni_readl(dev, NI611X_AI_FIFO_DATA_REG); |
1074 | /* This may get the hi/lo data in the wrong order */ |
1075 | data = (dl >> 16) & 0xffff; |
1076 | comedi_buf_write_samples(s, data: &data, nsamples: 1); |
1077 | data = dl & 0xffff; |
1078 | comedi_buf_write_samples(s, data: &data, nsamples: 1); |
1079 | } |
1080 | /* Check if there's a single sample stuck in the FIFO */ |
1081 | if (n % 2) { |
1082 | dl = ni_readl(dev, NI611X_AI_FIFO_DATA_REG); |
1083 | data = dl & 0xffff; |
1084 | comedi_buf_write_samples(s, data: &data, nsamples: 1); |
1085 | } |
1086 | } else if (devpriv->is_6143) { |
1087 | /* |
1088 | * This just reads the FIFO assuming the data is present, |
1089 | * no checks on the FIFO status are performed. |
1090 | */ |
1091 | for (i = 0; i < n / 2; i++) { |
1092 | dl = ni_readl(dev, NI6143_AI_FIFO_DATA_REG); |
1093 | |
1094 | data = (dl >> 16) & 0xffff; |
1095 | comedi_buf_write_samples(s, data: &data, nsamples: 1); |
1096 | data = dl & 0xffff; |
1097 | comedi_buf_write_samples(s, data: &data, nsamples: 1); |
1098 | } |
1099 | if (n % 2) { |
1100 | /* Assume there is a single sample stuck in the FIFO */ |
1101 | /* Get stranded sample into FIFO */ |
1102 | ni_writel(dev, data: 0x01, NI6143_AI_FIFO_CTRL_REG); |
1103 | dl = ni_readl(dev, NI6143_AI_FIFO_DATA_REG); |
1104 | data = (dl >> 16) & 0xffff; |
1105 | comedi_buf_write_samples(s, data: &data, nsamples: 1); |
1106 | } |
1107 | } else { |
1108 | if (n > ARRAY_SIZE(devpriv->ai_fifo_buffer)) { |
1109 | dev_err(dev->class_dev, |
1110 | "bug! ai_fifo_buffer too small\n" ); |
1111 | async->events |= COMEDI_CB_ERROR; |
1112 | return; |
1113 | } |
1114 | for (i = 0; i < n; i++) { |
1115 | devpriv->ai_fifo_buffer[i] = |
1116 | ni_readw(dev, NI_E_AI_FIFO_DATA_REG); |
1117 | } |
1118 | comedi_buf_write_samples(s, data: devpriv->ai_fifo_buffer, nsamples: n); |
1119 | } |
1120 | } |
1121 | |
1122 | static void ni_handle_fifo_half_full(struct comedi_device *dev) |
1123 | { |
1124 | const struct ni_board_struct *board = dev->board_ptr; |
1125 | struct comedi_subdevice *s = dev->read_subdev; |
1126 | int n; |
1127 | |
1128 | n = board->ai_fifo_depth / 2; |
1129 | |
1130 | ni_ai_fifo_read(dev, s, n); |
1131 | } |
1132 | #endif |
1133 | |
1134 | /* Empties the AI fifo */ |
1135 | static void ni_handle_fifo_dregs(struct comedi_device *dev) |
1136 | { |
1137 | struct ni_private *devpriv = dev->private; |
1138 | struct comedi_subdevice *s = dev->read_subdev; |
1139 | unsigned int dl; |
1140 | unsigned short data; |
1141 | int i; |
1142 | |
1143 | if (devpriv->is_611x) { |
1144 | while ((ni_stc_readw(dev, NISTC_AI_STATUS1_REG) & |
1145 | NISTC_AI_STATUS1_FIFO_E) == 0) { |
1146 | dl = ni_readl(dev, NI611X_AI_FIFO_DATA_REG); |
1147 | |
1148 | /* This may get the hi/lo data in the wrong order */ |
1149 | data = dl >> 16; |
1150 | comedi_buf_write_samples(s, data: &data, nsamples: 1); |
1151 | data = dl & 0xffff; |
1152 | comedi_buf_write_samples(s, data: &data, nsamples: 1); |
1153 | } |
1154 | } else if (devpriv->is_6143) { |
1155 | i = 0; |
1156 | while (ni_readl(dev, NI6143_AI_FIFO_STATUS_REG) & 0x04) { |
1157 | dl = ni_readl(dev, NI6143_AI_FIFO_DATA_REG); |
1158 | |
1159 | /* This may get the hi/lo data in the wrong order */ |
1160 | data = dl >> 16; |
1161 | comedi_buf_write_samples(s, data: &data, nsamples: 1); |
1162 | data = dl & 0xffff; |
1163 | comedi_buf_write_samples(s, data: &data, nsamples: 1); |
1164 | i += 2; |
1165 | } |
1166 | /* Check if stranded sample is present */ |
1167 | if (ni_readl(dev, NI6143_AI_FIFO_STATUS_REG) & 0x01) { |
1168 | /* Get stranded sample into FIFO */ |
1169 | ni_writel(dev, data: 0x01, NI6143_AI_FIFO_CTRL_REG); |
1170 | dl = ni_readl(dev, NI6143_AI_FIFO_DATA_REG); |
1171 | data = (dl >> 16) & 0xffff; |
1172 | comedi_buf_write_samples(s, data: &data, nsamples: 1); |
1173 | } |
1174 | |
1175 | } else { |
1176 | unsigned short fe; /* fifo empty */ |
1177 | |
1178 | fe = ni_stc_readw(dev, NISTC_AI_STATUS1_REG) & |
1179 | NISTC_AI_STATUS1_FIFO_E; |
1180 | while (fe == 0) { |
1181 | for (i = 0; |
1182 | i < ARRAY_SIZE(devpriv->ai_fifo_buffer); i++) { |
1183 | fe = ni_stc_readw(dev, NISTC_AI_STATUS1_REG) & |
1184 | NISTC_AI_STATUS1_FIFO_E; |
1185 | if (fe) |
1186 | break; |
1187 | devpriv->ai_fifo_buffer[i] = |
1188 | ni_readw(dev, NI_E_AI_FIFO_DATA_REG); |
1189 | } |
1190 | comedi_buf_write_samples(s, data: devpriv->ai_fifo_buffer, nsamples: i); |
1191 | } |
1192 | } |
1193 | } |
1194 | |
1195 | static void get_last_sample_611x(struct comedi_device *dev) |
1196 | { |
1197 | struct ni_private *devpriv = dev->private; |
1198 | struct comedi_subdevice *s = dev->read_subdev; |
1199 | unsigned short data; |
1200 | unsigned int dl; |
1201 | |
1202 | if (!devpriv->is_611x) |
1203 | return; |
1204 | |
1205 | /* Check if there's a single sample stuck in the FIFO */ |
1206 | if (ni_readb(dev, NI_E_STATUS_REG) & 0x80) { |
1207 | dl = ni_readl(dev, NI611X_AI_FIFO_DATA_REG); |
1208 | data = dl & 0xffff; |
1209 | comedi_buf_write_samples(s, data: &data, nsamples: 1); |
1210 | } |
1211 | } |
1212 | |
1213 | static void get_last_sample_6143(struct comedi_device *dev) |
1214 | { |
1215 | struct ni_private *devpriv = dev->private; |
1216 | struct comedi_subdevice *s = dev->read_subdev; |
1217 | unsigned short data; |
1218 | unsigned int dl; |
1219 | |
1220 | if (!devpriv->is_6143) |
1221 | return; |
1222 | |
1223 | /* Check if there's a single sample stuck in the FIFO */ |
1224 | if (ni_readl(dev, NI6143_AI_FIFO_STATUS_REG) & 0x01) { |
1225 | /* Get stranded sample into FIFO */ |
1226 | ni_writel(dev, data: 0x01, NI6143_AI_FIFO_CTRL_REG); |
1227 | dl = ni_readl(dev, NI6143_AI_FIFO_DATA_REG); |
1228 | |
1229 | /* This may get the hi/lo data in the wrong order */ |
1230 | data = (dl >> 16) & 0xffff; |
1231 | comedi_buf_write_samples(s, data: &data, nsamples: 1); |
1232 | } |
1233 | } |
1234 | |
1235 | static void shutdown_ai_command(struct comedi_device *dev) |
1236 | { |
1237 | struct comedi_subdevice *s = dev->read_subdev; |
1238 | |
1239 | #ifdef PCIDMA |
1240 | ni_ai_drain_dma(dev); |
1241 | #endif |
1242 | ni_handle_fifo_dregs(dev); |
1243 | get_last_sample_611x(dev); |
1244 | get_last_sample_6143(dev); |
1245 | |
1246 | s->async->events |= COMEDI_CB_EOA; |
1247 | } |
1248 | |
1249 | static void ni_handle_eos(struct comedi_device *dev, struct comedi_subdevice *s) |
1250 | { |
1251 | struct ni_private *devpriv = dev->private; |
1252 | |
1253 | if (devpriv->aimode == AIMODE_SCAN) { |
1254 | #ifdef PCIDMA |
1255 | static const int timeout = 10; |
1256 | int i; |
1257 | |
1258 | for (i = 0; i < timeout; i++) { |
1259 | ni_sync_ai_dma(dev); |
1260 | if ((s->async->events & COMEDI_CB_EOS)) |
1261 | break; |
1262 | udelay(1); |
1263 | } |
1264 | #else |
1265 | ni_handle_fifo_dregs(dev); |
1266 | s->async->events |= COMEDI_CB_EOS; |
1267 | #endif |
1268 | } |
1269 | /* handle special case of single scan */ |
1270 | if (devpriv->ai_cmd2 & NISTC_AI_CMD2_END_ON_EOS) |
1271 | shutdown_ai_command(dev); |
1272 | } |
1273 | |
1274 | static void handle_gpct_interrupt(struct comedi_device *dev, |
1275 | unsigned short counter_index) |
1276 | { |
1277 | #ifdef PCIDMA |
1278 | struct ni_private *devpriv = dev->private; |
1279 | struct comedi_subdevice *s; |
1280 | |
1281 | s = &dev->subdevices[NI_GPCT_SUBDEV(counter_index)]; |
1282 | |
1283 | ni_tio_handle_interrupt(&devpriv->counter_dev->counters[counter_index], |
1284 | s); |
1285 | comedi_handle_events(dev, s); |
1286 | #endif |
1287 | } |
1288 | |
1289 | static void ack_a_interrupt(struct comedi_device *dev, unsigned short a_status) |
1290 | { |
1291 | unsigned short ack = 0; |
1292 | |
1293 | if (a_status & NISTC_AI_STATUS1_SC_TC) |
1294 | ack |= NISTC_INTA_ACK_AI_SC_TC; |
1295 | if (a_status & NISTC_AI_STATUS1_START1) |
1296 | ack |= NISTC_INTA_ACK_AI_START1; |
1297 | if (a_status & NISTC_AI_STATUS1_START) |
1298 | ack |= NISTC_INTA_ACK_AI_START; |
1299 | if (a_status & NISTC_AI_STATUS1_STOP) |
1300 | ack |= NISTC_INTA_ACK_AI_STOP; |
1301 | if (a_status & NISTC_AI_STATUS1_OVER) |
1302 | ack |= NISTC_INTA_ACK_AI_ERR; |
1303 | if (ack) |
1304 | ni_stc_writew(dev, data: ack, NISTC_INTA_ACK_REG); |
1305 | } |
1306 | |
1307 | static void handle_a_interrupt(struct comedi_device *dev, |
1308 | struct comedi_subdevice *s, |
1309 | unsigned short status) |
1310 | { |
1311 | struct comedi_cmd *cmd = &s->async->cmd; |
1312 | |
1313 | /* test for all uncommon interrupt events at the same time */ |
1314 | if (status & (NISTC_AI_STATUS1_ERR | |
1315 | NISTC_AI_STATUS1_SC_TC | NISTC_AI_STATUS1_START1)) { |
1316 | if (status == 0xffff) { |
1317 | dev_err(dev->class_dev, "Card removed?\n" ); |
1318 | /* |
1319 | * We probably aren't even running a command now, |
1320 | * so it's a good idea to be careful. |
1321 | */ |
1322 | if (comedi_is_subdevice_running(s)) |
1323 | s->async->events |= COMEDI_CB_ERROR; |
1324 | return; |
1325 | } |
1326 | if (status & NISTC_AI_STATUS1_ERR) { |
1327 | dev_err(dev->class_dev, "ai error a_status=%04x\n" , |
1328 | status); |
1329 | |
1330 | shutdown_ai_command(dev); |
1331 | |
1332 | s->async->events |= COMEDI_CB_ERROR; |
1333 | if (status & NISTC_AI_STATUS1_OVER) |
1334 | s->async->events |= COMEDI_CB_OVERFLOW; |
1335 | return; |
1336 | } |
1337 | if (status & NISTC_AI_STATUS1_SC_TC) { |
1338 | if (cmd->stop_src == TRIG_COUNT) |
1339 | shutdown_ai_command(dev); |
1340 | } |
1341 | } |
1342 | #ifndef PCIDMA |
1343 | if (status & NISTC_AI_STATUS1_FIFO_HF) { |
1344 | int i; |
1345 | static const int timeout = 10; |
1346 | /* |
1347 | * PCMCIA cards (at least 6036) seem to stop producing |
1348 | * interrupts if we fail to get the fifo less than half |
1349 | * full, so loop to be sure. |
1350 | */ |
1351 | for (i = 0; i < timeout; ++i) { |
1352 | ni_handle_fifo_half_full(dev); |
1353 | if ((ni_stc_readw(dev, NISTC_AI_STATUS1_REG) & |
1354 | NISTC_AI_STATUS1_FIFO_HF) == 0) |
1355 | break; |
1356 | } |
1357 | } |
1358 | #endif /* !PCIDMA */ |
1359 | |
1360 | if (status & NISTC_AI_STATUS1_STOP) |
1361 | ni_handle_eos(dev, s); |
1362 | } |
1363 | |
1364 | static void ack_b_interrupt(struct comedi_device *dev, unsigned short b_status) |
1365 | { |
1366 | unsigned short ack = 0; |
1367 | |
1368 | if (b_status & NISTC_AO_STATUS1_BC_TC) |
1369 | ack |= NISTC_INTB_ACK_AO_BC_TC; |
1370 | if (b_status & NISTC_AO_STATUS1_OVERRUN) |
1371 | ack |= NISTC_INTB_ACK_AO_ERR; |
1372 | if (b_status & NISTC_AO_STATUS1_START) |
1373 | ack |= NISTC_INTB_ACK_AO_START; |
1374 | if (b_status & NISTC_AO_STATUS1_START1) |
1375 | ack |= NISTC_INTB_ACK_AO_START1; |
1376 | if (b_status & NISTC_AO_STATUS1_UC_TC) |
1377 | ack |= NISTC_INTB_ACK_AO_UC_TC; |
1378 | if (b_status & NISTC_AO_STATUS1_UI2_TC) |
1379 | ack |= NISTC_INTB_ACK_AO_UI2_TC; |
1380 | if (b_status & NISTC_AO_STATUS1_UPDATE) |
1381 | ack |= NISTC_INTB_ACK_AO_UPDATE; |
1382 | if (ack) |
1383 | ni_stc_writew(dev, data: ack, NISTC_INTB_ACK_REG); |
1384 | } |
1385 | |
1386 | static void handle_b_interrupt(struct comedi_device *dev, |
1387 | struct comedi_subdevice *s, |
1388 | unsigned short b_status) |
1389 | { |
1390 | if (b_status == 0xffff) |
1391 | return; |
1392 | if (b_status & NISTC_AO_STATUS1_OVERRUN) { |
1393 | dev_err(dev->class_dev, |
1394 | "AO FIFO underrun status=0x%04x status2=0x%04x\n" , |
1395 | b_status, ni_stc_readw(dev, NISTC_AO_STATUS2_REG)); |
1396 | s->async->events |= COMEDI_CB_OVERFLOW; |
1397 | } |
1398 | |
1399 | if (s->async->cmd.stop_src != TRIG_NONE && |
1400 | b_status & NISTC_AO_STATUS1_BC_TC) |
1401 | s->async->events |= COMEDI_CB_EOA; |
1402 | |
1403 | #ifndef PCIDMA |
1404 | if (b_status & NISTC_AO_STATUS1_FIFO_REQ) { |
1405 | int ret; |
1406 | |
1407 | ret = ni_ao_fifo_half_empty(dev, s); |
1408 | if (!ret) { |
1409 | dev_err(dev->class_dev, "AO buffer underrun\n" ); |
1410 | ni_set_bits(dev, NISTC_INTB_ENA_REG, |
1411 | NISTC_INTB_ENA_AO_FIFO | |
1412 | NISTC_INTB_ENA_AO_ERR, value: 0); |
1413 | s->async->events |= COMEDI_CB_OVERFLOW; |
1414 | } |
1415 | } |
1416 | #endif |
1417 | } |
1418 | |
1419 | static void ni_ai_munge(struct comedi_device *dev, struct comedi_subdevice *s, |
1420 | void *data, unsigned int num_bytes, |
1421 | unsigned int chan_index) |
1422 | { |
1423 | struct ni_private *devpriv = dev->private; |
1424 | struct comedi_async *async = s->async; |
1425 | struct comedi_cmd *cmd = &async->cmd; |
1426 | unsigned int nsamples = comedi_bytes_to_samples(s, nbytes: num_bytes); |
1427 | unsigned short *array = data; |
1428 | unsigned int *larray = data; |
1429 | unsigned int i; |
1430 | #ifdef PCIDMA |
1431 | __le16 *barray = data; |
1432 | __le32 *blarray = data; |
1433 | #endif |
1434 | |
1435 | for (i = 0; i < nsamples; i++) { |
1436 | #ifdef PCIDMA |
1437 | if (s->subdev_flags & SDF_LSAMPL) |
1438 | larray[i] = le32_to_cpu(blarray[i]); |
1439 | else |
1440 | array[i] = le16_to_cpu(barray[i]); |
1441 | #endif |
1442 | if (s->subdev_flags & SDF_LSAMPL) |
1443 | larray[i] += devpriv->ai_offset[chan_index]; |
1444 | else |
1445 | array[i] += devpriv->ai_offset[chan_index]; |
1446 | chan_index++; |
1447 | chan_index %= cmd->chanlist_len; |
1448 | } |
1449 | } |
1450 | |
1451 | #ifdef PCIDMA |
1452 | |
1453 | static int ni_ai_setup_MITE_dma(struct comedi_device *dev) |
1454 | { |
1455 | struct ni_private *devpriv = dev->private; |
1456 | struct comedi_subdevice *s = dev->read_subdev; |
1457 | int retval; |
1458 | unsigned long flags; |
1459 | |
1460 | retval = ni_request_ai_mite_channel(dev); |
1461 | if (retval) |
1462 | return retval; |
1463 | |
1464 | /* write alloc the entire buffer */ |
1465 | comedi_buf_write_alloc(s, s->async->prealloc_bufsz); |
1466 | |
1467 | spin_lock_irqsave(&devpriv->mite_channel_lock, flags); |
1468 | if (!devpriv->ai_mite_chan) { |
1469 | spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); |
1470 | return -EIO; |
1471 | } |
1472 | |
1473 | if (devpriv->is_611x || devpriv->is_6143) |
1474 | mite_prep_dma(devpriv->ai_mite_chan, 32, 16); |
1475 | else if (devpriv->is_628x) |
1476 | mite_prep_dma(devpriv->ai_mite_chan, 32, 32); |
1477 | else |
1478 | mite_prep_dma(devpriv->ai_mite_chan, 16, 16); |
1479 | |
1480 | /*start the MITE */ |
1481 | mite_dma_arm(devpriv->ai_mite_chan); |
1482 | spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); |
1483 | |
1484 | return 0; |
1485 | } |
1486 | |
1487 | static int ni_ao_setup_MITE_dma(struct comedi_device *dev) |
1488 | { |
1489 | struct ni_private *devpriv = dev->private; |
1490 | struct comedi_subdevice *s = dev->write_subdev; |
1491 | int retval; |
1492 | unsigned long flags; |
1493 | |
1494 | retval = ni_request_ao_mite_channel(dev); |
1495 | if (retval) |
1496 | return retval; |
1497 | |
1498 | /* read alloc the entire buffer */ |
1499 | comedi_buf_read_alloc(s, s->async->prealloc_bufsz); |
1500 | |
1501 | spin_lock_irqsave(&devpriv->mite_channel_lock, flags); |
1502 | if (devpriv->ao_mite_chan) { |
1503 | if (devpriv->is_611x || devpriv->is_6713) { |
1504 | mite_prep_dma(devpriv->ao_mite_chan, 32, 32); |
1505 | } else { |
1506 | /* |
1507 | * Doing 32 instead of 16 bit wide transfers from |
1508 | * memory makes the mite do 32 bit pci transfers, |
1509 | * doubling pci bandwidth. |
1510 | */ |
1511 | mite_prep_dma(devpriv->ao_mite_chan, 16, 32); |
1512 | } |
1513 | mite_dma_arm(devpriv->ao_mite_chan); |
1514 | } else { |
1515 | retval = -EIO; |
1516 | } |
1517 | spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); |
1518 | |
1519 | return retval; |
1520 | } |
1521 | |
1522 | #endif /* PCIDMA */ |
1523 | |
1524 | /* |
1525 | * used for both cancel ioctl and board initialization |
1526 | * |
1527 | * this is pretty harsh for a cancel, but it works... |
1528 | */ |
1529 | static int ni_ai_reset(struct comedi_device *dev, struct comedi_subdevice *s) |
1530 | { |
1531 | struct ni_private *devpriv = dev->private; |
1532 | unsigned int ai_personal; |
1533 | unsigned int ai_out_ctrl; |
1534 | |
1535 | ni_release_ai_mite_channel(dev); |
1536 | /* ai configuration */ |
1537 | ni_stc_writew(dev, NISTC_RESET_AI_CFG_START | NISTC_RESET_AI, |
1538 | NISTC_RESET_REG); |
1539 | |
1540 | ni_set_bits(dev, NISTC_INTA_ENA_REG, NISTC_INTA_ENA_AI_MASK, value: 0); |
1541 | |
1542 | ni_clear_ai_fifo(dev); |
1543 | |
1544 | if (!devpriv->is_6143) |
1545 | ni_writeb(dev, NI_E_MISC_CMD_EXT_ATRIG, NI_E_MISC_CMD_REG); |
1546 | |
1547 | ni_stc_writew(dev, NISTC_AI_CMD1_DISARM, NISTC_AI_CMD1_REG); |
1548 | ni_stc_writew(dev, NISTC_AI_MODE1_START_STOP | |
1549 | NISTC_AI_MODE1_RSVD |
1550 | /*| NISTC_AI_MODE1_TRIGGER_ONCE */, |
1551 | NISTC_AI_MODE1_REG); |
1552 | ni_stc_writew(dev, data: 0, NISTC_AI_MODE2_REG); |
1553 | /* generate FIFO interrupts on non-empty */ |
1554 | ni_stc_writew(dev, NISTC_AI_MODE3_FIFO_MODE_NE, |
1555 | NISTC_AI_MODE3_REG); |
1556 | |
1557 | ai_personal = NISTC_AI_PERSONAL_SHIFTIN_PW | |
1558 | NISTC_AI_PERSONAL_SOC_POLARITY | |
1559 | NISTC_AI_PERSONAL_LOCALMUX_CLK_PW; |
1560 | ai_out_ctrl = NISTC_AI_OUT_CTRL_SCAN_IN_PROG_SEL(3) | |
1561 | NISTC_AI_OUT_CTRL_EXTMUX_CLK_SEL(0) | |
1562 | NISTC_AI_OUT_CTRL_LOCALMUX_CLK_SEL(2) | |
1563 | NISTC_AI_OUT_CTRL_SC_TC_SEL(3); |
1564 | if (devpriv->is_611x) { |
1565 | ai_out_ctrl |= NISTC_AI_OUT_CTRL_CONVERT_HIGH; |
1566 | } else if (devpriv->is_6143) { |
1567 | ai_out_ctrl |= NISTC_AI_OUT_CTRL_CONVERT_LOW; |
1568 | } else { |
1569 | ai_personal |= NISTC_AI_PERSONAL_CONVERT_PW; |
1570 | if (devpriv->is_622x) |
1571 | ai_out_ctrl |= NISTC_AI_OUT_CTRL_CONVERT_HIGH; |
1572 | else |
1573 | ai_out_ctrl |= NISTC_AI_OUT_CTRL_CONVERT_LOW; |
1574 | } |
1575 | ni_stc_writew(dev, data: ai_personal, NISTC_AI_PERSONAL_REG); |
1576 | ni_stc_writew(dev, data: ai_out_ctrl, NISTC_AI_OUT_CTRL_REG); |
1577 | |
1578 | /* the following registers should not be changed, because there |
1579 | * are no backup registers in devpriv. If you want to change |
1580 | * any of these, add a backup register and other appropriate code: |
1581 | * NISTC_AI_MODE1_REG |
1582 | * NISTC_AI_MODE3_REG |
1583 | * NISTC_AI_PERSONAL_REG |
1584 | * NISTC_AI_OUT_CTRL_REG |
1585 | */ |
1586 | |
1587 | /* clear interrupts */ |
1588 | ni_stc_writew(dev, NISTC_INTA_ACK_AI_ALL, NISTC_INTA_ACK_REG); |
1589 | |
1590 | ni_stc_writew(dev, NISTC_RESET_AI_CFG_END, NISTC_RESET_REG); |
1591 | |
1592 | return 0; |
1593 | } |
1594 | |
1595 | static int ni_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s) |
1596 | { |
1597 | unsigned long flags; |
1598 | int count; |
1599 | |
1600 | /* lock to avoid race with interrupt handler */ |
1601 | spin_lock_irqsave(&dev->spinlock, flags); |
1602 | #ifndef PCIDMA |
1603 | ni_handle_fifo_dregs(dev); |
1604 | #else |
1605 | ni_sync_ai_dma(dev); |
1606 | #endif |
1607 | count = comedi_buf_n_bytes_ready(s); |
1608 | spin_unlock_irqrestore(lock: &dev->spinlock, flags); |
1609 | |
1610 | return count; |
1611 | } |
1612 | |
1613 | static void ni_prime_channelgain_list(struct comedi_device *dev) |
1614 | { |
1615 | int i; |
1616 | |
1617 | ni_stc_writew(dev, NISTC_AI_CMD1_CONVERT_PULSE, NISTC_AI_CMD1_REG); |
1618 | for (i = 0; i < NI_TIMEOUT; ++i) { |
1619 | if (!(ni_stc_readw(dev, NISTC_AI_STATUS1_REG) & |
1620 | NISTC_AI_STATUS1_FIFO_E)) { |
1621 | ni_stc_writew(dev, data: 1, NISTC_ADC_FIFO_CLR_REG); |
1622 | return; |
1623 | } |
1624 | udelay(1); |
1625 | } |
1626 | dev_err(dev->class_dev, "timeout loading channel/gain list\n" ); |
1627 | } |
1628 | |
1629 | static void ni_m_series_load_channelgain_list(struct comedi_device *dev, |
1630 | unsigned int n_chan, |
1631 | unsigned int *list) |
1632 | { |
1633 | const struct ni_board_struct *board = dev->board_ptr; |
1634 | struct ni_private *devpriv = dev->private; |
1635 | unsigned int chan, range, aref; |
1636 | unsigned int i; |
1637 | unsigned int dither; |
1638 | unsigned int range_code; |
1639 | |
1640 | ni_stc_writew(dev, data: 1, NISTC_CFG_MEM_CLR_REG); |
1641 | |
1642 | if ((list[0] & CR_ALT_SOURCE)) { |
1643 | unsigned int bypass_bits; |
1644 | |
1645 | chan = CR_CHAN(list[0]); |
1646 | range = CR_RANGE(list[0]); |
1647 | range_code = ni_gainlkup[board->gainlkup][range]; |
1648 | dither = (list[0] & CR_ALT_FILTER) != 0; |
1649 | bypass_bits = NI_M_CFG_BYPASS_FIFO | |
1650 | NI_M_CFG_BYPASS_AI_CHAN(chan) | |
1651 | NI_M_CFG_BYPASS_AI_GAIN(range_code) | |
1652 | devpriv->ai_calib_source; |
1653 | if (dither) |
1654 | bypass_bits |= NI_M_CFG_BYPASS_AI_DITHER; |
1655 | /* don't use 2's complement encoding */ |
1656 | bypass_bits |= NI_M_CFG_BYPASS_AI_POLARITY; |
1657 | ni_writel(dev, data: bypass_bits, NI_M_CFG_BYPASS_FIFO_REG); |
1658 | } else { |
1659 | ni_writel(dev, data: 0, NI_M_CFG_BYPASS_FIFO_REG); |
1660 | } |
1661 | for (i = 0; i < n_chan; i++) { |
1662 | unsigned int config_bits = 0; |
1663 | |
1664 | chan = CR_CHAN(list[i]); |
1665 | aref = CR_AREF(list[i]); |
1666 | range = CR_RANGE(list[i]); |
1667 | dither = (list[i] & CR_ALT_FILTER) != 0; |
1668 | |
1669 | range_code = ni_gainlkup[board->gainlkup][range]; |
1670 | devpriv->ai_offset[i] = 0; |
1671 | switch (aref) { |
1672 | case AREF_DIFF: |
1673 | config_bits |= NI_M_AI_CFG_CHAN_TYPE_DIFF; |
1674 | break; |
1675 | case AREF_COMMON: |
1676 | config_bits |= NI_M_AI_CFG_CHAN_TYPE_COMMON; |
1677 | break; |
1678 | case AREF_GROUND: |
1679 | config_bits |= NI_M_AI_CFG_CHAN_TYPE_GROUND; |
1680 | break; |
1681 | case AREF_OTHER: |
1682 | break; |
1683 | } |
1684 | config_bits |= NI_M_AI_CFG_CHAN_SEL(chan); |
1685 | config_bits |= NI_M_AI_CFG_BANK_SEL(chan); |
1686 | config_bits |= NI_M_AI_CFG_GAIN(range_code); |
1687 | if (i == n_chan - 1) |
1688 | config_bits |= NI_M_AI_CFG_LAST_CHAN; |
1689 | if (dither) |
1690 | config_bits |= NI_M_AI_CFG_DITHER; |
1691 | /* don't use 2's complement encoding */ |
1692 | config_bits |= NI_M_AI_CFG_POLARITY; |
1693 | ni_writew(dev, data: config_bits, NI_M_AI_CFG_FIFO_DATA_REG); |
1694 | } |
1695 | ni_prime_channelgain_list(dev); |
1696 | } |
1697 | |
1698 | /* |
1699 | * Notes on the 6110 and 6111: |
1700 | * These boards a slightly different than the rest of the series, since |
1701 | * they have multiple A/D converters. |
1702 | * From the driver side, the configuration memory is a |
1703 | * little different. |
1704 | * Configuration Memory Low: |
1705 | * bits 15-9: same |
1706 | * bit 8: unipolar/bipolar (should be 0 for bipolar) |
1707 | * bits 0-3: gain. This is 4 bits instead of 3 for the other boards |
1708 | * 1001 gain=0.1 (+/- 50) |
1709 | * 1010 0.2 |
1710 | * 1011 0.1 |
1711 | * 0001 1 |
1712 | * 0010 2 |
1713 | * 0011 5 |
1714 | * 0100 10 |
1715 | * 0101 20 |
1716 | * 0110 50 |
1717 | * Configuration Memory High: |
1718 | * bits 12-14: Channel Type |
1719 | * 001 for differential |
1720 | * 000 for calibration |
1721 | * bit 11: coupling (this is not currently handled) |
1722 | * 1 AC coupling |
1723 | * 0 DC coupling |
1724 | * bits 0-2: channel |
1725 | * valid channels are 0-3 |
1726 | */ |
1727 | static void ni_load_channelgain_list(struct comedi_device *dev, |
1728 | struct comedi_subdevice *s, |
1729 | unsigned int n_chan, unsigned int *list) |
1730 | { |
1731 | const struct ni_board_struct *board = dev->board_ptr; |
1732 | struct ni_private *devpriv = dev->private; |
1733 | unsigned int offset = (s->maxdata + 1) >> 1; |
1734 | unsigned int chan, range, aref; |
1735 | unsigned int i; |
1736 | unsigned int hi, lo; |
1737 | unsigned int dither; |
1738 | |
1739 | if (devpriv->is_m_series) { |
1740 | ni_m_series_load_channelgain_list(dev, n_chan, list); |
1741 | return; |
1742 | } |
1743 | if (n_chan == 1 && !devpriv->is_611x && !devpriv->is_6143) { |
1744 | if (devpriv->changain_state && |
1745 | devpriv->changain_spec == list[0]) { |
1746 | /* ready to go. */ |
1747 | return; |
1748 | } |
1749 | devpriv->changain_state = 1; |
1750 | devpriv->changain_spec = list[0]; |
1751 | } else { |
1752 | devpriv->changain_state = 0; |
1753 | } |
1754 | |
1755 | ni_stc_writew(dev, data: 1, NISTC_CFG_MEM_CLR_REG); |
1756 | |
1757 | /* Set up Calibration mode if required */ |
1758 | if (devpriv->is_6143) { |
1759 | if ((list[0] & CR_ALT_SOURCE) && |
1760 | !devpriv->ai_calib_source_enabled) { |
1761 | /* Strobe Relay enable bit */ |
1762 | ni_writew(dev, data: devpriv->ai_calib_source | |
1763 | NI6143_CALIB_CHAN_RELAY_ON, |
1764 | NI6143_CALIB_CHAN_REG); |
1765 | ni_writew(dev, data: devpriv->ai_calib_source, |
1766 | NI6143_CALIB_CHAN_REG); |
1767 | devpriv->ai_calib_source_enabled = 1; |
1768 | /* Allow relays to change */ |
1769 | msleep_interruptible(msecs: 100); |
1770 | } else if (!(list[0] & CR_ALT_SOURCE) && |
1771 | devpriv->ai_calib_source_enabled) { |
1772 | /* Strobe Relay disable bit */ |
1773 | ni_writew(dev, data: devpriv->ai_calib_source | |
1774 | NI6143_CALIB_CHAN_RELAY_OFF, |
1775 | NI6143_CALIB_CHAN_REG); |
1776 | ni_writew(dev, data: devpriv->ai_calib_source, |
1777 | NI6143_CALIB_CHAN_REG); |
1778 | devpriv->ai_calib_source_enabled = 0; |
1779 | /* Allow relays to change */ |
1780 | msleep_interruptible(msecs: 100); |
1781 | } |
1782 | } |
1783 | |
1784 | for (i = 0; i < n_chan; i++) { |
1785 | if (!devpriv->is_6143 && (list[i] & CR_ALT_SOURCE)) |
1786 | chan = devpriv->ai_calib_source; |
1787 | else |
1788 | chan = CR_CHAN(list[i]); |
1789 | aref = CR_AREF(list[i]); |
1790 | range = CR_RANGE(list[i]); |
1791 | dither = (list[i] & CR_ALT_FILTER) != 0; |
1792 | |
1793 | /* fix the external/internal range differences */ |
1794 | range = ni_gainlkup[board->gainlkup][range]; |
1795 | if (devpriv->is_611x) |
1796 | devpriv->ai_offset[i] = offset; |
1797 | else |
1798 | devpriv->ai_offset[i] = (range & 0x100) ? 0 : offset; |
1799 | |
1800 | hi = 0; |
1801 | if ((list[i] & CR_ALT_SOURCE)) { |
1802 | if (devpriv->is_611x) |
1803 | ni_writew(dev, CR_CHAN(list[i]) & 0x0003, |
1804 | NI611X_CALIB_CHAN_SEL_REG); |
1805 | } else { |
1806 | if (devpriv->is_611x) |
1807 | aref = AREF_DIFF; |
1808 | else if (devpriv->is_6143) |
1809 | aref = AREF_OTHER; |
1810 | switch (aref) { |
1811 | case AREF_DIFF: |
1812 | hi |= NI_E_AI_CFG_HI_TYPE_DIFF; |
1813 | break; |
1814 | case AREF_COMMON: |
1815 | hi |= NI_E_AI_CFG_HI_TYPE_COMMON; |
1816 | break; |
1817 | case AREF_GROUND: |
1818 | hi |= NI_E_AI_CFG_HI_TYPE_GROUND; |
1819 | break; |
1820 | case AREF_OTHER: |
1821 | break; |
1822 | } |
1823 | } |
1824 | hi |= NI_E_AI_CFG_HI_CHAN(chan); |
1825 | |
1826 | ni_writew(dev, data: hi, NI_E_AI_CFG_HI_REG); |
1827 | |
1828 | if (!devpriv->is_6143) { |
1829 | lo = NI_E_AI_CFG_LO_GAIN(range); |
1830 | |
1831 | if (i == n_chan - 1) |
1832 | lo |= NI_E_AI_CFG_LO_LAST_CHAN; |
1833 | if (dither) |
1834 | lo |= NI_E_AI_CFG_LO_DITHER; |
1835 | |
1836 | ni_writew(dev, data: lo, NI_E_AI_CFG_LO_REG); |
1837 | } |
1838 | } |
1839 | |
1840 | /* prime the channel/gain list */ |
1841 | if (!devpriv->is_611x && !devpriv->is_6143) |
1842 | ni_prime_channelgain_list(dev); |
1843 | } |
1844 | |
1845 | static int ni_ai_insn_read(struct comedi_device *dev, |
1846 | struct comedi_subdevice *s, |
1847 | struct comedi_insn *insn, |
1848 | unsigned int *data) |
1849 | { |
1850 | struct ni_private *devpriv = dev->private; |
1851 | unsigned int mask = s->maxdata; |
1852 | int i, n; |
1853 | unsigned int signbits; |
1854 | unsigned int d; |
1855 | |
1856 | ni_load_channelgain_list(dev, s, n_chan: 1, list: &insn->chanspec); |
1857 | |
1858 | ni_clear_ai_fifo(dev); |
1859 | |
1860 | signbits = devpriv->ai_offset[0]; |
1861 | if (devpriv->is_611x) { |
1862 | for (n = 0; n < num_adc_stages_611x; n++) { |
1863 | ni_stc_writew(dev, NISTC_AI_CMD1_CONVERT_PULSE, |
1864 | NISTC_AI_CMD1_REG); |
1865 | udelay(1); |
1866 | } |
1867 | for (n = 0; n < insn->n; n++) { |
1868 | ni_stc_writew(dev, NISTC_AI_CMD1_CONVERT_PULSE, |
1869 | NISTC_AI_CMD1_REG); |
1870 | /* The 611x has screwy 32-bit FIFOs. */ |
1871 | d = 0; |
1872 | for (i = 0; i < NI_TIMEOUT; i++) { |
1873 | if (ni_readb(dev, NI_E_STATUS_REG) & 0x80) { |
1874 | d = ni_readl(dev, |
1875 | NI611X_AI_FIFO_DATA_REG); |
1876 | d >>= 16; |
1877 | d &= 0xffff; |
1878 | break; |
1879 | } |
1880 | if (!(ni_stc_readw(dev, NISTC_AI_STATUS1_REG) & |
1881 | NISTC_AI_STATUS1_FIFO_E)) { |
1882 | d = ni_readl(dev, |
1883 | NI611X_AI_FIFO_DATA_REG); |
1884 | d &= 0xffff; |
1885 | break; |
1886 | } |
1887 | } |
1888 | if (i == NI_TIMEOUT) { |
1889 | dev_err(dev->class_dev, "timeout\n" ); |
1890 | return -ETIME; |
1891 | } |
1892 | d += signbits; |
1893 | data[n] = d & 0xffff; |
1894 | } |
1895 | } else if (devpriv->is_6143) { |
1896 | for (n = 0; n < insn->n; n++) { |
1897 | ni_stc_writew(dev, NISTC_AI_CMD1_CONVERT_PULSE, |
1898 | NISTC_AI_CMD1_REG); |
1899 | |
1900 | /* |
1901 | * The 6143 has 32-bit FIFOs. You need to strobe a |
1902 | * bit to move a single 16bit stranded sample into |
1903 | * the FIFO. |
1904 | */ |
1905 | d = 0; |
1906 | for (i = 0; i < NI_TIMEOUT; i++) { |
1907 | if (ni_readl(dev, NI6143_AI_FIFO_STATUS_REG) & |
1908 | 0x01) { |
1909 | /* Get stranded sample into FIFO */ |
1910 | ni_writel(dev, data: 0x01, |
1911 | NI6143_AI_FIFO_CTRL_REG); |
1912 | d = ni_readl(dev, |
1913 | NI6143_AI_FIFO_DATA_REG); |
1914 | break; |
1915 | } |
1916 | } |
1917 | if (i == NI_TIMEOUT) { |
1918 | dev_err(dev->class_dev, "timeout\n" ); |
1919 | return -ETIME; |
1920 | } |
1921 | data[n] = (((d >> 16) & 0xFFFF) + signbits) & 0xFFFF; |
1922 | } |
1923 | } else { |
1924 | for (n = 0; n < insn->n; n++) { |
1925 | ni_stc_writew(dev, NISTC_AI_CMD1_CONVERT_PULSE, |
1926 | NISTC_AI_CMD1_REG); |
1927 | for (i = 0; i < NI_TIMEOUT; i++) { |
1928 | if (!(ni_stc_readw(dev, NISTC_AI_STATUS1_REG) & |
1929 | NISTC_AI_STATUS1_FIFO_E)) |
1930 | break; |
1931 | } |
1932 | if (i == NI_TIMEOUT) { |
1933 | dev_err(dev->class_dev, "timeout\n" ); |
1934 | return -ETIME; |
1935 | } |
1936 | if (devpriv->is_m_series) { |
1937 | d = ni_readl(dev, NI_M_AI_FIFO_DATA_REG); |
1938 | d &= mask; |
1939 | data[n] = d; |
1940 | } else { |
1941 | d = ni_readw(dev, NI_E_AI_FIFO_DATA_REG); |
1942 | d += signbits; |
1943 | data[n] = d & 0xffff; |
1944 | } |
1945 | } |
1946 | } |
1947 | return insn->n; |
1948 | } |
1949 | |
1950 | static int ni_ns_to_timer(const struct comedi_device *dev, |
1951 | unsigned int nanosec, unsigned int flags) |
1952 | { |
1953 | struct ni_private *devpriv = dev->private; |
1954 | int divider; |
1955 | |
1956 | switch (flags & CMDF_ROUND_MASK) { |
1957 | case CMDF_ROUND_NEAREST: |
1958 | default: |
1959 | divider = DIV_ROUND_CLOSEST(nanosec, devpriv->clock_ns); |
1960 | break; |
1961 | case CMDF_ROUND_DOWN: |
1962 | divider = (nanosec) / devpriv->clock_ns; |
1963 | break; |
1964 | case CMDF_ROUND_UP: |
1965 | divider = DIV_ROUND_UP(nanosec, devpriv->clock_ns); |
1966 | break; |
1967 | } |
1968 | return divider - 1; |
1969 | } |
1970 | |
1971 | static unsigned int ni_timer_to_ns(const struct comedi_device *dev, int timer) |
1972 | { |
1973 | struct ni_private *devpriv = dev->private; |
1974 | |
1975 | return devpriv->clock_ns * (timer + 1); |
1976 | } |
1977 | |
1978 | static void ni_cmd_set_mite_transfer(struct mite_ring *ring, |
1979 | struct comedi_subdevice *sdev, |
1980 | const struct comedi_cmd *cmd, |
1981 | unsigned int max_count) |
1982 | { |
1983 | #ifdef PCIDMA |
1984 | unsigned int nbytes = max_count; |
1985 | |
1986 | if (cmd->stop_arg > 0 && cmd->stop_arg < max_count) |
1987 | nbytes = cmd->stop_arg; |
1988 | nbytes *= comedi_bytes_per_scan(sdev); |
1989 | |
1990 | if (nbytes > sdev->async->prealloc_bufsz) { |
1991 | if (cmd->stop_arg > 0) |
1992 | dev_err(sdev->device->class_dev, |
1993 | "%s: tried exact data transfer limits greater than buffer size\n" , |
1994 | __func__); |
1995 | |
1996 | /* |
1997 | * we can only transfer up to the size of the buffer. In this |
1998 | * case, the user is expected to continue to write into the |
1999 | * comedi buffer (already implemented as a ring buffer). |
2000 | */ |
2001 | nbytes = sdev->async->prealloc_bufsz; |
2002 | } |
2003 | |
2004 | mite_init_ring_descriptors(ring, sdev, nbytes); |
2005 | #else |
2006 | dev_err(sdev->device->class_dev, |
2007 | "%s: exact data transfer limits not implemented yet without DMA\n" , |
2008 | __func__); |
2009 | #endif |
2010 | } |
2011 | |
2012 | static unsigned int ni_min_ai_scan_period_ns(struct comedi_device *dev, |
2013 | unsigned int num_channels) |
2014 | { |
2015 | const struct ni_board_struct *board = dev->board_ptr; |
2016 | struct ni_private *devpriv = dev->private; |
2017 | |
2018 | /* simultaneously-sampled inputs */ |
2019 | if (devpriv->is_611x || devpriv->is_6143) |
2020 | return board->ai_speed; |
2021 | |
2022 | /* multiplexed inputs */ |
2023 | return board->ai_speed * num_channels; |
2024 | } |
2025 | |
2026 | static int ni_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, |
2027 | struct comedi_cmd *cmd) |
2028 | { |
2029 | const struct ni_board_struct *board = dev->board_ptr; |
2030 | struct ni_private *devpriv = dev->private; |
2031 | int err = 0; |
2032 | unsigned int sources; |
2033 | |
2034 | /* Step 1 : check if triggers are trivially valid */ |
2035 | |
2036 | err |= comedi_check_trigger_src(src: &cmd->start_src, |
2037 | TRIG_NOW | TRIG_INT | TRIG_EXT); |
2038 | err |= comedi_check_trigger_src(src: &cmd->scan_begin_src, |
2039 | TRIG_TIMER | TRIG_EXT); |
2040 | |
2041 | sources = TRIG_TIMER | TRIG_EXT; |
2042 | if (devpriv->is_611x || devpriv->is_6143) |
2043 | sources |= TRIG_NOW; |
2044 | err |= comedi_check_trigger_src(src: &cmd->convert_src, flags: sources); |
2045 | |
2046 | err |= comedi_check_trigger_src(src: &cmd->scan_end_src, TRIG_COUNT); |
2047 | err |= comedi_check_trigger_src(src: &cmd->stop_src, TRIG_COUNT | TRIG_NONE); |
2048 | |
2049 | if (err) |
2050 | return 1; |
2051 | |
2052 | /* Step 2a : make sure trigger sources are unique */ |
2053 | |
2054 | err |= comedi_check_trigger_is_unique(src: cmd->start_src); |
2055 | err |= comedi_check_trigger_is_unique(src: cmd->scan_begin_src); |
2056 | err |= comedi_check_trigger_is_unique(src: cmd->convert_src); |
2057 | err |= comedi_check_trigger_is_unique(src: cmd->stop_src); |
2058 | |
2059 | /* Step 2b : and mutually compatible */ |
2060 | |
2061 | if (err) |
2062 | return 2; |
2063 | |
2064 | /* Step 3: check if arguments are trivially valid */ |
2065 | |
2066 | switch (cmd->start_src) { |
2067 | case TRIG_NOW: |
2068 | case TRIG_INT: |
2069 | err |= comedi_check_trigger_arg_is(arg: &cmd->start_arg, val: 0); |
2070 | break; |
2071 | case TRIG_EXT: |
2072 | err |= ni_check_trigger_arg_roffs(CR_CHAN(cmd->start_arg), |
2073 | dest: NI_AI_StartTrigger, |
2074 | tables: &devpriv->routing_tables, direct_reg_offset: 1); |
2075 | break; |
2076 | } |
2077 | |
2078 | if (cmd->scan_begin_src == TRIG_TIMER) { |
2079 | err |= comedi_check_trigger_arg_min(arg: &cmd->scan_begin_arg, |
2080 | val: ni_min_ai_scan_period_ns(dev, num_channels: cmd->chanlist_len)); |
2081 | err |= comedi_check_trigger_arg_max(arg: &cmd->scan_begin_arg, |
2082 | val: devpriv->clock_ns * |
2083 | 0xffffff); |
2084 | } else if (cmd->scan_begin_src == TRIG_EXT) { |
2085 | /* external trigger */ |
2086 | err |= ni_check_trigger_arg_roffs(CR_CHAN(cmd->scan_begin_arg), |
2087 | dest: NI_AI_SampleClock, |
2088 | tables: &devpriv->routing_tables, direct_reg_offset: 1); |
2089 | } else { /* TRIG_OTHER */ |
2090 | err |= comedi_check_trigger_arg_is(arg: &cmd->scan_begin_arg, val: 0); |
2091 | } |
2092 | |
2093 | if (cmd->convert_src == TRIG_TIMER) { |
2094 | if (devpriv->is_611x || devpriv->is_6143) { |
2095 | err |= comedi_check_trigger_arg_is(arg: &cmd->convert_arg, |
2096 | val: 0); |
2097 | } else { |
2098 | err |= comedi_check_trigger_arg_min(arg: &cmd->convert_arg, |
2099 | val: board->ai_speed); |
2100 | err |= comedi_check_trigger_arg_max(arg: &cmd->convert_arg, |
2101 | val: devpriv->clock_ns * |
2102 | 0xffff); |
2103 | } |
2104 | } else if (cmd->convert_src == TRIG_EXT) { |
2105 | /* external trigger */ |
2106 | err |= ni_check_trigger_arg_roffs(CR_CHAN(cmd->convert_arg), |
2107 | dest: NI_AI_ConvertClock, |
2108 | tables: &devpriv->routing_tables, direct_reg_offset: 1); |
2109 | } else if (cmd->convert_src == TRIG_NOW) { |
2110 | err |= comedi_check_trigger_arg_is(arg: &cmd->convert_arg, val: 0); |
2111 | } |
2112 | |
2113 | err |= comedi_check_trigger_arg_is(arg: &cmd->scan_end_arg, |
2114 | val: cmd->chanlist_len); |
2115 | |
2116 | if (cmd->stop_src == TRIG_COUNT) { |
2117 | unsigned int max_count = 0x01000000; |
2118 | |
2119 | if (devpriv->is_611x) |
2120 | max_count -= num_adc_stages_611x; |
2121 | err |= comedi_check_trigger_arg_max(arg: &cmd->stop_arg, val: max_count); |
2122 | err |= comedi_check_trigger_arg_min(arg: &cmd->stop_arg, val: 1); |
2123 | } else { |
2124 | /* TRIG_NONE */ |
2125 | err |= comedi_check_trigger_arg_is(arg: &cmd->stop_arg, val: 0); |
2126 | } |
2127 | |
2128 | if (err) |
2129 | return 3; |
2130 | |
2131 | /* step 4: fix up any arguments */ |
2132 | |
2133 | if (cmd->scan_begin_src == TRIG_TIMER) { |
2134 | unsigned int tmp = cmd->scan_begin_arg; |
2135 | |
2136 | cmd->scan_begin_arg = |
2137 | ni_timer_to_ns(dev, timer: ni_ns_to_timer(dev, |
2138 | nanosec: cmd->scan_begin_arg, |
2139 | flags: cmd->flags)); |
2140 | if (tmp != cmd->scan_begin_arg) |
2141 | err++; |
2142 | } |
2143 | if (cmd->convert_src == TRIG_TIMER) { |
2144 | if (!devpriv->is_611x && !devpriv->is_6143) { |
2145 | unsigned int tmp = cmd->convert_arg; |
2146 | |
2147 | cmd->convert_arg = |
2148 | ni_timer_to_ns(dev, timer: ni_ns_to_timer(dev, |
2149 | nanosec: cmd->convert_arg, |
2150 | flags: cmd->flags)); |
2151 | if (tmp != cmd->convert_arg) |
2152 | err++; |
2153 | if (cmd->scan_begin_src == TRIG_TIMER && |
2154 | cmd->scan_begin_arg < |
2155 | cmd->convert_arg * cmd->scan_end_arg) { |
2156 | cmd->scan_begin_arg = |
2157 | cmd->convert_arg * cmd->scan_end_arg; |
2158 | err++; |
2159 | } |
2160 | } |
2161 | } |
2162 | |
2163 | if (err) |
2164 | return 4; |
2165 | |
2166 | return 0; |
2167 | } |
2168 | |
2169 | static int ni_ai_inttrig(struct comedi_device *dev, |
2170 | struct comedi_subdevice *s, |
2171 | unsigned int trig_num) |
2172 | { |
2173 | struct ni_private *devpriv = dev->private; |
2174 | struct comedi_cmd *cmd = &s->async->cmd; |
2175 | |
2176 | if (trig_num != cmd->start_arg) |
2177 | return -EINVAL; |
2178 | |
2179 | ni_stc_writew(dev, NISTC_AI_CMD2_START1_PULSE | devpriv->ai_cmd2, |
2180 | NISTC_AI_CMD2_REG); |
2181 | s->async->inttrig = NULL; |
2182 | |
2183 | return 1; |
2184 | } |
2185 | |
2186 | static int ni_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) |
2187 | { |
2188 | struct ni_private *devpriv = dev->private; |
2189 | const struct comedi_cmd *cmd = &s->async->cmd; |
2190 | int timer; |
2191 | int mode1 = 0; /* mode1 is needed for both stop and convert */ |
2192 | int mode2 = 0; |
2193 | int start_stop_select = 0; |
2194 | unsigned int stop_count; |
2195 | int interrupt_a_enable = 0; |
2196 | unsigned int ai_trig; |
2197 | |
2198 | if (dev->irq == 0) { |
2199 | dev_err(dev->class_dev, "cannot run command without an irq\n" ); |
2200 | return -EIO; |
2201 | } |
2202 | ni_clear_ai_fifo(dev); |
2203 | |
2204 | ni_load_channelgain_list(dev, s, n_chan: cmd->chanlist_len, list: cmd->chanlist); |
2205 | |
2206 | /* start configuration */ |
2207 | ni_stc_writew(dev, NISTC_RESET_AI_CFG_START, NISTC_RESET_REG); |
2208 | |
2209 | /* |
2210 | * Disable analog triggering for now, since it interferes |
2211 | * with the use of pfi0. |
2212 | */ |
2213 | devpriv->an_trig_etc_reg &= ~NISTC_ATRIG_ETC_ENA; |
2214 | ni_stc_writew(dev, data: devpriv->an_trig_etc_reg, NISTC_ATRIG_ETC_REG); |
2215 | |
2216 | ai_trig = NISTC_AI_TRIG_START2_SEL(0) | NISTC_AI_TRIG_START1_SYNC; |
2217 | switch (cmd->start_src) { |
2218 | case TRIG_INT: |
2219 | case TRIG_NOW: |
2220 | ai_trig |= NISTC_AI_TRIG_START1_EDGE | |
2221 | NISTC_AI_TRIG_START1_SEL(0); |
2222 | break; |
2223 | case TRIG_EXT: |
2224 | ai_trig |= NISTC_AI_TRIG_START1_SEL( |
2225 | ni_get_reg_value_roffs( |
2226 | CR_CHAN(cmd->start_arg), |
2227 | NI_AI_StartTrigger, |
2228 | &devpriv->routing_tables, 1)); |
2229 | |
2230 | if (cmd->start_arg & CR_INVERT) |
2231 | ai_trig |= NISTC_AI_TRIG_START1_POLARITY; |
2232 | if (cmd->start_arg & CR_EDGE) |
2233 | ai_trig |= NISTC_AI_TRIG_START1_EDGE; |
2234 | break; |
2235 | } |
2236 | ni_stc_writew(dev, data: ai_trig, NISTC_AI_TRIG_SEL_REG); |
2237 | |
2238 | mode2 &= ~NISTC_AI_MODE2_PRE_TRIGGER; |
2239 | mode2 &= ~NISTC_AI_MODE2_SC_INIT_LOAD_SRC; |
2240 | mode2 &= ~NISTC_AI_MODE2_SC_RELOAD_MODE; |
2241 | ni_stc_writew(dev, data: mode2, NISTC_AI_MODE2_REG); |
2242 | |
2243 | if (cmd->chanlist_len == 1 || devpriv->is_611x || devpriv->is_6143) { |
2244 | /* logic low */ |
2245 | start_stop_select |= NISTC_AI_STOP_POLARITY | |
2246 | NISTC_AI_STOP_SEL(31) | |
2247 | NISTC_AI_STOP_SYNC; |
2248 | } else { |
2249 | /* ai configuration memory */ |
2250 | start_stop_select |= NISTC_AI_STOP_SEL(19); |
2251 | } |
2252 | ni_stc_writew(dev, data: start_stop_select, NISTC_AI_START_STOP_REG); |
2253 | |
2254 | devpriv->ai_cmd2 = 0; |
2255 | switch (cmd->stop_src) { |
2256 | case TRIG_COUNT: |
2257 | stop_count = cmd->stop_arg - 1; |
2258 | |
2259 | if (devpriv->is_611x) { |
2260 | /* have to take 3 stage adc pipeline into account */ |
2261 | stop_count += num_adc_stages_611x; |
2262 | } |
2263 | /* stage number of scans */ |
2264 | ni_stc_writel(dev, data: stop_count, NISTC_AI_SC_LOADA_REG); |
2265 | |
2266 | mode1 |= NISTC_AI_MODE1_START_STOP | |
2267 | NISTC_AI_MODE1_RSVD | |
2268 | NISTC_AI_MODE1_TRIGGER_ONCE; |
2269 | ni_stc_writew(dev, data: mode1, NISTC_AI_MODE1_REG); |
2270 | /* load SC (Scan Count) */ |
2271 | ni_stc_writew(dev, NISTC_AI_CMD1_SC_LOAD, NISTC_AI_CMD1_REG); |
2272 | |
2273 | if (stop_count == 0) { |
2274 | devpriv->ai_cmd2 |= NISTC_AI_CMD2_END_ON_EOS; |
2275 | interrupt_a_enable |= NISTC_INTA_ENA_AI_STOP; |
2276 | /* |
2277 | * This is required to get the last sample for |
2278 | * chanlist_len > 1, not sure why. |
2279 | */ |
2280 | if (cmd->chanlist_len > 1) |
2281 | start_stop_select |= NISTC_AI_STOP_POLARITY | |
2282 | NISTC_AI_STOP_EDGE; |
2283 | } |
2284 | break; |
2285 | case TRIG_NONE: |
2286 | /* stage number of scans */ |
2287 | ni_stc_writel(dev, data: 0, NISTC_AI_SC_LOADA_REG); |
2288 | |
2289 | mode1 |= NISTC_AI_MODE1_START_STOP | |
2290 | NISTC_AI_MODE1_RSVD | |
2291 | NISTC_AI_MODE1_CONTINUOUS; |
2292 | ni_stc_writew(dev, data: mode1, NISTC_AI_MODE1_REG); |
2293 | |
2294 | /* load SC (Scan Count) */ |
2295 | ni_stc_writew(dev, NISTC_AI_CMD1_SC_LOAD, NISTC_AI_CMD1_REG); |
2296 | break; |
2297 | } |
2298 | |
2299 | switch (cmd->scan_begin_src) { |
2300 | case TRIG_TIMER: |
2301 | /* |
2302 | * stop bits for non 611x boards |
2303 | * NISTC_AI_MODE3_SI_TRIG_DELAY=0 |
2304 | * NISTC_AI_MODE2_PRE_TRIGGER=0 |
2305 | * NISTC_AI_START_STOP_REG: |
2306 | * NISTC_AI_START_POLARITY=0 (?) rising edge |
2307 | * NISTC_AI_START_EDGE=1 edge triggered |
2308 | * NISTC_AI_START_SYNC=1 (?) |
2309 | * NISTC_AI_START_SEL=0 SI_TC |
2310 | * NISTC_AI_STOP_POLARITY=0 rising edge |
2311 | * NISTC_AI_STOP_EDGE=0 level |
2312 | * NISTC_AI_STOP_SYNC=1 |
2313 | * NISTC_AI_STOP_SEL=19 external pin (configuration mem) |
2314 | */ |
2315 | start_stop_select |= NISTC_AI_START_EDGE | NISTC_AI_START_SYNC; |
2316 | ni_stc_writew(dev, data: start_stop_select, NISTC_AI_START_STOP_REG); |
2317 | |
2318 | mode2 &= ~NISTC_AI_MODE2_SI_INIT_LOAD_SRC; /* A */ |
2319 | mode2 |= NISTC_AI_MODE2_SI_RELOAD_MODE(0); |
2320 | /* mode2 |= NISTC_AI_MODE2_SC_RELOAD_MODE; */ |
2321 | ni_stc_writew(dev, data: mode2, NISTC_AI_MODE2_REG); |
2322 | |
2323 | /* load SI */ |
2324 | timer = ni_ns_to_timer(dev, nanosec: cmd->scan_begin_arg, |
2325 | CMDF_ROUND_NEAREST); |
2326 | ni_stc_writel(dev, data: timer, NISTC_AI_SI_LOADA_REG); |
2327 | ni_stc_writew(dev, NISTC_AI_CMD1_SI_LOAD, NISTC_AI_CMD1_REG); |
2328 | break; |
2329 | case TRIG_EXT: |
2330 | if (cmd->scan_begin_arg & CR_EDGE) |
2331 | start_stop_select |= NISTC_AI_START_EDGE; |
2332 | if (cmd->scan_begin_arg & CR_INVERT) /* falling edge */ |
2333 | start_stop_select |= NISTC_AI_START_POLARITY; |
2334 | if (cmd->scan_begin_src != cmd->convert_src || |
2335 | (cmd->scan_begin_arg & ~CR_EDGE) != |
2336 | (cmd->convert_arg & ~CR_EDGE)) |
2337 | start_stop_select |= NISTC_AI_START_SYNC; |
2338 | |
2339 | start_stop_select |= NISTC_AI_START_SEL( |
2340 | ni_get_reg_value_roffs( |
2341 | CR_CHAN(cmd->scan_begin_arg), |
2342 | NI_AI_SampleClock, |
2343 | &devpriv->routing_tables, 1)); |
2344 | ni_stc_writew(dev, data: start_stop_select, NISTC_AI_START_STOP_REG); |
2345 | break; |
2346 | } |
2347 | |
2348 | switch (cmd->convert_src) { |
2349 | case TRIG_TIMER: |
2350 | case TRIG_NOW: |
2351 | if (cmd->convert_arg == 0 || cmd->convert_src == TRIG_NOW) |
2352 | timer = 1; |
2353 | else |
2354 | timer = ni_ns_to_timer(dev, nanosec: cmd->convert_arg, |
2355 | CMDF_ROUND_NEAREST); |
2356 | /* 0,0 does not work */ |
2357 | ni_stc_writew(dev, data: 1, NISTC_AI_SI2_LOADA_REG); |
2358 | ni_stc_writew(dev, data: timer, NISTC_AI_SI2_LOADB_REG); |
2359 | |
2360 | mode2 &= ~NISTC_AI_MODE2_SI2_INIT_LOAD_SRC; /* A */ |
2361 | mode2 |= NISTC_AI_MODE2_SI2_RELOAD_MODE; /* alternate */ |
2362 | ni_stc_writew(dev, data: mode2, NISTC_AI_MODE2_REG); |
2363 | |
2364 | ni_stc_writew(dev, NISTC_AI_CMD1_SI2_LOAD, NISTC_AI_CMD1_REG); |
2365 | |
2366 | mode2 |= NISTC_AI_MODE2_SI2_INIT_LOAD_SRC; /* B */ |
2367 | mode2 |= NISTC_AI_MODE2_SI2_RELOAD_MODE; /* alternate */ |
2368 | ni_stc_writew(dev, data: mode2, NISTC_AI_MODE2_REG); |
2369 | break; |
2370 | case TRIG_EXT: |
2371 | mode1 |= NISTC_AI_MODE1_CONVERT_SRC( |
2372 | ni_get_reg_value_roffs( |
2373 | CR_CHAN(cmd->convert_arg), |
2374 | NI_AI_ConvertClock, |
2375 | &devpriv->routing_tables, 1)); |
2376 | if ((cmd->convert_arg & CR_INVERT) == 0) |
2377 | mode1 |= NISTC_AI_MODE1_CONVERT_POLARITY; |
2378 | ni_stc_writew(dev, data: mode1, NISTC_AI_MODE1_REG); |
2379 | |
2380 | mode2 |= NISTC_AI_MODE2_SC_GATE_ENA | |
2381 | NISTC_AI_MODE2_START_STOP_GATE_ENA; |
2382 | ni_stc_writew(dev, data: mode2, NISTC_AI_MODE2_REG); |
2383 | |
2384 | break; |
2385 | } |
2386 | |
2387 | if (dev->irq) { |
2388 | /* interrupt on FIFO, errors, SC_TC */ |
2389 | interrupt_a_enable |= NISTC_INTA_ENA_AI_ERR | |
2390 | NISTC_INTA_ENA_AI_SC_TC; |
2391 | |
2392 | #ifndef PCIDMA |
2393 | interrupt_a_enable |= NISTC_INTA_ENA_AI_FIFO; |
2394 | #endif |
2395 | |
2396 | if ((cmd->flags & CMDF_WAKE_EOS) || |
2397 | (devpriv->ai_cmd2 & NISTC_AI_CMD2_END_ON_EOS)) { |
2398 | /* wake on end-of-scan */ |
2399 | devpriv->aimode = AIMODE_SCAN; |
2400 | } else { |
2401 | devpriv->aimode = AIMODE_HALF_FULL; |
2402 | } |
2403 | |
2404 | switch (devpriv->aimode) { |
2405 | case AIMODE_HALF_FULL: |
2406 | /* FIFO interrupts and DMA requests on half-full */ |
2407 | #ifdef PCIDMA |
2408 | ni_stc_writew(dev, NISTC_AI_MODE3_FIFO_MODE_HF_E, |
2409 | NISTC_AI_MODE3_REG); |
2410 | #else |
2411 | ni_stc_writew(dev, NISTC_AI_MODE3_FIFO_MODE_HF, |
2412 | NISTC_AI_MODE3_REG); |
2413 | #endif |
2414 | break; |
2415 | case AIMODE_SAMPLE: |
2416 | /* generate FIFO interrupts on non-empty */ |
2417 | ni_stc_writew(dev, NISTC_AI_MODE3_FIFO_MODE_NE, |
2418 | NISTC_AI_MODE3_REG); |
2419 | break; |
2420 | case AIMODE_SCAN: |
2421 | #ifdef PCIDMA |
2422 | ni_stc_writew(dev, NISTC_AI_MODE3_FIFO_MODE_NE, |
2423 | NISTC_AI_MODE3_REG); |
2424 | #else |
2425 | ni_stc_writew(dev, NISTC_AI_MODE3_FIFO_MODE_HF, |
2426 | NISTC_AI_MODE3_REG); |
2427 | #endif |
2428 | interrupt_a_enable |= NISTC_INTA_ENA_AI_STOP; |
2429 | break; |
2430 | default: |
2431 | break; |
2432 | } |
2433 | |
2434 | /* clear interrupts */ |
2435 | ni_stc_writew(dev, NISTC_INTA_ACK_AI_ALL, NISTC_INTA_ACK_REG); |
2436 | |
2437 | ni_set_bits(dev, NISTC_INTA_ENA_REG, bits: interrupt_a_enable, value: 1); |
2438 | } else { |
2439 | /* interrupt on nothing */ |
2440 | ni_set_bits(dev, NISTC_INTA_ENA_REG, bits: ~0, value: 0); |
2441 | |
2442 | /* XXX start polling if necessary */ |
2443 | } |
2444 | |
2445 | /* end configuration */ |
2446 | ni_stc_writew(dev, NISTC_RESET_AI_CFG_END, NISTC_RESET_REG); |
2447 | |
2448 | switch (cmd->scan_begin_src) { |
2449 | case TRIG_TIMER: |
2450 | ni_stc_writew(dev, NISTC_AI_CMD1_SI2_ARM | |
2451 | NISTC_AI_CMD1_SI_ARM | |
2452 | NISTC_AI_CMD1_DIV_ARM | |
2453 | NISTC_AI_CMD1_SC_ARM, |
2454 | NISTC_AI_CMD1_REG); |
2455 | break; |
2456 | case TRIG_EXT: |
2457 | ni_stc_writew(dev, NISTC_AI_CMD1_SI2_ARM | |
2458 | NISTC_AI_CMD1_SI_ARM | /* XXX ? */ |
2459 | NISTC_AI_CMD1_DIV_ARM | |
2460 | NISTC_AI_CMD1_SC_ARM, |
2461 | NISTC_AI_CMD1_REG); |
2462 | break; |
2463 | } |
2464 | |
2465 | #ifdef PCIDMA |
2466 | { |
2467 | int retval = ni_ai_setup_MITE_dma(dev); |
2468 | |
2469 | if (retval) |
2470 | return retval; |
2471 | } |
2472 | #endif |
2473 | |
2474 | if (cmd->start_src == TRIG_NOW) { |
2475 | ni_stc_writew(dev, NISTC_AI_CMD2_START1_PULSE | |
2476 | devpriv->ai_cmd2, |
2477 | NISTC_AI_CMD2_REG); |
2478 | s->async->inttrig = NULL; |
2479 | } else if (cmd->start_src == TRIG_EXT) { |
2480 | s->async->inttrig = NULL; |
2481 | } else { /* TRIG_INT */ |
2482 | s->async->inttrig = ni_ai_inttrig; |
2483 | } |
2484 | |
2485 | return 0; |
2486 | } |
2487 | |
2488 | static int ni_ai_insn_config(struct comedi_device *dev, |
2489 | struct comedi_subdevice *s, |
2490 | struct comedi_insn *insn, unsigned int *data) |
2491 | { |
2492 | const struct ni_board_struct *board = dev->board_ptr; |
2493 | struct ni_private *devpriv = dev->private; |
2494 | |
2495 | if (insn->n < 1) |
2496 | return -EINVAL; |
2497 | |
2498 | switch (data[0]) { |
2499 | case INSN_CONFIG_ALT_SOURCE: |
2500 | if (devpriv->is_m_series) { |
2501 | if (data[1] & ~NI_M_CFG_BYPASS_AI_CAL_MASK) |
2502 | return -EINVAL; |
2503 | devpriv->ai_calib_source = data[1]; |
2504 | } else if (devpriv->is_6143) { |
2505 | unsigned int calib_source; |
2506 | |
2507 | calib_source = data[1] & 0xf; |
2508 | |
2509 | devpriv->ai_calib_source = calib_source; |
2510 | ni_writew(dev, data: calib_source, NI6143_CALIB_CHAN_REG); |
2511 | } else { |
2512 | unsigned int calib_source; |
2513 | unsigned int calib_source_adjust; |
2514 | |
2515 | calib_source = data[1] & 0xf; |
2516 | calib_source_adjust = (data[1] >> 4) & 0xff; |
2517 | |
2518 | if (calib_source >= 8) |
2519 | return -EINVAL; |
2520 | devpriv->ai_calib_source = calib_source; |
2521 | if (devpriv->is_611x) { |
2522 | ni_writeb(dev, data: calib_source_adjust, |
2523 | NI611X_CAL_GAIN_SEL_REG); |
2524 | } |
2525 | } |
2526 | return 2; |
2527 | case INSN_CONFIG_GET_CMD_TIMING_CONSTRAINTS: |
2528 | /* we don't care about actual channels */ |
2529 | /* data[3] : chanlist_len */ |
2530 | data[1] = ni_min_ai_scan_period_ns(dev, num_channels: data[3]); |
2531 | if (devpriv->is_611x || devpriv->is_6143) |
2532 | data[2] = 0; /* simultaneous output */ |
2533 | else |
2534 | data[2] = board->ai_speed; |
2535 | return 0; |
2536 | default: |
2537 | break; |
2538 | } |
2539 | |
2540 | return -EINVAL; |
2541 | } |
2542 | |
2543 | static void ni_ao_munge(struct comedi_device *dev, struct comedi_subdevice *s, |
2544 | void *data, unsigned int num_bytes, |
2545 | unsigned int chan_index) |
2546 | { |
2547 | struct comedi_cmd *cmd = &s->async->cmd; |
2548 | unsigned int nsamples = comedi_bytes_to_samples(s, nbytes: num_bytes); |
2549 | unsigned short *array = data; |
2550 | unsigned int i; |
2551 | #ifdef PCIDMA |
2552 | __le16 buf, *barray = data; |
2553 | #endif |
2554 | |
2555 | for (i = 0; i < nsamples; i++) { |
2556 | unsigned int range = CR_RANGE(cmd->chanlist[chan_index]); |
2557 | unsigned short val = array[i]; |
2558 | |
2559 | /* |
2560 | * Munge data from unsigned to two's complement for |
2561 | * bipolar ranges. |
2562 | */ |
2563 | if (comedi_range_is_bipolar(s, range)) |
2564 | val = comedi_offset_munge(s, val); |
2565 | #ifdef PCIDMA |
2566 | buf = cpu_to_le16(val); |
2567 | barray[i] = buf; |
2568 | #else |
2569 | array[i] = val; |
2570 | #endif |
2571 | chan_index++; |
2572 | chan_index %= cmd->chanlist_len; |
2573 | } |
2574 | } |
2575 | |
2576 | static int ni_m_series_ao_config_chanlist(struct comedi_device *dev, |
2577 | struct comedi_subdevice *s, |
2578 | unsigned int chanspec[], |
2579 | unsigned int n_chans, int timed) |
2580 | { |
2581 | struct ni_private *devpriv = dev->private; |
2582 | unsigned int range; |
2583 | unsigned int chan; |
2584 | unsigned int conf; |
2585 | int i; |
2586 | int invert = 0; |
2587 | |
2588 | if (timed) { |
2589 | for (i = 0; i < s->n_chan; ++i) { |
2590 | devpriv->ao_conf[i] &= ~NI_M_AO_CFG_BANK_UPDATE_TIMED; |
2591 | ni_writeb(dev, data: devpriv->ao_conf[i], |
2592 | NI_M_AO_CFG_BANK_REG(i)); |
2593 | ni_writeb(dev, data: 0xf, NI_M_AO_WAVEFORM_ORDER_REG(i)); |
2594 | } |
2595 | } |
2596 | for (i = 0; i < n_chans; i++) { |
2597 | const struct comedi_krange *krange; |
2598 | |
2599 | chan = CR_CHAN(chanspec[i]); |
2600 | range = CR_RANGE(chanspec[i]); |
2601 | krange = s->range_table->range + range; |
2602 | invert = 0; |
2603 | conf = 0; |
2604 | switch (krange->max - krange->min) { |
2605 | case 20000000: |
2606 | conf |= NI_M_AO_CFG_BANK_REF_INT_10V; |
2607 | ni_writeb(dev, data: 0, NI_M_AO_REF_ATTENUATION_REG(chan)); |
2608 | break; |
2609 | case 10000000: |
2610 | conf |= NI_M_AO_CFG_BANK_REF_INT_5V; |
2611 | ni_writeb(dev, data: 0, NI_M_AO_REF_ATTENUATION_REG(chan)); |
2612 | break; |
2613 | case 4000000: |
2614 | conf |= NI_M_AO_CFG_BANK_REF_INT_10V; |
2615 | ni_writeb(dev, NI_M_AO_REF_ATTENUATION_X5, |
2616 | NI_M_AO_REF_ATTENUATION_REG(chan)); |
2617 | break; |
2618 | case 2000000: |
2619 | conf |= NI_M_AO_CFG_BANK_REF_INT_5V; |
2620 | ni_writeb(dev, NI_M_AO_REF_ATTENUATION_X5, |
2621 | NI_M_AO_REF_ATTENUATION_REG(chan)); |
2622 | break; |
2623 | default: |
2624 | dev_err(dev->class_dev, |
2625 | "bug! unhandled ao reference voltage\n" ); |
2626 | break; |
2627 | } |
2628 | switch (krange->max + krange->min) { |
2629 | case 0: |
2630 | conf |= NI_M_AO_CFG_BANK_OFFSET_0V; |
2631 | break; |
2632 | case 10000000: |
2633 | conf |= NI_M_AO_CFG_BANK_OFFSET_5V; |
2634 | break; |
2635 | default: |
2636 | dev_err(dev->class_dev, |
2637 | "bug! unhandled ao offset voltage\n" ); |
2638 | break; |
2639 | } |
2640 | if (timed) |
2641 | conf |= NI_M_AO_CFG_BANK_UPDATE_TIMED; |
2642 | ni_writeb(dev, data: conf, NI_M_AO_CFG_BANK_REG(chan)); |
2643 | devpriv->ao_conf[chan] = conf; |
2644 | ni_writeb(dev, data: i, NI_M_AO_WAVEFORM_ORDER_REG(chan)); |
2645 | } |
2646 | return invert; |
2647 | } |
2648 | |
2649 | static int ni_old_ao_config_chanlist(struct comedi_device *dev, |
2650 | struct comedi_subdevice *s, |
2651 | unsigned int chanspec[], |
2652 | unsigned int n_chans) |
2653 | { |
2654 | struct ni_private *devpriv = dev->private; |
2655 | unsigned int range; |
2656 | unsigned int chan; |
2657 | unsigned int conf; |
2658 | int i; |
2659 | int invert = 0; |
2660 | |
2661 | for (i = 0; i < n_chans; i++) { |
2662 | chan = CR_CHAN(chanspec[i]); |
2663 | range = CR_RANGE(chanspec[i]); |
2664 | conf = NI_E_AO_DACSEL(chan); |
2665 | |
2666 | if (comedi_range_is_bipolar(s, range)) { |
2667 | conf |= NI_E_AO_CFG_BIP; |
2668 | invert = (s->maxdata + 1) >> 1; |
2669 | } else { |
2670 | invert = 0; |
2671 | } |
2672 | if (comedi_range_is_external(s, range)) |
2673 | conf |= NI_E_AO_EXT_REF; |
2674 | |
2675 | /* not all boards can deglitch, but this shouldn't hurt */ |
2676 | if (chanspec[i] & CR_DEGLITCH) |
2677 | conf |= NI_E_AO_DEGLITCH; |
2678 | |
2679 | /* analog reference */ |
2680 | /* AREF_OTHER connects AO ground to AI ground, i think */ |
2681 | if (CR_AREF(chanspec[i]) == AREF_OTHER) |
2682 | conf |= NI_E_AO_GROUND_REF; |
2683 | |
2684 | ni_writew(dev, data: conf, NI_E_AO_CFG_REG); |
2685 | devpriv->ao_conf[chan] = conf; |
2686 | } |
2687 | return invert; |
2688 | } |
2689 | |
2690 | static int ni_ao_config_chanlist(struct comedi_device *dev, |
2691 | struct comedi_subdevice *s, |
2692 | unsigned int chanspec[], unsigned int n_chans, |
2693 | int timed) |
2694 | { |
2695 | struct ni_private *devpriv = dev->private; |
2696 | |
2697 | if (devpriv->is_m_series) |
2698 | return ni_m_series_ao_config_chanlist(dev, s, chanspec, n_chans, |
2699 | timed); |
2700 | else |
2701 | return ni_old_ao_config_chanlist(dev, s, chanspec, n_chans); |
2702 | } |
2703 | |
2704 | static int ni_ao_insn_write(struct comedi_device *dev, |
2705 | struct comedi_subdevice *s, |
2706 | struct comedi_insn *insn, |
2707 | unsigned int *data) |
2708 | { |
2709 | struct ni_private *devpriv = dev->private; |
2710 | unsigned int chan = CR_CHAN(insn->chanspec); |
2711 | unsigned int range = CR_RANGE(insn->chanspec); |
2712 | int reg; |
2713 | int i; |
2714 | |
2715 | if (devpriv->is_6xxx) { |
2716 | ni_ao_win_outw(dev, data: 1 << chan, NI671X_AO_IMMEDIATE_REG); |
2717 | |
2718 | reg = NI671X_DAC_DIRECT_DATA_REG(chan); |
2719 | } else if (devpriv->is_m_series) { |
2720 | reg = NI_M_DAC_DIRECT_DATA_REG(chan); |
2721 | } else { |
2722 | reg = NI_E_DAC_DIRECT_DATA_REG(chan); |
2723 | } |
2724 | |
2725 | ni_ao_config_chanlist(dev, s, chanspec: &insn->chanspec, n_chans: 1, timed: 0); |
2726 | |
2727 | for (i = 0; i < insn->n; i++) { |
2728 | unsigned int val = data[i]; |
2729 | |
2730 | s->readback[chan] = val; |
2731 | |
2732 | if (devpriv->is_6xxx) { |
2733 | /* |
2734 | * 6xxx boards have bipolar outputs, munge the |
2735 | * unsigned comedi values to 2's complement |
2736 | */ |
2737 | val = comedi_offset_munge(s, val); |
2738 | |
2739 | ni_ao_win_outw(dev, data: val, addr: reg); |
2740 | } else if (devpriv->is_m_series) { |
2741 | /* |
2742 | * M-series boards use offset binary values for |
2743 | * bipolar and uinpolar outputs |
2744 | */ |
2745 | ni_writew(dev, data: val, reg); |
2746 | } else { |
2747 | /* |
2748 | * Non-M series boards need two's complement values |
2749 | * for bipolar ranges. |
2750 | */ |
2751 | if (comedi_range_is_bipolar(s, range)) |
2752 | val = comedi_offset_munge(s, val); |
2753 | |
2754 | ni_writew(dev, data: val, reg); |
2755 | } |
2756 | } |
2757 | |
2758 | return insn->n; |
2759 | } |
2760 | |
2761 | /* |
2762 | * Arms the AO device in preparation for a trigger event. |
2763 | * This function also allocates and prepares a DMA channel (or FIFO if DMA is |
2764 | * not used). As a part of this preparation, this function preloads the DAC |
2765 | * registers with the first values of the output stream. This ensures that the |
2766 | * first clock cycle after the trigger can be used for output. |
2767 | * |
2768 | * Note that this function _must_ happen after a user has written data to the |
2769 | * output buffers via either mmap or write(fileno,...). |
2770 | */ |
2771 | static int ni_ao_arm(struct comedi_device *dev, |
2772 | struct comedi_subdevice *s) |
2773 | { |
2774 | struct ni_private *devpriv = dev->private; |
2775 | int ret; |
2776 | int interrupt_b_bits; |
2777 | int i; |
2778 | static const int timeout = 1000; |
2779 | |
2780 | /* |
2781 | * Prevent ao from doing things like trying to allocate the ao dma |
2782 | * channel multiple times. |
2783 | */ |
2784 | if (!devpriv->ao_needs_arming) { |
2785 | dev_dbg(dev->class_dev, "%s: device does not need arming!\n" , |
2786 | __func__); |
2787 | return -EINVAL; |
2788 | } |
2789 | |
2790 | devpriv->ao_needs_arming = 0; |
2791 | |
2792 | ni_set_bits(dev, NISTC_INTB_ENA_REG, |
2793 | NISTC_INTB_ENA_AO_FIFO | NISTC_INTB_ENA_AO_ERR, value: 0); |
2794 | interrupt_b_bits = NISTC_INTB_ENA_AO_ERR; |
2795 | #ifdef PCIDMA |
2796 | ni_stc_writew(dev, 1, NISTC_DAC_FIFO_CLR_REG); |
2797 | if (devpriv->is_6xxx) |
2798 | ni_ao_win_outl(dev, 0x6, NI611X_AO_FIFO_OFFSET_LOAD_REG); |
2799 | ret = ni_ao_setup_MITE_dma(dev); |
2800 | if (ret) |
2801 | return ret; |
2802 | ret = ni_ao_wait_for_dma_load(dev); |
2803 | if (ret < 0) |
2804 | return ret; |
2805 | #else |
2806 | ret = ni_ao_prep_fifo(dev, s); |
2807 | if (ret == 0) |
2808 | return -EPIPE; |
2809 | |
2810 | interrupt_b_bits |= NISTC_INTB_ENA_AO_FIFO; |
2811 | #endif |
2812 | |
2813 | ni_stc_writew(dev, data: devpriv->ao_mode3 | NISTC_AO_MODE3_NOT_AN_UPDATE, |
2814 | NISTC_AO_MODE3_REG); |
2815 | ni_stc_writew(dev, data: devpriv->ao_mode3, NISTC_AO_MODE3_REG); |
2816 | /* wait for DACs to be loaded */ |
2817 | for (i = 0; i < timeout; i++) { |
2818 | udelay(1); |
2819 | if ((ni_stc_readw(dev, NISTC_STATUS2_REG) & |
2820 | NISTC_STATUS2_AO_TMRDACWRS_IN_PROGRESS) == 0) |
2821 | break; |
2822 | } |
2823 | if (i == timeout) { |
2824 | dev_err(dev->class_dev, |
2825 | "timed out waiting for AO_TMRDACWRs_In_Progress_St to clear\n" ); |
2826 | return -EIO; |
2827 | } |
2828 | /* |
2829 | * stc manual says we are need to clear error interrupt after |
2830 | * AO_TMRDACWRs_In_Progress_St clears |
2831 | */ |
2832 | ni_stc_writew(dev, NISTC_INTB_ACK_AO_ERR, NISTC_INTB_ACK_REG); |
2833 | |
2834 | ni_set_bits(dev, NISTC_INTB_ENA_REG, bits: interrupt_b_bits, value: 1); |
2835 | |
2836 | ni_stc_writew(dev, NISTC_AO_CMD1_UI_ARM | |
2837 | NISTC_AO_CMD1_UC_ARM | |
2838 | NISTC_AO_CMD1_BC_ARM | |
2839 | devpriv->ao_cmd1, |
2840 | NISTC_AO_CMD1_REG); |
2841 | |
2842 | return 0; |
2843 | } |
2844 | |
2845 | static int ni_ao_insn_config(struct comedi_device *dev, |
2846 | struct comedi_subdevice *s, |
2847 | struct comedi_insn *insn, unsigned int *data) |
2848 | { |
2849 | const struct ni_board_struct *board = dev->board_ptr; |
2850 | struct ni_private *devpriv = dev->private; |
2851 | unsigned int nbytes; |
2852 | |
2853 | switch (data[0]) { |
2854 | case INSN_CONFIG_GET_HARDWARE_BUFFER_SIZE: |
2855 | switch (data[1]) { |
2856 | case COMEDI_OUTPUT: |
2857 | nbytes = comedi_samples_to_bytes(s, |
2858 | nsamples: board->ao_fifo_depth); |
2859 | data[2] = 1 + nbytes; |
2860 | if (devpriv->mite) |
2861 | data[2] += devpriv->mite->fifo_size; |
2862 | break; |
2863 | case COMEDI_INPUT: |
2864 | data[2] = 0; |
2865 | break; |
2866 | default: |
2867 | return -EINVAL; |
2868 | } |
2869 | return 0; |
2870 | case INSN_CONFIG_ARM: |
2871 | return ni_ao_arm(dev, s); |
2872 | case INSN_CONFIG_GET_CMD_TIMING_CONSTRAINTS: |
2873 | /* we don't care about actual channels */ |
2874 | /* data[3] : chanlist_len */ |
2875 | data[1] = board->ao_speed * data[3]; |
2876 | data[2] = 0; |
2877 | return 0; |
2878 | default: |
2879 | break; |
2880 | } |
2881 | |
2882 | return -EINVAL; |
2883 | } |
2884 | |
2885 | static int ni_ao_inttrig(struct comedi_device *dev, |
2886 | struct comedi_subdevice *s, |
2887 | unsigned int trig_num) |
2888 | { |
2889 | struct ni_private *devpriv = dev->private; |
2890 | struct comedi_cmd *cmd = &s->async->cmd; |
2891 | int ret; |
2892 | |
2893 | /* |
2894 | * Require trig_num == cmd->start_arg when cmd->start_src == TRIG_INT. |
2895 | * For backwards compatibility, also allow trig_num == 0 when |
2896 | * cmd->start_src != TRIG_INT (i.e. when cmd->start_src == TRIG_EXT); |
2897 | * in that case, the internal trigger is being used as a pre-trigger |
2898 | * before the external trigger. |
2899 | */ |
2900 | if (!(trig_num == cmd->start_arg || |
2901 | (trig_num == 0 && cmd->start_src != TRIG_INT))) |
2902 | return -EINVAL; |
2903 | |
2904 | /* |
2905 | * Null trig at beginning prevent ao start trigger from executing more |
2906 | * than once per command. |
2907 | */ |
2908 | s->async->inttrig = NULL; |
2909 | |
2910 | if (devpriv->ao_needs_arming) { |
2911 | /* only arm this device if it still needs arming */ |
2912 | ret = ni_ao_arm(dev, s); |
2913 | if (ret) |
2914 | return ret; |
2915 | } |
2916 | |
2917 | ni_stc_writew(dev, NISTC_AO_CMD2_START1_PULSE | devpriv->ao_cmd2, |
2918 | NISTC_AO_CMD2_REG); |
2919 | |
2920 | return 0; |
2921 | } |
2922 | |
2923 | /* |
2924 | * begin ni_ao_cmd. |
2925 | * Organized similar to NI-STC and MHDDK examples. |
2926 | * ni_ao_cmd is broken out into configuration sub-routines for clarity. |
2927 | */ |
2928 | |
2929 | static void ni_ao_cmd_personalize(struct comedi_device *dev, |
2930 | const struct comedi_cmd *cmd) |
2931 | { |
2932 | const struct ni_board_struct *board = dev->board_ptr; |
2933 | unsigned int bits; |
2934 | |
2935 | ni_stc_writew(dev, NISTC_RESET_AO_CFG_START, NISTC_RESET_REG); |
2936 | |
2937 | bits = |
2938 | /* fast CPU interface--only eseries */ |
2939 | /* ((slow CPU interface) ? 0 : AO_Fast_CPU) | */ |
2940 | NISTC_AO_PERSONAL_BC_SRC_SEL | |
2941 | 0 /* (use_original_pulse ? 0 : NISTC_AO_PERSONAL_UPDATE_TIMEBASE) */ | |
2942 | /* |
2943 | * FIXME: start setting following bit when appropriate. Need to |
2944 | * determine whether board is E4 or E1. |
2945 | * FROM MHHDK: |
2946 | * if board is E4 or E1 |
2947 | * Set bit "NISTC_AO_PERSONAL_UPDATE_PW" to 0 |
2948 | * else |
2949 | * set it to 1 |
2950 | */ |
2951 | NISTC_AO_PERSONAL_UPDATE_PW | |
2952 | /* FIXME: when should we set following bit to zero? */ |
2953 | NISTC_AO_PERSONAL_TMRDACWR_PW | |
2954 | (board->ao_fifo_depth ? |
2955 | NISTC_AO_PERSONAL_FIFO_ENA : NISTC_AO_PERSONAL_DMA_PIO_CTRL) |
2956 | ; |
2957 | #if 0 |
2958 | /* |
2959 | * FIXME: |
2960 | * add something like ".has_individual_dacs = 0" to ni_board_struct |
2961 | * since, as F Hess pointed out, not all in m series have singles. not |
2962 | * sure if e-series all have duals... |
2963 | */ |
2964 | |
2965 | /* |
2966 | * F Hess: windows driver does not set NISTC_AO_PERSONAL_NUM_DAC bit for |
2967 | * 6281, verified with bus analyzer. |
2968 | */ |
2969 | if (devpriv->is_m_series) |
2970 | bits |= NISTC_AO_PERSONAL_NUM_DAC; |
2971 | #endif |
2972 | ni_stc_writew(dev, data: bits, NISTC_AO_PERSONAL_REG); |
2973 | |
2974 | ni_stc_writew(dev, NISTC_RESET_AO_CFG_END, NISTC_RESET_REG); |
2975 | } |
2976 | |
2977 | static void ni_ao_cmd_set_trigger(struct comedi_device *dev, |
2978 | const struct comedi_cmd *cmd) |
2979 | { |
2980 | struct ni_private *devpriv = dev->private; |
2981 | unsigned int trigsel; |
2982 | |
2983 | ni_stc_writew(dev, NISTC_RESET_AO_CFG_START, NISTC_RESET_REG); |
2984 | |
2985 | /* sync */ |
2986 | if (cmd->stop_src == TRIG_NONE) { |
2987 | devpriv->ao_mode1 |= NISTC_AO_MODE1_CONTINUOUS; |
2988 | devpriv->ao_mode1 &= ~NISTC_AO_MODE1_TRIGGER_ONCE; |
2989 | } else { |
2990 | devpriv->ao_mode1 &= ~NISTC_AO_MODE1_CONTINUOUS; |
2991 | devpriv->ao_mode1 |= NISTC_AO_MODE1_TRIGGER_ONCE; |
2992 | } |
2993 | ni_stc_writew(dev, data: devpriv->ao_mode1, NISTC_AO_MODE1_REG); |
2994 | |
2995 | if (cmd->start_src == TRIG_INT) { |
2996 | trigsel = NISTC_AO_TRIG_START1_EDGE | |
2997 | NISTC_AO_TRIG_START1_SYNC; |
2998 | } else { /* TRIG_EXT */ |
2999 | trigsel = NISTC_AO_TRIG_START1_SEL( |
3000 | ni_get_reg_value_roffs( |
3001 | CR_CHAN(cmd->start_arg), |
3002 | NI_AO_StartTrigger, |
3003 | &devpriv->routing_tables, 1)); |
3004 | |
3005 | /* 0=active high, 1=active low. see daq-stc 3-24 (p186) */ |
3006 | if (cmd->start_arg & CR_INVERT) |
3007 | trigsel |= NISTC_AO_TRIG_START1_POLARITY; |
3008 | /* 0=edge detection disabled, 1=enabled */ |
3009 | if (cmd->start_arg & CR_EDGE) |
3010 | trigsel |= NISTC_AO_TRIG_START1_EDGE; |
3011 | } |
3012 | ni_stc_writew(dev, data: trigsel, NISTC_AO_TRIG_SEL_REG); |
3013 | |
3014 | /* AO_Delayed_START1 = 0, we do not support delayed start...yet */ |
3015 | |
3016 | /* sync */ |
3017 | /* select DA_START1 as PFI6/AO_START1 when configured as an output */ |
3018 | devpriv->ao_mode3 &= ~NISTC_AO_MODE3_TRIG_LEN; |
3019 | ni_stc_writew(dev, data: devpriv->ao_mode3, NISTC_AO_MODE3_REG); |
3020 | |
3021 | ni_stc_writew(dev, NISTC_RESET_AO_CFG_END, NISTC_RESET_REG); |
3022 | } |
3023 | |
3024 | static void ni_ao_cmd_set_counters(struct comedi_device *dev, |
3025 | const struct comedi_cmd *cmd) |
3026 | { |
3027 | struct ni_private *devpriv = dev->private; |
3028 | /* Not supporting 'waveform staging' or 'local buffer with pauses' */ |
3029 | |
3030 | ni_stc_writew(dev, NISTC_RESET_AO_CFG_START, NISTC_RESET_REG); |
3031 | /* |
3032 | * This relies on ao_mode1/(Trigger_Once | Continuous) being set in |
3033 | * set_trigger above. It is unclear whether we really need to re-write |
3034 | * this register with these values. The mhddk examples for e-series |
3035 | * show writing this in both places, but the examples for m-series show |
3036 | * a single write in the set_counters function (here). |
3037 | */ |
3038 | ni_stc_writew(dev, data: devpriv->ao_mode1, NISTC_AO_MODE1_REG); |
3039 | |
3040 | /* sync (upload number of buffer iterations -1) */ |
3041 | /* indicate that we want to use BC_Load_A_Register as the source */ |
3042 | devpriv->ao_mode2 &= ~NISTC_AO_MODE2_BC_INIT_LOAD_SRC; |
3043 | ni_stc_writew(dev, data: devpriv->ao_mode2, NISTC_AO_MODE2_REG); |
3044 | |
3045 | /* |
3046 | * if the BC_TC interrupt is still issued in spite of UC, BC, UI |
3047 | * ignoring BC_TC, then we will need to find a way to ignore that |
3048 | * interrupt in continuous mode. |
3049 | */ |
3050 | ni_stc_writel(dev, data: 0, NISTC_AO_BC_LOADA_REG); /* iter once */ |
3051 | |
3052 | /* sync (issue command to load number of buffer iterations -1) */ |
3053 | ni_stc_writew(dev, NISTC_AO_CMD1_BC_LOAD, NISTC_AO_CMD1_REG); |
3054 | |
3055 | /* sync (upload number of updates in buffer) */ |
3056 | /* indicate that we want to use UC_Load_A_Register as the source */ |
3057 | devpriv->ao_mode2 &= ~NISTC_AO_MODE2_UC_INIT_LOAD_SRC; |
3058 | ni_stc_writew(dev, data: devpriv->ao_mode2, NISTC_AO_MODE2_REG); |
3059 | |
3060 | /* |
3061 | * if a user specifies '0', this automatically assumes the entire 24bit |
3062 | * address space is available for the (multiple iterations of single |
3063 | * buffer) MISB. Otherwise, stop_arg specifies the MISB length that |
3064 | * will be used, regardless of whether we are in continuous mode or not. |
3065 | * In continuous mode, the output will just iterate indefinitely over |
3066 | * the MISB. |
3067 | */ |
3068 | { |
3069 | unsigned int stop_arg = cmd->stop_arg > 0 ? |
3070 | (cmd->stop_arg & 0xffffff) : 0xffffff; |
3071 | |
3072 | if (devpriv->is_m_series) { |
3073 | /* |
3074 | * this is how the NI example code does it for m-series |
3075 | * boards, verified correct with 6259 |
3076 | */ |
3077 | ni_stc_writel(dev, data: stop_arg - 1, NISTC_AO_UC_LOADA_REG); |
3078 | |
3079 | /* sync (issue cmd to load number of updates in MISB) */ |
3080 | ni_stc_writew(dev, NISTC_AO_CMD1_UC_LOAD, |
3081 | NISTC_AO_CMD1_REG); |
3082 | } else { |
3083 | ni_stc_writel(dev, data: stop_arg, NISTC_AO_UC_LOADA_REG); |
3084 | |
3085 | /* sync (issue cmd to load number of updates in MISB) */ |
3086 | ni_stc_writew(dev, NISTC_AO_CMD1_UC_LOAD, |
3087 | NISTC_AO_CMD1_REG); |
3088 | |
3089 | /* |
3090 | * sync (upload number of updates-1 in MISB) |
3091 | * --eseries only? |
3092 | */ |
3093 | ni_stc_writel(dev, data: stop_arg - 1, NISTC_AO_UC_LOADA_REG); |
3094 | } |
3095 | } |
3096 | |
3097 | ni_stc_writew(dev, NISTC_RESET_AO_CFG_END, NISTC_RESET_REG); |
3098 | } |
3099 | |
3100 | static void ni_ao_cmd_set_update(struct comedi_device *dev, |
3101 | const struct comedi_cmd *cmd) |
3102 | { |
3103 | struct ni_private *devpriv = dev->private; |
3104 | |
3105 | ni_stc_writew(dev, NISTC_RESET_AO_CFG_START, NISTC_RESET_REG); |
3106 | |
3107 | /* |
3108 | * zero out these bit fields to be set below. Does an ao-reset do this |
3109 | * automatically? |
3110 | */ |
3111 | devpriv->ao_mode1 &= ~(NISTC_AO_MODE1_UI_SRC_MASK | |
3112 | NISTC_AO_MODE1_UI_SRC_POLARITY | |
3113 | NISTC_AO_MODE1_UPDATE_SRC_MASK | |
3114 | NISTC_AO_MODE1_UPDATE_SRC_POLARITY); |
3115 | |
3116 | if (cmd->scan_begin_src == TRIG_TIMER) { |
3117 | unsigned int trigvar; |
3118 | |
3119 | devpriv->ao_cmd2 &= ~NISTC_AO_CMD2_BC_GATE_ENA; |
3120 | |
3121 | /* |
3122 | * NOTE: there are several other ways of configuring internal |
3123 | * updates, but we'll only support one for now: using |
3124 | * AO_IN_TIMEBASE, w/o waveform staging, w/o a delay between |
3125 | * START1 and first update, and also w/o local buffer mode w/ |
3126 | * pauses. |
3127 | */ |
3128 | |
3129 | /* |
3130 | * This is already done above: |
3131 | * devpriv->ao_mode1 &= ~( |
3132 | * // set UPDATE_Source to UI_TC: |
3133 | * NISTC_AO_MODE1_UPDATE_SRC_MASK | |
3134 | * // set UPDATE_Source_Polarity to rising (required?) |
3135 | * NISTC_AO_MODE1_UPDATE_SRC_POLARITY | |
3136 | * // set UI_Source to AO_IN_TIMEBASE1: |
3137 | * NISTC_AO_MODE1_UI_SRC_MASK | |
3138 | * // set UI_Source_Polarity to rising (required?) |
3139 | * NISTC_AO_MODE1_UI_SRC_POLARITY |
3140 | * ); |
3141 | */ |
3142 | |
3143 | /* |
3144 | * TODO: use ao_ui_clock_source to allow all possible signals |
3145 | * to be routed to UI_Source_Select. See tSTC.h for |
3146 | * eseries/ni67xx and tMSeries.h for mseries. |
3147 | */ |
3148 | |
3149 | trigvar = ni_ns_to_timer(dev, nanosec: cmd->scan_begin_arg, |
3150 | CMDF_ROUND_NEAREST); |
3151 | |
3152 | /* |
3153 | * Wait N TB3 ticks after the start trigger before |
3154 | * clocking (N must be >=2). |
3155 | */ |
3156 | /* following line: 2-1 per STC */ |
3157 | ni_stc_writel(dev, data: 1, NISTC_AO_UI_LOADA_REG); |
3158 | ni_stc_writew(dev, NISTC_AO_CMD1_UI_LOAD, NISTC_AO_CMD1_REG); |
3159 | ni_stc_writel(dev, data: trigvar, NISTC_AO_UI_LOADA_REG); |
3160 | } else { /* TRIG_EXT */ |
3161 | /* FIXME: assert scan_begin_arg != 0, ret failure otherwise */ |
3162 | devpriv->ao_cmd2 |= NISTC_AO_CMD2_BC_GATE_ENA; |
3163 | devpriv->ao_mode1 |= NISTC_AO_MODE1_UPDATE_SRC( |
3164 | ni_get_reg_value( |
3165 | CR_CHAN(cmd->scan_begin_arg), |
3166 | NI_AO_SampleClock, |
3167 | &devpriv->routing_tables)); |
3168 | if (cmd->scan_begin_arg & CR_INVERT) |
3169 | devpriv->ao_mode1 |= NISTC_AO_MODE1_UPDATE_SRC_POLARITY; |
3170 | } |
3171 | |
3172 | ni_stc_writew(dev, data: devpriv->ao_cmd2, NISTC_AO_CMD2_REG); |
3173 | ni_stc_writew(dev, data: devpriv->ao_mode1, NISTC_AO_MODE1_REG); |
3174 | devpriv->ao_mode2 &= ~(NISTC_AO_MODE2_UI_RELOAD_MODE(3) | |
3175 | NISTC_AO_MODE2_UI_INIT_LOAD_SRC); |
3176 | ni_stc_writew(dev, data: devpriv->ao_mode2, NISTC_AO_MODE2_REG); |
3177 | |
3178 | /* Configure DAQ-STC for Timed update mode */ |
3179 | devpriv->ao_cmd1 |= NISTC_AO_CMD1_DAC1_UPDATE_MODE | |
3180 | NISTC_AO_CMD1_DAC0_UPDATE_MODE; |
3181 | /* We are not using UPDATE2-->don't have to set DACx_Source_Select */ |
3182 | ni_stc_writew(dev, data: devpriv->ao_cmd1, NISTC_AO_CMD1_REG); |
3183 | |
3184 | ni_stc_writew(dev, NISTC_RESET_AO_CFG_END, NISTC_RESET_REG); |
3185 | } |
3186 | |
3187 | static void ni_ao_cmd_set_channels(struct comedi_device *dev, |
3188 | struct comedi_subdevice *s) |
3189 | { |
3190 | struct ni_private *devpriv = dev->private; |
3191 | const struct comedi_cmd *cmd = &s->async->cmd; |
3192 | unsigned int bits = 0; |
3193 | |
3194 | ni_stc_writew(dev, NISTC_RESET_AO_CFG_START, NISTC_RESET_REG); |
3195 | |
3196 | if (devpriv->is_6xxx) { |
3197 | unsigned int i; |
3198 | |
3199 | bits = 0; |
3200 | for (i = 0; i < cmd->chanlist_len; ++i) { |
3201 | int chan = CR_CHAN(cmd->chanlist[i]); |
3202 | |
3203 | bits |= 1 << chan; |
3204 | ni_ao_win_outw(dev, data: chan, NI611X_AO_WAVEFORM_GEN_REG); |
3205 | } |
3206 | ni_ao_win_outw(dev, data: bits, NI611X_AO_TIMED_REG); |
3207 | } |
3208 | |
3209 | ni_ao_config_chanlist(dev, s, chanspec: cmd->chanlist, n_chans: cmd->chanlist_len, timed: 1); |
3210 | |
3211 | if (cmd->scan_end_arg > 1) { |
3212 | devpriv->ao_mode1 |= NISTC_AO_MODE1_MULTI_CHAN; |
3213 | bits = NISTC_AO_OUT_CTRL_CHANS(cmd->scan_end_arg - 1) |
3214 | | NISTC_AO_OUT_CTRL_UPDATE_SEL_HIGHZ; |
3215 | |
3216 | } else { |
3217 | devpriv->ao_mode1 &= ~NISTC_AO_MODE1_MULTI_CHAN; |
3218 | bits = NISTC_AO_OUT_CTRL_UPDATE_SEL_HIGHZ; |
3219 | if (devpriv->is_m_series | devpriv->is_6xxx) |
3220 | bits |= NISTC_AO_OUT_CTRL_CHANS(0); |
3221 | else |
3222 | bits |= NISTC_AO_OUT_CTRL_CHANS( |
3223 | CR_CHAN(cmd->chanlist[0])); |
3224 | } |
3225 | |
3226 | ni_stc_writew(dev, data: devpriv->ao_mode1, NISTC_AO_MODE1_REG); |
3227 | ni_stc_writew(dev, data: bits, NISTC_AO_OUT_CTRL_REG); |
3228 | |
3229 | ni_stc_writew(dev, NISTC_RESET_AO_CFG_END, NISTC_RESET_REG); |
3230 | } |
3231 | |
3232 | static void ni_ao_cmd_set_stop_conditions(struct comedi_device *dev, |
3233 | const struct comedi_cmd *cmd) |
3234 | { |
3235 | struct ni_private *devpriv = dev->private; |
3236 | |
3237 | ni_stc_writew(dev, NISTC_RESET_AO_CFG_START, NISTC_RESET_REG); |
3238 | |
3239 | devpriv->ao_mode3 |= NISTC_AO_MODE3_STOP_ON_OVERRUN_ERR; |
3240 | ni_stc_writew(dev, data: devpriv->ao_mode3, NISTC_AO_MODE3_REG); |
3241 | |
3242 | /* |
3243 | * Since we are not supporting waveform staging, we ignore these errors: |
3244 | * NISTC_AO_MODE3_STOP_ON_BC_TC_ERR, |
3245 | * NISTC_AO_MODE3_STOP_ON_BC_TC_TRIG_ERR |
3246 | */ |
3247 | |
3248 | ni_stc_writew(dev, NISTC_RESET_AO_CFG_END, NISTC_RESET_REG); |
3249 | } |
3250 | |
3251 | static void ni_ao_cmd_set_fifo_mode(struct comedi_device *dev) |
3252 | { |
3253 | struct ni_private *devpriv = dev->private; |
3254 | |
3255 | ni_stc_writew(dev, NISTC_RESET_AO_CFG_START, NISTC_RESET_REG); |
3256 | |
3257 | devpriv->ao_mode2 &= ~NISTC_AO_MODE2_FIFO_MODE_MASK; |
3258 | #ifdef PCIDMA |
3259 | devpriv->ao_mode2 |= NISTC_AO_MODE2_FIFO_MODE_HF_F; |
3260 | #else |
3261 | devpriv->ao_mode2 |= NISTC_AO_MODE2_FIFO_MODE_HF; |
3262 | #endif |
3263 | /* NOTE: this is where use_onboard_memory=True would be implemented */ |
3264 | devpriv->ao_mode2 &= ~NISTC_AO_MODE2_FIFO_REXMIT_ENA; |
3265 | ni_stc_writew(dev, data: devpriv->ao_mode2, NISTC_AO_MODE2_REG); |
3266 | |
3267 | /* enable sending of ao fifo requests (dma request) */ |
3268 | ni_stc_writew(dev, NISTC_AO_START_AOFREQ_ENA, NISTC_AO_START_SEL_REG); |
3269 | |
3270 | ni_stc_writew(dev, NISTC_RESET_AO_CFG_END, NISTC_RESET_REG); |
3271 | |
3272 | /* we are not supporting boards with virtual fifos */ |
3273 | } |
3274 | |
3275 | static void ni_ao_cmd_set_interrupts(struct comedi_device *dev, |
3276 | struct comedi_subdevice *s) |
3277 | { |
3278 | if (s->async->cmd.stop_src == TRIG_COUNT) |
3279 | ni_set_bits(dev, NISTC_INTB_ENA_REG, |
3280 | NISTC_INTB_ENA_AO_BC_TC, value: 1); |
3281 | |
3282 | s->async->inttrig = ni_ao_inttrig; |
3283 | } |
3284 | |
3285 | static int ni_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) |
3286 | { |
3287 | struct ni_private *devpriv = dev->private; |
3288 | const struct comedi_cmd *cmd = &s->async->cmd; |
3289 | |
3290 | if (dev->irq == 0) { |
3291 | dev_err(dev->class_dev, "cannot run command without an irq" ); |
3292 | return -EIO; |
3293 | } |
3294 | |
3295 | /* ni_ao_reset should have already been done */ |
3296 | ni_ao_cmd_personalize(dev, cmd); |
3297 | /* clearing fifo and preload happens elsewhere */ |
3298 | |
3299 | ni_ao_cmd_set_trigger(dev, cmd); |
3300 | ni_ao_cmd_set_counters(dev, cmd); |
3301 | ni_ao_cmd_set_update(dev, cmd); |
3302 | ni_ao_cmd_set_channels(dev, s); |
3303 | ni_ao_cmd_set_stop_conditions(dev, cmd); |
3304 | ni_ao_cmd_set_fifo_mode(dev); |
3305 | ni_cmd_set_mite_transfer(ring: devpriv->ao_mite_ring, sdev: s, cmd, max_count: 0x00ffffff); |
3306 | ni_ao_cmd_set_interrupts(dev, s); |
3307 | |
3308 | /* |
3309 | * arm(ing) must happen later so that DMA can be setup and DACs |
3310 | * preloaded with the actual output buffer before starting. |
3311 | * |
3312 | * start(ing) must happen _after_ arming is completed. Starting can be |
3313 | * done either via ni_ao_inttrig, or via an external trigger. |
3314 | * |
3315 | * **Currently, ni_ao_inttrig will automatically attempt a call to |
3316 | * ni_ao_arm if the device still needs arming at that point. This |
3317 | * allows backwards compatibility. |
3318 | */ |
3319 | devpriv->ao_needs_arming = 1; |
3320 | return 0; |
3321 | } |
3322 | |
3323 | /* end ni_ao_cmd */ |
3324 | |
3325 | static int ni_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s, |
3326 | struct comedi_cmd *cmd) |
3327 | { |
3328 | const struct ni_board_struct *board = dev->board_ptr; |
3329 | struct ni_private *devpriv = dev->private; |
3330 | int err = 0; |
3331 | unsigned int tmp; |
3332 | |
3333 | /* Step 1 : check if triggers are trivially valid */ |
3334 | |
3335 | err |= comedi_check_trigger_src(src: &cmd->start_src, TRIG_INT | TRIG_EXT); |
3336 | err |= comedi_check_trigger_src(src: &cmd->scan_begin_src, |
3337 | TRIG_TIMER | TRIG_EXT); |
3338 | err |= comedi_check_trigger_src(src: &cmd->convert_src, TRIG_NOW); |
3339 | err |= comedi_check_trigger_src(src: &cmd->scan_end_src, TRIG_COUNT); |
3340 | err |= comedi_check_trigger_src(src: &cmd->stop_src, TRIG_COUNT | TRIG_NONE); |
3341 | |
3342 | if (err) |
3343 | return 1; |
3344 | |
3345 | /* Step 2a : make sure trigger sources are unique */ |
3346 | |
3347 | err |= comedi_check_trigger_is_unique(src: cmd->start_src); |
3348 | err |= comedi_check_trigger_is_unique(src: cmd->scan_begin_src); |
3349 | err |= comedi_check_trigger_is_unique(src: cmd->stop_src); |
3350 | |
3351 | /* Step 2b : and mutually compatible */ |
3352 | |
3353 | if (err) |
3354 | return 2; |
3355 | |
3356 | /* Step 3: check if arguments are trivially valid */ |
3357 | |
3358 | switch (cmd->start_src) { |
3359 | case TRIG_INT: |
3360 | err |= comedi_check_trigger_arg_is(arg: &cmd->start_arg, val: 0); |
3361 | break; |
3362 | case TRIG_EXT: |
3363 | err |= ni_check_trigger_arg_roffs(CR_CHAN(cmd->start_arg), |
3364 | dest: NI_AO_StartTrigger, |
3365 | tables: &devpriv->routing_tables, direct_reg_offset: 1); |
3366 | break; |
3367 | } |
3368 | |
3369 | if (cmd->scan_begin_src == TRIG_TIMER) { |
3370 | err |= comedi_check_trigger_arg_min(arg: &cmd->scan_begin_arg, |
3371 | val: board->ao_speed); |
3372 | err |= comedi_check_trigger_arg_max(arg: &cmd->scan_begin_arg, |
3373 | val: devpriv->clock_ns * |
3374 | 0xffffff); |
3375 | } else { /* TRIG_EXT */ |
3376 | err |= ni_check_trigger_arg(CR_CHAN(cmd->scan_begin_arg), |
3377 | dest: NI_AO_SampleClock, |
3378 | tables: &devpriv->routing_tables); |
3379 | } |
3380 | |
3381 | err |= comedi_check_trigger_arg_is(arg: &cmd->convert_arg, val: 0); |
3382 | err |= comedi_check_trigger_arg_is(arg: &cmd->scan_end_arg, |
3383 | val: cmd->chanlist_len); |
3384 | err |= comedi_check_trigger_arg_max(arg: &cmd->stop_arg, val: 0x00ffffff); |
3385 | |
3386 | if (err) |
3387 | return 3; |
3388 | |
3389 | /* step 4: fix up any arguments */ |
3390 | if (cmd->scan_begin_src == TRIG_TIMER) { |
3391 | tmp = cmd->scan_begin_arg; |
3392 | cmd->scan_begin_arg = |
3393 | ni_timer_to_ns(dev, timer: ni_ns_to_timer(dev, |
3394 | nanosec: cmd->scan_begin_arg, |
3395 | flags: cmd->flags)); |
3396 | if (tmp != cmd->scan_begin_arg) |
3397 | err++; |
3398 | } |
3399 | if (err) |
3400 | return 4; |
3401 | |
3402 | return 0; |
3403 | } |
3404 | |
3405 | static int ni_ao_reset(struct comedi_device *dev, struct comedi_subdevice *s) |
3406 | { |
3407 | /* See 3.6.1.2 "Resetting", of DAQ-STC Technical Reference Manual */ |
3408 | |
3409 | /* |
3410 | * In the following, the "--sync" comments are meant to denote |
3411 | * asynchronous boundaries for setting the registers as described in the |
3412 | * DAQ-STC mostly in the order also described in the DAQ-STC. |
3413 | */ |
3414 | |
3415 | struct ni_private *devpriv = dev->private; |
3416 | |
3417 | ni_release_ao_mite_channel(dev); |
3418 | |
3419 | /* --sync (reset AO) */ |
3420 | if (devpriv->is_m_series) |
3421 | /* following example in mhddk for m-series */ |
3422 | ni_stc_writew(dev, NISTC_RESET_AO, NISTC_RESET_REG); |
3423 | |
3424 | /*--sync (start config) */ |
3425 | ni_stc_writew(dev, NISTC_RESET_AO_CFG_START, NISTC_RESET_REG); |
3426 | |
3427 | /*--sync (Disarm) */ |
3428 | ni_stc_writew(dev, NISTC_AO_CMD1_DISARM, NISTC_AO_CMD1_REG); |
3429 | |
3430 | /* |
3431 | * --sync |
3432 | * (clear bunch of registers--mseries mhddk examples do not include |
3433 | * this) |
3434 | */ |
3435 | devpriv->ao_cmd1 = 0; |
3436 | devpriv->ao_cmd2 = 0; |
3437 | devpriv->ao_mode1 = 0; |
3438 | devpriv->ao_mode2 = 0; |
3439 | if (devpriv->is_m_series) |
3440 | devpriv->ao_mode3 = NISTC_AO_MODE3_LAST_GATE_DISABLE; |
3441 | else |
3442 | devpriv->ao_mode3 = 0; |
3443 | |
3444 | ni_stc_writew(dev, data: 0, NISTC_AO_PERSONAL_REG); |
3445 | ni_stc_writew(dev, data: 0, NISTC_AO_CMD1_REG); |
3446 | ni_stc_writew(dev, data: 0, NISTC_AO_CMD2_REG); |
3447 | ni_stc_writew(dev, data: 0, NISTC_AO_MODE1_REG); |
3448 | ni_stc_writew(dev, data: 0, NISTC_AO_MODE2_REG); |
3449 | ni_stc_writew(dev, data: 0, NISTC_AO_OUT_CTRL_REG); |
3450 | ni_stc_writew(dev, data: devpriv->ao_mode3, NISTC_AO_MODE3_REG); |
3451 | ni_stc_writew(dev, data: 0, NISTC_AO_START_SEL_REG); |
3452 | ni_stc_writew(dev, data: 0, NISTC_AO_TRIG_SEL_REG); |
3453 | |
3454 | /*--sync (disable interrupts) */ |
3455 | ni_set_bits(dev, NISTC_INTB_ENA_REG, bits: ~0, value: 0); |
3456 | |
3457 | /*--sync (ack) */ |
3458 | ni_stc_writew(dev, NISTC_AO_PERSONAL_BC_SRC_SEL, NISTC_AO_PERSONAL_REG); |
3459 | ni_stc_writew(dev, NISTC_INTB_ACK_AO_ALL, NISTC_INTB_ACK_REG); |
3460 | |
3461 | /*--not in DAQ-STC. which doc? */ |
3462 | if (devpriv->is_6xxx) { |
3463 | ni_ao_win_outw(dev, data: (1u << s->n_chan) - 1u, |
3464 | NI671X_AO_IMMEDIATE_REG); |
3465 | ni_ao_win_outw(dev, NI611X_AO_MISC_CLEAR_WG, |
3466 | NI611X_AO_MISC_REG); |
3467 | } |
3468 | ni_stc_writew(dev, NISTC_RESET_AO_CFG_END, NISTC_RESET_REG); |
3469 | /*--end */ |
3470 | |
3471 | return 0; |
3472 | } |
3473 | |
3474 | /* digital io */ |
3475 | |
3476 | static int ni_dio_insn_config(struct comedi_device *dev, |
3477 | struct comedi_subdevice *s, |
3478 | struct comedi_insn *insn, |
3479 | unsigned int *data) |
3480 | { |
3481 | struct ni_private *devpriv = dev->private; |
3482 | int ret; |
3483 | |
3484 | ret = comedi_dio_insn_config(dev, s, insn, data, mask: 0); |
3485 | if (ret) |
3486 | return ret; |
3487 | |
3488 | devpriv->dio_control &= ~NISTC_DIO_CTRL_DIR_MASK; |
3489 | devpriv->dio_control |= NISTC_DIO_CTRL_DIR(s->io_bits); |
3490 | ni_stc_writew(dev, data: devpriv->dio_control, NISTC_DIO_CTRL_REG); |
3491 | |
3492 | return insn->n; |
3493 | } |
3494 | |
3495 | static int ni_dio_insn_bits(struct comedi_device *dev, |
3496 | struct comedi_subdevice *s, |
3497 | struct comedi_insn *insn, |
3498 | unsigned int *data) |
3499 | { |
3500 | struct ni_private *devpriv = dev->private; |
3501 | |
3502 | /* Make sure we're not using the serial part of the dio */ |
3503 | if ((data[0] & (NISTC_DIO_SDIN | NISTC_DIO_SDOUT)) && |
3504 | devpriv->serial_interval_ns) |
3505 | return -EBUSY; |
3506 | |
3507 | if (comedi_dio_update_state(s, data)) { |
3508 | devpriv->dio_output &= ~NISTC_DIO_OUT_PARALLEL_MASK; |
3509 | devpriv->dio_output |= NISTC_DIO_OUT_PARALLEL(s->state); |
3510 | ni_stc_writew(dev, data: devpriv->dio_output, NISTC_DIO_OUT_REG); |
3511 | } |
3512 | |
3513 | data[1] = ni_stc_readw(dev, NISTC_DIO_IN_REG); |
3514 | |
3515 | return insn->n; |
3516 | } |
3517 | |
3518 | #ifdef PCIDMA |
3519 | static int ni_m_series_dio_insn_config(struct comedi_device *dev, |
3520 | struct comedi_subdevice *s, |
3521 | struct comedi_insn *insn, |
3522 | unsigned int *data) |
3523 | { |
3524 | int ret; |
3525 | |
3526 | if (data[0] == INSN_CONFIG_GET_CMD_TIMING_CONSTRAINTS) { |
3527 | const struct ni_board_struct *board = dev->board_ptr; |
3528 | |
3529 | /* we don't care about actual channels */ |
3530 | data[1] = board->dio_speed; |
3531 | data[2] = 0; |
3532 | return 0; |
3533 | } |
3534 | |
3535 | ret = comedi_dio_insn_config(dev, s, insn, data, 0); |
3536 | if (ret) |
3537 | return ret; |
3538 | |
3539 | ni_writel(dev, s->io_bits, NI_M_DIO_DIR_REG); |
3540 | |
3541 | return insn->n; |
3542 | } |
3543 | |
3544 | static int ni_m_series_dio_insn_bits(struct comedi_device *dev, |
3545 | struct comedi_subdevice *s, |
3546 | struct comedi_insn *insn, |
3547 | unsigned int *data) |
3548 | { |
3549 | if (comedi_dio_update_state(s, data)) |
3550 | ni_writel(dev, s->state, NI_M_DIO_REG); |
3551 | |
3552 | data[1] = ni_readl(dev, NI_M_DIO_REG); |
3553 | |
3554 | return insn->n; |
3555 | } |
3556 | |
3557 | static int ni_cdio_check_chanlist(struct comedi_device *dev, |
3558 | struct comedi_subdevice *s, |
3559 | struct comedi_cmd *cmd) |
3560 | { |
3561 | int i; |
3562 | |
3563 | for (i = 0; i < cmd->chanlist_len; ++i) { |
3564 | unsigned int chan = CR_CHAN(cmd->chanlist[i]); |
3565 | |
3566 | if (chan != i) |
3567 | return -EINVAL; |
3568 | } |
3569 | |
3570 | return 0; |
3571 | } |
3572 | |
3573 | static int ni_cdio_cmdtest(struct comedi_device *dev, |
3574 | struct comedi_subdevice *s, struct comedi_cmd *cmd) |
3575 | { |
3576 | struct ni_private *devpriv = dev->private; |
3577 | unsigned int bytes_per_scan; |
3578 | int err = 0; |
3579 | |
3580 | /* Step 1 : check if triggers are trivially valid */ |
3581 | |
3582 | err |= comedi_check_trigger_src(&cmd->start_src, TRIG_INT); |
3583 | err |= comedi_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT); |
3584 | err |= comedi_check_trigger_src(&cmd->convert_src, TRIG_NOW); |
3585 | err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); |
3586 | err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_NONE); |
3587 | |
3588 | if (err) |
3589 | return 1; |
3590 | |
3591 | /* Step 2a : make sure trigger sources are unique */ |
3592 | /* Step 2b : and mutually compatible */ |
3593 | |
3594 | /* Step 3: check if arguments are trivially valid */ |
3595 | |
3596 | err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0); |
3597 | |
3598 | /* |
3599 | * Although NI_D[IO]_SampleClock are the same, perhaps we should still, |
3600 | * for completeness, test whether the cmd is output or input? |
3601 | */ |
3602 | err |= ni_check_trigger_arg(CR_CHAN(cmd->scan_begin_arg), |
3603 | NI_DO_SampleClock, |
3604 | &devpriv->routing_tables); |
3605 | if (CR_RANGE(cmd->scan_begin_arg) != 0 || |
3606 | CR_AREF(cmd->scan_begin_arg) != 0) |
3607 | err |= -EINVAL; |
3608 | |
3609 | err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0); |
3610 | err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg, |
3611 | cmd->chanlist_len); |
3612 | bytes_per_scan = comedi_bytes_per_scan_cmd(s, cmd); |
3613 | if (bytes_per_scan) { |
3614 | err |= comedi_check_trigger_arg_max(&cmd->stop_arg, |
3615 | s->async->prealloc_bufsz / |
3616 | bytes_per_scan); |
3617 | } |
3618 | |
3619 | if (err) |
3620 | return 3; |
3621 | |
3622 | /* Step 4: fix up any arguments */ |
3623 | |
3624 | /* Step 5: check channel list if it exists */ |
3625 | |
3626 | if (cmd->chanlist && cmd->chanlist_len > 0) |
3627 | err |= ni_cdio_check_chanlist(dev, s, cmd); |
3628 | |
3629 | if (err) |
3630 | return 5; |
3631 | |
3632 | return 0; |
3633 | } |
3634 | |
3635 | static int ni_cdo_inttrig(struct comedi_device *dev, |
3636 | struct comedi_subdevice *s, |
3637 | unsigned int trig_num) |
3638 | { |
3639 | struct comedi_cmd *cmd = &s->async->cmd; |
3640 | const unsigned int timeout = 1000; |
3641 | int retval = 0; |
3642 | unsigned int i; |
3643 | struct ni_private *devpriv = dev->private; |
3644 | unsigned long flags; |
3645 | |
3646 | if (trig_num != cmd->start_arg) |
3647 | return -EINVAL; |
3648 | |
3649 | s->async->inttrig = NULL; |
3650 | |
3651 | /* read alloc the entire buffer */ |
3652 | comedi_buf_read_alloc(s, s->async->prealloc_bufsz); |
3653 | |
3654 | spin_lock_irqsave(&devpriv->mite_channel_lock, flags); |
3655 | if (devpriv->cdo_mite_chan) { |
3656 | mite_prep_dma(devpriv->cdo_mite_chan, 32, 32); |
3657 | mite_dma_arm(devpriv->cdo_mite_chan); |
3658 | } else { |
3659 | dev_err(dev->class_dev, "BUG: no cdo mite channel?\n" ); |
3660 | retval = -EIO; |
3661 | } |
3662 | spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); |
3663 | if (retval < 0) |
3664 | return retval; |
3665 | |
3666 | /* |
3667 | * XXX not sure what interrupt C group does |
3668 | * wait for dma to fill output fifo |
3669 | * ni_writeb(dev, NI_M_INTC_ENA, NI_M_INTC_ENA_REG); |
3670 | */ |
3671 | for (i = 0; i < timeout; ++i) { |
3672 | if (ni_readl(dev, NI_M_CDIO_STATUS_REG) & |
3673 | NI_M_CDIO_STATUS_CDO_FIFO_FULL) |
3674 | break; |
3675 | usleep_range(10, 100); |
3676 | } |
3677 | if (i == timeout) { |
3678 | dev_err(dev->class_dev, "dma failed to fill cdo fifo!\n" ); |
3679 | s->cancel(dev, s); |
3680 | return -EIO; |
3681 | } |
3682 | ni_writel(dev, NI_M_CDO_CMD_ARM | |
3683 | NI_M_CDO_CMD_ERR_INT_ENA_SET | |
3684 | NI_M_CDO_CMD_F_E_INT_ENA_SET, |
3685 | NI_M_CDIO_CMD_REG); |
3686 | return retval; |
3687 | } |
3688 | |
3689 | static int ni_cdio_cmd(struct comedi_device *dev, struct comedi_subdevice *s) |
3690 | { |
3691 | struct ni_private *devpriv = dev->private; |
3692 | const struct comedi_cmd *cmd = &s->async->cmd; |
3693 | unsigned int cdo_mode_bits; |
3694 | int retval; |
3695 | |
3696 | ni_writel(dev, NI_M_CDO_CMD_RESET, NI_M_CDIO_CMD_REG); |
3697 | /* |
3698 | * Although NI_D[IO]_SampleClock are the same, perhaps we should still, |
3699 | * for completeness, test whether the cmd is output or input(?) |
3700 | */ |
3701 | cdo_mode_bits = NI_M_CDO_MODE_FIFO_MODE | |
3702 | NI_M_CDO_MODE_HALT_ON_ERROR | |
3703 | NI_M_CDO_MODE_SAMPLE_SRC( |
3704 | ni_get_reg_value( |
3705 | CR_CHAN(cmd->scan_begin_arg), |
3706 | NI_DO_SampleClock, |
3707 | &devpriv->routing_tables)); |
3708 | if (cmd->scan_begin_arg & CR_INVERT) |
3709 | cdo_mode_bits |= NI_M_CDO_MODE_POLARITY; |
3710 | ni_writel(dev, cdo_mode_bits, NI_M_CDO_MODE_REG); |
3711 | if (s->io_bits) { |
3712 | ni_writel(dev, s->state, NI_M_CDO_FIFO_DATA_REG); |
3713 | ni_writel(dev, NI_M_CDO_CMD_SW_UPDATE, NI_M_CDIO_CMD_REG); |
3714 | ni_writel(dev, s->io_bits, NI_M_CDO_MASK_ENA_REG); |
3715 | } else { |
3716 | dev_err(dev->class_dev, |
3717 | "attempted to run digital output command with no lines configured as outputs\n" ); |
3718 | return -EIO; |
3719 | } |
3720 | retval = ni_request_cdo_mite_channel(dev); |
3721 | if (retval < 0) |
3722 | return retval; |
3723 | |
3724 | ni_cmd_set_mite_transfer(devpriv->cdo_mite_ring, s, cmd, |
3725 | s->async->prealloc_bufsz / |
3726 | comedi_bytes_per_scan(s)); |
3727 | |
3728 | s->async->inttrig = ni_cdo_inttrig; |
3729 | |
3730 | return 0; |
3731 | } |
3732 | |
3733 | static int ni_cdio_cancel(struct comedi_device *dev, struct comedi_subdevice *s) |
3734 | { |
3735 | ni_writel(dev, NI_M_CDO_CMD_DISARM | |
3736 | NI_M_CDO_CMD_ERR_INT_ENA_CLR | |
3737 | NI_M_CDO_CMD_F_E_INT_ENA_CLR | |
3738 | NI_M_CDO_CMD_F_REQ_INT_ENA_CLR, |
3739 | NI_M_CDIO_CMD_REG); |
3740 | /* |
3741 | * XXX not sure what interrupt C group does |
3742 | * ni_writeb(dev, 0, NI_M_INTC_ENA_REG); |
3743 | */ |
3744 | ni_writel(dev, 0, NI_M_CDO_MASK_ENA_REG); |
3745 | ni_release_cdo_mite_channel(dev); |
3746 | return 0; |
3747 | } |
3748 | |
3749 | static void handle_cdio_interrupt(struct comedi_device *dev) |
3750 | { |
3751 | struct ni_private *devpriv = dev->private; |
3752 | unsigned int cdio_status; |
3753 | struct comedi_subdevice *s = &dev->subdevices[NI_DIO_SUBDEV]; |
3754 | unsigned long flags; |
3755 | |
3756 | spin_lock_irqsave(&devpriv->mite_channel_lock, flags); |
3757 | if (devpriv->cdo_mite_chan) |
3758 | mite_ack_linkc(devpriv->cdo_mite_chan, s, true); |
3759 | spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags); |
3760 | |
3761 | cdio_status = ni_readl(dev, NI_M_CDIO_STATUS_REG); |
3762 | if (cdio_status & NI_M_CDIO_STATUS_CDO_ERROR) { |
3763 | /* XXX just guessing this is needed and does something useful */ |
3764 | ni_writel(dev, NI_M_CDO_CMD_ERR_INT_CONFIRM, |
3765 | NI_M_CDIO_CMD_REG); |
3766 | s->async->events |= COMEDI_CB_OVERFLOW; |
3767 | } |
3768 | if (cdio_status & NI_M_CDIO_STATUS_CDO_FIFO_EMPTY) { |
3769 | ni_writel(dev, NI_M_CDO_CMD_F_E_INT_ENA_CLR, |
3770 | NI_M_CDIO_CMD_REG); |
3771 | /* s->async->events |= COMEDI_CB_EOA; */ |
3772 | } |
3773 | comedi_handle_events(dev, s); |
3774 | } |
3775 | #endif /* PCIDMA */ |
3776 | |
3777 | static int ni_serial_hw_readwrite8(struct comedi_device *dev, |
3778 | struct comedi_subdevice *s, |
3779 | unsigned char data_out, |
3780 | unsigned char *data_in) |
3781 | { |
3782 | struct ni_private *devpriv = dev->private; |
3783 | unsigned int status1; |
3784 | int err = 0, count = 20; |
3785 | |
3786 | devpriv->dio_output &= ~NISTC_DIO_OUT_SERIAL_MASK; |
3787 | devpriv->dio_output |= NISTC_DIO_OUT_SERIAL(data_out); |
3788 | ni_stc_writew(dev, data: devpriv->dio_output, NISTC_DIO_OUT_REG); |
3789 | |
3790 | status1 = ni_stc_readw(dev, NISTC_STATUS1_REG); |
3791 | if (status1 & NISTC_STATUS1_SERIO_IN_PROG) { |
3792 | err = -EBUSY; |
3793 | goto error; |
3794 | } |
3795 | |
3796 | devpriv->dio_control |= NISTC_DIO_CTRL_HW_SER_START; |
3797 | ni_stc_writew(dev, data: devpriv->dio_control, NISTC_DIO_CTRL_REG); |
3798 | devpriv->dio_control &= ~NISTC_DIO_CTRL_HW_SER_START; |
3799 | |
3800 | /* Wait until STC says we're done, but don't loop infinitely. */ |
3801 | while ((status1 = ni_stc_readw(dev, NISTC_STATUS1_REG)) & |
3802 | NISTC_STATUS1_SERIO_IN_PROG) { |
3803 | /* Delay one bit per loop */ |
3804 | udelay((devpriv->serial_interval_ns + 999) / 1000); |
3805 | if (--count < 0) { |
3806 | dev_err(dev->class_dev, |
3807 | "SPI serial I/O didn't finish in time!\n" ); |
3808 | err = -ETIME; |
3809 | goto error; |
3810 | } |
3811 | } |
3812 | |
3813 | /* |
3814 | * Delay for last bit. This delay is absolutely necessary, because |
3815 | * NISTC_STATUS1_SERIO_IN_PROG goes high one bit too early. |
3816 | */ |
3817 | udelay((devpriv->serial_interval_ns + 999) / 1000); |
3818 | |
3819 | if (data_in) |
3820 | *data_in = ni_stc_readw(dev, NISTC_DIO_SERIAL_IN_REG); |
3821 | |
3822 | error: |
3823 | ni_stc_writew(dev, data: devpriv->dio_control, NISTC_DIO_CTRL_REG); |
3824 | |
3825 | return err; |
3826 | } |
3827 | |
3828 | static int ni_serial_sw_readwrite8(struct comedi_device *dev, |
3829 | struct comedi_subdevice *s, |
3830 | unsigned char data_out, |
3831 | unsigned char *data_in) |
3832 | { |
3833 | struct ni_private *devpriv = dev->private; |
3834 | unsigned char mask, input = 0; |
3835 | |
3836 | /* Wait for one bit before transfer */ |
3837 | udelay((devpriv->serial_interval_ns + 999) / 1000); |
3838 | |
3839 | for (mask = 0x80; mask; mask >>= 1) { |
3840 | /* |
3841 | * Output current bit; note that we cannot touch s->state |
3842 | * because it is a per-subdevice field, and serial is |
3843 | * a separate subdevice from DIO. |
3844 | */ |
3845 | devpriv->dio_output &= ~NISTC_DIO_SDOUT; |
3846 | if (data_out & mask) |
3847 | devpriv->dio_output |= NISTC_DIO_SDOUT; |
3848 | ni_stc_writew(dev, data: devpriv->dio_output, NISTC_DIO_OUT_REG); |
3849 | |
3850 | /* |
3851 | * Assert SDCLK (active low, inverted), wait for half of |
3852 | * the delay, deassert SDCLK, and wait for the other half. |
3853 | */ |
3854 | devpriv->dio_control |= NISTC_DIO_SDCLK; |
3855 | ni_stc_writew(dev, data: devpriv->dio_control, NISTC_DIO_CTRL_REG); |
3856 | |
3857 | udelay((devpriv->serial_interval_ns + 999) / 2000); |
3858 | |
3859 | devpriv->dio_control &= ~NISTC_DIO_SDCLK; |
3860 | ni_stc_writew(dev, data: devpriv->dio_control, NISTC_DIO_CTRL_REG); |
3861 | |
3862 | udelay((devpriv->serial_interval_ns + 999) / 2000); |
3863 | |
3864 | /* Input current bit */ |
3865 | if (ni_stc_readw(dev, NISTC_DIO_IN_REG) & NISTC_DIO_SDIN) |
3866 | input |= mask; |
3867 | } |
3868 | |
3869 | if (data_in) |
3870 | *data_in = input; |
3871 | |
3872 | return 0; |
3873 | } |
3874 | |
3875 | static int ni_serial_insn_config(struct comedi_device *dev, |
3876 | struct comedi_subdevice *s, |
3877 | struct comedi_insn *insn, |
3878 | unsigned int *data) |
3879 | { |
3880 | struct ni_private *devpriv = dev->private; |
3881 | unsigned int clk_fout = devpriv->clock_and_fout; |
3882 | int err = insn->n; |
3883 | unsigned char byte_out, byte_in = 0; |
3884 | |
3885 | if (insn->n != 2) |
3886 | return -EINVAL; |
3887 | |
3888 | switch (data[0]) { |
3889 | case INSN_CONFIG_SERIAL_CLOCK: |
3890 | devpriv->serial_hw_mode = 1; |
3891 | devpriv->dio_control |= NISTC_DIO_CTRL_HW_SER_ENA; |
3892 | |
3893 | if (data[1] == SERIAL_DISABLED) { |
3894 | devpriv->serial_hw_mode = 0; |
3895 | devpriv->dio_control &= ~(NISTC_DIO_CTRL_HW_SER_ENA | |
3896 | NISTC_DIO_SDCLK); |
3897 | data[1] = SERIAL_DISABLED; |
3898 | devpriv->serial_interval_ns = data[1]; |
3899 | } else if (data[1] <= SERIAL_600NS) { |
3900 | /* |
3901 | * Warning: this clock speed is too fast to reliably |
3902 | * control SCXI. |
3903 | */ |
3904 | devpriv->dio_control &= ~NISTC_DIO_CTRL_HW_SER_TIMEBASE; |
3905 | clk_fout |= NISTC_CLK_FOUT_SLOW_TIMEBASE; |
3906 | clk_fout &= ~NISTC_CLK_FOUT_DIO_SER_OUT_DIV2; |
3907 | data[1] = SERIAL_600NS; |
3908 | devpriv->serial_interval_ns = data[1]; |
3909 | } else if (data[1] <= SERIAL_1_2US) { |
3910 | devpriv->dio_control &= ~NISTC_DIO_CTRL_HW_SER_TIMEBASE; |
3911 | clk_fout |= NISTC_CLK_FOUT_SLOW_TIMEBASE | |
3912 | NISTC_CLK_FOUT_DIO_SER_OUT_DIV2; |
3913 | data[1] = SERIAL_1_2US; |
3914 | devpriv->serial_interval_ns = data[1]; |
3915 | } else if (data[1] <= SERIAL_10US) { |
3916 | devpriv->dio_control |= NISTC_DIO_CTRL_HW_SER_TIMEBASE; |
3917 | clk_fout |= NISTC_CLK_FOUT_SLOW_TIMEBASE | |
3918 | NISTC_CLK_FOUT_DIO_SER_OUT_DIV2; |
3919 | /* |
3920 | * Note: NISTC_CLK_FOUT_DIO_SER_OUT_DIV2 only affects |
3921 | * 600ns/1.2us. If you turn divide_by_2 off with the |
3922 | * slow clock, you will still get 10us, except then |
3923 | * all your delays are wrong. |
3924 | */ |
3925 | data[1] = SERIAL_10US; |
3926 | devpriv->serial_interval_ns = data[1]; |
3927 | } else { |
3928 | devpriv->dio_control &= ~(NISTC_DIO_CTRL_HW_SER_ENA | |
3929 | NISTC_DIO_SDCLK); |
3930 | devpriv->serial_hw_mode = 0; |
3931 | data[1] = (data[1] / 1000) * 1000; |
3932 | devpriv->serial_interval_ns = data[1]; |
3933 | } |
3934 | devpriv->clock_and_fout = clk_fout; |
3935 | |
3936 | ni_stc_writew(dev, data: devpriv->dio_control, NISTC_DIO_CTRL_REG); |
3937 | ni_stc_writew(dev, data: devpriv->clock_and_fout, NISTC_CLK_FOUT_REG); |
3938 | return 1; |
3939 | |
3940 | case INSN_CONFIG_BIDIRECTIONAL_DATA: |
3941 | |
3942 | if (devpriv->serial_interval_ns == 0) |
3943 | return -EINVAL; |
3944 | |
3945 | byte_out = data[1] & 0xFF; |
3946 | |
3947 | if (devpriv->serial_hw_mode) { |
3948 | err = ni_serial_hw_readwrite8(dev, s, data_out: byte_out, |
3949 | data_in: &byte_in); |
3950 | } else if (devpriv->serial_interval_ns > 0) { |
3951 | err = ni_serial_sw_readwrite8(dev, s, data_out: byte_out, |
3952 | data_in: &byte_in); |
3953 | } else { |
3954 | dev_err(dev->class_dev, "serial disabled!\n" ); |
3955 | return -EINVAL; |
3956 | } |
3957 | if (err < 0) |
3958 | return err; |
3959 | data[1] = byte_in & 0xFF; |
3960 | return insn->n; |
3961 | |
3962 | break; |
3963 | default: |
3964 | return -EINVAL; |
3965 | } |
3966 | } |
3967 | |
3968 | static void init_ao_67xx(struct comedi_device *dev, struct comedi_subdevice *s) |
3969 | { |
3970 | int i; |
3971 | |
3972 | for (i = 0; i < s->n_chan; i++) { |
3973 | ni_ao_win_outw(dev, NI_E_AO_DACSEL(i) | 0x0, |
3974 | NI67XX_AO_CFG2_REG); |
3975 | } |
3976 | ni_ao_win_outw(dev, data: 0x0, NI67XX_AO_SP_UPDATES_REG); |
3977 | } |
3978 | |
3979 | static const struct mio_regmap ni_gpct_to_stc_regmap[] = { |
3980 | [NITIO_G0_AUTO_INC] = { NISTC_G0_AUTOINC_REG, 2 }, |
3981 | [NITIO_G1_AUTO_INC] = { NISTC_G1_AUTOINC_REG, .size: 2 }, |
3982 | [NITIO_G0_CMD] = { NISTC_G0_CMD_REG, .size: 2 }, |
3983 | [NITIO_G1_CMD] = { NISTC_G1_CMD_REG, .size: 2 }, |
3984 | [NITIO_G0_HW_SAVE] = { NISTC_G0_HW_SAVE_REG, .size: 4 }, |
3985 | [NITIO_G1_HW_SAVE] = { NISTC_G1_HW_SAVE_REG, .size: 4 }, |
3986 | [NITIO_G0_SW_SAVE] = { NISTC_G0_SAVE_REG, .size: 4 }, |
3987 | [NITIO_G1_SW_SAVE] = { NISTC_G1_SAVE_REG, .size: 4 }, |
3988 | [NITIO_G0_MODE] = { NISTC_G0_MODE_REG, .size: 2 }, |
3989 | [NITIO_G1_MODE] = { NISTC_G1_MODE_REG, .size: 2 }, |
3990 | [NITIO_G0_LOADA] = { NISTC_G0_LOADA_REG, .size: 4 }, |
3991 | [NITIO_G1_LOADA] = { NISTC_G1_LOADA_REG, .size: 4 }, |
3992 | [NITIO_G0_LOADB] = { NISTC_G0_LOADB_REG, .size: 4 }, |
3993 | [NITIO_G1_LOADB] = { NISTC_G1_LOADB_REG, .size: 4 }, |
3994 | [NITIO_G0_INPUT_SEL] = { NISTC_G0_INPUT_SEL_REG, .size: 2 }, |
3995 | [NITIO_G1_INPUT_SEL] = { NISTC_G1_INPUT_SEL_REG, .size: 2 }, |
3996 | [NITIO_G0_CNT_MODE] = { .mio_reg: 0x1b0, .size: 2 }, /* M-Series only */ |
3997 | [NITIO_G1_CNT_MODE] = { .mio_reg: 0x1b2, .size: 2 }, /* M-Series only */ |
3998 | [NITIO_G0_GATE2] = { .mio_reg: 0x1b4, .size: 2 }, /* M-Series only */ |
3999 | [NITIO_G1_GATE2] = { .mio_reg: 0x1b6, .size: 2 }, /* M-Series only */ |
4000 | [NITIO_G01_STATUS] = { NISTC_G01_STATUS_REG, .size: 2 }, |
4001 | [NITIO_G01_RESET] = { NISTC_RESET_REG, .size: 2 }, |
4002 | [NITIO_G01_STATUS1] = { NISTC_STATUS1_REG, .size: 2 }, |
4003 | [NITIO_G01_STATUS2] = { NISTC_STATUS2_REG, .size: 2 }, |
4004 | [NITIO_G0_DMA_CFG] = { .mio_reg: 0x1b8, .size: 2 }, /* M-Series only */ |
4005 | [NITIO_G1_DMA_CFG] = { .mio_reg: 0x1ba, .size: 2 }, /* M-Series only */ |
4006 | [NITIO_G0_DMA_STATUS] = { .mio_reg: 0x1b8, .size: 2 }, /* M-Series only */ |
4007 | [NITIO_G1_DMA_STATUS] = { .mio_reg: 0x1ba, .size: 2 }, /* M-Series only */ |
4008 | [NITIO_G0_ABZ] = { .mio_reg: 0x1c0, .size: 2 }, /* M-Series only */ |
4009 | [NITIO_G1_ABZ] = { .mio_reg: 0x1c2, .size: 2 }, /* M-Series only */ |
4010 | [NITIO_G0_INT_ACK] = { NISTC_INTA_ACK_REG, .size: 2 }, |
4011 | [NITIO_G1_INT_ACK] = { NISTC_INTB_ACK_REG, .size: 2 }, |
4012 | [NITIO_G0_STATUS] = { NISTC_AI_STATUS1_REG, .size: 2 }, |
4013 | [NITIO_G1_STATUS] = { NISTC_AO_STATUS1_REG, .size: 2 }, |
4014 | [NITIO_G0_INT_ENA] = { NISTC_INTA_ENA_REG, .size: 2 }, |
4015 | [NITIO_G1_INT_ENA] = { NISTC_INTB_ENA_REG, .size: 2 }, |
4016 | }; |
4017 | |
4018 | static unsigned int ni_gpct_to_stc_register(struct comedi_device *dev, |
4019 | enum ni_gpct_register reg) |
4020 | { |
4021 | const struct mio_regmap *regmap; |
4022 | |
4023 | if (reg < ARRAY_SIZE(ni_gpct_to_stc_regmap)) { |
4024 | regmap = &ni_gpct_to_stc_regmap[reg]; |
4025 | } else { |
4026 | dev_warn(dev->class_dev, "%s: unhandled register=0x%x\n" , |
4027 | __func__, reg); |
4028 | return 0; |
4029 | } |
4030 | |
4031 | return regmap->mio_reg; |
4032 | } |
4033 | |
4034 | static void ni_gpct_write_register(struct ni_gpct *counter, unsigned int bits, |
4035 | enum ni_gpct_register reg) |
4036 | { |
4037 | struct comedi_device *dev = counter->counter_dev->dev; |
4038 | unsigned int stc_register = ni_gpct_to_stc_register(dev, reg); |
4039 | |
4040 | if (stc_register == 0) |
4041 | return; |
4042 | |
4043 | switch (reg) { |
4044 | /* m-series only registers */ |
4045 | case NITIO_G0_CNT_MODE: |
4046 | case NITIO_G1_CNT_MODE: |
4047 | case NITIO_G0_GATE2: |
4048 | case NITIO_G1_GATE2: |
4049 | case NITIO_G0_DMA_CFG: |
4050 | case NITIO_G1_DMA_CFG: |
4051 | case NITIO_G0_ABZ: |
4052 | case NITIO_G1_ABZ: |
4053 | ni_writew(dev, data: bits, reg: stc_register); |
4054 | break; |
4055 | |
4056 | /* 32 bit registers */ |
4057 | case NITIO_G0_LOADA: |
4058 | case NITIO_G1_LOADA: |
4059 | case NITIO_G0_LOADB: |
4060 | case NITIO_G1_LOADB: |
4061 | ni_stc_writel(dev, data: bits, reg: stc_register); |
4062 | break; |
4063 | |
4064 | /* 16 bit registers */ |
4065 | case NITIO_G0_INT_ENA: |
4066 | ni_set_bitfield(dev, reg: stc_register, |
4067 | NISTC_INTA_ENA_G0_GATE | NISTC_INTA_ENA_G0_TC, |
4068 | bit_values: bits); |
4069 | break; |
4070 | case NITIO_G1_INT_ENA: |
4071 | ni_set_bitfield(dev, reg: stc_register, |
4072 | NISTC_INTB_ENA_G1_GATE | NISTC_INTB_ENA_G1_TC, |
4073 | bit_values: bits); |
4074 | break; |
4075 | default: |
4076 | ni_stc_writew(dev, data: bits, reg: stc_register); |
4077 | } |
4078 | } |
4079 | |
4080 | static unsigned int ni_gpct_read_register(struct ni_gpct *counter, |
4081 | enum ni_gpct_register reg) |
4082 | { |
4083 | struct comedi_device *dev = counter->counter_dev->dev; |
4084 | unsigned int stc_register = ni_gpct_to_stc_register(dev, reg); |
4085 | |
4086 | if (stc_register == 0) |
4087 | return 0; |
4088 | |
4089 | switch (reg) { |
4090 | /* m-series only registers */ |
4091 | case NITIO_G0_DMA_STATUS: |
4092 | case NITIO_G1_DMA_STATUS: |
4093 | return ni_readw(dev, reg: stc_register); |
4094 | |
4095 | /* 32 bit registers */ |
4096 | case NITIO_G0_HW_SAVE: |
4097 | case NITIO_G1_HW_SAVE: |
4098 | case NITIO_G0_SW_SAVE: |
4099 | case NITIO_G1_SW_SAVE: |
4100 | return ni_stc_readl(dev, reg: stc_register); |
4101 | |
4102 | /* 16 bit registers */ |
4103 | default: |
4104 | return ni_stc_readw(dev, reg: stc_register); |
4105 | } |
4106 | } |
4107 | |
4108 | static int ni_freq_out_insn_read(struct comedi_device *dev, |
4109 | struct comedi_subdevice *s, |
4110 | struct comedi_insn *insn, |
4111 | unsigned int *data) |
4112 | { |
4113 | struct ni_private *devpriv = dev->private; |
4114 | unsigned int val = NISTC_CLK_FOUT_TO_DIVIDER(devpriv->clock_and_fout); |
4115 | int i; |
4116 | |
4117 | for (i = 0; i < insn->n; i++) |
4118 | data[i] = val; |
4119 | |
4120 | return insn->n; |
4121 | } |
4122 | |
4123 | static int ni_freq_out_insn_write(struct comedi_device *dev, |
4124 | struct comedi_subdevice *s, |
4125 | struct comedi_insn *insn, |
4126 | unsigned int *data) |
4127 | { |
4128 | struct ni_private *devpriv = dev->private; |
4129 | |
4130 | if (insn->n) { |
4131 | unsigned int val = data[insn->n - 1]; |
4132 | |
4133 | devpriv->clock_and_fout &= ~NISTC_CLK_FOUT_ENA; |
4134 | ni_stc_writew(dev, data: devpriv->clock_and_fout, NISTC_CLK_FOUT_REG); |
4135 | devpriv->clock_and_fout &= ~NISTC_CLK_FOUT_DIVIDER_MASK; |
4136 | |
4137 | /* use the last data value to set the fout divider */ |
4138 | devpriv->clock_and_fout |= NISTC_CLK_FOUT_DIVIDER(val); |
4139 | |
4140 | devpriv->clock_and_fout |= NISTC_CLK_FOUT_ENA; |
4141 | ni_stc_writew(dev, data: devpriv->clock_and_fout, NISTC_CLK_FOUT_REG); |
4142 | } |
4143 | return insn->n; |
4144 | } |
4145 | |
4146 | static int ni_freq_out_insn_config(struct comedi_device *dev, |
4147 | struct comedi_subdevice *s, |
4148 | struct comedi_insn *insn, |
4149 | unsigned int *data) |
4150 | { |
4151 | struct ni_private *devpriv = dev->private; |
4152 | |
4153 | switch (data[0]) { |
4154 | case INSN_CONFIG_SET_CLOCK_SRC: |
4155 | switch (data[1]) { |
4156 | case NI_FREQ_OUT_TIMEBASE_1_DIV_2_CLOCK_SRC: |
4157 | devpriv->clock_and_fout &= ~NISTC_CLK_FOUT_TIMEBASE_SEL; |
4158 | break; |
4159 | case NI_FREQ_OUT_TIMEBASE_2_CLOCK_SRC: |
4160 | devpriv->clock_and_fout |= NISTC_CLK_FOUT_TIMEBASE_SEL; |
4161 | break; |
4162 | default: |
4163 | return -EINVAL; |
4164 | } |
4165 | ni_stc_writew(dev, data: devpriv->clock_and_fout, NISTC_CLK_FOUT_REG); |
4166 | break; |
4167 | case INSN_CONFIG_GET_CLOCK_SRC: |
4168 | if (devpriv->clock_and_fout & NISTC_CLK_FOUT_TIMEBASE_SEL) { |
4169 | data[1] = NI_FREQ_OUT_TIMEBASE_2_CLOCK_SRC; |
4170 | data[2] = TIMEBASE_2_NS; |
4171 | } else { |
4172 | data[1] = NI_FREQ_OUT_TIMEBASE_1_DIV_2_CLOCK_SRC; |
4173 | data[2] = TIMEBASE_1_NS * 2; |
4174 | } |
4175 | break; |
4176 | default: |
4177 | return -EINVAL; |
4178 | } |
4179 | return insn->n; |
4180 | } |
4181 | |
4182 | static int ni_8255_callback(struct comedi_device *dev, |
4183 | int dir, int port, int data, unsigned long iobase) |
4184 | { |
4185 | if (dir) { |
4186 | ni_writeb(dev, data, reg: iobase + 2 * port); |
4187 | return 0; |
4188 | } |
4189 | |
4190 | return ni_readb(dev, reg: iobase + 2 * port); |
4191 | } |
4192 | |
4193 | static int ni_get_pwm_config(struct comedi_device *dev, unsigned int *data) |
4194 | { |
4195 | struct ni_private *devpriv = dev->private; |
4196 | |
4197 | data[1] = devpriv->pwm_up_count * devpriv->clock_ns; |
4198 | data[2] = devpriv->pwm_down_count * devpriv->clock_ns; |
4199 | return 3; |
4200 | } |
4201 | |
4202 | static int ni_m_series_pwm_config(struct comedi_device *dev, |
4203 | struct comedi_subdevice *s, |
4204 | struct comedi_insn *insn, |
4205 | unsigned int *data) |
4206 | { |
4207 | struct ni_private *devpriv = dev->private; |
4208 | unsigned int up_count, down_count; |
4209 | |
4210 | switch (data[0]) { |
4211 | case INSN_CONFIG_PWM_OUTPUT: |
4212 | switch (data[1]) { |
4213 | case CMDF_ROUND_NEAREST: |
4214 | up_count = DIV_ROUND_CLOSEST(data[2], |
4215 | devpriv->clock_ns); |
4216 | break; |
4217 | case CMDF_ROUND_DOWN: |
4218 | up_count = data[2] / devpriv->clock_ns; |
4219 | break; |
4220 | case CMDF_ROUND_UP: |
4221 | up_count = |
4222 | DIV_ROUND_UP(data[2], devpriv->clock_ns); |
4223 | break; |
4224 | default: |
4225 | return -EINVAL; |
4226 | } |
4227 | switch (data[3]) { |
4228 | case CMDF_ROUND_NEAREST: |
4229 | down_count = DIV_ROUND_CLOSEST(data[4], |
4230 | devpriv->clock_ns); |
4231 | break; |
4232 | case CMDF_ROUND_DOWN: |
4233 | down_count = data[4] / devpriv->clock_ns; |
4234 | break; |
4235 | case CMDF_ROUND_UP: |
4236 | down_count = |
4237 | DIV_ROUND_UP(data[4], devpriv->clock_ns); |
4238 | break; |
4239 | default: |
4240 | return -EINVAL; |
4241 | } |
4242 | if (up_count * devpriv->clock_ns != data[2] || |
4243 | down_count * devpriv->clock_ns != data[4]) { |
4244 | data[2] = up_count * devpriv->clock_ns; |
4245 | data[4] = down_count * devpriv->clock_ns; |
4246 | return -EAGAIN; |
4247 | } |
4248 | ni_writel(dev, NI_M_CAL_PWM_HIGH_TIME(up_count) | |
4249 | NI_M_CAL_PWM_LOW_TIME(down_count), |
4250 | NI_M_CAL_PWM_REG); |
4251 | devpriv->pwm_up_count = up_count; |
4252 | devpriv->pwm_down_count = down_count; |
4253 | return 5; |
4254 | case INSN_CONFIG_GET_PWM_OUTPUT: |
4255 | return ni_get_pwm_config(dev, data); |
4256 | default: |
4257 | return -EINVAL; |
4258 | } |
4259 | return 0; |
4260 | } |
4261 | |
4262 | static int ni_6143_pwm_config(struct comedi_device *dev, |
4263 | struct comedi_subdevice *s, |
4264 | struct comedi_insn *insn, |
4265 | unsigned int *data) |
4266 | { |
4267 | struct ni_private *devpriv = dev->private; |
4268 | unsigned int up_count, down_count; |
4269 | |
4270 | switch (data[0]) { |
4271 | case INSN_CONFIG_PWM_OUTPUT: |
4272 | switch (data[1]) { |
4273 | case CMDF_ROUND_NEAREST: |
4274 | up_count = DIV_ROUND_CLOSEST(data[2], |
4275 | devpriv->clock_ns); |
4276 | break; |
4277 | case CMDF_ROUND_DOWN: |
4278 | up_count = data[2] / devpriv->clock_ns; |
4279 | break; |
4280 | case CMDF_ROUND_UP: |
4281 | up_count = |
4282 | DIV_ROUND_UP(data[2], devpriv->clock_ns); |
4283 | break; |
4284 | default: |
4285 | return -EINVAL; |
4286 | } |
4287 | switch (data[3]) { |
4288 | case CMDF_ROUND_NEAREST: |
4289 | down_count = DIV_ROUND_CLOSEST(data[4], |
4290 | devpriv->clock_ns); |
4291 | break; |
4292 | case CMDF_ROUND_DOWN: |
4293 | down_count = data[4] / devpriv->clock_ns; |
4294 | break; |
4295 | case CMDF_ROUND_UP: |
4296 | down_count = |
4297 | DIV_ROUND_UP(data[4], devpriv->clock_ns); |
4298 | break; |
4299 | default: |
4300 | return -EINVAL; |
4301 | } |
4302 | if (up_count * devpriv->clock_ns != data[2] || |
4303 | down_count * devpriv->clock_ns != data[4]) { |
4304 | data[2] = up_count * devpriv->clock_ns; |
4305 | data[4] = down_count * devpriv->clock_ns; |
4306 | return -EAGAIN; |
4307 | } |
4308 | ni_writel(dev, data: up_count, NI6143_CALIB_HI_TIME_REG); |
4309 | devpriv->pwm_up_count = up_count; |
4310 | ni_writel(dev, data: down_count, NI6143_CALIB_LO_TIME_REG); |
4311 | devpriv->pwm_down_count = down_count; |
4312 | return 5; |
4313 | case INSN_CONFIG_GET_PWM_OUTPUT: |
4314 | return ni_get_pwm_config(dev, data); |
4315 | default: |
4316 | return -EINVAL; |
4317 | } |
4318 | return 0; |
4319 | } |
4320 | |
4321 | static int pack_mb88341(int addr, int val, int *bitstring) |
4322 | { |
4323 | /* |
4324 | * Fujitsu MB 88341 |
4325 | * Note that address bits are reversed. Thanks to |
4326 | * Ingo Keen for noticing this. |
4327 | * |
4328 | * Note also that the 88341 expects address values from |
4329 | * 1-12, whereas we use channel numbers 0-11. The NI |
4330 | * docs use 1-12, also, so be careful here. |
4331 | */ |
4332 | addr++; |
4333 | *bitstring = ((addr & 0x1) << 11) | |
4334 | ((addr & 0x2) << 9) | |
4335 | ((addr & 0x4) << 7) | ((addr & 0x8) << 5) | (val & 0xff); |
4336 | return 12; |
4337 | } |
4338 | |
4339 | static int pack_dac8800(int addr, int val, int *bitstring) |
4340 | { |
4341 | *bitstring = ((addr & 0x7) << 8) | (val & 0xff); |
4342 | return 11; |
4343 | } |
4344 | |
4345 | static int pack_dac8043(int addr, int val, int *bitstring) |
4346 | { |
4347 | *bitstring = val & 0xfff; |
4348 | return 12; |
4349 | } |
4350 | |
4351 | static int pack_ad8522(int addr, int val, int *bitstring) |
4352 | { |
4353 | *bitstring = (val & 0xfff) | (addr ? 0xc000 : 0xa000); |
4354 | return 16; |
4355 | } |
4356 | |
4357 | static int pack_ad8804(int addr, int val, int *bitstring) |
4358 | { |
4359 | *bitstring = ((addr & 0xf) << 8) | (val & 0xff); |
4360 | return 12; |
4361 | } |
4362 | |
4363 | static int pack_ad8842(int addr, int val, int *bitstring) |
4364 | { |
4365 | *bitstring = ((addr + 1) << 8) | (val & 0xff); |
4366 | return 12; |
4367 | } |
4368 | |
4369 | struct caldac_struct { |
4370 | int n_chans; |
4371 | int n_bits; |
4372 | int (*packbits)(int address, int value, int *bitstring); |
4373 | }; |
4374 | |
4375 | static struct caldac_struct caldacs[] = { |
4376 | [mb88341] = {12, 8, pack_mb88341}, |
4377 | [dac8800] = {.n_chans: 8, .n_bits: 8, .packbits: pack_dac8800}, |
4378 | [dac8043] = {.n_chans: 1, .n_bits: 12, .packbits: pack_dac8043}, |
4379 | [ad8522] = {.n_chans: 2, .n_bits: 12, .packbits: pack_ad8522}, |
4380 | [ad8804] = {.n_chans: 12, .n_bits: 8, .packbits: pack_ad8804}, |
4381 | [ad8842] = {.n_chans: 8, .n_bits: 8, .packbits: pack_ad8842}, |
4382 | [ad8804_debug] = {.n_chans: 16, .n_bits: 8, .packbits: pack_ad8804}, |
4383 | }; |
4384 | |
4385 | static void ni_write_caldac(struct comedi_device *dev, int addr, int val) |
4386 | { |
4387 | const struct ni_board_struct *board = dev->board_ptr; |
4388 | struct ni_private *devpriv = dev->private; |
4389 | unsigned int loadbit = 0, bits = 0, bit, bitstring = 0; |
4390 | unsigned int cmd; |
4391 | int i; |
4392 | int type; |
4393 | |
4394 | if (devpriv->caldacs[addr] == val) |
4395 | return; |
4396 | devpriv->caldacs[addr] = val; |
4397 | |
4398 | for (i = 0; i < 3; i++) { |
4399 | type = board->caldac[i]; |
4400 | if (type == caldac_none) |
4401 | break; |
4402 | if (addr < caldacs[type].n_chans) { |
4403 | bits = caldacs[type].packbits(addr, val, &bitstring); |
4404 | loadbit = NI_E_SERIAL_CMD_DAC_LD(i); |
4405 | break; |
4406 | } |
4407 | addr -= caldacs[type].n_chans; |
4408 | } |
4409 | |
4410 | /* bits will be 0 if there is no caldac for the given addr */ |
4411 | if (bits == 0) |
4412 | return; |
4413 | |
4414 | for (bit = 1 << (bits - 1); bit; bit >>= 1) { |
4415 | cmd = (bit & bitstring) ? NI_E_SERIAL_CMD_SDATA : 0; |
4416 | ni_writeb(dev, data: cmd, NI_E_SERIAL_CMD_REG); |
4417 | udelay(1); |
4418 | ni_writeb(dev, NI_E_SERIAL_CMD_SCLK | cmd, NI_E_SERIAL_CMD_REG); |
4419 | udelay(1); |
4420 | } |
4421 | ni_writeb(dev, data: loadbit, NI_E_SERIAL_CMD_REG); |
4422 | udelay(1); |
4423 | ni_writeb(dev, data: 0, NI_E_SERIAL_CMD_REG); |
4424 | } |
4425 | |
4426 | static int ni_calib_insn_write(struct comedi_device *dev, |
4427 | struct comedi_subdevice *s, |
4428 | struct comedi_insn *insn, |
4429 | unsigned int *data) |
4430 | { |
4431 | if (insn->n) { |
4432 | /* only bother writing the last sample to the channel */ |
4433 | ni_write_caldac(dev, CR_CHAN(insn->chanspec), |
4434 | val: data[insn->n - 1]); |
4435 | } |
4436 | |
4437 | return insn->n; |
4438 | } |
4439 | |
4440 | static int ni_calib_insn_read(struct comedi_device *dev, |
4441 | struct comedi_subdevice *s, |
4442 | struct comedi_insn *insn, |
4443 | unsigned int *data) |
4444 | { |
4445 | struct ni_private *devpriv = dev->private; |
4446 | unsigned int i; |
4447 | |
4448 | for (i = 0; i < insn->n; i++) |
4449 | data[0] = devpriv->caldacs[CR_CHAN(insn->chanspec)]; |
4450 | |
4451 | return insn->n; |
4452 | } |
4453 | |
4454 | static void caldac_setup(struct comedi_device *dev, struct comedi_subdevice *s) |
4455 | { |
4456 | const struct ni_board_struct *board = dev->board_ptr; |
4457 | struct ni_private *devpriv = dev->private; |
4458 | int i, j; |
4459 | int n_dacs; |
4460 | int n_chans = 0; |
4461 | int n_bits; |
4462 | int diffbits = 0; |
4463 | int type; |
4464 | int chan; |
4465 | |
4466 | type = board->caldac[0]; |
4467 | if (type == caldac_none) |
4468 | return; |
4469 | n_bits = caldacs[type].n_bits; |
4470 | for (i = 0; i < 3; i++) { |
4471 | type = board->caldac[i]; |
4472 | if (type == caldac_none) |
4473 | break; |
4474 | if (caldacs[type].n_bits != n_bits) |
4475 | diffbits = 1; |
4476 | n_chans += caldacs[type].n_chans; |
4477 | } |
4478 | n_dacs = i; |
4479 | s->n_chan = n_chans; |
4480 | |
4481 | if (diffbits) { |
4482 | unsigned int *maxdata_list = devpriv->caldac_maxdata_list; |
4483 | |
4484 | if (n_chans > MAX_N_CALDACS) |
4485 | dev_err(dev->class_dev, |
4486 | "BUG! MAX_N_CALDACS too small\n" ); |
4487 | s->maxdata_list = maxdata_list; |
4488 | chan = 0; |
4489 | for (i = 0; i < n_dacs; i++) { |
4490 | type = board->caldac[i]; |
4491 | for (j = 0; j < caldacs[type].n_chans; j++) { |
4492 | maxdata_list[chan] = |
4493 | (1 << caldacs[type].n_bits) - 1; |
4494 | chan++; |
4495 | } |
4496 | } |
4497 | |
4498 | for (chan = 0; chan < s->n_chan; chan++) |
4499 | ni_write_caldac(dev, addr: i, val: s->maxdata_list[i] / 2); |
4500 | } else { |
4501 | type = board->caldac[0]; |
4502 | s->maxdata = (1 << caldacs[type].n_bits) - 1; |
4503 | |
4504 | for (chan = 0; chan < s->n_chan; chan++) |
4505 | ni_write_caldac(dev, addr: i, val: s->maxdata / 2); |
4506 | } |
4507 | } |
4508 | |
4509 | static int ni_read_eeprom(struct comedi_device *dev, int addr) |
4510 | { |
4511 | unsigned int cmd = NI_E_SERIAL_CMD_EEPROM_CS; |
4512 | int bit; |
4513 | int bitstring; |
4514 | |
4515 | bitstring = 0x0300 | ((addr & 0x100) << 3) | (addr & 0xff); |
4516 | ni_writeb(dev, data: cmd, NI_E_SERIAL_CMD_REG); |
4517 | for (bit = 0x8000; bit; bit >>= 1) { |
4518 | if (bit & bitstring) |
4519 | cmd |= NI_E_SERIAL_CMD_SDATA; |
4520 | else |
4521 | cmd &= ~NI_E_SERIAL_CMD_SDATA; |
4522 | |
4523 | ni_writeb(dev, data: cmd, NI_E_SERIAL_CMD_REG); |
4524 | ni_writeb(dev, NI_E_SERIAL_CMD_SCLK | cmd, NI_E_SERIAL_CMD_REG); |
4525 | } |
4526 | cmd = NI_E_SERIAL_CMD_EEPROM_CS; |
4527 | bitstring = 0; |
4528 | for (bit = 0x80; bit; bit >>= 1) { |
4529 | ni_writeb(dev, data: cmd, NI_E_SERIAL_CMD_REG); |
4530 | ni_writeb(dev, NI_E_SERIAL_CMD_SCLK | cmd, NI_E_SERIAL_CMD_REG); |
4531 | if (ni_readb(dev, NI_E_STATUS_REG) & NI_E_STATUS_PROMOUT) |
4532 | bitstring |= bit; |
4533 | } |
4534 | ni_writeb(dev, data: 0, NI_E_SERIAL_CMD_REG); |
4535 | |
4536 | return bitstring; |
4537 | } |
4538 | |
4539 | static int ni_eeprom_insn_read(struct comedi_device *dev, |
4540 | struct comedi_subdevice *s, |
4541 | struct comedi_insn *insn, |
4542 | unsigned int *data) |
4543 | { |
4544 | unsigned int val; |
4545 | unsigned int i; |
4546 | |
4547 | if (insn->n) { |
4548 | val = ni_read_eeprom(dev, CR_CHAN(insn->chanspec)); |
4549 | for (i = 0; i < insn->n; i++) |
4550 | data[i] = val; |
4551 | } |
4552 | return insn->n; |
4553 | } |
4554 | |
4555 | static int ni_m_series_eeprom_insn_read(struct comedi_device *dev, |
4556 | struct comedi_subdevice *s, |
4557 | struct comedi_insn *insn, |
4558 | unsigned int *data) |
4559 | { |
4560 | struct ni_private *devpriv = dev->private; |
4561 | unsigned int i; |
4562 | |
4563 | for (i = 0; i < insn->n; i++) |
4564 | data[i] = devpriv->eeprom_buffer[CR_CHAN(insn->chanspec)]; |
4565 | |
4566 | return insn->n; |
4567 | } |
4568 | |
4569 | static unsigned int ni_old_get_pfi_routing(struct comedi_device *dev, |
4570 | unsigned int chan) |
4571 | { |
4572 | /* pre-m-series boards have fixed signals on pfi pins */ |
4573 | switch (chan) { |
4574 | case 0: |
4575 | return NI_PFI_OUTPUT_AI_START1; |
4576 | case 1: |
4577 | return NI_PFI_OUTPUT_AI_START2; |
4578 | case 2: |
4579 | return NI_PFI_OUTPUT_AI_CONVERT; |
4580 | case 3: |
4581 | return NI_PFI_OUTPUT_G_SRC1; |
4582 | case 4: |
4583 | return NI_PFI_OUTPUT_G_GATE1; |
4584 | case 5: |
4585 | return NI_PFI_OUTPUT_AO_UPDATE_N; |
4586 | case 6: |
4587 | return NI_PFI_OUTPUT_AO_START1; |
4588 | case 7: |
4589 | return NI_PFI_OUTPUT_AI_START_PULSE; |
4590 | case 8: |
4591 | return NI_PFI_OUTPUT_G_SRC0; |
4592 | case 9: |
4593 | return NI_PFI_OUTPUT_G_GATE0; |
4594 | default: |
4595 | dev_err(dev->class_dev, "bug, unhandled case in switch.\n" ); |
4596 | break; |
4597 | } |
4598 | return 0; |
4599 | } |
4600 | |
4601 | static int ni_old_set_pfi_routing(struct comedi_device *dev, |
4602 | unsigned int chan, unsigned int source) |
4603 | { |
4604 | /* pre-m-series boards have fixed signals on pfi pins */ |
4605 | if (source != ni_old_get_pfi_routing(dev, chan)) |
4606 | return -EINVAL; |
4607 | return 2; |
4608 | } |
4609 | |
4610 | static unsigned int ni_m_series_get_pfi_routing(struct comedi_device *dev, |
4611 | unsigned int chan) |
4612 | { |
4613 | struct ni_private *devpriv = dev->private; |
4614 | const unsigned int array_offset = chan / 3; |
4615 | |
4616 | return NI_M_PFI_OUT_SEL_TO_SRC(chan, |
4617 | devpriv->pfi_output_select_reg[array_offset]); |
4618 | } |
4619 | |
4620 | static int ni_m_series_set_pfi_routing(struct comedi_device *dev, |
4621 | unsigned int chan, unsigned int source) |
4622 | { |
4623 | struct ni_private *devpriv = dev->private; |
4624 | unsigned int index = chan / 3; |
4625 | unsigned short val = devpriv->pfi_output_select_reg[index]; |
4626 | |
4627 | if ((source & 0x1f) != source) |
4628 | return -EINVAL; |
4629 | |
4630 | val &= ~NI_M_PFI_OUT_SEL_MASK(chan); |
4631 | val |= NI_M_PFI_OUT_SEL(chan, source); |
4632 | ni_writew(dev, data: val, NI_M_PFI_OUT_SEL_REG(index)); |
4633 | devpriv->pfi_output_select_reg[index] = val; |
4634 | |
4635 | return 2; |
4636 | } |
4637 | |
4638 | static unsigned int ni_get_pfi_routing(struct comedi_device *dev, |
4639 | unsigned int chan) |
4640 | { |
4641 | struct ni_private *devpriv = dev->private; |
4642 | |
4643 | if (chan >= NI_PFI(0)) { |
4644 | /* allow new and old names of pfi channels to work. */ |
4645 | chan -= NI_PFI(0); |
4646 | } |
4647 | return (devpriv->is_m_series) |
4648 | ? ni_m_series_get_pfi_routing(dev, chan) |
4649 | : ni_old_get_pfi_routing(dev, chan); |
4650 | } |
4651 | |
4652 | /* Sets the output mux for the specified PFI channel. */ |
4653 | static int ni_set_pfi_routing(struct comedi_device *dev, |
4654 | unsigned int chan, unsigned int source) |
4655 | { |
4656 | struct ni_private *devpriv = dev->private; |
4657 | |
4658 | if (chan >= NI_PFI(0)) { |
4659 | /* allow new and old names of pfi channels to work. */ |
4660 | chan -= NI_PFI(0); |
4661 | } |
4662 | return (devpriv->is_m_series) |
4663 | ? ni_m_series_set_pfi_routing(dev, chan, source) |
4664 | : ni_old_set_pfi_routing(dev, chan, source); |
4665 | } |
4666 | |
4667 | static int ni_config_pfi_filter(struct comedi_device *dev, |
4668 | unsigned int chan, |
4669 | enum ni_pfi_filter_select filter) |
4670 | { |
4671 | struct ni_private *devpriv = dev->private; |
4672 | unsigned int bits; |
4673 | |
4674 | if (!devpriv->is_m_series) |
4675 | return -ENOTSUPP; |
4676 | |
4677 | if (chan >= NI_PFI(0)) { |
4678 | /* allow new and old names of pfi channels to work. */ |
4679 | chan -= NI_PFI(0); |
4680 | } |
4681 | |
4682 | bits = ni_readl(dev, NI_M_PFI_FILTER_REG); |
4683 | bits &= ~NI_M_PFI_FILTER_SEL_MASK(chan); |
4684 | bits |= NI_M_PFI_FILTER_SEL(chan, filter); |
4685 | ni_writel(dev, data: bits, NI_M_PFI_FILTER_REG); |
4686 | return 0; |
4687 | } |
4688 | |
4689 | static void ni_set_pfi_direction(struct comedi_device *dev, int chan, |
4690 | unsigned int direction) |
4691 | { |
4692 | if (chan >= NI_PFI(0)) { |
4693 | /* allow new and old names of pfi channels to work. */ |
4694 | chan -= NI_PFI(0); |
4695 | } |
4696 | direction = (direction == COMEDI_OUTPUT) ? 1u : 0u; |
4697 | ni_set_bits(dev, NISTC_IO_BIDIR_PIN_REG, bits: 1 << chan, value: direction); |
4698 | } |
4699 | |
4700 | static int ni_get_pfi_direction(struct comedi_device *dev, int chan) |
4701 | { |
4702 | struct ni_private *devpriv = dev->private; |
4703 | |
4704 | if (chan >= NI_PFI(0)) { |
4705 | /* allow new and old names of pfi channels to work. */ |
4706 | chan -= NI_PFI(0); |
4707 | } |
4708 | return devpriv->io_bidirection_pin_reg & (1 << chan) ? |
4709 | COMEDI_OUTPUT : COMEDI_INPUT; |
4710 | } |
4711 | |
4712 | static int ni_pfi_insn_config(struct comedi_device *dev, |
4713 | struct comedi_subdevice *s, |
4714 | struct comedi_insn *insn, |
4715 | unsigned int *data) |
4716 | { |
4717 | unsigned int chan; |
4718 | |
4719 | if (insn->n < 1) |
4720 | return -EINVAL; |
4721 | |
4722 | chan = CR_CHAN(insn->chanspec); |
4723 | |
4724 | switch (data[0]) { |
4725 | case COMEDI_OUTPUT: |
4726 | case COMEDI_INPUT: |
4727 | ni_set_pfi_direction(dev, chan, direction: data[0]); |
4728 | break; |
4729 | case INSN_CONFIG_DIO_QUERY: |
4730 | data[1] = ni_get_pfi_direction(dev, chan); |
4731 | break; |
4732 | case INSN_CONFIG_SET_ROUTING: |
4733 | return ni_set_pfi_routing(dev, chan, source: data[1]); |
4734 | case INSN_CONFIG_GET_ROUTING: |
4735 | data[1] = ni_get_pfi_routing(dev, chan); |
4736 | break; |
4737 | case INSN_CONFIG_FILTER: |
4738 | return ni_config_pfi_filter(dev, chan, filter: data[1]); |
4739 | default: |
4740 | return -EINVAL; |
4741 | } |
4742 | return 0; |
4743 | } |
4744 | |
4745 | static int ni_pfi_insn_bits(struct comedi_device *dev, |
4746 | struct comedi_subdevice *s, |
4747 | struct comedi_insn *insn, |
4748 | unsigned int *data) |
4749 | { |
4750 | struct ni_private *devpriv = dev->private; |
4751 | |
4752 | if (!devpriv->is_m_series) |
4753 | return -ENOTSUPP; |
4754 | |
4755 | if (comedi_dio_update_state(s, data)) |
4756 | ni_writew(dev, data: s->state, NI_M_PFI_DO_REG); |
4757 | |
4758 | data[1] = ni_readw(dev, NI_M_PFI_DI_REG); |
4759 | |
4760 | return insn->n; |
4761 | } |
4762 | |
4763 | static int cs5529_wait_for_idle(struct comedi_device *dev) |
4764 | { |
4765 | unsigned short status; |
4766 | const int timeout = HZ; |
4767 | int i; |
4768 | |
4769 | for (i = 0; i < timeout; i++) { |
4770 | status = ni_ao_win_inw(dev, NI67XX_CAL_STATUS_REG); |
4771 | if ((status & NI67XX_CAL_STATUS_BUSY) == 0) |
4772 | break; |
4773 | set_current_state(TASK_INTERRUPTIBLE); |
4774 | if (schedule_timeout(timeout: 1)) |
4775 | return -EIO; |
4776 | } |
4777 | if (i == timeout) { |
4778 | dev_err(dev->class_dev, "timeout\n" ); |
4779 | return -ETIME; |
4780 | } |
4781 | return 0; |
4782 | } |
4783 | |
4784 | static void cs5529_command(struct comedi_device *dev, unsigned short value) |
4785 | { |
4786 | static const int timeout = 100; |
4787 | int i; |
4788 | |
4789 | ni_ao_win_outw(dev, data: value, NI67XX_CAL_CMD_REG); |
4790 | /* give time for command to start being serially clocked into cs5529. |
4791 | * this insures that the NI67XX_CAL_STATUS_BUSY bit will get properly |
4792 | * set before we exit this function. |
4793 | */ |
4794 | for (i = 0; i < timeout; i++) { |
4795 | if (ni_ao_win_inw(dev, NI67XX_CAL_STATUS_REG) & |
4796 | NI67XX_CAL_STATUS_BUSY) |
4797 | break; |
4798 | udelay(1); |
4799 | } |
4800 | if (i == timeout) |
4801 | dev_err(dev->class_dev, |
4802 | "possible problem - never saw adc go busy?\n" ); |
4803 | } |
4804 | |
4805 | static int cs5529_do_conversion(struct comedi_device *dev, |
4806 | unsigned short *data) |
4807 | { |
4808 | int retval; |
4809 | unsigned short status; |
4810 | |
4811 | cs5529_command(dev, CS5529_CMD_CB | CS5529_CMD_SINGLE_CONV); |
4812 | retval = cs5529_wait_for_idle(dev); |
4813 | if (retval) { |
4814 | dev_err(dev->class_dev, |
4815 | "timeout or signal in %s()\n" , __func__); |
4816 | return -ETIME; |
4817 | } |
4818 | status = ni_ao_win_inw(dev, NI67XX_CAL_STATUS_REG); |
4819 | if (status & NI67XX_CAL_STATUS_OSC_DETECT) { |
4820 | dev_err(dev->class_dev, |
4821 | "cs5529 conversion error, status CSS_OSC_DETECT\n" ); |
4822 | return -EIO; |
4823 | } |
4824 | if (status & NI67XX_CAL_STATUS_OVERRANGE) { |
4825 | dev_err(dev->class_dev, |
4826 | "cs5529 conversion error, overrange (ignoring)\n" ); |
4827 | } |
4828 | if (data) { |
4829 | *data = ni_ao_win_inw(dev, NI67XX_CAL_DATA_REG); |
4830 | /* cs5529 returns 16 bit signed data in bipolar mode */ |
4831 | *data ^= BIT(15); |
4832 | } |
4833 | return 0; |
4834 | } |
4835 | |
4836 | static int cs5529_ai_insn_read(struct comedi_device *dev, |
4837 | struct comedi_subdevice *s, |
4838 | struct comedi_insn *insn, |
4839 | unsigned int *data) |
4840 | { |
4841 | int n, retval; |
4842 | unsigned short sample; |
4843 | unsigned int channel_select; |
4844 | const unsigned int INTERNAL_REF = 0x1000; |
4845 | |
4846 | /* |
4847 | * Set calibration adc source. Docs lie, reference select bits 8 to 11 |
4848 | * do nothing. bit 12 seems to chooses internal reference voltage, bit |
4849 | * 13 causes the adc input to go overrange (maybe reads external |
4850 | * reference?) |
4851 | */ |
4852 | if (insn->chanspec & CR_ALT_SOURCE) |
4853 | channel_select = INTERNAL_REF; |
4854 | else |
4855 | channel_select = CR_CHAN(insn->chanspec); |
4856 | ni_ao_win_outw(dev, data: channel_select, NI67XX_AO_CAL_CHAN_SEL_REG); |
4857 | |
4858 | for (n = 0; n < insn->n; n++) { |
4859 | retval = cs5529_do_conversion(dev, data: &sample); |
4860 | if (retval < 0) |
4861 | return retval; |
4862 | data[n] = sample; |
4863 | } |
4864 | return insn->n; |
4865 | } |
4866 | |
4867 | static void cs5529_config_write(struct comedi_device *dev, unsigned int value, |
4868 | unsigned int reg_select_bits) |
4869 | { |
4870 | ni_ao_win_outw(dev, data: (value >> 16) & 0xff, NI67XX_CAL_CFG_HI_REG); |
4871 | ni_ao_win_outw(dev, data: value & 0xffff, NI67XX_CAL_CFG_LO_REG); |
4872 | reg_select_bits &= CS5529_CMD_REG_MASK; |
4873 | cs5529_command(dev, CS5529_CMD_CB | reg_select_bits); |
4874 | if (cs5529_wait_for_idle(dev)) |
4875 | dev_err(dev->class_dev, |
4876 | "timeout or signal in %s\n" , __func__); |
4877 | } |
4878 | |
4879 | static int init_cs5529(struct comedi_device *dev) |
4880 | { |
4881 | unsigned int config_bits = CS5529_CFG_PORT_FLAG | |
4882 | CS5529_CFG_WORD_RATE_2180; |
4883 | |
4884 | #if 1 |
4885 | /* do self-calibration */ |
4886 | cs5529_config_write(dev, value: config_bits | CS5529_CFG_CALIB_BOTH_SELF, |
4887 | CS5529_CFG_REG); |
4888 | /* need to force a conversion for calibration to run */ |
4889 | cs5529_do_conversion(dev, NULL); |
4890 | #else |
4891 | /* force gain calibration to 1 */ |
4892 | cs5529_config_write(dev, 0x400000, CS5529_GAIN_REG); |
4893 | cs5529_config_write(dev, config_bits | CS5529_CFG_CALIB_OFFSET_SELF, |
4894 | CS5529_CFG_REG); |
4895 | if (cs5529_wait_for_idle(dev)) |
4896 | dev_err(dev->class_dev, |
4897 | "timeout or signal in %s\n" , __func__); |
4898 | #endif |
4899 | return 0; |
4900 | } |
4901 | |
4902 | /* |
4903 | * Find best multiplier/divider to try and get the PLL running at 80 MHz |
4904 | * given an arbitrary frequency input clock. |
4905 | */ |
4906 | static int ni_mseries_get_pll_parameters(unsigned int reference_period_ns, |
4907 | unsigned int *freq_divider, |
4908 | unsigned int *freq_multiplier, |
4909 | unsigned int *actual_period_ns) |
4910 | { |
4911 | unsigned int div; |
4912 | unsigned int best_div = 1; |
4913 | unsigned int mult; |
4914 | unsigned int best_mult = 1; |
4915 | static const unsigned int pico_per_nano = 1000; |
4916 | const unsigned int reference_picosec = reference_period_ns * |
4917 | pico_per_nano; |
4918 | /* |
4919 | * m-series wants the phased-locked loop to output 80MHz, which is |
4920 | * divided by 4 to 20 MHz for most timing clocks |
4921 | */ |
4922 | static const unsigned int target_picosec = 12500; |
4923 | int best_period_picosec = 0; |
4924 | |
4925 | for (div = 1; div <= NI_M_PLL_MAX_DIVISOR; ++div) { |
4926 | for (mult = 1; mult <= NI_M_PLL_MAX_MULTIPLIER; ++mult) { |
4927 | unsigned int new_period_ps = |
4928 | (reference_picosec * div) / mult; |
4929 | if (abs(new_period_ps - target_picosec) < |
4930 | abs(best_period_picosec - target_picosec)) { |
4931 | best_period_picosec = new_period_ps; |
4932 | best_div = div; |
4933 | best_mult = mult; |
4934 | } |
4935 | } |
4936 | } |
4937 | if (best_period_picosec == 0) |
4938 | return -EIO; |
4939 | |
4940 | *freq_divider = best_div; |
4941 | *freq_multiplier = best_mult; |
4942 | /* return the actual period (* fudge factor for 80 to 20 MHz) */ |
4943 | *actual_period_ns = DIV_ROUND_CLOSEST(best_period_picosec * 4, |
4944 | pico_per_nano); |
4945 | return 0; |
4946 | } |
4947 | |
4948 | static int ni_mseries_set_pll_master_clock(struct comedi_device *dev, |
4949 | unsigned int source, |
4950 | unsigned int period_ns) |
4951 | { |
4952 | struct ni_private *devpriv = dev->private; |
4953 | static const unsigned int min_period_ns = 50; |
4954 | static const unsigned int max_period_ns = 1000; |
4955 | static const unsigned int timeout = 1000; |
4956 | unsigned int pll_control_bits; |
4957 | unsigned int freq_divider; |
4958 | unsigned int freq_multiplier; |
4959 | unsigned int rtsi; |
4960 | unsigned int i; |
4961 | int retval; |
4962 | |
4963 | if (source == NI_MIO_PLL_PXI10_CLOCK) |
4964 | period_ns = 100; |
4965 | /* |
4966 | * These limits are somewhat arbitrary, but NI advertises 1 to 20MHz |
4967 | * range so we'll use that. |
4968 | */ |
4969 | if (period_ns < min_period_ns || period_ns > max_period_ns) { |
4970 | dev_err(dev->class_dev, |
4971 | "%s: you must specify an input clock frequency between %i and %i nanosec for the phased-lock loop\n" , |
4972 | __func__, min_period_ns, max_period_ns); |
4973 | return -EINVAL; |
4974 | } |
4975 | devpriv->rtsi_trig_direction_reg &= ~NISTC_RTSI_TRIG_USE_CLK; |
4976 | ni_stc_writew(dev, data: devpriv->rtsi_trig_direction_reg, |
4977 | NISTC_RTSI_TRIG_DIR_REG); |
4978 | pll_control_bits = NI_M_PLL_CTRL_ENA | NI_M_PLL_CTRL_VCO_MODE_75_150MHZ; |
4979 | devpriv->clock_and_fout2 |= NI_M_CLK_FOUT2_TIMEBASE1_PLL | |
4980 | NI_M_CLK_FOUT2_TIMEBASE3_PLL; |
4981 | devpriv->clock_and_fout2 &= ~NI_M_CLK_FOUT2_PLL_SRC_MASK; |
4982 | switch (source) { |
4983 | case NI_MIO_PLL_PXI_STAR_TRIGGER_CLOCK: |
4984 | devpriv->clock_and_fout2 |= NI_M_CLK_FOUT2_PLL_SRC_STAR; |
4985 | break; |
4986 | case NI_MIO_PLL_PXI10_CLOCK: |
4987 | /* pxi clock is 10MHz */ |
4988 | devpriv->clock_and_fout2 |= NI_M_CLK_FOUT2_PLL_SRC_PXI10; |
4989 | break; |
4990 | default: |
4991 | for (rtsi = 0; rtsi <= NI_M_MAX_RTSI_CHAN; ++rtsi) { |
4992 | if (source == NI_MIO_PLL_RTSI_CLOCK(rtsi)) { |
4993 | devpriv->clock_and_fout2 |= |
4994 | NI_M_CLK_FOUT2_PLL_SRC_RTSI(rtsi); |
4995 | break; |
4996 | } |
4997 | } |
4998 | if (rtsi > NI_M_MAX_RTSI_CHAN) |
4999 | return -EINVAL; |
5000 | break; |
5001 | } |
5002 | retval = ni_mseries_get_pll_parameters(reference_period_ns: period_ns, |
5003 | freq_divider: &freq_divider, |
5004 | freq_multiplier: &freq_multiplier, |
5005 | actual_period_ns: &devpriv->clock_ns); |
5006 | if (retval < 0) { |
5007 | dev_err(dev->class_dev, |
5008 | "bug, failed to find pll parameters\n" ); |
5009 | return retval; |
5010 | } |
5011 | |
5012 | ni_writew(dev, data: devpriv->clock_and_fout2, NI_M_CLK_FOUT2_REG); |
5013 | pll_control_bits |= NI_M_PLL_CTRL_DIVISOR(freq_divider) | |
5014 | NI_M_PLL_CTRL_MULTIPLIER(freq_multiplier); |
5015 | |
5016 | ni_writew(dev, data: pll_control_bits, NI_M_PLL_CTRL_REG); |
5017 | devpriv->clock_source = source; |
5018 | /* it takes a few hundred microseconds for PLL to lock */ |
5019 | for (i = 0; i < timeout; ++i) { |
5020 | if (ni_readw(dev, NI_M_PLL_STATUS_REG) & NI_M_PLL_STATUS_LOCKED) |
5021 | break; |
5022 | udelay(1); |
5023 | } |
5024 | if (i == timeout) { |
5025 | dev_err(dev->class_dev, |
5026 | "%s: timed out waiting for PLL to lock to reference clock source %i with period %i ns\n" , |
5027 | __func__, source, period_ns); |
5028 | return -ETIMEDOUT; |
5029 | } |
5030 | return 3; |
5031 | } |
5032 | |
5033 | static int ni_set_master_clock(struct comedi_device *dev, |
5034 | unsigned int source, unsigned int period_ns) |
5035 | { |
5036 | struct ni_private *devpriv = dev->private; |
5037 | |
5038 | if (source == NI_MIO_INTERNAL_CLOCK) { |
5039 | devpriv->rtsi_trig_direction_reg &= ~NISTC_RTSI_TRIG_USE_CLK; |
5040 | ni_stc_writew(dev, data: devpriv->rtsi_trig_direction_reg, |
5041 | NISTC_RTSI_TRIG_DIR_REG); |
5042 | devpriv->clock_ns = TIMEBASE_1_NS; |
5043 | if (devpriv->is_m_series) { |
5044 | devpriv->clock_and_fout2 &= |
5045 | ~(NI_M_CLK_FOUT2_TIMEBASE1_PLL | |
5046 | NI_M_CLK_FOUT2_TIMEBASE3_PLL); |
5047 | ni_writew(dev, data: devpriv->clock_and_fout2, |
5048 | NI_M_CLK_FOUT2_REG); |
5049 | ni_writew(dev, data: 0, NI_M_PLL_CTRL_REG); |
5050 | } |
5051 | devpriv->clock_source = source; |
5052 | } else { |
5053 | if (devpriv->is_m_series) { |
5054 | return ni_mseries_set_pll_master_clock(dev, source, |
5055 | period_ns); |
5056 | } else { |
5057 | if (source == NI_MIO_RTSI_CLOCK) { |
5058 | devpriv->rtsi_trig_direction_reg |= |
5059 | NISTC_RTSI_TRIG_USE_CLK; |
5060 | ni_stc_writew(dev, |
5061 | data: devpriv->rtsi_trig_direction_reg, |
5062 | NISTC_RTSI_TRIG_DIR_REG); |
5063 | if (period_ns == 0) { |
5064 | dev_err(dev->class_dev, |
5065 | "we don't handle an unspecified clock period correctly yet, returning error\n" ); |
5066 | return -EINVAL; |
5067 | } |
5068 | devpriv->clock_ns = period_ns; |
5069 | devpriv->clock_source = source; |
5070 | } else { |
5071 | return -EINVAL; |
5072 | } |
5073 | } |
5074 | } |
5075 | return 3; |
5076 | } |
5077 | |
5078 | static int ni_valid_rtsi_output_source(struct comedi_device *dev, |
5079 | unsigned int chan, unsigned int source) |
5080 | { |
5081 | struct ni_private *devpriv = dev->private; |
5082 | |
5083 | if (chan >= NISTC_RTSI_TRIG_NUM_CHAN(devpriv->is_m_series)) { |
5084 | if (chan == NISTC_RTSI_TRIG_OLD_CLK_CHAN) { |
5085 | if (source == NI_RTSI_OUTPUT_RTSI_OSC) |
5086 | return 1; |
5087 | |
5088 | dev_err(dev->class_dev, |
5089 | "%s: invalid source for channel=%i, channel %i is always the RTSI clock for pre-m-series boards\n" , |
5090 | __func__, chan, NISTC_RTSI_TRIG_OLD_CLK_CHAN); |
5091 | return 0; |
5092 | } |
5093 | return 0; |
5094 | } |
5095 | switch (source) { |
5096 | case NI_RTSI_OUTPUT_ADR_START1: |
5097 | case NI_RTSI_OUTPUT_ADR_START2: |
5098 | case NI_RTSI_OUTPUT_SCLKG: |
5099 | case NI_RTSI_OUTPUT_DACUPDN: |
5100 | case NI_RTSI_OUTPUT_DA_START1: |
5101 | case NI_RTSI_OUTPUT_G_SRC0: |
5102 | case NI_RTSI_OUTPUT_G_GATE0: |
5103 | case NI_RTSI_OUTPUT_RGOUT0: |
5104 | case NI_RTSI_OUTPUT_RTSI_BRD(0): |
5105 | case NI_RTSI_OUTPUT_RTSI_BRD(1): |
5106 | case NI_RTSI_OUTPUT_RTSI_BRD(2): |
5107 | case NI_RTSI_OUTPUT_RTSI_BRD(3): |
5108 | return 1; |
5109 | case NI_RTSI_OUTPUT_RTSI_OSC: |
5110 | return (devpriv->is_m_series) ? 1 : 0; |
5111 | default: |
5112 | return 0; |
5113 | } |
5114 | } |
5115 | |
5116 | static int ni_set_rtsi_routing(struct comedi_device *dev, |
5117 | unsigned int chan, unsigned int src) |
5118 | { |
5119 | struct ni_private *devpriv = dev->private; |
5120 | |
5121 | if (chan >= TRIGGER_LINE(0)) |
5122 | /* allow new and old names of rtsi channels to work. */ |
5123 | chan -= TRIGGER_LINE(0); |
5124 | |
5125 | if (ni_valid_rtsi_output_source(dev, chan, source: src) == 0) |
5126 | return -EINVAL; |
5127 | if (chan < 4) { |
5128 | devpriv->rtsi_trig_a_output_reg &= ~NISTC_RTSI_TRIG_MASK(chan); |
5129 | devpriv->rtsi_trig_a_output_reg |= NISTC_RTSI_TRIG(chan, src); |
5130 | ni_stc_writew(dev, data: devpriv->rtsi_trig_a_output_reg, |
5131 | NISTC_RTSI_TRIGA_OUT_REG); |
5132 | } else if (chan < NISTC_RTSI_TRIG_NUM_CHAN(devpriv->is_m_series)) { |
5133 | devpriv->rtsi_trig_b_output_reg &= ~NISTC_RTSI_TRIG_MASK(chan); |
5134 | devpriv->rtsi_trig_b_output_reg |= NISTC_RTSI_TRIG(chan, src); |
5135 | ni_stc_writew(dev, data: devpriv->rtsi_trig_b_output_reg, |
5136 | NISTC_RTSI_TRIGB_OUT_REG); |
5137 | } else if (chan != NISTC_RTSI_TRIG_OLD_CLK_CHAN) { |
5138 | /* probably should never reach this, since the |
5139 | * ni_valid_rtsi_output_source above errors out if chan is too |
5140 | * high |
5141 | */ |
5142 | dev_err(dev->class_dev, "%s: unknown rtsi channel\n" , __func__); |
5143 | return -EINVAL; |
5144 | } |
5145 | return 2; |
5146 | } |
5147 | |
5148 | static unsigned int ni_get_rtsi_routing(struct comedi_device *dev, |
5149 | unsigned int chan) |
5150 | { |
5151 | struct ni_private *devpriv = dev->private; |
5152 | |
5153 | if (chan >= TRIGGER_LINE(0)) |
5154 | /* allow new and old names of rtsi channels to work. */ |
5155 | chan -= TRIGGER_LINE(0); |
5156 | |
5157 | if (chan < 4) { |
5158 | return NISTC_RTSI_TRIG_TO_SRC(chan, |
5159 | devpriv->rtsi_trig_a_output_reg); |
5160 | } else if (chan < NISTC_RTSI_TRIG_NUM_CHAN(devpriv->is_m_series)) { |
5161 | return NISTC_RTSI_TRIG_TO_SRC(chan, |
5162 | devpriv->rtsi_trig_b_output_reg); |
5163 | } else if (chan == NISTC_RTSI_TRIG_OLD_CLK_CHAN) { |
5164 | return NI_RTSI_OUTPUT_RTSI_OSC; |
5165 | } |
5166 | |
5167 | dev_err(dev->class_dev, "%s: unknown rtsi channel\n" , __func__); |
5168 | return -EINVAL; |
5169 | } |
5170 | |
5171 | static void ni_set_rtsi_direction(struct comedi_device *dev, int chan, |
5172 | unsigned int direction) |
5173 | { |
5174 | struct ni_private *devpriv = dev->private; |
5175 | unsigned int max_chan = NISTC_RTSI_TRIG_NUM_CHAN(devpriv->is_m_series); |
5176 | |
5177 | if (chan >= TRIGGER_LINE(0)) |
5178 | /* allow new and old names of rtsi channels to work. */ |
5179 | chan -= TRIGGER_LINE(0); |
5180 | |
5181 | if (direction == COMEDI_OUTPUT) { |
5182 | if (chan < max_chan) { |
5183 | devpriv->rtsi_trig_direction_reg |= |
5184 | NISTC_RTSI_TRIG_DIR(chan, devpriv->is_m_series); |
5185 | } else if (chan == NISTC_RTSI_TRIG_OLD_CLK_CHAN) { |
5186 | devpriv->rtsi_trig_direction_reg |= |
5187 | NISTC_RTSI_TRIG_DRV_CLK; |
5188 | } |
5189 | } else { |
5190 | if (chan < max_chan) { |
5191 | devpriv->rtsi_trig_direction_reg &= |
5192 | ~NISTC_RTSI_TRIG_DIR(chan, devpriv->is_m_series); |
5193 | } else if (chan == NISTC_RTSI_TRIG_OLD_CLK_CHAN) { |
5194 | devpriv->rtsi_trig_direction_reg &= |
5195 | ~NISTC_RTSI_TRIG_DRV_CLK; |
5196 | } |
5197 | } |
5198 | ni_stc_writew(dev, data: devpriv->rtsi_trig_direction_reg, |
5199 | NISTC_RTSI_TRIG_DIR_REG); |
5200 | } |
5201 | |
5202 | static int ni_get_rtsi_direction(struct comedi_device *dev, int chan) |
5203 | { |
5204 | struct ni_private *devpriv = dev->private; |
5205 | unsigned int max_chan = NISTC_RTSI_TRIG_NUM_CHAN(devpriv->is_m_series); |
5206 | |
5207 | if (chan >= TRIGGER_LINE(0)) |
5208 | /* allow new and old names of rtsi channels to work. */ |
5209 | chan -= TRIGGER_LINE(0); |
5210 | |
5211 | if (chan < max_chan) { |
5212 | return (devpriv->rtsi_trig_direction_reg & |
5213 | NISTC_RTSI_TRIG_DIR(chan, devpriv->is_m_series)) |
5214 | ? COMEDI_OUTPUT : COMEDI_INPUT; |
5215 | } else if (chan == NISTC_RTSI_TRIG_OLD_CLK_CHAN) { |
5216 | return (devpriv->rtsi_trig_direction_reg & |
5217 | NISTC_RTSI_TRIG_DRV_CLK) |
5218 | ? COMEDI_OUTPUT : COMEDI_INPUT; |
5219 | } |
5220 | return -EINVAL; |
5221 | } |
5222 | |
5223 | static int ni_rtsi_insn_config(struct comedi_device *dev, |
5224 | struct comedi_subdevice *s, |
5225 | struct comedi_insn *insn, |
5226 | unsigned int *data) |
5227 | { |
5228 | struct ni_private *devpriv = dev->private; |
5229 | unsigned int chan = CR_CHAN(insn->chanspec); |
5230 | |
5231 | switch (data[0]) { |
5232 | case COMEDI_OUTPUT: |
5233 | case COMEDI_INPUT: |
5234 | ni_set_rtsi_direction(dev, chan, direction: data[0]); |
5235 | break; |
5236 | case INSN_CONFIG_DIO_QUERY: { |
5237 | int ret = ni_get_rtsi_direction(dev, chan); |
5238 | |
5239 | if (ret < 0) |
5240 | return ret; |
5241 | data[1] = ret; |
5242 | return 2; |
5243 | } |
5244 | case INSN_CONFIG_SET_CLOCK_SRC: |
5245 | return ni_set_master_clock(dev, source: data[1], period_ns: data[2]); |
5246 | case INSN_CONFIG_GET_CLOCK_SRC: |
5247 | data[1] = devpriv->clock_source; |
5248 | data[2] = devpriv->clock_ns; |
5249 | return 3; |
5250 | case INSN_CONFIG_SET_ROUTING: |
5251 | return ni_set_rtsi_routing(dev, chan, src: data[1]); |
5252 | case INSN_CONFIG_GET_ROUTING: { |
5253 | int ret = ni_get_rtsi_routing(dev, chan); |
5254 | |
5255 | if (ret < 0) |
5256 | return ret; |
5257 | data[1] = ret; |
5258 | return 2; |
5259 | } |
5260 | default: |
5261 | return -EINVAL; |
5262 | } |
5263 | return 1; |
5264 | } |
5265 | |
5266 | static int ni_rtsi_insn_bits(struct comedi_device *dev, |
5267 | struct comedi_subdevice *s, |
5268 | struct comedi_insn *insn, |
5269 | unsigned int *data) |
5270 | { |
5271 | data[1] = 0; |
5272 | |
5273 | return insn->n; |
5274 | } |
5275 | |
5276 | /* |
5277 | * Default routing for RTSI trigger lines. |
5278 | * |
5279 | * These values are used here in the init function, as well as in the |
5280 | * disconnect_route function, after a RTSI route has been disconnected. |
5281 | */ |
5282 | static const int default_rtsi_routing[] = { |
5283 | [0] = NI_RTSI_OUTPUT_ADR_START1, |
5284 | [1] = NI_RTSI_OUTPUT_ADR_START2, |
5285 | [2] = NI_RTSI_OUTPUT_SCLKG, |
5286 | [3] = NI_RTSI_OUTPUT_DACUPDN, |
5287 | [4] = NI_RTSI_OUTPUT_DA_START1, |
5288 | [5] = NI_RTSI_OUTPUT_G_SRC0, |
5289 | [6] = NI_RTSI_OUTPUT_G_GATE0, |
5290 | [7] = NI_RTSI_OUTPUT_RTSI_OSC, |
5291 | }; |
5292 | |
5293 | /* |
5294 | * Route signals through RGOUT0 terminal. |
5295 | * @reg: raw register value of RGOUT0 bits (only bit0 is important). |
5296 | * @dev: comedi device handle. |
5297 | */ |
5298 | static void set_rgout0_reg(int reg, struct comedi_device *dev) |
5299 | { |
5300 | struct ni_private *devpriv = dev->private; |
5301 | |
5302 | if (devpriv->is_m_series) { |
5303 | devpriv->rtsi_trig_direction_reg &= |
5304 | ~NISTC_RTSI_TRIG_DIR_SUB_SEL1; |
5305 | devpriv->rtsi_trig_direction_reg |= |
5306 | (reg << NISTC_RTSI_TRIG_DIR_SUB_SEL1_SHIFT) & |
5307 | NISTC_RTSI_TRIG_DIR_SUB_SEL1; |
5308 | ni_stc_writew(dev, data: devpriv->rtsi_trig_direction_reg, |
5309 | NISTC_RTSI_TRIG_DIR_REG); |
5310 | } else { |
5311 | devpriv->rtsi_trig_b_output_reg &= ~NISTC_RTSI_TRIGB_SUB_SEL1; |
5312 | devpriv->rtsi_trig_b_output_reg |= |
5313 | (reg << NISTC_RTSI_TRIGB_SUB_SEL1_SHIFT) & |
5314 | NISTC_RTSI_TRIGB_SUB_SEL1; |
5315 | ni_stc_writew(dev, data: devpriv->rtsi_trig_b_output_reg, |
5316 | NISTC_RTSI_TRIGB_OUT_REG); |
5317 | } |
5318 | } |
5319 | |
5320 | static int get_rgout0_reg(struct comedi_device *dev) |
5321 | { |
5322 | struct ni_private *devpriv = dev->private; |
5323 | int reg; |
5324 | |
5325 | if (devpriv->is_m_series) |
5326 | reg = (devpriv->rtsi_trig_direction_reg & |
5327 | NISTC_RTSI_TRIG_DIR_SUB_SEL1) |
5328 | >> NISTC_RTSI_TRIG_DIR_SUB_SEL1_SHIFT; |
5329 | else |
5330 | reg = (devpriv->rtsi_trig_b_output_reg & |
5331 | NISTC_RTSI_TRIGB_SUB_SEL1) |
5332 | >> NISTC_RTSI_TRIGB_SUB_SEL1_SHIFT; |
5333 | return reg; |
5334 | } |
5335 | |
5336 | static inline int get_rgout0_src(struct comedi_device *dev) |
5337 | { |
5338 | struct ni_private *devpriv = dev->private; |
5339 | int reg = get_rgout0_reg(dev); |
5340 | |
5341 | return ni_find_route_source(src_sel_reg_value: reg, dest: NI_RGOUT0, tables: &devpriv->routing_tables); |
5342 | } |
5343 | |
5344 | /* |
5345 | * Route signals through RGOUT0 terminal and increment the RGOUT0 use for this |
5346 | * particular route. |
5347 | * @src: device-global signal name |
5348 | * @dev: comedi device handle |
5349 | * |
5350 | * Return: -EINVAL if the source is not valid to route to RGOUT0; |
5351 | * -EBUSY if the RGOUT0 is already used; |
5352 | * 0 if successful. |
5353 | */ |
5354 | static int incr_rgout0_src_use(int src, struct comedi_device *dev) |
5355 | { |
5356 | struct ni_private *devpriv = dev->private; |
5357 | s8 reg = ni_lookup_route_register(CR_CHAN(src), dest: NI_RGOUT0, |
5358 | tables: &devpriv->routing_tables); |
5359 | |
5360 | if (reg < 0) |
5361 | return -EINVAL; |
5362 | |
5363 | if (devpriv->rgout0_usage > 0 && get_rgout0_reg(dev) != reg) |
5364 | return -EBUSY; |
5365 | |
5366 | ++devpriv->rgout0_usage; |
5367 | set_rgout0_reg(reg, dev); |
5368 | return 0; |
5369 | } |
5370 | |
5371 | /* |
5372 | * Unroute signals through RGOUT0 terminal and deccrement the RGOUT0 use for |
5373 | * this particular source. This function does not actually unroute anything |
5374 | * with respect to RGOUT0. It does, on the other hand, decrement the usage |
5375 | * counter for the current src->RGOUT0 mapping. |
5376 | * |
5377 | * Return: -EINVAL if the source is not already routed to RGOUT0 (or usage is |
5378 | * already at zero); 0 if successful. |
5379 | */ |
5380 | static int decr_rgout0_src_use(int src, struct comedi_device *dev) |
5381 | { |
5382 | struct ni_private *devpriv = dev->private; |
5383 | s8 reg = ni_lookup_route_register(CR_CHAN(src), dest: NI_RGOUT0, |
5384 | tables: &devpriv->routing_tables); |
5385 | |
5386 | if (devpriv->rgout0_usage > 0 && get_rgout0_reg(dev) == reg) { |
5387 | --devpriv->rgout0_usage; |
5388 | if (!devpriv->rgout0_usage) |
5389 | set_rgout0_reg(reg: 0, dev); /* ok default? */ |
5390 | return 0; |
5391 | } |
5392 | return -EINVAL; |
5393 | } |
5394 | |
5395 | /* |
5396 | * Route signals through given NI_RTSI_BRD mux. |
5397 | * @i: index of mux to route |
5398 | * @reg: raw register value of RTSI_BRD bits |
5399 | * @dev: comedi device handle |
5400 | */ |
5401 | static void set_ith_rtsi_brd_reg(int i, int reg, struct comedi_device *dev) |
5402 | { |
5403 | struct ni_private *devpriv = dev->private; |
5404 | int reg_i_sz = 3; /* value for e-series */ |
5405 | int reg_i_mask; |
5406 | int reg_i_shift; |
5407 | |
5408 | if (devpriv->is_m_series) |
5409 | reg_i_sz = 4; |
5410 | reg_i_mask = ~((~0) << reg_i_sz); |
5411 | reg_i_shift = i * reg_i_sz; |
5412 | |
5413 | /* clear out the current reg_i for ith brd */ |
5414 | devpriv->rtsi_shared_mux_reg &= ~(reg_i_mask << reg_i_shift); |
5415 | /* (softcopy) write the new reg_i for ith brd */ |
5416 | devpriv->rtsi_shared_mux_reg |= (reg & reg_i_mask) << reg_i_shift; |
5417 | /* (hardcopy) write the new reg_i for ith brd */ |
5418 | ni_stc_writew(dev, data: devpriv->rtsi_shared_mux_reg, NISTC_RTSI_BOARD_REG); |
5419 | } |
5420 | |
5421 | static int get_ith_rtsi_brd_reg(int i, struct comedi_device *dev) |
5422 | { |
5423 | struct ni_private *devpriv = dev->private; |
5424 | int reg_i_sz = 3; /* value for e-series */ |
5425 | int reg_i_mask; |
5426 | int reg_i_shift; |
5427 | |
5428 | if (devpriv->is_m_series) |
5429 | reg_i_sz = 4; |
5430 | reg_i_mask = ~((~0) << reg_i_sz); |
5431 | reg_i_shift = i * reg_i_sz; |
5432 | |
5433 | return (devpriv->rtsi_shared_mux_reg >> reg_i_shift) & reg_i_mask; |
5434 | } |
5435 | |
5436 | static inline int get_rtsi_brd_src(int brd, struct comedi_device *dev) |
5437 | { |
5438 | struct ni_private *devpriv = dev->private; |
5439 | int brd_index = brd; |
5440 | int reg; |
5441 | |
5442 | if (brd >= NI_RTSI_BRD(0)) |
5443 | brd_index = brd - NI_RTSI_BRD(0); |
5444 | else |
5445 | brd = NI_RTSI_BRD(brd); |
5446 | /* |
5447 | * And now: |
5448 | * brd : device-global name |
5449 | * brd_index : index number of RTSI_BRD mux |
5450 | */ |
5451 | |
5452 | reg = get_ith_rtsi_brd_reg(i: brd_index, dev); |
5453 | |
5454 | return ni_find_route_source(src_sel_reg_value: reg, dest: brd, tables: &devpriv->routing_tables); |
5455 | } |
5456 | |
5457 | /* |
5458 | * Route signals through NI_RTSI_BRD mux and increment the use counter for this |
5459 | * particular route. |
5460 | * |
5461 | * Return: -EINVAL if the source is not valid to route to NI_RTSI_BRD(i); |
5462 | * -EBUSY if all NI_RTSI_BRD muxes are already used; |
5463 | * NI_RTSI_BRD(i) of allocated ith mux if successful. |
5464 | */ |
5465 | static int incr_rtsi_brd_src_use(int src, struct comedi_device *dev) |
5466 | { |
5467 | struct ni_private *devpriv = dev->private; |
5468 | int first_available = -1; |
5469 | int err = -EINVAL; |
5470 | s8 reg; |
5471 | int i; |
5472 | |
5473 | /* first look for a mux that is already configured to provide src */ |
5474 | for (i = 0; i < NUM_RTSI_SHARED_MUXS; ++i) { |
5475 | reg = ni_lookup_route_register(CR_CHAN(src), NI_RTSI_BRD(i), |
5476 | tables: &devpriv->routing_tables); |
5477 | |
5478 | if (reg < 0) |
5479 | continue; /* invalid route */ |
5480 | |
5481 | if (!devpriv->rtsi_shared_mux_usage[i]) { |
5482 | if (first_available < 0) |
5483 | /* found the first unused, but usable mux */ |
5484 | first_available = i; |
5485 | } else { |
5486 | /* |
5487 | * we've seen at least one possible route, so change the |
5488 | * final error to -EBUSY in case there are no muxes |
5489 | * available. |
5490 | */ |
5491 | err = -EBUSY; |
5492 | |
5493 | if (get_ith_rtsi_brd_reg(i, dev) == reg) { |
5494 | /* |
5495 | * we've found a mux that is already being used |
5496 | * to provide the requested signal. Reuse it. |
5497 | */ |
5498 | goto success; |
5499 | } |
5500 | } |
5501 | } |
5502 | |
5503 | if (first_available < 0) |
5504 | return err; |
5505 | |
5506 | /* we did not find a mux to reuse, but there is at least one usable */ |
5507 | i = first_available; |
5508 | |
5509 | success: |
5510 | ++devpriv->rtsi_shared_mux_usage[i]; |
5511 | set_ith_rtsi_brd_reg(i, reg, dev); |
5512 | return NI_RTSI_BRD(i); |
5513 | } |
5514 | |
5515 | /* |
5516 | * Unroute signals through NI_RTSI_BRD mux and decrement the user counter for |
5517 | * this particular route. |
5518 | * |
5519 | * Return: -EINVAL if the source is not already routed to rtsi_brd(i) (or usage |
5520 | * is already at zero); 0 if successful. |
5521 | */ |
5522 | static int decr_rtsi_brd_src_use(int src, int rtsi_brd, |
5523 | struct comedi_device *dev) |
5524 | { |
5525 | struct ni_private *devpriv = dev->private; |
5526 | s8 reg = ni_lookup_route_register(CR_CHAN(src), dest: rtsi_brd, |
5527 | tables: &devpriv->routing_tables); |
5528 | const int i = rtsi_brd - NI_RTSI_BRD(0); |
5529 | |
5530 | if (devpriv->rtsi_shared_mux_usage[i] > 0 && |
5531 | get_ith_rtsi_brd_reg(i, dev) == reg) { |
5532 | --devpriv->rtsi_shared_mux_usage[i]; |
5533 | if (!devpriv->rtsi_shared_mux_usage[i]) |
5534 | set_ith_rtsi_brd_reg(i, reg: 0, dev); /* ok default? */ |
5535 | return 0; |
5536 | } |
5537 | |
5538 | return -EINVAL; |
5539 | } |
5540 | |
5541 | static void ni_rtsi_init(struct comedi_device *dev) |
5542 | { |
5543 | struct ni_private *devpriv = dev->private; |
5544 | int i; |
5545 | |
5546 | /* Initialises the RTSI bus signal switch to a default state */ |
5547 | |
5548 | /* |
5549 | * Use 10MHz instead of 20MHz for RTSI clock frequency. Appears |
5550 | * to have no effect, at least on pxi-6281, which always uses |
5551 | * 20MHz rtsi clock frequency |
5552 | */ |
5553 | devpriv->clock_and_fout2 = NI_M_CLK_FOUT2_RTSI_10MHZ; |
5554 | /* Set clock mode to internal */ |
5555 | if (ni_set_master_clock(dev, source: NI_MIO_INTERNAL_CLOCK, period_ns: 0) < 0) |
5556 | dev_err(dev->class_dev, "ni_set_master_clock failed, bug?\n" ); |
5557 | |
5558 | /* default internal lines routing to RTSI bus lines */ |
5559 | for (i = 0; i < 8; ++i) { |
5560 | ni_set_rtsi_direction(dev, chan: i, direction: COMEDI_INPUT); |
5561 | ni_set_rtsi_routing(dev, chan: i, src: default_rtsi_routing[i]); |
5562 | } |
5563 | |
5564 | /* |
5565 | * Sets the source and direction of the 4 on board lines. |
5566 | * This configures all board lines to be: |
5567 | * for e-series: |
5568 | * 1) inputs (not sure what "output" would mean) |
5569 | * 2) copying TRIGGER_LINE(0) (or RTSI0) output |
5570 | * for m-series: |
5571 | * copying NI_PFI(0) output |
5572 | */ |
5573 | devpriv->rtsi_shared_mux_reg = 0; |
5574 | for (i = 0; i < 4; ++i) |
5575 | set_ith_rtsi_brd_reg(i, reg: 0, dev); |
5576 | memset(devpriv->rtsi_shared_mux_usage, 0, |
5577 | sizeof(devpriv->rtsi_shared_mux_usage)); |
5578 | |
5579 | /* initialize rgout0 pin as unused. */ |
5580 | devpriv->rgout0_usage = 0; |
5581 | set_rgout0_reg(reg: 0, dev); |
5582 | } |
5583 | |
5584 | /* Get route of GPFO_i/CtrOut pins */ |
5585 | static inline int ni_get_gout_routing(unsigned int dest, |
5586 | struct comedi_device *dev) |
5587 | { |
5588 | struct ni_private *devpriv = dev->private; |
5589 | unsigned int reg = devpriv->an_trig_etc_reg; |
5590 | |
5591 | switch (dest) { |
5592 | case 0: |
5593 | if (reg & NISTC_ATRIG_ETC_GPFO_0_ENA) |
5594 | return NISTC_ATRIG_ETC_GPFO_0_SEL_TO_SRC(reg); |
5595 | break; |
5596 | case 1: |
5597 | if (reg & NISTC_ATRIG_ETC_GPFO_1_ENA) |
5598 | return NISTC_ATRIG_ETC_GPFO_1_SEL_TO_SRC(reg); |
5599 | break; |
5600 | } |
5601 | |
5602 | return -EINVAL; |
5603 | } |
5604 | |
5605 | /* Set route of GPFO_i/CtrOut pins */ |
5606 | static inline int ni_disable_gout_routing(unsigned int dest, |
5607 | struct comedi_device *dev) |
5608 | { |
5609 | struct ni_private *devpriv = dev->private; |
5610 | |
5611 | switch (dest) { |
5612 | case 0: |
5613 | devpriv->an_trig_etc_reg &= ~NISTC_ATRIG_ETC_GPFO_0_ENA; |
5614 | break; |
5615 | case 1: |
5616 | devpriv->an_trig_etc_reg &= ~NISTC_ATRIG_ETC_GPFO_1_ENA; |
5617 | break; |
5618 | default: |
5619 | return -EINVAL; |
5620 | } |
5621 | |
5622 | ni_stc_writew(dev, data: devpriv->an_trig_etc_reg, NISTC_ATRIG_ETC_REG); |
5623 | return 0; |
5624 | } |
5625 | |
5626 | /* Set route of GPFO_i/CtrOut pins */ |
5627 | static inline int ni_set_gout_routing(unsigned int src, unsigned int dest, |
5628 | struct comedi_device *dev) |
5629 | { |
5630 | struct ni_private *devpriv = dev->private; |
5631 | |
5632 | switch (dest) { |
5633 | case 0: |
5634 | /* clear reg */ |
5635 | devpriv->an_trig_etc_reg &= ~NISTC_ATRIG_ETC_GPFO_0_SEL(-1); |
5636 | /* set reg */ |
5637 | devpriv->an_trig_etc_reg |= NISTC_ATRIG_ETC_GPFO_0_ENA |
5638 | | NISTC_ATRIG_ETC_GPFO_0_SEL(src); |
5639 | break; |
5640 | case 1: |
5641 | /* clear reg */ |
5642 | devpriv->an_trig_etc_reg &= ~NISTC_ATRIG_ETC_GPFO_1_SEL; |
5643 | src = src ? NISTC_ATRIG_ETC_GPFO_1_SEL : 0; |
5644 | /* set reg */ |
5645 | devpriv->an_trig_etc_reg |= NISTC_ATRIG_ETC_GPFO_1_ENA | src; |
5646 | break; |
5647 | default: |
5648 | return -EINVAL; |
5649 | } |
5650 | |
5651 | ni_stc_writew(dev, data: devpriv->an_trig_etc_reg, NISTC_ATRIG_ETC_REG); |
5652 | return 0; |
5653 | } |
5654 | |
5655 | /* |
5656 | * Retrieves the current source of the output selector for the given |
5657 | * destination. If the terminal for the destination is not already configured |
5658 | * as an output, this function returns -EINVAL as error. |
5659 | * |
5660 | * Return: the register value of the destination output selector; |
5661 | * -EINVAL if terminal is not configured for output. |
5662 | */ |
5663 | static int get_output_select_source(int dest, struct comedi_device *dev) |
5664 | { |
5665 | struct ni_private *devpriv = dev->private; |
5666 | int reg = -1; |
5667 | |
5668 | if (channel_is_pfi(channel: dest)) { |
5669 | if (ni_get_pfi_direction(dev, chan: dest) == COMEDI_OUTPUT) |
5670 | reg = ni_get_pfi_routing(dev, chan: dest); |
5671 | } else if (channel_is_rtsi(channel: dest)) { |
5672 | if (ni_get_rtsi_direction(dev, chan: dest) == COMEDI_OUTPUT) { |
5673 | reg = ni_get_rtsi_routing(dev, chan: dest); |
5674 | |
5675 | if (reg == NI_RTSI_OUTPUT_RGOUT0) { |
5676 | dest = NI_RGOUT0; /* prepare for lookup below */ |
5677 | reg = get_rgout0_reg(dev); |
5678 | } else if (reg >= NI_RTSI_OUTPUT_RTSI_BRD(0) && |
5679 | reg <= NI_RTSI_OUTPUT_RTSI_BRD(3)) { |
5680 | const int i = reg - NI_RTSI_OUTPUT_RTSI_BRD(0); |
5681 | |
5682 | dest = NI_RTSI_BRD(i); /* prepare for lookup */ |
5683 | reg = get_ith_rtsi_brd_reg(i, dev); |
5684 | } |
5685 | } |
5686 | } else if (dest >= NI_CtrOut(0) && dest <= NI_CtrOut(-1)) { |
5687 | /* |
5688 | * not handled by ni_tio. Only available for GPFO registers in |
5689 | * e/m series. |
5690 | */ |
5691 | dest -= NI_CtrOut(0); |
5692 | if (dest > 1) |
5693 | /* there are only two g_out outputs. */ |
5694 | return -EINVAL; |
5695 | reg = ni_get_gout_routing(dest, dev); |
5696 | } else if (channel_is_ctr(channel: dest)) { |
5697 | reg = ni_tio_get_routing(counter_dev: devpriv->counter_dev, destination: dest); |
5698 | } else { |
5699 | dev_dbg(dev->class_dev, "%s: unhandled destination (%d) queried\n" , |
5700 | __func__, dest); |
5701 | } |
5702 | |
5703 | if (reg >= 0) |
5704 | return ni_find_route_source(CR_CHAN(reg), dest, |
5705 | tables: &devpriv->routing_tables); |
5706 | return -EINVAL; |
5707 | } |
5708 | |
5709 | /* |
5710 | * Test a route: |
5711 | * |
5712 | * Return: -1 if not connectible; |
5713 | * 0 if connectible and not connected; |
5714 | * 1 if connectible and connected. |
5715 | */ |
5716 | static int test_route(unsigned int src, unsigned int dest, |
5717 | struct comedi_device *dev) |
5718 | { |
5719 | struct ni_private *devpriv = dev->private; |
5720 | s8 reg = ni_route_to_register(CR_CHAN(src), dest, |
5721 | tables: &devpriv->routing_tables); |
5722 | |
5723 | if (reg < 0) |
5724 | return -1; |
5725 | if (get_output_select_source(dest, dev) != CR_CHAN(src)) |
5726 | return 0; |
5727 | return 1; |
5728 | } |
5729 | |
5730 | /* Connect the actual route. */ |
5731 | static int connect_route(unsigned int src, unsigned int dest, |
5732 | struct comedi_device *dev) |
5733 | { |
5734 | struct ni_private *devpriv = dev->private; |
5735 | s8 reg = ni_route_to_register(CR_CHAN(src), dest, |
5736 | tables: &devpriv->routing_tables); |
5737 | s8 current_src; |
5738 | |
5739 | if (reg < 0) |
5740 | /* route is not valid */ |
5741 | return -EINVAL; |
5742 | |
5743 | current_src = get_output_select_source(dest, dev); |
5744 | if (current_src == CR_CHAN(src)) |
5745 | return -EALREADY; |
5746 | if (current_src >= 0) |
5747 | /* destination mux is already busy. complain, don't overwrite */ |
5748 | return -EBUSY; |
5749 | |
5750 | /* The route is valid and available. Now connect... */ |
5751 | if (channel_is_pfi(channel: dest)) { |
5752 | /* set routing source, then open output */ |
5753 | ni_set_pfi_routing(dev, chan: dest, source: reg); |
5754 | ni_set_pfi_direction(dev, chan: dest, direction: COMEDI_OUTPUT); |
5755 | } else if (channel_is_rtsi(channel: dest)) { |
5756 | if (reg == NI_RTSI_OUTPUT_RGOUT0) { |
5757 | int ret = incr_rgout0_src_use(src, dev); |
5758 | |
5759 | if (ret < 0) |
5760 | return ret; |
5761 | } else if (ni_rtsi_route_requires_mux(value: reg)) { |
5762 | /* Attempt to allocate and route (src->brd) */ |
5763 | int brd = incr_rtsi_brd_src_use(src, dev); |
5764 | |
5765 | if (brd < 0) |
5766 | return brd; |
5767 | |
5768 | /* Now lookup the register value for (brd->dest) */ |
5769 | reg = ni_lookup_route_register( |
5770 | src: brd, dest, tables: &devpriv->routing_tables); |
5771 | } |
5772 | |
5773 | ni_set_rtsi_direction(dev, chan: dest, direction: COMEDI_OUTPUT); |
5774 | ni_set_rtsi_routing(dev, chan: dest, src: reg); |
5775 | } else if (dest >= NI_CtrOut(0) && dest <= NI_CtrOut(-1)) { |
5776 | /* |
5777 | * not handled by ni_tio. Only available for GPFO registers in |
5778 | * e/m series. |
5779 | */ |
5780 | dest -= NI_CtrOut(0); |
5781 | if (dest > 1) |
5782 | /* there are only two g_out outputs. */ |
5783 | return -EINVAL; |
5784 | if (ni_set_gout_routing(src, dest, dev)) |
5785 | return -EINVAL; |
5786 | } else if (channel_is_ctr(channel: dest)) { |
5787 | /* |
5788 | * we are adding back the channel modifier info to set |
5789 | * invert/edge info passed by the user |
5790 | */ |
5791 | ni_tio_set_routing(counter_dev: devpriv->counter_dev, destination: dest, |
5792 | register_value: reg | (src & ~CR_CHAN(-1))); |
5793 | } else { |
5794 | return -EINVAL; |
5795 | } |
5796 | return 0; |
5797 | } |
5798 | |
5799 | static int disconnect_route(unsigned int src, unsigned int dest, |
5800 | struct comedi_device *dev) |
5801 | { |
5802 | struct ni_private *devpriv = dev->private; |
5803 | s8 reg = ni_route_to_register(CR_CHAN(src), dest, |
5804 | tables: &devpriv->routing_tables); |
5805 | |
5806 | if (reg < 0) |
5807 | /* route is not valid */ |
5808 | return -EINVAL; |
5809 | if (get_output_select_source(dest, dev) != src) |
5810 | /* cannot disconnect something not connected */ |
5811 | return -EINVAL; |
5812 | |
5813 | /* The route is valid and is connected. Now disconnect... */ |
5814 | if (channel_is_pfi(channel: dest)) { |
5815 | /* set the pfi to high impedance, and disconnect */ |
5816 | ni_set_pfi_direction(dev, chan: dest, direction: COMEDI_INPUT); |
5817 | ni_set_pfi_routing(dev, chan: dest, source: NI_PFI_OUTPUT_PFI_DEFAULT); |
5818 | } else if (channel_is_rtsi(channel: dest)) { |
5819 | if (reg == NI_RTSI_OUTPUT_RGOUT0) { |
5820 | int ret = decr_rgout0_src_use(src, dev); |
5821 | |
5822 | if (ret < 0) |
5823 | return ret; |
5824 | } else if (ni_rtsi_route_requires_mux(value: reg)) { |
5825 | /* find which RTSI_BRD line is source for rtsi pin */ |
5826 | int brd = ni_find_route_source( |
5827 | src_sel_reg_value: ni_get_rtsi_routing(dev, chan: dest), dest, |
5828 | tables: &devpriv->routing_tables); |
5829 | |
5830 | if (brd < 0) |
5831 | return brd; |
5832 | |
5833 | /* decrement/disconnect RTSI_BRD line from source */ |
5834 | decr_rtsi_brd_src_use(src, rtsi_brd: brd, dev); |
5835 | } |
5836 | |
5837 | /* set rtsi output selector to default state */ |
5838 | reg = default_rtsi_routing[dest - TRIGGER_LINE(0)]; |
5839 | ni_set_rtsi_direction(dev, chan: dest, direction: COMEDI_INPUT); |
5840 | ni_set_rtsi_routing(dev, chan: dest, src: reg); |
5841 | } else if (dest >= NI_CtrOut(0) && dest <= NI_CtrOut(-1)) { |
5842 | /* |
5843 | * not handled by ni_tio. Only available for GPFO registers in |
5844 | * e/m series. |
5845 | */ |
5846 | dest -= NI_CtrOut(0); |
5847 | if (dest > 1) |
5848 | /* there are only two g_out outputs. */ |
5849 | return -EINVAL; |
5850 | reg = ni_disable_gout_routing(dest, dev); |
5851 | } else if (channel_is_ctr(channel: dest)) { |
5852 | ni_tio_unset_routing(counter_dev: devpriv->counter_dev, destination: dest); |
5853 | } else { |
5854 | return -EINVAL; |
5855 | } |
5856 | return 0; |
5857 | } |
5858 | |
5859 | static int ni_global_insn_config(struct comedi_device *dev, |
5860 | struct comedi_insn *insn, |
5861 | unsigned int *data) |
5862 | { |
5863 | switch (data[0]) { |
5864 | case INSN_DEVICE_CONFIG_TEST_ROUTE: |
5865 | data[0] = test_route(src: data[1], dest: data[2], dev); |
5866 | return 2; |
5867 | case INSN_DEVICE_CONFIG_CONNECT_ROUTE: |
5868 | return connect_route(src: data[1], dest: data[2], dev); |
5869 | case INSN_DEVICE_CONFIG_DISCONNECT_ROUTE: |
5870 | return disconnect_route(src: data[1], dest: data[2], dev); |
5871 | /* |
5872 | * This case is already handled one level up. |
5873 | * case INSN_DEVICE_CONFIG_GET_ROUTES: |
5874 | */ |
5875 | default: |
5876 | return -EINVAL; |
5877 | } |
5878 | return 1; |
5879 | } |
5880 | |
5881 | #ifdef PCIDMA |
5882 | static int ni_gpct_cmd(struct comedi_device *dev, struct comedi_subdevice *s) |
5883 | { |
5884 | struct ni_gpct *counter = s->private; |
5885 | int retval; |
5886 | |
5887 | retval = ni_request_gpct_mite_channel(dev, counter->counter_index, |
5888 | COMEDI_INPUT); |
5889 | if (retval) { |
5890 | dev_err(dev->class_dev, |
5891 | "no dma channel available for use by counter\n" ); |
5892 | return retval; |
5893 | } |
5894 | ni_tio_acknowledge(counter); |
5895 | ni_e_series_enable_second_irq(dev, counter->counter_index, 1); |
5896 | |
5897 | return ni_tio_cmd(dev, s); |
5898 | } |
5899 | |
5900 | static int ni_gpct_cancel(struct comedi_device *dev, struct comedi_subdevice *s) |
5901 | { |
5902 | struct ni_gpct *counter = s->private; |
5903 | int retval; |
5904 | |
5905 | retval = ni_tio_cancel(counter); |
5906 | ni_e_series_enable_second_irq(dev, counter->counter_index, 0); |
5907 | ni_release_gpct_mite_channel(dev, counter->counter_index); |
5908 | return retval; |
5909 | } |
5910 | #endif |
5911 | |
5912 | static irqreturn_t ni_E_interrupt(int irq, void *d) |
5913 | { |
5914 | struct comedi_device *dev = d; |
5915 | struct comedi_subdevice *s_ai = dev->read_subdev; |
5916 | struct comedi_subdevice *s_ao = dev->write_subdev; |
5917 | unsigned short a_status; |
5918 | unsigned short b_status; |
5919 | unsigned long flags; |
5920 | #ifdef PCIDMA |
5921 | struct ni_private *devpriv = dev->private; |
5922 | #endif |
5923 | |
5924 | if (!dev->attached) |
5925 | return IRQ_NONE; |
5926 | smp_mb(); /* make sure dev->attached is checked */ |
5927 | |
5928 | /* lock to avoid race with comedi_poll */ |
5929 | spin_lock_irqsave(&dev->spinlock, flags); |
5930 | a_status = ni_stc_readw(dev, NISTC_AI_STATUS1_REG); |
5931 | b_status = ni_stc_readw(dev, NISTC_AO_STATUS1_REG); |
5932 | #ifdef PCIDMA |
5933 | if (devpriv->mite) { |
5934 | unsigned long flags_too; |
5935 | |
5936 | spin_lock_irqsave(&devpriv->mite_channel_lock, flags_too); |
5937 | if (s_ai && devpriv->ai_mite_chan) |
5938 | mite_ack_linkc(devpriv->ai_mite_chan, s_ai, false); |
5939 | if (s_ao && devpriv->ao_mite_chan) |
5940 | mite_ack_linkc(devpriv->ao_mite_chan, s_ao, false); |
5941 | spin_unlock_irqrestore(&devpriv->mite_channel_lock, flags_too); |
5942 | } |
5943 | #endif |
5944 | ack_a_interrupt(dev, a_status); |
5945 | ack_b_interrupt(dev, b_status); |
5946 | if (s_ai) { |
5947 | if (a_status & NISTC_AI_STATUS1_INTA) |
5948 | handle_a_interrupt(dev, s: s_ai, status: a_status); |
5949 | /* handle any interrupt or dma events */ |
5950 | comedi_handle_events(dev, s: s_ai); |
5951 | } |
5952 | if (s_ao) { |
5953 | if (b_status & NISTC_AO_STATUS1_INTB) |
5954 | handle_b_interrupt(dev, s: s_ao, b_status); |
5955 | /* handle any interrupt or dma events */ |
5956 | comedi_handle_events(dev, s: s_ao); |
5957 | } |
5958 | handle_gpct_interrupt(dev, counter_index: 0); |
5959 | handle_gpct_interrupt(dev, counter_index: 1); |
5960 | #ifdef PCIDMA |
5961 | if (devpriv->is_m_series) |
5962 | handle_cdio_interrupt(dev); |
5963 | #endif |
5964 | |
5965 | spin_unlock_irqrestore(lock: &dev->spinlock, flags); |
5966 | return IRQ_HANDLED; |
5967 | } |
5968 | |
5969 | static int ni_alloc_private(struct comedi_device *dev) |
5970 | { |
5971 | struct ni_private *devpriv; |
5972 | |
5973 | devpriv = comedi_alloc_devpriv(dev, size: sizeof(*devpriv)); |
5974 | if (!devpriv) |
5975 | return -ENOMEM; |
5976 | |
5977 | spin_lock_init(&devpriv->window_lock); |
5978 | spin_lock_init(&devpriv->soft_reg_copy_lock); |
5979 | spin_lock_init(&devpriv->mite_channel_lock); |
5980 | |
5981 | return 0; |
5982 | } |
5983 | |
5984 | static unsigned int _ni_get_valid_routes(struct comedi_device *dev, |
5985 | unsigned int n_pairs, |
5986 | unsigned int *pair_data) |
5987 | { |
5988 | struct ni_private *devpriv = dev->private; |
5989 | |
5990 | return ni_get_valid_routes(tables: &devpriv->routing_tables, n_pairs, |
5991 | pair_data); |
5992 | } |
5993 | |
5994 | static int ni_E_init(struct comedi_device *dev, |
5995 | unsigned int interrupt_pin, unsigned int irq_polarity) |
5996 | { |
5997 | const struct ni_board_struct *board = dev->board_ptr; |
5998 | struct ni_private *devpriv = dev->private; |
5999 | struct comedi_subdevice *s; |
6000 | int ret; |
6001 | int i; |
6002 | const char *dev_family = devpriv->is_m_series ? "ni_mseries" |
6003 | : "ni_eseries" ; |
6004 | if (!IS_PCIMIO != !dev->mmio) { |
6005 | dev_err(dev->class_dev, |
6006 | "%s: bug! %s device not supported.\n" , |
6007 | KBUILD_MODNAME, board->name); |
6008 | return -ENXIO; |
6009 | } |
6010 | |
6011 | /* prepare the device for globally-named routes. */ |
6012 | if (ni_assign_device_routes(device_family: dev_family, board_name: board->name, |
6013 | alt_board_name: board->alt_route_name, |
6014 | tables: &devpriv->routing_tables) < 0) { |
6015 | dev_warn(dev->class_dev, "%s: %s device has no signal routing table.\n" , |
6016 | __func__, board->name); |
6017 | dev_warn(dev->class_dev, "%s: High level NI signal names will not be available for this %s board.\n" , |
6018 | __func__, board->name); |
6019 | } else { |
6020 | /* |
6021 | * only(?) assign insn_device_config if we have global names for |
6022 | * this device. |
6023 | */ |
6024 | dev->insn_device_config = ni_global_insn_config; |
6025 | dev->get_valid_routes = _ni_get_valid_routes; |
6026 | } |
6027 | |
6028 | if (board->n_aochan > MAX_N_AO_CHAN) { |
6029 | dev_err(dev->class_dev, "bug! n_aochan > MAX_N_AO_CHAN\n" ); |
6030 | return -EINVAL; |
6031 | } |
6032 | |
6033 | /* initialize clock dividers */ |
6034 | devpriv->clock_and_fout = NISTC_CLK_FOUT_SLOW_DIV2 | |
6035 | NISTC_CLK_FOUT_SLOW_TIMEBASE | |
6036 | NISTC_CLK_FOUT_TO_BOARD_DIV2 | |
6037 | NISTC_CLK_FOUT_TO_BOARD; |
6038 | if (!devpriv->is_6xxx) { |
6039 | /* BEAM is this needed for PCI-6143 ?? */ |
6040 | devpriv->clock_and_fout |= (NISTC_CLK_FOUT_AI_OUT_DIV2 | |
6041 | NISTC_CLK_FOUT_AO_OUT_DIV2); |
6042 | } |
6043 | ni_stc_writew(dev, data: devpriv->clock_and_fout, NISTC_CLK_FOUT_REG); |
6044 | |
6045 | ret = comedi_alloc_subdevices(dev, num_subdevices: NI_NUM_SUBDEVICES); |
6046 | if (ret) |
6047 | return ret; |
6048 | |
6049 | /* Analog Input subdevice */ |
6050 | s = &dev->subdevices[NI_AI_SUBDEV]; |
6051 | if (board->n_adchan) { |
6052 | s->type = COMEDI_SUBD_AI; |
6053 | s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_DITHER; |
6054 | if (!devpriv->is_611x) |
6055 | s->subdev_flags |= SDF_GROUND | SDF_COMMON | SDF_OTHER; |
6056 | if (board->ai_maxdata > 0xffff) |
6057 | s->subdev_flags |= SDF_LSAMPL; |
6058 | if (devpriv->is_m_series) |
6059 | s->subdev_flags |= SDF_SOFT_CALIBRATED; |
6060 | s->n_chan = board->n_adchan; |
6061 | s->maxdata = board->ai_maxdata; |
6062 | s->range_table = ni_range_lkup[board->gainlkup]; |
6063 | s->insn_read = ni_ai_insn_read; |
6064 | s->insn_config = ni_ai_insn_config; |
6065 | if (dev->irq) { |
6066 | dev->read_subdev = s; |
6067 | s->subdev_flags |= SDF_CMD_READ; |
6068 | s->len_chanlist = 512; |
6069 | s->do_cmdtest = ni_ai_cmdtest; |
6070 | s->do_cmd = ni_ai_cmd; |
6071 | s->cancel = ni_ai_reset; |
6072 | s->poll = ni_ai_poll; |
6073 | s->munge = ni_ai_munge; |
6074 | |
6075 | if (devpriv->mite) |
6076 | s->async_dma_dir = DMA_FROM_DEVICE; |
6077 | } |
6078 | |
6079 | /* reset the analog input configuration */ |
6080 | ni_ai_reset(dev, s); |
6081 | } else { |
6082 | s->type = COMEDI_SUBD_UNUSED; |
6083 | } |
6084 | |
6085 | /* Analog Output subdevice */ |
6086 | s = &dev->subdevices[NI_AO_SUBDEV]; |
6087 | if (board->n_aochan) { |
6088 | s->type = COMEDI_SUBD_AO; |
6089 | s->subdev_flags = SDF_WRITABLE | SDF_DEGLITCH | SDF_GROUND; |
6090 | if (devpriv->is_m_series) |
6091 | s->subdev_flags |= SDF_SOFT_CALIBRATED; |
6092 | s->n_chan = board->n_aochan; |
6093 | s->maxdata = board->ao_maxdata; |
6094 | s->range_table = board->ao_range_table; |
6095 | s->insn_config = ni_ao_insn_config; |
6096 | s->insn_write = ni_ao_insn_write; |
6097 | |
6098 | ret = comedi_alloc_subdev_readback(s); |
6099 | if (ret) |
6100 | return ret; |
6101 | |
6102 | /* |
6103 | * Along with the IRQ we need either a FIFO or DMA for |
6104 | * async command support. |
6105 | */ |
6106 | if (dev->irq && (board->ao_fifo_depth || devpriv->mite)) { |
6107 | dev->write_subdev = s; |
6108 | s->subdev_flags |= SDF_CMD_WRITE; |
6109 | s->len_chanlist = s->n_chan; |
6110 | s->do_cmdtest = ni_ao_cmdtest; |
6111 | s->do_cmd = ni_ao_cmd; |
6112 | s->cancel = ni_ao_reset; |
6113 | if (!devpriv->is_m_series) |
6114 | s->munge = ni_ao_munge; |
6115 | |
6116 | if (devpriv->mite) |
6117 | s->async_dma_dir = DMA_TO_DEVICE; |
6118 | } |
6119 | |
6120 | if (devpriv->is_67xx) |
6121 | init_ao_67xx(dev, s); |
6122 | |
6123 | /* reset the analog output configuration */ |
6124 | ni_ao_reset(dev, s); |
6125 | } else { |
6126 | s->type = COMEDI_SUBD_UNUSED; |
6127 | } |
6128 | |
6129 | /* Digital I/O subdevice */ |
6130 | s = &dev->subdevices[NI_DIO_SUBDEV]; |
6131 | s->type = COMEDI_SUBD_DIO; |
6132 | s->subdev_flags = SDF_WRITABLE | SDF_READABLE; |
6133 | s->n_chan = board->has_32dio_chan ? 32 : 8; |
6134 | s->maxdata = 1; |
6135 | s->range_table = &range_digital; |
6136 | if (devpriv->is_m_series) { |
6137 | #ifdef PCIDMA |
6138 | s->subdev_flags |= SDF_LSAMPL; |
6139 | s->insn_bits = ni_m_series_dio_insn_bits; |
6140 | s->insn_config = ni_m_series_dio_insn_config; |
6141 | if (dev->irq) { |
6142 | s->subdev_flags |= SDF_CMD_WRITE /* | SDF_CMD_READ */; |
6143 | s->len_chanlist = s->n_chan; |
6144 | s->do_cmdtest = ni_cdio_cmdtest; |
6145 | s->do_cmd = ni_cdio_cmd; |
6146 | s->cancel = ni_cdio_cancel; |
6147 | |
6148 | /* M-series boards use DMA */ |
6149 | s->async_dma_dir = DMA_BIDIRECTIONAL; |
6150 | } |
6151 | |
6152 | /* reset DIO and set all channels to inputs */ |
6153 | ni_writel(dev, NI_M_CDO_CMD_RESET | |
6154 | NI_M_CDI_CMD_RESET, |
6155 | NI_M_CDIO_CMD_REG); |
6156 | ni_writel(dev, s->io_bits, NI_M_DIO_DIR_REG); |
6157 | #endif /* PCIDMA */ |
6158 | } else { |
6159 | s->insn_bits = ni_dio_insn_bits; |
6160 | s->insn_config = ni_dio_insn_config; |
6161 | |
6162 | /* set all channels to inputs */ |
6163 | devpriv->dio_control = NISTC_DIO_CTRL_DIR(s->io_bits); |
6164 | ni_writew(dev, data: devpriv->dio_control, NISTC_DIO_CTRL_REG); |
6165 | } |
6166 | |
6167 | /* 8255 device */ |
6168 | s = &dev->subdevices[NI_8255_DIO_SUBDEV]; |
6169 | if (board->has_8255) { |
6170 | ret = subdev_8255_cb_init(dev, s, io: ni_8255_callback, |
6171 | NI_E_8255_BASE); |
6172 | if (ret) |
6173 | return ret; |
6174 | } else { |
6175 | s->type = COMEDI_SUBD_UNUSED; |
6176 | } |
6177 | |
6178 | /* formerly general purpose counter/timer device, but no longer used */ |
6179 | s = &dev->subdevices[NI_UNUSED_SUBDEV]; |
6180 | s->type = COMEDI_SUBD_UNUSED; |
6181 | |
6182 | /* Calibration subdevice */ |
6183 | s = &dev->subdevices[NI_CALIBRATION_SUBDEV]; |
6184 | s->type = COMEDI_SUBD_CALIB; |
6185 | s->subdev_flags = SDF_INTERNAL; |
6186 | s->n_chan = 1; |
6187 | s->maxdata = 0; |
6188 | if (devpriv->is_m_series) { |
6189 | /* internal PWM output used for AI nonlinearity calibration */ |
6190 | s->insn_config = ni_m_series_pwm_config; |
6191 | |
6192 | ni_writel(dev, data: 0x0, NI_M_CAL_PWM_REG); |
6193 | } else if (devpriv->is_6143) { |
6194 | /* internal PWM output used for AI nonlinearity calibration */ |
6195 | s->insn_config = ni_6143_pwm_config; |
6196 | } else { |
6197 | s->subdev_flags |= SDF_WRITABLE; |
6198 | s->insn_read = ni_calib_insn_read; |
6199 | s->insn_write = ni_calib_insn_write; |
6200 | |
6201 | /* setup the caldacs and find the real n_chan and maxdata */ |
6202 | caldac_setup(dev, s); |
6203 | } |
6204 | |
6205 | /* EEPROM subdevice */ |
6206 | s = &dev->subdevices[NI_EEPROM_SUBDEV]; |
6207 | s->type = COMEDI_SUBD_MEMORY; |
6208 | s->subdev_flags = SDF_READABLE | SDF_INTERNAL; |
6209 | s->maxdata = 0xff; |
6210 | if (devpriv->is_m_series) { |
6211 | s->n_chan = M_SERIES_EEPROM_SIZE; |
6212 | s->insn_read = ni_m_series_eeprom_insn_read; |
6213 | } else { |
6214 | s->n_chan = 512; |
6215 | s->insn_read = ni_eeprom_insn_read; |
6216 | } |
6217 | |
6218 | /* Digital I/O (PFI) subdevice */ |
6219 | s = &dev->subdevices[NI_PFI_DIO_SUBDEV]; |
6220 | s->type = COMEDI_SUBD_DIO; |
6221 | s->maxdata = 1; |
6222 | if (devpriv->is_m_series) { |
6223 | s->n_chan = 16; |
6224 | s->insn_bits = ni_pfi_insn_bits; |
6225 | s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; |
6226 | |
6227 | ni_writew(dev, data: s->state, NI_M_PFI_DO_REG); |
6228 | for (i = 0; i < NUM_PFI_OUTPUT_SELECT_REGS; ++i) { |
6229 | ni_writew(dev, data: devpriv->pfi_output_select_reg[i], |
6230 | NI_M_PFI_OUT_SEL_REG(i)); |
6231 | } |
6232 | } else { |
6233 | s->n_chan = 10; |
6234 | s->subdev_flags = SDF_INTERNAL; |
6235 | } |
6236 | s->insn_config = ni_pfi_insn_config; |
6237 | |
6238 | ni_set_bits(dev, NISTC_IO_BIDIR_PIN_REG, bits: ~0, value: 0); |
6239 | |
6240 | /* cs5529 calibration adc */ |
6241 | s = &dev->subdevices[NI_CS5529_CALIBRATION_SUBDEV]; |
6242 | if (devpriv->is_67xx) { |
6243 | s->type = COMEDI_SUBD_AI; |
6244 | s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_INTERNAL; |
6245 | /* one channel for each analog output channel */ |
6246 | s->n_chan = board->n_aochan; |
6247 | s->maxdata = BIT(16) - 1; |
6248 | s->range_table = &range_unknown; /* XXX */ |
6249 | s->insn_read = cs5529_ai_insn_read; |
6250 | s->insn_config = NULL; |
6251 | init_cs5529(dev); |
6252 | } else { |
6253 | s->type = COMEDI_SUBD_UNUSED; |
6254 | } |
6255 | |
6256 | /* Serial */ |
6257 | s = &dev->subdevices[NI_SERIAL_SUBDEV]; |
6258 | s->type = COMEDI_SUBD_SERIAL; |
6259 | s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; |
6260 | s->n_chan = 1; |
6261 | s->maxdata = 0xff; |
6262 | s->insn_config = ni_serial_insn_config; |
6263 | devpriv->serial_interval_ns = 0; |
6264 | devpriv->serial_hw_mode = 0; |
6265 | |
6266 | /* RTSI */ |
6267 | s = &dev->subdevices[NI_RTSI_SUBDEV]; |
6268 | s->type = COMEDI_SUBD_DIO; |
6269 | s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL; |
6270 | s->n_chan = 8; |
6271 | s->maxdata = 1; |
6272 | s->insn_bits = ni_rtsi_insn_bits; |
6273 | s->insn_config = ni_rtsi_insn_config; |
6274 | ni_rtsi_init(dev); |
6275 | |
6276 | /* allocate and initialize the gpct counter device */ |
6277 | devpriv->counter_dev = ni_gpct_device_construct(dev, |
6278 | write: ni_gpct_write_register, |
6279 | read: ni_gpct_read_register, |
6280 | (devpriv->is_m_series) |
6281 | ? ni_gpct_variant_m_series |
6282 | : ni_gpct_variant_e_series, |
6283 | NUM_GPCT, |
6284 | NUM_GPCT, |
6285 | routing_tables: &devpriv->routing_tables); |
6286 | if (!devpriv->counter_dev) |
6287 | return -ENOMEM; |
6288 | |
6289 | /* Counter (gpct) subdevices */ |
6290 | for (i = 0; i < NUM_GPCT; ++i) { |
6291 | struct ni_gpct *gpct = &devpriv->counter_dev->counters[i]; |
6292 | |
6293 | /* setup and initialize the counter */ |
6294 | ni_tio_init_counter(counter: gpct); |
6295 | |
6296 | s = &dev->subdevices[NI_GPCT_SUBDEV(i)]; |
6297 | s->type = COMEDI_SUBD_COUNTER; |
6298 | s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_LSAMPL; |
6299 | s->n_chan = 3; |
6300 | s->maxdata = (devpriv->is_m_series) ? 0xffffffff |
6301 | : 0x00ffffff; |
6302 | s->insn_read = ni_tio_insn_read; |
6303 | s->insn_write = ni_tio_insn_write; |
6304 | s->insn_config = ni_tio_insn_config; |
6305 | #ifdef PCIDMA |
6306 | if (dev->irq && devpriv->mite) { |
6307 | s->subdev_flags |= SDF_CMD_READ /* | SDF_CMD_WRITE */; |
6308 | s->len_chanlist = 1; |
6309 | s->do_cmdtest = ni_tio_cmdtest; |
6310 | s->do_cmd = ni_gpct_cmd; |
6311 | s->cancel = ni_gpct_cancel; |
6312 | |
6313 | s->async_dma_dir = DMA_BIDIRECTIONAL; |
6314 | } |
6315 | #endif |
6316 | s->private = gpct; |
6317 | } |
6318 | |
6319 | /* Initialize GPFO_{0,1} to produce output of counters */ |
6320 | ni_set_gout_routing(src: 0, dest: 0, dev); /* output of counter 0; DAQ STC, p338 */ |
6321 | ni_set_gout_routing(src: 0, dest: 1, dev); /* output of counter 1; DAQ STC, p338 */ |
6322 | |
6323 | /* Frequency output subdevice */ |
6324 | s = &dev->subdevices[NI_FREQ_OUT_SUBDEV]; |
6325 | s->type = COMEDI_SUBD_COUNTER; |
6326 | s->subdev_flags = SDF_READABLE | SDF_WRITABLE; |
6327 | s->n_chan = 1; |
6328 | s->maxdata = 0xf; |
6329 | s->insn_read = ni_freq_out_insn_read; |
6330 | s->insn_write = ni_freq_out_insn_write; |
6331 | s->insn_config = ni_freq_out_insn_config; |
6332 | |
6333 | if (dev->irq) { |
6334 | ni_stc_writew(dev, |
6335 | data: (irq_polarity ? NISTC_INT_CTRL_INT_POL : 0) | |
6336 | (NISTC_INT_CTRL_3PIN_INT & 0) | |
6337 | NISTC_INT_CTRL_INTA_ENA | |
6338 | NISTC_INT_CTRL_INTB_ENA | |
6339 | NISTC_INT_CTRL_INTA_SEL(interrupt_pin) | |
6340 | NISTC_INT_CTRL_INTB_SEL(interrupt_pin), |
6341 | NISTC_INT_CTRL_REG); |
6342 | } |
6343 | |
6344 | /* DMA setup */ |
6345 | ni_writeb(dev, data: devpriv->ai_ao_select_reg, NI_E_DMA_AI_AO_SEL_REG); |
6346 | ni_writeb(dev, data: devpriv->g0_g1_select_reg, NI_E_DMA_G0_G1_SEL_REG); |
6347 | |
6348 | if (devpriv->is_6xxx) { |
6349 | ni_writeb(dev, data: 0, NI611X_MAGIC_REG); |
6350 | } else if (devpriv->is_m_series) { |
6351 | int channel; |
6352 | |
6353 | for (channel = 0; channel < board->n_aochan; ++channel) { |
6354 | ni_writeb(dev, data: 0xf, |
6355 | NI_M_AO_WAVEFORM_ORDER_REG(channel)); |
6356 | ni_writeb(dev, data: 0x0, |
6357 | NI_M_AO_REF_ATTENUATION_REG(channel)); |
6358 | } |
6359 | ni_writeb(dev, data: 0x0, NI_M_AO_CALIB_REG); |
6360 | } |
6361 | |
6362 | return 0; |
6363 | } |
6364 | |
6365 | static void mio_common_detach(struct comedi_device *dev) |
6366 | { |
6367 | struct ni_private *devpriv = dev->private; |
6368 | |
6369 | if (devpriv) |
6370 | ni_gpct_device_destroy(counter_dev: devpriv->counter_dev); |
6371 | } |
6372 | |