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