Adding the transceiver to ehci driver. Keeping the platform data for continuing the smooth operation for boards which still uses it Signed-off-by: Vivek Gautam <gautam.vivek@xxxxxxxxxxx> Acked-by: Jingoo Han <jg1.han@xxxxxxxxxxx> --- No change since v2. drivers/usb/host/ehci-s5p.c | 65 +++++++++++++++++++++++++++++------------- 1 files changed, 45 insertions(+), 20 deletions(-) diff --git a/drivers/usb/host/ehci-s5p.c b/drivers/usb/host/ehci-s5p.c index abc178d..e0a99af 100644 --- a/drivers/usb/host/ehci-s5p.c +++ b/drivers/usb/host/ehci-s5p.c @@ -17,6 +17,7 @@ #include <linux/platform_device.h> #include <linux/of_gpio.h> #include <linux/platform_data/usb-ehci-s5p.h> +#include <linux/usb/phy.h> #include <plat/usb-phy.h> #define EHCI_INSNREG00(base) (base + 0x90) @@ -32,6 +33,8 @@ struct s5p_ehci_hcd { struct device *dev; struct usb_hcd *hcd; struct clk *clk; + struct usb_phy *phy; + struct s5p_ehci_platdata *pdata; }; static const struct hc_driver s5p_ehci_hc_driver = { @@ -65,6 +68,26 @@ static const struct hc_driver s5p_ehci_hc_driver = { .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, }; +static void s5p_ehci_phy_enable(struct s5p_ehci_hcd *s5p_ehci) +{ + struct platform_device *pdev = to_platform_device(s5p_ehci->dev); + + if (s5p_ehci->phy) + usb_phy_init(s5p_ehci->phy); + else if (s5p_ehci->pdata->phy_init) + s5p_ehci->pdata->phy_init(pdev, S5P_USB_PHY_HOST); +} + +static void s5p_ehci_phy_disable(struct s5p_ehci_hcd *s5p_ehci) +{ + struct platform_device *pdev = to_platform_device(s5p_ehci->dev); + + if (s5p_ehci->phy) + usb_phy_shutdown(s5p_ehci->phy); + else if (s5p_ehci->pdata->phy_exit) + s5p_ehci->pdata->phy_exit(pdev, S5P_USB_PHY_HOST); +} + static void s5p_setup_vbus_gpio(struct platform_device *pdev) { int err; @@ -92,15 +115,10 @@ static int __devinit s5p_ehci_probe(struct platform_device *pdev) struct usb_hcd *hcd; struct ehci_hcd *ehci; struct resource *res; + struct usb_phy *phy; int irq; int err; - pdata = pdev->dev.platform_data; - if (!pdata) { - dev_err(&pdev->dev, "No platform data defined\n"); - return -EINVAL; - } - /* * Right now device-tree probed devices don't get dma_mask set. * Since shared usb code relies on it, set it here for now. @@ -118,6 +136,20 @@ static int __devinit s5p_ehci_probe(struct platform_device *pdev) if (!s5p_ehci) return -ENOMEM; + pdata = pdev->dev.platform_data; + if (!pdata) { + /* Fallback to Phy transceiver */ + phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2); + if (IS_ERR_OR_NULL(phy)) { + dev_err(&pdev->dev, "no platform data or transceiver defined\n"); + return -EPROBE_DEFER; + } else { + s5p_ehci->phy = phy; + } + } else { + s5p_ehci->pdata = pdata; + } + s5p_ehci->dev = &pdev->dev; hcd = usb_create_hcd(&s5p_ehci_hc_driver, &pdev->dev, @@ -163,8 +195,7 @@ static int __devinit s5p_ehci_probe(struct platform_device *pdev) goto fail_io; } - if (pdata->phy_init) - pdata->phy_init(pdev, S5P_USB_PHY_HOST); + s5p_ehci_phy_enable(s5p_ehci); ehci = hcd_to_ehci(hcd); ehci->caps = hcd->regs; @@ -175,13 +206,15 @@ static int __devinit s5p_ehci_probe(struct platform_device *pdev) err = usb_add_hcd(hcd, irq, IRQF_SHARED); if (err) { dev_err(&pdev->dev, "Failed to add USB HCD\n"); - goto fail_io; + goto fail_add_hcd; } platform_set_drvdata(pdev, s5p_ehci); return 0; +fail_add_hcd: + s5p_ehci_phy_disable(s5p_ehci); fail_io: clk_disable_unprepare(s5p_ehci->clk); fail_clk: @@ -191,14 +224,12 @@ fail_clk: static int __devexit s5p_ehci_remove(struct platform_device *pdev) { - struct s5p_ehci_platdata *pdata = pdev->dev.platform_data; struct s5p_ehci_hcd *s5p_ehci = platform_get_drvdata(pdev); struct usb_hcd *hcd = s5p_ehci->hcd; usb_remove_hcd(hcd); - if (pdata && pdata->phy_exit) - pdata->phy_exit(pdev, S5P_USB_PHY_HOST); + s5p_ehci_phy_disable(s5p_ehci); clk_disable_unprepare(s5p_ehci->clk); @@ -222,14 +253,11 @@ static int s5p_ehci_suspend(struct device *dev) struct s5p_ehci_hcd *s5p_ehci = dev_get_drvdata(dev); struct usb_hcd *hcd = s5p_ehci->hcd; bool do_wakeup = device_may_wakeup(dev); - struct platform_device *pdev = to_platform_device(dev); - struct s5p_ehci_platdata *pdata = pdev->dev.platform_data; int rc; rc = ehci_suspend(hcd, do_wakeup); - if (pdata && pdata->phy_exit) - pdata->phy_exit(pdev, S5P_USB_PHY_HOST); + s5p_ehci_phy_disable(s5p_ehci); clk_disable_unprepare(s5p_ehci->clk); @@ -240,13 +268,10 @@ static int s5p_ehci_resume(struct device *dev) { struct s5p_ehci_hcd *s5p_ehci = dev_get_drvdata(dev); struct usb_hcd *hcd = s5p_ehci->hcd; - struct platform_device *pdev = to_platform_device(dev); - struct s5p_ehci_platdata *pdata = pdev->dev.platform_data; clk_prepare_enable(s5p_ehci->clk); - if (pdata && pdata->phy_init) - pdata->phy_init(pdev, S5P_USB_PHY_HOST); + s5p_ehci_phy_enable(s5p_ehci); /* DMA burst Enable */ writel(EHCI_INSNREG00_ENABLE_DMA_BURST, EHCI_INSNREG00(hcd->regs)); -- 1.7.6.5 -- To unsubscribe from this list: send the line "unsubscribe linux-samsung-soc" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html