13adbf342SMartin Blumenstingl /* 23adbf342SMartin Blumenstingl * Amlogic Meson Successive Approximation Register (SAR) A/D Converter 33adbf342SMartin Blumenstingl * 43adbf342SMartin Blumenstingl * Copyright (C) 2017 Martin Blumenstingl <martin.blumenstingl@googlemail.com> 53adbf342SMartin Blumenstingl * 63adbf342SMartin Blumenstingl * This program is free software; you can redistribute it and/or modify 73adbf342SMartin Blumenstingl * it under the terms of the GNU General Public License version 2 as 83adbf342SMartin Blumenstingl * published by the Free Software Foundation. 93adbf342SMartin Blumenstingl * 103adbf342SMartin Blumenstingl * You should have received a copy of the GNU General Public License 113adbf342SMartin Blumenstingl * along with this program. If not, see <http://www.gnu.org/licenses/>. 123adbf342SMartin Blumenstingl */ 133adbf342SMartin Blumenstingl 143adbf342SMartin Blumenstingl #include <linux/bitfield.h> 153adbf342SMartin Blumenstingl #include <linux/clk.h> 163adbf342SMartin Blumenstingl #include <linux/clk-provider.h> 173adbf342SMartin Blumenstingl #include <linux/delay.h> 183adbf342SMartin Blumenstingl #include <linux/io.h> 193adbf342SMartin Blumenstingl #include <linux/iio/iio.h> 203adbf342SMartin Blumenstingl #include <linux/module.h> 213af10913SHeiner Kallweit #include <linux/interrupt.h> 223adbf342SMartin Blumenstingl #include <linux/of.h> 233af10913SHeiner Kallweit #include <linux/of_irq.h> 243adbf342SMartin Blumenstingl #include <linux/of_device.h> 253adbf342SMartin Blumenstingl #include <linux/platform_device.h> 263adbf342SMartin Blumenstingl #include <linux/regmap.h> 273adbf342SMartin Blumenstingl #include <linux/regulator/consumer.h> 283adbf342SMartin Blumenstingl 293adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0 0x00 303adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_PANEL_DETECT BIT(31) 313adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_BUSY_MASK GENMASK(30, 28) 323adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_DELTA_BUSY BIT(30) 333adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_AVG_BUSY BIT(29) 343adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_SAMPLE_BUSY BIT(28) 353adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_FIFO_FULL BIT(27) 363adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_FIFO_EMPTY BIT(26) 373adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_FIFO_COUNT_MASK GENMASK(25, 21) 383adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_ADC_BIAS_CTRL_MASK GENMASK(20, 19) 393adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_CURR_CHAN_ID_MASK GENMASK(18, 16) 403adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_ADC_TEMP_SEN_SEL BIT(15) 413adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_SAMPLING_STOP BIT(14) 423adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_CHAN_DELTA_EN_MASK GENMASK(13, 12) 433adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_DETECT_IRQ_POL BIT(10) 443adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_DETECT_IRQ_EN BIT(9) 453adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK GENMASK(8, 4) 463adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_FIFO_IRQ_EN BIT(3) 473adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_SAMPLING_START BIT(2) 483adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_CONTINUOUS_EN BIT(1) 493adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE BIT(0) 503adbf342SMartin Blumenstingl 513adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_LIST 0x04 523adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_LIST_MAX_INDEX_MASK GENMASK(26, 24) 533adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_LIST_ENTRY_MASK(_chan) \ 543adbf342SMartin Blumenstingl (GENMASK(2, 0) << ((_chan) * 3)) 553adbf342SMartin Blumenstingl 563adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AVG_CNTL 0x08 573adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AVG_CNTL_AVG_MODE_SHIFT(_chan) \ 583adbf342SMartin Blumenstingl (16 + ((_chan) * 2)) 593adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AVG_CNTL_AVG_MODE_MASK(_chan) \ 603adbf342SMartin Blumenstingl (GENMASK(17, 16) << ((_chan) * 2)) 613adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AVG_CNTL_NUM_SAMPLES_SHIFT(_chan) \ 623adbf342SMartin Blumenstingl (0 + ((_chan) * 2)) 633adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AVG_CNTL_NUM_SAMPLES_MASK(_chan) \ 643adbf342SMartin Blumenstingl (GENMASK(1, 0) << ((_chan) * 2)) 653adbf342SMartin Blumenstingl 663adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3 0x0c 673adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_CNTL_USE_SC_DLY BIT(31) 683adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_CLK_EN BIT(30) 693adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_BL30_INITIALIZED BIT(28) 703adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_CTRL_CONT_RING_COUNTER_EN BIT(27) 713adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_CTRL_SAMPLING_CLOCK_PHASE BIT(26) 723adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_CTRL_CHAN7_MUX_SEL_MASK GENMASK(25, 23) 733adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_DETECT_EN BIT(22) 743adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_ADC_EN BIT(21) 753adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_PANEL_DETECT_COUNT_MASK GENMASK(20, 18) 763adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_PANEL_DETECT_FILTER_TB_MASK GENMASK(17, 16) 773adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_ADC_CLK_DIV_SHIFT 10 783adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_ADC_CLK_DIV_WIDTH 5 793adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_BLOCK_DLY_SEL_MASK GENMASK(9, 8) 803adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_BLOCK_DLY_MASK GENMASK(7, 0) 813adbf342SMartin Blumenstingl 823adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELAY 0x10 833adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELAY_INPUT_DLY_SEL_MASK GENMASK(25, 24) 843adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELAY_BL30_BUSY BIT(15) 853adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELAY_KERNEL_BUSY BIT(14) 863adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELAY_INPUT_DLY_CNT_MASK GENMASK(23, 16) 873adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELAY_SAMPLE_DLY_SEL_MASK GENMASK(9, 8) 883adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELAY_SAMPLE_DLY_CNT_MASK GENMASK(7, 0) 893adbf342SMartin Blumenstingl 903adbf342SMartin Blumenstingl #define MESON_SAR_ADC_LAST_RD 0x14 913adbf342SMartin Blumenstingl #define MESON_SAR_ADC_LAST_RD_LAST_CHANNEL1_MASK GENMASK(23, 16) 923adbf342SMartin Blumenstingl #define MESON_SAR_ADC_LAST_RD_LAST_CHANNEL0_MASK GENMASK(9, 0) 933adbf342SMartin Blumenstingl 943adbf342SMartin Blumenstingl #define MESON_SAR_ADC_FIFO_RD 0x18 953adbf342SMartin Blumenstingl #define MESON_SAR_ADC_FIFO_RD_CHAN_ID_MASK GENMASK(14, 12) 963adbf342SMartin Blumenstingl #define MESON_SAR_ADC_FIFO_RD_SAMPLE_VALUE_MASK GENMASK(11, 0) 973adbf342SMartin Blumenstingl 983adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AUX_SW 0x1c 99ab569a4cSMartin Blumenstingl #define MESON_SAR_ADC_AUX_SW_MUX_SEL_CHAN_SHIFT(_chan) \ 100ab569a4cSMartin Blumenstingl (8 + (((_chan) - 2) * 3)) 1013adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AUX_SW_VREF_P_MUX BIT(6) 1023adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AUX_SW_VREF_N_MUX BIT(5) 1033adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AUX_SW_MODE_SEL BIT(4) 1043adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AUX_SW_YP_DRIVE_SW BIT(3) 1053adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AUX_SW_XP_DRIVE_SW BIT(2) 1063adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AUX_SW_YM_DRIVE_SW BIT(1) 1073adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AUX_SW_XM_DRIVE_SW BIT(0) 1083adbf342SMartin Blumenstingl 1093adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW 0x20 1103adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_MUX_SEL_MASK GENMASK(25, 23) 1113adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_VREF_P_MUX BIT(22) 1123adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_VREF_N_MUX BIT(21) 1133adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_MODE_SEL BIT(20) 1143adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_YP_DRIVE_SW BIT(19) 1153adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_XP_DRIVE_SW BIT(18) 1163adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_YM_DRIVE_SW BIT(17) 1173adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_XM_DRIVE_SW BIT(16) 1183adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_MUX_SEL_MASK GENMASK(9, 7) 1193adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_VREF_P_MUX BIT(6) 1203adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_VREF_N_MUX BIT(5) 1213adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_MODE_SEL BIT(4) 1223adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_YP_DRIVE_SW BIT(3) 1233adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_XP_DRIVE_SW BIT(2) 1243adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_YM_DRIVE_SW BIT(1) 1253adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_XM_DRIVE_SW BIT(0) 1263adbf342SMartin Blumenstingl 1273adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW 0x24 1283adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_SW_EN BIT(26) 1293adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_MUX_MASK GENMASK(25, 23) 1303adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_VREF_P_MUX BIT(22) 1313adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_VREF_N_MUX BIT(21) 1323adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_MODE_SEL BIT(20) 1333adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_YP_DRIVE_SW BIT(19) 1343adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_XP_DRIVE_SW BIT(18) 1353adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_YM_DRIVE_SW BIT(17) 1363adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_XM_DRIVE_SW BIT(16) 1373adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_MUX_SEL_MASK GENMASK(9, 7) 1383adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_VREF_P_MUX BIT(6) 1393adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_VREF_N_MUX BIT(5) 1403adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_MODE_SEL BIT(4) 1413adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_YP_DRIVE_SW BIT(3) 1423adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_XP_DRIVE_SW BIT(2) 1433adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_YM_DRIVE_SW BIT(1) 1443adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_XM_DRIVE_SW BIT(0) 1453adbf342SMartin Blumenstingl 1463adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELTA_10 0x28 1473adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELTA_10_TEMP_SEL BIT(27) 1483adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELTA_10_TS_REVE1 BIT(26) 1493adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELTA_10_CHAN1_DELTA_VALUE_MASK GENMASK(25, 16) 1503adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELTA_10_TS_REVE0 BIT(15) 1513adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELTA_10_TS_C_SHIFT 11 1523adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELTA_10_TS_C_MASK GENMASK(14, 11) 1533adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELTA_10_TS_VBG_EN BIT(10) 1543adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELTA_10_CHAN0_DELTA_VALUE_MASK GENMASK(9, 0) 1553adbf342SMartin Blumenstingl 1563adbf342SMartin Blumenstingl /* 1573adbf342SMartin Blumenstingl * NOTE: registers from here are undocumented (the vendor Linux kernel driver 1583adbf342SMartin Blumenstingl * and u-boot source served as reference). These only seem to be relevant on 1593adbf342SMartin Blumenstingl * GXBB and newer. 1603adbf342SMartin Blumenstingl */ 1613adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG11 0x2c 1623adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG11_BANDGAP_EN BIT(13) 1633adbf342SMartin Blumenstingl 1643adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG13 0x34 1653adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG13_12BIT_CALIBRATION_MASK GENMASK(13, 8) 1663adbf342SMartin Blumenstingl 1673adbf342SMartin Blumenstingl #define MESON_SAR_ADC_MAX_FIFO_SIZE 32 1683af10913SHeiner Kallweit #define MESON_SAR_ADC_TIMEOUT 100 /* ms */ 16948ba7c3cSHeiner Kallweit /* for use with IIO_VAL_INT_PLUS_MICRO */ 17048ba7c3cSHeiner Kallweit #define MILLION 1000000 1713adbf342SMartin Blumenstingl 1723adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN(_chan) { \ 1733adbf342SMartin Blumenstingl .type = IIO_VOLTAGE, \ 1743adbf342SMartin Blumenstingl .indexed = 1, \ 1753adbf342SMartin Blumenstingl .channel = _chan, \ 1763adbf342SMartin Blumenstingl .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ 1773adbf342SMartin Blumenstingl BIT(IIO_CHAN_INFO_AVERAGE_RAW), \ 17848ba7c3cSHeiner Kallweit .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \ 17948ba7c3cSHeiner Kallweit BIT(IIO_CHAN_INFO_CALIBBIAS) | \ 18048ba7c3cSHeiner Kallweit BIT(IIO_CHAN_INFO_CALIBSCALE), \ 1813adbf342SMartin Blumenstingl .datasheet_name = "SAR_ADC_CH"#_chan, \ 1823adbf342SMartin Blumenstingl } 1833adbf342SMartin Blumenstingl 1843adbf342SMartin Blumenstingl /* 1853adbf342SMartin Blumenstingl * TODO: the hardware supports IIO_TEMP for channel 6 as well which is 1863adbf342SMartin Blumenstingl * currently not supported by this driver. 1873adbf342SMartin Blumenstingl */ 1883adbf342SMartin Blumenstingl static const struct iio_chan_spec meson_sar_adc_iio_channels[] = { 1893adbf342SMartin Blumenstingl MESON_SAR_ADC_CHAN(0), 1903adbf342SMartin Blumenstingl MESON_SAR_ADC_CHAN(1), 1913adbf342SMartin Blumenstingl MESON_SAR_ADC_CHAN(2), 1923adbf342SMartin Blumenstingl MESON_SAR_ADC_CHAN(3), 1933adbf342SMartin Blumenstingl MESON_SAR_ADC_CHAN(4), 1943adbf342SMartin Blumenstingl MESON_SAR_ADC_CHAN(5), 1953adbf342SMartin Blumenstingl MESON_SAR_ADC_CHAN(6), 1963adbf342SMartin Blumenstingl MESON_SAR_ADC_CHAN(7), 1973adbf342SMartin Blumenstingl IIO_CHAN_SOFT_TIMESTAMP(8), 1983adbf342SMartin Blumenstingl }; 1993adbf342SMartin Blumenstingl 2003adbf342SMartin Blumenstingl enum meson_sar_adc_avg_mode { 2013adbf342SMartin Blumenstingl NO_AVERAGING = 0x0, 2023adbf342SMartin Blumenstingl MEAN_AVERAGING = 0x1, 2033adbf342SMartin Blumenstingl MEDIAN_AVERAGING = 0x2, 2043adbf342SMartin Blumenstingl }; 2053adbf342SMartin Blumenstingl 2063adbf342SMartin Blumenstingl enum meson_sar_adc_num_samples { 2073adbf342SMartin Blumenstingl ONE_SAMPLE = 0x0, 2083adbf342SMartin Blumenstingl TWO_SAMPLES = 0x1, 2093adbf342SMartin Blumenstingl FOUR_SAMPLES = 0x2, 2103adbf342SMartin Blumenstingl EIGHT_SAMPLES = 0x3, 2113adbf342SMartin Blumenstingl }; 2123adbf342SMartin Blumenstingl 2133adbf342SMartin Blumenstingl enum meson_sar_adc_chan7_mux_sel { 2143adbf342SMartin Blumenstingl CHAN7_MUX_VSS = 0x0, 2153adbf342SMartin Blumenstingl CHAN7_MUX_VDD_DIV4 = 0x1, 2163adbf342SMartin Blumenstingl CHAN7_MUX_VDD_DIV2 = 0x2, 2173adbf342SMartin Blumenstingl CHAN7_MUX_VDD_MUL3_DIV4 = 0x3, 2183adbf342SMartin Blumenstingl CHAN7_MUX_VDD = 0x4, 2193adbf342SMartin Blumenstingl CHAN7_MUX_CH7_INPUT = 0x7, 2203adbf342SMartin Blumenstingl }; 2213adbf342SMartin Blumenstingl 2223adbf342SMartin Blumenstingl struct meson_sar_adc_data { 2236c76ed31SMartin Blumenstingl bool has_bl30_integration; 224fda29dbaSMartin Blumenstingl unsigned long clock_rate; 225d85eed9fSMartin Blumenstingl u32 bandgap_reg; 2263adbf342SMartin Blumenstingl unsigned int resolution; 2273adbf342SMartin Blumenstingl const char *name; 22896748823SMartin Blumenstingl const struct regmap_config *regmap_config; 2293adbf342SMartin Blumenstingl }; 2303adbf342SMartin Blumenstingl 2313adbf342SMartin Blumenstingl struct meson_sar_adc_priv { 2323adbf342SMartin Blumenstingl struct regmap *regmap; 2333adbf342SMartin Blumenstingl struct regulator *vref; 2343adbf342SMartin Blumenstingl const struct meson_sar_adc_data *data; 2353adbf342SMartin Blumenstingl struct clk *clkin; 2363adbf342SMartin Blumenstingl struct clk *core_clk; 2373adbf342SMartin Blumenstingl struct clk *adc_sel_clk; 2383adbf342SMartin Blumenstingl struct clk *adc_clk; 2393adbf342SMartin Blumenstingl struct clk_gate clk_gate; 2403adbf342SMartin Blumenstingl struct clk *adc_div_clk; 2413adbf342SMartin Blumenstingl struct clk_divider clk_div; 2423af10913SHeiner Kallweit struct completion done; 24348ba7c3cSHeiner Kallweit int calibbias; 24448ba7c3cSHeiner Kallweit int calibscale; 2453adbf342SMartin Blumenstingl }; 2463adbf342SMartin Blumenstingl 24796748823SMartin Blumenstingl static const struct regmap_config meson_sar_adc_regmap_config_gxbb = { 2483adbf342SMartin Blumenstingl .reg_bits = 8, 2493adbf342SMartin Blumenstingl .val_bits = 32, 2503adbf342SMartin Blumenstingl .reg_stride = 4, 2513adbf342SMartin Blumenstingl .max_register = MESON_SAR_ADC_REG13, 2523adbf342SMartin Blumenstingl }; 2533adbf342SMartin Blumenstingl 25496748823SMartin Blumenstingl static const struct regmap_config meson_sar_adc_regmap_config_meson8 = { 25596748823SMartin Blumenstingl .reg_bits = 8, 25696748823SMartin Blumenstingl .val_bits = 32, 25796748823SMartin Blumenstingl .reg_stride = 4, 25896748823SMartin Blumenstingl .max_register = MESON_SAR_ADC_DELTA_10, 25996748823SMartin Blumenstingl }; 26096748823SMartin Blumenstingl 2613adbf342SMartin Blumenstingl static unsigned int meson_sar_adc_get_fifo_count(struct iio_dev *indio_dev) 2623adbf342SMartin Blumenstingl { 2633adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 2643adbf342SMartin Blumenstingl u32 regval; 2653adbf342SMartin Blumenstingl 2663adbf342SMartin Blumenstingl regmap_read(priv->regmap, MESON_SAR_ADC_REG0, ®val); 2673adbf342SMartin Blumenstingl 2683adbf342SMartin Blumenstingl return FIELD_GET(MESON_SAR_ADC_REG0_FIFO_COUNT_MASK, regval); 2693adbf342SMartin Blumenstingl } 2703adbf342SMartin Blumenstingl 27148ba7c3cSHeiner Kallweit static int meson_sar_adc_calib_val(struct iio_dev *indio_dev, int val) 27248ba7c3cSHeiner Kallweit { 27348ba7c3cSHeiner Kallweit struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 27448ba7c3cSHeiner Kallweit int tmp; 27548ba7c3cSHeiner Kallweit 27648ba7c3cSHeiner Kallweit /* use val_calib = scale * val_raw + offset calibration function */ 27748ba7c3cSHeiner Kallweit tmp = div_s64((s64)val * priv->calibscale, MILLION) + priv->calibbias; 27848ba7c3cSHeiner Kallweit 27948ba7c3cSHeiner Kallweit return clamp(tmp, 0, (1 << priv->data->resolution) - 1); 28048ba7c3cSHeiner Kallweit } 28148ba7c3cSHeiner Kallweit 2823adbf342SMartin Blumenstingl static int meson_sar_adc_wait_busy_clear(struct iio_dev *indio_dev) 2833adbf342SMartin Blumenstingl { 2843adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 2853adbf342SMartin Blumenstingl int regval, timeout = 10000; 2863adbf342SMartin Blumenstingl 2873adbf342SMartin Blumenstingl /* 2883adbf342SMartin Blumenstingl * NOTE: we need a small delay before reading the status, otherwise 2893adbf342SMartin Blumenstingl * the sample engine may not have started internally (which would 2903adbf342SMartin Blumenstingl * seem to us that sampling is already finished). 2913adbf342SMartin Blumenstingl */ 2923adbf342SMartin Blumenstingl do { 2933adbf342SMartin Blumenstingl udelay(1); 2943adbf342SMartin Blumenstingl regmap_read(priv->regmap, MESON_SAR_ADC_REG0, ®val); 2953adbf342SMartin Blumenstingl } while (FIELD_GET(MESON_SAR_ADC_REG0_BUSY_MASK, regval) && timeout--); 2963adbf342SMartin Blumenstingl 2973adbf342SMartin Blumenstingl if (timeout < 0) 2983adbf342SMartin Blumenstingl return -ETIMEDOUT; 2993adbf342SMartin Blumenstingl 3003adbf342SMartin Blumenstingl return 0; 3013adbf342SMartin Blumenstingl } 3023adbf342SMartin Blumenstingl 3033adbf342SMartin Blumenstingl static int meson_sar_adc_read_raw_sample(struct iio_dev *indio_dev, 3043adbf342SMartin Blumenstingl const struct iio_chan_spec *chan, 3053adbf342SMartin Blumenstingl int *val) 3063adbf342SMartin Blumenstingl { 3073adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 3086a882a2cSHeiner Kallweit int regval, fifo_chan, fifo_val, count; 3093adbf342SMartin Blumenstingl 3103af10913SHeiner Kallweit if(!wait_for_completion_timeout(&priv->done, 3113af10913SHeiner Kallweit msecs_to_jiffies(MESON_SAR_ADC_TIMEOUT))) 3123af10913SHeiner Kallweit return -ETIMEDOUT; 3133adbf342SMartin Blumenstingl 3146a882a2cSHeiner Kallweit count = meson_sar_adc_get_fifo_count(indio_dev); 3156a882a2cSHeiner Kallweit if (count != 1) { 3166a882a2cSHeiner Kallweit dev_err(&indio_dev->dev, 3176a882a2cSHeiner Kallweit "ADC FIFO has %d element(s) instead of one\n", count); 3186a882a2cSHeiner Kallweit return -EINVAL; 3193adbf342SMartin Blumenstingl } 3203adbf342SMartin Blumenstingl 3216a882a2cSHeiner Kallweit regmap_read(priv->regmap, MESON_SAR_ADC_FIFO_RD, ®val); 3226a882a2cSHeiner Kallweit fifo_chan = FIELD_GET(MESON_SAR_ADC_FIFO_RD_CHAN_ID_MASK, regval); 3236a882a2cSHeiner Kallweit if (fifo_chan != chan->channel) { 3246a882a2cSHeiner Kallweit dev_err(&indio_dev->dev, 3256a882a2cSHeiner Kallweit "ADC FIFO entry belongs to channel %d instead of %d\n", 3266a882a2cSHeiner Kallweit fifo_chan, chan->channel); 3276a882a2cSHeiner Kallweit return -EINVAL; 3286a882a2cSHeiner Kallweit } 3293adbf342SMartin Blumenstingl 3306a882a2cSHeiner Kallweit fifo_val = FIELD_GET(MESON_SAR_ADC_FIFO_RD_SAMPLE_VALUE_MASK, regval); 3316a882a2cSHeiner Kallweit fifo_val &= GENMASK(priv->data->resolution - 1, 0); 33248ba7c3cSHeiner Kallweit *val = meson_sar_adc_calib_val(indio_dev, fifo_val); 3333adbf342SMartin Blumenstingl 3343adbf342SMartin Blumenstingl return 0; 3353adbf342SMartin Blumenstingl } 3363adbf342SMartin Blumenstingl 3373adbf342SMartin Blumenstingl static void meson_sar_adc_set_averaging(struct iio_dev *indio_dev, 3383adbf342SMartin Blumenstingl const struct iio_chan_spec *chan, 3393adbf342SMartin Blumenstingl enum meson_sar_adc_avg_mode mode, 3403adbf342SMartin Blumenstingl enum meson_sar_adc_num_samples samples) 3413adbf342SMartin Blumenstingl { 3423adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 3433adbf342SMartin Blumenstingl int val, channel = chan->channel; 3443adbf342SMartin Blumenstingl 3453adbf342SMartin Blumenstingl val = samples << MESON_SAR_ADC_AVG_CNTL_NUM_SAMPLES_SHIFT(channel); 3463adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_AVG_CNTL, 3473adbf342SMartin Blumenstingl MESON_SAR_ADC_AVG_CNTL_NUM_SAMPLES_MASK(channel), 3483adbf342SMartin Blumenstingl val); 3493adbf342SMartin Blumenstingl 3503adbf342SMartin Blumenstingl val = mode << MESON_SAR_ADC_AVG_CNTL_AVG_MODE_SHIFT(channel); 3513adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_AVG_CNTL, 3523adbf342SMartin Blumenstingl MESON_SAR_ADC_AVG_CNTL_AVG_MODE_MASK(channel), val); 3533adbf342SMartin Blumenstingl } 3543adbf342SMartin Blumenstingl 3553adbf342SMartin Blumenstingl static void meson_sar_adc_enable_channel(struct iio_dev *indio_dev, 3563adbf342SMartin Blumenstingl const struct iio_chan_spec *chan) 3573adbf342SMartin Blumenstingl { 3583adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 3593adbf342SMartin Blumenstingl u32 regval; 3603adbf342SMartin Blumenstingl 3613adbf342SMartin Blumenstingl /* 3623adbf342SMartin Blumenstingl * the SAR ADC engine allows sampling multiple channels at the same 3633adbf342SMartin Blumenstingl * time. to keep it simple we're only working with one *internal* 3643adbf342SMartin Blumenstingl * channel, which starts counting at index 0 (which means: count = 1). 3653adbf342SMartin Blumenstingl */ 3663adbf342SMartin Blumenstingl regval = FIELD_PREP(MESON_SAR_ADC_CHAN_LIST_MAX_INDEX_MASK, 0); 3673adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_LIST, 3683adbf342SMartin Blumenstingl MESON_SAR_ADC_CHAN_LIST_MAX_INDEX_MASK, regval); 3693adbf342SMartin Blumenstingl 3703adbf342SMartin Blumenstingl /* map channel index 0 to the channel which we want to read */ 3713adbf342SMartin Blumenstingl regval = FIELD_PREP(MESON_SAR_ADC_CHAN_LIST_ENTRY_MASK(0), 3723adbf342SMartin Blumenstingl chan->channel); 3733adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_LIST, 3743adbf342SMartin Blumenstingl MESON_SAR_ADC_CHAN_LIST_ENTRY_MASK(0), regval); 3753adbf342SMartin Blumenstingl 3763adbf342SMartin Blumenstingl regval = FIELD_PREP(MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_MUX_MASK, 3773adbf342SMartin Blumenstingl chan->channel); 3783adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DETECT_IDLE_SW, 3793adbf342SMartin Blumenstingl MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_MUX_MASK, 3803adbf342SMartin Blumenstingl regval); 3813adbf342SMartin Blumenstingl 3823adbf342SMartin Blumenstingl regval = FIELD_PREP(MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_MUX_SEL_MASK, 3833adbf342SMartin Blumenstingl chan->channel); 3843adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DETECT_IDLE_SW, 3853adbf342SMartin Blumenstingl MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_MUX_SEL_MASK, 3863adbf342SMartin Blumenstingl regval); 3873adbf342SMartin Blumenstingl 3883adbf342SMartin Blumenstingl if (chan->channel == 6) 3893adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELTA_10, 3903adbf342SMartin Blumenstingl MESON_SAR_ADC_DELTA_10_TEMP_SEL, 0); 3913adbf342SMartin Blumenstingl } 3923adbf342SMartin Blumenstingl 3933adbf342SMartin Blumenstingl static void meson_sar_adc_set_chan7_mux(struct iio_dev *indio_dev, 3943adbf342SMartin Blumenstingl enum meson_sar_adc_chan7_mux_sel sel) 3953adbf342SMartin Blumenstingl { 3963adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 3973adbf342SMartin Blumenstingl u32 regval; 3983adbf342SMartin Blumenstingl 3993adbf342SMartin Blumenstingl regval = FIELD_PREP(MESON_SAR_ADC_REG3_CTRL_CHAN7_MUX_SEL_MASK, sel); 4003adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3, 4013adbf342SMartin Blumenstingl MESON_SAR_ADC_REG3_CTRL_CHAN7_MUX_SEL_MASK, regval); 4023adbf342SMartin Blumenstingl 4033adbf342SMartin Blumenstingl usleep_range(10, 20); 4043adbf342SMartin Blumenstingl } 4053adbf342SMartin Blumenstingl 4063adbf342SMartin Blumenstingl static void meson_sar_adc_start_sample_engine(struct iio_dev *indio_dev) 4073adbf342SMartin Blumenstingl { 4083adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 4093adbf342SMartin Blumenstingl 4103af10913SHeiner Kallweit reinit_completion(&priv->done); 4113af10913SHeiner Kallweit 4123af10913SHeiner Kallweit regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, 4133af10913SHeiner Kallweit MESON_SAR_ADC_REG0_FIFO_IRQ_EN, 4143af10913SHeiner Kallweit MESON_SAR_ADC_REG0_FIFO_IRQ_EN); 4153af10913SHeiner Kallweit 4163adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, 4173adbf342SMartin Blumenstingl MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE, 4183adbf342SMartin Blumenstingl MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE); 4193adbf342SMartin Blumenstingl 4203adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, 4213adbf342SMartin Blumenstingl MESON_SAR_ADC_REG0_SAMPLING_START, 4223adbf342SMartin Blumenstingl MESON_SAR_ADC_REG0_SAMPLING_START); 4233adbf342SMartin Blumenstingl } 4243adbf342SMartin Blumenstingl 4253adbf342SMartin Blumenstingl static void meson_sar_adc_stop_sample_engine(struct iio_dev *indio_dev) 4263adbf342SMartin Blumenstingl { 4273adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 4283adbf342SMartin Blumenstingl 4293adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, 4303af10913SHeiner Kallweit MESON_SAR_ADC_REG0_FIFO_IRQ_EN, 0); 4313af10913SHeiner Kallweit 4323af10913SHeiner Kallweit regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, 4333adbf342SMartin Blumenstingl MESON_SAR_ADC_REG0_SAMPLING_STOP, 4343adbf342SMartin Blumenstingl MESON_SAR_ADC_REG0_SAMPLING_STOP); 4353adbf342SMartin Blumenstingl 4363adbf342SMartin Blumenstingl /* wait until all modules are stopped */ 4373adbf342SMartin Blumenstingl meson_sar_adc_wait_busy_clear(indio_dev); 4383adbf342SMartin Blumenstingl 4393adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, 4403adbf342SMartin Blumenstingl MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE, 0); 4413adbf342SMartin Blumenstingl } 4423adbf342SMartin Blumenstingl 4433adbf342SMartin Blumenstingl static int meson_sar_adc_lock(struct iio_dev *indio_dev) 4443adbf342SMartin Blumenstingl { 4453adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 4463adbf342SMartin Blumenstingl int val, timeout = 10000; 4473adbf342SMartin Blumenstingl 4483adbf342SMartin Blumenstingl mutex_lock(&indio_dev->mlock); 4493adbf342SMartin Blumenstingl 4506c76ed31SMartin Blumenstingl if (priv->data->has_bl30_integration) { 4513adbf342SMartin Blumenstingl /* prevent BL30 from using the SAR ADC while we are using it */ 4523adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY, 4533adbf342SMartin Blumenstingl MESON_SAR_ADC_DELAY_KERNEL_BUSY, 4543adbf342SMartin Blumenstingl MESON_SAR_ADC_DELAY_KERNEL_BUSY); 4553adbf342SMartin Blumenstingl 4566c76ed31SMartin Blumenstingl /* 4576c76ed31SMartin Blumenstingl * wait until BL30 releases it's lock (so we can use the SAR 4586c76ed31SMartin Blumenstingl * ADC) 4596c76ed31SMartin Blumenstingl */ 4603adbf342SMartin Blumenstingl do { 4613adbf342SMartin Blumenstingl udelay(1); 4623adbf342SMartin Blumenstingl regmap_read(priv->regmap, MESON_SAR_ADC_DELAY, &val); 4633adbf342SMartin Blumenstingl } while (val & MESON_SAR_ADC_DELAY_BL30_BUSY && timeout--); 4643adbf342SMartin Blumenstingl 4653adbf342SMartin Blumenstingl if (timeout < 0) 4663adbf342SMartin Blumenstingl return -ETIMEDOUT; 4676c76ed31SMartin Blumenstingl } 4683adbf342SMartin Blumenstingl 4693adbf342SMartin Blumenstingl return 0; 4703adbf342SMartin Blumenstingl } 4713adbf342SMartin Blumenstingl 4723adbf342SMartin Blumenstingl static void meson_sar_adc_unlock(struct iio_dev *indio_dev) 4733adbf342SMartin Blumenstingl { 4743adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 4753adbf342SMartin Blumenstingl 4766c76ed31SMartin Blumenstingl if (priv->data->has_bl30_integration) 4773adbf342SMartin Blumenstingl /* allow BL30 to use the SAR ADC again */ 4783adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY, 4793adbf342SMartin Blumenstingl MESON_SAR_ADC_DELAY_KERNEL_BUSY, 0); 4803adbf342SMartin Blumenstingl 4813adbf342SMartin Blumenstingl mutex_unlock(&indio_dev->mlock); 4823adbf342SMartin Blumenstingl } 4833adbf342SMartin Blumenstingl 4843adbf342SMartin Blumenstingl static void meson_sar_adc_clear_fifo(struct iio_dev *indio_dev) 4853adbf342SMartin Blumenstingl { 4863adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 487103a07d4SMartin Blumenstingl unsigned int count, tmp; 4883adbf342SMartin Blumenstingl 4893adbf342SMartin Blumenstingl for (count = 0; count < MESON_SAR_ADC_MAX_FIFO_SIZE; count++) { 4903adbf342SMartin Blumenstingl if (!meson_sar_adc_get_fifo_count(indio_dev)) 4913adbf342SMartin Blumenstingl break; 4923adbf342SMartin Blumenstingl 493103a07d4SMartin Blumenstingl regmap_read(priv->regmap, MESON_SAR_ADC_FIFO_RD, &tmp); 4943adbf342SMartin Blumenstingl } 4953adbf342SMartin Blumenstingl } 4963adbf342SMartin Blumenstingl 4973adbf342SMartin Blumenstingl static int meson_sar_adc_get_sample(struct iio_dev *indio_dev, 4983adbf342SMartin Blumenstingl const struct iio_chan_spec *chan, 4993adbf342SMartin Blumenstingl enum meson_sar_adc_avg_mode avg_mode, 5003adbf342SMartin Blumenstingl enum meson_sar_adc_num_samples avg_samples, 5013adbf342SMartin Blumenstingl int *val) 5023adbf342SMartin Blumenstingl { 5033adbf342SMartin Blumenstingl int ret; 5043adbf342SMartin Blumenstingl 5053adbf342SMartin Blumenstingl ret = meson_sar_adc_lock(indio_dev); 5063adbf342SMartin Blumenstingl if (ret) 5073adbf342SMartin Blumenstingl return ret; 5083adbf342SMartin Blumenstingl 5093adbf342SMartin Blumenstingl /* clear the FIFO to make sure we're not reading old values */ 5103adbf342SMartin Blumenstingl meson_sar_adc_clear_fifo(indio_dev); 5113adbf342SMartin Blumenstingl 5123adbf342SMartin Blumenstingl meson_sar_adc_set_averaging(indio_dev, chan, avg_mode, avg_samples); 5133adbf342SMartin Blumenstingl 5143adbf342SMartin Blumenstingl meson_sar_adc_enable_channel(indio_dev, chan); 5153adbf342SMartin Blumenstingl 5163adbf342SMartin Blumenstingl meson_sar_adc_start_sample_engine(indio_dev); 5173adbf342SMartin Blumenstingl ret = meson_sar_adc_read_raw_sample(indio_dev, chan, val); 5183adbf342SMartin Blumenstingl meson_sar_adc_stop_sample_engine(indio_dev); 5193adbf342SMartin Blumenstingl 5203adbf342SMartin Blumenstingl meson_sar_adc_unlock(indio_dev); 5213adbf342SMartin Blumenstingl 5223adbf342SMartin Blumenstingl if (ret) { 5233adbf342SMartin Blumenstingl dev_warn(indio_dev->dev.parent, 5243adbf342SMartin Blumenstingl "failed to read sample for channel %d: %d\n", 5253adbf342SMartin Blumenstingl chan->channel, ret); 5263adbf342SMartin Blumenstingl return ret; 5273adbf342SMartin Blumenstingl } 5283adbf342SMartin Blumenstingl 5293adbf342SMartin Blumenstingl return IIO_VAL_INT; 5303adbf342SMartin Blumenstingl } 5313adbf342SMartin Blumenstingl 5323adbf342SMartin Blumenstingl static int meson_sar_adc_iio_info_read_raw(struct iio_dev *indio_dev, 5333adbf342SMartin Blumenstingl const struct iio_chan_spec *chan, 5343adbf342SMartin Blumenstingl int *val, int *val2, long mask) 5353adbf342SMartin Blumenstingl { 5363adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 5373adbf342SMartin Blumenstingl int ret; 5383adbf342SMartin Blumenstingl 5393adbf342SMartin Blumenstingl switch (mask) { 5403adbf342SMartin Blumenstingl case IIO_CHAN_INFO_RAW: 5413adbf342SMartin Blumenstingl return meson_sar_adc_get_sample(indio_dev, chan, NO_AVERAGING, 5423adbf342SMartin Blumenstingl ONE_SAMPLE, val); 5433adbf342SMartin Blumenstingl break; 5443adbf342SMartin Blumenstingl 5453adbf342SMartin Blumenstingl case IIO_CHAN_INFO_AVERAGE_RAW: 5463adbf342SMartin Blumenstingl return meson_sar_adc_get_sample(indio_dev, chan, 5473adbf342SMartin Blumenstingl MEAN_AVERAGING, EIGHT_SAMPLES, 5483adbf342SMartin Blumenstingl val); 5493adbf342SMartin Blumenstingl break; 5503adbf342SMartin Blumenstingl 5513adbf342SMartin Blumenstingl case IIO_CHAN_INFO_SCALE: 5523adbf342SMartin Blumenstingl ret = regulator_get_voltage(priv->vref); 5533adbf342SMartin Blumenstingl if (ret < 0) { 5543adbf342SMartin Blumenstingl dev_err(indio_dev->dev.parent, 5553adbf342SMartin Blumenstingl "failed to get vref voltage: %d\n", ret); 5563adbf342SMartin Blumenstingl return ret; 5573adbf342SMartin Blumenstingl } 5583adbf342SMartin Blumenstingl 5593adbf342SMartin Blumenstingl *val = ret / 1000; 5603adbf342SMartin Blumenstingl *val2 = priv->data->resolution; 5613adbf342SMartin Blumenstingl return IIO_VAL_FRACTIONAL_LOG2; 5623adbf342SMartin Blumenstingl 56348ba7c3cSHeiner Kallweit case IIO_CHAN_INFO_CALIBBIAS: 56448ba7c3cSHeiner Kallweit *val = priv->calibbias; 56548ba7c3cSHeiner Kallweit return IIO_VAL_INT; 56648ba7c3cSHeiner Kallweit 56748ba7c3cSHeiner Kallweit case IIO_CHAN_INFO_CALIBSCALE: 56848ba7c3cSHeiner Kallweit *val = priv->calibscale / MILLION; 56948ba7c3cSHeiner Kallweit *val2 = priv->calibscale % MILLION; 57048ba7c3cSHeiner Kallweit return IIO_VAL_INT_PLUS_MICRO; 57148ba7c3cSHeiner Kallweit 5723adbf342SMartin Blumenstingl default: 5733adbf342SMartin Blumenstingl return -EINVAL; 5743adbf342SMartin Blumenstingl } 5753adbf342SMartin Blumenstingl } 5763adbf342SMartin Blumenstingl 5773adbf342SMartin Blumenstingl static int meson_sar_adc_clk_init(struct iio_dev *indio_dev, 5783adbf342SMartin Blumenstingl void __iomem *base) 5793adbf342SMartin Blumenstingl { 5803adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 5813adbf342SMartin Blumenstingl struct clk_init_data init; 5823adbf342SMartin Blumenstingl const char *clk_parents[1]; 5833adbf342SMartin Blumenstingl 5843921db46SRob Herring init.name = devm_kasprintf(&indio_dev->dev, GFP_KERNEL, "%pOF#adc_div", 5853921db46SRob Herring indio_dev->dev.of_node); 5863adbf342SMartin Blumenstingl init.flags = 0; 5873adbf342SMartin Blumenstingl init.ops = &clk_divider_ops; 5883adbf342SMartin Blumenstingl clk_parents[0] = __clk_get_name(priv->clkin); 5893adbf342SMartin Blumenstingl init.parent_names = clk_parents; 5903adbf342SMartin Blumenstingl init.num_parents = 1; 5913adbf342SMartin Blumenstingl 5923adbf342SMartin Blumenstingl priv->clk_div.reg = base + MESON_SAR_ADC_REG3; 5933adbf342SMartin Blumenstingl priv->clk_div.shift = MESON_SAR_ADC_REG3_ADC_CLK_DIV_SHIFT; 5943adbf342SMartin Blumenstingl priv->clk_div.width = MESON_SAR_ADC_REG3_ADC_CLK_DIV_WIDTH; 5953adbf342SMartin Blumenstingl priv->clk_div.hw.init = &init; 5963adbf342SMartin Blumenstingl priv->clk_div.flags = 0; 5973adbf342SMartin Blumenstingl 5983adbf342SMartin Blumenstingl priv->adc_div_clk = devm_clk_register(&indio_dev->dev, 5993adbf342SMartin Blumenstingl &priv->clk_div.hw); 6003adbf342SMartin Blumenstingl if (WARN_ON(IS_ERR(priv->adc_div_clk))) 6013adbf342SMartin Blumenstingl return PTR_ERR(priv->adc_div_clk); 6023adbf342SMartin Blumenstingl 6033921db46SRob Herring init.name = devm_kasprintf(&indio_dev->dev, GFP_KERNEL, "%pOF#adc_en", 6043921db46SRob Herring indio_dev->dev.of_node); 6053adbf342SMartin Blumenstingl init.flags = CLK_SET_RATE_PARENT; 6063adbf342SMartin Blumenstingl init.ops = &clk_gate_ops; 6073adbf342SMartin Blumenstingl clk_parents[0] = __clk_get_name(priv->adc_div_clk); 6083adbf342SMartin Blumenstingl init.parent_names = clk_parents; 6093adbf342SMartin Blumenstingl init.num_parents = 1; 6103adbf342SMartin Blumenstingl 6113adbf342SMartin Blumenstingl priv->clk_gate.reg = base + MESON_SAR_ADC_REG3; 6127a6b0420SMartin Blumenstingl priv->clk_gate.bit_idx = __ffs(MESON_SAR_ADC_REG3_CLK_EN); 6133adbf342SMartin Blumenstingl priv->clk_gate.hw.init = &init; 6143adbf342SMartin Blumenstingl 6153adbf342SMartin Blumenstingl priv->adc_clk = devm_clk_register(&indio_dev->dev, &priv->clk_gate.hw); 6163adbf342SMartin Blumenstingl if (WARN_ON(IS_ERR(priv->adc_clk))) 6173adbf342SMartin Blumenstingl return PTR_ERR(priv->adc_clk); 6183adbf342SMartin Blumenstingl 6193adbf342SMartin Blumenstingl return 0; 6203adbf342SMartin Blumenstingl } 6213adbf342SMartin Blumenstingl 6223adbf342SMartin Blumenstingl static int meson_sar_adc_init(struct iio_dev *indio_dev) 6233adbf342SMartin Blumenstingl { 6243adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 625ab569a4cSMartin Blumenstingl int regval, i, ret; 6263adbf342SMartin Blumenstingl 6273adbf342SMartin Blumenstingl /* 6283adbf342SMartin Blumenstingl * make sure we start at CH7 input since the other muxes are only used 6293adbf342SMartin Blumenstingl * for internal calibration. 6303adbf342SMartin Blumenstingl */ 6313adbf342SMartin Blumenstingl meson_sar_adc_set_chan7_mux(indio_dev, CHAN7_MUX_CH7_INPUT); 6323adbf342SMartin Blumenstingl 6336c76ed31SMartin Blumenstingl if (priv->data->has_bl30_integration) { 6343adbf342SMartin Blumenstingl /* 6356c76ed31SMartin Blumenstingl * leave sampling delay and the input clocks as configured by 6366c76ed31SMartin Blumenstingl * BL30 to make sure BL30 gets the values it expects when 6376c76ed31SMartin Blumenstingl * reading the temperature sensor. 6383adbf342SMartin Blumenstingl */ 6393adbf342SMartin Blumenstingl regmap_read(priv->regmap, MESON_SAR_ADC_REG3, ®val); 6403adbf342SMartin Blumenstingl if (regval & MESON_SAR_ADC_REG3_BL30_INITIALIZED) 6413adbf342SMartin Blumenstingl return 0; 6426c76ed31SMartin Blumenstingl } 6433adbf342SMartin Blumenstingl 6443adbf342SMartin Blumenstingl meson_sar_adc_stop_sample_engine(indio_dev); 6453adbf342SMartin Blumenstingl 6463adbf342SMartin Blumenstingl /* update the channel 6 MUX to select the temperature sensor */ 6473adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, 6483adbf342SMartin Blumenstingl MESON_SAR_ADC_REG0_ADC_TEMP_SEN_SEL, 6493adbf342SMartin Blumenstingl MESON_SAR_ADC_REG0_ADC_TEMP_SEN_SEL); 6503adbf342SMartin Blumenstingl 6513adbf342SMartin Blumenstingl /* disable all channels by default */ 6523adbf342SMartin Blumenstingl regmap_write(priv->regmap, MESON_SAR_ADC_CHAN_LIST, 0x0); 6533adbf342SMartin Blumenstingl 6543adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3, 6553adbf342SMartin Blumenstingl MESON_SAR_ADC_REG3_CTRL_SAMPLING_CLOCK_PHASE, 0); 6563adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3, 6573adbf342SMartin Blumenstingl MESON_SAR_ADC_REG3_CNTL_USE_SC_DLY, 6583adbf342SMartin Blumenstingl MESON_SAR_ADC_REG3_CNTL_USE_SC_DLY); 6593adbf342SMartin Blumenstingl 6603adbf342SMartin Blumenstingl /* delay between two samples = (10+1) * 1uS */ 6613adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY, 6623adbf342SMartin Blumenstingl MESON_SAR_ADC_DELAY_INPUT_DLY_CNT_MASK, 6633adbf342SMartin Blumenstingl FIELD_PREP(MESON_SAR_ADC_DELAY_SAMPLE_DLY_CNT_MASK, 6643adbf342SMartin Blumenstingl 10)); 6653adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY, 6663adbf342SMartin Blumenstingl MESON_SAR_ADC_DELAY_SAMPLE_DLY_SEL_MASK, 6673adbf342SMartin Blumenstingl FIELD_PREP(MESON_SAR_ADC_DELAY_SAMPLE_DLY_SEL_MASK, 6683adbf342SMartin Blumenstingl 0)); 6693adbf342SMartin Blumenstingl 6703adbf342SMartin Blumenstingl /* delay between two samples = (10+1) * 1uS */ 6713adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY, 6723adbf342SMartin Blumenstingl MESON_SAR_ADC_DELAY_INPUT_DLY_CNT_MASK, 6733adbf342SMartin Blumenstingl FIELD_PREP(MESON_SAR_ADC_DELAY_INPUT_DLY_CNT_MASK, 6743adbf342SMartin Blumenstingl 10)); 6753adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY, 6763adbf342SMartin Blumenstingl MESON_SAR_ADC_DELAY_INPUT_DLY_SEL_MASK, 6773adbf342SMartin Blumenstingl FIELD_PREP(MESON_SAR_ADC_DELAY_INPUT_DLY_SEL_MASK, 6783adbf342SMartin Blumenstingl 1)); 6793adbf342SMartin Blumenstingl 680ab569a4cSMartin Blumenstingl /* 681ab569a4cSMartin Blumenstingl * set up the input channel muxes in MESON_SAR_ADC_CHAN_10_SW 682ab569a4cSMartin Blumenstingl * (0 = SAR_ADC_CH0, 1 = SAR_ADC_CH1) 683ab569a4cSMartin Blumenstingl */ 684ab569a4cSMartin Blumenstingl regval = FIELD_PREP(MESON_SAR_ADC_CHAN_10_SW_CHAN0_MUX_SEL_MASK, 0); 685ab569a4cSMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_10_SW, 686ab569a4cSMartin Blumenstingl MESON_SAR_ADC_CHAN_10_SW_CHAN0_MUX_SEL_MASK, 687ab569a4cSMartin Blumenstingl regval); 688ab569a4cSMartin Blumenstingl regval = FIELD_PREP(MESON_SAR_ADC_CHAN_10_SW_CHAN1_MUX_SEL_MASK, 1); 689ab569a4cSMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_10_SW, 690ab569a4cSMartin Blumenstingl MESON_SAR_ADC_CHAN_10_SW_CHAN1_MUX_SEL_MASK, 691ab569a4cSMartin Blumenstingl regval); 692ab569a4cSMartin Blumenstingl 693ab569a4cSMartin Blumenstingl /* 694ab569a4cSMartin Blumenstingl * set up the input channel muxes in MESON_SAR_ADC_AUX_SW 695ab569a4cSMartin Blumenstingl * (2 = SAR_ADC_CH2, 3 = SAR_ADC_CH3, ...) and enable 696ab569a4cSMartin Blumenstingl * MESON_SAR_ADC_AUX_SW_YP_DRIVE_SW and 697ab569a4cSMartin Blumenstingl * MESON_SAR_ADC_AUX_SW_XP_DRIVE_SW like the vendor driver. 698ab569a4cSMartin Blumenstingl */ 699ab569a4cSMartin Blumenstingl regval = 0; 700ab569a4cSMartin Blumenstingl for (i = 2; i <= 7; i++) 701ab569a4cSMartin Blumenstingl regval |= i << MESON_SAR_ADC_AUX_SW_MUX_SEL_CHAN_SHIFT(i); 702ab569a4cSMartin Blumenstingl regval |= MESON_SAR_ADC_AUX_SW_YP_DRIVE_SW; 703ab569a4cSMartin Blumenstingl regval |= MESON_SAR_ADC_AUX_SW_XP_DRIVE_SW; 704ab569a4cSMartin Blumenstingl regmap_write(priv->regmap, MESON_SAR_ADC_AUX_SW, regval); 705ab569a4cSMartin Blumenstingl 7063adbf342SMartin Blumenstingl ret = clk_set_parent(priv->adc_sel_clk, priv->clkin); 7073adbf342SMartin Blumenstingl if (ret) { 7083adbf342SMartin Blumenstingl dev_err(indio_dev->dev.parent, 7093adbf342SMartin Blumenstingl "failed to set adc parent to clkin\n"); 7103adbf342SMartin Blumenstingl return ret; 7113adbf342SMartin Blumenstingl } 7123adbf342SMartin Blumenstingl 713fda29dbaSMartin Blumenstingl ret = clk_set_rate(priv->adc_clk, priv->data->clock_rate); 7143adbf342SMartin Blumenstingl if (ret) { 7153adbf342SMartin Blumenstingl dev_err(indio_dev->dev.parent, 7163adbf342SMartin Blumenstingl "failed to set adc clock rate\n"); 7173adbf342SMartin Blumenstingl return ret; 7183adbf342SMartin Blumenstingl } 7193adbf342SMartin Blumenstingl 7203adbf342SMartin Blumenstingl return 0; 7213adbf342SMartin Blumenstingl } 7223adbf342SMartin Blumenstingl 723d85eed9fSMartin Blumenstingl static void meson_sar_adc_set_bandgap(struct iio_dev *indio_dev, bool on_off) 724d85eed9fSMartin Blumenstingl { 725d85eed9fSMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 726d85eed9fSMartin Blumenstingl u32 enable_mask; 727d85eed9fSMartin Blumenstingl 728d85eed9fSMartin Blumenstingl if (priv->data->bandgap_reg == MESON_SAR_ADC_REG11) 729d85eed9fSMartin Blumenstingl enable_mask = MESON_SAR_ADC_REG11_BANDGAP_EN; 730d85eed9fSMartin Blumenstingl else 731d85eed9fSMartin Blumenstingl enable_mask = MESON_SAR_ADC_DELTA_10_TS_VBG_EN; 732d85eed9fSMartin Blumenstingl 733d85eed9fSMartin Blumenstingl regmap_update_bits(priv->regmap, priv->data->bandgap_reg, enable_mask, 734d85eed9fSMartin Blumenstingl on_off ? enable_mask : 0); 735d85eed9fSMartin Blumenstingl } 736d85eed9fSMartin Blumenstingl 7373adbf342SMartin Blumenstingl static int meson_sar_adc_hw_enable(struct iio_dev *indio_dev) 7383adbf342SMartin Blumenstingl { 7393adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 7403adbf342SMartin Blumenstingl int ret; 7413af10913SHeiner Kallweit u32 regval; 7423adbf342SMartin Blumenstingl 7433adbf342SMartin Blumenstingl ret = meson_sar_adc_lock(indio_dev); 7443adbf342SMartin Blumenstingl if (ret) 7453adbf342SMartin Blumenstingl goto err_lock; 7463adbf342SMartin Blumenstingl 7473adbf342SMartin Blumenstingl ret = regulator_enable(priv->vref); 7483adbf342SMartin Blumenstingl if (ret < 0) { 7493adbf342SMartin Blumenstingl dev_err(indio_dev->dev.parent, 7503adbf342SMartin Blumenstingl "failed to enable vref regulator\n"); 7513adbf342SMartin Blumenstingl goto err_vref; 7523adbf342SMartin Blumenstingl } 7533adbf342SMartin Blumenstingl 7543adbf342SMartin Blumenstingl ret = clk_prepare_enable(priv->core_clk); 7553adbf342SMartin Blumenstingl if (ret) { 7563adbf342SMartin Blumenstingl dev_err(indio_dev->dev.parent, "failed to enable core clk\n"); 7573adbf342SMartin Blumenstingl goto err_core_clk; 7583adbf342SMartin Blumenstingl } 7593adbf342SMartin Blumenstingl 7603af10913SHeiner Kallweit regval = FIELD_PREP(MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, 1); 7613af10913SHeiner Kallweit regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, 7623af10913SHeiner Kallweit MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, regval); 763d85eed9fSMartin Blumenstingl 764d85eed9fSMartin Blumenstingl meson_sar_adc_set_bandgap(indio_dev, true); 765d85eed9fSMartin Blumenstingl 7663adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3, 7673adbf342SMartin Blumenstingl MESON_SAR_ADC_REG3_ADC_EN, 7683adbf342SMartin Blumenstingl MESON_SAR_ADC_REG3_ADC_EN); 7693adbf342SMartin Blumenstingl 7703adbf342SMartin Blumenstingl udelay(5); 7713adbf342SMartin Blumenstingl 7723adbf342SMartin Blumenstingl ret = clk_prepare_enable(priv->adc_clk); 7733adbf342SMartin Blumenstingl if (ret) { 7743adbf342SMartin Blumenstingl dev_err(indio_dev->dev.parent, "failed to enable adc clk\n"); 7753adbf342SMartin Blumenstingl goto err_adc_clk; 7763adbf342SMartin Blumenstingl } 7773adbf342SMartin Blumenstingl 7783adbf342SMartin Blumenstingl meson_sar_adc_unlock(indio_dev); 7793adbf342SMartin Blumenstingl 7803adbf342SMartin Blumenstingl return 0; 7813adbf342SMartin Blumenstingl 7823adbf342SMartin Blumenstingl err_adc_clk: 7833adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3, 7843adbf342SMartin Blumenstingl MESON_SAR_ADC_REG3_ADC_EN, 0); 785d85eed9fSMartin Blumenstingl meson_sar_adc_set_bandgap(indio_dev, false); 7863adbf342SMartin Blumenstingl clk_disable_unprepare(priv->core_clk); 7873adbf342SMartin Blumenstingl err_core_clk: 7883adbf342SMartin Blumenstingl regulator_disable(priv->vref); 7893adbf342SMartin Blumenstingl err_vref: 7903adbf342SMartin Blumenstingl meson_sar_adc_unlock(indio_dev); 7913adbf342SMartin Blumenstingl err_lock: 7923adbf342SMartin Blumenstingl return ret; 7933adbf342SMartin Blumenstingl } 7943adbf342SMartin Blumenstingl 7953adbf342SMartin Blumenstingl static int meson_sar_adc_hw_disable(struct iio_dev *indio_dev) 7963adbf342SMartin Blumenstingl { 7973adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 7983adbf342SMartin Blumenstingl int ret; 7993adbf342SMartin Blumenstingl 8003adbf342SMartin Blumenstingl ret = meson_sar_adc_lock(indio_dev); 8013adbf342SMartin Blumenstingl if (ret) 8023adbf342SMartin Blumenstingl return ret; 8033adbf342SMartin Blumenstingl 8043adbf342SMartin Blumenstingl clk_disable_unprepare(priv->adc_clk); 8053adbf342SMartin Blumenstingl 8063adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3, 8073adbf342SMartin Blumenstingl MESON_SAR_ADC_REG3_ADC_EN, 0); 808d85eed9fSMartin Blumenstingl 809d85eed9fSMartin Blumenstingl meson_sar_adc_set_bandgap(indio_dev, false); 8103adbf342SMartin Blumenstingl 8113adbf342SMartin Blumenstingl clk_disable_unprepare(priv->core_clk); 8123adbf342SMartin Blumenstingl 8133adbf342SMartin Blumenstingl regulator_disable(priv->vref); 8143adbf342SMartin Blumenstingl 8153adbf342SMartin Blumenstingl meson_sar_adc_unlock(indio_dev); 8163adbf342SMartin Blumenstingl 8173adbf342SMartin Blumenstingl return 0; 8183adbf342SMartin Blumenstingl } 8193adbf342SMartin Blumenstingl 8203af10913SHeiner Kallweit static irqreturn_t meson_sar_adc_irq(int irq, void *data) 8213af10913SHeiner Kallweit { 8223af10913SHeiner Kallweit struct iio_dev *indio_dev = data; 8233af10913SHeiner Kallweit struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 8243af10913SHeiner Kallweit unsigned int cnt, threshold; 8253af10913SHeiner Kallweit u32 regval; 8263af10913SHeiner Kallweit 8273af10913SHeiner Kallweit regmap_read(priv->regmap, MESON_SAR_ADC_REG0, ®val); 8283af10913SHeiner Kallweit cnt = FIELD_GET(MESON_SAR_ADC_REG0_FIFO_COUNT_MASK, regval); 8293af10913SHeiner Kallweit threshold = FIELD_GET(MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, regval); 8303af10913SHeiner Kallweit 8313af10913SHeiner Kallweit if (cnt < threshold) 8323af10913SHeiner Kallweit return IRQ_NONE; 8333af10913SHeiner Kallweit 8343af10913SHeiner Kallweit complete(&priv->done); 8353af10913SHeiner Kallweit 8363af10913SHeiner Kallweit return IRQ_HANDLED; 8373af10913SHeiner Kallweit } 8383af10913SHeiner Kallweit 83948ba7c3cSHeiner Kallweit static int meson_sar_adc_calib(struct iio_dev *indio_dev) 84048ba7c3cSHeiner Kallweit { 84148ba7c3cSHeiner Kallweit struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 84248ba7c3cSHeiner Kallweit int ret, nominal0, nominal1, value0, value1; 84348ba7c3cSHeiner Kallweit 84448ba7c3cSHeiner Kallweit /* use points 25% and 75% for calibration */ 84548ba7c3cSHeiner Kallweit nominal0 = (1 << priv->data->resolution) / 4; 84648ba7c3cSHeiner Kallweit nominal1 = (1 << priv->data->resolution) * 3 / 4; 84748ba7c3cSHeiner Kallweit 84848ba7c3cSHeiner Kallweit meson_sar_adc_set_chan7_mux(indio_dev, CHAN7_MUX_VDD_DIV4); 84948ba7c3cSHeiner Kallweit usleep_range(10, 20); 85048ba7c3cSHeiner Kallweit ret = meson_sar_adc_get_sample(indio_dev, 85148ba7c3cSHeiner Kallweit &meson_sar_adc_iio_channels[7], 85248ba7c3cSHeiner Kallweit MEAN_AVERAGING, EIGHT_SAMPLES, &value0); 85348ba7c3cSHeiner Kallweit if (ret < 0) 85448ba7c3cSHeiner Kallweit goto out; 85548ba7c3cSHeiner Kallweit 85648ba7c3cSHeiner Kallweit meson_sar_adc_set_chan7_mux(indio_dev, CHAN7_MUX_VDD_MUL3_DIV4); 85748ba7c3cSHeiner Kallweit usleep_range(10, 20); 85848ba7c3cSHeiner Kallweit ret = meson_sar_adc_get_sample(indio_dev, 85948ba7c3cSHeiner Kallweit &meson_sar_adc_iio_channels[7], 86048ba7c3cSHeiner Kallweit MEAN_AVERAGING, EIGHT_SAMPLES, &value1); 86148ba7c3cSHeiner Kallweit if (ret < 0) 86248ba7c3cSHeiner Kallweit goto out; 86348ba7c3cSHeiner Kallweit 86448ba7c3cSHeiner Kallweit if (value1 <= value0) { 86548ba7c3cSHeiner Kallweit ret = -EINVAL; 86648ba7c3cSHeiner Kallweit goto out; 86748ba7c3cSHeiner Kallweit } 86848ba7c3cSHeiner Kallweit 86948ba7c3cSHeiner Kallweit priv->calibscale = div_s64((nominal1 - nominal0) * (s64)MILLION, 87048ba7c3cSHeiner Kallweit value1 - value0); 87148ba7c3cSHeiner Kallweit priv->calibbias = nominal0 - div_s64((s64)value0 * priv->calibscale, 87248ba7c3cSHeiner Kallweit MILLION); 87348ba7c3cSHeiner Kallweit ret = 0; 87448ba7c3cSHeiner Kallweit out: 87548ba7c3cSHeiner Kallweit meson_sar_adc_set_chan7_mux(indio_dev, CHAN7_MUX_CH7_INPUT); 87648ba7c3cSHeiner Kallweit 87748ba7c3cSHeiner Kallweit return ret; 87848ba7c3cSHeiner Kallweit } 87948ba7c3cSHeiner Kallweit 8803adbf342SMartin Blumenstingl static const struct iio_info meson_sar_adc_iio_info = { 8813adbf342SMartin Blumenstingl .read_raw = meson_sar_adc_iio_info_read_raw, 8823adbf342SMartin Blumenstingl }; 8833adbf342SMartin Blumenstingl 8846c76ed31SMartin Blumenstingl static const struct meson_sar_adc_data meson_sar_adc_meson8_data = { 8856c76ed31SMartin Blumenstingl .has_bl30_integration = false, 886fda29dbaSMartin Blumenstingl .clock_rate = 1150000, 887d85eed9fSMartin Blumenstingl .bandgap_reg = MESON_SAR_ADC_DELTA_10, 88896748823SMartin Blumenstingl .regmap_config = &meson_sar_adc_regmap_config_meson8, 8896c76ed31SMartin Blumenstingl .resolution = 10, 8906c76ed31SMartin Blumenstingl .name = "meson-meson8-saradc", 8916c76ed31SMartin Blumenstingl }; 8926c76ed31SMartin Blumenstingl 8936c76ed31SMartin Blumenstingl static const struct meson_sar_adc_data meson_sar_adc_meson8b_data = { 8946c76ed31SMartin Blumenstingl .has_bl30_integration = false, 895fda29dbaSMartin Blumenstingl .clock_rate = 1150000, 896d85eed9fSMartin Blumenstingl .bandgap_reg = MESON_SAR_ADC_DELTA_10, 89796748823SMartin Blumenstingl .regmap_config = &meson_sar_adc_regmap_config_meson8, 8986c76ed31SMartin Blumenstingl .resolution = 10, 8996c76ed31SMartin Blumenstingl .name = "meson-meson8b-saradc", 9006c76ed31SMartin Blumenstingl }; 9016c76ed31SMartin Blumenstingl 902c1c2de37SMartin Blumenstingl static const struct meson_sar_adc_data meson_sar_adc_gxbb_data = { 9036c76ed31SMartin Blumenstingl .has_bl30_integration = true, 904fda29dbaSMartin Blumenstingl .clock_rate = 1200000, 905d85eed9fSMartin Blumenstingl .bandgap_reg = MESON_SAR_ADC_REG11, 90696748823SMartin Blumenstingl .regmap_config = &meson_sar_adc_regmap_config_gxbb, 9073adbf342SMartin Blumenstingl .resolution = 10, 9083adbf342SMartin Blumenstingl .name = "meson-gxbb-saradc", 9093adbf342SMartin Blumenstingl }; 9103adbf342SMartin Blumenstingl 911c1c2de37SMartin Blumenstingl static const struct meson_sar_adc_data meson_sar_adc_gxl_data = { 9126c76ed31SMartin Blumenstingl .has_bl30_integration = true, 913fda29dbaSMartin Blumenstingl .clock_rate = 1200000, 914d85eed9fSMartin Blumenstingl .bandgap_reg = MESON_SAR_ADC_REG11, 91596748823SMartin Blumenstingl .regmap_config = &meson_sar_adc_regmap_config_gxbb, 9163adbf342SMartin Blumenstingl .resolution = 12, 9173adbf342SMartin Blumenstingl .name = "meson-gxl-saradc", 9183adbf342SMartin Blumenstingl }; 9193adbf342SMartin Blumenstingl 920c1c2de37SMartin Blumenstingl static const struct meson_sar_adc_data meson_sar_adc_gxm_data = { 9216c76ed31SMartin Blumenstingl .has_bl30_integration = true, 922fda29dbaSMartin Blumenstingl .clock_rate = 1200000, 923d85eed9fSMartin Blumenstingl .bandgap_reg = MESON_SAR_ADC_REG11, 92496748823SMartin Blumenstingl .regmap_config = &meson_sar_adc_regmap_config_gxbb, 9253adbf342SMartin Blumenstingl .resolution = 12, 9263adbf342SMartin Blumenstingl .name = "meson-gxm-saradc", 9273adbf342SMartin Blumenstingl }; 9283adbf342SMartin Blumenstingl 9293adbf342SMartin Blumenstingl static const struct of_device_id meson_sar_adc_of_match[] = { 9303adbf342SMartin Blumenstingl { 9316c76ed31SMartin Blumenstingl .compatible = "amlogic,meson8-saradc", 9326c76ed31SMartin Blumenstingl .data = &meson_sar_adc_meson8_data, 9336c76ed31SMartin Blumenstingl }, 9346c76ed31SMartin Blumenstingl { 9356c76ed31SMartin Blumenstingl .compatible = "amlogic,meson8b-saradc", 9366c76ed31SMartin Blumenstingl .data = &meson_sar_adc_meson8b_data, 9376c76ed31SMartin Blumenstingl }, 9386c76ed31SMartin Blumenstingl { 9393adbf342SMartin Blumenstingl .compatible = "amlogic,meson-gxbb-saradc", 9403adbf342SMartin Blumenstingl .data = &meson_sar_adc_gxbb_data, 9413adbf342SMartin Blumenstingl }, { 9423adbf342SMartin Blumenstingl .compatible = "amlogic,meson-gxl-saradc", 9433adbf342SMartin Blumenstingl .data = &meson_sar_adc_gxl_data, 9443adbf342SMartin Blumenstingl }, { 9453adbf342SMartin Blumenstingl .compatible = "amlogic,meson-gxm-saradc", 9463adbf342SMartin Blumenstingl .data = &meson_sar_adc_gxm_data, 9473adbf342SMartin Blumenstingl }, 9483adbf342SMartin Blumenstingl {}, 9493adbf342SMartin Blumenstingl }; 9503adbf342SMartin Blumenstingl MODULE_DEVICE_TABLE(of, meson_sar_adc_of_match); 9513adbf342SMartin Blumenstingl 9523adbf342SMartin Blumenstingl static int meson_sar_adc_probe(struct platform_device *pdev) 9533adbf342SMartin Blumenstingl { 9543adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv; 9553adbf342SMartin Blumenstingl struct iio_dev *indio_dev; 9563adbf342SMartin Blumenstingl struct resource *res; 9573adbf342SMartin Blumenstingl void __iomem *base; 9583adbf342SMartin Blumenstingl const struct of_device_id *match; 9593af10913SHeiner Kallweit int irq, ret; 9603adbf342SMartin Blumenstingl 9613adbf342SMartin Blumenstingl indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*priv)); 9623adbf342SMartin Blumenstingl if (!indio_dev) { 9633adbf342SMartin Blumenstingl dev_err(&pdev->dev, "failed allocating iio device\n"); 9643adbf342SMartin Blumenstingl return -ENOMEM; 9653adbf342SMartin Blumenstingl } 9663adbf342SMartin Blumenstingl 9673adbf342SMartin Blumenstingl priv = iio_priv(indio_dev); 9683af10913SHeiner Kallweit init_completion(&priv->done); 9693adbf342SMartin Blumenstingl 9703adbf342SMartin Blumenstingl match = of_match_device(meson_sar_adc_of_match, &pdev->dev); 9712f9aeeedSGustavo A. R. Silva if (!match) { 9722f9aeeedSGustavo A. R. Silva dev_err(&pdev->dev, "failed to match device\n"); 9732f9aeeedSGustavo A. R. Silva return -ENODEV; 9742f9aeeedSGustavo A. R. Silva } 9752f9aeeedSGustavo A. R. Silva 9763adbf342SMartin Blumenstingl priv->data = match->data; 9773adbf342SMartin Blumenstingl 9783adbf342SMartin Blumenstingl indio_dev->name = priv->data->name; 9793adbf342SMartin Blumenstingl indio_dev->dev.parent = &pdev->dev; 9803adbf342SMartin Blumenstingl indio_dev->dev.of_node = pdev->dev.of_node; 9813adbf342SMartin Blumenstingl indio_dev->modes = INDIO_DIRECT_MODE; 9823adbf342SMartin Blumenstingl indio_dev->info = &meson_sar_adc_iio_info; 9833adbf342SMartin Blumenstingl 9843adbf342SMartin Blumenstingl indio_dev->channels = meson_sar_adc_iio_channels; 9853adbf342SMartin Blumenstingl indio_dev->num_channels = ARRAY_SIZE(meson_sar_adc_iio_channels); 9863adbf342SMartin Blumenstingl 9873adbf342SMartin Blumenstingl res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 9883adbf342SMartin Blumenstingl base = devm_ioremap_resource(&pdev->dev, res); 9893adbf342SMartin Blumenstingl if (IS_ERR(base)) 9903adbf342SMartin Blumenstingl return PTR_ERR(base); 9913adbf342SMartin Blumenstingl 9923af10913SHeiner Kallweit irq = irq_of_parse_and_map(pdev->dev.of_node, 0); 9933af10913SHeiner Kallweit if (!irq) 9943af10913SHeiner Kallweit return -EINVAL; 9953af10913SHeiner Kallweit 9963af10913SHeiner Kallweit ret = devm_request_irq(&pdev->dev, irq, meson_sar_adc_irq, IRQF_SHARED, 9973af10913SHeiner Kallweit dev_name(&pdev->dev), indio_dev); 9983af10913SHeiner Kallweit if (ret) 9993af10913SHeiner Kallweit return ret; 10003af10913SHeiner Kallweit 10013adbf342SMartin Blumenstingl priv->regmap = devm_regmap_init_mmio(&pdev->dev, base, 100296748823SMartin Blumenstingl priv->data->regmap_config); 10033adbf342SMartin Blumenstingl if (IS_ERR(priv->regmap)) 10043adbf342SMartin Blumenstingl return PTR_ERR(priv->regmap); 10053adbf342SMartin Blumenstingl 10063adbf342SMartin Blumenstingl priv->clkin = devm_clk_get(&pdev->dev, "clkin"); 10073adbf342SMartin Blumenstingl if (IS_ERR(priv->clkin)) { 10083adbf342SMartin Blumenstingl dev_err(&pdev->dev, "failed to get clkin\n"); 10093adbf342SMartin Blumenstingl return PTR_ERR(priv->clkin); 10103adbf342SMartin Blumenstingl } 10113adbf342SMartin Blumenstingl 10123adbf342SMartin Blumenstingl priv->core_clk = devm_clk_get(&pdev->dev, "core"); 10133adbf342SMartin Blumenstingl if (IS_ERR(priv->core_clk)) { 10143adbf342SMartin Blumenstingl dev_err(&pdev->dev, "failed to get core clk\n"); 10153adbf342SMartin Blumenstingl return PTR_ERR(priv->core_clk); 10163adbf342SMartin Blumenstingl } 10173adbf342SMartin Blumenstingl 10183adbf342SMartin Blumenstingl priv->adc_clk = devm_clk_get(&pdev->dev, "adc_clk"); 10193adbf342SMartin Blumenstingl if (IS_ERR(priv->adc_clk)) { 10203adbf342SMartin Blumenstingl if (PTR_ERR(priv->adc_clk) == -ENOENT) { 10213adbf342SMartin Blumenstingl priv->adc_clk = NULL; 10223adbf342SMartin Blumenstingl } else { 10233adbf342SMartin Blumenstingl dev_err(&pdev->dev, "failed to get adc clk\n"); 10243adbf342SMartin Blumenstingl return PTR_ERR(priv->adc_clk); 10253adbf342SMartin Blumenstingl } 10263adbf342SMartin Blumenstingl } 10273adbf342SMartin Blumenstingl 10283adbf342SMartin Blumenstingl priv->adc_sel_clk = devm_clk_get(&pdev->dev, "adc_sel"); 10293adbf342SMartin Blumenstingl if (IS_ERR(priv->adc_sel_clk)) { 10303adbf342SMartin Blumenstingl if (PTR_ERR(priv->adc_sel_clk) == -ENOENT) { 10313adbf342SMartin Blumenstingl priv->adc_sel_clk = NULL; 10323adbf342SMartin Blumenstingl } else { 10333adbf342SMartin Blumenstingl dev_err(&pdev->dev, "failed to get adc_sel clk\n"); 10343adbf342SMartin Blumenstingl return PTR_ERR(priv->adc_sel_clk); 10353adbf342SMartin Blumenstingl } 10363adbf342SMartin Blumenstingl } 10373adbf342SMartin Blumenstingl 10383adbf342SMartin Blumenstingl /* on pre-GXBB SoCs the SAR ADC itself provides the ADC clock: */ 10393adbf342SMartin Blumenstingl if (!priv->adc_clk) { 10403adbf342SMartin Blumenstingl ret = meson_sar_adc_clk_init(indio_dev, base); 10413adbf342SMartin Blumenstingl if (ret) 10423adbf342SMartin Blumenstingl return ret; 10433adbf342SMartin Blumenstingl } 10443adbf342SMartin Blumenstingl 10453adbf342SMartin Blumenstingl priv->vref = devm_regulator_get(&pdev->dev, "vref"); 10463adbf342SMartin Blumenstingl if (IS_ERR(priv->vref)) { 10473adbf342SMartin Blumenstingl dev_err(&pdev->dev, "failed to get vref regulator\n"); 10483adbf342SMartin Blumenstingl return PTR_ERR(priv->vref); 10493adbf342SMartin Blumenstingl } 10503adbf342SMartin Blumenstingl 105148ba7c3cSHeiner Kallweit priv->calibscale = MILLION; 105248ba7c3cSHeiner Kallweit 10533adbf342SMartin Blumenstingl ret = meson_sar_adc_init(indio_dev); 10543adbf342SMartin Blumenstingl if (ret) 10553adbf342SMartin Blumenstingl goto err; 10563adbf342SMartin Blumenstingl 10573adbf342SMartin Blumenstingl ret = meson_sar_adc_hw_enable(indio_dev); 10583adbf342SMartin Blumenstingl if (ret) 10593adbf342SMartin Blumenstingl goto err; 10603adbf342SMartin Blumenstingl 106148ba7c3cSHeiner Kallweit ret = meson_sar_adc_calib(indio_dev); 106248ba7c3cSHeiner Kallweit if (ret) 106348ba7c3cSHeiner Kallweit dev_warn(&pdev->dev, "calibration failed\n"); 106448ba7c3cSHeiner Kallweit 10653adbf342SMartin Blumenstingl platform_set_drvdata(pdev, indio_dev); 10663adbf342SMartin Blumenstingl 10673adbf342SMartin Blumenstingl ret = iio_device_register(indio_dev); 10683adbf342SMartin Blumenstingl if (ret) 10693adbf342SMartin Blumenstingl goto err_hw; 10703adbf342SMartin Blumenstingl 10713adbf342SMartin Blumenstingl return 0; 10723adbf342SMartin Blumenstingl 10733adbf342SMartin Blumenstingl err_hw: 10743adbf342SMartin Blumenstingl meson_sar_adc_hw_disable(indio_dev); 10753adbf342SMartin Blumenstingl err: 10763adbf342SMartin Blumenstingl return ret; 10773adbf342SMartin Blumenstingl } 10783adbf342SMartin Blumenstingl 10793adbf342SMartin Blumenstingl static int meson_sar_adc_remove(struct platform_device *pdev) 10803adbf342SMartin Blumenstingl { 10813adbf342SMartin Blumenstingl struct iio_dev *indio_dev = platform_get_drvdata(pdev); 10823adbf342SMartin Blumenstingl 10833adbf342SMartin Blumenstingl iio_device_unregister(indio_dev); 10843adbf342SMartin Blumenstingl 10853adbf342SMartin Blumenstingl return meson_sar_adc_hw_disable(indio_dev); 10863adbf342SMartin Blumenstingl } 10873adbf342SMartin Blumenstingl 10883adbf342SMartin Blumenstingl static int __maybe_unused meson_sar_adc_suspend(struct device *dev) 10893adbf342SMartin Blumenstingl { 10903adbf342SMartin Blumenstingl struct iio_dev *indio_dev = dev_get_drvdata(dev); 10913adbf342SMartin Blumenstingl 10923adbf342SMartin Blumenstingl return meson_sar_adc_hw_disable(indio_dev); 10933adbf342SMartin Blumenstingl } 10943adbf342SMartin Blumenstingl 10953adbf342SMartin Blumenstingl static int __maybe_unused meson_sar_adc_resume(struct device *dev) 10963adbf342SMartin Blumenstingl { 10973adbf342SMartin Blumenstingl struct iio_dev *indio_dev = dev_get_drvdata(dev); 10983adbf342SMartin Blumenstingl 10993adbf342SMartin Blumenstingl return meson_sar_adc_hw_enable(indio_dev); 11003adbf342SMartin Blumenstingl } 11013adbf342SMartin Blumenstingl 11023adbf342SMartin Blumenstingl static SIMPLE_DEV_PM_OPS(meson_sar_adc_pm_ops, 11033adbf342SMartin Blumenstingl meson_sar_adc_suspend, meson_sar_adc_resume); 11043adbf342SMartin Blumenstingl 11053adbf342SMartin Blumenstingl static struct platform_driver meson_sar_adc_driver = { 11063adbf342SMartin Blumenstingl .probe = meson_sar_adc_probe, 11073adbf342SMartin Blumenstingl .remove = meson_sar_adc_remove, 11083adbf342SMartin Blumenstingl .driver = { 11093adbf342SMartin Blumenstingl .name = "meson-saradc", 11103adbf342SMartin Blumenstingl .of_match_table = meson_sar_adc_of_match, 11113adbf342SMartin Blumenstingl .pm = &meson_sar_adc_pm_ops, 11123adbf342SMartin Blumenstingl }, 11133adbf342SMartin Blumenstingl }; 11143adbf342SMartin Blumenstingl 11153adbf342SMartin Blumenstingl module_platform_driver(meson_sar_adc_driver); 11163adbf342SMartin Blumenstingl 11173adbf342SMartin Blumenstingl MODULE_AUTHOR("Martin Blumenstingl <martin.blumenstingl@googlemail.com>"); 11183adbf342SMartin Blumenstingl MODULE_DESCRIPTION("Amlogic Meson SAR ADC driver"); 11193adbf342SMartin Blumenstingl MODULE_LICENSE("GPL v2"); 1120