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/platform_device.h>
213adbf342SMartin Blumenstingl #include <linux/regmap.h>
223adbf342SMartin Blumenstingl #include <linux/regulator/consumer.h>
23b002bf5fSMartin Blumenstingl #include <linux/mfd/syscon.h>
243adbf342SMartin Blumenstingl
253adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0 0x00
263adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_PANEL_DETECT BIT(31)
273adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_BUSY_MASK GENMASK(30, 28)
283adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_DELTA_BUSY BIT(30)
293adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_AVG_BUSY BIT(29)
303adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_SAMPLE_BUSY BIT(28)
313adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_FIFO_FULL BIT(27)
323adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_FIFO_EMPTY BIT(26)
333adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_FIFO_COUNT_MASK GENMASK(25, 21)
343adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_ADC_BIAS_CTRL_MASK GENMASK(20, 19)
353adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_CURR_CHAN_ID_MASK GENMASK(18, 16)
363adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_ADC_TEMP_SEN_SEL BIT(15)
373adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_SAMPLING_STOP BIT(14)
383adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_CHAN_DELTA_EN_MASK GENMASK(13, 12)
393adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_DETECT_IRQ_POL BIT(10)
403adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_DETECT_IRQ_EN BIT(9)
413adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK GENMASK(8, 4)
423adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_FIFO_IRQ_EN BIT(3)
433adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_SAMPLING_START BIT(2)
443adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_CONTINUOUS_EN BIT(1)
453adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE BIT(0)
463adbf342SMartin Blumenstingl
473adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_LIST 0x04
483adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_LIST_MAX_INDEX_MASK GENMASK(26, 24)
493adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_LIST_ENTRY_MASK(_chan) \
503adbf342SMartin Blumenstingl (GENMASK(2, 0) << ((_chan) * 3))
513adbf342SMartin Blumenstingl
523adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AVG_CNTL 0x08
533adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AVG_CNTL_AVG_MODE_SHIFT(_chan) \
543adbf342SMartin Blumenstingl (16 + ((_chan) * 2))
553adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AVG_CNTL_AVG_MODE_MASK(_chan) \
563adbf342SMartin Blumenstingl (GENMASK(17, 16) << ((_chan) * 2))
573adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AVG_CNTL_NUM_SAMPLES_SHIFT(_chan) \
583adbf342SMartin Blumenstingl (0 + ((_chan) * 2))
593adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AVG_CNTL_NUM_SAMPLES_MASK(_chan) \
603adbf342SMartin Blumenstingl (GENMASK(1, 0) << ((_chan) * 2))
613adbf342SMartin Blumenstingl
623adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3 0x0c
633adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_CNTL_USE_SC_DLY BIT(31)
643adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_CLK_EN BIT(30)
653adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_BL30_INITIALIZED BIT(28)
663adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_CTRL_CONT_RING_COUNTER_EN BIT(27)
673adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_CTRL_SAMPLING_CLOCK_PHASE BIT(26)
683adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_CTRL_CHAN7_MUX_SEL_MASK GENMASK(25, 23)
693adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_DETECT_EN BIT(22)
703adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_ADC_EN BIT(21)
713adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_PANEL_DETECT_COUNT_MASK GENMASK(20, 18)
723adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_PANEL_DETECT_FILTER_TB_MASK GENMASK(17, 16)
733adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_ADC_CLK_DIV_SHIFT 10
74c57fa003SGeorge Stark #define MESON_SAR_ADC_REG3_ADC_CLK_DIV_WIDTH 6
753adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_BLOCK_DLY_SEL_MASK GENMASK(9, 8)
763adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG3_BLOCK_DLY_MASK GENMASK(7, 0)
773adbf342SMartin Blumenstingl
783adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELAY 0x10
793adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELAY_INPUT_DLY_SEL_MASK GENMASK(25, 24)
803adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELAY_BL30_BUSY BIT(15)
813adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELAY_KERNEL_BUSY BIT(14)
823adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELAY_INPUT_DLY_CNT_MASK GENMASK(23, 16)
833adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELAY_SAMPLE_DLY_SEL_MASK GENMASK(9, 8)
843adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELAY_SAMPLE_DLY_CNT_MASK GENMASK(7, 0)
853adbf342SMartin Blumenstingl
863adbf342SMartin Blumenstingl #define MESON_SAR_ADC_LAST_RD 0x14
873adbf342SMartin Blumenstingl #define MESON_SAR_ADC_LAST_RD_LAST_CHANNEL1_MASK GENMASK(23, 16)
883adbf342SMartin Blumenstingl #define MESON_SAR_ADC_LAST_RD_LAST_CHANNEL0_MASK GENMASK(9, 0)
893adbf342SMartin Blumenstingl
903adbf342SMartin Blumenstingl #define MESON_SAR_ADC_FIFO_RD 0x18
913adbf342SMartin Blumenstingl #define MESON_SAR_ADC_FIFO_RD_CHAN_ID_MASK GENMASK(14, 12)
923adbf342SMartin Blumenstingl #define MESON_SAR_ADC_FIFO_RD_SAMPLE_VALUE_MASK GENMASK(11, 0)
933adbf342SMartin Blumenstingl
943adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AUX_SW 0x1c
95ab569a4cSMartin Blumenstingl #define MESON_SAR_ADC_AUX_SW_MUX_SEL_CHAN_SHIFT(_chan) \
96ab569a4cSMartin Blumenstingl (8 + (((_chan) - 2) * 3))
973adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AUX_SW_VREF_P_MUX BIT(6)
983adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AUX_SW_VREF_N_MUX BIT(5)
993adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AUX_SW_MODE_SEL BIT(4)
1003adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AUX_SW_YP_DRIVE_SW BIT(3)
1013adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AUX_SW_XP_DRIVE_SW BIT(2)
1023adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AUX_SW_YM_DRIVE_SW BIT(1)
1033adbf342SMartin Blumenstingl #define MESON_SAR_ADC_AUX_SW_XM_DRIVE_SW BIT(0)
1043adbf342SMartin Blumenstingl
1053adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW 0x20
1063adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_MUX_SEL_MASK GENMASK(25, 23)
1073adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_VREF_P_MUX BIT(22)
1083adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_VREF_N_MUX BIT(21)
1093adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_MODE_SEL BIT(20)
1103adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_YP_DRIVE_SW BIT(19)
1113adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_XP_DRIVE_SW BIT(18)
1123adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_YM_DRIVE_SW BIT(17)
1133adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN1_XM_DRIVE_SW BIT(16)
1143adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_MUX_SEL_MASK GENMASK(9, 7)
1153adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_VREF_P_MUX BIT(6)
1163adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_VREF_N_MUX BIT(5)
1173adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_MODE_SEL BIT(4)
1183adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_YP_DRIVE_SW BIT(3)
1193adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_XP_DRIVE_SW BIT(2)
1203adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_YM_DRIVE_SW BIT(1)
1213adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN_10_SW_CHAN0_XM_DRIVE_SW BIT(0)
1223adbf342SMartin Blumenstingl
1233adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW 0x24
1243adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_SW_EN BIT(26)
1253adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_MUX_MASK GENMASK(25, 23)
1263adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_VREF_P_MUX BIT(22)
1273adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_VREF_N_MUX BIT(21)
1283adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_MODE_SEL BIT(20)
1293adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_YP_DRIVE_SW BIT(19)
1303adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_XP_DRIVE_SW BIT(18)
1313adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_YM_DRIVE_SW BIT(17)
1323adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_XM_DRIVE_SW BIT(16)
1333adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_MUX_SEL_MASK GENMASK(9, 7)
1343adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_VREF_P_MUX BIT(6)
1353adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_VREF_N_MUX BIT(5)
1363adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_MODE_SEL BIT(4)
1373adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_YP_DRIVE_SW BIT(3)
1383adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_XP_DRIVE_SW BIT(2)
1393adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_YM_DRIVE_SW BIT(1)
1403adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_XM_DRIVE_SW BIT(0)
1413adbf342SMartin Blumenstingl
1423adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELTA_10 0x28
1433adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELTA_10_TEMP_SEL BIT(27)
1443adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELTA_10_TS_REVE1 BIT(26)
1453adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELTA_10_CHAN1_DELTA_VALUE_MASK GENMASK(25, 16)
1463adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELTA_10_TS_REVE0 BIT(15)
1473adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELTA_10_TS_C_MASK GENMASK(14, 11)
1483adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELTA_10_TS_VBG_EN BIT(10)
1493adbf342SMartin Blumenstingl #define MESON_SAR_ADC_DELTA_10_CHAN0_DELTA_VALUE_MASK GENMASK(9, 0)
1503adbf342SMartin Blumenstingl
1513adbf342SMartin Blumenstingl /*
1523adbf342SMartin Blumenstingl * NOTE: registers from here are undocumented (the vendor Linux kernel driver
1533adbf342SMartin Blumenstingl * and u-boot source served as reference). These only seem to be relevant on
1543adbf342SMartin Blumenstingl * GXBB and newer.
1553adbf342SMartin Blumenstingl */
1563adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG11 0x2c
1573adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG11_BANDGAP_EN BIT(13)
15890c62418SGeorge Stark #define MESON_SAR_ADC_REG11_CMV_SEL BIT(6)
15990c62418SGeorge Stark #define MESON_SAR_ADC_REG11_VREF_VOLTAGE BIT(5)
16090c62418SGeorge Stark #define MESON_SAR_ADC_REG11_EOC BIT(1)
16190c62418SGeorge Stark #define MESON_SAR_ADC_REG11_VREF_SEL BIT(0)
1623adbf342SMartin Blumenstingl
1633adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG13 0x34
1643adbf342SMartin Blumenstingl #define MESON_SAR_ADC_REG13_12BIT_CALIBRATION_MASK GENMASK(13, 8)
1653adbf342SMartin Blumenstingl
1663adbf342SMartin Blumenstingl #define MESON_SAR_ADC_MAX_FIFO_SIZE 32
1673af10913SHeiner Kallweit #define MESON_SAR_ADC_TIMEOUT 100 /* ms */
168723a61e0SMartin Blumenstingl #define MESON_SAR_ADC_VOLTAGE_AND_TEMP_CHANNEL 6
1693a06b284SGeorge Stark #define MESON_SAR_ADC_VOLTAGE_AND_MUX_CHANNEL 7
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
177b002bf5fSMartin Blumenstingl #define MESON_HHI_DPLL_TOP_0 0x318
178b002bf5fSMartin Blumenstingl #define MESON_HHI_DPLL_TOP_0_TSC_BIT4 BIT(9)
179b002bf5fSMartin Blumenstingl
18048ba7c3cSHeiner Kallweit /* for use with IIO_VAL_INT_PLUS_MICRO */
18148ba7c3cSHeiner Kallweit #define MILLION 1000000
1823adbf342SMartin Blumenstingl
1833adbf342SMartin Blumenstingl #define MESON_SAR_ADC_CHAN(_chan) { \
1843adbf342SMartin Blumenstingl .type = IIO_VOLTAGE, \
1853adbf342SMartin Blumenstingl .indexed = 1, \
1863adbf342SMartin Blumenstingl .channel = _chan, \
187827df057SMartin Blumenstingl .address = _chan, \
1883adbf342SMartin Blumenstingl .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
1893adbf342SMartin Blumenstingl BIT(IIO_CHAN_INFO_AVERAGE_RAW), \
190723a61e0SMartin Blumenstingl .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
191723a61e0SMartin Blumenstingl .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_CALIBBIAS) | \
19248ba7c3cSHeiner Kallweit BIT(IIO_CHAN_INFO_CALIBSCALE), \
1933adbf342SMartin Blumenstingl .datasheet_name = "SAR_ADC_CH"#_chan, \
1943adbf342SMartin Blumenstingl }
1953adbf342SMartin Blumenstingl
196723a61e0SMartin Blumenstingl #define MESON_SAR_ADC_TEMP_CHAN(_chan) { \
197723a61e0SMartin Blumenstingl .type = IIO_TEMP, \
198723a61e0SMartin Blumenstingl .channel = _chan, \
199723a61e0SMartin Blumenstingl .address = MESON_SAR_ADC_VOLTAGE_AND_TEMP_CHANNEL, \
200723a61e0SMartin Blumenstingl .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
201723a61e0SMartin Blumenstingl BIT(IIO_CHAN_INFO_AVERAGE_RAW), \
202723a61e0SMartin Blumenstingl .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) | \
203723a61e0SMartin Blumenstingl BIT(IIO_CHAN_INFO_SCALE), \
204723a61e0SMartin Blumenstingl .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_CALIBBIAS) | \
205723a61e0SMartin Blumenstingl BIT(IIO_CHAN_INFO_CALIBSCALE), \
206723a61e0SMartin Blumenstingl .datasheet_name = "TEMP_SENSOR", \
207723a61e0SMartin Blumenstingl }
208723a61e0SMartin Blumenstingl
2093a06b284SGeorge Stark #define MESON_SAR_ADC_MUX(_chan, _sel) { \
2103a06b284SGeorge Stark .type = IIO_VOLTAGE, \
2113a06b284SGeorge Stark .channel = _chan, \
2123a06b284SGeorge Stark .indexed = 1, \
2133a06b284SGeorge Stark .address = MESON_SAR_ADC_VOLTAGE_AND_MUX_CHANNEL, \
2143a06b284SGeorge Stark .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
2153a06b284SGeorge Stark BIT(IIO_CHAN_INFO_AVERAGE_RAW), \
2163a06b284SGeorge Stark .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
2173a06b284SGeorge Stark .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_CALIBBIAS) | \
2183a06b284SGeorge Stark BIT(IIO_CHAN_INFO_CALIBSCALE), \
2193a06b284SGeorge Stark .datasheet_name = "SAR_ADC_MUX_"#_sel, \
2203a06b284SGeorge Stark }
2213a06b284SGeorge Stark
22290c62418SGeorge Stark enum meson_sar_adc_vref_sel {
22390c62418SGeorge Stark VREF_CALIBATION_VOLTAGE = 0,
22490c62418SGeorge Stark VREF_VDDA = 1,
22590c62418SGeorge Stark };
22690c62418SGeorge Stark
227d26f0514SGeorge Stark enum meson_sar_adc_avg_mode {
228d26f0514SGeorge Stark NO_AVERAGING = 0x0,
229d26f0514SGeorge Stark MEAN_AVERAGING = 0x1,
230d26f0514SGeorge Stark MEDIAN_AVERAGING = 0x2,
231d26f0514SGeorge Stark };
232d26f0514SGeorge Stark
233d26f0514SGeorge Stark enum meson_sar_adc_num_samples {
234d26f0514SGeorge Stark ONE_SAMPLE = 0x0,
235d26f0514SGeorge Stark TWO_SAMPLES = 0x1,
236d26f0514SGeorge Stark FOUR_SAMPLES = 0x2,
237d26f0514SGeorge Stark EIGHT_SAMPLES = 0x3,
238d26f0514SGeorge Stark };
239d26f0514SGeorge Stark
240d26f0514SGeorge Stark enum meson_sar_adc_chan7_mux_sel {
241d26f0514SGeorge Stark CHAN7_MUX_VSS = 0x0,
242d26f0514SGeorge Stark CHAN7_MUX_VDD_DIV4 = 0x1,
243d26f0514SGeorge Stark CHAN7_MUX_VDD_DIV2 = 0x2,
244d26f0514SGeorge Stark CHAN7_MUX_VDD_MUL3_DIV4 = 0x3,
245d26f0514SGeorge Stark CHAN7_MUX_VDD = 0x4,
246d26f0514SGeorge Stark CHAN7_MUX_CH7_INPUT = 0x7,
247d26f0514SGeorge Stark };
248d26f0514SGeorge Stark
249c38180bfSGeorge Stark enum meson_sar_adc_channel_index {
250c38180bfSGeorge Stark NUM_CHAN_0,
251c38180bfSGeorge Stark NUM_CHAN_1,
252c38180bfSGeorge Stark NUM_CHAN_2,
253c38180bfSGeorge Stark NUM_CHAN_3,
254c38180bfSGeorge Stark NUM_CHAN_4,
255c38180bfSGeorge Stark NUM_CHAN_5,
256c38180bfSGeorge Stark NUM_CHAN_6,
257c38180bfSGeorge Stark NUM_CHAN_7,
258c38180bfSGeorge Stark NUM_CHAN_TEMP,
2593a06b284SGeorge Stark NUM_MUX_0_VSS,
2603a06b284SGeorge Stark NUM_MUX_1_VDD_DIV4,
2613a06b284SGeorge Stark NUM_MUX_2_VDD_DIV2,
2623a06b284SGeorge Stark NUM_MUX_3_VDD_MUL3_DIV4,
2633a06b284SGeorge Stark NUM_MUX_4_VDD,
2643a06b284SGeorge Stark };
2653a06b284SGeorge Stark
2663a06b284SGeorge Stark static enum meson_sar_adc_chan7_mux_sel chan7_mux_values[] = {
2673a06b284SGeorge Stark CHAN7_MUX_VSS,
2683a06b284SGeorge Stark CHAN7_MUX_VDD_DIV4,
2693a06b284SGeorge Stark CHAN7_MUX_VDD_DIV2,
2703a06b284SGeorge Stark CHAN7_MUX_VDD_MUL3_DIV4,
2713a06b284SGeorge Stark CHAN7_MUX_VDD,
2723a06b284SGeorge Stark };
2733a06b284SGeorge Stark
2743a06b284SGeorge Stark static const char * const chan7_mux_names[] = {
2753a06b284SGeorge Stark [CHAN7_MUX_VSS] = "gnd",
2763a06b284SGeorge Stark [CHAN7_MUX_VDD_DIV4] = "0.25vdd",
2773a06b284SGeorge Stark [CHAN7_MUX_VDD_DIV2] = "0.5vdd",
2783a06b284SGeorge Stark [CHAN7_MUX_VDD_MUL3_DIV4] = "0.75vdd",
2793a06b284SGeorge Stark [CHAN7_MUX_VDD] = "vdd",
280c38180bfSGeorge Stark };
281c38180bfSGeorge Stark
2823adbf342SMartin Blumenstingl static const struct iio_chan_spec meson_sar_adc_iio_channels[] = {
283c38180bfSGeorge Stark MESON_SAR_ADC_CHAN(NUM_CHAN_0),
284c38180bfSGeorge Stark MESON_SAR_ADC_CHAN(NUM_CHAN_1),
285c38180bfSGeorge Stark MESON_SAR_ADC_CHAN(NUM_CHAN_2),
286c38180bfSGeorge Stark MESON_SAR_ADC_CHAN(NUM_CHAN_3),
287c38180bfSGeorge Stark MESON_SAR_ADC_CHAN(NUM_CHAN_4),
288c38180bfSGeorge Stark MESON_SAR_ADC_CHAN(NUM_CHAN_5),
289c38180bfSGeorge Stark MESON_SAR_ADC_CHAN(NUM_CHAN_6),
290c38180bfSGeorge Stark MESON_SAR_ADC_CHAN(NUM_CHAN_7),
2913a06b284SGeorge Stark MESON_SAR_ADC_MUX(NUM_MUX_0_VSS, 0),
2923a06b284SGeorge Stark MESON_SAR_ADC_MUX(NUM_MUX_1_VDD_DIV4, 1),
2933a06b284SGeorge Stark MESON_SAR_ADC_MUX(NUM_MUX_2_VDD_DIV2, 2),
2943a06b284SGeorge Stark MESON_SAR_ADC_MUX(NUM_MUX_3_VDD_MUL3_DIV4, 3),
2953a06b284SGeorge Stark MESON_SAR_ADC_MUX(NUM_MUX_4_VDD, 4),
2963adbf342SMartin Blumenstingl };
2973adbf342SMartin Blumenstingl
298723a61e0SMartin Blumenstingl static const struct iio_chan_spec meson_sar_adc_and_temp_iio_channels[] = {
299c38180bfSGeorge Stark MESON_SAR_ADC_CHAN(NUM_CHAN_0),
300c38180bfSGeorge Stark MESON_SAR_ADC_CHAN(NUM_CHAN_1),
301c38180bfSGeorge Stark MESON_SAR_ADC_CHAN(NUM_CHAN_2),
302c38180bfSGeorge Stark MESON_SAR_ADC_CHAN(NUM_CHAN_3),
303c38180bfSGeorge Stark MESON_SAR_ADC_CHAN(NUM_CHAN_4),
304c38180bfSGeorge Stark MESON_SAR_ADC_CHAN(NUM_CHAN_5),
305c38180bfSGeorge Stark MESON_SAR_ADC_CHAN(NUM_CHAN_6),
306c38180bfSGeorge Stark MESON_SAR_ADC_CHAN(NUM_CHAN_7),
307c38180bfSGeorge Stark MESON_SAR_ADC_TEMP_CHAN(NUM_CHAN_TEMP),
3083a06b284SGeorge Stark MESON_SAR_ADC_MUX(NUM_MUX_0_VSS, 0),
3093a06b284SGeorge Stark MESON_SAR_ADC_MUX(NUM_MUX_1_VDD_DIV4, 1),
3103a06b284SGeorge Stark MESON_SAR_ADC_MUX(NUM_MUX_2_VDD_DIV2, 2),
3113a06b284SGeorge Stark MESON_SAR_ADC_MUX(NUM_MUX_3_VDD_MUL3_DIV4, 3),
3123a06b284SGeorge Stark MESON_SAR_ADC_MUX(NUM_MUX_4_VDD, 4),
313723a61e0SMartin Blumenstingl };
314723a61e0SMartin Blumenstingl
315053ffe3cSYixun Lan struct meson_sar_adc_param {
3166c76ed31SMartin Blumenstingl bool has_bl30_integration;
317fda29dbaSMartin Blumenstingl unsigned long clock_rate;
318d85eed9fSMartin Blumenstingl u32 bandgap_reg;
3193adbf342SMartin Blumenstingl unsigned int resolution;
32096748823SMartin Blumenstingl const struct regmap_config *regmap_config;
321723a61e0SMartin Blumenstingl u8 temperature_trimming_bits;
322723a61e0SMartin Blumenstingl unsigned int temperature_multiplier;
323723a61e0SMartin Blumenstingl unsigned int temperature_divider;
324d1adcaf7SGeorge Stark u8 disable_ring_counter;
32590c62418SGeorge Stark bool has_reg11;
32690c62418SGeorge Stark bool has_vref_select;
32790c62418SGeorge Stark u8 vref_select;
32890c62418SGeorge Stark u8 cmv_select;
32990c62418SGeorge Stark u8 adc_eoc;
33090c62418SGeorge Stark enum meson_sar_adc_vref_sel vref_volatge;
3313adbf342SMartin Blumenstingl };
3323adbf342SMartin Blumenstingl
333053ffe3cSYixun Lan struct meson_sar_adc_data {
334053ffe3cSYixun Lan const struct meson_sar_adc_param *param;
335053ffe3cSYixun Lan const char *name;
336053ffe3cSYixun Lan };
337053ffe3cSYixun Lan
3383adbf342SMartin Blumenstingl struct meson_sar_adc_priv {
3393adbf342SMartin Blumenstingl struct regmap *regmap;
3403adbf342SMartin Blumenstingl struct regulator *vref;
341057e5a11SMartin Blumenstingl const struct meson_sar_adc_param *param;
3423adbf342SMartin Blumenstingl struct clk *clkin;
3433adbf342SMartin Blumenstingl struct clk *core_clk;
3443adbf342SMartin Blumenstingl struct clk *adc_sel_clk;
3453adbf342SMartin Blumenstingl struct clk *adc_clk;
3463adbf342SMartin Blumenstingl struct clk_gate clk_gate;
3473adbf342SMartin Blumenstingl struct clk *adc_div_clk;
3483adbf342SMartin Blumenstingl struct clk_divider clk_div;
3493af10913SHeiner Kallweit struct completion done;
350d0c09264SNuno Sá /* lock to protect against multiple access to the device */
351d0c09264SNuno Sá struct mutex lock;
35248ba7c3cSHeiner Kallweit int calibbias;
35348ba7c3cSHeiner Kallweit int calibscale;
354b002bf5fSMartin Blumenstingl struct regmap *tsc_regmap;
355723a61e0SMartin Blumenstingl bool temperature_sensor_calibrated;
356723a61e0SMartin Blumenstingl u8 temperature_sensor_coefficient;
357723a61e0SMartin Blumenstingl u16 temperature_sensor_adc_val;
3583a06b284SGeorge Stark enum meson_sar_adc_chan7_mux_sel chan7_mux_sel;
3593adbf342SMartin Blumenstingl };
3603adbf342SMartin Blumenstingl
36196748823SMartin Blumenstingl static const struct regmap_config meson_sar_adc_regmap_config_gxbb = {
3623adbf342SMartin Blumenstingl .reg_bits = 8,
3633adbf342SMartin Blumenstingl .val_bits = 32,
3643adbf342SMartin Blumenstingl .reg_stride = 4,
3653adbf342SMartin Blumenstingl .max_register = MESON_SAR_ADC_REG13,
3663adbf342SMartin Blumenstingl };
3673adbf342SMartin Blumenstingl
36896748823SMartin Blumenstingl static const struct regmap_config meson_sar_adc_regmap_config_meson8 = {
36996748823SMartin Blumenstingl .reg_bits = 8,
37096748823SMartin Blumenstingl .val_bits = 32,
37196748823SMartin Blumenstingl .reg_stride = 4,
37296748823SMartin Blumenstingl .max_register = MESON_SAR_ADC_DELTA_10,
37396748823SMartin Blumenstingl };
37496748823SMartin Blumenstingl
3753a06b284SGeorge Stark static const struct iio_chan_spec *
find_channel_by_num(struct iio_dev * indio_dev,int num)3763a06b284SGeorge Stark find_channel_by_num(struct iio_dev *indio_dev, int num)
3773a06b284SGeorge Stark {
3783a06b284SGeorge Stark int i;
3793a06b284SGeorge Stark
3803a06b284SGeorge Stark for (i = 0; i < indio_dev->num_channels; i++)
3813a06b284SGeorge Stark if (indio_dev->channels[i].channel == num)
3823a06b284SGeorge Stark return &indio_dev->channels[i];
3833a06b284SGeorge Stark return NULL;
3843a06b284SGeorge Stark }
3853a06b284SGeorge Stark
meson_sar_adc_get_fifo_count(struct iio_dev * indio_dev)3863adbf342SMartin Blumenstingl static unsigned int meson_sar_adc_get_fifo_count(struct iio_dev *indio_dev)
3873adbf342SMartin Blumenstingl {
3883adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
3893adbf342SMartin Blumenstingl u32 regval;
3903adbf342SMartin Blumenstingl
3913adbf342SMartin Blumenstingl regmap_read(priv->regmap, MESON_SAR_ADC_REG0, ®val);
3923adbf342SMartin Blumenstingl
3933adbf342SMartin Blumenstingl return FIELD_GET(MESON_SAR_ADC_REG0_FIFO_COUNT_MASK, regval);
3943adbf342SMartin Blumenstingl }
3953adbf342SMartin Blumenstingl
meson_sar_adc_calib_val(struct iio_dev * indio_dev,int val)39648ba7c3cSHeiner Kallweit static int meson_sar_adc_calib_val(struct iio_dev *indio_dev, int val)
39748ba7c3cSHeiner Kallweit {
39848ba7c3cSHeiner Kallweit struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
39948ba7c3cSHeiner Kallweit int tmp;
40048ba7c3cSHeiner Kallweit
40148ba7c3cSHeiner Kallweit /* use val_calib = scale * val_raw + offset calibration function */
40248ba7c3cSHeiner Kallweit tmp = div_s64((s64)val * priv->calibscale, MILLION) + priv->calibbias;
40348ba7c3cSHeiner Kallweit
404057e5a11SMartin Blumenstingl return clamp(tmp, 0, (1 << priv->param->resolution) - 1);
40548ba7c3cSHeiner Kallweit }
40648ba7c3cSHeiner Kallweit
meson_sar_adc_wait_busy_clear(struct iio_dev * indio_dev)4073adbf342SMartin Blumenstingl static int meson_sar_adc_wait_busy_clear(struct iio_dev *indio_dev)
4083adbf342SMartin Blumenstingl {
4093adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
41079b584edSAndy Shevchenko int val;
4113adbf342SMartin Blumenstingl
4123adbf342SMartin Blumenstingl /*
4133adbf342SMartin Blumenstingl * NOTE: we need a small delay before reading the status, otherwise
4143adbf342SMartin Blumenstingl * the sample engine may not have started internally (which would
4153adbf342SMartin Blumenstingl * seem to us that sampling is already finished).
4163adbf342SMartin Blumenstingl */
4173adbf342SMartin Blumenstingl udelay(1);
41879b584edSAndy Shevchenko return regmap_read_poll_timeout_atomic(priv->regmap, MESON_SAR_ADC_REG0, val,
41979b584edSAndy Shevchenko !FIELD_GET(MESON_SAR_ADC_REG0_BUSY_MASK, val),
42079b584edSAndy Shevchenko 1, 10000);
4213adbf342SMartin Blumenstingl }
4223adbf342SMartin Blumenstingl
meson_sar_adc_set_chan7_mux(struct iio_dev * indio_dev,enum meson_sar_adc_chan7_mux_sel sel)4232b592ff4SGeorge Stark static void meson_sar_adc_set_chan7_mux(struct iio_dev *indio_dev,
4242b592ff4SGeorge Stark enum meson_sar_adc_chan7_mux_sel sel)
4252b592ff4SGeorge Stark {
4262b592ff4SGeorge Stark struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
4272b592ff4SGeorge Stark u32 regval;
4282b592ff4SGeorge Stark
4292b592ff4SGeorge Stark regval = FIELD_PREP(MESON_SAR_ADC_REG3_CTRL_CHAN7_MUX_SEL_MASK, sel);
4302b592ff4SGeorge Stark regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3,
4312b592ff4SGeorge Stark MESON_SAR_ADC_REG3_CTRL_CHAN7_MUX_SEL_MASK, regval);
4322b592ff4SGeorge Stark
4332b592ff4SGeorge Stark usleep_range(10, 20);
4343a06b284SGeorge Stark
4353a06b284SGeorge Stark priv->chan7_mux_sel = sel;
4362b592ff4SGeorge Stark }
4372b592ff4SGeorge Stark
meson_sar_adc_read_raw_sample(struct iio_dev * indio_dev,const struct iio_chan_spec * chan,int * val)4383adbf342SMartin Blumenstingl static int meson_sar_adc_read_raw_sample(struct iio_dev *indio_dev,
4393adbf342SMartin Blumenstingl const struct iio_chan_spec *chan,
4403adbf342SMartin Blumenstingl int *val)
4413adbf342SMartin Blumenstingl {
4423adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
443d43c7006SAndy Shevchenko struct device *dev = indio_dev->dev.parent;
4446a882a2cSHeiner Kallweit int regval, fifo_chan, fifo_val, count;
4453adbf342SMartin Blumenstingl
4463af10913SHeiner Kallweit if (!wait_for_completion_timeout(&priv->done,
4473af10913SHeiner Kallweit msecs_to_jiffies(MESON_SAR_ADC_TIMEOUT)))
4483af10913SHeiner Kallweit return -ETIMEDOUT;
4493adbf342SMartin Blumenstingl
4506a882a2cSHeiner Kallweit count = meson_sar_adc_get_fifo_count(indio_dev);
4516a882a2cSHeiner Kallweit if (count != 1) {
452d43c7006SAndy Shevchenko dev_err(dev, "ADC FIFO has %d element(s) instead of one\n", count);
4536a882a2cSHeiner Kallweit return -EINVAL;
4543adbf342SMartin Blumenstingl }
4553adbf342SMartin Blumenstingl
4566a882a2cSHeiner Kallweit regmap_read(priv->regmap, MESON_SAR_ADC_FIFO_RD, ®val);
4576a882a2cSHeiner Kallweit fifo_chan = FIELD_GET(MESON_SAR_ADC_FIFO_RD_CHAN_ID_MASK, regval);
458827df057SMartin Blumenstingl if (fifo_chan != chan->address) {
459d43c7006SAndy Shevchenko dev_err(dev, "ADC FIFO entry belongs to channel %d instead of %lu\n",
460827df057SMartin Blumenstingl fifo_chan, chan->address);
4616a882a2cSHeiner Kallweit return -EINVAL;
4626a882a2cSHeiner Kallweit }
4633adbf342SMartin Blumenstingl
4646a882a2cSHeiner Kallweit fifo_val = FIELD_GET(MESON_SAR_ADC_FIFO_RD_SAMPLE_VALUE_MASK, regval);
465057e5a11SMartin Blumenstingl fifo_val &= GENMASK(priv->param->resolution - 1, 0);
46648ba7c3cSHeiner Kallweit *val = meson_sar_adc_calib_val(indio_dev, fifo_val);
4673adbf342SMartin Blumenstingl
4683adbf342SMartin Blumenstingl return 0;
4693adbf342SMartin Blumenstingl }
4703adbf342SMartin Blumenstingl
meson_sar_adc_set_averaging(struct iio_dev * indio_dev,const struct iio_chan_spec * chan,enum meson_sar_adc_avg_mode mode,enum meson_sar_adc_num_samples samples)4713adbf342SMartin Blumenstingl static void meson_sar_adc_set_averaging(struct iio_dev *indio_dev,
4723adbf342SMartin Blumenstingl const struct iio_chan_spec *chan,
4733adbf342SMartin Blumenstingl enum meson_sar_adc_avg_mode mode,
4743adbf342SMartin Blumenstingl enum meson_sar_adc_num_samples samples)
4753adbf342SMartin Blumenstingl {
4763adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
477827df057SMartin Blumenstingl int val, address = chan->address;
4783adbf342SMartin Blumenstingl
479827df057SMartin Blumenstingl val = samples << MESON_SAR_ADC_AVG_CNTL_NUM_SAMPLES_SHIFT(address);
4803adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_AVG_CNTL,
481827df057SMartin Blumenstingl MESON_SAR_ADC_AVG_CNTL_NUM_SAMPLES_MASK(address),
4823adbf342SMartin Blumenstingl val);
4833adbf342SMartin Blumenstingl
484827df057SMartin Blumenstingl val = mode << MESON_SAR_ADC_AVG_CNTL_AVG_MODE_SHIFT(address);
4853adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_AVG_CNTL,
486827df057SMartin Blumenstingl MESON_SAR_ADC_AVG_CNTL_AVG_MODE_MASK(address), val);
4873adbf342SMartin Blumenstingl }
4883adbf342SMartin Blumenstingl
meson_sar_adc_enable_channel(struct iio_dev * indio_dev,const struct iio_chan_spec * chan)4893adbf342SMartin Blumenstingl static void meson_sar_adc_enable_channel(struct iio_dev *indio_dev,
4903adbf342SMartin Blumenstingl const struct iio_chan_spec *chan)
4913adbf342SMartin Blumenstingl {
4923adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
4933adbf342SMartin Blumenstingl u32 regval;
4943adbf342SMartin Blumenstingl
4953adbf342SMartin Blumenstingl /*
4963adbf342SMartin Blumenstingl * the SAR ADC engine allows sampling multiple channels at the same
4973adbf342SMartin Blumenstingl * time. to keep it simple we're only working with one *internal*
4983adbf342SMartin Blumenstingl * channel, which starts counting at index 0 (which means: count = 1).
4993adbf342SMartin Blumenstingl */
5003adbf342SMartin Blumenstingl regval = FIELD_PREP(MESON_SAR_ADC_CHAN_LIST_MAX_INDEX_MASK, 0);
5013adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_LIST,
5023adbf342SMartin Blumenstingl MESON_SAR_ADC_CHAN_LIST_MAX_INDEX_MASK, regval);
5033adbf342SMartin Blumenstingl
5043adbf342SMartin Blumenstingl /* map channel index 0 to the channel which we want to read */
5053adbf342SMartin Blumenstingl regval = FIELD_PREP(MESON_SAR_ADC_CHAN_LIST_ENTRY_MASK(0),
506827df057SMartin Blumenstingl chan->address);
5073adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_LIST,
5083adbf342SMartin Blumenstingl MESON_SAR_ADC_CHAN_LIST_ENTRY_MASK(0), regval);
5093adbf342SMartin Blumenstingl
5103adbf342SMartin Blumenstingl regval = FIELD_PREP(MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_MUX_MASK,
511827df057SMartin Blumenstingl chan->address);
5123adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DETECT_IDLE_SW,
5133adbf342SMartin Blumenstingl MESON_SAR_ADC_DETECT_IDLE_SW_DETECT_MUX_MASK,
5143adbf342SMartin Blumenstingl regval);
5153adbf342SMartin Blumenstingl
5163adbf342SMartin Blumenstingl regval = FIELD_PREP(MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_MUX_SEL_MASK,
517827df057SMartin Blumenstingl chan->address);
5183adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DETECT_IDLE_SW,
5193adbf342SMartin Blumenstingl MESON_SAR_ADC_DETECT_IDLE_SW_IDLE_MUX_SEL_MASK,
5203adbf342SMartin Blumenstingl regval);
5213adbf342SMartin Blumenstingl
522723a61e0SMartin Blumenstingl if (chan->address == MESON_SAR_ADC_VOLTAGE_AND_TEMP_CHANNEL) {
523723a61e0SMartin Blumenstingl if (chan->type == IIO_TEMP)
524723a61e0SMartin Blumenstingl regval = MESON_SAR_ADC_DELTA_10_TEMP_SEL;
525723a61e0SMartin Blumenstingl else
526723a61e0SMartin Blumenstingl regval = 0;
527723a61e0SMartin Blumenstingl
528723a61e0SMartin Blumenstingl regmap_update_bits(priv->regmap,
529723a61e0SMartin Blumenstingl MESON_SAR_ADC_DELTA_10,
530723a61e0SMartin Blumenstingl MESON_SAR_ADC_DELTA_10_TEMP_SEL, regval);
5313a06b284SGeorge Stark } else if (chan->address == MESON_SAR_ADC_VOLTAGE_AND_MUX_CHANNEL) {
5323a06b284SGeorge Stark enum meson_sar_adc_chan7_mux_sel sel;
5333a06b284SGeorge Stark
5343a06b284SGeorge Stark if (chan->channel == NUM_CHAN_7)
5353a06b284SGeorge Stark sel = CHAN7_MUX_CH7_INPUT;
5363a06b284SGeorge Stark else
5373a06b284SGeorge Stark sel = chan7_mux_values[chan->channel - NUM_MUX_0_VSS];
5383a06b284SGeorge Stark if (sel != priv->chan7_mux_sel)
5393a06b284SGeorge Stark meson_sar_adc_set_chan7_mux(indio_dev, sel);
540723a61e0SMartin Blumenstingl }
5413adbf342SMartin Blumenstingl }
5423adbf342SMartin Blumenstingl
meson_sar_adc_start_sample_engine(struct iio_dev * indio_dev)5433adbf342SMartin Blumenstingl static void meson_sar_adc_start_sample_engine(struct iio_dev *indio_dev)
5443adbf342SMartin Blumenstingl {
5453adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
5463adbf342SMartin Blumenstingl
5473af10913SHeiner Kallweit reinit_completion(&priv->done);
5483af10913SHeiner Kallweit
5493af10913SHeiner Kallweit regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
5503af10913SHeiner Kallweit MESON_SAR_ADC_REG0_FIFO_IRQ_EN,
5513af10913SHeiner Kallweit MESON_SAR_ADC_REG0_FIFO_IRQ_EN);
5523af10913SHeiner Kallweit
5533adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
5543adbf342SMartin Blumenstingl MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE,
5553adbf342SMartin Blumenstingl MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE);
5563adbf342SMartin Blumenstingl
5573adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
5583adbf342SMartin Blumenstingl MESON_SAR_ADC_REG0_SAMPLING_START,
5593adbf342SMartin Blumenstingl MESON_SAR_ADC_REG0_SAMPLING_START);
5603adbf342SMartin Blumenstingl }
5613adbf342SMartin Blumenstingl
meson_sar_adc_stop_sample_engine(struct iio_dev * indio_dev)5623adbf342SMartin Blumenstingl static void meson_sar_adc_stop_sample_engine(struct iio_dev *indio_dev)
5633adbf342SMartin Blumenstingl {
5643adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
5653adbf342SMartin Blumenstingl
5663adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
5673af10913SHeiner Kallweit MESON_SAR_ADC_REG0_FIFO_IRQ_EN, 0);
5683af10913SHeiner Kallweit
5693af10913SHeiner Kallweit regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
5703adbf342SMartin Blumenstingl MESON_SAR_ADC_REG0_SAMPLING_STOP,
5713adbf342SMartin Blumenstingl MESON_SAR_ADC_REG0_SAMPLING_STOP);
5723adbf342SMartin Blumenstingl
5733adbf342SMartin Blumenstingl /* wait until all modules are stopped */
5743adbf342SMartin Blumenstingl meson_sar_adc_wait_busy_clear(indio_dev);
5753adbf342SMartin Blumenstingl
5763adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
5773adbf342SMartin Blumenstingl MESON_SAR_ADC_REG0_SAMPLE_ENGINE_ENABLE, 0);
5783adbf342SMartin Blumenstingl }
5793adbf342SMartin Blumenstingl
meson_sar_adc_lock(struct iio_dev * indio_dev)5803adbf342SMartin Blumenstingl static int meson_sar_adc_lock(struct iio_dev *indio_dev)
5813adbf342SMartin Blumenstingl {
5823adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
58379b584edSAndy Shevchenko int val, ret;
5843adbf342SMartin Blumenstingl
585d0c09264SNuno Sá mutex_lock(&priv->lock);
5863adbf342SMartin Blumenstingl
587057e5a11SMartin Blumenstingl if (priv->param->has_bl30_integration) {
5883adbf342SMartin Blumenstingl /* prevent BL30 from using the SAR ADC while we are using it */
5893adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY,
5903adbf342SMartin Blumenstingl MESON_SAR_ADC_DELAY_KERNEL_BUSY,
5913adbf342SMartin Blumenstingl MESON_SAR_ADC_DELAY_KERNEL_BUSY);
5923adbf342SMartin Blumenstingl
59379b584edSAndy Shevchenko udelay(1);
59479b584edSAndy Shevchenko
5956c76ed31SMartin Blumenstingl /*
5966c76ed31SMartin Blumenstingl * wait until BL30 releases it's lock (so we can use the SAR
5976c76ed31SMartin Blumenstingl * ADC)
5986c76ed31SMartin Blumenstingl */
59979b584edSAndy Shevchenko ret = regmap_read_poll_timeout_atomic(priv->regmap, MESON_SAR_ADC_DELAY, val,
60079b584edSAndy Shevchenko !(val & MESON_SAR_ADC_DELAY_BL30_BUSY),
60179b584edSAndy Shevchenko 1, 10000);
60279b584edSAndy Shevchenko if (ret) {
603d0c09264SNuno Sá mutex_unlock(&priv->lock);
60479b584edSAndy Shevchenko return ret;
6056c76ed31SMartin Blumenstingl }
6063c3e4b3aSDan Carpenter }
6073adbf342SMartin Blumenstingl
6083adbf342SMartin Blumenstingl return 0;
6093adbf342SMartin Blumenstingl }
6103adbf342SMartin Blumenstingl
meson_sar_adc_unlock(struct iio_dev * indio_dev)6113adbf342SMartin Blumenstingl static void meson_sar_adc_unlock(struct iio_dev *indio_dev)
6123adbf342SMartin Blumenstingl {
6133adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
6143adbf342SMartin Blumenstingl
615057e5a11SMartin Blumenstingl if (priv->param->has_bl30_integration)
6163adbf342SMartin Blumenstingl /* allow BL30 to use the SAR ADC again */
6173adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY,
6183adbf342SMartin Blumenstingl MESON_SAR_ADC_DELAY_KERNEL_BUSY, 0);
6193adbf342SMartin Blumenstingl
620d0c09264SNuno Sá mutex_unlock(&priv->lock);
6213adbf342SMartin Blumenstingl }
6223adbf342SMartin Blumenstingl
meson_sar_adc_clear_fifo(struct iio_dev * indio_dev)6233adbf342SMartin Blumenstingl static void meson_sar_adc_clear_fifo(struct iio_dev *indio_dev)
6243adbf342SMartin Blumenstingl {
6253adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
626103a07d4SMartin Blumenstingl unsigned int count, tmp;
6273adbf342SMartin Blumenstingl
6283adbf342SMartin Blumenstingl for (count = 0; count < MESON_SAR_ADC_MAX_FIFO_SIZE; count++) {
6293adbf342SMartin Blumenstingl if (!meson_sar_adc_get_fifo_count(indio_dev))
6303adbf342SMartin Blumenstingl break;
6313adbf342SMartin Blumenstingl
632103a07d4SMartin Blumenstingl regmap_read(priv->regmap, MESON_SAR_ADC_FIFO_RD, &tmp);
6333adbf342SMartin Blumenstingl }
6343adbf342SMartin Blumenstingl }
6353adbf342SMartin Blumenstingl
meson_sar_adc_get_sample(struct iio_dev * indio_dev,const struct iio_chan_spec * chan,enum meson_sar_adc_avg_mode avg_mode,enum meson_sar_adc_num_samples avg_samples,int * val)6363adbf342SMartin Blumenstingl static int meson_sar_adc_get_sample(struct iio_dev *indio_dev,
6373adbf342SMartin Blumenstingl const struct iio_chan_spec *chan,
6383adbf342SMartin Blumenstingl enum meson_sar_adc_avg_mode avg_mode,
6393adbf342SMartin Blumenstingl enum meson_sar_adc_num_samples avg_samples,
6403adbf342SMartin Blumenstingl int *val)
6413adbf342SMartin Blumenstingl {
642723a61e0SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
64322c26db4SAndy Shevchenko struct device *dev = indio_dev->dev.parent;
6443adbf342SMartin Blumenstingl int ret;
6453adbf342SMartin Blumenstingl
646723a61e0SMartin Blumenstingl if (chan->type == IIO_TEMP && !priv->temperature_sensor_calibrated)
647723a61e0SMartin Blumenstingl return -ENOTSUPP;
648723a61e0SMartin Blumenstingl
6493adbf342SMartin Blumenstingl ret = meson_sar_adc_lock(indio_dev);
6503adbf342SMartin Blumenstingl if (ret)
6513adbf342SMartin Blumenstingl return ret;
6523adbf342SMartin Blumenstingl
6533adbf342SMartin Blumenstingl /* clear the FIFO to make sure we're not reading old values */
6543adbf342SMartin Blumenstingl meson_sar_adc_clear_fifo(indio_dev);
6553adbf342SMartin Blumenstingl
6563adbf342SMartin Blumenstingl meson_sar_adc_set_averaging(indio_dev, chan, avg_mode, avg_samples);
6573adbf342SMartin Blumenstingl
6583adbf342SMartin Blumenstingl meson_sar_adc_enable_channel(indio_dev, chan);
6593adbf342SMartin Blumenstingl
6603adbf342SMartin Blumenstingl meson_sar_adc_start_sample_engine(indio_dev);
6613adbf342SMartin Blumenstingl ret = meson_sar_adc_read_raw_sample(indio_dev, chan, val);
6623adbf342SMartin Blumenstingl meson_sar_adc_stop_sample_engine(indio_dev);
6633adbf342SMartin Blumenstingl
6643adbf342SMartin Blumenstingl meson_sar_adc_unlock(indio_dev);
6653adbf342SMartin Blumenstingl
6663adbf342SMartin Blumenstingl if (ret) {
66722c26db4SAndy Shevchenko dev_warn(dev, "failed to read sample for channel %lu: %d\n",
668827df057SMartin Blumenstingl chan->address, ret);
6693adbf342SMartin Blumenstingl return ret;
6703adbf342SMartin Blumenstingl }
6713adbf342SMartin Blumenstingl
6723adbf342SMartin Blumenstingl return IIO_VAL_INT;
6733adbf342SMartin Blumenstingl }
6743adbf342SMartin Blumenstingl
meson_sar_adc_iio_info_read_raw(struct iio_dev * indio_dev,const struct iio_chan_spec * chan,int * val,int * val2,long mask)6753adbf342SMartin Blumenstingl static int meson_sar_adc_iio_info_read_raw(struct iio_dev *indio_dev,
6763adbf342SMartin Blumenstingl const struct iio_chan_spec *chan,
6773adbf342SMartin Blumenstingl int *val, int *val2, long mask)
6783adbf342SMartin Blumenstingl {
6793adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
68022c26db4SAndy Shevchenko struct device *dev = indio_dev->dev.parent;
6813adbf342SMartin Blumenstingl int ret;
6823adbf342SMartin Blumenstingl
6833adbf342SMartin Blumenstingl switch (mask) {
6843adbf342SMartin Blumenstingl case IIO_CHAN_INFO_RAW:
6853adbf342SMartin Blumenstingl return meson_sar_adc_get_sample(indio_dev, chan, NO_AVERAGING,
6863adbf342SMartin Blumenstingl ONE_SAMPLE, val);
6873adbf342SMartin Blumenstingl
6883adbf342SMartin Blumenstingl case IIO_CHAN_INFO_AVERAGE_RAW:
6893adbf342SMartin Blumenstingl return meson_sar_adc_get_sample(indio_dev, chan,
6903adbf342SMartin Blumenstingl MEAN_AVERAGING, EIGHT_SAMPLES,
6913adbf342SMartin Blumenstingl val);
6923adbf342SMartin Blumenstingl
6933adbf342SMartin Blumenstingl case IIO_CHAN_INFO_SCALE:
694723a61e0SMartin Blumenstingl if (chan->type == IIO_VOLTAGE) {
6953adbf342SMartin Blumenstingl ret = regulator_get_voltage(priv->vref);
6963adbf342SMartin Blumenstingl if (ret < 0) {
69722c26db4SAndy Shevchenko dev_err(dev, "failed to get vref voltage: %d\n", ret);
6983adbf342SMartin Blumenstingl return ret;
6993adbf342SMartin Blumenstingl }
7003adbf342SMartin Blumenstingl
7013adbf342SMartin Blumenstingl *val = ret / 1000;
702057e5a11SMartin Blumenstingl *val2 = priv->param->resolution;
7033adbf342SMartin Blumenstingl return IIO_VAL_FRACTIONAL_LOG2;
704723a61e0SMartin Blumenstingl } else if (chan->type == IIO_TEMP) {
705723a61e0SMartin Blumenstingl /* SoC specific multiplier and divider */
706723a61e0SMartin Blumenstingl *val = priv->param->temperature_multiplier;
707723a61e0SMartin Blumenstingl *val2 = priv->param->temperature_divider;
708723a61e0SMartin Blumenstingl
709723a61e0SMartin Blumenstingl /* celsius to millicelsius */
710723a61e0SMartin Blumenstingl *val *= 1000;
711723a61e0SMartin Blumenstingl
712723a61e0SMartin Blumenstingl return IIO_VAL_FRACTIONAL;
713723a61e0SMartin Blumenstingl } else {
714723a61e0SMartin Blumenstingl return -EINVAL;
715723a61e0SMartin Blumenstingl }
7163adbf342SMartin Blumenstingl
71748ba7c3cSHeiner Kallweit case IIO_CHAN_INFO_CALIBBIAS:
71848ba7c3cSHeiner Kallweit *val = priv->calibbias;
71948ba7c3cSHeiner Kallweit return IIO_VAL_INT;
72048ba7c3cSHeiner Kallweit
72148ba7c3cSHeiner Kallweit case IIO_CHAN_INFO_CALIBSCALE:
72248ba7c3cSHeiner Kallweit *val = priv->calibscale / MILLION;
72348ba7c3cSHeiner Kallweit *val2 = priv->calibscale % MILLION;
72448ba7c3cSHeiner Kallweit return IIO_VAL_INT_PLUS_MICRO;
72548ba7c3cSHeiner Kallweit
726723a61e0SMartin Blumenstingl case IIO_CHAN_INFO_OFFSET:
727723a61e0SMartin Blumenstingl *val = DIV_ROUND_CLOSEST(MESON_SAR_ADC_TEMP_OFFSET *
728723a61e0SMartin Blumenstingl priv->param->temperature_divider,
729723a61e0SMartin Blumenstingl priv->param->temperature_multiplier);
730723a61e0SMartin Blumenstingl *val -= priv->temperature_sensor_adc_val;
731723a61e0SMartin Blumenstingl return IIO_VAL_INT;
732723a61e0SMartin Blumenstingl
7333adbf342SMartin Blumenstingl default:
7343adbf342SMartin Blumenstingl return -EINVAL;
7353adbf342SMartin Blumenstingl }
7363adbf342SMartin Blumenstingl }
7373adbf342SMartin Blumenstingl
meson_sar_adc_clk_init(struct iio_dev * indio_dev,void __iomem * base)7383adbf342SMartin Blumenstingl static int meson_sar_adc_clk_init(struct iio_dev *indio_dev,
7393adbf342SMartin Blumenstingl void __iomem *base)
7403adbf342SMartin Blumenstingl {
7413adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
742ec25bb6eSAndy Shevchenko struct device *dev = indio_dev->dev.parent;
7433adbf342SMartin Blumenstingl struct clk_init_data init;
7443adbf342SMartin Blumenstingl const char *clk_parents[1];
7453adbf342SMartin Blumenstingl
746ec25bb6eSAndy Shevchenko init.name = devm_kasprintf(dev, GFP_KERNEL, "%s#adc_div", dev_name(dev));
747aad172b0SNicholas Mc Guire if (!init.name)
748aad172b0SNicholas Mc Guire return -ENOMEM;
749aad172b0SNicholas Mc Guire
7503adbf342SMartin Blumenstingl init.flags = 0;
7513adbf342SMartin Blumenstingl init.ops = &clk_divider_ops;
7523adbf342SMartin Blumenstingl clk_parents[0] = __clk_get_name(priv->clkin);
7533adbf342SMartin Blumenstingl init.parent_names = clk_parents;
7543adbf342SMartin Blumenstingl init.num_parents = 1;
7553adbf342SMartin Blumenstingl
7563adbf342SMartin Blumenstingl priv->clk_div.reg = base + MESON_SAR_ADC_REG3;
7573adbf342SMartin Blumenstingl priv->clk_div.shift = MESON_SAR_ADC_REG3_ADC_CLK_DIV_SHIFT;
7583adbf342SMartin Blumenstingl priv->clk_div.width = MESON_SAR_ADC_REG3_ADC_CLK_DIV_WIDTH;
7593adbf342SMartin Blumenstingl priv->clk_div.hw.init = &init;
7603adbf342SMartin Blumenstingl priv->clk_div.flags = 0;
7613adbf342SMartin Blumenstingl
762ec25bb6eSAndy Shevchenko priv->adc_div_clk = devm_clk_register(dev, &priv->clk_div.hw);
7633adbf342SMartin Blumenstingl if (WARN_ON(IS_ERR(priv->adc_div_clk)))
7643adbf342SMartin Blumenstingl return PTR_ERR(priv->adc_div_clk);
7653adbf342SMartin Blumenstingl
766ec25bb6eSAndy Shevchenko init.name = devm_kasprintf(dev, GFP_KERNEL, "%s#adc_en", dev_name(dev));
767aad172b0SNicholas Mc Guire if (!init.name)
768aad172b0SNicholas Mc Guire return -ENOMEM;
769aad172b0SNicholas Mc Guire
7703adbf342SMartin Blumenstingl init.flags = CLK_SET_RATE_PARENT;
7713adbf342SMartin Blumenstingl init.ops = &clk_gate_ops;
7723adbf342SMartin Blumenstingl clk_parents[0] = __clk_get_name(priv->adc_div_clk);
7733adbf342SMartin Blumenstingl init.parent_names = clk_parents;
7743adbf342SMartin Blumenstingl init.num_parents = 1;
7753adbf342SMartin Blumenstingl
7763adbf342SMartin Blumenstingl priv->clk_gate.reg = base + MESON_SAR_ADC_REG3;
7777a6b0420SMartin Blumenstingl priv->clk_gate.bit_idx = __ffs(MESON_SAR_ADC_REG3_CLK_EN);
7783adbf342SMartin Blumenstingl priv->clk_gate.hw.init = &init;
7793adbf342SMartin Blumenstingl
780ec25bb6eSAndy Shevchenko priv->adc_clk = devm_clk_register(dev, &priv->clk_gate.hw);
7813adbf342SMartin Blumenstingl if (WARN_ON(IS_ERR(priv->adc_clk)))
7823adbf342SMartin Blumenstingl return PTR_ERR(priv->adc_clk);
7833adbf342SMartin Blumenstingl
7843adbf342SMartin Blumenstingl return 0;
7853adbf342SMartin Blumenstingl }
7863adbf342SMartin Blumenstingl
meson_sar_adc_temp_sensor_init(struct iio_dev * indio_dev)787723a61e0SMartin Blumenstingl static int meson_sar_adc_temp_sensor_init(struct iio_dev *indio_dev)
788723a61e0SMartin Blumenstingl {
789723a61e0SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
790723a61e0SMartin Blumenstingl u8 *buf, trimming_bits, trimming_mask, upper_adc_val;
7912d27a021SAndy Shevchenko struct device *dev = indio_dev->dev.parent;
792723a61e0SMartin Blumenstingl struct nvmem_cell *temperature_calib;
793723a61e0SMartin Blumenstingl size_t read_len;
794723a61e0SMartin Blumenstingl int ret;
795723a61e0SMartin Blumenstingl
79622c26db4SAndy Shevchenko temperature_calib = devm_nvmem_cell_get(dev, "temperature_calib");
797723a61e0SMartin Blumenstingl if (IS_ERR(temperature_calib)) {
798723a61e0SMartin Blumenstingl ret = PTR_ERR(temperature_calib);
799723a61e0SMartin Blumenstingl
800723a61e0SMartin Blumenstingl /*
801723a61e0SMartin Blumenstingl * leave the temperature sensor disabled if no calibration data
802723a61e0SMartin Blumenstingl * was passed via nvmem-cells.
803723a61e0SMartin Blumenstingl */
804723a61e0SMartin Blumenstingl if (ret == -ENODEV)
805723a61e0SMartin Blumenstingl return 0;
806723a61e0SMartin Blumenstingl
8072d27a021SAndy Shevchenko return dev_err_probe(dev, ret, "failed to get temperature_calib cell\n");
808723a61e0SMartin Blumenstingl }
809723a61e0SMartin Blumenstingl
81022c26db4SAndy Shevchenko priv->tsc_regmap = syscon_regmap_lookup_by_phandle(dev->of_node, "amlogic,hhi-sysctrl");
8112d27a021SAndy Shevchenko if (IS_ERR(priv->tsc_regmap))
8122d27a021SAndy Shevchenko return dev_err_probe(dev, PTR_ERR(priv->tsc_regmap),
813b002bf5fSMartin Blumenstingl "failed to get amlogic,hhi-sysctrl regmap\n");
814b002bf5fSMartin Blumenstingl
815723a61e0SMartin Blumenstingl read_len = MESON_SAR_ADC_EFUSE_BYTES;
816723a61e0SMartin Blumenstingl buf = nvmem_cell_read(temperature_calib, &read_len);
8172d27a021SAndy Shevchenko if (IS_ERR(buf))
8182d27a021SAndy Shevchenko return dev_err_probe(dev, PTR_ERR(buf), "failed to read temperature_calib cell\n");
8192d27a021SAndy Shevchenko if (read_len != MESON_SAR_ADC_EFUSE_BYTES) {
820723a61e0SMartin Blumenstingl kfree(buf);
8212d27a021SAndy Shevchenko return dev_err_probe(dev, -EINVAL, "invalid read size of temperature_calib cell\n");
822723a61e0SMartin Blumenstingl }
823723a61e0SMartin Blumenstingl
824723a61e0SMartin Blumenstingl trimming_bits = priv->param->temperature_trimming_bits;
825723a61e0SMartin Blumenstingl trimming_mask = BIT(trimming_bits) - 1;
826723a61e0SMartin Blumenstingl
827723a61e0SMartin Blumenstingl priv->temperature_sensor_calibrated =
828723a61e0SMartin Blumenstingl buf[3] & MESON_SAR_ADC_EFUSE_BYTE3_IS_CALIBRATED;
829723a61e0SMartin Blumenstingl priv->temperature_sensor_coefficient = buf[2] & trimming_mask;
830723a61e0SMartin Blumenstingl
831723a61e0SMartin Blumenstingl upper_adc_val = FIELD_GET(MESON_SAR_ADC_EFUSE_BYTE3_UPPER_ADC_VAL,
832723a61e0SMartin Blumenstingl buf[3]);
833723a61e0SMartin Blumenstingl
834723a61e0SMartin Blumenstingl priv->temperature_sensor_adc_val = buf[2];
835723a61e0SMartin Blumenstingl priv->temperature_sensor_adc_val |= upper_adc_val << BITS_PER_BYTE;
836723a61e0SMartin Blumenstingl priv->temperature_sensor_adc_val >>= trimming_bits;
837723a61e0SMartin Blumenstingl
838723a61e0SMartin Blumenstingl kfree(buf);
839723a61e0SMartin Blumenstingl
840723a61e0SMartin Blumenstingl return 0;
841723a61e0SMartin Blumenstingl }
842723a61e0SMartin Blumenstingl
meson_sar_adc_init(struct iio_dev * indio_dev)8433adbf342SMartin Blumenstingl static int meson_sar_adc_init(struct iio_dev *indio_dev)
8443adbf342SMartin Blumenstingl {
8453adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
8462d27a021SAndy Shevchenko struct device *dev = indio_dev->dev.parent;
847ab569a4cSMartin Blumenstingl int regval, i, ret;
8483adbf342SMartin Blumenstingl
8493adbf342SMartin Blumenstingl /*
8503adbf342SMartin Blumenstingl * make sure we start at CH7 input since the other muxes are only used
8513adbf342SMartin Blumenstingl * for internal calibration.
8523adbf342SMartin Blumenstingl */
8533adbf342SMartin Blumenstingl meson_sar_adc_set_chan7_mux(indio_dev, CHAN7_MUX_CH7_INPUT);
8543adbf342SMartin Blumenstingl
855057e5a11SMartin Blumenstingl if (priv->param->has_bl30_integration) {
8563adbf342SMartin Blumenstingl /*
8576c76ed31SMartin Blumenstingl * leave sampling delay and the input clocks as configured by
8586c76ed31SMartin Blumenstingl * BL30 to make sure BL30 gets the values it expects when
8596c76ed31SMartin Blumenstingl * reading the temperature sensor.
8603adbf342SMartin Blumenstingl */
8613adbf342SMartin Blumenstingl regmap_read(priv->regmap, MESON_SAR_ADC_REG3, ®val);
8623adbf342SMartin Blumenstingl if (regval & MESON_SAR_ADC_REG3_BL30_INITIALIZED)
8633adbf342SMartin Blumenstingl return 0;
8646c76ed31SMartin Blumenstingl }
8653adbf342SMartin Blumenstingl
8663adbf342SMartin Blumenstingl meson_sar_adc_stop_sample_engine(indio_dev);
8673adbf342SMartin Blumenstingl
868723a61e0SMartin Blumenstingl /*
869723a61e0SMartin Blumenstingl * disable this bit as seems to be only relevant for Meson6 (based
870723a61e0SMartin Blumenstingl * on the vendor driver), which we don't support at the moment.
871723a61e0SMartin Blumenstingl */
8723adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
873723a61e0SMartin Blumenstingl MESON_SAR_ADC_REG0_ADC_TEMP_SEN_SEL, 0);
8743adbf342SMartin Blumenstingl
8753adbf342SMartin Blumenstingl /* disable all channels by default */
8763adbf342SMartin Blumenstingl regmap_write(priv->regmap, MESON_SAR_ADC_CHAN_LIST, 0x0);
8773adbf342SMartin Blumenstingl
8783adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3,
8793adbf342SMartin Blumenstingl MESON_SAR_ADC_REG3_CTRL_SAMPLING_CLOCK_PHASE, 0);
8803adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3,
8813adbf342SMartin Blumenstingl MESON_SAR_ADC_REG3_CNTL_USE_SC_DLY,
8823adbf342SMartin Blumenstingl MESON_SAR_ADC_REG3_CNTL_USE_SC_DLY);
8833adbf342SMartin Blumenstingl
8843adbf342SMartin Blumenstingl /* delay between two samples = (10+1) * 1uS */
8853adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY,
8863adbf342SMartin Blumenstingl MESON_SAR_ADC_DELAY_INPUT_DLY_CNT_MASK,
8873adbf342SMartin Blumenstingl FIELD_PREP(MESON_SAR_ADC_DELAY_SAMPLE_DLY_CNT_MASK,
8883adbf342SMartin Blumenstingl 10));
8893adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY,
8903adbf342SMartin Blumenstingl MESON_SAR_ADC_DELAY_SAMPLE_DLY_SEL_MASK,
8913adbf342SMartin Blumenstingl FIELD_PREP(MESON_SAR_ADC_DELAY_SAMPLE_DLY_SEL_MASK,
8923adbf342SMartin Blumenstingl 0));
8933adbf342SMartin Blumenstingl
8943adbf342SMartin Blumenstingl /* delay between two samples = (10+1) * 1uS */
8953adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY,
8963adbf342SMartin Blumenstingl MESON_SAR_ADC_DELAY_INPUT_DLY_CNT_MASK,
8973adbf342SMartin Blumenstingl FIELD_PREP(MESON_SAR_ADC_DELAY_INPUT_DLY_CNT_MASK,
8983adbf342SMartin Blumenstingl 10));
8993adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELAY,
9003adbf342SMartin Blumenstingl MESON_SAR_ADC_DELAY_INPUT_DLY_SEL_MASK,
9013adbf342SMartin Blumenstingl FIELD_PREP(MESON_SAR_ADC_DELAY_INPUT_DLY_SEL_MASK,
9023adbf342SMartin Blumenstingl 1));
9033adbf342SMartin Blumenstingl
904ab569a4cSMartin Blumenstingl /*
905ab569a4cSMartin Blumenstingl * set up the input channel muxes in MESON_SAR_ADC_CHAN_10_SW
906ab569a4cSMartin Blumenstingl * (0 = SAR_ADC_CH0, 1 = SAR_ADC_CH1)
907ab569a4cSMartin Blumenstingl */
908ab569a4cSMartin Blumenstingl regval = FIELD_PREP(MESON_SAR_ADC_CHAN_10_SW_CHAN0_MUX_SEL_MASK, 0);
909ab569a4cSMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_10_SW,
910ab569a4cSMartin Blumenstingl MESON_SAR_ADC_CHAN_10_SW_CHAN0_MUX_SEL_MASK,
911ab569a4cSMartin Blumenstingl regval);
912ab569a4cSMartin Blumenstingl regval = FIELD_PREP(MESON_SAR_ADC_CHAN_10_SW_CHAN1_MUX_SEL_MASK, 1);
913ab569a4cSMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_10_SW,
914ab569a4cSMartin Blumenstingl MESON_SAR_ADC_CHAN_10_SW_CHAN1_MUX_SEL_MASK,
915ab569a4cSMartin Blumenstingl regval);
916ab569a4cSMartin Blumenstingl
9176ad9f01cSGeorge Stark regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_10_SW,
9186ad9f01cSGeorge Stark MESON_SAR_ADC_CHAN_10_SW_CHAN0_XP_DRIVE_SW,
9196ad9f01cSGeorge Stark MESON_SAR_ADC_CHAN_10_SW_CHAN0_XP_DRIVE_SW);
9206ad9f01cSGeorge Stark
9216ad9f01cSGeorge Stark regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_10_SW,
9226ad9f01cSGeorge Stark MESON_SAR_ADC_CHAN_10_SW_CHAN0_YP_DRIVE_SW,
9236ad9f01cSGeorge Stark MESON_SAR_ADC_CHAN_10_SW_CHAN0_YP_DRIVE_SW);
9246ad9f01cSGeorge Stark
9256ad9f01cSGeorge Stark regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_10_SW,
9266ad9f01cSGeorge Stark MESON_SAR_ADC_CHAN_10_SW_CHAN1_XP_DRIVE_SW,
9276ad9f01cSGeorge Stark MESON_SAR_ADC_CHAN_10_SW_CHAN1_XP_DRIVE_SW);
9286ad9f01cSGeorge Stark
9296ad9f01cSGeorge Stark regmap_update_bits(priv->regmap, MESON_SAR_ADC_CHAN_10_SW,
9306ad9f01cSGeorge Stark MESON_SAR_ADC_CHAN_10_SW_CHAN1_YP_DRIVE_SW,
9316ad9f01cSGeorge Stark MESON_SAR_ADC_CHAN_10_SW_CHAN1_YP_DRIVE_SW);
9326ad9f01cSGeorge Stark
933ab569a4cSMartin Blumenstingl /*
934ab569a4cSMartin Blumenstingl * set up the input channel muxes in MESON_SAR_ADC_AUX_SW
935ab569a4cSMartin Blumenstingl * (2 = SAR_ADC_CH2, 3 = SAR_ADC_CH3, ...) and enable
936ab569a4cSMartin Blumenstingl * MESON_SAR_ADC_AUX_SW_YP_DRIVE_SW and
937ab569a4cSMartin Blumenstingl * MESON_SAR_ADC_AUX_SW_XP_DRIVE_SW like the vendor driver.
938ab569a4cSMartin Blumenstingl */
939ab569a4cSMartin Blumenstingl regval = 0;
940ab569a4cSMartin Blumenstingl for (i = 2; i <= 7; i++)
941ab569a4cSMartin Blumenstingl regval |= i << MESON_SAR_ADC_AUX_SW_MUX_SEL_CHAN_SHIFT(i);
942ab569a4cSMartin Blumenstingl regval |= MESON_SAR_ADC_AUX_SW_YP_DRIVE_SW;
943ab569a4cSMartin Blumenstingl regval |= MESON_SAR_ADC_AUX_SW_XP_DRIVE_SW;
944ab569a4cSMartin Blumenstingl regmap_write(priv->regmap, MESON_SAR_ADC_AUX_SW, regval);
945ab569a4cSMartin Blumenstingl
946723a61e0SMartin Blumenstingl if (priv->temperature_sensor_calibrated) {
947723a61e0SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELTA_10,
948723a61e0SMartin Blumenstingl MESON_SAR_ADC_DELTA_10_TS_REVE1,
949723a61e0SMartin Blumenstingl MESON_SAR_ADC_DELTA_10_TS_REVE1);
950723a61e0SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELTA_10,
951723a61e0SMartin Blumenstingl MESON_SAR_ADC_DELTA_10_TS_REVE0,
952723a61e0SMartin Blumenstingl MESON_SAR_ADC_DELTA_10_TS_REVE0);
953723a61e0SMartin Blumenstingl
954723a61e0SMartin Blumenstingl /*
955723a61e0SMartin Blumenstingl * set bits [3:0] of the TSC (temperature sensor coefficient)
956723a61e0SMartin Blumenstingl * to get the correct values when reading the temperature.
957723a61e0SMartin Blumenstingl */
958723a61e0SMartin Blumenstingl regval = FIELD_PREP(MESON_SAR_ADC_DELTA_10_TS_C_MASK,
959723a61e0SMartin Blumenstingl priv->temperature_sensor_coefficient);
960723a61e0SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELTA_10,
961723a61e0SMartin Blumenstingl MESON_SAR_ADC_DELTA_10_TS_C_MASK, regval);
962b002bf5fSMartin Blumenstingl
963b002bf5fSMartin Blumenstingl if (priv->param->temperature_trimming_bits == 5) {
964b002bf5fSMartin Blumenstingl if (priv->temperature_sensor_coefficient & BIT(4))
965b002bf5fSMartin Blumenstingl regval = MESON_HHI_DPLL_TOP_0_TSC_BIT4;
966b002bf5fSMartin Blumenstingl else
967b002bf5fSMartin Blumenstingl regval = 0;
968b002bf5fSMartin Blumenstingl
969b002bf5fSMartin Blumenstingl /*
970b002bf5fSMartin Blumenstingl * bit [4] (the 5th bit when starting to count at 1)
971b002bf5fSMartin Blumenstingl * of the TSC is located in the HHI register area.
972b002bf5fSMartin Blumenstingl */
973b002bf5fSMartin Blumenstingl regmap_update_bits(priv->tsc_regmap,
974b002bf5fSMartin Blumenstingl MESON_HHI_DPLL_TOP_0,
975b002bf5fSMartin Blumenstingl MESON_HHI_DPLL_TOP_0_TSC_BIT4,
976b002bf5fSMartin Blumenstingl regval);
977b002bf5fSMartin Blumenstingl }
978723a61e0SMartin Blumenstingl } else {
979723a61e0SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELTA_10,
980723a61e0SMartin Blumenstingl MESON_SAR_ADC_DELTA_10_TS_REVE1, 0);
981723a61e0SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_DELTA_10,
982723a61e0SMartin Blumenstingl MESON_SAR_ADC_DELTA_10_TS_REVE0, 0);
983723a61e0SMartin Blumenstingl }
984723a61e0SMartin Blumenstingl
985d1adcaf7SGeorge Stark regval = FIELD_PREP(MESON_SAR_ADC_REG3_CTRL_CONT_RING_COUNTER_EN,
986d1adcaf7SGeorge Stark priv->param->disable_ring_counter);
987d1adcaf7SGeorge Stark regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3,
988d1adcaf7SGeorge Stark MESON_SAR_ADC_REG3_CTRL_CONT_RING_COUNTER_EN,
989d1adcaf7SGeorge Stark regval);
990d1adcaf7SGeorge Stark
99190c62418SGeorge Stark if (priv->param->has_reg11) {
99290c62418SGeorge Stark regval = FIELD_PREP(MESON_SAR_ADC_REG11_EOC, priv->param->adc_eoc);
99390c62418SGeorge Stark regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG11,
99490c62418SGeorge Stark MESON_SAR_ADC_REG11_EOC, regval);
99590c62418SGeorge Stark
99690c62418SGeorge Stark if (priv->param->has_vref_select) {
99790c62418SGeorge Stark regval = FIELD_PREP(MESON_SAR_ADC_REG11_VREF_SEL,
99890c62418SGeorge Stark priv->param->vref_select);
99990c62418SGeorge Stark regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG11,
100090c62418SGeorge Stark MESON_SAR_ADC_REG11_VREF_SEL, regval);
100190c62418SGeorge Stark }
100290c62418SGeorge Stark
100390c62418SGeorge Stark regval = FIELD_PREP(MESON_SAR_ADC_REG11_VREF_VOLTAGE,
100490c62418SGeorge Stark priv->param->vref_volatge);
100590c62418SGeorge Stark regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG11,
100690c62418SGeorge Stark MESON_SAR_ADC_REG11_VREF_VOLTAGE, regval);
100790c62418SGeorge Stark
100890c62418SGeorge Stark regval = FIELD_PREP(MESON_SAR_ADC_REG11_CMV_SEL,
100990c62418SGeorge Stark priv->param->cmv_select);
101090c62418SGeorge Stark regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG11,
101190c62418SGeorge Stark MESON_SAR_ADC_REG11_CMV_SEL, regval);
101290c62418SGeorge Stark }
101390c62418SGeorge Stark
10143adbf342SMartin Blumenstingl ret = clk_set_parent(priv->adc_sel_clk, priv->clkin);
10152d27a021SAndy Shevchenko if (ret)
10162d27a021SAndy Shevchenko return dev_err_probe(dev, ret, "failed to set adc parent to clkin\n");
10173adbf342SMartin Blumenstingl
1018057e5a11SMartin Blumenstingl ret = clk_set_rate(priv->adc_clk, priv->param->clock_rate);
10192d27a021SAndy Shevchenko if (ret)
10202d27a021SAndy Shevchenko return dev_err_probe(dev, ret, "failed to set adc clock rate\n");
10213adbf342SMartin Blumenstingl
10223adbf342SMartin Blumenstingl return 0;
10233adbf342SMartin Blumenstingl }
10243adbf342SMartin Blumenstingl
meson_sar_adc_set_bandgap(struct iio_dev * indio_dev,bool on_off)1025d85eed9fSMartin Blumenstingl static void meson_sar_adc_set_bandgap(struct iio_dev *indio_dev, bool on_off)
1026d85eed9fSMartin Blumenstingl {
1027d85eed9fSMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
1028057e5a11SMartin Blumenstingl const struct meson_sar_adc_param *param = priv->param;
1029d85eed9fSMartin Blumenstingl u32 enable_mask;
1030d85eed9fSMartin Blumenstingl
1031053ffe3cSYixun Lan if (param->bandgap_reg == MESON_SAR_ADC_REG11)
1032d85eed9fSMartin Blumenstingl enable_mask = MESON_SAR_ADC_REG11_BANDGAP_EN;
1033d85eed9fSMartin Blumenstingl else
1034d85eed9fSMartin Blumenstingl enable_mask = MESON_SAR_ADC_DELTA_10_TS_VBG_EN;
1035d85eed9fSMartin Blumenstingl
1036053ffe3cSYixun Lan regmap_update_bits(priv->regmap, param->bandgap_reg, enable_mask,
1037d85eed9fSMartin Blumenstingl on_off ? enable_mask : 0);
1038d85eed9fSMartin Blumenstingl }
1039d85eed9fSMartin Blumenstingl
meson_sar_adc_hw_enable(struct iio_dev * indio_dev)10403adbf342SMartin Blumenstingl static int meson_sar_adc_hw_enable(struct iio_dev *indio_dev)
10413adbf342SMartin Blumenstingl {
10423adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
104322c26db4SAndy Shevchenko struct device *dev = indio_dev->dev.parent;
10443adbf342SMartin Blumenstingl int ret;
10453af10913SHeiner Kallweit u32 regval;
10463adbf342SMartin Blumenstingl
10473adbf342SMartin Blumenstingl ret = meson_sar_adc_lock(indio_dev);
1048d27425d5SGeorge Stark if (ret) {
1049d27425d5SGeorge Stark dev_err(dev, "failed to lock adc\n");
10503adbf342SMartin Blumenstingl goto err_lock;
1051d27425d5SGeorge Stark }
10523adbf342SMartin Blumenstingl
10533adbf342SMartin Blumenstingl ret = regulator_enable(priv->vref);
10543adbf342SMartin Blumenstingl if (ret < 0) {
105522c26db4SAndy Shevchenko dev_err(dev, "failed to enable vref regulator\n");
10563adbf342SMartin Blumenstingl goto err_vref;
10573adbf342SMartin Blumenstingl }
10583adbf342SMartin Blumenstingl
10593af10913SHeiner Kallweit regval = FIELD_PREP(MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, 1);
10603af10913SHeiner Kallweit regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG0,
10613af10913SHeiner Kallweit MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, regval);
1062d85eed9fSMartin Blumenstingl
1063d85eed9fSMartin Blumenstingl meson_sar_adc_set_bandgap(indio_dev, true);
1064d85eed9fSMartin Blumenstingl
10653adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3,
10663adbf342SMartin Blumenstingl MESON_SAR_ADC_REG3_ADC_EN,
10673adbf342SMartin Blumenstingl MESON_SAR_ADC_REG3_ADC_EN);
10683adbf342SMartin Blumenstingl
10693adbf342SMartin Blumenstingl udelay(5);
10703adbf342SMartin Blumenstingl
10713adbf342SMartin Blumenstingl ret = clk_prepare_enable(priv->adc_clk);
10723adbf342SMartin Blumenstingl if (ret) {
107322c26db4SAndy Shevchenko dev_err(dev, "failed to enable adc clk\n");
10743adbf342SMartin Blumenstingl goto err_adc_clk;
10753adbf342SMartin Blumenstingl }
10763adbf342SMartin Blumenstingl
10773adbf342SMartin Blumenstingl meson_sar_adc_unlock(indio_dev);
10783adbf342SMartin Blumenstingl
10793adbf342SMartin Blumenstingl return 0;
10803adbf342SMartin Blumenstingl
10813adbf342SMartin Blumenstingl err_adc_clk:
10823adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3,
10833adbf342SMartin Blumenstingl MESON_SAR_ADC_REG3_ADC_EN, 0);
1084d85eed9fSMartin Blumenstingl meson_sar_adc_set_bandgap(indio_dev, false);
10853adbf342SMartin Blumenstingl regulator_disable(priv->vref);
10863adbf342SMartin Blumenstingl err_vref:
10873adbf342SMartin Blumenstingl meson_sar_adc_unlock(indio_dev);
10883adbf342SMartin Blumenstingl err_lock:
10893adbf342SMartin Blumenstingl return ret;
10903adbf342SMartin Blumenstingl }
10913adbf342SMartin Blumenstingl
meson_sar_adc_hw_disable(struct iio_dev * indio_dev)10924ab8bef1SUwe Kleine-König static void meson_sar_adc_hw_disable(struct iio_dev *indio_dev)
10933adbf342SMartin Blumenstingl {
10943adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
10953adbf342SMartin Blumenstingl int ret;
10963adbf342SMartin Blumenstingl
10974ab8bef1SUwe Kleine-König /*
10984ab8bef1SUwe Kleine-König * If taking the lock fails we have to assume that BL30 is broken. The
10994ab8bef1SUwe Kleine-König * best we can do then is to release the resources anyhow.
11004ab8bef1SUwe Kleine-König */
11013adbf342SMartin Blumenstingl ret = meson_sar_adc_lock(indio_dev);
11023adbf342SMartin Blumenstingl if (ret)
11034ab8bef1SUwe Kleine-König dev_err(indio_dev->dev.parent, "Failed to lock ADC (%pE)\n", ERR_PTR(ret));
11043adbf342SMartin Blumenstingl
11053adbf342SMartin Blumenstingl clk_disable_unprepare(priv->adc_clk);
11063adbf342SMartin Blumenstingl
11073adbf342SMartin Blumenstingl regmap_update_bits(priv->regmap, MESON_SAR_ADC_REG3,
11083adbf342SMartin Blumenstingl MESON_SAR_ADC_REG3_ADC_EN, 0);
1109d85eed9fSMartin Blumenstingl
1110d85eed9fSMartin Blumenstingl meson_sar_adc_set_bandgap(indio_dev, false);
11113adbf342SMartin Blumenstingl
11123adbf342SMartin Blumenstingl regulator_disable(priv->vref);
11133adbf342SMartin Blumenstingl
11144ab8bef1SUwe Kleine-König if (!ret)
11153adbf342SMartin Blumenstingl meson_sar_adc_unlock(indio_dev);
11163adbf342SMartin Blumenstingl }
11173adbf342SMartin Blumenstingl
meson_sar_adc_irq(int irq,void * data)11183af10913SHeiner Kallweit static irqreturn_t meson_sar_adc_irq(int irq, void *data)
11193af10913SHeiner Kallweit {
11203af10913SHeiner Kallweit struct iio_dev *indio_dev = data;
11213af10913SHeiner Kallweit struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
11223af10913SHeiner Kallweit unsigned int cnt, threshold;
11233af10913SHeiner Kallweit u32 regval;
11243af10913SHeiner Kallweit
11253af10913SHeiner Kallweit regmap_read(priv->regmap, MESON_SAR_ADC_REG0, ®val);
11263af10913SHeiner Kallweit cnt = FIELD_GET(MESON_SAR_ADC_REG0_FIFO_COUNT_MASK, regval);
11273af10913SHeiner Kallweit threshold = FIELD_GET(MESON_SAR_ADC_REG0_FIFO_CNT_IRQ_MASK, regval);
11283af10913SHeiner Kallweit
11293af10913SHeiner Kallweit if (cnt < threshold)
11303af10913SHeiner Kallweit return IRQ_NONE;
11313af10913SHeiner Kallweit
11323af10913SHeiner Kallweit complete(&priv->done);
11333af10913SHeiner Kallweit
11343af10913SHeiner Kallweit return IRQ_HANDLED;
11353af10913SHeiner Kallweit }
11363af10913SHeiner Kallweit
meson_sar_adc_calib(struct iio_dev * indio_dev)113748ba7c3cSHeiner Kallweit static int meson_sar_adc_calib(struct iio_dev *indio_dev)
113848ba7c3cSHeiner Kallweit {
113948ba7c3cSHeiner Kallweit struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
114048ba7c3cSHeiner Kallweit int ret, nominal0, nominal1, value0, value1;
114148ba7c3cSHeiner Kallweit
114248ba7c3cSHeiner Kallweit /* use points 25% and 75% for calibration */
1143057e5a11SMartin Blumenstingl nominal0 = (1 << priv->param->resolution) / 4;
1144057e5a11SMartin Blumenstingl nominal1 = (1 << priv->param->resolution) * 3 / 4;
114548ba7c3cSHeiner Kallweit
114648ba7c3cSHeiner Kallweit meson_sar_adc_set_chan7_mux(indio_dev, CHAN7_MUX_VDD_DIV4);
114748ba7c3cSHeiner Kallweit usleep_range(10, 20);
114848ba7c3cSHeiner Kallweit ret = meson_sar_adc_get_sample(indio_dev,
11493a06b284SGeorge Stark find_channel_by_num(indio_dev,
11503a06b284SGeorge Stark NUM_MUX_1_VDD_DIV4),
115148ba7c3cSHeiner Kallweit MEAN_AVERAGING, EIGHT_SAMPLES, &value0);
115248ba7c3cSHeiner Kallweit if (ret < 0)
115348ba7c3cSHeiner Kallweit goto out;
115448ba7c3cSHeiner Kallweit
115548ba7c3cSHeiner Kallweit meson_sar_adc_set_chan7_mux(indio_dev, CHAN7_MUX_VDD_MUL3_DIV4);
115648ba7c3cSHeiner Kallweit usleep_range(10, 20);
115748ba7c3cSHeiner Kallweit ret = meson_sar_adc_get_sample(indio_dev,
11583a06b284SGeorge Stark find_channel_by_num(indio_dev,
11593a06b284SGeorge Stark NUM_MUX_3_VDD_MUL3_DIV4),
116048ba7c3cSHeiner Kallweit MEAN_AVERAGING, EIGHT_SAMPLES, &value1);
116148ba7c3cSHeiner Kallweit if (ret < 0)
116248ba7c3cSHeiner Kallweit goto out;
116348ba7c3cSHeiner Kallweit
116448ba7c3cSHeiner Kallweit if (value1 <= value0) {
116548ba7c3cSHeiner Kallweit ret = -EINVAL;
116648ba7c3cSHeiner Kallweit goto out;
116748ba7c3cSHeiner Kallweit }
116848ba7c3cSHeiner Kallweit
116948ba7c3cSHeiner Kallweit priv->calibscale = div_s64((nominal1 - nominal0) * (s64)MILLION,
117048ba7c3cSHeiner Kallweit value1 - value0);
117148ba7c3cSHeiner Kallweit priv->calibbias = nominal0 - div_s64((s64)value0 * priv->calibscale,
117248ba7c3cSHeiner Kallweit MILLION);
117348ba7c3cSHeiner Kallweit ret = 0;
117448ba7c3cSHeiner Kallweit out:
117548ba7c3cSHeiner Kallweit meson_sar_adc_set_chan7_mux(indio_dev, CHAN7_MUX_CH7_INPUT);
117648ba7c3cSHeiner Kallweit
117748ba7c3cSHeiner Kallweit return ret;
117848ba7c3cSHeiner Kallweit }
117948ba7c3cSHeiner Kallweit
read_label(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,char * label)1180b593ce5dSGeorge Stark static int read_label(struct iio_dev *indio_dev,
1181b593ce5dSGeorge Stark struct iio_chan_spec const *chan,
1182b593ce5dSGeorge Stark char *label)
1183b593ce5dSGeorge Stark {
1184b593ce5dSGeorge Stark if (chan->type == IIO_TEMP)
1185b593ce5dSGeorge Stark return sprintf(label, "temp-sensor\n");
11863a06b284SGeorge Stark if (chan->type == IIO_VOLTAGE && chan->channel >= NUM_MUX_0_VSS)
11873a06b284SGeorge Stark return sprintf(label, "%s\n",
11883a06b284SGeorge Stark chan7_mux_names[chan->channel - NUM_MUX_0_VSS]);
1189b593ce5dSGeorge Stark if (chan->type == IIO_VOLTAGE)
1190b593ce5dSGeorge Stark return sprintf(label, "channel-%d\n", chan->channel);
1191b593ce5dSGeorge Stark return 0;
1192b593ce5dSGeorge Stark }
1193b593ce5dSGeorge Stark
11943adbf342SMartin Blumenstingl static const struct iio_info meson_sar_adc_iio_info = {
11953adbf342SMartin Blumenstingl .read_raw = meson_sar_adc_iio_info_read_raw,
1196b593ce5dSGeorge Stark .read_label = read_label,
11973adbf342SMartin Blumenstingl };
11983adbf342SMartin Blumenstingl
1199053ffe3cSYixun Lan static const struct meson_sar_adc_param meson_sar_adc_meson8_param = {
12006c76ed31SMartin Blumenstingl .has_bl30_integration = false,
1201fda29dbaSMartin Blumenstingl .clock_rate = 1150000,
1202d85eed9fSMartin Blumenstingl .bandgap_reg = MESON_SAR_ADC_DELTA_10,
120396748823SMartin Blumenstingl .regmap_config = &meson_sar_adc_regmap_config_meson8,
12046c76ed31SMartin Blumenstingl .resolution = 10,
1205723a61e0SMartin Blumenstingl .temperature_trimming_bits = 4,
1206723a61e0SMartin Blumenstingl .temperature_multiplier = 18 * 10000,
1207723a61e0SMartin Blumenstingl .temperature_divider = 1024 * 10 * 85,
1208723a61e0SMartin Blumenstingl };
1209723a61e0SMartin Blumenstingl
1210723a61e0SMartin Blumenstingl static const struct meson_sar_adc_param meson_sar_adc_meson8b_param = {
1211723a61e0SMartin Blumenstingl .has_bl30_integration = false,
1212723a61e0SMartin Blumenstingl .clock_rate = 1150000,
1213723a61e0SMartin Blumenstingl .bandgap_reg = MESON_SAR_ADC_DELTA_10,
1214723a61e0SMartin Blumenstingl .regmap_config = &meson_sar_adc_regmap_config_meson8,
1215723a61e0SMartin Blumenstingl .resolution = 10,
1216b002bf5fSMartin Blumenstingl .temperature_trimming_bits = 5,
1217b002bf5fSMartin Blumenstingl .temperature_multiplier = 10,
1218b002bf5fSMartin Blumenstingl .temperature_divider = 32,
1219053ffe3cSYixun Lan };
1220053ffe3cSYixun Lan
1221053ffe3cSYixun Lan static const struct meson_sar_adc_param meson_sar_adc_gxbb_param = {
1222053ffe3cSYixun Lan .has_bl30_integration = true,
1223053ffe3cSYixun Lan .clock_rate = 1200000,
1224053ffe3cSYixun Lan .bandgap_reg = MESON_SAR_ADC_REG11,
1225053ffe3cSYixun Lan .regmap_config = &meson_sar_adc_regmap_config_gxbb,
1226053ffe3cSYixun Lan .resolution = 10,
122790c62418SGeorge Stark .has_reg11 = true,
122890c62418SGeorge Stark .vref_volatge = 1,
122990c62418SGeorge Stark .cmv_select = 1,
1230053ffe3cSYixun Lan };
1231053ffe3cSYixun Lan
1232053ffe3cSYixun Lan static const struct meson_sar_adc_param meson_sar_adc_gxl_param = {
1233053ffe3cSYixun Lan .has_bl30_integration = true,
1234053ffe3cSYixun Lan .clock_rate = 1200000,
1235053ffe3cSYixun Lan .bandgap_reg = MESON_SAR_ADC_REG11,
1236053ffe3cSYixun Lan .regmap_config = &meson_sar_adc_regmap_config_gxbb,
1237053ffe3cSYixun Lan .resolution = 12,
1238d1adcaf7SGeorge Stark .disable_ring_counter = 1,
123990c62418SGeorge Stark .has_reg11 = true,
124090c62418SGeorge Stark .vref_volatge = 1,
124190c62418SGeorge Stark .cmv_select = 1,
1242053ffe3cSYixun Lan };
1243053ffe3cSYixun Lan
1244*59b75dcbSGeorge Stark static const struct meson_sar_adc_param meson_sar_adc_axg_param = {
1245*59b75dcbSGeorge Stark .has_bl30_integration = true,
1246*59b75dcbSGeorge Stark .clock_rate = 1200000,
1247*59b75dcbSGeorge Stark .bandgap_reg = MESON_SAR_ADC_REG11,
1248*59b75dcbSGeorge Stark .regmap_config = &meson_sar_adc_regmap_config_gxbb,
1249*59b75dcbSGeorge Stark .resolution = 12,
1250*59b75dcbSGeorge Stark .disable_ring_counter = 1,
1251*59b75dcbSGeorge Stark .has_reg11 = true,
1252*59b75dcbSGeorge Stark .vref_volatge = 1,
1253*59b75dcbSGeorge Stark .has_vref_select = true,
1254*59b75dcbSGeorge Stark .vref_select = VREF_VDDA,
1255*59b75dcbSGeorge Stark .cmv_select = 1,
1256*59b75dcbSGeorge Stark };
1257*59b75dcbSGeorge Stark
125848dc1abdSMartin Blumenstingl static const struct meson_sar_adc_param meson_sar_adc_g12a_param = {
125948dc1abdSMartin Blumenstingl .has_bl30_integration = false,
126048dc1abdSMartin Blumenstingl .clock_rate = 1200000,
126148dc1abdSMartin Blumenstingl .bandgap_reg = MESON_SAR_ADC_REG11,
126248dc1abdSMartin Blumenstingl .regmap_config = &meson_sar_adc_regmap_config_gxbb,
126348dc1abdSMartin Blumenstingl .resolution = 12,
1264d1adcaf7SGeorge Stark .disable_ring_counter = 1,
126590c62418SGeorge Stark .has_reg11 = true,
126690c62418SGeorge Stark .adc_eoc = 1,
126790c62418SGeorge Stark .has_vref_select = true,
126890c62418SGeorge Stark .vref_select = VREF_VDDA,
126948dc1abdSMartin Blumenstingl };
127048dc1abdSMartin Blumenstingl
1271053ffe3cSYixun Lan static const struct meson_sar_adc_data meson_sar_adc_meson8_data = {
1272053ffe3cSYixun Lan .param = &meson_sar_adc_meson8_param,
12736c76ed31SMartin Blumenstingl .name = "meson-meson8-saradc",
12746c76ed31SMartin Blumenstingl };
12756c76ed31SMartin Blumenstingl
12766c76ed31SMartin Blumenstingl static const struct meson_sar_adc_data meson_sar_adc_meson8b_data = {
1277723a61e0SMartin Blumenstingl .param = &meson_sar_adc_meson8b_param,
12786c76ed31SMartin Blumenstingl .name = "meson-meson8b-saradc",
12796c76ed31SMartin Blumenstingl };
12806c76ed31SMartin Blumenstingl
1281ffc0d638SMartin Blumenstingl static const struct meson_sar_adc_data meson_sar_adc_meson8m2_data = {
1282723a61e0SMartin Blumenstingl .param = &meson_sar_adc_meson8b_param,
1283ffc0d638SMartin Blumenstingl .name = "meson-meson8m2-saradc",
1284ffc0d638SMartin Blumenstingl };
1285ffc0d638SMartin Blumenstingl
1286c1c2de37SMartin Blumenstingl static const struct meson_sar_adc_data meson_sar_adc_gxbb_data = {
1287053ffe3cSYixun Lan .param = &meson_sar_adc_gxbb_param,
12883adbf342SMartin Blumenstingl .name = "meson-gxbb-saradc",
12893adbf342SMartin Blumenstingl };
12903adbf342SMartin Blumenstingl
1291c1c2de37SMartin Blumenstingl static const struct meson_sar_adc_data meson_sar_adc_gxl_data = {
1292053ffe3cSYixun Lan .param = &meson_sar_adc_gxl_param,
12933adbf342SMartin Blumenstingl .name = "meson-gxl-saradc",
12943adbf342SMartin Blumenstingl };
12953adbf342SMartin Blumenstingl
1296c1c2de37SMartin Blumenstingl static const struct meson_sar_adc_data meson_sar_adc_gxm_data = {
1297053ffe3cSYixun Lan .param = &meson_sar_adc_gxl_param,
12983adbf342SMartin Blumenstingl .name = "meson-gxm-saradc",
12993adbf342SMartin Blumenstingl };
13003adbf342SMartin Blumenstingl
1301ff632ddaSXingyu Chen static const struct meson_sar_adc_data meson_sar_adc_axg_data = {
1302*59b75dcbSGeorge Stark .param = &meson_sar_adc_axg_param,
1303ff632ddaSXingyu Chen .name = "meson-axg-saradc",
1304ff632ddaSXingyu Chen };
1305ff632ddaSXingyu Chen
1306e415a165SNeil Armstrong static const struct meson_sar_adc_data meson_sar_adc_g12a_data = {
130748dc1abdSMartin Blumenstingl .param = &meson_sar_adc_g12a_param,
1308e415a165SNeil Armstrong .name = "meson-g12a-saradc",
1309e415a165SNeil Armstrong };
1310e415a165SNeil Armstrong
13113adbf342SMartin Blumenstingl static const struct of_device_id meson_sar_adc_of_match[] = {
13123adbf342SMartin Blumenstingl {
13136c76ed31SMartin Blumenstingl .compatible = "amlogic,meson8-saradc",
13146c76ed31SMartin Blumenstingl .data = &meson_sar_adc_meson8_data,
131514b15f3fSMartin Blumenstingl }, {
13166c76ed31SMartin Blumenstingl .compatible = "amlogic,meson8b-saradc",
13176c76ed31SMartin Blumenstingl .data = &meson_sar_adc_meson8b_data,
131814b15f3fSMartin Blumenstingl }, {
1319ffc0d638SMartin Blumenstingl .compatible = "amlogic,meson8m2-saradc",
1320ffc0d638SMartin Blumenstingl .data = &meson_sar_adc_meson8m2_data,
132114b15f3fSMartin Blumenstingl }, {
13223adbf342SMartin Blumenstingl .compatible = "amlogic,meson-gxbb-saradc",
13233adbf342SMartin Blumenstingl .data = &meson_sar_adc_gxbb_data,
13243adbf342SMartin Blumenstingl }, {
13253adbf342SMartin Blumenstingl .compatible = "amlogic,meson-gxl-saradc",
13263adbf342SMartin Blumenstingl .data = &meson_sar_adc_gxl_data,
13273adbf342SMartin Blumenstingl }, {
13283adbf342SMartin Blumenstingl .compatible = "amlogic,meson-gxm-saradc",
13293adbf342SMartin Blumenstingl .data = &meson_sar_adc_gxm_data,
1330ff632ddaSXingyu Chen }, {
1331ff632ddaSXingyu Chen .compatible = "amlogic,meson-axg-saradc",
1332ff632ddaSXingyu Chen .data = &meson_sar_adc_axg_data,
1333e415a165SNeil Armstrong }, {
1334e415a165SNeil Armstrong .compatible = "amlogic,meson-g12a-saradc",
1335e415a165SNeil Armstrong .data = &meson_sar_adc_g12a_data,
13363adbf342SMartin Blumenstingl },
133714b15f3fSMartin Blumenstingl { /* sentinel */ }
13383adbf342SMartin Blumenstingl };
13393adbf342SMartin Blumenstingl MODULE_DEVICE_TABLE(of, meson_sar_adc_of_match);
13403adbf342SMartin Blumenstingl
meson_sar_adc_probe(struct platform_device * pdev)13413adbf342SMartin Blumenstingl static int meson_sar_adc_probe(struct platform_device *pdev)
13423adbf342SMartin Blumenstingl {
1343234c64a2SMartin Blumenstingl const struct meson_sar_adc_data *match_data;
13443adbf342SMartin Blumenstingl struct meson_sar_adc_priv *priv;
13452d27a021SAndy Shevchenko struct device *dev = &pdev->dev;
13463adbf342SMartin Blumenstingl struct iio_dev *indio_dev;
13473adbf342SMartin Blumenstingl void __iomem *base;
13483af10913SHeiner Kallweit int irq, ret;
13493adbf342SMartin Blumenstingl
135022c26db4SAndy Shevchenko indio_dev = devm_iio_device_alloc(dev, sizeof(*priv));
13512d27a021SAndy Shevchenko if (!indio_dev)
13522d27a021SAndy Shevchenko return dev_err_probe(dev, -ENOMEM, "failed allocating iio device\n");
13533adbf342SMartin Blumenstingl
13543adbf342SMartin Blumenstingl priv = iio_priv(indio_dev);
13553af10913SHeiner Kallweit init_completion(&priv->done);
13563adbf342SMartin Blumenstingl
135722c26db4SAndy Shevchenko match_data = of_device_get_match_data(dev);
13582d27a021SAndy Shevchenko if (!match_data)
13592d27a021SAndy Shevchenko return dev_err_probe(dev, -ENODEV, "failed to get match data\n");
13602f9aeeedSGustavo A. R. Silva
1361057e5a11SMartin Blumenstingl priv->param = match_data->param;
13623adbf342SMartin Blumenstingl
1363057e5a11SMartin Blumenstingl indio_dev->name = match_data->name;
13643adbf342SMartin Blumenstingl indio_dev->modes = INDIO_DIRECT_MODE;
13653adbf342SMartin Blumenstingl indio_dev->info = &meson_sar_adc_iio_info;
13663adbf342SMartin Blumenstingl
13675f401ef0SJonathan Cameron base = devm_platform_ioremap_resource(pdev, 0);
13683adbf342SMartin Blumenstingl if (IS_ERR(base))
13693adbf342SMartin Blumenstingl return PTR_ERR(base);
13703adbf342SMartin Blumenstingl
137122c26db4SAndy Shevchenko priv->regmap = devm_regmap_init_mmio(dev, base, priv->param->regmap_config);
1372de10ac47SRemi Pommarel if (IS_ERR(priv->regmap))
1373d27425d5SGeorge Stark return dev_err_probe(dev, PTR_ERR(priv->regmap), "failed to init regmap\n");
1374de10ac47SRemi Pommarel
137522c26db4SAndy Shevchenko irq = irq_of_parse_and_map(dev->of_node, 0);
13763af10913SHeiner Kallweit if (!irq)
1377d27425d5SGeorge Stark return dev_err_probe(dev, -EINVAL, "failed to get irq\n");
13783af10913SHeiner Kallweit
137922c26db4SAndy Shevchenko ret = devm_request_irq(dev, irq, meson_sar_adc_irq, IRQF_SHARED, dev_name(dev), indio_dev);
13803af10913SHeiner Kallweit if (ret)
1381d27425d5SGeorge Stark return dev_err_probe(dev, ret, "failed to request irq\n");
13823af10913SHeiner Kallweit
138322c26db4SAndy Shevchenko priv->clkin = devm_clk_get(dev, "clkin");
1384a5999024SCai Huoqing if (IS_ERR(priv->clkin))
138522c26db4SAndy Shevchenko return dev_err_probe(dev, PTR_ERR(priv->clkin), "failed to get clkin\n");
13863adbf342SMartin Blumenstingl
138709738ccbSGeorge Stark priv->core_clk = devm_clk_get_enabled(dev, "core");
1388a5999024SCai Huoqing if (IS_ERR(priv->core_clk))
138922c26db4SAndy Shevchenko return dev_err_probe(dev, PTR_ERR(priv->core_clk), "failed to get core clk\n");
13903adbf342SMartin Blumenstingl
13916531f3a4SAndy Shevchenko priv->adc_clk = devm_clk_get_optional(dev, "adc_clk");
13926531f3a4SAndy Shevchenko if (IS_ERR(priv->adc_clk))
13936531f3a4SAndy Shevchenko return dev_err_probe(dev, PTR_ERR(priv->adc_clk), "failed to get adc clk\n");
13943adbf342SMartin Blumenstingl
13956531f3a4SAndy Shevchenko priv->adc_sel_clk = devm_clk_get_optional(dev, "adc_sel");
13966531f3a4SAndy Shevchenko if (IS_ERR(priv->adc_sel_clk))
13976531f3a4SAndy Shevchenko return dev_err_probe(dev, PTR_ERR(priv->adc_sel_clk), "failed to get adc_sel clk\n");
13983adbf342SMartin Blumenstingl
13993adbf342SMartin Blumenstingl /* on pre-GXBB SoCs the SAR ADC itself provides the ADC clock: */
14003adbf342SMartin Blumenstingl if (!priv->adc_clk) {
14013adbf342SMartin Blumenstingl ret = meson_sar_adc_clk_init(indio_dev, base);
14023adbf342SMartin Blumenstingl if (ret)
1403d27425d5SGeorge Stark return dev_err_probe(dev, ret, "failed to init internal clk\n");
14043adbf342SMartin Blumenstingl }
14053adbf342SMartin Blumenstingl
140622c26db4SAndy Shevchenko priv->vref = devm_regulator_get(dev, "vref");
1407a5999024SCai Huoqing if (IS_ERR(priv->vref))
140822c26db4SAndy Shevchenko return dev_err_probe(dev, PTR_ERR(priv->vref), "failed to get vref regulator\n");
14093adbf342SMartin Blumenstingl
141048ba7c3cSHeiner Kallweit priv->calibscale = MILLION;
141148ba7c3cSHeiner Kallweit
1412723a61e0SMartin Blumenstingl if (priv->param->temperature_trimming_bits) {
1413723a61e0SMartin Blumenstingl ret = meson_sar_adc_temp_sensor_init(indio_dev);
1414723a61e0SMartin Blumenstingl if (ret)
1415723a61e0SMartin Blumenstingl return ret;
1416723a61e0SMartin Blumenstingl }
1417723a61e0SMartin Blumenstingl
1418723a61e0SMartin Blumenstingl if (priv->temperature_sensor_calibrated) {
1419723a61e0SMartin Blumenstingl indio_dev->channels = meson_sar_adc_and_temp_iio_channels;
1420723a61e0SMartin Blumenstingl indio_dev->num_channels =
1421723a61e0SMartin Blumenstingl ARRAY_SIZE(meson_sar_adc_and_temp_iio_channels);
1422723a61e0SMartin Blumenstingl } else {
1423723a61e0SMartin Blumenstingl indio_dev->channels = meson_sar_adc_iio_channels;
1424723a61e0SMartin Blumenstingl indio_dev->num_channels =
1425723a61e0SMartin Blumenstingl ARRAY_SIZE(meson_sar_adc_iio_channels);
1426723a61e0SMartin Blumenstingl }
1427723a61e0SMartin Blumenstingl
14283adbf342SMartin Blumenstingl ret = meson_sar_adc_init(indio_dev);
14293adbf342SMartin Blumenstingl if (ret)
14303adbf342SMartin Blumenstingl goto err;
14313adbf342SMartin Blumenstingl
1432d0c09264SNuno Sá mutex_init(&priv->lock);
1433d0c09264SNuno Sá
14343adbf342SMartin Blumenstingl ret = meson_sar_adc_hw_enable(indio_dev);
14353adbf342SMartin Blumenstingl if (ret)
14363adbf342SMartin Blumenstingl goto err;
14373adbf342SMartin Blumenstingl
143848ba7c3cSHeiner Kallweit ret = meson_sar_adc_calib(indio_dev);
143948ba7c3cSHeiner Kallweit if (ret)
144022c26db4SAndy Shevchenko dev_warn(dev, "calibration failed\n");
144148ba7c3cSHeiner Kallweit
14423adbf342SMartin Blumenstingl platform_set_drvdata(pdev, indio_dev);
14433adbf342SMartin Blumenstingl
14443adbf342SMartin Blumenstingl ret = iio_device_register(indio_dev);
1445d27425d5SGeorge Stark if (ret) {
1446d27425d5SGeorge Stark dev_err_probe(dev, ret, "failed to register iio device\n");
14473adbf342SMartin Blumenstingl goto err_hw;
1448d27425d5SGeorge Stark }
14493adbf342SMartin Blumenstingl
14503adbf342SMartin Blumenstingl return 0;
14513adbf342SMartin Blumenstingl
14523adbf342SMartin Blumenstingl err_hw:
14533adbf342SMartin Blumenstingl meson_sar_adc_hw_disable(indio_dev);
14543adbf342SMartin Blumenstingl err:
14553adbf342SMartin Blumenstingl return ret;
14563adbf342SMartin Blumenstingl }
14573adbf342SMartin Blumenstingl
meson_sar_adc_remove(struct platform_device * pdev)1458c0fe02aaSUwe Kleine-König static void meson_sar_adc_remove(struct platform_device *pdev)
14593adbf342SMartin Blumenstingl {
14603adbf342SMartin Blumenstingl struct iio_dev *indio_dev = platform_get_drvdata(pdev);
14613adbf342SMartin Blumenstingl
14623adbf342SMartin Blumenstingl iio_device_unregister(indio_dev);
14633adbf342SMartin Blumenstingl
14644ab8bef1SUwe Kleine-König meson_sar_adc_hw_disable(indio_dev);
14653adbf342SMartin Blumenstingl }
14663adbf342SMartin Blumenstingl
meson_sar_adc_suspend(struct device * dev)146750737998SJonathan Cameron static int meson_sar_adc_suspend(struct device *dev)
14683adbf342SMartin Blumenstingl {
14693adbf342SMartin Blumenstingl struct iio_dev *indio_dev = dev_get_drvdata(dev);
147009738ccbSGeorge Stark struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
14713adbf342SMartin Blumenstingl
14724ab8bef1SUwe Kleine-König meson_sar_adc_hw_disable(indio_dev);
14734ab8bef1SUwe Kleine-König
147409738ccbSGeorge Stark clk_disable_unprepare(priv->core_clk);
147509738ccbSGeorge Stark
14764ab8bef1SUwe Kleine-König return 0;
14773adbf342SMartin Blumenstingl }
14783adbf342SMartin Blumenstingl
meson_sar_adc_resume(struct device * dev)147950737998SJonathan Cameron static int meson_sar_adc_resume(struct device *dev)
14803adbf342SMartin Blumenstingl {
14813adbf342SMartin Blumenstingl struct iio_dev *indio_dev = dev_get_drvdata(dev);
148209738ccbSGeorge Stark struct meson_sar_adc_priv *priv = iio_priv(indio_dev);
148309738ccbSGeorge Stark int ret;
148409738ccbSGeorge Stark
148509738ccbSGeorge Stark ret = clk_prepare_enable(priv->core_clk);
148609738ccbSGeorge Stark if (ret) {
148709738ccbSGeorge Stark dev_err(dev, "failed to enable core clk\n");
148809738ccbSGeorge Stark return ret;
148909738ccbSGeorge Stark }
14903adbf342SMartin Blumenstingl
14913adbf342SMartin Blumenstingl return meson_sar_adc_hw_enable(indio_dev);
14923adbf342SMartin Blumenstingl }
14933adbf342SMartin Blumenstingl
149450737998SJonathan Cameron static DEFINE_SIMPLE_DEV_PM_OPS(meson_sar_adc_pm_ops,
14953adbf342SMartin Blumenstingl meson_sar_adc_suspend, meson_sar_adc_resume);
14963adbf342SMartin Blumenstingl
14973adbf342SMartin Blumenstingl static struct platform_driver meson_sar_adc_driver = {
14983adbf342SMartin Blumenstingl .probe = meson_sar_adc_probe,
1499c0fe02aaSUwe Kleine-König .remove_new = meson_sar_adc_remove,
15003adbf342SMartin Blumenstingl .driver = {
15013adbf342SMartin Blumenstingl .name = "meson-saradc",
15023adbf342SMartin Blumenstingl .of_match_table = meson_sar_adc_of_match,
150350737998SJonathan Cameron .pm = pm_sleep_ptr(&meson_sar_adc_pm_ops),
15043adbf342SMartin Blumenstingl },
15053adbf342SMartin Blumenstingl };
15063adbf342SMartin Blumenstingl
15073adbf342SMartin Blumenstingl module_platform_driver(meson_sar_adc_driver);
15083adbf342SMartin Blumenstingl
15093adbf342SMartin Blumenstingl MODULE_AUTHOR("Martin Blumenstingl <martin.blumenstingl@googlemail.com>");
15103adbf342SMartin Blumenstingl MODULE_DESCRIPTION("Amlogic Meson SAR ADC driver");
15113adbf342SMartin Blumenstingl MODULE_LICENSE("GPL v2");
1512