diff --git a/drivers/st/bsec/bsec.c b/drivers/st/bsec/bsec.c new file mode 100644 index 0000000000000000000000000000000000000000..aaecf1f83a0cf2235b7812973d7c9df91071f75b --- /dev/null +++ b/drivers/st/bsec/bsec.c @@ -0,0 +1,913 @@ +/* + * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include + +#define BSEC_IP_VERSION_1_0 0x10 +#define BSEC_COMPAT "st,stm32mp15-bsec" + +#define OTP_ACCESS_SIZE (round_up(OTP_MAX_SIZE, __WORD_BIT) / __WORD_BIT) + +static uint32_t otp_nsec_access[OTP_ACCESS_SIZE] __unused; + +static uint32_t bsec_power_safmem(bool power); + +/* BSEC access protection */ +static spinlock_t bsec_spinlock; +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) { + 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) { + spin_unlock(&bsec_spinlock); + } +} + +static int bsec_get_dt_node(struct dt_node_info *info) +{ + int node; + + node = dt_get_node(info, -1, BSEC_COMPAT); + if (node < 0) { + return -FDT_ERR_NOTFOUND; + } + + return node; +} + +#if defined(IMAGE_BL32) +static void enable_non_secure_access(uint32_t otp) +{ + otp_nsec_access[otp / __WORD_BIT] |= BIT(otp % __WORD_BIT); + + if (bsec_shadow_register(otp) != BSEC_OK) { + panic(); + } +} + +static bool non_secure_can_access(uint32_t otp) +{ + return (otp_nsec_access[otp / __WORD_BIT] & + BIT(otp % __WORD_BIT)) != 0; +} + +static int bsec_dt_otp_nsec_access(void *fdt, int bsec_node) +{ + int bsec_subnode; + + fdt_for_each_subnode(bsec_subnode, fdt, bsec_node) { + const fdt32_t *cuint; + uint32_t reg; + uint32_t i; + uint32_t size; + uint8_t status; + + cuint = fdt_getprop(fdt, bsec_subnode, "reg", NULL); + if (cuint == NULL) { + panic(); + } + + reg = fdt32_to_cpu(*cuint) / sizeof(uint32_t); + if (reg < STM32MP1_UPPER_OTP_START) { + continue; + } + + status = fdt_get_status(bsec_subnode); + if ((status & DT_NON_SECURE) == 0U) { + continue; + } + + size = fdt32_to_cpu(*(cuint + 1)) / sizeof(uint32_t); + + if ((fdt32_to_cpu(*(cuint + 1)) % sizeof(uint32_t)) != 0) { + size++; + } + + for (i = reg; i < (reg + size); i++) { + enable_non_secure_access(i); + } + } + + return 0; +} +#endif + +static uint32_t otp_bank_offset(uint32_t otp) +{ + assert(otp <= STM32MP1_OTP_MAX_ID); + + return ((otp & ~BSEC_OTP_MASK) >> BSEC_OTP_BANK_SHIFT) * + sizeof(uint32_t); +} + +static uint32_t bsec_check_error(uint32_t otp) +{ + uint32_t bit = BIT(otp & BSEC_OTP_MASK); + uint32_t bank = otp_bank_offset(otp); + + if ((mmio_read_32(bsec_base + BSEC_DISTURBED_OFF + bank) & bit) != 0U) { + return BSEC_DISTURBED; + } + + if ((mmio_read_32(bsec_base + BSEC_ERROR_OFF + bank) & bit) != 0U) { + return BSEC_ERROR; + } + + return BSEC_OK; +} + +/* + * bsec_probe: initialize BSEC driver. + * return value: BSEC_OK if no error. + */ +uint32_t bsec_probe(void) +{ + void *fdt; + int node; + struct dt_node_info bsec_info; + + if (fdt_get_address(&fdt) == 0) { + panic(); + } + + node = bsec_get_dt_node(&bsec_info); + if (node < 0) { + panic(); + } + + bsec_base = bsec_info.base; + +#if defined(IMAGE_BL32) + bsec_dt_otp_nsec_access(fdt, node); +#endif + return BSEC_OK; +} + +/* + * bsec_get_base: return BSEC base address. + */ +uint32_t bsec_get_base(void) +{ + return bsec_base; +} + +/* + * bsec_set_config: enable and configure BSEC. + * cfg: pointer to param structure used to set register. + * return value: BSEC_OK if no error. + */ +uint32_t bsec_set_config(struct bsec_config *cfg) +{ + uint32_t value; + int32_t result; + + value = ((((uint32_t)cfg->freq << BSEC_CONF_FRQ_SHIFT) & + BSEC_CONF_FRQ_MASK) | + (((uint32_t)cfg->pulse_width << BSEC_CONF_PRG_WIDTH_SHIFT) & + BSEC_CONF_PRG_WIDTH_MASK) | + (((uint32_t)cfg->tread << BSEC_CONF_TREAD_SHIFT) & + BSEC_CONF_TREAD_MASK)); + + bsec_lock(); + + mmio_write_32(bsec_base + BSEC_OTP_CONF_OFF, value); + + bsec_unlock(); + + result = bsec_power_safmem((bool)cfg->power & + BSEC_CONF_POWER_UP_MASK); + if (result != BSEC_OK) { + return result; + } + + value = ((((uint32_t)cfg->upper_otp_lock << UPPER_OTP_LOCK_SHIFT) & + UPPER_OTP_LOCK_MASK) | + (((uint32_t)cfg->den_lock << DENREG_LOCK_SHIFT) & + DENREG_LOCK_MASK) | + (((uint32_t)cfg->prog_lock << GPLOCK_LOCK_SHIFT) & + GPLOCK_LOCK_MASK)); + + bsec_lock(); + + mmio_write_32(bsec_base + BSEC_OTP_LOCK_OFF, value); + + bsec_unlock(); + + return BSEC_OK; +} + +/* + * bsec_get_config: return config parameters set in BSEC registers. + * cfg: config param return. + * return value: BSEC_OK if no error. + */ +uint32_t bsec_get_config(struct bsec_config *cfg) +{ + uint32_t value; + + if (cfg == NULL) { + return BSEC_INVALID_PARAM; + } + + value = mmio_read_32(bsec_base + BSEC_OTP_CONF_OFF); + cfg->power = (uint8_t)((value & BSEC_CONF_POWER_UP_MASK) >> + BSEC_CONF_POWER_UP_SHIFT); + cfg->freq = (uint8_t)((value & BSEC_CONF_FRQ_MASK) >> + BSEC_CONF_FRQ_SHIFT); + cfg->pulse_width = (uint8_t)((value & BSEC_CONF_PRG_WIDTH_MASK) >> + BSEC_CONF_PRG_WIDTH_SHIFT); + cfg->tread = (uint8_t)((value & BSEC_CONF_TREAD_MASK) >> + BSEC_CONF_TREAD_SHIFT); + + value = mmio_read_32(bsec_base + BSEC_OTP_LOCK_OFF); + cfg->upper_otp_lock = (uint8_t)((value & UPPER_OTP_LOCK_MASK) >> + UPPER_OTP_LOCK_SHIFT); + cfg->den_lock = (uint8_t)((value & DENREG_LOCK_MASK) >> + DENREG_LOCK_SHIFT); + cfg->prog_lock = (uint8_t)((value & GPLOCK_LOCK_MASK) >> + GPLOCK_LOCK_SHIFT); + + return BSEC_OK; +} + +/* + * bsec_shadow_register: copy SAFMEM OTP to BSEC data. + * otp: OTP number. + * return value: BSEC_OK if no error. + */ +uint32_t bsec_shadow_register(uint32_t otp) +{ + uint32_t result; + bool power_up = false; + + if (otp > STM32MP1_OTP_MAX_ID) { + return BSEC_INVALID_PARAM; + } + + /* Check if shadowing of OTP is locked */ + if (bsec_read_sr_lock(otp)) { + VERBOSE("BSEC: OTP %i is locked and will not be refreshed\n", + otp); + } + + if ((bsec_get_status() & BSEC_MODE_PWR_MASK) == 0U) { + result = bsec_power_safmem(true); + + if (result != BSEC_OK) { + return result; + } + + power_up = true; + } + + bsec_lock(); + + /* Set BSEC_OTP_CTRL_OFF and set ADDR with the OTP value */ + mmio_write_32(bsec_base + BSEC_OTP_CTRL_OFF, otp | BSEC_READ); + + while ((bsec_get_status() & BSEC_MODE_BUSY_MASK) != 0U) { + ; + } + + result = bsec_check_error(otp); + + bsec_unlock(); + + if (power_up) { + if (bsec_power_safmem(false) != BSEC_OK) { + panic(); + } + } + + return result; +} + +/* + * bsec_read_otp: read an OTP data value. + * val: read value. + * otp: OTP number. + * return value: BSEC_OK if no error. + */ +uint32_t bsec_read_otp(uint32_t *val, uint32_t otp) +{ + uint32_t result; + + if (otp > STM32MP1_OTP_MAX_ID) { + return BSEC_INVALID_PARAM; + } + + bsec_lock(); + + *val = mmio_read_32(bsec_base + BSEC_OTP_DATA_OFF + + (otp * sizeof(uint32_t))); + + result = bsec_check_error(otp); + + bsec_unlock(); + + return result; +} + +/* + * bsec_write_otp: write value in BSEC data register. + * val: value to write. + * otp: OTP number. + * return value: BSEC_OK if no error. + */ +uint32_t bsec_write_otp(uint32_t val, uint32_t otp) +{ + uint32_t result; + + if (otp > STM32MP1_OTP_MAX_ID) { + return BSEC_INVALID_PARAM; + } + + /* Check if programming of OTP is locked */ + if (bsec_read_sw_lock(otp)) { + VERBOSE("BSEC: OTP %i is locked and write will be ignored\n", + otp); + } + + bsec_lock(); + + mmio_write_32(bsec_base + BSEC_OTP_DATA_OFF + + (otp * sizeof(uint32_t)), val); + + result = bsec_check_error(otp); + + bsec_unlock(); + + return result; +} + +/* + * bsec_program_otp: program a bit in SAFMEM after the prog. + * The OTP data is not refreshed. + * val: value to program. + * otp: OTP number. + * return value: BSEC_OK if no error. + */ +uint32_t bsec_program_otp(uint32_t val, uint32_t otp) +{ + uint32_t result; + bool power_up = false; + + if (otp > STM32MP1_OTP_MAX_ID) { + return BSEC_INVALID_PARAM; + } + + /* Check if programming of OTP is locked */ + if (bsec_read_sp_lock(otp)) { + WARN("BSEC: OTP locked, prog will be ignored\n"); + } + + if ((mmio_read_32(bsec_base + BSEC_OTP_LOCK_OFF) & + BIT(BSEC_LOCK_PROGRAM)) != 0U) { + WARN("BSEC: GPLOCK activated, prog will be ignored\n"); + } + + if ((bsec_get_status() & BSEC_MODE_PWR_MASK) == 0U) { + result = bsec_power_safmem(true); + + if (result != BSEC_OK) { + return result; + } + + power_up = true; + } + + bsec_lock(); + + /* Set value in write register */ + mmio_write_32(bsec_base + BSEC_OTP_WRDATA_OFF, val); + + /* Set BSEC_OTP_CTRL_OFF and set ADDR with the OTP value */ + mmio_write_32(bsec_base + BSEC_OTP_CTRL_OFF, otp | BSEC_WRITE); + + while ((bsec_get_status() & BSEC_MODE_BUSY_MASK) != 0U) { + ; + } + + if ((bsec_get_status() & BSEC_MODE_PROGFAIL_MASK) != 0U) { + result = BSEC_PROG_FAIL; + } else { + result = bsec_check_error(otp); + } + + bsec_unlock(); + + if (power_up) { + if (bsec_power_safmem(false) != BSEC_OK) { + panic(); + } + } + + return result; +} + +/* + * bsec_permanent_lock_otp: permanent lock of OTP in SAFMEM. + * otp: OTP number. + * return value: BSEC_OK if no error. + */ +uint32_t bsec_permanent_lock_otp(uint32_t otp) +{ + uint32_t result; + bool power_up = false; + uint32_t data; + uint32_t addr; + + if (otp > STM32MP1_OTP_MAX_ID) { + return BSEC_INVALID_PARAM; + } + + if ((bsec_get_status() & BSEC_MODE_PWR_MASK) == 0U) { + result = bsec_power_safmem(true); + + if (result != BSEC_OK) { + return result; + } + + power_up = true; + } + + if (otp < STM32MP1_UPPER_OTP_START) { + addr = otp >> ADDR_LOWER_OTP_PERLOCK_SHIFT; + data = DATA_LOWER_OTP_PERLOCK_BIT << + ((otp & DATA_LOWER_OTP_PERLOCK_MASK) << 1U); + } else { + addr = (otp >> ADDR_UPPER_OTP_PERLOCK_SHIFT) + 2U; + data = DATA_UPPER_OTP_PERLOCK_BIT << + (otp & DATA_UPPER_OTP_PERLOCK_MASK); + } + + bsec_lock(); + + /* Set value in write register */ + mmio_write_32(bsec_base + BSEC_OTP_WRDATA_OFF, data); + + /* Set BSEC_OTP_CTRL_OFF and set ADDR with the OTP value */ + mmio_write_32(bsec_base + BSEC_OTP_CTRL_OFF, + addr | BSEC_WRITE | BSEC_LOCK); + + while ((bsec_get_status() & BSEC_MODE_BUSY_MASK) != 0U) { + ; + } + + if ((bsec_get_status() & BSEC_MODE_PROGFAIL_MASK) != 0U) { + result = BSEC_PROG_FAIL; + } else { + result = bsec_check_error(otp); + } + + bsec_unlock(); + + if (power_up) { + if (bsec_power_safmem(false) != BSEC_OK) { + panic(); + } + } + + return result; +} + +/* + * bsec_write_debug_conf: write value in debug feature + * to enable/disable debug service. + * val: value to write. + * return value: BSEC_OK if no error. + */ +uint32_t bsec_write_debug_conf(uint32_t val) +{ + uint32_t result = BSEC_ERROR; + uint32_t masked_val = val & BSEC_DEN_ALL_MSK; + + bsec_lock(); + + mmio_write_32(bsec_base + BSEC_DEN_OFF, masked_val); + + if ((mmio_read_32(bsec_base + BSEC_DEN_OFF) ^ masked_val) == 0U) { + result = BSEC_OK; + } + + bsec_unlock(); + + return result; +} + +/* + * bsec_read_debug_conf: read debug configuration. + */ +uint32_t bsec_read_debug_conf(void) +{ + return mmio_read_32(bsec_base + BSEC_DEN_OFF); +} + +/* + * bsec_get_status: return status register value. + */ +uint32_t bsec_get_status(void) +{ + return mmio_read_32(bsec_base + BSEC_OTP_STATUS_OFF); +} + +/* + * bsec_get_hw_conf: return hardware configuration. + */ +uint32_t bsec_get_hw_conf(void) +{ + return mmio_read_32(bsec_base + BSEC_IPHW_CFG_OFF); +} + +/* + * bsec_get_version: return BSEC version. + */ +uint32_t bsec_get_version(void) +{ + return mmio_read_32(bsec_base + BSEC_IPVR_OFF); +} + +/* + * bsec_get_id: return BSEC ID. + */ +uint32_t bsec_get_id(void) +{ + return mmio_read_32(bsec_base + BSEC_IP_ID_OFF); +} + +/* + * bsec_get_magic_id: return BSEC magic number. + */ +uint32_t bsec_get_magic_id(void) +{ + return mmio_read_32(bsec_base + BSEC_IP_MAGIC_ID_OFF); +} + +/* + * bsec_write_sr_lock: write shadow-read lock. + * otp: OTP number. + * value: value to write in the register. + * Must be always 1. + * return: true if OTP is locked, else false. + */ +bool bsec_write_sr_lock(uint32_t otp, uint32_t value) +{ + bool result = false; + uint32_t bank = otp_bank_offset(otp); + uint32_t bank_value; + uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK); + + bsec_lock(); + + bank_value = mmio_read_32(bsec_base + BSEC_SRLOCK_OFF + bank); + + if ((bank_value & otp_mask) == value) { + /* + * In case of write don't need to write, + * the lock is already set. + */ + if (value != 0U) { + result = true; + } + } else { + if (value != 0U) { + bank_value = bank_value | otp_mask; + } else { + bank_value = bank_value & ~otp_mask; + } + + /* + * We can write 0 in all other OTP + * if the lock is activated in one of other OTP. + * Write 0 has no effect. + */ + mmio_write_32(bsec_base + BSEC_SRLOCK_OFF + bank, bank_value); + result = true; + } + + bsec_unlock(); + + return result; +} + +/* + * bsec_read_sr_lock: read shadow-read lock. + * otp: OTP number. + * return: true if otp is locked, else false. + */ +bool bsec_read_sr_lock(uint32_t otp) +{ + uint32_t bank = otp_bank_offset(otp); + uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK); + uint32_t bank_value = mmio_read_32(bsec_base + BSEC_SRLOCK_OFF + bank); + + return (bank_value & otp_mask) != 0U; +} + +/* + * bsec_write_sw_lock: write shadow-write lock. + * otp: OTP number. + * value: Value to write in the register. + * Must be always 1. + * return: true if OTP is locked, else false. + */ +bool bsec_write_sw_lock(uint32_t otp, uint32_t value) +{ + bool result = false; + uint32_t bank = otp_bank_offset(otp); + uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK); + uint32_t bank_value; + + bsec_lock(); + + bank_value = mmio_read_32(bsec_base + BSEC_SWLOCK_OFF + bank); + + if ((bank_value & otp_mask) == value) { + /* + * In case of write don't need to write, + * the lock is already set. + */ + if (value != 0U) { + result = true; + } + } else { + if (value != 0U) { + bank_value = bank_value | otp_mask; + } else { + bank_value = bank_value & ~otp_mask; + } + + /* + * We can write 0 in all other OTP + * if the lock is activated in one of other OTP. + * Write 0 has no effect. + */ + mmio_write_32(bsec_base + BSEC_SWLOCK_OFF + bank, bank_value); + result = true; + } + + bsec_unlock(); + + return result; +} + +/* + * bsec_read_sw_lock: read shadow-write lock. + * otp: OTP number. + * return: true if OTP is locked, else false. + */ +bool bsec_read_sw_lock(uint32_t otp) +{ + uint32_t bank = otp_bank_offset(otp); + uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK); + uint32_t bank_value = mmio_read_32(bsec_base + BSEC_SWLOCK_OFF + bank); + + return (bank_value & otp_mask) != 0U; +} + +/* + * bsec_write_sp_lock: write shadow-program lock. + * otp: OTP number. + * value: Value to write in the register. + * Must be always 1. + * return: true if OTP is locked, else false. + */ +bool bsec_write_sp_lock(uint32_t otp, uint32_t value) +{ + bool result = false; + uint32_t bank = otp_bank_offset(otp); + uint32_t bank_value; + uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK); + + bsec_lock(); + + bank_value = mmio_read_32(bsec_base + BSEC_SPLOCK_OFF + bank); + + if ((bank_value & otp_mask) == value) { + /* + * In case of write don't need to write, + * the lock is already set. + */ + if (value != 0U) { + result = true; + } + } else { + if (value != 0U) { + bank_value = bank_value | otp_mask; + } else { + bank_value = bank_value & ~otp_mask; + } + + /* + * We can write 0 in all other OTP + * if the lock is activated in one of other OTP. + * Write 0 has no effect. + */ + mmio_write_32(bsec_base + BSEC_SPLOCK_OFF + bank, bank_value); + result = true; + } + + bsec_unlock(); + + return result; +} + +/* + * bsec_read_sp_lock: read shadow-program lock. + * otp: OTP number. + * return: true if OTP is locked, else false. + */ +bool bsec_read_sp_lock(uint32_t otp) +{ + uint32_t bank = otp_bank_offset(otp); + uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK); + uint32_t bank_value = mmio_read_32(bsec_base + BSEC_SPLOCK_OFF + bank); + + return (bank_value & otp_mask) != 0U; +} + +/* + * bsec_wr_lock: Read permanent lock status. + * otp: OTP number. + * return: true if OTP is locked, else false. + */ +bool bsec_wr_lock(uint32_t otp) +{ + uint32_t bank = otp_bank_offset(otp); + uint32_t lock_bit = BIT(otp & BSEC_OTP_MASK); + + if ((mmio_read_32(bsec_base + BSEC_WRLOCK_OFF + bank) & + lock_bit) != 0U) { + /* + * In case of write don't need to write, + * the lock is already set. + */ + return true; + } + + return false; +} + +/* + * bsec_otp_lock: Lock Upper OTP or Global programming or debug enable + * service: Service to lock see header file. + * value: Value to write must always set to 1 (only use for debug purpose). + * return: BSEC_OK if succeed. + */ +uint32_t bsec_otp_lock(uint32_t service, uint32_t value) +{ + uintptr_t reg = bsec_base + BSEC_OTP_LOCK_OFF; + + switch (service) { + case BSEC_LOCK_UPPER_OTP: + mmio_write_32(reg, value << BSEC_LOCK_UPPER_OTP); + break; + case BSEC_LOCK_DEBUG: + mmio_write_32(reg, value << BSEC_LOCK_DEBUG); + break; + case BSEC_LOCK_PROGRAM: + mmio_write_32(reg, value << BSEC_LOCK_PROGRAM); + break; + default: + return BSEC_INVALID_PARAM; + } + + return BSEC_OK; +} + +/* + * bsec_power_safmem: Activate or deactivate SAFMEM power. + * power: true to power up, false to power down. + * return: BSEC_OK if succeed. + */ +static uint32_t bsec_power_safmem(bool power) +{ + uint32_t register_val; + uint32_t timeout = BSEC_TIMEOUT_VALUE; + + bsec_lock(); + + register_val = mmio_read_32(bsec_base + BSEC_OTP_CONF_OFF); + + if (power) { + register_val |= BSEC_CONF_POWER_UP_MASK; + } else { + register_val &= ~BSEC_CONF_POWER_UP_MASK; + } + + mmio_write_32(bsec_base + BSEC_OTP_CONF_OFF, register_val); + + /* Waiting loop */ + if (power) { + while (((bsec_get_status() & BSEC_MODE_PWR_MASK) == 0U) && + (timeout != 0U)) { + timeout--; + } + } else { + while (((bsec_get_status() & BSEC_MODE_PWR_MASK) != 0U) && + (timeout != 0U)) { + timeout--; + } + } + + bsec_unlock(); + + if (timeout == 0U) { + return BSEC_TIMEOUT; + } + + return BSEC_OK; +} + +/* + * bsec_mode_is_closed_device: read OTP secure sub-mode. + * return: false if open_device and true of closed_device. + */ +bool bsec_mode_is_closed_device(void) +{ + uint32_t value; + + if ((bsec_shadow_register(DATA0_OTP) != BSEC_OK) || + (bsec_read_otp(&value, DATA0_OTP) != BSEC_OK)) { + return true; + } + + return (value & DATA0_OTP_SECURED) == DATA0_OTP_SECURED; +} + +/* + * bsec_shadow_read_otp: Load OTP from SAFMEM and provide its value + * otp_value: read value. + * word: OTP number. + * return value: BSEC_OK if no error. + */ +uint32_t bsec_shadow_read_otp(uint32_t *otp_value, uint32_t word) +{ + uint32_t result; + + result = bsec_shadow_register(word); + if (result != BSEC_OK) { + ERROR("BSEC: %u Shadowing Error %i\n", word, result); + return result; + } + + result = bsec_read_otp(otp_value, word); + if (result != BSEC_OK) { + ERROR("BSEC: %u Read Error %i\n", word, result); + } + + return result; +} + +/* + * bsec_check_nsec_access_rights: check non-secure access rights to target OTP. + * otp: OTP number. + * return: BSEC_OK if authorized access. + */ +uint32_t bsec_check_nsec_access_rights(uint32_t otp) +{ +#if defined(IMAGE_BL32) + if (otp > STM32MP1_OTP_MAX_ID) { + return BSEC_INVALID_PARAM; + } + + if (otp >= STM32MP1_UPPER_OTP_START) { + /* Check if BSEC is in OTP-SECURED closed_device state. */ + if (bsec_mode_is_closed_device()) { + if (!non_secure_can_access(otp)) { + return BSEC_ERROR; + } + } + } +#endif + + return BSEC_OK; +} + diff --git a/drivers/st/clk/stm32mp1_clkfunc.c b/drivers/st/clk/stm32mp1_clkfunc.c index 1d92271063c8f4a054845c2979e555675d9a7fd0..19dfe1b25417df5f9146157851edf2dcbd0d3819 100644 --- a/drivers/st/clk/stm32mp1_clkfunc.c +++ b/drivers/st/clk/stm32mp1_clkfunc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved + * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved * * SPDX-License-Identifier: BSD-3-Clause */ @@ -31,11 +31,19 @@ const char *stm32mp_osc_node_label[NB_OSC] = { [_USB_PHY_48] = "ck_usbo_48m" }; +/******************************************************************************* + * This function returns the RCC node in the device tree. + ******************************************************************************/ +static int fdt_get_rcc_node(void *fdt) +{ + return fdt_node_offset_by_compatible(fdt, -1, DT_RCC_CLK_COMPAT); +} + /******************************************************************************* * This function reads the frequency of an oscillator from its name. * It reads the value indicated inside the device tree. - * Returns 0 if success, and a negative value else. - * If success, value is stored in the second parameter. + * Returns 0 on success, and a negative FDT/ERRNO error code on failure. + * On success, value is stored in the second parameter. ******************************************************************************/ int fdt_osc_read_freq(const char *name, uint32_t *freq) { @@ -127,7 +135,7 @@ bool fdt_osc_read_bool(enum stm32mp_osc_id osc_id, const char *prop_name) /******************************************************************************* * This function reads a value of a oscillator property from its id. - * Returns value if success, and a default value if property not found. + * Returns value on success, and a default value if property not found. * Default value is passed as parameter. ******************************************************************************/ uint32_t fdt_osc_read_uint32_default(enum stm32mp_osc_id osc_id, @@ -240,7 +248,7 @@ int fdt_rcc_read_uint32_array(const char *prop_name, /******************************************************************************* * This function gets the subnode offset in rcc-clk section from its name. * It reads the values indicated inside the device tree. - * Returns offset if success, and a negative value else. + * Returns offset on success, and a negative FDT/ERRNO error code on failure. ******************************************************************************/ int fdt_rcc_subnode_offset(const char *name) { @@ -251,7 +259,7 @@ int fdt_rcc_subnode_offset(const char *name) return -ENOENT; } - node = fdt_node_offset_by_compatible(fdt, -1, DT_RCC_CLK_COMPAT); + node = fdt_get_rcc_node(fdt); if (node < 0) { return -FDT_ERR_NOTFOUND; } @@ -280,7 +288,7 @@ const fdt32_t *fdt_rcc_read_prop(const char *prop_name, int *lenp) return NULL; } - node = fdt_node_offset_by_compatible(fdt, -1, DT_RCC_CLK_COMPAT); + node = fdt_get_rcc_node(fdt); if (node < 0) { return NULL; } @@ -297,7 +305,7 @@ const fdt32_t *fdt_rcc_read_prop(const char *prop_name, int *lenp) /******************************************************************************* * This function gets the secure status for rcc node. * It reads secure-status in device tree. - * Returns 1 if rcc is available from secure world, 0 else. + * Returns true if rcc is available from secure world, false if not. ******************************************************************************/ bool fdt_get_rcc_secure_status(void) { @@ -308,18 +316,18 @@ bool fdt_get_rcc_secure_status(void) return false; } - node = fdt_node_offset_by_compatible(fdt, -1, DT_RCC_COMPAT); + node = fdt_get_rcc_node(fdt); if (node < 0) { return false; } - return fdt_check_secure_status(node); + return (fdt_get_status(node) & DT_SECURE) != 0U; } /******************************************************************************* * This function reads the stgen base address. * It reads the value indicated inside the device tree. - * Returns address if success, and NULL value else. + * Returns address on success, and NULL value on failure. ******************************************************************************/ uintptr_t fdt_get_stgen_base(void) { @@ -347,7 +355,7 @@ uintptr_t fdt_get_stgen_base(void) /******************************************************************************* * This function gets the clock ID of the given node. * It reads the value indicated inside the device tree. - * Returns ID if success, and a negative value else. + * Returns ID on success, and a negative FDT/ERRNO error code on failure. ******************************************************************************/ int fdt_get_clock_id(int node) { diff --git a/drivers/st/ddr/stm32mp1_ddr.c b/drivers/st/ddr/stm32mp1_ddr.c index aca04504f6ca6f9ce5cb54a5faedf091677954fa..79aff6e739058f0f15e2915eab7381abbc261f8d 100644 --- a/drivers/st/ddr/stm32mp1_ddr.c +++ b/drivers/st/ddr/stm32mp1_ddr.c @@ -1,9 +1,10 @@ /* - * Copyright (C) 2018, STMicroelectronics - All Rights Reserved + * Copyright (C) 2018-2019, STMicroelectronics - All Rights Reserved * * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */ +#include #include #include @@ -12,10 +13,10 @@ #include #include #include +#include #include #include #include -#include #include #include #include @@ -233,40 +234,67 @@ struct ddr_reg_info { static const struct ddr_reg_info ddr_registers[REG_TYPE_NB] = { [REG_REG] = { - "static", ddr_reg, ARRAY_SIZE(ddr_reg), DDR_BASE + .name = "static", + .desc = ddr_reg, + .size = ARRAY_SIZE(ddr_reg), + .base = DDR_BASE }, [REG_TIMING] = { - "timing", ddr_timing, ARRAY_SIZE(ddr_timing), DDR_BASE + .name = "timing", + .desc = ddr_timing, + .size = ARRAY_SIZE(ddr_timing), + .base = DDR_BASE }, [REG_PERF] = { - "perf", ddr_perf, ARRAY_SIZE(ddr_perf), DDR_BASE + .name = "perf", + .desc = ddr_perf, + .size = ARRAY_SIZE(ddr_perf), + .base = DDR_BASE }, [REG_MAP] = { - "map", ddr_map, ARRAY_SIZE(ddr_map), DDR_BASE + .name = "map", + .desc = ddr_map, + .size = ARRAY_SIZE(ddr_map), + .base = DDR_BASE }, [REGPHY_REG] = { - "static", ddrphy_reg, ARRAY_SIZE(ddrphy_reg), DDRPHY_BASE + .name = "static", + .desc = ddrphy_reg, + .size = ARRAY_SIZE(ddrphy_reg), + .base = DDRPHY_BASE }, [REGPHY_TIMING] = { - "timing", ddrphy_timing, ARRAY_SIZE(ddrphy_timing), DDRPHY_BASE + .name = "timing", + .desc = ddrphy_timing, + .size = ARRAY_SIZE(ddrphy_timing), + .base = DDRPHY_BASE }, [REGPHY_CAL] = { - "cal", ddrphy_cal, ARRAY_SIZE(ddrphy_cal), DDRPHY_BASE + .name = "cal", + .desc = ddrphy_cal, + .size = ARRAY_SIZE(ddrphy_cal), + .base = DDRPHY_BASE }, [REG_DYN] = { - "dyn", ddr_dyn, ARRAY_SIZE(ddr_dyn), DDR_BASE + .name = "dyn", + .desc = ddr_dyn, + .size = ARRAY_SIZE(ddr_dyn), + .base = DDR_BASE }, [REGPHY_DYN] = { - "dyn", ddrphy_dyn, ARRAY_SIZE(ddrphy_dyn), DDRPHY_BASE + .name = "dyn", + .desc = ddrphy_dyn, + .size = ARRAY_SIZE(ddrphy_dyn), + .base = DDRPHY_BASE }, }; -static uint32_t get_base_addr(const struct ddr_info *priv, enum base_type base) +static uintptr_t get_base_addr(const struct ddr_info *priv, enum base_type base) { if (base == DDRPHY_BASE) { - return (uint32_t)priv->phy; + return (uintptr_t)priv->phy; } else { - return (uint32_t)priv->ctl; + return (uintptr_t)priv->ctl; } } @@ -275,21 +303,22 @@ static void set_reg(const struct ddr_info *priv, const void *param) { unsigned int i; - unsigned int *ptr, value; + unsigned int value; enum base_type base = ddr_registers[type].base; - uint32_t base_addr = get_base_addr(priv, base); + uintptr_t base_addr = get_base_addr(priv, base); const struct reg_desc *desc = ddr_registers[type].desc; VERBOSE("init %s\n", ddr_registers[type].name); for (i = 0; i < ddr_registers[type].size; i++) { - ptr = (unsigned int *)(base_addr + desc[i].offset); + uintptr_t ptr = base_addr + desc[i].offset; + if (desc[i].par_offset == INVALID_OFFSET) { ERROR("invalid parameter offset for %s", desc[i].name); panic(); } else { - value = *((uint32_t *)((uint32_t)param + + value = *((uint32_t *)((uintptr_t)param + desc[i].par_offset)); - mmio_write_32((uint32_t)ptr, value); + mmio_write_32(ptr, value); } } } @@ -305,15 +334,15 @@ static void stm32mp1_ddrphy_idone_wait(struct stm32mp1_ddrphy *phy) time0 = start; do { - pgsr = mmio_read_32((uint32_t)&phy->pgsr); + pgsr = mmio_read_32((uintptr_t)&phy->pgsr); time = get_timer(start); if (time != time0) { - VERBOSE(" > [0x%x] pgsr = 0x%x &\n", - (uint32_t)&phy->pgsr, pgsr); - VERBOSE(" [0x%x] pir = 0x%x (time=%x)\n", - (uint32_t)&phy->pir, - mmio_read_32((uint32_t)&phy->pir), - (uint32_t)time); + VERBOSE(" > [0x%lx] pgsr = 0x%x &\n", + (uintptr_t)&phy->pgsr, pgsr); + VERBOSE(" [0x%lx] pir = 0x%x (time=%lx)\n", + (uintptr_t)&phy->pir, + mmio_read_32((uintptr_t)&phy->pir), + time); } time0 = time; @@ -341,18 +370,18 @@ static void stm32mp1_ddrphy_idone_wait(struct stm32mp1_ddrphy *phy) error++; } } while ((pgsr & DDRPHYC_PGSR_IDONE) == 0U && error == 0); - VERBOSE("\n[0x%x] pgsr = 0x%x\n", - (uint32_t)&phy->pgsr, pgsr); + VERBOSE("\n[0x%lx] pgsr = 0x%x\n", + (uintptr_t)&phy->pgsr, pgsr); } static void stm32mp1_ddrphy_init(struct stm32mp1_ddrphy *phy, uint32_t pir) { uint32_t pir_init = pir | DDRPHYC_PIR_INIT; - mmio_write_32((uint32_t)&phy->pir, pir_init); - VERBOSE("[0x%x] pir = 0x%x -> 0x%x\n", - (uint32_t)&phy->pir, pir_init, - mmio_read_32((uint32_t)&phy->pir)); + mmio_write_32((uintptr_t)&phy->pir, pir_init); + VERBOSE("[0x%lx] pir = 0x%x -> 0x%x\n", + (uintptr_t)&phy->pir, pir_init, + mmio_read_32((uintptr_t)&phy->pir)); /* Need to wait 10 configuration clock before start polling */ udelay(10); @@ -364,9 +393,9 @@ static void stm32mp1_ddrphy_init(struct stm32mp1_ddrphy *phy, uint32_t pir) /* Start quasi dynamic register update */ static void stm32mp1_start_sw_done(struct stm32mp1_ddrctl *ctl) { - mmio_clrbits_32((uint32_t)&ctl->swctl, DDRCTRL_SWCTL_SW_DONE); - VERBOSE("[0x%x] swctl = 0x%x\n", - (uint32_t)&ctl->swctl, mmio_read_32((uint32_t)&ctl->swctl)); + mmio_clrbits_32((uintptr_t)&ctl->swctl, DDRCTRL_SWCTL_SW_DONE); + VERBOSE("[0x%lx] swctl = 0x%x\n", + (uintptr_t)&ctl->swctl, mmio_read_32((uintptr_t)&ctl->swctl)); } /* Wait quasi dynamic register update */ @@ -375,15 +404,15 @@ static void stm32mp1_wait_sw_done_ack(struct stm32mp1_ddrctl *ctl) unsigned long start; uint32_t swstat; - mmio_setbits_32((uint32_t)&ctl->swctl, DDRCTRL_SWCTL_SW_DONE); - VERBOSE("[0x%x] swctl = 0x%x\n", - (uint32_t)&ctl->swctl, mmio_read_32((uint32_t)&ctl->swctl)); + mmio_setbits_32((uintptr_t)&ctl->swctl, DDRCTRL_SWCTL_SW_DONE); + VERBOSE("[0x%lx] swctl = 0x%x\n", + (uintptr_t)&ctl->swctl, mmio_read_32((uintptr_t)&ctl->swctl)); start = get_timer(0); do { - swstat = mmio_read_32((uint32_t)&ctl->swstat); - VERBOSE("[0x%x] swstat = 0x%x ", - (uint32_t)&ctl->swstat, swstat); + swstat = mmio_read_32((uintptr_t)&ctl->swstat); + VERBOSE("[0x%lx] swstat = 0x%x ", + (uintptr_t)&ctl->swstat, swstat); VERBOSE("timer in ms 0x%x = start 0x%lx\r", get_timer(0), start); if (get_timer(start) > plat_get_syscnt_freq2()) { @@ -391,8 +420,8 @@ static void stm32mp1_wait_sw_done_ack(struct stm32mp1_ddrctl *ctl) } } while ((swstat & DDRCTRL_SWSTAT_SW_DONE_ACK) == 0U); - VERBOSE("[0x%x] swstat = 0x%x\n", - (uint32_t)&ctl->swstat, swstat); + VERBOSE("[0x%lx] swstat = 0x%x\n", + (uintptr_t)&ctl->swstat, swstat); } /* Wait quasi dynamic register update */ @@ -406,11 +435,11 @@ static void stm32mp1_wait_operating_mode(struct ddr_info *priv, uint32_t mode) start = get_timer(0); for ( ; ; ) { - stat = mmio_read_32((uint32_t)&priv->ctl->stat); + stat = mmio_read_32((uintptr_t)&priv->ctl->stat); operating_mode = stat & DDRCTRL_STAT_OPERATING_MODE_MASK; selref_type = stat & DDRCTRL_STAT_SELFREF_TYPE_MASK; - VERBOSE("[0x%x] stat = 0x%x\n", - (uint32_t)&priv->ctl->stat, stat); + VERBOSE("[0x%lx] stat = 0x%x\n", + (uintptr_t)&priv->ctl->stat, stat); VERBOSE("timer in ms 0x%x = start 0x%lx\r", get_timer(0), start); if (get_timer(start) > plat_get_syscnt_freq2()) { @@ -441,8 +470,8 @@ static void stm32mp1_wait_operating_mode(struct ddr_info *priv, uint32_t mode) } } - VERBOSE("[0x%x] stat = 0x%x\n", - (uint32_t)&priv->ctl->stat, stat); + VERBOSE("[0x%lx] stat = 0x%x\n", + (uintptr_t)&priv->ctl->stat, stat); } /* Mode Register Writes (MRW or MRS) */ @@ -459,7 +488,7 @@ static void stm32mp1_mode_register_write(struct ddr_info *priv, uint8_t addr, * No write should be performed to MRCTRL0 and MRCTRL1 * if MRSTAT.mr_wr_busy = 1. */ - while ((mmio_read_32((uint32_t)&priv->ctl->mrstat) & + while ((mmio_read_32((uintptr_t)&priv->ctl->mrstat) & DDRCTRL_MRSTAT_MR_WR_BUSY) != 0U) { ; } @@ -472,14 +501,14 @@ static void stm32mp1_mode_register_write(struct ddr_info *priv, uint8_t addr, DDRCTRL_MRCTRL0_MR_RANK_ALL | (((uint32_t)addr << DDRCTRL_MRCTRL0_MR_ADDR_SHIFT) & DDRCTRL_MRCTRL0_MR_ADDR_MASK); - mmio_write_32((uint32_t)&priv->ctl->mrctrl0, mrctrl0); - VERBOSE("[0x%x] mrctrl0 = 0x%x (0x%x)\n", - (uint32_t)&priv->ctl->mrctrl0, - mmio_read_32((uint32_t)&priv->ctl->mrctrl0), mrctrl0); - mmio_write_32((uint32_t)&priv->ctl->mrctrl1, data); - VERBOSE("[0x%x] mrctrl1 = 0x%x\n", - (uint32_t)&priv->ctl->mrctrl1, - mmio_read_32((uint32_t)&priv->ctl->mrctrl1)); + mmio_write_32((uintptr_t)&priv->ctl->mrctrl0, mrctrl0); + VERBOSE("[0x%lx] mrctrl0 = 0x%x (0x%x)\n", + (uintptr_t)&priv->ctl->mrctrl0, + mmio_read_32((uintptr_t)&priv->ctl->mrctrl0), mrctrl0); + mmio_write_32((uintptr_t)&priv->ctl->mrctrl1, data); + VERBOSE("[0x%lx] mrctrl1 = 0x%x\n", + (uintptr_t)&priv->ctl->mrctrl1, + mmio_read_32((uintptr_t)&priv->ctl->mrctrl1)); /* * 3. In a separate APB transaction, write the MRCTRL0.mr_wr to 1. This @@ -489,22 +518,22 @@ static void stm32mp1_mode_register_write(struct ddr_info *priv, uint8_t addr, * initiated until it is deasserted. */ mrctrl0 |= DDRCTRL_MRCTRL0_MR_WR; - mmio_write_32((uint32_t)&priv->ctl->mrctrl0, mrctrl0); + mmio_write_32((uintptr_t)&priv->ctl->mrctrl0, mrctrl0); - while ((mmio_read_32((uint32_t)&priv->ctl->mrstat) & + while ((mmio_read_32((uintptr_t)&priv->ctl->mrstat) & DDRCTRL_MRSTAT_MR_WR_BUSY) != 0U) { ; } - VERBOSE("[0x%x] mrctrl0 = 0x%x\n", - (uint32_t)&priv->ctl->mrctrl0, mrctrl0); + VERBOSE("[0x%lx] mrctrl0 = 0x%x\n", + (uintptr_t)&priv->ctl->mrctrl0, mrctrl0); } /* Switch DDR3 from DLL-on to DLL-off */ static void stm32mp1_ddr3_dll_off(struct ddr_info *priv) { - uint32_t mr1 = mmio_read_32((uint32_t)&priv->phy->mr1); - uint32_t mr2 = mmio_read_32((uint32_t)&priv->phy->mr2); + uint32_t mr1 = mmio_read_32((uintptr_t)&priv->phy->mr1); + uint32_t mr2 = mmio_read_32((uintptr_t)&priv->phy->mr2); uint32_t dbgcam; VERBOSE("mr1: 0x%x\n", mr1); @@ -514,10 +543,10 @@ static void stm32mp1_ddr3_dll_off(struct ddr_info *priv) * 1. Set the DBG1.dis_hif = 1. * This prevents further reads/writes being received on the HIF. */ - mmio_setbits_32((uint32_t)&priv->ctl->dbg1, DDRCTRL_DBG1_DIS_HIF); - VERBOSE("[0x%x] dbg1 = 0x%x\n", - (uint32_t)&priv->ctl->dbg1, - mmio_read_32((uint32_t)&priv->ctl->dbg1)); + mmio_setbits_32((uintptr_t)&priv->ctl->dbg1, DDRCTRL_DBG1_DIS_HIF); + VERBOSE("[0x%lx] dbg1 = 0x%x\n", + (uintptr_t)&priv->ctl->dbg1, + mmio_read_32((uintptr_t)&priv->ctl->dbg1)); /* * 2. Ensure all commands have been flushed from the uMCTL2 by polling @@ -528,9 +557,9 @@ static void stm32mp1_ddr3_dll_off(struct ddr_info *priv) * DBGCAM.dbg_hpr_q_depth = 0. */ do { - dbgcam = mmio_read_32((uint32_t)&priv->ctl->dbgcam); - VERBOSE("[0x%x] dbgcam = 0x%x\n", - (uint32_t)&priv->ctl->dbgcam, dbgcam); + dbgcam = mmio_read_32((uintptr_t)&priv->ctl->dbgcam); + VERBOSE("[0x%lx] dbgcam = 0x%x\n", + (uintptr_t)&priv->ctl->dbgcam, dbgcam); } while ((((dbgcam & DDRCTRL_DBGCAM_DATA_PIPELINE_EMPTY) == DDRCTRL_DBGCAM_DATA_PIPELINE_EMPTY)) && ((dbgcam & DDRCTRL_DBGCAM_DBG_Q_DEPTH) == 0U)); @@ -574,11 +603,11 @@ static void stm32mp1_ddr3_dll_off(struct ddr_info *priv) * PWRCTL.selfref_sw = 1, and polling STAT.operating_mode to ensure * the DDRC has entered self-refresh. */ - mmio_setbits_32((uint32_t)&priv->ctl->pwrctl, + mmio_setbits_32((uintptr_t)&priv->ctl->pwrctl, DDRCTRL_PWRCTL_SELFREF_SW); - VERBOSE("[0x%x] pwrctl = 0x%x\n", - (uint32_t)&priv->ctl->pwrctl, - mmio_read_32((uint32_t)&priv->ctl->pwrctl)); + VERBOSE("[0x%lx] pwrctl = 0x%x\n", + (uintptr_t)&priv->ctl->pwrctl, + mmio_read_32((uintptr_t)&priv->ctl->pwrctl)); /* * 8. Wait until STAT.operating_mode[1:0]==11 indicating that the @@ -594,10 +623,10 @@ static void stm32mp1_ddr3_dll_off(struct ddr_info *priv) */ stm32mp1_start_sw_done(priv->ctl); - mmio_setbits_32((uint32_t)&priv->ctl->mstr, DDRCTRL_MSTR_DLL_OFF_MODE); - VERBOSE("[0x%x] mstr = 0x%x\n", - (uint32_t)&priv->ctl->mstr, - mmio_read_32((uint32_t)&priv->ctl->mstr)); + mmio_setbits_32((uintptr_t)&priv->ctl->mstr, DDRCTRL_MSTR_DLL_OFF_MODE); + VERBOSE("[0x%lx] mstr = 0x%x\n", + (uintptr_t)&priv->ctl->mstr, + mmio_read_32((uintptr_t)&priv->ctl->mstr)); stm32mp1_wait_sw_done_ack(priv->ctl); @@ -611,26 +640,26 @@ static void stm32mp1_ddr3_dll_off(struct ddr_info *priv) /* Change Bypass Mode Frequency Range */ if (stm32mp1_clk_get_rate(DDRPHYC) < 100000000U) { - mmio_clrbits_32((uint32_t)&priv->phy->dllgcr, + mmio_clrbits_32((uintptr_t)&priv->phy->dllgcr, DDRPHYC_DLLGCR_BPS200); } else { - mmio_setbits_32((uint32_t)&priv->phy->dllgcr, + mmio_setbits_32((uintptr_t)&priv->phy->dllgcr, DDRPHYC_DLLGCR_BPS200); } - mmio_setbits_32((uint32_t)&priv->phy->acdllcr, DDRPHYC_ACDLLCR_DLLDIS); + mmio_setbits_32((uintptr_t)&priv->phy->acdllcr, DDRPHYC_ACDLLCR_DLLDIS); - mmio_setbits_32((uint32_t)&priv->phy->dx0dllcr, + mmio_setbits_32((uintptr_t)&priv->phy->dx0dllcr, DDRPHYC_DXNDLLCR_DLLDIS); - mmio_setbits_32((uint32_t)&priv->phy->dx1dllcr, + mmio_setbits_32((uintptr_t)&priv->phy->dx1dllcr, DDRPHYC_DXNDLLCR_DLLDIS); - mmio_setbits_32((uint32_t)&priv->phy->dx2dllcr, + mmio_setbits_32((uintptr_t)&priv->phy->dx2dllcr, DDRPHYC_DXNDLLCR_DLLDIS); - mmio_setbits_32((uint32_t)&priv->phy->dx3dllcr, + mmio_setbits_32((uintptr_t)&priv->phy->dx3dllcr, DDRPHYC_DXNDLLCR_DLLDIS); /* 12. Exit the self-refresh state by setting PWRCTL.selfref_sw = 0. */ - mmio_clrbits_32((uint32_t)&priv->ctl->pwrctl, + mmio_clrbits_32((uintptr_t)&priv->ctl->pwrctl, DDRCTRL_PWRCTL_SELFREF_SW); stm32mp1_wait_operating_mode(priv, DDRCTRL_STAT_OPERATING_MODE_NORMAL); @@ -646,20 +675,20 @@ static void stm32mp1_ddr3_dll_off(struct ddr_info *priv) */ /* 15. Write DBG1.dis_hif = 0 to re-enable reads and writes. */ - mmio_clrbits_32((uint32_t)&priv->ctl->dbg1, DDRCTRL_DBG1_DIS_HIF); - VERBOSE("[0x%x] dbg1 = 0x%x\n", - (uint32_t)&priv->ctl->dbg1, - mmio_read_32((uint32_t)&priv->ctl->dbg1)); + mmio_clrbits_32((uintptr_t)&priv->ctl->dbg1, DDRCTRL_DBG1_DIS_HIF); + VERBOSE("[0x%lx] dbg1 = 0x%x\n", + (uintptr_t)&priv->ctl->dbg1, + mmio_read_32((uintptr_t)&priv->ctl->dbg1)); } static void stm32mp1_refresh_disable(struct stm32mp1_ddrctl *ctl) { stm32mp1_start_sw_done(ctl); /* Quasi-dynamic register update*/ - mmio_setbits_32((uint32_t)&ctl->rfshctl3, + mmio_setbits_32((uintptr_t)&ctl->rfshctl3, DDRCTRL_RFSHCTL3_DIS_AUTO_REFRESH); - mmio_clrbits_32((uint32_t)&ctl->pwrctl, DDRCTRL_PWRCTL_POWERDOWN_EN); - mmio_clrbits_32((uint32_t)&ctl->dfimisc, + mmio_clrbits_32((uintptr_t)&ctl->pwrctl, DDRCTRL_PWRCTL_POWERDOWN_EN); + mmio_clrbits_32((uintptr_t)&ctl->dfimisc, DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN); stm32mp1_wait_sw_done_ack(ctl); } @@ -669,14 +698,14 @@ static void stm32mp1_refresh_restore(struct stm32mp1_ddrctl *ctl, { stm32mp1_start_sw_done(ctl); if ((rfshctl3 & DDRCTRL_RFSHCTL3_DIS_AUTO_REFRESH) == 0U) { - mmio_clrbits_32((uint32_t)&ctl->rfshctl3, + mmio_clrbits_32((uintptr_t)&ctl->rfshctl3, DDRCTRL_RFSHCTL3_DIS_AUTO_REFRESH); } if ((pwrctl & DDRCTRL_PWRCTL_POWERDOWN_EN) != 0U) { - mmio_setbits_32((uint32_t)&ctl->pwrctl, + mmio_setbits_32((uintptr_t)&ctl->pwrctl, DDRCTRL_PWRCTL_POWERDOWN_EN); } - mmio_setbits_32((uint32_t)&ctl->dfimisc, + mmio_setbits_32((uintptr_t)&ctl->dfimisc, DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN); stm32mp1_wait_sw_done_ack(ctl); } @@ -694,12 +723,14 @@ void stm32mp1_ddr_init(struct ddr_info *priv, struct stm32mp1_ddr_config *config) { uint32_t pir; - int ret; + int ret = -EINVAL; if ((config->c_reg.mstr & DDRCTRL_MSTR_DDR3) != 0U) { ret = board_ddr_power_init(STM32MP_DDR3); - } else { + } else if ((config->c_reg.mstr & DDRCTRL_MSTR_LPDDR2) != 0U) { ret = board_ddr_power_init(STM32MP_LPDDR2); + } else { + ERROR("DDR type not supported\n"); } if (ret != 0) { @@ -707,7 +738,7 @@ void stm32mp1_ddr_init(struct ddr_info *priv, } VERBOSE("name = %s\n", config->info.name); - VERBOSE("speed = %d MHz\n", config->info.speed); + VERBOSE("speed = %d kHz\n", config->info.speed); VERBOSE("size = 0x%x\n", config->info.size); /* DDR INIT SEQUENCE */ @@ -746,11 +777,11 @@ void stm32mp1_ddr_init(struct ddr_info *priv, /* 1.5. initialize registers ddr_umctl2 */ /* Stop uMCTL2 before PHY is ready */ - mmio_clrbits_32((uint32_t)&priv->ctl->dfimisc, + mmio_clrbits_32((uintptr_t)&priv->ctl->dfimisc, DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN); - VERBOSE("[0x%x] dfimisc = 0x%x\n", - (uint32_t)&priv->ctl->dfimisc, - mmio_read_32((uint32_t)&priv->ctl->dfimisc)); + VERBOSE("[0x%lx] dfimisc = 0x%x\n", + (uintptr_t)&priv->ctl->dfimisc, + mmio_read_32((uintptr_t)&priv->ctl->dfimisc)); set_reg(priv, REG_REG, &config->c_reg); @@ -759,23 +790,23 @@ void stm32mp1_ddr_init(struct ddr_info *priv, (DDRCTRL_MSTR_DDR3 | DDRCTRL_MSTR_DLL_OFF_MODE)) == (DDRCTRL_MSTR_DDR3 | DDRCTRL_MSTR_DLL_OFF_MODE)) { VERBOSE("deactivate DLL OFF in mstr\n"); - mmio_clrbits_32((uint32_t)&priv->ctl->mstr, + mmio_clrbits_32((uintptr_t)&priv->ctl->mstr, DDRCTRL_MSTR_DLL_OFF_MODE); - VERBOSE("[0x%x] mstr = 0x%x\n", - (uint32_t)&priv->ctl->mstr, - mmio_read_32((uint32_t)&priv->ctl->mstr)); + VERBOSE("[0x%lx] mstr = 0x%x\n", + (uintptr_t)&priv->ctl->mstr, + mmio_read_32((uintptr_t)&priv->ctl->mstr)); } set_reg(priv, REG_TIMING, &config->c_timing); set_reg(priv, REG_MAP, &config->c_map); /* Skip CTRL init, SDRAM init is done by PHY PUBL */ - mmio_clrsetbits_32((uint32_t)&priv->ctl->init0, + mmio_clrsetbits_32((uintptr_t)&priv->ctl->init0, DDRCTRL_INIT0_SKIP_DRAM_INIT_MASK, DDRCTRL_INIT0_SKIP_DRAM_INIT_NORMAL); - VERBOSE("[0x%x] init0 = 0x%x\n", - (uint32_t)&priv->ctl->init0, - mmio_read_32((uint32_t)&priv->ctl->init0)); + VERBOSE("[0x%lx] init0 = 0x%x\n", + (uintptr_t)&priv->ctl->init0, + mmio_read_32((uintptr_t)&priv->ctl->init0)); set_reg(priv, REG_PERF, &config->c_perf); @@ -797,10 +828,10 @@ void stm32mp1_ddr_init(struct ddr_info *priv, (DDRCTRL_MSTR_DDR3 | DDRCTRL_MSTR_DLL_OFF_MODE)) == (DDRCTRL_MSTR_DDR3 | DDRCTRL_MSTR_DLL_OFF_MODE)) { VERBOSE("deactivate DLL OFF in mr1\n"); - mmio_clrbits_32((uint32_t)&priv->phy->mr1, BIT(0)); - VERBOSE("[0x%x] mr1 = 0x%x\n", - (uint32_t)&priv->phy->mr1, - mmio_read_32((uint32_t)&priv->phy->mr1)); + mmio_clrbits_32((uintptr_t)&priv->phy->mr1, BIT(0)); + VERBOSE("[0x%lx] mr1 = 0x%x\n", + (uintptr_t)&priv->phy->mr1, + mmio_read_32((uintptr_t)&priv->phy->mr1)); } /* @@ -830,11 +861,11 @@ void stm32mp1_ddr_init(struct ddr_info *priv, */ stm32mp1_start_sw_done(priv->ctl); - mmio_setbits_32((uint32_t)&priv->ctl->dfimisc, + mmio_setbits_32((uintptr_t)&priv->ctl->dfimisc, DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN); - VERBOSE("[0x%x] dfimisc = 0x%x\n", - (uint32_t)&priv->ctl->dfimisc, - mmio_read_32((uint32_t)&priv->ctl->dfimisc)); + VERBOSE("[0x%lx] dfimisc = 0x%x\n", + (uintptr_t)&priv->ctl->dfimisc, + mmio_read_32((uintptr_t)&priv->ctl->dfimisc)); stm32mp1_wait_sw_done_ack(priv->ctl); @@ -884,14 +915,16 @@ void stm32mp1_ddr_init(struct ddr_info *priv, config->c_reg.pwrctl); /* Enable uMCTL2 AXI port 0 */ - mmio_setbits_32((uint32_t)&priv->ctl->pctrl_0, DDRCTRL_PCTRL_N_PORT_EN); - VERBOSE("[0x%x] pctrl_0 = 0x%x\n", - (uint32_t)&priv->ctl->pctrl_0, - mmio_read_32((uint32_t)&priv->ctl->pctrl_0)); + mmio_setbits_32((uintptr_t)&priv->ctl->pctrl_0, + DDRCTRL_PCTRL_N_PORT_EN); + VERBOSE("[0x%lx] pctrl_0 = 0x%x\n", + (uintptr_t)&priv->ctl->pctrl_0, + mmio_read_32((uintptr_t)&priv->ctl->pctrl_0)); /* Enable uMCTL2 AXI port 1 */ - mmio_setbits_32((uint32_t)&priv->ctl->pctrl_1, DDRCTRL_PCTRL_N_PORT_EN); - VERBOSE("[0x%x] pctrl_1 = 0x%x\n", - (uint32_t)&priv->ctl->pctrl_1, - mmio_read_32((uint32_t)&priv->ctl->pctrl_1)); + mmio_setbits_32((uintptr_t)&priv->ctl->pctrl_1, + DDRCTRL_PCTRL_N_PORT_EN); + VERBOSE("[0x%lx] pctrl_1 = 0x%x\n", + (uintptr_t)&priv->ctl->pctrl_1, + mmio_read_32((uintptr_t)&priv->ctl->pctrl_1)); } diff --git a/drivers/st/ddr/stm32mp1_ram.c b/drivers/st/ddr/stm32mp1_ram.c index 127b6c7c1c85ea08107a2c54ccd2d876f993bb6e..e65fbeaa2692f093c820376caa609a75d02a5f14 100644 --- a/drivers/st/ddr/stm32mp1_ram.c +++ b/drivers/st/ddr/stm32mp1_ram.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018, STMicroelectronics - All Rights Reserved + * Copyright (C) 2018-2019, STMicroelectronics - All Rights Reserved * * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */ @@ -25,7 +25,7 @@ static struct ddr_info ddr_priv_data; -int stm32mp1_ddr_clk_enable(struct ddr_info *priv, uint16_t mem_speed) +int stm32mp1_ddr_clk_enable(struct ddr_info *priv, uint32_t mem_speed) { unsigned long ddrphy_clk, ddr_clk, mem_speed_hz; @@ -33,10 +33,10 @@ int stm32mp1_ddr_clk_enable(struct ddr_info *priv, uint16_t mem_speed) ddrphy_clk = stm32mp1_clk_get_rate(DDRPHYC); - VERBOSE("DDR: mem_speed (%d MHz), RCC %ld MHz\n", - mem_speed, ddrphy_clk / 1000U / 1000U); + VERBOSE("DDR: mem_speed (%d kHz), RCC %ld kHz\n", + mem_speed, ddrphy_clk / 1000U); - mem_speed_hz = (uint32_t)mem_speed * 1000U * 1000U; + mem_speed_hz = mem_speed * 1000U; /* Max 10% frequency delta */ if (ddrphy_clk > mem_speed_hz) { @@ -44,9 +44,9 @@ int stm32mp1_ddr_clk_enable(struct ddr_info *priv, uint16_t mem_speed) } else { ddr_clk = mem_speed_hz - ddrphy_clk; } - if (ddr_clk > mem_speed_hz) { - ERROR("DDR expected freq %d MHz, current is %ld MHz\n", - mem_speed, ddrphy_clk / 1000U / 1000U); + if (ddr_clk > (mem_speed_hz / 10)) { + ERROR("DDR expected freq %d kHz, current is %ld kHz\n", + mem_speed, ddrphy_clk / 1000U); return -1; } return 0; @@ -208,11 +208,16 @@ static int stm32mp1_ddr_setup(void) return -EINVAL; } - config.info.speed = - (uint16_t)fdt_read_uint32_default(node, "st,mem-speed", - STM32MP1_DDR_SPEED_DFLT); - config.info.size = fdt_read_uint32_default(node, "st,mem-size", - STM32MP1_DDR_SIZE_DFLT); + config.info.speed = fdt_read_uint32_default(node, "st,mem-speed", 0); + if (!config.info.speed) { + VERBOSE("%s: no st,mem-speed\n", __func__); + return -EINVAL; + } + config.info.size = fdt_read_uint32_default(node, "st,mem-size", 0); + if (!config.info.size) { + VERBOSE("%s: no st,mem-size\n", __func__); + return -EINVAL; + } config.info.name = fdt_getprop(fdt, node, "st,mem-name", &len); if (config.info.name == NULL) { VERBOSE("%s: no st,mem-name\n", __func__); @@ -222,7 +227,7 @@ static int stm32mp1_ddr_setup(void) for (idx = 0; idx < ARRAY_SIZE(param); idx++) { ret = fdt_read_uint32_array(node, param[idx].name, - (void *)((uint32_t)&config + + (void *)((uintptr_t)&config + param[idx].offset), param[idx].size); @@ -261,8 +266,8 @@ static int stm32mp1_ddr_setup(void) VERBOSE("%s : ram size(%x, %x)\n", __func__, (uint32_t)priv->info.base, (uint32_t)priv->info.size); - dcsw_op_all(DC_OP_CISW); write_sctlr(read_sctlr() & ~SCTLR_C_BIT); + dcsw_op_all(DC_OP_CISW); uret = ddr_test_data_bus(); if (uret != 0U) { diff --git a/drivers/st/gpio/stm32_gpio.c b/drivers/st/gpio/stm32_gpio.c index 9591e3738d3d922ce450dbbd50c62e78ee3731b6..d217c4501b6f8ca8d0b041211726440aff959b77 100644 --- a/drivers/st/gpio/stm32_gpio.c +++ b/drivers/st/gpio/stm32_gpio.c @@ -1,87 +1,276 @@ /* - * Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved + * Copyright (c) 2016-2019, STMicroelectronics - All Rights Reserved * * SPDX-License-Identifier: BSD-3-Clause */ +#include +#include #include +#include + +#include + #include #include #include +#include +#include #include +#include -static bool check_gpio(uint32_t bank, uint32_t pin) +#define DT_GPIO_BANK_SHIFT 12 +#define DT_GPIO_BANK_MASK GENMASK(16, 12) +#define DT_GPIO_PIN_SHIFT 8 +#define DT_GPIO_PIN_MASK GENMASK(11, 8) +#define DT_GPIO_MODE_MASK GENMASK(7, 0) + +/******************************************************************************* + * This function gets GPIO bank node in DT. + * Returns node offset if status is okay in DT, else return 0 + ******************************************************************************/ +static int ckeck_gpio_bank(void *fdt, uint32_t bank, int pinctrl_node) { - if (pin > GPIO_PIN_MAX) { - ERROR("%s: wrong pin number (%d)\n", __func__, pin); - return false; - } + int pinctrl_subnode; + uint32_t bank_offset = stm32_get_gpio_bank_offset(bank); - if ((bank > GPIO_BANK_K) && (bank != GPIO_BANK_Z)) { - ERROR("%s: wrong GPIO bank number (%d)\n", __func__, bank); - return false; + fdt_for_each_subnode(pinctrl_subnode, fdt, pinctrl_node) { + const fdt32_t *cuint; + + if (fdt_getprop(fdt, pinctrl_subnode, + "gpio-controller", NULL) == NULL) { + continue; + } + + cuint = fdt_getprop(fdt, pinctrl_subnode, "reg", NULL); + if (cuint == NULL) { + continue; + } + + if ((fdt32_to_cpu(*cuint) == bank_offset) && + (fdt_get_status(pinctrl_subnode) != DT_DISABLED)) { + return pinctrl_subnode; + } } - return true; + return 0; } -void set_gpio(uint32_t bank, uint32_t pin, uint32_t mode, uint32_t speed, - uint32_t pull, uint32_t alternate) +/******************************************************************************* + * This function gets the pin settings from DT information. + * When analyze and parsing is done, set the GPIO registers. + * Returns 0 on success and a negative FDT error code on failure. + ******************************************************************************/ +static int dt_set_gpio_config(void *fdt, int node, uint8_t status) { - volatile uint32_t bank_address; + const fdt32_t *cuint, *slewrate; + int len; + int pinctrl_node; + uint32_t i; + uint32_t speed = GPIO_SPEED_LOW; + uint32_t pull = GPIO_NO_PULL; - if (!check_gpio(bank, pin)) { - return; + cuint = fdt_getprop(fdt, node, "pinmux", &len); + if (cuint == NULL) { + return -FDT_ERR_NOTFOUND; } - if (bank == GPIO_BANK_Z) { - bank_address = STM32_GPIOZ_BANK; + pinctrl_node = fdt_parent_offset(fdt, fdt_parent_offset(fdt, node)); + if (pinctrl_node < 0) { + return -FDT_ERR_NOTFOUND; + } + + slewrate = fdt_getprop(fdt, node, "slew-rate", NULL); + if (slewrate != NULL) { + speed = fdt32_to_cpu(*slewrate); + } + + if (fdt_getprop(fdt, node, "bias-pull-up", NULL) != NULL) { + pull = GPIO_PULL_UP; + } else if (fdt_getprop(fdt, node, "bias-pull-down", NULL) != NULL) { + pull = GPIO_PULL_DOWN; } else { - bank_address = STM32_GPIOA_BANK + - (bank * STM32_GPIO_BANK_OFFSET); + VERBOSE("No bias configured in node %d\n", node); + } + + for (i = 0U; i < ((uint32_t)len / sizeof(uint32_t)); i++) { + uint32_t pincfg; + uint32_t bank; + uint32_t pin; + uint32_t mode; + uint32_t alternate = GPIO_ALTERNATE_(0); + int bank_node; + int clk; + + pincfg = fdt32_to_cpu(*cuint); + cuint++; + + bank = (pincfg & DT_GPIO_BANK_MASK) >> DT_GPIO_BANK_SHIFT; + + pin = (pincfg & DT_GPIO_PIN_MASK) >> DT_GPIO_PIN_SHIFT; + + mode = pincfg & DT_GPIO_MODE_MASK; + + switch (mode) { + case 0: + mode = GPIO_MODE_INPUT; + break; + case 1 ... 16: + alternate = mode - 1U; + mode = GPIO_MODE_ALTERNATE; + break; + case 17: + mode = GPIO_MODE_ANALOG; + break; + default: + mode = GPIO_MODE_OUTPUT; + break; + } + + if (fdt_getprop(fdt, node, "drive-open-drain", NULL) != NULL) { + mode |= GPIO_OPEN_DRAIN; + } + + bank_node = ckeck_gpio_bank(fdt, bank, pinctrl_node); + if (bank_node == 0) { + ERROR("PINCTRL inconsistent in DT\n"); + panic(); + } + + clk = fdt_get_clock_id(bank_node); + if (clk < 0) { + return -FDT_ERR_NOTFOUND; + } + + /* Platform knows the clock: assert it is okay */ + assert((unsigned long)clk == stm32_get_gpio_bank_clock(bank)); + + set_gpio(bank, pin, mode, speed, pull, alternate, status); + } + + return 0; +} + +/******************************************************************************* + * This function gets the pin settings from DT information. + * When analyze and parsing is done, set the GPIO registers. + * Returns 0 on success and a negative FDT/ERRNO error code on failure. + ******************************************************************************/ +int dt_set_pinctrl_config(int node) +{ + const fdt32_t *cuint; + int lenp = 0; + uint32_t i; + uint8_t status = fdt_get_status(node); + void *fdt; + + if (fdt_get_address(&fdt) == 0) { + return -ENOENT; + } + + if (status == DT_DISABLED) { + return -FDT_ERR_NOTFOUND; + } + + cuint = fdt_getprop(fdt, node, "pinctrl-0", &lenp); + if (cuint == NULL) { + return -FDT_ERR_NOTFOUND; } - mmio_clrbits_32(bank_address + GPIO_MODE_OFFSET, + for (i = 0; i < ((uint32_t)lenp / 4U); i++) { + int p_node, p_subnode; + + p_node = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint)); + if (p_node < 0) { + return -FDT_ERR_NOTFOUND; + } + + fdt_for_each_subnode(p_subnode, fdt, p_node) { + int ret = dt_set_gpio_config(fdt, p_subnode, status); + + if (ret < 0) { + return ret; + } + } + + cuint++; + } + + return 0; +} + +void set_gpio(uint32_t bank, uint32_t pin, uint32_t mode, uint32_t speed, + uint32_t pull, uint32_t alternate, uint8_t status) +{ + uintptr_t base = stm32_get_gpio_bank_base(bank); + unsigned long clock = stm32_get_gpio_bank_clock(bank); + + assert(pin <= GPIO_PIN_MAX); + + stm32mp1_clk_enable(clock); + + mmio_clrbits_32(base + GPIO_MODE_OFFSET, ((uint32_t)GPIO_MODE_MASK << (pin << 1))); - mmio_setbits_32(bank_address + GPIO_MODE_OFFSET, + mmio_setbits_32(base + GPIO_MODE_OFFSET, (mode & ~GPIO_OPEN_DRAIN) << (pin << 1)); if ((mode & GPIO_OPEN_DRAIN) != 0U) { - mmio_setbits_32(bank_address + GPIO_TYPE_OFFSET, - BIT(pin)); + mmio_setbits_32(base + GPIO_TYPE_OFFSET, BIT(pin)); + } else { + mmio_clrbits_32(base + GPIO_TYPE_OFFSET, BIT(pin)); } - mmio_clrbits_32(bank_address + GPIO_SPEED_OFFSET, + mmio_clrbits_32(base + GPIO_SPEED_OFFSET, ((uint32_t)GPIO_SPEED_MASK << (pin << 1))); - mmio_setbits_32(bank_address + GPIO_SPEED_OFFSET, speed << (pin << 1)); + mmio_setbits_32(base + GPIO_SPEED_OFFSET, speed << (pin << 1)); - mmio_clrbits_32(bank_address + GPIO_PUPD_OFFSET, + mmio_clrbits_32(base + GPIO_PUPD_OFFSET, ((uint32_t)GPIO_PULL_MASK << (pin << 1))); - mmio_setbits_32(bank_address + GPIO_PUPD_OFFSET, pull << (pin << 1)); + mmio_setbits_32(base + GPIO_PUPD_OFFSET, pull << (pin << 1)); if (pin < GPIO_ALT_LOWER_LIMIT) { - mmio_clrbits_32(bank_address + GPIO_AFRL_OFFSET, + mmio_clrbits_32(base + GPIO_AFRL_OFFSET, ((uint32_t)GPIO_ALTERNATE_MASK << (pin << 2))); - mmio_setbits_32(bank_address + GPIO_AFRL_OFFSET, + mmio_setbits_32(base + GPIO_AFRL_OFFSET, alternate << (pin << 2)); } else { - mmio_clrbits_32(bank_address + GPIO_AFRH_OFFSET, + mmio_clrbits_32(base + GPIO_AFRH_OFFSET, ((uint32_t)GPIO_ALTERNATE_MASK << ((pin - GPIO_ALT_LOWER_LIMIT) << 2))); - mmio_setbits_32(bank_address + GPIO_AFRH_OFFSET, + mmio_setbits_32(base + GPIO_AFRH_OFFSET, alternate << ((pin - GPIO_ALT_LOWER_LIMIT) << 2)); } VERBOSE("GPIO %u mode set to 0x%x\n", bank, - mmio_read_32(bank_address + GPIO_MODE_OFFSET)); + mmio_read_32(base + GPIO_MODE_OFFSET)); VERBOSE("GPIO %u speed set to 0x%x\n", bank, - mmio_read_32(bank_address + GPIO_SPEED_OFFSET)); + mmio_read_32(base + GPIO_SPEED_OFFSET)); VERBOSE("GPIO %u mode pull to 0x%x\n", bank, - mmio_read_32(bank_address + GPIO_PUPD_OFFSET)); + mmio_read_32(base + GPIO_PUPD_OFFSET)); VERBOSE("GPIO %u mode alternate low to 0x%x\n", bank, - mmio_read_32(bank_address + GPIO_AFRL_OFFSET)); + mmio_read_32(base + GPIO_AFRL_OFFSET)); VERBOSE("GPIO %u mode alternate high to 0x%x\n", bank, - mmio_read_32(bank_address + GPIO_AFRH_OFFSET)); + mmio_read_32(base + GPIO_AFRH_OFFSET)); + + stm32mp1_clk_disable((unsigned long)clock); +} + +void set_gpio_secure_cfg(uint32_t bank, uint32_t pin, bool secure) +{ + uintptr_t base = stm32_get_gpio_bank_base(bank); + int clock = stm32_get_gpio_bank_clock(bank); + + assert(pin <= GPIO_PIN_MAX); + + stm32mp1_clk_enable((unsigned long)clock); + + if (secure) { + mmio_setbits_32(base + GPIO_SECR_OFFSET, BIT(pin)); + } else { + mmio_clrbits_32(base + GPIO_SECR_OFFSET, BIT(pin)); + } + + stm32mp1_clk_disable((unsigned long)clock); } diff --git a/drivers/st/pmic/stm32_i2c.c b/drivers/st/i2c/stm32_i2c.c similarity index 99% rename from drivers/st/pmic/stm32_i2c.c rename to drivers/st/i2c/stm32_i2c.c index f861ba29634a42fd47a56e2258aedbfb385a3d00..2be7afe2df5bb5c296fa6f30f1c811dce15a9d7b 100644 --- a/drivers/st/pmic/stm32_i2c.c +++ b/drivers/st/i2c/stm32_i2c.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved + * Copyright (c) 2016-2019, STMicroelectronics - All Rights Reserved * * SPDX-License-Identifier: BSD-3-Clause */ diff --git a/drivers/st/io/io_stm32image.c b/drivers/st/io/io_stm32image.c index 0164a2d43da4688fe9d647aa88fdc32e7caedc59..dc2977d5a62a570e0269ff71af70c743eff80ffd 100644 --- a/drivers/st/io/io_stm32image.c +++ b/drivers/st/io/io_stm32image.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -94,6 +94,8 @@ static int stm32image_dev_open(const uintptr_t init_params, for (i = 0; i < STM32_PART_NUM; i++) { memcpy(stm32image_dev.part_info[i].name, device_info->part_info[i].name, MAX_PART_NAME_SIZE); + stm32image_dev.part_info[i].binary_type = + device_info->part_info[i].binary_type; stm32image_dev.part_info[i].part_offset = device_info->part_info[i].part_offset; stm32image_dev.part_info[i].bkp_offset = @@ -193,21 +195,29 @@ static int stm32image_partition_size(io_entity_t *entity, size_t *length) result = io_read(backend_handle, (uintptr_t)header, MAX_LBA_SIZE, (size_t *)&bytes_read); if (result != 0) { - ERROR("%s: io_read (%i)\n", __func__, result); - break; + if (current_part->bkp_offset == 0U) { + ERROR("%s: io_read (%i)\n", __func__, result); + } + header->magic = 0; } if ((header->magic != BOOT_API_IMAGE_HEADER_MAGIC_NB) || (header->binary_type != current_part->binary_type) || (header->image_length >= stm32image_dev.device_size)) { - WARN("%s: partition %s wrong header\n", - __func__, current_part->name); + VERBOSE("%s: partition %s not found at %x\n", + __func__, current_part->name, *stm32_img); + + if (current_part->bkp_offset == 0U) { + result = -ENOMEM; + break; + } /* Header not correct, check next offset for backup */ *stm32_img += current_part->bkp_offset; if (*stm32_img > stm32image_dev.device_size) { /* No backup found, end of device reached */ - WARN("Out of memory\n"); + WARN("%s : partition %s not found\n", + __func__, current_part->name); result = -ENOMEM; break; } @@ -221,9 +231,13 @@ static int stm32image_partition_size(io_entity_t *entity, size_t *length) return result; } - *length = header->image_length; + if (header->image_length < stm32image_dev.lba_size) { + *length = stm32image_dev.lba_size; + } else { + *length = header->image_length; + } - INFO("STM32 Image size : %i\n", *length); + INFO("STM32 Image size : %lu\n", (unsigned long)*length); return 0; } @@ -266,11 +280,10 @@ static int check_header(boot_api_image_header_t *header, uintptr_t buffer) static int stm32image_partition_read(io_entity_t *entity, uintptr_t buffer, size_t length, size_t *length_read) { - int result = 0, offset, local_length = 0; + int result = 0; uint8_t *local_buffer = (uint8_t *)buffer; boot_api_image_header_t *header = (boot_api_image_header_t *)first_lba_buffer; - uintptr_t backend_handle; assert(entity != NULL); assert(buffer != 0U); @@ -279,8 +292,17 @@ static int stm32image_partition_read(io_entity_t *entity, uintptr_t buffer, *length_read = 0U; while (*length_read == 0U) { + int offset; + int local_length; + uintptr_t backend_handle; + if (header->magic != BOOT_API_IMAGE_HEADER_MAGIC_NB) { /* Check for backup as image is corrupted */ + if (current_part->bkp_offset == 0U) { + result = -ENOMEM; + break; + } + *stm32_img += current_part->bkp_offset; if (*stm32_img >= stm32image_dev.device_size) { /* End of device reached */ @@ -342,8 +364,8 @@ static int stm32image_partition_read(io_entity_t *entity, uintptr_t buffer, if (result != 0) { ERROR("%s: io_read (%i)\n", __func__, result); *length_read = 0; - io_close(backend_handle); - break; + header->magic = 0; + continue; } result = check_header(header, buffer); @@ -351,8 +373,6 @@ static int stm32image_partition_read(io_entity_t *entity, uintptr_t buffer, ERROR("Header check failed\n"); *length_read = 0; header->magic = 0; - io_close(backend_handle); - break; } io_close(backend_handle); diff --git a/drivers/st/mmc/stm32_sdmmc2.c b/drivers/st/mmc/stm32_sdmmc2.c index 05f5ae17c9d802da9f0ad0edbb1b7cc62585992b..57812d89930b54e40b7b1f79f636570356bda8a4 100644 --- a/drivers/st/mmc/stm32_sdmmc2.c +++ b/drivers/st/mmc/stm32_sdmmc2.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, STMicroelectronics - All Rights Reserved + * Copyright (c) 2018-2019, STMicroelectronics - All Rights Reserved * * SPDX-License-Identifier: BSD-3-Clause */ @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -470,12 +471,11 @@ static int stm32_sdmmc2_prepare(int lba, uintptr_t buf, size_t size) } /* Prepare CMD 16*/ - mmio_write_32(base + SDMMC_DTIMER, UINT32_MAX); + mmio_write_32(base + SDMMC_DTIMER, 0); mmio_write_32(base + SDMMC_DLENR, 0); - mmio_clrsetbits_32(base + SDMMC_DCTRLR, - SDMMC_DCTRLR_CLEAR_MASK, SDMMC_DCTRLR_DTDIR); + mmio_write_32(base + SDMMC_DCTRLR, 0); zeromem(&cmd, sizeof(struct mmc_cmd)); @@ -643,7 +643,7 @@ static int stm32_sdmmc2_dt_get_config(void) return -FDT_ERR_NOTFOUND; } - if (fdt_check_status(sdmmc_node) == 0) { + if (fdt_get_status(sdmmc_node) == DT_DISABLED) { return -FDT_ERR_NOTFOUND; } @@ -667,15 +667,15 @@ static int stm32_sdmmc2_dt_get_config(void) cuint++; sdmmc2_params.reset_id = fdt32_to_cpu(*cuint); - if ((fdt_getprop(fdt, sdmmc_node, "st,pin-ckin", NULL)) != NULL) { + if ((fdt_getprop(fdt, sdmmc_node, "st,use-ckin", NULL)) != NULL) { sdmmc2_params.pin_ckin = SDMMC_CLKCR_SELCLKRX_0; } - if ((fdt_getprop(fdt, sdmmc_node, "st,dirpol", NULL)) != NULL) { + if ((fdt_getprop(fdt, sdmmc_node, "st,sig-dir", NULL)) != NULL) { sdmmc2_params.dirpol = SDMMC_POWER_DIRPOL; } - if ((fdt_getprop(fdt, sdmmc_node, "st,negedge", NULL)) != NULL) { + if ((fdt_getprop(fdt, sdmmc_node, "st,neg-edge", NULL)) != NULL) { sdmmc2_params.negedge = SDMMC_CLKCR_NEGEDGE; } diff --git a/drivers/st/pmic/stm32mp1_pmic.c b/drivers/st/pmic/stm32mp_pmic.c similarity index 69% rename from drivers/st/pmic/stm32mp1_pmic.c rename to drivers/st/pmic/stm32mp_pmic.c index c5bdfc07d3a1457dc570c3948e451ad5410ae357..6beabc15360f7a1853947af2143f88c36fe66761 100644 --- a/drivers/st/pmic/stm32mp1_pmic.c +++ b/drivers/st/pmic/stm32mp_pmic.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved + * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved * * SPDX-License-Identifier: BSD-3-Clause */ @@ -13,10 +13,10 @@ #include #include +#include #include #include -#include -#include +#include #include #include @@ -27,23 +27,23 @@ #define MASK_RESET_BUCK3 BIT(2) -#define STPMU1_LDO12356_OUTPUT_MASK (uint8_t)(GENMASK(6, 2)) -#define STPMU1_LDO12356_OUTPUT_SHIFT 2 -#define STPMU1_LDO3_MODE (uint8_t)(BIT(7)) -#define STPMU1_LDO3_DDR_SEL 31U -#define STPMU1_LDO3_1800000 (9U << STPMU1_LDO12356_OUTPUT_SHIFT) +#define STPMIC1_LDO12356_OUTPUT_MASK (uint8_t)(GENMASK(6, 2)) +#define STPMIC1_LDO12356_OUTPUT_SHIFT 2 +#define STPMIC1_LDO3_MODE (uint8_t)(BIT(7)) +#define STPMIC1_LDO3_DDR_SEL 31U +#define STPMIC1_LDO3_1800000 (9U << STPMIC1_LDO12356_OUTPUT_SHIFT) -#define STPMU1_BUCK_OUTPUT_SHIFT 2 -#define STPMU1_BUCK3_1V8 (39U << STPMU1_BUCK_OUTPUT_SHIFT) +#define STPMIC1_BUCK_OUTPUT_SHIFT 2 +#define STPMIC1_BUCK3_1V8 (39U << STPMIC1_BUCK_OUTPUT_SHIFT) -#define STPMU1_DEFAULT_START_UP_DELAY_MS 1 +#define STPMIC1_DEFAULT_START_UP_DELAY_MS 1 static struct i2c_handle_s i2c_handle; static uint32_t pmic_i2c_addr; static int dt_get_pmic_node(void *fdt) { - return fdt_node_offset_by_compatible(fdt, -1, "st,stpmu1"); + return fdt_node_offset_by_compatible(fdt, -1, "st,stpmic1"); } bool dt_check_pmic(void) @@ -61,7 +61,7 @@ bool dt_check_pmic(void) return false; } - return fdt_check_status(node); + return fdt_get_status(node); } static int dt_pmic_i2c_config(struct dt_node_info *i2c_info) @@ -138,16 +138,16 @@ int dt_pmic_enable_boot_on_regulators(void) voltage = (uint16_t)(fdt32_to_cpu(*cuint) / 1000U); node_name = fdt_get_name(fdt, regulator_node, NULL); - if (stpmu1_is_regulator_enabled(node_name) == 0U) { + if (stpmic1_is_regulator_enabled(node_name) == 0U) { int status; - status = stpmu1_regulator_voltage_set(node_name, - voltage); + status = stpmic1_regulator_voltage_set(node_name, + voltage); if (status != 0) { return status; } - status = stpmu1_regulator_enable(node_name); + status = stpmic1_regulator_enable(node_name); if (status != 0) { return status; } @@ -204,7 +204,7 @@ void initialize_pmic_i2c(void) panic(); } - stpmu1_bind_i2c(&i2c_handle, (uint16_t)pmic_i2c_addr); + stpmic1_bind_i2c(&i2c_handle, (uint16_t)pmic_i2c_addr); } void initialize_pmic(void) @@ -214,7 +214,7 @@ void initialize_pmic(void) initialize_pmic_i2c(); - status = stpmu1_register_read(VERSION_STATUS_REG, &read_val); + status = stpmic1_register_read(VERSION_STATUS_REG, &read_val); if (status != 0) { panic(); } @@ -222,7 +222,7 @@ void initialize_pmic(void) INFO("PMIC version = 0x%x\n", read_val); /* Keep VDD on during the reset cycle */ - status = stpmu1_register_update(MASK_RESET_BUCK_REG, + status = stpmic1_register_update(MASK_RESET_BUCK_REG, MASK_RESET_BUCK3, MASK_RESET_BUCK3); if (status != 0) { @@ -239,45 +239,46 @@ int pmic_ddr_power_init(enum ddr_type ddr_type) switch (ddr_type) { case STM32MP_DDR3: /* Set LDO3 to sync mode */ - status = stpmu1_register_read(LDO3_CONTROL_REG, &read_val); + status = stpmic1_register_read(LDO3_CONTROL_REG, &read_val); if (status != 0) { return status; } - read_val &= ~STPMU1_LDO3_MODE; - read_val &= ~STPMU1_LDO12356_OUTPUT_MASK; - read_val |= STPMU1_LDO3_DDR_SEL << STPMU1_LDO12356_OUTPUT_SHIFT; + read_val &= ~STPMIC1_LDO3_MODE; + read_val &= ~STPMIC1_LDO12356_OUTPUT_MASK; + read_val |= STPMIC1_LDO3_DDR_SEL << + STPMIC1_LDO12356_OUTPUT_SHIFT; - status = stpmu1_register_write(LDO3_CONTROL_REG, read_val); + status = stpmic1_register_write(LDO3_CONTROL_REG, read_val); if (status != 0) { return status; } - status = stpmu1_regulator_voltage_set("buck2", 1350); + status = stpmic1_regulator_voltage_set("buck2", 1350); if (status != 0) { return status; } - status = stpmu1_regulator_enable("buck2"); + status = stpmic1_regulator_enable("buck2"); if (status != 0) { return status; } - mdelay(STPMU1_DEFAULT_START_UP_DELAY_MS); + mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS); - status = stpmu1_regulator_enable("vref_ddr"); + status = stpmic1_regulator_enable("vref_ddr"); if (status != 0) { return status; } - mdelay(STPMU1_DEFAULT_START_UP_DELAY_MS); + mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS); - status = stpmu1_regulator_enable("ldo3"); + status = stpmic1_regulator_enable("ldo3"); if (status != 0) { return status; } - mdelay(STPMU1_DEFAULT_START_UP_DELAY_MS); + mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS); break; case STM32MP_LPDDR2: @@ -286,57 +287,57 @@ int pmic_ddr_power_init(enum ddr_type ddr_type) * Set LDO3 to bypass mode if BUCK3 = 1.8V * Set LDO3 to normal mode if BUCK3 != 1.8V */ - status = stpmu1_register_read(BUCK3_CONTROL_REG, &read_val); + status = stpmic1_register_read(BUCK3_CONTROL_REG, &read_val); if (status != 0) { return status; } - if ((read_val & STPMU1_BUCK3_1V8) == STPMU1_BUCK3_1V8) { + if ((read_val & STPMIC1_BUCK3_1V8) == STPMIC1_BUCK3_1V8) { buck3_at_1v8 = true; } - status = stpmu1_register_read(LDO3_CONTROL_REG, &read_val); + status = stpmic1_register_read(LDO3_CONTROL_REG, &read_val); if (status != 0) { return status; } - read_val &= ~STPMU1_LDO3_MODE; - read_val &= ~STPMU1_LDO12356_OUTPUT_MASK; - read_val |= STPMU1_LDO3_1800000; + read_val &= ~STPMIC1_LDO3_MODE; + read_val &= ~STPMIC1_LDO12356_OUTPUT_MASK; + read_val |= STPMIC1_LDO3_1800000; if (buck3_at_1v8) { - read_val |= STPMU1_LDO3_MODE; + read_val |= STPMIC1_LDO3_MODE; } - status = stpmu1_register_write(LDO3_CONTROL_REG, read_val); + status = stpmic1_register_write(LDO3_CONTROL_REG, read_val); if (status != 0) { return status; } - status = stpmu1_regulator_voltage_set("buck2", 1200); + status = stpmic1_regulator_voltage_set("buck2", 1200); if (status != 0) { return status; } - status = stpmu1_regulator_enable("ldo3"); + status = stpmic1_regulator_enable("ldo3"); if (status != 0) { return status; } - mdelay(STPMU1_DEFAULT_START_UP_DELAY_MS); + mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS); - status = stpmu1_regulator_enable("buck2"); + status = stpmic1_regulator_enable("buck2"); if (status != 0) { return status; } - mdelay(STPMU1_DEFAULT_START_UP_DELAY_MS); + mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS); - status = stpmu1_regulator_enable("vref_ddr"); + status = stpmic1_regulator_enable("vref_ddr"); if (status != 0) { return status; } - mdelay(STPMU1_DEFAULT_START_UP_DELAY_MS); + mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS); break; default: diff --git a/drivers/st/pmic/stpmu1.c b/drivers/st/pmic/stpmic1.c similarity index 52% rename from drivers/st/pmic/stpmu1.c rename to drivers/st/pmic/stpmic1.c index 9c36bf64a72cc0299cd1e780149ec4d6eefceee1..465996da93eae02ab45e47f912b961e840ace401 100644 --- a/drivers/st/pmic/stpmu1.c +++ b/drivers/st/pmic/stpmic1.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved + * Copyright (c) 2016-2019, STMicroelectronics - All Rights Reserved * * SPDX-License-Identifier: BSD-3-Clause */ @@ -7,7 +7,7 @@ #include #include -#include +#include #include struct regul_struct { @@ -16,18 +16,22 @@ struct regul_struct { uint8_t voltage_table_size; uint8_t control_reg; uint8_t low_power_reg; + uint8_t pull_down_reg; + uint8_t pull_down; + uint8_t mask_reset_reg; + uint8_t mask_reset; }; -static struct i2c_handle_s *stpmu_i2c_handle; -static uint16_t stpmu_i2c_addr; +static struct i2c_handle_s *pmic_i2c_handle; +static uint16_t pmic_i2c_addr; /* Voltage tables in mV */ static const uint16_t buck1_voltage_table[] = { - 600, - 625, - 650, - 675, - 700, + 725, + 725, + 725, + 725, + 725, 725, 750, 775, @@ -54,7 +58,39 @@ static const uint16_t buck1_voltage_table[] = { 1300, 1325, 1350, - 1350, + 1375, + 1400, + 1425, + 1450, + 1475, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, }; static const uint16_t buck2_voltage_table[] = { @@ -308,6 +344,7 @@ static const uint16_t ldo3_voltage_table[] = { 3300, 3300, 3300, + 500, 0xFFFF, /* VREFDDR */ }; @@ -389,6 +426,10 @@ static const struct regul_struct regulators_table[] = { .voltage_table_size = ARRAY_SIZE(buck1_voltage_table), .control_reg = BUCK1_CONTROL_REG, .low_power_reg = BUCK1_PWRCTRL_REG, + .pull_down_reg = BUCK_PULL_DOWN_REG, + .pull_down = BUCK1_PULL_DOWN_SHIFT, + .mask_reset_reg = MASK_RESET_BUCK_REG, + .mask_reset = BUCK1_MASK_RESET, }, { .dt_node_name = "buck2", @@ -396,6 +437,10 @@ static const struct regul_struct regulators_table[] = { .voltage_table_size = ARRAY_SIZE(buck2_voltage_table), .control_reg = BUCK2_CONTROL_REG, .low_power_reg = BUCK2_PWRCTRL_REG, + .pull_down_reg = BUCK_PULL_DOWN_REG, + .pull_down = BUCK2_PULL_DOWN_SHIFT, + .mask_reset_reg = MASK_RESET_BUCK_REG, + .mask_reset = BUCK2_MASK_RESET, }, { .dt_node_name = "buck3", @@ -403,6 +448,10 @@ static const struct regul_struct regulators_table[] = { .voltage_table_size = ARRAY_SIZE(buck3_voltage_table), .control_reg = BUCK3_CONTROL_REG, .low_power_reg = BUCK3_PWRCTRL_REG, + .pull_down_reg = BUCK_PULL_DOWN_REG, + .pull_down = BUCK3_PULL_DOWN_SHIFT, + .mask_reset_reg = MASK_RESET_BUCK_REG, + .mask_reset = BUCK3_MASK_RESET, }, { .dt_node_name = "buck4", @@ -410,6 +459,10 @@ static const struct regul_struct regulators_table[] = { .voltage_table_size = ARRAY_SIZE(buck4_voltage_table), .control_reg = BUCK4_CONTROL_REG, .low_power_reg = BUCK4_PWRCTRL_REG, + .pull_down_reg = BUCK_PULL_DOWN_REG, + .pull_down = BUCK4_PULL_DOWN_SHIFT, + .mask_reset_reg = MASK_RESET_BUCK_REG, + .mask_reset = BUCK4_MASK_RESET, }, { .dt_node_name = "ldo1", @@ -417,6 +470,8 @@ static const struct regul_struct regulators_table[] = { .voltage_table_size = ARRAY_SIZE(ldo1_voltage_table), .control_reg = LDO1_CONTROL_REG, .low_power_reg = LDO1_PWRCTRL_REG, + .mask_reset_reg = MASK_RESET_LDO_REG, + .mask_reset = LDO1_MASK_RESET, }, { .dt_node_name = "ldo2", @@ -424,6 +479,8 @@ static const struct regul_struct regulators_table[] = { .voltage_table_size = ARRAY_SIZE(ldo2_voltage_table), .control_reg = LDO2_CONTROL_REG, .low_power_reg = LDO2_PWRCTRL_REG, + .mask_reset_reg = MASK_RESET_LDO_REG, + .mask_reset = LDO2_MASK_RESET, }, { .dt_node_name = "ldo3", @@ -431,6 +488,8 @@ static const struct regul_struct regulators_table[] = { .voltage_table_size = ARRAY_SIZE(ldo3_voltage_table), .control_reg = LDO3_CONTROL_REG, .low_power_reg = LDO3_PWRCTRL_REG, + .mask_reset_reg = MASK_RESET_LDO_REG, + .mask_reset = LDO3_MASK_RESET, }, { .dt_node_name = "ldo4", @@ -438,6 +497,8 @@ static const struct regul_struct regulators_table[] = { .voltage_table_size = ARRAY_SIZE(ldo4_voltage_table), .control_reg = LDO4_CONTROL_REG, .low_power_reg = LDO4_PWRCTRL_REG, + .mask_reset_reg = MASK_RESET_LDO_REG, + .mask_reset = LDO4_MASK_RESET, }, { .dt_node_name = "ldo5", @@ -445,6 +506,8 @@ static const struct regul_struct regulators_table[] = { .voltage_table_size = ARRAY_SIZE(ldo5_voltage_table), .control_reg = LDO5_CONTROL_REG, .low_power_reg = LDO5_PWRCTRL_REG, + .mask_reset_reg = MASK_RESET_LDO_REG, + .mask_reset = LDO5_MASK_RESET, }, { .dt_node_name = "ldo6", @@ -452,6 +515,8 @@ static const struct regul_struct regulators_table[] = { .voltage_table_size = ARRAY_SIZE(ldo6_voltage_table), .control_reg = LDO6_CONTROL_REG, .low_power_reg = LDO6_PWRCTRL_REG, + .mask_reset_reg = MASK_RESET_LDO_REG, + .mask_reset = LDO6_MASK_RESET, }, { .dt_node_name = "vref_ddr", @@ -459,12 +524,14 @@ static const struct regul_struct regulators_table[] = { .voltage_table_size = ARRAY_SIZE(vref_ddr_voltage_table), .control_reg = VREF_DDR_CONTROL_REG, .low_power_reg = VREF_DDR_PWRCTRL_REG, + .mask_reset_reg = MASK_RESET_LDO_REG, + .mask_reset = VREF_DDR_MASK_RESET, }, }; -#define MAX_REGUL ARRAY_SIZE(regulators_table) +#define MAX_REGUL ARRAY_SIZE(regulators_table) -static const struct regul_struct *stpmu1_get_regulator_data(const char *name) +static const struct regul_struct *get_regulator_data(const char *name) { uint8_t i; @@ -480,10 +547,9 @@ static const struct regul_struct *stpmu1_get_regulator_data(const char *name) return NULL; } -static uint8_t stpmu1_voltage_find_index(const char *name, - uint16_t millivolts) +static uint8_t voltage_to_index(const char *name, uint16_t millivolts) { - const struct regul_struct *regul = stpmu1_get_regulator_data(name); + const struct regul_struct *regul = get_regulator_data(name); uint8_t i; for (i = 0 ; i < regul->voltage_table_size ; i++) { @@ -498,62 +564,132 @@ static uint8_t stpmu1_voltage_find_index(const char *name, return 0; } -int stpmu1_switch_off(void) +int stpmic1_powerctrl_on(void) +{ + return stpmic1_register_update(MAIN_CONTROL_REG, PWRCTRL_PIN_VALID, + PWRCTRL_PIN_VALID); +} + +int stpmic1_switch_off(void) { - return stpmu1_register_update(MAIN_CONTROL_REG, 1, - SOFTWARE_SWITCH_OFF_ENABLED); + return stpmic1_register_update(MAIN_CONTROL_REG, 1, + SOFTWARE_SWITCH_OFF_ENABLED); } -int stpmu1_regulator_enable(const char *name) +int stpmic1_regulator_enable(const char *name) { - const struct regul_struct *regul = stpmu1_get_regulator_data(name); + const struct regul_struct *regul = get_regulator_data(name); - return stpmu1_register_update(regul->control_reg, BIT(0), BIT(0)); + return stpmic1_register_update(regul->control_reg, BIT(0), BIT(0)); } -int stpmu1_regulator_disable(const char *name) +int stpmic1_regulator_disable(const char *name) { - const struct regul_struct *regul = stpmu1_get_regulator_data(name); + const struct regul_struct *regul = get_regulator_data(name); - return stpmu1_register_update(regul->control_reg, 0, BIT(0)); + return stpmic1_register_update(regul->control_reg, 0, BIT(0)); } -uint8_t stpmu1_is_regulator_enabled(const char *name) +uint8_t stpmic1_is_regulator_enabled(const char *name) { uint8_t val; - const struct regul_struct *regul = stpmu1_get_regulator_data(name); + const struct regul_struct *regul = get_regulator_data(name); - if (stpmu1_register_read(regul->control_reg, &val) != 0) { + if (stpmic1_register_read(regul->control_reg, &val) != 0) { panic(); } return (val & 0x1U); } -int stpmu1_regulator_voltage_set(const char *name, uint16_t millivolts) +int stpmic1_regulator_voltage_set(const char *name, uint16_t millivolts) +{ + uint8_t voltage_index = voltage_to_index(name, millivolts); + const struct regul_struct *regul = get_regulator_data(name); + uint8_t mask; + + /* Voltage can be set for buck or ldo (except ldo4) regulators */ + if (strncmp(name, "buck", 4) == 0) { + mask = BUCK_VOLTAGE_MASK; + } else if ((strncmp(name, "ldo", 3) == 0) && + (strncmp(name, "ldo4", 4) != 0)) { + mask = LDO_VOLTAGE_MASK; + } else { + return 0; + } + + return stpmic1_register_update(regul->control_reg, + voltage_index << LDO_BUCK_VOLTAGE_SHIFT, + mask); +} + +int stpmic1_regulator_pull_down_set(const char *name) { - uint8_t voltage_index = stpmu1_voltage_find_index(name, millivolts); - const struct regul_struct *regul = stpmu1_get_regulator_data(name); + const struct regul_struct *regul = get_regulator_data(name); - return stpmu1_register_update(regul->control_reg, voltage_index << 2, - 0xFC); + if (regul->pull_down_reg != 0) { + return stpmic1_register_update(regul->pull_down_reg, + BIT(regul->pull_down), + LDO_BUCK_PULL_DOWN_MASK << + regul->pull_down); + } + + return 0; } -int stpmu1_register_read(uint8_t register_id, uint8_t *value) +int stpmic1_regulator_mask_reset_set(const char *name) { - return stm32_i2c_mem_read(stpmu_i2c_handle, stpmu_i2c_addr, - (uint16_t)register_id, I2C_MEMADD_SIZE_8BIT, - value, 1, 100000); + const struct regul_struct *regul = get_regulator_data(name); + + return stpmic1_register_update(regul->mask_reset_reg, + BIT(regul->mask_reset), + LDO_BUCK_RESET_MASK << + regul->mask_reset); } -int stpmu1_register_write(uint8_t register_id, uint8_t value) +int stpmic1_regulator_voltage_get(const char *name) +{ + const struct regul_struct *regul = get_regulator_data(name); + uint8_t value; + uint8_t mask; + + /* Voltage can be set for buck or ldo (except ldo4) regulators */ + if (strncmp(name, "buck", 4) == 0) { + mask = BUCK_VOLTAGE_MASK; + } else if ((strncmp(name, "ldo", 3) == 0) && + (strncmp(name, "ldo4", 4) != 0)) { + mask = LDO_VOLTAGE_MASK; + } else { + return 0; + } + + if (stpmic1_register_read(regul->control_reg, &value)) + return -1; + + value = (value & mask) >> LDO_BUCK_VOLTAGE_SHIFT; + + if (value > regul->voltage_table_size) + return -1; + + return (int)regul->voltage_table[value]; +} + +int stpmic1_register_read(uint8_t register_id, uint8_t *value) +{ + return stm32_i2c_mem_read(pmic_i2c_handle, pmic_i2c_addr, + (uint16_t)register_id, I2C_MEMADD_SIZE_8BIT, + value, 1, 100000); +} + +int stpmic1_register_write(uint8_t register_id, uint8_t value) { int status; - status = stm32_i2c_mem_write(stpmu_i2c_handle, stpmu_i2c_addr, + status = stm32_i2c_mem_write(pmic_i2c_handle, pmic_i2c_addr, (uint16_t)register_id, I2C_MEMADD_SIZE_8BIT, &value, 1, 100000); +#if ENABLE_ASSERTIONS if (status != 0) { return status; } @@ -561,7 +697,7 @@ int stpmu1_register_write(uint8_t register_id, uint8_t value) if ((register_id != WATCHDOG_CONTROL_REG) && (register_id <= 0x40U)) { uint8_t readval; - status = stpmu1_register_read(register_id, &readval); + status = stpmic1_register_read(register_id, &readval); if (status != 0) { return status; } @@ -570,32 +706,57 @@ int stpmu1_register_write(uint8_t register_id, uint8_t value) return -1; } } +#endif - return 0; + return status; } -int stpmu1_register_update(uint8_t register_id, uint8_t value, uint8_t mask) +int stpmic1_register_update(uint8_t register_id, uint8_t value, uint8_t mask) { int status; uint8_t val; - status = stpmu1_register_read(register_id, &val); + status = stpmic1_register_read(register_id, &val); if (status != 0) { return status; } - /* Clear bits to update */ - val &= ~mask; + val = (val & ~mask) | (value & mask); - /* Update appropriate bits*/ - val |= (value & mask); + return stpmic1_register_write(register_id, val); +} - /* Send new value on I2C Bus */ - return stpmu1_register_write(register_id, val); +void stpmic1_bind_i2c(struct i2c_handle_s *i2c_handle, uint16_t i2c_addr) +{ + pmic_i2c_handle = i2c_handle; + pmic_i2c_addr = i2c_addr; } -void stpmu1_bind_i2c(struct i2c_handle_s *i2c_handle, uint16_t i2c_addr) +void stpmic1_dump_regulators(void) { - stpmu_i2c_handle = i2c_handle; - stpmu_i2c_addr = i2c_addr; + uint32_t i; + + for (i = 0U; i < MAX_REGUL; i++) { + const char *name __unused = regulators_table[i].dt_node_name; + + VERBOSE("PMIC regul %s: %sable, %dmV", + name, + stpmic1_is_regulator_enabled(name) ? "en" : "dis", + stpmic1_regulator_voltage_get(name)); + } +} + +int stpmic1_get_version(unsigned long *version) +{ + int rc; + uint8_t read_val; + + rc = stpmic1_register_read(VERSION_STATUS_REG, &read_val); + if (rc) { + return -1; + } + + *version = (unsigned long)read_val; + + return 0; } diff --git a/fdts/stm32mp15-ddr.dtsi b/fdts/stm32mp15-ddr.dtsi index be4e2c3721734b40944b2976ca073c4c546e7e0f..1a5c51c978e329c5c18c4996caca5ee3b8c0ffed 100644 --- a/fdts/stm32mp15-ddr.dtsi +++ b/fdts/stm32mp15-ddr.dtsi @@ -5,7 +5,7 @@ / { soc { - ddr: ddr@0x5A003000{ + ddr: ddr@5A003000{ compatible = "st,stm32mp1-ddr"; diff --git a/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi b/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi index 58a4cdc8c25ec781ba0d15f724bee2b044e097d8..82e710468d5c2b592f6637b34fba4f082c68da25 100644 --- a/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi +++ b/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi @@ -3,7 +3,7 @@ * Copyright (C) 2018, STMicroelectronics - All Rights Reserved */ -/* STM32MP157C ED1 and ED2 BOARD configuration +/* STM32MP157C ED1 BOARD configuration * 2x DDR3L 4Gb each, 16-bit, 533MHz, Single Die Package in flyby topology. * Reference used NT5CC256M16DP-DI from NANYA * @@ -15,10 +15,11 @@ * timing mode optimized * Scheduling/QoS options : type = 2 * address mapping : RBC + * Tc > + 85C : N */ -#define DDR_MEM_NAME "DDR3-1066 bin G 2x4Gb 533MHz v1.39" -#define DDR_MEM_SPEED 533 +#define DDR_MEM_NAME "DDR3-1066/888 bin G 2x4Gb 533MHz v1.41" +#define DDR_MEM_SPEED 533000 #define DDR_MEM_SIZE 0x40000000 #define DDR_MSTR 0x00040401 @@ -62,7 +63,7 @@ #define DDR_ADDRMAP11 0x00000000 #define DDR_ODTCFG 0x06000600 #define DDR_ODTMAP 0x00000001 -#define DDR_SCHED 0x00001201 +#define DDR_SCHED 0x00000C01 #define DDR_SCHED1 0x00000000 #define DDR_PERFHPR1 0x01000001 #define DDR_PERFLPR1 0x08000200 @@ -74,15 +75,15 @@ #define DDR_PCCFG 0x00000010 #define DDR_PCFGR_0 0x00010000 #define DDR_PCFGW_0 0x00000000 -#define DDR_PCFGQOS0_0 0x02100B03 +#define DDR_PCFGQOS0_0 0x02100C03 #define DDR_PCFGQOS1_0 0x00800100 -#define DDR_PCFGWQOS0_0 0x01100B03 +#define DDR_PCFGWQOS0_0 0x01100C03 #define DDR_PCFGWQOS1_0 0x01000200 #define DDR_PCFGR_1 0x00010000 #define DDR_PCFGW_1 0x00000000 -#define DDR_PCFGQOS0_1 0x02100B03 -#define DDR_PCFGQOS1_1 0x00800000 -#define DDR_PCFGWQOS0_1 0x01100B03 +#define DDR_PCFGQOS0_1 0x02100C03 +#define DDR_PCFGQOS1_1 0x00800040 +#define DDR_PCFGWQOS0_1 0x01100C03 #define DDR_PCFGWQOS1_1 0x01000200 #define DDR_PGCR 0x01442E02 #define DDR_PTR0 0x0022AA5B diff --git a/fdts/stm32mp157-pinctrl.dtsi b/fdts/stm32mp157-pinctrl.dtsi index 21bd34e0bd72e02aa0e238a0593f64b089a384e7..9dcd7b5e1788043382b1f1c4860a30efb2f5391d 100644 --- a/fdts/stm32mp157-pinctrl.dtsi +++ b/fdts/stm32mp157-pinctrl.dtsi @@ -3,13 +3,14 @@ * Copyright (C) STMicroelectronics 2017 - All Rights Reserved * Author: Ludovic Barre for STMicroelectronics. */ - #include + / { soc { - pinctrl: pin-controller { + pinctrl: pin-controller@50002000 { #address-cells = <1>; #size-cells = <1>; + compatible = "st,stm32mp157-pinctrl"; ranges = <0 0x50002000 0xa400>; pins-are-numbered; @@ -134,54 +135,76 @@ status = "disabled"; }; - uart4_pins_a: uart4@0 { + qspi_bk1_pins_a: qspi-bk1-0 { pins1 { - pinmux = ; /* UART4_TX */ + pinmux = , /* QSPI_BK1_IO0 */ + , /* QSPI_BK1_IO1 */ + , /* QSPI_BK1_IO2 */ + ; /* QSPI_BK1_IO3 */ bias-disable; drive-push-pull; - slew-rate = <0>; + slew-rate = <1>; }; pins2 { - pinmux = ; /* UART4_RX */ - bias-disable; + pinmux = ; /* QSPI_BK1_NCS */ + bias-pull-up; + drive-push-pull; + slew-rate = <1>; }; }; - usart3_pins_a: usart3@0 { + qspi_bk2_pins_a: qspi-bk2-0 { pins1 { - pinmux = , /* USART3_TX */ - ; /* USART3_RTS */ + pinmux = , /* QSPI_BK2_IO0 */ + , /* QSPI_BK2_IO1 */ + , /* QSPI_BK2_IO2 */ + ; /* QSPI_BK2_IO3 */ bias-disable; drive-push-pull; - slew-rate = <0>; + slew-rate = <1>; }; pins2 { - pinmux = , /* USART3_RX */ - ; /* USART3_CTS_NSS */ - bias-disable; + pinmux = ; /* QSPI_BK2_NCS */ + bias-pull-up; + drive-push-pull; + slew-rate = <1>; }; }; - sdmmc1_b4_pins_a: sdmmc1-b4@0 { + qspi_clk_pins_a: qspi-clk-0 { pins { + pinmux = ; /* QSPI_CLK */ + bias-disable; + drive-push-pull; + slew-rate = <3>; + }; + }; + + sdmmc1_b4_pins_a: sdmmc1-b4-0 { + pins1 { pinmux = , /* SDMMC1_D0 */ , /* SDMMC1_D1 */ , /* SDMMC1_D2 */ , /* SDMMC1_D3 */ - , /* SDMMC1_CK */ ; /* SDMMC1_CMD */ - slew-rate = <3>; + slew-rate = <1>; + drive-push-pull; + bias-disable; + }; + pins2 { + pinmux = ; /* SDMMC1_CK */ + slew-rate = <2>; drive-push-pull; bias-disable; }; }; - sdmmc1_dir_pins_a: sdmmc1-dir@0 { + sdmmc1_dir_pins_a: sdmmc1-dir-0 { pins1 { pinmux = , /* SDMMC1_D0DIR */ , /* SDMMC1_D123DIR */ ; /* SDMMC1_CDIR */ - slew-rate = <3>; + slew-rate = <1>; drive-push-pull; bias-pull-up; }; @@ -191,36 +214,85 @@ }; }; - sdmmc2_b4_pins_a: sdmmc2-b4@0 { - pins { + sdmmc1_dir_pins_b: sdmmc1-dir-1 { + pins1 { + pinmux = , /* SDMMC1_D0DIR */ + , /* SDMMC1_D123DIR */ + ; /* SDMMC1_CDIR */ + slew-rate = <3>; + drive-push-pull; + bias-pull-up; + }; + pins2 { + pinmux = ; /* SDMMC1_CKIN */ + bias-pull-up; + }; + }; + + sdmmc2_b4_pins_a: sdmmc2-b4-0 { + pins1 { pinmux = , /* SDMMC2_D0 */ , /* SDMMC2_D1 */ , /* SDMMC2_D2 */ , /* SDMMC2_D3 */ - , /* SDMMC2_CK */ ; /* SDMMC2_CMD */ - slew-rate = <3>; + slew-rate = <1>; + drive-push-pull; + bias-pull-up; + }; + pins2 { + pinmux = ; /* SDMMC2_CK */ + slew-rate = <2>; drive-push-pull; bias-pull-up; }; }; - sdmmc2_d47_pins_a: sdmmc2-d47@0 { + sdmmc2_d47_pins_a: sdmmc2-d47-0 { pins { pinmux = , /* SDMMC2_D4 */ , /* SDMMC2_D5 */ , /* SDMMC2_D6 */ ; /* SDMMC2_D7 */ - slew-rate = <3>; + slew-rate = <1>; drive-push-pull; bias-pull-up; }; }; + + uart4_pins_a: uart4-0 { + pins1 { + pinmux = ; /* UART4_TX */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins2 { + pinmux = ; /* UART4_RX */ + bias-disable; + }; + }; + + usart3_pins_a: usart3-0 { + pins1 { + pinmux = , /* USART3_TX */ + ; /* USART3_RTS */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins2 { + pinmux = , /* USART3_RX */ + ; /* USART3_CTS_NSS */ + bias-disable; + }; + }; }; - pinctrl_z: pin-controller-z { + pinctrl_z: pin-controller-z@54004000 { #address-cells = <1>; #size-cells = <1>; + compatible = "st,stm32mp157-z-pinctrl"; ranges = <0 0x54004000 0x400>; pins-are-numbered; @@ -236,7 +308,7 @@ status = "disabled"; }; - i2c4_pins_a: i2c4@0 { + i2c4_pins_a: i2c4-0 { pins { pinmux = , /* I2C4_SCL */ ; /* I2C4_SDA */ diff --git a/fdts/stm32mp157c-ed1.dts b/fdts/stm32mp157c-ed1.dts index e3dabe8b2b5e64dbcf54903e76d25232ad1587a1..a97e8053bac5a520d6201ceca3ed95457a70cb21 100644 --- a/fdts/stm32mp157c-ed1.dts +++ b/fdts/stm32mp157c-ed1.dts @@ -3,20 +3,26 @@ * Copyright (C) STMicroelectronics 2017 - All Rights Reserved * Author: Ludovic Barre for STMicroelectronics. */ - /dts-v1/; #include "stm32mp157c.dtsi" #include "stm32mp157caa-pinctrl.dtsi" / { - model = "STMicroelectronics STM32MP157C-ED1 pmic eval daughter"; + model = "STMicroelectronics STM32MP157C eval daughter"; compatible = "st,stm32mp157c-ed1", "st,stm32mp157"; chosen { - bootargs = "earlyprintk console=ttyS3,115200 root=/dev/ram"; - stdout-path = "serial3:115200n8"; + stdout-path = "serial0:115200n8"; }; + + aliases { + serial0 = &uart4; + }; +}; + +&clk_hse { + st,digbypass; }; &i2c4 { @@ -26,37 +32,88 @@ i2c-scl-falling-time-ns = <20>; status = "okay"; - pmic: stpmu1@33 { - compatible = "st,stpmu1"; + pmic: stpmic@33 { + compatible = "st,stpmic1"; reg = <0x33>; + interrupts-extended = <&exti_pwr 55 IRQ_TYPE_EDGE_FALLING>; + interrupt-controller; + #interrupt-cells = <2>; status = "okay"; - st,main_control_register = <0x04>; - st,vin_control_register = <0xc0>; - st,usb_control_register = <0x30>; + st,main-control-register = <0x04>; + st,vin-control-register = <0xc0>; + st,usb-control-register = <0x30>; regulators { - compatible = "st,stpmu1-regulators"; + compatible = "st,stpmic1-regulators"; + + ldo1-supply = <&v3v3>; + ldo2-supply = <&v3v3>; + ldo3-supply = <&vdd_ddr>; + ldo5-supply = <&v3v3>; + ldo6-supply = <&v3v3>; + + vddcore: buck1 { + regulator-name = "vddcore"; + regulator-min-microvolt = <800000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; + regulator-initial-mode = <0>; + regulator-over-current-protection; + }; + + vdd_ddr: buck2 { + regulator-name = "vdd_ddr"; + regulator-min-microvolt = <1350000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; + regulator-initial-mode = <0>; + regulator-over-current-protection; + }; + + vdd: buck3 { + regulator-name = "vdd"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + st,mask-reset; + regulator-initial-mode = <0>; + regulator-over-current-protection; + }; v3v3: buck4 { regulator-name = "v3v3"; regulator-min-microvolt = <3300000>; regulator-max-microvolt = <3300000>; - regulator-boot-on; + regulator-always-on; regulator-over-current-protection; - regulator-initial-mode = <8>; - - regulator-state-standby { - regulator-suspend-microvolt = <3300000>; - regulator-unchanged-in-suspend; - regulator-mode = <8>; - }; - regulator-state-mem { - regulator-off-in-suspend; - }; - regulator-state-disk { - regulator-off-in-suspend; - }; + regulator-initial-mode = <0>; + }; + + vdda: ldo1 { + regulator-name = "vdda"; + regulator-min-microvolt = <2900000>; + regulator-max-microvolt = <2900000>; + }; + + v2v8: ldo2 { + regulator-name = "v2v8"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + }; + + vtt_ddr: ldo3 { + regulator-name = "vtt_ddr"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <750000>; + regulator-always-on; + regulator-over-current-protection; + }; + + vdd_usb: ldo4 { + regulator-name = "vdd_usb"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; }; vdd_sd: ldo5 { @@ -64,24 +121,24 @@ regulator-min-microvolt = <2900000>; regulator-max-microvolt = <2900000>; regulator-boot-on; + }; - regulator-state-standby { - regulator-suspend-microvolt = <2900000>; - regulator-unchanged-in-suspend; - }; - regulator-state-mem { - regulator-off-in-suspend; - }; - regulator-state-disk { - regulator-off-in-suspend; - }; + v1v8: ldo6 { + regulator-name = "v1v8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + vref_ddr: vref_ddr { + regulator-name = "vref_ddr"; + regulator-always-on; + regulator-over-current-protection; }; }; }; }; &iwdg2 { - instance = <2>; timeout-sec = <32>; status = "okay"; }; @@ -90,14 +147,19 @@ status = "okay"; }; +&rtc { + status = "okay"; +}; + &sdmmc1 { pinctrl-names = "default"; pinctrl-0 = <&sdmmc1_b4_pins_a &sdmmc1_dir_pins_a>; broken-cd; - st,dirpol; - st,negedge; - st,pin-ckin; + st,sig-dir; + st,neg-edge; + st,use-ckin; bus-width = <4>; + vmmc-supply = <&vdd_sd>; sd-uhs-sdr12; sd-uhs-sdr25; sd-uhs-sdr50; @@ -112,16 +174,17 @@ non-removable; no-sd; no-sdio; - st,dirpol; - st,negedge; + st,neg-edge; bus-width = <8>; + vmmc-supply = <&v3v3>; + vqmmc-supply = <&v3v3>; + mmc-ddr-3_3v; status = "okay"; }; &uart4 { pinctrl-names = "default"; pinctrl-0 = <&uart4_pins_a>; - resets = <&rcc UART4_R>; status = "okay"; }; @@ -157,6 +220,7 @@ /* CLOCK init */ &rcc { + secure-status = "disabled"; st,clksrc = < CLK_MPU_PLL1P CLK_AXI_PLL2P @@ -186,7 +250,7 @@ CLK_FMC_ACLK CLK_QSPI_ACLK CLK_ETH_DISABLED - CLK_SDMMC12_PLL3R + CLK_SDMMC12_PLL4P CLK_DSI_DSIPLL CLK_STGEN_HSE CLK_USBPHY_HSE @@ -195,7 +259,7 @@ CLK_SPI45_HSI CLK_SPI6_HSI CLK_I2C46_HSI - CLK_SDMMC3_PLL3R + CLK_SDMMC3_PLL4P CLK_USBO_USBPHY CLK_ADC_CKPER CLK_CEC_LSE @@ -206,17 +270,17 @@ CLK_UART35_HSI CLK_UART6_HSI CLK_UART78_HSI - CLK_SPDIF_PLL3Q + CLK_SPDIF_PLL4P CLK_FDCAN_PLL4Q CLK_SAI1_PLL3Q CLK_SAI2_PLL3Q CLK_SAI3_PLL3Q CLK_SAI4_PLL3Q - CLK_RNG1_CSI - CLK_RNG2_CSI + CLK_RNG1_LSI + CLK_RNG2_LSI CLK_LPTIM1_PCLK1 CLK_LPTIM23_PCLK3 - CLK_LPTIM45_PCLK3 + CLK_LPTIM45_LSE >; /* VCO = 1300.0 MHz => P = 650 (CPU) */ @@ -231,15 +295,15 @@ frac = < 0x1400 >; }; - /* VCO = 786.4 MHz => P = 197, Q = 49, R = 98 */ + /* VCO = 417.8 MHz => P = 209, Q = 24, R = 11 */ pll3: st,pll@2 { - cfg = < 2 97 3 15 7 PQR(1,1,1) >; - frac = < 0x9ba >; + cfg = < 1 33 1 16 36 PQR(1,1,1) >; + frac = < 0x1a04 >; }; - /* VCO = 508.0 MHz => P = 56, Q = 56, R = 56 */ + /* VCO = 594.0 MHz => P = 99, Q = 74, R = 74 */ pll4: st,pll@3 { - cfg = < 5 126 8 8 8 PQR(1,1,1) >; + cfg = < 3 98 5 7 7 PQR(1,1,1) >; }; }; diff --git a/fdts/stm32mp157c-ev1.dts b/fdts/stm32mp157c-ev1.dts index 98a9d350049a2c383d5b1d216385123b2b6d7634..cfde8ed90eeecb8c951cd00c293255795ccec956 100644 --- a/fdts/stm32mp157c-ev1.dts +++ b/fdts/stm32mp157c-ev1.dts @@ -3,23 +3,65 @@ * Copyright (C) STMicroelectronics 2017 - All Rights Reserved * Author: Ludovic Barre for STMicroelectronics. */ - /dts-v1/; + #include "stm32mp157c-ed1.dts" / { - model = "STMicroelectronics STM32MP157C-EV1 pmic eval daughter on eval mother"; + model = "STMicroelectronics STM32MP157C eval daughter on eval mother"; compatible = "st,stm32mp157c-ev1", "st,stm32mp157c-ed1", "st,stm32mp157"; chosen { - bootargs = "earlyprintk console=ttyS3,115200 root=/dev/ram"; - stdout-path = "serial3:115200n8"; + stdout-path = "serial0:115200n8"; + }; + + aliases { + serial1 = &usart3; + }; +}; + +&fmc { + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + + nand: nand@0 { + reg = <0>; + nand-on-flash-bbt; + #address-cells = <1>; + #size-cells = <1>; + }; +}; + +&qspi { + pinctrl-names = "default"; + pinctrl-0 = <&qspi_clk_pins_a &qspi_bk1_pins_a &qspi_bk2_pins_a>; + reg = <0x58003000 0x1000>, <0x70000000 0x4000000>; + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + flash0: mx66l51235l@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-rx-bus-width = <4>; + spi-max-frequency = <108000000>; + #address-cells = <1>; + #size-cells = <1>; + }; + + flash1: mx66l51235l@1 { + compatible = "jedec,spi-nor"; + reg = <1>; + spi-rx-bus-width = <4>; + spi-max-frequency = <108000000>; + #address-cells = <1>; + #size-cells = <1>; }; }; &usart3 { pinctrl-names = "default"; pinctrl-0 = <&usart3_pins_a>; - resets = <&rcc USART3_R>; status = "disabled"; }; diff --git a/fdts/stm32mp157c.dtsi b/fdts/stm32mp157c.dtsi index 8b13c0e38066d4bbb23939b46e55b27493d19393..0ec7ecb783ef7fa09bd797d182a9ee75d74fdce7 100644 --- a/fdts/stm32mp157c.dtsi +++ b/fdts/stm32mp157c.dtsi @@ -3,7 +3,7 @@ * Copyright (C) STMicroelectronics 2017 - All Rights Reserved * Author: Ludovic Barre for STMicroelectronics. */ - +#include #include #include @@ -11,15 +11,12 @@ #address-cells = <1>; #size-cells = <1>; - aliases { - serial0 = &usart1; - serial1 = &usart2; - serial2 = &usart3; - serial3 = &uart4; - serial4 = &uart5; - serial5 = &usart6; - serial6 = &uart7; - serial7 = &uart8; + intc: interrupt-controller@a0021000 { + compatible = "arm,cortex-a7-gic"; + #interrupt-cells = <3>; + interrupt-controller; + reg = <0xa0021000 0x1000>, + <0xa0022000 0x2000>; }; clocks { @@ -56,7 +53,7 @@ clk_i2s_ckin: i2s_ckin { #clock-cells = <0>; compatible = "fixed-clock"; - clock-frequency = <64000000>; + clock-frequency = <0>; }; clk_dsi_phy: ck_dsi_phy { @@ -64,31 +61,28 @@ compatible = "fixed-clock"; clock-frequency = <0>; }; - - clk_usbo_48m: ck_usbo_48m { - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <48000000>; - }; }; soc { compatible = "simple-bus"; #address-cells = <1>; #size-cells = <1>; + interrupt-parent = <&intc>; ranges; usart2: serial@4000e000 { - compatible = "st,stm32h7-usart"; + compatible = "st,stm32h7-uart"; reg = <0x4000e000 0x400>; clocks = <&rcc USART2_K>; + resets = <&rcc USART2_R>; status = "disabled"; }; usart3: serial@4000f000 { - compatible = "st,stm32h7-usart"; + compatible = "st,stm32h7-uart"; reg = <0x4000f000 0x400>; clocks = <&rcc USART3_K>; + resets = <&rcc USART3_R>; status = "disabled"; }; @@ -96,6 +90,7 @@ compatible = "st,stm32h7-uart"; reg = <0x40010000 0x400>; clocks = <&rcc UART4_K>; + resets = <&rcc UART4_R>; status = "disabled"; }; @@ -103,6 +98,7 @@ compatible = "st,stm32h7-uart"; reg = <0x40011000 0x400>; clocks = <&rcc UART5_K>; + resets = <&rcc UART5_R>; status = "disabled"; }; @@ -111,6 +107,7 @@ compatible = "st,stm32h7-uart"; reg = <0x40018000 0x400>; clocks = <&rcc UART7_K>; + resets = <&rcc UART7_R>; status = "disabled"; }; @@ -118,21 +115,23 @@ compatible = "st,stm32h7-uart"; reg = <0x40019000 0x400>; clocks = <&rcc UART8_K>; + resets = <&rcc UART8_R>; status = "disabled"; }; usart6: serial@44003000 { - compatible = "st,stm32h7-usart"; + compatible = "st,stm32h7-uart"; reg = <0x44003000 0x400>; clocks = <&rcc USART6_K>; + resets = <&rcc USART6_R>; status = "disabled"; }; sdmmc3: sdmmc@48004000 { compatible = "st,stm32-sdmmc2"; reg = <0x48004000 0x400>, <0x48005000 0x400>; - reg-names = "sdmmc", "delay"; clocks = <&rcc SDMMC3_K>; + clock-names = "apb_pclk"; resets = <&rcc SDMMC3_R>; cap-sd-highspeed; cap-mmc-highspeed; @@ -141,17 +140,34 @@ }; rcc: rcc@50000000 { - compatible = "syscon", "st,stm32mp1-rcc"; + compatible = "st,stm32mp1-rcc", "syscon"; + reg = <0x50000000 0x1000>; #clock-cells = <1>; #reset-cells = <1>; - reg = <0x50000000 0x1000>; + interrupts = ; }; - rcc_reboot: rcc-reboot@50000000 { - compatible = "syscon-reboot"; - regmap = <&rcc>; - offset = <0x404>; - mask = <0x1>; + pwr: pwr@50001000 { + compatible = "st,stm32mp1-pwr", "syscon", "simple-mfd"; + reg = <0x50001000 0x400>; + }; + + exti: interrupt-controller@5000d000 { + compatible = "st,stm32mp1-exti", "syscon"; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x5000d000 0x400>; + + /* exti_pwr is an extra interrupt controller used for + * EXTI 55 to 60. It's mapped on pwr interrupt + * controller. + */ + exti_pwr: exti-pwr { + interrupt-controller; + #interrupt-cells = <2>; + interrupt-parent = <&pwr>; + st,irq-number = <6>; + }; }; rng1: rng@54003000 { @@ -162,13 +178,15 @@ status = "disabled"; }; - fmc_nand: fmc_nand@58002000 { - compatible = "st,stm32mp1-fmc"; + fmc: nand-controller@58002000 { + compatible = "st,stm32mp15-fmc2"; reg = <0x58002000 0x1000>, - <0x80000000 0x40000>, - <0x81000000 0x40000>, - <0x88000000 0x40000>, - <0x89000000 0x40000>; + <0x80000000 0x1000>, + <0x88010000 0x1000>, + <0x88020000 0x1000>, + <0x81000000 0x1000>, + <0x89010000 0x1000>, + <0x89020000 0x1000>; clocks = <&rcc FMC_K>; resets = <&rcc FMC_R>; status = "disabled"; @@ -177,15 +195,17 @@ qspi: qspi@58003000 { compatible = "st,stm32f469-qspi"; reg = <0x58003000 0x1000>, <0x70000000 0x10000000>; + reg-names = "qspi", "qspi_mm"; clocks = <&rcc QSPI_K>; + resets = <&rcc QSPI_R>; status = "disabled"; }; sdmmc1: sdmmc@58005000 { compatible = "st,stm32-sdmmc2"; reg = <0x58005000 0x1000>, <0x58006000 0x1000>; - reg-names = "sdmmc", "delay"; clocks = <&rcc SDMMC1_K>; + clock-names = "apb_pclk"; resets = <&rcc SDMMC1_R>; cap-sd-highspeed; cap-mmc-highspeed; @@ -196,8 +216,8 @@ sdmmc2: sdmmc@58007000 { compatible = "st,stm32-sdmmc2"; reg = <0x58007000 0x1000>, <0x58008000 0x1000>; - reg-names = "sdmmc", "delay"; clocks = <&rcc SDMMC2_K>; + clock-names = "apb_pclk"; resets = <&rcc SDMMC2_R>; cap-sd-highspeed; cap-mmc-highspeed; @@ -205,7 +225,7 @@ status = "disabled"; }; - iwdg2: iwdg@5a002000 { + iwdg2: watchdog@5a002000 { compatible = "st,stm32mp1-iwdg"; reg = <0x5a002000 0x400>; clocks = <&rcc IWDG2>, <&rcc CK_LSI>; @@ -214,15 +234,34 @@ }; usart1: serial@5c000000 { - compatible = "st,stm32h7-usart"; + compatible = "st,stm32h7-uart"; reg = <0x5c000000 0x400>; + interrupt-names = "event", "wakeup"; + interrupts-extended = <&intc GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>, + <&exti 26 1>; clocks = <&rcc USART1_K>; + resets = <&rcc USART1_R>; + status = "disabled"; + }; + + spi6: spi@5c001000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "st,stm32h7-spi"; + reg = <0x5c001000 0x400>; + interrupts = ; + clocks = <&rcc SPI6_K>; + resets = <&rcc SPI6_R>; status = "disabled"; }; i2c4: i2c@5c002000 { compatible = "st,stm32f7-i2c"; reg = <0x5c002000 0x400>; + interrupt-names = "event", "error", "wakeup"; + interrupts-extended = <&intc GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>, + <&intc GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>, + <&exti 24 1>; clocks = <&rcc I2C4_K>; resets = <&rcc I2C4_R>; #address-cells = <1>; @@ -235,6 +274,36 @@ reg = <0x5c004000 0x400>; clocks = <&rcc RTCAPB>, <&rcc RTC>; clock-names = "pclk", "rtc_ck"; + interrupts-extended = <&intc GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>, + <&exti 19 1>; + status = "disabled"; + }; + + bsec: nvmem@5c005000 { + compatible = "st,stm32mp15-bsec"; + reg = <0x5c005000 0x400>; + #address-cells = <1>; + #size-cells = <1>; + ts_cal1: calib@5c { + reg = <0x5c 0x2>; + }; + ts_cal2: calib@5e { + reg = <0x5e 0x2>; + }; + }; + + i2c6: i2c@5c009000 { + compatible = "st,stm32f7-i2c"; + reg = <0x5c009000 0x400>; + interrupt-names = "event", "error", "wakeup"; + interrupts-extended = <&intc GIC_SPI 135 IRQ_TYPE_LEVEL_HIGH>, + <&intc GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>, + <&exti 54 1>; + clocks = <&rcc I2C6_K>; + resets = <&rcc I2C6_R>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; }; }; }; diff --git a/fdts/stm32mp157caa-pinctrl.dtsi b/fdts/stm32mp157caa-pinctrl.dtsi index 774561aed901c80ed7277b7aa98b83fa79d84a89..9b9cd086c2b157286b0524f145d0bb4a7dac47c7 100644 --- a/fdts/stm32mp157caa-pinctrl.dtsi +++ b/fdts/stm32mp157caa-pinctrl.dtsi @@ -7,8 +7,8 @@ #include "stm32mp157-pinctrl.dtsi" / { soc { - pinctrl: pin-controller { - compatible = "st,stm32mp157caa-pinctrl"; + pinctrl: pin-controller@50002000 { + st,package = ; gpioa: gpio@50002000 { status = "okay"; @@ -77,8 +77,8 @@ }; }; - pinctrl_z: pin-controller-z { - compatible = "st,stm32mp157caa-z-pinctrl"; + pinctrl_z: pin-controller-z@54004000 { + st,package = ; gpioz: gpio@54004000 { status = "okay"; diff --git a/include/drivers/st/bsec.h b/include/drivers/st/bsec.h new file mode 100644 index 0000000000000000000000000000000000000000..2171550b3c6a09cf3050dd541ae702338a288a43 --- /dev/null +++ b/include/drivers/st/bsec.h @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BSEC_H +#define BSEC_H + +#include +#include + +#include + +/* + * IP configuration + */ +#define BSEC_OTP_MASK GENMASK(4, 0) +#define BSEC_OTP_BANK_SHIFT 5 +#define BSEC_TIMEOUT_VALUE 0xFFFF + +#define ADDR_LOWER_OTP_PERLOCK_SHIFT 0x03 +#define DATA_LOWER_OTP_PERLOCK_BIT 0x03U /* 2 significants bits are used */ +#define DATA_LOWER_OTP_PERLOCK_MASK GENMASK(2, 0) +#define ADDR_UPPER_OTP_PERLOCK_SHIFT 0x04 +#define DATA_UPPER_OTP_PERLOCK_BIT 0x01U /* 1 significants bits are used */ +#define DATA_UPPER_OTP_PERLOCK_MASK GENMASK(3, 0) + +/* + * Return status + */ +#define BSEC_OK 0U +#define BSEC_ERROR 0xFFFFFFFFU +#define BSEC_DISTURBED 0xFFFFFFFEU +#define BSEC_INVALID_PARAM 0xFFFFFFFCU +#define BSEC_PROG_FAIL 0xFFFFFFFBU +#define BSEC_LOCK_FAIL 0xFFFFFFFAU +#define BSEC_WRITE_FAIL 0xFFFFFFF9U +#define BSEC_SHADOW_FAIL 0xFFFFFFF8U +#define BSEC_TIMEOUT 0xFFFFFFF7U + +/* + * BSEC REGISTER OFFSET (base relative) + */ +#define BSEC_OTP_CONF_OFF 0x000U +#define BSEC_OTP_CTRL_OFF 0x004U +#define BSEC_OTP_WRDATA_OFF 0x008U +#define BSEC_OTP_STATUS_OFF 0x00CU +#define BSEC_OTP_LOCK_OFF 0x010U +#define BSEC_DEN_OFF 0x014U +#define BSEC_DISTURBED_OFF 0x01CU +#define BSEC_DISTURBED1_OFF 0x020U +#define BSEC_DISTURBED2_OFF 0x024U +#define BSEC_ERROR_OFF 0x034U +#define BSEC_ERROR1_OFF 0x038U +#define BSEC_ERROR2_OFF 0x03CU +#define BSEC_WRLOCK_OFF 0x04CU /* Safmem permanent lock */ +#define BSEC_WRLOCK1_OFF 0x050U +#define BSEC_WRLOCK2_OFF 0x054U +#define BSEC_SPLOCK_OFF 0x064U /* Program safmem sticky lock */ +#define BSEC_SPLOCK1_OFF 0x068U +#define BSEC_SPLOCK2_OFF 0x06CU +#define BSEC_SWLOCK_OFF 0x07CU /* Write in OTP sticky lock */ +#define BSEC_SWLOCK1_OFF 0x080U +#define BSEC_SWLOCK2_OFF 0x084U +#define BSEC_SRLOCK_OFF 0x094U /* Shadowing sticky lock */ +#define BSEC_SRLOCK1_OFF 0x098U +#define BSEC_SRLOCK2_OFF 0x09CU +#define BSEC_JTAG_IN_OFF 0x0ACU +#define BSEC_JTAG_OUT_OFF 0x0B0U +#define BSEC_SCRATCH_OFF 0x0B4U +#define BSEC_OTP_DATA_OFF 0x200U +#define BSEC_IPHW_CFG_OFF 0xFF0U +#define BSEC_IPVR_OFF 0xFF4U +#define BSEC_IP_ID_OFF 0xFF8U +#define BSEC_IP_MAGIC_ID_OFF 0xFFCU + +/* + * BSEC_CONFIGURATION Register + */ +#define BSEC_CONF_POWER_UP_MASK BIT(0) +#define BSEC_CONF_POWER_UP_SHIFT 0 +#define BSEC_CONF_FRQ_MASK GENMASK(2, 1) +#define BSEC_CONF_FRQ_SHIFT 1 +#define BSEC_CONF_PRG_WIDTH_MASK GENMASK(6, 3) +#define BSEC_CONF_PRG_WIDTH_SHIFT 3 +#define BSEC_CONF_TREAD_MASK GENMASK(8, 7) +#define BSEC_CONF_TREAD_SHIFT 7 + +/* + * BSEC_CONTROL Register + */ +#define BSEC_READ 0x000U +#define BSEC_WRITE 0x100U +#define BSEC_LOCK 0x200U + +/* + * BSEC_OTP_LOCK register + */ +#define UPPER_OTP_LOCK_MASK BIT(0) +#define UPPER_OTP_LOCK_SHIFT 0 +#define DENREG_LOCK_MASK BIT(2) +#define DENREG_LOCK_SHIFT 2 +#define GPLOCK_LOCK_MASK BIT(4) +#define GPLOCK_LOCK_SHIFT 4 + +/* + * BSEC_OTP_STATUS Register + */ +#define BSEC_MODE_STATUS_MASK GENMASK(2, 0) +#define BSEC_MODE_BUSY_MASK BIT(3) +#define BSEC_MODE_PROGFAIL_MASK BIT(4) +#define BSEC_MODE_PWR_MASK BIT(5) +#define BSEC_MODE_BIST1_LOCK_MASK BIT(6) +#define BSEC_MODE_BIST2_LOCK_MASK BIT(7) + +/* OTP MODE*/ +#define BSEC_MODE_OPEN1 0x00 +#define BSEC_MODE_SECURED 0x01 +#define BSEC_MODE_OPEN2 0x02 +#define BSEC_MODE_INVALID 0x04 + +/* BSEC_DENABLE Register */ +#define BSEC_HDPEN BIT(4) +#define BSEC_SPIDEN BIT(5) +#define BSEC_SPINDEN BIT(6) +#define BSEC_DBGSWGEN BIT(10) +#define BSEC_DEN_ALL_MSK GENMASK(10, 0) + +/* BSEC_FENABLE Register */ +#define BSEC_FEN_ALL_MSK GENMASK(14, 0) + +/* + * OTP Lock services definition + * Value must corresponding to the bit number in the register + */ +#define BSEC_LOCK_UPPER_OTP 0x00 +#define BSEC_LOCK_DEBUG 0x02 +#define BSEC_LOCK_PROGRAM 0x03 + +/* Values for struct bsec_config::freq */ +#define FREQ_10_20_MHZ 0x0 +#define FREQ_20_30_MHZ 0x1 +#define FREQ_30_45_MHZ 0x2 +#define FREQ_45_67_MHZ 0x3 + +/* + * Device info structure, providing device-specific functions and a means of + * adding driver-specific state + */ +struct bsec_config { + uint8_t tread; /* SAFMEM Reading current level default 0 */ + uint8_t pulse_width; /* SAFMEM Programming pulse width default 1 */ + uint8_t freq; /* SAFMEM CLOCK see freq value define + * default FREQ_45_67_MHZ + */ + uint8_t power; /* Power up SAFMEM. 1 power up, 0 power off */ + uint8_t prog_lock; /* Programming Sticky lock + * 1 programming is locked until next reset + */ + uint8_t den_lock; /* Debug enable sticky lock + * 1 debug enable is locked until next reset + */ + uint8_t upper_otp_lock; /* Shadowing of upper OTP sticky lock + * 1 shadowing of upper OTP is locked + * until next reset + */ +}; + +uint32_t bsec_probe(void); +uint32_t bsec_get_base(void); + +uint32_t bsec_set_config(struct bsec_config *cfg); +uint32_t bsec_get_config(struct bsec_config *cfg); + +uint32_t bsec_shadow_register(uint32_t otp); +uint32_t bsec_read_otp(uint32_t *val, uint32_t otp); +uint32_t bsec_write_otp(uint32_t val, uint32_t otp); +uint32_t bsec_program_otp(uint32_t val, uint32_t otp); +uint32_t bsec_permanent_lock_otp(uint32_t otp); + +uint32_t bsec_write_debug_conf(uint32_t val); +uint32_t bsec_read_debug_conf(void); +uint32_t bsec_write_feature_conf(uint32_t val); +uint32_t bsec_read_feature_conf(uint32_t *val); + +uint32_t bsec_get_status(void); +uint32_t bsec_get_hw_conf(void); +uint32_t bsec_get_version(void); +uint32_t bsec_get_id(void); +uint32_t bsec_get_magic_id(void); + +bool bsec_write_sr_lock(uint32_t otp, uint32_t value); +bool bsec_read_sr_lock(uint32_t otp); +bool bsec_write_sw_lock(uint32_t otp, uint32_t value); +bool bsec_read_sw_lock(uint32_t otp); +bool bsec_write_sp_lock(uint32_t otp, uint32_t value); +bool bsec_read_sp_lock(uint32_t otp); +bool bsec_wr_lock(uint32_t otp); +uint32_t bsec_otp_lock(uint32_t service, uint32_t value); + +bool bsec_mode_is_closed_device(void); +uint32_t bsec_shadow_read_otp(uint32_t *otp_value, uint32_t word); +uint32_t bsec_check_nsec_access_rights(uint32_t otp); + +#endif /* BSEC_H */ diff --git a/include/drivers/st/stm32_gpio.h b/include/drivers/st/stm32_gpio.h index acd95ecabf8bfe6b70baf920ba650196e049a064..4320eafcdaf07c8458a00c3928fb5c8fe3f9aaad 100644 --- a/include/drivers/st/stm32_gpio.h +++ b/include/drivers/st/stm32_gpio.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2018, STMicroelectronics - All Rights Reserved + * Copyright (c) 2015-2019, STMicroelectronics - All Rights Reserved * * SPDX-License-Identifier: BSD-3-Clause */ @@ -9,10 +9,6 @@ #include -#define STM32_GPIOA_BANK U(0x50002000) -#define STM32_GPIOZ_BANK U(0x54004000) -#define STM32_GPIO_BANK_OFFSET U(0x1000) - #define GPIO_MODE_OFFSET U(0x00) #define GPIO_TYPE_OFFSET U(0x04) #define GPIO_SPEED_OFFSET U(0x08) @@ -20,56 +16,14 @@ #define GPIO_BSRR_OFFSET U(0x18) #define GPIO_AFRL_OFFSET U(0x20) #define GPIO_AFRH_OFFSET U(0x24) +#define GPIO_SECR_OFFSET U(0x30) #define GPIO_ALT_LOWER_LIMIT U(0x08) -#define GPIO_BANK_A U(0x00) -#define GPIO_BANK_B U(0x01) -#define GPIO_BANK_C U(0x02) -#define GPIO_BANK_D U(0x03) -#define GPIO_BANK_E U(0x04) -#define GPIO_BANK_F U(0x05) -#define GPIO_BANK_G U(0x06) -#define GPIO_BANK_H U(0x07) -#define GPIO_BANK_I U(0x08) -#define GPIO_BANK_J U(0x09) -#define GPIO_BANK_K U(0x0A) -#define GPIO_BANK_Z U(0x19) - -#define GPIO_PIN_0 U(0x00) -#define GPIO_PIN_1 U(0x01) -#define GPIO_PIN_2 U(0x02) -#define GPIO_PIN_3 U(0x03) -#define GPIO_PIN_4 U(0x04) -#define GPIO_PIN_5 U(0x05) -#define GPIO_PIN_6 U(0x06) -#define GPIO_PIN_7 U(0x07) -#define GPIO_PIN_8 U(0x08) -#define GPIO_PIN_9 U(0x09) -#define GPIO_PIN_10 U(0x0A) -#define GPIO_PIN_11 U(0x0B) -#define GPIO_PIN_12 U(0x0C) -#define GPIO_PIN_13 U(0x0D) -#define GPIO_PIN_14 U(0x0E) -#define GPIO_PIN_15 U(0x0F) -#define GPIO_PIN_MAX GPIO_PIN_15 +#define GPIO_PIN_(_x) U(_x) +#define GPIO_PIN_MAX GPIO_PIN_(15) -#define GPIO_ALTERNATE_0 0x00 -#define GPIO_ALTERNATE_1 0x01 -#define GPIO_ALTERNATE_2 0x02 -#define GPIO_ALTERNATE_3 0x03 -#define GPIO_ALTERNATE_4 0x04 -#define GPIO_ALTERNATE_5 0x05 -#define GPIO_ALTERNATE_6 0x06 -#define GPIO_ALTERNATE_7 0x07 -#define GPIO_ALTERNATE_8 0x08 -#define GPIO_ALTERNATE_9 0x09 -#define GPIO_ALTERNATE_10 0x0A -#define GPIO_ALTERNATE_11 0x0B -#define GPIO_ALTERNATE_12 0x0C -#define GPIO_ALTERNATE_13 0x0D -#define GPIO_ALTERNATE_14 0x0E -#define GPIO_ALTERNATE_15 0x0F +#define GPIO_ALTERNATE_(_x) U(_x) #define GPIO_ALTERNATE_MASK U(0x0F) #define GPIO_MODE_INPUT 0x00 @@ -82,8 +36,8 @@ #define GPIO_SPEED_LOW 0x00 #define GPIO_SPEED_MEDIUM 0x01 -#define GPIO_SPEED_FAST 0x02 -#define GPIO_SPEED_HIGH 0x03 +#define GPIO_SPEED_HIGH 0x02 +#define GPIO_SPEED_VERY_HIGH 0x03 #define GPIO_SPEED_MASK U(0x03) #define GPIO_NO_PULL 0x00 @@ -94,8 +48,10 @@ #ifndef __ASSEMBLY__ #include +int dt_set_pinctrl_config(int node); void set_gpio(uint32_t bank, uint32_t pin, uint32_t mode, uint32_t speed, - uint32_t pull, uint32_t alternate); + uint32_t pull, uint32_t alternate, uint8_t status); +void set_gpio_secure_cfg(uint32_t bank, uint32_t pin, bool secure); #endif /*__ASSEMBLY__*/ #endif /* STM32_GPIO_H */ diff --git a/include/drivers/st/stm32mp1_ddr.h b/include/drivers/st/stm32mp1_ddr.h index 363e3020c26d2ac81d54baf37afc7426c457127a..4ab37d6b44a156db210033886fb0b53475305134 100644 --- a/include/drivers/st/stm32mp1_ddr.h +++ b/include/drivers/st/stm32mp1_ddr.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018, STMicroelectronics - All Rights Reserved + * Copyright (C) 2018-2019, STMicroelectronics - All Rights Reserved * * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */ @@ -153,7 +153,7 @@ struct stm32mp1_ddrphy_cal { struct stm32mp1_ddr_info { const char *name; - uint16_t speed; /* in MHZ */ + uint32_t speed; /* in kHZ */ uint32_t size; /* Memory size in byte = col * row * width */ }; @@ -168,7 +168,7 @@ struct stm32mp1_ddr_config { struct stm32mp1_ddrphy_cal p_cal; }; -int stm32mp1_ddr_clk_enable(struct ddr_info *priv, uint16_t mem_speed); +int stm32mp1_ddr_clk_enable(struct ddr_info *priv, uint32_t mem_speed); void stm32mp1_ddr_init(struct ddr_info *priv, struct stm32mp1_ddr_config *config); #endif /* STM32MP1_DDR_H */ diff --git a/include/drivers/st/stm32mp1_ddr_regs.h b/include/drivers/st/stm32mp1_ddr_regs.h index bfcd5e21042d94091665c3d6f422c2a85436ac10..342239a52de3a6f40db2b1264c1d97f65186b483 100644 --- a/include/drivers/st/stm32mp1_ddr_regs.h +++ b/include/drivers/st/stm32mp1_ddr_regs.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved + * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved * * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */ @@ -247,11 +247,14 @@ struct stm32mp1_ddrphy { #define DDRCTRL_DBGSTAT 0x310 #define DDRCTRL_SWCTL 0x320 #define DDRCTRL_SWSTAT 0x324 +#define DDRCTRL_PSTAT 0x3FC #define DDRCTRL_PCTRL_0 0x490 #define DDRCTRL_PCTRL_1 0x540 /* DDR Controller Register fields */ #define DDRCTRL_MSTR_DDR3 BIT(0) +#define DDRCTRL_MSTR_LPDDR2 BIT(2) +#define DDRCTRL_MSTR_LPDDR3 BIT(3) #define DDRCTRL_MSTR_DATA_BUS_WIDTH_MASK GENMASK(13, 12) #define DDRCTRL_MSTR_DATA_BUS_WIDTH_FULL 0 #define DDRCTRL_MSTR_DATA_BUS_WIDTH_HALF BIT(12) @@ -269,7 +272,7 @@ struct stm32mp1_ddrphy { /* Only one rank supported */ #define DDRCTRL_MRCTRL0_MR_RANK_SHIFT 4 #define DDRCTRL_MRCTRL0_MR_RANK_ALL \ - (0x1U << DDRCTRL_MRCTRL0_MR_RANK_SHIFT) + BIT(DDRCTRL_MRCTRL0_MR_RANK_SHIFT) #define DDRCTRL_MRCTRL0_MR_ADDR_SHIFT 12 #define DDRCTRL_MRCTRL0_MR_ADDR_MASK GENMASK(15, 12) #define DDRCTRL_MRCTRL0_MR_WR BIT(31) @@ -367,6 +370,7 @@ struct stm32mp1_ddrphy { #define DDRPHYC_DLLGCR_BPS200 BIT(23) +#define DDRPHYC_ACDLLCR_DLLSRST BIT(30) #define DDRPHYC_ACDLLCR_DLLDIS BIT(31) #define DDRPHYC_PTR0_TDLLSRST_OFFSET 0 diff --git a/include/drivers/st/stm32mp1_rcc.h b/include/drivers/st/stm32mp1_rcc.h index fd406c57e76c3649ebfea32352bd3655c281b965..2f29e84d595e4c19c1bcd26d377f9a4c0fc130a5 100644 --- a/include/drivers/st/stm32mp1_rcc.h +++ b/include/drivers/st/stm32mp1_rcc.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2018, STMicroelectronics - All Rights Reserved + * Copyright (c) 2015-2019, STMicroelectronics - All Rights Reserved * * SPDX-License-Identifier: BSD-3-Clause */ @@ -68,6 +68,14 @@ #define RCC_MP_AHB6ENCLRR U(0x21C) #define RCC_MP_TZAHB6ENSETR U(0x220) #define RCC_MP_TZAHB6ENCLRR U(0x224) +#define RCC_MC_APB4ENSETR U(0x280) +#define RCC_MC_APB4ENCLRR U(0x284) +#define RCC_MC_APB5ENSETR U(0x288) +#define RCC_MC_APB5ENCLRR U(0x28C) +#define RCC_MC_AHB5ENSETR U(0x290) +#define RCC_MC_AHB5ENCLRR U(0x294) +#define RCC_MC_AHB6ENSETR U(0x298) +#define RCC_MC_AHB6ENCLRR U(0x29C) #define RCC_MP_APB4LPENSETR U(0x300) #define RCC_MP_APB4LPENCLRR U(0x304) #define RCC_MP_APB5LPENSETR U(0x308) @@ -78,6 +86,14 @@ #define RCC_MP_AHB6LPENCLRR U(0x31C) #define RCC_MP_TZAHB6LPENSETR U(0x320) #define RCC_MP_TZAHB6LPENCLRR U(0x324) +#define RCC_MC_APB4LPENSETR U(0x380) +#define RCC_MC_APB4LPENCLRR U(0x384) +#define RCC_MC_APB5LPENSETR U(0x388) +#define RCC_MC_APB5LPENCLRR U(0x38C) +#define RCC_MC_AHB5LPENSETR U(0x390) +#define RCC_MC_AHB5LPENCLRR U(0x394) +#define RCC_MC_AHB6LPENSETR U(0x398) +#define RCC_MC_AHB6LPENCLRR U(0x39C) #define RCC_BR_RSTSCLRR U(0x400) #define RCC_MP_GRSTCSETR U(0x404) #define RCC_MP_RSTSCLRR U(0x408) @@ -162,6 +178,22 @@ #define RCC_MP_AHB4ENCLRR U(0xA2C) #define RCC_MP_MLAHBENSETR U(0xA38) #define RCC_MP_MLAHBENCLRR U(0xA3C) +#define RCC_MC_APB1ENSETR U(0xA80) +#define RCC_MC_APB1ENCLRR U(0xA84) +#define RCC_MC_APB2ENSETR U(0xA88) +#define RCC_MC_APB2ENCLRR U(0xA8C) +#define RCC_MC_APB3ENSETR U(0xA90) +#define RCC_MC_APB3ENCLRR U(0xA94) +#define RCC_MC_AHB2ENSETR U(0xA98) +#define RCC_MC_AHB2ENCLRR U(0xA9C) +#define RCC_MC_AHB3ENSETR U(0xAA0) +#define RCC_MC_AHB3ENCLRR U(0xAA4) +#define RCC_MC_AHB4ENSETR U(0xAA8) +#define RCC_MC_AHB4ENCLRR U(0xAAC) +#define RCC_MC_AXIMENSETR U(0xAB0) +#define RCC_MC_AXIMENCLRR U(0xAB4) +#define RCC_MC_MLAHBENSETR U(0xAB8) +#define RCC_MC_MLAHBENCLRR U(0xABC) #define RCC_MP_APB1LPENSETR U(0xB00) #define RCC_MP_APB1LPENCLRR U(0xB04) #define RCC_MP_APB2LPENSETR U(0xB08) @@ -178,10 +210,31 @@ #define RCC_MP_AXIMLPENCLRR U(0xB34) #define RCC_MP_MLAHBLPENSETR U(0xB38) #define RCC_MP_MLAHBLPENCLRR U(0xB3C) +#define RCC_MC_APB1LPENSETR U(0xB80) +#define RCC_MC_APB1LPENCLRR U(0xB84) +#define RCC_MC_APB2LPENSETR U(0xB88) +#define RCC_MC_APB2LPENCLRR U(0xB8C) +#define RCC_MC_APB3LPENSETR U(0xB90) +#define RCC_MC_APB3LPENCLRR U(0xB94) +#define RCC_MC_AHB2LPENSETR U(0xB98) +#define RCC_MC_AHB2LPENCLRR U(0xB9C) +#define RCC_MC_AHB3LPENSETR U(0xBA0) +#define RCC_MC_AHB3LPENCLRR U(0xBA4) +#define RCC_MC_AHB4LPENSETR U(0xBA8) +#define RCC_MC_AHB4LPENCLRR U(0xBAC) +#define RCC_MC_AXIMLPENSETR U(0xBB0) +#define RCC_MC_AXIMLPENCLRR U(0xBB4) +#define RCC_MC_MLAHBLPENSETR U(0xBB8) +#define RCC_MC_MLAHBLPENCLRR U(0xBBC) +#define RCC_MC_RSTSCLRR U(0xC00) +#define RCC_MC_CIER U(0xC14) +#define RCC_MC_CIFR U(0xC18) #define RCC_VERR U(0xFF4) #define RCC_IDR U(0xFF8) #define RCC_SIDR U(0xFFC) +#define RCC_OFFSET_MASK GENMASK(11, 0) + /* Values for RCC_TZCR register */ #define RCC_TZCR_TZEN BIT(0) @@ -221,6 +274,9 @@ #define RCC_MPUDIV_MASK GENMASK(2, 0) #define RCC_AXIDIV_MASK GENMASK(2, 0) +/* Used for TIMER Prescaler */ +#define RCC_TIMGXPRER_TIMGXPRE BIT(0) + /* Offset between RCC_MP_xxxENSETR and RCC_MP_xxxENCLRR registers */ #define RCC_MP_ENCLRR_OFFSET U(4) @@ -228,6 +284,7 @@ #define RCC_BDCR_LSEON BIT(0) #define RCC_BDCR_LSEBYP BIT(1) #define RCC_BDCR_LSERDY BIT(2) +#define RCC_BDCR_DIGBYP BIT(3) #define RCC_BDCR_LSEDRV_MASK GENMASK(5, 4) #define RCC_BDCR_LSEDRV_SHIFT 4 #define RCC_BDCR_LSECSSON BIT(8) @@ -243,6 +300,7 @@ /* Used for all RCC_PLLCR registers */ #define RCC_PLLNCR_PLLON BIT(0) #define RCC_PLLNCR_PLLRDY BIT(1) +#define RCC_PLLNCR_SSCG_CTRL BIT(2) #define RCC_PLLNCR_DIVPEN BIT(4) #define RCC_PLLNCR_DIVQEN BIT(5) #define RCC_PLLNCR_DIVREN BIT(6) @@ -281,8 +339,12 @@ /* Used for RCC_OCENSETR and RCC_OCENCLRR registers */ #define RCC_OCENR_HSION BIT(0) +#define RCC_OCENR_HSIKERON BIT(1) #define RCC_OCENR_CSION BIT(4) +#define RCC_OCENR_CSIKERON BIT(5) +#define RCC_OCENR_DIGBYP BIT(7) #define RCC_OCENR_HSEON BIT(8) +#define RCC_OCENR_HSEKERON BIT(9) #define RCC_OCENR_HSEBYP BIT(10) #define RCC_OCENR_HSECSSON BIT(11) @@ -319,6 +381,16 @@ /* Fields of RCC_HSICFGR register */ #define RCC_HSICFGR_HSIDIV_MASK GENMASK(1, 0) +#define RCC_HSICFGR_HSITRIM_SHIFT 8 +#define RCC_HSICFGR_HSITRIM_MASK GENMASK(14, 8) +#define RCC_HSICFGR_HSICAL_SHIFT 16 +#define RCC_HSICFGR_HSICAL_MASK GENMASK(27, 16) + +/* Fields of RCC_CSICFGR register */ +#define RCC_CSICFGR_CSITRIM_SHIFT 8 +#define RCC_CSICFGR_CSITRIM_MASK GENMASK(12, 8) +#define RCC_CSICFGR_CSICAL_SHIFT 16 +#define RCC_CSICFGR_CSICAL_MASK GENMASK(23, 16) /* Used for RCC_MCO related operations */ #define RCC_MCOCFG_MCOON BIT(12) @@ -330,22 +402,36 @@ #define RCC_DBGCFGR_DBGCKEN BIT(8) /* RCC register fields for reset reasons */ -#define RCC_MP_RSTSCLRR_PORRSTF BIT(0) -#define RCC_MP_RSTSCLRR_BORRSTF BIT(1) -#define RCC_MP_RSTSCLRR_PADRSTF BIT(2) -#define RCC_MP_RSTSCLRR_HCSSRSTF BIT(3) -#define RCC_MP_RSTSCLRR_VCORERSTF BIT(4) -#define RCC_MP_RSTSCLRR_MPSYSRSTF BIT(6) -#define RCC_MP_RSTSCLRR_IWDG1RSTF BIT(8) -#define RCC_MP_RSTSCLRR_IWDG2RSTF BIT(9) -#define RCC_MP_RSTSCLRR_STDBYRSTF BIT(11) -#define RCC_MP_RSTSCLRR_CSTDBYRSTF BIT(12) +#define RCC_MP_RSTSCLRR_PORRSTF BIT(0) +#define RCC_MP_RSTSCLRR_BORRSTF BIT(1) +#define RCC_MP_RSTSCLRR_PADRSTF BIT(2) +#define RCC_MP_RSTSCLRR_HCSSRSTF BIT(3) +#define RCC_MP_RSTSCLRR_VCORERSTF BIT(4) +#define RCC_MP_RSTSCLRR_MPSYSRSTF BIT(6) +#define RCC_MP_RSTSCLRR_MCSYSRSTF BIT(7) +#define RCC_MP_RSTSCLRR_IWDG1RSTF BIT(8) +#define RCC_MP_RSTSCLRR_IWDG2RSTF BIT(9) +#define RCC_MP_RSTSCLRR_STDBYRSTF BIT(11) +#define RCC_MP_RSTSCLRR_CSTDBYRSTF BIT(12) +#define RCC_MP_RSTSCLRR_MPUP0RSTF BIT(13) +#define RCC_MP_RSTSCLRR_MPUP1RSTF BIT(14) /* Global Reset Register */ #define RCC_MP_GRSTCSETR_MPSYSRST BIT(0) +#define RCC_MP_GRSTCSETR_MPUP0RST BIT(4) +#define RCC_MP_GRSTCSETR_MPUP1RST BIT(5) /* Clock Source Interrupt Flag Register */ #define RCC_MP_CIFR_MASK U(0x110F1F) +#define RCC_MP_CIFR_LSIRDYF BIT(0) +#define RCC_MP_CIFR_LSERDYF BIT(1) +#define RCC_MP_CIFR_HSIRDYF BIT(2) +#define RCC_MP_CIFR_HSERDYF BIT(3) +#define RCC_MP_CIFR_CSIRDYF BIT(4) +#define RCC_MP_CIFR_PLL1DYF BIT(8) +#define RCC_MP_CIFR_PLL2DYF BIT(9) +#define RCC_MP_CIFR_PLL3DYF BIT(10) +#define RCC_MP_CIFR_PLL4DYF BIT(11) #define RCC_MP_CIFR_WKUPF BIT(20) /* Stop Request Set Register */ @@ -362,7 +448,29 @@ /* Values of RCC_MP_APB1ENSETR register */ #define RCC_MP_APB1ENSETR_UART4EN BIT(16) +/* Values of RCC_MP_APB5ENSETR register */ +#define RCC_MP_APB5ENSETR_SPI6EN BIT(0) +#define RCC_MP_APB5ENSETR_I2C4EN BIT(2) +#define RCC_MP_APB5ENSETR_I2C6EN BIT(3) +#define RCC_MP_APB5ENSETR_USART1EN BIT(4) +#define RCC_MP_APB5ENSETR_RTCAPBEN BIT(8) +#define RCC_MP_APB5ENSETR_IWDG1APBEN BIT(15) + /* Values of RCC_MP_AHB4ENSETR register */ #define RCC_MP_AHB4ENSETR_GPIOGEN BIT(6) +#define RCC_MP_AHB4ENSETR_GPIOHEN BIT(7) + +/* Values of RCC_MP_AHB5ENSETR register */ +#define RCC_MP_AHB5ENSETR_GPIOZEN BIT(0) +#define RCC_MP_AHB5ENSETR_CRYP1EN BIT(4) +#define RCC_MP_AHB5ENSETR_HASH1EN BIT(5) +#define RCC_MP_AHB5ENSETR_RNG1EN BIT(6) + +/* Values of RCC_MP_IWDGFZSETR register */ +#define RCC_MP_IWDGFZSETR_IWDG1 BIT(0) +#define RCC_MP_IWDGFZSETR_IWDG2 BIT(1) + +/* Values of RCC_PWRLPDLYCR register */ +#define RCC_PWRLPDLYCR_PWRLP_DLY_MASK GENMASK(21, 0) #endif /* STM32MP1_RCC_H */ diff --git a/include/drivers/st/stm32mp1_pmic.h b/include/drivers/st/stm32mp_pmic.h similarity index 67% rename from include/drivers/st/stm32mp1_pmic.h rename to include/drivers/st/stm32mp_pmic.h index 75f8e61f7206c0a206e94c015ae1d763ed6d6350..700039b268a0198005b9d798d48531ce3b9b28b1 100644 --- a/include/drivers/st/stm32mp1_pmic.h +++ b/include/drivers/st/stm32mp_pmic.h @@ -1,11 +1,11 @@ /* - * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved + * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved * * SPDX-License-Identifier: BSD-3-Clause */ -#ifndef STM32MP1_PMIC_H -#define STM32MP1_PMIC_H +#ifndef STM32MP_PMIC_H +#define STM32MP_PMIC_H #include @@ -17,4 +17,4 @@ void initialize_pmic_i2c(void); void initialize_pmic(void); int pmic_ddr_power_init(enum ddr_type ddr_type); -#endif /* STM32MP1_PMIC_H */ +#endif /* STM32MP_PMIC_H */ diff --git a/include/drivers/st/stpmu1.h b/include/drivers/st/stpmic1.h similarity index 70% rename from include/drivers/st/stpmu1.h rename to include/drivers/st/stpmic1.h index e75d9a66b2f0c842d0df5b00fefd998d810bc414..f7e293b18996f706c3cf9f27befcbdd73bf9a331 100644 --- a/include/drivers/st/stpmu1.h +++ b/include/drivers/st/stpmic1.h @@ -1,11 +1,11 @@ /* - * Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved + * Copyright (c) 2016-2019, STMicroelectronics - All Rights Reserved * * SPDX-License-Identifier: BSD-3-Clause */ -#ifndef STPMU1_H -#define STPMU1_H +#ifndef STPMIC1_H +#define STPMIC1_H #include #include @@ -84,18 +84,40 @@ #define ITSOURCE2_REG 0xB1U #define ITSOURCE3_REG 0xB2U #define ITSOURCE4_REG 0xB3U + +/* Registers masks */ #define LDO_VOLTAGE_MASK 0x7CU #define BUCK_VOLTAGE_MASK 0xFCU #define LDO_BUCK_VOLTAGE_SHIFT 2 -#define LDO_ENABLE_MASK 0x01U -#define BUCK_ENABLE_MASK 0x01U -#define BUCK_HPLP_ENABLE_MASK 0x02U -#define LDO_HPLP_ENABLE_MASK 0x02U +#define LDO_BUCK_ENABLE_MASK 0x01U +#define LDO_BUCK_HPLP_ENABLE_MASK 0x02U #define LDO_BUCK_HPLP_SHIFT 1 #define LDO_BUCK_RANK_MASK 0x01U #define LDO_BUCK_RESET_MASK 0x01U #define LDO_BUCK_PULL_DOWN_MASK 0x03U +/* Pull down register */ +#define BUCK1_PULL_DOWN_SHIFT 0 +#define BUCK2_PULL_DOWN_SHIFT 2 +#define BUCK3_PULL_DOWN_SHIFT 4 +#define BUCK4_PULL_DOWN_SHIFT 6 +#define VREF_DDR_PULL_DOWN_SHIFT 4 + +/* Buck Mask reset register */ +#define BUCK1_MASK_RESET 0 +#define BUCK2_MASK_RESET 1 +#define BUCK3_MASK_RESET 2 +#define BUCK4_MASK_RESET 3 + +/* LDO Mask reset register */ +#define LDO1_MASK_RESET 0 +#define LDO2_MASK_RESET 1 +#define LDO3_MASK_RESET 2 +#define LDO4_MASK_RESET 3 +#define LDO5_MASK_RESET 4 +#define LDO6_MASK_RESET 5 +#define VREF_DDR_MASK_RESET 6 + /* Main PMIC Control Register (MAIN_CONTROL_REG) */ #define ICC_EVENT_ENABLED BIT(4) #define PWRCTRL_POLARITY_HIGH BIT(3) @@ -127,14 +149,21 @@ #define SWIN_SWOUT_ENABLED BIT(2) #define USBSW_OTG_SWITCH_ENABLED BIT(1) -int stpmu1_switch_off(void); -int stpmu1_register_read(uint8_t register_id, uint8_t *value); -int stpmu1_register_write(uint8_t register_id, uint8_t value); -int stpmu1_register_update(uint8_t register_id, uint8_t value, uint8_t mask); -int stpmu1_regulator_enable(const char *name); -int stpmu1_regulator_disable(const char *name); -uint8_t stpmu1_is_regulator_enabled(const char *name); -int stpmu1_regulator_voltage_set(const char *name, uint16_t millivolts); -void stpmu1_bind_i2c(struct i2c_handle_s *i2c_handle, uint16_t i2c_addr); +int stpmic1_powerctrl_on(void); +int stpmic1_switch_off(void); +int stpmic1_register_read(uint8_t register_id, uint8_t *value); +int stpmic1_register_write(uint8_t register_id, uint8_t value); +int stpmic1_register_update(uint8_t register_id, uint8_t value, uint8_t mask); +int stpmic1_regulator_enable(const char *name); +int stpmic1_regulator_disable(const char *name); +uint8_t stpmic1_is_regulator_enabled(const char *name); +int stpmic1_regulator_voltage_set(const char *name, uint16_t millivolts); +int stpmic1_regulator_voltage_get(const char *name); +int stpmic1_regulator_pull_down_set(const char *name); +int stpmic1_regulator_mask_reset_set(const char *name); +void stpmic1_bind_i2c(struct i2c_handle_s *i2c_handle, uint16_t i2c_addr); + +int stpmic1_get_version(unsigned long *version); +void stpmic1_dump_regulators(void); -#endif /* STPMU1_H */ +#endif /* STPMIC1_H */ diff --git a/include/dt-bindings/interrupt-controller/arm-gic.h b/include/dt-bindings/interrupt-controller/arm-gic.h new file mode 100644 index 0000000000000000000000000000000000000000..aa9158cb1b7504b7b8bb5a79e4a64896652ec2a6 --- /dev/null +++ b/include/dt-bindings/interrupt-controller/arm-gic.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */ +/* + * This header provides constants for the ARM GIC. + */ + +#ifndef _DT_BINDINGS_INTERRUPT_CONTROLLER_ARM_GIC_H +#define _DT_BINDINGS_INTERRUPT_CONTROLLER_ARM_GIC_H + +/* interrupt specifier cell 0 */ + +#define GIC_SPI 0 +#define GIC_PPI 1 + +#define IRQ_TYPE_NONE 0 +#define IRQ_TYPE_EDGE_RISING 1 +#define IRQ_TYPE_EDGE_FALLING 2 +#define IRQ_TYPE_EDGE_BOTH (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING) +#define IRQ_TYPE_LEVEL_HIGH 4 +#define IRQ_TYPE_LEVEL_LOW 8 + +#endif diff --git a/include/dt-bindings/pinctrl/stm32-pinfunc.h b/include/dt-bindings/pinctrl/stm32-pinfunc.h index e2f1f1b44d68024829d4f75f0d3c6144b27b2e9d..7f6e4b94ddd739073d480d7c5573a4872b36f809 100644 --- a/include/dt-bindings/pinctrl/stm32-pinfunc.h +++ b/include/dt-bindings/pinctrl/stm32-pinfunc.h @@ -32,4 +32,10 @@ #define STM32_PINMUX(port, line, mode) (((PIN_NO(port, line)) << 8) | (mode)) +/* package information */ +#define STM32MP157CAA 0x1 +#define STM32MP157CAB 0x2 +#define STM32MP157CAC 0x4 +#define STM32MP157CAD 0x8 + #endif /* _DT_BINDINGS_STM32_PINFUNC_H */ diff --git a/plat/st/stm32mp1/bl2_io_storage.c b/plat/st/stm32mp1/bl2_io_storage.c index 45a352e0c5a12434cb97f24df0722463e8094f89..8ccbc246c9a13fcd77d91a8c270ec015fb48e050 100644 --- a/plat/st/stm32mp1/bl2_io_storage.c +++ b/plat/st/stm32mp1/bl2_io_storage.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -58,13 +58,26 @@ static const io_block_dev_spec_t mmc_block_dev_spec = { static uintptr_t storage_dev_handle; static const io_dev_connector_t *mmc_dev_con; -#define IMG_IDX_BL33 0 +static const io_block_spec_t bl32_block_spec = { + .offset = BL32_BASE, + .length = STM32MP1_BL32_SIZE +}; + +static const io_block_spec_t bl2_block_spec = { + .offset = BL2_BASE, + .length = STM32MP1_BL2_SIZE, +}; static const struct stm32image_part_info bl33_partition_spec = { .name = BL33_IMAGE_NAME, .binary_type = BL33_BINARY_TYPE, }; +enum { + IMG_IDX_BL33, + IMG_IDX_NUM +}; + static struct stm32image_device_info stm32image_dev_info_spec = { .lba_size = MMC_BLOCK_SIZE, .part_info[IMG_IDX_BL33] = { @@ -73,19 +86,12 @@ static struct stm32image_device_info stm32image_dev_info_spec = { }, }; -static io_block_spec_t stm32image_block_spec; - -static const io_dev_connector_t *stm32image_dev_con; - -static const io_block_spec_t bl32_block_spec = { - .offset = BL32_BASE, - .length = STM32MP1_BL32_SIZE +static io_block_spec_t stm32image_block_spec = { + .offset = 0, + .length = 0, }; -static const io_block_spec_t bl2_block_spec = { - .offset = BL2_BASE, - .length = STM32MP1_BL2_SIZE, -}; +static const io_dev_connector_t *stm32image_dev_con; static int open_dummy(const uintptr_t spec); static int open_image(const uintptr_t spec); @@ -160,83 +166,18 @@ static void print_boot_device(boot_api_context_t *boot_context) } } -static void print_reset_reason(void) -{ - uint32_t rstsr = mmio_read_32(RCC_BASE + RCC_MP_RSTSCLRR); - - if (rstsr == 0U) { - WARN("Reset reason unknown\n"); - return; - } - - INFO("Reset reason (0x%x):\n", rstsr); - - if ((rstsr & RCC_MP_RSTSCLRR_PADRSTF) == 0U) { - if ((rstsr & RCC_MP_RSTSCLRR_STDBYRSTF) != 0U) { - INFO("System exits from STANDBY\n"); - return; - } - - if ((rstsr & RCC_MP_RSTSCLRR_CSTDBYRSTF) != 0U) { - INFO("MPU exits from CSTANDBY\n"); - return; - } - } - - if ((rstsr & RCC_MP_RSTSCLRR_PORRSTF) != 0U) { - INFO(" Power-on Reset (rst_por)\n"); - return; - } - - if ((rstsr & RCC_MP_RSTSCLRR_BORRSTF) != 0U) { - INFO(" Brownout Reset (rst_bor)\n"); - return; - } - - if ((rstsr & RCC_MP_RSTSCLRR_MPSYSRSTF) != 0U) { - INFO(" System reset generated by MPU (MPSYSRST)\n"); - return; - } - - if ((rstsr & RCC_MP_RSTSCLRR_HCSSRSTF) != 0U) { - INFO(" Reset due to a clock failure on HSE\n"); - return; - } - - if ((rstsr & RCC_MP_RSTSCLRR_IWDG1RSTF) != 0U) { - INFO(" IWDG1 Reset (rst_iwdg1)\n"); - return; - } - - if ((rstsr & RCC_MP_RSTSCLRR_IWDG2RSTF) != 0U) { - INFO(" IWDG2 Reset (rst_iwdg2)\n"); - return; - } - - if ((rstsr & RCC_MP_RSTSCLRR_PADRSTF) != 0U) { - INFO(" Pad Reset from NRST\n"); - return; - } - - if ((rstsr & RCC_MP_RSTSCLRR_VCORERSTF) != 0U) { - INFO(" Reset due to a failure of VDD_CORE\n"); - return; - } - - ERROR(" Unidentified reset reason\n"); -} - void stm32mp1_io_setup(void) { int io_result __unused; + uint8_t idx; + struct stm32image_part_info *part; struct stm32_sdmmc2_params params; struct mmc_device_info device_info; uintptr_t mmc_default_instance; + const partition_entry_t *entry; boot_api_context_t *boot_context = (boot_api_context_t *)stm32mp1_get_boot_ctx_address(); - print_reset_reason(); - print_boot_device(boot_context); if ((boot_context->boot_partition_used_toboot == 1U) || @@ -255,7 +196,7 @@ void stm32mp1_io_setup(void) switch (boot_context->boot_interface_selected) { case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD: case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC: - dmb(); + dmbsy(); memset(¶ms, 0, sizeof(struct stm32_sdmmc2_params)); @@ -309,14 +250,19 @@ void stm32mp1_io_setup(void) stm32image_dev_info_spec.device_size = stm32_sdmmc2_mmc_get_device_size(); - stm32image_dev_info_spec.part_info[IMG_IDX_BL33].part_offset = - get_partition_entry(BL33_IMAGE_NAME)->start; - stm32image_dev_info_spec.part_info[IMG_IDX_BL33].bkp_offset = - get_partition_entry(BL33_IMAGE_NAME)->length; - - stm32image_block_spec.offset = 0; - stm32image_block_spec.length = - get_partition_entry(BL33_IMAGE_NAME)->length; + + for (idx = 0U; idx < IMG_IDX_NUM; idx++) { + part = &stm32image_dev_info_spec.part_info[idx]; + entry = get_partition_entry(part->name); + if (entry == NULL) { + ERROR("Partition %s not found\n", + part->name); + panic(); + } + + part->part_offset = entry->start; + part->bkp_offset = 0U; + } /* * Re-open MMC with io_mmc, for better perfs compared to diff --git a/plat/st/stm32mp1/bl2_plat_setup.c b/plat/st/stm32mp1/bl2_plat_setup.c index 6af65fd26edc50e8405044075f79fed29f6f25db..a1ffd5a9db5a05d572add84f5251e314dbb6887a 100644 --- a/plat/st/stm32mp1/bl2_plat_setup.c +++ b/plat/st/stm32mp1/bl2_plat_setup.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -16,8 +16,8 @@ #include #include #include +#include #include -#include #include #include #include @@ -33,8 +33,95 @@ static struct console_stm32 console; -void bl2_el3_early_platform_setup(u_register_t arg0, u_register_t arg1, - u_register_t arg2, u_register_t arg3) +static void print_reset_reason(void) +{ + uint32_t rstsr = mmio_read_32(RCC_BASE + RCC_MP_RSTSCLRR); + + if (rstsr == 0U) { + WARN("Reset reason unknown\n"); + return; + } + + INFO("Reset reason (0x%x):\n", rstsr); + + if ((rstsr & RCC_MP_RSTSCLRR_PADRSTF) == 0U) { + if ((rstsr & RCC_MP_RSTSCLRR_STDBYRSTF) != 0U) { + INFO("System exits from STANDBY\n"); + return; + } + + if ((rstsr & RCC_MP_RSTSCLRR_CSTDBYRSTF) != 0U) { + INFO("MPU exits from CSTANDBY\n"); + return; + } + } + + if ((rstsr & RCC_MP_RSTSCLRR_PORRSTF) != 0U) { + INFO(" Power-on Reset (rst_por)\n"); + return; + } + + if ((rstsr & RCC_MP_RSTSCLRR_BORRSTF) != 0U) { + INFO(" Brownout Reset (rst_bor)\n"); + return; + } + + if ((rstsr & RCC_MP_RSTSCLRR_MCSYSRSTF) != 0U) { + if ((rstsr & RCC_MP_RSTSCLRR_PADRSTF) != 0U) { + INFO(" System reset generated by MCU (MCSYSRST)\n"); + } else { + INFO(" Local reset generated by MCU (MCSYSRST)\n"); + } + return; + } + + if ((rstsr & RCC_MP_RSTSCLRR_MPSYSRSTF) != 0U) { + INFO(" System reset generated by MPU (MPSYSRST)\n"); + return; + } + + if ((rstsr & RCC_MP_RSTSCLRR_HCSSRSTF) != 0U) { + INFO(" Reset due to a clock failure on HSE\n"); + return; + } + + if ((rstsr & RCC_MP_RSTSCLRR_IWDG1RSTF) != 0U) { + INFO(" IWDG1 Reset (rst_iwdg1)\n"); + return; + } + + if ((rstsr & RCC_MP_RSTSCLRR_IWDG2RSTF) != 0U) { + INFO(" IWDG2 Reset (rst_iwdg2)\n"); + return; + } + + if ((rstsr & RCC_MP_RSTSCLRR_MPUP0RSTF) != 0U) { + INFO(" MPU Processor 0 Reset\n"); + return; + } + + if ((rstsr & RCC_MP_RSTSCLRR_MPUP1RSTF) != 0U) { + INFO(" MPU Processor 1 Reset\n"); + return; + } + + if ((rstsr & RCC_MP_RSTSCLRR_PADRSTF) != 0U) { + INFO(" Pad Reset from NRST\n"); + return; + } + + if ((rstsr & RCC_MP_RSTSCLRR_VCORERSTF) != 0U) { + INFO(" Reset due to a failure of VDD_CORE\n"); + return; + } + + ERROR(" Unidentified reset reason\n"); +} + +void bl2_el3_early_platform_setup(u_register_t arg0, + u_register_t arg1 __unused, + u_register_t arg2 __unused, + u_register_t arg3 __unused) { stm32mp1_save_boot_ctx_address(arg0); } @@ -59,12 +146,38 @@ void bl2_platform_setup(void) void bl2_el3_plat_arch_setup(void) { int32_t result; - struct dt_node_info dt_dev_info; + struct dt_node_info dt_uart_info; const char *board_model; boot_api_context_t *boot_context = (boot_api_context_t *)stm32mp1_get_boot_ctx_address(); uint32_t clk_rate; + mmap_add_region(BL_CODE_BASE, BL_CODE_BASE, + BL_CODE_END - BL_CODE_BASE, + MT_CODE | MT_SECURE); + + /* Prevent corruption of preloaded BL32 */ + mmap_add_region(BL32_BASE, BL32_BASE, + BL32_LIMIT - BL32_BASE, + MT_MEMORY | MT_RO | MT_SECURE); + + /* Map non secure DDR for BL33 load and DDR training area restore */ + mmap_add_region(STM32MP1_DDR_BASE, + STM32MP1_DDR_BASE, + STM32MP1_DDR_MAX_SIZE, + MT_MEMORY | MT_RW | MT_NS); + + /* Prevent corruption of preloaded Device Tree */ + mmap_add_region(DTB_BASE, DTB_BASE, + DTB_LIMIT - DTB_BASE, + MT_MEMORY | MT_RO | MT_SECURE); + + configure_mmu(); + + if (dt_open_and_check() < 0) { + panic(); + } + /* * Disable the backup domain write protection. * The protection is enable at each reset by hardware @@ -88,28 +201,8 @@ void bl2_el3_plat_arch_setup(void) mmio_clrbits_32(RCC_BASE + RCC_BDCR, RCC_BDCR_VSWRST); } - mmap_add_region(BL_CODE_BASE, BL_CODE_BASE, - BL_CODE_END - BL_CODE_BASE, - MT_CODE | MT_SECURE); - - /* Prevent corruption of preloaded BL32 */ - mmap_add_region(BL32_BASE, BL32_BASE, - BL32_LIMIT - BL32_BASE, - MT_MEMORY | MT_RO | MT_SECURE); - - /* Prevent corruption of preloaded Device Tree */ - mmap_add_region(DTB_BASE, DTB_BASE, - DTB_LIMIT - DTB_BASE, - MT_MEMORY | MT_RO | MT_SECURE); - - configure_mmu(); - generic_delay_timer_init(); - if (dt_open_and_check() < 0) { - panic(); - } - if (stm32mp1_clk_probe() < 0) { panic(); } @@ -118,12 +211,12 @@ void bl2_el3_plat_arch_setup(void) panic(); } - result = dt_get_stdout_uart_info(&dt_dev_info); + result = dt_get_stdout_uart_info(&dt_uart_info); if ((result <= 0) || - (dt_dev_info.status == 0U) || - (dt_dev_info.clock < 0) || - (dt_dev_info.reset < 0)) { + (dt_uart_info.status == 0U) || + (dt_uart_info.clock < 0) || + (dt_uart_info.reset < 0)) { goto skip_console_init; } @@ -131,25 +224,25 @@ void bl2_el3_plat_arch_setup(void) goto skip_console_init; } - if (stm32mp1_clk_enable((unsigned long)dt_dev_info.clock) != 0) { + if (stm32mp1_clk_enable((unsigned long)dt_uart_info.clock) != 0) { goto skip_console_init; } - stm32mp1_reset_assert((uint32_t)dt_dev_info.reset); + stm32mp1_reset_assert((uint32_t)dt_uart_info.reset); udelay(2); - stm32mp1_reset_deassert((uint32_t)dt_dev_info.reset); + stm32mp1_reset_deassert((uint32_t)dt_uart_info.reset); mdelay(1); - clk_rate = stm32mp1_clk_get_rate((unsigned long)dt_dev_info.clock); + clk_rate = stm32mp1_clk_get_rate((unsigned long)dt_uart_info.clock); - if (console_stm32_register(dt_dev_info.base, clk_rate, + if (console_stm32_register(dt_uart_info.base, clk_rate, STM32MP1_UART_BAUDRATE, &console) == 0) { panic(); } board_model = dt_get_board_model(); if (board_model != NULL) { - NOTICE("%s\n", board_model); + NOTICE("Model: %s\n", board_model); } skip_console_init: @@ -162,5 +255,7 @@ skip_console_init: stm32mp1_arch_security_setup(); + print_reset_reason(); + stm32mp1_io_setup(); } diff --git a/plat/st/stm32mp1/include/platform_def.h b/plat/st/stm32mp1/include/platform_def.h index 1b4df163bbc0aef167a1d2a0132024ab2a04cc1b..6d3d36dbad4e7a556779b237c1da20b10bdcc926 100644 --- a/plat/st/stm32mp1/include/platform_def.h +++ b/plat/st/stm32mp1/include/platform_def.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -30,8 +30,8 @@ #define BL33_BINARY_TYPE U(0x0) #define STM32MP1_PRIMARY_CPU U(0x0) +#define STM32MP1_SECONDARY_CPU U(0x1) -#define PLATFORM_CACHE_LINE_SIZE 64 #define PLATFORM_CLUSTER_COUNT ULL(1) #define PLATFORM_CLUSTER0_CORE_COUNT U(2) #define PLATFORM_CLUSTER1_CORE_COUNT U(0) @@ -39,9 +39,9 @@ PLATFORM_CLUSTER0_CORE_COUNT) #define PLATFORM_MAX_CPUS_PER_CLUSTER 2 -#define MAX_IO_DEVICES 4 -#define MAX_IO_HANDLES 4 -#define MAX_IO_BLOCK_DEVICES 1 +#define MAX_IO_DEVICES U(4) +#define MAX_IO_HANDLES U(4) +#define MAX_IO_BLOCK_DEVICES U(1) /******************************************************************************* * BL2 specific defines. @@ -81,8 +81,8 @@ /******************************************************************************* * Platform specific page table and MMU setup constants ******************************************************************************/ -#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) -#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 32) +#define PLAT_PHY_ADDR_SPACE_SIZE (ULL(1) << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (ULL(1) << 32) /******************************************************************************* * Declarations and constants to access the mailboxes safely. Each mailbox is @@ -123,9 +123,6 @@ INTR_PROP_DESC(ARM_IRQ_SEC_PHY_TIMER, \ GIC_HIGHEST_SEC_PRIORITY, \ grp, GIC_INTR_CFG_LEVEL), \ - INTR_PROP_DESC(STM32MP1_IRQ_TAMPSERRS, \ - GIC_HIGHEST_SEC_PRIORITY, \ - grp, GIC_INTR_CFG_LEVEL), \ INTR_PROP_DESC(STM32MP1_IRQ_AXIERRIRQ, \ GIC_HIGHEST_SEC_PRIORITY, \ grp, GIC_INTR_CFG_LEVEL), \ diff --git a/plat/st/stm32mp1/include/stm32mp1_dt.h b/plat/st/stm32mp1/include/stm32mp1_dt.h index 19549ee9767b2b8b3323f81586b660ad8f025123..d5640c1fd5607c229dd397d26882c83d1f9f2bb3 100644 --- a/plat/st/stm32mp1/include/stm32mp1_dt.h +++ b/plat/st/stm32mp1/include/stm32mp1_dt.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -9,12 +9,16 @@ #include +#define DT_DISABLED U(0) +#define DT_NON_SECURE U(1) +#define DT_SECURE U(2) +#define DT_SHARED (DT_NON_SECURE | DT_SECURE) + struct dt_node_info { uint32_t base; int32_t clock; int32_t reset; - bool status; - bool sec_status; + uint32_t status; }; /******************************************************************************* @@ -23,13 +27,11 @@ struct dt_node_info { int dt_open_and_check(void); int fdt_get_address(void **fdt_addr); bool fdt_check_node(int node); -bool fdt_check_status(int node); -bool fdt_check_secure_status(int node); +uint32_t fdt_get_status(int node); uint32_t fdt_read_uint32_default(int node, const char *prop_name, uint32_t dflt_value); int fdt_read_uint32_array(int node, const char *prop_name, uint32_t *array, uint32_t count); -int dt_set_pinctrl_config(int node); int dt_set_stdout_pinctrl(void); void dt_fill_device_info(struct dt_node_info *info, int node); int dt_get_node(struct dt_node_info *info, int offset, const char *compat); diff --git a/plat/st/stm32mp1/include/stm32mp1_private.h b/plat/st/stm32mp1/include/stm32mp1_private.h index 3404bc685037fa0826b4daf30bb8207e753bfd6f..04c9a9ad5fb566230eb23d1ca1bf8d97d768b1af 100644 --- a/plat/st/stm32mp1/include/stm32mp1_private.h +++ b/plat/st/stm32mp1/include/stm32mp1_private.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -21,4 +21,8 @@ uintptr_t stm32mp1_get_boot_ctx_address(void); void stm32mp1_gic_pcpu_init(void); void stm32mp1_gic_init(void); +uintptr_t stm32_get_gpio_bank_base(unsigned int bank); +unsigned long stm32_get_gpio_bank_clock(unsigned int bank); +uint32_t stm32_get_gpio_bank_offset(unsigned int bank); + #endif /* STM32MP1_PRIVATE_H */ diff --git a/plat/st/stm32mp1/include/stm32mp1_smc.h b/plat/st/stm32mp1/include/stm32mp1_smc.h new file mode 100644 index 0000000000000000000000000000000000000000..b87275839370d765cb349cba6692e3fccfa61b3e --- /dev/null +++ b/plat/st/stm32mp1/include/stm32mp1_smc.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2016-2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32MP1_SMC_H +#define STM32MP1_SMC_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) + * https://developer.arm.com/docs/den0028/latest + */ + +/* Secure Service access from Non-secure */ + +/* + * STM32_SMC_BSEC call API + * + * Argument a0: (input) SMCC ID + * (output) status return code + * Argument a1: (input) Service ID (STM32_SMC_BSEC_xxx) + * Argument a2: (input) OTP index + * (output) OTP read value, if applicable + * Argument a3: (input) OTP value if applicable + */ +#define STM32_SMC_BSEC 0x82001003 + +/* SMC function IDs for SiP Service queries */ +#define STM32_SIP_SVC_CALL_COUNT 0x8200ff00 +#define STM32_SIP_SVC_UID 0x8200ff01 +/* 0x8200ff02 is reserved */ +#define STM32_SIP_SVC_VERSION 0x8200ff03 + +/* STM32 SiP Service Calls version numbers */ +#define STM32_SIP_SVC_VERSION_MAJOR 0x0 +#define STM32_SIP_SVC_VERSION_MINOR 0x1 + +/* Number of STM32 SiP Calls implemented */ +#define STM32_COMMON_SIP_NUM_CALLS 4 + +/* 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 + +#endif /* STM32MP1_SMC_H */ diff --git a/plat/st/stm32mp1/platform.mk b/plat/st/stm32mp1/platform.mk index 60852c6b4f965e940a6ab81f99584ba182f0c110..4288f23d9140ee574ef02ac99ce0b37375a82b09 100644 --- a/plat/st/stm32mp1/platform.mk +++ b/plat/st/stm32mp1/platform.mk @@ -1,5 +1,5 @@ # -# Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. +# Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # @@ -24,8 +24,8 @@ $(eval $(call add_define,PLAT_PARTITION_MAX_ENTRIES)) PLAT_INCLUDES := -Iplat/st/stm32mp1/include/ # Device tree -STM32_DTB_FILE_NAME ?= stm32mp157c-ev1.dtb -FDT_SOURCES := $(addprefix fdts/, $(patsubst %.dtb,%.dts,$(STM32_DTB_FILE_NAME))) +DTB_FILE_NAME ?= stm32mp157c-ev1.dtb +FDT_SOURCES := $(addprefix fdts/, $(patsubst %.dtb,%.dts,$(DTB_FILE_NAME))) DTC_FLAGS += -Wno-unit_address_vs_reg include lib/libfdt/libfdt.mk @@ -47,13 +47,14 @@ PLAT_BL_COMMON_SOURCES += ${LIBFDT_SRCS} \ drivers/arm/tzc/tzc400.c \ drivers/delay_timer/delay_timer.c \ drivers/delay_timer/generic_delay_timer.c \ + drivers/st/bsec/bsec.c \ drivers/st/clk/stm32mp1_clk.c \ drivers/st/clk/stm32mp1_clkfunc.c \ drivers/st/ddr/stm32mp1_ddr_helpers.c \ drivers/st/gpio/stm32_gpio.c \ - drivers/st/pmic/stm32_i2c.c \ - drivers/st/pmic/stm32mp1_pmic.c \ - drivers/st/pmic/stpmu1.c \ + drivers/st/i2c/stm32_i2c.c \ + drivers/st/pmic/stm32mp_pmic.c \ + drivers/st/pmic/stpmic1.c \ drivers/st/reset/stm32mp1_reset.c \ plat/st/stm32mp1/stm32mp1_context.c \ plat/st/stm32mp1/stm32mp1_dt.c \ @@ -82,13 +83,13 @@ BL2_SOURCES += common/desc_image_load.c \ # Macros and rules to build TF binary STM32_TF_ELF_LDFLAGS := --hash-style=gnu --as-needed -STM32_DT_BASENAME := $(STM32_DTB_FILE_NAME:.dtb=) +STM32_DT_BASENAME := $(DTB_FILE_NAME:.dtb=) STM32_TF_STM32 := ${BUILD_PLAT}/tf-a-${STM32_DT_BASENAME}.stm32 STM32_TF_BINARY := $(STM32_TF_STM32:.stm32=.bin) STM32_TF_MAPFILE := $(STM32_TF_STM32:.stm32=.map) STM32_TF_LINKERFILE := $(STM32_TF_STM32:.stm32=.ld) STM32_TF_ELF := $(STM32_TF_STM32:.stm32=.elf) -STM32_TF_DTBFILE := ${BUILD_PLAT}/fdts/${STM32_DTB_FILE_NAME} +STM32_TF_DTBFILE := ${BUILD_PLAT}/fdts/${DTB_FILE_NAME} STM32_TF_OBJS := ${BUILD_PLAT}/stm32mp1.o # Variables for use with stm32image @@ -131,7 +132,7 @@ ${STM32_TF_OBJS}: plat/st/stm32mp1/stm32mp1.S bl2 ${BL32_DEP} ${STM32_TF_DTBFILE -DDTB_BIN_PATH=\"${STM32_TF_DTBFILE}\" \ -c plat/st/stm32mp1/stm32mp1.S -o $@ -${STM32_TF_LINKERFILE}: plat/st/stm32mp1/stm32mp1.ld.S +${STM32_TF_LINKERFILE}: plat/st/stm32mp1/stm32mp1.ld.S ${BUILD_PLAT} @echo " LDS $<" ${Q}${AS} ${ASFLAGS} ${TF_CFLAGS} -P -E $< -o $@ diff --git a/plat/st/stm32mp1/services/bsec_svc.c b/plat/st/stm32mp1/services/bsec_svc.c new file mode 100644 index 0000000000000000000000000000000000000000..2a60e433939cf6dbfde669aee3c4deef56183c5b --- /dev/null +++ b/plat/st/stm32mp1/services/bsec_svc.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2016-2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +#include + +#include "bsec_svc.h" + +uint32_t bsec_main(uint32_t x1, uint32_t x2, uint32_t x3, + uint32_t *ret_otp_value) +{ + uint32_t result; + uint32_t tmp_data = 0U; + + switch (x1) { + case STM32_SMC_READ_SHADOW: + result = bsec_read_otp(ret_otp_value, x2); + break; + case STM32_SMC_PROG_OTP: + *ret_otp_value = 0U; + result = bsec_program_otp(x3, x2); + break; + case STM32_SMC_WRITE_SHADOW: + *ret_otp_value = 0; + result = bsec_write_otp(x3, x2); + break; + case STM32_SMC_READ_OTP: + *ret_otp_value = 0; + result = bsec_read_otp(&tmp_data, x2); + if (result != BSEC_OK) { + break; + } + + result = bsec_shadow_register(x2); + if (result != BSEC_OK) { + break; + } + + result = bsec_read_otp(ret_otp_value, x2); + if (result != BSEC_OK) { + break; + } + + result = bsec_write_otp(tmp_data, x2); + break; + + default: + result = BSEC_ERROR; + break; + } + + return result; +} diff --git a/plat/st/stm32mp1/services/bsec_svc.h b/plat/st/stm32mp1/services/bsec_svc.h new file mode 100644 index 0000000000000000000000000000000000000000..06752ef4df40ce68db627cbdff50438568276c05 --- /dev/null +++ b/plat/st/stm32mp1/services/bsec_svc.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2016-2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BSEC_SVC_H +#define BSEC_SVC_H + +#include + +/* version of this service */ +/* must be increase at each structure modification */ +#define BSEC_SERVICE_VERSION 0x01U + +uint32_t bsec_main(uint32_t x1, uint32_t x2, uint32_t x3, + uint32_t *ret_otp_value); + +#endif /* BSEC_SVC_H */ diff --git a/plat/st/stm32mp1/services/stm32mp1_svc_setup.c b/plat/st/stm32mp1/services/stm32mp1_svc_setup.c new file mode 100644 index 0000000000000000000000000000000000000000..72af9ff335b9081d1b24e20fdd827397a5f98b4f --- /dev/null +++ b/plat/st/stm32mp1/services/stm32mp1_svc_setup.c @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2014-2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include + +#include + +#include "bsec_svc.h" + +/* STM32 SiP Service UUID */ +DEFINE_SVC_UUID2(stm32_sip_svc_uid, + 0xa778aa50, 0xf49b, 0x144a, 0x8a, 0x5e, + 0x26, 0x4d, 0x59, 0x94, 0xc2, 0x14); + +/* Setup STM32MP1 Standard Services */ +static int32_t stm32mp1_svc_setup(void) +{ + /* + * PSCI is the only specification implemented as a Standard Service. + * Invoke PSCI setup from here. + */ + return 0; +} + +/* + * Top-level Standard Service SMC handler. This handler will in turn dispatch + * calls to PSCI SMC handler. + */ +static uintptr_t stm32mp1_svc_smc_handler(uint32_t smc_fid, u_register_t x1, + u_register_t x2, u_register_t x3, + u_register_t x4, void *cookie, + void *handle, u_register_t flags) +{ + uint32_t ret1 = 0U, ret2 = 0U; + bool ret_uid = false, ret2_enabled = false; + + switch (smc_fid) { + case STM32_SIP_SVC_CALL_COUNT: + ret1 = STM32_COMMON_SIP_NUM_CALLS; + break; + + case STM32_SIP_SVC_UID: + /* Return UUID to the caller */ + ret_uid = true; + break; + + case STM32_SIP_SVC_VERSION: + /* Return the version of current implementation */ + ret1 = STM32_SIP_SVC_VERSION_MAJOR; + ret2 = STM32_SIP_SVC_VERSION_MINOR; + ret2_enabled = true; + break; + + case STM32_SMC_BSEC: + ret1 = bsec_main(x1, x2, x3, &ret2); + ret2_enabled = true; + break; + + default: + WARN("Unimplemented STM32MP1 Service Call: 0x%x\n", smc_fid); + ret1 = SMC_UNK; + break; + } + + if (ret_uid) { + SMC_UUID_RET(handle, stm32_sip_svc_uid); + } + + if (ret2_enabled) { + SMC_RET2(handle, ret1, ret2); + } + + SMC_RET1(handle, ret1); +} + +/* Register Standard Service Calls as runtime service */ +DECLARE_RT_SVC(stm32mp1_sip_svc, + OEN_SIP_START, + OEN_SIP_END, + SMC_TYPE_FAST, + stm32mp1_svc_setup, + stm32mp1_svc_smc_handler +); diff --git a/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk b/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk index 9fde153879489af0d725b0c69688c08df77316e6..4188cc58ae3d275b3a1fccde92e4b5fa54ef9caf 100644 --- a/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk +++ b/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk @@ -1,5 +1,5 @@ # -# Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. +# Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # @@ -19,3 +19,7 @@ BL32_SOURCES += drivers/arm/gic/common/gic_common.c \ # Generic PSCI BL32_SOURCES += plat/common/plat_psci_common.c + +# stm32mp1 specific services +BL32_SOURCES += plat/st/stm32mp1/services/bsec_svc.c \ + plat/st/stm32mp1/services/stm32mp1_svc_setup.c diff --git a/plat/st/stm32mp1/sp_min/sp_min_setup.c b/plat/st/stm32mp1/sp_min/sp_min_setup.c index f5413797cf014e32b10ede5d143f99397dbdc7f7..0d76fb7e3ea316f5e2296ccbfb426b10542858ab 100644 --- a/plat/st/stm32mp1/sp_min/sp_min_setup.c +++ b/plat/st/stm32mp1/sp_min/sp_min_setup.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -13,9 +13,12 @@ #include #include #include +#include #include #include +#include #include +#include #include #include #include @@ -40,7 +43,7 @@ static struct console_stm32 console; ******************************************************************************/ void sp_min_plat_fiq_handler(uint32_t id) { - switch (id) { + switch (id & INT_ID_MASK) { case STM32MP1_IRQ_TZC400: ERROR("STM32MP1_IRQ_TZC400 generated\n"); panic(); @@ -50,7 +53,7 @@ void sp_min_plat_fiq_handler(uint32_t id) panic(); break; default: - ERROR("SECURE IT handler not define for it : %i", id); + ERROR("SECURE IT handler not define for it : %u", id); break; } } @@ -80,7 +83,7 @@ entry_point_info_t *sp_min_plat_get_bl33_ep_info(void) void sp_min_early_platform_setup2(u_register_t arg0, u_register_t arg1, u_register_t arg2, u_register_t arg3) { - struct dt_node_info dt_dev_info; + struct dt_node_info dt_uart_info; int result; bl_params_t *params_from_bl2 = (bl_params_t *)arg0; @@ -110,14 +113,18 @@ void sp_min_early_platform_setup2(u_register_t arg0, u_register_t arg1, panic(); } + if (bsec_probe() != 0) { + panic(); + } + if (stm32mp1_clk_probe() < 0) { panic(); } - result = dt_get_stdout_uart_info(&dt_dev_info); + result = dt_get_stdout_uart_info(&dt_uart_info); - if ((result > 0) && dt_dev_info.status) { - if (console_stm32_register(dt_dev_info.base, 0, + if ((result > 0) && (dt_uart_info.status != 0U)) { + if (console_stm32_register(dt_uart_info.base, 0, STM32MP1_UART_BAUDRATE, &console) == 0) { panic(); @@ -142,6 +149,16 @@ void sp_min_platform_setup(void) generic_delay_timer_init(); stm32mp1_gic_init(); + + /* Unlock ETZPC securable peripherals */ +#define STM32MP1_ETZPC_BASE 0x5C007000U +#define ETZPC_DECPROT0 0x010U + mmio_write_32(STM32MP1_ETZPC_BASE + ETZPC_DECPROT0, 0xFFFFFFFF); + + /* Set GPIO bank Z as non secure */ + for (uint32_t pin = 0U; pin < STM32MP_GPIOZ_PIN_MAX_COUNT; pin++) { + set_gpio_secure_cfg(GPIO_BANK_Z, pin, false); + } } void sp_min_plat_arch_setup(void) diff --git a/plat/st/stm32mp1/stm32mp1_common.c b/plat/st/stm32mp1/stm32mp1_common.c index b54f313ffec25c725fb63df8d7a4e5f3123e0450..cd93d2eef7a3e3ff29652e195be395f0eebeec94 100644 --- a/plat/st/stm32mp1/stm32mp1_common.c +++ b/plat/st/stm32mp1/stm32mp1_common.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -39,26 +40,11 @@ MT_SECURE | \ MT_EXECUTE_NEVER) -#define MAP_DDR MAP_REGION_FLAT(STM32MP1_DDR_BASE, \ - STM32MP1_DDR_MAX_SIZE, \ - MT_MEMORY | \ - MT_RW | \ - MT_SECURE | \ - MT_EXECUTE_NEVER) - -#define MAP_DDR_NS MAP_REGION_FLAT(STM32MP1_DDR_BASE, \ - STM32MP1_DDR_MAX_SIZE, \ - MT_MEMORY | \ - MT_RW | \ - MT_NS | \ - MT_EXECUTE_NEVER) - #if defined(IMAGE_BL2) static const mmap_region_t stm32mp1_mmap[] = { MAP_SRAM, MAP_DEVICE1, MAP_DEVICE2, - MAP_DDR, {0} }; #endif @@ -67,7 +53,6 @@ static const mmap_region_t stm32mp1_mmap[] = { MAP_SRAM, MAP_DEVICE1, MAP_DEVICE2, - MAP_DDR_NS, {0} }; #endif @@ -102,3 +87,37 @@ uintptr_t stm32mp1_get_boot_ctx_address(void) { return boot_ctx_address; } + +uintptr_t stm32_get_gpio_bank_base(unsigned int bank) +{ + switch (bank) { + case GPIO_BANK_A ... GPIO_BANK_K: + return GPIOA_BASE + (bank * GPIO_BANK_OFFSET); + case GPIO_BANK_Z: + return GPIOZ_BASE; + default: + panic(); + } +} + +/* Return clock ID on success, negative value on error */ +unsigned long stm32_get_gpio_bank_clock(unsigned int bank) +{ + switch (bank) { + case GPIO_BANK_A ... GPIO_BANK_K: + return GPIOA + (bank - GPIO_BANK_A); + case GPIO_BANK_Z: + return GPIOZ; + default: + panic(); + } +} + +uint32_t stm32_get_gpio_bank_offset(unsigned int bank) +{ + if (bank == GPIO_BANK_Z) { + return 0; + } else { + return bank * GPIO_BANK_OFFSET; + } +} diff --git a/plat/st/stm32mp1/stm32mp1_def.h b/plat/st/stm32mp1/stm32mp1_def.h index 15f0432b394a3a1dca91c1b365362171056955cb..8cd5aeb26c6c368089671d58601b7a5091707aaf 100644 --- a/plat/st/stm32mp1/stm32mp1_def.h +++ b/plat/st/stm32mp1/stm32mp1_def.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -111,6 +111,39 @@ enum ddr_type { ******************************************************************************/ #define PWR_BASE U(0x50001000) +/******************************************************************************* + * STM32MP1 GPIO + ******************************************************************************/ +#define GPIOA_BASE U(0x50002000) +#define GPIOB_BASE U(0x50003000) +#define GPIOC_BASE U(0x50004000) +#define GPIOD_BASE U(0x50005000) +#define GPIOE_BASE U(0x50006000) +#define GPIOF_BASE U(0x50007000) +#define GPIOG_BASE U(0x50008000) +#define GPIOH_BASE U(0x50009000) +#define GPIOI_BASE U(0x5000A000) +#define GPIOJ_BASE U(0x5000B000) +#define GPIOK_BASE U(0x5000C000) +#define GPIOZ_BASE U(0x54004000) +#define GPIO_BANK_OFFSET U(0x1000) + +/* Bank IDs used in GPIO driver API */ +#define GPIO_BANK_A U(0) +#define GPIO_BANK_B U(1) +#define GPIO_BANK_C U(2) +#define GPIO_BANK_D U(3) +#define GPIO_BANK_E U(4) +#define GPIO_BANK_F U(5) +#define GPIO_BANK_G U(6) +#define GPIO_BANK_H U(7) +#define GPIO_BANK_I U(8) +#define GPIO_BANK_J U(9) +#define GPIO_BANK_K U(10) +#define GPIO_BANK_Z U(25) + +#define STM32MP_GPIOZ_PIN_MAX_COUNT 8 + /******************************************************************************* * STM32MP1 UART ******************************************************************************/ @@ -122,16 +155,21 @@ enum ddr_type { #define USART6_BASE U(0x44003000) #define UART7_BASE U(0x40018000) #define UART8_BASE U(0x40019000) -#define STM32MP1_DEBUG_USART_BASE UART4_BASE -#define STM32MP1_UART_BAUDRATE 115200 +#define STM32MP1_UART_BAUDRATE U(115200) -/******************************************************************************* - * STM32MP1 GIC-400 - ******************************************************************************/ -#define STM32MP1_GICD_BASE U(0xA0021000) -#define STM32MP1_GICC_BASE U(0xA0022000) -#define STM32MP1_GICH_BASE U(0xA0024000) -#define STM32MP1_GICV_BASE U(0xA0026000) +/* For UART crash console */ +#define STM32MP1_DEBUG_USART_BASE UART4_BASE +/* UART4 on HSI@64MHz, TX on GPIOG11 Alternate 6 */ +#define STM32MP1_DEBUG_USART_CLK_FRQ 64000000 +#define DEBUG_UART_TX_GPIO_BANK_ADDRESS GPIOG_BASE +#define DEBUG_UART_TX_GPIO_BANK_CLK_REG RCC_MP_AHB4ENSETR +#define DEBUG_UART_TX_GPIO_BANK_CLK_EN RCC_MP_AHB4ENSETR_GPIOGEN +#define DEBUG_UART_TX_GPIO_PORT 11 +#define DEBUG_UART_TX_GPIO_ALTERNATE 6 +#define DEBUG_UART_TX_CLKSRC_REG RCC_UART24CKSELR +#define DEBUG_UART_TX_CLKSRC RCC_UART24CKSELR_HSI +#define DEBUG_UART_TX_EN_REG RCC_MP_APB1ENSETR +#define DEBUG_UART_TX_EN RCC_MP_APB1ENSETR_UART4EN /******************************************************************************* * STM32MP1 TZC (TZ400) @@ -149,10 +187,7 @@ enum ddr_type { #define STM32MP1_TZC_ETH_ID U(10) #define STM32MP1_TZC_DAP_ID U(15) -#define STM32MP1_MEMORY_NS 0 -#define STM32MP1_MEMORY_SECURE 1 - -#define STM32MP1_FILTER_BIT_ALL 3 +#define STM32MP1_FILTER_BIT_ALL U(3) /******************************************************************************* * STM32MP1 SDMMC @@ -167,6 +202,21 @@ enum ddr_type { #define STM32MP1_EMMC_NORMAL_SPEED_MAX_FREQ 26000000 /*26 MHz*/ #define STM32MP1_EMMC_HIGH_SPEED_MAX_FREQ 52000000 /*52 MHz*/ +/******************************************************************************* + * STM32MP1 BSEC / OTP + ******************************************************************************/ +#define STM32MP1_OTP_MAX_ID 0x5FU +#define STM32MP1_UPPER_OTP_START 0x20U + +#define OTP_MAX_SIZE (STM32MP1_OTP_MAX_ID + 1U) + +/* OTP offsets */ +#define DATA0_OTP U(0) + +/* OTP mask */ +/* DATA0 */ +#define DATA0_OTP_SECURED BIT(6) + /******************************************************************************* * STM32MP1 TAMP ******************************************************************************/ diff --git a/plat/st/stm32mp1/stm32mp1_dt.c b/plat/st/stm32mp1/stm32mp1_dt.c index 29e936aff8d71cb1f39dbcc0e976e2a0f65d544b..8493b87864c21721a23085313826d2531cb3ba4d 100644 --- a/plat/st/stm32mp1/stm32mp1_dt.c +++ b/plat/st/stm32mp1/stm32mp1_dt.c @@ -1,10 +1,11 @@ /* - * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ #include +#include #include @@ -17,135 +18,13 @@ #include #include -#include - -#define DT_GPIO_BANK_SHIFT 12 -#define DT_GPIO_BANK_MASK 0x1F000U -#define DT_GPIO_PIN_SHIFT 8 -#define DT_GPIO_PIN_MASK 0xF00U -#define DT_GPIO_MODE_MASK 0xFFU - static int fdt_checked; static void *fdt = (void *)(uintptr_t)STM32MP1_DTB_BASE; -/******************************************************************************* - * This function gets the pin settings from DT information. - * When analyze and parsing is done, set the GPIO registers. - * Return 0 on success, else return a negative FDT_ERR_xxx error code. - ******************************************************************************/ -static int dt_set_gpio_config(int node) -{ - const fdt32_t *cuint, *slewrate; - int len, pinctrl_node, pinctrl_subnode; - uint32_t i; - uint32_t speed = GPIO_SPEED_LOW; - uint32_t pull = GPIO_NO_PULL; - - cuint = fdt_getprop(fdt, node, "pinmux", &len); - if (cuint == NULL) { - return -FDT_ERR_NOTFOUND; - } - - pinctrl_node = fdt_parent_offset(fdt, fdt_parent_offset(fdt, node)); - if (pinctrl_node < 0) { - return -FDT_ERR_NOTFOUND; - } - - slewrate = fdt_getprop(fdt, node, "slew-rate", NULL); - if (slewrate != NULL) { - speed = fdt32_to_cpu(*slewrate); - } - - if (fdt_getprop(fdt, node, "bias-pull-up", NULL) != NULL) { - pull = GPIO_PULL_UP; - } else if (fdt_getprop(fdt, node, "bias-pull-down", NULL) != NULL) { - pull = GPIO_PULL_DOWN; - } else { - VERBOSE("No bias configured in node %d\n", node); - } - - for (i = 0; i < ((uint32_t)len / sizeof(uint32_t)); i++) { - uint32_t pincfg; - uint32_t bank; - uint32_t pin; - uint32_t mode; - uint32_t alternate = GPIO_ALTERNATE_0; - - pincfg = fdt32_to_cpu(*cuint); - cuint++; - - bank = (pincfg & DT_GPIO_BANK_MASK) >> DT_GPIO_BANK_SHIFT; - - pin = (pincfg & DT_GPIO_PIN_MASK) >> DT_GPIO_PIN_SHIFT; - - mode = pincfg & DT_GPIO_MODE_MASK; - - switch (mode) { - case 0: - mode = GPIO_MODE_INPUT; - break; - case 1 ... 16: - alternate = mode - 1U; - mode = GPIO_MODE_ALTERNATE; - break; - case 17: - mode = GPIO_MODE_ANALOG; - break; - default: - mode = GPIO_MODE_OUTPUT; - break; - } - - if (fdt_getprop(fdt, node, "drive-open-drain", NULL) != NULL) { - mode |= GPIO_OPEN_DRAIN; - } - - fdt_for_each_subnode(pinctrl_subnode, fdt, pinctrl_node) { - uint32_t bank_offset; - const fdt32_t *cuint2; - - if (fdt_getprop(fdt, pinctrl_subnode, - "gpio-controller", NULL) == NULL) { - continue; - } - - cuint2 = fdt_getprop(fdt, pinctrl_subnode, "reg", NULL); - if (cuint2 == NULL) { - continue; - } - - if (bank == GPIO_BANK_Z) { - bank_offset = 0; - } else { - bank_offset = bank * STM32_GPIO_BANK_OFFSET; - } - - if (fdt32_to_cpu(*cuint2) == bank_offset) { - int clk_id = fdt_get_clock_id(pinctrl_subnode); - - if (clk_id < 0) { - return -FDT_ERR_NOTFOUND; - } - - if (stm32mp1_clk_enable((unsigned long)clk_id) < - 0) { - return -FDT_ERR_BADVALUE; - } - - break; - } - } - - set_gpio(bank, pin, mode, speed, pull, alternate); - } - - return 0; -} - /******************************************************************************* * This function checks device tree file with its header. - * Returns 0 if success, and a negative value else. + * Returns 0 on success and a negative FDT error code on failure. ******************************************************************************/ int dt_open_and_check(void) { @@ -174,7 +53,7 @@ int fdt_get_address(void **fdt_addr) /******************************************************************************* * This function check the presence of a node (generic use of fdt library). - * Returns true if present, false else. + * Returns true if present, else return false. ******************************************************************************/ bool fdt_check_node(int node) { @@ -187,37 +66,30 @@ bool fdt_check_node(int node) } /******************************************************************************* - * This function check the status of a node (generic use of fdt library). - * Returns true if "okay" or missing, false else. + * This function return global node status (generic use of fdt library). ******************************************************************************/ -bool fdt_check_status(int node) +uint32_t fdt_get_status(int node) { + uint32_t status = DT_DISABLED; int len; const char *cchar; cchar = fdt_getprop(fdt, node, "status", &len); - if (cchar == NULL) { - return true; + if ((cchar == NULL) || + (strncmp(cchar, "okay", (size_t)len) == 0)) { + status |= DT_NON_SECURE; } - return strncmp(cchar, "okay", (size_t)len) == 0; -} - -/******************************************************************************* - * This function check the secure-status of a node (generic use of fdt library). - * Returns true if "okay" or missing, false else. - ******************************************************************************/ -bool fdt_check_secure_status(int node) -{ - int len; - const char *cchar; - cchar = fdt_getprop(fdt, node, "secure-status", &len); if (cchar == NULL) { - return true; + if (status == DT_NON_SECURE) { + status |= DT_SECURE; + } + } else if (strncmp(cchar, "okay", (size_t)len) == 0) { + status |= DT_SECURE; } - return strncmp(cchar, "okay", (size_t)len) == 0; + return status; } /******************************************************************************* @@ -245,7 +117,7 @@ uint32_t fdt_read_uint32_default(int node, const char *prop_name, * (generic use of fdt library). * It reads the values inside the device tree, from property name and node. * The number of parameters is also indicated as entry parameter. - * Returns 0 if success, and a negative value else. + * Returns 0 on success and a negative FDT error code on failure. * If success, values are stored at the third parameter address. ******************************************************************************/ int fdt_read_uint32_array(int node, const char *prop_name, uint32_t *array, @@ -273,53 +145,10 @@ int fdt_read_uint32_array(int node, const char *prop_name, uint32_t *array, return 0; } -/******************************************************************************* - * This function gets the pin settings from DT information. - * When analyze and parsing is done, set the GPIO registers. - * Returns 0 if success, and a negative value else. - ******************************************************************************/ -int dt_set_pinctrl_config(int node) -{ - const fdt32_t *cuint; - int lenp = 0; - uint32_t i; - - if (!fdt_check_status(node)) { - return -FDT_ERR_NOTFOUND; - } - - cuint = fdt_getprop(fdt, node, "pinctrl-0", &lenp); - if (cuint == NULL) { - return -FDT_ERR_NOTFOUND; - } - - for (i = 0; i < ((uint32_t)lenp / 4U); i++) { - int phandle_node, phandle_subnode; - - phandle_node = - fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint)); - if (phandle_node < 0) { - return -FDT_ERR_NOTFOUND; - } - - fdt_for_each_subnode(phandle_subnode, fdt, phandle_node) { - int ret = dt_set_gpio_config(phandle_subnode); - - if (ret < 0) { - return ret; - } - } - - cuint++; - } - - return 0; -} - /******************************************************************************* * This function gets the stdout pin configuration information from the DT. * And then calls the sub-function to treat it and set GPIO registers. - * Returns 0 if success, and a negative value else. + * Returns 0 on success and a negative FDT error code on failure. ******************************************************************************/ int dt_set_stdout_pinctrl(void) { @@ -363,13 +192,12 @@ void dt_fill_device_info(struct dt_node_info *info, int node) info->reset = -1; } - info->status = fdt_check_status(node); - info->sec_status = fdt_check_secure_status(node); + info->status = fdt_get_status(node); } /******************************************************************************* * This function retrieve the generic information from DT. - * Returns node if success, and a negative value else. + * Returns node on success and a negative FDT error code on failure. ******************************************************************************/ int dt_get_node(struct dt_node_info *info, int offset, const char *compat) { @@ -387,7 +215,7 @@ int dt_get_node(struct dt_node_info *info, int offset, const char *compat) /******************************************************************************* * This function gets the UART instance info of stdout from the DT. - * Returns node if success, and a negative value else. + * Returns node on success and a negative FDT error code on failure. ******************************************************************************/ int dt_get_stdout_uart_info(struct dt_node_info *info) { @@ -448,7 +276,7 @@ int dt_get_stdout_node_offset(void) /******************************************************************************* * This function gets DDR size information from the DT. - * Returns value in bytes if success, and STM32MP1_DDR_SIZE_DFLT else. + * Returns value in bytes on success, and 0 on failure. ******************************************************************************/ uint32_t dt_get_ddr_size(void) { @@ -457,11 +285,10 @@ uint32_t dt_get_ddr_size(void) node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT); if (node < 0) { INFO("%s: Cannot read DDR node in DT\n", __func__); - return STM32MP1_DDR_SIZE_DFLT; + return 0; } - return fdt_read_uint32_default(node, "st,mem-size", - STM32MP1_DDR_SIZE_DFLT); + return fdt_read_uint32_default(node, "st,mem-size", 0); } /******************************************************************************* diff --git a/plat/st/stm32mp1/stm32mp1_gic.c b/plat/st/stm32mp1/stm32mp1_gic.c index fabed370f0a2cab002e8429c689711ee52438a56..becb925c2373ec3802797e57589ced91bb15620b 100644 --- a/plat/st/stm32mp1/stm32mp1_gic.c +++ b/plat/st/stm32mp1/stm32mp1_gic.c @@ -1,18 +1,28 @@ /* - * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ +#include + #include #include +#include #include +#include #include #include +#include #include +struct stm32_gic_instance { + uint32_t cells; + uint32_t phandle_node; +}; + /****************************************************************************** * On a GICv2 system, the Group 1 secure interrupts are treated as Group 0 * interrupts. @@ -22,19 +32,55 @@ static const interrupt_prop_t stm32mp1_interrupt_props[] = { PLATFORM_G0_PROPS(GICV2_INTR_GROUP0) }; -static unsigned int target_mask_array[PLATFORM_CORE_COUNT]; +/* Fix target_mask_array as secondary core is not able to initialize it */ +static unsigned int target_mask_array[PLATFORM_CORE_COUNT] = {1, 2}; -static const gicv2_driver_data_t platform_gic_data = { - .gicd_base = STM32MP1_GICD_BASE, - .gicc_base = STM32MP1_GICC_BASE, +static gicv2_driver_data_t platform_gic_data = { .interrupt_props = stm32mp1_interrupt_props, .interrupt_props_num = ARRAY_SIZE(stm32mp1_interrupt_props), .target_masks = target_mask_array, .target_masks_num = ARRAY_SIZE(target_mask_array), }; +static struct stm32_gic_instance stm32_gic; + void stm32mp1_gic_init(void) { + int node; + void *fdt; + const fdt32_t *cuint; + struct dt_node_info dt_gic; + + if (fdt_get_address(&fdt) == 0) { + panic(); + } + + node = dt_get_node(&dt_gic, -1, "arm,cortex-a7-gic"); + if (node < 0) { + panic(); + } + + platform_gic_data.gicd_base = dt_gic.base; + + cuint = fdt_getprop(fdt, node, "reg", NULL); + if (cuint == NULL) { + panic(); + } + + platform_gic_data.gicc_base = fdt32_to_cpu(*(cuint + 2)); + + cuint = fdt_getprop(fdt, node, "#interrupt-cells", NULL); + if (cuint == NULL) { + panic(); + } + + stm32_gic.cells = fdt32_to_cpu(*cuint); + + stm32_gic.phandle_node = fdt_get_phandle(fdt, node); + if (stm32_gic.phandle_node == 0U) { + panic(); + } + gicv2_driver_init(&platform_gic_data); gicv2_distif_init(); diff --git a/plat/st/stm32mp1/stm32mp1_helper.S b/plat/st/stm32mp1/stm32mp1_helper.S index 61c587f4f1d0e899701cbe1d7258c5f22d3bdd21..8c2e1b6ea3ea10cb26b72b20d5195728fd7398f1 100644 --- a/plat/st/stm32mp1/stm32mp1_helper.S +++ b/plat/st/stm32mp1/stm32mp1_helper.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -12,11 +12,8 @@ #include #include -#define GPIO_BANK_G_ADDRESS 0x50008000 -#define GPIO_TX_PORT 11 -#define GPIO_TX_SHIFT (GPIO_TX_PORT << 1) -#define GPIO_TX_ALT_SHIFT ((GPIO_TX_PORT - GPIO_ALT_LOWER_LIMIT) << 2) -#define STM32MP1_HSI_CLK 64000000 +#define GPIO_TX_SHIFT (DEBUG_UART_TX_GPIO_PORT << 1) +#define GPIO_TX_ALT_SHIFT ((DEBUG_UART_TX_GPIO_PORT - GPIO_ALT_LOWER_LIMIT) << 2) .globl platform_mem_init .globl plat_report_exception @@ -112,13 +109,13 @@ endfunc plat_my_core_pos * --------------------------------------------- */ func plat_crash_console_init - /* Enable GPIOs for UART4 TX */ - ldr r1, =(RCC_BASE + RCC_MP_AHB4ENSETR) + /* Enable GPIOs for UART TX */ + ldr r1, =(RCC_BASE + DEBUG_UART_TX_GPIO_BANK_CLK_REG) ldr r2, [r1] - /* Configure GPIO G11 */ - orr r2, r2, #RCC_MP_AHB4ENSETR_GPIOGEN + /* Configure GPIO */ + orr r2, r2, #DEBUG_UART_TX_GPIO_BANK_CLK_EN str r2, [r1] - ldr r1, =GPIO_BANK_G_ADDRESS + ldr r1, =DEBUG_UART_TX_GPIO_BANK_ADDRESS /* Set GPIO mode alternate */ ldr r2, [r1, #GPIO_MODE_OFFSET] bic r2, r2, #(GPIO_MODE_MASK << GPIO_TX_SHIFT) @@ -132,23 +129,22 @@ func plat_crash_console_init ldr r2, [r1, #GPIO_PUPD_OFFSET] bic r2, r2, #(GPIO_PULL_MASK << GPIO_TX_SHIFT) str r2, [r1, #GPIO_PUPD_OFFSET] - /* Set alternate AF6 */ + /* Set alternate */ ldr r2, [r1, #GPIO_AFRH_OFFSET] bic r2, r2, #(GPIO_ALTERNATE_MASK << GPIO_TX_ALT_SHIFT) - orr r2, r2, #(GPIO_ALTERNATE_6 << GPIO_TX_ALT_SHIFT) + orr r2, r2, #(DEBUG_UART_TX_GPIO_ALTERNATE << GPIO_TX_ALT_SHIFT) str r2, [r1, #GPIO_AFRH_OFFSET] - - /* Enable UART clock, with HSI source */ - ldr r1, =(RCC_BASE + RCC_UART24CKSELR) - mov r2, #RCC_UART24CKSELR_HSI + /* Enable UART clock, with its source */ + ldr r1, =(RCC_BASE + DEBUG_UART_TX_CLKSRC_REG) + mov r2, #DEBUG_UART_TX_CLKSRC str r2, [r1] - ldr r1, =(RCC_BASE + RCC_MP_APB1ENSETR) + ldr r1, =(RCC_BASE + DEBUG_UART_TX_EN_REG) ldr r2, [r1] - orr r2, r2, #RCC_MP_APB1ENSETR_UART4EN + orr r2, r2, #DEBUG_UART_TX_EN str r2, [r1] ldr r0, =STM32MP1_DEBUG_USART_BASE - ldr r1, =STM32MP1_HSI_CLK + ldr r1, =STM32MP1_DEBUG_USART_CLK_FRQ ldr r2, =STM32MP1_UART_BAUDRATE b console_stm32_core_init endfunc plat_crash_console_init diff --git a/plat/st/stm32mp1/stm32mp1_pm.c b/plat/st/stm32mp1/stm32mp1_pm.c index 85189ff21de06d301982336916407c413f734ff9..c0e9c4eb8c5e133f158ccbb4d4740cff99621c03 100644 --- a/plat/st/stm32mp1/stm32mp1_pm.c +++ b/plat/st/stm32mp1/stm32mp1_pm.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -23,11 +23,9 @@ #include #include -static uint32_t stm32_sec_entrypoint; +static uintptr_t stm32_sec_entrypoint; static uint32_t cntfrq_core0; -#define SEND_SECURE_IT_TO_CORE_1 0x20000U - /******************************************************************************* * STM32MP1 handler called when a CPU is about to enter standby. * call by core 1 to enter in wfi @@ -42,6 +40,7 @@ static void stm32_cpu_standby(plat_local_state_t cpu_state) * Enter standby state * dsb is good practice before using wfi to enter low power states */ + isb(); dsb(); while (interrupt == GIC_SPURIOUS_INTERRUPT) { wfi(); @@ -59,7 +58,7 @@ static void stm32_cpu_standby(plat_local_state_t cpu_state) /******************************************************************************* * STM32MP1 handler called when a power domain is about to be turned on. The * mpidr determines the CPU to be turned on. - * call by core 0 to activate core 1 + * call by core 0 to activate core 1 ******************************************************************************/ static int stm32_pwr_domain_on(u_register_t mpidr) { @@ -102,8 +101,7 @@ static int stm32_pwr_domain_on(u_register_t mpidr) } /* Generate an IT to core 1 */ - mmio_write_32(STM32MP1_GICD_BASE + GICD_SGIR, - SEND_SECURE_IT_TO_CORE_1 | ARM_IRQ_SEC_SGI_0); + gicv2_raise_sgi(ARM_IRQ_SEC_SGI_0, STM32MP1_SECONDARY_CPU); return PSCI_E_SUCCESS; } diff --git a/plat/st/stm32mp1/stm32mp1_security.c b/plat/st/stm32mp1/stm32mp1_security.c index 39927040a84e8ecbadc868203fb8a136ab8501fb..cfdbf31852bd7c72e01dc6d48bdbc52d77ac2980 100644 --- a/plat/st/stm32mp1/stm32mp1_security.c +++ b/plat/st/stm32mp1/stm32mp1_security.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -65,22 +65,6 @@ static void init_tzc400(void) ******************************************************************************/ static void early_init_tzc400(void) { - uint32_t rstsr, rst_standby; - - rstsr = mmio_read_32(RCC_BASE + RCC_MP_RSTSCLRR); - - /* No warning if return from (C)STANDBY */ - rst_standby = rstsr & - (RCC_MP_RSTSCLRR_STDBYRSTF | RCC_MP_RSTSCLRR_CSTDBYRSTF); - - if (stm32mp1_clk_is_enabled(TZC1) && (rst_standby == 0U)) { - WARN("TZC400 port 1 clock already enable\n"); - } - - if (stm32mp1_clk_is_enabled(TZC2) && (rst_standby == 0U)) { - WARN("TZC400 port 2 clock already enable\n"); - } - if (stm32mp1_clk_enable(TZC1) != 0) { ERROR("Cannot enable TZC1 clock\n"); panic(); @@ -103,6 +87,7 @@ static void early_init_tzc400(void) STM32MP1_DDR_BASE + (STM32MP1_DDR_MAX_SIZE - 1U), TZC_REGION_S_RDWR, + TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_A7_ID) | TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_SDMMC_ID)); /* Raise an exception if a NS device tries to access secure memory */