diff options
Diffstat (limited to 'drivers/usb/host/xhci-plat.c')
| -rw-r--r-- | drivers/usb/host/xhci-plat.c | 57 | 
1 files changed, 51 insertions, 6 deletions
diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index d9c169f470d..29d8adb5c8d 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, @@ -69,6 +76,7 @@ static const struct hc_driver xhci_plat_xhci_driver = {  	.check_bandwidth =	xhci_check_bandwidth,  	.reset_bandwidth =	xhci_reset_bandwidth,  	.address_device =	xhci_address_device, +	.enable_device =	xhci_enable_device,  	.update_hub_device =	xhci_update_hub_device,  	.reset_device =		xhci_discover_or_reset_device, @@ -90,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; @@ -106,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) @@ -136,13 +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) { @@ -156,6 +188,9 @@ static int xhci_plat_probe(struct platform_device *pdev)  	 */  	*((struct xhci_hcd **) xhci->shared_hcd->hcd_priv) = xhci; +	if (HCC_MAX_PSA(xhci->hcc_params) >= 4) +		xhci->shared_hcd->can_do_streams = 1; +  	ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED);  	if (ret)  		goto put_usb3_hcd; @@ -168,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); @@ -184,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); @@ -197,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); @@ -224,7 +266,10 @@ static const struct dev_pm_ops xhci_plat_pm_ops = {  #ifdef CONFIG_OF  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);  | 
