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