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