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
RTC_Config_Interface(uint32_t addr,uint16_t data,uint16_t MASK,uint16_t SHIFT)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
rtc_disable_2sec_reboot(void)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
rtc_xosc_write(uint16_t val,bool reload)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
rtc_enable_k_eosc(void)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
rtc_power_off_sequence(void)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