blob: 4559ef599d7b61ad9850e553b4f0b422eaa8c600 [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>
9#include <regmap.h>
10#include <syscon.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 {
31 struct regmap *regmap;
32};
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
43 return regmap_write(priv->regmap, STM32MP_PWR_CR3, val);
44}
45
46static int stm32mp_pwr_read(struct udevice *dev, uint reg, uint8_t *buff,
47 int len)
48{
49 struct stm32mp_pwr_priv *priv = dev_get_priv(dev);
50
51 if (len != 4)
52 return -EINVAL;
53
54 return regmap_read(priv->regmap, STM32MP_PWR_CR3, (u32 *)buff);
55}
56
57static int stm32mp_pwr_ofdata_to_platdata(struct udevice *dev)
58{
59 struct stm32mp_pwr_priv *priv = dev_get_priv(dev);
60 struct regmap *regmap;
61
62 regmap = syscon_get_regmap_by_driver_data(STM32MP_SYSCON_PWR);
63 if (IS_ERR(regmap)) {
64 pr_err("%s: unable to find regmap (%ld)\n", __func__,
65 PTR_ERR(regmap));
66 return PTR_ERR(regmap);
67 }
68 priv->regmap = regmap;
69
70 return 0;
71}
72
73static const struct pmic_child_info pwr_children_info[] = {
74 { .prefix = "reg", .driver = "stm32mp_pwr_regulator"},
75 { .prefix = "usb", .driver = "stm32mp_pwr_regulator"},
76 { },
77};
78
79static int stm32mp_pwr_bind(struct udevice *dev)
80{
81 int children;
82
83 children = pmic_bind_children(dev, dev->node, pwr_children_info);
84 if (!children)
85 dev_dbg(dev, "no child found\n");
86
87 return 0;
88}
89
90static struct dm_pmic_ops stm32mp_pwr_ops = {
91 .read = stm32mp_pwr_read,
92 .write = stm32mp_pwr_write,
93};
94
95static const struct udevice_id stm32mp_pwr_ids[] = {
96 { .compatible = "st,stm32mp1,pwr-reg" },
97 { }
98};
99
100U_BOOT_DRIVER(stm32mp_pwr_pmic) = {
101 .name = "stm32mp_pwr_pmic",
102 .id = UCLASS_PMIC,
103 .of_match = stm32mp_pwr_ids,
104 .bind = stm32mp_pwr_bind,
105 .ops = &stm32mp_pwr_ops,
106 .ofdata_to_platdata = stm32mp_pwr_ofdata_to_platdata,
107 .priv_auto_alloc_size = sizeof(struct stm32mp_pwr_priv),
108};
109
110static const struct stm32mp_pwr_reg_info stm32mp_pwr_reg11 = {
111 .enable = STM32MP_PWR_CR3_REG11DEN,
112 .ready = STM32MP_PWR_CR3_REG11RDY,
113 .name = "reg11"
114};
115
116static const struct stm32mp_pwr_reg_info stm32mp_pwr_reg18 = {
117 .enable = STM32MP_PWR_CR3_REG18DEN,
118 .ready = STM32MP_PWR_CR3_REG18RDY,
119 .name = "reg18"
120};
121
122static const struct stm32mp_pwr_reg_info stm32mp_pwr_usb33 = {
123 .enable = STM32MP_PWR_CR3_USB33DEN,
124 .ready = STM32MP_PWR_CR3_USB33RDY,
125 .name = "usb33"
126};
127
128static const struct stm32mp_pwr_reg_info *stm32mp_pwr_reg_infos[] = {
129 &stm32mp_pwr_reg11,
130 &stm32mp_pwr_reg18,
131 &stm32mp_pwr_usb33,
132 NULL
133};
134
135static int stm32mp_pwr_regulator_probe(struct udevice *dev)
136{
137 const struct stm32mp_pwr_reg_info **p = stm32mp_pwr_reg_infos;
138 struct dm_regulator_uclass_platdata *uc_pdata;
139
140 uc_pdata = dev_get_uclass_platdata(dev);
141
142 while (*p) {
143 int rc;
144
145 rc = dev_read_stringlist_search(dev, "regulator-name",
146 (*p)->name);
147 if (rc >= 0) {
148 dev_dbg(dev, "found regulator %s\n", (*p)->name);
149 break;
150 } else if (rc != -ENODATA) {
151 return rc;
152 }
153 p++;
154 }
155 if (!*p) {
156 int i = 0;
157 const char *s;
158
159 dev_dbg(dev, "regulator ");
160 while (dev_read_string_index(dev, "regulator-name",
161 i++, &s) >= 0)
162 dev_dbg(dev, "%s'%s' ", (i > 1) ? ", " : "", s);
163 dev_dbg(dev, "%s not supported\n", (i > 2) ? "are" : "is");
164 return -EINVAL;
165 }
166
167 uc_pdata->type = REGULATOR_TYPE_FIXED;
168 dev->priv = (void *)*p;
169
170 return 0;
171}
172
173static int stm32mp_pwr_regulator_set_value(struct udevice *dev, int uV)
174{
175 struct dm_regulator_uclass_platdata *uc_pdata;
176
177 uc_pdata = dev_get_uclass_platdata(dev);
178 if (!uc_pdata)
179 return -ENXIO;
180
181 if (uc_pdata->min_uV != uV) {
182 dev_dbg(dev, "Invalid uV=%d for: %s\n", uV, uc_pdata->name);
183 return -EINVAL;
184 }
185
186 return 0;
187}
188
189static int stm32mp_pwr_regulator_get_value(struct udevice *dev)
190{
191 struct dm_regulator_uclass_platdata *uc_pdata;
192
193 uc_pdata = dev_get_uclass_platdata(dev);
194 if (!uc_pdata)
195 return -ENXIO;
196
197 if (uc_pdata->min_uV != uc_pdata->max_uV) {
198 dev_dbg(dev, "Invalid constraints for: %s\n", uc_pdata->name);
199 return -EINVAL;
200 }
201
202 return uc_pdata->min_uV;
203}
204
205static int stm32mp_pwr_regulator_get_enable(struct udevice *dev)
206{
207 const struct stm32mp_pwr_reg_info *p = dev_get_priv(dev);
208 int rc;
209 u32 reg;
210
211 rc = pmic_read(dev->parent, 0, (uint8_t *)&reg, sizeof(reg));
212 if (rc)
213 return rc;
214
215 dev_dbg(dev, "%s id %s\n", p->name, (reg & p->enable) ? "on" : "off");
216
217 return (reg & p->enable) != 0;
218}
219
220static int stm32mp_pwr_regulator_set_enable(struct udevice *dev, bool enable)
221{
222 const struct stm32mp_pwr_reg_info *p = dev_get_priv(dev);
223 int rc;
224 u32 reg;
225 u32 time_start;
226
227 dev_dbg(dev, "Turning %s %s\n", enable ? "on" : "off", p->name);
228
229 rc = pmic_read(dev->parent, 0, (uint8_t *)&reg, sizeof(reg));
230 if (rc)
231 return rc;
232
233 /* if regulator is already in the wanted state, nothing to do */
234 if (!!(reg & p->enable) == enable)
235 return 0;
236
237 reg &= ~p->enable;
238 if (enable)
239 reg |= p->enable;
240
241 rc = pmic_write(dev->parent, 0, (uint8_t *)&reg, sizeof(reg));
242 if (rc)
243 return rc;
244
245 if (!enable)
246 return 0;
247
248 /* waiting ready for enable */
249 time_start = get_timer(0);
250 while (1) {
251 rc = pmic_read(dev->parent, 0, (uint8_t *)&reg, sizeof(reg));
252 if (rc)
253 return rc;
254 if (reg & p->ready)
255 break;
256 if (get_timer(time_start) > CONFIG_SYS_HZ) {
257 dev_dbg(dev, "%s: timeout\n", p->name);
258 return -ETIMEDOUT;
259 }
260 }
261 return 0;
262}
263
264static const struct dm_regulator_ops stm32mp_pwr_regulator_ops = {
265 .set_value = stm32mp_pwr_regulator_set_value,
266 .get_value = stm32mp_pwr_regulator_get_value,
267 .get_enable = stm32mp_pwr_regulator_get_enable,
268 .set_enable = stm32mp_pwr_regulator_set_enable,
269};
270
271U_BOOT_DRIVER(stm32mp_pwr_regulator) = {
272 .name = "stm32mp_pwr_regulator",
273 .id = UCLASS_REGULATOR,
274 .ops = &stm32mp_pwr_regulator_ops,
275 .probe = stm32mp_pwr_regulator_probe,
276};