diff --git a/src/soc/mediatek/mt8196/Makefile.mk b/src/soc/mediatek/mt8196/Makefile.mk index 0410129e46..f898775838 100644 --- a/src/soc/mediatek/mt8196/Makefile.mk +++ b/src/soc/mediatek/mt8196/Makefile.mk @@ -30,6 +30,9 @@ romstage-y += l2c_ops.c 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/mcu.c 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 e4a41077b5..b252eecc26 100644 --- a/src/soc/mediatek/mt8196/include/soc/addressmap.h +++ b/src/soc/mediatek/mt8196/include/soc/addressmap.h @@ -34,6 +34,8 @@ enum { 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 0000000000..a114dc653e --- /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 +#include +#include + +/* 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 0000000000..b0f12640ca --- /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 +#include +#include +#include +#include + +/* 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 0000000000..2c59dc5221 --- /dev/null +++ b/src/soc/mediatek/mt8196/pmif_clk.c @@ -0,0 +1,251 @@ +/* SPDX-License-Identifier: GPL-2.0-only OR MIT */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 0000000000..0fda348d79 --- /dev/null +++ b/src/soc/mediatek/mt8196/pmif_init.c @@ -0,0 +1,83 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 0000000000..91f9038eff --- /dev/null +++ b/src/soc/mediatek/mt8196/pmif_spmi.c @@ -0,0 +1,350 @@ +/* SPDX-License-Identifier: GPL-2.0-only OR MIT */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#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; +}