mediatek: mt8192: add rtc power off sequence

add mt6359p rtc power off sequence and enable k_eosc mode

Change-Id: I65450c63c44ccb5082541dbbe28b8aa0a95ecc56
diff --git a/plat/mediatek/mt8192/drivers/rtc/rtc.c b/plat/mediatek/mt8192/drivers/rtc/rtc.c
new file mode 100644
index 0000000..124bc8f
--- /dev/null
+++ b/plat/mediatek/mt8192/drivers/rtc/rtc.c
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2020, MediaTek Inc. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <common/debug.h>
+#include <drivers/delay_timer.h>
+#include <rtc.h>
+
+
+static void RTC_Config_Interface(uint32_t addr, uint16_t data,
+			    uint16_t mask, uint16_t shift)
+{
+	uint16_t pmic_reg;
+
+	pmic_reg = RTC_Read(addr);
+
+	pmic_reg &= ~(mask << shift);
+	pmic_reg |= (data << shift);
+
+	RTC_Write(addr, pmic_reg);
+}
+
+static int32_t rtc_disable_2sec_reboot(void)
+{
+	uint16_t reboot;
+
+	reboot = (RTC_Read(RTC_AL_SEC) & ~RTC_BBPU_2SEC_EN) &
+		 ~RTC_BBPU_AUTO_PDN_SEL;
+	RTC_Write(RTC_AL_SEC, reboot);
+
+	return RTC_Write_Trigger();
+}
+
+static int32_t rtc_enable_k_eosc(void)
+{
+	uint16_t alm_dow, alm_sec;
+	int16_t ret;
+
+	/* Turning on eosc cali mode clock */
+	RTC_Config_Interface(PMIC_RG_SCK_TOP_CKPDN_CON0_CLR, 1,
+			PMIC_RG_RTC_EOSC32_CK_PDN_MASK,
+			PMIC_RG_RTC_EOSC32_CK_PDN_SHIFT);
+
+	alm_sec = RTC_Read(RTC_AL_SEC) & (~RTC_LPD_OPT_MASK);
+	RTC_Write(RTC_AL_SEC, alm_sec);
+	ret = RTC_Write_Trigger();
+	if (ret == 0) {
+		return 0;
+	}
+
+	RTC_Write(RTC_CON, RTC_LPD_EN);
+	ret = RTC_Write_Trigger();
+	if (ret == 0) {
+		return 0;
+	}
+
+	RTC_Write(RTC_CON, RTC_LPD_RST);
+	ret = RTC_Write_Trigger();
+	if (ret == 0) {
+		return 0;
+	}
+
+	RTC_Write(RTC_CON, RTC_LPD_EN);
+	ret = RTC_Write_Trigger();
+	if (ret == 0) {
+		return 0;
+	}
+
+	RTC_Write(RTC_POWERKEY1, RTC_POWERKEY1_KEY);
+	RTC_Write(RTC_POWERKEY2, RTC_POWERKEY2_KEY);
+	ret = RTC_Write_Trigger();
+	if (ret == 0) {
+		return 0;
+	}
+
+	/* set RTC EOSC calibration period = 8sec */
+	alm_dow = (RTC_Read(RTC_AL_DOW) & (~RTC_RG_EOSC_CALI_TD_MASK)) |
+		  RTC_RG_EOSC_CALI_TD_8SEC;
+	RTC_Write(RTC_AL_DOW, alm_dow);
+	ret = RTC_Write_Trigger();
+	if (ret == 0) {
+		return 0;
+	}
+
+	RTC_Write(RTC_BBPU,
+		  RTC_Read(RTC_BBPU) | RTC_BBPU_KEY | RTC_BBPU_RELOAD);
+	ret = RTC_Write_Trigger();
+	if (ret == 0) {
+		return 0;
+	}
+
+	/* Enable K EOSC mode :use solution1 of eosc cali to fix mt6359p 32K*/
+	RTC_Write(RTC_AL_YEA, (((RTC_Read(RTC_AL_YEA) | RTC_K_EOSC_RSV_0)
+				& (~RTC_K_EOSC_RSV_1)) | (RTC_K_EOSC_RSV_2)));
+	ret = RTC_Write_Trigger();
+	if (ret == 0) {
+		return 0;
+	}
+
+	INFO("[RTC] RTC_enable_k_eosc\n");
+
+	return 1;
+}
+
+void rtc_power_off_sequence(void)
+{
+	uint16_t bbpu;
+	int16_t ret;
+
+	ret = rtc_disable_2sec_reboot();
+	if (ret == 0) {
+		return;
+	}
+
+	ret = rtc_enable_k_eosc();
+	if (ret == 0) {
+		return;
+	}
+
+	bbpu = RTC_BBPU_KEY | RTC_BBPU_PWREN;
+
+	if (Writeif_unlock() != 0) {
+		RTC_Write(RTC_BBPU,
+			  bbpu | RTC_BBPU_RESET_ALARM | RTC_BBPU_RESET_SPAR);
+		RTC_Write(RTC_AL_MASK, RTC_AL_MASK_DOW);
+		ret = RTC_Write_Trigger();
+		if (ret == 0) {
+			return;
+		}
+		mdelay(1);
+
+		bbpu = RTC_Read(RTC_BBPU);
+
+		if (((bbpu & RTC_BBPU_RESET_ALARM) > 0) ||
+		    ((bbpu & RTC_BBPU_RESET_SPAR) > 0)) {
+			INFO("[RTC] timeout\n");
+		}
+
+		bbpu = RTC_Read(RTC_BBPU) | RTC_BBPU_KEY | RTC_BBPU_RELOAD;
+		RTC_Write(RTC_BBPU, bbpu);
+		ret = RTC_Write_Trigger();
+		if (ret == 0) {
+			return;
+		}
+	}
+}