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/barrier.h> 18 #include <cpu/cpuMath.h> 19 #include <plat/rtc.h> 20 #include <plat/pwr.h> 21 #include <timer.h> 22 #include <platform.h> 23 #include <plat/exti.h> 24 #include <plat/cmsis.h> 25 #include <variant/variant.h> 26 27 #ifndef NS_PER_S 28 #define NS_PER_S UINT64_C(1000000000) 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_DIV2_PERIOD_NS UINT64_C(61035) 106 #define RTC_DIV4_PERIOD_NS UINT64_C(122070) 107 #define RTC_DIV8_PERIOD_NS UINT64_C(244141) 108 #define RTC_DIV16_PERIOD_NS UINT64_C(488281) 109 110 #define RTC_VALID_DELAY_FOR_PERIOD(delay, period) \ 111 (delay < (period * (RTC_WKUP_DOWNCOUNT_MAX + 1))) 112 113 static void rtcSetDefaultDateTimeAndPrescalar(void) 114 { 115 /* Enable writability of RTC registers */ 116 RTC->WPR = 0xCA; 117 RTC->WPR = 0x53; 118 119 /* Enter RTC init mode */ 120 RTC->ISR |= RTC_ISR_INIT; 121 122 mem_reorder_barrier(); 123 /* Wait for initialization mode to be entered. */ 124 while ((RTC->ISR & RTC_ISR_INITF) == 0); 125 126 /* Set prescalar rtc register. Two writes required. */ 127 RTC->PRER = RTC_PREDIV_S; 128 RTC->PRER |= (RTC_PREDIV_A << 16); 129 RTC->CALR = (RTC_CALP << 15) | (RTC_CALM & 0x1FF); 130 131 /* 24 hour format */ 132 RTC->CR &= ~RTC_CR_FMT; 133 134 /* disable shadow registers */ 135 RTC->CR |= RTC_CR_BYPSHAD; 136 137 /* Set time and date registers to defaults */ 138 /* Midnight */ 139 RTC->TR = 0x0; 140 RTC->SSR = 0x0; 141 /* Sat Jan 1st, 2000 BCD */ 142 RTC->DR = 0b1100000100000001; 143 144 /* Exit init mode for RTC */ 145 RTC->ISR &= ~RTC_ISR_INIT; 146 147 /* Re-enable register write protection. RTC counting doesn't start for 148 * 4 RTC cycles after set - must poll RSF before read DR or TR */ 149 RTC->WPR = 0xFF; 150 151 extiEnableIntLine(EXTI_LINE_RTC_WKUP, EXTI_TRIGGER_RISING); 152 NVIC_EnableIRQ(RTC_WKUP_IRQn); 153 } 154 155 void rtcInit(void) 156 { 157 pwrEnableAndClockRtc(RTC_CLK); 158 rtcSetDefaultDateTimeAndPrescalar(); 159 } 160 161 /* Set calendar alarm to go off after delay has expired. uint64_t delay must 162 * be in valid uint64_t format */ 163 int rtcSetWakeupTimer(uint64_t delay) 164 { 165 uint64_t intState; 166 uint64_t periodNsRecip; 167 uint32_t wakeupClock; 168 uint32_t periodNs; 169 170 /* Minimum wakeup interrupt period is 122 us, max is 36.4 hours */ 171 if (delay < (RTC_DIV2_PERIOD_NS * 2)) { 172 return RTC_ERR_TOO_SMALL; 173 } else if (delay > (NS_PER_S * 2 * RTC_WKUP_DOWNCOUNT_MAX)) { 174 delay = NS_PER_S * 2 * RTC_WKUP_DOWNCOUNT_MAX; 175 } 176 177 /* Get appropriate clock period for delay size. Wakeup clock = RTC/x. */ 178 if (RTC_VALID_DELAY_FOR_PERIOD(delay, RTC_DIV2_PERIOD_NS)) { 179 180 wakeupClock = RTC_CR_WUCKSEL_2DIV; 181 periodNs = RTC_DIV2_PERIOD_NS; 182 periodNsRecip = U64_RECIPROCAL_CALCULATE(RTC_DIV2_PERIOD_NS); 183 } 184 else if (RTC_VALID_DELAY_FOR_PERIOD(delay, RTC_DIV4_PERIOD_NS)) { 185 186 wakeupClock = RTC_CR_WUCKSEL_4DIV; 187 periodNs = RTC_DIV4_PERIOD_NS; 188 periodNsRecip = U64_RECIPROCAL_CALCULATE(RTC_DIV4_PERIOD_NS); 189 } 190 else if (RTC_VALID_DELAY_FOR_PERIOD(delay, RTC_DIV8_PERIOD_NS)) { 191 192 wakeupClock = RTC_CR_WUCKSEL_8DIV; 193 periodNs = RTC_DIV8_PERIOD_NS; 194 periodNsRecip = U64_RECIPROCAL_CALCULATE(RTC_DIV8_PERIOD_NS); 195 } 196 else if (RTC_VALID_DELAY_FOR_PERIOD(delay, RTC_DIV16_PERIOD_NS)) { 197 198 wakeupClock = RTC_CR_WUCKSEL_16DIV; 199 periodNs = RTC_DIV16_PERIOD_NS; 200 periodNsRecip = U64_RECIPROCAL_CALCULATE(RTC_DIV16_PERIOD_NS); 201 } 202 else { 203 204 if (RTC_VALID_DELAY_FOR_PERIOD(delay, NS_PER_S)) 205 wakeupClock = RTC_CR_WUCKSEL_CK_SPRE; 206 else 207 wakeupClock = RTC_CR_WUCKSEL_CK_SPRE_2; 208 periodNs = NS_PER_S; 209 periodNsRecip = U64_RECIPROCAL_CALCULATE(NS_PER_S); 210 } 211 212 intState = cpuIntsOff(); 213 214 /* Enable RTC register write */ 215 RTC->WPR = 0xCA; 216 RTC->WPR = 0x53; 217 218 /* Disable wakeup timer */ 219 RTC->CR &= ~RTC_CR_WUTE; 220 221 /* Wait for access enabled for wakeup timer registers */ 222 while ((RTC->ISR & RTC_ISR_WUTWF) == 0); 223 224 /* Clear wakeup clock source */ 225 RTC->CR &= ~RTC_CR_WUCKSEL_MASK; 226 227 RTC->CR |= wakeupClock; 228 /* Downcounter value for wakeup clock. Wakeup flag is set every 229 * RTC->WUTR[15:0] + 1 cycles of the WUT clock. */ 230 RTC->WUTR = cpuMathRecipAssistedUdiv64by32(delay, periodNs, periodNsRecip) - 1; 231 232 /* Enable wakeup interrupts */ 233 RTC->CR |= RTC_CR_WUTIE; 234 extiClearPendingLine(EXTI_LINE_RTC_WKUP); 235 236 /* Enable wakeup timer */ 237 RTC->CR |= RTC_CR_WUTE; 238 239 /* Clear overflow flag */ 240 RTC->ISR &= ~RTC_ISR_WUTF; 241 242 /* Write-protect RTC registers */ 243 RTC->WPR = 0xFF; 244 245 cpuIntsRestore(intState); 246 247 return 0; 248 } 249 250 uint64_t rtcGetTime(void) 251 { 252 int32_t time_s; 253 uint32_t dr, tr, ssr; 254 // cumulative adjustments from 32 day months (year 2000) 255 // 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 256 // 1, 3, 1, 2, 1, 2, 1, 1, 2, 1, 2, 1 257 // 0 1, 4, 5, 7, 8, 10, 11, 12, 14, 15, 17 258 static const uint8_t adjust[] = { 0, 1, 4, 5, 7, 8, 10, 11, 12, 14, 15, 17 }; 259 uint8_t month; 260 261 // need to loop incase an interrupt occurs in the middle or ssr 262 // decrements (which can propagate changes to tr and dr) 263 do { 264 ssr = RTC->SSR; 265 tr = RTC->TR; 266 dr = RTC->DR; 267 } while (ssr != RTC->SSR); 268 269 month = (((dr >> 12) & 0x1) * 10) + ((dr >> 8) & 0xf) - 1; 270 time_s = (((((dr >> 4) & 0x3) * 10) + (dr & 0xF) - 1) + (month << 5) - adjust[month]) * 86400ULL; 271 time_s += ((((tr >> 22) & 0x1) * 43200ULL) + 272 (((tr >> 20) & 0x3) * 36000ULL) + 273 (((tr >> 16) & 0xF) * 3600ULL) + 274 (((tr >> 12) & 0x7) * 600ULL) + 275 (((tr >> 8) & 0xF) * 60ULL) + 276 (((tr >> 4) & 0x7) * 10ULL) + 277 (((tr) & 0xF))); 278 279 return (time_s * NS_PER_S) + U64_DIV_BY_CONST_U16(((RTC_PREDIV_S - ssr) * NS_PER_S), (RTC_PREDIV_S + 1)); 280 } 281 282 void EXTI22_RTC_WKUP_IRQHandler(void); 283 void EXTI22_RTC_WKUP_IRQHandler(void) 284 { 285 extiClearPendingLine(EXTI_LINE_RTC_WKUP); 286 timIntHandler(); 287 } 288 289 uint32_t* rtcGetBackupStorage(void) 290 { 291 return (uint32_t*)RTC->BKPR; 292 } 293