[Feature]add MT2731_MP2_MR2_SVN388 baseline version

Change-Id: Ief04314834b31e27effab435d3ca8ba33b499059
diff --git a/src/kernel/linux/v4.14/drivers/mfd/mt6358-misc.c b/src/kernel/linux/v4.14/drivers/mfd/mt6358-misc.c
new file mode 100644
index 0000000..e0f28d5
--- /dev/null
+++ b/src/kernel/linux/v4.14/drivers/mfd/mt6358-misc.c
@@ -0,0 +1,1832 @@
+/*
+ * Copyright (C) 2018 MediaTek, Inc.
+ * Author: Wilma Wu <wilma.wu@mediatek.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/rtc.h>
+#include <linux/sched/clock.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include <linux/irqdomain.h>
+#include <linux/platform_device.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/io.h>
+#include <linux/mfd/mt6358/core.h>
+#if defined(CONFIG_MTK_PMIC_CHIP_MT6358)
+#include <linux/mfd/mt6358/registers.h>
+#elif defined(CONFIG_MTK_PMIC_CHIP_MT6359)
+#include <linux/mfd/mt6359/registers.h>
+#elif defined(CONFIG_MTK_PMIC_CHIP_MT6389)
+#include <linux/mfd/mt6389/registers.h>
+#endif
+
+
+#ifdef pr_fmt
+#undef pr_fmt
+#endif
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+/* we map HW YEA 0 (2000) to 1968 not 1970 because 2000 is the leap year */
+#define RTC_MIN_YEAR		1968
+
+/*
+ * Reset to default date if RTC time is over 2038/1/19 3:14:7
+ * Year (YEA)        : 1970 ~ 2037
+ * Month (MTH)       : 1 ~ 12
+ * Day of Month (DOM): 1 ~ 31
+ */
+
+#define RTC_DEFAULT_YEA		2010
+#define RTC_DEFAULT_MTH		1
+#define RTC_DEFAULT_DOM		1
+
+/* Min, Hour, Dom... register offset to RTC_TC_SEC */
+#define RTC_OFFSET_SEC		0
+#define RTC_OFFSET_MIN		1
+#define RTC_OFFSET_HOUR		2
+#define RTC_OFFSET_DOM		3
+#define RTC_OFFSET_DOW		4
+#define RTC_OFFSET_MTH		5
+#define RTC_OFFSET_YEAR		6
+#define RTC_OFFSET_COUNT	7
+
+
+
+#define RTC_DSN_ID				0x580
+#define RTC_BBPU				0x8
+#define RTC_IRQ_STA				0xa
+#define RTC_IRQ_EN				0xc
+#define RTC_CII_EN				0xe
+#define RTC_AL_MASK				0x10
+#define RTC_TC_SEC				0x12
+#define RTC_TC_MIN				0x14
+#define RTC_TC_HOU				0x16
+#define RTC_TC_DOM				0x18
+#define RTC_TC_DOW				0x1a
+#define RTC_TC_MTH				0x1c
+#define RTC_TC_YEA				0x1e
+#define RTC_AL_SEC				0x20
+#define RTC_AL_MIN				0x22
+#define RTC_AL_HOU				0x24
+#define RTC_AL_DOM				0x26
+#define RTC_AL_DOW				0x28
+#define RTC_AL_MTH				0x2a
+#define RTC_AL_YEA				0x2c
+#define RTC_PDN1				0x34
+#define RTC_PDN2				0x36
+#define RTC_SPAR0				0x38
+#define RTC_SPAR1				0x3a
+#define RTC_WRTGR				0x42
+#define RTC_OSC32CON			0x2e
+#define RTC_POWERKEY1			0x30
+#define RTC_POWERKEY2			0x32
+#define RTC_PROT				0x3c
+#define RTC_DIFF				0x3e
+#define RTC_CALI				0x40
+#define RTC_CON					0x44
+
+#define RTC_AL_SEC_MASK			0x3f
+#define RTC_AL_MIN_MASK			0x3f
+#define RTC_AL_HOU_MASK			0x1f
+#define RTC_AL_DOM_MASK			0x1f
+#define RTC_AL_DOW_MASK			0x7
+#define RTC_AL_MTH_MASK			0xf
+#define RTC_AL_YEA_MASK			0x7f
+
+#define RTC_PWRON_SEC_MASK		0x3f
+#define RTC_PWRON_MIN_MASK		0x3f
+#define RTC_PWRON_HOU_MASK		0x7c0
+#define RTC_PWRON_DOM_MASK		0xf800
+#define RTC_PWRON_MTH_MASK		0xf
+#define RTC_PWRON_YEA_MASK		0x7f00
+#define RTC_PWRON_SEC_SHIFT		0x0
+#define RTC_PWRON_MIN_SHIFT		0x0
+#define RTC_PWRON_HOU_SHIFT		0x6
+#define RTC_PWRON_DOM_SHIFT		0xb
+#define RTC_PWRON_MTH_SHIFT		0x0
+#define RTC_PWRON_YEA_SHIFT		0x8
+
+#define	RTC_IRQ_EN_AL			BIT(0)
+
+/* RTC_BBPU bit field */
+#define	PMIC_SPAR_SW_SHIFT	1
+#define	PMIC_RESET_SPAR_SHIFT	2
+#define	PMIC_RESET_ALARM_SHIFT	3
+
+#define RTC_BBPU_KEY			0x4300
+#define RTC_BBPU_CBUSY			BIT(6)
+#define RTC_BBPU_RELOAD			BIT(5)
+#define RTC_BBPU_RESET_SPAR		BIT(PMIC_RESET_SPAR_SHIFT)
+#define RTC_BBPU_RESET_ALARM		BIT(PMIC_RESET_ALARM_SHIFT)
+#define RTC_BBPU_CLR			BIT(1)
+#define RTC_BBPU_SPAR_SW			BIT(PMIC_SPAR_SW_SHIFT)
+#define RTC_BBPU_PWREN			BIT(0)
+
+#define RTC_AL_MASK_DOW			BIT(4)
+
+#define RTC_GPIO_USER_MASK		0x1f00
+#define RTC_PDN1_PWRON_TIME		BIT(7)
+#define RTC_PDN2_PWRON_LOGO		BIT(15)
+
+#define RTC_CON_F32KOB			BIT(5)
+
+#define RTC_POWERKEY1_KEY		0xa357
+#define RTC_POWERKEY2_KEY		0x67d2
+
+#define RTC_OSC32CON_UNLOCK1		0x1a57
+#define RTC_OSC32CON_UNLOCK2		0x2b68
+
+#define RTC_EMBCK_SRC_SEL		BIT(8)
+
+#define RTC_K_EOSC_RSV_0			BIT(8)
+#define RTC_K_EOSC_RSV_1			BIT(9)
+#define RTC_K_EOSC_RSV_2			BIT(10)
+
+#define RTC_BBPU_2SEC_EN			BIT(8)
+#define RTC_BBPU_AUTO_PDN_SEL		BIT(6)
+
+#define RTC_EMBCK_SEL_K_EOSC		BIT(MT6389_RTC_EMBCK_SEL_MODE_SHIFT)
+#define RTC_EMBCK_SEL_OPTION		BIT(MT6389_RTC_EMBCK_SEL_OPTION_SHIFT)
+#define RTC_GPS_CKOUT_EN		BIT(MT6389_RTC_GPS_CKOUT_EN_SHIFT)
+#define RTC_EOSC32_VCT_EN		BIT(MT6389_RTC_EOSC32_VCT_EN_SHIFT)
+#define RTC_EOSC32_CHOP_EN		BIT(MT6389_RTC_EOSC32_CHOP_EN_SHIFT)
+#define RTC_GP_OSC32_CON		(2U << MT6389_RTC_GP_OSC32_CON_SHIFT)
+#define RTC_REG_XOSC32_ENB		BIT(MT6389_RTC_REG_XOSC32_ENB_SHIFT)
+#define OSC32CON_ANALOG_SETTING	(RTC_GP_OSC32_CON | RTC_EOSC32_CHOP_EN | \
+				 RTC_EOSC32_VCT_EN | \
+				 RTC_GPS_CKOUT_EN | RTC_EMBCK_SEL_OPTION | \
+				 RTC_EMBCK_SEL_K_EOSC)
+
+#define RTC_EOSC32_LPEN			BIT(MT6389_EOSC32_LPEN_SHIFT)
+#define RTC_XOSC32_LPEN			BIT(MT6389_XOSC32_LPEN_SHIFT)
+#define RTC_CON_LPRST			BIT(MT6389_LPRST_SHIFT)
+/* 1: GPO mode, 0: GPI mode */
+#define RTC_CON_GOE			BIT(MT6389_GOE_SHIFT)
+#define RTC_CON_GPEN			BIT(MT6389_GPEN_SHIFT)
+#define RTC_CON_GPU				BIT(MT6389_GPU_SHIFT)
+#define RTC_CON_LPSTA_RAW		BIT(MT6389_LPSTA_RAW_SHIFT)
+
+#define RTC_PROT_UNLOCK1		0x586a
+#define RTC_PROT_UNLOCK2		0x9136
+
+#define RTC_EOSC_CALI_TD_01_SEC	0x3
+#define RTC_EOSC_CALI_TD_02_SEC	0x4
+#define RTC_EOSC_CALI_TD_04_SEC	0x5
+#define RTC_EOSC_CALI_TD_08_SEC	0x6
+#define RTC_EOSC_CALI_TD_16_SEC	0x7
+
+#define RTC_LPD_OPT_F32K_CK_ALIVE	(3U << MT6389_RTC_LPD_OPT_SHIFT)
+#define RTC_K_EOSC32_VTCXO_ON_SEL	BIT(MT6389_K_EOSC32_VTCXO_ON_SEL_SHIFT)
+
+#define RTC_SPAR0_32K_LESS		BIT(6)
+#define RTC_LPD_OPT_MASK		(MT6389_RTC_LPD_OPT_MASK << \
+					 MT6389_RTC_LPD_OPT_SHIFT)
+
+#define RG_75K_32K_SEL			MT6389_TOP_CKSEL_CON0_SET_ADDR
+#define RTC_75K_TO_32K			BIT(MT6389_RG_RTC_32K1V8_SEL_SHIFT)
+
+#define RTC_LPD_OPT_EOSC_LPD		BIT(MT6389_RTC_LPD_OPT_SHIFT)
+
+#define RG_FQMTR_RST			MT6389_RG_FQMTR_RST_ADDR
+#define RG_FQMTR_TCKSEL			MT6389_FQMTR_TCKSEL_ADDR
+#define RG_FQMTR_WINSET			MT6389_FQMTR_WINSET_ADDR
+#define RG_FQMTR_BUSY			MT6389_FQMTR_BUSY_ADDR
+#define RG_FQMTR_DCXO26M_EN		MT6389_FQMTR_DCXO26M_EN_ADDR
+#define RG_FQMTR_DATA			MT6389_FQMTR_DATA_ADDR
+
+#define RG_FQMTR_32K_CLK_PDN_SET	MT6389_TOP_CKPDN_CON0_SET_ADDR
+#define RG_FQMTR_32K_CLK_PDN_CLR	MT6389_TOP_CKPDN_CON0_CLR_ADDR
+#define RG_FQMTR_32K_CLK_PDN_MASK	MT6389_RG_FQMTR_32K_CK_PDN_MASK
+#define RG_FQMTR_32K_CLK_PDN_SHIFT	MT6389_RG_FQMTR_32K_CK_PDN_SHIFT
+
+#define FQMTR_CLK_CK_PDN_SET		MT6389_TOP_CKPDN_CON0_SET_ADDR
+#define FQMTR_CLK_CK_PDN_CLR		MT6389_TOP_CKPDN_CON0_CLR_ADDR
+#define FQMTR_CLK_CK_PDN_MASK		MT6389_RG_FQMTR_CK_PDN_MASK
+#define FQMTR_CLK_CK_PDN_SHIFT	MT6389_RG_FQMTR_CK_PDN_SHIFT
+
+#define RG_FQMTR_CKSEL			MT6389_RG_FQMTR_CK_CKSEL_ADDR
+#define RG_FQMTR_CKSEL_SET		MT6389_TOP_CKSEL_CON0_SET_ADDR
+#define RG_FQMTR_CKSEL_CLR		MT6389_TOP_CKSEL_CON0_CLR_ADDR
+#define RG_FQMTR_CKSEL_MASK		MT6389_RG_FQMTR_CK_CKSEL_MASK
+#define RG_FQMTR_CKSEL_SHIFT		MT6389_RG_FQMTR_CK_CKSEL_SHIFT
+#define RG_FQMTR_TCKSEL_MASK		MT6389_FQMTR_TCKSEL_MASK
+#define RG_FQMTR_TCKSEL_SHIFT		MT6389_FQMTR_TCKSEL_SHIFT
+
+#define FQMTR_FIX_CLK_26M		(0 << RG_FQMTR_CKSEL_SHIFT)
+#define FQMTR_FIX_CLK_XOSC_32K_DET	(1 << RG_FQMTR_CKSEL_SHIFT)
+#define FQMTR_FIX_CLK_EOSC_32K	(2 << RG_FQMTR_CKSEL_SHIFT)
+#define FQMTR_FIX_CLK_RTC_32K		(3 << RG_FQMTR_CKSEL_SHIFT)
+#define FQMTR_FIX_CLK_SMPS_CK		(4 << RG_FQMTR_CKSEL_SHIFT)
+#define FQMTR_FIX_CLK_TCK_SEC		(5 << RG_FQMTR_CKSEL_SHIFT)
+#define FQMTR_FIX_CLK_PMU_75K		(6 << RG_FQMTR_CKSEL_SHIFT)
+
+#define FQMTR_RST			(1U << MT6389_RG_FQMTR_RST_SHIFT)
+#define FQMTR_EN			(1U << MT6389_FQMTR_EN_SHIFT)
+#define FQMTR_BUSY			(1U << MT6389_FQMTR_BUSY_SHIFT)
+#define FQMTR_DCXO26M_EN		(1U << MT6389_FQMTR_DCXO26M_EN_SHIFT)
+#define FQMTR_XOSC32_CK			0
+#define FQMTR_DCXO_F32K_CK		1
+#define FQMTR_EOSC32_CK			2
+#define FQMTR_XOSC32_CK_DETECTON	3
+#define FQMTR_FQM26M_CK			4
+#define FQMTR_FQM32K_CK			5
+#define FQMTR_TEST_CK			6
+#define FQMTR_WINSET			0x0000
+
+#define RTC_FQMTR_LOW_BASE	(794 - 2)
+#define RTC_FQMTR_HIGH_BASE (794 + 2)
+
+#define RTC_XOSCCALI_START		0x0000
+#define RTC_XOSCCALI_END			0x001f
+
+/* 0 (32k crystal exist)        1 (32k crystal doesn't exist) */
+#define RTC_XOSC32_ENB			(MT6389_RTC_XOSC32_ENB_MASK << \
+					 MT6389_RTC_XOSC32_ENB_SHIFT)
+
+#define RTC_BBPU_2SEC_STAT_CLEAR	(MT6389_BBPU_2SEC_STAT_CLEAR_MASK << \
+					 MT6389_BBPU_2SEC_STAT_CLEAR_SHIFT)
+/* Default 4'b0111, 2nd step suggest to set to 4'b0000
+ * EOSC_CALI = charging cap calibration
+ */
+#define RTC_XOSCCALI_MASK	(MT6389_XOSCCALI_MASK << MT6389_XOSCCALI_SHIFT)
+
+#define IPIMB
+
+
+enum rtc_spare_enum {
+	RTC_FGSOC = 0,
+	RTC_ANDROID,
+	RTC_FAC_RESET,
+	RTC_BYPASS_PWR,
+	RTC_PWRON_TIME,
+	RTC_FAST_BOOT,
+	RTC_KPOC,
+	RTC_DEBUG,
+	RTC_PWRON_AL,
+	RTC_UART,
+	RTC_AUTOBOOT,
+	RTC_PWRON_LOGO,
+	RTC_32K_LESS,
+	RTC_LP_DET,
+	RTC_FG_INIT,
+	RTC_SPAR_NUM
+};
+
+enum rtc_reg_set {
+	RTC_REG,
+	RTC_MASK,
+	RTC_SHIFT
+};
+
+u16 rtc_spare_reg[RTC_SPAR_NUM][3] = {
+	{RTC_AL_MTH, 0xff, 8},
+	{RTC_PDN1, 0xf, 0},
+	{RTC_PDN1, 0x3, 4},
+	{RTC_PDN1, 0x1, 6},
+	{RTC_PDN1, 0x1, 7},
+	{RTC_PDN1, 0x1, 13},
+	{RTC_PDN1, 0x1, 14},
+	{RTC_PDN1, 0x1, 15},
+	{RTC_PDN2, 0x1, 4},
+	{RTC_PDN2, 0x3, 5},
+	{RTC_PDN2, 0x1, 7},
+	{RTC_PDN2, 0x1, 15},
+	{RTC_SPAR0, 0x1, 6},
+	{RTC_SPAR0, 0x1, 7},
+	{RTC_AL_HOU, 0xff, 8}
+};
+
+/*
+ * RTC_PDN1:
+ *     bit 0 - 3  : Android bits
+ *     bit 4 - 5  : Recovery bits (0x10: factory data reset)
+ *     bit 6      : Bypass PWRKEY bit
+ *     bit 7      : Power-On Time bit
+ *     bit 8      : reserved bit
+ *     bit 9      : reserved bit
+ *     bit 10     : reserved bit
+ *     bit 11     : reserved bit
+ *     bit 12     : reserved bit
+ *     bit 13     : Fast Boot
+ *     bit 14	  : Kernel Power Off Charging
+ *     bit 15     : Debug bit
+ */
+
+/*
+ * RTC_PDN2:
+ *     bit 0 - 3 : MTH in power-on time
+ *     bit 4     : Power-On Alarm bit
+ *     bit 5 - 6 : UART bits
+ *     bit 7     : POWER DROP AUTO BOOT bit
+ *     bit 8 - 14: YEA in power-on time
+ *     bit 15    : Power-On Logo bit
+ */
+
+/*
+ * RTC_SPAR0:
+ *     bit 0 - 5 : SEC in power-on time
+ *     bit 6	 : 32K less bit. True:with 32K, False:Without 32K
+ *     bit 7     : Low power detected in preloader
+ *     bit 8 - 15: reserved bits
+ */
+
+/*
+ * RTC_SPAR1:
+ *     bit 0 - 5  : MIN in power-on time
+ *     bit 6 - 10 : HOU in power-on time
+ *     bit 11 - 15: DOM in power-on time
+ */
+
+
+/*
+ * RTC_NEW_SPARE0: RTC_AL_HOU bit8~15
+ *	   bit 8 ~ 14 : Fuel Gauge
+ *     bit 15     : reserved bits
+ */
+
+/*
+ * RTC_NEW_SPARE1: RTC_AL_DOM bit8~15
+ *	   bit 8 ~ 15 : reserved bits
+ */
+
+/*
+ * RTC_NEW_SPARE2: RTC_AL_DOW bit8~15
+ *	   bit 8 ~ 15 : reserved bits
+ */
+
+/*
+ * RTC_NEW_SPARE3: RTC_AL_MTH bit8~15
+ *	   bit 8 ~ 15 : reserved bits
+ */
+
+static u16 rtc_alarm_reg[RTC_OFFSET_COUNT][3] = {
+	{RTC_AL_SEC, RTC_AL_SEC_MASK, 0},
+	{RTC_AL_MIN, RTC_AL_MIN_MASK, 0},
+	{RTC_AL_HOU, RTC_AL_HOU_MASK, 0},
+	{RTC_AL_DOM, RTC_AL_DOM_MASK, 0},
+	{RTC_AL_DOW, RTC_AL_DOW_MASK, 0},
+	{RTC_AL_MTH, RTC_AL_MTH_MASK, 0},
+	{RTC_AL_YEA, RTC_AL_YEA_MASK, 0},
+};
+
+static u16 rtc_pwron_reg[RTC_OFFSET_COUNT][3] = {
+	{RTC_SPAR0, RTC_PWRON_SEC_MASK, RTC_PWRON_SEC_SHIFT},
+	{RTC_SPAR1, RTC_PWRON_MIN_MASK, RTC_PWRON_MIN_SHIFT},
+	{RTC_SPAR1, RTC_PWRON_HOU_MASK, RTC_PWRON_HOU_SHIFT},
+	{RTC_SPAR1, RTC_PWRON_DOM_MASK, RTC_PWRON_DOM_SHIFT},
+	{0, 0, 0},
+	{RTC_PDN2, RTC_PWRON_MTH_MASK, RTC_PWRON_MTH_SHIFT},
+	{RTC_PDN2, RTC_PWRON_YEA_MASK, RTC_PWRON_YEA_SHIFT},
+};
+
+struct mt6358_misc {
+	struct device *dev;
+	spinlock_t lock;
+	struct regmap *regmap;
+	u32 addr_base;
+};
+
+static struct mt6358_misc *rtc_misc;
+#ifdef IPIMB
+struct regmap *pmic_regmap;
+#endif
+
+static int rtc_eosc_cali_td = 8;
+static int dcxo_switch;
+static int eosc_k;
+static int support_xosc;
+module_param(rtc_eosc_cali_td, int, 0664);
+
+
+static int rtc_read(unsigned int reg, unsigned int *val)
+{
+	return regmap_read(rtc_misc->regmap, rtc_misc->addr_base + reg, val);
+}
+
+static int rtc_write(unsigned int reg, unsigned int val)
+{
+	return regmap_write(rtc_misc->regmap, rtc_misc->addr_base + reg, val);
+}
+
+static int rtc_update_bits(unsigned int reg, unsigned int mask,
+			   unsigned int val)
+{
+	return regmap_update_bits(rtc_misc->regmap,
+				  rtc_misc->addr_base + reg, mask, val);
+}
+
+static int rtc_field_read(unsigned int reg,
+			  unsigned int mask, unsigned int shift,
+			  unsigned int *val)
+{
+	int ret;
+	unsigned int reg_val;
+
+	ret = rtc_read(reg, &reg_val);
+	if (ret != 0)
+		return ret;
+
+	reg_val &= mask;
+	reg_val >>= shift;
+	*val = reg_val;
+
+	return ret;
+}
+
+static int rtc_busy_wait(void)
+{
+	unsigned long long timeout = sched_clock() + 500000000;
+	int ret;
+	unsigned int bbpu;
+	u32 pwrkey1, pwrkey2, sec;
+
+	do {
+		ret = rtc_read(RTC_BBPU, &bbpu);
+		if (ret < 0)
+			break;
+		if ((bbpu & RTC_BBPU_CBUSY) == 0)
+			break;
+		else if (sched_clock() > timeout) {
+			rtc_read(RTC_BBPU, &bbpu);
+			rtc_read(RTC_POWERKEY1, &pwrkey1);
+			rtc_read(RTC_POWERKEY2, &pwrkey2);
+			rtc_read(RTC_TC_SEC, &sec);
+			pr_err("%s, wait cbusy timeout, %x, %x, %x, %d\n",
+			       __func__, bbpu, pwrkey1, pwrkey2, sec);
+			ret = -ETIMEDOUT;
+			break;
+		}
+	} while (1);
+
+	return ret;
+}
+
+static int rtc_write_trigger(void)
+{
+	int ret;
+
+	ret = rtc_write(RTC_WRTGR, 1);
+	if (ret < 0)
+		return ret;
+
+	return !rtc_busy_wait();
+}
+
+static int mtk_rtc_get_spare_register(enum rtc_spare_enum cmd)
+{
+	unsigned int tmp_val = 0;
+	int ret = -EINVAL;
+
+	if (cmd >= 0 && cmd < RTC_SPAR_NUM) {
+
+		ret = rtc_field_read(rtc_spare_reg[cmd][RTC_REG],
+				     rtc_spare_reg[cmd][RTC_MASK]
+				     << rtc_spare_reg[cmd][RTC_SHIFT],
+				     rtc_spare_reg[cmd][RTC_SHIFT], &tmp_val);
+
+		if (ret < 0)
+			goto exit;
+
+		pr_notice("%s: cmd[%d], get rg[0x%x, 0x%x , %d] = 0x%x\n",
+			  __func__, cmd,
+			  rtc_spare_reg[cmd][RTC_REG],
+			  rtc_spare_reg[cmd][RTC_MASK],
+			  rtc_spare_reg[cmd][RTC_SHIFT], tmp_val);
+
+		return tmp_val;
+	}
+
+exit:
+	return ret;
+}
+
+static void mtk_rtc_set_spare_register(enum rtc_spare_enum cmd, u16 val)
+{
+	u32 tmp_val = 0;
+	int ret;
+
+	if (cmd >= 0 && cmd < RTC_SPAR_NUM) {
+
+		pr_notice("%s: cmd[%d], set rg[0x%x, 0x%x , %d] = 0x%x\n",
+			  __func__, cmd,
+			  rtc_spare_reg[cmd][RTC_REG],
+			  rtc_spare_reg[cmd][RTC_MASK],
+			  rtc_spare_reg[cmd][RTC_SHIFT], val);
+
+		tmp_val = ((val & rtc_spare_reg[cmd][RTC_MASK])
+			   << rtc_spare_reg[cmd][RTC_SHIFT]);
+		ret = rtc_update_bits(rtc_spare_reg[cmd][RTC_REG],
+				      rtc_spare_reg[cmd][RTC_MASK]
+				      << rtc_spare_reg[cmd][RTC_SHIFT],
+				      tmp_val);
+		if (ret < 0)
+			goto exit;
+		ret = rtc_write_trigger();
+		if (ret < 0)
+			goto exit;
+	}
+	return;
+exit:
+	pr_err("%s error\n", __func__);
+}
+
+int get_rtc_spare_fg_value(void)
+{
+	/* RTC_AL_HOU bit8~14 */
+	u16 temp;
+	unsigned long flags;
+
+	spin_lock_irqsave(&rtc_misc->lock, flags);
+	temp = mtk_rtc_get_spare_register(RTC_FGSOC);
+	spin_unlock_irqrestore(&rtc_misc->lock, flags);
+
+	return temp;
+}
+
+int set_rtc_spare_fg_value(int val)
+{
+	/* RTC_AL_HOU bit8~14 */
+	unsigned long flags;
+
+	spin_lock_irqsave(&rtc_misc->lock, flags);
+	mtk_rtc_set_spare_register(RTC_FGSOC, val);
+	spin_unlock_irqrestore(&rtc_misc->lock, flags);
+
+	return 0;
+}
+
+int get_rtc_spare0_fg_value(void)
+{
+	u16 temp;
+	unsigned long flags;
+
+	spin_lock_irqsave(&rtc_misc->lock, flags);
+	temp = mtk_rtc_get_spare_register(RTC_FG_INIT);
+	spin_unlock_irqrestore(&rtc_misc->lock, flags);
+
+	return temp;
+}
+
+int set_rtc_spare0_fg_value(int val)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&rtc_misc->lock, flags);
+	mtk_rtc_set_spare_register(RTC_FG_INIT, val);
+	spin_unlock_irqrestore(&rtc_misc->lock, flags);
+
+	return 0;
+}
+
+bool crystal_exist_status(void)
+{
+	unsigned long flags;
+	u16 ret;
+
+	spin_lock_irqsave(&rtc_misc->lock, flags);
+	ret = mtk_rtc_get_spare_register(RTC_32K_LESS);
+	spin_unlock_irqrestore(&rtc_misc->lock, flags);
+
+	if (ret)
+		return true;
+	else
+		return false;
+}
+EXPORT_SYMBOL(crystal_exist_status);
+
+static void mtk_rtc_clear_pwron_alarm(void)
+{
+	u16 data[RTC_OFFSET_COUNT];
+	int ret, i;
+
+	pr_notice("%s\n", __func__);
+
+	data[RTC_OFFSET_SEC] = 0;
+	data[RTC_OFFSET_MIN] = 0;
+	data[RTC_OFFSET_HOUR] = 0;
+	data[RTC_OFFSET_DOM] = ((RTC_DEFAULT_DOM << RTC_PWRON_DOM_SHIFT) &
+				RTC_PWRON_DOM_MASK);
+	data[RTC_OFFSET_MTH] = ((RTC_DEFAULT_MTH << RTC_PWRON_MTH_SHIFT) &
+				RTC_PWRON_MTH_MASK);
+	data[RTC_OFFSET_YEAR] = (((RTC_DEFAULT_YEA - RTC_MIN_YEAR) <<
+				 RTC_PWRON_YEA_SHIFT)
+				 & RTC_PWRON_YEA_MASK);
+
+	for (i = RTC_OFFSET_SEC; i < RTC_OFFSET_COUNT; i++) {
+		if (i == RTC_OFFSET_DOW)
+			continue;
+		ret = rtc_update_bits(rtc_pwron_reg[i][RTC_REG],
+				      rtc_pwron_reg[i][RTC_MASK], data[i]);
+		if (ret < 0)
+			goto exit;
+		ret = rtc_write_trigger();
+		if (ret < 0)
+			goto exit;
+	}
+
+	ret = rtc_update_bits(RTC_PDN1, RTC_PDN1_PWRON_TIME, 0);
+	if (ret < 0)
+		goto exit;
+	ret = rtc_update_bits(RTC_PDN2, RTC_PDN2_PWRON_LOGO, 0);
+	if (ret < 0)
+		goto exit;
+
+	ret = rtc_write_trigger();
+	if (ret < 0)
+		goto exit;
+
+	return;
+
+exit:
+	pr_err("%s error\n", __func__);
+}
+
+static void mtk_rtc_clear_alarm(void)
+{
+	unsigned int irqsta;
+	u16 data[RTC_OFFSET_COUNT];
+	int i, ret;
+
+	ret = rtc_update_bits(RTC_IRQ_EN, RTC_IRQ_EN_AL, 0);
+	if (ret < 0)
+		goto exit;
+	ret = rtc_write_trigger();
+	if (ret < 0)
+		goto exit;
+
+	ret = rtc_read(RTC_IRQ_STA, &irqsta);	/* read clear */
+	if (ret < 0)
+		goto exit;
+
+	data[RTC_OFFSET_SEC] = 0;
+	data[RTC_OFFSET_MIN] = 0;
+	data[RTC_OFFSET_HOUR] = 0;
+	data[RTC_OFFSET_DOM] = RTC_DEFAULT_DOM & RTC_AL_DOM_MASK;
+	data[RTC_OFFSET_MTH] = RTC_DEFAULT_MTH & RTC_AL_MTH_MASK;
+	data[RTC_OFFSET_YEAR] = ((RTC_DEFAULT_YEA - RTC_MIN_YEAR) &
+				 RTC_AL_YEA_MASK);
+
+	for (i = RTC_OFFSET_SEC; i < RTC_OFFSET_COUNT; i++) {
+		if (i == RTC_OFFSET_DOW)
+			continue;
+		ret = rtc_update_bits(rtc_alarm_reg[i][RTC_REG],
+				      rtc_alarm_reg[i][RTC_MASK], data[i]);
+		if (ret < 0)
+			goto exit;
+	}
+
+	ret = rtc_write_trigger();
+	if (ret < 0)
+		goto exit;
+
+	return;
+exit:
+	pr_err("%s error\n", __func__);
+}
+
+void rtc_mark_recovery(void)
+{
+	unsigned long flags;
+
+	pr_notice("%s\n", __func__);
+
+	spin_lock_irqsave(&rtc_misc->lock, flags);
+	mtk_rtc_set_spare_register(RTC_FAC_RESET, 0x1);
+	/* Clear alarm setting when doing factory recovery. */
+	mtk_rtc_clear_pwron_alarm();
+	mtk_rtc_clear_alarm();
+	spin_unlock_irqrestore(&rtc_misc->lock, flags);
+}
+
+void rtc_mark_kpoc(void)
+{
+	unsigned long flags;
+
+	pr_notice("%s\n", __func__);
+
+	spin_lock_irqsave(&rtc_misc->lock, flags);
+	mtk_rtc_set_spare_register(RTC_KPOC, 0x1);
+	spin_unlock_irqrestore(&rtc_misc->lock, flags);
+}
+
+void rtc_mark_fast(void)
+{
+	unsigned long flags;
+
+	pr_notice("%s\n", __func__);
+
+	spin_lock_irqsave(&rtc_misc->lock, flags);
+	mtk_rtc_set_spare_register(RTC_FAST_BOOT, 0x1);
+	spin_unlock_irqrestore(&rtc_misc->lock, flags);
+}
+
+static int pmic_read_interface(unsigned int RegNum, unsigned int *val,
+			       unsigned int MASK, unsigned int SHIFT)
+{
+	int ret = 0;
+
+#ifdef IPIMB
+	ret = regmap_read(pmic_regmap, RegNum, val);
+#else
+	ret = regmap_read(rtc_misc->regmap, RegNum, val);
+#endif
+	if (ret) {
+		pr_notice("[%s]ret=%d Reg=0x%x val=0x%x MASK=0x%x SHIFT=%d\n",
+			  __func__, ret, RegNum, val, MASK, SHIFT);
+		return ret;
+	}
+
+	*val = (*val >> SHIFT) & MASK;
+
+	return ret;
+}
+
+static int upmu_get_reg_value(unsigned int reg, unsigned int *reg_val)
+{
+	int ret = 0;
+
+	ret = pmic_read_interface(reg, reg_val, 0xFFFF, 0x0);
+
+	return ret;
+}
+
+static int pmic_config_interface(unsigned int RegNum, unsigned int val,
+				 unsigned int MASK, unsigned int SHIFT)
+{
+	int ret = 0;
+
+#ifdef IPIMB
+	ret = regmap_update_bits(pmic_regmap, RegNum,
+				 (MASK << SHIFT), (val << SHIFT));
+#else
+	ret = regmap_update_bits(rtc_misc->regmap, RegNum,
+				 (MASK << SHIFT), (val << SHIFT));
+#endif
+	if (ret) {
+		pr_notice("[%s]ret=%d Reg=0x%x val=0x%x MASK=0x%x SHIFT=%d\n",
+			  __func__, ret, RegNum, val, MASK, SHIFT);
+		return ret;
+	}
+
+	return ret;
+}
+
+static int upmu_set_reg_value(unsigned int reg, unsigned int reg_val)
+{
+	unsigned int ret = 0;
+
+	ret = pmic_config_interface(reg, reg_val, 0xFFFF, 0x0);
+
+	return ret;
+}
+
+static void mtk_rtc_enable_k_eosc(void)
+{
+	pr_notice("%s\n", __func__);
+
+	/* Truning on eosc cali mode clock */
+	pmic_config_interface(MT6389_SCK_TOP_CKPDN_CON0_CLR_ADDR, 1,
+			      MT6389_RG_RTC_EOSC32_CK_PDN_MASK,
+			      MT6389_RG_RTC_EOSC32_CK_PDN_SHIFT);
+
+	if (rtc_eosc_cali_td != 8) {
+		pr_notice("%s: rtc_eosc_cali_td = %d\n",
+			  __func__, rtc_eosc_cali_td);
+		switch (rtc_eosc_cali_td) {
+		case 1:
+			pmic_config_interface(MT6389_EOSC_CALI_TD_ADDR, 0x3,
+					      MT6389_EOSC_CALI_TD_MASK,
+					      MT6389_EOSC_CALI_TD_SHIFT);
+			break;
+		case 2:
+			pmic_config_interface(MT6389_EOSC_CALI_TD_ADDR, 0x4,
+					      MT6389_EOSC_CALI_TD_MASK,
+					      MT6389_EOSC_CALI_TD_SHIFT);
+			break;
+		case 4:
+			pmic_config_interface(MT6389_EOSC_CALI_TD_ADDR, 0x5,
+					      MT6389_EOSC_CALI_TD_MASK,
+					      MT6389_EOSC_CALI_TD_SHIFT);
+			break;
+		case 16:
+			pmic_config_interface(MT6389_EOSC_CALI_TD_ADDR, 0x7,
+					      MT6389_EOSC_CALI_TD_MASK,
+					      MT6389_EOSC_CALI_TD_SHIFT);
+			break;
+		default:
+			pmic_config_interface(MT6389_EOSC_CALI_TD_ADDR, 0x6,
+					      MT6389_EOSC_CALI_TD_MASK,
+					      MT6389_EOSC_CALI_TD_SHIFT);
+			break;
+		}
+	}
+	/*
+	 * Switch the DCXO from 32k-less mode to RTC mode,
+	 * otherwise, EOSC cali will fail
+	 * RTC mode will have only OFF mode and FPM
+	 */
+	if (dcxo_switch) {
+		pr_notice("%s: dcxo_switch\n", __func__);
+		pmic_config_interface(MT6389_XO_EN32K_MAN_ADDR, 0,
+				      MT6389_XO_EN32K_MAN_MASK,
+				      MT6389_XO_EN32K_MAN_SHIFT);
+	}
+}
+
+static void mtk_rtc_spar_alarm_clear_wait(void)
+{
+	unsigned long long timeout = sched_clock() + 500000000;
+	u32 bbpu;
+	int ret;
+
+	do {
+		ret = rtc_read(RTC_BBPU, &bbpu);
+		if (ret < 0)
+			break;
+		if ((bbpu & RTC_BBPU_CLR) == 0)
+			break;
+		else if (sched_clock() > timeout) {
+			pr_err("%s, spar/alarm clear time out,\n", __func__);
+			break;
+		}
+	} while (1);
+}
+
+void mt_power_off(void)
+{
+	unsigned long flags;
+	u32 pdn1 = 0, al_mask = 0, irq_en = 0;
+	int ret;
+
+	pr_notice("%s\n", __func__);
+	dump_stack();
+
+	spin_lock_irqsave(&rtc_misc->lock, flags);
+
+#ifndef CONFIG_MTK_PMIC_CHIP_MT6389
+	ret = rtc_field_read(RTC_PDN1, RTC_GPIO_USER_MASK,
+			     RTC_GPIO_USER_WIFI, &pdn1);
+	if (ret < 0)
+		goto exit;
+	/* disable 32K export if there are no RTC_GPIO users */
+	if (!pdn1) {
+		ret = rtc_update_bits(RTC_CON, RTC_CON_F32KOB, RTC_CON_F32KOB);
+		if (ret < 0)
+			goto exit;
+		ret = rtc_write_trigger();
+		if (ret < 0)
+			goto exit;
+	}
+#endif
+
+	/* lpsd */
+	pr_notice("clear lpsd solution\n");
+	ret = rtc_write(RTC_BBPU, RTC_BBPU_KEY | RTC_BBPU_CLR | RTC_BBPU_PWREN);
+	if (ret < 0)
+		goto exit;
+	ret = rtc_write(RTC_AL_MASK, RTC_AL_MASK_DOW);	/* mask DOW */
+	if (ret < 0)
+		goto exit;
+	ret = rtc_write_trigger();
+	if (ret < 0)
+		goto exit;
+	mtk_rtc_spar_alarm_clear_wait();
+
+	ret = rtc_update_bits(RTC_BBPU,
+			      (RTC_BBPU_KEY | RTC_BBPU_RELOAD),
+			      (RTC_BBPU_KEY | RTC_BBPU_RELOAD));
+	if (ret < 0)
+		goto exit;
+	ret = rtc_write_trigger();
+	if (ret < 0)
+		goto exit;
+
+	ret = rtc_read(RTC_AL_MASK, &al_mask);
+	if (ret < 0)
+		goto exit;
+	ret = rtc_read(RTC_IRQ_EN, &irq_en);
+	if (ret < 0)
+		goto exit;
+	pr_notice("%s: RTC_AL_MASK= 0x%x RTC_IRQ_EN= 0x%x\n",
+		  __func__, al_mask, irq_en);
+
+	spin_unlock_irqrestore(&rtc_misc->lock, flags);
+
+	//wk_pmic_enable_sdn_delay();
+	pmic_config_interface(MT6389_TMA_KEY_ADDR, 0x9CA7,
+			      MT6389_TMA_KEY_MASK, MT6389_TMA_KEY_SHIFT);
+	pmic_config_interface(MT6389_RG_SDN_DLY_ENB_ADDR, 0,
+			      MT6389_RG_SDN_DLY_ENB_MASK,
+			      MT6389_RG_SDN_DLY_ENB_SHIFT);
+	pmic_config_interface(MT6389_TMA_KEY_ADDR, 0,
+	MT6389_TMA_KEY_MASK, MT6389_TMA_KEY_SHIFT);
+
+#ifndef CONFIG_MTK_PMIC_CHIP_MT6389
+	pmic_config_interface(MT6389_RG_PWRHOLD_ADDR, 0,
+			      MT6389_RG_PWRHOLD_MASK, MT6389_RG_PWRHOLD_SHIFT);
+#endif
+
+	return;
+
+exit:
+	spin_unlock_irqrestore(&rtc_misc->lock, flags);
+	pr_err("%s error\n", __func__);
+
+}
+
+static void mtk_rtc_lpsd_restore_al_mask(void)
+{
+	int ret;
+	u32 val;
+
+	ret = rtc_update_bits(RTC_BBPU,
+			      (RTC_BBPU_KEY | RTC_BBPU_RELOAD),
+			      (RTC_BBPU_KEY | RTC_BBPU_RELOAD));
+	if (ret < 0)
+		goto exit;
+	ret = rtc_write_trigger();
+	if (ret < 0)
+		goto exit;
+
+	ret = rtc_read(RTC_AL_MASK, &val);
+	if (ret < 0)
+		goto exit;
+	pr_notice("%s: 1st RTC_AL_MASK = 0x%x\n", __func__, val);
+
+	/* mask DOW */
+	ret = rtc_write(RTC_AL_MASK, RTC_AL_MASK_DOW);
+	if (ret < 0)
+		goto exit;
+	ret = rtc_write_trigger();
+	if (ret < 0)
+		goto exit;
+
+	ret = rtc_read(RTC_AL_MASK, &val);
+	if (ret < 0)
+		goto exit;
+	pr_notice("%s: 2nd RTC_AL_MASK = 0x%x\n", __func__, val);
+
+	return;
+exit:
+	pr_err("%s error\n", __func__);
+}
+
+static void mt6358_misc_shutdown(struct platform_device *pdev)
+{
+	if (eosc_k)
+		mtk_rtc_enable_k_eosc();
+}
+
+static bool rtc_gpio_init(void)
+{
+	u16 con;
+	int ret;
+	u32 val;
+
+	/* GPI mode and pull enable + pull down */
+	ret = rtc_read(RTC_CON, &val);
+	if (ret < 0)
+		goto exit;
+	con = val & (RTC_CON_LPSTA_RAW | RTC_CON_LPRST |
+		     RTC_XOSC32_LPEN | RTC_EOSC32_LPEN);
+	con &= ~RTC_CON_GPU;
+	con &= ~RTC_CON_F32KOB;	//for avoid leak current
+	con |= RTC_CON_GPEN | RTC_CON_GOE;
+	rtc_write(RTC_CON, con);
+	if (rtc_write_trigger())
+		return true;
+	else
+		return false;
+exit:
+	pr_err("%s error\n", __func__);
+	return false;
+}
+
+void rtc_reload(void)
+{
+	u16 bbpu;
+	int ret;
+	u32 val;
+
+	ret = rtc_read(RTC_BBPU, &val);
+	if (ret < 0)
+		goto exit;
+	bbpu = val | RTC_BBPU_KEY | RTC_BBPU_RELOAD;
+	rtc_write(RTC_BBPU, bbpu);
+	rtc_write_trigger();
+	return;
+exit:
+	pr_err("%s error\n", __func__);
+}
+
+void rtc_xosc_write(u16 val)
+{
+	int ret;
+
+	rtc_write(RTC_OSC32CON, RTC_OSC32CON_UNLOCK1);
+	mdelay(1);
+
+	rtc_write(RTC_OSC32CON, RTC_OSC32CON_UNLOCK2);
+	mdelay(1);
+
+	rtc_write(RTC_OSC32CON, val);
+	mdelay(1);
+
+	pr_notice("[RTC] xosc write val=%x\n", val);
+}
+
+void rtc_switch_mode(bool XOSC, bool recovery)
+{
+	u16 osc32con;
+
+	if (XOSC) {
+		/* Since HW XTAL_DET is removed, there is a register for
+		 * switch the external crystal or the embedded clock
+		 */
+		/* 0: with the external xtal */
+		pmic_config_interface(MT6389_SCK_TOP_XTAL_SEL_ADDR, 0,
+				      MT6389_SCK_TOP_XTAL_SEL_MASK,
+				      MT6389_SCK_TOP_XTAL_SEL_SHIFT);
+		osc32con = OSC32CON_ANALOG_SETTING;
+		/* assume crystal exist mode + XOSCCALI = 0x7 */
+		rtc_xosc_write(osc32con | 0x7);
+		if (recovery)
+			mdelay(1500);
+	} else {
+		/* 1: without the external xtal */
+		pmic_config_interface(MT6389_SCK_TOP_XTAL_SEL_ADDR, 1,
+				      MT6389_SCK_TOP_XTAL_SEL_MASK,
+				      MT6389_SCK_TOP_XTAL_SEL_SHIFT);
+		if (recovery)
+			mdelay(100);
+		osc32con = OSC32CON_ANALOG_SETTING | RTC_REG_XOSC32_ENB;
+		/*crystal not exist + eosc cali = 0xF */
+		rtc_xosc_write(osc32con);
+		mdelay(10);
+	}
+}
+
+void rtc_switch_to_xosc_recv_mode(void)
+{
+	rtc_switch_mode(true, true);
+}
+
+void rtc_switch_to_dcxo_recv_mode(void)
+{
+	rtc_switch_mode(false, true);
+}
+
+static u16 get_frequency_meter(u16 cali, u16 measureSrc, u16 window_size)
+{
+	u16 data;
+	int ret;
+	u32 val;
+	unsigned long long timeout = sched_clock() + 500000000;
+
+	if (cali != 0) {
+		u16 osc32con;
+
+		rtc_reload();
+		ret = rtc_read(RTC_OSC32CON, &val);
+		if (ret < 0)
+			goto exit;
+		osc32con = val & 0xFFE0;
+		rtc_xosc_write(osc32con | (cali & RTC_XOSCCALI_MASK));
+	}
+
+	pmic_config_interface(FQMTR_CLK_CK_PDN_CLR, 1, FQMTR_CLK_CK_PDN_MASK,
+			      FQMTR_CLK_CK_PDN_SHIFT);
+	pmic_config_interface(RG_FQMTR_32K_CLK_PDN_CLR, 1,
+			      RG_FQMTR_32K_CLK_PDN_MASK,
+			      RG_FQMTR_32K_CLK_PDN_SHIFT);
+
+	pmic_config_interface(MT6389_RG_BANK_FQMTR_RST_ADDR, 1,
+			      MT6389_RG_BANK_FQMTR_RST_MASK,
+			      MT6389_RG_BANK_FQMTR_RST_SHIFT);
+	udelay(20);
+	pmic_config_interface(MT6389_RG_BANK_FQMTR_RST_ADDR, 0,
+			      MT6389_RG_BANK_FQMTR_RST_MASK,
+			      MT6389_RG_BANK_FQMTR_RST_SHIFT);
+
+	pmic_config_interface(MT6389_FQMTR_DCXO26M_EN_ADDR, 1,
+			      MT6389_FQMTR_DCXO26M_EN_MASK,
+			      MT6389_FQMTR_DCXO26M_EN_SHIFT);
+	//set freq. meter window value (0=1X32K(fix clock))
+	upmu_set_reg_value(RG_FQMTR_WINSET, window_size);
+	//enable freq. meter, set measure clock to 26Mhz
+	upmu_set_reg_value(RG_FQMTR_TCKSEL, FQMTR_DCXO26M_EN | measureSrc);
+	mdelay(1);
+	ret = upmu_get_reg_value(RG_FQMTR_TCKSEL, &val);
+	if (ret < 0)
+		goto exit;
+	upmu_set_reg_value(RG_FQMTR_TCKSEL, val | FQMTR_EN);
+	mdelay(1);
+
+	// FQMTR read until ready
+	do {
+		if (sched_clock() > timeout) {
+			pr_err("[RTC] get frequency time out\n");
+			break;
+		}
+		mdelay(1);
+		ret = upmu_get_reg_value(RG_FQMTR_BUSY, &val);
+		if (ret < 0)
+			goto exit;
+	} while ((FQMTR_BUSY & val) == FQMTR_BUSY);
+	ret = upmu_get_reg_value(RG_FQMTR_DATA, &val);
+	if (ret < 0)
+		goto exit;
+	data = val;		//read data should be closed to 26M/32k = 794
+
+	pmic_config_interface(MT6389_FQMTR_DCXO26M_EN_ADDR, 0,
+			      MT6389_FQMTR_DCXO26M_EN_MASK,
+			      MT6389_FQMTR_DCXO26M_EN_SHIFT);
+	ret = upmu_get_reg_value(RG_FQMTR_TCKSEL, &val);
+	if (ret < 0)
+		goto exit;
+	//enable freq. meter, set measure clock to 26Mhz
+	upmu_set_reg_value(RG_FQMTR_TCKSEL, val & ~(FQMTR_DCXO26M_EN));
+	mdelay(1);
+	ret = upmu_get_reg_value(RG_FQMTR_TCKSEL, &val);
+	if (ret < 0)
+		goto exit;
+	//enable freq. meter, set measure clock to 26Mhz
+	upmu_set_reg_value(RG_FQMTR_TCKSEL, val & ~(FQMTR_EN));
+	pr_notice("[RTC] %s: input=0x%x, output=%d\n", __func__, cali, data);
+
+	pmic_config_interface(FQMTR_CLK_CK_PDN_SET, 1, FQMTR_CLK_CK_PDN_MASK,
+			      FQMTR_CLK_CK_PDN_SHIFT);
+	pmic_config_interface(RG_FQMTR_32K_CLK_PDN_SET, 1,
+			      RG_FQMTR_32K_CLK_PDN_MASK,
+			      RG_FQMTR_32K_CLK_PDN_SHIFT);
+
+	return data;
+exit:
+	pr_err("%s error\n", __func__);
+	return 0;
+}
+
+void rtc_measure_four_clock(u16 *result)
+{
+	u16 window_size;
+	u16 regval;
+	int ret;
+	u32 val;
+
+	ret = upmu_get_reg_value(RG_FQMTR_CKSEL, &val);
+	if (ret < 0)
+		goto exit;
+	regval = val & (~(RG_FQMTR_CKSEL_MASK << RG_FQMTR_CKSEL_SHIFT));
+	//select 26M as fixed clock
+	upmu_set_reg_value(RG_FQMTR_CKSEL, regval | FQMTR_FIX_CLK_26M);
+	window_size = 4;
+	mdelay(1);
+	//select 26M as target clock
+	result[0] = get_frequency_meter(0, FQMTR_FQM26M_CK, window_size);
+	ret = upmu_get_reg_value(RG_FQMTR_CKSEL, &val);
+	if (ret < 0)
+		goto exit;
+	regval = val & (~(RG_FQMTR_CKSEL_MASK << RG_FQMTR_CKSEL_SHIFT));
+	//select XOSC_DET as fixed clock
+	upmu_set_reg_value(RG_FQMTR_CKSEL, regval | FQMTR_FIX_CLK_XOSC_32K_DET);
+	window_size = 4;
+	mdelay(1);
+	//select 26M as target clock
+	result[1] = get_frequency_meter(0, FQMTR_FQM26M_CK, window_size);
+	ret = upmu_get_reg_value(RG_FQMTR_CKSEL, &val);
+	if (ret < 0)
+		goto exit;
+	regval = val & (~(RG_FQMTR_CKSEL_MASK << RG_FQMTR_CKSEL_SHIFT));
+	//select 26M as fixed clock
+	upmu_set_reg_value(RG_FQMTR_CKSEL, regval | FQMTR_FIX_CLK_26M);
+	window_size = 3970;	// (26M / 32K) * 5
+	mdelay(1);
+	//select xosc_32 as target clock
+	result[2] = get_frequency_meter(0, FQMTR_XOSC32_CK, window_size);
+	//select DCXO_32 as target clock
+	result[2] = get_frequency_meter(0, FQMTR_DCXO_F32K_CK, window_size);
+	ret = upmu_get_reg_value(RG_FQMTR_CKSEL, &val);
+	if (ret < 0)
+		goto exit;
+	regval = val & (~(RG_FQMTR_CKSEL_MASK << RG_FQMTR_CKSEL_SHIFT));
+	//select EOSC_32 as fixed clock
+	upmu_set_reg_value(RG_FQMTR_CKSEL, regval | FQMTR_FIX_CLK_EOSC_32K);
+	window_size = 4;
+	mdelay(1);
+	//select 26M as target clock
+	result[3] = get_frequency_meter(0, FQMTR_FQM26M_CK, window_size);
+
+	return;
+exit:
+	pr_err("%s error\n", __func__);
+}
+
+static bool rtc_xosc_check_clock(u16 *result)
+{
+	///// fix me  loose range for frequency meter result////
+	if ((result[0] >= 3 && result[0] <= 7) &&
+	    (result[1] > 1500 && result[1] < 6000) &&
+	    (result[2] == 0) && (result[3] == 0))
+		return true;
+	else
+		return false;
+}
+
+static bool rtc_eosc_check_clock(u16 *result)
+{
+	if ((result[0] >= 3 && result[0] <= 7) &&
+	    (result[1] < 500) &&
+	    (result[2] > 2 && result[2] < 9) &&
+	    (result[3] > 300 && result[3] < 10400))
+		return true;
+	else
+		return false;
+}
+
+bool Writeif_unlock(void)
+{
+	rtc_write(RTC_PROT, RTC_PROT_UNLOCK1);
+	if (!rtc_write_trigger())
+		return false;
+	rtc_write(RTC_PROT, RTC_PROT_UNLOCK2);
+	if (!rtc_write_trigger())
+		return false;
+
+	return true;
+}
+
+int eosc_cali(void)
+{
+	u32 val, diff1, diff2, eosc_freq, regval;
+	int middle;
+	int i, left, right;
+	int ret;
+
+	ret = upmu_get_reg_value(RG_FQMTR_CKSEL, &val);
+	if (ret < 0)
+		goto exit;
+	regval = val & (~(RG_FQMTR_CKSEL_MASK << RG_FQMTR_CKSEL_SHIFT));
+	//select EOSC_32 as fixed clock
+	upmu_set_reg_value(RG_FQMTR_CKSEL, regval | FQMTR_FIX_CLK_EOSC_32K);
+
+	left = RTC_XOSCCALI_START;
+	right = RTC_XOSCCALI_END;
+	while (left <= right) {
+		middle = (right + left) / 2;
+		if (middle == left)
+			break;
+
+		//select 26M as target clock
+		val = get_frequency_meter(middle,
+					  FQMTR_FQM26M_CK, 0);
+		pr_notice("[RTC] EOSC_Cali: val=0x%x\n", val);
+		if ((val >= RTC_FQMTR_LOW_BASE) && (val <= RTC_FQMTR_HIGH_BASE))
+			break;
+		if (val > RTC_FQMTR_HIGH_BASE)
+			right = middle;
+		else
+			left = middle;
+	}
+
+	if ((val >= RTC_FQMTR_LOW_BASE) && (val <= RTC_FQMTR_HIGH_BASE))
+		return middle;
+
+	val = get_frequency_meter(left, FQMTR_FQM26M_CK, 0);
+	if (val > RTC_FQMTR_LOW_BASE)
+		diff1 = val - RTC_FQMTR_LOW_BASE;
+	else
+		diff1 = RTC_FQMTR_LOW_BASE - val;
+
+	val = get_frequency_meter(right, FQMTR_FQM26M_CK, 0);
+	if (val > RTC_FQMTR_LOW_BASE)
+		diff2 = val - RTC_FQMTR_LOW_BASE;
+	else
+		diff2 = RTC_FQMTR_LOW_BASE - val;
+
+	if (diff1 < diff2)
+		return left;
+	else
+		return right;
+exit:
+	pr_err("%s error\n", __func__);
+	return 0;
+}
+
+static bool eosc_init(void)
+{
+	u16 osc32con, val = 0;
+
+	val = eosc_cali();
+	pr_notice("EOSC cali val = 0x%x\n", val);
+	//EMB_HW_Mode
+	osc32con = OSC32CON_ANALOG_SETTING | RTC_REG_XOSC32_ENB;
+	val = (val & 0x001f) | osc32con;
+	pr_notice("EOSC cali val = 0x%x\n", val);
+	rtc_xosc_write(val);
+	return true;
+}
+
+static bool rtc_hw_init(void)
+{
+	int ret;
+	u32 val;
+	unsigned long long timeout = sched_clock() + 500000000;
+
+	ret = rtc_read(RTC_BBPU, &val);
+	if (ret < 0)
+		goto exit;
+	rtc_write(RTC_BBPU,
+		  val | RTC_BBPU_KEY | RTC_BBPU_RESET_ALARM |
+		  RTC_BBPU_RESET_SPAR &
+		  (~RTC_BBPU_SPAR_SW));
+	rtc_write_trigger();
+
+	do {
+		rtc_reload();
+		ret = rtc_read(RTC_BBPU, &val);
+		if (ret < 0)
+			goto exit;
+	} while (((val & RTC_BBPU_RESET_ALARM) || (val & RTC_BBPU_RESET_SPAR))
+		 && sched_clock() < timeout);
+
+	if ((val & RTC_BBPU_RESET_ALARM) || (val & RTC_BBPU_RESET_SPAR)) {
+		pr_err("[RTC] hw_init timeout\n");
+		return false;
+	}
+
+	return true;
+exit:
+	pr_err("%s error\n", __func__);
+	return false;
+}
+
+static bool rtc_lpd_init(void)
+{
+	u16 con;
+	int ret;
+	u32 val;
+
+	ret = rtc_read(RTC_CON, &val);
+	if (ret < 0)
+		goto exit;
+	con = val | RTC_XOSC32_LPEN;
+	con &= ~RTC_CON_LPRST;
+	rtc_write(RTC_CON, con);
+	if (!rtc_write_trigger())
+		return false;
+
+	con |= RTC_CON_LPRST;
+	rtc_write(RTC_CON, con);
+	if (!rtc_write_trigger())
+		return false;
+
+	con &= ~RTC_CON_LPRST;
+	rtc_write(RTC_CON, con);
+	if (!rtc_write_trigger())
+		return false;
+
+	ret = rtc_read(RTC_CON, &val);
+	if (ret < 0)
+		goto exit;
+	con = val | RTC_EOSC32_LPEN;
+	con &= ~RTC_CON_LPRST;
+	rtc_write(RTC_CON, con);
+	if (!rtc_write_trigger())
+		return false;
+
+	con |= RTC_CON_LPRST;
+	rtc_write(RTC_CON, con);
+	if (!rtc_write_trigger())
+		return false;
+
+	con &= ~RTC_CON_LPRST;
+	rtc_write(RTC_CON, con);
+	if (!rtc_write_trigger())
+		return false;
+
+	ret = rtc_read(RTC_CON, &val);
+	if (ret < 0)
+		goto exit;
+	pr_notice("[RTC] %s RTC_CON=0x%x\n", __func__, val);
+	ret = rtc_read(RTC_SPAR0, &val);
+	if (ret < 0)
+		goto exit;
+	//bit 7 for low power detected in preloader
+	rtc_write(RTC_SPAR0, val | 0x0080);
+	if (!rtc_write_trigger())
+		return false;
+
+	return true;
+exit:
+	pr_err("%s error\n", __func__);
+	return false;
+}
+
+static bool rtc_2sec_stat_clear(void)
+{
+	int ret;
+	u32 val;
+
+	pr_notice("[RTC] %s\n", __func__);
+
+	ret = rtc_read(RTC_AL_SEC, &val);
+	if (ret < 0)
+		goto exit;
+	rtc_write(RTC_AL_SEC, val & ~RTC_BBPU_2SEC_STAT_CLEAR);
+	if (!rtc_write_trigger())
+		return false;
+	ret = rtc_read(RTC_AL_SEC, &val);
+	if (ret < 0)
+		goto exit;
+	rtc_write(RTC_AL_SEC, val | RTC_BBPU_2SEC_STAT_CLEAR);
+	if (!rtc_write_trigger())
+		return false;
+	ret = rtc_read(RTC_AL_SEC, &val);
+	if (ret < 0)
+		goto exit;
+	rtc_write(RTC_AL_SEC, val & ~RTC_BBPU_2SEC_STAT_CLEAR);
+	if (!rtc_write_trigger())
+		return false;
+
+	return true;
+exit:
+	pr_err("%s error\n", __func__);
+	return false;
+}
+
+static bool rtc_android_init(void)
+{
+	u16 reboot;
+	int ret;
+	u32 val;
+
+	rtc_write(RTC_IRQ_EN, 0);
+	rtc_write(RTC_CII_EN, 0);
+	rtc_write(RTC_AL_MASK, 0);
+
+	ret = rtc_read(RTC_AL_YEA, &val);
+	if (ret < 0)
+		goto exit;
+	rtc_write(RTC_AL_YEA,
+		  (val & (~RTC_AL_YEA_MASK)) |
+		  ((1970 - RTC_MIN_YEAR) & RTC_AL_YEA_MASK));
+	rtc_write(RTC_AL_MTH, 1);
+	rtc_write(RTC_AL_DOM, 1);	/* NEW_SPARE1[0] = 0 */
+	/* RG_EOSC_CALI_TD = 8 sec */
+	rtc_write(RTC_AL_DOW, RTC_EOSC_CALI_TD_08_SEC <<
+		  MT6389_RG_EOSC_CALI_TD_SHIFT | 1);
+
+	rtc_write(RTC_AL_HOU, 0);
+	rtc_write(RTC_AL_MIN, 0);
+	ret = rtc_read(RTC_AL_SEC, &val);
+	if (ret < 0)
+		goto exit;
+	rtc_write(RTC_AL_SEC, val & (~RTC_AL_SEC_MASK));
+
+	rtc_write(RTC_PDN1, 0);	/* set Debug bit */
+	rtc_write(RTC_PDN2, 0);
+	rtc_write(RTC_SPAR0, 0);
+	rtc_write(RTC_SPAR1, 0);
+
+	rtc_write(RTC_DIFF, 0);
+	rtc_write(RTC_CALI, 0);
+
+	ret = rtc_read(RTC_AL_SEC, &val);
+	if (ret < 0)
+		goto exit;
+	reboot = (val & ~RTC_BBPU_2SEC_EN) & ~RTC_BBPU_AUTO_PDN_SEL;
+	rtc_write(RTC_AL_SEC, reboot);
+
+	if (!rtc_2sec_stat_clear())
+		return false;
+	if (!rtc_write_trigger())
+		return false;
+
+	/* read clear */
+	ret = rtc_read(RTC_AL_SEC, &val);
+	if (ret < 0)
+		goto exit;
+
+	/* init time counters after resetting RTC_DIFF and RTC_CALI */
+	rtc_write(RTC_TC_YEA, 2010 - RTC_MIN_YEAR);
+	rtc_write(RTC_TC_MTH, 1);
+	rtc_write(RTC_TC_DOM, 1);
+	rtc_write(RTC_TC_DOW, 1);
+	rtc_write(RTC_TC_HOU, 0);
+	rtc_write(RTC_TC_MIN, 0);
+	rtc_write(RTC_TC_SEC, 0);
+	if (!rtc_write_trigger())
+		return false;
+
+	return true;
+exit:
+	pr_err("%s error\n", __func__);
+	return false;
+}
+
+static bool rtc_first_boot_init(void)
+{
+	int ret;
+	u32 val;
+	u16 result[4];
+
+	pr_notice("[RTC] %s\n", __func__);
+
+	pmic_config_interface(MT6389_XO_EN32K_MAN_ADDR, 0,
+			      MT6389_XO_EN32K_MAN_MASK,
+			      MT6389_XO_EN32K_MAN_SHIFT);
+	pmic_config_interface(MT6389_XO_XMODE_M_ADDR, 1, MT6389_XO_XMODE_M_MASK,
+			      MT6389_XO_XMODE_M_SHIFT);
+
+	/* always try xosc fisrt */
+	/* switch to XOSC */
+	if (support_xosc) {
+		rtc_switch_to_xosc_recv_mode();
+		rtc_measure_four_clock(result);
+	}
+	if (!support_xosc || !rtc_xosc_check_clock(result)) {
+		/* switch to DCXO if XOSC detect failed */
+		rtc_switch_to_dcxo_recv_mode();
+		rtc_measure_four_clock(result);
+		if (!rtc_eosc_check_clock(result)) {
+			pr_err("32k detection failed\n");
+			return false;
+		}
+	}
+
+	if (!Writeif_unlock()) {
+		pr_err("[RTC] Writeif_unlock fail1\n");
+		return false;
+	}
+
+	rtc_reload();
+
+	if (!rtc_gpio_init())
+		return false;
+
+	/* write powerkeys */
+	ret = rtc_read(RTC_AL_SEC, &val);
+	if (ret < 0)
+		goto exit;
+	rtc_write(RTC_AL_SEC, val & (~RTC_K_EOSC32_VTCXO_ON_SEL));
+	rtc_write(RTC_POWERKEY1, RTC_POWERKEY1_KEY);
+	rtc_write(RTC_POWERKEY2, RTC_POWERKEY2_KEY);
+	if (!rtc_write_trigger()) {
+		pr_err("[RTC] first_boot_init rtc_write_trigger fail1\n");
+		return false;
+	}
+	//disable both XOSC & EOSC LPD
+	ret = rtc_read(RTC_AL_SEC, &val);
+	if (ret < 0)
+		goto exit;
+	rtc_write(RTC_AL_SEC, val | RTC_LPD_OPT_F32K_CK_ALIVE);
+	if (!rtc_write_trigger()) {
+		pr_err("[RTC] %s rtc_write_trigger fail2\n", __func__);
+		return false;
+	}
+
+	if (!rtc_lpd_init())
+		return false;
+
+	//write POWERKEY again to unlock RTC
+	rtc_write(RTC_POWERKEY1, RTC_POWERKEY1_KEY);
+	rtc_write(RTC_POWERKEY2, RTC_POWERKEY2_KEY);
+	if (!rtc_write_trigger()) {
+		pr_err("[RTC] %s rtc_write_trigger fail3\n", __func__);
+		return false;
+	}
+	//Enable EOSC LPD
+	ret = rtc_read(RTC_AL_SEC, &val);
+	if (ret < 0)
+		goto exit;
+	rtc_write(RTC_AL_SEC, (val & (~RTC_LPD_OPT_MASK)) |
+		  RTC_LPD_OPT_EOSC_LPD);
+	rtc_write_trigger();
+
+	if (!eosc_init()) {
+		pr_err("[RTC] %s eosc_init fail\n", __func__);
+		return false;
+	}
+
+	if (!rtc_lpd_init()) {
+		pr_err("[RTC] %s rtc_lpd_init fail\n", __func__);
+		return false;
+	}
+
+	if (!rtc_hw_init()) {
+		pr_err("[RTC] %s rtc_hw_init fail\n", __func__);
+		return false;
+	}
+
+	if (!rtc_android_init()) {
+		pr_err("[RTC] %s rtc_android_init fail\n", __func__);
+		return false;
+	}
+
+	return true;
+exit:
+	pr_err("%s error\n", __func__);
+	return false;
+}
+
+static bool rtc_get_xosc_mode(void)
+{
+	u16 xosc_mode;
+	int ret;
+	u32 val;
+
+	ret =
+	    pmic_read_interface(MT6389_SCK_TOP_XTAL_SEL_ADDR,
+				&val, MT6389_SCK_TOP_XTAL_SEL_MASK,
+				MT6389_SCK_TOP_XTAL_SEL_SHIFT);
+	if (ret < 0)
+		goto exit;
+
+	if (val)
+		xosc_mode = 0;	/* 32k */
+	else
+		xosc_mode = 1;	/* 32k-less */
+
+	return xosc_mode;
+exit:
+	pr_err("%s error\n", __func__);
+	return false;
+}
+
+void rtc_init(void)
+{
+	u16 spar0;
+	int ret;
+	u32 val1, val2, val3;
+
+	pmic_config_interface(MT6389_TOP_CKPDN_CON0_CLR_ADDR, 1,
+			      MT6389_RG_FQMTR_CK_PDN_MASK,
+			      MT6389_RG_FQMTR_CK_PDN_SHIFT);
+	pmic_config_interface(MT6389_TOP_CKPDN_CON0_CLR_ADDR, 1,
+			      MT6389_RG_FQMTR_32K_CK_PDN_MASK,
+			      MT6389_RG_FQMTR_32K_CK_PDN_SHIFT);
+
+	ret = rtc_read(RTC_POWERKEY1, &val1);
+	if (ret < 0)
+		goto exit;
+	ret = rtc_read(RTC_POWERKEY2, &val2);
+	if (ret < 0)
+		goto exit;
+	ret = rtc_read(RTC_CON, &val3);
+	if (ret < 0)
+		goto exit;
+	pr_notice("%s#1 powerkey1 = 0x%x, powerkey2 = 0x%x, %s LPD\n",
+		  __func__, val1, val2,
+		  (val3 & RTC_CON_LPSTA_RAW) ? "with" : "without");
+	ret = rtc_read(RTC_BBPU, &val1);
+	if (ret < 0)
+		goto exit;
+	ret = rtc_read(RTC_CON, &val2);
+	if (ret < 0)
+		goto exit;
+	ret = rtc_read(RTC_OSC32CON, &val3);
+	if (ret < 0)
+		goto exit;
+	pr_notice("bbpu = 0x%x, con = 0x%x, osc32con = 0x%x\n",
+		  val1, val2, val3);
+
+	// switch from 32k to 128/4k
+	pmic_config_interface(MT6389_TOP_CKSEL_CON0_CLR_ADDR, 1,
+			      MT6389_RG_RTC_32K1V8_SEL_MASK,
+			      MT6389_RG_RTC_32K1V8_SEL_SHIFT);
+
+	// always do first boot init
+	if (!rtc_first_boot_init())
+		goto exit;
+
+	// switch from 128/4k to 32k
+	pmic_config_interface(MT6389_TOP_CKSEL_CON0_SET_ADDR, 1,
+			      MT6389_RG_RTC_32K1V8_SEL_MASK,
+			      MT6389_RG_RTC_32K1V8_SEL_SHIFT);
+
+	rtc_reload();
+
+	/* HW K EOSC mode whatever power off (including plug out battery) */
+	ret = rtc_read(RTC_AL_YEA, &val1);
+	if (ret < 0)
+		goto exit;
+	rtc_write(RTC_AL_YEA,
+		  (val1 | RTC_K_EOSC_RSV_0) &
+		  (~RTC_K_EOSC_RSV_1) & (~RTC_K_EOSC_RSV_2));
+	pmic_config_interface(MT6389_TOP_CKPDN_CON0_CLR_ADDR, 1,
+			      MT6389_RG_FQMTR_CK_PDN_MASK,
+			      MT6389_RG_FQMTR_CK_PDN_SHIFT);
+	/* Truning off eosc cali mode clock */
+	pmic_config_interface(MT6389_SCK_TOP_CKPDN_CON0_SET_ADDR, 1,
+			      MT6389_RG_RTC_EOSC32_CK_PDN_MASK,
+			      MT6389_RG_RTC_EOSC32_CK_PDN_SHIFT);
+
+	//set register to let MD know 32k status
+	ret = rtc_read(RTC_SPAR0, &val1);
+	if (ret < 0)
+		goto exit;
+	if (rtc_get_xosc_mode()) {
+		rtc_write(RTC_SPAR0, (val1 | RTC_SPAR0_32K_LESS));
+		pr_notice("RTC/32k mode\n");
+	} else {
+		rtc_write(RTC_SPAR0, (val1 & ~RTC_SPAR0_32K_LESS));
+		pr_notice("32k-less mode\n");
+	}
+	rtc_write_trigger();
+
+	return;
+exit:
+	pr_err("%s error\n", __func__);
+}
+
+static int mt6358_misc_probe(struct platform_device *pdev)
+{
+	struct mt6358_chip *mt6358_chip = dev_get_drvdata(pdev->dev.parent);
+	struct mt6358_misc *misc;
+	unsigned long flags;
+
+	misc = devm_kzalloc(&pdev->dev, sizeof(struct mt6358_misc), GFP_KERNEL);
+	if (!misc)
+		return -ENOMEM;
+
+#ifdef IPIMB
+	pmic_regmap = mt6358_chip->regmap;
+	misc->regmap = dev_get_regmap(pdev->dev.parent->parent, NULL);
+#else
+	misc->regmap = mt6358_chip->regmap;
+#endif
+	if (!misc->regmap) {
+		pr_notice("get regmap failed\n");
+		return -ENODEV;
+	}
+
+	misc->dev = &pdev->dev;
+	spin_lock_init(&misc->lock);
+	rtc_misc = misc;
+	platform_set_drvdata(pdev, misc);
+
+	if (of_property_read_u32(pdev->dev.of_node,
+		"base", &rtc_misc->addr_base))
+		rtc_misc->addr_base = RTC_DSN_ID;
+	pr_notice("%s: rtc_misc->addr_base =0x%x\n",
+		__func__, rtc_misc->addr_base);
+
+	if (of_property_read_bool(pdev->dev.of_node, "apply-lpsd-solution")) {
+		spin_lock_irqsave(&misc->lock, flags);
+		mtk_rtc_lpsd_restore_al_mask();
+		spin_unlock_irqrestore(&misc->lock, flags);
+
+		pm_power_off = mt_power_off;
+	}
+
+	if (of_property_read_bool(pdev->dev.of_node, "dcxo-switch"))
+		dcxo_switch = 1;
+
+	if (of_property_read_bool(pdev->dev.of_node, "eosc-k"))
+		eosc_k = 1;
+
+	if (of_property_read_bool(pdev->dev.of_node, "support_xosc"))
+		support_xosc = 1;
+
+	rtc_init();
+
+	pr_notice("%s done\n", __func__);
+
+	return 0;
+}
+
+static const struct of_device_id mt6358_misc_of_match[] = {
+	{.compatible = "mediatek,mt6358-misc",},
+	{.compatible = "mediatek,mt6359-misc",},
+	{.compatible = "mediatek,mt6389-misc",},
+	{}
+};
+
+MODULE_DEVICE_TABLE(of, mt6358_misc_of_match);
+
+static struct platform_driver mt6358_misc_driver = {
+	.driver = {
+		   .name = "mt6358-misc",
+		   .of_match_table = mt6358_misc_of_match,
+		   },
+	.probe = mt6358_misc_probe,
+	.shutdown = mt6358_misc_shutdown,
+};
+
+module_platform_driver(mt6358_misc_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Wilma Wu <wilma.wu@mediatek.com>");
+MODULE_DESCRIPTION("Misc Driver for MediaTek MT6358 PMIC");