1 #include <minix/syslib.h>
2 #include <minix/drvlib.h>
4 #include <minix/mmio.h>
5 #include <minix/clkconf.h>
6 #include <minix/sysutil.h>
7 #include <minix/board.h>
10 #include <sys/types.h>
21 #include "readclock.h"
23 /* defines the set of register */
25 typedef struct omap_rtc_registers
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
;
64 typedef struct omap_rtc_clock
67 { am335x
} clock_type
;
70 vir_bytes mapped_addr
;
71 omap_rtc_registers_t
*regs
;
74 /* Define the registers for each chip */
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
114 static omap_rtc_clock_t rtc
= {
115 am335x
, AM335X_RTC_SS_BASE
, AM335X_RTC_SS_SIZE
, 0, &am335x_rtc_regs
118 /* used for logging */
119 static struct log log
= {
121 .log_level
= LEVEL_INFO
,
122 .log_func
= default_log
125 static u32_t use_count
= 0;
126 static u32_t pwr_off_in_progress
= 0;
128 static void omap_rtc_unlock(void);
129 static void omap_rtc_lock(void);
130 static int omap_rtc_clkconf(void);
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))
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.
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))
147 omap_rtc_unlock(void)
149 /* Specific bit patterns need to be written to specific registers in a
150 * specific order to enable writing to RTC_SS registers.
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
);
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
);
165 omap_rtc_clkconf(void)
169 /* Configure the clocks need to run the RTC */
175 r
= clkconf_set(CM_RTC_RTC_CLKCTRL
, 0xffffffff,
176 CM_RTC_RTC_CLKCTRL_MASK
);
181 r
= clkconf_set(CM_RTC_CLKSTCTRL
, 0xffffffff, CM_RTC_CLKSTCTRL_MASK
);
186 r
= clkconf_release();
198 int rtc_rev
, major
, minor
;
199 struct minix_mem_range mr
;
201 struct machine machine
;
202 sys_getmachine(&machine
);
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.
210 log_warn(&log
, "unsupported processor\n");
214 if (pwr_off_in_progress
)
218 if (rtc
.mapped_addr
!= 0) {
219 /* already intialized */
224 r
= omap_rtc_clkconf();
226 log_warn(&log
, "Failed to enable clocks for RTC.\n");
231 * Map RTC_SS Registers
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 */
238 /* ask for privileges to access the RTC_SS memory range */
239 if (sys_privctl(SELF
, SYS_PRIV_ADD_MEM
, &mr
) != OK
) {
241 "Unable to obtain RTC memory range privileges.");
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");
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
);
258 /* Disable register write protect */
262 reg_write(rtc
.regs
->RTC_SS_RTC_SYSCONFIG
, (1 << NOIDLE_BIT
));
264 /* Enable 32kHz clock */
265 reg_set_bit(rtc
.regs
->RTC_SS_RTC_OSC_REG
, EN_32KCLK_BIT
);
267 /* Setting the stop bit starts the RTC running */
268 reg_set_bit(rtc
.regs
->RTC_SS_RTC_CTRL_REG
, RTC_STOP_BIT
);
270 /* Re-enable Write Protection */
273 log_debug(&log
, "OMAP RTC Initialized\n");
279 * These are the ranges used by the real time clock and struct tm.
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
292 omap_rtc_get_time(struct tm
*t
, int flags
)
296 if (pwr_off_in_progress
)
299 memset(t
, '\0', sizeof(struct tm
));
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);
307 bcd_to_dec(reg_read(rtc
.regs
->RTC_SS_MONTHS_REG
) & 0x1f) - 1;
309 bcd_to_dec(reg_read(rtc
.regs
->RTC_SS_YEARS_REG
) & 0xff) + 100;
311 if (t
->tm_year
== 100) {
312 /* Cold start - no date/time set - default to 2013-01-01 */
320 omap_rtc_set_time(t
, RTCDEV_NOFLAGS
);
327 omap_rtc_set_time(struct tm
*t
, int flags
)
331 if (pwr_off_in_progress
)
334 /* Disable Write Protection */
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));
351 /* Re-enable Write Protection */
358 omap_rtc_pwr_off(void)
363 if (pwr_off_in_progress
)
366 /* wait until 3 seconds can be added without overflowing tm_sec */
368 omap_rtc_get_time(&t
, RTCDEV_NOFLAGS
);
370 } while (t
.tm_sec
>= 57);
372 /* set the alarm for 3 seconds from now */
375 /* Disable register write protect */
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
);
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));
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
);
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
);
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;
405 /* Make the kernel's job easier by not re-enabling write protection */
414 if (use_count
== 0) {
415 vm_unmap_phys(SELF
, (void *) rtc
.mapped_addr
, rtc
.mr_size
);
418 log_debug(&log
, "Exiting\n");