1*6e5d76baSYuchen Huang /* 2*6e5d76baSYuchen Huang * Copyright (c) 2021, MediaTek Inc. All rights reserved. 3*6e5d76baSYuchen Huang * 4*6e5d76baSYuchen Huang * SPDX-License-Identifier: BSD-3-Clause 5*6e5d76baSYuchen Huang */ 6*6e5d76baSYuchen Huang 7*6e5d76baSYuchen Huang #include <common/debug.h> 8*6e5d76baSYuchen Huang #include <drivers/delay_timer.h> 9*6e5d76baSYuchen Huang #include <rtc.h> 10*6e5d76baSYuchen Huang 11*6e5d76baSYuchen Huang static void RTC_Config_Interface(uint32_t addr, uint16_t data, 12*6e5d76baSYuchen Huang uint16_t MASK, uint16_t SHIFT) 13*6e5d76baSYuchen Huang { 14*6e5d76baSYuchen Huang uint16_t pmic_reg = 0; 15*6e5d76baSYuchen Huang 16*6e5d76baSYuchen Huang pmic_reg = RTC_Read(addr); 17*6e5d76baSYuchen Huang 18*6e5d76baSYuchen Huang pmic_reg &= ~(MASK << SHIFT); 19*6e5d76baSYuchen Huang pmic_reg |= (data << SHIFT); 20*6e5d76baSYuchen Huang 21*6e5d76baSYuchen Huang RTC_Write(addr, pmic_reg); 22*6e5d76baSYuchen Huang } 23*6e5d76baSYuchen Huang 24*6e5d76baSYuchen Huang static void rtc_disable_2sec_reboot(void) 25*6e5d76baSYuchen Huang { 26*6e5d76baSYuchen Huang uint16_t reboot; 27*6e5d76baSYuchen Huang 28*6e5d76baSYuchen Huang reboot = (RTC_Read(RTC_AL_SEC) & ~RTC_BBPU_2SEC_EN) & 29*6e5d76baSYuchen Huang ~RTC_BBPU_AUTO_PDN_SEL; 30*6e5d76baSYuchen Huang RTC_Write(RTC_AL_SEC, reboot); 31*6e5d76baSYuchen Huang RTC_Write_Trigger(); 32*6e5d76baSYuchen Huang } 33*6e5d76baSYuchen Huang 34*6e5d76baSYuchen Huang static void rtc_xosc_write(uint16_t val, bool reload) 35*6e5d76baSYuchen Huang { 36*6e5d76baSYuchen Huang uint16_t bbpu; 37*6e5d76baSYuchen Huang 38*6e5d76baSYuchen Huang RTC_Write(RTC_OSC32CON, RTC_OSC32CON_UNLOCK1); 39*6e5d76baSYuchen Huang rtc_busy_wait(); 40*6e5d76baSYuchen Huang RTC_Write(RTC_OSC32CON, RTC_OSC32CON_UNLOCK2); 41*6e5d76baSYuchen Huang rtc_busy_wait(); 42*6e5d76baSYuchen Huang 43*6e5d76baSYuchen Huang RTC_Write(RTC_OSC32CON, val); 44*6e5d76baSYuchen Huang rtc_busy_wait(); 45*6e5d76baSYuchen Huang 46*6e5d76baSYuchen Huang if (reload) { 47*6e5d76baSYuchen Huang bbpu = RTC_Read(RTC_BBPU) | RTC_BBPU_KEY | RTC_BBPU_RELOAD; 48*6e5d76baSYuchen Huang RTC_Write(RTC_BBPU, bbpu); 49*6e5d76baSYuchen Huang RTC_Write_Trigger(); 50*6e5d76baSYuchen Huang } 51*6e5d76baSYuchen Huang } 52*6e5d76baSYuchen Huang 53*6e5d76baSYuchen Huang static void rtc_enable_k_eosc(void) 54*6e5d76baSYuchen Huang { 55*6e5d76baSYuchen Huang uint16_t osc32; 56*6e5d76baSYuchen Huang uint16_t rtc_eosc_cali_td = 8; /* eosc cali period time */ 57*6e5d76baSYuchen Huang 58*6e5d76baSYuchen Huang /* Truning on eosc cali mode clock */ 59*6e5d76baSYuchen Huang RTC_Config_Interface(PMIC_RG_TOP_CON, 1, 60*6e5d76baSYuchen Huang PMIC_RG_SRCLKEN_IN0_HW_MODE_MASK, 61*6e5d76baSYuchen Huang PMIC_RG_SRCLKEN_IN0_HW_MODE_SHIFT); 62*6e5d76baSYuchen Huang RTC_Config_Interface(PMIC_RG_TOP_CON, 1, 63*6e5d76baSYuchen Huang PMIC_RG_SRCLKEN_IN1_HW_MODE_MASK, 64*6e5d76baSYuchen Huang PMIC_RG_SRCLKEN_IN1_HW_MODE_SHIFT); 65*6e5d76baSYuchen Huang RTC_Config_Interface(PMIC_RG_SCK_TOP_CKPDN_CON0, 0, 66*6e5d76baSYuchen Huang PMIC_RG_RTC_EOSC32_CK_PDN_MASK, 67*6e5d76baSYuchen Huang PMIC_RG_RTC_EOSC32_CK_PDN_SHIFT); 68*6e5d76baSYuchen Huang 69*6e5d76baSYuchen Huang switch (rtc_eosc_cali_td) { 70*6e5d76baSYuchen Huang case 1: 71*6e5d76baSYuchen Huang RTC_Config_Interface(PMIC_RG_EOSC_CALI_CON0, 0x3, 72*6e5d76baSYuchen Huang PMIC_RG_EOSC_CALI_TD_MASK, PMIC_RG_EOSC_CALI_TD_SHIFT); 73*6e5d76baSYuchen Huang break; 74*6e5d76baSYuchen Huang case 2: 75*6e5d76baSYuchen Huang RTC_Config_Interface(PMIC_RG_EOSC_CALI_CON0, 0x4, 76*6e5d76baSYuchen Huang PMIC_RG_EOSC_CALI_TD_MASK, PMIC_RG_EOSC_CALI_TD_SHIFT); 77*6e5d76baSYuchen Huang break; 78*6e5d76baSYuchen Huang case 4: 79*6e5d76baSYuchen Huang RTC_Config_Interface(PMIC_RG_EOSC_CALI_CON0, 0x5, 80*6e5d76baSYuchen Huang PMIC_RG_EOSC_CALI_TD_MASK, PMIC_RG_EOSC_CALI_TD_SHIFT); 81*6e5d76baSYuchen Huang break; 82*6e5d76baSYuchen Huang case 16: 83*6e5d76baSYuchen Huang RTC_Config_Interface(PMIC_RG_EOSC_CALI_CON0, 0x7, 84*6e5d76baSYuchen Huang PMIC_RG_EOSC_CALI_TD_MASK, PMIC_RG_EOSC_CALI_TD_SHIFT); 85*6e5d76baSYuchen Huang break; 86*6e5d76baSYuchen Huang default: 87*6e5d76baSYuchen Huang RTC_Config_Interface(PMIC_RG_EOSC_CALI_CON0, 0x6, 88*6e5d76baSYuchen Huang PMIC_RG_EOSC_CALI_TD_MASK, PMIC_RG_EOSC_CALI_TD_SHIFT); 89*6e5d76baSYuchen Huang break; 90*6e5d76baSYuchen Huang } 91*6e5d76baSYuchen Huang /* Switch the DCXO from 32k-less mode to RTC mode, 92*6e5d76baSYuchen Huang * otherwise, EOSC cali will fail 93*6e5d76baSYuchen Huang */ 94*6e5d76baSYuchen Huang /* RTC mode will have only OFF mode and FPM */ 95*6e5d76baSYuchen Huang RTC_Config_Interface(PMIC_RG_DCXO_CW02, 0, PMIC_RG_XO_EN32K_MAN_MASK, 96*6e5d76baSYuchen Huang PMIC_RG_XO_EN32K_MAN_SHIFT); 97*6e5d76baSYuchen Huang RTC_Write(RTC_BBPU, 98*6e5d76baSYuchen Huang RTC_Read(RTC_BBPU) | RTC_BBPU_KEY | RTC_BBPU_RELOAD); 99*6e5d76baSYuchen Huang RTC_Write_Trigger(); 100*6e5d76baSYuchen Huang /* Enable K EOSC mode for normal power off and then plug out battery */ 101*6e5d76baSYuchen Huang RTC_Write(RTC_AL_YEA, ((RTC_Read(RTC_AL_YEA) | RTC_K_EOSC_RSV_0) 102*6e5d76baSYuchen Huang & (~RTC_K_EOSC_RSV_1)) | RTC_K_EOSC_RSV_2); 103*6e5d76baSYuchen Huang RTC_Write_Trigger(); 104*6e5d76baSYuchen Huang 105*6e5d76baSYuchen Huang osc32 = RTC_Read(RTC_OSC32CON); 106*6e5d76baSYuchen Huang rtc_xosc_write(osc32 | RTC_EMBCK_SRC_SEL, true); 107*6e5d76baSYuchen Huang INFO("[RTC] RTC_enable_k_eosc\n"); 108*6e5d76baSYuchen Huang } 109*6e5d76baSYuchen Huang 110*6e5d76baSYuchen Huang void rtc_power_off_sequence(void) 111*6e5d76baSYuchen Huang { 112*6e5d76baSYuchen Huang uint16_t bbpu; 113*6e5d76baSYuchen Huang 114*6e5d76baSYuchen Huang rtc_disable_2sec_reboot(); 115*6e5d76baSYuchen Huang rtc_enable_k_eosc(); 116*6e5d76baSYuchen Huang 117*6e5d76baSYuchen Huang /* clear alarm */ 118*6e5d76baSYuchen Huang bbpu = RTC_BBPU_KEY | RTC_BBPU_CLR | RTC_BBPU_PWREN; 119*6e5d76baSYuchen Huang if (Writeif_unlock()) { 120*6e5d76baSYuchen Huang RTC_Write(RTC_BBPU, bbpu); 121*6e5d76baSYuchen Huang 122*6e5d76baSYuchen Huang RTC_Write(RTC_AL_MASK, RTC_AL_MASK_DOW); 123*6e5d76baSYuchen Huang RTC_Write_Trigger(); 124*6e5d76baSYuchen Huang mdelay(1); 125*6e5d76baSYuchen Huang 126*6e5d76baSYuchen Huang bbpu = RTC_Read(RTC_BBPU) | RTC_BBPU_KEY | RTC_BBPU_RELOAD; 127*6e5d76baSYuchen Huang RTC_Write(RTC_BBPU, bbpu); 128*6e5d76baSYuchen Huang RTC_Write_Trigger(); 129*6e5d76baSYuchen Huang INFO("[RTC] BBPU=0x%x, IRQ_EN=0x%x, AL_MSK=0x%x, AL_SEC=0x%x\n", 130*6e5d76baSYuchen Huang RTC_Read(RTC_BBPU), RTC_Read(RTC_IRQ_EN), 131*6e5d76baSYuchen Huang RTC_Read(RTC_AL_MASK), RTC_Read(RTC_AL_SEC)); 132*6e5d76baSYuchen Huang } 133*6e5d76baSYuchen Huang } 134