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