1 /**
2   ******************************************************************************
3   * @file    ald_rtchw.c
4   * @brief   RTCHW module driver.
5   *          This file provides firmware functions to manage the following
6   *          functionalities of the RTC peripheral:
7   *           + Calibration functions
8   * @version V1.0
9   * @date    25 Apr 2019
10   * @author  AE Team
11   * @note
12   *          Change Logs:
13   *          Date            Author          Notes
14   *          25 Apr 2019     AE Team         The first version
15   *
16   * Copyright (C) Shanghai Eastsoft Microelectronics Co. Ltd. All rights reserved.
17   *
18   * SPDX-License-Identifier: Apache-2.0
19   *
20   * Licensed under the Apache License, Version 2.0 (the License); you may
21   * not use this file except in compliance with the License.
22   * You may obtain a copy of the License at
23   *
24   * www.apache.org/licenses/LICENSE-2.0
25   *
26   * Unless required by applicable law or agreed to in writing, software
27   * distributed under the License is distributed on an AS IS BASIS, WITHOUT
28   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
29   * See the License for the specific language governing permissions and
30   * limitations under the License.
31   **********************************************************************************
32   */
33 
34 #include "ald_conf.h"
35 
36 /** @addtogroup ES32FXXX_ALD
37   * @{
38   */
39 
40 /** @defgroup RTCHW RTCHW
41   * @brief RTCHW module driver
42   * @{
43   */
44 #ifdef ALD_RTC
45 
46 /** @addtogroup RTCHW_Private_Functions  RTCHW Private Functions
47   * @{
48   */
49 /**
50   * @brief  delay losc clock
51   * @param  u: clock numbers.
52   * @retval None.
53   */
delay_losc_clk(uint16_t u)54 static void delay_losc_clk(uint16_t u)
55 {
56 	uint16_t i, j;
57 
58 	for (i = 0; i < u; i++) {
59                 for (j = 0; j < 60; j++) {
60                         __ASM volatile ("nop");
61                 }
62 	}
63 }
64 
65 /**
66   * @brief  Check parameter for calibation
67   * @param  config: pointer to rtc_hw_cali_offset_t structure.
68   * @param  mode: Running mode, see @ref rtc_hw_cali_mode_t.
69   * @retval Status.
70   */
rtc_hw_auto_check(rtc_hw_cali_offset_t * config,rtc_hw_cali_mode_t mode)71 static uint8_t rtc_hw_auto_check(rtc_hw_cali_offset_t *config, rtc_hw_cali_mode_t mode)
72 {
73 	uint8_t tom = READ_BITS(TSENSE->CR, TSENSE_CR_TOM_MSK, TSENSE_CR_TOM_POSS);
74 	uint8_t shift[8] = {0, 2, 4, 6, 8, 8, 8, 8};
75 
76 	if (mode == RTC_CALI_MODE_NORMAL) {
77 		if ((RTC->CALCON & 0x1F3000F) != (RTCINFO->RTC_CALCR & 0x1F3000F))
78 			return 1;
79 	}
80 	else {
81 		if ((RTC->CALCON & 0x183000F) != (RTCINFO->RTC_CALCR & 0x183000F))
82 			return 1;
83 
84 		if (READ_BITS(RTC->CALCON, RTC_CALCON_TCP_MSK, RTC_CALCON_TCP_POSS) != 7)	/* when sleep mode */
85 			return 1;
86 	}
87 
88 	if ((TSENSE->CR & 0x7702) != (RTCINFO->TEMP_CR & 0x7702))
89 		return 1;
90 	if (RTC->TEMPBDR != RTCINFO->RTC_TEMPBDR + config->offset_rtc_bdr)
91 		return 1;
92 	if (RTC->LTAXR != RTCINFO->RTC_LTAXR + config->offset_ltaxr)
93 		return 1;
94 	if (RTC->HTAXR != RTCINFO->RTC_HTAXR + config->offset_htaxr)
95 		return 1;
96 	if (RTC->HTAXR != RTCINFO->RTC_HTCAR + config->offset_htcar)
97 		return 1;
98 	if (RTC->HTCBR != RTCINFO->RTC_HTCBR + config->offset_htcbr)
99 		return 1;
100 	if (RTC->HTCCR != RTCINFO->RTC_HTCCR + config->offset_htccr)
101 		return 1;
102 	if (RTC->HTCDR != RTCINFO->RTC_HTCDR + config->offset_htcdr)
103 		return 1;
104 	if (RTC->HTCER != RTCINFO->RTC_HTCER + config->offset_htcer)
105 		return 1;
106 	if (RTC->LTAXR != RTCINFO->RTC_LTCAR + config->offset_ltcar)
107 		return 1;
108 	if (RTC->LTCBR != RTCINFO->RTC_LTCBR + config->offset_ltcbr)
109 		return 1;
110 	if (RTC->LTCCR != RTCINFO->RTC_LTCCR + config->offset_ltccr)
111 		return 1;
112 	if (RTC->LTCDR != RTCINFO->RTC_LTCDR + config->offset_ltcdr)
113 		return 1;
114 	if (RTC->LTCER != RTCINFO->RTC_LTCER + config->offset_ltcer)
115 		return 1;
116 	if (TSENSE->TBDR != (RTCINFO->TEMP_TBDR & 0xFFFF) + config->offset_temp_bdr)
117 		return 1;
118 	if (TSENSE->LTGR != RTCINFO->TEMP_LTGR + config->offset_ltgr)
119 		return 1;
120 	if (TSENSE->HTGR != RTCINFO->TEMP_HTGR + config->offset_htgr)
121 		return 1;
122 	if (TSENSE->TCALBDR != (((RTCINFO->TEMP_TCALBDR & 0x1FFFFFF) >> shift[tom]) & 0x1FFFF)
123 				 + config->offset_tcalbdr)
124 		return 1;
125 
126 	return 0;
127 }
128 /**
129   * @}
130   */
131 
132 /** @defgroup RTCHW_Public_Functions RTCHW Public Functions
133   * @{
134   */
135 /**
136   * @brief  Hardware automatic calibate
137   * @param  config: pointer to rtc_hw_cali_offset_t structure.
138   * @param  mode: Running mode, see @ref rtc_hw_cali_mode_t
139   * @retval None
140   */
ald_rtc_hw_auto_cali(rtc_hw_cali_offset_t * config,rtc_hw_cali_mode_t mode)141 void ald_rtc_hw_auto_cali(rtc_hw_cali_offset_t *config, rtc_hw_cali_mode_t mode)
142 {
143 	uint8_t shift[8] = {0, 2, 4, 6, 8, 8, 8, 8};
144 	uint8_t tmp;
145 	uint32_t v = 0;
146 	uint16_t temp_calf;
147 
148 	if (!(rtc_hw_auto_check(config, mode)))
149 		return;
150 
151 	RTC_UNLOCK();
152 	RTC_CALI_UNLOCK();
153 	TSENSE_UNLOCK();
154 
155 	temp_calf = (uint16_t)RTC->CALDR;
156 	while ((READ_BITS(RTC->IFR, RTC_IFR_TCCF_MSK, RTC_IFR_TCCF_POS) == 1) && (v < 0x20000))		/* no usr trig */
157 		v++;
158 
159 	MODIFY_REG(RTC->CALCON, RTC_CALCON_TCM_MSK, 0 << RTC_CALCON_TCM_POSS);		/* disable auto compensation */
160 	MODIFY_REG(TSENSE->CR, TSENSE_CR_REQEN_MSK, 0 << TSENSE_CR_REQEN_POS);		/* disable temp */
161 
162 	RTC->CALDR = temp_calf;
163 	delay_losc_clk(3);
164 
165 	if (mode == RTC_CALI_MODE_NORMAL) {
166 		v           = RTC->CALCON & ~0x01F0000F;
167 		RTC->CALCON = v | (RTCINFO->RTC_CALCR & 0x01F0000F);
168 	}
169 	else {
170 		v           = RTC->CALCON & ~0x0180000F;
171 		RTC->CALCON = v | (RTCINFO->RTC_CALCR & 0x0180000F);
172 		MODIFY_REG(RTC->CALCON, RTC_CALCON_TCP_MSK, 7 << RTC_CALCON_TCP_POSS);        // when sleep mode, caluate once in 1h
173 	}
174 
175 	RTC->TEMPBDR  = RTCINFO->RTC_TEMPBDR + config->offset_rtc_bdr;
176 	RTC->LTAXR    = RTCINFO->RTC_LTAXR + config->offset_ltaxr;
177 	RTC->HTAXR    = RTCINFO->RTC_HTAXR + config->offset_htaxr;
178 	RTC->LTCAR    = RTCINFO->RTC_LTCAR + config->offset_ltcar;
179 	RTC->LTCBR    = RTCINFO->RTC_LTCBR + config->offset_ltcbr;
180 	RTC->LTCCR    = RTCINFO->RTC_LTCCR + config->offset_ltccr;
181 	RTC->LTCDR    = RTCINFO->RTC_LTCDR + config->offset_ltcdr;
182 	RTC->LTCER    = RTCINFO->RTC_LTCER + config->offset_ltcer;
183 	RTC->HTCAR    = RTCINFO->RTC_HTCAR + config->offset_htcar;
184 	RTC->HTCBR    = RTCINFO->RTC_HTCBR + config->offset_htcbr;
185 	RTC->HTCCR    = RTCINFO->RTC_HTCCR + config->offset_htccr;
186 	RTC->HTCDR    = RTCINFO->RTC_HTCDR + config->offset_htcdr;
187 	RTC->HTCER    = RTCINFO->RTC_HTCER + config->offset_htcer;
188 	MODIFY_REG(RTC->CON, RTC_CON_CKOS_MSK, 5 << RTC_CON_CKOS_POSS);		/* output accuracy 1Hz */
189 
190 	v               = TSENSE->CR & ~0x00007700;
191 	TSENSE->CR      = v | (RTCINFO->TEMP_CR & 0x00007700);
192 	TSENSE->HTGR    = RTCINFO->TEMP_HTGR + config->offset_htgr;
193 	TSENSE->LTGR    = RTCINFO->TEMP_LTGR + config->offset_ltgr;
194 	tmp             = READ_BITS(RTCINFO->TEMP_CR, TSENSE_CR_TOM_MSK, TSENSE_CR_TOM_POSS);
195 	TSENSE->TCALBDR = ((RTCINFO->TEMP_TCALBDR & 0x1FFFFFF) >> shift[tmp]) + config->offset_tcalbdr;
196 	TSENSE->TBDR    = RTCINFO->TEMP_TBDR + config->offset_temp_bdr;
197 
198 	delay_losc_clk(3);
199 	tmp = READ_BITS(RTCINFO->TEMP_CR, TSENSE_CR_REQEN_MSK, TSENSE_CR_REQEN_POS);
200 	MODIFY_REG(TSENSE->CR, TSENSE_CR_REQEN_MSK, tmp << TSENSE_CR_REQEN_POS);
201 	MODIFY_REG(RTC->CALCON, RTC_CALCON_TCM_MSK, 3 << RTC_CALCON_TCM_POSS);	/* usr trig */
202 
203 	delay_losc_clk(3);
204 	MODIFY_REG(RTC->TEMPR, RTC_TEMPR_VAL_MSK, 1 << RTC_TEMPR_VAL_POSS);	/* trig immediate*/
205 
206 	delay_losc_clk(3);
207 	tmp           = READ_BITS(RTCINFO->RTC_CALCR, RTC_CALCON_TCM_MSK, RTC_CALCON_TCM_POSS);
208 	MODIFY_REG(RTC->CALCON, RTC_CALCON_TCM_MSK, tmp << RTC_CALCON_TCM_POSS);
209 
210 	RTC_CALI_LOCK();
211 	RTC_LOCK();
212 	TSENSE_LOCK();
213 	return;
214 }
215 /**
216   * @}
217   */
218 #endif /* ALD_RTC */
219 /**
220   * @}
221   */
222 /**
223   * @}
224   */
225