Patchwork [U-Boot,6/6] powerpc/85xx: update P4080DS MDIO bus multiplexer support

login
register
mail settings
Submitter Timur Tabi
Date Aug. 10, 2012, 10:01 p.m.
Message ID <1344636096-11669-6-git-send-email-timur@freescale.com>
Download mbox | patch
Permalink /patch/176635/
State Superseded
Headers show

Comments

Timur Tabi - Aug. 10, 2012, 10:01 p.m.
The Freescale P4080DS has a complex multiplexed MDIO bus, where the
muxing varies per SerDes protocol.  This is because the protocol
determines in which PCI slot the various SGMII and XGMII interface
cards belong, as well as whether the RGMII ports are enabled.

The Freescale SDK includes support for MDIO bus multiplexing, but the
upstream Linux kernel uses David Daney's (Cavium) method instead.
Therefore, the P4080 code needs to be migrated to the new method.

The device tree contains two top-level mdio-mux nodes, one for EMI1
(RGMII and SGMII) and the other for EMI2 (XGMII).  The U-boot code
depends on several device tree aliases to help it find the nodes that
need to be updated.

Signed-off-by: Timur Tabi <timur@freescale.com>
---
 board/freescale/corenet_ds/eth_p4080.c |  172 ++++++++++++++++++++++++--------
 1 files changed, 129 insertions(+), 43 deletions(-)

Patch

diff --git a/board/freescale/corenet_ds/eth_p4080.c b/board/freescale/corenet_ds/eth_p4080.c
index 2c69c51..3c1c3a1 100644
--- a/board/freescale/corenet_ds/eth_p4080.c
+++ b/board/freescale/corenet_ds/eth_p4080.c
@@ -53,7 +53,7 @@ 
 #define EMI1_MASK	0xc0000000
 #define EMI2_MASK	0x30000000
 
-static int mdio_mux[NUM_FM_PORTS];
+static u32 mdio_mux[NUM_FM_PORTS];
 
 static char *mdio_names[16] = {
 	"P4080DS_MDIO0",
@@ -232,73 +232,159 @@  static int p4080ds_mdio_init(char *realbusname, u32 muxval)
 	return mdio_register(bus);
 }
 
-void board_ft_fman_fixup_port(void *blob, char * prop, phys_addr_t pa,
-				enum fm_port port, int offset)
+/*
+ * Given the following ...
+ *
+ * 1) A pointer to an Fman Ethernet node (as identified by the 'compat'
+ * compatible string and 'addr' physical address)
+ *
+ * 2) An Fman port
+ *
+ * ... update the phy-handle property of the Ethernet node to point to the
+ * right PHY.  This assumes that we already know the PHY for each port.
+ *
+ * The PHY type (RGMII, SGMII, XGMII) is already set via a prior call to
+ * fdt_fixup_phy_connection().  The parent mdio-mux node will be enabled later
+ * in fdt_fixup_board_enet().
+ *
+ * Note that what we call "Fman ports" (enum fm_port) is really an Fman MAC.
+ * Inside the Fman, "ports" are things that connect to MACs.  We only call
+ * them ports in U-Boot because on previous Ethernet devices (e.g. Gianfar),
+ * MACs and ports are the same thing.
+ *
+ * XGMII Ethernet nodes are already mapped correctly, so we ignore those.
+ */
+void board_ft_fman_fixup_port(void *fdt, char *compat, phys_addr_t addr,
+			      enum fm_port port, int offset)
 {
-	if (mdio_mux[port] == EMI1_RGMII)
-		fdt_set_phy_handle(blob, prop, pa, "phy_rgmii");
-
-	if (mdio_mux[port] == EMI1_SLOT3) {
-		int idx = port - FM2_DTSEC1 + 5;
-		char phy[16];
+	phy_interface_t phyc = fm_info_get_enet_if(port);
+	enum srds_prtcl device;
+	int lane;
+	int ret = 0;
+
+	switch (phyc) {
+	case PHY_INTERFACE_MODE_RGMII:
+		debug("Setting phy-handle for ethernet@%llx to RGMII\n", addr);
+		ret = fdt_set_phy_handle(fdt, compat, addr, "phy_rgmii");
+		break;
+
+	case PHY_INTERFACE_MODE_SGMII:
+		device = serdes_device_from_fm_port(port);
+		lane = serdes_get_first_lane(device);
+
+		if (lane >= 0) {
+			unsigned int slot = lane_to_slot[lane];
+			int phy = fm_info_get_phy_address(port);
+			char alias[32];
+
+			debug("Setting phy-handle for ethernet@%llx to slot %u,"
+			      " addr %x\n", addr, slot, phy);
+			sprintf(alias, "phy_sgmii_slot%u_%x", slot, phy);
+			ret = fdt_set_phy_handle(fdt, compat, addr, alias);
+		}
+		break;
 
-		sprintf(phy, "phy%d_slot3", idx);
+	default:
+		/* XGMII nodes are already linked in the DTS */
+		debug("Skipping phy-handle setup for %s ethernet@%llx\n",
+		      phy_interface_strings[phyc], addr);
+		break;
+	}
 
-		fdt_set_phy_handle(blob, prop, pa, phy);
+	if (ret < 0) {
+		printf("Fman: could not set phy-handle for ethernet@%llx "
+		       "(%s)\n", addr, fdt_strerror(ret));
 	}
 }
 
 void fdt_fixup_board_enet(void *fdt)
 {
-	int i;
-
-	/*
-	 * P4080DS can be configured in many different ways, supporting a number
-	 * of combinations of ethernet devices and phy types.  In order to
-	 * have just one device tree for all of those configurations, we fix up
-	 * the tree here.  By default, the device tree configures FM1 and FM2
-	 * for SGMII, and configures XAUI on both 10G interfaces.  So we have
-	 * a number of different variables to track:
-	 *
-	 * 1) Whether the device is configured at all.  Whichever devices are
-	 *    not enabled should be disabled by setting the "status" property
-	 *    to "disabled".
-	 * 2) What the PHY interface is.  If this is an RGMII connection,
-	 *    we should change the "phy-connection-type" property to
-	 *    "rgmii"
-	 * 3) Which PHY is being used.  Because the MDIO buses are muxed,
-	 *    we need to redirect the "phy-handle" property to point at the
-	 *    PHY on the right slot/bus.
-	 */
-
-	/* We've got six MDIO nodes that may or may not need to exist */
-	fdt_status_disabled_by_alias(fdt, "emi1_slot3");
-	fdt_status_disabled_by_alias(fdt, "emi1_slot4");
-	fdt_status_disabled_by_alias(fdt, "emi1_slot5");
-	fdt_status_disabled_by_alias(fdt, "emi2_slot4");
-	fdt_status_disabled_by_alias(fdt, "emi2_slot5");
+	enum fm_port i;
+	int ret;
 
 	for (i = 0; i < NUM_FM_PORTS; i++) {
+		const char *alias;
+
 		switch (mdio_mux[i]) {
+		case EMI1_RGMII:
+			alias = "emi1_rgmii";
+			break;
 		case EMI1_SLOT3:
-			fdt_status_okay_by_alias(fdt, "emi1_slot3");
+			alias = "emi1_slot3";
 			break;
 		case EMI1_SLOT4:
-			fdt_status_okay_by_alias(fdt, "emi1_slot4");
+			alias = "emi1_slot4";
 			break;
 		case EMI1_SLOT5:
-			fdt_status_okay_by_alias(fdt, "emi1_slot5");
+			alias = "emi1_slot5";
 			break;
 		case EMI2_SLOT4:
-			fdt_status_okay_by_alias(fdt, "emi2_slot4");
+			alias = "emi2_slot4";
 			break;
 		case EMI2_SLOT5:
-			fdt_status_okay_by_alias(fdt, "emi2_slot5");
+			alias = "emi2_slot5";
 			break;
+		default:
+			continue;
+		}
+
+		debug("Enabling %s mdio-mux node for port %i\n", alias, i);
+		ret = fdt_status_okay_by_alias(fdt, alias);
+		if (ret < 0) {
+			printf("Fman: could not enable mdio-mux node %s (%s)\n",
+			       alias, fdt_strerror(ret));
 		}
 	}
 }
 
+/*
+ * Mapping of SerDes protocol to slots and SGMII card ports
+ *
+ *       EMI1         EMI2
+ * Slot  Mux Value    Mux Value
+ *  3     0b10
+ *  4     0b01         0b01
+ *  5     0b11         0b11
+ *
+ * Slot  Phy Addr
+ *  .1    0x1c
+ *  .2    0x1d
+ *  .3    0x1e
+ *  .4    0x1f
+ *
+ * Fman 1:
+ *       |  DTSEC1   |  DTSEC2  |  DTSEC3  |  DTSEC4  |  TGEC
+ * 0x02  |           |          |          |          |   5
+ * 0x05  |           |          |          |          |   5
+ * 0x08  |           |          |          |          |   5
+ * 0x0d  |           |          |          |          |   5
+ * 0x0e  |           |          |          |          |   5
+ * 0x0f  |           |          |          |          |
+ * 0x10  |           |          |          |          |
+ * 0x13  |           |          |          |          |   5
+ * 0x16  |   5.1     |   5.2    |   5.3    |   5.4    |
+ * 0x19  |   5.1     |   5.2    |   5.3    |   5.4    |
+ * 0x1d  |           |          |          |          |   5
+ * 0x22  |           |          |          |          |   5
+ * 0x25  |           |          |          |          |   5
+ *
+ * Fman 2:
+ *       |  DTSEC1   |  DTSEC2  |  DTSEC3  |  DTSEC4  |  TGEC
+ * 0x02  |           |          |          |          |   4
+ * 0x05  |           |          |          |          |   4
+ * 0x08  |           |          |          |          |   4
+ * 0x0d  |           |          |   3.3    |   3.4    |   4
+ * 0x0e  |           |          |   3.3    |   3.4    |   4
+ * 0x0f  |   3.1     |   3.2    |   3.3    |   3.4    |   4
+ * 0x10  |   3.1     |   3.2    |   3.3    |   3.4    |   4
+ * 0x13  |           |          |          |          |   4
+ * 0x16  |   4.1     |   4.2    |   4.3    |   4.4    |
+ * 0x19  |           |          |          |          |
+ * 0x1d  |           |          |          |          |   4
+ * 0x22  |           |          |          |          |   4
+ * 0x25  |           |          |          |          |   4
+ */
+
 int board_eth_init(bd_t *bis)
 {
 #ifdef CONFIG_FMAN_ENET