summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYuchen Huang <yuchen.huang@mediatek.com>2020-09-23 20:41:19 +0800
committerHung-Te Lin <hungte@chromium.org>2021-01-19 04:02:07 +0000
commitec39cb3a80c13dd385810f2b004819652f8cc8da (patch)
tree610a905017fc1ce69150cfd06597b56af997c2d3
parent68cb9ed0680a8197f0aeedc190eace2ffca62a0a (diff)
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 <ran.bi@mediatek.com> Change-Id: I947bf14df7a307bf359c590c2a20265882b3f1be Reviewed-on: https://review.coreboot.org/c/coreboot/+/46878 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Yu-Ping Wu <yupingso@google.com>
-rw-r--r--src/soc/mediatek/mt8192/Kconfig7
-rw-r--r--src/soc/mediatek/mt8192/Makefile.inc1
-rw-r--r--src/soc/mediatek/mt8192/bootblock.c4
-rw-r--r--src/soc/mediatek/mt8192/clkbuf.c139
-rw-r--r--src/soc/mediatek/mt8192/include/soc/addressmap.h2
-rw-r--r--src/soc/mediatek/mt8192/include/soc/clkbuf.h69
-rw-r--r--src/soc/mediatek/mt8192/include/soc/pmif.h31
-rw-r--r--src/soc/mediatek/mt8192/include/soc/rtc.h14
-rw-r--r--src/soc/mediatek/mt8192/include/soc/srclken_rc.h191
-rw-r--r--src/soc/mediatek/mt8192/pmif.c114
-rw-r--r--src/soc/mediatek/mt8192/rtc.c33
-rw-r--r--src/soc/mediatek/mt8192/srclken_rc.c388
12 files changed, 947 insertions, 46 deletions
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 <bootblock_common.h>
+#include <soc/clkbuf.h>
#include <soc/eint_event.h>
#include <soc/mmu_operations.h>
#include <soc/mt6315.h>
@@ -8,6 +9,7 @@
#include <soc/pll.h>
#include <soc/pmif.h>
#include <soc/rtc.h>
+#include <soc/srclken_rc.h>
#include <soc/wdt.h>
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 <console/console.h>
+#include <delay.h>
+#include <device/mmio.h>
+#include <soc/clkbuf.h>
+#include <soc/pmif.h>
+#include <soc/srclken_rc.h>
+
+
+#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 <device/mmio.h>
+
+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 <device/mmio.h>
#include <types.h>
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 <device/mmio.h>
+
+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 <delay.h>
#include <halt.h>
+#include <soc/clkbuf.h>
#include <soc/mt6359p.h>
#include <soc/pmif.h>
#include <soc/rtc.h>
@@ -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 <console/console.h>
+#include <delay.h>
+#include <soc/addressmap.h>
+#include <soc/pmif.h>
+#include <soc/srclken_rc.h>
+
+#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;
+}