[U-Boot] [PATCH 1/6] powerpc/85xx: add support for FM2 DTSEC5

Unlike previous SOCs, the Freescale P5040 has a fifth DTSEC on the second Fman, so add the Fman and SerDes macros for that DTSEC.
Signed-off-by: Timur Tabi timur@freescale.com --- arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c | 6 ++++++ arch/powerpc/include/asm/fsl_serdes.h | 1 + arch/powerpc/include/asm/immap_85xx.h | 1 + drivers/net/fm/init.c | 3 +++ include/fm_eth.h | 1 + 5 files changed, 12 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c b/arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c index 4b52dad..8aac1de 100644 --- a/arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c +++ b/arch/powerpc/cpu/mpc85xx/fsl_corenet_serdes.c @@ -68,6 +68,7 @@ static const char *serdes_prtcl_str[] = { [SGMII_FM2_DTSEC2] = "SGMII_FM2_DTSEC2", [SGMII_FM2_DTSEC3] = "SGMII_FM2_DTSEC3", [SGMII_FM2_DTSEC4] = "SGMII_FM2_DTSEC4", + [SGMII_FM2_DTSEC5] = "SGMII_FM2_DTSEC5", [XAUI_FM1] = "XAUI_FM1", [XAUI_FM2] = "XAUI_FM2", [AURORA] = "DEBUG", @@ -658,6 +659,7 @@ void fsl_serdes_init(void) case SGMII_FM2_DTSEC2: case SGMII_FM2_DTSEC3: case SGMII_FM2_DTSEC4: + case SGMII_FM2_DTSEC5: case XAUI_FM1: case XAUI_FM2: case SRIO1: @@ -717,6 +719,10 @@ void fsl_serdes_init(void) serdes8_devdisr2 |= FSL_CORENET_DEVDISR2_FM2 | FSL_CORENET_DEVDISR2_DTSEC2_4; break; + case SGMII_FM2_DTSEC5: + serdes8_devdisr2 |= FSL_CORENET_DEVDISR2_FM2 | + FSL_CORENET_DEVDISR2_DTSEC2_5; + break; case XAUI_FM1: serdes8_devdisr2 |= FSL_CORENET_DEVDISR2_FM1 | FSL_CORENET_DEVDISR2_10GEC1; diff --git a/arch/powerpc/include/asm/fsl_serdes.h b/arch/powerpc/include/asm/fsl_serdes.h index 0f31af1..22525f1 100644 --- a/arch/powerpc/include/asm/fsl_serdes.h +++ b/arch/powerpc/include/asm/fsl_serdes.h @@ -41,6 +41,7 @@ enum srds_prtcl { SGMII_FM2_DTSEC2, SGMII_FM2_DTSEC3, SGMII_FM2_DTSEC4, + SGMII_FM2_DTSEC5, SGMII_TSEC1, SGMII_TSEC2, SGMII_TSEC3, diff --git a/arch/powerpc/include/asm/immap_85xx.h b/arch/powerpc/include/asm/immap_85xx.h index 53d563e..42dd89c 100644 --- a/arch/powerpc/include/asm/immap_85xx.h +++ b/arch/powerpc/include/asm/immap_85xx.h @@ -1729,6 +1729,7 @@ typedef struct ccsr_gur { #define FSL_CORENET_DEVDISR2_DTSEC2_2 0x00004000 #define FSL_CORENET_DEVDISR2_DTSEC2_3 0x00002000 #define FSL_CORENET_DEVDISR2_DTSEC2_4 0x00001000 +#define FSL_CORENET_DEVDISR2_DTSEC2_5 0x00000800 #define FSL_CORENET_NUM_DEVDISR 2 u8 res7[8]; u32 powmgtcsr; /* Power management status & control */ diff --git a/drivers/net/fm/init.c b/drivers/net/fm/init.c index 953c359..9834cd9 100644 --- a/drivers/net/fm/init.c +++ b/drivers/net/fm/init.c @@ -50,6 +50,9 @@ struct fm_eth_info fm_info[] = { #if (CONFIG_SYS_NUM_FM2_DTSEC >= 4) FM_DTSEC_INFO_INITIALIZER(2, 4), #endif +#if (CONFIG_SYS_NUM_FM2_DTSEC >= 5) + FM_DTSEC_INFO_INITIALIZER(2, 5), +#endif #if (CONFIG_SYS_NUM_FM1_10GEC >= 1) FM_TGEC_INFO_INITIALIZER(1, 1), #endif diff --git a/include/fm_eth.h b/include/fm_eth.h index c7c6882..05121ea 100644 --- a/include/fm_eth.h +++ b/include/fm_eth.h @@ -35,6 +35,7 @@ enum fm_port { FM2_DTSEC2, FM2_DTSEC3, FM2_DTSEC4, + FM2_DTSEC5, FM2_10GEC1, NUM_FM_PORTS, };

Function fm_info_get_phy_address() returns the PHY address for a given Fman port. This is handy when the MDIO code needs to fixup the Ethernet nodes in the device tree to point to PHY nodes for a specific PHY address.
Signed-off-by: Timur Tabi timur@freescale.com --- drivers/net/fm/init.c | 16 ++++++++++++++++ include/fm_eth.h | 1 + 2 files changed, 17 insertions(+), 0 deletions(-)
diff --git a/drivers/net/fm/init.c b/drivers/net/fm/init.c index 9834cd9..8a5311c 100644 --- a/drivers/net/fm/init.c +++ b/drivers/net/fm/init.c @@ -155,6 +155,22 @@ void fm_info_set_phy_address(enum fm_port port, int address) }
/* + * Returns the PHY address for a given Fman port + * + * The port must be set via a prior call to fm_info_set_phy_address(). + * A negative error code is returned if the port is invalid. + */ +int fm_info_get_phy_address(enum fm_port port) +{ + int i = fm_port_to_index(port); + + if (i == -1) + return -1; + + return fm_info[i].phy_addr; +} + +/* * Returns the type of the data interface between the given MAC and its PHY. * This is typically determined by the RCW. */ diff --git a/include/fm_eth.h b/include/fm_eth.h index 05121ea..e56541d 100644 --- a/include/fm_eth.h +++ b/include/fm_eth.h @@ -110,6 +110,7 @@ void fman_enet_init(void); void fdt_fixup_fman_ethernet(void *fdt); phy_interface_t fm_info_get_enet_if(enum fm_port port); void fm_info_set_phy_address(enum fm_port port, int address); +int fm_info_get_phy_address(enum fm_port port); void fm_info_set_mdio(enum fm_port port, struct mii_dev *bus); void fm_disable_port(enum fm_port port);

In order to figure out which SerDes lane a given Fman port is connected to, we need a function that maps the fm_port namespace to the srds_prtcl namespace.
Signed-off-by: Timur Tabi timur@freescale.com --- board/freescale/common/fman.c | 40 ++++++++++++++++++++++++++++++++++++++++ board/freescale/common/fman.h | 2 ++ 2 files changed, 42 insertions(+), 0 deletions(-)
diff --git a/board/freescale/common/fman.c b/board/freescale/common/fman.c index 6ddf816..58b7c44 100644 --- a/board/freescale/common/fman.c +++ b/board/freescale/common/fman.c @@ -25,6 +25,9 @@ #include <libfdt_env.h> #include <fdt_support.h>
+#include <fm_eth.h> +#include <asm/fsl_serdes.h> + /* * Given the following ... * @@ -67,3 +70,40 @@ int fdt_set_phy_handle(void *fdt, char *compat, phys_addr_t addr,
return fdt_setprop(fdt, offset, "phy-handle", &ph, sizeof(ph)); } + +/* + * Return the SerDes device enum for a given Fman port + * + * This function just maps the fm_port namespace to the srds_prtcl namespace. + */ +enum srds_prtcl serdes_device_from_fm_port(enum fm_port port) +{ + switch (port) { + case FM1_DTSEC1: + return SGMII_FM1_DTSEC1; + case FM1_DTSEC2: + return SGMII_FM1_DTSEC2; + case FM1_DTSEC3: + return SGMII_FM1_DTSEC3; + case FM1_DTSEC4: + return SGMII_FM1_DTSEC4; + case FM1_DTSEC5: + return SGMII_FM1_DTSEC5; + case FM1_10GEC1: + return XAUI_FM1; + case FM2_DTSEC1: + return SGMII_FM2_DTSEC1; + case FM2_DTSEC2: + return SGMII_FM2_DTSEC2; + case FM2_DTSEC3: + return SGMII_FM2_DTSEC3; + case FM2_DTSEC4: + return SGMII_FM2_DTSEC4; + case FM2_DTSEC5: + return SGMII_FM2_DTSEC5; + case FM2_10GEC1: + return XAUI_FM2; + default: + return NONE; + } +} diff --git a/board/freescale/common/fman.h b/board/freescale/common/fman.h index d39ef08..734b1da 100644 --- a/board/freescale/common/fman.h +++ b/board/freescale/common/fman.h @@ -23,4 +23,6 @@ int fdt_set_phy_handle(void *fdt, char *compat, phys_addr_t addr, const char *alias);
+enum srds_prtcl serdes_device_from_fm_port(enum fm_port port); + #endif

please don't post patches upstream with '[u-boot-release]' in the subject.
On Fri, 10 Aug 2012 17:01:33 -0500 Timur Tabi timur@freescale.com wrote:
+enum srds_prtcl serdes_device_from_fm_port(enum fm_port port) +{
- switch (port) {
- case FM1_DTSEC1:
return SGMII_FM1_DTSEC1;
- case FM1_DTSEC2:
return SGMII_FM1_DTSEC2;
- case FM1_DTSEC3:
return SGMII_FM1_DTSEC3;
- case FM1_DTSEC4:
return SGMII_FM1_DTSEC4;
- case FM1_DTSEC5:
return SGMII_FM1_DTSEC5;
- case FM1_10GEC1:
return XAUI_FM1;
- case FM2_DTSEC1:
return SGMII_FM2_DTSEC1;
- case FM2_DTSEC2:
return SGMII_FM2_DTSEC2;
- case FM2_DTSEC3:
return SGMII_FM2_DTSEC3;
- case FM2_DTSEC4:
return SGMII_FM2_DTSEC4;
- case FM2_DTSEC5:
return SGMII_FM2_DTSEC5;
- case FM2_10GEC1:
return XAUI_FM2;
- default:
return NONE;
- }
+}
shouldn't this be a static const array lookup?
Kim

Kim Phillips wrote:
please don't post patches upstream with '[u-boot-release]' in the subject.
I didn't.
http://lists.denx.de/pipermail/u-boot/2012-August/130618.html
Your mailer is confused. I bcc the u-boot-release mailing list, and I presume your mailer (or our mail server) sent you that copy of the mail instead of the "real" one.
shouldn't this be a static const array lookup?
The compiler should convert it into an array lookup automatically, but I can change it if you insist. Since I don't like writing code that depends on the values of an enum, the array will look like this:
static const enum srds_prtcl srds_table[] = { [FM1_DTSEC1] = SGMII_FM1_DTSEC1, [FM1_DTSEC2] = SGMII_FM1_DTSEC2, [FM1_DTSEC3] = SGMII_FM1_DTSEC3, [FM1_DTSEC4] = SGMII_FM1_DTSEC4, [FM1_DTSEC5] = SGMII_FM1_DTSEC5, [FM1_10GEC1] = XAUI_FM1, [FM2_DTSEC1] = SGMII_FM2_DTSEC1, [FM2_DTSEC2] = SGMII_FM2_DTSEC2, [FM2_DTSEC3] = SGMII_FM2_DTSEC3, [FM2_DTSEC4] = SGMII_FM2_DTSEC4, [FM2_DTSEC5] = SGMII_FM2_DTSEC5, [FM2_10GEC1] = XAUI_FM2, };
if ((port < FM1_DTSEC1) || (port > FM2_10GEC1)) return NONE; else return srds_table[port];
I'm not sure that's an improvement.

On Mon, 13 Aug 2012 16:22:01 -0500 Timur Tabi timur@freescale.com wrote:
Kim Phillips wrote:
shouldn't this be a static const array lookup?
The compiler should convert it into an array lookup automatically, but I can change it if you insist. Since I don't like writing code that depends on the values of an enum, the array will look like this:
static const enum srds_prtcl srds_table[] = { [FM1_DTSEC1] = SGMII_FM1_DTSEC1, [FM1_DTSEC2] = SGMII_FM1_DTSEC2, [FM1_DTSEC3] = SGMII_FM1_DTSEC3, [FM1_DTSEC4] = SGMII_FM1_DTSEC4, [FM1_DTSEC5] = SGMII_FM1_DTSEC5, [FM1_10GEC1] = XAUI_FM1, [FM2_DTSEC1] = SGMII_FM2_DTSEC1, [FM2_DTSEC2] = SGMII_FM2_DTSEC2, [FM2_DTSEC3] = SGMII_FM2_DTSEC3, [FM2_DTSEC4] = SGMII_FM2_DTSEC4, [FM2_DTSEC5] = SGMII_FM2_DTSEC5, [FM2_10GEC1] = XAUI_FM2, };
if ((port < FM1_DTSEC1) || (port > FM2_10GEC1)) return NONE; else return srds_table[port];
I'm not sure that's an improvement.
it's ~30% less lines of code, and the maps lie on the same line, which helps when grepping.
Kim

We have a dedicated function for setting the node status now, so use it. Also improve a comment and fix the type of the phandle variable.
Signed-off-by: Timur Tabi timur@freescale.com --- drivers/net/fm/init.c | 11 +++++------ 1 files changed, 5 insertions(+), 6 deletions(-)
diff --git a/drivers/net/fm/init.c b/drivers/net/fm/init.c index 8a5311c..736b8b9 100644 --- a/drivers/net/fm/init.c +++ b/drivers/net/fm/init.c @@ -200,7 +200,8 @@ void board_ft_fman_fixup_port(void *blob, char * prop, phys_addr_t pa,
static void ft_fixup_port(void *blob, struct fm_eth_info *info, char *prop) { - int off, ph; + int off; + uint32_t ph; phys_addr_t paddr = CONFIG_SYS_CCSRBAR_PHYS + info->compat_offset; u64 dtsec1_addr = (u64)CONFIG_SYS_CCSRBAR_PHYS + CONFIG_SYS_FSL_FM1_DTSEC1_OFFSET; @@ -217,12 +218,10 @@ static void ft_fixup_port(void *blob, struct fm_eth_info *info, char *prop) off = fdt_node_offset_by_compat_reg(blob, prop, paddr);
/* Don't disable FM1-DTSEC1 MAC as its used for MDIO */ - if (paddr != dtsec1_addr) { - /* disable the mac node */ - fdt_setprop_string(blob, off, "status", "disabled"); - } + if (paddr != dtsec1_addr) + fdt_status_disabled(blob, off); /* disable the MAC node */
- /* disable the node point to the mac */ + /* disable the fsl,dpa-ethernet node that points to the MAC */ ph = fdt_get_phandle(blob, off); do_fixup_by_prop(blob, "fsl,fman-mac", &ph, sizeof(ph), "status", "disabled", strlen("disabled") + 1, 1);

enum board_slots contained six values, where SLOT1 == 1, SLOT2 == 2, and so on. This is pointless, so remove it. Also move the lane_to_slot[] array to the top of the file so that it can be used by other functions.
Signed-off-by: Timur Tabi timur@freescale.com --- board/freescale/corenet_ds/eth_p4080.c | 59 ++++++++++--------------------- 1 files changed, 19 insertions(+), 40 deletions(-)
diff --git a/board/freescale/corenet_ds/eth_p4080.c b/board/freescale/corenet_ds/eth_p4080.c index b87b092..2c69c51 100644 --- a/board/freescale/corenet_ds/eth_p4080.c +++ b/board/freescale/corenet_ds/eth_p4080.c @@ -68,6 +68,15 @@ static char *mdio_names[16] = { NULL, NULL, NULL, };
+/* + * Mapping of all 18 SERDES lanes to board slots. A value of '0' here means + * that the mapping must be determined dynamically, or that the lane maps to + * something other than a board slot. + */ +static u8 lane_to_slot[] = { + 1, 1, 2, 2, 3, 3, 3, 3, 6, 6, 4, 4, 4, 4, 5, 5, 5, 5 +}; + static char *p4080ds_mdio_name_for_muxval(u32 muxval) { return mdio_names[(muxval & EMI_MASK) >> 28]; @@ -290,15 +299,6 @@ void fdt_fixup_board_enet(void *fdt) } }
-enum board_slots { - SLOT1 = 1, - SLOT2, - SLOT3, - SLOT4, - SLOT5, - SLOT6, -}; - int board_eth_init(bd_t *bis) { #ifdef CONFIG_FMAN_ENET @@ -307,27 +307,6 @@ int board_eth_init(bd_t *bis) struct fsl_pq_mdio_info dtsec_mdio_info; struct tgec_mdio_info tgec_mdio_info;
- u8 lane_to_slot[] = { - SLOT1, /* 0 - Bank 1:A */ - SLOT1, /* 1 - Bank 1:B */ - SLOT2, /* 2 - Bank 1:C */ - SLOT2, /* 3 - Bank 1:D */ - SLOT3, /* 4 - Bank 1:E */ - SLOT3, /* 5 - Bank 1:F */ - SLOT3, /* 6 - Bank 1:G */ - SLOT3, /* 7 - Bank 1:H */ - SLOT6, /* 8 - Bank 1:I */ - SLOT6, /* 9 - Bank 1:J */ - SLOT4, /* 10 - Bank 2:A */ - SLOT4, /* 11 - Bank 2:B */ - SLOT4, /* 12 - Bank 2:C */ - SLOT4, /* 13 - Bank 2:D */ - SLOT5, /* 14 - Bank 3:A */ - SLOT5, /* 15 - Bank 3:B */ - SLOT5, /* 16 - Bank 3:C */ - SLOT5, /* 17 - Bank 3:D */ - }; - /* Initialize the mdio_mux array so we can recognize empty elements */ for (i = 0; i < NUM_FM_PORTS; i++) mdio_mux[i] = EMI_NONE; @@ -380,17 +359,17 @@ int board_eth_init(bd_t *bis) break; slot = lane_to_slot[lane]; switch (slot) { - case SLOT3: + case 3: mdio_mux[i] = EMI1_SLOT3; fm_info_set_mdio(i, mii_dev_for_muxval(mdio_mux[i])); break; - case SLOT4: + case 4: mdio_mux[i] = EMI1_SLOT4; fm_info_set_mdio(i, mii_dev_for_muxval(mdio_mux[i])); break; - case SLOT5: + case 5: mdio_mux[i] = EMI1_SLOT5; fm_info_set_mdio(i, mii_dev_for_muxval(mdio_mux[i])); @@ -417,12 +396,12 @@ int board_eth_init(bd_t *bis) break; slot = lane_to_slot[lane]; switch (slot) { - case SLOT4: + case 4: mdio_mux[i] = EMI2_SLOT4; fm_info_set_mdio(i, mii_dev_for_muxval(mdio_mux[i])); break; - case SLOT5: + case 5: mdio_mux[i] = EMI2_SLOT5; fm_info_set_mdio(i, mii_dev_for_muxval(mdio_mux[i])); @@ -444,17 +423,17 @@ int board_eth_init(bd_t *bis) break; slot = lane_to_slot[lane]; switch (slot) { - case SLOT3: + case 3: mdio_mux[i] = EMI1_SLOT3; fm_info_set_mdio(i, mii_dev_for_muxval(mdio_mux[i])); break; - case SLOT4: + case 4: mdio_mux[i] = EMI1_SLOT4; fm_info_set_mdio(i, mii_dev_for_muxval(mdio_mux[i])); break; - case SLOT5: + case 5: mdio_mux[i] = EMI1_SLOT5; fm_info_set_mdio(i, mii_dev_for_muxval(mdio_mux[i])); @@ -481,12 +460,12 @@ int board_eth_init(bd_t *bis) break; slot = lane_to_slot[lane]; switch (slot) { - case SLOT4: + case 4: mdio_mux[i] = EMI2_SLOT4; fm_info_set_mdio(i, mii_dev_for_muxval(mdio_mux[i])); break; - case SLOT5: + case 5: mdio_mux[i] = EMI2_SLOT5; fm_info_set_mdio(i, mii_dev_for_muxval(mdio_mux[i]));

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(-)
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
participants (2)
-
Kim Phillips
-
Timur Tabi