• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <cpu/inc/barrier.h>
18 #include <cpu/inc/cpuMath.h>
19 #include <plat/inc/rtc.h>
20 #include <plat/inc/pwr.h>
21 #include <inc/timer.h>
22 #include <inc/platform.h>
23 #include <plat/inc/exti.h>
24 #include <plat/inc/cmsis.h>
25 #include <variant/inc/variant.h>
26 
27 #ifndef NS_PER_S
28 #define NS_PER_S                    1000000000ULL
29 #endif
30 
31 
32 struct StmRtc
33 {
34     volatile uint32_t TR;       /* 0x00 */
35     volatile uint32_t DR;       /* 0x04 */
36     volatile uint32_t CR;       /* 0x08 */
37     volatile uint32_t ISR;      /* 0x0C */
38     volatile uint32_t PRER;     /* 0x10 */
39     volatile uint32_t WUTR;     /* 0x14 */
40     volatile uint32_t CALIBR;   /* 0x18 */
41     volatile uint32_t ALRMAR;   /* 0x1C */
42     volatile uint32_t ALRMBR;   /* 0x20 */
43     volatile uint32_t WPR;      /* 0x24 */
44     volatile uint32_t SSR;      /* 0x28 */
45     volatile uint32_t SHIFTR;   /* 0x2C */
46     volatile uint32_t TSTR;     /* 0x30 */
47     volatile uint32_t TSDR;     /* 0x34 */
48     volatile uint32_t TSSSR;    /* 0x38 */
49     volatile uint32_t CALR;     /* 0x3C */
50     volatile uint32_t TAFCR;    /* 0x40 */
51     volatile uint32_t ALRMASSR; /* 0x44 */
52     volatile uint32_t ALRMBSSR; /* 0x48 */
53     uint8_t unused0[4];         /* 0x4C */
54     volatile uint32_t BKPR[20]; /* 0x50 - 0x9C */
55 };
56 
57 #define RTC ((struct StmRtc*)RTC_BASE)
58 
59 /* RTC bit defintions */
60 #define RTC_CR_WUCKSEL_MASK         0x00000007UL
61 #define RTC_CR_WUCKSEL_16DIV        0x00000000UL
62 #define RTC_CR_WUCKSEL_8DIV         0x00000001UL
63 #define RTC_CR_WUCKSEL_4DIV         0x00000002UL
64 #define RTC_CR_WUCKSEL_2DIV         0x00000003UL
65 #define RTC_CR_WUCKSEL_CK_SPRE      0x00000004UL
66 #define RTC_CR_WUCKSEL_CK_SPRE_2    0x00000006UL
67 #define RTC_CR_BYPSHAD              0x00000020UL
68 #define RTC_CR_FMT                  0x00000040UL
69 #define RTC_CR_ALRAE                0x00000100UL
70 #define RTC_CR_WUTE                 0x00000400UL
71 #define RTC_CR_ALRAIE               0x00001000UL
72 #define RTC_CR_WUTIE                0x00004000UL
73 
74 #define RTC_ISR_ALRAWF              0x00000001UL
75 #define RTC_ISR_WUTWF               0x00000004UL
76 #define RTC_ISR_RSF                 0x00000020UL
77 #define RTC_ISR_INITF               0x00000040UL
78 #define RTC_ISR_INIT                0x00000080UL
79 #define RTC_ISR_WUTF                0x00000400UL
80 
81 /* RTC internal values */
82 #define RTC_FREQ_HZ                 32768UL
83 #define RTC_WKUP_DOWNCOUNT_MAX      0x10000UL
84 
85 /* TODO: Reset to crystal PPM once known */
86 #define RTC_PPM                     50UL
87 
88 /* Default prescalars of P[async] = 127 and P[sync] = 255 are appropriate
89  * produce a 1 Hz clock when using a 32.768kHZ clock source */
90 #ifndef RTC_PREDIV_A
91 #define RTC_PREDIV_A                31UL
92 #endif
93 #ifndef RTC_PREDIV_S
94 #define RTC_PREDIV_S                1023UL
95 #endif
96 #ifndef RTC_CALM
97 #define RTC_CALM                    0
98 #endif
99 #ifndef RTC_CALP
100 #define RTC_CALP                    0
101 #endif
102 
103 /* Jitter = max wakeup timer resolution (61.035 us)
104  * + 2 RTC cycles for synchronization (61.035 us) */
105 #define RTC_PERIOD_NS               30517UL
106 #define RTC_CK_APRE_HZ              256UL
107 #define RTC_CK_APRE_PERIOD_NS       3906250UL
108 #define RTC_DIV2_PERIOD_NS          61035UL
109 #define RTC_DIV4_PERIOD_NS          122070UL
110 #define RTC_DIV8_PERIOD_NS          244141UL
111 #define RTC_DIV16_PERIOD_NS         488281UL
112 /* TODO: Measure the jitter in the overhead of setting the wakeup timers.
113  * Initially setting to 1 RTC clock cycle. */
114 #define RTC_WUT_NOISE_NS            30517UL
115 #define RTC_ALARM_NOISE_NS          30517UL
116 
rtcSetDefaultDateTimeAndPrescalar(void)117 static void rtcSetDefaultDateTimeAndPrescalar(void)
118 {
119     /* Enable writability of RTC registers */
120     RTC->WPR = 0xCA;
121     RTC->WPR = 0x53;
122 
123     /* Enter RTC init mode */
124     RTC->ISR |= RTC_ISR_INIT;
125 
126     mem_reorder_barrier();
127     /* Wait for initialization mode to be entered. */
128     while ((RTC->ISR & RTC_ISR_INITF) == 0);
129 
130     /* Set prescalar rtc register.  Two writes required. */
131     RTC->PRER = RTC_PREDIV_S;
132     RTC->PRER |= (RTC_PREDIV_A << 16);
133     RTC->CALR = (RTC_CALP << 15) | (RTC_CALM & 0x1FF);
134 
135     /* 24 hour format */
136     RTC->CR &= ~RTC_CR_FMT;
137 
138     /* disable shadow registers */
139     RTC->CR |= RTC_CR_BYPSHAD;
140 
141     /* Set time and date registers to defaults */
142     /* Midnight */
143     RTC->TR = 0x0;
144     RTC->SSR = 0x0;
145     /* Sat Jan 1st, 2000 BCD */
146     RTC->DR = 0b1100000100000001;
147 
148     /* Exit init mode for RTC */
149     RTC->ISR &= ~RTC_ISR_INIT;
150 
151     /* Re-enable register write protection.  RTC counting doesn't start for
152      * 4 RTC cycles after set - must poll RSF before read DR or TR */
153     RTC->WPR = 0xFF;
154 
155     extiEnableIntLine(EXTI_LINE_RTC_WKUP, EXTI_TRIGGER_RISING);
156     NVIC_EnableIRQ(RTC_WKUP_IRQn);
157 }
158 
rtcInit(void)159 void rtcInit(void)
160 {
161     pwrEnableAndClockRtc(RTC_CLK);
162     rtcSetDefaultDateTimeAndPrescalar();
163 }
164 
165 /* Set calendar alarm to go off after delay has expired. uint64_t delay must
166  * be in valid uint64_t format */
rtcSetWakeupTimer(uint64_t delay)167 int rtcSetWakeupTimer(uint64_t delay)
168 {
169     uint64_t intState;
170     uint64_t periodNsRecip;
171     uint32_t wakeupClock;
172     uint32_t periodNs;
173 
174     /* Minimum wakeup interrupt period is 122 us */
175     if (delay < (RTC_DIV2_PERIOD_NS * 2)) {
176         return RTC_ERR_TOO_SMALL;
177     }
178 
179     /* Get appropriate clock period for delay size.  Wakeup clock = RTC/x. */
180     if (delay < (RTC_DIV2_PERIOD_NS * RTC_WKUP_DOWNCOUNT_MAX)) {
181 
182         wakeupClock = RTC_CR_WUCKSEL_2DIV;
183         periodNs = RTC_DIV2_PERIOD_NS;
184         periodNsRecip = U64_RECIPROCAL_CALCULATE(RTC_DIV2_PERIOD_NS);
185     }
186     else if (delay < ((unsigned long long)RTC_DIV4_PERIOD_NS * RTC_WKUP_DOWNCOUNT_MAX)) {
187 
188         wakeupClock = RTC_CR_WUCKSEL_4DIV;
189         periodNs = RTC_DIV4_PERIOD_NS;
190         periodNsRecip = U64_RECIPROCAL_CALCULATE(RTC_DIV4_PERIOD_NS);
191     }
192     else if (delay < ((unsigned long long)RTC_DIV8_PERIOD_NS * RTC_WKUP_DOWNCOUNT_MAX)) {
193 
194         wakeupClock = RTC_CR_WUCKSEL_8DIV;
195         periodNs = RTC_DIV8_PERIOD_NS;
196         periodNsRecip = U64_RECIPROCAL_CALCULATE(RTC_DIV8_PERIOD_NS);
197     }
198     else if (delay < ((unsigned long long)RTC_DIV16_PERIOD_NS * RTC_WKUP_DOWNCOUNT_MAX)) {
199 
200         wakeupClock = RTC_CR_WUCKSEL_16DIV;
201         periodNs = RTC_DIV16_PERIOD_NS;
202         periodNsRecip = U64_RECIPROCAL_CALCULATE(RTC_DIV16_PERIOD_NS);
203     }
204     else if (delay < ((unsigned long long)NS_PER_S * RTC_WKUP_DOWNCOUNT_MAX)) {
205 
206         wakeupClock = RTC_CR_WUCKSEL_CK_SPRE;
207         periodNs = NS_PER_S;
208         periodNsRecip = U64_RECIPROCAL_CALCULATE(NS_PER_S);
209     }
210     else if (delay < ((unsigned long long)NS_PER_S * 2 * RTC_WKUP_DOWNCOUNT_MAX)) {
211 
212         wakeupClock = RTC_CR_WUCKSEL_CK_SPRE_2;
213         periodNs = NS_PER_S;
214         periodNsRecip = U64_RECIPROCAL_CALCULATE(NS_PER_S);
215     }
216     else {
217 
218         osLog(LOG_ERROR, "RTC delay impossible");
219         return RTC_ERR_INTERNAL;
220     }
221 
222     intState = cpuIntsOff();
223 
224     /* Enable RTC register write */
225     RTC->WPR = 0xCA;
226     RTC->WPR = 0x53;
227 
228     /* Disable wakeup timer */
229     RTC->CR &= ~RTC_CR_WUTE;
230 
231     /* Wait for access enabled for wakeup timer registers */
232     while ((RTC->ISR & RTC_ISR_WUTWF) == 0);
233 
234     /* Clear wakeup clock source */
235     RTC->CR &= ~RTC_CR_WUCKSEL_MASK;
236 
237     RTC->CR |= wakeupClock;
238     /* Downcounter value for wakeup clock.  Wakeup flag is set every
239      * RTC->WUTR[15:0] + 1 cycles of the WUT clock. */
240     RTC->WUTR = cpuMathRecipAssistedUdiv64by32(delay, periodNs, periodNsRecip) - 1;
241 
242     /* Enable wakeup interrupts */
243     RTC->CR |= RTC_CR_WUTIE;
244     extiClearPendingLine(EXTI_LINE_RTC_WKUP);
245 
246     /* Enable wakeup timer */
247     RTC->CR |= RTC_CR_WUTE;
248 
249     /* Clear overflow flag */
250     RTC->ISR &= ~RTC_ISR_WUTF;
251 
252     /* Write-protect RTC registers */
253     RTC->WPR = 0xFF;
254 
255     cpuIntsRestore(intState);
256 
257     return 0;
258 }
259 
rtcGetTime(void)260 uint64_t rtcGetTime(void)
261 {
262     int32_t time_s;
263     uint32_t dr, tr, ssr;
264     // cumulative adjustments from 32 day months (year 2000)
265     //   31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
266     //    1,  3,  1,  2,  1,  2,  1,  1,  2,  1,  2,  1
267     //  0   1,  4,  5,  7,  8, 10, 11, 12, 14, 15, 17
268     static const uint8_t adjust[] = { 0, 1, 4, 5, 7, 8, 10, 11, 12, 14, 15, 17 };
269     uint8_t month;
270 
271     // need to loop incase an interrupt occurs in the middle or ssr
272     // decrements (which can propagate changes to tr and dr)
273     do {
274         ssr = RTC->SSR;
275         tr = RTC->TR;
276         dr = RTC->DR;
277     } while (ssr != RTC->SSR);
278 
279     month = (((dr >> 12) & 0x1) * 10) + ((dr >> 8) & 0xf) - 1;
280     time_s = (((((dr >> 4) & 0x3) * 10) + (dr & 0xF) - 1) + (month << 5) - adjust[month]) * 86400ULL;
281     time_s += ((((tr >> 22) & 0x1) * 43200ULL) +
282              (((tr >> 20) & 0x3) * 36000ULL) +
283              (((tr >> 16) & 0xF) * 3600ULL) +
284              (((tr >> 12) & 0x7) * 600ULL) +
285              (((tr >> 8) & 0xF) * 60ULL) +
286              (((tr >> 4) & 0x7) * 10ULL) +
287              (((tr) & 0xF)));
288 
289     return (time_s * NS_PER_S) + U64_DIV_BY_CONST_U16(((RTC_PREDIV_S - ssr) * NS_PER_S), (RTC_PREDIV_S + 1));
290 }
291 
292 void EXTI22_RTC_WKUP_IRQHandler(void);
EXTI22_RTC_WKUP_IRQHandler(void)293 void EXTI22_RTC_WKUP_IRQHandler(void)
294 {
295     extiClearPendingLine(EXTI_LINE_RTC_WKUP);
296     timIntHandler();
297 }
298 
rtcGetBackupStorage(void)299 uint32_t* rtcGetBackupStorage(void)
300 {
301     return (uint32_t*)RTC->BKPR;
302 }
303