Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fcaa36a8 authored by Samuel Holland's avatar Samuel Holland Committed by Greg Kroah-Hartman
Browse files

net: stmmac: dwmac-sun8i: Balance internal PHY power



[ Upstream commit b8239638853e3e37b287e4bd4d57b41f14c78550 ]

sun8i_dwmac_exit calls sun8i_dwmac_unpower_internal_phy, but
sun8i_dwmac_init did not call sun8i_dwmac_power_internal_phy. This
caused PHY power to remain off after a suspend/resume cycle. Fix this by
recording if PHY power should be restored, and if so, restoring it.

Fixes: 634db83b ("net: stmmac: dwmac-sun8i: Handle integrated/external MDIOs")
Signed-off-by: default avatarSamuel Holland <samuel@sholland.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent f0c95ef6
Loading
Loading
Loading
Loading
+23 −8
Original line number Diff line number Diff line
@@ -73,6 +73,7 @@ struct emac_variant {
 * @variant:	reference to the current board variant
 * @regmap:	regmap for using the syscon
 * @internal_phy_powered: Does the internal PHY is enabled
 * @use_internal_phy: Is the internal PHY selected for use
 * @mux_handle:	Internal pointer used by mdio-mux lib
 */
struct sunxi_priv_data {
@@ -83,6 +84,7 @@ struct sunxi_priv_data {
	const struct emac_variant *variant;
	struct regmap_field *regmap_field;
	bool internal_phy_powered;
	bool use_internal_phy;
	void *mux_handle;
};

@@ -518,8 +520,11 @@ static const struct stmmac_dma_ops sun8i_dwmac_dma_ops = {
	.dma_interrupt = sun8i_dwmac_dma_interrupt,
};

static int sun8i_dwmac_power_internal_phy(struct stmmac_priv *priv);

static int sun8i_dwmac_init(struct platform_device *pdev, void *priv)
{
	struct net_device *ndev = platform_get_drvdata(pdev);
	struct sunxi_priv_data *gmac = priv;
	int ret;

@@ -533,13 +538,25 @@ static int sun8i_dwmac_init(struct platform_device *pdev, void *priv)

	ret = clk_prepare_enable(gmac->tx_clk);
	if (ret) {
		if (gmac->regulator)
			regulator_disable(gmac->regulator);
		dev_err(&pdev->dev, "Could not enable AHB clock\n");
		return ret;
		goto err_disable_regulator;
	}

	if (gmac->use_internal_phy) {
		ret = sun8i_dwmac_power_internal_phy(netdev_priv(ndev));
		if (ret)
			goto err_disable_clk;
	}

	return 0;

err_disable_clk:
	clk_disable_unprepare(gmac->tx_clk);
err_disable_regulator:
	if (gmac->regulator)
		regulator_disable(gmac->regulator);

	return ret;
}

static void sun8i_dwmac_core_init(struct mac_device_info *hw,
@@ -809,7 +826,6 @@ static int mdio_mux_syscon_switch_fn(int current_child, int desired_child,
	struct sunxi_priv_data *gmac = priv->plat->bsp_priv;
	u32 reg, val;
	int ret = 0;
	bool need_power_ephy = false;

	if (current_child ^ desired_child) {
		regmap_field_read(gmac->regmap_field, &reg);
@@ -817,13 +833,12 @@ static int mdio_mux_syscon_switch_fn(int current_child, int desired_child,
		case DWMAC_SUN8I_MDIO_MUX_INTERNAL_ID:
			dev_info(priv->device, "Switch mux to internal PHY");
			val = (reg & ~H3_EPHY_MUX_MASK) | H3_EPHY_SELECT;

			need_power_ephy = true;
			gmac->use_internal_phy = true;
			break;
		case DWMAC_SUN8I_MDIO_MUX_EXTERNAL_ID:
			dev_info(priv->device, "Switch mux to external PHY");
			val = (reg & ~H3_EPHY_MUX_MASK) | H3_EPHY_SHUTDOWN;
			need_power_ephy = false;
			gmac->use_internal_phy = false;
			break;
		default:
			dev_err(priv->device, "Invalid child ID %x\n",
@@ -831,7 +846,7 @@ static int mdio_mux_syscon_switch_fn(int current_child, int desired_child,
			return -EINVAL;
		}
		regmap_field_write(gmac->regmap_field, val);
		if (need_power_ephy) {
		if (gmac->use_internal_phy) {
			ret = sun8i_dwmac_power_internal_phy(priv);
			if (ret)
				return ret;