1// SPDX-License-Identifier: GPL-2.0 2/* 3 * board/renesas/rcar-common/common.c 4 * 5 * Copyright (C) 2013 Renesas Electronics Corporation 6 * Copyright (C) 2013 Nobuhiro Iwamatsu <nobuhiro.iwamatsu.yj@renesas.com> 7 * Copyright (C) 2015 Nobuhiro Iwamatsu <iwamatsu@nigauri.org> 8 */ 9 10#include <dm.h> 11#include <fdt_support.h> 12#include <hang.h> 13#include <init.h> 14#include <asm/global_data.h> 15#include <asm/io.h> 16#include <dm/uclass-internal.h> 17#include <asm/arch/renesas.h> 18#include <linux/libfdt.h> 19 20#ifdef CONFIG_RCAR_64 21 22DECLARE_GLOBAL_DATA_PTR; 23 24/* If the firmware passed a device tree use it for e.g. U-Boot DRAM setup. */ 25extern u64 rcar_atf_boot_args[]; 26 27#define FDT_RPC_PATH "/soc/spi@ee200000" 28 29static void apply_atf_overlay(void *fdt_blob) 30{ 31 void *atf_fdt_blob = (void *)(rcar_atf_boot_args[1]); 32 33 if (fdt_magic(atf_fdt_blob) == FDT_MAGIC) 34 fdt_overlay_apply_node(fdt_blob, 0, atf_fdt_blob, 0); 35} 36 37int fdtdec_board_setup(const void *fdt_blob) 38{ 39 apply_atf_overlay((void *)fdt_blob); 40 41 return 0; 42} 43 44int dram_init(void) 45{ 46 return fdtdec_setup_mem_size_base(); 47} 48 49int dram_init_banksize(void) 50{ 51 fdtdec_setup_memory_banksize(); 52 53 return 0; 54} 55 56int __weak board_init(void) 57{ 58 return 0; 59} 60 61#if defined(CONFIG_RCAR_GEN3) 62#define RST_BASE 0xE6160000 63#define RST_CA57RESCNT (RST_BASE + 0x40) 64#define RST_CA53RESCNT (RST_BASE + 0x44) 65#define RST_RSTOUTCR (RST_BASE + 0x58) 66#define RST_CA57_CODE 0xA5A5000F 67#define RST_CA53_CODE 0x5A5A000F 68 69void __weak reset_cpu(void) 70{ 71 unsigned long midr, cputype; 72 73 asm volatile("mrs %0, midr_el1" : "=r" (midr)); 74 cputype = (midr >> 4) & 0xfff; 75 76 if (cputype == 0xd03) 77 writel(RST_CA53_CODE, RST_CA53RESCNT); 78 else if (cputype == 0xd07) 79 writel(RST_CA57_CODE, RST_CA57RESCNT); 80 else 81 hang(); 82} 83#elif defined(CONFIG_RCAR_GEN4) 84#define RST_BASE 0xE6160000 /* Domain0 */ 85#define RST_SRESCR0 (RST_BASE + 0x18) 86#define RST_SPRES 0x5AA58000 87 88void __weak reset_cpu(void) 89{ 90 writel(RST_SPRES, RST_SRESCR0); 91} 92#else 93#error Neither CONFIG_RCAR_GEN3 nor CONFIG_RCAR_GEN4 are set 94#endif 95 96#if defined(CONFIG_OF_BOARD_SETUP) 97static int is_mem_overlap(void *blob, int first_mem_node, int curr_mem_node) 98{ 99 struct fdt_resource first_mem_res, curr_mem_res; 100 int curr_mem_reg, first_mem_reg = 0; 101 int ret; 102 103 for (;;) { 104 ret = fdt_get_resource(blob, first_mem_node, "reg", 105 first_mem_reg++, &first_mem_res); 106 if (ret) /* No more entries, no overlap found */ 107 return 0; 108 109 curr_mem_reg = 0; 110 for (;;) { 111 ret = fdt_get_resource(blob, curr_mem_node, "reg", 112 curr_mem_reg++, &curr_mem_res); 113 if (ret) /* No more entries, check next tuple */ 114 break; 115 116 if (curr_mem_res.end < first_mem_res.start) 117 continue; 118 119 if (curr_mem_res.start >= first_mem_res.end) 120 continue; 121 122 log_debug("Overlap found: 0x%llx..0x%llx / 0x%llx..0x%llx\n", 123 first_mem_res.start, first_mem_res.end, 124 curr_mem_res.start, curr_mem_res.end); 125 126 return 1; 127 } 128 } 129 130 return 0; 131} 132 133static void scrub_duplicate_memory(void *blob) 134{ 135 /* 136 * Scrub duplicate /memory@* node entries here. Some R-Car DTs might 137 * contain multiple /memory@* nodes, however fdt_fixup_memory_banks() 138 * either generates single /memory node or updates the first /memory 139 * node. Any remaining memory nodes are thus potential duplicates. 140 * 141 * However, it is not possible to delete all the memory nodes right 142 * away, since some of those might not be DRAM memory nodes, but some 143 * sort of other memory. Thus, delete only the memory nodes which are 144 * in the R-Car3 DBSC ranges. 145 */ 146 int mem = 0, first_mem_node = 0; 147 148 for (;;) { 149 mem = fdt_node_offset_by_prop_value(blob, mem, 150 "device_type", "memory", 7); 151 if (mem < 0) 152 break; 153 if (!fdtdec_get_is_enabled(blob, mem)) 154 continue; 155 156 /* First memory node, patched by U-Boot */ 157 if (!first_mem_node) { 158 first_mem_node = mem; 159 continue; 160 } 161 162 /* Check the remaining nodes and delete duplicates */ 163 if (!is_mem_overlap(blob, first_mem_node, mem)) 164 continue; 165 166 /* Delete duplicate node, start again */ 167 fdt_del_node(blob, mem); 168 first_mem_node = 0; 169 mem = 0; 170 } 171} 172 173static void update_rpc_status(void *blob) 174{ 175 void *atf_fdt_blob = (void *)(rcar_atf_boot_args[1]); 176 int offset, enabled; 177 178 /* 179 * Check if the DT fragment received from TF-A had its RPC-IF device node 180 * enabled. 181 */ 182 if (fdt_magic(atf_fdt_blob) != FDT_MAGIC) 183 return; 184 185 offset = fdt_path_offset(atf_fdt_blob, FDT_RPC_PATH); 186 if (offset < 0) 187 return; 188 189 enabled = fdtdec_get_is_enabled(atf_fdt_blob, offset); 190 if (!enabled) 191 return; 192 193 /* 194 * Find the RPC-IF device node, and enable it if it has a flash subnode. 195 */ 196 offset = fdt_path_offset(blob, FDT_RPC_PATH); 197 if (offset < 0) 198 return; 199 200 if (fdt_subnode_offset(blob, offset, "flash") < 0) 201 return; 202 203 fdt_status_okay(blob, offset); 204} 205 206int ft_board_setup(void *blob, struct bd_info *bd) 207{ 208 apply_atf_overlay(blob); 209 scrub_duplicate_memory(blob); 210 update_rpc_status(blob); 211 212 return 0; 213} 214#endif 215#endif 216