usb: dwc3: meson-g12a: refactor usb2 phy init
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>
This commit is contained in:
Родитель
8f5bc1ec77
Коммит
31306821d8
|
@ -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);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче