linux/drivers/rtc/rtc-at91sam9.c
<<
>>
Prefs
   1/*
   2 * "RTT as Real Time Clock" driver for AT91SAM9 SoC family
   3 *
   4 * (C) 2007 Michel Benoit
   5 *
   6 * Based on rtc-at91rm9200.c by Rick Bronson
   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; either version
  11 * 2 of the License, or (at your option) any later version.
  12 */
  13
  14#include <linux/module.h>
  15#include <linux/kernel.h>
  16#include <linux/platform_device.h>
  17#include <linux/time.h>
  18#include <linux/rtc.h>
  19#include <linux/interrupt.h>
  20#include <linux/ioctl.h>
  21#include <linux/slab.h>
  22
  23#include <mach/board.h>
  24#include <mach/at91_rtt.h>
  25#include <mach/cpu.h>
  26
  27
  28/*
  29 * This driver uses two configurable hardware resources that live in the
  30 * AT91SAM9 backup power domain (intended to be powered at all times)
  31 * to implement the Real Time Clock interfaces
  32 *
  33 *  - A "Real-time Timer" (RTT) counts up in seconds from a base time.
  34 *    We can't assign the counter value (CRTV) ... but we can reset it.
  35 *
  36 *  - One of the "General Purpose Backup Registers" (GPBRs) holds the
  37 *    base time, normally an offset from the beginning of the POSIX
  38 *    epoch (1970-Jan-1 00:00:00 UTC).  Some systems also include the
  39 *    local timezone's offset.
  40 *
  41 * The RTC's value is the RTT counter plus that offset.  The RTC's alarm
  42 * is likewise a base (ALMV) plus that offset.
  43 *
  44 * Not all RTTs will be used as RTCs; some systems have multiple RTTs to
  45 * choose from, or a "real" RTC module.  All systems have multiple GPBR
  46 * registers available, likewise usable for more than "RTC" support.
  47 */
  48
  49/*
  50 * We store ALARM_DISABLED in ALMV to record that no alarm is set.
  51 * It's also the reset value for that field.
  52 */
  53#define ALARM_DISABLED  ((u32)~0)
  54
  55
  56struct sam9_rtc {
  57        void __iomem            *rtt;
  58        struct rtc_device       *rtcdev;
  59        u32                     imr;
  60};
  61
  62#define rtt_readl(rtc, field) \
  63        __raw_readl((rtc)->rtt + AT91_RTT_ ## field)
  64#define rtt_writel(rtc, field, val) \
  65        __raw_writel((val), (rtc)->rtt + AT91_RTT_ ## field)
  66
  67#define gpbr_readl(rtc) \
  68        at91_sys_read(AT91_GPBR + 4 * CONFIG_RTC_DRV_AT91SAM9_GPBR)
  69#define gpbr_writel(rtc, val) \
  70        at91_sys_write(AT91_GPBR + 4 * CONFIG_RTC_DRV_AT91SAM9_GPBR, (val))
  71
  72/*
  73 * Read current time and date in RTC
  74 */
  75static int at91_rtc_readtime(struct device *dev, struct rtc_time *tm)
  76{
  77        struct sam9_rtc *rtc = dev_get_drvdata(dev);
  78        u32 secs, secs2;
  79        u32 offset;
  80
  81        /* read current time offset */
  82        offset = gpbr_readl(rtc);
  83        if (offset == 0)
  84                return -EILSEQ;
  85
  86        /* reread the counter to help sync the two clock domains */
  87        secs = rtt_readl(rtc, VR);
  88        secs2 = rtt_readl(rtc, VR);
  89        if (secs != secs2)
  90                secs = rtt_readl(rtc, VR);
  91
  92        rtc_time_to_tm(offset + secs, tm);
  93
  94        dev_dbg(dev, "%s: %4d-%02d-%02d %02d:%02d:%02d\n", "readtime",
  95                1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
  96                tm->tm_hour, tm->tm_min, tm->tm_sec);
  97
  98        return 0;
  99}
 100
 101/*
 102 * Set current time and date in RTC
 103 */
 104static int at91_rtc_settime(struct device *dev, struct rtc_time *tm)
 105{
 106        struct sam9_rtc *rtc = dev_get_drvdata(dev);
 107        int err;
 108        u32 offset, alarm, mr;
 109        unsigned long secs;
 110
 111        dev_dbg(dev, "%s: %4d-%02d-%02d %02d:%02d:%02d\n", "settime",
 112                1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
 113                tm->tm_hour, tm->tm_min, tm->tm_sec);
 114
 115        err = rtc_tm_to_time(tm, &secs);
 116        if (err != 0)
 117                return err;
 118
 119        mr = rtt_readl(rtc, MR);
 120
 121        /* disable interrupts */
 122        rtt_writel(rtc, MR, mr & ~(AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN));
 123
 124        /* read current time offset */
 125        offset = gpbr_readl(rtc);
 126
 127        /* store the new base time in a battery backup register */
 128        secs += 1;
 129        gpbr_writel(rtc, secs);
 130
 131        /* adjust the alarm time for the new base */
 132        alarm = rtt_readl(rtc, AR);
 133        if (alarm != ALARM_DISABLED) {
 134                if (offset > secs) {
 135                        /* time jumped backwards, increase time until alarm */
 136                        alarm += (offset - secs);
 137                } else if ((alarm + offset) > secs) {
 138                        /* time jumped forwards, decrease time until alarm */
 139                        alarm -= (secs - offset);
 140                } else {
 141                        /* time jumped past the alarm, disable alarm */
 142                        alarm = ALARM_DISABLED;
 143                        mr &= ~AT91_RTT_ALMIEN;
 144                }
 145                rtt_writel(rtc, AR, alarm);
 146        }
 147
 148        /* reset the timer, and re-enable interrupts */
 149        rtt_writel(rtc, MR, mr | AT91_RTT_RTTRST);
 150
 151        return 0;
 152}
 153
 154static int at91_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
 155{
 156        struct sam9_rtc *rtc = dev_get_drvdata(dev);
 157        struct rtc_time *tm = &alrm->time;
 158        u32 alarm = rtt_readl(rtc, AR);
 159        u32 offset;
 160
 161        offset = gpbr_readl(rtc);
 162        if (offset == 0)
 163                return -EILSEQ;
 164
 165        memset(alrm, 0, sizeof(*alrm));
 166        if (alarm != ALARM_DISABLED && offset != 0) {
 167                rtc_time_to_tm(offset + alarm, tm);
 168
 169                dev_dbg(dev, "%s: %4d-%02d-%02d %02d:%02d:%02d\n", "readalarm",
 170                        1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
 171                        tm->tm_hour, tm->tm_min, tm->tm_sec);
 172
 173                if (rtt_readl(rtc, MR) & AT91_RTT_ALMIEN)
 174                        alrm->enabled = 1;
 175        }
 176
 177        return 0;
 178}
 179
 180static int at91_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
 181{
 182        struct sam9_rtc *rtc = dev_get_drvdata(dev);
 183        struct rtc_time *tm = &alrm->time;
 184        unsigned long secs;
 185        u32 offset;
 186        u32 mr;
 187        int err;
 188
 189        err = rtc_tm_to_time(tm, &secs);
 190        if (err != 0)
 191                return err;
 192
 193        offset = gpbr_readl(rtc);
 194        if (offset == 0) {
 195                /* time is not set */
 196                return -EILSEQ;
 197        }
 198        mr = rtt_readl(rtc, MR);
 199        rtt_writel(rtc, MR, mr & ~AT91_RTT_ALMIEN);
 200
 201        /* alarm in the past? finish and leave disabled */
 202        if (secs <= offset) {
 203                rtt_writel(rtc, AR, ALARM_DISABLED);
 204                return 0;
 205        }
 206
 207        /* else set alarm and maybe enable it */
 208        rtt_writel(rtc, AR, secs - offset);
 209        if (alrm->enabled)
 210                rtt_writel(rtc, MR, mr | AT91_RTT_ALMIEN);
 211
 212        dev_dbg(dev, "%s: %4d-%02d-%02d %02d:%02d:%02d\n", "setalarm",
 213                tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour,
 214                tm->tm_min, tm->tm_sec);
 215
 216        return 0;
 217}
 218
 219static int at91_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
 220{
 221        struct sam9_rtc *rtc = dev_get_drvdata(dev);
 222        u32 mr = rtt_readl(rtc, MR);
 223
 224        dev_dbg(dev, "alarm_irq_enable: enabled=%08x, mr %08x\n", enabled, mr);
 225        if (enabled)
 226                rtt_writel(rtc, MR, mr | AT91_RTT_ALMIEN);
 227        else
 228                rtt_writel(rtc, MR, mr & ~AT91_RTT_ALMIEN);
 229        return 0;
 230}
 231
 232/*
 233 * Provide additional RTC information in /proc/driver/rtc
 234 */
 235static int at91_rtc_proc(struct device *dev, struct seq_file *seq)
 236{
 237        struct sam9_rtc *rtc = dev_get_drvdata(dev);
 238        u32 mr = mr = rtt_readl(rtc, MR);
 239
 240        seq_printf(seq, "update_IRQ\t: %s\n",
 241                        (mr & AT91_RTT_RTTINCIEN) ? "yes" : "no");
 242        return 0;
 243}
 244
 245/*
 246 * IRQ handler for the RTC
 247 */
 248static irqreturn_t at91_rtc_interrupt(int irq, void *_rtc)
 249{
 250        struct sam9_rtc *rtc = _rtc;
 251        u32 sr, mr;
 252        unsigned long events = 0;
 253
 254        /* Shared interrupt may be for another device.  Note: reading
 255         * SR clears it, so we must only read it in this irq handler!
 256         */
 257        mr = rtt_readl(rtc, MR) & (AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN);
 258        sr = rtt_readl(rtc, SR) & (mr >> 16);
 259        if (!sr)
 260                return IRQ_NONE;
 261
 262        /* alarm status */
 263        if (sr & AT91_RTT_ALMS)
 264                events |= (RTC_AF | RTC_IRQF);
 265
 266        /* timer update/increment */
 267        if (sr & AT91_RTT_RTTINC)
 268                events |= (RTC_UF | RTC_IRQF);
 269
 270        rtc_update_irq(rtc->rtcdev, 1, events);
 271
 272        pr_debug("%s: num=%ld, events=0x%02lx\n", __func__,
 273                events >> 8, events & 0x000000FF);
 274
 275        return IRQ_HANDLED;
 276}
 277
 278static const struct rtc_class_ops at91_rtc_ops = {
 279        .read_time      = at91_rtc_readtime,
 280        .set_time       = at91_rtc_settime,
 281        .read_alarm     = at91_rtc_readalarm,
 282        .set_alarm      = at91_rtc_setalarm,
 283        .proc           = at91_rtc_proc,
 284        .alarm_irq_enable = at91_rtc_alarm_irq_enable,
 285};
 286
 287/*
 288 * Initialize and install RTC driver
 289 */
 290static int __init at91_rtc_probe(struct platform_device *pdev)
 291{
 292        struct resource *r;
 293        struct sam9_rtc *rtc;
 294        int             ret;
 295        u32             mr;
 296
 297        r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 298        if (!r)
 299                return -ENODEV;
 300
 301        rtc = kzalloc(sizeof *rtc, GFP_KERNEL);
 302        if (!rtc)
 303                return -ENOMEM;
 304
 305        /* platform setup code should have handled this; sigh */
 306        if (!device_can_wakeup(&pdev->dev))
 307                device_init_wakeup(&pdev->dev, 1);
 308
 309        platform_set_drvdata(pdev, rtc);
 310        rtc->rtt = ioremap(r->start, resource_size(r));
 311        if (!rtc->rtt) {
 312                dev_err(&pdev->dev, "failed to map registers, aborting.\n");
 313                ret = -ENOMEM;
 314                goto fail;
 315        }
 316
 317        mr = rtt_readl(rtc, MR);
 318
 319        /* unless RTT is counting at 1 Hz, re-initialize it */
 320        if ((mr & AT91_RTT_RTPRES) != AT91_SLOW_CLOCK) {
 321                mr = AT91_RTT_RTTRST | (AT91_SLOW_CLOCK & AT91_RTT_RTPRES);
 322                gpbr_writel(rtc, 0);
 323        }
 324
 325        /* disable all interrupts (same as on shutdown path) */
 326        mr &= ~(AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN);
 327        rtt_writel(rtc, MR, mr);
 328
 329        rtc->rtcdev = rtc_device_register(pdev->name, &pdev->dev,
 330                                &at91_rtc_ops, THIS_MODULE);
 331        if (IS_ERR(rtc->rtcdev)) {
 332                ret = PTR_ERR(rtc->rtcdev);
 333                goto fail_register;
 334        }
 335
 336        /* register irq handler after we know what name we'll use */
 337        ret = request_irq(AT91_ID_SYS, at91_rtc_interrupt,
 338                                IRQF_DISABLED | IRQF_SHARED,
 339                                dev_name(&rtc->rtcdev->dev), rtc);
 340        if (ret) {
 341                dev_dbg(&pdev->dev, "can't share IRQ %d?\n", AT91_ID_SYS);
 342                rtc_device_unregister(rtc->rtcdev);
 343                goto fail;
 344        }
 345
 346        /* NOTE:  sam9260 rev A silicon has a ROM bug which resets the
 347         * RTT on at least some reboots.  If you have that chip, you must
 348         * initialize the time from some external source like a GPS, wall
 349         * clock, discrete RTC, etc
 350         */
 351
 352        if (gpbr_readl(rtc) == 0)
 353                dev_warn(&pdev->dev, "%s: SET TIME!\n",
 354                                dev_name(&rtc->rtcdev->dev));
 355
 356        return 0;
 357
 358fail_register:
 359        iounmap(rtc->rtt);
 360fail:
 361        platform_set_drvdata(pdev, NULL);
 362        kfree(rtc);
 363        return ret;
 364}
 365
 366/*
 367 * Disable and remove the RTC driver
 368 */
 369static int __exit at91_rtc_remove(struct platform_device *pdev)
 370{
 371        struct sam9_rtc *rtc = platform_get_drvdata(pdev);
 372        u32             mr = rtt_readl(rtc, MR);
 373
 374        /* disable all interrupts */
 375        rtt_writel(rtc, MR, mr & ~(AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN));
 376        free_irq(AT91_ID_SYS, rtc);
 377
 378        rtc_device_unregister(rtc->rtcdev);
 379
 380        iounmap(rtc->rtt);
 381        platform_set_drvdata(pdev, NULL);
 382        kfree(rtc);
 383        return 0;
 384}
 385
 386static void at91_rtc_shutdown(struct platform_device *pdev)
 387{
 388        struct sam9_rtc *rtc = platform_get_drvdata(pdev);
 389        u32             mr = rtt_readl(rtc, MR);
 390
 391        rtc->imr = mr & (AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN);
 392        rtt_writel(rtc, MR, mr & ~rtc->imr);
 393}
 394
 395#ifdef CONFIG_PM
 396
 397/* AT91SAM9 RTC Power management control */
 398
 399static int at91_rtc_suspend(struct platform_device *pdev,
 400                                        pm_message_t state)
 401{
 402        struct sam9_rtc *rtc = platform_get_drvdata(pdev);
 403        u32             mr = rtt_readl(rtc, MR);
 404
 405        /*
 406         * This IRQ is shared with DBGU and other hardware which isn't
 407         * necessarily a wakeup event source.
 408         */
 409        rtc->imr = mr & (AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN);
 410        if (rtc->imr) {
 411                if (device_may_wakeup(&pdev->dev) && (mr & AT91_RTT_ALMIEN)) {
 412                        enable_irq_wake(AT91_ID_SYS);
 413                        /* don't let RTTINC cause wakeups */
 414                        if (mr & AT91_RTT_RTTINCIEN)
 415                                rtt_writel(rtc, MR, mr & ~AT91_RTT_RTTINCIEN);
 416                } else
 417                        rtt_writel(rtc, MR, mr & ~rtc->imr);
 418        }
 419
 420        return 0;
 421}
 422
 423static int at91_rtc_resume(struct platform_device *pdev)
 424{
 425        struct sam9_rtc *rtc = platform_get_drvdata(pdev);
 426        u32             mr;
 427
 428        if (rtc->imr) {
 429                if (device_may_wakeup(&pdev->dev))
 430                        disable_irq_wake(AT91_ID_SYS);
 431                mr = rtt_readl(rtc, MR);
 432                rtt_writel(rtc, MR, mr | rtc->imr);
 433        }
 434
 435        return 0;
 436}
 437#else
 438#define at91_rtc_suspend        NULL
 439#define at91_rtc_resume         NULL
 440#endif
 441
 442static struct platform_driver at91_rtc_driver = {
 443        .driver.name    = "rtc-at91sam9",
 444        .driver.owner   = THIS_MODULE,
 445        .remove         = __exit_p(at91_rtc_remove),
 446        .shutdown       = at91_rtc_shutdown,
 447        .suspend        = at91_rtc_suspend,
 448        .resume         = at91_rtc_resume,
 449};
 450
 451/* Chips can have more than one RTT module, and they can be used for more
 452 * than just RTCs.  So we can't just register as "the" RTT driver.
 453 *
 454 * A normal approach in such cases is to create a library to allocate and
 455 * free the modules.  Here we just use bus_find_device() as like such a
 456 * library, binding directly ... no runtime "library" footprint is needed.
 457 */
 458static int __init at91_rtc_match(struct device *dev, void *v)
 459{
 460        struct platform_device *pdev = to_platform_device(dev);
 461        int ret;
 462
 463        /* continue searching if this isn't the RTT we need */
 464        if (strcmp("at91_rtt", pdev->name) != 0
 465                        || pdev->id != CONFIG_RTC_DRV_AT91SAM9_RTT)
 466                goto fail;
 467
 468        /* else we found it ... but fail unless we can bind to the RTC driver */
 469        if (dev->driver) {
 470                dev_dbg(dev, "busy, can't use as RTC!\n");
 471                goto fail;
 472        }
 473        dev->driver = &at91_rtc_driver.driver;
 474        if (device_attach(dev) == 0) {
 475                dev_dbg(dev, "can't attach RTC!\n");
 476                goto fail;
 477        }
 478        ret = at91_rtc_probe(pdev);
 479        if (ret == 0)
 480                return true;
 481
 482        dev_dbg(dev, "RTC probe err %d!\n", ret);
 483fail:
 484        return false;
 485}
 486
 487static int __init at91_rtc_init(void)
 488{
 489        int status;
 490        struct device *rtc;
 491
 492        status = platform_driver_register(&at91_rtc_driver);
 493        if (status)
 494                return status;
 495        rtc = bus_find_device(&platform_bus_type, NULL,
 496                        NULL, at91_rtc_match);
 497        if (!rtc)
 498                platform_driver_unregister(&at91_rtc_driver);
 499        return rtc ? 0 : -ENODEV;
 500}
 501module_init(at91_rtc_init);
 502
 503static void __exit at91_rtc_exit(void)
 504{
 505        platform_driver_unregister(&at91_rtc_driver);
 506}
 507module_exit(at91_rtc_exit);
 508
 509
 510MODULE_AUTHOR("Michel Benoit");
 511MODULE_DESCRIPTION("RTC driver for Atmel AT91SAM9x");
 512MODULE_LICENSE("GPL");
 513