diff options
author | Sandrine Bailleux <sandrine.bailleux@arm.com> | 2020-02-28 10:48:21 +0000 |
---|---|---|
committer | TrustedFirmware Code Review <review@review.trustedfirmware.org> | 2020-02-28 10:48:21 +0000 |
commit | 1e81e9a4c7d96df1fc0edafb5b332aab0b61932d (patch) | |
tree | f1f73c9bf9a85de20b229c47fec9b6c272ba70f4 /plat | |
parent | 8f74c884a7bc8ed3e9e4684c2d81b6693b5a41c3 (diff) | |
parent | e9cf1bcc4544f966c979f875f539556cb70f1367 (diff) | |
download | platform_external_arm-trusted-firmware-1e81e9a4c7d96df1fc0edafb5b332aab0b61932d.tar.gz platform_external_arm-trusted-firmware-1e81e9a4c7d96df1fc0edafb5b332aab0b61932d.tar.bz2 platform_external_arm-trusted-firmware-1e81e9a4c7d96df1fc0edafb5b332aab0b61932d.zip |
Merge "mt8173: Add support for new watchdog SMC" into integration
Diffstat (limited to 'plat')
-rw-r--r-- | plat/mediatek/mt8173/drivers/wdt/wdt.c | 115 | ||||
-rw-r--r-- | plat/mediatek/mt8173/drivers/wdt/wdt.h | 20 | ||||
-rw-r--r-- | plat/mediatek/mt8173/include/mt8173_def.h | 12 | ||||
-rw-r--r-- | plat/mediatek/mt8173/include/plat_sip_calls.h | 3 | ||||
-rw-r--r-- | plat/mediatek/mt8173/plat_pm.c | 9 | ||||
-rw-r--r-- | plat/mediatek/mt8173/plat_sip_calls.c | 4 | ||||
-rw-r--r-- | plat/mediatek/mt8173/platform.mk | 2 |
7 files changed, 147 insertions, 18 deletions
diff --git a/plat/mediatek/mt8173/drivers/wdt/wdt.c b/plat/mediatek/mt8173/drivers/wdt/wdt.c new file mode 100644 index 000000000..40f57eed2 --- /dev/null +++ b/plat/mediatek/mt8173/drivers/wdt/wdt.c @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2020, Google LLC. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <common/debug.h> +#include <lib/mmio.h> +#include <mt8173_def.h> +#include <plat_sip_calls.h> +#include <lib/psci/psci.h> +#include <smccc_helpers.h> +#include <wdt.h> + +#define WDT_BASE (RGU_BASE + 0) +#define WDT_MODE (WDT_BASE + 0x00) +#define WDT_LENGTH (WDT_BASE + 0x04) +#define WDT_RESTART (WDT_BASE + 0x08) +#define WDT_SWRST (WDT_BASE + 0x14) + +#define WDT_MODE_DUAL_MODE 0x40 +#define WDT_MODE_IRQ 0x8 +#define WDT_MODE_KEY 0x22000000 +#define WDT_MODE_EXTEN 0x4 +#define WDT_MODE_EN 0x1 +#define WDT_LENGTH_KEY 0x8 +#define WDT_RESTART_KEY 0x1971 +#define WDT_SWRST_KEY 0x1209 + + +#define WDT_MIN_TIMEOUT 1 +#define WDT_MAX_TIMEOUT 31 + +enum smcwd_call { + SMCWD_INFO = 0, + SMCWD_SET_TIMEOUT = 1, + SMCWD_ENABLE = 2, + SMCWD_PET = 3, +}; + +static int wdt_enabled_before_suspend; + +/* + * We expect the WDT registers to be correctly initialized by BL2 firmware + * (which may be board specific), so we do not reinitialize them here. + */ + +void wdt_trigger_reset(void) +{ + mmio_write_32(WDT_SWRST, WDT_SWRST_KEY); +} + +void wdt_pet(void) +{ + mmio_write_32(WDT_RESTART, WDT_RESTART_KEY); +} + +int wdt_set_timeout(uint32_t timeout) +{ + /* One tick here equals 512 32KHz ticks. 512 / 32000 * 125 / 2 = 1 */ + uint32_t ticks = timeout * 125 / 2; + + if (timeout < WDT_MIN_TIMEOUT || timeout > WDT_MAX_TIMEOUT) + return PSCI_E_INVALID_PARAMS; + + mmio_write_32(WDT_LENGTH, ticks << 5 | WDT_LENGTH_KEY); + + return PSCI_E_SUCCESS; +} + +void wdt_set_enable(int enable) +{ + if (enable) + wdt_pet(); + mmio_clrsetbits_32(WDT_MODE, WDT_MODE_EN, + WDT_MODE_KEY | (enable ? WDT_MODE_EN : 0)); +} + +void wdt_suspend(void) +{ + wdt_enabled_before_suspend = mmio_read_32(WDT_MODE) & WDT_MODE_EN; + if (wdt_enabled_before_suspend) + wdt_set_enable(0); +} + +void wdt_resume(void) +{ + if (wdt_enabled_before_suspend) + wdt_set_enable(1); +} + +uint64_t wdt_smc_handler(uint32_t x1, + uint32_t x2, + void *handle) +{ + int ret; + + switch (x1) { + case SMCWD_INFO: + SMC_RET3(handle, PSCI_E_SUCCESS, + WDT_MIN_TIMEOUT, WDT_MAX_TIMEOUT); + case SMCWD_SET_TIMEOUT: + ret = wdt_set_timeout(x2); + SMC_RET1(handle, ret); + case SMCWD_ENABLE: + wdt_set_enable(x2 > 0); + SMC_RET1(handle, PSCI_E_SUCCESS); + case SMCWD_PET: + wdt_pet(); + SMC_RET1(handle, PSCI_E_SUCCESS); + default: + ERROR("Unimplemented SMCWD call (%d)\n", x1); + SMC_RET1(handle, PSCI_E_NOT_SUPPORTED); + } +} diff --git a/plat/mediatek/mt8173/drivers/wdt/wdt.h b/plat/mediatek/mt8173/drivers/wdt/wdt.h new file mode 100644 index 000000000..7262a5717 --- /dev/null +++ b/plat/mediatek/mt8173/drivers/wdt/wdt.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2020, Google LLC. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef WDT_H +#define WDT_H + +#include "stdint.h" + +void wdt_pet(void); +void wdt_resume(void); +void wdt_set_enable(int enable); +int wdt_set_timeout(uint32_t timeout); +uint64_t wdt_smc_handler(uint32_t x1, uint32_t x2, void *handle); +void wdt_suspend(void); +void wdt_trigger_reset(void); + +#endif /* WDT_H */ diff --git a/plat/mediatek/mt8173/include/mt8173_def.h b/plat/mediatek/mt8173/include/mt8173_def.h index 58962f03d..378b4da55 100644 --- a/plat/mediatek/mt8173/include/mt8173_def.h +++ b/plat/mediatek/mt8173/include/mt8173_def.h @@ -80,18 +80,6 @@ #define PLAT_MT_CCI_CLUSTER0_SL_IFACE_IX 4 #define PLAT_MT_CCI_CLUSTER1_SL_IFACE_IX 3 -/******************************************************************************* - * WDT related constants - ******************************************************************************/ -#define MTK_WDT_BASE (RGU_BASE + 0) -#define MTK_WDT_SWRST (MTK_WDT_BASE + 0x0014) - -#define MTK_WDT_MODE_DUAL_MODE 0x0040 -#define MTK_WDT_MODE_IRQ 0x0008 -#define MTK_WDT_MODE_KEY 0x22000000 -#define MTK_WDT_MODE_EXTEN 0x0004 -#define MTK_WDT_SWRST_KEY 0x1209 - /* FIQ platform related define */ #define MT_IRQ_SEC_SGI_0 8 #define MT_IRQ_SEC_SGI_1 9 diff --git a/plat/mediatek/mt8173/include/plat_sip_calls.h b/plat/mediatek/mt8173/include/plat_sip_calls.h index 88202cc55..ce9951a67 100644 --- a/plat/mediatek/mt8173/include/plat_sip_calls.h +++ b/plat/mediatek/mt8173/include/plat_sip_calls.h @@ -10,7 +10,7 @@ /******************************************************************************* * Plat SiP function constants ******************************************************************************/ -#define MTK_PLAT_SIP_NUM_CALLS 6 +#define MTK_PLAT_SIP_NUM_CALLS 7 #define MTK_SIP_PWR_ON_MTCMOS 0x82000402 #define MTK_SIP_PWR_OFF_MTCMOS 0x82000403 @@ -18,5 +18,6 @@ #define MTK_SIP_SET_HDCP_KEY_NUM 0x82000405 #define MTK_SIP_CLR_HDCP_KEY 0x82000406 #define MTK_SIP_SET_HDCP_KEY_EX 0x82000407 +#define MTK_SIP_SMC_WATCHDOG 0x82003D06 #endif /* PLAT_SIP_CALLS_H */ diff --git a/plat/mediatek/mt8173/plat_pm.c b/plat/mediatek/mt8173/plat_pm.c index 67f1c731b..e72a3434e 100644 --- a/plat/mediatek/mt8173/plat_pm.c +++ b/plat/mediatek/mt8173/plat_pm.c @@ -27,6 +27,7 @@ #include <spm_hotplug.h> #include <spm_mcdi.h> #include <spm_suspend.h> +#include <wdt.h> #define MTK_PWR_LVL0 0 #define MTK_PWR_LVL1 1 @@ -350,6 +351,7 @@ static void plat_power_domain_suspend(const psci_power_state_t *state) } if (MTK_SYSTEM_PWR_STATE(state) == MTK_LOCAL_STATE_OFF) { + wdt_suspend(); disable_scu(mpidr); generic_timer_backup(); spm_system_suspend(); @@ -409,6 +411,7 @@ static void plat_power_domain_suspend_finish(const psci_power_state_t *state) plat_arm_gic_init(); spm_system_suspend_finish(); enable_scu(mpidr); + wdt_resume(); } /* Perform the common cluster specific operations */ @@ -455,11 +458,7 @@ static void __dead2 plat_system_reset(void) /* Write the System Configuration Control Register */ INFO("MTK System Reset\n"); - mmio_clrsetbits_32(MTK_WDT_BASE, - (MTK_WDT_MODE_DUAL_MODE | MTK_WDT_MODE_IRQ), - MTK_WDT_MODE_KEY); - mmio_setbits_32(MTK_WDT_BASE, (MTK_WDT_MODE_KEY | MTK_WDT_MODE_EXTEN)); - mmio_setbits_32(MTK_WDT_SWRST, MTK_WDT_SWRST_KEY); + wdt_trigger_reset(); wfi(); ERROR("MTK System Reset: operation not handled.\n"); diff --git a/plat/mediatek/mt8173/plat_sip_calls.c b/plat/mediatek/mt8173/plat_sip_calls.c index 102feb22a..da9b91dd6 100644 --- a/plat/mediatek/mt8173/plat_sip_calls.c +++ b/plat/mediatek/mt8173/plat_sip_calls.c @@ -12,6 +12,7 @@ #include <mtcmos.h> #include <mtk_sip_svc.h> #include <plat_sip_calls.h> +#include <wdt.h> /* Authorized secure register list */ enum { @@ -102,6 +103,9 @@ uint64_t mediatek_plat_sip_handler(uint32_t smc_fid, ret = crypt_clear_hdcp_key(); SMC_RET1(handle, ret); + case MTK_SIP_SMC_WATCHDOG: + return wdt_smc_handler(x1, x2, handle); + default: ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid); break; diff --git a/plat/mediatek/mt8173/platform.mk b/plat/mediatek/mt8173/platform.mk index a66c49bb4..f62802cb9 100644 --- a/plat/mediatek/mt8173/platform.mk +++ b/plat/mediatek/mt8173/platform.mk @@ -15,6 +15,7 @@ PLAT_INCLUDES := -I${MTK_PLAT}/common/ \ -I${MTK_PLAT_SOC}/drivers/rtc/ \ -I${MTK_PLAT_SOC}/drivers/spm/ \ -I${MTK_PLAT_SOC}/drivers/timer/ \ + -I${MTK_PLAT_SOC}/drivers/wdt/ \ -I${MTK_PLAT_SOC}/include/ PLAT_BL_COMMON_SOURCES := lib/xlat_tables/xlat_tables_common.c \ @@ -50,6 +51,7 @@ BL31_SOURCES += common/desc_image_load.c \ ${MTK_PLAT_SOC}/drivers/spm/spm_mcdi.c \ ${MTK_PLAT_SOC}/drivers/spm/spm_suspend.c \ ${MTK_PLAT_SOC}/drivers/timer/mt_cpuxgpt.c \ + ${MTK_PLAT_SOC}/drivers/wdt/wdt.c \ ${MTK_PLAT_SOC}/plat_pm.c \ ${MTK_PLAT_SOC}/plat_sip_calls.c \ ${MTK_PLAT_SOC}/plat_topology.c \ |