GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)
This commit is contained in:
@@ -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);
|
||||
}
|
||||
Reference in New Issue
Block a user