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
  26#define SEC_PER_DAY     (24 * 60 * 60)
  27
  28struct mc13xxx_rtc {
  29        struct rtc_device *rtc;
  30        struct mc13xxx *mc13xxx;
  31        int valid;
  32};
  33
  34static int mc13xxx_rtc_irq_enable_unlocked(struct device *dev,
  35                unsigned int enabled, int irq)
  36{
  37        struct mc13xxx_rtc *priv = dev_get_drvdata(dev);
  38        int (*func)(struct mc13xxx *mc13xxx, int irq);
  39
  40        if (!priv->valid)
  41                return -ENODATA;
  42
  43        func = enabled ? mc13xxx_irq_unmask : mc13xxx_irq_mask;
  44        return func(priv->mc13xxx, irq);
  45}
  46
  47static int mc13xxx_rtc_alarm_irq_enable(struct device *dev,
  48                                        unsigned int enabled)
  49{
  50        struct mc13xxx_rtc *priv = dev_get_drvdata(dev);
  51        int ret;
  52
  53        mc13xxx_lock(priv->mc13xxx);
  54
  55        ret = mc13xxx_rtc_irq_enable_unlocked(dev, enabled, MC13XXX_IRQ_TODA);
  56
  57        mc13xxx_unlock(priv->mc13xxx);
  58
  59        return ret;
  60}
  61
  62static int mc13xxx_rtc_read_time(struct device *dev, struct rtc_time *tm)
  63{
  64        struct mc13xxx_rtc *priv = dev_get_drvdata(dev);
  65        unsigned int seconds, days1, days2;
  66
  67        if (!priv->valid)
  68                return -ENODATA;
  69
  70        do {
  71                int ret;
  72
  73                ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCDAY, &days1);
  74                if (ret)
  75                        return ret;
  76
  77                ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCTOD, &seconds);
  78                if (ret)
  79                        return ret;
  80
  81                ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCDAY, &days2);
  82                if (ret)
  83                        return ret;
  84        } while (days1 != days2);
  85
  86        rtc_time64_to_tm((time64_t)days1 * SEC_PER_DAY + seconds, tm);
  87
  88        return rtc_valid_tm(tm);
  89}
  90
  91static int mc13xxx_rtc_set_mmss(struct device *dev, time64_t secs)
  92{
  93        struct mc13xxx_rtc *priv = dev_get_drvdata(dev);
  94        unsigned int seconds, days;
  95        unsigned int alarmseconds;
  96        int ret;
  97
  98        days = div_s64_rem(secs, SEC_PER_DAY, &seconds);
  99
 100        mc13xxx_lock(priv->mc13xxx);
 101
 102        /*
 103         * temporarily invalidate alarm to prevent triggering it when the day is
 104         * already updated while the time isn't yet.
 105         */
 106        ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCTODA, &alarmseconds);
 107        if (unlikely(ret))
 108                goto out;
 109
 110        if (alarmseconds < SEC_PER_DAY) {
 111                ret = mc13xxx_reg_write(priv->mc13xxx,
 112                                MC13XXX_RTCTODA, 0x1ffff);
 113                if (unlikely(ret))
 114                        goto out;
 115        }
 116
 117        /*
 118         * write seconds=0 to prevent a day switch between writing days
 119         * and seconds below
 120         */
 121        ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCTOD, 0);
 122        if (unlikely(ret))
 123                goto out;
 124
 125        ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCDAY, days);
 126        if (unlikely(ret))
 127                goto out;
 128
 129        ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCTOD, seconds);
 130        if (unlikely(ret))
 131                goto out;
 132
 133        /* restore alarm */
 134        if (alarmseconds < SEC_PER_DAY) {
 135                ret = mc13xxx_reg_write(priv->mc13xxx,
 136                                MC13XXX_RTCTODA, alarmseconds);
 137                if (unlikely(ret))
 138                        goto out;
 139        }
 140
 141        if (!priv->valid) {
 142                ret = mc13xxx_irq_ack(priv->mc13xxx, MC13XXX_IRQ_RTCRST);
 143                if (unlikely(ret))
 144                        goto out;
 145
 146                ret = mc13xxx_irq_unmask(priv->mc13xxx, MC13XXX_IRQ_RTCRST);
 147        }
 148
 149out:
 150        priv->valid = !ret;
 151
 152        mc13xxx_unlock(priv->mc13xxx);
 153
 154        return ret;
 155}
 156
 157static int mc13xxx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
 158{
 159        struct mc13xxx_rtc *priv = dev_get_drvdata(dev);
 160        unsigned seconds, days;
 161        time64_t s1970;
 162        int enabled, pending;
 163        int ret;
 164
 165        mc13xxx_lock(priv->mc13xxx);
 166
 167        ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCTODA, &seconds);
 168        if (unlikely(ret))
 169                goto out;
 170        if (seconds >= SEC_PER_DAY) {
 171                ret = -ENODATA;
 172                goto out;
 173        }
 174
 175        ret = mc13xxx_reg_read(priv->mc13xxx, MC13XXX_RTCDAY, &days);
 176        if (unlikely(ret))
 177                goto out;
 178
 179        ret = mc13xxx_irq_status(priv->mc13xxx, MC13XXX_IRQ_TODA,
 180                        &enabled, &pending);
 181
 182out:
 183        mc13xxx_unlock(priv->mc13xxx);
 184
 185        if (ret)
 186                return ret;
 187
 188        alarm->enabled = enabled;
 189        alarm->pending = pending;
 190
 191        s1970 = (time64_t)days * SEC_PER_DAY + seconds;
 192
 193        rtc_time64_to_tm(s1970, &alarm->time);
 194        dev_dbg(dev, "%s: %lld\n", __func__, (long long)s1970);
 195
 196        return 0;
 197}
 198
 199static int mc13xxx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
 200{
 201        struct mc13xxx_rtc *priv = dev_get_drvdata(dev);
 202        time64_t s1970;
 203        u32 seconds, days;
 204        int ret;
 205
 206        mc13xxx_lock(priv->mc13xxx);
 207
 208        /* disable alarm to prevent false triggering */
 209        ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCTODA, 0x1ffff);
 210        if (unlikely(ret))
 211                goto out;
 212
 213        ret = mc13xxx_irq_ack(priv->mc13xxx, MC13XXX_IRQ_TODA);
 214        if (unlikely(ret))
 215                goto out;
 216
 217        s1970 = rtc_tm_to_time64(&alarm->time);
 218
 219        dev_dbg(dev, "%s: %s %lld\n", __func__, alarm->enabled ? "on" : "off",
 220                        (long long)s1970);
 221
 222        ret = mc13xxx_rtc_irq_enable_unlocked(dev, alarm->enabled,
 223                        MC13XXX_IRQ_TODA);
 224        if (unlikely(ret))
 225                goto out;
 226
 227        days = div_s64_rem(s1970, SEC_PER_DAY, &seconds);
 228
 229        ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCDAYA, days);
 230        if (unlikely(ret))
 231                goto out;
 232
 233        ret = mc13xxx_reg_write(priv->mc13xxx, MC13XXX_RTCTODA, seconds);
 234
 235out:
 236        mc13xxx_unlock(priv->mc13xxx);
 237
 238        return ret;
 239}
 240
 241static irqreturn_t mc13xxx_rtc_alarm_handler(int irq, void *dev)
 242{
 243        struct mc13xxx_rtc *priv = dev;
 244        struct mc13xxx *mc13xxx = priv->mc13xxx;
 245
 246        rtc_update_irq(priv->rtc, 1, RTC_IRQF | RTC_AF);
 247
 248        mc13xxx_irq_ack(mc13xxx, irq);
 249
 250        return IRQ_HANDLED;
 251}
 252
 253static const struct rtc_class_ops mc13xxx_rtc_ops = {
 254        .read_time = mc13xxx_rtc_read_time,
 255        .set_mmss64 = mc13xxx_rtc_set_mmss,
 256        .read_alarm = mc13xxx_rtc_read_alarm,
 257        .set_alarm = mc13xxx_rtc_set_alarm,
 258        .alarm_irq_enable = mc13xxx_rtc_alarm_irq_enable,
 259};
 260
 261static irqreturn_t mc13xxx_rtc_reset_handler(int irq, void *dev)
 262{
 263        struct mc13xxx_rtc *priv = dev;
 264        struct mc13xxx *mc13xxx = priv->mc13xxx;
 265
 266        priv->valid = 0;
 267
 268        mc13xxx_irq_mask(mc13xxx, irq);
 269
 270        return IRQ_HANDLED;
 271}
 272
 273static int __init mc13xxx_rtc_probe(struct platform_device *pdev)
 274{
 275        int ret;
 276        struct mc13xxx_rtc *priv;
 277        struct mc13xxx *mc13xxx;
 278
 279        priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
 280        if (!priv)
 281                return -ENOMEM;
 282
 283        mc13xxx = dev_get_drvdata(pdev->dev.parent);
 284        priv->mc13xxx = mc13xxx;
 285        priv->valid = 1;
 286
 287        platform_set_drvdata(pdev, priv);
 288
 289        mc13xxx_lock(mc13xxx);
 290
 291        mc13xxx_irq_ack(mc13xxx, MC13XXX_IRQ_RTCRST);
 292
 293        ret = mc13xxx_irq_request(mc13xxx, MC13XXX_IRQ_RTCRST,
 294                        mc13xxx_rtc_reset_handler, DRIVER_NAME, priv);
 295        if (ret)
 296                goto err_irq_request;
 297
 298        ret = mc13xxx_irq_request_nounmask(mc13xxx, MC13XXX_IRQ_TODA,
 299                        mc13xxx_rtc_alarm_handler, DRIVER_NAME, priv);
 300        if (ret)
 301                goto err_irq_request;
 302
 303        mc13xxx_unlock(mc13xxx);
 304
 305        priv->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
 306                                             &mc13xxx_rtc_ops, THIS_MODULE);
 307
 308        return 0;
 309
 310err_irq_request:
 311        mc13xxx_irq_free(mc13xxx, MC13XXX_IRQ_TODA, priv);
 312        mc13xxx_irq_free(mc13xxx, MC13XXX_IRQ_RTCRST, priv);
 313
 314        mc13xxx_unlock(mc13xxx);
 315
 316        return ret;
 317}
 318
 319static int mc13xxx_rtc_remove(struct platform_device *pdev)
 320{
 321        struct mc13xxx_rtc *priv = platform_get_drvdata(pdev);
 322
 323        mc13xxx_lock(priv->mc13xxx);
 324
 325        mc13xxx_irq_free(priv->mc13xxx, MC13XXX_IRQ_TODA, priv);
 326        mc13xxx_irq_free(priv->mc13xxx, MC13XXX_IRQ_RTCRST, priv);
 327
 328        mc13xxx_unlock(priv->mc13xxx);
 329
 330        return 0;
 331}
 332
 333static const struct platform_device_id mc13xxx_rtc_idtable[] = {
 334        {
 335                .name = "mc13783-rtc",
 336        }, {
 337                .name = "mc13892-rtc",
 338        }, {
 339                .name = "mc34708-rtc",
 340        },
 341        { /* sentinel */ }
 342};
 343MODULE_DEVICE_TABLE(platform, mc13xxx_rtc_idtable);
 344
 345static struct platform_driver mc13xxx_rtc_driver = {
 346        .id_table = mc13xxx_rtc_idtable,
 347        .remove = mc13xxx_rtc_remove,
 348        .driver = {
 349                .name = DRIVER_NAME,
 350        },
 351};
 352
 353module_platform_driver_probe(mc13xxx_rtc_driver, &mc13xxx_rtc_probe);
 354
 355MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
 356MODULE_DESCRIPTION("RTC driver for Freescale MC13XXX PMIC");
 357MODULE_LICENSE("GPL v2");
 358