You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
134 lines
3.4 KiB
134 lines
3.4 KiB
/*
|
|
* Copyright (c) 2019, 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 = 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));
|
|
}
|
|
}
|