Merge tag 'u-boot-atmel-fixes-2020.07-a' of https://gitlab.denx.de/u-boot/custodians...
[oweals/u-boot.git] / arch / arm / mach-stm32mp / pwr_regulator.c
1 // 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 <syscon.h>
10 #include <asm/io.h>
11 #include <dm/device_compat.h>
12 #include <linux/bitops.h>
13 #include <linux/err.h>
14 #include <power/pmic.h>
15 #include <power/regulator.h>
16
17 #define STM32MP_PWR_CR3 0xc
18 #define STM32MP_PWR_CR3_USB33DEN BIT(24)
19 #define STM32MP_PWR_CR3_USB33RDY BIT(26)
20 #define STM32MP_PWR_CR3_REG18DEN BIT(28)
21 #define STM32MP_PWR_CR3_REG18RDY BIT(29)
22 #define STM32MP_PWR_CR3_REG11DEN BIT(30)
23 #define STM32MP_PWR_CR3_REG11RDY BIT(31)
24
25 struct stm32mp_pwr_reg_info {
26         u32 enable;
27         u32 ready;
28         char *name;
29 };
30
31 struct stm32mp_pwr_priv {
32         fdt_addr_t base;
33 };
34
35 static int stm32mp_pwr_write(struct udevice *dev, uint reg,
36                              const uint8_t *buff, int len)
37 {
38         struct stm32mp_pwr_priv *priv = dev_get_priv(dev);
39         u32 val = *(u32 *)buff;
40
41         if (len != 4)
42                 return -EINVAL;
43
44         writel(val, priv->base + STM32MP_PWR_CR3);
45
46         return 0;
47 }
48
49 static int stm32mp_pwr_read(struct udevice *dev, uint reg, uint8_t *buff,
50                             int len)
51 {
52         struct stm32mp_pwr_priv *priv = dev_get_priv(dev);
53
54         if (len != 4)
55                 return -EINVAL;
56
57         *(u32 *)buff = readl(priv->base + STM32MP_PWR_CR3);
58
59         return 0;
60 }
61
62 static int stm32mp_pwr_ofdata_to_platdata(struct udevice *dev)
63 {
64         struct stm32mp_pwr_priv *priv = dev_get_priv(dev);
65
66         priv->base = dev_read_addr(dev);
67         if (priv->base == FDT_ADDR_T_NONE)
68                 return -EINVAL;
69
70         return 0;
71 }
72
73 static 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
79 static 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
90 static struct dm_pmic_ops stm32mp_pwr_ops = {
91         .read = stm32mp_pwr_read,
92         .write = stm32mp_pwr_write,
93 };
94
95 static const struct udevice_id stm32mp_pwr_ids[] = {
96         { .compatible = "st,stm32mp1,pwr-reg" },
97         { }
98 };
99
100 U_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
110 static 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
116 static 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
122 static 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
128 static 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
135 static 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
173 static 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
189 static 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
205 static 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
220 static 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
264 static 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
271 U_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 };