diff options
author | Ashish Kumar <Ashish.Kumar@nxp.com> | 2017-08-31 10:42:55 (GMT) |
---|---|---|
committer | York Sun <york.sun@nxp.com> | 2017-09-11 15:01:05 (GMT) |
commit | 7769776a603f76ab1b7c1478f6cf8388b3cb5464 (patch) | |
tree | ac709dd1fcb4185bb2ed865bb61c975be29e0ec0 /board/freescale | |
parent | e84a324ba7950e88c0df4a2c656f533c723aeaae (diff) | |
download | u-boot-7769776a603f76ab1b7c1478f6cf8388b3cb5464.tar.xz |
armv8: ls1088aqds: Add support of LS1088AQDS
This patch add support of LS1088AQDS platform.
The LS1088A QorIQTM Development System (QDS) is a high-performance
computing, evaluation, and development platform that supports the
LS1088A QorIQ Architecture processor.
Signed-off-by: Prabhakar Kushwaha <prabhakar.kushwaha@nxp.com>
Signed-off-by: Shaohui Xie <Shaohui.Xie@nxp.com>
Signed-off-by: Ashish Kumar <Ashish.Kumar@nxp.com>
Reviewed-by: York Sun <york.sun@nxp.com>
Diffstat (limited to 'board/freescale')
-rw-r--r-- | board/freescale/ls1088a/Kconfig | 16 | ||||
-rw-r--r-- | board/freescale/ls1088a/MAINTAINERS | 8 | ||||
-rw-r--r-- | board/freescale/ls1088a/Makefile | 1 | ||||
-rw-r--r-- | board/freescale/ls1088a/README | 79 | ||||
-rw-r--r-- | board/freescale/ls1088a/ddr.h | 5 | ||||
-rw-r--r-- | board/freescale/ls1088a/eth_ls1088aqds.c | 650 | ||||
-rw-r--r-- | board/freescale/ls1088a/ls1088a.c | 84 | ||||
-rw-r--r-- | board/freescale/ls1088a/ls1088a_qixis.h | 5 |
8 files changed, 843 insertions, 5 deletions
diff --git a/board/freescale/ls1088a/Kconfig b/board/freescale/ls1088a/Kconfig index a4d8223..1ada661 100644 --- a/board/freescale/ls1088a/Kconfig +++ b/board/freescale/ls1088a/Kconfig @@ -1,3 +1,19 @@ +if TARGET_LS1088AQDS + +config SYS_BOARD + default "ls1088a" + +config SYS_VENDOR + default "freescale" + +config SYS_SOC + default "fsl-layerscape" + +config SYS_CONFIG_NAME + default "ls1088aqds" + +endif + if TARGET_LS1088ARDB config SYS_BOARD diff --git a/board/freescale/ls1088a/MAINTAINERS b/board/freescale/ls1088a/MAINTAINERS index 12834f6..e1e6d4b 100644 --- a/board/freescale/ls1088a/MAINTAINERS +++ b/board/freescale/ls1088a/MAINTAINERS @@ -5,3 +5,11 @@ S: Maintained F: board/freescale/ls1088a/ F: include/configs/ls1088ardb.h F: configs/ls1088ardb_qspi_defconfig + +LS1088AQDS BOARD +M: Prabhakar Kushwaha <prabhakar.kushwaha@nxp.com> +M: Ashish Kumar <Ashish.Kumar@nxp.com> +S: Maintained +F: board/freescale/ls1088a/ +F: include/configs/ls1088aqds.h +F: configs/ls1088aqds_qspi_defconfig diff --git a/board/freescale/ls1088a/Makefile b/board/freescale/ls1088a/Makefile index e997cf1..bdcce9e 100644 --- a/board/freescale/ls1088a/Makefile +++ b/board/freescale/ls1088a/Makefile @@ -6,4 +6,5 @@ obj-y += ls1088a.o obj-$(CONFIG_TARGET_LS1088ARDB) += eth_ls1088ardb.o +obj-$(CONFIG_TARGET_LS1088AQDS) += eth_ls1088aqds.o obj-y += ddr.o diff --git a/board/freescale/ls1088a/README b/board/freescale/ls1088a/README index 3f4d987..aa0fb6a 100644 --- a/board/freescale/ls1088a/README +++ b/board/freescale/ls1088a/README @@ -64,3 +64,82 @@ Alternately you can use this command to switch from QSPI to SD - JTAG support - QSPI emulator support - TDM riser support + +QDS Default Switch Settings (1: ON; 0: OFF) +------------------------------------------- + +For 16b IFC-NOR +SW1 0001 0010 +SW2 x110 1111 + +For QSPI Boot +SW1 0011 0001 +SW2 0110 1111 + +For SD Boot +SW1 0010 0000 +SW2 0110 1111 + +For eMMC Boot +SW1 0010 0000 +SW2 1110 1111 + +For I2C (ext. addr.) +SW1 0010 0100 +SW2 1110 1111 + +SW3 to SW12 are identical for all boot source + +SW3 0010 0100 +SW4 0010 0000 +SW5 1110 0111 +SW6 1110 1000 +SW7 0001 1101 +SW8 0000 1101 +SW9 1100 1010 +SW10 1110 1000 +SW11 1111 0100 +SW12 1111 1111 + + LS1088AQDS board Overview + ------------------------- + - SERDES Connections, 16 lanes supporting: + - PCI Express - 3.0 + - SATA 3.0 + - 2 XFI + - QSGMII, SGMII with help for Riser card + - 2 RGMII + - 5 slot for Riser card or PCIe NIC + - DDR Controller + - One ports of 72-bits (8-bits ECC, 64-bits DATA) DDR4. Each port supports four + chip-selects on one DIMM connector. Support is up to 2133MT/s, Although MAX default + with FSL refernce software is 2100MT/s + - 2 QSPI-NOR Spansion(S25FS512SDSMFI011) flash of size 64MB + - IFC/Local Bus + - One 2 GB NAND flash with ECC support, not as boot source + - CPLD of size 2K + - USB 3.0 + - Two high speed USB 3.0 ports + - First USB 3.0 port configured as Host with Type-A connector + - Second USB 3.0 port configured as OTG with micro-AB connector + - SDHC/eMMC + - SDHC/eMMC slot via adaptor + - 4 I2C controllers + - Two SATA onboard connectors + - 2 UART + - JTAG support + - DSPI + - PROMJET support + - QSPI emulator support + - TDM riser support + +QSPI flash memory map valid for both QDS and RDB + Image Flash Offset + RCW+PBI 0x00000000 + Boot firmware (U-Boot) 0x00100000 + Boot firmware Environment 0x00300000 + PPA firmware 0x00400000 + DPAA2 MC 0x00A00000 + DPAA2 DPL 0x00D00000 + DPAA2 DPC 0x00E00000 + Kernel.itb 0x01000000 diff --git a/board/freescale/ls1088a/ddr.h b/board/freescale/ls1088a/ddr.h index dfcfc1f..a1ad709 100644 --- a/board/freescale/ls1088a/ddr.h +++ b/board/freescale/ls1088a/ddr.h @@ -34,6 +34,11 @@ static const struct board_specific_parameters udimm0[] = { {2, 1900, 0, 4, 7, 0x09090B0D, 0x0E10120B,}, {2, 2300, 0, 8, 9, 0x0A0C0E11, 0x1214160F,}, {} +#elif defined(CONFIG_TARGET_LS1088AQDS) + {2, 1666, 0, 8, 8, 0x0A0A0C0E, 0x0F10110C,}, + {2, 1900, 0, 4, 7, 0x09090B0D, 0x0E10120B,}, + {2, 2300, 0, 4, 9, 0x0A0C0D11, 0x1214150E,}, + {} #endif }; diff --git a/board/freescale/ls1088a/eth_ls1088aqds.c b/board/freescale/ls1088a/eth_ls1088aqds.c new file mode 100644 index 0000000..a912ff7 --- /dev/null +++ b/board/freescale/ls1088a/eth_ls1088aqds.c @@ -0,0 +1,650 @@ +/* + * Copyright 2017 NXP + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <netdev.h> +#include <asm/io.h> +#include <asm/arch/fsl_serdes.h> +#include <hwconfig.h> +#include <fsl_mdio.h> +#include <malloc.h> +#include <fm_eth.h> +#include <i2c.h> +#include <miiphy.h> +#include <fsl-mc/ldpaa_wriop.h> + +#include "../common/qixis.h" + +#include "ls1088a_qixis.h" + +#define MC_BOOT_ENV_VAR "mcinitcmd" + +#ifdef CONFIG_FSL_MC_ENET + +#define SFP_TX 0 + + /* - In LS1088A A there are only 16 SERDES lanes, spread across 2 SERDES banks. + * Bank 1 -> Lanes A, B, C, D, + * Bank 2 -> Lanes A,B, C, D, + */ + + /* Mapping of 8 SERDES lanes to LS1088A QDS 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_fsm1[] = { + 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* On the Vitesse VSC8234XHG SGMII riser card there are 4 SGMII PHYs + * housed. + */ + +static int xqsgii_riser_phy_addr[] = { + XQSGMII_CARD_PHY1_PORT0_ADDR, + XQSGMII_CARD_PHY2_PORT0_ADDR, + XQSGMII_CARD_PHY3_PORT0_ADDR, + XQSGMII_CARD_PHY4_PORT0_ADDR, + XQSGMII_CARD_PHY3_PORT2_ADDR, + XQSGMII_CARD_PHY1_PORT2_ADDR, + XQSGMII_CARD_PHY4_PORT2_ADDR, + XQSGMII_CARD_PHY2_PORT2_ADDR, +}; + +static int sgmii_riser_phy_addr[] = { + SGMII_CARD_PORT1_PHY_ADDR, + SGMII_CARD_PORT2_PHY_ADDR, + SGMII_CARD_PORT3_PHY_ADDR, + SGMII_CARD_PORT4_PHY_ADDR, +}; + +/* Slot2 does not have EMI connections */ +#define EMI_NONE 0xFF +#define EMI1_RGMII1 0 +#define EMI1_RGMII2 1 +#define EMI1_SLOT1 2 + +static const char * const mdio_names[] = { + "LS1088A_QDS_MDIO0", + "LS1088A_QDS_MDIO1", + "LS1088A_QDS_MDIO2", + DEFAULT_WRIOP_MDIO2_NAME, +}; + +struct ls1088a_qds_mdio { + u8 muxval; + struct mii_dev *realbus; +}; + +static void sgmii_configure_repeater(int dpmac) +{ + struct mii_dev *bus; + uint8_t a = 0xf; + int i, j, ret; + unsigned short value; + const char *dev = "LS1088A_QDS_MDIO2"; + int i2c_addr[] = {0x58, 0x59, 0x5a, 0x5b}; + int i2c_phy_addr = 0; + int phy_addr = 0; + + uint8_t ch_a_eq[] = {0x1, 0x2, 0x3, 0x7}; + uint8_t ch_a_ctl2[] = {0x81, 0x82, 0x83, 0x84}; + uint8_t ch_b_eq[] = {0x1, 0x2, 0x3, 0x7}; + uint8_t ch_b_ctl2[] = {0x81, 0x82, 0x83, 0x84}; + + /* Set I2c to Slot 1 */ + i2c_write(0x77, 0, 0, &a, 1); + + switch (dpmac) { + case 1: + i2c_phy_addr = i2c_addr[1]; + phy_addr = 4; + break; + case 2: + i2c_phy_addr = i2c_addr[0]; + phy_addr = 0; + break; + case 3: + i2c_phy_addr = i2c_addr[3]; + phy_addr = 0xc; + break; + case 7: + i2c_phy_addr = i2c_addr[2]; + phy_addr = 8; + break; + } + + /* Check the PHY status */ + ret = miiphy_set_current_dev(dev); + if (ret > 0) + goto error; + + bus = mdio_get_current_dev(); + debug("Reading from bus %s\n", bus->name); + + ret = miiphy_write(dev, phy_addr, 0x1f, 3); + if (ret > 0) + goto error; + + mdelay(10); + ret = miiphy_read(dev, phy_addr, 0x11, &value); + if (ret > 0) + goto error; + + mdelay(10); + + if ((value & 0xfff) == 0x401) { + miiphy_write(dev, phy_addr, 0x1f, 0); + printf("DPMAC %d:PHY is ..... Configured\n", dpmac); + return; + } + + for (i = 0; i < 4; i++) { + for (j = 0; j < 4; j++) { + a = 0x18; + i2c_write(i2c_phy_addr, 6, 1, &a, 1); + a = 0x38; + i2c_write(i2c_phy_addr, 4, 1, &a, 1); + a = 0x4; + i2c_write(i2c_phy_addr, 8, 1, &a, 1); + + i2c_write(i2c_phy_addr, 0xf, 1, + &ch_a_eq[i], 1); + i2c_write(i2c_phy_addr, 0x11, 1, + &ch_a_ctl2[j], 1); + + i2c_write(i2c_phy_addr, 0x16, 1, + &ch_b_eq[i], 1); + i2c_write(i2c_phy_addr, 0x18, 1, + &ch_b_ctl2[j], 1); + + a = 0x14; + i2c_write(i2c_phy_addr, 0x23, 1, &a, 1); + a = 0xb5; + i2c_write(i2c_phy_addr, 0x2d, 1, &a, 1); + a = 0x20; + i2c_write(i2c_phy_addr, 4, 1, &a, 1); + mdelay(100); + ret = miiphy_read(dev, phy_addr, 0x11, &value); + if (ret > 0) + goto error; + + mdelay(100); + ret = miiphy_read(dev, phy_addr, 0x11, &value); + if (ret > 0) + goto error; + + if ((value & 0xfff) == 0x401) { + printf("DPMAC %d :PHY is configured ", + dpmac); + printf("after setting repeater 0x%x\n", + value); + i = 5; + j = 5; + } else { + printf("DPMAC %d :PHY is failed to ", + dpmac); + printf("configure the repeater 0x%x\n", value); + } + } + } + miiphy_write(dev, phy_addr, 0x1f, 0); +error: + if (ret) + printf("DPMAC %d ..... FAILED to configure PHY\n", dpmac); + return; +} + +static void qsgmii_configure_repeater(int dpmac) +{ + uint8_t a = 0xf; + int i, j; + int i2c_phy_addr = 0; + int phy_addr = 0; + int i2c_addr[] = {0x58, 0x59, 0x5a, 0x5b}; + + uint8_t ch_a_eq[] = {0x1, 0x2, 0x3, 0x7}; + uint8_t ch_a_ctl2[] = {0x81, 0x82, 0x83, 0x84}; + uint8_t ch_b_eq[] = {0x1, 0x2, 0x3, 0x7}; + uint8_t ch_b_ctl2[] = {0x81, 0x82, 0x83, 0x84}; + + const char *dev = mdio_names[EMI1_SLOT1]; + int ret = 0; + unsigned short value; + + /* Set I2c to Slot 1 */ + i2c_write(0x77, 0, 0, &a, 1); + + switch (dpmac) { + case 7: + case 8: + case 9: + case 10: + i2c_phy_addr = i2c_addr[2]; + phy_addr = 8; + break; + + case 3: + case 4: + case 5: + case 6: + i2c_phy_addr = i2c_addr[3]; + phy_addr = 0xc; + break; + } + + /* Check the PHY status */ + ret = miiphy_set_current_dev(dev); + ret = miiphy_write(dev, phy_addr, 0x1f, 3); + mdelay(10); + ret = miiphy_read(dev, phy_addr, 0x11, &value); + mdelay(10); + ret = miiphy_read(dev, phy_addr, 0x11, &value); + mdelay(10); + if ((value & 0xf) == 0xf) { + miiphy_write(dev, phy_addr, 0x1f, 0); + printf("DPMAC %d :PHY is ..... Configured\n", dpmac); + return; + } + + for (i = 0; i < 4; i++) { + for (j = 0; j < 4; j++) { + a = 0x18; + i2c_write(i2c_phy_addr, 6, 1, &a, 1); + a = 0x38; + i2c_write(i2c_phy_addr, 4, 1, &a, 1); + a = 0x4; + i2c_write(i2c_phy_addr, 8, 1, &a, 1); + + i2c_write(i2c_phy_addr, 0xf, 1, &ch_a_eq[i], 1); + i2c_write(i2c_phy_addr, 0x11, 1, &ch_a_ctl2[j], 1); + + i2c_write(i2c_phy_addr, 0x16, 1, &ch_b_eq[i], 1); + i2c_write(i2c_phy_addr, 0x18, 1, &ch_b_ctl2[j], 1); + + a = 0x14; + i2c_write(i2c_phy_addr, 0x23, 1, &a, 1); + a = 0xb5; + i2c_write(i2c_phy_addr, 0x2d, 1, &a, 1); + a = 0x20; + i2c_write(i2c_phy_addr, 4, 1, &a, 1); + mdelay(100); + ret = miiphy_read(dev, phy_addr, 0x11, &value); + if (ret > 0) + goto error; + mdelay(1); + ret = miiphy_read(dev, phy_addr, 0x11, &value); + if (ret > 0) + goto error; + mdelay(10); + if ((value & 0xf) == 0xf) { + miiphy_write(dev, phy_addr, 0x1f, 0); + printf("DPMAC %d :PHY is ..... Configured\n", + dpmac); + return; + } + } + } +error: + printf("DPMAC %d :PHY ..... FAILED to configure PHY\n", dpmac); + return; +} + +static const char *ls1088a_qds_mdio_name_for_muxval(u8 muxval) +{ + return mdio_names[muxval]; +} + +struct mii_dev *mii_dev_for_muxval(u8 muxval) +{ + struct mii_dev *bus; + const char *name = ls1088a_qds_mdio_name_for_muxval(muxval); + + if (!name) { + printf("No bus for muxval %x\n", muxval); + return NULL; + } + + bus = miiphy_get_dev_by_name(name); + + if (!bus) { + printf("No bus by name %s\n", name); + return NULL; + } + + return bus; +} + +static void ls1088a_qds_enable_SFP_TX(u8 muxval) +{ + u8 brdcfg9; + + brdcfg9 = QIXIS_READ(brdcfg[9]); + brdcfg9 &= ~BRDCFG9_SFPTX_MASK; + brdcfg9 |= (muxval << BRDCFG9_SFPTX_SHIFT); + QIXIS_WRITE(brdcfg[9], brdcfg9); +} + +static void ls1088a_qds_mux_mdio(u8 muxval) +{ + u8 brdcfg4; + + if (muxval <= 5) { + brdcfg4 = QIXIS_READ(brdcfg[4]); + brdcfg4 &= ~BRDCFG4_EMISEL_MASK; + brdcfg4 |= (muxval << BRDCFG4_EMISEL_SHIFT); + QIXIS_WRITE(brdcfg[4], brdcfg4); + } +} + +static int ls1088a_qds_mdio_read(struct mii_dev *bus, int addr, + int devad, int regnum) +{ + struct ls1088a_qds_mdio *priv = bus->priv; + + ls1088a_qds_mux_mdio(priv->muxval); + + return priv->realbus->read(priv->realbus, addr, devad, regnum); +} + +static int ls1088a_qds_mdio_write(struct mii_dev *bus, int addr, int devad, + int regnum, u16 value) +{ + struct ls1088a_qds_mdio *priv = bus->priv; + + ls1088a_qds_mux_mdio(priv->muxval); + + return priv->realbus->write(priv->realbus, addr, devad, regnum, value); +} + +static int ls1088a_qds_mdio_reset(struct mii_dev *bus) +{ + struct ls1088a_qds_mdio *priv = bus->priv; + + return priv->realbus->reset(priv->realbus); +} + +static int ls1088a_qds_mdio_init(char *realbusname, u8 muxval) +{ + struct ls1088a_qds_mdio *pmdio; + struct mii_dev *bus = mdio_alloc(); + + if (!bus) { + printf("Failed to allocate ls1088a_qds MDIO bus\n"); + return -1; + } + + pmdio = malloc(sizeof(*pmdio)); + if (!pmdio) { + printf("Failed to allocate ls1088a_qds private data\n"); + free(bus); + return -1; + } + + bus->read = ls1088a_qds_mdio_read; + bus->write = ls1088a_qds_mdio_write; + bus->reset = ls1088a_qds_mdio_reset; + sprintf(bus->name, ls1088a_qds_mdio_name_for_muxval(muxval)); + + pmdio->realbus = miiphy_get_dev_by_name(realbusname); + + if (!pmdio->realbus) { + printf("No bus with name %s\n", realbusname); + free(bus); + free(pmdio); + return -1; + } + + pmdio->muxval = muxval; + bus->priv = pmdio; + + return mdio_register(bus); +} + +/* + * Initialize the dpmac_info array. + * + */ +static void initialize_dpmac_to_slot(void) +{ + struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR; + u32 serdes1_prtcl, cfg; + + cfg = in_le32(&gur->rcwsr[FSL_CHASSIS3_SRDS1_REGSR - 1]) & + FSL_CHASSIS3_SRDS1_PRTCL_MASK; + cfg >>= FSL_CHASSIS3_SRDS1_PRTCL_SHIFT; + serdes1_prtcl = serdes_get_number(FSL_SRDS_1, cfg); + + switch (serdes1_prtcl) { + case 0x12: + printf("qds: WRIOP: Supported SerDes1 Protocol 0x%02x\n", + serdes1_prtcl); + lane_to_slot_fsm1[0] = EMI1_SLOT1 - 1; + lane_to_slot_fsm1[1] = EMI1_SLOT1 - 1; + lane_to_slot_fsm1[2] = EMI1_SLOT1 - 1; + lane_to_slot_fsm1[3] = EMI1_SLOT1 - 1; + break; + case 0x15: + case 0x1D: + printf("qds: WRIOP: Supported SerDes1 Protocol 0x%02x\n", + serdes1_prtcl); + lane_to_slot_fsm1[0] = EMI1_SLOT1 - 1; + lane_to_slot_fsm1[1] = EMI1_SLOT1 - 1; + lane_to_slot_fsm1[2] = EMI_NONE; + lane_to_slot_fsm1[3] = EMI_NONE; + break; + case 0x1E: + printf("qds: WRIOP: Supported SerDes1 Protocol 0x%02x\n", + serdes1_prtcl); + lane_to_slot_fsm1[0] = EMI1_SLOT1 - 1; + lane_to_slot_fsm1[1] = EMI1_SLOT1 - 1; + lane_to_slot_fsm1[2] = EMI1_SLOT1 - 1; + lane_to_slot_fsm1[3] = EMI_NONE; + break; + case 0x3A: + printf("qds: WRIOP: Supported SerDes1 Protocol 0x%02x\n", + serdes1_prtcl); + lane_to_slot_fsm1[0] = EMI1_SLOT1 - 1; + lane_to_slot_fsm1[1] = EMI_NONE; + lane_to_slot_fsm1[2] = EMI1_SLOT1 - 1; + lane_to_slot_fsm1[3] = EMI1_SLOT1 - 1; + break; + + default: + printf("%s qds: WRIOP: Unsupported SerDes1 Protocol 0x%02x\n", + __func__, serdes1_prtcl); + break; + } +} + +void ls1088a_handle_phy_interface_sgmii(int dpmac_id) +{ + struct mii_dev *bus; + struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR; + u32 serdes1_prtcl, cfg; + + cfg = in_le32(&gur->rcwsr[FSL_CHASSIS3_SRDS1_REGSR - 1]) & + FSL_CHASSIS3_SRDS1_PRTCL_MASK; + cfg >>= FSL_CHASSIS3_SRDS1_PRTCL_SHIFT; + serdes1_prtcl = serdes_get_number(FSL_SRDS_1, cfg); + + int *riser_phy_addr; + char *env_hwconfig = env_get("hwconfig"); + + if (hwconfig_f("xqsgmii", env_hwconfig)) + riser_phy_addr = &xqsgii_riser_phy_addr[0]; + else + riser_phy_addr = &sgmii_riser_phy_addr[0]; + + switch (serdes1_prtcl) { + case 0x12: + case 0x15: + case 0x1E: + case 0x3A: + switch (dpmac_id) { + case 1: + wriop_set_phy_address(dpmac_id, riser_phy_addr[1]); + break; + case 2: + wriop_set_phy_address(dpmac_id, riser_phy_addr[0]); + break; + case 3: + wriop_set_phy_address(dpmac_id, riser_phy_addr[3]); + break; + case 7: + wriop_set_phy_address(dpmac_id, riser_phy_addr[2]); + break; + default: + printf("WRIOP: Wrong DPMAC%d set to SGMII", dpmac_id); + break; + } + break; + default: + printf("%s qds: WRIOP: Unsupported SerDes1 Protocol 0x%02x\n", + __func__, serdes1_prtcl); + return; + } + dpmac_info[dpmac_id].board_mux = EMI1_SLOT1; + bus = mii_dev_for_muxval(EMI1_SLOT1); + wriop_set_mdio(dpmac_id, bus); +} + +void ls1088a_handle_phy_interface_qsgmii(int dpmac_id) +{ + struct mii_dev *bus; + struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR; + u32 serdes1_prtcl, cfg; + + cfg = in_le32(&gur->rcwsr[FSL_CHASSIS3_SRDS1_REGSR - 1]) & + FSL_CHASSIS3_SRDS1_PRTCL_MASK; + cfg >>= FSL_CHASSIS3_SRDS1_PRTCL_SHIFT; + serdes1_prtcl = serdes_get_number(FSL_SRDS_1, cfg); + + switch (serdes1_prtcl) { + case 0x1D: + case 0x1E: + switch (dpmac_id) { + case 3: + case 4: + case 5: + case 6: + wriop_set_phy_address(dpmac_id, dpmac_id + 9); + break; + case 7: + case 8: + case 9: + case 10: + wriop_set_phy_address(dpmac_id, dpmac_id + 1); + break; + } + + dpmac_info[dpmac_id].board_mux = EMI1_SLOT1; + bus = mii_dev_for_muxval(EMI1_SLOT1); + wriop_set_mdio(dpmac_id, bus); + break; + default: + printf("qds: WRIOP: Unsupported SerDes Protocol 0x%02x\n", + serdes1_prtcl); + break; + } +} + +void ls1088a_handle_phy_interface_xsgmii(int i) +{ + struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR; + u32 serdes1_prtcl, cfg; + + cfg = in_le32(&gur->rcwsr[FSL_CHASSIS3_SRDS1_REGSR - 1]) & + FSL_CHASSIS3_SRDS1_PRTCL_MASK; + cfg >>= FSL_CHASSIS3_SRDS1_PRTCL_SHIFT; + serdes1_prtcl = serdes_get_number(FSL_SRDS_1, cfg); + + switch (serdes1_prtcl) { + case 0x15: + case 0x1D: + case 0x1E: + wriop_set_phy_address(i, i + 26); + ls1088a_qds_enable_SFP_TX(SFP_TX); + break; + default: + printf("qds: WRIOP: Unsupported SerDes Protocol 0x%02x\n", + serdes1_prtcl); + break; + } +} +#endif + +int board_eth_init(bd_t *bis) +{ + int error = 0, i; + char *mc_boot_env_var; +#ifdef CONFIG_FSL_MC_ENET + struct memac_mdio_info *memac_mdio0_info; + char *env_hwconfig = env_get("hwconfig"); + + initialize_dpmac_to_slot(); + + memac_mdio0_info = (struct memac_mdio_info *)malloc( + sizeof(struct memac_mdio_info)); + memac_mdio0_info->regs = + (struct memac_mdio_controller *) + CONFIG_SYS_FSL_WRIOP1_MDIO1; + memac_mdio0_info->name = DEFAULT_WRIOP_MDIO1_NAME; + + /* Register the real MDIO1 bus */ + fm_memac_mdio_init(bis, memac_mdio0_info); + + /* Register the muxing front-ends to the MDIO buses */ + ls1088a_qds_mdio_init(DEFAULT_WRIOP_MDIO1_NAME, EMI1_RGMII1); + ls1088a_qds_mdio_init(DEFAULT_WRIOP_MDIO1_NAME, EMI1_RGMII2); + ls1088a_qds_mdio_init(DEFAULT_WRIOP_MDIO1_NAME, EMI1_SLOT1); + + for (i = WRIOP1_DPMAC1; i < NUM_WRIOP_PORTS; i++) { + switch (wriop_get_enet_if(i)) { + case PHY_INTERFACE_MODE_QSGMII: + ls1088a_handle_phy_interface_qsgmii(i); + break; + case PHY_INTERFACE_MODE_SGMII: + ls1088a_handle_phy_interface_sgmii(i); + break; + case PHY_INTERFACE_MODE_XGMII: + ls1088a_handle_phy_interface_xsgmii(i); + break; + default: + break; + + if (i == 16) + i = NUM_WRIOP_PORTS; + } + } + + mc_boot_env_var = env_get(MC_BOOT_ENV_VAR); + if (mc_boot_env_var) + run_command_list(mc_boot_env_var, -1, 0); + error = cpu_eth_init(bis); + + if (hwconfig_f("xqsgmii", env_hwconfig)) { + for (i = WRIOP1_DPMAC1; i < NUM_WRIOP_PORTS; i++) { + switch (wriop_get_enet_if(i)) { + case PHY_INTERFACE_MODE_QSGMII: + qsgmii_configure_repeater(i); + break; + case PHY_INTERFACE_MODE_SGMII: + sgmii_configure_repeater(i); + break; + default: + break; + } + + if (i == 16) + i = NUM_WRIOP_PORTS; + } + } +#endif + error = pci_eth_init(bis); + return error; +} diff --git a/board/freescale/ls1088a/ls1088a.c b/board/freescale/ls1088a/ls1088a.c index a022da9..96d9ae7 100644 --- a/board/freescale/ls1088a/ls1088a.c +++ b/board/freescale/ls1088a/ls1088a.c @@ -50,14 +50,20 @@ int checkboard(void) "100 separate SSCG"}; int clock; - +#ifdef CONFIG_TARGET_LS1088AQDS + printf("Board: LS1088A-QDS, "); +#else printf("Board: LS1088A-RDB, "); +#endif sw = QIXIS_READ(arch); printf("Board Arch: V%d, ", sw >> 4); +#ifdef CONFIG_TARGET_LS1088AQDS + printf("Board version: %c, boot from ", (sw & 0xf) + 'A' - 1); +#else printf("Board version: %c, boot from ", (sw & 0xf) + 'A'); - +#endif memset((u8 *)buf, 0x00, ARRAY_SIZE(buf)); @@ -68,8 +74,27 @@ int checkboard(void) puts("SD card\n"); #endif switch (sw) { +#ifdef CONFIG_TARGET_LS1088AQDS case 0: - + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + printf("vBank: %d\n", sw); + break; + case 8: + puts("PromJet\n"); + break; + case 15: + puts("IFCCard\n"); + break; + case 14: +#else + case 0: +#endif puts("QSPI:"); sw = QIXIS_READ(brdcfg[0]); sw = (sw & QIXIS_QMAP_MASK) >> QIXIS_QMAP_SHIFT; @@ -86,9 +111,15 @@ int checkboard(void) break; } - +#ifdef CONFIG_TARGET_LS1088AQDS + printf("FPGA: v%d (%s), build %d", + (int)QIXIS_READ(scver), qixis_read_tag(buf), + (int)qixis_read_minor()); + /* the timestamp string contains "\n" at the end */ + printf(" on %s", qixis_read_time(buf)); +#else printf("CPLD: v%d.%d\n", QIXIS_READ(scver), QIXIS_READ(tagdata)); - +#endif /* * Display the actual SERDES reference clocks as configured by the @@ -116,8 +147,13 @@ int checkboard(void) bool if_board_diff_clk(void) { +#ifdef CONFIG_TARGET_LS1088AQDS + u8 diff_conf = QIXIS_READ(brdcfg[11]); + return diff_conf & 0x40; +#else u8 diff_conf = QIXIS_READ(dutcfg[11]); return diff_conf & 0x80; +#endif } unsigned long get_board_sys_clk(void) @@ -217,7 +253,45 @@ void board_retimer_init(void) reg |= 0x70; i2c_write(I2C_RETIMER_ADDR, 0x2F, 1, ®, 1); +#ifdef CONFIG_TARGET_LS1088AQDS + /* Retimer is connected to I2C1_CH5 */ + select_i2c_ch_pca9547(I2C_MUX_CH5); + + /* Access to Control/Shared register */ + reg = 0x0; + i2c_write(I2C_RETIMER_ADDR2, 0xff, 1, ®, 1); + /* Read device revision and ID */ + i2c_read(I2C_RETIMER_ADDR2, 1, 1, ®, 1); + debug("Retimer version id = 0x%x\n", reg); + + /* Enable Broadcast. All writes target all channel register sets */ + reg = 0x0c; + i2c_write(I2C_RETIMER_ADDR2, 0xff, 1, ®, 1); + + /* Reset Channel Registers */ + i2c_read(I2C_RETIMER_ADDR2, 0, 1, ®, 1); + reg |= 0x4; + i2c_write(I2C_RETIMER_ADDR2, 0, 1, ®, 1); + + /* Set data rate as 10.3125 Gbps */ + reg = 0x90; + i2c_write(I2C_RETIMER_ADDR2, 0x60, 1, ®, 1); + reg = 0xb3; + i2c_write(I2C_RETIMER_ADDR2, 0x61, 1, ®, 1); + reg = 0x90; + i2c_write(I2C_RETIMER_ADDR2, 0x62, 1, ®, 1); + reg = 0xb3; + i2c_write(I2C_RETIMER_ADDR2, 0x63, 1, ®, 1); + reg = 0xcd; + i2c_write(I2C_RETIMER_ADDR2, 0x64, 1, ®, 1); + + /* Select VCO Divider to full rate (000) */ + i2c_read(I2C_RETIMER_ADDR2, 0x2F, 1, ®, 1); + reg &= 0x0f; + reg |= 0x70; + i2c_write(I2C_RETIMER_ADDR2, 0x2F, 1, ®, 1); +#endif /*return the default channel*/ select_i2c_ch_pca9547(I2C_MUX_CH_DEFAULT); } diff --git a/board/freescale/ls1088a/ls1088a_qixis.h b/board/freescale/ls1088a/ls1088a_qixis.h index 9757d1b..4790461 100644 --- a/board/freescale/ls1088a/ls1088a_qixis.h +++ b/board/freescale/ls1088a/ls1088a_qixis.h @@ -31,4 +31,9 @@ #define QIXIS_SDCLK1_165 0x2 #define QIXIS_SDCLK1_100_SP 0x3 +#define BRDCFG4_EMISEL_MASK 0xE0 +#define BRDCFG4_EMISEL_SHIFT 5 +#define BRDCFG9_SFPTX_MASK 0x10 +#define BRDCFG9_SFPTX_SHIFT 4 + #endif |