aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2016-07-20 13:02:01 -0400
committerMark Brown <broonie@kernel.org>2016-07-20 13:02:01 -0400
commit38cdaddf56c56e6c99360942ca4d3eaf4c99d184 (patch)
tree4a834878bfea025bcda03ebf829c018e72ab7284
parent02214f10610e5e5d1187db1f594f2aba20e1a52e (diff)
parent636e2a39cf904946a0e062bc05445149b366ba2e (diff)
Merge remote-tracking branch 'regulator/topic/axp20x' into regulator-next
-rw-r--r--Documentation/devicetree/bindings/mfd/axp20x.txt6
-rw-r--r--drivers/regulator/axp20x-regulator.c147
2 files changed, 125 insertions, 28 deletions
diff --git a/Documentation/devicetree/bindings/mfd/axp20x.txt b/Documentation/devicetree/bindings/mfd/axp20x.txt
index d20b1034e967..585a95546288 100644
--- a/Documentation/devicetree/bindings/mfd/axp20x.txt
+++ b/Documentation/devicetree/bindings/mfd/axp20x.txt
@@ -22,6 +22,11 @@ Optional properties:
22 AXP152/20X: range: 750-1875, Default: 1.5 MHz 22 AXP152/20X: range: 750-1875, Default: 1.5 MHz
23 AXP22X/80X: range: 1800-4050, Default: 3 MHz 23 AXP22X/80X: range: 1800-4050, Default: 3 MHz
24 24
25- x-powers,drive-vbus-en: axp221 / axp223 only boolean, set this when the
26 N_VBUSEN pin is used as an output pin to control an external
27 regulator to drive the OTG VBus, rather then as an input pin
28 which signals whether the board is driving OTG VBus or not.
29
25- <input>-supply: a phandle to the regulator supply node. May be omitted if 30- <input>-supply: a phandle to the regulator supply node. May be omitted if
26 inputs are unregulated, such as using the IPSOUT output 31 inputs are unregulated, such as using the IPSOUT output
27 from the PMIC. 32 from the PMIC.
@@ -79,6 +84,7 @@ ELDO3 : LDO : eldoin-supply : shared supply
79LDO_IO0 : LDO : ips-supply : GPIO 0 84LDO_IO0 : LDO : ips-supply : GPIO 0
80LDO_IO1 : LDO : ips-supply : GPIO 1 85LDO_IO1 : LDO : ips-supply : GPIO 1
81RTC_LDO : LDO : ips-supply : always on 86RTC_LDO : LDO : ips-supply : always on
87DRIVEVBUS : Enable output : drivevbus-supply : external regulator
82 88
83AXP809 regulators, type, and corresponding input supply names: 89AXP809 regulators, type, and corresponding input supply names:
84 90
diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c
index 514a5e8fdbab..6d9ac76a772f 100644
--- a/drivers/regulator/axp20x-regulator.c
+++ b/drivers/regulator/axp20x-regulator.c
@@ -36,6 +36,8 @@
36 36
37#define AXP20X_FREQ_DCDC_MASK 0x0f 37#define AXP20X_FREQ_DCDC_MASK 0x0f
38 38
39#define AXP22X_MISC_N_VBUSEN_FUNC BIT(4)
40
39#define AXP_DESC_IO(_family, _id, _match, _supply, _min, _max, _step, _vreg, \ 41#define AXP_DESC_IO(_family, _id, _match, _supply, _min, _max, _step, _vreg, \
40 _vmask, _ereg, _emask, _enable_val, _disable_val) \ 42 _vmask, _ereg, _emask, _enable_val, _disable_val) \
41 [_family##_##_id] = { \ 43 [_family##_##_id] = { \
@@ -230,6 +232,73 @@ static const struct regulator_desc axp22x_regulators[] = {
230 AXP_DESC_FIXED(AXP22X, RTC_LDO, "rtc_ldo", "ips", 3000), 232 AXP_DESC_FIXED(AXP22X, RTC_LDO, "rtc_ldo", "ips", 3000),
231}; 233};
232 234
235static const struct regulator_desc axp22x_drivevbus_regulator = {
236 .name = "drivevbus",
237 .supply_name = "drivevbus",
238 .of_match = of_match_ptr("drivevbus"),
239 .regulators_node = of_match_ptr("regulators"),
240 .type = REGULATOR_VOLTAGE,
241 .owner = THIS_MODULE,
242 .enable_reg = AXP20X_VBUS_IPSOUT_MGMT,
243 .enable_mask = BIT(2),
244 .ops = &axp20x_ops_sw,
245};
246
247static const struct regulator_linear_range axp809_dcdc4_ranges[] = {
248 REGULATOR_LINEAR_RANGE(600000, 0x0, 0x2f, 20000),
249 REGULATOR_LINEAR_RANGE(1800000, 0x30, 0x38, 100000),
250};
251
252static const struct regulator_linear_range axp809_dldo1_ranges[] = {
253 REGULATOR_LINEAR_RANGE(700000, 0x0, 0x1a, 100000),
254 REGULATOR_LINEAR_RANGE(3400000, 0x1b, 0x1f, 200000),
255};
256
257static const struct regulator_desc axp809_regulators[] = {
258 AXP_DESC(AXP809, DCDC1, "dcdc1", "vin1", 1600, 3400, 100,
259 AXP22X_DCDC1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(1)),
260 AXP_DESC(AXP809, DCDC2, "dcdc2", "vin2", 600, 1540, 20,
261 AXP22X_DCDC2_V_OUT, 0x3f, AXP22X_PWR_OUT_CTRL1, BIT(2)),
262 AXP_DESC(AXP809, DCDC3, "dcdc3", "vin3", 600, 1860, 20,
263 AXP22X_DCDC3_V_OUT, 0x3f, AXP22X_PWR_OUT_CTRL1, BIT(3)),
264 AXP_DESC_RANGES(AXP809, DCDC4, "dcdc4", "vin4", axp809_dcdc4_ranges,
265 57, AXP22X_DCDC4_V_OUT, 0x3f, AXP22X_PWR_OUT_CTRL1,
266 BIT(4)),
267 AXP_DESC(AXP809, DCDC5, "dcdc5", "vin5", 1000, 2550, 50,
268 AXP22X_DCDC5_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(5)),
269 /* secondary switchable output of DCDC1 */
270 AXP_DESC_SW(AXP809, DC1SW, "dc1sw", NULL, AXP22X_PWR_OUT_CTRL2,
271 BIT(7)),
272 /* LDO regulator internally chained to DCDC5 */
273 AXP_DESC(AXP809, DC5LDO, "dc5ldo", NULL, 700, 1400, 100,
274 AXP22X_DC5LDO_V_OUT, 0x7, AXP22X_PWR_OUT_CTRL1, BIT(0)),
275 AXP_DESC(AXP809, ALDO1, "aldo1", "aldoin", 700, 3300, 100,
276 AXP22X_ALDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(6)),
277 AXP_DESC(AXP809, ALDO2, "aldo2", "aldoin", 700, 3300, 100,
278 AXP22X_ALDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL1, BIT(7)),
279 AXP_DESC(AXP809, ALDO3, "aldo3", "aldoin", 700, 3300, 100,
280 AXP22X_ALDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(5)),
281 AXP_DESC_RANGES(AXP809, DLDO1, "dldo1", "dldoin", axp809_dldo1_ranges,
282 32, AXP22X_DLDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2,
283 BIT(3)),
284 AXP_DESC(AXP809, DLDO2, "dldo2", "dldoin", 700, 3300, 100,
285 AXP22X_DLDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(4)),
286 AXP_DESC(AXP809, ELDO1, "eldo1", "eldoin", 700, 3300, 100,
287 AXP22X_ELDO1_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(0)),
288 AXP_DESC(AXP809, ELDO2, "eldo2", "eldoin", 700, 3300, 100,
289 AXP22X_ELDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(1)),
290 AXP_DESC(AXP809, ELDO3, "eldo3", "eldoin", 700, 3300, 100,
291 AXP22X_ELDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(2)),
292 AXP_DESC_IO(AXP809, LDO_IO0, "ldo_io0", "ips", 700, 3300, 100,
293 AXP22X_LDO_IO0_V_OUT, 0x1f, AXP20X_GPIO0_CTRL, 0x07,
294 AXP22X_IO_ENABLED, AXP22X_IO_DISABLED),
295 AXP_DESC_IO(AXP809, LDO_IO1, "ldo_io1", "ips", 700, 3300, 100,
296 AXP22X_LDO_IO1_V_OUT, 0x1f, AXP20X_GPIO1_CTRL, 0x07,
297 AXP22X_IO_ENABLED, AXP22X_IO_DISABLED),
298 AXP_DESC_FIXED(AXP809, RTC_LDO, "rtc_ldo", "ips", 1800),
299 AXP_DESC_SW(AXP809, SW, "sw", "swin", AXP22X_PWR_OUT_CTRL2, BIT(6)),
300};
301
233static int axp20x_set_dcdc_freq(struct platform_device *pdev, u32 dcdcfreq) 302static int axp20x_set_dcdc_freq(struct platform_device *pdev, u32 dcdcfreq)
234{ 303{
235 struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent); 304 struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent);
@@ -245,6 +314,7 @@ static int axp20x_set_dcdc_freq(struct platform_device *pdev, u32 dcdcfreq)
245 break; 314 break;
246 case AXP221_ID: 315 case AXP221_ID:
247 case AXP223_ID: 316 case AXP223_ID:
317 case AXP809_ID:
248 min = 1800; 318 min = 1800;
249 max = 4050; 319 max = 4050;
250 def = 3000; 320 def = 3000;
@@ -324,6 +394,7 @@ static int axp20x_set_dcdc_workmode(struct regulator_dev *rdev, int id, u32 work
324 394
325 case AXP221_ID: 395 case AXP221_ID:
326 case AXP223_ID: 396 case AXP223_ID:
397 case AXP809_ID:
327 if (id < AXP22X_DCDC1 || id > AXP22X_DCDC5) 398 if (id < AXP22X_DCDC1 || id > AXP22X_DCDC5)
328 return -EINVAL; 399 return -EINVAL;
329 400
@@ -352,8 +423,9 @@ static int axp20x_regulator_probe(struct platform_device *pdev)
352 }; 423 };
353 int ret, i, nregulators; 424 int ret, i, nregulators;
354 u32 workmode; 425 u32 workmode;
355 const char *axp22x_dc1_name = axp22x_regulators[AXP22X_DCDC1].name; 426 const char *dcdc1_name = axp22x_regulators[AXP22X_DCDC1].name;
356 const char *axp22x_dc5_name = axp22x_regulators[AXP22X_DCDC5].name; 427 const char *dcdc5_name = axp22x_regulators[AXP22X_DCDC5].name;
428 bool drivevbus = false;
357 429
358 switch (axp20x->variant) { 430 switch (axp20x->variant) {
359 case AXP202_ID: 431 case AXP202_ID:
@@ -365,6 +437,12 @@ static int axp20x_regulator_probe(struct platform_device *pdev)
365 case AXP223_ID: 437 case AXP223_ID:
366 regulators = axp22x_regulators; 438 regulators = axp22x_regulators;
367 nregulators = AXP22X_REG_ID_MAX; 439 nregulators = AXP22X_REG_ID_MAX;
440 drivevbus = of_property_read_bool(pdev->dev.parent->of_node,
441 "x-powers,drive-vbus-en");
442 break;
443 case AXP809_ID:
444 regulators = axp809_regulators;
445 nregulators = AXP809_REG_ID_MAX;
368 break; 446 break;
369 default: 447 default:
370 dev_err(&pdev->dev, "Unsupported AXP variant: %ld\n", 448 dev_err(&pdev->dev, "Unsupported AXP variant: %ld\n",
@@ -388,22 +466,22 @@ static int axp20x_regulator_probe(struct platform_device *pdev)
388 * part of this loop to see where we save the DT defined 466 * part of this loop to see where we save the DT defined
389 * name. 467 * name.
390 */ 468 */
391 if (regulators == axp22x_regulators) { 469 if ((regulators == axp22x_regulators && i == AXP22X_DC1SW) ||
392 if (i == AXP22X_DC1SW) { 470 (regulators == axp809_regulators && i == AXP809_DC1SW)) {
393 new_desc = devm_kzalloc(&pdev->dev, 471 new_desc = devm_kzalloc(&pdev->dev, sizeof(*desc),
394 sizeof(*desc), 472 GFP_KERNEL);
395 GFP_KERNEL); 473 *new_desc = regulators[i];
396 *new_desc = regulators[i]; 474 new_desc->supply_name = dcdc1_name;
397 new_desc->supply_name = axp22x_dc1_name; 475 desc = new_desc;
398 desc = new_desc; 476 }
399 } else if (i == AXP22X_DC5LDO) { 477
400 new_desc = devm_kzalloc(&pdev->dev, 478 if ((regulators == axp22x_regulators && i == AXP22X_DC5LDO) ||
401 sizeof(*desc), 479 (regulators == axp809_regulators && i == AXP809_DC5LDO)) {
402 GFP_KERNEL); 480 new_desc = devm_kzalloc(&pdev->dev, sizeof(*desc),
403 *new_desc = regulators[i]; 481 GFP_KERNEL);
404 new_desc->supply_name = axp22x_dc5_name; 482 *new_desc = regulators[i];
405 desc = new_desc; 483 new_desc->supply_name = dcdc5_name;
406 } 484 desc = new_desc;
407 } 485 }
408 486
409 rdev = devm_regulator_register(&pdev->dev, desc, &config); 487 rdev = devm_regulator_register(&pdev->dev, desc, &config);
@@ -426,16 +504,29 @@ static int axp20x_regulator_probe(struct platform_device *pdev)
426 /* 504 /*
427 * Save AXP22X DCDC1 / DCDC5 regulator names for later. 505 * Save AXP22X DCDC1 / DCDC5 regulator names for later.
428 */ 506 */
429 if (regulators == axp22x_regulators) { 507 if ((regulators == axp22x_regulators && i == AXP22X_DCDC1) ||
430 /* Can we use rdev->constraints->name instead? */ 508 (regulators == axp809_regulators && i == AXP809_DCDC1))
431 if (i == AXP22X_DCDC1) 509 of_property_read_string(rdev->dev.of_node,
432 of_property_read_string(rdev->dev.of_node, 510 "regulator-name",
433 "regulator-name", 511 &dcdc1_name);
434 &axp22x_dc1_name); 512
435 else if (i == AXP22X_DCDC5) 513 if ((regulators == axp22x_regulators && i == AXP22X_DCDC5) ||
436 of_property_read_string(rdev->dev.of_node, 514 (regulators == axp809_regulators && i == AXP809_DCDC5))
437 "regulator-name", 515 of_property_read_string(rdev->dev.of_node,
438 &axp22x_dc5_name); 516 "regulator-name",
517 &dcdc5_name);
518 }
519
520 if (drivevbus) {
521 /* Change N_VBUSEN sense pin to DRIVEVBUS output pin */
522 regmap_update_bits(axp20x->regmap, AXP20X_OVER_TMP,
523 AXP22X_MISC_N_VBUSEN_FUNC, 0);
524 rdev = devm_regulator_register(&pdev->dev,
525 &axp22x_drivevbus_regulator,
526 &config);
527 if (IS_ERR(rdev)) {
528 dev_err(&pdev->dev, "Failed to register drivevbus\n");
529 return PTR_ERR(rdev);
439 } 530 }
440 } 531 }
441 532