aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc/rtc-bfin.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/rtc/rtc-bfin.c')
-rw-r--r--drivers/rtc/rtc-bfin.c81
1 files changed, 36 insertions, 45 deletions
diff --git a/drivers/rtc/rtc-bfin.c b/drivers/rtc/rtc-bfin.c
index d4fb82d85e9b..90d866272c8e 100644
--- a/drivers/rtc/rtc-bfin.c
+++ b/drivers/rtc/rtc-bfin.c
@@ -2,7 +2,7 @@
2 * Blackfin On-Chip Real Time Clock Driver 2 * Blackfin On-Chip Real Time Clock Driver
3 * Supports BF51x/BF52x/BF53[123]/BF53[467]/BF54x 3 * Supports BF51x/BF52x/BF53[123]/BF53[467]/BF54x
4 * 4 *
5 * Copyright 2004-2009 Analog Devices Inc. 5 * Copyright 2004-2010 Analog Devices Inc.
6 * 6 *
7 * Enter bugs at http://blackfin.uclinux.org/ 7 * Enter bugs at http://blackfin.uclinux.org/
8 * 8 *
@@ -20,9 +20,9 @@
20 * write would be discarded and things quickly fall apart. 20 * write would be discarded and things quickly fall apart.
21 * 21 *
22 * To keep this delay from significantly degrading performance (we, in theory, 22 * To keep this delay from significantly degrading performance (we, in theory,
23 * would have to sleep for up to 1 second everytime we wanted to write a 23 * would have to sleep for up to 1 second every time we wanted to write a
24 * register), we only check the write pending status before we start to issue 24 * register), we only check the write pending status before we start to issue
25 * a new write. We bank on the idea that it doesnt matter when the sync 25 * a new write. We bank on the idea that it doesn't matter when the sync
26 * happens so long as we don't attempt another write before it does. The only 26 * happens so long as we don't attempt another write before it does. The only
27 * time userspace would take this penalty is when they try and do multiple 27 * time userspace would take this penalty is when they try and do multiple
28 * operations right after another ... but in this case, they need to take the 28 * operations right after another ... but in this case, they need to take the
@@ -183,29 +183,33 @@ static irqreturn_t bfin_rtc_interrupt(int irq, void *dev_id)
183 struct bfin_rtc *rtc = dev_get_drvdata(dev); 183 struct bfin_rtc *rtc = dev_get_drvdata(dev);
184 unsigned long events = 0; 184 unsigned long events = 0;
185 bool write_complete = false; 185 bool write_complete = false;
186 u16 rtc_istat, rtc_ictl; 186 u16 rtc_istat, rtc_istat_clear, rtc_ictl, bits;
187 187
188 dev_dbg_stamp(dev); 188 dev_dbg_stamp(dev);
189 189
190 rtc_istat = bfin_read_RTC_ISTAT(); 190 rtc_istat = bfin_read_RTC_ISTAT();
191 rtc_ictl = bfin_read_RTC_ICTL(); 191 rtc_ictl = bfin_read_RTC_ICTL();
192 rtc_istat_clear = 0;
192 193
193 if (rtc_istat & RTC_ISTAT_WRITE_COMPLETE) { 194 bits = RTC_ISTAT_WRITE_COMPLETE;
194 bfin_write_RTC_ISTAT(RTC_ISTAT_WRITE_COMPLETE); 195 if (rtc_istat & bits) {
196 rtc_istat_clear |= bits;
195 write_complete = true; 197 write_complete = true;
196 complete(&bfin_write_complete); 198 complete(&bfin_write_complete);
197 } 199 }
198 200
199 if (rtc_ictl & (RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY)) { 201 bits = (RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY);
200 if (rtc_istat & (RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY)) { 202 if (rtc_ictl & bits) {
201 bfin_write_RTC_ISTAT(RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY); 203 if (rtc_istat & bits) {
204 rtc_istat_clear |= bits;
202 events |= RTC_AF | RTC_IRQF; 205 events |= RTC_AF | RTC_IRQF;
203 } 206 }
204 } 207 }
205 208
206 if (rtc_ictl & RTC_ISTAT_SEC) { 209 bits = RTC_ISTAT_SEC;
207 if (rtc_istat & RTC_ISTAT_SEC) { 210 if (rtc_ictl & bits) {
208 bfin_write_RTC_ISTAT(RTC_ISTAT_SEC); 211 if (rtc_istat & bits) {
212 rtc_istat_clear |= bits;
209 events |= RTC_UF | RTC_IRQF; 213 events |= RTC_UF | RTC_IRQF;
210 } 214 }
211 } 215 }
@@ -213,9 +217,10 @@ static irqreturn_t bfin_rtc_interrupt(int irq, void *dev_id)
213 if (events) 217 if (events)
214 rtc_update_irq(rtc->rtc_dev, 1, events); 218 rtc_update_irq(rtc->rtc_dev, 1, events);
215 219
216 if (write_complete || events) 220 if (write_complete || events) {
221 bfin_write_RTC_ISTAT(rtc_istat_clear);
217 return IRQ_HANDLED; 222 return IRQ_HANDLED;
218 else 223 } else
219 return IRQ_NONE; 224 return IRQ_NONE;
220} 225}
221 226
@@ -235,40 +240,18 @@ static void bfin_rtc_int_set_alarm(struct bfin_rtc *rtc)
235 */ 240 */
236 bfin_rtc_int_set(rtc->rtc_alarm.tm_yday == -1 ? RTC_ISTAT_ALARM : RTC_ISTAT_ALARM_DAY); 241 bfin_rtc_int_set(rtc->rtc_alarm.tm_yday == -1 ? RTC_ISTAT_ALARM : RTC_ISTAT_ALARM_DAY);
237} 242}
238static int bfin_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) 243
244static int bfin_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
239{ 245{
240 struct bfin_rtc *rtc = dev_get_drvdata(dev); 246 struct bfin_rtc *rtc = dev_get_drvdata(dev);
241 int ret = 0;
242 247
243 dev_dbg_stamp(dev); 248 dev_dbg_stamp(dev);
244 249 if (enabled)
245 bfin_rtc_sync_pending(dev);
246
247 switch (cmd) {
248 case RTC_UIE_ON:
249 dev_dbg_stamp(dev);
250 bfin_rtc_int_set(RTC_ISTAT_SEC);
251 break;
252 case RTC_UIE_OFF:
253 dev_dbg_stamp(dev);
254 bfin_rtc_int_clear(~RTC_ISTAT_SEC);
255 break;
256
257 case RTC_AIE_ON:
258 dev_dbg_stamp(dev);
259 bfin_rtc_int_set_alarm(rtc); 250 bfin_rtc_int_set_alarm(rtc);
260 break; 251 else
261 case RTC_AIE_OFF:
262 dev_dbg_stamp(dev);
263 bfin_rtc_int_clear(~(RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY)); 252 bfin_rtc_int_clear(~(RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY));
264 break;
265 253
266 default: 254 return 0;
267 dev_dbg_stamp(dev);
268 ret = -ENOIOCTLCMD;
269 }
270
271 return ret;
272} 255}
273 256
274static int bfin_rtc_read_time(struct device *dev, struct rtc_time *tm) 257static int bfin_rtc_read_time(struct device *dev, struct rtc_time *tm)
@@ -351,12 +334,12 @@ static int bfin_rtc_proc(struct device *dev, struct seq_file *seq)
351} 334}
352 335
353static struct rtc_class_ops bfin_rtc_ops = { 336static struct rtc_class_ops bfin_rtc_ops = {
354 .ioctl = bfin_rtc_ioctl,
355 .read_time = bfin_rtc_read_time, 337 .read_time = bfin_rtc_read_time,
356 .set_time = bfin_rtc_set_time, 338 .set_time = bfin_rtc_set_time,
357 .read_alarm = bfin_rtc_read_alarm, 339 .read_alarm = bfin_rtc_read_alarm,
358 .set_alarm = bfin_rtc_set_alarm, 340 .set_alarm = bfin_rtc_set_alarm,
359 .proc = bfin_rtc_proc, 341 .proc = bfin_rtc_proc,
342 .alarm_irq_enable = bfin_rtc_alarm_irq_enable,
360}; 343};
361 344
362static int __devinit bfin_rtc_probe(struct platform_device *pdev) 345static int __devinit bfin_rtc_probe(struct platform_device *pdev)
@@ -422,9 +405,13 @@ static int __devexit bfin_rtc_remove(struct platform_device *pdev)
422#ifdef CONFIG_PM 405#ifdef CONFIG_PM
423static int bfin_rtc_suspend(struct platform_device *pdev, pm_message_t state) 406static int bfin_rtc_suspend(struct platform_device *pdev, pm_message_t state)
424{ 407{
425 if (device_may_wakeup(&pdev->dev)) { 408 struct device *dev = &pdev->dev;
409
410 dev_dbg_stamp(dev);
411
412 if (device_may_wakeup(dev)) {
426 enable_irq_wake(IRQ_RTC); 413 enable_irq_wake(IRQ_RTC);
427 bfin_rtc_sync_pending(&pdev->dev); 414 bfin_rtc_sync_pending(dev);
428 } else 415 } else
429 bfin_rtc_int_clear(0); 416 bfin_rtc_int_clear(0);
430 417
@@ -433,7 +420,11 @@ static int bfin_rtc_suspend(struct platform_device *pdev, pm_message_t state)
433 420
434static int bfin_rtc_resume(struct platform_device *pdev) 421static int bfin_rtc_resume(struct platform_device *pdev)
435{ 422{
436 if (device_may_wakeup(&pdev->dev)) 423 struct device *dev = &pdev->dev;
424
425 dev_dbg_stamp(dev);
426
427 if (device_may_wakeup(dev))
437 disable_irq_wake(IRQ_RTC); 428 disable_irq_wake(IRQ_RTC);
438 429
439 /* 430 /*