xref: /openbmc/linux/drivers/iio/adc/meson_saradc.c (revision 6ad9f01c)
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, &regval);
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, &regval);
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, &regval);
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, &regval);
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