/* * Copyright (C) 2017-2020 Alibaba Group Holding Limited * * SPDX-License-Identifier: GPL-2.0+ */ #include #include #include #include #include #include #include #ifdef CONFIG_TARGET_ICE_C910 static phys_addr_t opensbi_addr, dtb_addr; void (*image_entry)(u32, phys_addr_t); extern bootm_headers_t images; static inline void boot_core_vector(void) { /* Set pmp regs */ csr_write(pmpaddr0, 0x0 >> 2 | ((0x100000000 - 1) >> 3)); csr_write(pmpaddr1, 0x3f0000000 >> 2 | ((0x10000000 - 1) >> 3)); csr_write(pmpaddr6, 0x00000000 >> 2 | ((0x10000000 - 1) >> 3)); csr_write(pmpaddr7, 0xffffffffff >> 2); csr_write(pmpcfg0, 0x8898000000001b1f); /* Set cpu regs */ csr_write(CSR_MCOR, 0x70013); csr_write(CSR_MCCR2, 0xe0410009); csr_write(CSR_MHCR, 0x11ff); csr_write(CSR_MXSTATUS, 0x638000); csr_write(CSR_MHINT, 0x16e30c); image_entry(0xdeadbeef, dtb_addr); } static void set_vector_cpu(void) { int node, cpu; const void *blob = (const void *)dtb_addr; node = fdt_path_offset(blob, "/cpus"); if (node < 0) return; for (cpu = fdt_first_subnode(blob, node); cpu >= 0; cpu = fdt_next_subnode(blob, cpu)) { if (!strcmp("okay", fdt_getprop(blob, cpu, "status", NULL))) fdt_status_fail((void *)blob, cpu); else if (!strcmp("fail", fdt_getprop(blob, cpu, "status", NULL))) fdt_status_okay((void *)blob, cpu); } } static void prep_core_vector(void) { printf("Boot vector core(cpu2) only\n"); dtb_addr = (phys_addr_t)images.ft_addr; opensbi_addr = simple_strtol(env_get("opensbi_addr"), NULL, 0); image_entry = (void (*)(u32, phys_addr_t))(opensbi_addr); set_vector_cpu(); csr_write(mrvbr, &boot_core_vector); csr_write(mrmr, 0x5); while (1); } #endif /* * cleanup_before_linux() is called just before we call linux * it prepares the processor for linux * * we disable interrupt and caches. */ int cleanup_before_linux(void) { cache_flush(); #ifdef CONFIG_TARGET_ICE_C910 if ((simple_strtol(env_get("boot_vector"), NULL, 0)) == 1) prep_core_vector(); #endif return 0; } void flush_dcache_range(unsigned long start, unsigned long end) { register unsigned long i asm("a0") = start & ~(CONFIG_SYS_CACHELINE_SIZE - 1); for (; i < end; i += CONFIG_SYS_CACHELINE_SIZE) asm volatile(".long 0x0295000b"); /* dcache.cpa a0 */ sync_is(); } void invalidate_dcache_range(unsigned long start, unsigned long end) { register unsigned long i asm("a0") = start & ~(CONFIG_SYS_CACHELINE_SIZE - 1); for (; i < end; i += CONFIG_SYS_CACHELINE_SIZE) asm volatile(".long 0x02b5000b"); /* dcache.cipa a0 */ sync_is(); } void invalid_dcache_range(unsigned long start, unsigned long end) { register unsigned long i asm("a0") = start & ~(CONFIG_SYS_CACHELINE_SIZE - 1); for (; i < end; i += CONFIG_SYS_CACHELINE_SIZE) asm volatile(".long 0x02a5000b"); /* dcache.ipa a0 */ sync_is(); } void icache_enable(void) { #ifdef CONFIG_SPL_BUILD #ifdef CONFIG_SPL_RISCV_MMODE #ifdef CONFIG_TARGET_LIGHT_C910 // mhcr is 0x7c1 asm volatile ( "csrr x29, 0x7c1\n\t" "ori x28, x29, 0x1\n\t" "csrw 0x7c1, x28\n\t" ); #endif #endif #endif } void dcache_enable(void) { #ifdef CONFIG_SPL_BUILD #ifdef CONFIG_SPL_RISCV_MMODE #ifdef CONFIG_TARGET_LIGHT_C910 asm volatile ( "csrr x29, 0x7c1\n\t" "ori x28, x29, 0x2\n\t" "csrw 0x7c1, x28\n\t" ); #endif #endif #endif }