Merge tag 'nfs-for-5.13-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
[linux-2.6-microblaze.git] / drivers / comedi / drivers / ni_mio_cs.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Comedi driver for NI PCMCIA MIO E series cards
4  *
5  * COMEDI - Linux Control and Measurement Device Interface
6  * Copyright (C) 1997-2000 David A. Schleef <ds@schleef.org>
7  */
8
9 /*
10  * Driver: ni_mio_cs
11  * Description: National Instruments DAQCard E series
12  * Author: ds
13  * Status: works
14  * Devices: [National Instruments] DAQCard-AI-16XE-50 (ni_mio_cs),
15  *   DAQCard-AI-16E-4, DAQCard-6062E, DAQCard-6024E, DAQCard-6036E
16  * Updated: Thu Oct 23 19:43:17 CDT 2003
17  *
18  * See the notes in the ni_atmio.o driver.
19  */
20
21 /*
22  * The real guts of the driver is in ni_mio_common.c, which is
23  * included by all the E series drivers.
24  *
25  * References for specifications:
26  *      341080a.pdf  DAQCard E Series Register Level Programmer Manual
27  */
28
29 #include <linux/module.h>
30 #include <linux/delay.h>
31
32 #include "../comedi_pcmcia.h"
33 #include "ni_stc.h"
34 #include "8255.h"
35
36 /*
37  *  AT specific setup
38  */
39
40 static const struct ni_board_struct ni_boards[] = {
41         {
42                 .name           = "DAQCard-ai-16xe-50",
43                 .device_id      = 0x010d,
44                 .n_adchan       = 16,
45                 .ai_maxdata     = 0xffff,
46                 .ai_fifo_depth  = 1024,
47                 .gainlkup       = ai_gain_8,
48                 .ai_speed       = 5000,
49                 .caldac         = { dac8800, dac8043 },
50         }, {
51                 .name           = "DAQCard-ai-16e-4",
52                 .device_id      = 0x010c,
53                 .n_adchan       = 16,
54                 .ai_maxdata     = 0x0fff,
55                 .ai_fifo_depth  = 1024,
56                 .gainlkup       = ai_gain_16,
57                 .ai_speed       = 4000,
58                 .caldac         = { mb88341 },          /* verified */
59         }, {
60                 .name           = "DAQCard-6062E",
61                 .device_id      = 0x02c4,
62                 .n_adchan       = 16,
63                 .ai_maxdata     = 0x0fff,
64                 .ai_fifo_depth  = 8192,
65                 .gainlkup       = ai_gain_16,
66                 .ai_speed       = 2000,
67                 .n_aochan       = 2,
68                 .ao_maxdata     = 0x0fff,
69                 .ao_fifo_depth  = 2048,
70                 .ao_range_table = &range_bipolar10,
71                 .ao_speed       = 1176,
72                 .caldac         = { ad8804_debug },     /* verified */
73          }, {
74                 /* specs incorrect! */
75                 .name           = "DAQCard-6024E",
76                 .device_id      = 0x075e,
77                 .n_adchan       = 16,
78                 .ai_maxdata     = 0x0fff,
79                 .ai_fifo_depth  = 1024,
80                 .gainlkup       = ai_gain_4,
81                 .ai_speed       = 5000,
82                 .n_aochan       = 2,
83                 .ao_maxdata     = 0x0fff,
84                 .ao_range_table = &range_bipolar10,
85                 .ao_speed       = 1000000,
86                 .caldac         = { ad8804_debug },
87         }, {
88                 /* specs incorrect! */
89                 .name           = "DAQCard-6036E",
90                 .device_id      = 0x0245,
91                 .n_adchan       = 16,
92                 .ai_maxdata     = 0xffff,
93                 .ai_fifo_depth  = 1024,
94                 .alwaysdither   = 1,
95                 .gainlkup       = ai_gain_4,
96                 .ai_speed       = 5000,
97                 .n_aochan       = 2,
98                 .ao_maxdata     = 0xffff,
99                 .ao_range_table = &range_bipolar10,
100                 .ao_speed       = 1000000,
101                 .caldac         = { ad8804_debug },
102          },
103 #if 0
104         {
105                 .name           = "DAQCard-6715",
106                 .device_id      = 0x0000,       /* unknown */
107                 .n_aochan       = 8,
108                 .ao_maxdata     = 0x0fff,
109                 .ao_671x        = 8192,
110                 .caldac         = { mb88341, mb88341 },
111         },
112 #endif
113 };
114
115 #include "ni_mio_common.c"
116
117 static const void *ni_getboardtype(struct comedi_device *dev,
118                                    struct pcmcia_device *link)
119 {
120         static const struct ni_board_struct *board;
121         int i;
122
123         for (i = 0; i < ARRAY_SIZE(ni_boards); i++) {
124                 board = &ni_boards[i];
125                 if (board->device_id == link->card_id)
126                         return board;
127         }
128         return NULL;
129 }
130
131 static int mio_pcmcia_config_loop(struct pcmcia_device *p_dev, void *priv_data)
132 {
133         int base, ret;
134
135         p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
136         p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_16;
137
138         for (base = 0x000; base < 0x400; base += 0x20) {
139                 p_dev->resource[0]->start = base;
140                 ret = pcmcia_request_io(p_dev);
141                 if (!ret)
142                         return 0;
143         }
144         return -ENODEV;
145 }
146
147 static int mio_cs_auto_attach(struct comedi_device *dev,
148                               unsigned long context)
149 {
150         struct pcmcia_device *link = comedi_to_pcmcia_dev(dev);
151         static const struct ni_board_struct *board;
152         int ret;
153
154         board = ni_getboardtype(dev, link);
155         if (!board)
156                 return -ENODEV;
157         dev->board_ptr = board;
158         dev->board_name = board->name;
159
160         link->config_flags |= CONF_AUTO_SET_IO | CONF_ENABLE_IRQ;
161         ret = comedi_pcmcia_enable(dev, mio_pcmcia_config_loop);
162         if (ret)
163                 return ret;
164         dev->iobase = link->resource[0]->start;
165
166         link->priv = dev;
167         ret = pcmcia_request_irq(link, ni_E_interrupt);
168         if (ret)
169                 return ret;
170         dev->irq = link->irq;
171
172         ret = ni_alloc_private(dev);
173         if (ret)
174                 return ret;
175
176         return ni_E_init(dev, 0, 1);
177 }
178
179 static void mio_cs_detach(struct comedi_device *dev)
180 {
181         mio_common_detach(dev);
182         comedi_pcmcia_disable(dev);
183 }
184
185 static struct comedi_driver driver_ni_mio_cs = {
186         .driver_name    = "ni_mio_cs",
187         .module         = THIS_MODULE,
188         .auto_attach    = mio_cs_auto_attach,
189         .detach         = mio_cs_detach,
190 };
191
192 static int cs_attach(struct pcmcia_device *link)
193 {
194         return comedi_pcmcia_auto_config(link, &driver_ni_mio_cs);
195 }
196
197 static const struct pcmcia_device_id ni_mio_cs_ids[] = {
198         PCMCIA_DEVICE_MANF_CARD(0x010b, 0x010d),        /* DAQCard-ai-16xe-50 */
199         PCMCIA_DEVICE_MANF_CARD(0x010b, 0x010c),        /* DAQCard-ai-16e-4 */
200         PCMCIA_DEVICE_MANF_CARD(0x010b, 0x02c4),        /* DAQCard-6062E */
201         PCMCIA_DEVICE_MANF_CARD(0x010b, 0x075e),        /* DAQCard-6024E */
202         PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0245),        /* DAQCard-6036E */
203         PCMCIA_DEVICE_NULL
204 };
205 MODULE_DEVICE_TABLE(pcmcia, ni_mio_cs_ids);
206
207 static struct pcmcia_driver ni_mio_cs_driver = {
208         .name           = "ni_mio_cs",
209         .owner          = THIS_MODULE,
210         .id_table       = ni_mio_cs_ids,
211         .probe          = cs_attach,
212         .remove         = comedi_pcmcia_auto_unconfig,
213 };
214 module_comedi_pcmcia_driver(driver_ni_mio_cs, ni_mio_cs_driver);
215
216 MODULE_DESCRIPTION("Comedi driver for National Instruments DAQCard E series");
217 MODULE_AUTHOR("David A. Schleef <ds@schleef.org>");
218 MODULE_LICENSE("GPL");