Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0+ */
0002 /*
0003  * comedi_8254.h
0004  * Generic 8254 timer/counter support
0005  * Copyright (C) 2014 H Hartley Sweeten <hsweeten@visionengravers.com>
0006  *
0007  * COMEDI - Linux Control and Measurement Device Interface
0008  * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
0009  */
0010 
0011 #ifndef _COMEDI_8254_H
0012 #define _COMEDI_8254_H
0013 
0014 #include <linux/types.h>
0015 
0016 struct comedi_device;
0017 struct comedi_insn;
0018 struct comedi_subdevice;
0019 
0020 /*
0021  * Common oscillator base values in nanoseconds
0022  */
0023 #define I8254_OSC_BASE_10MHZ    100
0024 #define I8254_OSC_BASE_5MHZ 200
0025 #define I8254_OSC_BASE_4MHZ 250
0026 #define I8254_OSC_BASE_2MHZ 500
0027 #define I8254_OSC_BASE_1MHZ 1000
0028 #define I8254_OSC_BASE_100KHZ   10000
0029 #define I8254_OSC_BASE_10KHZ    100000
0030 #define I8254_OSC_BASE_1KHZ 1000000
0031 
0032 /*
0033  * I/O access size used to read/write registers
0034  */
0035 #define I8254_IO8       1
0036 #define I8254_IO16      2
0037 #define I8254_IO32      4
0038 
0039 /*
0040  * Register map for generic 8254 timer (I8254_IO8 with 0 regshift)
0041  */
0042 #define I8254_COUNTER0_REG      0x00
0043 #define I8254_COUNTER1_REG      0x01
0044 #define I8254_COUNTER2_REG      0x02
0045 #define I8254_CTRL_REG          0x03
0046 #define I8254_CTRL_SEL_CTR(x)       ((x) << 6)
0047 #define I8254_CTRL_READBACK(x)      (I8254_CTRL_SEL_CTR(3) | BIT(x))
0048 #define I8254_CTRL_READBACK_COUNT   I8254_CTRL_READBACK(4)
0049 #define I8254_CTRL_READBACK_STATUS  I8254_CTRL_READBACK(5)
0050 #define I8254_CTRL_READBACK_SEL_CTR(x)  (2 << (x))
0051 #define I8254_CTRL_RW(x)        (((x) & 0x3) << 4)
0052 #define I8254_CTRL_LATCH        I8254_CTRL_RW(0)
0053 #define I8254_CTRL_LSB_ONLY     I8254_CTRL_RW(1)
0054 #define I8254_CTRL_MSB_ONLY     I8254_CTRL_RW(2)
0055 #define I8254_CTRL_LSB_MSB      I8254_CTRL_RW(3)
0056 
0057 /* counter maps zero to 0x10000 */
0058 #define I8254_MAX_COUNT         0x10000
0059 
0060 /**
0061  * struct comedi_8254 - private data used by this module
0062  * @iobase:     PIO base address of the registers (in/out)
0063  * @mmio:       MMIO base address of the registers (read/write)
0064  * @iosize:     I/O size used to access the registers (b/w/l)
0065  * @regshift:       register gap shift
0066  * @osc_base:       cascaded oscillator speed in ns
0067  * @divisor:        divisor for single counter
0068  * @divisor1:       divisor loaded into first cascaded counter
0069  * @divisor2:       divisor loaded into second cascaded counter
0070  * #next_div:       next divisor for single counter
0071  * @next_div1:      next divisor to use for first cascaded counter
0072  * @next_div2:      next divisor to use for second cascaded counter
0073  * @clock_src;      current clock source for each counter (driver specific)
0074  * @gate_src;       current gate source  for each counter (driver specific)
0075  * @busy:       flags used to indicate that a counter is "busy"
0076  * @insn_config:    driver specific (*insn_config) callback
0077  */
0078 struct comedi_8254 {
0079     unsigned long iobase;
0080     void __iomem *mmio;
0081     unsigned int iosize;
0082     unsigned int regshift;
0083     unsigned int osc_base;
0084     unsigned int divisor;
0085     unsigned int divisor1;
0086     unsigned int divisor2;
0087     unsigned int next_div;
0088     unsigned int next_div1;
0089     unsigned int next_div2;
0090     unsigned int clock_src[3];
0091     unsigned int gate_src[3];
0092     bool busy[3];
0093 
0094     int (*insn_config)(struct comedi_device *dev,
0095                struct comedi_subdevice *s,
0096                struct comedi_insn *insn, unsigned int *data);
0097 };
0098 
0099 unsigned int comedi_8254_status(struct comedi_8254 *i8254,
0100                 unsigned int counter);
0101 unsigned int comedi_8254_read(struct comedi_8254 *i8254, unsigned int counter);
0102 void comedi_8254_write(struct comedi_8254 *i8254,
0103                unsigned int counter, unsigned int val);
0104 
0105 int comedi_8254_set_mode(struct comedi_8254 *i8254,
0106              unsigned int counter, unsigned int mode);
0107 int comedi_8254_load(struct comedi_8254 *i8254,
0108              unsigned int counter, unsigned int val, unsigned int mode);
0109 
0110 void comedi_8254_pacer_enable(struct comedi_8254 *i8254,
0111                   unsigned int counter1, unsigned int counter2,
0112                   bool enable);
0113 void comedi_8254_update_divisors(struct comedi_8254 *i8254);
0114 void comedi_8254_cascade_ns_to_timer(struct comedi_8254 *i8254,
0115                      unsigned int *nanosec, unsigned int flags);
0116 void comedi_8254_ns_to_timer(struct comedi_8254 *i8254,
0117                  unsigned int *nanosec, unsigned int flags);
0118 
0119 void comedi_8254_set_busy(struct comedi_8254 *i8254,
0120               unsigned int counter, bool busy);
0121 
0122 void comedi_8254_subdevice_init(struct comedi_subdevice *s,
0123                 struct comedi_8254 *i8254);
0124 
0125 struct comedi_8254 *comedi_8254_init(unsigned long iobase,
0126                      unsigned int osc_base,
0127                      unsigned int iosize,
0128                      unsigned int regshift);
0129 struct comedi_8254 *comedi_8254_mm_init(void __iomem *mmio,
0130                     unsigned int osc_base,
0131                     unsigned int iosize,
0132                     unsigned int regshift);
0133 
0134 #endif  /* _COMEDI_8254_H */