drivers/regulator/stm32-vrefbuf.c

Source file repositories/reference/linux-study-clean/drivers/regulator/stm32-vrefbuf.c

File Facts

System
Linux kernel
Corpus path
drivers/regulator/stm32-vrefbuf.c
Extension
.c
Size
7443 bytes
Lines
291
Domain
Driver Families
Bucket
drivers/regulator
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct stm32_vrefbuf {
	void __iomem *base;
	struct clk *clk;
	struct device *dev;
};

static const unsigned int stm32_vrefbuf_voltages[] = {
	/* Matches resp. VRS = 000b, 001b, 010b, 011b */
	2500000, 2048000, 1800000, 1500000,
};

static int stm32_vrefbuf_enable(struct regulator_dev *rdev)
{
	struct stm32_vrefbuf *priv = rdev_get_drvdata(rdev);
	u32 val;
	int ret;

	ret = pm_runtime_resume_and_get(priv->dev);
	if (ret < 0)
		return ret;

	val = readl_relaxed(priv->base + STM32_VREFBUF_CSR);
	val = (val & ~STM32_HIZ) | STM32_ENVR;
	writel_relaxed(val, priv->base + STM32_VREFBUF_CSR);

	/*
	 * Vrefbuf startup time depends on external capacitor: wait here for
	 * VRR to be set. That means output has reached expected value.
	 * ~650us sleep should be enough for caps up to 1.5uF. Use 10ms as
	 * arbitrary timeout.
	 */
	ret = readl_poll_timeout(priv->base + STM32_VREFBUF_CSR, val,
				 val & STM32_VRR, 650, 10000);
	if (ret) {
		dev_err(&rdev->dev, "stm32 vrefbuf timed out!\n");
		val = readl_relaxed(priv->base + STM32_VREFBUF_CSR);
		val = (val & ~STM32_ENVR) | STM32_HIZ;
		writel_relaxed(val, priv->base + STM32_VREFBUF_CSR);
	}

	pm_runtime_put_autosuspend(priv->dev);

	return ret;
}

static int stm32_vrefbuf_disable(struct regulator_dev *rdev)
{
	struct stm32_vrefbuf *priv = rdev_get_drvdata(rdev);
	u32 val;
	int ret;

	ret = pm_runtime_resume_and_get(priv->dev);
	if (ret < 0)
		return ret;

	val = readl_relaxed(priv->base + STM32_VREFBUF_CSR);
	val &= ~STM32_ENVR;
	writel_relaxed(val, priv->base + STM32_VREFBUF_CSR);

	pm_runtime_put_autosuspend(priv->dev);

	return 0;
}

static int stm32_vrefbuf_is_enabled(struct regulator_dev *rdev)
{
	struct stm32_vrefbuf *priv = rdev_get_drvdata(rdev);
	int ret;

	ret = pm_runtime_resume_and_get(priv->dev);
	if (ret < 0)
		return ret;

	ret = readl_relaxed(priv->base + STM32_VREFBUF_CSR) & STM32_ENVR;

	pm_runtime_put_autosuspend(priv->dev);

	return ret;
}

static int stm32_vrefbuf_set_voltage_sel(struct regulator_dev *rdev,
					 unsigned sel)
{
	struct stm32_vrefbuf *priv = rdev_get_drvdata(rdev);
	u32 val;
	int ret;

	ret = pm_runtime_resume_and_get(priv->dev);
	if (ret < 0)
		return ret;

Annotation

Implementation Notes