From 2444d2314c9d5c99c8e9101058e9e7bbea9abb2c Mon Sep 17 00:00:00 2001 From: Yann Gautier Date: Wed, 19 Jan 2022 13:57:49 +0100 Subject: [PATCH 1/7] refactor(st-clock): use refcnt instead of secure status Rework the internal functions __stm32mp1_clk_enable/disable to check for reference count instead of secure status for a clock. Some functions now unused can be removed. Change-Id: Ie4359110d7144229f85c961dcd5a019222c3fd25 Signed-off-by: Yann Gautier --- drivers/st/clk/stm32mp1_clk.c | 45 ++++++++++++++++++------------- include/drivers/st/stm32mp1_clk.h | 27 +------------------ 2 files changed, 27 insertions(+), 45 deletions(-) diff --git a/drivers/st/clk/stm32mp1_clk.c b/drivers/st/clk/stm32mp1_clk.c index 3227f1c87..3fe21efec 100644 --- a/drivers/st/clk/stm32mp1_clk.c +++ b/drivers/st/clk/stm32mp1_clk.c @@ -1062,17 +1062,6 @@ static bool __clk_is_enabled(struct stm32mp1_clk_gate const *gate) return mmio_read_32(rcc_base + gate->offset) & BIT(gate->bit); } -unsigned int stm32mp1_clk_get_refcount(unsigned long id) -{ - int i = stm32mp1_clk_get_gated_id(id); - - if (i < 0) { - panic(); - } - - return gate_refcounts[i]; -} - /* Oscillators and PLLs are not gated at runtime */ static bool clock_is_always_on(unsigned long id) { @@ -1101,11 +1090,10 @@ static bool clock_is_always_on(unsigned long id) } } -void __stm32mp1_clk_enable(unsigned long id, bool secure) +static void __stm32mp1_clk_enable(unsigned long id, bool with_refcnt) { const struct stm32mp1_clk_gate *gate; int i; - unsigned int *refcnt; if (clock_is_always_on(id)) { return; @@ -1118,22 +1106,31 @@ void __stm32mp1_clk_enable(unsigned long id, bool secure) } gate = gate_ref(i); - refcnt = &gate_refcounts[i]; + + if (!with_refcnt) { + __clk_enable(gate); + return; + } stm32mp1_clk_lock(&refcount_lock); - if (stm32mp_incr_shrefcnt(refcnt, secure) != 0) { + if (gate_refcounts[i] == 0U) { __clk_enable(gate); } + gate_refcounts[i]++; + if (gate_refcounts[i] == UINT_MAX) { + ERROR("Clock %lu refcount reached max value\n", id); + panic(); + } + stm32mp1_clk_unlock(&refcount_lock); } -void __stm32mp1_clk_disable(unsigned long id, bool secure) +static void __stm32mp1_clk_disable(unsigned long id, bool with_refcnt) { const struct stm32mp1_clk_gate *gate; int i; - unsigned int *refcnt; if (clock_is_always_on(id)) { return; @@ -1146,11 +1143,21 @@ void __stm32mp1_clk_disable(unsigned long id, bool secure) } gate = gate_ref(i); - refcnt = &gate_refcounts[i]; + + if (!with_refcnt) { + __clk_disable(gate); + return; + } stm32mp1_clk_lock(&refcount_lock); - if (stm32mp_decr_shrefcnt(refcnt, secure) != 0) { + if (gate_refcounts[i] == 0U) { + ERROR("Clock %lu refcount reached 0\n", id); + panic(); + } + gate_refcounts[i]--; + + if (gate_refcounts[i] == 0U) { __clk_disable(gate); } diff --git a/include/drivers/st/stm32mp1_clk.h b/include/drivers/st/stm32mp1_clk.h index c46892b78..59c7c0bd6 100644 --- a/include/drivers/st/stm32mp1_clk.h +++ b/include/drivers/st/stm32mp1_clk.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018-2019, STMicroelectronics - All Rights Reserved + * Copyright (c) 2018-2022, STMicroelectronics - All Rights Reserved * * SPDX-License-Identifier: BSD-3-Clause */ @@ -28,31 +28,6 @@ int stm32mp1_clk_init(void); bool stm32mp1_rcc_is_secure(void); bool stm32mp1_rcc_is_mckprot(void); -void __stm32mp1_clk_enable(unsigned long id, bool caller_is_secure); -void __stm32mp1_clk_disable(unsigned long id, bool caller_is_secure); - -static inline void stm32mp1_clk_enable_non_secure(unsigned long id) -{ - __stm32mp1_clk_enable(id, false); -} - -static inline void stm32mp1_clk_enable_secure(unsigned long id) -{ - __stm32mp1_clk_enable(id, true); -} - -static inline void stm32mp1_clk_disable_non_secure(unsigned long id) -{ - __stm32mp1_clk_disable(id, false); -} - -static inline void stm32mp1_clk_disable_secure(unsigned long id) -{ - __stm32mp1_clk_disable(id, true); -} - -unsigned int stm32mp1_clk_get_refcount(unsigned long id); - /* SMP protection on RCC registers access */ void stm32mp1_clk_rcc_regs_lock(void); void stm32mp1_clk_rcc_regs_unlock(void); From 356ed961184847dcd088cfcda44b71eeb0ef2377 Mon Sep 17 00:00:00 2001 From: Yann Gautier Date: Thu, 27 Jan 2022 13:55:18 +0100 Subject: [PATCH 2/7] fix(stm32mp1): add missing debug.h Due to stm32mp_shres_helpers.h removal, the debug.h header is no more included. It should then be added to stm32mp1_boot_device.c. Signed-off-by: Yann Gautier Change-Id: I397911ac05fdff464c010cf3b2e04320a781b4aa --- plat/st/stm32mp1/stm32mp1_boot_device.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plat/st/stm32mp1/stm32mp1_boot_device.c b/plat/st/stm32mp1/stm32mp1_boot_device.c index 997335d0d..6a0570795 100644 --- a/plat/st/stm32mp1/stm32mp1_boot_device.c +++ b/plat/st/stm32mp1/stm32mp1_boot_device.c @@ -1,11 +1,12 @@ /* - * Copyright (c) 2019, STMicroelectronics - All Rights Reserved + * Copyright (c) 2019-2022, STMicroelectronics - All Rights Reserved * * SPDX-License-Identifier: BSD-3-Clause */ #include +#include #include #include #include From e1bfbf8ad3d05ca370fb86b1d4cb96ee6107e936 Mon Sep 17 00:00:00 2001 From: Yann Gautier Date: Wed, 19 Jan 2022 14:01:52 +0100 Subject: [PATCH 3/7] refactor(stm32mp1): remove unused refcount helper functions Remove stm32mp_incr_shrefcnt(), stm32mp_decr_shrefcnt(), stm32mp_incr_refcnt() and stm32mp_decr_refcnt() that are unused. The file is then just removed. Change-Id: I09ee23c02317df5d8f71cbc355d3ed4a67ce2749 Signed-off-by: Etienne Carriere Signed-off-by: Yann Gautier --- .../st/common/include/stm32mp_shres_helpers.h | 74 ------------------- plat/st/stm32mp1/stm32mp1_def.h | 1 - 2 files changed, 75 deletions(-) delete mode 100644 plat/st/common/include/stm32mp_shres_helpers.h diff --git a/plat/st/common/include/stm32mp_shres_helpers.h b/plat/st/common/include/stm32mp_shres_helpers.h deleted file mode 100644 index 8b786cc04..000000000 --- a/plat/st/common/include/stm32mp_shres_helpers.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2018-2019, STMicroelectronics - All Rights Reserved - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -#ifndef STM32MP_SHRES_HELPERS_H -#define STM32MP_SHRES_HELPERS_H - -#include - -#include - -/* - * Shared reference counter: increments by 2 on secure increment - * request, decrements by 2 on secure decrement request. Bit #0 - * is set to 1 on non-secure increment request and reset to 0 on - * non-secure decrement request. The counter initializes to - * either 0, 1 or 2 upon their expect default state. - * Counters saturates once above UINT_MAX / 2. - */ -#define SHREFCNT_NONSECURE_FLAG 0x1UL -#define SHREFCNT_SECURE_STEP 0x2UL -#define SHREFCNT_MAX (UINT32_MAX / 2) - -/* Return 1 if refcnt increments from 0, else return 0 */ -static inline int stm32mp_incr_shrefcnt(unsigned int *refcnt, bool secure) -{ - int rc = !*refcnt; - - if (secure) { - *refcnt += SHREFCNT_SECURE_STEP; - if (*refcnt >= SHREFCNT_MAX) { - panic(); - } - } else { - *refcnt |= SHREFCNT_NONSECURE_FLAG; - } - - return rc; -} - -/* Return 1 if refcnt decrements to 0, else return 0 */ -static inline int stm32mp_decr_shrefcnt(unsigned int *refcnt, bool secure) -{ - int rc = 0; - - if (secure) { - if (*refcnt < SHREFCNT_MAX) { - if (*refcnt < SHREFCNT_SECURE_STEP) { - panic(); - } - *refcnt -= SHREFCNT_SECURE_STEP; - rc = !*refcnt; - } - } else { - rc = (*refcnt == SHREFCNT_NONSECURE_FLAG) ? 1 : 0; - *refcnt &= ~SHREFCNT_NONSECURE_FLAG; - } - - return rc; -} - -static inline int stm32mp_incr_refcnt(unsigned int *refcnt) -{ - return stm32mp_incr_shrefcnt(refcnt, true); -} - -static inline int stm32mp_decr_refcnt(unsigned int *refcnt) -{ - return stm32mp_decr_shrefcnt(refcnt, true); -} - -#endif /* STM32MP_SHRES_HELPERS_H */ diff --git a/plat/st/stm32mp1/stm32mp1_def.h b/plat/st/stm32mp1/stm32mp1_def.h index ab3ef1792..c63efd5af 100644 --- a/plat/st/stm32mp1/stm32mp1_def.h +++ b/plat/st/stm32mp1/stm32mp1_def.h @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include From aaa09b713c6f539fb5b2ee7e2dfd75f2d46875f5 Mon Sep 17 00:00:00 2001 From: Yann Gautier Date: Wed, 27 Oct 2021 18:16:59 +0200 Subject: [PATCH 4/7] feat(st-clock): define secure and non-secure gate clocks Array stm32mp1_clk_gate[] defines the clock resources. This change add a secure attribute to the clock: secure upon RCC[TZEN] (SEC), secure upon RCC[TZEN] and RCC[MCKPROT] (MKP) or always accessible from non-secure (N_S). At init, lookup clock tree to check if any of the secure clocks is derived from PLL3 in which case PLL3 shall be secure. Note that this change does not grow byte size of stm32mp1_clk_gate[]. Change-Id: I933d8a30007f3c72f755aa1ef6d7e6bcfabbfa9e Signed-off-by: Etienne Carriere Signed-off-by: Yann Gautier --- drivers/st/clk/stm32mp1_clk.c | 164 ++++++++++++++++++---------------- 1 file changed, 86 insertions(+), 78 deletions(-) diff --git a/drivers/st/clk/stm32mp1_clk.c b/drivers/st/clk/stm32mp1_clk.c index 3fe21efec..49146115b 100644 --- a/drivers/st/clk/stm32mp1_clk.c +++ b/drivers/st/clk/stm32mp1_clk.c @@ -241,6 +241,7 @@ struct stm32mp1_clk_gate { uint8_t bit; uint8_t index; uint8_t set_clr; + uint8_t secure; uint8_t sel; /* Relates to enum stm32mp1_parent_sel */ uint8_t fixed; /* Relates to enum stm32mp1_parent_id */ }; @@ -266,45 +267,49 @@ struct stm32mp1_clk_pll { }; /* Clocks with selectable source and non set/clr register access */ -#define _CLK_SELEC(off, b, idx, s) \ +#define _CLK_SELEC(sec, off, b, idx, s) \ { \ .offset = (off), \ .bit = (b), \ .index = (idx), \ .set_clr = 0, \ + .secure = (sec), \ .sel = (s), \ .fixed = _UNKNOWN_ID, \ } /* Clocks with fixed source and non set/clr register access */ -#define _CLK_FIXED(off, b, idx, f) \ +#define _CLK_FIXED(sec, off, b, idx, f) \ { \ .offset = (off), \ .bit = (b), \ .index = (idx), \ .set_clr = 0, \ + .secure = (sec), \ .sel = _UNKNOWN_SEL, \ .fixed = (f), \ } /* Clocks with selectable source and set/clr register access */ -#define _CLK_SC_SELEC(off, b, idx, s) \ +#define _CLK_SC_SELEC(sec, off, b, idx, s) \ { \ .offset = (off), \ .bit = (b), \ .index = (idx), \ .set_clr = 1, \ + .secure = (sec), \ .sel = (s), \ .fixed = _UNKNOWN_ID, \ } /* Clocks with fixed source and set/clr register access */ -#define _CLK_SC_FIXED(off, b, idx, f) \ +#define _CLK_SC_FIXED(sec, off, b, idx, f) \ { \ .offset = (off), \ .bit = (b), \ .index = (idx), \ .set_clr = 1, \ + .secure = (sec), \ .sel = _UNKNOWN_SEL, \ .fixed = (f), \ } @@ -338,81 +343,84 @@ struct stm32mp1_clk_pll { #define NB_GATES ARRAY_SIZE(stm32mp1_clk_gate) +#define SEC 1 +#define N_S 0 + static const struct stm32mp1_clk_gate stm32mp1_clk_gate[] = { - _CLK_FIXED(RCC_DDRITFCR, 0, DDRC1, _ACLK), - _CLK_FIXED(RCC_DDRITFCR, 1, DDRC1LP, _ACLK), - _CLK_FIXED(RCC_DDRITFCR, 2, DDRC2, _ACLK), - _CLK_FIXED(RCC_DDRITFCR, 3, DDRC2LP, _ACLK), - _CLK_FIXED(RCC_DDRITFCR, 4, DDRPHYC, _PLL2_R), - _CLK_FIXED(RCC_DDRITFCR, 5, DDRPHYCLP, _PLL2_R), - _CLK_FIXED(RCC_DDRITFCR, 6, DDRCAPB, _PCLK4), - _CLK_FIXED(RCC_DDRITFCR, 7, DDRCAPBLP, _PCLK4), - _CLK_FIXED(RCC_DDRITFCR, 8, AXIDCG, _ACLK), - _CLK_FIXED(RCC_DDRITFCR, 9, DDRPHYCAPB, _PCLK4), - _CLK_FIXED(RCC_DDRITFCR, 10, DDRPHYCAPBLP, _PCLK4), - - _CLK_SC_FIXED(RCC_MP_APB1ENSETR, 6, TIM12_K, _PCLK1), - _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 14, USART2_K, _UART24_SEL), - _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 15, USART3_K, _UART35_SEL), - _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 16, UART4_K, _UART24_SEL), - _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 17, UART5_K, _UART35_SEL), - _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 18, UART7_K, _UART78_SEL), - _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 19, UART8_K, _UART78_SEL), - _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 21, I2C1_K, _I2C12_SEL), - _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 22, I2C2_K, _I2C12_SEL), - _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 23, I2C3_K, _I2C35_SEL), - _CLK_SC_SELEC(RCC_MP_APB1ENSETR, 24, I2C5_K, _I2C35_SEL), - - _CLK_SC_FIXED(RCC_MP_APB2ENSETR, 2, TIM15_K, _PCLK2), - _CLK_SC_SELEC(RCC_MP_APB2ENSETR, 13, USART6_K, _UART6_SEL), - - _CLK_SC_FIXED(RCC_MP_APB3ENSETR, 11, SYSCFG, _UNKNOWN_ID), - - _CLK_SC_SELEC(RCC_MP_APB4ENSETR, 8, DDRPERFM, _UNKNOWN_SEL), - _CLK_SC_SELEC(RCC_MP_APB4ENSETR, 15, IWDG2, _UNKNOWN_SEL), - _CLK_SC_SELEC(RCC_MP_APB4ENSETR, 16, USBPHY_K, _USBPHY_SEL), - - _CLK_SC_SELEC(RCC_MP_APB5ENSETR, 0, SPI6_K, _SPI6_SEL), - _CLK_SC_SELEC(RCC_MP_APB5ENSETR, 2, I2C4_K, _I2C46_SEL), - _CLK_SC_SELEC(RCC_MP_APB5ENSETR, 3, I2C6_K, _I2C46_SEL), - _CLK_SC_SELEC(RCC_MP_APB5ENSETR, 4, USART1_K, _UART1_SEL), - _CLK_SC_FIXED(RCC_MP_APB5ENSETR, 8, RTCAPB, _PCLK5), - _CLK_SC_FIXED(RCC_MP_APB5ENSETR, 11, TZC1, _PCLK5), - _CLK_SC_FIXED(RCC_MP_APB5ENSETR, 12, TZC2, _PCLK5), - _CLK_SC_FIXED(RCC_MP_APB5ENSETR, 13, TZPC, _PCLK5), - _CLK_SC_FIXED(RCC_MP_APB5ENSETR, 15, IWDG1, _PCLK5), - _CLK_SC_FIXED(RCC_MP_APB5ENSETR, 16, BSEC, _PCLK5), - _CLK_SC_SELEC(RCC_MP_APB5ENSETR, 20, STGEN_K, _STGEN_SEL), - - _CLK_SC_SELEC(RCC_MP_AHB2ENSETR, 8, USBO_K, _USBO_SEL), - _CLK_SC_SELEC(RCC_MP_AHB2ENSETR, 16, SDMMC3_K, _SDMMC3_SEL), - - _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 0, GPIOA, _UNKNOWN_SEL), - _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 1, GPIOB, _UNKNOWN_SEL), - _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 2, GPIOC, _UNKNOWN_SEL), - _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 3, GPIOD, _UNKNOWN_SEL), - _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 4, GPIOE, _UNKNOWN_SEL), - _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 5, GPIOF, _UNKNOWN_SEL), - _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 6, GPIOG, _UNKNOWN_SEL), - _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 7, GPIOH, _UNKNOWN_SEL), - _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 8, GPIOI, _UNKNOWN_SEL), - _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 9, GPIOJ, _UNKNOWN_SEL), - _CLK_SC_SELEC(RCC_MP_AHB4ENSETR, 10, GPIOK, _UNKNOWN_SEL), - - _CLK_SC_FIXED(RCC_MP_AHB5ENSETR, 0, GPIOZ, _PCLK5), - _CLK_SC_FIXED(RCC_MP_AHB5ENSETR, 4, CRYP1, _PCLK5), - _CLK_SC_FIXED(RCC_MP_AHB5ENSETR, 5, HASH1, _PCLK5), - _CLK_SC_SELEC(RCC_MP_AHB5ENSETR, 6, RNG1_K, _RNG1_SEL), - _CLK_SC_FIXED(RCC_MP_AHB5ENSETR, 8, BKPSRAM, _PCLK5), - - _CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 12, FMC_K, _FMC_SEL), - _CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 14, QSPI_K, _QSPI_SEL), - _CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 16, SDMMC1_K, _SDMMC12_SEL), - _CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 17, SDMMC2_K, _SDMMC12_SEL), - _CLK_SC_SELEC(RCC_MP_AHB6ENSETR, 24, USBH, _UNKNOWN_SEL), - - _CLK_SELEC(RCC_BDCR, 20, RTC, _RTC_SEL), - _CLK_SELEC(RCC_DBGCFGR, 8, CK_DBG, _UNKNOWN_SEL), + _CLK_FIXED(SEC, RCC_DDRITFCR, 0, DDRC1, _ACLK), + _CLK_FIXED(SEC, RCC_DDRITFCR, 1, DDRC1LP, _ACLK), + _CLK_FIXED(SEC, RCC_DDRITFCR, 2, DDRC2, _ACLK), + _CLK_FIXED(SEC, RCC_DDRITFCR, 3, DDRC2LP, _ACLK), + _CLK_FIXED(SEC, RCC_DDRITFCR, 4, DDRPHYC, _PLL2_R), + _CLK_FIXED(SEC, RCC_DDRITFCR, 5, DDRPHYCLP, _PLL2_R), + _CLK_FIXED(SEC, RCC_DDRITFCR, 6, DDRCAPB, _PCLK4), + _CLK_FIXED(SEC, RCC_DDRITFCR, 7, DDRCAPBLP, _PCLK4), + _CLK_FIXED(SEC, RCC_DDRITFCR, 8, AXIDCG, _ACLK), + _CLK_FIXED(SEC, RCC_DDRITFCR, 9, DDRPHYCAPB, _PCLK4), + _CLK_FIXED(SEC, RCC_DDRITFCR, 10, DDRPHYCAPBLP, _PCLK4), + + _CLK_SC_FIXED(N_S, RCC_MP_APB1ENSETR, 6, TIM12_K, _PCLK1), + _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 14, USART2_K, _UART24_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 15, USART3_K, _UART35_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 16, UART4_K, _UART24_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 17, UART5_K, _UART35_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 18, UART7_K, _UART78_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 19, UART8_K, _UART78_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 21, I2C1_K, _I2C12_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 22, I2C2_K, _I2C12_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 23, I2C3_K, _I2C35_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 24, I2C5_K, _I2C35_SEL), + + _CLK_SC_FIXED(N_S, RCC_MP_APB2ENSETR, 2, TIM15_K, _PCLK2), + _CLK_SC_SELEC(N_S, RCC_MP_APB2ENSETR, 13, USART6_K, _UART6_SEL), + + _CLK_SC_FIXED(N_S, RCC_MP_APB3ENSETR, 11, SYSCFG, _UNKNOWN_ID), + + _CLK_SC_SELEC(N_S, RCC_MP_APB4ENSETR, 8, DDRPERFM, _UNKNOWN_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_APB4ENSETR, 15, IWDG2, _UNKNOWN_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_APB4ENSETR, 16, USBPHY_K, _USBPHY_SEL), + + _CLK_SC_SELEC(SEC, RCC_MP_APB5ENSETR, 0, SPI6_K, _SPI6_SEL), + _CLK_SC_SELEC(SEC, RCC_MP_APB5ENSETR, 2, I2C4_K, _I2C46_SEL), + _CLK_SC_SELEC(SEC, RCC_MP_APB5ENSETR, 3, I2C6_K, _I2C46_SEL), + _CLK_SC_SELEC(SEC, RCC_MP_APB5ENSETR, 4, USART1_K, _UART1_SEL), + _CLK_SC_FIXED(SEC, RCC_MP_APB5ENSETR, 8, RTCAPB, _PCLK5), + _CLK_SC_FIXED(SEC, RCC_MP_APB5ENSETR, 11, TZC1, _PCLK5), + _CLK_SC_FIXED(SEC, RCC_MP_APB5ENSETR, 12, TZC2, _PCLK5), + _CLK_SC_FIXED(SEC, RCC_MP_APB5ENSETR, 13, TZPC, _PCLK5), + _CLK_SC_FIXED(SEC, RCC_MP_APB5ENSETR, 15, IWDG1, _PCLK5), + _CLK_SC_FIXED(SEC, RCC_MP_APB5ENSETR, 16, BSEC, _PCLK5), + _CLK_SC_SELEC(SEC, RCC_MP_APB5ENSETR, 20, STGEN_K, _STGEN_SEL), + + _CLK_SC_SELEC(N_S, RCC_MP_AHB2ENSETR, 8, USBO_K, _USBO_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_AHB2ENSETR, 16, SDMMC3_K, _SDMMC3_SEL), + + _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 0, GPIOA, _UNKNOWN_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 1, GPIOB, _UNKNOWN_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 2, GPIOC, _UNKNOWN_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 3, GPIOD, _UNKNOWN_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 4, GPIOE, _UNKNOWN_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 5, GPIOF, _UNKNOWN_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 6, GPIOG, _UNKNOWN_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 7, GPIOH, _UNKNOWN_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 8, GPIOI, _UNKNOWN_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 9, GPIOJ, _UNKNOWN_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 10, GPIOK, _UNKNOWN_SEL), + + _CLK_SC_FIXED(SEC, RCC_MP_AHB5ENSETR, 0, GPIOZ, _PCLK5), + _CLK_SC_FIXED(SEC, RCC_MP_AHB5ENSETR, 4, CRYP1, _PCLK5), + _CLK_SC_FIXED(SEC, RCC_MP_AHB5ENSETR, 5, HASH1, _PCLK5), + _CLK_SC_SELEC(SEC, RCC_MP_AHB5ENSETR, 6, RNG1_K, _RNG1_SEL), + _CLK_SC_FIXED(SEC, RCC_MP_AHB5ENSETR, 8, BKPSRAM, _PCLK5), + + _CLK_SC_SELEC(N_S, RCC_MP_AHB6ENSETR, 12, FMC_K, _FMC_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_AHB6ENSETR, 14, QSPI_K, _QSPI_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_AHB6ENSETR, 16, SDMMC1_K, _SDMMC12_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_AHB6ENSETR, 17, SDMMC2_K, _SDMMC12_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_AHB6ENSETR, 24, USBH, _UNKNOWN_SEL), + + _CLK_SELEC(SEC, RCC_BDCR, 20, RTC, _RTC_SEL), + _CLK_SELEC(N_S, RCC_DBGCFGR, 8, CK_DBG, _UNKNOWN_SEL), }; static const uint8_t i2c12_parents[] = { From 3d69149a7e9e9a899d57f48bee26f98614f88935 Mon Sep 17 00:00:00 2001 From: Yann Gautier Date: Wed, 27 Oct 2021 18:21:11 +0200 Subject: [PATCH 5/7] feat(st-clock): do not refcount on non-secure clocks in bl32 This change removes reference counting support in clock gating implementation for clocks that rely on non-secure only RCC resources. As RCC registers are accessed straight by non-secure world for these clocks, secure world cannot safely store the clock state and even disabling such clock from secure world can jeopardize the non-secure world clock management framework and drivers. As a consequence, for such clocks, stm32_clock_enable() forces the clock ON without any increment of a refcount and stm32_clock_disable() does not disable the clock. Change-Id: I0cc159b36a25dbc8676f05edf2668ae63c640537 Signed-off-by: Etienne Carriere --- drivers/st/clk/stm32mp1_clk.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/drivers/st/clk/stm32mp1_clk.c b/drivers/st/clk/stm32mp1_clk.c index 49146115b..6b862dabd 100644 --- a/drivers/st/clk/stm32mp1_clk.c +++ b/drivers/st/clk/stm32mp1_clk.c @@ -636,6 +636,13 @@ static const struct stm32mp1_clk_gate *gate_ref(unsigned int idx) return &stm32mp1_clk_gate[idx]; } +#if defined(IMAGE_BL32) +static bool gate_is_non_secure(const struct stm32mp1_clk_gate *gate) +{ + return gate->secure == N_S; +} +#endif + static const struct stm32mp1_clk_sel *clk_sel_ref(unsigned int idx) { return &stm32mp1_clk_sel[idx]; @@ -1120,6 +1127,14 @@ static void __stm32mp1_clk_enable(unsigned long id, bool with_refcnt) return; } +#if defined(IMAGE_BL32) + if (gate_is_non_secure(gate)) { + /* Enable non-secure clock w/o any refcounting */ + __clk_enable(gate); + return; + } +#endif + stm32mp1_clk_lock(&refcount_lock); if (gate_refcounts[i] == 0U) { @@ -1157,6 +1172,13 @@ static void __stm32mp1_clk_disable(unsigned long id, bool with_refcnt) return; } +#if defined(IMAGE_BL32) + if (gate_is_non_secure(gate)) { + /* Don't disable non-secure clocks */ + return; + } +#endif + stm32mp1_clk_lock(&refcount_lock); if (gate_refcounts[i] == 0U) { From 7418cf397916c97cb4ecf159b1f497a84299b695 Mon Sep 17 00:00:00 2001 From: Yann Gautier Date: Fri, 17 Jan 2020 11:59:28 +0100 Subject: [PATCH 6/7] feat(st-clock): assign clocks to the correct BL Some clocks are only required in BL2, like boot devices clocks: FMC, QSPI. Some clocks are only used in BL32: Timers, devices that need special care for independent reset. Change-Id: Id4ba99afeea5095f419a86f7dc6423192c628d82 Signed-off-by: Etienne Carriere Signed-off-by: Yann Gautier --- drivers/st/clk/stm32mp1_clk.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/st/clk/stm32mp1_clk.c b/drivers/st/clk/stm32mp1_clk.c index 6b862dabd..2b6683dfa 100644 --- a/drivers/st/clk/stm32mp1_clk.c +++ b/drivers/st/clk/stm32mp1_clk.c @@ -359,7 +359,9 @@ static const struct stm32mp1_clk_gate stm32mp1_clk_gate[] = { _CLK_FIXED(SEC, RCC_DDRITFCR, 9, DDRPHYCAPB, _PCLK4), _CLK_FIXED(SEC, RCC_DDRITFCR, 10, DDRPHYCAPBLP, _PCLK4), +#if defined(IMAGE_BL32) _CLK_SC_FIXED(N_S, RCC_MP_APB1ENSETR, 6, TIM12_K, _PCLK1), +#endif _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 14, USART2_K, _UART24_SEL), _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 15, USART3_K, _UART35_SEL), _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 16, UART4_K, _UART24_SEL), @@ -371,7 +373,9 @@ static const struct stm32mp1_clk_gate stm32mp1_clk_gate[] = { _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 23, I2C3_K, _I2C35_SEL), _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 24, I2C5_K, _I2C35_SEL), +#if defined(IMAGE_BL32) _CLK_SC_FIXED(N_S, RCC_MP_APB2ENSETR, 2, TIM15_K, _PCLK2), +#endif _CLK_SC_SELEC(N_S, RCC_MP_APB2ENSETR, 13, USART6_K, _UART6_SEL), _CLK_SC_FIXED(N_S, RCC_MP_APB3ENSETR, 11, SYSCFG, _UNKNOWN_ID), @@ -392,8 +396,10 @@ static const struct stm32mp1_clk_gate stm32mp1_clk_gate[] = { _CLK_SC_FIXED(SEC, RCC_MP_APB5ENSETR, 16, BSEC, _PCLK5), _CLK_SC_SELEC(SEC, RCC_MP_APB5ENSETR, 20, STGEN_K, _STGEN_SEL), +#if defined(IMAGE_BL32) _CLK_SC_SELEC(N_S, RCC_MP_AHB2ENSETR, 8, USBO_K, _USBO_SEL), _CLK_SC_SELEC(N_S, RCC_MP_AHB2ENSETR, 16, SDMMC3_K, _SDMMC3_SEL), +#endif _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 0, GPIOA, _UNKNOWN_SEL), _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 1, GPIOB, _UNKNOWN_SEL), @@ -413,11 +419,15 @@ static const struct stm32mp1_clk_gate stm32mp1_clk_gate[] = { _CLK_SC_SELEC(SEC, RCC_MP_AHB5ENSETR, 6, RNG1_K, _RNG1_SEL), _CLK_SC_FIXED(SEC, RCC_MP_AHB5ENSETR, 8, BKPSRAM, _PCLK5), +#if defined(IMAGE_BL2) _CLK_SC_SELEC(N_S, RCC_MP_AHB6ENSETR, 12, FMC_K, _FMC_SEL), _CLK_SC_SELEC(N_S, RCC_MP_AHB6ENSETR, 14, QSPI_K, _QSPI_SEL), +#endif _CLK_SC_SELEC(N_S, RCC_MP_AHB6ENSETR, 16, SDMMC1_K, _SDMMC12_SEL), _CLK_SC_SELEC(N_S, RCC_MP_AHB6ENSETR, 17, SDMMC2_K, _SDMMC12_SEL), +#if defined(IMAGE_BL32) _CLK_SC_SELEC(N_S, RCC_MP_AHB6ENSETR, 24, USBH, _UNKNOWN_SEL), +#endif _CLK_SELEC(SEC, RCC_BDCR, 20, RTC, _RTC_SEL), _CLK_SELEC(N_S, RCC_DBGCFGR, 8, CK_DBG, _UNKNOWN_SEL), From 591d80c8b108e272ea988113ec23c4d2a3ae450a Mon Sep 17 00:00:00 2001 From: Lionel Debieve Date: Wed, 4 Dec 2019 21:50:19 +0100 Subject: [PATCH 7/7] refactor(st-clock): update STGEN management Rework STGEN config function, and move it to stm32mp_clkfunc.c file. Change-Id: I7784a79c486d1b8811f6f8d123e49ea34899e9b6 Signed-off-by: Lionel Debieve Signed-off-by: Yann Gautier --- drivers/st/clk/stm32mp1_clk.c | 51 ++--------------------- drivers/st/clk/stm32mp_clkfunc.c | 60 ++++++++++++++++++++++++++++ include/drivers/st/stm32mp1_clk.h | 2 - include/drivers/st/stm32mp_clkfunc.h | 5 +++ 4 files changed, 69 insertions(+), 49 deletions(-) diff --git a/drivers/st/clk/stm32mp1_clk.c b/drivers/st/clk/stm32mp1_clk.c index 2b6683dfa..af8b71e32 100644 --- a/drivers/st/clk/stm32mp1_clk.c +++ b/drivers/st/clk/stm32mp1_clk.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include @@ -1767,50 +1766,6 @@ static void stm32mp1_set_rtcsrc(unsigned int clksrc, bool lse_css) } } -static void stm32mp1_stgen_config(void) -{ - uint32_t cntfid0; - unsigned long rate; - unsigned long long counter; - - cntfid0 = mmio_read_32(STGEN_BASE + CNTFID_OFF); - rate = get_clock_rate(stm32mp1_clk_get_parent(STGEN_K)); - - if (cntfid0 == rate) { - return; - } - - mmio_clrbits_32(STGEN_BASE + CNTCR_OFF, CNTCR_EN); - counter = (unsigned long long)mmio_read_32(STGEN_BASE + CNTCVL_OFF); - counter |= ((unsigned long long)mmio_read_32(STGEN_BASE + CNTCVU_OFF)) << 32; - counter = (counter * rate / cntfid0); - - mmio_write_32(STGEN_BASE + CNTCVL_OFF, (uint32_t)counter); - mmio_write_32(STGEN_BASE + CNTCVU_OFF, (uint32_t)(counter >> 32)); - mmio_write_32(STGEN_BASE + CNTFID_OFF, rate); - mmio_setbits_32(STGEN_BASE + CNTCR_OFF, CNTCR_EN); - - write_cntfrq((u_register_t)rate); - - /* Need to update timer with new frequency */ - generic_delay_timer_init(); -} - -void stm32mp1_stgen_increment(unsigned long long offset_in_ms) -{ - unsigned long long cnt; - - cnt = ((unsigned long long)mmio_read_32(STGEN_BASE + CNTCVU_OFF) << 32) | - mmio_read_32(STGEN_BASE + CNTCVL_OFF); - - cnt += (offset_in_ms * mmio_read_32(STGEN_BASE + CNTFID_OFF)) / 1000U; - - mmio_clrbits_32(STGEN_BASE + CNTCR_OFF, CNTCR_EN); - mmio_write_32(STGEN_BASE + CNTCVL_OFF, (uint32_t)cnt); - mmio_write_32(STGEN_BASE + CNTCVU_OFF, (uint32_t)(cnt >> 32)); - mmio_setbits_32(STGEN_BASE + CNTCR_OFF, CNTCR_EN); -} - static void stm32mp1_pkcs_config(uint32_t pkcs) { uintptr_t address = stm32mp_rcc_base() + ((pkcs >> 4) & 0xFFFU); @@ -2006,7 +1961,8 @@ int stm32mp1_clk_init(void) if (ret != 0) { return ret; } - stm32mp1_stgen_config(); + + stm32mp_stgen_config(stm32mp_clk_get_rate(STGEN_K)); } /* Select DIV */ @@ -2180,7 +2136,8 @@ int stm32mp1_clk_init(void) if (stm32mp1_osc[_HSI] == 0U) { stm32mp1_hsi_set(false); } - stm32mp1_stgen_config(); + + stm32mp_stgen_config(stm32mp_clk_get_rate(STGEN_K)); /* Software Self-Refresh mode (SSR) during DDR initilialization */ mmio_clrsetbits_32(rcc_base + RCC_DDRITFCR, diff --git a/drivers/st/clk/stm32mp_clkfunc.c b/drivers/st/clk/stm32mp_clkfunc.c index 5ba64fd4e..a013a82c0 100644 --- a/drivers/st/clk/stm32mp_clkfunc.c +++ b/drivers/st/clk/stm32mp_clkfunc.c @@ -6,10 +6,13 @@ #include +#include #include #include +#include #include #include +#include #include #include @@ -318,3 +321,60 @@ unsigned long fdt_get_uart_clock_freq(uintptr_t instance) return clk_get_rate((unsigned long)clk_id); } + +/******************************************************************************* + * This function configures and restores the STGEN counter depending on the + * connected clock. + ******************************************************************************/ +void stm32mp_stgen_config(unsigned long rate) +{ + uint32_t cntfid0; + unsigned long long counter; + + cntfid0 = mmio_read_32(STGEN_BASE + CNTFID_OFF); + + if (cntfid0 == rate) { + return; + } + + mmio_clrbits_32(STGEN_BASE + CNTCR_OFF, CNTCR_EN); + counter = stm32mp_stgen_get_counter() * rate / cntfid0; + + mmio_write_32(STGEN_BASE + CNTCVL_OFF, (uint32_t)counter); + mmio_write_32(STGEN_BASE + CNTCVU_OFF, (uint32_t)(counter >> 32)); + mmio_write_32(STGEN_BASE + CNTFID_OFF, rate); + mmio_setbits_32(STGEN_BASE + CNTCR_OFF, CNTCR_EN); + + write_cntfrq_el0(rate); + + /* Need to update timer with new frequency */ + generic_delay_timer_init(); +} + +/******************************************************************************* + * This function returns the STGEN counter value. + ******************************************************************************/ +unsigned long long stm32mp_stgen_get_counter(void) +{ + return (((unsigned long long)mmio_read_32(STGEN_BASE + CNTCVU_OFF) << 32) | + mmio_read_32(STGEN_BASE + CNTCVL_OFF)); +} + +/******************************************************************************* + * This function restores the STGEN counter value. + * It takes a first input value as a counter backup value to be restored and a + * offset in ms to be added. + ******************************************************************************/ +void stm32mp_stgen_restore_counter(unsigned long long value, + unsigned long long offset_in_ms) +{ + unsigned long long cnt; + + cnt = value + ((offset_in_ms * + mmio_read_32(STGEN_BASE + CNTFID_OFF)) / 1000U); + + mmio_clrbits_32(STGEN_BASE + CNTCR_OFF, CNTCR_EN); + mmio_write_32(STGEN_BASE + CNTCVL_OFF, (uint32_t)cnt); + mmio_write_32(STGEN_BASE + CNTCVU_OFF, (uint32_t)(cnt >> 32)); + mmio_setbits_32(STGEN_BASE + CNTCR_OFF, CNTCR_EN); +} diff --git a/include/drivers/st/stm32mp1_clk.h b/include/drivers/st/stm32mp1_clk.h index 59c7c0bd6..e2395bc5c 100644 --- a/include/drivers/st/stm32mp1_clk.h +++ b/include/drivers/st/stm32mp1_clk.h @@ -32,8 +32,6 @@ bool stm32mp1_rcc_is_mckprot(void); void stm32mp1_clk_rcc_regs_lock(void); void stm32mp1_clk_rcc_regs_unlock(void); -void stm32mp1_stgen_increment(unsigned long long offset_in_ms); - #ifdef STM32MP_SHARED_RESOURCES void stm32mp1_register_clock_parents_secure(unsigned long id); #endif diff --git a/include/drivers/st/stm32mp_clkfunc.h b/include/drivers/st/stm32mp_clkfunc.h index 4876213a7..9df38d685 100644 --- a/include/drivers/st/stm32mp_clkfunc.h +++ b/include/drivers/st/stm32mp_clkfunc.h @@ -28,4 +28,9 @@ bool fdt_get_rcc_secure_status(void); int fdt_get_clock_id(int node); unsigned long fdt_get_uart_clock_freq(uintptr_t instance); +void stm32mp_stgen_config(unsigned long rate); +void stm32mp_stgen_restore_counter(unsigned long long value, + unsigned long long offset_in_ms); +unsigned long long stm32mp_stgen_get_counter(void); + #endif /* STM32MP_CLKFUNC_H */