diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/st/bsec/bsec.c | 10 | ||||
-rw-r--r-- | drivers/st/clk/stm32mp1_clk.c | 29 | ||||
-rw-r--r-- | drivers/st/ddr/stm32mp1_ddr.c | 2 | ||||
-rw-r--r-- | drivers/st/io/io_stm32image.c | 36 | ||||
-rw-r--r-- | drivers/st/iwdg/stm32_iwdg.c | 150 | ||||
-rw-r--r-- | drivers/st/mmc/stm32_sdmmc2.c | 49 | ||||
-rw-r--r-- | drivers/st/pmic/stm32mp_pmic.c | 1 |
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 |