diff options
Diffstat (limited to 'board/renesas/rcar-common')
-rw-r--r-- | board/renesas/rcar-common/common.c | 200 | ||||
-rw-r--r-- | board/renesas/rcar-common/gen3-common.c | 185 | ||||
-rw-r--r-- | board/renesas/rcar-common/gen4-common.c | 90 | ||||
-rw-r--r-- | board/renesas/rcar-common/gen4-spl.c | 119 |
4 files changed, 422 insertions, 172 deletions
diff --git a/board/renesas/rcar-common/common.c b/board/renesas/rcar-common/common.c index 499c31408f6..90eb468e4c4 100644 --- a/board/renesas/rcar-common/common.c +++ b/board/renesas/rcar-common/common.c @@ -15,201 +15,57 @@ #include <asm/io.h> #include <dm/uclass-internal.h> #include <asm/arch/renesas.h> +#include <asm/system.h> #include <linux/libfdt.h> #ifdef CONFIG_RCAR_64 DECLARE_GLOBAL_DATA_PTR; -/* If the firmware passed a device tree use it for e.g. U-Boot DRAM setup. */ -extern u64 rcar_atf_boot_args[]; - -#define FDT_RPC_PATH "/soc/spi@ee200000" - -static void apply_atf_overlay(void *fdt_blob) -{ - void *atf_fdt_blob = (void *)(rcar_atf_boot_args[1]); - - if (fdt_magic(atf_fdt_blob) == FDT_MAGIC) - fdt_overlay_apply_node(fdt_blob, 0, atf_fdt_blob, 0); -} - -int fdtdec_board_setup(const void *fdt_blob) -{ - apply_atf_overlay((void *)fdt_blob); - - return 0; -} - int dram_init(void) { - return fdtdec_setup_mem_size_base(); -} - -int dram_init_banksize(void) -{ - fdtdec_setup_memory_banksize(); - - return 0; -} - -int __weak board_init(void) -{ - return 0; -} - -#if defined(CONFIG_RCAR_GEN3) -#define RST_BASE 0xE6160000 -#define RST_CA57RESCNT (RST_BASE + 0x40) -#define RST_CA53RESCNT (RST_BASE + 0x44) -#define RST_RSTOUTCR (RST_BASE + 0x58) -#define RST_CA57_CODE 0xA5A5000F -#define RST_CA53_CODE 0x5A5A000F - -void __weak reset_cpu(void) -{ - unsigned long midr, cputype; - - asm volatile("mrs %0, midr_el1" : "=r" (midr)); - cputype = (midr >> 4) & 0xfff; - - if (cputype == 0xd03) - writel(RST_CA53_CODE, RST_CA53RESCNT); - else if (cputype == 0xd07) - writel(RST_CA57_CODE, RST_CA57RESCNT); - else - hang(); -} -#elif defined(CONFIG_RCAR_GEN4) -#define RST_BASE 0xE6160000 /* Domain0 */ -#define RST_SRESCR0 (RST_BASE + 0x18) -#define RST_SPRES 0x5AA58000 - -void __weak reset_cpu(void) -{ - writel(RST_SPRES, RST_SRESCR0); -} -#else -#error Neither CONFIG_RCAR_GEN3 nor CONFIG_RCAR_GEN4 are set -#endif - -#if defined(CONFIG_OF_BOARD_SETUP) -static int is_mem_overlap(void *blob, int first_mem_node, int curr_mem_node) -{ - struct fdt_resource first_mem_res, curr_mem_res; - int curr_mem_reg, first_mem_reg = 0; - int ret; - - for (;;) { - ret = fdt_get_resource(blob, first_mem_node, "reg", - first_mem_reg++, &first_mem_res); - if (ret) /* No more entries, no overlap found */ - return 0; - - curr_mem_reg = 0; - for (;;) { - ret = fdt_get_resource(blob, curr_mem_node, "reg", - curr_mem_reg++, &curr_mem_res); - if (ret) /* No more entries, check next tuple */ - break; - - if (curr_mem_res.end < first_mem_res.start) - continue; - - if (curr_mem_res.start >= first_mem_res.end) - continue; - - log_debug("Overlap found: 0x%llx..0x%llx / 0x%llx..0x%llx\n", - first_mem_res.start, first_mem_res.end, - curr_mem_res.start, curr_mem_res.end); - - return 1; - } + int ret = fdtdec_setup_mem_size_base(); + + if (current_el() == 3 && gd->ram_base == 0x48000000) { + /* + * If this U-Boot runs in EL3, make the bottom 128 MiB + * available for loading of follow up firmware blobs. + */ + gd->ram_base -= 0x8000000; + gd->ram_size += 0x8000000; } - return 0; + return ret; } -static void scrub_duplicate_memory(void *blob) +int dram_init_banksize(void) { - /* - * Scrub duplicate /memory@* node entries here. Some R-Car DTs might - * contain multiple /memory@* nodes, however fdt_fixup_memory_banks() - * either generates single /memory node or updates the first /memory - * node. Any remaining memory nodes are thus potential duplicates. - * - * However, it is not possible to delete all the memory nodes right - * away, since some of those might not be DRAM memory nodes, but some - * sort of other memory. Thus, delete only the memory nodes which are - * in the R-Car3 DBSC ranges. - */ - int mem = 0, first_mem_node = 0; + int bank; - for (;;) { - mem = fdt_node_offset_by_prop_value(blob, mem, - "device_type", "memory", 7); - if (mem < 0) - break; - if (!fdtdec_get_is_enabled(blob, mem)) - continue; + fdtdec_setup_memory_banksize(); - /* First memory node, patched by U-Boot */ - if (!first_mem_node) { - first_mem_node = mem; - continue; - } + if (current_el() != 3) + return 0; - /* Check the remaining nodes and delete duplicates */ - if (!is_mem_overlap(blob, first_mem_node, mem)) + for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) { + if (gd->bd->bi_dram[bank].start != 0x48000000) continue; - /* Delete duplicate node, start again */ - fdt_del_node(blob, mem); - first_mem_node = 0; - mem = 0; + /* + * If this U-Boot runs in EL3, make the bottom 128 MiB + * available for loading of follow up firmware blobs. + */ + gd->bd->bi_dram[bank].start -= 0x8000000; + gd->bd->bi_dram[bank].size += 0x8000000; + break; } -} - -static void update_rpc_status(void *blob) -{ - void *atf_fdt_blob = (void *)(rcar_atf_boot_args[1]); - int offset, enabled; - - /* - * Check if the DT fragment received from TF-A had its RPC-IF device node - * enabled. - */ - if (fdt_magic(atf_fdt_blob) != FDT_MAGIC) - return; - - offset = fdt_path_offset(atf_fdt_blob, FDT_RPC_PATH); - if (offset < 0) - return; - - enabled = fdtdec_get_is_enabled(atf_fdt_blob, offset); - if (!enabled) - return; - /* - * Find the RPC-IF device node, and enable it if it has a flash subnode. - */ - offset = fdt_path_offset(blob, FDT_RPC_PATH); - if (offset < 0) - return; - - if (fdt_subnode_offset(blob, offset, "flash") < 0) - return; - - fdt_status_okay(blob, offset); + return 0; } -int ft_board_setup(void *blob, struct bd_info *bd) +int __weak board_init(void) { - apply_atf_overlay(blob); - scrub_duplicate_memory(blob); - update_rpc_status(blob); - return 0; } -#endif + #endif diff --git a/board/renesas/rcar-common/gen3-common.c b/board/renesas/rcar-common/gen3-common.c new file mode 100644 index 00000000000..4291e1d5bcb --- /dev/null +++ b/board/renesas/rcar-common/gen3-common.c @@ -0,0 +1,185 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * board/renesas/rcar-common/gen3-common.c + * + * Copyright (C) 2013 Renesas Electronics Corporation + * Copyright (C) 2013 Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com> + * Copyright (C) 2015 Nobuhiro Iwamatsu <iwamatsu@nigauri.org> + */ + +#include <dm.h> +#include <fdt_support.h> +#include <hang.h> +#include <init.h> +#include <asm/global_data.h> +#include <asm/io.h> +#include <dm/uclass-internal.h> +#include <asm/arch/renesas.h> +#include <linux/libfdt.h> + +#ifdef CONFIG_RCAR_64 + +DECLARE_GLOBAL_DATA_PTR; + +/* If the firmware passed a device tree use it for e.g. U-Boot DRAM setup. */ +extern u64 rcar_atf_boot_args[]; + +#define FDT_RPC_PATH "/soc/spi@ee200000" + +static void apply_atf_overlay(void *fdt_blob) +{ + void *atf_fdt_blob = (void *)(rcar_atf_boot_args[1]); + + if (fdt_magic(atf_fdt_blob) == FDT_MAGIC) + fdt_overlay_apply_node(fdt_blob, 0, atf_fdt_blob, 0); +} + +int fdtdec_board_setup(const void *fdt_blob) +{ + apply_atf_overlay((void *)fdt_blob); + + return 0; +} + +#define RST_BASE 0xE6160000 +#define RST_CA57RESCNT (RST_BASE + 0x40) +#define RST_CA53RESCNT (RST_BASE + 0x44) +#define RST_RSTOUTCR (RST_BASE + 0x58) +#define RST_CA57_CODE 0xA5A5000F +#define RST_CA53_CODE 0x5A5A000F + +void __weak reset_cpu(void) +{ + unsigned long midr, cputype; + + asm volatile("mrs %0, midr_el1" : "=r" (midr)); + cputype = (midr >> 4) & 0xfff; + + if (cputype == 0xd03) + writel(RST_CA53_CODE, RST_CA53RESCNT); + else if (cputype == 0xd07) + writel(RST_CA57_CODE, RST_CA57RESCNT); + else + hang(); +} + +#if defined(CONFIG_OF_BOARD_SETUP) +static int is_mem_overlap(void *blob, int first_mem_node, int curr_mem_node) +{ + struct fdt_resource first_mem_res, curr_mem_res; + int curr_mem_reg, first_mem_reg = 0; + int ret; + + for (;;) { + ret = fdt_get_resource(blob, first_mem_node, "reg", + first_mem_reg++, &first_mem_res); + if (ret) /* No more entries, no overlap found */ + return 0; + + curr_mem_reg = 0; + for (;;) { + ret = fdt_get_resource(blob, curr_mem_node, "reg", + curr_mem_reg++, &curr_mem_res); + if (ret) /* No more entries, check next tuple */ + break; + + if (curr_mem_res.end < first_mem_res.start) + continue; + + if (curr_mem_res.start >= first_mem_res.end) + continue; + + log_debug("Overlap found: 0x%llx..0x%llx / 0x%llx..0x%llx\n", + first_mem_res.start, first_mem_res.end, + curr_mem_res.start, curr_mem_res.end); + + return 1; + } + } + + return 0; +} + +static void scrub_duplicate_memory(void *blob) +{ + /* + * Scrub duplicate /memory@* node entries here. Some R-Car DTs might + * contain multiple /memory@* nodes, however fdt_fixup_memory_banks() + * either generates single /memory node or updates the first /memory + * node. Any remaining memory nodes are thus potential duplicates. + * + * However, it is not possible to delete all the memory nodes right + * away, since some of those might not be DRAM memory nodes, but some + * sort of other memory. Thus, delete only the memory nodes which are + * in the R-Car3 DBSC ranges. + */ + int mem = 0, first_mem_node = 0; + + for (;;) { + mem = fdt_node_offset_by_prop_value(blob, mem, + "device_type", "memory", 7); + if (mem < 0) + break; + if (!fdtdec_get_is_enabled(blob, mem)) + continue; + + /* First memory node, patched by U-Boot */ + if (!first_mem_node) { + first_mem_node = mem; + continue; + } + + /* Check the remaining nodes and delete duplicates */ + if (!is_mem_overlap(blob, first_mem_node, mem)) + continue; + + /* Delete duplicate node, start again */ + fdt_del_node(blob, mem); + first_mem_node = 0; + mem = 0; + } +} + +static void update_rpc_status(void *blob) +{ + void *atf_fdt_blob = (void *)(rcar_atf_boot_args[1]); + int offset, enabled; + + /* + * Check if the DT fragment received from TF-A had its RPC-IF device node + * enabled. + */ + if (fdt_magic(atf_fdt_blob) != FDT_MAGIC) + return; + + offset = fdt_path_offset(atf_fdt_blob, FDT_RPC_PATH); + if (offset < 0) + return; + + enabled = fdtdec_get_is_enabled(atf_fdt_blob, offset); + if (!enabled) + return; + + /* + * Find the RPC-IF device node, and enable it if it has a flash subnode. + */ + offset = fdt_path_offset(blob, FDT_RPC_PATH); + if (offset < 0) + return; + + if (fdt_subnode_offset(blob, offset, "flash") < 0) + return; + + fdt_status_okay(blob, offset); +} + +int ft_board_setup(void *blob, struct bd_info *bd) +{ + apply_atf_overlay(blob); + scrub_duplicate_memory(blob); + update_rpc_status(blob); + + return 0; +} +#endif +#endif diff --git a/board/renesas/rcar-common/gen4-common.c b/board/renesas/rcar-common/gen4-common.c new file mode 100644 index 00000000000..2abe9660cf8 --- /dev/null +++ b/board/renesas/rcar-common/gen4-common.c @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * board/renesas/rcar-common/gen4-common.c + * + * Copyright (C) 2021-2024 Renesas Electronics Corp. + */ + +#include <asm/arch/renesas.h> +#include <asm/arch/sys_proto.h> +#include <asm/global_data.h> +#include <asm/io.h> +#include <asm/mach-types.h> +#include <asm/processor.h> +#include <asm/system.h> +#include <linux/errno.h> + +#define RST_BASE 0xE6160000 /* Domain0 */ +#define RST_WDTRSTCR (RST_BASE + 0x10) +#define RST_RWDT 0xA55A8002 + +DECLARE_GLOBAL_DATA_PTR; + +static void init_generic_timer(void) +{ + const u32 freq = CONFIG_SYS_CLK_FREQ; + + /* Update memory mapped and register based freqency */ + asm volatile ("msr cntfrq_el0, %0" :: "r" (freq)); + writel(freq, CNTFID0); + + /* Enable counter */ + setbits_le32(CNTCR_BASE, CNTCR_EN); +} + +static void init_gic_v3(void) +{ + /* GIC v3 power on */ + writel(BIT(1), GICR_LPI_PWRR); + + /* Wait till the WAKER_CA_BIT changes to 0 */ + clrbits_le32(GICR_LPI_WAKER, BIT(1)); + while (readl(GICR_LPI_WAKER) & BIT(2)) + ; + + writel(0xffffffff, GICR_SGI_BASE + GICR_IGROUPR0); +} + +void s_init(void) +{ + if (current_el() == 3) + init_generic_timer(); +} + +int board_early_init_f(void) +{ + /* Unlock CPG access */ + writel(0x5A5AFFFF, CPGWPR); + writel(0xA5A50000, CPGWPCR); + + return 0; +} + +int board_init(void) +{ + if (current_el() != 3) + return 0; + init_gic_v3(); + + /* Enable RWDT reset on V3U in EL3 */ + if (IS_ENABLED(CONFIG_R8A779A0) && + renesas_get_cpu_type() == RENESAS_CPU_TYPE_R8A779A0) { + writel(RST_RWDT, RST_WDTRSTCR); + } + + return 0; +} + +#define RST_BASE 0xE6160000 /* Domain0 */ +#define RST_SRESCR0 (RST_BASE + 0x18) +#define RST_SPRES 0x5AA58000 + +void __weak reset_cpu(void) +{ + writel(RST_SPRES, RST_SRESCR0); +} + +int ft_board_setup(void *blob, struct bd_info *bd) +{ + return 0; +} diff --git a/board/renesas/rcar-common/gen4-spl.c b/board/renesas/rcar-common/gen4-spl.c new file mode 100644 index 00000000000..2aca8baf3dd --- /dev/null +++ b/board/renesas/rcar-common/gen4-spl.c @@ -0,0 +1,119 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * R-Car Gen4 Cortex-R52 SPL + * + * Copyright (C) 2024 Marek Vasut <marek.vasut+renesas@mailbox.org> + */ + +#include <asm/arch/renesas.h> +#include <asm/io.h> +#include <cpu_func.h> +#include <dm/uclass.h> +#include <dm/util.h> +#include <hang.h> +#include <image.h> +#include <init.h> +#include <linux/bitops.h> +#include <log.h> +#include <mapmem.h> +#include <spl.h> + +#define CNTCR_EN BIT(0) + +#ifdef CONFIG_SPL_BUILD +void board_debug_uart_init(void) +{ +} +#endif + +static void init_generic_timer(void) +{ + const u32 freq = CONFIG_SYS_CLK_FREQ; + + /* Update memory mapped and register based freqency */ + if (IS_ENABLED(CONFIG_ARM64)) + asm volatile("msr cntfrq_el0, %0" :: "r" (freq)); + else + asm volatile("mcr p15, 0, %0, c14, c0, 0" :: "r" (freq)); + + writel(freq, CNTFID0); + + /* Enable counter */ + setbits_le32(CNTCR_BASE, CNTCR_EN); +} + +void board_init_f(ulong dummy) +{ + struct udevice *dev; + int ret; + + if (CONFIG_IS_ENABLED(OF_CONTROL)) { + ret = spl_early_init(); + if (ret) { + debug("spl_early_init() failed: %d\n", ret); + hang(); + } + } + + preloader_console_init(); + + ret = uclass_get_device_by_name(UCLASS_NOP, "ram@e6780000", &dev); + if (ret) + printf("DBSC5 init failed: %d\n", ret); + + ret = uclass_get_device_by_name(UCLASS_RAM, "ram@ffec0000", &dev); + if (ret) + printf("RTVRAM init failed: %d\n", ret); +}; + +u32 spl_boot_device(void) +{ + return BOOT_DEVICE_SPI; +} + +struct legacy_img_hdr *spl_get_load_buffer(ssize_t offset, size_t size) +{ + return map_sysmem(CONFIG_SYS_LOAD_ADDR + offset, 0); +} + +void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image) +{ + debug("image entry point: 0x%lx\n", spl_image->entry_point); + if (spl_image->os == IH_OS_ARM_TRUSTED_FIRMWARE) { + typedef void (*image_entry_arg_t)(int, int, int, int) + __attribute__ ((noreturn)); + image_entry_arg_t image_entry = + (image_entry_arg_t)(uintptr_t) spl_image->entry_point; + image_entry(IH_MAGIC, CONFIG_SPL_TEXT_BASE, 0, 0); + } else { + typedef void __noreturn (*image_entry_noargs_t)(void); + image_entry_noargs_t image_entry = + (image_entry_noargs_t)spl_image->entry_point; + image_entry(); + } +} + +#define APMU_BASE 0xe6170000U +#define CL0GRP3_BIT BIT(3) +#define CL1GRP3_BIT BIT(7) +#define RTGRP3_BIT BIT(19) +#define APMU_ACC_ENB_FOR_ARM_CPU (CL0GRP3_BIT | CL1GRP3_BIT | RTGRP3_BIT) + +void s_init(void) +{ + /* Unlock CPG access */ + writel(0x5A5AFFFF, CPGWPR); + writel(0xA5A50000, CPGWPCR); + init_generic_timer(); + + /* Define for Work Around of APMU */ + writel(0x00ff00ff, APMU_BASE + 0x10); + writel(0x00ff00ff, APMU_BASE + 0x14); + writel(0x00ff00ff, APMU_BASE + 0x18); + writel(0x00ff00ff, APMU_BASE + 0x1c); + clrbits_le32(APMU_BASE + 0x68, BIT(29)); +} + +void reset_cpu(void) +{ +} |