linux/drivers/iio/adc/stm32-adc-core.c

// SPDX-License-Identifier: GPL-2.0
/*
 * This file is part of STM32 ADC driver
 *
 * Copyright (C) 2016, STMicroelectronics - All Rights Reserved
 * Author: Fabrice Gasnier <[email protected]>.
 *
 * Inspired from: fsl-imx25-tsadc
 *
 */

#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/interrupt.h>
#include <linux/irqchip/chained_irq.h>
#include <linux/irqdesc.h>
#include <linux/irqdomain.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/property.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <linux/units.h>

#include "stm32-adc-core.h"

#define STM32_ADC_CORE_SLEEP_DELAY_MS

/* SYSCFG registers */
#define STM32MP1_SYSCFG_PMCSETR
#define STM32MP1_SYSCFG_PMCCLRR

/* SYSCFG bit fields */
#define STM32MP1_SYSCFG_ANASWVDD_MASK

/* SYSCFG capability flags */
#define HAS_VBOOSTER
#define HAS_ANASWVDD

/**
 * struct stm32_adc_common_regs - stm32 common registers
 * @csr:	common status register offset
 * @ccr:	common control register offset
 * @eoc_msk:    array of eoc (end of conversion flag) masks in csr for adc1..n
 * @ovr_msk:    array of ovr (overrun flag) masks in csr for adc1..n
 * @ier:	interrupt enable register offset for each adc
 * @eocie_msk:	end of conversion interrupt enable mask in @ier
 */
struct stm32_adc_common_regs {};

struct stm32_adc_priv;

/**
 * struct stm32_adc_priv_cfg - stm32 core compatible configuration data
 * @regs:	common registers for all instances
 * @clk_sel:	clock selection routine
 * @max_clk_rate_hz: maximum analog clock rate (Hz, from datasheet)
 * @ipid:	adc identification number
 * @has_syscfg: SYSCFG capability flags
 * @num_irqs:	number of interrupt lines
 * @num_adcs:   maximum number of ADC instances in the common registers
 */
struct stm32_adc_priv_cfg {};

/**
 * struct stm32_adc_priv - stm32 ADC core private data
 * @irq:		irq(s) for ADC block
 * @nb_adc_max:		actual maximum number of instance per ADC block
 * @domain:		irq domain reference
 * @aclk:		clock reference for the analog circuitry
 * @bclk:		bus clock common for all ADCs, depends on part used
 * @max_clk_rate:	desired maximum clock rate
 * @booster:		booster supply reference
 * @vdd:		vdd supply reference
 * @vdda:		vdda analog supply reference
 * @vref:		regulator reference
 * @vdd_uv:		vdd supply voltage (microvolts)
 * @vdda_uv:		vdda supply voltage (microvolts)
 * @cfg:		compatible configuration data
 * @common:		common data for all ADC instances
 * @ccr_bak:		backup CCR in low power mode
 * @syscfg:		reference to syscon, system control registers
 */
struct stm32_adc_priv {};

static struct stm32_adc_priv *to_stm32_adc_priv(struct stm32_adc_common *com)
{}

/* STM32F4 ADC internal common clock prescaler division ratios */
static int stm32f4_pclk_div[] =;

/**
 * stm32f4_adc_clk_sel() - Select stm32f4 ADC common clock prescaler
 * @pdev: platform device
 * @priv: stm32 ADC core private data
 * Select clock prescaler used for analog conversions, before using ADC.
 */
static int stm32f4_adc_clk_sel(struct platform_device *pdev,
			       struct stm32_adc_priv *priv)
{}

/**
 * struct stm32h7_adc_ck_spec - specification for stm32h7 adc clock
 * @ckmode: ADC clock mode, Async or sync with prescaler.
 * @presc: prescaler bitfield for async clock mode
 * @div: prescaler division ratio
 */
struct stm32h7_adc_ck_spec {};

static const struct stm32h7_adc_ck_spec stm32h7_adc_ckmodes_spec[] =;

static int stm32h7_adc_clk_sel(struct platform_device *pdev,
			       struct stm32_adc_priv *priv)
{}

/* STM32F4 common registers definitions */
static const struct stm32_adc_common_regs stm32f4_adc_common_regs =;

/* STM32H7 common registers definitions */
static const struct stm32_adc_common_regs stm32h7_adc_common_regs =;

/* STM32MP13 common registers definitions */
static const struct stm32_adc_common_regs stm32mp13_adc_common_regs =;

static const unsigned int stm32_adc_offset[STM32_ADC_MAX_ADCS] =;

static unsigned int stm32_adc_eoc_enabled(struct stm32_adc_priv *priv,
					  unsigned int adc)
{}

/* ADC common interrupt for all instances */
static void stm32_adc_irq_handler(struct irq_desc *desc)
{
	struct stm32_adc_priv *priv = irq_desc_get_handler_data(desc);
	struct irq_chip *chip = irq_desc_get_chip(desc);
	int i;
	u32 status;

	chained_irq_enter(chip, desc);
	status = readl_relaxed(priv->common.base + priv->cfg->regs->csr);

	/*
	 * End of conversion may be handled by using IRQ or DMA. There may be a
	 * race here when two conversions complete at the same time on several
	 * ADCs. EOC may be read 'set' for several ADCs, with:
	 * - an ADC configured to use DMA (EOC triggers the DMA request, and
	 *   is then automatically cleared by DR read in hardware)
	 * - an ADC configured to use IRQs (EOCIE bit is set. The handler must
	 *   be called in this case)
	 * So both EOC status bit in CSR and EOCIE control bit must be checked
	 * before invoking the interrupt handler (e.g. call ISR only for
	 * IRQ-enabled ADCs).
	 */
	for (i = 0; i < priv->nb_adc_max; i++) {
		if ((status & priv->cfg->regs->eoc_msk[i] &&
		     stm32_adc_eoc_enabled(priv, i)) ||
		     (status & priv->cfg->regs->ovr_msk[i]))
			generic_handle_domain_irq(priv->domain, i);
	}

	chained_irq_exit(chip, desc);
};

static int stm32_adc_domain_map(struct irq_domain *d, unsigned int irq,
				irq_hw_number_t hwirq)
{}

static void stm32_adc_domain_unmap(struct irq_domain *d, unsigned int irq)
{}

static const struct irq_domain_ops stm32_adc_domain_ops =;

static int stm32_adc_irq_probe(struct platform_device *pdev,
			       struct stm32_adc_priv *priv)
{}

static void stm32_adc_irq_remove(struct platform_device *pdev,
				 struct stm32_adc_priv *priv)
{}

static int stm32_adc_core_switches_supply_en(struct stm32_adc_priv *priv,
					     struct device *dev)
{}

static void stm32_adc_core_switches_supply_dis(struct stm32_adc_priv *priv)
{}

static int stm32_adc_core_hw_start(struct device *dev)
{}

static void stm32_adc_core_hw_stop(struct device *dev)
{}

static int stm32_adc_core_switches_probe(struct device *dev,
					 struct stm32_adc_priv *priv)
{}

static int stm32_adc_probe_identification(struct platform_device *pdev,
					  struct stm32_adc_priv *priv)
{}

static int stm32_adc_probe(struct platform_device *pdev)
{}

static void stm32_adc_remove(struct platform_device *pdev)
{}

static int stm32_adc_core_runtime_suspend(struct device *dev)
{}

static int stm32_adc_core_runtime_resume(struct device *dev)
{}

static int stm32_adc_core_runtime_idle(struct device *dev)
{}

static DEFINE_RUNTIME_DEV_PM_OPS(stm32_adc_core_pm_ops,
				stm32_adc_core_runtime_suspend,
				stm32_adc_core_runtime_resume,
				stm32_adc_core_runtime_idle);

static const struct stm32_adc_priv_cfg stm32f4_adc_priv_cfg =;

static const struct stm32_adc_priv_cfg stm32h7_adc_priv_cfg =;

static const struct stm32_adc_priv_cfg stm32mp1_adc_priv_cfg =;

static const struct stm32_adc_priv_cfg stm32mp13_adc_priv_cfg =;

static const struct of_device_id stm32_adc_of_match[] =;
MODULE_DEVICE_TABLE(of, stm32_adc_of_match);

static struct platform_driver stm32_adc_driver =;
module_platform_driver();

MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();
MODULE_ALIAS();