blob: 4291e1d5bcb6a7b9fbf4900ed79f1ea7a56fdff1 [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
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
44#define RST_BASE 0xE6160000
45#define RST_CA57RESCNT (RST_BASE + 0x40)
46#define RST_CA53RESCNT (RST_BASE + 0x44)
47#define RST_RSTOUTCR (RST_BASE + 0x58)
48#define RST_CA57_CODE 0xA5A5000F
49#define RST_CA53_CODE 0x5A5A000F
50
51void __weak reset_cpu(void)
52{
53 unsigned long midr, cputype;
54
55 asm volatile("mrs %0, midr_el1" : "=r" (midr));
56 cputype = (midr >> 4) & 0xfff;
57
58 if (cputype == 0xd03)
59 writel(RST_CA53_CODE, RST_CA53RESCNT);
60 else if (cputype == 0xd07)
61 writel(RST_CA57_CODE, RST_CA57RESCNT);
62 else
63 hang();
64}
65
66#if defined(CONFIG_OF_BOARD_SETUP)
67static int is_mem_overlap(void *blob, int first_mem_node, int curr_mem_node)
68{
69 struct fdt_resource first_mem_res, curr_mem_res;
70 int curr_mem_reg, first_mem_reg = 0;
71 int ret;
72
73 for (;;) {
74 ret = fdt_get_resource(blob, first_mem_node, "reg",
75 first_mem_reg++, &first_mem_res);
76 if (ret) /* No more entries, no overlap found */
77 return 0;
78
79 curr_mem_reg = 0;
80 for (;;) {
81 ret = fdt_get_resource(blob, curr_mem_node, "reg",
82 curr_mem_reg++, &curr_mem_res);
83 if (ret) /* No more entries, check next tuple */
84 break;
85
86 if (curr_mem_res.end < first_mem_res.start)
87 continue;
88
89 if (curr_mem_res.start >= first_mem_res.end)
90 continue;
91
92 log_debug("Overlap found: 0x%llx..0x%llx / 0x%llx..0x%llx\n",
93 first_mem_res.start, first_mem_res.end,
94 curr_mem_res.start, curr_mem_res.end);
95
96 return 1;
97 }
98 }
99
100 return 0;
101}
102
103static void scrub_duplicate_memory(void *blob)
104{
105 /*
106 * Scrub duplicate /memory@* node entries here. Some R-Car DTs might
107 * contain multiple /memory@* nodes, however fdt_fixup_memory_banks()
108 * either generates single /memory node or updates the first /memory
109 * node. Any remaining memory nodes are thus potential duplicates.
110 *
111 * However, it is not possible to delete all the memory nodes right
112 * away, since some of those might not be DRAM memory nodes, but some
113 * sort of other memory. Thus, delete only the memory nodes which are
114 * in the R-Car3 DBSC ranges.
115 */
116 int mem = 0, first_mem_node = 0;
117
118 for (;;) {
119 mem = fdt_node_offset_by_prop_value(blob, mem,
120 "device_type", "memory", 7);
121 if (mem < 0)
122 break;
123 if (!fdtdec_get_is_enabled(blob, mem))
124 continue;
125
126 /* First memory node, patched by U-Boot */
127 if (!first_mem_node) {
128 first_mem_node = mem;
129 continue;
130 }
131
132 /* Check the remaining nodes and delete duplicates */
133 if (!is_mem_overlap(blob, first_mem_node, mem))
134 continue;
135
136 /* Delete duplicate node, start again */
137 fdt_del_node(blob, mem);
138 first_mem_node = 0;
139 mem = 0;
140 }
141}
142
143static void update_rpc_status(void *blob)
144{
145 void *atf_fdt_blob = (void *)(rcar_atf_boot_args[1]);
146 int offset, enabled;
147
148 /*
149 * Check if the DT fragment received from TF-A had its RPC-IF device node
150 * enabled.
151 */
152 if (fdt_magic(atf_fdt_blob) != FDT_MAGIC)
153 return;
154
155 offset = fdt_path_offset(atf_fdt_blob, FDT_RPC_PATH);
156 if (offset < 0)
157 return;
158
159 enabled = fdtdec_get_is_enabled(atf_fdt_blob, offset);
160 if (!enabled)
161 return;
162
163 /*
164 * Find the RPC-IF device node, and enable it if it has a flash subnode.
165 */
166 offset = fdt_path_offset(blob, FDT_RPC_PATH);
167 if (offset < 0)
168 return;
169
170 if (fdt_subnode_offset(blob, offset, "flash") < 0)
171 return;
172
173 fdt_status_okay(blob, offset);
174}
175
176int ft_board_setup(void *blob, struct bd_info *bd)
177{
178 apply_atf_overlay(blob);
179 scrub_duplicate_memory(blob);
180 update_rpc_status(blob);
181
182 return 0;
183}
184#endif
185#endif