f024e0c95c012ef7e61132a54840788fba3180a9
[profile/mobile/platform/kernel/u-boot-tm1.git] / arch / arm / cpu / armv7 / sc8825 / rtc-sprd.c
1 /*
2  * An RTC device/driver
3  * Copyright (C) 2011 Spreadtrum Communication Inc 
4  * Author: Mark Yang<markyang@spreadtrum.com>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  */
10
11 #include <common.h>
12 #include "asm/arch/bits.h"
13 #include "asm/arch/rtc_reg_v3.h"
14 #include "asm/arch/regs_ana.h"
15 #include "asm/arch/adi_hal_internal.h"
16
17 #define CLEAR_RTC_INT(mask) \
18         do{ ANA_REG_SET(ANA_RTC_INT_CLR, mask); \
19                 while(ANA_REG_GET(ANA_RTC_INT_RSTS) & mask); \
20         }while(0)
21
22 #define mdelay(_ms) udelay(_ms*1000)
23
24 static inline unsigned get_sec(void)
25 {
26     unsigned sec, sec_bak;
27     sec = ANA_REG_GET(ANA_RTC_SEC_CNT) & RTC_SEC_MASK;
28     do{
29         sec_bak = ANA_REG_GET(ANA_RTC_SEC_CNT) & RTC_SEC_MASK;
30         if(sec_bak == sec)
31           break;
32         else
33           sec = sec_bak;
34     }while(1);
35
36     return sec;
37 }
38 static inline unsigned get_min(void)
39 {
40     unsigned min, min_bak;
41     min = ANA_REG_GET(ANA_RTC_MIN_CNT) & RTC_MIN_MASK;
42     do{
43         min_bak = ANA_REG_GET(ANA_RTC_MIN_CNT) & RTC_MIN_MASK;
44         if(min_bak == min)
45           break;
46         else
47           min = min_bak;
48     }while(1);
49
50     return min;
51 }
52 static inline unsigned get_hour(void)
53 {
54     unsigned hour, hour_bak;
55     hour = ANA_REG_GET(ANA_RTC_HOUR_CNT) & RTC_HOUR_MASK;
56     do{
57         hour_bak = ANA_REG_GET(ANA_RTC_HOUR_CNT) & RTC_HOUR_MASK;
58         if(hour_bak == hour)
59           break;
60         else
61           hour = hour_bak;
62     }while(1);
63
64     return hour;
65 }
66 static inline unsigned get_day(void)
67 {
68     unsigned day, day_bak;
69     day = ANA_REG_GET(ANA_RTC_DAY_CNT) & RTC_DAY_MASK;
70     do{
71         day_bak = ANA_REG_GET(ANA_RTC_DAY_CNT) & RTC_DAY_MASK;
72         if(day == day_bak)
73           break;
74         else
75           day = day_bak;
76     }while(1);
77     
78     return day;
79 }
80
81 unsigned long sprd_rtc_get_sec(void)
82 {
83         unsigned sec, min, hour, day;
84         unsigned first = 0, second = 0;
85
86         do {
87                 sec = get_sec();
88                 min = get_min();
89                 hour = get_hour();
90                 day = get_day();
91
92                 second = ((((day*24) + hour)*60 + min)*60 + sec);
93                 if((second - first) == 0)
94                         break;
95                 first = second;
96         }while(1);
97         return first;
98 }
99 void sprd_rtc_set_alarm_sec(unsigned long secs);
100 void sprd_rtc_set_sec(unsigned long secs)
101 {
102         unsigned sec, min, hour, day;
103     unsigned set_mask = 0, int_rsts;
104         unsigned long temp;
105
106         sec = secs % 60;
107         temp = (secs - sec)/60;
108         min = temp%60;
109         temp = (temp - min)/60;
110         hour = temp%24;
111         temp = (temp - hour)/24;
112         day = temp;
113
114
115     ANA_REG_OR(ANA_RTC_INT_CLR, RTC_UPD_TIME_MASK);
116
117     if(sec != get_sec()){
118         ANA_REG_SET(ANA_RTC_SEC_UPDATE, sec);
119         set_mask |= RTC_SEC_ACK_BIT;
120     }
121     if(min != get_min()){
122         ANA_REG_SET(ANA_RTC_MIN_UPDATE, min);
123         set_mask |= RTC_MIN_ACK_BIT;
124     }
125     if(hour != get_hour()){
126         ANA_REG_SET(ANA_RTC_HOUR_UPDATE, hour);
127         set_mask |= RTC_HOUR_ACK_BIT;
128     }
129     if(day != get_day()){
130         ANA_REG_SET(ANA_RTC_DAY_UPDATE, day);
131         set_mask |= RTC_DAY_ACK_BIT;
132     }
133
134     //wait till all update done
135
136     do{
137         int_rsts = ANA_REG_GET(ANA_RTC_INT_RSTS) & RTC_UPD_TIME_MASK;
138
139         if(set_mask == int_rsts)
140           break;
141     }while(1);
142     ANA_REG_OR(ANA_RTC_INT_CLR, RTC_UPD_TIME_MASK);
143
144         return;
145 }
146
147 unsigned long sprd_rtc_get_alarm_sec(void)
148 {
149         unsigned sec, min, hour, day;
150         day = ANA_REG_GET(ANA_RTC_DAY_ALM) & RTC_DAY_MASK;
151         hour = ANA_REG_GET(ANA_RTC_HOUR_ALM) & RTC_HOUR_MASK;
152         min = ANA_REG_GET(ANA_RTC_MIN_ALM) & RTC_MIN_MASK;
153         sec = ANA_REG_GET(ANA_RTC_SEC_ALM) & RTC_SEC_MASK;
154
155         return ((((day*24) + hour)*60 + min)*60 + sec);
156 }
157 void sprd_rtc_set_alarm_sec(unsigned long secs)
158 {
159         unsigned sec, min, hour, day;
160         unsigned long temp;
161         sec = secs % 60;
162         temp = (secs - sec)/60;
163         min = temp%60;
164         temp = (temp - min)/60;
165         hour = temp%24;
166         temp = (temp - hour)/24;
167         day = temp;
168         ANA_REG_SET(ANA_RTC_SEC_ALM, sec);
169         ANA_REG_SET(ANA_RTC_MIN_ALM, min);
170         ANA_REG_SET(ANA_RTC_HOUR_ALM, hour);
171         ANA_REG_SET(ANA_RTC_DAY_ALM, day);
172
173         return;
174 }
175
176
177 int sprd_clean_rtc(void)
178 {
179         int err;
180         ANA_REG_AND(ANA_RTC_INT_EN, ~(RTC_INT_ALL_MSK)); // disable all interrupt
181         ANA_REG_OR(ANA_APB_CLK_EN, AGEN_RTC_EN | AGEN_RTC_RTC_EN); //enable rtc device
182         CLEAR_RTC_INT(RTC_INT_ALL_MSK);
183         sprd_rtc_set_sec(0);
184     sprd_rtc_set_alarm_sec(0);
185     printf("now time sec %lu\n", sprd_rtc_get_sec());
186     printf("now alarm sec %lu\n", sprd_rtc_get_alarm_sec());
187
188         return 0;
189 }
190 void sprd_rtc_init(void)
191 {
192         ANA_REG_OR(ANA_APB_CLK_EN, AGEN_RTC_EN | AGEN_RTC_RTC_EN); //enable rtc device
193 }