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