Commit 3ae2da7b authored by Gregory CLEMENT's avatar Gregory CLEMENT Committed by Greg Kroah-Hartman

usb: host: xhci-plat: Fix clock resource by adding a register clock

On Armada 7K/8K we need to explicitly enable the register clock. This
clock is optional because not all the SoCs using this IP need it but at
least for Armada 7K/8K it is actually mandatory.

The change was done at xhci-plat level and not at a xhci-mvebu.c because,
it is expected that other SoC would have this kind of constraint.

The binding documentation is updating accordingly.
Signed-off-by: default avatarGregory CLEMENT <gregory.clement@bootlin.com>
Signed-off-by: default avatarMathias Nyman <mathias.nyman@linux.intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 2d79609b
...@@ -28,7 +28,10 @@ Required properties: ...@@ -28,7 +28,10 @@ Required properties:
- interrupts: one XHCI interrupt should be described here. - interrupts: one XHCI interrupt should be described here.
Optional properties: Optional properties:
- clocks: reference to a clock - clocks: reference to the clocks
- clock-names: mandatory if there is a second clock, in this case
the name must be "core" for the first clock and "reg" for the
second one
- usb2-lpm-disable: indicate if we don't want to enable USB2 HW LPM - usb2-lpm-disable: indicate if we don't want to enable USB2 HW LPM
- usb3-lpm-capable: determines if platform is USB3 LPM capable - usb3-lpm-capable: determines if platform is USB3 LPM capable
- quirk-broken-port-ped: set if the controller has broken port disable mechanism - quirk-broken-port-ped: set if the controller has broken port disable mechanism
......
...@@ -157,6 +157,7 @@ static int xhci_plat_probe(struct platform_device *pdev) ...@@ -157,6 +157,7 @@ static int xhci_plat_probe(struct platform_device *pdev)
struct resource *res; struct resource *res;
struct usb_hcd *hcd; struct usb_hcd *hcd;
struct clk *clk; struct clk *clk;
struct clk *reg_clk;
int ret; int ret;
int irq; int irq;
...@@ -226,17 +227,27 @@ static int xhci_plat_probe(struct platform_device *pdev) ...@@ -226,17 +227,27 @@ static int xhci_plat_probe(struct platform_device *pdev)
hcd->rsrc_len = resource_size(res); hcd->rsrc_len = resource_size(res);
/* /*
* Not all platforms have a clk so it is not an error if the * Not all platforms have clks so it is not an error if the
* clock does not exists. * clock do not exist.
*/ */
reg_clk = devm_clk_get(&pdev->dev, "reg");
if (!IS_ERR(reg_clk)) {
ret = clk_prepare_enable(reg_clk);
if (ret)
goto put_hcd;
} else if (PTR_ERR(reg_clk) == -EPROBE_DEFER) {
ret = -EPROBE_DEFER;
goto put_hcd;
}
clk = devm_clk_get(&pdev->dev, NULL); clk = devm_clk_get(&pdev->dev, NULL);
if (!IS_ERR(clk)) { if (!IS_ERR(clk)) {
ret = clk_prepare_enable(clk); ret = clk_prepare_enable(clk);
if (ret) if (ret)
goto put_hcd; goto disable_reg_clk;
} else if (PTR_ERR(clk) == -EPROBE_DEFER) { } else if (PTR_ERR(clk) == -EPROBE_DEFER) {
ret = -EPROBE_DEFER; ret = -EPROBE_DEFER;
goto put_hcd; goto disable_reg_clk;
} }
xhci = hcd_to_xhci(hcd); xhci = hcd_to_xhci(hcd);
...@@ -252,6 +263,7 @@ static int xhci_plat_probe(struct platform_device *pdev) ...@@ -252,6 +263,7 @@ static int xhci_plat_probe(struct platform_device *pdev)
device_wakeup_enable(hcd->self.controller); device_wakeup_enable(hcd->self.controller);
xhci->clk = clk; xhci->clk = clk;
xhci->reg_clk = reg_clk;
xhci->main_hcd = hcd; xhci->main_hcd = hcd;
xhci->shared_hcd = __usb_create_hcd(driver, sysdev, &pdev->dev, xhci->shared_hcd = __usb_create_hcd(driver, sysdev, &pdev->dev,
dev_name(&pdev->dev), hcd); dev_name(&pdev->dev), hcd);
...@@ -322,6 +334,9 @@ static int xhci_plat_probe(struct platform_device *pdev) ...@@ -322,6 +334,9 @@ static int xhci_plat_probe(struct platform_device *pdev)
disable_clk: disable_clk:
clk_disable_unprepare(clk); clk_disable_unprepare(clk);
disable_reg_clk:
clk_disable_unprepare(reg_clk);
put_hcd: put_hcd:
usb_put_hcd(hcd); usb_put_hcd(hcd);
...@@ -337,6 +352,7 @@ static int xhci_plat_remove(struct platform_device *dev) ...@@ -337,6 +352,7 @@ static int xhci_plat_remove(struct platform_device *dev)
struct usb_hcd *hcd = platform_get_drvdata(dev); struct usb_hcd *hcd = platform_get_drvdata(dev);
struct xhci_hcd *xhci = hcd_to_xhci(hcd); struct xhci_hcd *xhci = hcd_to_xhci(hcd);
struct clk *clk = xhci->clk; struct clk *clk = xhci->clk;
struct clk *reg_clk = xhci->reg_clk;
xhci->xhc_state |= XHCI_STATE_REMOVING; xhci->xhc_state |= XHCI_STATE_REMOVING;
...@@ -347,6 +363,7 @@ static int xhci_plat_remove(struct platform_device *dev) ...@@ -347,6 +363,7 @@ static int xhci_plat_remove(struct platform_device *dev)
usb_put_hcd(xhci->shared_hcd); usb_put_hcd(xhci->shared_hcd);
clk_disable_unprepare(clk); clk_disable_unprepare(clk);
clk_disable_unprepare(reg_clk);
usb_put_hcd(hcd); usb_put_hcd(hcd);
pm_runtime_set_suspended(&dev->dev); pm_runtime_set_suspended(&dev->dev);
......
...@@ -1729,8 +1729,9 @@ struct xhci_hcd { ...@@ -1729,8 +1729,9 @@ struct xhci_hcd {
int page_shift; int page_shift;
/* msi-x vectors */ /* msi-x vectors */
int msix_count; int msix_count;
/* optional clock */ /* optional clocks */
struct clk *clk; struct clk *clk;
struct clk *reg_clk;
/* data structures */ /* data structures */
struct xhci_device_context_array *dcbaa; struct xhci_device_context_array *dcbaa;
struct xhci_ring *cmd_ring; struct xhci_ring *cmd_ring;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment