rtc: Add drivers/rtc/rtc-mrst.c

Provide the standard kernel rtc driver interface on top of the vrtc layer
added in the previous patch.

Signed-off-by: Feng Tang <feng.tang@intel.com>
LKML-Reference: <20101110172911.3311.20593.stgit@localhost.localdomain>
[Fixed swapped arguments on IPC]
Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
[Cleaned up and the device creation moved to arch/x86/platform]
Signed-off-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

authored by

Feng Tang and committed by
Thomas Gleixner
0146f261 7309282c

+637
+46
arch/x86/platform/mrst/vrtc.c
··· 20 #include <linux/kernel.h> 21 #include <linux/init.h> 22 #include <linux/sfi.h> 23 24 #include <asm/mrst.h> 25 #include <asm/mrst-vrtc.h> ··· 119 x86_platform.get_wallclock = vrtc_get_time; 120 x86_platform.set_wallclock = vrtc_set_mmss; 121 }
··· 20 #include <linux/kernel.h> 21 #include <linux/init.h> 22 #include <linux/sfi.h> 23 + #include <linux/platform_device.h> 24 25 #include <asm/mrst.h> 26 #include <asm/mrst-vrtc.h> ··· 118 x86_platform.get_wallclock = vrtc_get_time; 119 x86_platform.set_wallclock = vrtc_set_mmss; 120 } 121 + 122 + /* 123 + * The Moorestown platform has a memory mapped virtual RTC device that emulates 124 + * the programming interface of the RTC. 125 + */ 126 + 127 + static struct resource vrtc_resources[] = { 128 + [0] = { 129 + .flags = IORESOURCE_MEM, 130 + }, 131 + [1] = { 132 + .flags = IORESOURCE_IRQ, 133 + } 134 + }; 135 + 136 + static struct platform_device vrtc_device = { 137 + .name = "rtc_mrst", 138 + .id = -1, 139 + .resource = vrtc_resources, 140 + .num_resources = ARRAY_SIZE(vrtc_resources), 141 + }; 142 + 143 + /* Register the RTC device if appropriate */ 144 + static int __init mrst_device_create(void) 145 + { 146 + /* No Moorestown, no device */ 147 + if (!mrst_identify_cpu()) 148 + return -ENODEV; 149 + /* No timer, no device */ 150 + if (!sfi_mrtc_num) 151 + return -ENODEV; 152 + 153 + /* iomem resource */ 154 + vrtc_resources[0].start = sfi_mrtc_array[0].phys_addr; 155 + vrtc_resources[0].end = sfi_mrtc_array[0].phys_addr + 156 + MRST_VRTC_MAP_SZ; 157 + /* irq resource */ 158 + vrtc_resources[1].start = sfi_mrtc_array[0].irq; 159 + vrtc_resources[1].end = sfi_mrtc_array[0].irq; 160 + 161 + platform_device_register(&vrtc_device); 162 + return 0; 163 + } 164 + 165 + module_init(mrst_device_create);
+12
drivers/rtc/Kconfig
··· 463 This driver can also be built as a module. If so, the module 464 will be called rtc-cmos. 465 466 config RTC_DRV_DS1216 467 tristate "Dallas DS1216" 468 depends on SNI_RM
··· 463 This driver can also be built as a module. If so, the module 464 will be called rtc-cmos. 465 466 + config RTC_DRV_VRTC 467 + tristate "Virtual RTC for Moorestown platforms" 468 + depends on X86_MRST 469 + default y if X86_MRST 470 + 471 + help 472 + Say "yes" here to get direct support for the real time clock 473 + found on Moorestown platforms. The VRTC is a emulated RTC that 474 + derives its clock source from a real RTC in the PMIC. The MC146818 475 + style programming interface is mostly conserved, but any 476 + updates are done via IPC calls to the system controller FW. 477 + 478 config RTC_DRV_DS1216 479 tristate "Dallas DS1216" 480 depends on SNI_RM
+1
drivers/rtc/Makefile
··· 30 obj-$(CONFIG_RTC_DRV_COH901331) += rtc-coh901331.o 31 obj-$(CONFIG_RTC_DRV_DAVINCI) += rtc-davinci.o 32 obj-$(CONFIG_RTC_DRV_DM355EVM) += rtc-dm355evm.o 33 obj-$(CONFIG_RTC_DRV_DS1216) += rtc-ds1216.o 34 obj-$(CONFIG_RTC_DRV_DS1286) += rtc-ds1286.o 35 obj-$(CONFIG_RTC_DRV_DS1302) += rtc-ds1302.o
··· 30 obj-$(CONFIG_RTC_DRV_COH901331) += rtc-coh901331.o 31 obj-$(CONFIG_RTC_DRV_DAVINCI) += rtc-davinci.o 32 obj-$(CONFIG_RTC_DRV_DM355EVM) += rtc-dm355evm.o 33 + obj-$(CONFIG_RTC_DRV_VRTC) += rtc-mrst.o 34 obj-$(CONFIG_RTC_DRV_DS1216) += rtc-ds1216.o 35 obj-$(CONFIG_RTC_DRV_DS1286) += rtc-ds1286.o 36 obj-$(CONFIG_RTC_DRV_DS1302) += rtc-ds1302.o
+578
drivers/rtc/rtc-mrst.c
···
··· 1 + /* 2 + * rtc-mrst.c: Driver for Moorestown virtual RTC 3 + * 4 + * (C) Copyright 2009 Intel Corporation 5 + * Author: Jacob Pan (jacob.jun.pan@intel.com) 6 + * Feng Tang (feng.tang@intel.com) 7 + * 8 + * This program is free software; you can redistribute it and/or 9 + * modify it under the terms of the GNU General Public License 10 + * as published by the Free Software Foundation; version 2 11 + * of the License. 12 + * 13 + * Note: 14 + * VRTC is emulated by system controller firmware, the real HW 15 + * RTC is located in the PMIC device. SCU FW shadows PMIC RTC 16 + * in a memory mapped IO space that is visible to the host IA 17 + * processor. 18 + * 19 + * This driver is based upon drivers/rtc/rtc-cmos.c 20 + */ 21 + 22 + /* 23 + * Note: 24 + * * vRTC only supports binary mode and 24H mode 25 + * * vRTC only support PIE and AIE, no UIE, and its PIE only happens 26 + * at 23:59:59pm everyday, no support for adjustable frequency 27 + * * Alarm function is also limited to hr/min/sec. 28 + */ 29 + 30 + #include <linux/mod_devicetable.h> 31 + #include <linux/platform_device.h> 32 + #include <linux/interrupt.h> 33 + #include <linux/spinlock.h> 34 + #include <linux/kernel.h> 35 + #include <linux/module.h> 36 + #include <linux/init.h> 37 + #include <linux/sfi.h> 38 + 39 + #include <asm-generic/rtc.h> 40 + #include <asm/intel_scu_ipc.h> 41 + #include <asm/mrst.h> 42 + #include <asm/mrst-vrtc.h> 43 + 44 + struct mrst_rtc { 45 + struct rtc_device *rtc; 46 + struct device *dev; 47 + int irq; 48 + struct resource *iomem; 49 + 50 + u8 enabled_wake; 51 + u8 suspend_ctrl; 52 + }; 53 + 54 + static const char driver_name[] = "rtc_mrst"; 55 + 56 + #define RTC_IRQMASK (RTC_PF | RTC_AF) 57 + 58 + static inline int is_intr(u8 rtc_intr) 59 + { 60 + if (!(rtc_intr & RTC_IRQF)) 61 + return 0; 62 + return rtc_intr & RTC_IRQMASK; 63 + } 64 + 65 + /* 66 + * rtc_time's year contains the increment over 1900, but vRTC's YEAR 67 + * register can't be programmed to value larger than 0x64, so vRTC 68 + * driver chose to use 1960 (1970 is UNIX time start point) as the base, 69 + * and does the translation at read/write time 70 + */ 71 + static int mrst_read_time(struct device *dev, struct rtc_time *time) 72 + { 73 + unsigned long flags; 74 + 75 + if (rtc_is_updating()) 76 + mdelay(20); 77 + 78 + spin_lock_irqsave(&rtc_lock, flags); 79 + time->tm_sec = vrtc_cmos_read(RTC_SECONDS); 80 + time->tm_min = vrtc_cmos_read(RTC_MINUTES); 81 + time->tm_hour = vrtc_cmos_read(RTC_HOURS); 82 + time->tm_mday = vrtc_cmos_read(RTC_DAY_OF_MONTH); 83 + time->tm_mon = vrtc_cmos_read(RTC_MONTH); 84 + time->tm_year = vrtc_cmos_read(RTC_YEAR); 85 + spin_unlock_irqrestore(&rtc_lock, flags); 86 + 87 + /* Adjust for the 1960/1900 */ 88 + time->tm_year += 60; 89 + time->tm_mon--; 90 + return RTC_24H; 91 + } 92 + 93 + static int mrst_set_time(struct device *dev, struct rtc_time *time) 94 + { 95 + int ret; 96 + unsigned long flags; 97 + unsigned char mon, day, hrs, min, sec; 98 + unsigned int yrs; 99 + 100 + yrs = time->tm_year; 101 + mon = time->tm_mon + 1; /* tm_mon starts at zero */ 102 + day = time->tm_mday; 103 + hrs = time->tm_hour; 104 + min = time->tm_min; 105 + sec = time->tm_sec; 106 + 107 + if (yrs < 70 || yrs > 138) 108 + return -EINVAL; 109 + yrs -= 60; 110 + 111 + spin_lock_irqsave(&rtc_lock, flags); 112 + 113 + vrtc_cmos_write(yrs, RTC_YEAR); 114 + vrtc_cmos_write(mon, RTC_MONTH); 115 + vrtc_cmos_write(day, RTC_DAY_OF_MONTH); 116 + vrtc_cmos_write(hrs, RTC_HOURS); 117 + vrtc_cmos_write(min, RTC_MINUTES); 118 + vrtc_cmos_write(sec, RTC_SECONDS); 119 + 120 + spin_unlock_irqrestore(&rtc_lock, flags); 121 + 122 + ret = intel_scu_ipc_simple_command(IPCMSG_VRTC, IPC_CMD_VRTC_SETTIME); 123 + return ret; 124 + } 125 + 126 + static int mrst_read_alarm(struct device *dev, struct rtc_wkalrm *t) 127 + { 128 + struct mrst_rtc *mrst = dev_get_drvdata(dev); 129 + unsigned char rtc_control; 130 + 131 + if (mrst->irq <= 0) 132 + return -EIO; 133 + 134 + /* Basic alarms only support hour, minute, and seconds fields. 135 + * Some also support day and month, for alarms up to a year in 136 + * the future. 137 + */ 138 + t->time.tm_mday = -1; 139 + t->time.tm_mon = -1; 140 + t->time.tm_year = -1; 141 + 142 + /* vRTC only supports binary mode */ 143 + spin_lock_irq(&rtc_lock); 144 + t->time.tm_sec = vrtc_cmos_read(RTC_SECONDS_ALARM); 145 + t->time.tm_min = vrtc_cmos_read(RTC_MINUTES_ALARM); 146 + t->time.tm_hour = vrtc_cmos_read(RTC_HOURS_ALARM); 147 + 148 + rtc_control = vrtc_cmos_read(RTC_CONTROL); 149 + spin_unlock_irq(&rtc_lock); 150 + 151 + t->enabled = !!(rtc_control & RTC_AIE); 152 + t->pending = 0; 153 + 154 + return 0; 155 + } 156 + 157 + static void mrst_checkintr(struct mrst_rtc *mrst, unsigned char rtc_control) 158 + { 159 + unsigned char rtc_intr; 160 + 161 + /* 162 + * NOTE after changing RTC_xIE bits we always read INTR_FLAGS; 163 + * allegedly some older rtcs need that to handle irqs properly 164 + */ 165 + rtc_intr = vrtc_cmos_read(RTC_INTR_FLAGS); 166 + rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF; 167 + if (is_intr(rtc_intr)) 168 + rtc_update_irq(mrst->rtc, 1, rtc_intr); 169 + } 170 + 171 + static void mrst_irq_enable(struct mrst_rtc *mrst, unsigned char mask) 172 + { 173 + unsigned char rtc_control; 174 + 175 + /* 176 + * Flush any pending IRQ status, notably for update irqs, 177 + * before we enable new IRQs 178 + */ 179 + rtc_control = vrtc_cmos_read(RTC_CONTROL); 180 + mrst_checkintr(mrst, rtc_control); 181 + 182 + rtc_control |= mask; 183 + vrtc_cmos_write(rtc_control, RTC_CONTROL); 184 + 185 + mrst_checkintr(mrst, rtc_control); 186 + } 187 + 188 + static void mrst_irq_disable(struct mrst_rtc *mrst, unsigned char mask) 189 + { 190 + unsigned char rtc_control; 191 + 192 + rtc_control = vrtc_cmos_read(RTC_CONTROL); 193 + rtc_control &= ~mask; 194 + vrtc_cmos_write(rtc_control, RTC_CONTROL); 195 + mrst_checkintr(mrst, rtc_control); 196 + } 197 + 198 + static int mrst_set_alarm(struct device *dev, struct rtc_wkalrm *t) 199 + { 200 + struct mrst_rtc *mrst = dev_get_drvdata(dev); 201 + unsigned char hrs, min, sec; 202 + int ret = 0; 203 + 204 + if (!mrst->irq) 205 + return -EIO; 206 + 207 + hrs = t->time.tm_hour; 208 + min = t->time.tm_min; 209 + sec = t->time.tm_sec; 210 + 211 + spin_lock_irq(&rtc_lock); 212 + /* Next rtc irq must not be from previous alarm setting */ 213 + mrst_irq_disable(mrst, RTC_AIE); 214 + 215 + /* Update alarm */ 216 + vrtc_cmos_write(hrs, RTC_HOURS_ALARM); 217 + vrtc_cmos_write(min, RTC_MINUTES_ALARM); 218 + vrtc_cmos_write(sec, RTC_SECONDS_ALARM); 219 + 220 + spin_unlock_irq(&rtc_lock); 221 + 222 + ret = intel_scu_ipc_simple_command(IPCMSG_VRTC, IPC_CMD_VRTC_SETALARM); 223 + if (ret) 224 + return ret; 225 + 226 + spin_lock_irq(&rtc_lock); 227 + if (t->enabled) 228 + mrst_irq_enable(mrst, RTC_AIE); 229 + 230 + spin_unlock_irq(&rtc_lock); 231 + 232 + return 0; 233 + } 234 + 235 + static int mrst_irq_set_state(struct device *dev, int enabled) 236 + { 237 + struct mrst_rtc *mrst = dev_get_drvdata(dev); 238 + unsigned long flags; 239 + 240 + if (!mrst->irq) 241 + return -ENXIO; 242 + 243 + spin_lock_irqsave(&rtc_lock, flags); 244 + 245 + if (enabled) 246 + mrst_irq_enable(mrst, RTC_PIE); 247 + else 248 + mrst_irq_disable(mrst, RTC_PIE); 249 + 250 + spin_unlock_irqrestore(&rtc_lock, flags); 251 + return 0; 252 + } 253 + 254 + #if defined(CONFIG_RTC_INTF_DEV) || defined(CONFIG_RTC_INTF_DEV_MODULE) 255 + 256 + /* Currently, the vRTC doesn't support UIE ON/OFF */ 257 + static int 258 + mrst_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) 259 + { 260 + struct mrst_rtc *mrst = dev_get_drvdata(dev); 261 + unsigned long flags; 262 + 263 + switch (cmd) { 264 + case RTC_AIE_OFF: 265 + case RTC_AIE_ON: 266 + if (!mrst->irq) 267 + return -EINVAL; 268 + break; 269 + default: 270 + /* PIE ON/OFF is handled by mrst_irq_set_state() */ 271 + return -ENOIOCTLCMD; 272 + } 273 + 274 + spin_lock_irqsave(&rtc_lock, flags); 275 + switch (cmd) { 276 + case RTC_AIE_OFF: /* alarm off */ 277 + mrst_irq_disable(mrst, RTC_AIE); 278 + break; 279 + case RTC_AIE_ON: /* alarm on */ 280 + mrst_irq_enable(mrst, RTC_AIE); 281 + break; 282 + } 283 + spin_unlock_irqrestore(&rtc_lock, flags); 284 + return 0; 285 + } 286 + 287 + #else 288 + #define mrst_rtc_ioctl NULL 289 + #endif 290 + 291 + #if defined(CONFIG_RTC_INTF_PROC) || defined(CONFIG_RTC_INTF_PROC_MODULE) 292 + 293 + static int mrst_procfs(struct device *dev, struct seq_file *seq) 294 + { 295 + unsigned char rtc_control, valid; 296 + 297 + spin_lock_irq(&rtc_lock); 298 + rtc_control = vrtc_cmos_read(RTC_CONTROL); 299 + valid = vrtc_cmos_read(RTC_VALID); 300 + spin_unlock_irq(&rtc_lock); 301 + 302 + return seq_printf(seq, 303 + "periodic_IRQ\t: %s\n" 304 + "alarm\t\t: %s\n" 305 + "BCD\t\t: no\n" 306 + "periodic_freq\t: daily (not adjustable)\n", 307 + (rtc_control & RTC_PIE) ? "on" : "off", 308 + (rtc_control & RTC_AIE) ? "on" : "off"); 309 + } 310 + 311 + #else 312 + #define mrst_procfs NULL 313 + #endif 314 + 315 + static const struct rtc_class_ops mrst_rtc_ops = { 316 + .ioctl = mrst_rtc_ioctl, 317 + .read_time = mrst_read_time, 318 + .set_time = mrst_set_time, 319 + .read_alarm = mrst_read_alarm, 320 + .set_alarm = mrst_set_alarm, 321 + .proc = mrst_procfs, 322 + .irq_set_state = mrst_irq_set_state, 323 + }; 324 + 325 + static struct mrst_rtc mrst_rtc; 326 + 327 + /* 328 + * When vRTC IRQ is captured by SCU FW, FW will clear the AIE bit in 329 + * Reg B, so no need for this driver to clear it 330 + */ 331 + static irqreturn_t mrst_rtc_irq(int irq, void *p) 332 + { 333 + u8 irqstat; 334 + 335 + spin_lock(&rtc_lock); 336 + /* This read will clear all IRQ flags inside Reg C */ 337 + irqstat = vrtc_cmos_read(RTC_INTR_FLAGS); 338 + spin_unlock(&rtc_lock); 339 + 340 + irqstat &= RTC_IRQMASK | RTC_IRQF; 341 + if (is_intr(irqstat)) { 342 + rtc_update_irq(p, 1, irqstat); 343 + return IRQ_HANDLED; 344 + } 345 + return IRQ_NONE; 346 + } 347 + 348 + static int __init 349 + vrtc_mrst_do_probe(struct device *dev, struct resource *iomem, int rtc_irq) 350 + { 351 + int retval = 0; 352 + unsigned char rtc_control; 353 + 354 + /* There can be only one ... */ 355 + if (mrst_rtc.dev) 356 + return -EBUSY; 357 + 358 + if (!iomem) 359 + return -ENODEV; 360 + 361 + iomem = request_mem_region(iomem->start, 362 + iomem->end + 1 - iomem->start, 363 + driver_name); 364 + if (!iomem) { 365 + dev_dbg(dev, "i/o mem already in use.\n"); 366 + return -EBUSY; 367 + } 368 + 369 + mrst_rtc.irq = rtc_irq; 370 + mrst_rtc.iomem = iomem; 371 + 372 + mrst_rtc.rtc = rtc_device_register(driver_name, dev, 373 + &mrst_rtc_ops, THIS_MODULE); 374 + if (IS_ERR(mrst_rtc.rtc)) { 375 + retval = PTR_ERR(mrst_rtc.rtc); 376 + goto cleanup0; 377 + } 378 + 379 + mrst_rtc.dev = dev; 380 + dev_set_drvdata(dev, &mrst_rtc); 381 + rename_region(iomem, dev_name(&mrst_rtc.rtc->dev)); 382 + 383 + spin_lock_irq(&rtc_lock); 384 + mrst_irq_disable(&mrst_rtc, RTC_PIE | RTC_AIE); 385 + rtc_control = vrtc_cmos_read(RTC_CONTROL); 386 + spin_unlock_irq(&rtc_lock); 387 + 388 + if (!(rtc_control & RTC_24H) || (rtc_control & (RTC_DM_BINARY))) 389 + dev_dbg(dev, "TODO: support more than 24-hr BCD mode\n"); 390 + 391 + if (rtc_irq) { 392 + retval = request_irq(rtc_irq, mrst_rtc_irq, 393 + IRQF_DISABLED, dev_name(&mrst_rtc.rtc->dev), 394 + mrst_rtc.rtc); 395 + if (retval < 0) { 396 + dev_dbg(dev, "IRQ %d is already in use, err %d\n", 397 + rtc_irq, retval); 398 + goto cleanup1; 399 + } 400 + } 401 + dev_dbg(dev, "initialised\n"); 402 + return 0; 403 + 404 + cleanup1: 405 + mrst_rtc.dev = NULL; 406 + rtc_device_unregister(mrst_rtc.rtc); 407 + cleanup0: 408 + release_region(iomem->start, iomem->end + 1 - iomem->start); 409 + dev_err(dev, "rtc-mrst: unable to initialise\n"); 410 + return retval; 411 + } 412 + 413 + static void rtc_mrst_do_shutdown(void) 414 + { 415 + spin_lock_irq(&rtc_lock); 416 + mrst_irq_disable(&mrst_rtc, RTC_IRQMASK); 417 + spin_unlock_irq(&rtc_lock); 418 + } 419 + 420 + static void __exit rtc_mrst_do_remove(struct device *dev) 421 + { 422 + struct mrst_rtc *mrst = dev_get_drvdata(dev); 423 + struct resource *iomem; 424 + 425 + rtc_mrst_do_shutdown(); 426 + 427 + if (mrst->irq) 428 + free_irq(mrst->irq, mrst->rtc); 429 + 430 + rtc_device_unregister(mrst->rtc); 431 + mrst->rtc = NULL; 432 + 433 + iomem = mrst->iomem; 434 + release_region(iomem->start, iomem->end + 1 - iomem->start); 435 + mrst->iomem = NULL; 436 + 437 + mrst->dev = NULL; 438 + dev_set_drvdata(dev, NULL); 439 + } 440 + 441 + #ifdef CONFIG_PM 442 + static int mrst_suspend(struct device *dev, pm_message_t mesg) 443 + { 444 + struct mrst_rtc *mrst = dev_get_drvdata(dev); 445 + unsigned char tmp; 446 + 447 + /* Only the alarm might be a wakeup event source */ 448 + spin_lock_irq(&rtc_lock); 449 + mrst->suspend_ctrl = tmp = vrtc_cmos_read(RTC_CONTROL); 450 + if (tmp & (RTC_PIE | RTC_AIE)) { 451 + unsigned char mask; 452 + 453 + if (device_may_wakeup(dev)) 454 + mask = RTC_IRQMASK & ~RTC_AIE; 455 + else 456 + mask = RTC_IRQMASK; 457 + tmp &= ~mask; 458 + vrtc_cmos_write(tmp, RTC_CONTROL); 459 + 460 + mrst_checkintr(mrst, tmp); 461 + } 462 + spin_unlock_irq(&rtc_lock); 463 + 464 + if (tmp & RTC_AIE) { 465 + mrst->enabled_wake = 1; 466 + enable_irq_wake(mrst->irq); 467 + } 468 + 469 + dev_dbg(&mrst_rtc.rtc->dev, "suspend%s, ctrl %02x\n", 470 + (tmp & RTC_AIE) ? ", alarm may wake" : "", 471 + tmp); 472 + 473 + return 0; 474 + } 475 + 476 + /* 477 + * We want RTC alarms to wake us from the deep power saving state 478 + */ 479 + static inline int mrst_poweroff(struct device *dev) 480 + { 481 + return mrst_suspend(dev, PMSG_HIBERNATE); 482 + } 483 + 484 + static int mrst_resume(struct device *dev) 485 + { 486 + struct mrst_rtc *mrst = dev_get_drvdata(dev); 487 + unsigned char tmp = mrst->suspend_ctrl; 488 + 489 + /* Re-enable any irqs previously active */ 490 + if (tmp & RTC_IRQMASK) { 491 + unsigned char mask; 492 + 493 + if (mrst->enabled_wake) { 494 + disable_irq_wake(mrst->irq); 495 + mrst->enabled_wake = 0; 496 + } 497 + 498 + spin_lock_irq(&rtc_lock); 499 + do { 500 + vrtc_cmos_write(tmp, RTC_CONTROL); 501 + 502 + mask = vrtc_cmos_read(RTC_INTR_FLAGS); 503 + mask &= (tmp & RTC_IRQMASK) | RTC_IRQF; 504 + if (!is_intr(mask)) 505 + break; 506 + 507 + rtc_update_irq(mrst->rtc, 1, mask); 508 + tmp &= ~RTC_AIE; 509 + } while (mask & RTC_AIE); 510 + spin_unlock_irq(&rtc_lock); 511 + } 512 + 513 + dev_dbg(&mrst_rtc.rtc->dev, "resume, ctrl %02x\n", tmp); 514 + 515 + return 0; 516 + } 517 + 518 + #else 519 + #define mrst_suspend NULL 520 + #define mrst_resume NULL 521 + 522 + static inline int mrst_poweroff(struct device *dev) 523 + { 524 + return -ENOSYS; 525 + } 526 + 527 + #endif 528 + 529 + static int __init vrtc_mrst_platform_probe(struct platform_device *pdev) 530 + { 531 + return vrtc_mrst_do_probe(&pdev->dev, 532 + platform_get_resource(pdev, IORESOURCE_MEM, 0), 533 + platform_get_irq(pdev, 0)); 534 + } 535 + 536 + static int __exit vrtc_mrst_platform_remove(struct platform_device *pdev) 537 + { 538 + rtc_mrst_do_remove(&pdev->dev); 539 + return 0; 540 + } 541 + 542 + static void vrtc_mrst_platform_shutdown(struct platform_device *pdev) 543 + { 544 + if (system_state == SYSTEM_POWER_OFF && !mrst_poweroff(&pdev->dev)) 545 + return; 546 + 547 + rtc_mrst_do_shutdown(); 548 + } 549 + 550 + MODULE_ALIAS("platform:vrtc_mrst"); 551 + 552 + static struct platform_driver vrtc_mrst_platform_driver = { 553 + .probe = vrtc_mrst_platform_probe, 554 + .remove = __exit_p(vrtc_mrst_platform_remove), 555 + .shutdown = vrtc_mrst_platform_shutdown, 556 + .driver = { 557 + .name = (char *) driver_name, 558 + .suspend = mrst_suspend, 559 + .resume = mrst_resume, 560 + } 561 + }; 562 + 563 + static int __init vrtc_mrst_init(void) 564 + { 565 + return platform_driver_register(&vrtc_mrst_platform_driver); 566 + } 567 + 568 + static void __exit vrtc_mrst_exit(void) 569 + { 570 + platform_driver_unregister(&vrtc_mrst_platform_driver); 571 + } 572 + 573 + module_init(vrtc_mrst_init); 574 + module_exit(vrtc_mrst_exit); 575 + 576 + MODULE_AUTHOR("Jacob Pan; Feng Tang"); 577 + MODULE_DESCRIPTION("Driver for Moorestown virtual RTC"); 578 + MODULE_LICENSE("GPL");