Skip to content

Commit 3241929

Browse files
paligregkh
authored andcommitted
usb: host: xhci: mvebu: make USB 3.0 PHY optional for Armada 3720
Older ATF does not provide SMC call for USB 3.0 phy power on functionality and therefore initialization of xhci-hcd is failing when older version of ATF is used. In this case phy_power_on() function returns -EOPNOTSUPP. [ 3.108467] mvebu-a3700-comphy d0018300.phy: unsupported SMC call, try updating your firmware [ 3.117250] phy phy-d0018300.phy.0: phy poweron failed --> -95 [ 3.123465] xhci-hcd: probe of d0058000.usb failed with error -95 This patch introduces a new plat_setup callback for xhci platform drivers which is called prior calling usb_add_hcd() function. This function at its beginning skips PHY init if hcd->skip_phy_initialization is set. Current init_quirk callback for xhci platform drivers is called from xhci_plat_setup() function which is called after chip reset completes. It happens in the middle of the usb_add_hcd() function and therefore this callback cannot be used for setting if PHY init should be skipped or not. For Armada 3720 this patch introduce a new xhci_mvebu_a3700_plat_setup() function configured as a xhci platform plat_setup callback. This new function calls phy_power_on() and in case it returns -EOPNOTSUPP then XHCI_SKIP_PHY_INIT quirk is set to instruct xhci-plat to skip PHY initialization. This patch fixes above failure by ignoring 'not supported' error in xhci-hcd driver. In this case it is expected that phy is already power on. It fixes initialization of xhci-hcd on Espressobin boards where is older Marvell's Arm Trusted Firmware without SMC call for USB 3.0 phy power. This is regression introduced in commit bd3d25b ("arm64: dts: marvell: armada-37xx: link USB hosts with their PHYs") where USB 3.0 phy was defined and therefore xhci-hcd on Espressobin with older ATF started failing. Fixes: bd3d25b ("arm64: dts: marvell: armada-37xx: link USB hosts with their PHYs") Cc: <[email protected]> # 5.1+: ea17a0f: phy: marvell: comphy: Convert internal SMCC firmware return codes to errno Cc: <[email protected]> # 5.1+: f768e71: usb: host: xhci-plat: add priv quirk for skip PHY initialization Tested-by: Tomasz Maciej Nowak <[email protected]> Tested-by: Yoshihiro Shimoda <[email protected]> # On R-Car Reviewed-by: Yoshihiro Shimoda <[email protected]> # xhci-plat Acked-by: Mathias Nyman <[email protected]> Signed-off-by: Pali Rohár <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent a50ea34 commit 3241929

4 files changed

Lines changed: 68 additions & 1 deletion

File tree

drivers/usb/host/xhci-mvebu.c

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <linux/mbus.h>
99
#include <linux/of.h>
1010
#include <linux/platform_device.h>
11+
#include <linux/phy/phy.h>
1112

1213
#include <linux/usb.h>
1314
#include <linux/usb/hcd.h>
@@ -74,6 +75,47 @@ int xhci_mvebu_mbus_init_quirk(struct usb_hcd *hcd)
7475
return 0;
7576
}
7677

78+
int xhci_mvebu_a3700_plat_setup(struct usb_hcd *hcd)
79+
{
80+
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
81+
struct device *dev = hcd->self.controller;
82+
struct phy *phy;
83+
int ret;
84+
85+
/* Old bindings miss the PHY handle */
86+
phy = of_phy_get(dev->of_node, "usb3-phy");
87+
if (IS_ERR(phy) && PTR_ERR(phy) == -EPROBE_DEFER)
88+
return -EPROBE_DEFER;
89+
else if (IS_ERR(phy))
90+
goto phy_out;
91+
92+
ret = phy_init(phy);
93+
if (ret)
94+
goto phy_put;
95+
96+
ret = phy_set_mode(phy, PHY_MODE_USB_HOST_SS);
97+
if (ret)
98+
goto phy_exit;
99+
100+
ret = phy_power_on(phy);
101+
if (ret == -EOPNOTSUPP) {
102+
/* Skip initializatin of XHCI PHY when it is unsupported by firmware */
103+
dev_warn(dev, "PHY unsupported by firmware\n");
104+
xhci->quirks |= XHCI_SKIP_PHY_INIT;
105+
}
106+
if (ret)
107+
goto phy_exit;
108+
109+
phy_power_off(phy);
110+
phy_exit:
111+
phy_exit(phy);
112+
phy_put:
113+
of_phy_put(phy);
114+
phy_out:
115+
116+
return 0;
117+
}
118+
77119
int xhci_mvebu_a3700_init_quirk(struct usb_hcd *hcd)
78120
{
79121
struct xhci_hcd *xhci = hcd_to_xhci(hcd);

drivers/usb/host/xhci-mvebu.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,19 @@ struct usb_hcd;
1212

1313
#if IS_ENABLED(CONFIG_USB_XHCI_MVEBU)
1414
int xhci_mvebu_mbus_init_quirk(struct usb_hcd *hcd);
15+
int xhci_mvebu_a3700_plat_setup(struct usb_hcd *hcd);
1516
int xhci_mvebu_a3700_init_quirk(struct usb_hcd *hcd);
1617
#else
1718
static inline int xhci_mvebu_mbus_init_quirk(struct usb_hcd *hcd)
1819
{
1920
return 0;
2021
}
2122

23+
static inline int xhci_mvebu_a3700_plat_setup(struct usb_hcd *hcd)
24+
{
25+
return 0;
26+
}
27+
2228
static inline int xhci_mvebu_a3700_init_quirk(struct usb_hcd *hcd)
2329
{
2430
return 0;

drivers/usb/host/xhci-plat.c

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,16 @@ static void xhci_priv_plat_start(struct usb_hcd *hcd)
4444
priv->plat_start(hcd);
4545
}
4646

47+
static int xhci_priv_plat_setup(struct usb_hcd *hcd)
48+
{
49+
struct xhci_plat_priv *priv = hcd_to_xhci_priv(hcd);
50+
51+
if (!priv->plat_setup)
52+
return 0;
53+
54+
return priv->plat_setup(hcd);
55+
}
56+
4757
static int xhci_priv_init_quirk(struct usb_hcd *hcd)
4858
{
4959
struct xhci_plat_priv *priv = hcd_to_xhci_priv(hcd);
@@ -111,6 +121,7 @@ static const struct xhci_plat_priv xhci_plat_marvell_armada = {
111121
};
112122

113123
static const struct xhci_plat_priv xhci_plat_marvell_armada3700 = {
124+
.plat_setup = xhci_mvebu_a3700_plat_setup,
114125
.init_quirk = xhci_mvebu_a3700_init_quirk,
115126
};
116127

@@ -330,7 +341,14 @@ static int xhci_plat_probe(struct platform_device *pdev)
330341

331342
hcd->tpl_support = of_usb_host_tpl_support(sysdev->of_node);
332343
xhci->shared_hcd->tpl_support = hcd->tpl_support;
333-
if (priv && (priv->quirks & XHCI_SKIP_PHY_INIT))
344+
345+
if (priv) {
346+
ret = xhci_priv_plat_setup(hcd);
347+
if (ret)
348+
goto disable_usb_phy;
349+
}
350+
351+
if ((xhci->quirks & XHCI_SKIP_PHY_INIT) || (priv && (priv->quirks & XHCI_SKIP_PHY_INIT)))
334352
hcd->skip_phy_initialization = 1;
335353

336354
if (priv && (priv->quirks & XHCI_SG_TRB_CACHE_SIZE_QUIRK))

drivers/usb/host/xhci-plat.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
struct xhci_plat_priv {
1414
const char *firmware_name;
1515
unsigned long long quirks;
16+
int (*plat_setup)(struct usb_hcd *);
1617
void (*plat_start)(struct usb_hcd *);
1718
int (*init_quirk)(struct usb_hcd *);
1819
int (*suspend_quirk)(struct usb_hcd *);

0 commit comments

Comments
 (0)