[Feature][Modem]Update MTK MODEM V1.6 baseline version: MOLY.NR15.R3.MD700.IVT.MP1MR3.MP.V1.6

MTK modem version: MT2735_IVT_MOLY.NR15.R3.MD700.IVT.MP1MR3.MP.V1.6.tar.gz
RF  modem version: NA

Change-Id: I45a4c2752fa9d1a618beacd5d40737fb39ab64fb
diff --git a/mcu/driver/devdrv/spmi/src/pmif.c b/mcu/driver/devdrv/spmi/src/pmif.c
new file mode 100644
index 0000000..7ef3e76
--- /dev/null
+++ b/mcu/driver/devdrv/spmi/src/pmif.c
@@ -0,0 +1,753 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein is
+ * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+ * the prior written permission of MediaTek inc. and/or its licensors, any
+ * reproduction, modification, use or disclosure of MediaTek Software, and
+ * information contained herein, in whole or in part, shall be strictly
+ * prohibited.
+ *
+ * MediaTek Inc. (C) 2019. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+ * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+ * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+ * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+ * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+ * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+ * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+ * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+ * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+ * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+ * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+ * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+ * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek
+ * Software") have been modified by MediaTek Inc. All revisions are subject to
+ * any receiver's applicable license agreements with MediaTek Inc.
+ */
+/*
+ * MTK PMIF Driver
+ *
+ * Copyright 2019 MediaTek Co.,Ltd.
+ *
+ * DESCRIPTION:
+ *     This file provides API for other drivers to access PMIC registers
+ *
+ */
+
+#include <pmif.h>
+#include <spmi.h>
+#include <pmif_sw.h>
+#include <spmi_sw.h>
+
+#define GET_SWINF_0_FSM(x)	((x>>1)  & 0x00000007)
+#define GET_PMIF_INIT_DONE(x)	((x>>15) & 0x00000001)
+#define TIMEOUT_WAIT_IDLE	(1000000) /* ap latency concern 1ms */
+
+#define PMIF_CMD_PER_3 (0x1 << PMIF_CMD_EXT_REG_LONG)
+#define PMIF_CMD_PER_1_3 \
+	((0x1 << PMIF_CMD_REG) | (0x1 << PMIF_CMD_EXT_REG_LONG))
+#define PMIF_CMD_PER_2_3 \
+	((0x1 << PMIF_CMD_EXT_REG) | (0x1 << PMIF_CMD_EXT_REG_LONG))
+
+static int pmif_spmi_read_cmd(struct pmif *arb, unsigned char opc,
+		unsigned char sid, unsigned short addr, unsigned char *buf,
+		unsigned short len);
+static int pmif_spmi_write_cmd(struct pmif *arb, unsigned char opc,
+	unsigned char sid, unsigned short addr, const unsigned char *buf,
+	unsigned short len);
+#if PMIF_NO_PMIC
+static int pmif_spmi_read_cmd(struct pmif *arb, unsigned char opc,
+		unsigned char sid, unsigned short addr, unsigned char *buf,
+		unsigned short len)
+{
+	PMIF_INFO("do Nothing.\n");
+	return 0;
+}
+
+static int pmif_spmi_write_cmd(struct pmif *arb, unsigned char opc,
+	unsigned char sid, unsigned short addr, const unsigned char *buf,
+	unsigned short len)
+{
+	PMIF_INFO("do Nothing.\n");
+	return 0;
+}
+
+/* init interface */
+int pmif_spmi_init(int mstid)
+{
+	PMIF_INFO("do Nothing.\n");
+	return 0;
+}
+#else /* #if PMIF_NO_PMIC */
+/* pmif internal API declaration */
+#if PMIF_TIMEOUT
+static unsigned long long pmif_get_current_time(void);
+static int pmif_timeout_ns(unsigned long long start_time_ns,
+	unsigned long long timeout_time_ns);
+static unsigned long long pmif_time2ns(unsigned long long time_us);
+#endif
+static void pmif_enable_soft_reset(int mstid);
+static void pmif_spmi_enable_clk_set(int mstid);
+static void pmif_spmi_force_normal_mode(int mstid);
+static void pmif_spmi_enable_swinf(int mstid, unsigned int chan_no,
+	unsigned int swinf_no);
+static void pmif_spmi_enable_cmdIssue(int mstid, kal_bool en);
+static void pmif_spmi_enable(int mstid);
+
+
+enum pmif_regs {
+	PMIF_INIT_DONE,
+	PMIF_INF_EN,
+	PMIF_INF_CMD_PER_0,
+	PMIF_INF_CMD_PER_1,
+	PMIF_INF_CMD_PER_2,
+	PMIF_INF_CMD_PER_3,
+	PMIF_INF_MAX_BYTECNT_PER_0,
+	PMIF_INF_MAX_BYTECNT_PER_1,
+	PMIF_INF_MAX_BYTECNT_PER_2,
+	PMIF_INF_MAX_BYTECNT_PER_3,
+	PMIF_ARB_EN,
+	PMIF_CMDISSUE_EN,
+	PMIF_TIMER_CTRL,
+	PMIF_SPI_MODE_CTRL,
+	PMIF_IRQ_EVENT_EN_0,
+	PMIF_IRQ_FLAG_0,
+	PMIF_IRQ_CLR_0,
+	PMIF_SWINF_0_ACC,
+	PMIF_SWINF_0_WDATA_31_0,
+	PMIF_SWINF_0_WDATA_63_32,
+	PMIF_SWINF_0_RDATA_31_0,
+	PMIF_SWINF_0_RDATA_63_32,
+	PMIF_SWINF_0_VLD_CLR,
+	PMIF_SWINF_0_STA,
+	PMIF_SWINF_1_ACC,
+	PMIF_SWINF_1_WDATA_31_0,
+	PMIF_SWINF_1_WDATA_63_32,
+	PMIF_SWINF_1_RDATA_31_0,
+	PMIF_SWINF_1_RDATA_63_32,
+	PMIF_SWINF_1_VLD_CLR,
+	PMIF_SWINF_1_STA,
+	PMIF_SWINF_2_ACC,
+	PMIF_SWINF_2_WDATA_31_0,
+	PMIF_SWINF_2_WDATA_63_32,
+	PMIF_SWINF_2_RDATA_31_0,
+	PMIF_SWINF_2_RDATA_63_32,
+	PMIF_SWINF_2_VLD_CLR,
+	PMIF_SWINF_2_STA,
+	PMIF_SWINF_3_ACC,
+	PMIF_SWINF_3_WDATA_31_0,
+	PMIF_SWINF_3_WDATA_63_32,
+	PMIF_SWINF_3_RDATA_31_0,
+	PMIF_SWINF_3_RDATA_63_32,
+	PMIF_SWINF_3_VLD_CLR,
+	PMIF_SWINF_3_STA,
+};
+
+static int mt6885_regs[] = {
+	[PMIF_INIT_DONE] =			0x0000,
+	[PMIF_INF_EN] =				0x0024,
+	[PMIF_INF_CMD_PER_0] =			0x002c,
+	[PMIF_INF_CMD_PER_1] =			0x0030,
+	[PMIF_INF_CMD_PER_2] =			0x0034,
+	[PMIF_INF_CMD_PER_3] =			0x0038,
+	[PMIF_INF_MAX_BYTECNT_PER_0] =		0x003c,
+	[PMIF_INF_MAX_BYTECNT_PER_1] =		0x0040,
+	[PMIF_INF_MAX_BYTECNT_PER_2] =		0x0044,
+	[PMIF_INF_MAX_BYTECNT_PER_3] =		0x0048,
+	[PMIF_ARB_EN] =				0x0150,
+	[PMIF_CMDISSUE_EN] =			0x03B4,
+	[PMIF_TIMER_CTRL] =			0x03E0,
+	[PMIF_SPI_MODE_CTRL] =			0x0400,
+	[PMIF_IRQ_EVENT_EN_0] =                 0x0418,
+	[PMIF_IRQ_FLAG_0] =                     0x0420,
+	[PMIF_IRQ_CLR_0] =                      0x0424,
+	[PMIF_SWINF_0_ACC] =			0x0C00,
+	[PMIF_SWINF_0_WDATA_31_0] =		0x0C04,
+	[PMIF_SWINF_0_WDATA_63_32] =		0x0C08,
+	[PMIF_SWINF_0_RDATA_31_0] =		0x0C14,
+	[PMIF_SWINF_0_RDATA_63_32] =		0x0C18,
+	[PMIF_SWINF_0_VLD_CLR] =		0x0C24,
+	[PMIF_SWINF_0_STA] =			0x0C28,
+	[PMIF_SWINF_1_ACC] =			0x0C40,
+	[PMIF_SWINF_1_WDATA_31_0] =		0x0C44,
+	[PMIF_SWINF_1_WDATA_63_32] =		0x0C48,
+	[PMIF_SWINF_1_RDATA_31_0] =		0x0C54,
+	[PMIF_SWINF_1_RDATA_63_32] =		0x0C58,
+	[PMIF_SWINF_1_VLD_CLR] =		0x0C64,
+	[PMIF_SWINF_1_STA] =			0x0C68,
+	[PMIF_SWINF_2_ACC] =			0x0C80,
+	[PMIF_SWINF_2_WDATA_31_0] =		0x0C84,
+	[PMIF_SWINF_2_WDATA_63_32] =		0x0C88,
+	[PMIF_SWINF_2_RDATA_31_0] =		0x0C94,
+	[PMIF_SWINF_2_RDATA_63_32] =		0x0C98,
+	[PMIF_SWINF_2_VLD_CLR] =		0x0CA4,
+	[PMIF_SWINF_2_STA] =			0x0CA8,
+	[PMIF_SWINF_3_ACC] =			0x0CC0,
+	[PMIF_SWINF_3_WDATA_31_0] =		0x0CC4,
+	[PMIF_SWINF_3_WDATA_63_32] =		0x0CC8,
+	[PMIF_SWINF_3_RDATA_31_0] =		0x0CD4,
+	[PMIF_SWINF_3_RDATA_63_32] =		0x0CD8,
+	[PMIF_SWINF_3_VLD_CLR] =		0x0CE4,
+	[PMIF_SWINF_3_STA] =			0x0CE8,
+};
+
+#if defined(CHIP10992)
+static int mt6880_regs[] = {
+	[PMIF_INIT_DONE] =			0x0000,
+	[PMIF_INF_EN] =				0x0024,
+	[PMIF_INF_CMD_PER_0] =			0x002c,
+	[PMIF_INF_CMD_PER_1] =			0x0030,
+	[PMIF_INF_CMD_PER_2] =			0x0034,
+	[PMIF_INF_CMD_PER_3] =			0x0038,
+	[PMIF_INF_MAX_BYTECNT_PER_0] =		0x003c,
+	[PMIF_INF_MAX_BYTECNT_PER_1] =		0x0040,
+	[PMIF_INF_MAX_BYTECNT_PER_2] =		0x0044,
+	[PMIF_INF_MAX_BYTECNT_PER_3] =		0x0048,
+	[PMIF_ARB_EN] =				0x0150,
+	[PMIF_CMDISSUE_EN] =			0x03B8,
+	[PMIF_TIMER_CTRL] =			0x03E4,
+	[PMIF_SPI_MODE_CTRL] =			0x0408,
+	[PMIF_IRQ_EVENT_EN_0] =			0x0420,
+	[PMIF_IRQ_FLAG_0] =			0x0428,
+	[PMIF_IRQ_CLR_0] =			0x042C,
+	[PMIF_SWINF_0_ACC] =			0x0800,
+	[PMIF_SWINF_0_WDATA_31_0] =		0x0804,
+	[PMIF_SWINF_0_RDATA_31_0] =		0x0814,
+	[PMIF_SWINF_0_VLD_CLR] =		0x0824,
+	[PMIF_SWINF_0_STA] =			0x0828,
+	[PMIF_SWINF_1_ACC] =			0x0840,
+	[PMIF_SWINF_1_WDATA_31_0] =		0x0844,
+	[PMIF_SWINF_1_RDATA_31_0] =		0x0854,
+	[PMIF_SWINF_1_VLD_CLR] =		0x0864,
+	[PMIF_SWINF_1_STA] =			0x0868,
+	[PMIF_SWINF_2_ACC] =			0x0880,
+	[PMIF_SWINF_2_WDATA_31_0] =		0x0884,
+	[PMIF_SWINF_2_RDATA_31_0] =		0x0894,
+	[PMIF_SWINF_2_VLD_CLR] =		0x08A4,
+	[PMIF_SWINF_2_STA] =			0x08A8,
+	[PMIF_SWINF_3_ACC] =			0x08C0,
+	[PMIF_SWINF_3_WDATA_31_0] =		0x08C4,
+	[PMIF_SWINF_3_RDATA_31_0] =		0x08D4,
+	[PMIF_SWINF_3_VLD_CLR] =		0x08E4,
+	[PMIF_SWINF_3_STA] =			0x08E8,
+};
+#else
+static int mt6853_regs[] = {
+	[PMIF_INIT_DONE] =			0x0000,
+	[PMIF_INF_EN] =				0x0024,
+	[PMIF_INF_CMD_PER_0] =			0x002c,
+	[PMIF_INF_CMD_PER_1] =			0x0030,
+	[PMIF_INF_CMD_PER_2] =			0x0034,
+	[PMIF_INF_CMD_PER_3] =			0x0038,
+	[PMIF_INF_MAX_BYTECNT_PER_0] =		0x003c,
+	[PMIF_INF_MAX_BYTECNT_PER_1] =		0x0040,
+	[PMIF_INF_MAX_BYTECNT_PER_2] =		0x0044,
+	[PMIF_INF_MAX_BYTECNT_PER_3] =		0x0048,
+	[PMIF_ARB_EN] =				0x0150,
+	[PMIF_CMDISSUE_EN] =			0x03B8,
+	[PMIF_TIMER_CTRL] =			0x03E4,
+	[PMIF_SPI_MODE_CTRL] =			0x0408,
+	[PMIF_IRQ_EVENT_EN_0] =                 0x0420,
+	[PMIF_IRQ_FLAG_0] =                     0x0428,
+	[PMIF_IRQ_CLR_0] =                      0x042C,
+	[PMIF_SWINF_0_ACC] =			0x0C00,
+	[PMIF_SWINF_0_WDATA_31_0] =		0x0C04,
+	[PMIF_SWINF_0_WDATA_63_32] =		0x0C08,
+	[PMIF_SWINF_0_RDATA_31_0] =		0x0C14,
+	[PMIF_SWINF_0_RDATA_63_32] =		0x0C18,
+	[PMIF_SWINF_0_VLD_CLR] =		0x0C24,
+	[PMIF_SWINF_0_STA] =			0x0C28,
+	[PMIF_SWINF_1_ACC] =			0x0C40,
+	[PMIF_SWINF_1_WDATA_31_0] =		0x0C44,
+	[PMIF_SWINF_1_WDATA_63_32] =		0x0C48,
+	[PMIF_SWINF_1_RDATA_31_0] =		0x0C54,
+	[PMIF_SWINF_1_RDATA_63_32] =		0x0C58,
+	[PMIF_SWINF_1_VLD_CLR] =		0x0C64,
+	[PMIF_SWINF_1_STA] =			0x0C68,
+	[PMIF_SWINF_2_ACC] =			0x0C80,
+	[PMIF_SWINF_2_WDATA_31_0] =		0x0C84,
+	[PMIF_SWINF_2_WDATA_63_32] =		0x0C88,
+	[PMIF_SWINF_2_RDATA_31_0] =		0x0C94,
+	[PMIF_SWINF_2_RDATA_63_32] =		0x0C98,
+	[PMIF_SWINF_2_VLD_CLR] =		0x0CA4,
+	[PMIF_SWINF_2_STA] =			0x0CA8,
+	[PMIF_SWINF_3_ACC] =			0x0CC0,
+	[PMIF_SWINF_3_WDATA_31_0] =		0x0CC4,
+	[PMIF_SWINF_3_WDATA_63_32] =		0x0CC8,
+	[PMIF_SWINF_3_RDATA_31_0] =		0x0CD4,
+	[PMIF_SWINF_3_RDATA_63_32] =		0x0CD8,
+	[PMIF_SWINF_3_VLD_CLR] =		0x0CE4,
+	[PMIF_SWINF_3_STA] =			0x0CE8,
+};
+#endif
+
+static struct pmif pmif_spmi_arb[] = {
+	{
+		.base = (unsigned int *)PMIF_SPMI_BASE,
+		.regs = mt6885_regs,
+		.spmimst_base = (unsigned int *)SPMI_MST_BASE,
+		.swinf_ch_start = PMIF_SWINF_0_CHAN_NO,
+		.swinf_no = PMIF_AP_SWINF_NO,
+		.write = 0x0,
+		.mstid = SPMI_MASTER_0,
+		.pmifid = PMIF_PMIFID,
+		.read_cmd = pmif_spmi_read_cmd,
+		.write_cmd = pmif_spmi_write_cmd,
+		.pmif_enable_clk_set = pmif_spmi_enable_clk_set,
+		.pmif_force_normal_mode = pmif_spmi_force_normal_mode,
+		.pmif_enable_swinf = pmif_spmi_enable_swinf,
+		.pmif_enable_cmdIssue = pmif_spmi_enable_cmdIssue,
+		.pmif_enable = pmif_spmi_enable,
+		.is_pmif_init_done = is_pmif_spmi_init_done,
+	},
+	{
+		.base = (unsigned int *)PMIF_SPMI_BASE,
+#if defined(CHIP10992)
+		.regs = mt6880_regs,
+#else
+		.regs = mt6853_regs,
+#endif
+		.spmimst_base = (unsigned int *)SPMI_MST_BASE,
+		.swinf_ch_start = PMIF_SWINF_0_CHAN_NO,
+		.swinf_no = PMIF_AP_SWINF_NO,
+		.write = 0x0,
+		.mstid = SPMI_MASTER_1,
+		.pmifid = PMIF_PMIFID,
+		.read_cmd = pmif_spmi_read_cmd,
+		.write_cmd = pmif_spmi_write_cmd,
+		.pmif_enable_clk_set = pmif_spmi_enable_clk_set,
+		.pmif_force_normal_mode = pmif_spmi_force_normal_mode,
+		.pmif_enable_swinf = pmif_spmi_enable_swinf,
+		.pmif_enable_cmdIssue = pmif_spmi_enable_cmdIssue,
+		.pmif_enable = pmif_spmi_enable,
+		.is_pmif_init_done = is_pmif_spmi_init_done,
+	},
+#if !defined(MT6885) && !defined(MT6873)
+	{
+		.base = (unsigned int *)PMIF_SPMI_P_BASE,
+#if defined(CHIP10992)
+		.regs = mt6880_regs,
+#else
+		.regs = mt6853_regs,
+#endif
+		.spmimst_base = (unsigned int *)SPMI_MST_P_BASE,
+		.swinf_ch_start = PMIF_SWINF_0_CHAN_NO_P,
+		.swinf_no = PMIF_AP_SWINF_NO_P,
+		.write = 0x0,
+		.mstid = SPMI_MASTER_P_1,
+		.pmifid = PMIF_PMIFID_2,
+		.read_cmd = pmif_spmi_read_cmd,
+		.write_cmd = pmif_spmi_write_cmd,
+		.pmif_enable_clk_set = pmif_spmi_enable_clk_set,
+		.pmif_force_normal_mode = pmif_spmi_force_normal_mode,
+		.pmif_enable_swinf = pmif_spmi_enable_swinf,
+		.pmif_enable_cmdIssue = pmif_spmi_enable_cmdIssue,
+		.pmif_enable = pmif_spmi_enable,
+		.is_pmif_init_done = is_pmif_spmi_init_done,
+	},
+#endif
+};
+/* static struct pmif pmif_spi_arb[0]; */
+
+/* pmif timeout */
+#if PMIF_TIMEOUT
+static unsigned long long pmif_get_current_time(void)
+{
+	return gpt4_get_current_tick();
+}
+
+static int pmif_timeout_ns(unsigned long long start_time_ns,
+	unsigned long long timeout_time_ns)
+{
+	return gpt4_timeout_tick(start_time_ns, timeout_time_ns);
+}
+
+static unsigned long long pmif_time2ns(unsigned long long time_us)
+{
+	return gpt4_time2tick_us(time_us);
+}
+#endif
+static inline unsigned int pmif_check_idle(int mstid) {
+	struct pmif *arb = get_pmif_controller(PMIF_SPMI, mstid);
+	unsigned int reg_rdata, offset = 0;
+#if PMIF_TIMEOUT
+	unsigned long long start_time_ns = 0, end_time_ns = 0, timeout_ns = 0;
+	unsigned long time_cnt = 100000;
+
+	start_time_ns = pmif_get_current_time();
+	timeout_ns = pmif_time2ns(TIMEOUT_WAIT_IDLE);
+#endif
+
+	do {
+#if PMIF_TIMEOUT
+		if (pmif_timeout_ns(start_time_ns, timeout_ns)) {
+			end_time_ns = pmif_get_current_time();
+			PMIF_ERR("%s timeout %d %d\n", __func__, start_time_ns,
+					end_time_ns - start_time_ns);
+			return -ETIMEDOUT;
+		}
+		if ((time_cnt--) == 0) {
+			PMIF_ERR("%s timeout %d %d\n", __func__, start_time_ns,
+					end_time_ns - start_time_ns);
+			return -ETIMEDOUT;
+		}
+#endif
+		offset = arb->regs[PMIF_SWINF_0_STA] + (0x40 * arb->swinf_no);
+		reg_rdata = DRV_Reg32(arb->base + offset);
+	} while(GET_SWINF_0_FSM(reg_rdata) != SWINF_FSM_IDLE);
+
+    return 0;
+}
+
+static inline unsigned int pmif_check_vldclr(int mstid) {
+	struct pmif *arb = get_pmif_controller(PMIF_SPMI, mstid);
+	unsigned int reg_rdata, offset = 0;
+#if PMIF_TIMEOUT
+	unsigned long long start_time_ns = 0, end_time_ns = 0, timeout_ns = 0;
+	unsigned long time_cnt = 100000;
+
+	start_time_ns = pmif_get_current_time();
+	timeout_ns = pmif_time2ns(TIMEOUT_WAIT_IDLE);
+#endif
+
+	do {
+#if PMIF_TIMEOUT
+		if (pmif_timeout_ns(start_time_ns, timeout_ns)) {
+			end_time_ns = pmif_get_current_time();
+			PMIF_ERR("%s timeout %d %d\n", __func__, start_time_ns,
+					end_time_ns - start_time_ns);
+			return -ETIMEDOUT;
+		}
+		if ((time_cnt--) == 0) {
+			PMIF_ERR("%s timeout %d %d\n", __func__, start_time_ns,
+					end_time_ns - start_time_ns);
+			return -ETIMEDOUT;
+		}
+#endif
+		offset = arb->regs[PMIF_SWINF_0_STA] + (0x40 * arb->swinf_no);
+		reg_rdata = DRV_Reg32(arb->base + offset);
+	} while(GET_SWINF_0_FSM(reg_rdata) != SWINF_FSM_WFVLDCLR);
+
+    return 0;
+}
+static void pmif_enable_soft_reset(int mstid)
+{
+	DRV_WriteReg32(INFRA_GLOBALCON_RST2_SET, 0x1 << 14);
+	DRV_WriteReg32(INFRA_GLOBALCON_RST2_CLR, 0x1 << 14);
+
+	PMIF_INFO("%s done\n", __func__);
+}
+
+static void pmif_spmi_enable_clk_set(int mstid)
+{
+#if !defined(CONFIG_FPGA_EARLY_PORTING)
+	/* TBD */
+	DRV_WriteReg32(CLK_CFG_8_CLR, (0x1 << 15) | (0x1 << 12) | (0x7 << 8));
+	DRV_WriteReg32(CLK_CFG_UPDATE1, 0x1 << 2);
+#endif
+
+	/* sys_ck cg enable, turn off clock */
+	DRV_WriteReg32(MODULE_SW_CG_0_SET, 0x0000000f);
+	/* turn off clock */
+	DRV_WriteReg32(MODULE_SW_CG_2_SET, 0x00000100);
+
+	/* toggle SPMI sw reset */
+	pmif_enable_soft_reset(mstid);
+
+	/* sys_ck cg enable, turn on clock */
+	DRV_WriteReg32(MODULE_SW_CG_0_CLR, 0x0000000f);
+	/* turn on clock */
+	DRV_WriteReg32(MODULE_SW_CG_2_CLR, 0x00000100);
+
+	PMIF_INFO("%s done\n", __func__);
+}
+
+static void pmif_spmi_force_normal_mode(int mstid)
+{
+	struct pmif *arb = get_pmif_controller(PMIF_SPMI, SPMI_MASTER_0);
+	unsigned int offset = 0;
+
+	/* Force SPMI in normal mode. */
+	offset = arb->regs[PMIF_SPI_MODE_CTRL];
+	DRV_WriteReg32(arb->base + offset,
+		DRV_Reg32(arb->base + offset) & (~(0x3 << 9)));
+	DRV_WriteReg32(arb->base + offset,
+		DRV_Reg32(arb->base + offset) | (0x1 << 9));
+
+	PMIF_INFO("%s done\n", __func__);
+}
+
+static void pmif_spmi_enable_swinf(int mstid, unsigned int chan_no,
+	unsigned int swinf_no)
+{
+	struct pmif *arb = get_pmif_controller(PMIF_SPMI, mstid);
+	unsigned int offset = 0;
+
+	/* Enable swinf */
+	offset = arb->regs[PMIF_INF_EN];
+	DRV_WriteReg32(arb->base + offset,
+			0x1 << (arb->swinf_ch_start + arb->swinf_no));
+
+	/* Enable arbitration */
+	offset = arb->regs[PMIF_ARB_EN];
+	DRV_WriteReg32(arb->base + offset,
+			0x1 << (arb->swinf_ch_start + arb->swinf_no));
+
+	PMIF_INFO("%s done\n", __func__);
+}
+
+static void pmif_spmi_enable_cmdIssue(int mstid, kal_bool en)
+{
+	struct pmif *arb = get_pmif_controller(PMIF_SPMI, mstid);
+
+	/* Enable cmdIssue */
+	DRV_WriteReg32(arb->base + arb->regs[PMIF_CMDISSUE_EN], en);
+
+	PMIF_INFO("%s done\n", __func__);
+}
+
+static void pmif_spmi_enable(int mstid)
+{
+	struct pmif *arb = get_pmif_controller(PMIF_SPMI, mstid);
+#if PMIF_NORMAL_BOOT
+	unsigned int bytecnt_per = 0, hw_bytecnt = 0;
+	unsigned int cmd_per = 0;
+
+	/* clear all cmd permission for per channel */
+	DRV_WriteReg32(arb->base + arb->regs[PMIF_INF_CMD_PER_0], 0);
+	DRV_WriteReg32(arb->base + arb->regs[PMIF_INF_CMD_PER_1], 0);
+	DRV_WriteReg32(arb->base + arb->regs[PMIF_INF_CMD_PER_2], 0);
+	DRV_WriteReg32(arb->base + arb->regs[PMIF_INF_CMD_PER_3], 0);
+	/* enable if we need cmd 0~3 permission for per channel */
+	cmd_per = PMIF_CMD_PER_3 << 28 | PMIF_CMD_PER_3 << 24 |
+		PMIF_CMD_PER_3 << 20 | PMIF_CMD_PER_1_3 << 16 |
+		PMIF_CMD_PER_3 << 8 | PMIF_CMD_PER_1_3 << 0;
+	DRV_WriteReg32(arb->base + arb->regs[PMIF_INF_CMD_PER_0], cmd_per);
+	cmd_per = PMIF_CMD_PER_3 << 4;
+	DRV_WriteReg32(arb->base + arb->regs[PMIF_INF_CMD_PER_1], cmd_per);
+
+	/* set bytecnt max limitation*/
+	DRV_WriteReg32(arb->base + arb->regs[PMIF_INF_MAX_BYTECNT_PER_0], 0);
+	DRV_WriteReg32(arb->base + arb->regs[PMIF_INF_MAX_BYTECNT_PER_1], 0);
+	DRV_WriteReg32(arb->base + arb->regs[PMIF_INF_MAX_BYTECNT_PER_2], 0);
+	DRV_WriteReg32(arb->base + arb->regs[PMIF_INF_MAX_BYTECNT_PER_3], 0);
+	/* hw bytecnt indicate when we set 0, it can send 1 byte;
+	 * set 1, it can send 2 byte.
+	 */
+	hw_bytecnt = PMIF_BYTECNT_MAX -1;
+	if (hw_bytecnt > 0) {
+		bytecnt_per = hw_bytecnt << 28 | hw_bytecnt << 24 |
+			hw_bytecnt << 20 | hw_bytecnt << 16 |
+			hw_bytecnt << 12 | hw_bytecnt << 8 |
+			hw_bytecnt << 4 | hw_bytecnt << 0;
+	}
+	DRV_WriteReg32(arb->base + arb->regs[PMIF_INF_MAX_BYTECNT_PER_0],
+			bytecnt_per);
+	DRV_WriteReg32(arb->base + arb->regs[PMIF_INF_MAX_BYTECNT_PER_1],
+			bytecnt_per);
+	DRV_WriteReg32(arb->base + arb->regs[PMIF_INF_MAX_BYTECNT_PER_2],
+			bytecnt_per);
+	DRV_WriteReg32(arb->base + arb->regs[PMIF_INF_MAX_BYTECNT_PER_3],
+			bytecnt_per);
+#endif /* end of #if PMIF_NORMAL_BOOT */
+	DRV_WriteReg32(arb->base + arb->regs[PMIF_INF_EN], 0x2F5);
+	DRV_WriteReg32(arb->base + arb->regs[PMIF_ARB_EN], 0x2F5);
+	DRV_WriteReg32(arb->base + arb->regs[PMIF_TIMER_CTRL], 0x3);
+	DRV_WriteReg32(arb->base + arb->regs[PMIF_INIT_DONE], 0x1);
+
+	PMIF_INFO("%s done\n", __func__);
+}
+
+static int pmif_spmi_read_cmd(struct pmif *arb, unsigned char opc,
+		unsigned char sid, unsigned short addr, unsigned char *buf,
+		unsigned short len)
+{
+	int write = 0x0;
+	unsigned int ret = 0, offset = 0, data = 0;
+	unsigned char bc = len - 1;
+
+	if ((sid & ~(0xf)) != 0x0)
+		return -EINVAL;
+
+	if (len > PMIF_BYTECNT_MAX)
+		return -EINVAL;
+
+	/* Check the opcode */
+	if (opc >= 0x60 && opc <= 0x7F)
+		opc = PMIF_CMD_REG;
+	else if (opc >= 0x20 && opc <= 0x2F)
+		opc = PMIF_CMD_EXT_REG;
+	else if (opc >= 0x38 && opc <= 0x3F)
+		opc = PMIF_CMD_EXT_REG_LONG;
+	else
+		return -EINVAL;
+
+	/* ENTER_CRITICAL(); */
+	kal_hrt_take_itc_lock(KAL_ITC_SPMI_LOCK, KAL_INFINITE_WAIT);
+
+	/* Wait for Software Interface FSM state to be IDLE. */
+	ret = pmif_check_idle(arb->mstid);
+	if(ret)
+		return ret;
+
+	/* Send the command. */
+	offset = arb->regs[PMIF_SWINF_0_ACC] + (0x40 * arb->swinf_no);
+	DRV_WriteReg32(arb->base + offset,
+		(opc << 30) | (write << 29) | (sid << 24) | (bc << 16) | addr);
+
+	/* Wait for Software Interface FSM state to be WFVLDCLR,
+	 *
+	 * read the data and clear the valid flag.
+	 */
+	if(write == 0)
+	{
+		ret = pmif_check_vldclr(arb->mstid);
+		if(ret)
+			return ret;
+
+		offset =
+		arb->regs[PMIF_SWINF_0_RDATA_31_0] + (0x40 * arb->swinf_no);
+		data = DRV_Reg32(arb->base + offset);
+		memcpy(buf, &data, (bc & 3) + 1);
+		offset =
+		arb->regs[PMIF_SWINF_0_VLD_CLR] + (0x40 * arb->swinf_no);
+		DRV_WriteReg32(arb->base + offset, 0x1);
+	}
+	kal_hrt_give_itc_lock(KAL_ITC_SPMI_LOCK);
+	/* EXIT_CRITICAL(); */
+
+	return 0x0;
+}
+
+static int pmif_spmi_write_cmd(struct pmif *arb, unsigned char opc,
+	unsigned char sid, unsigned short addr, const unsigned char *buf,
+	unsigned short len)
+{
+	int write = 0x1;
+	unsigned int ret = 0, offset = 0, data = 0;
+	unsigned char bc = len - 1;
+
+	if ((sid & ~(0xf)) != 0x0)
+		return -EINVAL;
+
+	if (len > PMIF_BYTECNT_MAX)
+		return -EINVAL;
+
+	/* Check the opcode */
+	if (opc >= 0x40 && opc <= 0x5F)
+		opc = PMIF_CMD_REG;
+	else if (opc <= 0x0F)
+		opc = PMIF_CMD_EXT_REG;
+	else if (opc >= 0x30 && opc <= 0x37)
+		opc = PMIF_CMD_EXT_REG_LONG;
+	else if (opc >= 0x80)
+		opc = PMIF_CMD_REG_0;
+	else
+		return -EINVAL;
+
+	/* ENTER_CRITICAL(); */
+	kal_hrt_take_itc_lock(KAL_ITC_SPMI_LOCK, KAL_INFINITE_WAIT);
+
+	/* Wait for Software Interface FSM state to be IDLE. */
+	ret = pmif_check_idle(arb->mstid);
+	if(ret)
+		return ret;
+
+	/* Set the write data. */
+	if (write == 1)
+	{
+		offset =
+		arb->regs[PMIF_SWINF_0_WDATA_31_0] + (0x40 * arb->swinf_no);
+		memcpy(&data, buf, (bc & 3) + 1);
+		DRV_WriteReg32(arb->base + offset, data);
+	}
+	/* Send the command. */
+	offset = arb->regs[PMIF_SWINF_0_ACC] + (0x40 * arb->swinf_no);
+	DRV_WriteReg32(arb->base + offset,
+		(opc << 30) | (write << 29) | (sid << 24) |
+		(bc << 16) | addr);
+
+	kal_hrt_give_itc_lock(KAL_ITC_SPMI_LOCK);
+	/* EXIT_CRITICAL(); */
+
+	return 0x0;
+}
+
+struct pmif *get_pmif_controller(int inf, int mstid)
+{
+	if (inf == PMIF_SPMI) {
+		return &pmif_spmi_arb[mstid];
+	} else if (inf == PMIF_SPI) {
+		/* TBD
+		 *pmif_spi_arb[mstid].base = (unsigned int *)PMIF_SPI_BASE;
+		 *pmif_spi_arb[mstid].swinf_no = 0x0;
+		 *pmif_spi_arb[mstid].write = 0x0;
+		 *pmif_spi_arb[mstid].pmifid = 0x0;
+		 *pmif_spi_arb[mstid].read_cmd = pmif_spi_read_cmd;
+		 *pmif_spi_arb[mstid].write_cmd = pmif_spi_write_cmd;
+		 *pmif_spi_arb[mstid].read_cmd_nochk = pmif_spi_read_cmd_nochk;
+		 *pmif_spi_arb[mstid].write_cmd_nochk =
+		 *		pmif_spi_write_cmd_nochk;
+		 *return &pmif_spi_arb[mstid];
+		 */
+	}
+
+	return 0;
+}
+int is_pmif_spmi_init_done(int mstid)
+{
+	int ret = 0;
+
+	struct pmif *arb = get_pmif_controller(PMIF_SPMI, mstid);
+
+	ret = DRV_Reg32(arb->base + arb->regs[PMIF_INIT_DONE]);
+	PMIF_INFO("%s ret = %d\n", __func__, ret);
+	if ((ret & 0x1) == 1)
+		return 0;
+
+	return -ENODEV;
+}
+
+int pmif_spmi_init(int mstid)
+{
+	struct pmif *arb = get_pmif_controller(PMIF_SPMI, mstid);
+	int ret = 0;
+
+	INIT_CRITICAL();
+
+	if (is_pmif_spmi_init_done(mstid) != 0) {
+		arb->pmif_enable_clk_set(mstid);
+		arb->pmif_force_normal_mode(mstid);
+		/* Enable SWINF and arbitration for AP. */
+		arb->pmif_enable_swinf(mstid, PMIF_SWINF_0_CHAN_NO,
+			PMIF_AP_SWINF_NO);
+		arb->pmif_enable_cmdIssue(mstid,KAL_TRUE);
+
+		arb->pmif_enable(mstid);
+		ret = arb->is_pmif_init_done(mstid);
+		if(ret) {
+			PMIF_ERR("init done check fail\n");
+			return -ENODEV;
+		}
+	}
+
+	ret = spmi_init(arb);
+	if(ret) {
+		PMIF_ERR("init fail\n");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+#endif /* endif PMIF_NO_PMIC */