1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * addi_apci_3501.c
4  * Copyright (C) 2004,2005  ADDI-DATA GmbH for the source code of this module.
5  * Project manager: Eric Stolz
6  *
7  *	ADDI-DATA GmbH
8  *	Dieselstrasse 3
9  *	D-77833 Ottersweier
10  *	Tel: +19(0)7223/9493-0
11  *	Fax: +49(0)7223/9493-92
12  *	http://www.addi-data.com
13  *	info@addi-data.com
14  */
15 
16 /*
17  * Driver: addi_apci_3501
18  * Description: ADDI-DATA APCI-3501 Analog output board
19  * Devices: [ADDI-DATA] APCI-3501 (addi_apci_3501)
20  * Author: H Hartley Sweeten <hsweeten@visionengravers.com>
21  * Updated: Mon, 20 Jun 2016 10:57:01 -0700
22  * Status: untested
23  *
24  * Configuration Options: not applicable, uses comedi PCI auto config
25  *
26  * This board has the following features:
27  *   - 4 or 8 analog output channels
28  *   - 2 optically isolated digital inputs
29  *   - 2 optically isolated digital outputs
30  *   - 1 12-bit watchdog/timer
31  *
32  * There are 2 versions of the APCI-3501:
33  *   - APCI-3501-4  4 analog output channels
34  *   - APCI-3501-8  8 analog output channels
35  *
36  * These boards use the same PCI Vendor/Device IDs. The number of output
37  * channels used by this driver is determined by reading the EEPROM on
38  * the board.
39  *
40  * The watchdog/timer subdevice is not currently supported.
41  */
42 
43 #include <linux/module.h>
44 #include <linux/comedi/comedi_pci.h>
45 
46 #include "amcc_s5933.h"
47 
48 /*
49  * PCI bar 1 register I/O map
50  */
51 #define APCI3501_AO_CTRL_STATUS_REG		0x00
52 #define APCI3501_AO_CTRL_BIPOLAR		BIT(0)
53 #define APCI3501_AO_STATUS_READY		BIT(8)
54 #define APCI3501_AO_DATA_REG			0x04
55 #define APCI3501_AO_DATA_CHAN(x)		((x) << 0)
56 #define APCI3501_AO_DATA_VAL(x)			((x) << 8)
57 #define APCI3501_AO_DATA_BIPOLAR		BIT(31)
58 #define APCI3501_AO_TRIG_SCS_REG		0x08
59 #define APCI3501_TIMER_BASE			0x20
60 #define APCI3501_DO_REG				0x40
61 #define APCI3501_DI_REG				0x50
62 
63 /*
64  * AMCC S5933 NVRAM
65  */
66 #define NVRAM_USER_DATA_START	0x100
67 
68 #define NVCMD_BEGIN_READ	(0x7 << 5)
69 #define NVCMD_LOAD_LOW		(0x4 << 5)
70 #define NVCMD_LOAD_HIGH		(0x5 << 5)
71 
72 /*
73  * Function types stored in the eeprom
74  */
75 #define EEPROM_DIGITALINPUT		0
76 #define EEPROM_DIGITALOUTPUT		1
77 #define EEPROM_ANALOGINPUT		2
78 #define EEPROM_ANALOGOUTPUT		3
79 #define EEPROM_TIMER			4
80 #define EEPROM_WATCHDOG			5
81 #define EEPROM_TIMER_WATCHDOG_COUNTER	10
82 
83 struct apci3501_private {
84 	unsigned long amcc;
85 	unsigned char timer_mode;
86 };
87 
88 static const struct comedi_lrange apci3501_ao_range = {
89 	2, {
90 		BIP_RANGE(10),
91 		UNI_RANGE(10)
92 	}
93 };
94 
95 static int apci3501_wait_for_dac(struct comedi_device *dev)
96 {
97 	unsigned int status;
98 
99 	do {
100 		status = inl(dev->iobase + APCI3501_AO_CTRL_STATUS_REG);
101 	} while (!(status & APCI3501_AO_STATUS_READY));
102 
103 	return 0;
104 }
105 
106 static int apci3501_ao_insn_write(struct comedi_device *dev,
107 				  struct comedi_subdevice *s,
108 				  struct comedi_insn *insn,
109 				  unsigned int *data)
110 {
111 	unsigned int chan = CR_CHAN(insn->chanspec);
112 	unsigned int range = CR_RANGE(insn->chanspec);
113 	unsigned int cfg = APCI3501_AO_DATA_CHAN(chan);
114 	int ret;
115 	int i;
116 
117 	/*
118 	 * All analog output channels have the same output range.
119 	 *	14-bit bipolar: 0-10V
120 	 *	13-bit unipolar: +/-10V
121 	 * Changing the range of one channel changes all of them!
122 	 */
123 	if (range) {
124 		outl(0, dev->iobase + APCI3501_AO_CTRL_STATUS_REG);
125 	} else {
126 		cfg |= APCI3501_AO_DATA_BIPOLAR;
127 		outl(APCI3501_AO_CTRL_BIPOLAR,
128 		     dev->iobase + APCI3501_AO_CTRL_STATUS_REG);
129 	}
130 
131 	for (i = 0; i < insn->n; i++) {
132 		unsigned int val = data[i];
133 
134 		if (range == 1) {
135 			if (data[i] > 0x1fff) {
136 				dev_err(dev->class_dev,
137 					"Unipolar resolution is only 13-bits\n");
138 				return -EINVAL;
139 			}
140 		}
141 
142 		ret = apci3501_wait_for_dac(dev);
143 		if (ret)
144 			return ret;
145 
146 		outl(cfg | APCI3501_AO_DATA_VAL(val),
147 		     dev->iobase + APCI3501_AO_DATA_REG);
148 
149 		s->readback[chan] = val;
150 	}
151 
152 	return insn->n;
153 }
154 
155 static int apci3501_di_insn_bits(struct comedi_device *dev,
156 				 struct comedi_subdevice *s,
157 				 struct comedi_insn *insn,
158 				 unsigned int *data)
159 {
160 	data[1] = inl(dev->iobase + APCI3501_DI_REG) & 0x3;
161 
162 	return insn->n;
163 }
164 
165 static int apci3501_do_insn_bits(struct comedi_device *dev,
166 				 struct comedi_subdevice *s,
167 				 struct comedi_insn *insn,
168 				 unsigned int *data)
169 {
170 	s->state = inl(dev->iobase + APCI3501_DO_REG);
171 
172 	if (comedi_dio_update_state(s, data))
173 		outl(s->state, dev->iobase + APCI3501_DO_REG);
174 
175 	data[1] = s->state;
176 
177 	return insn->n;
178 }
179 
180 static void apci3501_eeprom_wait(unsigned long iobase)
181 {
182 	unsigned char val;
183 
184 	do {
185 		val = inb(iobase + AMCC_OP_REG_MCSR_NVCMD);
186 	} while (val & 0x80);
187 }
188 
189 static unsigned short apci3501_eeprom_readw(unsigned long iobase,
190 					    unsigned short addr)
191 {
192 	unsigned short val = 0;
193 	unsigned char tmp;
194 	unsigned char i;
195 
196 	/* Add the offset to the start of the user data */
197 	addr += NVRAM_USER_DATA_START;
198 
199 	for (i = 0; i < 2; i++) {
200 		/* Load the low 8 bit address */
201 		outb(NVCMD_LOAD_LOW, iobase + AMCC_OP_REG_MCSR_NVCMD);
202 		apci3501_eeprom_wait(iobase);
203 		outb((addr + i) & 0xff, iobase + AMCC_OP_REG_MCSR_NVDATA);
204 		apci3501_eeprom_wait(iobase);
205 
206 		/* Load the high 8 bit address */
207 		outb(NVCMD_LOAD_HIGH, iobase + AMCC_OP_REG_MCSR_NVCMD);
208 		apci3501_eeprom_wait(iobase);
209 		outb(((addr + i) >> 8) & 0xff,
210 		     iobase + AMCC_OP_REG_MCSR_NVDATA);
211 		apci3501_eeprom_wait(iobase);
212 
213 		/* Read the eeprom data byte */
214 		outb(NVCMD_BEGIN_READ, iobase + AMCC_OP_REG_MCSR_NVCMD);
215 		apci3501_eeprom_wait(iobase);
216 		tmp = inb(iobase + AMCC_OP_REG_MCSR_NVDATA);
217 		apci3501_eeprom_wait(iobase);
218 
219 		if (i == 0)
220 			val |= tmp;
221 		else
222 			val |= (tmp << 8);
223 	}
224 
225 	return val;
226 }
227 
228 static int apci3501_eeprom_get_ao_n_chan(struct comedi_device *dev)
229 {
230 	struct apci3501_private *devpriv = dev->private;
231 	unsigned char nfuncs;
232 	int i;
233 
234 	nfuncs = apci3501_eeprom_readw(devpriv->amcc, 10) & 0xff;
235 
236 	/* Read functionality details */
237 	for (i = 0; i < nfuncs; i++) {
238 		unsigned short offset = i * 4;
239 		unsigned short addr;
240 		unsigned char func;
241 		unsigned short val;
242 
243 		func = apci3501_eeprom_readw(devpriv->amcc, 12 + offset) & 0x3f;
244 		addr = apci3501_eeprom_readw(devpriv->amcc, 14 + offset);
245 
246 		if (func == EEPROM_ANALOGOUTPUT) {
247 			val = apci3501_eeprom_readw(devpriv->amcc, addr + 10);
248 			return (val >> 4) & 0x3ff;
249 		}
250 	}
251 	return 0;
252 }
253 
254 static int apci3501_eeprom_insn_read(struct comedi_device *dev,
255 				     struct comedi_subdevice *s,
256 				     struct comedi_insn *insn,
257 				     unsigned int *data)
258 {
259 	struct apci3501_private *devpriv = dev->private;
260 	unsigned short addr = CR_CHAN(insn->chanspec);
261 	unsigned int val;
262 	unsigned int i;
263 
264 	if (insn->n) {
265 		/* No point reading the same EEPROM location more than once. */
266 		val = apci3501_eeprom_readw(devpriv->amcc, 2 * addr);
267 		for (i = 0; i < insn->n; i++)
268 			data[i] = val;
269 	}
270 
271 	return insn->n;
272 }
273 
274 static int apci3501_reset(struct comedi_device *dev)
275 {
276 	unsigned int val;
277 	int chan;
278 	int ret;
279 
280 	/* Reset all digital outputs to "0" */
281 	outl(0x0, dev->iobase + APCI3501_DO_REG);
282 
283 	/* Default all analog outputs to 0V (bipolar) */
284 	outl(APCI3501_AO_CTRL_BIPOLAR,
285 	     dev->iobase + APCI3501_AO_CTRL_STATUS_REG);
286 	val = APCI3501_AO_DATA_BIPOLAR | APCI3501_AO_DATA_VAL(0);
287 
288 	/* Set all analog output channels */
289 	for (chan = 0; chan < 8; chan++) {
290 		ret = apci3501_wait_for_dac(dev);
291 		if (ret) {
292 			dev_warn(dev->class_dev,
293 				 "%s: DAC not-ready for channel %i\n",
294 				 __func__, chan);
295 		} else {
296 			outl(val | APCI3501_AO_DATA_CHAN(chan),
297 			     dev->iobase + APCI3501_AO_DATA_REG);
298 		}
299 	}
300 
301 	return 0;
302 }
303 
304 static int apci3501_auto_attach(struct comedi_device *dev,
305 				unsigned long context_unused)
306 {
307 	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
308 	struct apci3501_private *devpriv;
309 	struct comedi_subdevice *s;
310 	int ao_n_chan;
311 	int ret;
312 
313 	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
314 	if (!devpriv)
315 		return -ENOMEM;
316 
317 	ret = comedi_pci_enable(dev);
318 	if (ret)
319 		return ret;
320 
321 	devpriv->amcc = pci_resource_start(pcidev, 0);
322 	dev->iobase = pci_resource_start(pcidev, 1);
323 
324 	ao_n_chan = apci3501_eeprom_get_ao_n_chan(dev);
325 
326 	ret = comedi_alloc_subdevices(dev, 5);
327 	if (ret)
328 		return ret;
329 
330 	/* Initialize the analog output subdevice */
331 	s = &dev->subdevices[0];
332 	if (ao_n_chan) {
333 		s->type		= COMEDI_SUBD_AO;
334 		s->subdev_flags	= SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
335 		s->n_chan	= ao_n_chan;
336 		s->maxdata	= 0x3fff;
337 		s->range_table	= &apci3501_ao_range;
338 		s->insn_write	= apci3501_ao_insn_write;
339 
340 		ret = comedi_alloc_subdev_readback(s);
341 		if (ret)
342 			return ret;
343 	} else {
344 		s->type		= COMEDI_SUBD_UNUSED;
345 	}
346 
347 	/* Initialize the digital input subdevice */
348 	s = &dev->subdevices[1];
349 	s->type		= COMEDI_SUBD_DI;
350 	s->subdev_flags	= SDF_READABLE;
351 	s->n_chan	= 2;
352 	s->maxdata	= 1;
353 	s->range_table	= &range_digital;
354 	s->insn_bits	= apci3501_di_insn_bits;
355 
356 	/* Initialize the digital output subdevice */
357 	s = &dev->subdevices[2];
358 	s->type		= COMEDI_SUBD_DO;
359 	s->subdev_flags	= SDF_WRITABLE;
360 	s->n_chan	= 2;
361 	s->maxdata	= 1;
362 	s->range_table	= &range_digital;
363 	s->insn_bits	= apci3501_do_insn_bits;
364 
365 	/* Timer/Watchdog subdevice */
366 	s = &dev->subdevices[3];
367 	s->type		= COMEDI_SUBD_UNUSED;
368 
369 	/* Initialize the eeprom subdevice */
370 	s = &dev->subdevices[4];
371 	s->type		= COMEDI_SUBD_MEMORY;
372 	s->subdev_flags	= SDF_READABLE | SDF_INTERNAL;
373 	s->n_chan	= 256;
374 	s->maxdata	= 0xffff;
375 	s->insn_read	= apci3501_eeprom_insn_read;
376 
377 	apci3501_reset(dev);
378 	return 0;
379 }
380 
381 static void apci3501_detach(struct comedi_device *dev)
382 {
383 	if (dev->iobase)
384 		apci3501_reset(dev);
385 	comedi_pci_detach(dev);
386 }
387 
388 static struct comedi_driver apci3501_driver = {
389 	.driver_name	= "addi_apci_3501",
390 	.module		= THIS_MODULE,
391 	.auto_attach	= apci3501_auto_attach,
392 	.detach		= apci3501_detach,
393 };
394 
395 static int apci3501_pci_probe(struct pci_dev *dev,
396 			      const struct pci_device_id *id)
397 {
398 	return comedi_pci_auto_config(dev, &apci3501_driver, id->driver_data);
399 }
400 
401 static const struct pci_device_id apci3501_pci_table[] = {
402 	{ PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x3001) },
403 	{ 0 }
404 };
405 MODULE_DEVICE_TABLE(pci, apci3501_pci_table);
406 
407 static struct pci_driver apci3501_pci_driver = {
408 	.name		= "addi_apci_3501",
409 	.id_table	= apci3501_pci_table,
410 	.probe		= apci3501_pci_probe,
411 	.remove		= comedi_pci_auto_unconfig,
412 };
413 module_comedi_pci_driver(apci3501_driver, apci3501_pci_driver);
414 
415 MODULE_DESCRIPTION("ADDI-DATA APCI-3501 Analog output board");
416 MODULE_AUTHOR("Comedi https://www.comedi.org");
417 MODULE_LICENSE("GPL");
418