linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/3] iio: at91_adc: add lowres, sleep and sample&hold time missing support
@ 2013-03-29 14:54 ludovic.desroches at atmel.com
  2013-03-29 14:54 ` [PATCH 1/3] iio: at91_adc: add low and high res support ludovic.desroches at atmel.com
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: ludovic.desroches at atmel.com @ 2013-03-29 14:54 UTC (permalink / raw)
  To: linux-arm-kernel

From: Ludovic Desroches <ludovic.desroches@atmel.com>

Hi,

The current adc driver is missing some key feature support
  - select high/low resolution support
  - sleep mode
  - sample and hold Time

v2 changes:
- split dts part
- correct typo and documentation


Jean-Christophe PLAGNIOL-VILLARD (2):
  iio: at91_adc: add sleep mode support
  iio: at91_adc: fix missing Sample and Hold time

Ludovic Desroches (1):
  iio: at91_adc: add low and high res support

 .../devicetree/bindings/arm/atmel-adc.txt          | 13 ++++
 drivers/iio/adc/at91_adc.c                         | 90 ++++++++++++++++++++--
 2 files changed, 98 insertions(+), 5 deletions(-)

-- 
1.7.11.3

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/3] iio: at91_adc: add low and high res support
  2013-03-29 14:54 [PATCH v2 0/3] iio: at91_adc: add lowres, sleep and sample&hold time missing support ludovic.desroches at atmel.com
@ 2013-03-29 14:54 ` ludovic.desroches at atmel.com
  2013-04-02 18:20   ` Jonathan Cameron
  2013-03-29 14:54 ` [PATCH 2/3] iio: at91_adc: add sleep mode support ludovic.desroches at atmel.com
  2013-03-29 14:54 ` [PATCH 3/3] iio: at91_adc: fix missing Sample and Hold time ludovic.desroches at atmel.com
  2 siblings, 1 reply; 7+ messages in thread
From: ludovic.desroches at atmel.com @ 2013-03-29 14:54 UTC (permalink / raw)
  To: linux-arm-kernel

From: Ludovic Desroches <ludovic.desroches@atmel.com>

at91 adc offers the choice between two resolutions: low and high.
The low and high resolution values depends on adc IP version, as many IP
properties have been exposed through device tree, these settings have also
been added to the dt bindings.

Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com>
Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
---
 .../devicetree/bindings/arm/atmel-adc.txt          | 11 ++++
 drivers/iio/adc/at91_adc.c                         | 74 ++++++++++++++++++++--
 2 files changed, 81 insertions(+), 4 deletions(-)

diff --git a/Documentation/devicetree/bindings/arm/atmel-adc.txt b/Documentation/devicetree/bindings/arm/atmel-adc.txt
index c63097d..fd2d69e 100644
--- a/Documentation/devicetree/bindings/arm/atmel-adc.txt
+++ b/Documentation/devicetree/bindings/arm/atmel-adc.txt
@@ -14,9 +14,17 @@ Required properties:
   - atmel,adc-status-register: Offset of the Interrupt Status Register
   - atmel,adc-trigger-register: Offset of the Trigger Register
   - atmel,adc-vref: Reference voltage in millivolts for the conversions
+  - atmel,adc-res: List of resolution in bits supported by the ADC. List size
+		   must be two at least.
+  - atmel,adc-res-names: Contains one identifier string for each resolution
+			 in atmel,adc-res property. "lowres" and "highres"
+			 identifiers are required.
 
 Optional properties:
   - atmel,adc-use-external: Boolean to enable of external triggers
+  - atmel,adc-use-res: String corresponding to an identifier from
+		       atmel,adc-res-names property. If not specified, the highest
+		       resolution will be used.
  
 Optional trigger Nodes:
   - Required properties:
@@ -40,6 +48,9 @@ adc0: adc at fffb0000 {
 	atmel,adc-trigger-register = <0x08>;
 	atmel,adc-use-external;
 	atmel,adc-vref = <3300>;
+	atmel,adc-res = <8 10>;
+	atmel,adc-res-names = "lowres", "highres";
+	atmel,adc-use-res = "lowres";
 
 	trigger at 0 {
 		trigger-name = "external-rising";
diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c
index 83c836b..a7ad3e7 100644
--- a/drivers/iio/adc/at91_adc.c
+++ b/drivers/iio/adc/at91_adc.c
@@ -57,6 +57,8 @@ struct at91_adc_state {
 	u32			trigger_number;
 	bool			use_external;
 	u32			vref_mv;
+	u32			res;		/* resolution used for convertions */
+	bool			low_res;	/* the resolution corresponds to the lowest one */
 	wait_queue_head_t	wq_data_avail;
 };
 
@@ -138,7 +140,7 @@ static int at91_adc_channel_init(struct iio_dev *idev)
 		chan->channel = bit;
 		chan->scan_index = idx;
 		chan->scan_type.sign = 'u';
-		chan->scan_type.realbits = 10;
+		chan->scan_type.realbits = st->res;
 		chan->scan_type.storagebits = 16;
 		chan->info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT |
 			IIO_CHAN_INFO_RAW_SEPARATE_BIT;
@@ -372,6 +374,59 @@ static int at91_adc_read_raw(struct iio_dev *idev,
 	return -EINVAL;
 }
 
+static int at91_adc_of_get_resolution(struct at91_adc_state *st,
+				      struct platform_device *pdev)
+{
+	struct iio_dev *idev = iio_priv_to_dev(st);
+	struct device_node *np = pdev->dev.of_node;
+	int count, i, ret = 0;
+	char *res_name, *s;
+	u32 *resolutions;
+
+	count = of_property_count_strings(np, "atmel,adc-res-names");
+	if (count < 2) {
+		dev_err(&idev->dev, "You must specified at least two resolution names for "
+				    "adc-res-names property in the DT\n");
+		return count;
+	}
+
+	resolutions = kmalloc(count * sizeof(*resolutions), GFP_KERNEL);
+	if (!resolutions)
+		return -ENOMEM;
+
+	if (of_property_read_u32_array(np, "atmel,adc-res", resolutions, count)) {
+		dev_err(&idev->dev, "Missing adc-res property in the DT.\n");
+		ret = -ENODEV;
+		goto ret;
+	}
+
+	if (of_property_read_string(np, "atmel,adc-use-res", (const char **)&res_name))
+		res_name = "highres";
+
+	for (i = 0; i < count; i++) {
+		if (of_property_read_string_index(np, "atmel,adc-res-names", i, (const char **)&s))
+			continue;
+
+		if (strcmp(res_name, s))
+			continue;
+
+		st->res = resolutions[i];
+		if (!strcmp(res_name, "lowres"))
+			st->low_res = true;
+		else
+			st->low_res = false;
+
+		dev_info(&idev->dev, "Resolution used: %u bits\n", st->res);
+		goto ret;
+	}
+
+	dev_err(&idev->dev, "There is no resolution for %s\n", res_name);
+
+ret:
+	kfree(resolutions);
+	return ret;
+}
+
 static int at91_adc_probe_dt(struct at91_adc_state *st,
 			     struct platform_device *pdev)
 {
@@ -415,6 +470,10 @@ static int at91_adc_probe_dt(struct at91_adc_state *st,
 	}
 	st->vref_mv = prop;
 
+	ret = at91_adc_of_get_resolution(st, pdev);
+	if (ret)
+		goto error_ret;
+
 	st->registers = devm_kzalloc(&idev->dev,
 				     sizeof(struct at91_adc_reg_desc),
 				     GFP_KERNEL);
@@ -628,9 +687,16 @@ static int at91_adc_probe(struct platform_device *pdev)
 	 */
 	ticks = round_up((st->startup_time * adc_clk /
 			  1000000) - 1, 8) / 8;
-	at91_adc_writel(st, AT91_ADC_MR,
-			(AT91_ADC_PRESCAL_(prsc) & AT91_ADC_PRESCAL) |
-			(AT91_ADC_STARTUP_(ticks) & AT91_ADC_STARTUP));
+
+	if (st->low_res)
+		at91_adc_writel(st, AT91_ADC_MR,
+				AT91_ADC_LOWRES |
+				(AT91_ADC_PRESCAL_(prsc) & AT91_ADC_PRESCAL) |
+				(AT91_ADC_STARTUP_(ticks) & AT91_ADC_STARTUP));
+	else
+		at91_adc_writel(st, AT91_ADC_MR,
+				(AT91_ADC_PRESCAL_(prsc) & AT91_ADC_PRESCAL) |
+				(AT91_ADC_STARTUP_(ticks) & AT91_ADC_STARTUP));
 
 	/* Setup the ADC channels available on the board */
 	ret = at91_adc_channel_init(idev);
-- 
1.7.11.3

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 2/3] iio: at91_adc: add sleep mode support
  2013-03-29 14:54 [PATCH v2 0/3] iio: at91_adc: add lowres, sleep and sample&hold time missing support ludovic.desroches at atmel.com
  2013-03-29 14:54 ` [PATCH 1/3] iio: at91_adc: add low and high res support ludovic.desroches at atmel.com
@ 2013-03-29 14:54 ` ludovic.desroches at atmel.com
  2013-04-02 18:22   ` Jonathan Cameron
  2013-03-29 14:54 ` [PATCH 3/3] iio: at91_adc: fix missing Sample and Hold time ludovic.desroches at atmel.com
  2 siblings, 1 reply; 7+ messages in thread
From: ludovic.desroches at atmel.com @ 2013-03-29 14:54 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>

The sleep mode will allow to put the adc in sleep between conversion.

Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
[ludovic.desroches at atmel.com: correct typo]
Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com>
Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 Documentation/devicetree/bindings/arm/atmel-adc.txt |  1 +
 drivers/iio/adc/at91_adc.c                          | 19 ++++++++++---------
 2 files changed, 11 insertions(+), 9 deletions(-)

diff --git a/Documentation/devicetree/bindings/arm/atmel-adc.txt b/Documentation/devicetree/bindings/arm/atmel-adc.txt
index fd2d69e..3a05492 100644
--- a/Documentation/devicetree/bindings/arm/atmel-adc.txt
+++ b/Documentation/devicetree/bindings/arm/atmel-adc.txt
@@ -25,6 +25,7 @@ Optional properties:
   - atmel,adc-use-res: String corresponding to an identifier from
 		       atmel,adc-res-names property. If not specified, the highest
 		       resolution will be used.
+  - atmel,adc-sleep-mode: Boolean to enable sleep mode when no conversion
  
 Optional trigger Nodes:
   - Required properties:
diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c
index a7ad3e7..8e38f1c 100644
--- a/drivers/iio/adc/at91_adc.c
+++ b/drivers/iio/adc/at91_adc.c
@@ -52,6 +52,7 @@ struct at91_adc_state {
 	void __iomem		*reg_base;
 	struct at91_adc_reg_desc *registers;
 	u8			startup_time;
+	bool			sleep_mode;
 	struct iio_trigger	**trig;
 	struct at91_adc_trigger	*trigger_list;
 	u32			trigger_number;
@@ -455,6 +456,8 @@ static int at91_adc_probe_dt(struct at91_adc_state *st,
 	}
 	st->num_channels = prop;
 
+	st->sleep_mode = of_property_read_bool(node, "atmel,adc-sleep-mode");
+
 	if (of_property_read_u32(node, "atmel,adc-startup-time", &prop)) {
 		dev_err(&idev->dev, "Missing adc-startup-time property in the DT.\n");
 		ret = -EINVAL;
@@ -580,6 +583,7 @@ static int at91_adc_probe(struct platform_device *pdev)
 	struct iio_dev *idev;
 	struct at91_adc_state *st;
 	struct resource *res;
+	u32 reg;
 
 	idev = iio_device_alloc(sizeof(struct at91_adc_state));
 	if (idev == NULL) {
@@ -687,16 +691,13 @@ static int at91_adc_probe(struct platform_device *pdev)
 	 */
 	ticks = round_up((st->startup_time * adc_clk /
 			  1000000) - 1, 8) / 8;
-
+	reg = AT91_ADC_PRESCAL_(prsc) & AT91_ADC_PRESCAL;
+	reg |= AT91_ADC_STARTUP_(ticks) & AT91_ADC_STARTUP;
 	if (st->low_res)
-		at91_adc_writel(st, AT91_ADC_MR,
-				AT91_ADC_LOWRES |
-				(AT91_ADC_PRESCAL_(prsc) & AT91_ADC_PRESCAL) |
-				(AT91_ADC_STARTUP_(ticks) & AT91_ADC_STARTUP));
-	else
-		at91_adc_writel(st, AT91_ADC_MR,
-				(AT91_ADC_PRESCAL_(prsc) & AT91_ADC_PRESCAL) |
-				(AT91_ADC_STARTUP_(ticks) & AT91_ADC_STARTUP));
+		reg |= AT91_ADC_LOWRES;
+	if (st->sleep_mode)
+		reg |= AT91_ADC_SLEEP;
+	at91_adc_writel(st, AT91_ADC_MR, reg);
 
 	/* Setup the ADC channels available on the board */
 	ret = at91_adc_channel_init(idev);
-- 
1.7.11.3

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 3/3] iio: at91_adc: fix missing Sample and Hold time
  2013-03-29 14:54 [PATCH v2 0/3] iio: at91_adc: add lowres, sleep and sample&hold time missing support ludovic.desroches at atmel.com
  2013-03-29 14:54 ` [PATCH 1/3] iio: at91_adc: add low and high res support ludovic.desroches at atmel.com
  2013-03-29 14:54 ` [PATCH 2/3] iio: at91_adc: add sleep mode support ludovic.desroches at atmel.com
@ 2013-03-29 14:54 ` ludovic.desroches at atmel.com
  2013-04-02 18:24   ` Jonathan Cameron
  2 siblings, 1 reply; 7+ messages in thread
From: ludovic.desroches at atmel.com @ 2013-03-29 14:54 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>

On the at91_adc a minimal Sample and Hold Time is necessary for the ADC to
guarantee the best converted final value between two channels selection.
This time has to be programmed through the bitfield SHTIM in the
Mode Register ADC_MR.

Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
[ludovic.desroches at atmel.com: add unit for sample and hold time]
Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com>
---
 Documentation/devicetree/bindings/arm/atmel-adc.txt |  1 +
 drivers/iio/adc/at91_adc.c                          | 15 ++++++++++++++-
 2 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/arm/atmel-adc.txt b/Documentation/devicetree/bindings/arm/atmel-adc.txt
index 3a05492..16769d9 100644
--- a/Documentation/devicetree/bindings/arm/atmel-adc.txt
+++ b/Documentation/devicetree/bindings/arm/atmel-adc.txt
@@ -26,6 +26,7 @@ Optional properties:
 		       atmel,adc-res-names property. If not specified, the highest
 		       resolution will be used.
   - atmel,adc-sleep-mode: Boolean to enable sleep mode when no conversion
+  - atmel,adc-sample-hold-time: Sample and Hold Time in microseconds
  
 Optional trigger Nodes:
   - Required properties:
diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c
index 8e38f1c..69fe8d4 100644
--- a/drivers/iio/adc/at91_adc.c
+++ b/drivers/iio/adc/at91_adc.c
@@ -52,6 +52,7 @@ struct at91_adc_state {
 	void __iomem		*reg_base;
 	struct at91_adc_reg_desc *registers;
 	u8			startup_time;
+	u8			sample_hold_time;
 	bool			sleep_mode;
 	struct iio_trigger	**trig;
 	struct at91_adc_trigger	*trigger_list;
@@ -465,6 +466,9 @@ static int at91_adc_probe_dt(struct at91_adc_state *st,
 	}
 	st->startup_time = prop;
 
+	prop = 0;
+	of_property_read_u32(node, "atmel,adc-sample-hold-time", &prop);
+	st->sample_hold_time = prop;
 
 	if (of_property_read_u32(node, "atmel,adc-vref", &prop)) {
 		dev_err(&idev->dev, "Missing adc-vref property in the DT.\n");
@@ -578,7 +582,7 @@ static const struct iio_info at91_adc_info = {
 
 static int at91_adc_probe(struct platform_device *pdev)
 {
-	unsigned int prsc, mstrclk, ticks, adc_clk;
+	unsigned int prsc, mstrclk, ticks, adc_clk, shtim;
 	int ret;
 	struct iio_dev *idev;
 	struct at91_adc_state *st;
@@ -691,12 +695,21 @@ static int at91_adc_probe(struct platform_device *pdev)
 	 */
 	ticks = round_up((st->startup_time * adc_clk /
 			  1000000) - 1, 8) / 8;
+	/*
+	 * a minimal Sample and Hold Time is necessary for the ADC to guarantee
+	 * the best converted final value between two channels selection
+	 * The formula thus is : Sample and Hold Time = (shtim + 1) / ADCClock
+	 */
+	shtim = round_up((st->sample_hold_time * adc_clk /
+			  1000000) - 1, 1);
+
 	reg = AT91_ADC_PRESCAL_(prsc) & AT91_ADC_PRESCAL;
 	reg |= AT91_ADC_STARTUP_(ticks) & AT91_ADC_STARTUP;
 	if (st->low_res)
 		reg |= AT91_ADC_LOWRES;
 	if (st->sleep_mode)
 		reg |= AT91_ADC_SLEEP;
+	reg |= AT91_ADC_SHTIM_(shtim) & AT91_ADC_SHTIM;
 	at91_adc_writel(st, AT91_ADC_MR, reg);
 
 	/* Setup the ADC channels available on the board */
-- 
1.7.11.3

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 1/3] iio: at91_adc: add low and high res support
  2013-03-29 14:54 ` [PATCH 1/3] iio: at91_adc: add low and high res support ludovic.desroches at atmel.com
@ 2013-04-02 18:20   ` Jonathan Cameron
  0 siblings, 0 replies; 7+ messages in thread
From: Jonathan Cameron @ 2013-04-02 18:20 UTC (permalink / raw)
  To: linux-arm-kernel

On 03/29/2013 02:54 PM, ludovic.desroches at atmel.com wrote:
> From: Ludovic Desroches <ludovic.desroches@atmel.com>
> 
> at91 adc offers the choice between two resolutions: low and high.
> The low and high resolution values depends on adc IP version, as many IP
> properties have been exposed through device tree, these settings have also
> been added to the dt bindings.
> 
> Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com>
> Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
Applied to the togreg branch of iio.git

> ---
>  .../devicetree/bindings/arm/atmel-adc.txt          | 11 ++++
>  drivers/iio/adc/at91_adc.c                         | 74 ++++++++++++++++++++--
>  2 files changed, 81 insertions(+), 4 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/arm/atmel-adc.txt b/Documentation/devicetree/bindings/arm/atmel-adc.txt
> index c63097d..fd2d69e 100644
> --- a/Documentation/devicetree/bindings/arm/atmel-adc.txt
> +++ b/Documentation/devicetree/bindings/arm/atmel-adc.txt
> @@ -14,9 +14,17 @@ Required properties:
>    - atmel,adc-status-register: Offset of the Interrupt Status Register
>    - atmel,adc-trigger-register: Offset of the Trigger Register
>    - atmel,adc-vref: Reference voltage in millivolts for the conversions
> +  - atmel,adc-res: List of resolution in bits supported by the ADC. List size
> +		   must be two at least.
> +  - atmel,adc-res-names: Contains one identifier string for each resolution
> +			 in atmel,adc-res property. "lowres" and "highres"
> +			 identifiers are required.
>  
>  Optional properties:
>    - atmel,adc-use-external: Boolean to enable of external triggers
> +  - atmel,adc-use-res: String corresponding to an identifier from
> +		       atmel,adc-res-names property. If not specified, the highest
> +		       resolution will be used.
>   
>  Optional trigger Nodes:
>    - Required properties:
> @@ -40,6 +48,9 @@ adc0: adc at fffb0000 {
>  	atmel,adc-trigger-register = <0x08>;
>  	atmel,adc-use-external;
>  	atmel,adc-vref = <3300>;
> +	atmel,adc-res = <8 10>;
> +	atmel,adc-res-names = "lowres", "highres";
> +	atmel,adc-use-res = "lowres";
>  
>  	trigger at 0 {
>  		trigger-name = "external-rising";
> diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c
> index 83c836b..a7ad3e7 100644
> --- a/drivers/iio/adc/at91_adc.c
> +++ b/drivers/iio/adc/at91_adc.c
> @@ -57,6 +57,8 @@ struct at91_adc_state {
>  	u32			trigger_number;
>  	bool			use_external;
>  	u32			vref_mv;
> +	u32			res;		/* resolution used for convertions */
> +	bool			low_res;	/* the resolution corresponds to the lowest one */
>  	wait_queue_head_t	wq_data_avail;
>  };
>  
> @@ -138,7 +140,7 @@ static int at91_adc_channel_init(struct iio_dev *idev)
>  		chan->channel = bit;
>  		chan->scan_index = idx;
>  		chan->scan_type.sign = 'u';
> -		chan->scan_type.realbits = 10;
> +		chan->scan_type.realbits = st->res;
>  		chan->scan_type.storagebits = 16;
>  		chan->info_mask = IIO_CHAN_INFO_SCALE_SHARED_BIT |
>  			IIO_CHAN_INFO_RAW_SEPARATE_BIT;
> @@ -372,6 +374,59 @@ static int at91_adc_read_raw(struct iio_dev *idev,
>  	return -EINVAL;
>  }
>  
> +static int at91_adc_of_get_resolution(struct at91_adc_state *st,
> +				      struct platform_device *pdev)
> +{
> +	struct iio_dev *idev = iio_priv_to_dev(st);
> +	struct device_node *np = pdev->dev.of_node;
> +	int count, i, ret = 0;
> +	char *res_name, *s;
> +	u32 *resolutions;
> +
> +	count = of_property_count_strings(np, "atmel,adc-res-names");
> +	if (count < 2) {
> +		dev_err(&idev->dev, "You must specified at least two resolution names for "
> +				    "adc-res-names property in the DT\n");
> +		return count;
> +	}
> +
> +	resolutions = kmalloc(count * sizeof(*resolutions), GFP_KERNEL);
> +	if (!resolutions)
> +		return -ENOMEM;
> +
> +	if (of_property_read_u32_array(np, "atmel,adc-res", resolutions, count)) {
> +		dev_err(&idev->dev, "Missing adc-res property in the DT.\n");
> +		ret = -ENODEV;
> +		goto ret;
> +	}
> +
> +	if (of_property_read_string(np, "atmel,adc-use-res", (const char **)&res_name))
> +		res_name = "highres";
> +
> +	for (i = 0; i < count; i++) {
> +		if (of_property_read_string_index(np, "atmel,adc-res-names", i, (const char **)&s))
> +			continue;
> +
> +		if (strcmp(res_name, s))
> +			continue;
> +
> +		st->res = resolutions[i];
> +		if (!strcmp(res_name, "lowres"))
> +			st->low_res = true;
> +		else
> +			st->low_res = false;
> +
> +		dev_info(&idev->dev, "Resolution used: %u bits\n", st->res);
> +		goto ret;
> +	}
> +
> +	dev_err(&idev->dev, "There is no resolution for %s\n", res_name);
> +
> +ret:
> +	kfree(resolutions);
> +	return ret;
> +}
> +
>  static int at91_adc_probe_dt(struct at91_adc_state *st,
>  			     struct platform_device *pdev)
>  {
> @@ -415,6 +470,10 @@ static int at91_adc_probe_dt(struct at91_adc_state *st,
>  	}
>  	st->vref_mv = prop;
>  
> +	ret = at91_adc_of_get_resolution(st, pdev);
> +	if (ret)
> +		goto error_ret;
> +
>  	st->registers = devm_kzalloc(&idev->dev,
>  				     sizeof(struct at91_adc_reg_desc),
>  				     GFP_KERNEL);
> @@ -628,9 +687,16 @@ static int at91_adc_probe(struct platform_device *pdev)
>  	 */
>  	ticks = round_up((st->startup_time * adc_clk /
>  			  1000000) - 1, 8) / 8;
> -	at91_adc_writel(st, AT91_ADC_MR,
> -			(AT91_ADC_PRESCAL_(prsc) & AT91_ADC_PRESCAL) |
> -			(AT91_ADC_STARTUP_(ticks) & AT91_ADC_STARTUP));
> +
> +	if (st->low_res)
> +		at91_adc_writel(st, AT91_ADC_MR,
> +				AT91_ADC_LOWRES |
> +				(AT91_ADC_PRESCAL_(prsc) & AT91_ADC_PRESCAL) |
> +				(AT91_ADC_STARTUP_(ticks) & AT91_ADC_STARTUP));
> +	else
> +		at91_adc_writel(st, AT91_ADC_MR,
> +				(AT91_ADC_PRESCAL_(prsc) & AT91_ADC_PRESCAL) |
> +				(AT91_ADC_STARTUP_(ticks) & AT91_ADC_STARTUP));
>  
>  	/* Setup the ADC channels available on the board */
>  	ret = at91_adc_channel_init(idev);
> 

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 2/3] iio: at91_adc: add sleep mode support
  2013-03-29 14:54 ` [PATCH 2/3] iio: at91_adc: add sleep mode support ludovic.desroches at atmel.com
@ 2013-04-02 18:22   ` Jonathan Cameron
  0 siblings, 0 replies; 7+ messages in thread
From: Jonathan Cameron @ 2013-04-02 18:22 UTC (permalink / raw)
  To: linux-arm-kernel

On 03/29/2013 02:54 PM, ludovic.desroches at atmel.com wrote:
> From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
> 
> The sleep mode will allow to put the adc in sleep between conversion.
> 
> Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
I tied this next comment out.  Nice as is it is to make it clear
what contributions are, this looks pretty non standard in a block
that has a very specific purpose.

> [ludovic.desroches at atmel.com: correct typo]
> Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com>
> Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Applied to togreg branch of iio.git
> ---
>  Documentation/devicetree/bindings/arm/atmel-adc.txt |  1 +
>  drivers/iio/adc/at91_adc.c                          | 19 ++++++++++---------
>  2 files changed, 11 insertions(+), 9 deletions(-)
> 
> diff --git a/Documentation/devicetree/bindings/arm/atmel-adc.txt b/Documentation/devicetree/bindings/arm/atmel-adc.txt
> index fd2d69e..3a05492 100644
> --- a/Documentation/devicetree/bindings/arm/atmel-adc.txt
> +++ b/Documentation/devicetree/bindings/arm/atmel-adc.txt
> @@ -25,6 +25,7 @@ Optional properties:
>    - atmel,adc-use-res: String corresponding to an identifier from
>  		       atmel,adc-res-names property. If not specified, the highest
>  		       resolution will be used.
> +  - atmel,adc-sleep-mode: Boolean to enable sleep mode when no conversion
>   
>  Optional trigger Nodes:
>    - Required properties:
> diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c
> index a7ad3e7..8e38f1c 100644
> --- a/drivers/iio/adc/at91_adc.c
> +++ b/drivers/iio/adc/at91_adc.c
> @@ -52,6 +52,7 @@ struct at91_adc_state {
>  	void __iomem		*reg_base;
>  	struct at91_adc_reg_desc *registers;
>  	u8			startup_time;
> +	bool			sleep_mode;
>  	struct iio_trigger	**trig;
>  	struct at91_adc_trigger	*trigger_list;
>  	u32			trigger_number;
> @@ -455,6 +456,8 @@ static int at91_adc_probe_dt(struct at91_adc_state *st,
>  	}
>  	st->num_channels = prop;
>  
> +	st->sleep_mode = of_property_read_bool(node, "atmel,adc-sleep-mode");
> +
>  	if (of_property_read_u32(node, "atmel,adc-startup-time", &prop)) {
>  		dev_err(&idev->dev, "Missing adc-startup-time property in the DT.\n");
>  		ret = -EINVAL;
> @@ -580,6 +583,7 @@ static int at91_adc_probe(struct platform_device *pdev)
>  	struct iio_dev *idev;
>  	struct at91_adc_state *st;
>  	struct resource *res;
> +	u32 reg;
>  
>  	idev = iio_device_alloc(sizeof(struct at91_adc_state));
>  	if (idev == NULL) {
> @@ -687,16 +691,13 @@ static int at91_adc_probe(struct platform_device *pdev)
>  	 */
>  	ticks = round_up((st->startup_time * adc_clk /
>  			  1000000) - 1, 8) / 8;
> -
> +	reg = AT91_ADC_PRESCAL_(prsc) & AT91_ADC_PRESCAL;
> +	reg |= AT91_ADC_STARTUP_(ticks) & AT91_ADC_STARTUP;
>  	if (st->low_res)
> -		at91_adc_writel(st, AT91_ADC_MR,
> -				AT91_ADC_LOWRES |
> -				(AT91_ADC_PRESCAL_(prsc) & AT91_ADC_PRESCAL) |
> -				(AT91_ADC_STARTUP_(ticks) & AT91_ADC_STARTUP));
> -	else
> -		at91_adc_writel(st, AT91_ADC_MR,
> -				(AT91_ADC_PRESCAL_(prsc) & AT91_ADC_PRESCAL) |
> -				(AT91_ADC_STARTUP_(ticks) & AT91_ADC_STARTUP));
> +		reg |= AT91_ADC_LOWRES;
> +	if (st->sleep_mode)
> +		reg |= AT91_ADC_SLEEP;
> +	at91_adc_writel(st, AT91_ADC_MR, reg);
>  
>  	/* Setup the ADC channels available on the board */
>  	ret = at91_adc_channel_init(idev);
> 

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 3/3] iio: at91_adc: fix missing Sample and Hold time
  2013-03-29 14:54 ` [PATCH 3/3] iio: at91_adc: fix missing Sample and Hold time ludovic.desroches at atmel.com
@ 2013-04-02 18:24   ` Jonathan Cameron
  0 siblings, 0 replies; 7+ messages in thread
From: Jonathan Cameron @ 2013-04-02 18:24 UTC (permalink / raw)
  To: linux-arm-kernel

On 03/29/2013 02:54 PM, ludovic.desroches at atmel.com wrote:
> From: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
> 
> On the at91_adc a minimal Sample and Hold Time is necessary for the ADC to
> guarantee the best converted final value between two channels selection.
> This time has to be programmed through the bitfield SHTIM in the
> Mode Register ADC_MR.
> 
> Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
Again tidied this out of the patch description.  You handled it and
posted this revision so to my mind the sign off covers all we need
to know.

> [ludovic.desroches at atmel.com: add unit for sample and hold time]
> Signed-off-by: Ludovic Desroches <ludovic.desroches@atmel.com>
Applied to togreg branch of iio.git

> ---
>  Documentation/devicetree/bindings/arm/atmel-adc.txt |  1 +
>  drivers/iio/adc/at91_adc.c                          | 15 ++++++++++++++-
>  2 files changed, 15 insertions(+), 1 deletion(-)
> 
> diff --git a/Documentation/devicetree/bindings/arm/atmel-adc.txt b/Documentation/devicetree/bindings/arm/atmel-adc.txt
> index 3a05492..16769d9 100644
> --- a/Documentation/devicetree/bindings/arm/atmel-adc.txt
> +++ b/Documentation/devicetree/bindings/arm/atmel-adc.txt
> @@ -26,6 +26,7 @@ Optional properties:
>  		       atmel,adc-res-names property. If not specified, the highest
>  		       resolution will be used.
>    - atmel,adc-sleep-mode: Boolean to enable sleep mode when no conversion
> +  - atmel,adc-sample-hold-time: Sample and Hold Time in microseconds
>   
>  Optional trigger Nodes:
>    - Required properties:
> diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c
> index 8e38f1c..69fe8d4 100644
> --- a/drivers/iio/adc/at91_adc.c
> +++ b/drivers/iio/adc/at91_adc.c
> @@ -52,6 +52,7 @@ struct at91_adc_state {
>  	void __iomem		*reg_base;
>  	struct at91_adc_reg_desc *registers;
>  	u8			startup_time;
> +	u8			sample_hold_time;
>  	bool			sleep_mode;
>  	struct iio_trigger	**trig;
>  	struct at91_adc_trigger	*trigger_list;
> @@ -465,6 +466,9 @@ static int at91_adc_probe_dt(struct at91_adc_state *st,
>  	}
>  	st->startup_time = prop;
>  
> +	prop = 0;
> +	of_property_read_u32(node, "atmel,adc-sample-hold-time", &prop);
> +	st->sample_hold_time = prop;
>  
>  	if (of_property_read_u32(node, "atmel,adc-vref", &prop)) {
>  		dev_err(&idev->dev, "Missing adc-vref property in the DT.\n");
> @@ -578,7 +582,7 @@ static const struct iio_info at91_adc_info = {
>  
>  static int at91_adc_probe(struct platform_device *pdev)
>  {
> -	unsigned int prsc, mstrclk, ticks, adc_clk;
> +	unsigned int prsc, mstrclk, ticks, adc_clk, shtim;
>  	int ret;
>  	struct iio_dev *idev;
>  	struct at91_adc_state *st;
> @@ -691,12 +695,21 @@ static int at91_adc_probe(struct platform_device *pdev)
>  	 */
>  	ticks = round_up((st->startup_time * adc_clk /
>  			  1000000) - 1, 8) / 8;
> +	/*
> +	 * a minimal Sample and Hold Time is necessary for the ADC to guarantee
> +	 * the best converted final value between two channels selection
> +	 * The formula thus is : Sample and Hold Time = (shtim + 1) / ADCClock
> +	 */
> +	shtim = round_up((st->sample_hold_time * adc_clk /
> +			  1000000) - 1, 1);
> +
>  	reg = AT91_ADC_PRESCAL_(prsc) & AT91_ADC_PRESCAL;
>  	reg |= AT91_ADC_STARTUP_(ticks) & AT91_ADC_STARTUP;
>  	if (st->low_res)
>  		reg |= AT91_ADC_LOWRES;
>  	if (st->sleep_mode)
>  		reg |= AT91_ADC_SLEEP;
> +	reg |= AT91_ADC_SHTIM_(shtim) & AT91_ADC_SHTIM;
>  	at91_adc_writel(st, AT91_ADC_MR, reg);
>  
>  	/* Setup the ADC channels available on the board */
> 

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2013-04-02 18:24 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-03-29 14:54 [PATCH v2 0/3] iio: at91_adc: add lowres, sleep and sample&hold time missing support ludovic.desroches at atmel.com
2013-03-29 14:54 ` [PATCH 1/3] iio: at91_adc: add low and high res support ludovic.desroches at atmel.com
2013-04-02 18:20   ` Jonathan Cameron
2013-03-29 14:54 ` [PATCH 2/3] iio: at91_adc: add sleep mode support ludovic.desroches at atmel.com
2013-04-02 18:22   ` Jonathan Cameron
2013-03-29 14:54 ` [PATCH 3/3] iio: at91_adc: fix missing Sample and Hold time ludovic.desroches at atmel.com
2013-04-02 18:24   ` Jonathan Cameron

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).