GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)

This commit is contained in:
lai
2026-09-06 03:52:57 +08:00
commit b1928b41c0
21813 changed files with 4413081 additions and 0 deletions
@@ -0,0 +1,138 @@
if ARCH_K3
choice
prompt "Texas Instruments' K3 based SoC select"
optional
config SOC_K3_AM6
bool "TI's K3 based AM6 SoC Family Support"
config SOC_K3_J721E
bool "TI's K3 based J721E SoC Family Support"
endchoice
config SYS_SOC
default "k3"
config SYS_K3_NON_SECURE_MSRAM_SIZE
hex
default 0x80000 if SOC_K3_AM6
default 0x100000 if SOC_K3_J721E
help
Describes the total size of the MCU MSRAM. This doesn't
specify the total size of SPL as ROM can use some part
of this RAM. Once ROM gives control to SPL then this
complete size can be usable.
config SYS_K3_MAX_DOWNLODABLE_IMAGE_SIZE
hex
default 0x58000 if SOC_K3_AM6
default 0xc0000 if SOC_K3_J721E
help
Describes the maximum size of the image that ROM can download
from any boot media.
config SYS_K3_MCU_SCRATCHPAD_BASE
hex
default 0x40280000 if SOC_K3_AM6
default 0x40280000 if SOC_K3_J721E
help
Describes the base address of MCU Scratchpad RAM.
config SYS_K3_MCU_SCRATCHPAD_SIZE
hex
default 0x200 if SOC_K3_AM6
default 0x200 if SOC_K3_J721E
help
Describes the size of MCU Scratchpad RAM.
config SYS_K3_BOOT_PARAM_TABLE_INDEX
hex
default 0x41c7fbfc if SOC_K3_AM6
default 0x41cffc00 if SOC_K3_J721E
help
Address at which ROM stores the value which determines if SPL
is booted up by primary boot media or secondary boot media.
config SYS_K3_KEY
string "Key used to generate x509 certificate"
help
This option enables to provide a custom key that can be used for
generating x509 certificate for spl binary. If not needed leave
it blank so that a random key is generated and used.
config SYS_K3_BOOT_CORE_ID
int
default 16
config K3_EARLY_CONS
bool "Activate to allow for an early console during SPL"
depends on SPL
help
Turn this option on to enable an early console functionality in SPL
before the main console is being brought up. This can be useful in
situations where the main console is dependent on System Firmware
(SYSFW) being up and running, which is usually not the case during
the very early stages of boot. Using this early console functionality
will allow for an alternate serial port to be used to support things
like UART-based boot and early diagnostic messages until the main
console is ready to get activated.
config K3_EARLY_CONS_IDX
depends on K3_EARLY_CONS
int "Index of serial device to use for SPL early console"
default 1
help
Use this option to set the index of the serial device to be used
for the early console during SPL execution.
config K3_LOAD_SYSFW
bool
depends on SPL
config K3_SYSFW_IMAGE_NAME
string "File name of SYSFW firmware and configuration blob"
depends on K3_LOAD_SYSFW
default "sysfw.itb"
help
Filename of the combined System Firmware and configuration image tree
blob to be loaded when booting from a filesystem.
config K3_SYSFW_IMAGE_MMCSD_RAW_MODE_SECT
hex "MMC sector to load SYSFW firmware and configuration blob from"
depends on K3_LOAD_SYSFW && SYS_MMCSD_RAW_MODE_U_BOOT_USE_SECTOR
default 0x3600
help
Address on the MMC to load the combined System Firmware and
configuration image tree blob from, when the MMC is being used
in raw mode. Units: MMC sectors (1 sector = 512 bytes).
config K3_SYSFW_IMAGE_MMCSD_RAW_MODE_PART
hex "MMC partition to load SYSFW firmware and configuration blob from"
depends on K3_LOAD_SYSFW && SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION
default 2
help
Partition on the MMC to the combined System Firmware and configuration
image tree blob from, when the MMC is being used in raw mode.
config K3_SYSFW_IMAGE_SIZE_MAX
int "Amount of memory dynamically allocated for loading SYSFW blob"
depends on K3_LOAD_SYSFW
default 276000
help
Amount of memory (in bytes) reserved through dynamic allocation at
runtime for loading the combined System Firmware and configuration image
tree blob. Keep it as tight as possible, as this directly affects the
overall SPL memory footprint.
config SYS_K3_SPL_ATF
bool "Start Cortex-A from SPL"
depends on SPL && CPU_V7R
help
Enabling this will try to start Cortex-A (typically with ATF)
after SPL from R5.
source "board/ti/am65x/Kconfig"
source "board/ti/j721e/Kconfig"
endif
@@ -0,0 +1,14 @@
# SPDX-License-Identifier: GPL-2.0+
#
# Copyright (C) 2017-2018 Texas Instruments Incorporated - http://www.ti.com/
# Lokesh Vutla <lokeshvutla@ti.com>
obj-$(CONFIG_SOC_K3_AM6) += am6_init.o
obj-$(CONFIG_SOC_K3_J721E) += j721e_init.o
obj-$(CONFIG_ARM64) += arm64-mmu.o
obj-$(CONFIG_CPU_V7R) += r5_mpu.o lowlevel_init.o
obj-$(CONFIG_TI_SECURE_DEVICE) += security.o
ifeq ($(CONFIG_SPL_BUILD),y)
obj-$(CONFIG_K3_LOAD_SYSFW) += sysfw-loader.o
endif
obj-y += common.o
@@ -0,0 +1,270 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* K3: Architecture initialization
*
* Copyright (C) 2017-2018 Texas Instruments Incorporated - http://www.ti.com/
* Lokesh Vutla <lokeshvutla@ti.com>
*/
#include <common.h>
#include <asm/io.h>
#include <spl.h>
#include <asm/arch/hardware.h>
#include <asm/arch/sysfw-loader.h>
#include <asm/arch/sys_proto.h>
#include "common.h"
#include <dm.h>
#include <dm/uclass-internal.h>
#include <dm/pinctrl.h>
#include <linux/soc/ti/ti_sci_protocol.h>
#ifdef CONFIG_SPL_BUILD
static void mmr_unlock(u32 base, u32 partition)
{
/* Translate the base address */
phys_addr_t part_base = base + partition * CTRL_MMR0_PARTITION_SIZE;
/* Unlock the requested partition if locked using two-step sequence */
writel(CTRLMMR_LOCK_KICK0_UNLOCK_VAL, part_base + CTRLMMR_LOCK_KICK0);
writel(CTRLMMR_LOCK_KICK1_UNLOCK_VAL, part_base + CTRLMMR_LOCK_KICK1);
}
static void ctrl_mmr_unlock(void)
{
/* Unlock all WKUP_CTRL_MMR0 module registers */
mmr_unlock(WKUP_CTRL_MMR0_BASE, 0);
mmr_unlock(WKUP_CTRL_MMR0_BASE, 1);
mmr_unlock(WKUP_CTRL_MMR0_BASE, 2);
mmr_unlock(WKUP_CTRL_MMR0_BASE, 3);
mmr_unlock(WKUP_CTRL_MMR0_BASE, 6);
mmr_unlock(WKUP_CTRL_MMR0_BASE, 7);
/* Unlock all MCU_CTRL_MMR0 module registers */
mmr_unlock(MCU_CTRL_MMR0_BASE, 0);
mmr_unlock(MCU_CTRL_MMR0_BASE, 1);
mmr_unlock(MCU_CTRL_MMR0_BASE, 2);
mmr_unlock(MCU_CTRL_MMR0_BASE, 6);
/* Unlock all CTRL_MMR0 module registers */
mmr_unlock(CTRL_MMR0_BASE, 0);
mmr_unlock(CTRL_MMR0_BASE, 1);
mmr_unlock(CTRL_MMR0_BASE, 2);
mmr_unlock(CTRL_MMR0_BASE, 3);
mmr_unlock(CTRL_MMR0_BASE, 6);
mmr_unlock(CTRL_MMR0_BASE, 7);
}
/*
* This uninitialized global variable would normal end up in the .bss section,
* but the .bss is cleared between writing and reading this variable, so move
* it to the .data section.
*/
u32 bootindex __attribute__((section(".data")));
static void store_boot_index_from_rom(void)
{
bootindex = *(u32 *)(CONFIG_SYS_K3_BOOT_PARAM_TABLE_INDEX);
}
void board_init_f(ulong dummy)
{
#if defined(CONFIG_K3_LOAD_SYSFW) || defined(CONFIG_K3_AM654_DDRSS)
struct udevice *dev;
int ret;
#endif
/*
* Cannot delay this further as there is a chance that
* K3_BOOT_PARAM_TABLE_INDEX can be over written by SPL MALLOC section.
*/
store_boot_index_from_rom();
/* Make all control module registers accessible */
ctrl_mmr_unlock();
#ifdef CONFIG_CPU_V7R
disable_linefill_optimization();
setup_k3_mpu_regions();
#endif
/* Init DM early in-order to invoke system controller */
spl_early_init();
#ifdef CONFIG_K3_LOAD_SYSFW
/*
* Process pinctrl for the serial0 a.k.a. WKUP_UART0 module and continue
* regardless of the result of pinctrl. Do this without probing the
* device, but instead by searching the device that would request the
* given sequence number if probed. The UART will be used by the system
* firmware (SYSFW) image for various purposes and SYSFW depends on us
* to initialize its pin settings.
*/
ret = uclass_find_device_by_seq(UCLASS_SERIAL, 0, true, &dev);
if (!ret)
pinctrl_select_state(dev, "default");
/*
* Load, start up, and configure system controller firmware. Provide
* the U-Boot console init function to the SYSFW post-PM configuration
* callback hook, effectively switching on (or over) the console
* output.
*/
k3_sysfw_loader(preloader_console_init);
#else
/* Prepare console output */
preloader_console_init();
#endif
/* Perform EEPROM-based board detection */
do_board_detect();
#if defined(CONFIG_CPU_V7R) && defined(CONFIG_K3_AVS0)
ret = uclass_get_device_by_driver(UCLASS_MISC, DM_GET_DRIVER(k3_avs),
&dev);
if (ret)
printf("AVS init failed: %d\n", ret);
#endif
#ifdef CONFIG_K3_AM654_DDRSS
ret = uclass_get_device(UCLASS_RAM, 0, &dev);
if (ret)
panic("DRAM init failed: %d\n", ret);
#endif
}
u32 spl_boot_mode(const u32 boot_device)
{
#if defined(CONFIG_SUPPORT_EMMC_BOOT)
u32 devstat = readl(CTRLMMR_MAIN_DEVSTAT);
u32 bootmode = (devstat & CTRLMMR_MAIN_DEVSTAT_BOOTMODE_MASK) >>
CTRLMMR_MAIN_DEVSTAT_BOOTMODE_SHIFT;
/* eMMC boot0 mode is only supported for primary boot */
if (bootindex == K3_PRIMARY_BOOTMODE &&
bootmode == BOOT_DEVICE_MMC1)
return MMCSD_MODE_EMMCBOOT;
#endif
/* Everything else use filesystem if available */
#if defined(CONFIG_SPL_FS_FAT) || defined(CONFIG_SPL_FS_EXT4)
return MMCSD_MODE_FS;
#else
return MMCSD_MODE_RAW;
#endif
}
static u32 __get_backup_bootmedia(u32 devstat)
{
u32 bkup_boot = (devstat & CTRLMMR_MAIN_DEVSTAT_BKUP_BOOTMODE_MASK) >>
CTRLMMR_MAIN_DEVSTAT_BKUP_BOOTMODE_SHIFT;
switch (bkup_boot) {
case BACKUP_BOOT_DEVICE_USB:
return BOOT_DEVICE_USB;
case BACKUP_BOOT_DEVICE_UART:
return BOOT_DEVICE_UART;
case BACKUP_BOOT_DEVICE_ETHERNET:
return BOOT_DEVICE_ETHERNET;
case BACKUP_BOOT_DEVICE_MMC2:
{
u32 port = (devstat & CTRLMMR_MAIN_DEVSTAT_BKUP_MMC_PORT_MASK) >>
CTRLMMR_MAIN_DEVSTAT_BKUP_MMC_PORT_SHIFT;
if (port == 0x0)
return BOOT_DEVICE_MMC1;
return BOOT_DEVICE_MMC2;
}
case BACKUP_BOOT_DEVICE_SPI:
return BOOT_DEVICE_SPI;
case BACKUP_BOOT_DEVICE_HYPERFLASH:
return BOOT_DEVICE_HYPERFLASH;
case BACKUP_BOOT_DEVICE_I2C:
return BOOT_DEVICE_I2C;
};
return BOOT_DEVICE_RAM;
}
static u32 __get_primary_bootmedia(u32 devstat)
{
u32 bootmode = (devstat & CTRLMMR_MAIN_DEVSTAT_BOOTMODE_MASK) >>
CTRLMMR_MAIN_DEVSTAT_BOOTMODE_SHIFT;
if (bootmode == BOOT_DEVICE_OSPI || bootmode == BOOT_DEVICE_QSPI)
bootmode = BOOT_DEVICE_SPI;
if (bootmode == BOOT_DEVICE_MMC2) {
u32 port = (devstat & CTRLMMR_MAIN_DEVSTAT_MMC_PORT_MASK) >>
CTRLMMR_MAIN_DEVSTAT_MMC_PORT_SHIFT;
if (port == 0x0)
bootmode = BOOT_DEVICE_MMC1;
} else if (bootmode == BOOT_DEVICE_MMC1) {
u32 port = (devstat & CTRLMMR_MAIN_DEVSTAT_EMMC_PORT_MASK) >>
CTRLMMR_MAIN_DEVSTAT_EMMC_PORT_SHIFT;
if (port == 0x1)
bootmode = BOOT_DEVICE_MMC2;
}
return bootmode;
}
u32 spl_boot_device(void)
{
u32 devstat = readl(CTRLMMR_MAIN_DEVSTAT);
if (bootindex == K3_PRIMARY_BOOTMODE)
return __get_primary_bootmedia(devstat);
else
return __get_backup_bootmedia(devstat);
}
#endif
#ifdef CONFIG_SYS_K3_SPL_ATF
#define AM6_DEV_MCU_RTI0 134
#define AM6_DEV_MCU_RTI1 135
#define AM6_DEV_MCU_ARMSS0_CPU0 159
#define AM6_DEV_MCU_ARMSS0_CPU1 245
void release_resources_for_core_shutdown(void)
{
struct ti_sci_handle *ti_sci = get_ti_sci_handle();
struct ti_sci_dev_ops *dev_ops = &ti_sci->ops.dev_ops;
struct ti_sci_proc_ops *proc_ops = &ti_sci->ops.proc_ops;
int ret;
u32 i;
const u32 put_device_ids[] = {
AM6_DEV_MCU_RTI0,
AM6_DEV_MCU_RTI1,
};
/* Iterate through list of devices to put (shutdown) */
for (i = 0; i < ARRAY_SIZE(put_device_ids); i++) {
u32 id = put_device_ids[i];
ret = dev_ops->put_device(ti_sci, id);
if (ret)
panic("Failed to put device %u (%d)\n", id, ret);
}
const u32 put_core_ids[] = {
AM6_DEV_MCU_ARMSS0_CPU1,
AM6_DEV_MCU_ARMSS0_CPU0, /* Handle CPU0 after CPU1 */
};
/* Iterate through list of cores to put (shutdown) */
for (i = 0; i < ARRAY_SIZE(put_core_ids); i++) {
u32 id = put_core_ids[i];
/*
* Queue up the core shutdown request. Note that this call
* needs to be followed up by an actual invocation of an WFE
* or WFI CPU instruction.
*/
ret = proc_ops->proc_shutdown_no_wait(ti_sci, id);
if (ret)
panic("Failed sending core %u shutdown message (%d)\n",
id, ret);
}
}
#endif
@@ -0,0 +1,112 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* K3: ARM64 MMU setup
*
* Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
* Lokesh Vutla <lokeshvutla@ti.com>
* (This file is derived from arch/arm/mach-zynqmp/cpu.c)
*
*/
#include <common.h>
#include <asm/system.h>
#include <asm/armv8/mmu.h>
#ifdef CONFIG_SOC_K3_AM6
/* NR_DRAM_BANKS + 32bit IO + 64bit IO + terminator */
#define NR_MMU_REGIONS (CONFIG_NR_DRAM_BANKS + 5)
/* ToDo: Add 64bit IO */
struct mm_region am654_mem_map[NR_MMU_REGIONS] = {
{
.virt = 0x0UL,
.phys = 0x0UL,
.size = 0x80000000UL,
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
PTE_BLOCK_NON_SHARE |
PTE_BLOCK_PXN | PTE_BLOCK_UXN
}, {
.virt = 0x80000000UL,
.phys = 0x80000000UL,
.size = 0x20000000UL,
.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
PTE_BLOCK_INNER_SHARE
}, {
.virt = 0xa0000000UL,
.phys = 0xa0000000UL,
.size = 0x02100000UL,
.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL_NC) |
PTE_BLOCK_INNER_SHARE
}, {
.virt = 0xa2100000UL,
.phys = 0xa2100000UL,
.size = 0x5df00000UL,
.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
PTE_BLOCK_INNER_SHARE
}, {
.virt = 0x880000000UL,
.phys = 0x880000000UL,
.size = 0x80000000UL,
.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
PTE_BLOCK_INNER_SHARE
}, {
/* List terminator */
0,
}
};
struct mm_region *mem_map = am654_mem_map;
#endif /* CONFIG_SOC_K3_AM6 */
#ifdef CONFIG_SOC_K3_J721E
/* NR_DRAM_BANKS + 32bit IO + 64bit IO + terminator */
#define NR_MMU_REGIONS (CONFIG_NR_DRAM_BANKS + 5)
/* ToDo: Add 64bit IO */
struct mm_region j721e_mem_map[NR_MMU_REGIONS] = {
{
.virt = 0x0UL,
.phys = 0x0UL,
.size = 0x80000000UL,
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
PTE_BLOCK_NON_SHARE |
PTE_BLOCK_PXN | PTE_BLOCK_UXN
}, {
.virt = 0x80000000UL,
.phys = 0x80000000UL,
.size = 0x20000000UL,
.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
PTE_BLOCK_INNER_SHARE
}, {
.virt = 0xa0000000UL,
.phys = 0xa0000000UL,
.size = 0x1bc00000UL,
.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL_NC) |
PTE_BLOCK_NON_SHARE
}, {
.virt = 0xbbc00000UL,
.phys = 0xbbc00000UL,
.size = 0x44400000UL,
.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
PTE_BLOCK_INNER_SHARE
}, {
.virt = 0x880000000UL,
.phys = 0x880000000UL,
.size = 0x80000000UL,
.attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
PTE_BLOCK_INNER_SHARE
}, {
.virt = 0x500000000UL,
.phys = 0x500000000UL,
.size = 0x400000000UL,
.attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
PTE_BLOCK_NON_SHARE |
PTE_BLOCK_PXN | PTE_BLOCK_UXN
}, {
/* List terminator */
0,
}
};
struct mm_region *mem_map = j721e_mem_map;
#endif /* CONFIG_SOC_K3_J721E */
@@ -0,0 +1,271 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* K3: Common Architecture initialization
*
* Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
* Lokesh Vutla <lokeshvutla@ti.com>
*/
#include <common.h>
#include <spl.h>
#include "common.h"
#include <dm.h>
#include <remoteproc.h>
#include <linux/soc/ti/ti_sci_protocol.h>
#include <fdt_support.h>
#include <asm/arch/sys_proto.h>
#include <asm/hardware.h>
#include <asm/io.h>
struct ti_sci_handle *get_ti_sci_handle(void)
{
struct udevice *dev;
int ret;
ret = uclass_get_device_by_driver(UCLASS_FIRMWARE,
DM_GET_DRIVER(ti_sci), &dev);
if (ret)
panic("Failed to get SYSFW (%d)\n", ret);
return (struct ti_sci_handle *)ti_sci_get_handle_from_sysfw(dev);
}
DECLARE_GLOBAL_DATA_PTR;
#ifdef CONFIG_K3_EARLY_CONS
int early_console_init(void)
{
struct udevice *dev;
int ret;
gd->baudrate = CONFIG_BAUDRATE;
ret = uclass_get_device_by_seq(UCLASS_SERIAL, CONFIG_K3_EARLY_CONS_IDX,
&dev);
if (ret) {
printf("Error getting serial dev for early console! (%d)\n",
ret);
return ret;
}
gd->cur_serial_dev = dev;
gd->flags |= GD_FLG_SERIAL_READY;
gd->have_console = 1;
return 0;
}
#endif
#ifdef CONFIG_SYS_K3_SPL_ATF
void __noreturn jump_to_image_no_args(struct spl_image_info *spl_image)
{
struct ti_sci_handle *ti_sci = get_ti_sci_handle();
int ret;
/* Release all the exclusive devices held by SPL before starting ATF */
ti_sci->ops.dev_ops.release_exclusive_devices(ti_sci);
/*
* It is assumed that remoteproc device 1 is the corresponding
* Cortex-A core which runs ATF. Make sure DT reflects the same.
*/
ret = rproc_dev_init(1);
if (ret)
panic("%s: ATF failed to initialize on rproc (%d)\n", __func__,
ret);
ret = rproc_load(1, spl_image->entry_point, 0x200);
if (ret)
panic("%s: ATF failed to load on rproc (%d)\n", __func__, ret);
/* Add an extra newline to differentiate the ATF logs from SPL */
printf("Starting ATF on ARM64 core...\n\n");
ret = rproc_start(1);
if (ret)
panic("%s: ATF failed to start on rproc (%d)\n", __func__, ret);
debug("Releasing resources...\n");
release_resources_for_core_shutdown();
debug("Finalizing core shutdown...\n");
while (1)
asm volatile("wfe");
}
#endif
#if defined(CONFIG_OF_LIBFDT)
int fdt_fixup_msmc_ram(void *blob, char *parent_path, char *node_name)
{
u64 msmc_start = 0, msmc_end = 0, msmc_size, reg[2];
struct ti_sci_handle *ti_sci = get_ti_sci_handle();
int ret, node, subnode, len, prev_node;
u32 range[4], addr, size;
const fdt32_t *sub_reg;
ti_sci->ops.core_ops.query_msmc(ti_sci, &msmc_start, &msmc_end);
msmc_size = msmc_end - msmc_start + 1;
debug("%s: msmc_start = 0x%llx, msmc_size = 0x%llx\n", __func__,
msmc_start, msmc_size);
/* find or create "msmc_sram node */
ret = fdt_path_offset(blob, parent_path);
if (ret < 0)
return ret;
node = fdt_find_or_add_subnode(blob, ret, node_name);
if (node < 0)
return node;
ret = fdt_setprop_string(blob, node, "compatible", "mmio-sram");
if (ret < 0)
return ret;
reg[0] = cpu_to_fdt64(msmc_start);
reg[1] = cpu_to_fdt64(msmc_size);
ret = fdt_setprop(blob, node, "reg", reg, sizeof(reg));
if (ret < 0)
return ret;
fdt_setprop_cell(blob, node, "#address-cells", 1);
fdt_setprop_cell(blob, node, "#size-cells", 1);
range[0] = 0;
range[1] = cpu_to_fdt32(msmc_start >> 32);
range[2] = cpu_to_fdt32(msmc_start & 0xffffffff);
range[3] = cpu_to_fdt32(msmc_size);
ret = fdt_setprop(blob, node, "ranges", range, sizeof(range));
if (ret < 0)
return ret;
subnode = fdt_first_subnode(blob, node);
prev_node = 0;
/* Look for invalid subnodes and delete them */
while (subnode >= 0) {
sub_reg = fdt_getprop(blob, subnode, "reg", &len);
addr = fdt_read_number(sub_reg, 1);
sub_reg++;
size = fdt_read_number(sub_reg, 1);
debug("%s: subnode = %d, addr = 0x%x. size = 0x%x\n", __func__,
subnode, addr, size);
if (addr + size > msmc_size ||
!strncmp(fdt_get_name(blob, subnode, &len), "sysfw", 5) ||
!strncmp(fdt_get_name(blob, subnode, &len), "l3cache", 7)) {
fdt_del_node(blob, subnode);
debug("%s: deleting subnode %d\n", __func__, subnode);
if (!prev_node)
subnode = fdt_first_subnode(blob, node);
else
subnode = fdt_next_subnode(blob, prev_node);
} else {
prev_node = subnode;
subnode = fdt_next_subnode(blob, prev_node);
}
}
return 0;
}
int fdt_disable_node(void *blob, char *node_path)
{
int offs;
int ret;
offs = fdt_path_offset(blob, node_path);
if (offs < 0) {
debug("Node %s not found.\n", node_path);
return 0;
}
ret = fdt_setprop_string(blob, offs, "status", "disabled");
if (ret < 0) {
printf("Could not add status property to node %s: %s\n",
node_path, fdt_strerror(ret));
return ret;
}
return 0;
}
#endif
#ifndef CONFIG_SYSRESET
void reset_cpu(ulong ignored)
{
}
#endif
#if defined(CONFIG_DISPLAY_CPUINFO)
int print_cpuinfo(void)
{
u32 soc, rev;
char *name;
soc = (readl(CTRLMMR_WKUP_JTAG_DEVICE_ID) &
DEVICE_ID_FAMILY_MASK) >> DEVICE_ID_FAMILY_SHIFT;
rev = (readl(CTRLMMR_WKUP_JTAG_ID) &
JTAG_ID_VARIANT_MASK) >> JTAG_ID_VARIANT_SHIFT;
printf("SoC: ");
switch (soc) {
case AM654:
name = "AM654";
break;
case J721E:
name = "J721E";
break;
default:
name = "Unknown Silicon";
};
printf("%s PG ", name);
switch (rev) {
case REV_PG1_0:
name = "1.0";
break;
case REV_PG2_0:
name = "2.0";
break;
default:
name = "Unknown Revision";
};
printf("%s\n", name);
return 0;
}
#endif
#ifdef CONFIG_ARM64
void board_prep_linux(bootm_headers_t *images)
{
debug("Linux kernel Image start = 0x%lx end = 0x%lx\n",
images->os.start, images->os.end);
__asm_flush_dcache_range(images->os.start,
ROUND(images->os.end,
CONFIG_SYS_CACHELINE_SIZE));
}
#endif
#ifdef CONFIG_CPU_V7R
void disable_linefill_optimization(void)
{
u32 actlr;
/*
* On K3 devices there are 2 conditions where R5F can deadlock:
* 1.When software is performing series of store operations to
* cacheable write back/write allocate memory region and later
* on software execute barrier operation (DSB or DMB). R5F may
* hang at the barrier instruction.
* 2.When software is performing a mix of load and store operations
* within a tight loop and store operations are all writing to
* cacheable write back/write allocates memory regions, R5F may
* hang at one of the load instruction.
*
* To avoid the above two conditions disable linefill optimization
* inside Cortex R5F.
*/
asm("mrc p15, 0, %0, c1, c0, 1" : "=r" (actlr));
actlr |= (1 << 13); /* Set DLFO bit */
asm("mcr p15, 0, %0, c1, c0, 1" : : "r" (actlr));
}
#endif
@@ -0,0 +1,19 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* K3: Architecture common definitions
*
* Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
* Lokesh Vutla <lokeshvutla@ti.com>
*/
#include <asm/armv7_mpu.h>
#define AM654 2
#define J721E 4
#define REV_PG1_0 0
#define REV_PG2_0 1
void setup_k3_mpu_regions(void);
int early_console_init(void);
void disable_linefill_optimization(void);
@@ -0,0 +1,78 @@
# SPDX-License-Identifier: GPL-2.0+
#
# Copyright (C) 2017-2018 Texas Instruments Incorporated - http://www.ti.com/
# Lokesh Vutla <lokeshvutla@ti.com>
ifdef CONFIG_SPL_BUILD
# Openssl is required to generate x509 certificate.
# Error out if openssl is not available.
ifeq ($(shell which openssl),)
$(error "No openssl in $(PATH), consider installing openssl")
endif
IMAGE_SIZE= $(shell cat $(obj)/u-boot-spl.bin | wc -c)
MAX_SIZE= $(shell printf "%d" $(CONFIG_SYS_K3_MAX_DOWNLODABLE_IMAGE_SIZE))
ifeq ($(CONFIG_SYS_K3_KEY), "")
KEY=""
# On HS use real key or warn if not available
ifeq ($(CONFIG_TI_SECURE_DEVICE),y)
ifneq ($(wildcard $(TI_SECURE_DEV_PKG)/keys/custMpk.pem),)
KEY=$(TI_SECURE_DEV_PKG)/keys/custMpk.pem
else
$(warning "WARNING: signing key not found. Random key will NOT work on HS hardware!")
endif
endif
else
KEY=$(patsubst "%",$(srctree)/%,$(CONFIG_SYS_K3_KEY))
endif
# tiboot3.bin is mandated by ROM and ROM only supports R5 boot.
# So restrict tiboot3.bin creation for CPU_V7R.
ifdef CONFIG_CPU_V7R
image_check: $(obj)/u-boot-spl.bin FORCE
@if [ $(IMAGE_SIZE) -gt $(MAX_SIZE) ]; then \
echo "===============================================" >&2; \
echo "ERROR: Final Image too big. " >&2; \
echo "$< size = $(IMAGE_SIZE), max size = $(MAX_SIZE)" >&2; \
echo "===============================================" >&2; \
exit 1; \
fi
tiboot3.bin: image_check FORCE
$(srctree)/tools/k3_gen_x509_cert.sh -c 16 -b $(obj)/u-boot-spl.bin \
-o $@ -l $(CONFIG_SPL_TEXT_BASE) -k $(KEY)
ALL-y += tiboot3.bin
endif
ifdef CONFIG_ARM64
ifeq ($(CONFIG_TI_SECURE_DEVICE),y)
SPL_ITS := u-boot-spl-k3_HS.its
$(SPL_ITS): FORCE
IS_HS=1 \
$(srctree)/tools/k3_fit_atf.sh \
$(patsubst %,$(obj)/dts/%.dtb,$(subst ",,$(CONFIG_SPL_OF_LIST))) > $@
ALL-y += tispl.bin_HS
else
SPL_ITS := u-boot-spl-k3.its
$(SPL_ITS): FORCE
$(srctree)/tools/k3_fit_atf.sh \
$(patsubst %,$(obj)/dts/%.dtb,$(subst ",,$(CONFIG_SPL_OF_LIST))) > $@
ALL-y += tispl.bin
endif
endif
else
ifeq ($(CONFIG_TI_SECURE_DEVICE),y)
ALL-y += u-boot.img_HS
else
ALL-y += u-boot.img
endif
endif
include $(srctree)/arch/arm/mach-k3/config_secure.mk
@@ -0,0 +1,44 @@
# SPDX-License-Identifier: GPL-2.0
#
# Copyright (C) 2018 Texas Instruments, Incorporated - http://www.ti.com/
# Andrew F. Davis <afd@ti.com>
quiet_cmd_k3secureimg = SECURE $@
ifneq ($(TI_SECURE_DEV_PKG),)
ifneq ($(wildcard $(TI_SECURE_DEV_PKG)/scripts/secure-binary-image.sh),)
cmd_k3secureimg = $(TI_SECURE_DEV_PKG)/scripts/secure-binary-image.sh \
$< $@ \
$(if $(KBUILD_VERBOSE:1=), >/dev/null)
else
cmd_k3secureimg = echo "WARNING:" \
"$(TI_SECURE_DEV_PKG)/scripts/secure-binary-image.sh not found." \
"$@ was NOT secured!"; cp $< $@
endif
else
cmd_k3secureimg = echo "WARNING: TI_SECURE_DEV_PKG environment" \
"variable must be defined for TI secure devices." \
"$@ was NOT secured!"; cp $< $@
endif
%.dtb_HS: %.dtb FORCE
$(call if_changed,k3secureimg)
$(obj)/u-boot-spl-nodtb.bin_HS: $(obj)/u-boot-spl-nodtb.bin FORCE
$(call if_changed,k3secureimg)
tispl.bin_HS: $(obj)/u-boot-spl-nodtb.bin_HS $(patsubst %,$(obj)/dts/%.dtb_HS,$(subst ",,$(CONFIG_SPL_OF_LIST))) $(SPL_ITS) FORCE
$(call if_changed,mkfitimage)
MKIMAGEFLAGS_u-boot.img_HS = -f auto -A $(ARCH) -T firmware -C none -O u-boot \
-a $(CONFIG_SYS_TEXT_BASE) -e $(CONFIG_SYS_UBOOT_START) \
-n "U-Boot $(UBOOTRELEASE) for $(BOARD) board" -E \
$(patsubst %,-b arch/$(ARCH)/dts/%.dtb_HS,$(subst ",,$(CONFIG_OF_LIST)))
OF_LIST_TARGETS = $(patsubst %,arch/$(ARCH)/dts/%.dtb,$(subst ",,$(CONFIG_OF_LIST)))
$(OF_LIST_TARGETS): dtbs
u-boot-nodtb.bin_HS: u-boot-nodtb.bin FORCE
$(call if_changed,k3secureimg)
u-boot.img_HS: u-boot-nodtb.bin_HS u-boot.img $(patsubst %.dtb,%.dtb_HS,$(OF_LIST_TARGETS)) FORCE
$(call if_changed,mkimage)
@@ -0,0 +1,50 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* K3: AM6 SoC definitions, structures etc.
*
* (C) Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
*/
#ifndef __ASM_ARCH_AM6_HARDWARE_H
#define __ASM_ARCH_AM6_HARDWARE_H
#include <config.h>
#define CTRL_MMR0_BASE 0x00100000
#define CTRLMMR_MAIN_DEVSTAT (CTRL_MMR0_BASE + 0x30)
#define CTRLMMR_MAIN_DEVSTAT_BOOTMODE_MASK GENMASK(3, 0)
#define CTRLMMR_MAIN_DEVSTAT_BOOTMODE_SHIFT 0
#define CTRLMMR_MAIN_DEVSTAT_BKUP_BOOTMODE_MASK GENMASK(6, 4)
#define CTRLMMR_MAIN_DEVSTAT_BKUP_BOOTMODE_SHIFT 4
#define CTRLMMR_MAIN_DEVSTAT_MMC_PORT_MASK GENMASK(12, 12)
#define CTRLMMR_MAIN_DEVSTAT_MMC_PORT_SHIFT 12
#define CTRLMMR_MAIN_DEVSTAT_EMMC_PORT_MASK GENMASK(14, 14)
#define CTRLMMR_MAIN_DEVSTAT_EMMC_PORT_SHIFT 14
#define CTRLMMR_MAIN_DEVSTAT_BKUP_MMC_PORT_MASK GENMASK(17, 17)
#define CTRLMMR_MAIN_DEVSTAT_BKUP_MMC_PORT_SHIFT 12
#define WKUP_CTRL_MMR0_BASE 0x43000000
#define MCU_CTRL_MMR0_BASE 0x40f00000
/*
* The CTRL_MMR0 memory space is divided into several equally-spaced
* partitions, so defining the partition size allows us to determine
* register addresses common to those partitions.
*/
#define CTRL_MMR0_PARTITION_SIZE 0x4000
/*
* CTRL_MMR0, WKUP_CTRL_MMR0, and MCU_CTR_MMR0 lock/kick-mechanism
* shared register definitions.
*/
#define CTRLMMR_LOCK_KICK0 0x01008
#define CTRLMMR_LOCK_KICK0_UNLOCK_VAL 0x68ef3490
#define CTRLMMR_LOCK_KICK0_UNLOCKED_MASK BIT(0)
#define CTRLMMR_LOCK_KICK0_UNLOCKED_SHIFT 0
#define CTRLMMR_LOCK_KICK1 0x0100c
#define CTRLMMR_LOCK_KICK1_UNLOCK_VAL 0xd172bc5a
/* MCU SCRATCHPAD usage */
#define TI_SRAM_SCRATCH_BOARD_EEPROM_START CONFIG_SYS_K3_MCU_SCRATCHPAD_BASE
#endif /* __ASM_ARCH_AM6_HARDWARE_H */
@@ -0,0 +1,36 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
* Lokesh Vutla <lokeshvutla@ti.com>
*/
#ifndef _ASM_ARCH_AM6_SPL_H_
#define _ASM_ARCH_AM6_SPL_H_
#define BOOT_DEVICE_RAM 0x00
#define BOOT_DEVICE_OSPI 0x01
#define BOOT_DEVICE_QSPI 0x02
#define BOOT_DEVICE_HYPERFLASH 0x03
#define BOOT_DEVICE_SPI 0x04
#define BOOT_DEVICE_I2C 0x05
#define BOOT_DEVICE_MMC2 0x06
#define BOOT_DEVICE_ETHERNET 0x07
#define BOOT_DEVICE_USB 0x08
#define BOOT_DEVICE_PCIE 0x09
#define BOOT_DEVICE_UART 0x0a
#define BOOT_DEVICE_NAND 0x0c
#define BOOT_DEVICE_MMC1 0x0d
#define BOOT_DEVICE_MMC2_2 0x0e
#define BACKUP_BOOT_DEVICE_RAM 0x0
#define BACKUP_BOOT_DEVICE_USB 0x1
#define BACKUP_BOOT_DEVICE_UART 0x2
#define BACKUP_BOOT_DEVICE_ETHERNET 0x3
#define BACKUP_BOOT_DEVICE_MMC2 0x4
#define BACKUP_BOOT_DEVICE_SPI 0x5
#define BACKUP_BOOT_DEVICE_HYPERFLASH 0x6
#define BACKUP_BOOT_DEVICE_I2C 0x7
#define K3_PRIMARY_BOOTMODE 0x0
#define K3_BACKUP_BOOTMODE 0x1
#endif
@@ -0,0 +1,16 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* K3: Common SoC clock definitions.
*
* (C) Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
*/
#ifndef __ASM_ARCH_CLOCK_H
#define __ASM_ARCH_CLOCK_H
#include <config.h>
/* Clock Defines */
#define V_OSCK 24000000
#define V_SCLK V_OSCK
#endif /* __ASM_ARCH_CLOCK_H */
@@ -0,0 +1,34 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
* Lokesh Vutla <lokeshvutla@ti.com>
*/
#ifndef _ASM_ARCH_HARDWARE_H_
#define _ASM_ARCH_HARDWARE_H_
#ifdef CONFIG_SOC_K3_AM6
#include "am6_hardware.h"
#endif
#ifdef CONFIG_SOC_K3_J721E
#include "j721e_hardware.h"
#endif
/* Assuming these addresses and definitions stay common across K3 devices */
#define CTRLMMR_WKUP_JTAG_DEVICE_ID 0x43000018
#define DEVICE_ID_FAMILY_SHIFT 26
#define DEVICE_ID_FAMILY_MASK (0x3f << 26)
#define DEVICE_ID_BASE_SHIFT 11
#define DEVICE_ID_BASE_MASK (0x1fff << 11)
#define DEVICE_ID_SPEED_SHIFT 6
#define DEVICE_ID_SPEED_MASK (0x1f << 6)
#define DEVICE_ID_TEMP_SHIFT 3
#define DEVICE_ID_TEMP_MASK (0x7 << 3)
#define CTRLMMR_WKUP_JTAG_ID 0x43000014
#define JTAG_ID_VARIANT_SHIFT 28
#define JTAG_ID_VARIANT_MASK (0xf << 28)
#define JTAG_ID_PARTNO_SHIFT 12
#define JTAG_ID_PARTNO_MASK (0x7ff << 1)
#endif /* _ASM_ARCH_HARDWARE_H_ */
@@ -0,0 +1,49 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* K3: J721E SoC definitions, structures etc.
*
* (C) Copyright (C) 2018-2019 Texas Instruments Incorporated - http://www.ti.com/
*/
#ifndef __ASM_ARCH_J721E_HARDWARE_H
#define __ASM_ARCH_J721E_HARDWARE_H
#include <config.h>
#define CTRL_MMR0_BASE 0x00100000
#define CTRLMMR_MAIN_DEVSTAT (CTRL_MMR0_BASE + 0x30)
#define MAIN_DEVSTAT_BOOT_MODE_B_MASK BIT(0)
#define MAIN_DEVSTAT_BOOT_MODE_B_SHIFT 0
#define MAIN_DEVSTAT_BKUP_BOOTMODE_MASK GENMASK(3, 1)
#define MAIN_DEVSTAT_BKUP_BOOTMODE_SHIFT 1
#define MAIN_DEVSTAT_PRIM_BOOTMODE_MMC_PORT_MASK BIT(6)
#define MAIN_DEVSTAT_PRIM_BOOTMODE_PORT_SHIFT 6
#define WKUP_CTRL_MMR0_BASE 0x43000000
#define MCU_CTRL_MMR0_BASE 0x40f00000
#define CTRLMMR_WKUP_DEVSTAT (WKUP_CTRL_MMR0_BASE + 0x30)
#define WKUP_DEVSTAT_PRIMARY_BOOTMODE_MASK GENMASK(5, 3)
#define WKUP_DEVSTAT_PRIMARY_BOOTMODE_SHIFT 3
#define WKUP_DEVSTAT_MCU_OMLY_MASK BIT(6)
#define WKUP_DEVSTAT_MCU_ONLY_SHIFT 6
/*
* The CTRL_MMR0 memory space is divided into several equally-spaced
* partitions, so defining the partition size allows us to determine
* register addresses common to those partitions.
*/
#define CTRL_MMR0_PARTITION_SIZE 0x4000
/*
* CTRL_MMR0, WKUP_CTRL_MMR0, and MCU_CTR_MMR0 lock/kick-mechanism
* shared register definitions.
*/
#define CTRLMMR_LOCK_KICK0 0x01008
#define CTRLMMR_LOCK_KICK0_UNLOCK_VAL 0x68ef3490
#define CTRLMMR_LOCK_KICK0_UNLOCKED_MASK BIT(0)
#define CTRLMMR_LOCK_KICK0_UNLOCKED_SHIFT 0
#define CTRLMMR_LOCK_KICK1 0x0100c
#define CTRLMMR_LOCK_KICK1_UNLOCK_VAL 0xd172bc5a
#endif /* __ASM_ARCH_J721E_HARDWARE_H */
@@ -0,0 +1,31 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright (C) 2018-2019 Texas Instruments Incorporated - http://www.ti.com/
* Lokesh Vutla <lokeshvutla@ti.com>
*/
#ifndef _ASM_ARCH_J721E_SPL_H_
#define _ASM_ARCH_J721E_SPL_H_
/* With BootMode B = 0 */
#define BOOT_DEVICE_HYPERFLASH 0x00
#define BOOT_DEVICE_OSPI 0x01
#define BOOT_DEVICE_QSPI 0x02
#define BOOT_DEVICE_SPI 0x03
#define BOOT_DEVICE_ETHERNET 0x04
#define BOOT_DEVICE_I2C 0x06
#define BOOT_DEVICE_UART 0x07
/* With BootMode B = 1 */
#define BOOT_DEVICE_MMC2 0x10
#define BOOT_DEVICE_MMC1 0x11
#define BOOT_DEVICE_USB 0x12
#define BOOT_DEVICE_UFS 0x13
#define BOOT_DEVIE_GPMC 0x14
#define BOOT_DEVICE_PCIE 0x15
#define BOOT_DEVICE_MMC2_2 0x16
#define BOOT_DEVICE_RAM 0x17
#define BOOT_MODE_B_SHIFT 4
#define BOOT_MODE_B_MASK BIT(4)
#endif
@@ -0,0 +1,16 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
* Lokesh Vutla <lokeshvutla@ti.com>
*/
#ifndef _ASM_ARCH_SPL_H_
#define _ASM_ARCH_SPL_H_
#ifdef CONFIG_SOC_K3_AM6
#include "am6_spl.h"
#endif
#ifdef CONFIG_SOC_K3_J721E
#include "j721e_spl.h"
#endif
#endif /* _ASM_ARCH_SPL_H_ */
@@ -0,0 +1,19 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
* Andreas Dannenberg <dannenberg@ti.com>
*/
#ifndef _SYS_PROTO_H_
#define _SYS_PROTO_H_
void sdelay(unsigned long loops);
u32 wait_on_value(u32 read_bit_mask, u32 match_value, void *read_addr,
u32 bound);
struct ti_sci_handle *get_ti_sci_handle(void);
int fdt_fixup_msmc_ram(void *blob, char *parent_path, char *node_name);
int do_board_detect(void);
void release_resources_for_core_shutdown(void);
int fdt_disable_node(void *blob, char *node_path);
#endif
@@ -0,0 +1,12 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
* Andreas Dannenberg <dannenberg@ti.com>
*/
#ifndef _SYSFW_LOADER_H_
#define _SYSFW_LOADER_H_
void k3_sysfw_loader(void (*config_pm_done_callback)(void));
#endif
@@ -0,0 +1,242 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* J721E: SoC specific initialization
*
* Copyright (C) 2018-2019 Texas Instruments Incorporated - http://www.ti.com/
* Lokesh Vutla <lokeshvutla@ti.com>
*/
#include <common.h>
#include <spl.h>
#include <asm/io.h>
#include <asm/armv7_mpu.h>
#include <asm/arch/hardware.h>
#include <asm/arch/sysfw-loader.h>
#include "common.h"
#include <asm/arch/sys_proto.h>
#include <linux/soc/ti/ti_sci_protocol.h>
#include <dm.h>
#include <dm/uclass-internal.h>
#include <dm/pinctrl.h>
#ifdef CONFIG_SPL_BUILD
static void mmr_unlock(u32 base, u32 partition)
{
/* Translate the base address */
phys_addr_t part_base = base + partition * CTRL_MMR0_PARTITION_SIZE;
/* Unlock the requested partition if locked using two-step sequence */
writel(CTRLMMR_LOCK_KICK0_UNLOCK_VAL, part_base + CTRLMMR_LOCK_KICK0);
writel(CTRLMMR_LOCK_KICK1_UNLOCK_VAL, part_base + CTRLMMR_LOCK_KICK1);
}
static void ctrl_mmr_unlock(void)
{
/* Unlock all WKUP_CTRL_MMR0 module registers */
mmr_unlock(WKUP_CTRL_MMR0_BASE, 0);
mmr_unlock(WKUP_CTRL_MMR0_BASE, 1);
mmr_unlock(WKUP_CTRL_MMR0_BASE, 2);
mmr_unlock(WKUP_CTRL_MMR0_BASE, 3);
mmr_unlock(WKUP_CTRL_MMR0_BASE, 4);
mmr_unlock(WKUP_CTRL_MMR0_BASE, 6);
mmr_unlock(WKUP_CTRL_MMR0_BASE, 7);
/* Unlock all MCU_CTRL_MMR0 module registers */
mmr_unlock(MCU_CTRL_MMR0_BASE, 0);
mmr_unlock(MCU_CTRL_MMR0_BASE, 1);
mmr_unlock(MCU_CTRL_MMR0_BASE, 2);
mmr_unlock(MCU_CTRL_MMR0_BASE, 3);
mmr_unlock(MCU_CTRL_MMR0_BASE, 4);
/* Unlock all CTRL_MMR0 module registers */
mmr_unlock(CTRL_MMR0_BASE, 0);
mmr_unlock(CTRL_MMR0_BASE, 1);
mmr_unlock(CTRL_MMR0_BASE, 2);
mmr_unlock(CTRL_MMR0_BASE, 3);
mmr_unlock(CTRL_MMR0_BASE, 4);
mmr_unlock(CTRL_MMR0_BASE, 5);
mmr_unlock(CTRL_MMR0_BASE, 6);
mmr_unlock(CTRL_MMR0_BASE, 7);
}
/*
* This uninitialized global variable would normal end up in the .bss section,
* but the .bss is cleared between writing and reading this variable, so move
* it to the .data section.
*/
u32 bootindex __attribute__((section(".data")));
static void store_boot_index_from_rom(void)
{
bootindex = *(u32 *)(CONFIG_SYS_K3_BOOT_PARAM_TABLE_INDEX);
}
void board_init_f(ulong dummy)
{
#if defined(CONFIG_K3_J721E_DDRSS) || defined(CONFIG_K3_LOAD_SYSFW)
struct udevice *dev;
int ret;
#endif
/*
* Cannot delay this further as there is a chance that
* K3_BOOT_PARAM_TABLE_INDEX can be over written by SPL MALLOC section.
*/
store_boot_index_from_rom();
/* Make all control module registers accessible */
ctrl_mmr_unlock();
#ifdef CONFIG_CPU_V7R
disable_linefill_optimization();
setup_k3_mpu_regions();
#endif
/* Init DM early */
spl_early_init();
#ifdef CONFIG_K3_LOAD_SYSFW
/*
* Process pinctrl for the serial0 a.k.a. MCU_UART0 module and continue
* regardless of the result of pinctrl. Do this without probing the
* device, but instead by searching the device that would request the
* given sequence number if probed. The UART will be used by the system
* firmware (SYSFW) image for various purposes and SYSFW depends on us
* to initialize its pin settings.
*/
ret = uclass_find_device_by_seq(UCLASS_SERIAL, 0, true, &dev);
if (!ret)
pinctrl_select_state(dev, "default");
/*
* Load, start up, and configure system controller firmware. Provide
* the U-Boot console init function to the SYSFW post-PM configuration
* callback hook, effectively switching on (or over) the console
* output.
*/
k3_sysfw_loader(preloader_console_init);
#else
/* Prepare console output */
preloader_console_init();
#endif
#if defined(CONFIG_CPU_V7R) && defined(CONFIG_K3_AVS0)
ret = uclass_get_device_by_driver(UCLASS_MISC, DM_GET_DRIVER(k3_avs),
&dev);
if (ret)
printf("AVS init failed: %d\n", ret);
#endif
#if defined(CONFIG_K3_J721E_DDRSS)
ret = uclass_get_device(UCLASS_RAM, 0, &dev);
if (ret)
panic("DRAM init failed: %d\n", ret);
#endif
}
u32 spl_boot_mode(const u32 boot_device)
{
switch (boot_device) {
case BOOT_DEVICE_MMC1:
return MMCSD_MODE_EMMCBOOT;
case BOOT_DEVICE_MMC2:
return MMCSD_MODE_FS;
default:
return MMCSD_MODE_RAW;
}
}
static u32 __get_primary_bootmedia(u32 main_devstat, u32 wkup_devstat)
{
u32 bootmode = (wkup_devstat & WKUP_DEVSTAT_PRIMARY_BOOTMODE_MASK) >>
WKUP_DEVSTAT_PRIMARY_BOOTMODE_SHIFT;
bootmode |= (main_devstat & MAIN_DEVSTAT_BOOT_MODE_B_MASK) <<
BOOT_MODE_B_SHIFT;
if (bootmode == BOOT_DEVICE_OSPI || bootmode == BOOT_DEVICE_QSPI)
bootmode = BOOT_DEVICE_SPI;
if (bootmode == BOOT_DEVICE_MMC2) {
u32 port = (main_devstat &
MAIN_DEVSTAT_PRIM_BOOTMODE_MMC_PORT_MASK) >>
MAIN_DEVSTAT_PRIM_BOOTMODE_PORT_SHIFT;
if (port == 0x0)
bootmode = BOOT_DEVICE_MMC1;
}
return bootmode;
}
u32 spl_boot_device(void)
{
u32 wkup_devstat = readl(CTRLMMR_WKUP_DEVSTAT);
u32 main_devstat;
if (wkup_devstat & WKUP_DEVSTAT_MCU_OMLY_MASK) {
printf("ERROR: MCU only boot is not yet supported\n");
return BOOT_DEVICE_RAM;
}
/* MAIN CTRL MMR can only be read if MCU ONLY is 0 */
main_devstat = readl(CTRLMMR_MAIN_DEVSTAT);
/* ToDo: Add support for backup boot media */
return __get_primary_bootmedia(main_devstat, wkup_devstat);
}
#endif
#ifdef CONFIG_SYS_K3_SPL_ATF
#define J721E_DEV_MCU_RTI0 262
#define J721E_DEV_MCU_RTI1 263
#define J721E_DEV_MCU_ARMSS0_CPU0 250
#define J721E_DEV_MCU_ARMSS0_CPU1 251
void release_resources_for_core_shutdown(void)
{
struct ti_sci_handle *ti_sci;
struct ti_sci_dev_ops *dev_ops;
struct ti_sci_proc_ops *proc_ops;
int ret;
u32 i;
const u32 put_device_ids[] = {
J721E_DEV_MCU_RTI0,
J721E_DEV_MCU_RTI1,
};
ti_sci = get_ti_sci_handle();
dev_ops = &ti_sci->ops.dev_ops;
proc_ops = &ti_sci->ops.proc_ops;
/* Iterate through list of devices to put (shutdown) */
for (i = 0; i < ARRAY_SIZE(put_device_ids); i++) {
u32 id = put_device_ids[i];
ret = dev_ops->put_device(ti_sci, id);
if (ret)
panic("Failed to put device %u (%d)\n", id, ret);
}
const u32 put_core_ids[] = {
J721E_DEV_MCU_ARMSS0_CPU1,
J721E_DEV_MCU_ARMSS0_CPU0, /* Handle CPU0 after CPU1 */
};
/* Iterate through list of cores to put (shutdown) */
for (i = 0; i < ARRAY_SIZE(put_core_ids); i++) {
u32 id = put_core_ids[i];
/*
* Queue up the core shutdown request. Note that this call
* needs to be followed up by an actual invocation of an WFE
* or WFI CPU instruction.
*/
ret = proc_ops->proc_shutdown_no_wait(ti_sci, id);
if (ret)
panic("Failed sending core %u shutdown message (%d)\n",
id, ret);
}
}
#endif
@@ -0,0 +1,20 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
* Lokesh Vutla <lokeshvutla@ti.com>
*/
#include <linux/linkage.h>
ENTRY(lowlevel_init)
mrc p15, 0, r0, c0, c0, 5 @ Read MPIDR
and r0, #0xff
cmp r0, #0x0
bne park_cpu
bx lr
park_cpu:
wfi
b park_cpu
ENDPROC(lowlevel_init)
@@ -0,0 +1,47 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* K3: R5 MPU region definitions
*
* Copyright (C) 2017-2018 Texas Instruments Incorporated - http://www.ti.com/
* Lokesh Vutla <lokeshvutla@ti.com>
*/
#include <common.h>
#include <asm/io.h>
#include <linux/kernel.h>
#include "common.h"
struct mpu_region_config k3_mpu_regions[16] = {
/*
* Make all 4GB as Device Memory and not executable. We are overriding
* it with next region for any requirement.
*/
{0x00000000, REGION_0, XN_EN, PRIV_RW_USR_RW, SHARED_WRITE_BUFFERED,
REGION_4GB},
/* SPL code area marking it as WB and Write allocate. */
{CONFIG_SPL_TEXT_BASE, REGION_1, XN_DIS, PRIV_RW_USR_RW,
O_I_WB_RD_WR_ALLOC, REGION_8MB},
/* U-Boot's code area marking it as WB and Write allocate */
{CONFIG_SYS_SDRAM_BASE, REGION_2, XN_DIS, PRIV_RW_USR_RW,
O_I_WB_RD_WR_ALLOC, REGION_2GB},
{0x0, 3, 0x0, 0x0, 0x0, 0x0},
{0x0, 4, 0x0, 0x0, 0x0, 0x0},
{0x0, 5, 0x0, 0x0, 0x0, 0x0},
{0x0, 6, 0x0, 0x0, 0x0, 0x0},
{0x0, 7, 0x0, 0x0, 0x0, 0x0},
{0x0, 8, 0x0, 0x0, 0x0, 0x0},
{0x0, 9, 0x0, 0x0, 0x0, 0x0},
{0x0, 10, 0x0, 0x0, 0x0, 0x0},
{0x0, 11, 0x0, 0x0, 0x0, 0x0},
{0x0, 12, 0x0, 0x0, 0x0, 0x0},
{0x0, 13, 0x0, 0x0, 0x0, 0x0},
{0x0, 14, 0x0, 0x0, 0x0, 0x0},
{0x0, 15, 0x0, 0x0, 0x0, 0x0},
};
void setup_k3_mpu_regions(void)
{
setup_mpu_regions(k3_mpu_regions, ARRAY_SIZE(k3_mpu_regions));
}
@@ -0,0 +1,54 @@
// SPDX-License-Identifier: GPL-2.0
/*
* K3: Security functions
*
* Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
* Andrew F. Davis <afd@ti.com>
*/
#include <common.h>
#include <dm.h>
#include <linux/soc/ti/ti_sci_protocol.h>
#include <mach/spl.h>
#include <spl.h>
#include <asm/arch/sys_proto.h>
void board_fit_image_post_process(void **p_image, size_t *p_size)
{
struct ti_sci_handle *ti_sci = get_ti_sci_handle();
struct ti_sci_proc_ops *proc_ops = &ti_sci->ops.proc_ops;
u64 image_addr;
u32 image_size;
int ret;
image_addr = (uintptr_t)*p_image;
debug("Authenticating image at address 0x%016llx\n", image_addr);
/* Authenticate image */
ret = proc_ops->proc_auth_boot_image(ti_sci, &image_addr, &image_size);
if (ret) {
printf("Authentication failed!\n");
hang();
}
/*
* The image_size returned may be 0 when the authentication process has
* moved the image. When this happens no further processing on the
* image is needed or often even possible as it may have also been
* placed behind a firewall when moved.
*/
*p_size = image_size;
/*
* Output notification of successful authentication to re-assure the
* user that the secure code is being processed as expected. However
* suppress any such log output in case of building for SPL and booting
* via YMODEM. This is done to avoid disturbing the YMODEM serial
* protocol transactions.
*/
if (!(IS_ENABLED(CONFIG_SPL_BUILD) &&
IS_ENABLED(CONFIG_SPL_YMODEM_SUPPORT) &&
spl_boot_device() == BOOT_DEVICE_UART))
printf("Authentication passed\n");
}
@@ -0,0 +1,292 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* K3: System Firmware Loader
*
* Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
* Andreas Dannenberg <dannenberg@ti.com>
*/
#include <common.h>
#include <spl.h>
#include <malloc.h>
#include <remoteproc.h>
#include <linux/soc/ti/ti_sci_protocol.h>
#include <asm/arch/sys_proto.h>
#include "common.h"
DECLARE_GLOBAL_DATA_PTR;
/* Name of the FIT image nodes for SYSFW and its config data */
#define SYSFW_FIRMWARE "sysfw.bin"
#define SYSFW_CFG_BOARD "board-cfg.bin"
#define SYSFW_CFG_PM "pm-cfg.bin"
#define SYSFW_CFG_RM "rm-cfg.bin"
#define SYSFW_CFG_SEC "sec-cfg.bin"
static bool sysfw_loaded;
static void *sysfw_load_address;
/*
* Populate SPL hook to override the default load address used by the SPL
* loader function with a custom address for SYSFW loading.
*/
struct image_header *spl_get_load_buffer(ssize_t offset, size_t size)
{
if (sysfw_loaded)
return (struct image_header *)(CONFIG_SYS_TEXT_BASE + offset);
else if (sysfw_load_address)
return sysfw_load_address;
else
panic("SYSFW load address not defined!");
}
/*
* Populate SPL hook to skip the default SPL loader FIT post-processing steps
* during SYSFW loading and return to the calling function so we can perform
* our own custom processing.
*/
bool spl_load_simple_fit_skip_processing(void)
{
return !sysfw_loaded;
}
static int fit_get_data_by_name(const void *fit, int images, const char *name,
const void **addr, size_t *size)
{
int node_offset;
node_offset = fdt_subnode_offset(fit, images, name);
if (node_offset < 0)
return -ENOENT;
return fit_image_get_data(fit, node_offset, addr, size);
}
static void k3_sysfw_load_using_fit(void *fit)
{
int images;
const void *sysfw_addr;
size_t sysfw_size;
int ret;
/* Find the node holding the images information */
images = fdt_path_offset(fit, FIT_IMAGES_PATH);
if (images < 0)
panic("Cannot find /images node (%d)\n", images);
/* Extract System Firmware (SYSFW) image from FIT */
ret = fit_get_data_by_name(fit, images, SYSFW_FIRMWARE,
&sysfw_addr, &sysfw_size);
if (ret < 0)
panic("Error accessing %s node in FIT (%d)\n", SYSFW_FIRMWARE,
ret);
/*
* Start up system controller firmware
*
* It is assumed that remoteproc device 0 is the corresponding
* system-controller that runs SYSFW. Make sure DT reflects the same.
*/
ret = rproc_dev_init(0);
if (ret)
panic("rproc failed to be initialized (%d)\n", ret);
ret = rproc_load(0, (ulong)sysfw_addr, (ulong)sysfw_size);
if (ret)
panic("Firmware failed to start on rproc (%d)\n", ret);
ret = rproc_start(0);
if (ret)
panic("Firmware init failed on rproc (%d)\n", ret);
}
static void k3_sysfw_configure_using_fit(void *fit,
struct ti_sci_handle *ti_sci)
{
struct ti_sci_board_ops *board_ops = &ti_sci->ops.board_ops;
int images;
const void *cfg_fragment_addr;
size_t cfg_fragment_size;
int ret;
/* Find the node holding the images information */
images = fdt_path_offset(fit, FIT_IMAGES_PATH);
if (images < 0)
panic("Cannot find /images node (%d)\n", images);
/* Extract board configuration from FIT */
ret = fit_get_data_by_name(fit, images, SYSFW_CFG_BOARD,
&cfg_fragment_addr, &cfg_fragment_size);
if (ret < 0)
panic("Error accessing %s node in FIT (%d)\n", SYSFW_CFG_BOARD,
ret);
/* Apply board configuration to SYSFW */
ret = board_ops->board_config(ti_sci,
(u64)(u32)cfg_fragment_addr,
(u32)cfg_fragment_size);
if (ret)
panic("Failed to set board configuration (%d)\n", ret);
/* Extract power/clock (PM) specific configuration from FIT */
ret = fit_get_data_by_name(fit, images, SYSFW_CFG_PM,
&cfg_fragment_addr, &cfg_fragment_size);
if (ret < 0)
panic("Error accessing %s node in FIT (%d)\n", SYSFW_CFG_PM,
ret);
/* Apply power/clock (PM) specific configuration to SYSFW */
ret = board_ops->board_config_pm(ti_sci,
(u64)(u32)cfg_fragment_addr,
(u32)cfg_fragment_size);
if (ret)
panic("Failed to set board PM configuration (%d)\n", ret);
/* Extract resource management (RM) specific configuration from FIT */
ret = fit_get_data_by_name(fit, images, SYSFW_CFG_RM,
&cfg_fragment_addr, &cfg_fragment_size);
if (ret < 0)
panic("Error accessing %s node in FIT (%d)\n", SYSFW_CFG_RM,
ret);
/* Apply resource management (RM) configuration to SYSFW */
ret = board_ops->board_config_rm(ti_sci,
(u64)(u32)cfg_fragment_addr,
(u32)cfg_fragment_size);
if (ret)
panic("Failed to set board RM configuration (%d)\n", ret);
/* Extract security specific configuration from FIT */
ret = fit_get_data_by_name(fit, images, SYSFW_CFG_SEC,
&cfg_fragment_addr, &cfg_fragment_size);
if (ret < 0)
panic("Error accessing %s node in FIT (%d)\n", SYSFW_CFG_SEC,
ret);
/* Apply security configuration to SYSFW */
ret = board_ops->board_config_security(ti_sci,
(u64)(u32)cfg_fragment_addr,
(u32)cfg_fragment_size);
if (ret)
panic("Failed to set board security configuration (%d)\n",
ret);
}
void k3_sysfw_loader(void (*config_pm_done_callback)(void))
{
struct spl_image_info spl_image = { 0 };
struct spl_boot_device bootdev = { 0 };
struct ti_sci_handle *ti_sci;
int ret;
/* Reserve a block of aligned memory for loading the SYSFW image */
sysfw_load_address = memalign(ARCH_DMA_MINALIGN,
CONFIG_K3_SYSFW_IMAGE_SIZE_MAX);
if (!sysfw_load_address)
panic("Error allocating %u bytes of memory for SYSFW image\n",
CONFIG_K3_SYSFW_IMAGE_SIZE_MAX);
debug("%s: allocated %u bytes at 0x%p\n", __func__,
CONFIG_K3_SYSFW_IMAGE_SIZE_MAX, sysfw_load_address);
/* Set load address for legacy modes that bypass spl_get_load_buffer */
spl_image.load_addr = (uintptr_t)sysfw_load_address;
bootdev.boot_device = spl_boot_device();
/* Load combined System Controller firmware and config data image */
switch (bootdev.boot_device) {
#if CONFIG_IS_ENABLED(MMC_SUPPORT)
case BOOT_DEVICE_MMC1:
case BOOT_DEVICE_MMC2:
case BOOT_DEVICE_MMC2_2:
ret = spl_mmc_load(&spl_image, &bootdev,
#ifdef CONFIG_K3_SYSFW_IMAGE_NAME
CONFIG_K3_SYSFW_IMAGE_NAME,
#else
NULL,
#endif
#ifdef CONFIG_K3_SYSFW_IMAGE_MMCSD_RAW_MODE_PART
CONFIG_K3_SYSFW_IMAGE_MMCSD_RAW_MODE_PART,
#else
0,
#endif
#ifdef CONFIG_K3_SYSFW_IMAGE_MMCSD_RAW_MODE_SECT
CONFIG_K3_SYSFW_IMAGE_MMCSD_RAW_MODE_SECT);
#else
0);
#endif
break;
#endif
#if CONFIG_IS_ENABLED(YMODEM_SUPPORT)
case BOOT_DEVICE_UART:
#ifdef CONFIG_K3_EARLY_CONS
/*
* Establish a serial console if not yet available as required
* for UART-based boot. For this use the early console feature
* that allows setting up a UART for use before SYSFW has been
* brought up. Note that the associated UART module's clocks
* must have gotten enabled by the ROM bootcode which will be
* the case when continuing to boot serially from the same
* UART that the ROM loaded the initial bootloader from.
*/
if (!gd->have_console)
early_console_init();
#endif
ret = spl_ymodem_load_image(&spl_image, &bootdev);
break;
#endif
default:
panic("Loading SYSFW image from device %u not supported!\n",
bootdev.boot_device);
}
if (ret)
panic("Error %d occurred during loading SYSFW image!\n", ret);
/*
* Now that SYSFW got loaded set helper flag to restore regular SPL
* loader behavior so we can later boot into the next stage as expected.
*/
sysfw_loaded = true;
/* Ensure the SYSFW image is in FIT format */
if (image_get_magic((const image_header_t *)sysfw_load_address) !=
FDT_MAGIC)
panic("SYSFW image not in FIT format!\n");
/* Extract and start SYSFW */
k3_sysfw_load_using_fit(sysfw_load_address);
/* Get handle for accessing SYSFW services */
ti_sci = get_ti_sci_handle();
/* Parse and apply the different SYSFW configuration fragments */
k3_sysfw_configure_using_fit(sysfw_load_address, ti_sci);
/*
* Now that all clocks and PM aspects are setup, invoke a user-
* provided callback function. Usually this callback would be used
* to setup or re-configure the U-Boot console UART.
*/
if (config_pm_done_callback)
config_pm_done_callback();
/*
* Output System Firmware version info. Note that since the
* 'firmware_description' field is not guaranteed to be zero-
* terminated we manually add a \0 terminator if needed. Further
* note that we intentionally no longer rely on the extended
* printf() formatter '%.*s' to not having to require a more
* full-featured printf() implementation.
*/
char fw_desc[sizeof(ti_sci->version.firmware_description) + 1];
strncpy(fw_desc, ti_sci->version.firmware_description,
sizeof(ti_sci->version.firmware_description));
fw_desc[sizeof(fw_desc) - 1] = '\0';
printf("SYSFW ABI: %d.%d (firmware rev 0x%04x '%s')\n",
ti_sci->version.abi_major, ti_sci->version.abi_minor,
ti_sci->version.firmware_revision, fw_desc);
}