[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/spmi.c b/mcu/driver/devdrv/spmi/src/spmi.c
new file mode 100644
index 0000000..f982a47
--- /dev/null
+++ b/mcu/driver/devdrv/spmi/src/spmi.c
@@ -0,0 +1,992 @@
+/* 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 SPMI Driver
+ *
+ * Copyright 2018 MediaTek Co.,Ltd.
+ *
+ * DESCRIPTION:
+ *     This file provides API for other drivers to access PMIC registers
+ *
+ */
+
+#include <spmi.h>
+#include <pmif.h>
+#include <pmif_sw.h>
+#include <spmi_sw.h>
+#include <mt6315_upmu_hw.h>
+
+static int mt6885_spmi_regs[] = {
+	[SPMI_OP_ST_CTRL] =		0x0000,
+	[SPMI_GRP_ID_EN] =		0x0004,
+	[SPMI_OP_ST_STA] =		0x0008,
+	[SPMI_MST_SAMPL] =		0x000c,
+	[SPMI_MST_REQ_EN] =		0x0010,
+#if SPMI_RCS_SUPPORT
+	[SPMI_RCS_CTRL] =		0x0014,
+	[SPMI_SLV_3_0_EINT] =		0x0020,
+	[SPMI_SLV_7_4_EINT] =		0x0024,
+	[SPMI_SLV_B_8_EINT] =		0x0028,
+	[SPMI_SLV_F_C_EINT] =		0x002c,
+#endif /* #if SPMI_RCS_SUPPORT */
+	[SPMI_REC_CTRL] =		0x0040,
+	[SPMI_REC0] =			0x0044,
+	[SPMI_REC1] =			0x0048,
+	[SPMI_REC2] =			0x004c,
+	[SPMI_REC3] =			0x0050,
+	[SPMI_REC4] =			0x0054,
+#if SPMI_RCS_SUPPORT
+	[SPMI_REC_CMD_DEC] =		0x005c,
+	[SPMI_DEC_DBG] =		0x00f8,
+#endif
+	[SPMI_MST_DBG] =		0x00fc,
+};
+
+static struct pmif *pmif_spmi_arb_ctrl[SPMI_MASTER_MAX];
+#if MT63xx_EVB
+#if defined(MT6885) || defined(MT6873)
+struct spmi_device spmi_dev[] = {
+	{
+		.slvid = SPMI_SLAVE_3,
+		.grpiden = 0x800,
+		.type = BUCK_MD,
+		.type_id = BUCK_MD_ID,
+		.mstid = SPMI_MASTER_0,/* spmi-m */
+		.hwcid_addr = 0x09,
+		.hwcid_val = 0x15,
+		.swcid_addr = 0x0b,
+		.swcid_val = 0x15,
+		.pmif_arb = NULL,
+	},	{
+		.slvid = SPMI_SLAVE_6,
+		.grpiden = 0x800,
+		.type = BUCK_CPU,
+		.type_id = BUCK_CPU_ID,
+		.mstid = SPMI_MASTER_0,/* spmi-m */
+		.hwcid_addr = 0x09,
+		.hwcid_val = 0x15,
+		.swcid_addr = 0x0b,
+		.swcid_val = 0x15,
+		.pmif_arb = NULL,
+	},	{
+		.slvid = SPMI_SLAVE_7,
+		.grpiden = 0x800,
+		.type = BUCK_GPU,
+		.type_id = BUCK_GPU_ID,
+		.mstid = SPMI_MASTER_0,/* spmi-m */
+		.hwcid_addr = 0x09,
+		.hwcid_val = 0x15,
+		.swcid_addr = 0x0b,
+		.swcid_val = 0x15,
+		.pmif_arb = NULL,
+	},
+};
+#elif  defined(MT6853)
+#if defined(MT6315)
+struct spmi_device spmi_dev[] = {
+	{
+		.slvid = SPMI_SLAVE_3,
+		.grpiden = 0x800,
+		.type = BUCK_MD,
+		.type_id = BUCK_MD_ID,
+		.mstid = SPMI_MASTER_1,/* spmi-m */
+		.hwcid_addr = 0x09,
+		.hwcid_val = 0x15,
+		.swcid_addr = 0x0b,
+		.swcid_val = 0x15,
+		.pmif_arb = NULL,
+	},
+};
+#else
+struct spmi_device spmi_dev[] = {
+	{
+		.slvid = SPMI_SLAVE_9,
+		.grpiden = 0x0,
+		.type = SUB_PMIC,
+		.type_id = SUB_PMIC_ID,
+		.mstid = SPMI_MASTER_1,/* spmi-m */
+		.hwcid_addr = 0x0000,
+		.hwcid_val = 0x70,/* check [7:4] */
+		.swcid_addr = 0x0001,
+		.swcid_val = 0x08,/* check [3:0] */
+		.pmif_arb = NULL,
+	},	{
+		.slvid = SPMI_SLAVE_8,
+		.grpiden = 0x0,
+		.type = BUCK_MD,
+		.type_id = BUCK_MD_ID,
+		.mstid = SPMI_MASTER_P_1, /* spmi-p */
+		.hwcid_addr = 0x0706,
+		.hwcid_val = 0x00,
+		.swcid_addr = 0x0706,
+		.swcid_val = 0x00,
+		.pmif_arb = NULL,
+	},
+};
+#endif
+#elif  defined(CHIP10992)
+struct spmi_device spmi_dev[] = {
+	{
+		.slvid = SPMI_SLAVE_4,
+		.grpiden = 0x1 << 0xB,
+		.type = MAIN_PMIC,
+		.type_id = MAIN_PMIC_ID,
+		.mstid = SPMI_MASTER_1,/* spmi-m */
+		.hwcid_addr = 0x09,
+		.hwcid_val = 0x30,
+		.swcid_addr = 0x0b,
+		.swcid_val = 0x30,
+		.pmif_arb = NULL,
+	}, {
+		.slvid = SPMI_SLAVE_4,
+		.grpiden = 0x1 << 0xB,
+		.type = BUCK_MD,
+		.type_id = BUCK_MD_ID,
+		.mstid = SPMI_MASTER_P_1,/* spmi-p */
+		.hwcid_addr = 0x01A0, /* TOP_VRCTL_VR0_EN */
+		.hwcid_val = 0xFF, /* All BUCK EN = 0xFF */
+		.pmif_arb = NULL,
+	},
+};
+#endif /* end of #if defined(MT6885) || defined(MT6873) */
+#else
+struct spmi_device spmi_dev[] = {
+	{
+		.slvid = SPMI_SLAVE_12,
+		.grpiden = 0x100,
+		.type = BUCK_MD,
+		.type_id = BUCK_MD_ID,
+		.pmif_arb = NULL,
+	},	{
+		.slvid = SPMI_SLAVE_10,
+		.grpiden = 0x100,
+		.type = BUCK_CPU,
+		.type_id = BUCK_CPU_ID,
+		.pmif_arb = NULL,
+	},	{
+		.slvid = SPMI_SLAVE_11,
+		.grpiden = 0x100,
+		.type = BUCK_GPU,
+		.type_id = BUCK_GPU_ID,
+		.pmif_arb = NULL,
+	},
+};
+#endif
+unsigned char spmi_device_cnt;
+
+/* spmi internal API declaration */
+static int spmi_config_master(unsigned int mstid, kal_bool en);
+static int spmi_config_slave(struct spmi_device *dev);
+static int spmi_cali_rd_clock_polarity(struct spmi_device *dev,
+		unsigned int mstid);
+static int spmi_ctrl_op_st(int mstid, unsigned int grpiden,
+	unsigned int sid, unsigned int cmd);
+#if SPMI_RCS_SUPPORT
+static int spmi_enable_rcs(struct spmi_device *dev, unsigned int mstid);
+int spmi_read_eint_sta(unsigned char *slv_eint_sta);
+#endif
+#if SPMI_DEBUG
+static int spmi_rw_test(struct spmi_device *dev);
+static int spmi_read_check(struct spmi_device *dev);
+static int spmi_drv_ut(struct spmi_device *dev, unsigned int ut);
+#endif
+int spmi_enable_group_id(int mstid, unsigned int grpiden);
+int spmi_lock_slave_reg(struct spmi_device *dev);
+int spmi_unlock_slave_reg(struct spmi_device *dev);
+
+#if SPMI_NO_PMIC
+int spmi_init(struct pmif *pmif_arb)
+{
+	SPMI_INFO("do Nothing.\n");
+	return 0;
+}
+
+#else /* #ifdef SPMI_NO_PMIC */
+/*
+ * Function : mtk_spmi_readl()
+ * Description : mtk spmi controller read api
+ * Parameter :
+ * Return :
+ */
+unsigned int spmi_readl(int mstid, enum spmi_regs reg)
+{
+	struct pmif *arb = get_pmif_controller(PMIF_SPMI, mstid);
+
+	return DRV_Reg32(arb->spmimst_base + arb->spmimst_regs[reg]);
+}
+
+/*
+ * Function : mtk_spmi_writel()
+ * Description : mtk spmi controller write api
+ * Parameter :
+ * Return :
+ */
+void spmi_writel(int mstid, enum spmi_regs reg, unsigned int val)
+{
+	struct pmif *arb = get_pmif_controller(PMIF_SPMI, mstid);
+
+	DRV_WriteReg32(arb->spmimst_base + arb->spmimst_regs[reg], val);
+}
+
+/*
+ * Function : spmi_lock_slave_reg()
+ * Description : protect spmi slv register to be write
+ * Parameter :
+ * Return :
+ */
+int spmi_lock_slave_reg(struct spmi_device *dev)
+{
+	const unsigned char wpk_key = 0x0;
+	const unsigned char wpk_key_h = 0x0;
+
+	if ((dev->slvid == SPMI_SLAVE_6) ||
+		(dev->slvid == SPMI_SLAVE_7) ||
+		(dev->slvid == SPMI_SLAVE_3)) {
+		/* enable dig_wpk key, write 0x0*/
+		spmi_ext_register_writel(dev, MT6315_PMIC_DIG_WPK_KEY_ADDR,
+				&wpk_key, 1);
+		spmi_ext_register_writel(dev, MT6315_PMIC_DIG_WPK_KEY_H_ADDR,
+				&wpk_key_h, 1);
+	}
+
+	return 0;
+}
+
+/*
+ * Function : spmi_unlock_slave_reg()
+ * Description : unlock spmi slv register to write
+ * Parameter :
+ * Return :
+ */
+int spmi_unlock_slave_reg(struct spmi_device *dev)
+{
+	const unsigned char wpk_key = 0x15;
+	const unsigned char wpk_key_h = 0x63;
+
+	if ((dev->slvid == SPMI_SLAVE_6) ||
+		(dev->slvid == SPMI_SLAVE_7) ||
+		(dev->slvid == SPMI_SLAVE_3)) {
+		/* disable dig_wpk key, write 0x6315*/
+		spmi_ext_register_writel(dev, MT6315_PMIC_DIG_WPK_KEY_ADDR,
+				&wpk_key, 1);
+		spmi_ext_register_writel(dev, MT6315_PMIC_DIG_WPK_KEY_H_ADDR,
+				&wpk_key_h, 1);
+	}
+
+	return 0;
+}
+
+static int spmi_config_master(unsigned int mstid, kal_bool en)
+{
+	/* Software reset */
+	DRV_WriteReg32(WDT_SWSYSRST2, 0x85 << 24 | 0x1 << 4);
+
+#if !defined(CONFIG_FPGA_EARLY_PORTING)
+	/* TBD */
+	DRV_WriteReg32(CLK_CFG_16_CLR, 0x7 | (0x1 << 4) | (0x1 << 7));
+	DRV_WriteReg32(CLK_CFG_UPDATE2, 0x1 << 2);
+#endif
+
+	/* Software reset */
+	DRV_WriteReg32(WDT_SWSYSRST2, 0x85 << 24);
+
+	/* Enable SPMI */
+	spmi_writel(mstid, SPMI_MST_REQ_EN, en);
+
+	SPMI_INFO("%s done\n", __func__);
+
+	return 0;
+}
+
+static int spmi_config_slave(struct spmi_device *dev)
+{
+	return 0;
+}
+
+static int spmi_cali_rd_clock_polarity(struct spmi_device *dev,
+		unsigned int mstid)
+{
+	unsigned int i = 0;
+#if 0 //TBD
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+#endif
+	struct cali cali_data[] = {
+			{SPMI_CK_DLY_1T, SPMI_CK_POL_POS},
+			{SPMI_CK_NO_DLY, SPMI_CK_POL_POS},
+			{SPMI_CK_NO_DLY, SPMI_CK_POL_NEG}
+	};
+
+	/* Indicate sampling clock polarity, 1: Positive 0: Negative  */
+	for (i = 0;i < 3; i++) {
+		spmi_writel(mstid, SPMI_MST_SAMPL,
+			(cali_data[i].dly << 0x1) | cali_data[i].pol);
+		/* for exception reboot, we only call UT/spmi_read_check w/o
+		 * write test. It avoid to affect exception record.
+		 */
+#if SPMI_DEBUG
+		if (spmi_read_check(dev) == 0) {
+			SPMI_DBG("dly:%d, pol:%d\n", cali_data[i].dly,
+					cali_data[i].pol);
+			break;
+		}
+#endif
+	}
+	if (i == 3) {
+		SPMI_ERR("FATAL ERROR");
+		ASSERT(0);
+	}
+
+#if 0 //TBD
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+/* under construction !*/
+#endif
+	return 0;
+}
+
+#if SPMI_RCS_SUPPORT
+static int spmi_enable_rcs(struct spmi_device *dev, unsigned int mstid)
+{
+	unsigned char wdata = 0, rdata = 0, i = 0;
+
+	/* clear int status */
+	wdata = 0xc0;
+	spmi_ext_register_writel(dev, MT6315_PMIC_RG_INT_STATUS_RCS0_ADDR,
+		&wdata, 1);
+
+	/* config match mode */
+	wdata = 0x2;
+	spmi_ext_register_writel(dev, MT6315_PMIC_RG_INT_RCS1_ADDR, &wdata, 1);
+	spmi_ext_register_readl(dev, MT6315_PMIC_RG_INT_RCS1_ADDR, &rdata, 1);
+	SPMI_DBG("slvid:%x After set RG_INT_RCS1[0x%x]=0x%x\n", dev->slvid,
+			MT6315_PMIC_RG_INT_RCS1_ADDR, rdata);
+
+	/* set
+	 * RG_RCS_ABIT[1] = 1
+	 * RG_RCS_CMD[3:2] = 1
+	 * RG_RCS_ID[7:4] = 0
+	 */
+	spmi_ext_register_readl(dev, MT6315_PMIC_RG_RCS_ABIT_ADDR, &rdata, 1);
+	wdata = rdata |
+			(0x1 << MT6315_PMIC_RG_RCS_ABIT_SHIFT) |
+			(0x1 << MT6315_PMIC_RG_RCS_CMD_SHIFT);
+	wdata &= ~(0xf << MT6315_PMIC_RG_RCS_ID_SHIFT);
+	spmi_ext_register_writel(dev, MT6315_PMIC_RG_RCS_ABIT_ADDR, &wdata, 1);
+	spmi_ext_register_readl(dev, MT6315_PMIC_RG_RCS_ABIT_ADDR, &rdata, 1);
+	SPMI_DBG("slvid:%x After set SPMI_RCS_FUN0[0x%x]=0x%x\n", dev->slvid,
+			MT6315_PMIC_RG_RCS_ABIT_ADDR, rdata);
+
+	/* set rcs_addr = slvid */
+	wdata = dev->slvid;
+	spmi_ext_register_writel(dev, MT6315_PMIC_RG_RCS_ADDR_ADDR, &wdata, 1);
+	spmi_ext_register_readl(dev, MT6315_PMIC_RG_RCS_ADDR_ADDR, &rdata, 1);
+	SPMI_DBG("slvid:%x After set RCS_ADDR[0x%x]=0x%x\n", dev->slvid,
+			MT6315_PMIC_RG_RCS_ADDR_ADDR, rdata);
+
+	/* set mask */
+	wdata = 0x0;
+	spmi_ext_register_writel(dev, MT6315_PMIC_RG_INT_MASK_RCS0_ADDR,
+			&wdata, 1);
+	spmi_ext_register_readl(dev, MT6315_PMIC_RG_INT_MASK_RCS0_ADDR,
+			&rdata, 1);
+	SPMI_DBG("slvid:%x After set RG_INT_MASK[0x%x]=0x%x\n", dev->slvid,
+			MT6315_PMIC_RG_INT_MASK_RCS0_ADDR, rdata);
+
+	/* set top rcs0/rcs1 interrupt enable */
+	wdata = (0x1 << MT6315_PMIC_RG_INT_EN_RCS0_SHIFT) |
+		(0x1 << MT6315_PMIC_RG_INT_EN_RCS1_SHIFT);
+	spmi_ext_register_writel(dev, MT6315_PMIC_RG_INT_EN_RCS0_ADDR,
+			&wdata, 1);
+	spmi_ext_register_readl(dev, MT6315_PMIC_RG_INT_EN_RCS0_ADDR,
+			&rdata, 1);
+	SPMI_DBG("slvid:%x After set RG_INT_EN[0x%x]=0x%x\n", dev->slvid,
+			MT6315_PMIC_RG_INT_EN_RCS0_ADDR, rdata);
+
+	/* enable rcs function */
+	spmi_ext_register_readl(dev, MT6315_PMIC_RG_RCS_ENABLE_ADDR,
+			&rdata, 1);
+	wdata = rdata | (0x1 << MT6315_PMIC_RG_RCS_ENABLE_SHIFT);
+	spmi_ext_register_writel(dev, MT6315_PMIC_RG_RCS_ENABLE_ADDR,
+			&wdata, 1);
+	spmi_ext_register_readl(dev, MT6315_PMIC_RG_RCS_ENABLE_ADDR,
+			&rdata, 1);
+	SPMI_DBG("slvid:%x After set Enable[0x%x]=0x%x\n", dev->slvid,
+			MT6315_PMIC_RG_RCS_ENABLE_ADDR, rdata);
+
+}
+
+int spmi_read_eint_sta(unsigned char *slv_eint_sta)
+{
+	struct pmif *arb = get_pmif_controller(PMIF_SPMI, SPMI_MASTER_0);
+	unsigned char offset = 0, j = 0, rdata = 0;
+	unsigned int regs = 0;
+
+	for (offset = 0; offset < 4; offset++) {
+		regs = arb->spmimst_regs[SPMI_SLV_3_0_EINT] + (offset*4);
+		rdata = DRV_Reg32(arb->spmimst_base + regs);
+		*(slv_eint_sta + j) = rdata & 0xff;
+		*(slv_eint_sta + j+1) = (rdata >> 8) & 0xff;
+		*(slv_eint_sta + j+2) = (rdata >> 16) & 0xff;
+		*(slv_eint_sta + j+3) = (rdata >> 24) & 0xff;
+		j += 4;
+	}
+
+	for (offset = 0; offset < 16; offset++) {
+		SPMI_INFO("%d, slv_eint_sta[0x%x]\n", offset,
+				*(slv_eint_sta + offset));
+	}
+	spmi_writel(mstid, SPMI_SLV_3_0_EINT, 0xffffffff);
+	spmi_writel(mstid, SPMI_SLV_7_4_EINT, 0xffffffff);
+	spmi_writel(mstid, SPMI_SLV_B_8_EINT, 0xffffffff);
+	spmi_writel(mstid, SPMI_SLV_F_C_EINT, 0xffffffff);
+
+	SPMI_INFO("%s, [0x%x]=0x%x\n", __func__,
+		arb->spmimst_base + arb->spmimst_regs[SPMI_DEC_DBG],
+		spmi_readl(mstid, SPMI_DEC_DBG));
+}
+#endif
+
+#if SPMI_EXTADDR_SUPPORT
+int spmi_register_zero_write_extaddr(struct spmi_device *dev,
+		unsigned int addr, unsigned char data)
+{
+	unsigned char wdata = 0;
+
+	spmi_unlock_slave_reg(dev);
+
+	if ((dev->slvid == SPMI_SLAVE_6) ||
+		(dev->slvid == SPMI_SLAVE_7) ||
+		(dev->slvid == SPMI_SLAVE_3)) {
+		/* assign specific addr */
+		wdata = (addr&0xff);
+		spmi_ext_register_writel(dev,
+			MT6315_PMIC_RG_EXTADR_REG0_W_ADDR, &wdata, 1);
+		wdata = (addr>>8)&0xff;
+		spmi_ext_register_writel(dev,
+			MT6315_PMIC_RG_EXTADR_REG0_W_H_ADDR, &wdata, 1);
+	}
+
+	spmi_lock_slave_reg(dev);
+
+	return dev->pmif_arb->write_cmd(dev->pmif_arb, SPMI_CMD_ZERO_WRITE,
+					dev->slvid, addr, &data, 1);
+}
+
+int spmi_register_zero_write_set_extaddr(struct spmi_device *dev,
+		unsigned int addr, kal_bool en)
+{
+	unsigned char wdata = 0;
+
+	spmi_unlock_slave_reg(dev);
+
+	if ((dev->slvid == SPMI_SLAVE_6) ||
+		(dev->slvid == SPMI_SLAVE_7) ||
+		(dev->slvid == SPMI_SLAVE_3)) {
+		if (en == KAL_TRUE) {
+			/* assign specific addr */
+			wdata = (addr&0xff);
+			spmi_ext_register_writel(dev,
+				MT6315_PMIC_RG_EXTADR_REG0_W_ADDR, &wdata, 1);
+			wdata = (addr>>8)&0xff;
+			spmi_ext_register_writel(dev,
+				MT6315_PMIC_RG_EXTADR_REG0_W_H_ADDR,
+				&wdata, 1);
+		} else {
+			/* assign specific addr */
+			wdata = 0;
+			spmi_ext_register_writel(dev,
+					MT6315_PMIC_RG_EXTADR_REG0_W_ADDR,
+					&wdata, 1);
+			spmi_ext_register_writel(dev,
+					MT6315_PMIC_RG_EXTADR_REG0_W_H_ADDR,
+					&wdata, 1);
+		}
+	}
+
+	spmi_lock_slave_reg(dev);
+
+	return 0;
+}
+
+int spmi_register_read_extaddr(struct spmi_device *dev, unsigned int addr,
+		unsigned char *buf)
+{
+	unsigned char wdata = 0;
+
+	spmi_unlock_slave_reg(dev);
+
+	if ((dev->slvid == SPMI_SLAVE_6) ||
+		(dev->slvid == SPMI_SLAVE_7) ||
+		(dev->slvid == SPMI_SLAVE_3)) {
+		/* assign specific addr */
+		wdata = ((addr >> 5) & 0xff);
+		spmi_ext_register_writel(dev,
+			MT6315_PMIC_RG_EXTADR_REG_RW_ADDR, &wdata, 1);
+		wdata = ((addr >> 5) & 0xff00);
+		spmi_ext_register_writel(dev,
+			MT6315_PMIC_RG_EXTADR_REG_RW_H_ADDR, &wdata, 1);
+	}
+
+	spmi_lock_slave_reg(dev);
+
+	return dev->pmif_arb->read_cmd(dev->pmif_arb, SPMI_CMD_READ,
+					dev->slvid, addr, buf, 1);
+}
+
+int spmi_register_write_extaddr(struct spmi_device *dev, unsigned int addr,
+		unsigned char data)
+{
+	unsigned char wdata = 0;
+
+	spmi_unlock_slave_reg(dev);
+
+	if ((dev->slvid == SPMI_SLAVE_6) ||
+		(dev->slvid == SPMI_SLAVE_7) ||
+		(dev->slvid == SPMI_SLAVE_3)) {
+		/* assign specific addr */
+		wdata = ((addr >> 5) & 0xff);
+		spmi_ext_register_writel(dev,
+				MT6315_PMIC_RG_EXTADR_REG_RW_ADDR, &wdata, 1);
+		wdata = ((addr >> 5) & 0xff00);
+		spmi_ext_register_writel(dev,
+				MT6315_PMIC_RG_EXTADR_REG_RW_H_ADDR,
+				&wdata, 1);
+	}
+
+	spmi_lock_slave_reg(dev);
+
+	return dev->pmif_arb->write_cmd(dev->pmif_arb, SPMI_CMD_WRITE,
+					dev->slvid, addr, &data, 1);
+}
+
+int spmi_register_rw_set_extaddr(struct spmi_device *dev, unsigned int addr,
+		kal_bool en)
+{
+	unsigned char wdata = 0;
+
+	spmi_unlock_slave_reg(dev);
+
+	if ((dev->slvid == SPMI_SLAVE_6) ||
+		(dev->slvid == SPMI_SLAVE_7) ||
+		(dev->slvid == SPMI_SLAVE_3)) {
+		if (en == KAL_TRUE) {
+			/* assign specific addr */
+			wdata = ((addr >> 5) & 0xff);
+			spmi_ext_register_writel(dev,
+					MT6315_PMIC_RG_EXTADR_REG_RW_ADDR,
+					&wdata, 1);
+			wdata = ((addr >> 5) & 0xff00);
+			spmi_ext_register_writel(dev,
+					MT6315_PMIC_RG_EXTADR_REG_RW_H_ADDR,
+					&wdata, 1);
+		} else {
+			/* assign specific addr */
+			wdata = 0;
+			spmi_ext_register_writel(dev,
+					MT6315_PMIC_RG_EXTADR_REG_RW_ADDR,
+					&wdata, 1);
+			spmi_ext_register_writel(dev,
+					MT6315_PMIC_RG_EXTADR_REG_RW_H_ADDR,
+					&wdata, 1);
+		}
+	}
+
+	spmi_lock_slave_reg(dev);
+
+	return 0;
+}
+
+int spmi_ext_register_read_extaddr(struct spmi_device *dev, unsigned int addr,
+		unsigned char *buf, unsigned short len)
+{
+	unsigned char wdata = 0;
+
+	spmi_unlock_slave_reg(dev);
+
+	if ((dev->slvid == SPMI_SLAVE_6) ||
+		(dev->slvid == SPMI_SLAVE_7) ||
+		(dev->slvid == SPMI_SLAVE_3)) {
+		/* assign specific addr */
+		wdata = ((addr >> 8) & 0xff);
+		spmi_ext_register_writel(dev,
+				MT6315_PMIC_RG_EXTADR_EXT_REG_RW_ADDR,
+				&wdata, 1);
+	}
+
+	spmi_lock_slave_reg(dev);
+
+	return dev->pmif_arb->read_cmd(dev->pmif_arb, SPMI_CMD_EXT_READ,
+					dev->slvid, addr, buf, len);
+}
+
+int spmi_ext_register_write_extaddr(struct spmi_device *dev, unsigned int addr,
+		const unsigned char *buf, unsigned short len)
+{
+	unsigned char wdata = 0;
+
+	spmi_unlock_slave_reg(dev);
+
+	if ((dev->slvid == SPMI_SLAVE_6) ||
+		(dev->slvid == SPMI_SLAVE_7) ||
+		(dev->slvid == SPMI_SLAVE_3)) {
+		/* assign specific addr */
+		wdata = ((addr >> 8) & 0xff);
+		spmi_ext_register_writel(dev,
+			MT6315_PMIC_RG_EXTADR_EXT_REG_RW_ADDR, &wdata, 1);
+	}
+
+	spmi_lock_slave_reg(dev);
+
+	return dev->pmif_arb->write_cmd(dev->pmif_arb, SPMI_CMD_EXT_WRITE,
+					dev->slvid, addr, buf, len);
+}
+
+int spmi_ext_register_rw_set_extaddr(struct spmi_device *dev,
+		unsigned int addr, kal_bool en)
+{
+	unsigned char wdata = 0;
+
+	spmi_unlock_slave_reg(dev);
+
+	if ((dev->slvid == SPMI_SLAVE_6) ||
+		(dev->slvid == SPMI_SLAVE_7) ||
+		(dev->slvid == SPMI_SLAVE_3)) {
+		/* assign specific addr */
+		if (en == KAL_TRUE) {
+			wdata = ((addr >> 8) & 0xff);
+			spmi_ext_register_writel(dev,
+				MT6315_PMIC_RG_EXTADR_EXT_REG_RW_ADDR,
+				&wdata, 1);
+		} else {
+			wdata = 0;
+			spmi_ext_register_writel(dev,
+				MT6315_PMIC_RG_EXTADR_EXT_REG_RW_ADDR,
+				&wdata, 1);
+		}
+	}
+
+	spmi_lock_slave_reg(dev);
+
+	return 0;
+}
+#endif /* end of SPMI_EXTADDR_SUPPORT */
+
+static int spmi_ctrl_op_st(int mstid, unsigned int grpiden, unsigned int sid,
+		unsigned int cmd)
+{
+	unsigned int rdata = 0x0;
+
+	/* gid is 0x800 */
+	spmi_writel(mstid, SPMI_GRP_ID_EN, grpiden);
+#if MT63xx_EVB
+	if (grpiden == (1 << SPMI_GROUP_ID))
+		spmi_writel(mstid, SPMI_OP_ST_CTRL,
+			(cmd << 0x4) | SPMI_GROUP_ID);
+#else
+	if (grpiden == 0x100)
+		spmi_writel(mstid, SPMI_OP_ST_CTRL, (cmd << 0x4) | 0x8);
+#endif
+	else
+		spmi_writel(mstid, SPMI_OP_ST_CTRL, (cmd << 0x4) | sid);
+
+	SPMI_WARN("spmi_ctrl_op_st 0x%x\n", spmi_readl(mstid, SPMI_OP_ST_CTRL));
+
+	do
+	{
+		rdata = spmi_readl(mstid, SPMI_OP_ST_STA);
+		SPMI_DBG("spmi_ctrl_op_st 0x%x\n", rdata);
+
+		if (((rdata >> 0x1) & SPMI_OP_ST_NACK) == SPMI_OP_ST_NACK) {
+			break;
+		}
+		}while((rdata & SPMI_OP_ST_BUSY) == SPMI_OP_ST_BUSY);
+
+	return 0;
+}
+
+int spmi_command_reset(int mstid, struct spmi_device *dev, unsigned int grpiden)
+{
+#if MT63xx_EVB
+	if (grpiden != (1 << SPMI_GROUP_ID))
+		dev->slvid = grpiden;
+#else
+	if (grpiden != 0x100)
+		dev->slvid = grpiden;
+#endif
+	return spmi_ctrl_op_st(mstid, grpiden, dev->slvid, SPMI_RESET);
+}
+int spmi_command_sleep(int mstid, struct spmi_device *dev, unsigned int grpiden)
+{
+#if MT63xx_EVB
+	if (grpiden != (1 << SPMI_GROUP_ID))
+		dev->slvid = grpiden;
+#else
+	if (grpiden != 0x100)
+		dev->slvid = grpiden;
+#endif
+	return spmi_ctrl_op_st(mstid, grpiden, dev->slvid, SPMI_SLEEP);
+}
+int spmi_command_wakeup(int mstid, struct spmi_device *dev, unsigned int grpiden)
+{
+#if MT63xx_EVB
+	if (grpiden != (1 << SPMI_GROUP_ID))
+		dev->slvid = grpiden;
+#else
+	if (grpiden != 0x100)
+		dev->slvid = grpiden;
+#endif
+	return spmi_ctrl_op_st(mstid, grpiden, dev->slvid, SPMI_WAKEUP);
+}
+int spmi_command_shutdown(int mstid, struct spmi_device *dev, unsigned int grpiden)
+{
+#if MT63xx_EVB
+	if (grpiden != (1 << SPMI_GROUP_ID))
+		dev->slvid = grpiden;
+#else
+	if (grpiden != 0x100)
+		dev->slvid = grpiden;
+#endif
+	return spmi_ctrl_op_st(mstid, grpiden, dev->slvid, SPMI_SHUTDOWN);
+}
+
+int spmi_enable_group_id(int mstid, unsigned int grpiden)
+{
+	spmi_writel(mstid, SPMI_GRP_ID_EN, grpiden);
+
+	return 0;
+}
+
+#if SPMI_DEBUG
+static int spmi_rw_test(struct spmi_device *dev)
+{
+	unsigned char wdata = 0, rdata = 0;
+
+	if (dev->mstid == SPMI_MASTER_P_1) {
+		SPMI_INFO("SPMI-P doesn't do %s\n", __func__);
+		return 0;
+	}
+	switch (dev->slvid) {
+	case SPMI_SLAVE_3:
+	case SPMI_SLAVE_6:
+	case SPMI_SLAVE_7:
+		wdata = DEFAULT_VALUE_READ_TEST;
+		spmi_ext_register_writel(dev, MT6315_PMIC_TOP_MDB_RSV1_ADDR,
+				&wdata, 1);
+		spmi_ext_register_readl(dev, MT6315_PMIC_TOP_MDB_RSV1_ADDR,
+				&rdata, 1);
+		if (rdata != DEFAULT_VALUE_READ_TEST) {
+			SPMI_ERR("%s fail_r, slvid:%d rdata = 0x%x.\n",
+				__func__, dev->slvid, rdata);
+			return -EIO;
+		} else
+			SPMI_DBG("%s pass_r, slvid:%d\n", __func__, dev->slvid);
+
+		wdata = DEFAULT_VALUE_WRITE_TEST;
+		spmi_ext_register_writel(dev, MT6315_PMIC_TOP_MDB_RSV1_H_ADDR,
+				&wdata, 1);
+
+		spmi_ext_register_readl(dev, MT6315_PMIC_TOP_MDB_RSV1_H_ADDR,
+				&rdata, 1);
+		if (rdata != DEFAULT_VALUE_WRITE_TEST) {
+			SPMI_ERR("%s fail_w, slvid:%d rdata = 0x%x.\n",
+				__func__, dev->slvid, rdata);
+			return -EIO;
+		} else
+			SPMI_DBG("%s pass_w, slvid:%d\n", __func__, dev->slvid);
+
+		break;
+	case SPMI_SLAVE_9:
+		spmi_read_check(dev);
+		break;
+	case SPMI_SLAVE_8:
+	default:
+		SPMI_ERR("%s not be here, slvid:%d\n", __func__, dev->slvid);
+		break;
+	}
+	return 0;
+}
+
+static int spmi_read_check(struct spmi_device *dev)
+{
+	unsigned char rdata = 0;
+
+	spmi_ext_register_readl(dev, dev->hwcid_addr, &rdata, 1);
+	/* mt6362 can only check 0x00[7:4], other mt63xx can align the rule */
+	if ((rdata & 0xF0) != (dev->hwcid_val & 0xF0)) {
+		SPMI_ERR("%s next, slvid:%d rdata = 0x%x.\n",
+			__func__, dev->slvid, rdata);
+		return -EIO;
+	} else
+		SPMI_DBG("%s done, slvid:%d\n", __func__, dev->slvid);
+
+	return 0;
+}
+
+static int spmi_drv_ut(struct spmi_device *dev, unsigned int ut)
+{
+	int ret = 0;
+
+	switch (ut) {
+		case 1:
+			ret = spmi_rw_test(dev);
+			break;
+		case 2:
+			ret = spmi_read_check(dev);
+			break;
+		case 3:
+			break;
+		default:
+			break;
+	}
+
+	return ret;
+}
+#endif /* end of #if SPMI_DEBUG */
+
+struct spmi_device *get_spmi_device(int mstid, unsigned int slv_type)
+{
+	unsigned int i;
+
+	for (i = 0; i < spmi_device_cnt; i++) {
+		if (slv_type == spmi_dev[i].type) {
+			return &spmi_dev[i];
+		}
+	}
+
+	return NULL;
+}
+
+int spmi_init(struct pmif *pmif_arb)
+{
+	int i = 0;
+#if SPMI_DEBUG
+	int ret = 0;
+#endif
+
+	if (pmif_arb == NULL) /* null check */ {
+		SPMI_ERR("arguments err\n");
+		return -EINVAL;
+	}
+
+	pmif_arb->spmimst_regs = mt6885_spmi_regs;
+	pmif_spmi_arb_ctrl[pmif_arb->mstid] = pmif_arb;
+	spmi_device_cnt = sizeof(spmi_dev)/sizeof(spmi_dev[0]);
+
+	if (is_pmif_spmi_init_done(pmif_arb->mstid) != 0)
+		spmi_config_master(pmif_arb->mstid, KAL_TRUE);
+
+	for (i = 0; i < spmi_device_cnt; i++) {
+		if (pmif_arb->mstid == spmi_dev[i].mstid) {
+			spmi_dev[i].pmif_arb = pmif_spmi_arb_ctrl[pmif_arb->mstid];
+			if (is_pmif_spmi_init_done(pmif_arb->mstid) != 0) {
+				spmi_config_slave(&spmi_dev[i]);
+				spmi_cali_rd_clock_polarity(&spmi_dev[i],
+						pmif_arb->mstid);
+			}
+#if SPMI_MONITOR_SUPPORT
+			/* dump 1st time slave debug register when booting */
+			spmi_dump_slv_record_reg(&spmi_dev[i]);
+#endif
+#if SPMI_RCS_SUPPORT
+			if (is_pmif_spmi_init_done() != 0) {
+				/* enable master rcs support */
+				spmi_writel(pmif_arb->mstid, SPMI_MST_RCS_CTRL, 0x15);
+				spmi_enable_rcs(&spmi_dev[i], pmif_arb->mstid);
+			}
+#endif
+
+#if SPMI_DEBUG
+			/* shouldn't enable at here*/
+			ret = spmi_drv_ut(&spmi_dev[i], 1);
+			if(ret) {
+				SPMI_ERR("EIO err\n");
+				return ret;
+			}
+#endif
+			/*TBD spmi_lock_slave_reg(&spmi_dev[i]); */
+		}
+	}
+	SPMI_INFO("%s done\n", __func__);
+
+	return 0;
+}
+
+#endif /* #ifdef SPMI_NO_PMIC */