blob: b52e1e85d5c3af625f0dac1d99c2b59bc2fbfa33 [file] [log] [blame]
Patrick Delaunayaa785312018-04-26 16:45:18 +02001// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
2/*
3 * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
4 */
5
6#include <common.h>
7#include <dm.h>
8#include <errno.h>
Patrick Delaunayaa785312018-04-26 16:45:18 +02009#include <syscon.h>
Patrick Delaunay900494d2020-01-28 10:10:59 +010010#include <asm/io.h>
Simon Glass9bc15642020-02-03 07:36:16 -070011#include <dm/device_compat.h>
Simon Glassd66c5f72020-02-03 07:36:15 -070012#include <linux/err.h>
Patrick Delaunayaa785312018-04-26 16:45:18 +020013#include <power/pmic.h>
14#include <power/regulator.h>
15
16#define STM32MP_PWR_CR3 0xc
17#define STM32MP_PWR_CR3_USB33DEN BIT(24)
18#define STM32MP_PWR_CR3_USB33RDY BIT(26)
19#define STM32MP_PWR_CR3_REG18DEN BIT(28)
20#define STM32MP_PWR_CR3_REG18RDY BIT(29)
21#define STM32MP_PWR_CR3_REG11DEN BIT(30)
22#define STM32MP_PWR_CR3_REG11RDY BIT(31)
23
24struct stm32mp_pwr_reg_info {
25 u32 enable;
26 u32 ready;
27 char *name;
28};
29
30struct stm32mp_pwr_priv {
Patrick Delaunay900494d2020-01-28 10:10:59 +010031 fdt_addr_t base;
Patrick Delaunayaa785312018-04-26 16:45:18 +020032};
33
34static int stm32mp_pwr_write(struct udevice *dev, uint reg,
35 const uint8_t *buff, int len)
36{
37 struct stm32mp_pwr_priv *priv = dev_get_priv(dev);
38 u32 val = *(u32 *)buff;
39
40 if (len != 4)
41 return -EINVAL;
42
Patrick Delaunay900494d2020-01-28 10:10:59 +010043 writel(val, priv->base + STM32MP_PWR_CR3);
44
45 return 0;
Patrick Delaunayaa785312018-04-26 16:45:18 +020046}
47
48static int stm32mp_pwr_read(struct udevice *dev, uint reg, uint8_t *buff,
49 int len)
50{
51 struct stm32mp_pwr_priv *priv = dev_get_priv(dev);
52
53 if (len != 4)
54 return -EINVAL;
55
Patrick Delaunay900494d2020-01-28 10:10:59 +010056 *(u32 *)buff = readl(priv->base + STM32MP_PWR_CR3);
57
58 return 0;
Patrick Delaunayaa785312018-04-26 16:45:18 +020059}
60
61static int stm32mp_pwr_ofdata_to_platdata(struct udevice *dev)
62{
63 struct stm32mp_pwr_priv *priv = dev_get_priv(dev);
Patrick Delaunayaa785312018-04-26 16:45:18 +020064
Patrick Delaunay900494d2020-01-28 10:10:59 +010065 priv->base = dev_read_addr(dev);
66 if (priv->base == FDT_ADDR_T_NONE)
67 return -EINVAL;
Patrick Delaunayaa785312018-04-26 16:45:18 +020068
69 return 0;
70}
71
72static const struct pmic_child_info pwr_children_info[] = {
73 { .prefix = "reg", .driver = "stm32mp_pwr_regulator"},
74 { .prefix = "usb", .driver = "stm32mp_pwr_regulator"},
75 { },
76};
77
78static int stm32mp_pwr_bind(struct udevice *dev)
79{
80 int children;
81
82 children = pmic_bind_children(dev, dev->node, pwr_children_info);
83 if (!children)
84 dev_dbg(dev, "no child found\n");
85
86 return 0;
87}
88
89static struct dm_pmic_ops stm32mp_pwr_ops = {
90 .read = stm32mp_pwr_read,
91 .write = stm32mp_pwr_write,
92};
93
94static const struct udevice_id stm32mp_pwr_ids[] = {
95 { .compatible = "st,stm32mp1,pwr-reg" },
96 { }
97};
98
99U_BOOT_DRIVER(stm32mp_pwr_pmic) = {
100 .name = "stm32mp_pwr_pmic",
101 .id = UCLASS_PMIC,
102 .of_match = stm32mp_pwr_ids,
103 .bind = stm32mp_pwr_bind,
104 .ops = &stm32mp_pwr_ops,
105 .ofdata_to_platdata = stm32mp_pwr_ofdata_to_platdata,
106 .priv_auto_alloc_size = sizeof(struct stm32mp_pwr_priv),
107};
108
109static const struct stm32mp_pwr_reg_info stm32mp_pwr_reg11 = {
110 .enable = STM32MP_PWR_CR3_REG11DEN,
111 .ready = STM32MP_PWR_CR3_REG11RDY,
112 .name = "reg11"
113};
114
115static const struct stm32mp_pwr_reg_info stm32mp_pwr_reg18 = {
116 .enable = STM32MP_PWR_CR3_REG18DEN,
117 .ready = STM32MP_PWR_CR3_REG18RDY,
118 .name = "reg18"
119};
120
121static const struct stm32mp_pwr_reg_info stm32mp_pwr_usb33 = {
122 .enable = STM32MP_PWR_CR3_USB33DEN,
123 .ready = STM32MP_PWR_CR3_USB33RDY,
124 .name = "usb33"
125};
126
127static const struct stm32mp_pwr_reg_info *stm32mp_pwr_reg_infos[] = {
128 &stm32mp_pwr_reg11,
129 &stm32mp_pwr_reg18,
130 &stm32mp_pwr_usb33,
131 NULL
132};
133
134static int stm32mp_pwr_regulator_probe(struct udevice *dev)
135{
136 const struct stm32mp_pwr_reg_info **p = stm32mp_pwr_reg_infos;
137 struct dm_regulator_uclass_platdata *uc_pdata;
138
139 uc_pdata = dev_get_uclass_platdata(dev);
140
141 while (*p) {
142 int rc;
143
144 rc = dev_read_stringlist_search(dev, "regulator-name",
145 (*p)->name);
146 if (rc >= 0) {
147 dev_dbg(dev, "found regulator %s\n", (*p)->name);
148 break;
149 } else if (rc != -ENODATA) {
150 return rc;
151 }
152 p++;
153 }
154 if (!*p) {
155 int i = 0;
156 const char *s;
157
158 dev_dbg(dev, "regulator ");
159 while (dev_read_string_index(dev, "regulator-name",
160 i++, &s) >= 0)
161 dev_dbg(dev, "%s'%s' ", (i > 1) ? ", " : "", s);
162 dev_dbg(dev, "%s not supported\n", (i > 2) ? "are" : "is");
163 return -EINVAL;
164 }
165
166 uc_pdata->type = REGULATOR_TYPE_FIXED;
167 dev->priv = (void *)*p;
168
169 return 0;
170}
171
172static int stm32mp_pwr_regulator_set_value(struct udevice *dev, int uV)
173{
174 struct dm_regulator_uclass_platdata *uc_pdata;
175
176 uc_pdata = dev_get_uclass_platdata(dev);
177 if (!uc_pdata)
178 return -ENXIO;
179
180 if (uc_pdata->min_uV != uV) {
181 dev_dbg(dev, "Invalid uV=%d for: %s\n", uV, uc_pdata->name);
182 return -EINVAL;
183 }
184
185 return 0;
186}
187
188static int stm32mp_pwr_regulator_get_value(struct udevice *dev)
189{
190 struct dm_regulator_uclass_platdata *uc_pdata;
191
192 uc_pdata = dev_get_uclass_platdata(dev);
193 if (!uc_pdata)
194 return -ENXIO;
195
196 if (uc_pdata->min_uV != uc_pdata->max_uV) {
197 dev_dbg(dev, "Invalid constraints for: %s\n", uc_pdata->name);
198 return -EINVAL;
199 }
200
201 return uc_pdata->min_uV;
202}
203
204static int stm32mp_pwr_regulator_get_enable(struct udevice *dev)
205{
206 const struct stm32mp_pwr_reg_info *p = dev_get_priv(dev);
207 int rc;
208 u32 reg;
209
210 rc = pmic_read(dev->parent, 0, (uint8_t *)&reg, sizeof(reg));
211 if (rc)
212 return rc;
213
214 dev_dbg(dev, "%s id %s\n", p->name, (reg & p->enable) ? "on" : "off");
215
216 return (reg & p->enable) != 0;
217}
218
219static int stm32mp_pwr_regulator_set_enable(struct udevice *dev, bool enable)
220{
221 const struct stm32mp_pwr_reg_info *p = dev_get_priv(dev);
222 int rc;
223 u32 reg;
224 u32 time_start;
225
226 dev_dbg(dev, "Turning %s %s\n", enable ? "on" : "off", p->name);
227
228 rc = pmic_read(dev->parent, 0, (uint8_t *)&reg, sizeof(reg));
229 if (rc)
230 return rc;
231
232 /* if regulator is already in the wanted state, nothing to do */
233 if (!!(reg & p->enable) == enable)
234 return 0;
235
236 reg &= ~p->enable;
237 if (enable)
238 reg |= p->enable;
239
240 rc = pmic_write(dev->parent, 0, (uint8_t *)&reg, sizeof(reg));
241 if (rc)
242 return rc;
243
244 if (!enable)
245 return 0;
246
247 /* waiting ready for enable */
248 time_start = get_timer(0);
249 while (1) {
250 rc = pmic_read(dev->parent, 0, (uint8_t *)&reg, sizeof(reg));
251 if (rc)
252 return rc;
253 if (reg & p->ready)
254 break;
255 if (get_timer(time_start) > CONFIG_SYS_HZ) {
256 dev_dbg(dev, "%s: timeout\n", p->name);
257 return -ETIMEDOUT;
258 }
259 }
260 return 0;
261}
262
263static const struct dm_regulator_ops stm32mp_pwr_regulator_ops = {
264 .set_value = stm32mp_pwr_regulator_set_value,
265 .get_value = stm32mp_pwr_regulator_get_value,
266 .get_enable = stm32mp_pwr_regulator_get_enable,
267 .set_enable = stm32mp_pwr_regulator_set_enable,
268};
269
270U_BOOT_DRIVER(stm32mp_pwr_regulator) = {
271 .name = "stm32mp_pwr_regulator",
272 .id = UCLASS_REGULATOR,
273 .ops = &stm32mp_pwr_regulator_ops,
274 .probe = stm32mp_pwr_regulator_probe,
275};