GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)
This commit is contained in:
+51
@@ -0,0 +1,51 @@
|
||||
#
|
||||
# Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
# Conditional makefile variable assignment
|
||||
|
||||
# Options depend on BUILD_TYPE variable
|
||||
ifeq ($(BUILD_TYPE),release)
|
||||
MTK_DEBUGSYS_LOCK := 1
|
||||
MTK_GET_PERM_DIS := 1
|
||||
ERRATA_KLEIN_2218950 := 0
|
||||
ERRATA_KLEIN_2184257 := 0
|
||||
ERRATA_KLEIN_BOOKER := 0
|
||||
ERRATA_MTH_BOOKER := 0
|
||||
ERRATA_MTHELP_BOOKER := 0
|
||||
CRASH_REPORTING := 1
|
||||
CONFIG_MTK_BL31_RAMDUMP := 0
|
||||
endif
|
||||
|
||||
ifeq ($(BUILD_TYPE),debug)
|
||||
MTK_PTP3_PROC_DEBUG := 1
|
||||
MTK_SRAMRC_DEBUG := 1
|
||||
MTK_IOMMU_DEBUG := 1
|
||||
MTK_DCM_DEBUG := 1
|
||||
MTK_EMI_MPU_DEBUG := 1
|
||||
endif
|
||||
|
||||
ifeq (${SPD},none)
|
||||
SPD_NONE:=1
|
||||
$(eval $(call add_define,SPD_NONE))
|
||||
endif
|
||||
|
||||
# TEE OS config
|
||||
ifeq ($(SPD), tbase)
|
||||
CONFIG_TBASE := y
|
||||
endif
|
||||
|
||||
# MICROTRUST OS config
|
||||
ifeq ($(SPD), teeid)
|
||||
CONFIG_MICROTRUST_TEEI := y
|
||||
endif
|
||||
|
||||
ifeq (${CONFIG_ARCH_ARM_V8_2},y)
|
||||
ARCH_VERSION := armv8_2
|
||||
endif
|
||||
|
||||
ifeq (${CONFIG_ARCH_ARM_V9},y)
|
||||
ARCH_VERSION := armv9
|
||||
endif
|
||||
+142
@@ -0,0 +1,142 @@
|
||||
#
|
||||
# Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
# Get local directory path
|
||||
define GET_LOCAL_DIR
|
||||
$(patsubst %/,%,$(dir $(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))))
|
||||
endef
|
||||
|
||||
# Clear module source variable
|
||||
define CLEAR_LOCAL_SRCS
|
||||
$(eval $(1) :=)
|
||||
endef
|
||||
|
||||
define EXPAND_SUB_MAKEFILE
|
||||
include $(S)
|
||||
endef
|
||||
|
||||
# Expand sub rules.mk
|
||||
define INCLUDE_MAKEFILE
|
||||
$(eval MODULES_SUB_MAKEFILE := $(patsubst %,%/rules.mk,$(1)))
|
||||
$(foreach S,$(MODULES_SUB_MAKEFILE),$(eval $(EXPAND_SUB_MAKEFILE)))
|
||||
endef
|
||||
|
||||
# Determine option variable is defined or not then define it
|
||||
define add_defined_option
|
||||
ifdef $(1)
|
||||
ifeq ($(findstring $(value $(1)), $(uppercase_table)),)
|
||||
DEFINES += -D$(1)$(if $(value $(1)),=$(value $(1)),)
|
||||
else
|
||||
ifeq ($(strip $(value $(1))),y)
|
||||
DEFINES += -D$(1)$(if $(value $(1)),=1,)
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endef
|
||||
|
||||
define EXPAND_RULES_MAKEFILE
|
||||
LOCAL_SRCS-y :=
|
||||
MODULE :=
|
||||
SUB_RULES-y :=
|
||||
include $(S)
|
||||
endef
|
||||
|
||||
# INCLUDE_MODULES macro expand included modules rules.mk
|
||||
# Arguments:
|
||||
# $(1) = MODULES variables
|
||||
define INCLUDE_MODULES
|
||||
$(eval MODULES_TEMP := $(1))
|
||||
$(eval MODULES_MAKEFILE := $(patsubst %,%/rules.mk,$(MODULES_TEMP)))
|
||||
$(foreach S,$(MODULES_MAKEFILE),$(eval $(EXPAND_RULES_MAKEFILE)))
|
||||
endef
|
||||
|
||||
# MAKE_LOCALS expand module source file variable to BL${BL}_SOURCES
|
||||
# Arguments:
|
||||
# $(1) = source file
|
||||
# $(2) = BL stage (1, 2, 2u, 31, 32)
|
||||
define MAKE_LOCALS
|
||||
$(eval $(call uppercase,$(2))_SOURCES += $(1))
|
||||
endef
|
||||
|
||||
# MAKE_LINKERFILE change linker script source file name to
|
||||
# target linker script
|
||||
# $(1) = linker script source file
|
||||
# $(2) = BL stage
|
||||
define MAKE_LINKERFILE
|
||||
$(eval EXTRA_GENERATED_LINKER_SCRIPT += $(BUILD_PLAT)/$(2)/$(patsubst %.ld.S,%.ld,$(notdir $(1))))
|
||||
endef
|
||||
|
||||
# MAKE_LINKERFILE_ITER call MAKE_LINKERFILE iteratively
|
||||
# $(1) = linker script source file
|
||||
# $(2) = BL stage
|
||||
define MAKE_LINKERFILE_ITER
|
||||
$(eval $(foreach link_src,$(1),$(call MAKE_LINKERFILE,$(link_src),$(2))))
|
||||
endef
|
||||
|
||||
# MAKE_LD_ITER generate the linker scripts using the C preprocessor iteratively
|
||||
# $(1) = output linker script
|
||||
# $(2) = input template
|
||||
# $(3) = BL stage (1, 2, 2u, 31, 32)
|
||||
define MAKE_LD_ITER
|
||||
$(eval index_list=$(shell seq $(words $(1))))
|
||||
$(eval $(foreach i, $(index_list), \
|
||||
$(call MAKE_LD,$(word $(i), $(1)), $(word $(i), $(2)),$(3))))
|
||||
endef
|
||||
|
||||
# MAKE_MODULE reference MAKE_OBJS.
|
||||
# Create module folder under out/bl$(BL)/$(module)
|
||||
# Arguments:
|
||||
# $(1) = module name
|
||||
# $(2) = source file
|
||||
# $(3) = BL stage
|
||||
define MAKE_MODULE
|
||||
$(eval MODULE := $(strip $(1)))
|
||||
$(eval BUILD_DIR := ${BUILD_PLAT}/${3})
|
||||
$(eval SOURCES := $(2))
|
||||
$(eval OBJS_TEMP := $(addprefix $(BUILD_DIR)/$(MODULE)/,$(call SOURCES_TO_OBJS,$(SOURCES))))
|
||||
$(eval MODULE_OBJS += $(OBJS_TEMP))
|
||||
# We use sort only to get a list of unique object directory names.
|
||||
# ordering is not relevant but sort removes duplicates.
|
||||
$(eval TEMP_OBJ_DIRS := $(sort $(dir ${OBJS_TEMP} ${LINKERFILE})))
|
||||
# The $(dir ) function leaves a trailing / on the directory names
|
||||
# Rip off the / to match directory names with make rule targets.
|
||||
$(eval OBJ_DIRS := $(patsubst %/,%,$(TEMP_OBJ_DIRS)))
|
||||
|
||||
$(eval $(foreach objd,${OBJ_DIRS},$(call MAKE_PREREQ_DIR,${objd},${BUILD_DIR})))
|
||||
${3}_dirs: | ${OBJ_DIRS}
|
||||
|
||||
$(eval $(call MAKE_OBJS,$(BUILD_DIR)/$(MODULE),$(SOURCES),${3}))
|
||||
|
||||
libraries: $(OBJS_TEMP)
|
||||
endef
|
||||
|
||||
# Include MTK configuration files
|
||||
|
||||
# MTK makefile variables
|
||||
ifeq (${COREBOOT},1)
|
||||
MTK_COMMON_CFG := $(MTK_PLAT)/common/coreboot_config.mk
|
||||
else
|
||||
MTK_COMMON_CFG := $(MTK_PLAT)/common/common_config.mk
|
||||
endif
|
||||
MTK_PLAT := plat/mediatek
|
||||
MTK_PLAT_SOC := ${MTK_PLAT}/${MTK_SOC}
|
||||
MTK_PLAT_CFG := $(MTK_PLAT_SOC)/plat_config.mk
|
||||
MTK_PROJECT_CFG := $(MTK_PLAT)/project/$(PLAT)/project_config.mk
|
||||
MTK_OPTIONS := $(MTK_PLAT)/build_helpers/options.mk
|
||||
MTK_COND_EVAL := $(MTK_PLAT)/build_helpers/conditional_eval_options.mk
|
||||
|
||||
# Indicate which BL should be built in command line
|
||||
ifeq (${NEED_BL32},yes)
|
||||
MTK_BL := bl32
|
||||
else
|
||||
MTK_BL := bl31
|
||||
endif
|
||||
# Include common, platform, board level config
|
||||
include $(MTK_COMMON_CFG)
|
||||
include $(MTK_PLAT_CFG)
|
||||
-include $(MTK_PROJECT_CFG)
|
||||
include $(MTK_COND_EVAL)
|
||||
include $(MTK_OPTIONS)
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
#
|
||||
# Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
# Expand include modules
|
||||
$(eval $(call INCLUDE_MODULES,$(MODULES-y)))
|
||||
|
||||
# Make next section align to page size
|
||||
ifneq ($(MTK_EXTRA_LINKERFILE),)
|
||||
$(eval $(call MAKE_LINKERFILE_ITER,$(MTK_LINKERFILE_SOURCE),bl31))
|
||||
|
||||
# EXTRA_GENERATED_LINKER_SCRIPT is a global variable of derived linker
|
||||
# script list(from MTK_LINKERFILE_SOURCE) after MAKE_LINKERFILE_ITER
|
||||
# function call
|
||||
EXTRA_LINKERFILE += ${EXTRA_GENERATED_LINKER_SCRIPT}
|
||||
|
||||
# Expand derived linker script as build target
|
||||
$(eval $(call MAKE_LD_ITER, $(EXTRA_GENERATED_LINKER_SCRIPT),$(MTK_LINKERFILE_SOURCE),bl31))
|
||||
|
||||
# mtk_align.ld MUST BE THE LAST LINKER SCRIPT!
|
||||
EXTRA_LINKERFILE += ${MTK_PLAT}/include/mtk_align.ld
|
||||
|
||||
# bl31.ld should depend on EXTRA_LINKERFILE
|
||||
$(eval ${BUILD_PLAT}/bl31/bl31.ld: ${EXTRA_LINKERFILE})
|
||||
EXTRA_LINKERFILE := $(addprefix -T,$(EXTRA_LINKERFILE))
|
||||
else
|
||||
EXTRA_LINKERFILE :=
|
||||
endif
|
||||
@@ -0,0 +1,25 @@
|
||||
#
|
||||
# Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
# call add_defined_option to evaluate MTK defined value
|
||||
$(eval $(call add_defined_option,MTK_SIP_KERNEL_BOOT_ENABLE))
|
||||
$(eval $(call add_defined_option,PLAT_EXTRA_RODATA_INCLUDES))
|
||||
$(eval $(call add_defined_option,MTK_EXTRA_LINKERFILE))
|
||||
$(eval $(call add_defined_option,MTK_BL31_AS_BL2))
|
||||
$(eval $(call add_defined_option,MTK_BL33_IS_64BIT))
|
||||
$(eval $(call add_defined_option,PLAT_XLAT_TABLES_DYNAMIC))
|
||||
$(eval $(call add_defined_option,MTK_ADAPTED))
|
||||
$(eval $(call add_defined_option,MTK_PUBEVENT_ENABLE))
|
||||
$(eval $(call add_defined_option,MTK_SOC))
|
||||
$(eval $(call add_defined_option,UART_CLOCK))
|
||||
$(eval $(call add_defined_option,UART_BAUDRATE))
|
||||
$(eval $(call add_defined_option,CONFIG_MTK_MCUSYS))
|
||||
$(eval $(call add_defined_option,CONFIG_MTK_PM_SUPPORT))
|
||||
$(eval $(call add_defined_option,CONFIG_MTK_CPU_PM_SUPPORT))
|
||||
$(eval $(call add_defined_option,CONFIG_MTK_SMP_EN))
|
||||
$(eval $(call add_defined_option,CONFIG_MTK_CPU_SUSPEND_EN))
|
||||
$(eval $(call add_defined_option,CONFIG_MTK_PM_ARCH))
|
||||
$(eval $(call add_defined_option,CONFIG_MTK_CPU_PM_ARCH))
|
||||
@@ -0,0 +1,34 @@
|
||||
#
|
||||
# Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
# indicate the reset vector address can be programmed
|
||||
PROGRAMMABLE_RESET_ADDRESS := 1
|
||||
MULTI_CONSOLE_API := 1
|
||||
COLD_BOOT_SINGLE_CPU := 1
|
||||
# Build flag to include AArch32 registers in cpu context save and restore during
|
||||
# world switch. This flag must be set to 0 for AArch64-only platforms.
|
||||
CTX_INCLUDE_AARCH32_REGS := 0
|
||||
PLAT_XLAT_TABLES_DYNAMIC := 1
|
||||
# enable this definition to print irq dump status in tf-a
|
||||
GIC_DEBUG := 0
|
||||
# Enable stack protector.
|
||||
# Allowed values are "all", "strong", "default" and "none"
|
||||
ENABLE_STACK_PROTECTOR := strong
|
||||
# AMU, Kernel will access amuserenr_el0 if PE supported
|
||||
# Firmware _must_ implement AMU support
|
||||
ENABLE_AMU := 1
|
||||
VENDOR_EXTEND_PUBEVENT_ENABLE := 1
|
||||
|
||||
# MTK define options
|
||||
MTK_BL33_IS_64BIT := 0
|
||||
MTK_ADAPTED := 1
|
||||
|
||||
# MTK module config
|
||||
CONFIG_MTK_INTERRUPT := y
|
||||
CONFIG_MTK_UART := y
|
||||
|
||||
# UART baudrate
|
||||
UART_BAUDRATE := 921600
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
#
|
||||
# Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
# indicate the reset vector address can be programmed
|
||||
PROGRAMMABLE_RESET_ADDRESS := 1
|
||||
COLD_BOOT_SINGLE_CPU := 1
|
||||
# Build flag to include AArch32 registers in cpu context save and restore during
|
||||
# world switch. This flag must be set to 0 for AArch64-only platforms.
|
||||
CTX_INCLUDE_AARCH32_REGS := 0
|
||||
PLAT_XLAT_TABLES_DYNAMIC := 1
|
||||
|
||||
VENDOR_EXTEND_PUBEVENT_ENABLE := 1
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2022, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <mt_lp_rm.h>
|
||||
#include <stddef.h>
|
||||
|
||||
struct platform_mt_resource_manager {
|
||||
unsigned int count;
|
||||
struct mt_resource_manager *plat_rm;
|
||||
};
|
||||
|
||||
static struct platform_mt_resource_manager plat_mt_rm;
|
||||
|
||||
int mt_lp_rm_register(struct mt_resource_manager *rm)
|
||||
{
|
||||
unsigned int i;
|
||||
struct mt_resource_constraint *const *rc;
|
||||
|
||||
if ((rm == NULL) || (rm->consts == NULL) ||
|
||||
(plat_mt_rm.plat_rm != NULL)) {
|
||||
return MT_RM_STATUS_BAD;
|
||||
}
|
||||
|
||||
for (i = 0U, rc = rm->consts; *rc != NULL; i++, rc++) {
|
||||
if ((*rc)->init != NULL) {
|
||||
(*rc)->init();
|
||||
}
|
||||
}
|
||||
|
||||
plat_mt_rm.plat_rm = rm;
|
||||
plat_mt_rm.count = i;
|
||||
|
||||
return MT_RM_STATUS_OK;
|
||||
}
|
||||
|
||||
int mt_lp_rm_reset_constraint(int idx, unsigned int cpuid, int stateid)
|
||||
{
|
||||
struct mt_resource_constraint const *rc = NULL;
|
||||
|
||||
if ((plat_mt_rm.plat_rm == NULL) || (idx < 0) ||
|
||||
(idx >= plat_mt_rm.count)) {
|
||||
return MT_RM_STATUS_BAD;
|
||||
}
|
||||
|
||||
rc = plat_mt_rm.plat_rm->consts[idx];
|
||||
|
||||
if ((rc == NULL) || (rc->reset == NULL)) {
|
||||
return MT_RM_STATUS_BAD;
|
||||
}
|
||||
|
||||
return rc->reset(cpuid, stateid);
|
||||
}
|
||||
|
||||
int mt_lp_rm_find_and_run_constraint(int idx, unsigned int cpuid,
|
||||
int stateid, void *priv)
|
||||
{
|
||||
int i, res = MT_RM_STATUS_BAD;
|
||||
struct mt_resource_constraint *const *rc;
|
||||
struct mt_resource_manager *rm = plat_mt_rm.plat_rm;
|
||||
|
||||
if ((rm == NULL) || (idx < 0) || (idx >= plat_mt_rm.count)) {
|
||||
return res;
|
||||
}
|
||||
|
||||
/* If subsys clk/mtcmos is on, add block-resource-off flag */
|
||||
if (rm->update != NULL) {
|
||||
res = rm->update(rm->consts, stateid, priv);
|
||||
if (res != 0) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = idx, rc = (rm->consts + idx); *rc != NULL; i++, rc++) {
|
||||
if (((*rc)->is_valid != NULL) &&
|
||||
((*rc)->is_valid(cpuid, stateid))) {
|
||||
if (((*rc)->run != NULL) &&
|
||||
((*rc)->run(cpuid, stateid) == 0)) {
|
||||
res = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int mt_lp_rm_do_update(int stateid, int type, void const *p)
|
||||
{
|
||||
int res = MT_RM_STATUS_BAD;
|
||||
struct mt_resource_constraint *const *rc;
|
||||
struct mt_resource_manager *rm = plat_mt_rm.plat_rm;
|
||||
|
||||
if (rm == NULL) {
|
||||
return res;
|
||||
}
|
||||
|
||||
for (rc = rm->consts; *rc != NULL; rc++) {
|
||||
if ((*rc)->update != NULL) {
|
||||
res = (*rc)->update(stateid, type, p);
|
||||
if (res != MT_RM_STATUS_OK) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2022, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef MT_LP_RM_H
|
||||
#define MT_LP_RM_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#define MT_RM_STATUS_OK 0
|
||||
#define MT_RM_STATUS_BAD -1
|
||||
|
||||
enum PLAT_MT_LPM_RC_TYPE {
|
||||
PLAT_RC_UPDATE_CONDITION,
|
||||
PLAT_RC_UPDATE_REMAIN_IRQS
|
||||
};
|
||||
|
||||
struct mt_resource_constraint {
|
||||
int level;
|
||||
int (*init)(void);
|
||||
bool (*is_valid)(unsigned int cpu, int stateid);
|
||||
int (*update)(int stateid, int type, const void *p);
|
||||
int (*run)(unsigned int cpu, int stateid);
|
||||
int (*reset)(unsigned int cpu, int stateid);
|
||||
unsigned int (*allow)(int stateid);
|
||||
};
|
||||
|
||||
struct mt_resource_manager {
|
||||
int (*update)(struct mt_resource_constraint **con,
|
||||
int stateid, void *priv);
|
||||
struct mt_resource_constraint **consts;
|
||||
};
|
||||
|
||||
extern int mt_lp_rm_register(struct mt_resource_manager *rm);
|
||||
extern int mt_lp_rm_find_and_run_constraint(int idx, unsigned int cpuid,
|
||||
int stateid, void *priv);
|
||||
extern int mt_lp_rm_reset_constraint(int constraint_id, unsigned int cpuid,
|
||||
int stateid);
|
||||
extern int mt_lp_rm_do_update(int stateid, int type, void const *p);
|
||||
#endif /* MT_LP_RM_H */
|
||||
@@ -0,0 +1,14 @@
|
||||
#
|
||||
# Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
LOCAL_DIR := $(call GET_LOCAL_DIR)
|
||||
|
||||
MODULE := lpm
|
||||
LOCAL_SRCS-y := $(LOCAL_DIR)/mt_lp_rm.c
|
||||
|
||||
PLAT_INCLUDES += -I${LOCAL_DIR}
|
||||
|
||||
$(eval $(call MAKE_MODULE,$(MODULE),$(LOCAL_SRCS-y),$(MTK_BL)))
|
||||
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
* Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <arch.h>
|
||||
#include <common/bl_common.h>
|
||||
#include <common/debug.h>
|
||||
#include <drivers/delay_timer.h>
|
||||
#include <drivers/generic_delay_timer.h>
|
||||
#if XLAT_TABLES_LIB_V2 && PLAT_XLAT_TABLES_DYNAMIC
|
||||
#include <lib/xlat_tables/xlat_tables_v2.h>
|
||||
#endif
|
||||
#include <plat/common/platform.h>
|
||||
|
||||
#if COREBOOT
|
||||
#include <common/desc_image_load.h>
|
||||
|
||||
#include <drivers/ti/uart/uart_16550.h>
|
||||
#include <lib/coreboot.h>
|
||||
#include <plat_params.h>
|
||||
#endif
|
||||
|
||||
/* MTK headers */
|
||||
#if MTK_SIP_KERNEL_BOOT_ENABLE
|
||||
#include <cold_boot.h>
|
||||
#endif
|
||||
#include <lib/mtk_init/mtk_init.h>
|
||||
#include <mtk_mmap_pool.h>
|
||||
|
||||
IMPORT_SYM(uintptr_t, __RW_START__, RW_START);
|
||||
IMPORT_SYM(uintptr_t, __DATA_START__, DATA_START);
|
||||
|
||||
#if COREBOOT
|
||||
static entry_point_info_t bl32_ep_info;
|
||||
static entry_point_info_t bl33_ep_info;
|
||||
|
||||
/*******************************************************************************
|
||||
* Return a pointer to the 'entry_point_info' structure of the next image for
|
||||
* the security state specified. BL33 corresponds to the non-secure image type
|
||||
* while BL32 corresponds to the secure image type. A NULL pointer is returned
|
||||
* if the image does not exist.
|
||||
******************************************************************************/
|
||||
entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
|
||||
{
|
||||
entry_point_info_t *next_image_info;
|
||||
|
||||
next_image_info = (type == NON_SECURE) ? &bl33_ep_info : &bl32_ep_info;
|
||||
assert(next_image_info->h.type == PARAM_EP);
|
||||
|
||||
/* None of the images on this platform can have 0x0 as the entrypoint */
|
||||
if (next_image_info->pc) {
|
||||
return next_image_info;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
#else
|
||||
#ifndef MTK_BL31_AS_BL2
|
||||
static struct mtk_bl31_fw_config bl31_fw_config;
|
||||
#else
|
||||
struct mtk_bl31_fw_config bl31_fw_config;
|
||||
#endif
|
||||
/* In order to be accessed after MMU enable */
|
||||
static struct mtk_bl_param_t bl_param_clone;
|
||||
|
||||
void *get_mtk_bl31_fw_config(int index)
|
||||
{
|
||||
void *arg = NULL;
|
||||
|
||||
switch (index) {
|
||||
case BOOT_ARG_FROM_BL2:
|
||||
arg = bl31_fw_config.from_bl2;
|
||||
break;
|
||||
case BOOT_ARG_SOC_FW_CONFIG:
|
||||
arg = bl31_fw_config.soc_fw_config;
|
||||
break;
|
||||
case BOOT_ARG_HW_CONFIG:
|
||||
arg = bl31_fw_config.hw_config;
|
||||
break;
|
||||
case BOOT_ARG_RESERVED:
|
||||
arg = bl31_fw_config.reserved;
|
||||
break;
|
||||
default:
|
||||
WARN("Fail to get boot arg, index:%d", index);
|
||||
break;
|
||||
}
|
||||
return arg;
|
||||
}
|
||||
#endif
|
||||
/*****************************************************************************
|
||||
* Perform the very early platform specific architectural setup shared between
|
||||
* ARM standard platforms. This only does basic initialization. Later
|
||||
* architectural setup (bl31_arch_setup()) does not do anything platform
|
||||
* specific.
|
||||
******************************************************************************/
|
||||
void bl31_early_platform_setup2(u_register_t from_bl2,
|
||||
u_register_t soc_fw_config,
|
||||
u_register_t hw_config, u_register_t plat_params_from_bl2)
|
||||
|
||||
{
|
||||
#if COREBOOT
|
||||
static console_t console;
|
||||
|
||||
params_early_setup(soc_fw_config);
|
||||
if (coreboot_serial.type) {
|
||||
console_16550_register(coreboot_serial.baseaddr,
|
||||
coreboot_serial.input_hertz,
|
||||
coreboot_serial.baud,
|
||||
&console);
|
||||
}
|
||||
bl31_params_parse_helper(from_bl2, &bl32_ep_info, &bl33_ep_info);
|
||||
#else
|
||||
struct mtk_bl_param_t *p_mtk_bl_param = (struct mtk_bl_param_t *)from_bl2;
|
||||
|
||||
if (p_mtk_bl_param == NULL) {
|
||||
ERROR("from_bl2 should not be NULL\n");
|
||||
panic();
|
||||
}
|
||||
memcpy(&bl_param_clone, p_mtk_bl_param, sizeof(struct mtk_bl_param_t));
|
||||
bl31_fw_config.from_bl2 = (void *)&bl_param_clone;
|
||||
bl31_fw_config.soc_fw_config = (void *)soc_fw_config;
|
||||
bl31_fw_config.hw_config = (void *)hw_config;
|
||||
bl31_fw_config.reserved = (void *)plat_params_from_bl2;
|
||||
#endif
|
||||
|
||||
INFO("MTK BL31 start\n");
|
||||
/* Init delay function */
|
||||
generic_delay_timer_init();
|
||||
/* Initialize module initcall */
|
||||
mtk_init_one_level(MTK_INIT_LVL_EARLY_PLAT);
|
||||
}
|
||||
|
||||
void bl31_plat_arch_setup(void)
|
||||
{
|
||||
const mmap_region_t bl_regions[] = {
|
||||
MAP_BL_RO,
|
||||
MAP_BL_RW,
|
||||
#if USE_COHERENT_MEM
|
||||
MAP_BL_COHERENT_RAM,
|
||||
#endif
|
||||
{0},
|
||||
};
|
||||
|
||||
mtk_xlat_init(bl_regions);
|
||||
/* Initialize module initcall */
|
||||
mtk_init_one_level(MTK_INIT_LVL_ARCH);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* Perform any BL31 platform setup common to ARM standard platforms
|
||||
******************************************************************************/
|
||||
|
||||
void bl31_platform_setup(void)
|
||||
{
|
||||
mtk_init_one_level(MTK_INIT_LVL_PLAT_SETUP_0);
|
||||
mtk_init_one_level(MTK_INIT_LVL_PLAT_SETUP_1);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Operations before cold CPU leave BL31.
|
||||
* Switch console to runtime state.
|
||||
******************************************************************************/
|
||||
void bl31_plat_runtime_setup(void)
|
||||
{
|
||||
mtk_init_one_level(MTK_INIT_LVL_PLAT_RUNTIME);
|
||||
console_switch_state(CONSOLE_FLAG_RUNTIME);
|
||||
}
|
||||
|
||||
unsigned int plat_get_syscnt_freq2(void)
|
||||
{
|
||||
return SYS_COUNTER_FREQ_IN_HZ;
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2022, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <common/bl_common.h>
|
||||
#include <common/debug.h>
|
||||
#include <drivers/arm/cci.h>
|
||||
#include <drivers/console.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <lib/smccc.h>
|
||||
#include <lib/xlat_tables/xlat_tables.h>
|
||||
#include <plat/common/platform.h>
|
||||
#include <services/arm_arch_svc.h>
|
||||
|
||||
#include <mtk_plat_common.h>
|
||||
#include <mtk_sip_svc.h>
|
||||
#include <plat_private.h>
|
||||
|
||||
void clean_top_32b_of_param(uint32_t smc_fid,
|
||||
u_register_t *px1,
|
||||
u_register_t *px2,
|
||||
u_register_t *px3,
|
||||
u_register_t *px4)
|
||||
{
|
||||
/* if parameters from SMC32. Clean top 32 bits */
|
||||
if (GET_SMC_CC(smc_fid) == SMC_64) {
|
||||
*px1 = *px1 & SMC32_PARAM_MASK;
|
||||
*px2 = *px2 & SMC32_PARAM_MASK;
|
||||
*px3 = *px3 & SMC32_PARAM_MASK;
|
||||
*px4 = *px4 & SMC32_PARAM_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* plat_is_smccc_feature_available() - This function checks whether SMCCC
|
||||
* feature is availabile for platform.
|
||||
* @fid: SMCCC function id
|
||||
*
|
||||
* Return SMC_OK if SMCCC feature is available and SMC_ARCH_CALL_NOT_SUPPORTED
|
||||
* otherwise.
|
||||
*****************************************************************************/
|
||||
int32_t plat_is_smccc_feature_available(u_register_t fid)
|
||||
{
|
||||
switch (fid) {
|
||||
case SMCCC_ARCH_SOC_ID:
|
||||
return SMC_ARCH_CALL_SUCCESS;
|
||||
default:
|
||||
return SMC_ARCH_CALL_NOT_SUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t plat_get_soc_version(void)
|
||||
{
|
||||
uint32_t manfid = SOC_ID_SET_JEP_106(JEDEC_MTK_BKID, JEDEC_MTK_MFID);
|
||||
|
||||
return (int32_t)(manfid | (SOC_CHIP_ID & SOC_ID_IMPL_DEF_MASK));
|
||||
}
|
||||
|
||||
int32_t plat_get_soc_revision(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2016-2022, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#ifndef MTK_PLAT_COMMON_H
|
||||
#define MTK_PLAT_COMMON_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <common/bl_common.h>
|
||||
#include <common/param_header.h>
|
||||
|
||||
/*******************************************************************************
|
||||
* Function and variable prototypes
|
||||
******************************************************************************/
|
||||
#define SMC32_PARAM_MASK (0xFFFFFFFF)
|
||||
|
||||
#define JEDEC_MTK_BKID U(4)
|
||||
#define JEDEC_MTK_MFID U(0x26)
|
||||
|
||||
struct mtk_bl31_params {
|
||||
param_header_t h;
|
||||
image_info_t *bl31_image_info;
|
||||
entry_point_info_t *bl32_ep_info;
|
||||
image_info_t *bl32_image_info;
|
||||
entry_point_info_t *bl33_ep_info;
|
||||
image_info_t *bl33_image_info;
|
||||
};
|
||||
|
||||
/* Declarations for mtk_plat_common.c */
|
||||
uint32_t plat_get_spsr_for_bl32_entry(void);
|
||||
uint32_t plat_get_spsr_for_bl33_entry(void);
|
||||
void clean_top_32b_of_param(uint32_t smc_fid, u_register_t *x1,
|
||||
u_register_t *x2,
|
||||
u_register_t *x3,
|
||||
u_register_t *x4);
|
||||
void bl31_prepare_kernel_entry(uint64_t k32_64);
|
||||
void enable_ns_access_to_cpuectlr(void);
|
||||
void boot_to_kernel(uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4);
|
||||
uint64_t get_kernel_info_pc(void);
|
||||
uint64_t get_kernel_info_r0(void);
|
||||
uint64_t get_kernel_info_r1(void);
|
||||
uint64_t get_kernel_info_r2(void);
|
||||
|
||||
extern struct atf_arg_t gteearg;
|
||||
#endif /* MTK_PLAT_COMMON_H */
|
||||
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <common/runtime_svc.h>
|
||||
#include <drivers/console.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <tools_share/uuid.h>
|
||||
|
||||
#include <mtk_plat_common.h>
|
||||
#include <mtk_sip_svc.h>
|
||||
#include <plat_sip_calls.h>
|
||||
|
||||
/* Mediatek SiP Service UUID */
|
||||
DEFINE_SVC_UUID2(mtk_sip_svc_uid,
|
||||
0xa42b58f7, 0x6242, 0x7d4d, 0x80, 0xe5,
|
||||
0x8f, 0x95, 0x05, 0x00, 0x0f, 0x3d);
|
||||
|
||||
#pragma weak mediatek_plat_sip_handler
|
||||
uintptr_t mediatek_plat_sip_handler(uint32_t smc_fid,
|
||||
u_register_t x1,
|
||||
u_register_t x2,
|
||||
u_register_t x3,
|
||||
u_register_t x4,
|
||||
void *cookie,
|
||||
void *handle,
|
||||
u_register_t flags)
|
||||
{
|
||||
ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid);
|
||||
SMC_RET1(handle, SMC_UNK);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function handles Mediatek defined SiP Calls */
|
||||
uintptr_t mediatek_sip_handler(uint32_t smc_fid,
|
||||
u_register_t x1,
|
||||
u_register_t x2,
|
||||
u_register_t x3,
|
||||
u_register_t x4,
|
||||
void *cookie,
|
||||
void *handle,
|
||||
u_register_t flags)
|
||||
{
|
||||
uint32_t ns;
|
||||
|
||||
/* if parameter is sent from SMC32. Clean top 32 bits */
|
||||
clean_top_32b_of_param(smc_fid, &x1, &x2, &x3, &x4);
|
||||
|
||||
/* Determine which security state this SMC originated from */
|
||||
ns = is_caller_non_secure(flags);
|
||||
if (!ns) {
|
||||
/* SiP SMC service secure world's call */
|
||||
;
|
||||
} else {
|
||||
/* SiP SMC service normal world's call */
|
||||
switch (smc_fid) {
|
||||
#if MTK_SIP_SET_AUTHORIZED_SECURE_REG_ENABLE
|
||||
case MTK_SIP_SET_AUTHORIZED_SECURE_REG: {
|
||||
/* only use ret here */
|
||||
uint64_t ret;
|
||||
|
||||
ret = mt_sip_set_authorized_sreg((uint32_t)x1,
|
||||
(uint32_t)x2);
|
||||
SMC_RET1(handle, ret);
|
||||
}
|
||||
#endif
|
||||
#if MTK_SIP_KERNEL_BOOT_ENABLE
|
||||
case MTK_SIP_KERNEL_BOOT_AARCH32:
|
||||
boot_to_kernel(x1, x2, x3, x4);
|
||||
SMC_RET0(handle);
|
||||
#endif
|
||||
default:
|
||||
/* Do nothing in default case */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return mediatek_plat_sip_handler(smc_fid, x1, x2, x3, x4,
|
||||
cookie, handle, flags);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is responsible for handling all SiP calls from the NS world
|
||||
*/
|
||||
uintptr_t sip_smc_handler(uint32_t smc_fid,
|
||||
u_register_t x1,
|
||||
u_register_t x2,
|
||||
u_register_t x3,
|
||||
u_register_t x4,
|
||||
void *cookie,
|
||||
void *handle,
|
||||
u_register_t flags)
|
||||
{
|
||||
switch (smc_fid) {
|
||||
case SIP_SVC_CALL_COUNT:
|
||||
/* Return the number of Mediatek SiP Service Calls. */
|
||||
SMC_RET1(handle,
|
||||
MTK_COMMON_SIP_NUM_CALLS + MTK_PLAT_SIP_NUM_CALLS);
|
||||
|
||||
case SIP_SVC_UID:
|
||||
/* Return UID to the caller */
|
||||
SMC_UUID_RET(handle, mtk_sip_svc_uid);
|
||||
|
||||
case SIP_SVC_VERSION:
|
||||
/* Return the version of current implementation */
|
||||
SMC_RET2(handle, MTK_SIP_SVC_VERSION_MAJOR,
|
||||
MTK_SIP_SVC_VERSION_MINOR);
|
||||
|
||||
default:
|
||||
return mediatek_sip_handler(smc_fid, x1, x2, x3, x4,
|
||||
cookie, handle, flags);
|
||||
}
|
||||
}
|
||||
|
||||
/* Define a runtime service descriptor for fast SMC calls */
|
||||
DECLARE_RT_SVC(
|
||||
mediatek_sip_svc,
|
||||
OEN_SIP_START,
|
||||
OEN_SIP_END,
|
||||
SMC_TYPE_FAST,
|
||||
NULL,
|
||||
sip_smc_handler
|
||||
);
|
||||
+235
@@ -0,0 +1,235 @@
|
||||
/*
|
||||
* Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#if MTK_SIP_KERNEL_BOOT_ENABLE
|
||||
#include <cold_boot.h>
|
||||
#endif
|
||||
#include <common/debug.h>
|
||||
#include <common/runtime_svc.h>
|
||||
#include <lib/mtk_init/mtk_init.h>
|
||||
#include <mtk_sip_svc.h>
|
||||
|
||||
#define SMC_HANDLER_DEBUG(...) VERBOSE(__VA_ARGS__)
|
||||
#define SMC_HANDLER_DEBUG_NOT_IMP_MSG "%s[0x%x] smc handler not implemented\n"
|
||||
#define SMC_HANDLER_DEBUG_START_MSG "%s[0x%x] smc handler start, smc desc. index:%d\n"
|
||||
#define SMC_HANDLER_DEBUG_END_MSG "%s[0x%x] smc handler end\n"
|
||||
|
||||
/*
|
||||
* These macros below are used to identify SIP calls from Kernel,
|
||||
* Hypervisor, or 2ndBootloader
|
||||
*/
|
||||
#define SIP_FID_ORI_MASK (0xc000)
|
||||
#define SIP_FID_ORI_SHIFT (14)
|
||||
#define SIP_FID_KERNEL (0x0)
|
||||
#define SIP_FID_KERNEL_VIA_GZ (0x1)
|
||||
#define SIP_FID_GZ (0x2)
|
||||
|
||||
#define GET_SMC_ORI(_fid) (((_fid) & SIP_FID_ORI_MASK) >> SIP_FID_ORI_SHIFT)
|
||||
#define GET_SMC_ORI_NUM(_fid) ((_fid) & ~(SIP_FID_ORI_MASK))
|
||||
|
||||
#define is_from_nsel2(_ori) (_ori == SIP_FID_GZ)
|
||||
#define is_from_bl33(_ori) \
|
||||
((_ori != SIP_FID_GZ) && (is_el1_2nd_bootloader() == 1))
|
||||
#define is_from_nsel1(_ori) \
|
||||
(((_ori == SIP_FID_KERNEL) || \
|
||||
(_ori == SIP_FID_KERNEL_VIA_GZ)) && \
|
||||
(is_el1_2nd_bootloader() == 0))
|
||||
|
||||
#define is_smc_forbidden(_ori) (_ori == SIP_FID_KERNEL_VIA_GZ)
|
||||
|
||||
#define MASK_32_BIT (0xffffffffU)
|
||||
#define SMC_ID_EXPAND_AS_SMC_OPERATION(_smc_id, _smc_num) \
|
||||
case _smc_id##_AARCH32: \
|
||||
{ \
|
||||
x1 = x1 & MASK_32_BIT; \
|
||||
x2 = x2 & MASK_32_BIT; \
|
||||
x3 = x3 & MASK_32_BIT; \
|
||||
x4 = x4 & MASK_32_BIT; \
|
||||
} \
|
||||
case _smc_id##_AARCH64: \
|
||||
{ \
|
||||
if (_smc_id##_descriptor_index < 0) { \
|
||||
SMC_HANDLER_DEBUG(SMC_HANDLER_DEBUG_NOT_IMP_MSG, #_smc_id, smc_id); \
|
||||
break; \
|
||||
} \
|
||||
if (_smc_id##_descriptor_index >= smc_id_descriptor_max) { \
|
||||
SMC_HANDLER_DEBUG("smc descriptor index[%d] exceed max[%d]\n", \
|
||||
_smc_id##_descriptor_index, smc_id_descriptor_max); \
|
||||
break; \
|
||||
} \
|
||||
SMC_HANDLER_DEBUG(SMC_HANDLER_DEBUG_START_MSG, #_smc_id, smc_id, \
|
||||
_smc_id##_descriptor_index); \
|
||||
ret = smc_handler_pool[_smc_id##_descriptor_index].smc_handler(x1,\
|
||||
x2, x3, x4, handle, &smc_ret); \
|
||||
SMC_HANDLER_DEBUG(SMC_HANDLER_DEBUG_END_MSG, #_smc_id, smc_id); \
|
||||
break; \
|
||||
}
|
||||
|
||||
#define SMC_ID_EXPAND_AS_DESCRIPTOR_INDEX(_smc_id, _smc_num) \
|
||||
short _smc_id##_descriptor_index __section("mtk_plat_ro") = -1;
|
||||
|
||||
MTK_SIP_SMC_FROM_BL33_TABLE(SMC_ID_EXPAND_AS_DESCRIPTOR_INDEX);
|
||||
MTK_SIP_SMC_FROM_NS_EL1_TABLE(SMC_ID_EXPAND_AS_DESCRIPTOR_INDEX);
|
||||
|
||||
IMPORT_SYM(uintptr_t, __MTK_SMC_POOL_START__, MTK_SMC_POOL_START);
|
||||
IMPORT_SYM(uintptr_t, __MTK_SMC_POOL_END_UNALIGNED__, MTK_SMC_POOL_END_UNALIGNED);
|
||||
|
||||
static const struct smc_descriptor *smc_handler_pool;
|
||||
static short smc_id_descriptor_max;
|
||||
|
||||
#if !MTK_SIP_KERNEL_BOOT_ENABLE
|
||||
/*
|
||||
* If there is no SMC request needs to be served in 2nd bootloader,
|
||||
* disable the service path inherently.
|
||||
*/
|
||||
bool is_el1_2nd_bootloader(void)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void print_smc_descriptor(const struct smc_descriptor pool[])
|
||||
{
|
||||
const struct smc_descriptor *p_smc_desc;
|
||||
|
||||
INFO("print smc descriptor pool\n");
|
||||
for (p_smc_desc = &pool[0];
|
||||
(char *)p_smc_desc < (char *)MTK_SMC_POOL_END_UNALIGNED;
|
||||
p_smc_desc++) {
|
||||
INFO("descriptor name:%s\n", p_smc_desc->smc_name);
|
||||
INFO("descriptor index:%d\n", *p_smc_desc->smc_descriptor_index);
|
||||
INFO("smc id 32:0x%x, smc id 64:0x%x\n",
|
||||
p_smc_desc->smc_id_aarch32, p_smc_desc->smc_id_aarch64);
|
||||
}
|
||||
}
|
||||
|
||||
static int mtk_smc_handler_init(void)
|
||||
{
|
||||
const struct smc_descriptor *iter;
|
||||
short index_cnt;
|
||||
int ret = 0;
|
||||
|
||||
smc_handler_pool = (const struct smc_descriptor *)MTK_SMC_POOL_START;
|
||||
/* Designate descriptor index point to smc_handler_pool */
|
||||
for (index_cnt = 0, iter = &smc_handler_pool[0];
|
||||
(char *)iter < (char *)MTK_SMC_POOL_END_UNALIGNED;
|
||||
iter++, index_cnt++) {
|
||||
if (index_cnt < 0) {
|
||||
SMC_HANDLER_DEBUG("smc handler pool index overflow!\n");
|
||||
ret = -EPERM;
|
||||
assert(0);
|
||||
break;
|
||||
}
|
||||
*(iter->smc_descriptor_index) = index_cnt;
|
||||
}
|
||||
smc_id_descriptor_max = index_cnt;
|
||||
print_smc_descriptor(smc_handler_pool);
|
||||
return ret;
|
||||
}
|
||||
MTK_EARLY_PLAT_INIT(mtk_smc_handler_init);
|
||||
|
||||
/* This function handles Mediatek defined SiP Calls from Bootloader */
|
||||
static uintptr_t mtk_smc_handler_bl33(uint32_t smc_id,
|
||||
u_register_t x1,
|
||||
u_register_t x2,
|
||||
u_register_t x3,
|
||||
u_register_t x4,
|
||||
void *cookie,
|
||||
void *handle,
|
||||
u_register_t flags)
|
||||
{
|
||||
uintptr_t ret = MTK_SIP_E_SUCCESS;
|
||||
struct smccc_res smc_ret = {0};
|
||||
|
||||
switch (smc_id) {
|
||||
MTK_SIP_SMC_FROM_BL33_TABLE(SMC_ID_EXPAND_AS_SMC_OPERATION);
|
||||
default:
|
||||
INFO("BL33 SMC ID:0x%x not supported\n", smc_id);
|
||||
ret = SMC_UNK;
|
||||
break;
|
||||
}
|
||||
SMC_RET4(handle, ret, smc_ret.a1, smc_ret.a2, smc_ret.a3);
|
||||
}
|
||||
|
||||
/* This function handles Mediatek defined SiP Calls from Kernel */
|
||||
static uintptr_t mtk_smc_handler_nsel1(uint32_t smc_id,
|
||||
u_register_t x1,
|
||||
u_register_t x2,
|
||||
u_register_t x3,
|
||||
u_register_t x4,
|
||||
void *cookie,
|
||||
void *handle,
|
||||
u_register_t flags)
|
||||
{
|
||||
uintptr_t ret = MTK_SIP_E_SUCCESS;
|
||||
struct smccc_res smc_ret = {0};
|
||||
|
||||
switch (smc_id) {
|
||||
MTK_SIP_SMC_FROM_NS_EL1_TABLE(SMC_ID_EXPAND_AS_SMC_OPERATION);
|
||||
default:
|
||||
INFO("NSEL1 SMC ID:0x%x not supported\n", smc_id);
|
||||
ret = SMC_UNK;
|
||||
break;
|
||||
}
|
||||
SMC_RET4(handle, ret, smc_ret.a1, smc_ret.a2, smc_ret.a3);
|
||||
}
|
||||
|
||||
static uintptr_t mtk_smc_handler(uint32_t smc_id,
|
||||
u_register_t x1,
|
||||
u_register_t x2,
|
||||
u_register_t x3,
|
||||
u_register_t x4,
|
||||
void *cookie,
|
||||
void *handle,
|
||||
u_register_t flags)
|
||||
{
|
||||
uintptr_t ret = SMC_UNK;
|
||||
uint32_t ns;
|
||||
uint32_t smc_ori;
|
||||
uint32_t smc_num;
|
||||
|
||||
/* Get SMC Originator bit 14.15 */
|
||||
smc_ori = GET_SMC_ORI(smc_id);
|
||||
/* Get SMC Number. Clean bit 14.15 */
|
||||
smc_num = GET_SMC_ORI_NUM(smc_id);
|
||||
|
||||
/* Determine which security state this SMC originated from */
|
||||
ns = is_caller_non_secure(flags);
|
||||
|
||||
if (ns && is_smc_forbidden(smc_ori)) {
|
||||
ERROR("%s: Forbidden SMC call (0x%x)\n", __func__, smc_id);
|
||||
SMC_RET1(handle, ret);
|
||||
}
|
||||
|
||||
if (!ns) {
|
||||
/* SiP SMC service secure world's call */
|
||||
INFO("Secure SMC ID:0x%x not supported\n", smc_id);
|
||||
SMC_RET1(handle, ret);
|
||||
}
|
||||
if (is_from_bl33(smc_ori)) {
|
||||
/* SiP SMC service secure bootloader's call */
|
||||
return mtk_smc_handler_bl33(smc_num, x1, x2, x3, x4,
|
||||
cookie, handle, flags);
|
||||
} else if (is_from_nsel1(smc_ori)) {
|
||||
/* SiP SMC service kernel's call */
|
||||
return mtk_smc_handler_nsel1(smc_num, x1, x2, x3, x4,
|
||||
cookie, handle, flags);
|
||||
}
|
||||
INFO("SMC ID:0x%x not supported\n", smc_id);
|
||||
SMC_RET1(handle, ret);
|
||||
}
|
||||
|
||||
/* Define a runtime service descriptor for fast SMC calls */
|
||||
DECLARE_RT_SVC(
|
||||
mtk_smc_handler,
|
||||
OEN_SIP_START,
|
||||
OEN_SIP_END,
|
||||
SMC_TYPE_FAST,
|
||||
NULL,
|
||||
mtk_smc_handler
|
||||
);
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2019, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <lib/bl_aux_params/bl_aux_params.h>
|
||||
#include <common/debug.h>
|
||||
#include <plat_params.h>
|
||||
#include <string.h>
|
||||
|
||||
static struct bl_aux_gpio_info rst_gpio;
|
||||
|
||||
struct bl_aux_gpio_info *plat_get_mtk_gpio_reset(void)
|
||||
{
|
||||
return &rst_gpio;
|
||||
}
|
||||
|
||||
static bool mtk_aux_param_handler(struct bl_aux_param_header *param)
|
||||
{
|
||||
/* Store platform parameters for later processing if needed. */
|
||||
switch (param->type) {
|
||||
case BL_AUX_PARAM_MTK_RESET_GPIO:
|
||||
rst_gpio = ((struct bl_aux_param_gpio *)param)->gpio;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void params_early_setup(u_register_t plat_param_from_bl2)
|
||||
{
|
||||
bl_aux_params_parse(plat_param_from_bl2, mtk_aux_param_handler);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright (c) 2019, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef PLAT_PARAMS_H
|
||||
#define PLAT_PARAMS_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <export/plat/mediatek/common/plat_params_exp.h>
|
||||
|
||||
struct bl_aux_gpio_info *plat_get_mtk_gpio_reset(void);
|
||||
void params_early_setup(u_register_t plat_param_from_bl2);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,15 @@
|
||||
#
|
||||
# Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
LOCAL_DIR := $(call GET_LOCAL_DIR)
|
||||
|
||||
MODULE := mtk_common
|
||||
|
||||
LOCAL_SRCS-y := ${LOCAL_DIR}/mtk_bl31_setup.c
|
||||
LOCAL_SRCS-y += ${LOCAL_DIR}/mtk_smc_handlers.c
|
||||
LOCAL_SRCS-$(MTK_SIP_KERNEL_BOOT_ENABLE) += ${LOCAL_DIR}/cold_boot.c
|
||||
|
||||
$(eval $(call MAKE_LOCALS,$(LOCAL_SRCS-y),$(MTK_BL)))
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <common/debug.h>
|
||||
|
||||
#include <audio.h>
|
||||
|
||||
#include <mtk_sip_svc.h>
|
||||
|
||||
#define MODULE_TAG "[AUDIO]"
|
||||
|
||||
static u_register_t audio_smc_handler(u_register_t x1, u_register_t x2,
|
||||
u_register_t x3, u_register_t x4,
|
||||
void *handle, struct smccc_res *smccc_ret)
|
||||
{
|
||||
uint32_t request_ops;
|
||||
int ret;
|
||||
|
||||
request_ops = (uint32_t)x1;
|
||||
|
||||
switch (request_ops) {
|
||||
case MTK_AUDIO_SMC_OP_DOMAIN_SIDEBANDS:
|
||||
ret = set_audio_domain_sidebands();
|
||||
break;
|
||||
default:
|
||||
ERROR("%s: %s: Unsupported request_ops %x\n",
|
||||
MODULE_TAG, __func__, request_ops);
|
||||
ret = -EIO;
|
||||
break;
|
||||
}
|
||||
|
||||
VERBOSE("%s: %s, request_ops = %x, ret = %d\n",
|
||||
MODULE_TAG, __func__, request_ops, ret);
|
||||
return ret;
|
||||
}
|
||||
/* Register SiP SMC service */
|
||||
DECLARE_SMC_HANDLER(MTK_SIP_AUDIO_CONTROL, audio_smc_handler);
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef AUDIO_H
|
||||
#define AUDIO_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <lib/mmio.h>
|
||||
|
||||
enum mtk_audio_smc_call_op {
|
||||
MTK_AUDIO_SMC_OP_INIT = 0,
|
||||
MTK_AUDIO_SMC_OP_DRAM_REQUEST,
|
||||
MTK_AUDIO_SMC_OP_DRAM_RELEASE,
|
||||
MTK_AUDIO_SMC_OP_SRAM_REQUEST,
|
||||
MTK_AUDIO_SMC_OP_SRAM_RELEASE,
|
||||
MTK_AUDIO_SMC_OP_ADSP_REQUEST,
|
||||
MTK_AUDIO_SMC_OP_ADSP_RELEASE,
|
||||
MTK_AUDIO_SMC_OP_DOMAIN_SIDEBANDS,
|
||||
MTK_AUDIO_SMC_OP_BTCVSD_WRITE,
|
||||
MTK_AUDIO_SMC_OP_BTCVSD_UPDATE_CTRL_CLEAR,
|
||||
MTK_AUDIO_SMC_OP_BTCVSD_UPDATE_CTRL_UNDERFLOW,
|
||||
MTK_AUDIO_SMC_OP_NUM,
|
||||
};
|
||||
|
||||
int32_t set_audio_domain_sidebands(void);
|
||||
|
||||
#endif /* AUDIO_H */
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Mediatek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <common/debug.h>
|
||||
|
||||
#include <audio.h>
|
||||
#include <mt_audio_private.h>
|
||||
#include <mtk_mmap_pool.h>
|
||||
#include <platform_def.h>
|
||||
#include <spm_reg.h>
|
||||
|
||||
#define MODULE_TAG "[AUDIO_DOMAIN]"
|
||||
|
||||
int32_t set_audio_domain_sidebands(void)
|
||||
{
|
||||
uint32_t val = mmio_read_32(PWR_STATUS);
|
||||
|
||||
if ((val & BIT(SPM_PWR_STATUS_AUDIO_BIT)) == 0) {
|
||||
ERROR("%s: %s, pwr_status=0x%x, w/o [%d]AUDIO!\n",
|
||||
MODULE_TAG, __func__, val, SPM_PWR_STATUS_AUDIO_BIT);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
mmio_write_32(AFE_SE_SECURE_CON, 0x0);
|
||||
|
||||
mmio_write_32(AFE_SECURE_SIDEBAND0, 0x0);
|
||||
mmio_write_32(AFE_SECURE_SIDEBAND1, 0x0);
|
||||
mmio_write_32(AFE_SECURE_SIDEBAND2, 0x0);
|
||||
mmio_write_32(AFE_SECURE_SIDEBAND3, 0x0);
|
||||
|
||||
VERBOSE("%s: %s, SE_SECURE_CON=0x%x, SIDEBAND0/1/2/3=0x%x/0x%x/0x%x/0x%x\n",
|
||||
MODULE_TAG, __func__,
|
||||
mmio_read_32(AFE_SE_SECURE_CON),
|
||||
mmio_read_32(AFE_SECURE_SIDEBAND0),
|
||||
mmio_read_32(AFE_SECURE_SIDEBAND1),
|
||||
mmio_read_32(AFE_SECURE_SIDEBAND2),
|
||||
mmio_read_32(AFE_SECURE_SIDEBAND3));
|
||||
|
||||
return 0;
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef MT_AUDIO_PRIVATE_H
|
||||
#define MT_AUDIO_PRIVATE_H
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
#define AFE_SE_SECURE_CON (AUDIO_BASE + 0x17a8)
|
||||
#define AFE_SECURE_SIDEBAND0 (AUDIO_BASE + 0x1908)
|
||||
#define AFE_SECURE_SIDEBAND1 (AUDIO_BASE + 0x190c)
|
||||
#define AFE_SECURE_SIDEBAND2 (AUDIO_BASE + 0x1910)
|
||||
#define AFE_SECURE_SIDEBAND3 (AUDIO_BASE + 0x1914)
|
||||
|
||||
#define SPM_PWR_STATUS_AUDIO_BIT (6)
|
||||
|
||||
#endif /* MT_AUDIO_PRIVATE_H */
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
#
|
||||
# Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
LOCAL_DIR := $(call GET_LOCAL_DIR)
|
||||
|
||||
MODULE := audio_${MTK_SOC}
|
||||
|
||||
LOCAL_SRCS-y := ${LOCAL_DIR}/audio_domain.c
|
||||
|
||||
$(eval $(call MAKE_MODULE,$(MODULE),$(LOCAL_SRCS-y),$(MTK_BL)))
|
||||
@@ -0,0 +1,19 @@
|
||||
#
|
||||
# Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
LOCAL_DIR := $(call GET_LOCAL_DIR)
|
||||
|
||||
MODULE := audio
|
||||
|
||||
LOCAL_SRCS-y := ${LOCAL_DIR}/audio.c
|
||||
|
||||
PLAT_INCLUDES += -I${LOCAL_DIR}
|
||||
PLAT_INCLUDES += -I${LOCAL_DIR}/$(MTK_SOC)
|
||||
|
||||
SUB_RULES-y:= ${LOCAL_DIR}/${MTK_SOC}
|
||||
|
||||
$(eval $(call MAKE_MODULE,$(MODULE),$(LOCAL_SRCS-y),$(MTK_BL)))
|
||||
$(eval $(call INCLUDE_MAKEFILE,$(SUB_RULES-y)))
|
||||
@@ -0,0 +1,549 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2022, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <common/debug.h>
|
||||
#include <drivers/arm/gic_common.h>
|
||||
#include <lib/mmio.h>
|
||||
|
||||
#include <mt_cirq.h>
|
||||
#include <mt_gic_v3.h>
|
||||
|
||||
static struct cirq_events cirq_all_events = {
|
||||
.spi_start = CIRQ_SPI_START,
|
||||
};
|
||||
static uint32_t already_cloned;
|
||||
/*
|
||||
* mt_irq_mask_restore: restore all interrupts
|
||||
* @mask: pointer to struct mtk_irq_mask for storing the original mask value.
|
||||
* Return 0 for success; return negative values for failure.
|
||||
* (This is ONLY used for the idle current measurement by the factory mode.)
|
||||
*/
|
||||
int mt_irq_mask_restore(struct mtk_irq_mask *mask)
|
||||
{
|
||||
if (mask == NULL) {
|
||||
return -1;
|
||||
}
|
||||
if (mask->header != IRQ_MASK_HEADER) {
|
||||
return -1;
|
||||
}
|
||||
if (mask->footer != IRQ_MASK_FOOTER) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x4),
|
||||
mask->mask1);
|
||||
mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x8),
|
||||
mask->mask2);
|
||||
mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0xc),
|
||||
mask->mask3);
|
||||
mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x10),
|
||||
mask->mask4);
|
||||
mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x14),
|
||||
mask->mask5);
|
||||
mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x18),
|
||||
mask->mask6);
|
||||
mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x1c),
|
||||
mask->mask7);
|
||||
mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x20),
|
||||
mask->mask8);
|
||||
mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x24),
|
||||
mask->mask9);
|
||||
mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x28),
|
||||
mask->mask10);
|
||||
mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x2c),
|
||||
mask->mask11);
|
||||
mmio_write_32((BASE_GICD_BASE + GICD_ISENABLER + 0x30),
|
||||
mask->mask12);
|
||||
/* make sure dist changes happen */
|
||||
dsb();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* mt_irq_mask_all: disable all interrupts
|
||||
* @mask: pointer to struct mtk_irq_mask for storing the original mask value.
|
||||
* Return 0 for success; return negative values for failure.
|
||||
* (This is ONLY used for the idle current measurement by the factory mode.)
|
||||
*/
|
||||
int mt_irq_mask_all(struct mtk_irq_mask *mask)
|
||||
{
|
||||
if (mask != NULL) {
|
||||
/* for SPI */
|
||||
mask->mask1 = mmio_read_32((BASE_GICD_BASE +
|
||||
GICD_ISENABLER + 0x4));
|
||||
mask->mask2 = mmio_read_32((BASE_GICD_BASE +
|
||||
GICD_ISENABLER + 0x8));
|
||||
mask->mask3 = mmio_read_32((BASE_GICD_BASE +
|
||||
GICD_ISENABLER + 0xc));
|
||||
mask->mask4 = mmio_read_32((BASE_GICD_BASE +
|
||||
GICD_ISENABLER + 0x10));
|
||||
mask->mask5 = mmio_read_32((BASE_GICD_BASE +
|
||||
GICD_ISENABLER + 0x14));
|
||||
mask->mask6 = mmio_read_32((BASE_GICD_BASE +
|
||||
GICD_ISENABLER + 0x18));
|
||||
mask->mask7 = mmio_read_32((BASE_GICD_BASE +
|
||||
GICD_ISENABLER + 0x1c));
|
||||
mask->mask8 = mmio_read_32((BASE_GICD_BASE +
|
||||
GICD_ISENABLER + 0x20));
|
||||
mask->mask9 = mmio_read_32((BASE_GICD_BASE +
|
||||
GICD_ISENABLER + 0x24));
|
||||
mask->mask10 = mmio_read_32((BASE_GICD_BASE +
|
||||
GICD_ISENABLER + 0x28));
|
||||
mask->mask11 = mmio_read_32((BASE_GICD_BASE +
|
||||
GICD_ISENABLER + 0x2c));
|
||||
mask->mask12 = mmio_read_32((BASE_GICD_BASE +
|
||||
GICD_ISENABLER + 0x30));
|
||||
|
||||
/* for SPI */
|
||||
mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x4),
|
||||
0xFFFFFFFF);
|
||||
mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x8),
|
||||
0xFFFFFFFF);
|
||||
mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0xC),
|
||||
0xFFFFFFFF);
|
||||
mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x10),
|
||||
0xFFFFFFFF);
|
||||
mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x14),
|
||||
0xFFFFFFFF);
|
||||
mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x18),
|
||||
0xFFFFFFFF);
|
||||
mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x1C),
|
||||
0xFFFFFFFF);
|
||||
mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x20),
|
||||
0xFFFFFFFF);
|
||||
mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x24),
|
||||
0xFFFFFFFF);
|
||||
mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x28),
|
||||
0xFFFFFFFF);
|
||||
mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x2c),
|
||||
0xFFFFFFFF);
|
||||
mmio_write_32((BASE_GICD_BASE + GICD_ICENABLER + 0x30),
|
||||
0xFFFFFFFF);
|
||||
/* make sure distributor changes happen */
|
||||
dsb();
|
||||
|
||||
mask->header = IRQ_MASK_HEADER;
|
||||
mask->footer = IRQ_MASK_FOOTER;
|
||||
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t mt_irq_get_pol(uint32_t irq)
|
||||
{
|
||||
#ifdef CIRQ_WITH_POLARITY
|
||||
uint32_t reg;
|
||||
uint32_t base = INT_POL_CTL0;
|
||||
|
||||
if (irq < 32U) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
reg = ((irq - 32U) / 32U);
|
||||
|
||||
return mmio_read_32(base + reg * 4U);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
unsigned int mt_irq_get_sens(unsigned int irq)
|
||||
{
|
||||
unsigned int config;
|
||||
|
||||
/*
|
||||
* 2'b10 edge
|
||||
* 2'b01 level
|
||||
*/
|
||||
config = mmio_read_32(MT_GIC_BASE + GICD_ICFGR + (irq / 16U) * 4U);
|
||||
config = (config >> (irq % 16U) * 2U) & 0x3;
|
||||
|
||||
return config;
|
||||
}
|
||||
|
||||
static void collect_all_wakeup_events(void)
|
||||
{
|
||||
unsigned int i;
|
||||
uint32_t gic_irq;
|
||||
uint32_t cirq;
|
||||
uint32_t cirq_reg;
|
||||
uint32_t cirq_offset;
|
||||
uint32_t mask;
|
||||
uint32_t pol_mask;
|
||||
uint32_t irq_offset;
|
||||
uint32_t irq_mask;
|
||||
|
||||
if ((cirq_all_events.wakeup_events == NULL) ||
|
||||
cirq_all_events.num_of_events == 0U) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0U; i < cirq_all_events.num_of_events; i++) {
|
||||
if (cirq_all_events.wakeup_events[i] > 0U) {
|
||||
gic_irq = cirq_all_events.wakeup_events[i];
|
||||
cirq = gic_irq - cirq_all_events.spi_start - 32U;
|
||||
cirq_reg = cirq / 32U;
|
||||
cirq_offset = cirq % 32U;
|
||||
mask = 0x1 << cirq_offset;
|
||||
irq_offset = gic_irq % 32U;
|
||||
irq_mask = 0x1 << irq_offset;
|
||||
/*
|
||||
* CIRQ default masks all
|
||||
*/
|
||||
cirq_all_events.table[cirq_reg].mask |= mask;
|
||||
/*
|
||||
* CIRQ default pol is low
|
||||
*/
|
||||
pol_mask = mt_irq_get_pol(
|
||||
cirq_all_events.wakeup_events[i])
|
||||
& irq_mask;
|
||||
/*
|
||||
* 0 means rising
|
||||
*/
|
||||
if (pol_mask == 0U) {
|
||||
cirq_all_events.table[cirq_reg].pol |= mask;
|
||||
}
|
||||
/*
|
||||
* CIRQ could monitor edge/level trigger
|
||||
* cirq register (0: edge, 1: level)
|
||||
*/
|
||||
if (mt_irq_get_sens(cirq_all_events.wakeup_events[i])
|
||||
== SENS_EDGE) {
|
||||
cirq_all_events.table[cirq_reg].sen |= mask;
|
||||
}
|
||||
|
||||
cirq_all_events.table[cirq_reg].used = 1U;
|
||||
cirq_all_events.table[cirq_reg].reg_num = cirq_reg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* mt_cirq_set_pol: Set the polarity for the specified SYS_CIRQ number.
|
||||
* @cirq_num: the SYS_CIRQ number to set
|
||||
* @pol: polarity to set
|
||||
* @return:
|
||||
* 0: set pol success
|
||||
* -1: cirq num is out of range
|
||||
*/
|
||||
#ifdef CIRQ_WITH_POLARITY
|
||||
static int mt_cirq_set_pol(uint32_t cirq_num, uint32_t pol)
|
||||
{
|
||||
uint32_t base;
|
||||
uint32_t bit = 1U << (cirq_num % 32U);
|
||||
|
||||
if (cirq_num >= CIRQ_IRQ_NUM) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pol == MT_CIRQ_POL_NEG) {
|
||||
base = (cirq_num / 32U) * 4U + CIRQ_POL_CLR_BASE;
|
||||
} else if (pol == MT_CIRQ_POL_POS) {
|
||||
base = (cirq_num / 32U) * 4U + CIRQ_POL_SET_BASE;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
mmio_write_32(base, bit);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* mt_cirq_mask: Mask the specified SYS_CIRQ.
|
||||
* @cirq_num: the SYS_CIRQ number to mask
|
||||
* @return:
|
||||
* 0: mask success
|
||||
* -1: cirq num is out of range
|
||||
*/
|
||||
static int mt_cirq_mask(uint32_t cirq_num)
|
||||
{
|
||||
uint32_t bit = 1U << (cirq_num % 32U);
|
||||
|
||||
if (cirq_num >= CIRQ_IRQ_NUM) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
mmio_write_32((cirq_num / 32U) * 4U + CIRQ_MASK_SET_BASE, bit);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* mt_cirq_unmask: Unmask the specified SYS_CIRQ.
|
||||
* @cirq_num: the SYS_CIRQ number to unmask
|
||||
* @return:
|
||||
* 0: umask success
|
||||
* -1: cirq num is out of range
|
||||
*/
|
||||
static int mt_cirq_unmask(uint32_t cirq_num)
|
||||
{
|
||||
uint32_t bit = 1U << (cirq_num % 32U);
|
||||
|
||||
if (cirq_num >= CIRQ_IRQ_NUM) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
mmio_write_32((cirq_num / 32U) * 4U + CIRQ_MASK_CLR_BASE, bit);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t mt_irq_get_en(uint32_t irq)
|
||||
{
|
||||
uint32_t addr, st, val;
|
||||
|
||||
addr = BASE_GICD_BASE + GICD_ISENABLER + (irq / 32U) * 4U;
|
||||
st = mmio_read_32(addr);
|
||||
|
||||
val = (st >> (irq % 32U)) & 1U;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static void __cirq_fast_clone(void)
|
||||
{
|
||||
struct cirq_reg *reg;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0U; i < CIRQ_REG_NUM ; ++i) {
|
||||
uint32_t cirq_bit;
|
||||
|
||||
reg = &cirq_all_events.table[i];
|
||||
|
||||
if (reg->used == 0U) {
|
||||
continue;
|
||||
}
|
||||
|
||||
mmio_write_32(CIRQ_SENS_CLR_BASE + (reg->reg_num * 4U),
|
||||
reg->sen);
|
||||
|
||||
for (cirq_bit = 0U; cirq_bit < 32U; ++cirq_bit) {
|
||||
uint32_t val, cirq_id;
|
||||
uint32_t gic_id;
|
||||
#ifdef CIRQ_WITH_POLARITY
|
||||
uint32_t gic_bit, pol;
|
||||
#endif
|
||||
uint32_t en;
|
||||
|
||||
val = ((1U << cirq_bit) & reg->mask);
|
||||
|
||||
if (val == 0U) {
|
||||
continue;
|
||||
}
|
||||
|
||||
cirq_id = (reg->reg_num << 5U) + cirq_bit;
|
||||
gic_id = CIRQ_TO_IRQ_NUM(cirq_id);
|
||||
#ifdef CIRQ_WITH_POLARITY
|
||||
gic_bit = (0x1U << ((gic_id - 32U) % 32U));
|
||||
pol = mt_irq_get_pol(gic_id) & gic_bit;
|
||||
if (pol != 0U) {
|
||||
mt_cirq_set_pol(cirq_id, MT_CIRQ_POL_NEG);
|
||||
} else {
|
||||
mt_cirq_set_pol(cirq_id, MT_CIRQ_POL_POS);
|
||||
}
|
||||
#endif
|
||||
en = mt_irq_get_en(gic_id);
|
||||
if (en == 1U) {
|
||||
mt_cirq_unmask(cirq_id);
|
||||
} else {
|
||||
mt_cirq_mask(cirq_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void cirq_fast_clone(void)
|
||||
{
|
||||
if (already_cloned == 0U) {
|
||||
collect_all_wakeup_events();
|
||||
already_cloned = 1U;
|
||||
}
|
||||
__cirq_fast_clone();
|
||||
}
|
||||
|
||||
void set_wakeup_sources(uint32_t *list, uint32_t num_of_events)
|
||||
{
|
||||
cirq_all_events.num_of_events = num_of_events;
|
||||
cirq_all_events.wakeup_events = list;
|
||||
}
|
||||
/*
|
||||
* mt_cirq_clone_gic: Copy the setting from GIC to SYS_CIRQ
|
||||
*/
|
||||
void mt_cirq_clone_gic(void)
|
||||
{
|
||||
cirq_fast_clone();
|
||||
}
|
||||
|
||||
uint32_t mt_irq_get_pending_vec(uint32_t start_irq)
|
||||
{
|
||||
uint32_t base = 0U;
|
||||
uint32_t pending_vec = 0U;
|
||||
uint32_t reg = start_irq / 32U;
|
||||
uint32_t LSB_num, MSB_num;
|
||||
uint32_t LSB_vec, MSB_vec;
|
||||
|
||||
base = BASE_GICD_BASE;
|
||||
|
||||
/* if start_irq is not aligned 32, do some assembling */
|
||||
MSB_num = start_irq % 32U;
|
||||
if (MSB_num != 0U) {
|
||||
LSB_num = 32U - MSB_num;
|
||||
LSB_vec = mmio_read_32(base + GICD_ISPENDR +
|
||||
reg * 4U) >> MSB_num;
|
||||
MSB_vec = mmio_read_32(base + GICD_ISPENDR +
|
||||
(reg + 1U) * 4U) << LSB_num;
|
||||
pending_vec = MSB_vec | LSB_vec;
|
||||
} else {
|
||||
pending_vec = mmio_read_32(base + GICD_ISPENDR + reg * 4);
|
||||
}
|
||||
|
||||
return pending_vec;
|
||||
}
|
||||
|
||||
static int mt_cirq_get_mask_vec(unsigned int i)
|
||||
{
|
||||
return mmio_read_32((i * 4U) + CIRQ_MASK_BASE);
|
||||
}
|
||||
|
||||
/*
|
||||
* mt_cirq_ack_all: Ack all the interrupt on SYS_CIRQ
|
||||
*/
|
||||
void mt_cirq_ack_all(void)
|
||||
{
|
||||
uint32_t ack_vec, pend_vec, mask_vec;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < CIRQ_CTRL_REG_NUM; i++) {
|
||||
/*
|
||||
* if a irq is pending & not masked, don't ack it
|
||||
* , since cirq start irq might not be 32 aligned with gic,
|
||||
* need an exotic API to get proper vector of pending irq
|
||||
*/
|
||||
pend_vec = mt_irq_get_pending_vec(CIRQ_SPI_START
|
||||
+ (i + 1U) * 32U);
|
||||
mask_vec = mt_cirq_get_mask_vec(i);
|
||||
/* those should be acked are: "not (pending & not masked)",
|
||||
*/
|
||||
ack_vec = (~pend_vec) | mask_vec;
|
||||
mmio_write_32(CIRQ_ACK_BASE + (i * 4U), ack_vec);
|
||||
}
|
||||
|
||||
/*
|
||||
* make sure all cirq setting take effect
|
||||
* before doing other things
|
||||
*/
|
||||
dsb();
|
||||
}
|
||||
/*
|
||||
* mt_cirq_enable: Enable SYS_CIRQ
|
||||
*/
|
||||
void mt_cirq_enable(void)
|
||||
{
|
||||
uint32_t st;
|
||||
|
||||
/* level only */
|
||||
mt_cirq_ack_all();
|
||||
|
||||
st = mmio_read_32(CIRQ_CON);
|
||||
/*
|
||||
* CIRQ could monitor edge/level trigger
|
||||
*/
|
||||
st |= (CIRQ_CON_EN << CIRQ_CON_EN_BITS);
|
||||
|
||||
mmio_write_32(CIRQ_CON, (st & CIRQ_CON_BITS_MASK));
|
||||
}
|
||||
|
||||
/*
|
||||
* mt_cirq_disable: Disable SYS_CIRQ
|
||||
*/
|
||||
void mt_cirq_disable(void)
|
||||
{
|
||||
uint32_t st;
|
||||
|
||||
st = mmio_read_32(CIRQ_CON);
|
||||
st &= ~(CIRQ_CON_EN << CIRQ_CON_EN_BITS);
|
||||
mmio_write_32(CIRQ_CON, (st & CIRQ_CON_BITS_MASK));
|
||||
}
|
||||
|
||||
void mt_irq_unmask_for_sleep_ex(uint32_t irq)
|
||||
{
|
||||
uint32_t mask;
|
||||
|
||||
mask = 1U << (irq % 32U);
|
||||
|
||||
mmio_write_32(BASE_GICD_BASE + GICD_ISENABLER +
|
||||
((irq / 32U) * 4U), mask);
|
||||
}
|
||||
|
||||
void mt_cirq_mask_all(void)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0U; i < CIRQ_CTRL_REG_NUM; i++) {
|
||||
mmio_write_32(CIRQ_MASK_SET_BASE + (i * 4U), 0xFFFFFFFF);
|
||||
}
|
||||
dsb();
|
||||
}
|
||||
|
||||
static void cirq_fast_sw_flush(void)
|
||||
{
|
||||
struct cirq_reg *reg;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0U; i < CIRQ_REG_NUM ; ++i) {
|
||||
uint32_t cirq_bit;
|
||||
|
||||
reg = &cirq_all_events.table[i];
|
||||
|
||||
if (reg->used == 0U) {
|
||||
continue;
|
||||
}
|
||||
|
||||
reg->pending = mmio_read_32(CIRQ_STA_BASE +
|
||||
(reg->reg_num << 2U));
|
||||
reg->pending &= reg->mask;
|
||||
|
||||
for (cirq_bit = 0U; cirq_bit < 32U; ++cirq_bit) {
|
||||
uint32_t val, cirq_id;
|
||||
|
||||
val = (1U << cirq_bit) & reg->pending;
|
||||
if (val == 0U) {
|
||||
continue;
|
||||
}
|
||||
|
||||
cirq_id = (reg->reg_num << 5U) + cirq_bit;
|
||||
mt_irq_set_pending(CIRQ_TO_IRQ_NUM(cirq_id));
|
||||
if (CIRQ_TO_IRQ_NUM(cirq_id) == MD_WDT_IRQ_BIT_ID) {
|
||||
INFO("Set MD_WDT_IRQ pending in %s\n",
|
||||
__func__);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* mt_cirq_disable: Flush interrupt from SYS_CIRQ to GIC
|
||||
*/
|
||||
void mt_cirq_flush(void)
|
||||
{
|
||||
cirq_fast_sw_flush();
|
||||
mt_cirq_mask_all();
|
||||
mt_cirq_ack_all();
|
||||
}
|
||||
|
||||
void mt_cirq_sw_reset(void)
|
||||
{
|
||||
uint32_t st;
|
||||
|
||||
st = mmio_read_32(CIRQ_CON);
|
||||
st |= (CIRQ_SW_RESET << CIRQ_CON_SW_RST_BITS);
|
||||
mmio_write_32(CIRQ_CON, st);
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2022, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef PLAT_MT_CIRQ_H
|
||||
#define PLAT_MT_CIRQ_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
enum {
|
||||
IRQ_MASK_HEADER = 0xF1F1F1F1,
|
||||
IRQ_MASK_FOOTER = 0xF2F2F2F2
|
||||
};
|
||||
|
||||
struct mtk_irq_mask {
|
||||
uint32_t header; /* for error checking */
|
||||
uint32_t mask0;
|
||||
uint32_t mask1;
|
||||
uint32_t mask2;
|
||||
uint32_t mask3;
|
||||
uint32_t mask4;
|
||||
uint32_t mask5;
|
||||
uint32_t mask6;
|
||||
uint32_t mask7;
|
||||
uint32_t mask8;
|
||||
uint32_t mask9;
|
||||
uint32_t mask10;
|
||||
uint32_t mask11;
|
||||
uint32_t mask12;
|
||||
uint32_t footer; /* for error checking */
|
||||
};
|
||||
|
||||
/*
|
||||
* Define hardware register
|
||||
*/
|
||||
#define CIRQ_STA_BASE (SYS_CIRQ_BASE + U(0x000))
|
||||
#define CIRQ_ACK_BASE (SYS_CIRQ_BASE + U(0x080))
|
||||
#define CIRQ_MASK_BASE (SYS_CIRQ_BASE + U(0x100))
|
||||
#define CIRQ_MASK_SET_BASE (SYS_CIRQ_BASE + U(0x180))
|
||||
#define CIRQ_MASK_CLR_BASE (SYS_CIRQ_BASE + U(0x200))
|
||||
#define CIRQ_SENS_BASE (SYS_CIRQ_BASE + U(0x280))
|
||||
#define CIRQ_SENS_SET_BASE (SYS_CIRQ_BASE + U(0x300))
|
||||
#define CIRQ_SENS_CLR_BASE (SYS_CIRQ_BASE + U(0x380))
|
||||
#define CIRQ_POL_BASE (SYS_CIRQ_BASE + U(0x400))
|
||||
#define CIRQ_POL_SET_BASE (SYS_CIRQ_BASE + U(0x480))
|
||||
#define CIRQ_POL_CLR_BASE (SYS_CIRQ_BASE + U(0x500))
|
||||
#define CIRQ_CON (SYS_CIRQ_BASE + U(0x600))
|
||||
|
||||
/*
|
||||
* Register placement
|
||||
*/
|
||||
#define CIRQ_CON_EN_BITS U(0)
|
||||
#define CIRQ_CON_EDGE_ONLY_BITS U(1)
|
||||
#define CIRQ_CON_FLUSH_BITS U(2)
|
||||
#define CIRQ_CON_SW_RST_BITS U(20)
|
||||
#define CIRQ_CON_EVENT_BITS U(31)
|
||||
#define CIRQ_CON_BITS_MASK U(0x7)
|
||||
|
||||
/*
|
||||
* Register setting
|
||||
*/
|
||||
#define CIRQ_CON_EN U(0x1)
|
||||
#define CIRQ_CON_EDGE_ONLY U(0x1)
|
||||
#define CIRQ_CON_FLUSH U(0x1)
|
||||
#define CIRQ_SW_RESET U(0x1)
|
||||
|
||||
/*
|
||||
* Define constant
|
||||
*/
|
||||
#define CIRQ_CTRL_REG_NUM ((CIRQ_IRQ_NUM + 31U) / 32U)
|
||||
|
||||
#define MT_CIRQ_POL_NEG U(0)
|
||||
#define MT_CIRQ_POL_POS U(1)
|
||||
|
||||
#define IRQ_TO_CIRQ_NUM(irq) ((irq) - (32U + CIRQ_SPI_START))
|
||||
#define CIRQ_TO_IRQ_NUM(cirq) ((cirq) + (32U + CIRQ_SPI_START))
|
||||
|
||||
/* GIC sensitive */
|
||||
#define SENS_EDGE U(0x2)
|
||||
#define SENS_LEVEL U(0x1)
|
||||
|
||||
|
||||
/*
|
||||
* Define function prototypes.
|
||||
*/
|
||||
int mt_cirq_test(void);
|
||||
void mt_cirq_dump_reg(void);
|
||||
int mt_irq_mask_restore(struct mtk_irq_mask *mask);
|
||||
int mt_irq_mask_all(struct mtk_irq_mask *mask);
|
||||
void mt_cirq_clone_gic(void);
|
||||
void mt_cirq_enable(void);
|
||||
void mt_cirq_flush(void);
|
||||
void mt_cirq_disable(void);
|
||||
void mt_irq_unmask_for_sleep_ex(uint32_t irq);
|
||||
void set_wakeup_sources(uint32_t *list, uint32_t num_of_events);
|
||||
void mt_cirq_sw_reset(void);
|
||||
|
||||
struct cirq_reg {
|
||||
uint32_t reg_num;
|
||||
uint32_t used;
|
||||
uint32_t mask;
|
||||
uint32_t pol;
|
||||
uint32_t sen;
|
||||
uint32_t pending;
|
||||
uint32_t the_link;
|
||||
};
|
||||
|
||||
struct cirq_events {
|
||||
uint32_t num_reg;
|
||||
uint32_t spi_start;
|
||||
uint32_t num_of_events;
|
||||
uint32_t *wakeup_events;
|
||||
struct cirq_reg table[CIRQ_REG_NUM];
|
||||
uint32_t dist_base;
|
||||
uint32_t cirq_base;
|
||||
uint32_t used_reg_head;
|
||||
};
|
||||
|
||||
#endif /* PLAT_MT_CIRQ_H */
|
||||
@@ -0,0 +1,14 @@
|
||||
#
|
||||
# Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
LOCAL_DIR := $(call GET_LOCAL_DIR)
|
||||
|
||||
MODULE := cirq
|
||||
LOCAL_SRCS-y := $(LOCAL_DIR)/mt_cirq.c
|
||||
|
||||
PLAT_INCLUDES += -I${LOCAL_DIR}
|
||||
|
||||
$(eval $(call MAKE_MODULE,$(MODULE),$(LOCAL_SRCS-y),$(MTK_BL)))
|
||||
+466
@@ -0,0 +1,466 @@
|
||||
/*
|
||||
* Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <lib/spinlock.h>
|
||||
|
||||
#include <lib/mtk_init/mtk_init.h>
|
||||
#include <lib/pm/mtk_pm.h>
|
||||
#include "mt_cpu_pm.h"
|
||||
#include "mt_cpu_pm_cpc.h"
|
||||
#include "mt_cpu_pm_mbox.h"
|
||||
#include <mt_lp_rm.h>
|
||||
#include "mt_smp.h"
|
||||
#include <mtk_mmap_pool.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
/*
|
||||
* The locker must use the bakery locker when cache turns off.
|
||||
* Using spin_lock will gain better performance.
|
||||
*/
|
||||
#ifdef MT_CPU_PM_USING_BAKERY_LOCK
|
||||
DEFINE_BAKERY_LOCK(mt_cpu_pm_lock);
|
||||
#define plat_cpu_pm_lock_init() bakery_lock_init(&mt_cpu_pm_lock)
|
||||
#define plat_cpu_pm_lock() bakery_lock_get(&mt_cpu_pm_lock)
|
||||
#define plat_cpu_pm_unlock() bakery_lock_release(&mt_cpu_pm_lock)
|
||||
#else
|
||||
spinlock_t mt_cpu_pm_lock;
|
||||
#define plat_cpu_pm_lock_init()
|
||||
#define plat_cpu_pm_lock() spin_lock(&mt_cpu_pm_lock)
|
||||
#define plat_cpu_pm_unlock() spin_unlock(&mt_cpu_pm_lock)
|
||||
#endif
|
||||
|
||||
enum mt_pwr_node {
|
||||
MT_PWR_NONMCUSYS = 0,
|
||||
MT_PWR_MCUSYS_PDN,
|
||||
MT_PWR_SUSPEND,
|
||||
MT_PWR_SYSTEM_MEM,
|
||||
MT_PWR_SYSTEM_PLL,
|
||||
MT_PWR_SYSTEM_BUS,
|
||||
MT_PWR_MAX,
|
||||
};
|
||||
|
||||
#define CPU_PM_DEPD_INIT BIT(0)
|
||||
#define CPU_PM_DEPD_READY BIT(1)
|
||||
#define CPU_PM_PLAT_READY BIT(2)
|
||||
|
||||
#ifdef CPU_PM_TINYSYS_SUPPORT
|
||||
#define CPU_PM_INIT_READY (CPU_PM_DEPD_INIT | CPU_PM_DEPD_READY)
|
||||
#define CPU_PM_LP_READY (CPU_PM_INIT_READY | CPU_PM_PLAT_READY)
|
||||
#else
|
||||
#define CPU_PM_LP_READY (CPU_PM_PLAT_READY)
|
||||
#endif
|
||||
|
||||
#if CONFIG_MTK_PM_SUPPORT
|
||||
|
||||
#if CONFIG_MTK_CPU_SUSPEND_EN || CONFIG_MTK_SMP_EN
|
||||
static void cpupm_cpu_resume_common(const struct mtk_cpupm_pwrstate *state)
|
||||
{
|
||||
CPU_PM_ASSERT(state != NULL);
|
||||
mtk_cpc_core_on_hint_clr(state->info.cpuid);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_MTK_SMP_EN
|
||||
static int cpupm_cpu_pwr_on_prepare(unsigned int cpu, uintptr_t entry)
|
||||
{
|
||||
struct cpu_pwr_ctrl pwr_ctrl;
|
||||
|
||||
PER_CPU_PWR_CTRL(pwr_ctrl, cpu);
|
||||
mt_smp_core_bootup_address_set(&pwr_ctrl, entry);
|
||||
mt_smp_core_init_arch(0, cpu, 1, &pwr_ctrl);
|
||||
|
||||
return mt_smp_power_core_on(cpu, &pwr_ctrl);
|
||||
}
|
||||
|
||||
static void cpupm_cpu_resume_smp(const struct mtk_cpupm_pwrstate *state)
|
||||
{
|
||||
CPU_PM_ASSERT(state != NULL);
|
||||
|
||||
plat_cpu_pm_lock();
|
||||
mmio_clrbits_32(CPC_MCUSYS_CPC_FLOW_CTRL_CFG,
|
||||
GIC_WAKEUP_IGNORE(state->info.cpuid));
|
||||
plat_cpu_pm_unlock();
|
||||
cpupm_cpu_resume_common(state);
|
||||
}
|
||||
|
||||
static void cpupm_cpu_suspend_smp(const struct mtk_cpupm_pwrstate *state)
|
||||
{
|
||||
struct cpu_pwr_ctrl pwr_ctrl;
|
||||
|
||||
CPU_PM_ASSERT(state != NULL);
|
||||
|
||||
PER_CPU_PWR_CTRL(pwr_ctrl, state->info.cpuid);
|
||||
mt_smp_power_core_off(&pwr_ctrl);
|
||||
mmio_setbits_32(CPC_MCUSYS_CPC_FLOW_CTRL_CFG,
|
||||
GIC_WAKEUP_IGNORE(state->info.cpuid));
|
||||
}
|
||||
|
||||
static void cpupm_smp_init(unsigned int cpu, uintptr_t sec_entrypoint)
|
||||
{
|
||||
unsigned int reg;
|
||||
struct mtk_cpupm_pwrstate state = {
|
||||
.info = {
|
||||
.cpuid = cpu,
|
||||
.mode = MTK_CPU_PM_SMP,
|
||||
},
|
||||
.pwr = {
|
||||
.afflv = 0,
|
||||
.state_id = 0,
|
||||
},
|
||||
};
|
||||
|
||||
reg = mmio_read_32(CPC_MCUSYS_CPC_FLOW_CTRL_CFG);
|
||||
if ((reg & CPC_MCUSYS_CPC_RESET_PWR_ON_EN) != 0) {
|
||||
INFO("[%s:%d][CPU_PM] reset pwr on is enabled then clear it!\n",
|
||||
__func__, __LINE__);
|
||||
mmio_clrbits_32(CPC_MCUSYS_CPC_FLOW_CTRL_CFG, CPC_MCUSYS_CPC_RESET_PWR_ON_EN);
|
||||
}
|
||||
|
||||
cpupm_cpu_pwr_on_prepare(cpu, sec_entrypoint);
|
||||
cpupm_cpu_resume_smp(&state);
|
||||
}
|
||||
|
||||
static struct mtk_cpu_smp_ops cpcv3_2_cpu_smp = {
|
||||
.init = cpupm_smp_init,
|
||||
.cpu_pwr_on_prepare = cpupm_cpu_pwr_on_prepare,
|
||||
.cpu_on = cpupm_cpu_resume_smp,
|
||||
.cpu_off = cpupm_cpu_suspend_smp,
|
||||
};
|
||||
|
||||
#endif /* CONFIG_MTK_SMP_EN */
|
||||
|
||||
#if CONFIG_MTK_CPU_SUSPEND_EN
|
||||
#define CPUPM_READY_MS (40000)
|
||||
#define CPUPM_ARCH_TIME_MS(ms) (ms * 1000 * SYS_COUNTER_FREQ_IN_MHZ)
|
||||
#define CPUPM_BOOTUP_TIME_THR CPUPM_ARCH_TIME_MS(CPUPM_READY_MS)
|
||||
|
||||
static int mt_pwr_nodes[MT_PWR_MAX];
|
||||
static int plat_mt_lp_cpu_rc;
|
||||
static unsigned int cpu_pm_status;
|
||||
static unsigned int plat_prev_stateid;
|
||||
|
||||
static int mcusys_prepare_suspend(const struct mtk_cpupm_pwrstate *state)
|
||||
{
|
||||
unsigned int stateid = state->pwr.state_id;
|
||||
|
||||
if (mtk_cpc_mcusys_off_prepare() != CPC_SUCCESS) {
|
||||
goto mt_pwr_mcusysoff_break;
|
||||
}
|
||||
|
||||
if (!IS_PLAT_SUSPEND_ID(stateid)) {
|
||||
if (mt_pwr_nodes[MT_PWR_SYSTEM_MEM] != 0) {
|
||||
stateid = MT_PLAT_PWR_STATE_SYSTEM_MEM;
|
||||
} else if (mt_pwr_nodes[MT_PWR_SYSTEM_PLL] != 0) {
|
||||
stateid = MT_PLAT_PWR_STATE_SYSTEM_PLL;
|
||||
} else if (mt_pwr_nodes[MT_PWR_SYSTEM_BUS] != 0) {
|
||||
stateid = MT_PLAT_PWR_STATE_SYSTEM_BUS;
|
||||
} else if (mt_pwr_nodes[MT_PWR_SUSPEND] != 0) {
|
||||
stateid = MT_PLAT_PWR_STATE_SUSPEND;
|
||||
} else {
|
||||
stateid = MT_PLAT_PWR_STATE_MCUSYS;
|
||||
}
|
||||
}
|
||||
|
||||
plat_prev_stateid = stateid;
|
||||
plat_mt_lp_cpu_rc = mt_lp_rm_find_and_run_constraint(0, state->info.cpuid, stateid, NULL);
|
||||
|
||||
if (plat_mt_lp_cpu_rc < 0) {
|
||||
goto mt_pwr_mcusysoff_reflect;
|
||||
}
|
||||
|
||||
#ifdef CPU_PM_TINYSYS_SUPPORT
|
||||
mtk_set_cpu_pm_preffered_cpu(state->info.cpuid);
|
||||
#endif
|
||||
return MTK_CPUPM_E_OK;
|
||||
|
||||
mt_pwr_mcusysoff_reflect:
|
||||
mtk_cpc_mcusys_off_reflect();
|
||||
mt_pwr_mcusysoff_break:
|
||||
plat_mt_lp_cpu_rc = -1;
|
||||
|
||||
return MTK_CPUPM_E_FAIL;
|
||||
}
|
||||
|
||||
static int mcusys_prepare_resume(const struct mtk_cpupm_pwrstate *state)
|
||||
{
|
||||
if (plat_mt_lp_cpu_rc < 0) {
|
||||
return MTK_CPUPM_E_FAIL;
|
||||
}
|
||||
|
||||
mt_lp_rm_reset_constraint(plat_mt_lp_cpu_rc, state->info.cpuid, plat_prev_stateid);
|
||||
mtk_cpc_mcusys_off_reflect();
|
||||
return MTK_CPUPM_E_OK;
|
||||
}
|
||||
|
||||
static unsigned int cpupm_do_pstate_off(const mtk_pstate_type psci_state,
|
||||
const struct mtk_cpupm_pwrstate *state)
|
||||
{
|
||||
unsigned int pstate = MT_CPUPM_PWR_DOMAIN_CORE;
|
||||
|
||||
if (!state || (state->pwr.afflv > PLAT_MAX_PWR_LVL)) {
|
||||
CPU_PM_ASSERT(0);
|
||||
}
|
||||
|
||||
switch (state->pwr.state_id) {
|
||||
case MT_PLAT_PWR_STATE_SYSTEM_MEM:
|
||||
mt_pwr_nodes[MT_PWR_SYSTEM_MEM] += 1;
|
||||
break;
|
||||
case MT_PLAT_PWR_STATE_SYSTEM_PLL:
|
||||
mt_pwr_nodes[MT_PWR_SYSTEM_PLL] += 1;
|
||||
break;
|
||||
case MT_PLAT_PWR_STATE_SYSTEM_BUS:
|
||||
mt_pwr_nodes[MT_PWR_SYSTEM_BUS] += 1;
|
||||
break;
|
||||
case MT_PLAT_PWR_STATE_SUSPEND:
|
||||
mt_pwr_nodes[MT_PWR_SUSPEND] += 1;
|
||||
break;
|
||||
default:
|
||||
if (!IS_MT_PLAT_PWR_STATE_MCUSYS(state->pwr.state_id) &&
|
||||
!IS_PLAT_SYSTEM_SUSPEND(state->pwr.afflv)) {
|
||||
plat_cpu_pm_lock();
|
||||
mt_pwr_nodes[MT_PWR_NONMCUSYS] += 1;
|
||||
flush_dcache_range((uintptr_t)&mt_pwr_nodes[MT_PWR_NONMCUSYS],
|
||||
sizeof(mt_pwr_nodes[MT_PWR_NONMCUSYS]));
|
||||
plat_cpu_pm_unlock();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if ((mt_pwr_nodes[MT_PWR_NONMCUSYS] == 0) && IS_PLAT_MCUSYSOFF_AFFLV(state->pwr.afflv)) {
|
||||
/* Prepare to power down mcusys */
|
||||
if (mcusys_prepare_suspend(state) == MTK_CPUPM_E_OK) {
|
||||
mt_pwr_nodes[MT_PWR_MCUSYS_PDN] += 1;
|
||||
flush_dcache_range((uintptr_t)&mt_pwr_nodes[MT_PWR_MCUSYS_PDN],
|
||||
sizeof(mt_pwr_nodes[MT_PWR_MCUSYS_PDN]));
|
||||
pstate |= (MT_CPUPM_PWR_DOMAIN_MCUSYS | MT_CPUPM_PWR_DOMAIN_CLUSTER);
|
||||
}
|
||||
}
|
||||
|
||||
if (state->pwr.afflv >= PLAT_MT_CPU_SUSPEND_CLUSTER) {
|
||||
pstate |= MT_CPUPM_PWR_DOMAIN_CLUSTER;
|
||||
}
|
||||
|
||||
if (psci_get_pstate_pwrlvl(psci_state) >= PLAT_MT_CPU_SUSPEND_CLUSTER) {
|
||||
pstate |= MT_CPUPM_PWR_DOMAIN_PERCORE_DSU;
|
||||
}
|
||||
|
||||
return pstate;
|
||||
}
|
||||
|
||||
static unsigned int cpupm_do_pstate_on(const mtk_pstate_type psci_state,
|
||||
const struct mtk_cpupm_pwrstate *state)
|
||||
{
|
||||
unsigned int pstate = MT_CPUPM_PWR_DOMAIN_CORE;
|
||||
|
||||
CPU_PM_ASSERT(state != NULL);
|
||||
|
||||
if (state->pwr.afflv > PLAT_MAX_PWR_LVL) {
|
||||
CPU_PM_ASSERT(0);
|
||||
}
|
||||
|
||||
if (mt_pwr_nodes[MT_PWR_MCUSYS_PDN] != 0) {
|
||||
mt_pwr_nodes[MT_PWR_MCUSYS_PDN] = 0;
|
||||
flush_dcache_range((uintptr_t)&mt_pwr_nodes[MT_PWR_MCUSYS_PDN],
|
||||
sizeof(mt_pwr_nodes[MT_PWR_MCUSYS_PDN]));
|
||||
pstate |= (MT_CPUPM_PWR_DOMAIN_MCUSYS | MT_CPUPM_PWR_DOMAIN_CLUSTER);
|
||||
mcusys_prepare_resume(state);
|
||||
}
|
||||
|
||||
if (state->pwr.afflv >= PLAT_MT_CPU_SUSPEND_CLUSTER) {
|
||||
pstate |= MT_CPUPM_PWR_DOMAIN_CLUSTER;
|
||||
}
|
||||
|
||||
switch (state->pwr.state_id) {
|
||||
case MT_PLAT_PWR_STATE_SYSTEM_MEM:
|
||||
mt_pwr_nodes[MT_PWR_SYSTEM_MEM] -= 1;
|
||||
CPU_PM_ASSERT(mt_pwr_nodes[MT_PWR_SYSTEM_MEM] >= 0);
|
||||
break;
|
||||
case MT_PLAT_PWR_STATE_SYSTEM_PLL:
|
||||
mt_pwr_nodes[MT_PWR_SYSTEM_PLL] -= 1;
|
||||
CPU_PM_ASSERT(mt_pwr_nodes[MT_PWR_SYSTEM_PLL] >= 0);
|
||||
break;
|
||||
case MT_PLAT_PWR_STATE_SYSTEM_BUS:
|
||||
mt_pwr_nodes[MT_PWR_SYSTEM_BUS] -= 1;
|
||||
CPU_PM_ASSERT(mt_pwr_nodes[MT_PWR_SYSTEM_BUS] >= 0);
|
||||
break;
|
||||
case MT_PLAT_PWR_STATE_SUSPEND:
|
||||
mt_pwr_nodes[MT_PWR_SUSPEND] -= 1;
|
||||
CPU_PM_ASSERT(mt_pwr_nodes[MT_PWR_SUSPEND] >= 0);
|
||||
break;
|
||||
default:
|
||||
if (!IS_MT_PLAT_PWR_STATE_MCUSYS(state->pwr.state_id) &&
|
||||
!IS_PLAT_SYSTEM_SUSPEND(state->pwr.afflv)) {
|
||||
plat_cpu_pm_lock();
|
||||
mt_pwr_nodes[MT_PWR_NONMCUSYS] -= 1;
|
||||
flush_dcache_range((uintptr_t)&mt_pwr_nodes[MT_PWR_NONMCUSYS],
|
||||
sizeof(mt_pwr_nodes[MT_PWR_NONMCUSYS]));
|
||||
plat_cpu_pm_unlock();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (IS_PLAT_SYSTEM_SUSPEND(state->pwr.afflv) ||
|
||||
(IS_PLAT_SYSTEM_RETENTION(state->pwr.afflv) && (mt_pwr_nodes[MT_PWR_SUSPEND] > 0))) {
|
||||
mtk_cpc_time_sync();
|
||||
}
|
||||
|
||||
if (mt_pwr_nodes[MT_PWR_NONMCUSYS] < 0) {
|
||||
CPU_PM_ASSERT(0);
|
||||
}
|
||||
|
||||
pstate |= MT_CPUPM_PWR_DOMAIN_PERCORE_DSU;
|
||||
|
||||
return pstate;
|
||||
}
|
||||
|
||||
static void cpupm_cpu_resume(const struct mtk_cpupm_pwrstate *state)
|
||||
{
|
||||
cpupm_cpu_resume_common(state);
|
||||
}
|
||||
|
||||
static void cpupm_mcusys_resume(const struct mtk_cpupm_pwrstate *state)
|
||||
{
|
||||
assert(state != NULL);
|
||||
}
|
||||
|
||||
static void cpupm_mcusys_suspend(const struct mtk_cpupm_pwrstate *state)
|
||||
{
|
||||
assert(state != NULL);
|
||||
}
|
||||
|
||||
static unsigned int cpupm_get_pstate(enum mt_cpupm_pwr_domain domain,
|
||||
const mtk_pstate_type psci_state,
|
||||
const struct mtk_cpupm_pwrstate *state)
|
||||
{
|
||||
unsigned int pstate = 0;
|
||||
|
||||
if (state == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (state->info.mode == MTK_CPU_PM_SMP) {
|
||||
pstate = MT_CPUPM_PWR_DOMAIN_CORE;
|
||||
} else {
|
||||
if (domain == CPUPM_PWR_OFF) {
|
||||
pstate = cpupm_do_pstate_off(psci_state, state);
|
||||
} else if (domain == CPUPM_PWR_ON) {
|
||||
pstate = cpupm_do_pstate_on(psci_state, state);
|
||||
} else {
|
||||
INFO("[%s:%d][CPU_PM] unknown pwr domain :%d\n",
|
||||
__func__, __LINE__, domain);
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
return pstate;
|
||||
}
|
||||
|
||||
static int cpupm_init(void)
|
||||
{
|
||||
int ret = MTK_CPUPM_E_OK;
|
||||
|
||||
#ifdef CPU_PM_TINYSYS_SUPPORT
|
||||
int status;
|
||||
|
||||
if ((cpu_pm_status & CPU_PM_INIT_READY) == CPU_PM_INIT_READY) {
|
||||
return MTK_CPUPM_E_OK;
|
||||
}
|
||||
|
||||
if (!(cpu_pm_status & CPU_PM_DEPD_INIT)) {
|
||||
status = mtk_lp_depd_condition(CPUPM_MBOX_WAIT_DEV_INIT);
|
||||
if (status == 0) {
|
||||
plat_cpu_pm_lock();
|
||||
cpu_pm_status |= CPU_PM_DEPD_INIT;
|
||||
plat_cpu_pm_unlock();
|
||||
}
|
||||
}
|
||||
|
||||
if ((cpu_pm_status & CPU_PM_DEPD_INIT) && !(cpu_pm_status & CPU_PM_DEPD_READY)) {
|
||||
status = mtk_lp_depd_condition(CPUPM_MBOX_WAIT_TASK_READY);
|
||||
if (status == 0) {
|
||||
plat_cpu_pm_lock();
|
||||
cpu_pm_status |= CPU_PM_DEPD_READY;
|
||||
plat_cpu_pm_unlock();
|
||||
}
|
||||
}
|
||||
|
||||
ret = ((cpu_pm_status & CPU_PM_INIT_READY) == CPU_PM_INIT_READY) ?
|
||||
MTK_CPUPM_E_OK : MTK_CPUPM_E_FAIL;
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cpupm_pwr_state_valid(unsigned int afflv, unsigned int state)
|
||||
{
|
||||
if (cpu_pm_status == CPU_PM_LP_READY) {
|
||||
return MTK_CPUPM_E_OK;
|
||||
}
|
||||
|
||||
if (cpupm_init() != MTK_CPUPM_E_OK) {
|
||||
return MTK_CPUPM_E_FAIL;
|
||||
}
|
||||
|
||||
if (read_cntpct_el0() >= (uint64_t)CPUPM_BOOTUP_TIME_THR) {
|
||||
plat_cpu_pm_lock();
|
||||
cpu_pm_status |= CPU_PM_PLAT_READY;
|
||||
plat_cpu_pm_unlock();
|
||||
}
|
||||
|
||||
if (!IS_PLAT_SYSTEM_SUSPEND(afflv) && (cpu_pm_status & CPU_PM_PLAT_READY) == 0) {
|
||||
return MTK_CPUPM_E_FAIL;
|
||||
}
|
||||
|
||||
return MTK_CPUPM_E_OK;
|
||||
}
|
||||
|
||||
static struct mtk_cpu_pm_ops cpcv3_2_mcdi = {
|
||||
.get_pstate = cpupm_get_pstate,
|
||||
.pwr_state_valid = cpupm_pwr_state_valid,
|
||||
.cpu_resume = cpupm_cpu_resume,
|
||||
.mcusys_suspend = cpupm_mcusys_suspend,
|
||||
.mcusys_resume = cpupm_mcusys_resume,
|
||||
};
|
||||
#endif /* CONFIG_MTK_CPU_SUSPEND_EN */
|
||||
|
||||
#endif /* CONFIG_MTK_PM_SUPPORT */
|
||||
|
||||
/*
|
||||
* Depend on mtk pm methodology, the psci op init must
|
||||
* be invoked after cpu pm to avoid initialization fail.
|
||||
*/
|
||||
int mt_plat_cpu_pm_init(void)
|
||||
{
|
||||
plat_cpu_pm_lock_init();
|
||||
|
||||
mtk_cpc_init();
|
||||
#if CONFIG_MTK_PM_SUPPORT
|
||||
|
||||
#if CONFIG_MTK_CPU_SUSPEND_EN
|
||||
register_cpu_pm_ops(CPU_PM_FN, &cpcv3_2_mcdi);
|
||||
#endif /* CONFIG_MTK_CPU_SUSPEND_EN */
|
||||
|
||||
#if CONFIG_MTK_SMP_EN
|
||||
register_cpu_smp_ops(CPU_PM_FN, &cpcv3_2_cpu_smp);
|
||||
#endif /* CONFIG_MTK_SMP_EN */
|
||||
|
||||
#endif /* CONFIG_MTK_PM_SUPPORT */
|
||||
|
||||
INFO("[%s:%d] - CPU PM INIT finished\n", __func__, __LINE__);
|
||||
return 0;
|
||||
}
|
||||
MTK_ARCH_INIT(mt_plat_cpu_pm_init);
|
||||
|
||||
static const mmap_region_t cpu_pm_mmap[] MTK_MMAP_SECTION = {
|
||||
#ifdef CPU_PM_TINYSYS_SUPPORT
|
||||
#if CONFIG_MTK_PM_SUPPORT && CONFIG_MTK_CPU_SUSPEND_EN
|
||||
MAP_REGION_FLAT(CPU_EB_TCM_BASE, CPU_EB_TCM_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
|
||||
#endif
|
||||
#endif
|
||||
{0}
|
||||
};
|
||||
DECLARE_MTK_MMAP_REGIONS(cpu_pm_mmap);
|
||||
+119
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef MT_CPU_PM_H
|
||||
#define MT_CPU_PM_H
|
||||
|
||||
#include <assert.h>
|
||||
#include <mcucfg.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
/*
|
||||
* After ARM v8.2, the cache will turn off automatically when powering down CPU. Therefore, there
|
||||
* is no doubt to use the spin_lock here.
|
||||
*/
|
||||
#if !HW_ASSISTED_COHERENCY
|
||||
#define MT_CPU_PM_USING_BAKERY_LOCK
|
||||
#endif
|
||||
|
||||
#define CPU_PM_FN (MTK_CPUPM_FN_CPUPM_GET_PWR_STATE | \
|
||||
MTK_CPUPM_FN_PWR_STATE_VALID | \
|
||||
MTK_CPUPM_FN_PWR_ON_CORE_PREPARE | \
|
||||
MTK_CPUPM_FN_RESUME_CORE | \
|
||||
MTK_CPUPM_FN_SUSPEND_MCUSYS | \
|
||||
MTK_CPUPM_FN_RESUME_MCUSYS | \
|
||||
MTK_CPUPM_FN_SMP_INIT | \
|
||||
MTK_CPUPM_FN_SMP_CORE_ON | \
|
||||
MTK_CPUPM_FN_SMP_CORE_OFF)
|
||||
|
||||
#define CPU_PM_ASSERT(_cond) ({ \
|
||||
if (!(_cond)) { \
|
||||
INFO("[%s:%d] - %s\n", __func__, __LINE__, #_cond); \
|
||||
panic(); \
|
||||
} })
|
||||
|
||||
#define CPC_PWR_MASK_MCUSYS_MP0 (0xC001)
|
||||
|
||||
#define PER_CPU_PWR_DATA(ctrl, cluster, core) \
|
||||
do { \
|
||||
ctrl.rvbaraddr_l = CORE_RVBRADDR_##cluster##_##core##_L; \
|
||||
ctrl.arch_addr = MCUCFG_MP0_CLUSTER_CFG5; \
|
||||
ctrl.pwpr = SPM_MP##cluster##_CPU##core##_PWR_CON; \
|
||||
} while (0)
|
||||
|
||||
#define PER_CPU_PWR_CTRL(ctrl, cpu) ({ \
|
||||
switch (cpu) { \
|
||||
case 0: \
|
||||
PER_CPU_PWR_DATA(ctrl, 0, 0); \
|
||||
break; \
|
||||
case 1: \
|
||||
PER_CPU_PWR_DATA(ctrl, 0, 1); \
|
||||
break; \
|
||||
case 2: \
|
||||
PER_CPU_PWR_DATA(ctrl, 0, 2); \
|
||||
break; \
|
||||
case 3: \
|
||||
PER_CPU_PWR_DATA(ctrl, 0, 3); \
|
||||
break; \
|
||||
case 4: \
|
||||
PER_CPU_PWR_DATA(ctrl, 0, 4); \
|
||||
break; \
|
||||
case 5: \
|
||||
PER_CPU_PWR_DATA(ctrl, 0, 5); \
|
||||
break; \
|
||||
case 6: \
|
||||
PER_CPU_PWR_DATA(ctrl, 0, 6); \
|
||||
break; \
|
||||
case 7: \
|
||||
PER_CPU_PWR_DATA(ctrl, 0, 7); \
|
||||
break; \
|
||||
default: \
|
||||
assert(0); \
|
||||
break; \
|
||||
} })
|
||||
|
||||
|
||||
/* MCUSYS DREQ BIG VPROC ISO control */
|
||||
#define DREQ20_BIG_VPROC_ISO (MCUCFG_BASE + 0xad8c)
|
||||
|
||||
/* Definition about bootup address for each core CORE_RVBRADDR_clusterid_cpuid */
|
||||
#define CORE_RVBRADDR_0_0_L (MCUCFG_BASE + 0xc900)
|
||||
#define CORE_RVBRADDR_0_1_L (MCUCFG_BASE + 0xc908)
|
||||
#define CORE_RVBRADDR_0_2_L (MCUCFG_BASE + 0xc910)
|
||||
#define CORE_RVBRADDR_0_3_L (MCUCFG_BASE + 0xc918)
|
||||
#define CORE_RVBRADDR_0_4_L (MCUCFG_BASE + 0xc920)
|
||||
#define CORE_RVBRADDR_0_5_L (MCUCFG_BASE + 0xc928)
|
||||
#define CORE_RVBRADDR_0_6_L (MCUCFG_BASE + 0xc930)
|
||||
#define CORE_RVBRADDR_0_7_L (MCUCFG_BASE + 0xc938)
|
||||
#define MCUCFG_MP0_CLUSTER_CFG5 (MCUCFG_BASE + 0xc8e4)
|
||||
|
||||
struct cpu_pwr_ctrl {
|
||||
unsigned int rvbaraddr_l;
|
||||
unsigned int arch_addr;
|
||||
unsigned int pwpr;
|
||||
};
|
||||
|
||||
#define MCUSYS_STATUS_PDN BIT(0)
|
||||
#define MCUSYS_STATUS_CPUSYS_PROTECT BIT(8)
|
||||
#define MCUSYS_STATUS_MCUSYS_PROTECT BIT(9)
|
||||
|
||||
/* cpu_pm function ID */
|
||||
enum mt_cpu_pm_user_id {
|
||||
MCUSYS_STATUS,
|
||||
CPC_COMMAND,
|
||||
};
|
||||
|
||||
/* cpu_pm lp function ID */
|
||||
enum mt_cpu_pm_lp_smc_id {
|
||||
LP_CPC_COMMAND,
|
||||
IRQS_REMAIN_ALLOC,
|
||||
IRQS_REMAIN_CTRL,
|
||||
IRQS_REMAIN_IRQ,
|
||||
IRQS_REMAIN_WAKEUP_CAT,
|
||||
IRQS_REMAIN_WAKEUP_SRC,
|
||||
};
|
||||
|
||||
#endif /* MT_CPU_PM_H */
|
||||
+253
@@ -0,0 +1,253 @@
|
||||
/*
|
||||
* Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <drivers/delay_timer.h>
|
||||
|
||||
#include "mt_cpu_pm.h"
|
||||
#include "mt_cpu_pm_cpc.h"
|
||||
#include "mt_smp.h"
|
||||
#include <mt_timer.h>
|
||||
|
||||
struct mtk_cpc_dev {
|
||||
int auto_off;
|
||||
unsigned int auto_thres_tick;
|
||||
};
|
||||
|
||||
static struct mtk_cpc_dev cpc;
|
||||
|
||||
static int mtk_cpc_last_core_prot(int prot_req, int resp_reg, int resp_ofs)
|
||||
{
|
||||
unsigned int staus;
|
||||
unsigned int retry = 0;
|
||||
|
||||
while (retry < RETRY_CNT_MAX) {
|
||||
retry++;
|
||||
|
||||
mmio_write_32(CPC_MCUSYS_LAST_CORE_REQ, prot_req);
|
||||
|
||||
udelay(1);
|
||||
|
||||
staus = (mmio_read_32(resp_reg) >> resp_ofs) & CPC_PROT_RESP_MASK;
|
||||
|
||||
if (staus == PROT_SUCCESS) {
|
||||
return CPC_SUCCESS;
|
||||
} else if (staus == PROT_GIVEUP) {
|
||||
return CPC_ERR_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
return CPC_ERR_TIMEOUT;
|
||||
}
|
||||
|
||||
static int mtk_cpu_pm_mcusys_prot_aquire(void)
|
||||
{
|
||||
return mtk_cpc_last_core_prot(MCUSYS_PROT_SET, CPC_MCUSYS_LAST_CORE_RESP, MCUSYS_RESP_OFS);
|
||||
}
|
||||
|
||||
static void mtk_cpu_pm_mcusys_prot_release(void)
|
||||
{
|
||||
mmio_write_32(CPC_MCUSYS_PWR_ON_MASK, MCUSYS_PROT_CLR);
|
||||
}
|
||||
|
||||
int mtk_cpu_pm_cluster_prot_aquire(void)
|
||||
{
|
||||
return mtk_cpc_last_core_prot(CPUSYS_PROT_SET, CPC_MCUSYS_MP_LAST_CORE_RESP,
|
||||
CPUSYS_RESP_OFS);
|
||||
}
|
||||
|
||||
void mtk_cpu_pm_cluster_prot_release(void)
|
||||
{
|
||||
mmio_write_32(CPC_MCUSYS_PWR_ON_MASK, CPUSYS_PROT_CLR);
|
||||
}
|
||||
|
||||
static void mtk_cpc_cluster_cnt_backup(void)
|
||||
{
|
||||
/* single cluster */
|
||||
uint32_t backup_cnt = mmio_read_32(CPC_CLUSTER_CNT_BACKUP);
|
||||
uint32_t curr_cnt = mmio_read_32(CPC_MCUSYS_CLUSTER_COUNTER);
|
||||
|
||||
if ((curr_cnt & 0x7fff) == 0) {
|
||||
curr_cnt = (curr_cnt >> 16) & 0x7fff;
|
||||
} else {
|
||||
curr_cnt = curr_cnt & 0x7fff;
|
||||
}
|
||||
|
||||
mmio_write_32(CPC_CLUSTER_CNT_BACKUP, backup_cnt + curr_cnt);
|
||||
mmio_write_32(CPC_MCUSYS_CLUSTER_COUNTER_CLR, 0x3);
|
||||
}
|
||||
|
||||
static inline void mtk_cpc_mcusys_off_enable(bool enable)
|
||||
{
|
||||
mmio_write_32(CPC_MCUSYS_PWR_CTRL, enable ? 1 : 0);
|
||||
}
|
||||
|
||||
void mtk_cpc_mcusys_off_reflect(void)
|
||||
{
|
||||
mtk_cpc_mcusys_off_enable(false);
|
||||
mtk_cpu_pm_mcusys_prot_release();
|
||||
}
|
||||
|
||||
int mtk_cpc_mcusys_off_prepare(void)
|
||||
{
|
||||
if (mtk_cpu_pm_mcusys_prot_aquire() != CPC_SUCCESS) {
|
||||
return CPC_ERR_FAIL;
|
||||
}
|
||||
|
||||
mtk_cpc_cluster_cnt_backup();
|
||||
mtk_cpc_mcusys_off_enable(true);
|
||||
|
||||
return CPC_SUCCESS;
|
||||
}
|
||||
|
||||
void mtk_cpc_core_on_hint_set(int cpu)
|
||||
{
|
||||
mmio_write_32(CPC_MCUSYS_CPU_ON_SW_HINT_SET, BIT(cpu));
|
||||
}
|
||||
|
||||
void mtk_cpc_core_on_hint_clr(int cpu)
|
||||
{
|
||||
mmio_write_32(CPC_MCUSYS_CPU_ON_SW_HINT_CLR, BIT(cpu));
|
||||
}
|
||||
|
||||
static void mtk_cpc_dump_timestamp(void)
|
||||
{
|
||||
unsigned int id;
|
||||
|
||||
for (id = 0; id < CPC_TRACE_ID_NUM; id++) {
|
||||
mmio_write_32(CPC_MCUSYS_TRACE_SEL, id);
|
||||
|
||||
memcpy((void *)(uintptr_t)CPC_TRACE_SRAM(id),
|
||||
(const void *)(uintptr_t)CPC_MCUSYS_TRACE_DATA,
|
||||
CPC_TRACE_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
void mtk_cpc_time_sync(void)
|
||||
{
|
||||
uint64_t kt;
|
||||
uint32_t systime_l, systime_h;
|
||||
|
||||
kt = sched_clock();
|
||||
systime_l = mmio_read_32(CNTSYS_L_REG);
|
||||
systime_h = mmio_read_32(CNTSYS_H_REG);
|
||||
|
||||
/* sync kernel timer to cpc */
|
||||
mmio_write_32(CPC_MCUSYS_CPC_KERNEL_TIME_L_BASE, (uint32_t)kt);
|
||||
mmio_write_32(CPC_MCUSYS_CPC_KERNEL_TIME_H_BASE, (uint32_t)(kt >> 32));
|
||||
|
||||
/* sync system timer to cpc */
|
||||
mmio_write_32(CPC_MCUSYS_CPC_SYSTEM_TIME_L_BASE, systime_l);
|
||||
mmio_write_32(CPC_MCUSYS_CPC_SYSTEM_TIME_H_BASE, systime_h);
|
||||
}
|
||||
|
||||
static void mtk_cpc_config(unsigned int cfg, unsigned int data)
|
||||
{
|
||||
switch (cfg) {
|
||||
case CPC_SMC_CONFIG_PROF:
|
||||
if (data) {
|
||||
mmio_setbits_32(CPC_MCUSYS_CPC_DBG_SETTING, CPC_PROF_EN);
|
||||
} else {
|
||||
mmio_clrbits_32(CPC_MCUSYS_CPC_DBG_SETTING, CPC_PROF_EN);
|
||||
}
|
||||
break;
|
||||
case CPC_SMC_CONFIG_AUTO_OFF:
|
||||
if (data) {
|
||||
mmio_setbits_32(CPC_MCUSYS_CPC_FLOW_CTRL_CFG, CPC_AUTO_OFF_EN);
|
||||
cpc.auto_off = 1;
|
||||
} else {
|
||||
mmio_setbits_32(CPC_MCUSYS_CPC_FLOW_CTRL_CFG, CPC_AUTO_OFF_EN);
|
||||
cpc.auto_off = 0;
|
||||
}
|
||||
break;
|
||||
case CPC_SMC_CONFIG_AUTO_OFF_THRES:
|
||||
cpc.auto_thres_tick = US_TO_TICKS(data);
|
||||
mmio_write_32(CPC_MCUSYS_CPC_OFF_THRES, cpc.auto_thres_tick);
|
||||
break;
|
||||
case CPC_SMC_CONFIG_CNT_CLR:
|
||||
mmio_write_32(CPC_MCUSYS_CLUSTER_COUNTER_CLR, 0x3);
|
||||
break;
|
||||
case CPC_SMC_CONFIG_TIME_SYNC:
|
||||
mtk_cpc_time_sync();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int mtk_cpc_read_config(unsigned int cfg)
|
||||
{
|
||||
unsigned int res = 0;
|
||||
|
||||
switch (cfg) {
|
||||
case CPC_SMC_CONFIG_PROF:
|
||||
res = (mmio_read_32(CPC_MCUSYS_CPC_DBG_SETTING) & CPC_PROF_EN) ? 1 : 0;
|
||||
break;
|
||||
case CPC_SMC_CONFIG_AUTO_OFF:
|
||||
res = cpc.auto_off;
|
||||
break;
|
||||
case CPC_SMC_CONFIG_AUTO_OFF_THRES:
|
||||
res = TICKS_TO_US(cpc.auto_thres_tick);
|
||||
break;
|
||||
case CPC_SMC_CONFIG_CNT_CLR:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
uint64_t mtk_cpc_handler(uint64_t act, uint64_t arg1, uint64_t arg2)
|
||||
{
|
||||
uint64_t res = 0;
|
||||
|
||||
switch (act) {
|
||||
case CPC_SMC_EVENT_CPC_CONFIG:
|
||||
mtk_cpc_config((unsigned int)arg1, (unsigned int)arg2);
|
||||
break;
|
||||
case CPC_SMC_EVENT_READ_CONFIG:
|
||||
res = mtk_cpc_read_config((unsigned int)arg1);
|
||||
break;
|
||||
case CPC_SMC_EVENT_GIC_DPG_SET:
|
||||
/* isolated_status = x2; */
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
uint64_t mtk_cpc_trace_dump(uint64_t act, uint64_t arg1, uint64_t arg2)
|
||||
{
|
||||
switch (act) {
|
||||
case CPC_SMC_EVENT_DUMP_TRACE_DATA:
|
||||
mtk_cpc_dump_timestamp();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mtk_cpc_init(void)
|
||||
{
|
||||
#if CONFIG_MTK_SMP_EN
|
||||
mt_smp_init();
|
||||
#endif
|
||||
mmio_setbits_32(CPC_MCUSYS_CPC_DBG_SETTING, (CPC_DBG_EN | CPC_CALC_EN));
|
||||
|
||||
cpc.auto_off = 1;
|
||||
mmio_setbits_32(CPC_MCUSYS_CPC_FLOW_CTRL_CFG, (CPC_OFF_PRE_EN |
|
||||
((cpc.auto_off > 0) ? CPC_AUTO_OFF_EN : 0)));
|
||||
|
||||
mtk_cpc_config(CPC_SMC_CONFIG_AUTO_OFF_THRES, 8000);
|
||||
|
||||
/* enable CPC */
|
||||
mmio_setbits_32(CPC_MCUSYS_CPC_FLOW_CTRL_CFG, CPC_CTRL_ENABLE);
|
||||
mmio_setbits_32(CPC_MCUSYS_CPC_FLOW_CTRL_CFG, SSPM_CORE_PWR_ON_EN);
|
||||
}
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef MT_CPU_PM_CPC_H
|
||||
#define MT_CPU_PM_CPC_H
|
||||
|
||||
#include <lib/mmio.h>
|
||||
|
||||
#include <mcucfg.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
#define NEED_CPUSYS_PROT_WORKAROUND (1)
|
||||
|
||||
/* system sram registers */
|
||||
#define CPUIDLE_SRAM_REG(r) (CPU_IDLE_SRAM_BASE + (r))
|
||||
|
||||
/* db dump */
|
||||
#define CPC_TRACE_SIZE (0x20)
|
||||
#define CPC_TRACE_ID_NUM (10)
|
||||
#define CPC_TRACE_SRAM(id) (CPUIDLE_SRAM_REG(0x10) + (id) * CPC_TRACE_SIZE)
|
||||
|
||||
/* buckup off count */
|
||||
#define CPC_CLUSTER_CNT_BACKUP CPUIDLE_SRAM_REG(0x1f0)
|
||||
#define CPC_MCUSYS_CNT CPUIDLE_SRAM_REG(0x1f4)
|
||||
|
||||
/* CPC_MCUSYS_CPC_FLOW_CTRL_CFG (0xA814): debug setting */
|
||||
#define CPC_PWR_ON_SEQ_DIS BIT(1)
|
||||
#define CPC_PWR_ON_PRIORITY BIT(2)
|
||||
#define CPC_AUTO_OFF_EN BIT(5)
|
||||
#define CPC_DORMANT_WAIT_EN BIT(14)
|
||||
#define CPC_CTRL_EN BIT(16)
|
||||
#define CPC_OFF_PRE_EN BIT(29)
|
||||
|
||||
/* CPC_MCUSYS_LAST_CORE_REQ (0xA818) : last core protection */
|
||||
#define CPUSYS_PROT_SET BIT(0)
|
||||
#define MCUSYS_PROT_SET BIT(8)
|
||||
#define CPUSYS_PROT_CLR BIT(8)
|
||||
#define MCUSYS_PROT_CLR BIT(9)
|
||||
|
||||
#define CPC_PROT_RESP_MASK (0x3)
|
||||
#define CPUSYS_RESP_OFS (16)
|
||||
#define MCUSYS_RESP_OFS (30)
|
||||
|
||||
#define RETRY_CNT_MAX (1000)
|
||||
|
||||
#define PROT_RETRY (0)
|
||||
#define PROT_SUCCESS (1)
|
||||
#define PROT_GIVEUP (2)
|
||||
|
||||
/* CPC_MCUSYS_CPC_DBG_SETTING (0xAB00): debug setting */
|
||||
#define CPC_PROF_EN BIT(0)
|
||||
#define CPC_DBG_EN BIT(1)
|
||||
#define CPC_FREEZE BIT(2)
|
||||
#define CPC_CALC_EN BIT(3)
|
||||
|
||||
enum mcusys_cpc_lastcore_prot_status {
|
||||
CPC_SUCCESS = 0,
|
||||
CPC_ERR_FAIL,
|
||||
CPC_ERR_TIMEOUT,
|
||||
NF_CPC_ERR,
|
||||
};
|
||||
|
||||
enum mcusys_cpc_smc_events {
|
||||
CPC_SMC_EVENT_DUMP_TRACE_DATA,
|
||||
CPC_SMC_EVENT_GIC_DPG_SET,
|
||||
CPC_SMC_EVENT_CPC_CONFIG,
|
||||
CPC_SMC_EVENT_READ_CONFIG,
|
||||
NF_CPC_SMC_EVENT,
|
||||
};
|
||||
|
||||
enum mcusys_cpc_smc_config {
|
||||
CPC_SMC_CONFIG_PROF,
|
||||
CPC_SMC_CONFIG_AUTO_OFF,
|
||||
CPC_SMC_CONFIG_AUTO_OFF_THRES,
|
||||
CPC_SMC_CONFIG_CNT_CLR,
|
||||
CPC_SMC_CONFIG_TIME_SYNC,
|
||||
NF_CPC_SMC_CONFIG,
|
||||
};
|
||||
|
||||
#define US_TO_TICKS(us) ((us) * 13)
|
||||
#define TICKS_TO_US(tick) ((tick) / 13)
|
||||
|
||||
int mtk_cpu_pm_cluster_prot_aquire(void);
|
||||
void mtk_cpu_pm_cluster_prot_release(void);
|
||||
|
||||
void mtk_cpc_mcusys_off_reflect(void);
|
||||
int mtk_cpc_mcusys_off_prepare(void);
|
||||
|
||||
void mtk_cpc_core_on_hint_set(int cpu);
|
||||
void mtk_cpc_core_on_hint_clr(int cpu);
|
||||
void mtk_cpc_time_sync(void);
|
||||
|
||||
uint64_t mtk_cpc_handler(uint64_t act, uint64_t arg1, uint64_t arg2);
|
||||
uint64_t mtk_cpc_trace_dump(uint64_t act, uint64_t arg1, uint64_t arg2);
|
||||
void mtk_cpc_init(void);
|
||||
|
||||
#endif /* MT_CPU_PM_CPC_H */
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include <lib/mmio.h>
|
||||
|
||||
#include "mt_cpu_pm_mbox.h"
|
||||
#include <platform_def.h>
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define MCDI_LIKELY(x) __builtin_expect(!!(x), 1)
|
||||
#define MCDI_UNLIKELY(x) __builtin_expect(!!(x), 0)
|
||||
#else
|
||||
#define MCDI_LIKELY(x) (x)
|
||||
#define MCDI_UNLIKELY(x) (x)
|
||||
#endif
|
||||
|
||||
#define MCUPM_MBOX_3_BASE (CPU_EB_TCM_BASE + CPU_EB_MBOX3_OFFSET)
|
||||
#define MCUPM_MBOX_WRITE(id, val) mmio_write_32(MCUPM_MBOX_3_BASE + 4 * (id), val)
|
||||
#define MCUPM_MBOX_READ(id) mmio_read_32(MCUPM_MBOX_3_BASE + 4 * (id))
|
||||
|
||||
void mtk_set_mcupm_pll_mode(unsigned int mode)
|
||||
{
|
||||
if (mode < NF_MCUPM_ARMPLL_MODE) {
|
||||
MCUPM_MBOX_WRITE(MCUPM_MBOX_ARMPLL_MODE, mode);
|
||||
}
|
||||
}
|
||||
|
||||
int mtk_get_mcupm_pll_mode(void)
|
||||
{
|
||||
return MCUPM_MBOX_READ(MCUPM_MBOX_ARMPLL_MODE);
|
||||
}
|
||||
|
||||
void mtk_set_mcupm_buck_mode(unsigned int mode)
|
||||
{
|
||||
if (mode < NF_MCUPM_BUCK_MODE) {
|
||||
MCUPM_MBOX_WRITE(MCUPM_MBOX_BUCK_MODE, mode);
|
||||
}
|
||||
}
|
||||
|
||||
int mtk_get_mcupm_buck_mode(void)
|
||||
{
|
||||
return MCUPM_MBOX_READ(MCUPM_MBOX_BUCK_MODE);
|
||||
}
|
||||
|
||||
void mtk_set_cpu_pm_preffered_cpu(unsigned int cpuid)
|
||||
{
|
||||
return MCUPM_MBOX_WRITE(MCUPM_MBOX_WAKEUP_CPU, cpuid);
|
||||
}
|
||||
|
||||
unsigned int mtk_get_cpu_pm_preffered_cpu(void)
|
||||
{
|
||||
return MCUPM_MBOX_READ(MCUPM_MBOX_WAKEUP_CPU);
|
||||
}
|
||||
|
||||
static int mtk_wait_mbox_init_done(void)
|
||||
{
|
||||
int status = MCUPM_MBOX_READ(MCUPM_MBOX_TASK_STA);
|
||||
|
||||
if (status != MCUPM_TASK_INIT) {
|
||||
return status;
|
||||
}
|
||||
|
||||
mtk_set_mcupm_pll_mode(MCUPM_ARMPLL_OFF);
|
||||
mtk_set_mcupm_buck_mode(MCUPM_BUCK_OFF_MODE);
|
||||
|
||||
MCUPM_MBOX_WRITE(MCUPM_MBOX_PWR_CTRL_EN, (MCUPM_MCUSYS_CTRL | MCUPM_CM_CTRL |
|
||||
MCUPM_BUCK_CTRL | MCUPM_ARMPLL_CTRL));
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
int mtk_lp_depd_condition(enum cpupm_mbox_depd_type type)
|
||||
{
|
||||
int status;
|
||||
|
||||
if (type == CPUPM_MBOX_WAIT_DEV_INIT) {
|
||||
status = mtk_wait_mbox_init_done();
|
||||
if (MCDI_UNLIKELY(status != MCUPM_TASK_INIT)) {
|
||||
return -ENXIO;
|
||||
}
|
||||
MCUPM_MBOX_WRITE(MCUPM_MBOX_AP_READY, 1);
|
||||
} else if (type == CPUPM_MBOX_WAIT_TASK_READY) {
|
||||
status = MCUPM_MBOX_READ(MCUPM_MBOX_TASK_STA);
|
||||
if (MCDI_UNLIKELY((status != MCUPM_TASK_WAIT) &&
|
||||
(status != MCUPM_TASK_INIT_FINISH))) {
|
||||
return -ENXIO;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef MT_CPU_PM_MBOX_H
|
||||
#define MT_CPU_PM_MBOX_H
|
||||
|
||||
#include <lib/utils_def.h>
|
||||
|
||||
/* MCUPM Mbox */
|
||||
/* AP Write */
|
||||
#define MCUPM_MBOX_AP_READY (0)
|
||||
#define MCUPM_MBOX_RESERVED_1 (1)
|
||||
#define MCUPM_MBOX_RESERVED_2 (2)
|
||||
#define MCUPM_MBOX_RESERVED_3 (3)
|
||||
#define MCUPM_MBOX_PWR_CTRL_EN (4)
|
||||
#define MCUPM_MBOX_L3_CACHE_MODE (5)
|
||||
#define MCUPM_MBOX_BUCK_MODE (6)
|
||||
#define MCUPM_MBOX_ARMPLL_MODE (7)
|
||||
/* AP Read */
|
||||
#define MCUPM_MBOX_TASK_STA (8)
|
||||
#define MCUPM_MBOX_RESERVED_9 (9)
|
||||
#define MCUPM_MBOX_RESERVED_10 (10)
|
||||
#define MCUPM_MBOX_RESERVED_11 (11)
|
||||
#define MCUPM_MBOX_WAKEUP_CPU (12)
|
||||
|
||||
/* Mbox Slot: APMCU_MCUPM_MBOX_PWR_CTRL_EN (4) */
|
||||
#define MCUPM_MCUSYS_CTRL BIT(0)
|
||||
#define MCUPM_BUCK_CTRL BIT(1)
|
||||
#define MCUPM_ARMPLL_CTRL BIT(2)
|
||||
#define MCUPM_CM_CTRL BIT(3)
|
||||
#define MCUPM_PWR_CTRL_MASK (BIT(3) - 1)
|
||||
|
||||
/* Mbox Slot: APMCU_MCUPM_MBOX_L3_CACHE_MODE (5) */
|
||||
#define MCUPM_L3_OFF_MODE (0) /* default */
|
||||
#define MCUPM_L3_DORMANT_MODE (1)
|
||||
#define NF_MCUPM_L3_MODE (2)
|
||||
|
||||
/* Mbox Slot: APMCU_MCUPM_MBOX_BUCK_MODE (6) */
|
||||
#define MCUPM_BUCK_NORMAL_MODE (0) /* default */
|
||||
#define MCUPM_BUCK_LP_MODE (1)
|
||||
#define MCUPM_BUCK_OFF_MODE (2)
|
||||
#define NF_MCUPM_BUCK_MODE (3)
|
||||
|
||||
/* Mbox Slot: APMCU_MCUPM_MBOX_ARMPLL_MODE (7) */
|
||||
#define MCUPM_ARMPLL_ON (0) /* default */
|
||||
#define MCUPM_ARMPLL_GATING (1)
|
||||
#define MCUPM_ARMPLL_OFF (2)
|
||||
#define NF_MCUPM_ARMPLL_MODE (3)
|
||||
|
||||
/* Mbox Slot: APMCU_MCUPM_MBOX_TASK_STA (9) */
|
||||
#define MCUPM_TASK_UNINIT (0)
|
||||
#define MCUPM_TASK_INIT (1)
|
||||
#define MCUPM_TASK_INIT_FINISH (2)
|
||||
#define MCUPM_TASK_WAIT (3)
|
||||
#define MCUPM_TASK_RUN (4)
|
||||
#define MCUPM_TASK_PAUSE (5)
|
||||
|
||||
|
||||
void mtk_set_mcupm_pll_mode(unsigned int mode);
|
||||
int mtk_get_mcupm_pll_mode(void);
|
||||
|
||||
void mtk_set_mcupm_buck_mode(unsigned int mode);
|
||||
int mtk_get_mcupm_buck_mode(void);
|
||||
|
||||
void mtk_set_cpu_pm_preffered_cpu(unsigned int cpuid);
|
||||
unsigned int mtk_get_cpu_pm_preffered_cpu(void);
|
||||
|
||||
enum cpupm_mbox_depd_type {
|
||||
CPUPM_MBOX_WAIT_DEV_INIT,
|
||||
CPUPM_MBOX_WAIT_TASK_READY,
|
||||
};
|
||||
|
||||
int mtk_lp_depd_condition(enum cpupm_mbox_depd_type type);
|
||||
|
||||
#endif /* MT_CPU_PM_MBOX_H */
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <common/debug.h>
|
||||
#include <drivers/delay_timer.h>
|
||||
#include <plat/common/platform.h>
|
||||
|
||||
#include <lib/pm/mtk_pm.h>
|
||||
#include <mcucfg.h>
|
||||
#include "mt_cpu_pm.h"
|
||||
#include "mt_smp.h"
|
||||
|
||||
static inline int is_core_power_status_on(unsigned int cpuid)
|
||||
{
|
||||
return !!(mmio_read_32(CPU_PWR_STATUS) & BIT(cpuid));
|
||||
}
|
||||
|
||||
void mt_smp_core_init_arch(unsigned int cluster, unsigned int cpu, int arm64,
|
||||
struct cpu_pwr_ctrl *pwr_ctrl)
|
||||
{
|
||||
CPU_PM_ASSERT(cluster == 0);
|
||||
CPU_PM_ASSERT(pwr_ctrl != NULL);
|
||||
|
||||
/* aa64naa32 in bits[16:23] */
|
||||
if (arm64 != 0) {
|
||||
mmio_setbits_32(pwr_ctrl->arch_addr, 1 << (16 + cpu));
|
||||
} else {
|
||||
mmio_clrbits_32(pwr_ctrl->arch_addr, 1 << (16 + cpu));
|
||||
}
|
||||
}
|
||||
|
||||
void mt_smp_core_bootup_address_set(struct cpu_pwr_ctrl *pwr_ctrl, uintptr_t entry)
|
||||
{
|
||||
CPU_PM_ASSERT(pwr_ctrl != NULL);
|
||||
|
||||
/* Set bootup address */
|
||||
mmio_write_32(pwr_ctrl->rvbaraddr_l, entry);
|
||||
}
|
||||
|
||||
int mt_smp_power_core_on(unsigned int cpu_id, struct cpu_pwr_ctrl *pwr_ctrl)
|
||||
{
|
||||
unsigned int val = is_core_power_status_on(cpu_id);
|
||||
|
||||
CPU_PM_ASSERT(pwr_ctrl);
|
||||
|
||||
mmio_clrbits_32(pwr_ctrl->pwpr, RESETPWRON_CONFIG);
|
||||
if (val == 0) {
|
||||
/*
|
||||
* Set to 0 after BIG VPROC bulk powered on (configure in MCUPM) and
|
||||
* before big core power-on sequence.
|
||||
*/
|
||||
if (cpu_id >= PLAT_CPU_PM_B_BUCK_ISO_ID) {
|
||||
mmio_write_32(DREQ20_BIG_VPROC_ISO, 0);
|
||||
}
|
||||
|
||||
mmio_setbits_32(pwr_ctrl->pwpr, PWR_RST_B);
|
||||
dsbsy();
|
||||
|
||||
/* set mp0_spmc_pwr_on_cpuX = 1 */
|
||||
mmio_setbits_32(pwr_ctrl->pwpr, PWR_ON);
|
||||
|
||||
val = 0;
|
||||
while (is_core_power_status_on(cpu_id) == 0) {
|
||||
DO_SMP_CORE_ON_WAIT_TIMEOUT(val);
|
||||
mmio_clrbits_32(pwr_ctrl->pwpr, PWR_ON);
|
||||
mmio_setbits_32(pwr_ctrl->pwpr, PWR_ON);
|
||||
}
|
||||
} else {
|
||||
INFO("[%s:%d] - core_%u haven been power on\n", __func__, __LINE__, cpu_id);
|
||||
}
|
||||
|
||||
return MTK_CPUPM_E_OK;
|
||||
}
|
||||
|
||||
int mt_smp_power_core_off(struct cpu_pwr_ctrl *pwr_ctrl)
|
||||
{
|
||||
/* set mp0_spmc_pwr_on_cpuX = 1 */
|
||||
mmio_clrbits_32(pwr_ctrl->pwpr, PWR_ON);
|
||||
return MTK_CPUPM_E_OK;
|
||||
}
|
||||
|
||||
void mt_smp_init(void)
|
||||
{
|
||||
/* clear RESETPWRON_CONFIG of mcusys/cluster/core0 */
|
||||
mmio_clrbits_32(SPM_MCUSYS_PWR_CON, RESETPWRON_CONFIG);
|
||||
mmio_clrbits_32(SPM_MP0_CPUTOP_PWR_CON, RESETPWRON_CONFIG);
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef MT_SMP_H
|
||||
#define MT_SMP_H
|
||||
|
||||
#include <lib/mmio.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
#define CPU_PWR_STATUS (MCUCFG_BASE + 0xA840)
|
||||
|
||||
#define SMP_CORE_TIMEOUT_MAX (50000)
|
||||
#define DO_SMP_CORE_ON_WAIT_TIMEOUT(k_cnt) ({ \
|
||||
CPU_PM_ASSERT(k_cnt < SMP_CORE_TIMEOUT_MAX); \
|
||||
k_cnt++; udelay(1); })
|
||||
|
||||
void mt_smp_core_init_arch(unsigned int cluster, unsigned int cpu, int arm64,
|
||||
struct cpu_pwr_ctrl *pwr_ctrl);
|
||||
void mt_smp_core_bootup_address_set(struct cpu_pwr_ctrl *pwr_ctrl, uintptr_t entry);
|
||||
int mt_smp_power_core_on(unsigned int cpu_id, struct cpu_pwr_ctrl *pwr_ctrl);
|
||||
int mt_smp_power_core_off(struct cpu_pwr_ctrl *pwr_ctrl);
|
||||
void mt_smp_init(void);
|
||||
|
||||
#endif /* MT_SMP_H */
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
#
|
||||
# Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
LOCAL_DIR := $(call GET_LOCAL_DIR)
|
||||
|
||||
MODULE := cpcv${CONFIG_MTK_CPU_PM_ARCH}
|
||||
|
||||
LOCAL_SRCS-y := ${LOCAL_DIR}/mt_cpu_pm.c ${LOCAL_DIR}/mt_cpu_pm_cpc.c
|
||||
|
||||
LOCAL_SRCS-$(CPU_PM_TINYSYS_SUPPORT) += ${LOCAL_DIR}/mt_cpu_pm_mbox.c
|
||||
LOCAL_SRCS-$(CONFIG_MTK_SMP_EN) += ${LOCAL_DIR}/mt_smp.c
|
||||
|
||||
$(eval $(call add_defined_option,CPU_PM_TINYSYS_SUPPORT))
|
||||
|
||||
$(eval $(call MAKE_MODULE,$(MODULE),$(LOCAL_SRCS-y),$(MTK_BL)))
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
#
|
||||
# Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
LOCAL_DIR := $(call GET_LOCAL_DIR)
|
||||
|
||||
MODULE := cpu_pm
|
||||
|
||||
SUB_RULES-${CONFIG_MTK_CPU_PM_SUPPORT} := $(LOCAL_DIR)/cpcv${CONFIG_MTK_CPU_PM_ARCH}
|
||||
|
||||
$(eval $(call INCLUDE_MAKEFILE,$(SUB_RULES-y)))
|
||||
+402
@@ -0,0 +1,402 @@
|
||||
/*
|
||||
* Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <lib/mmio.h>
|
||||
#include <lib/utils_def.h>
|
||||
#include <mtk_dcm_utils.h>
|
||||
|
||||
#define MP_CPUSYS_TOP_ADB_DCM_REG0_MASK BIT(17)
|
||||
#define MP_CPUSYS_TOP_ADB_DCM_REG1_MASK (BIT(15) | BIT(16) | BIT(17) | \
|
||||
BIT(18) | BIT(21))
|
||||
#define MP_CPUSYS_TOP_ADB_DCM_REG2_MASK (BIT(15) | BIT(16) | BIT(17) | BIT(18))
|
||||
#define MP_CPUSYS_TOP_ADB_DCM_REG0_ON BIT(17)
|
||||
#define MP_CPUSYS_TOP_ADB_DCM_REG1_ON (BIT(15) | BIT(16) | BIT(17) | \
|
||||
BIT(18) | BIT(21))
|
||||
#define MP_CPUSYS_TOP_ADB_DCM_REG2_ON (BIT(15) | BIT(16) | BIT(17) | BIT(18))
|
||||
#define MP_CPUSYS_TOP_ADB_DCM_REG0_OFF (0x0 << 17)
|
||||
#define MP_CPUSYS_TOP_ADB_DCM_REG1_OFF ((0x0 << 15) | (0x0 << 16) | \
|
||||
(0x0 << 17) | (0x0 << 18) | \
|
||||
(0x0 << 21))
|
||||
#define MP_CPUSYS_TOP_ADB_DCM_REG2_OFF ((0x0 << 15) | (0x0 << 16) | \
|
||||
(0x0 << 17) | (0x0 << 18))
|
||||
|
||||
bool dcm_mp_cpusys_top_adb_dcm_is_on(void)
|
||||
{
|
||||
bool ret = true;
|
||||
|
||||
ret &= dcm_check_state(MP_CPUSYS_TOP_MP_ADB_DCM_CFG0,
|
||||
MP_CPUSYS_TOP_ADB_DCM_REG0_MASK,
|
||||
MP_CPUSYS_TOP_ADB_DCM_REG0_ON);
|
||||
ret &= dcm_check_state(MP_CPUSYS_TOP_MP_ADB_DCM_CFG4,
|
||||
MP_CPUSYS_TOP_ADB_DCM_REG1_MASK,
|
||||
MP_CPUSYS_TOP_ADB_DCM_REG1_ON);
|
||||
ret &= dcm_check_state(MP_CPUSYS_TOP_MCUSYS_DCM_CFG0,
|
||||
MP_CPUSYS_TOP_ADB_DCM_REG2_MASK,
|
||||
MP_CPUSYS_TOP_ADB_DCM_REG2_ON);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void dcm_mp_cpusys_top_adb_dcm(bool on)
|
||||
{
|
||||
if (on) {
|
||||
/* TINFO = "Turn ON DCM 'mp_cpusys_top_adb_dcm'" */
|
||||
mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_ADB_DCM_CFG0,
|
||||
MP_CPUSYS_TOP_ADB_DCM_REG0_MASK,
|
||||
MP_CPUSYS_TOP_ADB_DCM_REG0_ON);
|
||||
mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_ADB_DCM_CFG4,
|
||||
MP_CPUSYS_TOP_ADB_DCM_REG1_MASK,
|
||||
MP_CPUSYS_TOP_ADB_DCM_REG1_ON);
|
||||
mmio_clrsetbits_32(MP_CPUSYS_TOP_MCUSYS_DCM_CFG0,
|
||||
MP_CPUSYS_TOP_ADB_DCM_REG2_MASK,
|
||||
MP_CPUSYS_TOP_ADB_DCM_REG2_ON);
|
||||
} else {
|
||||
/* TINFO = "Turn OFF DCM 'mp_cpusys_top_adb_dcm'" */
|
||||
mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_ADB_DCM_CFG0,
|
||||
MP_CPUSYS_TOP_ADB_DCM_REG0_MASK,
|
||||
MP_CPUSYS_TOP_ADB_DCM_REG0_OFF);
|
||||
mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_ADB_DCM_CFG4,
|
||||
MP_CPUSYS_TOP_ADB_DCM_REG1_MASK,
|
||||
MP_CPUSYS_TOP_ADB_DCM_REG1_OFF);
|
||||
mmio_clrsetbits_32(MP_CPUSYS_TOP_MCUSYS_DCM_CFG0,
|
||||
MP_CPUSYS_TOP_ADB_DCM_REG2_MASK,
|
||||
MP_CPUSYS_TOP_ADB_DCM_REG2_OFF);
|
||||
}
|
||||
}
|
||||
|
||||
#define MP_CPUSYS_TOP_APB_DCM_REG0_MASK BIT(5)
|
||||
#define MP_CPUSYS_TOP_APB_DCM_REG1_MASK BIT(8)
|
||||
#define MP_CPUSYS_TOP_APB_DCM_REG2_MASK BIT(16)
|
||||
#define MP_CPUSYS_TOP_APB_DCM_REG0_ON BIT(5)
|
||||
#define MP_CPUSYS_TOP_APB_DCM_REG1_ON BIT(8)
|
||||
#define MP_CPUSYS_TOP_APB_DCM_REG2_ON BIT(16)
|
||||
#define MP_CPUSYS_TOP_APB_DCM_REG0_OFF (0x0 << 5)
|
||||
#define MP_CPUSYS_TOP_APB_DCM_REG1_OFF (0x0 << 8)
|
||||
#define MP_CPUSYS_TOP_APB_DCM_REG2_OFF (0x0 << 16)
|
||||
|
||||
bool dcm_mp_cpusys_top_apb_dcm_is_on(void)
|
||||
{
|
||||
bool ret = true;
|
||||
|
||||
ret &= dcm_check_state(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0,
|
||||
MP_CPUSYS_TOP_APB_DCM_REG0_MASK,
|
||||
MP_CPUSYS_TOP_APB_DCM_REG0_ON);
|
||||
ret &= dcm_check_state(MP_CPUSYS_TOP_MCUSYS_DCM_CFG0,
|
||||
MP_CPUSYS_TOP_APB_DCM_REG1_MASK,
|
||||
MP_CPUSYS_TOP_APB_DCM_REG1_ON);
|
||||
ret &= dcm_check_state(MP_CPUSYS_TOP_MP0_DCM_CFG0,
|
||||
MP_CPUSYS_TOP_APB_DCM_REG2_MASK,
|
||||
MP_CPUSYS_TOP_APB_DCM_REG2_ON);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void dcm_mp_cpusys_top_apb_dcm(bool on)
|
||||
{
|
||||
if (on) {
|
||||
/* TINFO = "Turn ON DCM 'mp_cpusys_top_apb_dcm'" */
|
||||
mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0,
|
||||
MP_CPUSYS_TOP_APB_DCM_REG0_MASK,
|
||||
MP_CPUSYS_TOP_APB_DCM_REG0_ON);
|
||||
mmio_clrsetbits_32(MP_CPUSYS_TOP_MCUSYS_DCM_CFG0,
|
||||
MP_CPUSYS_TOP_APB_DCM_REG1_MASK,
|
||||
MP_CPUSYS_TOP_APB_DCM_REG1_ON);
|
||||
mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG0,
|
||||
MP_CPUSYS_TOP_APB_DCM_REG2_MASK,
|
||||
MP_CPUSYS_TOP_APB_DCM_REG2_ON);
|
||||
} else {
|
||||
/* TINFO = "Turn OFF DCM 'mp_cpusys_top_apb_dcm'" */
|
||||
mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0,
|
||||
MP_CPUSYS_TOP_APB_DCM_REG0_MASK,
|
||||
MP_CPUSYS_TOP_APB_DCM_REG0_OFF);
|
||||
mmio_clrsetbits_32(MP_CPUSYS_TOP_MCUSYS_DCM_CFG0,
|
||||
MP_CPUSYS_TOP_APB_DCM_REG1_MASK,
|
||||
MP_CPUSYS_TOP_APB_DCM_REG1_OFF);
|
||||
mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG0,
|
||||
MP_CPUSYS_TOP_APB_DCM_REG2_MASK,
|
||||
MP_CPUSYS_TOP_APB_DCM_REG2_OFF);
|
||||
}
|
||||
}
|
||||
|
||||
#define MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_MASK (BIT(11) | BIT(24) | BIT(25))
|
||||
#define MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_ON (BIT(11) | BIT(24) | BIT(25))
|
||||
#define MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_OFF ((0x0 << 11) | \
|
||||
(0x0 << 24) | \
|
||||
(0x0 << 25))
|
||||
|
||||
bool dcm_mp_cpusys_top_bus_pll_div_dcm_is_on(void)
|
||||
{
|
||||
return dcm_check_state(MP_CPUSYS_TOP_BUS_PLLDIV_CFG,
|
||||
MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_MASK,
|
||||
MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_ON);
|
||||
}
|
||||
|
||||
void dcm_mp_cpusys_top_bus_pll_div_dcm(bool on)
|
||||
{
|
||||
if (on) {
|
||||
/* TINFO = "Turn ON DCM 'mp_cpusys_top_bus_pll_div_dcm'" */
|
||||
mmio_clrsetbits_32(MP_CPUSYS_TOP_BUS_PLLDIV_CFG,
|
||||
MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_MASK,
|
||||
MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_ON);
|
||||
} else {
|
||||
/* TINFO = "Turn OFF DCM 'mp_cpusys_top_bus_pll_div_dcm'" */
|
||||
mmio_clrsetbits_32(MP_CPUSYS_TOP_BUS_PLLDIV_CFG,
|
||||
MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_MASK,
|
||||
MP_CPUSYS_TOP_BUS_PLL_DIV_DCM_REG0_OFF);
|
||||
}
|
||||
}
|
||||
|
||||
#define MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_MASK BIT(0)
|
||||
#define MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_ON BIT(0)
|
||||
#define MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_OFF (0x0 << 0)
|
||||
|
||||
bool dcm_mp_cpusys_top_core_stall_dcm_is_on(void)
|
||||
{
|
||||
return dcm_check_state(MP_CPUSYS_TOP_MP0_DCM_CFG7,
|
||||
MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_MASK,
|
||||
MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_ON);
|
||||
}
|
||||
|
||||
void dcm_mp_cpusys_top_core_stall_dcm(bool on)
|
||||
{
|
||||
if (on) {
|
||||
/* TINFO = "Turn ON DCM 'mp_cpusys_top_core_stall_dcm'" */
|
||||
mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG7,
|
||||
MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_MASK,
|
||||
MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_ON);
|
||||
} else {
|
||||
/* TINFO = "Turn OFF DCM 'mp_cpusys_top_core_stall_dcm'" */
|
||||
mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG7,
|
||||
MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_MASK,
|
||||
MP_CPUSYS_TOP_CORE_STALL_DCM_REG0_OFF);
|
||||
}
|
||||
}
|
||||
|
||||
#define MP_CPUSYS_TOP_CPUBIU_DCM_REG0_MASK (0xffff << 0)
|
||||
#define MP_CPUSYS_TOP_CPUBIU_DCM_REG0_ON (0xffff << 0)
|
||||
#define MP_CPUSYS_TOP_CPUBIU_DCM_REG0_OFF (0x0 << 0)
|
||||
|
||||
bool dcm_mp_cpusys_top_cpubiu_dcm_is_on(void)
|
||||
{
|
||||
return dcm_check_state(MP_CPUSYS_TOP_MCSIC_DCM0,
|
||||
MP_CPUSYS_TOP_CPUBIU_DCM_REG0_MASK,
|
||||
MP_CPUSYS_TOP_CPUBIU_DCM_REG0_ON);
|
||||
}
|
||||
|
||||
void dcm_mp_cpusys_top_cpubiu_dcm(bool on)
|
||||
{
|
||||
if (on) {
|
||||
/* TINFO = "Turn ON DCM 'mp_cpusys_top_cpubiu_dcm'" */
|
||||
mmio_clrsetbits_32(MP_CPUSYS_TOP_MCSIC_DCM0,
|
||||
MP_CPUSYS_TOP_CPUBIU_DCM_REG0_MASK,
|
||||
MP_CPUSYS_TOP_CPUBIU_DCM_REG0_ON);
|
||||
} else {
|
||||
/* TINFO = "Turn OFF DCM 'mp_cpusys_top_cpubiu_dcm'" */
|
||||
mmio_clrsetbits_32(MP_CPUSYS_TOP_MCSIC_DCM0,
|
||||
MP_CPUSYS_TOP_CPUBIU_DCM_REG0_MASK,
|
||||
MP_CPUSYS_TOP_CPUBIU_DCM_REG0_OFF);
|
||||
}
|
||||
}
|
||||
|
||||
#define MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_MASK (BIT(24) | BIT(25))
|
||||
#define MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_ON (BIT(24) | BIT(25))
|
||||
#define MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_OFF ((0x0 << 24) | (0x0 << 25))
|
||||
|
||||
bool dcm_mp_cpusys_top_cpu_pll_div_0_dcm_is_on(void)
|
||||
{
|
||||
return dcm_check_state(MP_CPUSYS_TOP_CPU_PLLDIV_CFG0,
|
||||
MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_MASK,
|
||||
MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_ON);
|
||||
}
|
||||
|
||||
void dcm_mp_cpusys_top_cpu_pll_div_0_dcm(bool on)
|
||||
{
|
||||
if (on) {
|
||||
/* TINFO = "Turn ON DCM 'mp_cpusys_top_cpu_pll_div_0_dcm'" */
|
||||
mmio_clrsetbits_32(MP_CPUSYS_TOP_CPU_PLLDIV_CFG0,
|
||||
MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_MASK,
|
||||
MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_ON);
|
||||
} else {
|
||||
/* TINFO = "Turn OFF DCM 'mp_cpusys_top_cpu_pll_div_0_dcm'" */
|
||||
mmio_clrsetbits_32(MP_CPUSYS_TOP_CPU_PLLDIV_CFG0,
|
||||
MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_MASK,
|
||||
MP_CPUSYS_TOP_CPU_PLL_DIV_0_DCM_REG0_OFF);
|
||||
}
|
||||
}
|
||||
|
||||
#define MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_MASK (BIT(24) | BIT(25))
|
||||
#define MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_ON (BIT(24) | BIT(25))
|
||||
#define MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_OFF ((0x0 << 24) | (0x0 << 25))
|
||||
|
||||
bool dcm_mp_cpusys_top_cpu_pll_div_1_dcm_is_on(void)
|
||||
{
|
||||
return dcm_check_state(MP_CPUSYS_TOP_CPU_PLLDIV_CFG1,
|
||||
MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_MASK,
|
||||
MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_ON);
|
||||
}
|
||||
|
||||
void dcm_mp_cpusys_top_cpu_pll_div_1_dcm(bool on)
|
||||
{
|
||||
if (on) {
|
||||
/* TINFO = "Turn ON DCM 'mp_cpusys_top_cpu_pll_div_1_dcm'" */
|
||||
mmio_clrsetbits_32(MP_CPUSYS_TOP_CPU_PLLDIV_CFG1,
|
||||
MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_MASK,
|
||||
MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_ON);
|
||||
} else {
|
||||
/* TINFO = "Turn OFF DCM 'mp_cpusys_top_cpu_pll_div_1_dcm'" */
|
||||
mmio_clrsetbits_32(MP_CPUSYS_TOP_CPU_PLLDIV_CFG1,
|
||||
MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_MASK,
|
||||
MP_CPUSYS_TOP_CPU_PLL_DIV_1_DCM_REG0_OFF);
|
||||
}
|
||||
}
|
||||
|
||||
#define MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_MASK BIT(4)
|
||||
#define MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_ON BIT(4)
|
||||
#define MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_OFF (0x0 << 4)
|
||||
|
||||
bool dcm_mp_cpusys_top_fcm_stall_dcm_is_on(void)
|
||||
{
|
||||
return dcm_check_state(MP_CPUSYS_TOP_MP0_DCM_CFG7,
|
||||
MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_MASK,
|
||||
MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_ON);
|
||||
}
|
||||
|
||||
void dcm_mp_cpusys_top_fcm_stall_dcm(bool on)
|
||||
{
|
||||
if (on) {
|
||||
/* TINFO = "Turn ON DCM 'mp_cpusys_top_fcm_stall_dcm'" */
|
||||
mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG7,
|
||||
MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_MASK,
|
||||
MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_ON);
|
||||
} else {
|
||||
/* TINFO = "Turn OFF DCM 'mp_cpusys_top_fcm_stall_dcm'" */
|
||||
mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG7,
|
||||
MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_MASK,
|
||||
MP_CPUSYS_TOP_FCM_STALL_DCM_REG0_OFF);
|
||||
}
|
||||
}
|
||||
|
||||
#define MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_MASK BIT(31)
|
||||
#define MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_ON BIT(31)
|
||||
#define MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_OFF (0x0U << 31)
|
||||
|
||||
bool dcm_mp_cpusys_top_last_cor_idle_dcm_is_on(void)
|
||||
{
|
||||
return dcm_check_state(MP_CPUSYS_TOP_BUS_PLLDIV_CFG,
|
||||
MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_MASK,
|
||||
MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_ON);
|
||||
}
|
||||
|
||||
void dcm_mp_cpusys_top_last_cor_idle_dcm(bool on)
|
||||
{
|
||||
if (on) {
|
||||
/* TINFO = "Turn ON DCM 'mp_cpusys_top_last_cor_idle_dcm'" */
|
||||
mmio_clrsetbits_32(MP_CPUSYS_TOP_BUS_PLLDIV_CFG,
|
||||
MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_MASK,
|
||||
MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_ON);
|
||||
} else {
|
||||
/* TINFO = "Turn OFF DCM 'mp_cpusys_top_last_cor_idle_dcm'" */
|
||||
mmio_clrsetbits_32(MP_CPUSYS_TOP_BUS_PLLDIV_CFG,
|
||||
MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_MASK,
|
||||
MP_CPUSYS_TOP_LAST_COR_IDLE_DCM_REG0_OFF);
|
||||
}
|
||||
}
|
||||
|
||||
#define MP_CPUSYS_TOP_MISC_DCM_REG0_MASK (BIT(1) | BIT(4))
|
||||
#define MP_CPUSYS_TOP_MISC_DCM_REG0_ON (BIT(1) | BIT(4))
|
||||
#define MP_CPUSYS_TOP_MISC_DCM_REG0_OFF ((0x0 << 1) | (0x0 << 4))
|
||||
|
||||
bool dcm_mp_cpusys_top_misc_dcm_is_on(void)
|
||||
{
|
||||
return dcm_check_state(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0,
|
||||
MP_CPUSYS_TOP_MISC_DCM_REG0_MASK,
|
||||
MP_CPUSYS_TOP_MISC_DCM_REG0_ON);
|
||||
}
|
||||
|
||||
void dcm_mp_cpusys_top_misc_dcm(bool on)
|
||||
{
|
||||
if (on) {
|
||||
/* TINFO = "Turn ON DCM 'mp_cpusys_top_misc_dcm'" */
|
||||
mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0,
|
||||
MP_CPUSYS_TOP_MISC_DCM_REG0_MASK,
|
||||
MP_CPUSYS_TOP_MISC_DCM_REG0_ON);
|
||||
} else {
|
||||
/* TINFO = "Turn OFF DCM 'mp_cpusys_top_misc_dcm'" */
|
||||
mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0,
|
||||
MP_CPUSYS_TOP_MISC_DCM_REG0_MASK,
|
||||
MP_CPUSYS_TOP_MISC_DCM_REG0_OFF);
|
||||
}
|
||||
}
|
||||
|
||||
#define MP_CPUSYS_TOP_MP0_QDCM_REG0_MASK BIT(3)
|
||||
#define MP_CPUSYS_TOP_MP0_QDCM_REG1_MASK (BIT(0) | BIT(1) | BIT(2) | BIT(3))
|
||||
#define MP_CPUSYS_TOP_MP0_QDCM_REG0_ON BIT(3)
|
||||
#define MP_CPUSYS_TOP_MP0_QDCM_REG1_ON (BIT(0) | BIT(1) | BIT(2) | BIT(3))
|
||||
#define MP_CPUSYS_TOP_MP0_QDCM_REG0_OFF ((0x0 << 3))
|
||||
#define MP_CPUSYS_TOP_MP0_QDCM_REG1_OFF ((0x0 << 0) | (0x0 << 1) | \
|
||||
(0x0 << 2) | (0x0 << 3))
|
||||
|
||||
bool dcm_mp_cpusys_top_mp0_qdcm_is_on(void)
|
||||
{
|
||||
bool ret = true;
|
||||
|
||||
ret &= dcm_check_state(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0,
|
||||
MP_CPUSYS_TOP_MP0_QDCM_REG0_MASK,
|
||||
MP_CPUSYS_TOP_MP0_QDCM_REG0_ON);
|
||||
ret &= dcm_check_state(MP_CPUSYS_TOP_MP0_DCM_CFG0,
|
||||
MP_CPUSYS_TOP_MP0_QDCM_REG1_MASK,
|
||||
MP_CPUSYS_TOP_MP0_QDCM_REG1_ON);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void dcm_mp_cpusys_top_mp0_qdcm(bool on)
|
||||
{
|
||||
if (on) {
|
||||
/* TINFO = "Turn ON DCM 'mp_cpusys_top_mp0_qdcm'" */
|
||||
mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0,
|
||||
MP_CPUSYS_TOP_MP0_QDCM_REG0_MASK,
|
||||
MP_CPUSYS_TOP_MP0_QDCM_REG0_ON);
|
||||
mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG0,
|
||||
MP_CPUSYS_TOP_MP0_QDCM_REG1_MASK,
|
||||
MP_CPUSYS_TOP_MP0_QDCM_REG1_ON);
|
||||
} else {
|
||||
/* TINFO = "Turn OFF DCM 'mp_cpusys_top_mp0_qdcm'" */
|
||||
mmio_clrsetbits_32(MP_CPUSYS_TOP_MP_MISC_DCM_CFG0,
|
||||
MP_CPUSYS_TOP_MP0_QDCM_REG0_MASK,
|
||||
MP_CPUSYS_TOP_MP0_QDCM_REG0_OFF);
|
||||
mmio_clrsetbits_32(MP_CPUSYS_TOP_MP0_DCM_CFG0,
|
||||
MP_CPUSYS_TOP_MP0_QDCM_REG1_MASK,
|
||||
MP_CPUSYS_TOP_MP0_QDCM_REG1_OFF);
|
||||
}
|
||||
}
|
||||
|
||||
#define CPCCFG_REG_EMI_WFIFO_REG0_MASK (BIT(0) | BIT(1) | BIT(2) | BIT(3))
|
||||
#define CPCCFG_REG_EMI_WFIFO_REG0_ON (BIT(0) | BIT(1) | BIT(2) | BIT(3))
|
||||
#define CPCCFG_REG_EMI_WFIFO_REG0_OFF ((0x0 << 0) | (0x0 << 1) | \
|
||||
(0x0 << 2) | (0x0 << 3))
|
||||
|
||||
bool dcm_cpccfg_reg_emi_wfifo_is_on(void)
|
||||
{
|
||||
return dcm_check_state(CPCCFG_REG_EMI_WFIFO,
|
||||
CPCCFG_REG_EMI_WFIFO_REG0_MASK,
|
||||
CPCCFG_REG_EMI_WFIFO_REG0_ON);
|
||||
}
|
||||
|
||||
void dcm_cpccfg_reg_emi_wfifo(bool on)
|
||||
{
|
||||
if (on) {
|
||||
/* TINFO = "Turn ON DCM 'cpccfg_reg_emi_wfifo'" */
|
||||
mmio_clrsetbits_32(CPCCFG_REG_EMI_WFIFO,
|
||||
CPCCFG_REG_EMI_WFIFO_REG0_MASK,
|
||||
CPCCFG_REG_EMI_WFIFO_REG0_ON);
|
||||
} else {
|
||||
/* TINFO = "Turn OFF DCM 'cpccfg_reg_emi_wfifo'" */
|
||||
mmio_clrsetbits_32(CPCCFG_REG_EMI_WFIFO,
|
||||
CPCCFG_REG_EMI_WFIFO_REG0_MASK,
|
||||
CPCCFG_REG_EMI_WFIFO_REG0_OFF);
|
||||
}
|
||||
}
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef MTK_DCM_UTILS_H
|
||||
#define MTK_DCM_UTILS_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <mtk_dcm.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
/* Base */
|
||||
#define MP_CPUSYS_TOP_BASE (MCUCFG_BASE + 0x8000)
|
||||
#define CPCCFG_REG_BASE (MCUCFG_BASE + 0xA800)
|
||||
|
||||
/* Register Definition */
|
||||
#define CPCCFG_REG_EMI_WFIFO (CPCCFG_REG_BASE + 0x100)
|
||||
#define MP_CPUSYS_TOP_CPU_PLLDIV_CFG0 (MP_CPUSYS_TOP_BASE + 0x22a0)
|
||||
#define MP_CPUSYS_TOP_CPU_PLLDIV_CFG1 (MP_CPUSYS_TOP_BASE + 0x22a4)
|
||||
#define MP_CPUSYS_TOP_BUS_PLLDIV_CFG (MP_CPUSYS_TOP_BASE + 0x22e0)
|
||||
#define MP_CPUSYS_TOP_MCSIC_DCM0 (MP_CPUSYS_TOP_BASE + 0x2440)
|
||||
#define MP_CPUSYS_TOP_MP_ADB_DCM_CFG0 (MP_CPUSYS_TOP_BASE + 0x2500)
|
||||
#define MP_CPUSYS_TOP_MP_ADB_DCM_CFG4 (MP_CPUSYS_TOP_BASE + 0x2510)
|
||||
#define MP_CPUSYS_TOP_MP_MISC_DCM_CFG0 (MP_CPUSYS_TOP_BASE + 0x2518)
|
||||
#define MP_CPUSYS_TOP_MCUSYS_DCM_CFG0 (MP_CPUSYS_TOP_BASE + 0x25c0)
|
||||
#define MP_CPUSYS_TOP_MP0_DCM_CFG0 (MP_CPUSYS_TOP_BASE + 0x4880)
|
||||
#define MP_CPUSYS_TOP_MP0_DCM_CFG7 (MP_CPUSYS_TOP_BASE + 0x489c)
|
||||
|
||||
/* MP_CPUSYS_TOP */
|
||||
bool dcm_mp_cpusys_top_adb_dcm_is_on(void);
|
||||
void dcm_mp_cpusys_top_adb_dcm(bool on);
|
||||
bool dcm_mp_cpusys_top_apb_dcm_is_on(void);
|
||||
void dcm_mp_cpusys_top_apb_dcm(bool on);
|
||||
bool dcm_mp_cpusys_top_bus_pll_div_dcm_is_on(void);
|
||||
void dcm_mp_cpusys_top_bus_pll_div_dcm(bool on);
|
||||
bool dcm_mp_cpusys_top_core_stall_dcm_is_on(void);
|
||||
void dcm_mp_cpusys_top_core_stall_dcm(bool on);
|
||||
bool dcm_mp_cpusys_top_cpubiu_dcm_is_on(void);
|
||||
void dcm_mp_cpusys_top_cpubiu_dcm(bool on);
|
||||
bool dcm_mp_cpusys_top_cpu_pll_div_0_dcm_is_on(void);
|
||||
void dcm_mp_cpusys_top_cpu_pll_div_0_dcm(bool on);
|
||||
bool dcm_mp_cpusys_top_cpu_pll_div_1_dcm_is_on(void);
|
||||
void dcm_mp_cpusys_top_cpu_pll_div_1_dcm(bool on);
|
||||
bool dcm_mp_cpusys_top_fcm_stall_dcm_is_on(void);
|
||||
void dcm_mp_cpusys_top_fcm_stall_dcm(bool on);
|
||||
bool dcm_mp_cpusys_top_last_cor_idle_dcm_is_on(void);
|
||||
void dcm_mp_cpusys_top_last_cor_idle_dcm(bool on);
|
||||
bool dcm_mp_cpusys_top_misc_dcm_is_on(void);
|
||||
void dcm_mp_cpusys_top_misc_dcm(bool on);
|
||||
bool dcm_mp_cpusys_top_mp0_qdcm_is_on(void);
|
||||
void dcm_mp_cpusys_top_mp0_qdcm(bool on);
|
||||
/* CPCCFG_REG */
|
||||
bool dcm_cpccfg_reg_emi_wfifo_is_on(void);
|
||||
void dcm_cpccfg_reg_emi_wfifo(bool on);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <lib/mtk_init/mtk_init.h>
|
||||
#include <mtk_dcm.h>
|
||||
#include <mtk_dcm_utils.h>
|
||||
|
||||
static void dcm_armcore(bool mode)
|
||||
{
|
||||
dcm_mp_cpusys_top_bus_pll_div_dcm(mode);
|
||||
dcm_mp_cpusys_top_cpu_pll_div_0_dcm(mode);
|
||||
dcm_mp_cpusys_top_cpu_pll_div_1_dcm(mode);
|
||||
}
|
||||
|
||||
static void dcm_mcusys(bool on)
|
||||
{
|
||||
dcm_mp_cpusys_top_adb_dcm(on);
|
||||
dcm_mp_cpusys_top_apb_dcm(on);
|
||||
dcm_mp_cpusys_top_cpubiu_dcm(on);
|
||||
dcm_mp_cpusys_top_misc_dcm(on);
|
||||
dcm_mp_cpusys_top_mp0_qdcm(on);
|
||||
|
||||
/* CPCCFG_REG */
|
||||
dcm_cpccfg_reg_emi_wfifo(on);
|
||||
dcm_mp_cpusys_top_last_cor_idle_dcm(on);
|
||||
}
|
||||
|
||||
static void dcm_stall(bool on)
|
||||
{
|
||||
dcm_mp_cpusys_top_core_stall_dcm(on);
|
||||
dcm_mp_cpusys_top_fcm_stall_dcm(on);
|
||||
}
|
||||
|
||||
static bool check_dcm_state(void)
|
||||
{
|
||||
bool ret = true;
|
||||
|
||||
ret &= dcm_mp_cpusys_top_bus_pll_div_dcm_is_on();
|
||||
ret &= dcm_mp_cpusys_top_cpu_pll_div_0_dcm_is_on();
|
||||
ret &= dcm_mp_cpusys_top_cpu_pll_div_1_dcm_is_on();
|
||||
|
||||
ret &= dcm_mp_cpusys_top_adb_dcm_is_on();
|
||||
ret &= dcm_mp_cpusys_top_apb_dcm_is_on();
|
||||
ret &= dcm_mp_cpusys_top_cpubiu_dcm_is_on();
|
||||
ret &= dcm_mp_cpusys_top_misc_dcm_is_on();
|
||||
ret &= dcm_mp_cpusys_top_mp0_qdcm_is_on();
|
||||
ret &= dcm_cpccfg_reg_emi_wfifo_is_on();
|
||||
ret &= dcm_mp_cpusys_top_last_cor_idle_dcm_is_on();
|
||||
|
||||
ret &= dcm_mp_cpusys_top_core_stall_dcm_is_on();
|
||||
ret &= dcm_mp_cpusys_top_fcm_stall_dcm_is_on();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool dcm_check_state(uintptr_t addr, unsigned int mask, unsigned int compare)
|
||||
{
|
||||
return ((mmio_read_32(addr) & mask) == compare);
|
||||
}
|
||||
|
||||
int dcm_set_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
dcm_armcore(true);
|
||||
dcm_mcusys(true);
|
||||
dcm_stall(true);
|
||||
|
||||
if (check_dcm_state() == false) {
|
||||
ERROR("Failed to set default dcm on!!\n");
|
||||
ret = -1;
|
||||
} else {
|
||||
INFO("%s, dcm pass\n", __func__);
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
MTK_PLAT_SETUP_0_INIT(dcm_set_init);
|
||||
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef MTK_DCM_H
|
||||
#define MTK_DCM_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
bool dcm_check_state(uintptr_t addr, unsigned int mask, unsigned int compare);
|
||||
int dcm_set_init(void);
|
||||
|
||||
#endif /* #ifndef MTK_DCM_H */
|
||||
@@ -0,0 +1,17 @@
|
||||
#
|
||||
# Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
LOCAL_DIR := $(call GET_LOCAL_DIR)
|
||||
|
||||
MODULE := mtk_dcm
|
||||
|
||||
LOCAL_SRCS-y := ${LOCAL_DIR}/mtk_dcm.c
|
||||
LOCAL_SRCS-y += ${LOCAL_DIR}/${MTK_SOC}/mtk_dcm_utils.c
|
||||
|
||||
PLAT_INCLUDES += -I${LOCAL_DIR}
|
||||
PLAT_INCLUDES += -I${LOCAL_DIR}/${MTK_SOC}
|
||||
|
||||
$(eval $(call MAKE_MODULE,$(MODULE),$(LOCAL_SRCS-y),$(MTK_BL)))
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#include <arch_helpers.h>
|
||||
#include <common/debug.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <dfd.h>
|
||||
#include <mtk_sip_svc.h>
|
||||
#include <plat_dfd.h>
|
||||
|
||||
static u_register_t dfd_smc_dispatcher(u_register_t arg0, u_register_t arg1,
|
||||
u_register_t arg2, u_register_t arg3,
|
||||
void *handle, struct smccc_res *smccc_ret)
|
||||
{
|
||||
int ret = MTK_SIP_E_SUCCESS;
|
||||
|
||||
switch (arg0) {
|
||||
case PLAT_MTK_DFD_SETUP_MAGIC:
|
||||
INFO("[%s] DFD setup call from kernel\n", __func__);
|
||||
dfd_setup(arg1, arg2, arg3);
|
||||
break;
|
||||
case PLAT_MTK_DFD_READ_MAGIC:
|
||||
/* only allow to access DFD register base + 0x200 */
|
||||
if (arg1 <= 0x200) {
|
||||
ret = mmio_read_32(MISC1_CFG_BASE + arg1);
|
||||
}
|
||||
break;
|
||||
case PLAT_MTK_DFD_WRITE_MAGIC:
|
||||
/* only allow to access DFD register base + 0x200 */
|
||||
if (arg1 <= 0x200) {
|
||||
sync_writel(MISC1_CFG_BASE + arg1, arg2);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ret = MTK_SIP_E_INVALID_PARAM;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
DECLARE_SMC_HANDLER(MTK_SIP_KERNEL_DFD, dfd_smc_dispatcher);
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef DFD_H
|
||||
#define DFD_H
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <lib/mmio.h>
|
||||
|
||||
void dfd_resume(void);
|
||||
void dfd_setup(uint64_t base_addr, uint64_t chain_length, uint64_t cache_dump);
|
||||
|
||||
#endif /* DFD_H */
|
||||
+82
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#include <arch_helpers.h>
|
||||
#include <common/debug.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <dfd.h>
|
||||
#include <plat_dfd.h>
|
||||
|
||||
static uint64_t dfd_cache_dump;
|
||||
static bool dfd_enabled;
|
||||
static uint64_t dfd_base_addr;
|
||||
static uint64_t dfd_chain_length;
|
||||
|
||||
void dfd_setup(uint64_t base_addr, uint64_t chain_length, uint64_t cache_dump)
|
||||
{
|
||||
mmio_write_32(MTK_DRM_LATCH_CTL1, MTK_DRM_LATCH_CTL1_VAL);
|
||||
mmio_write_32(MTK_DRM_LATCH_CTL2, MTK_DRM_LATCH_CTL2_VAL);
|
||||
mmio_write_32(MTK_WDT_LATCH_CTL2, MTK_WDT_LATCH_CTL2_VAL);
|
||||
|
||||
mmio_clrbits_32(DFD_O_INTRF_MCU_PWR_CTL_MASK, BIT(2));
|
||||
mmio_setbits_32(DFD_V50_GROUP_0_63_DIFF, 0x1);
|
||||
sync_writel(DFD_INTERNAL_CTL, 0x5);
|
||||
mmio_setbits_32(DFD_INTERNAL_CTL, BIT(13));
|
||||
mmio_setbits_32(DFD_INTERNAL_CTL, 0x1F << 3);
|
||||
mmio_setbits_32(DFD_INTERNAL_CTL, 0x3 << 9);
|
||||
mmio_setbits_32(DFD_INTERNAL_CTL, 0x3 << 19);
|
||||
|
||||
mmio_write_32(DFD_INTERNAL_PWR_ON, 0xB);
|
||||
mmio_write_32(DFD_CHAIN_LENGTH0, chain_length);
|
||||
mmio_write_32(DFD_INTERNAL_SHIFT_CLK_RATIO, 0x0);
|
||||
mmio_write_32(DFD_INTERNAL_TEST_SO_OVER_64, 0x1);
|
||||
|
||||
mmio_write_32(DFD_TEST_SI_0, 0x0);
|
||||
mmio_write_32(DFD_TEST_SI_1, 0x0);
|
||||
mmio_write_32(DFD_TEST_SI_2, 0x0);
|
||||
mmio_write_32(DFD_TEST_SI_3, 0x0);
|
||||
|
||||
sync_writel(DFD_POWER_CTL, 0xF9);
|
||||
sync_writel(DFD_READ_ADDR, DFD_READ_ADDR_VAL);
|
||||
sync_writel(DFD_V30_CTL, 0xD);
|
||||
|
||||
mmio_write_32(DFD_O_SET_BASEADDR_REG, base_addr >> 24);
|
||||
mmio_write_32(DFD_O_REG_0, 0);
|
||||
|
||||
/* setup global variables for suspend and resume */
|
||||
dfd_enabled = true;
|
||||
dfd_base_addr = base_addr;
|
||||
dfd_chain_length = chain_length;
|
||||
dfd_cache_dump = cache_dump;
|
||||
|
||||
if ((cache_dump & DFD_CACHE_DUMP_ENABLE) != 0UL) {
|
||||
mmio_write_32(MTK_DRM_LATCH_CTL2, MTK_DRM_LATCH_CTL2_CACHE_VAL);
|
||||
sync_writel(DFD_V35_ENABLE, 0x1);
|
||||
sync_writel(DFD_V35_TAP_NUMBER, 0xB);
|
||||
sync_writel(DFD_V35_TAP_EN, DFD_V35_TAP_EN_VAL);
|
||||
sync_writel(DFD_V35_SEQ0_0, DFD_V35_SEQ0_0_VAL);
|
||||
|
||||
/* Cache dump only mode */
|
||||
sync_writel(DFD_V35_CTL, 0x1);
|
||||
mmio_write_32(DFD_INTERNAL_NUM_OF_TEST_SO_GROUP, 0xF);
|
||||
mmio_write_32(DFD_CHAIN_LENGTH0, DFD_CHAIN_LENGTH_VAL);
|
||||
mmio_write_32(DFD_CHAIN_LENGTH1, DFD_CHAIN_LENGTH_VAL);
|
||||
mmio_write_32(DFD_CHAIN_LENGTH2, DFD_CHAIN_LENGTH_VAL);
|
||||
mmio_write_32(DFD_CHAIN_LENGTH3, DFD_CHAIN_LENGTH_VAL);
|
||||
|
||||
if ((cache_dump & DFD_PARITY_ERR_TRIGGER) != 0UL) {
|
||||
sync_writel(DFD_HW_TRIGGER_MASK, 0xC);
|
||||
mmio_setbits_32(DFD_INTERNAL_CTL, 0x1 << 4);
|
||||
}
|
||||
}
|
||||
dsbsy();
|
||||
}
|
||||
|
||||
void dfd_resume(void)
|
||||
{
|
||||
if (dfd_enabled == true) {
|
||||
dfd_setup(dfd_base_addr, dfd_chain_length, dfd_cache_dump);
|
||||
}
|
||||
}
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef PLAT_DFD_H
|
||||
#define PLAT_DFD_H
|
||||
|
||||
#include <lib/mmio.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
#define sync_writel(addr, val) do { mmio_write_32((addr), (val)); dsbsy(); } while (0)
|
||||
|
||||
#define PLAT_MTK_DFD_SETUP_MAGIC (0x99716150)
|
||||
#define PLAT_MTK_DFD_READ_MAGIC (0x99716151)
|
||||
#define PLAT_MTK_DFD_WRITE_MAGIC (0x99716152)
|
||||
|
||||
#define MTK_DRM_LATCH_CTL1 (DRM_BASE + 0x40)
|
||||
#define MTK_DRM_LATCH_CTL2 (DRM_BASE + 0x44)
|
||||
|
||||
#define MTK_WDT_BASE (RGU_BASE)
|
||||
#define MTK_WDT_INTERVAL (MTK_WDT_BASE + 0x10)
|
||||
#define MTK_WDT_LATCH_CTL2 (MTK_WDT_BASE + 0x48)
|
||||
|
||||
#define MCU_BIU_BASE (MCUCFG_BASE)
|
||||
#define MISC1_CFG_BASE (MCU_BIU_BASE + 0xE040)
|
||||
#define DFD_INTERNAL_CTL (MISC1_CFG_BASE + 0x00)
|
||||
#define DFD_INTERNAL_PWR_ON (MISC1_CFG_BASE + 0x08)
|
||||
#define DFD_CHAIN_LENGTH0 (MISC1_CFG_BASE + 0x0C)
|
||||
#define DFD_INTERNAL_SHIFT_CLK_RATIO (MISC1_CFG_BASE + 0x10)
|
||||
#define DFD_CHAIN_LENGTH1 (MISC1_CFG_BASE + 0x1C)
|
||||
#define DFD_CHAIN_LENGTH2 (MISC1_CFG_BASE + 0x20)
|
||||
#define DFD_CHAIN_LENGTH3 (MISC1_CFG_BASE + 0x24)
|
||||
#define DFD_INTERNAL_TEST_SO_0 (MISC1_CFG_BASE + 0x28)
|
||||
#define DFD_INTERNAL_NUM_OF_TEST_SO_GROUP (MISC1_CFG_BASE + 0x30)
|
||||
#define DFD_INTERNAL_TEST_SO_OVER_64 (MISC1_CFG_BASE + 0x34)
|
||||
#define DFD_INTERNAL_SW_NS_TRIGGER (MISC1_CFG_BASE + 0x3c)
|
||||
#define DFD_V30_CTL (MISC1_CFG_BASE + 0x48)
|
||||
#define DFD_V30_BASE_ADDR (MISC1_CFG_BASE + 0x4C)
|
||||
#define DFD_POWER_CTL (MISC1_CFG_BASE + 0x50)
|
||||
#define DFD_TEST_SI_0 (MISC1_CFG_BASE + 0x58)
|
||||
#define DFD_TEST_SI_1 (MISC1_CFG_BASE + 0x5C)
|
||||
#define DFD_CLEAN_STATUS (MISC1_CFG_BASE + 0x60)
|
||||
#define DFD_TEST_SI_2 (MISC1_CFG_BASE + 0x1D8)
|
||||
#define DFD_TEST_SI_3 (MISC1_CFG_BASE + 0x1DC)
|
||||
#define DFD_READ_ADDR (MISC1_CFG_BASE + 0x1E8)
|
||||
#define DFD_HW_TRIGGER_MASK (MISC1_CFG_BASE + 0xBC)
|
||||
|
||||
#define DFD_V35_ENABLE (MCU_BIU_BASE + 0xE0A8)
|
||||
#define DFD_V35_TAP_NUMBER (MCU_BIU_BASE + 0xE0AC)
|
||||
#define DFD_V35_TAP_EN (MCU_BIU_BASE + 0xE0B0)
|
||||
#define DFD_V35_CTL (MCU_BIU_BASE + 0xE0B4)
|
||||
#define DFD_V35_SEQ0_0 (MCU_BIU_BASE + 0xE0C0)
|
||||
#define DFD_V35_SEQ0_1 (MCU_BIU_BASE + 0xE0C4)
|
||||
#define DFD_V50_GROUP_0_63_DIFF (MCU_BIU_BASE + 0xE2AC)
|
||||
|
||||
#define DFD_O_PROTECT_EN_REG (0x10001220)
|
||||
#define DFD_O_INTRF_MCU_PWR_CTL_MASK (0x10001A3C)
|
||||
#define DFD_O_SET_BASEADDR_REG (0x10043000)
|
||||
#define DFD_O_REG_0 (0x10001390)
|
||||
|
||||
#define DFD_CACHE_DUMP_ENABLE (1U)
|
||||
#define DFD_PARITY_ERR_TRIGGER (2U)
|
||||
|
||||
#define DFD_V35_TAP_EN_VAL (0x43FF)
|
||||
#define DFD_V35_SEQ0_0_VAL (0x63668820)
|
||||
#define DFD_READ_ADDR_VAL (0x40000008)
|
||||
#define DFD_CHAIN_LENGTH_VAL (0xFFFFFFFF)
|
||||
|
||||
#define MTK_WDT_LATCH_CTL2_VAL (0x9507FFFF)
|
||||
#define MTK_WDT_INTERVAL_VAL (0x6600000A)
|
||||
#define MTK_DRM_LATCH_CTL2_VAL (0x950607D0)
|
||||
#define MTK_DRM_LATCH_CTL2_CACHE_VAL (0x95065DC0)
|
||||
|
||||
#define MTK_DRM_LATCH_CTL1_VAL (0x95000013)
|
||||
|
||||
#endif /* PLAT_DFD_H */
|
||||
@@ -0,0 +1,17 @@
|
||||
#
|
||||
# Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
LOCAL_DIR := $(call GET_LOCAL_DIR)
|
||||
|
||||
MODULE := mtk_dfd
|
||||
|
||||
LOCAL_SRCS-y := ${LOCAL_DIR}/dfd.c
|
||||
LOCAL_SRCS-y += ${LOCAL_DIR}/$(MTK_SOC)/plat_dfd.c
|
||||
|
||||
PLAT_INCLUDES += -I${LOCAL_DIR}
|
||||
PLAT_INCLUDES += -I${LOCAL_DIR}/$(MTK_SOC)
|
||||
|
||||
$(eval $(call MAKE_MODULE,$(MODULE),$(LOCAL_SRCS-y),$(MTK_BL)))
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2022, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <mt_dp.h>
|
||||
#include <mtk_sip_svc.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
static uint32_t dp_write_sec_reg(uint32_t is_edp, uint32_t offset,
|
||||
uint32_t value, uint32_t mask)
|
||||
{
|
||||
uint32_t reg = (is_edp != 0U) ? EDP_SEC_BASE : DP_SEC_BASE;
|
||||
|
||||
mmio_clrsetbits_32(reg + offset, mask, value);
|
||||
|
||||
return mmio_read_32(reg + offset);
|
||||
}
|
||||
|
||||
int32_t dp_secure_handler(uint64_t cmd, uint64_t para, uint32_t *val)
|
||||
{
|
||||
int32_t ret = 0L;
|
||||
uint32_t is_edp = 0UL;
|
||||
uint32_t regval = 0UL;
|
||||
uint32_t regmsk = 0UL;
|
||||
uint32_t fldmask = 0UL;
|
||||
|
||||
if ((cmd > DP_ATF_CMD_COUNT) || (val == NULL)) {
|
||||
INFO("dp_secure_handler error cmd 0x%" PRIx64 "\n", cmd);
|
||||
return MTK_SIP_E_INVALID_PARAM;
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
case DP_ATF_DP_VIDEO_UNMUTE:
|
||||
INFO("[%s] DP_ATF_DP_VIDEO_UNMUTE\n", __func__);
|
||||
is_edp = DP_ATF_TYPE_DP;
|
||||
ret = MTK_SIP_E_SUCCESS;
|
||||
break;
|
||||
case DP_ATF_EDP_VIDEO_UNMUTE:
|
||||
INFO("[%s] DP_ATF_EDP_VIDEO_UNMUTE\n", __func__);
|
||||
is_edp = DP_ATF_TYPE_EDP;
|
||||
ret = MTK_SIP_E_SUCCESS;
|
||||
break;
|
||||
default:
|
||||
ret = MTK_SIP_E_INVALID_PARAM;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret == MTK_SIP_E_SUCCESS) {
|
||||
regmsk = (VIDEO_MUTE_SEL_SECURE_FLDMASK |
|
||||
VIDEO_MUTE_SW_SECURE_FLDMASK);
|
||||
if (para > 0U) {
|
||||
fldmask = VIDEO_MUTE_SW_SECURE_FLDMASK;
|
||||
} else {
|
||||
fldmask = 0;
|
||||
}
|
||||
|
||||
regval = (VIDEO_MUTE_SEL_SECURE_FLDMASK | fldmask);
|
||||
*val = dp_write_sec_reg(is_edp, DP_TX_SECURE_REG11,
|
||||
regval, regmsk);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
u_register_t mtk_dp_sip_handler(u_register_t x1, u_register_t x2,
|
||||
u_register_t x3, u_register_t x4,
|
||||
void *handle, struct smccc_res *smccc_ret)
|
||||
{
|
||||
uint32_t ret_val;
|
||||
|
||||
return dp_secure_handler(x1, x2, &ret_val);
|
||||
}
|
||||
DECLARE_SMC_HANDLER(MTK_SIP_DP_CONTROL, mtk_dp_sip_handler);
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2022, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef MT_DP_H
|
||||
#define MT_DP_H
|
||||
|
||||
#define DP_TX_SECURE_REG11 (0x2c)
|
||||
|
||||
#define VIDEO_MUTE_SEL_SECURE_FLDMASK (0x10)
|
||||
#define VIDEO_MUTE_SW_SECURE_FLDMASK (0x8)
|
||||
|
||||
enum DP_ATF_HW_TYPE {
|
||||
DP_ATF_TYPE_DP = 0,
|
||||
DP_ATF_TYPE_EDP = 1
|
||||
};
|
||||
|
||||
enum DP_ATF_CMD {
|
||||
DP_ATF_DP_VIDEO_UNMUTE = 0x20,
|
||||
DP_ATF_EDP_VIDEO_UNMUTE,
|
||||
DP_ATF_CMD_COUNT
|
||||
};
|
||||
|
||||
int32_t dp_secure_handler(uint64_t cmd, uint64_t para, uint32_t *val);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,14 @@
|
||||
#
|
||||
# Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
LOCAL_DIR := $(call GET_LOCAL_DIR)
|
||||
|
||||
MODULE := dp
|
||||
LOCAL_SRCS-y := $(LOCAL_DIR)/mt_dp.c
|
||||
|
||||
PLAT_INCLUDES += -I${LOCAL_DIR}
|
||||
|
||||
$(eval $(call MAKE_MODULE,$(MODULE),$(LOCAL_SRCS-y),$(MTK_BL)))
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (c) 2022, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef EMI_MPU_H
|
||||
#define EMI_MPU_H
|
||||
|
||||
#include <emi_mpu_priv.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
#define NO_PROTECTION (0)
|
||||
#define SEC_RW (1)
|
||||
#define SEC_RW_NSEC_R (2)
|
||||
#define SEC_RW_NSEC_W (3)
|
||||
#define SEC_R_NSEC_R (4)
|
||||
#define FORBIDDEN (5)
|
||||
#define SEC_R_NSEC_RW (6)
|
||||
|
||||
#define LOCK (1)
|
||||
#define UNLOCK (0)
|
||||
|
||||
#if (EMI_MPU_DGROUP_NUM == 1)
|
||||
#define SET_ACCESS_PERMISSION(apc_ary, lock, d7, d6, d5, d4, d3, d2, d1, d0) \
|
||||
do { \
|
||||
apc_ary[1] = 0; \
|
||||
apc_ary[0] = \
|
||||
(((unsigned int) d7) << 21) | (((unsigned int) d6) << 18) | \
|
||||
(((unsigned int) d5) << 15) | (((unsigned int) d4) << 12) | \
|
||||
(((unsigned int) d3) << 9) | (((unsigned int) d2) << 6) | \
|
||||
(((unsigned int) d1) << 3) | ((unsigned int) d0) | \
|
||||
((unsigned int) lock << 31); \
|
||||
} while (0)
|
||||
#elif (EMI_MPU_DGROUP_NUM == 2)
|
||||
#define SET_ACCESS_PERMISSION(apc_ary, lock, d15, d14, d13, d12, d11, d10, \
|
||||
d9, d8, d7, d6, d5, d4, d3, d2, d1, d0) \
|
||||
do { \
|
||||
apc_ary[1] = \
|
||||
(((unsigned int) d15) << 21) | (((unsigned int) d14) << 18) | \
|
||||
(((unsigned int) d13) << 15) | (((unsigned int) d12) << 12) | \
|
||||
(((unsigned int) d11) << 9) | (((unsigned int) d10) << 6) | \
|
||||
(((unsigned int) d9) << 3) | ((unsigned int) d8); \
|
||||
apc_ary[0] = \
|
||||
(((unsigned int) d7) << 21) | (((unsigned int) d6) << 18) | \
|
||||
(((unsigned int) d5) << 15) | (((unsigned int) d4) << 12) | \
|
||||
(((unsigned int) d3) << 9) | (((unsigned int) d2) << 6) | \
|
||||
(((unsigned int) d1) << 3) | ((unsigned int) d0) | \
|
||||
((unsigned int) lock << 31); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
struct emi_region_info_t {
|
||||
unsigned long long start;
|
||||
unsigned long long end;
|
||||
unsigned int region;
|
||||
unsigned int apc[EMI_MPU_DGROUP_NUM];
|
||||
};
|
||||
|
||||
int emi_mpu_init(void);
|
||||
int emi_mpu_set_protection(struct emi_region_info_t *region_info);
|
||||
void set_emi_mpu_regions(void);
|
||||
|
||||
#endif
|
||||
+123
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright (c) 2022, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <common/debug.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <emi_mpu.h>
|
||||
#include <lib/mtk_init/mtk_init.h>
|
||||
|
||||
#if ENABLE_EMI_MPU_SW_LOCK
|
||||
static unsigned char region_lock_state[EMI_MPU_REGION_NUM];
|
||||
#endif
|
||||
|
||||
#define EMI_MPU_START_MASK (0x00FFFFFF)
|
||||
#define EMI_MPU_END_MASK (0x00FFFFFF)
|
||||
#define EMI_MPU_APC_SW_LOCK_MASK (0x00FFFFFF)
|
||||
#define EMI_MPU_APC_HW_LOCK_MASK (0x80FFFFFF)
|
||||
|
||||
static int _emi_mpu_set_protection(unsigned int start, unsigned int end,
|
||||
unsigned int apc)
|
||||
{
|
||||
unsigned int dgroup;
|
||||
unsigned int region;
|
||||
|
||||
region = (start >> 24) & 0xFF;
|
||||
start &= EMI_MPU_START_MASK;
|
||||
dgroup = (end >> 24) & 0xFF;
|
||||
end &= EMI_MPU_END_MASK;
|
||||
|
||||
if ((region >= EMI_MPU_REGION_NUM) || (dgroup > EMI_MPU_DGROUP_NUM)) {
|
||||
WARN("invalid region, domain\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if ENABLE_EMI_MPU_SW_LOCK
|
||||
if (region_lock_state[region] == 1) {
|
||||
WARN("invalid region\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((dgroup == 0) && ((apc >> 31) & 0x1)) {
|
||||
region_lock_state[region] = 1;
|
||||
}
|
||||
|
||||
apc &= EMI_MPU_APC_SW_LOCK_MASK;
|
||||
#else
|
||||
apc &= EMI_MPU_APC_HW_LOCK_MASK;
|
||||
#endif
|
||||
|
||||
if ((start >= DRAM_OFFSET) && (end >= start)) {
|
||||
start -= DRAM_OFFSET;
|
||||
end -= DRAM_OFFSET;
|
||||
} else {
|
||||
WARN("invalid range\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
mmio_write_32(EMI_MPU_SA(region), start);
|
||||
mmio_write_32(EMI_MPU_EA(region), end);
|
||||
mmio_write_32(EMI_MPU_APC(region, dgroup), apc);
|
||||
|
||||
#if defined(SUB_EMI_MPU_BASE)
|
||||
mmio_write_32(SUB_EMI_MPU_SA(region), start);
|
||||
mmio_write_32(SUB_EMI_MPU_EA(region), end);
|
||||
mmio_write_32(SUB_EMI_MPU_APC(region, dgroup), apc);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dump_emi_mpu_regions(void)
|
||||
{
|
||||
int region, i;
|
||||
|
||||
/* Only dump 8 regions(max: EMI_MPU_REGION_NUM --> 32) */
|
||||
for (region = 0; region < 8; ++region) {
|
||||
INFO("region %d:\n", region);
|
||||
INFO("\tsa: 0x%x, ea: 0x%x\n",
|
||||
mmio_read_32(EMI_MPU_SA(region)), mmio_read_32(EMI_MPU_EA(region)));
|
||||
|
||||
for (i = 0; i < EMI_MPU_DGROUP_NUM; ++i) {
|
||||
INFO("\tapc%d: 0x%x\n", i, mmio_read_32(EMI_MPU_APC(region, i)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int emi_mpu_set_protection(struct emi_region_info_t *region_info)
|
||||
{
|
||||
unsigned int start, end;
|
||||
int i;
|
||||
|
||||
if (region_info->region >= EMI_MPU_REGION_NUM) {
|
||||
WARN("invalid region\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
start = (unsigned int)(region_info->start >> EMI_MPU_ALIGN_BITS) |
|
||||
(region_info->region << 24);
|
||||
|
||||
for (i = EMI_MPU_DGROUP_NUM - 1; i >= 0; i--) {
|
||||
end = (unsigned int)(region_info->end >> EMI_MPU_ALIGN_BITS) | (i << 24);
|
||||
|
||||
if (_emi_mpu_set_protection(start, end, region_info->apc[i]) < 0) {
|
||||
WARN("Failed to set emi mpu protection(%d, %d, %d)\n",
|
||||
start, end, region_info->apc[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int emi_mpu_init(void)
|
||||
{
|
||||
INFO("[%s] emi mpu initialization\n", __func__);
|
||||
|
||||
set_emi_mpu_regions();
|
||||
dump_emi_mpu_regions();
|
||||
|
||||
return 0;
|
||||
}
|
||||
MTK_PLAT_SETUP_0_INIT(emi_mpu_init);
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright (c) 2022, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <emi_mpu.h>
|
||||
|
||||
void set_emi_mpu_regions(void)
|
||||
{
|
||||
/* TODO: set emi mpu region */
|
||||
INFO("%s, emi mpu is not setting currently\n", __func__);
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2022, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef EMI_MPU_PRIV_H
|
||||
#define EMI_MPU_PRIV_H
|
||||
|
||||
#define ENABLE_EMI_MPU_SW_LOCK (1)
|
||||
|
||||
#define EMI_MPU_CTRL (EMI_MPU_BASE + 0x000)
|
||||
#define EMI_MPU_DBG (EMI_MPU_BASE + 0x004)
|
||||
#define EMI_MPU_SA0 (EMI_MPU_BASE + 0x100)
|
||||
#define EMI_MPU_EA0 (EMI_MPU_BASE + 0x200)
|
||||
#define EMI_MPU_SA(region) (EMI_MPU_SA0 + (region * 4))
|
||||
#define EMI_MPU_EA(region) (EMI_MPU_EA0 + (region * 4))
|
||||
#define EMI_MPU_APC0 (EMI_MPU_BASE + 0x300)
|
||||
#define EMI_MPU_APC(region, dgroup) (EMI_MPU_APC0 + (region * 4) + (dgroup * 0x100))
|
||||
#define EMI_MPU_CTRL_D0 (EMI_MPU_BASE + 0x800)
|
||||
#define EMI_MPU_CTRL_D(domain) (EMI_MPU_CTRL_D0 + (domain * 4))
|
||||
#define EMI_RG_MASK_D0 (EMI_MPU_BASE + 0x900)
|
||||
#define EMI_RG_MASK_D(domain) (EMI_RG_MASK_D0 + (domain * 4))
|
||||
|
||||
#define SUB_EMI_MPU_CTRL (SUB_EMI_MPU_BASE + 0x000)
|
||||
#define SUB_EMI_MPU_DBG (SUB_EMI_MPU_BASE + 0x004)
|
||||
#define SUB_EMI_MPU_SA0 (SUB_EMI_MPU_BASE + 0x100)
|
||||
#define SUB_EMI_MPU_EA0 (SUB_EMI_MPU_BASE + 0x200)
|
||||
#define SUB_EMI_MPU_SA(region) (SUB_EMI_MPU_SA0 + (region * 4))
|
||||
#define SUB_EMI_MPU_EA(region) (SUB_EMI_MPU_EA0 + (region * 4))
|
||||
#define SUB_EMI_MPU_APC0 (SUB_EMI_MPU_BASE + 0x300)
|
||||
#define SUB_EMI_MPU_APC(region, dgroup) (SUB_EMI_MPU_APC0 + (region * 4) + (dgroup * 0x100))
|
||||
#define SUB_EMI_MPU_CTRL_D0 (SUB_EMI_MPU_BASE + 0x800)
|
||||
#define SUB_EMI_MPU_CTRL_D(domain) (SUB_EMI_MPU_CTRL_D0 + (domain * 4))
|
||||
#define SUB_EMI_RG_MASK_D0 (SUB_EMI_MPU_BASE + 0x900)
|
||||
#define SUB_EMI_RG_MASK_D(domain) (SUB_EMI_RG_MASK_D0 + (domain * 4))
|
||||
|
||||
#define EMI_MPU_DOMAIN_NUM (16)
|
||||
#define EMI_MPU_REGION_NUM (32)
|
||||
#define EMI_MPU_ALIGN_BITS (16)
|
||||
#define DRAM_OFFSET (0x40000000 >> EMI_MPU_ALIGN_BITS)
|
||||
|
||||
#define EMI_MPU_DGROUP_NUM (EMI_MPU_DOMAIN_NUM / 8)
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,16 @@
|
||||
#
|
||||
# Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
LOCAL_DIR := $(call GET_LOCAL_DIR)
|
||||
|
||||
MODULE := emi_mpu
|
||||
LOCAL_SRCS-y := $(LOCAL_DIR)/emi_mpu_common.c
|
||||
LOCAL_SRCS-y += ${LOCAL_DIR}/${MTK_SOC}/emi_mpu.c
|
||||
|
||||
PLAT_INCLUDES += -I${LOCAL_DIR}
|
||||
PLAT_INCLUDES += -I${LOCAL_DIR}/${MTK_SOC}
|
||||
|
||||
$(eval $(call MAKE_MODULE,$(MODULE),$(LOCAL_SRCS-y),$(MTK_BL)))
|
||||
+208
@@ -0,0 +1,208 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2022, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "../drivers/arm/gic/v3/gicv3_private.h"
|
||||
#include <bl31/interrupt_mgmt.h>
|
||||
#include <common/bl_common.h>
|
||||
#include <common/debug.h>
|
||||
#include <lib/mtk_init/mtk_init.h>
|
||||
#include <mt_gic_v3.h>
|
||||
#include <mtk_plat_common.h>
|
||||
#include <plat/common/platform.h>
|
||||
#include <plat_private.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
#define SGI_MASK 0xffff
|
||||
|
||||
uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT];
|
||||
static uint32_t rdist_has_saved[PLATFORM_CORE_COUNT];
|
||||
|
||||
/* we save and restore the GICv3 context on system suspend */
|
||||
gicv3_dist_ctx_t dist_ctx;
|
||||
|
||||
static unsigned int mt_mpidr_to_core_pos(u_register_t mpidr)
|
||||
{
|
||||
return plat_core_pos_by_mpidr(mpidr);
|
||||
}
|
||||
|
||||
gicv3_driver_data_t mt_gicv3_data = {
|
||||
.gicd_base = MT_GIC_BASE,
|
||||
.gicr_base = MT_GIC_RDIST_BASE,
|
||||
.rdistif_num = PLATFORM_CORE_COUNT,
|
||||
.rdistif_base_addrs = rdistif_base_addrs,
|
||||
.mpidr_to_core_pos = mt_mpidr_to_core_pos,
|
||||
};
|
||||
|
||||
struct gic_chip_data {
|
||||
/* All cores share the same configuration */
|
||||
unsigned int saved_group;
|
||||
unsigned int saved_enable;
|
||||
unsigned int saved_conf0;
|
||||
unsigned int saved_conf1;
|
||||
unsigned int saved_grpmod;
|
||||
/* Per-core sgi */
|
||||
unsigned int saved_sgi[PLATFORM_CORE_COUNT];
|
||||
};
|
||||
|
||||
static struct gic_chip_data gic_data;
|
||||
|
||||
void mt_gic_driver_init(void)
|
||||
{
|
||||
gicv3_driver_init(&mt_gicv3_data);
|
||||
}
|
||||
|
||||
void mt_gic_set_pending(uint32_t irq)
|
||||
{
|
||||
gicv3_set_interrupt_pending(irq, plat_my_core_pos());
|
||||
}
|
||||
|
||||
void mt_gic_distif_save(void)
|
||||
{
|
||||
gicv3_distif_save(&dist_ctx);
|
||||
}
|
||||
|
||||
void mt_gic_distif_restore(void)
|
||||
{
|
||||
gicv3_distif_init_restore(&dist_ctx);
|
||||
}
|
||||
|
||||
void mt_gic_rdistif_init(void)
|
||||
{
|
||||
unsigned int proc_num;
|
||||
unsigned int index;
|
||||
uintptr_t gicr_base;
|
||||
|
||||
proc_num = plat_my_core_pos();
|
||||
gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num];
|
||||
|
||||
/* set all SGI/PPI as non-secure GROUP1 by default */
|
||||
mmio_write_32(gicr_base + GICR_IGROUPR0, ~0U);
|
||||
mmio_write_32(gicr_base + GICR_IGRPMODR0, 0x0);
|
||||
|
||||
/* setup the default PPI/SGI priorities */
|
||||
for (index = 0; index < TOTAL_PCPU_INTR_NUM; index += 4U)
|
||||
gicr_write_ipriorityr(gicr_base, index,
|
||||
GICD_IPRIORITYR_DEF_VAL);
|
||||
}
|
||||
|
||||
void mt_gic_rdistif_save(void)
|
||||
{
|
||||
unsigned int proc_num;
|
||||
uintptr_t gicr_base;
|
||||
|
||||
proc_num = plat_my_core_pos();
|
||||
gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num];
|
||||
|
||||
gic_data.saved_group = mmio_read_32(gicr_base + GICR_IGROUPR0);
|
||||
gic_data.saved_enable = mmio_read_32(gicr_base + GICR_ISENABLER0);
|
||||
gic_data.saved_conf0 = mmio_read_32(gicr_base + GICR_ICFGR0);
|
||||
gic_data.saved_conf1 = mmio_read_32(gicr_base + GICR_ICFGR1);
|
||||
gic_data.saved_grpmod = mmio_read_32(gicr_base + GICR_IGRPMODR0);
|
||||
|
||||
rdist_has_saved[proc_num] = 1;
|
||||
}
|
||||
|
||||
void mt_gic_rdistif_restore(void)
|
||||
{
|
||||
unsigned int proc_num;
|
||||
uintptr_t gicr_base;
|
||||
|
||||
proc_num = plat_my_core_pos();
|
||||
if (rdist_has_saved[proc_num] == 1) {
|
||||
gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num];
|
||||
mmio_write_32(gicr_base + GICR_IGROUPR0, gic_data.saved_group);
|
||||
mmio_write_32(gicr_base + GICR_ISENABLER0,
|
||||
gic_data.saved_enable);
|
||||
mmio_write_32(gicr_base + GICR_ICFGR0, gic_data.saved_conf0);
|
||||
mmio_write_32(gicr_base + GICR_ICFGR1, gic_data.saved_conf1);
|
||||
mmio_write_32(gicr_base + GICR_IGRPMODR0,
|
||||
gic_data.saved_grpmod);
|
||||
}
|
||||
}
|
||||
|
||||
void mt_gic_rdistif_restore_all(void)
|
||||
{
|
||||
unsigned int proc_num;
|
||||
uintptr_t gicr_base;
|
||||
|
||||
for (proc_num = 0; proc_num < PLATFORM_CORE_COUNT; proc_num++) {
|
||||
gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num];
|
||||
mmio_write_32(gicr_base + GICR_IGROUPR0, gic_data.saved_group);
|
||||
mmio_write_32(gicr_base + GICR_ISENABLER0,
|
||||
gic_data.saved_enable);
|
||||
mmio_write_32(gicr_base + GICR_ICFGR0, gic_data.saved_conf0);
|
||||
mmio_write_32(gicr_base + GICR_ICFGR1, gic_data.saved_conf1);
|
||||
mmio_write_32(gicr_base + GICR_IGRPMODR0,
|
||||
gic_data.saved_grpmod);
|
||||
}
|
||||
}
|
||||
|
||||
void gic_sgi_save_all(void)
|
||||
{
|
||||
unsigned int proc_num;
|
||||
uintptr_t gicr_base;
|
||||
|
||||
for (proc_num = 0; proc_num < PLATFORM_CORE_COUNT; proc_num++) {
|
||||
gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num];
|
||||
gic_data.saved_sgi[proc_num] =
|
||||
mmio_read_32(gicr_base + GICR_ISPENDR0) & SGI_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
void gic_sgi_restore_all(void)
|
||||
{
|
||||
unsigned int proc_num;
|
||||
uintptr_t gicr_base;
|
||||
|
||||
for (proc_num = 0; proc_num < PLATFORM_CORE_COUNT; proc_num++) {
|
||||
gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num];
|
||||
mmio_write_32(gicr_base + GICR_ICPENDR0, SGI_MASK);
|
||||
mmio_write_32(gicr_base + GICR_ISPENDR0,
|
||||
gic_data.saved_sgi[proc_num] & SGI_MASK);
|
||||
}
|
||||
}
|
||||
|
||||
void mt_gic_init(void)
|
||||
{
|
||||
gicv3_distif_init();
|
||||
gicv3_rdistif_init(plat_my_core_pos());
|
||||
gicv3_cpuif_enable(plat_my_core_pos());
|
||||
}
|
||||
|
||||
uint32_t mt_irq_get_pending(uint32_t irq)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
val = mmio_read_32(BASE_GICD_BASE + GICD_ISPENDR +
|
||||
irq / 32 * 4);
|
||||
val = (val >> (irq % 32)) & 1U;
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
void mt_irq_set_pending(uint32_t irq)
|
||||
{
|
||||
uint32_t bit = 1U << (irq % 32);
|
||||
|
||||
mmio_write_32(BASE_GICD_BASE + GICD_ISPENDR +
|
||||
irq / 32 * 4, bit);
|
||||
}
|
||||
|
||||
int mt_gic_one_init(void)
|
||||
{
|
||||
INFO("[%s] GIC initialization\n", __func__);
|
||||
|
||||
/* Initialize the GIC driver, CPU and distributor interfaces */
|
||||
mt_gic_driver_init();
|
||||
mt_gic_init();
|
||||
|
||||
return 0;
|
||||
}
|
||||
MTK_PLAT_SETUP_0_INIT(mt_gic_one_init);
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2022, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef MT_GIC_V3_H
|
||||
#define MT_GIC_V3_H
|
||||
|
||||
#include <drivers/arm/gicv3.h>
|
||||
#include <lib/mmio.h>
|
||||
|
||||
void mt_gic_driver_init(void);
|
||||
void mt_gic_init(void);
|
||||
void mt_gic_set_pending(uint32_t irq);
|
||||
void mt_gic_distif_save(void);
|
||||
void mt_gic_distif_restore(void);
|
||||
void mt_gic_rdistif_init(void);
|
||||
void mt_gic_rdistif_save(void);
|
||||
void mt_gic_rdistif_restore(void);
|
||||
void mt_gic_rdistif_restore_all(void);
|
||||
void gic_sgi_save_all(void);
|
||||
void gic_sgi_restore_all(void);
|
||||
uint32_t mt_irq_get_pending(uint32_t irq);
|
||||
void mt_irq_set_pending(uint32_t irq);
|
||||
int mt_gic_one_init(void);
|
||||
|
||||
#endif /* MT_GIC_V3_H */
|
||||
@@ -0,0 +1,14 @@
|
||||
#
|
||||
# Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
LOCAL_DIR := $(call GET_LOCAL_DIR)
|
||||
|
||||
MODULE := gic600
|
||||
LOCAL_SRCS-y := $(LOCAL_DIR)/mt_gic_v3.c
|
||||
|
||||
PLAT_INCLUDES += -I${LOCAL_DIR}
|
||||
|
||||
$(eval $(call MAKE_MODULE,$(MODULE),$(LOCAL_SRCS-y),$(MTK_BL)))
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <mtgpio.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
uintptr_t mt_gpio_find_reg_addr(uint32_t pin)
|
||||
{
|
||||
uintptr_t reg_addr = 0U;
|
||||
struct mt_pin_info gpio_info;
|
||||
|
||||
assert(pin < MAX_GPIO_PIN);
|
||||
|
||||
gpio_info = mt_pin_infos[pin];
|
||||
|
||||
switch (gpio_info.base & 0x0f) {
|
||||
case 0:
|
||||
reg_addr = IOCFG_RM_BASE;
|
||||
break;
|
||||
case 1:
|
||||
reg_addr = IOCFG_LT_BASE;
|
||||
break;
|
||||
case 2:
|
||||
reg_addr = IOCFG_LM_BASE;
|
||||
break;
|
||||
case 3:
|
||||
reg_addr = IOCFG_RT_BASE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return reg_addr;
|
||||
}
|
||||
+221
@@ -0,0 +1,221 @@
|
||||
/*
|
||||
* Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef MT_GPIO_H
|
||||
#define MT_GPIO_H
|
||||
|
||||
#include <mtgpio_common.h>
|
||||
|
||||
/* Enumeration for GPIO pin */
|
||||
typedef enum GPIO_PIN {
|
||||
GPIO_UNSUPPORTED = -1,
|
||||
GPIO0, GPIO1, GPIO2, GPIO3, GPIO4, GPIO5, GPIO6,
|
||||
GPIO7, GPIO8, GPIO9, GPIO10, GPIO11, GPIO12, GPIO13, GPIO14,
|
||||
GPIO15, GPIO16, GPIO17, GPIO18, GPIO19, GPIO20, GPIO21, GPIO22,
|
||||
GPIO23, GPIO24, GPIO25, GPIO26, GPIO27, GPIO28, GPIO29, GPIO30,
|
||||
GPIO31, GPIO32, GPIO33, GPIO34, GPIO35, GPIO36, GPIO37, GPIO38,
|
||||
GPIO39, GPIO40, GPIO41, GPIO42, GPIO43, GPIO44, GPIO45, GPIO46,
|
||||
GPIO47, GPIO48, GPIO49, GPIO50, GPIO51, GPIO52, GPIO53, GPIO54,
|
||||
GPIO55, GPIO56, GPIO57, GPIO58, GPIO59, GPIO60, GPIO61, GPIO62,
|
||||
GPIO63, GPIO64, GPIO65, GPIO66, GPIO67, GPIO68, GPIO69, GPIO70,
|
||||
GPIO71, GPIO72, GPIO73, GPIO74, GPIO75, GPIO76, GPIO77, GPIO78,
|
||||
GPIO79, GPIO80, GPIO81, GPIO82, GPIO83, GPIO84, GPIO85, GPIO86,
|
||||
GPIO87, GPIO88, GPIO89, GPIO90, GPIO91, GPIO92, GPIO93, GPIO94,
|
||||
GPIO95, GPIO96, GPIO97, GPIO98, GPIO99, GPIO100, GPIO101, GPIO102,
|
||||
GPIO103, GPIO104, GPIO105, GPIO106, GPIO107, GPIO108, GPIO109, GPIO110,
|
||||
GPIO111, GPIO112, GPIO113, GPIO114, GPIO115, GPIO116, GPIO117, GPIO118,
|
||||
GPIO119, GPIO120, GPIO121, GPIO122, GPIO123, GPIO124, GPIO125, GPIO126,
|
||||
GPIO127, GPIO128, GPIO129, GPIO130, GPIO131, GPIO132, GPIO133, GPIO134,
|
||||
GPIO135, GPIO136, GPIO137, GPIO138, GPIO139, GPIO140, GPIO141, GPIO142,
|
||||
GPIO143, GPIO144, GPIO145, GPIO146, GPIO147, GPIO148, GPIO149, GPIO150,
|
||||
GPIO151, GPIO152, GPIO153, GPIO154, GPIO155, GPIO156, GPIO157, GPIO158,
|
||||
GPIO159, GPIO160, GPIO161, GPIO162, GPIO163, GPIO164, GPIO165, GPIO166,
|
||||
GPIO167, GPIO168, GPIO169, GPIO170, GPIO171, GPIO172, GPIO173, GPIO174,
|
||||
GPIO175, GPIO176,
|
||||
MT_GPIO_BASE_MAX
|
||||
} GPIO_PIN;
|
||||
|
||||
static const struct mt_pin_info mt_pin_infos[] = {
|
||||
PIN(0, 0, 6, 0x30, 0xb0),
|
||||
PIN(1, 0, 7, 0x30, 0xb0),
|
||||
PIN(2, 0, 8, 0x30, 0xb0),
|
||||
PIN(3, 0, 9, 0x30, 0xb0),
|
||||
PIN(4, 0, 10, 0x30, 0xb0),
|
||||
PIN(5, 0, 11, 0x30, 0xb0),
|
||||
PIN(6, 0, 12, 0x30, 0xb0),
|
||||
PIN(7, 0, 13, 0x30, 0xb0),
|
||||
PIN(8, 0, 14, 0x30, 0xb0),
|
||||
PIN(9, 0, 15, 0x30, 0xb0),
|
||||
PIN(10, 0, 16, 0x30, 0xb0),
|
||||
PIN(11, 0, 17, 0x30, 0xb0),
|
||||
PIN(12, 0, 12, 0x31, 0xa0),
|
||||
PIN(13, 0, 13, 0x31, 0xa0),
|
||||
PIN(14, 0, 14, 0x31, 0xa0),
|
||||
PIN(15, 0, 15, 0x31, 0xa0),
|
||||
PIN(16, 0, 1, 0x22, 0x50),
|
||||
PIN(17, 0, 2, 0x22, 0x50),
|
||||
PIN(18, 0, 3, 0x23, 0x60),
|
||||
PIN(19, 0, 4, 0x23, 0x60),
|
||||
PIN(20, 0, 5, 0x23, 0x60),
|
||||
PIN(21, 0, 6, 0x23, 0x60),
|
||||
PIN(22, 0, 0, 0x23, 0x60),
|
||||
PIN(23, 0, 1, 0x23, 0x60),
|
||||
PIN(24, 0, 2, 0x23, 0x60),
|
||||
PIN(25, 0, 3, 0x30, 0xb0),
|
||||
PIN(26, 0, 2, 0x30, 0xb0),
|
||||
PIN(27, 0, 5, 0x30, 0xb0),
|
||||
PIN(28, 0, 4, 0x30, 0xb0),
|
||||
PIN(29, 0, 0, 0x30, 0xb0),
|
||||
PIN(30, 0, 1, 0x30, 0xb0),
|
||||
PIN(31, 0, 11, 0x30, 0xc0),
|
||||
PIN(32, 0, 10, 0x30, 0xc0),
|
||||
PIN(33, 0, 13, 0x30, 0xc0),
|
||||
PIN(34, 0, 12, 0x30, 0xc0),
|
||||
PIN(35, 0, 15, 0x30, 0xc0),
|
||||
PIN(36, 0, 14, 0x30, 0xc0),
|
||||
PIN(37, 0, 21, 0x30, 0xb0),
|
||||
PIN(38, 0, 18, 0x30, 0xb0),
|
||||
PIN(39, 0, 19, 0x30, 0xb0),
|
||||
PIN(40, 0, 20, 0x30, 0xb0),
|
||||
PIN(41, 0, 22, 0x30, 0xb0),
|
||||
PIN(42, 1, 12, 0x31, 0xc0),
|
||||
PIN(43, 1, 13, 0x31, 0xc0),
|
||||
PIN(44, 1, 14, 0x31, 0xc0),
|
||||
PIN(45, 1, 15, 0x31, 0xc0),
|
||||
PIN(46, 0, 0, 0x22, 0x50),
|
||||
PIN(47, 0, 25, 0x30, 0xb0),
|
||||
PIN(48, 0, 24, 0x30, 0xb0),
|
||||
PIN(49, 0, 23, 0x30, 0xb0),
|
||||
PIN(50, 0, 5, 0x22, 0x50),
|
||||
PIN(51, 0, 4, 0x22, 0x50),
|
||||
PIN(52, 0, 3, 0x22, 0x50),
|
||||
PIN(53, 0, 6, 0x22, 0x50),
|
||||
PIN(54, 0, 7, 0x22, 0x50),
|
||||
PIN(55, 0, 26, 0x30, 0xb0),
|
||||
PIN(56, 0, 29, 0x30, 0xb0),
|
||||
PIN(57, 0, 6, 0x31, 0xb0),
|
||||
PIN(58, 0, 9, 0x31, 0xb0),
|
||||
PIN(59, 0, 27, 0x30, 0xb0),
|
||||
PIN(60, 0, 30, 0x30, 0xb0),
|
||||
PIN(61, 0, 28, 0x30, 0xb0),
|
||||
PIN(62, 0, 31, 0x30, 0xb0),
|
||||
PIN(63, 0, 7, 0x31, 0xb0),
|
||||
PIN(64, 0, 10, 0x31, 0xb0),
|
||||
PIN(65, 0, 7, 0x23, 0x60),
|
||||
PIN(66, 0, 9, 0x23, 0x60),
|
||||
PIN(67, 0, 8, 0x23, 0x60),
|
||||
PIN(68, 0, 10, 0x23, 0x60),
|
||||
PIN(69, 0, 1, 0x30, 0xc0),
|
||||
PIN(70, 0, 0, 0x30, 0xc0),
|
||||
PIN(71, 0, 5, 0x30, 0xc0),
|
||||
PIN(72, 0, 4, 0x30, 0xc0),
|
||||
PIN(73, 0, 2, 0x30, 0xc0),
|
||||
PIN(74, 0, 3, 0x30, 0xc0),
|
||||
PIN(75, 0, 7, 0x30, 0xc0),
|
||||
PIN(76, 0, 6, 0x30, 0xc0),
|
||||
PIN(77, 0, 9, 0x30, 0xc0),
|
||||
PIN(78, 0, 8, 0x30, 0xc0),
|
||||
PIN(79, 0, 12, 0x23, 0x60),
|
||||
PIN(80, 0, 11, 0x23, 0x60),
|
||||
PIN(81, 0, 14, 0x23, 0x60),
|
||||
PIN(82, 0, 13, 0x23, 0x60),
|
||||
PIN(83, 0, 16, 0x31, 0xb0),
|
||||
PIN(84, 0, 15, 0x31, 0xb0),
|
||||
PIN(85, 0, 17, 0x31, 0xb0),
|
||||
PIN(86, 0, 19, 0x31, 0xb0),
|
||||
PIN(87, 0, 18, 0x31, 0xb0),
|
||||
PIN(88, 0, 20, 0x31, 0xb0),
|
||||
PIN(89, 0, 22, 0x31, 0xb0),
|
||||
PIN(90, 0, 21, 0x31, 0xb0),
|
||||
PIN(91, 0, 23, 0x31, 0xb0),
|
||||
PIN(92, 0, 3, 0x31, 0xb0),
|
||||
PIN(93, 0, 2, 0x31, 0xb0),
|
||||
PIN(94, 0, 5, 0x31, 0xb0),
|
||||
PIN(95, 0, 4, 0x31, 0xb0),
|
||||
PIN(96, 0, 31, 0x31, 0xa0),
|
||||
PIN(97, 0, 0, 0x31, 0xb0),
|
||||
PIN(98, 0, 8, 0x31, 0xb0),
|
||||
PIN(99, 0, 30, 0x31, 0xa0),
|
||||
PIN(100, 0, 1, 0x31, 0xb0),
|
||||
PIN(101, 0, 0, 0x31, 0xa0),
|
||||
PIN(102, 0, 5, 0x31, 0xa0),
|
||||
PIN(103, 0, 3, 0x31, 0xa0),
|
||||
PIN(104, 0, 4, 0x31, 0xa0),
|
||||
PIN(105, 0, 1, 0x31, 0xa0),
|
||||
PIN(106, 0, 2, 0x31, 0xa0),
|
||||
PIN(107, 0, 21, 0x31, 0xa0),
|
||||
PIN(108, 0, 16, 0x31, 0xa0),
|
||||
PIN(109, 0, 22, 0x31, 0xa0),
|
||||
PIN(110, 0, 17, 0x31, 0xa0),
|
||||
PIN(111, 0, 18, 0x31, 0xa0),
|
||||
PIN(112, 0, 19, 0x31, 0xa0),
|
||||
PIN(113, 0, 20, 0x31, 0xa0),
|
||||
PIN(114, 0, 28, 0x31, 0xa0),
|
||||
PIN(115, 0, 23, 0x31, 0xa0),
|
||||
PIN(116, 0, 29, 0x31, 0xa0),
|
||||
PIN(117, 0, 24, 0x31, 0xa0),
|
||||
PIN(118, 0, 25, 0x31, 0xa0),
|
||||
PIN(119, 0, 26, 0x31, 0xa0),
|
||||
PIN(120, 0, 27, 0x31, 0xa0),
|
||||
PIN(121, 0, 8, 0x22, 0x50),
|
||||
PIN(122, 0, 11, 0x22, 0x50),
|
||||
PIN(123, 0, 10, 0x22, 0x50),
|
||||
PIN(124, 0, 9, 0x22, 0x50),
|
||||
PIN(125, 0, 6, 0x31, 0xa0),
|
||||
PIN(126, 0, 7, 0x31, 0xa0),
|
||||
PIN(127, 0, 8, 0x31, 0xa0),
|
||||
PIN(128, 0, 9, 0x31, 0xa0),
|
||||
PIN(129, 0, 10, 0x31, 0xa0),
|
||||
PIN(130, 0, 11, 0x31, 0xa0),
|
||||
PIN(131, 1, 1, 0x30, 0xd0),
|
||||
PIN(132, 1, 2, 0x30, 0xd0),
|
||||
PIN(133, 1, 9, 0x30, 0xd0),
|
||||
PIN(134, 1, 10, 0x30, 0xd0),
|
||||
PIN(135, 1, 11, 0x30, 0xd0),
|
||||
PIN(136, 1, 12, 0x30, 0xd0),
|
||||
PIN(137, 1, 13, 0x30, 0xd0),
|
||||
PIN(138, 1, 14, 0x30, 0xd0),
|
||||
PIN(139, 1, 15, 0x30, 0xd0),
|
||||
PIN(140, 1, 16, 0x30, 0xd0),
|
||||
PIN(141, 1, 3, 0x30, 0xd0),
|
||||
PIN(142, 1, 4, 0x30, 0xd0),
|
||||
PIN(143, 1, 5, 0x30, 0xd0),
|
||||
PIN(144, 1, 6, 0x30, 0xd0),
|
||||
PIN(145, 1, 7, 0x30, 0xd0),
|
||||
PIN(146, 1, 8, 0x30, 0xd0),
|
||||
PIN(147, 1, 18, 0x30, 0xd0),
|
||||
PIN(148, 1, 19, 0x30, 0xd0),
|
||||
PIN(149, 1, 17, 0x30, 0xd0),
|
||||
PIN(150, 1, 0, 0x30, 0xd0),
|
||||
PIN(151, 1, 9, 0x31, 0xc0),
|
||||
PIN(152, 1, 8, 0x31, 0xc0),
|
||||
PIN(153, 1, 7, 0x31, 0xc0),
|
||||
PIN(154, 1, 6, 0x31, 0xc0),
|
||||
PIN(155, 1, 11, 0x31, 0xc0),
|
||||
PIN(156, 1, 1, 0x31, 0xc0),
|
||||
PIN(157, 1, 0, 0x31, 0xc0),
|
||||
PIN(158, 1, 5, 0x31, 0xc0),
|
||||
PIN(159, 1, 4, 0x31, 0xc0),
|
||||
PIN(160, 1, 3, 0x31, 0xc0),
|
||||
PIN(161, 1, 2, 0x31, 0xc0),
|
||||
PIN(162, 1, 10, 0x31, 0xc0),
|
||||
PIN(163, 1, 1, 0x23, 0x70),
|
||||
PIN(164, 1, 0, 0x23, 0x70),
|
||||
PIN(165, 1, 2, 0x23, 0x70),
|
||||
PIN(166, 1, 3, 0x23, 0x70),
|
||||
PIN(167, 1, 4, 0x23, 0x70),
|
||||
PIN(168, 1, 5, 0x23, 0x70),
|
||||
PIN(169, 1, 1, 0x22, 0x60),
|
||||
PIN(170, 1, 0, 0x22, 0x60),
|
||||
PIN(171, 1, 2, 0x22, 0x60),
|
||||
PIN(172, 1, 3, 0x22, 0x60),
|
||||
PIN(173, 1, 4, 0x22, 0x60),
|
||||
PIN(174, 1, 5, 0x22, 0x60),
|
||||
PIN(175, 0, 11, 0x31, 0xb0),
|
||||
PIN(176, 0, 12, 0x31, 0xb0),
|
||||
};
|
||||
|
||||
#endif /* MT_GPIO_H */
|
||||
+302
@@ -0,0 +1,302 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2022, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <common/debug.h>
|
||||
#include <drivers/delay_timer.h>
|
||||
#include <drivers/gpio.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <lib/mtk_init/mtk_init.h>
|
||||
#include <mtgpio.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
/******************************************************************************
|
||||
*Macro Definition
|
||||
******************************************************************************/
|
||||
#define GPIO_MODE_BITS 4
|
||||
#define MAX_GPIO_MODE_PER_REG 8
|
||||
#define MAX_GPIO_REG_BITS 32
|
||||
#define DIR_BASE (GPIO_BASE + 0x000)
|
||||
#define DOUT_BASE (GPIO_BASE + 0x100)
|
||||
#define DIN_BASE (GPIO_BASE + 0x200)
|
||||
#define MODE_BASE (GPIO_BASE + 0x300)
|
||||
#define SET 0x4
|
||||
#define CLR 0x8
|
||||
|
||||
static void mt_set_gpio_dir_chip(uint32_t pin, int dir)
|
||||
{
|
||||
uint32_t pos, bit;
|
||||
|
||||
assert(pin < MAX_GPIO_PIN);
|
||||
assert(dir < MT_GPIO_DIR_MAX);
|
||||
|
||||
pos = pin / MAX_GPIO_REG_BITS;
|
||||
bit = pin % MAX_GPIO_REG_BITS;
|
||||
|
||||
if (dir == MT_GPIO_DIR_IN) {
|
||||
mmio_write_32(DIR_BASE + 0x10U * pos + CLR, 1U << bit);
|
||||
} else {
|
||||
mmio_write_32(DIR_BASE + 0x10U * pos + SET, 1U << bit);
|
||||
}
|
||||
}
|
||||
|
||||
static int mt_get_gpio_dir_chip(uint32_t pin)
|
||||
{
|
||||
uint32_t pos, bit;
|
||||
uint32_t reg;
|
||||
|
||||
assert(pin < MAX_GPIO_PIN);
|
||||
|
||||
pos = pin / MAX_GPIO_REG_BITS;
|
||||
bit = pin % MAX_GPIO_REG_BITS;
|
||||
|
||||
reg = mmio_read_32(DIR_BASE + 0x10U * pos);
|
||||
return (((reg & (1U << bit)) != 0U) ? MT_GPIO_DIR_OUT : MT_GPIO_DIR_IN);
|
||||
}
|
||||
|
||||
static void mt_set_gpio_out_chip(uint32_t pin, int output)
|
||||
{
|
||||
uint32_t pos, bit;
|
||||
|
||||
assert(pin < MAX_GPIO_PIN);
|
||||
assert(output < MT_GPIO_OUT_MAX);
|
||||
|
||||
pos = pin / MAX_GPIO_REG_BITS;
|
||||
bit = pin % MAX_GPIO_REG_BITS;
|
||||
|
||||
if (output == MT_GPIO_OUT_ZERO) {
|
||||
mmio_write_32(DOUT_BASE + 0x10U * pos + CLR, 1U << bit);
|
||||
} else {
|
||||
mmio_write_32(DOUT_BASE + 0x10U * pos + SET, 1U << bit);
|
||||
}
|
||||
}
|
||||
|
||||
static int mt_get_gpio_in_chip(uint32_t pin)
|
||||
{
|
||||
uint32_t pos, bit;
|
||||
uint32_t reg;
|
||||
|
||||
assert(pin < MAX_GPIO_PIN);
|
||||
|
||||
pos = pin / MAX_GPIO_REG_BITS;
|
||||
bit = pin % MAX_GPIO_REG_BITS;
|
||||
|
||||
reg = mmio_read_32(DIN_BASE + 0x10U * pos);
|
||||
return (((reg & (1U << bit)) != 0U) ? 1 : 0);
|
||||
}
|
||||
|
||||
static void mt_gpio_set_spec_pull_pupd(uint32_t pin, int enable,
|
||||
int select)
|
||||
{
|
||||
uintptr_t reg1;
|
||||
uintptr_t reg2;
|
||||
struct mt_pin_info gpio_info;
|
||||
|
||||
gpio_info = mt_pin_infos[pin];
|
||||
uint32_t bit = gpio_info.bit;
|
||||
|
||||
reg1 = mt_gpio_find_reg_addr(pin) + gpio_info.offset;
|
||||
reg2 = reg1 + (gpio_info.base & 0xf0);
|
||||
if (enable == MT_GPIO_PULL_ENABLE) {
|
||||
mmio_write_32(reg2 + SET, (1U << bit));
|
||||
if (select == MT_GPIO_PULL_DOWN) {
|
||||
mmio_write_32(reg1 + SET, (1U << bit));
|
||||
} else {
|
||||
mmio_write_32(reg1 + CLR, (1U << bit));
|
||||
}
|
||||
} else {
|
||||
mmio_write_32(reg2 + CLR, (1U << bit));
|
||||
mmio_write_32((reg2 + 0x010U) + CLR, (1U << bit));
|
||||
}
|
||||
}
|
||||
|
||||
static void mt_gpio_set_pull_pu_pd(uint32_t pin, int enable,
|
||||
int select)
|
||||
{
|
||||
uintptr_t reg1;
|
||||
uintptr_t reg2;
|
||||
struct mt_pin_info gpio_info;
|
||||
|
||||
gpio_info = mt_pin_infos[pin];
|
||||
uint32_t bit = gpio_info.bit;
|
||||
|
||||
reg1 = mt_gpio_find_reg_addr(pin) + gpio_info.offset;
|
||||
reg2 = reg1 - (gpio_info.base & 0xf0);
|
||||
|
||||
if (enable == MT_GPIO_PULL_ENABLE) {
|
||||
if (select == MT_GPIO_PULL_DOWN) {
|
||||
mmio_write_32(reg1 + CLR, (1U << bit));
|
||||
mmio_write_32(reg2 + SET, (1U << bit));
|
||||
} else {
|
||||
mmio_write_32(reg2 + CLR, (1U << bit));
|
||||
mmio_write_32(reg1 + SET, (1U << bit));
|
||||
}
|
||||
} else {
|
||||
mmio_write_32(reg1 + CLR, (1U << bit));
|
||||
mmio_write_32(reg2 + CLR, (1U << bit));
|
||||
}
|
||||
}
|
||||
|
||||
static void mt_gpio_set_pull_chip(uint32_t pin, int enable,
|
||||
int select)
|
||||
{
|
||||
struct mt_pin_info gpio_info;
|
||||
|
||||
gpio_info = mt_pin_infos[pin];
|
||||
if (gpio_info.flag) {
|
||||
mt_gpio_set_spec_pull_pupd(pin, enable, select);
|
||||
} else {
|
||||
mt_gpio_set_pull_pu_pd(pin, enable, select);
|
||||
}
|
||||
}
|
||||
|
||||
static int mt_gpio_get_spec_pull_pupd(uint32_t pin)
|
||||
{
|
||||
uintptr_t reg1;
|
||||
uintptr_t reg2;
|
||||
uint32_t r0;
|
||||
uint32_t r1;
|
||||
|
||||
struct mt_pin_info gpio_info;
|
||||
|
||||
gpio_info = mt_pin_infos[pin];
|
||||
uint32_t bit = gpio_info.bit;
|
||||
|
||||
reg1 = mt_gpio_find_reg_addr(pin) + gpio_info.offset;
|
||||
reg2 = reg1 + (gpio_info.base & 0xf0);
|
||||
|
||||
r0 = (mmio_read_32(reg2) >> bit) & 1U;
|
||||
r1 = (mmio_read_32(reg2 + 0x010) >> bit) & 1U;
|
||||
if (r0 == 0U && r1 == 0U) {
|
||||
return MT_GPIO_PULL_NONE;
|
||||
} else {
|
||||
if (mmio_read_32(reg1) & (1U << bit)) {
|
||||
return MT_GPIO_PULL_DOWN;
|
||||
} else {
|
||||
return MT_GPIO_PULL_UP;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int mt_gpio_get_pull_pu_pd(uint32_t pin)
|
||||
{
|
||||
uintptr_t reg1;
|
||||
uintptr_t reg2;
|
||||
uint32_t pu;
|
||||
uint32_t pd;
|
||||
|
||||
struct mt_pin_info gpio_info;
|
||||
|
||||
gpio_info = mt_pin_infos[pin];
|
||||
uint32_t bit = gpio_info.bit;
|
||||
|
||||
reg1 = mt_gpio_find_reg_addr(pin) + gpio_info.offset;
|
||||
reg2 = reg1 - (gpio_info.base & 0xf0);
|
||||
pu = (mmio_read_32(reg1) >> bit) & 1U;
|
||||
pd = (mmio_read_32(reg2) >> bit) & 1U;
|
||||
if (pu == 1U) {
|
||||
return MT_GPIO_PULL_UP;
|
||||
} else if (pd == 1U) {
|
||||
return MT_GPIO_PULL_DOWN;
|
||||
} else {
|
||||
return MT_GPIO_PULL_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
static int mt_gpio_get_pull_chip(uint32_t pin)
|
||||
{
|
||||
struct mt_pin_info gpio_info;
|
||||
|
||||
gpio_info = mt_pin_infos[pin];
|
||||
if (gpio_info.flag) {
|
||||
return mt_gpio_get_spec_pull_pupd(pin);
|
||||
} else {
|
||||
return mt_gpio_get_pull_pu_pd(pin);
|
||||
}
|
||||
}
|
||||
|
||||
static void mt_set_gpio_pull_select_chip(uint32_t pin, int sel)
|
||||
{
|
||||
assert(pin < MAX_GPIO_PIN);
|
||||
|
||||
if (sel == MT_GPIO_PULL_NONE) {
|
||||
mt_gpio_set_pull_chip(pin, MT_GPIO_PULL_DISABLE, MT_GPIO_PULL_DOWN);
|
||||
} else if (sel == MT_GPIO_PULL_UP) {
|
||||
mt_gpio_set_pull_chip(pin, MT_GPIO_PULL_ENABLE, MT_GPIO_PULL_UP);
|
||||
} else if (sel == MT_GPIO_PULL_DOWN) {
|
||||
mt_gpio_set_pull_chip(pin, MT_GPIO_PULL_ENABLE, MT_GPIO_PULL_DOWN);
|
||||
}
|
||||
}
|
||||
|
||||
/* get pull-up or pull-down, regardless of resistor value */
|
||||
static int mt_get_gpio_pull_select_chip(uint32_t pin)
|
||||
{
|
||||
assert(pin < MAX_GPIO_PIN);
|
||||
|
||||
return mt_gpio_get_pull_chip(pin);
|
||||
}
|
||||
|
||||
static void mt_set_gpio_dir(int gpio, int direction)
|
||||
{
|
||||
mt_set_gpio_dir_chip((uint32_t)gpio, direction);
|
||||
}
|
||||
|
||||
static int mt_get_gpio_dir(int gpio)
|
||||
{
|
||||
uint32_t pin;
|
||||
|
||||
pin = (uint32_t)gpio;
|
||||
return mt_get_gpio_dir_chip(pin);
|
||||
}
|
||||
|
||||
static void mt_set_gpio_pull(int gpio, int pull)
|
||||
{
|
||||
uint32_t pin;
|
||||
|
||||
pin = (uint32_t)gpio;
|
||||
mt_set_gpio_pull_select_chip(pin, pull);
|
||||
}
|
||||
|
||||
static int mt_get_gpio_pull(int gpio)
|
||||
{
|
||||
uint32_t pin;
|
||||
|
||||
pin = (uint32_t)gpio;
|
||||
return mt_get_gpio_pull_select_chip(pin);
|
||||
}
|
||||
|
||||
static void mt_set_gpio_out(int gpio, int value)
|
||||
{
|
||||
uint32_t pin;
|
||||
|
||||
pin = (uint32_t)gpio;
|
||||
mt_set_gpio_out_chip(pin, value);
|
||||
}
|
||||
|
||||
static int mt_get_gpio_in(int gpio)
|
||||
{
|
||||
uint32_t pin;
|
||||
|
||||
pin = (uint32_t)gpio;
|
||||
return mt_get_gpio_in_chip(pin);
|
||||
}
|
||||
|
||||
const gpio_ops_t mtgpio_ops = {
|
||||
.get_direction = mt_get_gpio_dir,
|
||||
.set_direction = mt_set_gpio_dir,
|
||||
.get_value = mt_get_gpio_in,
|
||||
.set_value = mt_set_gpio_out,
|
||||
.set_pull = mt_set_gpio_pull,
|
||||
.get_pull = mt_get_gpio_pull,
|
||||
};
|
||||
|
||||
int mt_gpio_init(void)
|
||||
{
|
||||
gpio_init(&mtgpio_ops);
|
||||
|
||||
return 0;
|
||||
}
|
||||
MTK_PLAT_SETUP_0_INIT(mt_gpio_init);
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2022, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef MT_GPIO_COMMON_H
|
||||
#define MT_GPIO_COMMON_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <plat/common/common_def.h>
|
||||
|
||||
/* Error Code No. */
|
||||
#define RSUCCESS 0
|
||||
#define ERACCESS 1
|
||||
#define ERINVAL 2
|
||||
#define ERWRAPPER 3
|
||||
#define MAX_GPIO_PIN MT_GPIO_BASE_MAX
|
||||
|
||||
/* GPIO MODE CONTROL VALUE*/
|
||||
typedef enum {
|
||||
GPIO_MODE_UNSUPPORTED = -1,
|
||||
GPIO_MODE_GPIO = 0,
|
||||
GPIO_MODE_00 = 0,
|
||||
GPIO_MODE_01,
|
||||
GPIO_MODE_02,
|
||||
GPIO_MODE_03,
|
||||
GPIO_MODE_04,
|
||||
GPIO_MODE_05,
|
||||
GPIO_MODE_06,
|
||||
GPIO_MODE_07,
|
||||
|
||||
GPIO_MODE_MAX,
|
||||
GPIO_MODE_DEFAULT = GPIO_MODE_00,
|
||||
} GPIO_MODE;
|
||||
|
||||
/* GPIO DIRECTION */
|
||||
typedef enum {
|
||||
MT_GPIO_DIR_UNSUPPORTED = -1,
|
||||
MT_GPIO_DIR_OUT = 0,
|
||||
MT_GPIO_DIR_IN = 1,
|
||||
MT_GPIO_DIR_MAX,
|
||||
MT_GPIO_DIR_DEFAULT = MT_GPIO_DIR_IN,
|
||||
} GPIO_DIR;
|
||||
|
||||
/* GPIO PULL ENABLE*/
|
||||
typedef enum {
|
||||
MT_GPIO_PULL_EN_UNSUPPORTED = -1,
|
||||
MT_GPIO_PULL_DISABLE = 0,
|
||||
MT_GPIO_PULL_ENABLE = 1,
|
||||
MT_GPIO_PULL_ENABLE_R0 = 2,
|
||||
MT_GPIO_PULL_ENABLE_R1 = 3,
|
||||
MT_GPIO_PULL_ENABLE_R0R1 = 4,
|
||||
|
||||
MT_GPIO_PULL_EN_MAX,
|
||||
MT_GPIO_PULL_EN_DEFAULT = MT_GPIO_PULL_ENABLE,
|
||||
} GPIO_PULL_EN;
|
||||
|
||||
/* GPIO PULL-UP/PULL-DOWN*/
|
||||
typedef enum {
|
||||
MT_GPIO_PULL_UNSUPPORTED = -1,
|
||||
MT_GPIO_PULL_NONE = 0,
|
||||
MT_GPIO_PULL_UP = 1,
|
||||
MT_GPIO_PULL_DOWN = 2,
|
||||
MT_GPIO_PULL_MAX,
|
||||
MT_GPIO_PULL_DEFAULT = MT_GPIO_PULL_DOWN
|
||||
} GPIO_PULL;
|
||||
|
||||
/* GPIO OUTPUT */
|
||||
typedef enum {
|
||||
MT_GPIO_OUT_UNSUPPORTED = -1,
|
||||
MT_GPIO_OUT_ZERO = 0,
|
||||
MT_GPIO_OUT_ONE = 1,
|
||||
|
||||
MT_GPIO_OUT_MAX,
|
||||
MT_GPIO_OUT_DEFAULT = MT_GPIO_OUT_ZERO,
|
||||
MT_GPIO_DATA_OUT_DEFAULT = MT_GPIO_OUT_ZERO, /*compatible with DCT*/
|
||||
} GPIO_OUT;
|
||||
|
||||
/* GPIO INPUT */
|
||||
typedef enum {
|
||||
MT_GPIO_IN_UNSUPPORTED = -1,
|
||||
MT_GPIO_IN_ZERO = 0,
|
||||
MT_GPIO_IN_ONE = 1,
|
||||
|
||||
MT_GPIO_IN_MAX,
|
||||
} GPIO_IN;
|
||||
|
||||
#define PIN(_id, _flag, _bit, _base, _offset) { \
|
||||
.id = _id, \
|
||||
.flag = _flag, \
|
||||
.bit = _bit, \
|
||||
.base = _base, \
|
||||
.offset = _offset, \
|
||||
}
|
||||
|
||||
struct mt_pin_info {
|
||||
uint8_t id;
|
||||
uint8_t flag;
|
||||
uint8_t bit;
|
||||
uint16_t base;
|
||||
uint16_t offset;
|
||||
};
|
||||
|
||||
int mt_gpio_init(void);
|
||||
uintptr_t mt_gpio_find_reg_addr(uint32_t pin);
|
||||
#endif /* MT_GPIO_COMMON_H */
|
||||
@@ -0,0 +1,18 @@
|
||||
#
|
||||
# Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
LOCAL_DIR := $(call GET_LOCAL_DIR)
|
||||
|
||||
MODULE := gpio
|
||||
|
||||
LOCAL_SRCS-y := drivers/gpio/gpio.c
|
||||
LOCAL_SRCS-y += ${LOCAL_DIR}/mtgpio_common.c
|
||||
LOCAL_SRCS-y += ${LOCAL_DIR}/${MTK_SOC}/mtgpio.c
|
||||
|
||||
PLAT_INCLUDES += -I${LOCAL_DIR}
|
||||
PLAT_INCLUDES += -I${LOCAL_DIR}/${MTK_SOC}
|
||||
|
||||
$(eval $(call MAKE_MODULE,$(MODULE),$(LOCAL_SRCS-y),$(MTK_BL)))
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <mtk_iommu_plat.h>
|
||||
#include <mtk_mmap_pool.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
/* mm iommu */
|
||||
#define SMI_L0_ID (0)
|
||||
#define SMI_L1_ID (1)
|
||||
#define SMI_L2_ID (2)
|
||||
#define SMI_L3_ID (3)
|
||||
#define SMI_L4_ID (4)
|
||||
#define SMI_L5_ID (5)
|
||||
#define SMI_L6_ID (6)
|
||||
#define SMI_L7_ID (7)
|
||||
#define SMI_L9_ID (8)
|
||||
#define SMI_L10_ID (9)
|
||||
#define SMI_L11A_ID (10)
|
||||
#define SMI_L11B_ID (11)
|
||||
#define SMI_L11C_ID (12)
|
||||
#define SMI_L12_ID (13)
|
||||
#define SMI_L13_ID (14)
|
||||
#define SMI_L14_ID (15)
|
||||
#define SMI_L15_ID (16)
|
||||
#define SMI_L16A_ID (17)
|
||||
#define SMI_L16B_ID (18)
|
||||
#define SMI_L17A_ID (19)
|
||||
#define SMI_L17B_ID (20)
|
||||
#define SMI_L19_ID (21)
|
||||
#define SMI_L21_ID (22)
|
||||
#define SMI_L23_ID (23)
|
||||
#define SMI_L27_ID (24)
|
||||
#define SMI_L28_ID (25)
|
||||
|
||||
/* infra iommu */
|
||||
#define PERI_MST_PROT (0x710)
|
||||
#define PERICFG_AO_IOMMU_1 (0x714)
|
||||
#define MMU_DEV_PCIE_0 (0)
|
||||
#define IFR_CFG_GROUP_NUM (1)
|
||||
|
||||
static struct mtk_smi_larb_config mt8188_larb_cfg[SMI_LARB_NUM] = {
|
||||
[SMI_L0_ID] = LARB_CFG_ENTRY(SMI_LARB_0_BASE, 7, 0),
|
||||
[SMI_L1_ID] = LARB_CFG_ENTRY(SMI_LARB_1_BASE, 7, 0),
|
||||
[SMI_L2_ID] = LARB_CFG_ENTRY(SMI_LARB_2_BASE, 5, 0),
|
||||
[SMI_L3_ID] = LARB_CFG_ENTRY(SMI_LARB_3_BASE, 7, 0),
|
||||
[SMI_L4_ID] = LARB_CFG_ENTRY(SMI_LARB_4_BASE, 7, 0),
|
||||
[SMI_L5_ID] = LARB_CFG_ENTRY(SMI_LARB_5_BASE, 8, 0),
|
||||
[SMI_L6_ID] = LARB_CFG_ENTRY(SMI_LARB_6_BASE, 4, 0),
|
||||
[SMI_L7_ID] = LARB_CFG_ENTRY(SMI_LARB_7_BASE, 3, 0),
|
||||
[SMI_L9_ID] = LARB_CFG_ENTRY(SMI_LARB_9_BASE, 25, 0),
|
||||
[SMI_L10_ID] = LARB_CFG_ENTRY(SMI_LARB_10_BASE, 20, 0),
|
||||
[SMI_L11A_ID] = LARB_CFG_ENTRY(SMI_LARB_11A_BASE, 30, 0),
|
||||
[SMI_L11B_ID] = LARB_CFG_ENTRY(SMI_LARB_11B_BASE, 30, 0),
|
||||
[SMI_L11C_ID] = LARB_CFG_ENTRY(SMI_LARB_11C_BASE, 30, 0),
|
||||
[SMI_L12_ID] = LARB_CFG_ENTRY(SMI_LARB_12_BASE, 16, 0),
|
||||
[SMI_L13_ID] = LARB_CFG_ENTRY(SMI_LARB_13_BASE, 24, 0),
|
||||
[SMI_L14_ID] = LARB_CFG_ENTRY(SMI_LARB_14_BASE, 23, 0),
|
||||
[SMI_L15_ID] = LARB_CFG_ENTRY(SMI_LARB_15_BASE, 19, 0),
|
||||
[SMI_L16A_ID] = LARB_CFG_ENTRY(SMI_LARB_16A_BASE, 17, 0),
|
||||
[SMI_L16B_ID] = LARB_CFG_ENTRY(SMI_LARB_16B_BASE, 17, 0),
|
||||
[SMI_L17A_ID] = LARB_CFG_ENTRY(SMI_LARB_17A_BASE, 7, 0),
|
||||
[SMI_L17B_ID] = LARB_CFG_ENTRY(SMI_LARB_17B_BASE, 7, 0),
|
||||
/* venc nbm ports (5/6/11/15/16/17) to sram */
|
||||
[SMI_L19_ID] = LARB_CFG_ENTRY_WITH_PATH(SMI_LARB_19_BASE, 27, 0, 0x38860),
|
||||
[SMI_L21_ID] = LARB_CFG_ENTRY(SMI_LARB_21_BASE, 11, 0),
|
||||
[SMI_L23_ID] = LARB_CFG_ENTRY(SMI_LARB_23_BASE, 9, 0),
|
||||
[SMI_L27_ID] = LARB_CFG_ENTRY(SMI_LARB_27_BASE, 4, 0),
|
||||
[SMI_L28_ID] = LARB_CFG_ENTRY(SMI_LARB_28_BASE, 0, 0),
|
||||
};
|
||||
|
||||
static bool is_protected;
|
||||
|
||||
static uint32_t mt8188_ifr_mst_cfg_base[IFR_CFG_GROUP_NUM] = {
|
||||
PERICFG_AO_BASE,
|
||||
};
|
||||
static uint32_t mt8188_ifr_mst_cfg_offs[IFR_CFG_GROUP_NUM] = {
|
||||
PERICFG_AO_IOMMU_1,
|
||||
};
|
||||
static struct mtk_ifr_mst_config mt8188_ifr_mst_cfg[MMU_DEV_NUM] = {
|
||||
[MMU_DEV_PCIE_0] = IFR_MST_CFG_ENTRY(0, 18),
|
||||
};
|
||||
|
||||
struct mtk_smi_larb_config *g_larb_cfg = &mt8188_larb_cfg[0];
|
||||
struct mtk_ifr_mst_config *g_ifr_mst_cfg = &mt8188_ifr_mst_cfg[0];
|
||||
uint32_t *g_ifr_mst_cfg_base = &mt8188_ifr_mst_cfg_base[0];
|
||||
uint32_t *g_ifr_mst_cfg_offs = &mt8188_ifr_mst_cfg_offs[0];
|
||||
|
||||
/* Protect infra iommu enable setting registers as secure access. */
|
||||
void mtk_infra_iommu_enable_protect(void)
|
||||
{
|
||||
if (!is_protected) {
|
||||
mmio_write_32(PERICFG_AO_BASE + PERI_MST_PROT, 0xffffffff);
|
||||
is_protected = true;
|
||||
}
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef IOMMU_PLAT_H
|
||||
#define IOMMU_PLAT_H
|
||||
|
||||
#include <mtk_iommu_priv.h>
|
||||
|
||||
/* mm iommu */
|
||||
#define SMI_LARB_NUM (26)
|
||||
extern struct mtk_smi_larb_config *g_larb_cfg;
|
||||
|
||||
/* infra iommu */
|
||||
#define MMU_DEV_NUM (1)
|
||||
extern struct mtk_ifr_mst_config *g_ifr_mst_cfg;
|
||||
extern uint32_t *g_ifr_mst_cfg_base;
|
||||
extern uint32_t *g_ifr_mst_cfg_offs;
|
||||
|
||||
extern void mtk_infra_iommu_enable_protect(void);
|
||||
|
||||
#endif /* IOMMU_PLAT_H */
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef IOMMU_PRIV_H
|
||||
#define IOMMU_PRIV_H
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <mtk_sip_svc.h>
|
||||
|
||||
#define LARB_CFG_ENTRY(bs, p_nr, dom) \
|
||||
{ .base = (bs), .port_nr = (p_nr), \
|
||||
.dom_id = (dom), .to_sram = 0, }
|
||||
|
||||
#define LARB_CFG_ENTRY_WITH_PATH(bs, p_nr, dom, sram) \
|
||||
{ .base = (bs), .port_nr = (p_nr), \
|
||||
.dom_id = (dom), .to_sram = (sram), }
|
||||
|
||||
#define IFR_MST_CFG_ENTRY(idx, bit) \
|
||||
{ .cfg_addr_idx = (idx), .r_mmu_en_bit = (bit), }
|
||||
|
||||
enum IOMMU_ATF_CMD {
|
||||
IOMMU_ATF_CMD_CONFIG_SMI_LARB, /* For mm master to enable iommu */
|
||||
IOMMU_ATF_CMD_CONFIG_INFRA_IOMMU, /* For infra master to enable iommu */
|
||||
IOMMU_ATF_CMD_COUNT,
|
||||
};
|
||||
|
||||
struct mtk_smi_larb_config {
|
||||
uint32_t base;
|
||||
uint32_t port_nr;
|
||||
uint32_t dom_id;
|
||||
uint32_t to_sram;
|
||||
uint32_t sec_en_msk;
|
||||
};
|
||||
|
||||
struct mtk_ifr_mst_config {
|
||||
uint8_t cfg_addr_idx;
|
||||
uint8_t r_mmu_en_bit;
|
||||
};
|
||||
|
||||
#endif /* IOMMU_PRIV_H */
|
||||
+125
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <mtk_iommu_plat.h>
|
||||
|
||||
/* defination */
|
||||
/* smi larb */
|
||||
#define SMI_LARB_NON_SEC_CON(port) (0x380 + ((port) << 2))
|
||||
#define PATH_SEL_MASK (0xf0000) /* to sram (INT) */
|
||||
#define SMI_LARB_SEC_CON_INT(port) (0xf00 + ((port) << 2))
|
||||
#define SMI_LARB_SEC_CON(port) (0xf80 + ((port) << 2))
|
||||
#define MMU_MASK BIT(0)
|
||||
#define MMU_EN(en) ((!!(en)) << 0)
|
||||
#define SEC_MASK BIT(1)
|
||||
#define SEC_EN(en) ((!!(en)) << 1)
|
||||
#define DOMAIN_MASK (0x1f << 4)
|
||||
#define SMI_MMU_EN(port) (0x1 << (port))
|
||||
|
||||
/* infra master */
|
||||
#define IFR_CFG_MMU_EN_MSK(r_bit) (0x3 << (r_bit))
|
||||
|
||||
/* smi larb configure */
|
||||
/*
|
||||
* If multimedia security config is enabled, the SMI config register must be
|
||||
* configurated in security world.
|
||||
* And the SRAM path is also configurated here to enhance security.
|
||||
*/
|
||||
static void mtk_smi_larb_port_config_to_sram(
|
||||
const struct mtk_smi_larb_config *larb,
|
||||
uint32_t port_id)
|
||||
{
|
||||
mmio_clrbits_32(larb->base + SMI_LARB_SEC_CON_INT(port_id),
|
||||
MMU_MASK | SEC_MASK | DOMAIN_MASK);
|
||||
|
||||
mmio_setbits_32(larb->base + SMI_LARB_NON_SEC_CON(port_id),
|
||||
PATH_SEL_MASK);
|
||||
}
|
||||
|
||||
static void mtk_smi_port_config(const struct mtk_smi_larb_config *larb,
|
||||
uint32_t port_id, uint8_t mmu_en, uint8_t sec_en)
|
||||
{
|
||||
mmio_clrsetbits_32(larb->base + SMI_LARB_SEC_CON(port_id),
|
||||
MMU_MASK | SEC_MASK | DOMAIN_MASK,
|
||||
MMU_EN(mmu_en) | SEC_EN(sec_en));
|
||||
}
|
||||
|
||||
static int mtk_smi_larb_port_config_sec(uint32_t larb_id, uint32_t mmu_en_msk)
|
||||
{
|
||||
uint32_t port_id, port_nr;
|
||||
const struct mtk_smi_larb_config *larb;
|
||||
uint32_t to_sram;
|
||||
uint8_t mmu_en;
|
||||
|
||||
if (larb_id >= SMI_LARB_NUM) {
|
||||
return MTK_SIP_E_INVALID_PARAM;
|
||||
}
|
||||
|
||||
larb = &g_larb_cfg[larb_id];
|
||||
port_nr = larb->port_nr;
|
||||
to_sram = larb->to_sram;
|
||||
|
||||
for (port_id = 0; port_id < port_nr; port_id++) {
|
||||
if ((to_sram & BIT(port_id)) > 0U) {
|
||||
mtk_smi_larb_port_config_to_sram(larb, port_id);
|
||||
continue;
|
||||
}
|
||||
mmu_en = !!(mmu_en_msk & SMI_MMU_EN(port_id));
|
||||
mtk_smi_port_config(larb, port_id, mmu_en, 0);
|
||||
}
|
||||
|
||||
return MTK_SIP_E_SUCCESS;
|
||||
}
|
||||
|
||||
static int mtk_infra_master_config_sec(uint32_t dev_id, uint32_t enable)
|
||||
{
|
||||
const struct mtk_ifr_mst_config *ifr_cfg;
|
||||
uint32_t reg_addr;
|
||||
|
||||
mtk_infra_iommu_enable_protect();
|
||||
|
||||
if (dev_id >= MMU_DEV_NUM) {
|
||||
return MTK_SIP_E_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
ifr_cfg = &g_ifr_mst_cfg[dev_id];
|
||||
reg_addr = g_ifr_mst_cfg_base[(ifr_cfg->cfg_addr_idx)] +
|
||||
g_ifr_mst_cfg_offs[(ifr_cfg->cfg_addr_idx)];
|
||||
|
||||
if (enable > 0U) {
|
||||
mmio_setbits_32(reg_addr, IFR_CFG_MMU_EN_MSK(ifr_cfg->r_mmu_en_bit));
|
||||
} else {
|
||||
mmio_clrbits_32(reg_addr, IFR_CFG_MMU_EN_MSK(ifr_cfg->r_mmu_en_bit));
|
||||
}
|
||||
|
||||
return MTK_SIP_E_SUCCESS;
|
||||
}
|
||||
|
||||
static u_register_t mtk_iommu_handler(u_register_t x1, u_register_t x2,
|
||||
u_register_t x3, u_register_t x4,
|
||||
void *handle, struct smccc_res *smccc_ret)
|
||||
{
|
||||
uint32_t cmd_id = x1, mdl_id = x2, val = x3;
|
||||
int ret = MTK_SIP_E_NOT_SUPPORTED;
|
||||
|
||||
(void)x4;
|
||||
(void)handle;
|
||||
|
||||
switch (cmd_id) {
|
||||
case IOMMU_ATF_CMD_CONFIG_SMI_LARB:
|
||||
ret = mtk_smi_larb_port_config_sec(mdl_id, val);
|
||||
break;
|
||||
case IOMMU_ATF_CMD_CONFIG_INFRA_IOMMU:
|
||||
ret = mtk_infra_master_config_sec(mdl_id, val);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
DECLARE_SMC_HANDLER(MTK_SIP_IOMMU_CONTROL, mtk_iommu_handler);
|
||||
@@ -0,0 +1,17 @@
|
||||
#
|
||||
# Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
LOCAL_DIR := $(call GET_LOCAL_DIR)
|
||||
|
||||
MODULE := mtk_iommu
|
||||
|
||||
LOCAL_SRCS-y := ${LOCAL_DIR}/mtk_iommu_smc.c
|
||||
LOCAL_SRCS-y += ${LOCAL_DIR}/${MTK_SOC}/mtk_iommu_plat.c
|
||||
|
||||
PLAT_INCLUDES += -I${LOCAL_DIR}
|
||||
PLAT_INCLUDES += -I${LOCAL_DIR}/${MTK_SOC}
|
||||
|
||||
$(eval $(call MAKE_MODULE,$(MODULE),$(LOCAL_SRCS-y),$(MTK_BL)))
|
||||
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <mtk_mmap_pool.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
static const mmap_region_t mcusys_mmap[] MTK_MMAP_SECTION = {
|
||||
MAP_REGION_FLAT(MCUCFG_BASE, MCUCFG_REG_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
|
||||
{0}
|
||||
};
|
||||
DECLARE_MTK_MMAP_REGIONS(mcusys_mmap);
|
||||
@@ -0,0 +1,15 @@
|
||||
#
|
||||
# Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
LOCAL_DIR := $(call GET_LOCAL_DIR)
|
||||
|
||||
MODULE := mcusys
|
||||
|
||||
PLAT_INCLUDES += -I$(LOCAL_DIR)/$(MCUSYS_VERSION)
|
||||
|
||||
LOCAL_SRCS-y := $(LOCAL_DIR)/mcusys.c
|
||||
|
||||
$(eval $(call MAKE_MODULE,$(MODULE),$(LOCAL_SRCS-y),$(MTK_BL)))
|
||||
+232
@@ -0,0 +1,232 @@
|
||||
/*
|
||||
* Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef MCUCFG_V1_H
|
||||
#define MCUCFG_V1_H
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
#include <stdint.h>
|
||||
#endif /*__ASSEMBLER__*/
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
#define MP2_MISC_CONFIG_BOOT_ADDR_L(cpu) (MCUCFG_BASE + 0x2290 + ((cpu) * 8))
|
||||
#define MP2_MISC_CONFIG_BOOT_ADDR_H(cpu) (MCUCFG_BASE + 0x2294 + ((cpu) * 8))
|
||||
|
||||
#define MP2_CPUCFG (MCUCFG_BASE + 0x2208)
|
||||
|
||||
#define MP0_CPUTOP_SPMC_CTL (MCUCFG_BASE + 0x788)
|
||||
#define MP1_CPUTOP_SPMC_CTL (MCUCFG_BASE + 0x78C)
|
||||
#define MP1_CPUTOP_SPMC_SRAM_CTL (MCUCFG_BASE + 0x790)
|
||||
|
||||
#define CPUSYSx_CPUx_SPMC_CTL(cluster, cpu) (MCUCFG_BASE + 0x1C30 + \
|
||||
(cluster) * 0x2000 + (cpu) * 4)
|
||||
|
||||
#define CPUSYS0_CPU0_SPMC_CTL (MCUCFG_BASE + 0x1C30)
|
||||
#define CPUSYS0_CPU1_SPMC_CTL (MCUCFG_BASE + 0x1C34)
|
||||
#define CPUSYS0_CPU2_SPMC_CTL (MCUCFG_BASE + 0x1C38)
|
||||
#define CPUSYS0_CPU3_SPMC_CTL (MCUCFG_BASE + 0x1C3C)
|
||||
|
||||
#define CPUSYS1_CPU0_SPMC_CTL (MCUCFG_BASE + 0x3C30)
|
||||
#define CPUSYS1_CPU1_SPMC_CTL (MCUCFG_BASE + 0x3C34)
|
||||
#define CPUSYS1_CPU2_SPMC_CTL (MCUCFG_BASE + 0x3C38)
|
||||
#define CPUSYS1_CPU3_SPMC_CTL (MCUCFG_BASE + 0x3C3C)
|
||||
|
||||
/* CPC related registers */
|
||||
#define CPC_MCUSYS_CPC_OFF_THRES (MCUCFG_BASE + 0xA714)
|
||||
#define CPC_MCUSYS_PWR_CTRL (MCUCFG_BASE + 0xA804)
|
||||
#define CPC_MCUSYS_CPC_FLOW_CTRL_CFG (MCUCFG_BASE + 0xA814)
|
||||
#define CPC_MCUSYS_LAST_CORE_REQ (MCUCFG_BASE + 0xA818)
|
||||
#define CPC_MCUSYS_MP_LAST_CORE_RESP (MCUCFG_BASE + 0xA81C)
|
||||
#define CPC_MCUSYS_LAST_CORE_RESP (MCUCFG_BASE + 0xA824)
|
||||
#define CPC_MCUSYS_PWR_ON_MASK (MCUCFG_BASE + 0xA828)
|
||||
#define CPC_SPMC_PWR_STATUS (MCUCFG_BASE + 0xA840)
|
||||
#define CPC_MCUSYS_CPU_ON_SW_HINT_SET (MCUCFG_BASE + 0xA8A8)
|
||||
#define CPC_MCUSYS_CPU_ON_SW_HINT_CLR (MCUCFG_BASE + 0xA8AC)
|
||||
#define CPC_MCUSYS_CPC_DBG_SETTING (MCUCFG_BASE + 0xAB00)
|
||||
#define CPC_MCUSYS_CPC_KERNEL_TIME_L_BASE (MCUCFG_BASE + 0xAB04)
|
||||
#define CPC_MCUSYS_CPC_KERNEL_TIME_H_BASE (MCUCFG_BASE + 0xAB08)
|
||||
#define CPC_MCUSYS_CPC_SYSTEM_TIME_L_BASE (MCUCFG_BASE + 0xAB0C)
|
||||
#define CPC_MCUSYS_CPC_SYSTEM_TIME_H_BASE (MCUCFG_BASE + 0xAB10)
|
||||
#define CPC_MCUSYS_TRACE_SEL (MCUCFG_BASE + 0xAB14)
|
||||
#define CPC_MCUSYS_TRACE_DATA (MCUCFG_BASE + 0xAB20)
|
||||
#define CPC_MCUSYS_CLUSTER_COUNTER (MCUCFG_BASE + 0xAB70)
|
||||
#define CPC_MCUSYS_CLUSTER_COUNTER_CLR (MCUCFG_BASE + 0xAB74)
|
||||
|
||||
/* CPC_MCUSYS_CPC_FLOW_CTRL_CFG bit control */
|
||||
#define CPC_CTRL_ENABLE BIT(16)
|
||||
#define SSPM_CORE_PWR_ON_EN BIT(7) /* for cpu-hotplug */
|
||||
#define SSPM_ALL_PWR_CTRL_EN BIT(13) /* for cpu-hotplug */
|
||||
#define GIC_WAKEUP_IGNORE(cpu) BIT(21 + cpu)
|
||||
|
||||
#define CPC_MCUSYS_CPC_RESET_ON_KEEP_ON BIT(17)
|
||||
#define CPC_MCUSYS_CPC_RESET_PWR_ON_EN BIT(20)
|
||||
|
||||
/* SPMC related registers */
|
||||
#define SPM_MCUSYS_PWR_CON (MCUCFG_BASE + 0xD200)
|
||||
#define SPM_MP0_CPUTOP_PWR_CON (MCUCFG_BASE + 0xD204)
|
||||
#define SPM_MP0_CPU0_PWR_CON (MCUCFG_BASE + 0xD208)
|
||||
#define SPM_MP0_CPU1_PWR_CON (MCUCFG_BASE + 0xD20C)
|
||||
#define SPM_MP0_CPU2_PWR_CON (MCUCFG_BASE + 0xD210)
|
||||
#define SPM_MP0_CPU3_PWR_CON (MCUCFG_BASE + 0xD214)
|
||||
#define SPM_MP0_CPU4_PWR_CON (MCUCFG_BASE + 0xD218)
|
||||
#define SPM_MP0_CPU5_PWR_CON (MCUCFG_BASE + 0xD21C)
|
||||
#define SPM_MP0_CPU6_PWR_CON (MCUCFG_BASE + 0xD220)
|
||||
#define SPM_MP0_CPU7_PWR_CON (MCUCFG_BASE + 0xD224)
|
||||
|
||||
/* bit fields of SPM_*_PWR_CON */
|
||||
#define PWR_ON_ACK BIT(31)
|
||||
#define VPROC_EXT_OFF BIT(7)
|
||||
#define DORMANT_EN BIT(6)
|
||||
#define RESETPWRON_CONFIG BIT(5)
|
||||
#define PWR_CLK_DIS BIT(4)
|
||||
#define PWR_ON BIT(2)
|
||||
#define PWR_RST_B BIT(0)
|
||||
|
||||
#define SPARK2LDO (MCUCFG_BASE + 0x2700)
|
||||
/* APB Module mcucfg */
|
||||
#define MP0_CA7_CACHE_CONFIG (MCUCFG_BASE + 0x000)
|
||||
#define MP0_AXI_CONFIG (MCUCFG_BASE + 0x02C)
|
||||
#define MP0_MISC_CONFIG0 (MCUCFG_BASE + 0x030)
|
||||
#define MP0_MISC_CONFIG1 (MCUCFG_BASE + 0x034)
|
||||
#define MP0_MISC_CONFIG2 (MCUCFG_BASE + 0x038)
|
||||
#define MP0_MISC_CONFIG_BOOT_ADDR(cpu) (MCUCFG_BASE + 0x038 + ((cpu) * 8))
|
||||
#define MP0_MISC_CONFIG3 (MCUCFG_BASE + 0x03C)
|
||||
#define MP0_MISC_CONFIG9 (MCUCFG_BASE + 0x054)
|
||||
#define MP0_CA7_MISC_CONFIG (MCUCFG_BASE + 0x064)
|
||||
|
||||
#define MP0_RW_RSVD0 (MCUCFG_BASE + 0x06C)
|
||||
#define MP1_CA7_CACHE_CONFIG (MCUCFG_BASE + 0x200)
|
||||
#define MP1_AXI_CONFIG (MCUCFG_BASE + 0x22C)
|
||||
#define MP1_MISC_CONFIG0 (MCUCFG_BASE + 0x230)
|
||||
#define MP1_MISC_CONFIG1 (MCUCFG_BASE + 0x234)
|
||||
#define MP1_MISC_CONFIG2 (MCUCFG_BASE + 0x238)
|
||||
#define MP1_MISC_CONFIG_BOOT_ADDR(cpu) (MCUCFG_BASE + 0x238 + ((cpu) * 8))
|
||||
#define MP1_MISC_CONFIG3 (MCUCFG_BASE + 0x23C)
|
||||
#define MP1_MISC_CONFIG9 (MCUCFG_BASE + 0x254)
|
||||
#define MP1_CA7_MISC_CONFIG (MCUCFG_BASE + 0x264)
|
||||
|
||||
#define CCI_ADB400_DCM_CONFIG (MCUCFG_BASE + 0x740)
|
||||
#define SYNC_DCM_CONFIG (MCUCFG_BASE + 0x744)
|
||||
|
||||
#define MP0_CLUSTER_CFG0 (MCUCFG_BASE + 0xC8D0)
|
||||
|
||||
#define MP0_SPMC (MCUCFG_BASE + 0x788)
|
||||
#define MP1_SPMC (MCUCFG_BASE + 0x78C)
|
||||
#define MP2_AXI_CONFIG (MCUCFG_BASE + 0x220C)
|
||||
#define MP2_AXI_CONFIG_ACINACTM BIT(0)
|
||||
#define MP2_AXI_CONFIG_AINACTS BIT(4)
|
||||
|
||||
#define MPx_AXI_CONFIG_ACINACTM BIT(4)
|
||||
#define MPx_AXI_CONFIG_AINACTS BIT(5)
|
||||
|
||||
#define MPx_CA7_MISC_CONFIG_standbywfil2 BIT(28)
|
||||
|
||||
#define MP0_CPU0_STANDBYWFE BIT(20)
|
||||
#define MP0_CPU1_STANDBYWFE BIT(21)
|
||||
#define MP0_CPU2_STANDBYWFE BIT(22)
|
||||
#define MP0_CPU3_STANDBYWFE BIT(23)
|
||||
|
||||
#define MP1_CPU0_STANDBYWFE BIT(20)
|
||||
#define MP1_CPU1_STANDBYWFE BIT(21)
|
||||
#define MP1_CPU2_STANDBYWFE BIT(22)
|
||||
#define MP1_CPU3_STANDBYWFE BIT(23)
|
||||
|
||||
#define CPUSYS0_SPARKVRETCNTRL (MCUCFG_BASE+0x1c00)
|
||||
#define CPUSYS0_SPARKEN (MCUCFG_BASE+0x1c04)
|
||||
#define CPUSYS0_AMUXSEL (MCUCFG_BASE+0x1c08)
|
||||
#define CPUSYS1_SPARKVRETCNTRL (MCUCFG_BASE+0x3c00)
|
||||
#define CPUSYS1_SPARKEN (MCUCFG_BASE+0x3c04)
|
||||
#define CPUSYS1_AMUXSEL (MCUCFG_BASE+0x3c08)
|
||||
|
||||
#define MP2_PWR_RST_CTL (MCUCFG_BASE + 0x2008)
|
||||
#define MP2_PTP3_CPUTOP_SPMC0 (MCUCFG_BASE + 0x22A0)
|
||||
#define MP2_PTP3_CPUTOP_SPMC1 (MCUCFG_BASE + 0x22A4)
|
||||
|
||||
#define MP2_COQ (MCUCFG_BASE + 0x22BC)
|
||||
#define MP2_COQ_SW_DIS BIT(0)
|
||||
|
||||
#define MP2_CA15M_MON_SEL (MCUCFG_BASE + 0x2400)
|
||||
#define MP2_CA15M_MON_L (MCUCFG_BASE + 0x2404)
|
||||
|
||||
#define CPUSYS2_CPU0_SPMC_CTL (MCUCFG_BASE + 0x2430)
|
||||
#define CPUSYS2_CPU1_SPMC_CTL (MCUCFG_BASE + 0x2438)
|
||||
#define CPUSYS2_CPU0_SPMC_STA (MCUCFG_BASE + 0x2434)
|
||||
#define CPUSYS2_CPU1_SPMC_STA (MCUCFG_BASE + 0x243C)
|
||||
|
||||
#define MP0_CA7L_DBG_PWR_CTRL (MCUCFG_BASE + 0x068)
|
||||
#define MP1_CA7L_DBG_PWR_CTRL (MCUCFG_BASE + 0x268)
|
||||
#define BIG_DBG_PWR_CTRL (MCUCFG_BASE + 0x75C)
|
||||
|
||||
#define MP2_SW_RST_B BIT(0)
|
||||
#define MP2_TOPAON_APB_MASK BIT(1)
|
||||
#define B_SW_HOT_PLUG_RESET BIT(30)
|
||||
#define B_SW_PD_OFFSET (18)
|
||||
#define B_SW_PD (0x3F << B_SW_PD_OFFSET)
|
||||
|
||||
#define B_SW_SRAM_SLEEPB_OFFSET (12)
|
||||
#define B_SW_SRAM_SLEEPB (0x3F << B_SW_SRAM_SLEEPB_OFFSET)
|
||||
|
||||
#define B_SW_SRAM_ISOINTB BIT(9)
|
||||
#define B_SW_ISO BIT(8)
|
||||
#define B_SW_LOGIC_PDB BIT(7)
|
||||
#define B_SW_LOGIC_PRE2_PDB BIT(6)
|
||||
#define B_SW_LOGIC_PRE1_PDB BIT(5)
|
||||
#define B_SW_FSM_OVERRIDE BIT(4)
|
||||
#define B_SW_PWR_ON BIT(3)
|
||||
#define B_SW_PWR_ON_OVERRIDE_EN BIT(2)
|
||||
|
||||
#define B_FSM_STATE_OUT_OFFSET (6)
|
||||
#define B_FSM_STATE_OUT_MASK (0x1F << B_FSM_STATE_OUT_OFFSET)
|
||||
#define B_SW_LOGIC_PDBO_ALL_OFF_ACK BIT(5)
|
||||
#define B_SW_LOGIC_PDBO_ALL_ON_ACK BIT(4)
|
||||
#define B_SW_LOGIC_PRE2_PDBO_ALL_ON_ACK BIT(3)
|
||||
#define B_SW_LOGIC_PRE1_PDBO_ALL_ON_ACK BIT(2)
|
||||
|
||||
|
||||
#define B_FSM_OFF (0U << B_FSM_STATE_OUT_OFFSET)
|
||||
#define B_FSM_ON (1U << B_FSM_STATE_OUT_OFFSET)
|
||||
#define B_FSM_RET (2U << B_FSM_STATE_OUT_OFFSET)
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
/* cpu boot mode */
|
||||
enum mp0_coucfg_64bit_ctrl {
|
||||
MP0_CPUCFG_64BIT_SHIFT = 12,
|
||||
MP1_CPUCFG_64BIT_SHIFT = 28,
|
||||
MP0_CPUCFG_64BIT = 0xfu << MP0_CPUCFG_64BIT_SHIFT,
|
||||
MP1_CPUCFG_64BIT = 0xfu << MP1_CPUCFG_64BIT_SHIFT,
|
||||
};
|
||||
|
||||
enum mp1_dis_rgu0_ctrl {
|
||||
MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK_SHIFT = 0,
|
||||
MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK_SHIFT = 4,
|
||||
MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK_SHIFT = 8,
|
||||
MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK_SHIFT = 12,
|
||||
MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK_SHIFT = 16,
|
||||
MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK = 0xF << MP1_DIS_RGU0_WAIT_PD_CPUS_L1_ACK_SHIFT,
|
||||
MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK = 0xF << MP1_DIS_RGU1_WAIT_PD_CPUS_L1_ACK_SHIFT,
|
||||
MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK = 0xF << MP1_DIS_RGU2_WAIT_PD_CPUS_L1_ACK_SHIFT,
|
||||
MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK = 0xF << MP1_DIS_RGU3_WAIT_PD_CPUS_L1_ACK_SHIFT,
|
||||
MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK = 0xF << MP1_DIS_RGU_NOCPU_WAIT_PD_CPUS_L1_ACK_SHIFT,
|
||||
};
|
||||
|
||||
enum mp1_ainacts_ctrl {
|
||||
MP1_AINACTS_SHIFT = 4,
|
||||
MP1_AINACTS = 1U << MP1_AINACTS_SHIFT,
|
||||
};
|
||||
|
||||
enum mp1_sw_cg_gen {
|
||||
MP1_SW_CG_GEN_SHIFT = 12,
|
||||
MP1_SW_CG_GEN = 1U << MP1_SW_CG_GEN_SHIFT,
|
||||
};
|
||||
|
||||
enum mp1_l2rstdisable {
|
||||
MP1_L2RSTDISABLE_SHIFT = 14,
|
||||
MP1_L2RSTDISABLE = 1U << MP1_L2RSTDISABLE_SHIFT,
|
||||
};
|
||||
#endif /*__ASSEMBLER__*/
|
||||
|
||||
#endif /* MCUCFG_V1_H */
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef MT_MSDC_PRIV_H
|
||||
#define MT_MSDC_PRIV_H
|
||||
|
||||
#define MSDC_CQHCI_CFG 0x808
|
||||
#define MSDC_CQHCI_CRYPTO_ENABLE BIT(1)
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <mt_msdc.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
uint64_t msdc_smc_dispatcher(uint64_t arg0, uint64_t arg1,
|
||||
uint64_t arg2, uint64_t arg3)
|
||||
{
|
||||
INFO("[%s] msdc setup call from kernel\n", __func__);
|
||||
mmio_setbits_32(MSDC0_BASE + MSDC_CQHCI_CFG, MSDC_CQHCI_CRYPTO_ENABLE);
|
||||
|
||||
return 0L;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef MT_MSDC_H
|
||||
#define MT_MSDC_H
|
||||
|
||||
#include <mt_msdc_priv.h>
|
||||
|
||||
uint64_t msdc_smc_dispatcher(uint64_t arg0, uint64_t arg1,
|
||||
uint64_t arg2, uint64_t arg3);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <pmic.h>
|
||||
#include <pmic_wrap_init.h>
|
||||
|
||||
void pmic_power_off(void)
|
||||
{
|
||||
pwrap_write(PMIC_PWRHOLD, 0x0);
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef PMIC_H
|
||||
#define PMIC_H
|
||||
|
||||
#define PMIC_PWRHOLD (0xa08)
|
||||
|
||||
/* external API */
|
||||
void pmic_power_off(void);
|
||||
|
||||
#endif /* PMIC_H */
|
||||
@@ -0,0 +1,15 @@
|
||||
#
|
||||
# Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
LOCAL_DIR := $(call GET_LOCAL_DIR)
|
||||
|
||||
MODULE := pmic
|
||||
|
||||
LOCAL_SRCS-y += ${LOCAL_DIR}/pmic.c
|
||||
|
||||
PLAT_INCLUDES += -I${LOCAL_DIR}/
|
||||
|
||||
$(eval $(call MAKE_MODULE,$(MODULE),$(LOCAL_SRCS-y),$(MTK_BL)))
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef PMIC_WRAP_INIT_H
|
||||
#define PMIC_WRAP_INIT_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "platform_def.h"
|
||||
#include <pmic_wrap_init_common.h>
|
||||
|
||||
static struct mt8188_pmic_wrap_regs *const mtk_pwrap = (void *)PMIC_WRAP_BASE;
|
||||
|
||||
/* PMIC_WRAP registers */
|
||||
struct mt8188_pmic_wrap_regs {
|
||||
uint32_t init_done;
|
||||
uint32_t reserved[543];
|
||||
uint32_t wacs2_cmd;
|
||||
uint32_t wacs2_wdata;
|
||||
uint32_t reserved1[3];
|
||||
uint32_t wacs2_rdata;
|
||||
uint32_t reserved2[3];
|
||||
uint32_t wacs2_vldclr;
|
||||
uint32_t wacs2_sta;
|
||||
};
|
||||
|
||||
#endif /* PMIC_WRAP_INIT_H */
|
||||
+165
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2022, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <drivers/delay_timer.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <platform_def.h>
|
||||
#include <pmic_wrap_init.h>
|
||||
|
||||
/* pmic wrap module wait_idle and read polling interval (in microseconds) */
|
||||
enum {
|
||||
WAIT_IDLE_POLLING_DELAY_US = 1,
|
||||
READ_POLLING_DELAY_US = 2
|
||||
};
|
||||
|
||||
static inline uint32_t wait_for_state_idle(uint32_t timeout_us,
|
||||
void *wacs_register,
|
||||
void *wacs_vldclr_register,
|
||||
uint32_t *read_reg)
|
||||
{
|
||||
uint32_t reg_rdata;
|
||||
uint32_t retry;
|
||||
|
||||
retry = (timeout_us + WAIT_IDLE_POLLING_DELAY_US) /
|
||||
WAIT_IDLE_POLLING_DELAY_US;
|
||||
|
||||
do {
|
||||
udelay(WAIT_IDLE_POLLING_DELAY_US);
|
||||
reg_rdata = mmio_read_32((uintptr_t)wacs_register);
|
||||
/* if last read command timeout,clear vldclr bit
|
||||
* read command state machine:FSM_REQ-->wfdle-->WFVLDCLR;
|
||||
* write:FSM_REQ-->idle
|
||||
*/
|
||||
switch (((reg_rdata >> RDATA_WACS_FSM_SHIFT) &
|
||||
RDATA_WACS_FSM_MASK)) {
|
||||
case WACS_FSM_WFVLDCLR:
|
||||
mmio_write_32((uintptr_t)wacs_vldclr_register, 1);
|
||||
ERROR("WACS_FSM = PMIC_WRAP_WACS_VLDCLR\n");
|
||||
break;
|
||||
case WACS_FSM_WFDLE:
|
||||
ERROR("WACS_FSM = WACS_FSM_WFDLE\n");
|
||||
break;
|
||||
case WACS_FSM_REQ:
|
||||
ERROR("WACS_FSM = WACS_FSM_REQ\n");
|
||||
break;
|
||||
case WACS_FSM_IDLE:
|
||||
goto done;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
retry--;
|
||||
} while (retry);
|
||||
|
||||
done:
|
||||
if (!retry) /* timeout */
|
||||
return E_PWR_WAIT_IDLE_TIMEOUT;
|
||||
|
||||
if (read_reg)
|
||||
*read_reg = reg_rdata;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline uint32_t wait_for_state_ready(uint32_t timeout_us,
|
||||
void *wacs_register,
|
||||
uint32_t *read_reg)
|
||||
{
|
||||
uint32_t reg_rdata;
|
||||
uint32_t retry;
|
||||
|
||||
retry = (timeout_us + READ_POLLING_DELAY_US) / READ_POLLING_DELAY_US;
|
||||
|
||||
do {
|
||||
udelay(READ_POLLING_DELAY_US);
|
||||
reg_rdata = mmio_read_32((uintptr_t)wacs_register);
|
||||
|
||||
if (((reg_rdata >> RDATA_WACS_FSM_SHIFT) & RDATA_WACS_FSM_MASK)
|
||||
== WACS_FSM_WFVLDCLR)
|
||||
break;
|
||||
|
||||
retry--;
|
||||
} while (retry);
|
||||
|
||||
if (!retry) { /* timeout */
|
||||
ERROR("timeout when waiting for idle\n");
|
||||
return E_PWR_WAIT_IDLE_TIMEOUT_READ;
|
||||
}
|
||||
|
||||
if (read_reg)
|
||||
*read_reg = reg_rdata;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t pwrap_wacs2(uint32_t write,
|
||||
uint32_t adr,
|
||||
uint32_t wdata,
|
||||
uint32_t *rdata,
|
||||
uint32_t init_check)
|
||||
{
|
||||
uint32_t reg_rdata = 0;
|
||||
uint32_t wacs_write = 0;
|
||||
uint32_t wacs_adr = 0;
|
||||
uint32_t wacs_cmd = 0;
|
||||
uint32_t return_value = 0;
|
||||
|
||||
if (init_check) {
|
||||
reg_rdata = mmio_read_32((uintptr_t)&mtk_pwrap->wacs2_rdata);
|
||||
/* Prevent someone to used pwrap before pwrap init */
|
||||
if (((reg_rdata >> RDATA_INIT_DONE_SHIFT) &
|
||||
RDATA_INIT_DONE_MASK) != WACS_INIT_DONE) {
|
||||
ERROR("initialization isn't finished\n");
|
||||
return E_PWR_NOT_INIT_DONE;
|
||||
}
|
||||
}
|
||||
reg_rdata = 0;
|
||||
/* Check IDLE in advance */
|
||||
return_value = wait_for_state_idle(TIMEOUT_WAIT_IDLE,
|
||||
&mtk_pwrap->wacs2_rdata,
|
||||
&mtk_pwrap->wacs2_vldclr,
|
||||
0);
|
||||
if (return_value != 0) {
|
||||
ERROR("wait_for_fsm_idle fail,return_value=%d\n", return_value);
|
||||
goto FAIL;
|
||||
}
|
||||
wacs_write = write << 31;
|
||||
wacs_adr = (adr >> 1) << 16;
|
||||
wacs_cmd = wacs_write | wacs_adr | wdata;
|
||||
|
||||
mmio_write_32((uintptr_t)&mtk_pwrap->wacs2_cmd, wacs_cmd);
|
||||
if (write == 0) {
|
||||
if (rdata == NULL) {
|
||||
ERROR("rdata is a NULL pointer\n");
|
||||
return_value = E_PWR_INVALID_ARG;
|
||||
goto FAIL;
|
||||
}
|
||||
return_value = wait_for_state_ready(TIMEOUT_READ,
|
||||
&mtk_pwrap->wacs2_rdata,
|
||||
®_rdata);
|
||||
if (return_value != 0) {
|
||||
ERROR("wait_for_fsm_vldclr fail,return_value=%d\n",
|
||||
return_value);
|
||||
goto FAIL;
|
||||
}
|
||||
*rdata = ((reg_rdata >> RDATA_WACS_RDATA_SHIFT)
|
||||
& RDATA_WACS_RDATA_MASK);
|
||||
mmio_write_32((uintptr_t)&mtk_pwrap->wacs2_vldclr, 1);
|
||||
}
|
||||
FAIL:
|
||||
return return_value;
|
||||
}
|
||||
|
||||
/* external API for pmic_wrap user */
|
||||
|
||||
int32_t pwrap_read(uint32_t adr, uint32_t *rdata)
|
||||
{
|
||||
return pwrap_wacs2(0, adr, 0, rdata, 1);
|
||||
}
|
||||
|
||||
int32_t pwrap_write(uint32_t adr, uint32_t wdata)
|
||||
{
|
||||
return pwrap_wacs2(1, adr, wdata, 0, 1);
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef PMIC_WRAP_INIT_COMMON_H
|
||||
#define PMIC_WRAP_INIT_COMMON_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "platform_def.h"
|
||||
|
||||
/* external API */
|
||||
int32_t pwrap_read(uint32_t adr, uint32_t *rdata);
|
||||
int32_t pwrap_write(uint32_t adr, uint32_t wdata);
|
||||
|
||||
#define GET_WACS_FSM(x) ((x >> 1) & 0x7)
|
||||
|
||||
/* macro for SWINF_FSM */
|
||||
#define SWINF_FSM_IDLE (0x00)
|
||||
#define SWINF_FSM_REQ (0x02)
|
||||
#define SWINF_FSM_WFDLE (0x04)
|
||||
#define SWINF_FSM_WFVLDCLR (0x06)
|
||||
#define SWINF_INIT_DONE (0x01)
|
||||
|
||||
/* timeout setting */
|
||||
#define PWRAP_READ_US (1000)
|
||||
#define PWRAP_WAIT_IDLE_US (1000)
|
||||
|
||||
/* error information flag */
|
||||
enum pwrap_errno {
|
||||
E_PWR_INVALID_ARG = 1,
|
||||
E_PWR_INVALID_RW = 2,
|
||||
E_PWR_INVALID_ADDR = 3,
|
||||
E_PWR_INVALID_WDAT = 4,
|
||||
E_PWR_INVALID_OP_MANUAL = 5,
|
||||
E_PWR_NOT_IDLE_STATE = 6,
|
||||
E_PWR_NOT_INIT_DONE = 7,
|
||||
E_PWR_NOT_INIT_DONE_READ = 8,
|
||||
E_PWR_WAIT_IDLE_TIMEOUT = 9,
|
||||
E_PWR_WAIT_IDLE_TIMEOUT_READ = 10,
|
||||
E_PWR_INIT_SIDLY_FAIL = 11,
|
||||
E_PWR_RESET_TIMEOUT = 12,
|
||||
E_PWR_TIMEOUT = 13,
|
||||
E_PWR_INIT_RESET_SPI = 20,
|
||||
E_PWR_INIT_SIDLY = 21,
|
||||
E_PWR_INIT_REG_CLOCK = 22,
|
||||
E_PWR_INIT_ENABLE_PMIC = 23,
|
||||
E_PWR_INIT_DIO = 24,
|
||||
E_PWR_INIT_CIPHER = 25,
|
||||
E_PWR_INIT_WRITE_TEST = 26,
|
||||
E_PWR_INIT_ENABLE_CRC = 27,
|
||||
E_PWR_INIT_ENABLE_DEWRAP = 28,
|
||||
E_PWR_INIT_ENABLE_EVENT = 29,
|
||||
E_PWR_READ_TEST_FAIL = 30,
|
||||
E_PWR_WRITE_TEST_FAIL = 31,
|
||||
E_PWR_SWITCH_DIO = 32,
|
||||
};
|
||||
|
||||
#endif /* PMIC_WRAP_INIT_COMMON_H */
|
||||
+143
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2022, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <drivers/delay_timer.h>
|
||||
#include <lib/mmio.h>
|
||||
|
||||
#include "platform_def.h"
|
||||
#include "pmic_wrap_init.h"
|
||||
|
||||
/* pmic wrap module wait_idle and read polling interval (in microseconds) */
|
||||
enum pwrap_polling_interval {
|
||||
WAIT_IDLE_POLLING_DELAY_US = 1,
|
||||
READ_POLLING_DELAY_US = 2
|
||||
};
|
||||
|
||||
static uint32_t pwrap_check_idle(void *wacs_register, uint32_t timeout_us)
|
||||
{
|
||||
uint32_t reg_rdata = 0U, retry;
|
||||
|
||||
retry = (timeout_us + WAIT_IDLE_POLLING_DELAY_US) /
|
||||
WAIT_IDLE_POLLING_DELAY_US;
|
||||
while (retry != 0) {
|
||||
udelay(WAIT_IDLE_POLLING_DELAY_US);
|
||||
reg_rdata = mmio_read_32((uintptr_t)wacs_register);
|
||||
/* if last read command timeout,clear vldclr bit
|
||||
* read command state machine:FSM_REQ-->wfdle-->WFVLDCLR;
|
||||
* write:FSM_REQ-->idle
|
||||
*/
|
||||
switch (GET_WACS_FSM(reg_rdata)) {
|
||||
case SWINF_FSM_WFVLDCLR:
|
||||
mmio_write_32((uintptr_t)&mtk_pwrap->wacs2_vldclr, 0x1);
|
||||
INFO("WACS_FSM = SWINF_FSM_WFVLDCLR\n");
|
||||
break;
|
||||
case SWINF_FSM_WFDLE:
|
||||
INFO("WACS_FSM = SWINF_FSM_WFDLE\n");
|
||||
break;
|
||||
case SWINF_FSM_REQ:
|
||||
INFO("WACS_FSM = SWINF_FSM_REQ\n");
|
||||
break;
|
||||
case SWINF_FSM_IDLE:
|
||||
goto done;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
retry--;
|
||||
};
|
||||
|
||||
done:
|
||||
if (retry == 0) {
|
||||
/* timeout */
|
||||
return E_PWR_WAIT_IDLE_TIMEOUT;
|
||||
}
|
||||
|
||||
return 0U;
|
||||
}
|
||||
|
||||
static uint32_t pwrap_check_vldclr(void *wacs_register, uint32_t timeout_us)
|
||||
{
|
||||
uint32_t reg_rdata = 0U, retry;
|
||||
|
||||
retry = (timeout_us + READ_POLLING_DELAY_US) / READ_POLLING_DELAY_US;
|
||||
while (retry != 0) {
|
||||
udelay(READ_POLLING_DELAY_US);
|
||||
reg_rdata = mmio_read_32((uintptr_t)wacs_register);
|
||||
if (GET_WACS_FSM(reg_rdata) == SWINF_FSM_WFVLDCLR) {
|
||||
break;
|
||||
}
|
||||
retry--;
|
||||
};
|
||||
|
||||
if (retry == 0) {
|
||||
/* timeout */
|
||||
return E_PWR_WAIT_IDLE_TIMEOUT;
|
||||
}
|
||||
|
||||
return 0U;
|
||||
}
|
||||
|
||||
static int32_t pwrap_wacs2(uint32_t write, uint32_t adr, uint32_t wdata,
|
||||
uint32_t *rdata, uint32_t init_check)
|
||||
{
|
||||
uint32_t reg_rdata, return_value;
|
||||
|
||||
if (init_check != 0) {
|
||||
if ((mmio_read_32((uintptr_t)&mtk_pwrap->init_done) & 0x1) == 0) {
|
||||
ERROR("initialization isn't finished\n");
|
||||
return E_PWR_NOT_INIT_DONE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Wait for Software Interface FSM state to be IDLE. */
|
||||
return_value = pwrap_check_idle(&mtk_pwrap->wacs2_sta,
|
||||
PWRAP_WAIT_IDLE_US);
|
||||
if (return_value != 0) {
|
||||
return return_value;
|
||||
}
|
||||
|
||||
/* Set the write data */
|
||||
if (write == 1) {
|
||||
/* Set the write data. */
|
||||
mmio_write_32((uintptr_t)&mtk_pwrap->wacs2_wdata, wdata);
|
||||
}
|
||||
|
||||
/* Send the command. */
|
||||
mmio_write_32((uintptr_t)&mtk_pwrap->wacs2_cmd, (write << 29) | adr);
|
||||
|
||||
if (write == 0) {
|
||||
/*
|
||||
* Wait for Software Interface FSM state to be WFVLDCLR,
|
||||
* read the data and clear the valid flag.
|
||||
*/
|
||||
return_value = pwrap_check_vldclr(&mtk_pwrap->wacs2_sta,
|
||||
PWRAP_READ_US);
|
||||
if (return_value != 0) {
|
||||
return return_value;
|
||||
}
|
||||
|
||||
if (rdata == NULL) {
|
||||
return E_PWR_INVALID_ARG;
|
||||
}
|
||||
|
||||
reg_rdata = mmio_read_32((uintptr_t)&mtk_pwrap->wacs2_rdata);
|
||||
*rdata = reg_rdata;
|
||||
mmio_write_32((uintptr_t)&mtk_pwrap->wacs2_vldclr, 0x1);
|
||||
}
|
||||
|
||||
return return_value;
|
||||
}
|
||||
|
||||
/* external API for pmic_wrap user */
|
||||
int32_t pwrap_read(uint32_t adr, uint32_t *rdata)
|
||||
{
|
||||
return pwrap_wacs2(0, adr, 0, rdata, 1);
|
||||
}
|
||||
|
||||
int32_t pwrap_write(uint32_t adr, uint32_t wdata)
|
||||
{
|
||||
return pwrap_wacs2(1, adr, wdata, 0, 1);
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
#
|
||||
# Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
LOCAL_DIR := $(call GET_LOCAL_DIR)
|
||||
|
||||
MODULE := pmic_wrap
|
||||
|
||||
ifeq (${USE_PMIC_WRAP_INIT_V2}, 1)
|
||||
LOCAL_SRCS-y += ${LOCAL_DIR}/pmic_wrap_init_v2.c
|
||||
else
|
||||
LOCAL_SRCS-y += ${LOCAL_DIR}/pmic_wrap_init.c
|
||||
endif
|
||||
|
||||
PLAT_INCLUDES += -I${LOCAL_DIR}/
|
||||
PLAT_INCLUDES += -I${LOCAL_DIR}/${MTK_SOC}
|
||||
|
||||
$(eval $(call MAKE_MODULE,$(MODULE),$(LOCAL_SRCS-y),$(MTK_BL)))
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef PTP3_PLAT_H
|
||||
#define PTP3_PLAT_H
|
||||
|
||||
#include <lib/mmio.h>
|
||||
#include <lib/utils_def.h>
|
||||
#include <ptp3_common.h>
|
||||
|
||||
/* CPU Info */
|
||||
#define NR_PTP3_CFG_CPU U(8)
|
||||
#define PTP3_CFG_CPU_START_ID_L U(0)
|
||||
#define PTP3_CFG_CPU_START_ID_B U(6)
|
||||
#define PTP3_CFG_CPU_END_ID U(7)
|
||||
|
||||
#define NR_PTP3_CFG1_DATA U(2)
|
||||
#define PTP3_CFG1_MASK (0x3000)
|
||||
|
||||
#define NR_PTP3_CFG2_DATA U(5)
|
||||
|
||||
#define PTP3_CFG3_MASK1 (0x1180)
|
||||
#define PTP3_CFG3_MASK2 (0x35C0)
|
||||
#define PTP3_CFG3_MASK3 (0x3DC0)
|
||||
|
||||
|
||||
/* Central control */
|
||||
static unsigned int ptp3_cfg1[NR_PTP3_CFG1_DATA][NR_PTP3_CFG] = {
|
||||
{0x0C53A2A0, 0x1000},
|
||||
{0x0C53A2A4, 0x1000}
|
||||
};
|
||||
|
||||
static unsigned int ptp3_cfg2[NR_PTP3_CFG2_DATA][NR_PTP3_CFG] = {
|
||||
{0x0C530404, 0x3A1000},
|
||||
{0x0C530428, 0x13E0408},
|
||||
{0x0C530434, 0xB22800},
|
||||
{0x0C53043C, 0x750},
|
||||
{0x0C530440, 0x0222c4cc}
|
||||
};
|
||||
|
||||
static unsigned int ptp3_cfg3[NR_PTP3_CFG] = {0x0C530400, 0xC00};
|
||||
static unsigned int ptp3_cfg3_ext[NR_PTP3_CFG] = {0x0C530400, 0xC00};
|
||||
|
||||
#endif /* PTP3_PLAT_H */
|
||||
+122
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#if MTK_PUBEVENT_ENABLE
|
||||
#include <lib/pm/mtk_pm.h>
|
||||
#endif
|
||||
#include <ptp3_plat.h>
|
||||
|
||||
#define PTP3_CORE_OFT(core) (0x800 * (core))
|
||||
|
||||
static void ptp3_init(unsigned int core)
|
||||
{
|
||||
unsigned int i, addr, value;
|
||||
|
||||
if (core < PTP3_CFG_CPU_START_ID_B) {
|
||||
mmio_clrsetbits_32(ptp3_cfg1[0][PTP3_CFG_ADDR], PTP3_CFG1_MASK,
|
||||
ptp3_cfg1[0][PTP3_CFG_VALUE]);
|
||||
} else {
|
||||
mmio_clrsetbits_32(ptp3_cfg1[1][PTP3_CFG_ADDR], PTP3_CFG1_MASK,
|
||||
ptp3_cfg1[1][PTP3_CFG_VALUE]);
|
||||
}
|
||||
|
||||
if (core < PTP3_CFG_CPU_START_ID_B) {
|
||||
for (i = 0; i < NR_PTP3_CFG2_DATA; i++) {
|
||||
addr = ptp3_cfg2[i][PTP3_CFG_ADDR] + PTP3_CORE_OFT(core);
|
||||
value = ptp3_cfg2[i][PTP3_CFG_VALUE];
|
||||
|
||||
mmio_write_32(addr, value);
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < NR_PTP3_CFG2_DATA; i++) {
|
||||
addr = ptp3_cfg2[i][PTP3_CFG_ADDR] + PTP3_CORE_OFT(core);
|
||||
|
||||
if (i == 2) {
|
||||
value = ptp3_cfg2[i][PTP3_CFG_VALUE] + 0x5E0;
|
||||
} else {
|
||||
value = ptp3_cfg2[i][PTP3_CFG_VALUE];
|
||||
}
|
||||
mmio_write_32(addr, value);
|
||||
}
|
||||
}
|
||||
|
||||
if (core < PTP3_CFG_CPU_START_ID_B) {
|
||||
addr = ptp3_cfg3[PTP3_CFG_ADDR] + PTP3_CORE_OFT(core);
|
||||
value = ptp3_cfg3[PTP3_CFG_VALUE];
|
||||
} else {
|
||||
addr = ptp3_cfg3_ext[PTP3_CFG_ADDR] + PTP3_CORE_OFT(core);
|
||||
value = ptp3_cfg3_ext[PTP3_CFG_VALUE];
|
||||
}
|
||||
mmio_write_32(addr, value & PTP3_CFG3_MASK1);
|
||||
mmio_write_32(addr, value & PTP3_CFG3_MASK2);
|
||||
mmio_write_32(addr, value & PTP3_CFG3_MASK3);
|
||||
}
|
||||
|
||||
static void pdp_proc_arm_write(unsigned int pdp_n)
|
||||
{
|
||||
unsigned long v = 0;
|
||||
|
||||
dsb();
|
||||
__asm__ volatile ("mrs %0, S3_6_C15_C2_0" : "=r" (v));
|
||||
v |= (UL(0x0) << 52);
|
||||
v |= (UL(0x1) << 53);
|
||||
v |= (UL(0x0) << 54);
|
||||
v |= (UL(0x0) << 48);
|
||||
v |= (UL(0x1) << 49);
|
||||
__asm__ volatile ("msr S3_6_C15_C2_0, %0" : : "r" (v));
|
||||
dsb();
|
||||
}
|
||||
|
||||
static void pdp_init(unsigned int pdp_cpu)
|
||||
{
|
||||
if ((pdp_cpu >= PTP3_CFG_CPU_START_ID_B) && (pdp_cpu < NR_PTP3_CFG_CPU)) {
|
||||
pdp_proc_arm_write(pdp_cpu);
|
||||
}
|
||||
}
|
||||
|
||||
void ptp3_core_init(unsigned int core)
|
||||
{
|
||||
ptp3_init(core);
|
||||
pdp_init(core);
|
||||
}
|
||||
|
||||
void ptp3_core_deinit(unsigned int core)
|
||||
{
|
||||
/* TBD */
|
||||
}
|
||||
|
||||
#if MTK_PUBEVENT_ENABLE
|
||||
/* Handle for power on domain */
|
||||
void *ptp3_handle_pwr_on_event(const void *arg)
|
||||
{
|
||||
if (arg != NULL) {
|
||||
struct mt_cpupm_event_data *data = (struct mt_cpupm_event_data *)arg;
|
||||
|
||||
if ((data->pwr_domain & MT_CPUPM_PWR_DOMAIN_CORE) > 0) {
|
||||
ptp3_core_init(data->cpuid);
|
||||
}
|
||||
}
|
||||
return (void *)arg;
|
||||
}
|
||||
MT_CPUPM_SUBCRIBE_EVENT_PWR_ON(ptp3_handle_pwr_on_event);
|
||||
|
||||
/* Handle for power off domain */
|
||||
void *ptp3_handle_pwr_off_event(const void *arg)
|
||||
{
|
||||
if (arg != NULL) {
|
||||
struct mt_cpupm_event_data *data = (struct mt_cpupm_event_data *)arg;
|
||||
|
||||
if ((data->pwr_domain & MT_CPUPM_PWR_DOMAIN_CORE) > 0) {
|
||||
ptp3_core_deinit(data->cpuid);
|
||||
}
|
||||
}
|
||||
return (void *)arg;
|
||||
}
|
||||
MT_CPUPM_SUBCRIBE_EVENT_PWR_OFF(ptp3_handle_pwr_off_event);
|
||||
#else
|
||||
#pragma message "PSCI hint not enable"
|
||||
#endif
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef PTP3_COMMON_H
|
||||
#define PTP3_COMMON_H
|
||||
|
||||
/* config enum */
|
||||
enum PTP3_CFG {
|
||||
PTP3_CFG_ADDR,
|
||||
PTP3_CFG_VALUE,
|
||||
NR_PTP3_CFG,
|
||||
};
|
||||
|
||||
/* prototype */
|
||||
void ptp3_core_init(unsigned int core);
|
||||
void ptp3_core_deinit(unsigned int core);
|
||||
|
||||
#endif /* PTP3_COMMON_H */
|
||||
@@ -0,0 +1,16 @@
|
||||
#
|
||||
# Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
LOCAL_DIR := $(call GET_LOCAL_DIR)
|
||||
|
||||
MODULE := mtk_ptp3
|
||||
|
||||
LOCAL_SRCS-y := ${LOCAL_DIR}/ptp3_common.c
|
||||
|
||||
PLAT_INCLUDES += -I${LOCAL_DIR}
|
||||
PLAT_INCLUDES += -I${LOCAL_DIR}/$(MTK_SOC)
|
||||
|
||||
$(eval $(call MAKE_MODULE,$(MODULE),$(LOCAL_SRCS-y),$(MTK_BL)))
|
||||
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef RTC_H
|
||||
#define RTC_H
|
||||
|
||||
#include <rtc_mt6359p.h>
|
||||
|
||||
#endif /* RTC_H */
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2022, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <drivers/delay_timer.h>
|
||||
|
||||
#include <pmic_wrap_init.h>
|
||||
#include <rtc.h>
|
||||
|
||||
/* RTC busy status polling interval and retry count */
|
||||
enum {
|
||||
RTC_WRTGR_POLLING_DELAY_MS = 10,
|
||||
RTC_WRTGR_POLLING_CNT = 100
|
||||
};
|
||||
|
||||
uint16_t RTC_Read(uint32_t addr)
|
||||
{
|
||||
uint32_t rdata = 0;
|
||||
|
||||
pwrap_read((uint32_t)addr, &rdata);
|
||||
return (uint16_t)rdata;
|
||||
}
|
||||
|
||||
void RTC_Write(uint32_t addr, uint16_t data)
|
||||
{
|
||||
pwrap_write((uint32_t)addr, (uint32_t)data);
|
||||
}
|
||||
|
||||
int32_t rtc_busy_wait(void)
|
||||
{
|
||||
uint64_t retry = RTC_WRTGR_POLLING_CNT;
|
||||
|
||||
do {
|
||||
mdelay(RTC_WRTGR_POLLING_DELAY_MS);
|
||||
if (!(RTC_Read(RTC_BBPU) & RTC_BBPU_CBUSY))
|
||||
return 1;
|
||||
retry--;
|
||||
} while (retry);
|
||||
|
||||
ERROR("[RTC] rtc cbusy time out!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t RTC_Write_Trigger(void)
|
||||
{
|
||||
RTC_Write(RTC_WRTGR, 1);
|
||||
return rtc_busy_wait();
|
||||
}
|
||||
|
||||
int32_t Writeif_unlock(void)
|
||||
{
|
||||
RTC_Write(RTC_PROT, RTC_PROT_UNLOCK1);
|
||||
if (!RTC_Write_Trigger())
|
||||
return 0;
|
||||
RTC_Write(RTC_PROT, RTC_PROT_UNLOCK2);
|
||||
if (!RTC_Write_Trigger())
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
+148
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2022, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <drivers/delay_timer.h>
|
||||
#include <rtc.h>
|
||||
|
||||
|
||||
static void RTC_Config_Interface(uint32_t addr, uint16_t data,
|
||||
uint16_t mask, uint16_t shift)
|
||||
{
|
||||
uint16_t pmic_reg;
|
||||
|
||||
pmic_reg = RTC_Read(addr);
|
||||
|
||||
pmic_reg &= ~(mask << shift);
|
||||
pmic_reg |= (data << shift);
|
||||
|
||||
RTC_Write(addr, pmic_reg);
|
||||
}
|
||||
|
||||
static int32_t rtc_disable_2sec_reboot(void)
|
||||
{
|
||||
uint16_t reboot;
|
||||
|
||||
reboot = (RTC_Read(RTC_AL_SEC) & ~RTC_BBPU_2SEC_EN) &
|
||||
~RTC_BBPU_AUTO_PDN_SEL;
|
||||
RTC_Write(RTC_AL_SEC, reboot);
|
||||
|
||||
return RTC_Write_Trigger();
|
||||
}
|
||||
|
||||
static int32_t rtc_enable_k_eosc(void)
|
||||
{
|
||||
uint16_t alm_dow, alm_sec;
|
||||
int16_t ret;
|
||||
|
||||
/* Turning on eosc cali mode clock */
|
||||
RTC_Config_Interface(PMIC_RG_SCK_TOP_CKPDN_CON0_CLR, 1,
|
||||
PMIC_RG_RTC_EOSC32_CK_PDN_MASK,
|
||||
PMIC_RG_RTC_EOSC32_CK_PDN_SHIFT);
|
||||
|
||||
alm_sec = RTC_Read(RTC_AL_SEC) & (~RTC_LPD_OPT_MASK);
|
||||
RTC_Write(RTC_AL_SEC, alm_sec);
|
||||
ret = RTC_Write_Trigger();
|
||||
if (ret == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
RTC_Write(RTC_CON, RTC_LPD_EN);
|
||||
ret = RTC_Write_Trigger();
|
||||
if (ret == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
RTC_Write(RTC_CON, RTC_LPD_RST);
|
||||
ret = RTC_Write_Trigger();
|
||||
if (ret == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
RTC_Write(RTC_CON, RTC_LPD_EN);
|
||||
ret = RTC_Write_Trigger();
|
||||
if (ret == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
RTC_Write(RTC_POWERKEY1, RTC_POWERKEY1_KEY);
|
||||
RTC_Write(RTC_POWERKEY2, RTC_POWERKEY2_KEY);
|
||||
ret = RTC_Write_Trigger();
|
||||
if (ret == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* set RTC EOSC calibration period = 8sec */
|
||||
alm_dow = (RTC_Read(RTC_AL_DOW) & (~RTC_RG_EOSC_CALI_TD_MASK)) |
|
||||
RTC_RG_EOSC_CALI_TD_8SEC;
|
||||
RTC_Write(RTC_AL_DOW, alm_dow);
|
||||
ret = RTC_Write_Trigger();
|
||||
if (ret == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
RTC_Write(RTC_BBPU,
|
||||
RTC_Read(RTC_BBPU) | RTC_BBPU_KEY | RTC_BBPU_RELOAD);
|
||||
ret = RTC_Write_Trigger();
|
||||
if (ret == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Enable K EOSC mode :use solution1 of eosc cali to fix mt6359p 32K*/
|
||||
RTC_Write(RTC_AL_YEA, (((RTC_Read(RTC_AL_YEA) | RTC_K_EOSC_RSV_0)
|
||||
& (~RTC_K_EOSC_RSV_1)) | (RTC_K_EOSC_RSV_2)));
|
||||
ret = RTC_Write_Trigger();
|
||||
if (ret == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
INFO("[RTC] RTC_enable_k_eosc\n");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void rtc_power_off_sequence(void)
|
||||
{
|
||||
uint16_t bbpu;
|
||||
int16_t ret;
|
||||
|
||||
ret = rtc_disable_2sec_reboot();
|
||||
if (ret == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
ret = rtc_enable_k_eosc();
|
||||
if (ret == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
bbpu = RTC_BBPU_KEY | RTC_BBPU_PWREN;
|
||||
|
||||
if (Writeif_unlock() != 0) {
|
||||
RTC_Write(RTC_BBPU,
|
||||
bbpu | RTC_BBPU_RESET_ALARM | RTC_BBPU_RESET_SPAR);
|
||||
RTC_Write(RTC_AL_MASK, RTC_AL_MASK_DOW);
|
||||
ret = RTC_Write_Trigger();
|
||||
if (ret == 0) {
|
||||
return;
|
||||
}
|
||||
mdelay(1);
|
||||
|
||||
bbpu = RTC_Read(RTC_BBPU);
|
||||
|
||||
if (((bbpu & RTC_BBPU_RESET_ALARM) > 0) ||
|
||||
((bbpu & RTC_BBPU_RESET_SPAR) > 0)) {
|
||||
INFO("[RTC] timeout\n");
|
||||
}
|
||||
|
||||
bbpu = RTC_Read(RTC_BBPU) | RTC_BBPU_KEY | RTC_BBPU_RELOAD;
|
||||
RTC_Write(RTC_BBPU, bbpu);
|
||||
ret = RTC_Write_Trigger();
|
||||
if (ret == 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
+197
@@ -0,0 +1,197 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2022, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef RTC_MT6359P_H
|
||||
#define RTC_MT6359P_H
|
||||
|
||||
/* RTC registers */
|
||||
enum {
|
||||
RTC_BBPU = 0x0588,
|
||||
RTC_IRQ_STA = 0x058A,
|
||||
RTC_IRQ_EN = 0x058C,
|
||||
RTC_CII_EN = 0x058E
|
||||
};
|
||||
|
||||
enum {
|
||||
RTC_AL_SEC = 0x05A0,
|
||||
RTC_AL_MIN = 0x05A2,
|
||||
RTC_AL_HOU = 0x05A4,
|
||||
RTC_AL_DOM = 0x05A6,
|
||||
RTC_AL_DOW = 0x05A8,
|
||||
RTC_AL_MTH = 0x05AA,
|
||||
RTC_AL_YEA = 0x05AC,
|
||||
RTC_AL_MASK = 0x0590
|
||||
};
|
||||
|
||||
enum {
|
||||
RTC_OSC32CON = 0x05AE,
|
||||
RTC_CON = 0x05C4,
|
||||
RTC_WRTGR = 0x05C2
|
||||
};
|
||||
|
||||
enum {
|
||||
RTC_POWERKEY1 = 0x05B0,
|
||||
RTC_POWERKEY2 = 0x05B2
|
||||
};
|
||||
|
||||
enum {
|
||||
RTC_POWERKEY1_KEY = 0xA357,
|
||||
RTC_POWERKEY2_KEY = 0x67D2
|
||||
};
|
||||
|
||||
enum {
|
||||
RTC_PDN1 = 0x05B4,
|
||||
RTC_PDN2 = 0x05B6,
|
||||
RTC_SPAR0 = 0x05B8,
|
||||
RTC_SPAR1 = 0x05BA,
|
||||
RTC_PROT = 0x05BC,
|
||||
RTC_DIFF = 0x05BE,
|
||||
RTC_CALI = 0x05C0
|
||||
};
|
||||
|
||||
enum {
|
||||
RTC_OSC32CON_UNLOCK1 = 0x1A57,
|
||||
RTC_OSC32CON_UNLOCK2 = 0x2B68
|
||||
};
|
||||
|
||||
enum {
|
||||
RTC_LPD_EN = 0x0406,
|
||||
RTC_LPD_RST = 0x040E
|
||||
};
|
||||
|
||||
enum {
|
||||
RTC_LPD_OPT_XOSC_AND_EOSC_LPD = 0U << 13,
|
||||
RTC_LPD_OPT_EOSC_LPD = 1U << 13,
|
||||
RTC_LPD_OPT_XOSC_LPD = 2U << 13,
|
||||
RTC_LPD_OPT_F32K_CK_ALIVE = 3U << 13,
|
||||
};
|
||||
|
||||
#define RTC_LPD_OPT_MASK (3U << 13)
|
||||
|
||||
enum {
|
||||
RTC_PROT_UNLOCK1 = 0x586A,
|
||||
RTC_PROT_UNLOCK2 = 0x9136
|
||||
};
|
||||
|
||||
enum {
|
||||
RTC_BBPU_PWREN = 1U << 0,
|
||||
RTC_BBPU_SPAR_SW = 1U << 1,
|
||||
RTC_BBPU_RESET_SPAR = 1U << 2,
|
||||
RTC_BBPU_RESET_ALARM = 1U << 3,
|
||||
RTC_BBPU_CLRPKY = 1U << 4,
|
||||
RTC_BBPU_RELOAD = 1U << 5,
|
||||
RTC_BBPU_CBUSY = 1U << 6
|
||||
};
|
||||
|
||||
enum {
|
||||
RTC_AL_MASK_SEC = 1U << 0,
|
||||
RTC_AL_MASK_MIN = 1U << 1,
|
||||
RTC_AL_MASK_HOU = 1U << 2,
|
||||
RTC_AL_MASK_DOM = 1U << 3,
|
||||
RTC_AL_MASK_DOW = 1U << 4,
|
||||
RTC_AL_MASK_MTH = 1U << 5,
|
||||
RTC_AL_MASK_YEA = 1U << 6
|
||||
};
|
||||
|
||||
enum {
|
||||
RTC_BBPU_AUTO_PDN_SEL = 1U << 6,
|
||||
RTC_BBPU_2SEC_CK_SEL = 1U << 7,
|
||||
RTC_BBPU_2SEC_EN = 1U << 8,
|
||||
RTC_BBPU_2SEC_MODE = 0x3 << 9,
|
||||
RTC_BBPU_2SEC_STAT_CLEAR = 1U << 11,
|
||||
RTC_BBPU_2SEC_STAT_STA = 1U << 12
|
||||
};
|
||||
|
||||
enum {
|
||||
RTC_BBPU_KEY = 0x43 << 8
|
||||
};
|
||||
|
||||
enum {
|
||||
RTC_EMBCK_SRC_SEL = 1 << 8,
|
||||
RTC_EMBCK_SEL_MODE = 3 << 6,
|
||||
RTC_XOSC32_ENB = 1 << 5,
|
||||
RTC_REG_XOSC32_ENB = 1 << 15
|
||||
};
|
||||
|
||||
enum {
|
||||
RTC_K_EOSC_RSV_0 = 1 << 8,
|
||||
RTC_K_EOSC_RSV_1 = 1 << 9,
|
||||
RTC_K_EOSC_RSV_2 = 1 << 10
|
||||
};
|
||||
|
||||
enum {
|
||||
RTC_RG_EOSC_CALI_TD_1SEC = 3 << 5,
|
||||
RTC_RG_EOSC_CALI_TD_2SEC = 4 << 5,
|
||||
RTC_RG_EOSC_CALI_TD_4SEC = 5 << 5,
|
||||
RTC_RG_EOSC_CALI_TD_8SEC = 6 << 5,
|
||||
RTC_RG_EOSC_CALI_TD_16SEC = 7 << 5,
|
||||
RTC_RG_EOSC_CALI_TD_MASK = 7 << 5
|
||||
};
|
||||
|
||||
/* PMIC TOP Register Definition */
|
||||
enum {
|
||||
PMIC_RG_TOP_CON = 0x0020,
|
||||
PMIC_RG_TOP_CKPDN_CON1 = 0x0112,
|
||||
PMIC_RG_TOP_CKPDN_CON1_SET = 0x0114,
|
||||
PMIC_RG_TOP_CKPDN_CON1_CLR = 0x0116,
|
||||
PMIC_RG_TOP_CKSEL_CON0 = 0x0118,
|
||||
PMIC_RG_TOP_CKSEL_CON0_SET = 0x011A,
|
||||
PMIC_RG_TOP_CKSEL_CON0_CLR = 0x011C
|
||||
};
|
||||
|
||||
/* PMIC SCK Register Definition */
|
||||
enum {
|
||||
PMIC_RG_SCK_TOP_CKPDN_CON0 = 0x0514,
|
||||
PMIC_RG_SCK_TOP_CKPDN_CON0_SET = 0x0516,
|
||||
PMIC_RG_SCK_TOP_CKPDN_CON0_CLR = 0x0518,
|
||||
PMIC_RG_EOSC_CALI_CON0 = 0x53A
|
||||
};
|
||||
|
||||
enum {
|
||||
PMIC_EOSC_CALI_START_ADDR = 0x53A
|
||||
};
|
||||
|
||||
enum {
|
||||
PMIC_EOSC_CALI_START_MASK = 0x1,
|
||||
PMIC_EOSC_CALI_START_SHIFT = 0
|
||||
};
|
||||
|
||||
/* PMIC DCXO Register Definition */
|
||||
enum {
|
||||
PMIC_RG_DCXO_CW00 = 0x0788,
|
||||
PMIC_RG_DCXO_CW02 = 0x0790,
|
||||
PMIC_RG_DCXO_CW08 = 0x079C,
|
||||
PMIC_RG_DCXO_CW09 = 0x079E,
|
||||
PMIC_RG_DCXO_CW09_CLR = 0x07A2,
|
||||
PMIC_RG_DCXO_CW10 = 0x07A4,
|
||||
PMIC_RG_DCXO_CW12 = 0x07A8,
|
||||
PMIC_RG_DCXO_CW13 = 0x07AA,
|
||||
PMIC_RG_DCXO_CW15 = 0x07AE,
|
||||
PMIC_RG_DCXO_CW19 = 0x07B6,
|
||||
};
|
||||
|
||||
enum {
|
||||
PMIC_RG_SRCLKEN_IN0_HW_MODE_MASK = 0x1,
|
||||
PMIC_RG_SRCLKEN_IN0_HW_MODE_SHIFT = 1,
|
||||
PMIC_RG_SRCLKEN_IN1_HW_MODE_MASK = 0x1,
|
||||
PMIC_RG_SRCLKEN_IN1_HW_MODE_SHIFT = 3,
|
||||
PMIC_RG_RTC_EOSC32_CK_PDN_MASK = 0x1,
|
||||
PMIC_RG_RTC_EOSC32_CK_PDN_SHIFT = 2,
|
||||
PMIC_RG_EOSC_CALI_TD_MASK = 0x7,
|
||||
PMIC_RG_EOSC_CALI_TD_SHIFT = 5,
|
||||
PMIC_RG_XO_EN32K_MAN_MASK = 0x1,
|
||||
PMIC_RG_XO_EN32K_MAN_SHIFT = 0
|
||||
};
|
||||
|
||||
/* external API */
|
||||
uint16_t RTC_Read(uint32_t addr);
|
||||
void RTC_Write(uint32_t addr, uint16_t data);
|
||||
int32_t rtc_busy_wait(void);
|
||||
int32_t RTC_Write_Trigger(void);
|
||||
int32_t Writeif_unlock(void);
|
||||
void rtc_power_off_sequence(void);
|
||||
|
||||
#endif /* RTC_MT6359P_H */
|
||||
@@ -0,0 +1,20 @@
|
||||
#
|
||||
# Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
LOCAL_DIR := $(call GET_LOCAL_DIR)
|
||||
|
||||
MODULE := rtc
|
||||
|
||||
LOCAL_SRCS-y := ${LOCAL_DIR}/rtc_common.c
|
||||
|
||||
ifeq (${USE_RTC_MT6359P}, 1)
|
||||
LOCAL_SRCS-y += ${LOCAL_DIR}/rtc_mt6359p.c
|
||||
PLAT_INCLUDES += -I${LOCAL_DIR}
|
||||
endif
|
||||
|
||||
PLAT_INCLUDES += -I${LOCAL_DIR}/${MTK_SOC}
|
||||
|
||||
$(eval $(call MAKE_MODULE,$(MODULE),$(LOCAL_SRCS-y),$(MTK_BL)))
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2022, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch_helpers.h>
|
||||
#include <common/debug.h>
|
||||
#include <lib/mmio.h>
|
||||
#include <lib/mtk_init/mtk_init.h>
|
||||
#include <mt_timer.h>
|
||||
#include <platform_def.h>
|
||||
|
||||
uint64_t normal_time_base;
|
||||
uint64_t atf_time_base;
|
||||
|
||||
void sched_clock_init(uint64_t normal_base, uint64_t atf_base)
|
||||
{
|
||||
normal_time_base += normal_base;
|
||||
atf_time_base = atf_base;
|
||||
}
|
||||
|
||||
uint64_t sched_clock(void)
|
||||
{
|
||||
uint64_t cval;
|
||||
uint64_t rel_base;
|
||||
|
||||
rel_base = read_cntpct_el0() - atf_time_base;
|
||||
cval = ((rel_base * 1000U) / SYS_COUNTER_FREQ_IN_MHZ)
|
||||
- normal_time_base;
|
||||
return cval;
|
||||
}
|
||||
|
||||
int mt_systimer_init(void)
|
||||
{
|
||||
INFO("[%s] systimer initialization\n", __func__);
|
||||
|
||||
/* Enable access in NS mode */
|
||||
mmio_write_32(CNTWACR_REG, CNT_WRITE_ACCESS_CTL_MASK);
|
||||
mmio_write_32(CNTRACR_REG, CNT_READ_ACCESS_CTL_MASK);
|
||||
|
||||
return 0;
|
||||
}
|
||||
MTK_PLAT_SETUP_0_INIT(mt_systimer_init);
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2022, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef MT_TIMER_H
|
||||
#define MT_TIMER_H
|
||||
|
||||
#define SYSTIMER_BASE (0x10017000)
|
||||
#define CNTCR_REG (SYSTIMER_BASE + 0x0)
|
||||
#define CNTSR_REG (SYSTIMER_BASE + 0x4)
|
||||
#define CNTSYS_L_REG (SYSTIMER_BASE + 0x8)
|
||||
#define CNTSYS_H_REG (SYSTIMER_BASE + 0xc)
|
||||
#define CNTWACR_REG (SYSTIMER_BASE + 0x10)
|
||||
#define CNTRACR_REG (SYSTIMER_BASE + 0x14)
|
||||
|
||||
#define TIEO_EN (1 << 3)
|
||||
#define COMP_15_EN (1 << 10)
|
||||
#define COMP_20_EN (1 << 11)
|
||||
#define COMP_25_EN (1 << 12)
|
||||
|
||||
#define COMP_FEATURE_MASK (COMP_15_EN | COMP_20_EN | COMP_25_EN | TIEO_EN)
|
||||
#define COMP_15_MASK (COMP_15_EN)
|
||||
#define COMP_20_MASK (COMP_20_EN | TIEO_EN)
|
||||
#define COMP_25_MASK (COMP_20_EN | COMP_25_EN)
|
||||
|
||||
#define CNT_WRITE_ACCESS_CTL_MASK (0x3FFFFF0U)
|
||||
#define CNT_READ_ACCESS_CTL_MASK (0x3FFFFFFU)
|
||||
|
||||
void sched_clock_init(uint64_t normal_base, uint64_t atf_base);
|
||||
uint64_t sched_clock(void);
|
||||
int mt_systimer_init(void);
|
||||
|
||||
#endif /* MT_TIMER_H */
|
||||
@@ -0,0 +1,14 @@
|
||||
#
|
||||
# Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
LOCAL_DIR := $(call GET_LOCAL_DIR)
|
||||
|
||||
MODULE := timer
|
||||
LOCAL_SRCS-y := $(LOCAL_DIR)/mt_timer.c
|
||||
|
||||
PLAT_INCLUDES += -I${LOCAL_DIR}
|
||||
|
||||
$(eval $(call MAKE_MODULE,$(MODULE),$(LOCAL_SRCS-y),$(MTK_BL)))
|
||||
+163
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#include <asm_macros.S>
|
||||
#include <uart8250.h>
|
||||
|
||||
.globl console_core_init
|
||||
.globl console_core_putc
|
||||
.globl console_core_getc
|
||||
.globl console_core_flush
|
||||
|
||||
/* -----------------------------------------------
|
||||
* int console_core_init(unsigned long base_addr,
|
||||
* unsigned int uart_clk, unsigned int baud_rate)
|
||||
* Function to initialize the console without a
|
||||
* C Runtime to print debug information. This
|
||||
* function will be accessed by console_init and
|
||||
* crash reporting.
|
||||
* In: x0 - console base address
|
||||
* w1 - Uart clock in Hz
|
||||
* w2 - Baud rate
|
||||
* Out: return 1 on success else 0 on error
|
||||
* Clobber list : x1, x2, x3
|
||||
* -----------------------------------------------
|
||||
*/
|
||||
func console_core_init
|
||||
/* Check the input base address */
|
||||
cbz x0, core_init_fail
|
||||
/* Check baud rate and uart clock for sanity */
|
||||
cbz w1, core_init_fail
|
||||
cbz w2, core_init_fail
|
||||
|
||||
/* Disable interrupt */
|
||||
str wzr, [x0, #UART_IER]
|
||||
|
||||
/* Force DTR and RTS to high */
|
||||
mov w3, #(UART_MCR_DTR | UART_MCR_RTS)
|
||||
str w3, [x0, #UART_MCR]
|
||||
|
||||
/* Check high speed */
|
||||
movz w3, #:abs_g1:115200
|
||||
movk w3, #:abs_g0_nc:115200
|
||||
cmp w2, w3
|
||||
b.hi 1f
|
||||
|
||||
/* Non high speed */
|
||||
lsl w2, w2, #4
|
||||
mov w3, wzr
|
||||
b 2f
|
||||
|
||||
/* High speed */
|
||||
1: lsl w2, w2, #2
|
||||
mov w3, #2
|
||||
|
||||
/* Set high speed UART register */
|
||||
2: str w3, [x0, #UART_HIGHSPEED]
|
||||
|
||||
/* Calculate divisor */
|
||||
udiv w3, w1, w2 /* divisor = uartclk / (quot * baudrate) */
|
||||
msub w1, w3, w2, w1 /* remainder = uartclk % (quot * baudrate) */
|
||||
lsr w2, w2, #1
|
||||
cmp w1, w2
|
||||
cinc w3, w3, hs
|
||||
|
||||
/* Set line configuration, access divisor latches */
|
||||
mov w1, #(UART_LCR_DLAB | UART_LCR_WLS_8)
|
||||
str w1, [x0, #UART_LCR]
|
||||
|
||||
/* Set the divisor */
|
||||
and w1, w3, #0xff
|
||||
str w1, [x0, #UART_DLL]
|
||||
lsr w1, w3, #8
|
||||
and w1, w1, #0xff
|
||||
str w1, [x0, #UART_DLH]
|
||||
|
||||
/* Hide the divisor latches */
|
||||
mov w1, #UART_LCR_WLS_8
|
||||
str w1, [x0, #UART_LCR]
|
||||
|
||||
/* Enable FIFOs, and clear receive and transmit */
|
||||
mov w1, #(UART_FCR_FIFO_EN | UART_FCR_CLEAR_RCVR | \
|
||||
UART_FCR_CLEAR_XMIT)
|
||||
str w1, [x0, #UART_FCR]
|
||||
|
||||
mov w0, #1
|
||||
ret
|
||||
core_init_fail:
|
||||
mov w0, wzr
|
||||
ret
|
||||
endfunc console_core_init
|
||||
|
||||
/* --------------------------------------------------------
|
||||
* int console_core_putc(int c, unsigned long base_addr)
|
||||
* Function to output a character over the console. It
|
||||
* returns the character printed on success or -1 on error.
|
||||
* In : w0 - character to be printed
|
||||
* x1 - console base address
|
||||
* Out : return -1 on error else return character.
|
||||
* Clobber list : x2
|
||||
* --------------------------------------------------------
|
||||
*/
|
||||
func console_core_putc
|
||||
/* Check the input parameter */
|
||||
cbz x1, putc_error
|
||||
/* Prepend '\r' to '\n' */
|
||||
cmp w0, #0xA
|
||||
b.ne 2f
|
||||
|
||||
/* Check if the transmit FIFO is full */
|
||||
1: ldr w2, [x1, #UART_LSR]
|
||||
and w2, w2, #UART_LSR_THRE
|
||||
cbz w2, 1b
|
||||
mov w2, #0xD
|
||||
str w2, [x1, #UART_THR]
|
||||
|
||||
/* Check if the transmit FIFO is full */
|
||||
2: ldr w2, [x1, #UART_LSR]
|
||||
and w2, w2, #UART_LSR_THRE
|
||||
cbz w2, 2b
|
||||
str w0, [x1, #UART_THR]
|
||||
ret
|
||||
putc_error:
|
||||
mov w0, #-1
|
||||
ret
|
||||
endfunc console_core_putc
|
||||
|
||||
/* ---------------------------------------------
|
||||
* int console_core_getc(unsigned long base_addr)
|
||||
* Function to get a character from the console.
|
||||
* It returns the character grabbed on success
|
||||
* or -1 on error.
|
||||
* In : x0 - console base address
|
||||
* Clobber list : x0, x1
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
func console_core_getc
|
||||
cbz x0, getc_error
|
||||
|
||||
/* Check if the receive FIFO is empty */
|
||||
1: ldr w1, [x0, #UART_LSR]
|
||||
tbz w1, #UART_LSR_DR, 1b
|
||||
ldr w0, [x0, #UART_RBR]
|
||||
ret
|
||||
getc_error:
|
||||
mov w0, #-1
|
||||
ret
|
||||
endfunc console_core_getc
|
||||
|
||||
/* ---------------------------------------------
|
||||
* void console_core_flush(uintptr_t base_addr)
|
||||
* Function to force a write of all buffered
|
||||
* data that hasn't been output.
|
||||
* In : x0 - console base address
|
||||
* Out : void.
|
||||
* Clobber list : x0, x1
|
||||
* ---------------------------------------------
|
||||
*/
|
||||
func console_core_flush
|
||||
/* Placeholder */
|
||||
ret
|
||||
endfunc console_core_flush
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2022, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <lib/mmio.h>
|
||||
#include <uart.h>
|
||||
|
||||
static struct mt_uart uart_save_addr[DRV_SUPPORT_UART_PORTS];
|
||||
|
||||
static const uint32_t uart_base_addr[DRV_SUPPORT_UART_PORTS] = {
|
||||
UART0_BASE,
|
||||
UART1_BASE
|
||||
};
|
||||
|
||||
void mt_uart_restore(void)
|
||||
{
|
||||
int uart_idx = UART_PORT0;
|
||||
struct mt_uart *uart;
|
||||
unsigned long base;
|
||||
|
||||
/* Must NOT print any debug log before UART restore */
|
||||
for (uart_idx = UART_PORT0; uart_idx < HW_SUPPORT_UART_PORTS;
|
||||
uart_idx++) {
|
||||
|
||||
uart = &uart_save_addr[uart_idx];
|
||||
base = uart->base;
|
||||
|
||||
mmio_write_32(UART_LCR(base), UART_LCR_MODE_B);
|
||||
mmio_write_32(UART_EFR(base), uart->registers.efr);
|
||||
mmio_write_32(UART_LCR(base), uart->registers.lcr);
|
||||
mmio_write_32(UART_FCR(base), uart->registers.fcr);
|
||||
|
||||
/* baudrate */
|
||||
mmio_write_32(UART_HIGHSPEED(base), uart->registers.highspeed);
|
||||
mmio_write_32(UART_FRACDIV_L(base), uart->registers.fracdiv_l);
|
||||
mmio_write_32(UART_FRACDIV_M(base), uart->registers.fracdiv_m);
|
||||
mmio_write_32(UART_LCR(base),
|
||||
uart->registers.lcr | UART_LCR_DLAB);
|
||||
mmio_write_32(UART_DLL(base), uart->registers.dll);
|
||||
mmio_write_32(UART_DLH(base), uart->registers.dlh);
|
||||
mmio_write_32(UART_LCR(base), uart->registers.lcr);
|
||||
mmio_write_32(UART_SAMPLE_COUNT(base),
|
||||
uart->registers.sample_count);
|
||||
mmio_write_32(UART_SAMPLE_POINT(base),
|
||||
uart->registers.sample_point);
|
||||
mmio_write_32(UART_GUARD(base), uart->registers.guard);
|
||||
|
||||
/* flow control */
|
||||
mmio_write_32(UART_ESCAPE_EN(base), uart->registers.escape_en);
|
||||
mmio_write_32(UART_MCR(base), uart->registers.mcr);
|
||||
mmio_write_32(UART_IER(base), uart->registers.ier);
|
||||
mmio_write_32(UART_SCR(base), uart->registers.scr);
|
||||
}
|
||||
}
|
||||
|
||||
void mt_uart_save(void)
|
||||
{
|
||||
int uart_idx = UART_PORT0;
|
||||
struct mt_uart *uart;
|
||||
unsigned long base;
|
||||
|
||||
for (uart_idx = UART_PORT0; uart_idx < HW_SUPPORT_UART_PORTS;
|
||||
uart_idx++) {
|
||||
|
||||
uart_save_addr[uart_idx].base = uart_base_addr[uart_idx];
|
||||
base = uart_base_addr[uart_idx];
|
||||
uart = &uart_save_addr[uart_idx];
|
||||
uart->registers.lcr = mmio_read_32(UART_LCR(base));
|
||||
|
||||
mmio_write_32(UART_LCR(base), UART_LCR_MODE_B);
|
||||
uart->registers.efr = mmio_read_32(UART_EFR(base));
|
||||
mmio_write_32(UART_LCR(base), uart->registers.lcr);
|
||||
uart->registers.fcr = mmio_read_32(UART_FCR_RD(base));
|
||||
|
||||
/* baudrate */
|
||||
uart->registers.highspeed = mmio_read_32(UART_HIGHSPEED(base));
|
||||
uart->registers.fracdiv_l = mmio_read_32(UART_FRACDIV_L(base));
|
||||
uart->registers.fracdiv_m = mmio_read_32(UART_FRACDIV_M(base));
|
||||
mmio_write_32(UART_LCR(base),
|
||||
uart->registers.lcr | UART_LCR_DLAB);
|
||||
uart->registers.dll = mmio_read_32(UART_DLL(base));
|
||||
uart->registers.dlh = mmio_read_32(UART_DLH(base));
|
||||
mmio_write_32(UART_LCR(base), uart->registers.lcr);
|
||||
uart->registers.sample_count = mmio_read_32(
|
||||
UART_SAMPLE_COUNT(base));
|
||||
uart->registers.sample_point = mmio_read_32(
|
||||
UART_SAMPLE_POINT(base));
|
||||
uart->registers.guard = mmio_read_32(UART_GUARD(base));
|
||||
|
||||
/* flow control */
|
||||
uart->registers.escape_en = mmio_read_32(UART_ESCAPE_EN(base));
|
||||
uart->registers.mcr = mmio_read_32(UART_MCR(base));
|
||||
uart->registers.ier = mmio_read_32(UART_IER(base));
|
||||
uart->registers.scr = mmio_read_32(UART_SCR(base));
|
||||
}
|
||||
}
|
||||
|
||||
void mt_console_uart_cg(int on)
|
||||
{
|
||||
if (on == 1) {
|
||||
mmio_write_32(UART_CLOCK_GATE_CLR, UART0_CLOCK_GATE_BIT);
|
||||
} else {
|
||||
mmio_write_32(UART_CLOCK_GATE_SET, UART0_CLOCK_GATE_BIT);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t mt_console_uart_cg_status(void)
|
||||
{
|
||||
return mmio_read_32(UART_CLOCK_GATE_STA) & UART0_CLOCK_GATE_BIT;
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2022, MediaTek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef UART_H
|
||||
#define UART_H
|
||||
|
||||
#include <platform_def.h>
|
||||
|
||||
/* UART HW information */
|
||||
#define HW_SUPPORT_UART_PORTS 2
|
||||
#define DRV_SUPPORT_UART_PORTS 2
|
||||
|
||||
/* console UART clock cg */
|
||||
#define UART_CLOCK_GATE_SET (INFRACFG_AO_BASE + 0x80)
|
||||
#define UART_CLOCK_GATE_CLR (INFRACFG_AO_BASE + 0x84)
|
||||
#define UART_CLOCK_GATE_STA (INFRACFG_AO_BASE + 0x90)
|
||||
#define UART0_CLOCK_GATE_BIT (1U<<22)
|
||||
#define UART1_CLOCK_GATE_BIT (1U<<23)
|
||||
|
||||
/* UART registers */
|
||||
#define UART_RBR(_baseaddr) (_baseaddr + 0x0)
|
||||
#define UART_THR(_baseaddr) (_baseaddr + 0x0)
|
||||
#define UART_IER(_baseaddr) (_baseaddr + 0x4)
|
||||
#define UART_IIR(_baseaddr) (_baseaddr + 0x8)
|
||||
#define UART_FCR(_baseaddr) (_baseaddr + 0x8)
|
||||
#define UART_LCR(_baseaddr) (_baseaddr + 0xc)
|
||||
#define UART_MCR(_baseaddr) (_baseaddr + 0x10)
|
||||
#define UART_LSR(_baseaddr) (_baseaddr + 0x14)
|
||||
#define UART_MSR(_baseaddr) (_baseaddr + 0x18)
|
||||
#define UART_SCR(_baseaddr) (_baseaddr + 0x1c)
|
||||
#define UART_DLL(_baseaddr) (_baseaddr + 0x0)
|
||||
#define UART_DLH(_baseaddr) (_baseaddr + 0x4)
|
||||
#define UART_EFR(_baseaddr) (_baseaddr + 0x8)
|
||||
#define UART_XON1(_baseaddr) (_baseaddr + 0x10)
|
||||
#define UART_XON2(_baseaddr) (_baseaddr + 0x14)
|
||||
#define UART_XOFF1(_baseaddr) (_baseaddr + 0x18)
|
||||
#define UART_XOFF2(_baseaddr) (_baseaddr + 0x1c)
|
||||
#define UART_AUTOBAUD(_baseaddr) (_baseaddr + 0x20)
|
||||
#define UART_HIGHSPEED(_baseaddr) (_baseaddr + 0x24)
|
||||
#define UART_SAMPLE_COUNT(_baseaddr) (_baseaddr + 0x28)
|
||||
#define UART_SAMPLE_POINT(_baseaddr) (_baseaddr + 0x2c)
|
||||
#define UART_AUTOBAUD_REG(_baseaddr) (_baseaddr + 0x30)
|
||||
#define UART_RATE_FIX_REG(_baseaddr) (_baseaddr + 0x34)
|
||||
#define UART_AUTO_BAUDSAMPLE(_baseaddr) (_baseaddr + 0x38)
|
||||
#define UART_GUARD(_baseaddr) (_baseaddr + 0x3c)
|
||||
#define UART_ESCAPE_DAT(_baseaddr) (_baseaddr + 0x40)
|
||||
#define UART_ESCAPE_EN(_baseaddr) (_baseaddr + 0x44)
|
||||
#define UART_SLEEP_EN(_baseaddr) (_baseaddr + 0x48)
|
||||
#define UART_DMA_EN(_baseaddr) (_baseaddr + 0x4c)
|
||||
#define UART_RXTRI_AD(_baseaddr) (_baseaddr + 0x50)
|
||||
#define UART_FRACDIV_L(_baseaddr) (_baseaddr + 0x54)
|
||||
#define UART_FRACDIV_M(_baseaddr) (_baseaddr + 0x58)
|
||||
#define UART_FCR_RD(_baseaddr) (_baseaddr + 0x5C)
|
||||
#define UART_USB_RX_SEL(_baseaddr) (_baseaddr + 0xB0)
|
||||
#define UART_SLEEP_REQ(_baseaddr) (_baseaddr + 0xB4)
|
||||
#define UART_SLEEP_ACK(_baseaddr) (_baseaddr + 0xB8)
|
||||
#define UART_SPM_SEL(_baseaddr) (_baseaddr + 0xBC)
|
||||
#define UART_LCR_DLAB 0x0080
|
||||
#define UART_LCR_MODE_B 0x00bf
|
||||
|
||||
enum uart_port_ID {
|
||||
UART_PORT0 = 0,
|
||||
UART_PORT1
|
||||
};
|
||||
|
||||
struct mt_uart_register {
|
||||
uint32_t dll;
|
||||
uint32_t dlh;
|
||||
uint32_t ier;
|
||||
uint32_t lcr;
|
||||
uint32_t mcr;
|
||||
uint32_t fcr;
|
||||
uint32_t lsr;
|
||||
uint32_t scr;
|
||||
uint32_t efr;
|
||||
uint32_t highspeed;
|
||||
uint32_t sample_count;
|
||||
uint32_t sample_point;
|
||||
uint32_t fracdiv_l;
|
||||
uint32_t fracdiv_m;
|
||||
uint32_t escape_en;
|
||||
uint32_t guard;
|
||||
uint32_t rx_sel;
|
||||
};
|
||||
|
||||
struct mt_uart {
|
||||
unsigned long base;
|
||||
struct mt_uart_register registers;
|
||||
};
|
||||
|
||||
/* external API */
|
||||
void mt_uart_save(void);
|
||||
void mt_uart_restore(void);
|
||||
void mt_console_uart_cg(int on);
|
||||
uint32_t mt_console_uart_cg_status(void);
|
||||
|
||||
#endif /* __UART_H__ */
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
#ifndef UART8250_H
|
||||
#define UART8250_H
|
||||
|
||||
/* UART register */
|
||||
#define UART_RBR 0x00 /* Receive buffer register */
|
||||
#define UART_DLL 0x00 /* Divisor latch lsb */
|
||||
#define UART_THR 0x00 /* Transmit holding register */
|
||||
#define UART_DLH 0x04 /* Divisor latch msb */
|
||||
#define UART_IER 0x04 /* Interrupt enable register */
|
||||
#define UART_FCR 0x08 /* FIFO control register */
|
||||
#define UART_LCR 0x0c /* Line control register */
|
||||
#define UART_MCR 0x10 /* Modem control register */
|
||||
#define UART_LSR 0x14 /* Line status register */
|
||||
#define UART_HIGHSPEED 0x24 /* High speed UART */
|
||||
|
||||
/* FCR */
|
||||
#define UART_FCR_FIFO_EN 0x01 /* enable FIFO */
|
||||
#define UART_FCR_CLEAR_RCVR 0x02 /* clear the RCVR FIFO */
|
||||
#define UART_FCR_CLEAR_XMIT 0x04 /* clear the XMIT FIFO */
|
||||
|
||||
/* LCR */
|
||||
#define UART_LCR_WLS_8 0x03 /* 8 bit character length */
|
||||
#define UART_LCR_DLAB 0x80 /* divisor latch access bit */
|
||||
|
||||
/* MCR */
|
||||
#define UART_MCR_DTR 0x01
|
||||
#define UART_MCR_RTS 0x02
|
||||
|
||||
/* LSR */
|
||||
#define UART_LSR_DR 0x01 /* Data ready */
|
||||
#define UART_LSR_THRE 0x20 /* Xmit holding register empty */
|
||||
|
||||
#endif /* UART8250_H */
|
||||
+118
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Mediatek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <arch.h>
|
||||
#include <asm_macros.S>
|
||||
#include <assert_macros.S>
|
||||
#include <cpu_macros.S>
|
||||
#if CONFIG_MTK_MCUSYS
|
||||
#include <mcucfg.h>
|
||||
#endif
|
||||
#include <platform_def.h>
|
||||
/*
|
||||
* Declare as weak function so that can be
|
||||
* overwritten by platform helpers
|
||||
*/
|
||||
.weak platform_mem_init
|
||||
.weak plat_core_pos_by_mpidr
|
||||
.weak plat_my_core_pos
|
||||
.weak plat_mediatek_calc_core_pos
|
||||
.global plat_mpidr_by_core_pos
|
||||
.global plat_reset_handler
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* unsigned long plat_mpidr_by_core_pos(uint32_t cpuid)
|
||||
* This function calcuate mpidr by cpu pos if cpu
|
||||
* topology is linear.
|
||||
*
|
||||
* Clobbers: x0-x1
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
func plat_mpidr_by_core_pos
|
||||
lsl x0, x0, #MPIDR_AFF1_SHIFT
|
||||
mrs x1, mpidr_el1
|
||||
and x1, x1, #MPIDR_MT_MASK
|
||||
orr x0, x0, x1
|
||||
ret
|
||||
endfunc plat_mpidr_by_core_pos
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* unsigned int plat_my_core_pos(void)
|
||||
* This function uses the plat_arm_calc_core_pos()
|
||||
* definition to get the index of the calling CPU.
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
func plat_my_core_pos
|
||||
mrs x0, mpidr_el1
|
||||
b plat_mediatek_calc_core_pos
|
||||
endfunc plat_my_core_pos
|
||||
|
||||
/* -----------------------------------------------------
|
||||
* int plat_mediatek_calc_core_pos(u_register_t mpidr);
|
||||
*
|
||||
* In ARMv8.2, AFF2 is cluster id, AFF1 is core id and
|
||||
* AFF0 is thread id. There is only one cluster in ARMv8.2
|
||||
* and one thread in current implementation.
|
||||
*
|
||||
* With this function: CorePos = CoreID (AFF1)
|
||||
* we do it with x0 = (x0 >> 8) & 0xff
|
||||
* -----------------------------------------------------
|
||||
*/
|
||||
func plat_mediatek_calc_core_pos
|
||||
b plat_core_pos_by_mpidr
|
||||
endfunc plat_mediatek_calc_core_pos
|
||||
|
||||
/* ------------------------------------------------------
|
||||
* int32_t plat_core_pos_by_mpidr(u_register_t mpidr)
|
||||
*
|
||||
* This function implements a part of the critical
|
||||
* interface between the psci generic layer and the
|
||||
* platform that allows the former to query the platform
|
||||
* to convert an MPIDR to a unique linear index.
|
||||
*
|
||||
* Clobbers: x0-x1
|
||||
* ------------------------------------------------------
|
||||
*/
|
||||
func plat_core_pos_by_mpidr
|
||||
mov x1, #MPIDR_AFFLVL_MASK
|
||||
and x0, x1, x0, lsr #MPIDR_AFF1_SHIFT
|
||||
ret
|
||||
endfunc plat_core_pos_by_mpidr
|
||||
|
||||
/* --------------------------------------------------------
|
||||
* void platform_mem_init (void);
|
||||
*
|
||||
* Any memory init, relocation to be done before the
|
||||
* platform boots. Called very early in the boot process.
|
||||
* --------------------------------------------------------
|
||||
*/
|
||||
func platform_mem_init
|
||||
ret
|
||||
endfunc platform_mem_init
|
||||
|
||||
func plat_reset_handler
|
||||
#if CONFIG_MTK_MCUSYS
|
||||
mov x10, x30
|
||||
bl plat_my_core_pos
|
||||
mov x30, x10
|
||||
mov w1, #0x1
|
||||
lsl w1, w1, w0
|
||||
ldr x0, =CPC_MCUSYS_CPU_ON_SW_HINT_SET
|
||||
str w1, [x0]
|
||||
dsb sy
|
||||
#endif
|
||||
|
||||
#if CONFIG_MTK_ECC
|
||||
mov x10, x30
|
||||
/* enable sequence of ecc for cpus */
|
||||
bl disable_core_ecc
|
||||
bl ft_ecc_clear_per_core
|
||||
bl enable_core_ecc
|
||||
mov x30, x10
|
||||
#endif
|
||||
|
||||
ret
|
||||
endfunc plat_reset_handler
|
||||
@@ -0,0 +1,12 @@
|
||||
#
|
||||
# Copyright (c) 2022, MediaTek Inc. All rights reserved.
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-3-Clause
|
||||
#
|
||||
|
||||
LOCAL_DIR := $(call GET_LOCAL_DIR)
|
||||
|
||||
MODULE := helpers
|
||||
LOCAL_SRCS-y += $(LOCAL_DIR)/$(ARCH_VERSION)/arch_helpers.S
|
||||
|
||||
$(eval $(call MAKE_MODULE,$(MODULE),$(LOCAL_SRCS-y),$(MTK_BL)))
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Mediatek Inc. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef ARCH_DEF_H
|
||||
#define ARCH_DEF_H
|
||||
|
||||
/* Topology constants */
|
||||
#define PLAT_MAX_PWR_LVL (2)
|
||||
#define PLAT_MAX_RET_STATE (1)
|
||||
#define PLAT_MAX_OFF_STATE (2)
|
||||
|
||||
#define PLATFORM_SYSTEM_COUNT (1)
|
||||
#define PLATFORM_CLUSTER_COUNT (1)
|
||||
#define PLATFORM_CLUSTER0_CORE_COUNT (8)
|
||||
#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER0_CORE_COUNT)
|
||||
#define PLATFORM_MAX_CPUS_PER_CLUSTER (8)
|
||||
#define PLATFORM_NUM_AFFS (PLATFORM_SYSTEM_COUNT + \
|
||||
PLATFORM_CLUSTER_COUNT + \
|
||||
PLATFORM_CORE_COUNT)
|
||||
|
||||
/*******************************************************************************
|
||||
* Declarations and constants to access the mailboxes safely. Each mailbox is
|
||||
* aligned on the biggest cache line size in the platform. This is known only
|
||||
* to the platform as it might have a combination of integrated and external
|
||||
* caches. Such alignment ensures that two maiboxes do not sit on the same cache
|
||||
* line at any cache level. They could belong to different cpus/clusters &
|
||||
* get written while being protected by different locks causing corruption of
|
||||
* a valid mailbox address.
|
||||
******************************************************************************/
|
||||
/* Cachline size */
|
||||
#define CACHE_WRITEBACK_SHIFT (6)
|
||||
#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
|
||||
|
||||
#endif /* ARCH_DEF_H */
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user