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
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

View File

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

View File

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

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,
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,

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__
#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__*/

View File

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

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

View File

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

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