147dd8378SNeil Armstrong // SPDX-License-Identifier: GPL-2.0 23adbf342SMartin Blumenstingl /* 33adbf342SMartin Blumenstingl * Amlogic Meson Successive Approximation Register (SAR) A/D Converter 43adbf342SMartin Blumenstingl * 53adbf342SMartin Blumenstingl * Copyright (C) 2017 Martin Blumenstingl <martin.blumenstingl@googlemail.com> 63adbf342SMartin Blumenstingl */ 73adbf342SMartin Blumenstingl 83adbf342SMartin Blumenstingl #include <linux/bitfield.h> 93adbf342SMartin Blumenstingl #include <linux/clk.h> 103adbf342SMartin Blumenstingl #include <linux/clk-provider.h> 113adbf342SMartin Blumenstingl #include <linux/delay.h> 123adbf342SMartin Blumenstingl #include <linux/io.h> 133adbf342SMartin Blumenstingl #include <linux/iio/iio.h> 143adbf342SMartin Blumenstingl #include <linux/module.h> 15d0c09264SNuno Sá #include <linux/mutex.h> 16723a61e0SMartin Blumenstingl #include <linux/nvmem-consumer.h> 173af10913SHeiner Kallweit #include <linux/interrupt.h> 183adbf342SMartin Blumenstingl #include <linux/of.h> 193af10913SHeiner Kallweit #include <linux/of_irq.h> 203adbf342SMartin Blumenstingl #include <linux/of_device.h> 213adbf342SMartin Blumenstingl #include <linux/platform_device.h> 223adbf342SMartin Blumenstingl #include <linux/regmap.h> 233adbf342SMartin Blumenstingl #include <linux/regulator/consumer.h> 24b002bf5fSMartin Blumenstingl #include <linux/mfd/syscon.h> 253adbf342SMartin Blumenstingl 263adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0 0x00 273adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_PANEL_DETECT BIT(31) 283adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_BUSY_MASK GENMASK(30, 28) 293adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_DELTA_BUSY BIT(30) 303adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_AVG_BUSY BIT(29) 313adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_SAMPLE_BUSY BIT(28) 323adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_FIFO_FULL BIT(27) 333adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_FIFO_EMPTY BIT(26) 343adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_FIFO_COUNT_MASK GENMASK(25, 21) 353adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_ADC_BIAS_CTRL_MASK GENMASK(20, 19) 363adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_CURR_CHAN_ID_MASK GENMASK(18, 16) 373adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_ADC_TEMP_SEN_SEL BIT(15) 383adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_SAMPLING_STOP BIT(14) 393adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_CHAN_DELTA_EN_MASK GENMASK(13, 12) 403adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_DETECT_IRQ_POL BIT(10) 413adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_DETECT_IRQ_EN BIT(9) 423adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK GENMASK(8, 4) 433adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_FIFO_IRQ_EN BIT(3) 443adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_SAMPLING_START BIT(2) 453adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_CONTINUOUS_EN BIT(1) 463adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE BIT(0) 473adbf342SMartin Blumenstingl 483adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_LIST 0x04 493adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_LIST_MAX_INDEX_MASK GENMASK(26, 24) 503adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_LIST_ENTRY_MASK(_chan) \ 513adbf342SMartin Blumenstingl (GENMASK(2, 0) << ((_chan) * 3)) 523adbf342SMartin Blumenstingl 533adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AVG_CNTL 0x08 543adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AVG_CNTL_AVG_MODE_SHIFT(_chan) \ 553adbf342SMartin Blumenstingl (16 + ((_chan) * 2)) 563adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AVG_CNTL_AVG_MODE_MASK(_chan) \ 573adbf342SMartin Blumenstingl (GENMASK(17, 16) << ((_chan) * 2)) 583adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AVG_CNTL_NUM_SAMPLES_SHIFT(_chan) \ 593adbf342SMartin Blumenstingl (0 + ((_chan) * 2)) 603adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AVG_CNTL_NUM_SAMPLES_MASK(_chan) \ 613adbf342SMartin Blumenstingl (GENMASK(1, 0) << ((_chan) * 2)) 623adbf342SMartin Blumenstingl 633adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3 0x0c 643adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_CNTL_USE_SC_DLY BIT(31) 653adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_CLK_EN BIT(30) 663adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_BL30_INITIALIZED BIT(28) 673adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_CTRL_CONT_RING_COUNTER_EN BIT(27) 683adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_CTRL_SAMPLING_CLOCK_PHASE BIT(26) 693adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_CTRL_CHAN7_MUX_SEL_MASK GENMASK(25, 23) 703adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_DETECT_EN BIT(22) 713adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_ADC_EN BIT(21) 723adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_PANEL_DETECT_COUNT_MASK GENMASK(20, 18) 733adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_PANEL_DETECT_FILTER_TB_MASK GENMASK(17, 16) 743adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_ADC_CLK_DIV_SHIFT 10 753adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_ADC_CLK_DIV_WIDTH 5 763adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_BLOCK_DLY_SEL_MASK GENMASK(9, 8) 773adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_BLOCK_DLY_MASK GENMASK(7, 0) 783adbf342SMartin Blumenstingl 793adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELAY 0x10 803adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELAY_INPUT_DLY_SEL_MASK GENMASK(25, 24) 813adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELAY_BL30_BUSY BIT(15) 823adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELAY_KERNEL_BUSY BIT(14) 833adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELAY_INPUT_DLY_CNT_MASK GENMASK(23, 16) 843adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELAY_SAMPLE_DLY_SEL_MASK GENMASK(9, 8) 853adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELAY_SAMPLE_DLY_CNT_MASK GENMASK(7, 0) 863adbf342SMartin Blumenstingl 873adbf342SMartin Blumenstingl #define MESON_SAR_ADC_LAST_RD 0x14 883adbf342SMartin Blumenstingl #define MESON_SAR_ADC_LAST_RD_LAST_CHANNEL1_MASK GENMASK(23, 16) 893adbf342SMartin Blumenstingl #define MESON_SAR_ADC_LAST_RD_LAST_CHANNEL0_MASK GENMASK(9, 0) 903adbf342SMartin Blumenstingl 913adbf342SMartin Blumenstingl #define MESON_SAR_ADC_FIFO_RD 0x18 923adbf342SMartin Blumenstingl #define MESON_SAR_ADC_FIFO_RD_CHAN_ID_MASK GENMASK(14, 12) 933adbf342SMartin Blumenstingl #define MESON_SAR_ADC_FIFO_RD_SAMPLE_VALUE_MASK GENMASK(11, 0) 943adbf342SMartin Blumenstingl 953adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AUX_SW 0x1c 96ab569a4cSMartin Blumenstingl #define MESON_SAR_ADC_AUX_SW_MUX_SEL_CHAN_SHIFT(_chan) \ 97ab569a4cSMartin Blumenstingl (8 + (((_chan) - 2) * 3)) 983adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AUX_SW_VREF_P_MUX BIT(6) 993adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AUX_SW_VREF_N_MUX BIT(5) 1003adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AUX_SW_MODE_SEL BIT(4) 1013adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AUX_SW_YP_DRIVE_SW BIT(3) 1023adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AUX_SW_XP_DRIVE_SW BIT(2) 1033adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AUX_SW_YM_DRIVE_SW BIT(1) 1043adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AUX_SW_XM_DRIVE_SW BIT(0) 1053adbf342SMartin Blumenstingl 1063adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW 0x20 1073adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_MUX_SEL_MASK GENMASK(25, 23) 1083adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_VREF_P_MUX BIT(22) 1093adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_VREF_N_MUX BIT(21) 1103adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_MODE_SEL BIT(20) 1113adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_YP_DRIVE_SW BIT(19) 1123adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_XP_DRIVE_SW BIT(18) 1133adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_YM_DRIVE_SW BIT(17) 1143adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_XM_DRIVE_SW BIT(16) 1153adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_MUX_SEL_MASK GENMASK(9, 7) 1163adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_VREF_P_MUX BIT(6) 1173adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_VREF_N_MUX BIT(5) 1183adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_MODE_SEL BIT(4) 1193adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_YP_DRIVE_SW BIT(3) 1203adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_XP_DRIVE_SW BIT(2) 1213adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_YM_DRIVE_SW BIT(1) 1223adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_XM_DRIVE_SW BIT(0) 1233adbf342SMartin Blumenstingl 1243adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW 0x24 1253adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_SW_EN BIT(26) 1263adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_MUX_MASK GENMASK(25, 23) 1273adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_VREF_P_MUX BIT(22) 1283adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_VREF_N_MUX BIT(21) 1293adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_MODE_SEL BIT(20) 1303adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_YP_DRIVE_SW BIT(19) 1313adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_XP_DRIVE_SW BIT(18) 1323adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_YM_DRIVE_SW BIT(17) 1333adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_XM_DRIVE_SW BIT(16) 1343adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_MUX_SEL_MASK GENMASK(9, 7) 1353adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_VREF_P_MUX BIT(6) 1363adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_VREF_N_MUX BIT(5) 1373adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_MODE_SEL BIT(4) 1383adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_YP_DRIVE_SW BIT(3) 1393adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_XP_DRIVE_SW BIT(2) 1403adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_YM_DRIVE_SW BIT(1) 1413adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_XM_DRIVE_SW BIT(0) 1423adbf342SMartin Blumenstingl 1433adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELTA_10 0x28 1443adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELTA_10_TEMP_SEL BIT(27) 1453adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELTA_10_TS_REVE1 BIT(26) 1463adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELTA_10_CHAN1_DELTA_VALUE_MASK GENMASK(25, 16) 1473adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELTA_10_TS_REVE0 BIT(15) 1483adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELTA_10_TS_C_MASK GENMASK(14, 11) 1493adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELTA_10_TS_VBG_EN BIT(10) 1503adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELTA_10_CHAN0_DELTA_VALUE_MASK GENMASK(9, 0) 1513adbf342SMartin Blumenstingl 1523adbf342SMartin Blumenstingl /* 1533adbf342SMartin Blumenstingl * NOTE: registers from here are undocumented (the vendor Linux kernel driver 1543adbf342SMartin Blumenstingl * and u-boot source served as reference). These only seem to be relevant on 1553adbf342SMartin Blumenstingl * GXBB and newer. 1563adbf342SMartin Blumenstingl */ 1573adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG11 0x2c 1583adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG11_BANDGAP_EN BIT(13) 1593adbf342SMartin Blumenstingl 1603adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG13 0x34 1613adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG13_12BIT_CALIBRATION_MASK GENMASK(13, 8) 1623adbf342SMartin Blumenstingl 1633adbf342SMartin Blumenstingl #define MESON_SAR_ADC_MAX_FIFO_SIZE 32 1643af10913SHeiner Kallweit #define MESON_SAR_ADC_TIMEOUT 100 /* ms */ 165723a61e0SMartin Blumenstingl #define MESON_SAR_ADC_VOLTAGE_AND_TEMP_CHANNEL 6 166723a61e0SMartin Blumenstingl #define MESON_SAR_ADC_TEMP_OFFSET 27 167723a61e0SMartin Blumenstingl 168723a61e0SMartin Blumenstingl /* temperature sensor calibration information in eFuse */ 169723a61e0SMartin Blumenstingl #define MESON_SAR_ADC_EFUSE_BYTES 4 170723a61e0SMartin Blumenstingl #define MESON_SAR_ADC_EFUSE_BYTE3_UPPER_ADC_VAL GENMASK(6, 0) 171723a61e0SMartin Blumenstingl #define MESON_SAR_ADC_EFUSE_BYTE3_IS_CALIBRATED BIT(7) 172723a61e0SMartin Blumenstingl 173b002bf5fSMartin Blumenstingl #define MESON_HHI_DPLL_TOP_0 0x318 174b002bf5fSMartin Blumenstingl #define MESON_HHI_DPLL_TOP_0_TSC_BIT4 BIT(9) 175b002bf5fSMartin Blumenstingl 17648ba7c3cSHeiner Kallweit /* for use with IIO_VAL_INT_PLUS_MICRO */ 17748ba7c3cSHeiner Kallweit #define MILLION 1000000 1783adbf342SMartin Blumenstingl 1793adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN(_chan) { \ 1803adbf342SMartin Blumenstingl .type = IIO_VOLTAGE, \ 1813adbf342SMartin Blumenstingl .indexed = 1, \ 1823adbf342SMartin Blumenstingl .channel = _chan, \ 183827df057SMartin Blumenstingl .address = _chan, \ 1843adbf342SMartin Blumenstingl .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ 1853adbf342SMartin Blumenstingl BIT(IIO_CHAN_INFO_AVERAGE_RAW), \ 186723a61e0SMartin Blumenstingl .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ 187723a61e0SMartin Blumenstingl .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_CALIBBIAS) | \ 18848ba7c3cSHeiner Kallweit BIT(IIO_CHAN_INFO_CALIBSCALE), \ 1893adbf342SMartin Blumenstingl .datasheet_name = "SAR_ADC_CH"#_chan, \ 1903adbf342SMartin Blumenstingl } 1913adbf342SMartin Blumenstingl 192723a61e0SMartin Blumenstingl #define MESON_SAR_ADC_TEMP_CHAN(_chan) { \ 193723a61e0SMartin Blumenstingl .type = IIO_TEMP, \ 194723a61e0SMartin Blumenstingl .channel = _chan, \ 195723a61e0SMartin Blumenstingl .address = MESON_SAR_ADC_VOLTAGE_AND_TEMP_CHANNEL, \ 196723a61e0SMartin Blumenstingl .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ 197723a61e0SMartin Blumenstingl BIT(IIO_CHAN_INFO_AVERAGE_RAW), \ 198723a61e0SMartin Blumenstingl .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | \ 199723a61e0SMartin Blumenstingl BIT(IIO_CHAN_INFO_SCALE), \ 200723a61e0SMartin Blumenstingl .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_CALIBBIAS) | \ 201723a61e0SMartin Blumenstingl BIT(IIO_CHAN_INFO_CALIBSCALE), \ 202723a61e0SMartin Blumenstingl .datasheet_name = "TEMP_SENSOR", \ 203723a61e0SMartin Blumenstingl } 204723a61e0SMartin Blumenstingl 2053adbf342SMartin Blumenstingl static const struct iio_chan_spec meson_sar_adc_iio_channels[] = { 2063adbf342SMartin Blumenstingl MESON_SAR_ADC_CHAN(0), 2073adbf342SMartin Blumenstingl MESON_SAR_ADC_CHAN(1), 2083adbf342SMartin Blumenstingl MESON_SAR_ADC_CHAN(2), 2093adbf342SMartin Blumenstingl MESON_SAR_ADC_CHAN(3), 2103adbf342SMartin Blumenstingl MESON_SAR_ADC_CHAN(4), 2113adbf342SMartin Blumenstingl MESON_SAR_ADC_CHAN(5), 2123adbf342SMartin Blumenstingl MESON_SAR_ADC_CHAN(6), 2133adbf342SMartin Blumenstingl MESON_SAR_ADC_CHAN(7), 2143adbf342SMartin Blumenstingl IIO_CHAN_SOFT_TIMESTAMP(8), 2153adbf342SMartin Blumenstingl }; 2163adbf342SMartin Blumenstingl 217723a61e0SMartin Blumenstingl static const struct iio_chan_spec meson_sar_adc_and_temp_iio_channels[] = { 218723a61e0SMartin Blumenstingl MESON_SAR_ADC_CHAN(0), 219723a61e0SMartin Blumenstingl MESON_SAR_ADC_CHAN(1), 220723a61e0SMartin Blumenstingl MESON_SAR_ADC_CHAN(2), 221723a61e0SMartin Blumenstingl MESON_SAR_ADC_CHAN(3), 222723a61e0SMartin Blumenstingl MESON_SAR_ADC_CHAN(4), 223723a61e0SMartin Blumenstingl MESON_SAR_ADC_CHAN(5), 224723a61e0SMartin Blumenstingl MESON_SAR_ADC_CHAN(6), 225723a61e0SMartin Blumenstingl MESON_SAR_ADC_CHAN(7), 226723a61e0SMartin Blumenstingl MESON_SAR_ADC_TEMP_CHAN(8), 227723a61e0SMartin Blumenstingl IIO_CHAN_SOFT_TIMESTAMP(9), 228723a61e0SMartin Blumenstingl }; 229723a61e0SMartin Blumenstingl 2303adbf342SMartin Blumenstingl enum meson_sar_adc_avg_mode { 2313adbf342SMartin Blumenstingl NO_AVERAGING = 0x0, 2323adbf342SMartin Blumenstingl MEAN_AVERAGING = 0x1, 2333adbf342SMartin Blumenstingl MEDIAN_AVERAGING = 0x2, 2343adbf342SMartin Blumenstingl }; 2353adbf342SMartin Blumenstingl 2363adbf342SMartin Blumenstingl enum meson_sar_adc_num_samples { 2373adbf342SMartin Blumenstingl ONE_SAMPLE = 0x0, 2383adbf342SMartin Blumenstingl TWO_SAMPLES = 0x1, 2393adbf342SMartin Blumenstingl FOUR_SAMPLES = 0x2, 2403adbf342SMartin Blumenstingl EIGHT_SAMPLES = 0x3, 2413adbf342SMartin Blumenstingl }; 2423adbf342SMartin Blumenstingl 2433adbf342SMartin Blumenstingl enum meson_sar_adc_chan7_mux_sel { 2443adbf342SMartin Blumenstingl CHAN7_MUX_VSS = 0x0, 2453adbf342SMartin Blumenstingl CHAN7_MUX_VDD_DIV4 = 0x1, 2463adbf342SMartin Blumenstingl CHAN7_MUX_VDD_DIV2 = 0x2, 2473adbf342SMartin Blumenstingl CHAN7_MUX_VDD_MUL3_DIV4 = 0x3, 2483adbf342SMartin Blumenstingl CHAN7_MUX_VDD = 0x4, 2493adbf342SMartin Blumenstingl CHAN7_MUX_CH7_INPUT = 0x7, 2503adbf342SMartin Blumenstingl }; 2513adbf342SMartin Blumenstingl 252053ffe3cSYixun Lan struct meson_sar_adc_param { 2536c76ed31SMartin Blumenstingl bool has_bl30_integration; 254fda29dbaSMartin Blumenstingl unsigned long clock_rate; 255d85eed9fSMartin Blumenstingl u32 bandgap_reg; 2563adbf342SMartin Blumenstingl unsigned int resolution; 25796748823SMartin Blumenstingl const struct regmap_config *regmap_config; 258723a61e0SMartin Blumenstingl u8 temperature_trimming_bits; 259723a61e0SMartin Blumenstingl unsigned int temperature_multiplier; 260723a61e0SMartin Blumenstingl unsigned int temperature_divider; 2613adbf342SMartin Blumenstingl }; 2623adbf342SMartin Blumenstingl 263053ffe3cSYixun Lan struct meson_sar_adc_data { 264053ffe3cSYixun Lan const struct meson_sar_adc_param *param; 265053ffe3cSYixun Lan const char *name; 266053ffe3cSYixun Lan }; 267053ffe3cSYixun Lan 2683adbf342SMartin Blumenstingl struct meson_sar_adc_priv { 2693adbf342SMartin Blumenstingl struct regmap *regmap; 2703adbf342SMartin Blumenstingl struct regulator *vref; 271057e5a11SMartin Blumenstingl const struct meson_sar_adc_param *param; 2723adbf342SMartin Blumenstingl struct clk *clkin; 2733adbf342SMartin Blumenstingl struct clk *core_clk; 2743adbf342SMartin Blumenstingl struct clk *adc_sel_clk; 2753adbf342SMartin Blumenstingl struct clk *adc_clk; 2763adbf342SMartin Blumenstingl struct clk_gate clk_gate; 2773adbf342SMartin Blumenstingl struct clk *adc_div_clk; 2783adbf342SMartin Blumenstingl struct clk_divider clk_div; 2793af10913SHeiner Kallweit struct completion done; 280d0c09264SNuno Sá /* lock to protect against multiple access to the device */ 281d0c09264SNuno Sá struct mutex lock; 28248ba7c3cSHeiner Kallweit int calibbias; 28348ba7c3cSHeiner Kallweit int calibscale; 284b002bf5fSMartin Blumenstingl struct regmap *tsc_regmap; 285723a61e0SMartin Blumenstingl bool temperature_sensor_calibrated; 286723a61e0SMartin Blumenstingl u8 temperature_sensor_coefficient; 287723a61e0SMartin Blumenstingl u16 temperature_sensor_adc_val; 2883adbf342SMartin Blumenstingl }; 2893adbf342SMartin Blumenstingl 29096748823SMartin Blumenstingl static const struct regmap_config meson_sar_adc_regmap_config_gxbb = { 2913adbf342SMartin Blumenstingl .reg_bits = 8, 2923adbf342SMartin Blumenstingl .val_bits = 32, 2933adbf342SMartin Blumenstingl .reg_stride = 4, 2943adbf342SMartin Blumenstingl .max_register = MESON_SAR_ADC_REG13, 2953adbf342SMartin Blumenstingl }; 2963adbf342SMartin Blumenstingl 29796748823SMartin Blumenstingl static const struct regmap_config meson_sar_adc_regmap_config_meson8 = { 29896748823SMartin Blumenstingl .reg_bits = 8, 29996748823SMartin Blumenstingl .val_bits = 32, 30096748823SMartin Blumenstingl .reg_stride = 4, 30196748823SMartin Blumenstingl .max_register = MESON_SAR_ADC_DELTA_10, 30296748823SMartin Blumenstingl }; 30396748823SMartin Blumenstingl 3043adbf342SMartin Blumenstingl static unsigned int meson_sar_adc_get_fifo_count(struct iio_dev *indio_dev) 3053adbf342SMartin Blumenstingl { 3063adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 3073adbf342SMartin Blumenstingl u32 regval; 3083adbf342SMartin Blumenstingl 3093adbf342SMartin Blumenstingl regmap_read(priv->regmap, MESON_SAR_ADC_REG0, ®val); 3103adbf342SMartin Blumenstingl 3113adbf342SMartin Blumenstingl return FIELD_GET(MESON_SAR_ADC_REG0_FIFO_COUNT_MASK, regval); 3123adbf342SMartin Blumenstingl } 3133adbf342SMartin Blumenstingl 31448ba7c3cSHeiner Kallweit static int meson_sar_adc_calib_val(struct iio_dev *indio_dev, int val) 31548ba7c3cSHeiner Kallweit { 31648ba7c3cSHeiner Kallweit struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 31748ba7c3cSHeiner Kallweit int tmp; 31848ba7c3cSHeiner Kallweit 31948ba7c3cSHeiner Kallweit /* use val_calib = scale * val_raw + offset calibration function */ 32048ba7c3cSHeiner Kallweit tmp = div_s64((s64)val * priv->calibscale, MILLION) + priv->calibbias; 32148ba7c3cSHeiner Kallweit 322057e5a11SMartin Blumenstingl return clamp(tmp, 0, (1 << priv->param->resolution) - 1); 32348ba7c3cSHeiner Kallweit } 32448ba7c3cSHeiner Kallweit 3253adbf342SMartin Blumenstingl static int meson_sar_adc_wait_busy_clear(struct iio_dev *indio_dev) 3263adbf342SMartin Blumenstingl { 3273adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 32879b584edSAndy Shevchenko int val; 3293adbf342SMartin Blumenstingl 3303adbf342SMartin Blumenstingl /* 3313adbf342SMartin Blumenstingl * NOTE: we need a small delay before reading the status, otherwise 3323adbf342SMartin Blumenstingl * the sample engine may not have started internally (which would 3333adbf342SMartin Blumenstingl * seem to us that sampling is already finished). 3343adbf342SMartin Blumenstingl */ 3353adbf342SMartin Blumenstingl udelay(1); 33679b584edSAndy Shevchenko return regmap_read_poll_timeout_atomic(priv->regmap, MESON_SAR_ADC_REG0, val, 33779b584edSAndy Shevchenko !FIELD_GET(MESON_SAR_ADC_REG0_BUSY_MASK, val), 33879b584edSAndy Shevchenko 1, 10000); 3393adbf342SMartin Blumenstingl } 3403adbf342SMartin Blumenstingl 3413adbf342SMartin Blumenstingl static int meson_sar_adc_read_raw_sample(struct iio_dev *indio_dev, 3423adbf342SMartin Blumenstingl const struct iio_chan_spec *chan, 3433adbf342SMartin Blumenstingl int *val) 3443adbf342SMartin Blumenstingl { 3453adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 346d43c7006SAndy Shevchenko struct device *dev = indio_dev->dev.parent; 3476a882a2cSHeiner Kallweit int regval, fifo_chan, fifo_val, count; 3483adbf342SMartin Blumenstingl 3493af10913SHeiner Kallweit if (!wait_for_completion_timeout(&priv->done, 3503af10913SHeiner Kallweit msecs_to_jiffies(MESON_SAR_ADC_TIMEOUT))) 3513af10913SHeiner Kallweit return -ETIMEDOUT; 3523adbf342SMartin Blumenstingl 3536a882a2cSHeiner Kallweit count = meson_sar_adc_get_fifo_count(indio_dev); 3546a882a2cSHeiner Kallweit if (count != 1) { 355d43c7006SAndy Shevchenko dev_err(dev, "ADC FIFO has %d element(s) instead of one\n", count); 3566a882a2cSHeiner Kallweit return -EINVAL; 3573adbf342SMartin Blumenstingl } 3583adbf342SMartin Blumenstingl 3596a882a2cSHeiner Kallweit regmap_read(priv->regmap, MESON_SAR_ADC_FIFO_RD, ®val); 3606a882a2cSHeiner Kallweit fifo_chan = FIELD_GET(MESON_SAR_ADC_FIFO_RD_CHAN_ID_MASK, regval); 361827df057SMartin Blumenstingl if (fifo_chan != chan->address) { 362d43c7006SAndy Shevchenko dev_err(dev, "ADC FIFO entry belongs to channel %d instead of %lu\n", 363827df057SMartin Blumenstingl fifo_chan, chan->address); 3646a882a2cSHeiner Kallweit return -EINVAL; 3656a882a2cSHeiner Kallweit } 3663adbf342SMartin Blumenstingl 3676a882a2cSHeiner Kallweit fifo_val = FIELD_GET(MESON_SAR_ADC_FIFO_RD_SAMPLE_VALUE_MASK, regval); 368057e5a11SMartin Blumenstingl fifo_val &= GENMASK(priv->param->resolution - 1, 0); 36948ba7c3cSHeiner Kallweit *val = meson_sar_adc_calib_val(indio_dev, fifo_val); 3703adbf342SMartin Blumenstingl 3713adbf342SMartin Blumenstingl return 0; 3723adbf342SMartin Blumenstingl } 3733adbf342SMartin Blumenstingl 3743adbf342SMartin Blumenstingl static void meson_sar_adc_set_averaging(struct iio_dev *indio_dev, 3753adbf342SMartin Blumenstingl const struct iio_chan_spec *chan, 3763adbf342SMartin Blumenstingl enum meson_sar_adc_avg_mode mode, 3773adbf342SMartin Blumenstingl enum meson_sar_adc_num_samples samples) 3783adbf342SMartin Blumenstingl { 3793adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 380827df057SMartin Blumenstingl int val, address = chan->address; 3813adbf342SMartin Blumenstingl 382827df057SMartin Blumenstingl val = samples << MESON_SAR_ADC_AVG_CNTL_NUM_SAMPLES_SHIFT(address); 3833adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_AVG_CNTL, 384827df057SMartin Blumenstingl MESON_SAR_ADC_AVG_CNTL_NUM_SAMPLES_MASK(address), 3853adbf342SMartin Blumenstingl val); 3863adbf342SMartin Blumenstingl 387827df057SMartin Blumenstingl val = mode << MESON_SAR_ADC_AVG_CNTL_AVG_MODE_SHIFT(address); 3883adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_AVG_CNTL, 389827df057SMartin Blumenstingl MESON_SAR_ADC_AVG_CNTL_AVG_MODE_MASK(address), val); 3903adbf342SMartin Blumenstingl } 3913adbf342SMartin Blumenstingl 3923adbf342SMartin Blumenstingl static void meson_sar_adc_enable_channel(struct iio_dev *indio_dev, 3933adbf342SMartin Blumenstingl const struct iio_chan_spec *chan) 3943adbf342SMartin Blumenstingl { 3953adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 3963adbf342SMartin Blumenstingl u32 regval; 3973adbf342SMartin Blumenstingl 3983adbf342SMartin Blumenstingl /* 3993adbf342SMartin Blumenstingl * the SAR ADC engine allows sampling multiple channels at the same 4003adbf342SMartin Blumenstingl * time. to keep it simple we're only working with one *internal* 4013adbf342SMartin Blumenstingl * channel, which starts counting at index 0 (which means: count = 1). 4023adbf342SMartin Blumenstingl */ 4033adbf342SMartin Blumenstingl regval = FIELD_PREP(MESON_SAR_ADC_CHAN_LIST_MAX_INDEX_MASK, 0); 4043adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_LIST, 4053adbf342SMartin Blumenstingl MESON_SAR_ADC_CHAN_LIST_MAX_INDEX_MASK, regval); 4063adbf342SMartin Blumenstingl 4073adbf342SMartin Blumenstingl /* map channel index 0 to the channel which we want to read */ 4083adbf342SMartin Blumenstingl regval = FIELD_PREP(MESON_SAR_ADC_CHAN_LIST_ENTRY_MASK(0), 409827df057SMartin Blumenstingl chan->address); 4103adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_LIST, 4113adbf342SMartin Blumenstingl MESON_SAR_ADC_CHAN_LIST_ENTRY_MASK(0), regval); 4123adbf342SMartin Blumenstingl 4133adbf342SMartin Blumenstingl regval = FIELD_PREP(MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_MUX_MASK, 414827df057SMartin Blumenstingl chan->address); 4153adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DETECT_IDLE_SW, 4163adbf342SMartin Blumenstingl MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_MUX_MASK, 4173adbf342SMartin Blumenstingl regval); 4183adbf342SMartin Blumenstingl 4193adbf342SMartin Blumenstingl regval = FIELD_PREP(MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_MUX_SEL_MASK, 420827df057SMartin Blumenstingl chan->address); 4213adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DETECT_IDLE_SW, 4223adbf342SMartin Blumenstingl MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_MUX_SEL_MASK, 4233adbf342SMartin Blumenstingl regval); 4243adbf342SMartin Blumenstingl 425723a61e0SMartin Blumenstingl if (chan->address == MESON_SAR_ADC_VOLTAGE_AND_TEMP_CHANNEL) { 426723a61e0SMartin Blumenstingl if (chan->type == IIO_TEMP) 427723a61e0SMartin Blumenstingl regval = MESON_SAR_ADC_DELTA_10_TEMP_SEL; 428723a61e0SMartin Blumenstingl else 429723a61e0SMartin Blumenstingl regval = 0; 430723a61e0SMartin Blumenstingl 431723a61e0SMartin Blumenstingl regmap_update_bits(priv->regmap, 432723a61e0SMartin Blumenstingl MESON_SAR_ADC_DELTA_10, 433723a61e0SMartin Blumenstingl MESON_SAR_ADC_DELTA_10_TEMP_SEL, regval); 434723a61e0SMartin Blumenstingl } 4353adbf342SMartin Blumenstingl } 4363adbf342SMartin Blumenstingl 4373adbf342SMartin Blumenstingl static void meson_sar_adc_set_chan7_mux(struct iio_dev *indio_dev, 4383adbf342SMartin Blumenstingl enum meson_sar_adc_chan7_mux_sel sel) 4393adbf342SMartin Blumenstingl { 4403adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 4413adbf342SMartin Blumenstingl u32 regval; 4423adbf342SMartin Blumenstingl 4433adbf342SMartin Blumenstingl regval = FIELD_PREP(MESON_SAR_ADC_REG3_CTRL_CHAN7_MUX_SEL_MASK, sel); 4443adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3, 4453adbf342SMartin Blumenstingl MESON_SAR_ADC_REG3_CTRL_CHAN7_MUX_SEL_MASK, regval); 4463adbf342SMartin Blumenstingl 4473adbf342SMartin Blumenstingl usleep_range(10, 20); 4483adbf342SMartin Blumenstingl } 4493adbf342SMartin Blumenstingl 4503adbf342SMartin Blumenstingl static void meson_sar_adc_start_sample_engine(struct iio_dev *indio_dev) 4513adbf342SMartin Blumenstingl { 4523adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 4533adbf342SMartin Blumenstingl 4543af10913SHeiner Kallweit reinit_completion(&priv->done); 4553af10913SHeiner Kallweit 4563af10913SHeiner Kallweit regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, 4573af10913SHeiner Kallweit MESON_SAR_ADC_REG0_FIFO_IRQ_EN, 4583af10913SHeiner Kallweit MESON_SAR_ADC_REG0_FIFO_IRQ_EN); 4593af10913SHeiner Kallweit 4603adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, 4613adbf342SMartin Blumenstingl MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE, 4623adbf342SMartin Blumenstingl MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE); 4633adbf342SMartin Blumenstingl 4643adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, 4653adbf342SMartin Blumenstingl MESON_SAR_ADC_REG0_SAMPLING_START, 4663adbf342SMartin Blumenstingl MESON_SAR_ADC_REG0_SAMPLING_START); 4673adbf342SMartin Blumenstingl } 4683adbf342SMartin Blumenstingl 4693adbf342SMartin Blumenstingl static void meson_sar_adc_stop_sample_engine(struct iio_dev *indio_dev) 4703adbf342SMartin Blumenstingl { 4713adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 4723adbf342SMartin Blumenstingl 4733adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, 4743af10913SHeiner Kallweit MESON_SAR_ADC_REG0_FIFO_IRQ_EN, 0); 4753af10913SHeiner Kallweit 4763af10913SHeiner Kallweit regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, 4773adbf342SMartin Blumenstingl MESON_SAR_ADC_REG0_SAMPLING_STOP, 4783adbf342SMartin Blumenstingl MESON_SAR_ADC_REG0_SAMPLING_STOP); 4793adbf342SMartin Blumenstingl 4803adbf342SMartin Blumenstingl /* wait until all modules are stopped */ 4813adbf342SMartin Blumenstingl meson_sar_adc_wait_busy_clear(indio_dev); 4823adbf342SMartin Blumenstingl 4833adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, 4843adbf342SMartin Blumenstingl MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE, 0); 4853adbf342SMartin Blumenstingl } 4863adbf342SMartin Blumenstingl 4873adbf342SMartin Blumenstingl static int meson_sar_adc_lock(struct iio_dev *indio_dev) 4883adbf342SMartin Blumenstingl { 4893adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 49079b584edSAndy Shevchenko int val, ret; 4913adbf342SMartin Blumenstingl 492d0c09264SNuno Sá mutex_lock(&priv->lock); 4933adbf342SMartin Blumenstingl 494057e5a11SMartin Blumenstingl if (priv->param->has_bl30_integration) { 4953adbf342SMartin Blumenstingl /* prevent BL30 from using the SAR ADC while we are using it */ 4963adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY, 4973adbf342SMartin Blumenstingl MESON_SAR_ADC_DELAY_KERNEL_BUSY, 4983adbf342SMartin Blumenstingl MESON_SAR_ADC_DELAY_KERNEL_BUSY); 4993adbf342SMartin Blumenstingl 50079b584edSAndy Shevchenko udelay(1); 50179b584edSAndy Shevchenko 5026c76ed31SMartin Blumenstingl /* 5036c76ed31SMartin Blumenstingl * wait until BL30 releases it's lock (so we can use the SAR 5046c76ed31SMartin Blumenstingl * ADC) 5056c76ed31SMartin Blumenstingl */ 50679b584edSAndy Shevchenko ret = regmap_read_poll_timeout_atomic(priv->regmap, MESON_SAR_ADC_DELAY, val, 50779b584edSAndy Shevchenko !(val & MESON_SAR_ADC_DELAY_BL30_BUSY), 50879b584edSAndy Shevchenko 1, 10000); 50979b584edSAndy Shevchenko if (ret) { 510d0c09264SNuno Sá mutex_unlock(&priv->lock); 51179b584edSAndy Shevchenko return ret; 5126c76ed31SMartin Blumenstingl } 5133c3e4b3aSDan Carpenter } 5143adbf342SMartin Blumenstingl 5153adbf342SMartin Blumenstingl return 0; 5163adbf342SMartin Blumenstingl } 5173adbf342SMartin Blumenstingl 5183adbf342SMartin Blumenstingl static void meson_sar_adc_unlock(struct iio_dev *indio_dev) 5193adbf342SMartin Blumenstingl { 5203adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 5213adbf342SMartin Blumenstingl 522057e5a11SMartin Blumenstingl if (priv->param->has_bl30_integration) 5233adbf342SMartin Blumenstingl /* allow BL30 to use the SAR ADC again */ 5243adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY, 5253adbf342SMartin Blumenstingl MESON_SAR_ADC_DELAY_KERNEL_BUSY, 0); 5263adbf342SMartin Blumenstingl 527d0c09264SNuno Sá mutex_unlock(&priv->lock); 5283adbf342SMartin Blumenstingl } 5293adbf342SMartin Blumenstingl 5303adbf342SMartin Blumenstingl static void meson_sar_adc_clear_fifo(struct iio_dev *indio_dev) 5313adbf342SMartin Blumenstingl { 5323adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 533103a07d4SMartin Blumenstingl unsigned int count, tmp; 5343adbf342SMartin Blumenstingl 5353adbf342SMartin Blumenstingl for (count = 0; count < MESON_SAR_ADC_MAX_FIFO_SIZE; count++) { 5363adbf342SMartin Blumenstingl if (!meson_sar_adc_get_fifo_count(indio_dev)) 5373adbf342SMartin Blumenstingl break; 5383adbf342SMartin Blumenstingl 539103a07d4SMartin Blumenstingl regmap_read(priv->regmap, MESON_SAR_ADC_FIFO_RD, &tmp); 5403adbf342SMartin Blumenstingl } 5413adbf342SMartin Blumenstingl } 5423adbf342SMartin Blumenstingl 5433adbf342SMartin Blumenstingl static int meson_sar_adc_get_sample(struct iio_dev *indio_dev, 5443adbf342SMartin Blumenstingl const struct iio_chan_spec *chan, 5453adbf342SMartin Blumenstingl enum meson_sar_adc_avg_mode avg_mode, 5463adbf342SMartin Blumenstingl enum meson_sar_adc_num_samples avg_samples, 5473adbf342SMartin Blumenstingl int *val) 5483adbf342SMartin Blumenstingl { 549723a61e0SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 55022c26db4SAndy Shevchenko struct device *dev = indio_dev->dev.parent; 5513adbf342SMartin Blumenstingl int ret; 5523adbf342SMartin Blumenstingl 553723a61e0SMartin Blumenstingl if (chan->type == IIO_TEMP && !priv->temperature_sensor_calibrated) 554723a61e0SMartin Blumenstingl return -ENOTSUPP; 555723a61e0SMartin Blumenstingl 5563adbf342SMartin Blumenstingl ret = meson_sar_adc_lock(indio_dev); 5573adbf342SMartin Blumenstingl if (ret) 5583adbf342SMartin Blumenstingl return ret; 5593adbf342SMartin Blumenstingl 5603adbf342SMartin Blumenstingl /* clear the FIFO to make sure we're not reading old values */ 5613adbf342SMartin Blumenstingl meson_sar_adc_clear_fifo(indio_dev); 5623adbf342SMartin Blumenstingl 5633adbf342SMartin Blumenstingl meson_sar_adc_set_averaging(indio_dev, chan, avg_mode, avg_samples); 5643adbf342SMartin Blumenstingl 5653adbf342SMartin Blumenstingl meson_sar_adc_enable_channel(indio_dev, chan); 5663adbf342SMartin Blumenstingl 5673adbf342SMartin Blumenstingl meson_sar_adc_start_sample_engine(indio_dev); 5683adbf342SMartin Blumenstingl ret = meson_sar_adc_read_raw_sample(indio_dev, chan, val); 5693adbf342SMartin Blumenstingl meson_sar_adc_stop_sample_engine(indio_dev); 5703adbf342SMartin Blumenstingl 5713adbf342SMartin Blumenstingl meson_sar_adc_unlock(indio_dev); 5723adbf342SMartin Blumenstingl 5733adbf342SMartin Blumenstingl if (ret) { 57422c26db4SAndy Shevchenko dev_warn(dev, "failed to read sample for channel %lu: %d\n", 575827df057SMartin Blumenstingl chan->address, ret); 5763adbf342SMartin Blumenstingl return ret; 5773adbf342SMartin Blumenstingl } 5783adbf342SMartin Blumenstingl 5793adbf342SMartin Blumenstingl return IIO_VAL_INT; 5803adbf342SMartin Blumenstingl } 5813adbf342SMartin Blumenstingl 5823adbf342SMartin Blumenstingl static int meson_sar_adc_iio_info_read_raw(struct iio_dev *indio_dev, 5833adbf342SMartin Blumenstingl const struct iio_chan_spec *chan, 5843adbf342SMartin Blumenstingl int *val, int *val2, long mask) 5853adbf342SMartin Blumenstingl { 5863adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 58722c26db4SAndy Shevchenko struct device *dev = indio_dev->dev.parent; 5883adbf342SMartin Blumenstingl int ret; 5893adbf342SMartin Blumenstingl 5903adbf342SMartin Blumenstingl switch (mask) { 5913adbf342SMartin Blumenstingl case IIO_CHAN_INFO_RAW: 5923adbf342SMartin Blumenstingl return meson_sar_adc_get_sample(indio_dev, chan, NO_AVERAGING, 5933adbf342SMartin Blumenstingl ONE_SAMPLE, val); 5943adbf342SMartin Blumenstingl 5953adbf342SMartin Blumenstingl case IIO_CHAN_INFO_AVERAGE_RAW: 5963adbf342SMartin Blumenstingl return meson_sar_adc_get_sample(indio_dev, chan, 5973adbf342SMartin Blumenstingl MEAN_AVERAGING, EIGHT_SAMPLES, 5983adbf342SMartin Blumenstingl val); 5993adbf342SMartin Blumenstingl 6003adbf342SMartin Blumenstingl case IIO_CHAN_INFO_SCALE: 601723a61e0SMartin Blumenstingl if (chan->type == IIO_VOLTAGE) { 6023adbf342SMartin Blumenstingl ret = regulator_get_voltage(priv->vref); 6033adbf342SMartin Blumenstingl if (ret < 0) { 60422c26db4SAndy Shevchenko dev_err(dev, "failed to get vref voltage: %d\n", ret); 6053adbf342SMartin Blumenstingl return ret; 6063adbf342SMartin Blumenstingl } 6073adbf342SMartin Blumenstingl 6083adbf342SMartin Blumenstingl *val = ret / 1000; 609057e5a11SMartin Blumenstingl *val2 = priv->param->resolution; 6103adbf342SMartin Blumenstingl return IIO_VAL_FRACTIONAL_LOG2; 611723a61e0SMartin Blumenstingl } else if (chan->type == IIO_TEMP) { 612723a61e0SMartin Blumenstingl /* SoC specific multiplier and divider */ 613723a61e0SMartin Blumenstingl *val = priv->param->temperature_multiplier; 614723a61e0SMartin Blumenstingl *val2 = priv->param->temperature_divider; 615723a61e0SMartin Blumenstingl 616723a61e0SMartin Blumenstingl /* celsius to millicelsius */ 617723a61e0SMartin Blumenstingl *val *= 1000; 618723a61e0SMartin Blumenstingl 619723a61e0SMartin Blumenstingl return IIO_VAL_FRACTIONAL; 620723a61e0SMartin Blumenstingl } else { 621723a61e0SMartin Blumenstingl return -EINVAL; 622723a61e0SMartin Blumenstingl } 6233adbf342SMartin Blumenstingl 62448ba7c3cSHeiner Kallweit case IIO_CHAN_INFO_CALIBBIAS: 62548ba7c3cSHeiner Kallweit *val = priv->calibbias; 62648ba7c3cSHeiner Kallweit return IIO_VAL_INT; 62748ba7c3cSHeiner Kallweit 62848ba7c3cSHeiner Kallweit case IIO_CHAN_INFO_CALIBSCALE: 62948ba7c3cSHeiner Kallweit *val = priv->calibscale / MILLION; 63048ba7c3cSHeiner Kallweit *val2 = priv->calibscale % MILLION; 63148ba7c3cSHeiner Kallweit return IIO_VAL_INT_PLUS_MICRO; 63248ba7c3cSHeiner Kallweit 633723a61e0SMartin Blumenstingl case IIO_CHAN_INFO_OFFSET: 634723a61e0SMartin Blumenstingl *val = DIV_ROUND_CLOSEST(MESON_SAR_ADC_TEMP_OFFSET * 635723a61e0SMartin Blumenstingl priv->param->temperature_divider, 636723a61e0SMartin Blumenstingl priv->param->temperature_multiplier); 637723a61e0SMartin Blumenstingl *val -= priv->temperature_sensor_adc_val; 638723a61e0SMartin Blumenstingl return IIO_VAL_INT; 639723a61e0SMartin Blumenstingl 6403adbf342SMartin Blumenstingl default: 6413adbf342SMartin Blumenstingl return -EINVAL; 6423adbf342SMartin Blumenstingl } 6433adbf342SMartin Blumenstingl } 6443adbf342SMartin Blumenstingl 6453adbf342SMartin Blumenstingl static int meson_sar_adc_clk_init(struct iio_dev *indio_dev, 6463adbf342SMartin Blumenstingl void __iomem *base) 6473adbf342SMartin Blumenstingl { 6483adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 649ec25bb6eSAndy Shevchenko struct device *dev = indio_dev->dev.parent; 6503adbf342SMartin Blumenstingl struct clk_init_data init; 6513adbf342SMartin Blumenstingl const char *clk_parents[1]; 6523adbf342SMartin Blumenstingl 653ec25bb6eSAndy Shevchenko init.name = devm_kasprintf(dev, GFP_KERNEL, "%s#adc_div", dev_name(dev)); 654aad172b0SNicholas Mc Guire if (!init.name) 655aad172b0SNicholas Mc Guire return -ENOMEM; 656aad172b0SNicholas Mc Guire 6573adbf342SMartin Blumenstingl init.flags = 0; 6583adbf342SMartin Blumenstingl init.ops = &clk_divider_ops; 6593adbf342SMartin Blumenstingl clk_parents[0] = __clk_get_name(priv->clkin); 6603adbf342SMartin Blumenstingl init.parent_names = clk_parents; 6613adbf342SMartin Blumenstingl init.num_parents = 1; 6623adbf342SMartin Blumenstingl 6633adbf342SMartin Blumenstingl priv->clk_div.reg = base + MESON_SAR_ADC_REG3; 6643adbf342SMartin Blumenstingl priv->clk_div.shift = MESON_SAR_ADC_REG3_ADC_CLK_DIV_SHIFT; 6653adbf342SMartin Blumenstingl priv->clk_div.width = MESON_SAR_ADC_REG3_ADC_CLK_DIV_WIDTH; 6663adbf342SMartin Blumenstingl priv->clk_div.hw.init = &init; 6673adbf342SMartin Blumenstingl priv->clk_div.flags = 0; 6683adbf342SMartin Blumenstingl 669ec25bb6eSAndy Shevchenko priv->adc_div_clk = devm_clk_register(dev, &priv->clk_div.hw); 6703adbf342SMartin Blumenstingl if (WARN_ON(IS_ERR(priv->adc_div_clk))) 6713adbf342SMartin Blumenstingl return PTR_ERR(priv->adc_div_clk); 6723adbf342SMartin Blumenstingl 673ec25bb6eSAndy Shevchenko init.name = devm_kasprintf(dev, GFP_KERNEL, "%s#adc_en", dev_name(dev)); 674aad172b0SNicholas Mc Guire if (!init.name) 675aad172b0SNicholas Mc Guire return -ENOMEM; 676aad172b0SNicholas Mc Guire 6773adbf342SMartin Blumenstingl init.flags = CLK_SET_RATE_PARENT; 6783adbf342SMartin Blumenstingl init.ops = &clk_gate_ops; 6793adbf342SMartin Blumenstingl clk_parents[0] = __clk_get_name(priv->adc_div_clk); 6803adbf342SMartin Blumenstingl init.parent_names = clk_parents; 6813adbf342SMartin Blumenstingl init.num_parents = 1; 6823adbf342SMartin Blumenstingl 6833adbf342SMartin Blumenstingl priv->clk_gate.reg = base + MESON_SAR_ADC_REG3; 6847a6b0420SMartin Blumenstingl priv->clk_gate.bit_idx = __ffs(MESON_SAR_ADC_REG3_CLK_EN); 6853adbf342SMartin Blumenstingl priv->clk_gate.hw.init = &init; 6863adbf342SMartin Blumenstingl 687ec25bb6eSAndy Shevchenko priv->adc_clk = devm_clk_register(dev, &priv->clk_gate.hw); 6883adbf342SMartin Blumenstingl if (WARN_ON(IS_ERR(priv->adc_clk))) 6893adbf342SMartin Blumenstingl return PTR_ERR(priv->adc_clk); 6903adbf342SMartin Blumenstingl 6913adbf342SMartin Blumenstingl return 0; 6923adbf342SMartin Blumenstingl } 6933adbf342SMartin Blumenstingl 694723a61e0SMartin Blumenstingl static int meson_sar_adc_temp_sensor_init(struct iio_dev *indio_dev) 695723a61e0SMartin Blumenstingl { 696723a61e0SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 697723a61e0SMartin Blumenstingl u8 *buf, trimming_bits, trimming_mask, upper_adc_val; 6982d27a021SAndy Shevchenko struct device *dev = indio_dev->dev.parent; 699723a61e0SMartin Blumenstingl struct nvmem_cell *temperature_calib; 700723a61e0SMartin Blumenstingl size_t read_len; 701723a61e0SMartin Blumenstingl int ret; 702723a61e0SMartin Blumenstingl 70322c26db4SAndy Shevchenko temperature_calib = devm_nvmem_cell_get(dev, "temperature_calib"); 704723a61e0SMartin Blumenstingl if (IS_ERR(temperature_calib)) { 705723a61e0SMartin Blumenstingl ret = PTR_ERR(temperature_calib); 706723a61e0SMartin Blumenstingl 707723a61e0SMartin Blumenstingl /* 708723a61e0SMartin Blumenstingl * leave the temperature sensor disabled if no calibration data 709723a61e0SMartin Blumenstingl * was passed via nvmem-cells. 710723a61e0SMartin Blumenstingl */ 711723a61e0SMartin Blumenstingl if (ret == -ENODEV) 712723a61e0SMartin Blumenstingl return 0; 713723a61e0SMartin Blumenstingl 7142d27a021SAndy Shevchenko return dev_err_probe(dev, ret, "failed to get temperature_calib cell\n"); 715723a61e0SMartin Blumenstingl } 716723a61e0SMartin Blumenstingl 71722c26db4SAndy Shevchenko priv->tsc_regmap = syscon_regmap_lookup_by_phandle(dev->of_node, "amlogic,hhi-sysctrl"); 7182d27a021SAndy Shevchenko if (IS_ERR(priv->tsc_regmap)) 7192d27a021SAndy Shevchenko return dev_err_probe(dev, PTR_ERR(priv->tsc_regmap), 720b002bf5fSMartin Blumenstingl "failed to get amlogic,hhi-sysctrl regmap\n"); 721b002bf5fSMartin Blumenstingl 722723a61e0SMartin Blumenstingl read_len = MESON_SAR_ADC_EFUSE_BYTES; 723723a61e0SMartin Blumenstingl buf = nvmem_cell_read(temperature_calib, &read_len); 7242d27a021SAndy Shevchenko if (IS_ERR(buf)) 7252d27a021SAndy Shevchenko return dev_err_probe(dev, PTR_ERR(buf), "failed to read temperature_calib cell\n"); 7262d27a021SAndy Shevchenko if (read_len != MESON_SAR_ADC_EFUSE_BYTES) { 727723a61e0SMartin Blumenstingl kfree(buf); 7282d27a021SAndy Shevchenko return dev_err_probe(dev, -EINVAL, "invalid read size of temperature_calib cell\n"); 729723a61e0SMartin Blumenstingl } 730723a61e0SMartin Blumenstingl 731723a61e0SMartin Blumenstingl trimming_bits = priv->param->temperature_trimming_bits; 732723a61e0SMartin Blumenstingl trimming_mask = BIT(trimming_bits) - 1; 733723a61e0SMartin Blumenstingl 734723a61e0SMartin Blumenstingl priv->temperature_sensor_calibrated = 735723a61e0SMartin Blumenstingl buf[3] & MESON_SAR_ADC_EFUSE_BYTE3_IS_CALIBRATED; 736723a61e0SMartin Blumenstingl priv->temperature_sensor_coefficient = buf[2] & trimming_mask; 737723a61e0SMartin Blumenstingl 738723a61e0SMartin Blumenstingl upper_adc_val = FIELD_GET(MESON_SAR_ADC_EFUSE_BYTE3_UPPER_ADC_VAL, 739723a61e0SMartin Blumenstingl buf[3]); 740723a61e0SMartin Blumenstingl 741723a61e0SMartin Blumenstingl priv->temperature_sensor_adc_val = buf[2]; 742723a61e0SMartin Blumenstingl priv->temperature_sensor_adc_val |= upper_adc_val << BITS_PER_BYTE; 743723a61e0SMartin Blumenstingl priv->temperature_sensor_adc_val >>= trimming_bits; 744723a61e0SMartin Blumenstingl 745723a61e0SMartin Blumenstingl kfree(buf); 746723a61e0SMartin Blumenstingl 747723a61e0SMartin Blumenstingl return 0; 748723a61e0SMartin Blumenstingl } 749723a61e0SMartin Blumenstingl 7503adbf342SMartin Blumenstingl static int meson_sar_adc_init(struct iio_dev *indio_dev) 7513adbf342SMartin Blumenstingl { 7523adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 7532d27a021SAndy Shevchenko struct device *dev = indio_dev->dev.parent; 754ab569a4cSMartin Blumenstingl int regval, i, ret; 7553adbf342SMartin Blumenstingl 7563adbf342SMartin Blumenstingl /* 7573adbf342SMartin Blumenstingl * make sure we start at CH7 input since the other muxes are only used 7583adbf342SMartin Blumenstingl * for internal calibration. 7593adbf342SMartin Blumenstingl */ 7603adbf342SMartin Blumenstingl meson_sar_adc_set_chan7_mux(indio_dev, CHAN7_MUX_CH7_INPUT); 7613adbf342SMartin Blumenstingl 762057e5a11SMartin Blumenstingl if (priv->param->has_bl30_integration) { 7633adbf342SMartin Blumenstingl /* 7646c76ed31SMartin Blumenstingl * leave sampling delay and the input clocks as configured by 7656c76ed31SMartin Blumenstingl * BL30 to make sure BL30 gets the values it expects when 7666c76ed31SMartin Blumenstingl * reading the temperature sensor. 7673adbf342SMartin Blumenstingl */ 7683adbf342SMartin Blumenstingl regmap_read(priv->regmap, MESON_SAR_ADC_REG3, ®val); 7693adbf342SMartin Blumenstingl if (regval & MESON_SAR_ADC_REG3_BL30_INITIALIZED) 7703adbf342SMartin Blumenstingl return 0; 7716c76ed31SMartin Blumenstingl } 7723adbf342SMartin Blumenstingl 7733adbf342SMartin Blumenstingl meson_sar_adc_stop_sample_engine(indio_dev); 7743adbf342SMartin Blumenstingl 775723a61e0SMartin Blumenstingl /* 776723a61e0SMartin Blumenstingl * disable this bit as seems to be only relevant for Meson6 (based 777723a61e0SMartin Blumenstingl * on the vendor driver), which we don't support at the moment. 778723a61e0SMartin Blumenstingl */ 7793adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, 780723a61e0SMartin Blumenstingl MESON_SAR_ADC_REG0_ADC_TEMP_SEN_SEL, 0); 7813adbf342SMartin Blumenstingl 7823adbf342SMartin Blumenstingl /* disable all channels by default */ 7833adbf342SMartin Blumenstingl regmap_write(priv->regmap, MESON_SAR_ADC_CHAN_LIST, 0x0); 7843adbf342SMartin Blumenstingl 7853adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3, 7863adbf342SMartin Blumenstingl MESON_SAR_ADC_REG3_CTRL_SAMPLING_CLOCK_PHASE, 0); 7873adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3, 7883adbf342SMartin Blumenstingl MESON_SAR_ADC_REG3_CNTL_USE_SC_DLY, 7893adbf342SMartin Blumenstingl MESON_SAR_ADC_REG3_CNTL_USE_SC_DLY); 7903adbf342SMartin Blumenstingl 7913adbf342SMartin Blumenstingl /* delay between two samples = (10+1) * 1uS */ 7923adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY, 7933adbf342SMartin Blumenstingl MESON_SAR_ADC_DELAY_INPUT_DLY_CNT_MASK, 7943adbf342SMartin Blumenstingl FIELD_PREP(MESON_SAR_ADC_DELAY_SAMPLE_DLY_CNT_MASK, 7953adbf342SMartin Blumenstingl 10)); 7963adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY, 7973adbf342SMartin Blumenstingl MESON_SAR_ADC_DELAY_SAMPLE_DLY_SEL_MASK, 7983adbf342SMartin Blumenstingl FIELD_PREP(MESON_SAR_ADC_DELAY_SAMPLE_DLY_SEL_MASK, 7993adbf342SMartin Blumenstingl 0)); 8003adbf342SMartin Blumenstingl 8013adbf342SMartin Blumenstingl /* delay between two samples = (10+1) * 1uS */ 8023adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY, 8033adbf342SMartin Blumenstingl MESON_SAR_ADC_DELAY_INPUT_DLY_CNT_MASK, 8043adbf342SMartin Blumenstingl FIELD_PREP(MESON_SAR_ADC_DELAY_INPUT_DLY_CNT_MASK, 8053adbf342SMartin Blumenstingl 10)); 8063adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY, 8073adbf342SMartin Blumenstingl MESON_SAR_ADC_DELAY_INPUT_DLY_SEL_MASK, 8083adbf342SMartin Blumenstingl FIELD_PREP(MESON_SAR_ADC_DELAY_INPUT_DLY_SEL_MASK, 8093adbf342SMartin Blumenstingl 1)); 8103adbf342SMartin Blumenstingl 811ab569a4cSMartin Blumenstingl /* 812ab569a4cSMartin Blumenstingl * set up the input channel muxes in MESON_SAR_ADC_CHAN_10_SW 813ab569a4cSMartin Blumenstingl * (0 = SAR_ADC_CH0, 1 = SAR_ADC_CH1) 814ab569a4cSMartin Blumenstingl */ 815ab569a4cSMartin Blumenstingl regval = FIELD_PREP(MESON_SAR_ADC_CHAN_10_SW_CHAN0_MUX_SEL_MASK, 0); 816ab569a4cSMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_10_SW, 817ab569a4cSMartin Blumenstingl MESON_SAR_ADC_CHAN_10_SW_CHAN0_MUX_SEL_MASK, 818ab569a4cSMartin Blumenstingl regval); 819ab569a4cSMartin Blumenstingl regval = FIELD_PREP(MESON_SAR_ADC_CHAN_10_SW_CHAN1_MUX_SEL_MASK, 1); 820ab569a4cSMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_10_SW, 821ab569a4cSMartin Blumenstingl MESON_SAR_ADC_CHAN_10_SW_CHAN1_MUX_SEL_MASK, 822ab569a4cSMartin Blumenstingl regval); 823ab569a4cSMartin Blumenstingl 824ab569a4cSMartin Blumenstingl /* 825ab569a4cSMartin Blumenstingl * set up the input channel muxes in MESON_SAR_ADC_AUX_SW 826ab569a4cSMartin Blumenstingl * (2 = SAR_ADC_CH2, 3 = SAR_ADC_CH3, ...) and enable 827ab569a4cSMartin Blumenstingl * MESON_SAR_ADC_AUX_SW_YP_DRIVE_SW and 828ab569a4cSMartin Blumenstingl * MESON_SAR_ADC_AUX_SW_XP_DRIVE_SW like the vendor driver. 829ab569a4cSMartin Blumenstingl */ 830ab569a4cSMartin Blumenstingl regval = 0; 831ab569a4cSMartin Blumenstingl for (i = 2; i <= 7; i++) 832ab569a4cSMartin Blumenstingl regval |= i << MESON_SAR_ADC_AUX_SW_MUX_SEL_CHAN_SHIFT(i); 833ab569a4cSMartin Blumenstingl regval |= MESON_SAR_ADC_AUX_SW_YP_DRIVE_SW; 834ab569a4cSMartin Blumenstingl regval |= MESON_SAR_ADC_AUX_SW_XP_DRIVE_SW; 835ab569a4cSMartin Blumenstingl regmap_write(priv->regmap, MESON_SAR_ADC_AUX_SW, regval); 836ab569a4cSMartin Blumenstingl 837723a61e0SMartin Blumenstingl if (priv->temperature_sensor_calibrated) { 838723a61e0SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELTA_10, 839723a61e0SMartin Blumenstingl MESON_SAR_ADC_DELTA_10_TS_REVE1, 840723a61e0SMartin Blumenstingl MESON_SAR_ADC_DELTA_10_TS_REVE1); 841723a61e0SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELTA_10, 842723a61e0SMartin Blumenstingl MESON_SAR_ADC_DELTA_10_TS_REVE0, 843723a61e0SMartin Blumenstingl MESON_SAR_ADC_DELTA_10_TS_REVE0); 844723a61e0SMartin Blumenstingl 845723a61e0SMartin Blumenstingl /* 846723a61e0SMartin Blumenstingl * set bits [3:0] of the TSC (temperature sensor coefficient) 847723a61e0SMartin Blumenstingl * to get the correct values when reading the temperature. 848723a61e0SMartin Blumenstingl */ 849723a61e0SMartin Blumenstingl regval = FIELD_PREP(MESON_SAR_ADC_DELTA_10_TS_C_MASK, 850723a61e0SMartin Blumenstingl priv->temperature_sensor_coefficient); 851723a61e0SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELTA_10, 852723a61e0SMartin Blumenstingl MESON_SAR_ADC_DELTA_10_TS_C_MASK, regval); 853b002bf5fSMartin Blumenstingl 854b002bf5fSMartin Blumenstingl if (priv->param->temperature_trimming_bits == 5) { 855b002bf5fSMartin Blumenstingl if (priv->temperature_sensor_coefficient & BIT(4)) 856b002bf5fSMartin Blumenstingl regval = MESON_HHI_DPLL_TOP_0_TSC_BIT4; 857b002bf5fSMartin Blumenstingl else 858b002bf5fSMartin Blumenstingl regval = 0; 859b002bf5fSMartin Blumenstingl 860b002bf5fSMartin Blumenstingl /* 861b002bf5fSMartin Blumenstingl * bit [4] (the 5th bit when starting to count at 1) 862b002bf5fSMartin Blumenstingl * of the TSC is located in the HHI register area. 863b002bf5fSMartin Blumenstingl */ 864b002bf5fSMartin Blumenstingl regmap_update_bits(priv->tsc_regmap, 865b002bf5fSMartin Blumenstingl MESON_HHI_DPLL_TOP_0, 866b002bf5fSMartin Blumenstingl MESON_HHI_DPLL_TOP_0_TSC_BIT4, 867b002bf5fSMartin Blumenstingl regval); 868b002bf5fSMartin Blumenstingl } 869723a61e0SMartin Blumenstingl } else { 870723a61e0SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELTA_10, 871723a61e0SMartin Blumenstingl MESON_SAR_ADC_DELTA_10_TS_REVE1, 0); 872723a61e0SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELTA_10, 873723a61e0SMartin Blumenstingl MESON_SAR_ADC_DELTA_10_TS_REVE0, 0); 874723a61e0SMartin Blumenstingl } 875723a61e0SMartin Blumenstingl 8763adbf342SMartin Blumenstingl ret = clk_set_parent(priv->adc_sel_clk, priv->clkin); 8772d27a021SAndy Shevchenko if (ret) 8782d27a021SAndy Shevchenko return dev_err_probe(dev, ret, "failed to set adc parent to clkin\n"); 8793adbf342SMartin Blumenstingl 880057e5a11SMartin Blumenstingl ret = clk_set_rate(priv->adc_clk, priv->param->clock_rate); 8812d27a021SAndy Shevchenko if (ret) 8822d27a021SAndy Shevchenko return dev_err_probe(dev, ret, "failed to set adc clock rate\n"); 8833adbf342SMartin Blumenstingl 8843adbf342SMartin Blumenstingl return 0; 8853adbf342SMartin Blumenstingl } 8863adbf342SMartin Blumenstingl 887d85eed9fSMartin Blumenstingl static void meson_sar_adc_set_bandgap(struct iio_dev *indio_dev, bool on_off) 888d85eed9fSMartin Blumenstingl { 889d85eed9fSMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 890057e5a11SMartin Blumenstingl const struct meson_sar_adc_param *param = priv->param; 891d85eed9fSMartin Blumenstingl u32 enable_mask; 892d85eed9fSMartin Blumenstingl 893053ffe3cSYixun Lan if (param->bandgap_reg == MESON_SAR_ADC_REG11) 894d85eed9fSMartin Blumenstingl enable_mask = MESON_SAR_ADC_REG11_BANDGAP_EN; 895d85eed9fSMartin Blumenstingl else 896d85eed9fSMartin Blumenstingl enable_mask = MESON_SAR_ADC_DELTA_10_TS_VBG_EN; 897d85eed9fSMartin Blumenstingl 898053ffe3cSYixun Lan regmap_update_bits(priv->regmap, param->bandgap_reg, enable_mask, 899d85eed9fSMartin Blumenstingl on_off ? enable_mask : 0); 900d85eed9fSMartin Blumenstingl } 901d85eed9fSMartin Blumenstingl 9023adbf342SMartin Blumenstingl static int meson_sar_adc_hw_enable(struct iio_dev *indio_dev) 9033adbf342SMartin Blumenstingl { 9043adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 90522c26db4SAndy Shevchenko struct device *dev = indio_dev->dev.parent; 9063adbf342SMartin Blumenstingl int ret; 9073af10913SHeiner Kallweit u32 regval; 9083adbf342SMartin Blumenstingl 9093adbf342SMartin Blumenstingl ret = meson_sar_adc_lock(indio_dev); 9103adbf342SMartin Blumenstingl if (ret) 9113adbf342SMartin Blumenstingl goto err_lock; 9123adbf342SMartin Blumenstingl 9133adbf342SMartin Blumenstingl ret = regulator_enable(priv->vref); 9143adbf342SMartin Blumenstingl if (ret < 0) { 91522c26db4SAndy Shevchenko dev_err(dev, "failed to enable vref regulator\n"); 9163adbf342SMartin Blumenstingl goto err_vref; 9173adbf342SMartin Blumenstingl } 9183adbf342SMartin Blumenstingl 9193adbf342SMartin Blumenstingl ret = clk_prepare_enable(priv->core_clk); 9203adbf342SMartin Blumenstingl if (ret) { 92122c26db4SAndy Shevchenko dev_err(dev, "failed to enable core clk\n"); 9223adbf342SMartin Blumenstingl goto err_core_clk; 9233adbf342SMartin Blumenstingl } 9243adbf342SMartin Blumenstingl 9253af10913SHeiner Kallweit regval = FIELD_PREP(MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, 1); 9263af10913SHeiner Kallweit regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, 9273af10913SHeiner Kallweit MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, regval); 928d85eed9fSMartin Blumenstingl 929d85eed9fSMartin Blumenstingl meson_sar_adc_set_bandgap(indio_dev, true); 930d85eed9fSMartin Blumenstingl 9313adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3, 9323adbf342SMartin Blumenstingl MESON_SAR_ADC_REG3_ADC_EN, 9333adbf342SMartin Blumenstingl MESON_SAR_ADC_REG3_ADC_EN); 9343adbf342SMartin Blumenstingl 9353adbf342SMartin Blumenstingl udelay(5); 9363adbf342SMartin Blumenstingl 9373adbf342SMartin Blumenstingl ret = clk_prepare_enable(priv->adc_clk); 9383adbf342SMartin Blumenstingl if (ret) { 93922c26db4SAndy Shevchenko dev_err(dev, "failed to enable adc clk\n"); 9403adbf342SMartin Blumenstingl goto err_adc_clk; 9413adbf342SMartin Blumenstingl } 9423adbf342SMartin Blumenstingl 9433adbf342SMartin Blumenstingl meson_sar_adc_unlock(indio_dev); 9443adbf342SMartin Blumenstingl 9453adbf342SMartin Blumenstingl return 0; 9463adbf342SMartin Blumenstingl 9473adbf342SMartin Blumenstingl err_adc_clk: 9483adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3, 9493adbf342SMartin Blumenstingl MESON_SAR_ADC_REG3_ADC_EN, 0); 950d85eed9fSMartin Blumenstingl meson_sar_adc_set_bandgap(indio_dev, false); 9513adbf342SMartin Blumenstingl clk_disable_unprepare(priv->core_clk); 9523adbf342SMartin Blumenstingl err_core_clk: 9533adbf342SMartin Blumenstingl regulator_disable(priv->vref); 9543adbf342SMartin Blumenstingl err_vref: 9553adbf342SMartin Blumenstingl meson_sar_adc_unlock(indio_dev); 9563adbf342SMartin Blumenstingl err_lock: 9573adbf342SMartin Blumenstingl return ret; 9583adbf342SMartin Blumenstingl } 9593adbf342SMartin Blumenstingl 960*4ab8bef1SUwe Kleine-König static void meson_sar_adc_hw_disable(struct iio_dev *indio_dev) 9613adbf342SMartin Blumenstingl { 9623adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 9633adbf342SMartin Blumenstingl int ret; 9643adbf342SMartin Blumenstingl 965*4ab8bef1SUwe Kleine-König /* 966*4ab8bef1SUwe Kleine-König * If taking the lock fails we have to assume that BL30 is broken. The 967*4ab8bef1SUwe Kleine-König * best we can do then is to release the resources anyhow. 968*4ab8bef1SUwe Kleine-König */ 9693adbf342SMartin Blumenstingl ret = meson_sar_adc_lock(indio_dev); 9703adbf342SMartin Blumenstingl if (ret) 971*4ab8bef1SUwe Kleine-König dev_err(indio_dev->dev.parent, "Failed to lock ADC (%pE)\n", ERR_PTR(ret)); 9723adbf342SMartin Blumenstingl 9733adbf342SMartin Blumenstingl clk_disable_unprepare(priv->adc_clk); 9743adbf342SMartin Blumenstingl 9753adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3, 9763adbf342SMartin Blumenstingl MESON_SAR_ADC_REG3_ADC_EN, 0); 977d85eed9fSMartin Blumenstingl 978d85eed9fSMartin Blumenstingl meson_sar_adc_set_bandgap(indio_dev, false); 9793adbf342SMartin Blumenstingl 9803adbf342SMartin Blumenstingl clk_disable_unprepare(priv->core_clk); 9813adbf342SMartin Blumenstingl 9823adbf342SMartin Blumenstingl regulator_disable(priv->vref); 9833adbf342SMartin Blumenstingl 984*4ab8bef1SUwe Kleine-König if (!ret) 9853adbf342SMartin Blumenstingl meson_sar_adc_unlock(indio_dev); 9863adbf342SMartin Blumenstingl } 9873adbf342SMartin Blumenstingl 9883af10913SHeiner Kallweit static irqreturn_t meson_sar_adc_irq(int irq, void *data) 9893af10913SHeiner Kallweit { 9903af10913SHeiner Kallweit struct iio_dev *indio_dev = data; 9913af10913SHeiner Kallweit struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 9923af10913SHeiner Kallweit unsigned int cnt, threshold; 9933af10913SHeiner Kallweit u32 regval; 9943af10913SHeiner Kallweit 9953af10913SHeiner Kallweit regmap_read(priv->regmap, MESON_SAR_ADC_REG0, ®val); 9963af10913SHeiner Kallweit cnt = FIELD_GET(MESON_SAR_ADC_REG0_FIFO_COUNT_MASK, regval); 9973af10913SHeiner Kallweit threshold = FIELD_GET(MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, regval); 9983af10913SHeiner Kallweit 9993af10913SHeiner Kallweit if (cnt < threshold) 10003af10913SHeiner Kallweit return IRQ_NONE; 10013af10913SHeiner Kallweit 10023af10913SHeiner Kallweit complete(&priv->done); 10033af10913SHeiner Kallweit 10043af10913SHeiner Kallweit return IRQ_HANDLED; 10053af10913SHeiner Kallweit } 10063af10913SHeiner Kallweit 100748ba7c3cSHeiner Kallweit static int meson_sar_adc_calib(struct iio_dev *indio_dev) 100848ba7c3cSHeiner Kallweit { 100948ba7c3cSHeiner Kallweit struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 101048ba7c3cSHeiner Kallweit int ret, nominal0, nominal1, value0, value1; 101148ba7c3cSHeiner Kallweit 101248ba7c3cSHeiner Kallweit /* use points 25% and 75% for calibration */ 1013057e5a11SMartin Blumenstingl nominal0 = (1 << priv->param->resolution) / 4; 1014057e5a11SMartin Blumenstingl nominal1 = (1 << priv->param->resolution) * 3 / 4; 101548ba7c3cSHeiner Kallweit 101648ba7c3cSHeiner Kallweit meson_sar_adc_set_chan7_mux(indio_dev, CHAN7_MUX_VDD_DIV4); 101748ba7c3cSHeiner Kallweit usleep_range(10, 20); 101848ba7c3cSHeiner Kallweit ret = meson_sar_adc_get_sample(indio_dev, 1019bdd4b07fSMartin Blumenstingl &indio_dev->channels[7], 102048ba7c3cSHeiner Kallweit MEAN_AVERAGING, EIGHT_SAMPLES, &value0); 102148ba7c3cSHeiner Kallweit if (ret < 0) 102248ba7c3cSHeiner Kallweit goto out; 102348ba7c3cSHeiner Kallweit 102448ba7c3cSHeiner Kallweit meson_sar_adc_set_chan7_mux(indio_dev, CHAN7_MUX_VDD_MUL3_DIV4); 102548ba7c3cSHeiner Kallweit usleep_range(10, 20); 102648ba7c3cSHeiner Kallweit ret = meson_sar_adc_get_sample(indio_dev, 1027bdd4b07fSMartin Blumenstingl &indio_dev->channels[7], 102848ba7c3cSHeiner Kallweit MEAN_AVERAGING, EIGHT_SAMPLES, &value1); 102948ba7c3cSHeiner Kallweit if (ret < 0) 103048ba7c3cSHeiner Kallweit goto out; 103148ba7c3cSHeiner Kallweit 103248ba7c3cSHeiner Kallweit if (value1 <= value0) { 103348ba7c3cSHeiner Kallweit ret = -EINVAL; 103448ba7c3cSHeiner Kallweit goto out; 103548ba7c3cSHeiner Kallweit } 103648ba7c3cSHeiner Kallweit 103748ba7c3cSHeiner Kallweit priv->calibscale = div_s64((nominal1 - nominal0) * (s64)MILLION, 103848ba7c3cSHeiner Kallweit value1 - value0); 103948ba7c3cSHeiner Kallweit priv->calibbias = nominal0 - div_s64((s64)value0 * priv->calibscale, 104048ba7c3cSHeiner Kallweit MILLION); 104148ba7c3cSHeiner Kallweit ret = 0; 104248ba7c3cSHeiner Kallweit out: 104348ba7c3cSHeiner Kallweit meson_sar_adc_set_chan7_mux(indio_dev, CHAN7_MUX_CH7_INPUT); 104448ba7c3cSHeiner Kallweit 104548ba7c3cSHeiner Kallweit return ret; 104648ba7c3cSHeiner Kallweit } 104748ba7c3cSHeiner Kallweit 10483adbf342SMartin Blumenstingl static const struct iio_info meson_sar_adc_iio_info = { 10493adbf342SMartin Blumenstingl .read_raw = meson_sar_adc_iio_info_read_raw, 10503adbf342SMartin Blumenstingl }; 10513adbf342SMartin Blumenstingl 1052053ffe3cSYixun Lan static const struct meson_sar_adc_param meson_sar_adc_meson8_param = { 10536c76ed31SMartin Blumenstingl .has_bl30_integration = false, 1054fda29dbaSMartin Blumenstingl .clock_rate = 1150000, 1055d85eed9fSMartin Blumenstingl .bandgap_reg = MESON_SAR_ADC_DELTA_10, 105696748823SMartin Blumenstingl .regmap_config = &meson_sar_adc_regmap_config_meson8, 10576c76ed31SMartin Blumenstingl .resolution = 10, 1058723a61e0SMartin Blumenstingl .temperature_trimming_bits = 4, 1059723a61e0SMartin Blumenstingl .temperature_multiplier = 18 * 10000, 1060723a61e0SMartin Blumenstingl .temperature_divider = 1024 * 10 * 85, 1061723a61e0SMartin Blumenstingl }; 1062723a61e0SMartin Blumenstingl 1063723a61e0SMartin Blumenstingl static const struct meson_sar_adc_param meson_sar_adc_meson8b_param = { 1064723a61e0SMartin Blumenstingl .has_bl30_integration = false, 1065723a61e0SMartin Blumenstingl .clock_rate = 1150000, 1066723a61e0SMartin Blumenstingl .bandgap_reg = MESON_SAR_ADC_DELTA_10, 1067723a61e0SMartin Blumenstingl .regmap_config = &meson_sar_adc_regmap_config_meson8, 1068723a61e0SMartin Blumenstingl .resolution = 10, 1069b002bf5fSMartin Blumenstingl .temperature_trimming_bits = 5, 1070b002bf5fSMartin Blumenstingl .temperature_multiplier = 10, 1071b002bf5fSMartin Blumenstingl .temperature_divider = 32, 1072053ffe3cSYixun Lan }; 1073053ffe3cSYixun Lan 1074053ffe3cSYixun Lan static const struct meson_sar_adc_param meson_sar_adc_gxbb_param = { 1075053ffe3cSYixun Lan .has_bl30_integration = true, 1076053ffe3cSYixun Lan .clock_rate = 1200000, 1077053ffe3cSYixun Lan .bandgap_reg = MESON_SAR_ADC_REG11, 1078053ffe3cSYixun Lan .regmap_config = &meson_sar_adc_regmap_config_gxbb, 1079053ffe3cSYixun Lan .resolution = 10, 1080053ffe3cSYixun Lan }; 1081053ffe3cSYixun Lan 1082053ffe3cSYixun Lan static const struct meson_sar_adc_param meson_sar_adc_gxl_param = { 1083053ffe3cSYixun Lan .has_bl30_integration = true, 1084053ffe3cSYixun Lan .clock_rate = 1200000, 1085053ffe3cSYixun Lan .bandgap_reg = MESON_SAR_ADC_REG11, 1086053ffe3cSYixun Lan .regmap_config = &meson_sar_adc_regmap_config_gxbb, 1087053ffe3cSYixun Lan .resolution = 12, 1088053ffe3cSYixun Lan }; 1089053ffe3cSYixun Lan 109048dc1abdSMartin Blumenstingl static const struct meson_sar_adc_param meson_sar_adc_g12a_param = { 109148dc1abdSMartin Blumenstingl .has_bl30_integration = false, 109248dc1abdSMartin Blumenstingl .clock_rate = 1200000, 109348dc1abdSMartin Blumenstingl .bandgap_reg = MESON_SAR_ADC_REG11, 109448dc1abdSMartin Blumenstingl .regmap_config = &meson_sar_adc_regmap_config_gxbb, 109548dc1abdSMartin Blumenstingl .resolution = 12, 109648dc1abdSMartin Blumenstingl }; 109748dc1abdSMartin Blumenstingl 1098053ffe3cSYixun Lan static const struct meson_sar_adc_data meson_sar_adc_meson8_data = { 1099053ffe3cSYixun Lan .param = &meson_sar_adc_meson8_param, 11006c76ed31SMartin Blumenstingl .name = "meson-meson8-saradc", 11016c76ed31SMartin Blumenstingl }; 11026c76ed31SMartin Blumenstingl 11036c76ed31SMartin Blumenstingl static const struct meson_sar_adc_data meson_sar_adc_meson8b_data = { 1104723a61e0SMartin Blumenstingl .param = &meson_sar_adc_meson8b_param, 11056c76ed31SMartin Blumenstingl .name = "meson-meson8b-saradc", 11066c76ed31SMartin Blumenstingl }; 11076c76ed31SMartin Blumenstingl 1108ffc0d638SMartin Blumenstingl static const struct meson_sar_adc_data meson_sar_adc_meson8m2_data = { 1109723a61e0SMartin Blumenstingl .param = &meson_sar_adc_meson8b_param, 1110ffc0d638SMartin Blumenstingl .name = "meson-meson8m2-saradc", 1111ffc0d638SMartin Blumenstingl }; 1112ffc0d638SMartin Blumenstingl 1113c1c2de37SMartin Blumenstingl static const struct meson_sar_adc_data meson_sar_adc_gxbb_data = { 1114053ffe3cSYixun Lan .param = &meson_sar_adc_gxbb_param, 11153adbf342SMartin Blumenstingl .name = "meson-gxbb-saradc", 11163adbf342SMartin Blumenstingl }; 11173adbf342SMartin Blumenstingl 1118c1c2de37SMartin Blumenstingl static const struct meson_sar_adc_data meson_sar_adc_gxl_data = { 1119053ffe3cSYixun Lan .param = &meson_sar_adc_gxl_param, 11203adbf342SMartin Blumenstingl .name = "meson-gxl-saradc", 11213adbf342SMartin Blumenstingl }; 11223adbf342SMartin Blumenstingl 1123c1c2de37SMartin Blumenstingl static const struct meson_sar_adc_data meson_sar_adc_gxm_data = { 1124053ffe3cSYixun Lan .param = &meson_sar_adc_gxl_param, 11253adbf342SMartin Blumenstingl .name = "meson-gxm-saradc", 11263adbf342SMartin Blumenstingl }; 11273adbf342SMartin Blumenstingl 1128ff632ddaSXingyu Chen static const struct meson_sar_adc_data meson_sar_adc_axg_data = { 1129ff632ddaSXingyu Chen .param = &meson_sar_adc_gxl_param, 1130ff632ddaSXingyu Chen .name = "meson-axg-saradc", 1131ff632ddaSXingyu Chen }; 1132ff632ddaSXingyu Chen 1133e415a165SNeil Armstrong static const struct meson_sar_adc_data meson_sar_adc_g12a_data = { 113448dc1abdSMartin Blumenstingl .param = &meson_sar_adc_g12a_param, 1135e415a165SNeil Armstrong .name = "meson-g12a-saradc", 1136e415a165SNeil Armstrong }; 1137e415a165SNeil Armstrong 11383adbf342SMartin Blumenstingl static const struct of_device_id meson_sar_adc_of_match[] = { 11393adbf342SMartin Blumenstingl { 11406c76ed31SMartin Blumenstingl .compatible = "amlogic,meson8-saradc", 11416c76ed31SMartin Blumenstingl .data = &meson_sar_adc_meson8_data, 114214b15f3fSMartin Blumenstingl }, { 11436c76ed31SMartin Blumenstingl .compatible = "amlogic,meson8b-saradc", 11446c76ed31SMartin Blumenstingl .data = &meson_sar_adc_meson8b_data, 114514b15f3fSMartin Blumenstingl }, { 1146ffc0d638SMartin Blumenstingl .compatible = "amlogic,meson8m2-saradc", 1147ffc0d638SMartin Blumenstingl .data = &meson_sar_adc_meson8m2_data, 114814b15f3fSMartin Blumenstingl }, { 11493adbf342SMartin Blumenstingl .compatible = "amlogic,meson-gxbb-saradc", 11503adbf342SMartin Blumenstingl .data = &meson_sar_adc_gxbb_data, 11513adbf342SMartin Blumenstingl }, { 11523adbf342SMartin Blumenstingl .compatible = "amlogic,meson-gxl-saradc", 11533adbf342SMartin Blumenstingl .data = &meson_sar_adc_gxl_data, 11543adbf342SMartin Blumenstingl }, { 11553adbf342SMartin Blumenstingl .compatible = "amlogic,meson-gxm-saradc", 11563adbf342SMartin Blumenstingl .data = &meson_sar_adc_gxm_data, 1157ff632ddaSXingyu Chen }, { 1158ff632ddaSXingyu Chen .compatible = "amlogic,meson-axg-saradc", 1159ff632ddaSXingyu Chen .data = &meson_sar_adc_axg_data, 1160e415a165SNeil Armstrong }, { 1161e415a165SNeil Armstrong .compatible = "amlogic,meson-g12a-saradc", 1162e415a165SNeil Armstrong .data = &meson_sar_adc_g12a_data, 11633adbf342SMartin Blumenstingl }, 116414b15f3fSMartin Blumenstingl { /* sentinel */ } 11653adbf342SMartin Blumenstingl }; 11663adbf342SMartin Blumenstingl MODULE_DEVICE_TABLE(of, meson_sar_adc_of_match); 11673adbf342SMartin Blumenstingl 11683adbf342SMartin Blumenstingl static int meson_sar_adc_probe(struct platform_device *pdev) 11693adbf342SMartin Blumenstingl { 1170234c64a2SMartin Blumenstingl const struct meson_sar_adc_data *match_data; 11713adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv; 11722d27a021SAndy Shevchenko struct device *dev = &pdev->dev; 11733adbf342SMartin Blumenstingl struct iio_dev *indio_dev; 11743adbf342SMartin Blumenstingl void __iomem *base; 11753af10913SHeiner Kallweit int irq, ret; 11763adbf342SMartin Blumenstingl 117722c26db4SAndy Shevchenko indio_dev = devm_iio_device_alloc(dev, sizeof(*priv)); 11782d27a021SAndy Shevchenko if (!indio_dev) 11792d27a021SAndy Shevchenko return dev_err_probe(dev, -ENOMEM, "failed allocating iio device\n"); 11803adbf342SMartin Blumenstingl 11813adbf342SMartin Blumenstingl priv = iio_priv(indio_dev); 11823af10913SHeiner Kallweit init_completion(&priv->done); 11833adbf342SMartin Blumenstingl 118422c26db4SAndy Shevchenko match_data = of_device_get_match_data(dev); 11852d27a021SAndy Shevchenko if (!match_data) 11862d27a021SAndy Shevchenko return dev_err_probe(dev, -ENODEV, "failed to get match data\n"); 11872f9aeeedSGustavo A. R. Silva 1188057e5a11SMartin Blumenstingl priv->param = match_data->param; 11893adbf342SMartin Blumenstingl 1190057e5a11SMartin Blumenstingl indio_dev->name = match_data->name; 11913adbf342SMartin Blumenstingl indio_dev->modes = INDIO_DIRECT_MODE; 11923adbf342SMartin Blumenstingl indio_dev->info = &meson_sar_adc_iio_info; 11933adbf342SMartin Blumenstingl 11945f401ef0SJonathan Cameron base = devm_platform_ioremap_resource(pdev, 0); 11953adbf342SMartin Blumenstingl if (IS_ERR(base)) 11963adbf342SMartin Blumenstingl return PTR_ERR(base); 11973adbf342SMartin Blumenstingl 119822c26db4SAndy Shevchenko priv->regmap = devm_regmap_init_mmio(dev, base, priv->param->regmap_config); 1199de10ac47SRemi Pommarel if (IS_ERR(priv->regmap)) 1200de10ac47SRemi Pommarel return PTR_ERR(priv->regmap); 1201de10ac47SRemi Pommarel 120222c26db4SAndy Shevchenko irq = irq_of_parse_and_map(dev->of_node, 0); 12033af10913SHeiner Kallweit if (!irq) 12043af10913SHeiner Kallweit return -EINVAL; 12053af10913SHeiner Kallweit 120622c26db4SAndy Shevchenko ret = devm_request_irq(dev, irq, meson_sar_adc_irq, IRQF_SHARED, dev_name(dev), indio_dev); 12073af10913SHeiner Kallweit if (ret) 12083af10913SHeiner Kallweit return ret; 12093af10913SHeiner Kallweit 121022c26db4SAndy Shevchenko priv->clkin = devm_clk_get(dev, "clkin"); 1211a5999024SCai Huoqing if (IS_ERR(priv->clkin)) 121222c26db4SAndy Shevchenko return dev_err_probe(dev, PTR_ERR(priv->clkin), "failed to get clkin\n"); 12133adbf342SMartin Blumenstingl 121422c26db4SAndy Shevchenko priv->core_clk = devm_clk_get(dev, "core"); 1215a5999024SCai Huoqing if (IS_ERR(priv->core_clk)) 121622c26db4SAndy Shevchenko return dev_err_probe(dev, PTR_ERR(priv->core_clk), "failed to get core clk\n"); 12173adbf342SMartin Blumenstingl 12186531f3a4SAndy Shevchenko priv->adc_clk = devm_clk_get_optional(dev, "adc_clk"); 12196531f3a4SAndy Shevchenko if (IS_ERR(priv->adc_clk)) 12206531f3a4SAndy Shevchenko return dev_err_probe(dev, PTR_ERR(priv->adc_clk), "failed to get adc clk\n"); 12213adbf342SMartin Blumenstingl 12226531f3a4SAndy Shevchenko priv->adc_sel_clk = devm_clk_get_optional(dev, "adc_sel"); 12236531f3a4SAndy Shevchenko if (IS_ERR(priv->adc_sel_clk)) 12246531f3a4SAndy Shevchenko return dev_err_probe(dev, PTR_ERR(priv->adc_sel_clk), "failed to get adc_sel clk\n"); 12253adbf342SMartin Blumenstingl 12263adbf342SMartin Blumenstingl /* on pre-GXBB SoCs the SAR ADC itself provides the ADC clock: */ 12273adbf342SMartin Blumenstingl if (!priv->adc_clk) { 12283adbf342SMartin Blumenstingl ret = meson_sar_adc_clk_init(indio_dev, base); 12293adbf342SMartin Blumenstingl if (ret) 12303adbf342SMartin Blumenstingl return ret; 12313adbf342SMartin Blumenstingl } 12323adbf342SMartin Blumenstingl 123322c26db4SAndy Shevchenko priv->vref = devm_regulator_get(dev, "vref"); 1234a5999024SCai Huoqing if (IS_ERR(priv->vref)) 123522c26db4SAndy Shevchenko return dev_err_probe(dev, PTR_ERR(priv->vref), "failed to get vref regulator\n"); 12363adbf342SMartin Blumenstingl 123748ba7c3cSHeiner Kallweit priv->calibscale = MILLION; 123848ba7c3cSHeiner Kallweit 1239723a61e0SMartin Blumenstingl if (priv->param->temperature_trimming_bits) { 1240723a61e0SMartin Blumenstingl ret = meson_sar_adc_temp_sensor_init(indio_dev); 1241723a61e0SMartin Blumenstingl if (ret) 1242723a61e0SMartin Blumenstingl return ret; 1243723a61e0SMartin Blumenstingl } 1244723a61e0SMartin Blumenstingl 1245723a61e0SMartin Blumenstingl if (priv->temperature_sensor_calibrated) { 1246723a61e0SMartin Blumenstingl indio_dev->channels = meson_sar_adc_and_temp_iio_channels; 1247723a61e0SMartin Blumenstingl indio_dev->num_channels = 1248723a61e0SMartin Blumenstingl ARRAY_SIZE(meson_sar_adc_and_temp_iio_channels); 1249723a61e0SMartin Blumenstingl } else { 1250723a61e0SMartin Blumenstingl indio_dev->channels = meson_sar_adc_iio_channels; 1251723a61e0SMartin Blumenstingl indio_dev->num_channels = 1252723a61e0SMartin Blumenstingl ARRAY_SIZE(meson_sar_adc_iio_channels); 1253723a61e0SMartin Blumenstingl } 1254723a61e0SMartin Blumenstingl 12553adbf342SMartin Blumenstingl ret = meson_sar_adc_init(indio_dev); 12563adbf342SMartin Blumenstingl if (ret) 12573adbf342SMartin Blumenstingl goto err; 12583adbf342SMartin Blumenstingl 1259d0c09264SNuno Sá mutex_init(&priv->lock); 1260d0c09264SNuno Sá 12613adbf342SMartin Blumenstingl ret = meson_sar_adc_hw_enable(indio_dev); 12623adbf342SMartin Blumenstingl if (ret) 12633adbf342SMartin Blumenstingl goto err; 12643adbf342SMartin Blumenstingl 126548ba7c3cSHeiner Kallweit ret = meson_sar_adc_calib(indio_dev); 126648ba7c3cSHeiner Kallweit if (ret) 126722c26db4SAndy Shevchenko dev_warn(dev, "calibration failed\n"); 126848ba7c3cSHeiner Kallweit 12693adbf342SMartin Blumenstingl platform_set_drvdata(pdev, indio_dev); 12703adbf342SMartin Blumenstingl 12713adbf342SMartin Blumenstingl ret = iio_device_register(indio_dev); 12723adbf342SMartin Blumenstingl if (ret) 12733adbf342SMartin Blumenstingl goto err_hw; 12743adbf342SMartin Blumenstingl 12753adbf342SMartin Blumenstingl return 0; 12763adbf342SMartin Blumenstingl 12773adbf342SMartin Blumenstingl err_hw: 12783adbf342SMartin Blumenstingl meson_sar_adc_hw_disable(indio_dev); 12793adbf342SMartin Blumenstingl err: 12803adbf342SMartin Blumenstingl return ret; 12813adbf342SMartin Blumenstingl } 12823adbf342SMartin Blumenstingl 12833adbf342SMartin Blumenstingl static int meson_sar_adc_remove(struct platform_device *pdev) 12843adbf342SMartin Blumenstingl { 12853adbf342SMartin Blumenstingl struct iio_dev *indio_dev = platform_get_drvdata(pdev); 12863adbf342SMartin Blumenstingl 12873adbf342SMartin Blumenstingl iio_device_unregister(indio_dev); 12883adbf342SMartin Blumenstingl 1289*4ab8bef1SUwe Kleine-König meson_sar_adc_hw_disable(indio_dev); 1290*4ab8bef1SUwe Kleine-König 1291*4ab8bef1SUwe Kleine-König return 0; 12923adbf342SMartin Blumenstingl } 12933adbf342SMartin Blumenstingl 129450737998SJonathan Cameron static int meson_sar_adc_suspend(struct device *dev) 12953adbf342SMartin Blumenstingl { 12963adbf342SMartin Blumenstingl struct iio_dev *indio_dev = dev_get_drvdata(dev); 12973adbf342SMartin Blumenstingl 1298*4ab8bef1SUwe Kleine-König meson_sar_adc_hw_disable(indio_dev); 1299*4ab8bef1SUwe Kleine-König 1300*4ab8bef1SUwe Kleine-König return 0; 13013adbf342SMartin Blumenstingl } 13023adbf342SMartin Blumenstingl 130350737998SJonathan Cameron static int meson_sar_adc_resume(struct device *dev) 13043adbf342SMartin Blumenstingl { 13053adbf342SMartin Blumenstingl struct iio_dev *indio_dev = dev_get_drvdata(dev); 13063adbf342SMartin Blumenstingl 13073adbf342SMartin Blumenstingl return meson_sar_adc_hw_enable(indio_dev); 13083adbf342SMartin Blumenstingl } 13093adbf342SMartin Blumenstingl 131050737998SJonathan Cameron static DEFINE_SIMPLE_DEV_PM_OPS(meson_sar_adc_pm_ops, 13113adbf342SMartin Blumenstingl meson_sar_adc_suspend, meson_sar_adc_resume); 13123adbf342SMartin Blumenstingl 13133adbf342SMartin Blumenstingl static struct platform_driver meson_sar_adc_driver = { 13143adbf342SMartin Blumenstingl .probe = meson_sar_adc_probe, 13153adbf342SMartin Blumenstingl .remove = meson_sar_adc_remove, 13163adbf342SMartin Blumenstingl .driver = { 13173adbf342SMartin Blumenstingl .name = "meson-saradc", 13183adbf342SMartin Blumenstingl .of_match_table = meson_sar_adc_of_match, 131950737998SJonathan Cameron .pm = pm_sleep_ptr(&meson_sar_adc_pm_ops), 13203adbf342SMartin Blumenstingl }, 13213adbf342SMartin Blumenstingl }; 13223adbf342SMartin Blumenstingl 13233adbf342SMartin Blumenstingl module_platform_driver(meson_sar_adc_driver); 13243adbf342SMartin Blumenstingl 13253adbf342SMartin Blumenstingl MODULE_AUTHOR("Martin Blumenstingl <martin.blumenstingl@googlemail.com>"); 13263adbf342SMartin Blumenstingl MODULE_DESCRIPTION("Amlogic Meson SAR ADC driver"); 13273adbf342SMartin Blumenstingl MODULE_LICENSE("GPL v2"); 1328