Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4718c177 authored by Gregory CLEMENT's avatar Gregory CLEMENT Committed by Greg Kroah-Hartman
Browse files

usb: host: xhci-plat: add clock support



Some platforms (such as the Armada 38x ones) can gate the clock of
their USB controller. This patch adds the support for one clock in
xhci-plat, by enabling it during probe and disabling it on remove.

To achieve this, it adds a 'struct clk *' member in xhci_hcd. While
only used for now in xhci-plat, it might be used by other drivers in
the future. Moreover, the xhci_hcd structure already holds other
members such as msix_count and msix_entries, which are MSI-X specific,
and therefore only used by xhci-pci.

Signed-off-by: default avatarGregory CLEMENT <gregory.clement@free-electrons.com>
Signed-off-by: default avatarThomas Petazzoni <thomas.petazzoni@free-electrons.com>
Acked-by: default avatarFelipe Balbi <balbi@ti.com>
Acked-by: default avatarMathias Nyman <mathias.nyman@linux.intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 48157bb9
Loading
Loading
Loading
Loading
+23 −1
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@
 * version 2 as published by the Free Software Foundation.
 */

#include <linux/clk.h>
#include <linux/dma-mapping.h>
#include <linux/module.h>
#include <linux/of.h>
@@ -91,6 +92,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;

@@ -137,14 +139,27 @@ static int xhci_plat_probe(struct platform_device *pdev)
		goto release_mem_region;
	}

	ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
	/*
	 * 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 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 +188,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 +208,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);
+2 −0
Original line number Diff line number Diff line
@@ -1472,6 +1472,8 @@ struct xhci_hcd {
	/* msi-x vectors */
	int		msix_count;
	struct msix_entry	*msix_entries;
	/* optional clock */
	struct clk		*clk;
	/* data structures */
	struct xhci_device_context_array *dcbaa;
	struct xhci_ring	*cmd_ring;