]>
Commit | Line | Data |
---|---|---|
b58d8b48 MF |
1 | /* |
2 | * Copyright (c) 2004-2008 Analog Devices Inc. | |
3 | * | |
4 | * (C) Copyright 2001 | |
5 | * Wolfgang Denk, DENX Software Engineering, wd@denx.de. | |
6 | * | |
7 | * Licensed under the GPL-2 or later. | |
8 | */ | |
9 | ||
10 | #include <common.h> | |
11 | #include <command.h> | |
12 | #include <rtc.h> | |
13 | ||
14 | #if defined(CONFIG_RTC_BFIN) && defined(CONFIG_CMD_DATE) | |
15 | ||
16 | #include <asm/blackfin.h> | |
17 | #include <asm/mach-common/bits/rtc.h> | |
18 | ||
19 | #define pr_stamp() debug("%s:%s:%i: here i am\n", __FILE__, __func__, __LINE__) | |
20 | ||
21 | #define MIN_TO_SECS(x) (60 * (x)) | |
22 | #define HRS_TO_SECS(x) (60 * MIN_TO_SECS(x)) | |
23 | #define DAYS_TO_SECS(x) (24 * HRS_TO_SECS(x)) | |
24 | ||
25 | #define NUM_SECS_IN_MIN MIN_TO_SECS(1) | |
26 | #define NUM_SECS_IN_HR HRS_TO_SECS(1) | |
27 | #define NUM_SECS_IN_DAY DAYS_TO_SECS(1) | |
28 | ||
29 | /* Our on-chip RTC has no notion of "reset" */ | |
30 | void rtc_reset(void) | |
31 | { | |
32 | return; | |
33 | } | |
34 | ||
35 | /* Wait for pending writes to complete */ | |
36 | static void wait_for_complete(void) | |
37 | { | |
38 | pr_stamp(); | |
39 | while (!(bfin_read_RTC_ISTAT() & WRITE_COMPLETE)) | |
40 | if (!(bfin_read_RTC_ISTAT() & WRITE_PENDING)) | |
41 | break; | |
42 | bfin_write_RTC_ISTAT(WRITE_COMPLETE); | |
43 | } | |
44 | ||
45 | /* Enable the RTC prescaler enable register */ | |
46 | int rtc_init(void) | |
47 | { | |
48 | pr_stamp(); | |
49 | bfin_write_RTC_PREN(0x1); | |
50 | return 0; | |
51 | } | |
52 | ||
53 | /* Set the time. Get the time_in_secs which is the number of seconds since Jan 1970 and set the RTC registers | |
54 | * based on this value. | |
55 | */ | |
56 | void rtc_set(struct rtc_time *tmp) | |
57 | { | |
58 | unsigned long remain, days, hrs, mins, secs; | |
59 | ||
60 | pr_stamp(); | |
61 | ||
62 | if (tmp == NULL) { | |
63 | puts("Error setting the date/time\n"); | |
64 | return; | |
65 | } | |
66 | ||
67 | wait_for_complete(); | |
68 | ||
69 | /* Calculate number of seconds this incoming time represents */ | |
70 | remain = mktime(tmp->tm_year, tmp->tm_mon, tmp->tm_mday, | |
71 | tmp->tm_hour, tmp->tm_min, tmp->tm_sec); | |
72 | ||
73 | /* Figure out how many days since epoch */ | |
74 | days = remain / NUM_SECS_IN_DAY; | |
75 | ||
76 | /* From the remaining secs, compute the hrs(0-23), mins(0-59) and secs(0-59) */ | |
77 | remain = remain % NUM_SECS_IN_DAY; | |
78 | hrs = remain / NUM_SECS_IN_HR; | |
79 | remain = remain % NUM_SECS_IN_HR; | |
80 | mins = remain / NUM_SECS_IN_MIN; | |
81 | secs = remain % NUM_SECS_IN_MIN; | |
82 | ||
83 | /* Encode these time values into our RTC_STAT register */ | |
84 | bfin_write_RTC_STAT(SET_ALARM(days, hrs, mins, secs)); | |
85 | } | |
86 | ||
87 | /* Read the time from the RTC_STAT. time_in_seconds is seconds since Jan 1970 */ | |
b73a19e1 | 88 | int rtc_get(struct rtc_time *tmp) |
b58d8b48 MF |
89 | { |
90 | uint32_t cur_rtc_stat; | |
91 | int time_in_sec; | |
92 | int tm_sec, tm_min, tm_hr, tm_day; | |
93 | ||
94 | pr_stamp(); | |
95 | ||
96 | if (tmp == NULL) { | |
97 | puts("Error getting the date/time\n"); | |
b73a19e1 | 98 | return -1; |
b58d8b48 MF |
99 | } |
100 | ||
101 | wait_for_complete(); | |
102 | ||
103 | /* Read the RTC_STAT register */ | |
104 | cur_rtc_stat = bfin_read_RTC_STAT(); | |
105 | ||
106 | /* Convert our encoded format into actual time values */ | |
107 | tm_sec = (cur_rtc_stat & RTC_SEC) >> RTC_SEC_P; | |
108 | tm_min = (cur_rtc_stat & RTC_MIN) >> RTC_MIN_P; | |
109 | tm_hr = (cur_rtc_stat & RTC_HR ) >> RTC_HR_P; | |
110 | tm_day = (cur_rtc_stat & RTC_DAY) >> RTC_DAY_P; | |
111 | ||
112 | /* Calculate the total number of seconds since epoch */ | |
113 | time_in_sec = (tm_sec) + MIN_TO_SECS(tm_min) + HRS_TO_SECS(tm_hr) + DAYS_TO_SECS(tm_day); | |
114 | to_tm(time_in_sec, tmp); | |
b73a19e1 YT |
115 | |
116 | return 0; | |
b58d8b48 MF |
117 | } |
118 | ||
119 | #endif |