diff options
-rw-r--r-- | Documentation/devicetree/bindings/arm/atmel-adc.txt | 7 | ||||
-rw-r--r-- | arch/arm/mach-at91/include/mach/at91_adc.h | 9 | ||||
-rw-r--r-- | drivers/iio/adc/at91_adc.c | 79 |
3 files changed, 52 insertions, 43 deletions
diff --git a/Documentation/devicetree/bindings/arm/atmel-adc.txt b/Documentation/devicetree/bindings/arm/atmel-adc.txt index 16769d9cedd6..723c205cb10d 100644 --- a/Documentation/devicetree/bindings/arm/atmel-adc.txt +++ b/Documentation/devicetree/bindings/arm/atmel-adc.txt | |||
@@ -1,18 +1,15 @@ | |||
1 | * AT91's Analog to Digital Converter (ADC) | 1 | * AT91's Analog to Digital Converter (ADC) |
2 | 2 | ||
3 | Required properties: | 3 | Required properties: |
4 | - compatible: Should be "atmel,at91sam9260-adc" | 4 | - compatible: Should be "atmel,<chip>-adc" |
5 | <chip> can be "at91sam9260", "at91sam9g45" or "at91sam9x5" | ||
5 | - reg: Should contain ADC registers location and length | 6 | - reg: Should contain ADC registers location and length |
6 | - interrupts: Should contain the IRQ line for the ADC | 7 | - interrupts: Should contain the IRQ line for the ADC |
7 | - atmel,adc-channel-base: Offset of the first channel data register | ||
8 | - atmel,adc-channels-used: Bitmask of the channels muxed and enable for this | 8 | - atmel,adc-channels-used: Bitmask of the channels muxed and enable for this |
9 | device | 9 | device |
10 | - atmel,adc-drdy-mask: Mask of the DRDY interruption in the ADC | ||
11 | - atmel,adc-num-channels: Number of channels available in the ADC | 10 | - atmel,adc-num-channels: Number of channels available in the ADC |
12 | - atmel,adc-startup-time: Startup Time of the ADC in microseconds as | 11 | - atmel,adc-startup-time: Startup Time of the ADC in microseconds as |
13 | defined in the datasheet | 12 | defined in the datasheet |
14 | - atmel,adc-status-register: Offset of the Interrupt Status Register | ||
15 | - atmel,adc-trigger-register: Offset of the Trigger Register | ||
16 | - atmel,adc-vref: Reference voltage in millivolts for the conversions | 13 | - atmel,adc-vref: Reference voltage in millivolts for the conversions |
17 | - atmel,adc-res: List of resolution in bits supported by the ADC. List size | 14 | - atmel,adc-res: List of resolution in bits supported by the ADC. List size |
18 | must be two at least. | 15 | must be two at least. |
diff --git a/arch/arm/mach-at91/include/mach/at91_adc.h b/arch/arm/mach-at91/include/mach/at91_adc.h index 8e7ed5c90817..bea1a2021d1e 100644 --- a/arch/arm/mach-at91/include/mach/at91_adc.h +++ b/arch/arm/mach-at91/include/mach/at91_adc.h | |||
@@ -48,6 +48,9 @@ | |||
48 | #define AT91_ADC_ENDRX (1 << 18) /* End of RX Buffer */ | 48 | #define AT91_ADC_ENDRX (1 << 18) /* End of RX Buffer */ |
49 | #define AT91_ADC_RXFUFF (1 << 19) /* RX Buffer Full */ | 49 | #define AT91_ADC_RXFUFF (1 << 19) /* RX Buffer Full */ |
50 | 50 | ||
51 | #define AT91_ADC_SR_9X5 0x30 /* Status Register for 9x5 */ | ||
52 | #define AT91_ADC_SR_DRDY_9X5 (1 << 24) /* Data Ready */ | ||
53 | |||
51 | #define AT91_ADC_LCDR 0x20 /* Last Converted Data Register */ | 54 | #define AT91_ADC_LCDR 0x20 /* Last Converted Data Register */ |
52 | #define AT91_ADC_LDATA (0x3ff) | 55 | #define AT91_ADC_LDATA (0x3ff) |
53 | 56 | ||
@@ -58,4 +61,10 @@ | |||
58 | #define AT91_ADC_CHR(n) (0x30 + ((n) * 4)) /* Channel Data Register N */ | 61 | #define AT91_ADC_CHR(n) (0x30 + ((n) * 4)) /* Channel Data Register N */ |
59 | #define AT91_ADC_DATA (0x3ff) | 62 | #define AT91_ADC_DATA (0x3ff) |
60 | 63 | ||
64 | #define AT91_ADC_CDR0_9X5 (0x50) /* Channel Data Register 0 for 9X5 */ | ||
65 | |||
66 | #define AT91_ADC_TRGR_9260 AT91_ADC_MR | ||
67 | #define AT91_ADC_TRGR_9G45 0x08 | ||
68 | #define AT91_ADC_TRGR_9X5 0xC0 | ||
69 | |||
61 | #endif | 70 | #endif |
diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c index 423e079460d3..ed5eebc93bb7 100644 --- a/drivers/iio/adc/at91_adc.c +++ b/drivers/iio/adc/at91_adc.c | |||
@@ -39,6 +39,10 @@ | |||
39 | #define at91_adc_writel(st, reg, val) \ | 39 | #define at91_adc_writel(st, reg, val) \ |
40 | (writel_relaxed(val, st->reg_base + reg)) | 40 | (writel_relaxed(val, st->reg_base + reg)) |
41 | 41 | ||
42 | struct at91_adc_caps { | ||
43 | struct at91_adc_reg_desc registers; | ||
44 | }; | ||
45 | |||
42 | struct at91_adc_state { | 46 | struct at91_adc_state { |
43 | struct clk *adc_clk; | 47 | struct clk *adc_clk; |
44 | u16 *buffer; | 48 | u16 *buffer; |
@@ -62,6 +66,7 @@ struct at91_adc_state { | |||
62 | u32 res; /* resolution used for convertions */ | 66 | u32 res; /* resolution used for convertions */ |
63 | bool low_res; /* the resolution corresponds to the lowest one */ | 67 | bool low_res; /* the resolution corresponds to the lowest one */ |
64 | wait_queue_head_t wq_data_avail; | 68 | wait_queue_head_t wq_data_avail; |
69 | struct at91_adc_caps *caps; | ||
65 | }; | 70 | }; |
66 | 71 | ||
67 | static irqreturn_t at91_adc_trigger_handler(int irq, void *p) | 72 | static irqreturn_t at91_adc_trigger_handler(int irq, void *p) |
@@ -429,6 +434,8 @@ ret: | |||
429 | return ret; | 434 | return ret; |
430 | } | 435 | } |
431 | 436 | ||
437 | static const struct of_device_id at91_adc_dt_ids[]; | ||
438 | |||
432 | static int at91_adc_probe_dt(struct at91_adc_state *st, | 439 | static int at91_adc_probe_dt(struct at91_adc_state *st, |
433 | struct platform_device *pdev) | 440 | struct platform_device *pdev) |
434 | { | 441 | { |
@@ -441,6 +448,9 @@ static int at91_adc_probe_dt(struct at91_adc_state *st, | |||
441 | if (!node) | 448 | if (!node) |
442 | return -EINVAL; | 449 | return -EINVAL; |
443 | 450 | ||
451 | st->caps = (struct at91_adc_caps *) | ||
452 | of_match_device(at91_adc_dt_ids, &pdev->dev)->data; | ||
453 | |||
444 | st->use_external = of_property_read_bool(node, "atmel,adc-use-external-triggers"); | 454 | st->use_external = of_property_read_bool(node, "atmel,adc-use-external-triggers"); |
445 | 455 | ||
446 | if (of_property_read_u32(node, "atmel,adc-channels-used", &prop)) { | 456 | if (of_property_read_u32(node, "atmel,adc-channels-used", &prop)) { |
@@ -481,43 +491,7 @@ static int at91_adc_probe_dt(struct at91_adc_state *st, | |||
481 | if (ret) | 491 | if (ret) |
482 | goto error_ret; | 492 | goto error_ret; |
483 | 493 | ||
484 | st->registers = devm_kzalloc(&idev->dev, | 494 | st->registers = &st->caps->registers; |
485 | sizeof(struct at91_adc_reg_desc), | ||
486 | GFP_KERNEL); | ||
487 | if (!st->registers) { | ||
488 | dev_err(&idev->dev, "Could not allocate register memory.\n"); | ||
489 | ret = -ENOMEM; | ||
490 | goto error_ret; | ||
491 | } | ||
492 | |||
493 | if (of_property_read_u32(node, "atmel,adc-channel-base", &prop)) { | ||
494 | dev_err(&idev->dev, "Missing adc-channel-base property in the DT.\n"); | ||
495 | ret = -EINVAL; | ||
496 | goto error_ret; | ||
497 | } | ||
498 | st->registers->channel_base = prop; | ||
499 | |||
500 | if (of_property_read_u32(node, "atmel,adc-drdy-mask", &prop)) { | ||
501 | dev_err(&idev->dev, "Missing adc-drdy-mask property in the DT.\n"); | ||
502 | ret = -EINVAL; | ||
503 | goto error_ret; | ||
504 | } | ||
505 | st->registers->drdy_mask = prop; | ||
506 | |||
507 | if (of_property_read_u32(node, "atmel,adc-status-register", &prop)) { | ||
508 | dev_err(&idev->dev, "Missing adc-status-register property in the DT.\n"); | ||
509 | ret = -EINVAL; | ||
510 | goto error_ret; | ||
511 | } | ||
512 | st->registers->status_register = prop; | ||
513 | |||
514 | if (of_property_read_u32(node, "atmel,adc-trigger-register", &prop)) { | ||
515 | dev_err(&idev->dev, "Missing adc-trigger-register property in the DT.\n"); | ||
516 | ret = -EINVAL; | ||
517 | goto error_ret; | ||
518 | } | ||
519 | st->registers->trigger_register = prop; | ||
520 | |||
521 | st->trigger_number = of_get_child_count(node); | 495 | st->trigger_number = of_get_child_count(node); |
522 | st->trigger_list = devm_kzalloc(&idev->dev, st->trigger_number * | 496 | st->trigger_list = devm_kzalloc(&idev->dev, st->trigger_number * |
523 | sizeof(struct at91_adc_trigger), | 497 | sizeof(struct at91_adc_trigger), |
@@ -766,8 +740,37 @@ static int at91_adc_remove(struct platform_device *pdev) | |||
766 | } | 740 | } |
767 | 741 | ||
768 | #ifdef CONFIG_OF | 742 | #ifdef CONFIG_OF |
743 | static struct at91_adc_caps at91sam9260_caps = { | ||
744 | .registers = { | ||
745 | .channel_base = AT91_ADC_CHR(0), | ||
746 | .drdy_mask = AT91_ADC_DRDY, | ||
747 | .status_register = AT91_ADC_SR, | ||
748 | .trigger_register = AT91_ADC_TRGR_9260, | ||
749 | }, | ||
750 | }; | ||
751 | |||
752 | static struct at91_adc_caps at91sam9g45_caps = { | ||
753 | .registers = { | ||
754 | .channel_base = AT91_ADC_CHR(0), | ||
755 | .drdy_mask = AT91_ADC_DRDY, | ||
756 | .status_register = AT91_ADC_SR, | ||
757 | .trigger_register = AT91_ADC_TRGR_9G45, | ||
758 | }, | ||
759 | }; | ||
760 | |||
761 | static struct at91_adc_caps at91sam9x5_caps = { | ||
762 | .registers = { | ||
763 | .channel_base = AT91_ADC_CDR0_9X5, | ||
764 | .drdy_mask = AT91_ADC_SR_DRDY_9X5, | ||
765 | .status_register = AT91_ADC_SR_9X5, | ||
766 | .trigger_register = AT91_ADC_TRGR_9X5, | ||
767 | }, | ||
768 | }; | ||
769 | |||
769 | static const struct of_device_id at91_adc_dt_ids[] = { | 770 | static const struct of_device_id at91_adc_dt_ids[] = { |
770 | { .compatible = "atmel,at91sam9260-adc" }, | 771 | { .compatible = "atmel,at91sam9260-adc", .data = &at91sam9260_caps }, |
772 | { .compatible = "atmel,at91sam9g45-adc", .data = &at91sam9g45_caps }, | ||
773 | { .compatible = "atmel,at91sam9x5-adc", .data = &at91sam9x5_caps }, | ||
771 | {}, | 774 | {}, |
772 | }; | 775 | }; |
773 | MODULE_DEVICE_TABLE(of, at91_adc_dt_ids); | 776 | MODULE_DEVICE_TABLE(of, at91_adc_dt_ids); |