common: Drop net.h from common header
[oweals/u-boot.git] / arch / arm / mach-k3 / common.c
1 // 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 <cpu_func.h>
11 #include <spl.h>
12 #include "common.h"
13 #include <dm.h>
14 #include <remoteproc.h>
15 #include <asm/cache.h>
16 #include <linux/soc/ti/ti_sci_protocol.h>
17 #include <fdt_support.h>
18 #include <asm/arch/sys_proto.h>
19 #include <asm/hardware.h>
20 #include <asm/io.h>
21 #include <fs_loader.h>
22 #include <fs.h>
23 #include <env.h>
24 #include <elf.h>
25
26 struct ti_sci_handle *get_ti_sci_handle(void)
27 {
28         struct udevice *dev;
29         int ret;
30
31         ret = uclass_get_device_by_driver(UCLASS_FIRMWARE,
32                                           DM_GET_DRIVER(ti_sci), &dev);
33         if (ret)
34                 panic("Failed to get SYSFW (%d)\n", ret);
35
36         return (struct ti_sci_handle *)ti_sci_get_handle_from_sysfw(dev);
37 }
38
39 void k3_sysfw_print_ver(void)
40 {
41         struct ti_sci_handle *ti_sci = get_ti_sci_handle();
42         char fw_desc[sizeof(ti_sci->version.firmware_description) + 1];
43
44         /*
45          * Output System Firmware version info. Note that since the
46          * 'firmware_description' field is not guaranteed to be zero-
47          * terminated we manually add a \0 terminator if needed. Further
48          * note that we intentionally no longer rely on the extended
49          * printf() formatter '%.*s' to not having to require a more
50          * full-featured printf() implementation.
51          */
52         strncpy(fw_desc, ti_sci->version.firmware_description,
53                 sizeof(ti_sci->version.firmware_description));
54         fw_desc[sizeof(fw_desc) - 1] = '\0';
55
56         printf("SYSFW ABI: %d.%d (firmware rev 0x%04x '%s')\n",
57                ti_sci->version.abi_major, ti_sci->version.abi_minor,
58                ti_sci->version.firmware_revision, fw_desc);
59 }
60
61 DECLARE_GLOBAL_DATA_PTR;
62
63 #ifdef CONFIG_K3_EARLY_CONS
64 int early_console_init(void)
65 {
66         struct udevice *dev;
67         int ret;
68
69         gd->baudrate = CONFIG_BAUDRATE;
70
71         ret = uclass_get_device_by_seq(UCLASS_SERIAL, CONFIG_K3_EARLY_CONS_IDX,
72                                        &dev);
73         if (ret) {
74                 printf("Error getting serial dev for early console! (%d)\n",
75                        ret);
76                 return ret;
77         }
78
79         gd->cur_serial_dev = dev;
80         gd->flags |= GD_FLG_SERIAL_READY;
81         gd->have_console = 1;
82
83         return 0;
84 }
85 #endif
86
87 #ifdef CONFIG_SYS_K3_SPL_ATF
88
89 void init_env(void)
90 {
91 #ifdef CONFIG_SPL_ENV_SUPPORT
92         char *part;
93
94         env_init();
95         env_relocate();
96         switch (spl_boot_device()) {
97         case BOOT_DEVICE_MMC2:
98                 part = env_get("bootpart");
99                 env_set("storage_interface", "mmc");
100                 env_set("fw_dev_part", part);
101                 break;
102         case BOOT_DEVICE_SPI:
103                 env_set("storage_interface", "ubi");
104                 env_set("fw_ubi_mtdpart", "UBI");
105                 env_set("fw_ubi_volume", "UBI0");
106                 break;
107         default:
108                 printf("%s from device %u not supported!\n",
109                        __func__, spl_boot_device());
110                 return;
111         }
112 #endif
113 }
114
115 #ifdef CONFIG_FS_LOADER
116 int load_firmware(char *name_fw, char *name_loadaddr, u32 *loadaddr)
117 {
118         struct udevice *fsdev;
119         char *name = NULL;
120         int size = 0;
121
122         *loadaddr = 0;
123 #ifdef CONFIG_SPL_ENV_SUPPORT
124         switch (spl_boot_device()) {
125         case BOOT_DEVICE_MMC2:
126                 name = env_get(name_fw);
127                 *loadaddr = env_get_hex(name_loadaddr, *loadaddr);
128                 break;
129         default:
130                 printf("Loading rproc fw image from device %u not supported!\n",
131                        spl_boot_device());
132                 return 0;
133         }
134 #endif
135         if (!*loadaddr)
136                 return 0;
137
138         if (!uclass_get_device(UCLASS_FS_FIRMWARE_LOADER, 0, &fsdev)) {
139                 size = request_firmware_into_buf(fsdev, name, (void *)*loadaddr,
140                                                  0, 0);
141         }
142
143         return size;
144 }
145 #else
146 int load_firmware(char *name_fw, char *name_loadaddr, u32 *loadaddr)
147 {
148         return 0;
149 }
150 #endif
151
152 __weak void start_non_linux_remote_cores(void)
153 {
154 }
155
156 void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image)
157 {
158         typedef void __noreturn (*image_entry_noargs_t)(void);
159         struct ti_sci_handle *ti_sci = get_ti_sci_handle();
160         u32 loadaddr = 0;
161         int ret, size;
162
163         /* Release all the exclusive devices held by SPL before starting ATF */
164         ti_sci->ops.dev_ops.release_exclusive_devices(ti_sci);
165
166         ret = rproc_init();
167         if (ret)
168                 panic("rproc failed to be initialized (%d)\n", ret);
169
170         init_env();
171         start_non_linux_remote_cores();
172         size = load_firmware("name_mcur5f0_0fw", "addr_mcur5f0_0load",
173                              &loadaddr);
174
175
176         /*
177          * It is assumed that remoteproc device 1 is the corresponding
178          * Cortex-A core which runs ATF. Make sure DT reflects the same.
179          */
180         ret = rproc_load(1, spl_image->entry_point, 0x200);
181         if (ret)
182                 panic("%s: ATF failed to load on rproc (%d)\n", __func__, ret);
183
184         /* Add an extra newline to differentiate the ATF logs from SPL */
185         printf("Starting ATF on ARM64 core...\n\n");
186
187         ret = rproc_start(1);
188         if (ret)
189                 panic("%s: ATF failed to start on rproc (%d)\n", __func__, ret);
190         if (!(size > 0 && valid_elf_image(loadaddr))) {
191                 debug("Shutting down...\n");
192                 release_resources_for_core_shutdown();
193
194                 while (1)
195                         asm volatile("wfe");
196         }
197
198         image_entry_noargs_t image_entry =
199                 (image_entry_noargs_t)load_elf_image_phdr(loadaddr);
200
201         image_entry();
202 }
203 #endif
204
205 #if defined(CONFIG_OF_LIBFDT)
206 int fdt_fixup_msmc_ram(void *blob, char *parent_path, char *node_name)
207 {
208         u64 msmc_start = 0, msmc_end = 0, msmc_size, reg[2];
209         struct ti_sci_handle *ti_sci = get_ti_sci_handle();
210         int ret, node, subnode, len, prev_node;
211         u32 range[4], addr, size;
212         const fdt32_t *sub_reg;
213
214         ti_sci->ops.core_ops.query_msmc(ti_sci, &msmc_start, &msmc_end);
215         msmc_size = msmc_end - msmc_start + 1;
216         debug("%s: msmc_start = 0x%llx, msmc_size = 0x%llx\n", __func__,
217               msmc_start, msmc_size);
218
219         /* find or create "msmc_sram node */
220         ret = fdt_path_offset(blob, parent_path);
221         if (ret < 0)
222                 return ret;
223
224         node = fdt_find_or_add_subnode(blob, ret, node_name);
225         if (node < 0)
226                 return node;
227
228         ret = fdt_setprop_string(blob, node, "compatible", "mmio-sram");
229         if (ret < 0)
230                 return ret;
231
232         reg[0] = cpu_to_fdt64(msmc_start);
233         reg[1] = cpu_to_fdt64(msmc_size);
234         ret = fdt_setprop(blob, node, "reg", reg, sizeof(reg));
235         if (ret < 0)
236                 return ret;
237
238         fdt_setprop_cell(blob, node, "#address-cells", 1);
239         fdt_setprop_cell(blob, node, "#size-cells", 1);
240
241         range[0] = 0;
242         range[1] = cpu_to_fdt32(msmc_start >> 32);
243         range[2] = cpu_to_fdt32(msmc_start & 0xffffffff);
244         range[3] = cpu_to_fdt32(msmc_size);
245         ret = fdt_setprop(blob, node, "ranges", range, sizeof(range));
246         if (ret < 0)
247                 return ret;
248
249         subnode = fdt_first_subnode(blob, node);
250         prev_node = 0;
251
252         /* Look for invalid subnodes and delete them */
253         while (subnode >= 0) {
254                 sub_reg = fdt_getprop(blob, subnode, "reg", &len);
255                 addr = fdt_read_number(sub_reg, 1);
256                 sub_reg++;
257                 size = fdt_read_number(sub_reg, 1);
258                 debug("%s: subnode = %d, addr = 0x%x. size = 0x%x\n", __func__,
259                       subnode, addr, size);
260                 if (addr + size > msmc_size ||
261                     !strncmp(fdt_get_name(blob, subnode, &len), "sysfw", 5) ||
262                     !strncmp(fdt_get_name(blob, subnode, &len), "l3cache", 7)) {
263                         fdt_del_node(blob, subnode);
264                         debug("%s: deleting subnode %d\n", __func__, subnode);
265                         if (!prev_node)
266                                 subnode = fdt_first_subnode(blob, node);
267                         else
268                                 subnode = fdt_next_subnode(blob, prev_node);
269                 } else {
270                         prev_node = subnode;
271                         subnode = fdt_next_subnode(blob, prev_node);
272                 }
273         }
274
275         return 0;
276 }
277
278 int fdt_disable_node(void *blob, char *node_path)
279 {
280         int offs;
281         int ret;
282
283         offs = fdt_path_offset(blob, node_path);
284         if (offs < 0) {
285                 printf("Node %s not found.\n", node_path);
286                 return offs;
287         }
288         ret = fdt_setprop_string(blob, offs, "status", "disabled");
289         if (ret < 0) {
290                 printf("Could not add status property to node %s: %s\n",
291                        node_path, fdt_strerror(ret));
292                 return ret;
293         }
294         return 0;
295 }
296
297 #endif
298
299 #ifndef CONFIG_SYSRESET
300 void reset_cpu(ulong ignored)
301 {
302 }
303 #endif
304
305 #if defined(CONFIG_DISPLAY_CPUINFO)
306 int print_cpuinfo(void)
307 {
308         u32 soc, rev;
309         char *name;
310
311         soc = (readl(CTRLMMR_WKUP_JTAG_ID) &
312                 JTAG_ID_PARTNO_MASK) >> JTAG_ID_PARTNO_SHIFT;
313         rev = (readl(CTRLMMR_WKUP_JTAG_ID) &
314                 JTAG_ID_VARIANT_MASK) >> JTAG_ID_VARIANT_SHIFT;
315
316         printf("SoC:   ");
317         switch (soc) {
318         case AM65X:
319                 name = "AM65x";
320                 break;
321         case J721E:
322                 name = "J721E";
323                 break;
324         default:
325                 name = "Unknown Silicon";
326         };
327
328         printf("%s SR ", name);
329         switch (rev) {
330         case REV_PG1_0:
331                 name = "1.0";
332                 break;
333         case REV_PG2_0:
334                 name = "2.0";
335                 break;
336         default:
337                 name = "Unknown Revision";
338         };
339         printf("%s\n", name);
340
341         return 0;
342 }
343 #endif
344
345 #ifdef CONFIG_ARM64
346 void board_prep_linux(bootm_headers_t *images)
347 {
348         debug("Linux kernel Image start = 0x%lx end = 0x%lx\n",
349               images->os.start, images->os.end);
350         __asm_flush_dcache_range(images->os.start,
351                                  ROUND(images->os.end,
352                                        CONFIG_SYS_CACHELINE_SIZE));
353 }
354 #endif
355
356 #ifdef CONFIG_CPU_V7R
357 void disable_linefill_optimization(void)
358 {
359         u32 actlr;
360
361         /*
362          * On K3 devices there are 2 conditions where R5F can deadlock:
363          * 1.When software is performing series of store operations to
364          *   cacheable write back/write allocate memory region and later
365          *   on software execute barrier operation (DSB or DMB). R5F may
366          *   hang at the barrier instruction.
367          * 2.When software is performing a mix of load and store operations
368          *   within a tight loop and store operations are all writing to
369          *   cacheable write back/write allocates memory regions, R5F may
370          *   hang at one of the load instruction.
371          *
372          * To avoid the above two conditions disable linefill optimization
373          * inside Cortex R5F.
374          */
375         asm("mrc p15, 0, %0, c1, c0, 1" : "=r" (actlr));
376         actlr |= (1 << 13); /* Set DLFO bit  */
377         asm("mcr p15, 0, %0, c1, c0, 1" : : "r" (actlr));
378 }
379 #endif
380
381 void remove_fwl_configs(struct fwl_data *fwl_data, size_t fwl_data_size)
382 {
383         struct ti_sci_msg_fwl_region region;
384         struct ti_sci_fwl_ops *fwl_ops;
385         struct ti_sci_handle *ti_sci;
386         size_t i, j;
387
388         ti_sci = get_ti_sci_handle();
389         fwl_ops = &ti_sci->ops.fwl_ops;
390         for (i = 0; i < fwl_data_size; i++) {
391                 for (j = 0; j <  fwl_data[i].regions; j++) {
392                         region.fwl_id = fwl_data[i].fwl_id;
393                         region.region = j;
394                         region.n_permission_regs = 3;
395
396                         fwl_ops->get_fwl_region(ti_sci, &region);
397
398                         if (region.control != 0) {
399                                 pr_debug("Attempting to disable firewall %5d (%25s)\n",
400                                          region.fwl_id, fwl_data[i].name);
401                                 region.control = 0;
402
403                                 if (fwl_ops->set_fwl_region(ti_sci, &region))
404                                         pr_err("Could not disable firewall %5d (%25s)\n",
405                                                region.fwl_id, fwl_data[i].name);
406                         }
407                 }
408         }
409 }