Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Revert "drivers/rtc/rtc-at91rm9200.c: use a variable for storing IMR"

This reverts commit 0ef1594c017521ea89278e80fe3f80dafb17abde.

This patch introduced a few races which cannot be easily fixed with a
small follow-up patch. Furthermore, the SoC with the broken hardware
register, which this patch intended to add support for, can only be used
with device trees, which this driver currently does not support.

[ Here is the discussion that led to this "revert" patch:
https://lkml.org/lkml/2013/4/3/176 ]

Cc: stable <stable@vger.kernel.org>
Signed-off-by: Johan Hovold <jhovold@gmail.com>
Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Johan Hovold and committed by
Linus Torvalds
e24b0bfa c4c80f63

+20 -31
+19 -31
drivers/rtc/rtc-at91rm9200.c
··· 44 44 static unsigned int at91_alarm_year = AT91_RTC_EPOCH; 45 45 static void __iomem *at91_rtc_regs; 46 46 static int irq; 47 - static u32 at91_rtc_imr; 48 47 49 48 /* 50 49 * Decode time/date into rtc_time structure ··· 108 109 cr = at91_rtc_read(AT91_RTC_CR); 109 110 at91_rtc_write(AT91_RTC_CR, cr | AT91_RTC_UPDCAL | AT91_RTC_UPDTIM); 110 111 111 - at91_rtc_imr |= AT91_RTC_ACKUPD; 112 112 at91_rtc_write(AT91_RTC_IER, AT91_RTC_ACKUPD); 113 113 wait_for_completion(&at91_rtc_updated); /* wait for ACKUPD interrupt */ 114 114 at91_rtc_write(AT91_RTC_IDR, AT91_RTC_ACKUPD); 115 - at91_rtc_imr &= ~AT91_RTC_ACKUPD; 116 115 117 116 at91_rtc_write(AT91_RTC_TIMR, 118 117 bin2bcd(tm->tm_sec) << 0 ··· 142 145 tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year); 143 146 tm->tm_year = at91_alarm_year - 1900; 144 147 145 - alrm->enabled = (at91_rtc_imr & AT91_RTC_ALARM) 148 + alrm->enabled = (at91_rtc_read(AT91_RTC_IMR) & AT91_RTC_ALARM) 146 149 ? 1 : 0; 147 150 148 151 dev_dbg(dev, "%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __func__, ··· 168 171 tm.tm_sec = alrm->time.tm_sec; 169 172 170 173 at91_rtc_write(AT91_RTC_IDR, AT91_RTC_ALARM); 171 - at91_rtc_imr &= ~AT91_RTC_ALARM; 172 174 at91_rtc_write(AT91_RTC_TIMALR, 173 175 bin2bcd(tm.tm_sec) << 0 174 176 | bin2bcd(tm.tm_min) << 8 ··· 180 184 181 185 if (alrm->enabled) { 182 186 at91_rtc_write(AT91_RTC_SCCR, AT91_RTC_ALARM); 183 - at91_rtc_imr |= AT91_RTC_ALARM; 184 187 at91_rtc_write(AT91_RTC_IER, AT91_RTC_ALARM); 185 188 } 186 189 ··· 196 201 197 202 if (enabled) { 198 203 at91_rtc_write(AT91_RTC_SCCR, AT91_RTC_ALARM); 199 - at91_rtc_imr |= AT91_RTC_ALARM; 200 204 at91_rtc_write(AT91_RTC_IER, AT91_RTC_ALARM); 201 - } else { 205 + } else 202 206 at91_rtc_write(AT91_RTC_IDR, AT91_RTC_ALARM); 203 - at91_rtc_imr &= ~AT91_RTC_ALARM; 204 - } 205 207 206 208 return 0; 207 209 } ··· 207 215 */ 208 216 static int at91_rtc_proc(struct device *dev, struct seq_file *seq) 209 217 { 218 + unsigned long imr = at91_rtc_read(AT91_RTC_IMR); 219 + 210 220 seq_printf(seq, "update_IRQ\t: %s\n", 211 - (at91_rtc_imr & AT91_RTC_ACKUPD) ? "yes" : "no"); 221 + (imr & AT91_RTC_ACKUPD) ? "yes" : "no"); 212 222 seq_printf(seq, "periodic_IRQ\t: %s\n", 213 - (at91_rtc_imr & AT91_RTC_SECEV) ? "yes" : "no"); 223 + (imr & AT91_RTC_SECEV) ? "yes" : "no"); 214 224 215 225 return 0; 216 226 } ··· 227 233 unsigned int rtsr; 228 234 unsigned long events = 0; 229 235 230 - rtsr = at91_rtc_read(AT91_RTC_SR) & at91_rtc_imr; 236 + rtsr = at91_rtc_read(AT91_RTC_SR) & at91_rtc_read(AT91_RTC_IMR); 231 237 if (rtsr) { /* this interrupt is shared! Is it ours? */ 232 238 if (rtsr & AT91_RTC_ALARM) 233 239 events |= (RTC_AF | RTC_IRQF); ··· 291 297 at91_rtc_write(AT91_RTC_IDR, AT91_RTC_ACKUPD | AT91_RTC_ALARM | 292 298 AT91_RTC_SECEV | AT91_RTC_TIMEV | 293 299 AT91_RTC_CALEV); 294 - at91_rtc_imr = 0; 295 300 296 301 ret = request_irq(irq, at91_rtc_interrupt, 297 302 IRQF_SHARED, ··· 329 336 at91_rtc_write(AT91_RTC_IDR, AT91_RTC_ACKUPD | AT91_RTC_ALARM | 330 337 AT91_RTC_SECEV | AT91_RTC_TIMEV | 331 338 AT91_RTC_CALEV); 332 - at91_rtc_imr = 0; 333 339 free_irq(irq, pdev); 334 340 335 341 rtc_device_unregister(rtc); ··· 341 349 342 350 /* AT91RM9200 RTC Power management control */ 343 351 344 - static u32 at91_rtc_bkpimr; 345 - 352 + static u32 at91_rtc_imr; 346 353 347 354 static int at91_rtc_suspend(struct device *dev) 348 355 { 349 356 /* this IRQ is shared with DBGU and other hardware which isn't 350 357 * necessarily doing PM like we are... 351 358 */ 352 - at91_rtc_bkpimr = at91_rtc_imr & (AT91_RTC_ALARM|AT91_RTC_SECEV); 353 - if (at91_rtc_bkpimr) { 354 - if (device_may_wakeup(dev)) { 359 + at91_rtc_imr = at91_rtc_read(AT91_RTC_IMR) 360 + & (AT91_RTC_ALARM|AT91_RTC_SECEV); 361 + if (at91_rtc_imr) { 362 + if (device_may_wakeup(dev)) 355 363 enable_irq_wake(irq); 356 - } else { 357 - at91_rtc_write(AT91_RTC_IDR, at91_rtc_bkpimr); 358 - at91_rtc_imr &= ~at91_rtc_bkpimr; 359 - } 360 - } 364 + else 365 + at91_rtc_write(AT91_RTC_IDR, at91_rtc_imr); 366 + } 361 367 return 0; 362 368 } 363 369 364 370 static int at91_rtc_resume(struct device *dev) 365 371 { 366 - if (at91_rtc_bkpimr) { 367 - if (device_may_wakeup(dev)) { 372 + if (at91_rtc_imr) { 373 + if (device_may_wakeup(dev)) 368 374 disable_irq_wake(irq); 369 - } else { 370 - at91_rtc_imr |= at91_rtc_bkpimr; 371 - at91_rtc_write(AT91_RTC_IER, at91_rtc_bkpimr); 372 - } 375 + else 376 + at91_rtc_write(AT91_RTC_IER, at91_rtc_imr); 373 377 } 374 378 return 0; 375 379 }
+1
drivers/rtc/rtc-at91rm9200.h
··· 64 64 #define AT91_RTC_SCCR 0x1c /* Status Clear Command Register */ 65 65 #define AT91_RTC_IER 0x20 /* Interrupt Enable Register */ 66 66 #define AT91_RTC_IDR 0x24 /* Interrupt Disable Register */ 67 + #define AT91_RTC_IMR 0x28 /* Interrupt Mask Register */ 67 68 68 69 #define AT91_RTC_VER 0x2c /* Valid Entry Register */ 69 70 #define AT91_RTC_NVTIM (1 << 0) /* Non valid Time */