[PATCH 1/3] iio: at91_adc: add low and high res support

Jonathan Cameron jic23 at kernel.org
Tue Apr 2 14:20:02 EDT 2013


On 03/29/2013 02:54 PM, ludovic.desroches at atmel.com wrote:
> From: Ludovic Desroches <ludovic.desroches at 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 at atmel.com>
> Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj at 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);
> 



More information about the linux-arm-kernel mailing list