summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorSoby Mathew <soby.mathew@arm.com>2019-09-10 14:32:59 +0000
committerTrustedFirmware Code Review <review@review.trustedfirmware.org>2019-09-10 14:32:59 +0000
commit0289ab9eb8476808f50e6b858079acc65f6cd2e6 (patch)
treeb231929a14cf4064b0e5317b6817b72e4af2354a /drivers
parent5dbdf8e4eac1d5999f07976f9f430894b0784907 (diff)
parentd9d803e0be7af7785d8ea72e79b2926db581bb65 (diff)
Merge changes from topic "yg/stm32mp1_wdg_updates" into integration
* changes: mmc: stm32_sdmmc2: correctly manage block size mmc: stm32_sdmmc2: manage max-frequency property from DT stm32mp1: move check_header() to common code stm32mp1: keep console during runtime stm32mp1: sp_min: initialize MMU and cache earlier stm32mp1: add support for LpDDR3 stm32mp1: use a common function to check spinlock is available clk: stm32mp: enable RTCAPB clock for dual-core chips stm32mp1: check if the SoC is single core stm32mp1: print information about board stm32mp1: print information about SoC stm32mp1: add watchdog support
Diffstat (limited to 'drivers')
-rw-r--r--drivers/st/bsec/bsec.c10
-rw-r--r--drivers/st/clk/stm32mp1_clk.c29
-rw-r--r--drivers/st/ddr/stm32mp1_ddr.c2
-rw-r--r--drivers/st/io/io_stm32image.c36
-rw-r--r--drivers/st/iwdg/stm32_iwdg.c150
-rw-r--r--drivers/st/mmc/stm32_sdmmc2.c49
-rw-r--r--drivers/st/pmic/stm32mp_pmic.c1
7 files changed, 199 insertions, 78 deletions
diff --git a/drivers/st/bsec/bsec.c b/drivers/st/bsec/bsec.c
index aaecf1f8..b3c15ee8 100644
--- a/drivers/st/bsec/bsec.c
+++ b/drivers/st/bsec/bsec.c
@@ -32,20 +32,14 @@ static uintptr_t bsec_base;
static void bsec_lock(void)
{
- const uint32_t mask = SCTLR_M_BIT | SCTLR_C_BIT;
-
- /* Lock is currently required only when MMU and cache are enabled */
- if ((read_sctlr() & mask) == mask) {
+ if (stm32mp_lock_available()) {
spin_lock(&bsec_spinlock);
}
}
static void bsec_unlock(void)
{
- const uint32_t mask = SCTLR_M_BIT | SCTLR_C_BIT;
-
- /* Unlock is required only when MMU and cache are enabled */
- if ((read_sctlr() & mask) == mask) {
+ if (stm32mp_lock_available()) {
spin_unlock(&bsec_spinlock);
}
}
diff --git a/drivers/st/clk/stm32mp1_clk.c b/drivers/st/clk/stm32mp1_clk.c
index 76e6e6fd..0cc87cc7 100644
--- a/drivers/st/clk/stm32mp1_clk.c
+++ b/drivers/st/clk/stm32mp1_clk.c
@@ -541,29 +541,19 @@ static const struct stm32mp1_clk_pll *pll_ref(unsigned int idx)
return &stm32mp1_clk_pll[idx];
}
-static int stm32mp1_lock_available(void)
-{
- /* The spinlocks are used only when MMU is enabled */
- return (read_sctlr() & SCTLR_M_BIT) && (read_sctlr() & SCTLR_C_BIT);
-}
-
static void stm32mp1_clk_lock(struct spinlock *lock)
{
- if (stm32mp1_lock_available() == 0U) {
- return;
+ if (stm32mp_lock_available()) {
+ /* Assume interrupts are masked */
+ spin_lock(lock);
}
-
- /* Assume interrupts are masked */
- spin_lock(lock);
}
static void stm32mp1_clk_unlock(struct spinlock *lock)
{
- if (stm32mp1_lock_available() == 0U) {
- return;
+ if (stm32mp_lock_available()) {
+ spin_unlock(lock);
}
-
- spin_unlock(lock);
}
bool stm32mp1_rcc_is_secure(void)
@@ -1912,9 +1902,18 @@ static void stm32mp1_osc_init(void)
}
}
+static void sync_earlyboot_clocks_state(void)
+{
+ if (!stm32mp_is_single_core()) {
+ stm32mp1_clk_enable_secure(RTCAPB);
+ }
+}
+
int stm32mp1_clk_probe(void)
{
stm32mp1_osc_init();
+ sync_earlyboot_clocks_state();
+
return 0;
}
diff --git a/drivers/st/ddr/stm32mp1_ddr.c b/drivers/st/ddr/stm32mp1_ddr.c
index caf8eefa..7d89d027 100644
--- a/drivers/st/ddr/stm32mp1_ddr.c
+++ b/drivers/st/ddr/stm32mp1_ddr.c
@@ -717,6 +717,8 @@ void stm32mp1_ddr_init(struct ddr_info *priv,
ret = board_ddr_power_init(STM32MP_DDR3);
} else if ((config->c_reg.mstr & DDRCTRL_MSTR_LPDDR2) != 0U) {
ret = board_ddr_power_init(STM32MP_LPDDR2);
+ } else if ((config->c_reg.mstr & DDRCTRL_MSTR_LPDDR3) != 0U) {
+ ret = board_ddr_power_init(STM32MP_LPDDR3);
} else {
ERROR("DDR type not supported\n");
}
diff --git a/drivers/st/io/io_stm32image.c b/drivers/st/io/io_stm32image.c
index dc2977d5..971dcce5 100644
--- a/drivers/st/io/io_stm32image.c
+++ b/drivers/st/io/io_stm32image.c
@@ -242,40 +242,6 @@ static int stm32image_partition_size(io_entity_t *entity, size_t *length)
return 0;
}
-static int check_header(boot_api_image_header_t *header, uintptr_t buffer)
-{
- uint32_t i;
- uint32_t img_checksum = 0;
-
- /*
- * Check header/payload validity:
- * - Header magic
- * - Header version
- * - Payload checksum
- */
- if (header->magic != BOOT_API_IMAGE_HEADER_MAGIC_NB) {
- ERROR("Header magic\n");
- return -EINVAL;
- }
-
- if (header->header_version != BOOT_API_HEADER_VERSION) {
- ERROR("Header version\n");
- return -EINVAL;
- }
-
- for (i = 0; i < header->image_length; i++) {
- img_checksum += *(uint8_t *)(buffer + i);
- }
-
- if (header->payload_checksum != img_checksum) {
- ERROR("Checksum: 0x%x (awaited: 0x%x)\n", img_checksum,
- header->payload_checksum);
- return -EINVAL;
- }
-
- return 0;
-}
-
/* Read data from a partition */
static int stm32image_partition_read(io_entity_t *entity, uintptr_t buffer,
size_t length, size_t *length_read)
@@ -368,7 +334,7 @@ static int stm32image_partition_read(io_entity_t *entity, uintptr_t buffer,
continue;
}
- result = check_header(header, buffer);
+ result = stm32mp_check_header(header, buffer);
if (result != 0) {
ERROR("Header check failed\n");
*length_read = 0;
diff --git a/drivers/st/iwdg/stm32_iwdg.c b/drivers/st/iwdg/stm32_iwdg.c
new file mode 100644
index 00000000..ea6fbb2b
--- /dev/null
+++ b/drivers/st/iwdg/stm32_iwdg.c
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+
+#include <libfdt.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/arm/gicv2.h>
+#include <drivers/delay_timer.h>
+#include <drivers/st/stm32_iwdg.h>
+#include <drivers/st/stm32mp_clkfunc.h>
+#include <lib/mmio.h>
+#include <lib/utils.h>
+#include <plat/common/platform.h>
+
+/* IWDG registers offsets */
+#define IWDG_KR_OFFSET 0x00U
+
+/* Registers values */
+#define IWDG_KR_RELOAD_KEY 0xAAAA
+
+struct stm32_iwdg_instance {
+ uintptr_t base;
+ unsigned long clock;
+ uint8_t flags;
+ int num_irq;
+};
+
+static struct stm32_iwdg_instance stm32_iwdg[IWDG_MAX_INSTANCE];
+
+static int stm32_iwdg_get_dt_node(struct dt_node_info *info, int offset)
+{
+ int node;
+
+ node = dt_get_node(info, offset, DT_IWDG_COMPAT);
+ if (node < 0) {
+ if (offset == -1) {
+ VERBOSE("%s: No IDWG found\n", __func__);
+ }
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ return node;
+}
+
+void stm32_iwdg_refresh(void)
+{
+ uint8_t i;
+
+ for (i = 0U; i < IWDG_MAX_INSTANCE; i++) {
+ struct stm32_iwdg_instance *iwdg = &stm32_iwdg[i];
+
+ /* 0x00000000 is not a valid address for IWDG peripherals */
+ if (iwdg->base != 0U) {
+ stm32mp_clk_enable(iwdg->clock);
+
+ mmio_write_32(iwdg->base + IWDG_KR_OFFSET,
+ IWDG_KR_RELOAD_KEY);
+
+ stm32mp_clk_disable(iwdg->clock);
+ }
+ }
+}
+
+int stm32_iwdg_init(void)
+{
+ int node = -1;
+ struct dt_node_info dt_info;
+ void *fdt;
+ uint32_t __unused count = 0;
+
+ if (fdt_get_address(&fdt) == 0) {
+ panic();
+ }
+
+ for (node = stm32_iwdg_get_dt_node(&dt_info, node);
+ node != -FDT_ERR_NOTFOUND;
+ node = stm32_iwdg_get_dt_node(&dt_info, node)) {
+ struct stm32_iwdg_instance *iwdg;
+ uint32_t hw_init;
+ uint32_t idx;
+
+ count++;
+
+ idx = stm32_iwdg_get_instance(dt_info.base);
+ iwdg = &stm32_iwdg[idx];
+ iwdg->base = dt_info.base;
+ iwdg->clock = (unsigned long)dt_info.clock;
+
+ /* DT can specify low power cases */
+ if (fdt_getprop(fdt, node, "stm32,enable-on-stop", NULL) ==
+ NULL) {
+ iwdg->flags |= IWDG_DISABLE_ON_STOP;
+ }
+
+ if (fdt_getprop(fdt, node, "stm32,enable-on-standby", NULL) ==
+ NULL) {
+ iwdg->flags |= IWDG_DISABLE_ON_STANDBY;
+ }
+
+ /* Explicit list of supported bit flags */
+ hw_init = stm32_iwdg_get_otp_config(idx);
+
+ if ((hw_init & IWDG_HW_ENABLED) != 0) {
+ if (dt_info.status == DT_DISABLED) {
+ ERROR("OTP enabled but iwdg%u DT-disabled\n",
+ idx + 1U);
+ panic();
+ }
+ iwdg->flags |= IWDG_HW_ENABLED;
+ }
+
+ if (dt_info.status == DT_DISABLED) {
+ zeromem((void *)iwdg,
+ sizeof(struct stm32_iwdg_instance));
+ continue;
+ }
+
+ if ((hw_init & IWDG_DISABLE_ON_STOP) != 0) {
+ iwdg->flags |= IWDG_DISABLE_ON_STOP;
+ }
+
+ if ((hw_init & IWDG_DISABLE_ON_STANDBY) != 0) {
+ iwdg->flags |= IWDG_DISABLE_ON_STANDBY;
+ }
+
+ VERBOSE("IWDG%u found, %ssecure\n", idx + 1U,
+ ((dt_info.status & DT_NON_SECURE) != 0) ?
+ "non-" : "");
+
+#if defined(IMAGE_BL2)
+ if (stm32_iwdg_shadow_update(idx, iwdg->flags) != BSEC_OK) {
+ return -1;
+ }
+#endif
+ }
+
+ VERBOSE("%u IWDG instance%s found\n", count, (count > 1U) ? "s" : "");
+
+ return 0;
+}
diff --git a/drivers/st/mmc/stm32_sdmmc2.c b/drivers/st/mmc/stm32_sdmmc2.c
index f453ce9a..24e6efe9 100644
--- a/drivers/st/mmc/stm32_sdmmc2.c
+++ b/drivers/st/mmc/stm32_sdmmc2.c
@@ -71,20 +71,14 @@
#define SDMMC_DCTRLR_DTEN BIT(0)
#define SDMMC_DCTRLR_DTDIR BIT(1)
#define SDMMC_DCTRLR_DTMODE GENMASK(3, 2)
-#define SDMMC_DCTRLR_DBLOCKSIZE_0 BIT(4)
-#define SDMMC_DCTRLR_DBLOCKSIZE_1 BIT(5)
-#define SDMMC_DCTRLR_DBLOCKSIZE_3 BIT(7)
#define SDMMC_DCTRLR_DBLOCKSIZE GENMASK(7, 4)
+#define SDMMC_DCTRLR_DBLOCKSIZE_SHIFT 4
#define SDMMC_DCTRLR_FIFORST BIT(13)
#define SDMMC_DCTRLR_CLEAR_MASK (SDMMC_DCTRLR_DTEN | \
SDMMC_DCTRLR_DTDIR | \
SDMMC_DCTRLR_DTMODE | \
SDMMC_DCTRLR_DBLOCKSIZE)
-#define SDMMC_DBLOCKSIZE_8 (SDMMC_DCTRLR_DBLOCKSIZE_0 | \
- SDMMC_DCTRLR_DBLOCKSIZE_1)
-#define SDMMC_DBLOCKSIZE_512 (SDMMC_DCTRLR_DBLOCKSIZE_0 | \
- SDMMC_DCTRLR_DBLOCKSIZE_3)
/* SDMMC status register */
#define SDMMC_STAR_CCRCFAIL BIT(0)
@@ -152,10 +146,14 @@ bool plat_sdmmc2_use_dma(unsigned int instance, unsigned int memory)
static void stm32_sdmmc2_init(void)
{
uint32_t clock_div;
+ uint32_t freq = STM32MP_MMC_INIT_FREQ;
uintptr_t base = sdmmc2_params.reg_base;
- clock_div = div_round_up(sdmmc2_params.clk_rate,
- STM32MP_MMC_INIT_FREQ * 2);
+ if (sdmmc2_params.max_freq != 0U) {
+ freq = MIN(sdmmc2_params.max_freq, freq);
+ }
+
+ clock_div = div_round_up(sdmmc2_params.clk_rate, freq * 2U);
mmio_write_32(base + SDMMC_CLKCR, SDMMC_CLKCR_HWFC_EN | clock_div |
sdmmc2_params.negedge |
@@ -406,7 +404,7 @@ static int stm32_sdmmc2_set_ios(unsigned int clk, unsigned int width)
{
uintptr_t base = sdmmc2_params.reg_base;
uint32_t bus_cfg = 0;
- uint32_t clock_div, max_freq;
+ uint32_t clock_div, max_freq, freq;
uint32_t clk_rate = sdmmc2_params.clk_rate;
uint32_t max_bus_freq = sdmmc2_params.device_info->max_bus_freq;
@@ -438,7 +436,13 @@ static int stm32_sdmmc2_set_ios(unsigned int clk, unsigned int width)
}
}
- clock_div = div_round_up(clk_rate, max_freq * 2);
+ if (sdmmc2_params.max_freq != 0U) {
+ freq = MIN(sdmmc2_params.max_freq, max_freq);
+ } else {
+ freq = max_freq;
+ }
+
+ clock_div = div_round_up(clk_rate, freq * 2U);
mmio_write_32(base + SDMMC_CLKCR,
SDMMC_CLKCR_HWFC_EN | clock_div | bus_cfg |
@@ -454,11 +458,14 @@ static int stm32_sdmmc2_prepare(int lba, uintptr_t buf, size_t size)
int ret;
uintptr_t base = sdmmc2_params.reg_base;
uint32_t data_ctrl = SDMMC_DCTRLR_DTDIR;
+ uint32_t arg_size;
+
+ assert(size != 0U);
- if (size == 8U) {
- data_ctrl |= SDMMC_DBLOCKSIZE_8;
+ if (size > MMC_BLOCK_SIZE) {
+ arg_size = MMC_BLOCK_SIZE;
} else {
- data_ctrl |= SDMMC_DBLOCKSIZE_512;
+ arg_size = size;
}
sdmmc2_params.use_dma = plat_sdmmc2_use_dma(base, buf);
@@ -477,12 +484,7 @@ static int stm32_sdmmc2_prepare(int lba, uintptr_t buf, size_t size)
zeromem(&cmd, sizeof(struct mmc_cmd));
cmd.cmd_idx = MMC_CMD(16);
- if (size > MMC_BLOCK_SIZE) {
- cmd.cmd_arg = MMC_BLOCK_SIZE;
- } else {
- cmd.cmd_arg = size;
- }
-
+ cmd.cmd_arg = arg_size;
cmd.resp_type = MMC_RESPONSE_R1;
ret = stm32_sdmmc2_send_cmd(&cmd);
@@ -504,6 +506,8 @@ static int stm32_sdmmc2_prepare(int lba, uintptr_t buf, size_t size)
flush_dcache_range(buf, size);
}
+ data_ctrl |= __builtin_ctz(arg_size) << SDMMC_DCTRLR_DBLOCKSIZE_SHIFT;
+
mmio_clrsetbits_32(base + SDMMC_DCTRLR,
SDMMC_DCTRLR_CLEAR_MASK,
data_ctrl);
@@ -692,6 +696,11 @@ static int stm32_sdmmc2_dt_get_config(void)
}
}
+ cuint = fdt_getprop(fdt, sdmmc_node, "max-frequency", NULL);
+ if (cuint != NULL) {
+ sdmmc2_params.max_freq = fdt32_to_cpu(*cuint);
+ }
+
return 0;
}
diff --git a/drivers/st/pmic/stm32mp_pmic.c b/drivers/st/pmic/stm32mp_pmic.c
index 6fe51f44..9e9dddc4 100644
--- a/drivers/st/pmic/stm32mp_pmic.c
+++ b/drivers/st/pmic/stm32mp_pmic.c
@@ -299,6 +299,7 @@ int pmic_ddr_power_init(enum ddr_type ddr_type)
break;
case STM32MP_LPDDR2:
+ case STM32MP_LPDDR3:
/*
* Set LDO3 to 1.8V
* Set LDO3 to bypass mode if BUCK3 = 1.8V