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