From ec39cb3a80c13dd385810f2b004819652f8cc8da Mon Sep 17 00:00:00 2001 From: Yuchen Huang Date: Wed, 23 Sep 2020 20:41:19 +0800 Subject: soc/mediatek/mt8192: add clkbuf and srclken_rc MT6359P driver Add clkbuf and srclken_rc init for low power. Reference datasheet: Document No: RH-D-2018-0205. TEST=boot asurada Signed-off-by: Ran Bi Change-Id: I947bf14df7a307bf359c590c2a20265882b3f1be Reviewed-on: https://review.coreboot.org/c/coreboot/+/46878 Tested-by: build bot (Jenkins) Reviewed-by: Yu-Ping Wu --- src/soc/mediatek/mt8192/Kconfig | 7 + src/soc/mediatek/mt8192/Makefile.inc | 1 + src/soc/mediatek/mt8192/bootblock.c | 4 + src/soc/mediatek/mt8192/clkbuf.c | 139 ++++++++ src/soc/mediatek/mt8192/include/soc/addressmap.h | 2 + src/soc/mediatek/mt8192/include/soc/clkbuf.h | 69 ++++ src/soc/mediatek/mt8192/include/soc/pmif.h | 31 ++ src/soc/mediatek/mt8192/include/soc/rtc.h | 14 - src/soc/mediatek/mt8192/include/soc/srclken_rc.h | 191 +++++++++++ src/soc/mediatek/mt8192/pmif.c | 114 +++++++ src/soc/mediatek/mt8192/rtc.c | 33 +- src/soc/mediatek/mt8192/srclken_rc.c | 388 +++++++++++++++++++++++ 12 files changed, 947 insertions(+), 46 deletions(-) create mode 100644 src/soc/mediatek/mt8192/clkbuf.c create mode 100644 src/soc/mediatek/mt8192/include/soc/clkbuf.h create mode 100644 src/soc/mediatek/mt8192/include/soc/srclken_rc.h create mode 100644 src/soc/mediatek/mt8192/srclken_rc.c (limited to 'src/soc/mediatek') diff --git a/src/soc/mediatek/mt8192/Kconfig b/src/soc/mediatek/mt8192/Kconfig index fd0a4cdb8d..e2d7eeac13 100644 --- a/src/soc/mediatek/mt8192/Kconfig +++ b/src/soc/mediatek/mt8192/Kconfig @@ -82,4 +82,11 @@ config FLASH_DUAL_READ When this option is enabled, the flash controller provides the ability to dual read mode. +config SRCLKEN_RC_SUPPORT + bool + default y + help + This option enables clock buffer remote controller module + to control PMIC 26MHz clock output. + endif diff --git a/src/soc/mediatek/mt8192/Makefile.inc b/src/soc/mediatek/mt8192/Makefile.inc index ce94a46231..ad8b3d984f 100644 --- a/src/soc/mediatek/mt8192/Makefile.inc +++ b/src/soc/mediatek/mt8192/Makefile.inc @@ -2,6 +2,7 @@ ifeq ($(CONFIG_SOC_MEDIATEK_MT8192),y) bootblock-y += ../common/auxadc.c bootblock-y += bootblock.c +bootblock-y += clkbuf.c srclken_rc.c bootblock-y += eint_event.c bootblock-y += ../common/flash_controller.c bootblock-y += ../common/gpio.c gpio.c diff --git a/src/soc/mediatek/mt8192/bootblock.c b/src/soc/mediatek/mt8192/bootblock.c index 1c95d65c94..0249b15627 100644 --- a/src/soc/mediatek/mt8192/bootblock.c +++ b/src/soc/mediatek/mt8192/bootblock.c @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ #include +#include #include #include #include @@ -8,6 +9,7 @@ #include #include #include +#include #include void bootblock_soc_init(void) @@ -18,6 +20,8 @@ void bootblock_soc_init(void) mtk_pmif_init(); mt6359p_init(); mt6315_init(); + srclken_rc_init(); + clk_buf_init(); rtc_boot(); unmask_eint_event_mask(); } diff --git a/src/soc/mediatek/mt8192/clkbuf.c b/src/soc/mediatek/mt8192/clkbuf.c new file mode 100644 index 0000000000..83fdb92067 --- /dev/null +++ b/src/soc/mediatek/mt8192/clkbuf.c @@ -0,0 +1,139 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include +#include +#include +#include +#include + + +#define BUFTAG "[CLKBUF]" +#define buf_info(fmt, arg ...) printk(BIOS_INFO, BUFTAG "%s,%d: " fmt, \ + __func__, __LINE__, ## arg) + +#define _buf_clrset32_impl(addr, clear, set) \ + buf_write(addr, (buf_read(addr) & ~((uint32_t)(clear))) | (set)) + +#define BUF_SET_FIELDS(addr, ...) \ + _BF_IMPL(_buf_clrset32_impl, addr, __VA_ARGS__) +#define BUF_READ_FIELD(addr, name) \ + EXTRACT_BITFIELD(buf_read(addr), name) + +#define PMIC_CW00_INIT_VAL 0x4005 /* 0100 0000 0000 0101 */ +#define PMIC_CW09_INIT_VAL 0x01F0 /* 0000 0001 1111 0000 */ + +static struct pmif *pmif_arb; + +static u32 buf_read(u32 addr) +{ + u32 rdata; + + if (pmif_arb == NULL) + pmif_arb = get_pmif_controller(PMIF_SPI, 0); + pmif_arb->read(pmif_arb, 0, addr, &rdata); + + return rdata; +} + +static void buf_write(u32 addr, u32 wdata) +{ + if (pmif_arb == NULL) + pmif_arb = get_pmif_controller(PMIF_SPI, 0); + pmif_arb->write(pmif_arb, 0, addr, wdata); +} + +static void dump_clkbuf_log(void) +{ + u32 pmic_cw00, pmic_cw09, pmic_cw12, pmic_cw13, pmic_cw15, pmic_cw19, + top_spi_con1, ldo_vrfck_op_en, ldo_vbbck_op_en, ldo_vrfck_en, + ldo_vbbck_en, vrfck_hv_en; + + pmic_cw00 = BUF_READ_FIELD(PMIC_RG_DCXO_CW00, PMIC_REG_COMMON); + pmic_cw09 = BUF_READ_FIELD(PMIC_RG_DCXO_CW09, PMIC_REG_COMMON); + pmic_cw12 = BUF_READ_FIELD(PMIC_RG_DCXO_CW12, PMIC_REG_COMMON); + pmic_cw13 = BUF_READ_FIELD(PMIC_RG_DCXO_CW13, PMIC_REG_COMMON); + pmic_cw15 = BUF_READ_FIELD(PMIC_RG_DCXO_CW15, PMIC_REG_COMMON); + pmic_cw19 = BUF_READ_FIELD(PMIC_RG_DCXO_CW19, PMIC_REG_COMMON); + buf_info("DCXO_CW00/09/12/13/15/19=%#x %#x %#x %#x %#x %#x\n", + pmic_cw00, pmic_cw09, pmic_cw12, + pmic_cw13, pmic_cw15, pmic_cw19); + + top_spi_con1 = BUF_READ_FIELD(PMIC_RG_TOP_SPI_CON1, PMIC_RG_SRCLKEN_IN3_EN); + ldo_vrfck_op_en = BUF_READ_FIELD(PMIC_RG_LDO_VRFCK_OP_EN, + PMIC_RG_LDO_VRFCK_HW14_OP_EN); + ldo_vbbck_op_en = BUF_READ_FIELD(PMIC_RG_LDO_VBBCK_OP_EN, + PMIC_RG_LDO_VBBCK_HW14_OP_EN); + ldo_vrfck_en = BUF_READ_FIELD(PMIC_RG_LDO_VRFCK_CON0, PMIC_RG_LDO_VRFCK_EN); + ldo_vbbck_en = BUF_READ_FIELD(PMIC_RG_LDO_VBBCK_CON0, PMIC_RG_LDO_VBBCK_EN); + buf_info("spi_con1/ldo_rf_op/ldo_bb_op/ldo_rf_en/ldo_bb_en=%#x %#x %#x %#x %#x\n", + top_spi_con1, ldo_vrfck_op_en, ldo_vbbck_op_en, + ldo_vrfck_en, ldo_vbbck_en); + + vrfck_hv_en = BUF_READ_FIELD(PMIC_RG_DCXO_ADLDO_BIAS_ELR_0, PMIC_RG_VRFCK_HV_EN); + buf_info("clk buf vrfck_hv_en=%#x\n", vrfck_hv_en); +} + +int clk_buf_init(void) +{ + /* Dump registers before setting */ + dump_clkbuf_log(); + + /* Unlock pmic key */ + BUF_SET_FIELDS(PMIC_TOP_TMA_KEY, PMIC_REG_COMMON, PMIC_TOP_TMA_KEY_UNLOCK); + + /* 1.1 Set VRFCK input supply(11.ac mode) */ + BUF_SET_FIELDS(PMIC_RG_DCXO_ADLDO_BIAS_ELR_0, PMIC_RG_VRFCK_HV_EN, 0x0); + + /* 1.2.0 Set VRFCK En = 0 */ + BUF_SET_FIELDS(PMIC_RG_LDO_VRFCK_CON0, PMIC_RG_LDO_VRFCK_EN, 0x0); + /* 1.2.1 Set VRFCK1 as power src */ + BUF_SET_FIELDS(PMIC_RG_LDO_VRFCK_ELR, PMIC_RG_LDO_VRFCK_ANA_SEL, 0x1); + + /* 1.2.2 Switch LDO-RFCK to LDO-RFCK1 */ + BUF_SET_FIELDS(PMIC_RG_DCXO_ADLDO_BIAS_ELR_0, PMIC_RG_VRFCK_NDIS_EN, 0x0); + BUF_SET_FIELDS(PMIC_RG_DCXO_ADLDO_BIAS_ELR_1, PMIC_RG_VRFCK_1_NDIS_EN, 0x1); + + /* 1.2.0 Set VRFCK En = 1 */ + BUF_SET_FIELDS(PMIC_RG_LDO_VRFCK_CON0, PMIC_RG_LDO_VRFCK_EN, 0x1); + + /* 1.2.3 Lock pmic key */ + BUF_SET_FIELDS(PMIC_TOP_TMA_KEY, PMIC_REG_COMMON, 0x0); + + /* Enable XO LDO */ + BUF_SET_FIELDS(PMIC_RG_LDO_VRFCK_OP_EN_SET, PMIC_RG_LDO_VRFCK_HW14_OP_EN, 0x1); + BUF_SET_FIELDS(PMIC_RG_LDO_VBBCK_OP_EN_SET, PMIC_RG_LDO_VBBCK_HW14_OP_EN, 0x1); + BUF_SET_FIELDS(PMIC_RG_LDO_VRFCK_CON0, PMIC_RG_LDO_VRFCK_EN, 0x0); + BUF_SET_FIELDS(PMIC_RG_LDO_VBBCK_CON0, PMIC_RG_LDO_VBBCK_EN, 0x0); + + /* Enable 26M control */ + if (!CONFIG(SRCLKEN_RC_SUPPORT)) { + /* Legacy co-clock mode */ + BUF_SET_FIELDS(PMIC_RG_TOP_SPI_CON1, PMIC_RG_SRCLKEN_IN3_EN, 0x0); + + BUF_SET_FIELDS(PMIC_RG_DCXO_CW00, PMIC_REG_COMMON, PMIC_CW00_INIT_VAL); + BUF_SET_FIELDS(PMIC_RG_DCXO_CW09, PMIC_REG_COMMON, PMIC_CW09_INIT_VAL); + } else { + /* New co-clock mode */ + /* All XO mode should set to 2'b01 */ + BUF_SET_FIELDS(PMIC_RG_DCXO_CW00, PMIC_REG_COMMON, PMIC_CW00_INIT_VAL); + BUF_SET_FIELDS(PMIC_RG_DCXO_CW09, PMIC_REG_COMMON, PMIC_CW09_INIT_VAL); + + /* 1. Update control mapping table */ + BUF_SET_FIELDS(PMIC_RG_XO_BUF_CTL0, PMIC_RG_XO_VOTE, 0x005); + BUF_SET_FIELDS(PMIC_RG_XO_BUF_CTL1, PMIC_RG_XO_VOTE, 0x0); + BUF_SET_FIELDS(PMIC_RG_XO_BUF_CTL2, PMIC_RG_XO_VOTE, 0x0); + BUF_SET_FIELDS(PMIC_RG_XO_BUF_CTL3, PMIC_RG_XO_VOTE, 0x0); + BUF_SET_FIELDS(PMIC_RG_XO_BUF_CTL4, PMIC_RG_XO_VOTE, 0x0); + /* Wait 100us */ + udelay(100); + + /* 2. Switch to new control mode */ + BUF_SET_FIELDS(PMIC_RG_DCXO_CW08, PMIC_RG_XO_PMIC_TOP_DIG_SW, 0x0); + } + + /* Check if the setting is ok */ + dump_clkbuf_log(); + + return 0; +} diff --git a/src/soc/mediatek/mt8192/include/soc/addressmap.h b/src/soc/mediatek/mt8192/include/soc/addressmap.h index e4d57b05fc..3a07802f8d 100644 --- a/src/soc/mediatek/mt8192/include/soc/addressmap.h +++ b/src/soc/mediatek/mt8192/include/soc/addressmap.h @@ -20,6 +20,8 @@ enum { INFRACFG_AO_MEM_BASE = IO_PHYS + 0x00002000, GPIO_BASE = IO_PHYS + 0x00005000, SPM_BASE = IO_PHYS + 0x00006000, + RC_BASE = IO_PHYS + 0x00006500, + RC_STATUS_BASE = IO_PHYS + 0x00006E00, RGU_BASE = IO_PHYS + 0x00007000, GPT_BASE = IO_PHYS + 0x00008000, EINT_BASE = IO_PHYS + 0x0000B000, diff --git a/src/soc/mediatek/mt8192/include/soc/clkbuf.h b/src/soc/mediatek/mt8192/include/soc/clkbuf.h new file mode 100644 index 0000000000..b5fa3a3f1b --- /dev/null +++ b/src/soc/mediatek/mt8192/include/soc/clkbuf.h @@ -0,0 +1,69 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef SOC_MEDIATEK_MT8192_CLKBUF_H +#define SOC_MEDIATEK_MT8192_CLKBUF_H + +#include + +enum { + PMIC_RG_DCXO_CW00 = 0x0788, + PMIC_RG_DCXO_CW02 = 0x0790, + PMIC_RG_DCXO_CW08 = 0x079C, + PMIC_RG_DCXO_CW09 = 0x079E, + PMIC_RG_DCXO_CW09_CLR = 0x07A2, + PMIC_RG_DCXO_CW10 = 0x07A4, + PMIC_RG_DCXO_CW12 = 0x07A8, + PMIC_RG_DCXO_CW13 = 0x07AA, + PMIC_RG_DCXO_CW15 = 0x07AE, + PMIC_RG_DCXO_CW19 = 0x07B6, +}; + +enum { + PMIC_TOP_TMA_KEY = 0x3A8, + PMIC_RG_TOP_SPI_CON1 = 0x458, +}; + +enum { + PMIC_TOP_TMA_KEY_UNLOCK = 0x9CA6, +}; + +enum { + PMIC_RG_LDO_VRFCK_ELR = 0x1B40, + PMIC_RG_LDO_VRFCK_CON0 = 0x1D1C, + PMIC_RG_LDO_VRFCK_OP_EN = 0x1D22, + PMIC_RG_LDO_VRFCK_OP_EN_SET = 0x1D24, + PMIC_RG_LDO_VBBCK_CON0 = 0x1D2E, + PMIC_RG_LDO_VBBCK_OP_EN = 0x1D34, + PMIC_RG_LDO_VBBCK_OP_EN_SET = 0x1D36, +}; + +enum { + PMIC_RG_DCXO_ADLDO_BIAS_ELR_0 = 0x209C, + PMIC_RG_DCXO_ADLDO_BIAS_ELR_1 = 0x209E, +}; + +enum { + PMIC_RG_XO_BUF_CTL0 = 0x54C, + PMIC_RG_XO_BUF_CTL1 = 0x54E, + PMIC_RG_XO_BUF_CTL2 = 0x550, + PMIC_RG_XO_BUF_CTL3 = 0x552, + PMIC_RG_XO_BUF_CTL4 = 0x554, + PMIC_RG_XO_CONN_BT0 = 0x556, +}; + +DEFINE_BITFIELD(PMIC_REG_COMMON, 15, 0) +DEFINE_BIT(PMIC_RG_VRFCK_HV_EN, 9) +DEFINE_BIT(PMIC_RG_LDO_VRFCK_EN, 0) +DEFINE_BIT(PMIC_RG_LDO_VRFCK_ANA_SEL, 0) +DEFINE_BIT(PMIC_RG_LDO_VBBCK_EN, 0) +DEFINE_BIT(PMIC_RG_VRFCK_NDIS_EN, 11) +DEFINE_BIT(PMIC_RG_VRFCK_1_NDIS_EN, 0) +DEFINE_BIT(PMIC_RG_LDO_VRFCK_HW14_OP_EN, 14) +DEFINE_BIT(PMIC_RG_LDO_VBBCK_HW14_OP_EN, 14) +DEFINE_BIT(PMIC_RG_SRCLKEN_IN3_EN, 0) +DEFINE_BIT(PMIC_RG_XO_PMIC_TOP_DIG_SW, 2) +DEFINE_BITFIELD(PMIC_RG_XO_VOTE, 10, 0) + +int clk_buf_init(void); + +#endif /* SOC_MEDIATEK_MT8192_CLKBUF_H */ diff --git a/src/soc/mediatek/mt8192/include/soc/pmif.h b/src/soc/mediatek/mt8192/include/soc/pmif.h index fe3def020a..cfc7fe5f1e 100644 --- a/src/soc/mediatek/mt8192/include/soc/pmif.h +++ b/src/soc/mediatek/mt8192/include/soc/pmif.h @@ -3,6 +3,7 @@ #ifndef __MT8192_SOC_PMIF_H__ #define __MT8192_SOC_PMIF_H__ +#include #include enum { @@ -167,6 +168,36 @@ enum { E_SPI_INIT_SIDLY, /* SPI edge calibration fail */ }; +enum pmic_interface { + PMIF_VLD_RDY = 0, + PMIF_SLP_REQ, +}; + +DEFINE_BIT(PMIFSPI_INF_EN_SRCLKEN_RC_HW, 4) + +DEFINE_BIT(PMIFSPI_OTHER_INF_DXCO0_EN, 0) +DEFINE_BIT(PMIFSPI_OTHER_INF_DXCO1_EN, 1) + +DEFINE_BIT(PMIFSPI_ARB_EN_SRCLKEN_RC_HW, 4) +DEFINE_BIT(PMIFSPI_ARB_EN_DCXO_CONN, 15) +DEFINE_BIT(PMIFSPI_ARB_EN_DCXO_NFC, 16) + +DEFINE_BITFIELD(PMIFSPI_SPM_SLEEP_REQ_SEL, 1, 0) +DEFINE_BITFIELD(PMIFSPI_SCP_SLEEP_REQ_SEL, 10, 9) + +DEFINE_BIT(PMIFSPI_MD_CTL_PMIF_RDY, 9) +DEFINE_BIT(PMIFSPI_MD_CTL_SRCLK_EN, 10) +DEFINE_BIT(PMIFSPI_MD_CTL_SRVOL_EN, 11) + +DEFINE_BITFIELD(PMIFSPMI_SPM_SLEEP_REQ_SEL, 1, 0) +DEFINE_BITFIELD(PMIFSPMI_SCP_SLEEP_REQ_SEL, 10, 9) + +DEFINE_BIT(PMIFSPMI_MD_CTL_PMIF_RDY, 9) +DEFINE_BIT(PMIFSPMI_MD_CTL_SRCLK_EN, 10) +DEFINE_BIT(PMIFSPMI_MD_CTL_SRVOL_EN, 11) + +/* External API */ extern struct pmif *get_pmif_controller(int inf, int mstid); +extern void pmwrap_interface_init(void); extern int mtk_pmif_init(void); #endif /*__MT8192_SOC_PMIF_H__*/ diff --git a/src/soc/mediatek/mt8192/include/soc/rtc.h b/src/soc/mediatek/mt8192/include/soc/rtc.h index 491aeabc37..46c06f4a52 100644 --- a/src/soc/mediatek/mt8192/include/soc/rtc.h +++ b/src/soc/mediatek/mt8192/include/soc/rtc.h @@ -149,19 +149,6 @@ enum { PMIC_RG_BANK_FQMTR_RST_SHIFT = 6, }; -/* PMIC DCXO Register Definition */ -enum { - PMIC_RG_DCXO_CW00 = 0x0788, - PMIC_RG_DCXO_CW00_SET = 0x078A, - PMIC_RG_DCXO_CW00_CLR = 0x078C, - PMIC_RG_DCXO_CW02 = 0x0790, - PMIC_RG_DCXO_CW08 = 0x079C, - PMIC_RG_DCXO_CW09 = 0x079E, - PMIC_RG_DCXO_CW09_SET = 0x07A0, - PMIC_RG_DCXO_CW09_CLR = 0x07A2, - PMIC_RG_DCXO_CW12 = 0x07A8, -}; - /* PMIC Frequency Meter Definition */ enum { PMIC_RG_FQMTR_CKSEL = 0x0118, @@ -228,5 +215,4 @@ int rtc_init(int recover); bool rtc_gpio_init(void); void rtc_boot(void); u16 rtc_get_frequency_meter(u16 val, u16 measure_src, u16 window_size); -void mt6359_dcxo_disable_unused(void); #endif /* SOC_MEDIATEK_MT8192_RTC_H */ diff --git a/src/soc/mediatek/mt8192/include/soc/srclken_rc.h b/src/soc/mediatek/mt8192/include/soc/srclken_rc.h new file mode 100644 index 0000000000..dc0a076087 --- /dev/null +++ b/src/soc/mediatek/mt8192/include/soc/srclken_rc.h @@ -0,0 +1,191 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef SOC_MEDIATEK_MT8192_SRCLKEN_RC_H +#define SOC_MEDIATEK_MT8192_SRCLKEN_RC_H + +#include + +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 rc_mxx_srclken_cfg[13]; + u32 srclken_sw_con_cfg; + u32 rc_central_cfg4; + u32 reserved1; + u32 rc_protocol_chk_cfg; + u32 rc_debug_cfg; + u32 reserved2[19]; + u32 rc_misc_0; + u32 rc_spm_ctrl; + u32 rc_subsys_intf_cfg; +}; + +check_member(mtk_rc_regs, rc_central_cfg1, 0x4); +check_member(mtk_rc_regs, rc_mxx_srclken_cfg[0], 0x20); +check_member(mtk_rc_regs, rc_mxx_srclken_cfg[12], 0x50); +check_member(mtk_rc_regs, rc_central_cfg4, 0x58); +check_member(mtk_rc_regs, rc_protocol_chk_cfg, 0x60); +check_member(mtk_rc_regs, rc_misc_0, 0xb4); +check_member(mtk_rc_regs, rc_subsys_intf_cfg, 0xbc); + +struct mtk_rc_status_regs { + u32 rc_fsm_sta_0; + u32 rc_cmd_sta_0; + u32 rc_cmd_sta_1; + u32 rc_spi_sta_0; + u32 rc_pi_po_sta_0; + u32 rc_mxx_req_sta_0[14]; + u32 reserved2[2]; + u32 rc_debug_trace; +}; + +check_member(mtk_rc_status_regs, rc_cmd_sta_1, 0x8); +check_member(mtk_rc_status_regs, rc_mxx_req_sta_0[0], 0x14); +check_member(mtk_rc_status_regs, rc_mxx_req_sta_0[13], 0x48); +check_member(mtk_rc_status_regs, rc_debug_trace, 0x54); + +/* SPM Register */ +/* SRCLKEN_RC_CFG */ +DEFINE_BIT(SW_RESET, 0) +DEFINE_BIT(CG_32K_EN, 1) +DEFINE_BIT(CG_FCLK_EN, 2) +DEFINE_BIT(CG_FCLK_FR_EN, 3) +DEFINE_BIT(MUX_FCLK_FR, 4) + +/* RC_CENTRAL_CFG1 */ +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) + +/* RC_CENTRAL_CFG2 */ +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_BITFIELD(ULPOSC_CTRL_M, 15, 12) +DEFINE_BITFIELD(PWRAP_SLP_CTRL_M, 24, 21) +DEFINE_BIT(PWRAP_SLP_MUX_SEL, 25) + +/* RC_DCXO_FPM_CFG */ +DEFINE_BITFIELD(DCXO_FPM_CTRL_M, 3, 0) +DEFINE_BIT(SRCVOLTEN_FPM_MSK_B, 4) +DEFINE_BITFIELD(SUB_SRCLKEN_FPM_MSK_B, 28, 16) + +/* RC_CENTRAL_CFG3 */ +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_BITFIELD(TO_LPM_SETTLE_T, 21, 12) + +/* RC_CENTRAL_CFG4 */ +DEFINE_BITFIELD(KEEP_RC_SPI_ACTIVE, 8, 0) +DEFINE_BIT(PWRAP_VLD_FORCE, 16) +DEFINE_BIT(SLEEP_VLD_MODE, 17) + +/* RC_MXX_SRCLKEN_CFG */ +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_LINK_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) + +enum { + SW_SRCLKEN_FPM_MSK = 0x1, + SW_SRCLKEN_BBLPM_MSK = 0x1, +}; + +/* RC_DEBUG_CFG */ +DEFINE_BIT(TRACE_MODE_EN, 24) + +/* SUBSYS_INTF_CFG */ +DEFINE_BITFIELD(SRCLKEN_FPM_MASK_B, 12, 0) +DEFINE_BITFIELD(SRCLKEN_BBLPM_MASK_B, 28, 16) + +enum { + PMIC_PMRC_CON0 = 0x1A6, + PMIC_PMRC_CON0_SET = 0x1A8, + PMIC_PMRC_CON0_CLR = 0x1AA, +}; + +enum chn_id { + CHN_SUSPEND = 0, + CHN_RF = 1, + CHN_DEEPIDLE = 2, + CHN_MD = 3, + CHN_GPS = 4, + CHN_BT = 5, + CHN_WIFI = 6, + CHN_MCU = 7, + CHN_COANT = 8, + CHN_NFC = 9, + CHN_UFS = 10, + CHN_SCP = 11, + CHN_RESERVE = 12, + MAX_CHN_NUM, +}; + +enum { + SRCLKENAO_MODE, + VREQ_MODE, +}; + +enum { + MERGE_OR_MODE = 0x0, + BYPASS_MODE = 0x1, + MERGE_AND_MODE = 0x1 << 1, + BYPASS_RC_MODE = 0x2 << 1, + BYPASS_OTHER_MODE = 0x3 << 1, + ASYNC_MODE = 0x1 << 3, +}; + +enum { + RC_32K = 0, + RC_ULPOSC1, +}; + +enum rc_ctrl_m { + HW_MODE = 0, + SW_MODE = 1, + INIT_MODE = 0xff, +}; + +enum rc_support { + SRCLKEN_RC_ENABLE = 0, + SRCLKEN_RC_DISABLE, +}; + +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; +}; + +extern int srclken_rc_init(void); + +#endif /* SOC_MEDIATEK_MT8192_SRCLKEN_RC_H */ diff --git a/src/soc/mediatek/mt8192/pmif.c b/src/soc/mediatek/mt8192/pmif.c index f6b1525915..57fc9d4a3f 100644 --- a/src/soc/mediatek/mt8192/pmif.c +++ b/src/soc/mediatek/mt8192/pmif.c @@ -177,6 +177,120 @@ struct pmif *get_pmif_controller(int inf, int mstid) return NULL; } +static void pmif_select(enum pmic_interface mode) +{ + unsigned int spi_spm_sleep_req, spi_scp_sleep_req, + spmi_spm_sleep_req, spmi_scp_sleep_req, + spi_md_ctl_pmif_rdy, spi_md_ctl_srclk_en, spi_md_ctl_srvol_en, + spmi_md_ctl_pmif_rdy, spmi_md_ctl_srclk_en, spmi_md_ctl_srvol_en, + spi_inf_srclken_rc_en, spi_other_inf_dcxo0_en, spi_other_inf_dcxo1_en, + spi_arb_srclken_rc_en, spi_arb_dcxo_conn_en, spi_arb_dcxo_nfc_en; + + switch (mode) { + case PMIF_VLD_RDY: + /* spm and scp sleep request disable spi and spmi */ + spi_spm_sleep_req = 1; + spi_scp_sleep_req = 1; + spmi_spm_sleep_req = 1; + spmi_scp_sleep_req = 1; + + /* + * pmic vld/rdy control spi mode enable + * srclken control spi mode disable + * vreq control spi mode disable + */ + spi_md_ctl_pmif_rdy = 1; + spi_md_ctl_srclk_en = 0; + spi_md_ctl_srvol_en = 0; + spmi_md_ctl_pmif_rdy = 1; + spmi_md_ctl_srclk_en = 0; + spmi_md_ctl_srvol_en = 0; + + /* srclken rc interface enable */ + spi_inf_srclken_rc_en = 1; + + /* dcxo interface disable */ + spi_other_inf_dcxo0_en = 0; + spi_other_inf_dcxo1_en = 0; + + /* srclken enable, dcxo0,1 disable */ + spi_arb_srclken_rc_en = 1; + spi_arb_dcxo_conn_en = 0; + spi_arb_dcxo_nfc_en = 0; + break; + + case PMIF_SLP_REQ: + /* spm and scp sleep request enable spi and spmi */ + spi_spm_sleep_req = 0; + spi_scp_sleep_req = 0; + spmi_spm_sleep_req = 0; + spmi_scp_sleep_req = 0; + + /* + * pmic vld/rdy control spi mode disable + * srclken control spi mode enable + * vreq control spi mode enable + */ + spi_md_ctl_pmif_rdy = 0; + spi_md_ctl_srclk_en = 1; + spi_md_ctl_srvol_en = 1; + spmi_md_ctl_pmif_rdy = 0; + spmi_md_ctl_srclk_en = 1; + spmi_md_ctl_srvol_en = 1; + + /* srclken rc interface disable */ + spi_inf_srclken_rc_en = 0; + + /* dcxo interface enable */ + spi_other_inf_dcxo0_en = 1; + spi_other_inf_dcxo1_en = 1; + + /* srclken disable, dcxo0,1 enable */ + spi_arb_srclken_rc_en = 0; + spi_arb_dcxo_conn_en = 1; + spi_arb_dcxo_nfc_en = 1; + break; + + default: + die("Can't support pmif mode %d\n", mode); + } + + SET32_BITFIELDS(&pmif_spi_arb[0].mtk_pmif->sleep_protection_ctrl, + PMIFSPI_SPM_SLEEP_REQ_SEL, spi_spm_sleep_req, + PMIFSPI_SCP_SLEEP_REQ_SEL, spi_scp_sleep_req); + SET32_BITFIELDS(&pmif_spmi_arb[0].mtk_pmif->sleep_protection_ctrl, + PMIFSPMI_SPM_SLEEP_REQ_SEL, spmi_spm_sleep_req, + PMIFSPMI_SCP_SLEEP_REQ_SEL, spmi_scp_sleep_req); + SET32_BITFIELDS(&pmif_spi_arb[0].mtk_pmif->spi_mode_ctrl, + PMIFSPI_MD_CTL_PMIF_RDY, spi_md_ctl_pmif_rdy, + PMIFSPI_MD_CTL_SRCLK_EN, spi_md_ctl_srclk_en, + PMIFSPI_MD_CTL_SRVOL_EN, spi_md_ctl_srvol_en); + SET32_BITFIELDS(&pmif_spmi_arb[0].mtk_pmif->spi_mode_ctrl, + PMIFSPMI_MD_CTL_PMIF_RDY, spmi_md_ctl_pmif_rdy, + PMIFSPMI_MD_CTL_SRCLK_EN, spmi_md_ctl_srclk_en, + PMIFSPMI_MD_CTL_SRVOL_EN, spmi_md_ctl_srvol_en); + SET32_BITFIELDS(&pmif_spi_arb[0].mtk_pmif->inf_en, + PMIFSPI_INF_EN_SRCLKEN_RC_HW, spi_inf_srclken_rc_en); + SET32_BITFIELDS(&pmif_spi_arb[0].mtk_pmif->other_inf_en, + PMIFSPI_OTHER_INF_DXCO0_EN, spi_other_inf_dcxo0_en, + PMIFSPI_OTHER_INF_DXCO1_EN, spi_other_inf_dcxo1_en); + SET32_BITFIELDS(&pmif_spi_arb[0].mtk_pmif->arb_en, + PMIFSPI_ARB_EN_SRCLKEN_RC_HW, spi_arb_srclken_rc_en, + PMIFSPI_ARB_EN_DCXO_CONN, spi_arb_dcxo_conn_en, + PMIFSPI_ARB_EN_DCXO_NFC, spi_arb_dcxo_nfc_en); +} + +void pmwrap_interface_init(void) +{ + if (CONFIG(SRCLKEN_RC_SUPPORT)) { + printk(BIOS_INFO, "%s: Select PMIF_VLD_RDY\n", __func__); + pmif_select(PMIF_VLD_RDY); + } else { + printk(BIOS_INFO, "%s: Select PMIF_SLP_REQ\n", __func__); + pmif_select(PMIF_SLP_REQ); + } +} + int mtk_pmif_init(void) { int ret; diff --git a/src/soc/mediatek/mt8192/rtc.c b/src/soc/mediatek/mt8192/rtc.c index d966cabb59..b5c381b50d 100644 --- a/src/soc/mediatek/mt8192/rtc.c +++ b/src/soc/mediatek/mt8192/rtc.c @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -312,43 +313,11 @@ void poweroff(void) halt(); } -static void dcxo_init(void) -{ - u16 tmp; - - rtc_read(PMIC_RG_DCXO_CW00, &tmp); - rtc_info("CW00,%#x:%#x\n", PMIC_RG_DCXO_CW00, tmp); - rtc_read(PMIC_RG_DCXO_CW09, &tmp); - rtc_info("CW09,%#x:%#x\n", PMIC_RG_DCXO_CW09, tmp); - rtc_read(PMIC_RG_DCXO_CW08, &tmp); - rtc_info("CW08,%#x:%#x\n", PMIC_RG_DCXO_CW08, tmp); - /* 26M enable control */ - /* enable clock buffer XO_SOC */ - rtc_write_field(PMIC_RG_DCXO_CW00, 0x4005, 0xFFFF, 0); - rtc_read(PMIC_RG_DCXO_CW00, &tmp); - rtc_info("CW0,%#x:%#x\n", PMIC_RG_DCXO_CW00, tmp); - rtc_write_field(PMIC_RG_DCXO_CW09_CLR, 0x3f, 0x3f, 9); - rtc_read(PMIC_RG_DCXO_CW09, &tmp); - rtc_info("PMIC_RG_DCXO_CW09,%#x:%#x\n", PMIC_RG_DCXO_CW09, tmp); - /* mode and buffer controlled by srclken0 */ - rtc_write_field(PMIC_RG_DCXO_CW08, 0x1, 0x1, 2); - rtc_read(PMIC_RG_DCXO_CW08, &tmp); - rtc_info("PMIC_RG_DCXO_CW08,%#x:%#x\n", PMIC_RG_DCXO_CW08, tmp); -} - -void mt6359_dcxo_disable_unused(void) -{ - /* disable HW BBLPM arbiter */ - rtc_write_field(PMIC_RG_DCXO_CW12, 0x2, 0x3, 0); -} - /* the rtc boot flow entry */ void rtc_boot(void) { u16 tmp; - /* dcxo clock init settings */ - dcxo_init(); /* dcxo 32k init settings */ rtc_write_field(PMIC_RG_DCXO_CW02, 0xF, 0xF, 0); rtc_read(PMIC_RG_SCK_TOP_CON0, &tmp); diff --git a/src/soc/mediatek/mt8192/srclken_rc.c b/src/soc/mediatek/mt8192/srclken_rc.c new file mode 100644 index 0000000000..f6790c6898 --- /dev/null +++ b/src/soc/mediatek/mt8192/srclken_rc.c @@ -0,0 +1,388 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include +#include +#include +#include + +#define RCTAG "[SRCLKEN_RC]" +#define rc_info(fmt, arg ...) printk(BIOS_INFO, RCTAG "%s,%d: " fmt, \ + __func__, __LINE__, ## arg) + +#define SRCLKEN_DBG 1 + +/* RC settle time setting */ +enum { + FULL_SET_HW_MODE = 0, /* dcxo mode use pmrc_en */ + VCORE_SETTLE_TIME = 1, /* ~= 30us */ + ULPOSC_SETTLE_TIME = 4, /* ~= 150us */ + XO_SETTLE_TIME = 0x1, /* 2 ^ (step_sz + 5) * 0x33 * 30.77ns ~= 400us */ + DCXO_SETTLE_TIME = 0x1, /* 2 ^ (step_sz + 5) * 0x87 * 30.77ns ~= 1063us */ + CENTROL_CNT_STEP = 0x3, /* fix in 3, central align with Mxx channel */ + DCXO_STABLE_TIME = 0x70, + XO_STABLE_TIME = 0x70, + KEEP_RC_SPI_ACTIVE_VAL = 1, + SRCLKEN_RC_EN_SEL_VAL = 0, +}; + +enum { + INIT_SUBSYS_FPM_TO_LPM = 1 << CHN_RF | 1 << CHN_DEEPIDLE | 1 << CHN_MD + | 1 << CHN_GPS | 1 << CHN_BT | 1 << CHN_WIFI + | 1 << CHN_MCU | 1 << CHN_COANT | 1 << CHN_NFC + | 1 << CHN_UFS | 1 << CHN_SCP | 1 << CHN_RESERVE, + INIT_SUBSYS_FPM_TO_BBLPM = 1 << CHN_DEEPIDLE, + INIT_SUBSYS_TO_HW = 1 << CHN_SUSPEND | 1 << CHN_DEEPIDLE | 1 << CHN_MCU, +}; + +/* RC central setting */ +enum { + RC_CENTRAL_ENABLE = 1, + RC_CENTRAL_DISABLE = 0, + SPI_TRIG_MODE = SRCLKENAO_MODE, /* use srlckenao to set vcore */ + IS_SPI_DONE_RELEASE = 0, /* release vcore when spi request done */ + IS_SPI2PMIC_SET_CLR = 0, /* register direct write */ + SRCLKENO_0_CTRL_M = MERGE_OR_MODE, /* merge with spm */ + VREQ_CTRL_M = BYPASS_MODE, /* merge with vreq */ + ULPOSC_CTRL_M_VAL = BYPASS_MODE, /* merge with ulposc */ + PWRAP_CTRL_M = MERGE_OR_MODE, /* merge with pwrap_scp */ + SPI_CLK_SRC = RC_32K, /* pmic spec under 200us */ +}; + +/* Other setting */ +enum { + DCXO_FPM_CTRL_MODE = MERGE_OR_MODE | ASYNC_MODE, /* merge with spm */ + PWRAP_TMOUT_VAL = 0xA, /* 31us * 0xa ~= 310us */ + FPM_MSK_B = FULL_SET_HW_MODE, + MD0_SRCLKENO_0_MASK_B = 0, /* md0 control by pmrc */ +}; + +enum { + SUB_BBLPM_SET = 1 << CHN_COANT | 1 << CHN_DEEPIDLE, + SUB_FPM_SET = 1 << CHN_SUSPEND | 1 << CHN_RF | 1 << CHN_MD + | 1 << CHN_GPS | 1 << CHN_BT | 1 << CHN_WIFI + | 1 << CHN_MCU | 1 << CHN_NFC | 1 << CHN_UFS + | 1 << CHN_SCP | 1 << CHN_RESERVE, +}; + +enum { + SW_FPM_LOW = 0, + SW_FPM_HIGH = 1, +}; + +enum { + SW_BBLPM_LOW = 0, + SW_BBLPM_HIGH = 1, +}; + +enum { + DXCO_SETTLE_BLK_DIS = 0, + DXCO_SETTLE_BLK_EN = 1, +}; + +#define SUB_CTRL_CON(_dcxo_prd, _xo_prd, _bypass_cmd, _dcxo_settle_blk_en) { \ + .dcxo_prd = _dcxo_prd, \ + .xo_prd = _xo_prd, \ + .cnt_step = CENTROL_CNT_STEP, \ + .track_en = 0x0, \ + .req_ack_imd_en = 0x1, \ + .xo_soc_link_en = 0x0, \ + .sw_bblpm = SW_BBLPM_LOW, \ + .sw_fpm = SW_FPM_HIGH, \ + .sw_rc = SW_MODE, \ + .bypass_cmd = _bypass_cmd, \ + .dcxo_settle_blk_en = _dcxo_settle_blk_en, \ + } + +static struct mtk_rc_regs *rc_regs = (struct mtk_rc_regs *)RC_BASE; +static struct mtk_rc_status_regs *rc_sta_regs = (struct mtk_rc_status_regs *)RC_STATUS_BASE; + +static struct subsys_rc_con rc_ctrl[MAX_CHN_NUM] = { + [CHN_SUSPEND] = SUB_CTRL_CON(DCXO_STABLE_TIME, XO_STABLE_TIME, 0x0, DXCO_SETTLE_BLK_EN), + [CHN_RF] = SUB_CTRL_CON(DCXO_STABLE_TIME, XO_STABLE_TIME, 0x0, DXCO_SETTLE_BLK_EN), + [CHN_DEEPIDLE] = SUB_CTRL_CON(DCXO_STABLE_TIME, XO_STABLE_TIME, + 0x0, DXCO_SETTLE_BLK_EN), + [CHN_MD] = SUB_CTRL_CON(DCXO_STABLE_TIME, XO_STABLE_TIME, 0x0, DXCO_SETTLE_BLK_EN), + [CHN_GPS] = SUB_CTRL_CON(DCXO_STABLE_TIME, XO_STABLE_TIME, 0x0, DXCO_SETTLE_BLK_EN), + [CHN_BT] = SUB_CTRL_CON(DCXO_STABLE_TIME, XO_STABLE_TIME, 0x0, DXCO_SETTLE_BLK_EN), + [CHN_WIFI] = SUB_CTRL_CON(DCXO_STABLE_TIME, XO_STABLE_TIME, 0x0, DXCO_SETTLE_BLK_EN), + [CHN_MCU] = SUB_CTRL_CON(DCXO_STABLE_TIME, XO_STABLE_TIME, 0x0, DXCO_SETTLE_BLK_EN), + [CHN_COANT] = SUB_CTRL_CON(0x0, 0x0, 0x1, DXCO_SETTLE_BLK_DIS), + [CHN_NFC] = SUB_CTRL_CON(DCXO_STABLE_TIME, XO_STABLE_TIME, 0x0, DXCO_SETTLE_BLK_EN), + [CHN_UFS] = SUB_CTRL_CON(DCXO_STABLE_TIME, XO_STABLE_TIME, 0x0, DXCO_SETTLE_BLK_EN), + [CHN_SCP] = SUB_CTRL_CON(0x0, 0x0, 0x1, DXCO_SETTLE_BLK_DIS), + [CHN_RESERVE] = SUB_CTRL_CON(0x0, 0x0, 0x1, DXCO_SETTLE_BLK_DIS), +}; + +static void pmic_read(u32 addr, u32 *rdata) +{ + static struct pmif *pmif_arb; + + if (pmif_arb == NULL) + pmif_arb = get_pmif_controller(PMIF_SPI, 0); + + pmif_arb->read(pmif_arb, 0, addr, rdata); +} + +static void rc_dump_reg_info(void) +{ + unsigned int chn_n; + + if (SRCLKEN_DBG) { + rc_info("SRCLKEN_RC_CFG:%#x\n", read32(&rc_regs->srclken_rc_cfg)); + rc_info("RC_CENTRAL_CFG1:%#x\n", read32(&rc_regs->rc_central_cfg1)); + rc_info("RC_CENTRAL_CFG2:%#x\n", read32(&rc_regs->rc_central_cfg2)); + rc_info("RC_CENTRAL_CFG3:%#x\n", read32(&rc_regs->rc_central_cfg3)); + rc_info("RC_CENTRAL_CFG4:%#x\n", read32(&rc_regs->rc_central_cfg4)); + rc_info("RC_DCXO_FPM_CFG:%#x\n", read32(&rc_regs->rc_dcxo_fpm_cfg)); + rc_info("SUBSYS_INTF_CFG:%#x\n", read32(&rc_regs->rc_subsys_intf_cfg)); + rc_info("RC_SPI_STA_0:%#x\n", read32(&rc_sta_regs->rc_spi_sta_0)); + rc_info("RC_PI_PO_STA:%#x\n", read32(&rc_sta_regs->rc_pi_po_sta_0)); + + for (chn_n = 0; chn_n < MAX_CHN_NUM; chn_n++) { + rc_info("M%02d: %#x\n", chn_n, + read32(&rc_regs->rc_mxx_srclken_cfg[chn_n])); + } + } +} + +/* RC initial flow and relative setting */ +static void __rc_ctrl_mode_switch(enum chn_id id, enum rc_ctrl_m mode) +{ + 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_LINK_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: + die("Can't support rc_mode %d\n", mode); + } + + rc_info("M%02d: %#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) +{ + SET32_BITFIELDS(&rc_regs->rc_mxx_srclken_cfg[id], SW_SRCLKEN_FPM, !!mode); + rc_ctrl[id].sw_fpm = mode; + rc_info("M%02d FPM SWITCH: %#x\n", id, read32(&rc_regs->rc_mxx_srclken_cfg[id])); +} + +static void __rc_ctrl_bblpm_switch(enum chn_id id, unsigned int mode) +{ + SET32_BITFIELDS(&rc_regs->rc_mxx_srclken_cfg[id], SW_SRCLKEN_BBLPM, !!mode); + rc_ctrl[id].sw_bblpm = mode; + rc_info("M%02d BBLPM SWITCH: %#x\n", id, read32(&rc_regs->rc_mxx_srclken_cfg[id])); +} + +static void rc_init_subsys_hw_mode(void) +{ + unsigned int chn_n; + + for (chn_n = 0; chn_n < MAX_CHN_NUM; chn_n++) { + if (INIT_SUBSYS_TO_HW & (1 << chn_n)) + __rc_ctrl_mode_switch(chn_n, HW_MODE); + } +} + +static void rc_init_subsys_lpm(void) +{ + unsigned int chn_n; + + for (chn_n = 0; chn_n < MAX_CHN_NUM; chn_n++) { + if (INIT_SUBSYS_FPM_TO_LPM & (1 << chn_n)) + __rc_ctrl_fpm_switch(chn_n, SW_FPM_LOW); + } + for (chn_n = 0; chn_n < MAX_CHN_NUM; chn_n++) { + if (INIT_SUBSYS_FPM_TO_BBLPM & (1 << chn_n)) + __rc_ctrl_bblpm_switch(chn_n, SW_BBLPM_HIGH); + } +} + +static void rc_ctrl_mode_switch_init(enum chn_id id) +{ + __rc_ctrl_mode_switch(id, INIT_MODE); +} + +static enum rc_support srclken_rc_chk_init_cfg(void) +{ + pmwrap_interface_init(); + if (!CONFIG(SRCLKEN_RC_SUPPORT)) { + rc_info("Bring-UP : skip srclken_rc init\n"); + return SRCLKEN_RC_DISABLE; + } + if (SRCLKEN_DBG) { + /* Enable debug trace */ + write32(&rc_sta_regs->rc_debug_trace, 1); + SET32_BITFIELDS(&rc_regs->rc_debug_cfg, TRACE_MODE_EN, 1); + } + return SRCLKEN_RC_ENABLE; +} + +int srclken_rc_init(void) +{ + /* New co-clock architecture srclkenrc implement here */ + unsigned int chn_n; + int ret = 0; + + /* Check platform config to proceed init flow */ + if (srclken_rc_chk_init_cfg() != SRCLKEN_RC_ENABLE) + return ret; + + /* Set SW RESET 1 */ + SET32_BITFIELDS(&rc_regs->srclken_rc_cfg, SW_RESET, 1); + + /* Wait 100us */ + udelay(100); + + /* Set SW CG 1 */ + write32(&rc_regs->srclken_rc_cfg, + _BF_VALUE(SW_RESET, 1) | _BF_VALUE(CG_32K_EN, 1) | + _BF_VALUE(CG_FCLK_EN, 1) | _BF_VALUE(CG_FCLK_FR_EN, 1)); + + /* Wait 100us */ + udelay(100); + + /* Set Clock Mux */ + write32(&rc_regs->srclken_rc_cfg, + _BF_VALUE(SW_RESET, 1) | _BF_VALUE(CG_32K_EN, 1) | + _BF_VALUE(CG_FCLK_EN, 1) | _BF_VALUE(CG_FCLK_FR_EN, 1) | + _BF_VALUE(MUX_FCLK_FR, 1)); + + /* Set req_filter m00~m12 as default SW_FPM */ + for (chn_n = 0; chn_n < MAX_CHN_NUM; chn_n++) + rc_ctrl_mode_switch_init(chn_n); + + /* Set PMIC addr for SPI CMD */ + write32(&rc_regs->rc_pmic_rcen_addr, PMIC_PMRC_CON0); + + write32(&rc_regs->rc_pmic_rcen_set_clr_addr, + (PMIC_PMRC_CON0_CLR << 16) | PMIC_PMRC_CON0_SET); + + 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) | + _BF_VALUE(NON_DCXO_SETTLE_T, XO_SETTLE_TIME) | + _BF_VALUE(ULPOSC_SETTLE_T, ULPOSC_SETTLE_TIME) | + _BF_VALUE(VCORE_SETTLE_T, VCORE_SETTLE_TIME) | + _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) | + _BF_VALUE(SRCLKEN_RC_EN, RC_CENTRAL_DISABLE)); + + /* 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, 1) | + _BF_VALUE(BLK_COANT_DXCO_MD_TARGET, 1) | + _BF_VALUE(BLK_SCP_DXCO_MD_TARGET, 1) | + _BF_VALUE(TO_LPM_SETTLE_EN, 1)); + + /* 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, FPM_MSK_B) | + _BF_VALUE(SRCVOLTEN_FPM_MSK_B, MD0_SRCLKENO_0_MASK_B) | + _BF_VALUE(DCXO_FPM_CTRL_M, DCXO_FPM_CTRL_MODE)); + + /* Set bblpm/fpm channel */ + write32(&rc_regs->rc_subsys_intf_cfg, + _BF_VALUE(SRCLKEN_BBLPM_MASK_B, SUB_BBLPM_SET) | + _BF_VALUE(SRCLKEN_FPM_MASK_B, SUB_FPM_SET)); + + /* Trigger srclken_rc enable */ + SET32_BITFIELDS(&rc_regs->rc_central_cfg1, + SRCLKEN_RC_EN, RC_CENTRAL_ENABLE); + + write32(&rc_regs->rc_central_cfg4, + _BF_VALUE(SLEEP_VLD_MODE, 0x1) | + _BF_VALUE(PWRAP_VLD_FORCE, 0x1) | + _BF_VALUE(KEEP_RC_SPI_ACTIVE, 0x800)); + + + /* Wait 100us */ + udelay(100); + + /* Set SW RESET 0 */ + write32(&rc_regs->srclken_rc_cfg, + _BF_VALUE(CG_32K_EN, 1) | _BF_VALUE(CG_FCLK_EN, 1) | + _BF_VALUE(CG_FCLK_FR_EN, 1) | _BF_VALUE(MUX_FCLK_FR, 1)); + + /* Wait 100us */ + udelay(100); + + /* Set SW CG 0 */ + write32(&rc_regs->srclken_rc_cfg, _BF_VALUE(MUX_FCLK_FR, 1)); + + /* Wait 500us */ + udelay(500); + + /* Set req_filter m00~m12 FPM to LPM */ + rc_init_subsys_lpm(); + + /* Polling ACK of Initial Subsys Input */ + for (chn_n = 0; chn_n < MAX_CHN_NUM; chn_n++) { + unsigned int chk_sta, shift_chn_n = 0; + int retry; + u32 temp; + + /* Fix RC_MXX_REQ_STA_0 register shift */ + if (chn_n > 0) + shift_chn_n = 1; + + chk_sta = (rc_ctrl[chn_n].sw_fpm & SW_SRCLKEN_FPM_MSK) << 1 | + (rc_ctrl[chn_n].sw_bblpm & SW_SRCLKEN_BBLPM_MSK) << 3; + retry = 200; + while ((read32(&rc_sta_regs->rc_mxx_req_sta_0[chn_n + shift_chn_n]) & 0xa) + != chk_sta && retry-- > 0) + udelay(10); + if (retry < 0) { + pmic_read(PMIC_PMRC_CON0, &temp); + rc_info("polling M%02d failed.(R:%#x)(C:%#x)(PMRC:%#x)\n", + chn_n, + read32(&rc_sta_regs->rc_mxx_req_sta_0[chn_n + shift_chn_n]), + read32(&rc_regs->rc_mxx_srclken_cfg[chn_n]), temp); + ret = -1; + } + } + + /* Set req_filter m00~m12 */ + rc_init_subsys_hw_mode(); + + /* Release force pmic req signal */ + write32(&rc_regs->rc_central_cfg4, + _BF_VALUE(SLEEP_VLD_MODE, 0x1) | + _BF_VALUE(KEEP_RC_SPI_ACTIVE, 0x800)); + + rc_dump_reg_info(); + + return ret; +} -- cgit v1.2.3