soc/mediatek/mt8196: Add mtcmos init support

Add mtcmos init code and APIs for controlling power domain.

TEST=build pass and driver init ok
BUG=b:317009620

Signed-off-by: Guangjie Song <guangjie.song@mediatek.corp-partner.google.com>
Change-Id: I44f2bb10453377a8412e80ac0c100760ebfbaff9
Reviewed-on: https://review.coreboot.org/c/coreboot/+/84497
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Yu-Ping Wu <yupingso@google.com>
Reviewed-by: Yidi Lin <yidilin@google.com>
This commit is contained in:
Guangjie Song 2024-07-24 17:30:30 +08:00 committed by Yidi Lin
commit 27fa0595de
5 changed files with 839 additions and 1 deletions

View file

@ -16,6 +16,7 @@ bootblock-y += ../common/bootblock.c bootblock.c
bootblock-y += ../common/early_init.c
bootblock-y += ../common/lastbus_v2.c lastbus.c
bootblock-y += ../common/mmu_operations.c
bootblock-y += mtcmos.c
bootblock-$(CONFIG_PCI) += ../common/pcie.c pcie.c
bootblock-y += ../common/wdt.c ../common/wdt_req.c wdt.c

View file

@ -6,6 +6,7 @@
#include <soc/lastbus_v2.h>
#include <soc/mmu_operations.h>
#include <soc/pll.h>
#include <soc/spm_mtcmos.h>
#include <soc/wdt.h>
void bootblock_soc_init(void)
@ -15,6 +16,8 @@ void bootblock_soc_init(void)
lastbus_init();
mtk_wdt_init();
mt_pll_init();
mtcmos_init();
mt_pll_post_init();
mtcmos_post_init();
early_init_clear();
}

View file

@ -46,7 +46,7 @@ SECTIONS
DRAM_INIT_CODE(0x02000000, 600K)
#else
/* The beginning 4K of SRAM_L2C is reserved for BOOTROM until BOOTBLOCK is started. */
BOOTBLOCK(0x02001000, 78K)
BOOTBLOCK(0x02001000, 85K)
#endif
OVERLAP_DECOMPRESSOR_VERSTAGE_ROMSTAGE(0x02096000, 272K)
PRERAM_CBFS_CACHE(0x020DA000, 48K)

View file

@ -0,0 +1,61 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef SOC_MEDIATEK_MT8196_SPM_MTCMOS_H
#define SOC_MEDIATEK_MT8196_SPM_MTCMOS_H
#include <commonlib/list.h>
enum mtcmos_state {
MTCMOS_POWER_DOWN,
MTCMOS_POWER_ON,
};
enum mtcmos_id {
MTCMOS_ID_SSUSB_DP_PHY_P0,
MTCMOS_ID_SSUSB_P0,
MTCMOS_ID_SSUSB_P1,
MTCMOS_ID_SSUSB_P23,
MTCMOS_ID_SSUSB_PHY_P2,
MTCMOS_ID_UFS0_SHUTDOWN,
MTCMOS_ID_UFS0_PHY,
MTCMOS_ID_PEXTP_MAC0,
MTCMOS_ID_PEXTP_MAC1,
MTCMOS_ID_PEXTP_MAC2,
MTCMOS_ID_PEXTP_PHY0,
MTCMOS_ID_PEXTP_PHY1,
MTCMOS_ID_PEXTP_PHY2,
MTCMOS_ID_AUDIO,
MTCMOS_ID_ADSP_TOP_SHUTDOWN,
MTCMOS_ID_ADSP_INFRA,
MTCMOS_ID_ADSP_AO,
MTCMOS_ID_MM_PROC_SHUTDOWN,
MTCMOS_ID_SSRSYS,
MTCMOS_ID_DISP_VCORE,
MTCMOS_ID_DIS0_SHUTDOWN,
MTCMOS_ID_DIS1_SHUTDOWN,
MTCMOS_ID_OVL0_SHUTDOWN,
MTCMOS_ID_OVL1_SHUTDOWN,
MTCMOS_ID_DISP_EDPTX_SHUTDOWN,
MTCMOS_ID_DISP_DPTX_SHUTDOWN,
MTCMOS_ID_MM_INFRA0,
MTCMOS_ID_MM_INFRA1,
MTCMOS_ID_MM_INFRA_AO,
MTCMOS_ID_DSI_PHY0,
MTCMOS_ID_DSI_PHY1,
MTCMOS_ID_DSI_PHY2,
MTCMOS_ID_NUM,
};
struct mtcmos_cb {
int (*pre_on)(void);
int (*pre_off)(void);
int (*post_on)(void);
int (*post_off)(void);
};
int mtcmos_cb_register(enum mtcmos_id id, const struct mtcmos_cb *cb);
void mtcmos_ctrl(enum mtcmos_id id, enum mtcmos_state state);
void mtcmos_init(void);
void mtcmos_post_init(void);
#endif

View file

@ -0,0 +1,773 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* This file is created based on MTCMOS_SW_NOTE.xlsx
*/
#include <console/console.h>
#include <delay.h>
#include <soc/addressmap.h>
#include <soc/mtcmos.h>
#include <soc/pll.h>
#include <soc/spm_mtcmos.h>
#include <timer.h>
#define MTK_SCPD_CAPS(_scpd, _x) ((_scpd)->caps & (_x))
#define POWERON_CONFIG_EN ((void *)(SPM_BASE + 0x0000))
#define SPM_PROJECT_CODE 0xB16
#define SET_BUS_PROTECT 1
#define RELEASE_BUS_PROTECT 0
#define WAIT_VOTE_TIMEOUT 20000
#define SPM_PBUS_BUS_PROTECT_EN_SET ((void *)(SPM_PBUS_BASE + 0x00DC))
#define SPM_PBUS_BUS_PROTECT_EN_CLR ((void *)(SPM_PBUS_BASE + 0x00E0))
#define SPM_PBUS_BUS_PROTECT_RDY_STA ((void *)(SPM_PBUS_BASE + 0x0208))
#define SPM_PBUS_BUS_MSB_PROTECT_EN_SET ((void *)(SPM_PBUS_BASE + 0x00E8))
#define SPM_PBUS_BUS_MSB_PROTECT_EN_CLR ((void *)(SPM_PBUS_BASE + 0x00EC))
#define SPM_PBUS_BUS_MSB_PROTECT_RDY_STA ((void *)(SPM_PBUS_BASE + 0x020C))
#define MM_BUCK_ISO_CON_CLR ((void *)(MMPC_BASE + 0x00C8))
#define DISP_AO_PWR_CON ((void *)(MMPC_BASE + 0x00E8))
#define MMPC_BUS_PROTECT_EN_1_CLR ((void *)(MMPC_BASE + 0x0188))
#define MMVOTE_MTCMOS_0_SET ((void *)(MMVOTE_BASE + 0x0218))
#define MMVOTE_MTCMOS_0_CLR ((void *)(MMVOTE_BASE + 0x021C))
#define MMVOTE_MTCMOS_0_DONE ((void *)(MMVOTE_BASE + 0x141C))
#define MMVOTE_MTCMOS_0_PM_ACK ((void *)(MMVOTE_BASE + 0x5514))
#define MMVOTE_MTCMOS_1_SET ((void *)(MMVOTE_BASE + 0x0220))
#define MMVOTE_MTCMOS_1_CLR ((void *)(MMVOTE_BASE + 0x0224))
#define MMVOTE_MTCMOS_1_DONE ((void *)(MMVOTE_BASE + 0x142C))
#define MMVOTE_MTCMOS_1_PM_ACK ((void *)(MMVOTE_BASE + 0x5518))
#define MMINFRA_MTCMOS_1_SET ((void *)(MMVOTE_BASE + 0x43220))
#define MMINFRA_MTCMOS_1_CLR ((void *)(MMVOTE_BASE + 0x43224))
#define DISP_VDISP_AO_CONFIG_CG 0x3E800108
#define DISP_DPC_DISP0_MTCMOS_CFG 0x3E8F0500
#define DISP_DPC_DISP1_MTCMOS_CFG 0x3E8F0580
#define DISP_DPC_OVL0_MTCMOS_CFG 0x3E8F0600
#define DISP_DPC_OVL1_MTCMOS_CFG 0x3E8F0680
#define DISP_DPC_MML0_MTCMOS_CFG 0x3E8F0B00
#define DISP_DPC_MML1_MTCMOS_CFG 0x3E8F0700
#define DISP_DPC_EDP_MTCMOS_CFG 0x3E8F0C00
#define DISP_DPC_EPTX_MTCMOS_CFG 0x3E8F0D00
#define MMINFRA0_VOTE_BIT 1
#define MMINFRA1_VOTE_BIT 2
#define MMINFRA_AO_VOTE_BIT 3
#define DSI_PHY0_VOTE_BIT 7
#define DSI_PHY1_VOTE_BIT 8
#define DSI_PHY2_VOTE_BIT 9
#define DISP_VCORE_VOTE_BIT 24
#define DISP0_VOTE_BIT 25
#define DISP1_VOTE_BIT 26
#define OVL0_VOTE_BIT 27
#define OVL1_VOTE_BIT 28
#define DISP_EDPTX_VOTE_BIT 29
#define DISP_DPTX_VOTE_BIT 30
#define MTK_SCPD_SRAM_ISO BIT(0)
#define MTK_SCPD_SRAM_SLP BIT(2)
#define MTK_SCPD_RTFF_DELAY BIT(6)
#define MTK_SCPD_NO_SRAM BIT(8)
#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 SRAM_CKISO BIT(5)
#define SRAM_ISOINT_B BIT(6)
#define SRAM_PDN BIT(8)
#define SRAM_SLP BIT(9)
#define SRAM_PDN_ACK BIT(12)
#define SRAM_SLP_ACK BIT(13)
#define PWR_RTFF_SAVE BIT(24)
#define PWR_RTFF_SAVE_FLAG BIT(27)
#define PWR_ACK BIT(30)
#define PWR_ACK_2ND BIT(31)
#define ACK_DELAY_US 10
#define ACK_DELAY_TIMES 10000
#define ADSP_AO_PROT_STEP1_SHIFT 23
#define ADSP_INFRA_PROT_STEP1_SHIFT 22
#define ADSP_TOP_PROT_STEP1_SHIFT 21
#define AUDIO_PROT_STEP1_SHIFT 19
#define MM_PROC_PROT_STEP1_SHIFT 24
#define PEXTP_MAC0_PROT_STEP1_SHIFT 13
#define PEXTP_MAC1_PROT_STEP1_SHIFT 14
#define PEXTP_MAC2_PROT_STEP1_SHIFT 15
#define PEXTP_PHY0_PROT_STEP1_SHIFT 16
#define PEXTP_PHY1_PROT_STEP1_SHIFT 17
#define PEXTP_PHY2_PROT_STEP1_SHIFT 18
#define SSRSYS_PROT_STEP1_SHIFT 10
#define SSUSB_DP_PHY_P0_PROT_STEP1_SHIFT 6
#define SSUSB_P0_PROT_STEP1_SHIFT 7
#define SSUSB_P1_PROT_STEP1_SHIFT 8
#define SSUSB_P23_PROT_STEP1_SHIFT 9
#define SSUSB_PHY_P2_PROT_STEP1_SHIFT 10
#define UFS0_PHY_PROT_STEP1_SHIFT 12
#define UFS0_PROT_STEP1_SHIFT 11
struct mtcmos_bus_prot {
u32 *bp_en_set;
u32 *bp_en_clr;
u32 *bp_rdy;
u8 bit;
};
struct mtcmos_data {
const struct mtcmos_bus_prot *bp_table;
u32 *ctl_addr;
u32 caps;
u32 bp_num;
const struct mtcmos_cb *cb;
};
struct mtcmos_vote_data {
u32 *set_addr;
u32 *clr_addr;
u32 *done_addr;
u32 *ack_addr;
u8 vote_bit;
const struct mtcmos_cb *cb;
};
static const struct mtcmos_bus_prot ssusb_dp_phy_p0_bp[] = {
{ SPM_PBUS_BUS_PROTECT_EN_SET, SPM_PBUS_BUS_PROTECT_EN_CLR,
SPM_PBUS_BUS_PROTECT_RDY_STA, SSUSB_DP_PHY_P0_PROT_STEP1_SHIFT },
};
static const struct mtcmos_bus_prot ssusb_p0_bp[] = {
{ SPM_PBUS_BUS_PROTECT_EN_SET, SPM_PBUS_BUS_PROTECT_EN_CLR,
SPM_PBUS_BUS_PROTECT_RDY_STA, SSUSB_P0_PROT_STEP1_SHIFT },
};
static const struct mtcmos_bus_prot ssusb_p1_bp[] = {
{ SPM_PBUS_BUS_PROTECT_EN_SET, SPM_PBUS_BUS_PROTECT_EN_CLR,
SPM_PBUS_BUS_PROTECT_RDY_STA, SSUSB_P1_PROT_STEP1_SHIFT },
};
static const struct mtcmos_bus_prot ssusb_p23_bp[] = {
{ SPM_PBUS_BUS_PROTECT_EN_SET, SPM_PBUS_BUS_PROTECT_EN_CLR,
SPM_PBUS_BUS_PROTECT_RDY_STA, SSUSB_P23_PROT_STEP1_SHIFT },
};
static const struct mtcmos_bus_prot ssusb_phy_p2_bp[] = {
{ SPM_PBUS_BUS_PROTECT_EN_SET, SPM_PBUS_BUS_PROTECT_EN_CLR,
SPM_PBUS_BUS_PROTECT_RDY_STA, SSUSB_PHY_P2_PROT_STEP1_SHIFT },
};
static const struct mtcmos_bus_prot ufs0_bp[] = {
{ SPM_PBUS_BUS_PROTECT_EN_SET, SPM_PBUS_BUS_PROTECT_EN_CLR,
SPM_PBUS_BUS_PROTECT_RDY_STA, UFS0_PROT_STEP1_SHIFT },
};
static const struct mtcmos_bus_prot ufs0_phy_bp[] = {
{ SPM_PBUS_BUS_PROTECT_EN_SET, SPM_PBUS_BUS_PROTECT_EN_CLR,
SPM_PBUS_BUS_PROTECT_RDY_STA, UFS0_PHY_PROT_STEP1_SHIFT },
};
static const struct mtcmos_bus_prot pextp_mac0_bp[] = {
{ SPM_PBUS_BUS_PROTECT_EN_SET, SPM_PBUS_BUS_PROTECT_EN_CLR,
SPM_PBUS_BUS_PROTECT_RDY_STA, PEXTP_MAC0_PROT_STEP1_SHIFT },
};
static const struct mtcmos_bus_prot pextp_mac1_bp[] = {
{ SPM_PBUS_BUS_PROTECT_EN_SET, SPM_PBUS_BUS_PROTECT_EN_CLR,
SPM_PBUS_BUS_PROTECT_RDY_STA, PEXTP_MAC1_PROT_STEP1_SHIFT },
};
static const struct mtcmos_bus_prot pextp_mac2_bp[] = {
{ SPM_PBUS_BUS_PROTECT_EN_SET, SPM_PBUS_BUS_PROTECT_EN_CLR,
SPM_PBUS_BUS_PROTECT_RDY_STA, PEXTP_MAC2_PROT_STEP1_SHIFT },
};
static const struct mtcmos_bus_prot pextp_phy0_bp[] = {
{ SPM_PBUS_BUS_PROTECT_EN_SET, SPM_PBUS_BUS_PROTECT_EN_CLR,
SPM_PBUS_BUS_PROTECT_RDY_STA, PEXTP_PHY0_PROT_STEP1_SHIFT },
};
static const struct mtcmos_bus_prot pextp_phy1_bp[] = {
{ SPM_PBUS_BUS_PROTECT_EN_SET, SPM_PBUS_BUS_PROTECT_EN_CLR,
SPM_PBUS_BUS_PROTECT_RDY_STA, PEXTP_PHY1_PROT_STEP1_SHIFT },
};
static const struct mtcmos_bus_prot pextp_phy2_bp[] = {
{ SPM_PBUS_BUS_PROTECT_EN_SET, SPM_PBUS_BUS_PROTECT_EN_CLR,
SPM_PBUS_BUS_PROTECT_RDY_STA, PEXTP_PHY2_PROT_STEP1_SHIFT },
};
static const struct mtcmos_bus_prot audio_bp[] = {
{ SPM_PBUS_BUS_PROTECT_EN_SET, SPM_PBUS_BUS_PROTECT_EN_CLR,
SPM_PBUS_BUS_PROTECT_RDY_STA, AUDIO_PROT_STEP1_SHIFT },
};
static const struct mtcmos_bus_prot adsp_top_bp[] = {
{ SPM_PBUS_BUS_PROTECT_EN_SET, SPM_PBUS_BUS_PROTECT_EN_CLR,
SPM_PBUS_BUS_PROTECT_RDY_STA, ADSP_TOP_PROT_STEP1_SHIFT },
};
static const struct mtcmos_bus_prot adsp_infra_bp[] = {
{ SPM_PBUS_BUS_PROTECT_EN_SET, SPM_PBUS_BUS_PROTECT_EN_CLR,
SPM_PBUS_BUS_PROTECT_RDY_STA, ADSP_INFRA_PROT_STEP1_SHIFT },
};
static const struct mtcmos_bus_prot adsp_ao_bp[] = {
{ SPM_PBUS_BUS_PROTECT_EN_SET, SPM_PBUS_BUS_PROTECT_EN_CLR,
SPM_PBUS_BUS_PROTECT_RDY_STA, ADSP_AO_PROT_STEP1_SHIFT },
};
static const struct mtcmos_bus_prot mm_proc_bp[] = {
{ SPM_PBUS_BUS_PROTECT_EN_SET, SPM_PBUS_BUS_PROTECT_EN_CLR,
SPM_PBUS_BUS_PROTECT_RDY_STA, MM_PROC_PROT_STEP1_SHIFT },
};
static const struct mtcmos_bus_prot ssrsys_bp[] = {
{ SPM_PBUS_BUS_MSB_PROTECT_EN_SET, SPM_PBUS_BUS_MSB_PROTECT_EN_CLR,
SPM_PBUS_BUS_MSB_PROTECT_RDY_STA, SSRSYS_PROT_STEP1_SHIFT },
};
static struct mtcmos_data mds[MTCMOS_ID_NUM] = {
[MTCMOS_ID_SSUSB_DP_PHY_P0] = {
ssusb_dp_phy_p0_bp, &mtk_spm_mtcmos->ssusb_dp_phy_p0_pwr_con,
MTK_SCPD_NO_SRAM, 1
},
[MTCMOS_ID_SSUSB_P0] = {
ssusb_p0_bp, &mtk_spm_mtcmos->ssusb_p0_pwr_con, 0, 1
},
[MTCMOS_ID_SSUSB_P1] = {
ssusb_p1_bp, &mtk_spm_mtcmos->ssusb_p1_pwr_con, 0, 1
},
[MTCMOS_ID_SSUSB_P23] = {
ssusb_p23_bp, &mtk_spm_mtcmos->ssusb_p23_pwr_con, MTK_SCPD_NO_SRAM, 1
},
[MTCMOS_ID_SSUSB_PHY_P2] = {
ssusb_phy_p2_bp, &mtk_spm_mtcmos->ssusb_phy_p2_pwr_con, 0, 1
},
[MTCMOS_ID_UFS0_SHUTDOWN] = {
ufs0_bp, &mtk_spm_mtcmos->ufs0_pwr_con, 0, 1
},
[MTCMOS_ID_UFS0_PHY] = {
ufs0_phy_bp, &mtk_spm_mtcmos->ufs0_phy_pwr_con, MTK_SCPD_NO_SRAM, 1
},
[MTCMOS_ID_PEXTP_MAC0] = {
pextp_mac0_bp, &mtk_spm_mtcmos->pextp_mac0_pwr_con, 0, 1
},
[MTCMOS_ID_PEXTP_MAC1] = {
pextp_mac1_bp, &mtk_spm_mtcmos->pextp_mac1_pwr_con, 0, 1
},
[MTCMOS_ID_PEXTP_MAC2] = {
pextp_mac2_bp, &mtk_spm_mtcmos->pextp_mac2_pwr_con, 0, 1
},
[MTCMOS_ID_PEXTP_PHY0] = {
pextp_phy0_bp, &mtk_spm_mtcmos->pextp_phy0_pwr_con, MTK_SCPD_NO_SRAM, 1
},
[MTCMOS_ID_PEXTP_PHY1] = {
pextp_phy1_bp, &mtk_spm_mtcmos->pextp_phy1_pwr_con, MTK_SCPD_NO_SRAM, 1
},
[MTCMOS_ID_PEXTP_PHY2] = {
pextp_phy2_bp, &mtk_spm_mtcmos->pextp_phy2_pwr_con, MTK_SCPD_NO_SRAM, 1
},
[MTCMOS_ID_AUDIO] = {
audio_bp, &mtk_spm_mtcmos->audio_pwr_con, 0, 1
},
[MTCMOS_ID_ADSP_TOP_SHUTDOWN] = {
adsp_top_bp, &mtk_spm_mtcmos->adsp_top_pwr_con, 0, 1
},
[MTCMOS_ID_ADSP_INFRA] = {
adsp_infra_bp, &mtk_spm_mtcmos->adsp_infra_pwr_con, MTK_SCPD_NO_SRAM, 1
},
[MTCMOS_ID_ADSP_AO] = {
adsp_ao_bp, &mtk_spm_mtcmos->adsp_ao_pwr_con, MTK_SCPD_NO_SRAM, 1
},
[MTCMOS_ID_MM_PROC_SHUTDOWN] = {
mm_proc_bp, &mtk_spm_mtcmos->mm_proc_pwr_con, 0, 1
},
[MTCMOS_ID_SSRSYS] = {
ssrsys_bp, &mtk_spm_mtcmos->ssrsys_pwr_con, 0, 1
},
};
static struct mtcmos_vote_data vote_mds[MTCMOS_ID_NUM] = {
[MTCMOS_ID_DISP_VCORE] = {
MMVOTE_MTCMOS_0_SET, MMVOTE_MTCMOS_0_CLR, MMVOTE_MTCMOS_0_DONE,
MMVOTE_MTCMOS_0_PM_ACK, DISP_VCORE_VOTE_BIT
},
[MTCMOS_ID_DIS0_SHUTDOWN] = {
MMVOTE_MTCMOS_0_SET, MMVOTE_MTCMOS_0_CLR, MMVOTE_MTCMOS_0_DONE,
MMVOTE_MTCMOS_0_PM_ACK, DISP0_VOTE_BIT
},
[MTCMOS_ID_DIS1_SHUTDOWN] = {
MMVOTE_MTCMOS_0_SET, MMVOTE_MTCMOS_0_CLR, MMVOTE_MTCMOS_0_DONE,
MMVOTE_MTCMOS_0_PM_ACK, DISP1_VOTE_BIT
},
[MTCMOS_ID_OVL0_SHUTDOWN] = {
MMVOTE_MTCMOS_0_SET, MMVOTE_MTCMOS_0_CLR, MMVOTE_MTCMOS_0_DONE,
MMVOTE_MTCMOS_0_PM_ACK, OVL0_VOTE_BIT
},
[MTCMOS_ID_OVL1_SHUTDOWN] = {
MMVOTE_MTCMOS_0_SET, MMVOTE_MTCMOS_0_CLR, MMVOTE_MTCMOS_0_DONE,
MMVOTE_MTCMOS_0_PM_ACK, OVL1_VOTE_BIT
},
[MTCMOS_ID_DISP_EDPTX_SHUTDOWN] = {
MMVOTE_MTCMOS_0_SET, MMVOTE_MTCMOS_0_CLR, MMVOTE_MTCMOS_0_DONE,
MMVOTE_MTCMOS_0_PM_ACK, DISP_EDPTX_VOTE_BIT
},
[MTCMOS_ID_DISP_DPTX_SHUTDOWN] = {
MMVOTE_MTCMOS_0_SET, MMVOTE_MTCMOS_0_CLR, MMVOTE_MTCMOS_0_DONE,
MMVOTE_MTCMOS_0_PM_ACK, DISP_DPTX_VOTE_BIT
},
[MTCMOS_ID_MM_INFRA0] = {
MMINFRA_MTCMOS_1_SET, MMINFRA_MTCMOS_1_CLR, MMVOTE_MTCMOS_1_DONE,
MMVOTE_MTCMOS_1_PM_ACK, MMINFRA0_VOTE_BIT
},
[MTCMOS_ID_MM_INFRA1] = {
MMINFRA_MTCMOS_1_SET, MMINFRA_MTCMOS_1_CLR, MMVOTE_MTCMOS_1_DONE,
MMVOTE_MTCMOS_1_PM_ACK, MMINFRA1_VOTE_BIT
},
[MTCMOS_ID_MM_INFRA_AO] = {
MMINFRA_MTCMOS_1_SET, MMINFRA_MTCMOS_1_CLR, MMVOTE_MTCMOS_1_DONE,
MMVOTE_MTCMOS_1_PM_ACK, MMINFRA_AO_VOTE_BIT
},
[MTCMOS_ID_DSI_PHY0] = {
MMVOTE_MTCMOS_1_SET, MMVOTE_MTCMOS_1_CLR, MMVOTE_MTCMOS_1_DONE,
MMVOTE_MTCMOS_1_PM_ACK, DSI_PHY0_VOTE_BIT
},
[MTCMOS_ID_DSI_PHY1] = {
MMVOTE_MTCMOS_1_SET, MMVOTE_MTCMOS_1_CLR, MMVOTE_MTCMOS_1_DONE,
MMVOTE_MTCMOS_1_PM_ACK, DSI_PHY1_VOTE_BIT
},
[MTCMOS_ID_DSI_PHY2] = {
MMVOTE_MTCMOS_1_SET, MMVOTE_MTCMOS_1_CLR, MMVOTE_MTCMOS_1_DONE,
MMVOTE_MTCMOS_1_PM_ACK, DSI_PHY2_VOTE_BIT
},
};
int mtcmos_cb_register(enum mtcmos_id id, const struct mtcmos_cb *cb)
{
if (id >= MTCMOS_ID_NUM) {
printk(BIOS_ERR, "id(%d) is invalid\n", id);
return -1;
}
if (id <= MTCMOS_ID_SSRSYS)
mds[id].cb = cb;
else
vote_mds[id].cb = cb;
return 0;
}
static int mtcmos_wait_for_state(u32 *reg, u32 mask, bool onoff)
{
u32 expect = onoff ? mask : 0;
if (!retry(ACK_DELAY_TIMES, (read32(reg) & mask) == expect, udelay(ACK_DELAY_US))) {
printk(BIOS_ERR, "%s(%p, %#x, %d) reg_val=%#x timeout\n",
__func__, reg, mask, onoff, read32(reg));
return -1;
}
return 0;
}
static int mtcmos_bus_prot_ctrl(const struct mtcmos_bus_prot *bp_table, bool set)
{
u32 *ctrl_addr;
u32 mask = BIT(bp_table->bit);
if (set)
ctrl_addr = bp_table->bp_en_set;
else
ctrl_addr = bp_table->bp_en_clr;
write32(ctrl_addr, mask);
if (set)
return mtcmos_wait_for_state(bp_table->bp_rdy, mask, set);
return 0;
}
static int mtcmos_setclr_bus_prot(const struct mtcmos_bus_prot *bp_table, u32 bp_num, bool set)
{
int step_idx;
int ret;
int i;
for (i = 0; i < bp_num; i++) {
step_idx = set ? i : bp_num - 1 - i;
ret = mtcmos_bus_prot_ctrl(&bp_table[step_idx], set);
if (ret) {
printk(BIOS_ERR, "mtcmos_bus_prot_ctrl set fail: %d\n", ret);
mtcmos_bus_prot_ctrl(&bp_table[step_idx], !set);
return ret;
}
}
return 0;
}
static int mtcmos_sram_on(enum mtcmos_id id, const struct mtcmos_data *md)
{
u32 *ctl_addr = md->ctl_addr;
int ret = 0;
if (MTK_SCPD_CAPS(md, MTK_SCPD_SRAM_SLP)) {
setbits32(ctl_addr, SRAM_SLP);
ret = mtcmos_wait_for_state(ctl_addr, SRAM_SLP_ACK, true);
} else {
clrbits32(ctl_addr, SRAM_PDN);
ret = mtcmos_wait_for_state(ctl_addr, SRAM_PDN_ACK, false);
}
if (ret)
return ret;
if (MTK_SCPD_CAPS(md, MTK_SCPD_SRAM_ISO)) {
setbits32(ctl_addr, SRAM_ISOINT_B);
udelay(1);
clrbits32(ctl_addr, SRAM_CKISO);
}
return 0;
}
static int mtcmos_sram_off(enum mtcmos_id id, const struct mtcmos_data *md)
{
u32 *ctl_addr = md->ctl_addr;
if (MTK_SCPD_CAPS(md, MTK_SCPD_SRAM_ISO)) {
setbits32(ctl_addr, SRAM_CKISO);
clrbits32(ctl_addr, SRAM_ISOINT_B);
udelay(1);
}
if (MTK_SCPD_CAPS(md, MTK_SCPD_SRAM_SLP)) {
clrbits32(ctl_addr, SRAM_SLP);
return mtcmos_wait_for_state(ctl_addr, SRAM_SLP_ACK, false);
} else {
setbits32(ctl_addr, SRAM_PDN);
return mtcmos_wait_for_state(ctl_addr, SRAM_PDN_ACK, true);
}
}
static int mtcmos_onoff(enum mtcmos_id id, enum mtcmos_state state)
{
const struct mtcmos_data *md = &mds[id];
u32 *ctl_addr = md->ctl_addr;
int ret = 0;
if (state == MTCMOS_POWER_DOWN) {
if (md->cb && md->cb->pre_off) {
ret = md->cb->pre_off();
if (ret) {
printk(BIOS_ERR, "mtcmos(%d) call pre_off fail(%d)\n", id, ret);
return ret;
}
}
ret = mtcmos_setclr_bus_prot(md->bp_table, md->bp_num, SET_BUS_PROTECT);
if (ret)
return ret;
if (!MTK_SCPD_CAPS(md, MTK_SCPD_NO_SRAM)) {
ret = mtcmos_sram_off(id, md);
if (ret)
return ret;
}
setbits32(ctl_addr, PWR_ISO);
setbits32(ctl_addr, PWR_CLK_DIS);
clrbits32(ctl_addr, PWR_RST_B);
clrbits32(ctl_addr, PWR_ON);
ret = mtcmos_wait_for_state(ctl_addr, PWR_ACK, state);
if (ret)
return ret;
clrbits32(ctl_addr, PWR_ON_2ND);
ret = mtcmos_wait_for_state(ctl_addr, PWR_ACK_2ND, state);
if (ret)
return ret;
if (md->cb && md->cb->post_off) {
ret = md->cb->post_off();
if (ret) {
printk(BIOS_ERR, "mtcmos(%d) call post_off fail(%d)\n", id, ret);
return ret;
}
}
} else {
if (md->cb && md->cb->pre_on) {
ret = md->cb->pre_on();
if (ret) {
printk(BIOS_ERR, "mtcmos(%d) call pre_on fail(%d)\n", id, ret);
return ret;
}
}
setbits32(ctl_addr, PWR_ON);
ret = mtcmos_wait_for_state(ctl_addr, PWR_ACK, state);
if (ret)
return ret;
udelay(50);
setbits32(ctl_addr, PWR_ON_2ND);
ret = mtcmos_wait_for_state(ctl_addr, PWR_ACK_2ND, state);
if (ret)
return ret;
clrbits32(ctl_addr, PWR_CLK_DIS);
clrbits32(ctl_addr, PWR_ISO);
if (MTK_SCPD_CAPS(md, MTK_SCPD_RTFF_DELAY))
udelay(10);
setbits32(ctl_addr, PWR_RST_B);
if (!MTK_SCPD_CAPS(md, MTK_SCPD_NO_SRAM)) {
ret = mtcmos_sram_on(id, md);
if (ret)
return ret;
}
ret = mtcmos_setclr_bus_prot(md->bp_table, md->bp_num, RELEASE_BUS_PROTECT);
if (ret)
return ret;
if (md->cb && md->cb->post_on) {
ret = md->cb->post_on();
if (ret) {
printk(BIOS_ERR, "mtcmos(%d) call post_on fail(%d)\n", id, ret);
return ret;
}
}
}
return 0;
}
static int mtcmos_vote_onoff(enum mtcmos_id id, enum mtcmos_state state)
{
const struct mtcmos_vote_data *md = &vote_mds[id];
u32 vote_bit = BIT(md->vote_bit);
int ret = 0;
if (state == MTCMOS_POWER_DOWN) {
if (md->cb && md->cb->pre_off) {
ret = md->cb->pre_off();
if (ret) {
printk(BIOS_ERR, "mtcmos(%d) call pre_off fail(%d)\n", id, ret);
return ret;
}
}
write32(md->clr_addr, vote_bit);
if (!wait_us(WAIT_VOTE_TIMEOUT, ((read32(md->done_addr) & vote_bit) != 0 &&
(read32(md->ack_addr) & vote_bit) == vote_bit))) {
printk(BIOS_ERR, "mtcmos_vote disable %d timeout\n", id);
return -1;
}
if (md->cb && md->cb->post_off) {
ret = md->cb->post_off();
if (ret) {
printk(BIOS_ERR, "mtcmos(%d) call post_off fail(%d)\n", id, ret);
return ret;
}
}
} else {
if (md->cb && md->cb->pre_on) {
ret = md->cb->pre_on();
if (ret) {
printk(BIOS_ERR, "mtcmos(%d) call pre_on fail(%d)\n", id, ret);
return ret;
}
}
write32(md->set_addr, vote_bit);
if (!wait_us(WAIT_VOTE_TIMEOUT, ((read32(md->done_addr) & vote_bit) != 0 &&
(read32(md->ack_addr) & vote_bit) == vote_bit))) {
printk(BIOS_ERR, "mtcmos_vote enable %d timeout\n", id);
return ret;
}
if (md->cb && md->cb->post_on) {
ret = md->cb->post_on();
if (ret) {
printk(BIOS_ERR, "mtcmos(%d) call post_on fail(%d)\n", id, ret);
return ret;
}
}
}
return 0;
}
static void mtcmos_spm_clr_rtff_flag(void)
{
clrbits32(&mtk_spm_mtcmos->conn_pwr_con, PWR_RTFF_SAVE_FLAG);
clrbits32(&mtk_spm_mtcmos->ssusb_dp_phy_p0_pwr_con, PWR_RTFF_SAVE_FLAG);
clrbits32(&mtk_spm_mtcmos->ssusb_p0_pwr_con, PWR_RTFF_SAVE_FLAG);
clrbits32(&mtk_spm_mtcmos->ssusb_p1_pwr_con, PWR_RTFF_SAVE_FLAG);
clrbits32(&mtk_spm_mtcmos->ssusb_p23_pwr_con, PWR_RTFF_SAVE_FLAG);
clrbits32(&mtk_spm_mtcmos->ssusb_phy_p2_pwr_con, PWR_RTFF_SAVE_FLAG);
clrbits32(&mtk_spm_mtcmos->ufs0_pwr_con, PWR_RTFF_SAVE_FLAG);
clrbits32(&mtk_spm_mtcmos->ufs0_phy_pwr_con, PWR_RTFF_SAVE_FLAG);
clrbits32(&mtk_spm_mtcmos->pextp_mac0_pwr_con, PWR_RTFF_SAVE_FLAG);
clrbits32(&mtk_spm_mtcmos->pextp_mac1_pwr_con, PWR_RTFF_SAVE_FLAG);
clrbits32(&mtk_spm_mtcmos->pextp_mac2_pwr_con, PWR_RTFF_SAVE_FLAG);
clrbits32(&mtk_spm_mtcmos->pextp_phy0_pwr_con, PWR_RTFF_SAVE_FLAG);
clrbits32(&mtk_spm_mtcmos->pextp_phy1_pwr_con, PWR_RTFF_SAVE_FLAG);
clrbits32(&mtk_spm_mtcmos->pextp_phy2_pwr_con, PWR_RTFF_SAVE_FLAG);
clrbits32(&mtk_spm_mtcmos->audio_pwr_con, PWR_RTFF_SAVE_FLAG);
clrbits32(&mtk_spm_mtcmos->adsp_infra_pwr_con, PWR_RTFF_SAVE_FLAG);
clrbits32(&mtk_spm_mtcmos->adsp_ao_pwr_con, PWR_RTFF_SAVE_FLAG);
clrbits32(&mtk_spm_mtcmos->mm_proc_pwr_con, PWR_RTFF_SAVE_FLAG);
clrbits32(&mtk_spm_mtcmos->ssrsys_pwr_con, PWR_RTFF_SAVE_FLAG);
clrbits32(&mtk_spm_mtcmos->spu_ise_pwr_con, PWR_RTFF_SAVE_FLAG);
clrbits32(&mtk_spm_mtcmos->spu_hwrot_pwr_con, PWR_RTFF_SAVE_FLAG);
clrbits32(&mtk_spm_mtcmos->hsgmii0_pwr_con, PWR_RTFF_SAVE_FLAG);
clrbits32(&mtk_spm_mtcmos->hsgmii1_pwr_con, PWR_RTFF_SAVE_FLAG);
}
static int mtcmos_disp_vcore_pre_on(void)
{
write32(MM_BUCK_ISO_CON_CLR, BIT(0));
write32(MM_BUCK_ISO_CON_CLR, BIT(1));
write32(MM_BUCK_ISO_CON_CLR, BIT(2));
write32(DISP_AO_PWR_CON, 0x1);
return 0;
}
static int mtcmos_disp_vcore_post_on(void)
{
write32(MMPC_BUS_PROTECT_EN_1_CLR, BIT(6) | BIT(7));
write32p(DISP_VDISP_AO_CONFIG_CG, 0xFFFFFFFF);
setbits32p(DISP_DPC_DISP0_MTCMOS_CFG, BIT(4));
setbits32p(DISP_DPC_DISP1_MTCMOS_CFG, BIT(4));
setbits32p(DISP_DPC_OVL0_MTCMOS_CFG, BIT(4));
setbits32p(DISP_DPC_OVL1_MTCMOS_CFG, BIT(4));
setbits32p(DISP_DPC_MML0_MTCMOS_CFG, BIT(4));
setbits32p(DISP_DPC_MML1_MTCMOS_CFG, BIT(4));
setbits32p(DISP_DPC_EDP_MTCMOS_CFG, BIT(4));
setbits32p(DISP_DPC_EPTX_MTCMOS_CFG, BIT(4));
return 0;
}
static struct mtcmos_cb disp_vcore_cb = {
.pre_on = mtcmos_disp_vcore_pre_on,
.post_on = mtcmos_disp_vcore_post_on,
};
void mtcmos_protect_display_bus(void)
{
/* empty implementation for user common flow */
}
void mtcmos_display_power_on(void)
{
mtcmos_ctrl(MTCMOS_ID_DIS0_SHUTDOWN, MTCMOS_POWER_ON);
mtcmos_ctrl(MTCMOS_ID_DIS1_SHUTDOWN, MTCMOS_POWER_ON);
mtcmos_ctrl(MTCMOS_ID_OVL0_SHUTDOWN, MTCMOS_POWER_ON);
mtcmos_ctrl(MTCMOS_ID_OVL1_SHUTDOWN, MTCMOS_POWER_ON);
mtcmos_ctrl(MTCMOS_ID_DISP_EDPTX_SHUTDOWN, MTCMOS_POWER_ON);
mtcmos_ctrl(MTCMOS_ID_DISP_DPTX_SHUTDOWN, MTCMOS_POWER_ON);
}
void mtcmos_ctrl(enum mtcmos_id id, enum mtcmos_state state)
{
int ret = 0;
if (id >= MTCMOS_ID_NUM) {
printk(BIOS_ERR, "id(%d) is invalid\n", id);
return;
}
if (id <= MTCMOS_ID_SSRSYS)
ret = mtcmos_onoff(id, state);
else
ret = mtcmos_vote_onoff(id, state);
if (ret)
printk(BIOS_ERR, "%s(%u, %u) fail, ret=%d\n", __func__, id, state, ret);
}
void mtcmos_init(void)
{
write32(POWERON_CONFIG_EN, (SPM_PROJECT_CODE << 16) | BIT(0));
mtcmos_spm_clr_rtff_flag();
mtcmos_ctrl(MTCMOS_ID_SSUSB_P0, MTCMOS_POWER_ON);
mtcmos_ctrl(MTCMOS_ID_SSUSB_DP_PHY_P0, MTCMOS_POWER_ON);
mtcmos_ctrl(MTCMOS_ID_SSUSB_P1, MTCMOS_POWER_ON);
mtcmos_ctrl(MTCMOS_ID_SSUSB_P23, MTCMOS_POWER_ON);
mtcmos_ctrl(MTCMOS_ID_SSUSB_PHY_P2, MTCMOS_POWER_ON);
mtcmos_ctrl(MTCMOS_ID_UFS0_SHUTDOWN, MTCMOS_POWER_ON);
mtcmos_ctrl(MTCMOS_ID_UFS0_PHY, MTCMOS_POWER_ON);
mtcmos_ctrl(MTCMOS_ID_PEXTP_MAC0, MTCMOS_POWER_ON);
mtcmos_ctrl(MTCMOS_ID_PEXTP_MAC1, MTCMOS_POWER_ON);
mtcmos_ctrl(MTCMOS_ID_PEXTP_MAC2, MTCMOS_POWER_ON);
mtcmos_ctrl(MTCMOS_ID_PEXTP_PHY0, MTCMOS_POWER_ON);
mtcmos_ctrl(MTCMOS_ID_PEXTP_PHY1, MTCMOS_POWER_ON);
mtcmos_ctrl(MTCMOS_ID_PEXTP_PHY2, MTCMOS_POWER_ON);
mtcmos_ctrl(MTCMOS_ID_ADSP_TOP_SHUTDOWN, MTCMOS_POWER_DOWN);
mtcmos_ctrl(MTCMOS_ID_AUDIO, MTCMOS_POWER_DOWN);
mtcmos_ctrl(MTCMOS_ID_ADSP_INFRA, MTCMOS_POWER_DOWN);
mtcmos_ctrl(MTCMOS_ID_ADSP_AO, MTCMOS_POWER_DOWN);
mtcmos_ctrl(MTCMOS_ID_ADSP_AO, MTCMOS_POWER_ON);
mtcmos_ctrl(MTCMOS_ID_ADSP_INFRA, MTCMOS_POWER_ON);
mtcmos_ctrl(MTCMOS_ID_AUDIO, MTCMOS_POWER_ON);
mtcmos_ctrl(MTCMOS_ID_ADSP_TOP_SHUTDOWN, MTCMOS_POWER_ON);
mtcmos_ctrl(MTCMOS_ID_MM_PROC_SHUTDOWN, MTCMOS_POWER_ON);
mtcmos_ctrl(MTCMOS_ID_SSRSYS, MTCMOS_POWER_ON);
}
void mtcmos_post_init(void)
{
if (mtcmos_cb_register(MTCMOS_ID_DISP_VCORE, &disp_vcore_cb))
printk(BIOS_ERR, "register disp_vcore failed\n");
mtcmos_ctrl(MTCMOS_ID_MM_INFRA_AO, MTCMOS_POWER_ON);
mtcmos_ctrl(MTCMOS_ID_MM_INFRA0, MTCMOS_POWER_ON);
mtcmos_ctrl(MTCMOS_ID_MM_INFRA1, MTCMOS_POWER_ON);
mtcmos_ctrl(MTCMOS_ID_DISP_VCORE, MTCMOS_POWER_ON);
write32(&mtk_disp->clk_cfg[0].clr, 0x00000007);
mtcmos_ctrl(MTCMOS_ID_DIS0_SHUTDOWN, MTCMOS_POWER_ON);
write32(&mtk_mmsys->clk_cfg[0].clr, 0xFFFFFFFF);
write32(&mtk_mmsys->clk_cfg[1].clr, 0x07FFFFFF);
mtcmos_ctrl(MTCMOS_ID_DIS1_SHUTDOWN, MTCMOS_POWER_ON);
write32(&mtk_mmsys1->clk_cfg[0].clr, 0xFFFFFFFF);
write32(&mtk_mmsys1->clk_cfg[1].clr, 0x1FF3FFFF);
mtcmos_ctrl(MTCMOS_ID_OVL0_SHUTDOWN, MTCMOS_POWER_ON);
write32(&mtk_ovlsys->clk_cfg[0].clr, 0xFFFFFFFF);
write32(&mtk_ovlsys->clk_cfg[1].clr, 0x7FFFFFFF);
mtcmos_ctrl(MTCMOS_ID_OVL1_SHUTDOWN, MTCMOS_POWER_ON);
write32(&mtk_ovlsys1->clk_cfg[0].clr, 0xFFFFFFFF);
write32(&mtk_ovlsys1->clk_cfg[1].clr, 0x7FFFFFFF);
mtcmos_ctrl(MTCMOS_ID_DISP_EDPTX_SHUTDOWN, MTCMOS_POWER_ON);
mtcmos_ctrl(MTCMOS_ID_DISP_DPTX_SHUTDOWN, MTCMOS_POWER_ON);
mtcmos_ctrl(MTCMOS_ID_DSI_PHY0, MTCMOS_POWER_ON);
mtcmos_ctrl(MTCMOS_ID_DSI_PHY1, MTCMOS_POWER_ON);
mtcmos_ctrl(MTCMOS_ID_DSI_PHY2, MTCMOS_POWER_ON);
/* vmm buck isolation off */
write32(MM_BUCK_ISO_CON_CLR, BIT(4));
write32(MM_BUCK_ISO_CON_CLR, BIT(5));
write32(MM_BUCK_ISO_CON_CLR, BIT(6));
}