.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * exynos_adc.c - Support for ADC in EXYNOS SoCs |
---|
3 | 4 | * |
---|
4 | 5 | * 8 ~ 10 channel, 10/12-bit ADC |
---|
5 | 6 | * |
---|
6 | 7 | * Copyright (C) 2013 Naveen Krishna Chatradhi <ch.naveen@samsung.com> |
---|
7 | | - * |
---|
8 | | - * This program is free software; you can redistribute it and/or modify |
---|
9 | | - * it under the terms of the GNU General Public License as published by |
---|
10 | | - * the Free Software Foundation; either version 2 of the License, or |
---|
11 | | - * (at your option) any later version. |
---|
12 | | - * |
---|
13 | | - * This program is distributed in the hope that it will be useful, |
---|
14 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
15 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
16 | | - * GNU General Public License for more details. |
---|
17 | | - * |
---|
18 | | - * You should have received a copy of the GNU General Public License |
---|
19 | | - * along with this program; if not, write to the Free Software |
---|
20 | | - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
---|
21 | 8 | */ |
---|
22 | 9 | |
---|
23 | 10 | #include <linux/module.h> |
---|
.. | .. |
---|
151 | 138 | bool read_ts; |
---|
152 | 139 | u32 ts_x; |
---|
153 | 140 | u32 ts_y; |
---|
| 141 | + |
---|
| 142 | + /* |
---|
| 143 | + * Lock to protect from potential concurrent access to the |
---|
| 144 | + * completion callback during a manual conversion. For this driver |
---|
| 145 | + * a wait-callback is used to wait for the conversion result, |
---|
| 146 | + * so in the meantime no other read request (or conversion start) |
---|
| 147 | + * must be performed, otherwise it would interfere with the |
---|
| 148 | + * current conversion result. |
---|
| 149 | + */ |
---|
| 150 | + struct mutex lock; |
---|
154 | 151 | }; |
---|
155 | 152 | |
---|
156 | 153 | struct exynos_adc_data { |
---|
.. | .. |
---|
462 | 459 | { |
---|
463 | 460 | u32 con1, con2; |
---|
464 | 461 | |
---|
465 | | - if (info->data->needs_adc_phy) |
---|
466 | | - regmap_write(info->pmu_map, info->data->phy_offset, 1); |
---|
467 | | - |
---|
468 | 462 | con1 = ADC_V2_CON1_SOFT_RESET; |
---|
469 | 463 | writel(con1, ADC_V2_CON1(info->regs)); |
---|
470 | 464 | |
---|
.. | .. |
---|
544 | 538 | unsigned long timeout; |
---|
545 | 539 | int ret; |
---|
546 | 540 | |
---|
547 | | - if (mask != IIO_CHAN_INFO_RAW) |
---|
548 | | - return -EINVAL; |
---|
| 541 | + if (mask == IIO_CHAN_INFO_SCALE) { |
---|
| 542 | + ret = regulator_get_voltage(info->vdd); |
---|
| 543 | + if (ret < 0) |
---|
| 544 | + return ret; |
---|
549 | 545 | |
---|
550 | | - mutex_lock(&indio_dev->mlock); |
---|
| 546 | + /* Regulator voltage is in uV, but need mV */ |
---|
| 547 | + *val = ret / 1000; |
---|
| 548 | + *val2 = info->data->mask; |
---|
| 549 | + |
---|
| 550 | + return IIO_VAL_FRACTIONAL; |
---|
| 551 | + } else if (mask != IIO_CHAN_INFO_RAW) { |
---|
| 552 | + return -EINVAL; |
---|
| 553 | + } |
---|
| 554 | + |
---|
| 555 | + mutex_lock(&info->lock); |
---|
551 | 556 | reinit_completion(&info->completion); |
---|
552 | 557 | |
---|
553 | 558 | /* Select the channel to be used and Trigger conversion */ |
---|
.. | .. |
---|
567 | 572 | ret = IIO_VAL_INT; |
---|
568 | 573 | } |
---|
569 | 574 | |
---|
570 | | - mutex_unlock(&indio_dev->mlock); |
---|
| 575 | + mutex_unlock(&info->lock); |
---|
571 | 576 | |
---|
572 | 577 | return ret; |
---|
573 | 578 | } |
---|
.. | .. |
---|
578 | 583 | unsigned long timeout; |
---|
579 | 584 | int ret; |
---|
580 | 585 | |
---|
581 | | - mutex_lock(&indio_dev->mlock); |
---|
| 586 | + mutex_lock(&info->lock); |
---|
582 | 587 | info->read_ts = true; |
---|
583 | 588 | |
---|
584 | 589 | reinit_completion(&info->completion); |
---|
.. | .. |
---|
603 | 608 | } |
---|
604 | 609 | |
---|
605 | 610 | info->read_ts = false; |
---|
606 | | - mutex_unlock(&indio_dev->mlock); |
---|
| 611 | + mutex_unlock(&info->lock); |
---|
607 | 612 | |
---|
608 | 613 | return ret; |
---|
609 | 614 | } |
---|
.. | .. |
---|
664 | 669 | input_sync(info->input); |
---|
665 | 670 | |
---|
666 | 671 | usleep_range(1000, 1100); |
---|
667 | | - }; |
---|
| 672 | + } |
---|
668 | 673 | |
---|
669 | 674 | writel(0, ADC_V1_CLRINTPNDNUP(info->regs)); |
---|
670 | 675 | |
---|
.. | .. |
---|
696 | 701 | .channel = _index, \ |
---|
697 | 702 | .address = _index, \ |
---|
698 | 703 | .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \ |
---|
| 704 | + .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SCALE), \ |
---|
699 | 705 | .datasheet_name = _id, \ |
---|
700 | 706 | } |
---|
701 | 707 | |
---|
.. | .. |
---|
782 | 788 | struct device_node *np = pdev->dev.of_node; |
---|
783 | 789 | struct s3c2410_ts_mach_info *pdata = dev_get_platdata(&pdev->dev); |
---|
784 | 790 | struct iio_dev *indio_dev = NULL; |
---|
785 | | - struct resource *mem; |
---|
786 | 791 | bool has_ts = false; |
---|
787 | 792 | int ret = -ENODEV; |
---|
788 | 793 | int irq; |
---|
.. | .. |
---|
801 | 806 | return -EINVAL; |
---|
802 | 807 | } |
---|
803 | 808 | |
---|
804 | | - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
---|
805 | | - info->regs = devm_ioremap_resource(&pdev->dev, mem); |
---|
| 809 | + info->regs = devm_platform_ioremap_resource(pdev, 0); |
---|
806 | 810 | if (IS_ERR(info->regs)) |
---|
807 | 811 | return PTR_ERR(info->regs); |
---|
808 | 812 | |
---|
.. | .. |
---|
818 | 822 | } |
---|
819 | 823 | |
---|
820 | 824 | irq = platform_get_irq(pdev, 0); |
---|
821 | | - if (irq < 0) { |
---|
822 | | - dev_err(&pdev->dev, "no irq resource?\n"); |
---|
| 825 | + if (irq < 0) |
---|
823 | 826 | return irq; |
---|
824 | | - } |
---|
825 | 827 | info->irq = irq; |
---|
826 | 828 | |
---|
827 | 829 | irq = platform_get_irq(pdev, 1); |
---|
.. | .. |
---|
852 | 854 | } |
---|
853 | 855 | |
---|
854 | 856 | info->vdd = devm_regulator_get(&pdev->dev, "vdd"); |
---|
855 | | - if (IS_ERR(info->vdd)) { |
---|
856 | | - dev_err(&pdev->dev, "failed getting regulator, err = %ld\n", |
---|
857 | | - PTR_ERR(info->vdd)); |
---|
858 | | - return PTR_ERR(info->vdd); |
---|
859 | | - } |
---|
| 857 | + if (IS_ERR(info->vdd)) |
---|
| 858 | + return dev_err_probe(&pdev->dev, PTR_ERR(info->vdd), |
---|
| 859 | + "failed getting regulator"); |
---|
860 | 860 | |
---|
861 | 861 | ret = regulator_enable(info->vdd); |
---|
862 | 862 | if (ret) |
---|
.. | .. |
---|
873 | 873 | platform_set_drvdata(pdev, indio_dev); |
---|
874 | 874 | |
---|
875 | 875 | indio_dev->name = dev_name(&pdev->dev); |
---|
876 | | - indio_dev->dev.parent = &pdev->dev; |
---|
877 | | - indio_dev->dev.of_node = pdev->dev.of_node; |
---|
878 | 876 | indio_dev->info = &exynos_adc_iio_info; |
---|
879 | 877 | indio_dev->modes = INDIO_DIRECT_MODE; |
---|
880 | 878 | indio_dev->channels = exynos_adc_iio_channels; |
---|
881 | 879 | indio_dev->num_channels = info->data->num_channels; |
---|
882 | 880 | |
---|
| 881 | + mutex_init(&info->lock); |
---|
| 882 | + |
---|
883 | 883 | ret = request_irq(info->irq, exynos_adc_isr, |
---|
884 | 884 | 0, dev_name(&pdev->dev), info); |
---|
885 | 885 | if (ret < 0) { |
---|