162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * This file is part of STM32 ADC driver
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2016, STMicroelectronics - All Rights Reserved
662306a36Sopenharmony_ci * Author: Fabrice Gasnier <fabrice.gasnier@st.com>.
762306a36Sopenharmony_ci */
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#include <linux/clk.h>
1062306a36Sopenharmony_ci#include <linux/debugfs.h>
1162306a36Sopenharmony_ci#include <linux/delay.h>
1262306a36Sopenharmony_ci#include <linux/dma-mapping.h>
1362306a36Sopenharmony_ci#include <linux/dmaengine.h>
1462306a36Sopenharmony_ci#include <linux/iio/iio.h>
1562306a36Sopenharmony_ci#include <linux/iio/buffer.h>
1662306a36Sopenharmony_ci#include <linux/iio/timer/stm32-lptim-trigger.h>
1762306a36Sopenharmony_ci#include <linux/iio/timer/stm32-timer-trigger.h>
1862306a36Sopenharmony_ci#include <linux/iio/trigger.h>
1962306a36Sopenharmony_ci#include <linux/iio/trigger_consumer.h>
2062306a36Sopenharmony_ci#include <linux/iio/triggered_buffer.h>
2162306a36Sopenharmony_ci#include <linux/interrupt.h>
2262306a36Sopenharmony_ci#include <linux/io.h>
2362306a36Sopenharmony_ci#include <linux/iopoll.h>
2462306a36Sopenharmony_ci#include <linux/module.h>
2562306a36Sopenharmony_ci#include <linux/mod_devicetable.h>
2662306a36Sopenharmony_ci#include <linux/nvmem-consumer.h>
2762306a36Sopenharmony_ci#include <linux/platform_device.h>
2862306a36Sopenharmony_ci#include <linux/pm_runtime.h>
2962306a36Sopenharmony_ci#include <linux/property.h>
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci#include "stm32-adc-core.h"
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci/* Number of linear calibration shadow registers / LINCALRDYW control bits */
3462306a36Sopenharmony_ci#define STM32H7_LINCALFACT_NUM		6
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci/* BOOST bit must be set on STM32H7 when ADC clock is above 20MHz */
3762306a36Sopenharmony_ci#define STM32H7_BOOST_CLKRATE		20000000UL
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci#define STM32_ADC_CH_MAX		20	/* max number of channels */
4062306a36Sopenharmony_ci#define STM32_ADC_CH_SZ			16	/* max channel name size */
4162306a36Sopenharmony_ci#define STM32_ADC_MAX_SQ		16	/* SQ1..SQ16 */
4262306a36Sopenharmony_ci#define STM32_ADC_MAX_SMP		7	/* SMPx range is [0..7] */
4362306a36Sopenharmony_ci#define STM32_ADC_TIMEOUT_US		100000
4462306a36Sopenharmony_ci#define STM32_ADC_TIMEOUT	(msecs_to_jiffies(STM32_ADC_TIMEOUT_US / 1000))
4562306a36Sopenharmony_ci#define STM32_ADC_HW_STOP_DELAY_MS	100
4662306a36Sopenharmony_ci#define STM32_ADC_VREFINT_VOLTAGE	3300
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci#define STM32_DMA_BUFFER_SIZE		PAGE_SIZE
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci/* External trigger enable */
5162306a36Sopenharmony_cienum stm32_adc_exten {
5262306a36Sopenharmony_ci	STM32_EXTEN_SWTRIG,
5362306a36Sopenharmony_ci	STM32_EXTEN_HWTRIG_RISING_EDGE,
5462306a36Sopenharmony_ci	STM32_EXTEN_HWTRIG_FALLING_EDGE,
5562306a36Sopenharmony_ci	STM32_EXTEN_HWTRIG_BOTH_EDGES,
5662306a36Sopenharmony_ci};
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci/* extsel - trigger mux selection value */
5962306a36Sopenharmony_cienum stm32_adc_extsel {
6062306a36Sopenharmony_ci	STM32_EXT0,
6162306a36Sopenharmony_ci	STM32_EXT1,
6262306a36Sopenharmony_ci	STM32_EXT2,
6362306a36Sopenharmony_ci	STM32_EXT3,
6462306a36Sopenharmony_ci	STM32_EXT4,
6562306a36Sopenharmony_ci	STM32_EXT5,
6662306a36Sopenharmony_ci	STM32_EXT6,
6762306a36Sopenharmony_ci	STM32_EXT7,
6862306a36Sopenharmony_ci	STM32_EXT8,
6962306a36Sopenharmony_ci	STM32_EXT9,
7062306a36Sopenharmony_ci	STM32_EXT10,
7162306a36Sopenharmony_ci	STM32_EXT11,
7262306a36Sopenharmony_ci	STM32_EXT12,
7362306a36Sopenharmony_ci	STM32_EXT13,
7462306a36Sopenharmony_ci	STM32_EXT14,
7562306a36Sopenharmony_ci	STM32_EXT15,
7662306a36Sopenharmony_ci	STM32_EXT16,
7762306a36Sopenharmony_ci	STM32_EXT17,
7862306a36Sopenharmony_ci	STM32_EXT18,
7962306a36Sopenharmony_ci	STM32_EXT19,
8062306a36Sopenharmony_ci	STM32_EXT20,
8162306a36Sopenharmony_ci};
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_cienum stm32_adc_int_ch {
8462306a36Sopenharmony_ci	STM32_ADC_INT_CH_NONE = -1,
8562306a36Sopenharmony_ci	STM32_ADC_INT_CH_VDDCORE,
8662306a36Sopenharmony_ci	STM32_ADC_INT_CH_VDDCPU,
8762306a36Sopenharmony_ci	STM32_ADC_INT_CH_VDDQ_DDR,
8862306a36Sopenharmony_ci	STM32_ADC_INT_CH_VREFINT,
8962306a36Sopenharmony_ci	STM32_ADC_INT_CH_VBAT,
9062306a36Sopenharmony_ci	STM32_ADC_INT_CH_NB,
9162306a36Sopenharmony_ci};
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci/**
9462306a36Sopenharmony_ci * struct stm32_adc_ic - ADC internal channels
9562306a36Sopenharmony_ci * @name:	name of the internal channel
9662306a36Sopenharmony_ci * @idx:	internal channel enum index
9762306a36Sopenharmony_ci */
9862306a36Sopenharmony_cistruct stm32_adc_ic {
9962306a36Sopenharmony_ci	const char *name;
10062306a36Sopenharmony_ci	u32 idx;
10162306a36Sopenharmony_ci};
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_cistatic const struct stm32_adc_ic stm32_adc_ic[STM32_ADC_INT_CH_NB] = {
10462306a36Sopenharmony_ci	{ "vddcore", STM32_ADC_INT_CH_VDDCORE },
10562306a36Sopenharmony_ci	{ "vddcpu", STM32_ADC_INT_CH_VDDCPU },
10662306a36Sopenharmony_ci	{ "vddq_ddr", STM32_ADC_INT_CH_VDDQ_DDR },
10762306a36Sopenharmony_ci	{ "vrefint", STM32_ADC_INT_CH_VREFINT },
10862306a36Sopenharmony_ci	{ "vbat", STM32_ADC_INT_CH_VBAT },
10962306a36Sopenharmony_ci};
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci/**
11262306a36Sopenharmony_ci * struct stm32_adc_trig_info - ADC trigger info
11362306a36Sopenharmony_ci * @name:		name of the trigger, corresponding to its source
11462306a36Sopenharmony_ci * @extsel:		trigger selection
11562306a36Sopenharmony_ci */
11662306a36Sopenharmony_cistruct stm32_adc_trig_info {
11762306a36Sopenharmony_ci	const char *name;
11862306a36Sopenharmony_ci	enum stm32_adc_extsel extsel;
11962306a36Sopenharmony_ci};
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_ci/**
12262306a36Sopenharmony_ci * struct stm32_adc_calib - optional adc calibration data
12362306a36Sopenharmony_ci * @lincalfact: Linearity calibration factor
12462306a36Sopenharmony_ci * @lincal_saved: Indicates that linear calibration factors are saved
12562306a36Sopenharmony_ci */
12662306a36Sopenharmony_cistruct stm32_adc_calib {
12762306a36Sopenharmony_ci	u32			lincalfact[STM32H7_LINCALFACT_NUM];
12862306a36Sopenharmony_ci	bool			lincal_saved;
12962306a36Sopenharmony_ci};
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ci/**
13262306a36Sopenharmony_ci * struct stm32_adc_regs - stm32 ADC misc registers & bitfield desc
13362306a36Sopenharmony_ci * @reg:		register offset
13462306a36Sopenharmony_ci * @mask:		bitfield mask
13562306a36Sopenharmony_ci * @shift:		left shift
13662306a36Sopenharmony_ci */
13762306a36Sopenharmony_cistruct stm32_adc_regs {
13862306a36Sopenharmony_ci	int reg;
13962306a36Sopenharmony_ci	int mask;
14062306a36Sopenharmony_ci	int shift;
14162306a36Sopenharmony_ci};
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci/**
14462306a36Sopenharmony_ci * struct stm32_adc_vrefint - stm32 ADC internal reference voltage data
14562306a36Sopenharmony_ci * @vrefint_cal:	vrefint calibration value from nvmem
14662306a36Sopenharmony_ci * @vrefint_data:	vrefint actual value
14762306a36Sopenharmony_ci */
14862306a36Sopenharmony_cistruct stm32_adc_vrefint {
14962306a36Sopenharmony_ci	u32 vrefint_cal;
15062306a36Sopenharmony_ci	u32 vrefint_data;
15162306a36Sopenharmony_ci};
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci/**
15462306a36Sopenharmony_ci * struct stm32_adc_regspec - stm32 registers definition
15562306a36Sopenharmony_ci * @dr:			data register offset
15662306a36Sopenharmony_ci * @ier_eoc:		interrupt enable register & eocie bitfield
15762306a36Sopenharmony_ci * @ier_ovr:		interrupt enable register & overrun bitfield
15862306a36Sopenharmony_ci * @isr_eoc:		interrupt status register & eoc bitfield
15962306a36Sopenharmony_ci * @isr_ovr:		interrupt status register & overrun bitfield
16062306a36Sopenharmony_ci * @sqr:		reference to sequence registers array
16162306a36Sopenharmony_ci * @exten:		trigger control register & bitfield
16262306a36Sopenharmony_ci * @extsel:		trigger selection register & bitfield
16362306a36Sopenharmony_ci * @res:		resolution selection register & bitfield
16462306a36Sopenharmony_ci * @difsel:		differential mode selection register & bitfield
16562306a36Sopenharmony_ci * @smpr:		smpr1 & smpr2 registers offset array
16662306a36Sopenharmony_ci * @smp_bits:		smpr1 & smpr2 index and bitfields
16762306a36Sopenharmony_ci * @or_vddcore:		option register & vddcore bitfield
16862306a36Sopenharmony_ci * @or_vddcpu:		option register & vddcpu bitfield
16962306a36Sopenharmony_ci * @or_vddq_ddr:	option register & vddq_ddr bitfield
17062306a36Sopenharmony_ci * @ccr_vbat:		common register & vbat bitfield
17162306a36Sopenharmony_ci * @ccr_vref:		common register & vrefint bitfield
17262306a36Sopenharmony_ci */
17362306a36Sopenharmony_cistruct stm32_adc_regspec {
17462306a36Sopenharmony_ci	const u32 dr;
17562306a36Sopenharmony_ci	const struct stm32_adc_regs ier_eoc;
17662306a36Sopenharmony_ci	const struct stm32_adc_regs ier_ovr;
17762306a36Sopenharmony_ci	const struct stm32_adc_regs isr_eoc;
17862306a36Sopenharmony_ci	const struct stm32_adc_regs isr_ovr;
17962306a36Sopenharmony_ci	const struct stm32_adc_regs *sqr;
18062306a36Sopenharmony_ci	const struct stm32_adc_regs exten;
18162306a36Sopenharmony_ci	const struct stm32_adc_regs extsel;
18262306a36Sopenharmony_ci	const struct stm32_adc_regs res;
18362306a36Sopenharmony_ci	const struct stm32_adc_regs difsel;
18462306a36Sopenharmony_ci	const u32 smpr[2];
18562306a36Sopenharmony_ci	const struct stm32_adc_regs *smp_bits;
18662306a36Sopenharmony_ci	const struct stm32_adc_regs or_vddcore;
18762306a36Sopenharmony_ci	const struct stm32_adc_regs or_vddcpu;
18862306a36Sopenharmony_ci	const struct stm32_adc_regs or_vddq_ddr;
18962306a36Sopenharmony_ci	const struct stm32_adc_regs ccr_vbat;
19062306a36Sopenharmony_ci	const struct stm32_adc_regs ccr_vref;
19162306a36Sopenharmony_ci};
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_cistruct stm32_adc;
19462306a36Sopenharmony_ci
19562306a36Sopenharmony_ci/**
19662306a36Sopenharmony_ci * struct stm32_adc_cfg - stm32 compatible configuration data
19762306a36Sopenharmony_ci * @regs:		registers descriptions
19862306a36Sopenharmony_ci * @adc_info:		per instance input channels definitions
19962306a36Sopenharmony_ci * @trigs:		external trigger sources
20062306a36Sopenharmony_ci * @clk_required:	clock is required
20162306a36Sopenharmony_ci * @has_vregready:	vregready status flag presence
20262306a36Sopenharmony_ci * @has_boostmode:	boost mode support flag
20362306a36Sopenharmony_ci * @has_linearcal:	linear calibration support flag
20462306a36Sopenharmony_ci * @has_presel:		channel preselection support flag
20562306a36Sopenharmony_ci * @prepare:		optional prepare routine (power-up, enable)
20662306a36Sopenharmony_ci * @start_conv:		routine to start conversions
20762306a36Sopenharmony_ci * @stop_conv:		routine to stop conversions
20862306a36Sopenharmony_ci * @unprepare:		optional unprepare routine (disable, power-down)
20962306a36Sopenharmony_ci * @irq_clear:		routine to clear irqs
21062306a36Sopenharmony_ci * @smp_cycles:		programmable sampling time (ADC clock cycles)
21162306a36Sopenharmony_ci * @ts_int_ch:		pointer to array of internal channels minimum sampling time in ns
21262306a36Sopenharmony_ci */
21362306a36Sopenharmony_cistruct stm32_adc_cfg {
21462306a36Sopenharmony_ci	const struct stm32_adc_regspec	*regs;
21562306a36Sopenharmony_ci	const struct stm32_adc_info	*adc_info;
21662306a36Sopenharmony_ci	struct stm32_adc_trig_info	*trigs;
21762306a36Sopenharmony_ci	bool clk_required;
21862306a36Sopenharmony_ci	bool has_vregready;
21962306a36Sopenharmony_ci	bool has_boostmode;
22062306a36Sopenharmony_ci	bool has_linearcal;
22162306a36Sopenharmony_ci	bool has_presel;
22262306a36Sopenharmony_ci	int (*prepare)(struct iio_dev *);
22362306a36Sopenharmony_ci	void (*start_conv)(struct iio_dev *, bool dma);
22462306a36Sopenharmony_ci	void (*stop_conv)(struct iio_dev *);
22562306a36Sopenharmony_ci	void (*unprepare)(struct iio_dev *);
22662306a36Sopenharmony_ci	void (*irq_clear)(struct iio_dev *indio_dev, u32 msk);
22762306a36Sopenharmony_ci	const unsigned int *smp_cycles;
22862306a36Sopenharmony_ci	const unsigned int *ts_int_ch;
22962306a36Sopenharmony_ci};
23062306a36Sopenharmony_ci
23162306a36Sopenharmony_ci/**
23262306a36Sopenharmony_ci * struct stm32_adc - private data of each ADC IIO instance
23362306a36Sopenharmony_ci * @common:		reference to ADC block common data
23462306a36Sopenharmony_ci * @offset:		ADC instance register offset in ADC block
23562306a36Sopenharmony_ci * @cfg:		compatible configuration data
23662306a36Sopenharmony_ci * @completion:		end of single conversion completion
23762306a36Sopenharmony_ci * @buffer:		data buffer + 8 bytes for timestamp if enabled
23862306a36Sopenharmony_ci * @clk:		clock for this adc instance
23962306a36Sopenharmony_ci * @irq:		interrupt for this adc instance
24062306a36Sopenharmony_ci * @lock:		spinlock
24162306a36Sopenharmony_ci * @bufi:		data buffer index
24262306a36Sopenharmony_ci * @num_conv:		expected number of scan conversions
24362306a36Sopenharmony_ci * @res:		data resolution (e.g. RES bitfield value)
24462306a36Sopenharmony_ci * @trigger_polarity:	external trigger polarity (e.g. exten)
24562306a36Sopenharmony_ci * @dma_chan:		dma channel
24662306a36Sopenharmony_ci * @rx_buf:		dma rx buffer cpu address
24762306a36Sopenharmony_ci * @rx_dma_buf:		dma rx buffer bus address
24862306a36Sopenharmony_ci * @rx_buf_sz:		dma rx buffer size
24962306a36Sopenharmony_ci * @difsel:		bitmask to set single-ended/differential channel
25062306a36Sopenharmony_ci * @pcsel:		bitmask to preselect channels on some devices
25162306a36Sopenharmony_ci * @smpr_val:		sampling time settings (e.g. smpr1 / smpr2)
25262306a36Sopenharmony_ci * @cal:		optional calibration data on some devices
25362306a36Sopenharmony_ci * @vrefint:		internal reference voltage data
25462306a36Sopenharmony_ci * @chan_name:		channel name array
25562306a36Sopenharmony_ci * @num_diff:		number of differential channels
25662306a36Sopenharmony_ci * @int_ch:		internal channel indexes array
25762306a36Sopenharmony_ci * @nsmps:		number of channels with optional sample time
25862306a36Sopenharmony_ci */
25962306a36Sopenharmony_cistruct stm32_adc {
26062306a36Sopenharmony_ci	struct stm32_adc_common	*common;
26162306a36Sopenharmony_ci	u32			offset;
26262306a36Sopenharmony_ci	const struct stm32_adc_cfg	*cfg;
26362306a36Sopenharmony_ci	struct completion	completion;
26462306a36Sopenharmony_ci	u16			buffer[STM32_ADC_MAX_SQ + 4] __aligned(8);
26562306a36Sopenharmony_ci	struct clk		*clk;
26662306a36Sopenharmony_ci	int			irq;
26762306a36Sopenharmony_ci	spinlock_t		lock;		/* interrupt lock */
26862306a36Sopenharmony_ci	unsigned int		bufi;
26962306a36Sopenharmony_ci	unsigned int		num_conv;
27062306a36Sopenharmony_ci	u32			res;
27162306a36Sopenharmony_ci	u32			trigger_polarity;
27262306a36Sopenharmony_ci	struct dma_chan		*dma_chan;
27362306a36Sopenharmony_ci	u8			*rx_buf;
27462306a36Sopenharmony_ci	dma_addr_t		rx_dma_buf;
27562306a36Sopenharmony_ci	unsigned int		rx_buf_sz;
27662306a36Sopenharmony_ci	u32			difsel;
27762306a36Sopenharmony_ci	u32			pcsel;
27862306a36Sopenharmony_ci	u32			smpr_val[2];
27962306a36Sopenharmony_ci	struct stm32_adc_calib	cal;
28062306a36Sopenharmony_ci	struct stm32_adc_vrefint vrefint;
28162306a36Sopenharmony_ci	char			chan_name[STM32_ADC_CH_MAX][STM32_ADC_CH_SZ];
28262306a36Sopenharmony_ci	u32			num_diff;
28362306a36Sopenharmony_ci	int			int_ch[STM32_ADC_INT_CH_NB];
28462306a36Sopenharmony_ci	int			nsmps;
28562306a36Sopenharmony_ci};
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_cistruct stm32_adc_diff_channel {
28862306a36Sopenharmony_ci	u32 vinp;
28962306a36Sopenharmony_ci	u32 vinn;
29062306a36Sopenharmony_ci};
29162306a36Sopenharmony_ci
29262306a36Sopenharmony_ci/**
29362306a36Sopenharmony_ci * struct stm32_adc_info - stm32 ADC, per instance config data
29462306a36Sopenharmony_ci * @max_channels:	Number of channels
29562306a36Sopenharmony_ci * @resolutions:	available resolutions
29662306a36Sopenharmony_ci * @num_res:		number of available resolutions
29762306a36Sopenharmony_ci */
29862306a36Sopenharmony_cistruct stm32_adc_info {
29962306a36Sopenharmony_ci	int max_channels;
30062306a36Sopenharmony_ci	const unsigned int *resolutions;
30162306a36Sopenharmony_ci	const unsigned int num_res;
30262306a36Sopenharmony_ci};
30362306a36Sopenharmony_ci
30462306a36Sopenharmony_cistatic const unsigned int stm32f4_adc_resolutions[] = {
30562306a36Sopenharmony_ci	/* sorted values so the index matches RES[1:0] in STM32F4_ADC_CR1 */
30662306a36Sopenharmony_ci	12, 10, 8, 6,
30762306a36Sopenharmony_ci};
30862306a36Sopenharmony_ci
30962306a36Sopenharmony_ci/* stm32f4 can have up to 16 channels */
31062306a36Sopenharmony_cistatic const struct stm32_adc_info stm32f4_adc_info = {
31162306a36Sopenharmony_ci	.max_channels = 16,
31262306a36Sopenharmony_ci	.resolutions = stm32f4_adc_resolutions,
31362306a36Sopenharmony_ci	.num_res = ARRAY_SIZE(stm32f4_adc_resolutions),
31462306a36Sopenharmony_ci};
31562306a36Sopenharmony_ci
31662306a36Sopenharmony_cistatic const unsigned int stm32h7_adc_resolutions[] = {
31762306a36Sopenharmony_ci	/* sorted values so the index matches RES[2:0] in STM32H7_ADC_CFGR */
31862306a36Sopenharmony_ci	16, 14, 12, 10, 8,
31962306a36Sopenharmony_ci};
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_ci/* stm32h7 can have up to 20 channels */
32262306a36Sopenharmony_cistatic const struct stm32_adc_info stm32h7_adc_info = {
32362306a36Sopenharmony_ci	.max_channels = STM32_ADC_CH_MAX,
32462306a36Sopenharmony_ci	.resolutions = stm32h7_adc_resolutions,
32562306a36Sopenharmony_ci	.num_res = ARRAY_SIZE(stm32h7_adc_resolutions),
32662306a36Sopenharmony_ci};
32762306a36Sopenharmony_ci
32862306a36Sopenharmony_ci/* stm32mp13 can have up to 19 channels */
32962306a36Sopenharmony_cistatic const struct stm32_adc_info stm32mp13_adc_info = {
33062306a36Sopenharmony_ci	.max_channels = 19,
33162306a36Sopenharmony_ci	.resolutions = stm32f4_adc_resolutions,
33262306a36Sopenharmony_ci	.num_res = ARRAY_SIZE(stm32f4_adc_resolutions),
33362306a36Sopenharmony_ci};
33462306a36Sopenharmony_ci
33562306a36Sopenharmony_ci/*
33662306a36Sopenharmony_ci * stm32f4_sq - describe regular sequence registers
33762306a36Sopenharmony_ci * - L: sequence len (register & bit field)
33862306a36Sopenharmony_ci * - SQ1..SQ16: sequence entries (register & bit field)
33962306a36Sopenharmony_ci */
34062306a36Sopenharmony_cistatic const struct stm32_adc_regs stm32f4_sq[STM32_ADC_MAX_SQ + 1] = {
34162306a36Sopenharmony_ci	/* L: len bit field description to be kept as first element */
34262306a36Sopenharmony_ci	{ STM32F4_ADC_SQR1, GENMASK(23, 20), 20 },
34362306a36Sopenharmony_ci	/* SQ1..SQ16 registers & bit fields (reg, mask, shift) */
34462306a36Sopenharmony_ci	{ STM32F4_ADC_SQR3, GENMASK(4, 0), 0 },
34562306a36Sopenharmony_ci	{ STM32F4_ADC_SQR3, GENMASK(9, 5), 5 },
34662306a36Sopenharmony_ci	{ STM32F4_ADC_SQR3, GENMASK(14, 10), 10 },
34762306a36Sopenharmony_ci	{ STM32F4_ADC_SQR3, GENMASK(19, 15), 15 },
34862306a36Sopenharmony_ci	{ STM32F4_ADC_SQR3, GENMASK(24, 20), 20 },
34962306a36Sopenharmony_ci	{ STM32F4_ADC_SQR3, GENMASK(29, 25), 25 },
35062306a36Sopenharmony_ci	{ STM32F4_ADC_SQR2, GENMASK(4, 0), 0 },
35162306a36Sopenharmony_ci	{ STM32F4_ADC_SQR2, GENMASK(9, 5), 5 },
35262306a36Sopenharmony_ci	{ STM32F4_ADC_SQR2, GENMASK(14, 10), 10 },
35362306a36Sopenharmony_ci	{ STM32F4_ADC_SQR2, GENMASK(19, 15), 15 },
35462306a36Sopenharmony_ci	{ STM32F4_ADC_SQR2, GENMASK(24, 20), 20 },
35562306a36Sopenharmony_ci	{ STM32F4_ADC_SQR2, GENMASK(29, 25), 25 },
35662306a36Sopenharmony_ci	{ STM32F4_ADC_SQR1, GENMASK(4, 0), 0 },
35762306a36Sopenharmony_ci	{ STM32F4_ADC_SQR1, GENMASK(9, 5), 5 },
35862306a36Sopenharmony_ci	{ STM32F4_ADC_SQR1, GENMASK(14, 10), 10 },
35962306a36Sopenharmony_ci	{ STM32F4_ADC_SQR1, GENMASK(19, 15), 15 },
36062306a36Sopenharmony_ci};
36162306a36Sopenharmony_ci
36262306a36Sopenharmony_ci/* STM32F4 external trigger sources for all instances */
36362306a36Sopenharmony_cistatic struct stm32_adc_trig_info stm32f4_adc_trigs[] = {
36462306a36Sopenharmony_ci	{ TIM1_CH1, STM32_EXT0 },
36562306a36Sopenharmony_ci	{ TIM1_CH2, STM32_EXT1 },
36662306a36Sopenharmony_ci	{ TIM1_CH3, STM32_EXT2 },
36762306a36Sopenharmony_ci	{ TIM2_CH2, STM32_EXT3 },
36862306a36Sopenharmony_ci	{ TIM2_CH3, STM32_EXT4 },
36962306a36Sopenharmony_ci	{ TIM2_CH4, STM32_EXT5 },
37062306a36Sopenharmony_ci	{ TIM2_TRGO, STM32_EXT6 },
37162306a36Sopenharmony_ci	{ TIM3_CH1, STM32_EXT7 },
37262306a36Sopenharmony_ci	{ TIM3_TRGO, STM32_EXT8 },
37362306a36Sopenharmony_ci	{ TIM4_CH4, STM32_EXT9 },
37462306a36Sopenharmony_ci	{ TIM5_CH1, STM32_EXT10 },
37562306a36Sopenharmony_ci	{ TIM5_CH2, STM32_EXT11 },
37662306a36Sopenharmony_ci	{ TIM5_CH3, STM32_EXT12 },
37762306a36Sopenharmony_ci	{ TIM8_CH1, STM32_EXT13 },
37862306a36Sopenharmony_ci	{ TIM8_TRGO, STM32_EXT14 },
37962306a36Sopenharmony_ci	{}, /* sentinel */
38062306a36Sopenharmony_ci};
38162306a36Sopenharmony_ci
38262306a36Sopenharmony_ci/*
38362306a36Sopenharmony_ci * stm32f4_smp_bits[] - describe sampling time register index & bit fields
38462306a36Sopenharmony_ci * Sorted so it can be indexed by channel number.
38562306a36Sopenharmony_ci */
38662306a36Sopenharmony_cistatic const struct stm32_adc_regs stm32f4_smp_bits[] = {
38762306a36Sopenharmony_ci	/* STM32F4_ADC_SMPR2: smpr[] index, mask, shift for SMP0 to SMP9 */
38862306a36Sopenharmony_ci	{ 1, GENMASK(2, 0), 0 },
38962306a36Sopenharmony_ci	{ 1, GENMASK(5, 3), 3 },
39062306a36Sopenharmony_ci	{ 1, GENMASK(8, 6), 6 },
39162306a36Sopenharmony_ci	{ 1, GENMASK(11, 9), 9 },
39262306a36Sopenharmony_ci	{ 1, GENMASK(14, 12), 12 },
39362306a36Sopenharmony_ci	{ 1, GENMASK(17, 15), 15 },
39462306a36Sopenharmony_ci	{ 1, GENMASK(20, 18), 18 },
39562306a36Sopenharmony_ci	{ 1, GENMASK(23, 21), 21 },
39662306a36Sopenharmony_ci	{ 1, GENMASK(26, 24), 24 },
39762306a36Sopenharmony_ci	{ 1, GENMASK(29, 27), 27 },
39862306a36Sopenharmony_ci	/* STM32F4_ADC_SMPR1, smpr[] index, mask, shift for SMP10 to SMP18 */
39962306a36Sopenharmony_ci	{ 0, GENMASK(2, 0), 0 },
40062306a36Sopenharmony_ci	{ 0, GENMASK(5, 3), 3 },
40162306a36Sopenharmony_ci	{ 0, GENMASK(8, 6), 6 },
40262306a36Sopenharmony_ci	{ 0, GENMASK(11, 9), 9 },
40362306a36Sopenharmony_ci	{ 0, GENMASK(14, 12), 12 },
40462306a36Sopenharmony_ci	{ 0, GENMASK(17, 15), 15 },
40562306a36Sopenharmony_ci	{ 0, GENMASK(20, 18), 18 },
40662306a36Sopenharmony_ci	{ 0, GENMASK(23, 21), 21 },
40762306a36Sopenharmony_ci	{ 0, GENMASK(26, 24), 24 },
40862306a36Sopenharmony_ci};
40962306a36Sopenharmony_ci
41062306a36Sopenharmony_ci/* STM32F4 programmable sampling time (ADC clock cycles) */
41162306a36Sopenharmony_cistatic const unsigned int stm32f4_adc_smp_cycles[STM32_ADC_MAX_SMP + 1] = {
41262306a36Sopenharmony_ci	3, 15, 28, 56, 84, 112, 144, 480,
41362306a36Sopenharmony_ci};
41462306a36Sopenharmony_ci
41562306a36Sopenharmony_cistatic const struct stm32_adc_regspec stm32f4_adc_regspec = {
41662306a36Sopenharmony_ci	.dr = STM32F4_ADC_DR,
41762306a36Sopenharmony_ci	.ier_eoc = { STM32F4_ADC_CR1, STM32F4_EOCIE },
41862306a36Sopenharmony_ci	.ier_ovr = { STM32F4_ADC_CR1, STM32F4_OVRIE },
41962306a36Sopenharmony_ci	.isr_eoc = { STM32F4_ADC_SR, STM32F4_EOC },
42062306a36Sopenharmony_ci	.isr_ovr = { STM32F4_ADC_SR, STM32F4_OVR },
42162306a36Sopenharmony_ci	.sqr = stm32f4_sq,
42262306a36Sopenharmony_ci	.exten = { STM32F4_ADC_CR2, STM32F4_EXTEN_MASK, STM32F4_EXTEN_SHIFT },
42362306a36Sopenharmony_ci	.extsel = { STM32F4_ADC_CR2, STM32F4_EXTSEL_MASK,
42462306a36Sopenharmony_ci		    STM32F4_EXTSEL_SHIFT },
42562306a36Sopenharmony_ci	.res = { STM32F4_ADC_CR1, STM32F4_RES_MASK, STM32F4_RES_SHIFT },
42662306a36Sopenharmony_ci	.smpr = { STM32F4_ADC_SMPR1, STM32F4_ADC_SMPR2 },
42762306a36Sopenharmony_ci	.smp_bits = stm32f4_smp_bits,
42862306a36Sopenharmony_ci};
42962306a36Sopenharmony_ci
43062306a36Sopenharmony_cistatic const struct stm32_adc_regs stm32h7_sq[STM32_ADC_MAX_SQ + 1] = {
43162306a36Sopenharmony_ci	/* L: len bit field description to be kept as first element */
43262306a36Sopenharmony_ci	{ STM32H7_ADC_SQR1, GENMASK(3, 0), 0 },
43362306a36Sopenharmony_ci	/* SQ1..SQ16 registers & bit fields (reg, mask, shift) */
43462306a36Sopenharmony_ci	{ STM32H7_ADC_SQR1, GENMASK(10, 6), 6 },
43562306a36Sopenharmony_ci	{ STM32H7_ADC_SQR1, GENMASK(16, 12), 12 },
43662306a36Sopenharmony_ci	{ STM32H7_ADC_SQR1, GENMASK(22, 18), 18 },
43762306a36Sopenharmony_ci	{ STM32H7_ADC_SQR1, GENMASK(28, 24), 24 },
43862306a36Sopenharmony_ci	{ STM32H7_ADC_SQR2, GENMASK(4, 0), 0 },
43962306a36Sopenharmony_ci	{ STM32H7_ADC_SQR2, GENMASK(10, 6), 6 },
44062306a36Sopenharmony_ci	{ STM32H7_ADC_SQR2, GENMASK(16, 12), 12 },
44162306a36Sopenharmony_ci	{ STM32H7_ADC_SQR2, GENMASK(22, 18), 18 },
44262306a36Sopenharmony_ci	{ STM32H7_ADC_SQR2, GENMASK(28, 24), 24 },
44362306a36Sopenharmony_ci	{ STM32H7_ADC_SQR3, GENMASK(4, 0), 0 },
44462306a36Sopenharmony_ci	{ STM32H7_ADC_SQR3, GENMASK(10, 6), 6 },
44562306a36Sopenharmony_ci	{ STM32H7_ADC_SQR3, GENMASK(16, 12), 12 },
44662306a36Sopenharmony_ci	{ STM32H7_ADC_SQR3, GENMASK(22, 18), 18 },
44762306a36Sopenharmony_ci	{ STM32H7_ADC_SQR3, GENMASK(28, 24), 24 },
44862306a36Sopenharmony_ci	{ STM32H7_ADC_SQR4, GENMASK(4, 0), 0 },
44962306a36Sopenharmony_ci	{ STM32H7_ADC_SQR4, GENMASK(10, 6), 6 },
45062306a36Sopenharmony_ci};
45162306a36Sopenharmony_ci
45262306a36Sopenharmony_ci/* STM32H7 external trigger sources for all instances */
45362306a36Sopenharmony_cistatic struct stm32_adc_trig_info stm32h7_adc_trigs[] = {
45462306a36Sopenharmony_ci	{ TIM1_CH1, STM32_EXT0 },
45562306a36Sopenharmony_ci	{ TIM1_CH2, STM32_EXT1 },
45662306a36Sopenharmony_ci	{ TIM1_CH3, STM32_EXT2 },
45762306a36Sopenharmony_ci	{ TIM2_CH2, STM32_EXT3 },
45862306a36Sopenharmony_ci	{ TIM3_TRGO, STM32_EXT4 },
45962306a36Sopenharmony_ci	{ TIM4_CH4, STM32_EXT5 },
46062306a36Sopenharmony_ci	{ TIM8_TRGO, STM32_EXT7 },
46162306a36Sopenharmony_ci	{ TIM8_TRGO2, STM32_EXT8 },
46262306a36Sopenharmony_ci	{ TIM1_TRGO, STM32_EXT9 },
46362306a36Sopenharmony_ci	{ TIM1_TRGO2, STM32_EXT10 },
46462306a36Sopenharmony_ci	{ TIM2_TRGO, STM32_EXT11 },
46562306a36Sopenharmony_ci	{ TIM4_TRGO, STM32_EXT12 },
46662306a36Sopenharmony_ci	{ TIM6_TRGO, STM32_EXT13 },
46762306a36Sopenharmony_ci	{ TIM15_TRGO, STM32_EXT14 },
46862306a36Sopenharmony_ci	{ TIM3_CH4, STM32_EXT15 },
46962306a36Sopenharmony_ci	{ LPTIM1_OUT, STM32_EXT18 },
47062306a36Sopenharmony_ci	{ LPTIM2_OUT, STM32_EXT19 },
47162306a36Sopenharmony_ci	{ LPTIM3_OUT, STM32_EXT20 },
47262306a36Sopenharmony_ci	{},
47362306a36Sopenharmony_ci};
47462306a36Sopenharmony_ci
47562306a36Sopenharmony_ci/*
47662306a36Sopenharmony_ci * stm32h7_smp_bits - describe sampling time register index & bit fields
47762306a36Sopenharmony_ci * Sorted so it can be indexed by channel number.
47862306a36Sopenharmony_ci */
47962306a36Sopenharmony_cistatic const struct stm32_adc_regs stm32h7_smp_bits[] = {
48062306a36Sopenharmony_ci	/* STM32H7_ADC_SMPR1, smpr[] index, mask, shift for SMP0 to SMP9 */
48162306a36Sopenharmony_ci	{ 0, GENMASK(2, 0), 0 },
48262306a36Sopenharmony_ci	{ 0, GENMASK(5, 3), 3 },
48362306a36Sopenharmony_ci	{ 0, GENMASK(8, 6), 6 },
48462306a36Sopenharmony_ci	{ 0, GENMASK(11, 9), 9 },
48562306a36Sopenharmony_ci	{ 0, GENMASK(14, 12), 12 },
48662306a36Sopenharmony_ci	{ 0, GENMASK(17, 15), 15 },
48762306a36Sopenharmony_ci	{ 0, GENMASK(20, 18), 18 },
48862306a36Sopenharmony_ci	{ 0, GENMASK(23, 21), 21 },
48962306a36Sopenharmony_ci	{ 0, GENMASK(26, 24), 24 },
49062306a36Sopenharmony_ci	{ 0, GENMASK(29, 27), 27 },
49162306a36Sopenharmony_ci	/* STM32H7_ADC_SMPR2, smpr[] index, mask, shift for SMP10 to SMP19 */
49262306a36Sopenharmony_ci	{ 1, GENMASK(2, 0), 0 },
49362306a36Sopenharmony_ci	{ 1, GENMASK(5, 3), 3 },
49462306a36Sopenharmony_ci	{ 1, GENMASK(8, 6), 6 },
49562306a36Sopenharmony_ci	{ 1, GENMASK(11, 9), 9 },
49662306a36Sopenharmony_ci	{ 1, GENMASK(14, 12), 12 },
49762306a36Sopenharmony_ci	{ 1, GENMASK(17, 15), 15 },
49862306a36Sopenharmony_ci	{ 1, GENMASK(20, 18), 18 },
49962306a36Sopenharmony_ci	{ 1, GENMASK(23, 21), 21 },
50062306a36Sopenharmony_ci	{ 1, GENMASK(26, 24), 24 },
50162306a36Sopenharmony_ci	{ 1, GENMASK(29, 27), 27 },
50262306a36Sopenharmony_ci};
50362306a36Sopenharmony_ci
50462306a36Sopenharmony_ci/* STM32H7 programmable sampling time (ADC clock cycles, rounded down) */
50562306a36Sopenharmony_cistatic const unsigned int stm32h7_adc_smp_cycles[STM32_ADC_MAX_SMP + 1] = {
50662306a36Sopenharmony_ci	1, 2, 8, 16, 32, 64, 387, 810,
50762306a36Sopenharmony_ci};
50862306a36Sopenharmony_ci
50962306a36Sopenharmony_cistatic const struct stm32_adc_regspec stm32h7_adc_regspec = {
51062306a36Sopenharmony_ci	.dr = STM32H7_ADC_DR,
51162306a36Sopenharmony_ci	.ier_eoc = { STM32H7_ADC_IER, STM32H7_EOCIE },
51262306a36Sopenharmony_ci	.ier_ovr = { STM32H7_ADC_IER, STM32H7_OVRIE },
51362306a36Sopenharmony_ci	.isr_eoc = { STM32H7_ADC_ISR, STM32H7_EOC },
51462306a36Sopenharmony_ci	.isr_ovr = { STM32H7_ADC_ISR, STM32H7_OVR },
51562306a36Sopenharmony_ci	.sqr = stm32h7_sq,
51662306a36Sopenharmony_ci	.exten = { STM32H7_ADC_CFGR, STM32H7_EXTEN_MASK, STM32H7_EXTEN_SHIFT },
51762306a36Sopenharmony_ci	.extsel = { STM32H7_ADC_CFGR, STM32H7_EXTSEL_MASK,
51862306a36Sopenharmony_ci		    STM32H7_EXTSEL_SHIFT },
51962306a36Sopenharmony_ci	.res = { STM32H7_ADC_CFGR, STM32H7_RES_MASK, STM32H7_RES_SHIFT },
52062306a36Sopenharmony_ci	.difsel = { STM32H7_ADC_DIFSEL, STM32H7_DIFSEL_MASK},
52162306a36Sopenharmony_ci	.smpr = { STM32H7_ADC_SMPR1, STM32H7_ADC_SMPR2 },
52262306a36Sopenharmony_ci	.smp_bits = stm32h7_smp_bits,
52362306a36Sopenharmony_ci};
52462306a36Sopenharmony_ci
52562306a36Sopenharmony_ci/* STM32MP13 programmable sampling time (ADC clock cycles, rounded down) */
52662306a36Sopenharmony_cistatic const unsigned int stm32mp13_adc_smp_cycles[STM32_ADC_MAX_SMP + 1] = {
52762306a36Sopenharmony_ci	2, 6, 12, 24, 47, 92, 247, 640,
52862306a36Sopenharmony_ci};
52962306a36Sopenharmony_ci
53062306a36Sopenharmony_cistatic const struct stm32_adc_regspec stm32mp13_adc_regspec = {
53162306a36Sopenharmony_ci	.dr = STM32H7_ADC_DR,
53262306a36Sopenharmony_ci	.ier_eoc = { STM32H7_ADC_IER, STM32H7_EOCIE },
53362306a36Sopenharmony_ci	.ier_ovr = { STM32H7_ADC_IER, STM32H7_OVRIE },
53462306a36Sopenharmony_ci	.isr_eoc = { STM32H7_ADC_ISR, STM32H7_EOC },
53562306a36Sopenharmony_ci	.isr_ovr = { STM32H7_ADC_ISR, STM32H7_OVR },
53662306a36Sopenharmony_ci	.sqr = stm32h7_sq,
53762306a36Sopenharmony_ci	.exten = { STM32H7_ADC_CFGR, STM32H7_EXTEN_MASK, STM32H7_EXTEN_SHIFT },
53862306a36Sopenharmony_ci	.extsel = { STM32H7_ADC_CFGR, STM32H7_EXTSEL_MASK,
53962306a36Sopenharmony_ci		    STM32H7_EXTSEL_SHIFT },
54062306a36Sopenharmony_ci	.res = { STM32H7_ADC_CFGR, STM32MP13_RES_MASK, STM32MP13_RES_SHIFT },
54162306a36Sopenharmony_ci	.difsel = { STM32MP13_ADC_DIFSEL, STM32MP13_DIFSEL_MASK},
54262306a36Sopenharmony_ci	.smpr = { STM32H7_ADC_SMPR1, STM32H7_ADC_SMPR2 },
54362306a36Sopenharmony_ci	.smp_bits = stm32h7_smp_bits,
54462306a36Sopenharmony_ci	.or_vddcore = { STM32MP13_ADC2_OR, STM32MP13_OP0 },
54562306a36Sopenharmony_ci	.or_vddcpu = { STM32MP13_ADC2_OR, STM32MP13_OP1 },
54662306a36Sopenharmony_ci	.or_vddq_ddr = { STM32MP13_ADC2_OR, STM32MP13_OP2 },
54762306a36Sopenharmony_ci	.ccr_vbat = { STM32H7_ADC_CCR, STM32H7_VBATEN },
54862306a36Sopenharmony_ci	.ccr_vref = { STM32H7_ADC_CCR, STM32H7_VREFEN },
54962306a36Sopenharmony_ci};
55062306a36Sopenharmony_ci
55162306a36Sopenharmony_cistatic const struct stm32_adc_regspec stm32mp1_adc_regspec = {
55262306a36Sopenharmony_ci	.dr = STM32H7_ADC_DR,
55362306a36Sopenharmony_ci	.ier_eoc = { STM32H7_ADC_IER, STM32H7_EOCIE },
55462306a36Sopenharmony_ci	.ier_ovr = { STM32H7_ADC_IER, STM32H7_OVRIE },
55562306a36Sopenharmony_ci	.isr_eoc = { STM32H7_ADC_ISR, STM32H7_EOC },
55662306a36Sopenharmony_ci	.isr_ovr = { STM32H7_ADC_ISR, STM32H7_OVR },
55762306a36Sopenharmony_ci	.sqr = stm32h7_sq,
55862306a36Sopenharmony_ci	.exten = { STM32H7_ADC_CFGR, STM32H7_EXTEN_MASK, STM32H7_EXTEN_SHIFT },
55962306a36Sopenharmony_ci	.extsel = { STM32H7_ADC_CFGR, STM32H7_EXTSEL_MASK,
56062306a36Sopenharmony_ci		    STM32H7_EXTSEL_SHIFT },
56162306a36Sopenharmony_ci	.res = { STM32H7_ADC_CFGR, STM32H7_RES_MASK, STM32H7_RES_SHIFT },
56262306a36Sopenharmony_ci	.difsel = { STM32H7_ADC_DIFSEL, STM32H7_DIFSEL_MASK},
56362306a36Sopenharmony_ci	.smpr = { STM32H7_ADC_SMPR1, STM32H7_ADC_SMPR2 },
56462306a36Sopenharmony_ci	.smp_bits = stm32h7_smp_bits,
56562306a36Sopenharmony_ci	.or_vddcore = { STM32MP1_ADC2_OR, STM32MP1_VDDCOREEN },
56662306a36Sopenharmony_ci	.ccr_vbat = { STM32H7_ADC_CCR, STM32H7_VBATEN },
56762306a36Sopenharmony_ci	.ccr_vref = { STM32H7_ADC_CCR, STM32H7_VREFEN },
56862306a36Sopenharmony_ci};
56962306a36Sopenharmony_ci
57062306a36Sopenharmony_ci/*
57162306a36Sopenharmony_ci * STM32 ADC registers access routines
57262306a36Sopenharmony_ci * @adc: stm32 adc instance
57362306a36Sopenharmony_ci * @reg: reg offset in adc instance
57462306a36Sopenharmony_ci *
57562306a36Sopenharmony_ci * Note: All instances share same base, with 0x0, 0x100 or 0x200 offset resp.
57662306a36Sopenharmony_ci * for adc1, adc2 and adc3.
57762306a36Sopenharmony_ci */
57862306a36Sopenharmony_cistatic u32 stm32_adc_readl(struct stm32_adc *adc, u32 reg)
57962306a36Sopenharmony_ci{
58062306a36Sopenharmony_ci	return readl_relaxed(adc->common->base + adc->offset + reg);
58162306a36Sopenharmony_ci}
58262306a36Sopenharmony_ci
58362306a36Sopenharmony_ci#define stm32_adc_readl_addr(addr)	stm32_adc_readl(adc, addr)
58462306a36Sopenharmony_ci
58562306a36Sopenharmony_ci#define stm32_adc_readl_poll_timeout(reg, val, cond, sleep_us, timeout_us) \
58662306a36Sopenharmony_ci	readx_poll_timeout(stm32_adc_readl_addr, reg, val, \
58762306a36Sopenharmony_ci			   cond, sleep_us, timeout_us)
58862306a36Sopenharmony_ci
58962306a36Sopenharmony_cistatic u16 stm32_adc_readw(struct stm32_adc *adc, u32 reg)
59062306a36Sopenharmony_ci{
59162306a36Sopenharmony_ci	return readw_relaxed(adc->common->base + adc->offset + reg);
59262306a36Sopenharmony_ci}
59362306a36Sopenharmony_ci
59462306a36Sopenharmony_cistatic void stm32_adc_writel(struct stm32_adc *adc, u32 reg, u32 val)
59562306a36Sopenharmony_ci{
59662306a36Sopenharmony_ci	writel_relaxed(val, adc->common->base + adc->offset + reg);
59762306a36Sopenharmony_ci}
59862306a36Sopenharmony_ci
59962306a36Sopenharmony_cistatic void stm32_adc_set_bits(struct stm32_adc *adc, u32 reg, u32 bits)
60062306a36Sopenharmony_ci{
60162306a36Sopenharmony_ci	unsigned long flags;
60262306a36Sopenharmony_ci
60362306a36Sopenharmony_ci	spin_lock_irqsave(&adc->lock, flags);
60462306a36Sopenharmony_ci	stm32_adc_writel(adc, reg, stm32_adc_readl(adc, reg) | bits);
60562306a36Sopenharmony_ci	spin_unlock_irqrestore(&adc->lock, flags);
60662306a36Sopenharmony_ci}
60762306a36Sopenharmony_ci
60862306a36Sopenharmony_cistatic void stm32_adc_set_bits_common(struct stm32_adc *adc, u32 reg, u32 bits)
60962306a36Sopenharmony_ci{
61062306a36Sopenharmony_ci	spin_lock(&adc->common->lock);
61162306a36Sopenharmony_ci	writel_relaxed(readl_relaxed(adc->common->base + reg) | bits,
61262306a36Sopenharmony_ci		       adc->common->base + reg);
61362306a36Sopenharmony_ci	spin_unlock(&adc->common->lock);
61462306a36Sopenharmony_ci}
61562306a36Sopenharmony_ci
61662306a36Sopenharmony_cistatic void stm32_adc_clr_bits(struct stm32_adc *adc, u32 reg, u32 bits)
61762306a36Sopenharmony_ci{
61862306a36Sopenharmony_ci	unsigned long flags;
61962306a36Sopenharmony_ci
62062306a36Sopenharmony_ci	spin_lock_irqsave(&adc->lock, flags);
62162306a36Sopenharmony_ci	stm32_adc_writel(adc, reg, stm32_adc_readl(adc, reg) & ~bits);
62262306a36Sopenharmony_ci	spin_unlock_irqrestore(&adc->lock, flags);
62362306a36Sopenharmony_ci}
62462306a36Sopenharmony_ci
62562306a36Sopenharmony_cistatic void stm32_adc_clr_bits_common(struct stm32_adc *adc, u32 reg, u32 bits)
62662306a36Sopenharmony_ci{
62762306a36Sopenharmony_ci	spin_lock(&adc->common->lock);
62862306a36Sopenharmony_ci	writel_relaxed(readl_relaxed(adc->common->base + reg) & ~bits,
62962306a36Sopenharmony_ci		       adc->common->base + reg);
63062306a36Sopenharmony_ci	spin_unlock(&adc->common->lock);
63162306a36Sopenharmony_ci}
63262306a36Sopenharmony_ci
63362306a36Sopenharmony_ci/**
63462306a36Sopenharmony_ci * stm32_adc_conv_irq_enable() - Enable end of conversion interrupt
63562306a36Sopenharmony_ci * @adc: stm32 adc instance
63662306a36Sopenharmony_ci */
63762306a36Sopenharmony_cistatic void stm32_adc_conv_irq_enable(struct stm32_adc *adc)
63862306a36Sopenharmony_ci{
63962306a36Sopenharmony_ci	stm32_adc_set_bits(adc, adc->cfg->regs->ier_eoc.reg,
64062306a36Sopenharmony_ci			   adc->cfg->regs->ier_eoc.mask);
64162306a36Sopenharmony_ci};
64262306a36Sopenharmony_ci
64362306a36Sopenharmony_ci/**
64462306a36Sopenharmony_ci * stm32_adc_conv_irq_disable() - Disable end of conversion interrupt
64562306a36Sopenharmony_ci * @adc: stm32 adc instance
64662306a36Sopenharmony_ci */
64762306a36Sopenharmony_cistatic void stm32_adc_conv_irq_disable(struct stm32_adc *adc)
64862306a36Sopenharmony_ci{
64962306a36Sopenharmony_ci	stm32_adc_clr_bits(adc, adc->cfg->regs->ier_eoc.reg,
65062306a36Sopenharmony_ci			   adc->cfg->regs->ier_eoc.mask);
65162306a36Sopenharmony_ci}
65262306a36Sopenharmony_ci
65362306a36Sopenharmony_cistatic void stm32_adc_ovr_irq_enable(struct stm32_adc *adc)
65462306a36Sopenharmony_ci{
65562306a36Sopenharmony_ci	stm32_adc_set_bits(adc, adc->cfg->regs->ier_ovr.reg,
65662306a36Sopenharmony_ci			   adc->cfg->regs->ier_ovr.mask);
65762306a36Sopenharmony_ci}
65862306a36Sopenharmony_ci
65962306a36Sopenharmony_cistatic void stm32_adc_ovr_irq_disable(struct stm32_adc *adc)
66062306a36Sopenharmony_ci{
66162306a36Sopenharmony_ci	stm32_adc_clr_bits(adc, adc->cfg->regs->ier_ovr.reg,
66262306a36Sopenharmony_ci			   adc->cfg->regs->ier_ovr.mask);
66362306a36Sopenharmony_ci}
66462306a36Sopenharmony_ci
66562306a36Sopenharmony_cistatic void stm32_adc_set_res(struct stm32_adc *adc)
66662306a36Sopenharmony_ci{
66762306a36Sopenharmony_ci	const struct stm32_adc_regs *res = &adc->cfg->regs->res;
66862306a36Sopenharmony_ci	u32 val;
66962306a36Sopenharmony_ci
67062306a36Sopenharmony_ci	val = stm32_adc_readl(adc, res->reg);
67162306a36Sopenharmony_ci	val = (val & ~res->mask) | (adc->res << res->shift);
67262306a36Sopenharmony_ci	stm32_adc_writel(adc, res->reg, val);
67362306a36Sopenharmony_ci}
67462306a36Sopenharmony_ci
67562306a36Sopenharmony_cistatic int stm32_adc_hw_stop(struct device *dev)
67662306a36Sopenharmony_ci{
67762306a36Sopenharmony_ci	struct iio_dev *indio_dev = dev_get_drvdata(dev);
67862306a36Sopenharmony_ci	struct stm32_adc *adc = iio_priv(indio_dev);
67962306a36Sopenharmony_ci
68062306a36Sopenharmony_ci	if (adc->cfg->unprepare)
68162306a36Sopenharmony_ci		adc->cfg->unprepare(indio_dev);
68262306a36Sopenharmony_ci
68362306a36Sopenharmony_ci	clk_disable_unprepare(adc->clk);
68462306a36Sopenharmony_ci
68562306a36Sopenharmony_ci	return 0;
68662306a36Sopenharmony_ci}
68762306a36Sopenharmony_ci
68862306a36Sopenharmony_cistatic int stm32_adc_hw_start(struct device *dev)
68962306a36Sopenharmony_ci{
69062306a36Sopenharmony_ci	struct iio_dev *indio_dev = dev_get_drvdata(dev);
69162306a36Sopenharmony_ci	struct stm32_adc *adc = iio_priv(indio_dev);
69262306a36Sopenharmony_ci	int ret;
69362306a36Sopenharmony_ci
69462306a36Sopenharmony_ci	ret = clk_prepare_enable(adc->clk);
69562306a36Sopenharmony_ci	if (ret)
69662306a36Sopenharmony_ci		return ret;
69762306a36Sopenharmony_ci
69862306a36Sopenharmony_ci	stm32_adc_set_res(adc);
69962306a36Sopenharmony_ci
70062306a36Sopenharmony_ci	if (adc->cfg->prepare) {
70162306a36Sopenharmony_ci		ret = adc->cfg->prepare(indio_dev);
70262306a36Sopenharmony_ci		if (ret)
70362306a36Sopenharmony_ci			goto err_clk_dis;
70462306a36Sopenharmony_ci	}
70562306a36Sopenharmony_ci
70662306a36Sopenharmony_ci	return 0;
70762306a36Sopenharmony_ci
70862306a36Sopenharmony_cierr_clk_dis:
70962306a36Sopenharmony_ci	clk_disable_unprepare(adc->clk);
71062306a36Sopenharmony_ci
71162306a36Sopenharmony_ci	return ret;
71262306a36Sopenharmony_ci}
71362306a36Sopenharmony_ci
71462306a36Sopenharmony_cistatic void stm32_adc_int_ch_enable(struct iio_dev *indio_dev)
71562306a36Sopenharmony_ci{
71662306a36Sopenharmony_ci	struct stm32_adc *adc = iio_priv(indio_dev);
71762306a36Sopenharmony_ci	u32 i;
71862306a36Sopenharmony_ci
71962306a36Sopenharmony_ci	for (i = 0; i < STM32_ADC_INT_CH_NB; i++) {
72062306a36Sopenharmony_ci		if (adc->int_ch[i] == STM32_ADC_INT_CH_NONE)
72162306a36Sopenharmony_ci			continue;
72262306a36Sopenharmony_ci
72362306a36Sopenharmony_ci		switch (i) {
72462306a36Sopenharmony_ci		case STM32_ADC_INT_CH_VDDCORE:
72562306a36Sopenharmony_ci			dev_dbg(&indio_dev->dev, "Enable VDDCore\n");
72662306a36Sopenharmony_ci			stm32_adc_set_bits(adc, adc->cfg->regs->or_vddcore.reg,
72762306a36Sopenharmony_ci					   adc->cfg->regs->or_vddcore.mask);
72862306a36Sopenharmony_ci			break;
72962306a36Sopenharmony_ci		case STM32_ADC_INT_CH_VDDCPU:
73062306a36Sopenharmony_ci			dev_dbg(&indio_dev->dev, "Enable VDDCPU\n");
73162306a36Sopenharmony_ci			stm32_adc_set_bits(adc, adc->cfg->regs->or_vddcpu.reg,
73262306a36Sopenharmony_ci					   adc->cfg->regs->or_vddcpu.mask);
73362306a36Sopenharmony_ci			break;
73462306a36Sopenharmony_ci		case STM32_ADC_INT_CH_VDDQ_DDR:
73562306a36Sopenharmony_ci			dev_dbg(&indio_dev->dev, "Enable VDDQ_DDR\n");
73662306a36Sopenharmony_ci			stm32_adc_set_bits(adc, adc->cfg->regs->or_vddq_ddr.reg,
73762306a36Sopenharmony_ci					   adc->cfg->regs->or_vddq_ddr.mask);
73862306a36Sopenharmony_ci			break;
73962306a36Sopenharmony_ci		case STM32_ADC_INT_CH_VREFINT:
74062306a36Sopenharmony_ci			dev_dbg(&indio_dev->dev, "Enable VREFInt\n");
74162306a36Sopenharmony_ci			stm32_adc_set_bits_common(adc, adc->cfg->regs->ccr_vref.reg,
74262306a36Sopenharmony_ci						  adc->cfg->regs->ccr_vref.mask);
74362306a36Sopenharmony_ci			break;
74462306a36Sopenharmony_ci		case STM32_ADC_INT_CH_VBAT:
74562306a36Sopenharmony_ci			dev_dbg(&indio_dev->dev, "Enable VBAT\n");
74662306a36Sopenharmony_ci			stm32_adc_set_bits_common(adc, adc->cfg->regs->ccr_vbat.reg,
74762306a36Sopenharmony_ci						  adc->cfg->regs->ccr_vbat.mask);
74862306a36Sopenharmony_ci			break;
74962306a36Sopenharmony_ci		}
75062306a36Sopenharmony_ci	}
75162306a36Sopenharmony_ci}
75262306a36Sopenharmony_ci
75362306a36Sopenharmony_cistatic void stm32_adc_int_ch_disable(struct stm32_adc *adc)
75462306a36Sopenharmony_ci{
75562306a36Sopenharmony_ci	u32 i;
75662306a36Sopenharmony_ci
75762306a36Sopenharmony_ci	for (i = 0; i < STM32_ADC_INT_CH_NB; i++) {
75862306a36Sopenharmony_ci		if (adc->int_ch[i] == STM32_ADC_INT_CH_NONE)
75962306a36Sopenharmony_ci			continue;
76062306a36Sopenharmony_ci
76162306a36Sopenharmony_ci		switch (i) {
76262306a36Sopenharmony_ci		case STM32_ADC_INT_CH_VDDCORE:
76362306a36Sopenharmony_ci			stm32_adc_clr_bits(adc, adc->cfg->regs->or_vddcore.reg,
76462306a36Sopenharmony_ci					   adc->cfg->regs->or_vddcore.mask);
76562306a36Sopenharmony_ci			break;
76662306a36Sopenharmony_ci		case STM32_ADC_INT_CH_VDDCPU:
76762306a36Sopenharmony_ci			stm32_adc_clr_bits(adc, adc->cfg->regs->or_vddcpu.reg,
76862306a36Sopenharmony_ci					   adc->cfg->regs->or_vddcpu.mask);
76962306a36Sopenharmony_ci			break;
77062306a36Sopenharmony_ci		case STM32_ADC_INT_CH_VDDQ_DDR:
77162306a36Sopenharmony_ci			stm32_adc_clr_bits(adc, adc->cfg->regs->or_vddq_ddr.reg,
77262306a36Sopenharmony_ci					   adc->cfg->regs->or_vddq_ddr.mask);
77362306a36Sopenharmony_ci			break;
77462306a36Sopenharmony_ci		case STM32_ADC_INT_CH_VREFINT:
77562306a36Sopenharmony_ci			stm32_adc_clr_bits_common(adc, adc->cfg->regs->ccr_vref.reg,
77662306a36Sopenharmony_ci						  adc->cfg->regs->ccr_vref.mask);
77762306a36Sopenharmony_ci			break;
77862306a36Sopenharmony_ci		case STM32_ADC_INT_CH_VBAT:
77962306a36Sopenharmony_ci			stm32_adc_clr_bits_common(adc, adc->cfg->regs->ccr_vbat.reg,
78062306a36Sopenharmony_ci						  adc->cfg->regs->ccr_vbat.mask);
78162306a36Sopenharmony_ci			break;
78262306a36Sopenharmony_ci		}
78362306a36Sopenharmony_ci	}
78462306a36Sopenharmony_ci}
78562306a36Sopenharmony_ci
78662306a36Sopenharmony_ci/**
78762306a36Sopenharmony_ci * stm32f4_adc_start_conv() - Start conversions for regular channels.
78862306a36Sopenharmony_ci * @indio_dev: IIO device instance
78962306a36Sopenharmony_ci * @dma: use dma to transfer conversion result
79062306a36Sopenharmony_ci *
79162306a36Sopenharmony_ci * Start conversions for regular channels.
79262306a36Sopenharmony_ci * Also take care of normal or DMA mode. Circular DMA may be used for regular
79362306a36Sopenharmony_ci * conversions, in IIO buffer modes. Otherwise, use ADC interrupt with direct
79462306a36Sopenharmony_ci * DR read instead (e.g. read_raw, or triggered buffer mode without DMA).
79562306a36Sopenharmony_ci */
79662306a36Sopenharmony_cistatic void stm32f4_adc_start_conv(struct iio_dev *indio_dev, bool dma)
79762306a36Sopenharmony_ci{
79862306a36Sopenharmony_ci	struct stm32_adc *adc = iio_priv(indio_dev);
79962306a36Sopenharmony_ci
80062306a36Sopenharmony_ci	stm32_adc_set_bits(adc, STM32F4_ADC_CR1, STM32F4_SCAN);
80162306a36Sopenharmony_ci
80262306a36Sopenharmony_ci	if (dma)
80362306a36Sopenharmony_ci		stm32_adc_set_bits(adc, STM32F4_ADC_CR2,
80462306a36Sopenharmony_ci				   STM32F4_DMA | STM32F4_DDS);
80562306a36Sopenharmony_ci
80662306a36Sopenharmony_ci	stm32_adc_set_bits(adc, STM32F4_ADC_CR2, STM32F4_EOCS | STM32F4_ADON);
80762306a36Sopenharmony_ci
80862306a36Sopenharmony_ci	/* Wait for Power-up time (tSTAB from datasheet) */
80962306a36Sopenharmony_ci	usleep_range(2, 3);
81062306a36Sopenharmony_ci
81162306a36Sopenharmony_ci	/* Software start ? (e.g. trigger detection disabled ?) */
81262306a36Sopenharmony_ci	if (!(stm32_adc_readl(adc, STM32F4_ADC_CR2) & STM32F4_EXTEN_MASK))
81362306a36Sopenharmony_ci		stm32_adc_set_bits(adc, STM32F4_ADC_CR2, STM32F4_SWSTART);
81462306a36Sopenharmony_ci}
81562306a36Sopenharmony_ci
81662306a36Sopenharmony_cistatic void stm32f4_adc_stop_conv(struct iio_dev *indio_dev)
81762306a36Sopenharmony_ci{
81862306a36Sopenharmony_ci	struct stm32_adc *adc = iio_priv(indio_dev);
81962306a36Sopenharmony_ci
82062306a36Sopenharmony_ci	stm32_adc_clr_bits(adc, STM32F4_ADC_CR2, STM32F4_EXTEN_MASK);
82162306a36Sopenharmony_ci	stm32_adc_clr_bits(adc, STM32F4_ADC_SR, STM32F4_STRT);
82262306a36Sopenharmony_ci
82362306a36Sopenharmony_ci	stm32_adc_clr_bits(adc, STM32F4_ADC_CR1, STM32F4_SCAN);
82462306a36Sopenharmony_ci	stm32_adc_clr_bits(adc, STM32F4_ADC_CR2,
82562306a36Sopenharmony_ci			   STM32F4_ADON | STM32F4_DMA | STM32F4_DDS);
82662306a36Sopenharmony_ci}
82762306a36Sopenharmony_ci
82862306a36Sopenharmony_cistatic void stm32f4_adc_irq_clear(struct iio_dev *indio_dev, u32 msk)
82962306a36Sopenharmony_ci{
83062306a36Sopenharmony_ci	struct stm32_adc *adc = iio_priv(indio_dev);
83162306a36Sopenharmony_ci
83262306a36Sopenharmony_ci	stm32_adc_clr_bits(adc, adc->cfg->regs->isr_eoc.reg, msk);
83362306a36Sopenharmony_ci}
83462306a36Sopenharmony_ci
83562306a36Sopenharmony_cistatic void stm32h7_adc_start_conv(struct iio_dev *indio_dev, bool dma)
83662306a36Sopenharmony_ci{
83762306a36Sopenharmony_ci	struct stm32_adc *adc = iio_priv(indio_dev);
83862306a36Sopenharmony_ci	enum stm32h7_adc_dmngt dmngt;
83962306a36Sopenharmony_ci	unsigned long flags;
84062306a36Sopenharmony_ci	u32 val;
84162306a36Sopenharmony_ci
84262306a36Sopenharmony_ci	if (dma)
84362306a36Sopenharmony_ci		dmngt = STM32H7_DMNGT_DMA_CIRC;
84462306a36Sopenharmony_ci	else
84562306a36Sopenharmony_ci		dmngt = STM32H7_DMNGT_DR_ONLY;
84662306a36Sopenharmony_ci
84762306a36Sopenharmony_ci	spin_lock_irqsave(&adc->lock, flags);
84862306a36Sopenharmony_ci	val = stm32_adc_readl(adc, STM32H7_ADC_CFGR);
84962306a36Sopenharmony_ci	val = (val & ~STM32H7_DMNGT_MASK) | (dmngt << STM32H7_DMNGT_SHIFT);
85062306a36Sopenharmony_ci	stm32_adc_writel(adc, STM32H7_ADC_CFGR, val);
85162306a36Sopenharmony_ci	spin_unlock_irqrestore(&adc->lock, flags);
85262306a36Sopenharmony_ci
85362306a36Sopenharmony_ci	stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_ADSTART);
85462306a36Sopenharmony_ci}
85562306a36Sopenharmony_ci
85662306a36Sopenharmony_cistatic void stm32h7_adc_stop_conv(struct iio_dev *indio_dev)
85762306a36Sopenharmony_ci{
85862306a36Sopenharmony_ci	struct stm32_adc *adc = iio_priv(indio_dev);
85962306a36Sopenharmony_ci	int ret;
86062306a36Sopenharmony_ci	u32 val;
86162306a36Sopenharmony_ci
86262306a36Sopenharmony_ci	stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_ADSTP);
86362306a36Sopenharmony_ci
86462306a36Sopenharmony_ci	ret = stm32_adc_readl_poll_timeout(STM32H7_ADC_CR, val,
86562306a36Sopenharmony_ci					   !(val & (STM32H7_ADSTART)),
86662306a36Sopenharmony_ci					   100, STM32_ADC_TIMEOUT_US);
86762306a36Sopenharmony_ci	if (ret)
86862306a36Sopenharmony_ci		dev_warn(&indio_dev->dev, "stop failed\n");
86962306a36Sopenharmony_ci
87062306a36Sopenharmony_ci	/* STM32H7_DMNGT_MASK covers STM32MP13_DMAEN & STM32MP13_DMACFG */
87162306a36Sopenharmony_ci	stm32_adc_clr_bits(adc, STM32H7_ADC_CFGR, STM32H7_DMNGT_MASK);
87262306a36Sopenharmony_ci}
87362306a36Sopenharmony_ci
87462306a36Sopenharmony_cistatic void stm32h7_adc_irq_clear(struct iio_dev *indio_dev, u32 msk)
87562306a36Sopenharmony_ci{
87662306a36Sopenharmony_ci	struct stm32_adc *adc = iio_priv(indio_dev);
87762306a36Sopenharmony_ci	/* On STM32H7 IRQs are cleared by writing 1 into ISR register */
87862306a36Sopenharmony_ci	stm32_adc_set_bits(adc, adc->cfg->regs->isr_eoc.reg, msk);
87962306a36Sopenharmony_ci}
88062306a36Sopenharmony_ci
88162306a36Sopenharmony_cistatic void stm32mp13_adc_start_conv(struct iio_dev *indio_dev, bool dma)
88262306a36Sopenharmony_ci{
88362306a36Sopenharmony_ci	struct stm32_adc *adc = iio_priv(indio_dev);
88462306a36Sopenharmony_ci
88562306a36Sopenharmony_ci	if (dma)
88662306a36Sopenharmony_ci		stm32_adc_set_bits(adc, STM32H7_ADC_CFGR,
88762306a36Sopenharmony_ci				   STM32MP13_DMAEN | STM32MP13_DMACFG);
88862306a36Sopenharmony_ci
88962306a36Sopenharmony_ci	stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_ADSTART);
89062306a36Sopenharmony_ci}
89162306a36Sopenharmony_ci
89262306a36Sopenharmony_cistatic int stm32h7_adc_exit_pwr_down(struct iio_dev *indio_dev)
89362306a36Sopenharmony_ci{
89462306a36Sopenharmony_ci	struct stm32_adc *adc = iio_priv(indio_dev);
89562306a36Sopenharmony_ci	int ret;
89662306a36Sopenharmony_ci	u32 val;
89762306a36Sopenharmony_ci
89862306a36Sopenharmony_ci	/* Exit deep power down, then enable ADC voltage regulator */
89962306a36Sopenharmony_ci	stm32_adc_clr_bits(adc, STM32H7_ADC_CR, STM32H7_DEEPPWD);
90062306a36Sopenharmony_ci	stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_ADVREGEN);
90162306a36Sopenharmony_ci
90262306a36Sopenharmony_ci	if (adc->cfg->has_boostmode &&
90362306a36Sopenharmony_ci	    adc->common->rate > STM32H7_BOOST_CLKRATE)
90462306a36Sopenharmony_ci		stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_BOOST);
90562306a36Sopenharmony_ci
90662306a36Sopenharmony_ci	/* Wait for startup time */
90762306a36Sopenharmony_ci	if (!adc->cfg->has_vregready) {
90862306a36Sopenharmony_ci		usleep_range(10, 20);
90962306a36Sopenharmony_ci		return 0;
91062306a36Sopenharmony_ci	}
91162306a36Sopenharmony_ci
91262306a36Sopenharmony_ci	ret = stm32_adc_readl_poll_timeout(STM32H7_ADC_ISR, val,
91362306a36Sopenharmony_ci					   val & STM32MP1_VREGREADY, 100,
91462306a36Sopenharmony_ci					   STM32_ADC_TIMEOUT_US);
91562306a36Sopenharmony_ci	if (ret) {
91662306a36Sopenharmony_ci		stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_DEEPPWD);
91762306a36Sopenharmony_ci		dev_err(&indio_dev->dev, "Failed to exit power down\n");
91862306a36Sopenharmony_ci	}
91962306a36Sopenharmony_ci
92062306a36Sopenharmony_ci	return ret;
92162306a36Sopenharmony_ci}
92262306a36Sopenharmony_ci
92362306a36Sopenharmony_cistatic void stm32h7_adc_enter_pwr_down(struct stm32_adc *adc)
92462306a36Sopenharmony_ci{
92562306a36Sopenharmony_ci	if (adc->cfg->has_boostmode)
92662306a36Sopenharmony_ci		stm32_adc_clr_bits(adc, STM32H7_ADC_CR, STM32H7_BOOST);
92762306a36Sopenharmony_ci
92862306a36Sopenharmony_ci	/* Setting DEEPPWD disables ADC vreg and clears ADVREGEN */
92962306a36Sopenharmony_ci	stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_DEEPPWD);
93062306a36Sopenharmony_ci}
93162306a36Sopenharmony_ci
93262306a36Sopenharmony_cistatic int stm32h7_adc_enable(struct iio_dev *indio_dev)
93362306a36Sopenharmony_ci{
93462306a36Sopenharmony_ci	struct stm32_adc *adc = iio_priv(indio_dev);
93562306a36Sopenharmony_ci	int ret;
93662306a36Sopenharmony_ci	u32 val;
93762306a36Sopenharmony_ci
93862306a36Sopenharmony_ci	stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_ADEN);
93962306a36Sopenharmony_ci
94062306a36Sopenharmony_ci	/* Poll for ADRDY to be set (after adc startup time) */
94162306a36Sopenharmony_ci	ret = stm32_adc_readl_poll_timeout(STM32H7_ADC_ISR, val,
94262306a36Sopenharmony_ci					   val & STM32H7_ADRDY,
94362306a36Sopenharmony_ci					   100, STM32_ADC_TIMEOUT_US);
94462306a36Sopenharmony_ci	if (ret) {
94562306a36Sopenharmony_ci		stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_ADDIS);
94662306a36Sopenharmony_ci		dev_err(&indio_dev->dev, "Failed to enable ADC\n");
94762306a36Sopenharmony_ci	} else {
94862306a36Sopenharmony_ci		/* Clear ADRDY by writing one */
94962306a36Sopenharmony_ci		stm32_adc_set_bits(adc, STM32H7_ADC_ISR, STM32H7_ADRDY);
95062306a36Sopenharmony_ci	}
95162306a36Sopenharmony_ci
95262306a36Sopenharmony_ci	return ret;
95362306a36Sopenharmony_ci}
95462306a36Sopenharmony_ci
95562306a36Sopenharmony_cistatic void stm32h7_adc_disable(struct iio_dev *indio_dev)
95662306a36Sopenharmony_ci{
95762306a36Sopenharmony_ci	struct stm32_adc *adc = iio_priv(indio_dev);
95862306a36Sopenharmony_ci	int ret;
95962306a36Sopenharmony_ci	u32 val;
96062306a36Sopenharmony_ci
96162306a36Sopenharmony_ci	if (!(stm32_adc_readl(adc, STM32H7_ADC_CR) & STM32H7_ADEN))
96262306a36Sopenharmony_ci		return;
96362306a36Sopenharmony_ci
96462306a36Sopenharmony_ci	/* Disable ADC and wait until it's effectively disabled */
96562306a36Sopenharmony_ci	stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_ADDIS);
96662306a36Sopenharmony_ci	ret = stm32_adc_readl_poll_timeout(STM32H7_ADC_CR, val,
96762306a36Sopenharmony_ci					   !(val & STM32H7_ADEN), 100,
96862306a36Sopenharmony_ci					   STM32_ADC_TIMEOUT_US);
96962306a36Sopenharmony_ci	if (ret)
97062306a36Sopenharmony_ci		dev_warn(&indio_dev->dev, "Failed to disable\n");
97162306a36Sopenharmony_ci}
97262306a36Sopenharmony_ci
97362306a36Sopenharmony_ci/**
97462306a36Sopenharmony_ci * stm32h7_adc_read_selfcalib() - read calibration shadow regs, save result
97562306a36Sopenharmony_ci * @indio_dev: IIO device instance
97662306a36Sopenharmony_ci * Note: Must be called once ADC is enabled, so LINCALRDYW[1..6] are writable
97762306a36Sopenharmony_ci */
97862306a36Sopenharmony_cistatic int stm32h7_adc_read_selfcalib(struct iio_dev *indio_dev)
97962306a36Sopenharmony_ci{
98062306a36Sopenharmony_ci	struct stm32_adc *adc = iio_priv(indio_dev);
98162306a36Sopenharmony_ci	int i, ret;
98262306a36Sopenharmony_ci	u32 lincalrdyw_mask, val;
98362306a36Sopenharmony_ci
98462306a36Sopenharmony_ci	/* Read linearity calibration */
98562306a36Sopenharmony_ci	lincalrdyw_mask = STM32H7_LINCALRDYW6;
98662306a36Sopenharmony_ci	for (i = STM32H7_LINCALFACT_NUM - 1; i >= 0; i--) {
98762306a36Sopenharmony_ci		/* Clear STM32H7_LINCALRDYW[6..1]: transfer calib to CALFACT2 */
98862306a36Sopenharmony_ci		stm32_adc_clr_bits(adc, STM32H7_ADC_CR, lincalrdyw_mask);
98962306a36Sopenharmony_ci
99062306a36Sopenharmony_ci		/* Poll: wait calib data to be ready in CALFACT2 register */
99162306a36Sopenharmony_ci		ret = stm32_adc_readl_poll_timeout(STM32H7_ADC_CR, val,
99262306a36Sopenharmony_ci						   !(val & lincalrdyw_mask),
99362306a36Sopenharmony_ci						   100, STM32_ADC_TIMEOUT_US);
99462306a36Sopenharmony_ci		if (ret) {
99562306a36Sopenharmony_ci			dev_err(&indio_dev->dev, "Failed to read calfact\n");
99662306a36Sopenharmony_ci			return ret;
99762306a36Sopenharmony_ci		}
99862306a36Sopenharmony_ci
99962306a36Sopenharmony_ci		val = stm32_adc_readl(adc, STM32H7_ADC_CALFACT2);
100062306a36Sopenharmony_ci		adc->cal.lincalfact[i] = (val & STM32H7_LINCALFACT_MASK);
100162306a36Sopenharmony_ci		adc->cal.lincalfact[i] >>= STM32H7_LINCALFACT_SHIFT;
100262306a36Sopenharmony_ci
100362306a36Sopenharmony_ci		lincalrdyw_mask >>= 1;
100462306a36Sopenharmony_ci	}
100562306a36Sopenharmony_ci	adc->cal.lincal_saved = true;
100662306a36Sopenharmony_ci
100762306a36Sopenharmony_ci	return 0;
100862306a36Sopenharmony_ci}
100962306a36Sopenharmony_ci
101062306a36Sopenharmony_ci/**
101162306a36Sopenharmony_ci * stm32h7_adc_restore_selfcalib() - Restore saved self-calibration result
101262306a36Sopenharmony_ci * @indio_dev: IIO device instance
101362306a36Sopenharmony_ci * Note: ADC must be enabled, with no on-going conversions.
101462306a36Sopenharmony_ci */
101562306a36Sopenharmony_cistatic int stm32h7_adc_restore_selfcalib(struct iio_dev *indio_dev)
101662306a36Sopenharmony_ci{
101762306a36Sopenharmony_ci	struct stm32_adc *adc = iio_priv(indio_dev);
101862306a36Sopenharmony_ci	int i, ret;
101962306a36Sopenharmony_ci	u32 lincalrdyw_mask, val;
102062306a36Sopenharmony_ci
102162306a36Sopenharmony_ci	lincalrdyw_mask = STM32H7_LINCALRDYW6;
102262306a36Sopenharmony_ci	for (i = STM32H7_LINCALFACT_NUM - 1; i >= 0; i--) {
102362306a36Sopenharmony_ci		/*
102462306a36Sopenharmony_ci		 * Write saved calibration data to shadow registers:
102562306a36Sopenharmony_ci		 * Write CALFACT2, and set LINCALRDYW[6..1] bit to trigger
102662306a36Sopenharmony_ci		 * data write. Then poll to wait for complete transfer.
102762306a36Sopenharmony_ci		 */
102862306a36Sopenharmony_ci		val = adc->cal.lincalfact[i] << STM32H7_LINCALFACT_SHIFT;
102962306a36Sopenharmony_ci		stm32_adc_writel(adc, STM32H7_ADC_CALFACT2, val);
103062306a36Sopenharmony_ci		stm32_adc_set_bits(adc, STM32H7_ADC_CR, lincalrdyw_mask);
103162306a36Sopenharmony_ci		ret = stm32_adc_readl_poll_timeout(STM32H7_ADC_CR, val,
103262306a36Sopenharmony_ci						   val & lincalrdyw_mask,
103362306a36Sopenharmony_ci						   100, STM32_ADC_TIMEOUT_US);
103462306a36Sopenharmony_ci		if (ret) {
103562306a36Sopenharmony_ci			dev_err(&indio_dev->dev, "Failed to write calfact\n");
103662306a36Sopenharmony_ci			return ret;
103762306a36Sopenharmony_ci		}
103862306a36Sopenharmony_ci
103962306a36Sopenharmony_ci		/*
104062306a36Sopenharmony_ci		 * Read back calibration data, has two effects:
104162306a36Sopenharmony_ci		 * - It ensures bits LINCALRDYW[6..1] are kept cleared
104262306a36Sopenharmony_ci		 *   for next time calibration needs to be restored.
104362306a36Sopenharmony_ci		 * - BTW, bit clear triggers a read, then check data has been
104462306a36Sopenharmony_ci		 *   correctly written.
104562306a36Sopenharmony_ci		 */
104662306a36Sopenharmony_ci		stm32_adc_clr_bits(adc, STM32H7_ADC_CR, lincalrdyw_mask);
104762306a36Sopenharmony_ci		ret = stm32_adc_readl_poll_timeout(STM32H7_ADC_CR, val,
104862306a36Sopenharmony_ci						   !(val & lincalrdyw_mask),
104962306a36Sopenharmony_ci						   100, STM32_ADC_TIMEOUT_US);
105062306a36Sopenharmony_ci		if (ret) {
105162306a36Sopenharmony_ci			dev_err(&indio_dev->dev, "Failed to read calfact\n");
105262306a36Sopenharmony_ci			return ret;
105362306a36Sopenharmony_ci		}
105462306a36Sopenharmony_ci		val = stm32_adc_readl(adc, STM32H7_ADC_CALFACT2);
105562306a36Sopenharmony_ci		if (val != adc->cal.lincalfact[i] << STM32H7_LINCALFACT_SHIFT) {
105662306a36Sopenharmony_ci			dev_err(&indio_dev->dev, "calfact not consistent\n");
105762306a36Sopenharmony_ci			return -EIO;
105862306a36Sopenharmony_ci		}
105962306a36Sopenharmony_ci
106062306a36Sopenharmony_ci		lincalrdyw_mask >>= 1;
106162306a36Sopenharmony_ci	}
106262306a36Sopenharmony_ci
106362306a36Sopenharmony_ci	return 0;
106462306a36Sopenharmony_ci}
106562306a36Sopenharmony_ci
106662306a36Sopenharmony_ci/*
106762306a36Sopenharmony_ci * Fixed timeout value for ADC calibration.
106862306a36Sopenharmony_ci * worst cases:
106962306a36Sopenharmony_ci * - low clock frequency
107062306a36Sopenharmony_ci * - maximum prescalers
107162306a36Sopenharmony_ci * Calibration requires:
107262306a36Sopenharmony_ci * - 131,072 ADC clock cycle for the linear calibration
107362306a36Sopenharmony_ci * - 20 ADC clock cycle for the offset calibration
107462306a36Sopenharmony_ci *
107562306a36Sopenharmony_ci * Set to 100ms for now
107662306a36Sopenharmony_ci */
107762306a36Sopenharmony_ci#define STM32H7_ADC_CALIB_TIMEOUT_US		100000
107862306a36Sopenharmony_ci
107962306a36Sopenharmony_ci/**
108062306a36Sopenharmony_ci * stm32h7_adc_selfcalib() - Procedure to calibrate ADC
108162306a36Sopenharmony_ci * @indio_dev: IIO device instance
108262306a36Sopenharmony_ci * @do_lincal: linear calibration request flag
108362306a36Sopenharmony_ci * Note: Must be called once ADC is out of power down.
108462306a36Sopenharmony_ci *
108562306a36Sopenharmony_ci * Run offset calibration unconditionally.
108662306a36Sopenharmony_ci * Run linear calibration if requested & supported.
108762306a36Sopenharmony_ci */
108862306a36Sopenharmony_cistatic int stm32h7_adc_selfcalib(struct iio_dev *indio_dev, int do_lincal)
108962306a36Sopenharmony_ci{
109062306a36Sopenharmony_ci	struct stm32_adc *adc = iio_priv(indio_dev);
109162306a36Sopenharmony_ci	int ret;
109262306a36Sopenharmony_ci	u32 msk = STM32H7_ADCALDIF;
109362306a36Sopenharmony_ci	u32 val;
109462306a36Sopenharmony_ci
109562306a36Sopenharmony_ci	if (adc->cfg->has_linearcal && do_lincal)
109662306a36Sopenharmony_ci		msk |= STM32H7_ADCALLIN;
109762306a36Sopenharmony_ci	/* ADC must be disabled for calibration */
109862306a36Sopenharmony_ci	stm32h7_adc_disable(indio_dev);
109962306a36Sopenharmony_ci
110062306a36Sopenharmony_ci	/*
110162306a36Sopenharmony_ci	 * Select calibration mode:
110262306a36Sopenharmony_ci	 * - Offset calibration for single ended inputs
110362306a36Sopenharmony_ci	 * - No linearity calibration (do it later, before reading it)
110462306a36Sopenharmony_ci	 */
110562306a36Sopenharmony_ci	stm32_adc_clr_bits(adc, STM32H7_ADC_CR, msk);
110662306a36Sopenharmony_ci
110762306a36Sopenharmony_ci	/* Start calibration, then wait for completion */
110862306a36Sopenharmony_ci	stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_ADCAL);
110962306a36Sopenharmony_ci	ret = stm32_adc_readl_poll_timeout(STM32H7_ADC_CR, val,
111062306a36Sopenharmony_ci					   !(val & STM32H7_ADCAL), 100,
111162306a36Sopenharmony_ci					   STM32H7_ADC_CALIB_TIMEOUT_US);
111262306a36Sopenharmony_ci	if (ret) {
111362306a36Sopenharmony_ci		dev_err(&indio_dev->dev, "calibration (single-ended) error %d\n", ret);
111462306a36Sopenharmony_ci		goto out;
111562306a36Sopenharmony_ci	}
111662306a36Sopenharmony_ci
111762306a36Sopenharmony_ci	/*
111862306a36Sopenharmony_ci	 * Select calibration mode, then start calibration:
111962306a36Sopenharmony_ci	 * - Offset calibration for differential input
112062306a36Sopenharmony_ci	 * - Linearity calibration (needs to be done only once for single/diff)
112162306a36Sopenharmony_ci	 *   will run simultaneously with offset calibration.
112262306a36Sopenharmony_ci	 */
112362306a36Sopenharmony_ci	stm32_adc_set_bits(adc, STM32H7_ADC_CR, msk);
112462306a36Sopenharmony_ci	stm32_adc_set_bits(adc, STM32H7_ADC_CR, STM32H7_ADCAL);
112562306a36Sopenharmony_ci	ret = stm32_adc_readl_poll_timeout(STM32H7_ADC_CR, val,
112662306a36Sopenharmony_ci					   !(val & STM32H7_ADCAL), 100,
112762306a36Sopenharmony_ci					   STM32H7_ADC_CALIB_TIMEOUT_US);
112862306a36Sopenharmony_ci	if (ret) {
112962306a36Sopenharmony_ci		dev_err(&indio_dev->dev, "calibration (diff%s) error %d\n",
113062306a36Sopenharmony_ci			(msk & STM32H7_ADCALLIN) ? "+linear" : "", ret);
113162306a36Sopenharmony_ci		goto out;
113262306a36Sopenharmony_ci	}
113362306a36Sopenharmony_ci
113462306a36Sopenharmony_ciout:
113562306a36Sopenharmony_ci	stm32_adc_clr_bits(adc, STM32H7_ADC_CR, msk);
113662306a36Sopenharmony_ci
113762306a36Sopenharmony_ci	return ret;
113862306a36Sopenharmony_ci}
113962306a36Sopenharmony_ci
114062306a36Sopenharmony_ci/**
114162306a36Sopenharmony_ci * stm32h7_adc_check_selfcalib() - Check linear calibration status
114262306a36Sopenharmony_ci * @indio_dev: IIO device instance
114362306a36Sopenharmony_ci *
114462306a36Sopenharmony_ci * Used to check if linear calibration has been done.
114562306a36Sopenharmony_ci * Return true if linear calibration factors are already saved in private data
114662306a36Sopenharmony_ci * or if a linear calibration has been done at boot stage.
114762306a36Sopenharmony_ci */
114862306a36Sopenharmony_cistatic int stm32h7_adc_check_selfcalib(struct iio_dev *indio_dev)
114962306a36Sopenharmony_ci{
115062306a36Sopenharmony_ci	struct stm32_adc *adc = iio_priv(indio_dev);
115162306a36Sopenharmony_ci	u32 val;
115262306a36Sopenharmony_ci
115362306a36Sopenharmony_ci	if (adc->cal.lincal_saved)
115462306a36Sopenharmony_ci		return true;
115562306a36Sopenharmony_ci
115662306a36Sopenharmony_ci	/*
115762306a36Sopenharmony_ci	 * Check if linear calibration factors are available in ADC registers,
115862306a36Sopenharmony_ci	 * by checking that all LINCALRDYWx bits are set.
115962306a36Sopenharmony_ci	 */
116062306a36Sopenharmony_ci	val = stm32_adc_readl(adc, STM32H7_ADC_CR) & STM32H7_LINCALRDYW_MASK;
116162306a36Sopenharmony_ci	if (val == STM32H7_LINCALRDYW_MASK)
116262306a36Sopenharmony_ci		return true;
116362306a36Sopenharmony_ci
116462306a36Sopenharmony_ci	return false;
116562306a36Sopenharmony_ci}
116662306a36Sopenharmony_ci
116762306a36Sopenharmony_ci/**
116862306a36Sopenharmony_ci * stm32h7_adc_prepare() - Leave power down mode to enable ADC.
116962306a36Sopenharmony_ci * @indio_dev: IIO device instance
117062306a36Sopenharmony_ci * Leave power down mode.
117162306a36Sopenharmony_ci * Configure channels as single ended or differential before enabling ADC.
117262306a36Sopenharmony_ci * Enable ADC.
117362306a36Sopenharmony_ci * Restore calibration data.
117462306a36Sopenharmony_ci * Pre-select channels that may be used in PCSEL (required by input MUX / IO):
117562306a36Sopenharmony_ci * - Only one input is selected for single ended (e.g. 'vinp')
117662306a36Sopenharmony_ci * - Two inputs are selected for differential channels (e.g. 'vinp' & 'vinn')
117762306a36Sopenharmony_ci */
117862306a36Sopenharmony_cistatic int stm32h7_adc_prepare(struct iio_dev *indio_dev)
117962306a36Sopenharmony_ci{
118062306a36Sopenharmony_ci	struct stm32_adc *adc = iio_priv(indio_dev);
118162306a36Sopenharmony_ci	int lincal_done = false;
118262306a36Sopenharmony_ci	int ret;
118362306a36Sopenharmony_ci
118462306a36Sopenharmony_ci	ret = stm32h7_adc_exit_pwr_down(indio_dev);
118562306a36Sopenharmony_ci	if (ret)
118662306a36Sopenharmony_ci		return ret;
118762306a36Sopenharmony_ci
118862306a36Sopenharmony_ci	if (adc->cfg->has_linearcal)
118962306a36Sopenharmony_ci		lincal_done = stm32h7_adc_check_selfcalib(indio_dev);
119062306a36Sopenharmony_ci
119162306a36Sopenharmony_ci	/* Always run offset calibration. Run linear calibration only once */
119262306a36Sopenharmony_ci	ret = stm32h7_adc_selfcalib(indio_dev, !lincal_done);
119362306a36Sopenharmony_ci	if (ret < 0)
119462306a36Sopenharmony_ci		goto pwr_dwn;
119562306a36Sopenharmony_ci
119662306a36Sopenharmony_ci	stm32_adc_int_ch_enable(indio_dev);
119762306a36Sopenharmony_ci
119862306a36Sopenharmony_ci	stm32_adc_writel(adc, adc->cfg->regs->difsel.reg, adc->difsel);
119962306a36Sopenharmony_ci
120062306a36Sopenharmony_ci	ret = stm32h7_adc_enable(indio_dev);
120162306a36Sopenharmony_ci	if (ret)
120262306a36Sopenharmony_ci		goto ch_disable;
120362306a36Sopenharmony_ci
120462306a36Sopenharmony_ci	if (adc->cfg->has_linearcal) {
120562306a36Sopenharmony_ci		if (!adc->cal.lincal_saved)
120662306a36Sopenharmony_ci			ret = stm32h7_adc_read_selfcalib(indio_dev);
120762306a36Sopenharmony_ci		else
120862306a36Sopenharmony_ci			ret = stm32h7_adc_restore_selfcalib(indio_dev);
120962306a36Sopenharmony_ci
121062306a36Sopenharmony_ci		if (ret)
121162306a36Sopenharmony_ci			goto disable;
121262306a36Sopenharmony_ci	}
121362306a36Sopenharmony_ci
121462306a36Sopenharmony_ci	if (adc->cfg->has_presel)
121562306a36Sopenharmony_ci		stm32_adc_writel(adc, STM32H7_ADC_PCSEL, adc->pcsel);
121662306a36Sopenharmony_ci
121762306a36Sopenharmony_ci	return 0;
121862306a36Sopenharmony_ci
121962306a36Sopenharmony_cidisable:
122062306a36Sopenharmony_ci	stm32h7_adc_disable(indio_dev);
122162306a36Sopenharmony_cich_disable:
122262306a36Sopenharmony_ci	stm32_adc_int_ch_disable(adc);
122362306a36Sopenharmony_cipwr_dwn:
122462306a36Sopenharmony_ci	stm32h7_adc_enter_pwr_down(adc);
122562306a36Sopenharmony_ci
122662306a36Sopenharmony_ci	return ret;
122762306a36Sopenharmony_ci}
122862306a36Sopenharmony_ci
122962306a36Sopenharmony_cistatic void stm32h7_adc_unprepare(struct iio_dev *indio_dev)
123062306a36Sopenharmony_ci{
123162306a36Sopenharmony_ci	struct stm32_adc *adc = iio_priv(indio_dev);
123262306a36Sopenharmony_ci
123362306a36Sopenharmony_ci	if (adc->cfg->has_presel)
123462306a36Sopenharmony_ci		stm32_adc_writel(adc, STM32H7_ADC_PCSEL, 0);
123562306a36Sopenharmony_ci	stm32h7_adc_disable(indio_dev);
123662306a36Sopenharmony_ci	stm32_adc_int_ch_disable(adc);
123762306a36Sopenharmony_ci	stm32h7_adc_enter_pwr_down(adc);
123862306a36Sopenharmony_ci}
123962306a36Sopenharmony_ci
124062306a36Sopenharmony_ci/**
124162306a36Sopenharmony_ci * stm32_adc_conf_scan_seq() - Build regular channels scan sequence
124262306a36Sopenharmony_ci * @indio_dev: IIO device
124362306a36Sopenharmony_ci * @scan_mask: channels to be converted
124462306a36Sopenharmony_ci *
124562306a36Sopenharmony_ci * Conversion sequence :
124662306a36Sopenharmony_ci * Apply sampling time settings for all channels.
124762306a36Sopenharmony_ci * Configure ADC scan sequence based on selected channels in scan_mask.
124862306a36Sopenharmony_ci * Add channels to SQR registers, from scan_mask LSB to MSB, then
124962306a36Sopenharmony_ci * program sequence len.
125062306a36Sopenharmony_ci */
125162306a36Sopenharmony_cistatic int stm32_adc_conf_scan_seq(struct iio_dev *indio_dev,
125262306a36Sopenharmony_ci				   const unsigned long *scan_mask)
125362306a36Sopenharmony_ci{
125462306a36Sopenharmony_ci	struct stm32_adc *adc = iio_priv(indio_dev);
125562306a36Sopenharmony_ci	const struct stm32_adc_regs *sqr = adc->cfg->regs->sqr;
125662306a36Sopenharmony_ci	const struct iio_chan_spec *chan;
125762306a36Sopenharmony_ci	u32 val, bit;
125862306a36Sopenharmony_ci	int i = 0;
125962306a36Sopenharmony_ci
126062306a36Sopenharmony_ci	/* Apply sampling time settings */
126162306a36Sopenharmony_ci	stm32_adc_writel(adc, adc->cfg->regs->smpr[0], adc->smpr_val[0]);
126262306a36Sopenharmony_ci	stm32_adc_writel(adc, adc->cfg->regs->smpr[1], adc->smpr_val[1]);
126362306a36Sopenharmony_ci
126462306a36Sopenharmony_ci	for_each_set_bit(bit, scan_mask, indio_dev->masklength) {
126562306a36Sopenharmony_ci		chan = indio_dev->channels + bit;
126662306a36Sopenharmony_ci		/*
126762306a36Sopenharmony_ci		 * Assign one channel per SQ entry in regular
126862306a36Sopenharmony_ci		 * sequence, starting with SQ1.
126962306a36Sopenharmony_ci		 */
127062306a36Sopenharmony_ci		i++;
127162306a36Sopenharmony_ci		if (i > STM32_ADC_MAX_SQ)
127262306a36Sopenharmony_ci			return -EINVAL;
127362306a36Sopenharmony_ci
127462306a36Sopenharmony_ci		dev_dbg(&indio_dev->dev, "%s chan %d to SQ%d\n",
127562306a36Sopenharmony_ci			__func__, chan->channel, i);
127662306a36Sopenharmony_ci
127762306a36Sopenharmony_ci		val = stm32_adc_readl(adc, sqr[i].reg);
127862306a36Sopenharmony_ci		val &= ~sqr[i].mask;
127962306a36Sopenharmony_ci		val |= chan->channel << sqr[i].shift;
128062306a36Sopenharmony_ci		stm32_adc_writel(adc, sqr[i].reg, val);
128162306a36Sopenharmony_ci	}
128262306a36Sopenharmony_ci
128362306a36Sopenharmony_ci	if (!i)
128462306a36Sopenharmony_ci		return -EINVAL;
128562306a36Sopenharmony_ci
128662306a36Sopenharmony_ci	/* Sequence len */
128762306a36Sopenharmony_ci	val = stm32_adc_readl(adc, sqr[0].reg);
128862306a36Sopenharmony_ci	val &= ~sqr[0].mask;
128962306a36Sopenharmony_ci	val |= ((i - 1) << sqr[0].shift);
129062306a36Sopenharmony_ci	stm32_adc_writel(adc, sqr[0].reg, val);
129162306a36Sopenharmony_ci
129262306a36Sopenharmony_ci	return 0;
129362306a36Sopenharmony_ci}
129462306a36Sopenharmony_ci
129562306a36Sopenharmony_ci/**
129662306a36Sopenharmony_ci * stm32_adc_get_trig_extsel() - Get external trigger selection
129762306a36Sopenharmony_ci * @indio_dev: IIO device structure
129862306a36Sopenharmony_ci * @trig: trigger
129962306a36Sopenharmony_ci *
130062306a36Sopenharmony_ci * Returns trigger extsel value, if trig matches, -EINVAL otherwise.
130162306a36Sopenharmony_ci */
130262306a36Sopenharmony_cistatic int stm32_adc_get_trig_extsel(struct iio_dev *indio_dev,
130362306a36Sopenharmony_ci				     struct iio_trigger *trig)
130462306a36Sopenharmony_ci{
130562306a36Sopenharmony_ci	struct stm32_adc *adc = iio_priv(indio_dev);
130662306a36Sopenharmony_ci	int i;
130762306a36Sopenharmony_ci
130862306a36Sopenharmony_ci	/* lookup triggers registered by stm32 timer trigger driver */
130962306a36Sopenharmony_ci	for (i = 0; adc->cfg->trigs[i].name; i++) {
131062306a36Sopenharmony_ci		/**
131162306a36Sopenharmony_ci		 * Checking both stm32 timer trigger type and trig name
131262306a36Sopenharmony_ci		 * should be safe against arbitrary trigger names.
131362306a36Sopenharmony_ci		 */
131462306a36Sopenharmony_ci		if ((is_stm32_timer_trigger(trig) ||
131562306a36Sopenharmony_ci		     is_stm32_lptim_trigger(trig)) &&
131662306a36Sopenharmony_ci		    !strcmp(adc->cfg->trigs[i].name, trig->name)) {
131762306a36Sopenharmony_ci			return adc->cfg->trigs[i].extsel;
131862306a36Sopenharmony_ci		}
131962306a36Sopenharmony_ci	}
132062306a36Sopenharmony_ci
132162306a36Sopenharmony_ci	return -EINVAL;
132262306a36Sopenharmony_ci}
132362306a36Sopenharmony_ci
132462306a36Sopenharmony_ci/**
132562306a36Sopenharmony_ci * stm32_adc_set_trig() - Set a regular trigger
132662306a36Sopenharmony_ci * @indio_dev: IIO device
132762306a36Sopenharmony_ci * @trig: IIO trigger
132862306a36Sopenharmony_ci *
132962306a36Sopenharmony_ci * Set trigger source/polarity (e.g. SW, or HW with polarity) :
133062306a36Sopenharmony_ci * - if HW trigger disabled (e.g. trig == NULL, conversion launched by sw)
133162306a36Sopenharmony_ci * - if HW trigger enabled, set source & polarity
133262306a36Sopenharmony_ci */
133362306a36Sopenharmony_cistatic int stm32_adc_set_trig(struct iio_dev *indio_dev,
133462306a36Sopenharmony_ci			      struct iio_trigger *trig)
133562306a36Sopenharmony_ci{
133662306a36Sopenharmony_ci	struct stm32_adc *adc = iio_priv(indio_dev);
133762306a36Sopenharmony_ci	u32 val, extsel = 0, exten = STM32_EXTEN_SWTRIG;
133862306a36Sopenharmony_ci	unsigned long flags;
133962306a36Sopenharmony_ci	int ret;
134062306a36Sopenharmony_ci
134162306a36Sopenharmony_ci	if (trig) {
134262306a36Sopenharmony_ci		ret = stm32_adc_get_trig_extsel(indio_dev, trig);
134362306a36Sopenharmony_ci		if (ret < 0)
134462306a36Sopenharmony_ci			return ret;
134562306a36Sopenharmony_ci
134662306a36Sopenharmony_ci		/* set trigger source and polarity (default to rising edge) */
134762306a36Sopenharmony_ci		extsel = ret;
134862306a36Sopenharmony_ci		exten = adc->trigger_polarity + STM32_EXTEN_HWTRIG_RISING_EDGE;
134962306a36Sopenharmony_ci	}
135062306a36Sopenharmony_ci
135162306a36Sopenharmony_ci	spin_lock_irqsave(&adc->lock, flags);
135262306a36Sopenharmony_ci	val = stm32_adc_readl(adc, adc->cfg->regs->exten.reg);
135362306a36Sopenharmony_ci	val &= ~(adc->cfg->regs->exten.mask | adc->cfg->regs->extsel.mask);
135462306a36Sopenharmony_ci	val |= exten << adc->cfg->regs->exten.shift;
135562306a36Sopenharmony_ci	val |= extsel << adc->cfg->regs->extsel.shift;
135662306a36Sopenharmony_ci	stm32_adc_writel(adc,  adc->cfg->regs->exten.reg, val);
135762306a36Sopenharmony_ci	spin_unlock_irqrestore(&adc->lock, flags);
135862306a36Sopenharmony_ci
135962306a36Sopenharmony_ci	return 0;
136062306a36Sopenharmony_ci}
136162306a36Sopenharmony_ci
136262306a36Sopenharmony_cistatic int stm32_adc_set_trig_pol(struct iio_dev *indio_dev,
136362306a36Sopenharmony_ci				  const struct iio_chan_spec *chan,
136462306a36Sopenharmony_ci				  unsigned int type)
136562306a36Sopenharmony_ci{
136662306a36Sopenharmony_ci	struct stm32_adc *adc = iio_priv(indio_dev);
136762306a36Sopenharmony_ci
136862306a36Sopenharmony_ci	adc->trigger_polarity = type;
136962306a36Sopenharmony_ci
137062306a36Sopenharmony_ci	return 0;
137162306a36Sopenharmony_ci}
137262306a36Sopenharmony_ci
137362306a36Sopenharmony_cistatic int stm32_adc_get_trig_pol(struct iio_dev *indio_dev,
137462306a36Sopenharmony_ci				  const struct iio_chan_spec *chan)
137562306a36Sopenharmony_ci{
137662306a36Sopenharmony_ci	struct stm32_adc *adc = iio_priv(indio_dev);
137762306a36Sopenharmony_ci
137862306a36Sopenharmony_ci	return adc->trigger_polarity;
137962306a36Sopenharmony_ci}
138062306a36Sopenharmony_ci
138162306a36Sopenharmony_cistatic const char * const stm32_trig_pol_items[] = {
138262306a36Sopenharmony_ci	"rising-edge", "falling-edge", "both-edges",
138362306a36Sopenharmony_ci};
138462306a36Sopenharmony_ci
138562306a36Sopenharmony_cistatic const struct iio_enum stm32_adc_trig_pol = {
138662306a36Sopenharmony_ci	.items = stm32_trig_pol_items,
138762306a36Sopenharmony_ci	.num_items = ARRAY_SIZE(stm32_trig_pol_items),
138862306a36Sopenharmony_ci	.get = stm32_adc_get_trig_pol,
138962306a36Sopenharmony_ci	.set = stm32_adc_set_trig_pol,
139062306a36Sopenharmony_ci};
139162306a36Sopenharmony_ci
139262306a36Sopenharmony_ci/**
139362306a36Sopenharmony_ci * stm32_adc_single_conv() - Performs a single conversion
139462306a36Sopenharmony_ci * @indio_dev: IIO device
139562306a36Sopenharmony_ci * @chan: IIO channel
139662306a36Sopenharmony_ci * @res: conversion result
139762306a36Sopenharmony_ci *
139862306a36Sopenharmony_ci * The function performs a single conversion on a given channel:
139962306a36Sopenharmony_ci * - Apply sampling time settings
140062306a36Sopenharmony_ci * - Program sequencer with one channel (e.g. in SQ1 with len = 1)
140162306a36Sopenharmony_ci * - Use SW trigger
140262306a36Sopenharmony_ci * - Start conversion, then wait for interrupt completion.
140362306a36Sopenharmony_ci */
140462306a36Sopenharmony_cistatic int stm32_adc_single_conv(struct iio_dev *indio_dev,
140562306a36Sopenharmony_ci				 const struct iio_chan_spec *chan,
140662306a36Sopenharmony_ci				 int *res)
140762306a36Sopenharmony_ci{
140862306a36Sopenharmony_ci	struct stm32_adc *adc = iio_priv(indio_dev);
140962306a36Sopenharmony_ci	struct device *dev = indio_dev->dev.parent;
141062306a36Sopenharmony_ci	const struct stm32_adc_regspec *regs = adc->cfg->regs;
141162306a36Sopenharmony_ci	long timeout;
141262306a36Sopenharmony_ci	u32 val;
141362306a36Sopenharmony_ci	int ret;
141462306a36Sopenharmony_ci
141562306a36Sopenharmony_ci	reinit_completion(&adc->completion);
141662306a36Sopenharmony_ci
141762306a36Sopenharmony_ci	adc->bufi = 0;
141862306a36Sopenharmony_ci
141962306a36Sopenharmony_ci	ret = pm_runtime_resume_and_get(dev);
142062306a36Sopenharmony_ci	if (ret < 0)
142162306a36Sopenharmony_ci		return ret;
142262306a36Sopenharmony_ci
142362306a36Sopenharmony_ci	/* Apply sampling time settings */
142462306a36Sopenharmony_ci	stm32_adc_writel(adc, regs->smpr[0], adc->smpr_val[0]);
142562306a36Sopenharmony_ci	stm32_adc_writel(adc, regs->smpr[1], adc->smpr_val[1]);
142662306a36Sopenharmony_ci
142762306a36Sopenharmony_ci	/* Program chan number in regular sequence (SQ1) */
142862306a36Sopenharmony_ci	val = stm32_adc_readl(adc, regs->sqr[1].reg);
142962306a36Sopenharmony_ci	val &= ~regs->sqr[1].mask;
143062306a36Sopenharmony_ci	val |= chan->channel << regs->sqr[1].shift;
143162306a36Sopenharmony_ci	stm32_adc_writel(adc, regs->sqr[1].reg, val);
143262306a36Sopenharmony_ci
143362306a36Sopenharmony_ci	/* Set regular sequence len (0 for 1 conversion) */
143462306a36Sopenharmony_ci	stm32_adc_clr_bits(adc, regs->sqr[0].reg, regs->sqr[0].mask);
143562306a36Sopenharmony_ci
143662306a36Sopenharmony_ci	/* Trigger detection disabled (conversion can be launched in SW) */
143762306a36Sopenharmony_ci	stm32_adc_clr_bits(adc, regs->exten.reg, regs->exten.mask);
143862306a36Sopenharmony_ci
143962306a36Sopenharmony_ci	stm32_adc_conv_irq_enable(adc);
144062306a36Sopenharmony_ci
144162306a36Sopenharmony_ci	adc->cfg->start_conv(indio_dev, false);
144262306a36Sopenharmony_ci
144362306a36Sopenharmony_ci	timeout = wait_for_completion_interruptible_timeout(
144462306a36Sopenharmony_ci					&adc->completion, STM32_ADC_TIMEOUT);
144562306a36Sopenharmony_ci	if (timeout == 0) {
144662306a36Sopenharmony_ci		ret = -ETIMEDOUT;
144762306a36Sopenharmony_ci	} else if (timeout < 0) {
144862306a36Sopenharmony_ci		ret = timeout;
144962306a36Sopenharmony_ci	} else {
145062306a36Sopenharmony_ci		*res = adc->buffer[0];
145162306a36Sopenharmony_ci		ret = IIO_VAL_INT;
145262306a36Sopenharmony_ci	}
145362306a36Sopenharmony_ci
145462306a36Sopenharmony_ci	adc->cfg->stop_conv(indio_dev);
145562306a36Sopenharmony_ci
145662306a36Sopenharmony_ci	stm32_adc_conv_irq_disable(adc);
145762306a36Sopenharmony_ci
145862306a36Sopenharmony_ci	pm_runtime_mark_last_busy(dev);
145962306a36Sopenharmony_ci	pm_runtime_put_autosuspend(dev);
146062306a36Sopenharmony_ci
146162306a36Sopenharmony_ci	return ret;
146262306a36Sopenharmony_ci}
146362306a36Sopenharmony_ci
146462306a36Sopenharmony_cistatic int stm32_adc_read_raw(struct iio_dev *indio_dev,
146562306a36Sopenharmony_ci			      struct iio_chan_spec const *chan,
146662306a36Sopenharmony_ci			      int *val, int *val2, long mask)
146762306a36Sopenharmony_ci{
146862306a36Sopenharmony_ci	struct stm32_adc *adc = iio_priv(indio_dev);
146962306a36Sopenharmony_ci	int ret;
147062306a36Sopenharmony_ci
147162306a36Sopenharmony_ci	switch (mask) {
147262306a36Sopenharmony_ci	case IIO_CHAN_INFO_RAW:
147362306a36Sopenharmony_ci	case IIO_CHAN_INFO_PROCESSED:
147462306a36Sopenharmony_ci		ret = iio_device_claim_direct_mode(indio_dev);
147562306a36Sopenharmony_ci		if (ret)
147662306a36Sopenharmony_ci			return ret;
147762306a36Sopenharmony_ci		if (chan->type == IIO_VOLTAGE)
147862306a36Sopenharmony_ci			ret = stm32_adc_single_conv(indio_dev, chan, val);
147962306a36Sopenharmony_ci		else
148062306a36Sopenharmony_ci			ret = -EINVAL;
148162306a36Sopenharmony_ci
148262306a36Sopenharmony_ci		if (mask == IIO_CHAN_INFO_PROCESSED)
148362306a36Sopenharmony_ci			*val = STM32_ADC_VREFINT_VOLTAGE * adc->vrefint.vrefint_cal / *val;
148462306a36Sopenharmony_ci
148562306a36Sopenharmony_ci		iio_device_release_direct_mode(indio_dev);
148662306a36Sopenharmony_ci		return ret;
148762306a36Sopenharmony_ci
148862306a36Sopenharmony_ci	case IIO_CHAN_INFO_SCALE:
148962306a36Sopenharmony_ci		if (chan->differential) {
149062306a36Sopenharmony_ci			*val = adc->common->vref_mv * 2;
149162306a36Sopenharmony_ci			*val2 = chan->scan_type.realbits;
149262306a36Sopenharmony_ci		} else {
149362306a36Sopenharmony_ci			*val = adc->common->vref_mv;
149462306a36Sopenharmony_ci			*val2 = chan->scan_type.realbits;
149562306a36Sopenharmony_ci		}
149662306a36Sopenharmony_ci		return IIO_VAL_FRACTIONAL_LOG2;
149762306a36Sopenharmony_ci
149862306a36Sopenharmony_ci	case IIO_CHAN_INFO_OFFSET:
149962306a36Sopenharmony_ci		if (chan->differential)
150062306a36Sopenharmony_ci			/* ADC_full_scale / 2 */
150162306a36Sopenharmony_ci			*val = -((1 << chan->scan_type.realbits) / 2);
150262306a36Sopenharmony_ci		else
150362306a36Sopenharmony_ci			*val = 0;
150462306a36Sopenharmony_ci		return IIO_VAL_INT;
150562306a36Sopenharmony_ci
150662306a36Sopenharmony_ci	default:
150762306a36Sopenharmony_ci		return -EINVAL;
150862306a36Sopenharmony_ci	}
150962306a36Sopenharmony_ci}
151062306a36Sopenharmony_ci
151162306a36Sopenharmony_cistatic void stm32_adc_irq_clear(struct iio_dev *indio_dev, u32 msk)
151262306a36Sopenharmony_ci{
151362306a36Sopenharmony_ci	struct stm32_adc *adc = iio_priv(indio_dev);
151462306a36Sopenharmony_ci
151562306a36Sopenharmony_ci	adc->cfg->irq_clear(indio_dev, msk);
151662306a36Sopenharmony_ci}
151762306a36Sopenharmony_ci
151862306a36Sopenharmony_cistatic irqreturn_t stm32_adc_threaded_isr(int irq, void *data)
151962306a36Sopenharmony_ci{
152062306a36Sopenharmony_ci	struct iio_dev *indio_dev = data;
152162306a36Sopenharmony_ci	struct stm32_adc *adc = iio_priv(indio_dev);
152262306a36Sopenharmony_ci	const struct stm32_adc_regspec *regs = adc->cfg->regs;
152362306a36Sopenharmony_ci	u32 status = stm32_adc_readl(adc, regs->isr_eoc.reg);
152462306a36Sopenharmony_ci
152562306a36Sopenharmony_ci	/* Check ovr status right now, as ovr mask should be already disabled */
152662306a36Sopenharmony_ci	if (status & regs->isr_ovr.mask) {
152762306a36Sopenharmony_ci		/*
152862306a36Sopenharmony_ci		 * Clear ovr bit to avoid subsequent calls to IRQ handler.
152962306a36Sopenharmony_ci		 * This requires to stop ADC first. OVR bit state in ISR,
153062306a36Sopenharmony_ci		 * is propaged to CSR register by hardware.
153162306a36Sopenharmony_ci		 */
153262306a36Sopenharmony_ci		adc->cfg->stop_conv(indio_dev);
153362306a36Sopenharmony_ci		stm32_adc_irq_clear(indio_dev, regs->isr_ovr.mask);
153462306a36Sopenharmony_ci		dev_err(&indio_dev->dev, "Overrun, stopping: restart needed\n");
153562306a36Sopenharmony_ci		return IRQ_HANDLED;
153662306a36Sopenharmony_ci	}
153762306a36Sopenharmony_ci
153862306a36Sopenharmony_ci	return IRQ_NONE;
153962306a36Sopenharmony_ci}
154062306a36Sopenharmony_ci
154162306a36Sopenharmony_cistatic irqreturn_t stm32_adc_isr(int irq, void *data)
154262306a36Sopenharmony_ci{
154362306a36Sopenharmony_ci	struct iio_dev *indio_dev = data;
154462306a36Sopenharmony_ci	struct stm32_adc *adc = iio_priv(indio_dev);
154562306a36Sopenharmony_ci	const struct stm32_adc_regspec *regs = adc->cfg->regs;
154662306a36Sopenharmony_ci	u32 status = stm32_adc_readl(adc, regs->isr_eoc.reg);
154762306a36Sopenharmony_ci
154862306a36Sopenharmony_ci	if (status & regs->isr_ovr.mask) {
154962306a36Sopenharmony_ci		/*
155062306a36Sopenharmony_ci		 * Overrun occurred on regular conversions: data for wrong
155162306a36Sopenharmony_ci		 * channel may be read. Unconditionally disable interrupts
155262306a36Sopenharmony_ci		 * to stop processing data and print error message.
155362306a36Sopenharmony_ci		 * Restarting the capture can be done by disabling, then
155462306a36Sopenharmony_ci		 * re-enabling it (e.g. write 0, then 1 to buffer/enable).
155562306a36Sopenharmony_ci		 */
155662306a36Sopenharmony_ci		stm32_adc_ovr_irq_disable(adc);
155762306a36Sopenharmony_ci		stm32_adc_conv_irq_disable(adc);
155862306a36Sopenharmony_ci		return IRQ_WAKE_THREAD;
155962306a36Sopenharmony_ci	}
156062306a36Sopenharmony_ci
156162306a36Sopenharmony_ci	if (status & regs->isr_eoc.mask) {
156262306a36Sopenharmony_ci		/* Reading DR also clears EOC status flag */
156362306a36Sopenharmony_ci		adc->buffer[adc->bufi] = stm32_adc_readw(adc, regs->dr);
156462306a36Sopenharmony_ci		if (iio_buffer_enabled(indio_dev)) {
156562306a36Sopenharmony_ci			adc->bufi++;
156662306a36Sopenharmony_ci			if (adc->bufi >= adc->num_conv) {
156762306a36Sopenharmony_ci				stm32_adc_conv_irq_disable(adc);
156862306a36Sopenharmony_ci				iio_trigger_poll(indio_dev->trig);
156962306a36Sopenharmony_ci			}
157062306a36Sopenharmony_ci		} else {
157162306a36Sopenharmony_ci			complete(&adc->completion);
157262306a36Sopenharmony_ci		}
157362306a36Sopenharmony_ci		return IRQ_HANDLED;
157462306a36Sopenharmony_ci	}
157562306a36Sopenharmony_ci
157662306a36Sopenharmony_ci	return IRQ_NONE;
157762306a36Sopenharmony_ci}
157862306a36Sopenharmony_ci
157962306a36Sopenharmony_ci/**
158062306a36Sopenharmony_ci * stm32_adc_validate_trigger() - validate trigger for stm32 adc
158162306a36Sopenharmony_ci * @indio_dev: IIO device
158262306a36Sopenharmony_ci * @trig: new trigger
158362306a36Sopenharmony_ci *
158462306a36Sopenharmony_ci * Returns: 0 if trig matches one of the triggers registered by stm32 adc
158562306a36Sopenharmony_ci * driver, -EINVAL otherwise.
158662306a36Sopenharmony_ci */
158762306a36Sopenharmony_cistatic int stm32_adc_validate_trigger(struct iio_dev *indio_dev,
158862306a36Sopenharmony_ci				      struct iio_trigger *trig)
158962306a36Sopenharmony_ci{
159062306a36Sopenharmony_ci	return stm32_adc_get_trig_extsel(indio_dev, trig) < 0 ? -EINVAL : 0;
159162306a36Sopenharmony_ci}
159262306a36Sopenharmony_ci
159362306a36Sopenharmony_cistatic int stm32_adc_set_watermark(struct iio_dev *indio_dev, unsigned int val)
159462306a36Sopenharmony_ci{
159562306a36Sopenharmony_ci	struct stm32_adc *adc = iio_priv(indio_dev);
159662306a36Sopenharmony_ci	unsigned int watermark = STM32_DMA_BUFFER_SIZE / 2;
159762306a36Sopenharmony_ci	unsigned int rx_buf_sz = STM32_DMA_BUFFER_SIZE;
159862306a36Sopenharmony_ci
159962306a36Sopenharmony_ci	/*
160062306a36Sopenharmony_ci	 * dma cyclic transfers are used, buffer is split into two periods.
160162306a36Sopenharmony_ci	 * There should be :
160262306a36Sopenharmony_ci	 * - always one buffer (period) dma is working on
160362306a36Sopenharmony_ci	 * - one buffer (period) driver can push data.
160462306a36Sopenharmony_ci	 */
160562306a36Sopenharmony_ci	watermark = min(watermark, val * (unsigned)(sizeof(u16)));
160662306a36Sopenharmony_ci	adc->rx_buf_sz = min(rx_buf_sz, watermark * 2 * adc->num_conv);
160762306a36Sopenharmony_ci
160862306a36Sopenharmony_ci	return 0;
160962306a36Sopenharmony_ci}
161062306a36Sopenharmony_ci
161162306a36Sopenharmony_cistatic int stm32_adc_update_scan_mode(struct iio_dev *indio_dev,
161262306a36Sopenharmony_ci				      const unsigned long *scan_mask)
161362306a36Sopenharmony_ci{
161462306a36Sopenharmony_ci	struct stm32_adc *adc = iio_priv(indio_dev);
161562306a36Sopenharmony_ci	struct device *dev = indio_dev->dev.parent;
161662306a36Sopenharmony_ci	int ret;
161762306a36Sopenharmony_ci
161862306a36Sopenharmony_ci	ret = pm_runtime_resume_and_get(dev);
161962306a36Sopenharmony_ci	if (ret < 0)
162062306a36Sopenharmony_ci		return ret;
162162306a36Sopenharmony_ci
162262306a36Sopenharmony_ci	adc->num_conv = bitmap_weight(scan_mask, indio_dev->masklength);
162362306a36Sopenharmony_ci
162462306a36Sopenharmony_ci	ret = stm32_adc_conf_scan_seq(indio_dev, scan_mask);
162562306a36Sopenharmony_ci	pm_runtime_mark_last_busy(dev);
162662306a36Sopenharmony_ci	pm_runtime_put_autosuspend(dev);
162762306a36Sopenharmony_ci
162862306a36Sopenharmony_ci	return ret;
162962306a36Sopenharmony_ci}
163062306a36Sopenharmony_ci
163162306a36Sopenharmony_cistatic int stm32_adc_fwnode_xlate(struct iio_dev *indio_dev,
163262306a36Sopenharmony_ci				  const struct fwnode_reference_args *iiospec)
163362306a36Sopenharmony_ci{
163462306a36Sopenharmony_ci	int i;
163562306a36Sopenharmony_ci
163662306a36Sopenharmony_ci	for (i = 0; i < indio_dev->num_channels; i++)
163762306a36Sopenharmony_ci		if (indio_dev->channels[i].channel == iiospec->args[0])
163862306a36Sopenharmony_ci			return i;
163962306a36Sopenharmony_ci
164062306a36Sopenharmony_ci	return -EINVAL;
164162306a36Sopenharmony_ci}
164262306a36Sopenharmony_ci
164362306a36Sopenharmony_ci/**
164462306a36Sopenharmony_ci * stm32_adc_debugfs_reg_access - read or write register value
164562306a36Sopenharmony_ci * @indio_dev: IIO device structure
164662306a36Sopenharmony_ci * @reg: register offset
164762306a36Sopenharmony_ci * @writeval: value to write
164862306a36Sopenharmony_ci * @readval: value to read
164962306a36Sopenharmony_ci *
165062306a36Sopenharmony_ci * To read a value from an ADC register:
165162306a36Sopenharmony_ci *   echo [ADC reg offset] > direct_reg_access
165262306a36Sopenharmony_ci *   cat direct_reg_access
165362306a36Sopenharmony_ci *
165462306a36Sopenharmony_ci * To write a value in a ADC register:
165562306a36Sopenharmony_ci *   echo [ADC_reg_offset] [value] > direct_reg_access
165662306a36Sopenharmony_ci */
165762306a36Sopenharmony_cistatic int stm32_adc_debugfs_reg_access(struct iio_dev *indio_dev,
165862306a36Sopenharmony_ci					unsigned reg, unsigned writeval,
165962306a36Sopenharmony_ci					unsigned *readval)
166062306a36Sopenharmony_ci{
166162306a36Sopenharmony_ci	struct stm32_adc *adc = iio_priv(indio_dev);
166262306a36Sopenharmony_ci	struct device *dev = indio_dev->dev.parent;
166362306a36Sopenharmony_ci	int ret;
166462306a36Sopenharmony_ci
166562306a36Sopenharmony_ci	ret = pm_runtime_resume_and_get(dev);
166662306a36Sopenharmony_ci	if (ret < 0)
166762306a36Sopenharmony_ci		return ret;
166862306a36Sopenharmony_ci
166962306a36Sopenharmony_ci	if (!readval)
167062306a36Sopenharmony_ci		stm32_adc_writel(adc, reg, writeval);
167162306a36Sopenharmony_ci	else
167262306a36Sopenharmony_ci		*readval = stm32_adc_readl(adc, reg);
167362306a36Sopenharmony_ci
167462306a36Sopenharmony_ci	pm_runtime_mark_last_busy(dev);
167562306a36Sopenharmony_ci	pm_runtime_put_autosuspend(dev);
167662306a36Sopenharmony_ci
167762306a36Sopenharmony_ci	return 0;
167862306a36Sopenharmony_ci}
167962306a36Sopenharmony_ci
168062306a36Sopenharmony_cistatic const struct iio_info stm32_adc_iio_info = {
168162306a36Sopenharmony_ci	.read_raw = stm32_adc_read_raw,
168262306a36Sopenharmony_ci	.validate_trigger = stm32_adc_validate_trigger,
168362306a36Sopenharmony_ci	.hwfifo_set_watermark = stm32_adc_set_watermark,
168462306a36Sopenharmony_ci	.update_scan_mode = stm32_adc_update_scan_mode,
168562306a36Sopenharmony_ci	.debugfs_reg_access = stm32_adc_debugfs_reg_access,
168662306a36Sopenharmony_ci	.fwnode_xlate = stm32_adc_fwnode_xlate,
168762306a36Sopenharmony_ci};
168862306a36Sopenharmony_ci
168962306a36Sopenharmony_cistatic unsigned int stm32_adc_dma_residue(struct stm32_adc *adc)
169062306a36Sopenharmony_ci{
169162306a36Sopenharmony_ci	struct dma_tx_state state;
169262306a36Sopenharmony_ci	enum dma_status status;
169362306a36Sopenharmony_ci
169462306a36Sopenharmony_ci	status = dmaengine_tx_status(adc->dma_chan,
169562306a36Sopenharmony_ci				     adc->dma_chan->cookie,
169662306a36Sopenharmony_ci				     &state);
169762306a36Sopenharmony_ci	if (status == DMA_IN_PROGRESS) {
169862306a36Sopenharmony_ci		/* Residue is size in bytes from end of buffer */
169962306a36Sopenharmony_ci		unsigned int i = adc->rx_buf_sz - state.residue;
170062306a36Sopenharmony_ci		unsigned int size;
170162306a36Sopenharmony_ci
170262306a36Sopenharmony_ci		/* Return available bytes */
170362306a36Sopenharmony_ci		if (i >= adc->bufi)
170462306a36Sopenharmony_ci			size = i - adc->bufi;
170562306a36Sopenharmony_ci		else
170662306a36Sopenharmony_ci			size = adc->rx_buf_sz + i - adc->bufi;
170762306a36Sopenharmony_ci
170862306a36Sopenharmony_ci		return size;
170962306a36Sopenharmony_ci	}
171062306a36Sopenharmony_ci
171162306a36Sopenharmony_ci	return 0;
171262306a36Sopenharmony_ci}
171362306a36Sopenharmony_ci
171462306a36Sopenharmony_cistatic void stm32_adc_dma_buffer_done(void *data)
171562306a36Sopenharmony_ci{
171662306a36Sopenharmony_ci	struct iio_dev *indio_dev = data;
171762306a36Sopenharmony_ci	struct stm32_adc *adc = iio_priv(indio_dev);
171862306a36Sopenharmony_ci	int residue = stm32_adc_dma_residue(adc);
171962306a36Sopenharmony_ci
172062306a36Sopenharmony_ci	/*
172162306a36Sopenharmony_ci	 * In DMA mode the trigger services of IIO are not used
172262306a36Sopenharmony_ci	 * (e.g. no call to iio_trigger_poll).
172362306a36Sopenharmony_ci	 * Calling irq handler associated to the hardware trigger is not
172462306a36Sopenharmony_ci	 * relevant as the conversions have already been done. Data
172562306a36Sopenharmony_ci	 * transfers are performed directly in DMA callback instead.
172662306a36Sopenharmony_ci	 * This implementation avoids to call trigger irq handler that
172762306a36Sopenharmony_ci	 * may sleep, in an atomic context (DMA irq handler context).
172862306a36Sopenharmony_ci	 */
172962306a36Sopenharmony_ci	dev_dbg(&indio_dev->dev, "%s bufi=%d\n", __func__, adc->bufi);
173062306a36Sopenharmony_ci
173162306a36Sopenharmony_ci	while (residue >= indio_dev->scan_bytes) {
173262306a36Sopenharmony_ci		u16 *buffer = (u16 *)&adc->rx_buf[adc->bufi];
173362306a36Sopenharmony_ci
173462306a36Sopenharmony_ci		iio_push_to_buffers(indio_dev, buffer);
173562306a36Sopenharmony_ci
173662306a36Sopenharmony_ci		residue -= indio_dev->scan_bytes;
173762306a36Sopenharmony_ci		adc->bufi += indio_dev->scan_bytes;
173862306a36Sopenharmony_ci		if (adc->bufi >= adc->rx_buf_sz)
173962306a36Sopenharmony_ci			adc->bufi = 0;
174062306a36Sopenharmony_ci	}
174162306a36Sopenharmony_ci}
174262306a36Sopenharmony_ci
174362306a36Sopenharmony_cistatic int stm32_adc_dma_start(struct iio_dev *indio_dev)
174462306a36Sopenharmony_ci{
174562306a36Sopenharmony_ci	struct stm32_adc *adc = iio_priv(indio_dev);
174662306a36Sopenharmony_ci	struct dma_async_tx_descriptor *desc;
174762306a36Sopenharmony_ci	dma_cookie_t cookie;
174862306a36Sopenharmony_ci	int ret;
174962306a36Sopenharmony_ci
175062306a36Sopenharmony_ci	if (!adc->dma_chan)
175162306a36Sopenharmony_ci		return 0;
175262306a36Sopenharmony_ci
175362306a36Sopenharmony_ci	dev_dbg(&indio_dev->dev, "%s size=%d watermark=%d\n", __func__,
175462306a36Sopenharmony_ci		adc->rx_buf_sz, adc->rx_buf_sz / 2);
175562306a36Sopenharmony_ci
175662306a36Sopenharmony_ci	/* Prepare a DMA cyclic transaction */
175762306a36Sopenharmony_ci	desc = dmaengine_prep_dma_cyclic(adc->dma_chan,
175862306a36Sopenharmony_ci					 adc->rx_dma_buf,
175962306a36Sopenharmony_ci					 adc->rx_buf_sz, adc->rx_buf_sz / 2,
176062306a36Sopenharmony_ci					 DMA_DEV_TO_MEM,
176162306a36Sopenharmony_ci					 DMA_PREP_INTERRUPT);
176262306a36Sopenharmony_ci	if (!desc)
176362306a36Sopenharmony_ci		return -EBUSY;
176462306a36Sopenharmony_ci
176562306a36Sopenharmony_ci	desc->callback = stm32_adc_dma_buffer_done;
176662306a36Sopenharmony_ci	desc->callback_param = indio_dev;
176762306a36Sopenharmony_ci
176862306a36Sopenharmony_ci	cookie = dmaengine_submit(desc);
176962306a36Sopenharmony_ci	ret = dma_submit_error(cookie);
177062306a36Sopenharmony_ci	if (ret) {
177162306a36Sopenharmony_ci		dmaengine_terminate_sync(adc->dma_chan);
177262306a36Sopenharmony_ci		return ret;
177362306a36Sopenharmony_ci	}
177462306a36Sopenharmony_ci
177562306a36Sopenharmony_ci	/* Issue pending DMA requests */
177662306a36Sopenharmony_ci	dma_async_issue_pending(adc->dma_chan);
177762306a36Sopenharmony_ci
177862306a36Sopenharmony_ci	return 0;
177962306a36Sopenharmony_ci}
178062306a36Sopenharmony_ci
178162306a36Sopenharmony_cistatic int stm32_adc_buffer_postenable(struct iio_dev *indio_dev)
178262306a36Sopenharmony_ci{
178362306a36Sopenharmony_ci	struct stm32_adc *adc = iio_priv(indio_dev);
178462306a36Sopenharmony_ci	struct device *dev = indio_dev->dev.parent;
178562306a36Sopenharmony_ci	int ret;
178662306a36Sopenharmony_ci
178762306a36Sopenharmony_ci	ret = pm_runtime_resume_and_get(dev);
178862306a36Sopenharmony_ci	if (ret < 0)
178962306a36Sopenharmony_ci		return ret;
179062306a36Sopenharmony_ci
179162306a36Sopenharmony_ci	ret = stm32_adc_set_trig(indio_dev, indio_dev->trig);
179262306a36Sopenharmony_ci	if (ret) {
179362306a36Sopenharmony_ci		dev_err(&indio_dev->dev, "Can't set trigger\n");
179462306a36Sopenharmony_ci		goto err_pm_put;
179562306a36Sopenharmony_ci	}
179662306a36Sopenharmony_ci
179762306a36Sopenharmony_ci	ret = stm32_adc_dma_start(indio_dev);
179862306a36Sopenharmony_ci	if (ret) {
179962306a36Sopenharmony_ci		dev_err(&indio_dev->dev, "Can't start dma\n");
180062306a36Sopenharmony_ci		goto err_clr_trig;
180162306a36Sopenharmony_ci	}
180262306a36Sopenharmony_ci
180362306a36Sopenharmony_ci	/* Reset adc buffer index */
180462306a36Sopenharmony_ci	adc->bufi = 0;
180562306a36Sopenharmony_ci
180662306a36Sopenharmony_ci	stm32_adc_ovr_irq_enable(adc);
180762306a36Sopenharmony_ci
180862306a36Sopenharmony_ci	if (!adc->dma_chan)
180962306a36Sopenharmony_ci		stm32_adc_conv_irq_enable(adc);
181062306a36Sopenharmony_ci
181162306a36Sopenharmony_ci	adc->cfg->start_conv(indio_dev, !!adc->dma_chan);
181262306a36Sopenharmony_ci
181362306a36Sopenharmony_ci	return 0;
181462306a36Sopenharmony_ci
181562306a36Sopenharmony_cierr_clr_trig:
181662306a36Sopenharmony_ci	stm32_adc_set_trig(indio_dev, NULL);
181762306a36Sopenharmony_cierr_pm_put:
181862306a36Sopenharmony_ci	pm_runtime_mark_last_busy(dev);
181962306a36Sopenharmony_ci	pm_runtime_put_autosuspend(dev);
182062306a36Sopenharmony_ci
182162306a36Sopenharmony_ci	return ret;
182262306a36Sopenharmony_ci}
182362306a36Sopenharmony_ci
182462306a36Sopenharmony_cistatic int stm32_adc_buffer_predisable(struct iio_dev *indio_dev)
182562306a36Sopenharmony_ci{
182662306a36Sopenharmony_ci	struct stm32_adc *adc = iio_priv(indio_dev);
182762306a36Sopenharmony_ci	struct device *dev = indio_dev->dev.parent;
182862306a36Sopenharmony_ci
182962306a36Sopenharmony_ci	adc->cfg->stop_conv(indio_dev);
183062306a36Sopenharmony_ci	if (!adc->dma_chan)
183162306a36Sopenharmony_ci		stm32_adc_conv_irq_disable(adc);
183262306a36Sopenharmony_ci
183362306a36Sopenharmony_ci	stm32_adc_ovr_irq_disable(adc);
183462306a36Sopenharmony_ci
183562306a36Sopenharmony_ci	if (adc->dma_chan)
183662306a36Sopenharmony_ci		dmaengine_terminate_sync(adc->dma_chan);
183762306a36Sopenharmony_ci
183862306a36Sopenharmony_ci	if (stm32_adc_set_trig(indio_dev, NULL))
183962306a36Sopenharmony_ci		dev_err(&indio_dev->dev, "Can't clear trigger\n");
184062306a36Sopenharmony_ci
184162306a36Sopenharmony_ci	pm_runtime_mark_last_busy(dev);
184262306a36Sopenharmony_ci	pm_runtime_put_autosuspend(dev);
184362306a36Sopenharmony_ci
184462306a36Sopenharmony_ci	return 0;
184562306a36Sopenharmony_ci}
184662306a36Sopenharmony_ci
184762306a36Sopenharmony_cistatic const struct iio_buffer_setup_ops stm32_adc_buffer_setup_ops = {
184862306a36Sopenharmony_ci	.postenable = &stm32_adc_buffer_postenable,
184962306a36Sopenharmony_ci	.predisable = &stm32_adc_buffer_predisable,
185062306a36Sopenharmony_ci};
185162306a36Sopenharmony_ci
185262306a36Sopenharmony_cistatic irqreturn_t stm32_adc_trigger_handler(int irq, void *p)
185362306a36Sopenharmony_ci{
185462306a36Sopenharmony_ci	struct iio_poll_func *pf = p;
185562306a36Sopenharmony_ci	struct iio_dev *indio_dev = pf->indio_dev;
185662306a36Sopenharmony_ci	struct stm32_adc *adc = iio_priv(indio_dev);
185762306a36Sopenharmony_ci
185862306a36Sopenharmony_ci	dev_dbg(&indio_dev->dev, "%s bufi=%d\n", __func__, adc->bufi);
185962306a36Sopenharmony_ci
186062306a36Sopenharmony_ci	/* reset buffer index */
186162306a36Sopenharmony_ci	adc->bufi = 0;
186262306a36Sopenharmony_ci	iio_push_to_buffers_with_timestamp(indio_dev, adc->buffer,
186362306a36Sopenharmony_ci					   pf->timestamp);
186462306a36Sopenharmony_ci	iio_trigger_notify_done(indio_dev->trig);
186562306a36Sopenharmony_ci
186662306a36Sopenharmony_ci	/* re-enable eoc irq */
186762306a36Sopenharmony_ci	stm32_adc_conv_irq_enable(adc);
186862306a36Sopenharmony_ci
186962306a36Sopenharmony_ci	return IRQ_HANDLED;
187062306a36Sopenharmony_ci}
187162306a36Sopenharmony_ci
187262306a36Sopenharmony_cistatic const struct iio_chan_spec_ext_info stm32_adc_ext_info[] = {
187362306a36Sopenharmony_ci	IIO_ENUM("trigger_polarity", IIO_SHARED_BY_ALL, &stm32_adc_trig_pol),
187462306a36Sopenharmony_ci	{
187562306a36Sopenharmony_ci		.name = "trigger_polarity_available",
187662306a36Sopenharmony_ci		.shared = IIO_SHARED_BY_ALL,
187762306a36Sopenharmony_ci		.read = iio_enum_available_read,
187862306a36Sopenharmony_ci		.private = (uintptr_t)&stm32_adc_trig_pol,
187962306a36Sopenharmony_ci	},
188062306a36Sopenharmony_ci	{},
188162306a36Sopenharmony_ci};
188262306a36Sopenharmony_ci
188362306a36Sopenharmony_cistatic void stm32_adc_debugfs_init(struct iio_dev *indio_dev)
188462306a36Sopenharmony_ci{
188562306a36Sopenharmony_ci	struct stm32_adc *adc = iio_priv(indio_dev);
188662306a36Sopenharmony_ci	struct dentry *d = iio_get_debugfs_dentry(indio_dev);
188762306a36Sopenharmony_ci	struct stm32_adc_calib *cal = &adc->cal;
188862306a36Sopenharmony_ci	char buf[16];
188962306a36Sopenharmony_ci	unsigned int i;
189062306a36Sopenharmony_ci
189162306a36Sopenharmony_ci	if (!adc->cfg->has_linearcal)
189262306a36Sopenharmony_ci		return;
189362306a36Sopenharmony_ci
189462306a36Sopenharmony_ci	for (i = 0; i < STM32H7_LINCALFACT_NUM; i++) {
189562306a36Sopenharmony_ci		snprintf(buf, sizeof(buf), "lincalfact%d", i + 1);
189662306a36Sopenharmony_ci		debugfs_create_u32(buf, 0444, d, &cal->lincalfact[i]);
189762306a36Sopenharmony_ci	}
189862306a36Sopenharmony_ci}
189962306a36Sopenharmony_ci
190062306a36Sopenharmony_cistatic int stm32_adc_fw_get_resolution(struct iio_dev *indio_dev)
190162306a36Sopenharmony_ci{
190262306a36Sopenharmony_ci	struct device *dev = &indio_dev->dev;
190362306a36Sopenharmony_ci	struct stm32_adc *adc = iio_priv(indio_dev);
190462306a36Sopenharmony_ci	unsigned int i;
190562306a36Sopenharmony_ci	u32 res;
190662306a36Sopenharmony_ci
190762306a36Sopenharmony_ci	if (device_property_read_u32(dev, "assigned-resolution-bits", &res))
190862306a36Sopenharmony_ci		res = adc->cfg->adc_info->resolutions[0];
190962306a36Sopenharmony_ci
191062306a36Sopenharmony_ci	for (i = 0; i < adc->cfg->adc_info->num_res; i++)
191162306a36Sopenharmony_ci		if (res == adc->cfg->adc_info->resolutions[i])
191262306a36Sopenharmony_ci			break;
191362306a36Sopenharmony_ci	if (i >= adc->cfg->adc_info->num_res) {
191462306a36Sopenharmony_ci		dev_err(&indio_dev->dev, "Bad resolution: %u bits\n", res);
191562306a36Sopenharmony_ci		return -EINVAL;
191662306a36Sopenharmony_ci	}
191762306a36Sopenharmony_ci
191862306a36Sopenharmony_ci	dev_dbg(&indio_dev->dev, "Using %u bits resolution\n", res);
191962306a36Sopenharmony_ci	adc->res = i;
192062306a36Sopenharmony_ci
192162306a36Sopenharmony_ci	return 0;
192262306a36Sopenharmony_ci}
192362306a36Sopenharmony_ci
192462306a36Sopenharmony_cistatic void stm32_adc_smpr_init(struct stm32_adc *adc, int channel, u32 smp_ns)
192562306a36Sopenharmony_ci{
192662306a36Sopenharmony_ci	const struct stm32_adc_regs *smpr = &adc->cfg->regs->smp_bits[channel];
192762306a36Sopenharmony_ci	u32 period_ns, shift = smpr->shift, mask = smpr->mask;
192862306a36Sopenharmony_ci	unsigned int i, smp, r = smpr->reg;
192962306a36Sopenharmony_ci
193062306a36Sopenharmony_ci	/*
193162306a36Sopenharmony_ci	 * For internal channels, ensure that the sampling time cannot
193262306a36Sopenharmony_ci	 * be lower than the one specified in the datasheet
193362306a36Sopenharmony_ci	 */
193462306a36Sopenharmony_ci	for (i = 0; i < STM32_ADC_INT_CH_NB; i++)
193562306a36Sopenharmony_ci		if (channel == adc->int_ch[i] && adc->int_ch[i] != STM32_ADC_INT_CH_NONE)
193662306a36Sopenharmony_ci			smp_ns = max(smp_ns, adc->cfg->ts_int_ch[i]);
193762306a36Sopenharmony_ci
193862306a36Sopenharmony_ci	/* Determine sampling time (ADC clock cycles) */
193962306a36Sopenharmony_ci	period_ns = NSEC_PER_SEC / adc->common->rate;
194062306a36Sopenharmony_ci	for (smp = 0; smp <= STM32_ADC_MAX_SMP; smp++)
194162306a36Sopenharmony_ci		if ((period_ns * adc->cfg->smp_cycles[smp]) >= smp_ns)
194262306a36Sopenharmony_ci			break;
194362306a36Sopenharmony_ci	if (smp > STM32_ADC_MAX_SMP)
194462306a36Sopenharmony_ci		smp = STM32_ADC_MAX_SMP;
194562306a36Sopenharmony_ci
194662306a36Sopenharmony_ci	/* pre-build sampling time registers (e.g. smpr1, smpr2) */
194762306a36Sopenharmony_ci	adc->smpr_val[r] = (adc->smpr_val[r] & ~mask) | (smp << shift);
194862306a36Sopenharmony_ci}
194962306a36Sopenharmony_ci
195062306a36Sopenharmony_cistatic void stm32_adc_chan_init_one(struct iio_dev *indio_dev,
195162306a36Sopenharmony_ci				    struct iio_chan_spec *chan, u32 vinp,
195262306a36Sopenharmony_ci				    u32 vinn, int scan_index, bool differential)
195362306a36Sopenharmony_ci{
195462306a36Sopenharmony_ci	struct stm32_adc *adc = iio_priv(indio_dev);
195562306a36Sopenharmony_ci	char *name = adc->chan_name[vinp];
195662306a36Sopenharmony_ci
195762306a36Sopenharmony_ci	chan->type = IIO_VOLTAGE;
195862306a36Sopenharmony_ci	chan->channel = vinp;
195962306a36Sopenharmony_ci	if (differential) {
196062306a36Sopenharmony_ci		chan->differential = 1;
196162306a36Sopenharmony_ci		chan->channel2 = vinn;
196262306a36Sopenharmony_ci		snprintf(name, STM32_ADC_CH_SZ, "in%d-in%d", vinp, vinn);
196362306a36Sopenharmony_ci	} else {
196462306a36Sopenharmony_ci		snprintf(name, STM32_ADC_CH_SZ, "in%d", vinp);
196562306a36Sopenharmony_ci	}
196662306a36Sopenharmony_ci	chan->datasheet_name = name;
196762306a36Sopenharmony_ci	chan->scan_index = scan_index;
196862306a36Sopenharmony_ci	chan->indexed = 1;
196962306a36Sopenharmony_ci	if (chan->channel == adc->int_ch[STM32_ADC_INT_CH_VREFINT])
197062306a36Sopenharmony_ci		chan->info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED);
197162306a36Sopenharmony_ci	else
197262306a36Sopenharmony_ci		chan->info_mask_separate = BIT(IIO_CHAN_INFO_RAW);
197362306a36Sopenharmony_ci	chan->info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |
197462306a36Sopenharmony_ci					 BIT(IIO_CHAN_INFO_OFFSET);
197562306a36Sopenharmony_ci	chan->scan_type.sign = 'u';
197662306a36Sopenharmony_ci	chan->scan_type.realbits = adc->cfg->adc_info->resolutions[adc->res];
197762306a36Sopenharmony_ci	chan->scan_type.storagebits = 16;
197862306a36Sopenharmony_ci	chan->ext_info = stm32_adc_ext_info;
197962306a36Sopenharmony_ci
198062306a36Sopenharmony_ci	/* pre-build selected channels mask */
198162306a36Sopenharmony_ci	adc->pcsel |= BIT(chan->channel);
198262306a36Sopenharmony_ci	if (differential) {
198362306a36Sopenharmony_ci		/* pre-build diff channels mask */
198462306a36Sopenharmony_ci		adc->difsel |= BIT(chan->channel) & adc->cfg->regs->difsel.mask;
198562306a36Sopenharmony_ci		/* Also add negative input to pre-selected channels */
198662306a36Sopenharmony_ci		adc->pcsel |= BIT(chan->channel2);
198762306a36Sopenharmony_ci	}
198862306a36Sopenharmony_ci}
198962306a36Sopenharmony_ci
199062306a36Sopenharmony_cistatic int stm32_adc_get_legacy_chan_count(struct iio_dev *indio_dev, struct stm32_adc *adc)
199162306a36Sopenharmony_ci{
199262306a36Sopenharmony_ci	struct device *dev = &indio_dev->dev;
199362306a36Sopenharmony_ci	const struct stm32_adc_info *adc_info = adc->cfg->adc_info;
199462306a36Sopenharmony_ci	int num_channels = 0, ret;
199562306a36Sopenharmony_ci
199662306a36Sopenharmony_ci	dev_dbg(&indio_dev->dev, "using legacy channel config\n");
199762306a36Sopenharmony_ci
199862306a36Sopenharmony_ci	ret = device_property_count_u32(dev, "st,adc-channels");
199962306a36Sopenharmony_ci	if (ret > adc_info->max_channels) {
200062306a36Sopenharmony_ci		dev_err(&indio_dev->dev, "Bad st,adc-channels?\n");
200162306a36Sopenharmony_ci		return -EINVAL;
200262306a36Sopenharmony_ci	} else if (ret > 0) {
200362306a36Sopenharmony_ci		num_channels += ret;
200462306a36Sopenharmony_ci	}
200562306a36Sopenharmony_ci
200662306a36Sopenharmony_ci	/*
200762306a36Sopenharmony_ci	 * each st,adc-diff-channels is a group of 2 u32 so we divide @ret
200862306a36Sopenharmony_ci	 * to get the *real* number of channels.
200962306a36Sopenharmony_ci	 */
201062306a36Sopenharmony_ci	ret = device_property_count_u32(dev, "st,adc-diff-channels");
201162306a36Sopenharmony_ci	if (ret > 0) {
201262306a36Sopenharmony_ci		ret /= (int)(sizeof(struct stm32_adc_diff_channel) / sizeof(u32));
201362306a36Sopenharmony_ci		if (ret > adc_info->max_channels) {
201462306a36Sopenharmony_ci			dev_err(&indio_dev->dev, "Bad st,adc-diff-channels?\n");
201562306a36Sopenharmony_ci			return -EINVAL;
201662306a36Sopenharmony_ci		} else if (ret > 0) {
201762306a36Sopenharmony_ci			adc->num_diff = ret;
201862306a36Sopenharmony_ci			num_channels += ret;
201962306a36Sopenharmony_ci		}
202062306a36Sopenharmony_ci	}
202162306a36Sopenharmony_ci
202262306a36Sopenharmony_ci	/* Optional sample time is provided either for each, or all channels */
202362306a36Sopenharmony_ci	adc->nsmps = device_property_count_u32(dev, "st,min-sample-time-nsecs");
202462306a36Sopenharmony_ci	if (adc->nsmps > 1 && adc->nsmps != num_channels) {
202562306a36Sopenharmony_ci		dev_err(&indio_dev->dev, "Invalid st,min-sample-time-nsecs\n");
202662306a36Sopenharmony_ci		return -EINVAL;
202762306a36Sopenharmony_ci	}
202862306a36Sopenharmony_ci
202962306a36Sopenharmony_ci	return num_channels;
203062306a36Sopenharmony_ci}
203162306a36Sopenharmony_ci
203262306a36Sopenharmony_cistatic int stm32_adc_legacy_chan_init(struct iio_dev *indio_dev,
203362306a36Sopenharmony_ci				      struct stm32_adc *adc,
203462306a36Sopenharmony_ci				      struct iio_chan_spec *channels,
203562306a36Sopenharmony_ci				      int nchans)
203662306a36Sopenharmony_ci{
203762306a36Sopenharmony_ci	const struct stm32_adc_info *adc_info = adc->cfg->adc_info;
203862306a36Sopenharmony_ci	struct stm32_adc_diff_channel diff[STM32_ADC_CH_MAX];
203962306a36Sopenharmony_ci	struct device *dev = &indio_dev->dev;
204062306a36Sopenharmony_ci	u32 num_diff = adc->num_diff;
204162306a36Sopenharmony_ci	int num_se = nchans - num_diff;
204262306a36Sopenharmony_ci	int size = num_diff * sizeof(*diff) / sizeof(u32);
204362306a36Sopenharmony_ci	int scan_index = 0, ret, i, c;
204462306a36Sopenharmony_ci	u32 smp = 0, smps[STM32_ADC_CH_MAX], chans[STM32_ADC_CH_MAX];
204562306a36Sopenharmony_ci
204662306a36Sopenharmony_ci	if (num_diff) {
204762306a36Sopenharmony_ci		ret = device_property_read_u32_array(dev, "st,adc-diff-channels",
204862306a36Sopenharmony_ci						     (u32 *)diff, size);
204962306a36Sopenharmony_ci		if (ret) {
205062306a36Sopenharmony_ci			dev_err(&indio_dev->dev, "Failed to get diff channels %d\n", ret);
205162306a36Sopenharmony_ci			return ret;
205262306a36Sopenharmony_ci		}
205362306a36Sopenharmony_ci
205462306a36Sopenharmony_ci		for (i = 0; i < num_diff; i++) {
205562306a36Sopenharmony_ci			if (diff[i].vinp >= adc_info->max_channels ||
205662306a36Sopenharmony_ci			    diff[i].vinn >= adc_info->max_channels) {
205762306a36Sopenharmony_ci				dev_err(&indio_dev->dev, "Invalid channel in%d-in%d\n",
205862306a36Sopenharmony_ci					diff[i].vinp, diff[i].vinn);
205962306a36Sopenharmony_ci				return -EINVAL;
206062306a36Sopenharmony_ci			}
206162306a36Sopenharmony_ci
206262306a36Sopenharmony_ci			stm32_adc_chan_init_one(indio_dev, &channels[scan_index],
206362306a36Sopenharmony_ci						diff[i].vinp, diff[i].vinn,
206462306a36Sopenharmony_ci						scan_index, true);
206562306a36Sopenharmony_ci			scan_index++;
206662306a36Sopenharmony_ci		}
206762306a36Sopenharmony_ci	}
206862306a36Sopenharmony_ci	if (num_se > 0) {
206962306a36Sopenharmony_ci		ret = device_property_read_u32_array(dev, "st,adc-channels", chans, num_se);
207062306a36Sopenharmony_ci		if (ret) {
207162306a36Sopenharmony_ci			dev_err(&indio_dev->dev, "Failed to get st,adc-channels %d\n", ret);
207262306a36Sopenharmony_ci			return ret;
207362306a36Sopenharmony_ci		}
207462306a36Sopenharmony_ci
207562306a36Sopenharmony_ci		for (c = 0; c < num_se; c++) {
207662306a36Sopenharmony_ci			if (chans[c] >= adc_info->max_channels) {
207762306a36Sopenharmony_ci				dev_err(&indio_dev->dev, "Invalid channel %d\n",
207862306a36Sopenharmony_ci					chans[c]);
207962306a36Sopenharmony_ci				return -EINVAL;
208062306a36Sopenharmony_ci			}
208162306a36Sopenharmony_ci
208262306a36Sopenharmony_ci			/* Channel can't be configured both as single-ended & diff */
208362306a36Sopenharmony_ci			for (i = 0; i < num_diff; i++) {
208462306a36Sopenharmony_ci				if (chans[c] == diff[i].vinp) {
208562306a36Sopenharmony_ci					dev_err(&indio_dev->dev, "channel %d misconfigured\n",
208662306a36Sopenharmony_ci						chans[c]);
208762306a36Sopenharmony_ci					return -EINVAL;
208862306a36Sopenharmony_ci				}
208962306a36Sopenharmony_ci			}
209062306a36Sopenharmony_ci			stm32_adc_chan_init_one(indio_dev, &channels[scan_index],
209162306a36Sopenharmony_ci						chans[c], 0, scan_index, false);
209262306a36Sopenharmony_ci			scan_index++;
209362306a36Sopenharmony_ci		}
209462306a36Sopenharmony_ci	}
209562306a36Sopenharmony_ci
209662306a36Sopenharmony_ci	if (adc->nsmps > 0) {
209762306a36Sopenharmony_ci		ret = device_property_read_u32_array(dev, "st,min-sample-time-nsecs",
209862306a36Sopenharmony_ci						     smps, adc->nsmps);
209962306a36Sopenharmony_ci		if (ret)
210062306a36Sopenharmony_ci			return ret;
210162306a36Sopenharmony_ci	}
210262306a36Sopenharmony_ci
210362306a36Sopenharmony_ci	for (i = 0; i < scan_index; i++) {
210462306a36Sopenharmony_ci		/*
210562306a36Sopenharmony_ci		 * This check is used with the above logic so that smp value
210662306a36Sopenharmony_ci		 * will only be modified if valid u32 value can be decoded. This
210762306a36Sopenharmony_ci		 * allows to get either no value, 1 shared value for all indexes,
210862306a36Sopenharmony_ci		 * or one value per channel. The point is to have the same
210962306a36Sopenharmony_ci		 * behavior as 'of_property_read_u32_index()'.
211062306a36Sopenharmony_ci		 */
211162306a36Sopenharmony_ci		if (i < adc->nsmps)
211262306a36Sopenharmony_ci			smp = smps[i];
211362306a36Sopenharmony_ci
211462306a36Sopenharmony_ci		/* Prepare sampling time settings */
211562306a36Sopenharmony_ci		stm32_adc_smpr_init(adc, channels[i].channel, smp);
211662306a36Sopenharmony_ci	}
211762306a36Sopenharmony_ci
211862306a36Sopenharmony_ci	return scan_index;
211962306a36Sopenharmony_ci}
212062306a36Sopenharmony_ci
212162306a36Sopenharmony_cistatic int stm32_adc_populate_int_ch(struct iio_dev *indio_dev, const char *ch_name,
212262306a36Sopenharmony_ci				     int chan)
212362306a36Sopenharmony_ci{
212462306a36Sopenharmony_ci	struct stm32_adc *adc = iio_priv(indio_dev);
212562306a36Sopenharmony_ci	u16 vrefint;
212662306a36Sopenharmony_ci	int i, ret;
212762306a36Sopenharmony_ci
212862306a36Sopenharmony_ci	for (i = 0; i < STM32_ADC_INT_CH_NB; i++) {
212962306a36Sopenharmony_ci		if (!strncmp(stm32_adc_ic[i].name, ch_name, STM32_ADC_CH_SZ)) {
213062306a36Sopenharmony_ci			/* Check internal channel availability */
213162306a36Sopenharmony_ci			switch (i) {
213262306a36Sopenharmony_ci			case STM32_ADC_INT_CH_VDDCORE:
213362306a36Sopenharmony_ci				if (!adc->cfg->regs->or_vddcore.reg)
213462306a36Sopenharmony_ci					dev_warn(&indio_dev->dev,
213562306a36Sopenharmony_ci						 "%s channel not available\n", ch_name);
213662306a36Sopenharmony_ci				break;
213762306a36Sopenharmony_ci			case STM32_ADC_INT_CH_VDDCPU:
213862306a36Sopenharmony_ci				if (!adc->cfg->regs->or_vddcpu.reg)
213962306a36Sopenharmony_ci					dev_warn(&indio_dev->dev,
214062306a36Sopenharmony_ci						 "%s channel not available\n", ch_name);
214162306a36Sopenharmony_ci				break;
214262306a36Sopenharmony_ci			case STM32_ADC_INT_CH_VDDQ_DDR:
214362306a36Sopenharmony_ci				if (!adc->cfg->regs->or_vddq_ddr.reg)
214462306a36Sopenharmony_ci					dev_warn(&indio_dev->dev,
214562306a36Sopenharmony_ci						 "%s channel not available\n", ch_name);
214662306a36Sopenharmony_ci				break;
214762306a36Sopenharmony_ci			case STM32_ADC_INT_CH_VREFINT:
214862306a36Sopenharmony_ci				if (!adc->cfg->regs->ccr_vref.reg)
214962306a36Sopenharmony_ci					dev_warn(&indio_dev->dev,
215062306a36Sopenharmony_ci						 "%s channel not available\n", ch_name);
215162306a36Sopenharmony_ci				break;
215262306a36Sopenharmony_ci			case STM32_ADC_INT_CH_VBAT:
215362306a36Sopenharmony_ci				if (!adc->cfg->regs->ccr_vbat.reg)
215462306a36Sopenharmony_ci					dev_warn(&indio_dev->dev,
215562306a36Sopenharmony_ci						 "%s channel not available\n", ch_name);
215662306a36Sopenharmony_ci				break;
215762306a36Sopenharmony_ci			}
215862306a36Sopenharmony_ci
215962306a36Sopenharmony_ci			if (stm32_adc_ic[i].idx != STM32_ADC_INT_CH_VREFINT) {
216062306a36Sopenharmony_ci				adc->int_ch[i] = chan;
216162306a36Sopenharmony_ci				break;
216262306a36Sopenharmony_ci			}
216362306a36Sopenharmony_ci
216462306a36Sopenharmony_ci			/* Get calibration data for vrefint channel */
216562306a36Sopenharmony_ci			ret = nvmem_cell_read_u16(&indio_dev->dev, "vrefint", &vrefint);
216662306a36Sopenharmony_ci			if (ret && ret != -ENOENT) {
216762306a36Sopenharmony_ci				return dev_err_probe(indio_dev->dev.parent, ret,
216862306a36Sopenharmony_ci						     "nvmem access error\n");
216962306a36Sopenharmony_ci			}
217062306a36Sopenharmony_ci			if (ret == -ENOENT) {
217162306a36Sopenharmony_ci				dev_dbg(&indio_dev->dev, "vrefint calibration not found. Skip vrefint channel\n");
217262306a36Sopenharmony_ci				return ret;
217362306a36Sopenharmony_ci			} else if (!vrefint) {
217462306a36Sopenharmony_ci				dev_dbg(&indio_dev->dev, "Null vrefint calibration value. Skip vrefint channel\n");
217562306a36Sopenharmony_ci				return -ENOENT;
217662306a36Sopenharmony_ci			}
217762306a36Sopenharmony_ci			adc->int_ch[i] = chan;
217862306a36Sopenharmony_ci			adc->vrefint.vrefint_cal = vrefint;
217962306a36Sopenharmony_ci		}
218062306a36Sopenharmony_ci	}
218162306a36Sopenharmony_ci
218262306a36Sopenharmony_ci	return 0;
218362306a36Sopenharmony_ci}
218462306a36Sopenharmony_ci
218562306a36Sopenharmony_cistatic int stm32_adc_generic_chan_init(struct iio_dev *indio_dev,
218662306a36Sopenharmony_ci				       struct stm32_adc *adc,
218762306a36Sopenharmony_ci				       struct iio_chan_spec *channels)
218862306a36Sopenharmony_ci{
218962306a36Sopenharmony_ci	const struct stm32_adc_info *adc_info = adc->cfg->adc_info;
219062306a36Sopenharmony_ci	struct fwnode_handle *child;
219162306a36Sopenharmony_ci	const char *name;
219262306a36Sopenharmony_ci	int val, scan_index = 0, ret;
219362306a36Sopenharmony_ci	bool differential;
219462306a36Sopenharmony_ci	u32 vin[2];
219562306a36Sopenharmony_ci
219662306a36Sopenharmony_ci	device_for_each_child_node(&indio_dev->dev, child) {
219762306a36Sopenharmony_ci		ret = fwnode_property_read_u32(child, "reg", &val);
219862306a36Sopenharmony_ci		if (ret) {
219962306a36Sopenharmony_ci			dev_err(&indio_dev->dev, "Missing channel index %d\n", ret);
220062306a36Sopenharmony_ci			goto err;
220162306a36Sopenharmony_ci		}
220262306a36Sopenharmony_ci
220362306a36Sopenharmony_ci		ret = fwnode_property_read_string(child, "label", &name);
220462306a36Sopenharmony_ci		/* label is optional */
220562306a36Sopenharmony_ci		if (!ret) {
220662306a36Sopenharmony_ci			if (strlen(name) >= STM32_ADC_CH_SZ) {
220762306a36Sopenharmony_ci				dev_err(&indio_dev->dev, "Label %s exceeds %d characters\n",
220862306a36Sopenharmony_ci					name, STM32_ADC_CH_SZ);
220962306a36Sopenharmony_ci				ret = -EINVAL;
221062306a36Sopenharmony_ci				goto err;
221162306a36Sopenharmony_ci			}
221262306a36Sopenharmony_ci			strncpy(adc->chan_name[val], name, STM32_ADC_CH_SZ);
221362306a36Sopenharmony_ci			ret = stm32_adc_populate_int_ch(indio_dev, name, val);
221462306a36Sopenharmony_ci			if (ret == -ENOENT)
221562306a36Sopenharmony_ci				continue;
221662306a36Sopenharmony_ci			else if (ret)
221762306a36Sopenharmony_ci				goto err;
221862306a36Sopenharmony_ci		} else if (ret != -EINVAL) {
221962306a36Sopenharmony_ci			dev_err(&indio_dev->dev, "Invalid label %d\n", ret);
222062306a36Sopenharmony_ci			goto err;
222162306a36Sopenharmony_ci		}
222262306a36Sopenharmony_ci
222362306a36Sopenharmony_ci		if (val >= adc_info->max_channels) {
222462306a36Sopenharmony_ci			dev_err(&indio_dev->dev, "Invalid channel %d\n", val);
222562306a36Sopenharmony_ci			ret = -EINVAL;
222662306a36Sopenharmony_ci			goto err;
222762306a36Sopenharmony_ci		}
222862306a36Sopenharmony_ci
222962306a36Sopenharmony_ci		differential = false;
223062306a36Sopenharmony_ci		ret = fwnode_property_read_u32_array(child, "diff-channels", vin, 2);
223162306a36Sopenharmony_ci		/* diff-channels is optional */
223262306a36Sopenharmony_ci		if (!ret) {
223362306a36Sopenharmony_ci			differential = true;
223462306a36Sopenharmony_ci			if (vin[0] != val || vin[1] >= adc_info->max_channels) {
223562306a36Sopenharmony_ci				dev_err(&indio_dev->dev, "Invalid channel in%d-in%d\n",
223662306a36Sopenharmony_ci					vin[0], vin[1]);
223762306a36Sopenharmony_ci				goto err;
223862306a36Sopenharmony_ci			}
223962306a36Sopenharmony_ci		} else if (ret != -EINVAL) {
224062306a36Sopenharmony_ci			dev_err(&indio_dev->dev, "Invalid diff-channels property %d\n", ret);
224162306a36Sopenharmony_ci			goto err;
224262306a36Sopenharmony_ci		}
224362306a36Sopenharmony_ci
224462306a36Sopenharmony_ci		stm32_adc_chan_init_one(indio_dev, &channels[scan_index], val,
224562306a36Sopenharmony_ci					vin[1], scan_index, differential);
224662306a36Sopenharmony_ci
224762306a36Sopenharmony_ci		val = 0;
224862306a36Sopenharmony_ci		ret = fwnode_property_read_u32(child, "st,min-sample-time-ns", &val);
224962306a36Sopenharmony_ci		/* st,min-sample-time-ns is optional */
225062306a36Sopenharmony_ci		if (ret && ret != -EINVAL) {
225162306a36Sopenharmony_ci			dev_err(&indio_dev->dev, "Invalid st,min-sample-time-ns property %d\n",
225262306a36Sopenharmony_ci				ret);
225362306a36Sopenharmony_ci			goto err;
225462306a36Sopenharmony_ci		}
225562306a36Sopenharmony_ci
225662306a36Sopenharmony_ci		stm32_adc_smpr_init(adc, channels[scan_index].channel, val);
225762306a36Sopenharmony_ci		if (differential)
225862306a36Sopenharmony_ci			stm32_adc_smpr_init(adc, vin[1], val);
225962306a36Sopenharmony_ci
226062306a36Sopenharmony_ci		scan_index++;
226162306a36Sopenharmony_ci	}
226262306a36Sopenharmony_ci
226362306a36Sopenharmony_ci	return scan_index;
226462306a36Sopenharmony_ci
226562306a36Sopenharmony_cierr:
226662306a36Sopenharmony_ci	fwnode_handle_put(child);
226762306a36Sopenharmony_ci
226862306a36Sopenharmony_ci	return ret;
226962306a36Sopenharmony_ci}
227062306a36Sopenharmony_ci
227162306a36Sopenharmony_cistatic int stm32_adc_chan_fw_init(struct iio_dev *indio_dev, bool timestamping)
227262306a36Sopenharmony_ci{
227362306a36Sopenharmony_ci	struct stm32_adc *adc = iio_priv(indio_dev);
227462306a36Sopenharmony_ci	const struct stm32_adc_info *adc_info = adc->cfg->adc_info;
227562306a36Sopenharmony_ci	struct iio_chan_spec *channels;
227662306a36Sopenharmony_ci	int scan_index = 0, num_channels = 0, ret, i;
227762306a36Sopenharmony_ci	bool legacy = false;
227862306a36Sopenharmony_ci
227962306a36Sopenharmony_ci	for (i = 0; i < STM32_ADC_INT_CH_NB; i++)
228062306a36Sopenharmony_ci		adc->int_ch[i] = STM32_ADC_INT_CH_NONE;
228162306a36Sopenharmony_ci
228262306a36Sopenharmony_ci	num_channels = device_get_child_node_count(&indio_dev->dev);
228362306a36Sopenharmony_ci	/* If no channels have been found, fallback to channels legacy properties. */
228462306a36Sopenharmony_ci	if (!num_channels) {
228562306a36Sopenharmony_ci		legacy = true;
228662306a36Sopenharmony_ci
228762306a36Sopenharmony_ci		ret = stm32_adc_get_legacy_chan_count(indio_dev, adc);
228862306a36Sopenharmony_ci		if (!ret) {
228962306a36Sopenharmony_ci			dev_err(indio_dev->dev.parent, "No channel found\n");
229062306a36Sopenharmony_ci			return -ENODATA;
229162306a36Sopenharmony_ci		} else if (ret < 0) {
229262306a36Sopenharmony_ci			return ret;
229362306a36Sopenharmony_ci		}
229462306a36Sopenharmony_ci
229562306a36Sopenharmony_ci		num_channels = ret;
229662306a36Sopenharmony_ci	}
229762306a36Sopenharmony_ci
229862306a36Sopenharmony_ci	if (num_channels > adc_info->max_channels) {
229962306a36Sopenharmony_ci		dev_err(&indio_dev->dev, "Channel number [%d] exceeds %d\n",
230062306a36Sopenharmony_ci			num_channels, adc_info->max_channels);
230162306a36Sopenharmony_ci		return -EINVAL;
230262306a36Sopenharmony_ci	}
230362306a36Sopenharmony_ci
230462306a36Sopenharmony_ci	if (timestamping)
230562306a36Sopenharmony_ci		num_channels++;
230662306a36Sopenharmony_ci
230762306a36Sopenharmony_ci	channels = devm_kcalloc(&indio_dev->dev, num_channels,
230862306a36Sopenharmony_ci				sizeof(struct iio_chan_spec), GFP_KERNEL);
230962306a36Sopenharmony_ci	if (!channels)
231062306a36Sopenharmony_ci		return -ENOMEM;
231162306a36Sopenharmony_ci
231262306a36Sopenharmony_ci	if (legacy)
231362306a36Sopenharmony_ci		ret = stm32_adc_legacy_chan_init(indio_dev, adc, channels,
231462306a36Sopenharmony_ci						 timestamping ? num_channels - 1 : num_channels);
231562306a36Sopenharmony_ci	else
231662306a36Sopenharmony_ci		ret = stm32_adc_generic_chan_init(indio_dev, adc, channels);
231762306a36Sopenharmony_ci	if (ret < 0)
231862306a36Sopenharmony_ci		return ret;
231962306a36Sopenharmony_ci	scan_index = ret;
232062306a36Sopenharmony_ci
232162306a36Sopenharmony_ci	if (timestamping) {
232262306a36Sopenharmony_ci		struct iio_chan_spec *timestamp = &channels[scan_index];
232362306a36Sopenharmony_ci
232462306a36Sopenharmony_ci		timestamp->type = IIO_TIMESTAMP;
232562306a36Sopenharmony_ci		timestamp->channel = -1;
232662306a36Sopenharmony_ci		timestamp->scan_index = scan_index;
232762306a36Sopenharmony_ci		timestamp->scan_type.sign = 's';
232862306a36Sopenharmony_ci		timestamp->scan_type.realbits = 64;
232962306a36Sopenharmony_ci		timestamp->scan_type.storagebits = 64;
233062306a36Sopenharmony_ci
233162306a36Sopenharmony_ci		scan_index++;
233262306a36Sopenharmony_ci	}
233362306a36Sopenharmony_ci
233462306a36Sopenharmony_ci	indio_dev->num_channels = scan_index;
233562306a36Sopenharmony_ci	indio_dev->channels = channels;
233662306a36Sopenharmony_ci
233762306a36Sopenharmony_ci	return 0;
233862306a36Sopenharmony_ci}
233962306a36Sopenharmony_ci
234062306a36Sopenharmony_cistatic int stm32_adc_dma_request(struct device *dev, struct iio_dev *indio_dev)
234162306a36Sopenharmony_ci{
234262306a36Sopenharmony_ci	struct stm32_adc *adc = iio_priv(indio_dev);
234362306a36Sopenharmony_ci	struct dma_slave_config config;
234462306a36Sopenharmony_ci	int ret;
234562306a36Sopenharmony_ci
234662306a36Sopenharmony_ci	adc->dma_chan = dma_request_chan(dev, "rx");
234762306a36Sopenharmony_ci	if (IS_ERR(adc->dma_chan)) {
234862306a36Sopenharmony_ci		ret = PTR_ERR(adc->dma_chan);
234962306a36Sopenharmony_ci		if (ret != -ENODEV)
235062306a36Sopenharmony_ci			return dev_err_probe(dev, ret,
235162306a36Sopenharmony_ci					     "DMA channel request failed with\n");
235262306a36Sopenharmony_ci
235362306a36Sopenharmony_ci		/* DMA is optional: fall back to IRQ mode */
235462306a36Sopenharmony_ci		adc->dma_chan = NULL;
235562306a36Sopenharmony_ci		return 0;
235662306a36Sopenharmony_ci	}
235762306a36Sopenharmony_ci
235862306a36Sopenharmony_ci	adc->rx_buf = dma_alloc_coherent(adc->dma_chan->device->dev,
235962306a36Sopenharmony_ci					 STM32_DMA_BUFFER_SIZE,
236062306a36Sopenharmony_ci					 &adc->rx_dma_buf, GFP_KERNEL);
236162306a36Sopenharmony_ci	if (!adc->rx_buf) {
236262306a36Sopenharmony_ci		ret = -ENOMEM;
236362306a36Sopenharmony_ci		goto err_release;
236462306a36Sopenharmony_ci	}
236562306a36Sopenharmony_ci
236662306a36Sopenharmony_ci	/* Configure DMA channel to read data register */
236762306a36Sopenharmony_ci	memset(&config, 0, sizeof(config));
236862306a36Sopenharmony_ci	config.src_addr = (dma_addr_t)adc->common->phys_base;
236962306a36Sopenharmony_ci	config.src_addr += adc->offset + adc->cfg->regs->dr;
237062306a36Sopenharmony_ci	config.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
237162306a36Sopenharmony_ci
237262306a36Sopenharmony_ci	ret = dmaengine_slave_config(adc->dma_chan, &config);
237362306a36Sopenharmony_ci	if (ret)
237462306a36Sopenharmony_ci		goto err_free;
237562306a36Sopenharmony_ci
237662306a36Sopenharmony_ci	return 0;
237762306a36Sopenharmony_ci
237862306a36Sopenharmony_cierr_free:
237962306a36Sopenharmony_ci	dma_free_coherent(adc->dma_chan->device->dev, STM32_DMA_BUFFER_SIZE,
238062306a36Sopenharmony_ci			  adc->rx_buf, adc->rx_dma_buf);
238162306a36Sopenharmony_cierr_release:
238262306a36Sopenharmony_ci	dma_release_channel(adc->dma_chan);
238362306a36Sopenharmony_ci
238462306a36Sopenharmony_ci	return ret;
238562306a36Sopenharmony_ci}
238662306a36Sopenharmony_ci
238762306a36Sopenharmony_cistatic int stm32_adc_probe(struct platform_device *pdev)
238862306a36Sopenharmony_ci{
238962306a36Sopenharmony_ci	struct iio_dev *indio_dev;
239062306a36Sopenharmony_ci	struct device *dev = &pdev->dev;
239162306a36Sopenharmony_ci	irqreturn_t (*handler)(int irq, void *p) = NULL;
239262306a36Sopenharmony_ci	struct stm32_adc *adc;
239362306a36Sopenharmony_ci	bool timestamping = false;
239462306a36Sopenharmony_ci	int ret;
239562306a36Sopenharmony_ci
239662306a36Sopenharmony_ci	indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*adc));
239762306a36Sopenharmony_ci	if (!indio_dev)
239862306a36Sopenharmony_ci		return -ENOMEM;
239962306a36Sopenharmony_ci
240062306a36Sopenharmony_ci	adc = iio_priv(indio_dev);
240162306a36Sopenharmony_ci	adc->common = dev_get_drvdata(pdev->dev.parent);
240262306a36Sopenharmony_ci	spin_lock_init(&adc->lock);
240362306a36Sopenharmony_ci	init_completion(&adc->completion);
240462306a36Sopenharmony_ci	adc->cfg = device_get_match_data(dev);
240562306a36Sopenharmony_ci
240662306a36Sopenharmony_ci	indio_dev->name = dev_name(&pdev->dev);
240762306a36Sopenharmony_ci	device_set_node(&indio_dev->dev, dev_fwnode(&pdev->dev));
240862306a36Sopenharmony_ci	indio_dev->info = &stm32_adc_iio_info;
240962306a36Sopenharmony_ci	indio_dev->modes = INDIO_DIRECT_MODE | INDIO_HARDWARE_TRIGGERED;
241062306a36Sopenharmony_ci
241162306a36Sopenharmony_ci	platform_set_drvdata(pdev, indio_dev);
241262306a36Sopenharmony_ci
241362306a36Sopenharmony_ci	ret = device_property_read_u32(dev, "reg", &adc->offset);
241462306a36Sopenharmony_ci	if (ret != 0) {
241562306a36Sopenharmony_ci		dev_err(&pdev->dev, "missing reg property\n");
241662306a36Sopenharmony_ci		return -EINVAL;
241762306a36Sopenharmony_ci	}
241862306a36Sopenharmony_ci
241962306a36Sopenharmony_ci	adc->irq = platform_get_irq(pdev, 0);
242062306a36Sopenharmony_ci	if (adc->irq < 0)
242162306a36Sopenharmony_ci		return adc->irq;
242262306a36Sopenharmony_ci
242362306a36Sopenharmony_ci	ret = devm_request_threaded_irq(&pdev->dev, adc->irq, stm32_adc_isr,
242462306a36Sopenharmony_ci					stm32_adc_threaded_isr,
242562306a36Sopenharmony_ci					0, pdev->name, indio_dev);
242662306a36Sopenharmony_ci	if (ret) {
242762306a36Sopenharmony_ci		dev_err(&pdev->dev, "failed to request IRQ\n");
242862306a36Sopenharmony_ci		return ret;
242962306a36Sopenharmony_ci	}
243062306a36Sopenharmony_ci
243162306a36Sopenharmony_ci	adc->clk = devm_clk_get(&pdev->dev, NULL);
243262306a36Sopenharmony_ci	if (IS_ERR(adc->clk)) {
243362306a36Sopenharmony_ci		ret = PTR_ERR(adc->clk);
243462306a36Sopenharmony_ci		if (ret == -ENOENT && !adc->cfg->clk_required) {
243562306a36Sopenharmony_ci			adc->clk = NULL;
243662306a36Sopenharmony_ci		} else {
243762306a36Sopenharmony_ci			dev_err(&pdev->dev, "Can't get clock\n");
243862306a36Sopenharmony_ci			return ret;
243962306a36Sopenharmony_ci		}
244062306a36Sopenharmony_ci	}
244162306a36Sopenharmony_ci
244262306a36Sopenharmony_ci	ret = stm32_adc_fw_get_resolution(indio_dev);
244362306a36Sopenharmony_ci	if (ret < 0)
244462306a36Sopenharmony_ci		return ret;
244562306a36Sopenharmony_ci
244662306a36Sopenharmony_ci	ret = stm32_adc_dma_request(dev, indio_dev);
244762306a36Sopenharmony_ci	if (ret < 0)
244862306a36Sopenharmony_ci		return ret;
244962306a36Sopenharmony_ci
245062306a36Sopenharmony_ci	if (!adc->dma_chan) {
245162306a36Sopenharmony_ci		/* For PIO mode only, iio_pollfunc_store_time stores a timestamp
245262306a36Sopenharmony_ci		 * in the primary trigger IRQ handler and stm32_adc_trigger_handler
245362306a36Sopenharmony_ci		 * runs in the IRQ thread to push out buffer along with timestamp.
245462306a36Sopenharmony_ci		 */
245562306a36Sopenharmony_ci		handler = &stm32_adc_trigger_handler;
245662306a36Sopenharmony_ci		timestamping = true;
245762306a36Sopenharmony_ci	}
245862306a36Sopenharmony_ci
245962306a36Sopenharmony_ci	ret = stm32_adc_chan_fw_init(indio_dev, timestamping);
246062306a36Sopenharmony_ci	if (ret < 0)
246162306a36Sopenharmony_ci		goto err_dma_disable;
246262306a36Sopenharmony_ci
246362306a36Sopenharmony_ci	ret = iio_triggered_buffer_setup(indio_dev,
246462306a36Sopenharmony_ci					 &iio_pollfunc_store_time, handler,
246562306a36Sopenharmony_ci					 &stm32_adc_buffer_setup_ops);
246662306a36Sopenharmony_ci	if (ret) {
246762306a36Sopenharmony_ci		dev_err(&pdev->dev, "buffer setup failed\n");
246862306a36Sopenharmony_ci		goto err_dma_disable;
246962306a36Sopenharmony_ci	}
247062306a36Sopenharmony_ci
247162306a36Sopenharmony_ci	/* Get stm32-adc-core PM online */
247262306a36Sopenharmony_ci	pm_runtime_get_noresume(dev);
247362306a36Sopenharmony_ci	pm_runtime_set_active(dev);
247462306a36Sopenharmony_ci	pm_runtime_set_autosuspend_delay(dev, STM32_ADC_HW_STOP_DELAY_MS);
247562306a36Sopenharmony_ci	pm_runtime_use_autosuspend(dev);
247662306a36Sopenharmony_ci	pm_runtime_enable(dev);
247762306a36Sopenharmony_ci
247862306a36Sopenharmony_ci	ret = stm32_adc_hw_start(dev);
247962306a36Sopenharmony_ci	if (ret)
248062306a36Sopenharmony_ci		goto err_buffer_cleanup;
248162306a36Sopenharmony_ci
248262306a36Sopenharmony_ci	ret = iio_device_register(indio_dev);
248362306a36Sopenharmony_ci	if (ret) {
248462306a36Sopenharmony_ci		dev_err(&pdev->dev, "iio dev register failed\n");
248562306a36Sopenharmony_ci		goto err_hw_stop;
248662306a36Sopenharmony_ci	}
248762306a36Sopenharmony_ci
248862306a36Sopenharmony_ci	pm_runtime_mark_last_busy(dev);
248962306a36Sopenharmony_ci	pm_runtime_put_autosuspend(dev);
249062306a36Sopenharmony_ci
249162306a36Sopenharmony_ci	if (IS_ENABLED(CONFIG_DEBUG_FS))
249262306a36Sopenharmony_ci		stm32_adc_debugfs_init(indio_dev);
249362306a36Sopenharmony_ci
249462306a36Sopenharmony_ci	return 0;
249562306a36Sopenharmony_ci
249662306a36Sopenharmony_cierr_hw_stop:
249762306a36Sopenharmony_ci	stm32_adc_hw_stop(dev);
249862306a36Sopenharmony_ci
249962306a36Sopenharmony_cierr_buffer_cleanup:
250062306a36Sopenharmony_ci	pm_runtime_disable(dev);
250162306a36Sopenharmony_ci	pm_runtime_set_suspended(dev);
250262306a36Sopenharmony_ci	pm_runtime_put_noidle(dev);
250362306a36Sopenharmony_ci	iio_triggered_buffer_cleanup(indio_dev);
250462306a36Sopenharmony_ci
250562306a36Sopenharmony_cierr_dma_disable:
250662306a36Sopenharmony_ci	if (adc->dma_chan) {
250762306a36Sopenharmony_ci		dma_free_coherent(adc->dma_chan->device->dev,
250862306a36Sopenharmony_ci				  STM32_DMA_BUFFER_SIZE,
250962306a36Sopenharmony_ci				  adc->rx_buf, adc->rx_dma_buf);
251062306a36Sopenharmony_ci		dma_release_channel(adc->dma_chan);
251162306a36Sopenharmony_ci	}
251262306a36Sopenharmony_ci
251362306a36Sopenharmony_ci	return ret;
251462306a36Sopenharmony_ci}
251562306a36Sopenharmony_ci
251662306a36Sopenharmony_cistatic int stm32_adc_remove(struct platform_device *pdev)
251762306a36Sopenharmony_ci{
251862306a36Sopenharmony_ci	struct iio_dev *indio_dev = platform_get_drvdata(pdev);
251962306a36Sopenharmony_ci	struct stm32_adc *adc = iio_priv(indio_dev);
252062306a36Sopenharmony_ci
252162306a36Sopenharmony_ci	pm_runtime_get_sync(&pdev->dev);
252262306a36Sopenharmony_ci	/* iio_device_unregister() also removes debugfs entries */
252362306a36Sopenharmony_ci	iio_device_unregister(indio_dev);
252462306a36Sopenharmony_ci	stm32_adc_hw_stop(&pdev->dev);
252562306a36Sopenharmony_ci	pm_runtime_disable(&pdev->dev);
252662306a36Sopenharmony_ci	pm_runtime_set_suspended(&pdev->dev);
252762306a36Sopenharmony_ci	pm_runtime_put_noidle(&pdev->dev);
252862306a36Sopenharmony_ci	iio_triggered_buffer_cleanup(indio_dev);
252962306a36Sopenharmony_ci	if (adc->dma_chan) {
253062306a36Sopenharmony_ci		dma_free_coherent(adc->dma_chan->device->dev,
253162306a36Sopenharmony_ci				  STM32_DMA_BUFFER_SIZE,
253262306a36Sopenharmony_ci				  adc->rx_buf, adc->rx_dma_buf);
253362306a36Sopenharmony_ci		dma_release_channel(adc->dma_chan);
253462306a36Sopenharmony_ci	}
253562306a36Sopenharmony_ci
253662306a36Sopenharmony_ci	return 0;
253762306a36Sopenharmony_ci}
253862306a36Sopenharmony_ci
253962306a36Sopenharmony_cistatic int stm32_adc_suspend(struct device *dev)
254062306a36Sopenharmony_ci{
254162306a36Sopenharmony_ci	struct iio_dev *indio_dev = dev_get_drvdata(dev);
254262306a36Sopenharmony_ci
254362306a36Sopenharmony_ci	if (iio_buffer_enabled(indio_dev))
254462306a36Sopenharmony_ci		stm32_adc_buffer_predisable(indio_dev);
254562306a36Sopenharmony_ci
254662306a36Sopenharmony_ci	return pm_runtime_force_suspend(dev);
254762306a36Sopenharmony_ci}
254862306a36Sopenharmony_ci
254962306a36Sopenharmony_cistatic int stm32_adc_resume(struct device *dev)
255062306a36Sopenharmony_ci{
255162306a36Sopenharmony_ci	struct iio_dev *indio_dev = dev_get_drvdata(dev);
255262306a36Sopenharmony_ci	int ret;
255362306a36Sopenharmony_ci
255462306a36Sopenharmony_ci	ret = pm_runtime_force_resume(dev);
255562306a36Sopenharmony_ci	if (ret < 0)
255662306a36Sopenharmony_ci		return ret;
255762306a36Sopenharmony_ci
255862306a36Sopenharmony_ci	if (!iio_buffer_enabled(indio_dev))
255962306a36Sopenharmony_ci		return 0;
256062306a36Sopenharmony_ci
256162306a36Sopenharmony_ci	ret = stm32_adc_update_scan_mode(indio_dev,
256262306a36Sopenharmony_ci					 indio_dev->active_scan_mask);
256362306a36Sopenharmony_ci	if (ret < 0)
256462306a36Sopenharmony_ci		return ret;
256562306a36Sopenharmony_ci
256662306a36Sopenharmony_ci	return stm32_adc_buffer_postenable(indio_dev);
256762306a36Sopenharmony_ci}
256862306a36Sopenharmony_ci
256962306a36Sopenharmony_cistatic int stm32_adc_runtime_suspend(struct device *dev)
257062306a36Sopenharmony_ci{
257162306a36Sopenharmony_ci	return stm32_adc_hw_stop(dev);
257262306a36Sopenharmony_ci}
257362306a36Sopenharmony_ci
257462306a36Sopenharmony_cistatic int stm32_adc_runtime_resume(struct device *dev)
257562306a36Sopenharmony_ci{
257662306a36Sopenharmony_ci	return stm32_adc_hw_start(dev);
257762306a36Sopenharmony_ci}
257862306a36Sopenharmony_ci
257962306a36Sopenharmony_cistatic const struct dev_pm_ops stm32_adc_pm_ops = {
258062306a36Sopenharmony_ci	SYSTEM_SLEEP_PM_OPS(stm32_adc_suspend, stm32_adc_resume)
258162306a36Sopenharmony_ci	RUNTIME_PM_OPS(stm32_adc_runtime_suspend, stm32_adc_runtime_resume,
258262306a36Sopenharmony_ci		       NULL)
258362306a36Sopenharmony_ci};
258462306a36Sopenharmony_ci
258562306a36Sopenharmony_cistatic const struct stm32_adc_cfg stm32f4_adc_cfg = {
258662306a36Sopenharmony_ci	.regs = &stm32f4_adc_regspec,
258762306a36Sopenharmony_ci	.adc_info = &stm32f4_adc_info,
258862306a36Sopenharmony_ci	.trigs = stm32f4_adc_trigs,
258962306a36Sopenharmony_ci	.clk_required = true,
259062306a36Sopenharmony_ci	.start_conv = stm32f4_adc_start_conv,
259162306a36Sopenharmony_ci	.stop_conv = stm32f4_adc_stop_conv,
259262306a36Sopenharmony_ci	.smp_cycles = stm32f4_adc_smp_cycles,
259362306a36Sopenharmony_ci	.irq_clear = stm32f4_adc_irq_clear,
259462306a36Sopenharmony_ci};
259562306a36Sopenharmony_ci
259662306a36Sopenharmony_cistatic const unsigned int stm32_adc_min_ts_h7[] = { 0, 0, 0, 4300, 9000 };
259762306a36Sopenharmony_cistatic_assert(ARRAY_SIZE(stm32_adc_min_ts_h7) == STM32_ADC_INT_CH_NB);
259862306a36Sopenharmony_ci
259962306a36Sopenharmony_cistatic const struct stm32_adc_cfg stm32h7_adc_cfg = {
260062306a36Sopenharmony_ci	.regs = &stm32h7_adc_regspec,
260162306a36Sopenharmony_ci	.adc_info = &stm32h7_adc_info,
260262306a36Sopenharmony_ci	.trigs = stm32h7_adc_trigs,
260362306a36Sopenharmony_ci	.has_boostmode = true,
260462306a36Sopenharmony_ci	.has_linearcal = true,
260562306a36Sopenharmony_ci	.has_presel = true,
260662306a36Sopenharmony_ci	.start_conv = stm32h7_adc_start_conv,
260762306a36Sopenharmony_ci	.stop_conv = stm32h7_adc_stop_conv,
260862306a36Sopenharmony_ci	.prepare = stm32h7_adc_prepare,
260962306a36Sopenharmony_ci	.unprepare = stm32h7_adc_unprepare,
261062306a36Sopenharmony_ci	.smp_cycles = stm32h7_adc_smp_cycles,
261162306a36Sopenharmony_ci	.irq_clear = stm32h7_adc_irq_clear,
261262306a36Sopenharmony_ci	.ts_int_ch = stm32_adc_min_ts_h7,
261362306a36Sopenharmony_ci};
261462306a36Sopenharmony_ci
261562306a36Sopenharmony_cistatic const unsigned int stm32_adc_min_ts_mp1[] = { 100, 100, 100, 4300, 9800 };
261662306a36Sopenharmony_cistatic_assert(ARRAY_SIZE(stm32_adc_min_ts_mp1) == STM32_ADC_INT_CH_NB);
261762306a36Sopenharmony_ci
261862306a36Sopenharmony_cistatic const struct stm32_adc_cfg stm32mp1_adc_cfg = {
261962306a36Sopenharmony_ci	.regs = &stm32mp1_adc_regspec,
262062306a36Sopenharmony_ci	.adc_info = &stm32h7_adc_info,
262162306a36Sopenharmony_ci	.trigs = stm32h7_adc_trigs,
262262306a36Sopenharmony_ci	.has_vregready = true,
262362306a36Sopenharmony_ci	.has_boostmode = true,
262462306a36Sopenharmony_ci	.has_linearcal = true,
262562306a36Sopenharmony_ci	.has_presel = true,
262662306a36Sopenharmony_ci	.start_conv = stm32h7_adc_start_conv,
262762306a36Sopenharmony_ci	.stop_conv = stm32h7_adc_stop_conv,
262862306a36Sopenharmony_ci	.prepare = stm32h7_adc_prepare,
262962306a36Sopenharmony_ci	.unprepare = stm32h7_adc_unprepare,
263062306a36Sopenharmony_ci	.smp_cycles = stm32h7_adc_smp_cycles,
263162306a36Sopenharmony_ci	.irq_clear = stm32h7_adc_irq_clear,
263262306a36Sopenharmony_ci	.ts_int_ch = stm32_adc_min_ts_mp1,
263362306a36Sopenharmony_ci};
263462306a36Sopenharmony_ci
263562306a36Sopenharmony_cistatic const unsigned int stm32_adc_min_ts_mp13[] = { 100, 0, 0, 4300, 9800 };
263662306a36Sopenharmony_cistatic_assert(ARRAY_SIZE(stm32_adc_min_ts_mp13) == STM32_ADC_INT_CH_NB);
263762306a36Sopenharmony_ci
263862306a36Sopenharmony_cistatic const struct stm32_adc_cfg stm32mp13_adc_cfg = {
263962306a36Sopenharmony_ci	.regs = &stm32mp13_adc_regspec,
264062306a36Sopenharmony_ci	.adc_info = &stm32mp13_adc_info,
264162306a36Sopenharmony_ci	.trigs = stm32h7_adc_trigs,
264262306a36Sopenharmony_ci	.start_conv = stm32mp13_adc_start_conv,
264362306a36Sopenharmony_ci	.stop_conv = stm32h7_adc_stop_conv,
264462306a36Sopenharmony_ci	.prepare = stm32h7_adc_prepare,
264562306a36Sopenharmony_ci	.unprepare = stm32h7_adc_unprepare,
264662306a36Sopenharmony_ci	.smp_cycles = stm32mp13_adc_smp_cycles,
264762306a36Sopenharmony_ci	.irq_clear = stm32h7_adc_irq_clear,
264862306a36Sopenharmony_ci	.ts_int_ch = stm32_adc_min_ts_mp13,
264962306a36Sopenharmony_ci};
265062306a36Sopenharmony_ci
265162306a36Sopenharmony_cistatic const struct of_device_id stm32_adc_of_match[] = {
265262306a36Sopenharmony_ci	{ .compatible = "st,stm32f4-adc", .data = (void *)&stm32f4_adc_cfg },
265362306a36Sopenharmony_ci	{ .compatible = "st,stm32h7-adc", .data = (void *)&stm32h7_adc_cfg },
265462306a36Sopenharmony_ci	{ .compatible = "st,stm32mp1-adc", .data = (void *)&stm32mp1_adc_cfg },
265562306a36Sopenharmony_ci	{ .compatible = "st,stm32mp13-adc", .data = (void *)&stm32mp13_adc_cfg },
265662306a36Sopenharmony_ci	{},
265762306a36Sopenharmony_ci};
265862306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, stm32_adc_of_match);
265962306a36Sopenharmony_ci
266062306a36Sopenharmony_cistatic struct platform_driver stm32_adc_driver = {
266162306a36Sopenharmony_ci	.probe = stm32_adc_probe,
266262306a36Sopenharmony_ci	.remove = stm32_adc_remove,
266362306a36Sopenharmony_ci	.driver = {
266462306a36Sopenharmony_ci		.name = "stm32-adc",
266562306a36Sopenharmony_ci		.of_match_table = stm32_adc_of_match,
266662306a36Sopenharmony_ci		.pm = pm_ptr(&stm32_adc_pm_ops),
266762306a36Sopenharmony_ci	},
266862306a36Sopenharmony_ci};
266962306a36Sopenharmony_cimodule_platform_driver(stm32_adc_driver);
267062306a36Sopenharmony_ci
267162306a36Sopenharmony_ciMODULE_AUTHOR("Fabrice Gasnier <fabrice.gasnier@st.com>");
267262306a36Sopenharmony_ciMODULE_DESCRIPTION("STMicroelectronics STM32 ADC IIO driver");
267362306a36Sopenharmony_ciMODULE_LICENSE("GPL v2");
267462306a36Sopenharmony_ciMODULE_ALIAS("platform:stm32-adc");
2675