1c9d75b3cSYann Gautier /*
2*08252f9dSPatrick Delaunay * Copyright (c) 2015-2025, Arm Limited and Contributors. All rights reserved.
3c9d75b3cSYann Gautier *
4c9d75b3cSYann Gautier * SPDX-License-Identifier: BSD-3-Clause
5c9d75b3cSYann Gautier */
6c9d75b3cSYann Gautier
7c9d75b3cSYann Gautier #include <assert.h>
81e919529SYann Gautier #include <errno.h>
9c9d75b3cSYann Gautier
10c9d75b3cSYann Gautier #include <arch_helpers.h>
11c9d75b3cSYann Gautier #include <common/debug.h>
1233667d29SYann Gautier #include <drivers/clk.h>
1353612f72SYann Gautier #include <drivers/delay_timer.h>
1453612f72SYann Gautier #include <drivers/st/stm32_console.h>
157ae58c6bSYann Gautier #include <drivers/st/stm32mp_clkfunc.h>
1653612f72SYann Gautier #include <drivers/st/stm32mp_reset.h>
17d8da13e5SYann Gautier #include <lib/mmio.h>
183d201787SYann Gautier #include <lib/smccc.h>
1984686ba3SYann Gautier #include <lib/xlat_tables/xlat_tables_v2.h>
20c9d75b3cSYann Gautier #include <plat/common/platform.h>
213d201787SYann Gautier #include <services/arm_arch_svc.h>
22c9d75b3cSYann Gautier
2353612f72SYann Gautier #include <platform_def.h>
2453612f72SYann Gautier
258ce89187SNicolas Le Bayon #define HEADER_VERSION_MAJOR_MASK GENMASK(23, 16)
2653612f72SYann Gautier #define RESET_TIMEOUT_US_1MS 1000U
2753612f72SYann Gautier
28992dba08SYann Gautier /* Internal layout of the 32bit OTP word board_id */
29992dba08SYann Gautier #define BOARD_ID_BOARD_NB_MASK GENMASK_32(31, 16)
30992dba08SYann Gautier #define BOARD_ID_BOARD_NB_SHIFT 16
31992dba08SYann Gautier #define BOARD_ID_VARCPN_MASK GENMASK_32(15, 12)
32992dba08SYann Gautier #define BOARD_ID_VARCPN_SHIFT 12
33992dba08SYann Gautier #define BOARD_ID_REVISION_MASK GENMASK_32(11, 8)
34992dba08SYann Gautier #define BOARD_ID_REVISION_SHIFT 8
35992dba08SYann Gautier #define BOARD_ID_VARFG_MASK GENMASK_32(7, 4)
36992dba08SYann Gautier #define BOARD_ID_VARFG_SHIFT 4
37992dba08SYann Gautier #define BOARD_ID_BOM_MASK GENMASK_32(3, 0)
38992dba08SYann Gautier
39992dba08SYann Gautier #define BOARD_ID2NB(_id) (((_id) & BOARD_ID_BOARD_NB_MASK) >> \
40992dba08SYann Gautier BOARD_ID_BOARD_NB_SHIFT)
41992dba08SYann Gautier #define BOARD_ID2VARCPN(_id) (((_id) & BOARD_ID_VARCPN_MASK) >> \
42992dba08SYann Gautier BOARD_ID_VARCPN_SHIFT)
43992dba08SYann Gautier #define BOARD_ID2REV(_id) (((_id) & BOARD_ID_REVISION_MASK) >> \
44992dba08SYann Gautier BOARD_ID_REVISION_SHIFT)
45992dba08SYann Gautier #define BOARD_ID2VARFG(_id) (((_id) & BOARD_ID_VARFG_MASK) >> \
46992dba08SYann Gautier BOARD_ID_VARFG_SHIFT)
47992dba08SYann Gautier #define BOARD_ID2BOM(_id) ((_id) & BOARD_ID_BOM_MASK)
48992dba08SYann Gautier
49d8da13e5SYann Gautier #define BOOT_AUTH_MASK GENMASK_32(23, 20)
50d8da13e5SYann Gautier #define BOOT_AUTH_SHIFT 20
51d8da13e5SYann Gautier #define BOOT_PART_MASK GENMASK_32(19, 16)
52d8da13e5SYann Gautier #define BOOT_PART_SHIFT 16
53d8da13e5SYann Gautier #define BOOT_ITF_MASK GENMASK_32(15, 12)
54d8da13e5SYann Gautier #define BOOT_ITF_SHIFT 12
55d8da13e5SYann Gautier #define BOOT_INST_MASK GENMASK_32(11, 8)
56d8da13e5SYann Gautier #define BOOT_INST_SHIFT 8
57d8da13e5SYann Gautier
58b91c7f5eSYann Gautier /* Layout for fwu update information. */
59b91c7f5eSYann Gautier #define FWU_INFO_IDX_MSK GENMASK(3, 0)
60b91c7f5eSYann Gautier #define FWU_INFO_IDX_OFF U(0)
61b91c7f5eSYann Gautier #define FWU_INFO_CNT_MSK GENMASK(7, 4)
62b91c7f5eSYann Gautier #define FWU_INFO_CNT_OFF U(4)
63b91c7f5eSYann Gautier
6453612f72SYann Gautier static console_t console;
658ce89187SNicolas Le Bayon
plat_get_ns_image_entrypoint(void)66c9d75b3cSYann Gautier uintptr_t plat_get_ns_image_entrypoint(void)
67c9d75b3cSYann Gautier {
68c9d75b3cSYann Gautier return BL33_BASE;
69c9d75b3cSYann Gautier }
70c9d75b3cSYann Gautier
plat_get_syscnt_freq2(void)71c9d75b3cSYann Gautier unsigned int plat_get_syscnt_freq2(void)
72c9d75b3cSYann Gautier {
73c9d75b3cSYann Gautier return read_cntfrq_el0();
74c9d75b3cSYann Gautier }
75c9d75b3cSYann Gautier
76c9d75b3cSYann Gautier static uintptr_t boot_ctx_address;
777e87ba25SYann Gautier static uint16_t boot_itf_selected;
78c9d75b3cSYann Gautier
stm32mp_save_boot_ctx_address(uintptr_t address)793f9c9784SYann Gautier void stm32mp_save_boot_ctx_address(uintptr_t address)
80c9d75b3cSYann Gautier {
817e87ba25SYann Gautier boot_api_context_t *boot_context = (boot_api_context_t *)address;
827e87ba25SYann Gautier
83c9d75b3cSYann Gautier boot_ctx_address = address;
847e87ba25SYann Gautier boot_itf_selected = boot_context->boot_interface_selected;
85c9d75b3cSYann Gautier }
86c9d75b3cSYann Gautier
stm32mp_get_boot_ctx_address(void)873f9c9784SYann Gautier uintptr_t stm32mp_get_boot_ctx_address(void)
88c9d75b3cSYann Gautier {
89c9d75b3cSYann Gautier return boot_ctx_address;
90c9d75b3cSYann Gautier }
91c9d75b3cSYann Gautier
stm32mp_get_boot_itf_selected(void)927e87ba25SYann Gautier uint16_t stm32mp_get_boot_itf_selected(void)
937e87ba25SYann Gautier {
947e87ba25SYann Gautier return boot_itf_selected;
957e87ba25SYann Gautier }
967e87ba25SYann Gautier
stm32mp_ddrctrl_base(void)977ae58c6bSYann Gautier uintptr_t stm32mp_ddrctrl_base(void)
987ae58c6bSYann Gautier {
99ade9ce03SYann Gautier return DDRCTRL_BASE;
1007ae58c6bSYann Gautier }
1017ae58c6bSYann Gautier
stm32mp_ddrphyc_base(void)1027ae58c6bSYann Gautier uintptr_t stm32mp_ddrphyc_base(void)
1037ae58c6bSYann Gautier {
104ade9ce03SYann Gautier return DDRPHYC_BASE;
1057ae58c6bSYann Gautier }
1067ae58c6bSYann Gautier
stm32mp_pwr_base(void)1077ae58c6bSYann Gautier uintptr_t stm32mp_pwr_base(void)
1087ae58c6bSYann Gautier {
109ade9ce03SYann Gautier return PWR_BASE;
1107ae58c6bSYann Gautier }
1117ae58c6bSYann Gautier
stm32mp_rcc_base(void)1127ae58c6bSYann Gautier uintptr_t stm32mp_rcc_base(void)
1137ae58c6bSYann Gautier {
114ade9ce03SYann Gautier return RCC_BASE;
1157ae58c6bSYann Gautier }
1167ae58c6bSYann Gautier
stm32mp_lock_available(void)117e463d3f4SYann Gautier bool stm32mp_lock_available(void)
118e463d3f4SYann Gautier {
119e463d3f4SYann Gautier const uint32_t c_m_bits = SCTLR_M_BIT | SCTLR_C_BIT;
120e463d3f4SYann Gautier
121e463d3f4SYann Gautier /* The spinlocks are used only when MMU and data cache are enabled */
122dad71816SYann Gautier #ifdef __aarch64__
123dad71816SYann Gautier return (read_sctlr_el3() & c_m_bits) == c_m_bits;
124dad71816SYann Gautier #else
125e463d3f4SYann Gautier return (read_sctlr() & c_m_bits) == c_m_bits;
126dad71816SYann Gautier #endif
127e463d3f4SYann Gautier }
128e463d3f4SYann Gautier
stm32mp_map_ddr_non_cacheable(void)12984686ba3SYann Gautier int stm32mp_map_ddr_non_cacheable(void)
13084686ba3SYann Gautier {
13184686ba3SYann Gautier return mmap_add_dynamic_region(STM32MP_DDR_BASE, STM32MP_DDR_BASE,
13284686ba3SYann Gautier STM32MP_DDR_MAX_SIZE,
133c1ad41fbSYann Gautier MT_NON_CACHEABLE | MT_RW | MT_SECURE);
13484686ba3SYann Gautier }
13584686ba3SYann Gautier
stm32mp_unmap_ddr(void)13684686ba3SYann Gautier int stm32mp_unmap_ddr(void)
13784686ba3SYann Gautier {
13884686ba3SYann Gautier return mmap_remove_dynamic_region(STM32MP_DDR_BASE,
13984686ba3SYann Gautier STM32MP_DDR_MAX_SIZE);
14084686ba3SYann Gautier }
1413d201787SYann Gautier
stm32_get_otp_index(const char * otp_name,uint32_t * otp_idx,uint32_t * otp_len)142ae3ce8b2SLionel Debieve int stm32_get_otp_index(const char *otp_name, uint32_t *otp_idx,
143ae3ce8b2SLionel Debieve uint32_t *otp_len)
144ae3ce8b2SLionel Debieve {
145ae3ce8b2SLionel Debieve assert(otp_name != NULL);
146ae3ce8b2SLionel Debieve assert(otp_idx != NULL);
147ae3ce8b2SLionel Debieve
148ae3ce8b2SLionel Debieve return dt_find_otp_name(otp_name, otp_idx, otp_len);
149ae3ce8b2SLionel Debieve }
150ae3ce8b2SLionel Debieve
stm32_get_otp_value(const char * otp_name,uint32_t * otp_val)151ae3ce8b2SLionel Debieve int stm32_get_otp_value(const char *otp_name, uint32_t *otp_val)
152ae3ce8b2SLionel Debieve {
153ae3ce8b2SLionel Debieve uint32_t otp_idx;
154ae3ce8b2SLionel Debieve
155ae3ce8b2SLionel Debieve assert(otp_name != NULL);
156ae3ce8b2SLionel Debieve assert(otp_val != NULL);
157ae3ce8b2SLionel Debieve
158ae3ce8b2SLionel Debieve if (stm32_get_otp_index(otp_name, &otp_idx, NULL) != 0) {
159ae3ce8b2SLionel Debieve return -1;
160ae3ce8b2SLionel Debieve }
161ae3ce8b2SLionel Debieve
162ae3ce8b2SLionel Debieve if (stm32_get_otp_value_from_idx(otp_idx, otp_val) != 0) {
163ae3ce8b2SLionel Debieve ERROR("BSEC: %s Read Error\n", otp_name);
164ae3ce8b2SLionel Debieve return -1;
165ae3ce8b2SLionel Debieve }
166ae3ce8b2SLionel Debieve
167ae3ce8b2SLionel Debieve return 0;
168ae3ce8b2SLionel Debieve }
169ae3ce8b2SLionel Debieve
stm32_get_otp_value_from_idx(const uint32_t otp_idx,uint32_t * otp_val)170ae3ce8b2SLionel Debieve int stm32_get_otp_value_from_idx(const uint32_t otp_idx, uint32_t *otp_val)
171ae3ce8b2SLionel Debieve {
172ae3ce8b2SLionel Debieve uint32_t ret = BSEC_NOT_SUPPORTED;
173ae3ce8b2SLionel Debieve
174ae3ce8b2SLionel Debieve assert(otp_val != NULL);
175ae3ce8b2SLionel Debieve
176ae3ce8b2SLionel Debieve #if defined(IMAGE_BL2)
1773007c728SYann Gautier ret = stm32_otp_shadow_read(otp_val, otp_idx);
178189db948SYann Gautier #elif defined(IMAGE_BL31) || defined(IMAGE_BL32)
1793007c728SYann Gautier ret = stm32_otp_read(otp_val, otp_idx);
180ae3ce8b2SLionel Debieve #else
181ae3ce8b2SLionel Debieve #error "Not supported"
182ae3ce8b2SLionel Debieve #endif
183ae3ce8b2SLionel Debieve if (ret != BSEC_OK) {
184ae3ce8b2SLionel Debieve ERROR("BSEC: idx=%u Read Error\n", otp_idx);
185ae3ce8b2SLionel Debieve return -1;
186ae3ce8b2SLionel Debieve }
187ae3ce8b2SLionel Debieve
188ae3ce8b2SLionel Debieve return 0;
189ae3ce8b2SLionel Debieve }
190ae3ce8b2SLionel Debieve
stm32_get_uid_otp(uint32_t uid[])191*08252f9dSPatrick Delaunay int stm32_get_uid_otp(uint32_t uid[])
192*08252f9dSPatrick Delaunay {
193*08252f9dSPatrick Delaunay uint8_t i;
194*08252f9dSPatrick Delaunay uint32_t otp;
195*08252f9dSPatrick Delaunay uint32_t len;
196*08252f9dSPatrick Delaunay
197*08252f9dSPatrick Delaunay if (stm32_get_otp_index(UID_OTP, &otp, &len) != 0) {
198*08252f9dSPatrick Delaunay ERROR("BSEC: Get UID_OTP number Error\n");
199*08252f9dSPatrick Delaunay return -1;
200*08252f9dSPatrick Delaunay }
201*08252f9dSPatrick Delaunay
202*08252f9dSPatrick Delaunay if ((len / __WORD_BIT) != UID_WORD_NB) {
203*08252f9dSPatrick Delaunay ERROR("BSEC: Get UID_OTP length Error\n");
204*08252f9dSPatrick Delaunay return -1;
205*08252f9dSPatrick Delaunay }
206*08252f9dSPatrick Delaunay
207*08252f9dSPatrick Delaunay for (i = 0U; i < UID_WORD_NB; i++) {
208*08252f9dSPatrick Delaunay if (stm32_otp_shadow_read(&uid[i], i + otp) != BSEC_OK) {
209*08252f9dSPatrick Delaunay ERROR("BSEC: UID%u Error\n", i);
210*08252f9dSPatrick Delaunay return -1;
211*08252f9dSPatrick Delaunay }
212*08252f9dSPatrick Delaunay }
213*08252f9dSPatrick Delaunay
214*08252f9dSPatrick Delaunay return 0;
215*08252f9dSPatrick Delaunay }
216*08252f9dSPatrick Delaunay
217aafff043SYann Gautier #if defined(IMAGE_BL2)
reset_uart(uint32_t reset)21853612f72SYann Gautier static void reset_uart(uint32_t reset)
21953612f72SYann Gautier {
22053612f72SYann Gautier int ret;
22153612f72SYann Gautier
22253612f72SYann Gautier ret = stm32mp_reset_assert(reset, RESET_TIMEOUT_US_1MS);
22353612f72SYann Gautier if (ret != 0) {
22453612f72SYann Gautier panic();
22553612f72SYann Gautier }
22653612f72SYann Gautier
22753612f72SYann Gautier udelay(2);
22853612f72SYann Gautier
22953612f72SYann Gautier ret = stm32mp_reset_deassert(reset, RESET_TIMEOUT_US_1MS);
23053612f72SYann Gautier if (ret != 0) {
23153612f72SYann Gautier panic();
23253612f72SYann Gautier }
23353612f72SYann Gautier
23453612f72SYann Gautier mdelay(1);
23553612f72SYann Gautier }
236aafff043SYann Gautier #endif
23753612f72SYann Gautier
set_console(uintptr_t base,uint32_t clk_rate)238c768b2b2SYann Gautier static void set_console(uintptr_t base, uint32_t clk_rate)
239c768b2b2SYann Gautier {
240c768b2b2SYann Gautier unsigned int console_flags;
241c768b2b2SYann Gautier
242c768b2b2SYann Gautier if (console_stm32_register(base, clk_rate,
24399887cb9SYann Gautier (uint32_t)STM32MP_UART_BAUDRATE, &console) == 0) {
244c768b2b2SYann Gautier panic();
245c768b2b2SYann Gautier }
246c768b2b2SYann Gautier
247c768b2b2SYann Gautier console_flags = CONSOLE_FLAG_BOOT | CONSOLE_FLAG_CRASH |
248c768b2b2SYann Gautier CONSOLE_FLAG_TRANSLATE_CRLF;
249c768b2b2SYann Gautier #if !defined(IMAGE_BL2) && defined(DEBUG)
250c768b2b2SYann Gautier console_flags |= CONSOLE_FLAG_RUNTIME;
251c768b2b2SYann Gautier #endif
252c768b2b2SYann Gautier
253c768b2b2SYann Gautier console_set_scope(&console, console_flags);
254c768b2b2SYann Gautier }
255c768b2b2SYann Gautier
stm32mp_uart_console_setup(void)25653612f72SYann Gautier int stm32mp_uart_console_setup(void)
25753612f72SYann Gautier {
25853612f72SYann Gautier struct dt_node_info dt_uart_info;
2599e52d45fSYann Gautier uint32_t clk_rate = 0U;
26053612f72SYann Gautier int result;
261acf28c26SYann Gautier uint32_t boot_itf __unused;
262acf28c26SYann Gautier uint32_t boot_instance __unused;
26353612f72SYann Gautier
26453612f72SYann Gautier result = dt_get_stdout_uart_info(&dt_uart_info);
26553612f72SYann Gautier
26653612f72SYann Gautier if ((result <= 0) ||
2679e52d45fSYann Gautier (dt_uart_info.status == DT_DISABLED)) {
2689e52d45fSYann Gautier return -ENODEV;
2699e52d45fSYann Gautier }
2709e52d45fSYann Gautier
2719e52d45fSYann Gautier #if defined(IMAGE_BL2)
2729e52d45fSYann Gautier if ((dt_uart_info.clock < 0) ||
27353612f72SYann Gautier (dt_uart_info.reset < 0)) {
27453612f72SYann Gautier return -ENODEV;
27553612f72SYann Gautier }
2769e52d45fSYann Gautier #endif
27753612f72SYann Gautier
278acf28c26SYann Gautier #if STM32MP_UART_PROGRAMMER || !defined(IMAGE_BL2)
279acf28c26SYann Gautier stm32_get_boot_interface(&boot_itf, &boot_instance);
280acf28c26SYann Gautier
281acf28c26SYann Gautier if ((boot_itf == BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_UART) &&
282acf28c26SYann Gautier (get_uart_address(boot_instance) == dt_uart_info.base)) {
283acf28c26SYann Gautier return -EACCES;
284acf28c26SYann Gautier }
285acf28c26SYann Gautier #endif
286acf28c26SYann Gautier
287aafff043SYann Gautier #if defined(IMAGE_BL2)
28853612f72SYann Gautier if (dt_set_stdout_pinctrl() != 0) {
28953612f72SYann Gautier return -ENODEV;
29053612f72SYann Gautier }
29153612f72SYann Gautier
29233667d29SYann Gautier clk_enable((unsigned long)dt_uart_info.clock);
29353612f72SYann Gautier
29453612f72SYann Gautier reset_uart((uint32_t)dt_uart_info.reset);
29553612f72SYann Gautier
29633667d29SYann Gautier clk_rate = clk_get_rate((unsigned long)dt_uart_info.clock);
2979e52d45fSYann Gautier #endif
29853612f72SYann Gautier
299c768b2b2SYann Gautier set_console(dt_uart_info.base, clk_rate);
30053612f72SYann Gautier
30153612f72SYann Gautier return 0;
30253612f72SYann Gautier }
30353612f72SYann Gautier
30494cad75aSYann Gautier #if EARLY_CONSOLE
plat_setup_early_console(void)30594cad75aSYann Gautier void plat_setup_early_console(void)
306c768b2b2SYann Gautier {
3075223d880SYann Gautier #if defined(IMAGE_BL2) || STM32MP_RECONFIGURE_CONSOLE
308c768b2b2SYann Gautier plat_crash_console_init();
3095223d880SYann Gautier #endif
310c768b2b2SYann Gautier set_console(STM32MP_DEBUG_USART_BASE, STM32MP_DEBUG_USART_CLK_FRQ);
31100606df0SYann Gautier NOTICE("Early console setup\n");
312c768b2b2SYann Gautier }
31394cad75aSYann Gautier #endif /* EARLY_CONSOLE */
314c768b2b2SYann Gautier
3153d201787SYann Gautier /*****************************************************************************
3163d201787SYann Gautier * plat_is_smccc_feature_available() - This function checks whether SMCCC
3173d201787SYann Gautier * feature is availabile for platform.
3183d201787SYann Gautier * @fid: SMCCC function id
3193d201787SYann Gautier *
3203d201787SYann Gautier * Return SMC_ARCH_CALL_SUCCESS if SMCCC feature is available and
3213d201787SYann Gautier * SMC_ARCH_CALL_NOT_SUPPORTED otherwise.
3223d201787SYann Gautier *****************************************************************************/
plat_is_smccc_feature_available(u_register_t fid)3233d201787SYann Gautier int32_t plat_is_smccc_feature_available(u_register_t fid)
3243d201787SYann Gautier {
3253d201787SYann Gautier switch (fid) {
3263d201787SYann Gautier case SMCCC_ARCH_SOC_ID:
3273d201787SYann Gautier return SMC_ARCH_CALL_SUCCESS;
3283d201787SYann Gautier default:
3293d201787SYann Gautier return SMC_ARCH_CALL_NOT_SUPPORTED;
3303d201787SYann Gautier }
3313d201787SYann Gautier }
3323d201787SYann Gautier
3333d201787SYann Gautier /* Get SOC version */
plat_get_soc_version(void)3343d201787SYann Gautier int32_t plat_get_soc_version(void)
3353d201787SYann Gautier {
3363d201787SYann Gautier uint32_t chip_id = stm32mp_get_chip_dev_id();
3373d201787SYann Gautier uint32_t manfid = SOC_ID_SET_JEP_106(JEDEC_ST_BKID, JEDEC_ST_MFID);
3383d201787SYann Gautier
3393d201787SYann Gautier return (int32_t)(manfid | (chip_id & SOC_ID_IMPL_DEF_MASK));
3403d201787SYann Gautier }
3413d201787SYann Gautier
3423d201787SYann Gautier /* Get SOC revision */
plat_get_soc_revision(void)3433d201787SYann Gautier int32_t plat_get_soc_revision(void)
3443d201787SYann Gautier {
3453d201787SYann Gautier return (int32_t)(stm32mp_get_chip_version() & SOC_ID_REV_MASK);
3463d201787SYann Gautier }
347d8da13e5SYann Gautier
stm32_display_board_info(uint32_t board_id)348992dba08SYann Gautier void stm32_display_board_info(uint32_t board_id)
349992dba08SYann Gautier {
350992dba08SYann Gautier char rev[2];
351992dba08SYann Gautier
352992dba08SYann Gautier rev[0] = BOARD_ID2REV(board_id) - 1 + 'A';
353992dba08SYann Gautier rev[1] = '\0';
354992dba08SYann Gautier NOTICE("Board: MB%04x Var%u.%u Rev.%s-%02u\n",
355992dba08SYann Gautier BOARD_ID2NB(board_id),
356992dba08SYann Gautier BOARD_ID2VARCPN(board_id),
357992dba08SYann Gautier BOARD_ID2VARFG(board_id),
358992dba08SYann Gautier rev,
359992dba08SYann Gautier BOARD_ID2BOM(board_id));
360992dba08SYann Gautier }
361992dba08SYann Gautier
stm32_save_boot_info(boot_api_context_t * boot_context)362d8da13e5SYann Gautier void stm32_save_boot_info(boot_api_context_t *boot_context)
363d8da13e5SYann Gautier {
364d8da13e5SYann Gautier uint32_t auth_status;
365d8da13e5SYann Gautier
366d8da13e5SYann Gautier assert(boot_context->boot_interface_instance <= (BOOT_INST_MASK >> BOOT_INST_SHIFT));
367d8da13e5SYann Gautier assert(boot_context->boot_interface_selected <= (BOOT_ITF_MASK >> BOOT_ITF_SHIFT));
368d8da13e5SYann Gautier assert(boot_context->boot_partition_used_toboot <= (BOOT_PART_MASK >> BOOT_PART_SHIFT));
369d8da13e5SYann Gautier
370d8da13e5SYann Gautier switch (boot_context->auth_status) {
371d8da13e5SYann Gautier case BOOT_API_CTX_AUTH_NO:
372d8da13e5SYann Gautier auth_status = 0x0U;
373d8da13e5SYann Gautier break;
374d8da13e5SYann Gautier
375d8da13e5SYann Gautier case BOOT_API_CTX_AUTH_SUCCESS:
376d8da13e5SYann Gautier auth_status = 0x2U;
377d8da13e5SYann Gautier break;
378d8da13e5SYann Gautier
379d8da13e5SYann Gautier case BOOT_API_CTX_AUTH_FAILED:
380d8da13e5SYann Gautier default:
381d8da13e5SYann Gautier auth_status = 0x1U;
382d8da13e5SYann Gautier break;
383d8da13e5SYann Gautier }
384d8da13e5SYann Gautier
385d8da13e5SYann Gautier clk_enable(TAMP_BKP_REG_CLK);
386d8da13e5SYann Gautier
387d8da13e5SYann Gautier mmio_clrsetbits_32(stm32_get_bkpr_boot_mode_addr(),
388d8da13e5SYann Gautier BOOT_ITF_MASK | BOOT_INST_MASK | BOOT_PART_MASK | BOOT_AUTH_MASK,
389d8da13e5SYann Gautier (boot_context->boot_interface_instance << BOOT_INST_SHIFT) |
390d8da13e5SYann Gautier (boot_context->boot_interface_selected << BOOT_ITF_SHIFT) |
391d8da13e5SYann Gautier (boot_context->boot_partition_used_toboot << BOOT_PART_SHIFT) |
392d8da13e5SYann Gautier (auth_status << BOOT_AUTH_SHIFT));
393d8da13e5SYann Gautier
394d8da13e5SYann Gautier clk_disable(TAMP_BKP_REG_CLK);
395d8da13e5SYann Gautier }
396d8da13e5SYann Gautier
stm32_get_boot_interface(uint32_t * interface,uint32_t * instance)397d8da13e5SYann Gautier void stm32_get_boot_interface(uint32_t *interface, uint32_t *instance)
398d8da13e5SYann Gautier {
399d8da13e5SYann Gautier static uint32_t itf;
400d8da13e5SYann Gautier
401d8da13e5SYann Gautier if (itf == 0U) {
402d8da13e5SYann Gautier clk_enable(TAMP_BKP_REG_CLK);
403d8da13e5SYann Gautier
404d8da13e5SYann Gautier itf = mmio_read_32(stm32_get_bkpr_boot_mode_addr()) &
405d8da13e5SYann Gautier (BOOT_ITF_MASK | BOOT_INST_MASK);
406d8da13e5SYann Gautier
407d8da13e5SYann Gautier clk_disable(TAMP_BKP_REG_CLK);
408d8da13e5SYann Gautier }
409d8da13e5SYann Gautier
410d8da13e5SYann Gautier *interface = (itf & BOOT_ITF_MASK) >> BOOT_ITF_SHIFT;
411d8da13e5SYann Gautier *instance = (itf & BOOT_INST_MASK) >> BOOT_INST_SHIFT;
412d8da13e5SYann Gautier }
413b91c7f5eSYann Gautier
414b91c7f5eSYann Gautier #if PSA_FWU_SUPPORT
stm32_fwu_set_boot_idx(void)415b91c7f5eSYann Gautier void stm32_fwu_set_boot_idx(void)
416b91c7f5eSYann Gautier {
417b91c7f5eSYann Gautier clk_enable(TAMP_BKP_REG_CLK);
418b91c7f5eSYann Gautier mmio_clrsetbits_32(stm32_get_bkpr_fwu_info_addr(),
419b91c7f5eSYann Gautier FWU_INFO_IDX_MSK,
420b91c7f5eSYann Gautier (plat_fwu_get_boot_idx() << FWU_INFO_IDX_OFF) &
421b91c7f5eSYann Gautier FWU_INFO_IDX_MSK);
422b91c7f5eSYann Gautier clk_disable(TAMP_BKP_REG_CLK);
423b91c7f5eSYann Gautier }
424b91c7f5eSYann Gautier
stm32_get_and_dec_fwu_trial_boot_cnt(void)425b91c7f5eSYann Gautier uint32_t stm32_get_and_dec_fwu_trial_boot_cnt(void)
426b91c7f5eSYann Gautier {
427b91c7f5eSYann Gautier uintptr_t bkpr_fwu_cnt = stm32_get_bkpr_fwu_info_addr();
428b91c7f5eSYann Gautier uint32_t try_cnt;
429b91c7f5eSYann Gautier
430b91c7f5eSYann Gautier clk_enable(TAMP_BKP_REG_CLK);
431b91c7f5eSYann Gautier try_cnt = (mmio_read_32(bkpr_fwu_cnt) & FWU_INFO_CNT_MSK) >> FWU_INFO_CNT_OFF;
432b91c7f5eSYann Gautier
433b91c7f5eSYann Gautier assert(try_cnt <= FWU_MAX_TRIAL_REBOOT);
434b91c7f5eSYann Gautier
435b91c7f5eSYann Gautier if (try_cnt != 0U) {
436b91c7f5eSYann Gautier mmio_clrsetbits_32(bkpr_fwu_cnt, FWU_INFO_CNT_MSK,
437b91c7f5eSYann Gautier (try_cnt - 1U) << FWU_INFO_CNT_OFF);
438b91c7f5eSYann Gautier }
439b91c7f5eSYann Gautier clk_disable(TAMP_BKP_REG_CLK);
440b91c7f5eSYann Gautier
441b91c7f5eSYann Gautier return try_cnt;
442b91c7f5eSYann Gautier }
443b91c7f5eSYann Gautier
stm32_set_max_fwu_trial_boot_cnt(void)444b91c7f5eSYann Gautier void stm32_set_max_fwu_trial_boot_cnt(void)
445b91c7f5eSYann Gautier {
446b91c7f5eSYann Gautier uintptr_t bkpr_fwu_cnt = stm32_get_bkpr_fwu_info_addr();
447b91c7f5eSYann Gautier
448b91c7f5eSYann Gautier clk_enable(TAMP_BKP_REG_CLK);
449b91c7f5eSYann Gautier mmio_clrsetbits_32(bkpr_fwu_cnt, FWU_INFO_CNT_MSK,
450b91c7f5eSYann Gautier (FWU_MAX_TRIAL_REBOOT << FWU_INFO_CNT_OFF) & FWU_INFO_CNT_MSK);
451b91c7f5eSYann Gautier clk_disable(TAMP_BKP_REG_CLK);
452b91c7f5eSYann Gautier }
453b91c7f5eSYann Gautier
stm32_clear_fwu_trial_boot_cnt(void)454b91c7f5eSYann Gautier void stm32_clear_fwu_trial_boot_cnt(void)
455b91c7f5eSYann Gautier {
456b91c7f5eSYann Gautier uintptr_t bkpr_fwu_cnt = stm32_get_bkpr_fwu_info_addr();
457b91c7f5eSYann Gautier
458b91c7f5eSYann Gautier clk_enable(TAMP_BKP_REG_CLK);
459b91c7f5eSYann Gautier mmio_clrbits_32(bkpr_fwu_cnt, FWU_INFO_CNT_MSK);
460b91c7f5eSYann Gautier clk_disable(TAMP_BKP_REG_CLK);
461b91c7f5eSYann Gautier }
462b91c7f5eSYann Gautier #endif /* PSA_FWU_SUPPORT */
463