// SPDX-License-Identifier: GPL-2.0+ /* * Copyright 2019, 2021 NXP */ #include <common.h> #include <i2c.h> #include <fdt_support.h> #include <init.h> #include <asm/global_data.h> #include <asm/io.h> #include <asm/arch/clock.h> #include <asm/arch/fsl_serdes.h> #include <asm/arch/soc.h> #include <asm/arch-fsl-layerscape/fsl_icid.h> #include <hwconfig.h> #include <ahci.h> #include <mmc.h> #include <scsi.h> #include <fm_eth.h> #include <fsl_csu.h> #include <fsl_esdhc.h> #include <fsl_dspi.h> #include "../common/i2c_mux.h" #define LS1046A_PORSR1_REG 0x1EE0000 #define BOOT_SRC_SD 0x20000000 #define BOOT_SRC_MASK 0xFF800000 #define BOARD_REV_GPIO_SHIFT 17 #define BOARD_REV_MASK 0x03 #define USB2_SEL_MASK 0x00000100 #define BYTE_SWAP_32(word) ((((word) & 0xff000000) >> 24) | \ (((word) & 0x00ff0000) >> 8) | \ (((word) & 0x0000ff00) << 8) | \ (((word) & 0x000000ff) << 24)) #define SPI_MCR_REG 0x2100000 DECLARE_GLOBAL_DATA_PTR; static inline void demux_select_usb2(void) { u32 val; struct ccsr_gpio *pgpio = (void *)(GPIO3_BASE_ADDR); val = in_be32(&pgpio->gpdir); val |= USB2_SEL_MASK; out_be32(&pgpio->gpdir, val); val = in_be32(&pgpio->gpdat); val |= USB2_SEL_MASK; out_be32(&pgpio->gpdat, val); } static inline void set_spi_cs_signal_inactive(void) { /* default: all CS signals inactive state is high */ uint mcr_val; uint mcr_cfg_val = DSPI_MCR_MSTR | DSPI_MCR_PCSIS_MASK | DSPI_MCR_CRXF | DSPI_MCR_CTXF; mcr_val = in_be32(SPI_MCR_REG); mcr_val |= DSPI_MCR_HALT; out_be32(SPI_MCR_REG, mcr_val); out_be32(SPI_MCR_REG, mcr_cfg_val); mcr_val = in_be32(SPI_MCR_REG); mcr_val &= ~DSPI_MCR_HALT; out_be32(SPI_MCR_REG, mcr_val); } int board_early_init_f(void) { fsl_lsch2_early_init_f(); return 0; } static inline uint8_t get_board_version(void) { struct ccsr_gpio *pgpio = (void *)(GPIO2_BASE_ADDR); /* GPIO 13 and GPIO 14 are used for Board Rev */ u32 gpio_val = ((in_be32(&pgpio->gpdat) >> BOARD_REV_GPIO_SHIFT)) & BOARD_REV_MASK; /* GPIOs' are 0..31 in Big Endiness, swap GPIO 13 and GPIO 14 */ u8 val = ((gpio_val >> 1) | (gpio_val << 1)) & BOARD_REV_MASK; return val; } int checkboard(void) { static const char *freq[2] = {"100.00MHZ", "100.00MHZ"}; u32 boot_src; u8 rev; rev = get_board_version(); switch (rev) { case 0x00: puts("Board: LS1046AFRWY, Rev: A, boot from "); break; case 0x01: puts("Board: LS1046AFRWY, Rev: B, boot from "); break; default: puts("Board: LS1046AFRWY, Rev: Unknown, boot from "); break; } boot_src = BYTE_SWAP_32(readl(LS1046A_PORSR1_REG)); if ((boot_src & BOOT_SRC_MASK) == BOOT_SRC_SD) puts("SD\n"); else puts("QSPI\n"); printf("SD1_CLK1 = %s, SD1_CLK2 = %s\n", freq[0], freq[1]); return 0; } int board_init(void) { #ifdef CONFIG_NXP_ESBC /* * In case of Secure Boot, the IBR configures the SMMU * to allow only Secure transactions. * SMMU must be reset in bypass mode. * Set the ClientPD bit and Clear the USFCFG Bit */ u32 val; val = (in_le32(SMMU_SCR0) | SCR0_CLIENTPD_MASK) & ~(SCR0_USFCFG_MASK); out_le32(SMMU_SCR0, val); val = (in_le32(SMMU_NSCR0) | SCR0_CLIENTPD_MASK) & ~(SCR0_USFCFG_MASK); out_le32(SMMU_NSCR0, val); #endif select_i2c_ch_pca9547(I2C_MUX_CH_DEFAULT, 0); return 0; } int board_setup_core_volt(u32 vdd) { return 0; } void config_board_mux(void) { #ifdef CONFIG_HAS_FSL_XHCI_USB struct ccsr_scfg *scfg = (struct ccsr_scfg *)CFG_SYS_FSL_SCFG_ADDR; u32 usb_pwrfault; /* * USB2 is used, configure mux to USB2_DRVVBUS/USB2_PWRFAULT * USB3 is not used, configure mux to IIC4_SCL/IIC4_SDA */ out_be32(&scfg->rcwpmuxcr0, 0x3300); #ifdef CONFIG_HAS_FSL_IIC3 /* IIC3 is used, configure mux to use IIC3_SCL/IIC3/SDA */ out_be32(&scfg->rcwpmuxcr0, 0x0000); #endif out_be32(&scfg->usbdrvvbus_selcr, SCFG_USBDRVVBUS_SELCR_USB1); usb_pwrfault = (SCFG_USBPWRFAULT_DEDICATED << SCFG_USBPWRFAULT_USB3_SHIFT) | (SCFG_USBPWRFAULT_DEDICATED << SCFG_USBPWRFAULT_USB2_SHIFT) | (SCFG_USBPWRFAULT_SHARED << SCFG_USBPWRFAULT_USB1_SHIFT); out_be32(&scfg->usbpwrfault_selcr, usb_pwrfault); #ifndef CONFIG_HAS_FSL_IIC3 /* * LS1046A FRWY board has demultiplexer NX3DV42GU with GPIO3_23 as input * to select I2C3_USB2_SEL_IO * I2C3_USB2_SEL = 0: I2C3_SCL/SDA signals are routed to * I2C3 header (default) * I2C3_USB2_SEL = 1: USB2_DRVVBUS/PWRFAULT signals are routed to * USB2 port * programmed to select USB2 by setting GPIO3_23 output to one */ demux_select_usb2(); #endif #endif set_spi_cs_signal_inactive(); } #ifdef CONFIG_MISC_INIT_R int misc_init_r(void) { config_board_mux(); return 0; } #endif int ft_board_setup(void *blob, struct bd_info *bd) { u64 base[CONFIG_NR_DRAM_BANKS]; u64 size[CONFIG_NR_DRAM_BANKS]; /* fixup DT for the two DDR banks */ base[0] = gd->bd->bi_dram[0].start; size[0] = gd->bd->bi_dram[0].size; base[1] = gd->bd->bi_dram[1].start; size[1] = gd->bd->bi_dram[1].size; fdt_fixup_memory_banks(blob, base, size, 2); ft_cpu_setup(blob, bd); #ifdef CONFIG_SYS_DPAA_FMAN #ifndef CONFIG_DM_ETH fdt_fixup_fman_ethernet(blob); #endif #endif fdt_fixup_icid(blob); return 0; }