diff options
author | Roger Quadros <ext-roger.quadros@nokia.com> | 2009-09-30 11:26:37 -0400 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2009-10-12 09:19:23 -0400 |
commit | f8ebdff08740709a75e796f12cc5902e3b5b9dd6 (patch) | |
tree | 3b0941b5e196ddeb8d9b109f8c4471d4246c660b | |
parent | d93a8f829fe1d2f3002f2c6ddb553d12db420412 (diff) |
mfd: Fix twl4030 boot with twl4030 usb transceiver enabled
The usb regulator supplies (usb1v5, usb1v8 & usb3v1) must be available
before adding the twl4030_usb child, else twl4030_usb_ldo_init() will
always fail thus causing boot lock-up.
This patch fixes boot on OMAP systems using the twl4030 usb transceiver.
CONFIG_TWL4030_USB=y
Signed-off-by: Roger Quadros <ext-roger.quadros@nokia.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
-rw-r--r-- | drivers/mfd/twl4030-core.c | 89 |
1 files changed, 46 insertions, 43 deletions
diff --git a/drivers/mfd/twl4030-core.c b/drivers/mfd/twl4030-core.c index e424cf6d8e9e..e832e975da60 100644 --- a/drivers/mfd/twl4030-core.c +++ b/drivers/mfd/twl4030-core.c | |||
@@ -480,7 +480,6 @@ static int | |||
480 | add_children(struct twl4030_platform_data *pdata, unsigned long features) | 480 | add_children(struct twl4030_platform_data *pdata, unsigned long features) |
481 | { | 481 | { |
482 | struct device *child; | 482 | struct device *child; |
483 | struct device *usb_transceiver = NULL; | ||
484 | 483 | ||
485 | if (twl_has_bci() && pdata->bci && !(features & TPS_SUBSET)) { | 484 | if (twl_has_bci() && pdata->bci && !(features & TPS_SUBSET)) { |
486 | child = add_child(3, "twl4030_bci", | 485 | child = add_child(3, "twl4030_bci", |
@@ -532,16 +531,61 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features) | |||
532 | } | 531 | } |
533 | 532 | ||
534 | if (twl_has_usb() && pdata->usb) { | 533 | if (twl_has_usb() && pdata->usb) { |
534 | |||
535 | static struct regulator_consumer_supply usb1v5 = { | ||
536 | .supply = "usb1v5", | ||
537 | }; | ||
538 | static struct regulator_consumer_supply usb1v8 = { | ||
539 | .supply = "usb1v8", | ||
540 | }; | ||
541 | static struct regulator_consumer_supply usb3v1 = { | ||
542 | .supply = "usb3v1", | ||
543 | }; | ||
544 | |||
545 | /* First add the regulators so that they can be used by transceiver */ | ||
546 | if (twl_has_regulator()) { | ||
547 | /* this is a template that gets copied */ | ||
548 | struct regulator_init_data usb_fixed = { | ||
549 | .constraints.valid_modes_mask = | ||
550 | REGULATOR_MODE_NORMAL | ||
551 | | REGULATOR_MODE_STANDBY, | ||
552 | .constraints.valid_ops_mask = | ||
553 | REGULATOR_CHANGE_MODE | ||
554 | | REGULATOR_CHANGE_STATUS, | ||
555 | }; | ||
556 | |||
557 | child = add_regulator_linked(TWL4030_REG_VUSB1V5, | ||
558 | &usb_fixed, &usb1v5, 1); | ||
559 | if (IS_ERR(child)) | ||
560 | return PTR_ERR(child); | ||
561 | |||
562 | child = add_regulator_linked(TWL4030_REG_VUSB1V8, | ||
563 | &usb_fixed, &usb1v8, 1); | ||
564 | if (IS_ERR(child)) | ||
565 | return PTR_ERR(child); | ||
566 | |||
567 | child = add_regulator_linked(TWL4030_REG_VUSB3V1, | ||
568 | &usb_fixed, &usb3v1, 1); | ||
569 | if (IS_ERR(child)) | ||
570 | return PTR_ERR(child); | ||
571 | |||
572 | } | ||
573 | |||
535 | child = add_child(0, "twl4030_usb", | 574 | child = add_child(0, "twl4030_usb", |
536 | pdata->usb, sizeof(*pdata->usb), | 575 | pdata->usb, sizeof(*pdata->usb), |
537 | true, | 576 | true, |
538 | /* irq0 = USB_PRES, irq1 = USB */ | 577 | /* irq0 = USB_PRES, irq1 = USB */ |
539 | pdata->irq_base + 8 + 2, pdata->irq_base + 4); | 578 | pdata->irq_base + 8 + 2, pdata->irq_base + 4); |
579 | |||
540 | if (IS_ERR(child)) | 580 | if (IS_ERR(child)) |
541 | return PTR_ERR(child); | 581 | return PTR_ERR(child); |
542 | 582 | ||
543 | /* we need to connect regulators to this transceiver */ | 583 | /* we need to connect regulators to this transceiver */ |
544 | usb_transceiver = child; | 584 | if (twl_has_regulator() && child) { |
585 | usb1v5.dev = child; | ||
586 | usb1v8.dev = child; | ||
587 | usb3v1.dev = child; | ||
588 | } | ||
545 | } | 589 | } |
546 | 590 | ||
547 | if (twl_has_watchdog()) { | 591 | if (twl_has_watchdog()) { |
@@ -580,47 +624,6 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features) | |||
580 | return PTR_ERR(child); | 624 | return PTR_ERR(child); |
581 | } | 625 | } |
582 | 626 | ||
583 | if (twl_has_regulator() && usb_transceiver) { | ||
584 | static struct regulator_consumer_supply usb1v5 = { | ||
585 | .supply = "usb1v5", | ||
586 | }; | ||
587 | static struct regulator_consumer_supply usb1v8 = { | ||
588 | .supply = "usb1v8", | ||
589 | }; | ||
590 | static struct regulator_consumer_supply usb3v1 = { | ||
591 | .supply = "usb3v1", | ||
592 | }; | ||
593 | |||
594 | /* this is a template that gets copied */ | ||
595 | struct regulator_init_data usb_fixed = { | ||
596 | .constraints.valid_modes_mask = | ||
597 | REGULATOR_MODE_NORMAL | ||
598 | | REGULATOR_MODE_STANDBY, | ||
599 | .constraints.valid_ops_mask = | ||
600 | REGULATOR_CHANGE_MODE | ||
601 | | REGULATOR_CHANGE_STATUS, | ||
602 | }; | ||
603 | |||
604 | usb1v5.dev = usb_transceiver; | ||
605 | usb1v8.dev = usb_transceiver; | ||
606 | usb3v1.dev = usb_transceiver; | ||
607 | |||
608 | child = add_regulator_linked(TWL4030_REG_VUSB1V5, &usb_fixed, | ||
609 | &usb1v5, 1); | ||
610 | if (IS_ERR(child)) | ||
611 | return PTR_ERR(child); | ||
612 | |||
613 | child = add_regulator_linked(TWL4030_REG_VUSB1V8, &usb_fixed, | ||
614 | &usb1v8, 1); | ||
615 | if (IS_ERR(child)) | ||
616 | return PTR_ERR(child); | ||
617 | |||
618 | child = add_regulator_linked(TWL4030_REG_VUSB3V1, &usb_fixed, | ||
619 | &usb3v1, 1); | ||
620 | if (IS_ERR(child)) | ||
621 | return PTR_ERR(child); | ||
622 | } | ||
623 | |||
624 | /* maybe add LDOs that are omitted on cost-reduced parts */ | 627 | /* maybe add LDOs that are omitted on cost-reduced parts */ |
625 | if (twl_has_regulator() && !(features & TPS_SUBSET)) { | 628 | if (twl_has_regulator() && !(features & TPS_SUBSET)) { |
626 | child = add_regulator(TWL4030_REG_VPLL2, pdata->vpll2); | 629 | child = add_regulator(TWL4030_REG_VPLL2, pdata->vpll2); |