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 * Inspired from: fsl-imx25-tsadc 962306a36Sopenharmony_ci * 1062306a36Sopenharmony_ci */ 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include <linux/bitfield.h> 1362306a36Sopenharmony_ci#include <linux/clk.h> 1462306a36Sopenharmony_ci#include <linux/interrupt.h> 1562306a36Sopenharmony_ci#include <linux/irqchip/chained_irq.h> 1662306a36Sopenharmony_ci#include <linux/irqdesc.h> 1762306a36Sopenharmony_ci#include <linux/irqdomain.h> 1862306a36Sopenharmony_ci#include <linux/mfd/syscon.h> 1962306a36Sopenharmony_ci#include <linux/module.h> 2062306a36Sopenharmony_ci#include <linux/of_device.h> 2162306a36Sopenharmony_ci#include <linux/of_platform.h> 2262306a36Sopenharmony_ci#include <linux/platform_device.h> 2362306a36Sopenharmony_ci#include <linux/pm_runtime.h> 2462306a36Sopenharmony_ci#include <linux/regmap.h> 2562306a36Sopenharmony_ci#include <linux/regulator/consumer.h> 2662306a36Sopenharmony_ci#include <linux/slab.h> 2762306a36Sopenharmony_ci#include <linux/units.h> 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci#include "stm32-adc-core.h" 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci#define STM32_ADC_CORE_SLEEP_DELAY_MS 2000 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci/* SYSCFG registers */ 3462306a36Sopenharmony_ci#define STM32MP1_SYSCFG_PMCSETR 0x04 3562306a36Sopenharmony_ci#define STM32MP1_SYSCFG_PMCCLRR 0x44 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci/* SYSCFG bit fields */ 3862306a36Sopenharmony_ci#define STM32MP1_SYSCFG_ANASWVDD_MASK BIT(9) 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci/* SYSCFG capability flags */ 4162306a36Sopenharmony_ci#define HAS_VBOOSTER BIT(0) 4262306a36Sopenharmony_ci#define HAS_ANASWVDD BIT(1) 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci/** 4562306a36Sopenharmony_ci * struct stm32_adc_common_regs - stm32 common registers 4662306a36Sopenharmony_ci * @csr: common status register offset 4762306a36Sopenharmony_ci * @ccr: common control register offset 4862306a36Sopenharmony_ci * @eoc_msk: array of eoc (end of conversion flag) masks in csr for adc1..n 4962306a36Sopenharmony_ci * @ovr_msk: array of ovr (overrun flag) masks in csr for adc1..n 5062306a36Sopenharmony_ci * @ier: interrupt enable register offset for each adc 5162306a36Sopenharmony_ci * @eocie_msk: end of conversion interrupt enable mask in @ier 5262306a36Sopenharmony_ci */ 5362306a36Sopenharmony_cistruct stm32_adc_common_regs { 5462306a36Sopenharmony_ci u32 csr; 5562306a36Sopenharmony_ci u32 ccr; 5662306a36Sopenharmony_ci u32 eoc_msk[STM32_ADC_MAX_ADCS]; 5762306a36Sopenharmony_ci u32 ovr_msk[STM32_ADC_MAX_ADCS]; 5862306a36Sopenharmony_ci u32 ier; 5962306a36Sopenharmony_ci u32 eocie_msk; 6062306a36Sopenharmony_ci}; 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_cistruct stm32_adc_priv; 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci/** 6562306a36Sopenharmony_ci * struct stm32_adc_priv_cfg - stm32 core compatible configuration data 6662306a36Sopenharmony_ci * @regs: common registers for all instances 6762306a36Sopenharmony_ci * @clk_sel: clock selection routine 6862306a36Sopenharmony_ci * @max_clk_rate_hz: maximum analog clock rate (Hz, from datasheet) 6962306a36Sopenharmony_ci * @ipid: adc identification number 7062306a36Sopenharmony_ci * @has_syscfg: SYSCFG capability flags 7162306a36Sopenharmony_ci * @num_irqs: number of interrupt lines 7262306a36Sopenharmony_ci * @num_adcs: maximum number of ADC instances in the common registers 7362306a36Sopenharmony_ci */ 7462306a36Sopenharmony_cistruct stm32_adc_priv_cfg { 7562306a36Sopenharmony_ci const struct stm32_adc_common_regs *regs; 7662306a36Sopenharmony_ci int (*clk_sel)(struct platform_device *, struct stm32_adc_priv *); 7762306a36Sopenharmony_ci u32 max_clk_rate_hz; 7862306a36Sopenharmony_ci u32 ipid; 7962306a36Sopenharmony_ci unsigned int has_syscfg; 8062306a36Sopenharmony_ci unsigned int num_irqs; 8162306a36Sopenharmony_ci unsigned int num_adcs; 8262306a36Sopenharmony_ci}; 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci/** 8562306a36Sopenharmony_ci * struct stm32_adc_priv - stm32 ADC core private data 8662306a36Sopenharmony_ci * @irq: irq(s) for ADC block 8762306a36Sopenharmony_ci * @nb_adc_max: actual maximum number of instance per ADC block 8862306a36Sopenharmony_ci * @domain: irq domain reference 8962306a36Sopenharmony_ci * @aclk: clock reference for the analog circuitry 9062306a36Sopenharmony_ci * @bclk: bus clock common for all ADCs, depends on part used 9162306a36Sopenharmony_ci * @max_clk_rate: desired maximum clock rate 9262306a36Sopenharmony_ci * @booster: booster supply reference 9362306a36Sopenharmony_ci * @vdd: vdd supply reference 9462306a36Sopenharmony_ci * @vdda: vdda analog supply reference 9562306a36Sopenharmony_ci * @vref: regulator reference 9662306a36Sopenharmony_ci * @vdd_uv: vdd supply voltage (microvolts) 9762306a36Sopenharmony_ci * @vdda_uv: vdda supply voltage (microvolts) 9862306a36Sopenharmony_ci * @cfg: compatible configuration data 9962306a36Sopenharmony_ci * @common: common data for all ADC instances 10062306a36Sopenharmony_ci * @ccr_bak: backup CCR in low power mode 10162306a36Sopenharmony_ci * @syscfg: reference to syscon, system control registers 10262306a36Sopenharmony_ci */ 10362306a36Sopenharmony_cistruct stm32_adc_priv { 10462306a36Sopenharmony_ci int irq[STM32_ADC_MAX_ADCS]; 10562306a36Sopenharmony_ci unsigned int nb_adc_max; 10662306a36Sopenharmony_ci struct irq_domain *domain; 10762306a36Sopenharmony_ci struct clk *aclk; 10862306a36Sopenharmony_ci struct clk *bclk; 10962306a36Sopenharmony_ci u32 max_clk_rate; 11062306a36Sopenharmony_ci struct regulator *booster; 11162306a36Sopenharmony_ci struct regulator *vdd; 11262306a36Sopenharmony_ci struct regulator *vdda; 11362306a36Sopenharmony_ci struct regulator *vref; 11462306a36Sopenharmony_ci int vdd_uv; 11562306a36Sopenharmony_ci int vdda_uv; 11662306a36Sopenharmony_ci const struct stm32_adc_priv_cfg *cfg; 11762306a36Sopenharmony_ci struct stm32_adc_common common; 11862306a36Sopenharmony_ci u32 ccr_bak; 11962306a36Sopenharmony_ci struct regmap *syscfg; 12062306a36Sopenharmony_ci}; 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_cistatic struct stm32_adc_priv *to_stm32_adc_priv(struct stm32_adc_common *com) 12362306a36Sopenharmony_ci{ 12462306a36Sopenharmony_ci return container_of(com, struct stm32_adc_priv, common); 12562306a36Sopenharmony_ci} 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci/* STM32F4 ADC internal common clock prescaler division ratios */ 12862306a36Sopenharmony_cistatic int stm32f4_pclk_div[] = {2, 4, 6, 8}; 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci/** 13162306a36Sopenharmony_ci * stm32f4_adc_clk_sel() - Select stm32f4 ADC common clock prescaler 13262306a36Sopenharmony_ci * @pdev: platform device 13362306a36Sopenharmony_ci * @priv: stm32 ADC core private data 13462306a36Sopenharmony_ci * Select clock prescaler used for analog conversions, before using ADC. 13562306a36Sopenharmony_ci */ 13662306a36Sopenharmony_cistatic int stm32f4_adc_clk_sel(struct platform_device *pdev, 13762306a36Sopenharmony_ci struct stm32_adc_priv *priv) 13862306a36Sopenharmony_ci{ 13962306a36Sopenharmony_ci unsigned long rate; 14062306a36Sopenharmony_ci u32 val; 14162306a36Sopenharmony_ci int i; 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci /* stm32f4 has one clk input for analog (mandatory), enforce it here */ 14462306a36Sopenharmony_ci if (!priv->aclk) { 14562306a36Sopenharmony_ci dev_err(&pdev->dev, "No 'adc' clock found\n"); 14662306a36Sopenharmony_ci return -ENOENT; 14762306a36Sopenharmony_ci } 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci rate = clk_get_rate(priv->aclk); 15062306a36Sopenharmony_ci if (!rate) { 15162306a36Sopenharmony_ci dev_err(&pdev->dev, "Invalid clock rate: 0\n"); 15262306a36Sopenharmony_ci return -EINVAL; 15362306a36Sopenharmony_ci } 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(stm32f4_pclk_div); i++) { 15662306a36Sopenharmony_ci if ((rate / stm32f4_pclk_div[i]) <= priv->max_clk_rate) 15762306a36Sopenharmony_ci break; 15862306a36Sopenharmony_ci } 15962306a36Sopenharmony_ci if (i >= ARRAY_SIZE(stm32f4_pclk_div)) { 16062306a36Sopenharmony_ci dev_err(&pdev->dev, "adc clk selection failed\n"); 16162306a36Sopenharmony_ci return -EINVAL; 16262306a36Sopenharmony_ci } 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci priv->common.rate = rate / stm32f4_pclk_div[i]; 16562306a36Sopenharmony_ci val = readl_relaxed(priv->common.base + STM32F4_ADC_CCR); 16662306a36Sopenharmony_ci val &= ~STM32F4_ADC_ADCPRE_MASK; 16762306a36Sopenharmony_ci val |= i << STM32F4_ADC_ADCPRE_SHIFT; 16862306a36Sopenharmony_ci writel_relaxed(val, priv->common.base + STM32F4_ADC_CCR); 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci dev_dbg(&pdev->dev, "Using analog clock source at %ld kHz\n", 17162306a36Sopenharmony_ci priv->common.rate / 1000); 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci return 0; 17462306a36Sopenharmony_ci} 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ci/** 17762306a36Sopenharmony_ci * struct stm32h7_adc_ck_spec - specification for stm32h7 adc clock 17862306a36Sopenharmony_ci * @ckmode: ADC clock mode, Async or sync with prescaler. 17962306a36Sopenharmony_ci * @presc: prescaler bitfield for async clock mode 18062306a36Sopenharmony_ci * @div: prescaler division ratio 18162306a36Sopenharmony_ci */ 18262306a36Sopenharmony_cistruct stm32h7_adc_ck_spec { 18362306a36Sopenharmony_ci u32 ckmode; 18462306a36Sopenharmony_ci u32 presc; 18562306a36Sopenharmony_ci int div; 18662306a36Sopenharmony_ci}; 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_cistatic const struct stm32h7_adc_ck_spec stm32h7_adc_ckmodes_spec[] = { 18962306a36Sopenharmony_ci /* 00: CK_ADC[1..3]: Asynchronous clock modes */ 19062306a36Sopenharmony_ci { 0, 0, 1 }, 19162306a36Sopenharmony_ci { 0, 1, 2 }, 19262306a36Sopenharmony_ci { 0, 2, 4 }, 19362306a36Sopenharmony_ci { 0, 3, 6 }, 19462306a36Sopenharmony_ci { 0, 4, 8 }, 19562306a36Sopenharmony_ci { 0, 5, 10 }, 19662306a36Sopenharmony_ci { 0, 6, 12 }, 19762306a36Sopenharmony_ci { 0, 7, 16 }, 19862306a36Sopenharmony_ci { 0, 8, 32 }, 19962306a36Sopenharmony_ci { 0, 9, 64 }, 20062306a36Sopenharmony_ci { 0, 10, 128 }, 20162306a36Sopenharmony_ci { 0, 11, 256 }, 20262306a36Sopenharmony_ci /* HCLK used: Synchronous clock modes (1, 2 or 4 prescaler) */ 20362306a36Sopenharmony_ci { 1, 0, 1 }, 20462306a36Sopenharmony_ci { 2, 0, 2 }, 20562306a36Sopenharmony_ci { 3, 0, 4 }, 20662306a36Sopenharmony_ci}; 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_cistatic int stm32h7_adc_clk_sel(struct platform_device *pdev, 20962306a36Sopenharmony_ci struct stm32_adc_priv *priv) 21062306a36Sopenharmony_ci{ 21162306a36Sopenharmony_ci u32 ckmode, presc, val; 21262306a36Sopenharmony_ci unsigned long rate; 21362306a36Sopenharmony_ci int i, div, duty; 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci /* stm32h7 bus clock is common for all ADC instances (mandatory) */ 21662306a36Sopenharmony_ci if (!priv->bclk) { 21762306a36Sopenharmony_ci dev_err(&pdev->dev, "No 'bus' clock found\n"); 21862306a36Sopenharmony_ci return -ENOENT; 21962306a36Sopenharmony_ci } 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci /* 22262306a36Sopenharmony_ci * stm32h7 can use either 'bus' or 'adc' clock for analog circuitry. 22362306a36Sopenharmony_ci * So, choice is to have bus clock mandatory and adc clock optional. 22462306a36Sopenharmony_ci * If optional 'adc' clock has been found, then try to use it first. 22562306a36Sopenharmony_ci */ 22662306a36Sopenharmony_ci if (priv->aclk) { 22762306a36Sopenharmony_ci /* 22862306a36Sopenharmony_ci * Asynchronous clock modes (e.g. ckmode == 0) 22962306a36Sopenharmony_ci * From spec: PLL output musn't exceed max rate 23062306a36Sopenharmony_ci */ 23162306a36Sopenharmony_ci rate = clk_get_rate(priv->aclk); 23262306a36Sopenharmony_ci if (!rate) { 23362306a36Sopenharmony_ci dev_err(&pdev->dev, "Invalid adc clock rate: 0\n"); 23462306a36Sopenharmony_ci return -EINVAL; 23562306a36Sopenharmony_ci } 23662306a36Sopenharmony_ci 23762306a36Sopenharmony_ci /* If duty is an error, kindly use at least /2 divider */ 23862306a36Sopenharmony_ci duty = clk_get_scaled_duty_cycle(priv->aclk, 100); 23962306a36Sopenharmony_ci if (duty < 0) 24062306a36Sopenharmony_ci dev_warn(&pdev->dev, "adc clock duty: %d\n", duty); 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(stm32h7_adc_ckmodes_spec); i++) { 24362306a36Sopenharmony_ci ckmode = stm32h7_adc_ckmodes_spec[i].ckmode; 24462306a36Sopenharmony_ci presc = stm32h7_adc_ckmodes_spec[i].presc; 24562306a36Sopenharmony_ci div = stm32h7_adc_ckmodes_spec[i].div; 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci if (ckmode) 24862306a36Sopenharmony_ci continue; 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci /* 25162306a36Sopenharmony_ci * For proper operation, clock duty cycle range is 49% 25262306a36Sopenharmony_ci * to 51%. Apply at least /2 prescaler otherwise. 25362306a36Sopenharmony_ci */ 25462306a36Sopenharmony_ci if (div == 1 && (duty < 49 || duty > 51)) 25562306a36Sopenharmony_ci continue; 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci if ((rate / div) <= priv->max_clk_rate) 25862306a36Sopenharmony_ci goto out; 25962306a36Sopenharmony_ci } 26062306a36Sopenharmony_ci } 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci /* Synchronous clock modes (e.g. ckmode is 1, 2 or 3) */ 26362306a36Sopenharmony_ci rate = clk_get_rate(priv->bclk); 26462306a36Sopenharmony_ci if (!rate) { 26562306a36Sopenharmony_ci dev_err(&pdev->dev, "Invalid bus clock rate: 0\n"); 26662306a36Sopenharmony_ci return -EINVAL; 26762306a36Sopenharmony_ci } 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci duty = clk_get_scaled_duty_cycle(priv->bclk, 100); 27062306a36Sopenharmony_ci if (duty < 0) 27162306a36Sopenharmony_ci dev_warn(&pdev->dev, "bus clock duty: %d\n", duty); 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(stm32h7_adc_ckmodes_spec); i++) { 27462306a36Sopenharmony_ci ckmode = stm32h7_adc_ckmodes_spec[i].ckmode; 27562306a36Sopenharmony_ci presc = stm32h7_adc_ckmodes_spec[i].presc; 27662306a36Sopenharmony_ci div = stm32h7_adc_ckmodes_spec[i].div; 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci if (!ckmode) 27962306a36Sopenharmony_ci continue; 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci if (div == 1 && (duty < 49 || duty > 51)) 28262306a36Sopenharmony_ci continue; 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci if ((rate / div) <= priv->max_clk_rate) 28562306a36Sopenharmony_ci goto out; 28662306a36Sopenharmony_ci } 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci dev_err(&pdev->dev, "adc clk selection failed\n"); 28962306a36Sopenharmony_ci return -EINVAL; 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ciout: 29262306a36Sopenharmony_ci /* rate used later by each ADC instance to control BOOST mode */ 29362306a36Sopenharmony_ci priv->common.rate = rate / div; 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci /* Set common clock mode and prescaler */ 29662306a36Sopenharmony_ci val = readl_relaxed(priv->common.base + STM32H7_ADC_CCR); 29762306a36Sopenharmony_ci val &= ~(STM32H7_CKMODE_MASK | STM32H7_PRESC_MASK); 29862306a36Sopenharmony_ci val |= ckmode << STM32H7_CKMODE_SHIFT; 29962306a36Sopenharmony_ci val |= presc << STM32H7_PRESC_SHIFT; 30062306a36Sopenharmony_ci writel_relaxed(val, priv->common.base + STM32H7_ADC_CCR); 30162306a36Sopenharmony_ci 30262306a36Sopenharmony_ci dev_dbg(&pdev->dev, "Using %s clock/%d source at %ld kHz\n", 30362306a36Sopenharmony_ci ckmode ? "bus" : "adc", div, priv->common.rate / 1000); 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci return 0; 30662306a36Sopenharmony_ci} 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci/* STM32F4 common registers definitions */ 30962306a36Sopenharmony_cistatic const struct stm32_adc_common_regs stm32f4_adc_common_regs = { 31062306a36Sopenharmony_ci .csr = STM32F4_ADC_CSR, 31162306a36Sopenharmony_ci .ccr = STM32F4_ADC_CCR, 31262306a36Sopenharmony_ci .eoc_msk = { STM32F4_EOC1, STM32F4_EOC2, STM32F4_EOC3 }, 31362306a36Sopenharmony_ci .ovr_msk = { STM32F4_OVR1, STM32F4_OVR2, STM32F4_OVR3 }, 31462306a36Sopenharmony_ci .ier = STM32F4_ADC_CR1, 31562306a36Sopenharmony_ci .eocie_msk = STM32F4_EOCIE, 31662306a36Sopenharmony_ci}; 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ci/* STM32H7 common registers definitions */ 31962306a36Sopenharmony_cistatic const struct stm32_adc_common_regs stm32h7_adc_common_regs = { 32062306a36Sopenharmony_ci .csr = STM32H7_ADC_CSR, 32162306a36Sopenharmony_ci .ccr = STM32H7_ADC_CCR, 32262306a36Sopenharmony_ci .eoc_msk = { STM32H7_EOC_MST, STM32H7_EOC_SLV }, 32362306a36Sopenharmony_ci .ovr_msk = { STM32H7_OVR_MST, STM32H7_OVR_SLV }, 32462306a36Sopenharmony_ci .ier = STM32H7_ADC_IER, 32562306a36Sopenharmony_ci .eocie_msk = STM32H7_EOCIE, 32662306a36Sopenharmony_ci}; 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_ci/* STM32MP13 common registers definitions */ 32962306a36Sopenharmony_cistatic const struct stm32_adc_common_regs stm32mp13_adc_common_regs = { 33062306a36Sopenharmony_ci .csr = STM32H7_ADC_CSR, 33162306a36Sopenharmony_ci .ccr = STM32H7_ADC_CCR, 33262306a36Sopenharmony_ci .eoc_msk = { STM32H7_EOC_MST }, 33362306a36Sopenharmony_ci .ovr_msk = { STM32H7_OVR_MST }, 33462306a36Sopenharmony_ci .ier = STM32H7_ADC_IER, 33562306a36Sopenharmony_ci .eocie_msk = STM32H7_EOCIE, 33662306a36Sopenharmony_ci}; 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_cistatic const unsigned int stm32_adc_offset[STM32_ADC_MAX_ADCS] = { 33962306a36Sopenharmony_ci 0, STM32_ADC_OFFSET, STM32_ADC_OFFSET * 2, 34062306a36Sopenharmony_ci}; 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_cistatic unsigned int stm32_adc_eoc_enabled(struct stm32_adc_priv *priv, 34362306a36Sopenharmony_ci unsigned int adc) 34462306a36Sopenharmony_ci{ 34562306a36Sopenharmony_ci u32 ier, offset = stm32_adc_offset[adc]; 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci ier = readl_relaxed(priv->common.base + offset + priv->cfg->regs->ier); 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci return ier & priv->cfg->regs->eocie_msk; 35062306a36Sopenharmony_ci} 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci/* ADC common interrupt for all instances */ 35362306a36Sopenharmony_cistatic void stm32_adc_irq_handler(struct irq_desc *desc) 35462306a36Sopenharmony_ci{ 35562306a36Sopenharmony_ci struct stm32_adc_priv *priv = irq_desc_get_handler_data(desc); 35662306a36Sopenharmony_ci struct irq_chip *chip = irq_desc_get_chip(desc); 35762306a36Sopenharmony_ci int i; 35862306a36Sopenharmony_ci u32 status; 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_ci chained_irq_enter(chip, desc); 36162306a36Sopenharmony_ci status = readl_relaxed(priv->common.base + priv->cfg->regs->csr); 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_ci /* 36462306a36Sopenharmony_ci * End of conversion may be handled by using IRQ or DMA. There may be a 36562306a36Sopenharmony_ci * race here when two conversions complete at the same time on several 36662306a36Sopenharmony_ci * ADCs. EOC may be read 'set' for several ADCs, with: 36762306a36Sopenharmony_ci * - an ADC configured to use DMA (EOC triggers the DMA request, and 36862306a36Sopenharmony_ci * is then automatically cleared by DR read in hardware) 36962306a36Sopenharmony_ci * - an ADC configured to use IRQs (EOCIE bit is set. The handler must 37062306a36Sopenharmony_ci * be called in this case) 37162306a36Sopenharmony_ci * So both EOC status bit in CSR and EOCIE control bit must be checked 37262306a36Sopenharmony_ci * before invoking the interrupt handler (e.g. call ISR only for 37362306a36Sopenharmony_ci * IRQ-enabled ADCs). 37462306a36Sopenharmony_ci */ 37562306a36Sopenharmony_ci for (i = 0; i < priv->nb_adc_max; i++) { 37662306a36Sopenharmony_ci if ((status & priv->cfg->regs->eoc_msk[i] && 37762306a36Sopenharmony_ci stm32_adc_eoc_enabled(priv, i)) || 37862306a36Sopenharmony_ci (status & priv->cfg->regs->ovr_msk[i])) 37962306a36Sopenharmony_ci generic_handle_domain_irq(priv->domain, i); 38062306a36Sopenharmony_ci } 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ci chained_irq_exit(chip, desc); 38362306a36Sopenharmony_ci}; 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_cistatic int stm32_adc_domain_map(struct irq_domain *d, unsigned int irq, 38662306a36Sopenharmony_ci irq_hw_number_t hwirq) 38762306a36Sopenharmony_ci{ 38862306a36Sopenharmony_ci irq_set_chip_data(irq, d->host_data); 38962306a36Sopenharmony_ci irq_set_chip_and_handler(irq, &dummy_irq_chip, handle_level_irq); 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_ci return 0; 39262306a36Sopenharmony_ci} 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_cistatic void stm32_adc_domain_unmap(struct irq_domain *d, unsigned int irq) 39562306a36Sopenharmony_ci{ 39662306a36Sopenharmony_ci irq_set_chip_and_handler(irq, NULL, NULL); 39762306a36Sopenharmony_ci irq_set_chip_data(irq, NULL); 39862306a36Sopenharmony_ci} 39962306a36Sopenharmony_ci 40062306a36Sopenharmony_cistatic const struct irq_domain_ops stm32_adc_domain_ops = { 40162306a36Sopenharmony_ci .map = stm32_adc_domain_map, 40262306a36Sopenharmony_ci .unmap = stm32_adc_domain_unmap, 40362306a36Sopenharmony_ci .xlate = irq_domain_xlate_onecell, 40462306a36Sopenharmony_ci}; 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_cistatic int stm32_adc_irq_probe(struct platform_device *pdev, 40762306a36Sopenharmony_ci struct stm32_adc_priv *priv) 40862306a36Sopenharmony_ci{ 40962306a36Sopenharmony_ci struct device_node *np = pdev->dev.of_node; 41062306a36Sopenharmony_ci unsigned int i; 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_ci /* 41362306a36Sopenharmony_ci * Interrupt(s) must be provided, depending on the compatible: 41462306a36Sopenharmony_ci * - stm32f4/h7 shares a common interrupt line. 41562306a36Sopenharmony_ci * - stm32mp1, has one line per ADC 41662306a36Sopenharmony_ci */ 41762306a36Sopenharmony_ci for (i = 0; i < priv->cfg->num_irqs; i++) { 41862306a36Sopenharmony_ci priv->irq[i] = platform_get_irq(pdev, i); 41962306a36Sopenharmony_ci if (priv->irq[i] < 0) 42062306a36Sopenharmony_ci return priv->irq[i]; 42162306a36Sopenharmony_ci } 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_ci priv->domain = irq_domain_add_simple(np, STM32_ADC_MAX_ADCS, 0, 42462306a36Sopenharmony_ci &stm32_adc_domain_ops, 42562306a36Sopenharmony_ci priv); 42662306a36Sopenharmony_ci if (!priv->domain) { 42762306a36Sopenharmony_ci dev_err(&pdev->dev, "Failed to add irq domain\n"); 42862306a36Sopenharmony_ci return -ENOMEM; 42962306a36Sopenharmony_ci } 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_ci for (i = 0; i < priv->cfg->num_irqs; i++) { 43262306a36Sopenharmony_ci irq_set_chained_handler(priv->irq[i], stm32_adc_irq_handler); 43362306a36Sopenharmony_ci irq_set_handler_data(priv->irq[i], priv); 43462306a36Sopenharmony_ci } 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_ci return 0; 43762306a36Sopenharmony_ci} 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_cistatic void stm32_adc_irq_remove(struct platform_device *pdev, 44062306a36Sopenharmony_ci struct stm32_adc_priv *priv) 44162306a36Sopenharmony_ci{ 44262306a36Sopenharmony_ci int hwirq; 44362306a36Sopenharmony_ci unsigned int i; 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_ci for (hwirq = 0; hwirq < priv->nb_adc_max; hwirq++) 44662306a36Sopenharmony_ci irq_dispose_mapping(irq_find_mapping(priv->domain, hwirq)); 44762306a36Sopenharmony_ci irq_domain_remove(priv->domain); 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ci for (i = 0; i < priv->cfg->num_irqs; i++) 45062306a36Sopenharmony_ci irq_set_chained_handler(priv->irq[i], NULL); 45162306a36Sopenharmony_ci} 45262306a36Sopenharmony_ci 45362306a36Sopenharmony_cistatic int stm32_adc_core_switches_supply_en(struct stm32_adc_priv *priv, 45462306a36Sopenharmony_ci struct device *dev) 45562306a36Sopenharmony_ci{ 45662306a36Sopenharmony_ci int ret; 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_ci /* 45962306a36Sopenharmony_ci * On STM32H7 and STM32MP1, the ADC inputs are multiplexed with analog 46062306a36Sopenharmony_ci * switches (via PCSEL) which have reduced performances when their 46162306a36Sopenharmony_ci * supply is below 2.7V (vdda by default): 46262306a36Sopenharmony_ci * - Voltage booster can be used, to get full ADC performances 46362306a36Sopenharmony_ci * (increases power consumption). 46462306a36Sopenharmony_ci * - Vdd can be used to supply them, if above 2.7V (STM32MP1 only). 46562306a36Sopenharmony_ci * 46662306a36Sopenharmony_ci * Recommended settings for ANASWVDD and EN_BOOSTER: 46762306a36Sopenharmony_ci * - vdda < 2.7V but vdd > 2.7V: ANASWVDD = 1, EN_BOOSTER = 0 (stm32mp1) 46862306a36Sopenharmony_ci * - vdda < 2.7V and vdd < 2.7V: ANASWVDD = 0, EN_BOOSTER = 1 46962306a36Sopenharmony_ci * - vdda >= 2.7V: ANASWVDD = 0, EN_BOOSTER = 0 (default) 47062306a36Sopenharmony_ci */ 47162306a36Sopenharmony_ci if (priv->vdda_uv < 2700000) { 47262306a36Sopenharmony_ci if (priv->syscfg && priv->vdd_uv > 2700000) { 47362306a36Sopenharmony_ci ret = regulator_enable(priv->vdd); 47462306a36Sopenharmony_ci if (ret < 0) { 47562306a36Sopenharmony_ci dev_err(dev, "vdd enable failed %d\n", ret); 47662306a36Sopenharmony_ci return ret; 47762306a36Sopenharmony_ci } 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_ci ret = regmap_write(priv->syscfg, 48062306a36Sopenharmony_ci STM32MP1_SYSCFG_PMCSETR, 48162306a36Sopenharmony_ci STM32MP1_SYSCFG_ANASWVDD_MASK); 48262306a36Sopenharmony_ci if (ret < 0) { 48362306a36Sopenharmony_ci regulator_disable(priv->vdd); 48462306a36Sopenharmony_ci dev_err(dev, "vdd select failed, %d\n", ret); 48562306a36Sopenharmony_ci return ret; 48662306a36Sopenharmony_ci } 48762306a36Sopenharmony_ci dev_dbg(dev, "analog switches supplied by vdd\n"); 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_ci return 0; 49062306a36Sopenharmony_ci } 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_ci if (priv->booster) { 49362306a36Sopenharmony_ci /* 49462306a36Sopenharmony_ci * This is optional, as this is a trade-off between 49562306a36Sopenharmony_ci * analog performance and power consumption. 49662306a36Sopenharmony_ci */ 49762306a36Sopenharmony_ci ret = regulator_enable(priv->booster); 49862306a36Sopenharmony_ci if (ret < 0) { 49962306a36Sopenharmony_ci dev_err(dev, "booster enable failed %d\n", ret); 50062306a36Sopenharmony_ci return ret; 50162306a36Sopenharmony_ci } 50262306a36Sopenharmony_ci dev_dbg(dev, "analog switches supplied by booster\n"); 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci return 0; 50562306a36Sopenharmony_ci } 50662306a36Sopenharmony_ci } 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_ci /* Fallback using vdda (default), nothing to do */ 50962306a36Sopenharmony_ci dev_dbg(dev, "analog switches supplied by vdda (%d uV)\n", 51062306a36Sopenharmony_ci priv->vdda_uv); 51162306a36Sopenharmony_ci 51262306a36Sopenharmony_ci return 0; 51362306a36Sopenharmony_ci} 51462306a36Sopenharmony_ci 51562306a36Sopenharmony_cistatic void stm32_adc_core_switches_supply_dis(struct stm32_adc_priv *priv) 51662306a36Sopenharmony_ci{ 51762306a36Sopenharmony_ci if (priv->vdda_uv < 2700000) { 51862306a36Sopenharmony_ci if (priv->syscfg && priv->vdd_uv > 2700000) { 51962306a36Sopenharmony_ci regmap_write(priv->syscfg, STM32MP1_SYSCFG_PMCCLRR, 52062306a36Sopenharmony_ci STM32MP1_SYSCFG_ANASWVDD_MASK); 52162306a36Sopenharmony_ci regulator_disable(priv->vdd); 52262306a36Sopenharmony_ci return; 52362306a36Sopenharmony_ci } 52462306a36Sopenharmony_ci if (priv->booster) 52562306a36Sopenharmony_ci regulator_disable(priv->booster); 52662306a36Sopenharmony_ci } 52762306a36Sopenharmony_ci} 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_cistatic int stm32_adc_core_hw_start(struct device *dev) 53062306a36Sopenharmony_ci{ 53162306a36Sopenharmony_ci struct stm32_adc_common *common = dev_get_drvdata(dev); 53262306a36Sopenharmony_ci struct stm32_adc_priv *priv = to_stm32_adc_priv(common); 53362306a36Sopenharmony_ci int ret; 53462306a36Sopenharmony_ci 53562306a36Sopenharmony_ci ret = regulator_enable(priv->vdda); 53662306a36Sopenharmony_ci if (ret < 0) { 53762306a36Sopenharmony_ci dev_err(dev, "vdda enable failed %d\n", ret); 53862306a36Sopenharmony_ci return ret; 53962306a36Sopenharmony_ci } 54062306a36Sopenharmony_ci 54162306a36Sopenharmony_ci ret = regulator_get_voltage(priv->vdda); 54262306a36Sopenharmony_ci if (ret < 0) { 54362306a36Sopenharmony_ci dev_err(dev, "vdda get voltage failed, %d\n", ret); 54462306a36Sopenharmony_ci goto err_vdda_disable; 54562306a36Sopenharmony_ci } 54662306a36Sopenharmony_ci priv->vdda_uv = ret; 54762306a36Sopenharmony_ci 54862306a36Sopenharmony_ci ret = stm32_adc_core_switches_supply_en(priv, dev); 54962306a36Sopenharmony_ci if (ret < 0) 55062306a36Sopenharmony_ci goto err_vdda_disable; 55162306a36Sopenharmony_ci 55262306a36Sopenharmony_ci ret = regulator_enable(priv->vref); 55362306a36Sopenharmony_ci if (ret < 0) { 55462306a36Sopenharmony_ci dev_err(dev, "vref enable failed\n"); 55562306a36Sopenharmony_ci goto err_switches_dis; 55662306a36Sopenharmony_ci } 55762306a36Sopenharmony_ci 55862306a36Sopenharmony_ci ret = clk_prepare_enable(priv->bclk); 55962306a36Sopenharmony_ci if (ret < 0) { 56062306a36Sopenharmony_ci dev_err(dev, "bus clk enable failed\n"); 56162306a36Sopenharmony_ci goto err_regulator_disable; 56262306a36Sopenharmony_ci } 56362306a36Sopenharmony_ci 56462306a36Sopenharmony_ci ret = clk_prepare_enable(priv->aclk); 56562306a36Sopenharmony_ci if (ret < 0) { 56662306a36Sopenharmony_ci dev_err(dev, "adc clk enable failed\n"); 56762306a36Sopenharmony_ci goto err_bclk_disable; 56862306a36Sopenharmony_ci } 56962306a36Sopenharmony_ci 57062306a36Sopenharmony_ci writel_relaxed(priv->ccr_bak, priv->common.base + priv->cfg->regs->ccr); 57162306a36Sopenharmony_ci 57262306a36Sopenharmony_ci return 0; 57362306a36Sopenharmony_ci 57462306a36Sopenharmony_cierr_bclk_disable: 57562306a36Sopenharmony_ci clk_disable_unprepare(priv->bclk); 57662306a36Sopenharmony_cierr_regulator_disable: 57762306a36Sopenharmony_ci regulator_disable(priv->vref); 57862306a36Sopenharmony_cierr_switches_dis: 57962306a36Sopenharmony_ci stm32_adc_core_switches_supply_dis(priv); 58062306a36Sopenharmony_cierr_vdda_disable: 58162306a36Sopenharmony_ci regulator_disable(priv->vdda); 58262306a36Sopenharmony_ci 58362306a36Sopenharmony_ci return ret; 58462306a36Sopenharmony_ci} 58562306a36Sopenharmony_ci 58662306a36Sopenharmony_cistatic void stm32_adc_core_hw_stop(struct device *dev) 58762306a36Sopenharmony_ci{ 58862306a36Sopenharmony_ci struct stm32_adc_common *common = dev_get_drvdata(dev); 58962306a36Sopenharmony_ci struct stm32_adc_priv *priv = to_stm32_adc_priv(common); 59062306a36Sopenharmony_ci 59162306a36Sopenharmony_ci /* Backup CCR that may be lost (depends on power state to achieve) */ 59262306a36Sopenharmony_ci priv->ccr_bak = readl_relaxed(priv->common.base + priv->cfg->regs->ccr); 59362306a36Sopenharmony_ci clk_disable_unprepare(priv->aclk); 59462306a36Sopenharmony_ci clk_disable_unprepare(priv->bclk); 59562306a36Sopenharmony_ci regulator_disable(priv->vref); 59662306a36Sopenharmony_ci stm32_adc_core_switches_supply_dis(priv); 59762306a36Sopenharmony_ci regulator_disable(priv->vdda); 59862306a36Sopenharmony_ci} 59962306a36Sopenharmony_ci 60062306a36Sopenharmony_cistatic int stm32_adc_core_switches_probe(struct device *dev, 60162306a36Sopenharmony_ci struct stm32_adc_priv *priv) 60262306a36Sopenharmony_ci{ 60362306a36Sopenharmony_ci struct device_node *np = dev->of_node; 60462306a36Sopenharmony_ci int ret; 60562306a36Sopenharmony_ci 60662306a36Sopenharmony_ci /* Analog switches supply can be controlled by syscfg (optional) */ 60762306a36Sopenharmony_ci priv->syscfg = syscon_regmap_lookup_by_phandle(np, "st,syscfg"); 60862306a36Sopenharmony_ci if (IS_ERR(priv->syscfg)) { 60962306a36Sopenharmony_ci ret = PTR_ERR(priv->syscfg); 61062306a36Sopenharmony_ci if (ret != -ENODEV) 61162306a36Sopenharmony_ci return dev_err_probe(dev, ret, "Can't probe syscfg\n"); 61262306a36Sopenharmony_ci 61362306a36Sopenharmony_ci priv->syscfg = NULL; 61462306a36Sopenharmony_ci } 61562306a36Sopenharmony_ci 61662306a36Sopenharmony_ci /* Booster can be used to supply analog switches (optional) */ 61762306a36Sopenharmony_ci if (priv->cfg->has_syscfg & HAS_VBOOSTER && 61862306a36Sopenharmony_ci of_property_read_bool(np, "booster-supply")) { 61962306a36Sopenharmony_ci priv->booster = devm_regulator_get_optional(dev, "booster"); 62062306a36Sopenharmony_ci if (IS_ERR(priv->booster)) { 62162306a36Sopenharmony_ci ret = PTR_ERR(priv->booster); 62262306a36Sopenharmony_ci if (ret != -ENODEV) 62362306a36Sopenharmony_ci return dev_err_probe(dev, ret, "can't get booster\n"); 62462306a36Sopenharmony_ci 62562306a36Sopenharmony_ci priv->booster = NULL; 62662306a36Sopenharmony_ci } 62762306a36Sopenharmony_ci } 62862306a36Sopenharmony_ci 62962306a36Sopenharmony_ci /* Vdd can be used to supply analog switches (optional) */ 63062306a36Sopenharmony_ci if (priv->cfg->has_syscfg & HAS_ANASWVDD && 63162306a36Sopenharmony_ci of_property_read_bool(np, "vdd-supply")) { 63262306a36Sopenharmony_ci priv->vdd = devm_regulator_get_optional(dev, "vdd"); 63362306a36Sopenharmony_ci if (IS_ERR(priv->vdd)) { 63462306a36Sopenharmony_ci ret = PTR_ERR(priv->vdd); 63562306a36Sopenharmony_ci if (ret != -ENODEV) 63662306a36Sopenharmony_ci return dev_err_probe(dev, ret, "can't get vdd\n"); 63762306a36Sopenharmony_ci 63862306a36Sopenharmony_ci priv->vdd = NULL; 63962306a36Sopenharmony_ci } 64062306a36Sopenharmony_ci } 64162306a36Sopenharmony_ci 64262306a36Sopenharmony_ci if (priv->vdd) { 64362306a36Sopenharmony_ci ret = regulator_enable(priv->vdd); 64462306a36Sopenharmony_ci if (ret < 0) { 64562306a36Sopenharmony_ci dev_err(dev, "vdd enable failed %d\n", ret); 64662306a36Sopenharmony_ci return ret; 64762306a36Sopenharmony_ci } 64862306a36Sopenharmony_ci 64962306a36Sopenharmony_ci ret = regulator_get_voltage(priv->vdd); 65062306a36Sopenharmony_ci if (ret < 0) { 65162306a36Sopenharmony_ci dev_err(dev, "vdd get voltage failed %d\n", ret); 65262306a36Sopenharmony_ci regulator_disable(priv->vdd); 65362306a36Sopenharmony_ci return ret; 65462306a36Sopenharmony_ci } 65562306a36Sopenharmony_ci priv->vdd_uv = ret; 65662306a36Sopenharmony_ci 65762306a36Sopenharmony_ci regulator_disable(priv->vdd); 65862306a36Sopenharmony_ci } 65962306a36Sopenharmony_ci 66062306a36Sopenharmony_ci return 0; 66162306a36Sopenharmony_ci} 66262306a36Sopenharmony_ci 66362306a36Sopenharmony_cistatic int stm32_adc_probe_identification(struct platform_device *pdev, 66462306a36Sopenharmony_ci struct stm32_adc_priv *priv) 66562306a36Sopenharmony_ci{ 66662306a36Sopenharmony_ci struct device_node *np = pdev->dev.of_node; 66762306a36Sopenharmony_ci struct device_node *child; 66862306a36Sopenharmony_ci const char *compat; 66962306a36Sopenharmony_ci int ret, count = 0; 67062306a36Sopenharmony_ci u32 id, val; 67162306a36Sopenharmony_ci 67262306a36Sopenharmony_ci if (!priv->cfg->ipid) 67362306a36Sopenharmony_ci return 0; 67462306a36Sopenharmony_ci 67562306a36Sopenharmony_ci id = FIELD_GET(STM32MP1_IPIDR_MASK, 67662306a36Sopenharmony_ci readl_relaxed(priv->common.base + STM32MP1_ADC_IPDR)); 67762306a36Sopenharmony_ci if (id != priv->cfg->ipid) { 67862306a36Sopenharmony_ci dev_err(&pdev->dev, "Unexpected IP version: 0x%x", id); 67962306a36Sopenharmony_ci return -EINVAL; 68062306a36Sopenharmony_ci } 68162306a36Sopenharmony_ci 68262306a36Sopenharmony_ci for_each_child_of_node(np, child) { 68362306a36Sopenharmony_ci ret = of_property_read_string(child, "compatible", &compat); 68462306a36Sopenharmony_ci if (ret) 68562306a36Sopenharmony_ci continue; 68662306a36Sopenharmony_ci /* Count child nodes with stm32 adc compatible */ 68762306a36Sopenharmony_ci if (strstr(compat, "st,stm32") && strstr(compat, "adc")) 68862306a36Sopenharmony_ci count++; 68962306a36Sopenharmony_ci } 69062306a36Sopenharmony_ci 69162306a36Sopenharmony_ci val = readl_relaxed(priv->common.base + STM32MP1_ADC_HWCFGR0); 69262306a36Sopenharmony_ci priv->nb_adc_max = FIELD_GET(STM32MP1_ADCNUM_MASK, val); 69362306a36Sopenharmony_ci if (count > priv->nb_adc_max) { 69462306a36Sopenharmony_ci dev_err(&pdev->dev, "Unexpected child number: %d", count); 69562306a36Sopenharmony_ci return -EINVAL; 69662306a36Sopenharmony_ci } 69762306a36Sopenharmony_ci 69862306a36Sopenharmony_ci val = readl_relaxed(priv->common.base + STM32MP1_ADC_VERR); 69962306a36Sopenharmony_ci dev_dbg(&pdev->dev, "ADC version: %lu.%lu\n", 70062306a36Sopenharmony_ci FIELD_GET(STM32MP1_MAJREV_MASK, val), 70162306a36Sopenharmony_ci FIELD_GET(STM32MP1_MINREV_MASK, val)); 70262306a36Sopenharmony_ci 70362306a36Sopenharmony_ci return 0; 70462306a36Sopenharmony_ci} 70562306a36Sopenharmony_ci 70662306a36Sopenharmony_cistatic int stm32_adc_probe(struct platform_device *pdev) 70762306a36Sopenharmony_ci{ 70862306a36Sopenharmony_ci struct stm32_adc_priv *priv; 70962306a36Sopenharmony_ci struct device *dev = &pdev->dev; 71062306a36Sopenharmony_ci struct device_node *np = pdev->dev.of_node; 71162306a36Sopenharmony_ci const struct of_device_id *of_id; 71262306a36Sopenharmony_ci 71362306a36Sopenharmony_ci struct resource *res; 71462306a36Sopenharmony_ci u32 max_rate; 71562306a36Sopenharmony_ci int ret; 71662306a36Sopenharmony_ci 71762306a36Sopenharmony_ci if (!pdev->dev.of_node) 71862306a36Sopenharmony_ci return -ENODEV; 71962306a36Sopenharmony_ci 72062306a36Sopenharmony_ci priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 72162306a36Sopenharmony_ci if (!priv) 72262306a36Sopenharmony_ci return -ENOMEM; 72362306a36Sopenharmony_ci platform_set_drvdata(pdev, &priv->common); 72462306a36Sopenharmony_ci 72562306a36Sopenharmony_ci of_id = of_match_device(dev->driver->of_match_table, dev); 72662306a36Sopenharmony_ci if (!of_id) 72762306a36Sopenharmony_ci return -ENODEV; 72862306a36Sopenharmony_ci 72962306a36Sopenharmony_ci priv->cfg = (const struct stm32_adc_priv_cfg *)of_id->data; 73062306a36Sopenharmony_ci priv->nb_adc_max = priv->cfg->num_adcs; 73162306a36Sopenharmony_ci spin_lock_init(&priv->common.lock); 73262306a36Sopenharmony_ci 73362306a36Sopenharmony_ci priv->common.base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); 73462306a36Sopenharmony_ci if (IS_ERR(priv->common.base)) 73562306a36Sopenharmony_ci return PTR_ERR(priv->common.base); 73662306a36Sopenharmony_ci priv->common.phys_base = res->start; 73762306a36Sopenharmony_ci 73862306a36Sopenharmony_ci priv->vdda = devm_regulator_get(&pdev->dev, "vdda"); 73962306a36Sopenharmony_ci if (IS_ERR(priv->vdda)) 74062306a36Sopenharmony_ci return dev_err_probe(&pdev->dev, PTR_ERR(priv->vdda), 74162306a36Sopenharmony_ci "vdda get failed\n"); 74262306a36Sopenharmony_ci 74362306a36Sopenharmony_ci priv->vref = devm_regulator_get(&pdev->dev, "vref"); 74462306a36Sopenharmony_ci if (IS_ERR(priv->vref)) 74562306a36Sopenharmony_ci return dev_err_probe(&pdev->dev, PTR_ERR(priv->vref), 74662306a36Sopenharmony_ci "vref get failed\n"); 74762306a36Sopenharmony_ci 74862306a36Sopenharmony_ci priv->aclk = devm_clk_get_optional(&pdev->dev, "adc"); 74962306a36Sopenharmony_ci if (IS_ERR(priv->aclk)) 75062306a36Sopenharmony_ci return dev_err_probe(&pdev->dev, PTR_ERR(priv->aclk), 75162306a36Sopenharmony_ci "Can't get 'adc' clock\n"); 75262306a36Sopenharmony_ci 75362306a36Sopenharmony_ci priv->bclk = devm_clk_get_optional(&pdev->dev, "bus"); 75462306a36Sopenharmony_ci if (IS_ERR(priv->bclk)) 75562306a36Sopenharmony_ci return dev_err_probe(&pdev->dev, PTR_ERR(priv->bclk), 75662306a36Sopenharmony_ci "Can't get 'bus' clock\n"); 75762306a36Sopenharmony_ci 75862306a36Sopenharmony_ci ret = stm32_adc_core_switches_probe(dev, priv); 75962306a36Sopenharmony_ci if (ret) 76062306a36Sopenharmony_ci return ret; 76162306a36Sopenharmony_ci 76262306a36Sopenharmony_ci pm_runtime_get_noresume(dev); 76362306a36Sopenharmony_ci pm_runtime_set_active(dev); 76462306a36Sopenharmony_ci pm_runtime_set_autosuspend_delay(dev, STM32_ADC_CORE_SLEEP_DELAY_MS); 76562306a36Sopenharmony_ci pm_runtime_use_autosuspend(dev); 76662306a36Sopenharmony_ci pm_runtime_enable(dev); 76762306a36Sopenharmony_ci 76862306a36Sopenharmony_ci ret = stm32_adc_core_hw_start(dev); 76962306a36Sopenharmony_ci if (ret) 77062306a36Sopenharmony_ci goto err_pm_stop; 77162306a36Sopenharmony_ci 77262306a36Sopenharmony_ci ret = stm32_adc_probe_identification(pdev, priv); 77362306a36Sopenharmony_ci if (ret < 0) 77462306a36Sopenharmony_ci goto err_hw_stop; 77562306a36Sopenharmony_ci 77662306a36Sopenharmony_ci ret = regulator_get_voltage(priv->vref); 77762306a36Sopenharmony_ci if (ret < 0) { 77862306a36Sopenharmony_ci dev_err(&pdev->dev, "vref get voltage failed, %d\n", ret); 77962306a36Sopenharmony_ci goto err_hw_stop; 78062306a36Sopenharmony_ci } 78162306a36Sopenharmony_ci priv->common.vref_mv = ret / 1000; 78262306a36Sopenharmony_ci dev_dbg(&pdev->dev, "vref+=%dmV\n", priv->common.vref_mv); 78362306a36Sopenharmony_ci 78462306a36Sopenharmony_ci ret = of_property_read_u32(pdev->dev.of_node, "st,max-clk-rate-hz", 78562306a36Sopenharmony_ci &max_rate); 78662306a36Sopenharmony_ci if (!ret) 78762306a36Sopenharmony_ci priv->max_clk_rate = min(max_rate, priv->cfg->max_clk_rate_hz); 78862306a36Sopenharmony_ci else 78962306a36Sopenharmony_ci priv->max_clk_rate = priv->cfg->max_clk_rate_hz; 79062306a36Sopenharmony_ci 79162306a36Sopenharmony_ci ret = priv->cfg->clk_sel(pdev, priv); 79262306a36Sopenharmony_ci if (ret < 0) 79362306a36Sopenharmony_ci goto err_hw_stop; 79462306a36Sopenharmony_ci 79562306a36Sopenharmony_ci ret = stm32_adc_irq_probe(pdev, priv); 79662306a36Sopenharmony_ci if (ret < 0) 79762306a36Sopenharmony_ci goto err_hw_stop; 79862306a36Sopenharmony_ci 79962306a36Sopenharmony_ci ret = of_platform_populate(np, NULL, NULL, &pdev->dev); 80062306a36Sopenharmony_ci if (ret < 0) { 80162306a36Sopenharmony_ci dev_err(&pdev->dev, "failed to populate DT children\n"); 80262306a36Sopenharmony_ci goto err_irq_remove; 80362306a36Sopenharmony_ci } 80462306a36Sopenharmony_ci 80562306a36Sopenharmony_ci pm_runtime_mark_last_busy(dev); 80662306a36Sopenharmony_ci pm_runtime_put_autosuspend(dev); 80762306a36Sopenharmony_ci 80862306a36Sopenharmony_ci return 0; 80962306a36Sopenharmony_ci 81062306a36Sopenharmony_cierr_irq_remove: 81162306a36Sopenharmony_ci stm32_adc_irq_remove(pdev, priv); 81262306a36Sopenharmony_cierr_hw_stop: 81362306a36Sopenharmony_ci stm32_adc_core_hw_stop(dev); 81462306a36Sopenharmony_cierr_pm_stop: 81562306a36Sopenharmony_ci pm_runtime_disable(dev); 81662306a36Sopenharmony_ci pm_runtime_set_suspended(dev); 81762306a36Sopenharmony_ci pm_runtime_put_noidle(dev); 81862306a36Sopenharmony_ci 81962306a36Sopenharmony_ci return ret; 82062306a36Sopenharmony_ci} 82162306a36Sopenharmony_ci 82262306a36Sopenharmony_cistatic int stm32_adc_remove(struct platform_device *pdev) 82362306a36Sopenharmony_ci{ 82462306a36Sopenharmony_ci struct stm32_adc_common *common = platform_get_drvdata(pdev); 82562306a36Sopenharmony_ci struct stm32_adc_priv *priv = to_stm32_adc_priv(common); 82662306a36Sopenharmony_ci 82762306a36Sopenharmony_ci pm_runtime_get_sync(&pdev->dev); 82862306a36Sopenharmony_ci of_platform_depopulate(&pdev->dev); 82962306a36Sopenharmony_ci stm32_adc_irq_remove(pdev, priv); 83062306a36Sopenharmony_ci stm32_adc_core_hw_stop(&pdev->dev); 83162306a36Sopenharmony_ci pm_runtime_disable(&pdev->dev); 83262306a36Sopenharmony_ci pm_runtime_set_suspended(&pdev->dev); 83362306a36Sopenharmony_ci pm_runtime_put_noidle(&pdev->dev); 83462306a36Sopenharmony_ci 83562306a36Sopenharmony_ci return 0; 83662306a36Sopenharmony_ci} 83762306a36Sopenharmony_ci 83862306a36Sopenharmony_cistatic int stm32_adc_core_runtime_suspend(struct device *dev) 83962306a36Sopenharmony_ci{ 84062306a36Sopenharmony_ci stm32_adc_core_hw_stop(dev); 84162306a36Sopenharmony_ci 84262306a36Sopenharmony_ci return 0; 84362306a36Sopenharmony_ci} 84462306a36Sopenharmony_ci 84562306a36Sopenharmony_cistatic int stm32_adc_core_runtime_resume(struct device *dev) 84662306a36Sopenharmony_ci{ 84762306a36Sopenharmony_ci return stm32_adc_core_hw_start(dev); 84862306a36Sopenharmony_ci} 84962306a36Sopenharmony_ci 85062306a36Sopenharmony_cistatic int stm32_adc_core_runtime_idle(struct device *dev) 85162306a36Sopenharmony_ci{ 85262306a36Sopenharmony_ci pm_runtime_mark_last_busy(dev); 85362306a36Sopenharmony_ci 85462306a36Sopenharmony_ci return 0; 85562306a36Sopenharmony_ci} 85662306a36Sopenharmony_ci 85762306a36Sopenharmony_cistatic DEFINE_RUNTIME_DEV_PM_OPS(stm32_adc_core_pm_ops, 85862306a36Sopenharmony_ci stm32_adc_core_runtime_suspend, 85962306a36Sopenharmony_ci stm32_adc_core_runtime_resume, 86062306a36Sopenharmony_ci stm32_adc_core_runtime_idle); 86162306a36Sopenharmony_ci 86262306a36Sopenharmony_cistatic const struct stm32_adc_priv_cfg stm32f4_adc_priv_cfg = { 86362306a36Sopenharmony_ci .regs = &stm32f4_adc_common_regs, 86462306a36Sopenharmony_ci .clk_sel = stm32f4_adc_clk_sel, 86562306a36Sopenharmony_ci .max_clk_rate_hz = 36000000, 86662306a36Sopenharmony_ci .num_irqs = 1, 86762306a36Sopenharmony_ci .num_adcs = 3, 86862306a36Sopenharmony_ci}; 86962306a36Sopenharmony_ci 87062306a36Sopenharmony_cistatic const struct stm32_adc_priv_cfg stm32h7_adc_priv_cfg = { 87162306a36Sopenharmony_ci .regs = &stm32h7_adc_common_regs, 87262306a36Sopenharmony_ci .clk_sel = stm32h7_adc_clk_sel, 87362306a36Sopenharmony_ci .max_clk_rate_hz = 36000000, 87462306a36Sopenharmony_ci .has_syscfg = HAS_VBOOSTER, 87562306a36Sopenharmony_ci .num_irqs = 1, 87662306a36Sopenharmony_ci .num_adcs = 2, 87762306a36Sopenharmony_ci}; 87862306a36Sopenharmony_ci 87962306a36Sopenharmony_cistatic const struct stm32_adc_priv_cfg stm32mp1_adc_priv_cfg = { 88062306a36Sopenharmony_ci .regs = &stm32h7_adc_common_regs, 88162306a36Sopenharmony_ci .clk_sel = stm32h7_adc_clk_sel, 88262306a36Sopenharmony_ci .max_clk_rate_hz = 36000000, 88362306a36Sopenharmony_ci .has_syscfg = HAS_VBOOSTER | HAS_ANASWVDD, 88462306a36Sopenharmony_ci .ipid = STM32MP15_IPIDR_NUMBER, 88562306a36Sopenharmony_ci .num_irqs = 2, 88662306a36Sopenharmony_ci}; 88762306a36Sopenharmony_ci 88862306a36Sopenharmony_cistatic const struct stm32_adc_priv_cfg stm32mp13_adc_priv_cfg = { 88962306a36Sopenharmony_ci .regs = &stm32mp13_adc_common_regs, 89062306a36Sopenharmony_ci .clk_sel = stm32h7_adc_clk_sel, 89162306a36Sopenharmony_ci .max_clk_rate_hz = 75 * HZ_PER_MHZ, 89262306a36Sopenharmony_ci .ipid = STM32MP13_IPIDR_NUMBER, 89362306a36Sopenharmony_ci .num_irqs = 1, 89462306a36Sopenharmony_ci}; 89562306a36Sopenharmony_ci 89662306a36Sopenharmony_cistatic const struct of_device_id stm32_adc_of_match[] = { 89762306a36Sopenharmony_ci { 89862306a36Sopenharmony_ci .compatible = "st,stm32f4-adc-core", 89962306a36Sopenharmony_ci .data = (void *)&stm32f4_adc_priv_cfg 90062306a36Sopenharmony_ci }, { 90162306a36Sopenharmony_ci .compatible = "st,stm32h7-adc-core", 90262306a36Sopenharmony_ci .data = (void *)&stm32h7_adc_priv_cfg 90362306a36Sopenharmony_ci }, { 90462306a36Sopenharmony_ci .compatible = "st,stm32mp1-adc-core", 90562306a36Sopenharmony_ci .data = (void *)&stm32mp1_adc_priv_cfg 90662306a36Sopenharmony_ci }, { 90762306a36Sopenharmony_ci .compatible = "st,stm32mp13-adc-core", 90862306a36Sopenharmony_ci .data = (void *)&stm32mp13_adc_priv_cfg 90962306a36Sopenharmony_ci }, { 91062306a36Sopenharmony_ci }, 91162306a36Sopenharmony_ci}; 91262306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, stm32_adc_of_match); 91362306a36Sopenharmony_ci 91462306a36Sopenharmony_cistatic struct platform_driver stm32_adc_driver = { 91562306a36Sopenharmony_ci .probe = stm32_adc_probe, 91662306a36Sopenharmony_ci .remove = stm32_adc_remove, 91762306a36Sopenharmony_ci .driver = { 91862306a36Sopenharmony_ci .name = "stm32-adc-core", 91962306a36Sopenharmony_ci .of_match_table = stm32_adc_of_match, 92062306a36Sopenharmony_ci .pm = pm_ptr(&stm32_adc_core_pm_ops), 92162306a36Sopenharmony_ci }, 92262306a36Sopenharmony_ci}; 92362306a36Sopenharmony_cimodule_platform_driver(stm32_adc_driver); 92462306a36Sopenharmony_ci 92562306a36Sopenharmony_ciMODULE_AUTHOR("Fabrice Gasnier <fabrice.gasnier@st.com>"); 92662306a36Sopenharmony_ciMODULE_DESCRIPTION("STMicroelectronics STM32 ADC core driver"); 92762306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 92862306a36Sopenharmony_ciMODULE_ALIAS("platform:stm32-adc-core"); 929