710 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*******************************************************************************3 STMMAC Ethernet Driver -- MDIO bus implementation4 Provides Bus interface for MII registers5 6 Copyright (C) 2007-2009 STMicroelectronics Ltd7 8 9 Author: Carl Shaw <carl.shaw@st.com>10 Maintainer: Giuseppe Cavallaro <peppe.cavallaro@st.com>11*******************************************************************************/12 13#include <linux/gpio/consumer.h>14#include <linux/io.h>15#include <linux/iopoll.h>16#include <linux/mii.h>17#include <linux/of_mdio.h>18#include <linux/pm_runtime.h>19#include <linux/phy.h>20#include <linux/property.h>21#include <linux/slab.h>22 23#include "dwxgmac2.h"24#include "stmmac.h"25 26#define MII_BUSY 0x0000000127#define MII_WRITE 0x0000000228#define MII_DATA_MASK GENMASK(15, 0)29 30/* GMAC4 defines */31#define MII_GMAC4_GOC_SHIFT 232#define MII_GMAC4_REG_ADDR_SHIFT 1633#define MII_GMAC4_WRITE (1 << MII_GMAC4_GOC_SHIFT)34#define MII_GMAC4_READ (3 << MII_GMAC4_GOC_SHIFT)35#define MII_GMAC4_C45E BIT(1)36 37/* XGMAC defines */38#define MII_XGMAC_SADDR BIT(18)39#define MII_XGMAC_CMD_SHIFT 1640#define MII_XGMAC_WRITE (1 << MII_XGMAC_CMD_SHIFT)41#define MII_XGMAC_READ (3 << MII_XGMAC_CMD_SHIFT)42#define MII_XGMAC_BUSY BIT(22)43#define MII_XGMAC_MAX_C22ADDR 344#define MII_XGMAC_C22P_MASK GENMASK(MII_XGMAC_MAX_C22ADDR, 0)45#define MII_XGMAC_PA_SHIFT 1646#define MII_XGMAC_DA_SHIFT 2147 48static void stmmac_xgmac2_c45_format(struct stmmac_priv *priv, int phyaddr,49 int devad, int phyreg, u32 *hw_addr)50{51 u32 tmp;52 53 /* Set port as Clause 45 */54 tmp = readl(priv->ioaddr + XGMAC_MDIO_C22P);55 tmp &= ~BIT(phyaddr);56 writel(tmp, priv->ioaddr + XGMAC_MDIO_C22P);57 58 *hw_addr = (phyaddr << MII_XGMAC_PA_SHIFT) | (phyreg & 0xffff);59 *hw_addr |= devad << MII_XGMAC_DA_SHIFT;60}61 62static void stmmac_xgmac2_c22_format(struct stmmac_priv *priv, int phyaddr,63 int phyreg, u32 *hw_addr)64{65 u32 tmp = 0;66 67 if (priv->synopsys_id < DWXGMAC_CORE_2_20) {68 /* Until ver 2.20 XGMAC does not support C22 addr >= 4. Those69 * bits above bit 3 of XGMAC_MDIO_C22P register are reserved.70 */71 tmp = readl(priv->ioaddr + XGMAC_MDIO_C22P);72 tmp &= ~MII_XGMAC_C22P_MASK;73 }74 /* Set port as Clause 22 */75 tmp |= BIT(phyaddr);76 writel(tmp, priv->ioaddr + XGMAC_MDIO_C22P);77 78 *hw_addr = (phyaddr << MII_XGMAC_PA_SHIFT) | (phyreg & 0x1f);79}80 81static int stmmac_xgmac2_mdio_read(struct stmmac_priv *priv, u32 addr,82 u32 value)83{84 unsigned int mii_address = priv->hw->mii.addr;85 unsigned int mii_data = priv->hw->mii.data;86 u32 tmp;87 int ret;88 89 ret = pm_runtime_resume_and_get(priv->device);90 if (ret < 0)91 return ret;92 93 /* Wait until any existing MII operation is complete */94 if (readl_poll_timeout(priv->ioaddr + mii_data, tmp,95 !(tmp & MII_XGMAC_BUSY), 100, 10000)) {96 ret = -EBUSY;97 goto err_disable_clks;98 }99 100 value |= (priv->clk_csr << priv->hw->mii.clk_csr_shift)101 & priv->hw->mii.clk_csr_mask;102 value |= MII_XGMAC_READ;103 104 /* Wait until any existing MII operation is complete */105 if (readl_poll_timeout(priv->ioaddr + mii_data, tmp,106 !(tmp & MII_XGMAC_BUSY), 100, 10000)) {107 ret = -EBUSY;108 goto err_disable_clks;109 }110 111 /* Set the MII address register to read */112 writel(addr, priv->ioaddr + mii_address);113 writel(value, priv->ioaddr + mii_data);114 115 /* Wait until any existing MII operation is complete */116 if (readl_poll_timeout(priv->ioaddr + mii_data, tmp,117 !(tmp & MII_XGMAC_BUSY), 100, 10000)) {118 ret = -EBUSY;119 goto err_disable_clks;120 }121 122 /* Read the data from the MII data register */123 ret = (int)readl(priv->ioaddr + mii_data) & GENMASK(15, 0);124 125err_disable_clks:126 pm_runtime_put(priv->device);127 128 return ret;129}130 131static int stmmac_xgmac2_mdio_read_c22(struct mii_bus *bus, int phyaddr,132 int phyreg)133{134 struct net_device *ndev = bus->priv;135 struct stmmac_priv *priv;136 u32 addr;137 138 priv = netdev_priv(ndev);139 140 /* Until ver 2.20 XGMAC does not support C22 addr >= 4 */141 if (priv->synopsys_id < DWXGMAC_CORE_2_20 &&142 phyaddr > MII_XGMAC_MAX_C22ADDR)143 return -ENODEV;144 145 stmmac_xgmac2_c22_format(priv, phyaddr, phyreg, &addr);146 147 return stmmac_xgmac2_mdio_read(priv, addr, MII_XGMAC_BUSY);148}149 150static int stmmac_xgmac2_mdio_read_c45(struct mii_bus *bus, int phyaddr,151 int devad, int phyreg)152{153 struct net_device *ndev = bus->priv;154 struct stmmac_priv *priv;155 u32 addr;156 157 priv = netdev_priv(ndev);158 159 stmmac_xgmac2_c45_format(priv, phyaddr, devad, phyreg, &addr);160 161 return stmmac_xgmac2_mdio_read(priv, addr, MII_XGMAC_BUSY);162}163 164static int stmmac_xgmac2_mdio_write(struct stmmac_priv *priv, u32 addr,165 u32 value, u16 phydata)166{167 unsigned int mii_address = priv->hw->mii.addr;168 unsigned int mii_data = priv->hw->mii.data;169 u32 tmp;170 int ret;171 172 ret = pm_runtime_resume_and_get(priv->device);173 if (ret < 0)174 return ret;175 176 /* Wait until any existing MII operation is complete */177 if (readl_poll_timeout(priv->ioaddr + mii_data, tmp,178 !(tmp & MII_XGMAC_BUSY), 100, 10000)) {179 ret = -EBUSY;180 goto err_disable_clks;181 }182 183 value |= (priv->clk_csr << priv->hw->mii.clk_csr_shift)184 & priv->hw->mii.clk_csr_mask;185 value |= phydata;186 value |= MII_XGMAC_WRITE;187 188 /* Wait until any existing MII operation is complete */189 if (readl_poll_timeout(priv->ioaddr + mii_data, tmp,190 !(tmp & MII_XGMAC_BUSY), 100, 10000)) {191 ret = -EBUSY;192 goto err_disable_clks;193 }194 195 /* Set the MII address register to write */196 writel(addr, priv->ioaddr + mii_address);197 writel(value, priv->ioaddr + mii_data);198 199 /* Wait until any existing MII operation is complete */200 ret = readl_poll_timeout(priv->ioaddr + mii_data, tmp,201 !(tmp & MII_XGMAC_BUSY), 100, 10000);202 203err_disable_clks:204 pm_runtime_put(priv->device);205 206 return ret;207}208 209static int stmmac_xgmac2_mdio_write_c22(struct mii_bus *bus, int phyaddr,210 int phyreg, u16 phydata)211{212 struct net_device *ndev = bus->priv;213 struct stmmac_priv *priv;214 u32 addr;215 216 priv = netdev_priv(ndev);217 218 /* Until ver 2.20 XGMAC does not support C22 addr >= 4 */219 if (priv->synopsys_id < DWXGMAC_CORE_2_20 &&220 phyaddr > MII_XGMAC_MAX_C22ADDR)221 return -ENODEV;222 223 stmmac_xgmac2_c22_format(priv, phyaddr, phyreg, &addr);224 225 return stmmac_xgmac2_mdio_write(priv, addr,226 MII_XGMAC_BUSY | MII_XGMAC_SADDR, phydata);227}228 229static int stmmac_xgmac2_mdio_write_c45(struct mii_bus *bus, int phyaddr,230 int devad, int phyreg, u16 phydata)231{232 struct net_device *ndev = bus->priv;233 struct stmmac_priv *priv;234 u32 addr;235 236 priv = netdev_priv(ndev);237 238 stmmac_xgmac2_c45_format(priv, phyaddr, devad, phyreg, &addr);239 240 return stmmac_xgmac2_mdio_write(priv, addr, MII_XGMAC_BUSY,241 phydata);242}243 244static int stmmac_mdio_read(struct stmmac_priv *priv, int data, u32 value)245{246 unsigned int mii_address = priv->hw->mii.addr;247 unsigned int mii_data = priv->hw->mii.data;248 u32 v;249 250 if (readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY),251 100, 10000))252 return -EBUSY;253 254 writel(data, priv->ioaddr + mii_data);255 writel(value, priv->ioaddr + mii_address);256 257 if (readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY),258 100, 10000))259 return -EBUSY;260 261 /* Read the data from the MII data register */262 return readl(priv->ioaddr + mii_data) & MII_DATA_MASK;263}264 265/**266 * stmmac_mdio_read_c22267 * @bus: points to the mii_bus structure268 * @phyaddr: MII addr269 * @phyreg: MII reg270 * Description: it reads data from the MII register from within the phy device.271 * For the 7111 GMAC, we must set the bit 0 in the MII address register while272 * accessing the PHY registers.273 * Fortunately, it seems this has no drawback for the 7109 MAC.274 */275static int stmmac_mdio_read_c22(struct mii_bus *bus, int phyaddr, int phyreg)276{277 struct net_device *ndev = bus->priv;278 struct stmmac_priv *priv = netdev_priv(ndev);279 u32 value = MII_BUSY;280 int data = 0;281 282 data = pm_runtime_resume_and_get(priv->device);283 if (data < 0)284 return data;285 286 value |= (phyaddr << priv->hw->mii.addr_shift)287 & priv->hw->mii.addr_mask;288 value |= (phyreg << priv->hw->mii.reg_shift) & priv->hw->mii.reg_mask;289 value |= (priv->clk_csr << priv->hw->mii.clk_csr_shift)290 & priv->hw->mii.clk_csr_mask;291 if (priv->plat->has_gmac4)292 value |= MII_GMAC4_READ;293 294 data = stmmac_mdio_read(priv, data, value);295 296 pm_runtime_put(priv->device);297 298 return data;299}300 301/**302 * stmmac_mdio_read_c45303 * @bus: points to the mii_bus structure304 * @phyaddr: MII addr305 * @devad: device address to read306 * @phyreg: MII reg307 * Description: it reads data from the MII register from within the phy device.308 * For the 7111 GMAC, we must set the bit 0 in the MII address register while309 * accessing the PHY registers.310 * Fortunately, it seems this has no drawback for the 7109 MAC.311 */312static int stmmac_mdio_read_c45(struct mii_bus *bus, int phyaddr, int devad,313 int phyreg)314{315 struct net_device *ndev = bus->priv;316 struct stmmac_priv *priv = netdev_priv(ndev);317 u32 value = MII_BUSY;318 int data = 0;319 320 data = pm_runtime_get_sync(priv->device);321 if (data < 0) {322 pm_runtime_put_noidle(priv->device);323 return data;324 }325 326 value |= (phyaddr << priv->hw->mii.addr_shift)327 & priv->hw->mii.addr_mask;328 value |= (phyreg << priv->hw->mii.reg_shift) & priv->hw->mii.reg_mask;329 value |= (priv->clk_csr << priv->hw->mii.clk_csr_shift)330 & priv->hw->mii.clk_csr_mask;331 value |= MII_GMAC4_READ;332 value |= MII_GMAC4_C45E;333 value &= ~priv->hw->mii.reg_mask;334 value |= (devad << priv->hw->mii.reg_shift) & priv->hw->mii.reg_mask;335 336 data |= phyreg << MII_GMAC4_REG_ADDR_SHIFT;337 338 data = stmmac_mdio_read(priv, data, value);339 340 pm_runtime_put(priv->device);341 342 return data;343}344 345static int stmmac_mdio_write(struct stmmac_priv *priv, int data, u32 value)346{347 unsigned int mii_address = priv->hw->mii.addr;348 unsigned int mii_data = priv->hw->mii.data;349 u32 v;350 351 /* Wait until any existing MII operation is complete */352 if (readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY),353 100, 10000))354 return -EBUSY;355 356 /* Set the MII address register to write */357 writel(data, priv->ioaddr + mii_data);358 writel(value, priv->ioaddr + mii_address);359 360 /* Wait until any existing MII operation is complete */361 return readl_poll_timeout(priv->ioaddr + mii_address, v,362 !(v & MII_BUSY), 100, 10000);363}364 365/**366 * stmmac_mdio_write_c22367 * @bus: points to the mii_bus structure368 * @phyaddr: MII addr369 * @phyreg: MII reg370 * @phydata: phy data371 * Description: it writes the data into the MII register from within the device.372 */373static int stmmac_mdio_write_c22(struct mii_bus *bus, int phyaddr, int phyreg,374 u16 phydata)375{376 struct net_device *ndev = bus->priv;377 struct stmmac_priv *priv = netdev_priv(ndev);378 int ret, data = phydata;379 u32 value = MII_BUSY;380 381 ret = pm_runtime_resume_and_get(priv->device);382 if (ret < 0)383 return ret;384 385 value |= (phyaddr << priv->hw->mii.addr_shift)386 & priv->hw->mii.addr_mask;387 value |= (phyreg << priv->hw->mii.reg_shift) & priv->hw->mii.reg_mask;388 389 value |= (priv->clk_csr << priv->hw->mii.clk_csr_shift)390 & priv->hw->mii.clk_csr_mask;391 if (priv->plat->has_gmac4)392 value |= MII_GMAC4_WRITE;393 else394 value |= MII_WRITE;395 396 ret = stmmac_mdio_write(priv, data, value);397 398 pm_runtime_put(priv->device);399 400 return ret;401}402 403/**404 * stmmac_mdio_write_c45405 * @bus: points to the mii_bus structure406 * @phyaddr: MII addr407 * @phyreg: MII reg408 * @devad: device address to read409 * @phydata: phy data410 * Description: it writes the data into the MII register from within the device.411 */412static int stmmac_mdio_write_c45(struct mii_bus *bus, int phyaddr,413 int devad, int phyreg, u16 phydata)414{415 struct net_device *ndev = bus->priv;416 struct stmmac_priv *priv = netdev_priv(ndev);417 int ret, data = phydata;418 u32 value = MII_BUSY;419 420 ret = pm_runtime_get_sync(priv->device);421 if (ret < 0) {422 pm_runtime_put_noidle(priv->device);423 return ret;424 }425 426 value |= (phyaddr << priv->hw->mii.addr_shift)427 & priv->hw->mii.addr_mask;428 value |= (phyreg << priv->hw->mii.reg_shift) & priv->hw->mii.reg_mask;429 430 value |= (priv->clk_csr << priv->hw->mii.clk_csr_shift)431 & priv->hw->mii.clk_csr_mask;432 433 value |= MII_GMAC4_WRITE;434 value |= MII_GMAC4_C45E;435 value &= ~priv->hw->mii.reg_mask;436 value |= (devad << priv->hw->mii.reg_shift) & priv->hw->mii.reg_mask;437 438 data |= phyreg << MII_GMAC4_REG_ADDR_SHIFT;439 440 ret = stmmac_mdio_write(priv, data, value);441 442 pm_runtime_put(priv->device);443 444 return ret;445}446 447/**448 * stmmac_mdio_reset449 * @bus: points to the mii_bus structure450 * Description: reset the MII bus451 */452int stmmac_mdio_reset(struct mii_bus *bus)453{454#if IS_ENABLED(CONFIG_STMMAC_PLATFORM)455 struct net_device *ndev = bus->priv;456 struct stmmac_priv *priv = netdev_priv(ndev);457 unsigned int mii_address = priv->hw->mii.addr;458 459#ifdef CONFIG_OF460 if (priv->device->of_node) {461 struct gpio_desc *reset_gpio;462 u32 delays[3] = { 0, 0, 0 };463 464 reset_gpio = devm_gpiod_get_optional(priv->device,465 "snps,reset",466 GPIOD_OUT_LOW);467 if (IS_ERR(reset_gpio))468 return PTR_ERR(reset_gpio);469 470 device_property_read_u32_array(priv->device,471 "snps,reset-delays-us",472 delays, ARRAY_SIZE(delays));473 474 if (delays[0])475 msleep(DIV_ROUND_UP(delays[0], 1000));476 477 gpiod_set_value_cansleep(reset_gpio, 1);478 if (delays[1])479 msleep(DIV_ROUND_UP(delays[1], 1000));480 481 gpiod_set_value_cansleep(reset_gpio, 0);482 if (delays[2])483 msleep(DIV_ROUND_UP(delays[2], 1000));484 }485#endif486 487 /* This is a workaround for problems with the STE101P PHY.488 * It doesn't complete its reset until at least one clock cycle489 * on MDC, so perform a dummy mdio read. To be updated for GMAC4490 * if needed.491 */492 if (!priv->plat->has_gmac4)493 writel(0, priv->ioaddr + mii_address);494#endif495 return 0;496}497 498int stmmac_pcs_setup(struct net_device *ndev)499{500 struct fwnode_handle *devnode, *pcsnode;501 struct dw_xpcs *xpcs = NULL;502 struct stmmac_priv *priv;503 int addr, mode, ret;504 505 priv = netdev_priv(ndev);506 mode = priv->plat->phy_interface;507 devnode = priv->plat->port_node;508 509 if (priv->plat->pcs_init) {510 ret = priv->plat->pcs_init(priv);511 } else if (fwnode_property_present(devnode, "pcs-handle")) {512 pcsnode = fwnode_find_reference(devnode, "pcs-handle", 0);513 xpcs = xpcs_create_fwnode(pcsnode, mode);514 fwnode_handle_put(pcsnode);515 ret = PTR_ERR_OR_ZERO(xpcs);516 } else if (priv->plat->mdio_bus_data &&517 priv->plat->mdio_bus_data->pcs_mask) {518 addr = ffs(priv->plat->mdio_bus_data->pcs_mask) - 1;519 xpcs = xpcs_create_mdiodev(priv->mii, addr, mode);520 ret = PTR_ERR_OR_ZERO(xpcs);521 } else {522 return 0;523 }524 525 if (ret)526 return dev_err_probe(priv->device, ret, "No xPCS found\n");527 528 priv->hw->xpcs = xpcs;529 530 return 0;531}532 533void stmmac_pcs_clean(struct net_device *ndev)534{535 struct stmmac_priv *priv = netdev_priv(ndev);536 537 if (priv->plat->pcs_exit)538 priv->plat->pcs_exit(priv);539 540 if (!priv->hw->xpcs)541 return;542 543 xpcs_destroy(priv->hw->xpcs);544 priv->hw->xpcs = NULL;545}546 547/**548 * stmmac_mdio_register549 * @ndev: net device structure550 * Description: it registers the MII bus551 */552int stmmac_mdio_register(struct net_device *ndev)553{554 int err = 0;555 struct mii_bus *new_bus;556 struct stmmac_priv *priv = netdev_priv(ndev);557 struct stmmac_mdio_bus_data *mdio_bus_data = priv->plat->mdio_bus_data;558 struct device_node *mdio_node = priv->plat->mdio_node;559 struct device *dev = ndev->dev.parent;560 struct fwnode_handle *fixed_node;561 struct fwnode_handle *fwnode;562 int addr, found, max_addr;563 564 if (!mdio_bus_data)565 return 0;566 567 new_bus = mdiobus_alloc();568 if (!new_bus)569 return -ENOMEM;570 571 if (mdio_bus_data->irqs)572 memcpy(new_bus->irq, mdio_bus_data->irqs, sizeof(new_bus->irq));573 574 new_bus->name = "stmmac";575 576 if (priv->plat->has_xgmac) {577 new_bus->read = &stmmac_xgmac2_mdio_read_c22;578 new_bus->write = &stmmac_xgmac2_mdio_write_c22;579 new_bus->read_c45 = &stmmac_xgmac2_mdio_read_c45;580 new_bus->write_c45 = &stmmac_xgmac2_mdio_write_c45;581 582 if (priv->synopsys_id < DWXGMAC_CORE_2_20) {583 /* Right now only C22 phys are supported */584 max_addr = MII_XGMAC_MAX_C22ADDR + 1;585 586 /* Check if DT specified an unsupported phy addr */587 if (priv->plat->phy_addr > MII_XGMAC_MAX_C22ADDR)588 dev_err(dev, "Unsupported phy_addr (max=%d)\n",589 MII_XGMAC_MAX_C22ADDR);590 } else {591 /* XGMAC version 2.20 onwards support 32 phy addr */592 max_addr = PHY_MAX_ADDR;593 }594 } else {595 new_bus->read = &stmmac_mdio_read_c22;596 new_bus->write = &stmmac_mdio_write_c22;597 if (priv->plat->has_gmac4) {598 new_bus->read_c45 = &stmmac_mdio_read_c45;599 new_bus->write_c45 = &stmmac_mdio_write_c45;600 }601 602 max_addr = PHY_MAX_ADDR;603 }604 605 if (mdio_bus_data->needs_reset)606 new_bus->reset = &stmmac_mdio_reset;607 608 snprintf(new_bus->id, MII_BUS_ID_SIZE, "%s-%x",609 new_bus->name, priv->plat->bus_id);610 new_bus->priv = ndev;611 new_bus->phy_mask = mdio_bus_data->phy_mask | mdio_bus_data->pcs_mask;612 new_bus->parent = priv->device;613 614 err = of_mdiobus_register(new_bus, mdio_node);615 if (err == -ENODEV) {616 err = 0;617 dev_info(dev, "MDIO bus is disabled\n");618 goto bus_register_fail;619 } else if (err) {620 dev_err_probe(dev, err, "Cannot register the MDIO bus\n");621 goto bus_register_fail;622 }623 624 /* Looks like we need a dummy read for XGMAC only and C45 PHYs */625 if (priv->plat->has_xgmac)626 stmmac_xgmac2_mdio_read_c45(new_bus, 0, 0, 0);627 628 /* If fixed-link is set, skip PHY scanning */629 fwnode = priv->plat->port_node;630 if (!fwnode)631 fwnode = dev_fwnode(priv->device);632 633 if (fwnode) {634 fixed_node = fwnode_get_named_child_node(fwnode, "fixed-link");635 if (fixed_node) {636 fwnode_handle_put(fixed_node);637 goto bus_register_done;638 }639 }640 641 if (priv->plat->phy_node || mdio_node)642 goto bus_register_done;643 644 found = 0;645 for (addr = 0; addr < max_addr; addr++) {646 struct phy_device *phydev = mdiobus_get_phy(new_bus, addr);647 648 if (!phydev)649 continue;650 651 /*652 * If an IRQ was provided to be assigned after653 * the bus probe, do it here.654 */655 if (!mdio_bus_data->irqs &&656 (mdio_bus_data->probed_phy_irq > 0)) {657 new_bus->irq[addr] = mdio_bus_data->probed_phy_irq;658 phydev->irq = mdio_bus_data->probed_phy_irq;659 }660 661 /*662 * If we're going to bind the MAC to this PHY bus,663 * and no PHY number was provided to the MAC,664 * use the one probed here.665 */666 if (priv->plat->phy_addr == -1)667 priv->plat->phy_addr = addr;668 669 phy_attached_info(phydev);670 found = 1;671 }672 673 if (!found && !mdio_node) {674 dev_warn(dev, "No PHY found\n");675 err = -ENODEV;676 goto no_phy_found;677 }678 679bus_register_done:680 priv->mii = new_bus;681 682 return 0;683 684no_phy_found:685 mdiobus_unregister(new_bus);686bus_register_fail:687 mdiobus_free(new_bus);688 return err;689}690 691/**692 * stmmac_mdio_unregister693 * @ndev: net device structure694 * Description: it unregisters the MII bus695 */696int stmmac_mdio_unregister(struct net_device *ndev)697{698 struct stmmac_priv *priv = netdev_priv(ndev);699 700 if (!priv->mii)701 return 0;702 703 mdiobus_unregister(priv->mii);704 priv->mii->priv = NULL;705 mdiobus_free(priv->mii);706 priv->mii = NULL;707 708 return 0;709}710