usb: chipidea: move PHY operation to core
PHY operations are common, so move them to core. Signed-off-by: Peter Chen <peter.chen@freescale.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
df9b17f586
commit
74475ede78
2 changed files with 52 additions and 44 deletions
|
@ -474,6 +474,33 @@ static void ci_get_otg_capable(struct ci_hdrc *ci)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ci_usb_phy_init(struct ci_hdrc *ci)
|
||||||
|
{
|
||||||
|
if (ci->platdata->phy) {
|
||||||
|
ci->transceiver = ci->platdata->phy;
|
||||||
|
return usb_phy_init(ci->transceiver);
|
||||||
|
} else {
|
||||||
|
ci->global_phy = true;
|
||||||
|
ci->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
|
||||||
|
if (IS_ERR(ci->transceiver))
|
||||||
|
ci->transceiver = NULL;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ci_usb_phy_destroy(struct ci_hdrc *ci)
|
||||||
|
{
|
||||||
|
if (!ci->transceiver)
|
||||||
|
return;
|
||||||
|
|
||||||
|
otg_set_peripheral(ci->transceiver->otg, NULL);
|
||||||
|
if (ci->global_phy)
|
||||||
|
usb_put_phy(ci->transceiver);
|
||||||
|
else
|
||||||
|
usb_phy_shutdown(ci->transceiver);
|
||||||
|
}
|
||||||
|
|
||||||
static int ci_hdrc_probe(struct platform_device *pdev)
|
static int ci_hdrc_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct device *dev = &pdev->dev;
|
struct device *dev = &pdev->dev;
|
||||||
|
@ -501,10 +528,6 @@ static int ci_hdrc_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
ci->dev = dev;
|
ci->dev = dev;
|
||||||
ci->platdata = dev->platform_data;
|
ci->platdata = dev->platform_data;
|
||||||
if (ci->platdata->phy)
|
|
||||||
ci->transceiver = ci->platdata->phy;
|
|
||||||
else
|
|
||||||
ci->global_phy = true;
|
|
||||||
|
|
||||||
ret = hw_device_init(ci, base);
|
ret = hw_device_init(ci, base);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
@ -512,12 +535,19 @@ static int ci_hdrc_probe(struct platform_device *pdev)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = ci_usb_phy_init(ci);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(dev, "unable to init phy: %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
ci->hw_bank.phys = res->start;
|
ci->hw_bank.phys = res->start;
|
||||||
|
|
||||||
ci->irq = platform_get_irq(pdev, 0);
|
ci->irq = platform_get_irq(pdev, 0);
|
||||||
if (ci->irq < 0) {
|
if (ci->irq < 0) {
|
||||||
dev_err(dev, "missing IRQ\n");
|
dev_err(dev, "missing IRQ\n");
|
||||||
return -ENODEV;
|
ret = -ENODEV;
|
||||||
|
goto destroy_phy;
|
||||||
}
|
}
|
||||||
|
|
||||||
ci_get_otg_capable(ci);
|
ci_get_otg_capable(ci);
|
||||||
|
@ -536,11 +566,23 @@ static int ci_hdrc_probe(struct platform_device *pdev)
|
||||||
ret = ci_hdrc_gadget_init(ci);
|
ret = ci_hdrc_gadget_init(ci);
|
||||||
if (ret)
|
if (ret)
|
||||||
dev_info(dev, "doesn't support gadget\n");
|
dev_info(dev, "doesn't support gadget\n");
|
||||||
|
if (!ret && ci->transceiver) {
|
||||||
|
ret = otg_set_peripheral(ci->transceiver->otg,
|
||||||
|
&ci->gadget);
|
||||||
|
/*
|
||||||
|
* If we implement all USB functions using chipidea drivers,
|
||||||
|
* it doesn't need to call above API, meanwhile, if we only
|
||||||
|
* use gadget function, calling above API is useless.
|
||||||
|
*/
|
||||||
|
if (ret && ret != -ENOTSUPP)
|
||||||
|
goto destroy_phy;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ci->roles[CI_ROLE_HOST] && !ci->roles[CI_ROLE_GADGET]) {
|
if (!ci->roles[CI_ROLE_HOST] && !ci->roles[CI_ROLE_GADGET]) {
|
||||||
dev_err(dev, "no supported roles\n");
|
dev_err(dev, "no supported roles\n");
|
||||||
return -ENODEV;
|
ret = -ENODEV;
|
||||||
|
goto destroy_phy;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ci->is_otg) {
|
if (ci->is_otg) {
|
||||||
|
@ -593,6 +635,8 @@ static int ci_hdrc_probe(struct platform_device *pdev)
|
||||||
free_irq(ci->irq, ci);
|
free_irq(ci->irq, ci);
|
||||||
stop:
|
stop:
|
||||||
ci_role_destroy(ci);
|
ci_role_destroy(ci);
|
||||||
|
destroy_phy:
|
||||||
|
ci_usb_phy_destroy(ci);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -604,6 +648,7 @@ static int ci_hdrc_remove(struct platform_device *pdev)
|
||||||
dbg_remove_files(ci);
|
dbg_remove_files(ci);
|
||||||
free_irq(ci->irq, ci);
|
free_irq(ci->irq, ci);
|
||||||
ci_role_destroy(ci);
|
ci_role_destroy(ci);
|
||||||
|
ci_usb_phy_destroy(ci);
|
||||||
kfree(ci->hw_bank.regmap);
|
kfree(ci->hw_bank.regmap);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
#include <linux/pm_runtime.h>
|
#include <linux/pm_runtime.h>
|
||||||
#include <linux/usb/ch9.h>
|
#include <linux/usb/ch9.h>
|
||||||
#include <linux/usb/gadget.h>
|
#include <linux/usb/gadget.h>
|
||||||
#include <linux/usb/otg.h>
|
|
||||||
#include <linux/usb/chipidea.h>
|
#include <linux/usb/chipidea.h>
|
||||||
|
|
||||||
#include "ci.h"
|
#include "ci.h"
|
||||||
|
@ -1790,34 +1789,9 @@ static int udc_start(struct ci_hdrc *ci)
|
||||||
|
|
||||||
ci->gadget.ep0 = &ci->ep0in->ep;
|
ci->gadget.ep0 = &ci->ep0in->ep;
|
||||||
|
|
||||||
if (ci->global_phy) {
|
|
||||||
ci->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
|
|
||||||
if (IS_ERR(ci->transceiver))
|
|
||||||
ci->transceiver = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ci->platdata->flags & CI_HDRC_REQUIRE_TRANSCEIVER) {
|
|
||||||
if (ci->transceiver == NULL) {
|
|
||||||
retval = -ENODEV;
|
|
||||||
goto destroy_eps;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ci->transceiver) {
|
|
||||||
retval = otg_set_peripheral(ci->transceiver->otg,
|
|
||||||
&ci->gadget);
|
|
||||||
/*
|
|
||||||
* If we implement all USB functions using chipidea drivers,
|
|
||||||
* it doesn't need to call above API, meanwhile, if we only
|
|
||||||
* use gadget function, calling above API is useless.
|
|
||||||
*/
|
|
||||||
if (retval && retval != -ENOTSUPP)
|
|
||||||
goto put_transceiver;
|
|
||||||
}
|
|
||||||
|
|
||||||
retval = usb_add_gadget_udc(dev, &ci->gadget);
|
retval = usb_add_gadget_udc(dev, &ci->gadget);
|
||||||
if (retval)
|
if (retval)
|
||||||
goto remove_trans;
|
goto destroy_eps;
|
||||||
|
|
||||||
pm_runtime_no_callbacks(&ci->gadget.dev);
|
pm_runtime_no_callbacks(&ci->gadget.dev);
|
||||||
pm_runtime_enable(&ci->gadget.dev);
|
pm_runtime_enable(&ci->gadget.dev);
|
||||||
|
@ -1827,17 +1801,6 @@ static int udc_start(struct ci_hdrc *ci)
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
remove_trans:
|
|
||||||
if (ci->transceiver) {
|
|
||||||
otg_set_peripheral(ci->transceiver->otg, NULL);
|
|
||||||
if (ci->global_phy)
|
|
||||||
usb_put_phy(ci->transceiver);
|
|
||||||
}
|
|
||||||
|
|
||||||
dev_err(dev, "error = %i\n", retval);
|
|
||||||
put_transceiver:
|
|
||||||
if (ci->transceiver && ci->global_phy)
|
|
||||||
usb_put_phy(ci->transceiver);
|
|
||||||
destroy_eps:
|
destroy_eps:
|
||||||
destroy_eps(ci);
|
destroy_eps(ci);
|
||||||
free_pools:
|
free_pools:
|
||||||
|
|
Loading…
Reference in a new issue