Re: [PATCH v3] iio: adc: vf610: Add IIO buffer support for Vybrid ADC

2015-08-17 Thread maitysanchayan
Hello Jonathan,

On 15-08-15 21:24:01, Jonathan Cameron wrote:
> On 11/08/15 10:05, Sanchayan Maity wrote:
> > This patch adds support for IIO buffer to the Vybrid ADC driver.
> > IIO triggered buffer infrastructure along with iio sysfs trigger
> > is used to leverage continuous sampling support provided by the
> > ADC block.
> > 
> > Signed-off-by: Sanchayan Maity 
> Hi Sanchayan,
> 
> Very nearly there. One little point to do with the buffer handling.
> Basically I don't think you want anything in the preenable or
> postdisable hooks, just in the 'internal' ones.
> 
> Jonathan
> > ---
> >  drivers/iio/adc/Kconfig |   2 +
> >  drivers/iio/adc/vf610_adc.c | 102 
> > +---
> >  2 files changed, 97 insertions(+), 7 deletions(-)
> > 
> > diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
> > index 7c55658..660f790 100644
> > --- a/drivers/iio/adc/Kconfig
> > +++ b/drivers/iio/adc/Kconfig
> > @@ -337,6 +337,8 @@ config TWL6030_GPADC
> >  config VF610_ADC
> > tristate "Freescale vf610 ADC driver"
> > depends on OF
> > +   select IIO_BUFFER
> > +   select IIO_TRIGGERED_BUFFER
> > help
> >   Say yes here to support for Vybrid board analog-to-digital converter.
> >   Since the IP is used for i.MX6SLX, the driver also support i.MX6SLX.
> > diff --git a/drivers/iio/adc/vf610_adc.c b/drivers/iio/adc/vf610_adc.c
> > index 23b8fb9..de62c48 100644
> > --- a/drivers/iio/adc/vf610_adc.c
> > +++ b/drivers/iio/adc/vf610_adc.c
> > @@ -34,8 +34,11 @@
> >  #include 
> >  
> >  #include 
> > +#include 
> >  #include 
> > -#include 
> > +#include 
> > +#include 
> > +#include 
> >  
> >  /* This will be the driver name the kernel reports */
> >  #define DRIVER_NAME "vf610-adc"
> > @@ -170,6 +173,7 @@ struct vf610_adc {
> > u32 sample_freq_avail[5];
> >  
> > struct completion completion;
> > +   u16 buffer[8];
> >  };
> >  
> >  static const u32 vf610_hw_avgs[] = { 1, 4, 8, 16, 32 };
> > @@ -505,12 +509,24 @@ static const struct iio_chan_spec_ext_info 
> > vf610_ext_info[] = {
> > .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |  \
> > BIT(IIO_CHAN_INFO_SAMP_FREQ),   \
> > .ext_info = vf610_ext_info, \
> > +   .scan_index = (_idx),   \
> > +   .scan_type = {  \
> > +   .sign = 'u',\
> > +   .realbits = 12, \
> > +   .storagebits = 16,  \
> > +   },  \
> >  }
> >  
> >  #define VF610_ADC_TEMPERATURE_CHAN(_idx, _chan_type) { \
> > .type = (_chan_type),   \
> > .channel = (_idx),  \
> > .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), \
> > +   .scan_index = (_idx),   \
> > +   .scan_type = {  \
> > +   .sign = 'u',\
> > +   .realbits = 12, \
> > +   .storagebits = 16,  \
> > +   },  \
> >  }
> >  
> >  static const struct iio_chan_spec vf610_adc_iio_channels[] = {
> > @@ -531,6 +547,7 @@ static const struct iio_chan_spec 
> > vf610_adc_iio_channels[] = {
> > VF610_ADC_CHAN(14, IIO_VOLTAGE),
> > VF610_ADC_CHAN(15, IIO_VOLTAGE),
> > VF610_ADC_TEMPERATURE_CHAN(26, IIO_TEMP),
> > +   IIO_CHAN_SOFT_TIMESTAMP(32),
> > /* sentinel */
> >  };
> >  
> > @@ -559,13 +576,20 @@ static int vf610_adc_read_data(struct vf610_adc *info)
> >  
> >  static irqreturn_t vf610_adc_isr(int irq, void *dev_id)
> >  {
> > -   struct vf610_adc *info = (struct vf610_adc *)dev_id;
> > +   struct iio_dev *indio_dev = (struct iio_dev *)dev_id;
> > +   struct vf610_adc *info = iio_priv(indio_dev);
> > int coco;
> >  
> > coco = readl(info->regs + VF610_REG_ADC_HS);
> > if (coco & VF610_ADC_HS_COCO0) {
> > info->value = vf610_adc_read_data(info);
> > -   complete(>completion);
> > +   if (iio_buffer_enabled(indio_dev)) {
> > +   info->buffer[0] = info->value;
> > +   iio_push_to_buffers_with_timestamp(indio_dev,
> > +   info->buffer, iio_get_time_ns());
> > +   iio_trigger_notify_done(indio_dev->trig);
> > +   } else
> > +   complete(>completion);
> > }
> >  
> > return IRQ_HANDLED;
> > @@ -613,8 +637,12 @@ static int vf610_read_raw(struct iio_dev *indio_dev,
> > case IIO_CHAN_INFO_RAW:
> > case IIO_CHAN_INFO_PROCESSED:
> > mutex_lock(_dev->mlock);
> > -   reinit_completion(>completion);
> > +   if (iio_buffer_enabled(indio_dev)) {
> > +   mutex_unlock(_dev->mlock);
> > +   return -EBUSY;
> > +   }
> >  
> > +  

Re: [PATCH v3] iio: adc: vf610: Add IIO buffer support for Vybrid ADC

2015-08-17 Thread maitysanchayan
Hello Jonathan,

On 15-08-15 21:24:01, Jonathan Cameron wrote:
 On 11/08/15 10:05, Sanchayan Maity wrote:
  This patch adds support for IIO buffer to the Vybrid ADC driver.
  IIO triggered buffer infrastructure along with iio sysfs trigger
  is used to leverage continuous sampling support provided by the
  ADC block.
  
  Signed-off-by: Sanchayan Maity maitysancha...@gmail.com
 Hi Sanchayan,
 
 Very nearly there. One little point to do with the buffer handling.
 Basically I don't think you want anything in the preenable or
 postdisable hooks, just in the 'internal' ones.
 
 Jonathan
  ---
   drivers/iio/adc/Kconfig |   2 +
   drivers/iio/adc/vf610_adc.c | 102 
  +---
   2 files changed, 97 insertions(+), 7 deletions(-)
  
  diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
  index 7c55658..660f790 100644
  --- a/drivers/iio/adc/Kconfig
  +++ b/drivers/iio/adc/Kconfig
  @@ -337,6 +337,8 @@ config TWL6030_GPADC
   config VF610_ADC
  tristate Freescale vf610 ADC driver
  depends on OF
  +   select IIO_BUFFER
  +   select IIO_TRIGGERED_BUFFER
  help
Say yes here to support for Vybrid board analog-to-digital converter.
Since the IP is used for i.MX6SLX, the driver also support i.MX6SLX.
  diff --git a/drivers/iio/adc/vf610_adc.c b/drivers/iio/adc/vf610_adc.c
  index 23b8fb9..de62c48 100644
  --- a/drivers/iio/adc/vf610_adc.c
  +++ b/drivers/iio/adc/vf610_adc.c
  @@ -34,8 +34,11 @@
   #include linux/err.h
   
   #include linux/iio/iio.h
  +#include linux/iio/buffer.h
   #include linux/iio/sysfs.h
  -#include linux/iio/driver.h
  +#include linux/iio/trigger.h
  +#include linux/iio/trigger_consumer.h
  +#include linux/iio/triggered_buffer.h
   
   /* This will be the driver name the kernel reports */
   #define DRIVER_NAME vf610-adc
  @@ -170,6 +173,7 @@ struct vf610_adc {
  u32 sample_freq_avail[5];
   
  struct completion completion;
  +   u16 buffer[8];
   };
   
   static const u32 vf610_hw_avgs[] = { 1, 4, 8, 16, 32 };
  @@ -505,12 +509,24 @@ static const struct iio_chan_spec_ext_info 
  vf610_ext_info[] = {
  .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |  \
  BIT(IIO_CHAN_INFO_SAMP_FREQ),   \
  .ext_info = vf610_ext_info, \
  +   .scan_index = (_idx),   \
  +   .scan_type = {  \
  +   .sign = 'u',\
  +   .realbits = 12, \
  +   .storagebits = 16,  \
  +   },  \
   }
   
   #define VF610_ADC_TEMPERATURE_CHAN(_idx, _chan_type) { \
  .type = (_chan_type),   \
  .channel = (_idx),  \
  .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), \
  +   .scan_index = (_idx),   \
  +   .scan_type = {  \
  +   .sign = 'u',\
  +   .realbits = 12, \
  +   .storagebits = 16,  \
  +   },  \
   }
   
   static const struct iio_chan_spec vf610_adc_iio_channels[] = {
  @@ -531,6 +547,7 @@ static const struct iio_chan_spec 
  vf610_adc_iio_channels[] = {
  VF610_ADC_CHAN(14, IIO_VOLTAGE),
  VF610_ADC_CHAN(15, IIO_VOLTAGE),
  VF610_ADC_TEMPERATURE_CHAN(26, IIO_TEMP),
  +   IIO_CHAN_SOFT_TIMESTAMP(32),
  /* sentinel */
   };
   
  @@ -559,13 +576,20 @@ static int vf610_adc_read_data(struct vf610_adc *info)
   
   static irqreturn_t vf610_adc_isr(int irq, void *dev_id)
   {
  -   struct vf610_adc *info = (struct vf610_adc *)dev_id;
  +   struct iio_dev *indio_dev = (struct iio_dev *)dev_id;
  +   struct vf610_adc *info = iio_priv(indio_dev);
  int coco;
   
  coco = readl(info-regs + VF610_REG_ADC_HS);
  if (coco  VF610_ADC_HS_COCO0) {
  info-value = vf610_adc_read_data(info);
  -   complete(info-completion);
  +   if (iio_buffer_enabled(indio_dev)) {
  +   info-buffer[0] = info-value;
  +   iio_push_to_buffers_with_timestamp(indio_dev,
  +   info-buffer, iio_get_time_ns());
  +   iio_trigger_notify_done(indio_dev-trig);
  +   } else
  +   complete(info-completion);
  }
   
  return IRQ_HANDLED;
  @@ -613,8 +637,12 @@ static int vf610_read_raw(struct iio_dev *indio_dev,
  case IIO_CHAN_INFO_RAW:
  case IIO_CHAN_INFO_PROCESSED:
  mutex_lock(indio_dev-mlock);
  -   reinit_completion(info-completion);
  +   if (iio_buffer_enabled(indio_dev)) {
  +   mutex_unlock(indio_dev-mlock);
  +   return -EBUSY;
  +   }
   
  +   reinit_completion(info-completion);
  

Re: [PATCH v3] iio: adc: vf610: Add IIO buffer support for Vybrid ADC

2015-08-15 Thread Jonathan Cameron
On 11/08/15 10:05, Sanchayan Maity wrote:
> This patch adds support for IIO buffer to the Vybrid ADC driver.
> IIO triggered buffer infrastructure along with iio sysfs trigger
> is used to leverage continuous sampling support provided by the
> ADC block.
> 
> Signed-off-by: Sanchayan Maity 
Hi Sanchayan,

Very nearly there. One little point to do with the buffer handling.
Basically I don't think you want anything in the preenable or
postdisable hooks, just in the 'internal' ones.

Jonathan
> ---
>  drivers/iio/adc/Kconfig |   2 +
>  drivers/iio/adc/vf610_adc.c | 102 
> +---
>  2 files changed, 97 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
> index 7c55658..660f790 100644
> --- a/drivers/iio/adc/Kconfig
> +++ b/drivers/iio/adc/Kconfig
> @@ -337,6 +337,8 @@ config TWL6030_GPADC
>  config VF610_ADC
>   tristate "Freescale vf610 ADC driver"
>   depends on OF
> + select IIO_BUFFER
> + select IIO_TRIGGERED_BUFFER
>   help
> Say yes here to support for Vybrid board analog-to-digital converter.
> Since the IP is used for i.MX6SLX, the driver also support i.MX6SLX.
> diff --git a/drivers/iio/adc/vf610_adc.c b/drivers/iio/adc/vf610_adc.c
> index 23b8fb9..de62c48 100644
> --- a/drivers/iio/adc/vf610_adc.c
> +++ b/drivers/iio/adc/vf610_adc.c
> @@ -34,8 +34,11 @@
>  #include 
>  
>  #include 
> +#include 
>  #include 
> -#include 
> +#include 
> +#include 
> +#include 
>  
>  /* This will be the driver name the kernel reports */
>  #define DRIVER_NAME "vf610-adc"
> @@ -170,6 +173,7 @@ struct vf610_adc {
>   u32 sample_freq_avail[5];
>  
>   struct completion completion;
> + u16 buffer[8];
>  };
>  
>  static const u32 vf610_hw_avgs[] = { 1, 4, 8, 16, 32 };
> @@ -505,12 +509,24 @@ static const struct iio_chan_spec_ext_info 
> vf610_ext_info[] = {
>   .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |  \
>   BIT(IIO_CHAN_INFO_SAMP_FREQ),   \
>   .ext_info = vf610_ext_info, \
> + .scan_index = (_idx),   \
> + .scan_type = {  \
> + .sign = 'u',\
> + .realbits = 12, \
> + .storagebits = 16,  \
> + },  \
>  }
>  
>  #define VF610_ADC_TEMPERATURE_CHAN(_idx, _chan_type) {   \
>   .type = (_chan_type),   \
>   .channel = (_idx),  \
>   .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), \
> + .scan_index = (_idx),   \
> + .scan_type = {  \
> + .sign = 'u',\
> + .realbits = 12, \
> + .storagebits = 16,  \
> + },  \
>  }
>  
>  static const struct iio_chan_spec vf610_adc_iio_channels[] = {
> @@ -531,6 +547,7 @@ static const struct iio_chan_spec 
> vf610_adc_iio_channels[] = {
>   VF610_ADC_CHAN(14, IIO_VOLTAGE),
>   VF610_ADC_CHAN(15, IIO_VOLTAGE),
>   VF610_ADC_TEMPERATURE_CHAN(26, IIO_TEMP),
> + IIO_CHAN_SOFT_TIMESTAMP(32),
>   /* sentinel */
>  };
>  
> @@ -559,13 +576,20 @@ static int vf610_adc_read_data(struct vf610_adc *info)
>  
>  static irqreturn_t vf610_adc_isr(int irq, void *dev_id)
>  {
> - struct vf610_adc *info = (struct vf610_adc *)dev_id;
> + struct iio_dev *indio_dev = (struct iio_dev *)dev_id;
> + struct vf610_adc *info = iio_priv(indio_dev);
>   int coco;
>  
>   coco = readl(info->regs + VF610_REG_ADC_HS);
>   if (coco & VF610_ADC_HS_COCO0) {
>   info->value = vf610_adc_read_data(info);
> - complete(>completion);
> + if (iio_buffer_enabled(indio_dev)) {
> + info->buffer[0] = info->value;
> + iio_push_to_buffers_with_timestamp(indio_dev,
> + info->buffer, iio_get_time_ns());
> + iio_trigger_notify_done(indio_dev->trig);
> + } else
> + complete(>completion);
>   }
>  
>   return IRQ_HANDLED;
> @@ -613,8 +637,12 @@ static int vf610_read_raw(struct iio_dev *indio_dev,
>   case IIO_CHAN_INFO_RAW:
>   case IIO_CHAN_INFO_PROCESSED:
>   mutex_lock(_dev->mlock);
> - reinit_completion(>completion);
> + if (iio_buffer_enabled(indio_dev)) {
> + mutex_unlock(_dev->mlock);
> + return -EBUSY;
> + }
>  
> + reinit_completion(>completion);
>   hc_cfg = VF610_ADC_ADCHC(chan->channel);
>   hc_cfg |= VF610_ADC_AIEN;
>   writel(hc_cfg, info->regs + 

Re: [PATCH v3] iio: adc: vf610: Add IIO buffer support for Vybrid ADC

2015-08-15 Thread Jonathan Cameron
On 11/08/15 10:05, Sanchayan Maity wrote:
 This patch adds support for IIO buffer to the Vybrid ADC driver.
 IIO triggered buffer infrastructure along with iio sysfs trigger
 is used to leverage continuous sampling support provided by the
 ADC block.
 
 Signed-off-by: Sanchayan Maity maitysancha...@gmail.com
Hi Sanchayan,

Very nearly there. One little point to do with the buffer handling.
Basically I don't think you want anything in the preenable or
postdisable hooks, just in the 'internal' ones.

Jonathan
 ---
  drivers/iio/adc/Kconfig |   2 +
  drivers/iio/adc/vf610_adc.c | 102 
 +---
  2 files changed, 97 insertions(+), 7 deletions(-)
 
 diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
 index 7c55658..660f790 100644
 --- a/drivers/iio/adc/Kconfig
 +++ b/drivers/iio/adc/Kconfig
 @@ -337,6 +337,8 @@ config TWL6030_GPADC
  config VF610_ADC
   tristate Freescale vf610 ADC driver
   depends on OF
 + select IIO_BUFFER
 + select IIO_TRIGGERED_BUFFER
   help
 Say yes here to support for Vybrid board analog-to-digital converter.
 Since the IP is used for i.MX6SLX, the driver also support i.MX6SLX.
 diff --git a/drivers/iio/adc/vf610_adc.c b/drivers/iio/adc/vf610_adc.c
 index 23b8fb9..de62c48 100644
 --- a/drivers/iio/adc/vf610_adc.c
 +++ b/drivers/iio/adc/vf610_adc.c
 @@ -34,8 +34,11 @@
  #include linux/err.h
  
  #include linux/iio/iio.h
 +#include linux/iio/buffer.h
  #include linux/iio/sysfs.h
 -#include linux/iio/driver.h
 +#include linux/iio/trigger.h
 +#include linux/iio/trigger_consumer.h
 +#include linux/iio/triggered_buffer.h
  
  /* This will be the driver name the kernel reports */
  #define DRIVER_NAME vf610-adc
 @@ -170,6 +173,7 @@ struct vf610_adc {
   u32 sample_freq_avail[5];
  
   struct completion completion;
 + u16 buffer[8];
  };
  
  static const u32 vf610_hw_avgs[] = { 1, 4, 8, 16, 32 };
 @@ -505,12 +509,24 @@ static const struct iio_chan_spec_ext_info 
 vf610_ext_info[] = {
   .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |  \
   BIT(IIO_CHAN_INFO_SAMP_FREQ),   \
   .ext_info = vf610_ext_info, \
 + .scan_index = (_idx),   \
 + .scan_type = {  \
 + .sign = 'u',\
 + .realbits = 12, \
 + .storagebits = 16,  \
 + },  \
  }
  
  #define VF610_ADC_TEMPERATURE_CHAN(_idx, _chan_type) {   \
   .type = (_chan_type),   \
   .channel = (_idx),  \
   .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), \
 + .scan_index = (_idx),   \
 + .scan_type = {  \
 + .sign = 'u',\
 + .realbits = 12, \
 + .storagebits = 16,  \
 + },  \
  }
  
  static const struct iio_chan_spec vf610_adc_iio_channels[] = {
 @@ -531,6 +547,7 @@ static const struct iio_chan_spec 
 vf610_adc_iio_channels[] = {
   VF610_ADC_CHAN(14, IIO_VOLTAGE),
   VF610_ADC_CHAN(15, IIO_VOLTAGE),
   VF610_ADC_TEMPERATURE_CHAN(26, IIO_TEMP),
 + IIO_CHAN_SOFT_TIMESTAMP(32),
   /* sentinel */
  };
  
 @@ -559,13 +576,20 @@ static int vf610_adc_read_data(struct vf610_adc *info)
  
  static irqreturn_t vf610_adc_isr(int irq, void *dev_id)
  {
 - struct vf610_adc *info = (struct vf610_adc *)dev_id;
 + struct iio_dev *indio_dev = (struct iio_dev *)dev_id;
 + struct vf610_adc *info = iio_priv(indio_dev);
   int coco;
  
   coco = readl(info-regs + VF610_REG_ADC_HS);
   if (coco  VF610_ADC_HS_COCO0) {
   info-value = vf610_adc_read_data(info);
 - complete(info-completion);
 + if (iio_buffer_enabled(indio_dev)) {
 + info-buffer[0] = info-value;
 + iio_push_to_buffers_with_timestamp(indio_dev,
 + info-buffer, iio_get_time_ns());
 + iio_trigger_notify_done(indio_dev-trig);
 + } else
 + complete(info-completion);
   }
  
   return IRQ_HANDLED;
 @@ -613,8 +637,12 @@ static int vf610_read_raw(struct iio_dev *indio_dev,
   case IIO_CHAN_INFO_RAW:
   case IIO_CHAN_INFO_PROCESSED:
   mutex_lock(indio_dev-mlock);
 - reinit_completion(info-completion);
 + if (iio_buffer_enabled(indio_dev)) {
 + mutex_unlock(indio_dev-mlock);
 + return -EBUSY;
 + }
  
 + reinit_completion(info-completion);
   hc_cfg = VF610_ADC_ADCHC(chan-channel);
   hc_cfg |= 

[PATCH v3] iio: adc: vf610: Add IIO buffer support for Vybrid ADC

2015-08-11 Thread Sanchayan Maity
This patch adds support for IIO buffer to the Vybrid ADC driver.
IIO triggered buffer infrastructure along with iio sysfs trigger
is used to leverage continuous sampling support provided by the
ADC block.

Signed-off-by: Sanchayan Maity 
---
 drivers/iio/adc/Kconfig |   2 +
 drivers/iio/adc/vf610_adc.c | 102 +---
 2 files changed, 97 insertions(+), 7 deletions(-)

diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 7c55658..660f790 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -337,6 +337,8 @@ config TWL6030_GPADC
 config VF610_ADC
tristate "Freescale vf610 ADC driver"
depends on OF
+   select IIO_BUFFER
+   select IIO_TRIGGERED_BUFFER
help
  Say yes here to support for Vybrid board analog-to-digital converter.
  Since the IP is used for i.MX6SLX, the driver also support i.MX6SLX.
diff --git a/drivers/iio/adc/vf610_adc.c b/drivers/iio/adc/vf610_adc.c
index 23b8fb9..de62c48 100644
--- a/drivers/iio/adc/vf610_adc.c
+++ b/drivers/iio/adc/vf610_adc.c
@@ -34,8 +34,11 @@
 #include 
 
 #include 
+#include 
 #include 
-#include 
+#include 
+#include 
+#include 
 
 /* This will be the driver name the kernel reports */
 #define DRIVER_NAME "vf610-adc"
@@ -170,6 +173,7 @@ struct vf610_adc {
u32 sample_freq_avail[5];
 
struct completion completion;
+   u16 buffer[8];
 };
 
 static const u32 vf610_hw_avgs[] = { 1, 4, 8, 16, 32 };
@@ -505,12 +509,24 @@ static const struct iio_chan_spec_ext_info 
vf610_ext_info[] = {
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |  \
BIT(IIO_CHAN_INFO_SAMP_FREQ),   \
.ext_info = vf610_ext_info, \
+   .scan_index = (_idx),   \
+   .scan_type = {  \
+   .sign = 'u',\
+   .realbits = 12, \
+   .storagebits = 16,  \
+   },  \
 }
 
 #define VF610_ADC_TEMPERATURE_CHAN(_idx, _chan_type) { \
.type = (_chan_type),   \
.channel = (_idx),  \
.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), \
+   .scan_index = (_idx),   \
+   .scan_type = {  \
+   .sign = 'u',\
+   .realbits = 12, \
+   .storagebits = 16,  \
+   },  \
 }
 
 static const struct iio_chan_spec vf610_adc_iio_channels[] = {
@@ -531,6 +547,7 @@ static const struct iio_chan_spec vf610_adc_iio_channels[] 
= {
VF610_ADC_CHAN(14, IIO_VOLTAGE),
VF610_ADC_CHAN(15, IIO_VOLTAGE),
VF610_ADC_TEMPERATURE_CHAN(26, IIO_TEMP),
+   IIO_CHAN_SOFT_TIMESTAMP(32),
/* sentinel */
 };
 
@@ -559,13 +576,20 @@ static int vf610_adc_read_data(struct vf610_adc *info)
 
 static irqreturn_t vf610_adc_isr(int irq, void *dev_id)
 {
-   struct vf610_adc *info = (struct vf610_adc *)dev_id;
+   struct iio_dev *indio_dev = (struct iio_dev *)dev_id;
+   struct vf610_adc *info = iio_priv(indio_dev);
int coco;
 
coco = readl(info->regs + VF610_REG_ADC_HS);
if (coco & VF610_ADC_HS_COCO0) {
info->value = vf610_adc_read_data(info);
-   complete(>completion);
+   if (iio_buffer_enabled(indio_dev)) {
+   info->buffer[0] = info->value;
+   iio_push_to_buffers_with_timestamp(indio_dev,
+   info->buffer, iio_get_time_ns());
+   iio_trigger_notify_done(indio_dev->trig);
+   } else
+   complete(>completion);
}
 
return IRQ_HANDLED;
@@ -613,8 +637,12 @@ static int vf610_read_raw(struct iio_dev *indio_dev,
case IIO_CHAN_INFO_RAW:
case IIO_CHAN_INFO_PROCESSED:
mutex_lock(_dev->mlock);
-   reinit_completion(>completion);
+   if (iio_buffer_enabled(indio_dev)) {
+   mutex_unlock(_dev->mlock);
+   return -EBUSY;
+   }
 
+   reinit_completion(>completion);
hc_cfg = VF610_ADC_ADCHC(chan->channel);
hc_cfg |= VF610_ADC_AIEN;
writel(hc_cfg, info->regs + VF610_REG_ADC_HC0);
@@ -694,6 +722,57 @@ static int vf610_write_raw(struct iio_dev *indio_dev,
return -EINVAL;
 }
 
+static int vf610_adc_buffer_postenable(struct iio_dev *indio_dev)
+{
+   struct vf610_adc *info = iio_priv(indio_dev);
+   unsigned int channel;
+   int ret;
+   int val;
+
+   ret = iio_triggered_buffer_postenable(indio_dev);
+   if (ret)

[PATCH v3] iio: adc: vf610: Add IIO buffer support for Vybrid ADC

2015-08-11 Thread Sanchayan Maity
This patch adds support for IIO buffer to the Vybrid ADC driver.
IIO triggered buffer infrastructure along with iio sysfs trigger
is used to leverage continuous sampling support provided by the
ADC block.

Signed-off-by: Sanchayan Maity maitysancha...@gmail.com
---
 drivers/iio/adc/Kconfig |   2 +
 drivers/iio/adc/vf610_adc.c | 102 +---
 2 files changed, 97 insertions(+), 7 deletions(-)

diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 7c55658..660f790 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -337,6 +337,8 @@ config TWL6030_GPADC
 config VF610_ADC
tristate Freescale vf610 ADC driver
depends on OF
+   select IIO_BUFFER
+   select IIO_TRIGGERED_BUFFER
help
  Say yes here to support for Vybrid board analog-to-digital converter.
  Since the IP is used for i.MX6SLX, the driver also support i.MX6SLX.
diff --git a/drivers/iio/adc/vf610_adc.c b/drivers/iio/adc/vf610_adc.c
index 23b8fb9..de62c48 100644
--- a/drivers/iio/adc/vf610_adc.c
+++ b/drivers/iio/adc/vf610_adc.c
@@ -34,8 +34,11 @@
 #include linux/err.h
 
 #include linux/iio/iio.h
+#include linux/iio/buffer.h
 #include linux/iio/sysfs.h
-#include linux/iio/driver.h
+#include linux/iio/trigger.h
+#include linux/iio/trigger_consumer.h
+#include linux/iio/triggered_buffer.h
 
 /* This will be the driver name the kernel reports */
 #define DRIVER_NAME vf610-adc
@@ -170,6 +173,7 @@ struct vf610_adc {
u32 sample_freq_avail[5];
 
struct completion completion;
+   u16 buffer[8];
 };
 
 static const u32 vf610_hw_avgs[] = { 1, 4, 8, 16, 32 };
@@ -505,12 +509,24 @@ static const struct iio_chan_spec_ext_info 
vf610_ext_info[] = {
.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |  \
BIT(IIO_CHAN_INFO_SAMP_FREQ),   \
.ext_info = vf610_ext_info, \
+   .scan_index = (_idx),   \
+   .scan_type = {  \
+   .sign = 'u',\
+   .realbits = 12, \
+   .storagebits = 16,  \
+   },  \
 }
 
 #define VF610_ADC_TEMPERATURE_CHAN(_idx, _chan_type) { \
.type = (_chan_type),   \
.channel = (_idx),  \
.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), \
+   .scan_index = (_idx),   \
+   .scan_type = {  \
+   .sign = 'u',\
+   .realbits = 12, \
+   .storagebits = 16,  \
+   },  \
 }
 
 static const struct iio_chan_spec vf610_adc_iio_channels[] = {
@@ -531,6 +547,7 @@ static const struct iio_chan_spec vf610_adc_iio_channels[] 
= {
VF610_ADC_CHAN(14, IIO_VOLTAGE),
VF610_ADC_CHAN(15, IIO_VOLTAGE),
VF610_ADC_TEMPERATURE_CHAN(26, IIO_TEMP),
+   IIO_CHAN_SOFT_TIMESTAMP(32),
/* sentinel */
 };
 
@@ -559,13 +576,20 @@ static int vf610_adc_read_data(struct vf610_adc *info)
 
 static irqreturn_t vf610_adc_isr(int irq, void *dev_id)
 {
-   struct vf610_adc *info = (struct vf610_adc *)dev_id;
+   struct iio_dev *indio_dev = (struct iio_dev *)dev_id;
+   struct vf610_adc *info = iio_priv(indio_dev);
int coco;
 
coco = readl(info-regs + VF610_REG_ADC_HS);
if (coco  VF610_ADC_HS_COCO0) {
info-value = vf610_adc_read_data(info);
-   complete(info-completion);
+   if (iio_buffer_enabled(indio_dev)) {
+   info-buffer[0] = info-value;
+   iio_push_to_buffers_with_timestamp(indio_dev,
+   info-buffer, iio_get_time_ns());
+   iio_trigger_notify_done(indio_dev-trig);
+   } else
+   complete(info-completion);
}
 
return IRQ_HANDLED;
@@ -613,8 +637,12 @@ static int vf610_read_raw(struct iio_dev *indio_dev,
case IIO_CHAN_INFO_RAW:
case IIO_CHAN_INFO_PROCESSED:
mutex_lock(indio_dev-mlock);
-   reinit_completion(info-completion);
+   if (iio_buffer_enabled(indio_dev)) {
+   mutex_unlock(indio_dev-mlock);
+   return -EBUSY;
+   }
 
+   reinit_completion(info-completion);
hc_cfg = VF610_ADC_ADCHC(chan-channel);
hc_cfg |= VF610_ADC_AIEN;
writel(hc_cfg, info-regs + VF610_REG_ADC_HC0);
@@ -694,6 +722,57 @@ static int vf610_write_raw(struct iio_dev *indio_dev,
return -EINVAL;
 }
 
+static int vf610_adc_buffer_postenable(struct iio_dev *indio_dev)
+{
+