[U-Boot] [PATCH v2 0/4] SGMII support for MPC8378E-MDS boards

Hi all,
Here are the updated patches.
v2: - Addressed Andy Fleming's comments. Now we don't need the exported tsec_info struct.
Thanks,

MPC837xE specs says that SerDes1 has:
— Two lanes running x1 SGMII at 1.25 Gbps; — Two lanes running x1 SATA at 1.5 or 3.0 Gbps.
And for SerDes2:
— Two lanes running x1 PCI Express at 2.5 Gbps; — One lane running x2 PCI Express at 2.5 Gbps; — Two lanes running x1 SATA at 1.5 or 3.0 Gbps.
The spec also explicitly states that PEX options are not valid for the SD1.
Nevertheless MPC8378 RDB and MDS boards configure the SD1 for PEX, which is wrong to do.
Signed-off-by: Anton Vorontsov avorontsov@ru.mvista.com --- board/freescale/mpc837xemds/mpc837xemds.c | 2 +- board/freescale/mpc837xerdb/mpc837xerdb.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/board/freescale/mpc837xemds/mpc837xemds.c b/board/freescale/mpc837xemds/mpc837xemds.c index 40f1e63..581397d 100644 --- a/board/freescale/mpc837xemds/mpc837xemds.c +++ b/board/freescale/mpc837xemds/mpc837xemds.c @@ -44,7 +44,7 @@ int board_early_init_f(void) FSL_SERDES_CLK_100, FSL_SERDES_VDD_1V); break; case SPR_8378: - fsl_setup_serdes(CONFIG_FSL_SERDES1, FSL_SERDES_PROTO_PEX, + fsl_setup_serdes(CONFIG_FSL_SERDES2, FSL_SERDES_PROTO_PEX, FSL_SERDES_CLK_100, FSL_SERDES_VDD_1V); break; case SPR_8379: diff --git a/board/freescale/mpc837xerdb/mpc837xerdb.c b/board/freescale/mpc837xerdb/mpc837xerdb.c index aaefc18..3eb53d8 100644 --- a/board/freescale/mpc837xerdb/mpc837xerdb.c +++ b/board/freescale/mpc837xerdb/mpc837xerdb.c @@ -148,7 +148,7 @@ int board_early_init_f(void) FSL_SERDES_CLK_100, FSL_SERDES_VDD_1V); break; case SPR_8378: - fsl_setup_serdes(CONFIG_FSL_SERDES1, FSL_SERDES_PROTO_PEX, + fsl_setup_serdes(CONFIG_FSL_SERDES2, FSL_SERDES_PROTO_PEX, FSL_SERDES_CLK_100, FSL_SERDES_VDD_1V); break; case SPR_8379:

The rfcks should be shifted by 28 bits left. We didn't notice the bug because we were using only 100MHz clocks (for which rfcks == 0).
Though, for SGMII we'll need 125MHz clocks.
Signed-off-by: Anton Vorontsov avorontsov@ru.mvista.com --- cpu/mpc83xx/serdes.c | 2 +- include/asm-ppc/fsl_serdes.h | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/cpu/mpc83xx/serdes.c b/cpu/mpc83xx/serdes.c index 020c4c8..d1e0c97 100644 --- a/cpu/mpc83xx/serdes.c +++ b/cpu/mpc83xx/serdes.c @@ -42,7 +42,7 @@ #define FSL_SRDSRSTCTL_RST 0x80000000 #define FSL_SRDSRSTCTL_SATA_RESET 0xf
-void fsl_setup_serdes(u32 offset, char proto, char rfcks, char vdd) +void fsl_setup_serdes(u32 offset, char proto, u32 rfcks, char vdd) { void *regs = (void *)CFG_IMMR + offset; u32 tmp; diff --git a/include/asm-ppc/fsl_serdes.h b/include/asm-ppc/fsl_serdes.h index 733f919..6da4b6f 100644 --- a/include/asm-ppc/fsl_serdes.h +++ b/include/asm-ppc/fsl_serdes.h @@ -3,9 +3,9 @@
#include <config.h>
-#define FSL_SERDES_CLK_100 0 -#define FSL_SERDES_CLK_125 1 -#define FSL_SERDES_CLK_150 3 +#define FSL_SERDES_CLK_100 (0 << 28) +#define FSL_SERDES_CLK_125 (1 << 28) +#define FSL_SERDES_CLK_150 (3 << 28) #define FSL_SERDES_PROTO_SATA 0 #define FSL_SERDES_PROTO_PEX 1 #define FSL_SERDES_PROTO_PEX_X2 2 @@ -13,9 +13,9 @@ #define FSL_SERDES_VDD_1V 1
#ifdef CONFIG_FSL_SERDES -extern void fsl_setup_serdes(u32 offset, char proto, char rfcks, char vdd); +extern void fsl_setup_serdes(u32 offset, char proto, u32 rfcks, char vdd); #else -static void fsl_setup_serdes(u32 offset, char proto, char rfcks, char vdd) {} +static void fsl_setup_serdes(u32 offset, char proto, u32 rfcks, char vdd) {} #endif /* CONFIG_FSL_SERDES */
#endif /* __FSL_SERDES_H */

We'll use these masks to parse TSEC modes out of HRCWH.
Signed-off-by: Anton Vorontsov avorontsov@ru.mvista.com --- include/mpc83xx.h | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/include/mpc83xx.h b/include/mpc83xx.h index 5d82bb4..ee38191 100644 --- a/include/mpc83xx.h +++ b/include/mpc83xx.h @@ -544,12 +544,14 @@ #define HRCWH_RL_EXT_LEGACY 0x00000000 #define HRCWH_RL_EXT_NAND 0x00040000
+#define HRCWH_TSEC1M_MASK 0x0000E000 #define HRCWH_TSEC1M_IN_MII 0x00000000 #define HRCWH_TSEC1M_IN_RMII 0x00002000 #define HRCWH_TSEC1M_IN_RGMII 0x00006000 #define HRCWH_TSEC1M_IN_RTBI 0x0000A000 #define HRCWH_TSEC1M_IN_SGMII 0x0000C000
+#define HRCWH_TSEC2M_MASK 0x00001C00 #define HRCWH_TSEC2M_IN_MII 0x00000000 #define HRCWH_TSEC2M_IN_RMII 0x00000400 #define HRCWH_TSEC2M_IN_RGMII 0x00000C00

This involves configuring the SerDes and fixing up the flags and PHY addresses for the TSECs.
For Linux we also fix up the device tree.
Signed-off-by: Anton Vorontsov avorontsov@ru.mvista.com --- board/freescale/mpc837xemds/mpc837xemds.c | 123 +++++++++++++++++++++++++++++ include/configs/MPC837XEMDS.h | 2 + 2 files changed, 125 insertions(+), 0 deletions(-)
diff --git a/board/freescale/mpc837xemds/mpc837xemds.c b/board/freescale/mpc837xemds/mpc837xemds.c index 581397d..b6b9678 100644 --- a/board/freescale/mpc837xemds/mpc837xemds.c +++ b/board/freescale/mpc837xemds/mpc837xemds.c @@ -15,6 +15,7 @@ #include <asm/io.h> #include <asm/fsl_serdes.h> #include <spd_sdram.h> +#include <tsec.h> #if defined(CONFIG_OF_LIBFDT) #include <libfdt.h> #endif @@ -44,6 +45,8 @@ int board_early_init_f(void) FSL_SERDES_CLK_100, FSL_SERDES_VDD_1V); break; case SPR_8378: + fsl_setup_serdes(CONFIG_FSL_SERDES1, FSL_SERDES_PROTO_SGMII, + FSL_SERDES_CLK_125, FSL_SERDES_VDD_1V); fsl_setup_serdes(CONFIG_FSL_SERDES2, FSL_SERDES_PROTO_PEX, FSL_SERDES_CLK_100, FSL_SERDES_VDD_1V); break; @@ -62,6 +65,125 @@ int board_early_init_f(void) return 0; }
+#if defined(CONFIG_TSEC1) || defined(CONFIG_TSEC2) +int board_eth_init(bd_t *bd) +{ + struct tsec_info_struct tsec_info[2]; + struct immap __iomem *im = (struct immap __iomem *)CFG_IMMR; + u32 rcwh = in_be32(&im->reset.rcwh); + u32 tsec_mode; + int num = 0; + + /* New line after Net: */ + printf("\n"); + +#ifdef CONFIG_TSEC1 + SET_STD_TSEC_INFO(tsec_info[num], 1); + + printf(CONFIG_TSEC1_NAME ": "); + + tsec_mode = rcwh & HRCWH_TSEC1M_MASK; + if (tsec_mode == HRCWH_TSEC1M_IN_RGMII) { + printf("RGMII\n"); + /* this is default, no need to fixup */ + } else if (tsec_mode == HRCWH_TSEC1M_IN_SGMII) { + printf("SGMII\n"); + tsec_info[num].phyaddr = TSEC1_PHY_ADDR_SGMII; + tsec_info[num].flags = TSEC_GIGABIT; + } else { + printf("unsupported PHY type\n"); + } + num++; +#endif +#ifdef CONFIG_TSEC2 + SET_STD_TSEC_INFO(tsec_info[num], 2); + + printf(CONFIG_TSEC2_NAME ": "); + + tsec_mode = rcwh & HRCWH_TSEC2M_MASK; + if (tsec_mode == HRCWH_TSEC2M_IN_RGMII) { + printf("RGMII\n"); + /* this is default, no need to fixup */ + } else if (tsec_mode == HRCWH_TSEC2M_IN_SGMII) { + printf("SGMII\n"); + tsec_info[num].phyaddr = TSEC2_PHY_ADDR_SGMII; + tsec_info[num].flags = TSEC_GIGABIT; + } else { + printf("unsupported PHY type\n"); + } + num++; +#endif + return tsec_eth_init(bd, tsec_info, num); +} + +static void __ft_tsec_fixup(void *blob, bd_t *bd, const char *alias, + int phy_addr) +{ + const char *phy_type = "sgmii"; + const u32 *ph; + int off; + int err; + + off = fdt_path_offset(blob, alias); + if (off < 0) { + printf("WARNING: could not find %s alias: %s.\n", alias, + fdt_strerror(off)); + return; + } + + err = fdt_setprop(blob, off, "phy-connection-type", phy_type, + strlen(phy_type) + 1); + if (err) { + printf("WARNING: could not set phy-connection-type for %s: " + "%s.\n", alias, fdt_strerror(err)); + return; + } + + ph = (u32 *)fdt_getprop(blob, off, "phy-handle", 0); + if (!ph) { + printf("WARNING: could not get phy-handle for %s.\n", + alias); + return; + } + + off = fdt_node_offset_by_phandle(blob, *ph); + if (off < 0) { + printf("WARNING: could not get phy node for %s: %s\n", alias, + fdt_strerror(off)); + return; + } + + phy_addr = cpu_to_fdt32(phy_addr); + err = fdt_setprop(blob, off, "reg", &phy_addr, sizeof(phy_addr)); + if (err < 0) { + printf("WARNING: could not set phy node's reg for %s: " + "%s.\n", alias, fdt_strerror(err)); + return; + } +} + +static void ft_tsec_fixup(void *blob, bd_t *bd) +{ + struct immap __iomem *im = (struct immap __iomem *)CFG_IMMR; + u32 rcwh = in_be32(&im->reset.rcwh); + u32 tsec_mode; + +#ifdef CONFIG_TSEC1 + tsec_mode = rcwh & HRCWH_TSEC1M_MASK; + if (tsec_mode == HRCWH_TSEC1M_IN_SGMII) + __ft_tsec_fixup(blob, bd, "ethernet0", TSEC1_PHY_ADDR_SGMII); +#endif + +#ifdef CONFIG_TSEC2 + tsec_mode = rcwh & HRCWH_TSEC2M_MASK; + if (tsec_mode == HRCWH_TSEC2M_IN_SGMII) + __ft_tsec_fixup(blob, bd, "ethernet1", TSEC2_PHY_ADDR_SGMII); +#endif +} +#else +static inline void ft_tsec_fixup(void *blob, bd_t *bd) {} +#endif /* defined(CONFIG_TSEC1) || defined(CONFIG_TSEC2) */ + int board_early_init_r(void) { #ifdef CONFIG_PQ_MDS_PIB @@ -152,6 +274,7 @@ int checkboard(void) void ft_board_setup(void *blob, bd_t *bd) { ft_cpu_setup(blob, bd); + ft_tsec_fixup(blob, bd); #ifdef CONFIG_PCI ft_pci_setup(blob, bd); #endif diff --git a/include/configs/MPC837XEMDS.h b/include/configs/MPC837XEMDS.h index 7c87388..ed70b9e 100644 --- a/include/configs/MPC837XEMDS.h +++ b/include/configs/MPC837XEMDS.h @@ -381,6 +381,8 @@ #define CONFIG_TSEC2_NAME "eTSEC1" #define TSEC1_PHY_ADDR 2 #define TSEC2_PHY_ADDR 3 +#define TSEC1_PHY_ADDR_SGMII 8 +#define TSEC2_PHY_ADDR_SGMII 4 #define TSEC1_PHYIDX 0 #define TSEC2_PHYIDX 0 #define TSEC1_FLAGS (TSEC_GIGABIT | TSEC_REDUCED)

On Thu, 2 Oct 2008 18:31:17 +0400 Anton Vorontsov avorontsov@ru.mvista.com wrote:
Hi all,
Here are the updated patches.
v2:
- Addressed Andy Fleming's comments. Now we don't need the exported tsec_info struct.
applied 1-4 to mpc83xx/next.
Thanks,
Kim
participants (2)
-
Anton Vorontsov
-
Kim Phillips