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
omap_rtc_unlock(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
omap_rtc_lock(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
omap_rtc_clkconf(void)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
omap_rtc_init(void)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
omap_rtc_get_time(struct tm * t,int flags)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
omap_rtc_set_time(struct tm * t,int flags)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
omap_rtc_pwr_off(void)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
omap_rtc_exit(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