staging: comedi: hwdrv_apci1564: tidy up apci1564_counter_insn_write()
[deliverable/linux.git] / drivers / staging / comedi / drivers / addi-data / hwdrv_apci1564.c
1 static int apci1564_timer_insn_config(struct comedi_device *dev,
2 struct comedi_subdevice *s,
3 struct comedi_insn *insn,
4 unsigned int *data)
5 {
6 struct apci1564_private *devpriv = dev->private;
7 unsigned int ctrl;
8
9 devpriv->tsk_current = current;
10
11 /* Stop the timer */
12 ctrl = inl(devpriv->timer + ADDI_TCW_CTRL_REG);
13 ctrl &= ~(ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG |
14 ADDI_TCW_CTRL_ENA);
15 outl(ctrl, devpriv->timer + ADDI_TCW_CTRL_REG);
16
17 if (data[1] == 1) {
18 /* Enable timer int & disable all the other int sources */
19 outl(ADDI_TCW_CTRL_IRQ_ENA,
20 devpriv->timer + ADDI_TCW_CTRL_REG);
21 outl(0x0, dev->iobase + APCI1564_DI_IRQ_REG);
22 outl(0x0, dev->iobase + APCI1564_DO_IRQ_REG);
23 outl(0x0, dev->iobase + APCI1564_WDOG_IRQ_REG);
24 if (devpriv->counters) {
25 unsigned long iobase;
26
27 iobase = devpriv->counters + ADDI_TCW_IRQ_REG;
28 outl(0x0, iobase + APCI1564_COUNTER(0));
29 outl(0x0, iobase + APCI1564_COUNTER(1));
30 outl(0x0, iobase + APCI1564_COUNTER(2));
31 }
32 } else {
33 /* disable Timer interrupt */
34 outl(0x0, devpriv->timer + ADDI_TCW_CTRL_REG);
35 }
36
37 /* Loading Timebase */
38 outl(data[2], devpriv->timer + ADDI_TCW_TIMEBASE_REG);
39
40 /* Loading the Reload value */
41 outl(data[3], devpriv->timer + ADDI_TCW_RELOAD_REG);
42
43 ctrl = inl(devpriv->timer + ADDI_TCW_CTRL_REG);
44 ctrl &= ~(ADDI_TCW_CTRL_CNTR_ENA | ADDI_TCW_CTRL_MODE_MASK |
45 ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG |
46 ADDI_TCW_CTRL_TIMER_ENA | ADDI_TCW_CTRL_RESET_ENA |
47 ADDI_TCW_CTRL_WARN_ENA | ADDI_TCW_CTRL_ENA);
48 ctrl |= ADDI_TCW_CTRL_MODE(2) | ADDI_TCW_CTRL_TIMER_ENA;
49 outl(ctrl, devpriv->timer + ADDI_TCW_CTRL_REG);
50
51 return insn->n;
52 }
53
54 static int apci1564_timer_insn_write(struct comedi_device *dev,
55 struct comedi_subdevice *s,
56 struct comedi_insn *insn,
57 unsigned int *data)
58 {
59 struct apci1564_private *devpriv = dev->private;
60 unsigned int ctrl;
61
62 ctrl = inl(devpriv->timer + ADDI_TCW_CTRL_REG);
63 ctrl &= ~(ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG);
64 switch (data[1]) {
65 case 0: /* Stop The Timer */
66 ctrl &= ~ADDI_TCW_CTRL_ENA;
67 break;
68 case 1: /* Enable the Timer */
69 ctrl |= ADDI_TCW_CTRL_ENA;
70 break;
71 }
72 outl(ctrl, devpriv->timer + ADDI_TCW_CTRL_REG);
73
74 return insn->n;
75 }
76
77 static int apci1564_timer_insn_read(struct comedi_device *dev,
78 struct comedi_subdevice *s,
79 struct comedi_insn *insn,
80 unsigned int *data)
81 {
82 struct apci1564_private *devpriv = dev->private;
83
84 /* Stores the status of the Timer */
85 data[0] = inl(devpriv->timer + ADDI_TCW_STATUS_REG) &
86 ADDI_TCW_STATUS_OVERFLOW;
87
88 /* Stores the Actual value of the Timer */
89 data[1] = inl(devpriv->timer + ADDI_TCW_VAL_REG);
90
91 return insn->n;
92 }
93
94 static int apci1564_counter_insn_config(struct comedi_device *dev,
95 struct comedi_subdevice *s,
96 struct comedi_insn *insn,
97 unsigned int *data)
98 {
99 struct apci1564_private *devpriv = dev->private;
100 unsigned int chan = CR_CHAN(insn->chanspec);
101 unsigned long iobase = devpriv->counters + APCI1564_COUNTER(chan);
102 unsigned int ctrl;
103
104 devpriv->tsk_current = current;
105
106 /* Stop The Timer */
107 ctrl = inl(iobase + ADDI_TCW_CTRL_REG);
108 ctrl &= ~(ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG |
109 ADDI_TCW_CTRL_ENA);
110 outl(ctrl, iobase + ADDI_TCW_CTRL_REG);
111
112 /* Set the reload value */
113 outl(data[3], iobase + ADDI_TCW_RELOAD_REG);
114
115 /* Set the mode */
116 ctrl &= ~(ADDI_TCW_CTRL_EXT_CLK_MASK | ADDI_TCW_CTRL_MODE_MASK |
117 ADDI_TCW_CTRL_TIMER_ENA | ADDI_TCW_CTRL_RESET_ENA |
118 ADDI_TCW_CTRL_WARN_ENA);
119 ctrl |= ADDI_TCW_CTRL_CNTR_ENA | ADDI_TCW_CTRL_MODE(data[4]);
120 outl(ctrl, iobase + ADDI_TCW_CTRL_REG);
121
122 /* Enable or Disable Interrupt */
123 if (data[1])
124 ctrl |= ADDI_TCW_CTRL_IRQ_ENA;
125 else
126 ctrl &= ~ADDI_TCW_CTRL_IRQ_ENA;
127 outl(ctrl, iobase + ADDI_TCW_CTRL_REG);
128
129 /* Set the Up/Down selection */
130 if (data[6])
131 ctrl |= ADDI_TCW_CTRL_CNT_UP;
132 else
133 ctrl &= ~ADDI_TCW_CTRL_CNT_UP;
134 outl(ctrl, iobase + ADDI_TCW_CTRL_REG);
135
136 return insn->n;
137 }
138
139 static int apci1564_counter_insn_write(struct comedi_device *dev,
140 struct comedi_subdevice *s,
141 struct comedi_insn *insn,
142 unsigned int *data)
143 {
144 struct apci1564_private *devpriv = dev->private;
145 unsigned int chan = CR_CHAN(insn->chanspec);
146 unsigned long iobase = devpriv->counters + APCI1564_COUNTER(chan);
147 unsigned int ctrl;
148
149 ctrl = inl(iobase + ADDI_TCW_CTRL_REG);
150 ctrl &= ~(ADDI_TCW_CTRL_GATE | ADDI_TCW_CTRL_TRIG);
151 switch (data[1]) {
152 case 0: /* Stops the Counter subdevice */
153 ctrl = 0;
154 break;
155 case 1: /* Start the Counter subdevice */
156 ctrl |= ADDI_TCW_CTRL_ENA;
157 break;
158 case 2: /* Clears the Counter subdevice */
159 ctrl |= ADDI_TCW_CTRL_GATE;
160 break;
161 }
162 outl(ctrl, iobase + ADDI_TCW_CTRL_REG);
163
164 return insn->n;
165 }
166
167 static int apci1564_counter_insn_read(struct comedi_device *dev,
168 struct comedi_subdevice *s,
169 struct comedi_insn *insn,
170 unsigned int *data)
171 {
172 struct apci1564_private *devpriv = dev->private;
173 unsigned int chan = CR_CHAN(insn->chanspec);
174 unsigned long iobase = devpriv->counters + APCI1564_COUNTER(chan);
175 unsigned int status;
176
177 /* Read the Counter Actual Value. */
178 data[0] = inl(iobase + ADDI_TCW_VAL_REG);
179
180 status = inl(iobase + ADDI_TCW_STATUS_REG);
181 data[1] = (status >> 1) & 1; /* software trigger status */
182 data[2] = (status >> 2) & 1; /* hardware trigger status */
183 data[3] = (status >> 3) & 1; /* software clear status */
184 data[4] = (status >> 0) & 1; /* overflow status */
185
186 return insn->n;
187 }
This page took 0.085214 seconds and 5 git commands to generate.