aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iio
diff options
context:
space:
mode:
authorLudovic Desroches <ludovic.desroches@atmel.com>2013-03-29 10:54:00 -0400
committerJonathan Cameron <jic23@kernel.org>2013-04-02 14:17:26 -0400
commit47be16b6683b86653545bf98f6f57019bb99969c (patch)
tree20ec6a5e68e53a79b363b38dac0030afabf4abae /drivers/iio
parent2fc72cd8354e3e9c4893fc082614266ddb599902 (diff)
iio: at91_adc: add low and high res support
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> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
Diffstat (limited to 'drivers/iio')
-rw-r--r--drivers/iio/adc/at91_adc.c74
1 files changed, 70 insertions, 4 deletions
diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c
index 6fc43c15f028..3fb3fe48a98c 100644
--- a/drivers/iio/adc/at91_adc.c
+++ b/drivers/iio/adc/at91_adc.c
@@ -57,6 +57,8 @@ struct at91_adc_state {
57 u32 trigger_number; 57 u32 trigger_number;
58 bool use_external; 58 bool use_external;
59 u32 vref_mv; 59 u32 vref_mv;
60 u32 res; /* resolution used for convertions */
61 bool low_res; /* the resolution corresponds to the lowest one */
60 wait_queue_head_t wq_data_avail; 62 wait_queue_head_t wq_data_avail;
61}; 63};
62 64
@@ -138,7 +140,7 @@ static int at91_adc_channel_init(struct iio_dev *idev)
138 chan->channel = bit; 140 chan->channel = bit;
139 chan->scan_index = idx; 141 chan->scan_index = idx;
140 chan->scan_type.sign = 'u'; 142 chan->scan_type.sign = 'u';
141 chan->scan_type.realbits = 10; 143 chan->scan_type.realbits = st->res;
142 chan->scan_type.storagebits = 16; 144 chan->scan_type.storagebits = 16;
143 chan->info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE); 145 chan->info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE);
144 chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW); 146 chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
@@ -372,6 +374,59 @@ static int at91_adc_read_raw(struct iio_dev *idev,
372 return -EINVAL; 374 return -EINVAL;
373} 375}
374 376
377static int at91_adc_of_get_resolution(struct at91_adc_state *st,
378 struct platform_device *pdev)
379{
380 struct iio_dev *idev = iio_priv_to_dev(st);
381 struct device_node *np = pdev->dev.of_node;
382 int count, i, ret = 0;
383 char *res_name, *s;
384 u32 *resolutions;
385
386 count = of_property_count_strings(np, "atmel,adc-res-names");
387 if (count < 2) {
388 dev_err(&idev->dev, "You must specified at least two resolution names for "
389 "adc-res-names property in the DT\n");
390 return count;
391 }
392
393 resolutions = kmalloc(count * sizeof(*resolutions), GFP_KERNEL);
394 if (!resolutions)
395 return -ENOMEM;
396
397 if (of_property_read_u32_array(np, "atmel,adc-res", resolutions, count)) {
398 dev_err(&idev->dev, "Missing adc-res property in the DT.\n");
399 ret = -ENODEV;
400 goto ret;
401 }
402
403 if (of_property_read_string(np, "atmel,adc-use-res", (const char **)&res_name))
404 res_name = "highres";
405
406 for (i = 0; i < count; i++) {
407 if (of_property_read_string_index(np, "atmel,adc-res-names", i, (const char **)&s))
408 continue;
409
410 if (strcmp(res_name, s))
411 continue;
412
413 st->res = resolutions[i];
414 if (!strcmp(res_name, "lowres"))
415 st->low_res = true;
416 else
417 st->low_res = false;
418
419 dev_info(&idev->dev, "Resolution used: %u bits\n", st->res);
420 goto ret;
421 }
422
423 dev_err(&idev->dev, "There is no resolution for %s\n", res_name);
424
425ret:
426 kfree(resolutions);
427 return ret;
428}
429
375static int at91_adc_probe_dt(struct at91_adc_state *st, 430static int at91_adc_probe_dt(struct at91_adc_state *st,
376 struct platform_device *pdev) 431 struct platform_device *pdev)
377{ 432{
@@ -415,6 +470,10 @@ static int at91_adc_probe_dt(struct at91_adc_state *st,
415 } 470 }
416 st->vref_mv = prop; 471 st->vref_mv = prop;
417 472
473 ret = at91_adc_of_get_resolution(st, pdev);
474 if (ret)
475 goto error_ret;
476
418 st->registers = devm_kzalloc(&idev->dev, 477 st->registers = devm_kzalloc(&idev->dev,
419 sizeof(struct at91_adc_reg_desc), 478 sizeof(struct at91_adc_reg_desc),
420 GFP_KERNEL); 479 GFP_KERNEL);
@@ -628,9 +687,16 @@ static int at91_adc_probe(struct platform_device *pdev)
628 */ 687 */
629 ticks = round_up((st->startup_time * adc_clk / 688 ticks = round_up((st->startup_time * adc_clk /
630 1000000) - 1, 8) / 8; 689 1000000) - 1, 8) / 8;
631 at91_adc_writel(st, AT91_ADC_MR, 690
632 (AT91_ADC_PRESCAL_(prsc) & AT91_ADC_PRESCAL) | 691 if (st->low_res)
633 (AT91_ADC_STARTUP_(ticks) & AT91_ADC_STARTUP)); 692 at91_adc_writel(st, AT91_ADC_MR,
693 AT91_ADC_LOWRES |
694 (AT91_ADC_PRESCAL_(prsc) & AT91_ADC_PRESCAL) |
695 (AT91_ADC_STARTUP_(ticks) & AT91_ADC_STARTUP));
696 else
697 at91_adc_writel(st, AT91_ADC_MR,
698 (AT91_ADC_PRESCAL_(prsc) & AT91_ADC_PRESCAL) |
699 (AT91_ADC_STARTUP_(ticks) & AT91_ADC_STARTUP));
634 700
635 /* Setup the ADC channels available on the board */ 701 /* Setup the ADC channels available on the board */
636 ret = at91_adc_channel_init(idev); 702 ret = at91_adc_channel_init(idev);