Yuchen Huang | ad04044 | 2021-11-12 16:56:33 +0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2021, 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | |
| 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 | } |