xref: /rk3399_rockchip-uboot/drivers/power/regulator/s5m8767.c (revision f615e6a64d23952d3c68b9ac92b4ef5fa5ebdf8a)
1*f615e6a6SSimon Glass /*
2*f615e6a6SSimon Glass  * Copyright (C) 2015 Google, Inc
3*f615e6a6SSimon Glass  *
4*f615e6a6SSimon Glass  * SPDX-License-Identifier:	GPL-2.0+
5*f615e6a6SSimon Glass  */
6*f615e6a6SSimon Glass 
7*f615e6a6SSimon Glass #include <common.h>
8*f615e6a6SSimon Glass #include <fdtdec.h>
9*f615e6a6SSimon Glass #include <errno.h>
10*f615e6a6SSimon Glass #include <dm.h>
11*f615e6a6SSimon Glass #include <i2c.h>
12*f615e6a6SSimon Glass #include <power/pmic.h>
13*f615e6a6SSimon Glass #include <power/regulator.h>
14*f615e6a6SSimon Glass #include <power/s5m8767.h>
15*f615e6a6SSimon Glass 
16*f615e6a6SSimon Glass DECLARE_GLOBAL_DATA_PTR;
17*f615e6a6SSimon Glass 
18*f615e6a6SSimon Glass static const struct sec_voltage_desc buck_v1 = {
19*f615e6a6SSimon Glass 	.max = 2225000,
20*f615e6a6SSimon Glass 	.min =  650000,
21*f615e6a6SSimon Glass 	.step =   6250,
22*f615e6a6SSimon Glass };
23*f615e6a6SSimon Glass 
24*f615e6a6SSimon Glass static const struct sec_voltage_desc buck_v2 = {
25*f615e6a6SSimon Glass 	.max = 1600000,
26*f615e6a6SSimon Glass 	.min =  600000,
27*f615e6a6SSimon Glass 	.step =   6250,
28*f615e6a6SSimon Glass };
29*f615e6a6SSimon Glass 
30*f615e6a6SSimon Glass static const struct sec_voltage_desc buck_v3 = {
31*f615e6a6SSimon Glass 	.max = 3000000,
32*f615e6a6SSimon Glass 	.min =  750000,
33*f615e6a6SSimon Glass 	.step =  12500,
34*f615e6a6SSimon Glass };
35*f615e6a6SSimon Glass 
36*f615e6a6SSimon Glass static const struct sec_voltage_desc ldo_v1 = {
37*f615e6a6SSimon Glass 	.max = 3950000,
38*f615e6a6SSimon Glass 	.min =  800000,
39*f615e6a6SSimon Glass 	.step =  50000,
40*f615e6a6SSimon Glass };
41*f615e6a6SSimon Glass 
42*f615e6a6SSimon Glass static const struct sec_voltage_desc ldo_v2 = {
43*f615e6a6SSimon Glass 	.max = 2375000,
44*f615e6a6SSimon Glass 	.min =  800000,
45*f615e6a6SSimon Glass 	.step =  25000,
46*f615e6a6SSimon Glass };
47*f615e6a6SSimon Glass 
48*f615e6a6SSimon Glass static const struct s5m8767_para buck_param[] = {
49*f615e6a6SSimon Glass 	/*
50*f615e6a6SSimon Glass 	 *            | voltage ----|  | enable -|   voltage
51*f615e6a6SSimon Glass 	 * regnum       addr  bpos mask  addr  on     desc
52*f615e6a6SSimon Glass 	 */
53*f615e6a6SSimon Glass 	{S5M8767_BUCK1, 0x33, 0x0, 0xff, 0x32, 0x3, &buck_v1},
54*f615e6a6SSimon Glass 	{S5M8767_BUCK2, 0x35, 0x0, 0xff, 0x34, 0x1, &buck_v2},
55*f615e6a6SSimon Glass 	{S5M8767_BUCK3, 0x3e, 0x0, 0xff, 0x3d, 0x1, &buck_v2},
56*f615e6a6SSimon Glass 	{S5M8767_BUCK4, 0x47, 0x0, 0xff, 0x46, 0x1, &buck_v2},
57*f615e6a6SSimon Glass 	{S5M8767_BUCK5, 0x50, 0x0, 0xff, 0x4f, 0x3, &buck_v1},
58*f615e6a6SSimon Glass 	{S5M8767_BUCK6, 0x55, 0x0, 0xff, 0x54, 0x3, &buck_v1},
59*f615e6a6SSimon Glass 	{S5M8767_BUCK7, 0x57, 0x0, 0xff, 0x56, 0x3, &buck_v3},
60*f615e6a6SSimon Glass 	{S5M8767_BUCK8, 0x59, 0x0, 0xff, 0x58, 0x3, &buck_v3},
61*f615e6a6SSimon Glass 	{S5M8767_BUCK9, 0x5b, 0x0, 0xff, 0x5a, 0x3, &buck_v3},
62*f615e6a6SSimon Glass };
63*f615e6a6SSimon Glass 
64*f615e6a6SSimon Glass static const struct s5m8767_para ldo_param[] = {
65*f615e6a6SSimon Glass 	{S5M8767_LDO1,  0x5c, 0x0, 0x3f, 0x5c, 0x3, &ldo_v2},
66*f615e6a6SSimon Glass 	{S5M8767_LDO2,  0x5d, 0x0, 0x3f, 0x5d, 0x1, &ldo_v2},
67*f615e6a6SSimon Glass 	{S5M8767_LDO3,  0x61, 0x0, 0x3f, 0x61, 0x3, &ldo_v1},
68*f615e6a6SSimon Glass 	{S5M8767_LDO4,  0x62, 0x0, 0x3f, 0x62, 0x3, &ldo_v1},
69*f615e6a6SSimon Glass 	{S5M8767_LDO5,  0x63, 0x0, 0x3f, 0x63, 0x3, &ldo_v1},
70*f615e6a6SSimon Glass 	{S5M8767_LDO6,  0x64, 0x0, 0x3f, 0x64, 0x1, &ldo_v2},
71*f615e6a6SSimon Glass 	{S5M8767_LDO7,  0x65, 0x0, 0x3f, 0x65, 0x1, &ldo_v2},
72*f615e6a6SSimon Glass 	{S5M8767_LDO8,  0x66, 0x0, 0x3f, 0x66, 0x1, &ldo_v2},
73*f615e6a6SSimon Glass 	{S5M8767_LDO9,  0x67, 0x0, 0x3f, 0x67, 0x3, &ldo_v1},
74*f615e6a6SSimon Glass 	{S5M8767_LDO10, 0x68, 0x0, 0x3f, 0x68, 0x1, &ldo_v1},
75*f615e6a6SSimon Glass 	{S5M8767_LDO11, 0x69, 0x0, 0x3f, 0x69, 0x1, &ldo_v1},
76*f615e6a6SSimon Glass 	{S5M8767_LDO12, 0x6a, 0x0, 0x3f, 0x6a, 0x1, &ldo_v1},
77*f615e6a6SSimon Glass 	{S5M8767_LDO13, 0x6b, 0x0, 0x3f, 0x6b, 0x3, &ldo_v1},
78*f615e6a6SSimon Glass 	{S5M8767_LDO14, 0x6c, 0x0, 0x3f, 0x6c, 0x1, &ldo_v1},
79*f615e6a6SSimon Glass 	{S5M8767_LDO15, 0x6d, 0x0, 0x3f, 0x6d, 0x1, &ldo_v2},
80*f615e6a6SSimon Glass 	{S5M8767_LDO16, 0x6e, 0x0, 0x3f, 0x6e, 0x1, &ldo_v1},
81*f615e6a6SSimon Glass 	{S5M8767_LDO17, 0x6f, 0x0, 0x3f, 0x6f, 0x3, &ldo_v1},
82*f615e6a6SSimon Glass 	{S5M8767_LDO18, 0x70, 0x0, 0x3f, 0x70, 0x3, &ldo_v1},
83*f615e6a6SSimon Glass 	{S5M8767_LDO19, 0x71, 0x0, 0x3f, 0x71, 0x3, &ldo_v1},
84*f615e6a6SSimon Glass 	{S5M8767_LDO20, 0x72, 0x0, 0x3f, 0x72, 0x3, &ldo_v1},
85*f615e6a6SSimon Glass 	{S5M8767_LDO21, 0x73, 0x0, 0x3f, 0x73, 0x3, &ldo_v1},
86*f615e6a6SSimon Glass 	{S5M8767_LDO22, 0x74, 0x0, 0x3f, 0x74, 0x3, &ldo_v1},
87*f615e6a6SSimon Glass 	{S5M8767_LDO23, 0x75, 0x0, 0x3f, 0x75, 0x3, &ldo_v1},
88*f615e6a6SSimon Glass 	{S5M8767_LDO24, 0x76, 0x0, 0x3f, 0x76, 0x3, &ldo_v1},
89*f615e6a6SSimon Glass 	{S5M8767_LDO25, 0x77, 0x0, 0x3f, 0x77, 0x3, &ldo_v1},
90*f615e6a6SSimon Glass 	{S5M8767_LDO26, 0x78, 0x0, 0x3f, 0x78, 0x3, &ldo_v1},
91*f615e6a6SSimon Glass 	{S5M8767_LDO27, 0x79, 0x0, 0x3f, 0x79, 0x3, &ldo_v1},
92*f615e6a6SSimon Glass 	{S5M8767_LDO28, 0x7a, 0x0, 0x3f, 0x7a, 0x3, &ldo_v1},
93*f615e6a6SSimon Glass };
94*f615e6a6SSimon Glass 
95*f615e6a6SSimon Glass enum {
96*f615e6a6SSimon Glass 	ENABLE_SHIFT	= 6,
97*f615e6a6SSimon Glass 	ENABLE_MASK	= 3,
98*f615e6a6SSimon Glass };
99*f615e6a6SSimon Glass 
100*f615e6a6SSimon Glass static int reg_get_value(struct udevice *dev, const struct s5m8767_para *param)
101*f615e6a6SSimon Glass {
102*f615e6a6SSimon Glass 	const struct sec_voltage_desc *desc;
103*f615e6a6SSimon Glass 	int ret, uv, val;
104*f615e6a6SSimon Glass 
105*f615e6a6SSimon Glass 	ret = pmic_reg_read(dev->parent, param->vol_addr);
106*f615e6a6SSimon Glass 	if (ret < 0)
107*f615e6a6SSimon Glass 		return ret;
108*f615e6a6SSimon Glass 
109*f615e6a6SSimon Glass 	desc = param->vol;
110*f615e6a6SSimon Glass 	val = (ret >> param->vol_bitpos) & param->vol_bitmask;
111*f615e6a6SSimon Glass 	uv = desc->min + val * desc->step;
112*f615e6a6SSimon Glass 
113*f615e6a6SSimon Glass 	return uv;
114*f615e6a6SSimon Glass }
115*f615e6a6SSimon Glass 
116*f615e6a6SSimon Glass static int reg_set_value(struct udevice *dev, const struct s5m8767_para *param,
117*f615e6a6SSimon Glass 			 int uv)
118*f615e6a6SSimon Glass {
119*f615e6a6SSimon Glass 	const struct sec_voltage_desc *desc;
120*f615e6a6SSimon Glass 	int ret, val;
121*f615e6a6SSimon Glass 
122*f615e6a6SSimon Glass 	desc = param->vol;
123*f615e6a6SSimon Glass 	if (uv < desc->min || uv > desc->max)
124*f615e6a6SSimon Glass 		return -EINVAL;
125*f615e6a6SSimon Glass 	val = (uv - desc->min) / desc->step;
126*f615e6a6SSimon Glass 	val = (val & param->vol_bitmask) << param->vol_bitpos;
127*f615e6a6SSimon Glass 	ret = pmic_clrsetbits(dev->parent, param->vol_addr,
128*f615e6a6SSimon Glass 			      param->vol_bitmask << param->vol_bitpos,
129*f615e6a6SSimon Glass 			      val);
130*f615e6a6SSimon Glass 
131*f615e6a6SSimon Glass 	return ret;
132*f615e6a6SSimon Glass }
133*f615e6a6SSimon Glass 
134*f615e6a6SSimon Glass static int s5m8767_ldo_probe(struct udevice *dev)
135*f615e6a6SSimon Glass {
136*f615e6a6SSimon Glass 	struct dm_regulator_uclass_platdata *uc_pdata;
137*f615e6a6SSimon Glass 
138*f615e6a6SSimon Glass 	uc_pdata = dev_get_uclass_platdata(dev);
139*f615e6a6SSimon Glass 
140*f615e6a6SSimon Glass 	uc_pdata->type = REGULATOR_TYPE_LDO;
141*f615e6a6SSimon Glass 	uc_pdata->mode_count = 0;
142*f615e6a6SSimon Glass 
143*f615e6a6SSimon Glass 	return 0;
144*f615e6a6SSimon Glass }
145*f615e6a6SSimon Glass static int ldo_get_value(struct udevice *dev)
146*f615e6a6SSimon Glass {
147*f615e6a6SSimon Glass 	int ldo = dev->driver_data;
148*f615e6a6SSimon Glass 
149*f615e6a6SSimon Glass 	return reg_get_value(dev, &ldo_param[ldo]);
150*f615e6a6SSimon Glass }
151*f615e6a6SSimon Glass 
152*f615e6a6SSimon Glass static int ldo_set_value(struct udevice *dev, int uv)
153*f615e6a6SSimon Glass {
154*f615e6a6SSimon Glass 	int ldo = dev->driver_data;
155*f615e6a6SSimon Glass 
156*f615e6a6SSimon Glass 	return reg_set_value(dev, &ldo_param[ldo], uv);
157*f615e6a6SSimon Glass }
158*f615e6a6SSimon Glass 
159*f615e6a6SSimon Glass static int reg_get_enable(struct udevice *dev, const struct s5m8767_para *param)
160*f615e6a6SSimon Glass {
161*f615e6a6SSimon Glass 	bool enable;
162*f615e6a6SSimon Glass 	int ret;
163*f615e6a6SSimon Glass 
164*f615e6a6SSimon Glass 	ret = pmic_reg_read(dev->parent, param->reg_enaddr);
165*f615e6a6SSimon Glass 	if (ret < 0)
166*f615e6a6SSimon Glass 		return ret;
167*f615e6a6SSimon Glass 
168*f615e6a6SSimon Glass 	enable = (ret >> ENABLE_SHIFT) & ENABLE_MASK;
169*f615e6a6SSimon Glass 
170*f615e6a6SSimon Glass 	return enable;
171*f615e6a6SSimon Glass }
172*f615e6a6SSimon Glass 
173*f615e6a6SSimon Glass static int reg_set_enable(struct udevice *dev, const struct s5m8767_para *param,
174*f615e6a6SSimon Glass 			  bool enable)
175*f615e6a6SSimon Glass {
176*f615e6a6SSimon Glass 	int ret;
177*f615e6a6SSimon Glass 
178*f615e6a6SSimon Glass 	ret = pmic_reg_read(dev->parent, param->reg_enaddr);
179*f615e6a6SSimon Glass 	if (ret < 0)
180*f615e6a6SSimon Glass 		return ret;
181*f615e6a6SSimon Glass 
182*f615e6a6SSimon Glass 	ret = pmic_clrsetbits(dev->parent, param->reg_enaddr,
183*f615e6a6SSimon Glass 			      ENABLE_MASK << ENABLE_SHIFT,
184*f615e6a6SSimon Glass 			      enable ? param->reg_enbiton << ENABLE_SHIFT : 0);
185*f615e6a6SSimon Glass 
186*f615e6a6SSimon Glass 	return ret;
187*f615e6a6SSimon Glass }
188*f615e6a6SSimon Glass 
189*f615e6a6SSimon Glass static bool ldo_get_enable(struct udevice *dev)
190*f615e6a6SSimon Glass {
191*f615e6a6SSimon Glass 	int ldo = dev->driver_data;
192*f615e6a6SSimon Glass 
193*f615e6a6SSimon Glass 	return reg_get_enable(dev, &ldo_param[ldo]);
194*f615e6a6SSimon Glass }
195*f615e6a6SSimon Glass 
196*f615e6a6SSimon Glass static int ldo_set_enable(struct udevice *dev, bool enable)
197*f615e6a6SSimon Glass {
198*f615e6a6SSimon Glass 	int ldo = dev->driver_data;
199*f615e6a6SSimon Glass 
200*f615e6a6SSimon Glass 	return reg_set_enable(dev, &ldo_param[ldo], enable);
201*f615e6a6SSimon Glass }
202*f615e6a6SSimon Glass 
203*f615e6a6SSimon Glass static int s5m8767_buck_probe(struct udevice *dev)
204*f615e6a6SSimon Glass {
205*f615e6a6SSimon Glass 	struct dm_regulator_uclass_platdata *uc_pdata;
206*f615e6a6SSimon Glass 
207*f615e6a6SSimon Glass 	uc_pdata = dev_get_uclass_platdata(dev);
208*f615e6a6SSimon Glass 
209*f615e6a6SSimon Glass 	uc_pdata->type = REGULATOR_TYPE_BUCK;
210*f615e6a6SSimon Glass 	uc_pdata->mode_count = 0;
211*f615e6a6SSimon Glass 
212*f615e6a6SSimon Glass 	return 0;
213*f615e6a6SSimon Glass }
214*f615e6a6SSimon Glass 
215*f615e6a6SSimon Glass static int buck_get_value(struct udevice *dev)
216*f615e6a6SSimon Glass {
217*f615e6a6SSimon Glass 	int buck = dev->driver_data;
218*f615e6a6SSimon Glass 
219*f615e6a6SSimon Glass 	return reg_get_value(dev, &buck_param[buck]);
220*f615e6a6SSimon Glass }
221*f615e6a6SSimon Glass 
222*f615e6a6SSimon Glass static int buck_set_value(struct udevice *dev, int uv)
223*f615e6a6SSimon Glass {
224*f615e6a6SSimon Glass 	int buck = dev->driver_data;
225*f615e6a6SSimon Glass 
226*f615e6a6SSimon Glass 	return reg_set_value(dev, &buck_param[buck], uv);
227*f615e6a6SSimon Glass }
228*f615e6a6SSimon Glass 
229*f615e6a6SSimon Glass static bool buck_get_enable(struct udevice *dev)
230*f615e6a6SSimon Glass {
231*f615e6a6SSimon Glass 	int buck = dev->driver_data;
232*f615e6a6SSimon Glass 
233*f615e6a6SSimon Glass 	return reg_get_enable(dev, &buck_param[buck]);
234*f615e6a6SSimon Glass }
235*f615e6a6SSimon Glass 
236*f615e6a6SSimon Glass static int buck_set_enable(struct udevice *dev, bool enable)
237*f615e6a6SSimon Glass {
238*f615e6a6SSimon Glass 	int buck = dev->driver_data;
239*f615e6a6SSimon Glass 
240*f615e6a6SSimon Glass 	return reg_set_enable(dev, &buck_param[buck], enable);
241*f615e6a6SSimon Glass }
242*f615e6a6SSimon Glass 
243*f615e6a6SSimon Glass static const struct dm_regulator_ops s5m8767_ldo_ops = {
244*f615e6a6SSimon Glass 	.get_value  = ldo_get_value,
245*f615e6a6SSimon Glass 	.set_value  = ldo_set_value,
246*f615e6a6SSimon Glass 	.get_enable = ldo_get_enable,
247*f615e6a6SSimon Glass 	.set_enable = ldo_set_enable,
248*f615e6a6SSimon Glass };
249*f615e6a6SSimon Glass 
250*f615e6a6SSimon Glass U_BOOT_DRIVER(s5m8767_ldo) = {
251*f615e6a6SSimon Glass 	.name = S5M8767_LDO_DRIVER,
252*f615e6a6SSimon Glass 	.id = UCLASS_REGULATOR,
253*f615e6a6SSimon Glass 	.ops = &s5m8767_ldo_ops,
254*f615e6a6SSimon Glass 	.probe = s5m8767_ldo_probe,
255*f615e6a6SSimon Glass };
256*f615e6a6SSimon Glass 
257*f615e6a6SSimon Glass static const struct dm_regulator_ops s5m8767_buck_ops = {
258*f615e6a6SSimon Glass 	.get_value  = buck_get_value,
259*f615e6a6SSimon Glass 	.set_value  = buck_set_value,
260*f615e6a6SSimon Glass 	.get_enable = buck_get_enable,
261*f615e6a6SSimon Glass 	.set_enable = buck_set_enable,
262*f615e6a6SSimon Glass };
263*f615e6a6SSimon Glass 
264*f615e6a6SSimon Glass U_BOOT_DRIVER(s5m8767_buck) = {
265*f615e6a6SSimon Glass 	.name = S5M8767_BUCK_DRIVER,
266*f615e6a6SSimon Glass 	.id = UCLASS_REGULATOR,
267*f615e6a6SSimon Glass 	.ops = &s5m8767_buck_ops,
268*f615e6a6SSimon Glass 	.probe = s5m8767_buck_probe,
269*f615e6a6SSimon Glass };
270