root/drivers/staging/comedi/drivers/ni_tiocmd.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ni_tio_configure_dma
  2. ni_tio_input_inttrig
  3. ni_tio_input_cmd
  4. ni_tio_output_cmd
  5. ni_tio_cmd_setup
  6. ni_tio_cmd
  7. ni_tio_cmdtest
  8. ni_tio_cancel
  9. should_ack_gate
  10. ni_tio_acknowledge_and_confirm
  11. ni_tio_acknowledge
  12. ni_tio_handle_interrupt
  13. ni_tio_set_mite_channel
  14. ni_tiocmd_init_module
  15. ni_tiocmd_cleanup_module

   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");

/* [<][>][^][v][top][bottom][index][help] */