uboot/drivers/power/regulator/stm32-vrefbuf.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
   4 * Author: Fabrice Gasnier <fabrice.gasnier@st.com>
   5 *
   6 * Originally based on the Linux kernel v4.16 drivers/regulator/stm32-vrefbuf.c
   7 */
   8
   9#include <common.h>
  10#include <clk.h>
  11#include <dm.h>
  12#include <asm/io.h>
  13#include <linux/iopoll.h>
  14#include <linux/kernel.h>
  15#include <power/regulator.h>
  16
  17/* STM32 VREFBUF registers */
  18#define STM32_VREFBUF_CSR               0x00
  19
  20/* STM32 VREFBUF CSR bitfields */
  21#define STM32_VRS                       GENMASK(6, 4)
  22#define STM32_VRS_SHIFT                 4
  23#define STM32_VRR                       BIT(3)
  24#define STM32_HIZ                       BIT(1)
  25#define STM32_ENVR                      BIT(0)
  26
  27struct stm32_vrefbuf {
  28        void __iomem *base;
  29        struct clk clk;
  30        struct udevice *vdda_supply;
  31};
  32
  33static const unsigned int stm32_vrefbuf_voltages[] = {
  34        /* Matches resp. VRS = 000b, 001b, 010b, 011b */
  35        2500000, 2048000, 1800000, 1500000,
  36};
  37
  38static int stm32_vrefbuf_set_enable(struct udevice *dev, bool enable)
  39{
  40        struct stm32_vrefbuf *priv = dev_get_priv(dev);
  41        u32 val;
  42        int ret;
  43
  44        clrsetbits_le32(priv->base + STM32_VREFBUF_CSR, STM32_HIZ | STM32_ENVR,
  45                        enable ? STM32_ENVR : STM32_HIZ);
  46        if (!enable)
  47                return 0;
  48
  49        /*
  50         * Vrefbuf startup time depends on external capacitor: wait here for
  51         * VRR to be set. That means output has reached expected value.
  52         * ~650us sleep should be enough for caps up to 1.5uF. Use 10ms as
  53         * arbitrary timeout.
  54         */
  55        ret = readl_poll_timeout(priv->base + STM32_VREFBUF_CSR, val,
  56                                 val & STM32_VRR, 10000);
  57        if (ret < 0) {
  58                dev_err(dev, "stm32 vrefbuf timed out: %d\n", ret);
  59                clrsetbits_le32(priv->base + STM32_VREFBUF_CSR, STM32_ENVR,
  60                                STM32_HIZ);
  61                return ret;
  62        }
  63
  64        return 0;
  65}
  66
  67static int stm32_vrefbuf_get_enable(struct udevice *dev)
  68{
  69        struct stm32_vrefbuf *priv = dev_get_priv(dev);
  70
  71        return readl(priv->base + STM32_VREFBUF_CSR) & STM32_ENVR;
  72}
  73
  74static int stm32_vrefbuf_set_value(struct udevice *dev, int uV)
  75{
  76        struct stm32_vrefbuf *priv = dev_get_priv(dev);
  77        unsigned int i;
  78
  79        for (i = 0; i < ARRAY_SIZE(stm32_vrefbuf_voltages); i++) {
  80                if (uV == stm32_vrefbuf_voltages[i]) {
  81                        clrsetbits_le32(priv->base + STM32_VREFBUF_CSR,
  82                                        STM32_VRS, i << STM32_VRS_SHIFT);
  83                        return 0;
  84                }
  85        }
  86
  87        return -EINVAL;
  88}
  89
  90static int stm32_vrefbuf_get_value(struct udevice *dev)
  91{
  92        struct stm32_vrefbuf *priv = dev_get_priv(dev);
  93        u32 val;
  94
  95        val = readl(priv->base + STM32_VREFBUF_CSR) & STM32_VRS;
  96        val >>= STM32_VRS_SHIFT;
  97
  98        return stm32_vrefbuf_voltages[val];
  99}
 100
 101static const struct dm_regulator_ops stm32_vrefbuf_ops = {
 102        .get_value  = stm32_vrefbuf_get_value,
 103        .set_value  = stm32_vrefbuf_set_value,
 104        .get_enable = stm32_vrefbuf_get_enable,
 105        .set_enable = stm32_vrefbuf_set_enable,
 106};
 107
 108static int stm32_vrefbuf_probe(struct udevice *dev)
 109{
 110        struct stm32_vrefbuf *priv = dev_get_priv(dev);
 111        int ret;
 112
 113        priv->base = dev_read_addr_ptr(dev);
 114
 115        ret = clk_get_by_index(dev, 0, &priv->clk);
 116        if (ret) {
 117                dev_err(dev, "Can't get clock: %d\n", ret);
 118                return ret;
 119        }
 120
 121        ret = clk_enable(&priv->clk);
 122        if (ret) {
 123                dev_err(dev, "Can't enable clock: %d\n", ret);
 124                return ret;
 125        }
 126
 127        ret = device_get_supply_regulator(dev, "vdda-supply",
 128                                          &priv->vdda_supply);
 129        if (ret) {
 130                dev_dbg(dev, "No vdda-supply: %d\n", ret);
 131                return 0;
 132        }
 133
 134        ret = regulator_set_enable(priv->vdda_supply, true);
 135        if (ret) {
 136                dev_err(dev, "Can't enable vdda-supply: %d\n", ret);
 137                clk_disable(&priv->clk);
 138        }
 139
 140        return ret;
 141}
 142
 143static const struct udevice_id stm32_vrefbuf_ids[] = {
 144        { .compatible = "st,stm32-vrefbuf" },
 145        { }
 146};
 147
 148U_BOOT_DRIVER(stm32_vrefbuf) = {
 149        .name  = "stm32-vrefbuf",
 150        .id = UCLASS_REGULATOR,
 151        .of_match = stm32_vrefbuf_ids,
 152        .probe = stm32_vrefbuf_probe,
 153        .ops = &stm32_vrefbuf_ops,
 154        .priv_auto_alloc_size = sizeof(struct stm32_vrefbuf),
 155};
 156