soc/mediatek/mt8189: Add SPMI and PWRAP driver

Add System Power Management Interface(SPMI) and PMIC Wrapper(PWRAP)
driver for PMIC.

BUG=b:379008996
BRANCH=none
TEST=build pass and driver log is normal:
[DEBUG]  [pmif_ulposc_check] calibration done:
cur=260M, CAL_RATE=40, target=260
[INFO ]  [Pass] dly:1, pol:0, sampl:0x2
[INFO ]  [Pass] dly:1, pol:0, sampl:0x2
[DEBUG]  pmic_efuse_setting: Set efuses in 10 msecs

Signed-off-by: Zhigang Qin <zhigang.qin@mediatek.corp-partner.google.com>
Change-Id: I7d0783ccaebd79db69a5a8ef18d7feb6cd4b14f3
Reviewed-on: https://review.coreboot.org/c/coreboot/+/87694
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Yidi Lin <yidilin@google.com>
Reviewed-by: Yu-Ping Wu <yupingso@google.com>
This commit is contained in:
Zhigang Qin 2024-11-26 17:29:13 +08:00 committed by Yidi Lin
commit cb77cafbb4
10 changed files with 424 additions and 7 deletions

View file

@ -108,4 +108,6 @@ enum {
int pmif_spi_init(struct pmif *arb);
void pmif_spi_iocfg(void);
void pmif_spi_setting(struct pmif *arb);
#endif /* __SOC_MEDIATEK_PMIF_SPI_H__ */

View file

@ -271,6 +271,11 @@ static void init_staupd(struct pmif *arb)
STAUPD_CTRL_PMIC0_EINT_STA, 1);
}
__weak void pmif_spi_setting(struct pmif *arb)
{
/* do nothing, only for special setting of IC */
}
int pmif_spi_init(struct pmif *arb)
{
pmif_spi_config(arb);
@ -316,6 +321,8 @@ int pmif_spi_init(struct pmif *arb)
/* Enable GPS AUXADC HW 0 and 1 */
SET32_BITFIELDS(&arb->mtk_pmif->other_inf_en, INTGPSADCINF_EN, 0x3);
pmif_spi_setting(arb);
/* Set INIT_DONE */
write32(&arb->mtk_pmif->init_done, 0x1);

View file

@ -22,6 +22,9 @@ romstage-y += ../common/emi.c
romstage-y += ../common/memory.c ../common/memory_test.c
romstage-y += ../common/mmu_operations.c ../common/mmu_cmops.c
romstage-y += ../common/pll.c pll.c
romstage-y += ../common/pmif.c ../common/pmif_clk.c ../common/pmif_init.c pmif_clk.c
romstage-y += ../common/pmif_spi.c pmif_spi.c
romstage-y += ../common/pmif_spmi.c pmif_spmi.c
ramstage-$(CONFIG_ARM64_USE_ARM_TRUSTED_FIRMWARE) += ../common/bl31.c
ramstage-y += ../common/dramc_info.c
@ -29,6 +32,9 @@ ramstage-y += ../common/emi.c
ramstage-y += ../common/memory.c
ramstage-y += ../common/mmu_operations.c ../common/mmu_cmops.c
ramstage-y += ../common/mtcmos.c mtcmos.c
ramstage-y += ../common/pmif.c ../common/pmif_clk.c ../common/pmif_init.c pmif_clk.c
ramstage-y += ../common/pmif_spi.c pmif_spi.c
ramstage-y += ../common/pmif_spmi.c pmif_spmi.c
ramstage-y += soc.c
ramstage-y += ../common/usb.c usb.c

View file

@ -111,13 +111,13 @@ enum {
VLPCFG_REG_BASE = IO_PHYS + 0x0C00C000,
DVFSRC_TOP_BASE = IO_PHYS + 0x0C00F000,
VLP_CK_BASE = IO_PHYS + 0x0C012000,
SPMI_MST_BASE = IO_PHYS + 0x0C013000,
PMICSPI_MST_BASE = IO_PHYS + 0x0C013000,
DEVAPC_VLP_AO_BASE = IO_PHYS + 0x0C018000,
SCP_IIC_BASE = IO_PHYS + 0x0C80A000,
SCP_BASE = IO_PHYS + 0x0CB21000,
SPMI_MST_P_BASE = IO_PHYS + 0x0CC00000,
PMIF_SPMI_BASE = IO_PHYS + 0x0CC04000,
PMIF_SPMI_P_BASE = IO_PHYS + 0x0CC06000,
SPMI_MST_BASE = IO_PHYS + 0x0CC00000,
PMIF_SPI_BASE = IO_PHYS + 0x0CC04000,
PMIF_SPMI_BASE = IO_PHYS + 0x0CC06000,
SYSTIMER_BASE = IO_PHYS + 0x0CC10000,
VAD_BASE = IO_PHYS + 0x0E010000,
DEVAPC_MM_AO_BASE = IO_PHYS + 0x0E820000,

View file

@ -123,16 +123,22 @@ struct mtk_vlp_regs {
u32 vlp_clk_cfg_30;
u32 vlp_clk_cfg_30_set;
u32 vlp_clk_cfg_30_clr;
u32 reserved3[13];
u32 reserved3[3];
u32 vlp_ulposc1_con0;
u32 vlp_ulposc1_con1;
u32 vlp_ulposc1_con2;
u32 reserved4[7];
u32 vlp_fqmtr_con[2];
};
check_member(mtk_vlp_regs, vlp_clk_cfg_update, 0x0004);
check_member(mtk_vlp_regs, vlp_clk_cfg[0].set, 0x000C);
check_member(mtk_vlp_regs, vlp_clk_cfg[0].clr, 0x0010);
check_member(mtk_vlp_regs, vlp_clk_cfg[5].set, 0x0048);
check_member(mtk_vlp_regs, vlp_clk_cfg[5].clr, 0x004C);
check_member(mtk_vlp_regs, vlp_clk_cfg_30, 0x01F0);
check_member(mtk_vlp_regs, vlp_ulposc1_con0, 0x0208);
check_member(mtk_vlp_regs, vlp_ulposc1_con1, 0x020C);
check_member(mtk_vlp_regs, vlp_ulposc1_con2, 0x0210);
check_member(mtk_vlp_regs, vlp_fqmtr_con[0], 0x0230);
struct mtk_topckgen_regs {

View file

@ -0,0 +1,156 @@
/* SPDX-License-Identifier: GPL-2.0-only OR MIT */
#ifndef __SOC_MEDIATEK_MT8189_INCLUDE_SOC_PMIF_H__
#define __SOC_MEDIATEK_MT8189_INCLUDE_SOC_PMIF_H__
#include <device/mmio.h>
#include <soc/addressmap.h>
#include <soc/pmif_common.h>
#include <types.h>
/* indicate which number SW channel start, by project */
#define PMIF_SPMI_SW_CHAN BIT(7)
#define PMIF_SPMI_INF 0x7FF
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_0;
u32 inf_cmd_per_1;
u32 inf_cmd_per_2;
u32 inf_cmd_per_3;
u32 inf_max_bytecnt_per_0;
u32 inf_max_bytecnt_per_1;
u32 inf_max_bytecnt_per_2;
u32 inf_max_bytecnt_per_3;
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_0;
u32 lat_limit_1;
u32 lat_limit_2;
u32 lat_limit_3;
u32 lat_limit_4;
u32 lat_limit_5;
u32 lat_limit_6;
u32 lat_limit_7;
u32 lat_limit_8;
u32 lat_limit_9;
u32 reserved5[99];
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;
u32 sleep_protection_ctrl;
u32 reserved8[6];
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_SPI_HW_INF 0x181F
#define PMIF_SPI_MD BIT(5)
#define PMIF_SPI_AP_SECURE BIT(6)
#define PMIF_SPI_AP BIT(7)
#define PMIF_SPI_INF_EN (PMIF_SPI_HW_INF | PMIF_SPI_MD | PMIF_SPI_AP_SECURE | \
PMIF_SPI_AP)
#define PMIF_SPI_ARB_EN (PMIF_SPI_HW_INF | PMIF_SPI_MD | PMIF_SPI_AP_SECURE | \
PMIF_SPI_AP)
#define PMIF_SPMI_AP_CHAN (PMIF_SPMI_BASE + 0x880)
#define PMIF_SPI_AP_CHAN (PMIF_SPI_BASE + 0x880)
enum {
PMIF_TARGET_FREQ_MHZ = 260,
};
/* calibation tolerance rate, unit: 0.1% */
enum {
CAL_TOL_RATE = 40,
CAL_MAX_VAL = 0x7F,
};
#define FREQ_METER_ABIST_AD_OSC_CK 42
#define CALI_DEFAULT_CAP_VALUE 0x3d
#define FREQ_METER_VLP_OSC_CK 28
#endif /*__SOC_MEDIATEK_MT8189_INCLUDE_SOC_PMIF_H__*/

View file

@ -17,13 +17,17 @@ struct mtk_reg_cfg {
struct mtk_vlpcfg_regs {
u32 reserved1;
u32 vlp_test_ck_ctrl;
u32 reserved2[130];
u32 reserved2[3];
u32 pmicw_clock_ctrl_set;
u32 pmicw_clock_ctrl_clr;
u32 reserved3[125];
u32 bus_vlp_topaxi_protecten;
u32 bus_vlp_topaxi_protecten_set;
u32 bus_vlp_topaxi_protecten_clr;
u32 bus_vlp_topaxi_protecten_sta1;
};
check_member(mtk_vlpcfg_regs, vlp_test_ck_ctrl, 0x0004);
check_member(mtk_vlpcfg_regs, pmicw_clock_ctrl_clr, 0x0018);
check_member(mtk_vlpcfg_regs, bus_vlp_topaxi_protecten, 0x0210);
struct mtk_infracfg_ao_regs {

View file

@ -0,0 +1,165 @@
/* SPDX-License-Identifier: GPL-2.0-only OR MIT */
#include <commonlib/helpers.h>
#include <console/console.h>
#include <delay.h>
#include <device/mmio.h>
#include <soc/pll.h>
#include <soc/pll_common.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>
#include <soc/spm_mtcmos.h>
#define ULPOSC1_CHECK_RETRY_COUNT 5
#define ULPOSC1_HW_CALI_VAL 0x11f10054
DEFINE_BITFIELD(CLK_EN, 18, 0)
/* APMIXED, ULPOSC1_CON0 */
DEFINE_BITFIELD(OSC1_CALI, 6, 0)
DEFINE_BITFIELD(OSC1_IBAND, 13, 7)
DEFINE_BITFIELD(OSC1_FBAND, 17, 14)
DEFINE_BITFIELD(OSC1_DIV, 23, 18)
DEFINE_BIT(OSC1_CP_EN, 24)
/* APMIXED, ULPOSC1_CON1 */
DEFINE_BITFIELD(OSC1_32KCALI, 7, 0)
DEFINE_BITFIELD(OSC1_RSV1, 15, 8)
DEFINE_BITFIELD(OSC1_RSV2, 23, 16)
DEFINE_BITFIELD(OSC1_MOD, 25, 24)
DEFINE_BIT(OSC1_DIV2_EN, 26)
/* APMIXED, ULPOSC1_CON2 */
DEFINE_BITFIELD(OSC1_BIAS, 7, 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_BITFIELD(ULPOSC_RST, 1, 0)
/* INFRA, PMICW_CLOCK_CTRL */
DEFINE_BITFIELD(PMIC_SYSCK_26M_SEL, 3, 0)
DEFINE_BITFIELD(CLK_PWRAP_ULPOSC_SEL, 10, 8)
DEFINE_BITFIELD(CLK_SPMI_P_MST_SEL, 19, 16)
DEFINE_BIT(CLK_PWRAP_ULPOSC_INV, 12)
DEFINE_BIT(CLK_SPMI_P_MST_INV, 20)
DEFINE_BIT(PDN_PWRAP_ULPOSC, 15)
DEFINE_BIT(PDN_SPMI_P_MST_ULPOSC, 23)
/* TOPCKGEN, CLK_CFG_UPDATE1 */
DEFINE_BITFIELD(CLK_CFG_UPDATE, 2, 1)
DEFINE_BITFIELD(SPMI_MST_RST, 13, 10)
DEFINE_BITFIELD(UNLOCK_KEY, 31, 24)
static void pmif_ulposc_config(void)
{
SET32_BITFIELDS(&mtk_vlpsys->vlp_clk_cfg_30_set, CLK_EN, 0x70000);
/* ULPOSC1_CON0 */
SET32_BITFIELDS(&mtk_vlpsys->vlp_ulposc1_con0, OSC1_CP_EN, 1, OSC1_DIV, 0xE,
OSC1_FBAND, 0, OSC1_IBAND, 0, OSC1_CALI, 0x3D);
/* ULPOSC1_CON1 */
SET32_BITFIELDS(&mtk_vlpsys->vlp_ulposc1_con1, OSC1_DIV2_EN, 1, OSC1_MOD, 0,
OSC1_RSV2, 0, OSC1_RSV1, 0, OSC1_32KCALI, 0);
/* ULPOSC1_CON2 */
SET32_BITFIELDS(&mtk_vlpsys->vlp_ulposc1_con2, OSC1_BIAS, 0x0);
udelay(15);
}
u32 pmif_get_ulposc_freq_mhz(u32 cali_val)
{
u32 result = 0;
/* set calibration value */
SET32_BITFIELDS(&mtk_vlpsys->vlp_ulposc1_con0, OSC1_CALI, cali_val);
udelay(50);
result = mt_get_vlpck_freq(FREQ_METER_VLP_OSC_CK);
return result / 1000;
}
static void pmif_turn_on_ulposc(void)
{
/* enable APB clock swinf */
if (!READ32_BITFIELD(&mtk_spm->poweron_config_set, BCLK_CG_EN))
SET32_BITFIELDS(&mtk_spm->poweron_config_set, BCLK_CG_EN, 1,
PROJECT_CODE, 0xb16);
SET32_BITFIELDS(&mtk_spm->ulposc_con, ULPOSC_EN, 1);
udelay(20);
SET32_BITFIELDS(&mtk_spm->ulposc_con, ULPOSC_RST, 0x3);
udelay(20);
SET32_BITFIELDS(&mtk_spm->ulposc_con, ULPOSC_EN, 1);
udelay(120);
}
static int pmif_init_ulposc(void)
{
/* calibrate ULPOSC1 */
pmif_ulposc_config();
pmif_turn_on_ulposc();
return pmif_ulposc_cali(PMIF_TARGET_FREQ_MHZ);
}
int pmif_clk_init(void)
{
bool sw_cali = false;
u32 cali_val;
for (int i = 0; i < ULPOSC1_CHECK_RETRY_COUNT; i++) {
cali_val = mt_get_vlpck_freq(FREQ_METER_VLP_OSC_CK) / 1000;
if (pmif_ulposc_check(cali_val, PMIF_TARGET_FREQ_MHZ) != 0) {
sw_cali = true;
break;
}
}
if (sw_cali) {
/* initialize pmif clock */
printk(BIOS_INFO, "Using SW calibration!\n");
if (pmif_init_ulposc())
return E_NODEV;
} else {
printk(BIOS_INFO, "Using HW calibration!\n");
/* set calibration value */
cali_val = read32p(ULPOSC1_HW_CALI_VAL);
printk(BIOS_INFO, "calibration pre value: %#x, PLL_ULPOSC1_CON0 value: %#x\n",
cali_val, read32(&mtk_vlpsys->vlp_ulposc1_con0));
SET32_BITFIELDS(&mtk_vlpsys->vlp_ulposc1_con0, OSC1_CALI,
(cali_val >> 1) & 0x7F);
SET32_BITFIELDS(&mtk_vlpsys->vlp_clk_cfg_30_set, CLK_EN, 0x70000);
pmif_turn_on_ulposc();
printk(BIOS_INFO, "PLL_ULPOSC1_CON0: 0x%x\n",
read32(&mtk_vlpsys->vlp_ulposc1_con0));
}
/* turn off pmic_cg_tmr, cg_ap, cg_md, cg_conn clock */
SET32_BITFIELDS(&mtk_vlpsys->vlp_clk_cfg[0].clr, CLK_PWRAP_ULPOSC_SEL, 0x7,
CLK_PWRAP_ULPOSC_INV, 0x1, PDN_PWRAP_ULPOSC, 0x1);
SET32_BITFIELDS(&mtk_vlpsys->vlp_clk_cfg[0].set, CLK_PWRAP_ULPOSC_SEL, 1);
SET32_BITFIELDS(&mtk_vlpsys->vlp_clk_cfg[0].clr, CLK_SPMI_P_MST_SEL, 0xf,
CLK_SPMI_P_MST_INV, 0x1, PDN_SPMI_P_MST_ULPOSC, 0x1);
SET32_BITFIELDS(&mtk_vlpsys->vlp_clk_cfg[0].set, CLK_SPMI_P_MST_SEL, 0x3);
SET32_BITFIELDS(&mtk_vlpsys->vlp_clk_cfg_update, CLK_CFG_UPDATE, 0x3);
/* use ULPOSC1 clock */
SET32_BITFIELDS(&mtk_vlpcfg->pmicw_clock_ctrl_clr, PMIC_SYSCK_26M_SEL, 0xf);
/* toggle pwrap & SPMI-P sw reset */
/* [10]: pmifspmi_m_rst_b [11]: pmifspmi_p_rst_b*/
/* [12]: spmi_p_mst_rst_b [13]: pmicspi_grst_b*/
SET32_BITFIELDS(&mtk_rug->wdt_vlp_swsysrst0, UNLOCK_KEY, 0x88, SPMI_MST_RST, 0xf);
SET32_BITFIELDS(&mtk_rug->wdt_vlp_swsysrst0, UNLOCK_KEY, 0x88, SPMI_MST_RST, 0x0);
return 0;
}

View file

@ -0,0 +1,25 @@
/* SPDX-License-Identifier: GPL-2.0-only OR MIT */
#include <device/mmio.h>
#include <gpio.h>
#include <soc/pmif_spi.h>
/* PMIF, SLEEP_PROTECTION_CTRL */
DEFINE_BITFIELD(SPM_SLEEP_REQ_SEL, 1, 0)
DEFINE_BITFIELD(SCP_SLEEP_REQ_SEL, 10, 9)
void pmif_spi_iocfg(void)
{
/* Set SoC SPI IO driving strength to 6 mA */
gpio_set_driving(GPIO(PWRAP_SPI_CK), GPIO_DRV_6_MA);
gpio_set_driving(GPIO(PWRAP_SPI_CSN), GPIO_DRV_6_MA);
gpio_set_driving(GPIO(PWRAP_SPI_MI), GPIO_DRV_6_MA);
gpio_set_driving(GPIO(PWRAP_SPI_MO), GPIO_DRV_6_MA);
}
void pmif_spi_setting(struct pmif *arb)
{
SET32_BITFIELDS(&arb->mtk_pmif->sleep_protection_ctrl,
SPM_SLEEP_REQ_SEL, 1,
SCP_SLEEP_REQ_SEL, 1);
}

View file

@ -0,0 +1,46 @@
/* SPDX-License-Identifier: GPL-2.0-only OR MIT */
#include <console/console.h>
#include <delay.h>
#include <device/mmio.h>
#include <gpio.h>
#include <soc/pll.h>
#include <soc/pmif_spmi.h>
const struct spmi_device spmi_dev[] = {
{
.slvid = SPMI_SLAVE_7,
.type = SUB_PMIC,
.type_id = SUB_PMIC_ID,
},
{
.slvid = SPMI_SLAVE_8,
.type = BUCK_CPU,
.type_id = BUCK_CPU_ID,
},
};
const size_t spmi_dev_cnt = ARRAY_SIZE(spmi_dev);
int spmi_config_master(void)
{
/* Enable SPMI */
write32(&mtk_spmi_mst->mst_req_en, 1);
return 0;
}
void pmif_spmi_config(struct pmif *arb)
{
/* Clear all cmd permission for per channel */
write32(&arb->mtk_pmif->inf_cmd_per_0, 0x888888AA);
write32(&arb->mtk_pmif->inf_cmd_per_1, 0x88888888);
write32(&arb->mtk_pmif->inf_cmd_per_2, 0x88888888);
write32(&arb->mtk_pmif->inf_cmd_per_3, 0x88888888);
}
void pmif_spmi_iocfg(void)
{
gpio_set_driving(GPIO(SPMI_P_SCL), GPIO_DRV_10_MA);
gpio_set_driving(GPIO(SPMI_P_SDA), GPIO_DRV_10_MA);
}