blob: 824a753db16122c16dcc1ac1fa3fc940a06fa543 [file] [log] [blame]
Ying-Chun Liu (PaulLiu)cd6425a2021-03-27 21:46:51 +08001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
4 * Copyright (C) 2021 Linaro
5 */
6
Ying-Chun Liu (PaulLiu)cd6425a2021-03-27 21:46:51 +08007#include <dm.h>
8#include <errno.h>
9#include <log.h>
10#include <regmap.h>
11#include <syscon.h>
12#include <dm/device-internal.h>
13#include <dm/device_compat.h>
14#include <linux/bitops.h>
15#include <linux/delay.h>
16#include <linux/err.h>
17#include <linux/ioport.h>
18#include <power/pmic.h>
19#include <power/regulator.h>
20
21#define LDO_RAMP_UP_UNIT_IN_CYCLES 64 /* 64 cycles per step */
22#define LDO_RAMP_UP_FREQ_IN_MHZ 24 /* cycle based on 24M OSC */
23
24#define LDO_POWER_GATE 0x00
25#define LDO_FET_FULL_ON 0x1f
26
27#define BIT_WIDTH_MAX 32
28
29#define ANATOP_REGULATOR_STEP 25000
30#define MIN_DROPOUT_UV 125000
31
32struct anatop_regulator {
33 const char *name;
34 struct regmap *regmap;
35 struct udevice *supply;
36 u32 control_reg;
37 u32 vol_bit_shift;
38 u32 vol_bit_width;
39 u32 min_bit_val;
40 u32 min_voltage;
41 u32 max_voltage;
42 u32 delay_reg;
43 u32 delay_bit_shift;
44 u32 delay_bit_width;
45};
46
47static u32 anatop_get_bits(struct udevice *dev, u32 addr, int bit_shift,
48 int bit_width)
49{
50 const struct anatop_regulator *anatop_reg = dev_get_plat(dev);
51 int err;
52 u32 val, mask;
53
54 if (bit_width == BIT_WIDTH_MAX)
55 mask = ~0;
56 else
57 mask = (1 << bit_width) - 1;
58
59 err = regmap_read(anatop_reg->regmap, addr, &val);
60 if (err) {
61 dev_dbg(dev, "cannot read reg (%d)\n", err);
62 return err;
63 }
64
65 val = (val >> bit_shift) & mask;
66
67 return val;
68}
69
70static int anatop_set_bits(struct udevice *dev, u32 addr, int bit_shift,
71 int bit_width, u32 data)
72{
73 const struct anatop_regulator *anatop_reg = dev_get_plat(dev);
74 int err;
75 u32 val, mask;
76
77 if (bit_width == 32)
78 mask = ~0;
79 else
80 mask = (1 << bit_width) - 1;
81
82 err = regmap_read(anatop_reg->regmap, addr, &val);
83 if (err) {
84 dev_dbg(dev, "cannot read reg (%d)\n", err);
85 return err;
86 }
87 val = val & ~(mask << bit_shift);
88 err = regmap_write(anatop_reg->regmap,
89 addr, (data << bit_shift) | val);
90 if (err) {
91 dev_dbg(dev, "cannot write reg (%d)\n", err);
92 return err;
93 }
94
95 return 0;
96}
97
98static int anatop_get_voltage(struct udevice *dev)
99{
100 const struct anatop_regulator *anatop_reg = dev_get_plat(dev);
101 u32 sel;
102 u32 val;
103
104 if (!anatop_reg->control_reg)
105 return -ENOSYS;
106
107 val = anatop_get_bits(dev,
108 anatop_reg->control_reg,
109 anatop_reg->vol_bit_shift,
110 anatop_reg->vol_bit_width);
111
112 sel = val - anatop_reg->min_bit_val;
113
114 return sel * ANATOP_REGULATOR_STEP + anatop_reg->min_voltage;
115}
116
117static int anatop_set_voltage(struct udevice *dev, int uV)
118{
119 const struct anatop_regulator *anatop_reg = dev_get_plat(dev);
120 u32 val;
121 u32 sel;
122 int ret;
123
124 dev_dbg(dev, "uv %d, min %d, max %d\n", uV, anatop_reg->min_voltage,
125 anatop_reg->max_voltage);
126
127 if (uV < anatop_reg->min_voltage)
128 return -EINVAL;
129
130 if (!anatop_reg->control_reg)
131 return -ENOSYS;
132
133 sel = DIV_ROUND_UP(uV - anatop_reg->min_voltage,
134 ANATOP_REGULATOR_STEP);
135 if (sel * ANATOP_REGULATOR_STEP + anatop_reg->min_voltage >
136 anatop_reg->max_voltage)
137 return -EINVAL;
138 val = anatop_reg->min_bit_val + sel;
139 dev_dbg(dev, "calculated val %d\n", val);
140
141 if (anatop_reg->supply) {
142 ret = regulator_set_value(anatop_reg->supply,
143 uV + MIN_DROPOUT_UV);
144 if (ret)
145 return ret;
146 }
147
148 ret = anatop_set_bits(dev,
149 anatop_reg->control_reg,
150 anatop_reg->vol_bit_shift,
151 anatop_reg->vol_bit_width,
152 val);
153
154 return ret;
155}
156
157static const struct dm_regulator_ops anatop_regulator_ops = {
158 .set_value = anatop_set_voltage,
159 .get_value = anatop_get_voltage,
160};
161
162static int anatop_regulator_probe(struct udevice *dev)
163{
164 struct anatop_regulator *anatop_reg;
165 struct dm_regulator_uclass_plat *uc_pdata;
166 struct udevice *syscon;
167 int ret = 0;
168 u32 val;
169
170 anatop_reg = dev_get_plat(dev);
171 uc_pdata = dev_get_uclass_plat(dev);
172
173 anatop_reg->name = ofnode_read_string(dev_ofnode(dev),
174 "regulator-name");
175 if (!anatop_reg->name)
176 return log_msg_ret("regulator-name", -EINVAL);
177
178 ret = device_get_supply_regulator(dev, "vin-supply",
179 &anatop_reg->supply);
180 if (ret != -ENODEV) {
181 if (ret)
182 return log_msg_ret("get vin-supply", ret);
183
184 ret = regulator_set_enable(anatop_reg->supply, true);
185 if (ret)
186 return ret;
187 }
188
189 ret = dev_read_u32(dev,
190 "anatop-reg-offset",
191 &anatop_reg->control_reg);
192 if (ret)
193 return log_msg_ret("anatop-reg-offset", ret);
194
195 ret = dev_read_u32(dev,
196 "anatop-vol-bit-width",
197 &anatop_reg->vol_bit_width);
198 if (ret)
199 return log_msg_ret("anatop-vol-bit-width", ret);
200
201 ret = dev_read_u32(dev,
202 "anatop-vol-bit-shift",
203 &anatop_reg->vol_bit_shift);
204 if (ret)
205 return log_msg_ret("anatop-vol-bit-shift", ret);
206
207 ret = dev_read_u32(dev,
208 "anatop-min-bit-val",
209 &anatop_reg->min_bit_val);
210 if (ret)
211 return log_msg_ret("anatop-min-bit-val", ret);
212
213 ret = dev_read_u32(dev,
214 "anatop-min-voltage",
215 &anatop_reg->min_voltage);
216 if (ret)
217 return log_msg_ret("anatop-min-voltage", ret);
218
219 ret = dev_read_u32(dev,
220 "anatop-max-voltage",
221 &anatop_reg->max_voltage);
222 if (ret)
223 return log_msg_ret("anatop-max-voltage", ret);
224
225 /* read LDO ramp up setting, only for core reg */
226 dev_read_u32(dev, "anatop-delay-reg-offset",
227 &anatop_reg->delay_reg);
228 dev_read_u32(dev, "anatop-delay-bit-width",
229 &anatop_reg->delay_bit_width);
230 dev_read_u32(dev, "anatop-delay-bit-shift",
231 &anatop_reg->delay_bit_shift);
232
233 syscon = dev_get_parent(dev);
234 if (!syscon) {
235 dev_dbg(dev, "unable to find syscon device\n");
236 return -ENOENT;
237 }
238
239 anatop_reg->regmap = syscon_get_regmap(syscon);
240 if (IS_ERR(anatop_reg->regmap)) {
241 dev_dbg(dev, "unable to find regmap (%ld)\n",
242 PTR_ERR(anatop_reg->regmap));
243 return -ENOENT;
244 }
245
246 /* check whether need to care about LDO ramp up speed */
247 if (anatop_reg->delay_bit_width) {
248 /*
249 * the delay for LDO ramp up time is
250 * based on the register setting, we need
251 * to calculate how many steps LDO need to
252 * ramp up, and how much delay needed. (us)
253 */
254 val = anatop_get_bits(dev,
255 anatop_reg->delay_reg,
256 anatop_reg->delay_bit_shift,
257 anatop_reg->delay_bit_width);
258 uc_pdata->ramp_delay = (LDO_RAMP_UP_UNIT_IN_CYCLES << val)
259 / LDO_RAMP_UP_FREQ_IN_MHZ + 1;
260 }
261
262 return 0;
263}
264
265static const struct udevice_id of_anatop_regulator_match_tbl[] = {
266 { .compatible = "fsl,anatop-regulator", },
267 { /* end */ }
268};
269
270U_BOOT_DRIVER(anatop_regulator) = {
271 .name = "anatop_regulator",
272 .id = UCLASS_REGULATOR,
273 .ops = &anatop_regulator_ops,
274 .of_match = of_anatop_regulator_match_tbl,
275 .plat_auto = sizeof(struct anatop_regulator),
276 .probe = anatop_regulator_probe,
277};