blob: 2131457937b7553221a6e41d7e82da2ddb6b33e1 [file] [log] [blame]
Tony Lindgren0ad4c072017-02-02 15:43:57 -08001/*
2 * Motorola CPCAP PMIC regulator driver
3 *
4 * Based on cpcap-regulator.c from Motorola Linux kernel tree
5 * Copyright (C) 2009-2011 Motorola, Inc.
6 *
7 * Rewritten for mainline kernel to use device tree and regmap
8 * Copyright (C) 2017 Tony Lindgren <tony@atomide.com>
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License as
12 * published by the Free Software Foundation version 2.
13 *
14 * This program is distributed "as is" WITHOUT ANY WARRANTY of any
15 * kind, whether express or implied; without even the implied warranty
16 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 */
19
20#include <linux/err.h>
21#include <linux/module.h>
22#include <linux/of.h>
23#include <linux/of_platform.h>
24#include <linux/regmap.h>
25#include <linux/regulator/driver.h>
26#include <linux/regulator/machine.h>
27#include <linux/regulator/of_regulator.h>
28#include <linux/mfd/motorola-cpcap.h>
29
30/*
31 * Resource assignment register bits. These seem to control the state
32 * idle modes adn are used at least for omap4.
33 */
34
35/* CPCAP_REG_ASSIGN2 bits - Resource Assignment 2 */
36#define CPCAP_BIT_VSDIO_SEL BIT(15)
37#define CPCAP_BIT_VDIG_SEL BIT(14)
38#define CPCAP_BIT_VCAM_SEL BIT(13)
39#define CPCAP_BIT_SW6_SEL BIT(12)
40#define CPCAP_BIT_SW5_SEL BIT(11)
41#define CPCAP_BIT_SW4_SEL BIT(10)
42#define CPCAP_BIT_SW3_SEL BIT(9)
43#define CPCAP_BIT_SW2_SEL BIT(8)
44#define CPCAP_BIT_SW1_SEL BIT(7)
45
46/* CPCAP_REG_ASSIGN3 bits - Resource Assignment 3 */
47#define CPCAP_BIT_VUSBINT2_SEL BIT(15)
48#define CPCAP_BIT_VUSBINT1_SEL BIT(14)
49#define CPCAP_BIT_VVIB_SEL BIT(13)
50#define CPCAP_BIT_VWLAN1_SEL BIT(12)
51#define CPCAP_BIT_VRF1_SEL BIT(11)
52#define CPCAP_BIT_VHVIO_SEL BIT(10)
53#define CPCAP_BIT_VDAC_SEL BIT(9)
54#define CPCAP_BIT_VUSB_SEL BIT(8)
55#define CPCAP_BIT_VSIM_SEL BIT(7)
56#define CPCAP_BIT_VRFREF_SEL BIT(6)
57#define CPCAP_BIT_VPLL_SEL BIT(5)
58#define CPCAP_BIT_VFUSE_SEL BIT(4)
59#define CPCAP_BIT_VCSI_SEL BIT(3)
60#define CPCAP_BIT_SPARE_14_2 BIT(2)
61#define CPCAP_BIT_VWLAN2_SEL BIT(1)
62#define CPCAP_BIT_VRF2_SEL BIT(0)
63
64/* CPCAP_REG_ASSIGN4 bits - Resource Assignment 4 */
65#define CPCAP_BIT_VAUDIO_SEL BIT(0)
66
67/*
68 * Enable register bits. At least CPCAP_BIT_AUDIO_LOW_PWR is generic,
69 * and not limited to audio regulator. Let's use the Motorola kernel
70 * naming for now until we have a better understanding of the other
71 * enable register bits. No idea why BIT(3) is not defined.
72 */
73#define CPCAP_BIT_AUDIO_LOW_PWR BIT(6)
74#define CPCAP_BIT_AUD_LOWPWR_SPEED BIT(5)
75#define CPCAP_BIT_VAUDIOPRISTBY BIT(4)
76#define CPCAP_BIT_VAUDIO_MODE1 BIT(2)
77#define CPCAP_BIT_VAUDIO_MODE0 BIT(1)
78#define CPCAP_BIT_V_AUDIO_EN BIT(0)
79
Sebastian Reichel91a024e2017-07-10 16:33:39 +020080#define CPCAP_BIT_AUDIO_NORMAL_MODE 0x00
81
Tony Lindgren0ad4c072017-02-02 15:43:57 -080082/*
83 * Off mode configuration bit. Used currently only by SW5 on omap4. There's
84 * the following comment in Motorola Linux kernel tree for it:
85 *
86 * When set in the regulator mode, the regulator assignment will be changed
87 * to secondary when the regulator is disabled. The mode will be set back to
88 * primary when the regulator is turned on.
89 */
90#define CPCAP_REG_OFF_MODE_SEC BIT(15)
91
92/**
93 * SoC specific configuraion for CPCAP regulator. There are at least three
94 * different SoCs each with their own parameters: omap3, omap4 and tegra2.
95 *
96 * The assign_reg and assign_mask seem to allow toggling between primary
97 * and secondary mode that at least omap4 uses for off mode.
98 */
99struct cpcap_regulator {
100 struct regulator_desc rdesc;
101 const u16 assign_reg;
102 const u16 assign_mask;
103 const u16 vsel_shift;
104};
105
106#define CPCAP_REG(_ID, reg, assignment_reg, assignment_mask, val_tbl, \
107 mode_mask, volt_mask, volt_shft, \
108 mode_val, off_val, volt_trans_time) { \
109 .rdesc = { \
110 .name = #_ID, \
111 .of_match = of_match_ptr(#_ID), \
112 .ops = &cpcap_regulator_ops, \
113 .regulators_node = of_match_ptr("regulators"), \
114 .type = REGULATOR_VOLTAGE, \
115 .id = CPCAP_##_ID, \
116 .owner = THIS_MODULE, \
117 .n_voltages = ARRAY_SIZE(val_tbl), \
118 .volt_table = (val_tbl), \
119 .vsel_reg = (reg), \
120 .vsel_mask = (volt_mask), \
121 .enable_reg = (reg), \
122 .enable_mask = (mode_mask), \
123 .enable_val = (mode_val), \
124 .disable_val = (off_val), \
125 .ramp_delay = (volt_trans_time), \
Sebastian Reichel74ff8e02017-07-10 16:33:40 +0200126 .of_map_mode = cpcap_map_mode, \
Tony Lindgren0ad4c072017-02-02 15:43:57 -0800127 }, \
128 .assign_reg = (assignment_reg), \
129 .assign_mask = (assignment_mask), \
130 .vsel_shift = (volt_shft), \
131}
132
133struct cpcap_ddata {
134 struct regmap *reg;
135 struct device *dev;
136 const struct cpcap_regulator *soc;
137};
138
139enum cpcap_regulator_id {
140 CPCAP_SW1,
141 CPCAP_SW2,
142 CPCAP_SW3,
143 CPCAP_SW4,
144 CPCAP_SW5,
145 CPCAP_SW6,
146 CPCAP_VCAM,
147 CPCAP_VCSI,
148 CPCAP_VDAC,
149 CPCAP_VDIG,
150 CPCAP_VFUSE,
151 CPCAP_VHVIO,
152 CPCAP_VSDIO,
153 CPCAP_VPLL,
154 CPCAP_VRF1,
155 CPCAP_VRF2,
156 CPCAP_VRFREF,
157 CPCAP_VWLAN1,
158 CPCAP_VWLAN2,
159 CPCAP_VSIM,
160 CPCAP_VSIMCARD,
161 CPCAP_VVIB,
162 CPCAP_VUSB,
163 CPCAP_VAUDIO,
164 CPCAP_NR_REGULATORS,
165};
166
167/*
168 * We need to also configure regulator idle mode for SoC off mode if
169 * CPCAP_REG_OFF_MODE_SEC is set.
170 */
171static int cpcap_regulator_enable(struct regulator_dev *rdev)
172{
173 struct cpcap_regulator *regulator = rdev_get_drvdata(rdev);
174 int error, ignore;
175
176 error = regulator_enable_regmap(rdev);
177 if (error)
178 return error;
179
180 if (rdev->desc->enable_val & CPCAP_REG_OFF_MODE_SEC) {
181 error = regmap_update_bits(rdev->regmap, regulator->assign_reg,
182 regulator->assign_mask,
183 regulator->assign_mask);
184 if (error)
185 ignore = regulator_disable_regmap(rdev);
186 }
187
188 return error;
189}
190
191/*
192 * We need to also configure regulator idle mode for SoC off mode if
193 * CPCAP_REG_OFF_MODE_SEC is set.
194 */
195static int cpcap_regulator_disable(struct regulator_dev *rdev)
196{
197 struct cpcap_regulator *regulator = rdev_get_drvdata(rdev);
198 int error, ignore;
199
200 if (rdev->desc->enable_val & CPCAP_REG_OFF_MODE_SEC) {
201 error = regmap_update_bits(rdev->regmap, regulator->assign_reg,
202 regulator->assign_mask, 0);
203 if (error)
204 return error;
205 }
206
207 error = regulator_disable_regmap(rdev);
208 if (error && (rdev->desc->enable_val & CPCAP_REG_OFF_MODE_SEC)) {
209 ignore = regmap_update_bits(rdev->regmap, regulator->assign_reg,
210 regulator->assign_mask,
211 regulator->assign_mask);
212 }
213
214 return error;
215}
216
Sebastian Reichel74ff8e02017-07-10 16:33:40 +0200217static unsigned int cpcap_map_mode(unsigned int mode)
218{
219 switch (mode) {
220 case CPCAP_BIT_AUDIO_NORMAL_MODE:
221 return REGULATOR_MODE_NORMAL;
222 case CPCAP_BIT_AUDIO_LOW_PWR:
223 return REGULATOR_MODE_STANDBY;
224 default:
Douglas Anderson02f37032018-04-18 08:54:18 -0700225 return REGULATOR_MODE_INVALID;
Sebastian Reichel74ff8e02017-07-10 16:33:40 +0200226 }
227}
228
Tony Lindgren0ad4c072017-02-02 15:43:57 -0800229static unsigned int cpcap_regulator_get_mode(struct regulator_dev *rdev)
230{
231 int value;
232
233 regmap_read(rdev->regmap, rdev->desc->enable_reg, &value);
234
Sebastian Reichel91a024e2017-07-10 16:33:39 +0200235 if (value & CPCAP_BIT_AUDIO_LOW_PWR)
Tony Lindgren0ad4c072017-02-02 15:43:57 -0800236 return REGULATOR_MODE_STANDBY;
237
238 return REGULATOR_MODE_NORMAL;
239}
240
241static int cpcap_regulator_set_mode(struct regulator_dev *rdev,
242 unsigned int mode)
243{
244 int value;
245
246 switch (mode) {
247 case REGULATOR_MODE_NORMAL:
Sebastian Reichel91a024e2017-07-10 16:33:39 +0200248 value = CPCAP_BIT_AUDIO_NORMAL_MODE;
Tony Lindgren0ad4c072017-02-02 15:43:57 -0800249 break;
250 case REGULATOR_MODE_STANDBY:
Sebastian Reichel91a024e2017-07-10 16:33:39 +0200251 value = CPCAP_BIT_AUDIO_LOW_PWR;
Tony Lindgren0ad4c072017-02-02 15:43:57 -0800252 break;
253 default:
254 return -EINVAL;
255 }
256
257 return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
258 CPCAP_BIT_AUDIO_LOW_PWR, value);
259}
260
261static struct regulator_ops cpcap_regulator_ops = {
262 .enable = cpcap_regulator_enable,
263 .disable = cpcap_regulator_disable,
264 .is_enabled = regulator_is_enabled_regmap,
265 .list_voltage = regulator_list_voltage_table,
266 .map_voltage = regulator_map_voltage_iterate,
267 .get_voltage_sel = regulator_get_voltage_sel_regmap,
268 .set_voltage_sel = regulator_set_voltage_sel_regmap,
269 .get_mode = cpcap_regulator_get_mode,
270 .set_mode = cpcap_regulator_set_mode,
271};
272
273static const unsigned int unknown_val_tbl[] = { 0, };
Peter Geisad662252018-07-24 09:25:40 -0400274static const unsigned int sw2_sw4_val_tbl[] = { 612500, 625000, 637500,
275 650000, 662500, 675000,
276 687500, 700000, 712500,
277 725000, 737500, 750000,
278 762500, 775000, 787500,
279 800000, 812500, 825000,
280 837500, 850000, 862500,
281 875000, 887500, 900000,
282 912500, 925000, 937500,
283 950000, 962500, 975000,
284 987500, 1000000, 1012500,
285 1025000, 1037500, 1050000,
286 1062500, 1075000, 1087500,
287 1100000, 1112500, 1125000,
288 1137500, 1150000, 1162500,
289 1175000, 1187500, 1200000,
290 1212500, 1225000, 1237500,
291 1250000, 1262500, 1275000,
292 1287500, 1300000, 1312500,
293 1325000, 1337500, 1350000,
294 1362500, 1375000, 1387500,
295 1400000, 1412500, 1425000,
296 1437500, 1450000, 1462500, };
Tony Lindgren0ad4c072017-02-02 15:43:57 -0800297static const unsigned int sw5_val_tbl[] = { 0, 5050000, };
298static const unsigned int vcam_val_tbl[] = { 2600000, 2700000, 2800000,
299 2900000, };
300static const unsigned int vcsi_val_tbl[] = { 1200000, 1800000, };
301static const unsigned int vdac_val_tbl[] = { 1200000, 1500000, 1800000,
302 2500000,};
303static const unsigned int vdig_val_tbl[] = { 1200000, 1350000, 1500000,
304 1875000, };
305static const unsigned int vfuse_val_tbl[] = { 1500000, 1600000, 1700000,
306 1800000, 1900000, 2000000,
307 2100000, 2200000, 2300000,
308 2400000, 2500000, 2600000,
309 2700000, 3150000, };
310static const unsigned int vhvio_val_tbl[] = { 2775000, };
311static const unsigned int vsdio_val_tbl[] = { 1500000, 1600000, 1800000,
312 2600000, 2700000, 2800000,
313 2900000, 3000000, };
314static const unsigned int vpll_val_tbl[] = { 1200000, 1300000, 1400000,
315 1800000, };
316/* Quirk: 2775000 is before 2500000 for vrf1 regulator */
317static const unsigned int vrf1_val_tbl[] = { 2775000, 2500000, };
318static const unsigned int vrf2_val_tbl[] = { 0, 2775000, };
319static const unsigned int vrfref_val_tbl[] = { 2500000, 2775000, };
320static const unsigned int vwlan1_val_tbl[] = { 1800000, 1900000, };
321static const unsigned int vwlan2_val_tbl[] = { 2775000, 3000000, 3300000,
322 3300000, };
323static const unsigned int vsim_val_tbl[] = { 1800000, 2900000, };
324static const unsigned int vsimcard_val_tbl[] = { 1800000, 2900000, };
325static const unsigned int vvib_val_tbl[] = { 1300000, 1800000, 2000000,
326 3000000, };
327static const unsigned int vusb_val_tbl[] = { 0, 3300000, };
328static const unsigned int vaudio_val_tbl[] = { 0, 2775000, };
329
330/**
331 * SoC specific configuration for omap4. The data below is comes from Motorola
332 * Linux kernel tree. It's basically the values of cpcap_regltr_data,
333 * cpcap_regulator_mode_values and cpcap_regulator_off_mode_values, see
334 * CPCAP_REG macro above.
335 *
336 * SW1 to SW4 and SW6 seems to be unused for mapphone. Note that VSIM and
337 * VSIMCARD have a shared resource assignment bit.
338 */
339static struct cpcap_regulator omap4_regulators[] = {
340 CPCAP_REG(SW1, CPCAP_REG_S1C1, CPCAP_REG_ASSIGN2,
341 CPCAP_BIT_SW1_SEL, unknown_val_tbl,
342 0, 0, 0, 0, 0, 0),
343 CPCAP_REG(SW2, CPCAP_REG_S2C1, CPCAP_REG_ASSIGN2,
344 CPCAP_BIT_SW2_SEL, unknown_val_tbl,
345 0, 0, 0, 0, 0, 0),
346 CPCAP_REG(SW3, CPCAP_REG_S3C, CPCAP_REG_ASSIGN2,
347 CPCAP_BIT_SW3_SEL, unknown_val_tbl,
348 0, 0, 0, 0, 0, 0),
349 CPCAP_REG(SW4, CPCAP_REG_S4C1, CPCAP_REG_ASSIGN2,
350 CPCAP_BIT_SW4_SEL, unknown_val_tbl,
351 0, 0, 0, 0, 0, 0),
352 CPCAP_REG(SW5, CPCAP_REG_S5C, CPCAP_REG_ASSIGN2,
353 CPCAP_BIT_SW5_SEL, sw5_val_tbl,
354 0x28, 0, 0, 0x20 | CPCAP_REG_OFF_MODE_SEC, 0, 0),
355 CPCAP_REG(SW6, CPCAP_REG_S6C, CPCAP_REG_ASSIGN2,
356 CPCAP_BIT_SW6_SEL, unknown_val_tbl,
357 0, 0, 0, 0, 0, 0),
358 CPCAP_REG(VCAM, CPCAP_REG_VCAMC, CPCAP_REG_ASSIGN2,
359 CPCAP_BIT_VCAM_SEL, vcam_val_tbl,
360 0x87, 0x30, 4, 0x3, 0, 420),
361 CPCAP_REG(VCSI, CPCAP_REG_VCSIC, CPCAP_REG_ASSIGN3,
362 CPCAP_BIT_VCSI_SEL, vcsi_val_tbl,
363 0x47, 0x10, 4, 0x43, 0x41, 350),
364 CPCAP_REG(VDAC, CPCAP_REG_VDACC, CPCAP_REG_ASSIGN3,
365 CPCAP_BIT_VDAC_SEL, vdac_val_tbl,
366 0x87, 0x30, 4, 0x3, 0, 420),
367 CPCAP_REG(VDIG, CPCAP_REG_VDIGC, CPCAP_REG_ASSIGN2,
368 CPCAP_BIT_VDIG_SEL, vdig_val_tbl,
369 0x87, 0x30, 4, 0x82, 0, 420),
370 CPCAP_REG(VFUSE, CPCAP_REG_VFUSEC, CPCAP_REG_ASSIGN3,
371 CPCAP_BIT_VFUSE_SEL, vfuse_val_tbl,
372 0x80, 0xf, 0, 0x80, 0, 420),
373 CPCAP_REG(VHVIO, CPCAP_REG_VHVIOC, CPCAP_REG_ASSIGN3,
374 CPCAP_BIT_VHVIO_SEL, vhvio_val_tbl,
375 0x17, 0, 0, 0, 0x12, 0),
376 CPCAP_REG(VSDIO, CPCAP_REG_VSDIOC, CPCAP_REG_ASSIGN2,
377 CPCAP_BIT_VSDIO_SEL, vsdio_val_tbl,
378 0x87, 0x38, 3, 0x82, 0, 420),
379 CPCAP_REG(VPLL, CPCAP_REG_VPLLC, CPCAP_REG_ASSIGN3,
380 CPCAP_BIT_VPLL_SEL, vpll_val_tbl,
381 0x43, 0x18, 3, 0x2, 0, 420),
382 CPCAP_REG(VRF1, CPCAP_REG_VRF1C, CPCAP_REG_ASSIGN3,
383 CPCAP_BIT_VRF1_SEL, vrf1_val_tbl,
384 0xac, 0x2, 1, 0x4, 0, 10),
385 CPCAP_REG(VRF2, CPCAP_REG_VRF2C, CPCAP_REG_ASSIGN3,
386 CPCAP_BIT_VRF2_SEL, vrf2_val_tbl,
387 0x23, 0x8, 3, 0, 0, 10),
388 CPCAP_REG(VRFREF, CPCAP_REG_VRFREFC, CPCAP_REG_ASSIGN3,
389 CPCAP_BIT_VRFREF_SEL, vrfref_val_tbl,
390 0x23, 0x8, 3, 0, 0, 420),
391 CPCAP_REG(VWLAN1, CPCAP_REG_VWLAN1C, CPCAP_REG_ASSIGN3,
392 CPCAP_BIT_VWLAN1_SEL, vwlan1_val_tbl,
393 0x47, 0x10, 4, 0, 0, 420),
394 CPCAP_REG(VWLAN2, CPCAP_REG_VWLAN2C, CPCAP_REG_ASSIGN3,
395 CPCAP_BIT_VWLAN2_SEL, vwlan2_val_tbl,
396 0x20c, 0xc0, 6, 0x20c, 0, 420),
397 CPCAP_REG(VSIM, CPCAP_REG_VSIMC, CPCAP_REG_ASSIGN3,
398 0xffff, vsim_val_tbl,
399 0x23, 0x8, 3, 0x3, 0, 420),
400 CPCAP_REG(VSIMCARD, CPCAP_REG_VSIMC, CPCAP_REG_ASSIGN3,
401 0xffff, vsimcard_val_tbl,
402 0x1e80, 0x8, 3, 0x1e00, 0, 420),
403 CPCAP_REG(VVIB, CPCAP_REG_VVIBC, CPCAP_REG_ASSIGN3,
404 CPCAP_BIT_VVIB_SEL, vvib_val_tbl,
405 0x1, 0xc, 2, 0x1, 0, 500),
406 CPCAP_REG(VUSB, CPCAP_REG_VUSBC, CPCAP_REG_ASSIGN3,
407 CPCAP_BIT_VUSB_SEL, vusb_val_tbl,
408 0x11c, 0x40, 6, 0xc, 0, 0),
409 CPCAP_REG(VAUDIO, CPCAP_REG_VAUDIOC, CPCAP_REG_ASSIGN4,
410 CPCAP_BIT_VAUDIO_SEL, vaudio_val_tbl,
411 0x16, 0x1, 0, 0x4, 0, 0),
412 { /* sentinel */ },
413};
414
Peter Geis6c0b3192018-07-24 09:25:41 -0400415static struct cpcap_regulator xoom_regulators[] = {
416 CPCAP_REG(SW1, CPCAP_REG_S1C1, CPCAP_REG_ASSIGN2,
417 CPCAP_BIT_SW1_SEL, unknown_val_tbl,
418 0, 0, 0, 0, 0, 0),
419 CPCAP_REG(SW2, CPCAP_REG_S2C1, CPCAP_REG_ASSIGN2,
420 CPCAP_BIT_SW2_SEL, sw2_sw4_val_tbl,
421 0xf00, 0x7f, 0, 0x800, 0, 120),
422 CPCAP_REG(SW3, CPCAP_REG_S3C, CPCAP_REG_ASSIGN2,
423 CPCAP_BIT_SW3_SEL, unknown_val_tbl,
424 0, 0, 0, 0, 0, 0),
425 CPCAP_REG(SW4, CPCAP_REG_S4C1, CPCAP_REG_ASSIGN2,
426 CPCAP_BIT_SW4_SEL, sw2_sw4_val_tbl,
427 0xf00, 0x7f, 0, 0x900, 0, 100),
428 CPCAP_REG(SW5, CPCAP_REG_S5C, CPCAP_REG_ASSIGN2,
429 CPCAP_BIT_SW5_SEL, sw5_val_tbl,
430 0x2a, 0, 0, 0x22, 0, 0),
431 CPCAP_REG(SW6, CPCAP_REG_S6C, CPCAP_REG_ASSIGN2,
432 CPCAP_BIT_SW6_SEL, unknown_val_tbl,
433 0, 0, 0, 0, 0, 0),
434 CPCAP_REG(VCAM, CPCAP_REG_VCAMC, CPCAP_REG_ASSIGN2,
435 CPCAP_BIT_VCAM_SEL, vcam_val_tbl,
436 0x87, 0x30, 4, 0x7, 0, 420),
437 CPCAP_REG(VCSI, CPCAP_REG_VCSIC, CPCAP_REG_ASSIGN3,
438 CPCAP_BIT_VCSI_SEL, vcsi_val_tbl,
439 0x47, 0x10, 4, 0x7, 0, 350),
440 CPCAP_REG(VDAC, CPCAP_REG_VDACC, CPCAP_REG_ASSIGN3,
441 CPCAP_BIT_VDAC_SEL, vdac_val_tbl,
442 0x87, 0x30, 4, 0x3, 0, 420),
443 CPCAP_REG(VDIG, CPCAP_REG_VDIGC, CPCAP_REG_ASSIGN2,
444 CPCAP_BIT_VDIG_SEL, vdig_val_tbl,
445 0x87, 0x30, 4, 0x5, 0, 420),
446 CPCAP_REG(VFUSE, CPCAP_REG_VFUSEC, CPCAP_REG_ASSIGN3,
447 CPCAP_BIT_VFUSE_SEL, vfuse_val_tbl,
448 0x80, 0xf, 0, 0x80, 0, 420),
449 CPCAP_REG(VHVIO, CPCAP_REG_VHVIOC, CPCAP_REG_ASSIGN3,
450 CPCAP_BIT_VHVIO_SEL, vhvio_val_tbl,
451 0x17, 0, 0, 0x2, 0, 0),
452 CPCAP_REG(VSDIO, CPCAP_REG_VSDIOC, CPCAP_REG_ASSIGN2,
453 CPCAP_BIT_VSDIO_SEL, vsdio_val_tbl,
454 0x87, 0x38, 3, 0x2, 0, 420),
455 CPCAP_REG(VPLL, CPCAP_REG_VPLLC, CPCAP_REG_ASSIGN3,
456 CPCAP_BIT_VPLL_SEL, vpll_val_tbl,
457 0x43, 0x18, 3, 0x1, 0, 420),
458 CPCAP_REG(VRF1, CPCAP_REG_VRF1C, CPCAP_REG_ASSIGN3,
459 CPCAP_BIT_VRF1_SEL, vrf1_val_tbl,
460 0xac, 0x2, 1, 0xc, 0, 10),
461 CPCAP_REG(VRF2, CPCAP_REG_VRF2C, CPCAP_REG_ASSIGN3,
462 CPCAP_BIT_VRF2_SEL, vrf2_val_tbl,
463 0x23, 0x8, 3, 0x3, 0, 10),
464 CPCAP_REG(VRFREF, CPCAP_REG_VRFREFC, CPCAP_REG_ASSIGN3,
465 CPCAP_BIT_VRFREF_SEL, vrfref_val_tbl,
466 0x23, 0x8, 3, 0x3, 0, 420),
467 CPCAP_REG(VWLAN1, CPCAP_REG_VWLAN1C, CPCAP_REG_ASSIGN3,
468 CPCAP_BIT_VWLAN1_SEL, vwlan1_val_tbl,
469 0x47, 0x10, 4, 0x5, 0, 420),
470 CPCAP_REG(VWLAN2, CPCAP_REG_VWLAN2C, CPCAP_REG_ASSIGN3,
471 CPCAP_BIT_VWLAN2_SEL, vwlan2_val_tbl,
472 0x20c, 0xc0, 6, 0x8, 0, 420),
473 CPCAP_REG(VSIM, CPCAP_REG_VSIMC, CPCAP_REG_ASSIGN3,
474 0xffff, vsim_val_tbl,
475 0x23, 0x8, 3, 0x3, 0, 420),
476 CPCAP_REG(VSIMCARD, CPCAP_REG_VSIMC, CPCAP_REG_ASSIGN3,
477 0xffff, vsimcard_val_tbl,
478 0x1e80, 0x8, 3, 0x1e00, 0, 420),
479 CPCAP_REG(VVIB, CPCAP_REG_VVIBC, CPCAP_REG_ASSIGN3,
480 CPCAP_BIT_VVIB_SEL, vvib_val_tbl,
481 0x1, 0xc, 2, 0, 0x1, 500),
482 CPCAP_REG(VUSB, CPCAP_REG_VUSBC, CPCAP_REG_ASSIGN3,
483 CPCAP_BIT_VUSB_SEL, vusb_val_tbl,
484 0x11c, 0x40, 6, 0xc, 0, 0),
485 CPCAP_REG(VAUDIO, CPCAP_REG_VAUDIOC, CPCAP_REG_ASSIGN4,
486 CPCAP_BIT_VAUDIO_SEL, vaudio_val_tbl,
487 0x16, 0x1, 0, 0x4, 0, 0),
488 { /* sentinel */ },
489};
490
Tony Lindgren0ad4c072017-02-02 15:43:57 -0800491static const struct of_device_id cpcap_regulator_id_table[] = {
492 {
493 .compatible = "motorola,cpcap-regulator",
494 },
495 {
496 .compatible = "motorola,mapphone-cpcap-regulator",
497 .data = omap4_regulators,
498 },
Peter Geis6c0b3192018-07-24 09:25:41 -0400499 {
500 .compatible = "motorola,xoom-cpcap-regulator",
501 .data = xoom_regulators,
502 },
Tony Lindgren0ad4c072017-02-02 15:43:57 -0800503 {},
504};
505MODULE_DEVICE_TABLE(of, cpcap_regulator_id_table);
506
507static int cpcap_regulator_probe(struct platform_device *pdev)
508{
509 struct cpcap_ddata *ddata;
510 const struct of_device_id *match;
511 struct regulator_config config;
512 struct regulator_init_data init_data;
513 int i;
514
515 match = of_match_device(of_match_ptr(cpcap_regulator_id_table),
516 &pdev->dev);
517 if (!match)
518 return -EINVAL;
519
520 if (!match->data) {
521 dev_err(&pdev->dev, "no configuration data found\n");
522
523 return -ENODEV;
524 }
525
526 ddata = devm_kzalloc(&pdev->dev, sizeof(*ddata), GFP_KERNEL);
527 if (!ddata)
528 return -ENOMEM;
529
530 ddata->reg = dev_get_regmap(pdev->dev.parent, NULL);
531 if (!ddata->reg)
532 return -ENODEV;
533
534 ddata->dev = &pdev->dev;
535 ddata->soc = match->data;
536 platform_set_drvdata(pdev, ddata);
537
538 memset(&config, 0, sizeof(config));
539 memset(&init_data, 0, sizeof(init_data));
540 config.dev = &pdev->dev;
541 config.regmap = ddata->reg;
542 config.init_data = &init_data;
543
544 for (i = 0; i < CPCAP_NR_REGULATORS; i++) {
545 const struct cpcap_regulator *regulator = &ddata->soc[i];
546 struct regulator_dev *rdev;
547
548 if (!regulator->rdesc.name)
549 break;
550
551 if (regulator->rdesc.volt_table == unknown_val_tbl)
552 continue;
553
554 config.driver_data = (void *)regulator;
555 rdev = devm_regulator_register(&pdev->dev,
556 &regulator->rdesc,
557 &config);
558 if (IS_ERR(rdev)) {
559 dev_err(&pdev->dev, "failed to register regulator %s\n",
560 regulator->rdesc.name);
561
562 return PTR_ERR(rdev);
563 }
564 }
565
566 return 0;
567}
568
569static struct platform_driver cpcap_regulator_driver = {
570 .probe = cpcap_regulator_probe,
571 .driver = {
572 .name = "cpcap-regulator",
573 .of_match_table = of_match_ptr(cpcap_regulator_id_table),
574 },
575};
576
577module_platform_driver(cpcap_regulator_driver);
578
579MODULE_ALIAS("platform:cpcap-regulator");
580MODULE_AUTHOR("Tony Lindgren <tony@atomide.com>");
581MODULE_DESCRIPTION("CPCAP regulator driver");
582MODULE_LICENSE("GPL v2");