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