Yidi Lin has submitted this change. ( https://review.coreboot.org/c/coreboot/+/85126?usp=email )
Change subject: soc/mediatek/mt8196: Add PMIF and PMIC driver support ......................................................................
soc/mediatek/mt8196: Add PMIF and PMIC driver support
Implement PMIF driver for communication between SoC and PMIC. Develop SPMI driver for communication over the SPMI bus. Add necessary configurations and base addresses to support PMIF.
TEST=build pass, check boot log with: [INFO ] mtk_pmif_init: SPMI_MASTER_1, 0 [INFO ] mtk_pmif_init: SPMI_MASTER_0, 0 BUG=b:317009620
Change-Id: I232015f45735ee5278b09d0352410617a1565177 Signed-off-by: Hope Wang hope.wang@mediatek.corp-partner.google.com Reviewed-on: https://review.coreboot.org/c/coreboot/+/85126 Reviewed-by: Paul Menzel paulepanter@mailbox.org Tested-by: build bot (Jenkins) no-reply@coreboot.org Reviewed-by: Yidi Lin yidilin@google.com Reviewed-by: Yu-Ping Wu yupingso@google.com --- M src/soc/mediatek/mt8196/Makefile.mk M src/soc/mediatek/mt8196/include/soc/addressmap.h A src/soc/mediatek/mt8196/include/soc/pmif.h A src/soc/mediatek/mt8196/include/soc/spm.h A src/soc/mediatek/mt8196/pmif_clk.c A src/soc/mediatek/mt8196/pmif_init.c A src/soc/mediatek/mt8196/pmif_spmi.c 7 files changed, 1,729 insertions(+), 0 deletions(-)
Approvals: Yidi Lin: Looks good to me, approved build bot (Jenkins): Verified Yu-Ping Wu: Looks good to me, approved Paul Menzel: Looks good to me, but someone else must approve
diff --git a/src/soc/mediatek/mt8196/Makefile.mk b/src/soc/mediatek/mt8196/Makefile.mk index 0410129..f898775 100644 --- a/src/soc/mediatek/mt8196/Makefile.mk +++ b/src/soc/mediatek/mt8196/Makefile.mk @@ -30,6 +30,9 @@ romstage-y += ../common/memory.c memory.c romstage-y += ../common/memory_test.c romstage-y += ../common/mmu_operations.c ../common/mmu_cmops.c +romstage-y += ../common/pmif_clk.c pmif_clk.c +romstage-y += ../common/pmif.c pmif_init.c +romstage-y += pmif_spmi.c
ramstage-$(CONFIG_ARM64_USE_ARM_TRUSTED_FIRMWARE) += ../common/bl31.c ramstage-y += ../common/dpm_v2.c @@ -41,6 +44,9 @@ ramstage-y += ../common/mmu_operations.c ../common/mmu_cmops.c ramstage-$(CONFIG_PCI) += ../common/pcie.c pcie.c ramstage-y += soc.c +ramstage-y += ../common/pmif_clk.c pmif_clk.c +ramstage-y += ../common/pmif.c pmif_init.c +ramstage-y += pmif_spmi.c ramstage-y += ../common/usb.c usb.c
BL31_MAKEARGS += PLAT=mt8196 diff --git a/src/soc/mediatek/mt8196/include/soc/addressmap.h b/src/soc/mediatek/mt8196/include/soc/addressmap.h index e4a4107..b252eec 100644 --- a/src/soc/mediatek/mt8196/include/soc/addressmap.h +++ b/src/soc/mediatek/mt8196/include/soc/addressmap.h @@ -34,6 +34,8 @@ CKSYS_GP2_BASE = IO_PHYS + 0x0000C000, APMIXEDSYS_GP2_BASE = IO_PHYS + 0x0000C800, BCRM_INFRA_AO_BASE = IO_PHYS + 0x00022000, + PMIF_SPI_BASE = IO_PHYS + 0x00024000, + PMICSPI_MST_BASE = IO_PHYS + 0x00025000, BCRM_INFRA1_AO_BASE = IO_PHYS + 0x0002A000, GPIO_BASE = IO_PHYS + 0x0002D000, DBGSYS_AO_DEBUG_BASE = IO_PHYS + 0x00031000, diff --git a/src/soc/mediatek/mt8196/include/soc/pmif.h b/src/soc/mediatek/mt8196/include/soc/pmif.h new file mode 100644 index 0000000..a114dc6 --- /dev/null +++ b/src/soc/mediatek/mt8196/include/soc/pmif.h @@ -0,0 +1,147 @@ +/* SPDX-License-Identifier: GPL-2.0-only OR MIT */ + +#ifndef __MT8196_SOC_PMIF_H__ +#define __MT8196_SOC_PMIF_H__ + +#include <device/mmio.h> +#include <soc/pmif_common.h> +#include <types.h> + +/* indicate which number SW channel start, by project */ +#define PMIF_SPMI_SW_CHAN BIT(17) +#define PMIF_SPMI_INF 0x579BFF +#define PMIF_SPMI_INF_P 0xFFFFFF + +struct mtk_pmif_regs { + u32 init_done; + u32 reserved1[5]; + u32 inf_busy_sta; + u32 other_busy_sta_0; + u32 other_busy_sta_1; + u32 inf_en; + u32 other_inf_en; + u32 inf_cmd_per[4]; + u32 inf_max_bytecnt_per[4]; + u32 staupd_ctrl; + u32 reserved2[48]; + u32 int_gps_auxadc_cmd_addr; + u32 int_gps_auxadc_cmd; + u32 int_gps_auxadc_rdata_addr; + u32 reserved3[13]; + u32 arb_en; + u32 reserved4[34]; + u32 lat_cnter_ctrl; + u32 lat_cnter_en; + u32 lat_limit_loading; + u32 lat_limit[23]; + u32 reserved5[86]; + u32 crc_ctrl; + u32 crc_sta; + u32 sig_mode; + u32 pmic_sig_addr; + u32 pmic_sig_val; + u32 reserved6[2]; + u32 cmdissue_en; + u32 reserved7[10]; + u32 timer_ctrl; + u32 timer_sta_0; + u32 timer_sta_1; + u32 sleep_protection_ctrl; + u32 reserved8[5]; + u32 spi_mode_ctrl; + u32 reserved9[2]; + u32 pmic_eint_sta_addr; + u32 reserved10[2]; + u32 irq_event_en_0; + u32 irq_flag_raw_0; + u32 irq_flag_0; + u32 irq_clr_0; + u32 reserved11[244]; + u32 swinf_0_acc; + u32 swinf_0_wdata_31_0; + u32 swinf_0_wdata_63_32; + u32 reserved12[2]; + u32 swinf_0_rdata_31_0; + u32 swinf_0_rdata_63_32; + u32 reserved13[2]; + u32 swinf_0_vld_clr; + u32 swinf_0_sta; + u32 reserved14[5]; + u32 swinf_1_acc; + u32 swinf_1_wdata_31_0; + u32 swinf_1_wdata_63_32; + u32 reserved15[2]; + u32 swinf_1_rdata_31_0; + u32 swinf_1_rdata_63_32; + u32 reserved16[2]; + u32 swinf_1_vld_clr; + u32 swinf_1_sta; + u32 reserved17[5]; + u32 swinf_2_acc; + u32 swinf_2_wdata_31_0; + u32 swinf_2_wdata_63_32; + u32 reserved18[2]; + u32 swinf_2_rdata_31_0; + u32 swinf_2_rdata_63_32; + u32 reserved19[2]; + u32 swinf_2_vld_clr; + u32 swinf_2_sta; + u32 reserved20[5]; + u32 swinf_3_acc; + u32 swinf_3_wdata_31_0; + u32 swinf_3_wdata_63_32; + u32 reserved21[2]; + u32 swinf_3_rdata_31_0; + u32 swinf_3_rdata_63_32; + u32 reserved22[2]; + u32 swinf_3_vld_clr; + u32 swinf_3_sta; + u32 reserved23[133]; +}; + +check_member(mtk_pmif_regs, inf_busy_sta, 0x18); +check_member(mtk_pmif_regs, int_gps_auxadc_cmd_addr, 0x110); +check_member(mtk_pmif_regs, arb_en, 0x0150); +check_member(mtk_pmif_regs, lat_cnter_en, 0x1E0); +check_member(mtk_pmif_regs, crc_ctrl, 0x39C); +check_member(mtk_pmif_regs, cmdissue_en, 0x3B8); +check_member(mtk_pmif_regs, timer_ctrl, 0x3E4); +check_member(mtk_pmif_regs, spi_mode_ctrl, 0x408); +check_member(mtk_pmif_regs, pmic_eint_sta_addr, 0x414); +check_member(mtk_pmif_regs, irq_event_en_0, 0x420); +check_member(mtk_pmif_regs, swinf_0_acc, 0x800); + +#define PMIF_SPMI_AP_CHAN (PMIF_SPMI_BASE + 0x880) +#define PMIF_SPMI_AP_CHAN_P (PMIF_SPMI_P_BASE + 0x880) +#define PMIF_SPI_AP_CHAN (PMIF_SPI_BASE + 0x880) + +#define mtk_spmi_mst_p ((struct mtk_spmi_mst_reg *)SPMI_MST_P_BASE) + +struct mtk_scp_regs { + u32 reserved[27]; + u32 scp_clk_on_ctrl; +}; + +check_member(mtk_scp_regs, scp_clk_on_ctrl, 0x6C); + +#define mtk_scp ((struct mtk_scp_regs *)(SCP_CFG_BASE + 0x21000)) + +enum { + PMIF_ULPOSC_TARGET_FREQ_MHZ = 260, + PMIF_VLPCK_TARGET_FREQ_MHZ = 520, +}; + +/* calibation miss rate, unit: 0.1% */ +#define CAL_MIS_RATE 20 +#define FREQ_METER_VLP_OSC_CK 24 +#define FREQ_METER_VLP_AD_OSC_SYNC_CK 48 +#define FREQ_METER_VLP_AD_OSC_CK 59 +#define PMIF_USE_FIX_26M_CLK 0 + +/* calibation tolerance rate, unit: 0.1% */ +enum { + CAL_TOL_RATE = 40, + CAL_MAX_VAL = 0x1FF, +}; + +#endif /*__MT8196_SOC_PMIF_H__*/ diff --git a/src/soc/mediatek/mt8196/include/soc/spm.h b/src/soc/mediatek/mt8196/include/soc/spm.h new file mode 100644 index 0000000..b0f1264 --- /dev/null +++ b/src/soc/mediatek/mt8196/include/soc/spm.h @@ -0,0 +1,890 @@ +/* SPDX-License-Identifier: GPL-2.0-only OR MIT */ + +#ifndef SOC_MEDIATEK_MT8196_SPM_H +#define SOC_MEDIATEK_MT8196_SPM_H + +#include <device/mmio.h> +#include <soc/addressmap.h> +#include <soc/mtcmos.h> +#include <soc/spm_common.h> +#include <types.h> + +/* SPM READ/WRITE CFG */ +#define SPM_PROJECT_CODE 0xb16 +#define SPM_REGWR_CFG_KEY (SPM_PROJECT_CODE << 16) + +/* POWERON_CONFIG_EN (0x10006000+0x000) */ +#define BCLK_CG_EN_LSB BIT(0) + +#define SPM_ACK_CHK_3_SEL_HW_S1 0x00350098 +#define SPM_ACK_CHK_3_HW_S1_CNT 1 + +/* PCM_CON0 (0x10006000+0x018) */ +#define PCM_CK_EN_LSB BIT(2) +#define PCM_SW_RESET_LSB BIT(15) + +/* PCM_CON1 (0x1C001000+0x01C) */ +#define REG_SPM_APB_INTERNAL_EN_LSB BIT(3) +#define REG_PCM_TIMER_EN_LSB BIT(5) +#define REG_PCM_WDT_EN_LSB BIT(8) +#define REG_PCM_WDT_WAKE_LSB BIT(9) +#define REG_SSPM_APB_P2P_EN_LSB BIT(10) +#define REG_MCUPM_APB_P2P_EN_LSB BIT(11) +#define REG_RSV_APB_P2P_EN_LSB BIT(12) +#define RG_PCM_IRQ_MSK_LSB BIT(15) +#define PCM_CON1_PROJECT_CODE_LSB BIT(16) + +/* DDREN_DBC_CON (0x1C001000+0x888) */ +#define REG_DDREN_DBC_EN_LSB BIT(16) + +/* SPM_WAKEUP_EVENT_MASK (0x10006000+0x0D0) */ +#define SPM_WAKEUP_EVENT_MASK_BIT0 (1U << 0) +#define SPM_WAKEUP_EVENT_MASK_CSYSPWREQ_B (1U << 11) + +/* SPM_DVFS_MISC (0x10006000+0x4AC) */ +DEFINE_BIT(SPM_DVFS_FORCE_ENABLE_LSB, 2) +DEFINE_BIT(SPM_DVFSRC_ENABLE_LSB, 4) + +/* --- SPM Flag Define --- */ +#define SPM_FLAG_DISABLE_VCORE_DVS BIT(8) +#define SPM_FLAG_DISABLE_DDR_DFS BIT(9) +#define SPM_FLAG_DISABLE_EMI_DFS BIT(10) +#define SPM_FLAG_DISABLE_BUS_DFS BIT(11) +#define SPM_FLAG_RUN_COMMON_SCENARIO BIT(19) + +/* SPM_EVENT_COUNTER_CLEAR (0x1C001000+0x8B8) */ +#define REG_SPM_EVENT_COUNTER_CLR_LSB BIT(0) + +/* SYS_TIMER_CON (0x10006000+0x98C) */ +#define SYS_TIMER_START_EN_LSB BIT(0) + +/* MD32PCM_CFGREG_SW_RSTN (0x10006000+0xA00) */ +DEFINE_BIT(MD32PCM_CFGREG_SW_RSTN_RESET, 0) + +/************************************** + * Config and Parameter + **************************************/ +#define SPM_SYSTEM_BASE_OFFSET 0x40000000 +#define POWER_ON_VAL1_DEF 0x003ffe24 +#define SPM_WAKEUP_EVENT_MASK_DEF 0xefffffff +#define SPM_BUS_PROTECT_MASK_B_DEF 0xffffffff +#define SPM_BUS_PROTECT2_MASK_B_DEF 0xffffffff +#define MD32PCM_DMA0_CON_VAL 0x0003820e +#define MD32PCM_DMA0_START_VAL 0x00008000 +#define MD32PCM_CFGREG_SW_RSTN_RUN 0x1 +#define SPM_DVFS_LEVEL_DEF 0x00000001 +#define SPM_DVS_DFS_LEVEL_DEF 0x00010001 +#define SPM_RESOURCE_ACK_CON0_DEF 0xffffffff +#define SPM_RESOURCE_ACK_CON1_DEF 0xffffffff +#define SPM_RESOURCE_ACK_CON2_DEF 0xffffffff +#define SPM_RESOURCE_ACK_CON3_DEF 0xffffffff +#define ARMPLL_CLK_SEL_DEF 0x3ff +#define SPM_SYSCLK_SETTLE 0x60fe +#define SPM_INIT_DONE_US 20 + +/************************************** + * Definition and Declaration + **************************************/ +/* SPM_IRQ_MASK */ +#define ISRM_TWAM BIT(2) +#define ISRM_PCM_RETURN BIT(3) +#define ISRM_RET_IRQ0 BIT(8) +#define ISRM_RET_IRQ1 BIT(9) +#define ISRM_RET_IRQ2 BIT(10) +#define ISRM_RET_IRQ3 BIT(11) +#define ISRM_RET_IRQ4 BIT(12) +#define ISRM_RET_IRQ5 BIT(13) +#define ISRM_RET_IRQ6 BIT(14) +#define ISRM_RET_IRQ7 BIT(15) +#define ISRM_RET_IRQ8 BIT(16) +#define ISRM_RET_IRQ9 BIT(17) +#define ISRM_RET_IRQ_AUX ((ISRM_RET_IRQ9) | (ISRM_RET_IRQ8) | \ + (ISRM_RET_IRQ7) | (ISRM_RET_IRQ6) | \ + (ISRM_RET_IRQ5) | (ISRM_RET_IRQ4) | \ + (ISRM_RET_IRQ3) | (ISRM_RET_IRQ2) | \ + (ISRM_RET_IRQ1)) +#define ISRM_ALL_EXC_TWAM (ISRM_RET_IRQ_AUX) +#define ISRM_ALL (ISRM_ALL_EXC_TWAM | ISRM_TWAM) + +/* SPM_IRQ_STA */ +#define ISRS_TWAM BIT(2) +#define ISRS_PCM_RETURN BIT(3) +#define ISRC_TWAM ISRS_TWAM +#define ISRC_ALL_EXC_TWAM ISRS_PCM_RETURN +#define ISRC_ALL (ISRC_ALL_EXC_TWAM | ISRC_TWAM) + +/* SPM_SWINT */ +#define PCM_SW_INT_ALL 0x3ff + +/* MD32PCM_STA1 define */ +#define R12_CSYSPWREQ_B BIT(24) + +#define SPM_INTERNAL_STATUS_HW_S1 BIT(0) +#define SPM_ACK_CHK_3_CON_HW_MODE_TRIG 0x800 +#define SPM_ACK_CHK_3_CON_EN 0x110 +#define SPM_ACK_CHK_3_CON_CLR_ALL 0x2 +#define SPM_ACK_CHK_3_CON_RESULT 0x8000 + +struct pwr_ctrl { + /* for SPM */ + u32 pcm_flags; + u32 pcm_flags_cust; + u32 pcm_flags_cust_set; + u32 pcm_flags_cust_clr; + u32 pcm_flags1; + u32 pcm_flags1_cust; + u32 pcm_flags1_cust_set; + u32 pcm_flags1_cust_clr; + u32 timer_val; + u32 timer_val_cust; + u32 timer_val_ramp_en; + u32 timer_val_ramp_en_sec; + u32 wake_src; + u32 wake_src_cust; + u32 wakelock_timer_val; + u8 wdt_disable; + /* Auto-gen Start */ + + /* SPM_CLK_CON */ + u8 reg_spm_lock_infra_dcm_lsb; + u8 reg_cxo32k_remove_en_lsb; + u8 reg_spm_leave_suspend_merge_mask_lsb; + u8 reg_sysclk0_src_mask_b_lsb; + u8 reg_sysclk1_src_mask_b_lsb; + u8 reg_sysclk2_src_mask_b_lsb; + + /* SPM_AP_STANDBY_CON */ + u8 reg_wfi_op; + u8 reg_wfi_type; + u8 reg_mp0_cputop_idle_mask; + u8 reg_mp1_cputop_idle_mask; + u8 reg_mcusys_idle_mask; + u8 reg_csyspwrup_req_mask_lsb; + u8 reg_wfi_af_sel; + u8 reg_cpu_sleep_wfi; + + /* SPM_SRC_REQ */ + u8 reg_spm_adsp_mailbox_req; + u8 reg_spm_apsrc_req; + u8 reg_spm_ddren_req; + u8 reg_spm_dvfs_req; + u8 reg_spm_emi_req; + u8 reg_spm_f26m_req; + u8 reg_spm_infra_req; + u8 reg_spm_pmic_req; + u8 reg_spm_scp_mailbox_req; + u8 reg_spm_sspm_mailbox_req; + u8 reg_spm_sw_mailbox_req; + u8 reg_spm_vcore_req; + u8 reg_spm_vrf18_req; + u8 adsp_mailbox_state; + u8 apsrc_state; + u8 ddren_state; + u8 dvfs_state; + u8 emi_state; + u8 f26m_state; + u8 infra_state; + u8 pmic_state; + u8 scp_mailbox_state; + u8 sspm_mailbox_state; + u8 sw_mailbox_state; + u8 vcore_state; + u8 vrf18_state; + + /* SPM_SRC_MASK_0 */ + u8 reg_apu_apsrc_req_mask_b; + u8 reg_apu_ddren_req_mask_b; + u8 reg_apu_emi_req_mask_b; + u8 reg_apu_infra_req_mask_b; + u8 reg_apu_pmic_req_mask_b; + u8 reg_apu_srcclkena_mask_b; + u8 reg_apu_vrf18_req_mask_b; + u8 reg_audio_dsp_apsrc_req_mask_b; + u8 reg_audio_dsp_ddren_req_mask_b; + u8 reg_audio_dsp_emi_req_mask_b; + u8 reg_audio_dsp_infra_req_mask_b; + u8 reg_audio_dsp_pmic_req_mask_b; + u8 reg_audio_dsp_srcclkena_mask_b; + u8 reg_audio_dsp_vcore_req_mask_b; + u8 reg_audio_dsp_vrf18_req_mask_b; + u8 reg_cam_apsrc_req_mask_b; + u8 reg_cam_ddren_req_mask_b; + u8 reg_cam_emi_req_mask_b; + u8 reg_cam_infra_req_mask_b; + u8 reg_cam_pmic_req_mask_b; + u8 reg_cam_srcclkena_mask_b; + u8 reg_cam_vrf18_req_mask_b; + + /* SPM_SRC_MASK_1 */ + u32 reg_ccif_apsrc_req_mask_b; + u32 reg_ccif_emi_req_mask_b; + u8 reg_vlpcfg_rsv0_apsrc_req_mask_b; + u8 reg_vlpcfg_rsv0_ddren_req_mask_b; + u8 reg_vlpcfg_rsv0_emi_req_mask_b; + u8 reg_vlpcfg_rsv0_infra_req_mask_b; + u8 reg_vlpcfg_rsv0_pmic_req_mask_b; + u8 reg_vlpcfg_rsv0_srcclkena_mask_b; + u8 reg_vlpcfg_rsv0_vcore_req_mask_b; + u8 reg_vlpcfg_rsv0_vrf18_req_mask_b; + + /* SPM_SRC_MASK_2 */ + u32 reg_ccif_infra_req_mask_b; + u32 reg_ccif_pmic_req_mask_b; + u8 reg_vlpcfg_rsv1_apsrc_req_mask_b; + u8 reg_vlpcfg_rsv1_ddren_req_mask_b; + u8 reg_vlpcfg_rsv1_emi_req_mask_b; + u8 reg_vlpcfg_rsv1_infra_req_mask_b; + u8 reg_vlpcfg_rsv1_pmic_req_mask_b; + u8 reg_vlpcfg_rsv1_srcclkena_mask_b; + u8 reg_vlpcfg_rsv1_vcore_req_mask_b; + u8 reg_vlpcfg_rsv1_vrf18_req_mask_b; + + /* SPM_SRC_MASK_3 */ + u32 reg_ccif_srcclkena_mask_b; + u32 reg_ccif_vrf18_req_mask_b; + u8 reg_ccu_apsrc_req_mask_b; + u8 reg_ccu_ddren_req_mask_b; + u8 reg_ccu_emi_req_mask_b; + u8 reg_ccu_infra_req_mask_b; + u8 reg_ccu_pmic_req_mask_b; + u8 reg_ccu_srcclkena_mask_b; + u8 reg_ccu_vrf18_req_mask_b; + u8 reg_cg_check_apsrc_req_mask_b; + + /* SPM_SRC_MASK_4 */ + u8 reg_cg_check_ddren_req_mask_b; + u8 reg_cg_check_emi_req_mask_b; + u8 reg_cg_check_infra_req_mask_b; + u8 reg_cg_check_pmic_req_mask_b; + u8 reg_cg_check_srcclkena_mask_b; + u8 reg_cg_check_vcore_req_mask_b; + u8 reg_cg_check_vrf18_req_mask_b; + u8 reg_conn_apsrc_req_mask_b; + u8 reg_conn_ddren_req_mask_b; + u8 reg_conn_emi_req_mask_b; + u8 reg_conn_infra_req_mask_b; + u8 reg_conn_pmic_req_mask_b; + u8 reg_conn_srcclkena_mask_b; + u8 reg_conn_srcclkenb_mask_b; + u8 reg_conn_vcore_req_mask_b; + u8 reg_conn_vrf18_req_mask_b; + u8 reg_cpueb_apsrc_req_mask_b; + u8 reg_cpueb_ddren_req_mask_b; + u8 reg_cpueb_emi_req_mask_b; + u8 reg_cpueb_infra_req_mask_b; + u8 reg_cpueb_pmic_req_mask_b; + u8 reg_cpueb_srcclkena_mask_b; + u8 reg_cpueb_vrf18_req_mask_b; + u8 reg_disp0_apsrc_req_mask_b; + u8 reg_disp0_ddren_req_mask_b; + u8 reg_disp0_emi_req_mask_b; + u8 reg_disp0_infra_req_mask_b; + u8 reg_disp0_pmic_req_mask_b; + u8 reg_disp0_srcclkena_mask_b; + u8 reg_disp0_vrf18_req_mask_b; + u8 reg_disp1_apsrc_req_mask_b; + u8 reg_disp1_ddren_req_mask_b; + + /* SPM_SRC_MASK_5 */ + u8 reg_disp1_emi_req_mask_b; + u8 reg_disp1_infra_req_mask_b; + u8 reg_disp1_pmic_req_mask_b; + u8 reg_disp1_srcclkena_mask_b; + u8 reg_disp1_vrf18_req_mask_b; + u8 reg_dpm_apsrc_req_mask_b; + u8 reg_dpm_ddren_req_mask_b; + u8 reg_dpm_emi_req_mask_b; + u8 reg_dpm_infra_req_mask_b; + u8 reg_dpm_pmic_req_mask_b; + u8 reg_dpm_srcclkena_mask_b; + + /* SPM_SRC_MASK_6 */ + u8 reg_dpm_vcore_req_mask_b; + u8 reg_dpm_vrf18_req_mask_b; + u8 reg_dpmaif_apsrc_req_mask_b; + u8 reg_dpmaif_ddren_req_mask_b; + u8 reg_dpmaif_emi_req_mask_b; + u8 reg_dpmaif_infra_req_mask_b; + u8 reg_dpmaif_pmic_req_mask_b; + u8 reg_dpmaif_srcclkena_mask_b; + u8 reg_dpmaif_vrf18_req_mask_b; + u8 reg_dvfsrc_level_req_mask_b; + u8 reg_emisys_apsrc_req_mask_b; + u8 reg_emisys_ddren_req_mask_b; + u8 reg_emisys_emi_req_mask_b; + u8 reg_gce_apsrc_req_mask_b; + u8 reg_gce_ddren_req_mask_b; + u8 reg_gce_emi_req_mask_b; + u8 reg_gce_infra_req_mask_b; + u8 reg_gce_pmic_req_mask_b; + u8 reg_gce_srcclkena_mask_b; + u8 reg_gce_vrf18_req_mask_b; + u8 reg_gpueb_apsrc_req_mask_b; + u8 reg_gpueb_ddren_req_mask_b; + u8 reg_gpueb_emi_req_mask_b; + u8 reg_gpueb_infra_req_mask_b; + u8 reg_gpueb_pmic_req_mask_b; + u8 reg_gpueb_srcclkena_mask_b; + + /* SPM_SRC_MASK_7 */ + u8 reg_gpueb_vrf18_req_mask_b; + u8 reg_hwccf_apsrc_req_mask_b; + u8 reg_hwccf_ddren_req_mask_b; + u8 reg_hwccf_emi_req_mask_b; + u8 reg_hwccf_infra_req_mask_b; + u8 reg_hwccf_pmic_req_mask_b; + u8 reg_hwccf_srcclkena_mask_b; + u8 reg_hwccf_vcore_req_mask_b; + u8 reg_hwccf_vrf18_req_mask_b; + u8 reg_img_apsrc_req_mask_b; + u8 reg_img_ddren_req_mask_b; + u8 reg_img_emi_req_mask_b; + u8 reg_img_infra_req_mask_b; + u8 reg_img_pmic_req_mask_b; + u8 reg_img_srcclkena_mask_b; + u8 reg_img_vrf18_req_mask_b; + u8 reg_infrasys_apsrc_req_mask_b; + u8 reg_infrasys_ddren_req_mask_b; + u8 reg_infrasys_emi_req_mask_b; + u8 reg_infrasys_infra_req_mask_b; + u8 reg_infrasys_vrf18_req_mask_b; + u8 reg_ipic_infra_req_mask_b; + u8 reg_ipic_vrf18_req_mask_b; + u8 reg_mcu_apsrc_req_mask_b; + u8 reg_mcu_ddren_req_mask_b; + u8 reg_mcu_emi_req_mask_b; + u8 reg_mcu_infra_req_mask_b; + u8 reg_mcu_pmic_req_mask_b; + u8 reg_mcu_srcclkena_mask_b; + u8 reg_mcu_vrf18_req_mask_b; + u8 reg_md_apsrc_req_mask_b; + u8 reg_md_ddren_req_mask_b; + + /* SPM_SRC_MASK_8 */ + u8 reg_md_emi_req_mask_b; + u8 reg_md_infra_req_mask_b; + u8 reg_md_pmic_req_mask_b; + u8 reg_md_srcclkena_mask_b; + u8 reg_md_srcclkena1_mask_b; + u8 reg_md_vcore_req_mask_b; + u8 reg_md_vrf18_req_mask_b; + u8 reg_mm_proc_apsrc_req_mask_b; + u8 reg_mm_proc_ddren_req_mask_b; + u8 reg_mm_proc_emi_req_mask_b; + u8 reg_mm_proc_infra_req_mask_b; + u8 reg_mm_proc_pmic_req_mask_b; + u8 reg_mm_proc_srcclkena_mask_b; + u8 reg_mm_proc_vrf18_req_mask_b; + u8 reg_mml0_apsrc_req_mask_b; + u8 reg_mml0_ddren_req_mask_b; + u8 reg_mml0_emi_req_mask_b; + u8 reg_mml0_infra_req_mask_b; + u8 reg_mml0_pmic_req_mask_b; + u8 reg_mml0_srcclkena_mask_b; + u8 reg_mml0_vrf18_req_mask_b; + u8 reg_mml1_apsrc_req_mask_b; + u8 reg_mml1_ddren_req_mask_b; + u8 reg_mml1_emi_req_mask_b; + u8 reg_mml1_infra_req_mask_b; + u8 reg_mml1_pmic_req_mask_b; + u8 reg_mml1_srcclkena_mask_b; + u8 reg_mml1_vrf18_req_mask_b; + u8 reg_ovl0_apsrc_req_mask_b; + u8 reg_ovl0_ddren_req_mask_b; + u8 reg_ovl0_emi_req_mask_b; + u8 reg_ovl0_infra_req_mask_b; + + /* SPM_SRC_MASK_9 */ + u8 reg_ovl0_pmic_req_mask_b; + u8 reg_ovl0_srcclkena_mask_b; + u8 reg_ovl0_vrf18_req_mask_b; + u8 reg_ovl1_apsrc_req_mask_b; + u8 reg_ovl1_ddren_req_mask_b; + u8 reg_ovl1_emi_req_mask_b; + u8 reg_ovl1_infra_req_mask_b; + u8 reg_ovl1_pmic_req_mask_b; + u8 reg_ovl1_srcclkena_mask_b; + u8 reg_ovl1_vrf18_req_mask_b; + u8 reg_pcie0_apsrc_req_mask_b; + u8 reg_pcie0_ddren_req_mask_b; + u8 reg_pcie0_emi_req_mask_b; + u8 reg_pcie0_infra_req_mask_b; + u8 reg_pcie0_pmic_req_mask_b; + u8 reg_pcie0_srcclkena_mask_b; + u8 reg_pcie0_vcore_req_mask_b; + u8 reg_pcie0_vrf18_req_mask_b; + u8 reg_perisys_apsrc_req_mask_b; + u8 reg_perisys_ddren_req_mask_b; + u8 reg_perisys_emi_req_mask_b; + u8 reg_perisys_infra_req_mask_b; + u8 reg_perisys_pmic_req_mask_b; + u8 reg_perisys_srcclkena_mask_b; + u8 reg_perisys_vrf18_req_mask_b; + u8 reg_scp_apsrc_req_mask_b; + u8 reg_scp_ddren_req_mask_b; + u8 reg_scp_emi_req_mask_b; + u8 reg_scp_infra_req_mask_b; + u8 reg_scp_pmic_req_mask_b; + u8 reg_scp_srcclkena_mask_b; + u8 reg_scp_vcore_req_mask_b; + + /* SPM_SRC_MASK_10 */ + u8 reg_scp_vrf18_req_mask_b; + u8 reg_spu_hwrot_apsrc_req_mask_b; + u8 reg_spu_hwrot_ddren_req_mask_b; + u8 reg_spu_hwrot_emi_req_mask_b; + u8 reg_spu_hwrot_infra_req_mask_b; + u8 reg_spu_hwrot_pmic_req_mask_b; + u8 reg_spu_hwrot_srcclkena_mask_b; + u8 reg_spu_hwrot_vrf18_req_mask_b; + u8 reg_spu_ise_apsrc_req_mask_b; + u8 reg_spu_ise_ddren_req_mask_b; + u8 reg_spu_ise_emi_req_mask_b; + u8 reg_spu_ise_infra_req_mask_b; + u8 reg_spu_ise_pmic_req_mask_b; + u8 reg_spu_ise_srcclkena_mask_b; + u8 reg_spu_ise_vrf18_req_mask_b; + u8 reg_srcclkeni_infra_req_mask_b; + u8 reg_srcclkeni_pmic_req_mask_b; + u8 reg_srcclkeni_srcclkena_mask_b; + u8 reg_sspm_apsrc_req_mask_b; + u8 reg_sspm_ddren_req_mask_b; + u8 reg_sspm_emi_req_mask_b; + u8 reg_sspm_infra_req_mask_b; + u8 reg_sspm_pmic_req_mask_b; + u8 reg_sspm_srcclkena_mask_b; + u8 reg_sspm_vrf18_req_mask_b; + u8 reg_ssrsys_apsrc_req_mask_b; + u8 reg_ssrsys_ddren_req_mask_b; + u8 reg_ssrsys_emi_req_mask_b; + u8 reg_ssrsys_infra_req_mask_b; + + /* SPM_SRC_MASK_11 */ + u8 reg_ssrsys_pmic_req_mask_b; + u8 reg_ssrsys_srcclkena_mask_b; + u8 reg_ssrsys_vrf18_req_mask_b; + u8 reg_uart_hub_infra_req_mask_b; + u8 reg_uart_hub_pmic_req_mask_b; + u8 reg_uart_hub_srcclkena_mask_b; + u8 reg_uart_hub_vcore_req_mask_b; + u8 reg_uart_hub_vrf18_req_mask_b; + u8 reg_ufs_apsrc_req_mask_b; + u8 reg_ufs_ddren_req_mask_b; + u8 reg_ufs_emi_req_mask_b; + u8 reg_ufs_infra_req_mask_b; + u8 reg_ufs_pmic_req_mask_b; + u8 reg_ufs_srcclkena_mask_b; + u8 reg_ufs_vrf18_req_mask_b; + u8 reg_vdec_apsrc_req_mask_b; + u8 reg_vdec_ddren_req_mask_b; + u8 reg_vdec_emi_req_mask_b; + u8 reg_vdec_infra_req_mask_b; + u8 reg_vdec_pmic_req_mask_b; + u8 reg_vdec_srcclkena_mask_b; + u8 reg_vdec_vrf18_req_mask_b; + u8 reg_venc_apsrc_req_mask_b; + u8 reg_venc_ddren_req_mask_b; + u8 reg_venc_emi_req_mask_b; + u8 reg_venc_infra_req_mask_b; + u8 reg_venc_pmic_req_mask_b; + u8 reg_venc_srcclkena_mask_b; + u8 reg_venc_vrf18_req_mask_b; + + /* SPM_EVENT_CON_MISC */ + u8 reg_srcclken_fast_resp; + u8 reg_csyspwrup_ack_mask; + + /* SPM_WAKEUP_EVENT_MASK */ + u32 reg_wakeup_event_mask; + + /* SPM_WAKEUP_EVENT_EXT_MASK */ + u32 reg_ext_wakeup_event_mask; + + /* Auto-gen End */ +}; + +struct mtk_spm_regs { + u32 poweron_config_en; + u32 spm_power_on_val[4]; + u32 pcm_pwr_io_en; + u32 pcm_con0; + u32 pcm_con1; + u32 spm_sram_sleep_ctrl; + u32 spm_clk_con; + u32 spm_clk_settle; + u8 reserved0[20]; + u32 spm_sw_rst_con; + u32 spm_sw_rst_con_set; + u32 spm_sw_rst_con_clr; + u8 reserved1[4]; + u32 r_sec_read_mask; + u32 r_one_time_lock_l; + u32 r_one_time_lock_m; + u32 r_one_time_lock_h; + u8 reserved2[36]; + u32 sspm_clk_con; + u32 scp_clk_con; + u8 reserved3[4]; + u32 spm_swint; + u32 spm_swint_set; + u32 spm_swint_clr; + u8 reserved4[20]; + u32 spm_cpu_wakeup_event; + u32 spm_irq_mask; + u8 reserved5[72]; + u32 md32pcm_scu_ctrl[4]; + u32 md32pcm_scu_sta0; + u8 reserved6[20]; + u32 spm_irq_sta; + u8 reserved7[4]; + u32 md32pcm_wakeup_sta; + u32 md32pcm_event_sta; + u8 reserved8[8]; + u32 spm_wakeup_misc; + u8 reserved9[32]; + u32 spm_ck_sta; + u8 reserved10[40]; + u32 md32pcm_sta; + u32 md32pcm_pc; + u8 reserved11[104]; + u32 spm_ap_standby_con; + u32 cpu_wfi_en; + u32 cpu_wfi_en_set; + u32 cpu_wfi_en_clr; + u32 ext_int_wakeup_req; + u32 ext_int_wakeup_req_set; + u32 ext_int_wakeup_req_clr; + u32 mcusys_idle_sta; + u32 cpu_pwr_status; + u32 sw2spm_wakeup; + u32 sw2spm_wakeup_set; + u32 sw2spm_wakeup_clr; + u32 sw2spm_mailbox[4]; + u32 spm2sw_mailbox[4]; + u32 spm2mcupm_con; + u8 reserved12[12]; + u32 spm_mcusys_pwr_con; + u32 spm_cputop_pwr_con; + u32 spm_cpu_pwr_con[8]; + u32 spm_mcupm_spmc_con; + u8 reserved13[20]; + u32 spm_dpm_p2p_sta; + u32 spm_dpm_p2p_con; + u32 spm_dpm_intf_sta; + u32 spm_dpm_wb_con; + u32 pcm_apwdt_latch[20]; + u32 spm_pwrap_con; + u32 spm_pwrap_con_sta; + u32 spm_pmic_spmi_con; + u8 reserved14[4]; + u32 spm_pwrap_cmd[32]; + u32 dvfsrc_event_sta; + u32 spm_force_dvfs; + u32 spm_dvfs_sta; + u32 spm_dvs_dfs_level; + u32 spm_dvfs_level; + u32 spm_dvfs_opp; + u32 spm_ultra_req; + u32 spm_dvfs_con; + u32 spm_sramrc_con; + u32 spm_srclkenrc_con; + u32 spm_dpsw_con; + u32 spm_dpsw_vapu_iso_con; + u32 spm_dpsw_vmm_iso_con; + u32 spm_dpsw_vmd_iso_con; + u32 spm_dpsw_vmodem_iso_con; + u32 spm_dpsw_vcore_iso_con; + u8 reserved15[48]; + u32 ulposc_con; + u32 ap_mdsrc_req; + u32 spm2md_switch_ctrl; + u32 rc_spm_ctrl; + u32 spm2gpupm_con; + u32 spm2apu_con; + u32 spm2efuse_con; + u32 spm2dfd_con; + u32 rsv_pll_con; + u32 emi_slb_con; + u32 spm_suspend_flag_con; + u32 spm2pmsr_con; + u32 spm_topck_rtff_con; + u32 emi_shf_con; + u32 cirq_bypass_con; + u32 aoc_vcore_sram_con; + u32 spm2emi_pdn_ctrl; + u8 reserved16[28]; + u32 reg_module_sw_cg_ddren_req_mask[4]; + u32 reg_module_sw_cg_vrf18_req_mask[4]; + u32 reg_module_sw_cg_infra_req_mask[4]; + u32 reg_module_sw_cg_f26m_req_mask[4]; + u32 reg_module_sw_cg_vcore_req_mask[4]; + u32 reg_pwr_status_ddren_req_mask; + u32 reg_pwr_status_vrf18_req_mask; + u32 reg_pwr_status_infra_req_mask; + u32 reg_pwr_status_f26m_req_mask; + u32 reg_pwr_status_pmic_req_mask; + u32 reg_pwr_status_vcore_req_mask; + u32 reg_pwr_status_msb_ddren_req_mask; + u32 reg_pwr_status_msb_vrf18_req_mask; + u32 reg_pwr_status_msb_infra_req_mask; + u32 reg_pwr_status_msb_f26m_req_mask; + u32 reg_pwr_status_msb_pmic_req_mask; + u32 reg_pwr_status_msb_vcore_req_mask; + u32 reg_module_busy_ddren_req_mask; + u32 reg_module_busy_vrf18_req_mask; + u32 reg_module_busy_infra_req_mask; + u32 reg_module_busy_f26m_req_mask; + u32 reg_module_busy_pmic_req_mask; + u32 reg_module_busy_vcore_req_mask; + u8 reserved17[8]; + u32 sys_timer_con; + u32 sys_timer_value_l; + u32 sys_timer_value_h; + u32 sys_timer_start_l; + u32 sys_timer_start_h; + struct { + u32 latch_l; + u32 latch_h; + } sys_timer_latch[16]; + u32 pcm_timer_val; + u32 pcm_timer_out; + u32 spm_counter[3]; + u32 pcm_wdt_val; + u32 pcm_wdt_out; + u32 pcm_apwdt_latch_20[19]; + u8 reserved18[4]; + u32 spm_sw_flag_0; + u32 spm_sw_debug_0; + u32 spm_sw_flag_1; + u32 spm_sw_debug_1; + u32 spm_sw_rsv[9]; + u32 spm_bk_wake_event; + u32 spm_bk_vtcxo_dur; + u32 spm_bk_wake_misc; + u32 spm_bk_pcm_timer; + u8 reserved19[12]; + u32 spm_rsv_con_0; + u32 spm_rsv_con_1; + u32 spm_rsv_sta_0; + u32 spm_rsv_sta_1; + u32 spm_spare_con; + u32 spm_spare_con_set; + u32 spm_spare_con_clr; + u32 spm_cross_wake_m00_req; + u32 spm_cross_wake_m01_req; + u32 spm_cross_wake_m02_req; + u32 spm_cross_wake_m03_req; + u32 scp_vcore_level; + u32 spm_ddren_ack_sel_con; + u32 spm_sw_flag_2; + u32 spm_sw_debug_2; + u32 spm_dv_con_0; + u32 spm_dv_con_1; + u8 reserved20[8]; + u32 spm_sema_m[8]; + u32 spm2adsp_mailbox; + u32 adsp2spm_mailbox; + u32 spm2pmcu_mailbox[4]; + u32 pmcu2spm_mailbox[4]; + u32 spm2scp_mailbox; + u32 scp2spm_mailbox; + u32 scp_aov_bus_con; + u32 vcore_rtff_ctrl_mask; + u32 vcore_rtff_ctrl_mask_set; + u32 vcore_rtff_ctrl_mask_clr; + u32 spm_sram_srclkeno_mask; + u8 reserved21[256]; + u32 spm_wakeup_sta; + u32 spm_wakeup_ext_sta; + u32 spm_wakeup_event_mask; + u32 spm_wakeup_event_ext_mask; + u32 spm_wakeup_event_sens; + u32 spm_wakeup_event_clear; + u32 spm_src_req; + u32 spm_src_mask[12]; + u32 spm_req_sta[12]; + u32 spm_ipc_wakeup_req; + u32 ipc_wakeup_req_mask_sta; + u32 spm_event_con_misc; + u32 ddren_dbc_con; + u32 spm_resource_ack_con[2]; + u32 spm_resource_ack_mask[9]; + u32 spm_event_counter_clear; + u32 spm_vcore_event_count_sta; + u32 spm_pmic_event_count_sta; + u32 spm_srcclkena_event_count_sta; + u32 spm_infra_event_count_sta; + u32 spm_vrf18_event_count_sta; + u32 spm_emi_event_count_sta; + u32 spm_apsrc_event_count_sta; + u32 spm_ddren_event_count_sta; + u32 pcm_wdt_latch[39]; + u32 pcm_wdt_latch_spare[10]; + u32 dramc_gating_err_latch[6]; + u32 dramc_gating_err_latch_spare_0; + u32 spm_debug_con; + u32 spm_ack_chk_con_0; + u32 spm_ack_chk_sel_0; + u32 spm_ack_chk_timer_0; + u32 spm_ack_chk_sta_0; + u32 spm_ack_chk_con_1; + u32 spm_ack_chk_sel_1; + u32 spm_ack_chk_timer_1; + u32 spm_ack_chk_sta_1; + u32 spm_ack_chk_con_2; + u32 spm_ack_chk_sel_2; + u32 spm_ack_chk_timer_2; + u32 spm_ack_chk_sta_2; + u32 spm_ack_chk_con_3; + u32 spm_ack_chk_sel_3; + u32 spm_ack_chk_timer_3; + u32 spm_ack_chk_sta_3; + u32 md32pcm_cfgreg_sw_rstn; + u8 reserved22[508]; + u32 md32pcm_dma0_src; + u32 md32pcm_dma0_dst; + u32 md32pcm_dma0_wppt; + u32 md32pcm_dma0_wpto; + u32 md32pcm_dma0_count; + u32 md32pcm_dma0_con; + u32 md32pcm_dma0_start; + u8 reserved23[8]; + u32 md32pcm_dma0_rlct; + u8 reserved24[276]; + u32 md32pcm_intc_irq_raw_sta; + u8 reserved25[192]; + u32 md1_pwr_con; + u32 conn_pwr_con; + u32 ifr_pwr_con; + u32 peri_pwr_con; + u32 peri_usb0_pwr_con; + u32 ufs0_pwr_con; + u32 ufs0_phy_pwr_con; + u32 pextp_mac0_pwr_con; + u32 pextp_mac1_pwr_con; + u32 pextp_phy0_pwr_con; + u32 pextp_phy1_pwr_con; + u32 audio_pwr_con; + u32 adsp_core1_pwr_con; + u32 adsp_top_pwr_con; + u32 adsp_infra_pwr_con; + u32 adsp_ao_pwr_con; + u32 isp_traw_pwr_con; + u32 isp_dip1_pwr_con; + u32 isp_main_pwr_con; + u32 isp_vcore_pwr_con; + u32 vde0_pwr_con; + u32 vde1_pwr_con; + u32 vde_vcore0_pwr_con; + u32 vde_vcore1_pwr_con; + u32 ven0_pwr_con; + u32 ven1_pwr_con; + u32 ven2_pwr_con; + u32 cam_mraw_pwr_con; + u32 cam_suba_pwr_con; + u32 cam_subb_pwr_con; + u32 cam_subc_pwr_con; + u32 cam_main_pwr_con; + u32 cam_vcore_pwr_con; + u32 cam_ccu_pwr_con; + u32 cam_ccu_ao_pwr_con; + u32 disp_vcore_pwr_con; + u32 mml0_pwr_con; + u32 mml1_pwr_con; + u32 dis0_pwr_con; + u32 dis1_pwr_con; + u32 ovl0_pwr_con; + u32 ovl1_pwr_con; + u32 mm_infra_pwr_con; + u32 mm_proc_pwr_con; + u32 dp_tx_pwr_con; + u32 scp_pwr_con; + u32 dpyd0_pwr_con; + u32 dpyd1_pwr_con; + u32 dpyd2_pwr_con; + u32 dpyd3_pwr_con; + u32 dpya0_pwr_con; + u32 dpya1_pwr_con; + u32 dpya2_pwr_con; + u32 dpya3_pwr_con; + u32 dpm0_pwr_con; + u32 dpm1_pwr_con; + u32 dpm2_pwr_con; + u32 dpm3_pwr_con; + u32 emi0_pwr_con; + u32 emi1_pwr_con; + u32 cpueb_pwr_con; + u32 csi_rx_pwr_con; + u32 ssrsys_pwr_con; + u32 spu_ise_pwr_con; + u32 spu_hwrot_pwr_con; + u32 mfg0_pwr_con; + u32 unipro_pdn_sram_con; + u32 ufs_sleep_sram_con; + u32 ccu_sleep_sram_con; + u32 mm_infra_ao_pdn_sram_con; + u32 infra_sleep_sram_con; + u32 peri_sleep_sram_con; + u32 nth_emi_slb_sram_con; + u32 nth_emi_slb_sram_ack; + u32 sth_emi_slb_sram_con; + u32 sth_emi_slb_sram_ack; + u32 ssr_sleep_sram_con; + u32 spu_ise_sleep_sram_con; + u32 spu_hwrot_sleep_sram_con; + u32 infra_hre_sram_con; + u32 emi_hre_sram_con; + u32 mm_hre_sram_con; + u32 mml_hre_sram_con; + u32 adsp_hre_sram_con; + u32 efuse_sram_con; + u32 spm_sram_con; + u32 sspm_sram_con; + u32 cpu_buck_iso_con; + u32 md_buck_iso_con; + u32 soc_buck_iso_con; + u32 soc_buck_iso_con_set; + u32 soc_buck_iso_con_clr; + u32 pwr_status; + u32 pwr_status_2nd; + u32 pwr_status_msb; + u32 pwr_status_msb_2nd; + u32 xpu_pwr_status; + u32 xpu_pwr_status_2nd; + u32 dfd_soc_pwr_latch; + u8 reserved26[68]; + u32 spm_twam_con; + u32 spm_twam_window_len; + u32 spm_twam_idle_sel; + u32 spm_twam_last_sta[4]; + u32 spm_twam_curr_sta[4]; + u32 spm_twam_timer_out; +}; + +check_member(mtk_spm_regs, spm_wakeup_misc, 0x140); +check_member(mtk_spm_regs, spm_mcupm_spmc_con, 0x288); +check_member(mtk_spm_regs, spm_dpm_wb_con, 0x2ac); +check_member(mtk_spm_regs, spm_pwrap_cmd[31], 0x38c); +check_member(mtk_spm_regs, spm_dpsw_con, 0x3b8); +check_member(mtk_spm_regs, spm2emi_pdn_ctrl, 0x440); +check_member(mtk_spm_regs, pcm_wdt_out, 0x5ac); +check_member(mtk_spm_regs, spm_sram_srclkeno_mask, 0x6fc); +check_member(mtk_spm_regs, spm_vcore_event_count_sta, 0x8bc); +check_member(mtk_spm_regs, spm_ack_chk_sta_3, 0x9fc); +check_member(mtk_spm_regs, md32pcm_cfgreg_sw_rstn, 0xa00); +check_member(mtk_spm_regs, md32pcm_dma0_src, 0xc00); +check_member(mtk_spm_regs, md32pcm_dma0_rlct, 0xc24); +check_member(mtk_spm_regs, soc_buck_iso_con, 0xf64); +check_member(mtk_spm_regs, spm_twam_timer_out, 0xffc); + +static struct mtk_spm_regs *const mtk_spm = (void *)SPM_BASE; + +static const struct power_domain_data disp[] = { + /* TODO: add disp power domains */ +}; + +static const struct power_domain_data audio[] = { + /* TODO: add audio power domains */ +}; + +#endif /* SOC_MEDIATEK_MT8196_SPM_H */ diff --git a/src/soc/mediatek/mt8196/pmif_clk.c b/src/soc/mediatek/mt8196/pmif_clk.c new file mode 100644 index 0000000..2c59dc5 --- /dev/null +++ b/src/soc/mediatek/mt8196/pmif_clk.c @@ -0,0 +1,251 @@ +/* SPDX-License-Identifier: GPL-2.0-only OR MIT */ + +#include <assert.h> +#include <delay.h> +#include <device/mmio.h> +#include <soc/pll.h> +#include <soc/pmif.h> +#include <soc/pmif_clk_common.h> +#include <soc/pmif_spmi.h> +#include <soc/pmif_sw.h> +#include <soc/spm.h> + +#define OUTSEL_AD_OSC_CK_VAL 0x8 + +/* VLP_TOPCKGEN, VLP_CLK_CFG_UPDATE */ +DEFINE_BIT(PWRAP_ULPOSC_CK_UPDATE, 4) +DEFINE_BIT(SPMI_M_TIA_32K_CK_UPDATE, 5) +DEFINE_BIT(SPMI_M_MST_CK_UPDATE, 9) + +/* VLP_TOPCKGEN, VLP_CLK_CFG_0 */ +DEFINE_BITFIELD(CLK_SCP_SEL, 3, 0) + +/* VLP_TOPCKGEN, VLP_CLK_CFG_1 */ +DEFINE_BITFIELD(CLK_PWRAP_ULPOSC_SEL, 1, 0) +DEFINE_BIT(CLK_PWRAP_ULPOSC_INV, 4) +DEFINE_BIT(PDN_PWRAP_ULPOSC, 7) +DEFINE_BITFIELD(CLK_SPMI_M_TIA_32K_SEL, 10, 8) +DEFINE_BIT(CLK_SPMI_M_TIA_32K_INV, 12) +DEFINE_BIT(PDN_SPMI_M_TIA_32K, 15) + +/* VLP_TOPCKGEN, VLP_CLK_CFG_2 */ +DEFINE_BITFIELD(CLK_SPMI_M_MST_SEL, 9, 8) +DEFINE_BIT(CLK_SPMI_M_MST_INV, 12) +DEFINE_BIT(PDN_SPMI_M_MST, 15) + +/* VLP_TOPCKGEN, ULPOSC1_CON0 */ +DEFINE_BITFIELD(ULPOSC1_CON0, 31, 0) +DEFINE_BITFIELD(OSC1_CALI_LOW, 6, 0) +DEFINE_BITFIELD(OSC1_CALI_HIGHT, 8, 7) +DEFINE_BITFIELD(OSC1_CALI, 8, 0) +DEFINE_BITFIELD(OSC1_IBAND, 15, 9) +DEFINE_BITFIELD(OSC1_FBAND, 20, 16) +DEFINE_BITFIELD(OSC1_DIV, 26, 21) +DEFINE_BIT(OSC1_CP_EN, 27) + +/* VLP_TOPCKGEN, ULPOSC1_CON1 */ +DEFINE_BITFIELD(ULPOSC1_CON1, 31, 0) +DEFINE_BITFIELD(OSC1_32KCALI, 7, 0) +DEFINE_BITFIELD(OSC1_LJ, 15, 8) +DEFINE_BITFIELD(OSC1_RSV, 23, 16) +DEFINE_BITFIELD(OSC1_MOD, 25, 24) +DEFINE_BITFIELD(OSC_OUTSEL, 30, 27) +DEFINE_BIT(OSC1_DIV2_EN, 26) + +/* VLP_TOPCKGEN, ULPOSC1_CON2 */ +DEFINE_BITFIELD(ULPOSC1_CON2, 31, 0) +DEFINE_BITFIELD(OSC1_BIAS, 7, 0) +DEFINE_BITFIELD(OSC_BUF, 15, 8) + +/* TOPRGU, WDT_VLP_SWSYSRST0 */ +DEFINE_BITFIELD(PMIF_RST_B, 11, 10) +DEFINE_BITFIELD(PMIFSPMI_RST_B, 13, 12) +DEFINE_BITFIELD(UNLOCK_KEY, 31, 24) +DEFINE_BIT(TIA_GRST_B, 0) + +/* SPM, POWERON_CONFIG_EN */ +DEFINE_BIT(BCLK_CG_EN, 0) +DEFINE_BITFIELD(PROJECT_CODE, 31, 16) + +/* SPM, ULPOSC_CON */ +DEFINE_BIT(ULPOSC_EN, 0) +DEFINE_BIT(ULPOSC_CG_EN, 2) + +static void pmif_ulposc_config(void) +{ + /* ULPOSC1_CON0 */ + SET32_BITFIELDS(&mtk_vlpsys->vlp_ulposc1_con[0], OSC1_CP_EN, 0, OSC1_DIV, 0x34, + OSC1_FBAND, 0xA, OSC1_IBAND, 0x53, OSC1_CALI, 0x140); + + /* ULPOSC1_CON1 */ + SET32_BITFIELDS(&mtk_vlpsys->vlp_ulposc1_con[1], OSC_OUTSEL, 0x2, OSC1_DIV2_EN, 0, + OSC1_MOD, 0, OSC1_RSV, 0, OSC1_LJ, 0xA, OSC1_32KCALI, 0); + + /* ULPOSC1_CON2 */ + SET32_BITFIELDS(&mtk_vlpsys->vlp_ulposc1_con[2], OSC1_BIAS, 0x4A, OSC_BUF, 0x48); + + printk(BIOS_INFO, "%s: ULPOSC1_CON0: 0x%x, ULPOSC1_CON1: 0x%x, ULPOSC1_CON2: 0x%x\n", + __func__, + READ32_BITFIELD(&mtk_vlpsys->vlp_ulposc1_con[0], ULPOSC1_CON0), + READ32_BITFIELD(&mtk_vlpsys->vlp_ulposc1_con[1], ULPOSC1_CON1), + READ32_BITFIELD(&mtk_vlpsys->vlp_ulposc1_con[2], ULPOSC1_CON2)); +} + +static void pmif_pre_ulposc_cali_bubble(u32 target_clk) +{ + unsigned int cali_val = 0; + unsigned int abs_distance; + unsigned int min_abs_distance = 0xFFFFFFFF; + int min_cali_vali = 0x2; + int64_t freq = 0; + + /* Calculate absolute delta to 260Mhz of 4 different calibration values */ + /* Try RG_OSC1_CALI[8:7] = 0x0 ~ 0x3 */ + for (cali_val = 0; cali_val < 4; cali_val++) { + SET32_BITFIELDS(&mtk_vlpsys->vlp_ulposc1_con[0], OSC1_CALI_HIGHT, cali_val); + freq = (int64_t)(mt_get_vlpck_freq(FREQ_METER_VLP_AD_OSC_SYNC_CK)); + abs_distance = ABS(freq - (target_clk * 1000)); + + /* Memorize the minimum absolute delta and its calibration value */ + if (abs_distance < min_abs_distance) { + min_abs_distance = abs_distance; + min_cali_vali = cali_val; + } + } + + printk(BIOS_INFO, "ULPOSC1 pre-cali for high bits, select cali_val = %#x\n", + min_cali_vali); + SET32_BITFIELDS(&mtk_vlpsys->vlp_ulposc1_con[0], OSC1_CALI_HIGHT, min_cali_vali); +} + +static int pmif_set_osc_outsel(u32 outsel) +{ + SET32_BITFIELDS(&mtk_vlpsys->vlp_ulposc1_con[1], OSC_OUTSEL, outsel); + + if ((READ32_BITFIELD(&mtk_vlpsys->vlp_ulposc1_con[1], OSC_OUTSEL)) != outsel) + return -1; + else + return 0; +} + +u32 pmif_get_ulposc_freq_mhz(u32 cali_val) +{ + u32 result = 0; + + /* set calibration value */ + SET32_BITFIELDS(&mtk_vlpsys->vlp_ulposc1_con[0], OSC1_CALI_LOW, cali_val); + udelay(50); + result = mt_get_vlpck_freq(FREQ_METER_VLP_AD_OSC_SYNC_CK); + + return result / 1000; +} + +static int pmif_check_vlpck_freq(u32 target_clk) +{ + u32 freq_mhz; + freq_mhz = mt_get_vlpck_freq(FREQ_METER_VLP_AD_OSC_CK) / 1000; + + /* check if calibrated value is in the range of target value +- 2% */ + if (freq_mhz > (target_clk * (1000 - CAL_MIS_RATE) / 1000) && + freq_mhz < (target_clk * (1000 + CAL_MIS_RATE) / 1000)) + return 0; + + printk(BIOS_ERR, "ULPOSC1 K fail: %dM, PLL_ULPOSC1_CON0/1/2 0x%x 0x%x 0x%x\n", + freq_mhz, + READ32_BITFIELD(&mtk_vlpsys->vlp_ulposc1_con[0], ULPOSC1_CON0), + READ32_BITFIELD(&mtk_vlpsys->vlp_ulposc1_con[1], ULPOSC1_CON1), + READ32_BITFIELD(&mtk_vlpsys->vlp_ulposc1_con[2], ULPOSC1_CON2)); + return -1; +} + +static void pmif_turn_onoff_ulposc(bool enable) +{ + if (enable) { + /* turn on ulposc */ + SET32_BITFIELDS(&mtk_spm->ulposc_con, ULPOSC_EN, 1); + udelay(100); + SET32_BITFIELDS(&mtk_spm->ulposc_con, ULPOSC_CG_EN, 1); + } else { + SET32_BITFIELDS(&mtk_spm->ulposc_con, ULPOSC_EN, 0, ULPOSC_CG_EN, 0); + } +} + +static int pmif_init_ulposc(void) +{ + int ret = 0; + /* calibrate ULPOSC1 */ + pmif_ulposc_config(); + /* enable spm swinf */ + SET32_BITFIELDS(&mtk_spm->poweron_config_en, BCLK_CG_EN, 1, + PROJECT_CODE, 0xb16); + pmif_turn_onoff_ulposc(true); + pmif_pre_ulposc_cali_bubble(PMIF_ULPOSC_TARGET_FREQ_MHZ); + ret = pmif_ulposc_cali(PMIF_ULPOSC_TARGET_FREQ_MHZ); + pmif_turn_onoff_ulposc(false); + ret |= pmif_set_osc_outsel(OUTSEL_AD_OSC_CK_VAL); + pmif_turn_onoff_ulposc(true); + ret |= pmif_check_vlpck_freq(PMIF_VLPCK_TARGET_FREQ_MHZ); + + return ret; +} + +int pmif_clk_init(void) +{ + if (pmif_init_ulposc()) + return E_NODEV; + + /* for TIA + * [15]: pdn_spmi_m_tia [12]: clk_spmi_m_tia_inv + * [10:8]: clk_spmi_m_tia_sel: + * 0x0: tck_26m_mx9_ck, 0x1: clkrtc, 0x2: osc_d20, + * 0x3: osc_d14, 0x4: osc_d10 + */ + SET32_BITFIELDS(&mtk_vlpsys->vlp_clk_cfg[1].cfg, PDN_SPMI_M_TIA_32K, 0, + CLK_SPMI_M_TIA_32K_INV, 0, CLK_SPMI_M_TIA_32K_SEL, 0x2); + /* for pmif_m/p + * [7]: pdn_pwrap_ulposc [4]: clk_pwrap_ulposc_inv + * [1:0]: clk_pwrap_ulposc_sel: + * 0x0: tck_26m_mx9_ck, 0x1: osc_d20, 0x2: osc_d14, 0x3: osc_d10, + */ + SET32_BITFIELDS(&mtk_vlpsys->vlp_clk_cfg[1].cfg, PDN_PWRAP_ULPOSC, 0, + CLK_PWRAP_ULPOSC_INV, 0, CLK_PWRAP_ULPOSC_SEL, 0x1); + /* for spmi_mst_m/p + * [15]: pdn_spmi_m_mst [12]: clk_spmi_m_mst_inv + * [9:8]: clk_spmi_m_mst_sel: + * 0x0: tck_26m_mx9_ck, 0x1: osc_d20, 0x2: osc_d14, 0x3: osc_d10, + */ + SET32_BITFIELDS(&mtk_vlpsys->vlp_clk_cfg[2].cfg, PDN_SPMI_M_MST, 0, + CLK_SPMI_M_MST_INV, 0, CLK_SPMI_M_MST_SEL, 0x1); + + /* [9]: spmi_m_mst_ck_update ,[5]: spmi_m_tia_32k_ck_update */ + /* [4]: pwrap_ulposc_ck_update */ + SET32_BITFIELDS(&mtk_vlpsys->vlp_clk_cfg_update[0], SPMI_M_MST_CK_UPDATE, 0x1, + SPMI_M_TIA_32K_CK_UPDATE, 0x1, PWRAP_ULPOSC_CK_UPDATE, 0x1); + + /* pmif use ULPOSC1 clock */ + /* [3]: pmicw_spmi_p_tmr_ck_26M_sel + * [2]: pmicw_spmi_m_tmr_ck_26M_sel + * [1]: spmi_mst_m_p_ulposc_32k_sel + * [0]: pmicw_spmi_m_ck_26M_sel + */ + /* Enable spmi support for ULPOSC off feature, bit[1] always set to 1 */ + SET32_BITFIELDS(&mtk_vlpsys->vlp_clk_cfg[0].set, CLK_SCP_SEL, 0x2); + /* No extra tia clk src mux, default use ULPOSC1 clock + * need to confirm with DE every platform + */ + + /* toggle SPMI-M & SPMI-P sw reset */ + /* [10]: pmifspi_m_rst_b [11]: pmifspi_p_rst_b*/ + /* [12]: pmifspi_m_rst_b [13]: pmifspi_p_rst_b*/ + SET32_BITFIELDS(&mtk_rug->wdt_vlp_swsysrst0, UNLOCK_KEY, 0x88, PMIFSPMI_RST_B, 0x3, + PMIF_RST_B, 0x3); + SET32_BITFIELDS(&mtk_rug->wdt_vlp_swsysrst0, UNLOCK_KEY, 0x88); + + /* [0]: tia_grst_b */ + SET32_BITFIELDS(&mtk_rug->wdt_vlp_swsysrst1, UNLOCK_KEY, 0x88, TIA_GRST_B, 0x1); + SET32_BITFIELDS(&mtk_rug->wdt_vlp_swsysrst1, UNLOCK_KEY, 0x88); + + printk(BIOS_INFO, "%s: done\n", __func__); + + return 0; +} diff --git a/src/soc/mediatek/mt8196/pmif_init.c b/src/soc/mediatek/mt8196/pmif_init.c new file mode 100644 index 0000000..0fda348 --- /dev/null +++ b/src/soc/mediatek/mt8196/pmif_init.c @@ -0,0 +1,83 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <assert.h> +#include <console/console.h> +#include <device/mmio.h> +#include <soc/addressmap.h> +#include <soc/pmif.h> +#include <soc/pmif_common.h> +#include <soc/pmif_spi.h> +#include <soc/pmif_spmi.h> +#include <soc/pmif_sw.h> +#include <soc/spmi.h> +#include <timer.h> + +const struct pmif pmif_spmi_arb[] = { + { + .mtk_pmif = (struct mtk_pmif_regs *)PMIF_SPMI_P_BASE, + .ch = (struct chan_regs *)PMIF_SPMI_AP_CHAN_P, + .mstid = SPMI_MASTER_0, + .pmifid = PMIF_SPMI, + .write = pmif_spmi_write, + .read = pmif_spmi_read, + .write_field = pmif_spmi_write_field, + .read_field = pmif_spmi_read_field, + .is_pmif_init_done = pmif_check_init_done, + }, { + .mtk_pmif = (struct mtk_pmif_regs *)PMIF_SPMI_BASE, + .ch = (struct chan_regs *)PMIF_SPMI_AP_CHAN, + .mstid = SPMI_MASTER_1, + .pmifid = PMIF_SPMI, + .write = pmif_spmi_write, + .read = pmif_spmi_read, + .write_field = pmif_spmi_write_field, + .read_field = pmif_spmi_read_field, + .is_pmif_init_done = pmif_check_init_done, + }, { + .mtk_pmif = (struct mtk_pmif_regs *)PMIF_SPMI_P_BASE, + .ch = (struct chan_regs *)PMIF_SPMI_AP_CHAN_P, + .mstid = SPMI_MASTER_2, + .pmifid = PMIF_SPMI, + .write = pmif_spmi_write, + .read = pmif_spmi_read, + .write_field = pmif_spmi_write_field, + .read_field = pmif_spmi_read_field, + .is_pmif_init_done = pmif_check_init_done, + }, +}; + +const size_t pmif_spmi_arb_count = ARRAY_SIZE(pmif_spmi_arb); + +const struct pmif pmif_spi_arb[] = { + { + .mtk_pmif = (struct mtk_pmif_regs *)PMIF_SPI_BASE, + .ch = (struct chan_regs *)PMIF_SPI_AP_CHAN, + .pmifid = PMIF_SPI, + .write = pmif_spi_write, + .read = pmif_spi_read, + .write_field = pmif_spi_write_field, + .read_field = pmif_spi_read_field, + .is_pmif_init_done = pmif_check_init_done, + }, +}; + +const size_t pmif_spi_arb_count = ARRAY_SIZE(pmif_spi_arb); + +int mtk_pmif_init(void) +{ + int ret; + + ret = pmif_clk_init(); + + if (!ret) { + ret = pmif_spmi_init(get_pmif_controller(PMIF_SPMI, SPMI_MASTER_1)); + printk(BIOS_INFO, "%s: SPMI_MASTER_1, %d\n", __func__, ret); + } + + if (!ret) { + ret = pmif_spmi_init(get_pmif_controller(PMIF_SPMI, SPMI_MASTER_0)); + printk(BIOS_INFO, "%s: SPMI_MASTER_0, %d\n", __func__, ret); + } + + return ret; +} diff --git a/src/soc/mediatek/mt8196/pmif_spmi.c b/src/soc/mediatek/mt8196/pmif_spmi.c new file mode 100644 index 0000000..91f9038 --- /dev/null +++ b/src/soc/mediatek/mt8196/pmif_spmi.c @@ -0,0 +1,350 @@ +/* SPDX-License-Identifier: GPL-2.0-only OR MIT */ + +#include <console/console.h> +#include <device/mmio.h> +#include <gpio.h> +#include <soc/addressmap.h> +#include <soc/pll.h> +#include <soc/pmif.h> +#include <soc/pmif_spmi.h> +#include <soc/spmi.h> + +#define SPMI_RCS_CTRL_BASE 0x140084 + +/* TOPCKGEN, CLK_CFG_17 */ +DEFINE_BITFIELD(CLK_SPMI_MST_SEL, 10, 8) +DEFINE_BIT(CLK_SPMI_MST_INT, 12) +DEFINE_BIT(PDN_SPMI_MST, 15) + +/* TOPCKGEN, CLK_CFG_UPDATE2 */ +DEFINE_BIT(SPMI_MST_CK_UPDATE, 5) + +/* SPMI_MST, SPMI_SAMPL_CTRL */ +DEFINE_BIT(SAMPL_CK_POL, 0) +DEFINE_BITFIELD(SAMPL_CK_DLY, 3, 1) +DEFINE_BITFIELD(SAMPL_CK_DLY_ARB, 6, 4) + +/* PMIF, SPI_MODE_CTRL */ +DEFINE_BIT(VLD_SRCLK_EN_CTRL, 5) +DEFINE_BIT(SPI_MODE_CTRL_PMIF_RDY, 9) +DEFINE_BIT(SPI_MODE_CTRL_SRCLK_EN, 10) +DEFINE_BIT(SPI_MODE_CTRL_SRVOL_EN, 11) + +/* PMIF, SLEEP_PROTECTION_CTRL */ +DEFINE_BIT(SPM_SLEEP_REQ_SEL, 0) +DEFINE_BIT(SCP_SLEEP_REQ_SEL, 9) + +const struct spmi_device spmi_dev[] = { + { + .slvid = SPMI_SLAVE_4, /* MT6363 */ + .mstid = SPMI_MASTER_1, + .type = MAIN_PMIC, + .type_id = MAIN_PMIC_ID, + .hwcid_addr = 0x09, + .hwcid_val = 0x63, + .hwcid_mask = 0xF0, + }, + { + .slvid = SPMI_SLAVE_9, /* MT6685 */ + .mstid = SPMI_MASTER_1, + .type = CLOCK_PMIC, + .type_id = CLOCK_PMIC_ID, + .hwcid_addr = 0x09, + .hwcid_val = 0x85, + .hwcid_mask = 0xF0, + }, + { + .slvid = SPMI_SLAVE_5, /* MT6373 */ + .mstid = SPMI_MASTER_1, + .type = SECOND_PMIC, + .type_id = SECOND_PMIC_ID, + .hwcid_addr = 0x09, + .hwcid_val = 0x73, + .hwcid_mask = 0xF0, + }, + { + .slvid = SPMI_SLAVE_6, /* MT6316 */ + .mstid = SPMI_MASTER_0, + .type = SUB_PMIC, + .type_id = SUB_PMIC_ID, + .hwcid_addr = 0x209, + .hwcid_val = 0x16, + .hwcid_mask = 0xf0, + }, + { + .slvid = SPMI_SLAVE_7, /* MT6316 */ + .mstid = SPMI_MASTER_0, + .type = SUB_PMIC, + .type_id = SUB_PMIC_ID, + .hwcid_addr = 0x209, + .hwcid_val = 0x16, + .hwcid_mask = 0xf0, + }, + { + .slvid = SPMI_SLAVE_8, /* MT6316 */ + .mstid = SPMI_MASTER_0, + .type = SUB_PMIC, + .type_id = SUB_PMIC_ID, + .hwcid_addr = 0x209, + .hwcid_val = 0x16, + .hwcid_mask = 0xf0, + }, + { + .slvid = SPMI_SLAVE_15, /* MT6316 */ + .mstid = SPMI_MASTER_0, + .type = SUB_PMIC, + .type_id = SUB_PMIC_ID, + .hwcid_addr = 0x209, + .hwcid_val = 0x16, + .hwcid_mask = 0xf0, + }, +}; + +static const uint32_t chan_perm[2][4] = { + [SPMI_MASTER_0] = { 0x8888888A, 0x88888888, 0x88888888, 0x88888888 }, + [SPMI_MASTER_1] = { 0x888888AA, 0x88888888, 0x88888888, 0x88888888 }, +}; + +static const uint32_t lat_limit[2][23] = { + [SPMI_MASTER_0] = { 0x3e6, 0x3e6, 0x9, 0x9, 0x3e6, 0x3e6, 0x3e6, 0x3e6, 0x9, 0x3e6, + 0x0, 0x3e6, 0x9, 0x0, 0x0, 0x3e6, 0x3e6, 0x3e6, 0x3e6, 0x0, + 0x3e6, 0x0, 0x3e6 }, + [SPMI_MASTER_1] = { 0x3e6, 0x0, 0x3e6, 0x3e6, 0x26, 0x37, 0x3e6, 0x10, 0x9, 0x23, + 0x0, 0x39, 0x9, 0x0, 0x0, 0x12, 0x3e6, 0x3e6, 0x3e6, 0x0, + 0x1e, 0x0, 0x3e6 }, +}; + +const size_t spmi_dev_cnt = ARRAY_SIZE(spmi_dev); + +static struct mtk_spmi_mst_reg *get_mst_reg(struct pmif *arb) +{ + if (arb->mstid == SPMI_MASTER_1) + return mtk_spmi_mst; + else if (arb->mstid == SPMI_MASTER_0 || arb->mstid == SPMI_MASTER_2) + return mtk_spmi_mst_p; + else + return NULL; +} + +static int pmif_spmi_config_master(struct pmif *arb) +{ + struct mtk_spmi_mst_reg *reg = get_mst_reg(arb); + if (!reg) { + printk(BIOS_ERR, "%s: get_mst_reg get null pointer\n", __func__); + return -1; + } + + write32(®->mst_req_en, 1); + write32(®->grp_id_en, 0xC00); + /* enable multi-master and rcs support */ + write32(®->rcs_ctrl, SPMI_RCS_CTRL_BASE + arb->mstid); + printk(BIOS_INFO, "%s: mstid=%d done\n", __func__, arb->mstid); + return 0; +} + +void pmif_spmi_config(struct pmif *arb) +{ + _Static_assert(ARRAY_SIZE(chan_perm[0]) == ARRAY_SIZE(arb->mtk_pmif->inf_cmd_per), + "Inconsistent array size for chan_perm and inf_cmd_per"); + const uint32_t *perm = chan_perm[arb->mstid % 2]; + /* + * all cmd permission for per channel + * [0]: Command 0 Permitted + * [1]: Command 1 Permitted + * [2]: Command 2 Permitted + * [3]: Command 3 Permitted + */ + /* PER_0[8:0]: CH0 or CH1 for MD DVFS HW, backward compatible for swrgo */ + for (int i = 0; i < ARRAY_SIZE(arb->mtk_pmif->inf_cmd_per); i++) + write32(&arb->mtk_pmif->inf_cmd_per[i], perm[i]); +} + +void pmif_spmi_iocfg(void) +{ + /* SPMI_M 10mA */ + gpio_set_driving(GPIO(SPMI_M_SCL), GPIO_DRV_10_MA); + gpio_set_driving(GPIO(SPMI_M_SDA), GPIO_DRV_10_MA); + /* SPMI_P 14mA */ + gpio_set_driving(GPIO(SPMI_P_SCL), GPIO_DRV_14_MA); + gpio_set_driving(GPIO(SPMI_P_SDA), GPIO_DRV_14_MA); + printk(BIOS_INFO, "%s done\n", __func__); +} + +static int spmi_read_check(struct pmif *arb, const struct spmi_device *dev) +{ + u32 rdata = 0; + + arb->read(arb, dev->slvid, dev->hwcid_addr, &rdata); + if ((rdata & dev->hwcid_mask) != (dev->hwcid_val & dev->hwcid_mask)) { + printk(BIOS_WARNING, "%s next, slvid:%d rdata = 0x%x\n", + __func__, dev->slvid, rdata); + return -E_NODEV; + } + + printk(BIOS_INFO, "%s next, slvid:%d rdata = 0x%x.\n", __func__, dev->slvid, rdata); + return 0; +} + +static int spmi_cali_rd_clock_polarity(struct pmif *arb, const struct spmi_device *dev) +{ + size_t i; + bool success = false; + const struct cali cali_data[] = { + {SPMI_CK_DLY_1T, SPMI_CK_POL_NEG}, + {SPMI_CK_DLY_1T, SPMI_CK_POL_POS}, + {SPMI_CK_NO_DLY, SPMI_CK_POL_POS}, + {SPMI_CK_NO_DLY, SPMI_CK_POL_NEG}, + {SPMI_CK_DLY_2T, SPMI_CK_POL_POS}, + {SPMI_CK_DLY_2T, SPMI_CK_POL_NEG}, + }; + + struct mtk_spmi_mst_reg *reg = get_mst_reg(arb); + if (!reg) { + printk(BIOS_ERR, "%s: get_mst_reg get null pointer\n", __func__); + return -1; + } + + /* Indicate sampling clock polarity, 1: Positive 0: Negative */ + for (i = 0; i < ARRAY_SIZE(cali_data); i++) { + SET32_BITFIELDS(®->mst_sampl, SAMPL_CK_DLY, cali_data[i].dly, + SAMPL_CK_POL, cali_data[i].pol); + SET32_BITFIELDS(®->mst_sampl, SAMPL_CK_DLY_ARB, cali_data[i].dly + 1); + printk(BIOS_DEBUG, "dly:%d, pol:%d, sampl:0x%x\n", + cali_data[i].dly, cali_data[i].pol, read32(®->mst_sampl)); + if (spmi_read_check(arb, dev) == 0) { + success = true; + break; + } + } + + if (!success) + die("ERROR - calibration fail for SPMI clk"); + + return 0; +} + +static int spmi_config_slave(struct pmif *arb, const struct spmi_device *dev) +{ + u32 wdata; + + /* set RG_RCS_ADDR=slave id */ + wdata = dev->slvid; + arb->write(arb, dev->slvid, 0x419, wdata); /* rcs_slvid_addr: 0x419 */ + + /* set RG_RCS_ENABLE=1, RG_RCS_ID=Master ID */ + wdata = 0x5 | (dev->mstid << 4); + arb->write(arb, dev->slvid, 0x418, wdata); /* rcs_slvid_en: 0x418 */ + + return 0; +} + +static int spmi_mst_init(struct pmif *arb) +{ + int i; + + if (!arb) { + printk(BIOS_ERR, "%s: null pointer for pmif dev\n", __func__); + return -E_INVAL; + } + + if (!CONFIG(PMIF_SPMI_IOCFG_DEFAULT_SETTING)) + pmif_spmi_iocfg(); + + if (pmif_spmi_config_master(arb)) + return -1; + + for (i = 0; i < spmi_dev_cnt; i++) { + if ((arb->mstid % 2) == spmi_dev[i].mstid) { + spmi_cali_rd_clock_polarity(arb, &spmi_dev[i]); /* spmi_cali */ + spmi_config_slave(arb, &spmi_dev[i]); + } + } + + return 0; +} + +static void pmif_spmi_force_normal_mode(struct pmif *arb) +{ + /* listen srclken_0 only for entering normal or sleep mode */ + SET32_BITFIELDS(&arb->mtk_pmif->spi_mode_ctrl, + VLD_SRCLK_EN_CTRL, 0, + SPI_MODE_CTRL_PMIF_RDY, 1, + SPI_MODE_CTRL_SRCLK_EN, 0, + SPI_MODE_CTRL_SRVOL_EN, 0); + + /* disable spm/scp sleep request */ + SET32_BITFIELDS(&arb->mtk_pmif->sleep_protection_ctrl, SPM_SLEEP_REQ_SEL, 1, + SCP_SLEEP_REQ_SEL, 1); + printk(BIOS_INFO, "%s done\n", __func__); +} + +static void pmif_spmi_enable_swinf(struct pmif *arb) +{ + write32(&arb->mtk_pmif->inf_en, PMIF_SPMI_SW_CHAN); + write32(&arb->mtk_pmif->arb_en, PMIF_SPMI_SW_CHAN); + printk(BIOS_INFO, "%s done\n", __func__); +} + +static void pmif_spmi_enable_cmd_issue(struct pmif *arb, bool en) +{ + /* Enable cmdIssue */ + write32(&arb->mtk_pmif->cmdissue_en, en); + printk(BIOS_INFO, "%s done\n", __func__); +} + +static void pmif_spmi_enable(struct pmif *arb) +{ + _Static_assert(ARRAY_SIZE(lat_limit[0]) == ARRAY_SIZE(arb->mtk_pmif->lat_limit), + "Inconsistent array size for lat_limit and arb->mtk_pmif->lat_limit"); + const uint32_t *lat_limit_value = lat_limit[arb->mstid % 2]; + u32 pmif_spmi_inf; + int i; + + if (arb->mstid % 2) + pmif_spmi_inf = PMIF_SPMI_INF; + else + pmif_spmi_inf = PMIF_SPMI_INF_P; + + pmif_spmi_config(arb); + + /* set bytecnt max limitation, 0:1 byte, 1:2 bytes */ + for (i = 0; i < ARRAY_SIZE(arb->mtk_pmif->inf_max_bytecnt_per); i++) + write32(&arb->mtk_pmif->inf_max_bytecnt_per[i], 0x11111111); + + /* Add latency limitation for all channels, method 2 */ + /* Latency unit = (LAT_UNIT_SEL + 1)T of TMR_CK, LAT_UNIT_SEL=25;Lat unit=26T ~=1us */ + write32(&arb->mtk_pmif->lat_cnter_ctrl, 0x32); + if (arb->mstid % 2) + write32(&arb->mtk_pmif->lat_cnter_en, pmif_spmi_inf); + for (i = 0; i < ARRAY_SIZE(arb->mtk_pmif->lat_limit); i++) + write32(&arb->mtk_pmif->lat_limit[i], lat_limit_value[i]); + write32(&arb->mtk_pmif->lat_limit_loading, pmif_spmi_inf); + + /* Disable STAUPD_ITEM_EN */ + write32(&arb->mtk_pmif->staupd_ctrl, 0x1030000); + + write32(&arb->mtk_pmif->inf_en, pmif_spmi_inf); + write32(&arb->mtk_pmif->arb_en, pmif_spmi_inf); + write32(&arb->mtk_pmif->timer_ctrl, 0x3); + write32(&arb->mtk_pmif->init_done, 1); + printk(BIOS_INFO, "%s init done: 0x%x\n", __func__, read32(&arb->mtk_pmif->init_done)); +} + +int pmif_spmi_init(struct pmif *arb) +{ + if (arb->is_pmif_init_done(arb) != 0) { + pmif_spmi_force_normal_mode(arb); + pmif_spmi_enable_swinf(arb); + pmif_spmi_enable_cmd_issue(arb, true); + pmif_spmi_enable(arb); + if (arb->is_pmif_init_done(arb)) + return -E_NODEV; + } + + if (spmi_mst_init(arb)) { + printk(BIOS_ERR, "[%s] failed to init SPMI master\n", __func__); + return -E_NODEV; + } + + return 0; +}