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

Configure Feed

Select the types of activity you want to include in your feed.

at 55fa6091d83160ca772fc37cebae45d42695a708 552 lines 13 kB view raw
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 44struct 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 54static const char driver_name[] = "rtc_mrst"; 55 56#define RTC_IRQMASK (RTC_PF | RTC_AF) 57 58static 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 65static inline unsigned char vrtc_is_updating(void) 66{ 67 unsigned char uip; 68 unsigned long flags; 69 70 spin_lock_irqsave(&rtc_lock, flags); 71 uip = (vrtc_cmos_read(RTC_FREQ_SELECT) & RTC_UIP); 72 spin_unlock_irqrestore(&rtc_lock, flags); 73 return uip; 74} 75 76/* 77 * rtc_time's year contains the increment over 1900, but vRTC's YEAR 78 * register can't be programmed to value larger than 0x64, so vRTC 79 * driver chose to use 1960 (1970 is UNIX time start point) as the base, 80 * and does the translation at read/write time. 81 * 82 * Why not just use 1970 as the offset? it's because using 1960 will 83 * make it consistent in leap year setting for both vrtc and low-level 84 * physical rtc devices. 85 */ 86static int mrst_read_time(struct device *dev, struct rtc_time *time) 87{ 88 unsigned long flags; 89 90 if (vrtc_is_updating()) 91 mdelay(20); 92 93 spin_lock_irqsave(&rtc_lock, flags); 94 time->tm_sec = vrtc_cmos_read(RTC_SECONDS); 95 time->tm_min = vrtc_cmos_read(RTC_MINUTES); 96 time->tm_hour = vrtc_cmos_read(RTC_HOURS); 97 time->tm_mday = vrtc_cmos_read(RTC_DAY_OF_MONTH); 98 time->tm_mon = vrtc_cmos_read(RTC_MONTH); 99 time->tm_year = vrtc_cmos_read(RTC_YEAR); 100 spin_unlock_irqrestore(&rtc_lock, flags); 101 102 /* Adjust for the 1960/1900 */ 103 time->tm_year += 60; 104 time->tm_mon--; 105 return RTC_24H; 106} 107 108static int mrst_set_time(struct device *dev, struct rtc_time *time) 109{ 110 int ret; 111 unsigned long flags; 112 unsigned char mon, day, hrs, min, sec; 113 unsigned int yrs; 114 115 yrs = time->tm_year; 116 mon = time->tm_mon + 1; /* tm_mon starts at zero */ 117 day = time->tm_mday; 118 hrs = time->tm_hour; 119 min = time->tm_min; 120 sec = time->tm_sec; 121 122 if (yrs < 70 || yrs > 138) 123 return -EINVAL; 124 yrs -= 60; 125 126 spin_lock_irqsave(&rtc_lock, flags); 127 128 vrtc_cmos_write(yrs, RTC_YEAR); 129 vrtc_cmos_write(mon, RTC_MONTH); 130 vrtc_cmos_write(day, RTC_DAY_OF_MONTH); 131 vrtc_cmos_write(hrs, RTC_HOURS); 132 vrtc_cmos_write(min, RTC_MINUTES); 133 vrtc_cmos_write(sec, RTC_SECONDS); 134 135 spin_unlock_irqrestore(&rtc_lock, flags); 136 137 ret = intel_scu_ipc_simple_command(IPCMSG_VRTC, IPC_CMD_VRTC_SETTIME); 138 return ret; 139} 140 141static int mrst_read_alarm(struct device *dev, struct rtc_wkalrm *t) 142{ 143 struct mrst_rtc *mrst = dev_get_drvdata(dev); 144 unsigned char rtc_control; 145 146 if (mrst->irq <= 0) 147 return -EIO; 148 149 /* Basic alarms only support hour, minute, and seconds fields. 150 * Some also support day and month, for alarms up to a year in 151 * the future. 152 */ 153 t->time.tm_mday = -1; 154 t->time.tm_mon = -1; 155 t->time.tm_year = -1; 156 157 /* vRTC only supports binary mode */ 158 spin_lock_irq(&rtc_lock); 159 t->time.tm_sec = vrtc_cmos_read(RTC_SECONDS_ALARM); 160 t->time.tm_min = vrtc_cmos_read(RTC_MINUTES_ALARM); 161 t->time.tm_hour = vrtc_cmos_read(RTC_HOURS_ALARM); 162 163 rtc_control = vrtc_cmos_read(RTC_CONTROL); 164 spin_unlock_irq(&rtc_lock); 165 166 t->enabled = !!(rtc_control & RTC_AIE); 167 t->pending = 0; 168 169 return 0; 170} 171 172static void mrst_checkintr(struct mrst_rtc *mrst, unsigned char rtc_control) 173{ 174 unsigned char rtc_intr; 175 176 /* 177 * NOTE after changing RTC_xIE bits we always read INTR_FLAGS; 178 * allegedly some older rtcs need that to handle irqs properly 179 */ 180 rtc_intr = vrtc_cmos_read(RTC_INTR_FLAGS); 181 rtc_intr &= (rtc_control & RTC_IRQMASK) | RTC_IRQF; 182 if (is_intr(rtc_intr)) 183 rtc_update_irq(mrst->rtc, 1, rtc_intr); 184} 185 186static void mrst_irq_enable(struct mrst_rtc *mrst, unsigned char mask) 187{ 188 unsigned char rtc_control; 189 190 /* 191 * Flush any pending IRQ status, notably for update irqs, 192 * before we enable new IRQs 193 */ 194 rtc_control = vrtc_cmos_read(RTC_CONTROL); 195 mrst_checkintr(mrst, rtc_control); 196 197 rtc_control |= mask; 198 vrtc_cmos_write(rtc_control, RTC_CONTROL); 199 200 mrst_checkintr(mrst, rtc_control); 201} 202 203static void mrst_irq_disable(struct mrst_rtc *mrst, unsigned char mask) 204{ 205 unsigned char rtc_control; 206 207 rtc_control = vrtc_cmos_read(RTC_CONTROL); 208 rtc_control &= ~mask; 209 vrtc_cmos_write(rtc_control, RTC_CONTROL); 210 mrst_checkintr(mrst, rtc_control); 211} 212 213static int mrst_set_alarm(struct device *dev, struct rtc_wkalrm *t) 214{ 215 struct mrst_rtc *mrst = dev_get_drvdata(dev); 216 unsigned char hrs, min, sec; 217 int ret = 0; 218 219 if (!mrst->irq) 220 return -EIO; 221 222 hrs = t->time.tm_hour; 223 min = t->time.tm_min; 224 sec = t->time.tm_sec; 225 226 spin_lock_irq(&rtc_lock); 227 /* Next rtc irq must not be from previous alarm setting */ 228 mrst_irq_disable(mrst, RTC_AIE); 229 230 /* Update alarm */ 231 vrtc_cmos_write(hrs, RTC_HOURS_ALARM); 232 vrtc_cmos_write(min, RTC_MINUTES_ALARM); 233 vrtc_cmos_write(sec, RTC_SECONDS_ALARM); 234 235 spin_unlock_irq(&rtc_lock); 236 237 ret = intel_scu_ipc_simple_command(IPCMSG_VRTC, IPC_CMD_VRTC_SETALARM); 238 if (ret) 239 return ret; 240 241 spin_lock_irq(&rtc_lock); 242 if (t->enabled) 243 mrst_irq_enable(mrst, RTC_AIE); 244 245 spin_unlock_irq(&rtc_lock); 246 247 return 0; 248} 249 250/* Currently, the vRTC doesn't support UIE ON/OFF */ 251static int mrst_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) 252{ 253 struct mrst_rtc *mrst = dev_get_drvdata(dev); 254 unsigned long flags; 255 256 spin_lock_irqsave(&rtc_lock, flags); 257 if (enabled) 258 mrst_irq_enable(mrst, RTC_AIE); 259 else 260 mrst_irq_disable(mrst, RTC_AIE); 261 spin_unlock_irqrestore(&rtc_lock, flags); 262 return 0; 263} 264 265 266#if defined(CONFIG_RTC_INTF_PROC) || defined(CONFIG_RTC_INTF_PROC_MODULE) 267 268static int mrst_procfs(struct device *dev, struct seq_file *seq) 269{ 270 unsigned char rtc_control, valid; 271 272 spin_lock_irq(&rtc_lock); 273 rtc_control = vrtc_cmos_read(RTC_CONTROL); 274 valid = vrtc_cmos_read(RTC_VALID); 275 spin_unlock_irq(&rtc_lock); 276 277 return seq_printf(seq, 278 "periodic_IRQ\t: %s\n" 279 "alarm\t\t: %s\n" 280 "BCD\t\t: no\n" 281 "periodic_freq\t: daily (not adjustable)\n", 282 (rtc_control & RTC_PIE) ? "on" : "off", 283 (rtc_control & RTC_AIE) ? "on" : "off"); 284} 285 286#else 287#define mrst_procfs NULL 288#endif 289 290static const struct rtc_class_ops mrst_rtc_ops = { 291 .read_time = mrst_read_time, 292 .set_time = mrst_set_time, 293 .read_alarm = mrst_read_alarm, 294 .set_alarm = mrst_set_alarm, 295 .proc = mrst_procfs, 296 .alarm_irq_enable = mrst_rtc_alarm_irq_enable, 297}; 298 299static struct mrst_rtc mrst_rtc; 300 301/* 302 * When vRTC IRQ is captured by SCU FW, FW will clear the AIE bit in 303 * Reg B, so no need for this driver to clear it 304 */ 305static irqreturn_t mrst_rtc_irq(int irq, void *p) 306{ 307 u8 irqstat; 308 309 spin_lock(&rtc_lock); 310 /* This read will clear all IRQ flags inside Reg C */ 311 irqstat = vrtc_cmos_read(RTC_INTR_FLAGS); 312 spin_unlock(&rtc_lock); 313 314 irqstat &= RTC_IRQMASK | RTC_IRQF; 315 if (is_intr(irqstat)) { 316 rtc_update_irq(p, 1, irqstat); 317 return IRQ_HANDLED; 318 } 319 return IRQ_NONE; 320} 321 322static int __init 323vrtc_mrst_do_probe(struct device *dev, struct resource *iomem, int rtc_irq) 324{ 325 int retval = 0; 326 unsigned char rtc_control; 327 328 /* There can be only one ... */ 329 if (mrst_rtc.dev) 330 return -EBUSY; 331 332 if (!iomem) 333 return -ENODEV; 334 335 iomem = request_mem_region(iomem->start, 336 iomem->end + 1 - iomem->start, 337 driver_name); 338 if (!iomem) { 339 dev_dbg(dev, "i/o mem already in use.\n"); 340 return -EBUSY; 341 } 342 343 mrst_rtc.irq = rtc_irq; 344 mrst_rtc.iomem = iomem; 345 346 mrst_rtc.rtc = rtc_device_register(driver_name, dev, 347 &mrst_rtc_ops, THIS_MODULE); 348 if (IS_ERR(mrst_rtc.rtc)) { 349 retval = PTR_ERR(mrst_rtc.rtc); 350 goto cleanup0; 351 } 352 353 mrst_rtc.dev = dev; 354 dev_set_drvdata(dev, &mrst_rtc); 355 rename_region(iomem, dev_name(&mrst_rtc.rtc->dev)); 356 357 spin_lock_irq(&rtc_lock); 358 mrst_irq_disable(&mrst_rtc, RTC_PIE | RTC_AIE); 359 rtc_control = vrtc_cmos_read(RTC_CONTROL); 360 spin_unlock_irq(&rtc_lock); 361 362 if (!(rtc_control & RTC_24H) || (rtc_control & (RTC_DM_BINARY))) 363 dev_dbg(dev, "TODO: support more than 24-hr BCD mode\n"); 364 365 if (rtc_irq) { 366 retval = request_irq(rtc_irq, mrst_rtc_irq, 367 IRQF_DISABLED, dev_name(&mrst_rtc.rtc->dev), 368 mrst_rtc.rtc); 369 if (retval < 0) { 370 dev_dbg(dev, "IRQ %d is already in use, err %d\n", 371 rtc_irq, retval); 372 goto cleanup1; 373 } 374 } 375 dev_dbg(dev, "initialised\n"); 376 return 0; 377 378cleanup1: 379 mrst_rtc.dev = NULL; 380 rtc_device_unregister(mrst_rtc.rtc); 381cleanup0: 382 release_region(iomem->start, iomem->end + 1 - iomem->start); 383 dev_err(dev, "rtc-mrst: unable to initialise\n"); 384 return retval; 385} 386 387static void rtc_mrst_do_shutdown(void) 388{ 389 spin_lock_irq(&rtc_lock); 390 mrst_irq_disable(&mrst_rtc, RTC_IRQMASK); 391 spin_unlock_irq(&rtc_lock); 392} 393 394static void __exit rtc_mrst_do_remove(struct device *dev) 395{ 396 struct mrst_rtc *mrst = dev_get_drvdata(dev); 397 struct resource *iomem; 398 399 rtc_mrst_do_shutdown(); 400 401 if (mrst->irq) 402 free_irq(mrst->irq, mrst->rtc); 403 404 rtc_device_unregister(mrst->rtc); 405 mrst->rtc = NULL; 406 407 iomem = mrst->iomem; 408 release_region(iomem->start, iomem->end + 1 - iomem->start); 409 mrst->iomem = NULL; 410 411 mrst->dev = NULL; 412 dev_set_drvdata(dev, NULL); 413} 414 415#ifdef CONFIG_PM 416static int mrst_suspend(struct device *dev, pm_message_t mesg) 417{ 418 struct mrst_rtc *mrst = dev_get_drvdata(dev); 419 unsigned char tmp; 420 421 /* Only the alarm might be a wakeup event source */ 422 spin_lock_irq(&rtc_lock); 423 mrst->suspend_ctrl = tmp = vrtc_cmos_read(RTC_CONTROL); 424 if (tmp & (RTC_PIE | RTC_AIE)) { 425 unsigned char mask; 426 427 if (device_may_wakeup(dev)) 428 mask = RTC_IRQMASK & ~RTC_AIE; 429 else 430 mask = RTC_IRQMASK; 431 tmp &= ~mask; 432 vrtc_cmos_write(tmp, RTC_CONTROL); 433 434 mrst_checkintr(mrst, tmp); 435 } 436 spin_unlock_irq(&rtc_lock); 437 438 if (tmp & RTC_AIE) { 439 mrst->enabled_wake = 1; 440 enable_irq_wake(mrst->irq); 441 } 442 443 dev_dbg(&mrst_rtc.rtc->dev, "suspend%s, ctrl %02x\n", 444 (tmp & RTC_AIE) ? ", alarm may wake" : "", 445 tmp); 446 447 return 0; 448} 449 450/* 451 * We want RTC alarms to wake us from the deep power saving state 452 */ 453static inline int mrst_poweroff(struct device *dev) 454{ 455 return mrst_suspend(dev, PMSG_HIBERNATE); 456} 457 458static int mrst_resume(struct device *dev) 459{ 460 struct mrst_rtc *mrst = dev_get_drvdata(dev); 461 unsigned char tmp = mrst->suspend_ctrl; 462 463 /* Re-enable any irqs previously active */ 464 if (tmp & RTC_IRQMASK) { 465 unsigned char mask; 466 467 if (mrst->enabled_wake) { 468 disable_irq_wake(mrst->irq); 469 mrst->enabled_wake = 0; 470 } 471 472 spin_lock_irq(&rtc_lock); 473 do { 474 vrtc_cmos_write(tmp, RTC_CONTROL); 475 476 mask = vrtc_cmos_read(RTC_INTR_FLAGS); 477 mask &= (tmp & RTC_IRQMASK) | RTC_IRQF; 478 if (!is_intr(mask)) 479 break; 480 481 rtc_update_irq(mrst->rtc, 1, mask); 482 tmp &= ~RTC_AIE; 483 } while (mask & RTC_AIE); 484 spin_unlock_irq(&rtc_lock); 485 } 486 487 dev_dbg(&mrst_rtc.rtc->dev, "resume, ctrl %02x\n", tmp); 488 489 return 0; 490} 491 492#else 493#define mrst_suspend NULL 494#define mrst_resume NULL 495 496static inline int mrst_poweroff(struct device *dev) 497{ 498 return -ENOSYS; 499} 500 501#endif 502 503static int __init vrtc_mrst_platform_probe(struct platform_device *pdev) 504{ 505 return vrtc_mrst_do_probe(&pdev->dev, 506 platform_get_resource(pdev, IORESOURCE_MEM, 0), 507 platform_get_irq(pdev, 0)); 508} 509 510static int __exit vrtc_mrst_platform_remove(struct platform_device *pdev) 511{ 512 rtc_mrst_do_remove(&pdev->dev); 513 return 0; 514} 515 516static void vrtc_mrst_platform_shutdown(struct platform_device *pdev) 517{ 518 if (system_state == SYSTEM_POWER_OFF && !mrst_poweroff(&pdev->dev)) 519 return; 520 521 rtc_mrst_do_shutdown(); 522} 523 524MODULE_ALIAS("platform:vrtc_mrst"); 525 526static struct platform_driver vrtc_mrst_platform_driver = { 527 .probe = vrtc_mrst_platform_probe, 528 .remove = __exit_p(vrtc_mrst_platform_remove), 529 .shutdown = vrtc_mrst_platform_shutdown, 530 .driver = { 531 .name = (char *) driver_name, 532 .suspend = mrst_suspend, 533 .resume = mrst_resume, 534 } 535}; 536 537static int __init vrtc_mrst_init(void) 538{ 539 return platform_driver_register(&vrtc_mrst_platform_driver); 540} 541 542static void __exit vrtc_mrst_exit(void) 543{ 544 platform_driver_unregister(&vrtc_mrst_platform_driver); 545} 546 547module_init(vrtc_mrst_init); 548module_exit(vrtc_mrst_exit); 549 550MODULE_AUTHOR("Jacob Pan; Feng Tang"); 551MODULE_DESCRIPTION("Driver for Moorestown virtual RTC"); 552MODULE_LICENSE("GPL");