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