Skip to content

Commit

Permalink
iio: adc: Add viperboard adc driver
Browse files Browse the repository at this point in the history
This adds the mfd cell to use the adc part of the Nano River Technologies
viperboard.

Signed-off-by: Lars Poeschel <poeschel@lemonage.de>
Reviewed-by: Lars-Peter Clausen <lars@metafoo.de>
Acked-by: Jonathan Cameron <jic23@kernel.org>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
  • Loading branch information
Lars Poeschel authored and Samuel Ortiz committed Nov 20, 2012
1 parent 174a13a commit ffd8a6e
Show file tree
Hide file tree
Showing 5 changed files with 193 additions and 0 deletions.
7 changes: 7 additions & 0 deletions drivers/iio/adc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,11 @@ config TI_AM335X_ADC
Say yes here to build support for Texas Instruments ADC
driver which is also a MFD client.

config VIPERBOARD_ADC
tristate "Viperboard ADC support"
depends on MFD_VIPERBOARD && USB
help
Say yes here to access the ADC part of the Nano River
Technologies Viperboard.

endmenu
1 change: 1 addition & 0 deletions drivers/iio/adc/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ obj-$(CONFIG_AD7791) += ad7791.o
obj-$(CONFIG_AT91_ADC) += at91_adc.o
obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
obj-$(CONFIG_TI_AM335X_ADC) += ti_am335x_adc.o
obj-$(CONFIG_VIPERBOARD_ADC) += viperboard_adc.o
181 changes: 181 additions & 0 deletions drivers/iio/adc/viperboard_adc.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
/*
* Nano River Technologies viperboard IIO ADC driver
*
* (C) 2012 by Lemonage GmbH
* Author: Lars Poeschel <poeschel@lemonage.de>
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
*/

#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/mutex.h>
#include <linux/platform_device.h>

#include <linux/usb.h>
#include <linux/iio/iio.h>

#include <linux/mfd/viperboard.h>

#define VPRBRD_ADC_CMD_GET 0x00

struct vprbrd_adc_msg {
u8 cmd;
u8 chan;
u8 val;
} __packed;

struct vprbrd_adc {
struct vprbrd *vb;
};

#define VPRBRD_ADC_CHANNEL(_index) { \
.type = IIO_VOLTAGE, \
.indexed = 1, \
.channel = _index, \
.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT, \
.scan_index = _index, \
.scan_type = { \
.sign = 'u', \
.realbits = 8, \
.storagebits = 8, \
}, \
}

static struct iio_chan_spec const vprbrd_adc_iio_channels[] = {
VPRBRD_ADC_CHANNEL(0),
VPRBRD_ADC_CHANNEL(1),
VPRBRD_ADC_CHANNEL(2),
VPRBRD_ADC_CHANNEL(3),
};

static int vprbrd_iio_read_raw(struct iio_dev *iio_dev,
struct iio_chan_spec const *chan,
int *val,
int *val2,
long info)
{
int ret, error = 0;
struct vprbrd_adc *adc = iio_priv(iio_dev);
struct vprbrd *vb = adc->vb;
struct vprbrd_adc_msg *admsg = (struct vprbrd_adc_msg *)vb->buf;

switch (info) {
case IIO_CHAN_INFO_RAW:
mutex_lock(&vb->lock);

admsg->cmd = VPRBRD_ADC_CMD_GET;
admsg->chan = chan->scan_index;
admsg->val = 0x00;

ret = usb_control_msg(vb->usb_dev,
usb_sndctrlpipe(vb->usb_dev, 0), VPRBRD_USB_REQUEST_ADC,
VPRBRD_USB_TYPE_OUT, 0x0000, 0x0000, admsg,
sizeof(struct vprbrd_adc_msg), VPRBRD_USB_TIMEOUT_MS);
if (ret != sizeof(struct vprbrd_adc_msg)) {
dev_err(&iio_dev->dev, "usb send error on adc read\n");
error = -EREMOTEIO;
}

ret = usb_control_msg(vb->usb_dev,
usb_rcvctrlpipe(vb->usb_dev, 0), VPRBRD_USB_REQUEST_ADC,
VPRBRD_USB_TYPE_IN, 0x0000, 0x0000, admsg,
sizeof(struct vprbrd_adc_msg), VPRBRD_USB_TIMEOUT_MS);

*val = admsg->val;

mutex_unlock(&vb->lock);

if (ret != sizeof(struct vprbrd_adc_msg)) {
dev_err(&iio_dev->dev, "usb recv error on adc read\n");
error = -EREMOTEIO;
}

if (error)
goto error;

return IIO_VAL_INT;
default:
error = -EINVAL;
break;
}
error:
return error;
}

static const struct iio_info vprbrd_adc_iio_info = {
.read_raw = &vprbrd_iio_read_raw,
.driver_module = THIS_MODULE,
};

static int __devinit vprbrd_adc_probe(struct platform_device *pdev)
{
struct vprbrd *vb = dev_get_drvdata(pdev->dev.parent);
struct vprbrd_adc *adc;
struct iio_dev *indio_dev;
int ret;

/* registering iio */
indio_dev = iio_device_alloc(sizeof(*adc));
if (!indio_dev) {
dev_err(&pdev->dev, "failed allocating iio device\n");
return -ENOMEM;
}

adc = iio_priv(indio_dev);
adc->vb = vb;
indio_dev->name = "viperboard adc";
indio_dev->dev.parent = &pdev->dev;
indio_dev->info = &vprbrd_adc_iio_info;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = vprbrd_adc_iio_channels;
indio_dev->num_channels = ARRAY_SIZE(vprbrd_adc_iio_channels);

ret = iio_device_register(indio_dev);
if (ret) {
dev_err(&pdev->dev, "could not register iio (adc)");
goto error;
}

platform_set_drvdata(pdev, indio_dev);

return 0;

error:
iio_device_free(indio_dev);
return ret;
}

static int __devexit vprbrd_adc_remove(struct platform_device *pdev)
{
struct iio_dev *indio_dev = platform_get_drvdata(pdev);

iio_device_unregister(indio_dev);
iio_device_free(indio_dev);

return 0;
}

static struct platform_driver vprbrd_adc_driver = {
.driver = {
.name = "viperboard-adc",
.owner = THIS_MODULE,
},
.probe = vprbrd_adc_probe,
.remove = __devexit_p(vprbrd_adc_remove),
};

module_platform_driver(vprbrd_adc_driver);

MODULE_AUTHOR("Lars Poeschel <poeschel@lemonage.de>");
MODULE_DESCRIPTION("IIO ADC driver for Nano River Techs Viperboard");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:viperboard-adc");
3 changes: 3 additions & 0 deletions drivers/mfd/viperboard.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ static struct mfd_cell vprbrd_devs[] = {
{
.name = "viperboard-i2c",
},
{
.name = "viperboard-adc",
},
};

static int vprbrd_probe(struct usb_interface *interface,
Expand Down
1 change: 1 addition & 0 deletions include/linux/mfd/viperboard.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
#define VPRBRD_USB_REQUEST_I2C 0xe9
#define VPRBRD_USB_REQUEST_MAJOR 0xea
#define VPRBRD_USB_REQUEST_MINOR 0xeb
#define VPRBRD_USB_REQUEST_ADC 0xec
#define VPRBRD_USB_REQUEST_GPIOA 0xed
#define VPRBRD_USB_REQUEST_GPIOB 0xdd

Expand Down

0 comments on commit ffd8a6e

Please sign in to comment.