diff options
Diffstat (limited to 'drivers/usb/host/xhci-plat.c')
-rw-r--r-- | drivers/usb/host/xhci-plat.c | 51 |
1 files changed, 45 insertions, 6 deletions
diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index 151901ce1ba9..29d8adb5c8d1 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -11,13 +11,15 @@ * version 2 as published by the Free Software Foundation. */ -#include <linux/platform_device.h> +#include <linux/clk.h> +#include <linux/dma-mapping.h> #include <linux/module.h> -#include <linux/slab.h> #include <linux/of.h> -#include <linux/dma-mapping.h> +#include <linux/platform_device.h> +#include <linux/slab.h> #include "xhci.h" +#include "xhci-mvebu.h" static void xhci_plat_quirks(struct device *dev, struct xhci_hcd *xhci) { @@ -35,6 +37,11 @@ static int xhci_plat_setup(struct usb_hcd *hcd) return xhci_gen_setup(hcd, xhci_plat_quirks); } +static int xhci_plat_start(struct usb_hcd *hcd) +{ + return xhci_run(hcd); +} + static const struct hc_driver xhci_plat_xhci_driver = { .description = "xhci-hcd", .product_desc = "xHCI Host Controller", @@ -50,7 +57,7 @@ static const struct hc_driver xhci_plat_xhci_driver = { * basic lifecycle operations */ .reset = xhci_plat_setup, - .start = xhci_run, + .start = xhci_plat_start, .stop = xhci_stop, .shutdown = xhci_shutdown, @@ -91,6 +98,7 @@ static int xhci_plat_probe(struct platform_device *pdev) struct xhci_hcd *xhci; struct resource *res; struct usb_hcd *hcd; + struct clk *clk; int ret; int irq; @@ -107,6 +115,15 @@ static int xhci_plat_probe(struct platform_device *pdev) if (!res) return -ENODEV; + if (of_device_is_compatible(pdev->dev.of_node, + "marvell,armada-375-xhci") || + of_device_is_compatible(pdev->dev.of_node, + "marvell,armada-380-xhci")) { + ret = xhci_mvebu_mbus_init_quirk(pdev); + if (ret) + return ret; + } + /* Initialize dma_mask and coherent_dma_mask to 32-bits */ ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); if (ret) @@ -137,14 +154,27 @@ static int xhci_plat_probe(struct platform_device *pdev) goto release_mem_region; } + /* + * Not all platforms have a clk so it is not an error if the + * clock does not exists. + */ + clk = devm_clk_get(&pdev->dev, NULL); + if (!IS_ERR(clk)) { + ret = clk_prepare_enable(clk); + if (ret) + goto unmap_registers; + } + ret = usb_add_hcd(hcd, irq, IRQF_SHARED); if (ret) - goto unmap_registers; + goto disable_clk; + device_wakeup_enable(hcd->self.controller); /* USB 2.0 roothub is stored in the platform_device now. */ hcd = platform_get_drvdata(pdev); xhci = hcd_to_xhci(hcd); + xhci->clk = clk; xhci->shared_hcd = usb_create_shared_hcd(driver, &pdev->dev, dev_name(&pdev->dev), hcd); if (!xhci->shared_hcd) { @@ -173,6 +203,10 @@ put_usb3_hcd: dealloc_usb2_hcd: usb_remove_hcd(hcd); +disable_clk: + if (!IS_ERR(clk)) + clk_disable_unprepare(clk); + unmap_registers: iounmap(hcd->regs); @@ -189,11 +223,14 @@ static int xhci_plat_remove(struct platform_device *dev) { struct usb_hcd *hcd = platform_get_drvdata(dev); struct xhci_hcd *xhci = hcd_to_xhci(hcd); + struct clk *clk = xhci->clk; usb_remove_hcd(xhci->shared_hcd); usb_put_hcd(xhci->shared_hcd); usb_remove_hcd(hcd); + if (!IS_ERR(clk)) + clk_disable_unprepare(clk); iounmap(hcd->regs); release_mem_region(hcd->rsrc_start, hcd->rsrc_len); usb_put_hcd(hcd); @@ -202,7 +239,7 @@ static int xhci_plat_remove(struct platform_device *dev) return 0; } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int xhci_plat_suspend(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); @@ -231,6 +268,8 @@ static const struct dev_pm_ops xhci_plat_pm_ops = { static const struct of_device_id usb_xhci_of_match[] = { { .compatible = "generic-xhci" }, { .compatible = "xhci-platform" }, + { .compatible = "marvell,armada-375-xhci"}, + { .compatible = "marvell,armada-380-xhci"}, { }, }; MODULE_DEVICE_TABLE(of, usb_xhci_of_match); |