1350b50eeSStefan Roese /* 29c6d3b7bSStefan Roese * Copyright (C) 2014-2015 Stefan Roese <sr@denx.de> 3350b50eeSStefan Roese * 4350b50eeSStefan Roese * SPDX-License-Identifier: GPL-2.0+ 5350b50eeSStefan Roese */ 6350b50eeSStefan Roese 7350b50eeSStefan Roese #include <common.h> 8350b50eeSStefan Roese #include <netdev.h> 94d991cb3SStefan Roese #include <ahci.h> 104d991cb3SStefan Roese #include <linux/mbus.h> 11350b50eeSStefan Roese #include <asm/io.h> 125730360eSStefan Roese #include <asm/pl310.h> 13350b50eeSStefan Roese #include <asm/arch/cpu.h> 14350b50eeSStefan Roese #include <asm/arch/soc.h> 157f1adcd7SStefan Roese #include <sdhci.h> 16350b50eeSStefan Roese 17350b50eeSStefan Roese #define DDR_BASE_CS_OFF(n) (0x0000 + ((n) << 3)) 18350b50eeSStefan Roese #define DDR_SIZE_CS_OFF(n) (0x0004 + ((n) << 3)) 19350b50eeSStefan Roese 20350b50eeSStefan Roese static struct mbus_win windows[] = { 21350b50eeSStefan Roese /* PCIE MEM address space */ 228ed20d65SStefan Roese { MBUS_PCI_MEM_BASE, MBUS_PCI_MEM_SIZE, 238ed20d65SStefan Roese CPU_TARGET_PCIE13, CPU_ATTR_PCIE_MEM }, 24350b50eeSStefan Roese 25350b50eeSStefan Roese /* PCIE IO address space */ 268ed20d65SStefan Roese { MBUS_PCI_IO_BASE, MBUS_PCI_IO_SIZE, 278ed20d65SStefan Roese CPU_TARGET_PCIE13, CPU_ATTR_PCIE_IO }, 28350b50eeSStefan Roese 29350b50eeSStefan Roese /* SPI */ 308ed20d65SStefan Roese { MBUS_SPI_BASE, MBUS_SPI_SIZE, 318ed20d65SStefan Roese CPU_TARGET_DEVICEBUS_BOOTROM_SPI, CPU_ATTR_SPIFLASH }, 32350b50eeSStefan Roese 33350b50eeSStefan Roese /* NOR */ 348ed20d65SStefan Roese { MBUS_BOOTROM_BASE, MBUS_BOOTROM_SIZE, 358ed20d65SStefan Roese CPU_TARGET_DEVICEBUS_BOOTROM_SPI, CPU_ATTR_BOOTROM }, 36350b50eeSStefan Roese }; 37350b50eeSStefan Roese 38350b50eeSStefan Roese void reset_cpu(unsigned long ignored) 39350b50eeSStefan Roese { 40350b50eeSStefan Roese struct mvebu_system_registers *reg = 41350b50eeSStefan Roese (struct mvebu_system_registers *)MVEBU_SYSTEM_REG_BASE; 42350b50eeSStefan Roese 43350b50eeSStefan Roese writel(readl(®->rstoutn_mask) | 1, ®->rstoutn_mask); 44350b50eeSStefan Roese writel(readl(®->sys_soft_rst) | 1, ®->sys_soft_rst); 45350b50eeSStefan Roese while (1) 46350b50eeSStefan Roese ; 47350b50eeSStefan Roese } 48350b50eeSStefan Roese 499c6d3b7bSStefan Roese int mvebu_soc_family(void) 509c6d3b7bSStefan Roese { 519c6d3b7bSStefan Roese u16 devid = (readl(MVEBU_REG_PCIE_DEVID) >> 16) & 0xffff; 529c6d3b7bSStefan Roese 539c6d3b7bSStefan Roese if (devid == SOC_MV78460_ID) 549c6d3b7bSStefan Roese return MVEBU_SOC_AXP; 559c6d3b7bSStefan Roese 569c6d3b7bSStefan Roese if (devid == SOC_88F6810_ID || devid == SOC_88F6820_ID || 579c6d3b7bSStefan Roese devid == SOC_88F6828_ID) 589c6d3b7bSStefan Roese return MVEBU_SOC_A38X; 599c6d3b7bSStefan Roese 609c6d3b7bSStefan Roese return MVEBU_SOC_UNKNOWN; 619c6d3b7bSStefan Roese } 629c6d3b7bSStefan Roese 63350b50eeSStefan Roese #if defined(CONFIG_DISPLAY_CPUINFO) 64350b50eeSStefan Roese int print_cpuinfo(void) 65350b50eeSStefan Roese { 66350b50eeSStefan Roese u16 devid = (readl(MVEBU_REG_PCIE_DEVID) >> 16) & 0xffff; 67350b50eeSStefan Roese u8 revid = readl(MVEBU_REG_PCIE_REVID) & 0xff; 68350b50eeSStefan Roese 69350b50eeSStefan Roese puts("SoC: "); 70350b50eeSStefan Roese 71350b50eeSStefan Roese switch (devid) { 72350b50eeSStefan Roese case SOC_MV78460_ID: 73350b50eeSStefan Roese puts("MV78460-"); 74350b50eeSStefan Roese break; 759c6d3b7bSStefan Roese case SOC_88F6810_ID: 769c6d3b7bSStefan Roese puts("MV88F6810-"); 779c6d3b7bSStefan Roese break; 789c6d3b7bSStefan Roese case SOC_88F6820_ID: 799c6d3b7bSStefan Roese puts("MV88F6820-"); 809c6d3b7bSStefan Roese break; 819c6d3b7bSStefan Roese case SOC_88F6828_ID: 829c6d3b7bSStefan Roese puts("MV88F6828-"); 839c6d3b7bSStefan Roese break; 84350b50eeSStefan Roese default: 85350b50eeSStefan Roese puts("Unknown-"); 86350b50eeSStefan Roese break; 87350b50eeSStefan Roese } 88350b50eeSStefan Roese 899c6d3b7bSStefan Roese if (mvebu_soc_family() == MVEBU_SOC_AXP) { 90350b50eeSStefan Roese switch (revid) { 91350b50eeSStefan Roese case 1: 92350b50eeSStefan Roese puts("A0\n"); 93350b50eeSStefan Roese break; 94350b50eeSStefan Roese case 2: 95350b50eeSStefan Roese puts("B0\n"); 96350b50eeSStefan Roese break; 97350b50eeSStefan Roese default: 989c6d3b7bSStefan Roese printf("?? (%x)\n", revid); 99350b50eeSStefan Roese break; 100350b50eeSStefan Roese } 1019c6d3b7bSStefan Roese } 1029c6d3b7bSStefan Roese 1039c6d3b7bSStefan Roese if (mvebu_soc_family() == MVEBU_SOC_A38X) { 1049c6d3b7bSStefan Roese switch (revid) { 1059c6d3b7bSStefan Roese case MV_88F68XX_Z1_ID: 1069c6d3b7bSStefan Roese puts("Z1\n"); 1079c6d3b7bSStefan Roese break; 1089c6d3b7bSStefan Roese case MV_88F68XX_A0_ID: 1099c6d3b7bSStefan Roese puts("A0\n"); 1109c6d3b7bSStefan Roese break; 1119c6d3b7bSStefan Roese default: 1129c6d3b7bSStefan Roese printf("?? (%x)\n", revid); 1139c6d3b7bSStefan Roese break; 1149c6d3b7bSStefan Roese } 1159c6d3b7bSStefan Roese } 116350b50eeSStefan Roese 117350b50eeSStefan Roese return 0; 118350b50eeSStefan Roese } 119350b50eeSStefan Roese #endif /* CONFIG_DISPLAY_CPUINFO */ 120350b50eeSStefan Roese 121350b50eeSStefan Roese /* 122350b50eeSStefan Roese * This function initialize Controller DRAM Fastpath windows. 123350b50eeSStefan Roese * It takes the CS size information from the 0x1500 scratch registers 124350b50eeSStefan Roese * and sets the correct windows sizes and base addresses accordingly. 125350b50eeSStefan Roese * 126350b50eeSStefan Roese * These values are set in the scratch registers by the Marvell 127350b50eeSStefan Roese * DDR3 training code, which is executed by the BootROM before the 128350b50eeSStefan Roese * main payload (U-Boot) is executed. This training code is currently 129350b50eeSStefan Roese * only available in the Marvell U-Boot version. It needs to be 130350b50eeSStefan Roese * ported to mainline U-Boot SPL at some point. 131350b50eeSStefan Roese */ 132350b50eeSStefan Roese static void update_sdram_window_sizes(void) 133350b50eeSStefan Roese { 134350b50eeSStefan Roese u64 base = 0; 135350b50eeSStefan Roese u32 size, temp; 136350b50eeSStefan Roese int i; 137350b50eeSStefan Roese 138350b50eeSStefan Roese for (i = 0; i < SDRAM_MAX_CS; i++) { 139350b50eeSStefan Roese size = readl((MVEBU_SDRAM_SCRATCH + (i * 8))) & SDRAM_ADDR_MASK; 140350b50eeSStefan Roese if (size != 0) { 141350b50eeSStefan Roese size |= ~(SDRAM_ADDR_MASK); 142350b50eeSStefan Roese 143350b50eeSStefan Roese /* Set Base Address */ 144350b50eeSStefan Roese temp = (base & 0xFF000000ll) | ((base >> 32) & 0xF); 145350b50eeSStefan Roese writel(temp, MVEBU_SDRAM_BASE + DDR_BASE_CS_OFF(i)); 146350b50eeSStefan Roese 147350b50eeSStefan Roese /* 148350b50eeSStefan Roese * Check if out of max window size and resize 149350b50eeSStefan Roese * the window 150350b50eeSStefan Roese */ 151350b50eeSStefan Roese temp = (readl(MVEBU_SDRAM_BASE + DDR_SIZE_CS_OFF(i)) & 152350b50eeSStefan Roese ~(SDRAM_ADDR_MASK)) | 1; 153350b50eeSStefan Roese temp |= (size & SDRAM_ADDR_MASK); 154350b50eeSStefan Roese writel(temp, MVEBU_SDRAM_BASE + DDR_SIZE_CS_OFF(i)); 155350b50eeSStefan Roese 156350b50eeSStefan Roese base += ((u64)size + 1); 157350b50eeSStefan Roese } else { 158350b50eeSStefan Roese /* 159350b50eeSStefan Roese * Disable window if not used, otherwise this 160350b50eeSStefan Roese * leads to overlapping enabled windows with 161350b50eeSStefan Roese * pretty strange results 162350b50eeSStefan Roese */ 163350b50eeSStefan Roese clrbits_le32(MVEBU_SDRAM_BASE + DDR_SIZE_CS_OFF(i), 1); 164350b50eeSStefan Roese } 165350b50eeSStefan Roese } 166350b50eeSStefan Roese } 167350b50eeSStefan Roese 1689f62b44eSStefan Roese void mmu_disable(void) 1699f62b44eSStefan Roese { 1709f62b44eSStefan Roese asm volatile( 1719f62b44eSStefan Roese "mrc p15, 0, r0, c1, c0, 0\n" 1729f62b44eSStefan Roese "bic r0, #1\n" 1739f62b44eSStefan Roese "mcr p15, 0, r0, c1, c0, 0\n"); 1749f62b44eSStefan Roese } 1759f62b44eSStefan Roese 176350b50eeSStefan Roese #ifdef CONFIG_ARCH_CPU_INIT 177e1b078e0SKevin Smith static void set_cbar(u32 addr) 178e1b078e0SKevin Smith { 179e1b078e0SKevin Smith asm("mcr p15, 4, %0, c15, c0" : : "r" (addr)); 180e1b078e0SKevin Smith } 181e1b078e0SKevin Smith 182e1b078e0SKevin Smith 183350b50eeSStefan Roese int arch_cpu_init(void) 184350b50eeSStefan Roese { 1859f62b44eSStefan Roese #ifndef CONFIG_SPL_BUILD 1862b181b5bSStefan Roese if (mvebu_soc_family() == MVEBU_SOC_A38X) { 1872b181b5bSStefan Roese struct pl310_regs *const pl310 = 1882b181b5bSStefan Roese (struct pl310_regs *)CONFIG_SYS_PL310_BASE; 1892b181b5bSStefan Roese 1909f62b44eSStefan Roese /* 1919f62b44eSStefan Roese * Only with disabled MMU its possible to switch the base 1929f62b44eSStefan Roese * register address on Armada 38x. Without this the SDRAM 1939f62b44eSStefan Roese * located at >= 0x4000.0000 is also not accessible, as its 1949f62b44eSStefan Roese * still locked to cache. 1952b181b5bSStefan Roese * 1962b181b5bSStefan Roese * So to fully release / unlock this area from cache, we need 1972b181b5bSStefan Roese * to first flush all caches, then disable the MMU and 1982b181b5bSStefan Roese * disable the L2 cache. 1999f62b44eSStefan Roese */ 2002b181b5bSStefan Roese icache_disable(); 2012b181b5bSStefan Roese dcache_disable(); 2029f62b44eSStefan Roese mmu_disable(); 2032b181b5bSStefan Roese clrbits_le32(&pl310->pl310_ctrl, L2X0_CTRL_EN); 2042b181b5bSStefan Roese } 2059f62b44eSStefan Roese #endif 2069f62b44eSStefan Roese 207350b50eeSStefan Roese /* Linux expects the internal registers to be at 0xf1000000 */ 208350b50eeSStefan Roese writel(SOC_REGS_PHY_BASE, INTREG_BASE_ADDR_REG); 209e1b078e0SKevin Smith set_cbar(SOC_REGS_PHY_BASE + 0xC000); 210350b50eeSStefan Roese 211350b50eeSStefan Roese /* 212350b50eeSStefan Roese * We need to call mvebu_mbus_probe() before calling 213350b50eeSStefan Roese * update_sdram_window_sizes() as it disables all previously 214350b50eeSStefan Roese * configured mbus windows and then configures them as 215350b50eeSStefan Roese * required for U-Boot. Calling update_sdram_window_sizes() 216350b50eeSStefan Roese * without this configuration will not work, as the internal 217350b50eeSStefan Roese * registers can't be accessed reliably because of potenial 218350b50eeSStefan Roese * double mapping. 219350b50eeSStefan Roese * After updating the SDRAM access windows we need to call 220350b50eeSStefan Roese * mvebu_mbus_probe() again, as this now correctly configures 221350b50eeSStefan Roese * the SDRAM areas that are later used by the MVEBU drivers 222350b50eeSStefan Roese * (e.g. USB, NETA). 223350b50eeSStefan Roese */ 224350b50eeSStefan Roese 225350b50eeSStefan Roese /* 226350b50eeSStefan Roese * First disable all windows 227350b50eeSStefan Roese */ 228350b50eeSStefan Roese mvebu_mbus_probe(NULL, 0); 229350b50eeSStefan Roese 2309c6d3b7bSStefan Roese if (mvebu_soc_family() == MVEBU_SOC_AXP) { 231350b50eeSStefan Roese /* 232350b50eeSStefan Roese * Now the SDRAM access windows can be reconfigured using 233350b50eeSStefan Roese * the information in the SDRAM scratch pad registers 234350b50eeSStefan Roese */ 235350b50eeSStefan Roese update_sdram_window_sizes(); 2369c6d3b7bSStefan Roese } 237350b50eeSStefan Roese 238350b50eeSStefan Roese /* 239350b50eeSStefan Roese * Finally the mbus windows can be configured with the 240350b50eeSStefan Roese * updated SDRAM sizes 241350b50eeSStefan Roese */ 242350b50eeSStefan Roese mvebu_mbus_probe(windows, ARRAY_SIZE(windows)); 243350b50eeSStefan Roese 244*2a0b7dc3SStefan Roese if (mvebu_soc_family() == MVEBU_SOC_AXP) { 245*2a0b7dc3SStefan Roese /* Enable GBE0, GBE1, LCD and NFC PUP */ 246*2a0b7dc3SStefan Roese clrsetbits_le32(ARMADA_XP_PUP_ENABLE, 0, 247*2a0b7dc3SStefan Roese GE0_PUP_EN | GE1_PUP_EN | LCD_PUP_EN | 248*2a0b7dc3SStefan Roese NAND_PUP_EN | SPI_PUP_EN); 249*2a0b7dc3SStefan Roese } 250*2a0b7dc3SStefan Roese 251*2a0b7dc3SStefan Roese /* Enable NAND and NAND arbiter */ 252*2a0b7dc3SStefan Roese clrsetbits_le32(MVEBU_SOC_DEV_MUX_REG, 0, NAND_EN | NAND_ARBITER_EN); 253*2a0b7dc3SStefan Roese 254501c098aSStefan Roese /* Disable MBUS error propagation */ 255501c098aSStefan Roese clrsetbits_le32(SOC_COHERENCY_FABRIC_CTRL_REG, MBUS_ERR_PROP_EN, 0); 256501c098aSStefan Roese 257350b50eeSStefan Roese return 0; 258350b50eeSStefan Roese } 259350b50eeSStefan Roese #endif /* CONFIG_ARCH_CPU_INIT */ 260350b50eeSStefan Roese 261*2a0b7dc3SStefan Roese u32 mvebu_get_nand_clock(void) 262*2a0b7dc3SStefan Roese { 263*2a0b7dc3SStefan Roese return CONFIG_SYS_MVEBU_PLL_CLOCK / 264*2a0b7dc3SStefan Roese ((readl(MVEBU_CORE_DIV_CLK_CTRL(1)) & 265*2a0b7dc3SStefan Roese NAND_ECC_DIVCKL_RATIO_MASK) >> NAND_ECC_DIVCKL_RATIO_OFFS); 266*2a0b7dc3SStefan Roese } 267*2a0b7dc3SStefan Roese 268350b50eeSStefan Roese /* 269350b50eeSStefan Roese * SOC specific misc init 270350b50eeSStefan Roese */ 271350b50eeSStefan Roese #if defined(CONFIG_ARCH_MISC_INIT) 272350b50eeSStefan Roese int arch_misc_init(void) 273350b50eeSStefan Roese { 274350b50eeSStefan Roese /* Nothing yet, perhaps we need something here later */ 275350b50eeSStefan Roese return 0; 276350b50eeSStefan Roese } 277350b50eeSStefan Roese #endif /* CONFIG_ARCH_MISC_INIT */ 278350b50eeSStefan Roese 279350b50eeSStefan Roese #ifdef CONFIG_MVNETA 280350b50eeSStefan Roese int cpu_eth_init(bd_t *bis) 281350b50eeSStefan Roese { 282cae9008fSStefan Roese u32 enet_base[] = { MVEBU_EGIGA0_BASE, MVEBU_EGIGA1_BASE, 283cae9008fSStefan Roese MVEBU_EGIGA2_BASE, MVEBU_EGIGA3_BASE }; 284cae9008fSStefan Roese u8 phy_addr[] = CONFIG_PHY_ADDR; 285cae9008fSStefan Roese int i; 286cae9008fSStefan Roese 287cae9008fSStefan Roese /* 288cae9008fSStefan Roese * Only Armada XP supports all 4 ethernet interfaces. A38x has 289cae9008fSStefan Roese * slightly different base addresses for its 2-3 interfaces. 290cae9008fSStefan Roese */ 291cae9008fSStefan Roese if (mvebu_soc_family() != MVEBU_SOC_AXP) { 292cae9008fSStefan Roese enet_base[1] = MVEBU_EGIGA2_BASE; 293cae9008fSStefan Roese enet_base[2] = MVEBU_EGIGA3_BASE; 294cae9008fSStefan Roese } 295cae9008fSStefan Roese 296cae9008fSStefan Roese for (i = 0; i < ARRAY_SIZE(phy_addr); i++) 297cae9008fSStefan Roese mvneta_initialize(bis, enet_base[i], i, phy_addr[i]); 298350b50eeSStefan Roese 299350b50eeSStefan Roese return 0; 300350b50eeSStefan Roese } 301350b50eeSStefan Roese #endif 302350b50eeSStefan Roese 3037f1adcd7SStefan Roese #ifdef CONFIG_MV_SDHCI 3047f1adcd7SStefan Roese int board_mmc_init(bd_t *bis) 3057f1adcd7SStefan Roese { 3067f1adcd7SStefan Roese mv_sdh_init(MVEBU_SDIO_BASE, 0, 0, 3077f1adcd7SStefan Roese SDHCI_QUIRK_32BIT_DMA_ADDR | SDHCI_QUIRK_WAIT_SEND_CMD); 3087f1adcd7SStefan Roese 3097f1adcd7SStefan Roese return 0; 3107f1adcd7SStefan Roese } 3117f1adcd7SStefan Roese #endif 3127f1adcd7SStefan Roese 3134d991cb3SStefan Roese #ifdef CONFIG_SCSI_AHCI_PLAT 3144d991cb3SStefan Roese #define AHCI_VENDOR_SPECIFIC_0_ADDR 0xa0 3154d991cb3SStefan Roese #define AHCI_VENDOR_SPECIFIC_0_DATA 0xa4 3164d991cb3SStefan Roese 3174d991cb3SStefan Roese #define AHCI_WINDOW_CTRL(win) (0x60 + ((win) << 4)) 3184d991cb3SStefan Roese #define AHCI_WINDOW_BASE(win) (0x64 + ((win) << 4)) 3194d991cb3SStefan Roese #define AHCI_WINDOW_SIZE(win) (0x68 + ((win) << 4)) 3204d991cb3SStefan Roese 3214d991cb3SStefan Roese static void ahci_mvebu_mbus_config(void __iomem *base) 3224d991cb3SStefan Roese { 3234d991cb3SStefan Roese const struct mbus_dram_target_info *dram; 3244d991cb3SStefan Roese int i; 3254d991cb3SStefan Roese 3264d991cb3SStefan Roese dram = mvebu_mbus_dram_info(); 3274d991cb3SStefan Roese 3284d991cb3SStefan Roese for (i = 0; i < 4; i++) { 3294d991cb3SStefan Roese writel(0, base + AHCI_WINDOW_CTRL(i)); 3304d991cb3SStefan Roese writel(0, base + AHCI_WINDOW_BASE(i)); 3314d991cb3SStefan Roese writel(0, base + AHCI_WINDOW_SIZE(i)); 3324d991cb3SStefan Roese } 3334d991cb3SStefan Roese 3344d991cb3SStefan Roese for (i = 0; i < dram->num_cs; i++) { 3354d991cb3SStefan Roese const struct mbus_dram_window *cs = dram->cs + i; 3364d991cb3SStefan Roese 3374d991cb3SStefan Roese writel((cs->mbus_attr << 8) | 3384d991cb3SStefan Roese (dram->mbus_dram_target_id << 4) | 1, 3394d991cb3SStefan Roese base + AHCI_WINDOW_CTRL(i)); 3404d991cb3SStefan Roese writel(cs->base >> 16, base + AHCI_WINDOW_BASE(i)); 3414d991cb3SStefan Roese writel(((cs->size - 1) & 0xffff0000), 3424d991cb3SStefan Roese base + AHCI_WINDOW_SIZE(i)); 3434d991cb3SStefan Roese } 3444d991cb3SStefan Roese } 3454d991cb3SStefan Roese 3464d991cb3SStefan Roese static void ahci_mvebu_regret_option(void __iomem *base) 3474d991cb3SStefan Roese { 3484d991cb3SStefan Roese /* 3494d991cb3SStefan Roese * Enable the regret bit to allow the SATA unit to regret a 3504d991cb3SStefan Roese * request that didn't receive an acknowlegde and avoid a 3514d991cb3SStefan Roese * deadlock 3524d991cb3SStefan Roese */ 3534d991cb3SStefan Roese writel(0x4, base + AHCI_VENDOR_SPECIFIC_0_ADDR); 3544d991cb3SStefan Roese writel(0x80, base + AHCI_VENDOR_SPECIFIC_0_DATA); 3554d991cb3SStefan Roese } 3564d991cb3SStefan Roese 3574d991cb3SStefan Roese void scsi_init(void) 3584d991cb3SStefan Roese { 3594d991cb3SStefan Roese printf("MVEBU SATA INIT\n"); 3604d991cb3SStefan Roese ahci_mvebu_mbus_config((void __iomem *)MVEBU_SATA0_BASE); 3614d991cb3SStefan Roese ahci_mvebu_regret_option((void __iomem *)MVEBU_SATA0_BASE); 3624d991cb3SStefan Roese ahci_init((void __iomem *)MVEBU_SATA0_BASE); 3634d991cb3SStefan Roese } 3644d991cb3SStefan Roese #endif 3654d991cb3SStefan Roese 366350b50eeSStefan Roese #ifndef CONFIG_SYS_DCACHE_OFF 367350b50eeSStefan Roese void enable_caches(void) 368350b50eeSStefan Roese { 3695730360eSStefan Roese struct pl310_regs *const pl310 = 3705730360eSStefan Roese (struct pl310_regs *)CONFIG_SYS_PL310_BASE; 3715730360eSStefan Roese 3725730360eSStefan Roese /* First disable L2 cache - may still be enable from BootROM */ 3735730360eSStefan Roese if (mvebu_soc_family() == MVEBU_SOC_A38X) 3745730360eSStefan Roese clrbits_le32(&pl310->pl310_ctrl, L2X0_CTRL_EN); 3755730360eSStefan Roese 37660b75324SStefan Roese /* Avoid problem with e.g. neta ethernet driver */ 37760b75324SStefan Roese invalidate_dcache_all(); 37860b75324SStefan Roese 379350b50eeSStefan Roese /* Enable D-cache. I-cache is already enabled in start.S */ 380350b50eeSStefan Roese dcache_enable(); 381350b50eeSStefan Roese } 382350b50eeSStefan Roese #endif 383