From 60a0dde91bd03f4011c1d52d4d3aea8166e939a0 Mon Sep 17 00:00:00 2001 From: Igor Opaniuk Date: Thu, 3 Jun 2021 15:00:26 +0300 Subject: [PATCH] feat(plat/imx8m): add system_reset2 implementation Add imx_system_reset2 which extends existing SYSTEM_RESET. It provides architectural reset definitions and vendor-specific resets. By default warm reset is triggered. Also refactor existing implementation of wdog reset, add details about each flag used. Change-Id: Ia7348c32c385f1c61f8085776e81dd1e38ddda5c Signed-off-by: Igor Opaniuk --- plat/imx/imx8m/imx8m_psci_common.c | 63 +++++++++++++++++++++++++---- plat/imx/imx8m/imx8mm/imx8mm_psci.c | 1 + plat/imx/imx8m/imx8mq/imx8mq_psci.c | 1 + plat/imx/imx8m/include/imx8m_psci.h | 1 + 4 files changed, 58 insertions(+), 8 deletions(-) diff --git a/plat/imx/imx8m/imx8m_psci_common.c b/plat/imx/imx8m/imx8m_psci_common.c index dbb772dc1..9dfd311d1 100644 --- a/plat/imx/imx8m/imx8m_psci_common.c +++ b/plat/imx/imx8m/imx8m_psci_common.c @@ -152,19 +152,45 @@ void imx_get_sys_suspend_power_state(psci_power_state_t *req_state) req_state->pwr_domain_state[i] = PLAT_STOP_OFF_STATE; } -void __dead2 imx_system_reset(void) +static void __dead2 imx_wdog_restart(bool external_reset) { uintptr_t wdog_base = IMX_WDOG_BASE; unsigned int val; - /* WDOG_B reset */ val = mmio_read_16(wdog_base); -#ifdef IMX_WDOG_B_RESET - val = (val & 0x00FF) | WDOG_WCR_WDZST | WDOG_WCR_WDE | - WDOG_WCR_WDT | WDOG_WCR_SRS; -#else - val = (val & 0x00FF) | WDOG_WCR_WDZST | WDOG_WCR_SRS; -#endif + /* + * Common watchdog init flags, for additional details check + * 6.6.4.1 Watchdog Control Register (WDOGx_WCR) + * + * Initial bit selection: + * WDOG_WCR_WDE - Enable the watchdog. + * + * 0x000E mask is used to keep previous values (that could be set + * in SPL) of WDBG and WDE/WDT (both are write-one once-only bits). + */ + val = (val & 0x000E) | WDOG_WCR_WDE; + if (external_reset) { + /* + * To assert WDOG_B (external reset) we have + * to set WDA bit 0 (already set in previous step). + * SRS bits are required to be set to 1 (no effect on the + * system). + */ + val |= WDOG_WCR_SRS; + } else { + /* + * To assert Software Reset Signal (internal reset) we have + * to set SRS bit to 0 (already set in previous step). + * SRE bit is required to be set to 1 when used in + * conjunction with the Software Reset Signal before + * SRS asserton, otherwise SRS bit will just automatically + * reset to 1. + * + * Also we set WDA to 1 (no effect on system). + */ + val |= WDOG_WCR_SRE | WDOG_WCR_WDA; + } + mmio_write_16(wdog_base, val); mmio_write_16(wdog_base + WDOG_WSR, 0x5555); @@ -173,6 +199,27 @@ void __dead2 imx_system_reset(void) ; } +void __dead2 imx_system_reset(void) +{ +#ifdef IMX_WDOG_B_RESET + imx_wdog_restart(true); +#else + imx_wdog_restart(false); +#endif +} + +int imx_system_reset2(int is_vendor, int reset_type, u_register_t cookie) +{ + imx_wdog_restart(false); + + /* + * imx_wdog_restart cannot return (as it's a __dead function), + * however imx_system_reset2 has to return some value according + * to PSCI v1.1 spec. + */ + return 0; +} + void __dead2 imx_system_off(void) { mmio_write_32(IMX_SNVS_BASE + SNVS_LPCR, SNVS_LPCR_SRTC_ENV | diff --git a/plat/imx/imx8m/imx8mm/imx8mm_psci.c b/plat/imx/imx8m/imx8mm/imx8mm_psci.c index e558724e8..815d3a2a5 100644 --- a/plat/imx/imx8m/imx8mm/imx8mm_psci.c +++ b/plat/imx/imx8m/imx8mm/imx8mm_psci.c @@ -28,6 +28,7 @@ static const plat_psci_ops_t imx_plat_psci_ops = { .pwr_domain_pwr_down_wfi = imx_pwr_domain_pwr_down_wfi, .get_sys_suspend_power_state = imx_get_sys_suspend_power_state, .system_reset = imx_system_reset, + .system_reset2 = imx_system_reset2, .system_off = imx_system_off, }; diff --git a/plat/imx/imx8m/imx8mq/imx8mq_psci.c b/plat/imx/imx8m/imx8mq/imx8mq_psci.c index 04e191ff8..662017d6f 100644 --- a/plat/imx/imx8m/imx8mq/imx8mq_psci.c +++ b/plat/imx/imx8m/imx8mq/imx8mq_psci.c @@ -117,6 +117,7 @@ static const plat_psci_ops_t imx_plat_psci_ops = { .pwr_domain_pwr_down_wfi = imx_pwr_domain_pwr_down_wfi, .get_sys_suspend_power_state = imx_get_sys_suspend_power_state, .system_reset = imx_system_reset, + .system_reset2 = imx_system_reset2, .system_off = imx_system_off, }; diff --git a/plat/imx/imx8m/include/imx8m_psci.h b/plat/imx/imx8m/include/imx8m_psci.h index c33d25e82..7d14d1120 100644 --- a/plat/imx/imx8m/include/imx8m_psci.h +++ b/plat/imx/imx8m/include/imx8m_psci.h @@ -19,5 +19,6 @@ void imx_cpu_standby(plat_local_state_t cpu_state); void imx_domain_suspend(const psci_power_state_t *target_state); void imx_domain_suspend_finish(const psci_power_state_t *target_state); void __dead2 imx_pwr_domain_pwr_down_wfi(const psci_power_state_t *target_state); +int imx_system_reset2(int is_vendor, int reset_type, u_register_t cookie); #endif /* IMX8M_PSCI_H */