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#define LOG_CATEGORY UCLASS_REGULATOR
  10
  11#include <common.h>
  12#include <clk.h>
  13#include <dm.h>
  14#include <asm/io.h>
  15#include <dm/device_compat.h>
  16#include <linux/bitops.h>
  17#include <linux/iopoll.h>
  18#include <linux/kernel.h>
  19#include <power/regulator.h>
  20
  21/* STM32 VREFBUF registers */
  22#define STM32_VREFBUF_CSR               0x00
  23
  24/* STM32 VREFBUF CSR bitfields */
  25#define STM32_VRS                       GENMASK(6, 4)
  26#define STM32_VRS_SHIFT                 4
  27#define STM32_VRR                       BIT(3)
  28#define STM32_HIZ                       BIT(1)
  29#define STM32_ENVR                      BIT(0)
  30
  31struct stm32_vrefbuf {
  32        void __iomem *base;
  33        struct clk clk;
  34        struct udevice *vdda_supply;
  35};
  36
  37static const int stm32_vrefbuf_voltages[] = {
  38        /* Matches resp. VRS = 000b, 001b, 010b, 011b */
  39        2500000, 2048000, 1800000, 1500000,
  40};
  41
  42static int stm32_vrefbuf_set_enable(struct udevice *dev, bool enable)
  43{
  44        struct stm32_vrefbuf *priv = dev_get_priv(dev);
  45        u32 val;
  46        int ret;
  47
  48        if (enable && !(readl(priv->base + STM32_VREFBUF_CSR) & STM32_ENVR)) {
  49                /*
  50                 * There maybe an overshoot:
  51                 * - when disabling, then re-enabling vrefbuf too quickly
  52                 * - or upon platform reset as external capacitor maybe slow
  53                 *   discharging (VREFBUF is HiZ at reset by default).
  54                 * So force active discharge (HiZ=0) for 1ms before enabling.
  55                 */
  56                clrbits_le32(priv->base + STM32_VREFBUF_CSR, STM32_HIZ);
  57                udelay(1000);
  58        }
  59
  60        clrsetbits_le32(priv->base + STM32_VREFBUF_CSR, STM32_ENVR,
  61                        enable ? STM32_ENVR : 0);
  62        if (!enable)
  63                return 0;
  64
  65        /*
  66         * Vrefbuf startup time depends on external capacitor: wait here for
  67         * VRR to be set. That means output has reached expected value.
  68         * ~650us sleep should be enough for caps up to 1.5uF. Use 10ms as
  69         * arbitrary timeout.
  70         */
  71        ret = readl_poll_timeout(priv->base + STM32_VREFBUF_CSR, val,
  72                                 val & STM32_VRR, 10000);
  73        if (ret < 0) {
  74                dev_err(dev, "stm32 vrefbuf timed out: %d\n", ret);
  75                clrsetbits_le32(priv->base + STM32_VREFBUF_CSR, STM32_ENVR,
  76                                STM32_HIZ);
  77                return ret;
  78        }
  79
  80        return 0;
  81}
  82
  83static int stm32_vrefbuf_get_enable(struct udevice *dev)
  84{
  85        struct stm32_vrefbuf *priv = dev_get_priv(dev);
  86
  87        return readl(priv->base + STM32_VREFBUF_CSR) & STM32_ENVR;
  88}
  89
  90static int stm32_vrefbuf_set_value(struct udevice *dev, int uV)
  91{
  92        struct stm32_vrefbuf *priv = dev_get_priv(dev);
  93        unsigned int i;
  94
  95        for (i = 0; i < ARRAY_SIZE(stm32_vrefbuf_voltages); i++) {
  96                if (uV == stm32_vrefbuf_voltages[i]) {
  97                        clrsetbits_le32(priv->base + STM32_VREFBUF_CSR,
  98                                        STM32_VRS, i << STM32_VRS_SHIFT);
  99                        return 0;
 100                }
 101        }
 102
 103        return -EINVAL;
 104}
 105
 106static int stm32_vrefbuf_get_value(struct udevice *dev)
 107{
 108        struct stm32_vrefbuf *priv = dev_get_priv(dev);
 109        u32 val;
 110
 111        val = readl(priv->base + STM32_VREFBUF_CSR) & STM32_VRS;
 112        val >>= STM32_VRS_SHIFT;
 113
 114        return stm32_vrefbuf_voltages[val];
 115}
 116
 117static const struct dm_regulator_ops stm32_vrefbuf_ops = {
 118        .get_value  = stm32_vrefbuf_get_value,
 119        .set_value  = stm32_vrefbuf_set_value,
 120        .get_enable = stm32_vrefbuf_get_enable,
 121        .set_enable = stm32_vrefbuf_set_enable,
 122};
 123
 124static int stm32_vrefbuf_probe(struct udevice *dev)
 125{
 126        struct stm32_vrefbuf *priv = dev_get_priv(dev);
 127        int ret;
 128
 129        priv->base = dev_read_addr_ptr(dev);
 130
 131        ret = clk_get_by_index(dev, 0, &priv->clk);
 132        if (ret) {
 133                dev_err(dev, "Can't get clock: %d\n", ret);
 134                return ret;
 135        }
 136
 137        ret = clk_enable(&priv->clk);
 138        if (ret) {
 139                dev_err(dev, "Can't enable clock: %d\n", ret);
 140                return ret;
 141        }
 142
 143        ret = device_get_supply_regulator(dev, "vdda-supply",
 144                                          &priv->vdda_supply);
 145        if (ret) {
 146                dev_dbg(dev, "No vdda-supply: %d\n", ret);
 147                return 0;
 148        }
 149
 150        ret = regulator_set_enable(priv->vdda_supply, true);
 151        if (ret) {
 152                dev_err(dev, "Can't enable vdda-supply: %d\n", ret);
 153                clk_disable(&priv->clk);
 154        }
 155
 156        return ret;
 157}
 158
 159static const struct udevice_id stm32_vrefbuf_ids[] = {
 160        { .compatible = "st,stm32-vrefbuf" },
 161        { }
 162};
 163
 164U_BOOT_DRIVER(stm32_vrefbuf) = {
 165        .name  = "stm32-vrefbuf",
 166        .id = UCLASS_REGULATOR,
 167        .of_match = stm32_vrefbuf_ids,
 168        .probe = stm32_vrefbuf_probe,
 169        .ops = &stm32_vrefbuf_ops,
 170        .priv_auto      = sizeof(struct stm32_vrefbuf),
 171};
 172