// SPDX-License-Identifier: GPL-2.0-or-later /* * (C) Copyright 2022 - Analog Devices, Inc. * * Written and/or maintained by Timesys Corporation * * Contact: Nathan Barrett-Morrison * Contact: Greg Malysa */ #include #include #include #include #include #ifdef CONFIG_SC58X #define RCU0_CTL 0x3108B000 #define RCU0_STAT 0x3108B004 #define RCU0_CRCTL 0x3108B008 #define RCU0_CRSTAT 0x3108B00C #define RCU0_SIDIS 0x3108B010 #define RCU0_MSG_SET 0x3108B064 #elif defined(CONFIG_SC57X) || defined(CONFIG_SC59X) || defined(CONFIG_SC59X_64) #define RCU0_CTL 0x3108C000 #define RCU0_STAT 0x3108C004 #define RCU0_CRCTL 0x3108C008 #define RCU0_CRSTAT 0x3108C00C #define RCU0_SIDIS 0x3108C01C #define RCU0_MSG_SET 0x3108C070 #else #error "No SC5xx SoC CONFIG_ enabled" #endif #define BITP_RCU_STAT_BMODE 8 #define BITM_RCU_STAT_BMODE 0x00000F00 #define REG_ARMPMU0_PMCR 0x31121E04 #define REG_ARMPMU0_PMUSERENR 0x31121E08 #define REG_ARMPMU0_PMLAR 0x31121FB0 DECLARE_GLOBAL_DATA_PTR; void reset_cpu(void) { u32 val = readl(RCU0_CTL); writel(val | 1, RCU0_CTL); } void enable_caches(void) { if (!IS_ENABLED(CONFIG_SYS_DCACHE_OFF)) dcache_enable(); } void sc5xx_enable_ns_sharc_access(uintptr_t securec0_base) { writel(0, securec0_base); writel(0, securec0_base + 0x4); writel(0, securec0_base + 0x8); } void sc5xx_disable_spu0(uintptr_t spu0_start, uintptr_t spu0_end) { for (uintptr_t i = spu0_start; i <= spu0_end; i += 4) writel(0, i); } /** * PMU is only available on armv7 platforms and all share the same location */ void sc5xx_enable_pmu(void) { if (!IS_ENABLED(CONFIG_SC59X_64)) { writel(readl(REG_ARMPMU0_PMUSERENR) | 0x01, REG_ARMPMU0_PMUSERENR); writel(0xc5acce55, REG_ARMPMU0_PMLAR); writel(readl(REG_ARMPMU0_PMCR) | (1 << 1), REG_ARMPMU0_PMCR); } } const char *sc5xx_get_boot_mode(u32 *bmode) { static const char * const bmodes[] = { "JTAG/BOOTROM", "QSPI Master", "QSPI Slave", "UART", "LP0 Slave", "OSPI", #ifdef CONFIG_SC59X_64 "eMMC" #endif }; u32 local_mode; local_mode = (readl(RCU0_STAT) & BITM_RCU_STAT_BMODE) >> BITP_RCU_STAT_BMODE; #if CONFIG_ADI_SPL_FORCE_BMODE != 0 /* * In case we want to force boot sequences such as: * QSPI -> OSPI * QSPI -> eMMC * If this is not set, then we will always try to use the BMODE setting * for both stages... i.e. * QSPI -> QSPI */ // (Don't allow skipping JTAG/UART BMODE settings) if (local_mode != 0 && local_mode != 3) local_mode = CONFIG_ADI_SPL_FORCE_BMODE; #endif *bmode = local_mode; if (local_mode >= 0 && local_mode <= ARRAY_SIZE(bmodes)) return bmodes[local_mode]; return "unknown"; } void print_cpu_id(void) { if (!IS_ENABLED(CONFIG_ARM64)) { u32 cpuid = 0; __asm__ __volatile__("mrc p15, 0, %0, c0, c0, 0" : "=r"(cpuid)); printf("Detected Revision: %d.%d\n", cpuid & 0xf00000 >> 20, cpuid & 0xf); } } int print_cpuinfo(void) { u32 bmode; printf("CPU: ADSP %s (%s boot)\n", CONFIG_LDR_CPU, sc5xx_get_boot_mode(&bmode)); print_cpu_id(); return 0; } void fixup_dp83867_phy(struct phy_device *phydev) { int phy_data = 0; phy_data = phy_read(phydev, MDIO_DEVAD_NONE, 0x32); phy_write(phydev, MDIO_DEVAD_NONE, 0x32, (1 << 7) | phy_data); int cfg3 = 0; #define MII_DP83867_CFG3 (0x1e) /* * Pin INT/PWDN on DP83867 should be configured as an Interrupt Output * instead of a Power-Down Input on ADI SC5XX boards in order to * prevent the signal interference from other peripherals during they * are running at the same time. */ cfg3 = phy_read(phydev, MDIO_DEVAD_NONE, MII_DP83867_CFG3); cfg3 |= (1 << 7); phy_write(phydev, MDIO_DEVAD_NONE, MII_DP83867_CFG3, cfg3); // Mystery second port fixup on ezkits with two PHYs if (CONFIG_DW_PORTS & 2) phy_write(phydev, MDIO_DEVAD_NONE, 0x11, 3); if (IS_ENABLED(CONFIG_ADI_BUG_EZKHW21)) { phydev->advertising &= PHY_BASIC_FEATURES; phydev->speed = SPEED_100; } if (phydev->drv->config) phydev->drv->config(phydev); if (IS_ENABLED(CONFIG_ADI_BUG_EZKHW21)) phy_write(phydev, MDIO_DEVAD_NONE, 0, 0x3100); } int dram_init(void) { gd->ram_size = CFG_SYS_SDRAM_SIZE; return 0; }