Browse Source

mt8173: Add support for new watchdog SMC

This patch adds support for a new SMC that can be used to control the
watchdog. This allows for a cleaner separation of responsibilities where
all watchdog operations have to go through Trusted Firmware and we could
no longer have kernel and firmware poking concurrently at the same
register block.

Signed-off-by: Julius Werner <jwerner@chromium.org>
Signed-off-by: Evan Benn <evanbenn@chromium.org>
Change-Id: I4844a3559d5c956a53a74a61dd5bc2956f0cce7b
pull/1938/head
Julius Werner 7 years ago
committed by Evan Benn
parent
commit
e9cf1bcc45
  1. 115
      plat/mediatek/mt8173/drivers/wdt/wdt.c
  2. 20
      plat/mediatek/mt8173/drivers/wdt/wdt.h
  3. 12
      plat/mediatek/mt8173/include/mt8173_def.h
  4. 3
      plat/mediatek/mt8173/include/plat_sip_calls.h
  5. 9
      plat/mediatek/mt8173/plat_pm.c
  6. 4
      plat/mediatek/mt8173/plat_sip_calls.c
  7. 2
      plat/mediatek/mt8173/platform.mk

115
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);
}
}

20
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 */

12
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

3
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 */

9
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");

4
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;

2
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 \

Loading…
Cancel
Save