File Index
Files and directories
Sign in
FILE

bcmmii.c

File preview with syntax highlighting.

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