Browse Source
* changes: fdts: stm32mp1: realign device tree files with internal devs stm32mp1: increase device tree size to 20kB stm32mp1: make dt_get_stdout_node_offset() static stm32mp1: use unsigned values for SDMMC defines stm32mp1: remove useless LIBFDT_SRCS from PLAT_BL_COMMON_SOURCES stm32mp1: update doc for U-Boot compilation stm32mp1: add general SYSCFG management stm32mp1: move stm32_get_gpio_bank_clock() to private file clk: stm32mp1: correctly handle Clock Spreading Generator clk: stm32mp1: use defines for mask values in stm32mp1_clk_sel array clk: stm32mp1: move oscillator functions to generic file arch: add some defines for generic timer registerspull/1931/head
John Tsichritzis
5 years ago
committed by
TrustedFirmware Code Review
26 changed files with 773 additions and 342 deletions
@ -1,167 +0,0 @@ |
|||
/*
|
|||
* Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved |
|||
* |
|||
* SPDX-License-Identifier: BSD-3-Clause |
|||
*/ |
|||
|
|||
#include <errno.h> |
|||
|
|||
#include <libfdt.h> |
|||
|
|||
#include <platform_def.h> |
|||
|
|||
#include <drivers/st/stm32_gpio.h> |
|||
#include <drivers/st/stm32mp_clkfunc.h> |
|||
#include <drivers/st/stm32mp1_clk.h> |
|||
#include <drivers/st/stm32mp1_clkfunc.h> |
|||
#include <dt-bindings/clock/stm32mp1-clksrc.h> |
|||
|
|||
const char *stm32mp_osc_node_label[NB_OSC] = { |
|||
[_LSI] = "clk-lsi", |
|||
[_LSE] = "clk-lse", |
|||
[_HSI] = "clk-hsi", |
|||
[_HSE] = "clk-hse", |
|||
[_CSI] = "clk-csi", |
|||
[_I2S_CKIN] = "i2s_ckin", |
|||
}; |
|||
|
|||
/*
|
|||
* Get the frequency of an oscillator from its name in device tree. |
|||
* @param name: oscillator name |
|||
* @param freq: stores the frequency of the oscillator |
|||
* @return: 0 on success, and a negative FDT/ERRNO error code on failure. |
|||
*/ |
|||
int fdt_osc_read_freq(const char *name, uint32_t *freq) |
|||
{ |
|||
int node, subnode; |
|||
void *fdt; |
|||
|
|||
if (fdt_get_address(&fdt) == 0) { |
|||
return -ENOENT; |
|||
} |
|||
|
|||
node = fdt_path_offset(fdt, "/clocks"); |
|||
if (node < 0) { |
|||
return -FDT_ERR_NOTFOUND; |
|||
} |
|||
|
|||
fdt_for_each_subnode(subnode, fdt, node) { |
|||
const char *cchar; |
|||
int ret; |
|||
|
|||
cchar = fdt_get_name(fdt, subnode, &ret); |
|||
if (cchar == NULL) { |
|||
return ret; |
|||
} |
|||
|
|||
if (strncmp(cchar, name, (size_t)ret) == 0) { |
|||
const fdt32_t *cuint; |
|||
|
|||
cuint = fdt_getprop(fdt, subnode, "clock-frequency", |
|||
&ret); |
|||
if (cuint == NULL) { |
|||
return ret; |
|||
} |
|||
|
|||
*freq = fdt32_to_cpu(*cuint); |
|||
|
|||
return 0; |
|||
} |
|||
} |
|||
|
|||
/* Oscillator not found, freq=0 */ |
|||
*freq = 0; |
|||
return 0; |
|||
} |
|||
|
|||
/*
|
|||
* Check the presence of an oscillator property from its id. |
|||
* @param osc_id: oscillator ID |
|||
* @param prop_name: property name |
|||
* @return: true/false regarding search result. |
|||
*/ |
|||
bool fdt_osc_read_bool(enum stm32mp_osc_id osc_id, const char *prop_name) |
|||
{ |
|||
int node, subnode; |
|||
void *fdt; |
|||
|
|||
if (fdt_get_address(&fdt) == 0) { |
|||
return false; |
|||
} |
|||
|
|||
if (osc_id >= NB_OSC) { |
|||
return false; |
|||
} |
|||
|
|||
node = fdt_path_offset(fdt, "/clocks"); |
|||
if (node < 0) { |
|||
return false; |
|||
} |
|||
|
|||
fdt_for_each_subnode(subnode, fdt, node) { |
|||
const char *cchar; |
|||
int ret; |
|||
|
|||
cchar = fdt_get_name(fdt, subnode, &ret); |
|||
if (cchar == NULL) { |
|||
return false; |
|||
} |
|||
|
|||
if (strncmp(cchar, stm32mp_osc_node_label[osc_id], |
|||
(size_t)ret) != 0) { |
|||
continue; |
|||
} |
|||
|
|||
if (fdt_getprop(fdt, subnode, prop_name, NULL) != NULL) { |
|||
return true; |
|||
} |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
/*
|
|||
* Get the value of a oscillator property from its ID. |
|||
* @param osc_id: oscillator ID |
|||
* @param prop_name: property name |
|||
* @param dflt_value: default value |
|||
* @return oscillator value on success, default value if property not found. |
|||
*/ |
|||
uint32_t fdt_osc_read_uint32_default(enum stm32mp_osc_id osc_id, |
|||
const char *prop_name, uint32_t dflt_value) |
|||
{ |
|||
int node, subnode; |
|||
void *fdt; |
|||
|
|||
if (fdt_get_address(&fdt) == 0) { |
|||
return dflt_value; |
|||
} |
|||
|
|||
if (osc_id >= NB_OSC) { |
|||
return dflt_value; |
|||
} |
|||
|
|||
node = fdt_path_offset(fdt, "/clocks"); |
|||
if (node < 0) { |
|||
return dflt_value; |
|||
} |
|||
|
|||
fdt_for_each_subnode(subnode, fdt, node) { |
|||
const char *cchar; |
|||
int ret; |
|||
|
|||
cchar = fdt_get_name(fdt, subnode, &ret); |
|||
if (cchar == NULL) { |
|||
return dflt_value; |
|||
} |
|||
|
|||
if (strncmp(cchar, stm32mp_osc_node_label[osc_id], |
|||
(size_t)ret) != 0) { |
|||
continue; |
|||
} |
|||
|
|||
return fdt_read_uint32_default(subnode, prop_name, dflt_value); |
|||
} |
|||
|
|||
return dflt_value; |
|||
} |
@ -1,33 +0,0 @@ |
|||
/*
|
|||
* Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved |
|||
* |
|||
* SPDX-License-Identifier: BSD-3-Clause |
|||
*/ |
|||
|
|||
#ifndef STM32MP1_CLKFUNC_H |
|||
#define STM32MP1_CLKFUNC_H |
|||
|
|||
#include <stdbool.h> |
|||
|
|||
#include <libfdt.h> |
|||
|
|||
enum stm32mp_osc_id { |
|||
_HSI, |
|||
_HSE, |
|||
_CSI, |
|||
_LSI, |
|||
_LSE, |
|||
_I2S_CKIN, |
|||
NB_OSC, |
|||
_UNKNOWN_OSC_ID = 0xFF |
|||
}; |
|||
|
|||
extern const char *stm32mp_osc_node_label[NB_OSC]; |
|||
|
|||
int fdt_osc_read_freq(const char *name, uint32_t *freq); |
|||
bool fdt_osc_read_bool(enum stm32mp_osc_id osc_id, const char *prop_name); |
|||
uint32_t fdt_osc_read_uint32_default(enum stm32mp_osc_id osc_id, |
|||
const char *prop_name, |
|||
uint32_t dflt_value); |
|||
|
|||
#endif /* STM32MP1_CLKFUNC_H */ |
@ -0,0 +1,180 @@ |
|||
/*
|
|||
* Copyright (c) 2019, STMicroelectronics - All Rights Reserved |
|||
* |
|||
* SPDX-License-Identifier: BSD-3-Clause |
|||
*/ |
|||
|
|||
#include <platform_def.h> |
|||
|
|||
#include <common/debug.h> |
|||
#include <drivers/st/bsec.h> |
|||
#include <drivers/st/stpmic1.h> |
|||
#include <lib/mmio.h> |
|||
|
|||
#include <stm32mp_dt.h> |
|||
#include <stm32mp1_private.h> |
|||
|
|||
/*
|
|||
* SYSCFG REGISTER OFFSET (base relative) |
|||
*/ |
|||
#define SYSCFG_BOOTR 0x00U |
|||
#define SYSCFG_IOCTRLSETR 0x18U |
|||
#define SYSCFG_ICNR 0x1CU |
|||
#define SYSCFG_CMPCR 0x20U |
|||
#define SYSCFG_CMPENSETR 0x24U |
|||
|
|||
/*
|
|||
* SYSCFG_BOOTR Register |
|||
*/ |
|||
#define SYSCFG_BOOTR_BOOT_MASK GENMASK(2, 0) |
|||
#define SYSCFG_BOOTR_BOOTPD_MASK GENMASK(6, 4) |
|||
#define SYSCFG_BOOTR_BOOTPD_SHIFT 4 |
|||
/*
|
|||
* SYSCFG_IOCTRLSETR Register |
|||
*/ |
|||
#define SYSCFG_IOCTRLSETR_HSLVEN_TRACE BIT(0) |
|||
#define SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI BIT(1) |
|||
#define SYSCFG_IOCTRLSETR_HSLVEN_ETH BIT(2) |
|||
#define SYSCFG_IOCTRLSETR_HSLVEN_SDMMC BIT(3) |
|||
#define SYSCFG_IOCTRLSETR_HSLVEN_SPI BIT(4) |
|||
|
|||
/*
|
|||
* SYSCFG_ICNR Register |
|||
*/ |
|||
#define SYSCFG_ICNR_AXI_M9 BIT(9) |
|||
|
|||
/*
|
|||
* SYSCFG_CMPCR Register |
|||
*/ |
|||
#define SYSCFG_CMPCR_SW_CTRL BIT(1) |
|||
#define SYSCFG_CMPCR_READY BIT(8) |
|||
#define SYSCFG_CMPCR_RANSRC GENMASK(19, 16) |
|||
#define SYSCFG_CMPCR_RANSRC_SHIFT 16 |
|||
#define SYSCFG_CMPCR_RAPSRC GENMASK(23, 20) |
|||
#define SYSCFG_CMPCR_ANSRC_SHIFT 24 |
|||
|
|||
/*
|
|||
* SYSCFG_CMPENSETR Register |
|||
*/ |
|||
#define SYSCFG_CMPENSETR_MPU_EN BIT(0) |
|||
|
|||
void stm32mp1_syscfg_init(void) |
|||
{ |
|||
uint32_t bootr; |
|||
uint32_t otp = 0; |
|||
uint32_t vdd_voltage; |
|||
uintptr_t syscfg_base = dt_get_syscfg_base(); |
|||
|
|||
/*
|
|||
* Interconnect update : select master using the port 1. |
|||
* LTDC = AXI_M9. |
|||
*/ |
|||
mmio_write_32(syscfg_base + SYSCFG_ICNR, SYSCFG_ICNR_AXI_M9); |
|||
|
|||
/* Disable Pull-Down for boot pin connected to VDD */ |
|||
bootr = mmio_read_32(syscfg_base + SYSCFG_BOOTR) & |
|||
SYSCFG_BOOTR_BOOT_MASK; |
|||
mmio_clrsetbits_32(syscfg_base + SYSCFG_BOOTR, SYSCFG_BOOTR_BOOTPD_MASK, |
|||
bootr << SYSCFG_BOOTR_BOOTPD_SHIFT); |
|||
|
|||
/*
|
|||
* High Speed Low Voltage Pad mode Enable for SPI, SDMMC, ETH, QSPI |
|||
* and TRACE. Needed above ~50MHz and conditioned by AFMUX selection. |
|||
* It could be disabled for low frequencies or if AFMUX is selected |
|||
* but the function is not used, typically for TRACE. |
|||
* If high speed low voltage pad mode is node enable, platform will |
|||
* over consume. |
|||
* |
|||
* WARNING: |
|||
* Enabling High Speed mode while VDD > 2.7V |
|||
* with the OTP product_below_2v5 (OTP 18, BIT 13) |
|||
* erroneously set to 1 can damage the SoC! |
|||
* => TF-A enables the low power mode only if VDD < 2.7V (in DT) |
|||
* but this value needs to be consistent with board design. |
|||
*/ |
|||
if (bsec_read_otp(&otp, HW2_OTP) != BSEC_OK) { |
|||
panic(); |
|||
} |
|||
|
|||
otp = otp & HW2_OTP_PRODUCT_BELOW_2V5; |
|||
|
|||
/* Get VDD supply */ |
|||
vdd_voltage = dt_get_pwr_vdd_voltage(); |
|||
|
|||
/* Check if VDD is Low Voltage */ |
|||
if (vdd_voltage == 0U) { |
|||
WARN("VDD unknown"); |
|||
} else if (vdd_voltage < 2700000U) { |
|||
mmio_write_32(syscfg_base + SYSCFG_IOCTRLSETR, |
|||
SYSCFG_IOCTRLSETR_HSLVEN_TRACE | |
|||
SYSCFG_IOCTRLSETR_HSLVEN_QUADSPI | |
|||
SYSCFG_IOCTRLSETR_HSLVEN_ETH | |
|||
SYSCFG_IOCTRLSETR_HSLVEN_SDMMC | |
|||
SYSCFG_IOCTRLSETR_HSLVEN_SPI); |
|||
|
|||
if (otp == 0U) { |
|||
INFO("Product_below_2v5=0: HSLVEN protected by HW\n"); |
|||
} |
|||
} else { |
|||
if (otp != 0U) { |
|||
ERROR("Product_below_2v5=1:\n"); |
|||
ERROR("\tHSLVEN update is destructive,\n"); |
|||
ERROR("\tno update as VDD > 2.7V\n"); |
|||
panic(); |
|||
} |
|||
} |
|||
|
|||
stm32mp1_syscfg_enable_io_compensation(); |
|||
} |
|||
|
|||
void stm32mp1_syscfg_enable_io_compensation(void) |
|||
{ |
|||
uintptr_t syscfg_base = dt_get_syscfg_base(); |
|||
|
|||
/*
|
|||
* Activate automatic I/O compensation. |
|||
* Warning: need to ensure CSI enabled and ready in clock driver. |
|||
* Enable non-secure clock, we assume non-secure is suspended. |
|||
*/ |
|||
stm32mp1_clk_enable_non_secure(SYSCFG); |
|||
|
|||
mmio_setbits_32(syscfg_base + SYSCFG_CMPENSETR, |
|||
SYSCFG_CMPENSETR_MPU_EN); |
|||
|
|||
while ((mmio_read_32(syscfg_base + SYSCFG_CMPCR) & |
|||
SYSCFG_CMPCR_READY) == 0U) { |
|||
; |
|||
} |
|||
|
|||
mmio_clrbits_32(syscfg_base + SYSCFG_CMPCR, SYSCFG_CMPCR_SW_CTRL); |
|||
} |
|||
|
|||
void stm32mp1_syscfg_disable_io_compensation(void) |
|||
{ |
|||
uintptr_t syscfg_base = dt_get_syscfg_base(); |
|||
uint32_t value; |
|||
|
|||
/*
|
|||
* Deactivate automatic I/O compensation. |
|||
* Warning: CSI is disabled automatically in STOP if not |
|||
* requested for other usages and always OFF in STANDBY. |
|||
* Disable non-secure SYSCFG clock, we assume non-secure is suspended. |
|||
*/ |
|||
value = mmio_read_32(syscfg_base + SYSCFG_CMPCR) >> |
|||
SYSCFG_CMPCR_ANSRC_SHIFT; |
|||
|
|||
mmio_clrbits_32(syscfg_base + SYSCFG_CMPCR, |
|||
SYSCFG_CMPCR_RANSRC | SYSCFG_CMPCR_RAPSRC); |
|||
|
|||
value = mmio_read_32(syscfg_base + SYSCFG_CMPCR) | |
|||
(value << SYSCFG_CMPCR_RANSRC_SHIFT); |
|||
|
|||
mmio_write_32(syscfg_base + SYSCFG_CMPCR, value); |
|||
|
|||
mmio_setbits_32(syscfg_base + SYSCFG_CMPCR, SYSCFG_CMPCR_SW_CTRL); |
|||
|
|||
mmio_clrbits_32(syscfg_base + SYSCFG_CMPENSETR, |
|||
SYSCFG_CMPENSETR_MPU_EN); |
|||
|
|||
stm32mp1_clk_disable_non_secure(SYSCFG); |
|||
} |
Loading…
Reference in new issue