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