Commit 6b7a02f7 authored by David S. Miller's avatar David S. Miller

Merge branch 'netsec-fixes'

Masahisa Kojima says:

====================
Bugfix for the netsec driver

This patch series include bugfix for the netsec ethernet
controller driver, fix the problem in interface down/up.

changes in v2:
 - change the place to perform the PHY power down
 - use the MACROs defiend in include/uapi/linux/mii.h
 - update commit comment
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 487e2e22 8d5b0bf6
...@@ -274,6 +274,7 @@ struct netsec_priv { ...@@ -274,6 +274,7 @@ struct netsec_priv {
struct clk *clk; struct clk *clk;
u32 msg_enable; u32 msg_enable;
u32 freq; u32 freq;
u32 phy_addr;
bool rx_cksum_offload_flag; bool rx_cksum_offload_flag;
}; };
...@@ -431,9 +432,12 @@ static int netsec_mac_update_to_phy_state(struct netsec_priv *priv) ...@@ -431,9 +432,12 @@ static int netsec_mac_update_to_phy_state(struct netsec_priv *priv)
return 0; return 0;
} }
static int netsec_phy_read(struct mii_bus *bus, int phy_addr, int reg_addr);
static int netsec_phy_write(struct mii_bus *bus, static int netsec_phy_write(struct mii_bus *bus,
int phy_addr, int reg, u16 val) int phy_addr, int reg, u16 val)
{ {
int status;
struct netsec_priv *priv = bus->priv; struct netsec_priv *priv = bus->priv;
if (netsec_mac_write(priv, GMAC_REG_GDR, val)) if (netsec_mac_write(priv, GMAC_REG_GDR, val))
...@@ -446,8 +450,19 @@ static int netsec_phy_write(struct mii_bus *bus, ...@@ -446,8 +450,19 @@ static int netsec_phy_write(struct mii_bus *bus,
GMAC_REG_SHIFT_CR_GAR))) GMAC_REG_SHIFT_CR_GAR)))
return -ETIMEDOUT; return -ETIMEDOUT;
return netsec_mac_wait_while_busy(priv, GMAC_REG_GAR, status = netsec_mac_wait_while_busy(priv, GMAC_REG_GAR,
NETSEC_GMAC_GAR_REG_GB); NETSEC_GMAC_GAR_REG_GB);
/* Developerbox implements RTL8211E PHY and there is
* a compatibility problem with F_GMAC4.
* RTL8211E expects MDC clock must be kept toggling for several
* clock cycle with MDIO high before entering the IDLE state.
* To meet this requirement, netsec driver needs to issue dummy
* read(e.g. read PHYID1(offset 0x2) register) right after write.
*/
netsec_phy_read(bus, phy_addr, MII_PHYSID1);
return status;
} }
static int netsec_phy_read(struct mii_bus *bus, int phy_addr, int reg_addr) static int netsec_phy_read(struct mii_bus *bus, int phy_addr, int reg_addr)
...@@ -940,6 +955,9 @@ static void netsec_uninit_pkt_dring(struct netsec_priv *priv, int id) ...@@ -940,6 +955,9 @@ static void netsec_uninit_pkt_dring(struct netsec_priv *priv, int id)
dring->head = 0; dring->head = 0;
dring->tail = 0; dring->tail = 0;
dring->pkt_cnt = 0; dring->pkt_cnt = 0;
if (id == NETSEC_RING_TX)
netdev_reset_queue(priv->ndev);
} }
static void netsec_free_dring(struct netsec_priv *priv, int id) static void netsec_free_dring(struct netsec_priv *priv, int id)
...@@ -1343,11 +1361,11 @@ static int netsec_netdev_stop(struct net_device *ndev) ...@@ -1343,11 +1361,11 @@ static int netsec_netdev_stop(struct net_device *ndev)
netsec_uninit_pkt_dring(priv, NETSEC_RING_TX); netsec_uninit_pkt_dring(priv, NETSEC_RING_TX);
netsec_uninit_pkt_dring(priv, NETSEC_RING_RX); netsec_uninit_pkt_dring(priv, NETSEC_RING_RX);
ret = netsec_reset_hardware(priv, false);
phy_stop(ndev->phydev); phy_stop(ndev->phydev);
phy_disconnect(ndev->phydev); phy_disconnect(ndev->phydev);
ret = netsec_reset_hardware(priv, false);
pm_runtime_put_sync(priv->dev); pm_runtime_put_sync(priv->dev);
return ret; return ret;
...@@ -1357,6 +1375,7 @@ static int netsec_netdev_init(struct net_device *ndev) ...@@ -1357,6 +1375,7 @@ static int netsec_netdev_init(struct net_device *ndev)
{ {
struct netsec_priv *priv = netdev_priv(ndev); struct netsec_priv *priv = netdev_priv(ndev);
int ret; int ret;
u16 data;
ret = netsec_alloc_dring(priv, NETSEC_RING_TX); ret = netsec_alloc_dring(priv, NETSEC_RING_TX);
if (ret) if (ret)
...@@ -1366,6 +1385,11 @@ static int netsec_netdev_init(struct net_device *ndev) ...@@ -1366,6 +1385,11 @@ static int netsec_netdev_init(struct net_device *ndev)
if (ret) if (ret)
goto err1; goto err1;
/* set phy power down */
data = netsec_phy_read(priv->mii_bus, priv->phy_addr, MII_BMCR) |
BMCR_PDOWN;
netsec_phy_write(priv->mii_bus, priv->phy_addr, MII_BMCR, data);
ret = netsec_reset_hardware(priv, true); ret = netsec_reset_hardware(priv, true);
if (ret) if (ret)
goto err2; goto err2;
...@@ -1415,7 +1439,7 @@ static const struct net_device_ops netsec_netdev_ops = { ...@@ -1415,7 +1439,7 @@ static const struct net_device_ops netsec_netdev_ops = {
}; };
static int netsec_of_probe(struct platform_device *pdev, static int netsec_of_probe(struct platform_device *pdev,
struct netsec_priv *priv) struct netsec_priv *priv, u32 *phy_addr)
{ {
priv->phy_np = of_parse_phandle(pdev->dev.of_node, "phy-handle", 0); priv->phy_np = of_parse_phandle(pdev->dev.of_node, "phy-handle", 0);
if (!priv->phy_np) { if (!priv->phy_np) {
...@@ -1423,6 +1447,8 @@ static int netsec_of_probe(struct platform_device *pdev, ...@@ -1423,6 +1447,8 @@ static int netsec_of_probe(struct platform_device *pdev,
return -EINVAL; return -EINVAL;
} }
*phy_addr = of_mdio_parse_addr(&pdev->dev, priv->phy_np);
priv->clk = devm_clk_get(&pdev->dev, NULL); /* get by 'phy_ref_clk' */ priv->clk = devm_clk_get(&pdev->dev, NULL); /* get by 'phy_ref_clk' */
if (IS_ERR(priv->clk)) { if (IS_ERR(priv->clk)) {
dev_err(&pdev->dev, "phy_ref_clk not found\n"); dev_err(&pdev->dev, "phy_ref_clk not found\n");
...@@ -1623,12 +1649,14 @@ static int netsec_probe(struct platform_device *pdev) ...@@ -1623,12 +1649,14 @@ static int netsec_probe(struct platform_device *pdev)
} }
if (dev_of_node(&pdev->dev)) if (dev_of_node(&pdev->dev))
ret = netsec_of_probe(pdev, priv); ret = netsec_of_probe(pdev, priv, &phy_addr);
else else
ret = netsec_acpi_probe(pdev, priv, &phy_addr); ret = netsec_acpi_probe(pdev, priv, &phy_addr);
if (ret) if (ret)
goto free_ndev; goto free_ndev;
priv->phy_addr = phy_addr;
if (!priv->freq) { if (!priv->freq) {
dev_err(&pdev->dev, "missing PHY reference clock frequency\n"); dev_err(&pdev->dev, "missing PHY reference clock frequency\n");
ret = -ENODEV; ret = -ENODEV;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment