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:
Родитель
df9b17f586
Коммит
74475ede78
|
@ -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)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
|
@ -501,10 +528,6 @@ static int ci_hdrc_probe(struct platform_device *pdev)
|
|||
|
||||
ci->dev = dev;
|
||||
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);
|
||||
if (ret < 0) {
|
||||
|
@ -512,12 +535,19 @@ static int ci_hdrc_probe(struct platform_device *pdev)
|
|||
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->irq = platform_get_irq(pdev, 0);
|
||||
if (ci->irq < 0) {
|
||||
dev_err(dev, "missing IRQ\n");
|
||||
return -ENODEV;
|
||||
ret = -ENODEV;
|
||||
goto destroy_phy;
|
||||
}
|
||||
|
||||
ci_get_otg_capable(ci);
|
||||
|
@ -536,11 +566,23 @@ static int ci_hdrc_probe(struct platform_device *pdev)
|
|||
ret = ci_hdrc_gadget_init(ci);
|
||||
if (ret)
|
||||
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]) {
|
||||
dev_err(dev, "no supported roles\n");
|
||||
return -ENODEV;
|
||||
ret = -ENODEV;
|
||||
goto destroy_phy;
|
||||
}
|
||||
|
||||
if (ci->is_otg) {
|
||||
|
@ -593,6 +635,8 @@ static int ci_hdrc_probe(struct platform_device *pdev)
|
|||
free_irq(ci->irq, ci);
|
||||
stop:
|
||||
ci_role_destroy(ci);
|
||||
destroy_phy:
|
||||
ci_usb_phy_destroy(ci);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -604,6 +648,7 @@ static int ci_hdrc_remove(struct platform_device *pdev)
|
|||
dbg_remove_files(ci);
|
||||
free_irq(ci->irq, ci);
|
||||
ci_role_destroy(ci);
|
||||
ci_usb_phy_destroy(ci);
|
||||
kfree(ci->hw_bank.regmap);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
#include <linux/pm_runtime.h>
|
||||
#include <linux/usb/ch9.h>
|
||||
#include <linux/usb/gadget.h>
|
||||
#include <linux/usb/otg.h>
|
||||
#include <linux/usb/chipidea.h>
|
||||
|
||||
#include "ci.h"
|
||||
|
@ -1790,34 +1789,9 @@ static int udc_start(struct ci_hdrc *ci)
|
|||
|
||||
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);
|
||||
if (retval)
|
||||
goto remove_trans;
|
||||
goto destroy_eps;
|
||||
|
||||
pm_runtime_no_callbacks(&ci->gadget.dev);
|
||||
pm_runtime_enable(&ci->gadget.dev);
|
||||
|
@ -1827,17 +1801,6 @@ static int udc_start(struct ci_hdrc *ci)
|
|||
|
||||
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(ci);
|
||||
free_pools:
|
||||
|
|
Загрузка…
Ссылка в новой задаче