blob: 8f06e27b898cfa6b555dbd8f2a3513014adc719a [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>
10#include <power/pmic.h>
11#include <power/regulator.h>
12#include <regmap.h>
13#include <syscon.h>
14#include <linux/bitops.h>
15#include <linux/ioport.h>
16#include <dm/read.h>
17
Jean-Jacques Hiblot4612bdd2017-09-21 17:03:10 +020018struct pbias_reg_info {
19 u32 enable;
20 u32 enable_mask;
21 u32 disable_val;
22 u32 vmode;
23 unsigned int enable_time;
24 char *name;
25};
26
27struct pbias_priv {
28 struct regmap *regmap;
29 int offset;
30};
31
32static const struct pmic_child_info pmic_children_info[] = {
33 { .prefix = "pbias", .driver = "pbias_regulator"},
34 { },
35};
36
37static int pbias_write(struct udevice *dev, uint reg, const uint8_t *buff,
38 int len)
39{
40 struct pbias_priv *priv = dev_get_priv(dev);
41 u32 val = *(u32 *)buff;
42
43 if (len != 4)
44 return -EINVAL;
45
46 return regmap_write(priv->regmap, priv->offset, val);
47}
48
49static int pbias_read(struct udevice *dev, uint reg, uint8_t *buff, int len)
50{
51 struct pbias_priv *priv = dev_get_priv(dev);
52
53 if (len != 4)
54 return -EINVAL;
55
56 return regmap_read(priv->regmap, priv->offset, (u32 *)buff);
57}
58
59static int pbias_ofdata_to_platdata(struct udevice *dev)
60{
61 struct pbias_priv *priv = dev_get_priv(dev);
62 struct udevice *syscon;
63 struct regmap *regmap;
64 struct resource res;
65 int err;
66
67 err = uclass_get_device_by_phandle(UCLASS_SYSCON, dev,
68 "syscon", &syscon);
69 if (err) {
Masahiro Yamada81e10422017-09-16 14:10:41 +090070 pr_err("%s: unable to find syscon device (%d)\n", __func__,
Jean-Jacques Hiblot4612bdd2017-09-21 17:03:10 +020071 err);
72 return err;
73 }
74
75 regmap = syscon_get_regmap(syscon);
76 if (IS_ERR(regmap)) {
Masahiro Yamada81e10422017-09-16 14:10:41 +090077 pr_err("%s: unable to find regmap (%ld)\n", __func__,
Jean-Jacques Hiblot4612bdd2017-09-21 17:03:10 +020078 PTR_ERR(regmap));
79 return PTR_ERR(regmap);
80 }
81 priv->regmap = regmap;
82
83 err = dev_read_resource(dev, 0, &res);
84 if (err) {
Masahiro Yamada81e10422017-09-16 14:10:41 +090085 pr_err("%s: unable to find offset (%d)\n", __func__, err);
Jean-Jacques Hiblot4612bdd2017-09-21 17:03:10 +020086 return err;
87 }
88 priv->offset = res.start;
89
90 return 0;
91}
92
93static int pbias_bind(struct udevice *dev)
94{
95 int children;
96
97 children = pmic_bind_children(dev, dev->node, pmic_children_info);
98 if (!children)
99 debug("%s: %s - no child found\n", __func__, dev->name);
100
101 return 0;
102}
103
104static struct dm_pmic_ops pbias_ops = {
105 .read = pbias_read,
106 .write = pbias_write,
107};
108
109static const struct udevice_id pbias_ids[] = {
110 { .compatible = "ti,pbias-dra7" },
111 { }
112};
113
114U_BOOT_DRIVER(pbias_pmic) = {
115 .name = "pbias_pmic",
116 .id = UCLASS_PMIC,
117 .of_match = pbias_ids,
118 .bind = pbias_bind,
119 .ops = &pbias_ops,
120 .ofdata_to_platdata = pbias_ofdata_to_platdata,
121 .priv_auto_alloc_size = sizeof(struct pbias_priv),
122};
123
124static const struct pbias_reg_info pbias_mmc_omap2430 = {
125 .enable = BIT(1),
126 .enable_mask = BIT(1),
127 .vmode = BIT(0),
128 .disable_val = 0,
129 .enable_time = 100,
130 .name = "pbias_mmc_omap2430"
131};
132
133static const struct pbias_reg_info pbias_sim_omap3 = {
134 .enable = BIT(9),
135 .enable_mask = BIT(9),
136 .vmode = BIT(8),
137 .enable_time = 100,
138 .name = "pbias_sim_omap3"
139};
140
141static const struct pbias_reg_info pbias_mmc_omap4 = {
142 .enable = BIT(26) | BIT(22),
143 .enable_mask = BIT(26) | BIT(25) | BIT(22),
144 .disable_val = BIT(25),
145 .vmode = BIT(21),
146 .enable_time = 100,
147 .name = "pbias_mmc_omap4"
148};
149
150static const struct pbias_reg_info pbias_mmc_omap5 = {
151 .enable = BIT(27) | BIT(26),
152 .enable_mask = BIT(27) | BIT(25) | BIT(26),
153 .disable_val = BIT(25),
154 .vmode = BIT(21),
155 .enable_time = 100,
156 .name = "pbias_mmc_omap5"
157};
158
159static const struct pbias_reg_info *pbias_reg_infos[] = {
160 &pbias_mmc_omap5,
161 &pbias_mmc_omap4,
162 &pbias_sim_omap3,
163 &pbias_mmc_omap2430,
164 NULL
165};
166
167static int pbias_regulator_probe(struct udevice *dev)
168{
169 const struct pbias_reg_info **p = pbias_reg_infos;
170 struct dm_regulator_uclass_platdata *uc_pdata;
171
172 uc_pdata = dev_get_uclass_platdata(dev);
173
174 while (*p) {
175 int rc;
176
177 rc = dev_read_stringlist_search(dev, "regulator-name",
178 (*p)->name);
179 if (rc >= 0) {
180 debug("found regulator %s\n", (*p)->name);
181 break;
182 } else if (rc != -ENODATA) {
183 return rc;
184 }
185 p++;
186 }
187 if (!*p) {
188 int i = 0;
189 const char *s;
190
191 debug("regulator ");
192 while (dev_read_string_index(dev, "regulator-name", i++, &s) >= 0)
193 debug("%s'%s' ", (i > 1) ? ", " : "", s);
194 debug("%s not supported\n", (i > 2) ? "are" : "is");
195 return -EINVAL;
196 }
197
198 uc_pdata->type = REGULATOR_TYPE_OTHER;
199 dev->priv = (void *)*p;
200
201 return 0;
202}
203
204static int pbias_regulator_get_value(struct udevice *dev)
205{
206 const struct pbias_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 debug("%s voltage id %s\n", p->name,
215 (reg & p->vmode) ? "3.0v" : "1.8v");
216 return (reg & p->vmode) ? 3000000 : 1800000;
217}
218
219static int pbias_regulator_set_value(struct udevice *dev, int uV)
220{
221 const struct pbias_reg_info *p = dev_get_priv(dev);
222 int rc;
223 u32 reg;
224
Jean-Jacques Hiblot4612bdd2017-09-21 17:03:10 +0200225 rc = pmic_read(dev->parent, 0, (uint8_t *)&reg, sizeof(reg));
226 if (rc)
227 return rc;
228
229 if (uV == 3000000)
230 reg |= p->vmode;
231 else if (uV == 1800000)
232 reg &= ~p->vmode;
233 else
234 return -EINVAL;
235
Heinrich Schuchardtdfe81982018-03-18 12:01:06 +0100236 debug("Setting %s voltage to %s\n", p->name,
237 (reg & p->vmode) ? "3.0v" : "1.8v");
238
Jean-Jacques Hiblot4612bdd2017-09-21 17:03:10 +0200239 return pmic_write(dev->parent, 0, (uint8_t *)&reg, sizeof(reg));
240}
241
242static int pbias_regulator_get_enable(struct udevice *dev)
243{
244 const struct pbias_reg_info *p = dev_get_priv(dev);
245 int rc;
246 u32 reg;
247
248 rc = pmic_read(dev->parent, 0, (uint8_t *)&reg, sizeof(reg));
249 if (rc)
250 return rc;
251
252 debug("%s id %s\n", p->name,
253 (reg & p->enable_mask) == (p->disable_val) ? "on" : "off");
254
255 return (reg & p->enable_mask) == (p->disable_val);
256}
257
258static int pbias_regulator_set_enable(struct udevice *dev, bool enable)
259{
260 const struct pbias_reg_info *p = dev_get_priv(dev);
261 int rc;
262 u32 reg;
263
264 debug("Turning %s %s\n", enable ? "on" : "off", p->name);
265
266 rc = pmic_read(dev->parent, 0, (uint8_t *)&reg, sizeof(reg));
267 if (rc)
268 return rc;
269
270 reg &= ~p->enable_mask;
271 if (enable)
272 reg |= p->enable;
273 else
274 reg |= p->disable_val;
275
276 rc = pmic_write(dev->parent, 0, (uint8_t *)&reg, sizeof(reg));
277 if (rc)
278 return rc;
279
280 if (enable)
281 udelay(p->enable_time);
282
283 return 0;
284}
285
286static const struct dm_regulator_ops pbias_regulator_ops = {
287 .get_value = pbias_regulator_get_value,
288 .set_value = pbias_regulator_set_value,
289 .get_enable = pbias_regulator_get_enable,
290 .set_enable = pbias_regulator_set_enable,
291};
292
293U_BOOT_DRIVER(pbias_regulator) = {
294 .name = "pbias_regulator",
295 .id = UCLASS_REGULATOR,
296 .ops = &pbias_regulator_ops,
297 .probe = pbias_regulator_probe,
298};