blob: 004feca6180caac7502dea42636ce1eabeccab07 [file] [log] [blame]
Marek Vasutf48b1332024-12-12 14:38:27 +01001// SPDX-License-Identifier: GPL-2.0
2/*
3 * board/renesas/rcar-common/gen3-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
Marek Vasut364d29b2025-01-01 20:19:06 +010010#include <asm/armv8/cpu.h>
Marek Vasutf48b1332024-12-12 14:38:27 +010011#include <dm.h>
12#include <fdt_support.h>
13#include <hang.h>
14#include <init.h>
15#include <asm/global_data.h>
16#include <asm/io.h>
17#include <dm/uclass-internal.h>
18#include <asm/arch/renesas.h>
19#include <linux/libfdt.h>
20
21#ifdef CONFIG_RCAR_64
22
23DECLARE_GLOBAL_DATA_PTR;
24
25/* If the firmware passed a device tree use it for e.g. U-Boot DRAM setup. */
26extern u64 rcar_atf_boot_args[];
27
28#define FDT_RPC_PATH "/soc/spi@ee200000"
29
30static void apply_atf_overlay(void *fdt_blob)
31{
32 void *atf_fdt_blob = (void *)(rcar_atf_boot_args[1]);
33
34 if (fdt_magic(atf_fdt_blob) == FDT_MAGIC)
35 fdt_overlay_apply_node(fdt_blob, 0, atf_fdt_blob, 0);
36}
37
38int fdtdec_board_setup(const void *fdt_blob)
39{
40 apply_atf_overlay((void *)fdt_blob);
41
42 return 0;
43}
44
45#define RST_BASE 0xE6160000
46#define RST_CA57RESCNT (RST_BASE + 0x40)
47#define RST_CA53RESCNT (RST_BASE + 0x44)
48#define RST_RSTOUTCR (RST_BASE + 0x58)
49#define RST_CA57_CODE 0xA5A5000F
50#define RST_CA53_CODE 0x5A5A000F
51
52void __weak reset_cpu(void)
53{
Marek Vasut364d29b2025-01-01 20:19:06 +010054 if (is_cortex_a53())
Marek Vasutf48b1332024-12-12 14:38:27 +010055 writel(RST_CA53_CODE, RST_CA53RESCNT);
Marek Vasut364d29b2025-01-01 20:19:06 +010056 else if (is_cortex_a57())
Marek Vasutf48b1332024-12-12 14:38:27 +010057 writel(RST_CA57_CODE, RST_CA57RESCNT);
58 else
59 hang();
60}
61
62#if defined(CONFIG_OF_BOARD_SETUP)
63static int is_mem_overlap(void *blob, int first_mem_node, int curr_mem_node)
64{
65 struct fdt_resource first_mem_res, curr_mem_res;
66 int curr_mem_reg, first_mem_reg = 0;
67 int ret;
68
69 for (;;) {
70 ret = fdt_get_resource(blob, first_mem_node, "reg",
71 first_mem_reg++, &first_mem_res);
72 if (ret) /* No more entries, no overlap found */
73 return 0;
74
75 curr_mem_reg = 0;
76 for (;;) {
77 ret = fdt_get_resource(blob, curr_mem_node, "reg",
78 curr_mem_reg++, &curr_mem_res);
79 if (ret) /* No more entries, check next tuple */
80 break;
81
82 if (curr_mem_res.end < first_mem_res.start)
83 continue;
84
85 if (curr_mem_res.start >= first_mem_res.end)
86 continue;
87
88 log_debug("Overlap found: 0x%llx..0x%llx / 0x%llx..0x%llx\n",
89 first_mem_res.start, first_mem_res.end,
90 curr_mem_res.start, curr_mem_res.end);
91
92 return 1;
93 }
94 }
95
96 return 0;
97}
98
99static void scrub_duplicate_memory(void *blob)
100{
101 /*
102 * Scrub duplicate /memory@* node entries here. Some R-Car DTs might
103 * contain multiple /memory@* nodes, however fdt_fixup_memory_banks()
104 * either generates single /memory node or updates the first /memory
105 * node. Any remaining memory nodes are thus potential duplicates.
106 *
107 * However, it is not possible to delete all the memory nodes right
108 * away, since some of those might not be DRAM memory nodes, but some
109 * sort of other memory. Thus, delete only the memory nodes which are
110 * in the R-Car3 DBSC ranges.
111 */
112 int mem = 0, first_mem_node = 0;
113
114 for (;;) {
115 mem = fdt_node_offset_by_prop_value(blob, mem,
116 "device_type", "memory", 7);
117 if (mem < 0)
118 break;
119 if (!fdtdec_get_is_enabled(blob, mem))
120 continue;
121
122 /* First memory node, patched by U-Boot */
123 if (!first_mem_node) {
124 first_mem_node = mem;
125 continue;
126 }
127
128 /* Check the remaining nodes and delete duplicates */
129 if (!is_mem_overlap(blob, first_mem_node, mem))
130 continue;
131
132 /* Delete duplicate node, start again */
133 fdt_del_node(blob, mem);
134 first_mem_node = 0;
135 mem = 0;
136 }
137}
138
139static void update_rpc_status(void *blob)
140{
141 void *atf_fdt_blob = (void *)(rcar_atf_boot_args[1]);
142 int offset, enabled;
143
144 /*
145 * Check if the DT fragment received from TF-A had its RPC-IF device node
146 * enabled.
147 */
148 if (fdt_magic(atf_fdt_blob) != FDT_MAGIC)
149 return;
150
151 offset = fdt_path_offset(atf_fdt_blob, FDT_RPC_PATH);
152 if (offset < 0)
153 return;
154
155 enabled = fdtdec_get_is_enabled(atf_fdt_blob, offset);
156 if (!enabled)
157 return;
158
159 /*
160 * Find the RPC-IF device node, and enable it if it has a flash subnode.
161 */
162 offset = fdt_path_offset(blob, FDT_RPC_PATH);
163 if (offset < 0)
164 return;
165
166 if (fdt_subnode_offset(blob, offset, "flash") < 0)
167 return;
168
169 fdt_status_okay(blob, offset);
170}
171
172int ft_board_setup(void *blob, struct bd_info *bd)
173{
174 apply_atf_overlay(blob);
175 scrub_duplicate_memory(blob);
176 update_rpc_status(blob);
177
178 return 0;
179}
180#endif
181#endif