aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/otg
diff options
context:
space:
mode:
authorKishon Vijay Abraham I <kishon@ti.com>2012-06-22 07:32:46 -0400
committerFelipe Balbi <balbi@ti.com>2012-06-25 07:05:35 -0400
commit662dca54ca67c92b7aa14b9a2ec54acacf33ce45 (patch)
tree80c77434b1c4d33ce4e7db56f284c9ae65e16a8d /drivers/usb/otg
parent721002ec1dd55a52425455826af49cf8853b2d4f (diff)
usb: otg: support for multiple transceivers by a single controller
Add a linked list for keeping multiple PHY instances with different types so that we can have separate USB2 and USB3 PHYs on one single board. _get_phy_ has been changed so that the controller gets the transceiver by type. _remove_phy_ has been added to let the phy be removed from the phy list. Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com> Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/otg')
-rw-r--r--drivers/usb/otg/ab8500-usb.c4
-rw-r--r--drivers/usb/otg/fsl_otg.c6
-rw-r--r--drivers/usb/otg/gpio_vbus.c4
-rw-r--r--drivers/usb/otg/isp1301_omap.c4
-rw-r--r--drivers/usb/otg/msm_otg.c4
-rw-r--r--drivers/usb/otg/mv_otg.c6
-rw-r--r--drivers/usb/otg/nop-usb-xceiv.c4
-rw-r--r--drivers/usb/otg/otg.c96
-rw-r--r--drivers/usb/otg/twl4030-usb.c2
-rw-r--r--drivers/usb/otg/twl6030-usb.c2
10 files changed, 102 insertions, 30 deletions
diff --git a/drivers/usb/otg/ab8500-usb.c b/drivers/usb/otg/ab8500-usb.c
index 672e28c81437..ae8ad561f083 100644
--- a/drivers/usb/otg/ab8500-usb.c
+++ b/drivers/usb/otg/ab8500-usb.c
@@ -529,7 +529,7 @@ static int __devinit ab8500_usb_probe(struct platform_device *pdev)
529 if (err < 0) 529 if (err < 0)
530 goto fail0; 530 goto fail0;
531 531
532 err = usb_add_phy(&ab->phy); 532 err = usb_add_phy(&ab->phy, USB_PHY_TYPE_USB2);
533 if (err) { 533 if (err) {
534 dev_err(&pdev->dev, "Can't register transceiver\n"); 534 dev_err(&pdev->dev, "Can't register transceiver\n");
535 goto fail1; 535 goto fail1;
@@ -556,7 +556,7 @@ static int __devexit ab8500_usb_remove(struct platform_device *pdev)
556 556
557 cancel_work_sync(&ab->phy_dis_work); 557 cancel_work_sync(&ab->phy_dis_work);
558 558
559 usb_add_phy(NULL); 559 usb_remove_phy(&ab->phy);
560 560
561 ab8500_usb_host_phy_dis(ab); 561 ab8500_usb_host_phy_dis(ab);
562 ab8500_usb_peri_phy_dis(ab); 562 ab8500_usb_peri_phy_dis(ab);
diff --git a/drivers/usb/otg/fsl_otg.c b/drivers/usb/otg/fsl_otg.c
index 73561edd81de..23c798cb2d7f 100644
--- a/drivers/usb/otg/fsl_otg.c
+++ b/drivers/usb/otg/fsl_otg.c
@@ -806,7 +806,7 @@ static int fsl_otg_conf(struct platform_device *pdev)
806 fsl_otg_dev = fsl_otg_tc; 806 fsl_otg_dev = fsl_otg_tc;
807 807
808 /* Store the otg transceiver */ 808 /* Store the otg transceiver */
809 status = usb_add_phy(&fsl_otg_tc->phy); 809 status = usb_add_phy(&fsl_otg_tc->phy, USB_PHY_TYPE_USB2);
810 if (status) { 810 if (status) {
811 pr_warn(FSL_OTG_NAME ": unable to register OTG transceiver.\n"); 811 pr_warn(FSL_OTG_NAME ": unable to register OTG transceiver.\n");
812 goto err; 812 goto err;
@@ -824,7 +824,7 @@ err:
824int usb_otg_start(struct platform_device *pdev) 824int usb_otg_start(struct platform_device *pdev)
825{ 825{
826 struct fsl_otg *p_otg; 826 struct fsl_otg *p_otg;
827 struct usb_phy *otg_trans = usb_get_phy(); 827 struct usb_phy *otg_trans = usb_get_phy(USB_PHY_TYPE_USB2);
828 struct otg_fsm *fsm; 828 struct otg_fsm *fsm;
829 int status; 829 int status;
830 struct resource *res; 830 struct resource *res;
@@ -1134,7 +1134,7 @@ static int __devexit fsl_otg_remove(struct platform_device *pdev)
1134{ 1134{
1135 struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; 1135 struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
1136 1136
1137 usb_add_phy(NULL); 1137 usb_remove_phy(&fsl_otg_dev->phy);
1138 free_irq(fsl_otg_dev->irq, fsl_otg_dev); 1138 free_irq(fsl_otg_dev->irq, fsl_otg_dev);
1139 1139
1140 iounmap((void *)usb_dr_regs); 1140 iounmap((void *)usb_dr_regs);
diff --git a/drivers/usb/otg/gpio_vbus.c b/drivers/usb/otg/gpio_vbus.c
index 9b3c264cdb56..a67ffe22179a 100644
--- a/drivers/usb/otg/gpio_vbus.c
+++ b/drivers/usb/otg/gpio_vbus.c
@@ -320,7 +320,7 @@ static int __init gpio_vbus_probe(struct platform_device *pdev)
320 } 320 }
321 321
322 /* only active when a gadget is registered */ 322 /* only active when a gadget is registered */
323 err = usb_add_phy(&gpio_vbus->phy); 323 err = usb_add_phy(&gpio_vbus->phy, USB_PHY_TYPE_USB2);
324 if (err) { 324 if (err) {
325 dev_err(&pdev->dev, "can't register transceiver, err: %d\n", 325 dev_err(&pdev->dev, "can't register transceiver, err: %d\n",
326 err); 326 err);
@@ -354,7 +354,7 @@ static int __exit gpio_vbus_remove(struct platform_device *pdev)
354 cancel_delayed_work_sync(&gpio_vbus->work); 354 cancel_delayed_work_sync(&gpio_vbus->work);
355 regulator_put(gpio_vbus->vbus_draw); 355 regulator_put(gpio_vbus->vbus_draw);
356 356
357 usb_add_phy(NULL); 357 usb_remove_phy(&gpio_vbus->phy);
358 358
359 free_irq(gpio_vbus->irq, pdev); 359 free_irq(gpio_vbus->irq, pdev);
360 if (gpio_is_valid(pdata->gpio_pullup)) 360 if (gpio_is_valid(pdata->gpio_pullup))
diff --git a/drivers/usb/otg/isp1301_omap.c b/drivers/usb/otg/isp1301_omap.c
index b74df3fec56f..75cea4ab0985 100644
--- a/drivers/usb/otg/isp1301_omap.c
+++ b/drivers/usb/otg/isp1301_omap.c
@@ -1611,7 +1611,7 @@ isp1301_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
1611 dev_dbg(&i2c->dev, "scheduled timer, %d min\n", TIMER_MINUTES); 1611 dev_dbg(&i2c->dev, "scheduled timer, %d min\n", TIMER_MINUTES);
1612#endif 1612#endif
1613 1613
1614 status = usb_add_phy(&isp->phy); 1614 status = usb_add_phy(&isp->phy, USB_PHY_TYPE_USB2);
1615 if (status < 0) 1615 if (status < 0)
1616 dev_err(&i2c->dev, "can't register transceiver, %d\n", 1616 dev_err(&i2c->dev, "can't register transceiver, %d\n",
1617 status); 1617 status);
@@ -1650,7 +1650,7 @@ subsys_initcall(isp_init);
1650static void __exit isp_exit(void) 1650static void __exit isp_exit(void)
1651{ 1651{
1652 if (the_transceiver) 1652 if (the_transceiver)
1653 usb_add_phy(NULL); 1653 usb_remove_phy(&the_transceiver->phy);
1654 i2c_del_driver(&isp1301_driver); 1654 i2c_del_driver(&isp1301_driver);
1655} 1655}
1656module_exit(isp_exit); 1656module_exit(isp_exit);
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index dd606c010035..9f5fc906041a 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -1555,7 +1555,7 @@ static int __init msm_otg_probe(struct platform_device *pdev)
1555 phy->otg->set_host = msm_otg_set_host; 1555 phy->otg->set_host = msm_otg_set_host;
1556 phy->otg->set_peripheral = msm_otg_set_peripheral; 1556 phy->otg->set_peripheral = msm_otg_set_peripheral;
1557 1557
1558 ret = usb_add_phy(&motg->phy); 1558 ret = usb_add_phy(&motg->phy, USB_PHY_TYPE_USB2);
1559 if (ret) { 1559 if (ret) {
1560 dev_err(&pdev->dev, "usb_add_phy failed\n"); 1560 dev_err(&pdev->dev, "usb_add_phy failed\n");
1561 goto free_irq; 1561 goto free_irq;
@@ -1624,7 +1624,7 @@ static int __devexit msm_otg_remove(struct platform_device *pdev)
1624 device_init_wakeup(&pdev->dev, 0); 1624 device_init_wakeup(&pdev->dev, 0);
1625 pm_runtime_disable(&pdev->dev); 1625 pm_runtime_disable(&pdev->dev);
1626 1626
1627 usb_add_phy(NULL); 1627 usb_remove_phy(phy);
1628 free_irq(motg->irq, motg); 1628 free_irq(motg->irq, motg);
1629 1629
1630 /* 1630 /*
diff --git a/drivers/usb/otg/mv_otg.c b/drivers/usb/otg/mv_otg.c
index 18e90fe1fbd1..3f124e8f5792 100644
--- a/drivers/usb/otg/mv_otg.c
+++ b/drivers/usb/otg/mv_otg.c
@@ -690,7 +690,7 @@ int mv_otg_remove(struct platform_device *pdev)
690 for (clk_i = 0; clk_i <= mvotg->clknum; clk_i++) 690 for (clk_i = 0; clk_i <= mvotg->clknum; clk_i++)
691 clk_put(mvotg->clk[clk_i]); 691 clk_put(mvotg->clk[clk_i]);
692 692
693 usb_add_phy(NULL); 693 usb_remove_phy(&mvotg->phy);
694 platform_set_drvdata(pdev, NULL); 694 platform_set_drvdata(pdev, NULL);
695 695
696 kfree(mvotg->phy.otg); 696 kfree(mvotg->phy.otg);
@@ -853,7 +853,7 @@ static int mv_otg_probe(struct platform_device *pdev)
853 goto err_disable_clk; 853 goto err_disable_clk;
854 } 854 }
855 855
856 retval = usb_add_phy(&mvotg->phy); 856 retval = usb_add_phy(&mvotg->phy, USB_PHY_TYPE_USB2);
857 if (retval < 0) { 857 if (retval < 0) {
858 dev_err(&pdev->dev, "can't register transceiver, %d\n", 858 dev_err(&pdev->dev, "can't register transceiver, %d\n",
859 retval); 859 retval);
@@ -880,7 +880,7 @@ static int mv_otg_probe(struct platform_device *pdev)
880 return 0; 880 return 0;
881 881
882err_set_transceiver: 882err_set_transceiver:
883 usb_add_phy(NULL); 883 usb_remove_phy(&mvotg->phy);
884err_free_irq: 884err_free_irq:
885 free_irq(mvotg->irq, mvotg); 885 free_irq(mvotg->irq, mvotg);
886err_disable_clk: 886err_disable_clk:
diff --git a/drivers/usb/otg/nop-usb-xceiv.c b/drivers/usb/otg/nop-usb-xceiv.c
index 33000dae7200..803f958f4133 100644
--- a/drivers/usb/otg/nop-usb-xceiv.c
+++ b/drivers/usb/otg/nop-usb-xceiv.c
@@ -117,7 +117,7 @@ static int __devinit nop_usb_xceiv_probe(struct platform_device *pdev)
117 nop->phy.otg->set_host = nop_set_host; 117 nop->phy.otg->set_host = nop_set_host;
118 nop->phy.otg->set_peripheral = nop_set_peripheral; 118 nop->phy.otg->set_peripheral = nop_set_peripheral;
119 119
120 err = usb_add_phy(&nop->phy); 120 err = usb_add_phy(&nop->phy, USB_PHY_TYPE_USB2);
121 if (err) { 121 if (err) {
122 dev_err(&pdev->dev, "can't register transceiver, err: %d\n", 122 dev_err(&pdev->dev, "can't register transceiver, err: %d\n",
123 err); 123 err);
@@ -139,7 +139,7 @@ static int __devexit nop_usb_xceiv_remove(struct platform_device *pdev)
139{ 139{
140 struct nop_usb_xceiv *nop = platform_get_drvdata(pdev); 140 struct nop_usb_xceiv *nop = platform_get_drvdata(pdev);
141 141
142 usb_add_phy(NULL); 142 usb_remove_phy(&nop->phy);
143 143
144 platform_set_drvdata(pdev, NULL); 144 platform_set_drvdata(pdev, NULL);
145 kfree(nop->phy.otg); 145 kfree(nop->phy.otg);
diff --git a/drivers/usb/otg/otg.c b/drivers/usb/otg/otg.c
index 300a995cfdbe..a23065820ead 100644
--- a/drivers/usb/otg/otg.c
+++ b/drivers/usb/otg/otg.c
@@ -11,14 +11,32 @@
11 11
12#include <linux/kernel.h> 12#include <linux/kernel.h>
13#include <linux/export.h> 13#include <linux/export.h>
14#include <linux/err.h>
14#include <linux/device.h> 15#include <linux/device.h>
15 16
16#include <linux/usb/otg.h> 17#include <linux/usb/otg.h>
17 18
18static struct usb_phy *phy; 19static LIST_HEAD(phy_list);
20static DEFINE_SPINLOCK(phy_lock);
21
22static struct usb_phy *__usb_find_phy(struct list_head *list,
23 enum usb_phy_type type)
24{
25 struct usb_phy *phy = NULL;
26
27 list_for_each_entry(phy, list, head) {
28 if (phy->type != type)
29 continue;
30
31 return phy;
32 }
33
34 return ERR_PTR(-ENODEV);
35}
19 36
20/** 37/**
21 * usb_get_phy - find the (single) USB PHY 38 * usb_get_phy - find the USB PHY
39 * @type - the type of the phy the controller requires
22 * 40 *
23 * Returns the phy driver, after getting a refcount to it; or 41 * Returns the phy driver, after getting a refcount to it; or
24 * null if there is no such phy. The caller is responsible for 42 * null if there is no such phy. The caller is responsible for
@@ -26,16 +44,30 @@ static struct usb_phy *phy;
26 * 44 *
27 * For use by USB host and peripheral drivers. 45 * For use by USB host and peripheral drivers.
28 */ 46 */
29struct usb_phy *usb_get_phy(void) 47struct usb_phy *usb_get_phy(enum usb_phy_type type)
30{ 48{
31 if (phy) 49 struct usb_phy *phy = NULL;
32 get_device(phy->dev); 50 unsigned long flags;
51
52 spin_lock_irqsave(&phy_lock, flags);
53
54 phy = __usb_find_phy(&phy_list, type);
55 if (IS_ERR(phy)) {
56 pr_err("unable to find transceiver of type %s\n",
57 usb_phy_type_string(type));
58 return phy;
59 }
60
61 get_device(phy->dev);
62
63 spin_unlock_irqrestore(&phy_lock, flags);
64
33 return phy; 65 return phy;
34} 66}
35EXPORT_SYMBOL(usb_get_phy); 67EXPORT_SYMBOL(usb_get_phy);
36 68
37/** 69/**
38 * usb_put_phy - release the (single) USB PHY 70 * usb_put_phy - release the USB PHY
39 * @x: the phy returned by usb_get_phy() 71 * @x: the phy returned by usb_get_phy()
40 * 72 *
41 * Releases a refcount the caller received from usb_get_phy(). 73 * Releases a refcount the caller received from usb_get_phy().
@@ -50,22 +82,62 @@ void usb_put_phy(struct usb_phy *x)
50EXPORT_SYMBOL(usb_put_phy); 82EXPORT_SYMBOL(usb_put_phy);
51 83
52/** 84/**
53 * usb_add_phy - declare the (single) USB PHY 85 * usb_add_phy - declare the USB PHY
54 * @x: the USB phy to be used; or NULL 86 * @x: the USB phy to be used; or NULL
87 * @type - the type of this PHY
55 * 88 *
56 * This call is exclusively for use by phy drivers, which 89 * This call is exclusively for use by phy drivers, which
57 * coordinate the activities of drivers for host and peripheral 90 * coordinate the activities of drivers for host and peripheral
58 * controllers, and in some cases for VBUS current regulation. 91 * controllers, and in some cases for VBUS current regulation.
59 */ 92 */
60int usb_add_phy(struct usb_phy *x) 93int usb_add_phy(struct usb_phy *x, enum usb_phy_type type)
61{ 94{
62 if (phy && x) 95 int ret = 0;
63 return -EBUSY; 96 unsigned long flags;
64 phy = x; 97 struct usb_phy *phy;
65 return 0; 98
99 if (x && x->type != USB_PHY_TYPE_UNDEFINED) {
100 dev_err(x->dev, "not accepting initialized PHY %s\n", x->label);
101 return -EINVAL;
102 }
103
104 spin_lock_irqsave(&phy_lock, flags);
105
106 list_for_each_entry(phy, &phy_list, head) {
107 if (phy->type == type) {
108 ret = -EBUSY;
109 dev_err(x->dev, "transceiver type %s already exists\n",
110 usb_phy_type_string(type));
111 goto out;
112 }
113 }
114
115 x->type = type;
116 list_add_tail(&x->head, &phy_list);
117
118out:
119 spin_unlock_irqrestore(&phy_lock, flags);
120 return ret;
66} 121}
67EXPORT_SYMBOL(usb_add_phy); 122EXPORT_SYMBOL(usb_add_phy);
68 123
124/**
125 * usb_remove_phy - remove the OTG PHY
126 * @x: the USB OTG PHY to be removed;
127 *
128 * This reverts the effects of usb_add_phy
129 */
130void usb_remove_phy(struct usb_phy *x)
131{
132 unsigned long flags;
133
134 spin_lock_irqsave(&phy_lock, flags);
135 if (x)
136 list_del(&x->head);
137 spin_unlock_irqrestore(&phy_lock, flags);
138}
139EXPORT_SYMBOL(usb_remove_phy);
140
69const char *otg_state_string(enum usb_otg_state state) 141const char *otg_state_string(enum usb_otg_state state)
70{ 142{
71 switch (state) { 143 switch (state) {
diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/otg/twl4030-usb.c
index 01022c891e26..25a09fabbe35 100644
--- a/drivers/usb/otg/twl4030-usb.c
+++ b/drivers/usb/otg/twl4030-usb.c
@@ -633,7 +633,7 @@ static int __devinit twl4030_usb_probe(struct platform_device *pdev)
633 kfree(twl); 633 kfree(twl);
634 return err; 634 return err;
635 } 635 }
636 usb_add_phy(&twl->phy); 636 usb_add_phy(&twl->phy, USB_PHY_TYPE_USB2);
637 637
638 platform_set_drvdata(pdev, twl); 638 platform_set_drvdata(pdev, twl);
639 if (device_create_file(&pdev->dev, &dev_attr_vbus)) 639 if (device_create_file(&pdev->dev, &dev_attr_vbus))
diff --git a/drivers/usb/otg/twl6030-usb.c b/drivers/usb/otg/twl6030-usb.c
index a8be20878eb9..dbee00aea755 100644
--- a/drivers/usb/otg/twl6030-usb.c
+++ b/drivers/usb/otg/twl6030-usb.c
@@ -443,7 +443,7 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev)
443 kfree(twl); 443 kfree(twl);
444 return err; 444 return err;
445 } 445 }
446 usb_add_phy(&twl->phy); 446 usb_add_phy(&twl->phy, USB_PHY_TYPE_USB2);
447 447
448 platform_set_drvdata(pdev, twl); 448 platform_set_drvdata(pdev, twl);
449 if (device_create_file(&pdev->dev, &dev_attr_vbus)) 449 if (device_create_file(&pdev->dev, &dev_attr_vbus))