diff options
author | Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> | 2011-11-14 01:24:53 -0500 |
---|---|---|
committer | Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> | 2011-11-28 09:50:39 -0500 |
commit | d28bdfc5c80fb64bf50824920bf9b554732dec74 (patch) | |
tree | 2f2ce017d27c0094a8a1561d532f73f50a4156fe /drivers/rtc/rtc-at91rm9200.c | |
parent | be6d4321720cd56623c1d5be311bde65c2c91229 (diff) |
ARM: at91: make rm9200 rtc drivers soc independent
switch the rtc drivers to resource and pass it via platform_device
Signed-off-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
Cc: Nicolas Ferre <nicolas.ferre@atmel.com>
Diffstat (limited to 'drivers/rtc/rtc-at91rm9200.c')
-rw-r--r-- | drivers/rtc/rtc-at91rm9200.c | 101 |
1 files changed, 63 insertions, 38 deletions
diff --git a/drivers/rtc/rtc-at91rm9200.c b/drivers/rtc/rtc-at91rm9200.c index e39b77a4609a..dc474bc6522d 100644 --- a/drivers/rtc/rtc-at91rm9200.c +++ b/drivers/rtc/rtc-at91rm9200.c | |||
@@ -32,11 +32,17 @@ | |||
32 | 32 | ||
33 | #include <mach/at91_rtc.h> | 33 | #include <mach/at91_rtc.h> |
34 | 34 | ||
35 | #define at91_rtc_read(field) \ | ||
36 | __raw_readl(at91_rtc_regs + field) | ||
37 | #define at91_rtc_write(field, val) \ | ||
38 | __raw_writel((val), at91_rtc_regs + field) | ||
35 | 39 | ||
36 | #define AT91_RTC_EPOCH 1900UL /* just like arch/arm/common/rtctime.c */ | 40 | #define AT91_RTC_EPOCH 1900UL /* just like arch/arm/common/rtctime.c */ |
37 | 41 | ||
38 | static DECLARE_COMPLETION(at91_rtc_updated); | 42 | static DECLARE_COMPLETION(at91_rtc_updated); |
39 | static unsigned int at91_alarm_year = AT91_RTC_EPOCH; | 43 | static unsigned int at91_alarm_year = AT91_RTC_EPOCH; |
44 | static void __iomem *at91_rtc_regs; | ||
45 | static int irq; | ||
40 | 46 | ||
41 | /* | 47 | /* |
42 | * Decode time/date into rtc_time structure | 48 | * Decode time/date into rtc_time structure |
@@ -48,10 +54,10 @@ static void at91_rtc_decodetime(unsigned int timereg, unsigned int calreg, | |||
48 | 54 | ||
49 | /* must read twice in case it changes */ | 55 | /* must read twice in case it changes */ |
50 | do { | 56 | do { |
51 | time = at91_sys_read(timereg); | 57 | time = at91_rtc_read(timereg); |
52 | date = at91_sys_read(calreg); | 58 | date = at91_rtc_read(calreg); |
53 | } while ((time != at91_sys_read(timereg)) || | 59 | } while ((time != at91_rtc_read(timereg)) || |
54 | (date != at91_sys_read(calreg))); | 60 | (date != at91_rtc_read(calreg))); |
55 | 61 | ||
56 | tm->tm_sec = bcd2bin((time & AT91_RTC_SEC) >> 0); | 62 | tm->tm_sec = bcd2bin((time & AT91_RTC_SEC) >> 0); |
57 | tm->tm_min = bcd2bin((time & AT91_RTC_MIN) >> 8); | 63 | tm->tm_min = bcd2bin((time & AT91_RTC_MIN) >> 8); |
@@ -98,19 +104,19 @@ static int at91_rtc_settime(struct device *dev, struct rtc_time *tm) | |||
98 | tm->tm_hour, tm->tm_min, tm->tm_sec); | 104 | tm->tm_hour, tm->tm_min, tm->tm_sec); |
99 | 105 | ||
100 | /* Stop Time/Calendar from counting */ | 106 | /* Stop Time/Calendar from counting */ |
101 | cr = at91_sys_read(AT91_RTC_CR); | 107 | cr = at91_rtc_read(AT91_RTC_CR); |
102 | at91_sys_write(AT91_RTC_CR, cr | AT91_RTC_UPDCAL | AT91_RTC_UPDTIM); | 108 | at91_rtc_write(AT91_RTC_CR, cr | AT91_RTC_UPDCAL | AT91_RTC_UPDTIM); |
103 | 109 | ||
104 | at91_sys_write(AT91_RTC_IER, AT91_RTC_ACKUPD); | 110 | at91_rtc_write(AT91_RTC_IER, AT91_RTC_ACKUPD); |
105 | wait_for_completion(&at91_rtc_updated); /* wait for ACKUPD interrupt */ | 111 | wait_for_completion(&at91_rtc_updated); /* wait for ACKUPD interrupt */ |
106 | at91_sys_write(AT91_RTC_IDR, AT91_RTC_ACKUPD); | 112 | at91_rtc_write(AT91_RTC_IDR, AT91_RTC_ACKUPD); |
107 | 113 | ||
108 | at91_sys_write(AT91_RTC_TIMR, | 114 | at91_rtc_write(AT91_RTC_TIMR, |
109 | bin2bcd(tm->tm_sec) << 0 | 115 | bin2bcd(tm->tm_sec) << 0 |
110 | | bin2bcd(tm->tm_min) << 8 | 116 | | bin2bcd(tm->tm_min) << 8 |
111 | | bin2bcd(tm->tm_hour) << 16); | 117 | | bin2bcd(tm->tm_hour) << 16); |
112 | 118 | ||
113 | at91_sys_write(AT91_RTC_CALR, | 119 | at91_rtc_write(AT91_RTC_CALR, |
114 | bin2bcd((tm->tm_year + 1900) / 100) /* century */ | 120 | bin2bcd((tm->tm_year + 1900) / 100) /* century */ |
115 | | bin2bcd(tm->tm_year % 100) << 8 /* year */ | 121 | | bin2bcd(tm->tm_year % 100) << 8 /* year */ |
116 | | bin2bcd(tm->tm_mon + 1) << 16 /* tm_mon starts at zero */ | 122 | | bin2bcd(tm->tm_mon + 1) << 16 /* tm_mon starts at zero */ |
@@ -118,8 +124,8 @@ static int at91_rtc_settime(struct device *dev, struct rtc_time *tm) | |||
118 | | bin2bcd(tm->tm_mday) << 24); | 124 | | bin2bcd(tm->tm_mday) << 24); |
119 | 125 | ||
120 | /* Restart Time/Calendar */ | 126 | /* Restart Time/Calendar */ |
121 | cr = at91_sys_read(AT91_RTC_CR); | 127 | cr = at91_rtc_read(AT91_RTC_CR); |
122 | at91_sys_write(AT91_RTC_CR, cr & ~(AT91_RTC_UPDCAL | AT91_RTC_UPDTIM)); | 128 | at91_rtc_write(AT91_RTC_CR, cr & ~(AT91_RTC_UPDCAL | AT91_RTC_UPDTIM)); |
123 | 129 | ||
124 | return 0; | 130 | return 0; |
125 | } | 131 | } |
@@ -135,7 +141,7 @@ static int at91_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
135 | tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year); | 141 | tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year); |
136 | tm->tm_year = at91_alarm_year - 1900; | 142 | tm->tm_year = at91_alarm_year - 1900; |
137 | 143 | ||
138 | alrm->enabled = (at91_sys_read(AT91_RTC_IMR) & AT91_RTC_ALARM) | 144 | alrm->enabled = (at91_rtc_read(AT91_RTC_IMR) & AT91_RTC_ALARM) |
139 | ? 1 : 0; | 145 | ? 1 : 0; |
140 | 146 | ||
141 | pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __func__, | 147 | pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __func__, |
@@ -160,20 +166,20 @@ static int at91_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
160 | tm.tm_min = alrm->time.tm_min; | 166 | tm.tm_min = alrm->time.tm_min; |
161 | tm.tm_sec = alrm->time.tm_sec; | 167 | tm.tm_sec = alrm->time.tm_sec; |
162 | 168 | ||
163 | at91_sys_write(AT91_RTC_IDR, AT91_RTC_ALARM); | 169 | at91_rtc_write(AT91_RTC_IDR, AT91_RTC_ALARM); |
164 | at91_sys_write(AT91_RTC_TIMALR, | 170 | at91_rtc_write(AT91_RTC_TIMALR, |
165 | bin2bcd(tm.tm_sec) << 0 | 171 | bin2bcd(tm.tm_sec) << 0 |
166 | | bin2bcd(tm.tm_min) << 8 | 172 | | bin2bcd(tm.tm_min) << 8 |
167 | | bin2bcd(tm.tm_hour) << 16 | 173 | | bin2bcd(tm.tm_hour) << 16 |
168 | | AT91_RTC_HOUREN | AT91_RTC_MINEN | AT91_RTC_SECEN); | 174 | | AT91_RTC_HOUREN | AT91_RTC_MINEN | AT91_RTC_SECEN); |
169 | at91_sys_write(AT91_RTC_CALALR, | 175 | at91_rtc_write(AT91_RTC_CALALR, |
170 | bin2bcd(tm.tm_mon + 1) << 16 /* tm_mon starts at zero */ | 176 | bin2bcd(tm.tm_mon + 1) << 16 /* tm_mon starts at zero */ |
171 | | bin2bcd(tm.tm_mday) << 24 | 177 | | bin2bcd(tm.tm_mday) << 24 |
172 | | AT91_RTC_DATEEN | AT91_RTC_MTHEN); | 178 | | AT91_RTC_DATEEN | AT91_RTC_MTHEN); |
173 | 179 | ||
174 | if (alrm->enabled) { | 180 | if (alrm->enabled) { |
175 | at91_sys_write(AT91_RTC_SCCR, AT91_RTC_ALARM); | 181 | at91_rtc_write(AT91_RTC_SCCR, AT91_RTC_ALARM); |
176 | at91_sys_write(AT91_RTC_IER, AT91_RTC_ALARM); | 182 | at91_rtc_write(AT91_RTC_IER, AT91_RTC_ALARM); |
177 | } | 183 | } |
178 | 184 | ||
179 | pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __func__, | 185 | pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __func__, |
@@ -188,10 +194,10 @@ static int at91_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) | |||
188 | pr_debug("%s(): cmd=%08x\n", __func__, enabled); | 194 | pr_debug("%s(): cmd=%08x\n", __func__, enabled); |
189 | 195 | ||
190 | if (enabled) { | 196 | if (enabled) { |
191 | at91_sys_write(AT91_RTC_SCCR, AT91_RTC_ALARM); | 197 | at91_rtc_write(AT91_RTC_SCCR, AT91_RTC_ALARM); |
192 | at91_sys_write(AT91_RTC_IER, AT91_RTC_ALARM); | 198 | at91_rtc_write(AT91_RTC_IER, AT91_RTC_ALARM); |
193 | } else | 199 | } else |
194 | at91_sys_write(AT91_RTC_IDR, AT91_RTC_ALARM); | 200 | at91_rtc_write(AT91_RTC_IDR, AT91_RTC_ALARM); |
195 | 201 | ||
196 | return 0; | 202 | return 0; |
197 | } | 203 | } |
@@ -200,7 +206,7 @@ static int at91_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) | |||
200 | */ | 206 | */ |
201 | static int at91_rtc_proc(struct device *dev, struct seq_file *seq) | 207 | static int at91_rtc_proc(struct device *dev, struct seq_file *seq) |
202 | { | 208 | { |
203 | unsigned long imr = at91_sys_read(AT91_RTC_IMR); | 209 | unsigned long imr = at91_rtc_read(AT91_RTC_IMR); |
204 | 210 | ||
205 | seq_printf(seq, "update_IRQ\t: %s\n", | 211 | seq_printf(seq, "update_IRQ\t: %s\n", |
206 | (imr & AT91_RTC_ACKUPD) ? "yes" : "no"); | 212 | (imr & AT91_RTC_ACKUPD) ? "yes" : "no"); |
@@ -220,7 +226,7 @@ static irqreturn_t at91_rtc_interrupt(int irq, void *dev_id) | |||
220 | unsigned int rtsr; | 226 | unsigned int rtsr; |
221 | unsigned long events = 0; | 227 | unsigned long events = 0; |
222 | 228 | ||
223 | rtsr = at91_sys_read(AT91_RTC_SR) & at91_sys_read(AT91_RTC_IMR); | 229 | rtsr = at91_rtc_read(AT91_RTC_SR) & at91_rtc_read(AT91_RTC_IMR); |
224 | if (rtsr) { /* this interrupt is shared! Is it ours? */ | 230 | if (rtsr) { /* this interrupt is shared! Is it ours? */ |
225 | if (rtsr & AT91_RTC_ALARM) | 231 | if (rtsr & AT91_RTC_ALARM) |
226 | events |= (RTC_AF | RTC_IRQF); | 232 | events |= (RTC_AF | RTC_IRQF); |
@@ -229,7 +235,7 @@ static irqreturn_t at91_rtc_interrupt(int irq, void *dev_id) | |||
229 | if (rtsr & AT91_RTC_ACKUPD) | 235 | if (rtsr & AT91_RTC_ACKUPD) |
230 | complete(&at91_rtc_updated); | 236 | complete(&at91_rtc_updated); |
231 | 237 | ||
232 | at91_sys_write(AT91_RTC_SCCR, rtsr); /* clear status reg */ | 238 | at91_rtc_write(AT91_RTC_SCCR, rtsr); /* clear status reg */ |
233 | 239 | ||
234 | rtc_update_irq(rtc, 1, events); | 240 | rtc_update_irq(rtc, 1, events); |
235 | 241 | ||
@@ -256,22 +262,41 @@ static const struct rtc_class_ops at91_rtc_ops = { | |||
256 | static int __init at91_rtc_probe(struct platform_device *pdev) | 262 | static int __init at91_rtc_probe(struct platform_device *pdev) |
257 | { | 263 | { |
258 | struct rtc_device *rtc; | 264 | struct rtc_device *rtc; |
259 | int ret; | 265 | struct resource *regs; |
266 | int ret = 0; | ||
260 | 267 | ||
261 | at91_sys_write(AT91_RTC_CR, 0); | 268 | regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
262 | at91_sys_write(AT91_RTC_MR, 0); /* 24 hour mode */ | 269 | if (!regs) { |
270 | dev_err(&pdev->dev, "no mmio resource defined\n"); | ||
271 | return -ENXIO; | ||
272 | } | ||
273 | |||
274 | irq = platform_get_irq(pdev, 0); | ||
275 | if (irq < 0) { | ||
276 | dev_err(&pdev->dev, "no irq resource defined\n"); | ||
277 | return -ENXIO; | ||
278 | } | ||
279 | |||
280 | at91_rtc_regs = ioremap(regs->start, resource_size(regs)); | ||
281 | if (!at91_rtc_regs) { | ||
282 | dev_err(&pdev->dev, "failed to map registers, aborting.\n"); | ||
283 | return -ENOMEM; | ||
284 | } | ||
285 | |||
286 | at91_rtc_write(AT91_RTC_CR, 0); | ||
287 | at91_rtc_write(AT91_RTC_MR, 0); /* 24 hour mode */ | ||
263 | 288 | ||
264 | /* Disable all interrupts */ | 289 | /* Disable all interrupts */ |
265 | at91_sys_write(AT91_RTC_IDR, AT91_RTC_ACKUPD | AT91_RTC_ALARM | | 290 | at91_rtc_write(AT91_RTC_IDR, AT91_RTC_ACKUPD | AT91_RTC_ALARM | |
266 | AT91_RTC_SECEV | AT91_RTC_TIMEV | | 291 | AT91_RTC_SECEV | AT91_RTC_TIMEV | |
267 | AT91_RTC_CALEV); | 292 | AT91_RTC_CALEV); |
268 | 293 | ||
269 | ret = request_irq(AT91_ID_SYS, at91_rtc_interrupt, | 294 | ret = request_irq(irq, at91_rtc_interrupt, |
270 | IRQF_SHARED, | 295 | IRQF_SHARED, |
271 | "at91_rtc", pdev); | 296 | "at91_rtc", pdev); |
272 | if (ret) { | 297 | if (ret) { |
273 | printk(KERN_ERR "at91_rtc: IRQ %d already in use.\n", | 298 | printk(KERN_ERR "at91_rtc: IRQ %d already in use.\n", |
274 | AT91_ID_SYS); | 299 | irq); |
275 | return ret; | 300 | return ret; |
276 | } | 301 | } |
277 | 302 | ||
@@ -284,7 +309,7 @@ static int __init at91_rtc_probe(struct platform_device *pdev) | |||
284 | rtc = rtc_device_register(pdev->name, &pdev->dev, | 309 | rtc = rtc_device_register(pdev->name, &pdev->dev, |
285 | &at91_rtc_ops, THIS_MODULE); | 310 | &at91_rtc_ops, THIS_MODULE); |
286 | if (IS_ERR(rtc)) { | 311 | if (IS_ERR(rtc)) { |
287 | free_irq(AT91_ID_SYS, pdev); | 312 | free_irq(irq, pdev); |
288 | return PTR_ERR(rtc); | 313 | return PTR_ERR(rtc); |
289 | } | 314 | } |
290 | platform_set_drvdata(pdev, rtc); | 315 | platform_set_drvdata(pdev, rtc); |
@@ -301,10 +326,10 @@ static int __exit at91_rtc_remove(struct platform_device *pdev) | |||
301 | struct rtc_device *rtc = platform_get_drvdata(pdev); | 326 | struct rtc_device *rtc = platform_get_drvdata(pdev); |
302 | 327 | ||
303 | /* Disable all interrupts */ | 328 | /* Disable all interrupts */ |
304 | at91_sys_write(AT91_RTC_IDR, AT91_RTC_ACKUPD | AT91_RTC_ALARM | | 329 | at91_rtc_write(AT91_RTC_IDR, AT91_RTC_ACKUPD | AT91_RTC_ALARM | |
305 | AT91_RTC_SECEV | AT91_RTC_TIMEV | | 330 | AT91_RTC_SECEV | AT91_RTC_TIMEV | |
306 | AT91_RTC_CALEV); | 331 | AT91_RTC_CALEV); |
307 | free_irq(AT91_ID_SYS, pdev); | 332 | free_irq(irq, pdev); |
308 | 333 | ||
309 | rtc_device_unregister(rtc); | 334 | rtc_device_unregister(rtc); |
310 | platform_set_drvdata(pdev, NULL); | 335 | platform_set_drvdata(pdev, NULL); |
@@ -323,13 +348,13 @@ static int at91_rtc_suspend(struct device *dev) | |||
323 | /* this IRQ is shared with DBGU and other hardware which isn't | 348 | /* this IRQ is shared with DBGU and other hardware which isn't |
324 | * necessarily doing PM like we are... | 349 | * necessarily doing PM like we are... |
325 | */ | 350 | */ |
326 | at91_rtc_imr = at91_sys_read(AT91_RTC_IMR) | 351 | at91_rtc_imr = at91_rtc_read(AT91_RTC_IMR) |
327 | & (AT91_RTC_ALARM|AT91_RTC_SECEV); | 352 | & (AT91_RTC_ALARM|AT91_RTC_SECEV); |
328 | if (at91_rtc_imr) { | 353 | if (at91_rtc_imr) { |
329 | if (device_may_wakeup(dev)) | 354 | if (device_may_wakeup(dev)) |
330 | enable_irq_wake(AT91_ID_SYS); | 355 | enable_irq_wake(irq); |
331 | else | 356 | else |
332 | at91_sys_write(AT91_RTC_IDR, at91_rtc_imr); | 357 | at91_rtc_write(AT91_RTC_IDR, at91_rtc_imr); |
333 | } | 358 | } |
334 | return 0; | 359 | return 0; |
335 | } | 360 | } |
@@ -338,9 +363,9 @@ static int at91_rtc_resume(struct device *dev) | |||
338 | { | 363 | { |
339 | if (at91_rtc_imr) { | 364 | if (at91_rtc_imr) { |
340 | if (device_may_wakeup(dev)) | 365 | if (device_may_wakeup(dev)) |
341 | disable_irq_wake(AT91_ID_SYS); | 366 | disable_irq_wake(irq); |
342 | else | 367 | else |
343 | at91_sys_write(AT91_RTC_IER, at91_rtc_imr); | 368 | at91_rtc_write(AT91_RTC_IER, at91_rtc_imr); |
344 | } | 369 | } |
345 | return 0; | 370 | return 0; |
346 | } | 371 | } |