1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32#include <common.h>
33#include <command.h>
34#include <linux/compat.h>
35#include <rtc.h>
36
37#if defined(CONFIG_CMD_DATE)
38
39#include <asm/io.h>
40#include <asm/arch/imx-regs.h>
41
42
43
44struct imxdi_regs {
45 u32 dtcmr;
46 u32 dtclr;
47 u32 dcamr;
48 u32 dcalr;
49 u32 dcr;
50 u32 dsr;
51 u32 dier;
52};
53
54#define DCAMR_UNSET 0xFFFFFFFF
55
56#define DCR_TCE (1 << 3)
57
58#define DSR_WBF (1 << 10)
59#define DSR_WNF (1 << 9)
60#define DSR_WCF (1 << 8)
61#define DSR_WEF (1 << 7)
62#define DSR_CAF (1 << 4)
63#define DSR_NVF (1 << 1)
64#define DSR_SVF (1 << 0)
65
66#define DIER_WNIE (1 << 9)
67#define DIER_WCIE (1 << 8)
68#define DIER_WEIE (1 << 7)
69#define DIER_CAIE (1 << 4)
70
71
72
73struct imxdi_data {
74 struct imxdi_regs __iomem *regs;
75 int init_done;
76};
77
78static struct imxdi_data data;
79
80
81
82
83
84
85
86
87static void clear_write_error(void)
88{
89 int cnt;
90
91 puts("### Warning: RTC - Register write error!\n");
92
93
94 __raw_writel(DSR_WEF, &data.regs->dsr);
95
96
97 for (cnt = 0; cnt < 1000; cnt++) {
98 if ((__raw_readl(&data.regs->dsr) & DSR_WEF) == 0)
99 return;
100 udelay(10);
101 }
102 puts("### Error: RTC - Cannot clear write-error flag!\n");
103}
104
105
106
107
108
109
110#define DI_WRITE_WAIT(val, reg) \
111( \
112 \
113 __raw_writel((val), &data.regs->reg), \
114 \
115 di_write_wait((val), #reg) \
116)
117static int di_write_wait(u32 val, const char *reg)
118{
119 int cnt;
120 int ret = 0;
121 int rc = 0;
122
123
124 for (cnt = 0; cnt < 100; cnt++) {
125 if ((__raw_readl(&data.regs->dsr) & (DSR_WCF | DSR_WEF)) != 0) {
126 ret = 1;
127 break;
128 }
129 udelay(10);
130 }
131 if (ret == 0)
132 printf("### Warning: RTC - Write-wait timeout "
133 "val = 0x%.8x reg = %s\n", val, reg);
134
135
136 if (__raw_readl(&data.regs->dsr) & DSR_WEF) {
137 clear_write_error();
138 rc = -1;
139 }
140
141 return rc;
142}
143
144
145
146
147static int di_init(void)
148{
149 int rc = 0;
150
151 data.regs = (struct imxdi_regs __iomem *)IMX_DRYICE_BASE;
152
153
154 __raw_writel(0, &data.regs->dier);
155
156
157 if (__raw_readl(&data.regs->dsr) & DSR_NVF) {
158 rc = DI_WRITE_WAIT(DSR_NVF | DSR_SVF, dsr);
159 if (rc)
160 goto err;
161 }
162
163
164 rc = DI_WRITE_WAIT(DCAMR_UNSET, dcamr);
165 if (rc)
166 goto err;
167 rc = DI_WRITE_WAIT(0, dcalr);
168 if (rc)
169 goto err;
170
171
172 if (__raw_readl(&data.regs->dsr) & DSR_CAF) {
173 rc = DI_WRITE_WAIT(DSR_CAF, dsr);
174 if (rc)
175 goto err;
176 }
177
178
179 if (__raw_readl(&data.regs->dtcmr) == 0) {
180 rc = DI_WRITE_WAIT(0, dtcmr);
181 if (rc)
182 goto err;
183 }
184
185
186 if (!(__raw_readl(&data.regs->dcr) & DCR_TCE)) {
187 rc = DI_WRITE_WAIT(__raw_readl(&data.regs->dcr) | DCR_TCE, dcr);
188 if (rc)
189 goto err;
190 }
191
192 data.init_done = 1;
193 return 0;
194
195err:
196 return rc;
197}
198
199int rtc_get(struct rtc_time *tmp)
200{
201 unsigned long now;
202 int rc = 0;
203
204 if (!data.init_done) {
205 rc = di_init();
206 if (rc)
207 goto err;
208 }
209
210 now = __raw_readl(&data.regs->dtcmr);
211 to_tm(now, tmp);
212
213err:
214 return rc;
215}
216
217int rtc_set(struct rtc_time *tmp)
218{
219 unsigned long now;
220 int rc;
221
222 if (!data.init_done) {
223 rc = di_init();
224 if (rc)
225 goto err;
226 }
227
228 now = mktime(tmp->tm_year, tmp->tm_mon, tmp->tm_mday,
229 tmp->tm_hour, tmp->tm_min, tmp->tm_sec);
230
231 rc = DI_WRITE_WAIT(0, dtclr);
232 if (rc == 0)
233 rc = DI_WRITE_WAIT(now, dtcmr);
234
235err:
236 return rc;
237}
238
239void rtc_reset(void)
240{
241 di_init();
242}
243
244#endif
245