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>
This commit is contained in:
Yuchen Huang 2020-09-23 20:41:19 +08:00 committed by Hung-Te Lin
parent 68cb9ed068
commit ec39cb3a80
12 changed files with 947 additions and 46 deletions

View File

@ -82,4 +82,11 @@ config FLASH_DUAL_READ
When this option is enabled, the flash controller provides the ability When this option is enabled, the flash controller provides the ability
to dual read mode. 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 endif

View File

@ -2,6 +2,7 @@ ifeq ($(CONFIG_SOC_MEDIATEK_MT8192),y)
bootblock-y += ../common/auxadc.c bootblock-y += ../common/auxadc.c
bootblock-y += bootblock.c bootblock-y += bootblock.c
bootblock-y += clkbuf.c srclken_rc.c
bootblock-y += eint_event.c bootblock-y += eint_event.c
bootblock-y += ../common/flash_controller.c bootblock-y += ../common/flash_controller.c
bootblock-y += ../common/gpio.c gpio.c bootblock-y += ../common/gpio.c gpio.c

View File

@ -1,6 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* SPDX-License-Identifier: GPL-2.0-only */
#include <bootblock_common.h> #include <bootblock_common.h>
#include <soc/clkbuf.h>
#include <soc/eint_event.h> #include <soc/eint_event.h>
#include <soc/mmu_operations.h> #include <soc/mmu_operations.h>
#include <soc/mt6315.h> #include <soc/mt6315.h>
@ -8,6 +9,7 @@
#include <soc/pll.h> #include <soc/pll.h>
#include <soc/pmif.h> #include <soc/pmif.h>
#include <soc/rtc.h> #include <soc/rtc.h>
#include <soc/srclken_rc.h>
#include <soc/wdt.h> #include <soc/wdt.h>
void bootblock_soc_init(void) void bootblock_soc_init(void)
@ -18,6 +20,8 @@ void bootblock_soc_init(void)
mtk_pmif_init(); mtk_pmif_init();
mt6359p_init(); mt6359p_init();
mt6315_init(); mt6315_init();
srclken_rc_init();
clk_buf_init();
rtc_boot(); rtc_boot();
unmask_eint_event_mask(); unmask_eint_event_mask();
} }

View File

@ -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;
}

View File

@ -20,6 +20,8 @@ enum {
INFRACFG_AO_MEM_BASE = IO_PHYS + 0x00002000, INFRACFG_AO_MEM_BASE = IO_PHYS + 0x00002000,
GPIO_BASE = IO_PHYS + 0x00005000, GPIO_BASE = IO_PHYS + 0x00005000,
SPM_BASE = IO_PHYS + 0x00006000, SPM_BASE = IO_PHYS + 0x00006000,
RC_BASE = IO_PHYS + 0x00006500,
RC_STATUS_BASE = IO_PHYS + 0x00006E00,
RGU_BASE = IO_PHYS + 0x00007000, RGU_BASE = IO_PHYS + 0x00007000,
GPT_BASE = IO_PHYS + 0x00008000, GPT_BASE = IO_PHYS + 0x00008000,
EINT_BASE = IO_PHYS + 0x0000B000, EINT_BASE = IO_PHYS + 0x0000B000,

View File

@ -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 */

View File

@ -3,6 +3,7 @@
#ifndef __MT8192_SOC_PMIF_H__ #ifndef __MT8192_SOC_PMIF_H__
#define __MT8192_SOC_PMIF_H__ #define __MT8192_SOC_PMIF_H__
#include <device/mmio.h>
#include <types.h> #include <types.h>
enum { enum {
@ -167,6 +168,36 @@ enum {
E_SPI_INIT_SIDLY, /* SPI edge calibration fail */ 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 struct pmif *get_pmif_controller(int inf, int mstid);
extern void pmwrap_interface_init(void);
extern int mtk_pmif_init(void); extern int mtk_pmif_init(void);
#endif /*__MT8192_SOC_PMIF_H__*/ #endif /*__MT8192_SOC_PMIF_H__*/

View File

@ -149,19 +149,6 @@ enum {
PMIC_RG_BANK_FQMTR_RST_SHIFT = 6, 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 */ /* PMIC Frequency Meter Definition */
enum { enum {
PMIC_RG_FQMTR_CKSEL = 0x0118, PMIC_RG_FQMTR_CKSEL = 0x0118,
@ -228,5 +215,4 @@ int rtc_init(int recover);
bool rtc_gpio_init(void); bool rtc_gpio_init(void);
void rtc_boot(void); void rtc_boot(void);
u16 rtc_get_frequency_meter(u16 val, u16 measure_src, u16 window_size); 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 */ #endif /* SOC_MEDIATEK_MT8192_RTC_H */

View File

@ -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 */

View File

@ -177,6 +177,120 @@ struct pmif *get_pmif_controller(int inf, int mstid)
return NULL; 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 mtk_pmif_init(void)
{ {
int ret; int ret;

View File

@ -2,6 +2,7 @@
#include <delay.h> #include <delay.h>
#include <halt.h> #include <halt.h>
#include <soc/clkbuf.h>
#include <soc/mt6359p.h> #include <soc/mt6359p.h>
#include <soc/pmif.h> #include <soc/pmif.h>
#include <soc/rtc.h> #include <soc/rtc.h>
@ -312,43 +313,11 @@ void poweroff(void)
halt(); 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 */ /* the rtc boot flow entry */
void rtc_boot(void) void rtc_boot(void)
{ {
u16 tmp; u16 tmp;
/* dcxo clock init settings */
dcxo_init();
/* dcxo 32k init settings */ /* dcxo 32k init settings */
rtc_write_field(PMIC_RG_DCXO_CW02, 0xF, 0xF, 0); rtc_write_field(PMIC_RG_DCXO_CW02, 0xF, 0xF, 0);
rtc_read(PMIC_RG_SCK_TOP_CON0, &tmp); rtc_read(PMIC_RG_SCK_TOP_CON0, &tmp);

View File

@ -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;
}