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