xref: /linux/drivers/regulator/sc2730-regulator.c (revision b3438e5ca785565a65ef231bc03cd5a05c3be5c7)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2018-2021 Unisoc Inc.
4  */
5 
6 #include <linux/module.h>
7 #include <linux/of.h>
8 #include <linux/platform_device.h>
9 #include <linux/regmap.h>
10 #include <linux/regulator/driver.h>
11 #include <linux/regulator/of_regulator.h>
12 
13 /*
14  * SC2730 regulator base address
15  */
16 #define SC2730_REGULATOR_BASE		0x1800
17 
18 /*
19  * SC2730 regulator lock register
20  */
21 #define SC2730_WR_UNLOCK_VALUE		0x6e7f
22 #define SC2730_PWR_WR_PROT		(SC2730_REGULATOR_BASE + 0x3d0)
23 
24 /*
25  * SC2730 enable register
26  */
27 #define SC2730_POWER_PD_SW		(SC2730_REGULATOR_BASE + 0x01c)
28 #define SC2730_LDO_VDDRF18_PD		(SC2730_REGULATOR_BASE + 0x10c)
29 #define SC2730_LDO_VDDCAMIO_PD		(SC2730_REGULATOR_BASE + 0x118)
30 #define SC2730_LDO_VDDWCN_PD		(SC2730_REGULATOR_BASE + 0x11c)
31 #define SC2730_LDO_VDDCAMD1_PD		(SC2730_REGULATOR_BASE + 0x128)
32 #define SC2730_LDO_VDDCAMD0_PD		(SC2730_REGULATOR_BASE + 0x134)
33 #define SC2730_LDO_VDDRF1V25_PD		(SC2730_REGULATOR_BASE + 0x140)
34 #define SC2730_LDO_AVDD12_PD		(SC2730_REGULATOR_BASE + 0x14c)
35 #define SC2730_LDO_VDDCAMA0_PD		(SC2730_REGULATOR_BASE + 0x158)
36 #define SC2730_LDO_VDDCAMA1_PD		(SC2730_REGULATOR_BASE + 0x164)
37 #define SC2730_LDO_VDDCAMMOT_PD		(SC2730_REGULATOR_BASE + 0x170)
38 #define SC2730_LDO_VDDSIM2_PD		(SC2730_REGULATOR_BASE + 0x194)
39 #define SC2730_LDO_VDDEMMCCORE_PD	(SC2730_REGULATOR_BASE + 0x1a0)
40 #define SC2730_LDO_VDDSDCORE_PD		(SC2730_REGULATOR_BASE + 0x1ac)
41 #define SC2730_LDO_VDDSDIO_PD		(SC2730_REGULATOR_BASE + 0x1b8)
42 #define SC2730_LDO_VDDWIFIPA_PD		(SC2730_REGULATOR_BASE + 0x1d0)
43 #define SC2730_LDO_VDDUSB33_PD		(SC2730_REGULATOR_BASE + 0x1e8)
44 #define SC2730_LDO_VDDLDO0_PD		(SC2730_REGULATOR_BASE + 0x1f4)
45 #define SC2730_LDO_VDDLDO1_PD		(SC2730_REGULATOR_BASE + 0x200)
46 #define SC2730_LDO_VDDLDO2_PD		(SC2730_REGULATOR_BASE + 0x20c)
47 #define SC2730_LDO_VDDKPLED_PD		(SC2730_REGULATOR_BASE + 0x38c)
48 
49 /*
50  * SC2730 enable mask
51  */
52 #define SC2730_DCDC_CPU_PD_MASK		BIT(4)
53 #define SC2730_DCDC_GPU_PD_MASK		BIT(3)
54 #define SC2730_DCDC_CORE_PD_MASK	BIT(5)
55 #define SC2730_DCDC_MODEM_PD_MASK	BIT(11)
56 #define SC2730_DCDC_MEM_PD_MASK		BIT(6)
57 #define SC2730_DCDC_MEMQ_PD_MASK	BIT(12)
58 #define SC2730_DCDC_GEN0_PD_MASK	BIT(8)
59 #define SC2730_DCDC_GEN1_PD_MASK	BIT(7)
60 #define SC2730_DCDC_SRAM_PD_MASK	BIT(13)
61 #define SC2730_LDO_AVDD18_PD_MASK	BIT(2)
62 #define SC2730_LDO_VDDRF18_PD_MASK	BIT(0)
63 #define SC2730_LDO_VDDCAMIO_PD_MASK	BIT(0)
64 #define SC2730_LDO_VDDWCN_PD_MASK	BIT(0)
65 #define SC2730_LDO_VDDCAMD1_PD_MASK	BIT(0)
66 #define SC2730_LDO_VDDCAMD0_PD_MASK	BIT(0)
67 #define SC2730_LDO_VDDRF1V25_PD_MASK	BIT(0)
68 #define SC2730_LDO_AVDD12_PD_MASK	BIT(0)
69 #define SC2730_LDO_VDDCAMA0_PD_MASK	BIT(0)
70 #define SC2730_LDO_VDDCAMA1_PD_MASK	BIT(0)
71 #define SC2730_LDO_VDDCAMMOT_PD_MASK	BIT(0)
72 #define SC2730_LDO_VDDSIM2_PD_MASK	BIT(0)
73 #define SC2730_LDO_VDDEMMCCORE_PD_MASK	BIT(0)
74 #define SC2730_LDO_VDDSDCORE_PD_MASK	BIT(0)
75 #define SC2730_LDO_VDDSDIO_PD_MASK	BIT(0)
76 #define SC2730_LDO_VDD28_PD_MASK	BIT(1)
77 #define SC2730_LDO_VDDWIFIPA_PD_MASK	BIT(0)
78 #define SC2730_LDO_VDD18_DCXO_PD_MASK	BIT(10)
79 #define SC2730_LDO_VDDUSB33_PD_MASK	BIT(0)
80 #define SC2730_LDO_VDDLDO0_PD_MASK	BIT(0)
81 #define SC2730_LDO_VDDLDO1_PD_MASK	BIT(0)
82 #define SC2730_LDO_VDDLDO2_PD_MASK	BIT(0)
83 #define SC2730_LDO_VDDKPLED_PD_MASK	BIT(15)
84 
85 /*
86  * SC2730 vsel register
87  */
88 #define SC2730_DCDC_CPU_VOL		(SC2730_REGULATOR_BASE + 0x44)
89 #define SC2730_DCDC_GPU_VOL		(SC2730_REGULATOR_BASE + 0x54)
90 #define SC2730_DCDC_CORE_VOL		(SC2730_REGULATOR_BASE + 0x64)
91 #define SC2730_DCDC_MODEM_VOL		(SC2730_REGULATOR_BASE + 0x74)
92 #define SC2730_DCDC_MEM_VOL		(SC2730_REGULATOR_BASE + 0x84)
93 #define SC2730_DCDC_MEMQ_VOL		(SC2730_REGULATOR_BASE + 0x94)
94 #define SC2730_DCDC_GEN0_VOL		(SC2730_REGULATOR_BASE + 0xa4)
95 #define SC2730_DCDC_GEN1_VOL		(SC2730_REGULATOR_BASE + 0xb4)
96 #define SC2730_DCDC_SRAM_VOL		(SC2730_REGULATOR_BASE + 0xdc)
97 #define SC2730_LDO_AVDD18_VOL		(SC2730_REGULATOR_BASE + 0x104)
98 #define SC2730_LDO_VDDRF18_VOL		(SC2730_REGULATOR_BASE + 0x110)
99 #define SC2730_LDO_VDDCAMIO_VOL		(SC2730_REGULATOR_BASE + 0x28)
100 #define SC2730_LDO_VDDWCN_VOL		(SC2730_REGULATOR_BASE + 0x120)
101 #define SC2730_LDO_VDDCAMD1_VOL		(SC2730_REGULATOR_BASE + 0x12c)
102 #define SC2730_LDO_VDDCAMD0_VOL		(SC2730_REGULATOR_BASE + 0x138)
103 #define SC2730_LDO_VDDRF1V25_VOL	(SC2730_REGULATOR_BASE + 0x144)
104 #define SC2730_LDO_AVDD12_VOL		(SC2730_REGULATOR_BASE + 0x150)
105 #define SC2730_LDO_VDDCAMA0_VOL		(SC2730_REGULATOR_BASE + 0x15c)
106 #define SC2730_LDO_VDDCAMA1_VOL		(SC2730_REGULATOR_BASE + 0x168)
107 #define SC2730_LDO_VDDCAMMOT_VOL	(SC2730_REGULATOR_BASE + 0x174)
108 #define SC2730_LDO_VDDSIM2_VOL		(SC2730_REGULATOR_BASE + 0x198)
109 #define SC2730_LDO_VDDEMMCCORE_VOL	(SC2730_REGULATOR_BASE + 0x1a4)
110 #define SC2730_LDO_VDDSDCORE_VOL	(SC2730_REGULATOR_BASE + 0x1b0)
111 #define SC2730_LDO_VDDSDIO_VOL		(SC2730_REGULATOR_BASE + 0x1bc)
112 #define SC2730_LDO_VDD28_VOL		(SC2730_REGULATOR_BASE + 0x1c8)
113 #define SC2730_LDO_VDDWIFIPA_VOL	(SC2730_REGULATOR_BASE + 0x1d4)
114 #define SC2730_LDO_VDD18_DCXO_VOL	(SC2730_REGULATOR_BASE + 0x1e0)
115 #define SC2730_LDO_VDDUSB33_VOL		(SC2730_REGULATOR_BASE + 0x1ec)
116 #define SC2730_LDO_VDDLDO0_VOL		(SC2730_REGULATOR_BASE + 0x1f8)
117 #define SC2730_LDO_VDDLDO1_VOL		(SC2730_REGULATOR_BASE + 0x204)
118 #define SC2730_LDO_VDDLDO2_VOL		(SC2730_REGULATOR_BASE + 0x210)
119 #define SC2730_LDO_VDDKPLED_VOL		(SC2730_REGULATOR_BASE + 0x38c)
120 
121 /*
122  * SC2730 vsel register mask
123  */
124 #define SC2730_DCDC_CPU_VOL_MASK	GENMASK(8, 0)
125 #define SC2730_DCDC_GPU_VOL_MASK	GENMASK(8, 0)
126 #define SC2730_DCDC_CORE_VOL_MASK	GENMASK(8, 0)
127 #define SC2730_DCDC_MODEM_VOL_MASK	GENMASK(8, 0)
128 #define SC2730_DCDC_MEM_VOL_MASK	GENMASK(7, 0)
129 #define SC2730_DCDC_MEMQ_VOL_MASK	GENMASK(8, 0)
130 #define SC2730_DCDC_GEN0_VOL_MASK	GENMASK(7, 0)
131 #define SC2730_DCDC_GEN1_VOL_MASK	GENMASK(7, 0)
132 #define SC2730_DCDC_SRAM_VOL_MASK	GENMASK(8, 0)
133 #define SC2730_LDO_AVDD18_VOL_MASK	GENMASK(5, 0)
134 #define SC2730_LDO_VDDRF18_VOL_MASK	GENMASK(5, 0)
135 #define SC2730_LDO_VDDCAMIO_VOL_MASK	GENMASK(5, 0)
136 #define SC2730_LDO_VDDWCN_VOL_MASK	GENMASK(5, 0)
137 #define SC2730_LDO_VDDCAMD1_VOL_MASK	GENMASK(4, 0)
138 #define SC2730_LDO_VDDCAMD0_VOL_MASK	GENMASK(4, 0)
139 #define SC2730_LDO_VDDRF1V25_VOL_MASK	GENMASK(4, 0)
140 #define SC2730_LDO_AVDD12_VOL_MASK	GENMASK(4, 0)
141 #define SC2730_LDO_VDDCAMA0_VOL_MASK	GENMASK(7, 0)
142 #define SC2730_LDO_VDDCAMA1_VOL_MASK	GENMASK(7, 0)
143 #define SC2730_LDO_VDDCAMMOT_VOL_MASK	GENMASK(7, 0)
144 #define SC2730_LDO_VDDSIM2_VOL_MASK	GENMASK(7, 0)
145 #define SC2730_LDO_VDDEMMCCORE_VOL_MASK	GENMASK(7, 0)
146 #define SC2730_LDO_VDDSDCORE_VOL_MASK	GENMASK(7, 0)
147 #define SC2730_LDO_VDDSDIO_VOL_MASK	GENMASK(7, 0)
148 #define SC2730_LDO_VDD28_VOL_MASK	GENMASK(7, 0)
149 #define SC2730_LDO_VDDWIFIPA_VOL_MASK	GENMASK(7, 0)
150 #define SC2730_LDO_VDD18_DCXO_VOL_MASK	GENMASK(7, 0)
151 #define SC2730_LDO_VDDUSB33_VOL_MASK	GENMASK(7, 0)
152 #define SC2730_LDO_VDDLDO0_VOL_MASK	GENMASK(7, 0)
153 #define SC2730_LDO_VDDLDO1_VOL_MASK	GENMASK(7, 0)
154 #define SC2730_LDO_VDDLDO2_VOL_MASK	GENMASK(7, 0)
155 #define SC2730_LDO_VDDKPLED_VOL_MASK	GENMASK(14, 7)
156 
157 enum sc2730_regulator_id {
158 	SC2730_DCDC_CPU,
159 	SC2730_DCDC_GPU,
160 	SC2730_DCDC_CORE,
161 	SC2730_DCDC_MODEM,
162 	SC2730_DCDC_MEM,
163 	SC2730_DCDC_MEMQ,
164 	SC2730_DCDC_GEN0,
165 	SC2730_DCDC_GEN1,
166 	SC2730_DCDC_SRAM,
167 	SC2730_LDO_AVDD18,
168 	SC2730_LDO_VDDRF18,
169 	SC2730_LDO_VDDCAMIO,
170 	SC2730_LDO_VDDWCN,
171 	SC2730_LDO_VDDCAMD1,
172 	SC2730_LDO_VDDCAMD0,
173 	SC2730_LDO_VDDRF1V25,
174 	SC2730_LDO_AVDD12,
175 	SC2730_LDO_VDDCAMA0,
176 	SC2730_LDO_VDDCAMA1,
177 	SC2730_LDO_VDDCAMMOT,
178 	SC2730_LDO_VDDSIM2,
179 	SC2730_LDO_VDDEMMCCORE,
180 	SC2730_LDO_VDDSDCORE,
181 	SC2730_LDO_VDDSDIO,
182 	SC2730_LDO_VDD28,
183 	SC2730_LDO_VDDWIFIPA,
184 	SC2730_LDO_VDD18_DCXO,
185 	SC2730_LDO_VDDUSB33,
186 	SC2730_LDO_VDDLDO0,
187 	SC2730_LDO_VDDLDO1,
188 	SC2730_LDO_VDDLDO2,
189 	SC2730_LDO_VDDKPLED,
190 };
191 
192 static const struct regulator_ops sc2730_regu_linear_ops = {
193 	.enable = regulator_enable_regmap,
194 	.disable = regulator_disable_regmap,
195 	.is_enabled = regulator_is_enabled_regmap,
196 	.list_voltage = regulator_list_voltage_linear,
197 	.get_voltage_sel = regulator_get_voltage_sel_regmap,
198 	.set_voltage_sel = regulator_set_voltage_sel_regmap,
199 };
200 
201 #define SC2730_REGU_LINEAR(_id, of_name, en_reg, en_mask, vreg, vmask,	\
202 			   vstep, vmin, vmax) {				\
203 	.name			= #_id,					\
204 	.of_match		= of_name,				\
205 	.regulators_node	= "regulators",				\
206 	.ops			= &sc2730_regu_linear_ops,		\
207 	.type			= REGULATOR_VOLTAGE,			\
208 	.id			= SC2730_##_id,				\
209 	.owner			= THIS_MODULE,				\
210 	.min_uV			= vmin,					\
211 	.n_voltages		= ((vmax) - (vmin)) / (vstep) + 1,	\
212 	.uV_step		= vstep,				\
213 	.enable_is_inverted	= true,					\
214 	.enable_val		= 0,					\
215 	.enable_reg		= en_reg,				\
216 	.enable_mask		= en_mask,				\
217 	.vsel_reg		= vreg,					\
218 	.vsel_mask		= vmask,				\
219 	.linear_min_sel		= 0,					\
220 }
221 
222 static const struct regulator_desc regulators[] = {
223 	SC2730_REGU_LINEAR(DCDC_CPU, "dcdc-cpu", SC2730_POWER_PD_SW,
224 			   SC2730_DCDC_CPU_PD_MASK, SC2730_DCDC_CPU_VOL,
225 			   SC2730_DCDC_CPU_VOL_MASK, 3125, 0, 1596875),
226 	SC2730_REGU_LINEAR(DCDC_GPU, "dcdc-gpu", SC2730_POWER_PD_SW,
227 			   SC2730_DCDC_GPU_PD_MASK, SC2730_DCDC_GPU_VOL,
228 			   SC2730_DCDC_GPU_VOL_MASK, 3125, 0, 1596875),
229 	SC2730_REGU_LINEAR(DCDC_CORE, "dcdc-core", SC2730_POWER_PD_SW,
230 			   SC2730_DCDC_CORE_PD_MASK, SC2730_DCDC_CORE_VOL,
231 			   SC2730_DCDC_CORE_VOL_MASK, 3125, 0, 1596875),
232 	SC2730_REGU_LINEAR(DCDC_MODEM, "dcdc-modem", SC2730_POWER_PD_SW,
233 			   SC2730_DCDC_MODEM_PD_MASK, SC2730_DCDC_MODEM_VOL,
234 			   SC2730_DCDC_MODEM_VOL_MASK, 3125, 0, 1596875),
235 	SC2730_REGU_LINEAR(DCDC_MEM, "dcdc-mem", SC2730_POWER_PD_SW,
236 			   SC2730_DCDC_MEM_PD_MASK, SC2730_DCDC_MEM_VOL,
237 			   SC2730_DCDC_MEM_VOL_MASK, 6250, 0, 1593750),
238 	SC2730_REGU_LINEAR(DCDC_MEMQ, "dcdc-memq", SC2730_POWER_PD_SW,
239 			   SC2730_DCDC_MEMQ_PD_MASK, SC2730_DCDC_MEMQ_VOL,
240 			   SC2730_DCDC_MEMQ_VOL_MASK, 3125, 0, 1596875),
241 	SC2730_REGU_LINEAR(DCDC_GEN0, "dcdc-gen0", SC2730_POWER_PD_SW,
242 			   SC2730_DCDC_GEN0_PD_MASK, SC2730_DCDC_GEN0_VOL,
243 			   SC2730_DCDC_GEN0_VOL_MASK, 9375, 20000, 2410625),
244 	SC2730_REGU_LINEAR(DCDC_GEN1, "dcdc-gen1", SC2730_POWER_PD_SW,
245 			   SC2730_DCDC_GEN1_PD_MASK, SC2730_DCDC_GEN1_VOL,
246 			   SC2730_DCDC_GEN1_VOL_MASK, 6250, 50000, 1643750),
247 	SC2730_REGU_LINEAR(DCDC_SRAM, "dcdc-sram", SC2730_POWER_PD_SW,
248 			   SC2730_DCDC_SRAM_PD_MASK, SC2730_DCDC_SRAM_VOL,
249 			   SC2730_DCDC_SRAM_VOL_MASK, 3125, 0, 1596875),
250 	SC2730_REGU_LINEAR(LDO_AVDD18, "ldo-avdd18", SC2730_POWER_PD_SW,
251 			   SC2730_LDO_AVDD18_PD_MASK, SC2730_LDO_AVDD18_VOL,
252 			   SC2730_LDO_AVDD18_VOL_MASK, 10000, 1175000, 1805000),
253 	SC2730_REGU_LINEAR(LDO_VDDRF18, "ldo-vddrf18", SC2730_LDO_VDDRF18_PD,
254 			   SC2730_LDO_VDDRF18_PD_MASK, SC2730_LDO_VDDRF18_VOL,
255 			   SC2730_LDO_VDDRF18_VOL_MASK, 10000, 1175000, 1805000),
256 	SC2730_REGU_LINEAR(LDO_VDDCAMIO, "ldo-vddcamio", SC2730_LDO_VDDCAMIO_PD,
257 			   SC2730_LDO_VDDCAMIO_PD_MASK, SC2730_LDO_VDDCAMIO_VOL,
258 			   SC2730_LDO_VDDCAMIO_VOL_MASK, 10000, 1200000, 1830000),
259 	SC2730_REGU_LINEAR(LDO_VDDWCN, "ldo-vddwcn", SC2730_LDO_VDDWCN_PD,
260 			   SC2730_LDO_VDDWCN_PD_MASK, SC2730_LDO_VDDWCN_VOL,
261 			   SC2730_LDO_VDDWCN_VOL_MASK, 15000, 900000, 1845000),
262 	SC2730_REGU_LINEAR(LDO_VDDCAMD1, "ldo-vddcamd1", SC2730_LDO_VDDCAMD1_PD,
263 			   SC2730_LDO_VDDCAMD1_PD_MASK, SC2730_LDO_VDDCAMD1_VOL,
264 			   SC2730_LDO_VDDCAMD1_VOL_MASK, 15000, 900000, 1365000),
265 	SC2730_REGU_LINEAR(LDO_VDDCAMD0, "ldo-vddcamd0", SC2730_LDO_VDDCAMD0_PD,
266 			   SC2730_LDO_VDDCAMD0_PD_MASK, SC2730_LDO_VDDCAMD0_VOL,
267 			   SC2730_LDO_VDDCAMD0_VOL_MASK, 15000, 900000, 1365000),
268 	SC2730_REGU_LINEAR(LDO_VDDRF1V25, "ldo-vddrf1v25", SC2730_LDO_VDDRF1V25_PD,
269 			   SC2730_LDO_VDDRF1V25_PD_MASK, SC2730_LDO_VDDRF1V25_VOL,
270 			   SC2730_LDO_VDDRF1V25_VOL_MASK, 15000, 900000, 1365000),
271 	SC2730_REGU_LINEAR(LDO_AVDD12, "ldo-avdd12", SC2730_LDO_AVDD12_PD,
272 			   SC2730_LDO_AVDD12_PD_MASK, SC2730_LDO_AVDD12_VOL,
273 			   SC2730_LDO_AVDD12_VOL_MASK, 15000, 900000, 1365000),
274 	SC2730_REGU_LINEAR(LDO_VDDCAMA0, "ldo-vddcama0", SC2730_LDO_VDDCAMA0_PD,
275 			   SC2730_LDO_VDDCAMA0_PD_MASK, SC2730_LDO_VDDCAMA0_VOL,
276 			   SC2730_LDO_VDDCAMA0_VOL_MASK, 10000, 1200000, 3750000),
277 	SC2730_REGU_LINEAR(LDO_VDDCAMA1, "ldo-vddcama1", SC2730_LDO_VDDCAMA1_PD,
278 			   SC2730_LDO_VDDCAMA1_PD_MASK, SC2730_LDO_VDDCAMA1_VOL,
279 			   SC2730_LDO_VDDCAMA1_VOL_MASK, 10000, 1200000, 3750000),
280 	SC2730_REGU_LINEAR(LDO_VDDCAMMOT, "ldo-vddcammot", SC2730_LDO_VDDCAMMOT_PD,
281 			   SC2730_LDO_VDDCAMMOT_PD_MASK, SC2730_LDO_VDDCAMMOT_VOL,
282 			   SC2730_LDO_VDDCAMMOT_VOL_MASK, 10000, 1200000, 3750000),
283 	SC2730_REGU_LINEAR(LDO_VDDSIM2, "ldo-vddsim2", SC2730_LDO_VDDSIM2_PD,
284 			   SC2730_LDO_VDDSIM2_PD_MASK, SC2730_LDO_VDDSIM2_VOL,
285 			   SC2730_LDO_VDDSIM2_VOL_MASK, 10000, 1200000, 3750000),
286 	SC2730_REGU_LINEAR(LDO_VDDEMMCCORE, "ldo-vddemmccore", SC2730_LDO_VDDEMMCCORE_PD,
287 			   SC2730_LDO_VDDEMMCCORE_PD_MASK, SC2730_LDO_VDDEMMCCORE_VOL,
288 			   SC2730_LDO_VDDEMMCCORE_VOL_MASK, 10000, 1200000, 3750000),
289 	SC2730_REGU_LINEAR(LDO_VDDSDCORE, "ldo-vddsdcore", SC2730_LDO_VDDSDCORE_PD,
290 			   SC2730_LDO_VDDSDCORE_PD_MASK, SC2730_LDO_VDDSDCORE_VOL,
291 			   SC2730_LDO_VDDSDCORE_VOL_MASK, 10000, 1200000, 3750000),
292 	SC2730_REGU_LINEAR(LDO_VDDSDIO, "ldo-vddsdio", SC2730_LDO_VDDSDIO_PD,
293 			   SC2730_LDO_VDDSDIO_PD_MASK, SC2730_LDO_VDDSDIO_VOL,
294 			   SC2730_LDO_VDDSDIO_VOL_MASK, 10000, 1200000, 3750000),
295 	SC2730_REGU_LINEAR(LDO_VDD28, "ldo-vdd28", SC2730_POWER_PD_SW,
296 			   SC2730_LDO_VDD28_PD_MASK, SC2730_LDO_VDD28_VOL,
297 			   SC2730_LDO_VDD28_VOL_MASK, 10000, 1200000, 3750000),
298 	SC2730_REGU_LINEAR(LDO_VDDWIFIPA, "ldo-vddwifipa", SC2730_LDO_VDDWIFIPA_PD,
299 			   SC2730_LDO_VDDWIFIPA_PD_MASK, SC2730_LDO_VDDWIFIPA_VOL,
300 			   SC2730_LDO_VDDWIFIPA_VOL_MASK, 10000, 1200000, 3750000),
301 	SC2730_REGU_LINEAR(LDO_VDD18_DCXO, "ldo-vdd18-dcxo", SC2730_POWER_PD_SW,
302 			   SC2730_LDO_VDD18_DCXO_PD_MASK, SC2730_LDO_VDD18_DCXO_VOL,
303 			   SC2730_LDO_VDD18_DCXO_VOL_MASK, 10000, 1200000, 3750000),
304 	SC2730_REGU_LINEAR(LDO_VDDUSB33, "ldo-vddusb33", SC2730_LDO_VDDUSB33_PD,
305 			   SC2730_LDO_VDDUSB33_PD_MASK, SC2730_LDO_VDDUSB33_VOL,
306 			   SC2730_LDO_VDDUSB33_VOL_MASK, 10000, 1200000, 3750000),
307 	SC2730_REGU_LINEAR(LDO_VDDLDO0, "ldo-vddldo0", SC2730_LDO_VDDLDO0_PD,
308 			   SC2730_LDO_VDDLDO0_PD_MASK, SC2730_LDO_VDDLDO0_VOL,
309 			   SC2730_LDO_VDDLDO0_VOL_MASK, 10000, 1200000, 3750000),
310 	SC2730_REGU_LINEAR(LDO_VDDLDO1, "ldo-vddldo1", SC2730_LDO_VDDLDO1_PD,
311 			   SC2730_LDO_VDDLDO1_PD_MASK, SC2730_LDO_VDDLDO1_VOL,
312 			   SC2730_LDO_VDDLDO1_VOL_MASK, 10000, 1200000, 3750000),
313 	SC2730_REGU_LINEAR(LDO_VDDLDO2, "ldo-vddldo2", SC2730_LDO_VDDLDO2_PD,
314 			   SC2730_LDO_VDDLDO2_PD_MASK, SC2730_LDO_VDDLDO2_VOL,
315 			   SC2730_LDO_VDDLDO2_VOL_MASK, 10000, 1200000, 3750000),
316 	SC2730_REGU_LINEAR(LDO_VDDKPLED, "ldo-vddkpled", SC2730_LDO_VDDKPLED_PD,
317 			   SC2730_LDO_VDDKPLED_PD_MASK, SC2730_LDO_VDDKPLED_VOL,
318 			   SC2730_LDO_VDDKPLED_VOL_MASK, 10000, 1200000, 3750000),
319 };
320 
321 static int sc2730_regulator_unlock(struct regmap *regmap)
322 {
323 	return regmap_write(regmap, SC2730_PWR_WR_PROT, SC2730_WR_UNLOCK_VALUE);
324 }
325 
326 static int sc2730_regulator_probe(struct platform_device *pdev)
327 {
328 	int i, ret;
329 	struct regmap *regmap;
330 	struct regulator_config config = { };
331 	struct regulator_dev *rdev;
332 
333 	regmap = dev_get_regmap(pdev->dev.parent, NULL);
334 	if (!regmap)
335 		return dev_err_probe(&pdev->dev, -ENODEV, "failed to get regmap\n");
336 
337 	ret = sc2730_regulator_unlock(regmap);
338 	if (ret)
339 		return dev_err_probe(&pdev->dev, ret, "failed to release regulator lock\n");
340 
341 	config.dev = pdev->dev.parent;
342 	config.regmap = regmap;
343 
344 	for (i = 0; i < ARRAY_SIZE(regulators); i++) {
345 		rdev = devm_regulator_register(&pdev->dev, &regulators[i], &config);
346 		if (IS_ERR(rdev)) {
347 			return dev_err_probe(&pdev->dev, PTR_ERR(rdev),
348 					     "failed to register regulator %s\n",
349 					     regulators[i].name);
350 		}
351 	}
352 
353 	return 0;
354 }
355 
356 static const struct platform_device_id sc2730_regulator_id_table[] = {
357 	{ .name = "sc2730-regulator" },
358 	{ }
359 };
360 MODULE_DEVICE_TABLE(platform, sc2730_regulator_id_table);
361 
362 static struct platform_driver sc2730_regulator_driver = {
363 	.driver = {
364 		.name = "sc2730-regulator",
365 		.probe_type = PROBE_PREFER_ASYNCHRONOUS,
366 	},
367 	.probe = sc2730_regulator_probe,
368 	.id_table = sc2730_regulator_id_table,
369 };
370 
371 module_platform_driver(sc2730_regulator_driver);
372 
373 MODULE_AUTHOR("Zhongfa Wang <zhongfa.wang@unisoc.com>");
374 MODULE_DESCRIPTION("Spreadtrum SC2730 regulator driver");
375 MODULE_LICENSE("GPL");
376