Unverified Commit fbf35335 authored by Antonio Niño Díaz's avatar Antonio Niño Díaz Committed by GitHub
Browse files

Merge pull request #1767 from Yann-lms/updates_stm32mp1

Updates for STM32MP1
parents f0bfe15b 7747356d
/*
* Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <limits.h>
#include <libfdt.h>
#include <platform_def.h>
#include <arch_helpers.h>
#include <common/debug.h>
#include <drivers/st/bsec.h>
#include <lib/mmio.h>
#include <lib/spinlock.h>
#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;
}
/*
* 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)
{
......
This diff is collapsed.
/*
* 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) {
......
/*
* Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved
* Copyright (c) 2016-2019, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <errno.h>
#include <stdbool.h>
#include <libfdt.h>
#include <platform_def.h>
#include <common/bl_common.h>
#include <common/debug.h>
#include <drivers/st/stm32_gpio.h>
#include <drivers/st/stm32mp1_clk.h>
#include <drivers/st/stm32mp1_clkfunc.h>
#include <lib/mmio.h>
#include <lib/utils_def.h>
#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)
static bool check_gpio(uint32_t bank, uint32_t pin)
/*******************************************************************************
* 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);
fdt_for_each_subnode(pinctrl_subnode, fdt, pinctrl_node) {
const fdt32_t *cuint;
if (fdt_getprop(fdt, pinctrl_subnode,
"gpio-controller", NULL) == NULL) {
continue;
}
if ((bank > GPIO_BANK_K) && (bank != GPIO_BANK_Z)) {
ERROR("%s: wrong GPIO bank number (%d)\n", __func__, bank);
return false;
cuint = fdt_getprop(fdt, pinctrl_subnode, "reg", NULL);
if (cuint == NULL) {
continue;
}
return true;
if ((fdt32_to_cpu(*cuint) == bank_offset) &&
(fdt_get_status(pinctrl_subnode) != DT_DISABLED)) {
return pinctrl_subnode;
}
}
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;
}
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;
}
mmio_clrbits_32(bank_address + GPIO_MODE_OFFSET,
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);
}
/*
* Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved
* Copyright (c) 2016-2019, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
......
/*
* 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) {
if (current_part->bkp_offset == 0U) {
ERROR("%s: io_read (%i)\n", __func__, result);
break;
}
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;
}
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);
......
/*
* 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 <common/debug.h>
#include <drivers/delay_timer.h>
#include <drivers/mmc.h>
#include <drivers/st/stm32_gpio.h>
#include <drivers/st/stm32_sdmmc2.h>
#include <drivers/st/stm32mp1_clk.h>
#include <drivers/st/stm32mp1_rcc.h>
......@@ -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;
}
......
/*
* 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 <common/debug.h>
#include <drivers/delay_timer.h>
#include <drivers/st/stm32mp_pmic.h>
#include <drivers/st/stm32_gpio.h>
#include <drivers/st/stm32mp1_clk.h>
#include <drivers/st/stm32mp1_pmic.h>
#include <drivers/st/stpmu1.h>
#include <drivers/st/stpmic1.h>
#include <lib/mmio.h>
#include <lib/utils_def.h>
......@@ -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,
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:
......
/*
* 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 <string.h>
#include <common/debug.h>
#include <drivers/st/stpmu1.h>
#include <drivers/st/stpmic1.h>
#include <plat/common/platform.h>
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)
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,
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 = stpmu1_voltage_find_index(name, millivolts);
const struct regul_struct *regul = stpmu1_get_regulator_data(name);
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<N> or ldo<N> (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)
{
const struct regul_struct *regul = get_regulator_data(name);
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 stpmic1_regulator_mask_reset_set(const char *name)
{
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 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<N> or ldo<N> (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 stpmu1_register_update(regul->control_reg, voltage_index << 2,
0xFC);
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 stpmu1_register_read(uint8_t register_id, uint8_t *value)
int stpmic1_register_read(uint8_t register_id, uint8_t *value)
{
return stm32_i2c_mem_read(stpmu_i2c_handle, stpmu_i2c_addr,
return stm32_i2c_mem_read(pmic_i2c_handle, pmic_i2c_addr,
(uint16_t)register_id, I2C_MEMADD_SIZE_8BIT,
value, 1, 100000);
}
int stpmu1_register_write(uint8_t register_id, uint8_t value)
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;
}
......@@ -5,7 +5,7 @@
/ {
soc {
ddr: ddr@0x5A003000{
ddr: ddr@5A003000{
compatible = "st,stm32mp1-ddr";
......
......@@ -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
......
......@@ -3,13 +3,14 @@
* Copyright (C) STMicroelectronics 2017 - All Rights Reserved
* Author: Ludovic Barre <ludovic.barre@st.com> for STMicroelectronics.
*/
#include <dt-bindings/pinctrl/stm32-pinfunc.h>
/ {
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 = <STM32_PINMUX('G', 11, AF6)>; /* UART4_TX */
pinmux = <STM32_PINMUX('F', 8, AF10)>, /* QSPI_BK1_IO0 */
<STM32_PINMUX('F', 9, AF10)>, /* QSPI_BK1_IO1 */
<STM32_PINMUX('F', 7, AF9)>, /* QSPI_BK1_IO2 */
<STM32_PINMUX('F', 6, AF9)>; /* QSPI_BK1_IO3 */
bias-disable;
drive-push-pull;
slew-rate = <0>;
slew-rate = <1>;
};
pins2 {
pinmux = <STM32_PINMUX('B', 2, AF8)>; /* UART4_RX */
bias-disable;
pinmux = <STM32_PINMUX('B', 6, AF10)>; /* 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 = <STM32_PINMUX('B', 10, AF7)>, /* USART3_TX */
<STM32_PINMUX('G', 8, AF8)>; /* USART3_RTS */
pinmux = <STM32_PINMUX('H', 2, AF9)>, /* QSPI_BK2_IO0 */
<STM32_PINMUX('H', 3, AF9)>, /* QSPI_BK2_IO1 */
<STM32_PINMUX('G', 10, AF11)>, /* QSPI_BK2_IO2 */
<STM32_PINMUX('G', 7, AF11)>; /* QSPI_BK2_IO3 */
bias-disable;
drive-push-pull;
slew-rate = <0>;
slew-rate = <1>;
};
pins2 {
pinmux = <STM32_PINMUX('B', 12, AF8)>, /* USART3_RX */
<STM32_PINMUX('I', 10, AF8)>; /* USART3_CTS_NSS */
bias-disable;
pinmux = <STM32_PINMUX('C', 0, AF10)>; /* 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 = <STM32_PINMUX('F', 10, AF9)>; /* QSPI_CLK */
bias-disable;
drive-push-pull;
slew-rate = <3>;
};
};
sdmmc1_b4_pins_a: sdmmc1-b4-0 {
pins1 {
pinmux = <STM32_PINMUX('C', 8, AF12)>, /* SDMMC1_D0 */
<STM32_PINMUX('C', 9, AF12)>, /* SDMMC1_D1 */
<STM32_PINMUX('C', 10, AF12)>, /* SDMMC1_D2 */
<STM32_PINMUX('C', 11, AF12)>, /* SDMMC1_D3 */
<STM32_PINMUX('C', 12, AF12)>, /* SDMMC1_CK */
<STM32_PINMUX('D', 2, AF12)>; /* SDMMC1_CMD */
slew-rate = <3>;
slew-rate = <1>;
drive-push-pull;
bias-disable;
};
pins2 {
pinmux = <STM32_PINMUX('C', 12, AF12)>; /* 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 = <STM32_PINMUX('F', 2, AF11)>, /* SDMMC1_D0DIR */
<STM32_PINMUX('C', 7, AF8)>, /* SDMMC1_D123DIR */
<STM32_PINMUX('B', 9, AF11)>; /* 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 = <STM32_PINMUX('E', 12, AF8)>, /* SDMMC1_D0DIR */
<STM32_PINMUX('E', 14, AF11)>, /* SDMMC1_D123DIR */
<STM32_PINMUX('B', 9, AF11)>; /* SDMMC1_CDIR */
slew-rate = <3>;
drive-push-pull;
bias-pull-up;
};
pins2 {
pinmux = <STM32_PINMUX('E', 4, AF8)>; /* SDMMC1_CKIN */
bias-pull-up;
};
};
sdmmc2_b4_pins_a: sdmmc2-b4-0 {
pins1 {
pinmux = <STM32_PINMUX('B', 14, AF9)>, /* SDMMC2_D0 */
<STM32_PINMUX('B', 15, AF9)>, /* SDMMC2_D1 */
<STM32_PINMUX('B', 3, AF9)>, /* SDMMC2_D2 */
<STM32_PINMUX('B', 4, AF9)>, /* SDMMC2_D3 */
<STM32_PINMUX('E', 3, AF9)>, /* SDMMC2_CK */
<STM32_PINMUX('G', 6, AF10)>; /* SDMMC2_CMD */
slew-rate = <3>;
slew-rate = <1>;
drive-push-pull;
bias-pull-up;
};
pins2 {
pinmux = <STM32_PINMUX('E', 3, AF9)>; /* 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 = <STM32_PINMUX('A', 8, AF9)>, /* SDMMC2_D4 */
<STM32_PINMUX('A', 9, AF10)>, /* SDMMC2_D5 */
<STM32_PINMUX('E', 5, AF9)>, /* SDMMC2_D6 */
<STM32_PINMUX('D', 3, AF9)>; /* SDMMC2_D7 */
slew-rate = <3>;
slew-rate = <1>;
drive-push-pull;
bias-pull-up;
};
};
uart4_pins_a: uart4-0 {
pins1 {
pinmux = <STM32_PINMUX('G', 11, AF6)>; /* UART4_TX */
bias-disable;
drive-push-pull;
slew-rate = <0>;
};
pins2 {
pinmux = <STM32_PINMUX('B', 2, AF8)>; /* UART4_RX */
bias-disable;
};
};
usart3_pins_a: usart3-0 {
pins1 {
pinmux = <STM32_PINMUX('B', 10, AF7)>, /* USART3_TX */
<STM32_PINMUX('G', 8, AF8)>; /* USART3_RTS */
bias-disable;
drive-push-pull;
slew-rate = <0>;
};
pins2 {
pinmux = <STM32_PINMUX('B', 12, AF8)>, /* USART3_RX */
<STM32_PINMUX('I', 10, AF8)>; /* 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 = <STM32_PINMUX('Z', 4, AF6)>, /* I2C4_SCL */
<STM32_PINMUX('Z', 5, AF6)>; /* I2C4_SDA */
......
......@@ -3,22 +3,28 @@
* Copyright (C) STMicroelectronics 2017 - All Rights Reserved
* Author: Ludovic Barre <ludovic.barre@st.com> 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 {
pinctrl-names = "default";
pinctrl-0 = <&i2c4_pins_a>;
......@@ -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-initial-mode = <0>;
};
regulator-state-standby {
regulator-suspend-microvolt = <3300000>;
regulator-unchanged-in-suspend;
regulator-mode = <8>;
vdda: ldo1 {
regulator-name = "vdda";
regulator-min-microvolt = <2900000>;
regulator-max-microvolt = <2900000>;
};
regulator-state-mem {
regulator-off-in-suspend;
v2v8: ldo2 {
regulator-name = "v2v8";
regulator-min-microvolt = <2800000>;
regulator-max-microvolt = <2800000>;
};
regulator-state-disk {
regulator-off-in-suspend;
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) >;
};
};
......
......@@ -3,23 +3,65 @@
* Copyright (C) STMicroelectronics 2017 - All Rights Reserved
* Author: Ludovic Barre <ludovic.barre@st.com> 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";
};
......@@ -3,7 +3,7 @@
* Copyright (C) STMicroelectronics 2017 - All Rights Reserved
* Author: Ludovic Barre <ludovic.barre@st.com> for STMicroelectronics.
*/
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/clock/stm32mp1-clks.h>
#include <dt-bindings/reset/stm32mp1-resets.h>
......@@ -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 = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
};
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 = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
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";
};
};
};
......@@ -7,8 +7,8 @@
#include "stm32mp157-pinctrl.dtsi"
/ {
soc {
pinctrl: pin-controller {
compatible = "st,stm32mp157caa-pinctrl";
pinctrl: pin-controller@50002000 {
st,package = <STM32MP157CAA>;
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 = <STM32MP157CAA>;
gpioz: gpio@54004000 {
status = "okay";
......
/*
* Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef BSEC_H
#define BSEC_H
#include <stdbool.h>
#include <stdint.h>
#include <lib/utils_def.h>
/*
* 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 */
/*
* 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 <lib/utils_def.h>
#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 <stdint.h>
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 */
/*
* 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 */
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment