1 // SPDX-License-Identifier: GPL-2.0+
3 * K3: Common Architecture initialization
5 * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
6 * Lokesh Vutla <lokeshvutla@ti.com>
15 #include <remoteproc.h>
16 #include <asm/cache.h>
17 #include <linux/soc/ti/ti_sci_protocol.h>
18 #include <fdt_support.h>
19 #include <asm/arch/sys_proto.h>
20 #include <asm/hardware.h>
22 #include <fs_loader.h>
27 struct ti_sci_handle *get_ti_sci_handle(void)
32 ret = uclass_get_device_by_driver(UCLASS_FIRMWARE,
33 DM_GET_DRIVER(ti_sci), &dev);
35 panic("Failed to get SYSFW (%d)\n", ret);
37 return (struct ti_sci_handle *)ti_sci_get_handle_from_sysfw(dev);
40 void k3_sysfw_print_ver(void)
42 struct ti_sci_handle *ti_sci = get_ti_sci_handle();
43 char fw_desc[sizeof(ti_sci->version.firmware_description) + 1];
46 * Output System Firmware version info. Note that since the
47 * 'firmware_description' field is not guaranteed to be zero-
48 * terminated we manually add a \0 terminator if needed. Further
49 * note that we intentionally no longer rely on the extended
50 * printf() formatter '%.*s' to not having to require a more
51 * full-featured printf() implementation.
53 strncpy(fw_desc, ti_sci->version.firmware_description,
54 sizeof(ti_sci->version.firmware_description));
55 fw_desc[sizeof(fw_desc) - 1] = '\0';
57 printf("SYSFW ABI: %d.%d (firmware rev 0x%04x '%s')\n",
58 ti_sci->version.abi_major, ti_sci->version.abi_minor,
59 ti_sci->version.firmware_revision, fw_desc);
62 DECLARE_GLOBAL_DATA_PTR;
64 #ifdef CONFIG_K3_EARLY_CONS
65 int early_console_init(void)
70 gd->baudrate = CONFIG_BAUDRATE;
72 ret = uclass_get_device_by_seq(UCLASS_SERIAL, CONFIG_K3_EARLY_CONS_IDX,
75 printf("Error getting serial dev for early console! (%d)\n",
80 gd->cur_serial_dev = dev;
81 gd->flags |= GD_FLG_SERIAL_READY;
88 #ifdef CONFIG_SYS_K3_SPL_ATF
92 #ifdef CONFIG_SPL_ENV_SUPPORT
97 switch (spl_boot_device()) {
98 case BOOT_DEVICE_MMC2:
99 part = env_get("bootpart");
100 env_set("storage_interface", "mmc");
101 env_set("fw_dev_part", part);
103 case BOOT_DEVICE_SPI:
104 env_set("storage_interface", "ubi");
105 env_set("fw_ubi_mtdpart", "UBI");
106 env_set("fw_ubi_volume", "UBI0");
109 printf("%s from device %u not supported!\n",
110 __func__, spl_boot_device());
116 #ifdef CONFIG_FS_LOADER
117 int load_firmware(char *name_fw, char *name_loadaddr, u32 *loadaddr)
119 struct udevice *fsdev;
124 #ifdef CONFIG_SPL_ENV_SUPPORT
125 switch (spl_boot_device()) {
126 case BOOT_DEVICE_MMC2:
127 name = env_get(name_fw);
128 *loadaddr = env_get_hex(name_loadaddr, *loadaddr);
131 printf("Loading rproc fw image from device %u not supported!\n",
139 if (!uclass_get_device(UCLASS_FS_FIRMWARE_LOADER, 0, &fsdev)) {
140 size = request_firmware_into_buf(fsdev, name, (void *)*loadaddr,
147 int load_firmware(char *name_fw, char *name_loadaddr, u32 *loadaddr)
153 __weak void start_non_linux_remote_cores(void)
157 void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image)
159 typedef void __noreturn (*image_entry_noargs_t)(void);
160 struct ti_sci_handle *ti_sci = get_ti_sci_handle();
164 /* Release all the exclusive devices held by SPL before starting ATF */
165 ti_sci->ops.dev_ops.release_exclusive_devices(ti_sci);
169 panic("rproc failed to be initialized (%d)\n", ret);
172 start_non_linux_remote_cores();
173 size = load_firmware("name_mcur5f0_0fw", "addr_mcur5f0_0load",
178 * It is assumed that remoteproc device 1 is the corresponding
179 * Cortex-A core which runs ATF. Make sure DT reflects the same.
181 ret = rproc_load(1, spl_image->entry_point, 0x200);
183 panic("%s: ATF failed to load on rproc (%d)\n", __func__, ret);
185 /* Add an extra newline to differentiate the ATF logs from SPL */
186 printf("Starting ATF on ARM64 core...\n\n");
188 ret = rproc_start(1);
190 panic("%s: ATF failed to start on rproc (%d)\n", __func__, ret);
191 if (!(size > 0 && valid_elf_image(loadaddr))) {
192 debug("Shutting down...\n");
193 release_resources_for_core_shutdown();
199 image_entry_noargs_t image_entry =
200 (image_entry_noargs_t)load_elf_image_phdr(loadaddr);
206 #if defined(CONFIG_OF_LIBFDT)
207 int fdt_fixup_msmc_ram(void *blob, char *parent_path, char *node_name)
209 u64 msmc_start = 0, msmc_end = 0, msmc_size, reg[2];
210 struct ti_sci_handle *ti_sci = get_ti_sci_handle();
211 int ret, node, subnode, len, prev_node;
212 u32 range[4], addr, size;
213 const fdt32_t *sub_reg;
215 ti_sci->ops.core_ops.query_msmc(ti_sci, &msmc_start, &msmc_end);
216 msmc_size = msmc_end - msmc_start + 1;
217 debug("%s: msmc_start = 0x%llx, msmc_size = 0x%llx\n", __func__,
218 msmc_start, msmc_size);
220 /* find or create "msmc_sram node */
221 ret = fdt_path_offset(blob, parent_path);
225 node = fdt_find_or_add_subnode(blob, ret, node_name);
229 ret = fdt_setprop_string(blob, node, "compatible", "mmio-sram");
233 reg[0] = cpu_to_fdt64(msmc_start);
234 reg[1] = cpu_to_fdt64(msmc_size);
235 ret = fdt_setprop(blob, node, "reg", reg, sizeof(reg));
239 fdt_setprop_cell(blob, node, "#address-cells", 1);
240 fdt_setprop_cell(blob, node, "#size-cells", 1);
243 range[1] = cpu_to_fdt32(msmc_start >> 32);
244 range[2] = cpu_to_fdt32(msmc_start & 0xffffffff);
245 range[3] = cpu_to_fdt32(msmc_size);
246 ret = fdt_setprop(blob, node, "ranges", range, sizeof(range));
250 subnode = fdt_first_subnode(blob, node);
253 /* Look for invalid subnodes and delete them */
254 while (subnode >= 0) {
255 sub_reg = fdt_getprop(blob, subnode, "reg", &len);
256 addr = fdt_read_number(sub_reg, 1);
258 size = fdt_read_number(sub_reg, 1);
259 debug("%s: subnode = %d, addr = 0x%x. size = 0x%x\n", __func__,
260 subnode, addr, size);
261 if (addr + size > msmc_size ||
262 !strncmp(fdt_get_name(blob, subnode, &len), "sysfw", 5) ||
263 !strncmp(fdt_get_name(blob, subnode, &len), "l3cache", 7)) {
264 fdt_del_node(blob, subnode);
265 debug("%s: deleting subnode %d\n", __func__, subnode);
267 subnode = fdt_first_subnode(blob, node);
269 subnode = fdt_next_subnode(blob, prev_node);
272 subnode = fdt_next_subnode(blob, prev_node);
279 int fdt_disable_node(void *blob, char *node_path)
284 offs = fdt_path_offset(blob, node_path);
286 printf("Node %s not found.\n", node_path);
289 ret = fdt_setprop_string(blob, offs, "status", "disabled");
291 printf("Could not add status property to node %s: %s\n",
292 node_path, fdt_strerror(ret));
300 #ifndef CONFIG_SYSRESET
301 void reset_cpu(ulong ignored)
306 #if defined(CONFIG_DISPLAY_CPUINFO)
307 int print_cpuinfo(void)
312 soc = (readl(CTRLMMR_WKUP_JTAG_ID) &
313 JTAG_ID_PARTNO_MASK) >> JTAG_ID_PARTNO_SHIFT;
314 rev = (readl(CTRLMMR_WKUP_JTAG_ID) &
315 JTAG_ID_VARIANT_MASK) >> JTAG_ID_VARIANT_SHIFT;
326 name = "Unknown Silicon";
329 printf("%s SR ", name);
338 name = "Unknown Revision";
340 printf("%s\n", name);
347 void board_prep_linux(bootm_headers_t *images)
349 debug("Linux kernel Image start = 0x%lx end = 0x%lx\n",
350 images->os.start, images->os.end);
351 __asm_flush_dcache_range(images->os.start,
352 ROUND(images->os.end,
353 CONFIG_SYS_CACHELINE_SIZE));
357 #ifdef CONFIG_CPU_V7R
358 void disable_linefill_optimization(void)
363 * On K3 devices there are 2 conditions where R5F can deadlock:
364 * 1.When software is performing series of store operations to
365 * cacheable write back/write allocate memory region and later
366 * on software execute barrier operation (DSB or DMB). R5F may
367 * hang at the barrier instruction.
368 * 2.When software is performing a mix of load and store operations
369 * within a tight loop and store operations are all writing to
370 * cacheable write back/write allocates memory regions, R5F may
371 * hang at one of the load instruction.
373 * To avoid the above two conditions disable linefill optimization
376 asm("mrc p15, 0, %0, c1, c0, 1" : "=r" (actlr));
377 actlr |= (1 << 13); /* Set DLFO bit */
378 asm("mcr p15, 0, %0, c1, c0, 1" : : "r" (actlr));
382 void remove_fwl_configs(struct fwl_data *fwl_data, size_t fwl_data_size)
384 struct ti_sci_msg_fwl_region region;
385 struct ti_sci_fwl_ops *fwl_ops;
386 struct ti_sci_handle *ti_sci;
389 ti_sci = get_ti_sci_handle();
390 fwl_ops = &ti_sci->ops.fwl_ops;
391 for (i = 0; i < fwl_data_size; i++) {
392 for (j = 0; j < fwl_data[i].regions; j++) {
393 region.fwl_id = fwl_data[i].fwl_id;
395 region.n_permission_regs = 3;
397 fwl_ops->get_fwl_region(ti_sci, ®ion);
399 if (region.control != 0) {
400 pr_debug("Attempting to disable firewall %5d (%25s)\n",
401 region.fwl_id, fwl_data[i].name);
404 if (fwl_ops->set_fwl_region(ti_sci, ®ion))
405 pr_err("Could not disable firewall %5d (%25s)\n",
406 region.fwl_id, fwl_data[i].name);