usb: dwc3: meson-g12a: refactor usb2 phy init
authorNeil Armstrong <narmstrong@baylibre.com>
Thu, 26 Mar 2020 13:44:58 +0000 (14:44 +0100)
committerFelipe Balbi <balbi@kernel.org>
Tue, 5 May 2020 08:00:12 +0000 (11:00 +0300)
Refactor the USB2 PHY init code patch to handle the Amlogic GXL/GXM
not having the PHY mode control registers in the Glue but in the PHY
registers.

The Amlogic GXL/GXM will call phy_set_mode() instead of programming the
PHY mode control registers, thus add two new callbacks to the SoC match
data.

Reviewed-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
Signed-off-by: Felipe Balbi <balbi@kernel.org>
drivers/usb/dwc3/dwc3-meson-g12a.c

index 6351012..7027ee2 100644 (file)
@@ -136,11 +136,21 @@ struct dwc3_meson_g12a_drvdata {
        const char **phy_names;
        int num_phys;
        int (*setup_regmaps)(struct dwc3_meson_g12a *priv, void __iomem *base);
+       int (*usb2_init_phy)(struct dwc3_meson_g12a *priv, int i,
+                            enum phy_mode mode);
+       int (*set_phy_mode)(struct dwc3_meson_g12a *priv, int i,
+                           enum phy_mode mode);
 };
 
 static int dwc3_meson_g12a_setup_regmaps(struct dwc3_meson_g12a *priv,
                                         void __iomem *base);
 
+static int dwc3_meson_g12a_usb2_init_phy(struct dwc3_meson_g12a *priv, int i,
+                                         enum phy_mode mode);
+
+static int dwc3_meson_g12a_set_phy_mode(struct dwc3_meson_g12a *priv,
+                                       int i, enum phy_mode mode);
+
 static struct dwc3_meson_g12a_drvdata g12a_drvdata = {
        .otg_switch_supported = true,
        .clks = meson_g12a_clocks,
@@ -148,6 +158,8 @@ static struct dwc3_meson_g12a_drvdata g12a_drvdata = {
        .phy_names = meson_g12a_phy_names,
        .num_phys = ARRAY_SIZE(meson_g12a_phy_names),
        .setup_regmaps = dwc3_meson_g12a_setup_regmaps,
+       .usb2_init_phy = dwc3_meson_g12a_usb2_init_phy,
+       .set_phy_mode = dwc3_meson_g12a_set_phy_mode,
 };
 
 static struct dwc3_meson_g12a_drvdata a1_drvdata = {
@@ -157,6 +169,8 @@ static struct dwc3_meson_g12a_drvdata a1_drvdata = {
        .phy_names = meson_a1_phy_names,
        .num_phys = ARRAY_SIZE(meson_a1_phy_names),
        .setup_regmaps = dwc3_meson_g12a_setup_regmaps,
+       .usb2_init_phy = dwc3_meson_g12a_usb2_init_phy,
+       .set_phy_mode = dwc3_meson_g12a_set_phy_mode,
 };
 
 struct dwc3_meson_g12a {
@@ -175,8 +189,8 @@ struct dwc3_meson_g12a {
        const struct dwc3_meson_g12a_drvdata *drvdata;
 };
 
-static void dwc3_meson_g12a_usb2_set_mode(struct dwc3_meson_g12a *priv,
-                                         int i, enum phy_mode mode)
+static int dwc3_meson_g12a_set_phy_mode(struct dwc3_meson_g12a *priv,
+                                        int i, enum phy_mode mode)
 {
        if (mode == PHY_MODE_USB_HOST)
                regmap_update_bits(priv->u2p_regmap[i], U2P_R0,
@@ -185,11 +199,41 @@ static void dwc3_meson_g12a_usb2_set_mode(struct dwc3_meson_g12a *priv,
        else
                regmap_update_bits(priv->u2p_regmap[i], U2P_R0,
                                U2P_R0_HOST_DEVICE, 0);
+
+       return 0;
+}
+
+static int dwc3_meson_g12a_usb2_init_phy(struct dwc3_meson_g12a *priv, int i,
+                                        enum phy_mode mode)
+{
+       int ret;
+
+       regmap_update_bits(priv->u2p_regmap[i], U2P_R0,
+                       U2P_R0_POWER_ON_RESET,
+                       U2P_R0_POWER_ON_RESET);
+
+       if (priv->drvdata->otg_switch_supported && i == USB2_OTG_PHY) {
+               regmap_update_bits(priv->u2p_regmap[i], U2P_R0,
+                                  U2P_R0_ID_PULLUP | U2P_R0_DRV_VBUS,
+                                  U2P_R0_ID_PULLUP | U2P_R0_DRV_VBUS);
+
+               ret = priv->drvdata->set_phy_mode(priv, i, mode);
+       } else
+               ret = priv->drvdata->set_phy_mode(priv, i,
+                                                 PHY_MODE_USB_HOST);
+
+       if (ret)
+               return ret;
+
+       regmap_update_bits(priv->u2p_regmap[i], U2P_R0,
+                       U2P_R0_POWER_ON_RESET, 0);
+
+       return 0;
 }
 
 static int dwc3_meson_g12a_usb2_init(struct dwc3_meson_g12a *priv)
 {
-       int i;
+       int i, ret;
 
        if (priv->otg_mode == USB_DR_MODE_PERIPHERAL)
                priv->otg_phy_mode = PHY_MODE_USB_DEVICE;
@@ -203,23 +247,9 @@ static int dwc3_meson_g12a_usb2_init(struct dwc3_meson_g12a *priv)
                if (!strstr(priv->drvdata->phy_names[i], "usb2"))
                        continue;
 
-               regmap_update_bits(priv->u2p_regmap[i], U2P_R0,
-                                  U2P_R0_POWER_ON_RESET,
-                                  U2P_R0_POWER_ON_RESET);
-
-               if (priv->drvdata->otg_switch_supported && i == USB2_OTG_PHY) {
-                       regmap_update_bits(priv->u2p_regmap[i], U2P_R0,
-                               U2P_R0_ID_PULLUP | U2P_R0_DRV_VBUS,
-                               U2P_R0_ID_PULLUP | U2P_R0_DRV_VBUS);
-
-                       dwc3_meson_g12a_usb2_set_mode(priv, i,
-                                                     priv->otg_phy_mode);
-               } else
-                       dwc3_meson_g12a_usb2_set_mode(priv, i,
-                                                     PHY_MODE_USB_HOST);
-
-               regmap_update_bits(priv->u2p_regmap[i], U2P_R0,
-                                  U2P_R0_POWER_ON_RESET, 0);
+               ret = priv->drvdata->usb2_init_phy(priv, i, priv->otg_phy_mode);
+               if (ret)
+                       return ret;
        }
 
        return 0;
@@ -372,7 +402,9 @@ static int dwc3_meson_g12a_otg_mode_set(struct dwc3_meson_g12a *priv,
 
        priv->otg_phy_mode = mode;
 
-       dwc3_meson_g12a_usb2_set_mode(priv, USB2_OTG_PHY, mode);
+       ret = priv->drvdata->set_phy_mode(priv, USB2_OTG_PHY, mode);
+       if (ret)
+               return ret;
 
        dwc3_meson_g12a_usb_otg_apply_mode(priv);