This source file includes following definitions.
- atao_select_reg_group
- atao_ao_insn_write
- atao_dio_insn_bits
- atao_dio_insn_config
- atao_calib_insn_write
- atao_reset
- atao_attach
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 #include <linux/module.h>
28
29 #include "../comedidev.h"
30
31 #include "comedi_8254.h"
32
33
34
35
36
37
38
39 #define ATAO_DIO_REG 0x00
40 #define ATAO_CFG2_REG 0x02
41 #define ATAO_CFG2_CALLD_NOP (0 << 14)
42 #define ATAO_CFG2_CALLD(x) ((((x) >> 3) + 1) << 14)
43 #define ATAO_CFG2_FFRTEN BIT(13)
44 #define ATAO_CFG2_DACS(x) (1 << (((x) / 2) + 8))
45 #define ATAO_CFG2_LDAC(x) (1 << (((x) / 2) + 3))
46 #define ATAO_CFG2_PROMEN BIT(2)
47 #define ATAO_CFG2_SCLK BIT(1)
48 #define ATAO_CFG2_SDATA BIT(0)
49 #define ATAO_CFG3_REG 0x04
50 #define ATAO_CFG3_DMAMODE BIT(6)
51 #define ATAO_CFG3_CLKOUT BIT(5)
52 #define ATAO_CFG3_RCLKEN BIT(4)
53 #define ATAO_CFG3_DOUTEN2 BIT(3)
54 #define ATAO_CFG3_DOUTEN1 BIT(2)
55 #define ATAO_CFG3_EN2_5V BIT(1)
56 #define ATAO_CFG3_SCANEN BIT(0)
57 #define ATAO_82C53_BASE 0x06
58 #define ATAO_CFG1_REG 0x0a
59 #define ATAO_CFG1_EXTINT2EN BIT(15)
60 #define ATAO_CFG1_EXTINT1EN BIT(14)
61 #define ATAO_CFG1_CNTINT2EN BIT(13)
62 #define ATAO_CFG1_CNTINT1EN BIT(12)
63 #define ATAO_CFG1_TCINTEN BIT(11)
64 #define ATAO_CFG1_CNT1SRC BIT(10)
65 #define ATAO_CFG1_CNT2SRC BIT(9)
66 #define ATAO_CFG1_FIFOEN BIT(8)
67 #define ATAO_CFG1_GRP2WR BIT(7)
68 #define ATAO_CFG1_EXTUPDEN BIT(6)
69 #define ATAO_CFG1_DMARQ BIT(5)
70 #define ATAO_CFG1_DMAEN BIT(4)
71 #define ATAO_CFG1_CH(x) (((x) & 0xf) << 0)
72 #define ATAO_STATUS_REG 0x0a
73 #define ATAO_STATUS_FH BIT(6)
74 #define ATAO_STATUS_FE BIT(5)
75 #define ATAO_STATUS_FF BIT(4)
76 #define ATAO_STATUS_INT2 BIT(3)
77 #define ATAO_STATUS_INT1 BIT(2)
78 #define ATAO_STATUS_TCINT BIT(1)
79 #define ATAO_STATUS_PROMOUT BIT(0)
80 #define ATAO_FIFO_WRITE_REG 0x0c
81 #define ATAO_FIFO_CLEAR_REG 0x0c
82 #define ATAO_AO_REG(x) (0x0c + ((x) * 2))
83
84
85 #define ATAO_2_DMATCCLR_REG 0x00
86 #define ATAO_2_INT1CLR_REG 0x02
87 #define ATAO_2_INT2CLR_REG 0x04
88 #define ATAO_2_RTSISHFT_REG 0x06
89 #define ATAO_2_RTSISHFT_RSI BIT(0)
90 #define ATAO_2_RTSISTRB_REG 0x07
91
92 struct atao_board {
93 const char *name;
94 int n_ao_chans;
95 };
96
97 static const struct atao_board atao_boards[] = {
98 {
99 .name = "at-ao-6",
100 .n_ao_chans = 6,
101 }, {
102 .name = "at-ao-10",
103 .n_ao_chans = 10,
104 },
105 };
106
107 struct atao_private {
108 unsigned short cfg1;
109 unsigned short cfg3;
110
111
112 unsigned char caldac[21];
113 };
114
115 static void atao_select_reg_group(struct comedi_device *dev, int group)
116 {
117 struct atao_private *devpriv = dev->private;
118
119 if (group)
120 devpriv->cfg1 |= ATAO_CFG1_GRP2WR;
121 else
122 devpriv->cfg1 &= ~ATAO_CFG1_GRP2WR;
123 outw(devpriv->cfg1, dev->iobase + ATAO_CFG1_REG);
124 }
125
126 static int atao_ao_insn_write(struct comedi_device *dev,
127 struct comedi_subdevice *s,
128 struct comedi_insn *insn,
129 unsigned int *data)
130 {
131 unsigned int chan = CR_CHAN(insn->chanspec);
132 unsigned int val = s->readback[chan];
133 int i;
134
135 if (chan == 0)
136 atao_select_reg_group(dev, 1);
137
138 for (i = 0; i < insn->n; i++) {
139 val = data[i];
140
141
142 outw(comedi_offset_munge(s, val),
143 dev->iobase + ATAO_AO_REG(chan));
144 }
145 s->readback[chan] = val;
146
147 if (chan == 0)
148 atao_select_reg_group(dev, 0);
149
150 return insn->n;
151 }
152
153 static int atao_dio_insn_bits(struct comedi_device *dev,
154 struct comedi_subdevice *s,
155 struct comedi_insn *insn,
156 unsigned int *data)
157 {
158 if (comedi_dio_update_state(s, data))
159 outw(s->state, dev->iobase + ATAO_DIO_REG);
160
161 data[1] = inw(dev->iobase + ATAO_DIO_REG);
162
163 return insn->n;
164 }
165
166 static int atao_dio_insn_config(struct comedi_device *dev,
167 struct comedi_subdevice *s,
168 struct comedi_insn *insn,
169 unsigned int *data)
170 {
171 struct atao_private *devpriv = dev->private;
172 unsigned int chan = CR_CHAN(insn->chanspec);
173 unsigned int mask;
174 int ret;
175
176 if (chan < 4)
177 mask = 0x0f;
178 else
179 mask = 0xf0;
180
181 ret = comedi_dio_insn_config(dev, s, insn, data, mask);
182 if (ret)
183 return ret;
184
185 if (s->io_bits & 0x0f)
186 devpriv->cfg3 |= ATAO_CFG3_DOUTEN1;
187 else
188 devpriv->cfg3 &= ~ATAO_CFG3_DOUTEN1;
189 if (s->io_bits & 0xf0)
190 devpriv->cfg3 |= ATAO_CFG3_DOUTEN2;
191 else
192 devpriv->cfg3 &= ~ATAO_CFG3_DOUTEN2;
193
194 outw(devpriv->cfg3, dev->iobase + ATAO_CFG3_REG);
195
196 return insn->n;
197 }
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232 static int atao_calib_insn_write(struct comedi_device *dev,
233 struct comedi_subdevice *s,
234 struct comedi_insn *insn,
235 unsigned int *data)
236 {
237 unsigned int chan = CR_CHAN(insn->chanspec);
238
239 if (insn->n) {
240 unsigned int val = data[insn->n - 1];
241 unsigned int bitstring = ((chan & 0x7) << 8) | val;
242 unsigned int bits;
243 int bit;
244
245
246
247 for (bit = BIT(10); bit; bit >>= 1) {
248 bits = (bit & bitstring) ? ATAO_CFG2_SDATA : 0;
249
250 outw(bits, dev->iobase + ATAO_CFG2_REG);
251 outw(bits | ATAO_CFG2_SCLK,
252 dev->iobase + ATAO_CFG2_REG);
253 }
254
255
256 outw(ATAO_CFG2_CALLD(chan), dev->iobase + ATAO_CFG2_REG);
257 outw(ATAO_CFG2_CALLD_NOP, dev->iobase + ATAO_CFG2_REG);
258
259 s->readback[chan] = val;
260 }
261
262 return insn->n;
263 }
264
265 static void atao_reset(struct comedi_device *dev)
266 {
267 struct atao_private *devpriv = dev->private;
268
269
270
271 devpriv->cfg1 = 0;
272 outw(devpriv->cfg1, dev->iobase + ATAO_CFG1_REG);
273
274
275 comedi_8254_set_mode(dev->pacer, 0, I8254_MODE4 | I8254_BINARY);
276 comedi_8254_set_mode(dev->pacer, 1, I8254_MODE4 | I8254_BINARY);
277 comedi_8254_write(dev->pacer, 0, 0x0003);
278
279 outw(ATAO_CFG2_CALLD_NOP, dev->iobase + ATAO_CFG2_REG);
280
281 devpriv->cfg3 = 0;
282 outw(devpriv->cfg3, dev->iobase + ATAO_CFG3_REG);
283
284 inw(dev->iobase + ATAO_FIFO_CLEAR_REG);
285
286 atao_select_reg_group(dev, 1);
287 outw(0, dev->iobase + ATAO_2_INT1CLR_REG);
288 outw(0, dev->iobase + ATAO_2_INT2CLR_REG);
289 outw(0, dev->iobase + ATAO_2_DMATCCLR_REG);
290 atao_select_reg_group(dev, 0);
291 }
292
293 static int atao_attach(struct comedi_device *dev, struct comedi_devconfig *it)
294 {
295 const struct atao_board *board = dev->board_ptr;
296 struct atao_private *devpriv;
297 struct comedi_subdevice *s;
298 int ret;
299
300 ret = comedi_request_region(dev, it->options[0], 0x20);
301 if (ret)
302 return ret;
303
304 devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
305 if (!devpriv)
306 return -ENOMEM;
307
308 dev->pacer = comedi_8254_init(dev->iobase + ATAO_82C53_BASE,
309 0, I8254_IO8, 0);
310 if (!dev->pacer)
311 return -ENOMEM;
312
313 ret = comedi_alloc_subdevices(dev, 4);
314 if (ret)
315 return ret;
316
317
318 s = &dev->subdevices[0];
319 s->type = COMEDI_SUBD_AO;
320 s->subdev_flags = SDF_WRITABLE;
321 s->n_chan = board->n_ao_chans;
322 s->maxdata = 0x0fff;
323 s->range_table = it->options[3] ? &range_unipolar10 : &range_bipolar10;
324 s->insn_write = atao_ao_insn_write;
325
326 ret = comedi_alloc_subdev_readback(s);
327 if (ret)
328 return ret;
329
330
331 s = &dev->subdevices[1];
332 s->type = COMEDI_SUBD_DIO;
333 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
334 s->n_chan = 8;
335 s->maxdata = 1;
336 s->range_table = &range_digital;
337 s->insn_bits = atao_dio_insn_bits;
338 s->insn_config = atao_dio_insn_config;
339
340
341 s = &dev->subdevices[2];
342 s->type = COMEDI_SUBD_CALIB;
343 s->subdev_flags = SDF_WRITABLE | SDF_INTERNAL;
344 s->n_chan = (board->n_ao_chans * 2) + 1;
345 s->maxdata = 0xff;
346 s->insn_write = atao_calib_insn_write;
347
348 ret = comedi_alloc_subdev_readback(s);
349 if (ret)
350 return ret;
351
352
353 s = &dev->subdevices[3];
354 s->type = COMEDI_SUBD_UNUSED;
355
356 atao_reset(dev);
357
358 return 0;
359 }
360
361 static struct comedi_driver ni_at_ao_driver = {
362 .driver_name = "ni_at_ao",
363 .module = THIS_MODULE,
364 .attach = atao_attach,
365 .detach = comedi_legacy_detach,
366 .board_name = &atao_boards[0].name,
367 .offset = sizeof(struct atao_board),
368 .num_names = ARRAY_SIZE(atao_boards),
369 };
370 module_comedi_driver(ni_at_ao_driver);
371
372 MODULE_AUTHOR("Comedi http://www.comedi.org");
373 MODULE_DESCRIPTION("Comedi driver for NI AT-AO-6/10 boards");
374 MODULE_LICENSE("GPL");