feat(mt8196): add mtcmos driver

add mtcmos driver for ufs power control

Signed-off-by: Guangjie Song <guangjie.song@mediatek.com>
Change-Id: I3f63d5976906aaca91a71a147497e9345339774d
This commit is contained in:
Guangjie Song 2024-12-18 21:54:45 +08:00
parent e578702f71
commit 1f913a6e3a
6 changed files with 220 additions and 0 deletions
plat/mediatek

View file

@ -24,3 +24,4 @@ $(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))
$(eval $(call add_defined_option,CONFIG_MTK_SUPPORT_SYSTEM_SUSPEND))
$(eval $(call add_defined_option,CONFIG_MTK_MTCMOS))

View file

@ -0,0 +1,185 @@
/*
* Copyright (c) 2025, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdint.h>
#include <common/debug.h>
#include <drivers/delay_timer.h>
#include <lib/mmio.h>
#include <lib/spinlock.h>
#include <platform_def.h>
#include <mtcmos.h>
#define SPM_PROJECT_CODE 0xB16
#define PWR_RST_B BIT(0)
#define PWR_ISO BIT(1)
#define PWR_ON BIT(2)
#define PWR_ON_2ND BIT(3)
#define PWR_CLK_DIS BIT(4)
#define RTFF_SAVE BIT(24)
#define RTFF_NRESTORE BIT(25)
#define RTFF_CLK_DIS BIT(26)
#define RTFF_SAVE_FLAG BIT(27)
#define PWR_ACK BIT(30)
#define PWR_ACK_2ND BIT(31)
#define UFS0_SRAM_PDN BIT(8)
#define UFS0_SRAM_PDN_ACK BIT(12)
#define POWERON_CONFIG_EN (SPM_BASE + 0x0)
#define UFS0_PWR_CON (SPM_BASE + 0xE2C)
#define UFS0_PHY_PWR_CON (SPM_BASE + 0xE30)
#define SPM_BUS_PROTECT_EN_SET (SPM_BASE + 0x90DC)
#define SPM_BUS_PROTECT_EN_CLR (SPM_BASE + 0x90E0)
#define SPM_BUS_PROTECT_CG_EN_SET (SPM_BASE + 0x90F4)
#define SPM_BUS_PROTECT_CG_EN_CLR (SPM_BASE + 0x90F8)
#define SPM_BUS_PROTECT_RDY_STA (SPM_BASE + 0x9208)
#define UFS0_PROT_STEP1_MASK BIT(11)
#define UFS0_PHY_PROT_STEP1_MASK BIT(12)
enum {
RELEASE_BUS_PROTECT,
SET_BUS_PROTECT
};
#define MTCMOS_TIMEOUT_US 500
#define ETIMEDOUT 25
static spinlock_t mtcmos_ctrl_lock;
static int mtcmos_wait_for_state(uint32_t reg, uint32_t mask, bool is_set)
{
uint32_t retry = MTCMOS_TIMEOUT_US;
uint32_t expect = is_set ? mask : 0;
do {
if ((mmio_read_32(reg) & mask) == expect)
return 0;
udelay(1);
retry--;
} while (retry);
ERROR("%s(0x%x, 0x%x, %d) timeout, reg_val=0x%x\n",
__func__, reg, mask, is_set, mmio_read_32(reg));
return -ETIMEDOUT;
}
static int spm_mtcmos_ctrl_bus_prot(int state, uint32_t mask)
{
mmio_write_32(SPM_BUS_PROTECT_CG_EN_SET, mask);
if (state == SET_BUS_PROTECT) {
mmio_write_32(SPM_BUS_PROTECT_EN_SET, mask);
if (mtcmos_wait_for_state(SPM_BUS_PROTECT_RDY_STA, mask,
true))
return -ETIMEDOUT;
} else if (state == RELEASE_BUS_PROTECT) {
mmio_write_32(SPM_BUS_PROTECT_EN_CLR, mask);
}
mmio_write_32(SPM_BUS_PROTECT_CG_EN_CLR, mask);
return 0;
}
int spm_mtcmos_ctrl(enum mtcmos_state state, uintptr_t reg, uint32_t mask)
{
int ret = 0;
spin_lock(&mtcmos_ctrl_lock);
mmio_write_32(POWERON_CONFIG_EN, (SPM_PROJECT_CODE << 16) | BIT(0));
if (state == STA_POWER_DOWN) {
ret = spm_mtcmos_ctrl_bus_prot(SET_BUS_PROTECT, mask);
if (ret)
goto exit;
if (reg == UFS0_PWR_CON) {
mmio_setbits_32(reg, UFS0_SRAM_PDN);
ret = mtcmos_wait_for_state(reg, UFS0_SRAM_PDN_ACK,
true);
if (ret)
goto exit;
}
mmio_setbits_32(reg, RTFF_CLK_DIS);
mmio_setbits_32(reg, RTFF_SAVE);
mmio_clrbits_32(reg, RTFF_SAVE);
mmio_clrbits_32(reg, RTFF_CLK_DIS);
mmio_setbits_32(reg, RTFF_SAVE_FLAG);
mmio_setbits_32(reg, PWR_ISO);
mmio_setbits_32(reg, PWR_CLK_DIS);
mmio_clrbits_32(reg, PWR_RST_B);
mmio_clrbits_32(reg, PWR_ON);
ret = mtcmos_wait_for_state(reg, PWR_ACK, false);
if (ret)
goto exit;
mmio_clrbits_32(reg, PWR_ON_2ND);
ret = mtcmos_wait_for_state(reg, PWR_ACK_2ND, false);
if (ret)
goto exit;
} else if (state == STA_POWER_ON) {
mmio_setbits_32(reg, PWR_ON);
ret = mtcmos_wait_for_state(reg, PWR_ACK, true);
if (ret)
goto exit;
udelay(50);
mmio_setbits_32(reg, PWR_ON_2ND);
ret = mtcmos_wait_for_state(reg, PWR_ACK_2ND, true);
if (ret)
goto exit;
mmio_clrbits_32(reg, PWR_CLK_DIS);
mmio_clrbits_32(reg, PWR_ISO);
udelay(10);
mmio_setbits_32(reg, PWR_RST_B);
if ((mmio_read_32(reg) & RTFF_SAVE_FLAG) == RTFF_SAVE_FLAG) {
mmio_setbits_32(reg, RTFF_CLK_DIS);
mmio_clrbits_32(reg, RTFF_NRESTORE);
mmio_setbits_32(reg, RTFF_NRESTORE);
mmio_clrbits_32(reg, RTFF_CLK_DIS);
}
if (reg == UFS0_PWR_CON) {
mmio_clrbits_32(UFS0_PWR_CON, UFS0_SRAM_PDN);
ret = mtcmos_wait_for_state(UFS0_PWR_CON,
UFS0_SRAM_PDN_ACK,
false);
if (ret)
goto exit;
}
spm_mtcmos_ctrl_bus_prot(RELEASE_BUS_PROTECT, mask);
}
exit:
spin_unlock(&mtcmos_ctrl_lock);
return ret;
}
int spm_mtcmos_ctrl_ufs0(enum mtcmos_state state)
{
return spm_mtcmos_ctrl(state, UFS0_PWR_CON, UFS0_PROT_STEP1_MASK);
}
int spm_mtcmos_ctrl_ufs0_phy(enum mtcmos_state state)
{
return spm_mtcmos_ctrl(state, UFS0_PHY_PWR_CON,
UFS0_PHY_PROT_STEP1_MASK);
}

View file

@ -0,0 +1,18 @@
/*
* Copyright (c) 2025, MediaTek Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef PLAT_MEDIATEK_DRIVERS_MTCMOS_MT8196_MTCMOS_H_
#define PLAT_MEDIATEK_DRIVERS_MTCMOS_MT8196_MTCMOS_H_
enum mtcmos_state {
STA_POWER_DOWN,
STA_POWER_ON,
};
int spm_mtcmos_ctrl_ufs0(enum mtcmos_state state);
int spm_mtcmos_ctrl_ufs0_phy(enum mtcmos_state state);
#endif /* PLAT_MEDIATEK_DRIVERS_MTCMOS_MT8196_MTCMOS_H_ */

View file

@ -0,0 +1,13 @@
#
# Copyright (c) 2025, MediaTek Inc. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
LOCAL_DIR := $(call GET_LOCAL_DIR)
MODULE := mtcmos
LOCAL_SRCS-y := $(LOCAL_DIR)/${MTK_SOC}/mtcmos.c
PLAT_INCLUDES += -I${LOCAL_DIR}/${MTK_SOC}
$(eval $(call MAKE_MODULE,$(MODULE),$(LOCAL_SRCS-y),$(MTK_BL)))

View file

@ -42,6 +42,7 @@ CONFIG_MTK_CPU_PM_SUPPORT := y
CONFIG_MTK_CPU_PM_ARCH := 5_4
CONFIG_MTK_SMP_EN := n
CONFIG_MTK_CPU_SUSPEND_EN := y
CONFIG_MTK_MTCMOS := y
CONFIG_MTK_SPM_VERSION := mt8196
CONFIG_MTK_SUPPORT_SYSTEM_SUSPEND := y
CONFIG_MTK_TINYSYS_VCP := y

View file

@ -35,6 +35,8 @@ MODULES-y += $(MTK_PLAT)/drivers/vcp
MODULES-y += $(MTK_PLAT)/helpers
MODULES-y += $(MTK_PLAT)/topology
MODULES-$(CONFIG_MTK_MTCMOS) += $(MTK_PLAT)/drivers/mtcmos
ifneq ($(MTKLIB_PATH),)
LDFLAGS += -L $(dir $(MTKLIB_PATH))
LDLIBS += -l$(patsubst lib%.a,%,$(notdir $(MTKLIB_PATH)))