aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2015-03-22 18:52:48 -0400
committerFelipe Balbi <balbi@ti.com>2015-05-26 11:44:06 -0400
commitf5e4edb8c888958a970b2d42c47d2871a1a4fcdf (patch)
tree52f6424eac196fe27c5b21f9f9ba88ae7024fcd3
parente842b84c8e7221c45c8dbd7de09185c6149e1cf9 (diff)
power: twl4030_charger: find associated phy by more reliable means.
twl4030_charger currently finds the associated phy using usb_get_phy() which will return the first USB2 phy. If your platform has multiple such phys (as mine does), this is not reliable (and reliably fails on the GTA04). Change to use devm_usb_get_phy_by_node(), having found the node by looking for an appropriately named sibling in device-tree. This makes usb-charging dependent on correct device-tree configuration. Acked-By: Sebastian Reichel <sre@kernel.org> Acked-by: Pavel Machek <pavel@ucw.cz> Signed-off-by: NeilBrown <neilb@suse.de> Signed-off-by: Felipe Balbi <balbi@ti.com>
-rw-r--r--Documentation/devicetree/bindings/power/twl-charger.txt10
-rw-r--r--Documentation/devicetree/bindings/usb/twlxxxx-usb.txt3
-rw-r--r--drivers/power/twl4030_charger.c21
3 files changed, 22 insertions, 12 deletions
diff --git a/Documentation/devicetree/bindings/power/twl-charger.txt b/Documentation/devicetree/bindings/power/twl-charger.txt
index d5c706216df5..3b4ea1b73b38 100644
--- a/Documentation/devicetree/bindings/power/twl-charger.txt
+++ b/Documentation/devicetree/bindings/power/twl-charger.txt
@@ -1,5 +1,15 @@
1TWL BCI (Battery Charger Interface) 1TWL BCI (Battery Charger Interface)
2 2
3The battery charger needs to interact with the USB phy in order
4to know when charging is permissible, and when there is a connection
5or disconnection.
6
7The choice of phy cannot be configured at a hardware level, so there
8is no value in explicit configuration in device-tree. Rather
9if there is a sibling of the BCI node which is compatible with
10"ti,twl4030-usb", then that is used to determine when and how
11use USB power for charging.
12
3Required properties: 13Required properties:
4- compatible: 14- compatible:
5 - "ti,twl4030-bci" 15 - "ti,twl4030-bci"
diff --git a/Documentation/devicetree/bindings/usb/twlxxxx-usb.txt b/Documentation/devicetree/bindings/usb/twlxxxx-usb.txt
index 0aee0ad3f035..17327a296110 100644
--- a/Documentation/devicetree/bindings/usb/twlxxxx-usb.txt
+++ b/Documentation/devicetree/bindings/usb/twlxxxx-usb.txt
@@ -30,6 +30,9 @@ TWL4030 USB PHY AND COMPARATOR
30 - usb_mode : The mode used by the phy to connect to the controller. "1" 30 - usb_mode : The mode used by the phy to connect to the controller. "1"
31 specifies "ULPI" mode and "2" specifies "CEA2011_3PIN" mode. 31 specifies "ULPI" mode and "2" specifies "CEA2011_3PIN" mode.
32 32
33If a sibling node is compatible "ti,twl4030-bci", then it will find
34this device and query it for USB power status.
35
33twl4030-usb { 36twl4030-usb {
34 compatible = "ti,twl4030-usb"; 37 compatible = "ti,twl4030-usb";
35 interrupts = < 10 4 >; 38 interrupts = < 10 4 >;
diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c
index 02a522cb7753..022b8910e443 100644
--- a/drivers/power/twl4030_charger.c
+++ b/drivers/power/twl4030_charger.c
@@ -638,10 +638,15 @@ static int __init twl4030_bci_probe(struct platform_device *pdev)
638 638
639 INIT_WORK(&bci->work, twl4030_bci_usb_work); 639 INIT_WORK(&bci->work, twl4030_bci_usb_work);
640 640
641 bci->transceiver = usb_get_phy(USB_PHY_TYPE_USB2); 641 bci->usb_nb.notifier_call = twl4030_bci_usb_ncb;
642 if (!IS_ERR_OR_NULL(bci->transceiver)) { 642 if (bci->dev->of_node) {
643 bci->usb_nb.notifier_call = twl4030_bci_usb_ncb; 643 struct device_node *phynode;
644 usb_register_notifier(bci->transceiver, &bci->usb_nb); 644
645 phynode = of_find_compatible_node(bci->dev->of_node->parent,
646 NULL, "ti,twl4030-usb");
647 if (phynode)
648 bci->transceiver = devm_usb_get_phy_by_node(
649 bci->dev, phynode, &bci->usb_nb);
645 } 650 }
646 651
647 /* Enable interrupts now. */ 652 /* Enable interrupts now. */
@@ -671,10 +676,6 @@ static int __init twl4030_bci_probe(struct platform_device *pdev)
671 return 0; 676 return 0;
672 677
673fail_unmask_interrupts: 678fail_unmask_interrupts:
674 if (!IS_ERR_OR_NULL(bci->transceiver)) {
675 usb_unregister_notifier(bci->transceiver, &bci->usb_nb);
676 usb_put_phy(bci->transceiver);
677 }
678 free_irq(bci->irq_bci, bci); 679 free_irq(bci->irq_bci, bci);
679fail_bci_irq: 680fail_bci_irq:
680 free_irq(bci->irq_chg, bci); 681 free_irq(bci->irq_chg, bci);
@@ -703,10 +704,6 @@ static int __exit twl4030_bci_remove(struct platform_device *pdev)
703 twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xff, 704 twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, 0xff,
704 TWL4030_INTERRUPTS_BCIIMR2A); 705 TWL4030_INTERRUPTS_BCIIMR2A);
705 706
706 if (!IS_ERR_OR_NULL(bci->transceiver)) {
707 usb_unregister_notifier(bci->transceiver, &bci->usb_nb);
708 usb_put_phy(bci->transceiver);
709 }
710 free_irq(bci->irq_bci, bci); 707 free_irq(bci->irq_bci, bci);
711 free_irq(bci->irq_chg, bci); 708 free_irq(bci->irq_chg, bci);
712 power_supply_unregister(bci->usb); 709 power_supply_unregister(bci->usb);