linux/drivers/rtc/rtc-mc13xxx.c
<<
>>
Prefs
   1/*
   2 * Real Time Clock driver for Freescale MC13XXX PMIC
   3 *
   4 * (C) 2009 Sascha Hauer, Pengutronix
   5 * (C) 2009 Uwe Kleine-Koenig, Pengutronix
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License version 2 as
   9 * published by the Free Software Foundation.
  10 */
  11
  12#include <linux/mfd/mc13xxx.h>
  13#include <linux/platform_device.h>
  14#include <linux/kernel.h>
  15#include <linux/module.h>
  16#include <linux/slab.h>
  17#include <linux/rtc.h>
  18
  19#define DRIVER_NAME "mc13xxx-rtc"
  20
  21#define MC13XXX_RTCTOD  20
  22#define MC13XXX_RTCTODA 21
  23#define MC13XXX_RTCDAY  22
  24#define MC13XXX_RTCDAYA 23
  25
  26struct mc13xxx_rtc {
  27        struct rtc_device *rtc;
  28        struct mc13xxx *mc13xxx;
  29        int valid;
  30};
  31
  32static int mc13xxx_rtc_irq_enable_unlocked(struct device *dev,
  33                unsigned int enabled, int irq)
  34{
  35        struct mc13xxx_rtc *priv = dev_get_drvdata(dev);
  36        int (*func)(struct mc13xxx *mc13xxx, int irq);
  37
  38        if (!priv->valid)
  39                return -ENODATA;
  40
  41        func = enabled ? mc13xxx_irq_unmask : mc13xxx_irq_mask;
  42        return func(priv->mc13xxx, irq);
  43}
  44
  45static int mc13xxx_rtc_irq_enable(struct device *dev,
  46                unsigned int enabled, int irq)
  47{
  48        struct mc13xxx_rtc *priv = dev_get_drvdata(dev);
  49        int ret;
  50
  51        mc13xxx_lock(priv->mc13xxx);
  52
  53        ret = mc13xxx_rtc_irq_enable_unlocked(dev, enabled, irq);
  54
  55        mc13xxx_unlock(priv->mc13xxx);
  56
  57        return ret;
  58}
  59
  60static int mc13xxx_rtc_read_time(struct device *dev, struct rtc_time *tm)
  61{
  62        struct mc13xxx_rtc *priv = dev_get_drvdata(dev);
  63        unsigned int seconds, days1, days2;
  64        unsigned long s1970;
  65        int ret;
  66
  67        mc13xxx_lock(priv->mc13xxx);
  68
  69        if (!priv->valid) {
  70                ret = -ENODATA;
  71                goto out;
  72        }
  73
  74        ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCDAY, &days1);
  75        if (unlikely(ret))
  76                goto out;
  77
  78        ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCTOD, &seconds);
  79        if (unlikely(ret))
  80                goto out;
  81
  82        ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCDAY, &days2);
  83out:
  84        mc13xxx_unlock(priv->mc13xxx);
  85
  86        if (ret)
  87                return ret;
  88
  89        if (days2 == days1 + 1) {
  90                if (seconds >= 86400 / 2)
  91                        days2 = days1;
  92                else
  93                        days1 = days2;
  94        }
  95
  96        if (days1 != days2)
  97                return -EIO;
  98
  99        s1970 = days1 * 86400 + seconds;
 100
 101        rtc_time_to_tm(s1970, tm);
 102
 103        return rtc_valid_tm(tm);
 104}
 105
 106static int mc13xxx_rtc_set_mmss(struct device *dev, unsigned long secs)
 107{
 108        struct mc13xxx_rtc *priv = dev_get_drvdata(dev);
 109        unsigned int seconds, days;
 110        unsigned int alarmseconds;
 111        int ret;
 112
 113        seconds = secs % 86400;
 114        days = secs / 86400;
 115
 116        mc13xxx_lock(priv->mc13xxx);
 117
 118        /*
 119         * temporarily invalidate alarm to prevent triggering it when the day is
 120         * already updated while the time isn't yet.
 121         */
 122        ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCTODA, &alarmseconds);
 123        if (unlikely(ret))
 124                goto out;
 125
 126        if (alarmseconds < 86400) {
 127                ret = mc13xxx_reg_write(priv->mc13xxx,
 128                                MC13XXX_RTCTODA, 0x1ffff);
 129                if (unlikely(ret))
 130                        goto out;
 131        }
 132
 133        /*
 134         * write seconds=0 to prevent a day switch between writing days
 135         * and seconds below
 136         */
 137        ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCTOD, 0);
 138        if (unlikely(ret))
 139                goto out;
 140
 141        ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCDAY, days);
 142        if (unlikely(ret))
 143                goto out;
 144
 145        ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCTOD, seconds);
 146        if (unlikely(ret))
 147                goto out;
 148
 149        /* restore alarm */
 150        if (alarmseconds < 86400) {
 151                ret = mc13xxx_reg_write(priv->mc13xxx,
 152                                MC13XXX_RTCTODA, alarmseconds);
 153                if (unlikely(ret))
 154                        goto out;
 155        }
 156
 157        ret = mc13xxx_irq_ack(priv->mc13xxx, MC13XXX_IRQ_RTCRST);
 158        if (unlikely(ret))
 159                goto out;
 160
 161        ret = mc13xxx_irq_unmask(priv->mc13xxx, MC13XXX_IRQ_RTCRST);
 162out:
 163        priv->valid = !ret;
 164
 165        mc13xxx_unlock(priv->mc13xxx);
 166
 167        return ret;
 168}
 169
 170static int mc13xxx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
 171{
 172        struct mc13xxx_rtc *priv = dev_get_drvdata(dev);
 173        unsigned seconds, days;
 174        unsigned long s1970;
 175        int enabled, pending;
 176        int ret;
 177
 178        mc13xxx_lock(priv->mc13xxx);
 179
 180        ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCTODA, &seconds);
 181        if (unlikely(ret))
 182                goto out;
 183        if (seconds >= 86400) {
 184                ret = -ENODATA;
 185                goto out;
 186        }
 187
 188        ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCDAY, &days);
 189        if (unlikely(ret))
 190                goto out;
 191
 192        ret = mc13xxx_irq_status(priv->mc13xxx, MC13XXX_IRQ_TODA,
 193                        &enabled, &pending);
 194
 195out:
 196        mc13xxx_unlock(priv->mc13xxx);
 197
 198        if (ret)
 199                return ret;
 200
 201        alarm->enabled = enabled;
 202        alarm->pending = pending;
 203
 204        s1970 = days * 86400 + seconds;
 205
 206        rtc_time_to_tm(s1970, &alarm->time);
 207        dev_dbg(dev, "%s: %lu\n", __func__, s1970);
 208
 209        return 0;
 210}
 211
 212static int mc13xxx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
 213{
 214        struct mc13xxx_rtc *priv = dev_get_drvdata(dev);
 215        unsigned long s1970;
 216        unsigned seconds, days;
 217        int ret;
 218
 219        mc13xxx_lock(priv->mc13xxx);
 220
 221        /* disable alarm to prevent false triggering */
 222        ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCTODA, 0x1ffff);
 223        if (unlikely(ret))
 224                goto out;
 225
 226        ret = mc13xxx_irq_ack(priv->mc13xxx, MC13XXX_IRQ_TODA);
 227        if (unlikely(ret))
 228                goto out;
 229
 230        ret = rtc_tm_to_time(&alarm->time, &s1970);
 231        if (unlikely(ret))
 232                goto out;
 233
 234        dev_dbg(dev, "%s: o%2.s %lu\n", __func__, alarm->enabled ? "n" : "ff",
 235                        s1970);
 236
 237        ret = mc13xxx_rtc_irq_enable_unlocked(dev, alarm->enabled,
 238                        MC13XXX_IRQ_TODA);
 239        if (unlikely(ret))
 240                goto out;
 241
 242        seconds = s1970 % 86400;
 243        days = s1970 / 86400;
 244
 245        ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCDAYA, days);
 246        if (unlikely(ret))
 247                goto out;
 248
 249        ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCTODA, seconds);
 250
 251out:
 252        mc13xxx_unlock(priv->mc13xxx);
 253
 254        return ret;
 255}
 256
 257static irqreturn_t mc13xxx_rtc_alarm_handler(int irq, void *dev)
 258{
 259        struct mc13xxx_rtc *priv = dev;
 260        struct mc13xxx *mc13xxx = priv->mc13xxx;
 261
 262        dev_dbg(&priv->rtc->dev, "Alarm\n");
 263
 264        rtc_update_irq(priv->rtc, 1, RTC_IRQF | RTC_AF);
 265
 266        mc13xxx_irq_ack(mc13xxx, irq);
 267
 268        return IRQ_HANDLED;
 269}
 270
 271static irqreturn_t mc13xxx_rtc_update_handler(int irq, void *dev)
 272{
 273        struct mc13xxx_rtc *priv = dev;
 274        struct mc13xxx *mc13xxx = priv->mc13xxx;
 275
 276        dev_dbg(&priv->rtc->dev, "1HZ\n");
 277
 278        rtc_update_irq(priv->rtc, 1, RTC_IRQF | RTC_UF);
 279
 280        mc13xxx_irq_ack(mc13xxx, irq);
 281
 282        return IRQ_HANDLED;
 283}
 284
 285static int mc13xxx_rtc_update_irq_enable(struct device *dev,
 286                unsigned int enabled)
 287{
 288        return mc13xxx_rtc_irq_enable(dev, enabled, MC13XXX_IRQ_1HZ);
 289}
 290
 291static int mc13xxx_rtc_alarm_irq_enable(struct device *dev,
 292                unsigned int enabled)
 293{
 294        return mc13xxx_rtc_irq_enable(dev, enabled, MC13XXX_IRQ_TODA);
 295}
 296
 297static const struct rtc_class_ops mc13xxx_rtc_ops = {
 298        .read_time = mc13xxx_rtc_read_time,
 299        .set_mmss = mc13xxx_rtc_set_mmss,
 300        .read_alarm = mc13xxx_rtc_read_alarm,
 301        .set_alarm = mc13xxx_rtc_set_alarm,
 302        .alarm_irq_enable = mc13xxx_rtc_alarm_irq_enable,
 303        .update_irq_enable = mc13xxx_rtc_update_irq_enable,
 304};
 305
 306static irqreturn_t mc13xxx_rtc_reset_handler(int irq, void *dev)
 307{
 308        struct mc13xxx_rtc *priv = dev;
 309        struct mc13xxx *mc13xxx = priv->mc13xxx;
 310
 311        dev_dbg(&priv->rtc->dev, "RTCRST\n");
 312        priv->valid = 0;
 313
 314        mc13xxx_irq_mask(mc13xxx, irq);
 315
 316        return IRQ_HANDLED;
 317}
 318
 319static int __devinit mc13xxx_rtc_probe(struct platform_device *pdev)
 320{
 321        int ret;
 322        struct mc13xxx_rtc *priv;
 323        struct mc13xxx *mc13xxx;
 324        int rtcrst_pending;
 325
 326        priv = kzalloc(sizeof(*priv), GFP_KERNEL);
 327        if (!priv)
 328                return -ENOMEM;
 329
 330        mc13xxx = dev_get_drvdata(pdev->dev.parent);
 331        priv->mc13xxx = mc13xxx;
 332
 333        platform_set_drvdata(pdev, priv);
 334
 335        mc13xxx_lock(mc13xxx);
 336
 337        ret = mc13xxx_irq_request(mc13xxx, MC13XXX_IRQ_RTCRST,
 338                        mc13xxx_rtc_reset_handler, DRIVER_NAME, priv);
 339        if (ret)
 340                goto err_reset_irq_request;
 341
 342        ret = mc13xxx_irq_status(mc13xxx, MC13XXX_IRQ_RTCRST,
 343                        NULL, &rtcrst_pending);
 344        if (ret)
 345                goto err_reset_irq_status;
 346
 347        priv->valid = !rtcrst_pending;
 348
 349        ret = mc13xxx_irq_request_nounmask(mc13xxx, MC13XXX_IRQ_1HZ,
 350                        mc13xxx_rtc_update_handler, DRIVER_NAME, priv);
 351        if (ret)
 352                goto err_update_irq_request;
 353
 354        ret = mc13xxx_irq_request_nounmask(mc13xxx, MC13XXX_IRQ_TODA,
 355                        mc13xxx_rtc_alarm_handler, DRIVER_NAME, priv);
 356        if (ret)
 357                goto err_alarm_irq_request;
 358
 359        priv->rtc = rtc_device_register(pdev->name,
 360                        &pdev->dev, &mc13xxx_rtc_ops, THIS_MODULE);
 361        if (IS_ERR(priv->rtc)) {
 362                ret = PTR_ERR(priv->rtc);
 363
 364                mc13xxx_irq_free(mc13xxx, MC13XXX_IRQ_TODA, priv);
 365err_alarm_irq_request:
 366
 367                mc13xxx_irq_free(mc13xxx, MC13XXX_IRQ_1HZ, priv);
 368err_update_irq_request:
 369
 370err_reset_irq_status:
 371
 372                mc13xxx_irq_free(mc13xxx, MC13XXX_IRQ_RTCRST, priv);
 373err_reset_irq_request:
 374
 375                platform_set_drvdata(pdev, NULL);
 376                kfree(priv);
 377        }
 378
 379        mc13xxx_unlock(mc13xxx);
 380
 381        return ret;
 382}
 383
 384static int __devexit mc13xxx_rtc_remove(struct platform_device *pdev)
 385{
 386        struct mc13xxx_rtc *priv = platform_get_drvdata(pdev);
 387
 388        mc13xxx_lock(priv->mc13xxx);
 389
 390        rtc_device_unregister(priv->rtc);
 391
 392        mc13xxx_irq_free(priv->mc13xxx, MC13XXX_IRQ_TODA, priv);
 393        mc13xxx_irq_free(priv->mc13xxx, MC13XXX_IRQ_1HZ, priv);
 394        mc13xxx_irq_free(priv->mc13xxx, MC13XXX_IRQ_RTCRST, priv);
 395
 396        mc13xxx_unlock(priv->mc13xxx);
 397
 398        platform_set_drvdata(pdev, NULL);
 399
 400        kfree(priv);
 401
 402        return 0;
 403}
 404
 405const struct platform_device_id mc13xxx_rtc_idtable[] = {
 406        {
 407                .name = "mc13783-rtc",
 408        }, {
 409                .name = "mc13892-rtc",
 410        },
 411};
 412
 413static struct platform_driver mc13xxx_rtc_driver = {
 414        .id_table = mc13xxx_rtc_idtable,
 415        .remove = __devexit_p(mc13xxx_rtc_remove),
 416        .driver = {
 417                .name = DRIVER_NAME,
 418                .owner = THIS_MODULE,
 419        },
 420};
 421
 422static int __init mc13xxx_rtc_init(void)
 423{
 424        return platform_driver_probe(&mc13xxx_rtc_driver, &mc13xxx_rtc_probe);
 425}
 426module_init(mc13xxx_rtc_init);
 427
 428static void __exit mc13xxx_rtc_exit(void)
 429{
 430        platform_driver_unregister(&mc13xxx_rtc_driver);
 431}
 432module_exit(mc13xxx_rtc_exit);
 433
 434MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
 435MODULE_DESCRIPTION("RTC driver for Freescale MC13XXX PMIC");
 436MODULE_LICENSE("GPL v2");
 437MODULE_ALIAS("platform:" DRIVER_NAME);
 438