提交 c4dea9dd 编写于 作者: S Samuel Holland 提交者: Zheng Zengkai

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

stable inclusion
from stable-5.10.8
commit 35526a9c46b40f9465f136894695c74a288e03a2
bugzilla: 47450

--------------------------------

[ Upstream commit b8239638 ]

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: NSamuel Holland <samuel@sholland.org>
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: NChen Jun <chenjun102@huawei.com>
Acked-by: NXie XiuQi <xiexiuqi@huawei.com>
上级 6ab1dd50
...@@ -64,6 +64,7 @@ struct emac_variant { ...@@ -64,6 +64,7 @@ struct emac_variant {
* @variant: reference to the current board variant * @variant: reference to the current board variant
* @regmap: regmap for using the syscon * @regmap: regmap for using the syscon
* @internal_phy_powered: Does the internal PHY is enabled * @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 * @mux_handle: Internal pointer used by mdio-mux lib
*/ */
struct sunxi_priv_data { struct sunxi_priv_data {
...@@ -74,6 +75,7 @@ struct sunxi_priv_data { ...@@ -74,6 +75,7 @@ struct sunxi_priv_data {
const struct emac_variant *variant; const struct emac_variant *variant;
struct regmap_field *regmap_field; struct regmap_field *regmap_field;
bool internal_phy_powered; bool internal_phy_powered;
bool use_internal_phy;
void *mux_handle; void *mux_handle;
}; };
...@@ -539,8 +541,11 @@ static const struct stmmac_dma_ops sun8i_dwmac_dma_ops = { ...@@ -539,8 +541,11 @@ static const struct stmmac_dma_ops sun8i_dwmac_dma_ops = {
.dma_interrupt = sun8i_dwmac_dma_interrupt, .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) 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; struct sunxi_priv_data *gmac = priv;
int ret; int ret;
...@@ -554,13 +559,25 @@ static int sun8i_dwmac_init(struct platform_device *pdev, void *priv) ...@@ -554,13 +559,25 @@ static int sun8i_dwmac_init(struct platform_device *pdev, void *priv)
ret = clk_prepare_enable(gmac->tx_clk); ret = clk_prepare_enable(gmac->tx_clk);
if (ret) { if (ret) {
if (gmac->regulator)
regulator_disable(gmac->regulator);
dev_err(&pdev->dev, "Could not enable AHB clock\n"); 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; 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, static void sun8i_dwmac_core_init(struct mac_device_info *hw,
...@@ -831,7 +848,6 @@ static int mdio_mux_syscon_switch_fn(int current_child, int desired_child, ...@@ -831,7 +848,6 @@ static int mdio_mux_syscon_switch_fn(int current_child, int desired_child,
struct sunxi_priv_data *gmac = priv->plat->bsp_priv; struct sunxi_priv_data *gmac = priv->plat->bsp_priv;
u32 reg, val; u32 reg, val;
int ret = 0; int ret = 0;
bool need_power_ephy = false;
if (current_child ^ desired_child) { if (current_child ^ desired_child) {
regmap_field_read(gmac->regmap_field, &reg); regmap_field_read(gmac->regmap_field, &reg);
...@@ -839,13 +855,12 @@ static int mdio_mux_syscon_switch_fn(int current_child, int desired_child, ...@@ -839,13 +855,12 @@ static int mdio_mux_syscon_switch_fn(int current_child, int desired_child,
case DWMAC_SUN8I_MDIO_MUX_INTERNAL_ID: case DWMAC_SUN8I_MDIO_MUX_INTERNAL_ID:
dev_info(priv->device, "Switch mux to internal PHY"); dev_info(priv->device, "Switch mux to internal PHY");
val = (reg & ~H3_EPHY_MUX_MASK) | H3_EPHY_SELECT; val = (reg & ~H3_EPHY_MUX_MASK) | H3_EPHY_SELECT;
gmac->use_internal_phy = true;
need_power_ephy = true;
break; break;
case DWMAC_SUN8I_MDIO_MUX_EXTERNAL_ID: case DWMAC_SUN8I_MDIO_MUX_EXTERNAL_ID:
dev_info(priv->device, "Switch mux to external PHY"); dev_info(priv->device, "Switch mux to external PHY");
val = (reg & ~H3_EPHY_MUX_MASK) | H3_EPHY_SHUTDOWN; val = (reg & ~H3_EPHY_MUX_MASK) | H3_EPHY_SHUTDOWN;
need_power_ephy = false; gmac->use_internal_phy = false;
break; break;
default: default:
dev_err(priv->device, "Invalid child ID %x\n", dev_err(priv->device, "Invalid child ID %x\n",
...@@ -853,7 +868,7 @@ static int mdio_mux_syscon_switch_fn(int current_child, int desired_child, ...@@ -853,7 +868,7 @@ static int mdio_mux_syscon_switch_fn(int current_child, int desired_child,
return -EINVAL; return -EINVAL;
} }
regmap_field_write(gmac->regmap_field, val); regmap_field_write(gmac->regmap_field, val);
if (need_power_ephy) { if (gmac->use_internal_phy) {
ret = sun8i_dwmac_power_internal_phy(priv); ret = sun8i_dwmac_power_internal_phy(priv);
if (ret) if (ret)
return ret; return ret;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册