db8c5a949c6f1f71bff32592a82f1220cb432caf
[oweals/u-boot.git] / drivers / power / regulator / pbias_regulator.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * (C) Copyright 2016 Texas Instruments Incorporated, <www.ti.com>
4  * Jean-Jacques Hiblot <jjhiblot@ti.com>
5  */
6
7 #include <common.h>
8 #include <errno.h>
9 #include <dm.h>
10 #include <log.h>
11 #include <linux/err.h>
12 #include <power/pmic.h>
13 #include <power/regulator.h>
14 #include <regmap.h>
15 #include <syscon.h>
16 #include <linux/bitops.h>
17 #include <linux/ioport.h>
18 #include <dm/read.h>
19 #ifdef CONFIG_MMC_OMAP36XX_PINS
20 #include <asm/arch/sys_proto.h>
21 #include <asm/io.h>
22 #include <asm/arch/mux.h>
23 #endif
24
25 struct pbias_reg_info {
26         u32 enable;
27         u32 enable_mask;
28         u32 disable_val;
29         u32 vmode;
30         unsigned int enable_time;
31         char *name;
32 };
33
34 struct pbias_priv {
35         struct regmap *regmap;
36         int offset;
37 };
38
39 static const struct pmic_child_info pmic_children_info[] = {
40         { .prefix = "pbias", .driver = "pbias_regulator"},
41         { },
42 };
43
44 static int pbias_write(struct udevice *dev, uint reg, const uint8_t *buff,
45                        int len)
46 {
47         struct pbias_priv *priv = dev_get_priv(dev);
48         u32 val = *(u32 *)buff;
49
50         if (len != 4)
51                 return -EINVAL;
52
53         return regmap_write(priv->regmap, priv->offset, val);
54 }
55
56 static int pbias_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
57 {
58         struct pbias_priv *priv = dev_get_priv(dev);
59
60         if (len != 4)
61                 return -EINVAL;
62
63         return regmap_read(priv->regmap, priv->offset, (u32 *)buff);
64 }
65
66 static int pbias_ofdata_to_platdata(struct udevice *dev)
67 {
68         struct pbias_priv *priv = dev_get_priv(dev);
69         struct udevice *syscon;
70         struct regmap *regmap;
71         struct resource res;
72         int err;
73
74         err = uclass_get_device_by_phandle(UCLASS_SYSCON, dev,
75                                            "syscon", &syscon);
76         if (err) {
77                 pr_err("%s: unable to find syscon device (%d)\n", __func__,
78                       err);
79                 return err;
80         }
81
82         regmap = syscon_get_regmap(syscon);
83         if (IS_ERR(regmap)) {
84                 pr_err("%s: unable to find regmap (%ld)\n", __func__,
85                       PTR_ERR(regmap));
86                 return PTR_ERR(regmap);
87         }
88         priv->regmap = regmap;
89
90         err = dev_read_resource(dev, 0, &res);
91         if (err) {
92                 pr_err("%s: unable to find offset (%d)\n", __func__, err);
93                 return err;
94         }
95         priv->offset = res.start;
96
97         return 0;
98 }
99
100 static int pbias_bind(struct udevice *dev)
101 {
102         int children;
103
104         children = pmic_bind_children(dev, dev->node, pmic_children_info);
105         if (!children)
106                 debug("%s: %s - no child found\n", __func__, dev->name);
107
108         return 0;
109 }
110
111 static struct dm_pmic_ops pbias_ops = {
112         .read = pbias_read,
113         .write = pbias_write,
114 };
115
116 static const struct udevice_id pbias_ids[] = {
117         { .compatible = "ti,pbias-dra7" },
118         { .compatible = "ti,pbias-omap2" },
119         { .compatible = "ti,pbias-omap3" },
120         { .compatible = "ti,pbias-omap4" },
121         { .compatible = "ti,pbias-omap5" },
122         { }
123 };
124
125 U_BOOT_DRIVER(pbias_pmic) = {
126         .name = "pbias_pmic",
127         .id = UCLASS_PMIC,
128         .of_match = pbias_ids,
129         .bind = pbias_bind,
130         .ops = &pbias_ops,
131         .ofdata_to_platdata = pbias_ofdata_to_platdata,
132         .priv_auto_alloc_size = sizeof(struct pbias_priv),
133 };
134
135 static const struct pbias_reg_info pbias_mmc_omap2430 = {
136         .enable = BIT(1),
137         .enable_mask = BIT(1),
138         .vmode = BIT(0),
139         .disable_val = 0,
140         .enable_time = 100,
141         .name = "pbias_mmc_omap2430"
142 };
143
144 static const struct pbias_reg_info pbias_sim_omap3 = {
145         .enable = BIT(9),
146         .enable_mask = BIT(9),
147         .vmode = BIT(8),
148         .enable_time = 100,
149         .name = "pbias_sim_omap3"
150 };
151
152 static const struct pbias_reg_info pbias_mmc_omap4 = {
153         .enable = BIT(26) | BIT(22),
154         .enable_mask = BIT(26) | BIT(25) | BIT(22),
155         .disable_val = BIT(25),
156         .vmode = BIT(21),
157         .enable_time = 100,
158         .name = "pbias_mmc_omap4"
159 };
160
161 static const struct pbias_reg_info pbias_mmc_omap5 = {
162         .enable = BIT(27) | BIT(26),
163         .enable_mask = BIT(27) | BIT(25) | BIT(26),
164         .disable_val = BIT(25),
165         .vmode = BIT(21),
166         .enable_time = 100,
167         .name = "pbias_mmc_omap5"
168 };
169
170 static const struct pbias_reg_info *pbias_reg_infos[] = {
171         &pbias_mmc_omap5,
172         &pbias_mmc_omap4,
173         &pbias_sim_omap3,
174         &pbias_mmc_omap2430,
175         NULL
176 };
177
178 static int pbias_regulator_probe(struct udevice *dev)
179 {
180         const struct pbias_reg_info **p = pbias_reg_infos;
181         struct dm_regulator_uclass_platdata *uc_pdata;
182
183         uc_pdata = dev_get_uclass_platdata(dev);
184
185         while (*p) {
186                 int rc;
187
188                 rc = dev_read_stringlist_search(dev, "regulator-name",
189                                                 (*p)->name);
190                 if (rc >= 0) {
191                         debug("found regulator %s\n", (*p)->name);
192                         break;
193                 } else if (rc != -ENODATA) {
194                         return rc;
195                 }
196                 p++;
197         }
198         if (!*p) {
199                 int i = 0;
200                 const char *s;
201
202                 debug("regulator ");
203                 while (dev_read_string_index(dev, "regulator-name", i++, &s) >= 0)
204                         debug("%s'%s' ", (i > 1) ? ", " : "", s);
205                 debug("%s not supported\n", (i > 2) ? "are" : "is");
206                 return -EINVAL;
207         }
208
209         uc_pdata->type = REGULATOR_TYPE_OTHER;
210         dev->priv = (void *)*p;
211
212         return 0;
213 }
214
215 static int pbias_regulator_get_value(struct udevice *dev)
216 {
217         const struct pbias_reg_info *p = dev_get_priv(dev);
218         int rc;
219         u32 reg;
220
221         rc = pmic_read(dev->parent, 0, (uint8_t *)&reg, sizeof(reg));
222         if (rc)
223                 return rc;
224
225         debug("%s voltage id %s\n", p->name,
226               (reg & p->vmode) ? "3.0v" : "1.8v");
227         return (reg & p->vmode) ? 3000000 : 1800000;
228 }
229
230 static int pbias_regulator_set_value(struct udevice *dev, int uV)
231 {
232         const struct pbias_reg_info *p = dev_get_priv(dev);
233         int rc, ret;
234         u32 reg;
235 #ifdef CONFIG_MMC_OMAP36XX_PINS
236         u32 wkup_ctrl = readl(OMAP34XX_CTRL_WKUP_CTRL);
237 #endif
238
239         rc = pmic_read(dev->parent, 0, (uint8_t *)&reg, sizeof(reg));
240         if (rc)
241                 return rc;
242
243         if (uV == 3300000)
244                 reg |= p->vmode;
245         else if (uV == 1800000)
246                 reg &= ~p->vmode;
247         else
248                 return -EINVAL;
249
250         debug("Setting %s voltage to %s\n", p->name,
251               (reg & p->vmode) ? "3.0v" : "1.8v");
252
253 #ifdef CONFIG_MMC_OMAP36XX_PINS
254         if (get_cpu_family() == CPU_OMAP36XX) {
255                 /* Disable extended drain IO before changing PBIAS */
256                 wkup_ctrl &= ~OMAP34XX_CTRL_WKUP_CTRL_GPIO_IO_PWRDNZ;
257                 writel(wkup_ctrl, OMAP34XX_CTRL_WKUP_CTRL);
258         }
259 #endif
260         ret = pmic_write(dev->parent, 0, (uint8_t *)&reg, sizeof(reg));
261 #ifdef CONFIG_MMC_OMAP36XX_PINS
262         if (get_cpu_family() == CPU_OMAP36XX) {
263                 /* Enable extended drain IO after changing PBIAS */
264                 writel(wkup_ctrl |
265                                 OMAP34XX_CTRL_WKUP_CTRL_GPIO_IO_PWRDNZ,
266                                 OMAP34XX_CTRL_WKUP_CTRL);
267         }
268 #endif
269         return ret;
270 }
271
272 static int pbias_regulator_get_enable(struct udevice *dev)
273 {
274         const struct pbias_reg_info *p = dev_get_priv(dev);
275         int rc;
276         u32 reg;
277
278         rc = pmic_read(dev->parent, 0, (uint8_t *)&reg, sizeof(reg));
279         if (rc)
280                 return rc;
281
282         debug("%s id %s\n", p->name,
283               (reg & p->enable_mask) == (p->disable_val) ? "on" : "off");
284
285         return (reg & p->enable_mask) == (p->disable_val);
286 }
287
288 static int pbias_regulator_set_enable(struct udevice *dev, bool enable)
289 {
290         const struct pbias_reg_info *p = dev_get_priv(dev);
291         int rc;
292         u32 reg;
293 #ifdef CONFIG_MMC_OMAP36XX_PINS
294         u32 wkup_ctrl = readl(OMAP34XX_CTRL_WKUP_CTRL);
295 #endif
296
297         debug("Turning %s %s\n", enable ? "on" : "off", p->name);
298
299 #ifdef CONFIG_MMC_OMAP36XX_PINS
300         if (get_cpu_family() == CPU_OMAP36XX) {
301                 /* Disable extended drain IO before changing PBIAS */
302                 wkup_ctrl &= ~OMAP34XX_CTRL_WKUP_CTRL_GPIO_IO_PWRDNZ;
303                 writel(wkup_ctrl, OMAP34XX_CTRL_WKUP_CTRL);
304         }
305 #endif
306
307         rc = pmic_read(dev->parent, 0, (uint8_t *)&reg, sizeof(reg));
308         if (rc)
309                 return rc;
310
311         reg &= ~p->enable_mask;
312         if (enable)
313                 reg |= p->enable;
314         else
315                 reg |= p->disable_val;
316
317         rc = pmic_write(dev->parent, 0, (uint8_t *)&reg, sizeof(reg));
318
319 #ifdef CONFIG_MMC_OMAP36XX_PINS
320         if (get_cpu_family() == CPU_OMAP36XX) {
321                 /* Enable extended drain IO after changing PBIAS */
322                 writel(wkup_ctrl |
323                                 OMAP34XX_CTRL_WKUP_CTRL_GPIO_IO_PWRDNZ,
324                                 OMAP34XX_CTRL_WKUP_CTRL);
325         }
326 #endif
327
328         if (rc)
329                 return rc;
330
331         if (enable)
332                 udelay(p->enable_time);
333
334         return 0;
335 }
336
337 static const struct dm_regulator_ops pbias_regulator_ops = {
338         .get_value  = pbias_regulator_get_value,
339         .set_value  = pbias_regulator_set_value,
340         .get_enable = pbias_regulator_get_enable,
341         .set_enable = pbias_regulator_set_enable,
342 };
343
344 U_BOOT_DRIVER(pbias_regulator) = {
345         .name = "pbias_regulator",
346         .id = UCLASS_REGULATOR,
347         .ops = &pbias_regulator_ops,
348         .probe = pbias_regulator_probe,
349 };