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