cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

bcmmii.c (17399B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Broadcom GENET MDIO routines
      4 *
      5 * Copyright (c) 2014-2017 Broadcom
      6 */
      7
      8#include <linux/acpi.h>
      9#include <linux/types.h>
     10#include <linux/delay.h>
     11#include <linux/wait.h>
     12#include <linux/mii.h>
     13#include <linux/ethtool.h>
     14#include <linux/bitops.h>
     15#include <linux/netdevice.h>
     16#include <linux/platform_device.h>
     17#include <linux/phy.h>
     18#include <linux/phy_fixed.h>
     19#include <linux/brcmphy.h>
     20#include <linux/of.h>
     21#include <linux/of_net.h>
     22#include <linux/of_mdio.h>
     23#include <linux/platform_data/bcmgenet.h>
     24#include <linux/platform_data/mdio-bcm-unimac.h>
     25
     26#include "bcmgenet.h"
     27
     28static void bcmgenet_mac_config(struct net_device *dev)
     29{
     30	struct bcmgenet_priv *priv = netdev_priv(dev);
     31	struct phy_device *phydev = dev->phydev;
     32	u32 reg, cmd_bits = 0;
     33
     34	/* speed */
     35	if (phydev->speed == SPEED_1000)
     36		cmd_bits = CMD_SPEED_1000;
     37	else if (phydev->speed == SPEED_100)
     38		cmd_bits = CMD_SPEED_100;
     39	else
     40		cmd_bits = CMD_SPEED_10;
     41	cmd_bits <<= CMD_SPEED_SHIFT;
     42
     43	/* duplex */
     44	if (phydev->duplex != DUPLEX_FULL) {
     45		cmd_bits |= CMD_HD_EN |
     46			CMD_RX_PAUSE_IGNORE | CMD_TX_PAUSE_IGNORE;
     47	} else {
     48		/* pause capability defaults to Symmetric */
     49		if (priv->autoneg_pause) {
     50			bool tx_pause = 0, rx_pause = 0;
     51
     52			if (phydev->autoneg)
     53				phy_get_pause(phydev, &tx_pause, &rx_pause);
     54
     55			if (!tx_pause)
     56				cmd_bits |= CMD_TX_PAUSE_IGNORE;
     57			if (!rx_pause)
     58				cmd_bits |= CMD_RX_PAUSE_IGNORE;
     59		}
     60
     61		/* Manual override */
     62		if (!priv->rx_pause)
     63			cmd_bits |= CMD_RX_PAUSE_IGNORE;
     64		if (!priv->tx_pause)
     65			cmd_bits |= CMD_TX_PAUSE_IGNORE;
     66	}
     67
     68	/* Program UMAC and RGMII block based on established
     69	 * link speed, duplex, and pause. The speed set in
     70	 * umac->cmd tell RGMII block which clock to use for
     71	 * transmit -- 25MHz(100Mbps) or 125MHz(1Gbps).
     72	 * Receive clock is provided by the PHY.
     73	 */
     74	reg = bcmgenet_ext_readl(priv, EXT_RGMII_OOB_CTRL);
     75	reg &= ~OOB_DISABLE;
     76	reg |= RGMII_LINK;
     77	bcmgenet_ext_writel(priv, reg, EXT_RGMII_OOB_CTRL);
     78
     79	reg = bcmgenet_umac_readl(priv, UMAC_CMD);
     80	reg &= ~((CMD_SPEED_MASK << CMD_SPEED_SHIFT) |
     81		       CMD_HD_EN |
     82		       CMD_RX_PAUSE_IGNORE | CMD_TX_PAUSE_IGNORE);
     83	reg |= cmd_bits;
     84	if (reg & CMD_SW_RESET) {
     85		reg &= ~CMD_SW_RESET;
     86		bcmgenet_umac_writel(priv, reg, UMAC_CMD);
     87		udelay(2);
     88		reg |= CMD_TX_EN | CMD_RX_EN;
     89	}
     90	bcmgenet_umac_writel(priv, reg, UMAC_CMD);
     91}
     92
     93/* setup netdev link state when PHY link status change and
     94 * update UMAC and RGMII block when link up
     95 */
     96void bcmgenet_mii_setup(struct net_device *dev)
     97{
     98	struct phy_device *phydev = dev->phydev;
     99
    100	if (phydev->link)
    101		bcmgenet_mac_config(dev);
    102	phy_print_status(phydev);
    103}
    104
    105
    106static int bcmgenet_fixed_phy_link_update(struct net_device *dev,
    107					  struct fixed_phy_status *status)
    108{
    109	struct bcmgenet_priv *priv;
    110	u32 reg;
    111
    112	if (dev && dev->phydev && status) {
    113		priv = netdev_priv(dev);
    114		reg = bcmgenet_umac_readl(priv, UMAC_MODE);
    115		status->link = !!(reg & MODE_LINK_STATUS);
    116	}
    117
    118	return 0;
    119}
    120
    121void bcmgenet_phy_pause_set(struct net_device *dev, bool rx, bool tx)
    122{
    123	struct phy_device *phydev = dev->phydev;
    124
    125	linkmode_mod_bit(ETHTOOL_LINK_MODE_Pause_BIT, phydev->advertising, rx);
    126	linkmode_mod_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, phydev->advertising,
    127			 rx | tx);
    128	phy_start_aneg(phydev);
    129
    130	mutex_lock(&phydev->lock);
    131	if (phydev->link)
    132		bcmgenet_mac_config(dev);
    133	mutex_unlock(&phydev->lock);
    134}
    135
    136void bcmgenet_phy_power_set(struct net_device *dev, bool enable)
    137{
    138	struct bcmgenet_priv *priv = netdev_priv(dev);
    139	u32 reg = 0;
    140
    141	/* EXT_GPHY_CTRL is only valid for GENETv4 and onward */
    142	if (GENET_IS_V4(priv) || priv->ephy_16nm) {
    143		reg = bcmgenet_ext_readl(priv, EXT_GPHY_CTRL);
    144		if (enable) {
    145			reg &= ~EXT_CK25_DIS;
    146			bcmgenet_ext_writel(priv, reg, EXT_GPHY_CTRL);
    147			mdelay(1);
    148
    149			reg &= ~(EXT_CFG_IDDQ_BIAS | EXT_CFG_PWR_DOWN |
    150				 EXT_CFG_IDDQ_GLOBAL_PWR);
    151			reg |= EXT_GPHY_RESET;
    152			bcmgenet_ext_writel(priv, reg, EXT_GPHY_CTRL);
    153			mdelay(1);
    154
    155			reg &= ~EXT_GPHY_RESET;
    156		} else {
    157			reg |= EXT_CFG_IDDQ_BIAS | EXT_CFG_PWR_DOWN |
    158			       EXT_GPHY_RESET | EXT_CFG_IDDQ_GLOBAL_PWR;
    159			bcmgenet_ext_writel(priv, reg, EXT_GPHY_CTRL);
    160			mdelay(1);
    161			reg |= EXT_CK25_DIS;
    162		}
    163		bcmgenet_ext_writel(priv, reg, EXT_GPHY_CTRL);
    164		udelay(60);
    165	} else {
    166		mdelay(1);
    167	}
    168}
    169
    170static void bcmgenet_moca_phy_setup(struct bcmgenet_priv *priv)
    171{
    172	u32 reg;
    173
    174	if (!GENET_IS_V5(priv)) {
    175		/* Speed settings are set in bcmgenet_mii_setup() */
    176		reg = bcmgenet_sys_readl(priv, SYS_PORT_CTRL);
    177		reg |= LED_ACT_SOURCE_MAC;
    178		bcmgenet_sys_writel(priv, reg, SYS_PORT_CTRL);
    179	}
    180
    181	if (priv->hw_params->flags & GENET_HAS_MOCA_LINK_DET)
    182		fixed_phy_set_link_update(priv->dev->phydev,
    183					  bcmgenet_fixed_phy_link_update);
    184}
    185
    186int bcmgenet_mii_config(struct net_device *dev, bool init)
    187{
    188	struct bcmgenet_priv *priv = netdev_priv(dev);
    189	struct phy_device *phydev = dev->phydev;
    190	struct device *kdev = &priv->pdev->dev;
    191	const char *phy_name = NULL;
    192	u32 id_mode_dis = 0;
    193	u32 port_ctrl;
    194	u32 reg;
    195
    196	switch (priv->phy_interface) {
    197	case PHY_INTERFACE_MODE_INTERNAL:
    198		phy_name = "internal PHY";
    199		fallthrough;
    200	case PHY_INTERFACE_MODE_MOCA:
    201		/* Irrespective of the actually configured PHY speed (100 or
    202		 * 1000) GENETv4 only has an internal GPHY so we will just end
    203		 * up masking the Gigabit features from what we support, not
    204		 * switching to the EPHY
    205		 */
    206		if (GENET_IS_V4(priv))
    207			port_ctrl = PORT_MODE_INT_GPHY;
    208		else
    209			port_ctrl = PORT_MODE_INT_EPHY;
    210
    211		if (!phy_name) {
    212			phy_name = "MoCA";
    213			bcmgenet_moca_phy_setup(priv);
    214		}
    215		break;
    216
    217	case PHY_INTERFACE_MODE_MII:
    218		phy_name = "external MII";
    219		phy_set_max_speed(phydev, SPEED_100);
    220		port_ctrl = PORT_MODE_EXT_EPHY;
    221		break;
    222
    223	case PHY_INTERFACE_MODE_REVMII:
    224		phy_name = "external RvMII";
    225		/* of_mdiobus_register took care of reading the 'max-speed'
    226		 * PHY property for us, effectively limiting the PHY supported
    227		 * capabilities, use that knowledge to also configure the
    228		 * Reverse MII interface correctly.
    229		 */
    230		if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
    231				      dev->phydev->supported))
    232			port_ctrl = PORT_MODE_EXT_RVMII_50;
    233		else
    234			port_ctrl = PORT_MODE_EXT_RVMII_25;
    235		break;
    236
    237	case PHY_INTERFACE_MODE_RGMII:
    238		/* RGMII_NO_ID: TXC transitions at the same time as TXD
    239		 *		(requires PCB or receiver-side delay)
    240		 *
    241		 * ID is implicitly disabled for 100Mbps (RG)MII operation.
    242		 */
    243		phy_name = "external RGMII (no delay)";
    244		id_mode_dis = BIT(16);
    245		port_ctrl = PORT_MODE_EXT_GPHY;
    246		break;
    247
    248	case PHY_INTERFACE_MODE_RGMII_TXID:
    249		/* RGMII_TXID:	Add 2ns delay on TXC (90 degree shift) */
    250		phy_name = "external RGMII (TX delay)";
    251		port_ctrl = PORT_MODE_EXT_GPHY;
    252		break;
    253
    254	case PHY_INTERFACE_MODE_RGMII_RXID:
    255		phy_name = "external RGMII (RX delay)";
    256		port_ctrl = PORT_MODE_EXT_GPHY;
    257		break;
    258	default:
    259		dev_err(kdev, "unknown phy mode: %d\n", priv->phy_interface);
    260		return -EINVAL;
    261	}
    262
    263	bcmgenet_sys_writel(priv, port_ctrl, SYS_PORT_CTRL);
    264
    265	priv->ext_phy = !priv->internal_phy &&
    266			(priv->phy_interface != PHY_INTERFACE_MODE_MOCA);
    267
    268	/* This is an external PHY (xMII), so we need to enable the RGMII
    269	 * block for the interface to work
    270	 */
    271	if (priv->ext_phy) {
    272		reg = bcmgenet_ext_readl(priv, EXT_RGMII_OOB_CTRL);
    273		reg &= ~ID_MODE_DIS;
    274		reg |= id_mode_dis;
    275		if (GENET_IS_V1(priv) || GENET_IS_V2(priv) || GENET_IS_V3(priv))
    276			reg |= RGMII_MODE_EN_V123;
    277		else
    278			reg |= RGMII_MODE_EN;
    279		bcmgenet_ext_writel(priv, reg, EXT_RGMII_OOB_CTRL);
    280	}
    281
    282	if (init)
    283		dev_info(kdev, "configuring instance for %s\n", phy_name);
    284
    285	return 0;
    286}
    287
    288int bcmgenet_mii_probe(struct net_device *dev)
    289{
    290	struct bcmgenet_priv *priv = netdev_priv(dev);
    291	struct device *kdev = &priv->pdev->dev;
    292	struct device_node *dn = kdev->of_node;
    293	phy_interface_t phy_iface = priv->phy_interface;
    294	struct phy_device *phydev;
    295	u32 phy_flags = PHY_BRCM_AUTO_PWRDWN_ENABLE |
    296			PHY_BRCM_DIS_TXCRXC_NOENRGY |
    297			PHY_BRCM_IDDQ_SUSPEND;
    298	int ret;
    299
    300	/* Communicate the integrated PHY revision */
    301	if (priv->internal_phy)
    302		phy_flags = priv->gphy_rev;
    303
    304	/* This is an ugly quirk but we have not been correctly interpreting
    305	 * the phy_interface values and we have done that across different
    306	 * drivers, so at least we are consistent in our mistakes.
    307	 *
    308	 * When the Generic PHY driver is in use either the PHY has been
    309	 * strapped or programmed correctly by the boot loader so we should
    310	 * stick to our incorrect interpretation since we have validated it.
    311	 *
    312	 * Now when a dedicated PHY driver is in use, we need to reverse the
    313	 * meaning of the phy_interface_mode values to something that the PHY
    314	 * driver will interpret and act on such that we have two mistakes
    315	 * canceling themselves so to speak. We only do this for the two
    316	 * modes that GENET driver officially supports on Broadcom STB chips:
    317	 * PHY_INTERFACE_MODE_RGMII and PHY_INTERFACE_MODE_RGMII_TXID. Other
    318	 * modes are not *officially* supported with the boot loader and the
    319	 * scripted environment generating Device Tree blobs for those
    320	 * platforms.
    321	 *
    322	 * Note that internal PHY, MoCA and fixed-link configurations are not
    323	 * affected because they use different phy_interface_t values or the
    324	 * Generic PHY driver.
    325	 */
    326	switch (priv->phy_interface) {
    327	case PHY_INTERFACE_MODE_RGMII:
    328		phy_iface = PHY_INTERFACE_MODE_RGMII_ID;
    329		break;
    330	case PHY_INTERFACE_MODE_RGMII_TXID:
    331		phy_iface = PHY_INTERFACE_MODE_RGMII_RXID;
    332		break;
    333	default:
    334		break;
    335	}
    336
    337	if (dn) {
    338		phydev = of_phy_connect(dev, priv->phy_dn, bcmgenet_mii_setup,
    339					phy_flags, phy_iface);
    340		if (!phydev) {
    341			pr_err("could not attach to PHY\n");
    342			return -ENODEV;
    343		}
    344	} else {
    345		if (has_acpi_companion(kdev)) {
    346			char mdio_bus_id[MII_BUS_ID_SIZE];
    347			struct mii_bus *unimacbus;
    348
    349			snprintf(mdio_bus_id, MII_BUS_ID_SIZE, "%s-%d",
    350				 UNIMAC_MDIO_DRV_NAME, priv->pdev->id);
    351
    352			unimacbus = mdio_find_bus(mdio_bus_id);
    353			if (!unimacbus) {
    354				pr_err("Unable to find mii\n");
    355				return -ENODEV;
    356			}
    357			phydev = phy_find_first(unimacbus);
    358			put_device(&unimacbus->dev);
    359			if (!phydev) {
    360				pr_err("Unable to find PHY\n");
    361				return -ENODEV;
    362			}
    363		} else {
    364			phydev = dev->phydev;
    365		}
    366		phydev->dev_flags = phy_flags;
    367
    368		ret = phy_connect_direct(dev, phydev, bcmgenet_mii_setup,
    369					 phy_iface);
    370		if (ret) {
    371			pr_err("could not attach to PHY\n");
    372			return -ENODEV;
    373		}
    374	}
    375
    376	/* Configure port multiplexer based on what the probed PHY device since
    377	 * reading the 'max-speed' property determines the maximum supported
    378	 * PHY speed which is needed for bcmgenet_mii_config() to configure
    379	 * things appropriately.
    380	 */
    381	ret = bcmgenet_mii_config(dev, true);
    382	if (ret) {
    383		phy_disconnect(dev->phydev);
    384		return ret;
    385	}
    386
    387	/* The internal PHY has its link interrupts routed to the
    388	 * Ethernet MAC ISRs. On GENETv5 there is a hardware issue
    389	 * that prevents the signaling of link UP interrupts when
    390	 * the link operates at 10Mbps, so fallback to polling for
    391	 * those versions of GENET.
    392	 */
    393	if (priv->internal_phy && !GENET_IS_V5(priv))
    394		dev->phydev->irq = PHY_MAC_INTERRUPT;
    395
    396	return 0;
    397}
    398
    399static struct device_node *bcmgenet_mii_of_find_mdio(struct bcmgenet_priv *priv)
    400{
    401	struct device_node *dn = priv->pdev->dev.of_node;
    402	struct device *kdev = &priv->pdev->dev;
    403	char *compat;
    404
    405	compat = kasprintf(GFP_KERNEL, "brcm,genet-mdio-v%d", priv->version);
    406	if (!compat)
    407		return NULL;
    408
    409	priv->mdio_dn = of_get_compatible_child(dn, compat);
    410	kfree(compat);
    411	if (!priv->mdio_dn) {
    412		dev_err(kdev, "unable to find MDIO bus node\n");
    413		return NULL;
    414	}
    415
    416	return priv->mdio_dn;
    417}
    418
    419static void bcmgenet_mii_pdata_init(struct bcmgenet_priv *priv,
    420				    struct unimac_mdio_pdata *ppd)
    421{
    422	struct device *kdev = &priv->pdev->dev;
    423	struct bcmgenet_platform_data *pd = kdev->platform_data;
    424
    425	if (pd->phy_interface != PHY_INTERFACE_MODE_MOCA && pd->mdio_enabled) {
    426		/*
    427		 * Internal or external PHY with MDIO access
    428		 */
    429		if (pd->phy_address >= 0 && pd->phy_address < PHY_MAX_ADDR)
    430			ppd->phy_mask = 1 << pd->phy_address;
    431		else
    432			ppd->phy_mask = 0;
    433	}
    434}
    435
    436static int bcmgenet_mii_wait(void *wait_func_data)
    437{
    438	struct bcmgenet_priv *priv = wait_func_data;
    439
    440	wait_event_timeout(priv->wq,
    441			   !(bcmgenet_umac_readl(priv, UMAC_MDIO_CMD)
    442			   & MDIO_START_BUSY),
    443			   HZ / 100);
    444	return 0;
    445}
    446
    447static int bcmgenet_mii_register(struct bcmgenet_priv *priv)
    448{
    449	struct platform_device *pdev = priv->pdev;
    450	struct bcmgenet_platform_data *pdata = pdev->dev.platform_data;
    451	struct device_node *dn = pdev->dev.of_node;
    452	struct unimac_mdio_pdata ppd;
    453	struct platform_device *ppdev;
    454	struct resource *pres, res;
    455	int id, ret;
    456
    457	pres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    458	if (!pres) {
    459		dev_err(&pdev->dev, "Invalid resource\n");
    460		return -EINVAL;
    461	}
    462	memset(&res, 0, sizeof(res));
    463	memset(&ppd, 0, sizeof(ppd));
    464
    465	ppd.wait_func = bcmgenet_mii_wait;
    466	ppd.wait_func_data = priv;
    467	ppd.bus_name = "bcmgenet MII bus";
    468
    469	/* Unimac MDIO bus controller starts at UniMAC offset + MDIO_CMD
    470	 * and is 2 * 32-bits word long, 8 bytes total.
    471	 */
    472	res.start = pres->start + GENET_UMAC_OFF + UMAC_MDIO_CMD;
    473	res.end = res.start + 8;
    474	res.flags = IORESOURCE_MEM;
    475
    476	if (dn)
    477		id = of_alias_get_id(dn, "eth");
    478	else
    479		id = pdev->id;
    480
    481	ppdev = platform_device_alloc(UNIMAC_MDIO_DRV_NAME, id);
    482	if (!ppdev)
    483		return -ENOMEM;
    484
    485	/* Retain this platform_device pointer for later cleanup */
    486	priv->mii_pdev = ppdev;
    487	ppdev->dev.parent = &pdev->dev;
    488	if (dn)
    489		ppdev->dev.of_node = bcmgenet_mii_of_find_mdio(priv);
    490	else if (pdata)
    491		bcmgenet_mii_pdata_init(priv, &ppd);
    492	else
    493		ppd.phy_mask = ~0;
    494
    495	ret = platform_device_add_resources(ppdev, &res, 1);
    496	if (ret)
    497		goto out;
    498
    499	ret = platform_device_add_data(ppdev, &ppd, sizeof(ppd));
    500	if (ret)
    501		goto out;
    502
    503	ret = platform_device_add(ppdev);
    504	if (ret)
    505		goto out;
    506
    507	return 0;
    508out:
    509	platform_device_put(ppdev);
    510	return ret;
    511}
    512
    513static int bcmgenet_phy_interface_init(struct bcmgenet_priv *priv)
    514{
    515	struct device *kdev = &priv->pdev->dev;
    516	int phy_mode = device_get_phy_mode(kdev);
    517
    518	if (phy_mode < 0) {
    519		dev_err(kdev, "invalid PHY mode property\n");
    520		return phy_mode;
    521	}
    522
    523	priv->phy_interface = phy_mode;
    524
    525	/* We need to specifically look up whether this PHY interface is
    526	 * internal or not *before* we even try to probe the PHY driver
    527	 * over MDIO as we may have shut down the internal PHY for power
    528	 * saving purposes.
    529	 */
    530	if (priv->phy_interface == PHY_INTERFACE_MODE_INTERNAL)
    531		priv->internal_phy = true;
    532
    533	return 0;
    534}
    535
    536static int bcmgenet_mii_of_init(struct bcmgenet_priv *priv)
    537{
    538	struct device_node *dn = priv->pdev->dev.of_node;
    539	struct phy_device *phydev;
    540	int ret;
    541
    542	/* Fetch the PHY phandle */
    543	priv->phy_dn = of_parse_phandle(dn, "phy-handle", 0);
    544
    545	/* In the case of a fixed PHY, the DT node associated
    546	 * to the PHY is the Ethernet MAC DT node.
    547	 */
    548	if (!priv->phy_dn && of_phy_is_fixed_link(dn)) {
    549		ret = of_phy_register_fixed_link(dn);
    550		if (ret)
    551			return ret;
    552
    553		priv->phy_dn = of_node_get(dn);
    554	}
    555
    556	/* Get the link mode */
    557	ret = bcmgenet_phy_interface_init(priv);
    558	if (ret)
    559		return ret;
    560
    561	/* Make sure we initialize MoCA PHYs with a link down */
    562	if (priv->phy_interface == PHY_INTERFACE_MODE_MOCA) {
    563		phydev = of_phy_find_device(dn);
    564		if (phydev) {
    565			phydev->link = 0;
    566			put_device(&phydev->mdio.dev);
    567		}
    568	}
    569
    570	return 0;
    571}
    572
    573static int bcmgenet_mii_pd_init(struct bcmgenet_priv *priv)
    574{
    575	struct device *kdev = &priv->pdev->dev;
    576	struct bcmgenet_platform_data *pd = kdev->platform_data;
    577	char phy_name[MII_BUS_ID_SIZE + 3];
    578	char mdio_bus_id[MII_BUS_ID_SIZE];
    579	struct phy_device *phydev;
    580
    581	snprintf(mdio_bus_id, MII_BUS_ID_SIZE, "%s-%d",
    582		 UNIMAC_MDIO_DRV_NAME, priv->pdev->id);
    583
    584	if (pd->phy_interface != PHY_INTERFACE_MODE_MOCA && pd->mdio_enabled) {
    585		snprintf(phy_name, MII_BUS_ID_SIZE, PHY_ID_FMT,
    586			 mdio_bus_id, pd->phy_address);
    587
    588		/*
    589		 * Internal or external PHY with MDIO access
    590		 */
    591		phydev = phy_attach(priv->dev, phy_name, pd->phy_interface);
    592		if (IS_ERR(phydev)) {
    593			dev_err(kdev, "failed to register PHY device\n");
    594			return PTR_ERR(phydev);
    595		}
    596	} else {
    597		/*
    598		 * MoCA port or no MDIO access.
    599		 * Use fixed PHY to represent the link layer.
    600		 */
    601		struct fixed_phy_status fphy_status = {
    602			.link = 1,
    603			.speed = pd->phy_speed,
    604			.duplex = pd->phy_duplex,
    605			.pause = 0,
    606			.asym_pause = 0,
    607		};
    608
    609		phydev = fixed_phy_register(PHY_POLL, &fphy_status, NULL);
    610		if (!phydev || IS_ERR(phydev)) {
    611			dev_err(kdev, "failed to register fixed PHY device\n");
    612			return -ENODEV;
    613		}
    614
    615		/* Make sure we initialize MoCA PHYs with a link down */
    616		phydev->link = 0;
    617
    618	}
    619
    620	priv->phy_interface = pd->phy_interface;
    621
    622	return 0;
    623}
    624
    625static int bcmgenet_mii_bus_init(struct bcmgenet_priv *priv)
    626{
    627	struct device *kdev = &priv->pdev->dev;
    628	struct device_node *dn = kdev->of_node;
    629
    630	if (dn)
    631		return bcmgenet_mii_of_init(priv);
    632	else if (has_acpi_companion(kdev))
    633		return bcmgenet_phy_interface_init(priv);
    634	else
    635		return bcmgenet_mii_pd_init(priv);
    636}
    637
    638int bcmgenet_mii_init(struct net_device *dev)
    639{
    640	struct bcmgenet_priv *priv = netdev_priv(dev);
    641	int ret;
    642
    643	ret = bcmgenet_mii_register(priv);
    644	if (ret)
    645		return ret;
    646
    647	ret = bcmgenet_mii_bus_init(priv);
    648	if (ret)
    649		goto out;
    650
    651	return 0;
    652
    653out:
    654	bcmgenet_mii_exit(dev);
    655	return ret;
    656}
    657
    658void bcmgenet_mii_exit(struct net_device *dev)
    659{
    660	struct bcmgenet_priv *priv = netdev_priv(dev);
    661	struct device_node *dn = priv->pdev->dev.of_node;
    662
    663	if (of_phy_is_fixed_link(dn))
    664		of_phy_deregister_fixed_link(dn);
    665	of_node_put(priv->phy_dn);
    666	platform_device_unregister(priv->mii_pdev);
    667}