147dd8378SNeil Armstrong // SPDX-License-Identifier: GPL-2.0 23adbf342SMartin Blumenstingl /* 33adbf342SMartin Blumenstingl * Amlogic Meson Successive Approximation Register (SAR) A/D Converter 43adbf342SMartin Blumenstingl * 53adbf342SMartin Blumenstingl * Copyright (C) 2017 Martin Blumenstingl <martin.blumenstingl@googlemail.com> 63adbf342SMartin Blumenstingl */ 73adbf342SMartin Blumenstingl 83adbf342SMartin Blumenstingl #include <linux/bitfield.h> 93adbf342SMartin Blumenstingl #include <linux/clk.h> 103adbf342SMartin Blumenstingl #include <linux/clk-provider.h> 113adbf342SMartin Blumenstingl #include <linux/delay.h> 123adbf342SMartin Blumenstingl #include <linux/io.h> 133adbf342SMartin Blumenstingl #include <linux/iio/iio.h> 143adbf342SMartin Blumenstingl #include <linux/module.h> 15d0c09264SNuno Sá #include <linux/mutex.h> 16723a61e0SMartin Blumenstingl #include <linux/nvmem-consumer.h> 173af10913SHeiner Kallweit #include <linux/interrupt.h> 183adbf342SMartin Blumenstingl #include <linux/of.h> 193af10913SHeiner Kallweit #include <linux/of_irq.h> 203adbf342SMartin Blumenstingl #include <linux/of_device.h> 213adbf342SMartin Blumenstingl #include <linux/platform_device.h> 223adbf342SMartin Blumenstingl #include <linux/regmap.h> 233adbf342SMartin Blumenstingl #include <linux/regulator/consumer.h> 24b002bf5fSMartin Blumenstingl #include <linux/mfd/syscon.h> 253adbf342SMartin Blumenstingl 263adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0 0x00 273adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_PANEL_DETECT BIT(31) 283adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_BUSY_MASK GENMASK(30, 28) 293adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_DELTA_BUSY BIT(30) 303adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_AVG_BUSY BIT(29) 313adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_SAMPLE_BUSY BIT(28) 323adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_FIFO_FULL BIT(27) 333adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_FIFO_EMPTY BIT(26) 343adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_FIFO_COUNT_MASK GENMASK(25, 21) 353adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_ADC_BIAS_CTRL_MASK GENMASK(20, 19) 363adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_CURR_CHAN_ID_MASK GENMASK(18, 16) 373adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_ADC_TEMP_SEN_SEL BIT(15) 383adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_SAMPLING_STOP BIT(14) 393adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_CHAN_DELTA_EN_MASK GENMASK(13, 12) 403adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_DETECT_IRQ_POL BIT(10) 413adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_DETECT_IRQ_EN BIT(9) 423adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK GENMASK(8, 4) 433adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_FIFO_IRQ_EN BIT(3) 443adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_SAMPLING_START BIT(2) 453adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_CONTINUOUS_EN BIT(1) 463adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE BIT(0) 473adbf342SMartin Blumenstingl 483adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_LIST 0x04 493adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_LIST_MAX_INDEX_MASK GENMASK(26, 24) 503adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_LIST_ENTRY_MASK(_chan) \ 513adbf342SMartin Blumenstingl (GENMASK(2, 0) << ((_chan) * 3)) 523adbf342SMartin Blumenstingl 533adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AVG_CNTL 0x08 543adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AVG_CNTL_AVG_MODE_SHIFT(_chan) \ 553adbf342SMartin Blumenstingl (16 + ((_chan) * 2)) 563adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AVG_CNTL_AVG_MODE_MASK(_chan) \ 573adbf342SMartin Blumenstingl (GENMASK(17, 16) << ((_chan) * 2)) 583adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AVG_CNTL_NUM_SAMPLES_SHIFT(_chan) \ 593adbf342SMartin Blumenstingl (0 + ((_chan) * 2)) 603adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AVG_CNTL_NUM_SAMPLES_MASK(_chan) \ 613adbf342SMartin Blumenstingl (GENMASK(1, 0) << ((_chan) * 2)) 623adbf342SMartin Blumenstingl 633adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3 0x0c 643adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_CNTL_USE_SC_DLY BIT(31) 653adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_CLK_EN BIT(30) 663adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_BL30_INITIALIZED BIT(28) 673adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_CTRL_CONT_RING_COUNTER_EN BIT(27) 683adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_CTRL_SAMPLING_CLOCK_PHASE BIT(26) 693adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_CTRL_CHAN7_MUX_SEL_MASK GENMASK(25, 23) 703adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_DETECT_EN BIT(22) 713adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_ADC_EN BIT(21) 723adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_PANEL_DETECT_COUNT_MASK GENMASK(20, 18) 733adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_PANEL_DETECT_FILTER_TB_MASK GENMASK(17, 16) 743adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_ADC_CLK_DIV_SHIFT 10 75c57fa003SGeorge Stark #define MESON_SAR_ADC_REG3_ADC_CLK_DIV_WIDTH 6 763adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_BLOCK_DLY_SEL_MASK GENMASK(9, 8) 773adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_BLOCK_DLY_MASK GENMASK(7, 0) 783adbf342SMartin Blumenstingl 793adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELAY 0x10 803adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELAY_INPUT_DLY_SEL_MASK GENMASK(25, 24) 813adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELAY_BL30_BUSY BIT(15) 823adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELAY_KERNEL_BUSY BIT(14) 833adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELAY_INPUT_DLY_CNT_MASK GENMASK(23, 16) 843adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELAY_SAMPLE_DLY_SEL_MASK GENMASK(9, 8) 853adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELAY_SAMPLE_DLY_CNT_MASK GENMASK(7, 0) 863adbf342SMartin Blumenstingl 873adbf342SMartin Blumenstingl #define MESON_SAR_ADC_LAST_RD 0x14 883adbf342SMartin Blumenstingl #define MESON_SAR_ADC_LAST_RD_LAST_CHANNEL1_MASK GENMASK(23, 16) 893adbf342SMartin Blumenstingl #define MESON_SAR_ADC_LAST_RD_LAST_CHANNEL0_MASK GENMASK(9, 0) 903adbf342SMartin Blumenstingl 913adbf342SMartin Blumenstingl #define MESON_SAR_ADC_FIFO_RD 0x18 923adbf342SMartin Blumenstingl #define MESON_SAR_ADC_FIFO_RD_CHAN_ID_MASK GENMASK(14, 12) 933adbf342SMartin Blumenstingl #define MESON_SAR_ADC_FIFO_RD_SAMPLE_VALUE_MASK GENMASK(11, 0) 943adbf342SMartin Blumenstingl 953adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AUX_SW 0x1c 96ab569a4cSMartin Blumenstingl #define MESON_SAR_ADC_AUX_SW_MUX_SEL_CHAN_SHIFT(_chan) \ 97ab569a4cSMartin Blumenstingl (8 + (((_chan) - 2) * 3)) 983adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AUX_SW_VREF_P_MUX BIT(6) 993adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AUX_SW_VREF_N_MUX BIT(5) 1003adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AUX_SW_MODE_SEL BIT(4) 1013adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AUX_SW_YP_DRIVE_SW BIT(3) 1023adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AUX_SW_XP_DRIVE_SW BIT(2) 1033adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AUX_SW_YM_DRIVE_SW BIT(1) 1043adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AUX_SW_XM_DRIVE_SW BIT(0) 1053adbf342SMartin Blumenstingl 1063adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW 0x20 1073adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_MUX_SEL_MASK GENMASK(25, 23) 1083adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_VREF_P_MUX BIT(22) 1093adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_VREF_N_MUX BIT(21) 1103adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_MODE_SEL BIT(20) 1113adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_YP_DRIVE_SW BIT(19) 1123adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_XP_DRIVE_SW BIT(18) 1133adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_YM_DRIVE_SW BIT(17) 1143adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_XM_DRIVE_SW BIT(16) 1153adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_MUX_SEL_MASK GENMASK(9, 7) 1163adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_VREF_P_MUX BIT(6) 1173adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_VREF_N_MUX BIT(5) 1183adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_MODE_SEL BIT(4) 1193adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_YP_DRIVE_SW BIT(3) 1203adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_XP_DRIVE_SW BIT(2) 1213adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_YM_DRIVE_SW BIT(1) 1223adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_XM_DRIVE_SW BIT(0) 1233adbf342SMartin Blumenstingl 1243adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW 0x24 1253adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_SW_EN BIT(26) 1263adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_MUX_MASK GENMASK(25, 23) 1273adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_VREF_P_MUX BIT(22) 1283adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_VREF_N_MUX BIT(21) 1293adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_MODE_SEL BIT(20) 1303adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_YP_DRIVE_SW BIT(19) 1313adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_XP_DRIVE_SW BIT(18) 1323adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_YM_DRIVE_SW BIT(17) 1333adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_XM_DRIVE_SW BIT(16) 1343adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_MUX_SEL_MASK GENMASK(9, 7) 1353adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_VREF_P_MUX BIT(6) 1363adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_VREF_N_MUX BIT(5) 1373adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_MODE_SEL BIT(4) 1383adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_YP_DRIVE_SW BIT(3) 1393adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_XP_DRIVE_SW BIT(2) 1403adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_YM_DRIVE_SW BIT(1) 1413adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_XM_DRIVE_SW BIT(0) 1423adbf342SMartin Blumenstingl 1433adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELTA_10 0x28 1443adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELTA_10_TEMP_SEL BIT(27) 1453adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELTA_10_TS_REVE1 BIT(26) 1463adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELTA_10_CHAN1_DELTA_VALUE_MASK GENMASK(25, 16) 1473adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELTA_10_TS_REVE0 BIT(15) 1483adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELTA_10_TS_C_MASK GENMASK(14, 11) 1493adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELTA_10_TS_VBG_EN BIT(10) 1503adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELTA_10_CHAN0_DELTA_VALUE_MASK GENMASK(9, 0) 1513adbf342SMartin Blumenstingl 1523adbf342SMartin Blumenstingl /* 1533adbf342SMartin Blumenstingl * NOTE: registers from here are undocumented (the vendor Linux kernel driver 1543adbf342SMartin Blumenstingl * and u-boot source served as reference). These only seem to be relevant on 1553adbf342SMartin Blumenstingl * GXBB and newer. 1563adbf342SMartin Blumenstingl */ 1573adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG11 0x2c 1583adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG11_BANDGAP_EN BIT(13) 1593adbf342SMartin Blumenstingl 1603adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG13 0x34 1613adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG13_12BIT_CALIBRATION_MASK GENMASK(13, 8) 1623adbf342SMartin Blumenstingl 1633adbf342SMartin Blumenstingl #define MESON_SAR_ADC_MAX_FIFO_SIZE 32 1643af10913SHeiner Kallweit #define MESON_SAR_ADC_TIMEOUT 100 /* ms */ 165723a61e0SMartin Blumenstingl #define MESON_SAR_ADC_VOLTAGE_AND_TEMP_CHANNEL 6 1663a06b284SGeorge Stark #define MESON_SAR_ADC_VOLTAGE_AND_MUX_CHANNEL 7 167723a61e0SMartin Blumenstingl #define MESON_SAR_ADC_TEMP_OFFSET 27 168723a61e0SMartin Blumenstingl 169723a61e0SMartin Blumenstingl /* temperature sensor calibration information in eFuse */ 170723a61e0SMartin Blumenstingl #define MESON_SAR_ADC_EFUSE_BYTES 4 171723a61e0SMartin Blumenstingl #define MESON_SAR_ADC_EFUSE_BYTE3_UPPER_ADC_VAL GENMASK(6, 0) 172723a61e0SMartin Blumenstingl #define MESON_SAR_ADC_EFUSE_BYTE3_IS_CALIBRATED BIT(7) 173723a61e0SMartin Blumenstingl 174b002bf5fSMartin Blumenstingl #define MESON_HHI_DPLL_TOP_0 0x318 175b002bf5fSMartin Blumenstingl #define MESON_HHI_DPLL_TOP_0_TSC_BIT4 BIT(9) 176b002bf5fSMartin 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 2063a06b284SGeorge Stark #define MESON_SAR_ADC_MUX(_chan, _sel) { \ 2073a06b284SGeorge Stark .type = IIO_VOLTAGE, \ 2083a06b284SGeorge Stark .channel = _chan, \ 2093a06b284SGeorge Stark .indexed = 1, \ 2103a06b284SGeorge Stark .address = MESON_SAR_ADC_VOLTAGE_AND_MUX_CHANNEL, \ 2113a06b284SGeorge Stark .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \ 2123a06b284SGeorge Stark BIT(IIO_CHAN_INFO_AVERAGE_RAW), \ 2133a06b284SGeorge Stark .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \ 2143a06b284SGeorge Stark .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_CALIBBIAS) | \ 2153a06b284SGeorge Stark BIT(IIO_CHAN_INFO_CALIBSCALE), \ 2163a06b284SGeorge Stark .datasheet_name = "SAR_ADC_MUX_"#_sel, \ 2173a06b284SGeorge Stark } 2183a06b284SGeorge Stark 219d26f0514SGeorge Stark enum meson_sar_adc_avg_mode { 220d26f0514SGeorge Stark NO_AVERAGING = 0x0, 221d26f0514SGeorge Stark MEAN_AVERAGING = 0x1, 222d26f0514SGeorge Stark MEDIAN_AVERAGING = 0x2, 223d26f0514SGeorge Stark }; 224d26f0514SGeorge Stark 225d26f0514SGeorge Stark enum meson_sar_adc_num_samples { 226d26f0514SGeorge Stark ONE_SAMPLE = 0x0, 227d26f0514SGeorge Stark TWO_SAMPLES = 0x1, 228d26f0514SGeorge Stark FOUR_SAMPLES = 0x2, 229d26f0514SGeorge Stark EIGHT_SAMPLES = 0x3, 230d26f0514SGeorge Stark }; 231d26f0514SGeorge Stark 232d26f0514SGeorge Stark enum meson_sar_adc_chan7_mux_sel { 233d26f0514SGeorge Stark CHAN7_MUX_VSS = 0x0, 234d26f0514SGeorge Stark CHAN7_MUX_VDD_DIV4 = 0x1, 235d26f0514SGeorge Stark CHAN7_MUX_VDD_DIV2 = 0x2, 236d26f0514SGeorge Stark CHAN7_MUX_VDD_MUL3_DIV4 = 0x3, 237d26f0514SGeorge Stark CHAN7_MUX_VDD = 0x4, 238d26f0514SGeorge Stark CHAN7_MUX_CH7_INPUT = 0x7, 239d26f0514SGeorge Stark }; 240d26f0514SGeorge Stark 241c38180bfSGeorge Stark enum meson_sar_adc_channel_index { 242c38180bfSGeorge Stark NUM_CHAN_0, 243c38180bfSGeorge Stark NUM_CHAN_1, 244c38180bfSGeorge Stark NUM_CHAN_2, 245c38180bfSGeorge Stark NUM_CHAN_3, 246c38180bfSGeorge Stark NUM_CHAN_4, 247c38180bfSGeorge Stark NUM_CHAN_5, 248c38180bfSGeorge Stark NUM_CHAN_6, 249c38180bfSGeorge Stark NUM_CHAN_7, 250c38180bfSGeorge Stark NUM_CHAN_TEMP, 2513a06b284SGeorge Stark NUM_MUX_0_VSS, 2523a06b284SGeorge Stark NUM_MUX_1_VDD_DIV4, 2533a06b284SGeorge Stark NUM_MUX_2_VDD_DIV2, 2543a06b284SGeorge Stark NUM_MUX_3_VDD_MUL3_DIV4, 2553a06b284SGeorge Stark NUM_MUX_4_VDD, 2563a06b284SGeorge Stark }; 2573a06b284SGeorge Stark 2583a06b284SGeorge Stark static enum meson_sar_adc_chan7_mux_sel chan7_mux_values[] = { 2593a06b284SGeorge Stark CHAN7_MUX_VSS, 2603a06b284SGeorge Stark CHAN7_MUX_VDD_DIV4, 2613a06b284SGeorge Stark CHAN7_MUX_VDD_DIV2, 2623a06b284SGeorge Stark CHAN7_MUX_VDD_MUL3_DIV4, 2633a06b284SGeorge Stark CHAN7_MUX_VDD, 2643a06b284SGeorge Stark }; 2653a06b284SGeorge Stark 2663a06b284SGeorge Stark static const char * const chan7_mux_names[] = { 2673a06b284SGeorge Stark [CHAN7_MUX_VSS] = "gnd", 2683a06b284SGeorge Stark [CHAN7_MUX_VDD_DIV4] = "0.25vdd", 2693a06b284SGeorge Stark [CHAN7_MUX_VDD_DIV2] = "0.5vdd", 2703a06b284SGeorge Stark [CHAN7_MUX_VDD_MUL3_DIV4] = "0.75vdd", 2713a06b284SGeorge Stark [CHAN7_MUX_VDD] = "vdd", 272c38180bfSGeorge Stark }; 273c38180bfSGeorge Stark 2743adbf342SMartin Blumenstingl static const struct iio_chan_spec meson_sar_adc_iio_channels[] = { 275c38180bfSGeorge Stark MESON_SAR_ADC_CHAN(NUM_CHAN_0), 276c38180bfSGeorge Stark MESON_SAR_ADC_CHAN(NUM_CHAN_1), 277c38180bfSGeorge Stark MESON_SAR_ADC_CHAN(NUM_CHAN_2), 278c38180bfSGeorge Stark MESON_SAR_ADC_CHAN(NUM_CHAN_3), 279c38180bfSGeorge Stark MESON_SAR_ADC_CHAN(NUM_CHAN_4), 280c38180bfSGeorge Stark MESON_SAR_ADC_CHAN(NUM_CHAN_5), 281c38180bfSGeorge Stark MESON_SAR_ADC_CHAN(NUM_CHAN_6), 282c38180bfSGeorge Stark MESON_SAR_ADC_CHAN(NUM_CHAN_7), 2833a06b284SGeorge Stark MESON_SAR_ADC_MUX(NUM_MUX_0_VSS, 0), 2843a06b284SGeorge Stark MESON_SAR_ADC_MUX(NUM_MUX_1_VDD_DIV4, 1), 2853a06b284SGeorge Stark MESON_SAR_ADC_MUX(NUM_MUX_2_VDD_DIV2, 2), 2863a06b284SGeorge Stark MESON_SAR_ADC_MUX(NUM_MUX_3_VDD_MUL3_DIV4, 3), 2873a06b284SGeorge Stark MESON_SAR_ADC_MUX(NUM_MUX_4_VDD, 4), 2883adbf342SMartin Blumenstingl }; 2893adbf342SMartin Blumenstingl 290723a61e0SMartin Blumenstingl static const struct iio_chan_spec meson_sar_adc_and_temp_iio_channels[] = { 291c38180bfSGeorge Stark MESON_SAR_ADC_CHAN(NUM_CHAN_0), 292c38180bfSGeorge Stark MESON_SAR_ADC_CHAN(NUM_CHAN_1), 293c38180bfSGeorge Stark MESON_SAR_ADC_CHAN(NUM_CHAN_2), 294c38180bfSGeorge Stark MESON_SAR_ADC_CHAN(NUM_CHAN_3), 295c38180bfSGeorge Stark MESON_SAR_ADC_CHAN(NUM_CHAN_4), 296c38180bfSGeorge Stark MESON_SAR_ADC_CHAN(NUM_CHAN_5), 297c38180bfSGeorge Stark MESON_SAR_ADC_CHAN(NUM_CHAN_6), 298c38180bfSGeorge Stark MESON_SAR_ADC_CHAN(NUM_CHAN_7), 299c38180bfSGeorge Stark MESON_SAR_ADC_TEMP_CHAN(NUM_CHAN_TEMP), 3003a06b284SGeorge Stark MESON_SAR_ADC_MUX(NUM_MUX_0_VSS, 0), 3013a06b284SGeorge Stark MESON_SAR_ADC_MUX(NUM_MUX_1_VDD_DIV4, 1), 3023a06b284SGeorge Stark MESON_SAR_ADC_MUX(NUM_MUX_2_VDD_DIV2, 2), 3033a06b284SGeorge Stark MESON_SAR_ADC_MUX(NUM_MUX_3_VDD_MUL3_DIV4, 3), 3043a06b284SGeorge Stark MESON_SAR_ADC_MUX(NUM_MUX_4_VDD, 4), 305723a61e0SMartin Blumenstingl }; 306723a61e0SMartin Blumenstingl 307053ffe3cSYixun Lan struct meson_sar_adc_param { 3086c76ed31SMartin Blumenstingl bool has_bl30_integration; 309fda29dbaSMartin Blumenstingl unsigned long clock_rate; 310d85eed9fSMartin Blumenstingl u32 bandgap_reg; 3113adbf342SMartin Blumenstingl unsigned int resolution; 31296748823SMartin Blumenstingl const struct regmap_config *regmap_config; 313723a61e0SMartin Blumenstingl u8 temperature_trimming_bits; 314723a61e0SMartin Blumenstingl unsigned int temperature_multiplier; 315723a61e0SMartin Blumenstingl unsigned int temperature_divider; 3163adbf342SMartin Blumenstingl }; 3173adbf342SMartin Blumenstingl 318053ffe3cSYixun Lan struct meson_sar_adc_data { 319053ffe3cSYixun Lan const struct meson_sar_adc_param *param; 320053ffe3cSYixun Lan const char *name; 321053ffe3cSYixun Lan }; 322053ffe3cSYixun Lan 3233adbf342SMartin Blumenstingl struct meson_sar_adc_priv { 3243adbf342SMartin Blumenstingl struct regmap *regmap; 3253adbf342SMartin Blumenstingl struct regulator *vref; 326057e5a11SMartin Blumenstingl const struct meson_sar_adc_param *param; 3273adbf342SMartin Blumenstingl struct clk *clkin; 3283adbf342SMartin Blumenstingl struct clk *core_clk; 3293adbf342SMartin Blumenstingl struct clk *adc_sel_clk; 3303adbf342SMartin Blumenstingl struct clk *adc_clk; 3313adbf342SMartin Blumenstingl struct clk_gate clk_gate; 3323adbf342SMartin Blumenstingl struct clk *adc_div_clk; 3333adbf342SMartin Blumenstingl struct clk_divider clk_div; 3343af10913SHeiner Kallweit struct completion done; 335d0c09264SNuno Sá /* lock to protect against multiple access to the device */ 336d0c09264SNuno Sá struct mutex lock; 33748ba7c3cSHeiner Kallweit int calibbias; 33848ba7c3cSHeiner Kallweit int calibscale; 339b002bf5fSMartin Blumenstingl struct regmap *tsc_regmap; 340723a61e0SMartin Blumenstingl bool temperature_sensor_calibrated; 341723a61e0SMartin Blumenstingl u8 temperature_sensor_coefficient; 342723a61e0SMartin Blumenstingl u16 temperature_sensor_adc_val; 3433a06b284SGeorge Stark enum meson_sar_adc_chan7_mux_sel chan7_mux_sel; 3443adbf342SMartin Blumenstingl }; 3453adbf342SMartin Blumenstingl 34696748823SMartin Blumenstingl static const struct regmap_config meson_sar_adc_regmap_config_gxbb = { 3473adbf342SMartin Blumenstingl .reg_bits = 8, 3483adbf342SMartin Blumenstingl .val_bits = 32, 3493adbf342SMartin Blumenstingl .reg_stride = 4, 3503adbf342SMartin Blumenstingl .max_register = MESON_SAR_ADC_REG13, 3513adbf342SMartin Blumenstingl }; 3523adbf342SMartin Blumenstingl 35396748823SMartin Blumenstingl static const struct regmap_config meson_sar_adc_regmap_config_meson8 = { 35496748823SMartin Blumenstingl .reg_bits = 8, 35596748823SMartin Blumenstingl .val_bits = 32, 35696748823SMartin Blumenstingl .reg_stride = 4, 35796748823SMartin Blumenstingl .max_register = MESON_SAR_ADC_DELTA_10, 35896748823SMartin Blumenstingl }; 35996748823SMartin Blumenstingl 3603a06b284SGeorge Stark static const struct iio_chan_spec * 3613a06b284SGeorge Stark find_channel_by_num(struct iio_dev *indio_dev, int num) 3623a06b284SGeorge Stark { 3633a06b284SGeorge Stark int i; 3643a06b284SGeorge Stark 3653a06b284SGeorge Stark for (i = 0; i < indio_dev->num_channels; i++) 3663a06b284SGeorge Stark if (indio_dev->channels[i].channel == num) 3673a06b284SGeorge Stark return &indio_dev->channels[i]; 3683a06b284SGeorge Stark return NULL; 3693a06b284SGeorge Stark } 3703a06b284SGeorge Stark 3713adbf342SMartin Blumenstingl static unsigned int meson_sar_adc_get_fifo_count(struct iio_dev *indio_dev) 3723adbf342SMartin Blumenstingl { 3733adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 3743adbf342SMartin Blumenstingl u32 regval; 3753adbf342SMartin Blumenstingl 3763adbf342SMartin Blumenstingl regmap_read(priv->regmap, MESON_SAR_ADC_REG0, ®val); 3773adbf342SMartin Blumenstingl 3783adbf342SMartin Blumenstingl return FIELD_GET(MESON_SAR_ADC_REG0_FIFO_COUNT_MASK, regval); 3793adbf342SMartin Blumenstingl } 3803adbf342SMartin Blumenstingl 38148ba7c3cSHeiner Kallweit static int meson_sar_adc_calib_val(struct iio_dev *indio_dev, int val) 38248ba7c3cSHeiner Kallweit { 38348ba7c3cSHeiner Kallweit struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 38448ba7c3cSHeiner Kallweit int tmp; 38548ba7c3cSHeiner Kallweit 38648ba7c3cSHeiner Kallweit /* use val_calib = scale * val_raw + offset calibration function */ 38748ba7c3cSHeiner Kallweit tmp = div_s64((s64)val * priv->calibscale, MILLION) + priv->calibbias; 38848ba7c3cSHeiner Kallweit 389057e5a11SMartin Blumenstingl return clamp(tmp, 0, (1 << priv->param->resolution) - 1); 39048ba7c3cSHeiner Kallweit } 39148ba7c3cSHeiner Kallweit 3923adbf342SMartin Blumenstingl static int meson_sar_adc_wait_busy_clear(struct iio_dev *indio_dev) 3933adbf342SMartin Blumenstingl { 3943adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 39579b584edSAndy Shevchenko int val; 3963adbf342SMartin Blumenstingl 3973adbf342SMartin Blumenstingl /* 3983adbf342SMartin Blumenstingl * NOTE: we need a small delay before reading the status, otherwise 3993adbf342SMartin Blumenstingl * the sample engine may not have started internally (which would 4003adbf342SMartin Blumenstingl * seem to us that sampling is already finished). 4013adbf342SMartin Blumenstingl */ 4023adbf342SMartin Blumenstingl udelay(1); 40379b584edSAndy Shevchenko return regmap_read_poll_timeout_atomic(priv->regmap, MESON_SAR_ADC_REG0, val, 40479b584edSAndy Shevchenko !FIELD_GET(MESON_SAR_ADC_REG0_BUSY_MASK, val), 40579b584edSAndy Shevchenko 1, 10000); 4063adbf342SMartin Blumenstingl } 4073adbf342SMartin Blumenstingl 4082b592ff4SGeorge Stark static void meson_sar_adc_set_chan7_mux(struct iio_dev *indio_dev, 4092b592ff4SGeorge Stark enum meson_sar_adc_chan7_mux_sel sel) 4102b592ff4SGeorge Stark { 4112b592ff4SGeorge Stark struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 4122b592ff4SGeorge Stark u32 regval; 4132b592ff4SGeorge Stark 4142b592ff4SGeorge Stark regval = FIELD_PREP(MESON_SAR_ADC_REG3_CTRL_CHAN7_MUX_SEL_MASK, sel); 4152b592ff4SGeorge Stark regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3, 4162b592ff4SGeorge Stark MESON_SAR_ADC_REG3_CTRL_CHAN7_MUX_SEL_MASK, regval); 4172b592ff4SGeorge Stark 4182b592ff4SGeorge Stark usleep_range(10, 20); 4193a06b284SGeorge Stark 4203a06b284SGeorge Stark priv->chan7_mux_sel = sel; 4212b592ff4SGeorge Stark } 4222b592ff4SGeorge Stark 4233adbf342SMartin Blumenstingl static int meson_sar_adc_read_raw_sample(struct iio_dev *indio_dev, 4243adbf342SMartin Blumenstingl const struct iio_chan_spec *chan, 4253adbf342SMartin Blumenstingl int *val) 4263adbf342SMartin Blumenstingl { 4273adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 428d43c7006SAndy Shevchenko struct device *dev = indio_dev->dev.parent; 4296a882a2cSHeiner Kallweit int regval, fifo_chan, fifo_val, count; 4303adbf342SMartin Blumenstingl 4313af10913SHeiner Kallweit if (!wait_for_completion_timeout(&priv->done, 4323af10913SHeiner Kallweit msecs_to_jiffies(MESON_SAR_ADC_TIMEOUT))) 4333af10913SHeiner Kallweit return -ETIMEDOUT; 4343adbf342SMartin Blumenstingl 4356a882a2cSHeiner Kallweit count = meson_sar_adc_get_fifo_count(indio_dev); 4366a882a2cSHeiner Kallweit if (count != 1) { 437d43c7006SAndy Shevchenko dev_err(dev, "ADC FIFO has %d element(s) instead of one\n", count); 4386a882a2cSHeiner Kallweit return -EINVAL; 4393adbf342SMartin Blumenstingl } 4403adbf342SMartin Blumenstingl 4416a882a2cSHeiner Kallweit regmap_read(priv->regmap, MESON_SAR_ADC_FIFO_RD, ®val); 4426a882a2cSHeiner Kallweit fifo_chan = FIELD_GET(MESON_SAR_ADC_FIFO_RD_CHAN_ID_MASK, regval); 443827df057SMartin Blumenstingl if (fifo_chan != chan->address) { 444d43c7006SAndy Shevchenko dev_err(dev, "ADC FIFO entry belongs to channel %d instead of %lu\n", 445827df057SMartin Blumenstingl fifo_chan, chan->address); 4466a882a2cSHeiner Kallweit return -EINVAL; 4476a882a2cSHeiner Kallweit } 4483adbf342SMartin Blumenstingl 4496a882a2cSHeiner Kallweit fifo_val = FIELD_GET(MESON_SAR_ADC_FIFO_RD_SAMPLE_VALUE_MASK, regval); 450057e5a11SMartin Blumenstingl fifo_val &= GENMASK(priv->param->resolution - 1, 0); 45148ba7c3cSHeiner Kallweit *val = meson_sar_adc_calib_val(indio_dev, fifo_val); 4523adbf342SMartin Blumenstingl 4533adbf342SMartin Blumenstingl return 0; 4543adbf342SMartin Blumenstingl } 4553adbf342SMartin Blumenstingl 4563adbf342SMartin Blumenstingl static void meson_sar_adc_set_averaging(struct iio_dev *indio_dev, 4573adbf342SMartin Blumenstingl const struct iio_chan_spec *chan, 4583adbf342SMartin Blumenstingl enum meson_sar_adc_avg_mode mode, 4593adbf342SMartin Blumenstingl enum meson_sar_adc_num_samples samples) 4603adbf342SMartin Blumenstingl { 4613adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 462827df057SMartin Blumenstingl int val, address = chan->address; 4633adbf342SMartin Blumenstingl 464827df057SMartin Blumenstingl val = samples << MESON_SAR_ADC_AVG_CNTL_NUM_SAMPLES_SHIFT(address); 4653adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_AVG_CNTL, 466827df057SMartin Blumenstingl MESON_SAR_ADC_AVG_CNTL_NUM_SAMPLES_MASK(address), 4673adbf342SMartin Blumenstingl val); 4683adbf342SMartin Blumenstingl 469827df057SMartin Blumenstingl val = mode << MESON_SAR_ADC_AVG_CNTL_AVG_MODE_SHIFT(address); 4703adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_AVG_CNTL, 471827df057SMartin Blumenstingl MESON_SAR_ADC_AVG_CNTL_AVG_MODE_MASK(address), val); 4723adbf342SMartin Blumenstingl } 4733adbf342SMartin Blumenstingl 4743adbf342SMartin Blumenstingl static void meson_sar_adc_enable_channel(struct iio_dev *indio_dev, 4753adbf342SMartin Blumenstingl const struct iio_chan_spec *chan) 4763adbf342SMartin Blumenstingl { 4773adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 4783adbf342SMartin Blumenstingl u32 regval; 4793adbf342SMartin Blumenstingl 4803adbf342SMartin Blumenstingl /* 4813adbf342SMartin Blumenstingl * the SAR ADC engine allows sampling multiple channels at the same 4823adbf342SMartin Blumenstingl * time. to keep it simple we're only working with one *internal* 4833adbf342SMartin Blumenstingl * channel, which starts counting at index 0 (which means: count = 1). 4843adbf342SMartin Blumenstingl */ 4853adbf342SMartin Blumenstingl regval = FIELD_PREP(MESON_SAR_ADC_CHAN_LIST_MAX_INDEX_MASK, 0); 4863adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_LIST, 4873adbf342SMartin Blumenstingl MESON_SAR_ADC_CHAN_LIST_MAX_INDEX_MASK, regval); 4883adbf342SMartin Blumenstingl 4893adbf342SMartin Blumenstingl /* map channel index 0 to the channel which we want to read */ 4903adbf342SMartin Blumenstingl regval = FIELD_PREP(MESON_SAR_ADC_CHAN_LIST_ENTRY_MASK(0), 491827df057SMartin Blumenstingl chan->address); 4923adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_LIST, 4933adbf342SMartin Blumenstingl MESON_SAR_ADC_CHAN_LIST_ENTRY_MASK(0), regval); 4943adbf342SMartin Blumenstingl 4953adbf342SMartin Blumenstingl regval = FIELD_PREP(MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_MUX_MASK, 496827df057SMartin Blumenstingl chan->address); 4973adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DETECT_IDLE_SW, 4983adbf342SMartin Blumenstingl MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_MUX_MASK, 4993adbf342SMartin Blumenstingl regval); 5003adbf342SMartin Blumenstingl 5013adbf342SMartin Blumenstingl regval = FIELD_PREP(MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_MUX_SEL_MASK, 502827df057SMartin Blumenstingl chan->address); 5033adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DETECT_IDLE_SW, 5043adbf342SMartin Blumenstingl MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_MUX_SEL_MASK, 5053adbf342SMartin Blumenstingl regval); 5063adbf342SMartin Blumenstingl 507723a61e0SMartin Blumenstingl if (chan->address == MESON_SAR_ADC_VOLTAGE_AND_TEMP_CHANNEL) { 508723a61e0SMartin Blumenstingl if (chan->type == IIO_TEMP) 509723a61e0SMartin Blumenstingl regval = MESON_SAR_ADC_DELTA_10_TEMP_SEL; 510723a61e0SMartin Blumenstingl else 511723a61e0SMartin Blumenstingl regval = 0; 512723a61e0SMartin Blumenstingl 513723a61e0SMartin Blumenstingl regmap_update_bits(priv->regmap, 514723a61e0SMartin Blumenstingl MESON_SAR_ADC_DELTA_10, 515723a61e0SMartin Blumenstingl MESON_SAR_ADC_DELTA_10_TEMP_SEL, regval); 5163a06b284SGeorge Stark } else if (chan->address == MESON_SAR_ADC_VOLTAGE_AND_MUX_CHANNEL) { 5173a06b284SGeorge Stark enum meson_sar_adc_chan7_mux_sel sel; 5183a06b284SGeorge Stark 5193a06b284SGeorge Stark if (chan->channel == NUM_CHAN_7) 5203a06b284SGeorge Stark sel = CHAN7_MUX_CH7_INPUT; 5213a06b284SGeorge Stark else 5223a06b284SGeorge Stark sel = chan7_mux_values[chan->channel - NUM_MUX_0_VSS]; 5233a06b284SGeorge Stark if (sel != priv->chan7_mux_sel) 5243a06b284SGeorge Stark meson_sar_adc_set_chan7_mux(indio_dev, sel); 525723a61e0SMartin Blumenstingl } 5263adbf342SMartin Blumenstingl } 5273adbf342SMartin Blumenstingl 5283adbf342SMartin Blumenstingl static void meson_sar_adc_start_sample_engine(struct iio_dev *indio_dev) 5293adbf342SMartin Blumenstingl { 5303adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 5313adbf342SMartin Blumenstingl 5323af10913SHeiner Kallweit reinit_completion(&priv->done); 5333af10913SHeiner Kallweit 5343af10913SHeiner Kallweit regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, 5353af10913SHeiner Kallweit MESON_SAR_ADC_REG0_FIFO_IRQ_EN, 5363af10913SHeiner Kallweit MESON_SAR_ADC_REG0_FIFO_IRQ_EN); 5373af10913SHeiner Kallweit 5383adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, 5393adbf342SMartin Blumenstingl MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE, 5403adbf342SMartin Blumenstingl MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE); 5413adbf342SMartin Blumenstingl 5423adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, 5433adbf342SMartin Blumenstingl MESON_SAR_ADC_REG0_SAMPLING_START, 5443adbf342SMartin Blumenstingl MESON_SAR_ADC_REG0_SAMPLING_START); 5453adbf342SMartin Blumenstingl } 5463adbf342SMartin Blumenstingl 5473adbf342SMartin Blumenstingl static void meson_sar_adc_stop_sample_engine(struct iio_dev *indio_dev) 5483adbf342SMartin Blumenstingl { 5493adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 5503adbf342SMartin Blumenstingl 5513adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, 5523af10913SHeiner Kallweit MESON_SAR_ADC_REG0_FIFO_IRQ_EN, 0); 5533af10913SHeiner Kallweit 5543af10913SHeiner Kallweit regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, 5553adbf342SMartin Blumenstingl MESON_SAR_ADC_REG0_SAMPLING_STOP, 5563adbf342SMartin Blumenstingl MESON_SAR_ADC_REG0_SAMPLING_STOP); 5573adbf342SMartin Blumenstingl 5583adbf342SMartin Blumenstingl /* wait until all modules are stopped */ 5593adbf342SMartin Blumenstingl meson_sar_adc_wait_busy_clear(indio_dev); 5603adbf342SMartin Blumenstingl 5613adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, 5623adbf342SMartin Blumenstingl MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE, 0); 5633adbf342SMartin Blumenstingl } 5643adbf342SMartin Blumenstingl 5653adbf342SMartin Blumenstingl static int meson_sar_adc_lock(struct iio_dev *indio_dev) 5663adbf342SMartin Blumenstingl { 5673adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 56879b584edSAndy Shevchenko int val, ret; 5693adbf342SMartin Blumenstingl 570d0c09264SNuno Sá mutex_lock(&priv->lock); 5713adbf342SMartin Blumenstingl 572057e5a11SMartin Blumenstingl if (priv->param->has_bl30_integration) { 5733adbf342SMartin Blumenstingl /* prevent BL30 from using the SAR ADC while we are using it */ 5743adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY, 5753adbf342SMartin Blumenstingl MESON_SAR_ADC_DELAY_KERNEL_BUSY, 5763adbf342SMartin Blumenstingl MESON_SAR_ADC_DELAY_KERNEL_BUSY); 5773adbf342SMartin Blumenstingl 57879b584edSAndy Shevchenko udelay(1); 57979b584edSAndy Shevchenko 5806c76ed31SMartin Blumenstingl /* 5816c76ed31SMartin Blumenstingl * wait until BL30 releases it's lock (so we can use the SAR 5826c76ed31SMartin Blumenstingl * ADC) 5836c76ed31SMartin Blumenstingl */ 58479b584edSAndy Shevchenko ret = regmap_read_poll_timeout_atomic(priv->regmap, MESON_SAR_ADC_DELAY, val, 58579b584edSAndy Shevchenko !(val & MESON_SAR_ADC_DELAY_BL30_BUSY), 58679b584edSAndy Shevchenko 1, 10000); 58779b584edSAndy Shevchenko if (ret) { 588d0c09264SNuno Sá mutex_unlock(&priv->lock); 58979b584edSAndy Shevchenko return ret; 5906c76ed31SMartin Blumenstingl } 5913c3e4b3aSDan Carpenter } 5923adbf342SMartin Blumenstingl 5933adbf342SMartin Blumenstingl return 0; 5943adbf342SMartin Blumenstingl } 5953adbf342SMartin Blumenstingl 5963adbf342SMartin Blumenstingl static void meson_sar_adc_unlock(struct iio_dev *indio_dev) 5973adbf342SMartin Blumenstingl { 5983adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 5993adbf342SMartin Blumenstingl 600057e5a11SMartin Blumenstingl if (priv->param->has_bl30_integration) 6013adbf342SMartin Blumenstingl /* allow BL30 to use the SAR ADC again */ 6023adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY, 6033adbf342SMartin Blumenstingl MESON_SAR_ADC_DELAY_KERNEL_BUSY, 0); 6043adbf342SMartin Blumenstingl 605d0c09264SNuno Sá mutex_unlock(&priv->lock); 6063adbf342SMartin Blumenstingl } 6073adbf342SMartin Blumenstingl 6083adbf342SMartin Blumenstingl static void meson_sar_adc_clear_fifo(struct iio_dev *indio_dev) 6093adbf342SMartin Blumenstingl { 6103adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 611103a07d4SMartin Blumenstingl unsigned int count, tmp; 6123adbf342SMartin Blumenstingl 6133adbf342SMartin Blumenstingl for (count = 0; count < MESON_SAR_ADC_MAX_FIFO_SIZE; count++) { 6143adbf342SMartin Blumenstingl if (!meson_sar_adc_get_fifo_count(indio_dev)) 6153adbf342SMartin Blumenstingl break; 6163adbf342SMartin Blumenstingl 617103a07d4SMartin Blumenstingl regmap_read(priv->regmap, MESON_SAR_ADC_FIFO_RD, &tmp); 6183adbf342SMartin Blumenstingl } 6193adbf342SMartin Blumenstingl } 6203adbf342SMartin Blumenstingl 6213adbf342SMartin Blumenstingl static int meson_sar_adc_get_sample(struct iio_dev *indio_dev, 6223adbf342SMartin Blumenstingl const struct iio_chan_spec *chan, 6233adbf342SMartin Blumenstingl enum meson_sar_adc_avg_mode avg_mode, 6243adbf342SMartin Blumenstingl enum meson_sar_adc_num_samples avg_samples, 6253adbf342SMartin Blumenstingl int *val) 6263adbf342SMartin Blumenstingl { 627723a61e0SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 62822c26db4SAndy Shevchenko struct device *dev = indio_dev->dev.parent; 6293adbf342SMartin Blumenstingl int ret; 6303adbf342SMartin Blumenstingl 631723a61e0SMartin Blumenstingl if (chan->type == IIO_TEMP && !priv->temperature_sensor_calibrated) 632723a61e0SMartin Blumenstingl return -ENOTSUPP; 633723a61e0SMartin Blumenstingl 6343adbf342SMartin Blumenstingl ret = meson_sar_adc_lock(indio_dev); 6353adbf342SMartin Blumenstingl if (ret) 6363adbf342SMartin Blumenstingl return ret; 6373adbf342SMartin Blumenstingl 6383adbf342SMartin Blumenstingl /* clear the FIFO to make sure we're not reading old values */ 6393adbf342SMartin Blumenstingl meson_sar_adc_clear_fifo(indio_dev); 6403adbf342SMartin Blumenstingl 6413adbf342SMartin Blumenstingl meson_sar_adc_set_averaging(indio_dev, chan, avg_mode, avg_samples); 6423adbf342SMartin Blumenstingl 6433adbf342SMartin Blumenstingl meson_sar_adc_enable_channel(indio_dev, chan); 6443adbf342SMartin Blumenstingl 6453adbf342SMartin Blumenstingl meson_sar_adc_start_sample_engine(indio_dev); 6463adbf342SMartin Blumenstingl ret = meson_sar_adc_read_raw_sample(indio_dev, chan, val); 6473adbf342SMartin Blumenstingl meson_sar_adc_stop_sample_engine(indio_dev); 6483adbf342SMartin Blumenstingl 6493adbf342SMartin Blumenstingl meson_sar_adc_unlock(indio_dev); 6503adbf342SMartin Blumenstingl 6513adbf342SMartin Blumenstingl if (ret) { 65222c26db4SAndy Shevchenko dev_warn(dev, "failed to read sample for channel %lu: %d\n", 653827df057SMartin Blumenstingl chan->address, ret); 6543adbf342SMartin Blumenstingl return ret; 6553adbf342SMartin Blumenstingl } 6563adbf342SMartin Blumenstingl 6573adbf342SMartin Blumenstingl return IIO_VAL_INT; 6583adbf342SMartin Blumenstingl } 6593adbf342SMartin Blumenstingl 6603adbf342SMartin Blumenstingl static int meson_sar_adc_iio_info_read_raw(struct iio_dev *indio_dev, 6613adbf342SMartin Blumenstingl const struct iio_chan_spec *chan, 6623adbf342SMartin Blumenstingl int *val, int *val2, long mask) 6633adbf342SMartin Blumenstingl { 6643adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 66522c26db4SAndy Shevchenko struct device *dev = indio_dev->dev.parent; 6663adbf342SMartin Blumenstingl int ret; 6673adbf342SMartin Blumenstingl 6683adbf342SMartin Blumenstingl switch (mask) { 6693adbf342SMartin Blumenstingl case IIO_CHAN_INFO_RAW: 6703adbf342SMartin Blumenstingl return meson_sar_adc_get_sample(indio_dev, chan, NO_AVERAGING, 6713adbf342SMartin Blumenstingl ONE_SAMPLE, val); 6723adbf342SMartin Blumenstingl 6733adbf342SMartin Blumenstingl case IIO_CHAN_INFO_AVERAGE_RAW: 6743adbf342SMartin Blumenstingl return meson_sar_adc_get_sample(indio_dev, chan, 6753adbf342SMartin Blumenstingl MEAN_AVERAGING, EIGHT_SAMPLES, 6763adbf342SMartin Blumenstingl val); 6773adbf342SMartin Blumenstingl 6783adbf342SMartin Blumenstingl case IIO_CHAN_INFO_SCALE: 679723a61e0SMartin Blumenstingl if (chan->type == IIO_VOLTAGE) { 6803adbf342SMartin Blumenstingl ret = regulator_get_voltage(priv->vref); 6813adbf342SMartin Blumenstingl if (ret < 0) { 68222c26db4SAndy Shevchenko dev_err(dev, "failed to get vref voltage: %d\n", ret); 6833adbf342SMartin Blumenstingl return ret; 6843adbf342SMartin Blumenstingl } 6853adbf342SMartin Blumenstingl 6863adbf342SMartin Blumenstingl *val = ret / 1000; 687057e5a11SMartin Blumenstingl *val2 = priv->param->resolution; 6883adbf342SMartin Blumenstingl return IIO_VAL_FRACTIONAL_LOG2; 689723a61e0SMartin Blumenstingl } else if (chan->type == IIO_TEMP) { 690723a61e0SMartin Blumenstingl /* SoC specific multiplier and divider */ 691723a61e0SMartin Blumenstingl *val = priv->param->temperature_multiplier; 692723a61e0SMartin Blumenstingl *val2 = priv->param->temperature_divider; 693723a61e0SMartin Blumenstingl 694723a61e0SMartin Blumenstingl /* celsius to millicelsius */ 695723a61e0SMartin Blumenstingl *val *= 1000; 696723a61e0SMartin Blumenstingl 697723a61e0SMartin Blumenstingl return IIO_VAL_FRACTIONAL; 698723a61e0SMartin Blumenstingl } else { 699723a61e0SMartin Blumenstingl return -EINVAL; 700723a61e0SMartin Blumenstingl } 7013adbf342SMartin Blumenstingl 70248ba7c3cSHeiner Kallweit case IIO_CHAN_INFO_CALIBBIAS: 70348ba7c3cSHeiner Kallweit *val = priv->calibbias; 70448ba7c3cSHeiner Kallweit return IIO_VAL_INT; 70548ba7c3cSHeiner Kallweit 70648ba7c3cSHeiner Kallweit case IIO_CHAN_INFO_CALIBSCALE: 70748ba7c3cSHeiner Kallweit *val = priv->calibscale / MILLION; 70848ba7c3cSHeiner Kallweit *val2 = priv->calibscale % MILLION; 70948ba7c3cSHeiner Kallweit return IIO_VAL_INT_PLUS_MICRO; 71048ba7c3cSHeiner Kallweit 711723a61e0SMartin Blumenstingl case IIO_CHAN_INFO_OFFSET: 712723a61e0SMartin Blumenstingl *val = DIV_ROUND_CLOSEST(MESON_SAR_ADC_TEMP_OFFSET * 713723a61e0SMartin Blumenstingl priv->param->temperature_divider, 714723a61e0SMartin Blumenstingl priv->param->temperature_multiplier); 715723a61e0SMartin Blumenstingl *val -= priv->temperature_sensor_adc_val; 716723a61e0SMartin Blumenstingl return IIO_VAL_INT; 717723a61e0SMartin Blumenstingl 7183adbf342SMartin Blumenstingl default: 7193adbf342SMartin Blumenstingl return -EINVAL; 7203adbf342SMartin Blumenstingl } 7213adbf342SMartin Blumenstingl } 7223adbf342SMartin Blumenstingl 7233adbf342SMartin Blumenstingl static int meson_sar_adc_clk_init(struct iio_dev *indio_dev, 7243adbf342SMartin Blumenstingl void __iomem *base) 7253adbf342SMartin Blumenstingl { 7263adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 727ec25bb6eSAndy Shevchenko struct device *dev = indio_dev->dev.parent; 7283adbf342SMartin Blumenstingl struct clk_init_data init; 7293adbf342SMartin Blumenstingl const char *clk_parents[1]; 7303adbf342SMartin Blumenstingl 731ec25bb6eSAndy Shevchenko init.name = devm_kasprintf(dev, GFP_KERNEL, "%s#adc_div", dev_name(dev)); 732aad172b0SNicholas Mc Guire if (!init.name) 733aad172b0SNicholas Mc Guire return -ENOMEM; 734aad172b0SNicholas Mc Guire 7353adbf342SMartin Blumenstingl init.flags = 0; 7363adbf342SMartin Blumenstingl init.ops = &clk_divider_ops; 7373adbf342SMartin Blumenstingl clk_parents[0] = __clk_get_name(priv->clkin); 7383adbf342SMartin Blumenstingl init.parent_names = clk_parents; 7393adbf342SMartin Blumenstingl init.num_parents = 1; 7403adbf342SMartin Blumenstingl 7413adbf342SMartin Blumenstingl priv->clk_div.reg = base + MESON_SAR_ADC_REG3; 7423adbf342SMartin Blumenstingl priv->clk_div.shift = MESON_SAR_ADC_REG3_ADC_CLK_DIV_SHIFT; 7433adbf342SMartin Blumenstingl priv->clk_div.width = MESON_SAR_ADC_REG3_ADC_CLK_DIV_WIDTH; 7443adbf342SMartin Blumenstingl priv->clk_div.hw.init = &init; 7453adbf342SMartin Blumenstingl priv->clk_div.flags = 0; 7463adbf342SMartin Blumenstingl 747ec25bb6eSAndy Shevchenko priv->adc_div_clk = devm_clk_register(dev, &priv->clk_div.hw); 7483adbf342SMartin Blumenstingl if (WARN_ON(IS_ERR(priv->adc_div_clk))) 7493adbf342SMartin Blumenstingl return PTR_ERR(priv->adc_div_clk); 7503adbf342SMartin Blumenstingl 751ec25bb6eSAndy Shevchenko init.name = devm_kasprintf(dev, GFP_KERNEL, "%s#adc_en", dev_name(dev)); 752aad172b0SNicholas Mc Guire if (!init.name) 753aad172b0SNicholas Mc Guire return -ENOMEM; 754aad172b0SNicholas Mc Guire 7553adbf342SMartin Blumenstingl init.flags = CLK_SET_RATE_PARENT; 7563adbf342SMartin Blumenstingl init.ops = &clk_gate_ops; 7573adbf342SMartin Blumenstingl clk_parents[0] = __clk_get_name(priv->adc_div_clk); 7583adbf342SMartin Blumenstingl init.parent_names = clk_parents; 7593adbf342SMartin Blumenstingl init.num_parents = 1; 7603adbf342SMartin Blumenstingl 7613adbf342SMartin Blumenstingl priv->clk_gate.reg = base + MESON_SAR_ADC_REG3; 7627a6b0420SMartin Blumenstingl priv->clk_gate.bit_idx = __ffs(MESON_SAR_ADC_REG3_CLK_EN); 7633adbf342SMartin Blumenstingl priv->clk_gate.hw.init = &init; 7643adbf342SMartin Blumenstingl 765ec25bb6eSAndy Shevchenko priv->adc_clk = devm_clk_register(dev, &priv->clk_gate.hw); 7663adbf342SMartin Blumenstingl if (WARN_ON(IS_ERR(priv->adc_clk))) 7673adbf342SMartin Blumenstingl return PTR_ERR(priv->adc_clk); 7683adbf342SMartin Blumenstingl 7693adbf342SMartin Blumenstingl return 0; 7703adbf342SMartin Blumenstingl } 7713adbf342SMartin Blumenstingl 772723a61e0SMartin Blumenstingl static int meson_sar_adc_temp_sensor_init(struct iio_dev *indio_dev) 773723a61e0SMartin Blumenstingl { 774723a61e0SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 775723a61e0SMartin Blumenstingl u8 *buf, trimming_bits, trimming_mask, upper_adc_val; 7762d27a021SAndy Shevchenko struct device *dev = indio_dev->dev.parent; 777723a61e0SMartin Blumenstingl struct nvmem_cell *temperature_calib; 778723a61e0SMartin Blumenstingl size_t read_len; 779723a61e0SMartin Blumenstingl int ret; 780723a61e0SMartin Blumenstingl 78122c26db4SAndy Shevchenko temperature_calib = devm_nvmem_cell_get(dev, "temperature_calib"); 782723a61e0SMartin Blumenstingl if (IS_ERR(temperature_calib)) { 783723a61e0SMartin Blumenstingl ret = PTR_ERR(temperature_calib); 784723a61e0SMartin Blumenstingl 785723a61e0SMartin Blumenstingl /* 786723a61e0SMartin Blumenstingl * leave the temperature sensor disabled if no calibration data 787723a61e0SMartin Blumenstingl * was passed via nvmem-cells. 788723a61e0SMartin Blumenstingl */ 789723a61e0SMartin Blumenstingl if (ret == -ENODEV) 790723a61e0SMartin Blumenstingl return 0; 791723a61e0SMartin Blumenstingl 7922d27a021SAndy Shevchenko return dev_err_probe(dev, ret, "failed to get temperature_calib cell\n"); 793723a61e0SMartin Blumenstingl } 794723a61e0SMartin Blumenstingl 79522c26db4SAndy Shevchenko priv->tsc_regmap = syscon_regmap_lookup_by_phandle(dev->of_node, "amlogic,hhi-sysctrl"); 7962d27a021SAndy Shevchenko if (IS_ERR(priv->tsc_regmap)) 7972d27a021SAndy Shevchenko return dev_err_probe(dev, PTR_ERR(priv->tsc_regmap), 798b002bf5fSMartin Blumenstingl "failed to get amlogic,hhi-sysctrl regmap\n"); 799b002bf5fSMartin Blumenstingl 800723a61e0SMartin Blumenstingl read_len = MESON_SAR_ADC_EFUSE_BYTES; 801723a61e0SMartin Blumenstingl buf = nvmem_cell_read(temperature_calib, &read_len); 8022d27a021SAndy Shevchenko if (IS_ERR(buf)) 8032d27a021SAndy Shevchenko return dev_err_probe(dev, PTR_ERR(buf), "failed to read temperature_calib cell\n"); 8042d27a021SAndy Shevchenko if (read_len != MESON_SAR_ADC_EFUSE_BYTES) { 805723a61e0SMartin Blumenstingl kfree(buf); 8062d27a021SAndy Shevchenko return dev_err_probe(dev, -EINVAL, "invalid read size of temperature_calib cell\n"); 807723a61e0SMartin Blumenstingl } 808723a61e0SMartin Blumenstingl 809723a61e0SMartin Blumenstingl trimming_bits = priv->param->temperature_trimming_bits; 810723a61e0SMartin Blumenstingl trimming_mask = BIT(trimming_bits) - 1; 811723a61e0SMartin Blumenstingl 812723a61e0SMartin Blumenstingl priv->temperature_sensor_calibrated = 813723a61e0SMartin Blumenstingl buf[3] & MESON_SAR_ADC_EFUSE_BYTE3_IS_CALIBRATED; 814723a61e0SMartin Blumenstingl priv->temperature_sensor_coefficient = buf[2] & trimming_mask; 815723a61e0SMartin Blumenstingl 816723a61e0SMartin Blumenstingl upper_adc_val = FIELD_GET(MESON_SAR_ADC_EFUSE_BYTE3_UPPER_ADC_VAL, 817723a61e0SMartin Blumenstingl buf[3]); 818723a61e0SMartin Blumenstingl 819723a61e0SMartin Blumenstingl priv->temperature_sensor_adc_val = buf[2]; 820723a61e0SMartin Blumenstingl priv->temperature_sensor_adc_val |= upper_adc_val << BITS_PER_BYTE; 821723a61e0SMartin Blumenstingl priv->temperature_sensor_adc_val >>= trimming_bits; 822723a61e0SMartin Blumenstingl 823723a61e0SMartin Blumenstingl kfree(buf); 824723a61e0SMartin Blumenstingl 825723a61e0SMartin Blumenstingl return 0; 826723a61e0SMartin Blumenstingl } 827723a61e0SMartin Blumenstingl 8283adbf342SMartin Blumenstingl static int meson_sar_adc_init(struct iio_dev *indio_dev) 8293adbf342SMartin Blumenstingl { 8303adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 8312d27a021SAndy Shevchenko struct device *dev = indio_dev->dev.parent; 832ab569a4cSMartin Blumenstingl int regval, i, ret; 8333adbf342SMartin Blumenstingl 8343adbf342SMartin Blumenstingl /* 8353adbf342SMartin Blumenstingl * make sure we start at CH7 input since the other muxes are only used 8363adbf342SMartin Blumenstingl * for internal calibration. 8373adbf342SMartin Blumenstingl */ 8383adbf342SMartin Blumenstingl meson_sar_adc_set_chan7_mux(indio_dev, CHAN7_MUX_CH7_INPUT); 8393adbf342SMartin Blumenstingl 840057e5a11SMartin Blumenstingl if (priv->param->has_bl30_integration) { 8413adbf342SMartin Blumenstingl /* 8426c76ed31SMartin Blumenstingl * leave sampling delay and the input clocks as configured by 8436c76ed31SMartin Blumenstingl * BL30 to make sure BL30 gets the values it expects when 8446c76ed31SMartin Blumenstingl * reading the temperature sensor. 8453adbf342SMartin Blumenstingl */ 8463adbf342SMartin Blumenstingl regmap_read(priv->regmap, MESON_SAR_ADC_REG3, ®val); 8473adbf342SMartin Blumenstingl if (regval & MESON_SAR_ADC_REG3_BL30_INITIALIZED) 8483adbf342SMartin Blumenstingl return 0; 8496c76ed31SMartin Blumenstingl } 8503adbf342SMartin Blumenstingl 8513adbf342SMartin Blumenstingl meson_sar_adc_stop_sample_engine(indio_dev); 8523adbf342SMartin Blumenstingl 853723a61e0SMartin Blumenstingl /* 854723a61e0SMartin Blumenstingl * disable this bit as seems to be only relevant for Meson6 (based 855723a61e0SMartin Blumenstingl * on the vendor driver), which we don't support at the moment. 856723a61e0SMartin Blumenstingl */ 8573adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, 858723a61e0SMartin Blumenstingl MESON_SAR_ADC_REG0_ADC_TEMP_SEN_SEL, 0); 8593adbf342SMartin Blumenstingl 8603adbf342SMartin Blumenstingl /* disable all channels by default */ 8613adbf342SMartin Blumenstingl regmap_write(priv->regmap, MESON_SAR_ADC_CHAN_LIST, 0x0); 8623adbf342SMartin Blumenstingl 8633adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3, 8643adbf342SMartin Blumenstingl MESON_SAR_ADC_REG3_CTRL_SAMPLING_CLOCK_PHASE, 0); 8653adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3, 8663adbf342SMartin Blumenstingl MESON_SAR_ADC_REG3_CNTL_USE_SC_DLY, 8673adbf342SMartin Blumenstingl MESON_SAR_ADC_REG3_CNTL_USE_SC_DLY); 8683adbf342SMartin Blumenstingl 8693adbf342SMartin Blumenstingl /* delay between two samples = (10+1) * 1uS */ 8703adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY, 8713adbf342SMartin Blumenstingl MESON_SAR_ADC_DELAY_INPUT_DLY_CNT_MASK, 8723adbf342SMartin Blumenstingl FIELD_PREP(MESON_SAR_ADC_DELAY_SAMPLE_DLY_CNT_MASK, 8733adbf342SMartin Blumenstingl 10)); 8743adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY, 8753adbf342SMartin Blumenstingl MESON_SAR_ADC_DELAY_SAMPLE_DLY_SEL_MASK, 8763adbf342SMartin Blumenstingl FIELD_PREP(MESON_SAR_ADC_DELAY_SAMPLE_DLY_SEL_MASK, 8773adbf342SMartin Blumenstingl 0)); 8783adbf342SMartin Blumenstingl 8793adbf342SMartin Blumenstingl /* delay between two samples = (10+1) * 1uS */ 8803adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY, 8813adbf342SMartin Blumenstingl MESON_SAR_ADC_DELAY_INPUT_DLY_CNT_MASK, 8823adbf342SMartin Blumenstingl FIELD_PREP(MESON_SAR_ADC_DELAY_INPUT_DLY_CNT_MASK, 8833adbf342SMartin Blumenstingl 10)); 8843adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY, 8853adbf342SMartin Blumenstingl MESON_SAR_ADC_DELAY_INPUT_DLY_SEL_MASK, 8863adbf342SMartin Blumenstingl FIELD_PREP(MESON_SAR_ADC_DELAY_INPUT_DLY_SEL_MASK, 8873adbf342SMartin Blumenstingl 1)); 8883adbf342SMartin Blumenstingl 889ab569a4cSMartin Blumenstingl /* 890ab569a4cSMartin Blumenstingl * set up the input channel muxes in MESON_SAR_ADC_CHAN_10_SW 891ab569a4cSMartin Blumenstingl * (0 = SAR_ADC_CH0, 1 = SAR_ADC_CH1) 892ab569a4cSMartin Blumenstingl */ 893ab569a4cSMartin Blumenstingl regval = FIELD_PREP(MESON_SAR_ADC_CHAN_10_SW_CHAN0_MUX_SEL_MASK, 0); 894ab569a4cSMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_10_SW, 895ab569a4cSMartin Blumenstingl MESON_SAR_ADC_CHAN_10_SW_CHAN0_MUX_SEL_MASK, 896ab569a4cSMartin Blumenstingl regval); 897ab569a4cSMartin Blumenstingl regval = FIELD_PREP(MESON_SAR_ADC_CHAN_10_SW_CHAN1_MUX_SEL_MASK, 1); 898ab569a4cSMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_10_SW, 899ab569a4cSMartin Blumenstingl MESON_SAR_ADC_CHAN_10_SW_CHAN1_MUX_SEL_MASK, 900ab569a4cSMartin Blumenstingl regval); 901ab569a4cSMartin Blumenstingl 902*6ad9f01cSGeorge Stark regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_10_SW, 903*6ad9f01cSGeorge Stark MESON_SAR_ADC_CHAN_10_SW_CHAN0_XP_DRIVE_SW, 904*6ad9f01cSGeorge Stark MESON_SAR_ADC_CHAN_10_SW_CHAN0_XP_DRIVE_SW); 905*6ad9f01cSGeorge Stark 906*6ad9f01cSGeorge Stark regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_10_SW, 907*6ad9f01cSGeorge Stark MESON_SAR_ADC_CHAN_10_SW_CHAN0_YP_DRIVE_SW, 908*6ad9f01cSGeorge Stark MESON_SAR_ADC_CHAN_10_SW_CHAN0_YP_DRIVE_SW); 909*6ad9f01cSGeorge Stark 910*6ad9f01cSGeorge Stark regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_10_SW, 911*6ad9f01cSGeorge Stark MESON_SAR_ADC_CHAN_10_SW_CHAN1_XP_DRIVE_SW, 912*6ad9f01cSGeorge Stark MESON_SAR_ADC_CHAN_10_SW_CHAN1_XP_DRIVE_SW); 913*6ad9f01cSGeorge Stark 914*6ad9f01cSGeorge Stark regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_10_SW, 915*6ad9f01cSGeorge Stark MESON_SAR_ADC_CHAN_10_SW_CHAN1_YP_DRIVE_SW, 916*6ad9f01cSGeorge Stark MESON_SAR_ADC_CHAN_10_SW_CHAN1_YP_DRIVE_SW); 917*6ad9f01cSGeorge Stark 918ab569a4cSMartin Blumenstingl /* 919ab569a4cSMartin Blumenstingl * set up the input channel muxes in MESON_SAR_ADC_AUX_SW 920ab569a4cSMartin Blumenstingl * (2 = SAR_ADC_CH2, 3 = SAR_ADC_CH3, ...) and enable 921ab569a4cSMartin Blumenstingl * MESON_SAR_ADC_AUX_SW_YP_DRIVE_SW and 922ab569a4cSMartin Blumenstingl * MESON_SAR_ADC_AUX_SW_XP_DRIVE_SW like the vendor driver. 923ab569a4cSMartin Blumenstingl */ 924ab569a4cSMartin Blumenstingl regval = 0; 925ab569a4cSMartin Blumenstingl for (i = 2; i <= 7; i++) 926ab569a4cSMartin Blumenstingl regval |= i << MESON_SAR_ADC_AUX_SW_MUX_SEL_CHAN_SHIFT(i); 927ab569a4cSMartin Blumenstingl regval |= MESON_SAR_ADC_AUX_SW_YP_DRIVE_SW; 928ab569a4cSMartin Blumenstingl regval |= MESON_SAR_ADC_AUX_SW_XP_DRIVE_SW; 929ab569a4cSMartin Blumenstingl regmap_write(priv->regmap, MESON_SAR_ADC_AUX_SW, regval); 930ab569a4cSMartin Blumenstingl 931723a61e0SMartin Blumenstingl if (priv->temperature_sensor_calibrated) { 932723a61e0SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELTA_10, 933723a61e0SMartin Blumenstingl MESON_SAR_ADC_DELTA_10_TS_REVE1, 934723a61e0SMartin Blumenstingl MESON_SAR_ADC_DELTA_10_TS_REVE1); 935723a61e0SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELTA_10, 936723a61e0SMartin Blumenstingl MESON_SAR_ADC_DELTA_10_TS_REVE0, 937723a61e0SMartin Blumenstingl MESON_SAR_ADC_DELTA_10_TS_REVE0); 938723a61e0SMartin Blumenstingl 939723a61e0SMartin Blumenstingl /* 940723a61e0SMartin Blumenstingl * set bits [3:0] of the TSC (temperature sensor coefficient) 941723a61e0SMartin Blumenstingl * to get the correct values when reading the temperature. 942723a61e0SMartin Blumenstingl */ 943723a61e0SMartin Blumenstingl regval = FIELD_PREP(MESON_SAR_ADC_DELTA_10_TS_C_MASK, 944723a61e0SMartin Blumenstingl priv->temperature_sensor_coefficient); 945723a61e0SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELTA_10, 946723a61e0SMartin Blumenstingl MESON_SAR_ADC_DELTA_10_TS_C_MASK, regval); 947b002bf5fSMartin Blumenstingl 948b002bf5fSMartin Blumenstingl if (priv->param->temperature_trimming_bits == 5) { 949b002bf5fSMartin Blumenstingl if (priv->temperature_sensor_coefficient & BIT(4)) 950b002bf5fSMartin Blumenstingl regval = MESON_HHI_DPLL_TOP_0_TSC_BIT4; 951b002bf5fSMartin Blumenstingl else 952b002bf5fSMartin Blumenstingl regval = 0; 953b002bf5fSMartin Blumenstingl 954b002bf5fSMartin Blumenstingl /* 955b002bf5fSMartin Blumenstingl * bit [4] (the 5th bit when starting to count at 1) 956b002bf5fSMartin Blumenstingl * of the TSC is located in the HHI register area. 957b002bf5fSMartin Blumenstingl */ 958b002bf5fSMartin Blumenstingl regmap_update_bits(priv->tsc_regmap, 959b002bf5fSMartin Blumenstingl MESON_HHI_DPLL_TOP_0, 960b002bf5fSMartin Blumenstingl MESON_HHI_DPLL_TOP_0_TSC_BIT4, 961b002bf5fSMartin Blumenstingl regval); 962b002bf5fSMartin Blumenstingl } 963723a61e0SMartin Blumenstingl } else { 964723a61e0SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELTA_10, 965723a61e0SMartin Blumenstingl MESON_SAR_ADC_DELTA_10_TS_REVE1, 0); 966723a61e0SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELTA_10, 967723a61e0SMartin Blumenstingl MESON_SAR_ADC_DELTA_10_TS_REVE0, 0); 968723a61e0SMartin Blumenstingl } 969723a61e0SMartin Blumenstingl 9703adbf342SMartin Blumenstingl ret = clk_set_parent(priv->adc_sel_clk, priv->clkin); 9712d27a021SAndy Shevchenko if (ret) 9722d27a021SAndy Shevchenko return dev_err_probe(dev, ret, "failed to set adc parent to clkin\n"); 9733adbf342SMartin Blumenstingl 974057e5a11SMartin Blumenstingl ret = clk_set_rate(priv->adc_clk, priv->param->clock_rate); 9752d27a021SAndy Shevchenko if (ret) 9762d27a021SAndy Shevchenko return dev_err_probe(dev, ret, "failed to set adc clock rate\n"); 9773adbf342SMartin Blumenstingl 9783adbf342SMartin Blumenstingl return 0; 9793adbf342SMartin Blumenstingl } 9803adbf342SMartin Blumenstingl 981d85eed9fSMartin Blumenstingl static void meson_sar_adc_set_bandgap(struct iio_dev *indio_dev, bool on_off) 982d85eed9fSMartin Blumenstingl { 983d85eed9fSMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 984057e5a11SMartin Blumenstingl const struct meson_sar_adc_param *param = priv->param; 985d85eed9fSMartin Blumenstingl u32 enable_mask; 986d85eed9fSMartin Blumenstingl 987053ffe3cSYixun Lan if (param->bandgap_reg == MESON_SAR_ADC_REG11) 988d85eed9fSMartin Blumenstingl enable_mask = MESON_SAR_ADC_REG11_BANDGAP_EN; 989d85eed9fSMartin Blumenstingl else 990d85eed9fSMartin Blumenstingl enable_mask = MESON_SAR_ADC_DELTA_10_TS_VBG_EN; 991d85eed9fSMartin Blumenstingl 992053ffe3cSYixun Lan regmap_update_bits(priv->regmap, param->bandgap_reg, enable_mask, 993d85eed9fSMartin Blumenstingl on_off ? enable_mask : 0); 994d85eed9fSMartin Blumenstingl } 995d85eed9fSMartin Blumenstingl 9963adbf342SMartin Blumenstingl static int meson_sar_adc_hw_enable(struct iio_dev *indio_dev) 9973adbf342SMartin Blumenstingl { 9983adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 99922c26db4SAndy Shevchenko struct device *dev = indio_dev->dev.parent; 10003adbf342SMartin Blumenstingl int ret; 10013af10913SHeiner Kallweit u32 regval; 10023adbf342SMartin Blumenstingl 10033adbf342SMartin Blumenstingl ret = meson_sar_adc_lock(indio_dev); 10043adbf342SMartin Blumenstingl if (ret) 10053adbf342SMartin Blumenstingl goto err_lock; 10063adbf342SMartin Blumenstingl 10073adbf342SMartin Blumenstingl ret = regulator_enable(priv->vref); 10083adbf342SMartin Blumenstingl if (ret < 0) { 100922c26db4SAndy Shevchenko dev_err(dev, "failed to enable vref regulator\n"); 10103adbf342SMartin Blumenstingl goto err_vref; 10113adbf342SMartin Blumenstingl } 10123adbf342SMartin Blumenstingl 10133adbf342SMartin Blumenstingl ret = clk_prepare_enable(priv->core_clk); 10143adbf342SMartin Blumenstingl if (ret) { 101522c26db4SAndy Shevchenko dev_err(dev, "failed to enable core clk\n"); 10163adbf342SMartin Blumenstingl goto err_core_clk; 10173adbf342SMartin Blumenstingl } 10183adbf342SMartin Blumenstingl 10193af10913SHeiner Kallweit regval = FIELD_PREP(MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, 1); 10203af10913SHeiner Kallweit regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0, 10213af10913SHeiner Kallweit MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, regval); 1022d85eed9fSMartin Blumenstingl 1023d85eed9fSMartin Blumenstingl meson_sar_adc_set_bandgap(indio_dev, true); 1024d85eed9fSMartin Blumenstingl 10253adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3, 10263adbf342SMartin Blumenstingl MESON_SAR_ADC_REG3_ADC_EN, 10273adbf342SMartin Blumenstingl MESON_SAR_ADC_REG3_ADC_EN); 10283adbf342SMartin Blumenstingl 10293adbf342SMartin Blumenstingl udelay(5); 10303adbf342SMartin Blumenstingl 10313adbf342SMartin Blumenstingl ret = clk_prepare_enable(priv->adc_clk); 10323adbf342SMartin Blumenstingl if (ret) { 103322c26db4SAndy Shevchenko dev_err(dev, "failed to enable adc clk\n"); 10343adbf342SMartin Blumenstingl goto err_adc_clk; 10353adbf342SMartin Blumenstingl } 10363adbf342SMartin Blumenstingl 10373adbf342SMartin Blumenstingl meson_sar_adc_unlock(indio_dev); 10383adbf342SMartin Blumenstingl 10393adbf342SMartin Blumenstingl return 0; 10403adbf342SMartin Blumenstingl 10413adbf342SMartin Blumenstingl err_adc_clk: 10423adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3, 10433adbf342SMartin Blumenstingl MESON_SAR_ADC_REG3_ADC_EN, 0); 1044d85eed9fSMartin Blumenstingl meson_sar_adc_set_bandgap(indio_dev, false); 10453adbf342SMartin Blumenstingl clk_disable_unprepare(priv->core_clk); 10463adbf342SMartin Blumenstingl err_core_clk: 10473adbf342SMartin Blumenstingl regulator_disable(priv->vref); 10483adbf342SMartin Blumenstingl err_vref: 10493adbf342SMartin Blumenstingl meson_sar_adc_unlock(indio_dev); 10503adbf342SMartin Blumenstingl err_lock: 10513adbf342SMartin Blumenstingl return ret; 10523adbf342SMartin Blumenstingl } 10533adbf342SMartin Blumenstingl 10544ab8bef1SUwe Kleine-König static void meson_sar_adc_hw_disable(struct iio_dev *indio_dev) 10553adbf342SMartin Blumenstingl { 10563adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 10573adbf342SMartin Blumenstingl int ret; 10583adbf342SMartin Blumenstingl 10594ab8bef1SUwe Kleine-König /* 10604ab8bef1SUwe Kleine-König * If taking the lock fails we have to assume that BL30 is broken. The 10614ab8bef1SUwe Kleine-König * best we can do then is to release the resources anyhow. 10624ab8bef1SUwe Kleine-König */ 10633adbf342SMartin Blumenstingl ret = meson_sar_adc_lock(indio_dev); 10643adbf342SMartin Blumenstingl if (ret) 10654ab8bef1SUwe Kleine-König dev_err(indio_dev->dev.parent, "Failed to lock ADC (%pE)\n", ERR_PTR(ret)); 10663adbf342SMartin Blumenstingl 10673adbf342SMartin Blumenstingl clk_disable_unprepare(priv->adc_clk); 10683adbf342SMartin Blumenstingl 10693adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3, 10703adbf342SMartin Blumenstingl MESON_SAR_ADC_REG3_ADC_EN, 0); 1071d85eed9fSMartin Blumenstingl 1072d85eed9fSMartin Blumenstingl meson_sar_adc_set_bandgap(indio_dev, false); 10733adbf342SMartin Blumenstingl 10743adbf342SMartin Blumenstingl clk_disable_unprepare(priv->core_clk); 10753adbf342SMartin Blumenstingl 10763adbf342SMartin Blumenstingl regulator_disable(priv->vref); 10773adbf342SMartin Blumenstingl 10784ab8bef1SUwe Kleine-König if (!ret) 10793adbf342SMartin Blumenstingl meson_sar_adc_unlock(indio_dev); 10803adbf342SMartin Blumenstingl } 10813adbf342SMartin Blumenstingl 10823af10913SHeiner Kallweit static irqreturn_t meson_sar_adc_irq(int irq, void *data) 10833af10913SHeiner Kallweit { 10843af10913SHeiner Kallweit struct iio_dev *indio_dev = data; 10853af10913SHeiner Kallweit struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 10863af10913SHeiner Kallweit unsigned int cnt, threshold; 10873af10913SHeiner Kallweit u32 regval; 10883af10913SHeiner Kallweit 10893af10913SHeiner Kallweit regmap_read(priv->regmap, MESON_SAR_ADC_REG0, ®val); 10903af10913SHeiner Kallweit cnt = FIELD_GET(MESON_SAR_ADC_REG0_FIFO_COUNT_MASK, regval); 10913af10913SHeiner Kallweit threshold = FIELD_GET(MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, regval); 10923af10913SHeiner Kallweit 10933af10913SHeiner Kallweit if (cnt < threshold) 10943af10913SHeiner Kallweit return IRQ_NONE; 10953af10913SHeiner Kallweit 10963af10913SHeiner Kallweit complete(&priv->done); 10973af10913SHeiner Kallweit 10983af10913SHeiner Kallweit return IRQ_HANDLED; 10993af10913SHeiner Kallweit } 11003af10913SHeiner Kallweit 110148ba7c3cSHeiner Kallweit static int meson_sar_adc_calib(struct iio_dev *indio_dev) 110248ba7c3cSHeiner Kallweit { 110348ba7c3cSHeiner Kallweit struct meson_sar_adc_priv *priv = iio_priv(indio_dev); 110448ba7c3cSHeiner Kallweit int ret, nominal0, nominal1, value0, value1; 110548ba7c3cSHeiner Kallweit 110648ba7c3cSHeiner Kallweit /* use points 25% and 75% for calibration */ 1107057e5a11SMartin Blumenstingl nominal0 = (1 << priv->param->resolution) / 4; 1108057e5a11SMartin Blumenstingl nominal1 = (1 << priv->param->resolution) * 3 / 4; 110948ba7c3cSHeiner Kallweit 111048ba7c3cSHeiner Kallweit meson_sar_adc_set_chan7_mux(indio_dev, CHAN7_MUX_VDD_DIV4); 111148ba7c3cSHeiner Kallweit usleep_range(10, 20); 111248ba7c3cSHeiner Kallweit ret = meson_sar_adc_get_sample(indio_dev, 11133a06b284SGeorge Stark find_channel_by_num(indio_dev, 11143a06b284SGeorge Stark NUM_MUX_1_VDD_DIV4), 111548ba7c3cSHeiner Kallweit MEAN_AVERAGING, EIGHT_SAMPLES, &value0); 111648ba7c3cSHeiner Kallweit if (ret < 0) 111748ba7c3cSHeiner Kallweit goto out; 111848ba7c3cSHeiner Kallweit 111948ba7c3cSHeiner Kallweit meson_sar_adc_set_chan7_mux(indio_dev, CHAN7_MUX_VDD_MUL3_DIV4); 112048ba7c3cSHeiner Kallweit usleep_range(10, 20); 112148ba7c3cSHeiner Kallweit ret = meson_sar_adc_get_sample(indio_dev, 11223a06b284SGeorge Stark find_channel_by_num(indio_dev, 11233a06b284SGeorge Stark NUM_MUX_3_VDD_MUL3_DIV4), 112448ba7c3cSHeiner Kallweit MEAN_AVERAGING, EIGHT_SAMPLES, &value1); 112548ba7c3cSHeiner Kallweit if (ret < 0) 112648ba7c3cSHeiner Kallweit goto out; 112748ba7c3cSHeiner Kallweit 112848ba7c3cSHeiner Kallweit if (value1 <= value0) { 112948ba7c3cSHeiner Kallweit ret = -EINVAL; 113048ba7c3cSHeiner Kallweit goto out; 113148ba7c3cSHeiner Kallweit } 113248ba7c3cSHeiner Kallweit 113348ba7c3cSHeiner Kallweit priv->calibscale = div_s64((nominal1 - nominal0) * (s64)MILLION, 113448ba7c3cSHeiner Kallweit value1 - value0); 113548ba7c3cSHeiner Kallweit priv->calibbias = nominal0 - div_s64((s64)value0 * priv->calibscale, 113648ba7c3cSHeiner Kallweit MILLION); 113748ba7c3cSHeiner Kallweit ret = 0; 113848ba7c3cSHeiner Kallweit out: 113948ba7c3cSHeiner Kallweit meson_sar_adc_set_chan7_mux(indio_dev, CHAN7_MUX_CH7_INPUT); 114048ba7c3cSHeiner Kallweit 114148ba7c3cSHeiner Kallweit return ret; 114248ba7c3cSHeiner Kallweit } 114348ba7c3cSHeiner Kallweit 1144b593ce5dSGeorge Stark static int read_label(struct iio_dev *indio_dev, 1145b593ce5dSGeorge Stark struct iio_chan_spec const *chan, 1146b593ce5dSGeorge Stark char *label) 1147b593ce5dSGeorge Stark { 1148b593ce5dSGeorge Stark if (chan->type == IIO_TEMP) 1149b593ce5dSGeorge Stark return sprintf(label, "temp-sensor\n"); 11503a06b284SGeorge Stark if (chan->type == IIO_VOLTAGE && chan->channel >= NUM_MUX_0_VSS) 11513a06b284SGeorge Stark return sprintf(label, "%s\n", 11523a06b284SGeorge Stark chan7_mux_names[chan->channel - NUM_MUX_0_VSS]); 1153b593ce5dSGeorge Stark if (chan->type == IIO_VOLTAGE) 1154b593ce5dSGeorge Stark return sprintf(label, "channel-%d\n", chan->channel); 1155b593ce5dSGeorge Stark return 0; 1156b593ce5dSGeorge Stark } 1157b593ce5dSGeorge Stark 11583adbf342SMartin Blumenstingl static const struct iio_info meson_sar_adc_iio_info = { 11593adbf342SMartin Blumenstingl .read_raw = meson_sar_adc_iio_info_read_raw, 1160b593ce5dSGeorge Stark .read_label = read_label, 11613adbf342SMartin Blumenstingl }; 11623adbf342SMartin Blumenstingl 1163053ffe3cSYixun Lan static const struct meson_sar_adc_param meson_sar_adc_meson8_param = { 11646c76ed31SMartin Blumenstingl .has_bl30_integration = false, 1165fda29dbaSMartin Blumenstingl .clock_rate = 1150000, 1166d85eed9fSMartin Blumenstingl .bandgap_reg = MESON_SAR_ADC_DELTA_10, 116796748823SMartin Blumenstingl .regmap_config = &meson_sar_adc_regmap_config_meson8, 11686c76ed31SMartin Blumenstingl .resolution = 10, 1169723a61e0SMartin Blumenstingl .temperature_trimming_bits = 4, 1170723a61e0SMartin Blumenstingl .temperature_multiplier = 18 * 10000, 1171723a61e0SMartin Blumenstingl .temperature_divider = 1024 * 10 * 85, 1172723a61e0SMartin Blumenstingl }; 1173723a61e0SMartin Blumenstingl 1174723a61e0SMartin Blumenstingl static const struct meson_sar_adc_param meson_sar_adc_meson8b_param = { 1175723a61e0SMartin Blumenstingl .has_bl30_integration = false, 1176723a61e0SMartin Blumenstingl .clock_rate = 1150000, 1177723a61e0SMartin Blumenstingl .bandgap_reg = MESON_SAR_ADC_DELTA_10, 1178723a61e0SMartin Blumenstingl .regmap_config = &meson_sar_adc_regmap_config_meson8, 1179723a61e0SMartin Blumenstingl .resolution = 10, 1180b002bf5fSMartin Blumenstingl .temperature_trimming_bits = 5, 1181b002bf5fSMartin Blumenstingl .temperature_multiplier = 10, 1182b002bf5fSMartin Blumenstingl .temperature_divider = 32, 1183053ffe3cSYixun Lan }; 1184053ffe3cSYixun Lan 1185053ffe3cSYixun Lan static const struct meson_sar_adc_param meson_sar_adc_gxbb_param = { 1186053ffe3cSYixun Lan .has_bl30_integration = true, 1187053ffe3cSYixun Lan .clock_rate = 1200000, 1188053ffe3cSYixun Lan .bandgap_reg = MESON_SAR_ADC_REG11, 1189053ffe3cSYixun Lan .regmap_config = &meson_sar_adc_regmap_config_gxbb, 1190053ffe3cSYixun Lan .resolution = 10, 1191053ffe3cSYixun Lan }; 1192053ffe3cSYixun Lan 1193053ffe3cSYixun Lan static const struct meson_sar_adc_param meson_sar_adc_gxl_param = { 1194053ffe3cSYixun Lan .has_bl30_integration = true, 1195053ffe3cSYixun Lan .clock_rate = 1200000, 1196053ffe3cSYixun Lan .bandgap_reg = MESON_SAR_ADC_REG11, 1197053ffe3cSYixun Lan .regmap_config = &meson_sar_adc_regmap_config_gxbb, 1198053ffe3cSYixun Lan .resolution = 12, 1199053ffe3cSYixun Lan }; 1200053ffe3cSYixun Lan 120148dc1abdSMartin Blumenstingl static const struct meson_sar_adc_param meson_sar_adc_g12a_param = { 120248dc1abdSMartin Blumenstingl .has_bl30_integration = false, 120348dc1abdSMartin Blumenstingl .clock_rate = 1200000, 120448dc1abdSMartin Blumenstingl .bandgap_reg = MESON_SAR_ADC_REG11, 120548dc1abdSMartin Blumenstingl .regmap_config = &meson_sar_adc_regmap_config_gxbb, 120648dc1abdSMartin Blumenstingl .resolution = 12, 120748dc1abdSMartin Blumenstingl }; 120848dc1abdSMartin Blumenstingl 1209053ffe3cSYixun Lan static const struct meson_sar_adc_data meson_sar_adc_meson8_data = { 1210053ffe3cSYixun Lan .param = &meson_sar_adc_meson8_param, 12116c76ed31SMartin Blumenstingl .name = "meson-meson8-saradc", 12126c76ed31SMartin Blumenstingl }; 12136c76ed31SMartin Blumenstingl 12146c76ed31SMartin Blumenstingl static const struct meson_sar_adc_data meson_sar_adc_meson8b_data = { 1215723a61e0SMartin Blumenstingl .param = &meson_sar_adc_meson8b_param, 12166c76ed31SMartin Blumenstingl .name = "meson-meson8b-saradc", 12176c76ed31SMartin Blumenstingl }; 12186c76ed31SMartin Blumenstingl 1219ffc0d638SMartin Blumenstingl static const struct meson_sar_adc_data meson_sar_adc_meson8m2_data = { 1220723a61e0SMartin Blumenstingl .param = &meson_sar_adc_meson8b_param, 1221ffc0d638SMartin Blumenstingl .name = "meson-meson8m2-saradc", 1222ffc0d638SMartin Blumenstingl }; 1223ffc0d638SMartin Blumenstingl 1224c1c2de37SMartin Blumenstingl static const struct meson_sar_adc_data meson_sar_adc_gxbb_data = { 1225053ffe3cSYixun Lan .param = &meson_sar_adc_gxbb_param, 12263adbf342SMartin Blumenstingl .name = "meson-gxbb-saradc", 12273adbf342SMartin Blumenstingl }; 12283adbf342SMartin Blumenstingl 1229c1c2de37SMartin Blumenstingl static const struct meson_sar_adc_data meson_sar_adc_gxl_data = { 1230053ffe3cSYixun Lan .param = &meson_sar_adc_gxl_param, 12313adbf342SMartin Blumenstingl .name = "meson-gxl-saradc", 12323adbf342SMartin Blumenstingl }; 12333adbf342SMartin Blumenstingl 1234c1c2de37SMartin Blumenstingl static const struct meson_sar_adc_data meson_sar_adc_gxm_data = { 1235053ffe3cSYixun Lan .param = &meson_sar_adc_gxl_param, 12363adbf342SMartin Blumenstingl .name = "meson-gxm-saradc", 12373adbf342SMartin Blumenstingl }; 12383adbf342SMartin Blumenstingl 1239ff632ddaSXingyu Chen static const struct meson_sar_adc_data meson_sar_adc_axg_data = { 1240ff632ddaSXingyu Chen .param = &meson_sar_adc_gxl_param, 1241ff632ddaSXingyu Chen .name = "meson-axg-saradc", 1242ff632ddaSXingyu Chen }; 1243ff632ddaSXingyu Chen 1244e415a165SNeil Armstrong static const struct meson_sar_adc_data meson_sar_adc_g12a_data = { 124548dc1abdSMartin Blumenstingl .param = &meson_sar_adc_g12a_param, 1246e415a165SNeil Armstrong .name = "meson-g12a-saradc", 1247e415a165SNeil Armstrong }; 1248e415a165SNeil Armstrong 12493adbf342SMartin Blumenstingl static const struct of_device_id meson_sar_adc_of_match[] = { 12503adbf342SMartin Blumenstingl { 12516c76ed31SMartin Blumenstingl .compatible = "amlogic,meson8-saradc", 12526c76ed31SMartin Blumenstingl .data = &meson_sar_adc_meson8_data, 125314b15f3fSMartin Blumenstingl }, { 12546c76ed31SMartin Blumenstingl .compatible = "amlogic,meson8b-saradc", 12556c76ed31SMartin Blumenstingl .data = &meson_sar_adc_meson8b_data, 125614b15f3fSMartin Blumenstingl }, { 1257ffc0d638SMartin Blumenstingl .compatible = "amlogic,meson8m2-saradc", 1258ffc0d638SMartin Blumenstingl .data = &meson_sar_adc_meson8m2_data, 125914b15f3fSMartin Blumenstingl }, { 12603adbf342SMartin Blumenstingl .compatible = "amlogic,meson-gxbb-saradc", 12613adbf342SMartin Blumenstingl .data = &meson_sar_adc_gxbb_data, 12623adbf342SMartin Blumenstingl }, { 12633adbf342SMartin Blumenstingl .compatible = "amlogic,meson-gxl-saradc", 12643adbf342SMartin Blumenstingl .data = &meson_sar_adc_gxl_data, 12653adbf342SMartin Blumenstingl }, { 12663adbf342SMartin Blumenstingl .compatible = "amlogic,meson-gxm-saradc", 12673adbf342SMartin Blumenstingl .data = &meson_sar_adc_gxm_data, 1268ff632ddaSXingyu Chen }, { 1269ff632ddaSXingyu Chen .compatible = "amlogic,meson-axg-saradc", 1270ff632ddaSXingyu Chen .data = &meson_sar_adc_axg_data, 1271e415a165SNeil Armstrong }, { 1272e415a165SNeil Armstrong .compatible = "amlogic,meson-g12a-saradc", 1273e415a165SNeil Armstrong .data = &meson_sar_adc_g12a_data, 12743adbf342SMartin Blumenstingl }, 127514b15f3fSMartin Blumenstingl { /* sentinel */ } 12763adbf342SMartin Blumenstingl }; 12773adbf342SMartin Blumenstingl MODULE_DEVICE_TABLE(of, meson_sar_adc_of_match); 12783adbf342SMartin Blumenstingl 12793adbf342SMartin Blumenstingl static int meson_sar_adc_probe(struct platform_device *pdev) 12803adbf342SMartin Blumenstingl { 1281234c64a2SMartin Blumenstingl const struct meson_sar_adc_data *match_data; 12823adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv; 12832d27a021SAndy Shevchenko struct device *dev = &pdev->dev; 12843adbf342SMartin Blumenstingl struct iio_dev *indio_dev; 12853adbf342SMartin Blumenstingl void __iomem *base; 12863af10913SHeiner Kallweit int irq, ret; 12873adbf342SMartin Blumenstingl 128822c26db4SAndy Shevchenko indio_dev = devm_iio_device_alloc(dev, sizeof(*priv)); 12892d27a021SAndy Shevchenko if (!indio_dev) 12902d27a021SAndy Shevchenko return dev_err_probe(dev, -ENOMEM, "failed allocating iio device\n"); 12913adbf342SMartin Blumenstingl 12923adbf342SMartin Blumenstingl priv = iio_priv(indio_dev); 12933af10913SHeiner Kallweit init_completion(&priv->done); 12943adbf342SMartin Blumenstingl 129522c26db4SAndy Shevchenko match_data = of_device_get_match_data(dev); 12962d27a021SAndy Shevchenko if (!match_data) 12972d27a021SAndy Shevchenko return dev_err_probe(dev, -ENODEV, "failed to get match data\n"); 12982f9aeeedSGustavo A. R. Silva 1299057e5a11SMartin Blumenstingl priv->param = match_data->param; 13003adbf342SMartin Blumenstingl 1301057e5a11SMartin Blumenstingl indio_dev->name = match_data->name; 13023adbf342SMartin Blumenstingl indio_dev->modes = INDIO_DIRECT_MODE; 13033adbf342SMartin Blumenstingl indio_dev->info = &meson_sar_adc_iio_info; 13043adbf342SMartin Blumenstingl 13055f401ef0SJonathan Cameron base = devm_platform_ioremap_resource(pdev, 0); 13063adbf342SMartin Blumenstingl if (IS_ERR(base)) 13073adbf342SMartin Blumenstingl return PTR_ERR(base); 13083adbf342SMartin Blumenstingl 130922c26db4SAndy Shevchenko priv->regmap = devm_regmap_init_mmio(dev, base, priv->param->regmap_config); 1310de10ac47SRemi Pommarel if (IS_ERR(priv->regmap)) 1311de10ac47SRemi Pommarel return PTR_ERR(priv->regmap); 1312de10ac47SRemi Pommarel 131322c26db4SAndy Shevchenko irq = irq_of_parse_and_map(dev->of_node, 0); 13143af10913SHeiner Kallweit if (!irq) 13153af10913SHeiner Kallweit return -EINVAL; 13163af10913SHeiner Kallweit 131722c26db4SAndy Shevchenko ret = devm_request_irq(dev, irq, meson_sar_adc_irq, IRQF_SHARED, dev_name(dev), indio_dev); 13183af10913SHeiner Kallweit if (ret) 13193af10913SHeiner Kallweit return ret; 13203af10913SHeiner Kallweit 132122c26db4SAndy Shevchenko priv->clkin = devm_clk_get(dev, "clkin"); 1322a5999024SCai Huoqing if (IS_ERR(priv->clkin)) 132322c26db4SAndy Shevchenko return dev_err_probe(dev, PTR_ERR(priv->clkin), "failed to get clkin\n"); 13243adbf342SMartin Blumenstingl 132522c26db4SAndy Shevchenko priv->core_clk = devm_clk_get(dev, "core"); 1326a5999024SCai Huoqing if (IS_ERR(priv->core_clk)) 132722c26db4SAndy Shevchenko return dev_err_probe(dev, PTR_ERR(priv->core_clk), "failed to get core clk\n"); 13283adbf342SMartin Blumenstingl 13296531f3a4SAndy Shevchenko priv->adc_clk = devm_clk_get_optional(dev, "adc_clk"); 13306531f3a4SAndy Shevchenko if (IS_ERR(priv->adc_clk)) 13316531f3a4SAndy Shevchenko return dev_err_probe(dev, PTR_ERR(priv->adc_clk), "failed to get adc clk\n"); 13323adbf342SMartin Blumenstingl 13336531f3a4SAndy Shevchenko priv->adc_sel_clk = devm_clk_get_optional(dev, "adc_sel"); 13346531f3a4SAndy Shevchenko if (IS_ERR(priv->adc_sel_clk)) 13356531f3a4SAndy Shevchenko return dev_err_probe(dev, PTR_ERR(priv->adc_sel_clk), "failed to get adc_sel clk\n"); 13363adbf342SMartin Blumenstingl 13373adbf342SMartin Blumenstingl /* on pre-GXBB SoCs the SAR ADC itself provides the ADC clock: */ 13383adbf342SMartin Blumenstingl if (!priv->adc_clk) { 13393adbf342SMartin Blumenstingl ret = meson_sar_adc_clk_init(indio_dev, base); 13403adbf342SMartin Blumenstingl if (ret) 13413adbf342SMartin Blumenstingl return ret; 13423adbf342SMartin Blumenstingl } 13433adbf342SMartin Blumenstingl 134422c26db4SAndy Shevchenko priv->vref = devm_regulator_get(dev, "vref"); 1345a5999024SCai Huoqing if (IS_ERR(priv->vref)) 134622c26db4SAndy Shevchenko return dev_err_probe(dev, PTR_ERR(priv->vref), "failed to get vref regulator\n"); 13473adbf342SMartin Blumenstingl 134848ba7c3cSHeiner Kallweit priv->calibscale = MILLION; 134948ba7c3cSHeiner Kallweit 1350723a61e0SMartin Blumenstingl if (priv->param->temperature_trimming_bits) { 1351723a61e0SMartin Blumenstingl ret = meson_sar_adc_temp_sensor_init(indio_dev); 1352723a61e0SMartin Blumenstingl if (ret) 1353723a61e0SMartin Blumenstingl return ret; 1354723a61e0SMartin Blumenstingl } 1355723a61e0SMartin Blumenstingl 1356723a61e0SMartin Blumenstingl if (priv->temperature_sensor_calibrated) { 1357723a61e0SMartin Blumenstingl indio_dev->channels = meson_sar_adc_and_temp_iio_channels; 1358723a61e0SMartin Blumenstingl indio_dev->num_channels = 1359723a61e0SMartin Blumenstingl ARRAY_SIZE(meson_sar_adc_and_temp_iio_channels); 1360723a61e0SMartin Blumenstingl } else { 1361723a61e0SMartin Blumenstingl indio_dev->channels = meson_sar_adc_iio_channels; 1362723a61e0SMartin Blumenstingl indio_dev->num_channels = 1363723a61e0SMartin Blumenstingl ARRAY_SIZE(meson_sar_adc_iio_channels); 1364723a61e0SMartin Blumenstingl } 1365723a61e0SMartin Blumenstingl 13663adbf342SMartin Blumenstingl ret = meson_sar_adc_init(indio_dev); 13673adbf342SMartin Blumenstingl if (ret) 13683adbf342SMartin Blumenstingl goto err; 13693adbf342SMartin Blumenstingl 1370d0c09264SNuno Sá mutex_init(&priv->lock); 1371d0c09264SNuno Sá 13723adbf342SMartin Blumenstingl ret = meson_sar_adc_hw_enable(indio_dev); 13733adbf342SMartin Blumenstingl if (ret) 13743adbf342SMartin Blumenstingl goto err; 13753adbf342SMartin Blumenstingl 137648ba7c3cSHeiner Kallweit ret = meson_sar_adc_calib(indio_dev); 137748ba7c3cSHeiner Kallweit if (ret) 137822c26db4SAndy Shevchenko dev_warn(dev, "calibration failed\n"); 137948ba7c3cSHeiner Kallweit 13803adbf342SMartin Blumenstingl platform_set_drvdata(pdev, indio_dev); 13813adbf342SMartin Blumenstingl 13823adbf342SMartin Blumenstingl ret = iio_device_register(indio_dev); 13833adbf342SMartin Blumenstingl if (ret) 13843adbf342SMartin Blumenstingl goto err_hw; 13853adbf342SMartin Blumenstingl 13863adbf342SMartin Blumenstingl return 0; 13873adbf342SMartin Blumenstingl 13883adbf342SMartin Blumenstingl err_hw: 13893adbf342SMartin Blumenstingl meson_sar_adc_hw_disable(indio_dev); 13903adbf342SMartin Blumenstingl err: 13913adbf342SMartin Blumenstingl return ret; 13923adbf342SMartin Blumenstingl } 13933adbf342SMartin Blumenstingl 13943adbf342SMartin Blumenstingl static int meson_sar_adc_remove(struct platform_device *pdev) 13953adbf342SMartin Blumenstingl { 13963adbf342SMartin Blumenstingl struct iio_dev *indio_dev = platform_get_drvdata(pdev); 13973adbf342SMartin Blumenstingl 13983adbf342SMartin Blumenstingl iio_device_unregister(indio_dev); 13993adbf342SMartin Blumenstingl 14004ab8bef1SUwe Kleine-König meson_sar_adc_hw_disable(indio_dev); 14014ab8bef1SUwe Kleine-König 14024ab8bef1SUwe Kleine-König return 0; 14033adbf342SMartin Blumenstingl } 14043adbf342SMartin Blumenstingl 140550737998SJonathan Cameron static int meson_sar_adc_suspend(struct device *dev) 14063adbf342SMartin Blumenstingl { 14073adbf342SMartin Blumenstingl struct iio_dev *indio_dev = dev_get_drvdata(dev); 14083adbf342SMartin Blumenstingl 14094ab8bef1SUwe Kleine-König meson_sar_adc_hw_disable(indio_dev); 14104ab8bef1SUwe Kleine-König 14114ab8bef1SUwe Kleine-König return 0; 14123adbf342SMartin Blumenstingl } 14133adbf342SMartin Blumenstingl 141450737998SJonathan Cameron static int meson_sar_adc_resume(struct device *dev) 14153adbf342SMartin Blumenstingl { 14163adbf342SMartin Blumenstingl struct iio_dev *indio_dev = dev_get_drvdata(dev); 14173adbf342SMartin Blumenstingl 14183adbf342SMartin Blumenstingl return meson_sar_adc_hw_enable(indio_dev); 14193adbf342SMartin Blumenstingl } 14203adbf342SMartin Blumenstingl 142150737998SJonathan Cameron static DEFINE_SIMPLE_DEV_PM_OPS(meson_sar_adc_pm_ops, 14223adbf342SMartin Blumenstingl meson_sar_adc_suspend, meson_sar_adc_resume); 14233adbf342SMartin Blumenstingl 14243adbf342SMartin Blumenstingl static struct platform_driver meson_sar_adc_driver = { 14253adbf342SMartin Blumenstingl .probe = meson_sar_adc_probe, 14263adbf342SMartin Blumenstingl .remove = meson_sar_adc_remove, 14273adbf342SMartin Blumenstingl .driver = { 14283adbf342SMartin Blumenstingl .name = "meson-saradc", 14293adbf342SMartin Blumenstingl .of_match_table = meson_sar_adc_of_match, 143050737998SJonathan Cameron .pm = pm_sleep_ptr(&meson_sar_adc_pm_ops), 14313adbf342SMartin Blumenstingl }, 14323adbf342SMartin Blumenstingl }; 14333adbf342SMartin Blumenstingl 14343adbf342SMartin Blumenstingl module_platform_driver(meson_sar_adc_driver); 14353adbf342SMartin Blumenstingl 14363adbf342SMartin Blumenstingl MODULE_AUTHOR("Martin Blumenstingl <martin.blumenstingl@googlemail.com>"); 14373adbf342SMartin Blumenstingl MODULE_DESCRIPTION("Amlogic Meson SAR ADC driver"); 14383adbf342SMartin Blumenstingl MODULE_LICENSE("GPL v2"); 1439