Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / drivers / staging / comedi / drivers / comedi_8254.c
1 /*
2  * comedi_8254.c
3  * Generic 8254 timer/counter support
4  * Copyright (C) 2014 H Hartley Sweeten <hsweeten@visionengravers.com>
5  *
6  * Based on 8253.h and various subdevice implementations in comedi drivers.
7  *
8  * COMEDI - Linux Control and Measurement Device Interface
9  * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  */
21
22 /*
23  * Module: comedi_8254
24  * Description: Generic 8254 timer/counter support
25  * Author: H Hartley Sweeten <hsweeten@visionengravers.com>
26  * Updated: Thu Jan 8 16:45:45 MST 2015
27  * Status: works
28  *
29  * This module is not used directly by end-users. Rather, it is used by other
30  * drivers to provide support for an 8254 Programmable Interval Timer. These
31  * counters are typically used to generate the pacer clock used for data
32  * acquisition. Some drivers also expose the counters for general purpose use.
33  *
34  * This module provides the following basic functions:
35  *
36  * comedi_8254_init() / comedi_8254_mm_init()
37  *      Initializes this module to access the 8254 registers. The _mm version
38  *      sets up the module for MMIO register access the other for PIO access.
39  *      The pointer returned from these functions is normally stored in the
40  *      comedi_device dev->pacer and will be freed by the comedi core during
41  *      the driver (*detach). If a driver has multiple 8254 devices, they need
42  *      to be stored in the drivers private data and freed when the driver is
43  *      detached.
44  *
45  *      NOTE: The counters are reset by setting them to I8254_MODE0 as part of
46  *      this initialization.
47  *
48  * comedi_8254_set_mode()
49  *      Sets a counters operation mode:
50  *              I8254_MODE0     Interrupt on terminal count
51  *              I8254_MODE1     Hardware retriggerable one-shot
52  *              I8254_MODE2     Rate generator
53  *              I8254_MODE3     Square wave mode
54  *              I8254_MODE4     Software triggered strobe
55  *              I8254_MODE5     Hardware triggered strobe (retriggerable)
56  *
57  *      In addition I8254_BCD and I8254_BINARY specify the counting mode:
58  *              I8254_BCD       BCD counting
59  *              I8254_BINARY    Binary counting
60  *
61  * comedi_8254_write()
62  *      Writes an initial value to a counter.
63  *
64  *      The largest possible initial count is 0; this is equivalent to 2^16
65  *      for binary counting and 10^4 for BCD counting.
66  *
67  *      NOTE: The counter does not stop when it reaches zero. In Mode 0, 1, 4,
68  *      and 5 the counter "wraps around" to the highest count, either 0xffff
69  *      for binary counting or 9999 for BCD counting, and continues counting.
70  *      Modes 2 and 3 are periodic; the counter reloads itself with the initial
71  *      count and continues counting from there.
72  *
73  * comedi_8254_read()
74  *      Reads the current value from a counter.
75  *
76  * comedi_8254_status()
77  *      Reads the status of a counter.
78  *
79  * comedi_8254_load()
80  *      Sets a counters operation mode and writes the initial value.
81  *
82  * Typically the pacer clock is created by cascading two of the 16-bit counters
83  * to create a 32-bit rate generator (I8254_MODE2). These functions are
84  * provided to handle the cascaded counters:
85  *
86  * comedi_8254_ns_to_timer()
87  *      Calculates the divisor value needed for a single counter to generate
88  *      ns timing.
89  *
90  * comedi_8254_cascade_ns_to_timer()
91  *      Calculates the two divisor values needed to the generate the pacer
92  *      clock (in ns).
93  *
94  * comedi_8254_update_divisors()
95  *      Transfers the intermediate divisor values to the current divisors.
96  *
97  * comedi_8254_pacer_enable()
98  *      Programs the mode of the cascaded counters and writes the current
99  *      divisor values.
100  *
101  * To expose the counters as a subdevice for general purpose use the following
102  * functions a provided:
103  *
104  * comedi_8254_subdevice_init()
105  *      Initializes a comedi_subdevice to use the 8254 timer.
106  *
107  * comedi_8254_set_busy()
108  *      Internally flags a counter as "busy". This is done to protect the
109  *      counters that are used for the cascaded 32-bit pacer.
110  *
111  * The subdevice provides (*insn_read) and (*insn_write) operations to read
112  * the current value and write an initial value to a counter. A (*insn_config)
113  * operation is also provided to handle the following comedi instructions:
114  *
115  *      INSN_CONFIG_SET_COUNTER_MODE    calls comedi_8254_set_mode()
116  *      INSN_CONFIG_8254_READ_STATUS    calls comedi_8254_status()
117  *
118  * The (*insn_config) member of comedi_8254 can be initialized by the external
119  * driver to handle any additional instructions.
120  *
121  * NOTE: Gate control, clock routing, and any interrupt handling for the
122  * counters is not handled by this module. These features are driver dependent.
123  */
124
125 #include <linux/module.h>
126 #include <linux/slab.h>
127 #include <linux/io.h>
128
129 #include "../comedidev.h"
130
131 #include "comedi_8254.h"
132
133 static unsigned int __i8254_read(struct comedi_8254 *i8254, unsigned int reg)
134 {
135         unsigned int reg_offset = (reg * i8254->iosize) << i8254->regshift;
136         unsigned int val;
137
138         switch (i8254->iosize) {
139         default:
140         case I8254_IO8:
141                 if (i8254->mmio)
142                         val = readb(i8254->mmio + reg_offset);
143                 else
144                         val = inb(i8254->iobase + reg_offset);
145                 break;
146         case I8254_IO16:
147                 if (i8254->mmio)
148                         val = readw(i8254->mmio + reg_offset);
149                 else
150                         val = inw(i8254->iobase + reg_offset);
151                 break;
152         case I8254_IO32:
153                 if (i8254->mmio)
154                         val = readl(i8254->mmio + reg_offset);
155                 else
156                         val = inl(i8254->iobase + reg_offset);
157                 break;
158         }
159         return val & 0xff;
160 }
161
162 static void __i8254_write(struct comedi_8254 *i8254,
163                           unsigned int val, unsigned int reg)
164 {
165         unsigned int reg_offset = (reg * i8254->iosize) << i8254->regshift;
166
167         switch (i8254->iosize) {
168         default:
169         case I8254_IO8:
170                 if (i8254->mmio)
171                         writeb(val, i8254->mmio + reg_offset);
172                 else
173                         outb(val, i8254->iobase + reg_offset);
174                 break;
175         case I8254_IO16:
176                 if (i8254->mmio)
177                         writew(val, i8254->mmio + reg_offset);
178                 else
179                         outw(val, i8254->iobase + reg_offset);
180                 break;
181         case I8254_IO32:
182                 if (i8254->mmio)
183                         writel(val, i8254->mmio + reg_offset);
184                 else
185                         outl(val, i8254->iobase + reg_offset);
186                 break;
187         }
188 }
189
190 /**
191  * comedi_8254_status - return the status of a counter
192  * @i8254:      comedi_8254 struct for the timer
193  * @counter:    the counter number
194  */
195 unsigned int comedi_8254_status(struct comedi_8254 *i8254, unsigned int counter)
196 {
197         unsigned int cmd;
198
199         if (counter > 2)
200                 return 0;
201
202         cmd = I8254_CTRL_READBACK_STATUS | I8254_CTRL_READBACK_SEL_CTR(counter);
203         __i8254_write(i8254, cmd, I8254_CTRL_REG);
204
205         return __i8254_read(i8254, counter);
206 }
207 EXPORT_SYMBOL_GPL(comedi_8254_status);
208
209 /**
210  * comedi_8254_read - read the current counter value
211  * @i8254:      comedi_8254 struct for the timer
212  * @counter:    the counter number
213  */
214 unsigned int comedi_8254_read(struct comedi_8254 *i8254, unsigned int counter)
215 {
216         unsigned int val;
217
218         if (counter > 2)
219                 return 0;
220
221         /* latch counter */
222         __i8254_write(i8254, I8254_CTRL_SEL_CTR(counter) | I8254_CTRL_LATCH,
223                       I8254_CTRL_REG);
224
225         /* read LSB then MSB */
226         val = __i8254_read(i8254, counter);
227         val |= (__i8254_read(i8254, counter) << 8);
228
229         return val;
230 }
231 EXPORT_SYMBOL_GPL(comedi_8254_read);
232
233 /**
234  * comedi_8254_write - load a 16-bit initial counter value
235  * @i8254:      comedi_8254 struct for the timer
236  * @counter:    the counter number
237  * @val:        the initial value
238  */
239 void comedi_8254_write(struct comedi_8254 *i8254,
240                        unsigned int counter, unsigned int val)
241 {
242         unsigned int byte;
243
244         if (counter > 2)
245                 return;
246         if (val > 0xffff)
247                 return;
248
249         /* load LSB then MSB */
250         byte = val & 0xff;
251         __i8254_write(i8254, byte, counter);
252         byte = (val >> 8) & 0xff;
253         __i8254_write(i8254, byte, counter);
254 }
255 EXPORT_SYMBOL_GPL(comedi_8254_write);
256
257 /**
258  * comedi_8254_set_mode - set the mode of a counter
259  * @i8254:      comedi_8254 struct for the timer
260  * @counter:    the counter number
261  * @mode:       the I8254_MODEx and I8254_BCD|I8254_BINARY
262  */
263 int comedi_8254_set_mode(struct comedi_8254 *i8254, unsigned int counter,
264                          unsigned int mode)
265 {
266         unsigned int byte;
267
268         if (counter > 2)
269                 return -EINVAL;
270         if (mode > (I8254_MODE5 | I8254_BCD))
271                 return -EINVAL;
272
273         byte = I8254_CTRL_SEL_CTR(counter) |    /* select counter */
274                I8254_CTRL_LSB_MSB |             /* load LSB then MSB */
275                mode;                            /* mode and BCD|binary */
276         __i8254_write(i8254, byte, I8254_CTRL_REG);
277
278         return 0;
279 }
280 EXPORT_SYMBOL_GPL(comedi_8254_set_mode);
281
282 /**
283  * comedi_8254_load - program the mode and initial count of a counter
284  * @i8254:      comedi_8254 struct for the timer
285  * @counter:    the counter number
286  * @mode:       the I8254_MODEx and I8254_BCD|I8254_BINARY
287  * @val:        the initial value
288  */
289 int comedi_8254_load(struct comedi_8254 *i8254, unsigned int counter,
290                      unsigned int val, unsigned int mode)
291 {
292         if (counter > 2)
293                 return -EINVAL;
294         if (val > 0xffff)
295                 return -EINVAL;
296         if (mode > (I8254_MODE5 | I8254_BCD))
297                 return -EINVAL;
298
299         comedi_8254_set_mode(i8254, counter, mode);
300         comedi_8254_write(i8254, counter, val);
301
302         return 0;
303 }
304 EXPORT_SYMBOL_GPL(comedi_8254_load);
305
306 /**
307  * comedi_8254_pacer_enable - set the mode and load the cascaded counters
308  * @i8254:      comedi_8254 struct for the timer
309  * @counter1:   the counter number for the first divisor
310  * @counter2:   the counter number for the second divisor
311  * @enable:     flag to enable (load) the counters
312  */
313 void comedi_8254_pacer_enable(struct comedi_8254 *i8254,
314                               unsigned int counter1,
315                               unsigned int counter2,
316                               bool enable)
317 {
318         unsigned int mode;
319
320         if (counter1 > 2 || counter2 > 2 || counter1 == counter2)
321                 return;
322
323         if (enable)
324                 mode = I8254_MODE2 | I8254_BINARY;
325         else
326                 mode = I8254_MODE0 | I8254_BINARY;
327
328         comedi_8254_set_mode(i8254, counter1, mode);
329         comedi_8254_set_mode(i8254, counter2, mode);
330
331         if (enable) {
332                 /*
333                  * Divisors are loaded second counter then first counter to
334                  * avoid possible issues with the first counter expiring
335                  * before the second counter is loaded.
336                  */
337                 comedi_8254_write(i8254, counter2, i8254->divisor2);
338                 comedi_8254_write(i8254, counter1, i8254->divisor1);
339         }
340 }
341 EXPORT_SYMBOL_GPL(comedi_8254_pacer_enable);
342
343 /**
344  * comedi_8254_update_divisors - update the divisors for the cascaded counters
345  * @i8254:      comedi_8254 struct for the timer
346  */
347 void comedi_8254_update_divisors(struct comedi_8254 *i8254)
348 {
349         /* masking is done since counter maps zero to 0x10000 */
350         i8254->divisor = i8254->next_div & 0xffff;
351         i8254->divisor1 = i8254->next_div1 & 0xffff;
352         i8254->divisor2 = i8254->next_div2 & 0xffff;
353 }
354 EXPORT_SYMBOL_GPL(comedi_8254_update_divisors);
355
356 /**
357  * comedi_8254_cascade_ns_to_timer - calculate the cascaded divisor values
358  * @i8254:      comedi_8254 struct for the timer
359  * @nanosec:    the desired ns time
360  * @flags:      comedi_cmd flags
361  */
362 void comedi_8254_cascade_ns_to_timer(struct comedi_8254 *i8254,
363                                      unsigned int *nanosec,
364                                      unsigned int flags)
365 {
366         unsigned int d1 = i8254->next_div1 ? i8254->next_div1 : I8254_MAX_COUNT;
367         unsigned int d2 = i8254->next_div2 ? i8254->next_div2 : I8254_MAX_COUNT;
368         unsigned int div = d1 * d2;
369         unsigned int ns_lub = 0xffffffff;
370         unsigned int ns_glb = 0;
371         unsigned int d1_lub = 0;
372         unsigned int d1_glb = 0;
373         unsigned int d2_lub = 0;
374         unsigned int d2_glb = 0;
375         unsigned int start;
376         unsigned int ns;
377         unsigned int ns_low;
378         unsigned int ns_high;
379
380         /* exit early if everything is already correct */
381         if (div * i8254->osc_base == *nanosec &&
382             d1 > 1 && d1 <= I8254_MAX_COUNT &&
383             d2 > 1 && d2 <= I8254_MAX_COUNT &&
384             /* check for overflow */
385             div > d1 && div > d2 &&
386             div * i8254->osc_base > div &&
387             div * i8254->osc_base > i8254->osc_base)
388                 return;
389
390         div = *nanosec / i8254->osc_base;
391         d2 = I8254_MAX_COUNT;
392         start = div / d2;
393         if (start < 2)
394                 start = 2;
395         for (d1 = start; d1 <= div / d1 + 1 && d1 <= I8254_MAX_COUNT; d1++) {
396                 for (d2 = div / d1;
397                      d1 * d2 <= div + d1 + 1 && d2 <= I8254_MAX_COUNT; d2++) {
398                         ns = i8254->osc_base * d1 * d2;
399                         if (ns <= *nanosec && ns > ns_glb) {
400                                 ns_glb = ns;
401                                 d1_glb = d1;
402                                 d2_glb = d2;
403                         }
404                         if (ns >= *nanosec && ns < ns_lub) {
405                                 ns_lub = ns;
406                                 d1_lub = d1;
407                                 d2_lub = d2;
408                         }
409                 }
410         }
411
412         switch (flags & CMDF_ROUND_MASK) {
413         case CMDF_ROUND_NEAREST:
414         default:
415                 ns_high = d1_lub * d2_lub * i8254->osc_base;
416                 ns_low = d1_glb * d2_glb * i8254->osc_base;
417                 if (ns_high - *nanosec < *nanosec - ns_low) {
418                         d1 = d1_lub;
419                         d2 = d2_lub;
420                 } else {
421                         d1 = d1_glb;
422                         d2 = d2_glb;
423                 }
424                 break;
425         case CMDF_ROUND_UP:
426                 d1 = d1_lub;
427                 d2 = d2_lub;
428                 break;
429         case CMDF_ROUND_DOWN:
430                 d1 = d1_glb;
431                 d2 = d2_glb;
432                 break;
433         }
434
435         *nanosec = d1 * d2 * i8254->osc_base;
436         i8254->next_div1 = d1;
437         i8254->next_div2 = d2;
438 }
439 EXPORT_SYMBOL_GPL(comedi_8254_cascade_ns_to_timer);
440
441 /**
442  * comedi_8254_ns_to_timer - calculate the divisor value for nanosec timing
443  * @i8254:      comedi_8254 struct for the timer
444  * @nanosec:    the desired ns time
445  * @flags:      comedi_cmd flags
446  */
447 void comedi_8254_ns_to_timer(struct comedi_8254 *i8254,
448                              unsigned int *nanosec, unsigned int flags)
449 {
450         unsigned int divisor;
451
452         switch (flags & CMDF_ROUND_MASK) {
453         default:
454         case CMDF_ROUND_NEAREST:
455                 divisor = DIV_ROUND_CLOSEST(*nanosec, i8254->osc_base);
456                 break;
457         case CMDF_ROUND_UP:
458                 divisor = DIV_ROUND_UP(*nanosec, i8254->osc_base);
459                 break;
460         case CMDF_ROUND_DOWN:
461                 divisor = *nanosec / i8254->osc_base;
462                 break;
463         }
464         if (divisor < 2)
465                 divisor = 2;
466         if (divisor > I8254_MAX_COUNT)
467                 divisor = I8254_MAX_COUNT;
468
469         *nanosec = divisor * i8254->osc_base;
470         i8254->next_div = divisor;
471 }
472 EXPORT_SYMBOL_GPL(comedi_8254_ns_to_timer);
473
474 /**
475  * comedi_8254_set_busy - set/clear the "busy" flag for a given counter
476  * @i8254:      comedi_8254 struct for the timer
477  * @counter:    the counter number
478  * @busy:       set/clear flag
479  */
480 void comedi_8254_set_busy(struct comedi_8254 *i8254,
481                           unsigned int counter, bool busy)
482 {
483         if (counter < 3)
484                 i8254->busy[counter] = busy;
485 }
486 EXPORT_SYMBOL_GPL(comedi_8254_set_busy);
487
488 static int comedi_8254_insn_read(struct comedi_device *dev,
489                                  struct comedi_subdevice *s,
490                                  struct comedi_insn *insn,
491                                  unsigned int *data)
492 {
493         struct comedi_8254 *i8254 = s->private;
494         unsigned int chan = CR_CHAN(insn->chanspec);
495         int i;
496
497         if (i8254->busy[chan])
498                 return -EBUSY;
499
500         for (i = 0; i < insn->n; i++)
501                 data[i] = comedi_8254_read(i8254, chan);
502
503         return insn->n;
504 }
505
506 static int comedi_8254_insn_write(struct comedi_device *dev,
507                                   struct comedi_subdevice *s,
508                                   struct comedi_insn *insn,
509                                   unsigned int *data)
510 {
511         struct comedi_8254 *i8254 = s->private;
512         unsigned int chan = CR_CHAN(insn->chanspec);
513
514         if (i8254->busy[chan])
515                 return -EBUSY;
516
517         if (insn->n)
518                 comedi_8254_write(i8254, chan, data[insn->n - 1]);
519
520         return insn->n;
521 }
522
523 static int comedi_8254_insn_config(struct comedi_device *dev,
524                                    struct comedi_subdevice *s,
525                                    struct comedi_insn *insn,
526                                    unsigned int *data)
527 {
528         struct comedi_8254 *i8254 = s->private;
529         unsigned int chan = CR_CHAN(insn->chanspec);
530         int ret;
531
532         if (i8254->busy[chan])
533                 return -EBUSY;
534
535         switch (data[0]) {
536         case INSN_CONFIG_RESET:
537                 ret = comedi_8254_set_mode(i8254, chan,
538                                            I8254_MODE0 | I8254_BINARY);
539                 if (ret)
540                         return ret;
541                 break;
542         case INSN_CONFIG_SET_COUNTER_MODE:
543                 ret = comedi_8254_set_mode(i8254, chan, data[1]);
544                 if (ret)
545                         return ret;
546                 break;
547         case INSN_CONFIG_8254_READ_STATUS:
548                 data[1] = comedi_8254_status(i8254, chan);
549                 break;
550         default:
551                 /*
552                  * If available, call the driver provided (*insn_config)
553                  * to handle any driver implemented instructions.
554                  */
555                 if (i8254->insn_config)
556                         return i8254->insn_config(dev, s, insn, data);
557
558                 return -EINVAL;
559         }
560
561         return insn->n;
562 }
563
564 /**
565  * comedi_8254_subdevice_init - initialize a comedi_subdevice for the 8254 timer
566  * @s:          comedi_subdevice struct
567  */
568 void comedi_8254_subdevice_init(struct comedi_subdevice *s,
569                                 struct comedi_8254 *i8254)
570 {
571         s->type         = COMEDI_SUBD_COUNTER;
572         s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
573         s->n_chan       = 3;
574         s->maxdata      = 0xffff;
575         s->range_table  = &range_unknown;
576         s->insn_read    = comedi_8254_insn_read;
577         s->insn_write   = comedi_8254_insn_write;
578         s->insn_config  = comedi_8254_insn_config;
579
580         s->private      = i8254;
581 }
582 EXPORT_SYMBOL_GPL(comedi_8254_subdevice_init);
583
584 static struct comedi_8254 *__i8254_init(unsigned long iobase,
585                                         void __iomem *mmio,
586                                         unsigned int osc_base,
587                                         unsigned int iosize,
588                                         unsigned int regshift)
589 {
590         struct comedi_8254 *i8254;
591         int i;
592
593         /* sanity check that the iosize is valid */
594         if (!(iosize == I8254_IO8 || iosize == I8254_IO16 ||
595               iosize == I8254_IO32))
596                 return NULL;
597
598         i8254 = kzalloc(sizeof(*i8254), GFP_KERNEL);
599         if (!i8254)
600                 return NULL;
601
602         i8254->iobase   = iobase;
603         i8254->mmio     = mmio;
604         i8254->iosize   = iosize;
605         i8254->regshift = regshift;
606
607         /* default osc_base to the max speed of a generic 8254 timer */
608         i8254->osc_base = osc_base ? osc_base : I8254_OSC_BASE_10MHZ;
609
610         /* reset all the counters by setting them to I8254_MODE0 */
611         for (i = 0; i < 3; i++)
612                 comedi_8254_set_mode(i8254, i, I8254_MODE0 | I8254_BINARY);
613
614         return i8254;
615 }
616
617 /**
618  * comedi_8254_init - allocate and initialize the 8254 device for pio access
619  * @mmio:       port I/O base address
620  * @osc_base:   base time of the counter in ns
621  *              OPTIONAL - only used by comedi_8254_cascade_ns_to_timer()
622  * @iosize:     I/O register size
623  * @regshift:   register gap shift
624  */
625 struct comedi_8254 *comedi_8254_init(unsigned long iobase,
626                                      unsigned int osc_base,
627                                      unsigned int iosize,
628                                      unsigned int regshift)
629 {
630         return __i8254_init(iobase, NULL, osc_base, iosize, regshift);
631 }
632 EXPORT_SYMBOL_GPL(comedi_8254_init);
633
634 /**
635  * comedi_8254_mm_init - allocate and initialize the 8254 device for mmio access
636  * @mmio:       memory mapped I/O base address
637  * @osc_base:   base time of the counter in ns
638  *              OPTIONAL - only used by comedi_8254_cascade_ns_to_timer()
639  * @iosize:     I/O register size
640  * @regshift:   register gap shift
641  */
642 struct comedi_8254 *comedi_8254_mm_init(void __iomem *mmio,
643                                         unsigned int osc_base,
644                                         unsigned int iosize,
645                                         unsigned int regshift)
646 {
647         return __i8254_init(0, mmio, osc_base, iosize, regshift);
648 }
649 EXPORT_SYMBOL_GPL(comedi_8254_mm_init);
650
651 static int __init comedi_8254_module_init(void)
652 {
653         return 0;
654 }
655 module_init(comedi_8254_module_init);
656
657 static void __exit comedi_8254_module_exit(void)
658 {
659 }
660 module_exit(comedi_8254_module_exit);
661
662 MODULE_AUTHOR("H Hartley Sweeten <hsweeten@visionengravers.com>");
663 MODULE_DESCRIPTION("Comedi: Generic 8254 timer/counter support");
664 MODULE_LICENSE("GPL");