1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Nano River Technologies viperboard IIO ADC driver
5 * (C) 2012 by Lemonage GmbH
6 * Author: Lars Poeschel <poeschel@lemonage.de>
10 #include <linux/kernel.h>
11 #include <linux/errno.h>
12 #include <linux/module.h>
13 #include <linux/slab.h>
14 #include <linux/types.h>
15 #include <linux/mutex.h>
16 #include <linux/platform_device.h>
18 #include <linux/usb.h>
19 #include <linux/iio/iio.h>
21 #include <linux/mfd/viperboard.h>
23 #define VPRBRD_ADC_CMD_GET 0x00
25 struct vprbrd_adc_msg
{
35 #define VPRBRD_ADC_CHANNEL(_index) { \
36 .type = IIO_VOLTAGE, \
39 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
42 static struct iio_chan_spec
const vprbrd_adc_iio_channels
[] = {
43 VPRBRD_ADC_CHANNEL(0),
44 VPRBRD_ADC_CHANNEL(1),
45 VPRBRD_ADC_CHANNEL(2),
46 VPRBRD_ADC_CHANNEL(3),
49 static int vprbrd_iio_read_raw(struct iio_dev
*iio_dev
,
50 struct iio_chan_spec
const *chan
,
56 struct vprbrd_adc
*adc
= iio_priv(iio_dev
);
57 struct vprbrd
*vb
= adc
->vb
;
58 struct vprbrd_adc_msg
*admsg
= (struct vprbrd_adc_msg
*)vb
->buf
;
61 case IIO_CHAN_INFO_RAW
:
62 mutex_lock(&vb
->lock
);
64 admsg
->cmd
= VPRBRD_ADC_CMD_GET
;
65 admsg
->chan
= chan
->channel
;
68 ret
= usb_control_msg(vb
->usb_dev
,
69 usb_sndctrlpipe(vb
->usb_dev
, 0), VPRBRD_USB_REQUEST_ADC
,
70 VPRBRD_USB_TYPE_OUT
, 0x0000, 0x0000, admsg
,
71 sizeof(struct vprbrd_adc_msg
), VPRBRD_USB_TIMEOUT_MS
);
72 if (ret
!= sizeof(struct vprbrd_adc_msg
)) {
73 dev_err(&iio_dev
->dev
, "usb send error on adc read\n");
77 ret
= usb_control_msg(vb
->usb_dev
,
78 usb_rcvctrlpipe(vb
->usb_dev
, 0), VPRBRD_USB_REQUEST_ADC
,
79 VPRBRD_USB_TYPE_IN
, 0x0000, 0x0000, admsg
,
80 sizeof(struct vprbrd_adc_msg
), VPRBRD_USB_TIMEOUT_MS
);
84 mutex_unlock(&vb
->lock
);
86 if (ret
!= sizeof(struct vprbrd_adc_msg
)) {
87 dev_err(&iio_dev
->dev
, "usb recv error on adc read\n");
103 static const struct iio_info vprbrd_adc_iio_info
= {
104 .read_raw
= &vprbrd_iio_read_raw
,
107 static int vprbrd_adc_probe(struct platform_device
*pdev
)
109 struct vprbrd
*vb
= dev_get_drvdata(pdev
->dev
.parent
);
110 struct vprbrd_adc
*adc
;
111 struct iio_dev
*indio_dev
;
114 /* registering iio */
115 indio_dev
= devm_iio_device_alloc(&pdev
->dev
, sizeof(*adc
));
117 dev_err(&pdev
->dev
, "failed allocating iio device\n");
121 adc
= iio_priv(indio_dev
);
123 indio_dev
->name
= "viperboard adc";
124 indio_dev
->info
= &vprbrd_adc_iio_info
;
125 indio_dev
->modes
= INDIO_DIRECT_MODE
;
126 indio_dev
->channels
= vprbrd_adc_iio_channels
;
127 indio_dev
->num_channels
= ARRAY_SIZE(vprbrd_adc_iio_channels
);
129 ret
= devm_iio_device_register(&pdev
->dev
, indio_dev
);
131 dev_err(&pdev
->dev
, "could not register iio (adc)");
138 static struct platform_driver vprbrd_adc_driver
= {
140 .name
= "viperboard-adc",
142 .probe
= vprbrd_adc_probe
,
145 module_platform_driver(vprbrd_adc_driver
);
147 MODULE_AUTHOR("Lars Poeschel <poeschel@lemonage.de>");
148 MODULE_DESCRIPTION("IIO ADC driver for Nano River Techs Viperboard");
149 MODULE_LICENSE("GPL");
150 MODULE_ALIAS("platform:viperboard-adc");