Merge "feat(mediatek): add vcp driver support" into integration

This commit is contained in:
Olivier Deprez 2024-12-20 11:12:22 +01:00 committed by TrustedFirmware Code Review
commit 3951baa6a6
10 changed files with 484 additions and 1 deletions

View file

@ -0,0 +1,29 @@
/*
* Copyright (c) 2024, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef VCP_HELPER_H
#define VCP_HELPER_H
#define MTK_VCP_SRAM_SIZE (0x60000)
/* Export extern API */
uint32_t get_mmup_fw_size(void);
uint64_t get_mmup_l2tcm_offset(void);
/* SMC calls OPS */
enum mtk_tinysys_vcp_kernel_op {
MTK_TINYSYS_VCP_KERNEL_OP_RESET_SET = 0,
MTK_TINYSYS_VCP_KERNEL_OP_RESET_RELEASE,
MTK_TINYSYS_VCP_KERNEL_OP_COLD_BOOT_VCP,
MTK_TINYSYS_MMUP_KERNEL_OP_RESET_SET,
MTK_TINYSYS_MMUP_KERNEL_OP_RESET_RELEASE,
MTK_TINYSYS_MMUP_KERNEL_OP_SET_L2TCM_OFFSET,
MTK_TINYSYS_MMUP_KERNEL_OP_SET_FW_SIZE,
MTK_TINYSYS_MMUP_KERNEL_OP_COLD_BOOT_MMUP,
MTK_TINYSYS_VCP_KERNEL_OP_NUM,
};
#endif /* VCP_HELPER_H */

View file

@ -0,0 +1,104 @@
/*
* Copyright (c) 2024, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef VCP_REG_H
#define VCP_REG_H
#include <platform_def.h>
#define MTK_VCP_REG_BASE (IO_PHYS + 0x21800000)
#define MTK_VCP_REG_BANK_SIZE (0x1000)
/*******************************************************************************
* VCP power related setting
******************************************************************************/
#define VCP_POWER_STATUS (0xE60)
#define MMUP_PWR_STA_BIT (30)
#define MMUP_PWR_STA_EN ((uint32_t)(0x3))
/*******************************************************************************
* VCP registers
******************************************************************************/
/* cfgreg */
#define VCP_R_CFGREG (MTK_VCP_REG_BASE + 0x3d0000)
#define VCP_R_CORE0_SW_RSTN_CLR (VCP_R_CFGREG + 0x0000)
#define VCP_R_CORE0_SW_RSTN_SET (VCP_R_CFGREG + 0x0004)
#define VCP_R_CORE1_SW_RSTN_CLR (VCP_R_CFGREG + 0x0008)
#define VCP_R_CORE1_SW_RSTN_SET (VCP_R_CFGREG + 0x000c)
#define VCP_R_GIPC_IN_SET (VCP_R_CFGREG + 0x0028)
#define VCP_R_GIPC_IN_CLR (VCP_R_CFGREG + 0x002c)
#define B_GIPC3_SETCLR_1 BIT(13)
/* cfgreg_core0 */
#define VCP_R_CFGREG_CORE0 (MTK_VCP_REG_BASE + 0x20a000)
#define VCP_R_CORE0_STATUS (VCP_R_CFGREG_CORE0 + 0x0070)
#define CORE0_R_GPR5 (VCP_R_CFGREG_CORE0 + 0x0054)
#define VCP_GPR_C0_H0_REBOOT CORE0_R_GPR5
#define CORE0_R_GPR6 (VCP_R_CFGREG_CORE0 + 0x0058)
#define VCP_GPR_C0_H1_REBOOT CORE0_R_GPR6
#define VCP_CORE_RDY_TO_REBOOT (0x34)
#define VCP_CORE_REBOOT_OK BIT(0)
/* cfgreg_core1 */
#define VCP_R_CFGREG_CORE1 (MTK_VCP_REG_BASE + 0x20d000)
#define VCP_R_CORE1_STATUS (VCP_R_CFGREG_CORE1 + 0x0070)
#define CORE1_R_GPR5 (VCP_R_CFGREG_CORE1 + 0x0054)
#define VCP_GPR_CORE1_REBOOT CORE1_R_GPR5
/* sec */
#define VCP_R_SEC_CTRL (MTK_VCP_REG_BASE + 0x270000)
#define VCP_OFFSET_ENABLE_P BIT(13)
#define VCP_OFFSET_ENABLE_B BIT(12)
#define VCP_R_SEC_CTRL_2 (VCP_R_SEC_CTRL + 0x0004)
#define CORE0_SEC_BIT_SEL BIT(0)
#define CORE1_SEC_BIT_SEL BIT(8)
#define VCP_GPR0_CFGREG_SEC (VCP_R_SEC_CTRL + 0x0040)
#define VCP_GPR1_CFGREG_SEC (VCP_R_SEC_CTRL + 0x0044)
#define VCP_GPR2_CFGREG_SEC (VCP_R_SEC_CTRL + 0x0048)
#define VCP_GPR3_CFGREG_SEC (VCP_R_SEC_CTRL + 0x004C)
#define VCP_R_SEC_DOMAIN (VCP_R_SEC_CTRL + 0x0080)
#define VCP_DOMAIN_ID U(13)
#define VCP_DOMAIN_MASK U(0xF)
#define VCP_CORE0_TH0_PM_AXI_DOMAIN (0)
#define VCP_CORE0_TH0_DM_AXI_DOMAIN (4)
#define VCP_S_DMA0_DOMAIN (12)
#define VCP_HWCCF_DOMAIN (16)
#define VCP_CORE0_TH1_PM_AXI_DOMAIN (20)
#define VCP_CORE0_TH1_DM_AXI_DOMAIN (24)
#define VCP_DOMAIN_SET ((VCP_DOMAIN_ID << VCP_CORE0_TH0_PM_AXI_DOMAIN) | \
(VCP_DOMAIN_ID << VCP_CORE0_TH0_DM_AXI_DOMAIN) | \
(VCP_DOMAIN_ID << VCP_CORE0_TH1_PM_AXI_DOMAIN) | \
(VCP_DOMAIN_ID << VCP_CORE0_TH1_DM_AXI_DOMAIN) | \
(VCP_DOMAIN_ID << VCP_S_DMA0_DOMAIN))
#define VCP_R_SEC_DOMAIN_MMPC (VCP_R_SEC_CTRL + 0x0084)
#define VCP_CORE_MMPC_PM_AXI_DOMAIN (0)
#define VCP_CORE_MMPC_DM_AXI_DOMAIN (4)
#define VCP_DOMAIN_SET_MMPC ((VCP_DOMAIN_ID << VCP_CORE_MMPC_PM_AXI_DOMAIN) | \
(VCP_DOMAIN_ID << VCP_CORE_MMPC_DM_AXI_DOMAIN))
#define R_L2TCM_OFFSET_RANGE_0_LOW (VCP_R_SEC_CTRL + 0x00B0)
#define R_L2TCM_OFFSET_RANGE_0_HIGH (VCP_R_SEC_CTRL + 0x00B4)
#define R_L2TCM_OFFSET (VCP_R_SEC_CTRL + 0x00D0)
#define VCP_R_DYN_SECURE (VCP_R_SEC_CTRL + 0x01d0)
#define VCP_NS_I0 BIT(4)
#define VCP_NS_D0 BIT(6)
#define VCP_NS_SECURE_B_REGION_ENABLE (24)
#define RESET_NS_SECURE_B_REGION U(0xFF)
#define VCP_R_DYN_SECURE_TH1 (VCP_R_SEC_CTRL + 0x01d4)
#define VCP_NS_I1 BIT(5)
#define VCP_NS_D1 BIT(7)
#define VCP_R_S_DOM_EN0_31 (VCP_R_SEC_CTRL + 0x0200)
#define VCP_R_S_DOM_EN32_63 (VCP_R_SEC_CTRL + 0x0204)
#define VCP_R_NS_DOM_EN0_31 (VCP_R_SEC_CTRL + 0x0208)
#define VCP_R_NS_DOM_EN32_63 (VCP_R_SEC_CTRL + 0x020c)
/* IOMMU */
#define VCP_R_AXIOMMUEN_DEV_APC (VCP_R_SEC_CTRL + 0x0088)
#define VCP_R_CFG_DEVAPC_AO_BASE (MTK_VCP_REG_BASE + 0x2d0000)
#endif /* VCP_REG_H */

View file

@ -0,0 +1,13 @@
#
# Copyright (c) 2024, MediaTek Inc. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
LOCAL_DIR := $(call GET_LOCAL_DIR)
MODULE := vcp
SUB_RULES-y := $(LOCAL_DIR)/rv
$(eval $(call INCLUDE_MAKEFILE,$(SUB_RULES-y)))

View file

@ -0,0 +1,84 @@
/*
* Copyright (c) 2024, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <inttypes.h>
#include <common/debug.h>
#include <lib/mmio.h>
#include "mmup_common.h"
#include "vcp_helper.h"
#include "vcp_reg.h"
#define MODULE_TAG "[MMUP]"
bool mmup_smc_rstn_set(bool boot_ok)
{
if (mmio_read_32(VCP_GPR_CORE1_REBOOT) != 0 &&
mmio_read_32(VCP_R_CORE1_STATUS) != 0 &&
(mmio_read_32(VCP_R_GIPC_IN_SET) & B_GIPC3_SETCLR_1) == 0 &&
(mmio_read_32(VCP_R_GIPC_IN_CLR) & B_GIPC3_SETCLR_1) == 0 &&
mmio_read_32(VCP_GPR_CORE1_REBOOT) != VCP_CORE_RDY_TO_REBOOT) {
ERROR("%s: [%s] mmup reset set fail!GIPC 0x%x 0x%x REBOOT 0x%x\n",
MODULE_TAG, __func__, mmio_read_32(VCP_R_GIPC_IN_SET),
mmio_read_32(VCP_R_GIPC_IN_CLR),
mmio_read_32(VCP_GPR_CORE1_REBOOT));
return false;
}
mmio_write_32(VCP_R_CORE1_SW_RSTN_SET, BIT(0));
/* reset sec control */
mmio_write_32(VCP_R_SEC_CTRL_2, 0);
/* reset domain setting */
mmio_write_32(VCP_R_S_DOM_EN0_31, 0x0);
mmio_write_32(VCP_R_S_DOM_EN32_63, 0x0);
mmio_write_32(VCP_R_NS_DOM_EN0_31, 0x0);
mmio_write_32(VCP_R_NS_DOM_EN32_63, 0x0);
/* reset sec setting */
mmio_clrbits_32(VCP_R_DYN_SECURE,
RESET_NS_SECURE_B_REGION << VCP_NS_SECURE_B_REGION_ENABLE);
if (boot_ok)
mmio_write_32(VCP_GPR_CORE1_REBOOT, VCP_CORE_REBOOT_OK);
dsbsy();
return true;
}
bool mmup_smc_rstn_clr(void)
{
if ((mmio_read_32(VCP_R_CORE1_SW_RSTN_SET) & BIT(0)) == 1) {
ERROR("%s: [%s] mmup not reset set !\n", MODULE_TAG, __func__);
return false;
}
if ((get_mmup_fw_size() == 0) || get_mmup_l2tcm_offset() == 0) {
ERROR("%s: [%s] mmup no enough l2tcm to run !\n", MODULE_TAG, __func__);
return false;
}
mmio_write_32(VCP_R_SEC_DOMAIN_MMPC, VCP_DOMAIN_SET_MMPC);
/* enable IOVA Mode */
mmio_write_32(VCP_R_AXIOMMUEN_DEV_APC, BIT(0));
/* reset secure setting */
mmio_setbits_32(VCP_R_SEC_CTRL_2, CORE1_SEC_BIT_SEL);
/* l2tcm offset*/
mmio_setbits_32(VCP_R_SEC_CTRL, VCP_OFFSET_ENABLE_P | VCP_OFFSET_ENABLE_B);
mmio_write_32(R_L2TCM_OFFSET_RANGE_0_LOW, 0x0);
mmio_write_32(R_L2TCM_OFFSET_RANGE_0_HIGH, round_up(get_mmup_fw_size(), PAGE_SIZE));
mmio_write_32(R_L2TCM_OFFSET, get_mmup_l2tcm_offset());
/* start vcp-mmup */
mmio_write_32(VCP_R_CORE1_SW_RSTN_CLR, BIT(0));
dsbsy();
return true;
}

View file

@ -0,0 +1,13 @@
/*
* Copyright (c) 2024, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef MMUP_COMMON_H
#define MMUP_COMMON_H
bool mmup_smc_rstn_set(bool boot_ok);
bool mmup_smc_rstn_clr(void);
#endif /* MMUP_COMMON_H */

View file

@ -0,0 +1,16 @@
#
# Copyright (c) 2024, MediaTek Inc. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
LOCAL_DIR := $(call GET_LOCAL_DIR)
MODULE := vcp_rv_${MTK_SOC}
PLAT_INCLUDES += -I${MTK_PLAT}/drivers/vcp/${MTK_SOC}
LOCAL_SRCS-${CONFIG_MTK_TINYSYS_VCP} := ${LOCAL_DIR}/vcp_common.c
LOCAL_SRCS-${CONFIG_MTK_TINYSYS_VCP} += ${LOCAL_DIR}/mmup_common.c
$(eval $(call MAKE_MODULE,$(MODULE),$(LOCAL_SRCS-y),$(MTK_BL)))

View file

@ -0,0 +1,221 @@
/*
* Copyright (c) 2024, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <errno.h>
#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
#include <arch_helpers.h>
#include <common/debug.h>
#include <lib/mmio.h>
#include <lib/xlat_tables/xlat_tables_v2.h>
#include <smccc_helpers.h>
#include "mmup_common.h"
#include <mtk_mmap_pool.h>
#include <mtk_sip_svc.h>
#include "vcp_helper.h"
#include "vcp_reg.h"
#define MODULE_TAG "[VCP]"
static const mmap_region_t vcp_mmap[] MTK_MMAP_SECTION = {
MAP_REGION_FLAT(VCP_R_CFGREG, MTK_VCP_REG_BANK_SIZE,
MT_DEVICE | MT_RW | MT_SECURE),
MAP_REGION_FLAT(VCP_R_CFGREG_CORE0, MTK_VCP_REG_BANK_SIZE,
MT_DEVICE | MT_RW | MT_SECURE),
MAP_REGION_FLAT(VCP_R_CFGREG_CORE1, MTK_VCP_REG_BANK_SIZE,
MT_DEVICE | MT_RW | MT_SECURE),
MAP_REGION_FLAT(VCP_R_SEC_CTRL, MTK_VCP_REG_BANK_SIZE,
MT_DEVICE | MT_RW | MT_SECURE),
{0}
};
DECLARE_MTK_MMAP_REGIONS(vcp_mmap);
/* vcp-mmup l2tcm memory offset */
static uint64_t g_l2tcm_offset;
static uint32_t g_mmup_fw_size;
static bool get_vcp_pwr_status(void)
{
#if defined(SPM_BASE)
uint32_t spm_pwr_sta = mmio_read_32(SPM_BASE + VCP_POWER_STATUS);
if (!(spm_pwr_sta & (MMUP_PWR_STA_EN << MMUP_PWR_STA_BIT))) {
ERROR("%s: pwr_sta:%x, bit:%d disable\n", MODULE_TAG,
spm_pwr_sta, MMUP_PWR_STA_BIT);
return false;
}
#endif
return true;
}
uint32_t get_mmup_fw_size(void)
{
return g_mmup_fw_size;
}
uint64_t get_mmup_l2tcm_offset(void)
{
return g_l2tcm_offset;
}
static bool vcp_cold_boot_reset(void)
{
mmio_write_32(VCP_GPR2_CFGREG_SEC, 0);
mmio_write_32(VCP_GPR3_CFGREG_SEC, 0);
return true;
}
static bool mmup_cold_boot_reset(void)
{
mmio_write_32(VCP_GPR0_CFGREG_SEC, 0);
mmio_write_32(VCP_GPR1_CFGREG_SEC, 0);
return true;
}
static bool vcp_set_mmup_l2tcm_offset(uint64_t l2tcm_offset)
{
g_l2tcm_offset = l2tcm_offset;
if (g_l2tcm_offset > MTK_VCP_SRAM_SIZE) {
g_l2tcm_offset = 0;
return false;
}
return true;
}
static bool vcp_set_mmup_fw_size(uint64_t fw_size)
{
g_mmup_fw_size = fw_size;
if (g_mmup_fw_size > MTK_VCP_SRAM_SIZE - g_l2tcm_offset) {
g_mmup_fw_size = 0;
return false;
}
return true;
}
static bool vcp_smc_rstn_set(bool boot_ok)
{
if (mmio_read_32(VCP_GPR_C0_H0_REBOOT) != 0 &&
mmio_read_32(VCP_R_CORE0_STATUS) != 0 &&
(mmio_read_32(VCP_R_GIPC_IN_SET) & B_GIPC3_SETCLR_1) == 0 &&
(mmio_read_32(VCP_R_GIPC_IN_CLR) & B_GIPC3_SETCLR_1) == 0 &&
mmio_read_32(VCP_GPR_C0_H0_REBOOT) != VCP_CORE_RDY_TO_REBOOT &&
mmio_read_32(VCP_GPR_C0_H1_REBOOT) != VCP_CORE_RDY_TO_REBOOT) {
ERROR("%s: [%s] mmup reset set fail!GIPC 0x%x 0x%x REBOOT 0x%x 0x%x\n",
MODULE_TAG, __func__, mmio_read_32(VCP_R_GIPC_IN_SET),
mmio_read_32(VCP_R_GIPC_IN_CLR),
mmio_read_32(VCP_GPR_C0_H0_REBOOT),
mmio_read_32(VCP_GPR_C0_H1_REBOOT));
return false;
}
mmio_write_32(VCP_R_CORE0_SW_RSTN_SET, BIT(0));
/* reset sec control */
mmio_write_32(VCP_R_SEC_CTRL_2, 0);
/* reset domain setting */
mmio_write_32(VCP_R_S_DOM_EN0_31, 0x0);
mmio_write_32(VCP_R_S_DOM_EN32_63, 0x0);
mmio_write_32(VCP_R_NS_DOM_EN0_31, 0x0);
mmio_write_32(VCP_R_NS_DOM_EN32_63, 0x0);
/* reset sec setting */
mmio_clrbits_32(VCP_R_DYN_SECURE,
RESET_NS_SECURE_B_REGION << VCP_NS_SECURE_B_REGION_ENABLE);
if (boot_ok) {
mmio_write_32(VCP_GPR_C0_H0_REBOOT, VCP_CORE_REBOOT_OK);
mmio_write_32(VCP_GPR_C0_H1_REBOOT, VCP_CORE_REBOOT_OK);
}
dsbsy();
return true;
}
static bool vcp_smc_rstn_clr(void)
{
if ((mmio_read_32(VCP_R_CORE0_SW_RSTN_SET) & BIT(0)) == 1) {
ERROR("%s: [%s] mmup not reset set !\n", MODULE_TAG, __func__);
return false;
}
mmio_clrsetbits_32(VCP_R_SEC_DOMAIN,
~(VCP_DOMAIN_MASK << VCP_HWCCF_DOMAIN), VCP_DOMAIN_SET);
/* enable IOVA Mode */
mmio_write_32(VCP_R_AXIOMMUEN_DEV_APC, BIT(0));
/* reset secure setting */
mmio_setbits_32(VCP_R_SEC_CTRL_2, CORE0_SEC_BIT_SEL);
mmio_clrbits_32(VCP_R_DYN_SECURE, VCP_NS_I0 | VCP_NS_D0);
mmio_clrbits_32(VCP_R_DYN_SECURE_TH1, VCP_NS_I1 | VCP_NS_D1);
/* start vcp */
mmio_write_32(VCP_R_CORE0_SW_RSTN_CLR, BIT(0));
dsbsy();
return true;
}
static u_register_t tinysys_vcp_kernel_control(u_register_t arg0,
u_register_t arg1,
u_register_t arg2,
u_register_t arg3,
void *handle,
struct smccc_res *smccc_ret)
{
uint32_t request_ops;
uint64_t ret = MTK_SIP_E_SUCCESS;
if (!get_vcp_pwr_status())
return MTK_SIP_E_NOT_SUPPORTED;
request_ops = (uint32_t)arg0;
switch (request_ops) {
case MTK_TINYSYS_VCP_KERNEL_OP_RESET_SET:
ret = vcp_smc_rstn_set((bool)!!arg1);
break;
case MTK_TINYSYS_VCP_KERNEL_OP_RESET_RELEASE:
ret = vcp_smc_rstn_clr();
break;
case MTK_TINYSYS_VCP_KERNEL_OP_COLD_BOOT_VCP:
ret = vcp_cold_boot_reset();
break;
case MTK_TINYSYS_MMUP_KERNEL_OP_RESET_SET:
ret = mmup_smc_rstn_set((bool)!!arg1);
break;
case MTK_TINYSYS_MMUP_KERNEL_OP_RESET_RELEASE:
ret = mmup_smc_rstn_clr();
break;
case MTK_TINYSYS_MMUP_KERNEL_OP_SET_L2TCM_OFFSET:
ret = vcp_set_mmup_l2tcm_offset(arg1);
break;
case MTK_TINYSYS_MMUP_KERNEL_OP_SET_FW_SIZE:
ret = vcp_set_mmup_fw_size(arg1);
break;
case MTK_TINYSYS_MMUP_KERNEL_OP_COLD_BOOT_MMUP:
ret = mmup_cold_boot_reset();
break;
default:
ERROR("%s: %s, unknown request_ops = %x\n", MODULE_TAG, __func__, request_ops);
ret = MTK_SIP_E_INVALID_PARAM;
break;
}
return ret;
}
/* Register SiP SMC service */
DECLARE_SMC_HANDLER(MTK_SIP_KERNEL_VCP_CONTROL, tinysys_vcp_kernel_control);

View file

@ -17,7 +17,8 @@
_func(MTK_SIP_AUDIO_CONTROL, 0x517) \
_func(MTK_SIP_APUSYS_CONTROL, 0x51E) \
_func(MTK_SIP_DP_CONTROL, 0x523) \
_func(MTK_SIP_KERNEL_GIC_OP, 0x526)
_func(MTK_SIP_KERNEL_GIC_OP, 0x526) \
_func(MTK_SIP_KERNEL_VCP_CONTROL, 0x52C)
#define MTK_SIP_SMC_FROM_S_EL1_TABLE(_func) \
_func(MTK_SIP_TEE_MPU_PERM_SET, 0x031)

View file

@ -36,6 +36,7 @@ CONFIG_MTK_SMP_EN := n
CONFIG_MTK_CPU_SUSPEND_EN := y
CONFIG_MTK_SPM_VERSION := mt8196
CONFIG_MTK_SUPPORT_SYSTEM_SUSPEND := y
CONFIG_MTK_TINYSYS_VCP := y
CPU_PM_TINYSYS_SUPPORT := y
MTK_PUBEVENT_ENABLE := y

View file

@ -28,6 +28,7 @@ MODULES-y += $(MTK_PLAT)/lib/pm
MODULES-y += $(MTK_PLAT)/drivers/dp
MODULES-y += $(MTK_PLAT)/drivers/mcusys
MODULES-y += $(MTK_PLAT)/drivers/timer
MODULES-y += $(MTK_PLAT)/drivers/vcp
MODULES-y += $(MTK_PLAT)/helpers
MODULES-y += $(MTK_PLAT)/topology