Attention is currently required from: Hung-Te Lin, Yidi Lin, Yu-Ping Wu.
Jarried Lin has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/85842?usp=email )
Change subject: soc/mediatek/mt8196: Add srclken_rc drivers ......................................................................
soc/mediatek/mt8196: Add srclken_rc drivers
Mt8196 use new RC mode with clk_buf driver, and need srclken_rc to send cmd.
TEST=Build pass. BUG=b:317009620
Signed-off-by: ot_song fan ot_song.fan@mediatek.corp-partner.google.com Change-Id: I40f8d2b12027955e6bd57b666e9f04c0116a0a93 --- M src/soc/mediatek/mt8196/Makefile.mk M src/soc/mediatek/mt8196/include/soc/addressmap.h A src/soc/mediatek/mt8196/include/soc/srclken_rc.h A src/soc/mediatek/mt8196/srclken_rc.c 4 files changed, 797 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/42/85842/1
diff --git a/src/soc/mediatek/mt8196/Makefile.mk b/src/soc/mediatek/mt8196/Makefile.mk index a079a05..2011b6b 100644 --- a/src/soc/mediatek/mt8196/Makefile.mk +++ b/src/soc/mediatek/mt8196/Makefile.mk @@ -43,6 +43,7 @@ romstage-y += ../common/pmif_clk.c pmif_clk.c romstage-y += ../common/pmif.c pmif_init.c romstage-y += pmif_spmi.c +romstage-y += srclken_rc.c
ramstage-$(CONFIG_ARM64_USE_ARM_TRUSTED_FIRMWARE) += ../common/bl31.c ramstage-y += ../common/dpm_v2.c diff --git a/src/soc/mediatek/mt8196/include/soc/addressmap.h b/src/soc/mediatek/mt8196/include/soc/addressmap.h index 8d0a4bb..209c290 100644 --- a/src/soc/mediatek/mt8196/include/soc/addressmap.h +++ b/src/soc/mediatek/mt8196/include/soc/addressmap.h @@ -148,6 +148,8 @@ SPM_BASE = IO_PHYS + 0x0C004000, SPM_PBUS_BASE = IO_PHYS + 0x0C00D000, RGU_BASE = IO_PHYS + 0x0C010000, + RC_BASE = IO_PHYS + 0x0C011000, + RC_STATE_BASE = IO_PHYS + 0x0C011100, GPT_BASE = IO_PHYS + 0x0C015000, VLP_CKSYS_BASE = IO_PHYS + 0x0C016000, PMIF_SPMI_P_BASE = IO_PHYS + 0x0C018000, diff --git a/src/soc/mediatek/mt8196/include/soc/srclken_rc.h b/src/soc/mediatek/mt8196/include/soc/srclken_rc.h new file mode 100644 index 0000000..08d0e30 --- /dev/null +++ b/src/soc/mediatek/mt8196/include/soc/srclken_rc.h @@ -0,0 +1,251 @@ +/* SPDX-License-Identifier: GPL-2.0-only OR MIT */ + +#ifndef __SOC_MEDIATEK_MT8196_INCLUDE_SOC_SRCLKEN_RC_H__ +#define __SOC_MEDIATEK_MT8196_INCLUDE_SOC_SRCLKEN_RC_H__ + +/*********************************************************************************** +** Definitions +************************************************************************************/ +/* Channel id: Update this enum for porting */ +enum chn_id { + CHN_SUSPEND = 0, + CHN_MD1, + CHN_MD2, + CHN_MD3, + CHN_MDRF, + CHN_MMWAVE = 5, + CHN_GPS, + CHN_PCIE_CONN1, + CHN_VCORE, + CHN_CONN_MCU, + CHN_COANT = 10, + CHN_NFC_CONN2, + CHN_SUSPEND2, + CHN_UFS_VREQ, + CHN_DCXO_L, + CHN_DCXO_H = 15, + CHN_UFS_2, + CHN_PCIE_2, + CHN_NFC_2, + CHN_EXT1, + CHN_EXT2 = 20, + CHN_EXT3, + CHN_T900, + CHN_RSV1, + CHN_RSV2, + CHN_RSV3 = 25, + CHN_RSV4, + CHN_RSV5, + CHN_RSV6, + CHN_RSV7, + CHN_RSV8 = 30, + CHN_RSV9, + MAX_CHN_NUM, +}; + +struct mtk_rc_regs { + u32 srclken_rc_cfg; + u32 rc_central_cfg1; + u32 rc_central_cfg2; + u32 rc_cmd_arb_cfg; + u32 rc_pmic_rcen_addr; + u32 rc_pmic_rcen_set_clr_addr; + u32 rc_dcxo_fpm_cfg; + u32 rc_central_cfg3; + u32 reserved1[14]; + u32 srclken_sw_con_cfg; + u32 rc_central_cfg4; + u32 reserved2; + u32 rc_debug_cfg; + u32 reserved3; + u32 reserved4; + u32 rc_central_cfg5; + u32 rc_central_cfg6; + u32 rcen_mt_m_cfg_0; + u32 rcen_mt_m_cfg_1; + u32 rcen_mt_p_cfg_0; + u32 rcen_mt_p_cfg_1; + u32 rcen_mt_cfg_0; + u32 reserved5[173]; + u32 central_cfg4_1; + u32 central_cfg6_1; + u32 central_cfg6_2; + u32 reserved6[39]; + u32 subsys_intf_cfg_fpm; + u32 reserved7[5]; + u32 src_pmrc_starter_bypass_cfg; + u32 src_pmrc_starter_disable_cfg; + u32 src_pmrc_multi_master_cfg; + u32 src_pmrc_starter_mask_cfg; + u32 src_pmrc_starter_turn_on_cnt_size; + u32 src_pmrc_starter_turn_off_cnt_size; + u32 reserved8[58]; + u32 rc_mxx_srclken_cfg[MAX_CHN_NUM]; +}; + +DEFINE_BIT(SW_RESET, 0) +DEFINE_BITFIELD(CG_32K_EN, 3, 1) +DEFINE_BIT(CG_FCLK_EN, 2) +DEFINE_BIT(CG_FCLK_FR_EN, 3) +DEFINE_BIT(MUX_FCLK_FR, 4) +DEFINE_BIT(RC_32K_DCM, 8) +DEFINE_BIT(SRCLKEN_RC_EN, 0) +DEFINE_BIT(RCEN_ISSUE_M, 1) +DEFINE_BIT(RC_SPI_ACTIVE, 2) +DEFINE_BIT(SRCLKEN_RC_EN_SEL, 3) +DEFINE_BITFIELD(VCORE_SETTLE_T, 7, 5) +DEFINE_BITFIELD(ULPOSC_SETTLE_T, 11, 8) +DEFINE_BITFIELD(NON_DCXO_SETTLE_T, 21, 12) +DEFINE_BITFIELD(DCXO_SETTLE_T, 31, 22) +DEFINE_BITFIELD(SRCVOLTEN_CTRL, 3, 0) +DEFINE_BITFIELD(VREQ_CTRL, 7, 4) +DEFINE_BIT(SRCVOLTEN_VREQ_SEL, 8) +DEFINE_BIT(SRCVOLTEN_VREQ_M, 9) +DEFINE_BIT(FORCE_SRCVOLTEN_OFF, 10) +DEFINE_BIT(FORCE_SRCVOLTEN_ON, 11) +DEFINE_BITFIELD(ULPOSC_CTRL_M, 15, 12) +DEFINE_BIT(FORCE_VCORE_RDY, 16) +DEFINE_BIT(FORCE_ULPOSC2ON, 17) +DEFINE_BIT(FORCE_ULPOSC_CLK_EN, 18) +DEFINE_BIT(FORCE_ULPOSC_ON, 19) +DEFINE_BIT(DIS_ULPOSC_RDY_CHK, 20) +DEFINE_BIT(PWRAP_SLP_CTRL_M, 21) +DEFINE_BIT(PWRAP_SLP_MUX_SEL, 25) +DEFINE_BIT(FORCE_PWRAP_ON, 26) +DEFINE_BIT(FORCE_PWRAP_AWK, 27) +DEFINE_BIT(NON_DCXO_REQ_FORCEON, 28) +DEFINE_BIT(NON_DCXO_REQ_FORCEOFF, 29) +DEFINE_BIT(DCXO_REQ_FORCEON, 30) +DEFINE_BIT(DCXO_REQ_FORCEOFF, 31) + +DEFINE_BITFIELD(SW_RC_EN, 12, 0) +DEFINE_BITFIELD(SW_RCEN_EN, 25, 13) +DEFINE_BIT(SW_DCXO_M_EN, 28) +DEFINE_BITFIELD(SW_DCXO_M, 31, 29) + +DEFINE_BITFIELD(DCXO_FPM_CTRL_M, 3, 0) +DEFINE_BIT(SRCVOLTEN_FPM_MSK_B, 4) +DEFINE_BITFIELD(SUB_SRCLKEN_FPM_MSK_B, 28, 16) + +DEFINE_BIT(TO_LPM_SETTLE_EN, 0) +DEFINE_BIT(BLK_SCP_DXCO_MD_TARGET, 1) +DEFINE_BIT(BLK_COANT_DXCO_MD_TARGET, 2) +DEFINE_BIT(TO_BBLPM_SETTLE_EN, 3) +DEFINE_BIT(TO_BBLPM_SETTLE_ND_EN, 4) +DEFINE_BITFIELD(TO_LPM_SETTLE_T, 21, 12) + +DEFINE_BIT(DCXO_SETTLE_BLK_EN, 1) +DEFINE_BIT(BYPASS_CMD_EN, 2) +DEFINE_BIT(SW_SRCLKEN_RC, 3) +DEFINE_BIT(SW_SRCLKEN_FPM, 4) +DEFINE_BIT(SW_SRCLKEN_BBLPM, 5) +DEFINE_BIT(XO_SOC_LINKAGE_EN, 6) +DEFINE_BIT(REQ_ACK_LOW_IMD_EN, 7) +DEFINE_BIT(SRCLKEN_TRACK_M_EN, 8) +DEFINE_BITFIELD(CNT_PRD_STEP, 11, 10) +DEFINE_BITFIELD(XO_STABLE_PRD, 21, 12) +DEFINE_BITFIELD(DCXO_STABLE_PRD, 31, 22) + +DEFINE_BIT(TACE_EN, 0) +DEFINE_BITFIELD(TIE_SYS_RDY, 4, 1) + +DEFINE_BITFIELD(KEEP_RC_SPI_ACTIVE, 12, 0) +DEFINE_BIT(PWRAP_VLD_FORCE, 16) +DEFINE_BIT(SLEEP_VLD_MODE, 17) +DEFINE_BIT(SCP_SLEEP_REQ_MODE, 18) +DEFINE_BIT(SLEEP_REQ_MODE, 20) +DEFINE_BIT(BYPASS_PMIF_M, 24) +DEFINE_BIT(BYPASS_PMIF_P, 25) + +DEFINE_BIT(TRACE_MODE_EN, 24) +DEFINE_BIT(DBG_STOP_PROT_EN, 28) + +DEFINE_BIT(SPMI_CMD_BYTE_CNT, 0) +DEFINE_BITFIELD(SPMI_M_SLV_ID, 8, 5) +DEFINE_BITFIELD(SPMI_P_SLV_ID, 12, 9) +DEFINE_BIT(SPMI_M_PMIF_ID, 17) +DEFINE_BIT(SPMI_P_PMIF_ID, 18) +DEFINE_BITFIELD(SPMI_M_CMD_TYPE, 21, 19) +DEFINE_BITFIELD(SPMI_P_CMD_TYPE, 22, 21) +DEFINE_BIT(SPMI_M_WRITE_EN, 23) +DEFINE_BIT(SPMI_P_WRITE_EN, 24) +DEFINE_BIT(BROADCAST_MODE_EN, 25) +DEFINE_BIT(MULTI_CMD_MODE_EN, 26) +DEFINE_BIT(DCXO_ENCODE, 27) +DEFINE_BIT(SPMI_M_FIRST, 28) +DEFINE_BITFIELD(REQ_TO_DCXO_MASK, 15, 0) +DEFINE_BITFIELD(PMIC_M_COUNTER_VAL, 3, 0) +DEFINE_BITFIELD(PMIC_P_COUNTER_VAL, 7, 4) +DEFINE_BITFIELD(SRCLKEN_FPM_MASK_B, 13, 0) +DEFINE_BITFIELD(SRCLKEN_BBLPM_MASK_B, 29, 16) +DEFINE_BIT(FPM_ACK, 1) +DEFINE_BIT(BBLPM_ACK, 3) + +struct mtk_rc_status_regs { + u32 reserved1[3]; + u32 rc_spi_sta_0; + u32 rc_pi_po_sta; + u32 reserved2[283]; + u32 rc_mxx_req_sta_0[MAX_CHN_NUM]; +}; + +#define REQ_TO_SPMI_P_MASK_SHFT 0 +#define BYPASS_DCXO_VOTE_L_SHIFT 0 +#define BYPASS_DCXO_VOTE_H_SHIFT 16 + +enum { + SW_SRCLKEN_FPM_MSK = 0x1, + SW_SRCLKEN_BBLPM_MSK = 0x1, +}; + +/* RC_CENTRAL_CFG2[8] */ +#define SRCLKENAO_MODE 0 +#define VREQ_MODE 1 + +/* RC_CENTRAL_CFG2[25] */ +#define RC_32K 0 +#define RC_ULPOSC1 1 + +/* Signal Control Mode */ +#define MERGE_OR_MODE 0x0 +#define BYPASS_MODE 0x1 +#define MERGE_AND_MODE BIT(1) +#define BYPASS_RC_MODE (0x2 << 1) +#define BYPASS_OR_MODE 0x3 +#define BYPASS_OTHER_MODE (0x3 << 1) +#define ASYNC_MODE BIT(3) + +#define NO_REQ 0 +#define FPM_REQ BIT(4) +#define BBLPM_REQ BIT(5) + +enum rc_ctrl_m { + HW_MODE = 0, + SW_MODE = 1, + INIT_MODE = 0xff, +}; + +enum { + SRLCKEN_RC_BRINGUP = 0, + SRCLKEN_RC_DISABLE, + SRCLKEN_RC_ENABLE, + SRCLKEN_RC_SKIP, +}; + +struct subsys_rc_con { + unsigned int dcxo_prd; + unsigned int xo_prd; + unsigned int cnt_step; + unsigned int track_en; + unsigned int req_ack_imd_en; + unsigned int xo_soc_link_en; + unsigned int sw_bblpm; + unsigned int sw_fpm; + unsigned int sw_rc; + unsigned int bypass_cmd; + unsigned int dcxo_settle_blk_en; +}; + +int srclken_rc_init(void); + +#endif diff --git a/src/soc/mediatek/mt8196/srclken_rc.c b/src/soc/mediatek/mt8196/srclken_rc.c new file mode 100644 index 0000000..cf2215a --- /dev/null +++ b/src/soc/mediatek/mt8196/srclken_rc.c @@ -0,0 +1,543 @@ +/* SPDX-License-Identifier: GPL-2.0-only OR MIT */ + +#include <assert.h> +#include <console/console.h> +#include <delay.h> +#include <soc/addressmap.h> +#include <soc/clkbuf_ctl.h> +#include <soc/pmif.h> +#include <soc/pmif_common.h> +#include <soc/spmi.h> +#include <soc/srclken_rc.h> +#include <timer.h> + +static struct mtk_rc_regs *rc_regs = (struct mtk_rc_regs *)RC_BASE; +static struct mtk_rc_status_regs *rc_status_regs = (struct mtk_rc_status_regs *)RC_STATE_BASE; + +#define ACK_DELAY_US 10 +#define ACK_DELAY_TIMES 200 + +/* RC_CENTRAL_CFG1 setting */ +#define RC_CENTRAL_ENABLE_VAL 1 +#define RC_CENTRAL_DISABLE_VAL 0 + +/* register direct write */ +#define IS_SPI2PMIC_SET_CLR_VAL 0 +#define KEEP_RC_SPI_ACTIVE_VAL 1 +#define SRCLKEN_RC_EN_SEL_VAL 0 + +/* RC_CENTRAL_CFG1 settle time setting */ +#define VCORE_SETTLE_TIME_VAL 0x7 /* ~= 200us */ +#define ULPOSC_SETTLE_TIME_VAL 0x4 /* ~= ? 150us */ +#define NON_DCXO_SETTLE_TIME_VAL 0x1 /* 2^(step+5)*0x33*30.77ns~=400us */ +#define DCXO_SETTLE_TIME_VAL 0x41 /* 2^(step+5)*0x87*30.77ns~= 1063us */ + +/* RC_CENTRAL_CFG2 setting */ +/* use srlckenao to set vcore */ +#define SPI_TRIG_MODE SRCLKENAO_MODE +/* release vcore when spi request done */ +#define IS_SPI_DONE_RELEASE 0 +/* pmic spec under 200us */ +#define SPI_CLK_SRC RC_32K +/* RC_CENTRAL_CFG2 control mode */ +/* merge with spm */ +#define SRCLKENO_0_CTRL_M BYPASS_MODE +/* merge with vreq */ +#define VREQ_CTRL_M BYPASS_MODE +/* merge with ulposc */ +#define ULPOSC_CTRL_M_VAL BYPASS_MODE +/* merge with pwrap_scp */ +#define PWRAP_CTRL_M MERGE_OR_MODE + +/* RC_DCXO_FPM_CFG*/ +#define MD0_SRCLKENO_0_MASK_B 0 /* md0 control by pmrc */ +#define FULL_SET_HW_MODE 0 /* dcxo mode use pmrc_en */ +/* RC_DCXO_FPM_CFG control mode*/ +/* merge with spm */ +#define DCXO_FPM_CTRL_MODE (MERGE_OR_MODE | ASYNC_MODE) + +/* RC_CENTRAL_CFG5 */ +#define RC_SPMI_BYTE_LEN 0x1 /* 0: 2bytes, 1: 2 * 2bytes */ +#define PMIC_GROUP_ID 0xB + +/* pmrc_en address */ +/* default use this reg direct write */ +#define PMRC_CON0 0x190 +#define PMRC_CON0_SET 0x198 +#define PMRC_CON0_CLR 0x19A + +#define SW_BBLPM_HIGH 1 +#define SW_BBLPM_LOW 0 +#define SW_FPM_HIGH 1 +#define SW_FPM_LOW 0 +enum { + DXCO_SETTLE_BLK_EN = 1, + DXCO_SETTLE_BLK_DIS = 0, +}; + +#define REQ_ACK_IMD_EN 1 +#define REQ_ACK_IMD_DIS 0 + +#define SUB_CTRL_CON(_id, _dcxo_prd, _xo_prd, \ + _sw_bblpm, _sw_fpm, _sw_rc, \ + _req_ack_imd_en, _bypass_cmd, \ + _dcxo_settle_blk_en) \ + [_id] = { \ + .dcxo_prd = _dcxo_prd, \ + .xo_prd = _xo_prd, \ + .cnt_step = CENTROL_CNT_STEP, \ + .track_en = 0, \ + .req_ack_imd_en = _req_ack_imd_en, \ + .xo_soc_link_en = 0, \ + .sw_bblpm = _sw_bblpm, \ + .sw_fpm = _sw_fpm, \ + .sw_rc = _sw_rc, \ + .bypass_cmd = _bypass_cmd, \ + .dcxo_settle_blk_en = _dcxo_settle_blk_en, \ + } + +/* Init as SW FPM mode */ +#define SUB_CTRL_CON_INIT(_id, _dcxo_prd, _xo_prd, \ + _req_ack_imd_en, _bypass_cmd, \ + _dcxo_settle_blk_en) \ + SUB_CTRL_CON(_id, _dcxo_prd, _xo_prd, \ + SW_BBLPM_LOW, SW_FPM_HIGH, SW_MODE, \ + _req_ack_imd_en, _bypass_cmd, \ + _dcxo_settle_blk_en) + +/* Init as SW LPM mode */ +#define SUB_CTRL_CON_NO_INIT(_id, _dcxo_prd, _xo_prd, \ + _req_ack_imd_en, _bypass_cmd, \ + _dcxo_settle_blk_en) \ + SUB_CTRL_CON(_id, _dcxo_prd, _xo_prd, \ + SW_BBLPM_LOW, SW_FPM_LOW, SW_MODE, \ + _req_ack_imd_en, _bypass_cmd, \ + _dcxo_settle_blk_en) + +/* Normal init, SW FPM mode */ +#define SUB_CTRL_CON_EN(_id, _xo_prd, _req_ack_imd_en) \ + SUB_CTRL_CON_INIT(_id, \ + DCXO_STABLE_TIME, _xo_prd, \ + _req_ack_imd_en, 0, DXCO_SETTLE_BLK_EN) + +/* XO/DCXO settle time=0, bypass cmd */ +#define SUB_CTRL_CON_DIS(_id) \ + SUB_CTRL_CON_INIT(_id, \ + DCXO_STABLE_TIME, 0, REQ_ACK_IMD_EN, \ + 0x1, DXCO_SETTLE_BLK_DIS) + +/* Normal init, SW LPM mode */ +#define SUB_CTRL_CON_UNUSE(_id, _xo_prd, _req_ack_imd_en) \ + SUB_CTRL_CON_NO_INIT(_id, \ + DCXO_STABLE_TIME, _xo_prd, \ + _req_ack_imd_en, 0, DXCO_SETTLE_BLK_EN) + + +/* Porting starting from here */ +/* MXX_SRCLKEN_CFG settle time setting */ +#define CENTROL_CNT_STEP 0x3 /* Fix in 3 */ +#define DCXO_STABLE_TIME 0x70 /* ~= 700us */ +#define XO_DEFAULT_STABLE_TIME 0x29 /* ~= 400us */ +#define XO_MD0_STABLE_TIME 0x15 /* ~= 200us */ +#define XO_MD1_STABLE_TIME 0x15 /* ~= 200us */ +#define XO_MD2_STABLE_TIME 0x33 /* ~= 500us */ +#define XO_MDRF_STABLE_TIME 0x3D /* ~= 600us */ +#define VCORE_STABLE_TIME 0x15 /* ~= 200us */ + +/* SUBSYS_INTF_CFG_FPM */ +#define SUB_FPM_SET (BIT(CHN_SUSPEND) | BIT(CHN_MD1) \ + | BIT(CHN_MD2) | BIT(CHN_MD3) \ + | BIT(CHN_MDRF) | BIT(CHN_MMWAVE) \ + | BIT(CHN_GPS) | BIT(CHN_PCIE_CONN1) \ + | BIT(CHN_VCORE) | BIT(CHN_CONN_MCU) \ + | BIT(CHN_COANT) | BIT(CHN_NFC_CONN2) \ + | BIT(CHN_SUSPEND2) | BIT(CHN_UFS_VREQ)) + +/* first try to switch fpm */ +#define INIT_SUBSYS_FPM2LPM (1 << CHN_GPS | 1 << CHN_VCORE \ + | 1 << CHN_CONN_MCU | 1 << CHN_COANT \ + | 1 << CHN_NFC_CONN2) + +/* CFG6_1, all 1 means RC M & P used */ +#define REQ_TO_SPMI_P_SUBSYS 0xFFFFFFFF +/* subsys 8-vcore on/off & subsys 11-pmic power not join DCXO vote*/ +#define SUBSYS_EN_L 0x110E +#define SUBSYS_EN_H 0x0000 + +#define CHN_MASK (BIT(CHN_DCXO_L) | BIT(CHN_DCXO_H)) +#define CHN_NOT_SUPPORT(i) (BIT(i) & CHN_MASK) + +/* after polling ack done, switch to HW mode */ +#define INIT_SUBSYS_TO_HW (1 << CHN_SUSPEND | 1 << CHN_MD1 \ + | 1 << CHN_MD2 | 1 << CHN_MD3 \ + | 1 << CHN_MDRF | 1 << CHN_MMWAVE \ + | 1 << CHN_GPS | 1 << CHN_PCIE_CONN1 \ + | 1 << CHN_CONN_MCU \ + | 1 << CHN_COANT | 1 << CHN_NFC_CONN2 \ + | 1 << CHN_SUSPEND2 | 1 << CHN_UFS_VREQ) + +static struct subsys_rc_con rc_ctrl[MAX_CHN_NUM] = { + SUB_CTRL_CON_EN(CHN_SUSPEND, XO_DEFAULT_STABLE_TIME, REQ_ACK_IMD_EN), + /* CFG[2] = 0x1 for bypass waiting DCXO settle time */ + /* usually also need to set CFG6_2 not involve FPM vote*/ + SUB_CTRL_CON_INIT(CHN_MD1, DCXO_STABLE_TIME, XO_MD0_STABLE_TIME, REQ_ACK_IMD_EN, + 0x1, DXCO_SETTLE_BLK_EN), + SUB_CTRL_CON_INIT(CHN_MD2, DCXO_STABLE_TIME, XO_MD1_STABLE_TIME, REQ_ACK_IMD_EN, + 0x1, DXCO_SETTLE_BLK_EN), + SUB_CTRL_CON_INIT(CHN_MD3, DCXO_STABLE_TIME, XO_MD2_STABLE_TIME, REQ_ACK_IMD_EN, + 0x1, DXCO_SETTLE_BLK_EN), + SUB_CTRL_CON_EN(CHN_MDRF, XO_MDRF_STABLE_TIME, REQ_ACK_IMD_EN), + SUB_CTRL_CON_EN(CHN_MMWAVE, XO_DEFAULT_STABLE_TIME, REQ_ACK_IMD_EN), + SUB_CTRL_CON_EN(CHN_GPS, XO_DEFAULT_STABLE_TIME, REQ_ACK_IMD_EN), + SUB_CTRL_CON_EN(CHN_PCIE_CONN1, XO_DEFAULT_STABLE_TIME, REQ_ACK_IMD_EN), + SUB_CTRL_CON_INIT(CHN_VCORE, DCXO_STABLE_TIME, VCORE_STABLE_TIME, REQ_ACK_IMD_EN, + 0x1, DXCO_SETTLE_BLK_EN), + SUB_CTRL_CON_EN(CHN_CONN_MCU, XO_DEFAULT_STABLE_TIME, REQ_ACK_IMD_EN), + SUB_CTRL_CON_DIS(CHN_COANT), + SUB_CTRL_CON_EN(CHN_NFC_CONN2, XO_DEFAULT_STABLE_TIME, REQ_ACK_IMD_EN), + SUB_CTRL_CON_INIT(CHN_SUSPEND2, DCXO_STABLE_TIME, VCORE_STABLE_TIME, REQ_ACK_IMD_EN, + 0x1, DXCO_SETTLE_BLK_EN), + SUB_CTRL_CON_EN(CHN_UFS_VREQ, XO_DEFAULT_STABLE_TIME, REQ_ACK_IMD_EN), + SUB_CTRL_CON_DIS(CHN_DCXO_L), + SUB_CTRL_CON_DIS(CHN_DCXO_H), + SUB_CTRL_CON_UNUSE(CHN_UFS_2, XO_DEFAULT_STABLE_TIME, REQ_ACK_IMD_EN), + SUB_CTRL_CON_UNUSE(CHN_PCIE_2, XO_DEFAULT_STABLE_TIME, REQ_ACK_IMD_EN), + SUB_CTRL_CON_UNUSE(CHN_NFC_2, XO_DEFAULT_STABLE_TIME, REQ_ACK_IMD_EN), + SUB_CTRL_CON_UNUSE(CHN_EXT1, XO_DEFAULT_STABLE_TIME, REQ_ACK_IMD_EN), + SUB_CTRL_CON_UNUSE(CHN_EXT2, XO_DEFAULT_STABLE_TIME, REQ_ACK_IMD_EN), + SUB_CTRL_CON_UNUSE(CHN_EXT3, XO_DEFAULT_STABLE_TIME, REQ_ACK_IMD_EN), + SUB_CTRL_CON_UNUSE(CHN_T900, XO_DEFAULT_STABLE_TIME, REQ_ACK_IMD_EN), + SUB_CTRL_CON_UNUSE(CHN_RSV1, XO_DEFAULT_STABLE_TIME, REQ_ACK_IMD_EN), + SUB_CTRL_CON_UNUSE(CHN_RSV2, XO_DEFAULT_STABLE_TIME, REQ_ACK_IMD_EN), + SUB_CTRL_CON_UNUSE(CHN_RSV3, XO_DEFAULT_STABLE_TIME, REQ_ACK_IMD_EN), + SUB_CTRL_CON_UNUSE(CHN_RSV4, XO_DEFAULT_STABLE_TIME, REQ_ACK_IMD_EN), + SUB_CTRL_CON_UNUSE(CHN_RSV5, XO_DEFAULT_STABLE_TIME, REQ_ACK_IMD_EN), + SUB_CTRL_CON_UNUSE(CHN_RSV6, XO_DEFAULT_STABLE_TIME, REQ_ACK_IMD_EN), + SUB_CTRL_CON_UNUSE(CHN_RSV7, XO_DEFAULT_STABLE_TIME, REQ_ACK_IMD_EN), + SUB_CTRL_CON_UNUSE(CHN_RSV8, XO_DEFAULT_STABLE_TIME, REQ_ACK_IMD_EN), + SUB_CTRL_CON_UNUSE(CHN_RSV9, XO_DEFAULT_STABLE_TIME, REQ_ACK_IMD_EN) +}; + +static void rc_dump_reg_info(void) +{ + u32 ch; + + printk(BIOS_INFO, "RG_DEBUG_CFG[24] : 0x%#lx\n", + (read32(&rc_regs->rc_debug_cfg) & BIT(24)) >> 24); + printk(BIOS_INFO, "RG_SRCLKEN_RC_CFG : 0x%x\n", read32(&rc_regs->srclken_rc_cfg)); + + for (ch = 0; ch < MAX_CHN_NUM; ch++) { + if (CHN_NOT_SUPPORT(ch)) + continue; + printk(BIOS_INFO, "RG_M0%d_SRCLKEN_CFG : 0x%#x\n", + ch, read32(&rc_regs->rc_mxx_srclken_cfg[ch])); + } + + printk(BIOS_INFO, "RG_SRCLKEN_SW_CON_CFG : 0x%x\n", + read32(&rc_regs->srclken_sw_con_cfg)); + printk(BIOS_INFO, "RG_PMIC_RCEN_ADDR : 0x%x\n", read32(&rc_regs->rc_pmic_rcen_addr)); + printk(BIOS_INFO, "RG_PMIC_RCEN_SET_CLR_ADDR : 0x%x\n", + read32(&rc_regs->rc_pmic_rcen_set_clr_addr)); + printk(BIOS_INFO, "RG_CMD_ARB_CFG : 0x%x\n", read32(&rc_regs->rc_cmd_arb_cfg)); + printk(BIOS_INFO, "RG_CENTRAL_CFG1 : 0x%x\n", read32(&rc_regs->rc_central_cfg1)); + printk(BIOS_INFO, "RG_CENTRAL_CFG2 : 0x%x\n", read32(&rc_regs->rc_central_cfg2)); + printk(BIOS_INFO, "RG_CENTRAL_CFG3 : 0x%x\n", read32(&rc_regs->rc_central_cfg3)); + printk(BIOS_INFO, "RG_CENTRAL_CFG5 : 0x%x\n", read32(&rc_regs->rc_central_cfg5)); + printk(BIOS_INFO, "RG_CENTRAL_CFG6_1 : 0x%x\n", read32(&rc_regs->central_cfg6_1)); + printk(BIOS_INFO, "RG_CENTRAL_CFG6_2 : 0x%x\n", read32(&rc_regs->central_cfg6_2)); + printk(BIOS_INFO, "RG_DCXO_FPM_CFG : 0x%x\n", read32(&rc_regs->rc_dcxo_fpm_cfg)); + printk(BIOS_INFO, "SUBSYS_INTF_CFG_FPM : 0x%x\n", + read32(&rc_regs->subsys_intf_cfg_fpm)); + printk(BIOS_INFO, "RG_CENTRAL_CFG4 : 0x%x\n", read32(&rc_regs->rc_central_cfg4)); + printk(BIOS_INFO, "RG_CENTRAL_CFG4_1 : 0x%x\n", read32(&rc_regs->central_cfg4_1)); + printk(BIOS_INFO, "RG_SRC_PMIC_MULTI_MASTER_CFG : 0x%x\n", + read32(&rc_regs->src_pmrc_multi_master_cfg)); + printk(BIOS_INFO, "RG_SRC_PMRC_STARTER_DISABLE_CFG : 0x%x\n", + read32(&rc_regs->src_pmrc_starter_disable_cfg)); + printk(BIOS_INFO, "RG_SRC_PMRC_STARTER_MASK_CFG : 0x%x\n", + read32(&rc_regs->src_pmrc_starter_mask_cfg)); + printk(BIOS_INFO, "RG_SRC_PMRC_STARTER_BYPASS_CFG : 0x%x\n", + read32(&rc_regs->src_pmrc_starter_bypass_cfg)); + printk(BIOS_INFO, "RG_SRC_PMRC_STARTER_TURN_ON_CNT_SIZE : 0x%x\n", + read32(&rc_regs->src_pmrc_starter_turn_on_cnt_size)); + printk(BIOS_INFO, "RG_SRC_PMRC_STARTER_TURN_OFF_CNT_SIZE : 0x%x\n", + read32(&rc_regs->src_pmrc_starter_turn_off_cnt_size)); + /* skip print RC_Mxx_REQ_STA_0 because code flow ASSERT already */ + printk(BIOS_INFO, "RC_SPI_STA_0:0x%x\n", read32(&rc_status_regs->rc_spi_sta_0)); + printk(BIOS_INFO, "RC_PI_PO_STA:0x%x\n", read32(&rc_status_regs->rc_pi_po_sta)); +} + +/* RC initial flow and relative setting */ +static void rc_ctrl_mode_switch(enum chn_id id, enum rc_ctrl_m mode) +{ + ASSERT(id < MAX_CHN_NUM); + + switch (mode) { + case INIT_MODE: + SET32_BITFIELDS(&rc_regs->rc_mxx_srclken_cfg[id], + DCXO_SETTLE_BLK_EN, rc_ctrl[id].dcxo_settle_blk_en, + BYPASS_CMD_EN, rc_ctrl[id].bypass_cmd, + SW_SRCLKEN_RC, rc_ctrl[id].sw_rc, + SW_SRCLKEN_FPM, rc_ctrl[id].sw_fpm, + SW_SRCLKEN_BBLPM, rc_ctrl[id].sw_bblpm, + XO_SOC_LINKAGE_EN, rc_ctrl[id].xo_soc_link_en, + REQ_ACK_LOW_IMD_EN, rc_ctrl[id].req_ack_imd_en, + SRCLKEN_TRACK_M_EN, rc_ctrl[id].track_en, + CNT_PRD_STEP, rc_ctrl[id].cnt_step, + XO_STABLE_PRD, rc_ctrl[id].xo_prd, + DCXO_STABLE_PRD, rc_ctrl[id].dcxo_prd); + break; + case SW_MODE: + SET32_BITFIELDS(&rc_regs->rc_mxx_srclken_cfg[id], SW_SRCLKEN_RC, 1); + break; + case HW_MODE: + SET32_BITFIELDS(&rc_regs->rc_mxx_srclken_cfg[id], SW_SRCLKEN_RC, 0); + break; + default: + return; + } + + printk(BIOS_INFO, "M0%d: 0x%x\n", id, read32(&rc_regs->rc_mxx_srclken_cfg[id])); +} + +/* RC subsys FPM control*/ +static void rc_ctrl_fpm_switch(enum chn_id id, unsigned int mode) +{ + ASSERT(id < MAX_CHN_NUM); + + if (mode == SW_FPM_HIGH) + SET32_BITFIELDS(&rc_regs->rc_mxx_srclken_cfg[id], SW_SRCLKEN_FPM, 1); + else if (mode == SW_FPM_LOW) + SET32_BITFIELDS(&rc_regs->rc_mxx_srclken_cfg[id], SW_SRCLKEN_FPM, 0); + else + return; + + rc_ctrl[id].sw_fpm = mode; + + printk(BIOS_INFO, "M0%d FPM SWITCH: 0x%x\n", + id, read32(&rc_regs->rc_mxx_srclken_cfg[id])); +} + + +static void rc_init_subsys_hw_mode(void) +{ + unsigned int ch; + + for (ch = 0; ch < MAX_CHN_NUM; ch++) { + if (CHN_NOT_SUPPORT(ch)) + continue; + if (INIT_SUBSYS_TO_HW & BIT(ch)) + rc_ctrl_mode_switch(ch, HW_MODE); + } +} + +static void rc_init_subsys_lpm(void) +{ + unsigned int ch; + + for (ch = 0; ch < MAX_CHN_NUM; ch++) { + if (CHN_NOT_SUPPORT(ch)) + continue; + if (INIT_SUBSYS_FPM2LPM & BIT(ch)) + rc_ctrl_fpm_switch(ch, SW_FPM_LOW); + } +} + +static void rc_ctrl_mode_switch_init(void) +{ + unsigned int ch; + + for (ch = 0; ch < MAX_CHN_NUM; ch++) { + if (CHN_NOT_SUPPORT(ch)) + continue; + rc_ctrl_mode_switch(ch, INIT_MODE); + } +} + +static int polling_rc_chn_ack(unsigned int chn, unsigned int state) +{ + if (!retry(ACK_DELAY_TIMES, (read32(&rc_status_regs->rc_mxx_req_sta_0[chn]) & 0xa) == state, udelay(ACK_DELAY_US))) { + printk(BIOS_INFO, "%s: polling M%u status fail(R:0x%x)(C:0x%x)(PMRC:0x%x)\n", + __func__, + chn, + read32(&rc_status_regs->rc_mxx_req_sta_0[chn]), + read32(&rc_regs->rc_mxx_srclken_cfg[chn]), + clk_buf_get_pmrc_en0()); + return -1; + } + + return 0; +} + +int srclken_rc_init(void) +{ + unsigned int ch; + unsigned int state; + int ret = 0; + + /* enable srclken_rc debug trace */ + SET32_BITFIELDS(&rc_regs->rc_debug_cfg, TRACE_MODE_EN, 0x1); + + /* Set SW RESET 1 */ + SET32_BITFIELDS(&rc_regs->srclken_rc_cfg, SW_RESET, 0x1); + + /* Wait 100us */ + dsb(); + udelay(100); + + /* Set SW CG 1 */ + SET32_BITFIELDS(&rc_regs->srclken_rc_cfg, CG_32K_EN, 0x7); + + /* Wait 100us */ + dsb(); + udelay(100); + + /* Set Clock Mux*/ + SET32_BITFIELDS(&rc_regs->srclken_rc_cfg, MUX_FCLK_FR, 0x1); + + /* Set req_filter m00~m13 as default SW_FPM */ + rc_ctrl_mode_switch_init(); + + /* enable sw trace & pmrc_o0 sel */ + SET32_BITFIELDS(&rc_regs->srclken_sw_con_cfg, TACE_EN, 0x1); + SET32_BITFIELDS(&rc_regs->srclken_sw_con_cfg, TIE_SYS_RDY, 0x1); + + /* Set PMIC addr for SPI CMD */ + write32(&rc_regs->rc_pmic_rcen_addr, PMRC_CON0); + + write32(&rc_regs->rc_pmic_rcen_set_clr_addr, PMRC_CON0); + + write32(&rc_regs->rc_cmd_arb_cfg, 0); + + /* CFG1 setting for spi cmd config */ + write32(&rc_regs->rc_central_cfg1, + _BF_VALUE(DCXO_SETTLE_T, DCXO_SETTLE_TIME_VAL) | + _BF_VALUE(NON_DCXO_SETTLE_T, NON_DCXO_SETTLE_TIME_VAL) | + _BF_VALUE(ULPOSC_SETTLE_T, ULPOSC_SETTLE_TIME_VAL) | + _BF_VALUE(VCORE_SETTLE_T, VCORE_SETTLE_TIME_VAL) | + _BF_VALUE(SRCLKEN_RC_EN_SEL, SRCLKEN_RC_EN_SEL_VAL) | + _BF_VALUE(RC_SPI_ACTIVE, KEEP_RC_SPI_ACTIVE_VAL) | + _BF_VALUE(RCEN_ISSUE_M, IS_SPI2PMIC_SET_CLR_VAL) | + _BF_VALUE(SRCLKEN_RC_EN, RC_CENTRAL_DISABLE_VAL)); + + /* CFG2 setting for signal mode of each control mux */ + write32(&rc_regs->rc_central_cfg2, + _BF_VALUE(PWRAP_SLP_MUX_SEL, SPI_CLK_SRC) | + _BF_VALUE(PWRAP_SLP_CTRL_M, PWRAP_CTRL_M) | + _BF_VALUE(ULPOSC_CTRL_M, ULPOSC_CTRL_M_VAL) | + _BF_VALUE(SRCVOLTEN_VREQ_M, IS_SPI_DONE_RELEASE) | + _BF_VALUE(SRCVOLTEN_VREQ_SEL, SPI_TRIG_MODE) | + _BF_VALUE(VREQ_CTRL, VREQ_CTRL_M) | + _BF_VALUE(SRCVOLTEN_CTRL, SRCLKENO_0_CTRL_M)); + + write32(&rc_regs->rc_central_cfg3, + _BF_VALUE(TO_LPM_SETTLE_T, 0x4) | + _BF_VALUE(TO_BBLPM_SETTLE_EN, 0x1) | + _BF_VALUE(BLK_COANT_DXCO_MD_TARGET, 0x1) | + _BF_VALUE(BLK_SCP_DXCO_MD_TARGET, 0x1) | + _BF_VALUE(TO_LPM_SETTLE_EN, 0x1)); + + /* broadcast/multi-cmd setting */ + write32(&rc_regs->rc_central_cfg5, + _BF_VALUE(SPMI_CMD_BYTE_CNT, RC_SPMI_BYTE_LEN) | + _BF_VALUE(SPMI_M_SLV_ID, PMIC_GROUP_ID) | + _BF_VALUE(SPMI_P_SLV_ID, PMIC_GROUP_ID) | + _BF_VALUE(SPMI_P_PMIF_ID, 0x1) | + _BF_VALUE(SPMI_M_CMD_TYPE, 0x3) | /* SPMI Burst write */ + _BF_VALUE(SPMI_P_CMD_TYPE, 0x3) | /* SPMI Burst write */ + _BF_VALUE(SPMI_M_WRITE_EN, 0x1) | + _BF_VALUE(SPMI_P_WRITE_EN, 0x1) | + _BF_VALUE(BROADCAST_MODE_EN, 0x1) | + _BF_VALUE(DCXO_ENCODE, 0x1) | /* DCXO 3bits --> 2bits */ + _BF_VALUE(SPMI_M_FIRST, 0x1) | + BIT(29)); /* Setting: [29:30] = 1 means send 2 bytes to pmif*/ + + /* CFG6-1 = 0x11111111 */ + write32(&rc_regs->central_cfg6_1, + REQ_TO_SPMI_P_SUBSYS << REQ_TO_SPMI_P_MASK_SHFT); + + /* CFG6-2 = 0x00001100 */ + write32(&rc_regs->central_cfg6_2, + SUBSYS_EN_L << BYPASS_DCXO_VOTE_L_SHIFT | + SUBSYS_EN_H << BYPASS_DCXO_VOTE_H_SHIFT); + + /* Set srclkeno_0/conn_bt as factor to allow dcxo change to FPM */ + write32(&rc_regs->rc_dcxo_fpm_cfg, + _BF_VALUE(SUB_SRCLKEN_FPM_MSK_B, FULL_SET_HW_MODE) | + _BF_VALUE(SRCVOLTEN_FPM_MSK_B, MD0_SRCLKENO_0_MASK_B) | + _BF_VALUE(DCXO_FPM_CTRL_M, DCXO_FPM_CTRL_MODE)); + + /* Set fpm channel */ + write32(&rc_regs->subsys_intf_cfg_fpm, + _BF_VALUE(SRCLKEN_FPM_MASK_B, SUB_FPM_SET)); + + /* Trigger srclken_rc enable */ + SET32_BITFIELDS(&rc_regs->rc_central_cfg1, SRCLKEN_RC_EN, 0x1); + + /* use PMIF_M + PMIF_P */ + write32(&rc_regs->rc_central_cfg4, + _BF_VALUE(SLEEP_VLD_MODE, 0x1) | _BF_VALUE(PWRAP_VLD_FORCE, 0x1)); + + /* CFG4_1: extension CFG4[0:15] */ + write32(&rc_regs->central_cfg4_1, + _BF_VALUE(KEEP_RC_SPI_ACTIVE, 0x800)); + + /* Wait 100us */ + dsb(); + udelay(100); + + /* Set SW RESET 0 */ + SET32_BITFIELDS(&rc_regs->srclken_rc_cfg, SW_RESET, 0); + + /* Wait 100us */ + dsb(); + udelay(100); + + /* Set SW CG 0 */ + SET32_BITFIELDS(&rc_regs->srclken_rc_cfg, CG_32K_EN, 0); + + /* Wait 500us */ + dsb(); + udelay(500); + + /* Set req_filter m00~m31 FPM to LPM, hack original rc_ctrl[]*/ + rc_init_subsys_lpm(); + + /* Polling ACK of Initial Subsys Input */ + for (ch = 0; ch < MAX_CHN_NUM; ch++) { + if (CHN_NOT_SUPPORT(ch)) + continue; + + state = (rc_ctrl[ch].sw_fpm & SW_SRCLKEN_FPM_MSK) << 1 | + (rc_ctrl[ch].sw_bblpm & SW_SRCLKEN_BBLPM_MSK) << 3; + + ret = polling_rc_chn_ack(ch, state); + ASSERT(!ret); + } + + /* Set req_filter m00~m31 */ + rc_init_subsys_hw_mode(); + + /* [1] = 1 means pmrc7,11,13 mux choose non multi master */ + write32(&rc_regs->src_pmrc_multi_master_cfg, 0x00000002); + + /* [0] = 1 means disable pmic starter */ + write32(&rc_regs->src_pmrc_starter_disable_cfg, 0x00000001); + write32(&rc_regs->src_pmrc_starter_mask_cfg, 0x00000000); + + /* pmrc8 & pmrc12 : bypass trigger pmic starter */ + write32(&rc_regs->src_pmrc_starter_bypass_cfg, 0x00001100); + + /* 92E ---> 90us */ + write32(&rc_regs->src_pmrc_starter_turn_on_cnt_size, 0x0000092E); + + /* 92E ---> 90us */ + write32(&rc_regs->src_pmrc_starter_turn_off_cnt_size, 0x0000092E); + + /* write 0 to release force pmic req signal */ + SET32_BITFIELDS(&rc_regs->rc_central_cfg4, PWRAP_VLD_FORCE, 0); + + rc_dump_reg_info(); + + return ret; +}