/* * Copyright (c) 2019, MediaTek Inc. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ #include #include #include static void RTC_Config_Interface(uint32_t addr, uint16_t data, uint16_t MASK, uint16_t SHIFT) { uint16_t pmic_reg = 0; pmic_reg = RTC_Read(addr); pmic_reg &= ~(MASK << SHIFT); pmic_reg |= (data << SHIFT); RTC_Write(addr, pmic_reg); } static void 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); RTC_Write_Trigger(); } static void rtc_xosc_write(uint16_t val, bool reload) { uint16_t bbpu; RTC_Write(RTC_OSC32CON, RTC_OSC32CON_UNLOCK1); rtc_busy_wait(); RTC_Write(RTC_OSC32CON, RTC_OSC32CON_UNLOCK2); rtc_busy_wait(); RTC_Write(RTC_OSC32CON, val); rtc_busy_wait(); if (reload) { bbpu = RTC_Read(RTC_BBPU) | RTC_BBPU_KEY | RTC_BBPU_RELOAD; RTC_Write(RTC_BBPU, bbpu); RTC_Write_Trigger(); } } static void rtc_enable_k_eosc(void) { uint16_t osc32; uint16_t rtc_eosc_cali_td = 8; /* eosc cali period time */ /* Truning on eosc cali mode clock */ RTC_Config_Interface(PMIC_RG_TOP_CON, 1, PMIC_RG_SRCLKEN_IN0_HW_MODE_MASK, PMIC_RG_SRCLKEN_IN0_HW_MODE_SHIFT); RTC_Config_Interface(PMIC_RG_TOP_CON, 1, PMIC_RG_SRCLKEN_IN1_HW_MODE_MASK, PMIC_RG_SRCLKEN_IN1_HW_MODE_SHIFT); RTC_Config_Interface(PMIC_RG_SCK_TOP_CKPDN_CON0, 0, PMIC_RG_RTC_EOSC32_CK_PDN_MASK, PMIC_RG_RTC_EOSC32_CK_PDN_SHIFT); switch (rtc_eosc_cali_td) { case 1: RTC_Config_Interface(PMIC_RG_EOSC_CALI_CON0, 0x3, PMIC_RG_EOSC_CALI_TD_MASK, PMIC_RG_EOSC_CALI_TD_SHIFT); break; case 2: RTC_Config_Interface(PMIC_RG_EOSC_CALI_CON0, 0x4, PMIC_RG_EOSC_CALI_TD_MASK, PMIC_RG_EOSC_CALI_TD_SHIFT); break; case 4: RTC_Config_Interface(PMIC_RG_EOSC_CALI_CON0, 0x5, PMIC_RG_EOSC_CALI_TD_MASK, PMIC_RG_EOSC_CALI_TD_SHIFT); break; case 16: RTC_Config_Interface(PMIC_RG_EOSC_CALI_CON0, 0x7, PMIC_RG_EOSC_CALI_TD_MASK, PMIC_RG_EOSC_CALI_TD_SHIFT); break; default: RTC_Config_Interface(PMIC_RG_EOSC_CALI_CON0, 0x6, PMIC_RG_EOSC_CALI_TD_MASK, PMIC_RG_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 */ RTC_Config_Interface(PMIC_RG_DCXO_CW02, 0, PMIC_RG_XO_EN32K_MAN_MASK, PMIC_RG_XO_EN32K_MAN_SHIFT); RTC_Write(RTC_BBPU, RTC_Read(RTC_BBPU) | RTC_BBPU_KEY | RTC_BBPU_RELOAD); RTC_Write_Trigger(); /* Enable K EOSC mode for normal power off and then plug out battery */ 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); RTC_Write_Trigger(); osc32 = RTC_Read(RTC_OSC32CON); rtc_xosc_write(osc32 | RTC_EMBCK_SRC_SEL, true); INFO("[RTC] RTC_enable_k_eosc\n"); } void rtc_power_off_sequence(void) { uint16_t bbpu; rtc_disable_2sec_reboot(); rtc_enable_k_eosc(); /* clear alarm */ bbpu = RTC_BBPU_KEY | RTC_BBPU_CLR | RTC_BBPU_PWREN; if (Writeif_unlock()) { RTC_Write(RTC_BBPU, bbpu); RTC_Write(RTC_AL_MASK, RTC_AL_MASK_DOW); RTC_Write_Trigger(); mdelay(1); bbpu = RTC_Read(RTC_BBPU) | RTC_BBPU_KEY | RTC_BBPU_RELOAD; RTC_Write(RTC_BBPU, bbpu); RTC_Write_Trigger(); INFO("[RTC] BBPU=0x%x, IRQ_EN=0x%x, AL_MSK=0x%x, AL_SEC=0x%x\n", RTC_Read(RTC_BBPU), RTC_Read(RTC_IRQ_EN), RTC_Read(RTC_AL_MASK), RTC_Read(RTC_AL_SEC)); } }