1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright 2022 Microchip 4 * 5 * Driver for AT91 RTC 6 */ 7 8 #include <assert.h> 9 #include <drivers/atmel_rtc.h> 10 #include <drivers/rtc.h> 11 #include <io.h> 12 #include <kernel/dt.h> 13 #include <kernel/dt_driver.h> 14 #include <matrix.h> 15 #include <mm/core_memprot.h> 16 #include <platform_config.h> 17 18 #define RTC_VAL(reg, val) (((val) >> RTC_## reg ## _SHIFT) & \ 19 RTC_## reg ##_MASK) 20 21 #define RTC_SET_VAL(reg, val) SHIFT_U32((val) & RTC_## reg ##_MASK, \ 22 RTC_## reg ## _SHIFT) 23 24 #define RTC_CR 0x0 25 #define RTC_CR_UPDCAL BIT(1) 26 #define RTC_CR_UPDTIM BIT(0) 27 28 #define RTC_MR 0x4 29 #define RTC_MR_HR_MODE BIT(0) 30 #define RTC_MR_PERSIAN BIT(1) 31 #define RTC_MR_UTC BIT(2) 32 #define RTC_MR_NEGPPM BIT(4) 33 #define RTC_MR_CORR_SHIFT 8 34 #define RTC_MR_CORR_MASK GENMASK_32(6, 0) 35 #define RTC_MR_CORR(val) RTC_VAL(val, MR_CORR) 36 #define RTC_MR_HIGHPPM BIT(15) 37 38 #define RTC_TIMR 0x8 39 #define RTC_CALR 0xC 40 41 #define RTC_SR 0x18 42 #define RTC_SR_ACKUPD BIT(0) 43 #define RTC_SR_SEC BIT(2) 44 45 #define RTC_SCCR 0x1C 46 #define RTC_SCCR_ACKCLR BIT(0) 47 #define RTC_SCCR_SECCLR BIT(2) 48 49 #define RTC_VER 0x2C 50 #define RTC_VER_NVTIM BIT(0) 51 #define RTC_VER_NVCAL BIT(1) 52 53 #define RTC_TSTR0 0xB0 54 #define RTC_TSDR0 0xB4 55 56 #define RTC_TSSR0 0xB8 57 #define RTC_TSSR_DET_OFFSET 16 58 #define RTC_TSSR_DET_COUNT 8 59 #define RTC_TSSR_TST_PIN BIT(2) 60 #define RTC_TSSR_JTAG BIT(3) 61 62 /* Layout of Time registers */ 63 #define RTC_TIME_BACKUP BIT(31) 64 #define RTC_TIME_HOUR_SHIFT 16 65 #define RTC_TIME_HOUR_MASK GENMASK_32(5, 0) 66 #define RTC_TIME_MIN_SHIFT 8 67 #define RTC_TIME_MIN_MASK GENMASK_32(6, 0) 68 #define RTC_TIME_SEC_SHIFT 0 69 #define RTC_TIME_SEC_MASK GENMASK_32(6, 0) 70 71 /* Layout of Calendar registers */ 72 #define RTC_CAL_DATE_SHIFT 24 73 #define RTC_CAL_DATE_MASK GENMASK_32(5, 0) 74 #define RTC_CAL_DAY_SHIFT 21 75 #define RTC_CAL_DAY_MASK GENMASK_32(2, 0) 76 #define RTC_CAL_MONTH_SHIFT 16 77 #define RTC_CAL_MONTH_MASK GENMASK_32(4, 0) 78 #define RTC_CAL_YEAR_SHIFT 8 79 #define RTC_CAL_YEAR_MASK GENMASK_32(7, 0) 80 #define RTC_CAL_CENT_SHIFT 0 81 #define RTC_CAL_CENT_MASK GENMASK_32(6, 0) 82 83 #define ATMEL_RTC_CORR_DIVIDEND 3906000 84 #define ATMEL_RTC_CORR_LOW_RATIO 20 85 86 static vaddr_t rtc_base; 87 88 static uint8_t bcd_decode(uint8_t dcb_val) 89 { 90 return (dcb_val & 0xF) + (dcb_val >> 4) * 10; 91 } 92 93 static uint8_t bcd_encode(uint32_t value) 94 { 95 return ((value / 10) << 4) + value % 10; 96 } 97 98 static uint32_t atmel_rtc_read(unsigned int offset) 99 { 100 return io_read32(rtc_base + offset); 101 } 102 103 static void atmel_rtc_write(unsigned int offset, uint32_t val) 104 { 105 return io_write32(rtc_base + offset, val); 106 } 107 108 static void atmel_decode_date(unsigned int time_reg, unsigned int cal_reg, 109 struct optee_rtc_time *tm) 110 { 111 uint32_t time = 0; 112 uint32_t date = 0; 113 114 /* Must read twice in case it changes */ 115 do { 116 time = atmel_rtc_read(time_reg); 117 date = atmel_rtc_read(cal_reg); 118 } while ((time != atmel_rtc_read(time_reg)) || 119 (date != atmel_rtc_read(cal_reg))); 120 121 tm->tm_wday = bcd_decode(RTC_VAL(CAL_DAY, date)) - 1; 122 tm->tm_mday = bcd_decode(RTC_VAL(CAL_DATE, date)); 123 tm->tm_mon = bcd_decode(RTC_VAL(CAL_MONTH, date)) - 1; 124 tm->tm_year = bcd_decode(RTC_VAL(CAL_CENT, date)) * 100; 125 tm->tm_year += bcd_decode(RTC_VAL(CAL_YEAR, date)); 126 127 tm->tm_hour = bcd_decode(RTC_VAL(TIME_HOUR, time)); 128 tm->tm_min = bcd_decode(RTC_VAL(TIME_MIN, time)); 129 tm->tm_sec = bcd_decode(RTC_VAL(TIME_SEC, time)); 130 } 131 132 static TEE_Result atmel_rtc_get_time(struct rtc *rtc __unused, 133 struct optee_rtc_time *tm) 134 { 135 atmel_decode_date(RTC_TIMR, RTC_CALR, tm); 136 137 return TEE_SUCCESS; 138 } 139 140 TEE_Result atmel_rtc_get_tamper_timestamp(struct optee_rtc_time *tm) 141 { 142 if (!rtc_base) 143 return TEE_ERROR_NOT_SUPPORTED; 144 145 atmel_decode_date(RTC_TSTR0, RTC_TSDR0, tm); 146 147 return TEE_SUCCESS; 148 } 149 150 static TEE_Result atmel_rtc_set_time(struct rtc *rtc __unused, 151 struct optee_rtc_time *tm) 152 { 153 uint32_t cr = 0; 154 uint32_t sr = 0; 155 uint32_t err = 0; 156 157 /* First, wait for UPDCAL/UPDTIM to be 0 */ 158 do { 159 cr = atmel_rtc_read(RTC_CR); 160 } while (cr & (RTC_CR_UPDCAL | RTC_CR_UPDTIM)); 161 162 /* Stop Time/Calendar for update */ 163 atmel_rtc_write(RTC_CR, cr | RTC_CR_UPDCAL | RTC_CR_UPDTIM); 164 165 do { 166 sr = atmel_rtc_read(RTC_SR); 167 } while (!(sr & RTC_SR_ACKUPD)); 168 169 atmel_rtc_write(RTC_SCCR, RTC_SCCR_ACKCLR); 170 171 atmel_rtc_write(RTC_TIMR, 172 RTC_SET_VAL(TIME_SEC, bcd_encode(tm->tm_sec)) | 173 RTC_SET_VAL(TIME_MIN, bcd_encode(tm->tm_min)) | 174 RTC_SET_VAL(TIME_HOUR, bcd_encode(tm->tm_hour))); 175 176 atmel_rtc_write(RTC_CALR, 177 RTC_SET_VAL(CAL_CENT, 178 bcd_encode(tm->tm_year / 100)) | 179 RTC_SET_VAL(CAL_YEAR, bcd_encode(tm->tm_year % 100)) | 180 RTC_SET_VAL(CAL_MONTH, bcd_encode(tm->tm_mon + 1)) | 181 RTC_SET_VAL(CAL_DAY, bcd_encode(tm->tm_wday + 1)) | 182 RTC_SET_VAL(CAL_DATE, bcd_encode(tm->tm_mday))); 183 184 err = atmel_rtc_read(RTC_VER); 185 if (err) { 186 if (err & RTC_VER_NVTIM) 187 DMSG("Invalid time programmed"); 188 if (err & RTC_VER_NVCAL) 189 DMSG("Invalid date programmed"); 190 191 return TEE_ERROR_BAD_PARAMETERS; 192 } 193 194 /* Restart Time/Calendar */ 195 atmel_rtc_write(RTC_CR, cr); 196 197 return TEE_SUCCESS; 198 } 199 200 static TEE_Result atmel_rtc_get_offset(struct rtc *rtc __unused, long *offset) 201 { 202 uint32_t mr = atmel_rtc_read(RTC_MR); 203 long val = RTC_VAL(MR_CORR, mr); 204 205 if (!val) { 206 *offset = 0; 207 return TEE_SUCCESS; 208 } 209 210 val++; 211 212 if (!(mr & RTC_MR_HIGHPPM)) 213 val *= ATMEL_RTC_CORR_LOW_RATIO; 214 215 val = UDIV_ROUND_NEAREST(ATMEL_RTC_CORR_DIVIDEND, val); 216 217 if (!(mr & RTC_MR_NEGPPM)) 218 val = -val; 219 220 *offset = val; 221 222 return TEE_SUCCESS; 223 } 224 225 static TEE_Result atmel_rtc_set_offset(struct rtc *rtc __unused, long offset) 226 { 227 long corr = 0; 228 uint32_t mr = 0; 229 230 if (offset > ATMEL_RTC_CORR_DIVIDEND / 2) 231 return TEE_ERROR_BAD_PARAMETERS; 232 if (offset < -ATMEL_RTC_CORR_DIVIDEND / 2) 233 return TEE_ERROR_BAD_PARAMETERS; 234 235 mr = atmel_rtc_read(RTC_MR); 236 mr &= ~(RTC_MR_NEGPPM | RTC_MR_CORR_MASK | RTC_MR_HIGHPPM); 237 238 if (offset > 0) 239 mr |= RTC_MR_NEGPPM; 240 else 241 offset = -offset; 242 243 /* offset less than 764 ppb, disable correction */ 244 if (offset < 764) { 245 atmel_rtc_write(RTC_MR, mr & ~RTC_MR_NEGPPM); 246 247 return TEE_SUCCESS; 248 } 249 250 /* 251 * 29208 ppb is the perfect cutoff between low range and high range 252 * low range values are never better than high range value after that. 253 */ 254 if (offset < 29208) { 255 corr = UDIV_ROUND_NEAREST(ATMEL_RTC_CORR_DIVIDEND, 256 offset * ATMEL_RTC_CORR_LOW_RATIO); 257 } else { 258 corr = UDIV_ROUND_NEAREST(ATMEL_RTC_CORR_DIVIDEND, offset); 259 mr |= RTC_MR_HIGHPPM; 260 } 261 262 corr = MIN(corr, 128); 263 264 mr |= ((corr - 1) & RTC_MR_CORR_MASK) << RTC_MR_CORR_SHIFT; 265 266 atmel_rtc_write(RTC_MR, mr); 267 268 return TEE_SUCCESS; 269 } 270 271 static const struct rtc_ops atmel_rtc_ops = { 272 .get_time = atmel_rtc_get_time, 273 .set_time = atmel_rtc_set_time, 274 .get_offset = atmel_rtc_get_offset, 275 .set_offset = atmel_rtc_set_offset, 276 }; 277 278 static struct rtc atmel_rtc = { 279 .ops = &atmel_rtc_ops, 280 .range_min = RTC_TIME(1900, 0, 1, 1, 0, 0, 0, 0), 281 .range_max = RTC_TIME(2099, 11, 31, 4, 23, 59, 59, 999), 282 }; 283 284 /* Non-null reference for compat data */ 285 static const uint8_t rtc_always_secure; 286 287 static TEE_Result atmel_rtc_probe(const void *fdt, int node, 288 const void *compat_data) 289 { 290 size_t size = 0; 291 292 if (rtc_base) 293 return TEE_ERROR_GENERIC; 294 295 if (fdt_get_status(fdt, node) != DT_STATUS_OK_SEC) 296 return TEE_ERROR_BAD_PARAMETERS; 297 298 if (compat_data != &rtc_always_secure) 299 matrix_configure_periph_secure(AT91C_ID_SYS); 300 301 if (dt_map_dev(fdt, node, &rtc_base, &size, DT_MAP_AUTO) < 0) 302 return TEE_ERROR_GENERIC; 303 304 atmel_rtc_write(RTC_CR, 0); 305 /* Enable 24 hours Gregorian mode (this is a clear bits operation !) */ 306 io_clrbits32(rtc_base + RTC_MR, RTC_MR_PERSIAN | RTC_MR_UTC | 307 RTC_MR_HR_MODE); 308 309 rtc_register(&atmel_rtc); 310 311 return TEE_SUCCESS; 312 } 313 314 static const struct dt_device_match atmel_rtc_match_table[] = { 315 { .compatible = "atmel,sama5d2-rtc" }, 316 { 317 .compatible = "microchip,sama7g5-rtc", 318 .compat_data = &rtc_always_secure, 319 }, 320 { } 321 }; 322 323 DEFINE_DT_DRIVER(atmel_rtc_dt_driver) = { 324 .name = "atmel_rtc", 325 .type = DT_DRIVER_NOTYPE, 326 .match_table = atmel_rtc_match_table, 327 .probe = atmel_rtc_probe, 328 }; 329 330