Lines Matching +full:acquisition +full:- +full:time +full:- +full:ns
1 // SPDX-License-Identifier: GPL-2.0+
9 * COMEDI - Linux Control and Measurement Device Interface
20 * This module is not used directly by end-users. Rather, it is used by other
23 * acquisition. Some drivers also expose the counters for general purpose use.
31 * comedi_device dev->pacer and will be freed by the comedi core during
42 * I8254_MODE1 Hardware retriggerable one-shot
73 * Typically the pacer clock is created by cascading two of the 16-bit counters
74 * to create a 32-bit rate generator (I8254_MODE2). These functions are
79 * ns timing.
83 * clock (in ns).
100 * counters that are used for the cascaded 32-bit pacer.
124 unsigned int reg_offset = (reg * i8254->iosize) << i8254->regshift; in __i8254_read()
127 switch (i8254->iosize) { in __i8254_read()
130 if (i8254->mmio) in __i8254_read()
131 val = readb(i8254->mmio + reg_offset); in __i8254_read()
133 val = inb(i8254->iobase + reg_offset); in __i8254_read()
136 if (i8254->mmio) in __i8254_read()
137 val = readw(i8254->mmio + reg_offset); in __i8254_read()
139 val = inw(i8254->iobase + reg_offset); in __i8254_read()
142 if (i8254->mmio) in __i8254_read()
143 val = readl(i8254->mmio + reg_offset); in __i8254_read()
145 val = inl(i8254->iobase + reg_offset); in __i8254_read()
154 unsigned int reg_offset = (reg * i8254->iosize) << i8254->regshift; in __i8254_write()
156 switch (i8254->iosize) { in __i8254_write()
159 if (i8254->mmio) in __i8254_write()
160 writeb(val, i8254->mmio + reg_offset); in __i8254_write()
162 outb(val, i8254->iobase + reg_offset); in __i8254_write()
165 if (i8254->mmio) in __i8254_write()
166 writew(val, i8254->mmio + reg_offset); in __i8254_write()
168 outw(val, i8254->iobase + reg_offset); in __i8254_write()
171 if (i8254->mmio) in __i8254_write()
172 writel(val, i8254->mmio + reg_offset); in __i8254_write()
174 outl(val, i8254->iobase + reg_offset); in __i8254_write()
180 * comedi_8254_status - return the status of a counter
199 * comedi_8254_read - read the current counter value
223 * comedi_8254_write - load a 16-bit initial counter value
247 * comedi_8254_set_mode - set the mode of a counter
258 return -EINVAL; in comedi_8254_set_mode()
260 return -EINVAL; in comedi_8254_set_mode()
272 * comedi_8254_load - program the mode and initial count of a counter
282 return -EINVAL; in comedi_8254_load()
284 return -EINVAL; in comedi_8254_load()
286 return -EINVAL; in comedi_8254_load()
296 * comedi_8254_pacer_enable - set the mode and load the cascaded counters
326 comedi_8254_write(i8254, counter2, i8254->divisor2); in comedi_8254_pacer_enable()
327 comedi_8254_write(i8254, counter1, i8254->divisor1); in comedi_8254_pacer_enable()
333 * comedi_8254_update_divisors - update the divisors for the cascaded counters
339 i8254->divisor = i8254->next_div & 0xffff; in comedi_8254_update_divisors()
340 i8254->divisor1 = i8254->next_div1 & 0xffff; in comedi_8254_update_divisors()
341 i8254->divisor2 = i8254->next_div2 & 0xffff; in comedi_8254_update_divisors()
346 * comedi_8254_cascade_ns_to_timer - calculate the cascaded divisor values
348 * @nanosec: the desired ns time
355 unsigned int d1 = i8254->next_div1 ? i8254->next_div1 : I8254_MAX_COUNT; in comedi_8254_cascade_ns_to_timer()
356 unsigned int d2 = i8254->next_div2 ? i8254->next_div2 : I8254_MAX_COUNT; in comedi_8254_cascade_ns_to_timer()
365 unsigned int ns; in comedi_8254_cascade_ns_to_timer() local
370 if (div * i8254->osc_base == *nanosec && in comedi_8254_cascade_ns_to_timer()
375 div * i8254->osc_base > div && in comedi_8254_cascade_ns_to_timer()
376 div * i8254->osc_base > i8254->osc_base) in comedi_8254_cascade_ns_to_timer()
379 div = *nanosec / i8254->osc_base; in comedi_8254_cascade_ns_to_timer()
387 ns = i8254->osc_base * d1 * d2; in comedi_8254_cascade_ns_to_timer()
388 if (ns <= *nanosec && ns > ns_glb) { in comedi_8254_cascade_ns_to_timer()
389 ns_glb = ns; in comedi_8254_cascade_ns_to_timer()
393 if (ns >= *nanosec && ns < ns_lub) { in comedi_8254_cascade_ns_to_timer()
394 ns_lub = ns; in comedi_8254_cascade_ns_to_timer()
404 ns_high = d1_lub * d2_lub * i8254->osc_base; in comedi_8254_cascade_ns_to_timer()
405 ns_low = d1_glb * d2_glb * i8254->osc_base; in comedi_8254_cascade_ns_to_timer()
406 if (ns_high - *nanosec < *nanosec - ns_low) { in comedi_8254_cascade_ns_to_timer()
424 *nanosec = d1 * d2 * i8254->osc_base; in comedi_8254_cascade_ns_to_timer()
425 i8254->next_div1 = d1; in comedi_8254_cascade_ns_to_timer()
426 i8254->next_div2 = d2; in comedi_8254_cascade_ns_to_timer()
431 * comedi_8254_ns_to_timer - calculate the divisor value for nanosec timing
433 * @nanosec: the desired ns time
444 divisor = DIV_ROUND_CLOSEST(*nanosec, i8254->osc_base); in comedi_8254_ns_to_timer()
447 divisor = DIV_ROUND_UP(*nanosec, i8254->osc_base); in comedi_8254_ns_to_timer()
450 divisor = *nanosec / i8254->osc_base; in comedi_8254_ns_to_timer()
458 *nanosec = divisor * i8254->osc_base; in comedi_8254_ns_to_timer()
459 i8254->next_div = divisor; in comedi_8254_ns_to_timer()
464 * comedi_8254_set_busy - set/clear the "busy" flag for a given counter
473 i8254->busy[counter] = busy; in comedi_8254_set_busy()
482 struct comedi_8254 *i8254 = s->private; in comedi_8254_insn_read()
483 unsigned int chan = CR_CHAN(insn->chanspec); in comedi_8254_insn_read()
486 if (i8254->busy[chan]) in comedi_8254_insn_read()
487 return -EBUSY; in comedi_8254_insn_read()
489 for (i = 0; i < insn->n; i++) in comedi_8254_insn_read()
492 return insn->n; in comedi_8254_insn_read()
500 struct comedi_8254 *i8254 = s->private; in comedi_8254_insn_write()
501 unsigned int chan = CR_CHAN(insn->chanspec); in comedi_8254_insn_write()
503 if (i8254->busy[chan]) in comedi_8254_insn_write()
504 return -EBUSY; in comedi_8254_insn_write()
506 if (insn->n) in comedi_8254_insn_write()
507 comedi_8254_write(i8254, chan, data[insn->n - 1]); in comedi_8254_insn_write()
509 return insn->n; in comedi_8254_insn_write()
517 struct comedi_8254 *i8254 = s->private; in comedi_8254_insn_config()
518 unsigned int chan = CR_CHAN(insn->chanspec); in comedi_8254_insn_config()
521 if (i8254->busy[chan]) in comedi_8254_insn_config()
522 return -EBUSY; in comedi_8254_insn_config()
544 if (i8254->insn_config) in comedi_8254_insn_config()
545 return i8254->insn_config(dev, s, insn, data); in comedi_8254_insn_config()
547 return -EINVAL; in comedi_8254_insn_config()
550 return insn->n; in comedi_8254_insn_config()
554 * comedi_8254_subdevice_init - initialize a comedi_subdevice for the 8254 timer
561 s->type = COMEDI_SUBD_COUNTER; in comedi_8254_subdevice_init()
562 s->subdev_flags = SDF_READABLE | SDF_WRITABLE; in comedi_8254_subdevice_init()
563 s->n_chan = 3; in comedi_8254_subdevice_init()
564 s->maxdata = 0xffff; in comedi_8254_subdevice_init()
565 s->range_table = &range_unknown; in comedi_8254_subdevice_init()
566 s->insn_read = comedi_8254_insn_read; in comedi_8254_subdevice_init()
567 s->insn_write = comedi_8254_insn_write; in comedi_8254_subdevice_init()
568 s->insn_config = comedi_8254_insn_config; in comedi_8254_subdevice_init()
570 s->private = i8254; in comedi_8254_subdevice_init()
592 i8254->iobase = iobase; in __i8254_init()
593 i8254->mmio = mmio; in __i8254_init()
594 i8254->iosize = iosize; in __i8254_init()
595 i8254->regshift = regshift; in __i8254_init()
598 i8254->osc_base = osc_base ? osc_base : I8254_OSC_BASE_10MHZ; in __i8254_init()
608 * comedi_8254_init - allocate and initialize the 8254 device for pio access
610 * @osc_base: base time of the counter in ns
611 * OPTIONAL - only used by comedi_8254_cascade_ns_to_timer()
625 * comedi_8254_mm_init - allocate and initialize the 8254 device for mmio access
627 * @osc_base: base time of the counter in ns
628 * OPTIONAL - only used by comedi_8254_cascade_ns_to_timer()