1 #include <minix/syslib.h> 2 #include <minix/drvlib.h> 3 #include <minix/log.h> 4 #include <minix/mmio.h> 5 #include <minix/clkconf.h> 6 #include <minix/sysutil.h> 7 #include <minix/board.h> 8 9 #include <sys/mman.h> 10 #include <sys/types.h> 11 12 #include <stdio.h> 13 #include <stdlib.h> 14 #include <stdarg.h> 15 #include <string.h> 16 #include <errno.h> 17 #include <assert.h> 18 #include <time.h> 19 20 #include "omap_rtc.h" 21 #include "readclock.h" 22 23 /* defines the set of register */ 24 25 typedef struct omap_rtc_registers 26 { 27 vir_bytes RTC_SS_SECONDS_REG; 28 vir_bytes RTC_SS_MINUTES_REG; 29 vir_bytes RTC_SS_HOURS_REG; 30 vir_bytes RTC_SS_DAYS_REG; 31 vir_bytes RTC_SS_MONTHS_REG; 32 vir_bytes RTC_SS_YEARS_REG; 33 vir_bytes RTC_SS_WEEKS_REG; 34 vir_bytes RTC_SS_ALARM_SECONDS_REG; 35 vir_bytes RTC_SS_ALARM_MINUTES_REG; 36 vir_bytes RTC_SS_ALARM_HOURS_REG; 37 vir_bytes RTC_SS_ALARM_DAYS_REG; 38 vir_bytes RTC_SS_ALARM_MONTHS_REG; 39 vir_bytes RTC_SS_ALARM_YEARS_REG; 40 vir_bytes RTC_SS_RTC_CTRL_REG; 41 vir_bytes RTC_SS_RTC_STATUS_REG; 42 vir_bytes RTC_SS_RTC_INTERRUPTS_REG; 43 vir_bytes RTC_SS_RTC_COMP_LSB_REG; 44 vir_bytes RTC_SS_RTC_COMP_MSB_REG; 45 vir_bytes RTC_SS_RTC_OSC_REG; 46 vir_bytes RTC_SS_RTC_SCRATCH0_REG; 47 vir_bytes RTC_SS_RTC_SCRATCH1_REG; 48 vir_bytes RTC_SS_RTC_SCRATCH2_REG; 49 vir_bytes RTC_SS_KICK0R; 50 vir_bytes RTC_SS_KICK1R; 51 vir_bytes RTC_SS_RTC_REVISION; 52 vir_bytes RTC_SS_RTC_SYSCONFIG; 53 vir_bytes RTC_SS_RTC_IRQWAKEEN; 54 vir_bytes RTC_SS_ALARM2_SECONDS_REG; 55 vir_bytes RTC_SS_ALARM2_MINUTES_REG; 56 vir_bytes RTC_SS_ALARM2_HOURS_REG; 57 vir_bytes RTC_SS_ALARM2_DAYS_REG; 58 vir_bytes RTC_SS_ALARM2_MONTHS_REG; 59 vir_bytes RTC_SS_ALARM2_YEARS_REG; 60 vir_bytes RTC_SS_RTC_PMIC; 61 vir_bytes RTC_SS_RTC_DEBOUNCE; 62 } omap_rtc_registers_t; 63 64 typedef struct omap_rtc_clock 65 { 66 enum rtc_clock_type 67 { am335x } clock_type; 68 phys_bytes mr_base; 69 phys_bytes mr_size; 70 vir_bytes mapped_addr; 71 omap_rtc_registers_t *regs; 72 } omap_rtc_clock_t; 73 74 /* Define the registers for each chip */ 75 76 static omap_rtc_registers_t am335x_rtc_regs = { 77 .RTC_SS_SECONDS_REG = AM335X_RTC_SS_SECONDS_REG, 78 .RTC_SS_MINUTES_REG = AM335X_RTC_SS_MINUTES_REG, 79 .RTC_SS_HOURS_REG = AM335X_RTC_SS_HOURS_REG, 80 .RTC_SS_DAYS_REG = AM335X_RTC_SS_DAYS_REG, 81 .RTC_SS_MONTHS_REG = AM335X_RTC_SS_MONTHS_REG, 82 .RTC_SS_YEARS_REG = AM335X_RTC_SS_YEARS_REG, 83 .RTC_SS_WEEKS_REG = AM335X_RTC_SS_WEEKS_REG, 84 .RTC_SS_ALARM_SECONDS_REG = AM335X_RTC_SS_ALARM_SECONDS_REG, 85 .RTC_SS_ALARM_MINUTES_REG = AM335X_RTC_SS_ALARM_MINUTES_REG, 86 .RTC_SS_ALARM_HOURS_REG = AM335X_RTC_SS_ALARM_HOURS_REG, 87 .RTC_SS_ALARM_DAYS_REG = AM335X_RTC_SS_ALARM_DAYS_REG, 88 .RTC_SS_ALARM_MONTHS_REG = AM335X_RTC_SS_ALARM_MONTHS_REG, 89 .RTC_SS_ALARM_YEARS_REG = AM335X_RTC_SS_ALARM_YEARS_REG, 90 .RTC_SS_RTC_CTRL_REG = AM335X_RTC_SS_RTC_CTRL_REG, 91 .RTC_SS_RTC_STATUS_REG = AM335X_RTC_SS_RTC_STATUS_REG, 92 .RTC_SS_RTC_INTERRUPTS_REG = AM335X_RTC_SS_RTC_INTERRUPTS_REG, 93 .RTC_SS_RTC_COMP_LSB_REG = AM335X_RTC_SS_RTC_COMP_LSB_REG, 94 .RTC_SS_RTC_COMP_MSB_REG = AM335X_RTC_SS_RTC_COMP_MSB_REG, 95 .RTC_SS_RTC_OSC_REG = AM335X_RTC_SS_RTC_OSC_REG, 96 .RTC_SS_RTC_SCRATCH0_REG = AM335X_RTC_SS_RTC_SCRATCH0_REG, 97 .RTC_SS_RTC_SCRATCH1_REG = AM335X_RTC_SS_RTC_SCRATCH1_REG, 98 .RTC_SS_RTC_SCRATCH2_REG = AM335X_RTC_SS_RTC_SCRATCH2_REG, 99 .RTC_SS_KICK0R = AM335X_RTC_SS_KICK0R, 100 .RTC_SS_KICK1R = AM335X_RTC_SS_KICK1R, 101 .RTC_SS_RTC_REVISION = AM335X_RTC_SS_RTC_REVISION, 102 .RTC_SS_RTC_SYSCONFIG = AM335X_RTC_SS_RTC_SYSCONFIG, 103 .RTC_SS_RTC_IRQWAKEEN = AM335X_RTC_SS_RTC_IRQWAKEEN, 104 .RTC_SS_ALARM2_SECONDS_REG = AM335X_RTC_SS_ALARM2_SECONDS_REG, 105 .RTC_SS_ALARM2_MINUTES_REG = AM335X_RTC_SS_ALARM2_MINUTES_REG, 106 .RTC_SS_ALARM2_HOURS_REG = AM335X_RTC_SS_ALARM2_HOURS_REG, 107 .RTC_SS_ALARM2_DAYS_REG = AM335X_RTC_SS_ALARM2_DAYS_REG, 108 .RTC_SS_ALARM2_MONTHS_REG = AM335X_RTC_SS_ALARM2_MONTHS_REG, 109 .RTC_SS_ALARM2_YEARS_REG = AM335X_RTC_SS_ALARM2_YEARS_REG, 110 .RTC_SS_RTC_PMIC = AM335X_RTC_SS_RTC_PMIC, 111 .RTC_SS_RTC_DEBOUNCE = AM335X_RTC_SS_RTC_DEBOUNCE 112 }; 113 114 static omap_rtc_clock_t rtc = { 115 am335x, AM335X_RTC_SS_BASE, AM335X_RTC_SS_SIZE, 0, &am335x_rtc_regs 116 }; 117 118 /* used for logging */ 119 static struct log log = { 120 .name = "omap_rtc", 121 .log_level = LEVEL_INFO, 122 .log_func = default_log 123 }; 124 125 static u32_t use_count = 0; 126 static u32_t pwr_off_in_progress = 0; 127 128 static void omap_rtc_unlock(void); 129 static void omap_rtc_lock(void); 130 static int omap_rtc_clkconf(void); 131 132 /* Helper Functions for Register Access */ 133 #define reg_read(a) (*(volatile uint32_t *)(rtc.mapped_addr + a)) 134 #define reg_write(a,v) (*(volatile uint32_t *)(rtc.mapped_addr + a) = (v)) 135 #define reg_set_bit(a,v) reg_write((a), reg_read((a)) | (1<<v)) 136 #define reg_clear_bit(a,v) reg_write((a), reg_read((a)) & ~(1<<v)) 137 #define RTC_IS_BUSY (reg_read(rtc.regs->RTC_SS_RTC_STATUS_REG) & (1<<RTC_BUSY_BIT)) 138 139 /* When the RTC is running, writes should not happen when the RTC is busy. 140 * This macro waits until the RTC is free before doing the write. 141 */ 142 #define safe_reg_write(a,v) do { while (RTC_IS_BUSY) {micro_delay(1);} reg_write((a),(v)); } while (0) 143 #define safe_reg_set_bit(a,v) safe_reg_write((a), reg_read((a)) | (1<<v)) 144 #define safe_reg_clear_bit(a,v) safe_reg_write((a), reg_read((a)) & ~(1<<v)) 145 146 static void 147 omap_rtc_unlock(void) 148 { 149 /* Specific bit patterns need to be written to specific registers in a 150 * specific order to enable writing to RTC_SS registers. 151 */ 152 reg_write(rtc.regs->RTC_SS_KICK0R, AM335X_RTC_SS_KICK0R_UNLOCK_MASK); 153 reg_write(rtc.regs->RTC_SS_KICK1R, AM335X_RTC_SS_KICK1R_UNLOCK_MASK); 154 } 155 156 static void 157 omap_rtc_lock(void) 158 { 159 /* Write garbage to the KICK registers to enable write protect. */ 160 reg_write(rtc.regs->RTC_SS_KICK0R, AM335X_RTC_SS_KICK0R_LOCK_MASK); 161 reg_write(rtc.regs->RTC_SS_KICK1R, AM335X_RTC_SS_KICK1R_LOCK_MASK); 162 } 163 164 static int 165 omap_rtc_clkconf(void) 166 { 167 int r; 168 169 /* Configure the clocks need to run the RTC */ 170 r = clkconf_init(); 171 if (r != OK) { 172 return r; 173 } 174 175 r = clkconf_set(CM_RTC_RTC_CLKCTRL, 0xffffffff, 176 CM_RTC_RTC_CLKCTRL_MASK); 177 if (r != OK) { 178 return r; 179 } 180 181 r = clkconf_set(CM_RTC_CLKSTCTRL, 0xffffffff, CM_RTC_CLKSTCTRL_MASK); 182 if (r != OK) { 183 return r; 184 } 185 186 r = clkconf_release(); 187 if (r != OK) { 188 return r; 189 } 190 191 return OK; 192 } 193 194 int 195 omap_rtc_init(void) 196 { 197 int r; 198 int rtc_rev, major, minor; 199 struct minix_mem_range mr; 200 201 struct machine machine ; 202 sys_getmachine(&machine); 203 204 if(! BOARD_IS_BB(machine.board_id)){ 205 /* Only the am335x (BeagleBone & BeagleBone Black) is supported ATM. 206 * The dm37xx (BeagleBoard-xM) doesn't have a real time clock 207 * built-in. Instead, it uses the RTC on the PMIC. A driver for 208 * the BeagleBoard-xM's PMIC still needs to be developed. 209 */ 210 log_warn(&log, "unsupported processor\n"); 211 return ENOSYS; 212 } 213 214 if (pwr_off_in_progress) 215 return EINVAL; 216 217 use_count++; 218 if (rtc.mapped_addr != 0) { 219 /* already intialized */ 220 return OK; 221 } 222 223 /* Enable Clocks */ 224 r = omap_rtc_clkconf(); 225 if (r != OK) { 226 log_warn(&log, "Failed to enable clocks for RTC.\n"); 227 return r; 228 } 229 230 /* 231 * Map RTC_SS Registers 232 */ 233 234 /* Configure memory access */ 235 mr.mr_base = rtc.mr_base; /* start addr */ 236 mr.mr_limit = mr.mr_base + rtc.mr_size; /* end addr */ 237 238 /* ask for privileges to access the RTC_SS memory range */ 239 if (sys_privctl(SELF, SYS_PRIV_ADD_MEM, &mr) != OK) { 240 log_warn(&log, 241 "Unable to obtain RTC memory range privileges."); 242 return EPERM; 243 } 244 245 /* map the memory into this process */ 246 rtc.mapped_addr = (vir_bytes) vm_map_phys(SELF, 247 (void *) rtc.mr_base, rtc.mr_size); 248 if (rtc.mapped_addr == (vir_bytes) MAP_FAILED) { 249 log_warn(&log, "Unable to map RTC registers\n"); 250 return EPERM; 251 } 252 253 rtc_rev = reg_read(rtc.regs->RTC_SS_RTC_REVISION); 254 major = (rtc_rev & 0x0700) >> 8; 255 minor = (rtc_rev & 0x001f); 256 log_debug(&log, "omap rtc rev %d.%d\n", major, minor); 257 258 /* Disable register write protect */ 259 omap_rtc_unlock(); 260 261 /* Set NOIDLE */ 262 reg_write(rtc.regs->RTC_SS_RTC_SYSCONFIG, (1 << NOIDLE_BIT)); 263 264 /* Enable 32kHz clock */ 265 reg_set_bit(rtc.regs->RTC_SS_RTC_OSC_REG, EN_32KCLK_BIT); 266 267 /* Setting the stop bit starts the RTC running */ 268 reg_set_bit(rtc.regs->RTC_SS_RTC_CTRL_REG, RTC_STOP_BIT); 269 270 /* Re-enable Write Protection */ 271 omap_rtc_lock(); 272 273 log_debug(&log, "OMAP RTC Initialized\n"); 274 275 return OK; 276 } 277 278 /* 279 * These are the ranges used by the real time clock and struct tm. 280 * 281 * Field OMAP RTC struct tm 282 * ----- -------- --------- 283 * seconds 0 to 59 (Mask 0x7f) 0 to 59 (60 for leap seconds) 284 * minutes 0 to 59 (Mask 0x7f) 0 to 59 285 * hours 0 to 23 (Mask 0x3f) 0 to 23 286 * day 1 to 31 (Mask 0x3f) 1 to 31 287 * month 1 to 12 (Mask 0x1f) 0 to 11 288 * year last 2 digits of year X + 1900 289 */ 290 291 int 292 omap_rtc_get_time(struct tm *t, int flags) 293 { 294 int r; 295 296 if (pwr_off_in_progress) 297 return EINVAL; 298 299 memset(t, '\0', sizeof(struct tm)); 300 301 /* Read and Convert BCD to binary (default RTC mode). */ 302 t->tm_sec = bcd_to_dec(reg_read(rtc.regs->RTC_SS_SECONDS_REG) & 0x7f); 303 t->tm_min = bcd_to_dec(reg_read(rtc.regs->RTC_SS_MINUTES_REG) & 0x7f); 304 t->tm_hour = bcd_to_dec(reg_read(rtc.regs->RTC_SS_HOURS_REG) & 0x3f); 305 t->tm_mday = bcd_to_dec(reg_read(rtc.regs->RTC_SS_DAYS_REG) & 0x3f); 306 t->tm_mon = 307 bcd_to_dec(reg_read(rtc.regs->RTC_SS_MONTHS_REG) & 0x1f) - 1; 308 t->tm_year = 309 bcd_to_dec(reg_read(rtc.regs->RTC_SS_YEARS_REG) & 0xff) + 100; 310 311 if (t->tm_year == 100) { 312 /* Cold start - no date/time set - default to 2013-01-01 */ 313 t->tm_sec = 0; 314 t->tm_min = 0; 315 t->tm_hour = 0; 316 t->tm_mday = 1; 317 t->tm_mon = 0; 318 t->tm_year = 113; 319 320 omap_rtc_set_time(t, RTCDEV_NOFLAGS); 321 } 322 323 return OK; 324 } 325 326 int 327 omap_rtc_set_time(struct tm *t, int flags) 328 { 329 int r; 330 331 if (pwr_off_in_progress) 332 return EINVAL; 333 334 /* Disable Write Protection */ 335 omap_rtc_unlock(); 336 337 /* Write the date/time to the RTC registers. */ 338 safe_reg_write(rtc.regs->RTC_SS_SECONDS_REG, 339 (dec_to_bcd(t->tm_sec) & 0x7f)); 340 safe_reg_write(rtc.regs->RTC_SS_MINUTES_REG, 341 (dec_to_bcd(t->tm_min) & 0x7f)); 342 safe_reg_write(rtc.regs->RTC_SS_HOURS_REG, 343 (dec_to_bcd(t->tm_hour) & 0x3f)); 344 safe_reg_write(rtc.regs->RTC_SS_DAYS_REG, 345 (dec_to_bcd(t->tm_mday) & 0x3f)); 346 safe_reg_write(rtc.regs->RTC_SS_MONTHS_REG, 347 (dec_to_bcd(t->tm_mon + 1) & 0x1f)); 348 safe_reg_write(rtc.regs->RTC_SS_YEARS_REG, 349 (dec_to_bcd(t->tm_year % 100) & 0xff)); 350 351 /* Re-enable Write Protection */ 352 omap_rtc_lock(); 353 354 return OK; 355 } 356 357 int 358 omap_rtc_pwr_off(void) 359 { 360 int r; 361 struct tm t; 362 363 if (pwr_off_in_progress) 364 return EINVAL; 365 366 /* wait until 3 seconds can be added without overflowing tm_sec */ 367 do { 368 omap_rtc_get_time(&t, RTCDEV_NOFLAGS); 369 micro_delay(250000); 370 } while (t.tm_sec >= 57); 371 372 /* set the alarm for 3 seconds from now */ 373 t.tm_sec += 3; 374 375 /* Disable register write protect */ 376 omap_rtc_unlock(); 377 378 /* enable power-off via ALARM2 by setting the PWR_ENABLE_EN bit. */ 379 safe_reg_set_bit(rtc.regs->RTC_SS_RTC_PMIC, PWR_ENABLE_EN_BIT); 380 381 /* Write the date/time to the RTC registers. */ 382 safe_reg_write(rtc.regs->RTC_SS_ALARM2_SECONDS_REG, 383 (dec_to_bcd(t.tm_sec) & 0x7f)); 384 safe_reg_write(rtc.regs->RTC_SS_ALARM2_MINUTES_REG, 385 (dec_to_bcd(t.tm_min) & 0x7f)); 386 safe_reg_write(rtc.regs->RTC_SS_ALARM2_HOURS_REG, 387 (dec_to_bcd(t.tm_hour) & 0x3f)); 388 safe_reg_write(rtc.regs->RTC_SS_ALARM2_DAYS_REG, 389 (dec_to_bcd(t.tm_mday) & 0x3f)); 390 safe_reg_write(rtc.regs->RTC_SS_ALARM2_MONTHS_REG, 391 (dec_to_bcd(t.tm_mon + 1) & 0x1f)); 392 safe_reg_write(rtc.regs->RTC_SS_ALARM2_YEARS_REG, 393 (dec_to_bcd(t.tm_year % 100) & 0xff)); 394 395 /* enable interrupt to trigger POWER_EN to go low when alarm2 hits. */ 396 safe_reg_set_bit(rtc.regs->RTC_SS_RTC_INTERRUPTS_REG, IT_ALARM2_BIT); 397 398 /* pause the realtime clock. the kernel will enable it when safe. */ 399 reg_clear_bit(rtc.regs->RTC_SS_RTC_CTRL_REG, RTC_STOP_BIT); 400 401 /* Set this flag to block all other operations so that the clock isn't 402 * accidentally re-startered and so write protect isn't re-enabled. */ 403 pwr_off_in_progress = 1; 404 405 /* Make the kernel's job easier by not re-enabling write protection */ 406 407 return OK; 408 } 409 410 void 411 omap_rtc_exit(void) 412 { 413 use_count--; 414 if (use_count == 0) { 415 vm_unmap_phys(SELF, (void *) rtc.mapped_addr, rtc.mr_size); 416 rtc.mapped_addr = 0; 417 } 418 log_debug(&log, "Exiting\n"); 419 } 420