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