13adbf342SMartin Blumenstingl /* 23adbf342SMartin Blumenstingl * Amlogic Meson Successive Approximation Register (SAR) A/D Converter 33adbf342SMartin Blumenstingl * 43adbf342SMartin Blumenstingl * Copyright (C) 2017 Martin Blumenstingl <martin.blumenstingl@googlemail.com> 53adbf342SMartin Blumenstingl * 63adbf342SMartin Blumenstingl * This program is free software; you can redistribute it and/or modify 73adbf342SMartin Blumenstingl * it under the terms of the GNU General Public License version 2 as 83adbf342SMartin Blumenstingl * published by the Free Software Foundation. 93adbf342SMartin Blumenstingl * 103adbf342SMartin Blumenstingl * You should have received a copy of the GNU General Public License 113adbf342SMartin Blumenstingl * along with this program. If not, see <http://www.gnu.org/licenses/>. 123adbf342SMartin Blumenstingl */ 133adbf342SMartin Blumenstingl 143adbf342SMartin Blumenstingl #include <linux/bitfield.h> 153adbf342SMartin Blumenstingl #include <linux/clk.h> 163adbf342SMartin Blumenstingl #include <linux/clk-provider.h> 173adbf342SMartin Blumenstingl #include <linux/delay.h> 183adbf342SMartin Blumenstingl #include <linux/io.h> 193adbf342SMartin Blumenstingl #include <linux/iio/iio.h> 203adbf342SMartin Blumenstingl #include <linux/module.h> 21723a61e0SMartin Blumenstingl #include <linux/nvmem-consumer.h> 223af10913SHeiner Kallweit #include <linux/interrupt.h> 233adbf342SMartin Blumenstingl #include <linux/of.h> 243af10913SHeiner Kallweit #include <linux/of_irq.h> 253adbf342SMartin Blumenstingl #include <linux/of_device.h> 263adbf342SMartin Blumenstingl #include <linux/platform_device.h> 273adbf342SMartin Blumenstingl #include <linux/regmap.h> 283adbf342SMartin Blumenstingl #include <linux/regulator/consumer.h> 293adbf342SMartin Blumenstingl 303adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0 0x00 313adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_PANEL_DETECT BIT(31) 323adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_BUSY_MASK GENMASK(30, 28) 333adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_DELTA_BUSY BIT(30) 343adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_AVG_BUSY BIT(29) 353adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_SAMPLE_BUSY BIT(28) 363adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_FIFO_FULL BIT(27) 373adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_FIFO_EMPTY BIT(26) 383adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_FIFO_COUNT_MASK GENMASK(25, 21) 393adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_ADC_BIAS_CTRL_MASK GENMASK(20, 19) 403adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_CURR_CHAN_ID_MASK GENMASK(18, 16) 413adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_ADC_TEMP_SEN_SEL BIT(15) 423adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_SAMPLING_STOP BIT(14) 433adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_CHAN_DELTA_EN_MASK GENMASK(13, 12) 443adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_DETECT_IRQ_POL BIT(10) 453adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_DETECT_IRQ_EN BIT(9) 463adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK GENMASK(8, 4) 473adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_FIFO_IRQ_EN BIT(3) 483adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_SAMPLING_START BIT(2) 493adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_CONTINUOUS_EN BIT(1) 503adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE BIT(0) 513adbf342SMartin Blumenstingl 523adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_LIST 0x04 533adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_LIST_MAX_INDEX_MASK GENMASK(26, 24) 543adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_LIST_ENTRY_MASK(_chan) \ 553adbf342SMartin Blumenstingl (GENMASK(2, 0) << ((_chan) * 3)) 563adbf342SMartin Blumenstingl 573adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AVG_CNTL 0x08 583adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AVG_CNTL_AVG_MODE_SHIFT(_chan) \ 593adbf342SMartin Blumenstingl (16 + ((_chan) * 2)) 603adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AVG_CNTL_AVG_MODE_MASK(_chan) \ 613adbf342SMartin Blumenstingl (GENMASK(17, 16) << ((_chan) * 2)) 623adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AVG_CNTL_NUM_SAMPLES_SHIFT(_chan) \ 633adbf342SMartin Blumenstingl (0 + ((_chan) * 2)) 643adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AVG_CNTL_NUM_SAMPLES_MASK(_chan) \ 653adbf342SMartin Blumenstingl (GENMASK(1, 0) << ((_chan) * 2)) 663adbf342SMartin Blumenstingl 673adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3 0x0c 683adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_CNTL_USE_SC_DLY BIT(31) 693adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_CLK_EN BIT(30) 703adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_BL30_INITIALIZED BIT(28) 713adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_CTRL_CONT_RING_COUNTER_EN BIT(27) 723adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_CTRL_SAMPLING_CLOCK_PHASE BIT(26) 733adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_CTRL_CHAN7_MUX_SEL_MASK GENMASK(25, 23) 743adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_DETECT_EN BIT(22) 753adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_ADC_EN BIT(21) 763adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_PANEL_DETECT_COUNT_MASK GENMASK(20, 18) 773adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_PANEL_DETECT_FILTER_TB_MASK GENMASK(17, 16) 783adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_ADC_CLK_DIV_SHIFT 10 793adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_ADC_CLK_DIV_WIDTH 5 803adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_BLOCK_DLY_SEL_MASK GENMASK(9, 8) 813adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_BLOCK_DLY_MASK GENMASK(7, 0) 823adbf342SMartin Blumenstingl 833adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELAY 0x10 843adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELAY_INPUT_DLY_SEL_MASK GENMASK(25, 24) 853adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELAY_BL30_BUSY BIT(15) 863adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELAY_KERNEL_BUSY BIT(14) 873adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELAY_INPUT_DLY_CNT_MASK GENMASK(23, 16) 883adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELAY_SAMPLE_DLY_SEL_MASK GENMASK(9, 8) 893adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELAY_SAMPLE_DLY_CNT_MASK GENMASK(7, 0) 903adbf342SMartin Blumenstingl 913adbf342SMartin Blumenstingl #define MESON_SAR_ADC_LAST_RD 0x14 923adbf342SMartin Blumenstingl #define MESON_SAR_ADC_LAST_RD_LAST_CHANNEL1_MASK GENMASK(23, 16) 933adbf342SMartin Blumenstingl #define MESON_SAR_ADC_LAST_RD_LAST_CHANNEL0_MASK GENMASK(9, 0) 943adbf342SMartin Blumenstingl 953adbf342SMartin Blumenstingl #define MESON_SAR_ADC_FIFO_RD 0x18 963adbf342SMartin Blumenstingl #define MESON_SAR_ADC_FIFO_RD_CHAN_ID_MASK GENMASK(14, 12) 973adbf342SMartin Blumenstingl #define MESON_SAR_ADC_FIFO_RD_SAMPLE_VALUE_MASK GENMASK(11, 0) 983adbf342SMartin Blumenstingl 993adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AUX_SW 0x1c 100ab569a4cSMartin Blumenstingl #define MESON_SAR_ADC_AUX_SW_MUX_SEL_CHAN_SHIFT(_chan) \ 101ab569a4cSMartin Blumenstingl (8 + (((_chan) - 2) * 3)) 1023adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AUX_SW_VREF_P_MUX BIT(6) 1033adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AUX_SW_VREF_N_MUX BIT(5) 1043adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AUX_SW_MODE_SEL BIT(4) 1053adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AUX_SW_YP_DRIVE_SW BIT(3) 1063adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AUX_SW_XP_DRIVE_SW BIT(2) 1073adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AUX_SW_YM_DRIVE_SW BIT(1) 1083adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AUX_SW_XM_DRIVE_SW BIT(0) 1093adbf342SMartin Blumenstingl 1103adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW 0x20 1113adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_MUX_SEL_MASK GENMASK(25, 23) 1123adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_VREF_P_MUX BIT(22) 1133adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_VREF_N_MUX BIT(21) 1143adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_MODE_SEL BIT(20) 1153adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_YP_DRIVE_SW BIT(19) 1163adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_XP_DRIVE_SW BIT(18) 1173adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_YM_DRIVE_SW BIT(17) 1183adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_XM_DRIVE_SW BIT(16) 1193adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_MUX_SEL_MASK GENMASK(9, 7) 1203adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_VREF_P_MUX BIT(6) 1213adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_VREF_N_MUX BIT(5) 1223adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_MODE_SEL BIT(4) 1233adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_YP_DRIVE_SW BIT(3) 1243adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_XP_DRIVE_SW BIT(2) 1253adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_YM_DRIVE_SW BIT(1) 1263adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_XM_DRIVE_SW BIT(0) 1273adbf342SMartin Blumenstingl 1283adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW 0x24 1293adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_SW_EN BIT(26) 1303adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_MUX_MASK GENMASK(25, 23) 1313adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_VREF_P_MUX BIT(22) 1323adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_VREF_N_MUX BIT(21) 1333adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_MODE_SEL BIT(20) 1343adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_YP_DRIVE_SW BIT(19) 1353adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_XP_DRIVE_SW BIT(18) 1363adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_YM_DRIVE_SW BIT(17) 1373adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_XM_DRIVE_SW BIT(16) 1383adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_MUX_SEL_MASK GENMASK(9, 7) 1393adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_VREF_P_MUX BIT(6) 1403adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_VREF_N_MUX BIT(5) 1413adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_MODE_SEL BIT(4) 1423adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_YP_DRIVE_SW BIT(3) 1433adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_XP_DRIVE_SW BIT(2) 1443adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_YM_DRIVE_SW BIT(1) 1453adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_XM_DRIVE_SW BIT(0) 1463adbf342SMartin Blumenstingl 1473adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELTA_10 0x28 1483adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELTA_10_TEMP_SEL BIT(27) 1493adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELTA_10_TS_REVE1 BIT(26) 1503adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELTA_10_CHAN1_DELTA_VALUE_MASK GENMASK(25, 16) 1513adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELTA_10_TS_REVE0 BIT(15) 1523adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELTA_10_TS_C_MASK GENMASK(14, 11) 1533adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELTA_10_TS_VBG_EN BIT(10) 1543adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELTA_10_CHAN0_DELTA_VALUE_MASK GENMASK(9, 0) 1553adbf342SMartin Blumenstingl 1563adbf342SMartin Blumenstingl /* 1573adbf342SMartin Blumenstingl * NOTE: registers from here are undocumented (the vendor Linux kernel driver 1583adbf342SMartin Blumenstingl * and u-boot source served as reference). These only seem to be relevant on 1593adbf342SMartin Blumenstingl * GXBB and newer. 1603adbf342SMartin Blumenstingl */ 1613adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG11 0x2c 1623adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG11_BANDGAP_EN BIT(13) 1633adbf342SMartin Blumenstingl 1643adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG13 0x34 1653adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG13_12BIT_CALIBRATION_MASK GENMASK(13, 8) 1663adbf342SMartin Blumenstingl 1673adbf342SMartin Blumenstingl #define MESON_SAR_ADC_MAX_FIFO_SIZE 32 1683af10913SHeiner Kallweit #define MESON_SAR_ADC_TIMEOUT 100 /* ms */ 169723a61e0SMartin Blumenstingl #define MESON_SAR_ADC_VOLTAGE_AND_TEMP_CHANNEL 6 170723a61e0SMartin Blumenstingl #define MESON_SAR_ADC_TEMP_OFFSET 27 171723a61e0SMartin Blumenstingl 172723a61e0SMartin Blumenstingl /* temperature sensor calibration information in eFuse */ 173723a61e0SMartin Blumenstingl #define MESON_SAR_ADC_EFUSE_BYTES 4 174723a61e0SMartin Blumenstingl #define MESON_SAR_ADC_EFUSE_BYTE3_UPPER_ADC_VAL GENMASK(6, 0) 175723a61e0SMartin Blumenstingl #define MESON_SAR_ADC_EFUSE_BYTE3_IS_CALIBRATED BIT(7) 176723a61e0SMartin Blumenstingl 17748ba7c3cSHeiner Kallweit /* for use with IIO_VAL_INT_PLUS_MICRO */ 17848ba7c3cSHeiner Kallweit #define MILLION 1000000 1793adbf342SMartin Blumenstingl 1803adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN(_chan) { \ 1813adbf342SMartin Blumenstingl .type = IIO_VOLTAGE, \ 1823adbf342SMartin Blumenstingl .indexed = 1, \ 1833adbf342SMartin Blumenstingl .channel = _chan, \ 184827df057SMartin Blumenstingl .address = _chan, \ 1853adbf342SMartin Blumenstingl .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ 1863adbf342SMartin Blumenstingl BIT(IIO_CHAN_INFO_AVERAGE_RAW), \ 187723a61e0SMartin Blumenstingl .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ 188723a61e0SMartin Blumenstingl .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_CALIBBIAS) | \ 18948ba7c3cSHeiner Kallweit BIT(IIO_CHAN_INFO_CALIBSCALE), \ 1903adbf342SMartin Blumenstingl .datasheet_name = "SAR_ADC_CH"#_chan, \ 1913adbf342SMartin Blumenstingl } 1923adbf342SMartin Blumenstingl 193723a61e0SMartin Blumenstingl #define MESON_SAR_ADC_TEMP_CHAN(_chan) { \ 194723a61e0SMartin Blumenstingl .type = IIO_TEMP, \ 195723a61e0SMartin Blumenstingl .channel = _chan, \ 196723a61e0SMartin Blumenstingl .address = MESON_SAR_ADC_VOLTAGE_AND_TEMP_CHANNEL, \ 197723a61e0SMartin Blumenstingl .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ 198723a61e0SMartin Blumenstingl BIT(IIO_CHAN_INFO_AVERAGE_RAW), \ 199723a61e0SMartin Blumenstingl .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | \ 200723a61e0SMartin Blumenstingl BIT(IIO_CHAN_INFO_SCALE), \ 201723a61e0SMartin Blumenstingl .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_CALIBBIAS) | \ 202723a61e0SMartin Blumenstingl BIT(IIO_CHAN_INFO_CALIBSCALE), \ 203723a61e0SMartin Blumenstingl .datasheet_name = "TEMP_SENSOR", \ 204723a61e0SMartin Blumenstingl } 205723a61e0SMartin Blumenstingl 2063adbf342SMartin Blumenstingl static const struct iio_chan_spec meson_sar_adc_iio_channels[] = { 2073adbf342SMartin Blumenstingl MESON_SAR_ADC_CHAN(0), 2083adbf342SMartin Blumenstingl MESON_SAR_ADC_CHAN(1), 2093adbf342SMartin Blumenstingl MESON_SAR_ADC_CHAN(2), 2103adbf342SMartin Blumenstingl MESON_SAR_ADC_CHAN(3), 2113adbf342SMartin Blumenstingl MESON_SAR_ADC_CHAN(4), 2123adbf342SMartin Blumenstingl MESON_SAR_ADC_CHAN(5), 2133adbf342SMartin Blumenstingl MESON_SAR_ADC_CHAN(6), 2143adbf342SMartin Blumenstingl MESON_SAR_ADC_CHAN(7), 2153adbf342SMartin Blumenstingl IIO_CHAN_SOFT_TIMESTAMP(8), 2163adbf342SMartin Blumenstingl }; 2173adbf342SMartin Blumenstingl 218723a61e0SMartin Blumenstingl static const struct iio_chan_spec meson_sar_adc_and_temp_iio_channels[] = { 219723a61e0SMartin Blumenstingl MESON_SAR_ADC_CHAN(0), 220723a61e0SMartin Blumenstingl MESON_SAR_ADC_CHAN(1), 221723a61e0SMartin Blumenstingl MESON_SAR_ADC_CHAN(2), 222723a61e0SMartin Blumenstingl MESON_SAR_ADC_CHAN(3), 223723a61e0SMartin Blumenstingl MESON_SAR_ADC_CHAN(4), 224723a61e0SMartin Blumenstingl MESON_SAR_ADC_CHAN(5), 225723a61e0SMartin Blumenstingl MESON_SAR_ADC_CHAN(6), 226723a61e0SMartin Blumenstingl MESON_SAR_ADC_CHAN(7), 227723a61e0SMartin Blumenstingl MESON_SAR_ADC_TEMP_CHAN(8), 228723a61e0SMartin Blumenstingl IIO_CHAN_SOFT_TIMESTAMP(9), 229723a61e0SMartin Blumenstingl }; 230723a61e0SMartin Blumenstingl 2313adbf342SMartin Blumenstingl enum meson_sar_adc_avg_mode { 2323adbf342SMartin Blumenstingl NO_AVERAGING = 0x0, 2333adbf342SMartin Blumenstingl MEAN_AVERAGING = 0x1, 2343adbf342SMartin Blumenstingl MEDIAN_AVERAGING = 0x2, 2353adbf342SMartin Blumenstingl }; 2363adbf342SMartin Blumenstingl 2373adbf342SMartin Blumenstingl enum meson_sar_adc_num_samples { 2383adbf342SMartin Blumenstingl ONE_SAMPLE = 0x0, 2393adbf342SMartin Blumenstingl TWO_SAMPLES = 0x1, 2403adbf342SMartin Blumenstingl FOUR_SAMPLES = 0x2, 2413adbf342SMartin Blumenstingl EIGHT_SAMPLES = 0x3, 2423adbf342SMartin Blumenstingl }; 2433adbf342SMartin Blumenstingl 2443adbf342SMartin Blumenstingl enum meson_sar_adc_chan7_mux_sel { 2453adbf342SMartin Blumenstingl CHAN7_MUX_VSS = 0x0, 2463adbf342SMartin Blumenstingl CHAN7_MUX_VDD_DIV4 = 0x1, 2473adbf342SMartin Blumenstingl CHAN7_MUX_VDD_DIV2 = 0x2, 2483adbf342SMartin Blumenstingl CHAN7_MUX_VDD_MUL3_DIV4 = 0x3, 2493adbf342SMartin Blumenstingl CHAN7_MUX_VDD = 0x4, 2503adbf342SMartin Blumenstingl CHAN7_MUX_CH7_INPUT = 0x7, 2513adbf342SMartin Blumenstingl }; 2523adbf342SMartin Blumenstingl 253053ffe3cSYixun Lan struct meson_sar_adc_param { 2546c76ed31SMartin Blumenstingl bool has_bl30_integration; 255fda29dbaSMartin Blumenstingl unsigned long clock_rate; 256d85eed9fSMartin Blumenstingl u32 bandgap_reg; 2573adbf342SMartin Blumenstingl unsigned int resolution; 25896748823SMartin Blumenstingl const struct regmap_config *regmap_config; 259723a61e0SMartin Blumenstingl u8 temperature_trimming_bits; 260723a61e0SMartin Blumenstingl unsigned int temperature_multiplier; 261723a61e0SMartin Blumenstingl unsigned int temperature_divider; 2623adbf342SMartin Blumenstingl }; 2633adbf342SMartin Blumenstingl 264053ffe3cSYixun Lan struct meson_sar_adc_data { 265053ffe3cSYixun Lan const struct meson_sar_adc_param *param; 266053ffe3cSYixun Lan const char *name; 267053ffe3cSYixun Lan }; 268053ffe3cSYixun Lan 2693adbf342SMartin Blumenstingl struct meson_sar_adc_priv { 2703adbf342SMartin Blumenstingl struct regmap *regmap; 2713adbf342SMartin Blumenstingl struct regulator *vref; 272057e5a11SMartin Blumenstingl const struct meson_sar_adc_param *param; 2733adbf342SMartin Blumenstingl struct clk *clkin; 2743adbf342SMartin Blumenstingl struct clk *core_clk; 2753adbf342SMartin Blumenstingl struct clk *adc_sel_clk; 2763adbf342SMartin Blumenstingl struct clk *adc_clk; 2773adbf342SMartin Blumenstingl struct clk_gate clk_gate; 2783adbf342SMartin Blumenstingl struct clk *adc_div_clk; 2793adbf342SMartin Blumenstingl struct clk_divider clk_div; 2803af10913SHeiner Kallweit struct completion done; 28148ba7c3cSHeiner Kallweit int calibbias; 28248ba7c3cSHeiner Kallweit int calibscale; 283723a61e0SMartin Blumenstingl bool temperature_sensor_calibrated; 284723a61e0SMartin Blumenstingl u8 temperature_sensor_coefficient; 285723a61e0SMartin Blumenstingl u16 temperature_sensor_adc_val; 2863adbf342SMartin Blumenstingl }; 2873adbf342SMartin Blumenstingl 28896748823SMartin Blumenstingl static const struct regmap_config meson_sar_adc_regmap_config_gxbb = { 2893adbf342SMartin Blumenstingl .reg_bits = 8, 2903adbf342SMartin Blumenstingl .val_bits = 32, 2913adbf342SMartin Blumenstingl .reg_stride = 4, 2923adbf342SMartin Blumenstingl .max_register = MESON_SAR_ADC_REG13, 2933adbf342SMartin Blumenstingl }; 2943adbf342SMartin Blumenstingl 29596748823SMartin Blumenstingl static const struct regmap_config meson_sar_adc_regmap_config_meson8 = { 29696748823SMartin Blumenstingl .reg_bits = 8, 29796748823SMartin Blumenstingl .val_bits = 32, 29896748823SMartin Blumenstingl .reg_stride = 4, 29996748823SMartin Blumenstingl .max_register = MESON_SAR_ADC_DELTA_10, 30096748823SMartin Blumenstingl }; 30196748823SMartin Blumenstingl 3023adbf342SMartin Blumenstingl static unsigned int meson_sar_adc_get_fifo_count(struct iio_dev *indio_dev) 3033adbf342SMartin Blumenstingl { 3043adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 3053adbf342SMartin Blumenstingl u32 regval; 3063adbf342SMartin Blumenstingl 3073adbf342SMartin Blumenstingl regmap_read(priv->regmap, MESON_SAR_ADC_REG0, ®val); 3083adbf342SMartin Blumenstingl 3093adbf342SMartin Blumenstingl return FIELD_GET(MESON_SAR_ADC_REG0_FIFO_COUNT_MASK, regval); 3103adbf342SMartin Blumenstingl } 3113adbf342SMartin Blumenstingl 31248ba7c3cSHeiner Kallweit static int meson_sar_adc_calib_val(struct iio_dev *indio_dev, int val) 31348ba7c3cSHeiner Kallweit { 31448ba7c3cSHeiner Kallweit struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 31548ba7c3cSHeiner Kallweit int tmp; 31648ba7c3cSHeiner Kallweit 31748ba7c3cSHeiner Kallweit /* use val_calib = scale * val_raw + offset calibration function */ 31848ba7c3cSHeiner Kallweit tmp = div_s64((s64)val * priv->calibscale, MILLION) + priv->calibbias; 31948ba7c3cSHeiner Kallweit 320057e5a11SMartin Blumenstingl return clamp(tmp, 0, (1 << priv->param->resolution) - 1); 32148ba7c3cSHeiner Kallweit } 32248ba7c3cSHeiner Kallweit 3233adbf342SMartin Blumenstingl static int meson_sar_adc_wait_busy_clear(struct iio_dev *indio_dev) 3243adbf342SMartin Blumenstingl { 3253adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 3263adbf342SMartin Blumenstingl int regval, timeout = 10000; 3273adbf342SMartin Blumenstingl 3283adbf342SMartin Blumenstingl /* 3293adbf342SMartin Blumenstingl * NOTE: we need a small delay before reading the status, otherwise 3303adbf342SMartin Blumenstingl * the sample engine may not have started internally (which would 3313adbf342SMartin Blumenstingl * seem to us that sampling is already finished). 3323adbf342SMartin Blumenstingl */ 3333adbf342SMartin Blumenstingl do { 3343adbf342SMartin Blumenstingl udelay(1); 3353adbf342SMartin Blumenstingl regmap_read(priv->regmap, MESON_SAR_ADC_REG0, ®val); 3363adbf342SMartin Blumenstingl } while (FIELD_GET(MESON_SAR_ADC_REG0_BUSY_MASK, regval) && timeout--); 3373adbf342SMartin Blumenstingl 3383adbf342SMartin Blumenstingl if (timeout < 0) 3393adbf342SMartin Blumenstingl return -ETIMEDOUT; 3403adbf342SMartin Blumenstingl 3413adbf342SMartin Blumenstingl return 0; 3423adbf342SMartin Blumenstingl } 3433adbf342SMartin Blumenstingl 3443adbf342SMartin Blumenstingl static int meson_sar_adc_read_raw_sample(struct iio_dev *indio_dev, 3453adbf342SMartin Blumenstingl const struct iio_chan_spec *chan, 3463adbf342SMartin Blumenstingl int *val) 3473adbf342SMartin Blumenstingl { 3483adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 3496a882a2cSHeiner Kallweit int regval, fifo_chan, fifo_val, count; 3503adbf342SMartin Blumenstingl 3513af10913SHeiner Kallweit if(!wait_for_completion_timeout(&priv->done, 3523af10913SHeiner Kallweit msecs_to_jiffies(MESON_SAR_ADC_TIMEOUT))) 3533af10913SHeiner Kallweit return -ETIMEDOUT; 3543adbf342SMartin Blumenstingl 3556a882a2cSHeiner Kallweit count = meson_sar_adc_get_fifo_count(indio_dev); 3566a882a2cSHeiner Kallweit if (count != 1) { 3576a882a2cSHeiner Kallweit dev_err(&indio_dev->dev, 3586a882a2cSHeiner Kallweit "ADC FIFO has %d element(s) instead of one\n", count); 3596a882a2cSHeiner Kallweit return -EINVAL; 3603adbf342SMartin Blumenstingl } 3613adbf342SMartin Blumenstingl 3626a882a2cSHeiner Kallweit regmap_read(priv->regmap, MESON_SAR_ADC_FIFO_RD, ®val); 3636a882a2cSHeiner Kallweit fifo_chan = FIELD_GET(MESON_SAR_ADC_FIFO_RD_CHAN_ID_MASK, regval); 364827df057SMartin Blumenstingl if (fifo_chan != chan->address) { 3656a882a2cSHeiner Kallweit dev_err(&indio_dev->dev, 366827df057SMartin Blumenstingl "ADC FIFO entry belongs to channel %d instead of %lu\n", 367827df057SMartin Blumenstingl fifo_chan, chan->address); 3686a882a2cSHeiner Kallweit return -EINVAL; 3696a882a2cSHeiner Kallweit } 3703adbf342SMartin Blumenstingl 3716a882a2cSHeiner Kallweit fifo_val = FIELD_GET(MESON_SAR_ADC_FIFO_RD_SAMPLE_VALUE_MASK, regval); 372057e5a11SMartin Blumenstingl fifo_val &= GENMASK(priv->param->resolution - 1, 0); 37348ba7c3cSHeiner Kallweit *val = meson_sar_adc_calib_val(indio_dev, fifo_val); 3743adbf342SMartin Blumenstingl 3753adbf342SMartin Blumenstingl return 0; 3763adbf342SMartin Blumenstingl } 3773adbf342SMartin Blumenstingl 3783adbf342SMartin Blumenstingl static void meson_sar_adc_set_averaging(struct iio_dev *indio_dev, 3793adbf342SMartin Blumenstingl const struct iio_chan_spec *chan, 3803adbf342SMartin Blumenstingl enum meson_sar_adc_avg_mode mode, 3813adbf342SMartin Blumenstingl enum meson_sar_adc_num_samples samples) 3823adbf342SMartin Blumenstingl { 3833adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 384827df057SMartin Blumenstingl int val, address = chan->address; 3853adbf342SMartin Blumenstingl 386827df057SMartin Blumenstingl val = samples << MESON_SAR_ADC_AVG_CNTL_NUM_SAMPLES_SHIFT(address); 3873adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_AVG_CNTL, 388827df057SMartin Blumenstingl MESON_SAR_ADC_AVG_CNTL_NUM_SAMPLES_MASK(address), 3893adbf342SMartin Blumenstingl val); 3903adbf342SMartin Blumenstingl 391827df057SMartin Blumenstingl val = mode << MESON_SAR_ADC_AVG_CNTL_AVG_MODE_SHIFT(address); 3923adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_AVG_CNTL, 393827df057SMartin Blumenstingl MESON_SAR_ADC_AVG_CNTL_AVG_MODE_MASK(address), val); 3943adbf342SMartin Blumenstingl } 3953adbf342SMartin Blumenstingl 3963adbf342SMartin Blumenstingl static void meson_sar_adc_enable_channel(struct iio_dev *indio_dev, 3973adbf342SMartin Blumenstingl const struct iio_chan_spec *chan) 3983adbf342SMartin Blumenstingl { 3993adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 4003adbf342SMartin Blumenstingl u32 regval; 4013adbf342SMartin Blumenstingl 4023adbf342SMartin Blumenstingl /* 4033adbf342SMartin Blumenstingl * the SAR ADC engine allows sampling multiple channels at the same 4043adbf342SMartin Blumenstingl * time. to keep it simple we're only working with one *internal* 4053adbf342SMartin Blumenstingl * channel, which starts counting at index 0 (which means: count = 1). 4063adbf342SMartin Blumenstingl */ 4073adbf342SMartin Blumenstingl regval = FIELD_PREP(MESON_SAR_ADC_CHAN_LIST_MAX_INDEX_MASK, 0); 4083adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_LIST, 4093adbf342SMartin Blumenstingl MESON_SAR_ADC_CHAN_LIST_MAX_INDEX_MASK, regval); 4103adbf342SMartin Blumenstingl 4113adbf342SMartin Blumenstingl /* map channel index 0 to the channel which we want to read */ 4123adbf342SMartin Blumenstingl regval = FIELD_PREP(MESON_SAR_ADC_CHAN_LIST_ENTRY_MASK(0), 413827df057SMartin Blumenstingl chan->address); 4143adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_LIST, 4153adbf342SMartin Blumenstingl MESON_SAR_ADC_CHAN_LIST_ENTRY_MASK(0), regval); 4163adbf342SMartin Blumenstingl 4173adbf342SMartin Blumenstingl regval = FIELD_PREP(MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_MUX_MASK, 418827df057SMartin Blumenstingl chan->address); 4193adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DETECT_IDLE_SW, 4203adbf342SMartin Blumenstingl MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_MUX_MASK, 4213adbf342SMartin Blumenstingl regval); 4223adbf342SMartin Blumenstingl 4233adbf342SMartin Blumenstingl regval = FIELD_PREP(MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_MUX_SEL_MASK, 424827df057SMartin Blumenstingl chan->address); 4253adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DETECT_IDLE_SW, 4263adbf342SMartin Blumenstingl MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_MUX_SEL_MASK, 4273adbf342SMartin Blumenstingl regval); 4283adbf342SMartin Blumenstingl 429723a61e0SMartin Blumenstingl if (chan->address == MESON_SAR_ADC_VOLTAGE_AND_TEMP_CHANNEL) { 430723a61e0SMartin Blumenstingl if (chan->type == IIO_TEMP) 431723a61e0SMartin Blumenstingl regval = MESON_SAR_ADC_DELTA_10_TEMP_SEL; 432723a61e0SMartin Blumenstingl else 433723a61e0SMartin Blumenstingl regval = 0; 434723a61e0SMartin Blumenstingl 435723a61e0SMartin Blumenstingl regmap_update_bits(priv->regmap, 436723a61e0SMartin Blumenstingl MESON_SAR_ADC_DELTA_10, 437723a61e0SMartin Blumenstingl MESON_SAR_ADC_DELTA_10_TEMP_SEL, regval); 438723a61e0SMartin Blumenstingl } 4393adbf342SMartin Blumenstingl } 4403adbf342SMartin Blumenstingl 4413adbf342SMartin Blumenstingl static void meson_sar_adc_set_chan7_mux(struct iio_dev *indio_dev, 4423adbf342SMartin Blumenstingl enum meson_sar_adc_chan7_mux_sel sel) 4433adbf342SMartin Blumenstingl { 4443adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 4453adbf342SMartin Blumenstingl u32 regval; 4463adbf342SMartin Blumenstingl 4473adbf342SMartin Blumenstingl regval = FIELD_PREP(MESON_SAR_ADC_REG3_CTRL_CHAN7_MUX_SEL_MASK, sel); 4483adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3, 4493adbf342SMartin Blumenstingl MESON_SAR_ADC_REG3_CTRL_CHAN7_MUX_SEL_MASK, regval); 4503adbf342SMartin Blumenstingl 4513adbf342SMartin Blumenstingl usleep_range(10, 20); 4523adbf342SMartin Blumenstingl } 4533adbf342SMartin Blumenstingl 4543adbf342SMartin Blumenstingl static void meson_sar_adc_start_sample_engine(struct iio_dev *indio_dev) 4553adbf342SMartin Blumenstingl { 4563adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 4573adbf342SMartin Blumenstingl 4583af10913SHeiner Kallweit reinit_completion(&priv->done); 4593af10913SHeiner Kallweit 4603af10913SHeiner Kallweit regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, 4613af10913SHeiner Kallweit MESON_SAR_ADC_REG0_FIFO_IRQ_EN, 4623af10913SHeiner Kallweit MESON_SAR_ADC_REG0_FIFO_IRQ_EN); 4633af10913SHeiner Kallweit 4643adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, 4653adbf342SMartin Blumenstingl MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE, 4663adbf342SMartin Blumenstingl MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE); 4673adbf342SMartin Blumenstingl 4683adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, 4693adbf342SMartin Blumenstingl MESON_SAR_ADC_REG0_SAMPLING_START, 4703adbf342SMartin Blumenstingl MESON_SAR_ADC_REG0_SAMPLING_START); 4713adbf342SMartin Blumenstingl } 4723adbf342SMartin Blumenstingl 4733adbf342SMartin Blumenstingl static void meson_sar_adc_stop_sample_engine(struct iio_dev *indio_dev) 4743adbf342SMartin Blumenstingl { 4753adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 4763adbf342SMartin Blumenstingl 4773adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, 4783af10913SHeiner Kallweit MESON_SAR_ADC_REG0_FIFO_IRQ_EN, 0); 4793af10913SHeiner Kallweit 4803af10913SHeiner Kallweit regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, 4813adbf342SMartin Blumenstingl MESON_SAR_ADC_REG0_SAMPLING_STOP, 4823adbf342SMartin Blumenstingl MESON_SAR_ADC_REG0_SAMPLING_STOP); 4833adbf342SMartin Blumenstingl 4843adbf342SMartin Blumenstingl /* wait until all modules are stopped */ 4853adbf342SMartin Blumenstingl meson_sar_adc_wait_busy_clear(indio_dev); 4863adbf342SMartin Blumenstingl 4873adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, 4883adbf342SMartin Blumenstingl MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE, 0); 4893adbf342SMartin Blumenstingl } 4903adbf342SMartin Blumenstingl 4913adbf342SMartin Blumenstingl static int meson_sar_adc_lock(struct iio_dev *indio_dev) 4923adbf342SMartin Blumenstingl { 4933adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 4943adbf342SMartin Blumenstingl int val, timeout = 10000; 4953adbf342SMartin Blumenstingl 4963adbf342SMartin Blumenstingl mutex_lock(&indio_dev->mlock); 4973adbf342SMartin Blumenstingl 498057e5a11SMartin Blumenstingl if (priv->param->has_bl30_integration) { 4993adbf342SMartin Blumenstingl /* prevent BL30 from using the SAR ADC while we are using it */ 5003adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY, 5013adbf342SMartin Blumenstingl MESON_SAR_ADC_DELAY_KERNEL_BUSY, 5023adbf342SMartin Blumenstingl MESON_SAR_ADC_DELAY_KERNEL_BUSY); 5033adbf342SMartin Blumenstingl 5046c76ed31SMartin Blumenstingl /* 5056c76ed31SMartin Blumenstingl * wait until BL30 releases it's lock (so we can use the SAR 5066c76ed31SMartin Blumenstingl * ADC) 5076c76ed31SMartin Blumenstingl */ 5083adbf342SMartin Blumenstingl do { 5093adbf342SMartin Blumenstingl udelay(1); 5103adbf342SMartin Blumenstingl regmap_read(priv->regmap, MESON_SAR_ADC_DELAY, &val); 5113adbf342SMartin Blumenstingl } while (val & MESON_SAR_ADC_DELAY_BL30_BUSY && timeout--); 5123adbf342SMartin Blumenstingl 5133c3e4b3aSDan Carpenter if (timeout < 0) { 5143c3e4b3aSDan Carpenter mutex_unlock(&indio_dev->mlock); 5153adbf342SMartin Blumenstingl return -ETIMEDOUT; 5166c76ed31SMartin Blumenstingl } 5173c3e4b3aSDan Carpenter } 5183adbf342SMartin Blumenstingl 5193adbf342SMartin Blumenstingl return 0; 5203adbf342SMartin Blumenstingl } 5213adbf342SMartin Blumenstingl 5223adbf342SMartin Blumenstingl static void meson_sar_adc_unlock(struct iio_dev *indio_dev) 5233adbf342SMartin Blumenstingl { 5243adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 5253adbf342SMartin Blumenstingl 526057e5a11SMartin Blumenstingl if (priv->param->has_bl30_integration) 5273adbf342SMartin Blumenstingl /* allow BL30 to use the SAR ADC again */ 5283adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY, 5293adbf342SMartin Blumenstingl MESON_SAR_ADC_DELAY_KERNEL_BUSY, 0); 5303adbf342SMartin Blumenstingl 5313adbf342SMartin Blumenstingl mutex_unlock(&indio_dev->mlock); 5323adbf342SMartin Blumenstingl } 5333adbf342SMartin Blumenstingl 5343adbf342SMartin Blumenstingl static void meson_sar_adc_clear_fifo(struct iio_dev *indio_dev) 5353adbf342SMartin Blumenstingl { 5363adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 537103a07d4SMartin Blumenstingl unsigned int count, tmp; 5383adbf342SMartin Blumenstingl 5393adbf342SMartin Blumenstingl for (count = 0; count < MESON_SAR_ADC_MAX_FIFO_SIZE; count++) { 5403adbf342SMartin Blumenstingl if (!meson_sar_adc_get_fifo_count(indio_dev)) 5413adbf342SMartin Blumenstingl break; 5423adbf342SMartin Blumenstingl 543103a07d4SMartin Blumenstingl regmap_read(priv->regmap, MESON_SAR_ADC_FIFO_RD, &tmp); 5443adbf342SMartin Blumenstingl } 5453adbf342SMartin Blumenstingl } 5463adbf342SMartin Blumenstingl 5473adbf342SMartin Blumenstingl static int meson_sar_adc_get_sample(struct iio_dev *indio_dev, 5483adbf342SMartin Blumenstingl const struct iio_chan_spec *chan, 5493adbf342SMartin Blumenstingl enum meson_sar_adc_avg_mode avg_mode, 5503adbf342SMartin Blumenstingl enum meson_sar_adc_num_samples avg_samples, 5513adbf342SMartin Blumenstingl int *val) 5523adbf342SMartin Blumenstingl { 553723a61e0SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 5543adbf342SMartin Blumenstingl int ret; 5553adbf342SMartin Blumenstingl 556723a61e0SMartin Blumenstingl if (chan->type == IIO_TEMP && !priv->temperature_sensor_calibrated) 557723a61e0SMartin Blumenstingl return -ENOTSUPP; 558723a61e0SMartin Blumenstingl 5593adbf342SMartin Blumenstingl ret = meson_sar_adc_lock(indio_dev); 5603adbf342SMartin Blumenstingl if (ret) 5613adbf342SMartin Blumenstingl return ret; 5623adbf342SMartin Blumenstingl 5633adbf342SMartin Blumenstingl /* clear the FIFO to make sure we're not reading old values */ 5643adbf342SMartin Blumenstingl meson_sar_adc_clear_fifo(indio_dev); 5653adbf342SMartin Blumenstingl 5663adbf342SMartin Blumenstingl meson_sar_adc_set_averaging(indio_dev, chan, avg_mode, avg_samples); 5673adbf342SMartin Blumenstingl 5683adbf342SMartin Blumenstingl meson_sar_adc_enable_channel(indio_dev, chan); 5693adbf342SMartin Blumenstingl 5703adbf342SMartin Blumenstingl meson_sar_adc_start_sample_engine(indio_dev); 5713adbf342SMartin Blumenstingl ret = meson_sar_adc_read_raw_sample(indio_dev, chan, val); 5723adbf342SMartin Blumenstingl meson_sar_adc_stop_sample_engine(indio_dev); 5733adbf342SMartin Blumenstingl 5743adbf342SMartin Blumenstingl meson_sar_adc_unlock(indio_dev); 5753adbf342SMartin Blumenstingl 5763adbf342SMartin Blumenstingl if (ret) { 5773adbf342SMartin Blumenstingl dev_warn(indio_dev->dev.parent, 578827df057SMartin Blumenstingl "failed to read sample for channel %lu: %d\n", 579827df057SMartin Blumenstingl chan->address, ret); 5803adbf342SMartin Blumenstingl return ret; 5813adbf342SMartin Blumenstingl } 5823adbf342SMartin Blumenstingl 5833adbf342SMartin Blumenstingl return IIO_VAL_INT; 5843adbf342SMartin Blumenstingl } 5853adbf342SMartin Blumenstingl 5863adbf342SMartin Blumenstingl static int meson_sar_adc_iio_info_read_raw(struct iio_dev *indio_dev, 5873adbf342SMartin Blumenstingl const struct iio_chan_spec *chan, 5883adbf342SMartin Blumenstingl int *val, int *val2, long mask) 5893adbf342SMartin Blumenstingl { 5903adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 5913adbf342SMartin Blumenstingl int ret; 5923adbf342SMartin Blumenstingl 5933adbf342SMartin Blumenstingl switch (mask) { 5943adbf342SMartin Blumenstingl case IIO_CHAN_INFO_RAW: 5953adbf342SMartin Blumenstingl return meson_sar_adc_get_sample(indio_dev, chan, NO_AVERAGING, 5963adbf342SMartin Blumenstingl ONE_SAMPLE, val); 5973adbf342SMartin Blumenstingl break; 5983adbf342SMartin Blumenstingl 5993adbf342SMartin Blumenstingl case IIO_CHAN_INFO_AVERAGE_RAW: 6003adbf342SMartin Blumenstingl return meson_sar_adc_get_sample(indio_dev, chan, 6013adbf342SMartin Blumenstingl MEAN_AVERAGING, EIGHT_SAMPLES, 6023adbf342SMartin Blumenstingl val); 6033adbf342SMartin Blumenstingl break; 6043adbf342SMartin Blumenstingl 6053adbf342SMartin Blumenstingl case IIO_CHAN_INFO_SCALE: 606723a61e0SMartin Blumenstingl if (chan->type == IIO_VOLTAGE) { 6073adbf342SMartin Blumenstingl ret = regulator_get_voltage(priv->vref); 6083adbf342SMartin Blumenstingl if (ret < 0) { 6093adbf342SMartin Blumenstingl dev_err(indio_dev->dev.parent, 610723a61e0SMartin Blumenstingl "failed to get vref voltage: %d\n", 611723a61e0SMartin Blumenstingl ret); 6123adbf342SMartin Blumenstingl return ret; 6133adbf342SMartin Blumenstingl } 6143adbf342SMartin Blumenstingl 6153adbf342SMartin Blumenstingl *val = ret / 1000; 616057e5a11SMartin Blumenstingl *val2 = priv->param->resolution; 6173adbf342SMartin Blumenstingl return IIO_VAL_FRACTIONAL_LOG2; 618723a61e0SMartin Blumenstingl } else if (chan->type == IIO_TEMP) { 619723a61e0SMartin Blumenstingl /* SoC specific multiplier and divider */ 620723a61e0SMartin Blumenstingl *val = priv->param->temperature_multiplier; 621723a61e0SMartin Blumenstingl *val2 = priv->param->temperature_divider; 622723a61e0SMartin Blumenstingl 623723a61e0SMartin Blumenstingl /* celsius to millicelsius */ 624723a61e0SMartin Blumenstingl *val *= 1000; 625723a61e0SMartin Blumenstingl 626723a61e0SMartin Blumenstingl return IIO_VAL_FRACTIONAL; 627723a61e0SMartin Blumenstingl } else { 628723a61e0SMartin Blumenstingl return -EINVAL; 629723a61e0SMartin Blumenstingl } 6303adbf342SMartin Blumenstingl 63148ba7c3cSHeiner Kallweit case IIO_CHAN_INFO_CALIBBIAS: 63248ba7c3cSHeiner Kallweit *val = priv->calibbias; 63348ba7c3cSHeiner Kallweit return IIO_VAL_INT; 63448ba7c3cSHeiner Kallweit 63548ba7c3cSHeiner Kallweit case IIO_CHAN_INFO_CALIBSCALE: 63648ba7c3cSHeiner Kallweit *val = priv->calibscale / MILLION; 63748ba7c3cSHeiner Kallweit *val2 = priv->calibscale % MILLION; 63848ba7c3cSHeiner Kallweit return IIO_VAL_INT_PLUS_MICRO; 63948ba7c3cSHeiner Kallweit 640723a61e0SMartin Blumenstingl case IIO_CHAN_INFO_OFFSET: 641723a61e0SMartin Blumenstingl *val = DIV_ROUND_CLOSEST(MESON_SAR_ADC_TEMP_OFFSET * 642723a61e0SMartin Blumenstingl priv->param->temperature_divider, 643723a61e0SMartin Blumenstingl priv->param->temperature_multiplier); 644723a61e0SMartin Blumenstingl *val -= priv->temperature_sensor_adc_val; 645723a61e0SMartin Blumenstingl return IIO_VAL_INT; 646723a61e0SMartin Blumenstingl 6473adbf342SMartin Blumenstingl default: 6483adbf342SMartin Blumenstingl return -EINVAL; 6493adbf342SMartin Blumenstingl } 6503adbf342SMartin Blumenstingl } 6513adbf342SMartin Blumenstingl 6523adbf342SMartin Blumenstingl static int meson_sar_adc_clk_init(struct iio_dev *indio_dev, 6533adbf342SMartin Blumenstingl void __iomem *base) 6543adbf342SMartin Blumenstingl { 6553adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 6563adbf342SMartin Blumenstingl struct clk_init_data init; 6573adbf342SMartin Blumenstingl const char *clk_parents[1]; 6583adbf342SMartin Blumenstingl 6593921db46SRob Herring init.name = devm_kasprintf(&indio_dev->dev, GFP_KERNEL, "%pOF#adc_div", 6603921db46SRob Herring indio_dev->dev.of_node); 661aad172b0SNicholas Mc Guire if (!init.name) 662aad172b0SNicholas Mc Guire return -ENOMEM; 663aad172b0SNicholas Mc Guire 6643adbf342SMartin Blumenstingl init.flags = 0; 6653adbf342SMartin Blumenstingl init.ops = &clk_divider_ops; 6663adbf342SMartin Blumenstingl clk_parents[0] = __clk_get_name(priv->clkin); 6673adbf342SMartin Blumenstingl init.parent_names = clk_parents; 6683adbf342SMartin Blumenstingl init.num_parents = 1; 6693adbf342SMartin Blumenstingl 6703adbf342SMartin Blumenstingl priv->clk_div.reg = base + MESON_SAR_ADC_REG3; 6713adbf342SMartin Blumenstingl priv->clk_div.shift = MESON_SAR_ADC_REG3_ADC_CLK_DIV_SHIFT; 6723adbf342SMartin Blumenstingl priv->clk_div.width = MESON_SAR_ADC_REG3_ADC_CLK_DIV_WIDTH; 6733adbf342SMartin Blumenstingl priv->clk_div.hw.init = &init; 6743adbf342SMartin Blumenstingl priv->clk_div.flags = 0; 6753adbf342SMartin Blumenstingl 6763adbf342SMartin Blumenstingl priv->adc_div_clk = devm_clk_register(&indio_dev->dev, 6773adbf342SMartin Blumenstingl &priv->clk_div.hw); 6783adbf342SMartin Blumenstingl if (WARN_ON(IS_ERR(priv->adc_div_clk))) 6793adbf342SMartin Blumenstingl return PTR_ERR(priv->adc_div_clk); 6803adbf342SMartin Blumenstingl 6813921db46SRob Herring init.name = devm_kasprintf(&indio_dev->dev, GFP_KERNEL, "%pOF#adc_en", 6823921db46SRob Herring indio_dev->dev.of_node); 683aad172b0SNicholas Mc Guire if (!init.name) 684aad172b0SNicholas Mc Guire return -ENOMEM; 685aad172b0SNicholas Mc Guire 6863adbf342SMartin Blumenstingl init.flags = CLK_SET_RATE_PARENT; 6873adbf342SMartin Blumenstingl init.ops = &clk_gate_ops; 6883adbf342SMartin Blumenstingl clk_parents[0] = __clk_get_name(priv->adc_div_clk); 6893adbf342SMartin Blumenstingl init.parent_names = clk_parents; 6903adbf342SMartin Blumenstingl init.num_parents = 1; 6913adbf342SMartin Blumenstingl 6923adbf342SMartin Blumenstingl priv->clk_gate.reg = base + MESON_SAR_ADC_REG3; 6937a6b0420SMartin Blumenstingl priv->clk_gate.bit_idx = __ffs(MESON_SAR_ADC_REG3_CLK_EN); 6943adbf342SMartin Blumenstingl priv->clk_gate.hw.init = &init; 6953adbf342SMartin Blumenstingl 6963adbf342SMartin Blumenstingl priv->adc_clk = devm_clk_register(&indio_dev->dev, &priv->clk_gate.hw); 6973adbf342SMartin Blumenstingl if (WARN_ON(IS_ERR(priv->adc_clk))) 6983adbf342SMartin Blumenstingl return PTR_ERR(priv->adc_clk); 6993adbf342SMartin Blumenstingl 7003adbf342SMartin Blumenstingl return 0; 7013adbf342SMartin Blumenstingl } 7023adbf342SMartin Blumenstingl 703723a61e0SMartin Blumenstingl static int meson_sar_adc_temp_sensor_init(struct iio_dev *indio_dev) 704723a61e0SMartin Blumenstingl { 705723a61e0SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 706723a61e0SMartin Blumenstingl u8 *buf, trimming_bits, trimming_mask, upper_adc_val; 707723a61e0SMartin Blumenstingl struct nvmem_cell *temperature_calib; 708723a61e0SMartin Blumenstingl size_t read_len; 709723a61e0SMartin Blumenstingl int ret; 710723a61e0SMartin Blumenstingl 711723a61e0SMartin Blumenstingl temperature_calib = devm_nvmem_cell_get(&indio_dev->dev, 712723a61e0SMartin Blumenstingl "temperature_calib"); 713723a61e0SMartin Blumenstingl if (IS_ERR(temperature_calib)) { 714723a61e0SMartin Blumenstingl ret = PTR_ERR(temperature_calib); 715723a61e0SMartin Blumenstingl 716723a61e0SMartin Blumenstingl /* 717723a61e0SMartin Blumenstingl * leave the temperature sensor disabled if no calibration data 718723a61e0SMartin Blumenstingl * was passed via nvmem-cells. 719723a61e0SMartin Blumenstingl */ 720723a61e0SMartin Blumenstingl if (ret == -ENODEV) 721723a61e0SMartin Blumenstingl return 0; 722723a61e0SMartin Blumenstingl 723723a61e0SMartin Blumenstingl if (ret != -EPROBE_DEFER) 724723a61e0SMartin Blumenstingl dev_err(indio_dev->dev.parent, 725723a61e0SMartin Blumenstingl "failed to get temperature_calib cell\n"); 726723a61e0SMartin Blumenstingl 727723a61e0SMartin Blumenstingl return ret; 728723a61e0SMartin Blumenstingl } 729723a61e0SMartin Blumenstingl 730723a61e0SMartin Blumenstingl read_len = MESON_SAR_ADC_EFUSE_BYTES; 731723a61e0SMartin Blumenstingl buf = nvmem_cell_read(temperature_calib, &read_len); 732723a61e0SMartin Blumenstingl if (IS_ERR(buf)) { 733723a61e0SMartin Blumenstingl dev_err(indio_dev->dev.parent, 734723a61e0SMartin Blumenstingl "failed to read temperature_calib cell\n"); 735723a61e0SMartin Blumenstingl return PTR_ERR(buf); 736723a61e0SMartin Blumenstingl } else if (read_len != MESON_SAR_ADC_EFUSE_BYTES) { 737723a61e0SMartin Blumenstingl kfree(buf); 738723a61e0SMartin Blumenstingl dev_err(indio_dev->dev.parent, 739723a61e0SMartin Blumenstingl "invalid read size of temperature_calib cell\n"); 740723a61e0SMartin Blumenstingl return -EINVAL; 741723a61e0SMartin Blumenstingl } 742723a61e0SMartin Blumenstingl 743723a61e0SMartin Blumenstingl trimming_bits = priv->param->temperature_trimming_bits; 744723a61e0SMartin Blumenstingl trimming_mask = BIT(trimming_bits) - 1; 745723a61e0SMartin Blumenstingl 746723a61e0SMartin Blumenstingl priv->temperature_sensor_calibrated = 747723a61e0SMartin Blumenstingl buf[3] & MESON_SAR_ADC_EFUSE_BYTE3_IS_CALIBRATED; 748723a61e0SMartin Blumenstingl priv->temperature_sensor_coefficient = buf[2] & trimming_mask; 749723a61e0SMartin Blumenstingl 750723a61e0SMartin Blumenstingl upper_adc_val = FIELD_GET(MESON_SAR_ADC_EFUSE_BYTE3_UPPER_ADC_VAL, 751723a61e0SMartin Blumenstingl buf[3]); 752723a61e0SMartin Blumenstingl 753723a61e0SMartin Blumenstingl priv->temperature_sensor_adc_val = buf[2]; 754723a61e0SMartin Blumenstingl priv->temperature_sensor_adc_val |= upper_adc_val << BITS_PER_BYTE; 755723a61e0SMartin Blumenstingl priv->temperature_sensor_adc_val >>= trimming_bits; 756723a61e0SMartin Blumenstingl 757723a61e0SMartin Blumenstingl kfree(buf); 758723a61e0SMartin Blumenstingl 759723a61e0SMartin Blumenstingl return 0; 760723a61e0SMartin Blumenstingl } 761723a61e0SMartin Blumenstingl 7623adbf342SMartin Blumenstingl static int meson_sar_adc_init(struct iio_dev *indio_dev) 7633adbf342SMartin Blumenstingl { 7643adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 765ab569a4cSMartin Blumenstingl int regval, i, ret; 7663adbf342SMartin Blumenstingl 7673adbf342SMartin Blumenstingl /* 7683adbf342SMartin Blumenstingl * make sure we start at CH7 input since the other muxes are only used 7693adbf342SMartin Blumenstingl * for internal calibration. 7703adbf342SMartin Blumenstingl */ 7713adbf342SMartin Blumenstingl meson_sar_adc_set_chan7_mux(indio_dev, CHAN7_MUX_CH7_INPUT); 7723adbf342SMartin Blumenstingl 773057e5a11SMartin Blumenstingl if (priv->param->has_bl30_integration) { 7743adbf342SMartin Blumenstingl /* 7756c76ed31SMartin Blumenstingl * leave sampling delay and the input clocks as configured by 7766c76ed31SMartin Blumenstingl * BL30 to make sure BL30 gets the values it expects when 7776c76ed31SMartin Blumenstingl * reading the temperature sensor. 7783adbf342SMartin Blumenstingl */ 7793adbf342SMartin Blumenstingl regmap_read(priv->regmap, MESON_SAR_ADC_REG3, ®val); 7803adbf342SMartin Blumenstingl if (regval & MESON_SAR_ADC_REG3_BL30_INITIALIZED) 7813adbf342SMartin Blumenstingl return 0; 7826c76ed31SMartin Blumenstingl } 7833adbf342SMartin Blumenstingl 7843adbf342SMartin Blumenstingl meson_sar_adc_stop_sample_engine(indio_dev); 7853adbf342SMartin Blumenstingl 786723a61e0SMartin Blumenstingl /* 787723a61e0SMartin Blumenstingl * disable this bit as seems to be only relevant for Meson6 (based 788723a61e0SMartin Blumenstingl * on the vendor driver), which we don't support at the moment. 789723a61e0SMartin Blumenstingl */ 7903adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, 791723a61e0SMartin Blumenstingl MESON_SAR_ADC_REG0_ADC_TEMP_SEN_SEL, 0); 7923adbf342SMartin Blumenstingl 7933adbf342SMartin Blumenstingl /* disable all channels by default */ 7943adbf342SMartin Blumenstingl regmap_write(priv->regmap, MESON_SAR_ADC_CHAN_LIST, 0x0); 7953adbf342SMartin Blumenstingl 7963adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3, 7973adbf342SMartin Blumenstingl MESON_SAR_ADC_REG3_CTRL_SAMPLING_CLOCK_PHASE, 0); 7983adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3, 7993adbf342SMartin Blumenstingl MESON_SAR_ADC_REG3_CNTL_USE_SC_DLY, 8003adbf342SMartin Blumenstingl MESON_SAR_ADC_REG3_CNTL_USE_SC_DLY); 8013adbf342SMartin Blumenstingl 8023adbf342SMartin Blumenstingl /* delay between two samples = (10+1) * 1uS */ 8033adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY, 8043adbf342SMartin Blumenstingl MESON_SAR_ADC_DELAY_INPUT_DLY_CNT_MASK, 8053adbf342SMartin Blumenstingl FIELD_PREP(MESON_SAR_ADC_DELAY_SAMPLE_DLY_CNT_MASK, 8063adbf342SMartin Blumenstingl 10)); 8073adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY, 8083adbf342SMartin Blumenstingl MESON_SAR_ADC_DELAY_SAMPLE_DLY_SEL_MASK, 8093adbf342SMartin Blumenstingl FIELD_PREP(MESON_SAR_ADC_DELAY_SAMPLE_DLY_SEL_MASK, 8103adbf342SMartin Blumenstingl 0)); 8113adbf342SMartin Blumenstingl 8123adbf342SMartin Blumenstingl /* delay between two samples = (10+1) * 1uS */ 8133adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY, 8143adbf342SMartin Blumenstingl MESON_SAR_ADC_DELAY_INPUT_DLY_CNT_MASK, 8153adbf342SMartin Blumenstingl FIELD_PREP(MESON_SAR_ADC_DELAY_INPUT_DLY_CNT_MASK, 8163adbf342SMartin Blumenstingl 10)); 8173adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY, 8183adbf342SMartin Blumenstingl MESON_SAR_ADC_DELAY_INPUT_DLY_SEL_MASK, 8193adbf342SMartin Blumenstingl FIELD_PREP(MESON_SAR_ADC_DELAY_INPUT_DLY_SEL_MASK, 8203adbf342SMartin Blumenstingl 1)); 8213adbf342SMartin Blumenstingl 822ab569a4cSMartin Blumenstingl /* 823ab569a4cSMartin Blumenstingl * set up the input channel muxes in MESON_SAR_ADC_CHAN_10_SW 824ab569a4cSMartin Blumenstingl * (0 = SAR_ADC_CH0, 1 = SAR_ADC_CH1) 825ab569a4cSMartin Blumenstingl */ 826ab569a4cSMartin Blumenstingl regval = FIELD_PREP(MESON_SAR_ADC_CHAN_10_SW_CHAN0_MUX_SEL_MASK, 0); 827ab569a4cSMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_10_SW, 828ab569a4cSMartin Blumenstingl MESON_SAR_ADC_CHAN_10_SW_CHAN0_MUX_SEL_MASK, 829ab569a4cSMartin Blumenstingl regval); 830ab569a4cSMartin Blumenstingl regval = FIELD_PREP(MESON_SAR_ADC_CHAN_10_SW_CHAN1_MUX_SEL_MASK, 1); 831ab569a4cSMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_10_SW, 832ab569a4cSMartin Blumenstingl MESON_SAR_ADC_CHAN_10_SW_CHAN1_MUX_SEL_MASK, 833ab569a4cSMartin Blumenstingl regval); 834ab569a4cSMartin Blumenstingl 835ab569a4cSMartin Blumenstingl /* 836ab569a4cSMartin Blumenstingl * set up the input channel muxes in MESON_SAR_ADC_AUX_SW 837ab569a4cSMartin Blumenstingl * (2 = SAR_ADC_CH2, 3 = SAR_ADC_CH3, ...) and enable 838ab569a4cSMartin Blumenstingl * MESON_SAR_ADC_AUX_SW_YP_DRIVE_SW and 839ab569a4cSMartin Blumenstingl * MESON_SAR_ADC_AUX_SW_XP_DRIVE_SW like the vendor driver. 840ab569a4cSMartin Blumenstingl */ 841ab569a4cSMartin Blumenstingl regval = 0; 842ab569a4cSMartin Blumenstingl for (i = 2; i <= 7; i++) 843ab569a4cSMartin Blumenstingl regval |= i << MESON_SAR_ADC_AUX_SW_MUX_SEL_CHAN_SHIFT(i); 844ab569a4cSMartin Blumenstingl regval |= MESON_SAR_ADC_AUX_SW_YP_DRIVE_SW; 845ab569a4cSMartin Blumenstingl regval |= MESON_SAR_ADC_AUX_SW_XP_DRIVE_SW; 846ab569a4cSMartin Blumenstingl regmap_write(priv->regmap, MESON_SAR_ADC_AUX_SW, regval); 847ab569a4cSMartin Blumenstingl 848723a61e0SMartin Blumenstingl if (priv->temperature_sensor_calibrated) { 849723a61e0SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELTA_10, 850723a61e0SMartin Blumenstingl MESON_SAR_ADC_DELTA_10_TS_REVE1, 851723a61e0SMartin Blumenstingl MESON_SAR_ADC_DELTA_10_TS_REVE1); 852723a61e0SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELTA_10, 853723a61e0SMartin Blumenstingl MESON_SAR_ADC_DELTA_10_TS_REVE0, 854723a61e0SMartin Blumenstingl MESON_SAR_ADC_DELTA_10_TS_REVE0); 855723a61e0SMartin Blumenstingl 856723a61e0SMartin Blumenstingl /* 857723a61e0SMartin Blumenstingl * set bits [3:0] of the TSC (temperature sensor coefficient) 858723a61e0SMartin Blumenstingl * to get the correct values when reading the temperature. 859723a61e0SMartin Blumenstingl */ 860723a61e0SMartin Blumenstingl regval = FIELD_PREP(MESON_SAR_ADC_DELTA_10_TS_C_MASK, 861723a61e0SMartin Blumenstingl priv->temperature_sensor_coefficient); 862723a61e0SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELTA_10, 863723a61e0SMartin Blumenstingl MESON_SAR_ADC_DELTA_10_TS_C_MASK, regval); 864723a61e0SMartin Blumenstingl } else { 865723a61e0SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELTA_10, 866723a61e0SMartin Blumenstingl MESON_SAR_ADC_DELTA_10_TS_REVE1, 0); 867723a61e0SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELTA_10, 868723a61e0SMartin Blumenstingl MESON_SAR_ADC_DELTA_10_TS_REVE0, 0); 869723a61e0SMartin Blumenstingl } 870723a61e0SMartin Blumenstingl 8713adbf342SMartin Blumenstingl ret = clk_set_parent(priv->adc_sel_clk, priv->clkin); 8723adbf342SMartin Blumenstingl if (ret) { 8733adbf342SMartin Blumenstingl dev_err(indio_dev->dev.parent, 8743adbf342SMartin Blumenstingl "failed to set adc parent to clkin\n"); 8753adbf342SMartin Blumenstingl return ret; 8763adbf342SMartin Blumenstingl } 8773adbf342SMartin Blumenstingl 878057e5a11SMartin Blumenstingl ret = clk_set_rate(priv->adc_clk, priv->param->clock_rate); 8793adbf342SMartin Blumenstingl if (ret) { 8803adbf342SMartin Blumenstingl dev_err(indio_dev->dev.parent, 8813adbf342SMartin Blumenstingl "failed to set adc clock rate\n"); 8823adbf342SMartin Blumenstingl return ret; 8833adbf342SMartin Blumenstingl } 8843adbf342SMartin Blumenstingl 8853adbf342SMartin Blumenstingl return 0; 8863adbf342SMartin Blumenstingl } 8873adbf342SMartin Blumenstingl 888d85eed9fSMartin Blumenstingl static void meson_sar_adc_set_bandgap(struct iio_dev *indio_dev, bool on_off) 889d85eed9fSMartin Blumenstingl { 890d85eed9fSMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 891057e5a11SMartin Blumenstingl const struct meson_sar_adc_param *param = priv->param; 892d85eed9fSMartin Blumenstingl u32 enable_mask; 893d85eed9fSMartin Blumenstingl 894053ffe3cSYixun Lan if (param->bandgap_reg == MESON_SAR_ADC_REG11) 895d85eed9fSMartin Blumenstingl enable_mask = MESON_SAR_ADC_REG11_BANDGAP_EN; 896d85eed9fSMartin Blumenstingl else 897d85eed9fSMartin Blumenstingl enable_mask = MESON_SAR_ADC_DELTA_10_TS_VBG_EN; 898d85eed9fSMartin Blumenstingl 899053ffe3cSYixun Lan regmap_update_bits(priv->regmap, param->bandgap_reg, enable_mask, 900d85eed9fSMartin Blumenstingl on_off ? enable_mask : 0); 901d85eed9fSMartin Blumenstingl } 902d85eed9fSMartin Blumenstingl 9033adbf342SMartin Blumenstingl static int meson_sar_adc_hw_enable(struct iio_dev *indio_dev) 9043adbf342SMartin Blumenstingl { 9053adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 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) { 9153adbf342SMartin Blumenstingl dev_err(indio_dev->dev.parent, 9163adbf342SMartin Blumenstingl "failed to enable vref regulator\n"); 9173adbf342SMartin Blumenstingl goto err_vref; 9183adbf342SMartin Blumenstingl } 9193adbf342SMartin Blumenstingl 9203adbf342SMartin Blumenstingl ret = clk_prepare_enable(priv->core_clk); 9213adbf342SMartin Blumenstingl if (ret) { 9223adbf342SMartin Blumenstingl dev_err(indio_dev->dev.parent, "failed to enable core clk\n"); 9233adbf342SMartin Blumenstingl goto err_core_clk; 9243adbf342SMartin Blumenstingl } 9253adbf342SMartin Blumenstingl 9263af10913SHeiner Kallweit regval = FIELD_PREP(MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, 1); 9273af10913SHeiner Kallweit regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, 9283af10913SHeiner Kallweit MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, regval); 929d85eed9fSMartin Blumenstingl 930d85eed9fSMartin Blumenstingl meson_sar_adc_set_bandgap(indio_dev, true); 931d85eed9fSMartin Blumenstingl 9323adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3, 9333adbf342SMartin Blumenstingl MESON_SAR_ADC_REG3_ADC_EN, 9343adbf342SMartin Blumenstingl MESON_SAR_ADC_REG3_ADC_EN); 9353adbf342SMartin Blumenstingl 9363adbf342SMartin Blumenstingl udelay(5); 9373adbf342SMartin Blumenstingl 9383adbf342SMartin Blumenstingl ret = clk_prepare_enable(priv->adc_clk); 9393adbf342SMartin Blumenstingl if (ret) { 9403adbf342SMartin Blumenstingl dev_err(indio_dev->dev.parent, "failed to enable adc clk\n"); 9413adbf342SMartin Blumenstingl goto err_adc_clk; 9423adbf342SMartin Blumenstingl } 9433adbf342SMartin Blumenstingl 9443adbf342SMartin Blumenstingl meson_sar_adc_unlock(indio_dev); 9453adbf342SMartin Blumenstingl 9463adbf342SMartin Blumenstingl return 0; 9473adbf342SMartin Blumenstingl 9483adbf342SMartin Blumenstingl err_adc_clk: 9493adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3, 9503adbf342SMartin Blumenstingl MESON_SAR_ADC_REG3_ADC_EN, 0); 951d85eed9fSMartin Blumenstingl meson_sar_adc_set_bandgap(indio_dev, false); 9523adbf342SMartin Blumenstingl clk_disable_unprepare(priv->core_clk); 9533adbf342SMartin Blumenstingl err_core_clk: 9543adbf342SMartin Blumenstingl regulator_disable(priv->vref); 9553adbf342SMartin Blumenstingl err_vref: 9563adbf342SMartin Blumenstingl meson_sar_adc_unlock(indio_dev); 9573adbf342SMartin Blumenstingl err_lock: 9583adbf342SMartin Blumenstingl return ret; 9593adbf342SMartin Blumenstingl } 9603adbf342SMartin Blumenstingl 9613adbf342SMartin Blumenstingl static int meson_sar_adc_hw_disable(struct iio_dev *indio_dev) 9623adbf342SMartin Blumenstingl { 9633adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 9643adbf342SMartin Blumenstingl int ret; 9653adbf342SMartin Blumenstingl 9663adbf342SMartin Blumenstingl ret = meson_sar_adc_lock(indio_dev); 9673adbf342SMartin Blumenstingl if (ret) 9683adbf342SMartin Blumenstingl return ret; 9693adbf342SMartin Blumenstingl 9703adbf342SMartin Blumenstingl clk_disable_unprepare(priv->adc_clk); 9713adbf342SMartin Blumenstingl 9723adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3, 9733adbf342SMartin Blumenstingl MESON_SAR_ADC_REG3_ADC_EN, 0); 974d85eed9fSMartin Blumenstingl 975d85eed9fSMartin Blumenstingl meson_sar_adc_set_bandgap(indio_dev, false); 9763adbf342SMartin Blumenstingl 9773adbf342SMartin Blumenstingl clk_disable_unprepare(priv->core_clk); 9783adbf342SMartin Blumenstingl 9793adbf342SMartin Blumenstingl regulator_disable(priv->vref); 9803adbf342SMartin Blumenstingl 9813adbf342SMartin Blumenstingl meson_sar_adc_unlock(indio_dev); 9823adbf342SMartin Blumenstingl 9833adbf342SMartin Blumenstingl return 0; 9843adbf342SMartin Blumenstingl } 9853adbf342SMartin Blumenstingl 9863af10913SHeiner Kallweit static irqreturn_t meson_sar_adc_irq(int irq, void *data) 9873af10913SHeiner Kallweit { 9883af10913SHeiner Kallweit struct iio_dev *indio_dev = data; 9893af10913SHeiner Kallweit struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 9903af10913SHeiner Kallweit unsigned int cnt, threshold; 9913af10913SHeiner Kallweit u32 regval; 9923af10913SHeiner Kallweit 9933af10913SHeiner Kallweit regmap_read(priv->regmap, MESON_SAR_ADC_REG0, ®val); 9943af10913SHeiner Kallweit cnt = FIELD_GET(MESON_SAR_ADC_REG0_FIFO_COUNT_MASK, regval); 9953af10913SHeiner Kallweit threshold = FIELD_GET(MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, regval); 9963af10913SHeiner Kallweit 9973af10913SHeiner Kallweit if (cnt < threshold) 9983af10913SHeiner Kallweit return IRQ_NONE; 9993af10913SHeiner Kallweit 10003af10913SHeiner Kallweit complete(&priv->done); 10013af10913SHeiner Kallweit 10023af10913SHeiner Kallweit return IRQ_HANDLED; 10033af10913SHeiner Kallweit } 10043af10913SHeiner Kallweit 100548ba7c3cSHeiner Kallweit static int meson_sar_adc_calib(struct iio_dev *indio_dev) 100648ba7c3cSHeiner Kallweit { 100748ba7c3cSHeiner Kallweit struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 100848ba7c3cSHeiner Kallweit int ret, nominal0, nominal1, value0, value1; 100948ba7c3cSHeiner Kallweit 101048ba7c3cSHeiner Kallweit /* use points 25% and 75% for calibration */ 1011057e5a11SMartin Blumenstingl nominal0 = (1 << priv->param->resolution) / 4; 1012057e5a11SMartin Blumenstingl nominal1 = (1 << priv->param->resolution) * 3 / 4; 101348ba7c3cSHeiner Kallweit 101448ba7c3cSHeiner Kallweit meson_sar_adc_set_chan7_mux(indio_dev, CHAN7_MUX_VDD_DIV4); 101548ba7c3cSHeiner Kallweit usleep_range(10, 20); 101648ba7c3cSHeiner Kallweit ret = meson_sar_adc_get_sample(indio_dev, 1017bdd4b07fSMartin Blumenstingl &indio_dev->channels[7], 101848ba7c3cSHeiner Kallweit MEAN_AVERAGING, EIGHT_SAMPLES, &value0); 101948ba7c3cSHeiner Kallweit if (ret < 0) 102048ba7c3cSHeiner Kallweit goto out; 102148ba7c3cSHeiner Kallweit 102248ba7c3cSHeiner Kallweit meson_sar_adc_set_chan7_mux(indio_dev, CHAN7_MUX_VDD_MUL3_DIV4); 102348ba7c3cSHeiner Kallweit usleep_range(10, 20); 102448ba7c3cSHeiner Kallweit ret = meson_sar_adc_get_sample(indio_dev, 1025bdd4b07fSMartin Blumenstingl &indio_dev->channels[7], 102648ba7c3cSHeiner Kallweit MEAN_AVERAGING, EIGHT_SAMPLES, &value1); 102748ba7c3cSHeiner Kallweit if (ret < 0) 102848ba7c3cSHeiner Kallweit goto out; 102948ba7c3cSHeiner Kallweit 103048ba7c3cSHeiner Kallweit if (value1 <= value0) { 103148ba7c3cSHeiner Kallweit ret = -EINVAL; 103248ba7c3cSHeiner Kallweit goto out; 103348ba7c3cSHeiner Kallweit } 103448ba7c3cSHeiner Kallweit 103548ba7c3cSHeiner Kallweit priv->calibscale = div_s64((nominal1 - nominal0) * (s64)MILLION, 103648ba7c3cSHeiner Kallweit value1 - value0); 103748ba7c3cSHeiner Kallweit priv->calibbias = nominal0 - div_s64((s64)value0 * priv->calibscale, 103848ba7c3cSHeiner Kallweit MILLION); 103948ba7c3cSHeiner Kallweit ret = 0; 104048ba7c3cSHeiner Kallweit out: 104148ba7c3cSHeiner Kallweit meson_sar_adc_set_chan7_mux(indio_dev, CHAN7_MUX_CH7_INPUT); 104248ba7c3cSHeiner Kallweit 104348ba7c3cSHeiner Kallweit return ret; 104448ba7c3cSHeiner Kallweit } 104548ba7c3cSHeiner Kallweit 10463adbf342SMartin Blumenstingl static const struct iio_info meson_sar_adc_iio_info = { 10473adbf342SMartin Blumenstingl .read_raw = meson_sar_adc_iio_info_read_raw, 10483adbf342SMartin Blumenstingl }; 10493adbf342SMartin Blumenstingl 1050053ffe3cSYixun Lan static const struct meson_sar_adc_param meson_sar_adc_meson8_param = { 10516c76ed31SMartin Blumenstingl .has_bl30_integration = false, 1052fda29dbaSMartin Blumenstingl .clock_rate = 1150000, 1053d85eed9fSMartin Blumenstingl .bandgap_reg = MESON_SAR_ADC_DELTA_10, 105496748823SMartin Blumenstingl .regmap_config = &meson_sar_adc_regmap_config_meson8, 10556c76ed31SMartin Blumenstingl .resolution = 10, 1056723a61e0SMartin Blumenstingl .temperature_trimming_bits = 4, 1057723a61e0SMartin Blumenstingl .temperature_multiplier = 18 * 10000, 1058723a61e0SMartin Blumenstingl .temperature_divider = 1024 * 10 * 85, 1059723a61e0SMartin Blumenstingl }; 1060723a61e0SMartin Blumenstingl 1061723a61e0SMartin Blumenstingl static const struct meson_sar_adc_param meson_sar_adc_meson8b_param = { 1062723a61e0SMartin Blumenstingl .has_bl30_integration = false, 1063723a61e0SMartin Blumenstingl .clock_rate = 1150000, 1064723a61e0SMartin Blumenstingl .bandgap_reg = MESON_SAR_ADC_DELTA_10, 1065723a61e0SMartin Blumenstingl .regmap_config = &meson_sar_adc_regmap_config_meson8, 1066723a61e0SMartin Blumenstingl .resolution = 10, 1067053ffe3cSYixun Lan }; 1068053ffe3cSYixun Lan 1069053ffe3cSYixun Lan static const struct meson_sar_adc_param meson_sar_adc_gxbb_param = { 1070053ffe3cSYixun Lan .has_bl30_integration = true, 1071053ffe3cSYixun Lan .clock_rate = 1200000, 1072053ffe3cSYixun Lan .bandgap_reg = MESON_SAR_ADC_REG11, 1073053ffe3cSYixun Lan .regmap_config = &meson_sar_adc_regmap_config_gxbb, 1074053ffe3cSYixun Lan .resolution = 10, 1075053ffe3cSYixun Lan }; 1076053ffe3cSYixun Lan 1077053ffe3cSYixun Lan static const struct meson_sar_adc_param meson_sar_adc_gxl_param = { 1078053ffe3cSYixun Lan .has_bl30_integration = true, 1079053ffe3cSYixun Lan .clock_rate = 1200000, 1080053ffe3cSYixun Lan .bandgap_reg = MESON_SAR_ADC_REG11, 1081053ffe3cSYixun Lan .regmap_config = &meson_sar_adc_regmap_config_gxbb, 1082053ffe3cSYixun Lan .resolution = 12, 1083053ffe3cSYixun Lan }; 1084053ffe3cSYixun Lan 1085053ffe3cSYixun Lan static const struct meson_sar_adc_data meson_sar_adc_meson8_data = { 1086053ffe3cSYixun Lan .param = &meson_sar_adc_meson8_param, 10876c76ed31SMartin Blumenstingl .name = "meson-meson8-saradc", 10886c76ed31SMartin Blumenstingl }; 10896c76ed31SMartin Blumenstingl 10906c76ed31SMartin Blumenstingl static const struct meson_sar_adc_data meson_sar_adc_meson8b_data = { 1091723a61e0SMartin Blumenstingl .param = &meson_sar_adc_meson8b_param, 10926c76ed31SMartin Blumenstingl .name = "meson-meson8b-saradc", 10936c76ed31SMartin Blumenstingl }; 10946c76ed31SMartin Blumenstingl 1095ffc0d638SMartin Blumenstingl static const struct meson_sar_adc_data meson_sar_adc_meson8m2_data = { 1096723a61e0SMartin Blumenstingl .param = &meson_sar_adc_meson8b_param, 1097ffc0d638SMartin Blumenstingl .name = "meson-meson8m2-saradc", 1098ffc0d638SMartin Blumenstingl }; 1099ffc0d638SMartin Blumenstingl 1100c1c2de37SMartin Blumenstingl static const struct meson_sar_adc_data meson_sar_adc_gxbb_data = { 1101053ffe3cSYixun Lan .param = &meson_sar_adc_gxbb_param, 11023adbf342SMartin Blumenstingl .name = "meson-gxbb-saradc", 11033adbf342SMartin Blumenstingl }; 11043adbf342SMartin Blumenstingl 1105c1c2de37SMartin Blumenstingl static const struct meson_sar_adc_data meson_sar_adc_gxl_data = { 1106053ffe3cSYixun Lan .param = &meson_sar_adc_gxl_param, 11073adbf342SMartin Blumenstingl .name = "meson-gxl-saradc", 11083adbf342SMartin Blumenstingl }; 11093adbf342SMartin Blumenstingl 1110c1c2de37SMartin Blumenstingl static const struct meson_sar_adc_data meson_sar_adc_gxm_data = { 1111053ffe3cSYixun Lan .param = &meson_sar_adc_gxl_param, 11123adbf342SMartin Blumenstingl .name = "meson-gxm-saradc", 11133adbf342SMartin Blumenstingl }; 11143adbf342SMartin Blumenstingl 1115ff632ddaSXingyu Chen static const struct meson_sar_adc_data meson_sar_adc_axg_data = { 1116ff632ddaSXingyu Chen .param = &meson_sar_adc_gxl_param, 1117ff632ddaSXingyu Chen .name = "meson-axg-saradc", 1118ff632ddaSXingyu Chen }; 1119ff632ddaSXingyu Chen 11203adbf342SMartin Blumenstingl static const struct of_device_id meson_sar_adc_of_match[] = { 11213adbf342SMartin Blumenstingl { 11226c76ed31SMartin Blumenstingl .compatible = "amlogic,meson8-saradc", 11236c76ed31SMartin Blumenstingl .data = &meson_sar_adc_meson8_data, 11246c76ed31SMartin Blumenstingl }, 11256c76ed31SMartin Blumenstingl { 11266c76ed31SMartin Blumenstingl .compatible = "amlogic,meson8b-saradc", 11276c76ed31SMartin Blumenstingl .data = &meson_sar_adc_meson8b_data, 11286c76ed31SMartin Blumenstingl }, 11296c76ed31SMartin Blumenstingl { 1130ffc0d638SMartin Blumenstingl .compatible = "amlogic,meson8m2-saradc", 1131ffc0d638SMartin Blumenstingl .data = &meson_sar_adc_meson8m2_data, 1132ffc0d638SMartin Blumenstingl }, 1133ffc0d638SMartin Blumenstingl { 11343adbf342SMartin Blumenstingl .compatible = "amlogic,meson-gxbb-saradc", 11353adbf342SMartin Blumenstingl .data = &meson_sar_adc_gxbb_data, 11363adbf342SMartin Blumenstingl }, { 11373adbf342SMartin Blumenstingl .compatible = "amlogic,meson-gxl-saradc", 11383adbf342SMartin Blumenstingl .data = &meson_sar_adc_gxl_data, 11393adbf342SMartin Blumenstingl }, { 11403adbf342SMartin Blumenstingl .compatible = "amlogic,meson-gxm-saradc", 11413adbf342SMartin Blumenstingl .data = &meson_sar_adc_gxm_data, 1142ff632ddaSXingyu Chen }, { 1143ff632ddaSXingyu Chen .compatible = "amlogic,meson-axg-saradc", 1144ff632ddaSXingyu Chen .data = &meson_sar_adc_axg_data, 11453adbf342SMartin Blumenstingl }, 11463adbf342SMartin Blumenstingl {}, 11473adbf342SMartin Blumenstingl }; 11483adbf342SMartin Blumenstingl MODULE_DEVICE_TABLE(of, meson_sar_adc_of_match); 11493adbf342SMartin Blumenstingl 11503adbf342SMartin Blumenstingl static int meson_sar_adc_probe(struct platform_device *pdev) 11513adbf342SMartin Blumenstingl { 1152234c64a2SMartin Blumenstingl const struct meson_sar_adc_data *match_data; 11533adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv; 11543adbf342SMartin Blumenstingl struct iio_dev *indio_dev; 11553adbf342SMartin Blumenstingl struct resource *res; 11563adbf342SMartin Blumenstingl void __iomem *base; 11573af10913SHeiner Kallweit int irq, ret; 11583adbf342SMartin Blumenstingl 11593adbf342SMartin Blumenstingl indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*priv)); 11603adbf342SMartin Blumenstingl if (!indio_dev) { 11613adbf342SMartin Blumenstingl dev_err(&pdev->dev, "failed allocating iio device\n"); 11623adbf342SMartin Blumenstingl return -ENOMEM; 11633adbf342SMartin Blumenstingl } 11643adbf342SMartin Blumenstingl 11653adbf342SMartin Blumenstingl priv = iio_priv(indio_dev); 11663af10913SHeiner Kallweit init_completion(&priv->done); 11673adbf342SMartin Blumenstingl 1168234c64a2SMartin Blumenstingl match_data = of_device_get_match_data(&pdev->dev); 1169234c64a2SMartin Blumenstingl if (!match_data) { 1170234c64a2SMartin Blumenstingl dev_err(&pdev->dev, "failed to get match data\n"); 11712f9aeeedSGustavo A. R. Silva return -ENODEV; 11722f9aeeedSGustavo A. R. Silva } 11732f9aeeedSGustavo A. R. Silva 1174057e5a11SMartin Blumenstingl priv->param = match_data->param; 11753adbf342SMartin Blumenstingl 1176057e5a11SMartin Blumenstingl indio_dev->name = match_data->name; 11773adbf342SMartin Blumenstingl indio_dev->dev.parent = &pdev->dev; 11783adbf342SMartin Blumenstingl indio_dev->dev.of_node = pdev->dev.of_node; 11793adbf342SMartin Blumenstingl indio_dev->modes = INDIO_DIRECT_MODE; 11803adbf342SMartin Blumenstingl indio_dev->info = &meson_sar_adc_iio_info; 11813adbf342SMartin Blumenstingl 11823adbf342SMartin Blumenstingl res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 11833adbf342SMartin Blumenstingl base = devm_ioremap_resource(&pdev->dev, res); 11843adbf342SMartin Blumenstingl if (IS_ERR(base)) 11853adbf342SMartin Blumenstingl return PTR_ERR(base); 11863adbf342SMartin Blumenstingl 11873af10913SHeiner Kallweit irq = irq_of_parse_and_map(pdev->dev.of_node, 0); 11883af10913SHeiner Kallweit if (!irq) 11893af10913SHeiner Kallweit return -EINVAL; 11903af10913SHeiner Kallweit 11913af10913SHeiner Kallweit ret = devm_request_irq(&pdev->dev, irq, meson_sar_adc_irq, IRQF_SHARED, 11923af10913SHeiner Kallweit dev_name(&pdev->dev), indio_dev); 11933af10913SHeiner Kallweit if (ret) 11943af10913SHeiner Kallweit return ret; 11953af10913SHeiner Kallweit 11963adbf342SMartin Blumenstingl priv->regmap = devm_regmap_init_mmio(&pdev->dev, base, 1197057e5a11SMartin Blumenstingl priv->param->regmap_config); 11983adbf342SMartin Blumenstingl if (IS_ERR(priv->regmap)) 11993adbf342SMartin Blumenstingl return PTR_ERR(priv->regmap); 12003adbf342SMartin Blumenstingl 12013adbf342SMartin Blumenstingl priv->clkin = devm_clk_get(&pdev->dev, "clkin"); 12023adbf342SMartin Blumenstingl if (IS_ERR(priv->clkin)) { 12033adbf342SMartin Blumenstingl dev_err(&pdev->dev, "failed to get clkin\n"); 12043adbf342SMartin Blumenstingl return PTR_ERR(priv->clkin); 12053adbf342SMartin Blumenstingl } 12063adbf342SMartin Blumenstingl 12073adbf342SMartin Blumenstingl priv->core_clk = devm_clk_get(&pdev->dev, "core"); 12083adbf342SMartin Blumenstingl if (IS_ERR(priv->core_clk)) { 12093adbf342SMartin Blumenstingl dev_err(&pdev->dev, "failed to get core clk\n"); 12103adbf342SMartin Blumenstingl return PTR_ERR(priv->core_clk); 12113adbf342SMartin Blumenstingl } 12123adbf342SMartin Blumenstingl 12133adbf342SMartin Blumenstingl priv->adc_clk = devm_clk_get(&pdev->dev, "adc_clk"); 12143adbf342SMartin Blumenstingl if (IS_ERR(priv->adc_clk)) { 12153adbf342SMartin Blumenstingl if (PTR_ERR(priv->adc_clk) == -ENOENT) { 12163adbf342SMartin Blumenstingl priv->adc_clk = NULL; 12173adbf342SMartin Blumenstingl } else { 12183adbf342SMartin Blumenstingl dev_err(&pdev->dev, "failed to get adc clk\n"); 12193adbf342SMartin Blumenstingl return PTR_ERR(priv->adc_clk); 12203adbf342SMartin Blumenstingl } 12213adbf342SMartin Blumenstingl } 12223adbf342SMartin Blumenstingl 12233adbf342SMartin Blumenstingl priv->adc_sel_clk = devm_clk_get(&pdev->dev, "adc_sel"); 12243adbf342SMartin Blumenstingl if (IS_ERR(priv->adc_sel_clk)) { 12253adbf342SMartin Blumenstingl if (PTR_ERR(priv->adc_sel_clk) == -ENOENT) { 12263adbf342SMartin Blumenstingl priv->adc_sel_clk = NULL; 12273adbf342SMartin Blumenstingl } else { 12283adbf342SMartin Blumenstingl dev_err(&pdev->dev, "failed to get adc_sel clk\n"); 12293adbf342SMartin Blumenstingl return PTR_ERR(priv->adc_sel_clk); 12303adbf342SMartin Blumenstingl } 12313adbf342SMartin Blumenstingl } 12323adbf342SMartin Blumenstingl 12333adbf342SMartin Blumenstingl /* on pre-GXBB SoCs the SAR ADC itself provides the ADC clock: */ 12343adbf342SMartin Blumenstingl if (!priv->adc_clk) { 12353adbf342SMartin Blumenstingl ret = meson_sar_adc_clk_init(indio_dev, base); 12363adbf342SMartin Blumenstingl if (ret) 12373adbf342SMartin Blumenstingl return ret; 12383adbf342SMartin Blumenstingl } 12393adbf342SMartin Blumenstingl 12403adbf342SMartin Blumenstingl priv->vref = devm_regulator_get(&pdev->dev, "vref"); 12413adbf342SMartin Blumenstingl if (IS_ERR(priv->vref)) { 12423adbf342SMartin Blumenstingl dev_err(&pdev->dev, "failed to get vref regulator\n"); 12433adbf342SMartin Blumenstingl return PTR_ERR(priv->vref); 12443adbf342SMartin Blumenstingl } 12453adbf342SMartin Blumenstingl 124648ba7c3cSHeiner Kallweit priv->calibscale = MILLION; 124748ba7c3cSHeiner Kallweit 1248723a61e0SMartin Blumenstingl if (priv->param->temperature_trimming_bits) { 1249723a61e0SMartin Blumenstingl ret = meson_sar_adc_temp_sensor_init(indio_dev); 1250723a61e0SMartin Blumenstingl if (ret) 1251723a61e0SMartin Blumenstingl return ret; 1252723a61e0SMartin Blumenstingl } 1253723a61e0SMartin Blumenstingl 1254723a61e0SMartin Blumenstingl if (priv->temperature_sensor_calibrated) { 1255723a61e0SMartin Blumenstingl indio_dev->channels = meson_sar_adc_and_temp_iio_channels; 1256723a61e0SMartin Blumenstingl indio_dev->num_channels = 1257723a61e0SMartin Blumenstingl ARRAY_SIZE(meson_sar_adc_and_temp_iio_channels); 1258723a61e0SMartin Blumenstingl } else { 1259723a61e0SMartin Blumenstingl indio_dev->channels = meson_sar_adc_iio_channels; 1260723a61e0SMartin Blumenstingl indio_dev->num_channels = 1261723a61e0SMartin Blumenstingl ARRAY_SIZE(meson_sar_adc_iio_channels); 1262723a61e0SMartin Blumenstingl } 1263723a61e0SMartin Blumenstingl 12643adbf342SMartin Blumenstingl ret = meson_sar_adc_init(indio_dev); 12653adbf342SMartin Blumenstingl if (ret) 12663adbf342SMartin Blumenstingl goto err; 12673adbf342SMartin Blumenstingl 12683adbf342SMartin Blumenstingl ret = meson_sar_adc_hw_enable(indio_dev); 12693adbf342SMartin Blumenstingl if (ret) 12703adbf342SMartin Blumenstingl goto err; 12713adbf342SMartin Blumenstingl 127248ba7c3cSHeiner Kallweit ret = meson_sar_adc_calib(indio_dev); 127348ba7c3cSHeiner Kallweit if (ret) 127448ba7c3cSHeiner Kallweit dev_warn(&pdev->dev, "calibration failed\n"); 127548ba7c3cSHeiner Kallweit 12763adbf342SMartin Blumenstingl platform_set_drvdata(pdev, indio_dev); 12773adbf342SMartin Blumenstingl 12783adbf342SMartin Blumenstingl ret = iio_device_register(indio_dev); 12793adbf342SMartin Blumenstingl if (ret) 12803adbf342SMartin Blumenstingl goto err_hw; 12813adbf342SMartin Blumenstingl 12823adbf342SMartin Blumenstingl return 0; 12833adbf342SMartin Blumenstingl 12843adbf342SMartin Blumenstingl err_hw: 12853adbf342SMartin Blumenstingl meson_sar_adc_hw_disable(indio_dev); 12863adbf342SMartin Blumenstingl err: 12873adbf342SMartin Blumenstingl return ret; 12883adbf342SMartin Blumenstingl } 12893adbf342SMartin Blumenstingl 12903adbf342SMartin Blumenstingl static int meson_sar_adc_remove(struct platform_device *pdev) 12913adbf342SMartin Blumenstingl { 12923adbf342SMartin Blumenstingl struct iio_dev *indio_dev = platform_get_drvdata(pdev); 12933adbf342SMartin Blumenstingl 12943adbf342SMartin Blumenstingl iio_device_unregister(indio_dev); 12953adbf342SMartin Blumenstingl 12963adbf342SMartin Blumenstingl return meson_sar_adc_hw_disable(indio_dev); 12973adbf342SMartin Blumenstingl } 12983adbf342SMartin Blumenstingl 12993adbf342SMartin Blumenstingl static int __maybe_unused meson_sar_adc_suspend(struct device *dev) 13003adbf342SMartin Blumenstingl { 13013adbf342SMartin Blumenstingl struct iio_dev *indio_dev = dev_get_drvdata(dev); 13023adbf342SMartin Blumenstingl 13033adbf342SMartin Blumenstingl return meson_sar_adc_hw_disable(indio_dev); 13043adbf342SMartin Blumenstingl } 13053adbf342SMartin Blumenstingl 13063adbf342SMartin Blumenstingl static int __maybe_unused meson_sar_adc_resume(struct device *dev) 13073adbf342SMartin Blumenstingl { 13083adbf342SMartin Blumenstingl struct iio_dev *indio_dev = dev_get_drvdata(dev); 13093adbf342SMartin Blumenstingl 13103adbf342SMartin Blumenstingl return meson_sar_adc_hw_enable(indio_dev); 13113adbf342SMartin Blumenstingl } 13123adbf342SMartin Blumenstingl 13133adbf342SMartin Blumenstingl static SIMPLE_DEV_PM_OPS(meson_sar_adc_pm_ops, 13143adbf342SMartin Blumenstingl meson_sar_adc_suspend, meson_sar_adc_resume); 13153adbf342SMartin Blumenstingl 13163adbf342SMartin Blumenstingl static struct platform_driver meson_sar_adc_driver = { 13173adbf342SMartin Blumenstingl .probe = meson_sar_adc_probe, 13183adbf342SMartin Blumenstingl .remove = meson_sar_adc_remove, 13193adbf342SMartin Blumenstingl .driver = { 13203adbf342SMartin Blumenstingl .name = "meson-saradc", 13213adbf342SMartin Blumenstingl .of_match_table = meson_sar_adc_of_match, 13223adbf342SMartin Blumenstingl .pm = &meson_sar_adc_pm_ops, 13233adbf342SMartin Blumenstingl }, 13243adbf342SMartin Blumenstingl }; 13253adbf342SMartin Blumenstingl 13263adbf342SMartin Blumenstingl module_platform_driver(meson_sar_adc_driver); 13273adbf342SMartin Blumenstingl 13283adbf342SMartin Blumenstingl MODULE_AUTHOR("Martin Blumenstingl <martin.blumenstingl@googlemail.com>"); 13293adbf342SMartin Blumenstingl MODULE_DESCRIPTION("Amlogic Meson SAR ADC driver"); 13303adbf342SMartin Blumenstingl MODULE_LICENSE("GPL v2"); 1331