xref: /linux/drivers/iio/adc/stm32-adc.c (revision da8431b4fd160ac9f13c8ca2bef04d89ff559a67)
16e93e261SBenjamin Gaignard // SPDX-License-Identifier: GPL-2.0
20f883b22SFabrice Gasnier /*
30f883b22SFabrice Gasnier  * This file is part of STM32 ADC driver
40f883b22SFabrice Gasnier  *
50f883b22SFabrice Gasnier  * Copyright (C) 2016, STMicroelectronics - All Rights Reserved
60f883b22SFabrice Gasnier  * Author: Fabrice Gasnier <fabrice.gasnier@st.com>.
70f883b22SFabrice Gasnier  */
80f883b22SFabrice Gasnier 
90f883b22SFabrice Gasnier #include <linux/clk.h>
1051bcacc6SOlivier Moysan #include <linux/debugfs.h>
110f883b22SFabrice Gasnier #include <linux/delay.h>
122763ea05SFabrice Gasnier #include <linux/dma-mapping.h>
132763ea05SFabrice Gasnier #include <linux/dmaengine.h>
140f883b22SFabrice Gasnier #include <linux/iio/iio.h>
15da9b9485SFabrice Gasnier #include <linux/iio/buffer.h>
16f0b638a7SFabrice Gasnier #include <linux/iio/timer/stm32-lptim-trigger.h>
17f24a33b3SFabrice Gasnier #include <linux/iio/timer/stm32-timer-trigger.h>
18da9b9485SFabrice Gasnier #include <linux/iio/trigger.h>
19da9b9485SFabrice Gasnier #include <linux/iio/trigger_consumer.h>
20da9b9485SFabrice Gasnier #include <linux/iio/triggered_buffer.h>
210f883b22SFabrice Gasnier #include <linux/interrupt.h>
220f883b22SFabrice Gasnier #include <linux/io.h>
2395e339b6SFabrice Gasnier #include <linux/iopoll.h>
240f883b22SFabrice Gasnier #include <linux/module.h>
25d7705f35SNuno Sá #include <linux/mod_devicetable.h>
260e346b2cSOlivier Moysan #include <linux/nvmem-consumer.h>
270f883b22SFabrice Gasnier #include <linux/platform_device.h>
289bdbb113SFabrice Gasnier #include <linux/pm_runtime.h>
29d7705f35SNuno Sá #include <linux/property.h>
300f883b22SFabrice Gasnier 
310f883b22SFabrice Gasnier #include "stm32-adc-core.h"
320f883b22SFabrice Gasnier 
3395e339b6SFabrice Gasnier /* Number of linear calibration shadow registers / LINCALRDYW control bits */
3495e339b6SFabrice Gasnier #define STM32H7_LINCALFACT_NUM		6
3595e339b6SFabrice Gasnier 
3695e339b6SFabrice Gasnier /* BOOST bit must be set on STM32H7 when ADC clock is above 20MHz */
3795e339b6SFabrice Gasnier #define STM32H7_BOOST_CLKRATE		20000000UL
3895e339b6SFabrice Gasnier 
390bae72aaSFabrice Gasnier #define STM32_ADC_CH_MAX		20	/* max number of channels */
4095bc8184SOlivier Moysan #define STM32_ADC_CH_SZ			16	/* max channel name size */
41da9b9485SFabrice Gasnier #define STM32_ADC_MAX_SQ		16	/* SQ1..SQ16 */
42ee2ac1cdSFabrice Gasnier #define STM32_ADC_MAX_SMP		7	/* SMPx range is [0..7] */
430f883b22SFabrice Gasnier #define STM32_ADC_TIMEOUT_US		100000
440f883b22SFabrice Gasnier #define STM32_ADC_TIMEOUT	(msecs_to_jiffies(STM32_ADC_TIMEOUT_US / 1000))
459bdbb113SFabrice Gasnier #define STM32_ADC_HW_STOP_DELAY_MS	100
460e346b2cSOlivier Moysan #define STM32_ADC_VREFINT_VOLTAGE	3300
470f883b22SFabrice Gasnier 
482763ea05SFabrice Gasnier #define STM32_DMA_BUFFER_SIZE		PAGE_SIZE
492763ea05SFabrice Gasnier 
50da9b9485SFabrice Gasnier /* External trigger enable */
51da9b9485SFabrice Gasnier enum stm32_adc_exten {
52da9b9485SFabrice Gasnier 	STM32_EXTEN_SWTRIG,
53da9b9485SFabrice Gasnier 	STM32_EXTEN_HWTRIG_RISING_EDGE,
54da9b9485SFabrice Gasnier 	STM32_EXTEN_HWTRIG_FALLING_EDGE,
55da9b9485SFabrice Gasnier 	STM32_EXTEN_HWTRIG_BOTH_EDGES,
56da9b9485SFabrice Gasnier };
57da9b9485SFabrice Gasnier 
58f24a33b3SFabrice Gasnier /* extsel - trigger mux selection value */
59f24a33b3SFabrice Gasnier enum stm32_adc_extsel {
60f24a33b3SFabrice Gasnier 	STM32_EXT0,
61f24a33b3SFabrice Gasnier 	STM32_EXT1,
62f24a33b3SFabrice Gasnier 	STM32_EXT2,
63f24a33b3SFabrice Gasnier 	STM32_EXT3,
64f24a33b3SFabrice Gasnier 	STM32_EXT4,
65f24a33b3SFabrice Gasnier 	STM32_EXT5,
66f24a33b3SFabrice Gasnier 	STM32_EXT6,
67f24a33b3SFabrice Gasnier 	STM32_EXT7,
68f24a33b3SFabrice Gasnier 	STM32_EXT8,
69f24a33b3SFabrice Gasnier 	STM32_EXT9,
70f24a33b3SFabrice Gasnier 	STM32_EXT10,
71f24a33b3SFabrice Gasnier 	STM32_EXT11,
72f24a33b3SFabrice Gasnier 	STM32_EXT12,
73f24a33b3SFabrice Gasnier 	STM32_EXT13,
74f24a33b3SFabrice Gasnier 	STM32_EXT14,
75f24a33b3SFabrice Gasnier 	STM32_EXT15,
76f0b638a7SFabrice Gasnier 	STM32_EXT16,
77f0b638a7SFabrice Gasnier 	STM32_EXT17,
78f0b638a7SFabrice Gasnier 	STM32_EXT18,
79f0b638a7SFabrice Gasnier 	STM32_EXT19,
80f0b638a7SFabrice Gasnier 	STM32_EXT20,
81f24a33b3SFabrice Gasnier };
82f24a33b3SFabrice Gasnier 
83aec6e0d8SOlivier Moysan enum stm32_adc_int_ch {
84aec6e0d8SOlivier Moysan 	STM32_ADC_INT_CH_NONE = -1,
85aec6e0d8SOlivier Moysan 	STM32_ADC_INT_CH_VDDCORE,
86cf0fb80aSOlivier Moysan 	STM32_ADC_INT_CH_VDDCPU,
87cf0fb80aSOlivier Moysan 	STM32_ADC_INT_CH_VDDQ_DDR,
88aec6e0d8SOlivier Moysan 	STM32_ADC_INT_CH_VREFINT,
89aec6e0d8SOlivier Moysan 	STM32_ADC_INT_CH_VBAT,
90aec6e0d8SOlivier Moysan 	STM32_ADC_INT_CH_NB,
91aec6e0d8SOlivier Moysan };
92aec6e0d8SOlivier Moysan 
93aec6e0d8SOlivier Moysan /**
94aec6e0d8SOlivier Moysan  * struct stm32_adc_ic - ADC internal channels
95aec6e0d8SOlivier Moysan  * @name:	name of the internal channel
96aec6e0d8SOlivier Moysan  * @idx:	internal channel enum index
97aec6e0d8SOlivier Moysan  */
98aec6e0d8SOlivier Moysan struct stm32_adc_ic {
99aec6e0d8SOlivier Moysan 	const char *name;
100aec6e0d8SOlivier Moysan 	u32 idx;
101aec6e0d8SOlivier Moysan };
102aec6e0d8SOlivier Moysan 
103aec6e0d8SOlivier Moysan static const struct stm32_adc_ic stm32_adc_ic[STM32_ADC_INT_CH_NB] = {
104aec6e0d8SOlivier Moysan 	{ "vddcore", STM32_ADC_INT_CH_VDDCORE },
105cf0fb80aSOlivier Moysan 	{ "vddcpu", STM32_ADC_INT_CH_VDDCPU },
106cf0fb80aSOlivier Moysan 	{ "vddq_ddr", STM32_ADC_INT_CH_VDDQ_DDR },
107aec6e0d8SOlivier Moysan 	{ "vrefint", STM32_ADC_INT_CH_VREFINT },
108aec6e0d8SOlivier Moysan 	{ "vbat", STM32_ADC_INT_CH_VBAT },
109aec6e0d8SOlivier Moysan };
110aec6e0d8SOlivier Moysan 
111f24a33b3SFabrice Gasnier /**
112f24a33b3SFabrice Gasnier  * struct stm32_adc_trig_info - ADC trigger info
113f24a33b3SFabrice Gasnier  * @name:		name of the trigger, corresponding to its source
114f24a33b3SFabrice Gasnier  * @extsel:		trigger selection
115f24a33b3SFabrice Gasnier  */
116f24a33b3SFabrice Gasnier struct stm32_adc_trig_info {
117f24a33b3SFabrice Gasnier 	const char *name;
118f24a33b3SFabrice Gasnier 	enum stm32_adc_extsel extsel;
119f24a33b3SFabrice Gasnier };
120f24a33b3SFabrice Gasnier 
121da9b9485SFabrice Gasnier /**
12295e339b6SFabrice Gasnier  * struct stm32_adc_calib - optional adc calibration data
12395e339b6SFabrice Gasnier  * @lincalfact: Linearity calibration factor
1249d901e35SOlivier Moysan  * @lincal_saved: Indicates that linear calibration factors are saved
12595e339b6SFabrice Gasnier  */
12695e339b6SFabrice Gasnier struct stm32_adc_calib {
12795e339b6SFabrice Gasnier 	u32			lincalfact[STM32H7_LINCALFACT_NUM];
1289d901e35SOlivier Moysan 	bool			lincal_saved;
12995e339b6SFabrice Gasnier };
13095e339b6SFabrice Gasnier 
13195e339b6SFabrice Gasnier /**
1321cd92d42SFabrice Gasnier  * struct stm32_adc_regs - stm32 ADC misc registers & bitfield desc
133da9b9485SFabrice Gasnier  * @reg:		register offset
134da9b9485SFabrice Gasnier  * @mask:		bitfield mask
135da9b9485SFabrice Gasnier  * @shift:		left shift
136da9b9485SFabrice Gasnier  */
137da9b9485SFabrice Gasnier struct stm32_adc_regs {
138da9b9485SFabrice Gasnier 	int reg;
139da9b9485SFabrice Gasnier 	int mask;
140da9b9485SFabrice Gasnier 	int shift;
141da9b9485SFabrice Gasnier };
142da9b9485SFabrice Gasnier 
1430f883b22SFabrice Gasnier /**
1440e346b2cSOlivier Moysan  * struct stm32_adc_vrefint - stm32 ADC internal reference voltage data
1450e346b2cSOlivier Moysan  * @vrefint_cal:	vrefint calibration value from nvmem
1460e346b2cSOlivier Moysan  * @vrefint_data:	vrefint actual value
1470e346b2cSOlivier Moysan  */
1480e346b2cSOlivier Moysan struct stm32_adc_vrefint {
1490e346b2cSOlivier Moysan 	u32 vrefint_cal;
1500e346b2cSOlivier Moysan 	u32 vrefint_data;
1510e346b2cSOlivier Moysan };
1520e346b2cSOlivier Moysan 
1530e346b2cSOlivier Moysan /**
1541cd92d42SFabrice Gasnier  * struct stm32_adc_regspec - stm32 registers definition
15564ad7f64SFabrice Gasnier  * @dr:			data register offset
15664ad7f64SFabrice Gasnier  * @ier_eoc:		interrupt enable register & eocie bitfield
157cc06e67dSFabrice Gasnier  * @ier_ovr:		interrupt enable register & overrun bitfield
15864ad7f64SFabrice Gasnier  * @isr_eoc:		interrupt status register & eoc bitfield
159cc06e67dSFabrice Gasnier  * @isr_ovr:		interrupt status register & overrun bitfield
16064ad7f64SFabrice Gasnier  * @sqr:		reference to sequence registers array
16164ad7f64SFabrice Gasnier  * @exten:		trigger control register & bitfield
16264ad7f64SFabrice Gasnier  * @extsel:		trigger selection register & bitfield
16364ad7f64SFabrice Gasnier  * @res:		resolution selection register & bitfield
164cf0fb80aSOlivier Moysan  * @difsel:		differential mode selection register & bitfield
165ee2ac1cdSFabrice Gasnier  * @smpr:		smpr1 & smpr2 registers offset array
166ee2ac1cdSFabrice Gasnier  * @smp_bits:		smpr1 & smpr2 index and bitfields
167cf0fb80aSOlivier Moysan  * @or_vddcore:		option register & vddcore bitfield
168cf0fb80aSOlivier Moysan  * @or_vddcpu:		option register & vddcpu bitfield
169cf0fb80aSOlivier Moysan  * @or_vddq_ddr:	option register & vddq_ddr bitfield
170aec6e0d8SOlivier Moysan  * @ccr_vbat:		common register & vbat bitfield
171aec6e0d8SOlivier Moysan  * @ccr_vref:		common register & vrefint bitfield
17264ad7f64SFabrice Gasnier  */
17364ad7f64SFabrice Gasnier struct stm32_adc_regspec {
17464ad7f64SFabrice Gasnier 	const u32 dr;
17564ad7f64SFabrice Gasnier 	const struct stm32_adc_regs ier_eoc;
176cc06e67dSFabrice Gasnier 	const struct stm32_adc_regs ier_ovr;
17764ad7f64SFabrice Gasnier 	const struct stm32_adc_regs isr_eoc;
178cc06e67dSFabrice Gasnier 	const struct stm32_adc_regs isr_ovr;
17964ad7f64SFabrice Gasnier 	const struct stm32_adc_regs *sqr;
18064ad7f64SFabrice Gasnier 	const struct stm32_adc_regs exten;
18164ad7f64SFabrice Gasnier 	const struct stm32_adc_regs extsel;
18264ad7f64SFabrice Gasnier 	const struct stm32_adc_regs res;
183cf0fb80aSOlivier Moysan 	const struct stm32_adc_regs difsel;
184ee2ac1cdSFabrice Gasnier 	const u32 smpr[2];
185ee2ac1cdSFabrice Gasnier 	const struct stm32_adc_regs *smp_bits;
186cf0fb80aSOlivier Moysan 	const struct stm32_adc_regs or_vddcore;
187cf0fb80aSOlivier Moysan 	const struct stm32_adc_regs or_vddcpu;
188cf0fb80aSOlivier Moysan 	const struct stm32_adc_regs or_vddq_ddr;
189aec6e0d8SOlivier Moysan 	const struct stm32_adc_regs ccr_vbat;
190aec6e0d8SOlivier Moysan 	const struct stm32_adc_regs ccr_vref;
19164ad7f64SFabrice Gasnier };
19264ad7f64SFabrice Gasnier 
19364ad7f64SFabrice Gasnier struct stm32_adc;
19464ad7f64SFabrice Gasnier 
19564ad7f64SFabrice Gasnier /**
1961cd92d42SFabrice Gasnier  * struct stm32_adc_cfg - stm32 compatible configuration data
19764ad7f64SFabrice Gasnier  * @regs:		registers descriptions
19864ad7f64SFabrice Gasnier  * @adc_info:		per instance input channels definitions
19964ad7f64SFabrice Gasnier  * @trigs:		external trigger sources
200204a6a25SFabrice Gasnier  * @clk_required:	clock is required
201d58c67d1SFabrice Gasnier  * @has_vregready:	vregready status flag presence
202cf0fb80aSOlivier Moysan  * @has_boostmode:	boost mode support flag
203cf0fb80aSOlivier Moysan  * @has_linearcal:	linear calibration support flag
204cf0fb80aSOlivier Moysan  * @has_presel:		channel preselection support flag
20595e339b6SFabrice Gasnier  * @prepare:		optional prepare routine (power-up, enable)
20664ad7f64SFabrice Gasnier  * @start_conv:		routine to start conversions
20764ad7f64SFabrice Gasnier  * @stop_conv:		routine to stop conversions
20895e339b6SFabrice Gasnier  * @unprepare:		optional unprepare routine (disable, power-down)
209695e2f5cSOlivier Moysan  * @irq_clear:		routine to clear irqs
210ee2ac1cdSFabrice Gasnier  * @smp_cycles:		programmable sampling time (ADC clock cycles)
2117cb2303dSOlivier Moysan  * @ts_int_ch:		pointer to array of internal channels minimum sampling time in ns
21264ad7f64SFabrice Gasnier  */
21364ad7f64SFabrice Gasnier struct stm32_adc_cfg {
21464ad7f64SFabrice Gasnier 	const struct stm32_adc_regspec	*regs;
21564ad7f64SFabrice Gasnier 	const struct stm32_adc_info	*adc_info;
21664ad7f64SFabrice Gasnier 	struct stm32_adc_trig_info	*trigs;
217204a6a25SFabrice Gasnier 	bool clk_required;
218d58c67d1SFabrice Gasnier 	bool has_vregready;
219cf0fb80aSOlivier Moysan 	bool has_boostmode;
220cf0fb80aSOlivier Moysan 	bool has_linearcal;
221cf0fb80aSOlivier Moysan 	bool has_presel;
222cd64d357SAlexandru Ardelean 	int (*prepare)(struct iio_dev *);
223cd64d357SAlexandru Ardelean 	void (*start_conv)(struct iio_dev *, bool dma);
224cd64d357SAlexandru Ardelean 	void (*stop_conv)(struct iio_dev *);
225cd64d357SAlexandru Ardelean 	void (*unprepare)(struct iio_dev *);
226695e2f5cSOlivier Moysan 	void (*irq_clear)(struct iio_dev *indio_dev, u32 msk);
227ee2ac1cdSFabrice Gasnier 	const unsigned int *smp_cycles;
2287cb2303dSOlivier Moysan 	const unsigned int *ts_int_ch;
22964ad7f64SFabrice Gasnier };
23064ad7f64SFabrice Gasnier 
23164ad7f64SFabrice Gasnier /**
2320f883b22SFabrice Gasnier  * struct stm32_adc - private data of each ADC IIO instance
2330f883b22SFabrice Gasnier  * @common:		reference to ADC block common data
2340f883b22SFabrice Gasnier  * @offset:		ADC instance register offset in ADC block
23564ad7f64SFabrice Gasnier  * @cfg:		compatible configuration data
2360f883b22SFabrice Gasnier  * @completion:		end of single conversion completion
2378a09054fSAhmad Fatoum  * @buffer:		data buffer + 8 bytes for timestamp if enabled
2380f883b22SFabrice Gasnier  * @clk:		clock for this adc instance
2390f883b22SFabrice Gasnier  * @irq:		interrupt for this adc instance
2400f883b22SFabrice Gasnier  * @lock:		spinlock
241da9b9485SFabrice Gasnier  * @bufi:		data buffer index
242da9b9485SFabrice Gasnier  * @num_conv:		expected number of scan conversions
24325a85bedSFabrice Gasnier  * @res:		data resolution (e.g. RES bitfield value)
244732f2dc4SFabrice Gasnier  * @trigger_polarity:	external trigger polarity (e.g. exten)
2452763ea05SFabrice Gasnier  * @dma_chan:		dma channel
2462763ea05SFabrice Gasnier  * @rx_buf:		dma rx buffer cpu address
2472763ea05SFabrice Gasnier  * @rx_dma_buf:		dma rx buffer bus address
2482763ea05SFabrice Gasnier  * @rx_buf_sz:		dma rx buffer size
2491cd92d42SFabrice Gasnier  * @difsel:		bitmask to set single-ended/differential channel
2501cd92d42SFabrice Gasnier  * @pcsel:		bitmask to preselect channels on some devices
251ee2ac1cdSFabrice Gasnier  * @smpr_val:		sampling time settings (e.g. smpr1 / smpr2)
25295e339b6SFabrice Gasnier  * @cal:		optional calibration data on some devices
2530e346b2cSOlivier Moysan  * @vrefint:		internal reference voltage data
2540bae72aaSFabrice Gasnier  * @chan_name:		channel name array
25545571a36SOlivier Moysan  * @num_diff:		number of differential channels
256aec6e0d8SOlivier Moysan  * @int_ch:		internal channel indexes array
257d7705f35SNuno Sá  * @nsmps:		number of channels with optional sample time
2580f883b22SFabrice Gasnier  */
2590f883b22SFabrice Gasnier struct stm32_adc {
2600f883b22SFabrice Gasnier 	struct stm32_adc_common	*common;
2610f883b22SFabrice Gasnier 	u32			offset;
26264ad7f64SFabrice Gasnier 	const struct stm32_adc_cfg	*cfg;
2630f883b22SFabrice Gasnier 	struct completion	completion;
2648a09054fSAhmad Fatoum 	u16			buffer[STM32_ADC_MAX_SQ + 4] __aligned(8);
2650f883b22SFabrice Gasnier 	struct clk		*clk;
2660f883b22SFabrice Gasnier 	int			irq;
2670f883b22SFabrice Gasnier 	spinlock_t		lock;		/* interrupt lock */
268da9b9485SFabrice Gasnier 	unsigned int		bufi;
269da9b9485SFabrice Gasnier 	unsigned int		num_conv;
27025a85bedSFabrice Gasnier 	u32			res;
271732f2dc4SFabrice Gasnier 	u32			trigger_polarity;
2722763ea05SFabrice Gasnier 	struct dma_chan		*dma_chan;
2732763ea05SFabrice Gasnier 	u8			*rx_buf;
2742763ea05SFabrice Gasnier 	dma_addr_t		rx_dma_buf;
2752763ea05SFabrice Gasnier 	unsigned int		rx_buf_sz;
2763fb2e24eSFabrice Gasnier 	u32			difsel;
27795e339b6SFabrice Gasnier 	u32			pcsel;
278ee2ac1cdSFabrice Gasnier 	u32			smpr_val[2];
27995e339b6SFabrice Gasnier 	struct stm32_adc_calib	cal;
2800e346b2cSOlivier Moysan 	struct stm32_adc_vrefint vrefint;
2810bae72aaSFabrice Gasnier 	char			chan_name[STM32_ADC_CH_MAX][STM32_ADC_CH_SZ];
28245571a36SOlivier Moysan 	u32			num_diff;
283aec6e0d8SOlivier Moysan 	int			int_ch[STM32_ADC_INT_CH_NB];
284d7705f35SNuno Sá 	int			nsmps;
2850f883b22SFabrice Gasnier };
2860f883b22SFabrice Gasnier 
2873fb2e24eSFabrice Gasnier struct stm32_adc_diff_channel {
2883fb2e24eSFabrice Gasnier 	u32 vinp;
2893fb2e24eSFabrice Gasnier 	u32 vinn;
2903fb2e24eSFabrice Gasnier };
2913fb2e24eSFabrice Gasnier 
29264ad7f64SFabrice Gasnier /**
29364ad7f64SFabrice Gasnier  * struct stm32_adc_info - stm32 ADC, per instance config data
29464ad7f64SFabrice Gasnier  * @max_channels:	Number of channels
29564ad7f64SFabrice Gasnier  * @resolutions:	available resolutions
29664ad7f64SFabrice Gasnier  * @num_res:		number of available resolutions
29764ad7f64SFabrice Gasnier  */
29864ad7f64SFabrice Gasnier struct stm32_adc_info {
29964ad7f64SFabrice Gasnier 	int max_channels;
30064ad7f64SFabrice Gasnier 	const unsigned int *resolutions;
30164ad7f64SFabrice Gasnier 	const unsigned int num_res;
30264ad7f64SFabrice Gasnier };
30364ad7f64SFabrice Gasnier 
30425a85bedSFabrice Gasnier static const unsigned int stm32f4_adc_resolutions[] = {
30525a85bedSFabrice Gasnier 	/* sorted values so the index matches RES[1:0] in STM32F4_ADC_CR1 */
30625a85bedSFabrice Gasnier 	12, 10, 8, 6,
30725a85bedSFabrice Gasnier };
30825a85bedSFabrice Gasnier 
3090bae72aaSFabrice Gasnier /* stm32f4 can have up to 16 channels */
31064ad7f64SFabrice Gasnier static const struct stm32_adc_info stm32f4_adc_info = {
31164ad7f64SFabrice Gasnier 	.max_channels = 16,
31264ad7f64SFabrice Gasnier 	.resolutions = stm32f4_adc_resolutions,
31364ad7f64SFabrice Gasnier 	.num_res = ARRAY_SIZE(stm32f4_adc_resolutions),
31464ad7f64SFabrice Gasnier };
31564ad7f64SFabrice Gasnier 
31695e339b6SFabrice Gasnier static const unsigned int stm32h7_adc_resolutions[] = {
31795e339b6SFabrice Gasnier 	/* sorted values so the index matches RES[2:0] in STM32H7_ADC_CFGR */
31895e339b6SFabrice Gasnier 	16, 14, 12, 10, 8,
31995e339b6SFabrice Gasnier };
32095e339b6SFabrice Gasnier 
3210bae72aaSFabrice Gasnier /* stm32h7 can have up to 20 channels */
32295e339b6SFabrice Gasnier static const struct stm32_adc_info stm32h7_adc_info = {
3230bae72aaSFabrice Gasnier 	.max_channels = STM32_ADC_CH_MAX,
32495e339b6SFabrice Gasnier 	.resolutions = stm32h7_adc_resolutions,
32595e339b6SFabrice Gasnier 	.num_res = ARRAY_SIZE(stm32h7_adc_resolutions),
32695e339b6SFabrice Gasnier };
32795e339b6SFabrice Gasnier 
328cf0fb80aSOlivier Moysan /* stm32mp13 can have up to 19 channels */
329cf0fb80aSOlivier Moysan static const struct stm32_adc_info stm32mp13_adc_info = {
330cf0fb80aSOlivier Moysan 	.max_channels = 19,
331cf0fb80aSOlivier Moysan 	.resolutions = stm32f4_adc_resolutions,
332cf0fb80aSOlivier Moysan 	.num_res = ARRAY_SIZE(stm32f4_adc_resolutions),
333cf0fb80aSOlivier Moysan };
334cf0fb80aSOlivier Moysan 
3351cd92d42SFabrice Gasnier /*
336da9b9485SFabrice Gasnier  * stm32f4_sq - describe regular sequence registers
337da9b9485SFabrice Gasnier  * - L: sequence len (register & bit field)
338da9b9485SFabrice Gasnier  * - SQ1..SQ16: sequence entries (register & bit field)
339da9b9485SFabrice Gasnier  */
340da9b9485SFabrice Gasnier static const struct stm32_adc_regs stm32f4_sq[STM32_ADC_MAX_SQ + 1] = {
341da9b9485SFabrice Gasnier 	/* L: len bit field description to be kept as first element */
342da9b9485SFabrice Gasnier 	{ STM32F4_ADC_SQR1, GENMASK(23, 20), 20 },
343da9b9485SFabrice Gasnier 	/* SQ1..SQ16 registers & bit fields (reg, mask, shift) */
344da9b9485SFabrice Gasnier 	{ STM32F4_ADC_SQR3, GENMASK(4, 0), 0 },
345da9b9485SFabrice Gasnier 	{ STM32F4_ADC_SQR3, GENMASK(9, 5), 5 },
346da9b9485SFabrice Gasnier 	{ STM32F4_ADC_SQR3, GENMASK(14, 10), 10 },
347da9b9485SFabrice Gasnier 	{ STM32F4_ADC_SQR3, GENMASK(19, 15), 15 },
348da9b9485SFabrice Gasnier 	{ STM32F4_ADC_SQR3, GENMASK(24, 20), 20 },
349da9b9485SFabrice Gasnier 	{ STM32F4_ADC_SQR3, GENMASK(29, 25), 25 },
350da9b9485SFabrice Gasnier 	{ STM32F4_ADC_SQR2, GENMASK(4, 0), 0 },
351da9b9485SFabrice Gasnier 	{ STM32F4_ADC_SQR2, GENMASK(9, 5), 5 },
352da9b9485SFabrice Gasnier 	{ STM32F4_ADC_SQR2, GENMASK(14, 10), 10 },
353da9b9485SFabrice Gasnier 	{ STM32F4_ADC_SQR2, GENMASK(19, 15), 15 },
354da9b9485SFabrice Gasnier 	{ STM32F4_ADC_SQR2, GENMASK(24, 20), 20 },
355da9b9485SFabrice Gasnier 	{ STM32F4_ADC_SQR2, GENMASK(29, 25), 25 },
356da9b9485SFabrice Gasnier 	{ STM32F4_ADC_SQR1, GENMASK(4, 0), 0 },
357da9b9485SFabrice Gasnier 	{ STM32F4_ADC_SQR1, GENMASK(9, 5), 5 },
358da9b9485SFabrice Gasnier 	{ STM32F4_ADC_SQR1, GENMASK(14, 10), 10 },
359da9b9485SFabrice Gasnier 	{ STM32F4_ADC_SQR1, GENMASK(19, 15), 15 },
360da9b9485SFabrice Gasnier };
361da9b9485SFabrice Gasnier 
362f24a33b3SFabrice Gasnier /* STM32F4 external trigger sources for all instances */
363f24a33b3SFabrice Gasnier static struct stm32_adc_trig_info stm32f4_adc_trigs[] = {
364f24a33b3SFabrice Gasnier 	{ TIM1_CH1, STM32_EXT0 },
365f24a33b3SFabrice Gasnier 	{ TIM1_CH2, STM32_EXT1 },
366f24a33b3SFabrice Gasnier 	{ TIM1_CH3, STM32_EXT2 },
367f24a33b3SFabrice Gasnier 	{ TIM2_CH2, STM32_EXT3 },
368f24a33b3SFabrice Gasnier 	{ TIM2_CH3, STM32_EXT4 },
369f24a33b3SFabrice Gasnier 	{ TIM2_CH4, STM32_EXT5 },
370f24a33b3SFabrice Gasnier 	{ TIM2_TRGO, STM32_EXT6 },
371f24a33b3SFabrice Gasnier 	{ TIM3_CH1, STM32_EXT7 },
372f24a33b3SFabrice Gasnier 	{ TIM3_TRGO, STM32_EXT8 },
373f24a33b3SFabrice Gasnier 	{ TIM4_CH4, STM32_EXT9 },
374f24a33b3SFabrice Gasnier 	{ TIM5_CH1, STM32_EXT10 },
375f24a33b3SFabrice Gasnier 	{ TIM5_CH2, STM32_EXT11 },
376f24a33b3SFabrice Gasnier 	{ TIM5_CH3, STM32_EXT12 },
377f24a33b3SFabrice Gasnier 	{ TIM8_CH1, STM32_EXT13 },
378f24a33b3SFabrice Gasnier 	{ TIM8_TRGO, STM32_EXT14 },
379f24a33b3SFabrice Gasnier 	{}, /* sentinel */
380f24a33b3SFabrice Gasnier };
381f24a33b3SFabrice Gasnier 
3821cd92d42SFabrice Gasnier /*
383ee2ac1cdSFabrice Gasnier  * stm32f4_smp_bits[] - describe sampling time register index & bit fields
384ee2ac1cdSFabrice Gasnier  * Sorted so it can be indexed by channel number.
385ee2ac1cdSFabrice Gasnier  */
386ee2ac1cdSFabrice Gasnier static const struct stm32_adc_regs stm32f4_smp_bits[] = {
387ee2ac1cdSFabrice Gasnier 	/* STM32F4_ADC_SMPR2: smpr[] index, mask, shift for SMP0 to SMP9 */
388ee2ac1cdSFabrice Gasnier 	{ 1, GENMASK(2, 0), 0 },
389ee2ac1cdSFabrice Gasnier 	{ 1, GENMASK(5, 3), 3 },
390ee2ac1cdSFabrice Gasnier 	{ 1, GENMASK(8, 6), 6 },
391ee2ac1cdSFabrice Gasnier 	{ 1, GENMASK(11, 9), 9 },
392ee2ac1cdSFabrice Gasnier 	{ 1, GENMASK(14, 12), 12 },
393ee2ac1cdSFabrice Gasnier 	{ 1, GENMASK(17, 15), 15 },
394ee2ac1cdSFabrice Gasnier 	{ 1, GENMASK(20, 18), 18 },
395ee2ac1cdSFabrice Gasnier 	{ 1, GENMASK(23, 21), 21 },
396ee2ac1cdSFabrice Gasnier 	{ 1, GENMASK(26, 24), 24 },
397ee2ac1cdSFabrice Gasnier 	{ 1, GENMASK(29, 27), 27 },
398ee2ac1cdSFabrice Gasnier 	/* STM32F4_ADC_SMPR1, smpr[] index, mask, shift for SMP10 to SMP18 */
399ee2ac1cdSFabrice Gasnier 	{ 0, GENMASK(2, 0), 0 },
400ee2ac1cdSFabrice Gasnier 	{ 0, GENMASK(5, 3), 3 },
401ee2ac1cdSFabrice Gasnier 	{ 0, GENMASK(8, 6), 6 },
402ee2ac1cdSFabrice Gasnier 	{ 0, GENMASK(11, 9), 9 },
403ee2ac1cdSFabrice Gasnier 	{ 0, GENMASK(14, 12), 12 },
404ee2ac1cdSFabrice Gasnier 	{ 0, GENMASK(17, 15), 15 },
405ee2ac1cdSFabrice Gasnier 	{ 0, GENMASK(20, 18), 18 },
406ee2ac1cdSFabrice Gasnier 	{ 0, GENMASK(23, 21), 21 },
407ee2ac1cdSFabrice Gasnier 	{ 0, GENMASK(26, 24), 24 },
408ee2ac1cdSFabrice Gasnier };
409ee2ac1cdSFabrice Gasnier 
410ee2ac1cdSFabrice Gasnier /* STM32F4 programmable sampling time (ADC clock cycles) */
411ee2ac1cdSFabrice Gasnier static const unsigned int stm32f4_adc_smp_cycles[STM32_ADC_MAX_SMP + 1] = {
412ee2ac1cdSFabrice Gasnier 	3, 15, 28, 56, 84, 112, 144, 480,
413ee2ac1cdSFabrice Gasnier };
414ee2ac1cdSFabrice Gasnier 
41564ad7f64SFabrice Gasnier static const struct stm32_adc_regspec stm32f4_adc_regspec = {
41664ad7f64SFabrice Gasnier 	.dr = STM32F4_ADC_DR,
41764ad7f64SFabrice Gasnier 	.ier_eoc = { STM32F4_ADC_CR1, STM32F4_EOCIE },
418cc06e67dSFabrice Gasnier 	.ier_ovr = { STM32F4_ADC_CR1, STM32F4_OVRIE },
41964ad7f64SFabrice Gasnier 	.isr_eoc = { STM32F4_ADC_SR, STM32F4_EOC },
420cc06e67dSFabrice Gasnier 	.isr_ovr = { STM32F4_ADC_SR, STM32F4_OVR },
42164ad7f64SFabrice Gasnier 	.sqr = stm32f4_sq,
42264ad7f64SFabrice Gasnier 	.exten = { STM32F4_ADC_CR2, STM32F4_EXTEN_MASK, STM32F4_EXTEN_SHIFT },
42364ad7f64SFabrice Gasnier 	.extsel = { STM32F4_ADC_CR2, STM32F4_EXTSEL_MASK,
42464ad7f64SFabrice Gasnier 		    STM32F4_EXTSEL_SHIFT },
42564ad7f64SFabrice Gasnier 	.res = { STM32F4_ADC_CR1, STM32F4_RES_MASK, STM32F4_RES_SHIFT },
426ee2ac1cdSFabrice Gasnier 	.smpr = { STM32F4_ADC_SMPR1, STM32F4_ADC_SMPR2 },
427ee2ac1cdSFabrice Gasnier 	.smp_bits = stm32f4_smp_bits,
42864ad7f64SFabrice Gasnier };
42964ad7f64SFabrice Gasnier 
43095e339b6SFabrice Gasnier static const struct stm32_adc_regs stm32h7_sq[STM32_ADC_MAX_SQ + 1] = {
43195e339b6SFabrice Gasnier 	/* L: len bit field description to be kept as first element */
43295e339b6SFabrice Gasnier 	{ STM32H7_ADC_SQR1, GENMASK(3, 0), 0 },
43395e339b6SFabrice Gasnier 	/* SQ1..SQ16 registers & bit fields (reg, mask, shift) */
43495e339b6SFabrice Gasnier 	{ STM32H7_ADC_SQR1, GENMASK(10, 6), 6 },
43595e339b6SFabrice Gasnier 	{ STM32H7_ADC_SQR1, GENMASK(16, 12), 12 },
43695e339b6SFabrice Gasnier 	{ STM32H7_ADC_SQR1, GENMASK(22, 18), 18 },
43795e339b6SFabrice Gasnier 	{ STM32H7_ADC_SQR1, GENMASK(28, 24), 24 },
43895e339b6SFabrice Gasnier 	{ STM32H7_ADC_SQR2, GENMASK(4, 0), 0 },
43995e339b6SFabrice Gasnier 	{ STM32H7_ADC_SQR2, GENMASK(10, 6), 6 },
44095e339b6SFabrice Gasnier 	{ STM32H7_ADC_SQR2, GENMASK(16, 12), 12 },
44195e339b6SFabrice Gasnier 	{ STM32H7_ADC_SQR2, GENMASK(22, 18), 18 },
44295e339b6SFabrice Gasnier 	{ STM32H7_ADC_SQR2, GENMASK(28, 24), 24 },
44395e339b6SFabrice Gasnier 	{ STM32H7_ADC_SQR3, GENMASK(4, 0), 0 },
44495e339b6SFabrice Gasnier 	{ STM32H7_ADC_SQR3, GENMASK(10, 6), 6 },
44595e339b6SFabrice Gasnier 	{ STM32H7_ADC_SQR3, GENMASK(16, 12), 12 },
44695e339b6SFabrice Gasnier 	{ STM32H7_ADC_SQR3, GENMASK(22, 18), 18 },
44795e339b6SFabrice Gasnier 	{ STM32H7_ADC_SQR3, GENMASK(28, 24), 24 },
44895e339b6SFabrice Gasnier 	{ STM32H7_ADC_SQR4, GENMASK(4, 0), 0 },
44995e339b6SFabrice Gasnier 	{ STM32H7_ADC_SQR4, GENMASK(10, 6), 6 },
45095e339b6SFabrice Gasnier };
45195e339b6SFabrice Gasnier 
45295e339b6SFabrice Gasnier /* STM32H7 external trigger sources for all instances */
45395e339b6SFabrice Gasnier static struct stm32_adc_trig_info stm32h7_adc_trigs[] = {
45495e339b6SFabrice Gasnier 	{ TIM1_CH1, STM32_EXT0 },
45595e339b6SFabrice Gasnier 	{ TIM1_CH2, STM32_EXT1 },
45695e339b6SFabrice Gasnier 	{ TIM1_CH3, STM32_EXT2 },
45795e339b6SFabrice Gasnier 	{ TIM2_CH2, STM32_EXT3 },
45895e339b6SFabrice Gasnier 	{ TIM3_TRGO, STM32_EXT4 },
45995e339b6SFabrice Gasnier 	{ TIM4_CH4, STM32_EXT5 },
46095e339b6SFabrice Gasnier 	{ TIM8_TRGO, STM32_EXT7 },
46195e339b6SFabrice Gasnier 	{ TIM8_TRGO2, STM32_EXT8 },
46295e339b6SFabrice Gasnier 	{ TIM1_TRGO, STM32_EXT9 },
46395e339b6SFabrice Gasnier 	{ TIM1_TRGO2, STM32_EXT10 },
46495e339b6SFabrice Gasnier 	{ TIM2_TRGO, STM32_EXT11 },
46595e339b6SFabrice Gasnier 	{ TIM4_TRGO, STM32_EXT12 },
46695e339b6SFabrice Gasnier 	{ TIM6_TRGO, STM32_EXT13 },
4673a069904SFabrice Gasnier 	{ TIM15_TRGO, STM32_EXT14 },
46895e339b6SFabrice Gasnier 	{ TIM3_CH4, STM32_EXT15 },
469f0b638a7SFabrice Gasnier 	{ LPTIM1_OUT, STM32_EXT18 },
470f0b638a7SFabrice Gasnier 	{ LPTIM2_OUT, STM32_EXT19 },
471f0b638a7SFabrice Gasnier 	{ LPTIM3_OUT, STM32_EXT20 },
47295e339b6SFabrice Gasnier 	{},
47395e339b6SFabrice Gasnier };
47495e339b6SFabrice Gasnier 
4751cd92d42SFabrice Gasnier /*
476ee2ac1cdSFabrice Gasnier  * stm32h7_smp_bits - describe sampling time register index & bit fields
477ee2ac1cdSFabrice Gasnier  * Sorted so it can be indexed by channel number.
478ee2ac1cdSFabrice Gasnier  */
479ee2ac1cdSFabrice Gasnier static const struct stm32_adc_regs stm32h7_smp_bits[] = {
480ee2ac1cdSFabrice Gasnier 	/* STM32H7_ADC_SMPR1, smpr[] index, mask, shift for SMP0 to SMP9 */
481ee2ac1cdSFabrice Gasnier 	{ 0, GENMASK(2, 0), 0 },
482ee2ac1cdSFabrice Gasnier 	{ 0, GENMASK(5, 3), 3 },
483ee2ac1cdSFabrice Gasnier 	{ 0, GENMASK(8, 6), 6 },
484ee2ac1cdSFabrice Gasnier 	{ 0, GENMASK(11, 9), 9 },
485ee2ac1cdSFabrice Gasnier 	{ 0, GENMASK(14, 12), 12 },
486ee2ac1cdSFabrice Gasnier 	{ 0, GENMASK(17, 15), 15 },
487ee2ac1cdSFabrice Gasnier 	{ 0, GENMASK(20, 18), 18 },
488ee2ac1cdSFabrice Gasnier 	{ 0, GENMASK(23, 21), 21 },
489ee2ac1cdSFabrice Gasnier 	{ 0, GENMASK(26, 24), 24 },
490ee2ac1cdSFabrice Gasnier 	{ 0, GENMASK(29, 27), 27 },
491ee2ac1cdSFabrice Gasnier 	/* STM32H7_ADC_SMPR2, smpr[] index, mask, shift for SMP10 to SMP19 */
492ee2ac1cdSFabrice Gasnier 	{ 1, GENMASK(2, 0), 0 },
493ee2ac1cdSFabrice Gasnier 	{ 1, GENMASK(5, 3), 3 },
494ee2ac1cdSFabrice Gasnier 	{ 1, GENMASK(8, 6), 6 },
495ee2ac1cdSFabrice Gasnier 	{ 1, GENMASK(11, 9), 9 },
496ee2ac1cdSFabrice Gasnier 	{ 1, GENMASK(14, 12), 12 },
497ee2ac1cdSFabrice Gasnier 	{ 1, GENMASK(17, 15), 15 },
498ee2ac1cdSFabrice Gasnier 	{ 1, GENMASK(20, 18), 18 },
499ee2ac1cdSFabrice Gasnier 	{ 1, GENMASK(23, 21), 21 },
500ee2ac1cdSFabrice Gasnier 	{ 1, GENMASK(26, 24), 24 },
501ee2ac1cdSFabrice Gasnier 	{ 1, GENMASK(29, 27), 27 },
502ee2ac1cdSFabrice Gasnier };
503ee2ac1cdSFabrice Gasnier 
504ee2ac1cdSFabrice Gasnier /* STM32H7 programmable sampling time (ADC clock cycles, rounded down) */
505ee2ac1cdSFabrice Gasnier static const unsigned int stm32h7_adc_smp_cycles[STM32_ADC_MAX_SMP + 1] = {
506ee2ac1cdSFabrice Gasnier 	1, 2, 8, 16, 32, 64, 387, 810,
507ee2ac1cdSFabrice Gasnier };
508ee2ac1cdSFabrice Gasnier 
50995e339b6SFabrice Gasnier static const struct stm32_adc_regspec stm32h7_adc_regspec = {
51095e339b6SFabrice Gasnier 	.dr = STM32H7_ADC_DR,
51195e339b6SFabrice Gasnier 	.ier_eoc = { STM32H7_ADC_IER, STM32H7_EOCIE },
512cc06e67dSFabrice Gasnier 	.ier_ovr = { STM32H7_ADC_IER, STM32H7_OVRIE },
51395e339b6SFabrice Gasnier 	.isr_eoc = { STM32H7_ADC_ISR, STM32H7_EOC },
514cc06e67dSFabrice Gasnier 	.isr_ovr = { STM32H7_ADC_ISR, STM32H7_OVR },
51595e339b6SFabrice Gasnier 	.sqr = stm32h7_sq,
51695e339b6SFabrice Gasnier 	.exten = { STM32H7_ADC_CFGR, STM32H7_EXTEN_MASK, STM32H7_EXTEN_SHIFT },
51795e339b6SFabrice Gasnier 	.extsel = { STM32H7_ADC_CFGR, STM32H7_EXTSEL_MASK,
51895e339b6SFabrice Gasnier 		    STM32H7_EXTSEL_SHIFT },
51995e339b6SFabrice Gasnier 	.res = { STM32H7_ADC_CFGR, STM32H7_RES_MASK, STM32H7_RES_SHIFT },
520cf0fb80aSOlivier Moysan 	.difsel = { STM32H7_ADC_DIFSEL, STM32H7_DIFSEL_MASK},
521ee2ac1cdSFabrice Gasnier 	.smpr = { STM32H7_ADC_SMPR1, STM32H7_ADC_SMPR2 },
522ee2ac1cdSFabrice Gasnier 	.smp_bits = stm32h7_smp_bits,
52395e339b6SFabrice Gasnier };
52495e339b6SFabrice Gasnier 
525cf0fb80aSOlivier Moysan /* STM32MP13 programmable sampling time (ADC clock cycles, rounded down) */
526cf0fb80aSOlivier Moysan static const unsigned int stm32mp13_adc_smp_cycles[STM32_ADC_MAX_SMP + 1] = {
527cf0fb80aSOlivier Moysan 	2, 6, 12, 24, 47, 92, 247, 640,
528cf0fb80aSOlivier Moysan };
529cf0fb80aSOlivier Moysan 
530cf0fb80aSOlivier Moysan static const struct stm32_adc_regspec stm32mp13_adc_regspec = {
531cf0fb80aSOlivier Moysan 	.dr = STM32H7_ADC_DR,
532cf0fb80aSOlivier Moysan 	.ier_eoc = { STM32H7_ADC_IER, STM32H7_EOCIE },
533cf0fb80aSOlivier Moysan 	.ier_ovr = { STM32H7_ADC_IER, STM32H7_OVRIE },
534cf0fb80aSOlivier Moysan 	.isr_eoc = { STM32H7_ADC_ISR, STM32H7_EOC },
535cf0fb80aSOlivier Moysan 	.isr_ovr = { STM32H7_ADC_ISR, STM32H7_OVR },
536cf0fb80aSOlivier Moysan 	.sqr = stm32h7_sq,
537cf0fb80aSOlivier Moysan 	.exten = { STM32H7_ADC_CFGR, STM32H7_EXTEN_MASK, STM32H7_EXTEN_SHIFT },
538cf0fb80aSOlivier Moysan 	.extsel = { STM32H7_ADC_CFGR, STM32H7_EXTSEL_MASK,
539cf0fb80aSOlivier Moysan 		    STM32H7_EXTSEL_SHIFT },
540cf0fb80aSOlivier Moysan 	.res = { STM32H7_ADC_CFGR, STM32MP13_RES_MASK, STM32MP13_RES_SHIFT },
541cf0fb80aSOlivier Moysan 	.difsel = { STM32MP13_ADC_DIFSEL, STM32MP13_DIFSEL_MASK},
542cf0fb80aSOlivier Moysan 	.smpr = { STM32H7_ADC_SMPR1, STM32H7_ADC_SMPR2 },
543cf0fb80aSOlivier Moysan 	.smp_bits = stm32h7_smp_bits,
544cf0fb80aSOlivier Moysan 	.or_vddcore = { STM32MP13_ADC2_OR, STM32MP13_OP0 },
545cf0fb80aSOlivier Moysan 	.or_vddcpu = { STM32MP13_ADC2_OR, STM32MP13_OP1 },
546cf0fb80aSOlivier Moysan 	.or_vddq_ddr = { STM32MP13_ADC2_OR, STM32MP13_OP2 },
547cf0fb80aSOlivier Moysan 	.ccr_vbat = { STM32H7_ADC_CCR, STM32H7_VBATEN },
548cf0fb80aSOlivier Moysan 	.ccr_vref = { STM32H7_ADC_CCR, STM32H7_VREFEN },
549cf0fb80aSOlivier Moysan };
550cf0fb80aSOlivier Moysan 
551aec6e0d8SOlivier Moysan static const struct stm32_adc_regspec stm32mp1_adc_regspec = {
552aec6e0d8SOlivier Moysan 	.dr = STM32H7_ADC_DR,
553aec6e0d8SOlivier Moysan 	.ier_eoc = { STM32H7_ADC_IER, STM32H7_EOCIE },
554aec6e0d8SOlivier Moysan 	.ier_ovr = { STM32H7_ADC_IER, STM32H7_OVRIE },
555aec6e0d8SOlivier Moysan 	.isr_eoc = { STM32H7_ADC_ISR, STM32H7_EOC },
556aec6e0d8SOlivier Moysan 	.isr_ovr = { STM32H7_ADC_ISR, STM32H7_OVR },
557aec6e0d8SOlivier Moysan 	.sqr = stm32h7_sq,
558aec6e0d8SOlivier Moysan 	.exten = { STM32H7_ADC_CFGR, STM32H7_EXTEN_MASK, STM32H7_EXTEN_SHIFT },
559aec6e0d8SOlivier Moysan 	.extsel = { STM32H7_ADC_CFGR, STM32H7_EXTSEL_MASK,
560aec6e0d8SOlivier Moysan 		    STM32H7_EXTSEL_SHIFT },
561aec6e0d8SOlivier Moysan 	.res = { STM32H7_ADC_CFGR, STM32H7_RES_MASK, STM32H7_RES_SHIFT },
562cf0fb80aSOlivier Moysan 	.difsel = { STM32H7_ADC_DIFSEL, STM32H7_DIFSEL_MASK},
563aec6e0d8SOlivier Moysan 	.smpr = { STM32H7_ADC_SMPR1, STM32H7_ADC_SMPR2 },
564aec6e0d8SOlivier Moysan 	.smp_bits = stm32h7_smp_bits,
565cf0fb80aSOlivier Moysan 	.or_vddcore = { STM32MP1_ADC2_OR, STM32MP1_VDDCOREEN },
566aec6e0d8SOlivier Moysan 	.ccr_vbat = { STM32H7_ADC_CCR, STM32H7_VBATEN },
567aec6e0d8SOlivier Moysan 	.ccr_vref = { STM32H7_ADC_CCR, STM32H7_VREFEN },
568aec6e0d8SOlivier Moysan };
569aec6e0d8SOlivier Moysan 
570fb6da706SJonathan Cameron /*
5710f883b22SFabrice Gasnier  * STM32 ADC registers access routines
5720f883b22SFabrice Gasnier  * @adc: stm32 adc instance
5730f883b22SFabrice Gasnier  * @reg: reg offset in adc instance
5740f883b22SFabrice Gasnier  *
5750f883b22SFabrice Gasnier  * Note: All instances share same base, with 0x0, 0x100 or 0x200 offset resp.
5760f883b22SFabrice Gasnier  * for adc1, adc2 and adc3.
5770f883b22SFabrice Gasnier  */
5780f883b22SFabrice Gasnier static u32 stm32_adc_readl(struct stm32_adc *adc, u32 reg)
5790f883b22SFabrice Gasnier {
5800f883b22SFabrice Gasnier 	return readl_relaxed(adc->common->base + adc->offset + reg);
5810f883b22SFabrice Gasnier }
5820f883b22SFabrice Gasnier 
58395e339b6SFabrice Gasnier #define stm32_adc_readl_addr(addr)	stm32_adc_readl(adc, addr)
58495e339b6SFabrice Gasnier 
58595e339b6SFabrice Gasnier #define stm32_adc_readl_poll_timeout(reg, val, cond, sleep_us, timeout_us) \
58695e339b6SFabrice Gasnier 	readx_poll_timeout(stm32_adc_readl_addr, reg, val, \
58795e339b6SFabrice Gasnier 			   cond, sleep_us, timeout_us)
58895e339b6SFabrice Gasnier 
5890f883b22SFabrice Gasnier static u16 stm32_adc_readw(struct stm32_adc *adc, u32 reg)
5900f883b22SFabrice Gasnier {
5910f883b22SFabrice Gasnier 	return readw_relaxed(adc->common->base + adc->offset + reg);
5920f883b22SFabrice Gasnier }
5930f883b22SFabrice Gasnier 
5940f883b22SFabrice Gasnier static void stm32_adc_writel(struct stm32_adc *adc, u32 reg, u32 val)
5950f883b22SFabrice Gasnier {
5960f883b22SFabrice Gasnier 	writel_relaxed(val, adc->common->base + adc->offset + reg);
5970f883b22SFabrice Gasnier }
5980f883b22SFabrice Gasnier 
5990f883b22SFabrice Gasnier static void stm32_adc_set_bits(struct stm32_adc *adc, u32 reg, u32 bits)
6000f883b22SFabrice Gasnier {
6010f883b22SFabrice Gasnier 	unsigned long flags;
6020f883b22SFabrice Gasnier 
6030f883b22SFabrice Gasnier 	spin_lock_irqsave(&adc->lock, flags);
6040f883b22SFabrice Gasnier 	stm32_adc_writel(adc, reg, stm32_adc_readl(adc, reg) | bits);
6050f883b22SFabrice Gasnier 	spin_unlock_irqrestore(&adc->lock, flags);
6060f883b22SFabrice Gasnier }
6070f883b22SFabrice Gasnier 
608aec6e0d8SOlivier Moysan static void stm32_adc_set_bits_common(struct stm32_adc *adc, u32 reg, u32 bits)
609aec6e0d8SOlivier Moysan {
610aec6e0d8SOlivier Moysan 	spin_lock(&adc->common->lock);
611aec6e0d8SOlivier Moysan 	writel_relaxed(readl_relaxed(adc->common->base + reg) | bits,
612aec6e0d8SOlivier Moysan 		       adc->common->base + reg);
613aec6e0d8SOlivier Moysan 	spin_unlock(&adc->common->lock);
614aec6e0d8SOlivier Moysan }
615aec6e0d8SOlivier Moysan 
6160f883b22SFabrice Gasnier static void stm32_adc_clr_bits(struct stm32_adc *adc, u32 reg, u32 bits)
6170f883b22SFabrice Gasnier {
6180f883b22SFabrice Gasnier 	unsigned long flags;
6190f883b22SFabrice Gasnier 
6200f883b22SFabrice Gasnier 	spin_lock_irqsave(&adc->lock, flags);
6210f883b22SFabrice Gasnier 	stm32_adc_writel(adc, reg, stm32_adc_readl(adc, reg) & ~bits);
6220f883b22SFabrice Gasnier 	spin_unlock_irqrestore(&adc->lock, flags);
6230f883b22SFabrice Gasnier }
6240f883b22SFabrice Gasnier 
625aec6e0d8SOlivier Moysan static void stm32_adc_clr_bits_common(struct stm32_adc *adc, u32 reg, u32 bits)
626aec6e0d8SOlivier Moysan {
627aec6e0d8SOlivier Moysan 	spin_lock(&adc->common->lock);
628aec6e0d8SOlivier Moysan 	writel_relaxed(readl_relaxed(adc->common->base + reg) & ~bits,
629aec6e0d8SOlivier Moysan 		       adc->common->base + reg);
630aec6e0d8SOlivier Moysan 	spin_unlock(&adc->common->lock);
631aec6e0d8SOlivier Moysan }
632aec6e0d8SOlivier Moysan 
6330f883b22SFabrice Gasnier /**
6340f883b22SFabrice Gasnier  * stm32_adc_conv_irq_enable() - Enable end of conversion interrupt
6350f883b22SFabrice Gasnier  * @adc: stm32 adc instance
6360f883b22SFabrice Gasnier  */
6370f883b22SFabrice Gasnier static void stm32_adc_conv_irq_enable(struct stm32_adc *adc)
6380f883b22SFabrice Gasnier {
63964ad7f64SFabrice Gasnier 	stm32_adc_set_bits(adc, adc->cfg->regs->ier_eoc.reg,
64064ad7f64SFabrice Gasnier 			   adc->cfg->regs->ier_eoc.mask);
6410f883b22SFabrice Gasnier };
6420f883b22SFabrice Gasnier 
6430f883b22SFabrice Gasnier /**
6440f883b22SFabrice Gasnier  * stm32_adc_conv_irq_disable() - Disable end of conversion interrupt
6450f883b22SFabrice Gasnier  * @adc: stm32 adc instance
6460f883b22SFabrice Gasnier  */
6470f883b22SFabrice Gasnier static void stm32_adc_conv_irq_disable(struct stm32_adc *adc)
6480f883b22SFabrice Gasnier {
64964ad7f64SFabrice Gasnier 	stm32_adc_clr_bits(adc, adc->cfg->regs->ier_eoc.reg,
65064ad7f64SFabrice Gasnier 			   adc->cfg->regs->ier_eoc.mask);
6510f883b22SFabrice Gasnier }
6520f883b22SFabrice Gasnier 
653cc06e67dSFabrice Gasnier static void stm32_adc_ovr_irq_enable(struct stm32_adc *adc)
654cc06e67dSFabrice Gasnier {
655cc06e67dSFabrice Gasnier 	stm32_adc_set_bits(adc, adc->cfg->regs->ier_ovr.reg,
656cc06e67dSFabrice Gasnier 			   adc->cfg->regs->ier_ovr.mask);
657cc06e67dSFabrice Gasnier }
658cc06e67dSFabrice Gasnier 
659cc06e67dSFabrice Gasnier static void stm32_adc_ovr_irq_disable(struct stm32_adc *adc)
660cc06e67dSFabrice Gasnier {
661cc06e67dSFabrice Gasnier 	stm32_adc_clr_bits(adc, adc->cfg->regs->ier_ovr.reg,
662cc06e67dSFabrice Gasnier 			   adc->cfg->regs->ier_ovr.mask);
663cc06e67dSFabrice Gasnier }
664cc06e67dSFabrice Gasnier 
66525a85bedSFabrice Gasnier static void stm32_adc_set_res(struct stm32_adc *adc)
66625a85bedSFabrice Gasnier {
66764ad7f64SFabrice Gasnier 	const struct stm32_adc_regs *res = &adc->cfg->regs->res;
66864ad7f64SFabrice Gasnier 	u32 val;
66925a85bedSFabrice Gasnier 
67064ad7f64SFabrice Gasnier 	val = stm32_adc_readl(adc, res->reg);
67164ad7f64SFabrice Gasnier 	val = (val & ~res->mask) | (adc->res << res->shift);
67264ad7f64SFabrice Gasnier 	stm32_adc_writel(adc, res->reg, val);
67325a85bedSFabrice Gasnier }
67425a85bedSFabrice Gasnier 
6759bdbb113SFabrice Gasnier static int stm32_adc_hw_stop(struct device *dev)
6769bdbb113SFabrice Gasnier {
677cd64d357SAlexandru Ardelean 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
678cd64d357SAlexandru Ardelean 	struct stm32_adc *adc = iio_priv(indio_dev);
6799bdbb113SFabrice Gasnier 
6809bdbb113SFabrice Gasnier 	if (adc->cfg->unprepare)
681cd64d357SAlexandru Ardelean 		adc->cfg->unprepare(indio_dev);
6829bdbb113SFabrice Gasnier 
6839bdbb113SFabrice Gasnier 	clk_disable_unprepare(adc->clk);
6849bdbb113SFabrice Gasnier 
6859bdbb113SFabrice Gasnier 	return 0;
6869bdbb113SFabrice Gasnier }
6879bdbb113SFabrice Gasnier 
6889bdbb113SFabrice Gasnier static int stm32_adc_hw_start(struct device *dev)
6899bdbb113SFabrice Gasnier {
690cd64d357SAlexandru Ardelean 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
691cd64d357SAlexandru Ardelean 	struct stm32_adc *adc = iio_priv(indio_dev);
6929bdbb113SFabrice Gasnier 	int ret;
6939bdbb113SFabrice Gasnier 
6949bdbb113SFabrice Gasnier 	ret = clk_prepare_enable(adc->clk);
6959bdbb113SFabrice Gasnier 	if (ret)
6969bdbb113SFabrice Gasnier 		return ret;
6979bdbb113SFabrice Gasnier 
6989bdbb113SFabrice Gasnier 	stm32_adc_set_res(adc);
6999bdbb113SFabrice Gasnier 
7009bdbb113SFabrice Gasnier 	if (adc->cfg->prepare) {
701cd64d357SAlexandru Ardelean 		ret = adc->cfg->prepare(indio_dev);
7029bdbb113SFabrice Gasnier 		if (ret)
7039bdbb113SFabrice Gasnier 			goto err_clk_dis;
7049bdbb113SFabrice Gasnier 	}
7059bdbb113SFabrice Gasnier 
7069bdbb113SFabrice Gasnier 	return 0;
7079bdbb113SFabrice Gasnier 
7089bdbb113SFabrice Gasnier err_clk_dis:
7099bdbb113SFabrice Gasnier 	clk_disable_unprepare(adc->clk);
7109bdbb113SFabrice Gasnier 
7119bdbb113SFabrice Gasnier 	return ret;
7129bdbb113SFabrice Gasnier }
7139bdbb113SFabrice Gasnier 
714aec6e0d8SOlivier Moysan static void stm32_adc_int_ch_enable(struct iio_dev *indio_dev)
715aec6e0d8SOlivier Moysan {
716aec6e0d8SOlivier Moysan 	struct stm32_adc *adc = iio_priv(indio_dev);
717aec6e0d8SOlivier Moysan 	u32 i;
718aec6e0d8SOlivier Moysan 
719aec6e0d8SOlivier Moysan 	for (i = 0; i < STM32_ADC_INT_CH_NB; i++) {
720aec6e0d8SOlivier Moysan 		if (adc->int_ch[i] == STM32_ADC_INT_CH_NONE)
721aec6e0d8SOlivier Moysan 			continue;
722aec6e0d8SOlivier Moysan 
723aec6e0d8SOlivier Moysan 		switch (i) {
724aec6e0d8SOlivier Moysan 		case STM32_ADC_INT_CH_VDDCORE:
725aec6e0d8SOlivier Moysan 			dev_dbg(&indio_dev->dev, "Enable VDDCore\n");
726cf0fb80aSOlivier Moysan 			stm32_adc_set_bits(adc, adc->cfg->regs->or_vddcore.reg,
727cf0fb80aSOlivier Moysan 					   adc->cfg->regs->or_vddcore.mask);
728cf0fb80aSOlivier Moysan 			break;
729cf0fb80aSOlivier Moysan 		case STM32_ADC_INT_CH_VDDCPU:
730cf0fb80aSOlivier Moysan 			dev_dbg(&indio_dev->dev, "Enable VDDCPU\n");
731cf0fb80aSOlivier Moysan 			stm32_adc_set_bits(adc, adc->cfg->regs->or_vddcpu.reg,
732cf0fb80aSOlivier Moysan 					   adc->cfg->regs->or_vddcpu.mask);
733cf0fb80aSOlivier Moysan 			break;
734cf0fb80aSOlivier Moysan 		case STM32_ADC_INT_CH_VDDQ_DDR:
735cf0fb80aSOlivier Moysan 			dev_dbg(&indio_dev->dev, "Enable VDDQ_DDR\n");
736cf0fb80aSOlivier Moysan 			stm32_adc_set_bits(adc, adc->cfg->regs->or_vddq_ddr.reg,
737cf0fb80aSOlivier Moysan 					   adc->cfg->regs->or_vddq_ddr.mask);
738aec6e0d8SOlivier Moysan 			break;
739aec6e0d8SOlivier Moysan 		case STM32_ADC_INT_CH_VREFINT:
740aec6e0d8SOlivier Moysan 			dev_dbg(&indio_dev->dev, "Enable VREFInt\n");
741aec6e0d8SOlivier Moysan 			stm32_adc_set_bits_common(adc, adc->cfg->regs->ccr_vref.reg,
742aec6e0d8SOlivier Moysan 						  adc->cfg->regs->ccr_vref.mask);
743aec6e0d8SOlivier Moysan 			break;
744aec6e0d8SOlivier Moysan 		case STM32_ADC_INT_CH_VBAT:
745aec6e0d8SOlivier Moysan 			dev_dbg(&indio_dev->dev, "Enable VBAT\n");
746aec6e0d8SOlivier Moysan 			stm32_adc_set_bits_common(adc, adc->cfg->regs->ccr_vbat.reg,
747aec6e0d8SOlivier Moysan 						  adc->cfg->regs->ccr_vbat.mask);
748aec6e0d8SOlivier Moysan 			break;
749aec6e0d8SOlivier Moysan 		}
750aec6e0d8SOlivier Moysan 	}
751aec6e0d8SOlivier Moysan }
752aec6e0d8SOlivier Moysan 
753aec6e0d8SOlivier Moysan static void stm32_adc_int_ch_disable(struct stm32_adc *adc)
754aec6e0d8SOlivier Moysan {
755aec6e0d8SOlivier Moysan 	u32 i;
756aec6e0d8SOlivier Moysan 
757aec6e0d8SOlivier Moysan 	for (i = 0; i < STM32_ADC_INT_CH_NB; i++) {
758aec6e0d8SOlivier Moysan 		if (adc->int_ch[i] == STM32_ADC_INT_CH_NONE)
759aec6e0d8SOlivier Moysan 			continue;
760aec6e0d8SOlivier Moysan 
761aec6e0d8SOlivier Moysan 		switch (i) {
762aec6e0d8SOlivier Moysan 		case STM32_ADC_INT_CH_VDDCORE:
763cf0fb80aSOlivier Moysan 			stm32_adc_clr_bits(adc, adc->cfg->regs->or_vddcore.reg,
764cf0fb80aSOlivier Moysan 					   adc->cfg->regs->or_vddcore.mask);
765cf0fb80aSOlivier Moysan 			break;
766cf0fb80aSOlivier Moysan 		case STM32_ADC_INT_CH_VDDCPU:
767cf0fb80aSOlivier Moysan 			stm32_adc_clr_bits(adc, adc->cfg->regs->or_vddcpu.reg,
768cf0fb80aSOlivier Moysan 					   adc->cfg->regs->or_vddcpu.mask);
769cf0fb80aSOlivier Moysan 			break;
770cf0fb80aSOlivier Moysan 		case STM32_ADC_INT_CH_VDDQ_DDR:
771cf0fb80aSOlivier Moysan 			stm32_adc_clr_bits(adc, adc->cfg->regs->or_vddq_ddr.reg,
772cf0fb80aSOlivier Moysan 					   adc->cfg->regs->or_vddq_ddr.mask);
773aec6e0d8SOlivier Moysan 			break;
774aec6e0d8SOlivier Moysan 		case STM32_ADC_INT_CH_VREFINT:
775aec6e0d8SOlivier Moysan 			stm32_adc_clr_bits_common(adc, adc->cfg->regs->ccr_vref.reg,
776aec6e0d8SOlivier Moysan 						  adc->cfg->regs->ccr_vref.mask);
777aec6e0d8SOlivier Moysan 			break;
778aec6e0d8SOlivier Moysan 		case STM32_ADC_INT_CH_VBAT:
779aec6e0d8SOlivier Moysan 			stm32_adc_clr_bits_common(adc, adc->cfg->regs->ccr_vbat.reg,
780aec6e0d8SOlivier Moysan 						  adc->cfg->regs->ccr_vbat.mask);
781aec6e0d8SOlivier Moysan 			break;
782aec6e0d8SOlivier Moysan 		}
783aec6e0d8SOlivier Moysan 	}
784aec6e0d8SOlivier Moysan }
785aec6e0d8SOlivier Moysan 
7860f883b22SFabrice Gasnier /**
78764ad7f64SFabrice Gasnier  * stm32f4_adc_start_conv() - Start conversions for regular channels.
788cd64d357SAlexandru Ardelean  * @indio_dev: IIO device instance
7892763ea05SFabrice Gasnier  * @dma: use dma to transfer conversion result
7902763ea05SFabrice Gasnier  *
7912763ea05SFabrice Gasnier  * Start conversions for regular channels.
7922763ea05SFabrice Gasnier  * Also take care of normal or DMA mode. Circular DMA may be used for regular
7932763ea05SFabrice Gasnier  * conversions, in IIO buffer modes. Otherwise, use ADC interrupt with direct
7942763ea05SFabrice Gasnier  * DR read instead (e.g. read_raw, or triggered buffer mode without DMA).
7950f883b22SFabrice Gasnier  */
796cd64d357SAlexandru Ardelean static void stm32f4_adc_start_conv(struct iio_dev *indio_dev, bool dma)
7970f883b22SFabrice Gasnier {
798cd64d357SAlexandru Ardelean 	struct stm32_adc *adc = iio_priv(indio_dev);
799cd64d357SAlexandru Ardelean 
8000f883b22SFabrice Gasnier 	stm32_adc_set_bits(adc, STM32F4_ADC_CR1, STM32F4_SCAN);
8012763ea05SFabrice Gasnier 
8022763ea05SFabrice Gasnier 	if (dma)
8032763ea05SFabrice Gasnier 		stm32_adc_set_bits(adc, STM32F4_ADC_CR2,
8042763ea05SFabrice Gasnier 				   STM32F4_DMA | STM32F4_DDS);
8052763ea05SFabrice Gasnier 
8060f883b22SFabrice Gasnier 	stm32_adc_set_bits(adc, STM32F4_ADC_CR2, STM32F4_EOCS | STM32F4_ADON);
8070f883b22SFabrice Gasnier 
8080f883b22SFabrice Gasnier 	/* Wait for Power-up time (tSTAB from datasheet) */
8090f883b22SFabrice Gasnier 	usleep_range(2, 3);
8100f883b22SFabrice Gasnier 
8110f883b22SFabrice Gasnier 	/* Software start ? (e.g. trigger detection disabled ?) */
8120f883b22SFabrice Gasnier 	if (!(stm32_adc_readl(adc, STM32F4_ADC_CR2) & STM32F4_EXTEN_MASK))
8130f883b22SFabrice Gasnier 		stm32_adc_set_bits(adc, STM32F4_ADC_CR2, STM32F4_SWSTART);
8140f883b22SFabrice Gasnier }
8150f883b22SFabrice Gasnier 
816cd64d357SAlexandru Ardelean static void stm32f4_adc_stop_conv(struct iio_dev *indio_dev)
8170f883b22SFabrice Gasnier {
818cd64d357SAlexandru Ardelean 	struct stm32_adc *adc = iio_priv(indio_dev);
819cd64d357SAlexandru Ardelean 
8200f883b22SFabrice Gasnier 	stm32_adc_clr_bits(adc, STM32F4_ADC_CR2, STM32F4_EXTEN_MASK);
8210f883b22SFabrice Gasnier 	stm32_adc_clr_bits(adc, STM32F4_ADC_SR, STM32F4_STRT);
8220f883b22SFabrice Gasnier 
8230f883b22SFabrice Gasnier 	stm32_adc_clr_bits(adc, STM32F4_ADC_CR1, STM32F4_SCAN);
8242763ea05SFabrice Gasnier 	stm32_adc_clr_bits(adc, STM32F4_ADC_CR2,
8252763ea05SFabrice Gasnier 			   STM32F4_ADON | STM32F4_DMA | STM32F4_DDS);
8260f883b22SFabrice Gasnier }
8270f883b22SFabrice Gasnier 
828695e2f5cSOlivier Moysan static void stm32f4_adc_irq_clear(struct iio_dev *indio_dev, u32 msk)
829695e2f5cSOlivier Moysan {
830695e2f5cSOlivier Moysan 	struct stm32_adc *adc = iio_priv(indio_dev);
831695e2f5cSOlivier Moysan 
832695e2f5cSOlivier Moysan 	stm32_adc_clr_bits(adc, adc->cfg->regs->isr_eoc.reg, msk);
833695e2f5cSOlivier Moysan }
834695e2f5cSOlivier Moysan 
835cd64d357SAlexandru Ardelean static void stm32h7_adc_start_conv(struct iio_dev *indio_dev, bool dma)
83695e339b6SFabrice Gasnier {
837cd64d357SAlexandru Ardelean 	struct stm32_adc *adc = iio_priv(indio_dev);
83895e339b6SFabrice Gasnier 	enum stm32h7_adc_dmngt dmngt;
83995e339b6SFabrice Gasnier 	unsigned long flags;
84095e339b6SFabrice Gasnier 	u32 val;
84195e339b6SFabrice Gasnier 
84295e339b6SFabrice Gasnier 	if (dma)
84395e339b6SFabrice Gasnier 		dmngt = STM32H7_DMNGT_DMA_CIRC;
84495e339b6SFabrice Gasnier 	else
84595e339b6SFabrice Gasnier 		dmngt = STM32H7_DMNGT_DR_ONLY;
84695e339b6SFabrice Gasnier 
84795e339b6SFabrice Gasnier 	spin_lock_irqsave(&adc->lock, flags);
84895e339b6SFabrice Gasnier 	val = stm32_adc_readl(adc, STM32H7_ADC_CFGR);
84995e339b6SFabrice Gasnier 	val = (val & ~STM32H7_DMNGT_MASK) | (dmngt << STM32H7_DMNGT_SHIFT);
85095e339b6SFabrice Gasnier 	stm32_adc_writel(adc, STM32H7_ADC_CFGR, val);
85195e339b6SFabrice Gasnier 	spin_unlock_irqrestore(&adc->lock, flags);
85295e339b6SFabrice Gasnier 
85395e339b6SFabrice Gasnier 	stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_ADSTART);
85495e339b6SFabrice Gasnier }
85595e339b6SFabrice Gasnier 
856cd64d357SAlexandru Ardelean static void stm32h7_adc_stop_conv(struct iio_dev *indio_dev)
85795e339b6SFabrice Gasnier {
858cd64d357SAlexandru Ardelean 	struct stm32_adc *adc = iio_priv(indio_dev);
85995e339b6SFabrice Gasnier 	int ret;
86095e339b6SFabrice Gasnier 	u32 val;
86195e339b6SFabrice Gasnier 
86295e339b6SFabrice Gasnier 	stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_ADSTP);
86395e339b6SFabrice Gasnier 
86495e339b6SFabrice Gasnier 	ret = stm32_adc_readl_poll_timeout(STM32H7_ADC_CR, val,
86595e339b6SFabrice Gasnier 					   !(val & (STM32H7_ADSTART)),
86695e339b6SFabrice Gasnier 					   100, STM32_ADC_TIMEOUT_US);
86795e339b6SFabrice Gasnier 	if (ret)
86895e339b6SFabrice Gasnier 		dev_warn(&indio_dev->dev, "stop failed\n");
86995e339b6SFabrice Gasnier 
870cf0fb80aSOlivier Moysan 	/* STM32H7_DMNGT_MASK covers STM32MP13_DMAEN & STM32MP13_DMACFG */
87195e339b6SFabrice Gasnier 	stm32_adc_clr_bits(adc, STM32H7_ADC_CFGR, STM32H7_DMNGT_MASK);
87295e339b6SFabrice Gasnier }
87395e339b6SFabrice Gasnier 
874695e2f5cSOlivier Moysan static void stm32h7_adc_irq_clear(struct iio_dev *indio_dev, u32 msk)
875695e2f5cSOlivier Moysan {
876695e2f5cSOlivier Moysan 	struct stm32_adc *adc = iio_priv(indio_dev);
877695e2f5cSOlivier Moysan 	/* On STM32H7 IRQs are cleared by writing 1 into ISR register */
878695e2f5cSOlivier Moysan 	stm32_adc_set_bits(adc, adc->cfg->regs->isr_eoc.reg, msk);
879695e2f5cSOlivier Moysan }
880695e2f5cSOlivier Moysan 
881cf0fb80aSOlivier Moysan static void stm32mp13_adc_start_conv(struct iio_dev *indio_dev, bool dma)
882cf0fb80aSOlivier Moysan {
883cf0fb80aSOlivier Moysan 	struct stm32_adc *adc = iio_priv(indio_dev);
884cf0fb80aSOlivier Moysan 
885cf0fb80aSOlivier Moysan 	if (dma)
886cf0fb80aSOlivier Moysan 		stm32_adc_set_bits(adc, STM32H7_ADC_CFGR,
887cf0fb80aSOlivier Moysan 				   STM32MP13_DMAEN | STM32MP13_DMACFG);
888cf0fb80aSOlivier Moysan 
889cf0fb80aSOlivier Moysan 	stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_ADSTART);
890cf0fb80aSOlivier Moysan }
891cf0fb80aSOlivier Moysan 
892cd64d357SAlexandru Ardelean static int stm32h7_adc_exit_pwr_down(struct iio_dev *indio_dev)
89395e339b6SFabrice Gasnier {
894cd64d357SAlexandru Ardelean 	struct stm32_adc *adc = iio_priv(indio_dev);
895d58c67d1SFabrice Gasnier 	int ret;
896d58c67d1SFabrice Gasnier 	u32 val;
897d58c67d1SFabrice Gasnier 
89895e339b6SFabrice Gasnier 	/* Exit deep power down, then enable ADC voltage regulator */
89995e339b6SFabrice Gasnier 	stm32_adc_clr_bits(adc, STM32H7_ADC_CR, STM32H7_DEEPPWD);
90095e339b6SFabrice Gasnier 	stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_ADVREGEN);
90195e339b6SFabrice Gasnier 
902cf0fb80aSOlivier Moysan 	if (adc->cfg->has_boostmode &&
903cf0fb80aSOlivier Moysan 	    adc->common->rate > STM32H7_BOOST_CLKRATE)
90495e339b6SFabrice Gasnier 		stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_BOOST);
90595e339b6SFabrice Gasnier 
90695e339b6SFabrice Gasnier 	/* Wait for startup time */
907d58c67d1SFabrice Gasnier 	if (!adc->cfg->has_vregready) {
90895e339b6SFabrice Gasnier 		usleep_range(10, 20);
909d58c67d1SFabrice Gasnier 		return 0;
910d58c67d1SFabrice Gasnier 	}
911d58c67d1SFabrice Gasnier 
912d58c67d1SFabrice Gasnier 	ret = stm32_adc_readl_poll_timeout(STM32H7_ADC_ISR, val,
913d58c67d1SFabrice Gasnier 					   val & STM32MP1_VREGREADY, 100,
914d58c67d1SFabrice Gasnier 					   STM32_ADC_TIMEOUT_US);
915d58c67d1SFabrice Gasnier 	if (ret) {
916d58c67d1SFabrice Gasnier 		stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_DEEPPWD);
917d58c67d1SFabrice Gasnier 		dev_err(&indio_dev->dev, "Failed to exit power down\n");
918d58c67d1SFabrice Gasnier 	}
919d58c67d1SFabrice Gasnier 
920d58c67d1SFabrice Gasnier 	return ret;
92195e339b6SFabrice Gasnier }
92295e339b6SFabrice Gasnier 
92395e339b6SFabrice Gasnier static void stm32h7_adc_enter_pwr_down(struct stm32_adc *adc)
92495e339b6SFabrice Gasnier {
925cf0fb80aSOlivier Moysan 	if (adc->cfg->has_boostmode)
92695e339b6SFabrice Gasnier 		stm32_adc_clr_bits(adc, STM32H7_ADC_CR, STM32H7_BOOST);
92795e339b6SFabrice Gasnier 
92895e339b6SFabrice Gasnier 	/* Setting DEEPPWD disables ADC vreg and clears ADVREGEN */
92995e339b6SFabrice Gasnier 	stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_DEEPPWD);
93095e339b6SFabrice Gasnier }
93195e339b6SFabrice Gasnier 
932cd64d357SAlexandru Ardelean static int stm32h7_adc_enable(struct iio_dev *indio_dev)
93395e339b6SFabrice Gasnier {
934cd64d357SAlexandru Ardelean 	struct stm32_adc *adc = iio_priv(indio_dev);
93595e339b6SFabrice Gasnier 	int ret;
93695e339b6SFabrice Gasnier 	u32 val;
93795e339b6SFabrice Gasnier 
93895e339b6SFabrice Gasnier 	stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_ADEN);
93995e339b6SFabrice Gasnier 
94095e339b6SFabrice Gasnier 	/* Poll for ADRDY to be set (after adc startup time) */
94195e339b6SFabrice Gasnier 	ret = stm32_adc_readl_poll_timeout(STM32H7_ADC_ISR, val,
94295e339b6SFabrice Gasnier 					   val & STM32H7_ADRDY,
94395e339b6SFabrice Gasnier 					   100, STM32_ADC_TIMEOUT_US);
94495e339b6SFabrice Gasnier 	if (ret) {
945a3b5655eSFabrice Gasnier 		stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_ADDIS);
94695e339b6SFabrice Gasnier 		dev_err(&indio_dev->dev, "Failed to enable ADC\n");
947a3b5655eSFabrice Gasnier 	} else {
948a3b5655eSFabrice Gasnier 		/* Clear ADRDY by writing one */
949a3b5655eSFabrice Gasnier 		stm32_adc_set_bits(adc, STM32H7_ADC_ISR, STM32H7_ADRDY);
95095e339b6SFabrice Gasnier 	}
95195e339b6SFabrice Gasnier 
95295e339b6SFabrice Gasnier 	return ret;
95395e339b6SFabrice Gasnier }
95495e339b6SFabrice Gasnier 
955cd64d357SAlexandru Ardelean static void stm32h7_adc_disable(struct iio_dev *indio_dev)
95695e339b6SFabrice Gasnier {
957cd64d357SAlexandru Ardelean 	struct stm32_adc *adc = iio_priv(indio_dev);
95895e339b6SFabrice Gasnier 	int ret;
95995e339b6SFabrice Gasnier 	u32 val;
96095e339b6SFabrice Gasnier 
961cf59ad96SOlivier Moysan 	if (!(stm32_adc_readl(adc, STM32H7_ADC_CR) & STM32H7_ADEN))
962cf59ad96SOlivier Moysan 		return;
963cf59ad96SOlivier Moysan 
96495e339b6SFabrice Gasnier 	/* Disable ADC and wait until it's effectively disabled */
96595e339b6SFabrice Gasnier 	stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_ADDIS);
96695e339b6SFabrice Gasnier 	ret = stm32_adc_readl_poll_timeout(STM32H7_ADC_CR, val,
96795e339b6SFabrice Gasnier 					   !(val & STM32H7_ADEN), 100,
96895e339b6SFabrice Gasnier 					   STM32_ADC_TIMEOUT_US);
96995e339b6SFabrice Gasnier 	if (ret)
97095e339b6SFabrice Gasnier 		dev_warn(&indio_dev->dev, "Failed to disable\n");
97195e339b6SFabrice Gasnier }
97295e339b6SFabrice Gasnier 
97395e339b6SFabrice Gasnier /**
97495e339b6SFabrice Gasnier  * stm32h7_adc_read_selfcalib() - read calibration shadow regs, save result
975cd64d357SAlexandru Ardelean  * @indio_dev: IIO device instance
9760da98c7bSFabrice Gasnier  * Note: Must be called once ADC is enabled, so LINCALRDYW[1..6] are writable
97795e339b6SFabrice Gasnier  */
978cd64d357SAlexandru Ardelean static int stm32h7_adc_read_selfcalib(struct iio_dev *indio_dev)
97995e339b6SFabrice Gasnier {
980cd64d357SAlexandru Ardelean 	struct stm32_adc *adc = iio_priv(indio_dev);
98195e339b6SFabrice Gasnier 	int i, ret;
98295e339b6SFabrice Gasnier 	u32 lincalrdyw_mask, val;
98395e339b6SFabrice Gasnier 
98495e339b6SFabrice Gasnier 	/* Read linearity calibration */
98595e339b6SFabrice Gasnier 	lincalrdyw_mask = STM32H7_LINCALRDYW6;
98695e339b6SFabrice Gasnier 	for (i = STM32H7_LINCALFACT_NUM - 1; i >= 0; i--) {
98795e339b6SFabrice Gasnier 		/* Clear STM32H7_LINCALRDYW[6..1]: transfer calib to CALFACT2 */
98895e339b6SFabrice Gasnier 		stm32_adc_clr_bits(adc, STM32H7_ADC_CR, lincalrdyw_mask);
98995e339b6SFabrice Gasnier 
99095e339b6SFabrice Gasnier 		/* Poll: wait calib data to be ready in CALFACT2 register */
99195e339b6SFabrice Gasnier 		ret = stm32_adc_readl_poll_timeout(STM32H7_ADC_CR, val,
99295e339b6SFabrice Gasnier 						   !(val & lincalrdyw_mask),
99395e339b6SFabrice Gasnier 						   100, STM32_ADC_TIMEOUT_US);
99495e339b6SFabrice Gasnier 		if (ret) {
99595e339b6SFabrice Gasnier 			dev_err(&indio_dev->dev, "Failed to read calfact\n");
9960da98c7bSFabrice Gasnier 			return ret;
99795e339b6SFabrice Gasnier 		}
99895e339b6SFabrice Gasnier 
99995e339b6SFabrice Gasnier 		val = stm32_adc_readl(adc, STM32H7_ADC_CALFACT2);
100095e339b6SFabrice Gasnier 		adc->cal.lincalfact[i] = (val & STM32H7_LINCALFACT_MASK);
100195e339b6SFabrice Gasnier 		adc->cal.lincalfact[i] >>= STM32H7_LINCALFACT_SHIFT;
100295e339b6SFabrice Gasnier 
100395e339b6SFabrice Gasnier 		lincalrdyw_mask >>= 1;
100495e339b6SFabrice Gasnier 	}
10059d901e35SOlivier Moysan 	adc->cal.lincal_saved = true;
100695e339b6SFabrice Gasnier 
10070da98c7bSFabrice Gasnier 	return 0;
100895e339b6SFabrice Gasnier }
100995e339b6SFabrice Gasnier 
101095e339b6SFabrice Gasnier /**
101195e339b6SFabrice Gasnier  * stm32h7_adc_restore_selfcalib() - Restore saved self-calibration result
1012cd64d357SAlexandru Ardelean  * @indio_dev: IIO device instance
101395e339b6SFabrice Gasnier  * Note: ADC must be enabled, with no on-going conversions.
101495e339b6SFabrice Gasnier  */
1015cd64d357SAlexandru Ardelean static int stm32h7_adc_restore_selfcalib(struct iio_dev *indio_dev)
101695e339b6SFabrice Gasnier {
1017cd64d357SAlexandru Ardelean 	struct stm32_adc *adc = iio_priv(indio_dev);
101895e339b6SFabrice Gasnier 	int i, ret;
101995e339b6SFabrice Gasnier 	u32 lincalrdyw_mask, val;
102095e339b6SFabrice Gasnier 
102195e339b6SFabrice Gasnier 	lincalrdyw_mask = STM32H7_LINCALRDYW6;
102295e339b6SFabrice Gasnier 	for (i = STM32H7_LINCALFACT_NUM - 1; i >= 0; i--) {
102395e339b6SFabrice Gasnier 		/*
102495e339b6SFabrice Gasnier 		 * Write saved calibration data to shadow registers:
102595e339b6SFabrice Gasnier 		 * Write CALFACT2, and set LINCALRDYW[6..1] bit to trigger
102695e339b6SFabrice Gasnier 		 * data write. Then poll to wait for complete transfer.
102795e339b6SFabrice Gasnier 		 */
102895e339b6SFabrice Gasnier 		val = adc->cal.lincalfact[i] << STM32H7_LINCALFACT_SHIFT;
102995e339b6SFabrice Gasnier 		stm32_adc_writel(adc, STM32H7_ADC_CALFACT2, val);
103095e339b6SFabrice Gasnier 		stm32_adc_set_bits(adc, STM32H7_ADC_CR, lincalrdyw_mask);
103195e339b6SFabrice Gasnier 		ret = stm32_adc_readl_poll_timeout(STM32H7_ADC_CR, val,
103295e339b6SFabrice Gasnier 						   val & lincalrdyw_mask,
103395e339b6SFabrice Gasnier 						   100, STM32_ADC_TIMEOUT_US);
103495e339b6SFabrice Gasnier 		if (ret) {
103595e339b6SFabrice Gasnier 			dev_err(&indio_dev->dev, "Failed to write calfact\n");
103695e339b6SFabrice Gasnier 			return ret;
103795e339b6SFabrice Gasnier 		}
103895e339b6SFabrice Gasnier 
103995e339b6SFabrice Gasnier 		/*
104095e339b6SFabrice Gasnier 		 * Read back calibration data, has two effects:
104195e339b6SFabrice Gasnier 		 * - It ensures bits LINCALRDYW[6..1] are kept cleared
104295e339b6SFabrice Gasnier 		 *   for next time calibration needs to be restored.
104395e339b6SFabrice Gasnier 		 * - BTW, bit clear triggers a read, then check data has been
104495e339b6SFabrice Gasnier 		 *   correctly written.
104595e339b6SFabrice Gasnier 		 */
104695e339b6SFabrice Gasnier 		stm32_adc_clr_bits(adc, STM32H7_ADC_CR, lincalrdyw_mask);
104795e339b6SFabrice Gasnier 		ret = stm32_adc_readl_poll_timeout(STM32H7_ADC_CR, val,
104895e339b6SFabrice Gasnier 						   !(val & lincalrdyw_mask),
104995e339b6SFabrice Gasnier 						   100, STM32_ADC_TIMEOUT_US);
105095e339b6SFabrice Gasnier 		if (ret) {
105195e339b6SFabrice Gasnier 			dev_err(&indio_dev->dev, "Failed to read calfact\n");
105295e339b6SFabrice Gasnier 			return ret;
105395e339b6SFabrice Gasnier 		}
105495e339b6SFabrice Gasnier 		val = stm32_adc_readl(adc, STM32H7_ADC_CALFACT2);
105595e339b6SFabrice Gasnier 		if (val != adc->cal.lincalfact[i] << STM32H7_LINCALFACT_SHIFT) {
105695e339b6SFabrice Gasnier 			dev_err(&indio_dev->dev, "calfact not consistent\n");
105795e339b6SFabrice Gasnier 			return -EIO;
105895e339b6SFabrice Gasnier 		}
105995e339b6SFabrice Gasnier 
106095e339b6SFabrice Gasnier 		lincalrdyw_mask >>= 1;
106195e339b6SFabrice Gasnier 	}
106295e339b6SFabrice Gasnier 
106395e339b6SFabrice Gasnier 	return 0;
106495e339b6SFabrice Gasnier }
106595e339b6SFabrice Gasnier 
1066fb6da706SJonathan Cameron /*
106795e339b6SFabrice Gasnier  * Fixed timeout value for ADC calibration.
106895e339b6SFabrice Gasnier  * worst cases:
106995e339b6SFabrice Gasnier  * - low clock frequency
107095e339b6SFabrice Gasnier  * - maximum prescalers
107195e339b6SFabrice Gasnier  * Calibration requires:
107295e339b6SFabrice Gasnier  * - 131,072 ADC clock cycle for the linear calibration
107395e339b6SFabrice Gasnier  * - 20 ADC clock cycle for the offset calibration
107495e339b6SFabrice Gasnier  *
107595e339b6SFabrice Gasnier  * Set to 100ms for now
107695e339b6SFabrice Gasnier  */
107795e339b6SFabrice Gasnier #define STM32H7_ADC_CALIB_TIMEOUT_US		100000
107895e339b6SFabrice Gasnier 
107995e339b6SFabrice Gasnier /**
10800da98c7bSFabrice Gasnier  * stm32h7_adc_selfcalib() - Procedure to calibrate ADC
1081cd64d357SAlexandru Ardelean  * @indio_dev: IIO device instance
10829d901e35SOlivier Moysan  * @do_lincal: linear calibration request flag
10830da98c7bSFabrice Gasnier  * Note: Must be called once ADC is out of power down.
10849d901e35SOlivier Moysan  *
10859d901e35SOlivier Moysan  * Run offset calibration unconditionally.
10869d901e35SOlivier Moysan  * Run linear calibration if requested & supported.
108795e339b6SFabrice Gasnier  */
10889d901e35SOlivier Moysan static int stm32h7_adc_selfcalib(struct iio_dev *indio_dev, int do_lincal)
108995e339b6SFabrice Gasnier {
1090cd64d357SAlexandru Ardelean 	struct stm32_adc *adc = iio_priv(indio_dev);
109195e339b6SFabrice Gasnier 	int ret;
1092cf0fb80aSOlivier Moysan 	u32 msk = STM32H7_ADCALDIF;
109395e339b6SFabrice Gasnier 	u32 val;
109495e339b6SFabrice Gasnier 
10959d901e35SOlivier Moysan 	if (adc->cfg->has_linearcal && do_lincal)
1096cf0fb80aSOlivier Moysan 		msk |= STM32H7_ADCALLIN;
1097883f50eaSOlivier Moysan 	/* ADC must be disabled for calibration */
1098883f50eaSOlivier Moysan 	stm32h7_adc_disable(indio_dev);
1099883f50eaSOlivier Moysan 
110095e339b6SFabrice Gasnier 	/*
110195e339b6SFabrice Gasnier 	 * Select calibration mode:
110295e339b6SFabrice Gasnier 	 * - Offset calibration for single ended inputs
110395e339b6SFabrice Gasnier 	 * - No linearity calibration (do it later, before reading it)
110495e339b6SFabrice Gasnier 	 */
1105cf0fb80aSOlivier Moysan 	stm32_adc_clr_bits(adc, STM32H7_ADC_CR, msk);
110695e339b6SFabrice Gasnier 
110795e339b6SFabrice Gasnier 	/* Start calibration, then wait for completion */
110895e339b6SFabrice Gasnier 	stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_ADCAL);
110995e339b6SFabrice Gasnier 	ret = stm32_adc_readl_poll_timeout(STM32H7_ADC_CR, val,
111095e339b6SFabrice Gasnier 					   !(val & STM32H7_ADCAL), 100,
111195e339b6SFabrice Gasnier 					   STM32H7_ADC_CALIB_TIMEOUT_US);
111295e339b6SFabrice Gasnier 	if (ret) {
11132206732bSOlivier Moysan 		dev_err(&indio_dev->dev, "calibration (single-ended) error %d\n", ret);
11140da98c7bSFabrice Gasnier 		goto out;
111595e339b6SFabrice Gasnier 	}
111695e339b6SFabrice Gasnier 
111795e339b6SFabrice Gasnier 	/*
111895e339b6SFabrice Gasnier 	 * Select calibration mode, then start calibration:
111995e339b6SFabrice Gasnier 	 * - Offset calibration for differential input
112095e339b6SFabrice Gasnier 	 * - Linearity calibration (needs to be done only once for single/diff)
112195e339b6SFabrice Gasnier 	 *   will run simultaneously with offset calibration.
112295e339b6SFabrice Gasnier 	 */
1123cf0fb80aSOlivier Moysan 	stm32_adc_set_bits(adc, STM32H7_ADC_CR, msk);
112495e339b6SFabrice Gasnier 	stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_ADCAL);
112595e339b6SFabrice Gasnier 	ret = stm32_adc_readl_poll_timeout(STM32H7_ADC_CR, val,
112695e339b6SFabrice Gasnier 					   !(val & STM32H7_ADCAL), 100,
112795e339b6SFabrice Gasnier 					   STM32H7_ADC_CALIB_TIMEOUT_US);
112895e339b6SFabrice Gasnier 	if (ret) {
11292206732bSOlivier Moysan 		dev_err(&indio_dev->dev, "calibration (diff%s) error %d\n",
11302206732bSOlivier Moysan 			(msk & STM32H7_ADCALLIN) ? "+linear" : "", ret);
11310da98c7bSFabrice Gasnier 		goto out;
113295e339b6SFabrice Gasnier 	}
113395e339b6SFabrice Gasnier 
11340da98c7bSFabrice Gasnier out:
1135cf0fb80aSOlivier Moysan 	stm32_adc_clr_bits(adc, STM32H7_ADC_CR, msk);
113695e339b6SFabrice Gasnier 
113795e339b6SFabrice Gasnier 	return ret;
113895e339b6SFabrice Gasnier }
113995e339b6SFabrice Gasnier 
114095e339b6SFabrice Gasnier /**
11419d901e35SOlivier Moysan  * stm32h7_adc_check_selfcalib() - Check linear calibration status
11429d901e35SOlivier Moysan  * @indio_dev: IIO device instance
11439d901e35SOlivier Moysan  *
11449d901e35SOlivier Moysan  * Used to check if linear calibration has been done.
11459d901e35SOlivier Moysan  * Return true if linear calibration factors are already saved in private data
11469d901e35SOlivier Moysan  * or if a linear calibration has been done at boot stage.
11479d901e35SOlivier Moysan  */
11489d901e35SOlivier Moysan static int stm32h7_adc_check_selfcalib(struct iio_dev *indio_dev)
11499d901e35SOlivier Moysan {
11509d901e35SOlivier Moysan 	struct stm32_adc *adc = iio_priv(indio_dev);
11519d901e35SOlivier Moysan 	u32 val;
11529d901e35SOlivier Moysan 
11539d901e35SOlivier Moysan 	if (adc->cal.lincal_saved)
11549d901e35SOlivier Moysan 		return true;
11559d901e35SOlivier Moysan 
11569d901e35SOlivier Moysan 	/*
11579d901e35SOlivier Moysan 	 * Check if linear calibration factors are available in ADC registers,
11589d901e35SOlivier Moysan 	 * by checking that all LINCALRDYWx bits are set.
11599d901e35SOlivier Moysan 	 */
11609d901e35SOlivier Moysan 	val = stm32_adc_readl(adc, STM32H7_ADC_CR) & STM32H7_LINCALRDYW_MASK;
11619d901e35SOlivier Moysan 	if (val == STM32H7_LINCALRDYW_MASK)
11629d901e35SOlivier Moysan 		return true;
11639d901e35SOlivier Moysan 
11649d901e35SOlivier Moysan 	return false;
11659d901e35SOlivier Moysan }
11669d901e35SOlivier Moysan 
11679d901e35SOlivier Moysan /**
116895e339b6SFabrice Gasnier  * stm32h7_adc_prepare() - Leave power down mode to enable ADC.
1169cd64d357SAlexandru Ardelean  * @indio_dev: IIO device instance
117095e339b6SFabrice Gasnier  * Leave power down mode.
11713fb2e24eSFabrice Gasnier  * Configure channels as single ended or differential before enabling ADC.
117295e339b6SFabrice Gasnier  * Enable ADC.
117395e339b6SFabrice Gasnier  * Restore calibration data.
11743fb2e24eSFabrice Gasnier  * Pre-select channels that may be used in PCSEL (required by input MUX / IO):
11753fb2e24eSFabrice Gasnier  * - Only one input is selected for single ended (e.g. 'vinp')
11763fb2e24eSFabrice Gasnier  * - Two inputs are selected for differential channels (e.g. 'vinp' & 'vinn')
117795e339b6SFabrice Gasnier  */
1178cd64d357SAlexandru Ardelean static int stm32h7_adc_prepare(struct iio_dev *indio_dev)
117995e339b6SFabrice Gasnier {
1180cd64d357SAlexandru Ardelean 	struct stm32_adc *adc = iio_priv(indio_dev);
11819d901e35SOlivier Moysan 	int lincal_done = false;
11829d901e35SOlivier Moysan 	int ret;
118395e339b6SFabrice Gasnier 
1184cd64d357SAlexandru Ardelean 	ret = stm32h7_adc_exit_pwr_down(indio_dev);
1185d58c67d1SFabrice Gasnier 	if (ret)
1186d58c67d1SFabrice Gasnier 		return ret;
1187d58c67d1SFabrice Gasnier 
11889d901e35SOlivier Moysan 	if (adc->cfg->has_linearcal)
11899d901e35SOlivier Moysan 		lincal_done = stm32h7_adc_check_selfcalib(indio_dev);
11909d901e35SOlivier Moysan 
11919d901e35SOlivier Moysan 	/* Always run offset calibration. Run linear calibration only once */
11929d901e35SOlivier Moysan 	ret = stm32h7_adc_selfcalib(indio_dev, !lincal_done);
11930da98c7bSFabrice Gasnier 	if (ret < 0)
11940da98c7bSFabrice Gasnier 		goto pwr_dwn;
11950da98c7bSFabrice Gasnier 
1196aec6e0d8SOlivier Moysan 	stm32_adc_int_ch_enable(indio_dev);
1197aec6e0d8SOlivier Moysan 
1198cf0fb80aSOlivier Moysan 	stm32_adc_writel(adc, adc->cfg->regs->difsel.reg, adc->difsel);
119995e339b6SFabrice Gasnier 
1200cd64d357SAlexandru Ardelean 	ret = stm32h7_adc_enable(indio_dev);
120195e339b6SFabrice Gasnier 	if (ret)
1202aec6e0d8SOlivier Moysan 		goto ch_disable;
120395e339b6SFabrice Gasnier 
12049d901e35SOlivier Moysan 	if (adc->cfg->has_linearcal) {
12059d901e35SOlivier Moysan 		if (!adc->cal.lincal_saved)
1206cd64d357SAlexandru Ardelean 			ret = stm32h7_adc_read_selfcalib(indio_dev);
12079d901e35SOlivier Moysan 		else
12089d901e35SOlivier Moysan 			ret = stm32h7_adc_restore_selfcalib(indio_dev);
12099d901e35SOlivier Moysan 
121095e339b6SFabrice Gasnier 		if (ret)
121195e339b6SFabrice Gasnier 			goto disable;
12129d901e35SOlivier Moysan 	}
121395e339b6SFabrice Gasnier 
1214cf0fb80aSOlivier Moysan 	if (adc->cfg->has_presel)
121595e339b6SFabrice Gasnier 		stm32_adc_writel(adc, STM32H7_ADC_PCSEL, adc->pcsel);
121695e339b6SFabrice Gasnier 
121795e339b6SFabrice Gasnier 	return 0;
121895e339b6SFabrice Gasnier 
121995e339b6SFabrice Gasnier disable:
1220cd64d357SAlexandru Ardelean 	stm32h7_adc_disable(indio_dev);
1221aec6e0d8SOlivier Moysan ch_disable:
1222aec6e0d8SOlivier Moysan 	stm32_adc_int_ch_disable(adc);
122395e339b6SFabrice Gasnier pwr_dwn:
122495e339b6SFabrice Gasnier 	stm32h7_adc_enter_pwr_down(adc);
122595e339b6SFabrice Gasnier 
122695e339b6SFabrice Gasnier 	return ret;
122795e339b6SFabrice Gasnier }
122895e339b6SFabrice Gasnier 
1229cd64d357SAlexandru Ardelean static void stm32h7_adc_unprepare(struct iio_dev *indio_dev)
123095e339b6SFabrice Gasnier {
1231cd64d357SAlexandru Ardelean 	struct stm32_adc *adc = iio_priv(indio_dev);
1232cd64d357SAlexandru Ardelean 
1233cf0fb80aSOlivier Moysan 	if (adc->cfg->has_presel)
1234f711f28eSFabrice Gasnier 		stm32_adc_writel(adc, STM32H7_ADC_PCSEL, 0);
1235cd64d357SAlexandru Ardelean 	stm32h7_adc_disable(indio_dev);
1236aec6e0d8SOlivier Moysan 	stm32_adc_int_ch_disable(adc);
123795e339b6SFabrice Gasnier 	stm32h7_adc_enter_pwr_down(adc);
123895e339b6SFabrice Gasnier }
123995e339b6SFabrice Gasnier 
12400f883b22SFabrice Gasnier /**
1241da9b9485SFabrice Gasnier  * stm32_adc_conf_scan_seq() - Build regular channels scan sequence
1242da9b9485SFabrice Gasnier  * @indio_dev: IIO device
1243da9b9485SFabrice Gasnier  * @scan_mask: channels to be converted
1244da9b9485SFabrice Gasnier  *
1245da9b9485SFabrice Gasnier  * Conversion sequence :
1246ee2ac1cdSFabrice Gasnier  * Apply sampling time settings for all channels.
1247da9b9485SFabrice Gasnier  * Configure ADC scan sequence based on selected channels in scan_mask.
1248da9b9485SFabrice Gasnier  * Add channels to SQR registers, from scan_mask LSB to MSB, then
1249da9b9485SFabrice Gasnier  * program sequence len.
1250da9b9485SFabrice Gasnier  */
1251da9b9485SFabrice Gasnier static int stm32_adc_conf_scan_seq(struct iio_dev *indio_dev,
1252da9b9485SFabrice Gasnier 				   const unsigned long *scan_mask)
1253da9b9485SFabrice Gasnier {
1254da9b9485SFabrice Gasnier 	struct stm32_adc *adc = iio_priv(indio_dev);
125564ad7f64SFabrice Gasnier 	const struct stm32_adc_regs *sqr = adc->cfg->regs->sqr;
1256da9b9485SFabrice Gasnier 	const struct iio_chan_spec *chan;
1257da9b9485SFabrice Gasnier 	u32 val, bit;
1258da9b9485SFabrice Gasnier 	int i = 0;
1259da9b9485SFabrice Gasnier 
1260ee2ac1cdSFabrice Gasnier 	/* Apply sampling time settings */
1261ee2ac1cdSFabrice Gasnier 	stm32_adc_writel(adc, adc->cfg->regs->smpr[0], adc->smpr_val[0]);
1262ee2ac1cdSFabrice Gasnier 	stm32_adc_writel(adc, adc->cfg->regs->smpr[1], adc->smpr_val[1]);
1263ee2ac1cdSFabrice Gasnier 
1264da9b9485SFabrice Gasnier 	for_each_set_bit(bit, scan_mask, indio_dev->masklength) {
1265da9b9485SFabrice Gasnier 		chan = indio_dev->channels + bit;
1266da9b9485SFabrice Gasnier 		/*
1267da9b9485SFabrice Gasnier 		 * Assign one channel per SQ entry in regular
1268da9b9485SFabrice Gasnier 		 * sequence, starting with SQ1.
1269da9b9485SFabrice Gasnier 		 */
1270da9b9485SFabrice Gasnier 		i++;
1271da9b9485SFabrice Gasnier 		if (i > STM32_ADC_MAX_SQ)
1272da9b9485SFabrice Gasnier 			return -EINVAL;
1273da9b9485SFabrice Gasnier 
1274da9b9485SFabrice Gasnier 		dev_dbg(&indio_dev->dev, "%s chan %d to SQ%d\n",
1275da9b9485SFabrice Gasnier 			__func__, chan->channel, i);
1276da9b9485SFabrice Gasnier 
127764ad7f64SFabrice Gasnier 		val = stm32_adc_readl(adc, sqr[i].reg);
127864ad7f64SFabrice Gasnier 		val &= ~sqr[i].mask;
127964ad7f64SFabrice Gasnier 		val |= chan->channel << sqr[i].shift;
128064ad7f64SFabrice Gasnier 		stm32_adc_writel(adc, sqr[i].reg, val);
1281da9b9485SFabrice Gasnier 	}
1282da9b9485SFabrice Gasnier 
1283da9b9485SFabrice Gasnier 	if (!i)
1284da9b9485SFabrice Gasnier 		return -EINVAL;
1285da9b9485SFabrice Gasnier 
1286da9b9485SFabrice Gasnier 	/* Sequence len */
128764ad7f64SFabrice Gasnier 	val = stm32_adc_readl(adc, sqr[0].reg);
128864ad7f64SFabrice Gasnier 	val &= ~sqr[0].mask;
128964ad7f64SFabrice Gasnier 	val |= ((i - 1) << sqr[0].shift);
129064ad7f64SFabrice Gasnier 	stm32_adc_writel(adc, sqr[0].reg, val);
1291da9b9485SFabrice Gasnier 
1292da9b9485SFabrice Gasnier 	return 0;
1293da9b9485SFabrice Gasnier }
1294da9b9485SFabrice Gasnier 
1295da9b9485SFabrice Gasnier /**
1296da9b9485SFabrice Gasnier  * stm32_adc_get_trig_extsel() - Get external trigger selection
12971cd92d42SFabrice Gasnier  * @indio_dev: IIO device structure
1298da9b9485SFabrice Gasnier  * @trig: trigger
1299da9b9485SFabrice Gasnier  *
1300da9b9485SFabrice Gasnier  * Returns trigger extsel value, if trig matches, -EINVAL otherwise.
1301da9b9485SFabrice Gasnier  */
130264ad7f64SFabrice Gasnier static int stm32_adc_get_trig_extsel(struct iio_dev *indio_dev,
130364ad7f64SFabrice Gasnier 				     struct iio_trigger *trig)
1304da9b9485SFabrice Gasnier {
130564ad7f64SFabrice Gasnier 	struct stm32_adc *adc = iio_priv(indio_dev);
1306f24a33b3SFabrice Gasnier 	int i;
1307f24a33b3SFabrice Gasnier 
1308f24a33b3SFabrice Gasnier 	/* lookup triggers registered by stm32 timer trigger driver */
130964ad7f64SFabrice Gasnier 	for (i = 0; adc->cfg->trigs[i].name; i++) {
1310f24a33b3SFabrice Gasnier 		/**
1311f24a33b3SFabrice Gasnier 		 * Checking both stm32 timer trigger type and trig name
1312f24a33b3SFabrice Gasnier 		 * should be safe against arbitrary trigger names.
1313f24a33b3SFabrice Gasnier 		 */
1314f0b638a7SFabrice Gasnier 		if ((is_stm32_timer_trigger(trig) ||
1315f0b638a7SFabrice Gasnier 		     is_stm32_lptim_trigger(trig)) &&
131664ad7f64SFabrice Gasnier 		    !strcmp(adc->cfg->trigs[i].name, trig->name)) {
131764ad7f64SFabrice Gasnier 			return adc->cfg->trigs[i].extsel;
1318f24a33b3SFabrice Gasnier 		}
1319f24a33b3SFabrice Gasnier 	}
1320f24a33b3SFabrice Gasnier 
1321da9b9485SFabrice Gasnier 	return -EINVAL;
1322da9b9485SFabrice Gasnier }
1323da9b9485SFabrice Gasnier 
1324da9b9485SFabrice Gasnier /**
1325da9b9485SFabrice Gasnier  * stm32_adc_set_trig() - Set a regular trigger
1326da9b9485SFabrice Gasnier  * @indio_dev: IIO device
1327da9b9485SFabrice Gasnier  * @trig: IIO trigger
1328da9b9485SFabrice Gasnier  *
1329da9b9485SFabrice Gasnier  * Set trigger source/polarity (e.g. SW, or HW with polarity) :
1330da9b9485SFabrice Gasnier  * - if HW trigger disabled (e.g. trig == NULL, conversion launched by sw)
1331da9b9485SFabrice Gasnier  * - if HW trigger enabled, set source & polarity
1332da9b9485SFabrice Gasnier  */
1333da9b9485SFabrice Gasnier static int stm32_adc_set_trig(struct iio_dev *indio_dev,
1334da9b9485SFabrice Gasnier 			      struct iio_trigger *trig)
1335da9b9485SFabrice Gasnier {
1336da9b9485SFabrice Gasnier 	struct stm32_adc *adc = iio_priv(indio_dev);
1337da9b9485SFabrice Gasnier 	u32 val, extsel = 0, exten = STM32_EXTEN_SWTRIG;
1338da9b9485SFabrice Gasnier 	unsigned long flags;
1339da9b9485SFabrice Gasnier 	int ret;
1340da9b9485SFabrice Gasnier 
1341da9b9485SFabrice Gasnier 	if (trig) {
134264ad7f64SFabrice Gasnier 		ret = stm32_adc_get_trig_extsel(indio_dev, trig);
1343da9b9485SFabrice Gasnier 		if (ret < 0)
1344da9b9485SFabrice Gasnier 			return ret;
1345da9b9485SFabrice Gasnier 
1346da9b9485SFabrice Gasnier 		/* set trigger source and polarity (default to rising edge) */
1347da9b9485SFabrice Gasnier 		extsel = ret;
1348732f2dc4SFabrice Gasnier 		exten = adc->trigger_polarity + STM32_EXTEN_HWTRIG_RISING_EDGE;
1349da9b9485SFabrice Gasnier 	}
1350da9b9485SFabrice Gasnier 
1351da9b9485SFabrice Gasnier 	spin_lock_irqsave(&adc->lock, flags);
135264ad7f64SFabrice Gasnier 	val = stm32_adc_readl(adc, adc->cfg->regs->exten.reg);
135364ad7f64SFabrice Gasnier 	val &= ~(adc->cfg->regs->exten.mask | adc->cfg->regs->extsel.mask);
135464ad7f64SFabrice Gasnier 	val |= exten << adc->cfg->regs->exten.shift;
135564ad7f64SFabrice Gasnier 	val |= extsel << adc->cfg->regs->extsel.shift;
135664ad7f64SFabrice Gasnier 	stm32_adc_writel(adc,  adc->cfg->regs->exten.reg, val);
1357da9b9485SFabrice Gasnier 	spin_unlock_irqrestore(&adc->lock, flags);
1358da9b9485SFabrice Gasnier 
1359da9b9485SFabrice Gasnier 	return 0;
1360da9b9485SFabrice Gasnier }
1361da9b9485SFabrice Gasnier 
1362732f2dc4SFabrice Gasnier static int stm32_adc_set_trig_pol(struct iio_dev *indio_dev,
1363732f2dc4SFabrice Gasnier 				  const struct iio_chan_spec *chan,
1364732f2dc4SFabrice Gasnier 				  unsigned int type)
1365732f2dc4SFabrice Gasnier {
1366732f2dc4SFabrice Gasnier 	struct stm32_adc *adc = iio_priv(indio_dev);
1367732f2dc4SFabrice Gasnier 
1368732f2dc4SFabrice Gasnier 	adc->trigger_polarity = type;
1369732f2dc4SFabrice Gasnier 
1370732f2dc4SFabrice Gasnier 	return 0;
1371732f2dc4SFabrice Gasnier }
1372732f2dc4SFabrice Gasnier 
1373732f2dc4SFabrice Gasnier static int stm32_adc_get_trig_pol(struct iio_dev *indio_dev,
1374732f2dc4SFabrice Gasnier 				  const struct iio_chan_spec *chan)
1375732f2dc4SFabrice Gasnier {
1376732f2dc4SFabrice Gasnier 	struct stm32_adc *adc = iio_priv(indio_dev);
1377732f2dc4SFabrice Gasnier 
1378732f2dc4SFabrice Gasnier 	return adc->trigger_polarity;
1379732f2dc4SFabrice Gasnier }
1380732f2dc4SFabrice Gasnier 
1381732f2dc4SFabrice Gasnier static const char * const stm32_trig_pol_items[] = {
1382732f2dc4SFabrice Gasnier 	"rising-edge", "falling-edge", "both-edges",
1383732f2dc4SFabrice Gasnier };
1384732f2dc4SFabrice Gasnier 
13852763ea05SFabrice Gasnier static const struct iio_enum stm32_adc_trig_pol = {
1386732f2dc4SFabrice Gasnier 	.items = stm32_trig_pol_items,
1387732f2dc4SFabrice Gasnier 	.num_items = ARRAY_SIZE(stm32_trig_pol_items),
1388732f2dc4SFabrice Gasnier 	.get = stm32_adc_get_trig_pol,
1389732f2dc4SFabrice Gasnier 	.set = stm32_adc_set_trig_pol,
1390732f2dc4SFabrice Gasnier };
1391732f2dc4SFabrice Gasnier 
1392da9b9485SFabrice Gasnier /**
13930f883b22SFabrice Gasnier  * stm32_adc_single_conv() - Performs a single conversion
13940f883b22SFabrice Gasnier  * @indio_dev: IIO device
13950f883b22SFabrice Gasnier  * @chan: IIO channel
13960f883b22SFabrice Gasnier  * @res: conversion result
13970f883b22SFabrice Gasnier  *
13980f883b22SFabrice Gasnier  * The function performs a single conversion on a given channel:
1399ee2ac1cdSFabrice Gasnier  * - Apply sampling time settings
14000f883b22SFabrice Gasnier  * - Program sequencer with one channel (e.g. in SQ1 with len = 1)
14010f883b22SFabrice Gasnier  * - Use SW trigger
14020f883b22SFabrice Gasnier  * - Start conversion, then wait for interrupt completion.
14030f883b22SFabrice Gasnier  */
14040f883b22SFabrice Gasnier static int stm32_adc_single_conv(struct iio_dev *indio_dev,
14050f883b22SFabrice Gasnier 				 const struct iio_chan_spec *chan,
14060f883b22SFabrice Gasnier 				 int *res)
14070f883b22SFabrice Gasnier {
14080f883b22SFabrice Gasnier 	struct stm32_adc *adc = iio_priv(indio_dev);
14099bdbb113SFabrice Gasnier 	struct device *dev = indio_dev->dev.parent;
141064ad7f64SFabrice Gasnier 	const struct stm32_adc_regspec *regs = adc->cfg->regs;
14110f883b22SFabrice Gasnier 	long timeout;
14120f883b22SFabrice Gasnier 	u32 val;
14130f883b22SFabrice Gasnier 	int ret;
14140f883b22SFabrice Gasnier 
14150f883b22SFabrice Gasnier 	reinit_completion(&adc->completion);
14160f883b22SFabrice Gasnier 
1417da9b9485SFabrice Gasnier 	adc->bufi = 0;
14180f883b22SFabrice Gasnier 
1419265028b8SJonathan Cameron 	ret = pm_runtime_resume_and_get(dev);
1420265028b8SJonathan Cameron 	if (ret < 0)
142195e339b6SFabrice Gasnier 		return ret;
142295e339b6SFabrice Gasnier 
1423ee2ac1cdSFabrice Gasnier 	/* Apply sampling time settings */
1424ee2ac1cdSFabrice Gasnier 	stm32_adc_writel(adc, regs->smpr[0], adc->smpr_val[0]);
1425ee2ac1cdSFabrice Gasnier 	stm32_adc_writel(adc, regs->smpr[1], adc->smpr_val[1]);
1426ee2ac1cdSFabrice Gasnier 
1427da9b9485SFabrice Gasnier 	/* Program chan number in regular sequence (SQ1) */
142864ad7f64SFabrice Gasnier 	val = stm32_adc_readl(adc, regs->sqr[1].reg);
142964ad7f64SFabrice Gasnier 	val &= ~regs->sqr[1].mask;
143064ad7f64SFabrice Gasnier 	val |= chan->channel << regs->sqr[1].shift;
143164ad7f64SFabrice Gasnier 	stm32_adc_writel(adc, regs->sqr[1].reg, val);
14320f883b22SFabrice Gasnier 
14330f883b22SFabrice Gasnier 	/* Set regular sequence len (0 for 1 conversion) */
143464ad7f64SFabrice Gasnier 	stm32_adc_clr_bits(adc, regs->sqr[0].reg, regs->sqr[0].mask);
14350f883b22SFabrice Gasnier 
14360f883b22SFabrice Gasnier 	/* Trigger detection disabled (conversion can be launched in SW) */
143764ad7f64SFabrice Gasnier 	stm32_adc_clr_bits(adc, regs->exten.reg, regs->exten.mask);
14380f883b22SFabrice Gasnier 
14390f883b22SFabrice Gasnier 	stm32_adc_conv_irq_enable(adc);
14400f883b22SFabrice Gasnier 
1441cd64d357SAlexandru Ardelean 	adc->cfg->start_conv(indio_dev, false);
14420f883b22SFabrice Gasnier 
14430f883b22SFabrice Gasnier 	timeout = wait_for_completion_interruptible_timeout(
14440f883b22SFabrice Gasnier 					&adc->completion, STM32_ADC_TIMEOUT);
14450f883b22SFabrice Gasnier 	if (timeout == 0) {
14460f883b22SFabrice Gasnier 		ret = -ETIMEDOUT;
14470f883b22SFabrice Gasnier 	} else if (timeout < 0) {
14480f883b22SFabrice Gasnier 		ret = timeout;
14490f883b22SFabrice Gasnier 	} else {
1450da9b9485SFabrice Gasnier 		*res = adc->buffer[0];
14510f883b22SFabrice Gasnier 		ret = IIO_VAL_INT;
14520f883b22SFabrice Gasnier 	}
14530f883b22SFabrice Gasnier 
1454cd64d357SAlexandru Ardelean 	adc->cfg->stop_conv(indio_dev);
14550f883b22SFabrice Gasnier 
14560f883b22SFabrice Gasnier 	stm32_adc_conv_irq_disable(adc);
14570f883b22SFabrice Gasnier 
14589bdbb113SFabrice Gasnier 	pm_runtime_mark_last_busy(dev);
14599bdbb113SFabrice Gasnier 	pm_runtime_put_autosuspend(dev);
146095e339b6SFabrice Gasnier 
14610f883b22SFabrice Gasnier 	return ret;
14620f883b22SFabrice Gasnier }
14630f883b22SFabrice Gasnier 
14640f883b22SFabrice Gasnier static int stm32_adc_read_raw(struct iio_dev *indio_dev,
14650f883b22SFabrice Gasnier 			      struct iio_chan_spec const *chan,
14660f883b22SFabrice Gasnier 			      int *val, int *val2, long mask)
14670f883b22SFabrice Gasnier {
14680f883b22SFabrice Gasnier 	struct stm32_adc *adc = iio_priv(indio_dev);
14690f883b22SFabrice Gasnier 	int ret;
14700f883b22SFabrice Gasnier 
14710f883b22SFabrice Gasnier 	switch (mask) {
14720f883b22SFabrice Gasnier 	case IIO_CHAN_INFO_RAW:
14730e346b2cSOlivier Moysan 	case IIO_CHAN_INFO_PROCESSED:
14740f883b22SFabrice Gasnier 		ret = iio_device_claim_direct_mode(indio_dev);
14750f883b22SFabrice Gasnier 		if (ret)
14760f883b22SFabrice Gasnier 			return ret;
14770f883b22SFabrice Gasnier 		if (chan->type == IIO_VOLTAGE)
14780f883b22SFabrice Gasnier 			ret = stm32_adc_single_conv(indio_dev, chan, val);
14790f883b22SFabrice Gasnier 		else
14800f883b22SFabrice Gasnier 			ret = -EINVAL;
14810e346b2cSOlivier Moysan 
1482bc05f30fSOlivier Moysan 		if (mask == IIO_CHAN_INFO_PROCESSED)
14830e346b2cSOlivier Moysan 			*val = STM32_ADC_VREFINT_VOLTAGE * adc->vrefint.vrefint_cal / *val;
14840e346b2cSOlivier Moysan 
14850f883b22SFabrice Gasnier 		iio_device_release_direct_mode(indio_dev);
14860f883b22SFabrice Gasnier 		return ret;
14870f883b22SFabrice Gasnier 
14880f883b22SFabrice Gasnier 	case IIO_CHAN_INFO_SCALE:
14893fb2e24eSFabrice Gasnier 		if (chan->differential) {
14903fb2e24eSFabrice Gasnier 			*val = adc->common->vref_mv * 2;
14913fb2e24eSFabrice Gasnier 			*val2 = chan->scan_type.realbits;
14923fb2e24eSFabrice Gasnier 		} else {
14930f883b22SFabrice Gasnier 			*val = adc->common->vref_mv;
14940f883b22SFabrice Gasnier 			*val2 = chan->scan_type.realbits;
14953fb2e24eSFabrice Gasnier 		}
14960f883b22SFabrice Gasnier 		return IIO_VAL_FRACTIONAL_LOG2;
14970f883b22SFabrice Gasnier 
14983fb2e24eSFabrice Gasnier 	case IIO_CHAN_INFO_OFFSET:
14993fb2e24eSFabrice Gasnier 		if (chan->differential)
15003fb2e24eSFabrice Gasnier 			/* ADC_full_scale / 2 */
15013fb2e24eSFabrice Gasnier 			*val = -((1 << chan->scan_type.realbits) / 2);
15023fb2e24eSFabrice Gasnier 		else
15033fb2e24eSFabrice Gasnier 			*val = 0;
15043fb2e24eSFabrice Gasnier 		return IIO_VAL_INT;
15053fb2e24eSFabrice Gasnier 
15060f883b22SFabrice Gasnier 	default:
15070f883b22SFabrice Gasnier 		return -EINVAL;
15080f883b22SFabrice Gasnier 	}
15090f883b22SFabrice Gasnier }
15100f883b22SFabrice Gasnier 
1511695e2f5cSOlivier Moysan static void stm32_adc_irq_clear(struct iio_dev *indio_dev, u32 msk)
1512695e2f5cSOlivier Moysan {
1513695e2f5cSOlivier Moysan 	struct stm32_adc *adc = iio_priv(indio_dev);
1514695e2f5cSOlivier Moysan 
1515695e2f5cSOlivier Moysan 	adc->cfg->irq_clear(indio_dev, msk);
1516695e2f5cSOlivier Moysan }
1517695e2f5cSOlivier Moysan 
1518cc06e67dSFabrice Gasnier static irqreturn_t stm32_adc_threaded_isr(int irq, void *data)
1519cc06e67dSFabrice Gasnier {
1520cd64d357SAlexandru Ardelean 	struct iio_dev *indio_dev = data;
1521cd64d357SAlexandru Ardelean 	struct stm32_adc *adc = iio_priv(indio_dev);
1522cc06e67dSFabrice Gasnier 	const struct stm32_adc_regspec *regs = adc->cfg->regs;
1523cc06e67dSFabrice Gasnier 	u32 status = stm32_adc_readl(adc, regs->isr_eoc.reg);
1524cc06e67dSFabrice Gasnier 
1525695e2f5cSOlivier Moysan 	/* Check ovr status right now, as ovr mask should be already disabled */
1526695e2f5cSOlivier Moysan 	if (status & regs->isr_ovr.mask) {
1527695e2f5cSOlivier Moysan 		/*
1528695e2f5cSOlivier Moysan 		 * Clear ovr bit to avoid subsequent calls to IRQ handler.
1529695e2f5cSOlivier Moysan 		 * This requires to stop ADC first. OVR bit state in ISR,
1530695e2f5cSOlivier Moysan 		 * is propaged to CSR register by hardware.
1531695e2f5cSOlivier Moysan 		 */
1532695e2f5cSOlivier Moysan 		adc->cfg->stop_conv(indio_dev);
1533695e2f5cSOlivier Moysan 		stm32_adc_irq_clear(indio_dev, regs->isr_ovr.mask);
1534cc06e67dSFabrice Gasnier 		dev_err(&indio_dev->dev, "Overrun, stopping: restart needed\n");
1535cc06e67dSFabrice Gasnier 		return IRQ_HANDLED;
1536cc06e67dSFabrice Gasnier 	}
1537cc06e67dSFabrice Gasnier 
1538695e2f5cSOlivier Moysan 	return IRQ_NONE;
1539695e2f5cSOlivier Moysan }
1540695e2f5cSOlivier Moysan 
15410f883b22SFabrice Gasnier static irqreturn_t stm32_adc_isr(int irq, void *data)
15420f883b22SFabrice Gasnier {
1543cd64d357SAlexandru Ardelean 	struct iio_dev *indio_dev = data;
1544cd64d357SAlexandru Ardelean 	struct stm32_adc *adc = iio_priv(indio_dev);
154564ad7f64SFabrice Gasnier 	const struct stm32_adc_regspec *regs = adc->cfg->regs;
154664ad7f64SFabrice Gasnier 	u32 status = stm32_adc_readl(adc, regs->isr_eoc.reg);
15470f883b22SFabrice Gasnier 
1548cc06e67dSFabrice Gasnier 	if (status & regs->isr_ovr.mask) {
1549cc06e67dSFabrice Gasnier 		/*
1550cc06e67dSFabrice Gasnier 		 * Overrun occurred on regular conversions: data for wrong
1551cc06e67dSFabrice Gasnier 		 * channel may be read. Unconditionally disable interrupts
1552cc06e67dSFabrice Gasnier 		 * to stop processing data and print error message.
1553cc06e67dSFabrice Gasnier 		 * Restarting the capture can be done by disabling, then
1554cc06e67dSFabrice Gasnier 		 * re-enabling it (e.g. write 0, then 1 to buffer/enable).
1555cc06e67dSFabrice Gasnier 		 */
1556cc06e67dSFabrice Gasnier 		stm32_adc_ovr_irq_disable(adc);
1557cc06e67dSFabrice Gasnier 		stm32_adc_conv_irq_disable(adc);
1558cc06e67dSFabrice Gasnier 		return IRQ_WAKE_THREAD;
1559cc06e67dSFabrice Gasnier 	}
1560cc06e67dSFabrice Gasnier 
156164ad7f64SFabrice Gasnier 	if (status & regs->isr_eoc.mask) {
1562da9b9485SFabrice Gasnier 		/* Reading DR also clears EOC status flag */
156364ad7f64SFabrice Gasnier 		adc->buffer[adc->bufi] = stm32_adc_readw(adc, regs->dr);
1564da9b9485SFabrice Gasnier 		if (iio_buffer_enabled(indio_dev)) {
1565da9b9485SFabrice Gasnier 			adc->bufi++;
1566da9b9485SFabrice Gasnier 			if (adc->bufi >= adc->num_conv) {
1567da9b9485SFabrice Gasnier 				stm32_adc_conv_irq_disable(adc);
1568da9b9485SFabrice Gasnier 				iio_trigger_poll(indio_dev->trig);
1569da9b9485SFabrice Gasnier 			}
1570da9b9485SFabrice Gasnier 		} else {
15710f883b22SFabrice Gasnier 			complete(&adc->completion);
1572da9b9485SFabrice Gasnier 		}
15730f883b22SFabrice Gasnier 		return IRQ_HANDLED;
15740f883b22SFabrice Gasnier 	}
15750f883b22SFabrice Gasnier 
15760f883b22SFabrice Gasnier 	return IRQ_NONE;
15770f883b22SFabrice Gasnier }
15780f883b22SFabrice Gasnier 
1579da9b9485SFabrice Gasnier /**
1580da9b9485SFabrice Gasnier  * stm32_adc_validate_trigger() - validate trigger for stm32 adc
1581da9b9485SFabrice Gasnier  * @indio_dev: IIO device
1582da9b9485SFabrice Gasnier  * @trig: new trigger
1583da9b9485SFabrice Gasnier  *
1584da9b9485SFabrice Gasnier  * Returns: 0 if trig matches one of the triggers registered by stm32 adc
1585da9b9485SFabrice Gasnier  * driver, -EINVAL otherwise.
1586da9b9485SFabrice Gasnier  */
1587da9b9485SFabrice Gasnier static int stm32_adc_validate_trigger(struct iio_dev *indio_dev,
1588da9b9485SFabrice Gasnier 				      struct iio_trigger *trig)
1589da9b9485SFabrice Gasnier {
159064ad7f64SFabrice Gasnier 	return stm32_adc_get_trig_extsel(indio_dev, trig) < 0 ? -EINVAL : 0;
1591da9b9485SFabrice Gasnier }
1592da9b9485SFabrice Gasnier 
15932763ea05SFabrice Gasnier static int stm32_adc_set_watermark(struct iio_dev *indio_dev, unsigned int val)
15942763ea05SFabrice Gasnier {
15952763ea05SFabrice Gasnier 	struct stm32_adc *adc = iio_priv(indio_dev);
15962763ea05SFabrice Gasnier 	unsigned int watermark = STM32_DMA_BUFFER_SIZE / 2;
159704e491caSFabrice Gasnier 	unsigned int rx_buf_sz = STM32_DMA_BUFFER_SIZE;
15982763ea05SFabrice Gasnier 
15992763ea05SFabrice Gasnier 	/*
16002763ea05SFabrice Gasnier 	 * dma cyclic transfers are used, buffer is split into two periods.
16012763ea05SFabrice Gasnier 	 * There should be :
16022763ea05SFabrice Gasnier 	 * - always one buffer (period) dma is working on
1603499da8bdSOlivier Moysan 	 * - one buffer (period) driver can push data.
16042763ea05SFabrice Gasnier 	 */
16052763ea05SFabrice Gasnier 	watermark = min(watermark, val * (unsigned)(sizeof(u16)));
160604e491caSFabrice Gasnier 	adc->rx_buf_sz = min(rx_buf_sz, watermark * 2 * adc->num_conv);
16072763ea05SFabrice Gasnier 
16082763ea05SFabrice Gasnier 	return 0;
16092763ea05SFabrice Gasnier }
16102763ea05SFabrice Gasnier 
1611da9b9485SFabrice Gasnier static int stm32_adc_update_scan_mode(struct iio_dev *indio_dev,
1612da9b9485SFabrice Gasnier 				      const unsigned long *scan_mask)
1613da9b9485SFabrice Gasnier {
1614da9b9485SFabrice Gasnier 	struct stm32_adc *adc = iio_priv(indio_dev);
16159bdbb113SFabrice Gasnier 	struct device *dev = indio_dev->dev.parent;
1616da9b9485SFabrice Gasnier 	int ret;
1617da9b9485SFabrice Gasnier 
1618265028b8SJonathan Cameron 	ret = pm_runtime_resume_and_get(dev);
1619265028b8SJonathan Cameron 	if (ret < 0)
16209bdbb113SFabrice Gasnier 		return ret;
16219bdbb113SFabrice Gasnier 
1622da9b9485SFabrice Gasnier 	adc->num_conv = bitmap_weight(scan_mask, indio_dev->masklength);
1623da9b9485SFabrice Gasnier 
1624da9b9485SFabrice Gasnier 	ret = stm32_adc_conf_scan_seq(indio_dev, scan_mask);
16259bdbb113SFabrice Gasnier 	pm_runtime_mark_last_busy(dev);
16269bdbb113SFabrice Gasnier 	pm_runtime_put_autosuspend(dev);
1627da9b9485SFabrice Gasnier 
16289bdbb113SFabrice Gasnier 	return ret;
1629da9b9485SFabrice Gasnier }
1630da9b9485SFabrice Gasnier 
1631d7705f35SNuno Sá static int stm32_adc_fwnode_xlate(struct iio_dev *indio_dev,
1632d7705f35SNuno Sá 				  const struct fwnode_reference_args *iiospec)
16330f883b22SFabrice Gasnier {
16340f883b22SFabrice Gasnier 	int i;
16350f883b22SFabrice Gasnier 
16360f883b22SFabrice Gasnier 	for (i = 0; i < indio_dev->num_channels; i++)
16370f883b22SFabrice Gasnier 		if (indio_dev->channels[i].channel == iiospec->args[0])
16380f883b22SFabrice Gasnier 			return i;
16390f883b22SFabrice Gasnier 
16400f883b22SFabrice Gasnier 	return -EINVAL;
16410f883b22SFabrice Gasnier }
16420f883b22SFabrice Gasnier 
16430f883b22SFabrice Gasnier /**
16440f883b22SFabrice Gasnier  * stm32_adc_debugfs_reg_access - read or write register value
16451cd92d42SFabrice Gasnier  * @indio_dev: IIO device structure
16461cd92d42SFabrice Gasnier  * @reg: register offset
16471cd92d42SFabrice Gasnier  * @writeval: value to write
16481cd92d42SFabrice Gasnier  * @readval: value to read
16490f883b22SFabrice Gasnier  *
16500f883b22SFabrice Gasnier  * To read a value from an ADC register:
16510f883b22SFabrice Gasnier  *   echo [ADC reg offset] > direct_reg_access
16520f883b22SFabrice Gasnier  *   cat direct_reg_access
16530f883b22SFabrice Gasnier  *
16540f883b22SFabrice Gasnier  * To write a value in a ADC register:
16550f883b22SFabrice Gasnier  *   echo [ADC_reg_offset] [value] > direct_reg_access
16560f883b22SFabrice Gasnier  */
16570f883b22SFabrice Gasnier static int stm32_adc_debugfs_reg_access(struct iio_dev *indio_dev,
16580f883b22SFabrice Gasnier 					unsigned reg, unsigned writeval,
16590f883b22SFabrice Gasnier 					unsigned *readval)
16600f883b22SFabrice Gasnier {
16610f883b22SFabrice Gasnier 	struct stm32_adc *adc = iio_priv(indio_dev);
16629bdbb113SFabrice Gasnier 	struct device *dev = indio_dev->dev.parent;
16639bdbb113SFabrice Gasnier 	int ret;
16649bdbb113SFabrice Gasnier 
1665265028b8SJonathan Cameron 	ret = pm_runtime_resume_and_get(dev);
1666265028b8SJonathan Cameron 	if (ret < 0)
16679bdbb113SFabrice Gasnier 		return ret;
16680f883b22SFabrice Gasnier 
16690f883b22SFabrice Gasnier 	if (!readval)
16700f883b22SFabrice Gasnier 		stm32_adc_writel(adc, reg, writeval);
16710f883b22SFabrice Gasnier 	else
16720f883b22SFabrice Gasnier 		*readval = stm32_adc_readl(adc, reg);
16730f883b22SFabrice Gasnier 
16749bdbb113SFabrice Gasnier 	pm_runtime_mark_last_busy(dev);
16759bdbb113SFabrice Gasnier 	pm_runtime_put_autosuspend(dev);
16769bdbb113SFabrice Gasnier 
16770f883b22SFabrice Gasnier 	return 0;
16780f883b22SFabrice Gasnier }
16790f883b22SFabrice Gasnier 
16800f883b22SFabrice Gasnier static const struct iio_info stm32_adc_iio_info = {
16810f883b22SFabrice Gasnier 	.read_raw = stm32_adc_read_raw,
1682da9b9485SFabrice Gasnier 	.validate_trigger = stm32_adc_validate_trigger,
16832763ea05SFabrice Gasnier 	.hwfifo_set_watermark = stm32_adc_set_watermark,
1684da9b9485SFabrice Gasnier 	.update_scan_mode = stm32_adc_update_scan_mode,
16850f883b22SFabrice Gasnier 	.debugfs_reg_access = stm32_adc_debugfs_reg_access,
1686d7705f35SNuno Sá 	.fwnode_xlate = stm32_adc_fwnode_xlate,
16870f883b22SFabrice Gasnier };
16880f883b22SFabrice Gasnier 
16892763ea05SFabrice Gasnier static unsigned int stm32_adc_dma_residue(struct stm32_adc *adc)
16902763ea05SFabrice Gasnier {
16912763ea05SFabrice Gasnier 	struct dma_tx_state state;
16922763ea05SFabrice Gasnier 	enum dma_status status;
16932763ea05SFabrice Gasnier 
16942763ea05SFabrice Gasnier 	status = dmaengine_tx_status(adc->dma_chan,
16952763ea05SFabrice Gasnier 				     adc->dma_chan->cookie,
16962763ea05SFabrice Gasnier 				     &state);
16972763ea05SFabrice Gasnier 	if (status == DMA_IN_PROGRESS) {
16982763ea05SFabrice Gasnier 		/* Residue is size in bytes from end of buffer */
16992763ea05SFabrice Gasnier 		unsigned int i = adc->rx_buf_sz - state.residue;
17002763ea05SFabrice Gasnier 		unsigned int size;
17012763ea05SFabrice Gasnier 
17022763ea05SFabrice Gasnier 		/* Return available bytes */
17032763ea05SFabrice Gasnier 		if (i >= adc->bufi)
17042763ea05SFabrice Gasnier 			size = i - adc->bufi;
17052763ea05SFabrice Gasnier 		else
17062763ea05SFabrice Gasnier 			size = adc->rx_buf_sz + i - adc->bufi;
17072763ea05SFabrice Gasnier 
17082763ea05SFabrice Gasnier 		return size;
17092763ea05SFabrice Gasnier 	}
17102763ea05SFabrice Gasnier 
17112763ea05SFabrice Gasnier 	return 0;
17122763ea05SFabrice Gasnier }
17132763ea05SFabrice Gasnier 
17142763ea05SFabrice Gasnier static void stm32_adc_dma_buffer_done(void *data)
17152763ea05SFabrice Gasnier {
17162763ea05SFabrice Gasnier 	struct iio_dev *indio_dev = data;
1717e2042d29SOlivier Moysan 	struct stm32_adc *adc = iio_priv(indio_dev);
1718e2042d29SOlivier Moysan 	int residue = stm32_adc_dma_residue(adc);
17192763ea05SFabrice Gasnier 
1720e2042d29SOlivier Moysan 	/*
1721e2042d29SOlivier Moysan 	 * In DMA mode the trigger services of IIO are not used
1722e2042d29SOlivier Moysan 	 * (e.g. no call to iio_trigger_poll).
1723e2042d29SOlivier Moysan 	 * Calling irq handler associated to the hardware trigger is not
1724e2042d29SOlivier Moysan 	 * relevant as the conversions have already been done. Data
1725e2042d29SOlivier Moysan 	 * transfers are performed directly in DMA callback instead.
1726e2042d29SOlivier Moysan 	 * This implementation avoids to call trigger irq handler that
1727e2042d29SOlivier Moysan 	 * may sleep, in an atomic context (DMA irq handler context).
1728e2042d29SOlivier Moysan 	 */
1729e2042d29SOlivier Moysan 	dev_dbg(&indio_dev->dev, "%s bufi=%d\n", __func__, adc->bufi);
1730e2042d29SOlivier Moysan 
1731e2042d29SOlivier Moysan 	while (residue >= indio_dev->scan_bytes) {
1732e2042d29SOlivier Moysan 		u16 *buffer = (u16 *)&adc->rx_buf[adc->bufi];
1733e2042d29SOlivier Moysan 
1734e2042d29SOlivier Moysan 		iio_push_to_buffers(indio_dev, buffer);
1735e2042d29SOlivier Moysan 
1736e2042d29SOlivier Moysan 		residue -= indio_dev->scan_bytes;
1737e2042d29SOlivier Moysan 		adc->bufi += indio_dev->scan_bytes;
1738e2042d29SOlivier Moysan 		if (adc->bufi >= adc->rx_buf_sz)
1739e2042d29SOlivier Moysan 			adc->bufi = 0;
1740e2042d29SOlivier Moysan 	}
17412763ea05SFabrice Gasnier }
17422763ea05SFabrice Gasnier 
17432763ea05SFabrice Gasnier static int stm32_adc_dma_start(struct iio_dev *indio_dev)
17442763ea05SFabrice Gasnier {
17452763ea05SFabrice Gasnier 	struct stm32_adc *adc = iio_priv(indio_dev);
17462763ea05SFabrice Gasnier 	struct dma_async_tx_descriptor *desc;
17472763ea05SFabrice Gasnier 	dma_cookie_t cookie;
17482763ea05SFabrice Gasnier 	int ret;
17492763ea05SFabrice Gasnier 
17502763ea05SFabrice Gasnier 	if (!adc->dma_chan)
17512763ea05SFabrice Gasnier 		return 0;
17522763ea05SFabrice Gasnier 
17532763ea05SFabrice Gasnier 	dev_dbg(&indio_dev->dev, "%s size=%d watermark=%d\n", __func__,
17542763ea05SFabrice Gasnier 		adc->rx_buf_sz, adc->rx_buf_sz / 2);
17552763ea05SFabrice Gasnier 
17562763ea05SFabrice Gasnier 	/* Prepare a DMA cyclic transaction */
17572763ea05SFabrice Gasnier 	desc = dmaengine_prep_dma_cyclic(adc->dma_chan,
17582763ea05SFabrice Gasnier 					 adc->rx_dma_buf,
17592763ea05SFabrice Gasnier 					 adc->rx_buf_sz, adc->rx_buf_sz / 2,
17602763ea05SFabrice Gasnier 					 DMA_DEV_TO_MEM,
17612763ea05SFabrice Gasnier 					 DMA_PREP_INTERRUPT);
17622763ea05SFabrice Gasnier 	if (!desc)
17632763ea05SFabrice Gasnier 		return -EBUSY;
17642763ea05SFabrice Gasnier 
17652763ea05SFabrice Gasnier 	desc->callback = stm32_adc_dma_buffer_done;
17662763ea05SFabrice Gasnier 	desc->callback_param = indio_dev;
17672763ea05SFabrice Gasnier 
17682763ea05SFabrice Gasnier 	cookie = dmaengine_submit(desc);
17692763ea05SFabrice Gasnier 	ret = dma_submit_error(cookie);
17702763ea05SFabrice Gasnier 	if (ret) {
1771e6afcf6cSFabrice Gasnier 		dmaengine_terminate_sync(adc->dma_chan);
17722763ea05SFabrice Gasnier 		return ret;
17732763ea05SFabrice Gasnier 	}
17742763ea05SFabrice Gasnier 
17752763ea05SFabrice Gasnier 	/* Issue pending DMA requests */
17762763ea05SFabrice Gasnier 	dma_async_issue_pending(adc->dma_chan);
17772763ea05SFabrice Gasnier 
17782763ea05SFabrice Gasnier 	return 0;
17792763ea05SFabrice Gasnier }
17802763ea05SFabrice Gasnier 
1781f11d59d8SLars-Peter Clausen static int stm32_adc_buffer_postenable(struct iio_dev *indio_dev)
1782da9b9485SFabrice Gasnier {
1783da9b9485SFabrice Gasnier 	struct stm32_adc *adc = iio_priv(indio_dev);
17849bdbb113SFabrice Gasnier 	struct device *dev = indio_dev->dev.parent;
1785da9b9485SFabrice Gasnier 	int ret;
1786da9b9485SFabrice Gasnier 
1787265028b8SJonathan Cameron 	ret = pm_runtime_resume_and_get(dev);
1788265028b8SJonathan Cameron 	if (ret < 0)
178995e339b6SFabrice Gasnier 		return ret;
179095e339b6SFabrice Gasnier 
1791da9b9485SFabrice Gasnier 	ret = stm32_adc_set_trig(indio_dev, indio_dev->trig);
1792da9b9485SFabrice Gasnier 	if (ret) {
1793da9b9485SFabrice Gasnier 		dev_err(&indio_dev->dev, "Can't set trigger\n");
17949bdbb113SFabrice Gasnier 		goto err_pm_put;
1795da9b9485SFabrice Gasnier 	}
1796da9b9485SFabrice Gasnier 
17972763ea05SFabrice Gasnier 	ret = stm32_adc_dma_start(indio_dev);
17982763ea05SFabrice Gasnier 	if (ret) {
17992763ea05SFabrice Gasnier 		dev_err(&indio_dev->dev, "Can't start dma\n");
18002763ea05SFabrice Gasnier 		goto err_clr_trig;
18012763ea05SFabrice Gasnier 	}
18022763ea05SFabrice Gasnier 
1803da9b9485SFabrice Gasnier 	/* Reset adc buffer index */
1804da9b9485SFabrice Gasnier 	adc->bufi = 0;
1805da9b9485SFabrice Gasnier 
1806cc06e67dSFabrice Gasnier 	stm32_adc_ovr_irq_enable(adc);
1807cc06e67dSFabrice Gasnier 
18082763ea05SFabrice Gasnier 	if (!adc->dma_chan)
1809da9b9485SFabrice Gasnier 		stm32_adc_conv_irq_enable(adc);
18102763ea05SFabrice Gasnier 
1811cd64d357SAlexandru Ardelean 	adc->cfg->start_conv(indio_dev, !!adc->dma_chan);
1812da9b9485SFabrice Gasnier 
1813da9b9485SFabrice Gasnier 	return 0;
1814da9b9485SFabrice Gasnier 
1815da9b9485SFabrice Gasnier err_clr_trig:
1816da9b9485SFabrice Gasnier 	stm32_adc_set_trig(indio_dev, NULL);
18179bdbb113SFabrice Gasnier err_pm_put:
18189bdbb113SFabrice Gasnier 	pm_runtime_mark_last_busy(dev);
18199bdbb113SFabrice Gasnier 	pm_runtime_put_autosuspend(dev);
1820da9b9485SFabrice Gasnier 
1821da9b9485SFabrice Gasnier 	return ret;
1822da9b9485SFabrice Gasnier }
1823da9b9485SFabrice Gasnier 
1824f11d59d8SLars-Peter Clausen static int stm32_adc_buffer_predisable(struct iio_dev *indio_dev)
1825da9b9485SFabrice Gasnier {
1826da9b9485SFabrice Gasnier 	struct stm32_adc *adc = iio_priv(indio_dev);
18279bdbb113SFabrice Gasnier 	struct device *dev = indio_dev->dev.parent;
1828da9b9485SFabrice Gasnier 
1829cd64d357SAlexandru Ardelean 	adc->cfg->stop_conv(indio_dev);
18302763ea05SFabrice Gasnier 	if (!adc->dma_chan)
1831da9b9485SFabrice Gasnier 		stm32_adc_conv_irq_disable(adc);
1832da9b9485SFabrice Gasnier 
1833cc06e67dSFabrice Gasnier 	stm32_adc_ovr_irq_disable(adc);
1834cc06e67dSFabrice Gasnier 
18352763ea05SFabrice Gasnier 	if (adc->dma_chan)
1836e6afcf6cSFabrice Gasnier 		dmaengine_terminate_sync(adc->dma_chan);
18372763ea05SFabrice Gasnier 
1838da9b9485SFabrice Gasnier 	if (stm32_adc_set_trig(indio_dev, NULL))
1839da9b9485SFabrice Gasnier 		dev_err(&indio_dev->dev, "Can't clear trigger\n");
1840da9b9485SFabrice Gasnier 
18419bdbb113SFabrice Gasnier 	pm_runtime_mark_last_busy(dev);
18429bdbb113SFabrice Gasnier 	pm_runtime_put_autosuspend(dev);
184349ad8d28SFabrice Gasnier 
1844f11d59d8SLars-Peter Clausen 	return 0;
1845da9b9485SFabrice Gasnier }
1846da9b9485SFabrice Gasnier 
1847da9b9485SFabrice Gasnier static const struct iio_buffer_setup_ops stm32_adc_buffer_setup_ops = {
1848da9b9485SFabrice Gasnier 	.postenable = &stm32_adc_buffer_postenable,
1849da9b9485SFabrice Gasnier 	.predisable = &stm32_adc_buffer_predisable,
1850da9b9485SFabrice Gasnier };
1851da9b9485SFabrice Gasnier 
1852da9b9485SFabrice Gasnier static irqreturn_t stm32_adc_trigger_handler(int irq, void *p)
1853da9b9485SFabrice Gasnier {
1854da9b9485SFabrice Gasnier 	struct iio_poll_func *pf = p;
1855da9b9485SFabrice Gasnier 	struct iio_dev *indio_dev = pf->indio_dev;
1856da9b9485SFabrice Gasnier 	struct stm32_adc *adc = iio_priv(indio_dev);
1857da9b9485SFabrice Gasnier 
1858da9b9485SFabrice Gasnier 	dev_dbg(&indio_dev->dev, "%s bufi=%d\n", __func__, adc->bufi);
1859da9b9485SFabrice Gasnier 
1860da9b9485SFabrice Gasnier 	/* reset buffer index */
1861da9b9485SFabrice Gasnier 	adc->bufi = 0;
1862da9b9485SFabrice Gasnier 	iio_push_to_buffers_with_timestamp(indio_dev, adc->buffer,
1863da9b9485SFabrice Gasnier 					   pf->timestamp);
1864da9b9485SFabrice Gasnier 	iio_trigger_notify_done(indio_dev->trig);
1865da9b9485SFabrice Gasnier 
1866da9b9485SFabrice Gasnier 	/* re-enable eoc irq */
1867da9b9485SFabrice Gasnier 	stm32_adc_conv_irq_enable(adc);
1868da9b9485SFabrice Gasnier 
1869da9b9485SFabrice Gasnier 	return IRQ_HANDLED;
1870da9b9485SFabrice Gasnier }
1871da9b9485SFabrice Gasnier 
1872732f2dc4SFabrice Gasnier static const struct iio_chan_spec_ext_info stm32_adc_ext_info[] = {
1873732f2dc4SFabrice Gasnier 	IIO_ENUM("trigger_polarity", IIO_SHARED_BY_ALL, &stm32_adc_trig_pol),
1874732f2dc4SFabrice Gasnier 	{
1875732f2dc4SFabrice Gasnier 		.name = "trigger_polarity_available",
1876732f2dc4SFabrice Gasnier 		.shared = IIO_SHARED_BY_ALL,
1877732f2dc4SFabrice Gasnier 		.read = iio_enum_available_read,
1878732f2dc4SFabrice Gasnier 		.private = (uintptr_t)&stm32_adc_trig_pol,
1879732f2dc4SFabrice Gasnier 	},
1880732f2dc4SFabrice Gasnier 	{},
1881732f2dc4SFabrice Gasnier };
1882732f2dc4SFabrice Gasnier 
188351bcacc6SOlivier Moysan static void stm32_adc_debugfs_init(struct iio_dev *indio_dev)
188451bcacc6SOlivier Moysan {
188551bcacc6SOlivier Moysan 	struct stm32_adc *adc = iio_priv(indio_dev);
188651bcacc6SOlivier Moysan 	struct dentry *d = iio_get_debugfs_dentry(indio_dev);
188751bcacc6SOlivier Moysan 	struct stm32_adc_calib *cal = &adc->cal;
188851bcacc6SOlivier Moysan 	char buf[16];
188951bcacc6SOlivier Moysan 	unsigned int i;
189051bcacc6SOlivier Moysan 
189151bcacc6SOlivier Moysan 	if (!adc->cfg->has_linearcal)
189251bcacc6SOlivier Moysan 		return;
189351bcacc6SOlivier Moysan 
189451bcacc6SOlivier Moysan 	for (i = 0; i < STM32H7_LINCALFACT_NUM; i++) {
189551bcacc6SOlivier Moysan 		snprintf(buf, sizeof(buf), "lincalfact%d", i + 1);
189651bcacc6SOlivier Moysan 		debugfs_create_u32(buf, 0444, d, &cal->lincalfact[i]);
189751bcacc6SOlivier Moysan 	}
189851bcacc6SOlivier Moysan }
189951bcacc6SOlivier Moysan 
1900d7705f35SNuno Sá static int stm32_adc_fw_get_resolution(struct iio_dev *indio_dev)
190125a85bedSFabrice Gasnier {
1902d7705f35SNuno Sá 	struct device *dev = &indio_dev->dev;
190325a85bedSFabrice Gasnier 	struct stm32_adc *adc = iio_priv(indio_dev);
190425a85bedSFabrice Gasnier 	unsigned int i;
190525a85bedSFabrice Gasnier 	u32 res;
190625a85bedSFabrice Gasnier 
1907d7705f35SNuno Sá 	if (device_property_read_u32(dev, "assigned-resolution-bits", &res))
190864ad7f64SFabrice Gasnier 		res = adc->cfg->adc_info->resolutions[0];
190925a85bedSFabrice Gasnier 
191064ad7f64SFabrice Gasnier 	for (i = 0; i < adc->cfg->adc_info->num_res; i++)
191164ad7f64SFabrice Gasnier 		if (res == adc->cfg->adc_info->resolutions[i])
191225a85bedSFabrice Gasnier 			break;
191364ad7f64SFabrice Gasnier 	if (i >= adc->cfg->adc_info->num_res) {
191425a85bedSFabrice Gasnier 		dev_err(&indio_dev->dev, "Bad resolution: %u bits\n", res);
191525a85bedSFabrice Gasnier 		return -EINVAL;
191625a85bedSFabrice Gasnier 	}
191725a85bedSFabrice Gasnier 
191825a85bedSFabrice Gasnier 	dev_dbg(&indio_dev->dev, "Using %u bits resolution\n", res);
191925a85bedSFabrice Gasnier 	adc->res = i;
192025a85bedSFabrice Gasnier 
192125a85bedSFabrice Gasnier 	return 0;
192225a85bedSFabrice Gasnier }
192325a85bedSFabrice Gasnier 
1924ee2ac1cdSFabrice Gasnier static void stm32_adc_smpr_init(struct stm32_adc *adc, int channel, u32 smp_ns)
1925ee2ac1cdSFabrice Gasnier {
1926ee2ac1cdSFabrice Gasnier 	const struct stm32_adc_regs *smpr = &adc->cfg->regs->smp_bits[channel];
1927ee2ac1cdSFabrice Gasnier 	u32 period_ns, shift = smpr->shift, mask = smpr->mask;
19287cb2303dSOlivier Moysan 	unsigned int i, smp, r = smpr->reg;
1929ee2ac1cdSFabrice Gasnier 
1930796e5d0bSOlivier Moysan 	/*
19317cb2303dSOlivier Moysan 	 * For internal channels, ensure that the sampling time cannot
1932796e5d0bSOlivier Moysan 	 * be lower than the one specified in the datasheet
1933796e5d0bSOlivier Moysan 	 */
19347cb2303dSOlivier Moysan 	for (i = 0; i < STM32_ADC_INT_CH_NB; i++)
19357cb2303dSOlivier Moysan 		if (channel == adc->int_ch[i] && adc->int_ch[i] != STM32_ADC_INT_CH_NONE)
19367cb2303dSOlivier Moysan 			smp_ns = max(smp_ns, adc->cfg->ts_int_ch[i]);
1937796e5d0bSOlivier Moysan 
1938ee2ac1cdSFabrice Gasnier 	/* Determine sampling time (ADC clock cycles) */
1939ee2ac1cdSFabrice Gasnier 	period_ns = NSEC_PER_SEC / adc->common->rate;
1940ee2ac1cdSFabrice Gasnier 	for (smp = 0; smp <= STM32_ADC_MAX_SMP; smp++)
1941ee2ac1cdSFabrice Gasnier 		if ((period_ns * adc->cfg->smp_cycles[smp]) >= smp_ns)
1942ee2ac1cdSFabrice Gasnier 			break;
1943ee2ac1cdSFabrice Gasnier 	if (smp > STM32_ADC_MAX_SMP)
1944ee2ac1cdSFabrice Gasnier 		smp = STM32_ADC_MAX_SMP;
1945ee2ac1cdSFabrice Gasnier 
1946ee2ac1cdSFabrice Gasnier 	/* pre-build sampling time registers (e.g. smpr1, smpr2) */
1947ee2ac1cdSFabrice Gasnier 	adc->smpr_val[r] = (adc->smpr_val[r] & ~mask) | (smp << shift);
1948ee2ac1cdSFabrice Gasnier }
1949ee2ac1cdSFabrice Gasnier 
19500f883b22SFabrice Gasnier static void stm32_adc_chan_init_one(struct iio_dev *indio_dev,
19510bae72aaSFabrice Gasnier 				    struct iio_chan_spec *chan, u32 vinp,
19523fb2e24eSFabrice Gasnier 				    u32 vinn, int scan_index, bool differential)
19530f883b22SFabrice Gasnier {
195425a85bedSFabrice Gasnier 	struct stm32_adc *adc = iio_priv(indio_dev);
19550bae72aaSFabrice Gasnier 	char *name = adc->chan_name[vinp];
195625a85bedSFabrice Gasnier 
19570bae72aaSFabrice Gasnier 	chan->type = IIO_VOLTAGE;
19580bae72aaSFabrice Gasnier 	chan->channel = vinp;
19593fb2e24eSFabrice Gasnier 	if (differential) {
19603fb2e24eSFabrice Gasnier 		chan->differential = 1;
19613fb2e24eSFabrice Gasnier 		chan->channel2 = vinn;
19623fb2e24eSFabrice Gasnier 		snprintf(name, STM32_ADC_CH_SZ, "in%d-in%d", vinp, vinn);
19633fb2e24eSFabrice Gasnier 	} else {
19640bae72aaSFabrice Gasnier 		snprintf(name, STM32_ADC_CH_SZ, "in%d", vinp);
19653fb2e24eSFabrice Gasnier 	}
19660bae72aaSFabrice Gasnier 	chan->datasheet_name = name;
19670f883b22SFabrice Gasnier 	chan->scan_index = scan_index;
19680f883b22SFabrice Gasnier 	chan->indexed = 1;
19690e346b2cSOlivier Moysan 	if (chan->channel == adc->int_ch[STM32_ADC_INT_CH_VREFINT])
19700e346b2cSOlivier Moysan 		chan->info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED);
19710e346b2cSOlivier Moysan 	else
19720f883b22SFabrice Gasnier 		chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
19733fb2e24eSFabrice Gasnier 	chan->info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |
19743fb2e24eSFabrice Gasnier 					 BIT(IIO_CHAN_INFO_OFFSET);
19750f883b22SFabrice Gasnier 	chan->scan_type.sign = 'u';
197664ad7f64SFabrice Gasnier 	chan->scan_type.realbits = adc->cfg->adc_info->resolutions[adc->res];
19770f883b22SFabrice Gasnier 	chan->scan_type.storagebits = 16;
1978732f2dc4SFabrice Gasnier 	chan->ext_info = stm32_adc_ext_info;
197995e339b6SFabrice Gasnier 
198095e339b6SFabrice Gasnier 	/* pre-build selected channels mask */
198195e339b6SFabrice Gasnier 	adc->pcsel |= BIT(chan->channel);
19823fb2e24eSFabrice Gasnier 	if (differential) {
19833fb2e24eSFabrice Gasnier 		/* pre-build diff channels mask */
1984cf0fb80aSOlivier Moysan 		adc->difsel |= BIT(chan->channel) & adc->cfg->regs->difsel.mask;
19853fb2e24eSFabrice Gasnier 		/* Also add negative input to pre-selected channels */
19863fb2e24eSFabrice Gasnier 		adc->pcsel |= BIT(chan->channel2);
19873fb2e24eSFabrice Gasnier 	}
19880f883b22SFabrice Gasnier }
19890f883b22SFabrice Gasnier 
199045571a36SOlivier Moysan static int stm32_adc_get_legacy_chan_count(struct iio_dev *indio_dev, struct stm32_adc *adc)
19910f883b22SFabrice Gasnier {
1992d7705f35SNuno Sá 	struct device *dev = &indio_dev->dev;
199364ad7f64SFabrice Gasnier 	const struct stm32_adc_info *adc_info = adc->cfg->adc_info;
199445571a36SOlivier Moysan 	int num_channels = 0, ret;
19950f883b22SFabrice Gasnier 
19967b0d54aeSSean Nyekjaer 	dev_dbg(&indio_dev->dev, "using legacy channel config\n");
19977b0d54aeSSean Nyekjaer 
1998d7705f35SNuno Sá 	ret = device_property_count_u32(dev, "st,adc-channels");
19993fb2e24eSFabrice Gasnier 	if (ret > adc_info->max_channels) {
20000f883b22SFabrice Gasnier 		dev_err(&indio_dev->dev, "Bad st,adc-channels?\n");
20013fb2e24eSFabrice Gasnier 		return -EINVAL;
20023fb2e24eSFabrice Gasnier 	} else if (ret > 0) {
20033fb2e24eSFabrice Gasnier 		num_channels += ret;
20043fb2e24eSFabrice Gasnier 	}
20053fb2e24eSFabrice Gasnier 
2006d7705f35SNuno Sá 	/*
2007d7705f35SNuno Sá 	 * each st,adc-diff-channels is a group of 2 u32 so we divide @ret
2008d7705f35SNuno Sá 	 * to get the *real* number of channels.
2009d7705f35SNuno Sá 	 */
2010d7705f35SNuno Sá 	ret = device_property_count_u32(dev, "st,adc-diff-channels");
20119c0d6ccdSSean Nyekjaer 	if (ret > 0) {
2012d7705f35SNuno Sá 		ret /= (int)(sizeof(struct stm32_adc_diff_channel) / sizeof(u32));
20133fb2e24eSFabrice Gasnier 		if (ret > adc_info->max_channels) {
20143fb2e24eSFabrice Gasnier 			dev_err(&indio_dev->dev, "Bad st,adc-diff-channels?\n");
20153fb2e24eSFabrice Gasnier 			return -EINVAL;
20163fb2e24eSFabrice Gasnier 		} else if (ret > 0) {
201745571a36SOlivier Moysan 			adc->num_diff = ret;
20183fb2e24eSFabrice Gasnier 			num_channels += ret;
201945571a36SOlivier Moysan 		}
20209c0d6ccdSSean Nyekjaer 	}
202145571a36SOlivier Moysan 
2022796e5d0bSOlivier Moysan 	/* Optional sample time is provided either for each, or all channels */
2023d7705f35SNuno Sá 	adc->nsmps = device_property_count_u32(dev, "st,min-sample-time-nsecs");
2024d7705f35SNuno Sá 	if (adc->nsmps > 1 && adc->nsmps != num_channels) {
2025796e5d0bSOlivier Moysan 		dev_err(&indio_dev->dev, "Invalid st,min-sample-time-nsecs\n");
2026796e5d0bSOlivier Moysan 		return -EINVAL;
2027796e5d0bSOlivier Moysan 	}
2028796e5d0bSOlivier Moysan 
202945571a36SOlivier Moysan 	return num_channels;
203045571a36SOlivier Moysan }
203145571a36SOlivier Moysan 
203245571a36SOlivier Moysan static int stm32_adc_legacy_chan_init(struct iio_dev *indio_dev,
203345571a36SOlivier Moysan 				      struct stm32_adc *adc,
2034d7705f35SNuno Sá 				      struct iio_chan_spec *channels,
2035d7705f35SNuno Sá 				      int nchans)
203645571a36SOlivier Moysan {
203745571a36SOlivier Moysan 	const struct stm32_adc_info *adc_info = adc->cfg->adc_info;
203845571a36SOlivier Moysan 	struct stm32_adc_diff_channel diff[STM32_ADC_CH_MAX];
2039d7705f35SNuno Sá 	struct device *dev = &indio_dev->dev;
204045571a36SOlivier Moysan 	u32 num_diff = adc->num_diff;
20413e27ef0cSSean Nyekjaer 	int num_se = nchans - num_diff;
204245571a36SOlivier Moysan 	int size = num_diff * sizeof(*diff) / sizeof(u32);
2043d7705f35SNuno Sá 	int scan_index = 0, ret, i, c;
2044d7705f35SNuno Sá 	u32 smp = 0, smps[STM32_ADC_CH_MAX], chans[STM32_ADC_CH_MAX];
204545571a36SOlivier Moysan 
204645571a36SOlivier Moysan 	if (num_diff) {
2047d7705f35SNuno Sá 		ret = device_property_read_u32_array(dev, "st,adc-diff-channels",
20483fb2e24eSFabrice Gasnier 						     (u32 *)diff, size);
204945571a36SOlivier Moysan 		if (ret) {
205045571a36SOlivier Moysan 			dev_err(&indio_dev->dev, "Failed to get diff channels %d\n", ret);
20513fb2e24eSFabrice Gasnier 			return ret;
20523fb2e24eSFabrice Gasnier 		}
20533fb2e24eSFabrice Gasnier 
205445571a36SOlivier Moysan 		for (i = 0; i < num_diff; i++) {
205545571a36SOlivier Moysan 			if (diff[i].vinp >= adc_info->max_channels ||
205645571a36SOlivier Moysan 			    diff[i].vinn >= adc_info->max_channels) {
205745571a36SOlivier Moysan 				dev_err(&indio_dev->dev, "Invalid channel in%d-in%d\n",
205845571a36SOlivier Moysan 					diff[i].vinp, diff[i].vinn);
205945571a36SOlivier Moysan 				return -EINVAL;
206045571a36SOlivier Moysan 			}
206145571a36SOlivier Moysan 
206245571a36SOlivier Moysan 			stm32_adc_chan_init_one(indio_dev, &channels[scan_index],
206345571a36SOlivier Moysan 						diff[i].vinp, diff[i].vinn,
206445571a36SOlivier Moysan 						scan_index, true);
206545571a36SOlivier Moysan 			scan_index++;
206645571a36SOlivier Moysan 		}
206745571a36SOlivier Moysan 	}
20683e27ef0cSSean Nyekjaer 	if (num_se > 0) {
20693e27ef0cSSean Nyekjaer 		ret = device_property_read_u32_array(dev, "st,adc-channels", chans, num_se);
20703e27ef0cSSean Nyekjaer 		if (ret) {
20713e27ef0cSSean Nyekjaer 			dev_err(&indio_dev->dev, "Failed to get st,adc-channels %d\n", ret);
2072d7705f35SNuno Sá 			return ret;
20733e27ef0cSSean Nyekjaer 		}
2074d7705f35SNuno Sá 
20753e27ef0cSSean Nyekjaer 		for (c = 0; c < num_se; c++) {
2076d7705f35SNuno Sá 			if (chans[c] >= adc_info->max_channels) {
2077d7705f35SNuno Sá 				dev_err(&indio_dev->dev, "Invalid channel %d\n",
2078d7705f35SNuno Sá 					chans[c]);
207945571a36SOlivier Moysan 				return -EINVAL;
208045571a36SOlivier Moysan 			}
208145571a36SOlivier Moysan 
208245571a36SOlivier Moysan 			/* Channel can't be configured both as single-ended & diff */
208345571a36SOlivier Moysan 			for (i = 0; i < num_diff; i++) {
2084d7705f35SNuno Sá 				if (chans[c] == diff[i].vinp) {
20853e27ef0cSSean Nyekjaer 					dev_err(&indio_dev->dev, "channel %d misconfigured\n",
20863e27ef0cSSean Nyekjaer 						chans[c]);
208745571a36SOlivier Moysan 					return -EINVAL;
208845571a36SOlivier Moysan 				}
208945571a36SOlivier Moysan 			}
2090d7705f35SNuno Sá 			stm32_adc_chan_init_one(indio_dev, &channels[scan_index],
2091d7705f35SNuno Sá 						chans[c], 0, scan_index, false);
209245571a36SOlivier Moysan 			scan_index++;
209345571a36SOlivier Moysan 		}
20943e27ef0cSSean Nyekjaer 	}
209545571a36SOlivier Moysan 
2096d7705f35SNuno Sá 	if (adc->nsmps > 0) {
2097d7705f35SNuno Sá 		ret = device_property_read_u32_array(dev, "st,min-sample-time-nsecs",
2098d7705f35SNuno Sá 						     smps, adc->nsmps);
2099d7705f35SNuno Sá 		if (ret)
2100d7705f35SNuno Sá 			return ret;
2101d7705f35SNuno Sá 	}
2102d7705f35SNuno Sá 
2103796e5d0bSOlivier Moysan 	for (i = 0; i < scan_index; i++) {
2104796e5d0bSOlivier Moysan 		/*
2105d7705f35SNuno Sá 		 * This check is used with the above logic so that smp value
2106d7705f35SNuno Sá 		 * will only be modified if valid u32 value can be decoded. This
2107d7705f35SNuno Sá 		 * allows to get either no value, 1 shared value for all indexes,
2108d7705f35SNuno Sá 		 * or one value per channel. The point is to have the same
2109d7705f35SNuno Sá 		 * behavior as 'of_property_read_u32_index()'.
2110796e5d0bSOlivier Moysan 		 */
2111d7705f35SNuno Sá 		if (i < adc->nsmps)
2112d7705f35SNuno Sá 			smp = smps[i];
2113796e5d0bSOlivier Moysan 
2114796e5d0bSOlivier Moysan 		/* Prepare sampling time settings */
2115796e5d0bSOlivier Moysan 		stm32_adc_smpr_init(adc, channels[i].channel, smp);
2116796e5d0bSOlivier Moysan 	}
2117796e5d0bSOlivier Moysan 
211845571a36SOlivier Moysan 	return scan_index;
211945571a36SOlivier Moysan }
212045571a36SOlivier Moysan 
21210e346b2cSOlivier Moysan static int stm32_adc_populate_int_ch(struct iio_dev *indio_dev, const char *ch_name,
21220e346b2cSOlivier Moysan 				     int chan)
21230e346b2cSOlivier Moysan {
21240e346b2cSOlivier Moysan 	struct stm32_adc *adc = iio_priv(indio_dev);
21250e346b2cSOlivier Moysan 	u16 vrefint;
21260e346b2cSOlivier Moysan 	int i, ret;
21270e346b2cSOlivier Moysan 
21280e346b2cSOlivier Moysan 	for (i = 0; i < STM32_ADC_INT_CH_NB; i++) {
21290e346b2cSOlivier Moysan 		if (!strncmp(stm32_adc_ic[i].name, ch_name, STM32_ADC_CH_SZ)) {
2130cf0fb80aSOlivier Moysan 			/* Check internal channel availability */
2131cf0fb80aSOlivier Moysan 			switch (i) {
2132cf0fb80aSOlivier Moysan 			case STM32_ADC_INT_CH_VDDCORE:
2133cf0fb80aSOlivier Moysan 				if (!adc->cfg->regs->or_vddcore.reg)
2134cf0fb80aSOlivier Moysan 					dev_warn(&indio_dev->dev,
2135cf0fb80aSOlivier Moysan 						 "%s channel not available\n", ch_name);
2136cf0fb80aSOlivier Moysan 				break;
2137cf0fb80aSOlivier Moysan 			case STM32_ADC_INT_CH_VDDCPU:
2138cf0fb80aSOlivier Moysan 				if (!adc->cfg->regs->or_vddcpu.reg)
2139cf0fb80aSOlivier Moysan 					dev_warn(&indio_dev->dev,
2140cf0fb80aSOlivier Moysan 						 "%s channel not available\n", ch_name);
2141cf0fb80aSOlivier Moysan 				break;
2142cf0fb80aSOlivier Moysan 			case STM32_ADC_INT_CH_VDDQ_DDR:
2143cf0fb80aSOlivier Moysan 				if (!adc->cfg->regs->or_vddq_ddr.reg)
2144cf0fb80aSOlivier Moysan 					dev_warn(&indio_dev->dev,
2145cf0fb80aSOlivier Moysan 						 "%s channel not available\n", ch_name);
2146cf0fb80aSOlivier Moysan 				break;
2147cf0fb80aSOlivier Moysan 			case STM32_ADC_INT_CH_VREFINT:
2148cf0fb80aSOlivier Moysan 				if (!adc->cfg->regs->ccr_vref.reg)
2149cf0fb80aSOlivier Moysan 					dev_warn(&indio_dev->dev,
2150cf0fb80aSOlivier Moysan 						 "%s channel not available\n", ch_name);
2151cf0fb80aSOlivier Moysan 				break;
2152cf0fb80aSOlivier Moysan 			case STM32_ADC_INT_CH_VBAT:
2153cf0fb80aSOlivier Moysan 				if (!adc->cfg->regs->ccr_vbat.reg)
2154cf0fb80aSOlivier Moysan 					dev_warn(&indio_dev->dev,
2155cf0fb80aSOlivier Moysan 						 "%s channel not available\n", ch_name);
2156cf0fb80aSOlivier Moysan 				break;
2157cf0fb80aSOlivier Moysan 			}
2158cf0fb80aSOlivier Moysan 
2159bc05f30fSOlivier Moysan 			if (stm32_adc_ic[i].idx != STM32_ADC_INT_CH_VREFINT) {
21600e346b2cSOlivier Moysan 				adc->int_ch[i] = chan;
2161bc05f30fSOlivier Moysan 				break;
2162bc05f30fSOlivier Moysan 			}
21630e346b2cSOlivier Moysan 
21640e346b2cSOlivier Moysan 			/* Get calibration data for vrefint channel */
21650e346b2cSOlivier Moysan 			ret = nvmem_cell_read_u16(&indio_dev->dev, "vrefint", &vrefint);
21660e346b2cSOlivier Moysan 			if (ret && ret != -ENOENT) {
2167784b4707SOlivier Moysan 				return dev_err_probe(indio_dev->dev.parent, ret,
21680e346b2cSOlivier Moysan 						     "nvmem access error\n");
21690e346b2cSOlivier Moysan 			}
2170bc05f30fSOlivier Moysan 			if (ret == -ENOENT) {
2171bc05f30fSOlivier Moysan 				dev_dbg(&indio_dev->dev, "vrefint calibration not found. Skip vrefint channel\n");
2172bc05f30fSOlivier Moysan 				return ret;
2173bc05f30fSOlivier Moysan 			} else if (!vrefint) {
2174bc05f30fSOlivier Moysan 				dev_dbg(&indio_dev->dev, "Null vrefint calibration value. Skip vrefint channel\n");
2175bc05f30fSOlivier Moysan 				return -ENOENT;
2176bc05f30fSOlivier Moysan 			}
2177bc05f30fSOlivier Moysan 			adc->int_ch[i] = chan;
21780e346b2cSOlivier Moysan 			adc->vrefint.vrefint_cal = vrefint;
21790e346b2cSOlivier Moysan 		}
21800e346b2cSOlivier Moysan 	}
21810e346b2cSOlivier Moysan 
21820e346b2cSOlivier Moysan 	return 0;
21830e346b2cSOlivier Moysan }
21840e346b2cSOlivier Moysan 
218595bc8184SOlivier Moysan static int stm32_adc_generic_chan_init(struct iio_dev *indio_dev,
218695bc8184SOlivier Moysan 				       struct stm32_adc *adc,
218795bc8184SOlivier Moysan 				       struct iio_chan_spec *channels)
218895bc8184SOlivier Moysan {
218995bc8184SOlivier Moysan 	const struct stm32_adc_info *adc_info = adc->cfg->adc_info;
2190d7705f35SNuno Sá 	struct fwnode_handle *child;
219195bc8184SOlivier Moysan 	const char *name;
21920e346b2cSOlivier Moysan 	int val, scan_index = 0, ret;
219395bc8184SOlivier Moysan 	bool differential;
219495bc8184SOlivier Moysan 	u32 vin[2];
219595bc8184SOlivier Moysan 
2196d7705f35SNuno Sá 	device_for_each_child_node(&indio_dev->dev, child) {
2197d7705f35SNuno Sá 		ret = fwnode_property_read_u32(child, "reg", &val);
219895bc8184SOlivier Moysan 		if (ret) {
219995bc8184SOlivier Moysan 			dev_err(&indio_dev->dev, "Missing channel index %d\n", ret);
220095bc8184SOlivier Moysan 			goto err;
220195bc8184SOlivier Moysan 		}
220295bc8184SOlivier Moysan 
2203d7705f35SNuno Sá 		ret = fwnode_property_read_string(child, "label", &name);
220495bc8184SOlivier Moysan 		/* label is optional */
220595bc8184SOlivier Moysan 		if (!ret) {
220695bc8184SOlivier Moysan 			if (strlen(name) >= STM32_ADC_CH_SZ) {
220795bc8184SOlivier Moysan 				dev_err(&indio_dev->dev, "Label %s exceeds %d characters\n",
220895bc8184SOlivier Moysan 					name, STM32_ADC_CH_SZ);
22098cf524beSWan Jiabing 				ret = -EINVAL;
22108cf524beSWan Jiabing 				goto err;
221195bc8184SOlivier Moysan 			}
221295bc8184SOlivier Moysan 			strncpy(adc->chan_name[val], name, STM32_ADC_CH_SZ);
22130e346b2cSOlivier Moysan 			ret = stm32_adc_populate_int_ch(indio_dev, name, val);
2214bc05f30fSOlivier Moysan 			if (ret == -ENOENT)
2215bc05f30fSOlivier Moysan 				continue;
2216bc05f30fSOlivier Moysan 			else if (ret)
22170e346b2cSOlivier Moysan 				goto err;
221895bc8184SOlivier Moysan 		} else if (ret != -EINVAL) {
221995bc8184SOlivier Moysan 			dev_err(&indio_dev->dev, "Invalid label %d\n", ret);
222095bc8184SOlivier Moysan 			goto err;
222195bc8184SOlivier Moysan 		}
222295bc8184SOlivier Moysan 
222395bc8184SOlivier Moysan 		if (val >= adc_info->max_channels) {
222495bc8184SOlivier Moysan 			dev_err(&indio_dev->dev, "Invalid channel %d\n", val);
222595bc8184SOlivier Moysan 			ret = -EINVAL;
222695bc8184SOlivier Moysan 			goto err;
222795bc8184SOlivier Moysan 		}
222895bc8184SOlivier Moysan 
222995bc8184SOlivier Moysan 		differential = false;
2230d7705f35SNuno Sá 		ret = fwnode_property_read_u32_array(child, "diff-channels", vin, 2);
223195bc8184SOlivier Moysan 		/* diff-channels is optional */
223295bc8184SOlivier Moysan 		if (!ret) {
223395bc8184SOlivier Moysan 			differential = true;
223495bc8184SOlivier Moysan 			if (vin[0] != val || vin[1] >= adc_info->max_channels) {
223595bc8184SOlivier Moysan 				dev_err(&indio_dev->dev, "Invalid channel in%d-in%d\n",
223695bc8184SOlivier Moysan 					vin[0], vin[1]);
223795bc8184SOlivier Moysan 				goto err;
223895bc8184SOlivier Moysan 			}
223995bc8184SOlivier Moysan 		} else if (ret != -EINVAL) {
224095bc8184SOlivier Moysan 			dev_err(&indio_dev->dev, "Invalid diff-channels property %d\n", ret);
224195bc8184SOlivier Moysan 			goto err;
224295bc8184SOlivier Moysan 		}
224395bc8184SOlivier Moysan 
224495bc8184SOlivier Moysan 		stm32_adc_chan_init_one(indio_dev, &channels[scan_index], val,
224595bc8184SOlivier Moysan 					vin[1], scan_index, differential);
2246796e5d0bSOlivier Moysan 
2247174dac5dSOlivier Moysan 		val = 0;
2248d7705f35SNuno Sá 		ret = fwnode_property_read_u32(child, "st,min-sample-time-ns", &val);
2249796e5d0bSOlivier Moysan 		/* st,min-sample-time-ns is optional */
2250174dac5dSOlivier Moysan 		if (ret && ret != -EINVAL) {
2251796e5d0bSOlivier Moysan 			dev_err(&indio_dev->dev, "Invalid st,min-sample-time-ns property %d\n",
2252796e5d0bSOlivier Moysan 				ret);
2253796e5d0bSOlivier Moysan 			goto err;
2254796e5d0bSOlivier Moysan 		}
2255796e5d0bSOlivier Moysan 
2256174dac5dSOlivier Moysan 		stm32_adc_smpr_init(adc, channels[scan_index].channel, val);
2257174dac5dSOlivier Moysan 		if (differential)
2258174dac5dSOlivier Moysan 			stm32_adc_smpr_init(adc, vin[1], val);
2259174dac5dSOlivier Moysan 
226095bc8184SOlivier Moysan 		scan_index++;
226195bc8184SOlivier Moysan 	}
226295bc8184SOlivier Moysan 
226395bc8184SOlivier Moysan 	return scan_index;
226495bc8184SOlivier Moysan 
226595bc8184SOlivier Moysan err:
2266d7705f35SNuno Sá 	fwnode_handle_put(child);
226795bc8184SOlivier Moysan 
226895bc8184SOlivier Moysan 	return ret;
226995bc8184SOlivier Moysan }
227095bc8184SOlivier Moysan 
2271d7705f35SNuno Sá static int stm32_adc_chan_fw_init(struct iio_dev *indio_dev, bool timestamping)
227245571a36SOlivier Moysan {
227345571a36SOlivier Moysan 	struct stm32_adc *adc = iio_priv(indio_dev);
227445571a36SOlivier Moysan 	const struct stm32_adc_info *adc_info = adc->cfg->adc_info;
227545571a36SOlivier Moysan 	struct iio_chan_spec *channels;
227645571a36SOlivier Moysan 	int scan_index = 0, num_channels = 0, ret, i;
227795bc8184SOlivier Moysan 	bool legacy = false;
227895bc8184SOlivier Moysan 
2279aec6e0d8SOlivier Moysan 	for (i = 0; i < STM32_ADC_INT_CH_NB; i++)
2280aec6e0d8SOlivier Moysan 		adc->int_ch[i] = STM32_ADC_INT_CH_NONE;
2281aec6e0d8SOlivier Moysan 
2282d7705f35SNuno Sá 	num_channels = device_get_child_node_count(&indio_dev->dev);
228395bc8184SOlivier Moysan 	/* If no channels have been found, fallback to channels legacy properties. */
228495bc8184SOlivier Moysan 	if (!num_channels) {
228595bc8184SOlivier Moysan 		legacy = true;
228645571a36SOlivier Moysan 
228745571a36SOlivier Moysan 		ret = stm32_adc_get_legacy_chan_count(indio_dev, adc);
228895bc8184SOlivier Moysan 		if (!ret) {
228995bc8184SOlivier Moysan 			dev_err(indio_dev->dev.parent, "No channel found\n");
22903fb2e24eSFabrice Gasnier 			return -ENODATA;
229195bc8184SOlivier Moysan 		} else if (ret < 0) {
229295bc8184SOlivier Moysan 			return ret;
229395bc8184SOlivier Moysan 		}
229495bc8184SOlivier Moysan 
229595bc8184SOlivier Moysan 		num_channels = ret;
22960f883b22SFabrice Gasnier 	}
22970f883b22SFabrice Gasnier 
229845571a36SOlivier Moysan 	if (num_channels > adc_info->max_channels) {
229945571a36SOlivier Moysan 		dev_err(&indio_dev->dev, "Channel number [%d] exceeds %d\n",
230045571a36SOlivier Moysan 			num_channels, adc_info->max_channels);
230145571a36SOlivier Moysan 		return -EINVAL;
230245571a36SOlivier Moysan 	}
230345571a36SOlivier Moysan 
23048a09054fSAhmad Fatoum 	if (timestamping)
23058a09054fSAhmad Fatoum 		num_channels++;
23068a09054fSAhmad Fatoum 
23070f883b22SFabrice Gasnier 	channels = devm_kcalloc(&indio_dev->dev, num_channels,
23080f883b22SFabrice Gasnier 				sizeof(struct iio_chan_spec), GFP_KERNEL);
23090f883b22SFabrice Gasnier 	if (!channels)
23100f883b22SFabrice Gasnier 		return -ENOMEM;
23110f883b22SFabrice Gasnier 
231295bc8184SOlivier Moysan 	if (legacy)
2313d7705f35SNuno Sá 		ret = stm32_adc_legacy_chan_init(indio_dev, adc, channels,
23143e27ef0cSSean Nyekjaer 						 timestamping ? num_channels - 1 : num_channels);
231595bc8184SOlivier Moysan 	else
231695bc8184SOlivier Moysan 		ret = stm32_adc_generic_chan_init(indio_dev, adc, channels);
231745571a36SOlivier Moysan 	if (ret < 0)
231845571a36SOlivier Moysan 		return ret;
231945571a36SOlivier Moysan 	scan_index = ret;
23203fb2e24eSFabrice Gasnier 
23218a09054fSAhmad Fatoum 	if (timestamping) {
23228a09054fSAhmad Fatoum 		struct iio_chan_spec *timestamp = &channels[scan_index];
23238a09054fSAhmad Fatoum 
23248a09054fSAhmad Fatoum 		timestamp->type = IIO_TIMESTAMP;
23258a09054fSAhmad Fatoum 		timestamp->channel = -1;
23268a09054fSAhmad Fatoum 		timestamp->scan_index = scan_index;
23278a09054fSAhmad Fatoum 		timestamp->scan_type.sign = 's';
23288a09054fSAhmad Fatoum 		timestamp->scan_type.realbits = 64;
23298a09054fSAhmad Fatoum 		timestamp->scan_type.storagebits = 64;
23308a09054fSAhmad Fatoum 
23318a09054fSAhmad Fatoum 		scan_index++;
23328a09054fSAhmad Fatoum 	}
23338a09054fSAhmad Fatoum 
23340f883b22SFabrice Gasnier 	indio_dev->num_channels = scan_index;
23350f883b22SFabrice Gasnier 	indio_dev->channels = channels;
23360f883b22SFabrice Gasnier 
23370f883b22SFabrice Gasnier 	return 0;
23380f883b22SFabrice Gasnier }
23390f883b22SFabrice Gasnier 
234052cd91c2SFabrice Gasnier static int stm32_adc_dma_request(struct device *dev, struct iio_dev *indio_dev)
23412763ea05SFabrice Gasnier {
23422763ea05SFabrice Gasnier 	struct stm32_adc *adc = iio_priv(indio_dev);
23432763ea05SFabrice Gasnier 	struct dma_slave_config config;
23442763ea05SFabrice Gasnier 	int ret;
23452763ea05SFabrice Gasnier 
234652cd91c2SFabrice Gasnier 	adc->dma_chan = dma_request_chan(dev, "rx");
2347735404b8SPeter Ujfalusi 	if (IS_ERR(adc->dma_chan)) {
2348735404b8SPeter Ujfalusi 		ret = PTR_ERR(adc->dma_chan);
2349ce30eeb6SKrzysztof Kozlowski 		if (ret != -ENODEV)
2350ce30eeb6SKrzysztof Kozlowski 			return dev_err_probe(dev, ret,
2351ce30eeb6SKrzysztof Kozlowski 					     "DMA channel request failed with\n");
2352735404b8SPeter Ujfalusi 
2353735404b8SPeter Ujfalusi 		/* DMA is optional: fall back to IRQ mode */
2354735404b8SPeter Ujfalusi 		adc->dma_chan = NULL;
23552763ea05SFabrice Gasnier 		return 0;
2356735404b8SPeter Ujfalusi 	}
23572763ea05SFabrice Gasnier 
23582763ea05SFabrice Gasnier 	adc->rx_buf = dma_alloc_coherent(adc->dma_chan->device->dev,
23592763ea05SFabrice Gasnier 					 STM32_DMA_BUFFER_SIZE,
23602763ea05SFabrice Gasnier 					 &adc->rx_dma_buf, GFP_KERNEL);
23612763ea05SFabrice Gasnier 	if (!adc->rx_buf) {
23622763ea05SFabrice Gasnier 		ret = -ENOMEM;
23632763ea05SFabrice Gasnier 		goto err_release;
23642763ea05SFabrice Gasnier 	}
23652763ea05SFabrice Gasnier 
23662763ea05SFabrice Gasnier 	/* Configure DMA channel to read data register */
23672763ea05SFabrice Gasnier 	memset(&config, 0, sizeof(config));
23682763ea05SFabrice Gasnier 	config.src_addr = (dma_addr_t)adc->common->phys_base;
236964ad7f64SFabrice Gasnier 	config.src_addr += adc->offset + adc->cfg->regs->dr;
23702763ea05SFabrice Gasnier 	config.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
23712763ea05SFabrice Gasnier 
23722763ea05SFabrice Gasnier 	ret = dmaengine_slave_config(adc->dma_chan, &config);
23732763ea05SFabrice Gasnier 	if (ret)
23742763ea05SFabrice Gasnier 		goto err_free;
23752763ea05SFabrice Gasnier 
23762763ea05SFabrice Gasnier 	return 0;
23772763ea05SFabrice Gasnier 
23782763ea05SFabrice Gasnier err_free:
23792763ea05SFabrice Gasnier 	dma_free_coherent(adc->dma_chan->device->dev, STM32_DMA_BUFFER_SIZE,
23802763ea05SFabrice Gasnier 			  adc->rx_buf, adc->rx_dma_buf);
23812763ea05SFabrice Gasnier err_release:
23822763ea05SFabrice Gasnier 	dma_release_channel(adc->dma_chan);
23832763ea05SFabrice Gasnier 
23842763ea05SFabrice Gasnier 	return ret;
23852763ea05SFabrice Gasnier }
23862763ea05SFabrice Gasnier 
23870f883b22SFabrice Gasnier static int stm32_adc_probe(struct platform_device *pdev)
23880f883b22SFabrice Gasnier {
23890f883b22SFabrice Gasnier 	struct iio_dev *indio_dev;
239064ad7f64SFabrice Gasnier 	struct device *dev = &pdev->dev;
2391e2042d29SOlivier Moysan 	irqreturn_t (*handler)(int irq, void *p) = NULL;
23920f883b22SFabrice Gasnier 	struct stm32_adc *adc;
23938a09054fSAhmad Fatoum 	bool timestamping = false;
23940f883b22SFabrice Gasnier 	int ret;
23950f883b22SFabrice Gasnier 
23960f883b22SFabrice Gasnier 	indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*adc));
23970f883b22SFabrice Gasnier 	if (!indio_dev)
23980f883b22SFabrice Gasnier 		return -ENOMEM;
23990f883b22SFabrice Gasnier 
24000f883b22SFabrice Gasnier 	adc = iio_priv(indio_dev);
24010f883b22SFabrice Gasnier 	adc->common = dev_get_drvdata(pdev->dev.parent);
24020f883b22SFabrice Gasnier 	spin_lock_init(&adc->lock);
24030f883b22SFabrice Gasnier 	init_completion(&adc->completion);
2404d7705f35SNuno Sá 	adc->cfg = device_get_match_data(dev);
24050f883b22SFabrice Gasnier 
24060f883b22SFabrice Gasnier 	indio_dev->name = dev_name(&pdev->dev);
2407d7705f35SNuno Sá 	device_set_node(&indio_dev->dev, dev_fwnode(&pdev->dev));
24080f883b22SFabrice Gasnier 	indio_dev->info = &stm32_adc_iio_info;
2409f0b638a7SFabrice Gasnier 	indio_dev->modes = INDIO_DIRECT_MODE | INDIO_HARDWARE_TRIGGERED;
24100f883b22SFabrice Gasnier 
2411cd64d357SAlexandru Ardelean 	platform_set_drvdata(pdev, indio_dev);
24120f883b22SFabrice Gasnier 
2413d7705f35SNuno Sá 	ret = device_property_read_u32(dev, "reg", &adc->offset);
24140f883b22SFabrice Gasnier 	if (ret != 0) {
24150f883b22SFabrice Gasnier 		dev_err(&pdev->dev, "missing reg property\n");
24160f883b22SFabrice Gasnier 		return -EINVAL;
24170f883b22SFabrice Gasnier 	}
24180f883b22SFabrice Gasnier 
24190f883b22SFabrice Gasnier 	adc->irq = platform_get_irq(pdev, 0);
24207c279229SStephen Boyd 	if (adc->irq < 0)
24210f883b22SFabrice Gasnier 		return adc->irq;
24220f883b22SFabrice Gasnier 
2423cc06e67dSFabrice Gasnier 	ret = devm_request_threaded_irq(&pdev->dev, adc->irq, stm32_adc_isr,
2424cc06e67dSFabrice Gasnier 					stm32_adc_threaded_isr,
2425cd64d357SAlexandru Ardelean 					0, pdev->name, indio_dev);
24260f883b22SFabrice Gasnier 	if (ret) {
24270f883b22SFabrice Gasnier 		dev_err(&pdev->dev, "failed to request IRQ\n");
24280f883b22SFabrice Gasnier 		return ret;
24290f883b22SFabrice Gasnier 	}
24300f883b22SFabrice Gasnier 
24310f883b22SFabrice Gasnier 	adc->clk = devm_clk_get(&pdev->dev, NULL);
24320f883b22SFabrice Gasnier 	if (IS_ERR(adc->clk)) {
2433204a6a25SFabrice Gasnier 		ret = PTR_ERR(adc->clk);
2434204a6a25SFabrice Gasnier 		if (ret == -ENOENT && !adc->cfg->clk_required) {
2435204a6a25SFabrice Gasnier 			adc->clk = NULL;
2436204a6a25SFabrice Gasnier 		} else {
24370f883b22SFabrice Gasnier 			dev_err(&pdev->dev, "Can't get clock\n");
2438204a6a25SFabrice Gasnier 			return ret;
2439204a6a25SFabrice Gasnier 		}
24400f883b22SFabrice Gasnier 	}
24410f883b22SFabrice Gasnier 
2442d7705f35SNuno Sá 	ret = stm32_adc_fw_get_resolution(indio_dev);
244325a85bedSFabrice Gasnier 	if (ret < 0)
24449bdbb113SFabrice Gasnier 		return ret;
244525a85bedSFabrice Gasnier 
244652cd91c2SFabrice Gasnier 	ret = stm32_adc_dma_request(dev, indio_dev);
24472763ea05SFabrice Gasnier 	if (ret < 0)
24489bdbb113SFabrice Gasnier 		return ret;
24492763ea05SFabrice Gasnier 
24508a09054fSAhmad Fatoum 	if (!adc->dma_chan) {
24518a09054fSAhmad Fatoum 		/* For PIO mode only, iio_pollfunc_store_time stores a timestamp
24528a09054fSAhmad Fatoum 		 * in the primary trigger IRQ handler and stm32_adc_trigger_handler
24538a09054fSAhmad Fatoum 		 * runs in the IRQ thread to push out buffer along with timestamp.
24548a09054fSAhmad Fatoum 		 */
2455e2042d29SOlivier Moysan 		handler = &stm32_adc_trigger_handler;
24568a09054fSAhmad Fatoum 		timestamping = true;
24578a09054fSAhmad Fatoum 	}
24588a09054fSAhmad Fatoum 
2459d7705f35SNuno Sá 	ret = stm32_adc_chan_fw_init(indio_dev, timestamping);
24608a09054fSAhmad Fatoum 	if (ret < 0)
24618a09054fSAhmad Fatoum 		goto err_dma_disable;
2462e2042d29SOlivier Moysan 
2463da9b9485SFabrice Gasnier 	ret = iio_triggered_buffer_setup(indio_dev,
2464e2042d29SOlivier Moysan 					 &iio_pollfunc_store_time, handler,
2465da9b9485SFabrice Gasnier 					 &stm32_adc_buffer_setup_ops);
24660f883b22SFabrice Gasnier 	if (ret) {
2467da9b9485SFabrice Gasnier 		dev_err(&pdev->dev, "buffer setup failed\n");
24682763ea05SFabrice Gasnier 		goto err_dma_disable;
24690f883b22SFabrice Gasnier 	}
24700f883b22SFabrice Gasnier 
24719bdbb113SFabrice Gasnier 	/* Get stm32-adc-core PM online */
24729bdbb113SFabrice Gasnier 	pm_runtime_get_noresume(dev);
24739bdbb113SFabrice Gasnier 	pm_runtime_set_active(dev);
24749bdbb113SFabrice Gasnier 	pm_runtime_set_autosuspend_delay(dev, STM32_ADC_HW_STOP_DELAY_MS);
24759bdbb113SFabrice Gasnier 	pm_runtime_use_autosuspend(dev);
24769bdbb113SFabrice Gasnier 	pm_runtime_enable(dev);
24779bdbb113SFabrice Gasnier 
24789bdbb113SFabrice Gasnier 	ret = stm32_adc_hw_start(dev);
24799bdbb113SFabrice Gasnier 	if (ret)
24809bdbb113SFabrice Gasnier 		goto err_buffer_cleanup;
24819bdbb113SFabrice Gasnier 
2482da9b9485SFabrice Gasnier 	ret = iio_device_register(indio_dev);
2483da9b9485SFabrice Gasnier 	if (ret) {
2484da9b9485SFabrice Gasnier 		dev_err(&pdev->dev, "iio dev register failed\n");
24859bdbb113SFabrice Gasnier 		goto err_hw_stop;
2486da9b9485SFabrice Gasnier 	}
2487da9b9485SFabrice Gasnier 
24889bdbb113SFabrice Gasnier 	pm_runtime_mark_last_busy(dev);
24899bdbb113SFabrice Gasnier 	pm_runtime_put_autosuspend(dev);
24909bdbb113SFabrice Gasnier 
249151bcacc6SOlivier Moysan 	if (IS_ENABLED(CONFIG_DEBUG_FS))
249251bcacc6SOlivier Moysan 		stm32_adc_debugfs_init(indio_dev);
249351bcacc6SOlivier Moysan 
24940f883b22SFabrice Gasnier 	return 0;
24950f883b22SFabrice Gasnier 
24969bdbb113SFabrice Gasnier err_hw_stop:
24979bdbb113SFabrice Gasnier 	stm32_adc_hw_stop(dev);
24989bdbb113SFabrice Gasnier 
2499da9b9485SFabrice Gasnier err_buffer_cleanup:
25009bdbb113SFabrice Gasnier 	pm_runtime_disable(dev);
25019bdbb113SFabrice Gasnier 	pm_runtime_set_suspended(dev);
25029bdbb113SFabrice Gasnier 	pm_runtime_put_noidle(dev);
2503da9b9485SFabrice Gasnier 	iio_triggered_buffer_cleanup(indio_dev);
2504da9b9485SFabrice Gasnier 
25052763ea05SFabrice Gasnier err_dma_disable:
25062763ea05SFabrice Gasnier 	if (adc->dma_chan) {
25072763ea05SFabrice Gasnier 		dma_free_coherent(adc->dma_chan->device->dev,
25082763ea05SFabrice Gasnier 				  STM32_DMA_BUFFER_SIZE,
25092763ea05SFabrice Gasnier 				  adc->rx_buf, adc->rx_dma_buf);
25102763ea05SFabrice Gasnier 		dma_release_channel(adc->dma_chan);
25112763ea05SFabrice Gasnier 	}
25120f883b22SFabrice Gasnier 
25130f883b22SFabrice Gasnier 	return ret;
25140f883b22SFabrice Gasnier }
25150f883b22SFabrice Gasnier 
2516*da8431b4SUwe Kleine-König static void stm32_adc_remove(struct platform_device *pdev)
25170f883b22SFabrice Gasnier {
2518cd64d357SAlexandru Ardelean 	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
2519cd64d357SAlexandru Ardelean 	struct stm32_adc *adc = iio_priv(indio_dev);
25200f883b22SFabrice Gasnier 
25219bdbb113SFabrice Gasnier 	pm_runtime_get_sync(&pdev->dev);
252251bcacc6SOlivier Moysan 	/* iio_device_unregister() also removes debugfs entries */
25230f883b22SFabrice Gasnier 	iio_device_unregister(indio_dev);
25249bdbb113SFabrice Gasnier 	stm32_adc_hw_stop(&pdev->dev);
25259bdbb113SFabrice Gasnier 	pm_runtime_disable(&pdev->dev);
25269bdbb113SFabrice Gasnier 	pm_runtime_set_suspended(&pdev->dev);
25279bdbb113SFabrice Gasnier 	pm_runtime_put_noidle(&pdev->dev);
2528da9b9485SFabrice Gasnier 	iio_triggered_buffer_cleanup(indio_dev);
25292763ea05SFabrice Gasnier 	if (adc->dma_chan) {
25302763ea05SFabrice Gasnier 		dma_free_coherent(adc->dma_chan->device->dev,
25312763ea05SFabrice Gasnier 				  STM32_DMA_BUFFER_SIZE,
25322763ea05SFabrice Gasnier 				  adc->rx_buf, adc->rx_dma_buf);
25332763ea05SFabrice Gasnier 		dma_release_channel(adc->dma_chan);
25342763ea05SFabrice Gasnier 	}
25350f883b22SFabrice Gasnier }
25360f883b22SFabrice Gasnier 
253749ad8d28SFabrice Gasnier static int stm32_adc_suspend(struct device *dev)
253849ad8d28SFabrice Gasnier {
2539cd64d357SAlexandru Ardelean 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
254049ad8d28SFabrice Gasnier 
254149ad8d28SFabrice Gasnier 	if (iio_buffer_enabled(indio_dev))
2542f11d59d8SLars-Peter Clausen 		stm32_adc_buffer_predisable(indio_dev);
254349ad8d28SFabrice Gasnier 
254449ad8d28SFabrice Gasnier 	return pm_runtime_force_suspend(dev);
254549ad8d28SFabrice Gasnier }
254649ad8d28SFabrice Gasnier 
254749ad8d28SFabrice Gasnier static int stm32_adc_resume(struct device *dev)
254849ad8d28SFabrice Gasnier {
2549cd64d357SAlexandru Ardelean 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
255049ad8d28SFabrice Gasnier 	int ret;
255149ad8d28SFabrice Gasnier 
255249ad8d28SFabrice Gasnier 	ret = pm_runtime_force_resume(dev);
255349ad8d28SFabrice Gasnier 	if (ret < 0)
255449ad8d28SFabrice Gasnier 		return ret;
255549ad8d28SFabrice Gasnier 
255649ad8d28SFabrice Gasnier 	if (!iio_buffer_enabled(indio_dev))
255749ad8d28SFabrice Gasnier 		return 0;
255849ad8d28SFabrice Gasnier 
255949ad8d28SFabrice Gasnier 	ret = stm32_adc_update_scan_mode(indio_dev,
256049ad8d28SFabrice Gasnier 					 indio_dev->active_scan_mask);
256149ad8d28SFabrice Gasnier 	if (ret < 0)
256249ad8d28SFabrice Gasnier 		return ret;
256349ad8d28SFabrice Gasnier 
2564f11d59d8SLars-Peter Clausen 	return stm32_adc_buffer_postenable(indio_dev);
256549ad8d28SFabrice Gasnier }
256649ad8d28SFabrice Gasnier 
25679bdbb113SFabrice Gasnier static int stm32_adc_runtime_suspend(struct device *dev)
25689bdbb113SFabrice Gasnier {
25699bdbb113SFabrice Gasnier 	return stm32_adc_hw_stop(dev);
25709bdbb113SFabrice Gasnier }
25719bdbb113SFabrice Gasnier 
25729bdbb113SFabrice Gasnier static int stm32_adc_runtime_resume(struct device *dev)
25739bdbb113SFabrice Gasnier {
25749bdbb113SFabrice Gasnier 	return stm32_adc_hw_start(dev);
25759bdbb113SFabrice Gasnier }
25769bdbb113SFabrice Gasnier 
25779bdbb113SFabrice Gasnier static const struct dev_pm_ops stm32_adc_pm_ops = {
2578d65daa79SJonathan Cameron 	SYSTEM_SLEEP_PM_OPS(stm32_adc_suspend, stm32_adc_resume)
2579d65daa79SJonathan Cameron 	RUNTIME_PM_OPS(stm32_adc_runtime_suspend, stm32_adc_runtime_resume,
25809bdbb113SFabrice Gasnier 		       NULL)
25819bdbb113SFabrice Gasnier };
25829bdbb113SFabrice Gasnier 
258364ad7f64SFabrice Gasnier static const struct stm32_adc_cfg stm32f4_adc_cfg = {
258464ad7f64SFabrice Gasnier 	.regs = &stm32f4_adc_regspec,
258564ad7f64SFabrice Gasnier 	.adc_info = &stm32f4_adc_info,
258664ad7f64SFabrice Gasnier 	.trigs = stm32f4_adc_trigs,
2587204a6a25SFabrice Gasnier 	.clk_required = true,
258864ad7f64SFabrice Gasnier 	.start_conv = stm32f4_adc_start_conv,
258964ad7f64SFabrice Gasnier 	.stop_conv = stm32f4_adc_stop_conv,
2590ee2ac1cdSFabrice Gasnier 	.smp_cycles = stm32f4_adc_smp_cycles,
2591695e2f5cSOlivier Moysan 	.irq_clear = stm32f4_adc_irq_clear,
259264ad7f64SFabrice Gasnier };
259364ad7f64SFabrice Gasnier 
2594225dc61eSTom Rix static const unsigned int stm32_adc_min_ts_h7[] = { 0, 0, 0, 4300, 9000 };
25957cb2303dSOlivier Moysan static_assert(ARRAY_SIZE(stm32_adc_min_ts_h7) == STM32_ADC_INT_CH_NB);
25967cb2303dSOlivier Moysan 
259795e339b6SFabrice Gasnier static const struct stm32_adc_cfg stm32h7_adc_cfg = {
259895e339b6SFabrice Gasnier 	.regs = &stm32h7_adc_regspec,
259995e339b6SFabrice Gasnier 	.adc_info = &stm32h7_adc_info,
260095e339b6SFabrice Gasnier 	.trigs = stm32h7_adc_trigs,
2601cf0fb80aSOlivier Moysan 	.has_boostmode = true,
2602cf0fb80aSOlivier Moysan 	.has_linearcal = true,
2603cf0fb80aSOlivier Moysan 	.has_presel = true,
260495e339b6SFabrice Gasnier 	.start_conv = stm32h7_adc_start_conv,
260595e339b6SFabrice Gasnier 	.stop_conv = stm32h7_adc_stop_conv,
260695e339b6SFabrice Gasnier 	.prepare = stm32h7_adc_prepare,
260795e339b6SFabrice Gasnier 	.unprepare = stm32h7_adc_unprepare,
2608ee2ac1cdSFabrice Gasnier 	.smp_cycles = stm32h7_adc_smp_cycles,
2609695e2f5cSOlivier Moysan 	.irq_clear = stm32h7_adc_irq_clear,
26107cb2303dSOlivier Moysan 	.ts_int_ch = stm32_adc_min_ts_h7,
261195e339b6SFabrice Gasnier };
261295e339b6SFabrice Gasnier 
2613225dc61eSTom Rix static const unsigned int stm32_adc_min_ts_mp1[] = { 100, 100, 100, 4300, 9800 };
26147cb2303dSOlivier Moysan static_assert(ARRAY_SIZE(stm32_adc_min_ts_mp1) == STM32_ADC_INT_CH_NB);
26157cb2303dSOlivier Moysan 
2616d58c67d1SFabrice Gasnier static const struct stm32_adc_cfg stm32mp1_adc_cfg = {
2617aec6e0d8SOlivier Moysan 	.regs = &stm32mp1_adc_regspec,
2618d58c67d1SFabrice Gasnier 	.adc_info = &stm32h7_adc_info,
2619d58c67d1SFabrice Gasnier 	.trigs = stm32h7_adc_trigs,
2620d58c67d1SFabrice Gasnier 	.has_vregready = true,
2621cf0fb80aSOlivier Moysan 	.has_boostmode = true,
2622cf0fb80aSOlivier Moysan 	.has_linearcal = true,
2623cf0fb80aSOlivier Moysan 	.has_presel = true,
2624d58c67d1SFabrice Gasnier 	.start_conv = stm32h7_adc_start_conv,
2625d58c67d1SFabrice Gasnier 	.stop_conv = stm32h7_adc_stop_conv,
2626d58c67d1SFabrice Gasnier 	.prepare = stm32h7_adc_prepare,
2627d58c67d1SFabrice Gasnier 	.unprepare = stm32h7_adc_unprepare,
2628d58c67d1SFabrice Gasnier 	.smp_cycles = stm32h7_adc_smp_cycles,
2629695e2f5cSOlivier Moysan 	.irq_clear = stm32h7_adc_irq_clear,
26307cb2303dSOlivier Moysan 	.ts_int_ch = stm32_adc_min_ts_mp1,
2631d58c67d1SFabrice Gasnier };
2632d58c67d1SFabrice Gasnier 
2633225dc61eSTom Rix static const unsigned int stm32_adc_min_ts_mp13[] = { 100, 0, 0, 4300, 9800 };
26347cb2303dSOlivier Moysan static_assert(ARRAY_SIZE(stm32_adc_min_ts_mp13) == STM32_ADC_INT_CH_NB);
26357cb2303dSOlivier Moysan 
2636cf0fb80aSOlivier Moysan static const struct stm32_adc_cfg stm32mp13_adc_cfg = {
2637cf0fb80aSOlivier Moysan 	.regs = &stm32mp13_adc_regspec,
2638cf0fb80aSOlivier Moysan 	.adc_info = &stm32mp13_adc_info,
2639cf0fb80aSOlivier Moysan 	.trigs = stm32h7_adc_trigs,
2640cf0fb80aSOlivier Moysan 	.start_conv = stm32mp13_adc_start_conv,
2641cf0fb80aSOlivier Moysan 	.stop_conv = stm32h7_adc_stop_conv,
2642cf0fb80aSOlivier Moysan 	.prepare = stm32h7_adc_prepare,
2643cf0fb80aSOlivier Moysan 	.unprepare = stm32h7_adc_unprepare,
2644cf0fb80aSOlivier Moysan 	.smp_cycles = stm32mp13_adc_smp_cycles,
2645cf0fb80aSOlivier Moysan 	.irq_clear = stm32h7_adc_irq_clear,
26467cb2303dSOlivier Moysan 	.ts_int_ch = stm32_adc_min_ts_mp13,
2647cf0fb80aSOlivier Moysan };
2648cf0fb80aSOlivier Moysan 
26490f883b22SFabrice Gasnier static const struct of_device_id stm32_adc_of_match[] = {
265064ad7f64SFabrice Gasnier 	{ .compatible = "st,stm32f4-adc", .data = (void *)&stm32f4_adc_cfg },
265195e339b6SFabrice Gasnier 	{ .compatible = "st,stm32h7-adc", .data = (void *)&stm32h7_adc_cfg },
2652d58c67d1SFabrice Gasnier 	{ .compatible = "st,stm32mp1-adc", .data = (void *)&stm32mp1_adc_cfg },
2653cf0fb80aSOlivier Moysan 	{ .compatible = "st,stm32mp13-adc", .data = (void *)&stm32mp13_adc_cfg },
26540f883b22SFabrice Gasnier 	{},
26550f883b22SFabrice Gasnier };
26560f883b22SFabrice Gasnier MODULE_DEVICE_TABLE(of, stm32_adc_of_match);
26570f883b22SFabrice Gasnier 
26580f883b22SFabrice Gasnier static struct platform_driver stm32_adc_driver = {
26590f883b22SFabrice Gasnier 	.probe = stm32_adc_probe,
2660*da8431b4SUwe Kleine-König 	.remove_new = stm32_adc_remove,
26610f883b22SFabrice Gasnier 	.driver = {
26620f883b22SFabrice Gasnier 		.name = "stm32-adc",
26630f883b22SFabrice Gasnier 		.of_match_table = stm32_adc_of_match,
2664d65daa79SJonathan Cameron 		.pm = pm_ptr(&stm32_adc_pm_ops),
26650f883b22SFabrice Gasnier 	},
26660f883b22SFabrice Gasnier };
26670f883b22SFabrice Gasnier module_platform_driver(stm32_adc_driver);
26680f883b22SFabrice Gasnier 
26690f883b22SFabrice Gasnier MODULE_AUTHOR("Fabrice Gasnier <fabrice.gasnier@st.com>");
26700f883b22SFabrice Gasnier MODULE_DESCRIPTION("STMicroelectronics STM32 ADC IIO driver");
26710f883b22SFabrice Gasnier MODULE_LICENSE("GPL v2");
26720f883b22SFabrice Gasnier MODULE_ALIAS("platform:stm32-adc");
2673