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