diff options
Diffstat (limited to 'roms/u-boot/board/freescale/ls1088a')
-rw-r--r-- | roms/u-boot/board/freescale/ls1088a/Kconfig | 61 | ||||
-rw-r--r-- | roms/u-boot/board/freescale/ls1088a/MAINTAINERS | 37 | ||||
-rw-r--r-- | roms/u-boot/board/freescale/ls1088a/Makefile | 10 | ||||
-rw-r--r-- | roms/u-boot/board/freescale/ls1088a/README | 145 | ||||
-rw-r--r-- | roms/u-boot/board/freescale/ls1088a/ddr.c | 138 | ||||
-rw-r--r-- | roms/u-boot/board/freescale/ls1088a/ddr.h | 48 | ||||
-rw-r--r-- | roms/u-boot/board/freescale/ls1088a/eth_ls1088aqds.c | 835 | ||||
-rw-r--r-- | roms/u-boot/board/freescale/ls1088a/eth_ls1088ardb.c | 106 | ||||
-rw-r--r-- | roms/u-boot/board/freescale/ls1088a/ls1088a.c | 1059 | ||||
-rw-r--r-- | roms/u-boot/board/freescale/ls1088a/ls1088a_qixis.h | 55 |
10 files changed, 2494 insertions, 0 deletions
diff --git a/roms/u-boot/board/freescale/ls1088a/Kconfig b/roms/u-boot/board/freescale/ls1088a/Kconfig new file mode 100644 index 000000000..8bb828e3f --- /dev/null +++ b/roms/u-boot/board/freescale/ls1088a/Kconfig @@ -0,0 +1,61 @@ +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" + +if FSL_LS_PPA +config SYS_LS_PPA_FW_ADDR + hex "PPA Firmware Addr" + default 0x20400000 if SYS_LS_PPA_FW_IN_XIP + default 0x400000 if SYS_LS_PPA_FW_IN_MMC || SYS_LS_PPA_FW_IN_NAND + +if CHAIN_OF_TRUST +config SYS_LS_PPA_ESBC_ADDR + hex "PPA Firmware HDR Addr" + default 0x20680000 if SYS_LS_PPA_FW_IN_XIP + default 0x680000 if SYS_LS_PPA_FW_IN_MMC || SYS_LS_PPA_FW_IN_NAND +endif +endif + +source "board/freescale/common/Kconfig" +endif + +if TARGET_LS1088ARDB + +config SYS_BOARD + default "ls1088a" + +config SYS_VENDOR + default "freescale" + +config SYS_SOC + default "fsl-layerscape" + +config SYS_CONFIG_NAME + default "ls1088ardb" + +if FSL_LS_PPA +config SYS_LS_PPA_FW_ADDR + hex "PPA Firmware Addr" + default 0x20400000 if SYS_LS_PPA_FW_IN_XIP + default 0x400000 if SYS_LS_PPA_FW_IN_MMC || SYS_LS_PPA_FW_IN_NAND + +if CHAIN_OF_TRUST +config SYS_LS_PPA_ESBC_ADDR + hex "PPA Firmware HDR Addr" + default 0x20680000 if SYS_LS_PPA_FW_IN_XIP + default 0x680000 if SYS_LS_PPA_FW_IN_MMC || SYS_LS_PPA_FW_IN_NAND +endif +endif + +source "board/freescale/common/Kconfig" +endif diff --git a/roms/u-boot/board/freescale/ls1088a/MAINTAINERS b/roms/u-boot/board/freescale/ls1088a/MAINTAINERS new file mode 100644 index 000000000..5c7925a95 --- /dev/null +++ b/roms/u-boot/board/freescale/ls1088a/MAINTAINERS @@ -0,0 +1,37 @@ +LS1088ARDB BOARD +M: Ashish Kumar <Ashish.Kumar@nxp.com> +M: Rajesh Bhagat <rajesh.bhagat@nxp.com> +S: Maintained +F: board/freescale/ls1088a/ +F: include/configs/ls1088ardb.h +F: configs/ls1088ardb_qspi_defconfig +F: configs/ls1088ardb_sdcard_qspi_defconfig +F: configs/ls1088ardb_tfa_defconfig +F: configs/ls1088ardb_tfa_SECURE_BOOT_defconfig + +LS1088AQDS BOARD +M: Ashish Kumar <Ashish.Kumar@nxp.com> +M: Rajesh Bhagat <rajesh.bhagat@nxp.com> +S: Maintained +F: board/freescale/ls1088a/ +F: include/configs/ls1088aqds.h +F: configs/ls1088aqds_qspi_defconfig +F: configs/ls1088aqds_sdcard_qspi_defconfig +F: configs/ls1088aqds_defconfig +F: configs/ls1088aqds_sdcard_ifc_defconfig +F: configs/ls1088aqds_tfa_defconfig + +LS1088AQDS_QSPI_SECURE_BOOT BOARD +M: Udit Agarwal <udit.agarwal@nxp.com> +S: Maintained +F: configs/ls1088aqds_qspi_SECURE_BOOT_defconfig + +LS1088ARDB_QSPI_SECURE_BOOT BOARD +M: Udit Agarwal <udit.agarwal@nxp.com> +S: Maintained +F: configs/ls1088ardb_qspi_SECURE_BOOT_defconfig + +LS1088ARDB_SD_SECURE_BOOT BOARD +M: Udit Agarwal <udit.agarwal@nxp.com> +S: Maintained +F: configs/ls1088ardb_sdcard_qspi_SECURE_BOOT_defconfig diff --git a/roms/u-boot/board/freescale/ls1088a/Makefile b/roms/u-boot/board/freescale/ls1088a/Makefile new file mode 100644 index 000000000..c2b0e7dc0 --- /dev/null +++ b/roms/u-boot/board/freescale/ls1088a/Makefile @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright 2017 NXP + +obj-y += ls1088a.o +obj-y += ddr.o +ifndef CONFIG_SPL_BUILD +obj-$(CONFIG_TARGET_LS1088ARDB) += eth_ls1088ardb.o +obj-$(CONFIG_TARGET_LS1088AQDS) += eth_ls1088aqds.o +endif diff --git a/roms/u-boot/board/freescale/ls1088a/README b/roms/u-boot/board/freescale/ls1088a/README new file mode 100644 index 000000000..aa0fb6ac6 --- /dev/null +++ b/roms/u-boot/board/freescale/ls1088a/README @@ -0,0 +1,145 @@ +Overview +-------- +The LS1088A Reference Design (RDB) is a high-performance computing, +evaluation, and development platform that supports ARM SoC LS1088A and its +derivatives. + + +LS1088A SoC Overview +-------------------------------------- +Please refer arch/arm/cpu/armv8/fsl-layerscape/doc/README.soc + +RDB Default Switch Settings (1: ON; 0: OFF) +------------------------------------------- + +For QSPI Boot +SW1 0011 0001 +SW2 x100 0000 +SW3 1111 0010 +SW4 1001 0011 +SW5 1111 0000 + +For SD Boot +SW1 0010 0000 +SW2 0100 0000 +SW3 1111 0010 +SW4 1001 0011 +SW5 1111 0000 + +For eMMC Boot +SW1 0010 0000 +SW2 1100 0000 +SW3 1111 0010 +SW4 1001 0011 +SW5 1111 0000 + +Alternately you can use this command to switch from QSPI to SD + +=> i2c mw 66 0x60 0x20; i2c mw 66 10 10;i2c mw 66 10 21 + + LS1088ARDB board Overview + ------------------------- + - SERDES Connections, 16 lanes supporting: + - PCI Express - 3.0 + - SATA 3.0 + - XFI + - QSGMII + - 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 slot and onboard eMMC are muxed together + - 4 I2C controllers + - Two SATA onboard connectors + - 2 UART + - 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/roms/u-boot/board/freescale/ls1088a/ddr.c b/roms/u-boot/board/freescale/ls1088a/ddr.c new file mode 100644 index 000000000..995c42960 --- /dev/null +++ b/roms/u-boot/board/freescale/ls1088a/ddr.c @@ -0,0 +1,138 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2017 NXP + */ + +#include <common.h> +#include <fsl_ddr_sdram.h> +#include <fsl_ddr_dimm_params.h> +#include <log.h> +#include <asm/arch/soc.h> +#include <asm/arch/clock.h> +#include <asm/global_data.h> +#include "ddr.h" + +DECLARE_GLOBAL_DATA_PTR; + +#if defined(CONFIG_VID) && (!defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD)) +static void fsl_ddr_setup_0v9_volt(memctl_options_t *popts) +{ + int vdd; + + vdd = get_core_volt_from_fuse(); + /* Nothing to do for silicons doesn't support VID */ + if (vdd < 0) + return; + + if (vdd == 900) { + popts->ddr_cdr1 |= DDR_CDR1_V0PT9_EN; + debug("VID: configure DDR to support 900 mV\n"); + } +} +#endif + +void fsl_ddr_board_options(memctl_options_t *popts, + dimm_params_t *pdimm, + unsigned int ctrl_num) +{ + const struct board_specific_parameters *pbsp, *pbsp_highest = NULL; + ulong ddr_freq; + + if (ctrl_num > 1) { + printf("Not supported controller number %d\n", ctrl_num); + return; + } + if (!pdimm->n_ranks) + return; + + /* + * we use identical timing for all slots. If needed, change the code + * to pbsp = rdimms[ctrl_num] or pbsp = udimms[ctrl_num]; + */ + pbsp = udimms[0]; + + /* Get clk_adjust, wrlvl_start, wrlvl_ctl, according to the board ddr + * freqency and n_banks specified in board_specific_parameters table. + */ + ddr_freq = get_ddr_freq(0) / 1000000; + while (pbsp->datarate_mhz_high) { + if (pbsp->n_ranks == pdimm->n_ranks) { + if (ddr_freq <= pbsp->datarate_mhz_high) { + popts->clk_adjust = pbsp->clk_adjust; + popts->wrlvl_start = pbsp->wrlvl_start; + popts->wrlvl_ctl_2 = pbsp->wrlvl_ctl_2; + popts->wrlvl_ctl_3 = pbsp->wrlvl_ctl_3; + goto found; + } + pbsp_highest = pbsp; + } + pbsp++; + } + + if (pbsp_highest) { + printf("Error: board specific timing not found for %lu MT/s\n", + ddr_freq); + printf("Trying to use the highest speed (%u) parameters\n", + pbsp_highest->datarate_mhz_high); + popts->clk_adjust = pbsp_highest->clk_adjust; + popts->wrlvl_start = pbsp_highest->wrlvl_start; + popts->wrlvl_ctl_2 = pbsp->wrlvl_ctl_2; + popts->wrlvl_ctl_3 = pbsp->wrlvl_ctl_3; + } else { + panic("DIMM is not supported by this board"); + } +found: + debug("Found timing match: n_ranks %d, data rate %d, rank_gb %d\n" + "\tclk_adjust %d, wrlvl_start %d, wrlvl_ctrl_2 0x%x, wrlvl_ctrl_3 0x%x\n", + pbsp->n_ranks, pbsp->datarate_mhz_high, pbsp->rank_gb, + pbsp->clk_adjust, pbsp->wrlvl_start, pbsp->wrlvl_ctl_2, + pbsp->wrlvl_ctl_3); + + + + popts->half_strength_driver_enable = 0; + /* + * Write leveling override + */ + popts->wrlvl_override = 1; + popts->wrlvl_sample = 0xf; + + + /* Enable ZQ calibration */ + popts->zq_en = 1; + + /* Enable DDR hashing */ + popts->addr_hash = 1; + + popts->ddr_cdr1 = DDR_CDR1_DHC_EN | DDR_CDR1_ODT(DDR_CDR_ODT_60ohm); +#if defined(CONFIG_VID) && (!defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD)) + fsl_ddr_setup_0v9_volt(popts); +#endif + + popts->ddr_cdr2 = DDR_CDR2_ODT(DDR_CDR_ODT_60ohm) | + DDR_CDR2_VREF_TRAIN_EN | DDR_CDR2_VREF_RANGE_2; +} + +#ifdef CONFIG_TFABOOT +int fsl_initdram(void) +{ + gd->ram_size = tfa_get_dram_size(); + + if (!gd->ram_size) + gd->ram_size = fsl_ddr_sdram_size(); + + return 0; +} +#else +int fsl_initdram(void) +{ + puts("Initializing DDR....using SPD\n"); + +#if defined(CONFIG_SPL) && !defined(CONFIG_SPL_BUILD) + gd->ram_size = fsl_ddr_sdram_size(); +#else + gd->ram_size = fsl_ddr_sdram(); +#endif + return 0; +} +#endif /* CONFIG_TFABOOT */ diff --git a/roms/u-boot/board/freescale/ls1088a/ddr.h b/roms/u-boot/board/freescale/ls1088a/ddr.h new file mode 100644 index 000000000..b35c4ae2d --- /dev/null +++ b/roms/u-boot/board/freescale/ls1088a/ddr.h @@ -0,0 +1,48 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2017 NXP + */ + +#ifndef __LS1088A_DDR_H__ +#define __LS1088A_DDR_H__ +struct board_specific_parameters { + u32 n_ranks; + u32 datarate_mhz_high; + u32 rank_gb; + u32 clk_adjust; + u32 wrlvl_start; + u32 wrlvl_ctl_2; + u32 wrlvl_ctl_3; +}; + +/* + * These tables contain all valid speeds we want to override with board + * specific parameters. datarate_mhz_high values need to be in ascending order + * for each n_ranks group. + */ + +static const struct board_specific_parameters udimm0[] = { + /* + * memory controller 0 + * num| hi| rank| clk| wrlvl | wrlvl | wrlvl + * ranks| mhz| GB |adjst| start | ctl2 | ctl3 + */ +#if defined(CONFIG_TARGET_LS1088ARDB) + + {2, 1666, 0, 8, 8, 0x090A0B0E, 0x0F10110D,}, + {2, 1900, 0, 8, 9, 0x0A0B0C10, 0x1112140E,}, + {2, 2300, 0, 8, 9, 0x0A0C0E11, 0x1214160F,}, + {} +#elif defined(CONFIG_TARGET_LS1088AQDS) + {2, 1666, 0, 8, 8, 0x0A0A0C0E, 0x0F10110C,}, + {2, 1900, 0, 8, 9, 0x0A0B0C10, 0x1112140E,}, + {2, 2300, 0, 4, 9, 0x0A0C0D11, 0x1214150E,}, + {} + +#endif +}; + +static const struct board_specific_parameters *udimms[] = { + udimm0, +}; +#endif diff --git a/roms/u-boot/board/freescale/ls1088a/eth_ls1088aqds.c b/roms/u-boot/board/freescale/ls1088a/eth_ls1088aqds.c new file mode 100644 index 000000000..140733de6 --- /dev/null +++ b/roms/u-boot/board/freescale/ls1088a/eth_ls1088aqds.c @@ -0,0 +1,835 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2017 NXP + */ + +#include <common.h> +#include <command.h> +#include <env.h> +#include <log.h> +#include <net.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 <phy.h> +#include <fm_eth.h> +#include <i2c.h> +#include <miiphy.h> +#include <fsl-mc/fsl_mc.h> +#include <fsl-mc/ldpaa_wriop.h> +#include <linux/delay.h> + +#include "../common/qixis.h" + +#include "ls1088a_qixis.h" + +#ifndef CONFIG_DM_ETH +#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; +}; + +struct reg_pair { + uint addr; + u8 *val; +}; + +static void sgmii_configure_repeater(int dpmac) +{ + struct mii_dev *bus; + uint8_t a = 0xf; + int i, j, k, 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}; + + u8 reg_val[6] = {0x18, 0x38, 0x4, 0x14, 0xb5, 0x20}; + struct reg_pair reg_pair[10] = { + {6, ®_val[0]}, {4, ®_val[1]}, + {8, ®_val[2]}, {0xf, NULL}, + {0x11, NULL}, {0x16, NULL}, + {0x18, NULL}, {0x23, ®_val[3]}, + {0x2d, ®_val[4]}, {4, ®_val[5]}, + }; +#if CONFIG_IS_ENABLED(DM_I2C) + struct udevice *udev; +#endif + + /* Set I2c to Slot 1 */ +#if !CONFIG_IS_ENABLED(DM_I2C) + ret = i2c_write(0x77, 0, 0, &a, 1); +#else + ret = i2c_get_chip_for_busnum(0, 0x77, 1, &udev); + if (!ret) + ret = dm_i2c_write(udev, 0, &a, 1); +#endif + if (ret) + goto error; + + 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; + } + +#if CONFIG_IS_ENABLED(DM_I2C) + i2c_get_chip_for_busnum(0, i2c_phy_addr, 1, &udev); +#endif + + for (i = 0; i < 4; i++) { + for (j = 0; j < 4; j++) { + reg_pair[3].val = &ch_a_eq[i]; + reg_pair[4].val = &ch_a_ctl2[j]; + reg_pair[5].val = &ch_b_eq[i]; + reg_pair[6].val = &ch_b_ctl2[j]; + for (k = 0; k < 10; k++) { +#if !CONFIG_IS_ENABLED(DM_I2C) + ret = i2c_write(i2c_phy_addr, + reg_pair[k].addr, + 1, reg_pair[k].val, 1); +#else + ret = i2c_get_chip_for_busnum(0, + i2c_phy_addr, + 1, &udev); + if (!ret) + ret = dm_i2c_write(udev, + reg_pair[k].addr, + reg_pair[k].val, 1); +#endif + if (ret) + goto error; + } + + 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, k; + 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}; + + u8 reg_val[6] = {0x18, 0x38, 0x4, 0x14, 0xb5, 0x20}; + struct reg_pair reg_pair[10] = { + {6, ®_val[0]}, {4, ®_val[1]}, + {8, ®_val[2]}, {0xf, NULL}, + {0x11, NULL}, {0x16, NULL}, + {0x18, NULL}, {0x23, ®_val[3]}, + {0x2d, ®_val[4]}, {4, ®_val[5]}, + }; + + const char *dev = mdio_names[EMI1_SLOT1]; + int ret = 0; + unsigned short value; +#if CONFIG_IS_ENABLED(DM_I2C) + struct udevice *udev; +#endif + + /* Set I2c to Slot 1 */ +#if !CONFIG_IS_ENABLED(DM_I2C) + ret = i2c_write(0x77, 0, 0, &a, 1); +#else + ret = i2c_get_chip_for_busnum(0, 0x77, 1, &udev); + if (!ret) + ret = dm_i2c_write(udev, 0, &a, 1); +#endif + if (ret) + goto error; + + 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; + } + +#if CONFIG_IS_ENABLED(DM_I2C) + i2c_get_chip_for_busnum(0, i2c_phy_addr, 1, &udev); +#endif + + for (i = 0; i < 4; i++) { + for (j = 0; j < 4; j++) { + reg_pair[3].val = &ch_a_eq[i]; + reg_pair[4].val = &ch_a_ctl2[j]; + reg_pair[5].val = &ch_b_eq[i]; + reg_pair[6].val = &ch_b_ctl2[j]; + + for (k = 0; k < 10; k++) { +#if !CONFIG_IS_ENABLED(DM_I2C) + ret = i2c_write(i2c_phy_addr, + reg_pair[k].addr, + 1, reg_pair[k].val, 1); +#else + ret = i2c_get_chip_for_busnum(0, + i2c_addr[dpmac], + 1, &udev); + if (!ret) + ret = dm_i2c_write(udev, + reg_pair[k].addr, + reg_pair[k].val, 1); +#endif + if (ret) + goto error; + } + + 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, 0, riser_phy_addr[1]); + break; + case 2: + wriop_set_phy_address(dpmac_id, 0, riser_phy_addr[0]); + break; + case 3: + wriop_set_phy_address(dpmac_id, 0, riser_phy_addr[3]); + break; + case 7: + wriop_set_phy_address(dpmac_id, 0, 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, 0, dpmac_id + 9); + break; + case 7: + case 8: + case 9: + case 10: + wriop_set_phy_address(dpmac_id, 0, 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, 0, i + 26); + ls1088a_qds_enable_SFP_TX(SFP_TX); + break; + default: + printf("qds: WRIOP: Unsupported SerDes Protocol 0x%02x\n", + serdes1_prtcl); + break; + } +} + +static void ls1088a_handle_phy_interface_rgmii(int dpmac_id) +{ + struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR; + u32 serdes1_prtcl, cfg; + struct mii_dev *bus; + + 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 (dpmac_id) { + case 4: + wriop_set_phy_address(dpmac_id, 0, RGMII_PHY1_ADDR); + dpmac_info[dpmac_id].board_mux = EMI1_RGMII1; + bus = mii_dev_for_muxval(EMI1_RGMII1); + wriop_set_mdio(dpmac_id, bus); + break; + case 5: + wriop_set_phy_address(dpmac_id, 0, RGMII_PHY2_ADDR); + dpmac_info[dpmac_id].board_mux = EMI1_RGMII2; + bus = mii_dev_for_muxval(EMI1_RGMII2); + wriop_set_mdio(dpmac_id, bus); + break; + default: + printf("qds: WRIOP: Unsupported RGMII SerDes Protocol 0x%02x\n", + serdes1_prtcl); + break; + } +} +#endif + +int board_eth_init(struct bd_info *bis) +{ + int error = 0, i; +#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_RGMII: + case PHY_INTERFACE_MODE_RGMII_ID: + ls1088a_handle_phy_interface_rgmii(i); + break; + 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; + } + } + + 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; +} +#endif // !CONFIG_DM_ETH + +#if defined(CONFIG_RESET_PHY_R) +void reset_phy(void) +{ + mc_env_boot(); +} +#endif /* CONFIG_RESET_PHY_R */ + +#if defined(CONFIG_DM_ETH) && defined(CONFIG_MULTI_DTB_FIT) + +/* Structure to hold SERDES protocols supported in case of + * CONFIG_DM_ETH enabled (network interfaces are described in the DTS). + * + * @serdes_block: the index of the SERDES block + * @serdes_protocol: the decimal value of the protocol supported + * @dts_needed: DTS notes describing the current configuration are needed + * + * When dts_needed is true, the board_fit_config_name_match() function + * will try to exactly match the current configuration of the block with a DTS + * name provided. + */ +static struct serdes_configuration { + u8 serdes_block; + u32 serdes_protocol; + bool dts_needed; +} supported_protocols[] = { + /* Serdes block #1 */ + {1, 21, true}, + {1, 29, true}, +}; + +#define SUPPORTED_SERDES_PROTOCOLS ARRAY_SIZE(supported_protocols) + +static bool protocol_supported(u8 serdes_block, u32 protocol) +{ + struct serdes_configuration serdes_conf; + int i; + + for (i = 0; i < SUPPORTED_SERDES_PROTOCOLS; i++) { + serdes_conf = supported_protocols[i]; + if (serdes_conf.serdes_block == serdes_block && + serdes_conf.serdes_protocol == protocol) + return true; + } + + return false; +} + +static void get_str_protocol(u8 serdes_block, u32 protocol, char *str) +{ + struct serdes_configuration serdes_conf; + int i; + + for (i = 0; i < SUPPORTED_SERDES_PROTOCOLS; i++) { + serdes_conf = supported_protocols[i]; + if (serdes_conf.serdes_block == serdes_block && + serdes_conf.serdes_protocol == protocol) { + if (serdes_conf.dts_needed == true) + sprintf(str, "%u", protocol); + else + sprintf(str, "x"); + return; + } + } +} + +int board_fit_config_name_match(const char *name) +{ + struct ccsr_gur *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); + char expected_dts[100]; + char srds_s1_str[2]; + u32 srds_s1, cfg; + + cfg = in_le32(&gur->rcwsr[FSL_CHASSIS3_SRDS1_REGSR - 1]) & + FSL_CHASSIS3_SRDS1_PRTCL_MASK; + cfg >>= FSL_CHASSIS3_SRDS1_PRTCL_SHIFT; + srds_s1 = serdes_get_number(FSL_SRDS_1, cfg); + + /* Check for supported protocols. The default DTS will be used + * in this case + */ + if (!protocol_supported(1, srds_s1)) + return -1; + + get_str_protocol(1, srds_s1, srds_s1_str); + + sprintf(expected_dts, "fsl-ls1088a-qds-%s-x", srds_s1_str); + + if (!strcmp(name, expected_dts)) + return 0; + + return -1; +} +#endif diff --git a/roms/u-boot/board/freescale/ls1088a/eth_ls1088ardb.c b/roms/u-boot/board/freescale/ls1088a/eth_ls1088ardb.c new file mode 100644 index 000000000..a8e9ef15d --- /dev/null +++ b/roms/u-boot/board/freescale/ls1088a/eth_ls1088ardb.c @@ -0,0 +1,106 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2017 NXP + */ + +#include <common.h> +#include <command.h> +#include <net.h> +#include <netdev.h> +#include <malloc.h> +#include <fsl_mdio.h> +#include <miiphy.h> +#include <phy.h> +#include <fm_eth.h> +#include <asm/io.h> +#include <exports.h> +#include <asm/arch/fsl_serdes.h> +#include <fsl-mc/fsl_mc.h> +#include <fsl-mc/ldpaa_wriop.h> + +#ifndef CONFIG_DM_ETH +int board_eth_init(struct bd_info *bis) +{ +#if defined(CONFIG_FSL_MC_ENET) + int i, interface; + struct memac_mdio_info mdio_info; + struct mii_dev *dev; + struct ccsr_gur *gur = (void *)(CONFIG_SYS_FSL_GUTS_ADDR); + struct memac_mdio_controller *reg; + u32 srds_s1, cfg; + + cfg = in_le32(&gur->rcwsr[FSL_CHASSIS3_SRDS1_REGSR - 1]) & + FSL_CHASSIS3_SRDS1_PRTCL_MASK; + cfg >>= FSL_CHASSIS3_SRDS1_PRTCL_SHIFT; + + srds_s1 = serdes_get_number(FSL_SRDS_1, cfg); + + reg = (struct memac_mdio_controller *)CONFIG_SYS_FSL_WRIOP1_MDIO1; + mdio_info.regs = reg; + mdio_info.name = DEFAULT_WRIOP_MDIO1_NAME; + + /* Register the EMI 1 */ + fm_memac_mdio_init(bis, &mdio_info); + + reg = (struct memac_mdio_controller *)CONFIG_SYS_FSL_WRIOP1_MDIO2; + mdio_info.regs = reg; + mdio_info.name = DEFAULT_WRIOP_MDIO2_NAME; + + /* Register the EMI 2 */ + fm_memac_mdio_init(bis, &mdio_info); + + switch (srds_s1) { + case 0x1D: + /* + * XFI does not need a PHY to work, but to avoid U-boot use + * default PHY address which is zero to a MAC when it found + * a MAC has no PHY address, we give a PHY address to XFI + * MAC error. + */ + wriop_set_phy_address(WRIOP1_DPMAC1, 0, 0x0a); + wriop_set_phy_address(WRIOP1_DPMAC2, 0, AQ_PHY_ADDR1); + wriop_set_phy_address(WRIOP1_DPMAC3, 0, QSGMII1_PORT1_PHY_ADDR); + wriop_set_phy_address(WRIOP1_DPMAC4, 0, QSGMII1_PORT2_PHY_ADDR); + wriop_set_phy_address(WRIOP1_DPMAC5, 0, QSGMII1_PORT3_PHY_ADDR); + wriop_set_phy_address(WRIOP1_DPMAC6, 0, QSGMII1_PORT4_PHY_ADDR); + wriop_set_phy_address(WRIOP1_DPMAC7, 0, QSGMII2_PORT1_PHY_ADDR); + wriop_set_phy_address(WRIOP1_DPMAC8, 0, QSGMII2_PORT2_PHY_ADDR); + wriop_set_phy_address(WRIOP1_DPMAC9, 0, QSGMII2_PORT3_PHY_ADDR); + wriop_set_phy_address(WRIOP1_DPMAC10, 0, + QSGMII2_PORT4_PHY_ADDR); + + break; + default: + printf("SerDes1 protocol 0x%x is not supported on LS1088ARDB\n", + srds_s1); + break; + } + + for (i = WRIOP1_DPMAC3; i <= WRIOP1_DPMAC10; i++) { + interface = wriop_get_enet_if(i); + switch (interface) { + case PHY_INTERFACE_MODE_QSGMII: + dev = miiphy_get_dev_by_name(DEFAULT_WRIOP_MDIO1_NAME); + wriop_set_mdio(i, dev); + break; + default: + break; + } + } + + dev = miiphy_get_dev_by_name(DEFAULT_WRIOP_MDIO2_NAME); + wriop_set_mdio(WRIOP1_DPMAC2, dev); + + cpu_eth_init(bis); +#endif /* CONFIG_FMAN_ENET */ + + return pci_eth_init(bis); +} +#endif + +#if defined(CONFIG_RESET_PHY_R) +void reset_phy(void) +{ + mc_env_boot(); +} +#endif /* CONFIG_RESET_PHY_R */ diff --git a/roms/u-boot/board/freescale/ls1088a/ls1088a.c b/roms/u-boot/board/freescale/ls1088a/ls1088a.c new file mode 100644 index 000000000..f5dc449d8 --- /dev/null +++ b/roms/u-boot/board/freescale/ls1088a/ls1088a.c @@ -0,0 +1,1059 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2017-2018 NXP + */ +#include <common.h> +#include <env.h> +#include <i2c.h> +#include <init.h> +#include <log.h> +#include <malloc.h> +#include <errno.h> +#include <netdev.h> +#include <fsl_ifc.h> +#include <fsl_ddr.h> +#include <fsl_sec.h> +#include <asm/global_data.h> +#include <asm/io.h> +#include <fdt_support.h> +#include <linux/delay.h> +#include <linux/libfdt.h> +#include <fsl-mc/fsl_mc.h> +#include <env_internal.h> +#include <asm/arch-fsl-layerscape/soc.h> +#include <asm/arch/ppa.h> +#include <hwconfig.h> +#include <asm/arch/fsl_serdes.h> +#include <asm/arch/soc.h> +#include <asm/arch-fsl-layerscape/fsl_icid.h> + +#include "../common/qixis.h" +#include "ls1088a_qixis.h" +#include "../common/vid.h" +#include <fsl_immap.h> + +DECLARE_GLOBAL_DATA_PTR; + +#ifdef CONFIG_TARGET_LS1088AQDS +#ifdef CONFIG_TFABOOT +struct ifc_regs ifc_cfg_ifc_nor_boot[CONFIG_SYS_FSL_IFC_BANK_COUNT] = { + { + "nor0", + CONFIG_SYS_NOR0_CSPR_EARLY, + CONFIG_SYS_NOR0_CSPR_EXT, + CONFIG_SYS_NOR_AMASK, + CONFIG_SYS_NOR_CSOR, + { + CONFIG_SYS_NOR_FTIM0, + CONFIG_SYS_NOR_FTIM1, + CONFIG_SYS_NOR_FTIM2, + CONFIG_SYS_NOR_FTIM3 + }, + 0, + CONFIG_SYS_NOR0_CSPR, + 0, + }, + { + "nor1", + CONFIG_SYS_NOR1_CSPR_EARLY, + CONFIG_SYS_NOR0_CSPR_EXT, + CONFIG_SYS_NOR_AMASK_EARLY, + CONFIG_SYS_NOR_CSOR, + { + CONFIG_SYS_NOR_FTIM0, + CONFIG_SYS_NOR_FTIM1, + CONFIG_SYS_NOR_FTIM2, + CONFIG_SYS_NOR_FTIM3 + }, + 0, + CONFIG_SYS_NOR1_CSPR, + CONFIG_SYS_NOR_AMASK, + }, + { + "nand", + CONFIG_SYS_NAND_CSPR, + CONFIG_SYS_NAND_CSPR_EXT, + CONFIG_SYS_NAND_AMASK, + CONFIG_SYS_NAND_CSOR, + { + CONFIG_SYS_NAND_FTIM0, + CONFIG_SYS_NAND_FTIM1, + CONFIG_SYS_NAND_FTIM2, + CONFIG_SYS_NAND_FTIM3 + }, + }, + { + "fpga", + CONFIG_SYS_FPGA_CSPR, + CONFIG_SYS_FPGA_CSPR_EXT, + SYS_FPGA_AMASK, + CONFIG_SYS_FPGA_CSOR, + { + SYS_FPGA_CS_FTIM0, + SYS_FPGA_CS_FTIM1, + SYS_FPGA_CS_FTIM2, + SYS_FPGA_CS_FTIM3 + }, + 0, + SYS_FPGA_CSPR_FINAL, + 0, + } +}; + +struct ifc_regs ifc_cfg_qspi_nor_boot[CONFIG_SYS_FSL_IFC_BANK_COUNT] = { + { + "nand", + CONFIG_SYS_NAND_CSPR, + CONFIG_SYS_NAND_CSPR_EXT, + CONFIG_SYS_NAND_AMASK, + CONFIG_SYS_NAND_CSOR, + { + CONFIG_SYS_NAND_FTIM0, + CONFIG_SYS_NAND_FTIM1, + CONFIG_SYS_NAND_FTIM2, + CONFIG_SYS_NAND_FTIM3 + }, + }, + { + "reserved", + }, + { + "fpga", + CONFIG_SYS_FPGA_CSPR, + CONFIG_SYS_FPGA_CSPR_EXT, + SYS_FPGA_AMASK, + CONFIG_SYS_FPGA_CSOR, + { + SYS_FPGA_CS_FTIM0, + SYS_FPGA_CS_FTIM1, + SYS_FPGA_CS_FTIM2, + SYS_FPGA_CS_FTIM3 + }, + 0, + SYS_FPGA_CSPR_FINAL, + 0, + } +}; + +void ifc_cfg_boot_info(struct ifc_regs_info *regs_info) +{ + enum boot_src src = get_boot_src(); + + if (src == BOOT_SOURCE_QSPI_NOR) + regs_info->regs = ifc_cfg_qspi_nor_boot; + else + regs_info->regs = ifc_cfg_ifc_nor_boot; + + regs_info->cs_size = CONFIG_SYS_FSL_IFC_BANK_COUNT; +} +#endif /* CONFIG_TFABOOT */ +#endif /* CONFIG_TARGET_LS1088AQDS */ + +int board_early_init_f(void) +{ +#if defined(CONFIG_SYS_I2C_EARLY_INIT) && defined(CONFIG_TARGET_LS1088AQDS) + i2c_early_init_f(); +#endif + fsl_lsch3_early_init_f(); + return 0; +} + +#ifdef CONFIG_FSL_QIXIS +unsigned long long get_qixis_addr(void) +{ + unsigned long long addr; + + if (gd->flags & GD_FLG_RELOC) + addr = QIXIS_BASE_PHYS; + else + addr = QIXIS_BASE_PHYS_EARLY; + + /* + * IFC address under 256MB is mapped to 0x30000000, any address above + * is mapped to 0x5_10000000 up to 4GB. + */ + addr = addr > 0x10000000 ? addr + 0x500000000ULL : addr + 0x30000000; + + return addr; +} +#endif + +#if defined(CONFIG_VID) +int init_func_vid(void) +{ + if (adjust_vdd(0) < 0) + printf("core voltage not adjusted\n"); + + return 0; +} + +u16 soc_get_fuse_vid(int vid_index) +{ + static const u16 vdd[32] = { + 10250, + 9875, + 9750, + 0, /* reserved */ + 0, /* reserved */ + 0, /* reserved */ + 0, /* reserved */ + 0, /* reserved */ + 9000, + 0, /* reserved */ + 0, /* reserved */ + 0, /* reserved */ + 0, /* reserved */ + 0, /* reserved */ + 0, /* reserved */ + 0, /* reserved */ + 10000, /* 1.0000V */ + 10125, + 10250, + 0, /* reserved */ + 0, /* reserved */ + 0, /* reserved */ + 0, /* reserved */ + 0, /* reserved */ + 0, /* reserved */ + 0, /* reserved */ + 0, /* reserved */ + 0, /* reserved */ + 0, /* reserved */ + 0, /* reserved */ + 0, /* reserved */ + 0, /* reserved */ + }; + + return vdd[vid_index]; +}; +#endif + +int is_pb_board(void) +{ + u8 board_id; + + board_id = QIXIS_READ(id); + if (board_id == LS1088ARDB_PB_BOARD) + return 1; + else + return 0; +} + +int fixup_ls1088ardb_pb_banner(void *fdt) +{ + fdt_setprop_string(fdt, 0, "model", "LS1088ARDB-PB Board"); + + return 0; +} + +#if !defined(CONFIG_SPL_BUILD) +int checkboard(void) +{ +#ifdef CONFIG_TFABOOT + enum boot_src src = get_boot_src(); +#endif + char buf[64]; + u8 sw; + static const char *const freq[] = {"100", "125", "156.25", + "100 separate SSCG"}; + int clock; + +#ifdef CONFIG_TARGET_LS1088AQDS + printf("Board: LS1088A-QDS, "); +#else + if (is_pb_board()) + printf("Board: LS1088ARDB-PB, "); + 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)); + + sw = QIXIS_READ(brdcfg[0]); + sw = (sw & QIXIS_LBMAP_MASK) >> QIXIS_LBMAP_SHIFT; + +#ifdef CONFIG_TFABOOT + if (src == BOOT_SOURCE_SD_MMC) + puts("SD card\n"); +#else +#ifdef CONFIG_SD_BOOT + puts("SD card\n"); +#endif +#endif /* CONFIG_TFABOOT */ + 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; + if (sw == 0 || sw == 4) + puts("0\n"); + else if (sw == 1) + puts("1\n"); + else + puts("EMU\n"); + break; + + default: + printf("invalid setting of SW%u\n", QIXIS_LBMAP_SWITCH); + 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 + * dip switches on the board. Note that the SWx registers could + * technically be set to force the reference clocks to match the + * values that the SERDES expects (or vice versa). For now, however, + * we just display both values and hope the user notices when they + * don't match. + */ + puts("SERDES1 Reference : "); + sw = QIXIS_READ(brdcfg[2]); + clock = (sw >> 6) & 3; + printf("Clock1 = %sMHz ", freq[clock]); + clock = (sw >> 4) & 3; + printf("Clock2 = %sMHz", freq[clock]); + + puts("\nSERDES2 Reference : "); + clock = (sw >> 2) & 3; + printf("Clock1 = %sMHz ", freq[clock]); + clock = (sw >> 0) & 3; + printf("Clock2 = %sMHz\n", freq[clock]); + + return 0; +} +#endif + +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) +{ + u8 sysclk_conf = QIXIS_READ(brdcfg[1]); + + switch (sysclk_conf & 0x0f) { + case QIXIS_SYSCLK_83: + return 83333333; + case QIXIS_SYSCLK_100: + return 100000000; + case QIXIS_SYSCLK_125: + return 125000000; + case QIXIS_SYSCLK_133: + return 133333333; + case QIXIS_SYSCLK_150: + return 150000000; + case QIXIS_SYSCLK_160: + return 160000000; + case QIXIS_SYSCLK_166: + return 166666666; + } + + return 66666666; +} + +unsigned long get_board_ddr_clk(void) +{ + u8 ddrclk_conf = QIXIS_READ(brdcfg[1]); + + if (if_board_diff_clk()) + return get_board_sys_clk(); + switch ((ddrclk_conf & 0x30) >> 4) { + case QIXIS_DDRCLK_100: + return 100000000; + case QIXIS_DDRCLK_125: + return 125000000; + case QIXIS_DDRCLK_133: + return 133333333; + } + + return 66666666; +} + +int select_i2c_ch_pca9547(u8 ch) +{ + int ret; + +#if !CONFIG_IS_ENABLED(DM_I2C) + ret = i2c_write(I2C_MUX_PCA_ADDR_PRI, 0, 1, &ch, 1); +#else + struct udevice *dev; + + ret = i2c_get_chip_for_busnum(0, I2C_MUX_PCA_ADDR_PRI, 1, &dev); + if (!ret) + ret = dm_i2c_write(dev, 0, &ch, 1); +#endif + if (ret) { + puts("PCA: failed to select proper channel\n"); + return ret; + } + + return 0; +} + +#if !defined(CONFIG_SPL_BUILD) +void board_retimer_init(void) +{ + u8 reg; + + /* Retimer is connected to I2C1_CH5 */ + select_i2c_ch_pca9547(I2C_MUX_CH5); + + /* Access to Control/Shared register */ + reg = 0x0; +#if !CONFIG_IS_ENABLED(DM_I2C) + i2c_write(I2C_RETIMER_ADDR, 0xff, 1, ®, 1); +#else + struct udevice *dev; + + i2c_get_chip_for_busnum(0, I2C_RETIMER_ADDR, 1, &dev); + dm_i2c_write(dev, 0xff, ®, 1); +#endif + + /* Read device revision and ID */ +#if !CONFIG_IS_ENABLED(DM_I2C) + i2c_read(I2C_RETIMER_ADDR, 1, 1, ®, 1); +#else + dm_i2c_read(dev, 1, ®, 1); +#endif + debug("Retimer version id = 0x%x\n", reg); + + /* Enable Broadcast. All writes target all channel register sets */ + reg = 0x0c; +#if !CONFIG_IS_ENABLED(DM_I2C) + i2c_write(I2C_RETIMER_ADDR, 0xff, 1, ®, 1); +#else + dm_i2c_write(dev, 0xff, ®, 1); +#endif + + /* Reset Channel Registers */ +#if !CONFIG_IS_ENABLED(DM_I2C) + i2c_read(I2C_RETIMER_ADDR, 0, 1, ®, 1); +#else + dm_i2c_read(dev, 0, ®, 1); +#endif + reg |= 0x4; +#if !CONFIG_IS_ENABLED(DM_I2C) + i2c_write(I2C_RETIMER_ADDR, 0, 1, ®, 1); +#else + dm_i2c_write(dev, 0, ®, 1); +#endif + + /* Set data rate as 10.3125 Gbps */ + reg = 0x90; +#if !CONFIG_IS_ENABLED(DM_I2C) + i2c_write(I2C_RETIMER_ADDR, 0x60, 1, ®, 1); +#else + dm_i2c_write(dev, 0x60, ®, 1); +#endif + reg = 0xb3; +#if !CONFIG_IS_ENABLED(DM_I2C) + i2c_write(I2C_RETIMER_ADDR, 0x61, 1, ®, 1); +#else + dm_i2c_write(dev, 0x61, ®, 1); +#endif + reg = 0x90; +#if !CONFIG_IS_ENABLED(DM_I2C) + i2c_write(I2C_RETIMER_ADDR, 0x62, 1, ®, 1); +#else + dm_i2c_write(dev, 0x62, ®, 1); +#endif + reg = 0xb3; +#if !CONFIG_IS_ENABLED(DM_I2C) + i2c_write(I2C_RETIMER_ADDR, 0x63, 1, ®, 1); +#else + dm_i2c_write(dev, 0x63, ®, 1); +#endif + reg = 0xcd; +#if !CONFIG_IS_ENABLED(DM_I2C) + i2c_write(I2C_RETIMER_ADDR, 0x64, 1, ®, 1); +#else + dm_i2c_write(dev, 0x64, ®, 1); +#endif + + /* Select VCO Divider to full rate (000) */ +#if !CONFIG_IS_ENABLED(DM_I2C) + i2c_read(I2C_RETIMER_ADDR, 0x2F, 1, ®, 1); +#else + dm_i2c_read(dev, 0x2F, ®, 1); +#endif + reg &= 0x0f; + reg |= 0x70; +#if !CONFIG_IS_ENABLED(DM_I2C) + i2c_write(I2C_RETIMER_ADDR, 0x2F, 1, ®, 1); +#else + dm_i2c_write(dev, 0x2F, ®, 1); +#endif + +#ifdef CONFIG_TARGET_LS1088AQDS + /* Retimer is connected to I2C1_CH5 */ + select_i2c_ch_pca9547(I2C_MUX_CH5); + + /* Access to Control/Shared register */ + reg = 0x0; +#if !CONFIG_IS_ENABLED(DM_I2C) + i2c_write(I2C_RETIMER_ADDR2, 0xff, 1, ®, 1); +#else + i2c_get_chip_for_busnum(0, I2C_RETIMER_ADDR2, 1, &dev); + dm_i2c_write(dev, 0xff, ®, 1); +#endif + + /* Read device revision and ID */ +#if !CONFIG_IS_ENABLED(DM_I2C) + i2c_read(I2C_RETIMER_ADDR2, 1, 1, ®, 1); +#else + dm_i2c_read(dev, 1, ®, 1); +#endif + debug("Retimer version id = 0x%x\n", reg); + + /* Enable Broadcast. All writes target all channel register sets */ + reg = 0x0c; +#if !CONFIG_IS_ENABLED(DM_I2C) + i2c_write(I2C_RETIMER_ADDR2, 0xff, 1, ®, 1); +#else + dm_i2c_write(dev, 0xff, ®, 1); +#endif + + /* Reset Channel Registers */ +#if !CONFIG_IS_ENABLED(DM_I2C) + i2c_read(I2C_RETIMER_ADDR2, 0, 1, ®, 1); +#else + dm_i2c_read(dev, 0, ®, 1); +#endif + reg |= 0x4; +#if !CONFIG_IS_ENABLED(DM_I2C) + i2c_write(I2C_RETIMER_ADDR2, 0, 1, ®, 1); +#else + dm_i2c_write(dev, 0, ®, 1); +#endif + + /* Set data rate as 10.3125 Gbps */ + reg = 0x90; +#if !CONFIG_IS_ENABLED(DM_I2C) + i2c_write(I2C_RETIMER_ADDR2, 0x60, 1, ®, 1); +#else + dm_i2c_write(dev, 0x60, ®, 1); +#endif + reg = 0xb3; +#if !CONFIG_IS_ENABLED(DM_I2C) + i2c_write(I2C_RETIMER_ADDR2, 0x61, 1, ®, 1); +#else + dm_i2c_write(dev, 0x61, ®, 1); +#endif + reg = 0x90; +#if !CONFIG_IS_ENABLED(DM_I2C) + i2c_write(I2C_RETIMER_ADDR2, 0x62, 1, ®, 1); +#else + dm_i2c_write(dev, 0x62, ®, 1); +#endif + reg = 0xb3; +#if !CONFIG_IS_ENABLED(DM_I2C) + i2c_write(I2C_RETIMER_ADDR2, 0x63, 1, ®, 1); +#else + dm_i2c_write(dev, 0x63, ®, 1); +#endif + reg = 0xcd; +#if !CONFIG_IS_ENABLED(DM_I2C) + i2c_write(I2C_RETIMER_ADDR2, 0x64, 1, ®, 1); +#else + dm_i2c_write(dev, 0x64, ®, 1); +#endif + + /* Select VCO Divider to full rate (000) */ +#if !CONFIG_IS_ENABLED(DM_I2C) + i2c_read(I2C_RETIMER_ADDR2, 0x2F, 1, ®, 1); +#else + dm_i2c_read(dev, 0x2F, ®, 1); +#endif + reg &= 0x0f; + reg |= 0x70; +#if !CONFIG_IS_ENABLED(DM_I2C) + i2c_write(I2C_RETIMER_ADDR2, 0x2F, 1, ®, 1); +#else + dm_i2c_write(dev, 0x2F, ®, 1); +#endif + +#endif + /*return the default channel*/ + select_i2c_ch_pca9547(I2C_MUX_CH_DEFAULT); +} + +#ifdef CONFIG_MISC_INIT_R +int misc_init_r(void) +{ +#ifdef CONFIG_TARGET_LS1088ARDB + u8 brdcfg5; + + if (hwconfig("esdhc-force-sd")) { + brdcfg5 = QIXIS_READ(brdcfg[5]); + brdcfg5 &= ~BRDCFG5_SPISDHC_MASK; + brdcfg5 |= BRDCFG5_FORCE_SD; + QIXIS_WRITE(brdcfg[5], brdcfg5); + } +#endif + +#ifdef CONFIG_TARGET_LS1088AQDS + u8 brdcfg4, brdcfg5; + + if (hwconfig("dspi-on-board")) { + brdcfg4 = QIXIS_READ(brdcfg[4]); + brdcfg4 &= ~BRDCFG4_USBOSC_MASK; + brdcfg4 |= BRDCFG4_SPI; + QIXIS_WRITE(brdcfg[4], brdcfg4); + + brdcfg5 = QIXIS_READ(brdcfg[5]); + brdcfg5 &= ~BRDCFG5_SPR_MASK; + brdcfg5 |= BRDCFG5_SPI_ON_BOARD; + QIXIS_WRITE(brdcfg[5], brdcfg5); + } else if (hwconfig("dspi-off-board")) { + brdcfg4 = QIXIS_READ(brdcfg[4]); + brdcfg4 &= ~BRDCFG4_USBOSC_MASK; + brdcfg4 |= BRDCFG4_SPI; + QIXIS_WRITE(brdcfg[4], brdcfg4); + + brdcfg5 = QIXIS_READ(brdcfg[5]); + brdcfg5 &= ~BRDCFG5_SPR_MASK; + brdcfg5 |= BRDCFG5_SPI_OFF_BOARD; + QIXIS_WRITE(brdcfg[5], brdcfg5); + } +#endif + return 0; +} +#endif +#endif + +int i2c_multiplexer_select_vid_channel(u8 channel) +{ + return select_i2c_ch_pca9547(channel); +} + +#ifdef CONFIG_TARGET_LS1088AQDS +/* read the current value(SVDD) of the LTM Regulator Voltage */ +int get_serdes_volt(void) +{ + int ret, vcode = 0; + u8 chan = PWM_CHANNEL0; + + /* Select the PAGE 0 using PMBus commands PAGE for VDD */ +#if !CONFIG_IS_ENABLED(DM_I2C) + ret = i2c_write(I2C_SVDD_MONITOR_ADDR, + PMBUS_CMD_PAGE, 1, &chan, 1); +#else + struct udevice *dev; + + ret = i2c_get_chip_for_busnum(0, I2C_SVDD_MONITOR_ADDR, 1, &dev); + if (!ret) + ret = dm_i2c_write(dev, PMBUS_CMD_PAGE, + &chan, 1); +#endif + + if (ret) { + printf("VID: failed to select VDD Page 0\n"); + return ret; + } + + /* Read the output voltage using PMBus command READ_VOUT */ +#if !CONFIG_IS_ENABLED(DM_I2C) + ret = i2c_read(I2C_SVDD_MONITOR_ADDR, + PMBUS_CMD_READ_VOUT, 1, (void *)&vcode, 2); +#else + dm_i2c_read(dev, PMBUS_CMD_READ_VOUT, (void *)&vcode, 2); +#endif + if (ret) { + printf("VID: failed to read the volatge\n"); + return ret; + } + + return vcode; +} + +int set_serdes_volt(int svdd) +{ + int ret, vdd_last; + u8 buff[5] = {0x04, PWM_CHANNEL0, PMBUS_CMD_VOUT_COMMAND, + svdd & 0xFF, (svdd & 0xFF00) >> 8}; + + /* Write the desired voltage code to the SVDD regulator */ +#if !CONFIG_IS_ENABLED(DM_I2C) + ret = i2c_write(I2C_SVDD_MONITOR_ADDR, + PMBUS_CMD_PAGE_PLUS_WRITE, 1, (void *)&buff, 5); +#else + struct udevice *dev; + + ret = i2c_get_chip_for_busnum(0, I2C_SVDD_MONITOR_ADDR, 1, &dev); + if (!ret) + ret = dm_i2c_write(dev, PMBUS_CMD_PAGE_PLUS_WRITE, + (void *)&buff, 5); +#endif + if (ret) { + printf("VID: I2C failed to write to the volatge regulator\n"); + return -1; + } + + /* Wait for the volatge to get to the desired value */ + do { + vdd_last = get_serdes_volt(); + if (vdd_last < 0) { + printf("VID: Couldn't read sensor abort VID adjust\n"); + return -1; + } + } while (vdd_last != svdd); + + return 1; +} +#else +int get_serdes_volt(void) +{ + return 0; +} + +int set_serdes_volt(int svdd) +{ + int ret; + u8 brdcfg4; + + printf("SVDD changing of RDB\n"); + + /* Read the BRDCFG54 via CLPD */ +#if !CONFIG_IS_ENABLED(DM_I2C) + ret = i2c_read(CONFIG_SYS_I2C_FPGA_ADDR, + QIXIS_BRDCFG4_OFFSET, 1, (void *)&brdcfg4, 1); +#else + struct udevice *dev; + + ret = i2c_get_chip_for_busnum(0, CONFIG_SYS_I2C_FPGA_ADDR, 1, &dev); + if (!ret) + ret = dm_i2c_read(dev, QIXIS_BRDCFG4_OFFSET, + (void *)&brdcfg4, 1); +#endif + + if (ret) { + printf("VID: I2C failed to read the CPLD BRDCFG4\n"); + return -1; + } + + brdcfg4 = brdcfg4 | 0x08; + + /* Write to the BRDCFG4 */ +#if !CONFIG_IS_ENABLED(DM_I2C) + ret = i2c_write(CONFIG_SYS_I2C_FPGA_ADDR, + QIXIS_BRDCFG4_OFFSET, 1, (void *)&brdcfg4, 1); +#else + ret = dm_i2c_write(dev, QIXIS_BRDCFG4_OFFSET, + (void *)&brdcfg4, 1); +#endif + + if (ret) { + debug("VID: I2C failed to set the SVDD CPLD BRDCFG4\n"); + return -1; + } + + /* Wait for the volatge to get to the desired value */ + udelay(10000); + + return 1; +} +#endif + +/* this function disables the SERDES, changes the SVDD Voltage and enables it*/ +int board_adjust_vdd(int vdd) +{ + int ret = 0; + + debug("%s: vdd = %d\n", __func__, vdd); + + /* Special settings to be performed when voltage is 900mV */ + if (vdd == 900) { + ret = setup_serdes_volt(vdd); + if (ret < 0) { + ret = -1; + goto exit; + } + } +exit: + return ret; +} + +#if !defined(CONFIG_SPL_BUILD) +int board_init(void) +{ + init_final_memctl_regs(); +#if defined(CONFIG_TARGET_LS1088ARDB) && defined(CONFIG_FSL_MC_ENET) + u32 __iomem *irq_ccsr = (u32 __iomem *)ISC_BASE; +#endif + + select_i2c_ch_pca9547(I2C_MUX_CH_DEFAULT); + board_retimer_init(); + +#ifdef CONFIG_ENV_IS_NOWHERE + gd->env_addr = (ulong)&default_environment[0]; +#endif + +#if defined(CONFIG_TARGET_LS1088ARDB) && defined(CONFIG_FSL_MC_ENET) + /* invert AQR105 IRQ pins polarity */ + out_le32(irq_ccsr + IRQCR_OFFSET / 4, AQR105_IRQ_MASK); +#endif + +#ifdef CONFIG_FSL_CAAM + sec_init(); +#endif +#ifdef CONFIG_FSL_LS_PPA + ppa_init(); +#endif + +#if !defined(CONFIG_SYS_EARLY_PCI_INIT) && defined(CONFIG_DM_ETH) + pci_init(); +#endif + + return 0; +} + +void detail_board_ddr_info(void) +{ + puts("\nDDR "); + print_size(gd->bd->bi_dram[0].size + gd->bd->bi_dram[1].size, ""); + print_ddr_info(0); +} + +#ifdef CONFIG_FSL_MC_ENET +void board_quiesce_devices(void) +{ + fsl_mc_ldpaa_exit(gd->bd); +} + +void fdt_fixup_board_enet(void *fdt) +{ + int offset; + + offset = fdt_path_offset(fdt, "/fsl-mc"); + + if (offset < 0) + offset = fdt_path_offset(fdt, "/soc/fsl-mc"); + + if (offset < 0) { + printf("%s: ERROR: fsl-mc node not found in device tree (error %d)\n", + __func__, offset); + return; + } + + if (get_mc_boot_status() == 0 && + (is_lazy_dpl_addr_valid() || get_dpl_apply_status() == 0)) + fdt_status_okay(fdt, offset); + else + fdt_status_fail(fdt, offset); +} +#endif + +#ifdef CONFIG_OF_BOARD_SETUP +void fsl_fdt_fixup_flash(void *fdt) +{ + int offset; +#ifdef CONFIG_TFABOOT + u32 __iomem *dcfg_ccsr = (u32 __iomem *)DCFG_BASE; + u32 val; +#endif + +/* + * IFC-NOR and QSPI are muxed on SoC. + * So disable IFC node in dts if QSPI is enabled or + * disable QSPI node in dts in case QSPI is not enabled. + */ + +#ifdef CONFIG_TFABOOT + enum boot_src src = get_boot_src(); + bool disable_ifc = false; + + switch (src) { + case BOOT_SOURCE_IFC_NOR: + disable_ifc = false; + break; + case BOOT_SOURCE_QSPI_NOR: + disable_ifc = true; + break; + default: + val = in_le32(dcfg_ccsr + DCFG_RCWSR15 / 4); + if (DCFG_RCWSR15_IFCGRPABASE_QSPI == (val & (u32)0x3)) + disable_ifc = true; + break; + } + + if (disable_ifc) { + offset = fdt_path_offset(fdt, "/soc/ifc/nor"); + + if (offset < 0) + offset = fdt_path_offset(fdt, "/ifc/nor"); + } else { + offset = fdt_path_offset(fdt, "/soc/quadspi"); + + if (offset < 0) + offset = fdt_path_offset(fdt, "/quadspi"); + } + +#else +#ifdef CONFIG_FSL_QSPI + offset = fdt_path_offset(fdt, "/soc/ifc/nor"); + + if (offset < 0) + offset = fdt_path_offset(fdt, "/ifc/nor"); +#else + offset = fdt_path_offset(fdt, "/soc/quadspi"); + + if (offset < 0) + offset = fdt_path_offset(fdt, "/quadspi"); +#endif +#endif + if (offset < 0) + return; + + fdt_status_disabled(fdt, offset); +} + +int ft_board_setup(void *blob, struct bd_info *bd) +{ + int i; + u16 mc_memory_bank = 0; + + u64 *base; + u64 *size; + u64 mc_memory_base = 0; + u64 mc_memory_size = 0; + u16 total_memory_banks; + + ft_cpu_setup(blob, bd); + + fdt_fixup_mc_ddr(&mc_memory_base, &mc_memory_size); + + if (mc_memory_base != 0) + mc_memory_bank++; + + total_memory_banks = CONFIG_NR_DRAM_BANKS + mc_memory_bank; + + base = calloc(total_memory_banks, sizeof(u64)); + size = calloc(total_memory_banks, sizeof(u64)); + + /* fixup DT for the two GPP DDR banks */ + for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { + base[i] = gd->bd->bi_dram[i].start; + size[i] = gd->bd->bi_dram[i].size; + } + +#ifdef CONFIG_RESV_RAM + /* reduce size if reserved memory is within this bank */ + if (gd->arch.resv_ram >= base[0] && + gd->arch.resv_ram < base[0] + size[0]) + size[0] = gd->arch.resv_ram - base[0]; + else if (gd->arch.resv_ram >= base[1] && + gd->arch.resv_ram < base[1] + size[1]) + size[1] = gd->arch.resv_ram - base[1]; +#endif + + if (mc_memory_base != 0) { + for (i = 0; i <= total_memory_banks; i++) { + if (base[i] == 0 && size[i] == 0) { + base[i] = mc_memory_base; + size[i] = mc_memory_size; + break; + } + } + } + + fdt_fixup_memory_banks(blob, base, size, total_memory_banks); + + fdt_fsl_mc_fixup_iommu_map_entry(blob); + + fsl_fdt_fixup_flash(blob); + +#ifdef CONFIG_FSL_MC_ENET + fdt_fixup_board_enet(blob); +#endif + + fdt_fixup_icid(blob); + + if (is_pb_board()) + fixup_ls1088ardb_pb_banner(blob); + + return 0; +} +#endif +#endif /* defined(CONFIG_SPL_BUILD) */ + +#ifdef CONFIG_TFABOOT +#ifdef CONFIG_MTD_NOR_FLASH +int is_flash_available(void) +{ + char *env_hwconfig = env_get("hwconfig"); + enum boot_src src = get_boot_src(); + int is_nor_flash_available = 1; + + switch (src) { + case BOOT_SOURCE_IFC_NOR: + is_nor_flash_available = 1; + break; + case BOOT_SOURCE_QSPI_NOR: + is_nor_flash_available = 0; + break; + /* + * In Case of SD boot,if qspi is defined in env_hwconfig + * disable nor flash probe. + */ + default: + if (hwconfig_f("qspi", env_hwconfig)) + is_nor_flash_available = 0; + break; + } + return is_nor_flash_available; +} +#endif + +#ifdef CONFIG_ENV_IS_IN_SPI_FLASH +void *env_sf_get_env_addr(void) +{ + return (void *)(CONFIG_SYS_FSL_QSPI_BASE + CONFIG_ENV_OFFSET); +} +#endif +#endif diff --git a/roms/u-boot/board/freescale/ls1088a/ls1088a_qixis.h b/roms/u-boot/board/freescale/ls1088a/ls1088a_qixis.h new file mode 100644 index 000000000..e3502eb1d --- /dev/null +++ b/roms/u-boot/board/freescale/ls1088a/ls1088a_qixis.h @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2017 NXP + */ + +#ifndef __LS1088AQDS_QIXIS_H__ +#define __LS1088AQDS_QIXIS_H__ + +/* Definitions of QIXIS Registers for LS1088AQDS */ + +/* SYSCLK */ +#define QIXIS_SYSCLK_66 0x0 +#define QIXIS_SYSCLK_83 0x1 +#define QIXIS_SYSCLK_100 0x2 +#define QIXIS_SYSCLK_125 0x3 +#define QIXIS_SYSCLK_133 0x4 +#define QIXIS_SYSCLK_150 0x5 +#define QIXIS_SYSCLK_160 0x6 +#define QIXIS_SYSCLK_166 0x7 + +/* DDRCLK */ +#define QIXIS_DDRCLK_66 0x0 +#define QIXIS_DDRCLK_100 0x1 +#define QIXIS_DDRCLK_125 0x2 +#define QIXIS_DDRCLK_133 0x3 + +/* BRDCFG2 - SD clock*/ +#define QIXIS_SDCLK1_100 0x0 +#define QIXIS_SDCLK1_125 0x1 +#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 + +/* Definitions of QIXIS Registers for LS1088ARDB */ + +/* BRDCFG5 */ +#define BRDCFG5_SPISDHC_MASK 0x0C +#define BRDCFG5_FORCE_SD 0x08 + +/* Definitions of QIXIS Registers for LS1088AQDS */ + +/* BRDCFG4 */ +#define BRDCFG4_USBOSC_MASK 0x01 +#define BRDCFG4_SPI 0x01 + +/* BRDCFG5 */ +#define BRDCFG5_SPR_MASK 0x0f +#define BRDCFG5_SPI_ON_BOARD 0x0a +#define BRDCFG5_SPI_OFF_BOARD 0x0f + +#endif |