1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0+ */
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * (C) Copyright 2018 Rockchip Electronics Co., Ltd
4*4882a593Smuzhiyun */
5*4882a593Smuzhiyun
6*4882a593Smuzhiyun #include <common.h>
7*4882a593Smuzhiyun #include <dm.h>
8*4882a593Smuzhiyun #include <dm/of_access.h>
9*4882a593Smuzhiyun #include <regmap.h>
10*4882a593Smuzhiyun #include <syscon.h>
11*4882a593Smuzhiyun #include <asm/arch/clock.h>
12*4882a593Smuzhiyun #include <fdtdec.h>
13*4882a593Smuzhiyun #include <linux/compat.h>
14*4882a593Smuzhiyun #include <linux/err.h>
15*4882a593Smuzhiyun #include <power/regulator.h>
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun #define MAX_SUPPLIES 16
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun /*
20*4882a593Smuzhiyun * The max voltage for 1.8V and 3.3V come from the Rockchip datasheet under
21*4882a593Smuzhiyun * "Recommended Operating Conditions" for "Digital GPIO". When the typical
22*4882a593Smuzhiyun * is 3.3V the max is 3.6V. When the typical is 1.8V the max is 1.98V.
23*4882a593Smuzhiyun *
24*4882a593Smuzhiyun * They are used like this:
25*4882a593Smuzhiyun * - If the voltage on a rail is above the "1.8" voltage (1.98V) we'll tell the
26*4882a593Smuzhiyun * SoC we're at 3.3.
27*4882a593Smuzhiyun * - If the voltage on a rail is above the "3.3" voltage (3.6V) we'll consider
28*4882a593Smuzhiyun * that to be an error.
29*4882a593Smuzhiyun */
30*4882a593Smuzhiyun #define MAX_VOLTAGE_1_8 1980000
31*4882a593Smuzhiyun #define MAX_VOLTAGE_3_3 3600000
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun #define PX30_IO_VSEL 0x180
34*4882a593Smuzhiyun #define PX30_IO_VSEL_VCCIO6_SRC BIT(0)
35*4882a593Smuzhiyun #define PX30_IO_VSEL_VCCIO6_SUPPLY_NUM 1
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun #define RK3288_SOC_CON2 0x24c
38*4882a593Smuzhiyun #define RK3288_SOC_CON2_FLASH0 BIT(7)
39*4882a593Smuzhiyun #define RK3288_SOC_FLASH_SUPPLY_NUM 2
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun #define RK3308_SOC_CON0 0x300
42*4882a593Smuzhiyun #define RK3308_SOC_CON0_VCCIO3 BIT(8)
43*4882a593Smuzhiyun #define RK3308_SOC_VCCIO3_SUPPLY_NUM 3
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun #define RK3328_SOC_CON4 0x410
46*4882a593Smuzhiyun #define RK3328_SOC_CON4_VCCIO2 BIT(7)
47*4882a593Smuzhiyun #define RK3328_SOC_VCCIO2_SUPPLY_NUM 1
48*4882a593Smuzhiyun
49*4882a593Smuzhiyun #define RK3366_SOC_CON6 0x418
50*4882a593Smuzhiyun #define RK3366_SOC_CON6_FLASH0 BIT(14)
51*4882a593Smuzhiyun #define RK3366_SOC_FLASH_SUPPLY_NUM 2
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun #define RK3368_SOC_CON15 0x43c
54*4882a593Smuzhiyun #define RK3368_SOC_CON15_FLASH0 BIT(14)
55*4882a593Smuzhiyun #define RK3368_SOC_FLASH_SUPPLY_NUM 2
56*4882a593Smuzhiyun
57*4882a593Smuzhiyun #define RK3399_PMUGRF_CON0 0x180
58*4882a593Smuzhiyun #define RK3399_PMUGRF_CON0_VSEL BIT(8)
59*4882a593Smuzhiyun #define RK3399_PMUGRF_VSEL_SUPPLY_NUM 9
60*4882a593Smuzhiyun
61*4882a593Smuzhiyun #define RK3568_PMU_GRF_IO_VSEL0 (0x0140)
62*4882a593Smuzhiyun #define RK3568_PMU_GRF_IO_VSEL1 (0x0144)
63*4882a593Smuzhiyun #define RK3568_PMU_GRF_IO_VSEL2 (0x0148)
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun #define RV1126_PMU_GRF_IO_RETENTION (0x0144)
66*4882a593Smuzhiyun
67*4882a593Smuzhiyun struct rockchip_iodomain_priv;
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun /**
70*4882a593Smuzhiyun * @supplies: voltage settings matching the register bits.
71*4882a593Smuzhiyun */
72*4882a593Smuzhiyun struct rockchip_iodomain_soc_data {
73*4882a593Smuzhiyun int grf_offset;
74*4882a593Smuzhiyun const char *supply_names[MAX_SUPPLIES];
75*4882a593Smuzhiyun void (*init)(struct rockchip_iodomain_priv *iod);
76*4882a593Smuzhiyun };
77*4882a593Smuzhiyun
78*4882a593Smuzhiyun struct rockchip_iodomain_supply {
79*4882a593Smuzhiyun struct rockchip_iodomain_priv *iod;
80*4882a593Smuzhiyun struct udevice *reg;
81*4882a593Smuzhiyun int idx;
82*4882a593Smuzhiyun };
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun struct rockchip_iodomain_priv {
85*4882a593Smuzhiyun struct regmap *regmap_base;
86*4882a593Smuzhiyun struct rockchip_iodomain_soc_data *sdata;
87*4882a593Smuzhiyun struct rockchip_iodomain_supply supplies[MAX_SUPPLIES];
88*4882a593Smuzhiyun int (*write)(struct rockchip_iodomain_supply *supply, int uV);
89*4882a593Smuzhiyun };
90*4882a593Smuzhiyun
rockchip_ofdata_to_platdata(struct udevice * dev)91*4882a593Smuzhiyun static int rockchip_ofdata_to_platdata(struct udevice *dev)
92*4882a593Smuzhiyun {
93*4882a593Smuzhiyun struct rockchip_iodomain_priv *priv = dev_get_priv(dev);
94*4882a593Smuzhiyun struct syscon_uc_info *syscon_priv;
95*4882a593Smuzhiyun struct regmap *regmap;
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun syscon_priv = dev_get_uclass_priv(dev_get_parent(dev));
98*4882a593Smuzhiyun regmap = syscon_priv->regmap;
99*4882a593Smuzhiyun if (IS_ERR(regmap))
100*4882a593Smuzhiyun return PTR_ERR(regmap);
101*4882a593Smuzhiyun
102*4882a593Smuzhiyun priv->regmap_base = regmap;
103*4882a593Smuzhiyun
104*4882a593Smuzhiyun return 0;
105*4882a593Smuzhiyun }
106*4882a593Smuzhiyun
rk3568_pmu_iodomain_write(struct rockchip_iodomain_supply * supply,int uV)107*4882a593Smuzhiyun static int rk3568_pmu_iodomain_write(struct rockchip_iodomain_supply *supply,
108*4882a593Smuzhiyun int uV)
109*4882a593Smuzhiyun {
110*4882a593Smuzhiyun struct rockchip_iodomain_priv *priv = supply->iod;
111*4882a593Smuzhiyun struct regmap *regmap = priv->regmap_base;
112*4882a593Smuzhiyun u32 is_3v3 = uV > MAX_VOLTAGE_1_8;
113*4882a593Smuzhiyun u32 val0, val1;
114*4882a593Smuzhiyun int b;
115*4882a593Smuzhiyun
116*4882a593Smuzhiyun switch (supply->idx) {
117*4882a593Smuzhiyun case 0: /* pmuio1 */
118*4882a593Smuzhiyun case 1: /* pmuio2 */
119*4882a593Smuzhiyun b = supply->idx;
120*4882a593Smuzhiyun val0 = BIT(16 + b) | (is_3v3 ? 0 : BIT(b));
121*4882a593Smuzhiyun b = supply->idx + 4;
122*4882a593Smuzhiyun val1 = BIT(16 + b) | (is_3v3 ? BIT(b) : 0);
123*4882a593Smuzhiyun
124*4882a593Smuzhiyun regmap_write(regmap, RK3568_PMU_GRF_IO_VSEL2, val0);
125*4882a593Smuzhiyun regmap_write(regmap, RK3568_PMU_GRF_IO_VSEL2, val1);
126*4882a593Smuzhiyun break;
127*4882a593Smuzhiyun case 2: /* vccio1 */
128*4882a593Smuzhiyun case 3: /* vccio2 */
129*4882a593Smuzhiyun case 4: /* vccio3 */
130*4882a593Smuzhiyun case 5: /* vccio4 */
131*4882a593Smuzhiyun case 6: /* vccio5 */
132*4882a593Smuzhiyun case 7: /* vccio6 */
133*4882a593Smuzhiyun case 8: /* vccio7 */
134*4882a593Smuzhiyun b = supply->idx - 1;
135*4882a593Smuzhiyun val0 = BIT(16 + b) | (is_3v3 ? 0 : BIT(b));
136*4882a593Smuzhiyun val1 = BIT(16 + b) | (is_3v3 ? BIT(b) : 0);
137*4882a593Smuzhiyun
138*4882a593Smuzhiyun regmap_write(regmap, RK3568_PMU_GRF_IO_VSEL0, val0);
139*4882a593Smuzhiyun regmap_write(regmap, RK3568_PMU_GRF_IO_VSEL1, val1);
140*4882a593Smuzhiyun break;
141*4882a593Smuzhiyun default:
142*4882a593Smuzhiyun return -EINVAL;
143*4882a593Smuzhiyun };
144*4882a593Smuzhiyun
145*4882a593Smuzhiyun return 0;
146*4882a593Smuzhiyun }
147*4882a593Smuzhiyun
rv1126_iodomain_write(struct rockchip_iodomain_supply * supply,int uV)148*4882a593Smuzhiyun static int rv1126_iodomain_write(struct rockchip_iodomain_supply *supply,
149*4882a593Smuzhiyun int uV)
150*4882a593Smuzhiyun {
151*4882a593Smuzhiyun struct rockchip_iodomain_priv *priv = supply->iod;
152*4882a593Smuzhiyun struct regmap *regmap = priv->regmap_base;
153*4882a593Smuzhiyun u32 val, vret_hold, vret_release;
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun /* set value bit */
156*4882a593Smuzhiyun val = (uV > MAX_VOLTAGE_1_8) ? 0 : 1;
157*4882a593Smuzhiyun val <<= supply->idx;
158*4882a593Smuzhiyun /* apply hiword-mask */
159*4882a593Smuzhiyun val |= (BIT(supply->idx) << 16);
160*4882a593Smuzhiyun
161*4882a593Smuzhiyun vret_hold = (BIT(supply->idx) << 16);
162*4882a593Smuzhiyun vret_release = (BIT(supply->idx) << 16) | BIT(supply->idx);
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun printf("%s: %d uv, vsel: 0x%x\n",
165*4882a593Smuzhiyun priv->sdata->supply_names[supply->idx], uV, val);
166*4882a593Smuzhiyun
167*4882a593Smuzhiyun regmap_write(regmap, RV1126_PMU_GRF_IO_RETENTION, vret_hold);
168*4882a593Smuzhiyun regmap_write(regmap, priv->sdata->grf_offset, val);
169*4882a593Smuzhiyun regmap_write(regmap, RV1126_PMU_GRF_IO_RETENTION, vret_release);
170*4882a593Smuzhiyun
171*4882a593Smuzhiyun return 0;
172*4882a593Smuzhiyun }
173*4882a593Smuzhiyun
rockchip_iodomain_write(struct rockchip_iodomain_supply * supply,int uV)174*4882a593Smuzhiyun static int rockchip_iodomain_write(struct rockchip_iodomain_supply *supply,
175*4882a593Smuzhiyun int uV)
176*4882a593Smuzhiyun {
177*4882a593Smuzhiyun struct rockchip_iodomain_priv *priv = supply->iod;
178*4882a593Smuzhiyun struct regmap *regmap = priv->regmap_base;
179*4882a593Smuzhiyun u32 val;
180*4882a593Smuzhiyun int ret;
181*4882a593Smuzhiyun
182*4882a593Smuzhiyun /* set value bit */
183*4882a593Smuzhiyun val = (uV > MAX_VOLTAGE_1_8) ? 0 : 1;
184*4882a593Smuzhiyun val <<= supply->idx;
185*4882a593Smuzhiyun
186*4882a593Smuzhiyun /* apply hiword-mask */
187*4882a593Smuzhiyun val |= (BIT(supply->idx) << 16);
188*4882a593Smuzhiyun
189*4882a593Smuzhiyun ret = regmap_write(regmap, priv->sdata->grf_offset, val);
190*4882a593Smuzhiyun if (ret) {
191*4882a593Smuzhiyun dev_err(priv->dev, "Couldn't write to GRF\n");
192*4882a593Smuzhiyun return ret;
193*4882a593Smuzhiyun }
194*4882a593Smuzhiyun
195*4882a593Smuzhiyun return 0;
196*4882a593Smuzhiyun }
197*4882a593Smuzhiyun
px30_iodomain_init(struct rockchip_iodomain_priv * iod)198*4882a593Smuzhiyun static void px30_iodomain_init(struct rockchip_iodomain_priv *iod)
199*4882a593Smuzhiyun {
200*4882a593Smuzhiyun int ret;
201*4882a593Smuzhiyun u32 val;
202*4882a593Smuzhiyun
203*4882a593Smuzhiyun /* if no VCCIO0 supply we should leave things alone */
204*4882a593Smuzhiyun if (!iod->supplies[PX30_IO_VSEL_VCCIO6_SUPPLY_NUM].reg)
205*4882a593Smuzhiyun return;
206*4882a593Smuzhiyun
207*4882a593Smuzhiyun /*
208*4882a593Smuzhiyun * set vccio0 iodomain to also use this framework
209*4882a593Smuzhiyun * instead of a special gpio.
210*4882a593Smuzhiyun */
211*4882a593Smuzhiyun val = PX30_IO_VSEL_VCCIO6_SRC | (PX30_IO_VSEL_VCCIO6_SRC << 16);
212*4882a593Smuzhiyun ret = regmap_write(iod->regmap_base, PX30_IO_VSEL, val);
213*4882a593Smuzhiyun if (ret < 0)
214*4882a593Smuzhiyun dev_warn(iod->dev, "couldn't update vccio0 ctrl\n");
215*4882a593Smuzhiyun }
216*4882a593Smuzhiyun
rk3288_iodomain_init(struct rockchip_iodomain_priv * iod)217*4882a593Smuzhiyun static void rk3288_iodomain_init(struct rockchip_iodomain_priv *iod)
218*4882a593Smuzhiyun {
219*4882a593Smuzhiyun int ret;
220*4882a593Smuzhiyun u32 val;
221*4882a593Smuzhiyun
222*4882a593Smuzhiyun /* if no flash supply we should leave things alone */
223*4882a593Smuzhiyun if (!iod->supplies[RK3288_SOC_FLASH_SUPPLY_NUM].reg)
224*4882a593Smuzhiyun return;
225*4882a593Smuzhiyun
226*4882a593Smuzhiyun /*
227*4882a593Smuzhiyun * set flash0 iodomain to also use this framework
228*4882a593Smuzhiyun * instead of a special gpio.
229*4882a593Smuzhiyun */
230*4882a593Smuzhiyun val = RK3288_SOC_CON2_FLASH0 | (RK3288_SOC_CON2_FLASH0 << 16);
231*4882a593Smuzhiyun ret = regmap_write(iod->regmap_base, RK3288_SOC_CON2, val);
232*4882a593Smuzhiyun if (ret < 0)
233*4882a593Smuzhiyun dev_warn(iod->dev, "couldn't update flash0 ctrl\n");
234*4882a593Smuzhiyun }
235*4882a593Smuzhiyun
rk3308_iodomain_init(struct rockchip_iodomain_priv * iod)236*4882a593Smuzhiyun static void rk3308_iodomain_init(struct rockchip_iodomain_priv *iod)
237*4882a593Smuzhiyun {
238*4882a593Smuzhiyun int ret;
239*4882a593Smuzhiyun u32 val;
240*4882a593Smuzhiyun
241*4882a593Smuzhiyun /* if no vccio3 supply we should leave things alone */
242*4882a593Smuzhiyun if (!iod->supplies[RK3308_SOC_VCCIO3_SUPPLY_NUM].reg)
243*4882a593Smuzhiyun return;
244*4882a593Smuzhiyun
245*4882a593Smuzhiyun /*
246*4882a593Smuzhiyun * set vccio3 iodomain to also use this framework
247*4882a593Smuzhiyun * instead of a special gpio.
248*4882a593Smuzhiyun */
249*4882a593Smuzhiyun val = RK3308_SOC_CON0_VCCIO3 | (RK3308_SOC_CON0_VCCIO3 << 16);
250*4882a593Smuzhiyun ret = regmap_write(iod->regmap_base, RK3308_SOC_CON0, val);
251*4882a593Smuzhiyun if (ret < 0)
252*4882a593Smuzhiyun dev_warn(iod->dev, "couldn't update vccio3 vsel ctrl\n");
253*4882a593Smuzhiyun }
254*4882a593Smuzhiyun
rk3328_iodomain_init(struct rockchip_iodomain_priv * iod)255*4882a593Smuzhiyun static void rk3328_iodomain_init(struct rockchip_iodomain_priv *iod)
256*4882a593Smuzhiyun {
257*4882a593Smuzhiyun int ret;
258*4882a593Smuzhiyun u32 val;
259*4882a593Smuzhiyun
260*4882a593Smuzhiyun /* if no vccio2 supply we should leave things alone */
261*4882a593Smuzhiyun if (!iod->supplies[RK3328_SOC_VCCIO2_SUPPLY_NUM].reg)
262*4882a593Smuzhiyun return;
263*4882a593Smuzhiyun
264*4882a593Smuzhiyun /*
265*4882a593Smuzhiyun * set vccio2 iodomain to also use this framework
266*4882a593Smuzhiyun * instead of a special gpio.
267*4882a593Smuzhiyun */
268*4882a593Smuzhiyun val = RK3328_SOC_CON4_VCCIO2 | (RK3328_SOC_CON4_VCCIO2 << 16);
269*4882a593Smuzhiyun ret = regmap_write(iod->regmap_base, RK3328_SOC_CON4, val);
270*4882a593Smuzhiyun if (ret < 0)
271*4882a593Smuzhiyun dev_warn(iod->dev, "couldn't update vccio2 vsel ctrl\n");
272*4882a593Smuzhiyun }
273*4882a593Smuzhiyun
rk3366_iodomain_init(struct rockchip_iodomain_priv * iod)274*4882a593Smuzhiyun static void rk3366_iodomain_init(struct rockchip_iodomain_priv *iod)
275*4882a593Smuzhiyun {
276*4882a593Smuzhiyun int ret;
277*4882a593Smuzhiyun u32 val;
278*4882a593Smuzhiyun
279*4882a593Smuzhiyun /* if no flash supply we should leave things alone */
280*4882a593Smuzhiyun if (!iod->supplies[RK3366_SOC_FLASH_SUPPLY_NUM].reg)
281*4882a593Smuzhiyun return;
282*4882a593Smuzhiyun
283*4882a593Smuzhiyun /*
284*4882a593Smuzhiyun * set flash0 iodomain to also use this framework
285*4882a593Smuzhiyun * instead of a special gpio.
286*4882a593Smuzhiyun */
287*4882a593Smuzhiyun val = RK3366_SOC_CON6_FLASH0 | (RK3366_SOC_CON6_FLASH0 << 16);
288*4882a593Smuzhiyun ret = regmap_write(iod->regmap_base, RK3368_SOC_CON15, val);
289*4882a593Smuzhiyun if (ret < 0)
290*4882a593Smuzhiyun dev_warn(iod->dev, "couldn't update flash0 ctrl\n");
291*4882a593Smuzhiyun }
292*4882a593Smuzhiyun
rk3368_iodomain_init(struct rockchip_iodomain_priv * iod)293*4882a593Smuzhiyun static void rk3368_iodomain_init(struct rockchip_iodomain_priv *iod)
294*4882a593Smuzhiyun {
295*4882a593Smuzhiyun int ret;
296*4882a593Smuzhiyun u32 val;
297*4882a593Smuzhiyun
298*4882a593Smuzhiyun /* if no flash supply we should leave things alone */
299*4882a593Smuzhiyun if (!iod->supplies[RK3368_SOC_FLASH_SUPPLY_NUM].reg)
300*4882a593Smuzhiyun return;
301*4882a593Smuzhiyun
302*4882a593Smuzhiyun /*
303*4882a593Smuzhiyun * set flash0 iodomain to also use this framework
304*4882a593Smuzhiyun * instead of a special gpio.
305*4882a593Smuzhiyun */
306*4882a593Smuzhiyun val = RK3368_SOC_CON15_FLASH0 | (RK3368_SOC_CON15_FLASH0 << 16);
307*4882a593Smuzhiyun ret = regmap_write(iod->regmap_base, RK3368_SOC_CON15, val);
308*4882a593Smuzhiyun if (ret < 0)
309*4882a593Smuzhiyun dev_warn(iod->dev, "couldn't update flash0 ctrl\n");
310*4882a593Smuzhiyun }
311*4882a593Smuzhiyun
rk3399_pmu_iodomain_init(struct rockchip_iodomain_priv * iod)312*4882a593Smuzhiyun static void rk3399_pmu_iodomain_init(struct rockchip_iodomain_priv *iod)
313*4882a593Smuzhiyun {
314*4882a593Smuzhiyun int ret;
315*4882a593Smuzhiyun u32 val;
316*4882a593Smuzhiyun
317*4882a593Smuzhiyun /* if no pmu io supply we should leave things alone */
318*4882a593Smuzhiyun if (!iod->supplies[RK3399_PMUGRF_VSEL_SUPPLY_NUM].reg)
319*4882a593Smuzhiyun return;
320*4882a593Smuzhiyun
321*4882a593Smuzhiyun /*
322*4882a593Smuzhiyun * set pmu io iodomain to also use this framework
323*4882a593Smuzhiyun * instead of a special gpio.
324*4882a593Smuzhiyun */
325*4882a593Smuzhiyun val = RK3399_PMUGRF_CON0_VSEL | (RK3399_PMUGRF_CON0_VSEL << 16);
326*4882a593Smuzhiyun ret = regmap_write(iod->regmap_base, RK3399_PMUGRF_CON0, val);
327*4882a593Smuzhiyun if (ret < 0)
328*4882a593Smuzhiyun dev_warn(iod->dev, "couldn't update pmu io iodomain ctrl\n");
329*4882a593Smuzhiyun }
330*4882a593Smuzhiyun
331*4882a593Smuzhiyun static const struct rockchip_iodomain_soc_data soc_data_px30 = {
332*4882a593Smuzhiyun .grf_offset = 0x180,
333*4882a593Smuzhiyun .supply_names = {
334*4882a593Smuzhiyun NULL,
335*4882a593Smuzhiyun "vccio6",
336*4882a593Smuzhiyun "vccio1",
337*4882a593Smuzhiyun "vccio2",
338*4882a593Smuzhiyun "vccio3",
339*4882a593Smuzhiyun "vccio4",
340*4882a593Smuzhiyun "vccio5",
341*4882a593Smuzhiyun "vccio-oscgpi",
342*4882a593Smuzhiyun },
343*4882a593Smuzhiyun .init = px30_iodomain_init,
344*4882a593Smuzhiyun };
345*4882a593Smuzhiyun
346*4882a593Smuzhiyun static const struct rockchip_iodomain_soc_data soc_data_px30_pmu = {
347*4882a593Smuzhiyun .grf_offset = 0x100,
348*4882a593Smuzhiyun .supply_names = {
349*4882a593Smuzhiyun NULL,
350*4882a593Smuzhiyun NULL,
351*4882a593Smuzhiyun NULL,
352*4882a593Smuzhiyun NULL,
353*4882a593Smuzhiyun NULL,
354*4882a593Smuzhiyun NULL,
355*4882a593Smuzhiyun NULL,
356*4882a593Smuzhiyun NULL,
357*4882a593Smuzhiyun NULL,
358*4882a593Smuzhiyun NULL,
359*4882a593Smuzhiyun NULL,
360*4882a593Smuzhiyun NULL,
361*4882a593Smuzhiyun NULL,
362*4882a593Smuzhiyun NULL,
363*4882a593Smuzhiyun "pmuio1",
364*4882a593Smuzhiyun "pmuio2",
365*4882a593Smuzhiyun },
366*4882a593Smuzhiyun };
367*4882a593Smuzhiyun
368*4882a593Smuzhiyun /*
369*4882a593Smuzhiyun * On the rk3188 the io-domains are handled by a shared register with the
370*4882a593Smuzhiyun * lower 8 bits being still being continuing drive-strength settings.
371*4882a593Smuzhiyun */
372*4882a593Smuzhiyun static const struct rockchip_iodomain_soc_data soc_data_rk3188 = {
373*4882a593Smuzhiyun .grf_offset = 0x104,
374*4882a593Smuzhiyun .supply_names = {
375*4882a593Smuzhiyun NULL,
376*4882a593Smuzhiyun NULL,
377*4882a593Smuzhiyun NULL,
378*4882a593Smuzhiyun NULL,
379*4882a593Smuzhiyun NULL,
380*4882a593Smuzhiyun NULL,
381*4882a593Smuzhiyun NULL,
382*4882a593Smuzhiyun NULL,
383*4882a593Smuzhiyun "ap0",
384*4882a593Smuzhiyun "ap1",
385*4882a593Smuzhiyun "cif",
386*4882a593Smuzhiyun "flash",
387*4882a593Smuzhiyun "vccio0",
388*4882a593Smuzhiyun "vccio1",
389*4882a593Smuzhiyun "lcdc0",
390*4882a593Smuzhiyun "lcdc1",
391*4882a593Smuzhiyun },
392*4882a593Smuzhiyun };
393*4882a593Smuzhiyun
394*4882a593Smuzhiyun static const struct rockchip_iodomain_soc_data soc_data_rk322x = {
395*4882a593Smuzhiyun .grf_offset = 0x418,
396*4882a593Smuzhiyun .supply_names = {
397*4882a593Smuzhiyun "vccio1",
398*4882a593Smuzhiyun "vccio2",
399*4882a593Smuzhiyun "vccio3",
400*4882a593Smuzhiyun "vccio4",
401*4882a593Smuzhiyun },
402*4882a593Smuzhiyun };
403*4882a593Smuzhiyun
404*4882a593Smuzhiyun static const struct rockchip_iodomain_soc_data soc_data_rk3288 = {
405*4882a593Smuzhiyun .grf_offset = 0x380,
406*4882a593Smuzhiyun .supply_names = {
407*4882a593Smuzhiyun "lcdc", /* LCDC_VDD */
408*4882a593Smuzhiyun "dvp", /* DVPIO_VDD */
409*4882a593Smuzhiyun "flash0", /* FLASH0_VDD (emmc) */
410*4882a593Smuzhiyun "flash1", /* FLASH1_VDD (sdio1) */
411*4882a593Smuzhiyun "wifi", /* APIO3_VDD (sdio0) */
412*4882a593Smuzhiyun "bb", /* APIO5_VDD */
413*4882a593Smuzhiyun "audio", /* APIO4_VDD */
414*4882a593Smuzhiyun "sdcard", /* SDMMC0_VDD (sdmmc) */
415*4882a593Smuzhiyun "gpio30", /* APIO1_VDD */
416*4882a593Smuzhiyun "gpio1830", /* APIO2_VDD */
417*4882a593Smuzhiyun },
418*4882a593Smuzhiyun .init = rk3288_iodomain_init,
419*4882a593Smuzhiyun };
420*4882a593Smuzhiyun
421*4882a593Smuzhiyun static const struct rockchip_iodomain_soc_data soc_data_rk3308 = {
422*4882a593Smuzhiyun .grf_offset = 0x300,
423*4882a593Smuzhiyun .supply_names = {
424*4882a593Smuzhiyun "vccio0",
425*4882a593Smuzhiyun "vccio1",
426*4882a593Smuzhiyun "vccio2",
427*4882a593Smuzhiyun "vccio3",
428*4882a593Smuzhiyun "vccio4",
429*4882a593Smuzhiyun "vccio5",
430*4882a593Smuzhiyun },
431*4882a593Smuzhiyun .init = rk3308_iodomain_init,
432*4882a593Smuzhiyun };
433*4882a593Smuzhiyun
434*4882a593Smuzhiyun static const struct rockchip_iodomain_soc_data soc_data_rk3328 = {
435*4882a593Smuzhiyun .grf_offset = 0x410,
436*4882a593Smuzhiyun .supply_names = {
437*4882a593Smuzhiyun "vccio1",
438*4882a593Smuzhiyun "vccio2",
439*4882a593Smuzhiyun "vccio3",
440*4882a593Smuzhiyun "vccio4",
441*4882a593Smuzhiyun "vccio5",
442*4882a593Smuzhiyun "vccio6",
443*4882a593Smuzhiyun "pmuio",
444*4882a593Smuzhiyun },
445*4882a593Smuzhiyun .init = rk3328_iodomain_init,
446*4882a593Smuzhiyun };
447*4882a593Smuzhiyun
448*4882a593Smuzhiyun static const struct rockchip_iodomain_soc_data soc_data_rk3366 = {
449*4882a593Smuzhiyun .grf_offset = 0x900,
450*4882a593Smuzhiyun .supply_names = {
451*4882a593Smuzhiyun "lcdc", /* LCDC_IOVDD */
452*4882a593Smuzhiyun "dvpts", /* DVP_IOVDD */
453*4882a593Smuzhiyun "flash", /* FLASH_IOVDD (emmc) */
454*4882a593Smuzhiyun "wifibt", /* APIO1_IOVDD */
455*4882a593Smuzhiyun NULL,
456*4882a593Smuzhiyun "audio", /* AUDIO_IODVDD */
457*4882a593Smuzhiyun "sdcard", /* SDMMC_IOVDD (sdmmc) */
458*4882a593Smuzhiyun "tphdsor", /* APIO2_IOVDD */
459*4882a593Smuzhiyun },
460*4882a593Smuzhiyun .init = rk3366_iodomain_init,
461*4882a593Smuzhiyun };
462*4882a593Smuzhiyun
463*4882a593Smuzhiyun static const struct rockchip_iodomain_soc_data soc_data_rk3368 = {
464*4882a593Smuzhiyun .grf_offset = 0x900,
465*4882a593Smuzhiyun .supply_names = {
466*4882a593Smuzhiyun NULL, /* reserved */
467*4882a593Smuzhiyun "dvp", /* DVPIO_VDD */
468*4882a593Smuzhiyun "flash0", /* FLASH0_VDD (emmc) */
469*4882a593Smuzhiyun "wifi", /* APIO2_VDD (sdio0) */
470*4882a593Smuzhiyun NULL,
471*4882a593Smuzhiyun "audio", /* APIO3_VDD */
472*4882a593Smuzhiyun "sdcard", /* SDMMC0_VDD (sdmmc) */
473*4882a593Smuzhiyun "gpio30", /* APIO1_VDD */
474*4882a593Smuzhiyun "gpio1830", /* APIO4_VDD (gpujtag) */
475*4882a593Smuzhiyun },
476*4882a593Smuzhiyun .init = rk3368_iodomain_init,
477*4882a593Smuzhiyun };
478*4882a593Smuzhiyun
479*4882a593Smuzhiyun static const struct rockchip_iodomain_soc_data soc_data_rk3368_pmu = {
480*4882a593Smuzhiyun .grf_offset = 0x100,
481*4882a593Smuzhiyun .supply_names = {
482*4882a593Smuzhiyun NULL,
483*4882a593Smuzhiyun NULL,
484*4882a593Smuzhiyun NULL,
485*4882a593Smuzhiyun NULL,
486*4882a593Smuzhiyun "pmu", /*PMU IO domain*/
487*4882a593Smuzhiyun "vop", /*LCDC IO domain*/
488*4882a593Smuzhiyun },
489*4882a593Smuzhiyun };
490*4882a593Smuzhiyun
491*4882a593Smuzhiyun static const struct rockchip_iodomain_soc_data soc_data_rk3399 = {
492*4882a593Smuzhiyun .grf_offset = 0xe640,
493*4882a593Smuzhiyun .supply_names = {
494*4882a593Smuzhiyun "bt656", /* APIO2_VDD */
495*4882a593Smuzhiyun "audio", /* APIO5_VDD */
496*4882a593Smuzhiyun "sdmmc", /* SDMMC0_VDD */
497*4882a593Smuzhiyun "gpio1830", /* APIO4_VDD */
498*4882a593Smuzhiyun },
499*4882a593Smuzhiyun };
500*4882a593Smuzhiyun
501*4882a593Smuzhiyun static const struct rockchip_iodomain_soc_data soc_data_rk3399_pmu = {
502*4882a593Smuzhiyun .grf_offset = 0x180,
503*4882a593Smuzhiyun .supply_names = {
504*4882a593Smuzhiyun NULL,
505*4882a593Smuzhiyun NULL,
506*4882a593Smuzhiyun NULL,
507*4882a593Smuzhiyun NULL,
508*4882a593Smuzhiyun NULL,
509*4882a593Smuzhiyun NULL,
510*4882a593Smuzhiyun NULL,
511*4882a593Smuzhiyun NULL,
512*4882a593Smuzhiyun NULL,
513*4882a593Smuzhiyun "pmu1830", /* PMUIO2_VDD */
514*4882a593Smuzhiyun },
515*4882a593Smuzhiyun .init = rk3399_pmu_iodomain_init,
516*4882a593Smuzhiyun };
517*4882a593Smuzhiyun
518*4882a593Smuzhiyun static const struct rockchip_iodomain_soc_data soc_data_rk3568_pmu = {
519*4882a593Smuzhiyun .grf_offset = 0x140,
520*4882a593Smuzhiyun .supply_names = {
521*4882a593Smuzhiyun "pmuio1",
522*4882a593Smuzhiyun "pmuio2",
523*4882a593Smuzhiyun "vccio1",
524*4882a593Smuzhiyun "vccio2",
525*4882a593Smuzhiyun "vccio3",
526*4882a593Smuzhiyun "vccio4",
527*4882a593Smuzhiyun "vccio5",
528*4882a593Smuzhiyun "vccio6",
529*4882a593Smuzhiyun "vccio7",
530*4882a593Smuzhiyun },
531*4882a593Smuzhiyun };
532*4882a593Smuzhiyun
533*4882a593Smuzhiyun static const struct rockchip_iodomain_soc_data soc_data_rv1108 = {
534*4882a593Smuzhiyun .grf_offset = 0x404,
535*4882a593Smuzhiyun .supply_names = {
536*4882a593Smuzhiyun NULL,
537*4882a593Smuzhiyun NULL,
538*4882a593Smuzhiyun NULL,
539*4882a593Smuzhiyun NULL,
540*4882a593Smuzhiyun NULL,
541*4882a593Smuzhiyun NULL,
542*4882a593Smuzhiyun NULL,
543*4882a593Smuzhiyun NULL,
544*4882a593Smuzhiyun NULL,
545*4882a593Smuzhiyun NULL,
546*4882a593Smuzhiyun NULL,
547*4882a593Smuzhiyun "vccio1",
548*4882a593Smuzhiyun "vccio2",
549*4882a593Smuzhiyun "vccio3",
550*4882a593Smuzhiyun "vccio5",
551*4882a593Smuzhiyun "vccio6",
552*4882a593Smuzhiyun },
553*4882a593Smuzhiyun
554*4882a593Smuzhiyun };
555*4882a593Smuzhiyun
556*4882a593Smuzhiyun static const struct rockchip_iodomain_soc_data soc_data_rv1108_pmu = {
557*4882a593Smuzhiyun .grf_offset = 0x104,
558*4882a593Smuzhiyun .supply_names = {
559*4882a593Smuzhiyun "pmu",
560*4882a593Smuzhiyun },
561*4882a593Smuzhiyun };
562*4882a593Smuzhiyun
563*4882a593Smuzhiyun static const struct rockchip_iodomain_soc_data soc_data_rv1126_pmu = {
564*4882a593Smuzhiyun .grf_offset = 0x140,
565*4882a593Smuzhiyun .supply_names = {
566*4882a593Smuzhiyun NULL,
567*4882a593Smuzhiyun "vccio1",
568*4882a593Smuzhiyun "vccio2",
569*4882a593Smuzhiyun "vccio3",
570*4882a593Smuzhiyun "vccio4",
571*4882a593Smuzhiyun "vccio5",
572*4882a593Smuzhiyun "vccio6",
573*4882a593Smuzhiyun "vccio7",
574*4882a593Smuzhiyun "pmuio0",
575*4882a593Smuzhiyun "pmuio1",
576*4882a593Smuzhiyun },
577*4882a593Smuzhiyun };
578*4882a593Smuzhiyun
of_get_regulator(ofnode node,const char * supply)579*4882a593Smuzhiyun static struct udevice *of_get_regulator(ofnode node, const char *supply)
580*4882a593Smuzhiyun {
581*4882a593Smuzhiyun char sname[32]; /* 32 is max size of property name */
582*4882a593Smuzhiyun struct udevice *sudev = NULL;
583*4882a593Smuzhiyun ofnode snode;
584*4882a593Smuzhiyun u32 phandle;
585*4882a593Smuzhiyun int ret;
586*4882a593Smuzhiyun
587*4882a593Smuzhiyun snprintf(sname, 32, "%s-supply", supply);
588*4882a593Smuzhiyun
589*4882a593Smuzhiyun /* Get regulator and clk */
590*4882a593Smuzhiyun if (!ofnode_read_u32(node, sname, &phandle)) {
591*4882a593Smuzhiyun snode = ofnode_get_by_phandle(phandle);
592*4882a593Smuzhiyun ret = regulator_get_by_devname(snode.np->name, &sudev);
593*4882a593Smuzhiyun if (ret) {
594*4882a593Smuzhiyun printf("%s: Get (%s) regulator: %s failed, ret=%d\n",
595*4882a593Smuzhiyun __func__,
596*4882a593Smuzhiyun sname, snode.np->full_name, ret);
597*4882a593Smuzhiyun return NULL;
598*4882a593Smuzhiyun }
599*4882a593Smuzhiyun debug("IO-DOMAIN: supply: %s\n", snode.np->full_name);
600*4882a593Smuzhiyun }
601*4882a593Smuzhiyun
602*4882a593Smuzhiyun return sudev;
603*4882a593Smuzhiyun }
604*4882a593Smuzhiyun
rockchip_iodomain_probe(struct udevice * dev)605*4882a593Smuzhiyun static int rockchip_iodomain_probe(struct udevice *dev)
606*4882a593Smuzhiyun {
607*4882a593Smuzhiyun struct rockchip_iodomain_priv *priv = dev_get_priv(dev);
608*4882a593Smuzhiyun struct rockchip_iodomain_soc_data *sdata;
609*4882a593Smuzhiyun int i, ret;
610*4882a593Smuzhiyun
611*4882a593Smuzhiyun sdata = (struct rockchip_iodomain_soc_data *)dev_get_driver_data(dev);
612*4882a593Smuzhiyun priv->sdata = sdata;
613*4882a593Smuzhiyun if (sdata == &soc_data_rk3568_pmu)
614*4882a593Smuzhiyun priv->write = rk3568_pmu_iodomain_write;
615*4882a593Smuzhiyun else if (sdata == &soc_data_rv1126_pmu)
616*4882a593Smuzhiyun priv->write = rv1126_iodomain_write;
617*4882a593Smuzhiyun else
618*4882a593Smuzhiyun priv->write = rockchip_iodomain_write;
619*4882a593Smuzhiyun
620*4882a593Smuzhiyun if (!priv->regmap_base)
621*4882a593Smuzhiyun return -1;
622*4882a593Smuzhiyun
623*4882a593Smuzhiyun for (i = 0; i < MAX_SUPPLIES; i++) {
624*4882a593Smuzhiyun const char *supply_name = priv->sdata->supply_names[i];
625*4882a593Smuzhiyun struct rockchip_iodomain_supply *supply = &priv->supplies[i];
626*4882a593Smuzhiyun struct udevice *reg;
627*4882a593Smuzhiyun u32 uV;
628*4882a593Smuzhiyun
629*4882a593Smuzhiyun if (!supply_name)
630*4882a593Smuzhiyun continue;
631*4882a593Smuzhiyun
632*4882a593Smuzhiyun reg = of_get_regulator(dev_ofnode(dev), supply_name);
633*4882a593Smuzhiyun if (!reg)
634*4882a593Smuzhiyun continue;
635*4882a593Smuzhiyun
636*4882a593Smuzhiyun uV = regulator_get_value(reg);
637*4882a593Smuzhiyun if (uV <= 0) {
638*4882a593Smuzhiyun printf("voltage(%d uV) is invalid from %s\n", uV, reg->name);
639*4882a593Smuzhiyun continue;
640*4882a593Smuzhiyun }
641*4882a593Smuzhiyun
642*4882a593Smuzhiyun if (uV > MAX_VOLTAGE_3_3) {
643*4882a593Smuzhiyun printf("%d uV is too high from %s\n", uV, reg->name);
644*4882a593Smuzhiyun continue;
645*4882a593Smuzhiyun }
646*4882a593Smuzhiyun
647*4882a593Smuzhiyun /* setup our supply */
648*4882a593Smuzhiyun supply->idx = i;
649*4882a593Smuzhiyun supply->iod = priv;
650*4882a593Smuzhiyun supply->reg = reg;
651*4882a593Smuzhiyun
652*4882a593Smuzhiyun ret = priv->write(supply, uV);
653*4882a593Smuzhiyun if (ret)
654*4882a593Smuzhiyun supply->reg = NULL;
655*4882a593Smuzhiyun }
656*4882a593Smuzhiyun
657*4882a593Smuzhiyun if (priv->sdata->init)
658*4882a593Smuzhiyun priv->sdata->init(priv);
659*4882a593Smuzhiyun
660*4882a593Smuzhiyun return 0;
661*4882a593Smuzhiyun }
662*4882a593Smuzhiyun
663*4882a593Smuzhiyun static const struct udevice_id rockchip_iodomain_match[] = {
664*4882a593Smuzhiyun {
665*4882a593Smuzhiyun .compatible = "rockchip,px30-io-voltage-domain",
666*4882a593Smuzhiyun .data = (ulong)&soc_data_px30
667*4882a593Smuzhiyun },
668*4882a593Smuzhiyun {
669*4882a593Smuzhiyun .compatible = "rockchip,px30-pmu-io-voltage-domain",
670*4882a593Smuzhiyun .data = (ulong)&soc_data_px30_pmu
671*4882a593Smuzhiyun },
672*4882a593Smuzhiyun {
673*4882a593Smuzhiyun .compatible = "rockchip,rk3188-io-voltage-domain",
674*4882a593Smuzhiyun .data = (ulong)&soc_data_rk3188
675*4882a593Smuzhiyun },
676*4882a593Smuzhiyun {
677*4882a593Smuzhiyun .compatible = "rockchip,rk322x-io-voltage-domain",
678*4882a593Smuzhiyun .data = (ulong)&soc_data_rk322x
679*4882a593Smuzhiyun },
680*4882a593Smuzhiyun {
681*4882a593Smuzhiyun .compatible = "rockchip,rk3288-io-voltage-domain",
682*4882a593Smuzhiyun .data = (ulong)&soc_data_rk3288
683*4882a593Smuzhiyun },
684*4882a593Smuzhiyun {
685*4882a593Smuzhiyun .compatible = "rockchip,rk3308-io-voltage-domain",
686*4882a593Smuzhiyun .data = (ulong)&soc_data_rk3308
687*4882a593Smuzhiyun },
688*4882a593Smuzhiyun {
689*4882a593Smuzhiyun .compatible = "rockchip,rk3328-io-voltage-domain",
690*4882a593Smuzhiyun .data = (ulong)&soc_data_rk3328
691*4882a593Smuzhiyun },
692*4882a593Smuzhiyun {
693*4882a593Smuzhiyun .compatible = "rockchip,rk3366-io-voltage-domain",
694*4882a593Smuzhiyun .data = (ulong)&soc_data_rk3366
695*4882a593Smuzhiyun },
696*4882a593Smuzhiyun {
697*4882a593Smuzhiyun .compatible = "rockchip,rk3368-io-voltage-domain",
698*4882a593Smuzhiyun .data = (ulong)&soc_data_rk3368
699*4882a593Smuzhiyun },
700*4882a593Smuzhiyun {
701*4882a593Smuzhiyun .compatible = "rockchip,rk3368-pmu-io-voltage-domain",
702*4882a593Smuzhiyun .data = (ulong)&soc_data_rk3368_pmu
703*4882a593Smuzhiyun },
704*4882a593Smuzhiyun {
705*4882a593Smuzhiyun .compatible = "rockchip,rk3399-io-voltage-domain",
706*4882a593Smuzhiyun .data = (ulong)&soc_data_rk3399
707*4882a593Smuzhiyun },
708*4882a593Smuzhiyun {
709*4882a593Smuzhiyun .compatible = "rockchip,rk3399-pmu-io-voltage-domain",
710*4882a593Smuzhiyun .data = (ulong)&soc_data_rk3399_pmu
711*4882a593Smuzhiyun },
712*4882a593Smuzhiyun {
713*4882a593Smuzhiyun .compatible = "rockchip,rk3568-pmu-io-voltage-domain",
714*4882a593Smuzhiyun .data = (ulong)&soc_data_rk3568_pmu
715*4882a593Smuzhiyun },
716*4882a593Smuzhiyun {
717*4882a593Smuzhiyun .compatible = "rockchip,rv1108-io-voltage-domain",
718*4882a593Smuzhiyun .data = (ulong)&soc_data_rv1108
719*4882a593Smuzhiyun },
720*4882a593Smuzhiyun {
721*4882a593Smuzhiyun .compatible = "rockchip,rv1108-pmu-io-voltage-domain",
722*4882a593Smuzhiyun .data = (ulong)&soc_data_rv1108_pmu
723*4882a593Smuzhiyun },
724*4882a593Smuzhiyun {
725*4882a593Smuzhiyun .compatible = "rockchip,rv1126-pmu-io-voltage-domain",
726*4882a593Smuzhiyun .data = (ulong)&soc_data_rv1126_pmu
727*4882a593Smuzhiyun },
728*4882a593Smuzhiyun { /* sentinel */ },
729*4882a593Smuzhiyun };
730*4882a593Smuzhiyun
731*4882a593Smuzhiyun U_BOOT_DRIVER(io_domain) = {
732*4882a593Smuzhiyun .name = "io_domain",
733*4882a593Smuzhiyun .id = UCLASS_IO_DOMAIN,
734*4882a593Smuzhiyun .of_match = rockchip_iodomain_match,
735*4882a593Smuzhiyun .priv_auto_alloc_size = sizeof(struct rockchip_iodomain_priv),
736*4882a593Smuzhiyun .ofdata_to_platdata = rockchip_ofdata_to_platdata,
737*4882a593Smuzhiyun .probe = rockchip_iodomain_probe,
738*4882a593Smuzhiyun };
739