提交 0d4823fb 编写于 作者: T Tom Rini

Merge tag 'u-boot-stm32-20210727' of https://source.denx.de/u-boot/custodians/u-boot-stm

- FIP Enable OP-TEE and TZC support in SPL for STM32MP15 SoC
- Add stm32mp15 missing SPI clock support
- Manage pull-up on gpio button STM32MP15 boards
- Correct STM32MP15 boot when TAMPER registers are invalid
- Fix EMMC pinmux on STM32MP15 Avenger96 board
......@@ -17,8 +17,8 @@
u-boot,error-led = "error";
u-boot,mmc-env-partition = "ssbl";
st,adc_usb_pd = <&adc1 18>, <&adc1 19>;
st,fastboot-gpios = <&gpioa 13 GPIO_ACTIVE_LOW>;
st,stm32prog-gpios = <&gpioa 14 GPIO_ACTIVE_LOW>;
st,fastboot-gpios = <&gpioa 13 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
st,stm32prog-gpios = <&gpioa 14 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
};
firmware {
......@@ -29,9 +29,12 @@
};
reserved-memory {
u-boot,dm-spl;
optee@de000000 {
reg = <0xde000000 0x02000000>;
no-map;
u-boot,dm-spl;
};
};
......
......@@ -16,8 +16,8 @@
u-boot,boot-led = "heartbeat";
u-boot,error-led = "error";
u-boot,mmc-env-partition = "ssbl";
st,fastboot-gpios = <&gpioa 13 GPIO_ACTIVE_LOW>;
st,stm32prog-gpios = <&gpioa 14 GPIO_ACTIVE_LOW>;
st,fastboot-gpios = <&gpioa 13 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
st,stm32prog-gpios = <&gpioa 14 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
};
firmware {
......
......@@ -57,7 +57,7 @@
};
};
&sdmmc2_d47_pins_b {
&sdmmc2_d47_pins_c {
u-boot,dm-spl;
pins {
u-boot,dm-spl;
......
......@@ -152,7 +152,7 @@
&sdmmc2 {
pinctrl-names = "default";
pinctrl-0 = <&sdmmc2_b4_pins_a &sdmmc2_d47_pins_b>;
pinctrl-0 = <&sdmmc2_b4_pins_a &sdmmc2_d47_pins_c>;
non-removable;
no-sd;
no-sdio;
......
......@@ -10,6 +10,7 @@ obj-y += bsec.o
ifdef CONFIG_SPL_BUILD
obj-y += spl.o
obj-y += tzc400.o
else
obj-y += cmd_stm32prog/
obj-$(CONFIG_CMD_STM32KEY) += cmd_stm32key.o
......
......@@ -556,7 +556,9 @@ static void setup_boot_mode(void)
env_set("boot_instance", "0");
break;
default:
log_debug("unexpected boot mode = %x\n", boot_mode);
env_set("boot_device", "invalid");
env_set("boot_instance", "");
log_err("unexpected boot mode = %x\n", boot_mode);
break;
}
......
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Simple API for configuring TrustZone memory regions
*
* The premise is that the desired TZC layout is known beforehand, and it can
* be configured in one step. tzc_configure() provides this functionality.
*/
#ifndef MACH_TZC_H
#define MACH_TZC_H
#include <linux/types.h>
enum tzc_sec_mode {
TZC_ATTR_SEC_NONE = 0,
TZC_ATTR_SEC_R = 1,
TZC_ATTR_SEC_W = 2,
TZC_ATTR_SEC_RW = 3
};
struct tzc_region {
uintptr_t base;
uintptr_t top;
enum tzc_sec_mode sec_mode;
uint16_t nsec_id;
uint16_t filters_mask;
};
int tzc_configure(uintptr_t tzc, const struct tzc_region *cfg);
int tzc_disable_filters(uintptr_t tzc, uint16_t filters_mask);
int tzc_enable_filters(uintptr_t tzc, uint16_t filters_mask);
void tzc_dump_config(uintptr_t tzc);
#endif /* MACH_TZC_H */
......@@ -11,11 +11,13 @@
#include <hang.h>
#include <init.h>
#include <log.h>
#include <ram.h>
#include <spl.h>
#include <asm/cache.h>
#include <asm/global_data.h>
#include <asm/io.h>
#include <asm/arch/sys_proto.h>
#include <mach/tzc.h>
#include <linux/libfdt.h>
u32 spl_boot_device(void)
......@@ -92,6 +94,96 @@ __weak int board_early_init_f(void)
return 0;
}
uint32_t stm32mp_get_dram_size(void)
{
struct ram_info ram;
struct udevice *dev;
int ret;
if (uclass_get_device(UCLASS_RAM, 0, &dev))
return 0;
ret = ram_get_info(dev, &ram);
if (ret)
return 0;
return ram.size;
}
static int optee_get_reserved_memory(uint32_t *start, uint32_t *size)
{
phys_size_t fdt_mem_size;
fdt_addr_t fdt_start;
ofnode node;
node = ofnode_path("/reserved-memory/optee");
if (!ofnode_valid(node))
return 0;
fdt_start = ofnode_get_addr_size(node, "reg", &fdt_mem_size);
*start = fdt_start;
*size = fdt_mem_size;
return (fdt_start < 0) ? fdt_start : 0;
}
#define CFG_SHMEM_SIZE 0x200000
#define STM32_TZC_NSID_ALL 0xffff
#define STM32_TZC_FILTER_ALL 3
void stm32_init_tzc_for_optee(void)
{
const uint32_t dram_size = stm32mp_get_dram_size();
const uintptr_t dram_top = STM32_DDR_BASE + (dram_size - 1);
uint32_t optee_base, optee_size, tee_shmem_base;
const uintptr_t tzc = STM32_TZC_BASE;
int ret;
if (dram_size == 0)
panic("Cannot determine DRAM size from devicetree\n");
ret = optee_get_reserved_memory(&optee_base, &optee_size);
if (ret < 0 || optee_size <= CFG_SHMEM_SIZE)
panic("Invalid OPTEE reserved memory in devicetree\n");
tee_shmem_base = optee_base + optee_size - CFG_SHMEM_SIZE;
const struct tzc_region optee_config[] = {
{
.base = STM32_DDR_BASE,
.top = optee_base - 1,
.sec_mode = TZC_ATTR_SEC_NONE,
.nsec_id = STM32_TZC_NSID_ALL,
.filters_mask = STM32_TZC_FILTER_ALL,
}, {
.base = optee_base,
.top = tee_shmem_base - 1,
.sec_mode = TZC_ATTR_SEC_RW,
.nsec_id = 0,
.filters_mask = STM32_TZC_FILTER_ALL,
}, {
.base = tee_shmem_base,
.top = dram_top,
.sec_mode = TZC_ATTR_SEC_NONE,
.nsec_id = STM32_TZC_NSID_ALL,
.filters_mask = STM32_TZC_FILTER_ALL,
}, {
.top = 0,
}
};
flush_dcache_all();
tzc_configure(tzc, optee_config);
tzc_dump_config(tzc);
dcache_disable();
}
void spl_board_prepare_for_optee(void *fdt)
{
stm32_init_tzc_for_optee();
}
void board_init_f(ulong dummy)
{
struct udevice *dev;
......
// SPDX-License-Identifier: GPL-2.0+
/*
* Simple API for configuring TrustZone memory restrictions for TZC400
*/
#define LOG_CATEGORY LOGC_ARCH
#include <linux/iopoll.h>
#include <mach/tzc.h>
#define TZC_TIMEOUT_US 100
#define TZC_BUILD_CONFIG 0x00
#define TZC_ACTION 0x04
#define TZC_ACTION_NONE 0
#define TZC_ACTION_ERR 1
#define TZC_ACTION_INT 2
#define TZC_ACTION_INT_ERR 3
#define TZC_GATE_KEEPER 0x08
#define TZC_REGION0_OFFSET 0x100
#define TZC_REGION_CFG_SIZE 0x20
#define TZC_REGION1_OFFSET 0x120
#define TZC_REGION_BASE 0x00
#define TZC_REGION_TOP 0x08
#define TZC_REGION_ATTRIBUTE 0x10
#define TZC_REGION_ACCESS 0x14
static uint32_t tzc_read(uintptr_t tzc, size_t reg)
{
return readl(tzc + reg);
}
static void tzc_write(uintptr_t tzc, size_t reg, uint32_t val)
{
writel(val, tzc + reg);
}
static uint16_t tzc_config_get_active_filters(const struct tzc_region *cfg)
{
uint16_t active_filters = 0;
for ( ; cfg->top != 0; cfg++)
active_filters |= cfg->filters_mask;
return active_filters;
}
int tzc_configure(uintptr_t tzc, const struct tzc_region *cfg)
{
uintptr_t region = tzc + TZC_REGION1_OFFSET;
uint32_t nsid, attr_reg, active_filters;
int ret;
active_filters = tzc_config_get_active_filters(cfg);
if (active_filters == 0)
return -EINVAL;
ret = tzc_disable_filters(tzc, active_filters);
if (ret < 0)
return ret;
for ( ; cfg->top != 0; cfg++, region += TZC_REGION_CFG_SIZE) {
attr_reg = (cfg->sec_mode & 0x03) << 30;
attr_reg |= (cfg->filters_mask & 0x03) << 0;
nsid = cfg->nsec_id & 0xffff;
nsid |= nsid << 16;
tzc_write(region, TZC_REGION_BASE, cfg->base);
tzc_write(region, TZC_REGION_TOP, cfg->top);
tzc_write(region, TZC_REGION_ACCESS, nsid);
tzc_write(region, TZC_REGION_ATTRIBUTE, attr_reg);
}
tzc_write(tzc, TZC_ACTION, TZC_ACTION_ERR);
return tzc_enable_filters(tzc, active_filters);
}
int tzc_disable_filters(uintptr_t tzc, uint16_t filters_mask)
{
uint32_t gate = tzc_read(tzc, TZC_GATE_KEEPER);
uint32_t filter_status = filters_mask << 16;
gate &= ~filters_mask;
tzc_write(tzc, TZC_GATE_KEEPER, gate);
return readl_poll_timeout(tzc + TZC_GATE_KEEPER, gate,
(gate & filter_status) == 0, TZC_TIMEOUT_US);
}
int tzc_enable_filters(uintptr_t tzc, uint16_t filters_mask)
{
uint32_t gate = tzc_read(tzc, TZC_GATE_KEEPER);
uint32_t filter_status = filters_mask << 16;
gate |= filters_mask;
tzc_write(tzc, TZC_GATE_KEEPER, gate);
return readl_poll_timeout(tzc + TZC_GATE_KEEPER, gate,
(gate & filter_status) == filter_status,
TZC_TIMEOUT_US);
}
static const char *sec_access_str_from_attr(uint32_t attr)
{
const char *const sec_mode[] = { "none", "RO ", "WO ", "RW " };
return sec_mode[(attr >> 30) & 0x03];
}
void tzc_dump_config(uintptr_t tzc)
{
uint32_t build_config, base, top, attr, nsaid;
int num_regions, i;
uintptr_t region;
build_config = tzc_read(tzc, TZC_BUILD_CONFIG);
num_regions = ((build_config >> 0) & 0x1f) + 1;
for (i = 0; i < num_regions; i++) {
region = tzc + TZC_REGION0_OFFSET + i * TZC_REGION_CFG_SIZE;
base = tzc_read(region, TZC_REGION_BASE);
top = tzc_read(region, TZC_REGION_TOP);
attr = tzc_read(region, TZC_REGION_ATTRIBUTE);
nsaid = tzc_read(region, TZC_REGION_ACCESS);
if (attr == 0 && nsaid == 0)
continue;
log_info("TZC region %u: %08x->%08x - filters 0x%x\n",
i, base, top, (attr >> 0) & 0xf);
log_info("\t Secure access %s NSAID %08x\n",
sec_access_str_from_attr(attr), nsaid);
}
}
......@@ -155,6 +155,7 @@ static void board_key_check(void)
&gpio, GPIOD_IS_IN)) {
log_debug("could not find a /config/st,fastboot-gpios\n");
} else {
udelay(20);
if (dm_gpio_get_value(&gpio)) {
log_notice("Fastboot key pressed, ");
boot_mode = BOOT_FASTBOOT;
......@@ -168,6 +169,7 @@ static void board_key_check(void)
&gpio, GPIOD_IS_IN)) {
log_debug("could not find a /config/st,stm32prog-gpios\n");
} else {
udelay(20);
if (dm_gpio_get_value(&gpio)) {
log_notice("STM32Programmer key pressed, ");
boot_mode = BOOT_STM32PROG;
......
......@@ -167,6 +167,10 @@ __weak void spl_board_prepare_for_linux(void)
/* Nothing to do! */
}
__weak void spl_board_prepare_for_optee(void *fdt)
{
}
__weak void spl_board_prepare_for_boot(void)
{
/* Nothing to do! */
......@@ -763,6 +767,7 @@ void board_init_r(gd_t *dummy1, ulong dummy2)
#if CONFIG_IS_ENABLED(OPTEE)
case IH_OS_TEE:
debug("Jumping to U-Boot via OP-TEE\n");
spl_board_prepare_for_optee(spl_image.fdt_addr);
spl_optee_entry(NULL, NULL, spl_image.fdt_addr,
(void *)spl_image.entry_point);
break;
......
......@@ -230,8 +230,8 @@ static int mmc_load_image_raw_os(struct spl_image_info *spl_image,
if (ret)
return ret;
if (spl_image->os != IH_OS_LINUX) {
puts("Expected Linux image is not found. Trying to start U-boot\n");
if (spl_image->os != IH_OS_LINUX && spl_image->os != IH_OS_TEE) {
puts("Expected image is not found. Trying to start U-boot\n");
return -ENOENT;
}
......
......@@ -73,6 +73,7 @@ DECLARE_GLOBAL_DATA_PTR;
#define RCC_PLL2FRACR 0xA0
#define RCC_PLL2CSGR 0xA4
#define RCC_I2C46CKSELR 0xC0
#define RCC_SPI6CKSELR 0xC4
#define RCC_CPERCKSELR 0xD0
#define RCC_STGENCKSELR 0xD4
#define RCC_DDRITFCR 0xD8
......@@ -103,6 +104,7 @@ DECLARE_GLOBAL_DATA_PTR;
#define RCC_I2C12CKSELR 0x8C0
#define RCC_I2C35CKSELR 0x8C4
#define RCC_SPI2S1CKSELR 0x8D8
#define RCC_SPI2S23CKSELR 0x8DC
#define RCC_SPI45CKSELR 0x8E0
#define RCC_UART6CKSELR 0x8E4
#define RCC_UART24CKSELR 0x8E8
......@@ -313,7 +315,9 @@ enum stm32mp1_parent_sel {
_DSI_SEL,
_ADC12_SEL,
_SPI1_SEL,
_SPI23_SEL,
_SPI45_SEL,
_SPI6_SEL,
_RTC_SEL,
_PARENT_SEL_NB,
_UNKNOWN_SEL = 0xff,
......@@ -524,6 +528,8 @@ static const struct stm32mp1_clk_gate stm32mp1_clk_gate[] = {
STM32MP1_CLK(RCC_DDRITFCR, 9, DDRPHYCAPB, _UNKNOWN_SEL),
STM32MP1_CLK(RCC_DDRITFCR, 10, DDRPHYCAPBLP, _UNKNOWN_SEL),
STM32MP1_CLK_SET_CLR(RCC_MP_APB1ENSETR, 11, SPI2_K, _SPI23_SEL),
STM32MP1_CLK_SET_CLR(RCC_MP_APB1ENSETR, 12, SPI3_K, _SPI23_SEL),
STM32MP1_CLK_SET_CLR(RCC_MP_APB1ENSETR, 14, USART2_K, _UART24_SEL),
STM32MP1_CLK_SET_CLR(RCC_MP_APB1ENSETR, 15, USART3_K, _UART35_SEL),
STM32MP1_CLK_SET_CLR(RCC_MP_APB1ENSETR, 16, UART4_K, _UART24_SEL),
......@@ -536,6 +542,7 @@ static const struct stm32mp1_clk_gate stm32mp1_clk_gate[] = {
STM32MP1_CLK_SET_CLR(RCC_MP_APB1ENSETR, 24, I2C5_K, _I2C35_SEL),
STM32MP1_CLK_SET_CLR(RCC_MP_APB2ENSETR, 8, SPI1_K, _SPI1_SEL),
STM32MP1_CLK_SET_CLR(RCC_MP_APB2ENSETR, 9, SPI4_K, _SPI45_SEL),
STM32MP1_CLK_SET_CLR(RCC_MP_APB2ENSETR, 10, SPI5_K, _SPI45_SEL),
STM32MP1_CLK_SET_CLR(RCC_MP_APB2ENSETR, 13, USART6_K, _UART6_SEL),
......@@ -549,6 +556,7 @@ static const struct stm32mp1_clk_gate stm32mp1_clk_gate[] = {
STM32MP1_CLK_SET_CLR(RCC_MP_APB4ENSETR, 15, IWDG2, _UNKNOWN_SEL),
STM32MP1_CLK_SET_CLR(RCC_MP_APB4ENSETR, 16, USBPHY_K, _USBPHY_SEL),
STM32MP1_CLK_SET_CLR(RCC_MP_APB5ENSETR, 0, SPI6_K, _SPI6_SEL),
STM32MP1_CLK_SET_CLR(RCC_MP_APB5ENSETR, 2, I2C4_K, _I2C46_SEL),
STM32MP1_CLK_SET_CLR(RCC_MP_APB5ENSETR, 3, I2C6_K, _I2C46_SEL),
STM32MP1_CLK_SET_CLR(RCC_MP_APB5ENSETR, 8, RTCAPB, _PCLK5),
......@@ -613,10 +621,13 @@ static const u8 usbo_parents[] = {_PLL4_R, _USB_PHY_48};
static const u8 stgen_parents[] = {_HSI_KER, _HSE_KER};
static const u8 dsi_parents[] = {_DSI_PHY, _PLL4_P};
static const u8 adc_parents[] = {_PLL4_R, _CK_PER, _PLL3_Q};
/* same parents for SPI1=RCC_SPI2S1CKSELR and SPI2&3 = RCC_SPI2S23CKSELR */
static const u8 spi_parents[] = {_PLL4_P, _PLL3_Q, _I2S_CKIN, _CK_PER,
_PLL3_R};
static const u8 spi45_parents[] = {_PCLK2, _PLL4_Q, _HSI_KER, _CSI_KER,
_HSE_KER};
static const u8 spi6_parents[] = {_PCLK5, _PLL4_Q, _HSI_KER, _CSI_KER,
_HSE_KER, _PLL3_Q};
static const u8 rtc_parents[] = {_UNKNOWN_ID, _LSE, _LSI, _HSE};
static const struct stm32mp1_clk_sel stm32mp1_clk_sel[_PARENT_SEL_NB] = {
......@@ -643,7 +654,9 @@ static const struct stm32mp1_clk_sel stm32mp1_clk_sel[_PARENT_SEL_NB] = {
STM32MP1_CLK_PARENT(_DSI_SEL, RCC_DSICKSELR, 0, 0x1, dsi_parents),
STM32MP1_CLK_PARENT(_ADC12_SEL, RCC_ADCCKSELR, 0, 0x3, adc_parents),
STM32MP1_CLK_PARENT(_SPI1_SEL, RCC_SPI2S1CKSELR, 0, 0x7, spi_parents),
STM32MP1_CLK_PARENT(_SPI23_SEL, RCC_SPI2S23CKSELR, 0, 0x7, spi_parents),
STM32MP1_CLK_PARENT(_SPI45_SEL, RCC_SPI45CKSELR, 0, 0x7, spi45_parents),
STM32MP1_CLK_PARENT(_SPI6_SEL, RCC_SPI6CKSELR, 0, 0x7, spi6_parents),
STM32MP1_CLK_PARENT(_RTC_SEL, RCC_BDCR, RCC_BDCR_RTCSRC_SHIFT,
(RCC_BDCR_RTCSRC_MASK >> RCC_BDCR_RTCSRC_SHIFT),
rtc_parents),
......
......@@ -432,6 +432,20 @@ int spl_parse_image_header(struct spl_image_info *spl_image,
const struct image_header *header);
void spl_board_prepare_for_linux(void);
/**
* spl_board_prepare_for_optee() - Prepare board for an OPTEE payload
*
* Prepares the board for booting an OP-TEE payload. Initialization is platform
* specific, and may include configuring the TrustZone memory, and other
* initialization steps required by OP-TEE.
* Note that @fdt is not used directly by OP-TEE. OP-TEE passes this @fdt to
* its normal world target. This target is not guaranteed to be u-boot, so @fdt
* changes that would normally be done by u-boot should be done in this step.
*
* @fdt: Devicetree that will be passed on, or NULL
*/
void spl_board_prepare_for_optee(void *fdt);
void spl_board_prepare_for_boot(void);
int spl_board_ubi_load_image(u32 boot_device);
int spl_board_boot_device(u32 boot_device);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册