From 4e5b4527dd5f225ccaec2139f9956bca9029b92c Mon Sep 17 00:00:00 2001 From: William Wu Date: Thu, 19 Jul 2018 16:01:57 +0800 Subject: [PATCH] USB: ehci-platform: support EHCIs with usic phy Some EHCI controllers use usic phy (e.g rk3399/rk3288), in order to enable these controllers, we need to set some additional EHCI vendor-specific registers. Support this feature in device tree when using the ehci platform driver by adding a new property for it. Conflicts: drivers/usb/host/ehci-platform.c Change-Id: I279ccfdb5866df49828825bfd41b39fcd58a2832 Signed-off-by: William Wu Signed-off-by: Frank Wang --- .../devicetree/bindings/usb/usb-ehci.txt | 1 + drivers/usb/host/ehci-platform.c | 19 +++++++++++++++++++ drivers/usb/host/ehci.h | 7 +++++++ 3 files changed, 27 insertions(+) diff --git a/Documentation/devicetree/bindings/usb/usb-ehci.txt b/Documentation/devicetree/bindings/usb/usb-ehci.txt index 0f1b75386207..da4642d77e4d 100644 --- a/Documentation/devicetree/bindings/usb/usb-ehci.txt +++ b/Documentation/devicetree/bindings/usb/usb-ehci.txt @@ -15,6 +15,7 @@ Optional properties: - needs-reset-on-resume : boolean, set this to force EHCI reset after resume - has-transaction-translator : boolean, set this if EHCI have a Transaction Translator built into the root hub. + - rockchip-has-usic : boolean, set this if EHCI use usic phy. - clocks : a list of phandle + clock specifier pairs - phys : see usb-hcd.txt in the current directory - resets : phandle + reset specifier pair diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c index 491da8033a78..1530b58527dd 100644 --- a/drivers/usb/host/ehci-platform.c +++ b/drivers/usb/host/ehci-platform.c @@ -60,6 +60,18 @@ static void ehci_rockchip_relinquish_port(struct usb_hcd *hcd, int portnum) ehci_writel(ehci, portsc, status_reg); } +static void ehci_rockchip_usic_init(struct usb_hcd *hcd) +{ + struct ehci_hcd *ehci = hcd_to_ehci(hcd); + + ehci_writel(ehci, USIC_ENABLE, + hcd->regs + USIC_ENABLE_OFFSET); + ehci_writel(ehci, USIC_MICROFRAME_COUNT, + hcd->regs + USIC_MICROFRAME_OFFSET); + ehci_writel(ehci, USIC_SCALE_DOWN, + hcd->regs + USIC_SCALE_DOWN_OFFSET); +} + static int ehci_platform_reset(struct usb_hcd *hcd) { struct platform_device *pdev = to_platform_device(hcd->self.controller); @@ -198,6 +210,10 @@ static int ehci_platform_probe(struct platform_device *dev) hcd->rk3288_relinquish_port_quirk = 1; } + if (of_property_read_bool(dev->dev.of_node, + "rockchip-has-usic")) + ehci->has_usic = 1; + for (clk = 0; clk < EHCI_MAX_CLKS; clk++) { priv->clks[clk] = of_clk_get(dev->dev.of_node, clk); if (IS_ERR(priv->clks[clk])) { @@ -265,6 +281,9 @@ static int ehci_platform_probe(struct platform_device *dev) if (err) goto err_power; + if (ehci->has_usic) + ehci_rockchip_usic_init(hcd); + device_wakeup_enable(hcd->self.controller); device_enable_async_suspend(hcd->self.controller); platform_set_drvdata(dev, hcd); diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index c8e9a48e1d51..cd5ba34c7c02 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -218,6 +218,13 @@ struct ehci_hcd { /* one per controller */ unsigned frame_index_bug:1; /* MosChip (AKA NetMos) */ unsigned need_oc_pp_cycle:1; /* MPC834X port power */ unsigned imx28_write_fix:1; /* For Freescale i.MX28 */ + unsigned has_usic:1; + #define USIC_MICROFRAME_OFFSET 0x90 + #define USIC_SCALE_DOWN_OFFSET 0xa0 + #define USIC_ENABLE_OFFSET 0xb0 + #define USIC_ENABLE BIT(0) + #define USIC_SCALE_DOWN BIT(2) + #define USIC_MICROFRAME_COUNT 0x1d4d /* required for usb32 quirk */ #define OHCI_CTRL_HCFS (3 << 6)