diff options
| author | Jakub Kicinski <kuba@kernel.org> | 2025-09-08 18:12:10 -0700 |
|---|---|---|
| committer | Jakub Kicinski <kuba@kernel.org> | 2025-09-08 18:12:10 -0700 |
| commit | 6e0cca6ba3425f992dd6ad5049c47005dcb18ad8 (patch) | |
| tree | 13acb51920cfc8507437b46cb4218eefcfbf6037 | |
| parent | 144d0b1c45ea382c9ff6d7d9c6dfe609ae1ef169 (diff) | |
| parent | fc8f62c827ead74ec6bdf76bc78993e9402968ee (diff) | |
Merge branch 'net-stmmac-mdio-cleanups'
Russell King says:
====================
net: stmmac: mdio cleanups
Clean up the stmmac MDIO code:
- provide an address register formatter to avoid repeated code
- provide a common function to wait for the busy bit to clear
- pre-compute the CR field (mdio clock divider)
- move address formatter into read/write functions
- combine the read/write functions into a common accessor function
- move runtime PM handling into common accessor function
- rename register constants to better reflect manufacturer names
- move stmmac_clk_csr_set() into stmmac_mdio
- make stmmac_clk_csr_set() return the CR field value and remove
priv->clk_csr
- clean up if() range tests in stmmac_clk_csr_set()
- use STMMAC_CSR_xxx definitions in initialisers
For Qualcomm QCS9100 Ride R3 board with the AQR115C PHY:
Tested-by: Mohd Ayaan Anwar <quic_mohdayaa@quicinc.com>
====================
Link: https://patch.msgid.link/aLmBwsMdW__XBv7g@shell.armlinux.org.uk
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
| -rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c | 5 | ||||
| -rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c | 3 | ||||
| -rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/stmmac.h | 2 | ||||
| -rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 82 | ||||
| -rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c | 345 | ||||
| -rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c | 5 |
6 files changed, 207 insertions, 235 deletions
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c index 3ff271b097ea..e74d00984b88 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c @@ -563,7 +563,8 @@ static int intel_mac_finish(struct net_device *ndev, static void common_default_data(struct plat_stmmacenet_data *plat) { - plat->clk_csr = 2; /* clk_csr_i = 20-35MHz & MDC = clk_csr_i/16 */ + /* clk_csr_i = 20-35MHz & MDC = clk_csr_i/16 */ + plat->clk_csr = STMMAC_CSR_20_35M; plat->has_gmac = 1; plat->force_sf_dma_mode = 1; @@ -610,7 +611,7 @@ static int intel_mgbe_common_data(struct pci_dev *pdev, plat->pdev = pdev; plat->phy_addr = -1; - plat->clk_csr = 5; + plat->clk_csr = STMMAC_CSR_250_300M; plat->has_gmac = 0; plat->has_gmac4 = 1; plat->force_sf_dma_mode = 0; diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c index 6fca0fca4892..dd82dc2189e9 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-loongson.c @@ -90,7 +90,8 @@ static void loongson_default_data(struct pci_dev *pdev, /* Get bus_id, this can be overwritten later */ plat->bus_id = pci_dev_id(pdev); - plat->clk_csr = 2; /* clk_csr_i = 20-35MHz & MDC = clk_csr_i/16 */ + /* clk_csr_i = 20-35MHz & MDC = clk_csr_i/16 */ + plat->clk_csr = STMMAC_CSR_20_35M; plat->has_gmac = 1; plat->force_sf_dma_mode = 1; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h index 78d6b3737a26..ec6bccb13710 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h @@ -289,7 +289,7 @@ struct stmmac_priv { u32 msg_enable; int wolopts; int wol_irq; - int clk_csr; + u32 gmii_address_bus_config; struct timer_list eee_ctrl_timer; int lpi_irq; u32 tx_lpi_timer; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index f0abd99fd137..419cb49ee5a2 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -314,77 +314,6 @@ static void stmmac_global_err(struct stmmac_priv *priv) stmmac_service_event_schedule(priv); } -/** - * stmmac_clk_csr_set - dynamically set the MDC clock - * @priv: driver private structure - * Description: this is to dynamically set the MDC clock according to the csr - * clock input. - * Note: - * If a specific clk_csr value is passed from the platform - * this means that the CSR Clock Range selection cannot be - * changed at run-time and it is fixed (as reported in the driver - * documentation). Viceversa the driver will try to set the MDC - * clock dynamically according to the actual clock input. - */ -static void stmmac_clk_csr_set(struct stmmac_priv *priv) -{ - unsigned long clk_rate; - - clk_rate = clk_get_rate(priv->plat->stmmac_clk); - - /* Platform provided default clk_csr would be assumed valid - * for all other cases except for the below mentioned ones. - * For values higher than the IEEE 802.3 specified frequency - * we can not estimate the proper divider as it is not known - * the frequency of clk_csr_i. So we do not change the default - * divider. - */ - if (!(priv->clk_csr & MAC_CSR_H_FRQ_MASK)) { - if (clk_rate < CSR_F_35M) - priv->clk_csr = STMMAC_CSR_20_35M; - else if ((clk_rate >= CSR_F_35M) && (clk_rate < CSR_F_60M)) - priv->clk_csr = STMMAC_CSR_35_60M; - else if ((clk_rate >= CSR_F_60M) && (clk_rate < CSR_F_100M)) - priv->clk_csr = STMMAC_CSR_60_100M; - else if ((clk_rate >= CSR_F_100M) && (clk_rate < CSR_F_150M)) - priv->clk_csr = STMMAC_CSR_100_150M; - else if ((clk_rate >= CSR_F_150M) && (clk_rate < CSR_F_250M)) - priv->clk_csr = STMMAC_CSR_150_250M; - else if ((clk_rate >= CSR_F_250M) && (clk_rate <= CSR_F_300M)) - priv->clk_csr = STMMAC_CSR_250_300M; - else if ((clk_rate >= CSR_F_300M) && (clk_rate < CSR_F_500M)) - priv->clk_csr = STMMAC_CSR_300_500M; - else if ((clk_rate >= CSR_F_500M) && (clk_rate < CSR_F_800M)) - priv->clk_csr = STMMAC_CSR_500_800M; - } - - if (priv->plat->flags & STMMAC_FLAG_HAS_SUN8I) { - if (clk_rate > 160000000) - priv->clk_csr = 0x03; - else if (clk_rate > 80000000) - priv->clk_csr = 0x02; - else if (clk_rate > 40000000) - priv->clk_csr = 0x01; - else - priv->clk_csr = 0; - } - - if (priv->plat->has_xgmac) { - if (clk_rate > 400000000) - priv->clk_csr = 0x5; - else if (clk_rate > 350000000) - priv->clk_csr = 0x4; - else if (clk_rate > 300000000) - priv->clk_csr = 0x3; - else if (clk_rate > 250000000) - priv->clk_csr = 0x2; - else if (clk_rate > 150000000) - priv->clk_csr = 0x1; - else - priv->clk_csr = 0x0; - } -} - static void print_pkt(unsigned char *buf, int len) { pr_debug("len = %d byte, buf addr: 0x%p\n", len, buf); @@ -7718,17 +7647,6 @@ int stmmac_dvr_probe(struct device *device, stmmac_fpe_init(priv); - /* If a specific clk_csr value is passed from the platform - * this means that the CSR Clock Range selection cannot be - * changed at run-time and it is fixed. Viceversa the driver'll try to - * set the MDC clock dynamically according to the csr actual - * clock input. - */ - if (priv->plat->clk_csr >= 0) - priv->clk_csr = priv->plat->clk_csr; - else - stmmac_clk_csr_set(priv); - stmmac_check_pcs_mode(priv); pm_runtime_get_noresume(device); diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c index 0a302b711bc2..f408737f6fc7 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c @@ -23,9 +23,9 @@ #include "dwxgmac2.h" #include "stmmac.h" -#define MII_BUSY 0x00000001 -#define MII_WRITE 0x00000002 -#define MII_DATA_MASK GENMASK(15, 0) +#define MII_ADDR_GBUSY BIT(0) +#define MII_ADDR_GWRITE BIT(1) +#define MII_DATA_GD_MASK GENMASK(15, 0) /* GMAC4 defines */ #define MII_GMAC4_GOC_SHIFT 2 @@ -45,6 +45,16 @@ #define MII_XGMAC_PA_SHIFT 16 #define MII_XGMAC_DA_SHIFT 21 +static int stmmac_mdio_wait(void __iomem *reg, u32 mask) +{ + u32 v; + + if (readl_poll_timeout(reg, v, !(v & mask), 100, 10000)) + return -EBUSY; + + return 0; +} + static void stmmac_xgmac2_c45_format(struct stmmac_priv *priv, int phyaddr, int devad, int phyreg, u32 *hw_addr) { @@ -83,7 +93,6 @@ static int stmmac_xgmac2_mdio_read(struct stmmac_priv *priv, u32 addr, { unsigned int mii_address = priv->hw->mii.addr; unsigned int mii_data = priv->hw->mii.data; - u32 tmp; int ret; ret = pm_runtime_resume_and_get(priv->device); @@ -91,33 +100,25 @@ static int stmmac_xgmac2_mdio_read(struct stmmac_priv *priv, u32 addr, return ret; /* Wait until any existing MII operation is complete */ - if (readl_poll_timeout(priv->ioaddr + mii_data, tmp, - !(tmp & MII_XGMAC_BUSY), 100, 10000)) { - ret = -EBUSY; + ret = stmmac_mdio_wait(priv->ioaddr + mii_data, MII_XGMAC_BUSY); + if (ret) goto err_disable_clks; - } - value |= (priv->clk_csr << priv->hw->mii.clk_csr_shift) - & priv->hw->mii.clk_csr_mask; - value |= MII_XGMAC_READ; + value |= priv->gmii_address_bus_config | MII_XGMAC_READ; /* Wait until any existing MII operation is complete */ - if (readl_poll_timeout(priv->ioaddr + mii_data, tmp, - !(tmp & MII_XGMAC_BUSY), 100, 10000)) { - ret = -EBUSY; + ret = stmmac_mdio_wait(priv->ioaddr + mii_data, MII_XGMAC_BUSY); + if (ret) goto err_disable_clks; - } /* Set the MII address register to read */ writel(addr, priv->ioaddr + mii_address); writel(value, priv->ioaddr + mii_data); /* Wait until any existing MII operation is complete */ - if (readl_poll_timeout(priv->ioaddr + mii_data, tmp, - !(tmp & MII_XGMAC_BUSY), 100, 10000)) { - ret = -EBUSY; + ret = stmmac_mdio_wait(priv->ioaddr + mii_data, MII_XGMAC_BUSY); + if (ret) goto err_disable_clks; - } /* Read the data from the MII data register */ ret = (int)readl(priv->ioaddr + mii_data) & GENMASK(15, 0); @@ -160,7 +161,6 @@ static int stmmac_xgmac2_mdio_write(struct stmmac_priv *priv, u32 addr, { unsigned int mii_address = priv->hw->mii.addr; unsigned int mii_data = priv->hw->mii.data; - u32 tmp; int ret; ret = pm_runtime_resume_and_get(priv->device); @@ -168,31 +168,23 @@ static int stmmac_xgmac2_mdio_write(struct stmmac_priv *priv, u32 addr, return ret; /* Wait until any existing MII operation is complete */ - if (readl_poll_timeout(priv->ioaddr + mii_data, tmp, - !(tmp & MII_XGMAC_BUSY), 100, 10000)) { - ret = -EBUSY; + ret = stmmac_mdio_wait(priv->ioaddr + mii_data, MII_XGMAC_BUSY); + if (ret) goto err_disable_clks; - } - value |= (priv->clk_csr << priv->hw->mii.clk_csr_shift) - & priv->hw->mii.clk_csr_mask; - value |= phydata; - value |= MII_XGMAC_WRITE; + value |= priv->gmii_address_bus_config | phydata | MII_XGMAC_WRITE; /* Wait until any existing MII operation is complete */ - if (readl_poll_timeout(priv->ioaddr + mii_data, tmp, - !(tmp & MII_XGMAC_BUSY), 100, 10000)) { - ret = -EBUSY; + ret = stmmac_mdio_wait(priv->ioaddr + mii_data, MII_XGMAC_BUSY); + if (ret) goto err_disable_clks; - } /* Set the MII address register to write */ writel(addr, priv->ioaddr + mii_address); writel(value, priv->ioaddr + mii_data); /* Wait until any existing MII operation is complete */ - ret = readl_poll_timeout(priv->ioaddr + mii_data, tmp, - !(tmp & MII_XGMAC_BUSY), 100, 10000); + ret = stmmac_mdio_wait(priv->ioaddr + mii_data, MII_XGMAC_BUSY); err_disable_clks: pm_runtime_put(priv->device); @@ -229,25 +221,69 @@ static int stmmac_xgmac2_mdio_write_c45(struct mii_bus *bus, int phyaddr, phydata); } -static int stmmac_mdio_read(struct stmmac_priv *priv, int data, u32 value) +/** + * stmmac_mdio_format_addr() - format the address register + * @priv: struct stmmac_priv pointer + * @pa: 5-bit MDIO package address + * @gr: 5-bit MDIO register address (C22) or MDIO device address (C45) + * + * Return: formatted address register + */ +static u32 stmmac_mdio_format_addr(struct stmmac_priv *priv, + unsigned int pa, unsigned int gr) { - unsigned int mii_address = priv->hw->mii.addr; - unsigned int mii_data = priv->hw->mii.data; - u32 v; + const struct mii_regs *mii_regs = &priv->hw->mii; - if (readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY), - 100, 10000)) - return -EBUSY; + return ((pa << mii_regs->addr_shift) & mii_regs->addr_mask) | + ((gr << mii_regs->reg_shift) & mii_regs->reg_mask) | + priv->gmii_address_bus_config | + MII_ADDR_GBUSY; +} + +static int stmmac_mdio_access(struct stmmac_priv *priv, unsigned int pa, + unsigned int gr, u32 cmd, u32 data, bool read) +{ + void __iomem *mii_address = priv->ioaddr + priv->hw->mii.addr; + void __iomem *mii_data = priv->ioaddr + priv->hw->mii.data; + u32 addr; + int ret; + + ret = pm_runtime_resume_and_get(priv->device); + if (ret < 0) + return ret; - writel(data, priv->ioaddr + mii_data); - writel(value, priv->ioaddr + mii_address); + ret = stmmac_mdio_wait(mii_address, MII_ADDR_GBUSY); + if (ret) + goto out; - if (readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY), - 100, 10000)) - return -EBUSY; + addr = stmmac_mdio_format_addr(priv, pa, gr) | cmd; - /* Read the data from the MII data register */ - return readl(priv->ioaddr + mii_data) & MII_DATA_MASK; + writel(data, mii_data); + writel(addr, mii_address); + + ret = stmmac_mdio_wait(mii_address, MII_ADDR_GBUSY); + if (ret) + goto out; + + /* Read the data from the MII data register if in read mode */ + ret = read ? readl(mii_data) & MII_DATA_GD_MASK : 0; + +out: + pm_runtime_put(priv->device); + + return ret; +} + +static int stmmac_mdio_read(struct stmmac_priv *priv, unsigned int pa, + unsigned int gr, u32 cmd, int data) +{ + return stmmac_mdio_access(priv, pa, gr, cmd, data, true); +} + +static int stmmac_mdio_write(struct stmmac_priv *priv, unsigned int pa, + unsigned int gr, u32 cmd, int data) +{ + return stmmac_mdio_access(priv, pa, gr, cmd, data, false); } /** @@ -263,26 +299,14 @@ static int stmmac_mdio_read(struct stmmac_priv *priv, int data, u32 value) static int stmmac_mdio_read_c22(struct mii_bus *bus, int phyaddr, int phyreg) { struct stmmac_priv *priv = netdev_priv(bus->priv); - u32 value = MII_BUSY; - int data = 0; - - data = pm_runtime_resume_and_get(priv->device); - if (data < 0) - return data; - - value |= (phyaddr << priv->hw->mii.addr_shift) - & priv->hw->mii.addr_mask; - value |= (phyreg << priv->hw->mii.reg_shift) & priv->hw->mii.reg_mask; - value |= (priv->clk_csr << priv->hw->mii.clk_csr_shift) - & priv->hw->mii.clk_csr_mask; - if (priv->plat->has_gmac4) - value |= MII_GMAC4_READ; - - data = stmmac_mdio_read(priv, data, value); + u32 cmd; - pm_runtime_put(priv->device); + if (priv->plat->has_gmac4) + cmd = MII_GMAC4_READ; + else + cmd = 0; - return data; + return stmmac_mdio_read(priv, phyaddr, phyreg, cmd, 0); } /** @@ -300,48 +324,10 @@ static int stmmac_mdio_read_c45(struct mii_bus *bus, int phyaddr, int devad, int phyreg) { struct stmmac_priv *priv = netdev_priv(bus->priv); - u32 value = MII_BUSY; - int data = 0; - - data = pm_runtime_resume_and_get(priv->device); - if (data < 0) - return data; - - value |= (phyaddr << priv->hw->mii.addr_shift) - & priv->hw->mii.addr_mask; - value |= (priv->clk_csr << priv->hw->mii.clk_csr_shift) - & priv->hw->mii.clk_csr_mask; - value |= MII_GMAC4_READ; - value |= MII_GMAC4_C45E; - value |= (devad << priv->hw->mii.reg_shift) & priv->hw->mii.reg_mask; - - data |= phyreg << MII_GMAC4_REG_ADDR_SHIFT; + int data = phyreg << MII_GMAC4_REG_ADDR_SHIFT; + u32 cmd = MII_GMAC4_READ | MII_GMAC4_C45E; - data = stmmac_mdio_read(priv, data, value); - - pm_runtime_put(priv->device); - - return data; -} - -static int stmmac_mdio_write(struct stmmac_priv *priv, int data, u32 value) -{ - unsigned int mii_address = priv->hw->mii.addr; - unsigned int mii_data = priv->hw->mii.data; - u32 v; - - /* Wait until any existing MII operation is complete */ - if (readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY), - 100, 10000)) - return -EBUSY; - - /* Set the MII address register to write */ - writel(data, priv->ioaddr + mii_data); - writel(value, priv->ioaddr + mii_address); - - /* Wait until any existing MII operation is complete */ - return readl_poll_timeout(priv->ioaddr + mii_address, v, - !(v & MII_BUSY), 100, 10000); + return stmmac_mdio_read(priv, phyaddr, devad, cmd, data); } /** @@ -356,29 +342,14 @@ static int stmmac_mdio_write_c22(struct mii_bus *bus, int phyaddr, int phyreg, u16 phydata) { struct stmmac_priv *priv = netdev_priv(bus->priv); - int ret, data = phydata; - u32 value = MII_BUSY; - - ret = pm_runtime_resume_and_get(priv->device); - if (ret < 0) - return ret; - - value |= (phyaddr << priv->hw->mii.addr_shift) - & priv->hw->mii.addr_mask; - value |= (phyreg << priv->hw->mii.reg_shift) & priv->hw->mii.reg_mask; + u32 cmd; - value |= (priv->clk_csr << priv->hw->mii.clk_csr_shift) - & priv->hw->mii.clk_csr_mask; if (priv->plat->has_gmac4) - value |= MII_GMAC4_WRITE; + cmd = MII_GMAC4_WRITE; else - value |= MII_WRITE; + cmd = MII_ADDR_GWRITE; - ret = stmmac_mdio_write(priv, data, value); - - pm_runtime_put(priv->device); - - return ret; + return stmmac_mdio_write(priv, phyaddr, phyreg, cmd, phydata); } /** @@ -394,30 +365,12 @@ static int stmmac_mdio_write_c45(struct mii_bus *bus, int phyaddr, int devad, int phyreg, u16 phydata) { struct stmmac_priv *priv = netdev_priv(bus->priv); - int ret, data = phydata; - u32 value = MII_BUSY; - - ret = pm_runtime_resume_and_get(priv->device); - if (ret < 0) - return ret; - - value |= (phyaddr << priv->hw->mii.addr_shift) - & priv->hw->mii.addr_mask; - - value |= (priv->clk_csr << priv->hw->mii.clk_csr_shift) - & priv->hw->mii.clk_csr_mask; - - value |= MII_GMAC4_WRITE; - value |= MII_GMAC4_C45E; - value |= (devad << priv->hw->mii.reg_shift) & priv->hw->mii.reg_mask; + u32 cmd = MII_GMAC4_WRITE | MII_GMAC4_C45E; + int data = phydata; data |= phyreg << MII_GMAC4_REG_ADDR_SHIFT; - ret = stmmac_mdio_write(priv, data, value); - - pm_runtime_put(priv->device); - - return ret; + return stmmac_mdio_write(priv, phyaddr, devad, cmd, data); } /** @@ -521,6 +474,102 @@ void stmmac_pcs_clean(struct net_device *ndev) } /** + * stmmac_clk_csr_set - dynamically set the MDC clock + * @priv: driver private structure + * Description: this is to dynamically set the MDC clock according to the csr + * clock input. + * Return: MII register CR field value + * Note: + * If a specific clk_csr value is passed from the platform + * this means that the CSR Clock Range selection cannot be + * changed at run-time and it is fixed (as reported in the driver + * documentation). Viceversa the driver will try to set the MDC + * clock dynamically according to the actual clock input. + */ +static u32 stmmac_clk_csr_set(struct stmmac_priv *priv) +{ + unsigned long clk_rate; + u32 value = ~0; + + clk_rate = clk_get_rate(priv->plat->stmmac_clk); + + /* Platform provided default clk_csr would be assumed valid + * for all other cases except for the below mentioned ones. + * For values higher than the IEEE 802.3 specified frequency + * we can not estimate the proper divider as it is not known + * the frequency of clk_csr_i. So we do not change the default + * divider. + */ + if (clk_rate < CSR_F_35M) + value = STMMAC_CSR_20_35M; + else if (clk_rate < CSR_F_60M) + value = STMMAC_CSR_35_60M; + else if (clk_rate < CSR_F_100M) + value = STMMAC_CSR_60_100M; + else if (clk_rate < CSR_F_150M) + value = STMMAC_CSR_100_150M; + else if (clk_rate < CSR_F_250M) + value = STMMAC_CSR_150_250M; + else if (clk_rate <= CSR_F_300M) + value = STMMAC_CSR_250_300M; + else if (clk_rate < CSR_F_500M) + value = STMMAC_CSR_300_500M; + else if (clk_rate < CSR_F_800M) + value = STMMAC_CSR_500_800M; + + if (priv->plat->flags & STMMAC_FLAG_HAS_SUN8I) { + if (clk_rate > 160000000) + value = 0x03; + else if (clk_rate > 80000000) + value = 0x02; + else if (clk_rate > 40000000) + value = 0x01; + else + value = 0; + } + + if (priv->plat->has_xgmac) { + if (clk_rate > 400000000) + value = 0x5; + else if (clk_rate > 350000000) + value = 0x4; + else if (clk_rate > 300000000) + value = 0x3; + else if (clk_rate > 250000000) + value = 0x2; + else if (clk_rate > 150000000) + value = 0x1; + else + value = 0x0; + } + + return value; +} + +static void stmmac_mdio_bus_config(struct stmmac_priv *priv) +{ + u32 value; + + /* If a specific clk_csr value is passed from the platform, this means + * that the CSR Clock Range value should not be computed from the CSR + * clock. + */ + if (priv->plat->clk_csr >= 0) + value = priv->plat->clk_csr; + else + value = stmmac_clk_csr_set(priv); + + value <<= priv->hw->mii.clk_csr_shift; + + if (value & ~priv->hw->mii.clk_csr_mask) + dev_warn(priv->device, + "clk_csr value out of range (0x%08x exceeds mask 0x%08x), truncating\n", + value, priv->hw->mii.clk_csr_mask); + + priv->gmii_address_bus_config = value & priv->hw->mii.clk_csr_mask; +} + +/** * stmmac_mdio_register * @ndev: net device structure * Description: it registers the MII bus @@ -540,6 +589,8 @@ int stmmac_mdio_register(struct net_device *ndev) if (!mdio_bus_data) return 0; + stmmac_mdio_bus_config(priv); + new_bus = mdiobus_alloc(); if (!new_bus) return -ENOMEM; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c index e6a7d0ddac2a..4e3aa611fda8 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c @@ -21,7 +21,8 @@ struct stmmac_pci_info { static void common_default_data(struct plat_stmmacenet_data *plat) { - plat->clk_csr = 2; /* clk_csr_i = 20-35MHz & MDC = clk_csr_i/16 */ + /* clk_csr_i = 20-35MHz & MDC = clk_csr_i/16 */ + plat->clk_csr = STMMAC_CSR_20_35M; plat->has_gmac = 1; plat->force_sf_dma_mode = 1; @@ -74,7 +75,7 @@ static int snps_gmac5_default_data(struct pci_dev *pdev, { int i; - plat->clk_csr = 5; + plat->clk_csr = STMMAC_CSR_250_300M; plat->has_gmac4 = 1; plat->force_sf_dma_mode = 1; plat->flags |= STMMAC_FLAG_TSO_EN; |
