blob: 97aa15d6a68e5955b7696b43bc445739cfc0cad0 [file] [log] [blame]
Lokesh Vutlaa3501a42018-11-02 19:51:05 +05301// SPDX-License-Identifier: GPL-2.0+
2/*
3 * K3: Common Architecture initialization
4 *
5 * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
6 * Lokesh Vutla <lokeshvutla@ti.com>
7 */
8
9#include <common.h>
10#include <spl.h>
11#include "common.h"
12#include <dm.h>
13#include <remoteproc.h>
Lokesh Vutla6ce424a2019-03-08 11:47:33 +053014#include <linux/soc/ti/ti_sci_protocol.h>
Lokesh Vutlaa9a84482019-03-08 11:47:34 +053015#include <fdt_support.h>
Andreas Dannenbergf9380a72019-06-07 19:24:42 +053016#include <asm/arch/sys_proto.h>
Lokesh Vutlaf8ca9122019-09-27 13:32:11 +053017#include <asm/hardware.h>
18#include <asm/io.h>
Lokesh Vutla6ce424a2019-03-08 11:47:33 +053019
20struct ti_sci_handle *get_ti_sci_handle(void)
21{
22 struct udevice *dev;
23 int ret;
24
Lokesh Vutlae8d3a182019-09-09 12:47:37 +053025 ret = uclass_get_device(UCLASS_FIRMWARE, 0, &dev);
Lokesh Vutla6ce424a2019-03-08 11:47:33 +053026 if (ret)
27 panic("Failed to get SYSFW (%d)\n", ret);
28
29 return (struct ti_sci_handle *)ti_sci_get_handle_from_sysfw(dev);
30}
Lokesh Vutlaa3501a42018-11-02 19:51:05 +053031
Andreas Dannenberge630afe12019-08-15 15:55:28 -050032DECLARE_GLOBAL_DATA_PTR;
33
34#ifdef CONFIG_K3_EARLY_CONS
35int early_console_init(void)
36{
37 struct udevice *dev;
38 int ret;
39
40 gd->baudrate = CONFIG_BAUDRATE;
41
42 ret = uclass_get_device_by_seq(UCLASS_SERIAL, CONFIG_K3_EARLY_CONS_IDX,
43 &dev);
44 if (ret) {
45 printf("Error getting serial dev for early console! (%d)\n",
46 ret);
47 return ret;
48 }
49
50 gd->cur_serial_dev = dev;
51 gd->flags |= GD_FLG_SERIAL_READY;
52 gd->have_console = 1;
53
54 return 0;
55}
56#endif
57
Lokesh Vutlaa3501a42018-11-02 19:51:05 +053058#ifdef CONFIG_SYS_K3_SPL_ATF
59void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image)
60{
Lokesh Vutlac0669d22019-06-07 19:24:43 +053061 struct ti_sci_handle *ti_sci = get_ti_sci_handle();
Lokesh Vutlaa3501a42018-11-02 19:51:05 +053062 int ret;
63
Lokesh Vutlac0669d22019-06-07 19:24:43 +053064 /* Release all the exclusive devices held by SPL before starting ATF */
65 ti_sci->ops.dev_ops.release_exclusive_devices(ti_sci);
66
Lokesh Vutlaa3501a42018-11-02 19:51:05 +053067 /*
68 * It is assumed that remoteproc device 1 is the corresponding
Andreas Dannenberg4a1fa522019-02-04 12:58:47 -060069 * Cortex-A core which runs ATF. Make sure DT reflects the same.
Lokesh Vutlaa3501a42018-11-02 19:51:05 +053070 */
71 ret = rproc_dev_init(1);
Andreas Dannenberg4a1fa522019-02-04 12:58:47 -060072 if (ret)
73 panic("%s: ATF failed to initialize on rproc (%d)\n", __func__,
74 ret);
Lokesh Vutlaa3501a42018-11-02 19:51:05 +053075
76 ret = rproc_load(1, spl_image->entry_point, 0x200);
Andreas Dannenberg4a1fa522019-02-04 12:58:47 -060077 if (ret)
78 panic("%s: ATF failed to load on rproc (%d)\n", __func__, ret);
Lokesh Vutlaa3501a42018-11-02 19:51:05 +053079
Andreas Dannenberg4a1fa522019-02-04 12:58:47 -060080 /* Add an extra newline to differentiate the ATF logs from SPL */
Lokesh Vutlaa3501a42018-11-02 19:51:05 +053081 printf("Starting ATF on ARM64 core...\n\n");
82
83 ret = rproc_start(1);
Andreas Dannenberg4a1fa522019-02-04 12:58:47 -060084 if (ret)
85 panic("%s: ATF failed to start on rproc (%d)\n", __func__, ret);
Lokesh Vutlaa3501a42018-11-02 19:51:05 +053086
Andreas Dannenbergf9380a72019-06-07 19:24:42 +053087 debug("Releasing resources...\n");
88 release_resources_for_core_shutdown();
89
90 debug("Finalizing core shutdown...\n");
Lokesh Vutlaa3501a42018-11-02 19:51:05 +053091 while (1)
92 asm volatile("wfe");
93}
94#endif
Lokesh Vutlaa9a84482019-03-08 11:47:34 +053095
96#if defined(CONFIG_OF_LIBFDT)
97int fdt_fixup_msmc_ram(void *blob, char *parent_path, char *node_name)
98{
99 u64 msmc_start = 0, msmc_end = 0, msmc_size, reg[2];
100 struct ti_sci_handle *ti_sci = get_ti_sci_handle();
101 int ret, node, subnode, len, prev_node;
102 u32 range[4], addr, size;
103 const fdt32_t *sub_reg;
104
105 ti_sci->ops.core_ops.query_msmc(ti_sci, &msmc_start, &msmc_end);
106 msmc_size = msmc_end - msmc_start + 1;
107 debug("%s: msmc_start = 0x%llx, msmc_size = 0x%llx\n", __func__,
108 msmc_start, msmc_size);
109
110 /* find or create "msmc_sram node */
111 ret = fdt_path_offset(blob, parent_path);
112 if (ret < 0)
113 return ret;
114
115 node = fdt_find_or_add_subnode(blob, ret, node_name);
116 if (node < 0)
117 return node;
118
119 ret = fdt_setprop_string(blob, node, "compatible", "mmio-sram");
120 if (ret < 0)
121 return ret;
122
123 reg[0] = cpu_to_fdt64(msmc_start);
124 reg[1] = cpu_to_fdt64(msmc_size);
125 ret = fdt_setprop(blob, node, "reg", reg, sizeof(reg));
126 if (ret < 0)
127 return ret;
128
129 fdt_setprop_cell(blob, node, "#address-cells", 1);
130 fdt_setprop_cell(blob, node, "#size-cells", 1);
131
132 range[0] = 0;
133 range[1] = cpu_to_fdt32(msmc_start >> 32);
134 range[2] = cpu_to_fdt32(msmc_start & 0xffffffff);
135 range[3] = cpu_to_fdt32(msmc_size);
136 ret = fdt_setprop(blob, node, "ranges", range, sizeof(range));
137 if (ret < 0)
138 return ret;
139
140 subnode = fdt_first_subnode(blob, node);
141 prev_node = 0;
142
143 /* Look for invalid subnodes and delete them */
144 while (subnode >= 0) {
145 sub_reg = fdt_getprop(blob, subnode, "reg", &len);
146 addr = fdt_read_number(sub_reg, 1);
147 sub_reg++;
148 size = fdt_read_number(sub_reg, 1);
149 debug("%s: subnode = %d, addr = 0x%x. size = 0x%x\n", __func__,
150 subnode, addr, size);
151 if (addr + size > msmc_size ||
152 !strncmp(fdt_get_name(blob, subnode, &len), "sysfw", 5) ||
153 !strncmp(fdt_get_name(blob, subnode, &len), "l3cache", 7)) {
154 fdt_del_node(blob, subnode);
155 debug("%s: deleting subnode %d\n", __func__, subnode);
156 if (!prev_node)
157 subnode = fdt_first_subnode(blob, node);
158 else
159 subnode = fdt_next_subnode(blob, prev_node);
160 } else {
161 prev_node = subnode;
162 subnode = fdt_next_subnode(blob, prev_node);
163 }
164 }
165
166 return 0;
167}
Andrew F. Davis29c9db42019-09-17 17:15:40 -0400168
169int fdt_disable_node(void *blob, char *node_path)
170{
171 int offs;
172 int ret;
173
174 offs = fdt_path_offset(blob, node_path);
175 if (offs < 0) {
176 debug("Node %s not found.\n", node_path);
177 return 0;
178 }
179 ret = fdt_setprop_string(blob, offs, "status", "disabled");
180 if (ret < 0) {
181 printf("Could not add status property to node %s: %s\n",
182 node_path, fdt_strerror(ret));
183 return ret;
184 }
185 return 0;
186}
187
Lokesh Vutlaa9a84482019-03-08 11:47:34 +0530188#endif
Lokesh Vutlac2562d72019-06-13 10:29:42 +0530189
190#ifndef CONFIG_SYSRESET
191void reset_cpu(ulong ignored)
192{
193}
194#endif
Lokesh Vutlaf8ca9122019-09-27 13:32:11 +0530195
196#if defined(CONFIG_DISPLAY_CPUINFO)
197int print_cpuinfo(void)
198{
199 u32 soc, rev;
200 char *name;
201
202 soc = (readl(CTRLMMR_WKUP_JTAG_DEVICE_ID) &
203 DEVICE_ID_FAMILY_MASK) >> DEVICE_ID_FAMILY_SHIFT;
204 rev = (readl(CTRLMMR_WKUP_JTAG_ID) &
205 JTAG_ID_VARIANT_MASK) >> JTAG_ID_VARIANT_SHIFT;
206
207 printf("SoC: ");
208 switch (soc) {
209 case AM654:
210 name = "AM654";
211 break;
212 case J721E:
213 name = "J721E";
214 break;
215 default:
216 name = "Unknown Silicon";
217 };
218
219 printf("%s PG ", name);
220 switch (rev) {
221 case REV_PG1_0:
222 name = "1.0";
223 break;
224 case REV_PG2_0:
225 name = "2.0";
226 break;
227 default:
228 name = "Unknown Revision";
229 };
230 printf("%s\n", name);
231
232 return 0;
233}
234#endif