13ef177b4SGabriel Fernandez // SPDX-License-Identifier: BSD-2-Clause
23ef177b4SGabriel Fernandez /*
33ef177b4SGabriel Fernandez * Copyright (c) 2021-2022, Linaro Limited
43ef177b4SGabriel Fernandez * Copyright (c) 2018-2024, STMicroelectronics
53ef177b4SGabriel Fernandez */
63ef177b4SGabriel Fernandez
73ef177b4SGabriel Fernandez #include <arm.h>
83ef177b4SGabriel Fernandez #include <drivers/rstctrl.h>
93ef177b4SGabriel Fernandez #include <drivers/stm32mp1_rcc.h>
103ef177b4SGabriel Fernandez #include <drivers/stm32mp_dt_bindings.h>
113ef177b4SGabriel Fernandez #include <io.h>
123ef177b4SGabriel Fernandez #include <keep.h>
133ef177b4SGabriel Fernandez #include <kernel/dt.h>
143ef177b4SGabriel Fernandez #include <kernel/dt_driver.h>
153ef177b4SGabriel Fernandez #include <stm32_util.h>
163ef177b4SGabriel Fernandez
173ef177b4SGabriel Fernandez #include "stm32_rstctrl.h"
183ef177b4SGabriel Fernandez
193ef177b4SGabriel Fernandez #define RESET_ID_MASK GENMASK_32(31, 5)
203ef177b4SGabriel Fernandez #define RESET_ID_SHIFT U(5)
213ef177b4SGabriel Fernandez #define RESET_BIT_POS_MASK GENMASK_32(4, 0)
223ef177b4SGabriel Fernandez #define RESET_OFFSET_MAX U(1024)
233ef177b4SGabriel Fernandez
reset_id2reg_offset(unsigned int id)243ef177b4SGabriel Fernandez static size_t reset_id2reg_offset(unsigned int id)
253ef177b4SGabriel Fernandez {
263ef177b4SGabriel Fernandez size_t offset = (id & RESET_ID_MASK) >> RESET_ID_SHIFT;
273ef177b4SGabriel Fernandez
283ef177b4SGabriel Fernandez assert(offset < RESET_OFFSET_MAX);
293ef177b4SGabriel Fernandez return offset * sizeof(uint32_t);
303ef177b4SGabriel Fernandez }
313ef177b4SGabriel Fernandez
reset_id2reg_bit_pos(unsigned int reset_id)323ef177b4SGabriel Fernandez static uint32_t reset_id2reg_bit_pos(unsigned int reset_id)
333ef177b4SGabriel Fernandez {
343ef177b4SGabriel Fernandez uint32_t pos = reset_id & RESET_BIT_POS_MASK;
353ef177b4SGabriel Fernandez
363ef177b4SGabriel Fernandez assert(pos < 32);
373ef177b4SGabriel Fernandez return pos;
383ef177b4SGabriel Fernandez }
393ef177b4SGabriel Fernandez
reset_assert(struct rstctrl * rstctrl,unsigned int to_us)403ef177b4SGabriel Fernandez static TEE_Result reset_assert(struct rstctrl *rstctrl, unsigned int to_us)
413ef177b4SGabriel Fernandez {
423ef177b4SGabriel Fernandez unsigned int id = to_stm32_rstline(rstctrl)->id;
433ef177b4SGabriel Fernandez vaddr_t rcc_base = stm32_rcc_base();
443ef177b4SGabriel Fernandez uint32_t bit_mask = 0;
453ef177b4SGabriel Fernandez size_t offset = 0;
463ef177b4SGabriel Fernandez
473ef177b4SGabriel Fernandez #ifdef CFG_STM32MP15
483ef177b4SGabriel Fernandez switch (id) {
493ef177b4SGabriel Fernandez case MCU_HOLD_BOOT_R:
503ef177b4SGabriel Fernandez /*
513ef177b4SGabriel Fernandez * The RCC_MP_GCR is a read/write register.
523ef177b4SGabriel Fernandez * Assert the MCU HOLD_BOOT means clear the BOOT_MCU bit
533ef177b4SGabriel Fernandez */
543ef177b4SGabriel Fernandez io_clrbits32(rcc_base + RCC_MP_GCR, RCC_MP_GCR_BOOT_MCU);
553ef177b4SGabriel Fernandez
563ef177b4SGabriel Fernandez return TEE_SUCCESS;
573ef177b4SGabriel Fernandez case MCU_R:
583ef177b4SGabriel Fernandez /* MCU reset can only be written */
593ef177b4SGabriel Fernandez to_us = 0;
603ef177b4SGabriel Fernandez break;
613ef177b4SGabriel Fernandez default:
623ef177b4SGabriel Fernandez break;
633ef177b4SGabriel Fernandez }
643ef177b4SGabriel Fernandez #endif
653ef177b4SGabriel Fernandez
663ef177b4SGabriel Fernandez offset = reset_id2reg_offset(id);
673ef177b4SGabriel Fernandez bit_mask = BIT(reset_id2reg_bit_pos(id));
683ef177b4SGabriel Fernandez
693ef177b4SGabriel Fernandez io_write32(rcc_base + offset, bit_mask);
703ef177b4SGabriel Fernandez
713ef177b4SGabriel Fernandez if (to_us) {
723ef177b4SGabriel Fernandez uint32_t value = 0;
733ef177b4SGabriel Fernandez
743ef177b4SGabriel Fernandez if (IO_READ32_POLL_TIMEOUT(rcc_base + offset, value,
753ef177b4SGabriel Fernandez value & bit_mask, 0, to_us))
763ef177b4SGabriel Fernandez return TEE_ERROR_GENERIC;
773ef177b4SGabriel Fernandez } else {
783ef177b4SGabriel Fernandez /* Make sure the above write is performed */
793ef177b4SGabriel Fernandez dsb();
803ef177b4SGabriel Fernandez }
813ef177b4SGabriel Fernandez
823ef177b4SGabriel Fernandez return TEE_SUCCESS;
833ef177b4SGabriel Fernandez }
843ef177b4SGabriel Fernandez
reset_deassert(struct rstctrl * rstctrl,unsigned int to_us)853ef177b4SGabriel Fernandez static TEE_Result reset_deassert(struct rstctrl *rstctrl, unsigned int to_us)
863ef177b4SGabriel Fernandez {
873ef177b4SGabriel Fernandez unsigned int id = to_stm32_rstline(rstctrl)->id;
883ef177b4SGabriel Fernandez vaddr_t rcc_base = stm32_rcc_base();
893ef177b4SGabriel Fernandez uint32_t bit_mask = 0;
903ef177b4SGabriel Fernandez size_t offset = 0;
913ef177b4SGabriel Fernandez
923ef177b4SGabriel Fernandez #ifdef CFG_STM32MP15
933ef177b4SGabriel Fernandez switch (id) {
943ef177b4SGabriel Fernandez case MCU_HOLD_BOOT_R:
953ef177b4SGabriel Fernandez /*
963ef177b4SGabriel Fernandez * The RCC_MP_GCR is a read/write register.
973ef177b4SGabriel Fernandez * Deassert the MCU HOLD_BOOT means set the BOOT_MCU the bit
983ef177b4SGabriel Fernandez */
993ef177b4SGabriel Fernandez io_setbits32(rcc_base + RCC_MP_GCR, RCC_MP_GCR_BOOT_MCU);
1003ef177b4SGabriel Fernandez
1013ef177b4SGabriel Fernandez return TEE_SUCCESS;
1023ef177b4SGabriel Fernandez case MCU_R:
1033ef177b4SGabriel Fernandez /* MCU reset deasserts by its own */
1043ef177b4SGabriel Fernandez return TEE_SUCCESS;
1053ef177b4SGabriel Fernandez default:
1063ef177b4SGabriel Fernandez break;
1073ef177b4SGabriel Fernandez }
1083ef177b4SGabriel Fernandez #endif
1093ef177b4SGabriel Fernandez
1103ef177b4SGabriel Fernandez offset = reset_id2reg_offset(id) + RCC_MP_RSTCLRR_OFFSET;
1113ef177b4SGabriel Fernandez bit_mask = BIT(reset_id2reg_bit_pos(id));
1123ef177b4SGabriel Fernandez
1133ef177b4SGabriel Fernandez io_write32(rcc_base + offset, bit_mask);
1143ef177b4SGabriel Fernandez
1153ef177b4SGabriel Fernandez if (to_us) {
1163ef177b4SGabriel Fernandez uint32_t value = 0;
1173ef177b4SGabriel Fernandez
1183ef177b4SGabriel Fernandez if (IO_READ32_POLL_TIMEOUT(rcc_base + offset, value,
1193ef177b4SGabriel Fernandez !(value & bit_mask), 0, to_us))
1203ef177b4SGabriel Fernandez return TEE_ERROR_GENERIC;
1213ef177b4SGabriel Fernandez } else {
1223ef177b4SGabriel Fernandez /* Make sure the above write is performed */
1233ef177b4SGabriel Fernandez dsb();
1243ef177b4SGabriel Fernandez }
1253ef177b4SGabriel Fernandez
1263ef177b4SGabriel Fernandez return TEE_SUCCESS;
1273ef177b4SGabriel Fernandez }
1283ef177b4SGabriel Fernandez
129b0323341SGabriel Fernandez static const struct rstctrl_ops stm32_rstctrl_ops = {
1303ef177b4SGabriel Fernandez .assert_level = reset_assert,
1313ef177b4SGabriel Fernandez .deassert_level = reset_deassert,
1323ef177b4SGabriel Fernandez };
1333ef177b4SGabriel Fernandez DECLARE_KEEP_PAGER(stm32_rstctrl_ops);
1343ef177b4SGabriel Fernandez
stm32_reset_get_ops(unsigned int id __unused)135b0323341SGabriel Fernandez static const struct rstctrl_ops *stm32_reset_get_ops(unsigned int id __unused)
1363ef177b4SGabriel Fernandez {
1373ef177b4SGabriel Fernandez return &stm32_rstctrl_ops;
1383ef177b4SGabriel Fernandez }
1393ef177b4SGabriel Fernandez
1403ef177b4SGabriel Fernandez static const struct stm32_reset_data stm32mp1_reset_data = {
1413ef177b4SGabriel Fernandez .get_rstctrl_ops = stm32_reset_get_ops
1423ef177b4SGabriel Fernandez };
143*82d8cbbdSEtienne Carriere DECLARE_KEEP_PAGER(stm32mp1_reset_data);
1443ef177b4SGabriel Fernandez
1453ef177b4SGabriel Fernandez static const struct dt_device_match stm32_rstctrl_match_table[] = {
1463ef177b4SGabriel Fernandez {
1473ef177b4SGabriel Fernandez .compatible = "st,stm32mp1-rcc",
1483ef177b4SGabriel Fernandez .compat_data = &stm32mp1_reset_data,
1493ef177b4SGabriel Fernandez },
1503ef177b4SGabriel Fernandez {
1513ef177b4SGabriel Fernandez .compatible = "st,stm32mp1-rcc-secure",
1523ef177b4SGabriel Fernandez .compat_data = &stm32mp1_reset_data,
1533ef177b4SGabriel Fernandez },
1543ef177b4SGabriel Fernandez {
1553ef177b4SGabriel Fernandez .compatible = "st,stm32mp13-rcc",
1563ef177b4SGabriel Fernandez .compat_data = &stm32mp1_reset_data,
1573ef177b4SGabriel Fernandez },
1583ef177b4SGabriel Fernandez { }
1593ef177b4SGabriel Fernandez };
1603ef177b4SGabriel Fernandez
1613ef177b4SGabriel Fernandez DEFINE_DT_DRIVER(stm32_rstctrl_dt_driver) = {
1623ef177b4SGabriel Fernandez .name = "stm32_rstctrl",
1633ef177b4SGabriel Fernandez .type = DT_DRIVER_RSTCTRL,
1643ef177b4SGabriel Fernandez .match_table = stm32_rstctrl_match_table,
1653ef177b4SGabriel Fernandez .probe = stm32_rstctrl_provider_probe,
1663ef177b4SGabriel Fernandez };
167