diff options
Diffstat (limited to 'drivers/iio/adc/at91_adc.c')
-rw-r--r-- | drivers/iio/adc/at91_adc.c | 113 |
1 files changed, 57 insertions, 56 deletions
diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c index b6db6a0e09cd..84be63bdf038 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), |
@@ -589,11 +563,9 @@ static int at91_adc_probe(struct platform_device *pdev) | |||
589 | struct resource *res; | 563 | struct resource *res; |
590 | u32 reg; | 564 | u32 reg; |
591 | 565 | ||
592 | idev = iio_device_alloc(sizeof(struct at91_adc_state)); | 566 | idev = devm_iio_device_alloc(&pdev->dev, sizeof(struct at91_adc_state)); |
593 | if (idev == NULL) { | 567 | if (!idev) |
594 | ret = -ENOMEM; | 568 | return -ENOMEM; |
595 | goto error_ret; | ||
596 | } | ||
597 | 569 | ||
598 | st = iio_priv(idev); | 570 | st = iio_priv(idev); |
599 | 571 | ||
@@ -604,8 +576,7 @@ static int at91_adc_probe(struct platform_device *pdev) | |||
604 | 576 | ||
605 | if (ret) { | 577 | if (ret) { |
606 | dev_err(&pdev->dev, "No platform data available.\n"); | 578 | dev_err(&pdev->dev, "No platform data available.\n"); |
607 | ret = -EINVAL; | 579 | return -EINVAL; |
608 | goto error_free_device; | ||
609 | } | 580 | } |
610 | 581 | ||
611 | platform_set_drvdata(pdev, idev); | 582 | platform_set_drvdata(pdev, idev); |
@@ -618,16 +589,14 @@ static int at91_adc_probe(struct platform_device *pdev) | |||
618 | st->irq = platform_get_irq(pdev, 0); | 589 | st->irq = platform_get_irq(pdev, 0); |
619 | if (st->irq < 0) { | 590 | if (st->irq < 0) { |
620 | dev_err(&pdev->dev, "No IRQ ID is designated\n"); | 591 | dev_err(&pdev->dev, "No IRQ ID is designated\n"); |
621 | ret = -ENODEV; | 592 | return -ENODEV; |
622 | goto error_free_device; | ||
623 | } | 593 | } |
624 | 594 | ||
625 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 595 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
626 | 596 | ||
627 | st->reg_base = devm_ioremap_resource(&pdev->dev, res); | 597 | st->reg_base = devm_ioremap_resource(&pdev->dev, res); |
628 | if (IS_ERR(st->reg_base)) { | 598 | if (IS_ERR(st->reg_base)) { |
629 | ret = PTR_ERR(st->reg_base); | 599 | return PTR_ERR(st->reg_base); |
630 | goto error_free_device; | ||
631 | } | 600 | } |
632 | 601 | ||
633 | /* | 602 | /* |
@@ -642,7 +611,7 @@ static int at91_adc_probe(struct platform_device *pdev) | |||
642 | idev); | 611 | idev); |
643 | if (ret) { | 612 | if (ret) { |
644 | dev_err(&pdev->dev, "Failed to allocate IRQ.\n"); | 613 | dev_err(&pdev->dev, "Failed to allocate IRQ.\n"); |
645 | goto error_free_device; | 614 | return ret; |
646 | } | 615 | } |
647 | 616 | ||
648 | st->clk = devm_clk_get(&pdev->dev, "adc_clk"); | 617 | st->clk = devm_clk_get(&pdev->dev, "adc_clk"); |
@@ -703,8 +672,8 @@ static int at91_adc_probe(struct platform_device *pdev) | |||
703 | shtim = round_up((st->sample_hold_time * adc_clk / | 672 | shtim = round_up((st->sample_hold_time * adc_clk / |
704 | 1000000) - 1, 1); | 673 | 1000000) - 1, 1); |
705 | 674 | ||
706 | reg = AT91_ADC_PRESCAL_(prsc) & AT91_ADC_PRESCAL; | 675 | reg = AT91_ADC_PRESCAL_(prsc) & st->registers->mr_prescal_mask; |
707 | reg |= AT91_ADC_STARTUP_(ticks) & AT91_ADC_STARTUP; | 676 | reg |= AT91_ADC_STARTUP_(ticks) & st->registers->mr_startup_mask; |
708 | if (st->low_res) | 677 | if (st->low_res) |
709 | reg |= AT91_ADC_LOWRES; | 678 | reg |= AT91_ADC_LOWRES; |
710 | if (st->sleep_mode) | 679 | if (st->sleep_mode) |
@@ -752,9 +721,6 @@ error_disable_clk: | |||
752 | clk_disable_unprepare(st->clk); | 721 | clk_disable_unprepare(st->clk); |
753 | error_free_irq: | 722 | error_free_irq: |
754 | free_irq(st->irq, idev); | 723 | free_irq(st->irq, idev); |
755 | error_free_device: | ||
756 | iio_device_free(idev); | ||
757 | error_ret: | ||
758 | return ret; | 724 | return ret; |
759 | } | 725 | } |
760 | 726 | ||
@@ -769,14 +735,49 @@ static int at91_adc_remove(struct platform_device *pdev) | |||
769 | clk_disable_unprepare(st->adc_clk); | 735 | clk_disable_unprepare(st->adc_clk); |
770 | clk_disable_unprepare(st->clk); | 736 | clk_disable_unprepare(st->clk); |
771 | free_irq(st->irq, idev); | 737 | free_irq(st->irq, idev); |
772 | iio_device_free(idev); | ||
773 | 738 | ||
774 | return 0; | 739 | return 0; |
775 | } | 740 | } |
776 | 741 | ||
777 | #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 | .mr_prescal_mask = AT91_ADC_PRESCAL_9260, | ||
750 | .mr_startup_mask = AT91_ADC_STARTUP_9260, | ||
751 | }, | ||
752 | }; | ||
753 | |||
754 | static struct at91_adc_caps at91sam9g45_caps = { | ||
755 | .registers = { | ||
756 | .channel_base = AT91_ADC_CHR(0), | ||
757 | .drdy_mask = AT91_ADC_DRDY, | ||
758 | .status_register = AT91_ADC_SR, | ||
759 | .trigger_register = AT91_ADC_TRGR_9G45, | ||
760 | .mr_prescal_mask = AT91_ADC_PRESCAL_9G45, | ||
761 | .mr_startup_mask = AT91_ADC_STARTUP_9G45, | ||
762 | }, | ||
763 | }; | ||
764 | |||
765 | static struct at91_adc_caps at91sam9x5_caps = { | ||
766 | .registers = { | ||
767 | .channel_base = AT91_ADC_CDR0_9X5, | ||
768 | .drdy_mask = AT91_ADC_SR_DRDY_9X5, | ||
769 | .status_register = AT91_ADC_SR_9X5, | ||
770 | .trigger_register = AT91_ADC_TRGR_9X5, | ||
771 | /* prescal mask is same as 9G45 */ | ||
772 | .mr_prescal_mask = AT91_ADC_PRESCAL_9G45, | ||
773 | .mr_startup_mask = AT91_ADC_STARTUP_9X5, | ||
774 | }, | ||
775 | }; | ||
776 | |||
778 | static const struct of_device_id at91_adc_dt_ids[] = { | 777 | static const struct of_device_id at91_adc_dt_ids[] = { |
779 | { .compatible = "atmel,at91sam9260-adc" }, | 778 | { .compatible = "atmel,at91sam9260-adc", .data = &at91sam9260_caps }, |
779 | { .compatible = "atmel,at91sam9g45-adc", .data = &at91sam9g45_caps }, | ||
780 | { .compatible = "atmel,at91sam9x5-adc", .data = &at91sam9x5_caps }, | ||
780 | {}, | 781 | {}, |
781 | }; | 782 | }; |
782 | MODULE_DEVICE_TABLE(of, at91_adc_dt_ids); | 783 | MODULE_DEVICE_TABLE(of, at91_adc_dt_ids); |