Linux-libre 5.4.47-gnu
[librecmc/linux-libre.git] / drivers / staging / comedi / drivers / ni_tiocmd.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Command support for NI general purpose counters
4  *
5  * Copyright (C) 2006 Frank Mori Hess <fmhess@users.sourceforge.net>
6  */
7
8 /*
9  * Module: ni_tiocmd
10  * Description: National Instruments general purpose counters command support
11  * Author: J.P. Mellor <jpmellor@rose-hulman.edu>,
12  *         Herman.Bruyninckx@mech.kuleuven.ac.be,
13  *         Wim.Meeussen@mech.kuleuven.ac.be,
14  *         Klaas.Gadeyne@mech.kuleuven.ac.be,
15  *         Frank Mori Hess <fmhess@users.sourceforge.net>
16  * Updated: Fri, 11 Apr 2008 12:32:35 +0100
17  * Status: works
18  *
19  * This module is not used directly by end-users.  Rather, it
20  * is used by other drivers (for example ni_660x and ni_pcimio)
21  * to provide command support for NI's general purpose counters.
22  * It was originally split out of ni_tio.c to stop the 'ni_tio'
23  * module depending on the 'mite' module.
24  *
25  * References:
26  * DAQ 660x Register-Level Programmer Manual  (NI 370505A-01)
27  * DAQ 6601/6602 User Manual (NI 322137B-01)
28  * 340934b.pdf  DAQ-STC reference manual
29  *
30  * TODO: Support use of both banks X and Y
31  */
32
33 #include <linux/module.h>
34 #include "ni_tio_internal.h"
35 #include "mite.h"
36 #include "ni_routes.h"
37
38 static void ni_tio_configure_dma(struct ni_gpct *counter,
39                                  bool enable, bool read)
40 {
41         struct ni_gpct_device *counter_dev = counter->counter_dev;
42         unsigned int cidx = counter->counter_index;
43         unsigned int mask;
44         unsigned int bits;
45
46         mask = GI_READ_ACKS_IRQ | GI_WRITE_ACKS_IRQ;
47         bits = 0;
48
49         if (enable) {
50                 if (read)
51                         bits |= GI_READ_ACKS_IRQ;
52                 else
53                         bits |= GI_WRITE_ACKS_IRQ;
54         }
55         ni_tio_set_bits(counter, NITIO_INPUT_SEL_REG(cidx), mask, bits);
56
57         switch (counter_dev->variant) {
58         case ni_gpct_variant_e_series:
59                 break;
60         case ni_gpct_variant_m_series:
61         case ni_gpct_variant_660x:
62                 mask = GI_DMA_ENABLE | GI_DMA_INT_ENA | GI_DMA_WRITE;
63                 bits = 0;
64
65                 if (enable)
66                         bits |= GI_DMA_ENABLE | GI_DMA_INT_ENA;
67                 if (!read)
68                         bits |= GI_DMA_WRITE;
69                 ni_tio_set_bits(counter, NITIO_DMA_CFG_REG(cidx), mask, bits);
70                 break;
71         }
72 }
73
74 static int ni_tio_input_inttrig(struct comedi_device *dev,
75                                 struct comedi_subdevice *s,
76                                 unsigned int trig_num)
77 {
78         struct ni_gpct *counter = s->private;
79         struct comedi_cmd *cmd = &s->async->cmd;
80         unsigned long flags;
81         int ret = 0;
82
83         if (trig_num != cmd->start_arg)
84                 return -EINVAL;
85
86         spin_lock_irqsave(&counter->lock, flags);
87         if (counter->mite_chan)
88                 mite_dma_arm(counter->mite_chan);
89         else
90                 ret = -EIO;
91         spin_unlock_irqrestore(&counter->lock, flags);
92         if (ret < 0)
93                 return ret;
94         ret = ni_tio_arm(counter, true, NI_GPCT_ARM_IMMEDIATE);
95         s->async->inttrig = NULL;
96
97         return ret;
98 }
99
100 static int ni_tio_input_cmd(struct comedi_subdevice *s)
101 {
102         struct ni_gpct *counter = s->private;
103         struct ni_gpct_device *counter_dev = counter->counter_dev;
104         const struct ni_route_tables *routing_tables =
105                 counter_dev->routing_tables;
106         unsigned int cidx = counter->counter_index;
107         struct comedi_async *async = s->async;
108         struct comedi_cmd *cmd = &async->cmd;
109         int ret = 0;
110
111         /* write alloc the entire buffer */
112         comedi_buf_write_alloc(s, async->prealloc_bufsz);
113         counter->mite_chan->dir = COMEDI_INPUT;
114         switch (counter_dev->variant) {
115         case ni_gpct_variant_m_series:
116         case ni_gpct_variant_660x:
117                 mite_prep_dma(counter->mite_chan, 32, 32);
118                 break;
119         case ni_gpct_variant_e_series:
120                 mite_prep_dma(counter->mite_chan, 16, 32);
121                 break;
122         }
123         ni_tio_set_bits(counter, NITIO_CMD_REG(cidx), GI_SAVE_TRACE, 0);
124         ni_tio_configure_dma(counter, true, true);
125
126         if (cmd->start_src == TRIG_INT) {
127                 async->inttrig = &ni_tio_input_inttrig;
128         } else {        /* TRIG_NOW || TRIG_EXT || TRIG_OTHER */
129                 async->inttrig = NULL;
130                 mite_dma_arm(counter->mite_chan);
131
132                 if (cmd->start_src == TRIG_NOW)
133                         ret = ni_tio_arm(counter, true, NI_GPCT_ARM_IMMEDIATE);
134                 else if (cmd->start_src == TRIG_EXT) {
135                         int reg = CR_CHAN(cmd->start_arg);
136
137                         if (reg >= NI_NAMES_BASE) {
138                                 /* using a device-global name. lookup reg */
139                                 reg = ni_get_reg_value(reg,
140                                                        NI_CtrArmStartTrigger(cidx),
141                                                        routing_tables);
142                                 /* mark this as a raw register value */
143                                 reg |= NI_GPCT_HW_ARM;
144                         }
145                         ret = ni_tio_arm(counter, true, reg);
146                 }
147         }
148         return ret;
149 }
150
151 static int ni_tio_output_cmd(struct comedi_subdevice *s)
152 {
153         struct ni_gpct *counter = s->private;
154
155         dev_err(counter->counter_dev->dev->class_dev,
156                 "output commands not yet implemented.\n");
157         return -ENOTSUPP;
158 }
159
160 static int ni_tio_cmd_setup(struct comedi_subdevice *s)
161 {
162         struct comedi_cmd *cmd = &s->async->cmd;
163         struct ni_gpct *counter = s->private;
164         unsigned int cidx = counter->counter_index;
165         const struct ni_route_tables *routing_tables =
166                 counter->counter_dev->routing_tables;
167         int set_gate_source = 0;
168         unsigned int gate_source;
169         int retval = 0;
170
171         if (cmd->scan_begin_src == TRIG_EXT) {
172                 set_gate_source = 1;
173                 gate_source = cmd->scan_begin_arg;
174         } else if (cmd->convert_src == TRIG_EXT) {
175                 set_gate_source = 1;
176                 gate_source = cmd->convert_arg;
177         }
178         if (set_gate_source) {
179                 if (CR_CHAN(gate_source) >= NI_NAMES_BASE) {
180                         /* Lookup and use the real register values */
181                         int reg = ni_get_reg_value(CR_CHAN(gate_source),
182                                                    NI_CtrGate(cidx),
183                                                    routing_tables);
184                         if (reg < 0)
185                                 return -EINVAL;
186                         retval = ni_tio_set_gate_src_raw(counter, 0, reg);
187                 } else {
188                         /*
189                          * This function must be used separately since it does
190                          * not expect real register values and attempts to
191                          * convert these to real register values.
192                          */
193                         retval = ni_tio_set_gate_src(counter, 0, gate_source);
194                 }
195         }
196         if (cmd->flags & CMDF_WAKE_EOS) {
197                 ni_tio_set_bits(counter, NITIO_INT_ENA_REG(cidx),
198                                 GI_GATE_INTERRUPT_ENABLE(cidx),
199                                 GI_GATE_INTERRUPT_ENABLE(cidx));
200         }
201         return retval;
202 }
203
204 int ni_tio_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
205 {
206         struct ni_gpct *counter = s->private;
207         struct comedi_async *async = s->async;
208         struct comedi_cmd *cmd = &async->cmd;
209         int retval = 0;
210         unsigned long flags;
211
212         spin_lock_irqsave(&counter->lock, flags);
213         if (!counter->mite_chan) {
214                 dev_err(counter->counter_dev->dev->class_dev,
215                         "commands only supported with DMA.  ");
216                 dev_err(counter->counter_dev->dev->class_dev,
217                         "Interrupt-driven commands not yet implemented.\n");
218                 retval = -EIO;
219         } else {
220                 retval = ni_tio_cmd_setup(s);
221                 if (retval == 0) {
222                         if (cmd->flags & CMDF_WRITE)
223                                 retval = ni_tio_output_cmd(s);
224                         else
225                                 retval = ni_tio_input_cmd(s);
226                 }
227         }
228         spin_unlock_irqrestore(&counter->lock, flags);
229         return retval;
230 }
231 EXPORT_SYMBOL_GPL(ni_tio_cmd);
232
233 int ni_tio_cmdtest(struct comedi_device *dev,
234                    struct comedi_subdevice *s,
235                    struct comedi_cmd *cmd)
236 {
237         struct ni_gpct *counter = s->private;
238         unsigned int cidx = counter->counter_index;
239         const struct ni_route_tables *routing_tables =
240                 counter->counter_dev->routing_tables;
241         int err = 0;
242         unsigned int sources;
243
244         /* Step 1 : check if triggers are trivially valid */
245
246         sources = TRIG_NOW | TRIG_INT | TRIG_OTHER;
247         if (ni_tio_counting_mode_registers_present(counter->counter_dev))
248                 sources |= TRIG_EXT;
249         err |= comedi_check_trigger_src(&cmd->start_src, sources);
250
251         err |= comedi_check_trigger_src(&cmd->scan_begin_src,
252                                         TRIG_FOLLOW | TRIG_EXT | TRIG_OTHER);
253         err |= comedi_check_trigger_src(&cmd->convert_src,
254                                         TRIG_NOW | TRIG_EXT | TRIG_OTHER);
255         err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
256         err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_NONE);
257
258         if (err)
259                 return 1;
260
261         /* Step 2a : make sure trigger sources are unique */
262
263         err |= comedi_check_trigger_is_unique(cmd->start_src);
264         err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
265         err |= comedi_check_trigger_is_unique(cmd->convert_src);
266
267         /* Step 2b : and mutually compatible */
268
269         if (cmd->convert_src != TRIG_NOW && cmd->scan_begin_src != TRIG_FOLLOW)
270                 err |= -EINVAL;
271
272         if (err)
273                 return 2;
274
275         /* Step 3: check if arguments are trivially valid */
276
277         switch (cmd->start_src) {
278         case TRIG_NOW:
279         case TRIG_INT:
280         case TRIG_OTHER:
281                 err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
282                 break;
283         case TRIG_EXT:
284                 /* start_arg is the start_trigger passed to ni_tio_arm() */
285                 /*
286                  * This should be done, but we don't yet know the actual
287                  * register values.  These should be tested and then documented
288                  * in the ni_route_values/ni_*.csv files, with indication of
289                  * who/when/which/how these these were tested.
290                  * When at least a e/m/660x series have been tested, this code
291                  * should be uncommented:
292                  *
293                  * err |= ni_check_trigger_arg(CR_CHAN(cmd->start_arg),
294                  *                          NI_CtrArmStartTrigger(cidx),
295                  *                          routing_tables);
296                  */
297                 break;
298         }
299
300         /*
301          * It seems that convention is to allow either scan_begin_arg or
302          * convert_arg to specify the Gate source, with scan_begin_arg taking
303          * precedence.
304          */
305         if (cmd->scan_begin_src != TRIG_EXT)
306                 err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
307         else
308                 err |= ni_check_trigger_arg(CR_CHAN(cmd->scan_begin_arg),
309                                             NI_CtrGate(cidx), routing_tables);
310
311         if (cmd->convert_src != TRIG_EXT)
312                 err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0);
313         else
314                 err |= ni_check_trigger_arg(CR_CHAN(cmd->convert_arg),
315                                             NI_CtrGate(cidx), routing_tables);
316
317         err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
318                                            cmd->chanlist_len);
319         err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
320
321         if (err)
322                 return 3;
323
324         /* Step 4: fix up any arguments */
325
326         /* Step 5: check channel list if it exists */
327
328         return 0;
329 }
330 EXPORT_SYMBOL_GPL(ni_tio_cmdtest);
331
332 int ni_tio_cancel(struct ni_gpct *counter)
333 {
334         unsigned int cidx = counter->counter_index;
335         unsigned long flags;
336
337         ni_tio_arm(counter, false, 0);
338         spin_lock_irqsave(&counter->lock, flags);
339         if (counter->mite_chan)
340                 mite_dma_disarm(counter->mite_chan);
341         spin_unlock_irqrestore(&counter->lock, flags);
342         ni_tio_configure_dma(counter, false, false);
343
344         ni_tio_set_bits(counter, NITIO_INT_ENA_REG(cidx),
345                         GI_GATE_INTERRUPT_ENABLE(cidx), 0x0);
346         return 0;
347 }
348 EXPORT_SYMBOL_GPL(ni_tio_cancel);
349
350 static int should_ack_gate(struct ni_gpct *counter)
351 {
352         unsigned long flags;
353         int retval = 0;
354
355         switch (counter->counter_dev->variant) {
356         case ni_gpct_variant_m_series:
357         case ni_gpct_variant_660x:
358                 /*
359                  * not sure if 660x really supports gate interrupts
360                  * (the bits are not listed in register-level manual)
361                  */
362                 return 1;
363         case ni_gpct_variant_e_series:
364                 /*
365                  * During buffered input counter operation for e-series,
366                  * the gate interrupt is acked automatically by the dma
367                  * controller, due to the Gi_Read/Write_Acknowledges_IRQ
368                  * bits in the input select register.
369                  */
370                 spin_lock_irqsave(&counter->lock, flags);
371                 {
372                         if (!counter->mite_chan ||
373                             counter->mite_chan->dir != COMEDI_INPUT ||
374                             (mite_done(counter->mite_chan))) {
375                                 retval = 1;
376                         }
377                 }
378                 spin_unlock_irqrestore(&counter->lock, flags);
379                 break;
380         }
381         return retval;
382 }
383
384 static void ni_tio_acknowledge_and_confirm(struct ni_gpct *counter,
385                                            int *gate_error,
386                                            int *tc_error,
387                                            int *perm_stale_data)
388 {
389         unsigned int cidx = counter->counter_index;
390         const unsigned short gxx_status = ni_tio_read(counter,
391                                                 NITIO_SHARED_STATUS_REG(cidx));
392         const unsigned short gi_status = ni_tio_read(counter,
393                                                 NITIO_STATUS_REG(cidx));
394         unsigned int ack = 0;
395
396         if (gate_error)
397                 *gate_error = 0;
398         if (tc_error)
399                 *tc_error = 0;
400         if (perm_stale_data)
401                 *perm_stale_data = 0;
402
403         if (gxx_status & GI_GATE_ERROR(cidx)) {
404                 ack |= GI_GATE_ERROR_CONFIRM(cidx);
405                 if (gate_error) {
406                         /*
407                          * 660x don't support automatic acknowledgment
408                          * of gate interrupt via dma read/write
409                          * and report bogus gate errors
410                          */
411                         if (counter->counter_dev->variant !=
412                             ni_gpct_variant_660x)
413                                 *gate_error = 1;
414                 }
415         }
416         if (gxx_status & GI_TC_ERROR(cidx)) {
417                 ack |= GI_TC_ERROR_CONFIRM(cidx);
418                 if (tc_error)
419                         *tc_error = 1;
420         }
421         if (gi_status & GI_TC)
422                 ack |= GI_TC_INTERRUPT_ACK;
423         if (gi_status & GI_GATE_INTERRUPT) {
424                 if (should_ack_gate(counter))
425                         ack |= GI_GATE_INTERRUPT_ACK;
426         }
427         if (ack)
428                 ni_tio_write(counter, ack, NITIO_INT_ACK_REG(cidx));
429         if (ni_tio_get_soft_copy(counter, NITIO_MODE_REG(cidx)) &
430             GI_LOADING_ON_GATE) {
431                 if (ni_tio_read(counter, NITIO_STATUS2_REG(cidx)) &
432                     GI_PERMANENT_STALE(cidx)) {
433                         dev_info(counter->counter_dev->dev->class_dev,
434                                  "%s: Gi_Permanent_Stale_Data detected.\n",
435                                  __func__);
436                         if (perm_stale_data)
437                                 *perm_stale_data = 1;
438                 }
439         }
440 }
441
442 void ni_tio_acknowledge(struct ni_gpct *counter)
443 {
444         ni_tio_acknowledge_and_confirm(counter, NULL, NULL, NULL);
445 }
446 EXPORT_SYMBOL_GPL(ni_tio_acknowledge);
447
448 void ni_tio_handle_interrupt(struct ni_gpct *counter,
449                              struct comedi_subdevice *s)
450 {
451         unsigned int cidx = counter->counter_index;
452         unsigned long flags;
453         int gate_error;
454         int tc_error;
455         int perm_stale_data;
456
457         ni_tio_acknowledge_and_confirm(counter, &gate_error, &tc_error,
458                                        &perm_stale_data);
459         if (gate_error) {
460                 dev_notice(counter->counter_dev->dev->class_dev,
461                            "%s: Gi_Gate_Error detected.\n", __func__);
462                 s->async->events |= COMEDI_CB_OVERFLOW;
463         }
464         if (perm_stale_data)
465                 s->async->events |= COMEDI_CB_ERROR;
466         switch (counter->counter_dev->variant) {
467         case ni_gpct_variant_m_series:
468         case ni_gpct_variant_660x:
469                 if (ni_tio_read(counter, NITIO_DMA_STATUS_REG(cidx)) &
470                     GI_DRQ_ERROR) {
471                         dev_notice(counter->counter_dev->dev->class_dev,
472                                    "%s: Gi_DRQ_Error detected.\n", __func__);
473                         s->async->events |= COMEDI_CB_OVERFLOW;
474                 }
475                 break;
476         case ni_gpct_variant_e_series:
477                 break;
478         }
479         spin_lock_irqsave(&counter->lock, flags);
480         if (counter->mite_chan)
481                 mite_ack_linkc(counter->mite_chan, s, true);
482         spin_unlock_irqrestore(&counter->lock, flags);
483 }
484 EXPORT_SYMBOL_GPL(ni_tio_handle_interrupt);
485
486 void ni_tio_set_mite_channel(struct ni_gpct *counter,
487                              struct mite_channel *mite_chan)
488 {
489         unsigned long flags;
490
491         spin_lock_irqsave(&counter->lock, flags);
492         counter->mite_chan = mite_chan;
493         spin_unlock_irqrestore(&counter->lock, flags);
494 }
495 EXPORT_SYMBOL_GPL(ni_tio_set_mite_channel);
496
497 static int __init ni_tiocmd_init_module(void)
498 {
499         return 0;
500 }
501 module_init(ni_tiocmd_init_module);
502
503 static void __exit ni_tiocmd_cleanup_module(void)
504 {
505 }
506 module_exit(ni_tiocmd_cleanup_module);
507
508 MODULE_AUTHOR("Comedi <comedi@comedi.org>");
509 MODULE_DESCRIPTION("Comedi command support for NI general-purpose counters");
510 MODULE_LICENSE("GPL");