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> 15723a61e0SMartin Blumenstingl #include <linux/nvmem-consumer.h> 163af10913SHeiner Kallweit #include <linux/interrupt.h> 173adbf342SMartin Blumenstingl #include <linux/of.h> 183af10913SHeiner Kallweit #include <linux/of_irq.h> 193adbf342SMartin Blumenstingl #include <linux/of_device.h> 203adbf342SMartin Blumenstingl #include <linux/platform_device.h> 213adbf342SMartin Blumenstingl #include <linux/regmap.h> 223adbf342SMartin Blumenstingl #include <linux/regulator/consumer.h> 23b002bf5fSMartin Blumenstingl #include <linux/mfd/syscon.h> 243adbf342SMartin Blumenstingl 253adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0 0x00 263adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_PANEL_DETECT BIT(31) 273adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_BUSY_MASK GENMASK(30, 28) 283adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_DELTA_BUSY BIT(30) 293adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_AVG_BUSY BIT(29) 303adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_SAMPLE_BUSY BIT(28) 313adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_FIFO_FULL BIT(27) 323adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_FIFO_EMPTY BIT(26) 333adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_FIFO_COUNT_MASK GENMASK(25, 21) 343adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_ADC_BIAS_CTRL_MASK GENMASK(20, 19) 353adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_CURR_CHAN_ID_MASK GENMASK(18, 16) 363adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_ADC_TEMP_SEN_SEL BIT(15) 373adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_SAMPLING_STOP BIT(14) 383adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_CHAN_DELTA_EN_MASK GENMASK(13, 12) 393adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_DETECT_IRQ_POL BIT(10) 403adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_DETECT_IRQ_EN BIT(9) 413adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK GENMASK(8, 4) 423adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_FIFO_IRQ_EN BIT(3) 433adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_SAMPLING_START BIT(2) 443adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_CONTINUOUS_EN BIT(1) 453adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE BIT(0) 463adbf342SMartin Blumenstingl 473adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_LIST 0x04 483adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_LIST_MAX_INDEX_MASK GENMASK(26, 24) 493adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_LIST_ENTRY_MASK(_chan) \ 503adbf342SMartin Blumenstingl (GENMASK(2, 0) << ((_chan) * 3)) 513adbf342SMartin Blumenstingl 523adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AVG_CNTL 0x08 533adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AVG_CNTL_AVG_MODE_SHIFT(_chan) \ 543adbf342SMartin Blumenstingl (16 + ((_chan) * 2)) 553adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AVG_CNTL_AVG_MODE_MASK(_chan) \ 563adbf342SMartin Blumenstingl (GENMASK(17, 16) << ((_chan) * 2)) 573adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AVG_CNTL_NUM_SAMPLES_SHIFT(_chan) \ 583adbf342SMartin Blumenstingl (0 + ((_chan) * 2)) 593adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AVG_CNTL_NUM_SAMPLES_MASK(_chan) \ 603adbf342SMartin Blumenstingl (GENMASK(1, 0) << ((_chan) * 2)) 613adbf342SMartin Blumenstingl 623adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3 0x0c 633adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_CNTL_USE_SC_DLY BIT(31) 643adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_CLK_EN BIT(30) 653adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_BL30_INITIALIZED BIT(28) 663adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_CTRL_CONT_RING_COUNTER_EN BIT(27) 673adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_CTRL_SAMPLING_CLOCK_PHASE BIT(26) 683adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_CTRL_CHAN7_MUX_SEL_MASK GENMASK(25, 23) 693adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_DETECT_EN BIT(22) 703adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_ADC_EN BIT(21) 713adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_PANEL_DETECT_COUNT_MASK GENMASK(20, 18) 723adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_PANEL_DETECT_FILTER_TB_MASK GENMASK(17, 16) 733adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_ADC_CLK_DIV_SHIFT 10 743adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_ADC_CLK_DIV_WIDTH 5 753adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_BLOCK_DLY_SEL_MASK GENMASK(9, 8) 763adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_BLOCK_DLY_MASK GENMASK(7, 0) 773adbf342SMartin Blumenstingl 783adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELAY 0x10 793adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELAY_INPUT_DLY_SEL_MASK GENMASK(25, 24) 803adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELAY_BL30_BUSY BIT(15) 813adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELAY_KERNEL_BUSY BIT(14) 823adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELAY_INPUT_DLY_CNT_MASK GENMASK(23, 16) 833adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELAY_SAMPLE_DLY_SEL_MASK GENMASK(9, 8) 843adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELAY_SAMPLE_DLY_CNT_MASK GENMASK(7, 0) 853adbf342SMartin Blumenstingl 863adbf342SMartin Blumenstingl #define MESON_SAR_ADC_LAST_RD 0x14 873adbf342SMartin Blumenstingl #define MESON_SAR_ADC_LAST_RD_LAST_CHANNEL1_MASK GENMASK(23, 16) 883adbf342SMartin Blumenstingl #define MESON_SAR_ADC_LAST_RD_LAST_CHANNEL0_MASK GENMASK(9, 0) 893adbf342SMartin Blumenstingl 903adbf342SMartin Blumenstingl #define MESON_SAR_ADC_FIFO_RD 0x18 913adbf342SMartin Blumenstingl #define MESON_SAR_ADC_FIFO_RD_CHAN_ID_MASK GENMASK(14, 12) 923adbf342SMartin Blumenstingl #define MESON_SAR_ADC_FIFO_RD_SAMPLE_VALUE_MASK GENMASK(11, 0) 933adbf342SMartin Blumenstingl 943adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AUX_SW 0x1c 95ab569a4cSMartin Blumenstingl #define MESON_SAR_ADC_AUX_SW_MUX_SEL_CHAN_SHIFT(_chan) \ 96ab569a4cSMartin Blumenstingl (8 + (((_chan) - 2) * 3)) 973adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AUX_SW_VREF_P_MUX BIT(6) 983adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AUX_SW_VREF_N_MUX BIT(5) 993adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AUX_SW_MODE_SEL BIT(4) 1003adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AUX_SW_YP_DRIVE_SW BIT(3) 1013adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AUX_SW_XP_DRIVE_SW BIT(2) 1023adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AUX_SW_YM_DRIVE_SW BIT(1) 1033adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AUX_SW_XM_DRIVE_SW BIT(0) 1043adbf342SMartin Blumenstingl 1053adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW 0x20 1063adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_MUX_SEL_MASK GENMASK(25, 23) 1073adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_VREF_P_MUX BIT(22) 1083adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_VREF_N_MUX BIT(21) 1093adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_MODE_SEL BIT(20) 1103adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_YP_DRIVE_SW BIT(19) 1113adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_XP_DRIVE_SW BIT(18) 1123adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_YM_DRIVE_SW BIT(17) 1133adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_XM_DRIVE_SW BIT(16) 1143adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_MUX_SEL_MASK GENMASK(9, 7) 1153adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_VREF_P_MUX BIT(6) 1163adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_VREF_N_MUX BIT(5) 1173adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_MODE_SEL BIT(4) 1183adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_YP_DRIVE_SW BIT(3) 1193adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_XP_DRIVE_SW BIT(2) 1203adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_YM_DRIVE_SW BIT(1) 1213adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_XM_DRIVE_SW BIT(0) 1223adbf342SMartin Blumenstingl 1233adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW 0x24 1243adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_SW_EN BIT(26) 1253adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_MUX_MASK GENMASK(25, 23) 1263adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_VREF_P_MUX BIT(22) 1273adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_VREF_N_MUX BIT(21) 1283adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_MODE_SEL BIT(20) 1293adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_YP_DRIVE_SW BIT(19) 1303adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_XP_DRIVE_SW BIT(18) 1313adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_YM_DRIVE_SW BIT(17) 1323adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_XM_DRIVE_SW BIT(16) 1333adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_MUX_SEL_MASK GENMASK(9, 7) 1343adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_VREF_P_MUX BIT(6) 1353adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_VREF_N_MUX BIT(5) 1363adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_MODE_SEL BIT(4) 1373adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_YP_DRIVE_SW BIT(3) 1383adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_XP_DRIVE_SW BIT(2) 1393adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_YM_DRIVE_SW BIT(1) 1403adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_XM_DRIVE_SW BIT(0) 1413adbf342SMartin Blumenstingl 1423adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELTA_10 0x28 1433adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELTA_10_TEMP_SEL BIT(27) 1443adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELTA_10_TS_REVE1 BIT(26) 1453adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELTA_10_CHAN1_DELTA_VALUE_MASK GENMASK(25, 16) 1463adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELTA_10_TS_REVE0 BIT(15) 1473adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELTA_10_TS_C_MASK GENMASK(14, 11) 1483adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELTA_10_TS_VBG_EN BIT(10) 1493adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELTA_10_CHAN0_DELTA_VALUE_MASK GENMASK(9, 0) 1503adbf342SMartin Blumenstingl 1513adbf342SMartin Blumenstingl /* 1523adbf342SMartin Blumenstingl * NOTE: registers from here are undocumented (the vendor Linux kernel driver 1533adbf342SMartin Blumenstingl * and u-boot source served as reference). These only seem to be relevant on 1543adbf342SMartin Blumenstingl * GXBB and newer. 1553adbf342SMartin Blumenstingl */ 1563adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG11 0x2c 1573adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG11_BANDGAP_EN BIT(13) 1583adbf342SMartin Blumenstingl 1593adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG13 0x34 1603adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG13_12BIT_CALIBRATION_MASK GENMASK(13, 8) 1613adbf342SMartin Blumenstingl 1623adbf342SMartin Blumenstingl #define MESON_SAR_ADC_MAX_FIFO_SIZE 32 1633af10913SHeiner Kallweit #define MESON_SAR_ADC_TIMEOUT 100 /* ms */ 164723a61e0SMartin Blumenstingl #define MESON_SAR_ADC_VOLTAGE_AND_TEMP_CHANNEL 6 165723a61e0SMartin Blumenstingl #define MESON_SAR_ADC_TEMP_OFFSET 27 166723a61e0SMartin Blumenstingl 167723a61e0SMartin Blumenstingl /* temperature sensor calibration information in eFuse */ 168723a61e0SMartin Blumenstingl #define MESON_SAR_ADC_EFUSE_BYTES 4 169723a61e0SMartin Blumenstingl #define MESON_SAR_ADC_EFUSE_BYTE3_UPPER_ADC_VAL GENMASK(6, 0) 170723a61e0SMartin Blumenstingl #define MESON_SAR_ADC_EFUSE_BYTE3_IS_CALIBRATED BIT(7) 171723a61e0SMartin Blumenstingl 172b002bf5fSMartin Blumenstingl #define MESON_HHI_DPLL_TOP_0 0x318 173b002bf5fSMartin Blumenstingl #define MESON_HHI_DPLL_TOP_0_TSC_BIT4 BIT(9) 174b002bf5fSMartin Blumenstingl 17548ba7c3cSHeiner Kallweit /* for use with IIO_VAL_INT_PLUS_MICRO */ 17648ba7c3cSHeiner Kallweit #define MILLION 1000000 1773adbf342SMartin Blumenstingl 1783adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN(_chan) { \ 1793adbf342SMartin Blumenstingl .type = IIO_VOLTAGE, \ 1803adbf342SMartin Blumenstingl .indexed = 1, \ 1813adbf342SMartin Blumenstingl .channel = _chan, \ 182827df057SMartin Blumenstingl .address = _chan, \ 1833adbf342SMartin Blumenstingl .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ 1843adbf342SMartin Blumenstingl BIT(IIO_CHAN_INFO_AVERAGE_RAW), \ 185723a61e0SMartin Blumenstingl .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ 186723a61e0SMartin Blumenstingl .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_CALIBBIAS) | \ 18748ba7c3cSHeiner Kallweit BIT(IIO_CHAN_INFO_CALIBSCALE), \ 1883adbf342SMartin Blumenstingl .datasheet_name = "SAR_ADC_CH"#_chan, \ 1893adbf342SMartin Blumenstingl } 1903adbf342SMartin Blumenstingl 191723a61e0SMartin Blumenstingl #define MESON_SAR_ADC_TEMP_CHAN(_chan) { \ 192723a61e0SMartin Blumenstingl .type = IIO_TEMP, \ 193723a61e0SMartin Blumenstingl .channel = _chan, \ 194723a61e0SMartin Blumenstingl .address = MESON_SAR_ADC_VOLTAGE_AND_TEMP_CHANNEL, \ 195723a61e0SMartin Blumenstingl .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ 196723a61e0SMartin Blumenstingl BIT(IIO_CHAN_INFO_AVERAGE_RAW), \ 197723a61e0SMartin Blumenstingl .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | \ 198723a61e0SMartin Blumenstingl BIT(IIO_CHAN_INFO_SCALE), \ 199723a61e0SMartin Blumenstingl .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_CALIBBIAS) | \ 200723a61e0SMartin Blumenstingl BIT(IIO_CHAN_INFO_CALIBSCALE), \ 201723a61e0SMartin Blumenstingl .datasheet_name = "TEMP_SENSOR", \ 202723a61e0SMartin Blumenstingl } 203723a61e0SMartin Blumenstingl 2043adbf342SMartin Blumenstingl static const struct iio_chan_spec meson_sar_adc_iio_channels[] = { 2053adbf342SMartin Blumenstingl MESON_SAR_ADC_CHAN(0), 2063adbf342SMartin Blumenstingl MESON_SAR_ADC_CHAN(1), 2073adbf342SMartin Blumenstingl MESON_SAR_ADC_CHAN(2), 2083adbf342SMartin Blumenstingl MESON_SAR_ADC_CHAN(3), 2093adbf342SMartin Blumenstingl MESON_SAR_ADC_CHAN(4), 2103adbf342SMartin Blumenstingl MESON_SAR_ADC_CHAN(5), 2113adbf342SMartin Blumenstingl MESON_SAR_ADC_CHAN(6), 2123adbf342SMartin Blumenstingl MESON_SAR_ADC_CHAN(7), 2133adbf342SMartin Blumenstingl IIO_CHAN_SOFT_TIMESTAMP(8), 2143adbf342SMartin Blumenstingl }; 2153adbf342SMartin Blumenstingl 216723a61e0SMartin Blumenstingl static const struct iio_chan_spec meson_sar_adc_and_temp_iio_channels[] = { 217723a61e0SMartin Blumenstingl MESON_SAR_ADC_CHAN(0), 218723a61e0SMartin Blumenstingl MESON_SAR_ADC_CHAN(1), 219723a61e0SMartin Blumenstingl MESON_SAR_ADC_CHAN(2), 220723a61e0SMartin Blumenstingl MESON_SAR_ADC_CHAN(3), 221723a61e0SMartin Blumenstingl MESON_SAR_ADC_CHAN(4), 222723a61e0SMartin Blumenstingl MESON_SAR_ADC_CHAN(5), 223723a61e0SMartin Blumenstingl MESON_SAR_ADC_CHAN(6), 224723a61e0SMartin Blumenstingl MESON_SAR_ADC_CHAN(7), 225723a61e0SMartin Blumenstingl MESON_SAR_ADC_TEMP_CHAN(8), 226723a61e0SMartin Blumenstingl IIO_CHAN_SOFT_TIMESTAMP(9), 227723a61e0SMartin Blumenstingl }; 228723a61e0SMartin Blumenstingl 2293adbf342SMartin Blumenstingl enum meson_sar_adc_avg_mode { 2303adbf342SMartin Blumenstingl NO_AVERAGING = 0x0, 2313adbf342SMartin Blumenstingl MEAN_AVERAGING = 0x1, 2323adbf342SMartin Blumenstingl MEDIAN_AVERAGING = 0x2, 2333adbf342SMartin Blumenstingl }; 2343adbf342SMartin Blumenstingl 2353adbf342SMartin Blumenstingl enum meson_sar_adc_num_samples { 2363adbf342SMartin Blumenstingl ONE_SAMPLE = 0x0, 2373adbf342SMartin Blumenstingl TWO_SAMPLES = 0x1, 2383adbf342SMartin Blumenstingl FOUR_SAMPLES = 0x2, 2393adbf342SMartin Blumenstingl EIGHT_SAMPLES = 0x3, 2403adbf342SMartin Blumenstingl }; 2413adbf342SMartin Blumenstingl 2423adbf342SMartin Blumenstingl enum meson_sar_adc_chan7_mux_sel { 2433adbf342SMartin Blumenstingl CHAN7_MUX_VSS = 0x0, 2443adbf342SMartin Blumenstingl CHAN7_MUX_VDD_DIV4 = 0x1, 2453adbf342SMartin Blumenstingl CHAN7_MUX_VDD_DIV2 = 0x2, 2463adbf342SMartin Blumenstingl CHAN7_MUX_VDD_MUL3_DIV4 = 0x3, 2473adbf342SMartin Blumenstingl CHAN7_MUX_VDD = 0x4, 2483adbf342SMartin Blumenstingl CHAN7_MUX_CH7_INPUT = 0x7, 2493adbf342SMartin Blumenstingl }; 2503adbf342SMartin Blumenstingl 251053ffe3cSYixun Lan struct meson_sar_adc_param { 2526c76ed31SMartin Blumenstingl bool has_bl30_integration; 253fda29dbaSMartin Blumenstingl unsigned long clock_rate; 254d85eed9fSMartin Blumenstingl u32 bandgap_reg; 2553adbf342SMartin Blumenstingl unsigned int resolution; 25696748823SMartin Blumenstingl const struct regmap_config *regmap_config; 257723a61e0SMartin Blumenstingl u8 temperature_trimming_bits; 258723a61e0SMartin Blumenstingl unsigned int temperature_multiplier; 259723a61e0SMartin Blumenstingl unsigned int temperature_divider; 2603adbf342SMartin Blumenstingl }; 2613adbf342SMartin Blumenstingl 262053ffe3cSYixun Lan struct meson_sar_adc_data { 263053ffe3cSYixun Lan const struct meson_sar_adc_param *param; 264053ffe3cSYixun Lan const char *name; 265053ffe3cSYixun Lan }; 266053ffe3cSYixun Lan 2673adbf342SMartin Blumenstingl struct meson_sar_adc_priv { 2683adbf342SMartin Blumenstingl struct regmap *regmap; 2693adbf342SMartin Blumenstingl struct regulator *vref; 270057e5a11SMartin Blumenstingl const struct meson_sar_adc_param *param; 2713adbf342SMartin Blumenstingl struct clk *clkin; 2723adbf342SMartin Blumenstingl struct clk *core_clk; 2733adbf342SMartin Blumenstingl struct clk *adc_sel_clk; 2743adbf342SMartin Blumenstingl struct clk *adc_clk; 2753adbf342SMartin Blumenstingl struct clk_gate clk_gate; 2763adbf342SMartin Blumenstingl struct clk *adc_div_clk; 2773adbf342SMartin Blumenstingl struct clk_divider clk_div; 2783af10913SHeiner Kallweit struct completion done; 27948ba7c3cSHeiner Kallweit int calibbias; 28048ba7c3cSHeiner Kallweit int calibscale; 281b002bf5fSMartin Blumenstingl struct regmap *tsc_regmap; 282723a61e0SMartin Blumenstingl bool temperature_sensor_calibrated; 283723a61e0SMartin Blumenstingl u8 temperature_sensor_coefficient; 284723a61e0SMartin Blumenstingl u16 temperature_sensor_adc_val; 2853adbf342SMartin Blumenstingl }; 2863adbf342SMartin Blumenstingl 28796748823SMartin Blumenstingl static const struct regmap_config meson_sar_adc_regmap_config_gxbb = { 2883adbf342SMartin Blumenstingl .reg_bits = 8, 2893adbf342SMartin Blumenstingl .val_bits = 32, 2903adbf342SMartin Blumenstingl .reg_stride = 4, 2913adbf342SMartin Blumenstingl .max_register = MESON_SAR_ADC_REG13, 2923adbf342SMartin Blumenstingl }; 2933adbf342SMartin Blumenstingl 29496748823SMartin Blumenstingl static const struct regmap_config meson_sar_adc_regmap_config_meson8 = { 29596748823SMartin Blumenstingl .reg_bits = 8, 29696748823SMartin Blumenstingl .val_bits = 32, 29796748823SMartin Blumenstingl .reg_stride = 4, 29896748823SMartin Blumenstingl .max_register = MESON_SAR_ADC_DELTA_10, 29996748823SMartin Blumenstingl }; 30096748823SMartin Blumenstingl 3013adbf342SMartin Blumenstingl static unsigned int meson_sar_adc_get_fifo_count(struct iio_dev *indio_dev) 3023adbf342SMartin Blumenstingl { 3033adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 3043adbf342SMartin Blumenstingl u32 regval; 3053adbf342SMartin Blumenstingl 3063adbf342SMartin Blumenstingl regmap_read(priv->regmap, MESON_SAR_ADC_REG0, ®val); 3073adbf342SMartin Blumenstingl 3083adbf342SMartin Blumenstingl return FIELD_GET(MESON_SAR_ADC_REG0_FIFO_COUNT_MASK, regval); 3093adbf342SMartin Blumenstingl } 3103adbf342SMartin Blumenstingl 31148ba7c3cSHeiner Kallweit static int meson_sar_adc_calib_val(struct iio_dev *indio_dev, int val) 31248ba7c3cSHeiner Kallweit { 31348ba7c3cSHeiner Kallweit struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 31448ba7c3cSHeiner Kallweit int tmp; 31548ba7c3cSHeiner Kallweit 31648ba7c3cSHeiner Kallweit /* use val_calib = scale * val_raw + offset calibration function */ 31748ba7c3cSHeiner Kallweit tmp = div_s64((s64)val * priv->calibscale, MILLION) + priv->calibbias; 31848ba7c3cSHeiner Kallweit 319057e5a11SMartin Blumenstingl return clamp(tmp, 0, (1 << priv->param->resolution) - 1); 32048ba7c3cSHeiner Kallweit } 32148ba7c3cSHeiner Kallweit 3223adbf342SMartin Blumenstingl static int meson_sar_adc_wait_busy_clear(struct iio_dev *indio_dev) 3233adbf342SMartin Blumenstingl { 3243adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 3253adbf342SMartin Blumenstingl int regval, timeout = 10000; 3263adbf342SMartin Blumenstingl 3273adbf342SMartin Blumenstingl /* 3283adbf342SMartin Blumenstingl * NOTE: we need a small delay before reading the status, otherwise 3293adbf342SMartin Blumenstingl * the sample engine may not have started internally (which would 3303adbf342SMartin Blumenstingl * seem to us that sampling is already finished). 3313adbf342SMartin Blumenstingl */ 3323adbf342SMartin Blumenstingl do { 3333adbf342SMartin Blumenstingl udelay(1); 3343adbf342SMartin Blumenstingl regmap_read(priv->regmap, MESON_SAR_ADC_REG0, ®val); 3353adbf342SMartin Blumenstingl } while (FIELD_GET(MESON_SAR_ADC_REG0_BUSY_MASK, regval) && timeout--); 3363adbf342SMartin Blumenstingl 3373adbf342SMartin Blumenstingl if (timeout < 0) 3383adbf342SMartin Blumenstingl return -ETIMEDOUT; 3393adbf342SMartin Blumenstingl 3403adbf342SMartin Blumenstingl return 0; 3413adbf342SMartin Blumenstingl } 3423adbf342SMartin Blumenstingl 3433adbf342SMartin Blumenstingl static int meson_sar_adc_read_raw_sample(struct iio_dev *indio_dev, 3443adbf342SMartin Blumenstingl const struct iio_chan_spec *chan, 3453adbf342SMartin Blumenstingl int *val) 3463adbf342SMartin Blumenstingl { 3473adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 3486a882a2cSHeiner Kallweit int regval, fifo_chan, fifo_val, count; 3493adbf342SMartin Blumenstingl 3503af10913SHeiner Kallweit if(!wait_for_completion_timeout(&priv->done, 3513af10913SHeiner Kallweit msecs_to_jiffies(MESON_SAR_ADC_TIMEOUT))) 3523af10913SHeiner Kallweit return -ETIMEDOUT; 3533adbf342SMartin Blumenstingl 3546a882a2cSHeiner Kallweit count = meson_sar_adc_get_fifo_count(indio_dev); 3556a882a2cSHeiner Kallweit if (count != 1) { 3566a882a2cSHeiner Kallweit dev_err(&indio_dev->dev, 3576a882a2cSHeiner Kallweit "ADC FIFO has %d element(s) instead of one\n", count); 3586a882a2cSHeiner Kallweit return -EINVAL; 3593adbf342SMartin Blumenstingl } 3603adbf342SMartin Blumenstingl 3616a882a2cSHeiner Kallweit regmap_read(priv->regmap, MESON_SAR_ADC_FIFO_RD, ®val); 3626a882a2cSHeiner Kallweit fifo_chan = FIELD_GET(MESON_SAR_ADC_FIFO_RD_CHAN_ID_MASK, regval); 363827df057SMartin Blumenstingl if (fifo_chan != chan->address) { 3646a882a2cSHeiner Kallweit dev_err(&indio_dev->dev, 365827df057SMartin Blumenstingl "ADC FIFO entry belongs to channel %d instead of %lu\n", 366827df057SMartin Blumenstingl fifo_chan, chan->address); 3676a882a2cSHeiner Kallweit return -EINVAL; 3686a882a2cSHeiner Kallweit } 3693adbf342SMartin Blumenstingl 3706a882a2cSHeiner Kallweit fifo_val = FIELD_GET(MESON_SAR_ADC_FIFO_RD_SAMPLE_VALUE_MASK, regval); 371057e5a11SMartin Blumenstingl fifo_val &= GENMASK(priv->param->resolution - 1, 0); 37248ba7c3cSHeiner Kallweit *val = meson_sar_adc_calib_val(indio_dev, fifo_val); 3733adbf342SMartin Blumenstingl 3743adbf342SMartin Blumenstingl return 0; 3753adbf342SMartin Blumenstingl } 3763adbf342SMartin Blumenstingl 3773adbf342SMartin Blumenstingl static void meson_sar_adc_set_averaging(struct iio_dev *indio_dev, 3783adbf342SMartin Blumenstingl const struct iio_chan_spec *chan, 3793adbf342SMartin Blumenstingl enum meson_sar_adc_avg_mode mode, 3803adbf342SMartin Blumenstingl enum meson_sar_adc_num_samples samples) 3813adbf342SMartin Blumenstingl { 3823adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 383827df057SMartin Blumenstingl int val, address = chan->address; 3843adbf342SMartin Blumenstingl 385827df057SMartin Blumenstingl val = samples << MESON_SAR_ADC_AVG_CNTL_NUM_SAMPLES_SHIFT(address); 3863adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_AVG_CNTL, 387827df057SMartin Blumenstingl MESON_SAR_ADC_AVG_CNTL_NUM_SAMPLES_MASK(address), 3883adbf342SMartin Blumenstingl val); 3893adbf342SMartin Blumenstingl 390827df057SMartin Blumenstingl val = mode << MESON_SAR_ADC_AVG_CNTL_AVG_MODE_SHIFT(address); 3913adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_AVG_CNTL, 392827df057SMartin Blumenstingl MESON_SAR_ADC_AVG_CNTL_AVG_MODE_MASK(address), val); 3933adbf342SMartin Blumenstingl } 3943adbf342SMartin Blumenstingl 3953adbf342SMartin Blumenstingl static void meson_sar_adc_enable_channel(struct iio_dev *indio_dev, 3963adbf342SMartin Blumenstingl const struct iio_chan_spec *chan) 3973adbf342SMartin Blumenstingl { 3983adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 3993adbf342SMartin Blumenstingl u32 regval; 4003adbf342SMartin Blumenstingl 4013adbf342SMartin Blumenstingl /* 4023adbf342SMartin Blumenstingl * the SAR ADC engine allows sampling multiple channels at the same 4033adbf342SMartin Blumenstingl * time. to keep it simple we're only working with one *internal* 4043adbf342SMartin Blumenstingl * channel, which starts counting at index 0 (which means: count = 1). 4053adbf342SMartin Blumenstingl */ 4063adbf342SMartin Blumenstingl regval = FIELD_PREP(MESON_SAR_ADC_CHAN_LIST_MAX_INDEX_MASK, 0); 4073adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_LIST, 4083adbf342SMartin Blumenstingl MESON_SAR_ADC_CHAN_LIST_MAX_INDEX_MASK, regval); 4093adbf342SMartin Blumenstingl 4103adbf342SMartin Blumenstingl /* map channel index 0 to the channel which we want to read */ 4113adbf342SMartin Blumenstingl regval = FIELD_PREP(MESON_SAR_ADC_CHAN_LIST_ENTRY_MASK(0), 412827df057SMartin Blumenstingl chan->address); 4133adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_LIST, 4143adbf342SMartin Blumenstingl MESON_SAR_ADC_CHAN_LIST_ENTRY_MASK(0), regval); 4153adbf342SMartin Blumenstingl 4163adbf342SMartin Blumenstingl regval = FIELD_PREP(MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_MUX_MASK, 417827df057SMartin Blumenstingl chan->address); 4183adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DETECT_IDLE_SW, 4193adbf342SMartin Blumenstingl MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_MUX_MASK, 4203adbf342SMartin Blumenstingl regval); 4213adbf342SMartin Blumenstingl 4223adbf342SMartin Blumenstingl regval = FIELD_PREP(MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_MUX_SEL_MASK, 423827df057SMartin Blumenstingl chan->address); 4243adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DETECT_IDLE_SW, 4253adbf342SMartin Blumenstingl MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_MUX_SEL_MASK, 4263adbf342SMartin Blumenstingl regval); 4273adbf342SMartin Blumenstingl 428723a61e0SMartin Blumenstingl if (chan->address == MESON_SAR_ADC_VOLTAGE_AND_TEMP_CHANNEL) { 429723a61e0SMartin Blumenstingl if (chan->type == IIO_TEMP) 430723a61e0SMartin Blumenstingl regval = MESON_SAR_ADC_DELTA_10_TEMP_SEL; 431723a61e0SMartin Blumenstingl else 432723a61e0SMartin Blumenstingl regval = 0; 433723a61e0SMartin Blumenstingl 434723a61e0SMartin Blumenstingl regmap_update_bits(priv->regmap, 435723a61e0SMartin Blumenstingl MESON_SAR_ADC_DELTA_10, 436723a61e0SMartin Blumenstingl MESON_SAR_ADC_DELTA_10_TEMP_SEL, regval); 437723a61e0SMartin Blumenstingl } 4383adbf342SMartin Blumenstingl } 4393adbf342SMartin Blumenstingl 4403adbf342SMartin Blumenstingl static void meson_sar_adc_set_chan7_mux(struct iio_dev *indio_dev, 4413adbf342SMartin Blumenstingl enum meson_sar_adc_chan7_mux_sel sel) 4423adbf342SMartin Blumenstingl { 4433adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 4443adbf342SMartin Blumenstingl u32 regval; 4453adbf342SMartin Blumenstingl 4463adbf342SMartin Blumenstingl regval = FIELD_PREP(MESON_SAR_ADC_REG3_CTRL_CHAN7_MUX_SEL_MASK, sel); 4473adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3, 4483adbf342SMartin Blumenstingl MESON_SAR_ADC_REG3_CTRL_CHAN7_MUX_SEL_MASK, regval); 4493adbf342SMartin Blumenstingl 4503adbf342SMartin Blumenstingl usleep_range(10, 20); 4513adbf342SMartin Blumenstingl } 4523adbf342SMartin Blumenstingl 4533adbf342SMartin Blumenstingl static void meson_sar_adc_start_sample_engine(struct iio_dev *indio_dev) 4543adbf342SMartin Blumenstingl { 4553adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 4563adbf342SMartin Blumenstingl 4573af10913SHeiner Kallweit reinit_completion(&priv->done); 4583af10913SHeiner Kallweit 4593af10913SHeiner Kallweit regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, 4603af10913SHeiner Kallweit MESON_SAR_ADC_REG0_FIFO_IRQ_EN, 4613af10913SHeiner Kallweit MESON_SAR_ADC_REG0_FIFO_IRQ_EN); 4623af10913SHeiner Kallweit 4633adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, 4643adbf342SMartin Blumenstingl MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE, 4653adbf342SMartin Blumenstingl MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE); 4663adbf342SMartin Blumenstingl 4673adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, 4683adbf342SMartin Blumenstingl MESON_SAR_ADC_REG0_SAMPLING_START, 4693adbf342SMartin Blumenstingl MESON_SAR_ADC_REG0_SAMPLING_START); 4703adbf342SMartin Blumenstingl } 4713adbf342SMartin Blumenstingl 4723adbf342SMartin Blumenstingl static void meson_sar_adc_stop_sample_engine(struct iio_dev *indio_dev) 4733adbf342SMartin Blumenstingl { 4743adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 4753adbf342SMartin Blumenstingl 4763adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, 4773af10913SHeiner Kallweit MESON_SAR_ADC_REG0_FIFO_IRQ_EN, 0); 4783af10913SHeiner Kallweit 4793af10913SHeiner Kallweit regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, 4803adbf342SMartin Blumenstingl MESON_SAR_ADC_REG0_SAMPLING_STOP, 4813adbf342SMartin Blumenstingl MESON_SAR_ADC_REG0_SAMPLING_STOP); 4823adbf342SMartin Blumenstingl 4833adbf342SMartin Blumenstingl /* wait until all modules are stopped */ 4843adbf342SMartin Blumenstingl meson_sar_adc_wait_busy_clear(indio_dev); 4853adbf342SMartin Blumenstingl 4863adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, 4873adbf342SMartin Blumenstingl MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE, 0); 4883adbf342SMartin Blumenstingl } 4893adbf342SMartin Blumenstingl 4903adbf342SMartin Blumenstingl static int meson_sar_adc_lock(struct iio_dev *indio_dev) 4913adbf342SMartin Blumenstingl { 4923adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 4933adbf342SMartin Blumenstingl int val, timeout = 10000; 4943adbf342SMartin Blumenstingl 4953adbf342SMartin Blumenstingl mutex_lock(&indio_dev->mlock); 4963adbf342SMartin Blumenstingl 497057e5a11SMartin Blumenstingl if (priv->param->has_bl30_integration) { 4983adbf342SMartin Blumenstingl /* prevent BL30 from using the SAR ADC while we are using it */ 4993adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY, 5003adbf342SMartin Blumenstingl MESON_SAR_ADC_DELAY_KERNEL_BUSY, 5013adbf342SMartin Blumenstingl MESON_SAR_ADC_DELAY_KERNEL_BUSY); 5023adbf342SMartin Blumenstingl 5036c76ed31SMartin Blumenstingl /* 5046c76ed31SMartin Blumenstingl * wait until BL30 releases it's lock (so we can use the SAR 5056c76ed31SMartin Blumenstingl * ADC) 5066c76ed31SMartin Blumenstingl */ 5073adbf342SMartin Blumenstingl do { 5083adbf342SMartin Blumenstingl udelay(1); 5093adbf342SMartin Blumenstingl regmap_read(priv->regmap, MESON_SAR_ADC_DELAY, &val); 5103adbf342SMartin Blumenstingl } while (val & MESON_SAR_ADC_DELAY_BL30_BUSY && timeout--); 5113adbf342SMartin Blumenstingl 5123c3e4b3aSDan Carpenter if (timeout < 0) { 5133c3e4b3aSDan Carpenter mutex_unlock(&indio_dev->mlock); 5143adbf342SMartin Blumenstingl return -ETIMEDOUT; 5156c76ed31SMartin Blumenstingl } 5163c3e4b3aSDan Carpenter } 5173adbf342SMartin Blumenstingl 5183adbf342SMartin Blumenstingl return 0; 5193adbf342SMartin Blumenstingl } 5203adbf342SMartin Blumenstingl 5213adbf342SMartin Blumenstingl static void meson_sar_adc_unlock(struct iio_dev *indio_dev) 5223adbf342SMartin Blumenstingl { 5233adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 5243adbf342SMartin Blumenstingl 525057e5a11SMartin Blumenstingl if (priv->param->has_bl30_integration) 5263adbf342SMartin Blumenstingl /* allow BL30 to use the SAR ADC again */ 5273adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY, 5283adbf342SMartin Blumenstingl MESON_SAR_ADC_DELAY_KERNEL_BUSY, 0); 5293adbf342SMartin Blumenstingl 5303adbf342SMartin Blumenstingl mutex_unlock(&indio_dev->mlock); 5313adbf342SMartin Blumenstingl } 5323adbf342SMartin Blumenstingl 5333adbf342SMartin Blumenstingl static void meson_sar_adc_clear_fifo(struct iio_dev *indio_dev) 5343adbf342SMartin Blumenstingl { 5353adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 536103a07d4SMartin Blumenstingl unsigned int count, tmp; 5373adbf342SMartin Blumenstingl 5383adbf342SMartin Blumenstingl for (count = 0; count < MESON_SAR_ADC_MAX_FIFO_SIZE; count++) { 5393adbf342SMartin Blumenstingl if (!meson_sar_adc_get_fifo_count(indio_dev)) 5403adbf342SMartin Blumenstingl break; 5413adbf342SMartin Blumenstingl 542103a07d4SMartin Blumenstingl regmap_read(priv->regmap, MESON_SAR_ADC_FIFO_RD, &tmp); 5433adbf342SMartin Blumenstingl } 5443adbf342SMartin Blumenstingl } 5453adbf342SMartin Blumenstingl 5463adbf342SMartin Blumenstingl static int meson_sar_adc_get_sample(struct iio_dev *indio_dev, 5473adbf342SMartin Blumenstingl const struct iio_chan_spec *chan, 5483adbf342SMartin Blumenstingl enum meson_sar_adc_avg_mode avg_mode, 5493adbf342SMartin Blumenstingl enum meson_sar_adc_num_samples avg_samples, 5503adbf342SMartin Blumenstingl int *val) 5513adbf342SMartin Blumenstingl { 552723a61e0SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 5533adbf342SMartin Blumenstingl int ret; 5543adbf342SMartin Blumenstingl 555723a61e0SMartin Blumenstingl if (chan->type == IIO_TEMP && !priv->temperature_sensor_calibrated) 556723a61e0SMartin Blumenstingl return -ENOTSUPP; 557723a61e0SMartin Blumenstingl 5583adbf342SMartin Blumenstingl ret = meson_sar_adc_lock(indio_dev); 5593adbf342SMartin Blumenstingl if (ret) 5603adbf342SMartin Blumenstingl return ret; 5613adbf342SMartin Blumenstingl 5623adbf342SMartin Blumenstingl /* clear the FIFO to make sure we're not reading old values */ 5633adbf342SMartin Blumenstingl meson_sar_adc_clear_fifo(indio_dev); 5643adbf342SMartin Blumenstingl 5653adbf342SMartin Blumenstingl meson_sar_adc_set_averaging(indio_dev, chan, avg_mode, avg_samples); 5663adbf342SMartin Blumenstingl 5673adbf342SMartin Blumenstingl meson_sar_adc_enable_channel(indio_dev, chan); 5683adbf342SMartin Blumenstingl 5693adbf342SMartin Blumenstingl meson_sar_adc_start_sample_engine(indio_dev); 5703adbf342SMartin Blumenstingl ret = meson_sar_adc_read_raw_sample(indio_dev, chan, val); 5713adbf342SMartin Blumenstingl meson_sar_adc_stop_sample_engine(indio_dev); 5723adbf342SMartin Blumenstingl 5733adbf342SMartin Blumenstingl meson_sar_adc_unlock(indio_dev); 5743adbf342SMartin Blumenstingl 5753adbf342SMartin Blumenstingl if (ret) { 5763adbf342SMartin Blumenstingl dev_warn(indio_dev->dev.parent, 577827df057SMartin Blumenstingl "failed to read sample for channel %lu: %d\n", 578827df057SMartin Blumenstingl chan->address, ret); 5793adbf342SMartin Blumenstingl return ret; 5803adbf342SMartin Blumenstingl } 5813adbf342SMartin Blumenstingl 5823adbf342SMartin Blumenstingl return IIO_VAL_INT; 5833adbf342SMartin Blumenstingl } 5843adbf342SMartin Blumenstingl 5853adbf342SMartin Blumenstingl static int meson_sar_adc_iio_info_read_raw(struct iio_dev *indio_dev, 5863adbf342SMartin Blumenstingl const struct iio_chan_spec *chan, 5873adbf342SMartin Blumenstingl int *val, int *val2, long mask) 5883adbf342SMartin Blumenstingl { 5893adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 5903adbf342SMartin Blumenstingl int ret; 5913adbf342SMartin Blumenstingl 5923adbf342SMartin Blumenstingl switch (mask) { 5933adbf342SMartin Blumenstingl case IIO_CHAN_INFO_RAW: 5943adbf342SMartin Blumenstingl return meson_sar_adc_get_sample(indio_dev, chan, NO_AVERAGING, 5953adbf342SMartin Blumenstingl ONE_SAMPLE, val); 5963adbf342SMartin Blumenstingl break; 5973adbf342SMartin Blumenstingl 5983adbf342SMartin Blumenstingl case IIO_CHAN_INFO_AVERAGE_RAW: 5993adbf342SMartin Blumenstingl return meson_sar_adc_get_sample(indio_dev, chan, 6003adbf342SMartin Blumenstingl MEAN_AVERAGING, EIGHT_SAMPLES, 6013adbf342SMartin Blumenstingl val); 6023adbf342SMartin Blumenstingl break; 6033adbf342SMartin Blumenstingl 6043adbf342SMartin Blumenstingl case IIO_CHAN_INFO_SCALE: 605723a61e0SMartin Blumenstingl if (chan->type == IIO_VOLTAGE) { 6063adbf342SMartin Blumenstingl ret = regulator_get_voltage(priv->vref); 6073adbf342SMartin Blumenstingl if (ret < 0) { 6083adbf342SMartin Blumenstingl dev_err(indio_dev->dev.parent, 609723a61e0SMartin Blumenstingl "failed to get vref voltage: %d\n", 610723a61e0SMartin Blumenstingl ret); 6113adbf342SMartin Blumenstingl return ret; 6123adbf342SMartin Blumenstingl } 6133adbf342SMartin Blumenstingl 6143adbf342SMartin Blumenstingl *val = ret / 1000; 615057e5a11SMartin Blumenstingl *val2 = priv->param->resolution; 6163adbf342SMartin Blumenstingl return IIO_VAL_FRACTIONAL_LOG2; 617723a61e0SMartin Blumenstingl } else if (chan->type == IIO_TEMP) { 618723a61e0SMartin Blumenstingl /* SoC specific multiplier and divider */ 619723a61e0SMartin Blumenstingl *val = priv->param->temperature_multiplier; 620723a61e0SMartin Blumenstingl *val2 = priv->param->temperature_divider; 621723a61e0SMartin Blumenstingl 622723a61e0SMartin Blumenstingl /* celsius to millicelsius */ 623723a61e0SMartin Blumenstingl *val *= 1000; 624723a61e0SMartin Blumenstingl 625723a61e0SMartin Blumenstingl return IIO_VAL_FRACTIONAL; 626723a61e0SMartin Blumenstingl } else { 627723a61e0SMartin Blumenstingl return -EINVAL; 628723a61e0SMartin Blumenstingl } 6293adbf342SMartin Blumenstingl 63048ba7c3cSHeiner Kallweit case IIO_CHAN_INFO_CALIBBIAS: 63148ba7c3cSHeiner Kallweit *val = priv->calibbias; 63248ba7c3cSHeiner Kallweit return IIO_VAL_INT; 63348ba7c3cSHeiner Kallweit 63448ba7c3cSHeiner Kallweit case IIO_CHAN_INFO_CALIBSCALE: 63548ba7c3cSHeiner Kallweit *val = priv->calibscale / MILLION; 63648ba7c3cSHeiner Kallweit *val2 = priv->calibscale % MILLION; 63748ba7c3cSHeiner Kallweit return IIO_VAL_INT_PLUS_MICRO; 63848ba7c3cSHeiner Kallweit 639723a61e0SMartin Blumenstingl case IIO_CHAN_INFO_OFFSET: 640723a61e0SMartin Blumenstingl *val = DIV_ROUND_CLOSEST(MESON_SAR_ADC_TEMP_OFFSET * 641723a61e0SMartin Blumenstingl priv->param->temperature_divider, 642723a61e0SMartin Blumenstingl priv->param->temperature_multiplier); 643723a61e0SMartin Blumenstingl *val -= priv->temperature_sensor_adc_val; 644723a61e0SMartin Blumenstingl return IIO_VAL_INT; 645723a61e0SMartin Blumenstingl 6463adbf342SMartin Blumenstingl default: 6473adbf342SMartin Blumenstingl return -EINVAL; 6483adbf342SMartin Blumenstingl } 6493adbf342SMartin Blumenstingl } 6503adbf342SMartin Blumenstingl 6513adbf342SMartin Blumenstingl static int meson_sar_adc_clk_init(struct iio_dev *indio_dev, 6523adbf342SMartin Blumenstingl void __iomem *base) 6533adbf342SMartin Blumenstingl { 6543adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 6553adbf342SMartin Blumenstingl struct clk_init_data init; 6563adbf342SMartin Blumenstingl const char *clk_parents[1]; 6573adbf342SMartin Blumenstingl 65850314f98SMartin Blumenstingl init.name = devm_kasprintf(&indio_dev->dev, GFP_KERNEL, "%s#adc_div", 65950314f98SMartin Blumenstingl dev_name(indio_dev->dev.parent)); 660aad172b0SNicholas Mc Guire if (!init.name) 661aad172b0SNicholas Mc Guire return -ENOMEM; 662aad172b0SNicholas Mc Guire 6633adbf342SMartin Blumenstingl init.flags = 0; 6643adbf342SMartin Blumenstingl init.ops = &clk_divider_ops; 6653adbf342SMartin Blumenstingl clk_parents[0] = __clk_get_name(priv->clkin); 6663adbf342SMartin Blumenstingl init.parent_names = clk_parents; 6673adbf342SMartin Blumenstingl init.num_parents = 1; 6683adbf342SMartin Blumenstingl 6693adbf342SMartin Blumenstingl priv->clk_div.reg = base + MESON_SAR_ADC_REG3; 6703adbf342SMartin Blumenstingl priv->clk_div.shift = MESON_SAR_ADC_REG3_ADC_CLK_DIV_SHIFT; 6713adbf342SMartin Blumenstingl priv->clk_div.width = MESON_SAR_ADC_REG3_ADC_CLK_DIV_WIDTH; 6723adbf342SMartin Blumenstingl priv->clk_div.hw.init = &init; 6733adbf342SMartin Blumenstingl priv->clk_div.flags = 0; 6743adbf342SMartin Blumenstingl 6753adbf342SMartin Blumenstingl priv->adc_div_clk = devm_clk_register(&indio_dev->dev, 6763adbf342SMartin Blumenstingl &priv->clk_div.hw); 6773adbf342SMartin Blumenstingl if (WARN_ON(IS_ERR(priv->adc_div_clk))) 6783adbf342SMartin Blumenstingl return PTR_ERR(priv->adc_div_clk); 6793adbf342SMartin Blumenstingl 68050314f98SMartin Blumenstingl init.name = devm_kasprintf(&indio_dev->dev, GFP_KERNEL, "%s#adc_en", 68150314f98SMartin Blumenstingl dev_name(indio_dev->dev.parent)); 682aad172b0SNicholas Mc Guire if (!init.name) 683aad172b0SNicholas Mc Guire return -ENOMEM; 684aad172b0SNicholas Mc Guire 6853adbf342SMartin Blumenstingl init.flags = CLK_SET_RATE_PARENT; 6863adbf342SMartin Blumenstingl init.ops = &clk_gate_ops; 6873adbf342SMartin Blumenstingl clk_parents[0] = __clk_get_name(priv->adc_div_clk); 6883adbf342SMartin Blumenstingl init.parent_names = clk_parents; 6893adbf342SMartin Blumenstingl init.num_parents = 1; 6903adbf342SMartin Blumenstingl 6913adbf342SMartin Blumenstingl priv->clk_gate.reg = base + MESON_SAR_ADC_REG3; 6927a6b0420SMartin Blumenstingl priv->clk_gate.bit_idx = __ffs(MESON_SAR_ADC_REG3_CLK_EN); 6933adbf342SMartin Blumenstingl priv->clk_gate.hw.init = &init; 6943adbf342SMartin Blumenstingl 6953adbf342SMartin Blumenstingl priv->adc_clk = devm_clk_register(&indio_dev->dev, &priv->clk_gate.hw); 6963adbf342SMartin Blumenstingl if (WARN_ON(IS_ERR(priv->adc_clk))) 6973adbf342SMartin Blumenstingl return PTR_ERR(priv->adc_clk); 6983adbf342SMartin Blumenstingl 6993adbf342SMartin Blumenstingl return 0; 7003adbf342SMartin Blumenstingl } 7013adbf342SMartin Blumenstingl 702723a61e0SMartin Blumenstingl static int meson_sar_adc_temp_sensor_init(struct iio_dev *indio_dev) 703723a61e0SMartin Blumenstingl { 704723a61e0SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 705723a61e0SMartin Blumenstingl u8 *buf, trimming_bits, trimming_mask, upper_adc_val; 706723a61e0SMartin Blumenstingl struct nvmem_cell *temperature_calib; 707723a61e0SMartin Blumenstingl size_t read_len; 708723a61e0SMartin Blumenstingl int ret; 709723a61e0SMartin Blumenstingl 710723a61e0SMartin Blumenstingl temperature_calib = devm_nvmem_cell_get(&indio_dev->dev, 711723a61e0SMartin Blumenstingl "temperature_calib"); 712723a61e0SMartin Blumenstingl if (IS_ERR(temperature_calib)) { 713723a61e0SMartin Blumenstingl ret = PTR_ERR(temperature_calib); 714723a61e0SMartin Blumenstingl 715723a61e0SMartin Blumenstingl /* 716723a61e0SMartin Blumenstingl * leave the temperature sensor disabled if no calibration data 717723a61e0SMartin Blumenstingl * was passed via nvmem-cells. 718723a61e0SMartin Blumenstingl */ 719723a61e0SMartin Blumenstingl if (ret == -ENODEV) 720723a61e0SMartin Blumenstingl return 0; 721723a61e0SMartin Blumenstingl 722723a61e0SMartin Blumenstingl if (ret != -EPROBE_DEFER) 723723a61e0SMartin Blumenstingl dev_err(indio_dev->dev.parent, 724723a61e0SMartin Blumenstingl "failed to get temperature_calib cell\n"); 725723a61e0SMartin Blumenstingl 726723a61e0SMartin Blumenstingl return ret; 727723a61e0SMartin Blumenstingl } 728723a61e0SMartin Blumenstingl 729b002bf5fSMartin Blumenstingl priv->tsc_regmap = 730b002bf5fSMartin Blumenstingl syscon_regmap_lookup_by_phandle(indio_dev->dev.parent->of_node, 731b002bf5fSMartin Blumenstingl "amlogic,hhi-sysctrl"); 732b002bf5fSMartin Blumenstingl if (IS_ERR(priv->tsc_regmap)) { 733b002bf5fSMartin Blumenstingl dev_err(indio_dev->dev.parent, 734b002bf5fSMartin Blumenstingl "failed to get amlogic,hhi-sysctrl regmap\n"); 735b002bf5fSMartin Blumenstingl return PTR_ERR(priv->tsc_regmap); 736b002bf5fSMartin Blumenstingl } 737b002bf5fSMartin Blumenstingl 738723a61e0SMartin Blumenstingl read_len = MESON_SAR_ADC_EFUSE_BYTES; 739723a61e0SMartin Blumenstingl buf = nvmem_cell_read(temperature_calib, &read_len); 740723a61e0SMartin Blumenstingl if (IS_ERR(buf)) { 741723a61e0SMartin Blumenstingl dev_err(indio_dev->dev.parent, 742723a61e0SMartin Blumenstingl "failed to read temperature_calib cell\n"); 743723a61e0SMartin Blumenstingl return PTR_ERR(buf); 744723a61e0SMartin Blumenstingl } else if (read_len != MESON_SAR_ADC_EFUSE_BYTES) { 745723a61e0SMartin Blumenstingl kfree(buf); 746723a61e0SMartin Blumenstingl dev_err(indio_dev->dev.parent, 747723a61e0SMartin Blumenstingl "invalid read size of temperature_calib cell\n"); 748723a61e0SMartin Blumenstingl return -EINVAL; 749723a61e0SMartin Blumenstingl } 750723a61e0SMartin Blumenstingl 751723a61e0SMartin Blumenstingl trimming_bits = priv->param->temperature_trimming_bits; 752723a61e0SMartin Blumenstingl trimming_mask = BIT(trimming_bits) - 1; 753723a61e0SMartin Blumenstingl 754723a61e0SMartin Blumenstingl priv->temperature_sensor_calibrated = 755723a61e0SMartin Blumenstingl buf[3] & MESON_SAR_ADC_EFUSE_BYTE3_IS_CALIBRATED; 756723a61e0SMartin Blumenstingl priv->temperature_sensor_coefficient = buf[2] & trimming_mask; 757723a61e0SMartin Blumenstingl 758723a61e0SMartin Blumenstingl upper_adc_val = FIELD_GET(MESON_SAR_ADC_EFUSE_BYTE3_UPPER_ADC_VAL, 759723a61e0SMartin Blumenstingl buf[3]); 760723a61e0SMartin Blumenstingl 761723a61e0SMartin Blumenstingl priv->temperature_sensor_adc_val = buf[2]; 762723a61e0SMartin Blumenstingl priv->temperature_sensor_adc_val |= upper_adc_val << BITS_PER_BYTE; 763723a61e0SMartin Blumenstingl priv->temperature_sensor_adc_val >>= trimming_bits; 764723a61e0SMartin Blumenstingl 765723a61e0SMartin Blumenstingl kfree(buf); 766723a61e0SMartin Blumenstingl 767723a61e0SMartin Blumenstingl return 0; 768723a61e0SMartin Blumenstingl } 769723a61e0SMartin Blumenstingl 7703adbf342SMartin Blumenstingl static int meson_sar_adc_init(struct iio_dev *indio_dev) 7713adbf342SMartin Blumenstingl { 7723adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 773ab569a4cSMartin Blumenstingl int regval, i, ret; 7743adbf342SMartin Blumenstingl 7753adbf342SMartin Blumenstingl /* 7763adbf342SMartin Blumenstingl * make sure we start at CH7 input since the other muxes are only used 7773adbf342SMartin Blumenstingl * for internal calibration. 7783adbf342SMartin Blumenstingl */ 7793adbf342SMartin Blumenstingl meson_sar_adc_set_chan7_mux(indio_dev, CHAN7_MUX_CH7_INPUT); 7803adbf342SMartin Blumenstingl 781057e5a11SMartin Blumenstingl if (priv->param->has_bl30_integration) { 7823adbf342SMartin Blumenstingl /* 7836c76ed31SMartin Blumenstingl * leave sampling delay and the input clocks as configured by 7846c76ed31SMartin Blumenstingl * BL30 to make sure BL30 gets the values it expects when 7856c76ed31SMartin Blumenstingl * reading the temperature sensor. 7863adbf342SMartin Blumenstingl */ 7873adbf342SMartin Blumenstingl regmap_read(priv->regmap, MESON_SAR_ADC_REG3, ®val); 7883adbf342SMartin Blumenstingl if (regval & MESON_SAR_ADC_REG3_BL30_INITIALIZED) 7893adbf342SMartin Blumenstingl return 0; 7906c76ed31SMartin Blumenstingl } 7913adbf342SMartin Blumenstingl 7923adbf342SMartin Blumenstingl meson_sar_adc_stop_sample_engine(indio_dev); 7933adbf342SMartin Blumenstingl 794723a61e0SMartin Blumenstingl /* 795723a61e0SMartin Blumenstingl * disable this bit as seems to be only relevant for Meson6 (based 796723a61e0SMartin Blumenstingl * on the vendor driver), which we don't support at the moment. 797723a61e0SMartin Blumenstingl */ 7983adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, 799723a61e0SMartin Blumenstingl MESON_SAR_ADC_REG0_ADC_TEMP_SEN_SEL, 0); 8003adbf342SMartin Blumenstingl 8013adbf342SMartin Blumenstingl /* disable all channels by default */ 8023adbf342SMartin Blumenstingl regmap_write(priv->regmap, MESON_SAR_ADC_CHAN_LIST, 0x0); 8033adbf342SMartin Blumenstingl 8043adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3, 8053adbf342SMartin Blumenstingl MESON_SAR_ADC_REG3_CTRL_SAMPLING_CLOCK_PHASE, 0); 8063adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3, 8073adbf342SMartin Blumenstingl MESON_SAR_ADC_REG3_CNTL_USE_SC_DLY, 8083adbf342SMartin Blumenstingl MESON_SAR_ADC_REG3_CNTL_USE_SC_DLY); 8093adbf342SMartin Blumenstingl 8103adbf342SMartin Blumenstingl /* delay between two samples = (10+1) * 1uS */ 8113adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY, 8123adbf342SMartin Blumenstingl MESON_SAR_ADC_DELAY_INPUT_DLY_CNT_MASK, 8133adbf342SMartin Blumenstingl FIELD_PREP(MESON_SAR_ADC_DELAY_SAMPLE_DLY_CNT_MASK, 8143adbf342SMartin Blumenstingl 10)); 8153adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY, 8163adbf342SMartin Blumenstingl MESON_SAR_ADC_DELAY_SAMPLE_DLY_SEL_MASK, 8173adbf342SMartin Blumenstingl FIELD_PREP(MESON_SAR_ADC_DELAY_SAMPLE_DLY_SEL_MASK, 8183adbf342SMartin Blumenstingl 0)); 8193adbf342SMartin Blumenstingl 8203adbf342SMartin Blumenstingl /* delay between two samples = (10+1) * 1uS */ 8213adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY, 8223adbf342SMartin Blumenstingl MESON_SAR_ADC_DELAY_INPUT_DLY_CNT_MASK, 8233adbf342SMartin Blumenstingl FIELD_PREP(MESON_SAR_ADC_DELAY_INPUT_DLY_CNT_MASK, 8243adbf342SMartin Blumenstingl 10)); 8253adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY, 8263adbf342SMartin Blumenstingl MESON_SAR_ADC_DELAY_INPUT_DLY_SEL_MASK, 8273adbf342SMartin Blumenstingl FIELD_PREP(MESON_SAR_ADC_DELAY_INPUT_DLY_SEL_MASK, 8283adbf342SMartin Blumenstingl 1)); 8293adbf342SMartin Blumenstingl 830ab569a4cSMartin Blumenstingl /* 831ab569a4cSMartin Blumenstingl * set up the input channel muxes in MESON_SAR_ADC_CHAN_10_SW 832ab569a4cSMartin Blumenstingl * (0 = SAR_ADC_CH0, 1 = SAR_ADC_CH1) 833ab569a4cSMartin Blumenstingl */ 834ab569a4cSMartin Blumenstingl regval = FIELD_PREP(MESON_SAR_ADC_CHAN_10_SW_CHAN0_MUX_SEL_MASK, 0); 835ab569a4cSMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_10_SW, 836ab569a4cSMartin Blumenstingl MESON_SAR_ADC_CHAN_10_SW_CHAN0_MUX_SEL_MASK, 837ab569a4cSMartin Blumenstingl regval); 838ab569a4cSMartin Blumenstingl regval = FIELD_PREP(MESON_SAR_ADC_CHAN_10_SW_CHAN1_MUX_SEL_MASK, 1); 839ab569a4cSMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_10_SW, 840ab569a4cSMartin Blumenstingl MESON_SAR_ADC_CHAN_10_SW_CHAN1_MUX_SEL_MASK, 841ab569a4cSMartin Blumenstingl regval); 842ab569a4cSMartin Blumenstingl 843ab569a4cSMartin Blumenstingl /* 844ab569a4cSMartin Blumenstingl * set up the input channel muxes in MESON_SAR_ADC_AUX_SW 845ab569a4cSMartin Blumenstingl * (2 = SAR_ADC_CH2, 3 = SAR_ADC_CH3, ...) and enable 846ab569a4cSMartin Blumenstingl * MESON_SAR_ADC_AUX_SW_YP_DRIVE_SW and 847ab569a4cSMartin Blumenstingl * MESON_SAR_ADC_AUX_SW_XP_DRIVE_SW like the vendor driver. 848ab569a4cSMartin Blumenstingl */ 849ab569a4cSMartin Blumenstingl regval = 0; 850ab569a4cSMartin Blumenstingl for (i = 2; i <= 7; i++) 851ab569a4cSMartin Blumenstingl regval |= i << MESON_SAR_ADC_AUX_SW_MUX_SEL_CHAN_SHIFT(i); 852ab569a4cSMartin Blumenstingl regval |= MESON_SAR_ADC_AUX_SW_YP_DRIVE_SW; 853ab569a4cSMartin Blumenstingl regval |= MESON_SAR_ADC_AUX_SW_XP_DRIVE_SW; 854ab569a4cSMartin Blumenstingl regmap_write(priv->regmap, MESON_SAR_ADC_AUX_SW, regval); 855ab569a4cSMartin Blumenstingl 856723a61e0SMartin Blumenstingl if (priv->temperature_sensor_calibrated) { 857723a61e0SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELTA_10, 858723a61e0SMartin Blumenstingl MESON_SAR_ADC_DELTA_10_TS_REVE1, 859723a61e0SMartin Blumenstingl MESON_SAR_ADC_DELTA_10_TS_REVE1); 860723a61e0SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELTA_10, 861723a61e0SMartin Blumenstingl MESON_SAR_ADC_DELTA_10_TS_REVE0, 862723a61e0SMartin Blumenstingl MESON_SAR_ADC_DELTA_10_TS_REVE0); 863723a61e0SMartin Blumenstingl 864723a61e0SMartin Blumenstingl /* 865723a61e0SMartin Blumenstingl * set bits [3:0] of the TSC (temperature sensor coefficient) 866723a61e0SMartin Blumenstingl * to get the correct values when reading the temperature. 867723a61e0SMartin Blumenstingl */ 868723a61e0SMartin Blumenstingl regval = FIELD_PREP(MESON_SAR_ADC_DELTA_10_TS_C_MASK, 869723a61e0SMartin Blumenstingl priv->temperature_sensor_coefficient); 870723a61e0SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELTA_10, 871723a61e0SMartin Blumenstingl MESON_SAR_ADC_DELTA_10_TS_C_MASK, regval); 872b002bf5fSMartin Blumenstingl 873b002bf5fSMartin Blumenstingl if (priv->param->temperature_trimming_bits == 5) { 874b002bf5fSMartin Blumenstingl if (priv->temperature_sensor_coefficient & BIT(4)) 875b002bf5fSMartin Blumenstingl regval = MESON_HHI_DPLL_TOP_0_TSC_BIT4; 876b002bf5fSMartin Blumenstingl else 877b002bf5fSMartin Blumenstingl regval = 0; 878b002bf5fSMartin Blumenstingl 879b002bf5fSMartin Blumenstingl /* 880b002bf5fSMartin Blumenstingl * bit [4] (the 5th bit when starting to count at 1) 881b002bf5fSMartin Blumenstingl * of the TSC is located in the HHI register area. 882b002bf5fSMartin Blumenstingl */ 883b002bf5fSMartin Blumenstingl regmap_update_bits(priv->tsc_regmap, 884b002bf5fSMartin Blumenstingl MESON_HHI_DPLL_TOP_0, 885b002bf5fSMartin Blumenstingl MESON_HHI_DPLL_TOP_0_TSC_BIT4, 886b002bf5fSMartin Blumenstingl regval); 887b002bf5fSMartin Blumenstingl } 888723a61e0SMartin Blumenstingl } else { 889723a61e0SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELTA_10, 890723a61e0SMartin Blumenstingl MESON_SAR_ADC_DELTA_10_TS_REVE1, 0); 891723a61e0SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELTA_10, 892723a61e0SMartin Blumenstingl MESON_SAR_ADC_DELTA_10_TS_REVE0, 0); 893723a61e0SMartin Blumenstingl } 894723a61e0SMartin Blumenstingl 8953adbf342SMartin Blumenstingl ret = clk_set_parent(priv->adc_sel_clk, priv->clkin); 8963adbf342SMartin Blumenstingl if (ret) { 8973adbf342SMartin Blumenstingl dev_err(indio_dev->dev.parent, 8983adbf342SMartin Blumenstingl "failed to set adc parent to clkin\n"); 8993adbf342SMartin Blumenstingl return ret; 9003adbf342SMartin Blumenstingl } 9013adbf342SMartin Blumenstingl 902057e5a11SMartin Blumenstingl ret = clk_set_rate(priv->adc_clk, priv->param->clock_rate); 9033adbf342SMartin Blumenstingl if (ret) { 9043adbf342SMartin Blumenstingl dev_err(indio_dev->dev.parent, 9053adbf342SMartin Blumenstingl "failed to set adc clock rate\n"); 9063adbf342SMartin Blumenstingl return ret; 9073adbf342SMartin Blumenstingl } 9083adbf342SMartin Blumenstingl 9093adbf342SMartin Blumenstingl return 0; 9103adbf342SMartin Blumenstingl } 9113adbf342SMartin Blumenstingl 912d85eed9fSMartin Blumenstingl static void meson_sar_adc_set_bandgap(struct iio_dev *indio_dev, bool on_off) 913d85eed9fSMartin Blumenstingl { 914d85eed9fSMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 915057e5a11SMartin Blumenstingl const struct meson_sar_adc_param *param = priv->param; 916d85eed9fSMartin Blumenstingl u32 enable_mask; 917d85eed9fSMartin Blumenstingl 918053ffe3cSYixun Lan if (param->bandgap_reg == MESON_SAR_ADC_REG11) 919d85eed9fSMartin Blumenstingl enable_mask = MESON_SAR_ADC_REG11_BANDGAP_EN; 920d85eed9fSMartin Blumenstingl else 921d85eed9fSMartin Blumenstingl enable_mask = MESON_SAR_ADC_DELTA_10_TS_VBG_EN; 922d85eed9fSMartin Blumenstingl 923053ffe3cSYixun Lan regmap_update_bits(priv->regmap, param->bandgap_reg, enable_mask, 924d85eed9fSMartin Blumenstingl on_off ? enable_mask : 0); 925d85eed9fSMartin Blumenstingl } 926d85eed9fSMartin Blumenstingl 9273adbf342SMartin Blumenstingl static int meson_sar_adc_hw_enable(struct iio_dev *indio_dev) 9283adbf342SMartin Blumenstingl { 9293adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 9303adbf342SMartin Blumenstingl int ret; 9313af10913SHeiner Kallweit u32 regval; 9323adbf342SMartin Blumenstingl 9333adbf342SMartin Blumenstingl ret = meson_sar_adc_lock(indio_dev); 9343adbf342SMartin Blumenstingl if (ret) 9353adbf342SMartin Blumenstingl goto err_lock; 9363adbf342SMartin Blumenstingl 9373adbf342SMartin Blumenstingl ret = regulator_enable(priv->vref); 9383adbf342SMartin Blumenstingl if (ret < 0) { 9393adbf342SMartin Blumenstingl dev_err(indio_dev->dev.parent, 9403adbf342SMartin Blumenstingl "failed to enable vref regulator\n"); 9413adbf342SMartin Blumenstingl goto err_vref; 9423adbf342SMartin Blumenstingl } 9433adbf342SMartin Blumenstingl 9443adbf342SMartin Blumenstingl ret = clk_prepare_enable(priv->core_clk); 9453adbf342SMartin Blumenstingl if (ret) { 9463adbf342SMartin Blumenstingl dev_err(indio_dev->dev.parent, "failed to enable core clk\n"); 9473adbf342SMartin Blumenstingl goto err_core_clk; 9483adbf342SMartin Blumenstingl } 9493adbf342SMartin Blumenstingl 9503af10913SHeiner Kallweit regval = FIELD_PREP(MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, 1); 9513af10913SHeiner Kallweit regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, 9523af10913SHeiner Kallweit MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, regval); 953d85eed9fSMartin Blumenstingl 954d85eed9fSMartin Blumenstingl meson_sar_adc_set_bandgap(indio_dev, true); 955d85eed9fSMartin Blumenstingl 9563adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3, 9573adbf342SMartin Blumenstingl MESON_SAR_ADC_REG3_ADC_EN, 9583adbf342SMartin Blumenstingl MESON_SAR_ADC_REG3_ADC_EN); 9593adbf342SMartin Blumenstingl 9603adbf342SMartin Blumenstingl udelay(5); 9613adbf342SMartin Blumenstingl 9623adbf342SMartin Blumenstingl ret = clk_prepare_enable(priv->adc_clk); 9633adbf342SMartin Blumenstingl if (ret) { 9643adbf342SMartin Blumenstingl dev_err(indio_dev->dev.parent, "failed to enable adc clk\n"); 9653adbf342SMartin Blumenstingl goto err_adc_clk; 9663adbf342SMartin Blumenstingl } 9673adbf342SMartin Blumenstingl 9683adbf342SMartin Blumenstingl meson_sar_adc_unlock(indio_dev); 9693adbf342SMartin Blumenstingl 9703adbf342SMartin Blumenstingl return 0; 9713adbf342SMartin Blumenstingl 9723adbf342SMartin Blumenstingl err_adc_clk: 9733adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3, 9743adbf342SMartin Blumenstingl MESON_SAR_ADC_REG3_ADC_EN, 0); 975d85eed9fSMartin Blumenstingl meson_sar_adc_set_bandgap(indio_dev, false); 9763adbf342SMartin Blumenstingl clk_disable_unprepare(priv->core_clk); 9773adbf342SMartin Blumenstingl err_core_clk: 9783adbf342SMartin Blumenstingl regulator_disable(priv->vref); 9793adbf342SMartin Blumenstingl err_vref: 9803adbf342SMartin Blumenstingl meson_sar_adc_unlock(indio_dev); 9813adbf342SMartin Blumenstingl err_lock: 9823adbf342SMartin Blumenstingl return ret; 9833adbf342SMartin Blumenstingl } 9843adbf342SMartin Blumenstingl 9853adbf342SMartin Blumenstingl static int meson_sar_adc_hw_disable(struct iio_dev *indio_dev) 9863adbf342SMartin Blumenstingl { 9873adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 9883adbf342SMartin Blumenstingl int ret; 9893adbf342SMartin Blumenstingl 9903adbf342SMartin Blumenstingl ret = meson_sar_adc_lock(indio_dev); 9913adbf342SMartin Blumenstingl if (ret) 9923adbf342SMartin Blumenstingl return ret; 9933adbf342SMartin Blumenstingl 9943adbf342SMartin Blumenstingl clk_disable_unprepare(priv->adc_clk); 9953adbf342SMartin Blumenstingl 9963adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3, 9973adbf342SMartin Blumenstingl MESON_SAR_ADC_REG3_ADC_EN, 0); 998d85eed9fSMartin Blumenstingl 999d85eed9fSMartin Blumenstingl meson_sar_adc_set_bandgap(indio_dev, false); 10003adbf342SMartin Blumenstingl 10013adbf342SMartin Blumenstingl clk_disable_unprepare(priv->core_clk); 10023adbf342SMartin Blumenstingl 10033adbf342SMartin Blumenstingl regulator_disable(priv->vref); 10043adbf342SMartin Blumenstingl 10053adbf342SMartin Blumenstingl meson_sar_adc_unlock(indio_dev); 10063adbf342SMartin Blumenstingl 10073adbf342SMartin Blumenstingl return 0; 10083adbf342SMartin Blumenstingl } 10093adbf342SMartin Blumenstingl 10103af10913SHeiner Kallweit static irqreturn_t meson_sar_adc_irq(int irq, void *data) 10113af10913SHeiner Kallweit { 10123af10913SHeiner Kallweit struct iio_dev *indio_dev = data; 10133af10913SHeiner Kallweit struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 10143af10913SHeiner Kallweit unsigned int cnt, threshold; 10153af10913SHeiner Kallweit u32 regval; 10163af10913SHeiner Kallweit 10173af10913SHeiner Kallweit regmap_read(priv->regmap, MESON_SAR_ADC_REG0, ®val); 10183af10913SHeiner Kallweit cnt = FIELD_GET(MESON_SAR_ADC_REG0_FIFO_COUNT_MASK, regval); 10193af10913SHeiner Kallweit threshold = FIELD_GET(MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, regval); 10203af10913SHeiner Kallweit 10213af10913SHeiner Kallweit if (cnt < threshold) 10223af10913SHeiner Kallweit return IRQ_NONE; 10233af10913SHeiner Kallweit 10243af10913SHeiner Kallweit complete(&priv->done); 10253af10913SHeiner Kallweit 10263af10913SHeiner Kallweit return IRQ_HANDLED; 10273af10913SHeiner Kallweit } 10283af10913SHeiner Kallweit 102948ba7c3cSHeiner Kallweit static int meson_sar_adc_calib(struct iio_dev *indio_dev) 103048ba7c3cSHeiner Kallweit { 103148ba7c3cSHeiner Kallweit struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 103248ba7c3cSHeiner Kallweit int ret, nominal0, nominal1, value0, value1; 103348ba7c3cSHeiner Kallweit 103448ba7c3cSHeiner Kallweit /* use points 25% and 75% for calibration */ 1035057e5a11SMartin Blumenstingl nominal0 = (1 << priv->param->resolution) / 4; 1036057e5a11SMartin Blumenstingl nominal1 = (1 << priv->param->resolution) * 3 / 4; 103748ba7c3cSHeiner Kallweit 103848ba7c3cSHeiner Kallweit meson_sar_adc_set_chan7_mux(indio_dev, CHAN7_MUX_VDD_DIV4); 103948ba7c3cSHeiner Kallweit usleep_range(10, 20); 104048ba7c3cSHeiner Kallweit ret = meson_sar_adc_get_sample(indio_dev, 1041bdd4b07fSMartin Blumenstingl &indio_dev->channels[7], 104248ba7c3cSHeiner Kallweit MEAN_AVERAGING, EIGHT_SAMPLES, &value0); 104348ba7c3cSHeiner Kallweit if (ret < 0) 104448ba7c3cSHeiner Kallweit goto out; 104548ba7c3cSHeiner Kallweit 104648ba7c3cSHeiner Kallweit meson_sar_adc_set_chan7_mux(indio_dev, CHAN7_MUX_VDD_MUL3_DIV4); 104748ba7c3cSHeiner Kallweit usleep_range(10, 20); 104848ba7c3cSHeiner Kallweit ret = meson_sar_adc_get_sample(indio_dev, 1049bdd4b07fSMartin Blumenstingl &indio_dev->channels[7], 105048ba7c3cSHeiner Kallweit MEAN_AVERAGING, EIGHT_SAMPLES, &value1); 105148ba7c3cSHeiner Kallweit if (ret < 0) 105248ba7c3cSHeiner Kallweit goto out; 105348ba7c3cSHeiner Kallweit 105448ba7c3cSHeiner Kallweit if (value1 <= value0) { 105548ba7c3cSHeiner Kallweit ret = -EINVAL; 105648ba7c3cSHeiner Kallweit goto out; 105748ba7c3cSHeiner Kallweit } 105848ba7c3cSHeiner Kallweit 105948ba7c3cSHeiner Kallweit priv->calibscale = div_s64((nominal1 - nominal0) * (s64)MILLION, 106048ba7c3cSHeiner Kallweit value1 - value0); 106148ba7c3cSHeiner Kallweit priv->calibbias = nominal0 - div_s64((s64)value0 * priv->calibscale, 106248ba7c3cSHeiner Kallweit MILLION); 106348ba7c3cSHeiner Kallweit ret = 0; 106448ba7c3cSHeiner Kallweit out: 106548ba7c3cSHeiner Kallweit meson_sar_adc_set_chan7_mux(indio_dev, CHAN7_MUX_CH7_INPUT); 106648ba7c3cSHeiner Kallweit 106748ba7c3cSHeiner Kallweit return ret; 106848ba7c3cSHeiner Kallweit } 106948ba7c3cSHeiner Kallweit 10703adbf342SMartin Blumenstingl static const struct iio_info meson_sar_adc_iio_info = { 10713adbf342SMartin Blumenstingl .read_raw = meson_sar_adc_iio_info_read_raw, 10723adbf342SMartin Blumenstingl }; 10733adbf342SMartin Blumenstingl 1074053ffe3cSYixun Lan static const struct meson_sar_adc_param meson_sar_adc_meson8_param = { 10756c76ed31SMartin Blumenstingl .has_bl30_integration = false, 1076fda29dbaSMartin Blumenstingl .clock_rate = 1150000, 1077d85eed9fSMartin Blumenstingl .bandgap_reg = MESON_SAR_ADC_DELTA_10, 107896748823SMartin Blumenstingl .regmap_config = &meson_sar_adc_regmap_config_meson8, 10796c76ed31SMartin Blumenstingl .resolution = 10, 1080723a61e0SMartin Blumenstingl .temperature_trimming_bits = 4, 1081723a61e0SMartin Blumenstingl .temperature_multiplier = 18 * 10000, 1082723a61e0SMartin Blumenstingl .temperature_divider = 1024 * 10 * 85, 1083723a61e0SMartin Blumenstingl }; 1084723a61e0SMartin Blumenstingl 1085723a61e0SMartin Blumenstingl static const struct meson_sar_adc_param meson_sar_adc_meson8b_param = { 1086723a61e0SMartin Blumenstingl .has_bl30_integration = false, 1087723a61e0SMartin Blumenstingl .clock_rate = 1150000, 1088723a61e0SMartin Blumenstingl .bandgap_reg = MESON_SAR_ADC_DELTA_10, 1089723a61e0SMartin Blumenstingl .regmap_config = &meson_sar_adc_regmap_config_meson8, 1090723a61e0SMartin Blumenstingl .resolution = 10, 1091b002bf5fSMartin Blumenstingl .temperature_trimming_bits = 5, 1092b002bf5fSMartin Blumenstingl .temperature_multiplier = 10, 1093b002bf5fSMartin Blumenstingl .temperature_divider = 32, 1094053ffe3cSYixun Lan }; 1095053ffe3cSYixun Lan 1096053ffe3cSYixun Lan static const struct meson_sar_adc_param meson_sar_adc_gxbb_param = { 1097053ffe3cSYixun Lan .has_bl30_integration = true, 1098053ffe3cSYixun Lan .clock_rate = 1200000, 1099053ffe3cSYixun Lan .bandgap_reg = MESON_SAR_ADC_REG11, 1100053ffe3cSYixun Lan .regmap_config = &meson_sar_adc_regmap_config_gxbb, 1101053ffe3cSYixun Lan .resolution = 10, 1102053ffe3cSYixun Lan }; 1103053ffe3cSYixun Lan 1104053ffe3cSYixun Lan static const struct meson_sar_adc_param meson_sar_adc_gxl_param = { 1105053ffe3cSYixun Lan .has_bl30_integration = true, 1106053ffe3cSYixun Lan .clock_rate = 1200000, 1107053ffe3cSYixun Lan .bandgap_reg = MESON_SAR_ADC_REG11, 1108053ffe3cSYixun Lan .regmap_config = &meson_sar_adc_regmap_config_gxbb, 1109053ffe3cSYixun Lan .resolution = 12, 1110053ffe3cSYixun Lan }; 1111053ffe3cSYixun Lan 1112053ffe3cSYixun Lan static const struct meson_sar_adc_data meson_sar_adc_meson8_data = { 1113053ffe3cSYixun Lan .param = &meson_sar_adc_meson8_param, 11146c76ed31SMartin Blumenstingl .name = "meson-meson8-saradc", 11156c76ed31SMartin Blumenstingl }; 11166c76ed31SMartin Blumenstingl 11176c76ed31SMartin Blumenstingl static const struct meson_sar_adc_data meson_sar_adc_meson8b_data = { 1118723a61e0SMartin Blumenstingl .param = &meson_sar_adc_meson8b_param, 11196c76ed31SMartin Blumenstingl .name = "meson-meson8b-saradc", 11206c76ed31SMartin Blumenstingl }; 11216c76ed31SMartin Blumenstingl 1122ffc0d638SMartin Blumenstingl static const struct meson_sar_adc_data meson_sar_adc_meson8m2_data = { 1123723a61e0SMartin Blumenstingl .param = &meson_sar_adc_meson8b_param, 1124ffc0d638SMartin Blumenstingl .name = "meson-meson8m2-saradc", 1125ffc0d638SMartin Blumenstingl }; 1126ffc0d638SMartin Blumenstingl 1127c1c2de37SMartin Blumenstingl static const struct meson_sar_adc_data meson_sar_adc_gxbb_data = { 1128053ffe3cSYixun Lan .param = &meson_sar_adc_gxbb_param, 11293adbf342SMartin Blumenstingl .name = "meson-gxbb-saradc", 11303adbf342SMartin Blumenstingl }; 11313adbf342SMartin Blumenstingl 1132c1c2de37SMartin Blumenstingl static const struct meson_sar_adc_data meson_sar_adc_gxl_data = { 1133053ffe3cSYixun Lan .param = &meson_sar_adc_gxl_param, 11343adbf342SMartin Blumenstingl .name = "meson-gxl-saradc", 11353adbf342SMartin Blumenstingl }; 11363adbf342SMartin Blumenstingl 1137c1c2de37SMartin Blumenstingl static const struct meson_sar_adc_data meson_sar_adc_gxm_data = { 1138053ffe3cSYixun Lan .param = &meson_sar_adc_gxl_param, 11393adbf342SMartin Blumenstingl .name = "meson-gxm-saradc", 11403adbf342SMartin Blumenstingl }; 11413adbf342SMartin Blumenstingl 1142ff632ddaSXingyu Chen static const struct meson_sar_adc_data meson_sar_adc_axg_data = { 1143ff632ddaSXingyu Chen .param = &meson_sar_adc_gxl_param, 1144ff632ddaSXingyu Chen .name = "meson-axg-saradc", 1145ff632ddaSXingyu Chen }; 1146ff632ddaSXingyu Chen 1147e415a165SNeil Armstrong static const struct meson_sar_adc_data meson_sar_adc_g12a_data = { 1148e415a165SNeil Armstrong .param = &meson_sar_adc_gxl_param, 1149e415a165SNeil Armstrong .name = "meson-g12a-saradc", 1150e415a165SNeil Armstrong }; 1151e415a165SNeil Armstrong 11523adbf342SMartin Blumenstingl static const struct of_device_id meson_sar_adc_of_match[] = { 11533adbf342SMartin Blumenstingl { 11546c76ed31SMartin Blumenstingl .compatible = "amlogic,meson8-saradc", 11556c76ed31SMartin Blumenstingl .data = &meson_sar_adc_meson8_data, 11566c76ed31SMartin Blumenstingl }, 11576c76ed31SMartin Blumenstingl { 11586c76ed31SMartin Blumenstingl .compatible = "amlogic,meson8b-saradc", 11596c76ed31SMartin Blumenstingl .data = &meson_sar_adc_meson8b_data, 11606c76ed31SMartin Blumenstingl }, 11616c76ed31SMartin Blumenstingl { 1162ffc0d638SMartin Blumenstingl .compatible = "amlogic,meson8m2-saradc", 1163ffc0d638SMartin Blumenstingl .data = &meson_sar_adc_meson8m2_data, 1164ffc0d638SMartin Blumenstingl }, 1165ffc0d638SMartin Blumenstingl { 11663adbf342SMartin Blumenstingl .compatible = "amlogic,meson-gxbb-saradc", 11673adbf342SMartin Blumenstingl .data = &meson_sar_adc_gxbb_data, 11683adbf342SMartin Blumenstingl }, { 11693adbf342SMartin Blumenstingl .compatible = "amlogic,meson-gxl-saradc", 11703adbf342SMartin Blumenstingl .data = &meson_sar_adc_gxl_data, 11713adbf342SMartin Blumenstingl }, { 11723adbf342SMartin Blumenstingl .compatible = "amlogic,meson-gxm-saradc", 11733adbf342SMartin Blumenstingl .data = &meson_sar_adc_gxm_data, 1174ff632ddaSXingyu Chen }, { 1175ff632ddaSXingyu Chen .compatible = "amlogic,meson-axg-saradc", 1176ff632ddaSXingyu Chen .data = &meson_sar_adc_axg_data, 1177e415a165SNeil Armstrong }, { 1178e415a165SNeil Armstrong .compatible = "amlogic,meson-g12a-saradc", 1179e415a165SNeil Armstrong .data = &meson_sar_adc_g12a_data, 11803adbf342SMartin Blumenstingl }, 11813adbf342SMartin Blumenstingl {}, 11823adbf342SMartin Blumenstingl }; 11833adbf342SMartin Blumenstingl MODULE_DEVICE_TABLE(of, meson_sar_adc_of_match); 11843adbf342SMartin Blumenstingl 11853adbf342SMartin Blumenstingl static int meson_sar_adc_probe(struct platform_device *pdev) 11863adbf342SMartin Blumenstingl { 1187234c64a2SMartin Blumenstingl const struct meson_sar_adc_data *match_data; 11883adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv; 11893adbf342SMartin Blumenstingl struct iio_dev *indio_dev; 11903adbf342SMartin Blumenstingl struct resource *res; 11913adbf342SMartin Blumenstingl void __iomem *base; 11923af10913SHeiner Kallweit int irq, ret; 11933adbf342SMartin Blumenstingl 11943adbf342SMartin Blumenstingl indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*priv)); 11953adbf342SMartin Blumenstingl if (!indio_dev) { 11963adbf342SMartin Blumenstingl dev_err(&pdev->dev, "failed allocating iio device\n"); 11973adbf342SMartin Blumenstingl return -ENOMEM; 11983adbf342SMartin Blumenstingl } 11993adbf342SMartin Blumenstingl 12003adbf342SMartin Blumenstingl priv = iio_priv(indio_dev); 12013af10913SHeiner Kallweit init_completion(&priv->done); 12023adbf342SMartin Blumenstingl 1203234c64a2SMartin Blumenstingl match_data = of_device_get_match_data(&pdev->dev); 1204234c64a2SMartin Blumenstingl if (!match_data) { 1205234c64a2SMartin Blumenstingl dev_err(&pdev->dev, "failed to get match data\n"); 12062f9aeeedSGustavo A. R. Silva return -ENODEV; 12072f9aeeedSGustavo A. R. Silva } 12082f9aeeedSGustavo A. R. Silva 1209057e5a11SMartin Blumenstingl priv->param = match_data->param; 12103adbf342SMartin Blumenstingl 1211057e5a11SMartin Blumenstingl indio_dev->name = match_data->name; 12123adbf342SMartin Blumenstingl indio_dev->dev.parent = &pdev->dev; 12133adbf342SMartin Blumenstingl indio_dev->dev.of_node = pdev->dev.of_node; 12143adbf342SMartin Blumenstingl indio_dev->modes = INDIO_DIRECT_MODE; 12153adbf342SMartin Blumenstingl indio_dev->info = &meson_sar_adc_iio_info; 12163adbf342SMartin Blumenstingl 12173adbf342SMartin Blumenstingl res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 12183adbf342SMartin Blumenstingl base = devm_ioremap_resource(&pdev->dev, res); 12193adbf342SMartin Blumenstingl if (IS_ERR(base)) 12203adbf342SMartin Blumenstingl return PTR_ERR(base); 12213adbf342SMartin Blumenstingl 1222de10ac47SRemi Pommarel priv->regmap = devm_regmap_init_mmio(&pdev->dev, base, 1223de10ac47SRemi Pommarel priv->param->regmap_config); 1224de10ac47SRemi Pommarel if (IS_ERR(priv->regmap)) 1225de10ac47SRemi Pommarel return PTR_ERR(priv->regmap); 1226de10ac47SRemi Pommarel 12273af10913SHeiner Kallweit irq = irq_of_parse_and_map(pdev->dev.of_node, 0); 12283af10913SHeiner Kallweit if (!irq) 12293af10913SHeiner Kallweit return -EINVAL; 12303af10913SHeiner Kallweit 12313af10913SHeiner Kallweit ret = devm_request_irq(&pdev->dev, irq, meson_sar_adc_irq, IRQF_SHARED, 12323af10913SHeiner Kallweit dev_name(&pdev->dev), indio_dev); 12333af10913SHeiner Kallweit if (ret) 12343af10913SHeiner Kallweit return ret; 12353af10913SHeiner Kallweit 12363adbf342SMartin Blumenstingl priv->clkin = devm_clk_get(&pdev->dev, "clkin"); 12373adbf342SMartin Blumenstingl if (IS_ERR(priv->clkin)) { 12383adbf342SMartin Blumenstingl dev_err(&pdev->dev, "failed to get clkin\n"); 12393adbf342SMartin Blumenstingl return PTR_ERR(priv->clkin); 12403adbf342SMartin Blumenstingl } 12413adbf342SMartin Blumenstingl 12423adbf342SMartin Blumenstingl priv->core_clk = devm_clk_get(&pdev->dev, "core"); 12433adbf342SMartin Blumenstingl if (IS_ERR(priv->core_clk)) { 12443adbf342SMartin Blumenstingl dev_err(&pdev->dev, "failed to get core clk\n"); 12453adbf342SMartin Blumenstingl return PTR_ERR(priv->core_clk); 12463adbf342SMartin Blumenstingl } 12473adbf342SMartin Blumenstingl 12483adbf342SMartin Blumenstingl priv->adc_clk = devm_clk_get(&pdev->dev, "adc_clk"); 12493adbf342SMartin Blumenstingl if (IS_ERR(priv->adc_clk)) { 12503adbf342SMartin Blumenstingl if (PTR_ERR(priv->adc_clk) == -ENOENT) { 12513adbf342SMartin Blumenstingl priv->adc_clk = NULL; 12523adbf342SMartin Blumenstingl } else { 12533adbf342SMartin Blumenstingl dev_err(&pdev->dev, "failed to get adc clk\n"); 12543adbf342SMartin Blumenstingl return PTR_ERR(priv->adc_clk); 12553adbf342SMartin Blumenstingl } 12563adbf342SMartin Blumenstingl } 12573adbf342SMartin Blumenstingl 12583adbf342SMartin Blumenstingl priv->adc_sel_clk = devm_clk_get(&pdev->dev, "adc_sel"); 12593adbf342SMartin Blumenstingl if (IS_ERR(priv->adc_sel_clk)) { 12603adbf342SMartin Blumenstingl if (PTR_ERR(priv->adc_sel_clk) == -ENOENT) { 12613adbf342SMartin Blumenstingl priv->adc_sel_clk = NULL; 12623adbf342SMartin Blumenstingl } else { 12633adbf342SMartin Blumenstingl dev_err(&pdev->dev, "failed to get adc_sel clk\n"); 12643adbf342SMartin Blumenstingl return PTR_ERR(priv->adc_sel_clk); 12653adbf342SMartin Blumenstingl } 12663adbf342SMartin Blumenstingl } 12673adbf342SMartin Blumenstingl 12683adbf342SMartin Blumenstingl /* on pre-GXBB SoCs the SAR ADC itself provides the ADC clock: */ 12693adbf342SMartin Blumenstingl if (!priv->adc_clk) { 12703adbf342SMartin Blumenstingl ret = meson_sar_adc_clk_init(indio_dev, base); 12713adbf342SMartin Blumenstingl if (ret) 12723adbf342SMartin Blumenstingl return ret; 12733adbf342SMartin Blumenstingl } 12743adbf342SMartin Blumenstingl 12753adbf342SMartin Blumenstingl priv->vref = devm_regulator_get(&pdev->dev, "vref"); 12763adbf342SMartin Blumenstingl if (IS_ERR(priv->vref)) { 12773adbf342SMartin Blumenstingl dev_err(&pdev->dev, "failed to get vref regulator\n"); 12783adbf342SMartin Blumenstingl return PTR_ERR(priv->vref); 12793adbf342SMartin Blumenstingl } 12803adbf342SMartin Blumenstingl 128148ba7c3cSHeiner Kallweit priv->calibscale = MILLION; 128248ba7c3cSHeiner Kallweit 1283723a61e0SMartin Blumenstingl if (priv->param->temperature_trimming_bits) { 1284723a61e0SMartin Blumenstingl ret = meson_sar_adc_temp_sensor_init(indio_dev); 1285723a61e0SMartin Blumenstingl if (ret) 1286723a61e0SMartin Blumenstingl return ret; 1287723a61e0SMartin Blumenstingl } 1288723a61e0SMartin Blumenstingl 1289723a61e0SMartin Blumenstingl if (priv->temperature_sensor_calibrated) { 1290723a61e0SMartin Blumenstingl indio_dev->channels = meson_sar_adc_and_temp_iio_channels; 1291723a61e0SMartin Blumenstingl indio_dev->num_channels = 1292723a61e0SMartin Blumenstingl ARRAY_SIZE(meson_sar_adc_and_temp_iio_channels); 1293723a61e0SMartin Blumenstingl } else { 1294723a61e0SMartin Blumenstingl indio_dev->channels = meson_sar_adc_iio_channels; 1295723a61e0SMartin Blumenstingl indio_dev->num_channels = 1296723a61e0SMartin Blumenstingl ARRAY_SIZE(meson_sar_adc_iio_channels); 1297723a61e0SMartin Blumenstingl } 1298723a61e0SMartin Blumenstingl 12993adbf342SMartin Blumenstingl ret = meson_sar_adc_init(indio_dev); 13003adbf342SMartin Blumenstingl if (ret) 13013adbf342SMartin Blumenstingl goto err; 13023adbf342SMartin Blumenstingl 13033adbf342SMartin Blumenstingl ret = meson_sar_adc_hw_enable(indio_dev); 13043adbf342SMartin Blumenstingl if (ret) 13053adbf342SMartin Blumenstingl goto err; 13063adbf342SMartin Blumenstingl 130748ba7c3cSHeiner Kallweit ret = meson_sar_adc_calib(indio_dev); 130848ba7c3cSHeiner Kallweit if (ret) 130948ba7c3cSHeiner Kallweit dev_warn(&pdev->dev, "calibration failed\n"); 131048ba7c3cSHeiner Kallweit 13113adbf342SMartin Blumenstingl platform_set_drvdata(pdev, indio_dev); 13123adbf342SMartin Blumenstingl 13133adbf342SMartin Blumenstingl ret = iio_device_register(indio_dev); 13143adbf342SMartin Blumenstingl if (ret) 13153adbf342SMartin Blumenstingl goto err_hw; 13163adbf342SMartin Blumenstingl 13173adbf342SMartin Blumenstingl return 0; 13183adbf342SMartin Blumenstingl 13193adbf342SMartin Blumenstingl err_hw: 13203adbf342SMartin Blumenstingl meson_sar_adc_hw_disable(indio_dev); 13213adbf342SMartin Blumenstingl err: 13223adbf342SMartin Blumenstingl return ret; 13233adbf342SMartin Blumenstingl } 13243adbf342SMartin Blumenstingl 13253adbf342SMartin Blumenstingl static int meson_sar_adc_remove(struct platform_device *pdev) 13263adbf342SMartin Blumenstingl { 13273adbf342SMartin Blumenstingl struct iio_dev *indio_dev = platform_get_drvdata(pdev); 13283adbf342SMartin Blumenstingl 13293adbf342SMartin Blumenstingl iio_device_unregister(indio_dev); 13303adbf342SMartin Blumenstingl 13313adbf342SMartin Blumenstingl return meson_sar_adc_hw_disable(indio_dev); 13323adbf342SMartin Blumenstingl } 13333adbf342SMartin Blumenstingl 13343adbf342SMartin Blumenstingl static int __maybe_unused meson_sar_adc_suspend(struct device *dev) 13353adbf342SMartin Blumenstingl { 13363adbf342SMartin Blumenstingl struct iio_dev *indio_dev = dev_get_drvdata(dev); 13373adbf342SMartin Blumenstingl 13383adbf342SMartin Blumenstingl return meson_sar_adc_hw_disable(indio_dev); 13393adbf342SMartin Blumenstingl } 13403adbf342SMartin Blumenstingl 13413adbf342SMartin Blumenstingl static int __maybe_unused meson_sar_adc_resume(struct device *dev) 13423adbf342SMartin Blumenstingl { 13433adbf342SMartin Blumenstingl struct iio_dev *indio_dev = dev_get_drvdata(dev); 13443adbf342SMartin Blumenstingl 13453adbf342SMartin Blumenstingl return meson_sar_adc_hw_enable(indio_dev); 13463adbf342SMartin Blumenstingl } 13473adbf342SMartin Blumenstingl 13483adbf342SMartin Blumenstingl static SIMPLE_DEV_PM_OPS(meson_sar_adc_pm_ops, 13493adbf342SMartin Blumenstingl meson_sar_adc_suspend, meson_sar_adc_resume); 13503adbf342SMartin Blumenstingl 13513adbf342SMartin Blumenstingl static struct platform_driver meson_sar_adc_driver = { 13523adbf342SMartin Blumenstingl .probe = meson_sar_adc_probe, 13533adbf342SMartin Blumenstingl .remove = meson_sar_adc_remove, 13543adbf342SMartin Blumenstingl .driver = { 13553adbf342SMartin Blumenstingl .name = "meson-saradc", 13563adbf342SMartin Blumenstingl .of_match_table = meson_sar_adc_of_match, 13573adbf342SMartin Blumenstingl .pm = &meson_sar_adc_pm_ops, 13583adbf342SMartin Blumenstingl }, 13593adbf342SMartin Blumenstingl }; 13603adbf342SMartin Blumenstingl 13613adbf342SMartin Blumenstingl module_platform_driver(meson_sar_adc_driver); 13623adbf342SMartin Blumenstingl 13633adbf342SMartin Blumenstingl MODULE_AUTHOR("Martin Blumenstingl <martin.blumenstingl@googlemail.com>"); 13643adbf342SMartin Blumenstingl MODULE_DESCRIPTION("Amlogic Meson SAR ADC driver"); 13653adbf342SMartin Blumenstingl MODULE_LICENSE("GPL v2"); 1366