| .. | .. |
|---|
| 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) { |
|---|