Commit 31306821 authored by Neil Armstrong's avatar Neil Armstrong Committed by Felipe Balbi
Browse files

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: default avatarMartin Blumenstingl <martin.blumenstingl@googlemail.com>
Signed-off-by: default avatarNeil Armstrong <narmstrong@baylibre.com>
Signed-off-by: default avatarFelipe Balbi <balbi@kernel.org>
parent 8f5bc1ec
Loading
Loading
Loading
Loading
+53 −21
Original line number Diff line number Diff line
@@ -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,7 +189,7 @@ struct dwc3_meson_g12a {
	const struct dwc3_meson_g12a_drvdata *drvdata;
};

static void dwc3_meson_g12a_usb2_set_mode(struct dwc3_meson_g12a *priv,
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)
@@ -185,23 +199,14 @@ 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(struct dwc3_meson_g12a *priv)
static int dwc3_meson_g12a_usb2_init_phy(struct dwc3_meson_g12a *priv, int i,
					 enum phy_mode mode)
{
	int i;

	if (priv->otg_mode == USB_DR_MODE_PERIPHERAL)
		priv->otg_phy_mode = PHY_MODE_USB_DEVICE;
	else
		priv->otg_phy_mode = PHY_MODE_USB_HOST;

	for (i = 0; i < priv->drvdata->num_phys; ++i) {
		if (!priv->phys[i])
			continue;

		if (!strstr(priv->drvdata->phy_names[i], "usb2"))
			continue;
	int ret;

	regmap_update_bits(priv->u2p_regmap[i], U2P_R0,
			U2P_R0_POWER_ON_RESET,
@@ -212,14 +217,39 @@ static int dwc3_meson_g12a_usb2_init(struct dwc3_meson_g12a *priv)
				   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);
		ret = priv->drvdata->set_phy_mode(priv, i, mode);
	} else
			dwc3_meson_g12a_usb2_set_mode(priv, i,
		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, ret;

	if (priv->otg_mode == USB_DR_MODE_PERIPHERAL)
		priv->otg_phy_mode = PHY_MODE_USB_DEVICE;
	else
		priv->otg_phy_mode = PHY_MODE_USB_HOST;

	for (i = 0; i < priv->drvdata->num_phys; ++i) {
		if (!priv->phys[i])
			continue;

		if (!strstr(priv->drvdata->phy_names[i], "usb2"))
			continue;

		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);