blob: 375707497896f65fc562fdc1c35e4e5f67732f5d [file] [log] [blame]
H Hartley Sweetenc919d712012-10-30 16:57:59 -07001/* Watchdog Related Defines */
2
H Hartley Sweetenc919d712012-10-30 16:57:59 -07003#define ADDIDATA_TIMER 0
4#define ADDIDATA_WATCHDOG 2
5
ADDI-DATA GmbHc995fe92009-02-12 15:14:18 -08006/*
H Hartley Sweeten1ef0cfb2013-01-23 12:46:45 -07007 * (*insn_config) for the timer subdevice
8 *
9 * Configures The Timer, Counter or Watchdog
10 * Data Pointer contains configuration parameters as below
11 * data[0] : 0 Configure As Timer
12 * 1 Configure As Counter
13 * 2 Configure As Watchdog
14 * data[1] : 1 Enable Interrupt
15 * 0 Disable Interrupt
16 * data[2] : Time Unit
17 * data[3] : Reload Value
18 */
Fred Akers805077b2014-03-11 18:19:12 -040019static int apci3501_config_insn_timer(struct comedi_device *dev,
20 struct comedi_subdevice *s,
21 struct comedi_insn *insn,
22 unsigned int *data)
ADDI-DATA GmbHc995fe92009-02-12 15:14:18 -080023{
H Hartley Sweeten015aebe2013-01-23 12:43:14 -070024 struct apci3501_private *devpriv = dev->private;
H Hartley Sweetenc85c26b2015-08-12 13:25:42 -070025 unsigned int ctrl;
26
27 if (data[0] != ADDIDATA_WATCHDOG &&
28 data[0] != ADDIDATA_TIMER)
29 return -EINVAL;
H Hartley Sweeten843690b2012-10-15 10:15:05 -070030
ADDI-DATA GmbHc995fe92009-02-12 15:14:18 -080031 devpriv->tsk_Current = current;
ADDI-DATA GmbHc995fe92009-02-12 15:14:18 -080032
H Hartley Sweetenc85c26b2015-08-12 13:25:42 -070033 devpriv->timer_mode = data[0];
ADDI-DATA GmbHc995fe92009-02-12 15:14:18 -080034
H Hartley Sweetenc85c26b2015-08-12 13:25:42 -070035 /* first, disable the watchdog or stop the timer */
36 if (devpriv->timer_mode == ADDIDATA_WATCHDOG) {
37 ctrl = 0;
38 } else {
H Hartley Sweetencd5d0ae2015-08-12 13:25:46 -070039 ctrl = inl(devpriv->tcw + ADDI_TCW_CTRL_REG);
H Hartley Sweeten7dc68e32015-08-12 13:25:48 -070040 ctrl &= ~(ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG |
41 ADDI_TCW_CTRL_ENA);
H Hartley Sweetenc85c26b2015-08-12 13:25:42 -070042 }
H Hartley Sweetencd5d0ae2015-08-12 13:25:46 -070043 outl(ctrl, devpriv->tcw + ADDI_TCW_CTRL_REG);
ADDI-DATA GmbHc995fe92009-02-12 15:14:18 -080044
H Hartley Sweetenc85c26b2015-08-12 13:25:42 -070045 /* enable/disable the timer interrupt */
H Hartley Sweeten7dc68e32015-08-12 13:25:48 -070046 ctrl = (data[1] == 1) ? ADDI_TCW_CTRL_IRQ_ENA : 0;
H Hartley Sweetencd5d0ae2015-08-12 13:25:46 -070047 outl(ctrl, devpriv->tcw + ADDI_TCW_CTRL_REG);
ADDI-DATA GmbHc995fe92009-02-12 15:14:18 -080048
H Hartley Sweetencd5d0ae2015-08-12 13:25:46 -070049 outl(data[2], devpriv->tcw + ADDI_TCW_TIMEBASE_REG);
50 outl(data[3], devpriv->tcw + ADDI_TCW_RELOAD_REG);
H Hartley Sweetenc85c26b2015-08-12 13:25:42 -070051
H Hartley Sweetencd5d0ae2015-08-12 13:25:46 -070052 ctrl = inl(devpriv->tcw + ADDI_TCW_CTRL_REG);
H Hartley Sweetenc85c26b2015-08-12 13:25:42 -070053 if (devpriv->timer_mode == ADDIDATA_WATCHDOG) {
54 /* Set the mode (e2->e0) NOTE: this doesn't look correct */
H Hartley Sweeten7dc68e32015-08-12 13:25:48 -070055 ctrl |= ~(ADDI_TCW_CTRL_CNT_UP | ADDI_TCW_CTRL_EXT_CLK_MASK |
56 ADDI_TCW_CTRL_MODE_MASK | ADDI_TCW_CTRL_GATE |
57 ADDI_TCW_CTRL_TRIG | ADDI_TCW_CTRL_TIMER_ENA |
58 ADDI_TCW_CTRL_RESET_ENA | ADDI_TCW_CTRL_WARN_ENA |
59 ADDI_TCW_CTRL_IRQ_ENA | ADDI_TCW_CTRL_ENA);
H Hartley Sweetenc85c26b2015-08-12 13:25:42 -070060 } else {
H Hartley Sweeten9798df72013-01-23 12:46:22 -070061 /* mode 2 */
H Hartley Sweeten7dc68e32015-08-12 13:25:48 -070062 ctrl &= ~(ADDI_TCW_CTRL_CNTR_ENA | ADDI_TCW_CTRL_MODE_MASK |
63 ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG |
64 ADDI_TCW_CTRL_TIMER_ENA | ADDI_TCW_CTRL_RESET_ENA |
65 ADDI_TCW_CTRL_WARN_ENA | ADDI_TCW_CTRL_ENA);
66 ctrl |= ADDI_TCW_CTRL_MODE(2) | ADDI_TCW_CTRL_TIMER_ENA;
H Hartley Sweeten9798df72013-01-23 12:46:22 -070067 }
H Hartley Sweetencd5d0ae2015-08-12 13:25:46 -070068 outl(ctrl, devpriv->tcw + ADDI_TCW_CTRL_REG);
ADDI-DATA GmbHc995fe92009-02-12 15:14:18 -080069
70 return insn->n;
71}
72
73/*
H Hartley Sweeten1ef0cfb2013-01-23 12:46:45 -070074 * (*insn_write) for the timer subdevice
75 *
76 * Start / Stop The Selected Timer , Counter or Watchdog
77 * Data Pointer contains configuration parameters as below
78 * data[0] : 0 Timer
79 * 1 Counter
80 * 2 Watchdog
81 * data[1] : 1 Start
82 * 0 Stop
83 * 2 Trigger
84 */
Fred Akers805077b2014-03-11 18:19:12 -040085static int apci3501_write_insn_timer(struct comedi_device *dev,
86 struct comedi_subdevice *s,
87 struct comedi_insn *insn,
88 unsigned int *data)
ADDI-DATA GmbHc995fe92009-02-12 15:14:18 -080089{
H Hartley Sweeten015aebe2013-01-23 12:43:14 -070090 struct apci3501_private *devpriv = dev->private;
H Hartley Sweeten626bb282015-08-12 13:25:39 -070091 unsigned int ctrl;
H Hartley Sweeten843690b2012-10-15 10:15:05 -070092
H Hartley Sweeten626bb282015-08-12 13:25:39 -070093 if (devpriv->timer_mode == ADDIDATA_WATCHDOG ||
94 devpriv->timer_mode == ADDIDATA_TIMER) {
H Hartley Sweetencd5d0ae2015-08-12 13:25:46 -070095 ctrl = inl(devpriv->tcw + ADDI_TCW_CTRL_REG);
H Hartley Sweeten0d5e0302015-08-12 13:25:49 -070096 ctrl &= ~(ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG);
H Hartley Sweeten626bb282015-08-12 13:25:39 -070097
98 if (data[1] == 1) { /* enable */
H Hartley Sweeten0d5e0302015-08-12 13:25:49 -070099 ctrl |= ADDI_TCW_CTRL_ENA;
H Hartley Sweeten626bb282015-08-12 13:25:39 -0700100 } else if (data[1] == 0) { /* stop */
101 if (devpriv->timer_mode == ADDIDATA_WATCHDOG)
102 ctrl = 0;
103 else
H Hartley Sweeten0d5e0302015-08-12 13:25:49 -0700104 ctrl &= ~ADDI_TCW_CTRL_ENA;
H Hartley Sweeten626bb282015-08-12 13:25:39 -0700105 } else if (data[1] == 2) { /* trigger */
H Hartley Sweeten0d5e0302015-08-12 13:25:49 -0700106 ctrl |= ADDI_TCW_CTRL_TRIG;
H Hartley Sweeten9798df72013-01-23 12:46:22 -0700107 }
H Hartley Sweetencd5d0ae2015-08-12 13:25:46 -0700108 outl(ctrl, devpriv->tcw + ADDI_TCW_CTRL_REG);
H Hartley Sweeten9798df72013-01-23 12:46:22 -0700109 }
ADDI-DATA GmbHc995fe92009-02-12 15:14:18 -0800110
H Hartley Sweetencd5d0ae2015-08-12 13:25:46 -0700111 inl(devpriv->tcw + ADDI_TCW_STATUS_REG);
ADDI-DATA GmbHc995fe92009-02-12 15:14:18 -0800112 return insn->n;
113}
114
115/*
H Hartley Sweeten1ef0cfb2013-01-23 12:46:45 -0700116 * (*insn_read) for the timer subdevice
117 *
118 * Read The Selected Timer, Counter or Watchdog
119 * Data Pointer contains configuration parameters as below
120 * data[0] : 0 Timer
121 * 1 Counter
122 * 2 Watchdog
123 * data[1] : Timer Counter Watchdog Number
124 */
Fred Akers805077b2014-03-11 18:19:12 -0400125static int apci3501_read_insn_timer(struct comedi_device *dev,
126 struct comedi_subdevice *s,
127 struct comedi_insn *insn,
128 unsigned int *data)
ADDI-DATA GmbHc995fe92009-02-12 15:14:18 -0800129{
H Hartley Sweeten015aebe2013-01-23 12:43:14 -0700130 struct apci3501_private *devpriv = dev->private;
ADDI-DATA GmbHc995fe92009-02-12 15:14:18 -0800131
H Hartley Sweetenf7f909e2015-08-12 13:25:40 -0700132 if (devpriv->timer_mode != ADDIDATA_TIMER &&
133 devpriv->timer_mode != ADDIDATA_WATCHDOG)
134 return -EINVAL;
ADDI-DATA GmbHc995fe92009-02-12 15:14:18 -0800135
H Hartley Sweeten1c38d032015-08-12 13:25:50 -0700136 data[0] = inl(devpriv->tcw + ADDI_TCW_STATUS_REG) &
137 ADDI_TCW_STATUS_OVERFLOW;
H Hartley Sweetencd5d0ae2015-08-12 13:25:46 -0700138 data[1] = inl(devpriv->tcw + ADDI_TCW_VAL_REG);
ADDI-DATA GmbHc995fe92009-02-12 15:14:18 -0800139
ADDI-DATA GmbHc995fe92009-02-12 15:14:18 -0800140 return insn->n;
141}