Re: [PATCH v2 4/4] iio: adc: add viperboard adc driver

2012-10-16 Thread Lars Poeschel
On Monday 15 October 2012 at 16:26:36, Lars-Peter Clausen wrote:
> Added linux-...@vger.kernel.org to Cc.
> 
> On 10/12/2012 04:34 PM, Lars Poeschel wrote:
> > From: Lars Poeschel 
> > 
> > This adds the mfd cell to use the adc part of the Nano River Technologies
> > viperboard.
> > 
> > Signed-off-by: Lars Poeschel 
> 
> Looks good in general, just some minor code style issues.
> 
> > ---
> > 
> >  drivers/iio/adc/Kconfig  |7 ++
> >  drivers/iio/adc/Makefile |1 +
> >  drivers/iio/adc/viperboard_adc.c |  185
> >  ++ drivers/mfd/viperboard.c
> >  |3 +
> >  4 files changed, 196 insertions(+)
> >  create mode 100644 drivers/iio/adc/viperboard_adc.c
> 
> [...]
> 
> > diff --git a/drivers/iio/adc/viperboard_adc.c
> > b/drivers/iio/adc/viperboard_adc.c new file mode 100644
> > index 000..8ae6634
> > --- /dev/null
> > +++ b/drivers/iio/adc/viperboard_adc.c
> > @@ -0,0 +1,185 @@
> > +/*
> > + *  Nano River Technologies viperboard iio ADC driver
> > + *
> > + *  (C) 2012 by Lemonage GmbH
> > + *  Author: Lars Poeschel 
> > + *  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 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +
> > +#include 
> > +#include 
> > +
> > +#include 
> > +
> > +#define VPRBRD_ADC_CMD_GET 0x00
> > +
> > +struct __packed vprbrd_adc_msg {
> > +   u8 cmd;
> > +   u8 chan;
> > +   u8 val;
> > +};
> 
> put the __packed between } and ;

GCC allows both alternatives, but you are right: Most kernel code is doing it 
between } and ; so I will change this.

> > +
> > +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,\
> 
> It would be good if you could also report the channel scale.

I saw that there is the possibility to supply a channel scale, which is way 
cool. :-) The doc of the viperboard says nothing about the scale of the ADC. 
At the moment I do not have the right measuring equipment here to measure a 
scale myself. I would do another tiny patch if I have the oppotunity to 
measure somewhere.

> > +   .scan_index = _index,   \
> > +   .scan_type.sign = 'u',  \
> > +   .scan_type.realbits = 8,\
> > +   .scan_type.storagebits = 8, \
> 
> Usually this is written as
>   .scan_type = {
>   .sign = 'u',
>   
>   },
> 
> > +}
> > +
> > +static struct iio_chan_spec vprbrd_adc_iio_channels[] = {
> 
> const
> 
> > +   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 mask)
> 
> 'mask' used to be a mask and that's why it is still called 'mask' in older
> drivers. For new drivers we should use '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;
> > +
> > +   if (mask == IIO_CHAN_INFO_RAW) {
> > +
> 
> Use switch instead of if. Otherwise you'd end up with if(mask == ...) else
> if(mask == ...) else if (mask == ...) if you add support for more channel
> attributes.
> 
> > +   mutex_lock(>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), 0xec, 0x40,
> > +   0x, 0x, admsg,
> > +   sizeof(struct vprbrd_adc_msg), 100);
> > +   if (ret != sizeof(struct vprbrd_adc_msg)) {
> > +   dev_err(_dev->dev, "usb send error on adc read\n");
> > +   error = -EREMOTEIO;
> > +   }
> 
> Does it make sense to send out the second msg if the first one failed?

This is a good question. I can not fully answer it, because I did not build 
the hardware. I thought it is better to try send the second message, because 
there is some chance it reaches the device. I would opt for trying it.

> > +
> > +   

Re: [PATCH v2 4/4] iio: adc: add viperboard adc driver

2012-10-16 Thread Lars Poeschel
On Monday 15 October 2012 at 16:26:36, Lars-Peter Clausen wrote:
 Added linux-...@vger.kernel.org to Cc.
 
 On 10/12/2012 04:34 PM, Lars Poeschel wrote:
  From: Lars Poeschel poesc...@lemonage.de
  
  This adds the mfd cell to use the adc part of the Nano River Technologies
  viperboard.
  
  Signed-off-by: Lars Poeschel poesc...@lemonage.de
 
 Looks good in general, just some minor code style issues.
 
  ---
  
   drivers/iio/adc/Kconfig  |7 ++
   drivers/iio/adc/Makefile |1 +
   drivers/iio/adc/viperboard_adc.c |  185
   ++ drivers/mfd/viperboard.c
   |3 +
   4 files changed, 196 insertions(+)
   create mode 100644 drivers/iio/adc/viperboard_adc.c
 
 [...]
 
  diff --git a/drivers/iio/adc/viperboard_adc.c
  b/drivers/iio/adc/viperboard_adc.c new file mode 100644
  index 000..8ae6634
  --- /dev/null
  +++ b/drivers/iio/adc/viperboard_adc.c
  @@ -0,0 +1,185 @@
  +/*
  + *  Nano River Technologies viperboard iio ADC driver
  + *
  + *  (C) 2012 by Lemonage GmbH
  + *  Author: Lars Poeschel poesc...@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 __packed vprbrd_adc_msg {
  +   u8 cmd;
  +   u8 chan;
  +   u8 val;
  +};
 
 put the __packed between } and ;

GCC allows both alternatives, but you are right: Most kernel code is doing it 
between } and ; so I will change this.

  +
  +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,\
 
 It would be good if you could also report the channel scale.

I saw that there is the possibility to supply a channel scale, which is way 
cool. :-) The doc of the viperboard says nothing about the scale of the ADC. 
At the moment I do not have the right measuring equipment here to measure a 
scale myself. I would do another tiny patch if I have the oppotunity to 
measure somewhere.

  +   .scan_index = _index,   \
  +   .scan_type.sign = 'u',  \
  +   .scan_type.realbits = 8,\
  +   .scan_type.storagebits = 8, \
 
 Usually this is written as
   .scan_type = {
   .sign = 'u',
   
   },
 
  +}
  +
  +static struct iio_chan_spec vprbrd_adc_iio_channels[] = {
 
 const
 
  +   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 mask)
 
 'mask' used to be a mask and that's why it is still called 'mask' in older
 drivers. For new drivers we should use '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;
  +
  +   if (mask == IIO_CHAN_INFO_RAW) {
  +
 
 Use switch instead of if. Otherwise you'd end up with if(mask == ...) else
 if(mask == ...) else if (mask == ...) if you add support for more channel
 attributes.
 
  +   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), 0xec, 0x40,
  +   0x, 0x, admsg,
  +   sizeof(struct vprbrd_adc_msg), 100);
  +   if (ret != sizeof(struct vprbrd_adc_msg)) {
  +   dev_err(iio_dev-dev, usb send error on adc read\n);
  +   error = -EREMOTEIO;
  +   }
 
 Does it make sense to send out the second msg if the first one failed?

This is a good question. I can not fully answer it, because I did not build 
the hardware. I thought it is better to try send the second message, because 
there is some chance it reaches the device. I would opt for trying it.

  +
  +   ret = usb_control_msg(vb-usb_dev,
  +

Re: [PATCH v2 4/4] iio: adc: add viperboard adc driver

2012-10-15 Thread Lars-Peter Clausen
Added linux-...@vger.kernel.org to Cc.

On 10/12/2012 04:34 PM, Lars Poeschel wrote:
> From: Lars Poeschel 
> 
> This adds the mfd cell to use the adc part of the Nano River Technologies
> viperboard.
> 
> Signed-off-by: Lars Poeschel 

Looks good in general, just some minor code style issues.

> ---
>  drivers/iio/adc/Kconfig  |7 ++
>  drivers/iio/adc/Makefile |1 +
>  drivers/iio/adc/viperboard_adc.c |  185 
> ++
>  drivers/mfd/viperboard.c |3 +
>  4 files changed, 196 insertions(+)
>  create mode 100644 drivers/iio/adc/viperboard_adc.c
> 
[...]
> diff --git a/drivers/iio/adc/viperboard_adc.c 
> b/drivers/iio/adc/viperboard_adc.c
> new file mode 100644
> index 000..8ae6634
> --- /dev/null
> +++ b/drivers/iio/adc/viperboard_adc.c
> @@ -0,0 +1,185 @@
> +/*
> + *  Nano River Technologies viperboard iio ADC driver
> + *
> + *  (C) 2012 by Lemonage GmbH
> + *  Author: Lars Poeschel 
> + *  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 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#include 
> +#include 
> +
> +#include 
> +
> +#define VPRBRD_ADC_CMD_GET   0x00
> +
> +struct __packed vprbrd_adc_msg {
> + u8 cmd;
> + u8 chan;
> + u8 val;
> +};

put the __packed between } and ;

> +
> +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,\

It would be good if you could also report the channel scale.

> + .scan_index = _index,   \
> + .scan_type.sign = 'u',  \
> + .scan_type.realbits = 8,\
> + .scan_type.storagebits = 8, \

Usually this is written as
.scan_type = {
.sign = 'u',

},

> +}
> +
> +static struct iio_chan_spec vprbrd_adc_iio_channels[] = {
const

> + 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 mask)

'mask' used to be a mask and that's why it is still called 'mask' in older
drivers. For new drivers we should use '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;
> +
> + if (mask == IIO_CHAN_INFO_RAW) {
> +

Use switch instead of if. Otherwise you'd end up with if(mask == ...) else
if(mask == ...) else if (mask == ...) if you add support for more channel
attributes.

> + mutex_lock(>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), 0xec, 0x40,
> + 0x, 0x, admsg,
> + sizeof(struct vprbrd_adc_msg), 100);
> + if (ret != sizeof(struct vprbrd_adc_msg)) {
> + dev_err(_dev->dev, "usb send error on adc read\n");
> + error = -EREMOTEIO;
> + }

Does it make sense to send out the second msg if the first one failed?

> +
> + ret = usb_control_msg(vb->usb_dev,
> + usb_rcvctrlpipe(vb->usb_dev, 0), 0xec, 0xc0,
> + 0x, 0x, admsg,
> + sizeof(struct vprbrd_adc_msg), 100);
> +

It would be good to have some defines for the magic constants used for
request and request_type.

> + *val = admsg->val;
> +
> + mutex_unlock(>lock);
> +
> + if (ret != sizeof(struct vprbrd_adc_msg)) {
> + dev_err(_dev->dev, "usb recv error on adc read\n");
> + error = -EREMOTEIO;
> + }
> +
> + if (error)
> + goto error;
> +
> + return IIO_VAL_INT;
> + }
> + error =  -EINVAL;
> +error:
> + return error;
> +}
> +
> +static const struct iio_info vprbrd_adc_iio_info = {
> + .read_raw = _iio_read_raw,
> + .driver_module = THIS_MODULE,
> +};
> +
> +static int 

Re: [PATCH v2 4/4] iio: adc: add viperboard adc driver

2012-10-15 Thread Lars-Peter Clausen
Added linux-...@vger.kernel.org to Cc.

On 10/12/2012 04:34 PM, Lars Poeschel wrote:
 From: Lars Poeschel poesc...@lemonage.de
 
 This adds the mfd cell to use the adc part of the Nano River Technologies
 viperboard.
 
 Signed-off-by: Lars Poeschel poesc...@lemonage.de

Looks good in general, just some minor code style issues.

 ---
  drivers/iio/adc/Kconfig  |7 ++
  drivers/iio/adc/Makefile |1 +
  drivers/iio/adc/viperboard_adc.c |  185 
 ++
  drivers/mfd/viperboard.c |3 +
  4 files changed, 196 insertions(+)
  create mode 100644 drivers/iio/adc/viperboard_adc.c
 
[...]
 diff --git a/drivers/iio/adc/viperboard_adc.c 
 b/drivers/iio/adc/viperboard_adc.c
 new file mode 100644
 index 000..8ae6634
 --- /dev/null
 +++ b/drivers/iio/adc/viperboard_adc.c
 @@ -0,0 +1,185 @@
 +/*
 + *  Nano River Technologies viperboard iio ADC driver
 + *
 + *  (C) 2012 by Lemonage GmbH
 + *  Author: Lars Poeschel poesc...@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 __packed vprbrd_adc_msg {
 + u8 cmd;
 + u8 chan;
 + u8 val;
 +};

put the __packed between } and ;

 +
 +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,\

It would be good if you could also report the channel scale.

 + .scan_index = _index,   \
 + .scan_type.sign = 'u',  \
 + .scan_type.realbits = 8,\
 + .scan_type.storagebits = 8, \

Usually this is written as
.scan_type = {
.sign = 'u',

},

 +}
 +
 +static struct iio_chan_spec vprbrd_adc_iio_channels[] = {
const

 + 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 mask)

'mask' used to be a mask and that's why it is still called 'mask' in older
drivers. For new drivers we should use '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;
 +
 + if (mask == IIO_CHAN_INFO_RAW) {
 +

Use switch instead of if. Otherwise you'd end up with if(mask == ...) else
if(mask == ...) else if (mask == ...) if you add support for more channel
attributes.

 + 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), 0xec, 0x40,
 + 0x, 0x, admsg,
 + sizeof(struct vprbrd_adc_msg), 100);
 + if (ret != sizeof(struct vprbrd_adc_msg)) {
 + dev_err(iio_dev-dev, usb send error on adc read\n);
 + error = -EREMOTEIO;
 + }

Does it make sense to send out the second msg if the first one failed?

 +
 + ret = usb_control_msg(vb-usb_dev,
 + usb_rcvctrlpipe(vb-usb_dev, 0), 0xec, 0xc0,
 + 0x, 0x, admsg,
 + sizeof(struct vprbrd_adc_msg), 100);
 +

It would be good to have some defines for the magic constants used for
request and request_type.

 + *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;
 + }
 + error =  -EINVAL;
 +error:
 + return error;
 +}
 +
 +static const struct iio_info vprbrd_adc_iio_info = {
 + .read_raw = 

[PATCH v2 4/4] iio: adc: add viperboard adc driver

2012-10-12 Thread Lars Poeschel
From: Lars Poeschel 

This adds the mfd cell to use the adc part of the Nano River Technologies
viperboard.

Signed-off-by: Lars Poeschel 
---
 drivers/iio/adc/Kconfig  |7 ++
 drivers/iio/adc/Makefile |1 +
 drivers/iio/adc/viperboard_adc.c |  185 ++
 drivers/mfd/viperboard.c |3 +
 4 files changed, 196 insertions(+)
 create mode 100644 drivers/iio/adc/viperboard_adc.c

diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 4927581..35ad77d 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -60,4 +60,11 @@ config LP8788_ADC
help
  Say yes here to build support for TI LP8788 ADC.
 
+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
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index 900995d..4852c2e 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -8,3 +8,4 @@ obj-$(CONFIG_AD7476) += ad7476.o
 obj-$(CONFIG_AD7791) += ad7791.o
 obj-$(CONFIG_AT91_ADC) += at91_adc.o
 obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
+obj-$(CONFIG_VIPERBOARD_ADC) += viperboard_adc.o
diff --git a/drivers/iio/adc/viperboard_adc.c b/drivers/iio/adc/viperboard_adc.c
new file mode 100644
index 000..8ae6634
--- /dev/null
+++ b/drivers/iio/adc/viperboard_adc.c
@@ -0,0 +1,185 @@
+/*
+ *  Nano River Technologies viperboard iio ADC driver
+ *
+ *  (C) 2012 by Lemonage GmbH
+ *  Author: Lars Poeschel 
+ *  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 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+
+#include 
+
+#define VPRBRD_ADC_CMD_GET 0x00
+
+struct __packed vprbrd_adc_msg {
+   u8 cmd;
+   u8 chan;
+   u8 val;
+};
+
+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',  \
+   .scan_type.realbits = 8,\
+   .scan_type.storagebits = 8, \
+}
+
+static struct iio_chan_spec 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 mask)
+{
+   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;
+
+   if (mask == IIO_CHAN_INFO_RAW) {
+
+   mutex_lock(>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), 0xec, 0x40,
+   0x, 0x, admsg,
+   sizeof(struct vprbrd_adc_msg), 100);
+   if (ret != sizeof(struct vprbrd_adc_msg)) {
+   dev_err(_dev->dev, "usb send error on adc read\n");
+   error = -EREMOTEIO;
+   }
+
+   ret = usb_control_msg(vb->usb_dev,
+   usb_rcvctrlpipe(vb->usb_dev, 0), 0xec, 0xc0,
+   0x, 0x, admsg,
+   sizeof(struct vprbrd_adc_msg), 100);
+
+   *val = admsg->val;
+
+   mutex_unlock(>lock);
+
+   if (ret != sizeof(struct vprbrd_adc_msg)) {
+   dev_err(_dev->dev, "usb recv error on adc read\n");
+   error = -EREMOTEIO;
+   }
+
+   if (error)
+   goto error;
+
+   return IIO_VAL_INT;
+   }
+   error =  -EINVAL;
+error:
+   return error;
+}
+
+static const struct iio_info vprbrd_adc_iio_info = {
+   .read_raw = _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);
+   

[PATCH v2 4/4] iio: adc: add viperboard adc driver

2012-10-12 Thread Lars Poeschel
From: Lars Poeschel poesc...@lemonage.de

This adds the mfd cell to use the adc part of the Nano River Technologies
viperboard.

Signed-off-by: Lars Poeschel poesc...@lemonage.de
---
 drivers/iio/adc/Kconfig  |7 ++
 drivers/iio/adc/Makefile |1 +
 drivers/iio/adc/viperboard_adc.c |  185 ++
 drivers/mfd/viperboard.c |3 +
 4 files changed, 196 insertions(+)
 create mode 100644 drivers/iio/adc/viperboard_adc.c

diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 4927581..35ad77d 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -60,4 +60,11 @@ config LP8788_ADC
help
  Say yes here to build support for TI LP8788 ADC.
 
+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
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index 900995d..4852c2e 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -8,3 +8,4 @@ obj-$(CONFIG_AD7476) += ad7476.o
 obj-$(CONFIG_AD7791) += ad7791.o
 obj-$(CONFIG_AT91_ADC) += at91_adc.o
 obj-$(CONFIG_LP8788_ADC) += lp8788_adc.o
+obj-$(CONFIG_VIPERBOARD_ADC) += viperboard_adc.o
diff --git a/drivers/iio/adc/viperboard_adc.c b/drivers/iio/adc/viperboard_adc.c
new file mode 100644
index 000..8ae6634
--- /dev/null
+++ b/drivers/iio/adc/viperboard_adc.c
@@ -0,0 +1,185 @@
+/*
+ *  Nano River Technologies viperboard iio ADC driver
+ *
+ *  (C) 2012 by Lemonage GmbH
+ *  Author: Lars Poeschel poesc...@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 __packed vprbrd_adc_msg {
+   u8 cmd;
+   u8 chan;
+   u8 val;
+};
+
+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',  \
+   .scan_type.realbits = 8,\
+   .scan_type.storagebits = 8, \
+}
+
+static struct iio_chan_spec 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 mask)
+{
+   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;
+
+   if (mask == 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), 0xec, 0x40,
+   0x, 0x, admsg,
+   sizeof(struct vprbrd_adc_msg), 100);
+   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), 0xec, 0xc0,
+   0x, 0x, admsg,
+   sizeof(struct vprbrd_adc_msg), 100);
+
+   *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;
+   }
+   error =  -EINVAL;
+error:
+   return error;
+}
+
+static const struct iio_info vprbrd_adc_iio_info = {
+   .read_raw =