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,151 @@
if ARCH_STM32MP
config SPL
select SPL_BOARD_INIT
select SPL_CLK
select SPL_DM
select SPL_DM_SEQ_ALIAS
select SPL_DRIVERS_MISC_SUPPORT
select SPL_FRAMEWORK
select SPL_GPIO_SUPPORT
select SPL_LIBCOMMON_SUPPORT
select SPL_LIBGENERIC_SUPPORT
select SPL_OF_CONTROL
select SPL_OF_TRANSLATE
select SPL_PINCTRL
select SPL_REGMAP
select SPL_DM_RESET
select SPL_SERIAL_SUPPORT
select SPL_SPI_LOAD
select SPL_SYSCON
select SPL_WATCHDOG_SUPPORT if WATCHDOG
imply BOOTSTAGE_STASH if SPL_BOOTSTAGE
imply SPL_BOOTSTAGE if BOOTSTAGE
imply SPL_DISPLAY_PRINT
imply SPL_LIBDISK_SUPPORT
config SYS_SOC
default "stm32mp"
config SYS_MALLOC_LEN
default 0x2000000
config ENV_SIZE
default 0x2000
config TARGET_STM32MP1
bool "Support stm32mp1xx"
select ARCH_SUPPORT_PSCI if !STM32MP1_TRUSTED
select CPU_V7A
select CPU_V7_HAS_NONSEC if !STM32MP1_TRUSTED
select CPU_V7_HAS_VIRT
select OF_BOARD_SETUP
select PINCTRL_STM32
select STM32_RCC
select STM32_RESET
select STM32_SERIAL
select SYS_ARCH_TIMER
imply BOOTCOUNT_LIMIT
imply CMD_BOOTCOUNT
imply CMD_CLS if CMD_BMP
imply DISABLE_CONSOLE
imply PRE_CONSOLE_BUFFER
imply SILENT_CONSOLE
imply SYSRESET_PSCI if STM32MP1_TRUSTED
imply SYSRESET_SYSCON if !STM32MP1_TRUSTED
help
target STMicroelectronics SOC STM32MP1 family
STM32MP157, STM32MP153 or STM32MP151
STMicroelectronics MPU with core ARMv7
dual core A7 for STM32MP157/3, monocore for STM32MP151
config STM32MP1_TRUSTED
bool "Support trusted boot with TF-A"
default y if !SPL
select ARM_SMCCC
help
Say Y here to enable boot with TF-A
Trusted boot chain is :
BootRom => TF-A.stm32 (clock & DDR) => U-Boot.stm32
TF-A monitor provides proprietary SMC to manage secure devices
config STM32MP1_OPTEE
bool "Support trusted boot with TF-A and OP-TEE"
depends on STM32MP1_TRUSTED
default n
help
Say Y here to enable boot with TF-A and OP-TEE
Trusted boot chain is :
BootRom => TF-A.stm32 (clock & DDR) => OP-TEE => U-Boot.stm32
OP-TEE monitor provides ST SMC to access to secure resources
config SYS_TEXT_BASE
prompt "U-Boot base address"
default 0xC0100000
help
configure the U-Boot base address
when DDR driver is used:
DDR + 1MB (0xC0100000)
config NR_DRAM_BANKS
default 1
config SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION_MMC2
hex "Partition on MMC2 to use to load U-Boot from"
depends on SYS_MMCSD_RAW_MODE_U_BOOT_USE_PARTITION
default 1
help
Partition on the second MMC to load U-Boot from when the MMC is being
used in raw mode
config STM32_ETZPC
bool "STM32 Extended TrustZone Protection"
depends on TARGET_STM32MP1
default y
help
Say y to enable STM32 Extended TrustZone Protection
config CMD_STM32KEY
bool "command stm32key to fuse public key hash"
default y
depends on CMD_FUSE
help
fuse public key hash in corresponding fuse used to authenticate
binary.
config PRE_CON_BUF_ADDR
default 0xC02FF000
config PRE_CON_BUF_SZ
default 4096
config BOOTSTAGE_STASH_ADDR
default 0xC3000000
if BOOTCOUNT_LIMIT
config SYS_BOOTCOUNT_SINGLEWORD
default y
# TAMP_BOOTCOUNT = TAMP_BACKUP_REGISTER(21)
config SYS_BOOTCOUNT_ADDR
default 0x5C00A154
endif
if DEBUG_UART
config DEBUG_UART_BOARD_INIT
default y
# debug on UART4 by default
config DEBUG_UART_BASE
default 0x40010000
# clock source is HSI on reset
config DEBUG_UART_CLOCK
default 64000000
endif
source "board/st/stm32mp1/Kconfig"
endif
@@ -0,0 +1,19 @@
# SPDX-License-Identifier: GPL-2.0+
#
# Copyright (C) 2018, STMicroelectronics - All Rights Reserved
#
obj-y += cpu.o
obj-y += dram_init.o
obj-y += syscon.o
ifdef CONFIG_SPL_BUILD
obj-y += spl.o
else
obj-y += bsec.o
obj-$(CONFIG_CMD_STM32KEY) += cmd_stm32key.o
obj-$(CONFIG_ARMV7_PSCI) += psci.o
endif
obj-$(CONFIG_$(SPL_)DM_REGULATOR) += pwr_regulator.o
obj-$(CONFIG_OF_SYSTEM_SETUP) += fdt.o
@@ -0,0 +1,470 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (C) 2018, STMicroelectronics - All Rights Reserved
*/
#include <common.h>
#include <dm.h>
#include <misc.h>
#include <asm/io.h>
#include <asm/arch/stm32mp1_smc.h>
#include <linux/arm-smccc.h>
#include <linux/iopoll.h>
#define BSEC_OTP_MAX_VALUE 95
#ifndef CONFIG_STM32MP1_TRUSTED
#define BSEC_TIMEOUT_US 10000
/* BSEC REGISTER OFFSET (base relative) */
#define BSEC_OTP_CONF_OFF 0x000
#define BSEC_OTP_CTRL_OFF 0x004
#define BSEC_OTP_WRDATA_OFF 0x008
#define BSEC_OTP_STATUS_OFF 0x00C
#define BSEC_OTP_LOCK_OFF 0x010
#define BSEC_DISTURBED_OFF 0x01C
#define BSEC_ERROR_OFF 0x034
#define BSEC_SPLOCK_OFF 0x064 /* Program safmem sticky lock */
#define BSEC_SWLOCK_OFF 0x07C /* write in OTP sticky lock */
#define BSEC_SRLOCK_OFF 0x094 /* shadowing sticky lock */
#define BSEC_OTP_DATA_OFF 0x200
/* BSEC_CONFIGURATION Register MASK */
#define BSEC_CONF_POWER_UP 0x001
/* BSEC_CONTROL Register */
#define BSEC_READ 0x000
#define BSEC_WRITE 0x100
/* LOCK Register */
#define OTP_LOCK_MASK 0x1F
#define OTP_LOCK_BANK_SHIFT 0x05
#define OTP_LOCK_BIT_MASK 0x01
/* STATUS Register */
#define BSEC_MODE_BUSY_MASK 0x08
#define BSEC_MODE_PROGFAIL_MASK 0x10
#define BSEC_MODE_PWR_MASK 0x20
/*
* OTP Lock services definition
* Value must corresponding to the bit number in the register
*/
#define BSEC_LOCK_PROGRAM 0x04
/**
* bsec_check_error() - Check status of one otp
* @base: base address of bsec IP
* @otp: otp number (0 - BSEC_OTP_MAX_VALUE)
* Return: 0 if no error, -EAGAIN or -ENOTSUPP
*/
static u32 bsec_check_error(u32 base, u32 otp)
{
u32 bit;
u32 bank;
bit = 1 << (otp & OTP_LOCK_MASK);
bank = ((otp >> OTP_LOCK_BANK_SHIFT) & OTP_LOCK_MASK) * sizeof(u32);
if (readl(base + BSEC_DISTURBED_OFF + bank) & bit)
return -EAGAIN;
else if (readl(base + BSEC_ERROR_OFF + bank) & bit)
return -ENOTSUPP;
return 0;
}
/**
* bsec_lock() - manage lock for each type SR/SP/SW
* @address: address of bsec IP register
* @otp: otp number (0 - BSEC_OTP_MAX_VALUE)
* Return: true if locked else false
*/
static bool bsec_read_lock(u32 address, u32 otp)
{
u32 bit;
u32 bank;
bit = 1 << (otp & OTP_LOCK_MASK);
bank = ((otp >> OTP_LOCK_BANK_SHIFT) & OTP_LOCK_MASK) * sizeof(u32);
return !!(readl(address + bank) & bit);
}
/**
* bsec_read_SR_lock() - read SR lock (Shadowing)
* @base: base address of bsec IP
* @otp: otp number (0 - BSEC_OTP_MAX_VALUE)
* Return: true if locked else false
*/
static bool bsec_read_SR_lock(u32 base, u32 otp)
{
return bsec_read_lock(base + BSEC_SRLOCK_OFF, otp);
}
/**
* bsec_read_SP_lock() - read SP lock (program Lock)
* @base: base address of bsec IP
* @otp: otp number (0 - BSEC_OTP_MAX_VALUE)
* Return: true if locked else false
*/
static bool bsec_read_SP_lock(u32 base, u32 otp)
{
return bsec_read_lock(base + BSEC_SPLOCK_OFF, otp);
}
/**
* bsec_SW_lock() - manage SW lock (Write in Shadow)
* @base: base address of bsec IP
* @otp: otp number (0 - BSEC_OTP_MAX_VALUE)
* Return: true if locked else false
*/
static bool bsec_read_SW_lock(u32 base, u32 otp)
{
return bsec_read_lock(base + BSEC_SWLOCK_OFF, otp);
}
/**
* bsec_power_safmem() - Activate or deactivate safmem power
* @base: base address of bsec IP
* @power: true to power up , false to power down
* Return: 0 if succeed
*/
static int bsec_power_safmem(u32 base, bool power)
{
u32 val;
u32 mask;
if (power) {
setbits_le32(base + BSEC_OTP_CONF_OFF, BSEC_CONF_POWER_UP);
mask = BSEC_MODE_PWR_MASK;
} else {
clrbits_le32(base + BSEC_OTP_CONF_OFF, BSEC_CONF_POWER_UP);
mask = 0;
}
/* waiting loop */
return readl_poll_timeout(base + BSEC_OTP_STATUS_OFF,
val, (val & BSEC_MODE_PWR_MASK) == mask,
BSEC_TIMEOUT_US);
}
/**
* bsec_shadow_register() - copy safmen otp to bsec data
* @base: base address of bsec IP
* @otp: otp number (0 - BSEC_OTP_MAX_VALUE)
* Return: 0 if no error
*/
static int bsec_shadow_register(u32 base, u32 otp)
{
u32 val;
int ret;
bool power_up = false;
/* check if shadowing of otp is locked */
if (bsec_read_SR_lock(base, otp))
pr_debug("bsec : OTP %d is locked and refreshed with 0\n", otp);
/* check if safemem is power up */
val = readl(base + BSEC_OTP_STATUS_OFF);
if (!(val & BSEC_MODE_PWR_MASK)) {
ret = bsec_power_safmem(base, true);
if (ret)
return ret;
power_up = true;
}
/* set BSEC_OTP_CTRL_OFF with the otp value*/
writel(otp | BSEC_READ, base + BSEC_OTP_CTRL_OFF);
/* check otp status*/
ret = readl_poll_timeout(base + BSEC_OTP_STATUS_OFF,
val, (val & BSEC_MODE_BUSY_MASK) == 0,
BSEC_TIMEOUT_US);
if (ret)
return ret;
ret = bsec_check_error(base, otp);
if (power_up)
bsec_power_safmem(base, false);
return ret;
}
/**
* bsec_read_shadow() - read an otp data value from shadow
* @base: base address of bsec IP
* @val: read value
* @otp: otp number (0 - BSEC_OTP_MAX_VALUE)
* Return: 0 if no error
*/
static int bsec_read_shadow(u32 base, u32 *val, u32 otp)
{
*val = readl(base + BSEC_OTP_DATA_OFF + otp * sizeof(u32));
return bsec_check_error(base, otp);
}
/**
* bsec_write_shadow() - write value in BSEC data register in shadow
* @base: base address of bsec IP
* @val: value to write
* @otp: otp number (0 - BSEC_OTP_MAX_VALUE)
* Return: 0 if no error
*/
static int bsec_write_shadow(u32 base, u32 val, u32 otp)
{
/* check if programming of otp is locked */
if (bsec_read_SW_lock(base, otp))
pr_debug("bsec : OTP %d is lock, write will be ignore\n", otp);
writel(val, base + BSEC_OTP_DATA_OFF + otp * sizeof(u32));
return bsec_check_error(base, otp);
}
/**
* bsec_program_otp() - program a bit in SAFMEM
* @base: base address of bsec IP
* @val: value to program
* @otp: otp number (0 - BSEC_OTP_MAX_VALUE)
* after the function the otp data is not refreshed in shadow
* Return: 0 if no error
*/
static int bsec_program_otp(long base, u32 val, u32 otp)
{
u32 ret;
bool power_up = false;
if (bsec_read_SP_lock(base, otp))
pr_debug("bsec : OTP %d locked, prog will be ignore\n", otp);
if (readl(base + BSEC_OTP_LOCK_OFF) & (1 << BSEC_LOCK_PROGRAM))
pr_debug("bsec : Global lock, prog will be ignore\n");
/* check if safemem is power up */
if (!(readl(base + BSEC_OTP_STATUS_OFF) & BSEC_MODE_PWR_MASK)) {
ret = bsec_power_safmem(base, true);
if (ret)
return ret;
power_up = true;
}
/* set value in write register*/
writel(val, base + BSEC_OTP_WRDATA_OFF);
/* set BSEC_OTP_CTRL_OFF with the otp value */
writel(otp | BSEC_WRITE, base + BSEC_OTP_CTRL_OFF);
/* check otp status*/
ret = readl_poll_timeout(base + BSEC_OTP_STATUS_OFF,
val, (val & BSEC_MODE_BUSY_MASK) == 0,
BSEC_TIMEOUT_US);
if (ret)
return ret;
if (val & BSEC_MODE_PROGFAIL_MASK)
ret = -EACCES;
else
ret = bsec_check_error(base, otp);
if (power_up)
bsec_power_safmem(base, false);
return ret;
}
#endif /* CONFIG_STM32MP1_TRUSTED */
/* BSEC MISC driver *******************************************************/
struct stm32mp_bsec_platdata {
u32 base;
};
static int stm32mp_bsec_read_otp(struct udevice *dev, u32 *val, u32 otp)
{
#ifdef CONFIG_STM32MP1_TRUSTED
return stm32_smc(STM32_SMC_BSEC,
STM32_SMC_READ_OTP,
otp, 0, val);
#else
struct stm32mp_bsec_platdata *plat = dev_get_platdata(dev);
u32 tmp_data = 0;
int ret;
/* read current shadow value */
ret = bsec_read_shadow(plat->base, &tmp_data, otp);
if (ret)
return ret;
/* copy otp in shadow */
ret = bsec_shadow_register(plat->base, otp);
if (ret)
return ret;
ret = bsec_read_shadow(plat->base, val, otp);
if (ret)
return ret;
/* restore shadow value */
ret = bsec_write_shadow(plat->base, tmp_data, otp);
return ret;
#endif
}
static int stm32mp_bsec_read_shadow(struct udevice *dev, u32 *val, u32 otp)
{
#ifdef CONFIG_STM32MP1_TRUSTED
return stm32_smc(STM32_SMC_BSEC,
STM32_SMC_READ_SHADOW,
otp, 0, val);
#else
struct stm32mp_bsec_platdata *plat = dev_get_platdata(dev);
return bsec_read_shadow(plat->base, val, otp);
#endif
}
static int stm32mp_bsec_write_otp(struct udevice *dev, u32 val, u32 otp)
{
#ifdef CONFIG_STM32MP1_TRUSTED
return stm32_smc_exec(STM32_SMC_BSEC,
STM32_SMC_PROG_OTP,
otp, val);
#else
struct stm32mp_bsec_platdata *plat = dev_get_platdata(dev);
return bsec_program_otp(plat->base, val, otp);
#endif
}
static int stm32mp_bsec_write_shadow(struct udevice *dev, u32 val, u32 otp)
{
#ifdef CONFIG_STM32MP1_TRUSTED
return stm32_smc_exec(STM32_SMC_BSEC,
STM32_SMC_WRITE_SHADOW,
otp, val);
#else
struct stm32mp_bsec_platdata *plat = dev_get_platdata(dev);
return bsec_write_shadow(plat->base, val, otp);
#endif
}
static int stm32mp_bsec_read(struct udevice *dev, int offset,
void *buf, int size)
{
int ret;
int i;
bool shadow = true;
int nb_otp = size / sizeof(u32);
int otp;
unsigned int offs = offset;
if (offs >= STM32_BSEC_OTP_OFFSET) {
offs -= STM32_BSEC_OTP_OFFSET;
shadow = false;
}
if (offs < 0 || (offs % 4) || (size % 4))
return -EINVAL;
otp = offs / sizeof(u32);
for (i = otp; i < (otp + nb_otp) && i <= BSEC_OTP_MAX_VALUE; i++) {
u32 *addr = &((u32 *)buf)[i - otp];
if (shadow)
ret = stm32mp_bsec_read_shadow(dev, addr, i);
else
ret = stm32mp_bsec_read_otp(dev, addr, i);
if (ret)
break;
}
if (ret)
return ret;
else
return (i - otp) * 4;
}
static int stm32mp_bsec_write(struct udevice *dev, int offset,
const void *buf, int size)
{
int ret = 0;
int i;
bool shadow = true;
int nb_otp = size / sizeof(u32);
int otp;
unsigned int offs = offset;
if (offs >= STM32_BSEC_OTP_OFFSET) {
offs -= STM32_BSEC_OTP_OFFSET;
shadow = false;
}
if (offs < 0 || (offs % 4) || (size % 4))
return -EINVAL;
otp = offs / sizeof(u32);
for (i = otp; i < otp + nb_otp && i <= BSEC_OTP_MAX_VALUE; i++) {
u32 *val = &((u32 *)buf)[i - otp];
if (shadow)
ret = stm32mp_bsec_write_shadow(dev, *val, i);
else
ret = stm32mp_bsec_write_otp(dev, *val, i);
if (ret)
break;
}
if (ret)
return ret;
else
return (i - otp) * 4;
}
static const struct misc_ops stm32mp_bsec_ops = {
.read = stm32mp_bsec_read,
.write = stm32mp_bsec_write,
};
static int stm32mp_bsec_ofdata_to_platdata(struct udevice *dev)
{
struct stm32mp_bsec_platdata *plat = dev_get_platdata(dev);
plat->base = (u32)dev_read_addr_ptr(dev);
return 0;
}
#ifndef CONFIG_STM32MP1_TRUSTED
static int stm32mp_bsec_probe(struct udevice *dev)
{
int otp;
struct stm32mp_bsec_platdata *plat = dev_get_platdata(dev);
/* update unlocked shadow for OTP cleared by the rom code */
for (otp = 57; otp <= BSEC_OTP_MAX_VALUE; otp++)
if (!bsec_read_SR_lock(plat->base, otp))
bsec_shadow_register(plat->base, otp);
return 0;
}
#endif
static const struct udevice_id stm32mp_bsec_ids[] = {
{ .compatible = "st,stm32mp15-bsec" },
{}
};
U_BOOT_DRIVER(stm32mp_bsec) = {
.name = "stm32mp_bsec",
.id = UCLASS_MISC,
.of_match = stm32mp_bsec_ids,
.ofdata_to_platdata = stm32mp_bsec_ofdata_to_platdata,
.platdata_auto_alloc_size = sizeof(struct stm32mp_bsec_platdata),
.ops = &stm32mp_bsec_ops,
#ifndef CONFIG_STM32MP1_TRUSTED
.probe = stm32mp_bsec_probe,
#endif
};
@@ -0,0 +1,101 @@
// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
/*
* Copyright (C) 2019, STMicroelectronics - All Rights Reserved
*/
#include <common.h>
#include <command.h>
#include <console.h>
#include <misc.h>
#include <dm/device.h>
#include <dm/uclass.h>
#define STM32_OTP_HASH_KEY_START 24
#define STM32_OTP_HASH_KEY_SIZE 8
static void read_hash_value(u32 addr)
{
int i;
for (i = 0; i < STM32_OTP_HASH_KEY_SIZE; i++) {
printf("OTP value %i: %x\n", STM32_OTP_HASH_KEY_START + i,
__be32_to_cpu(*(u32 *)addr));
addr += 4;
}
}
static void fuse_hash_value(u32 addr, bool print)
{
struct udevice *dev;
u32 word, val;
int i, ret;
ret = uclass_get_device_by_driver(UCLASS_MISC,
DM_GET_DRIVER(stm32mp_bsec),
&dev);
if (ret) {
pr_err("Can't find stm32mp_bsec driver\n");
return;
}
for (i = 0; i < STM32_OTP_HASH_KEY_SIZE; i++) {
if (print)
printf("Fuse OTP %i : %x\n",
STM32_OTP_HASH_KEY_START + i,
__be32_to_cpu(*(u32 *)addr));
word = STM32_OTP_HASH_KEY_START + i;
val = __be32_to_cpu(*(u32 *)addr);
misc_write(dev, STM32_BSEC_OTP(word), &val, 4);
addr += 4;
}
}
static int confirm_prog(void)
{
puts("Warning: Programming fuses is an irreversible operation!\n"
" This may brick your system.\n"
" Use this command only if you are sure of what you are doing!\n"
"\nReally perform this fuse programming? <y/N>\n");
if (confirm_yesno())
return 1;
puts("Fuse programming aborted\n");
return 0;
}
static int do_stm32key(cmd_tbl_t *cmdtp, int flag, int argc,
char * const argv[])
{
u32 addr;
const char *op = argc >= 2 ? argv[1] : NULL;
int confirmed = argc > 3 && !strcmp(argv[2], "-y");
argc -= 2 + confirmed;
argv += 2 + confirmed;
if (argc < 1)
return CMD_RET_USAGE;
addr = simple_strtoul(argv[0], NULL, 16);
if (!addr)
return CMD_RET_USAGE;
if (!strcmp(op, "read"))
read_hash_value(addr);
if (!strcmp(op, "fuse")) {
if (!confirmed && !confirm_prog())
return CMD_RET_FAILURE;
fuse_hash_value(addr, !confirmed);
}
return CMD_RET_SUCCESS;
}
U_BOOT_CMD(stm32key, 4, 1, do_stm32key,
"Fuse ST Hash key",
"read <addr>: Read the hash store at addr in memory\n"
"stm32key fuse [-y] <addr> : Fuse hash store at addr in otp\n");
@@ -0,0 +1,29 @@
# SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
#
# Copyright (C) 2018, STMicroelectronics - All Rights Reserved
#
ifndef CONFIG_SPL
ALL-y += u-boot.stm32
else
ifdef CONFIG_SPL_BUILD
ALL-y += u-boot-spl.stm32
endif
endif
MKIMAGEFLAGS_u-boot.stm32 = -T stm32image -a $(CONFIG_SYS_TEXT_BASE) -e $(CONFIG_SYS_TEXT_BASE)
u-boot.stm32: MKIMAGEOUTPUT = u-boot.stm32.log
u-boot.stm32: u-boot.bin FORCE
$(call if_changed,mkimage)
MKIMAGEFLAGS_u-boot-spl.stm32 = -T stm32image -a $(CONFIG_SPL_TEXT_BASE) -e $(CONFIG_SPL_TEXT_BASE)
spl/u-boot-spl.stm32: MKIMAGEOUTPUT = spl/u-boot-spl.stm32.log
spl/u-boot-spl.stm32: spl/u-boot-spl.bin FORCE
$(call if_changed,mkimage)
u-boot-spl.stm32 : spl/u-boot-spl.stm32
$(call if_changed,copy)
@@ -0,0 +1,527 @@
// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
/*
* Copyright (C) 2018, STMicroelectronics - All Rights Reserved
*/
#include <common.h>
#include <clk.h>
#include <cpu_func.h>
#include <debug_uart.h>
#include <env.h>
#include <misc.h>
#include <asm/io.h>
#include <asm/arch/stm32.h>
#include <asm/arch/sys_proto.h>
#include <dm/device.h>
#include <dm/uclass.h>
/* RCC register */
#define RCC_TZCR (STM32_RCC_BASE + 0x00)
#define RCC_DBGCFGR (STM32_RCC_BASE + 0x080C)
#define RCC_BDCR (STM32_RCC_BASE + 0x0140)
#define RCC_MP_APB5ENSETR (STM32_RCC_BASE + 0x0208)
#define RCC_MP_AHB5ENSETR (STM32_RCC_BASE + 0x0210)
#define RCC_BDCR_VSWRST BIT(31)
#define RCC_BDCR_RTCSRC GENMASK(17, 16)
#define RCC_DBGCFGR_DBGCKEN BIT(8)
/* Security register */
#define ETZPC_TZMA1_SIZE (STM32_ETZPC_BASE + 0x04)
#define ETZPC_DECPROT0 (STM32_ETZPC_BASE + 0x10)
#define TZC_GATE_KEEPER (STM32_TZC_BASE + 0x008)
#define TZC_REGION_ATTRIBUTE0 (STM32_TZC_BASE + 0x110)
#define TZC_REGION_ID_ACCESS0 (STM32_TZC_BASE + 0x114)
#define TAMP_CR1 (STM32_TAMP_BASE + 0x00)
#define PWR_CR1 (STM32_PWR_BASE + 0x00)
#define PWR_CR1_DBP BIT(8)
/* DBGMCU register */
#define DBGMCU_IDC (STM32_DBGMCU_BASE + 0x00)
#define DBGMCU_APB4FZ1 (STM32_DBGMCU_BASE + 0x2C)
#define DBGMCU_APB4FZ1_IWDG2 BIT(2)
#define DBGMCU_IDC_DEV_ID_MASK GENMASK(11, 0)
#define DBGMCU_IDC_DEV_ID_SHIFT 0
#define DBGMCU_IDC_REV_ID_MASK GENMASK(31, 16)
#define DBGMCU_IDC_REV_ID_SHIFT 16
/* GPIOZ registers */
#define GPIOZ_SECCFGR 0x54004030
/* boot interface from Bootrom
* - boot instance = bit 31:16
* - boot device = bit 15:0
*/
#define BOOTROM_PARAM_ADDR 0x2FFC0078
#define BOOTROM_MODE_MASK GENMASK(15, 0)
#define BOOTROM_MODE_SHIFT 0
#define BOOTROM_INSTANCE_MASK GENMASK(31, 16)
#define BOOTROM_INSTANCE_SHIFT 16
/* BSEC OTP index */
#define BSEC_OTP_RPN 1
#define BSEC_OTP_SERIAL 13
#define BSEC_OTP_PKG 16
#define BSEC_OTP_MAC 57
/* Device Part Number (RPN) = OTP_DATA1 lower 8 bits */
#define RPN_SHIFT 0
#define RPN_MASK GENMASK(7, 0)
/* Package = bit 27:29 of OTP16
* - 100: LBGA448 (FFI) => AA = LFBGA 18x18mm 448 balls p. 0.8mm
* - 011: LBGA354 (LCI) => AB = LFBGA 16x16mm 359 balls p. 0.8mm
* - 010: TFBGA361 (FFC) => AC = TFBGA 12x12mm 361 balls p. 0.5mm
* - 001: TFBGA257 (LCC) => AD = TFBGA 10x10mm 257 balls p. 0.5mm
* - others: Reserved
*/
#define PKG_SHIFT 27
#define PKG_MASK GENMASK(2, 0)
#if !defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD)
#ifndef CONFIG_STM32MP1_TRUSTED
static void security_init(void)
{
/* Disable the backup domain write protection */
/* the protection is enable at each reset by hardware */
/* And must be disable by software */
setbits_le32(PWR_CR1, PWR_CR1_DBP);
while (!(readl(PWR_CR1) & PWR_CR1_DBP))
;
/* If RTC clock isn't enable so this is a cold boot then we need
* to reset the backup domain
*/
if (!(readl(RCC_BDCR) & RCC_BDCR_RTCSRC)) {
setbits_le32(RCC_BDCR, RCC_BDCR_VSWRST);
while (!(readl(RCC_BDCR) & RCC_BDCR_VSWRST))
;
clrbits_le32(RCC_BDCR, RCC_BDCR_VSWRST);
}
/* allow non secure access in Write/Read for all peripheral */
writel(GENMASK(25, 0), ETZPC_DECPROT0);
/* Open SYSRAM for no secure access */
writel(0x0, ETZPC_TZMA1_SIZE);
/* enable TZC1 TZC2 clock */
writel(BIT(11) | BIT(12), RCC_MP_APB5ENSETR);
/* Region 0 set to no access by default */
/* bit 0 / 16 => nsaid0 read/write Enable
* bit 1 / 17 => nsaid1 read/write Enable
* ...
* bit 15 / 31 => nsaid15 read/write Enable
*/
writel(0xFFFFFFFF, TZC_REGION_ID_ACCESS0);
/* bit 30 / 31 => Secure Global Enable : write/read */
/* bit 0 / 1 => Region Enable for filter 0/1 */
writel(BIT(0) | BIT(1) | BIT(30) | BIT(31), TZC_REGION_ATTRIBUTE0);
/* Enable Filter 0 and 1 */
setbits_le32(TZC_GATE_KEEPER, BIT(0) | BIT(1));
/* RCC trust zone deactivated */
writel(0x0, RCC_TZCR);
/* TAMP: deactivate the internal tamper
* Bit 23 ITAMP8E: monotonic counter overflow
* Bit 20 ITAMP5E: RTC calendar overflow
* Bit 19 ITAMP4E: HSE monitoring
* Bit 18 ITAMP3E: LSE monitoring
* Bit 16 ITAMP1E: RTC power domain supply monitoring
*/
writel(0x0, TAMP_CR1);
/* GPIOZ: deactivate the security */
writel(BIT(0), RCC_MP_AHB5ENSETR);
writel(0x0, GPIOZ_SECCFGR);
}
#endif /* CONFIG_STM32MP1_TRUSTED */
/*
* Debug init
*/
static void dbgmcu_init(void)
{
setbits_le32(RCC_DBGCFGR, RCC_DBGCFGR_DBGCKEN);
/* Freeze IWDG2 if Cortex-A7 is in debug mode */
setbits_le32(DBGMCU_APB4FZ1, DBGMCU_APB4FZ1_IWDG2);
}
#endif /* !defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD) */
#if !defined(CONFIG_STM32MP1_TRUSTED) && \
(!defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD))
/* get bootmode from ROM code boot context: saved in TAMP register */
static void update_bootmode(void)
{
u32 boot_mode;
u32 bootrom_itf = readl(BOOTROM_PARAM_ADDR);
u32 bootrom_device, bootrom_instance;
/* enable TAMP clock = RTCAPBEN */
writel(BIT(8), RCC_MP_APB5ENSETR);
/* read bootrom context */
bootrom_device =
(bootrom_itf & BOOTROM_MODE_MASK) >> BOOTROM_MODE_SHIFT;
bootrom_instance =
(bootrom_itf & BOOTROM_INSTANCE_MASK) >> BOOTROM_INSTANCE_SHIFT;
boot_mode =
((bootrom_device << BOOT_TYPE_SHIFT) & BOOT_TYPE_MASK) |
((bootrom_instance << BOOT_INSTANCE_SHIFT) &
BOOT_INSTANCE_MASK);
/* save the boot mode in TAMP backup register */
clrsetbits_le32(TAMP_BOOT_CONTEXT,
TAMP_BOOT_MODE_MASK,
boot_mode << TAMP_BOOT_MODE_SHIFT);
}
#endif
u32 get_bootmode(void)
{
/* read bootmode from TAMP backup register */
return (readl(TAMP_BOOT_CONTEXT) & TAMP_BOOT_MODE_MASK) >>
TAMP_BOOT_MODE_SHIFT;
}
/*
* Early system init
*/
int arch_cpu_init(void)
{
u32 boot_mode;
/* early armv7 timer init: needed for polling */
timer_init();
#if !defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD)
dbgmcu_init();
#ifndef CONFIG_STM32MP1_TRUSTED
security_init();
update_bootmode();
#endif
#endif
boot_mode = get_bootmode();
if ((boot_mode & TAMP_BOOT_DEVICE_MASK) == BOOT_SERIAL_UART)
gd->flags |= GD_FLG_SILENT | GD_FLG_DISABLE_CONSOLE;
#if defined(CONFIG_DEBUG_UART) && \
!defined(CONFIG_STM32MP1_TRUSTED) && \
(!defined(CONFIG_SPL) || defined(CONFIG_SPL_BUILD))
else
debug_uart_init();
#endif
return 0;
}
void enable_caches(void)
{
/* Enable D-cache. I-cache is already enabled in start.S */
dcache_enable();
}
static u32 read_idc(void)
{
setbits_le32(RCC_DBGCFGR, RCC_DBGCFGR_DBGCKEN);
return readl(DBGMCU_IDC);
}
u32 get_cpu_rev(void)
{
return (read_idc() & DBGMCU_IDC_REV_ID_MASK) >> DBGMCU_IDC_REV_ID_SHIFT;
}
static u32 get_otp(int index, int shift, int mask)
{
int ret;
struct udevice *dev;
u32 otp = 0;
ret = uclass_get_device_by_driver(UCLASS_MISC,
DM_GET_DRIVER(stm32mp_bsec),
&dev);
if (!ret)
ret = misc_read(dev, STM32_BSEC_SHADOW(index),
&otp, sizeof(otp));
return (otp >> shift) & mask;
}
/* Get Device Part Number (RPN) from OTP */
static u32 get_cpu_rpn(void)
{
return get_otp(BSEC_OTP_RPN, RPN_SHIFT, RPN_MASK);
}
u32 get_cpu_type(void)
{
u32 id;
id = (read_idc() & DBGMCU_IDC_DEV_ID_MASK) >> DBGMCU_IDC_DEV_ID_SHIFT;
return (id << 16) | get_cpu_rpn();
}
/* Get Package options from OTP */
u32 get_cpu_package(void)
{
return get_otp(BSEC_OTP_PKG, PKG_SHIFT, PKG_MASK);
}
#if defined(CONFIG_DISPLAY_CPUINFO)
int print_cpuinfo(void)
{
char *cpu_s, *cpu_r, *pkg;
/* MPUs Part Numbers */
switch (get_cpu_type()) {
case CPU_STM32MP157Cxx:
cpu_s = "157C";
break;
case CPU_STM32MP157Axx:
cpu_s = "157A";
break;
case CPU_STM32MP153Cxx:
cpu_s = "153C";
break;
case CPU_STM32MP153Axx:
cpu_s = "153A";
break;
case CPU_STM32MP151Cxx:
cpu_s = "151C";
break;
case CPU_STM32MP151Axx:
cpu_s = "151A";
break;
default:
cpu_s = "????";
break;
}
/* Package */
switch (get_cpu_package()) {
case PKG_AA_LBGA448:
pkg = "AA";
break;
case PKG_AB_LBGA354:
pkg = "AB";
break;
case PKG_AC_TFBGA361:
pkg = "AC";
break;
case PKG_AD_TFBGA257:
pkg = "AD";
break;
default:
pkg = "??";
break;
}
/* REVISION */
switch (get_cpu_rev()) {
case CPU_REVA:
cpu_r = "A";
break;
case CPU_REVB:
cpu_r = "B";
break;
default:
cpu_r = "?";
break;
}
printf("CPU: STM32MP%s%s Rev.%s\n", cpu_s, pkg, cpu_r);
return 0;
}
#endif /* CONFIG_DISPLAY_CPUINFO */
static void setup_boot_mode(void)
{
const u32 serial_addr[] = {
STM32_USART1_BASE,
STM32_USART2_BASE,
STM32_USART3_BASE,
STM32_UART4_BASE,
STM32_UART5_BASE,
STM32_USART6_BASE,
STM32_UART7_BASE,
STM32_UART8_BASE
};
char cmd[60];
u32 boot_ctx = readl(TAMP_BOOT_CONTEXT);
u32 boot_mode =
(boot_ctx & TAMP_BOOT_MODE_MASK) >> TAMP_BOOT_MODE_SHIFT;
unsigned int instance = (boot_mode & TAMP_BOOT_INSTANCE_MASK) - 1;
u32 forced_mode = (boot_ctx & TAMP_BOOT_FORCED_MASK);
struct udevice *dev;
int alias;
pr_debug("%s: boot_ctx=0x%x => boot_mode=%x, instance=%d forced=%x\n",
__func__, boot_ctx, boot_mode, instance, forced_mode);
switch (boot_mode & TAMP_BOOT_DEVICE_MASK) {
case BOOT_SERIAL_UART:
if (instance > ARRAY_SIZE(serial_addr))
break;
/* serial : search associated alias in devicetree */
sprintf(cmd, "serial@%x", serial_addr[instance]);
if (uclass_get_device_by_name(UCLASS_SERIAL, cmd, &dev))
break;
if (fdtdec_get_alias_seq(gd->fdt_blob, "serial",
dev_of_offset(dev), &alias))
break;
sprintf(cmd, "%d", alias);
env_set("boot_device", "serial");
env_set("boot_instance", cmd);
/* restore console on uart when not used */
if (gd->cur_serial_dev != dev) {
gd->flags &= ~(GD_FLG_SILENT |
GD_FLG_DISABLE_CONSOLE);
printf("serial boot with console enabled!\n");
}
break;
case BOOT_SERIAL_USB:
env_set("boot_device", "usb");
env_set("boot_instance", "0");
break;
case BOOT_FLASH_SD:
case BOOT_FLASH_EMMC:
sprintf(cmd, "%d", instance);
env_set("boot_device", "mmc");
env_set("boot_instance", cmd);
break;
case BOOT_FLASH_NAND:
env_set("boot_device", "nand");
env_set("boot_instance", "0");
break;
case BOOT_FLASH_NOR:
env_set("boot_device", "nor");
env_set("boot_instance", "0");
break;
default:
pr_debug("unexpected boot mode = %x\n", boot_mode);
break;
}
switch (forced_mode) {
case BOOT_FASTBOOT:
printf("Enter fastboot!\n");
env_set("preboot", "env set preboot; fastboot 0");
break;
case BOOT_STM32PROG:
env_set("boot_device", "usb");
env_set("boot_instance", "0");
break;
case BOOT_UMS_MMC0:
case BOOT_UMS_MMC1:
case BOOT_UMS_MMC2:
printf("Enter UMS!\n");
instance = forced_mode - BOOT_UMS_MMC0;
sprintf(cmd, "env set preboot; ums 0 mmc %d", instance);
env_set("preboot", cmd);
break;
case BOOT_RECOVERY:
env_set("preboot", "env set preboot; run altbootcmd");
break;
case BOOT_NORMAL:
break;
default:
pr_debug("unexpected forced boot mode = %x\n", forced_mode);
break;
}
/* clear TAMP for next reboot */
clrsetbits_le32(TAMP_BOOT_CONTEXT, TAMP_BOOT_FORCED_MASK, BOOT_NORMAL);
}
/*
* If there is no MAC address in the environment, then it will be initialized
* (silently) from the value in the OTP.
*/
static int setup_mac_address(void)
{
#if defined(CONFIG_NET)
int ret;
int i;
u32 otp[2];
uchar enetaddr[6];
struct udevice *dev;
/* MAC already in environment */
if (eth_env_get_enetaddr("ethaddr", enetaddr))
return 0;
ret = uclass_get_device_by_driver(UCLASS_MISC,
DM_GET_DRIVER(stm32mp_bsec),
&dev);
if (ret)
return ret;
ret = misc_read(dev, STM32_BSEC_SHADOW(BSEC_OTP_MAC),
otp, sizeof(otp));
if (ret < 0)
return ret;
for (i = 0; i < 6; i++)
enetaddr[i] = ((uint8_t *)&otp)[i];
if (!is_valid_ethaddr(enetaddr)) {
pr_err("invalid MAC address in OTP %pM\n", enetaddr);
return -EINVAL;
}
pr_debug("OTP MAC address = %pM\n", enetaddr);
ret = !eth_env_set_enetaddr("ethaddr", enetaddr);
if (!ret)
pr_err("Failed to set mac address %pM from OTP: %d\n",
enetaddr, ret);
#endif
return 0;
}
static int setup_serial_number(void)
{
char serial_string[25];
u32 otp[3] = {0, 0, 0 };
struct udevice *dev;
int ret;
if (env_get("serial#"))
return 0;
ret = uclass_get_device_by_driver(UCLASS_MISC,
DM_GET_DRIVER(stm32mp_bsec),
&dev);
if (ret)
return ret;
ret = misc_read(dev, STM32_BSEC_SHADOW(BSEC_OTP_SERIAL),
otp, sizeof(otp));
if (ret < 0)
return ret;
sprintf(serial_string, "%08X%08X%08X", otp[0], otp[1], otp[2]);
env_set("serial#", serial_string);
return 0;
}
int arch_misc_init(void)
{
setup_boot_mode();
setup_mac_address();
setup_serial_number();
return 0;
}
@@ -0,0 +1,33 @@
// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
/*
* Copyright (C) 2018, STMicroelectronics - All Rights Reserved
*/
#include <common.h>
#include <dm.h>
#include <ram.h>
DECLARE_GLOBAL_DATA_PTR;
int dram_init(void)
{
struct ram_info ram;
struct udevice *dev;
int ret;
ret = uclass_get_device(UCLASS_RAM, 0, &dev);
if (ret) {
debug("RAM init failed: %d\n", ret);
return ret;
}
ret = ram_get_info(dev, &ram);
if (ret) {
debug("Cannot get RAM size: %d\n", ret);
return ret;
}
debug("RAM init base=%lx, size=%x\n", ram.base, ram.size);
gd->ram_size = ram.size;
return 0;
}
@@ -0,0 +1,223 @@
// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
/*
* Copyright (C) 2019, STMicroelectronics - All Rights Reserved
*/
#include <common.h>
#include <fdt_support.h>
#include <asm/arch/sys_proto.h>
#include <dt-bindings/pinctrl/stm32-pinfunc.h>
#include <linux/io.h>
#define ETZPC_DECPROT(n) (STM32_ETZPC_BASE + 0x10 + 4 * (n))
#define ETZPC_DECPROT_NB 6
#define DECPROT_MASK 0x03
#define NB_PROT_PER_REG 0x10
#define DECPROT_NB_BITS 2
#define DECPROT_SECURED 0x00
#define DECPROT_WRITE_SECURE 0x01
#define DECPROT_MCU_ISOLATION 0x02
#define DECPROT_NON_SECURED 0x03
#define ETZPC_RESERVED 0xffffffff
static const u32 stm32mp1_ip_addr[] = {
0x5c008000, /* 00 stgenc */
0x54000000, /* 01 bkpsram */
0x5c003000, /* 02 iwdg1 */
0x5c000000, /* 03 usart1 */
0x5c001000, /* 04 spi6 */
0x5c002000, /* 05 i2c4 */
ETZPC_RESERVED, /* 06 reserved */
0x54003000, /* 07 rng1 */
0x54002000, /* 08 hash1 */
0x54001000, /* 09 cryp1 */
0x5a003000, /* 0A ddrctrl */
0x5a004000, /* 0B ddrphyc */
0x5c009000, /* 0C i2c6 */
ETZPC_RESERVED, /* 0D reserved */
ETZPC_RESERVED, /* 0E reserved */
ETZPC_RESERVED, /* 0F reserved */
0x40000000, /* 10 tim2 */
0x40001000, /* 11 tim3 */
0x40002000, /* 12 tim4 */
0x40003000, /* 13 tim5 */
0x40004000, /* 14 tim6 */
0x40005000, /* 15 tim7 */
0x40006000, /* 16 tim12 */
0x40007000, /* 17 tim13 */
0x40008000, /* 18 tim14 */
0x40009000, /* 19 lptim1 */
0x4000a000, /* 1A wwdg1 */
0x4000b000, /* 1B spi2 */
0x4000c000, /* 1C spi3 */
0x4000d000, /* 1D spdifrx */
0x4000e000, /* 1E usart2 */
0x4000f000, /* 1F usart3 */
0x40010000, /* 20 uart4 */
0x40011000, /* 21 uart5 */
0x40012000, /* 22 i2c1 */
0x40013000, /* 23 i2c2 */
0x40014000, /* 24 i2c3 */
0x40015000, /* 25 i2c5 */
0x40016000, /* 26 cec */
0x40017000, /* 27 dac */
0x40018000, /* 28 uart7 */
0x40019000, /* 29 uart8 */
ETZPC_RESERVED, /* 2A reserved */
ETZPC_RESERVED, /* 2B reserved */
0x4001c000, /* 2C mdios */
ETZPC_RESERVED, /* 2D reserved */
ETZPC_RESERVED, /* 2E reserved */
ETZPC_RESERVED, /* 2F reserved */
0x44000000, /* 30 tim1 */
0x44001000, /* 31 tim8 */
ETZPC_RESERVED, /* 32 reserved */
0x44003000, /* 33 usart6 */
0x44004000, /* 34 spi1 */
0x44005000, /* 35 spi4 */
0x44006000, /* 36 tim15 */
0x44007000, /* 37 tim16 */
0x44008000, /* 38 tim17 */
0x44009000, /* 39 spi5 */
0x4400a000, /* 3A sai1 */
0x4400b000, /* 3B sai2 */
0x4400c000, /* 3C sai3 */
0x4400d000, /* 3D dfsdm */
0x4400e000, /* 3E tt_fdcan */
ETZPC_RESERVED, /* 3F reserved */
0x50021000, /* 40 lptim2 */
0x50022000, /* 41 lptim3 */
0x50023000, /* 42 lptim4 */
0x50024000, /* 43 lptim5 */
0x50027000, /* 44 sai4 */
0x50025000, /* 45 vrefbuf */
0x4c006000, /* 46 dcmi */
0x4c004000, /* 47 crc2 */
0x48003000, /* 48 adc */
0x4c002000, /* 49 hash2 */
0x4c003000, /* 4A rng2 */
0x4c005000, /* 4B cryp2 */
ETZPC_RESERVED, /* 4C reserved */
ETZPC_RESERVED, /* 4D reserved */
ETZPC_RESERVED, /* 4E reserved */
ETZPC_RESERVED, /* 4F reserved */
ETZPC_RESERVED, /* 50 sram1 */
ETZPC_RESERVED, /* 51 sram2 */
ETZPC_RESERVED, /* 52 sram3 */
ETZPC_RESERVED, /* 53 sram4 */
ETZPC_RESERVED, /* 54 retram */
0x49000000, /* 55 otg */
0x48004000, /* 56 sdmmc3 */
0x48005000, /* 57 dlybsd3 */
0x48000000, /* 58 dma1 */
0x48001000, /* 59 dma2 */
0x48002000, /* 5A dmamux */
0x58002000, /* 5B fmc */
0x58003000, /* 5C qspi */
0x58004000, /* 5D dlybq */
0x5800a000, /* 5E eth */
ETZPC_RESERVED, /* 5F reserved */
};
/* fdt helper */
static bool fdt_disable_subnode_by_address(void *fdt, int offset, u32 addr)
{
int node;
for (node = fdt_first_subnode(fdt, offset);
node >= 0;
node = fdt_next_subnode(fdt, node)) {
if (addr == (u32)fdt_getprop(fdt, node, "reg", 0)) {
if (fdtdec_get_is_enabled(fdt, node)) {
fdt_status_disabled(fdt, node);
return true;
}
return false;
}
}
return false;
}
static int stm32_fdt_fixup_etzpc(void *fdt)
{
const u32 *array;
int array_size, i;
int soc_node, offset, shift;
u32 addr, status, decprot[ETZPC_DECPROT_NB];
array = stm32mp1_ip_addr;
array_size = ARRAY_SIZE(stm32mp1_ip_addr);
for (i = 0; i < ETZPC_DECPROT_NB; i++)
decprot[i] = readl(ETZPC_DECPROT(i));
soc_node = fdt_path_offset(fdt, "/soc");
if (soc_node < 0)
return soc_node;
for (i = 0; i < array_size; i++) {
offset = i / NB_PROT_PER_REG;
shift = (i % NB_PROT_PER_REG) * DECPROT_NB_BITS;
status = (decprot[offset] >> shift) & DECPROT_MASK;
addr = array[i];
debug("ETZPC: 0x%08x decprot %d=%d\n", addr, i, status);
if (addr == ETZPC_RESERVED ||
status == DECPROT_NON_SECURED)
continue;
if (fdt_disable_subnode_by_address(fdt, soc_node, addr))
printf("ETZPC: 0x%08x node disabled, decprot %d=%d\n",
addr, i, status);
}
return 0;
}
/*
* This function is called right before the kernel is booted. "blob" is the
* device tree that will be passed to the kernel.
*/
int ft_system_setup(void *blob, bd_t *bd)
{
int ret = 0;
u32 pkg;
if (CONFIG_IS_ENABLED(STM32_ETZPC)) {
ret = stm32_fdt_fixup_etzpc(blob);
if (ret)
return ret;
}
switch (get_cpu_package()) {
case PKG_AA_LBGA448:
pkg = STM32MP_PKG_AA;
break;
case PKG_AB_LBGA354:
pkg = STM32MP_PKG_AB;
break;
case PKG_AC_TFBGA361:
pkg = STM32MP_PKG_AC;
break;
case PKG_AD_TFBGA257:
pkg = STM32MP_PKG_AD;
break;
default:
pkg = 0;
break;
}
if (pkg) {
do_fixup_by_compat_u32(blob, "st,stm32mp157-pinctrl",
"st,package", pkg, false);
do_fixup_by_compat_u32(blob, "st,stm32mp157-z-pinctrl",
"st,package", pkg, false);
}
return ret;
}
@@ -0,0 +1,18 @@
/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */
/*
* Copyright (C) 2018, STMicroelectronics - All Rights Reserved
*/
#ifndef __MACH_STM32MP_DDR_H_
#define __MACH_STM32MP_DDR_H_
/* DDR power initializations */
enum ddr_type {
STM32MP_DDR3,
STM32MP_LPDDR2,
STM32MP_LPDDR3,
};
int board_ddr_power_init(enum ddr_type ddr_type);
#endif
@@ -0,0 +1,120 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* (C) Copyright 2016
* Vikas Manocha, <vikas.manocha@st.com>
*/
#ifndef _STM32_GPIO_H_
#define _STM32_GPIO_H_
#include <asm/gpio.h>
#define STM32_GPIOS_PER_BANK 16
enum stm32_gpio_port {
STM32_GPIO_PORT_A = 0,
STM32_GPIO_PORT_B,
STM32_GPIO_PORT_C,
STM32_GPIO_PORT_D,
STM32_GPIO_PORT_E,
STM32_GPIO_PORT_F,
STM32_GPIO_PORT_G,
STM32_GPIO_PORT_H,
STM32_GPIO_PORT_I
};
enum stm32_gpio_pin {
STM32_GPIO_PIN_0 = 0,
STM32_GPIO_PIN_1,
STM32_GPIO_PIN_2,
STM32_GPIO_PIN_3,
STM32_GPIO_PIN_4,
STM32_GPIO_PIN_5,
STM32_GPIO_PIN_6,
STM32_GPIO_PIN_7,
STM32_GPIO_PIN_8,
STM32_GPIO_PIN_9,
STM32_GPIO_PIN_10,
STM32_GPIO_PIN_11,
STM32_GPIO_PIN_12,
STM32_GPIO_PIN_13,
STM32_GPIO_PIN_14,
STM32_GPIO_PIN_15
};
enum stm32_gpio_mode {
STM32_GPIO_MODE_IN = 0,
STM32_GPIO_MODE_OUT,
STM32_GPIO_MODE_AF,
STM32_GPIO_MODE_AN
};
enum stm32_gpio_otype {
STM32_GPIO_OTYPE_PP = 0,
STM32_GPIO_OTYPE_OD
};
enum stm32_gpio_speed {
STM32_GPIO_SPEED_2M = 0,
STM32_GPIO_SPEED_25M,
STM32_GPIO_SPEED_50M,
STM32_GPIO_SPEED_100M
};
enum stm32_gpio_pupd {
STM32_GPIO_PUPD_NO = 0,
STM32_GPIO_PUPD_UP,
STM32_GPIO_PUPD_DOWN
};
enum stm32_gpio_af {
STM32_GPIO_AF0 = 0,
STM32_GPIO_AF1,
STM32_GPIO_AF2,
STM32_GPIO_AF3,
STM32_GPIO_AF4,
STM32_GPIO_AF5,
STM32_GPIO_AF6,
STM32_GPIO_AF7,
STM32_GPIO_AF8,
STM32_GPIO_AF9,
STM32_GPIO_AF10,
STM32_GPIO_AF11,
STM32_GPIO_AF12,
STM32_GPIO_AF13,
STM32_GPIO_AF14,
STM32_GPIO_AF15
};
struct stm32_gpio_dsc {
enum stm32_gpio_port port;
enum stm32_gpio_pin pin;
};
struct stm32_gpio_ctl {
enum stm32_gpio_mode mode;
enum stm32_gpio_otype otype;
enum stm32_gpio_speed speed;
enum stm32_gpio_pupd pupd;
enum stm32_gpio_af af;
};
struct stm32_gpio_regs {
u32 moder; /* GPIO port mode */
u32 otyper; /* GPIO port output type */
u32 ospeedr; /* GPIO port output speed */
u32 pupdr; /* GPIO port pull-up/pull-down */
u32 idr; /* GPIO port input data */
u32 odr; /* GPIO port output data */
u32 bsrr; /* GPIO port bit set/reset */
u32 lckr; /* GPIO port configuration lock */
u32 afr[2]; /* GPIO alternate function */
};
struct stm32_gpio_priv {
struct stm32_gpio_regs *regs;
unsigned int gpio_range;
};
int stm32_offset_to_index(struct udevice *dev, unsigned int offset);
#endif /* _STM32_GPIO_H_ */
@@ -0,0 +1,118 @@
/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */
/*
* Copyright (C) 2018, STMicroelectronics - All Rights Reserved
*/
#ifndef _MACH_STM32_H_
#define _MACH_STM32_H_
/*
* Peripheral memory map
* only address used before device tree parsing
*/
#define STM32_RCC_BASE 0x50000000
#define STM32_PWR_BASE 0x50001000
#define STM32_DBGMCU_BASE 0x50081000
#define STM32_TZC_BASE 0x5C006000
#define STM32_ETZPC_BASE 0x5C007000
#define STM32_STGEN_BASE 0x5C008000
#define STM32_TAMP_BASE 0x5C00A000
#define STM32_USART1_BASE 0x5C000000
#define STM32_USART2_BASE 0x4000E000
#define STM32_USART3_BASE 0x4000F000
#define STM32_UART4_BASE 0x40010000
#define STM32_UART5_BASE 0x40011000
#define STM32_USART6_BASE 0x44003000
#define STM32_UART7_BASE 0x40018000
#define STM32_UART8_BASE 0x40019000
#define STM32_SYSRAM_BASE 0x2FFC0000
#define STM32_SYSRAM_SIZE SZ_256K
#define STM32_DDR_BASE 0xC0000000
#define STM32_DDR_SIZE SZ_1G
#ifndef __ASSEMBLY__
/* enumerated used to identify the SYSCON driver instance */
enum {
STM32MP_SYSCON_UNKNOWN,
STM32MP_SYSCON_PWR,
STM32MP_SYSCON_SYSCFG,
};
/*
* enumerated for boot interface from Bootrom, used in TAMP_BOOT_CONTEXT
* - boot device = bit 8:4
* - boot instance = bit 3:0
*/
#define BOOT_TYPE_MASK 0xF0
#define BOOT_TYPE_SHIFT 4
#define BOOT_INSTANCE_MASK 0x0F
#define BOOT_INSTANCE_SHIFT 0
enum boot_device {
BOOT_FLASH_SD = 0x10,
BOOT_FLASH_SD_1 = 0x11,
BOOT_FLASH_SD_2 = 0x12,
BOOT_FLASH_SD_3 = 0x13,
BOOT_FLASH_EMMC = 0x20,
BOOT_FLASH_EMMC_1 = 0x21,
BOOT_FLASH_EMMC_2 = 0x22,
BOOT_FLASH_EMMC_3 = 0x23,
BOOT_FLASH_NAND = 0x30,
BOOT_FLASH_NAND_FMC = 0x31,
BOOT_FLASH_NOR = 0x40,
BOOT_FLASH_NOR_QSPI = 0x41,
BOOT_SERIAL_UART = 0x50,
BOOT_SERIAL_UART_1 = 0x51,
BOOT_SERIAL_UART_2 = 0x52,
BOOT_SERIAL_UART_3 = 0x53,
BOOT_SERIAL_UART_4 = 0x54,
BOOT_SERIAL_UART_5 = 0x55,
BOOT_SERIAL_UART_6 = 0x56,
BOOT_SERIAL_UART_7 = 0x57,
BOOT_SERIAL_UART_8 = 0x58,
BOOT_SERIAL_USB = 0x60,
BOOT_SERIAL_USB_OTG = 0x62,
};
/* TAMP registers */
#define TAMP_BACKUP_REGISTER(x) (STM32_TAMP_BASE + 0x100 + 4 * x)
#define TAMP_BACKUP_MAGIC_NUMBER TAMP_BACKUP_REGISTER(4)
#define TAMP_BACKUP_BRANCH_ADDRESS TAMP_BACKUP_REGISTER(5)
#define TAMP_BOOT_CONTEXT TAMP_BACKUP_REGISTER(20)
#define TAMP_BOOTCOUNT TAMP_BACKUP_REGISTER(21)
#define TAMP_BOOT_MODE_MASK GENMASK(15, 8)
#define TAMP_BOOT_MODE_SHIFT 8
#define TAMP_BOOT_DEVICE_MASK GENMASK(7, 4)
#define TAMP_BOOT_INSTANCE_MASK GENMASK(3, 0)
#define TAMP_BOOT_FORCED_MASK GENMASK(7, 0)
#define TAMP_BOOT_DEBUG_ON BIT(16)
enum forced_boot_mode {
BOOT_NORMAL = 0x00,
BOOT_FASTBOOT = 0x01,
BOOT_RECOVERY = 0x02,
BOOT_STM32PROG = 0x03,
BOOT_UMS_MMC0 = 0x10,
BOOT_UMS_MMC1 = 0x11,
BOOT_UMS_MMC2 = 0x12,
};
/* offset used for BSEC driver: misc_read and misc_write */
#define STM32_BSEC_SHADOW_OFFSET 0x0
#define STM32_BSEC_SHADOW(id) (STM32_BSEC_SHADOW_OFFSET + (id) * 4)
#define STM32_BSEC_OTP_OFFSET 0x80000000
#define STM32_BSEC_OTP(id) (STM32_BSEC_OTP_OFFSET + (id) * 4)
#define BSEC_OTP_BOARD 59
#endif /* __ASSEMBLY__*/
#endif /* _MACH_STM32_H_ */
@@ -0,0 +1,64 @@
/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */
/*
* Copyright (C) 2019, STMicroelectronics - All Rights Reserved
*/
#ifndef __STM32MP1_SMC_H__
#define __STM32MP1_SMC_H__
#include <linux/arm-smccc.h>
/*
* SMC function IDs for STM32 Service queries
* STM32 SMC services use the space between 0x82000000 and 0x8200FFFF
* like this is defined in SMC calling Convention by ARM
* for SiP (silicon Partner)
* http://infocenter.arm.com/help/topic/com.arm.doc.den0028a/index.html
*/
#define STM32_SMC_VERSION 0x82000000
/* Secure Service access from Non-secure */
#define STM32_SMC_BSEC 0x82001003
/* Service for BSEC */
#define STM32_SMC_READ_SHADOW 0x01
#define STM32_SMC_PROG_OTP 0x02
#define STM32_SMC_WRITE_SHADOW 0x03
#define STM32_SMC_READ_OTP 0x04
#define STM32_SMC_READ_ALL 0x05
#define STM32_SMC_WRITE_ALL 0x06
/* SMC error codes */
#define STM32_SMC_OK 0x0
#define STM32_SMC_NOT_SUPPORTED -1
#define STM32_SMC_FAILED -2
#define STM32_SMC_INVALID_PARAMS -3
#define stm32_smc_exec(svc, op, data1, data2) \
stm32_smc(svc, op, data1, data2, NULL)
#ifdef CONFIG_ARM_SMCCC
static inline u32 stm32_smc(u32 svc, u8 op, u32 data1, u32 data2, u32 *result)
{
struct arm_smccc_res res;
arm_smccc_smc(svc, op, data1, data2, 0, 0, 0, 0, &res);
if (res.a0) {
pr_err("%s: Failed to exec in secure mode (err = %ld)\n",
__func__, res.a0);
return -EINVAL;
}
if (result)
*result = (u32)res.a1;
return 0;
}
#else
static inline u32 stm32_smc(u32 svc, u8 op, u32 data1, u32 data2, u32 *result)
{
return 0;
}
#endif
#endif /* __STM32MP1_SMC_H__ */
@@ -0,0 +1,32 @@
/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */
/*
* Copyright (C) 2015-2017, STMicroelectronics - All Rights Reserved
*/
/* ID = Device Version (bit31:16) + Device Part Number (RPN) (bit15:0)*/
#define CPU_STM32MP157Cxx 0x05000000
#define CPU_STM32MP157Axx 0x05000001
#define CPU_STM32MP153Cxx 0x05000024
#define CPU_STM32MP153Axx 0x05000025
#define CPU_STM32MP151Cxx 0x0500002E
#define CPU_STM32MP151Axx 0x0500002F
/* return CPU_STMP32MP...Xxx constants */
u32 get_cpu_type(void);
#define CPU_REVA 0x1000
#define CPU_REVB 0x2000
/* return CPU_REV constants */
u32 get_cpu_rev(void);
/* Get Package options from OTP */
u32 get_cpu_package(void);
#define PKG_AA_LBGA448 4
#define PKG_AB_LBGA354 3
#define PKG_AC_TFBGA361 2
#define PKG_AD_TFBGA257 1
/* return boot mode */
u32 get_bootmode(void);
@@ -0,0 +1,200 @@
// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
/*
* Copyright (C) 2018, STMicroelectronics - All Rights Reserved
*/
#include <config.h>
#include <common.h>
#include <asm/armv7.h>
#include <asm/gic.h>
#include <asm/io.h>
#include <asm/psci.h>
#include <asm/secure.h>
#define BOOT_API_A7_CORE0_MAGIC_NUMBER 0xCA7FACE0
#define BOOT_API_A7_CORE1_MAGIC_NUMBER 0xCA7FACE1
#define MPIDR_AFF0 GENMASK(7, 0)
#define RCC_MP_GRSTCSETR (STM32_RCC_BASE + 0x0404)
#define RCC_MP_GRSTCSETR_MPUP1RST BIT(5)
#define RCC_MP_GRSTCSETR_MPUP0RST BIT(4)
#define RCC_MP_GRSTCSETR_MPSYSRST BIT(0)
#define STM32MP1_PSCI_NR_CPUS 2
#if STM32MP1_PSCI_NR_CPUS > CONFIG_ARMV7_PSCI_NR_CPUS
#error "invalid value for CONFIG_ARMV7_PSCI_NR_CPUS"
#endif
u8 psci_state[STM32MP1_PSCI_NR_CPUS] __secure_data = {
PSCI_AFFINITY_LEVEL_ON,
PSCI_AFFINITY_LEVEL_OFF};
static inline void psci_set_state(int cpu, u8 state)
{
psci_state[cpu] = state;
dsb();
isb();
}
static u32 __secure stm32mp_get_gicd_base_address(void)
{
u32 periphbase;
/* get the GIC base address from the CBAR register */
asm("mrc p15, 4, %0, c15, c0, 0\n" : "=r" (periphbase));
return (periphbase & CBAR_MASK) + GIC_DIST_OFFSET;
}
static void __secure stm32mp_raise_sgi0(int cpu)
{
u32 gic_dist_addr;
gic_dist_addr = stm32mp_get_gicd_base_address();
/* ask cpu with SGI0 */
writel((BIT(cpu) << 16), gic_dist_addr + GICD_SGIR);
}
void __secure psci_arch_cpu_entry(void)
{
u32 cpu = psci_get_cpu_id();
psci_set_state(cpu, PSCI_AFFINITY_LEVEL_ON);
/* reset magic in TAMP register */
writel(0xFFFFFFFF, TAMP_BACKUP_MAGIC_NUMBER);
}
s32 __secure psci_features(u32 function_id, u32 psci_fid)
{
switch (psci_fid) {
case ARM_PSCI_0_2_FN_PSCI_VERSION:
case ARM_PSCI_0_2_FN_CPU_OFF:
case ARM_PSCI_0_2_FN_CPU_ON:
case ARM_PSCI_0_2_FN_AFFINITY_INFO:
case ARM_PSCI_0_2_FN_MIGRATE_INFO_TYPE:
case ARM_PSCI_0_2_FN_SYSTEM_OFF:
case ARM_PSCI_0_2_FN_SYSTEM_RESET:
return 0x0;
}
return ARM_PSCI_RET_NI;
}
u32 __secure psci_version(void)
{
return ARM_PSCI_VER_1_0;
}
s32 __secure psci_affinity_info(u32 function_id, u32 target_affinity,
u32 lowest_affinity_level)
{
u32 cpu = target_affinity & MPIDR_AFF0;
if (lowest_affinity_level > 0)
return ARM_PSCI_RET_INVAL;
if (target_affinity & ~MPIDR_AFF0)
return ARM_PSCI_RET_INVAL;
if (cpu >= STM32MP1_PSCI_NR_CPUS)
return ARM_PSCI_RET_INVAL;
return psci_state[cpu];
}
u32 __secure psci_migrate_info_type(void)
{
/*
* in Power_State_Coordination_Interface_PDD_v1_1_DEN0022D.pdf
* return 2 = Trusted OS is either not present or does not require
* migration, system of this type does not require the caller
* to use the MIGRATE function.
* MIGRATE function calls return NOT_SUPPORTED.
*/
return 2;
}
s32 __secure psci_cpu_on(u32 function_id, u32 target_cpu, u32 pc,
u32 context_id)
{
u32 cpu = target_cpu & MPIDR_AFF0;
if (target_cpu & ~MPIDR_AFF0)
return ARM_PSCI_RET_INVAL;
if (cpu >= STM32MP1_PSCI_NR_CPUS)
return ARM_PSCI_RET_INVAL;
if (psci_state[cpu] == PSCI_AFFINITY_LEVEL_ON)
return ARM_PSCI_RET_ALREADY_ON;
/* reset magic in TAMP register */
if (readl(TAMP_BACKUP_MAGIC_NUMBER))
writel(0xFFFFFFFF, TAMP_BACKUP_MAGIC_NUMBER);
/*
* ROM code need a first SGI0 after core reset
* core is ready when magic is set to 0 in ROM code
*/
while (readl(TAMP_BACKUP_MAGIC_NUMBER))
stm32mp_raise_sgi0(cpu);
/* store target PC and context id*/
psci_save(cpu, pc, context_id);
/* write entrypoint in backup RAM register */
writel((u32)&psci_cpu_entry, TAMP_BACKUP_BRANCH_ADDRESS);
psci_set_state(cpu, PSCI_AFFINITY_LEVEL_ON_PENDING);
/* write magic number in backup register */
if (cpu == 0x01)
writel(BOOT_API_A7_CORE1_MAGIC_NUMBER,
TAMP_BACKUP_MAGIC_NUMBER);
else
writel(BOOT_API_A7_CORE0_MAGIC_NUMBER,
TAMP_BACKUP_MAGIC_NUMBER);
/* Generate an IT to start the core */
stm32mp_raise_sgi0(cpu);
return ARM_PSCI_RET_SUCCESS;
}
s32 __secure psci_cpu_off(void)
{
u32 cpu;
cpu = psci_get_cpu_id();
psci_cpu_off_common();
psci_set_state(cpu, PSCI_AFFINITY_LEVEL_OFF);
/* reset core: wfi is managed by BootRom */
if (cpu == 0x01)
writel(RCC_MP_GRSTCSETR_MPUP1RST, RCC_MP_GRSTCSETR);
else
writel(RCC_MP_GRSTCSETR_MPUP0RST, RCC_MP_GRSTCSETR);
/* just waiting reset */
while (1)
wfi();
}
void __secure psci_system_reset(void)
{
/* System reset */
writel(RCC_MP_GRSTCSETR_MPSYSRST, RCC_MP_GRSTCSETR);
/* just waiting reset */
while (1)
wfi();
}
void __secure psci_system_off(void)
{
/* System Off is not managed, waiting user power off
* TODO: handle I2C write in PMIC Main Control register bit 0 = SWOFF
*/
while (1)
wfi();
}
@@ -0,0 +1,274 @@
// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
/*
* Copyright (C) 2018, STMicroelectronics - All Rights Reserved
*/
#include <common.h>
#include <dm.h>
#include <errno.h>
#include <regmap.h>
#include <syscon.h>
#include <power/pmic.h>
#include <power/regulator.h>
#define STM32MP_PWR_CR3 0xc
#define STM32MP_PWR_CR3_USB33DEN BIT(24)
#define STM32MP_PWR_CR3_USB33RDY BIT(26)
#define STM32MP_PWR_CR3_REG18DEN BIT(28)
#define STM32MP_PWR_CR3_REG18RDY BIT(29)
#define STM32MP_PWR_CR3_REG11DEN BIT(30)
#define STM32MP_PWR_CR3_REG11RDY BIT(31)
struct stm32mp_pwr_reg_info {
u32 enable;
u32 ready;
char *name;
};
struct stm32mp_pwr_priv {
struct regmap *regmap;
};
static int stm32mp_pwr_write(struct udevice *dev, uint reg,
const uint8_t *buff, int len)
{
struct stm32mp_pwr_priv *priv = dev_get_priv(dev);
u32 val = *(u32 *)buff;
if (len != 4)
return -EINVAL;
return regmap_write(priv->regmap, STM32MP_PWR_CR3, val);
}
static int stm32mp_pwr_read(struct udevice *dev, uint reg, uint8_t *buff,
int len)
{
struct stm32mp_pwr_priv *priv = dev_get_priv(dev);
if (len != 4)
return -EINVAL;
return regmap_read(priv->regmap, STM32MP_PWR_CR3, (u32 *)buff);
}
static int stm32mp_pwr_ofdata_to_platdata(struct udevice *dev)
{
struct stm32mp_pwr_priv *priv = dev_get_priv(dev);
struct regmap *regmap;
regmap = syscon_get_regmap_by_driver_data(STM32MP_SYSCON_PWR);
if (IS_ERR(regmap)) {
pr_err("%s: unable to find regmap (%ld)\n", __func__,
PTR_ERR(regmap));
return PTR_ERR(regmap);
}
priv->regmap = regmap;
return 0;
}
static const struct pmic_child_info pwr_children_info[] = {
{ .prefix = "reg", .driver = "stm32mp_pwr_regulator"},
{ .prefix = "usb", .driver = "stm32mp_pwr_regulator"},
{ },
};
static int stm32mp_pwr_bind(struct udevice *dev)
{
int children;
children = pmic_bind_children(dev, dev->node, pwr_children_info);
if (!children)
dev_dbg(dev, "no child found\n");
return 0;
}
static struct dm_pmic_ops stm32mp_pwr_ops = {
.read = stm32mp_pwr_read,
.write = stm32mp_pwr_write,
};
static const struct udevice_id stm32mp_pwr_ids[] = {
{ .compatible = "st,stm32mp1,pwr-reg" },
{ }
};
U_BOOT_DRIVER(stm32mp_pwr_pmic) = {
.name = "stm32mp_pwr_pmic",
.id = UCLASS_PMIC,
.of_match = stm32mp_pwr_ids,
.bind = stm32mp_pwr_bind,
.ops = &stm32mp_pwr_ops,
.ofdata_to_platdata = stm32mp_pwr_ofdata_to_platdata,
.priv_auto_alloc_size = sizeof(struct stm32mp_pwr_priv),
};
static const struct stm32mp_pwr_reg_info stm32mp_pwr_reg11 = {
.enable = STM32MP_PWR_CR3_REG11DEN,
.ready = STM32MP_PWR_CR3_REG11RDY,
.name = "reg11"
};
static const struct stm32mp_pwr_reg_info stm32mp_pwr_reg18 = {
.enable = STM32MP_PWR_CR3_REG18DEN,
.ready = STM32MP_PWR_CR3_REG18RDY,
.name = "reg18"
};
static const struct stm32mp_pwr_reg_info stm32mp_pwr_usb33 = {
.enable = STM32MP_PWR_CR3_USB33DEN,
.ready = STM32MP_PWR_CR3_USB33RDY,
.name = "usb33"
};
static const struct stm32mp_pwr_reg_info *stm32mp_pwr_reg_infos[] = {
&stm32mp_pwr_reg11,
&stm32mp_pwr_reg18,
&stm32mp_pwr_usb33,
NULL
};
static int stm32mp_pwr_regulator_probe(struct udevice *dev)
{
const struct stm32mp_pwr_reg_info **p = stm32mp_pwr_reg_infos;
struct dm_regulator_uclass_platdata *uc_pdata;
uc_pdata = dev_get_uclass_platdata(dev);
while (*p) {
int rc;
rc = dev_read_stringlist_search(dev, "regulator-name",
(*p)->name);
if (rc >= 0) {
dev_dbg(dev, "found regulator %s\n", (*p)->name);
break;
} else if (rc != -ENODATA) {
return rc;
}
p++;
}
if (!*p) {
int i = 0;
const char *s;
dev_dbg(dev, "regulator ");
while (dev_read_string_index(dev, "regulator-name",
i++, &s) >= 0)
dev_dbg(dev, "%s'%s' ", (i > 1) ? ", " : "", s);
dev_dbg(dev, "%s not supported\n", (i > 2) ? "are" : "is");
return -EINVAL;
}
uc_pdata->type = REGULATOR_TYPE_FIXED;
dev->priv = (void *)*p;
return 0;
}
static int stm32mp_pwr_regulator_set_value(struct udevice *dev, int uV)
{
struct dm_regulator_uclass_platdata *uc_pdata;
uc_pdata = dev_get_uclass_platdata(dev);
if (!uc_pdata)
return -ENXIO;
if (uc_pdata->min_uV != uV) {
dev_dbg(dev, "Invalid uV=%d for: %s\n", uV, uc_pdata->name);
return -EINVAL;
}
return 0;
}
static int stm32mp_pwr_regulator_get_value(struct udevice *dev)
{
struct dm_regulator_uclass_platdata *uc_pdata;
uc_pdata = dev_get_uclass_platdata(dev);
if (!uc_pdata)
return -ENXIO;
if (uc_pdata->min_uV != uc_pdata->max_uV) {
dev_dbg(dev, "Invalid constraints for: %s\n", uc_pdata->name);
return -EINVAL;
}
return uc_pdata->min_uV;
}
static int stm32mp_pwr_regulator_get_enable(struct udevice *dev)
{
const struct stm32mp_pwr_reg_info *p = dev_get_priv(dev);
int rc;
u32 reg;
rc = pmic_read(dev->parent, 0, (uint8_t *)&reg, sizeof(reg));
if (rc)
return rc;
dev_dbg(dev, "%s id %s\n", p->name, (reg & p->enable) ? "on" : "off");
return (reg & p->enable) != 0;
}
static int stm32mp_pwr_regulator_set_enable(struct udevice *dev, bool enable)
{
const struct stm32mp_pwr_reg_info *p = dev_get_priv(dev);
int rc;
u32 reg;
u32 time_start;
dev_dbg(dev, "Turning %s %s\n", enable ? "on" : "off", p->name);
rc = pmic_read(dev->parent, 0, (uint8_t *)&reg, sizeof(reg));
if (rc)
return rc;
/* if regulator is already in the wanted state, nothing to do */
if (!!(reg & p->enable) == enable)
return 0;
reg &= ~p->enable;
if (enable)
reg |= p->enable;
rc = pmic_write(dev->parent, 0, (uint8_t *)&reg, sizeof(reg));
if (rc)
return rc;
if (!enable)
return 0;
/* waiting ready for enable */
time_start = get_timer(0);
while (1) {
rc = pmic_read(dev->parent, 0, (uint8_t *)&reg, sizeof(reg));
if (rc)
return rc;
if (reg & p->ready)
break;
if (get_timer(time_start) > CONFIG_SYS_HZ) {
dev_dbg(dev, "%s: timeout\n", p->name);
return -ETIMEDOUT;
}
}
return 0;
}
static const struct dm_regulator_ops stm32mp_pwr_regulator_ops = {
.set_value = stm32mp_pwr_regulator_set_value,
.get_value = stm32mp_pwr_regulator_get_value,
.get_enable = stm32mp_pwr_regulator_get_enable,
.set_enable = stm32mp_pwr_regulator_set_enable,
};
U_BOOT_DRIVER(stm32mp_pwr_regulator) = {
.name = "stm32mp_pwr_regulator",
.id = UCLASS_REGULATOR,
.ops = &stm32mp_pwr_regulator_ops,
.probe = stm32mp_pwr_regulator_probe,
};
@@ -0,0 +1,117 @@
// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
/*
* Copyright (C) 2018, STMicroelectronics - All Rights Reserved
*/
#include <common.h>
#include <dm.h>
#include <spl.h>
#include <asm/io.h>
#include <asm/arch/sys_proto.h>
#include <linux/libfdt.h>
u32 spl_boot_device(void)
{
u32 boot_mode;
boot_mode = get_bootmode();
switch (boot_mode) {
case BOOT_FLASH_SD_1:
case BOOT_FLASH_EMMC_1:
return BOOT_DEVICE_MMC1;
case BOOT_FLASH_SD_2:
case BOOT_FLASH_EMMC_2:
return BOOT_DEVICE_MMC2;
case BOOT_SERIAL_UART_1:
case BOOT_SERIAL_UART_2:
case BOOT_SERIAL_UART_3:
case BOOT_SERIAL_UART_4:
case BOOT_SERIAL_UART_5:
case BOOT_SERIAL_UART_6:
case BOOT_SERIAL_UART_7:
case BOOT_SERIAL_UART_8:
return BOOT_DEVICE_UART;
case BOOT_SERIAL_USB_OTG:
return BOOT_DEVICE_USB;
case BOOT_FLASH_NAND_FMC:
return BOOT_DEVICE_NAND;
case BOOT_FLASH_NOR_QSPI:
return BOOT_DEVICE_SPI;
}
return BOOT_DEVICE_MMC1;
}
u32 spl_boot_mode(const u32 boot_device)
{
return MMCSD_MODE_RAW;
}
int spl_boot_partition(const u32 boot_device)
{
switch (boot_device) {
case BOOT_DEVICE_MMC1:
return CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION;
case BOOT_DEVICE_MMC2:
return CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_PARTITION_MMC2;
default:
return -EINVAL;
}
}
#ifdef CONFIG_SPL_DISPLAY_PRINT
void spl_display_print(void)
{
DECLARE_GLOBAL_DATA_PTR;
const char *model;
/* same code than show_board_info() but not compiled for SPL
* see CONFIG_DISPLAY_BOARDINFO & common/board_info.c
*/
model = fdt_getprop(gd->fdt_blob, 0, "model", NULL);
if (model)
printf("Model: %s\n", model);
}
#endif
void board_init_f(ulong dummy)
{
struct udevice *dev;
int ret;
arch_cpu_init();
ret = spl_early_init();
if (ret) {
debug("spl_early_init() failed: %d\n", ret);
hang();
}
ret = uclass_get_device(UCLASS_CLK, 0, &dev);
if (ret) {
debug("Clock init failed: %d\n", ret);
return;
}
ret = uclass_get_device(UCLASS_RESET, 0, &dev);
if (ret) {
debug("Reset init failed: %d\n", ret);
return;
}
ret = uclass_get_device(UCLASS_PINCTRL, 0, &dev);
if (ret) {
debug("%s: Cannot find pinctrl device\n", __func__);
return;
}
/* enable console uart printing */
preloader_console_init();
ret = uclass_get_device(UCLASS_RAM, 0, &dev);
if (ret) {
printf("DRAM init failed: %d\n", ret);
hang();
}
}
@@ -0,0 +1,23 @@
// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
/*
* Copyright (C) 2018, STMicroelectronics - All Rights Reserved
*/
#include <common.h>
#include <dm.h>
#include <syscon.h>
#include <asm/arch/stm32.h>
static const struct udevice_id stm32mp_syscon_ids[] = {
{ .compatible = "st,stm32mp1-pwr", .data = STM32MP_SYSCON_PWR },
{ .compatible = "st,stm32mp157-syscfg",
.data = STM32MP_SYSCON_SYSCFG },
{ }
};
U_BOOT_DRIVER(syscon_stm32mp) = {
.name = "stmp32mp_syscon",
.id = UCLASS_SYSCON,
.of_match = stm32mp_syscon_ids,
.bind = dm_scan_fdt_dev,
};