linux/drivers/rtc/rtc-m48t59.c
<<
>>
Prefs
   1/*
   2 * ST M48T59 RTC driver
   3 *
   4 * Copyright (c) 2007 Wind River Systems, Inc.
   5 *
   6 * Author: Mark Zhan <rongkai.zhan@windriver.com>
   7 *
   8 * This program is free software; you can redistribute it and/or modify
   9 * it under the terms of the GNU General Public License version 2 as
  10 * published by the Free Software Foundation.
  11 */
  12
  13#include <linux/kernel.h>
  14#include <linux/module.h>
  15#include <linux/init.h>
  16#include <linux/io.h>
  17#include <linux/device.h>
  18#include <linux/platform_device.h>
  19#include <linux/rtc.h>
  20#include <linux/rtc/m48t59.h>
  21#include <linux/bcd.h>
  22
  23#ifndef NO_IRQ
  24#define NO_IRQ  (-1)
  25#endif
  26
  27#define M48T59_READ(reg) (pdata->read_byte(dev, pdata->offset + reg))
  28#define M48T59_WRITE(val, reg) \
  29        (pdata->write_byte(dev, pdata->offset + reg, val))
  30
  31#define M48T59_SET_BITS(mask, reg)      \
  32        M48T59_WRITE((M48T59_READ(reg) | (mask)), (reg))
  33#define M48T59_CLEAR_BITS(mask, reg)    \
  34        M48T59_WRITE((M48T59_READ(reg) & ~(mask)), (reg))
  35
  36struct m48t59_private {
  37        void __iomem *ioaddr;
  38        int irq;
  39        struct rtc_device *rtc;
  40        spinlock_t lock; /* serialize the NVRAM and RTC access */
  41};
  42
  43/*
  44 * This is the generic access method when the chip is memory-mapped
  45 */
  46static void
  47m48t59_mem_writeb(struct device *dev, u32 ofs, u8 val)
  48{
  49        struct platform_device *pdev = to_platform_device(dev);
  50        struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
  51
  52        writeb(val, m48t59->ioaddr+ofs);
  53}
  54
  55static u8
  56m48t59_mem_readb(struct device *dev, u32 ofs)
  57{
  58        struct platform_device *pdev = to_platform_device(dev);
  59        struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
  60
  61        return readb(m48t59->ioaddr+ofs);
  62}
  63
  64/*
  65 * NOTE: M48T59 only uses BCD mode
  66 */
  67static int m48t59_rtc_read_time(struct device *dev, struct rtc_time *tm)
  68{
  69        struct platform_device *pdev = to_platform_device(dev);
  70        struct m48t59_plat_data *pdata = pdev->dev.platform_data;
  71        struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
  72        unsigned long flags;
  73        u8 val;
  74
  75        spin_lock_irqsave(&m48t59->lock, flags);
  76        /* Issue the READ command */
  77        M48T59_SET_BITS(M48T59_CNTL_READ, M48T59_CNTL);
  78
  79        tm->tm_year     = bcd2bin(M48T59_READ(M48T59_YEAR));
  80        /* tm_mon is 0-11 */
  81        tm->tm_mon      = bcd2bin(M48T59_READ(M48T59_MONTH)) - 1;
  82        tm->tm_mday     = bcd2bin(M48T59_READ(M48T59_MDAY));
  83
  84        val = M48T59_READ(M48T59_WDAY);
  85        if ((pdata->type == M48T59RTC_TYPE_M48T59) &&
  86            (val & M48T59_WDAY_CEB) && (val & M48T59_WDAY_CB)) {
  87                dev_dbg(dev, "Century bit is enabled\n");
  88                tm->tm_year += 100;     /* one century */
  89        }
  90#ifdef CONFIG_SPARC
  91        /* Sun SPARC machines count years since 1968 */
  92        tm->tm_year += 68;
  93#endif
  94
  95        tm->tm_wday     = bcd2bin(val & 0x07);
  96        tm->tm_hour     = bcd2bin(M48T59_READ(M48T59_HOUR) & 0x3F);
  97        tm->tm_min      = bcd2bin(M48T59_READ(M48T59_MIN) & 0x7F);
  98        tm->tm_sec      = bcd2bin(M48T59_READ(M48T59_SEC) & 0x7F);
  99
 100        /* Clear the READ bit */
 101        M48T59_CLEAR_BITS(M48T59_CNTL_READ, M48T59_CNTL);
 102        spin_unlock_irqrestore(&m48t59->lock, flags);
 103
 104        dev_dbg(dev, "RTC read time %04d-%02d-%02d %02d/%02d/%02d\n",
 105                tm->tm_year + 1900, tm->tm_mon, tm->tm_mday,
 106                tm->tm_hour, tm->tm_min, tm->tm_sec);
 107        return 0;
 108}
 109
 110static int m48t59_rtc_set_time(struct device *dev, struct rtc_time *tm)
 111{
 112        struct platform_device *pdev = to_platform_device(dev);
 113        struct m48t59_plat_data *pdata = pdev->dev.platform_data;
 114        struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
 115        unsigned long flags;
 116        u8 val = 0;
 117        int year = tm->tm_year;
 118
 119#ifdef CONFIG_SPARC
 120        /* Sun SPARC machines count years since 1968 */
 121        year -= 68;
 122#endif
 123
 124        dev_dbg(dev, "RTC set time %04d-%02d-%02d %02d/%02d/%02d\n",
 125                year + 1900, tm->tm_mon, tm->tm_mday,
 126                tm->tm_hour, tm->tm_min, tm->tm_sec);
 127
 128        if (year < 0)
 129                return -EINVAL;
 130
 131        spin_lock_irqsave(&m48t59->lock, flags);
 132        /* Issue the WRITE command */
 133        M48T59_SET_BITS(M48T59_CNTL_WRITE, M48T59_CNTL);
 134
 135        M48T59_WRITE((bin2bcd(tm->tm_sec) & 0x7F), M48T59_SEC);
 136        M48T59_WRITE((bin2bcd(tm->tm_min) & 0x7F), M48T59_MIN);
 137        M48T59_WRITE((bin2bcd(tm->tm_hour) & 0x3F), M48T59_HOUR);
 138        M48T59_WRITE((bin2bcd(tm->tm_mday) & 0x3F), M48T59_MDAY);
 139        /* tm_mon is 0-11 */
 140        M48T59_WRITE((bin2bcd(tm->tm_mon + 1) & 0x1F), M48T59_MONTH);
 141        M48T59_WRITE(bin2bcd(year % 100), M48T59_YEAR);
 142
 143        if (pdata->type == M48T59RTC_TYPE_M48T59 && (year / 100))
 144                val = (M48T59_WDAY_CEB | M48T59_WDAY_CB);
 145        val |= (bin2bcd(tm->tm_wday) & 0x07);
 146        M48T59_WRITE(val, M48T59_WDAY);
 147
 148        /* Clear the WRITE bit */
 149        M48T59_CLEAR_BITS(M48T59_CNTL_WRITE, M48T59_CNTL);
 150        spin_unlock_irqrestore(&m48t59->lock, flags);
 151        return 0;
 152}
 153
 154/*
 155 * Read alarm time and date in RTC
 156 */
 157static int m48t59_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
 158{
 159        struct platform_device *pdev = to_platform_device(dev);
 160        struct m48t59_plat_data *pdata = pdev->dev.platform_data;
 161        struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
 162        struct rtc_time *tm = &alrm->time;
 163        unsigned long flags;
 164        u8 val;
 165
 166        /* If no irq, we don't support ALARM */
 167        if (m48t59->irq == NO_IRQ)
 168                return -EIO;
 169
 170        spin_lock_irqsave(&m48t59->lock, flags);
 171        /* Issue the READ command */
 172        M48T59_SET_BITS(M48T59_CNTL_READ, M48T59_CNTL);
 173
 174        tm->tm_year = bcd2bin(M48T59_READ(M48T59_YEAR));
 175#ifdef CONFIG_SPARC
 176        /* Sun SPARC machines count years since 1968 */
 177        tm->tm_year += 68;
 178#endif
 179        /* tm_mon is 0-11 */
 180        tm->tm_mon = bcd2bin(M48T59_READ(M48T59_MONTH)) - 1;
 181
 182        val = M48T59_READ(M48T59_WDAY);
 183        if ((val & M48T59_WDAY_CEB) && (val & M48T59_WDAY_CB))
 184                tm->tm_year += 100;     /* one century */
 185
 186        tm->tm_mday = bcd2bin(M48T59_READ(M48T59_ALARM_DATE));
 187        tm->tm_hour = bcd2bin(M48T59_READ(M48T59_ALARM_HOUR));
 188        tm->tm_min = bcd2bin(M48T59_READ(M48T59_ALARM_MIN));
 189        tm->tm_sec = bcd2bin(M48T59_READ(M48T59_ALARM_SEC));
 190
 191        /* Clear the READ bit */
 192        M48T59_CLEAR_BITS(M48T59_CNTL_READ, M48T59_CNTL);
 193        spin_unlock_irqrestore(&m48t59->lock, flags);
 194
 195        dev_dbg(dev, "RTC read alarm time %04d-%02d-%02d %02d/%02d/%02d\n",
 196                tm->tm_year + 1900, tm->tm_mon, tm->tm_mday,
 197                tm->tm_hour, tm->tm_min, tm->tm_sec);
 198        return 0;
 199}
 200
 201/*
 202 * Set alarm time and date in RTC
 203 */
 204static int m48t59_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
 205{
 206        struct platform_device *pdev = to_platform_device(dev);
 207        struct m48t59_plat_data *pdata = pdev->dev.platform_data;
 208        struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
 209        struct rtc_time *tm = &alrm->time;
 210        u8 mday, hour, min, sec;
 211        unsigned long flags;
 212        int year = tm->tm_year;
 213
 214#ifdef CONFIG_SPARC
 215        /* Sun SPARC machines count years since 1968 */
 216        year -= 68;
 217#endif
 218
 219        /* If no irq, we don't support ALARM */
 220        if (m48t59->irq == NO_IRQ)
 221                return -EIO;
 222
 223        if (year < 0)
 224                return -EINVAL;
 225
 226        /*
 227         * 0xff means "always match"
 228         */
 229        mday = tm->tm_mday;
 230        mday = (mday >= 1 && mday <= 31) ? bin2bcd(mday) : 0xff;
 231        if (mday == 0xff)
 232                mday = M48T59_READ(M48T59_MDAY);
 233
 234        hour = tm->tm_hour;
 235        hour = (hour < 24) ? bin2bcd(hour) : 0x00;
 236
 237        min = tm->tm_min;
 238        min = (min < 60) ? bin2bcd(min) : 0x00;
 239
 240        sec = tm->tm_sec;
 241        sec = (sec < 60) ? bin2bcd(sec) : 0x00;
 242
 243        spin_lock_irqsave(&m48t59->lock, flags);
 244        /* Issue the WRITE command */
 245        M48T59_SET_BITS(M48T59_CNTL_WRITE, M48T59_CNTL);
 246
 247        M48T59_WRITE(mday, M48T59_ALARM_DATE);
 248        M48T59_WRITE(hour, M48T59_ALARM_HOUR);
 249        M48T59_WRITE(min, M48T59_ALARM_MIN);
 250        M48T59_WRITE(sec, M48T59_ALARM_SEC);
 251
 252        /* Clear the WRITE bit */
 253        M48T59_CLEAR_BITS(M48T59_CNTL_WRITE, M48T59_CNTL);
 254        spin_unlock_irqrestore(&m48t59->lock, flags);
 255
 256        dev_dbg(dev, "RTC set alarm time %04d-%02d-%02d %02d/%02d/%02d\n",
 257                year + 1900, tm->tm_mon, tm->tm_mday,
 258                tm->tm_hour, tm->tm_min, tm->tm_sec);
 259        return 0;
 260}
 261
 262/*
 263 * Handle commands from user-space
 264 */
 265static int m48t59_rtc_ioctl(struct device *dev, unsigned int cmd,
 266                        unsigned long arg)
 267{
 268        struct platform_device *pdev = to_platform_device(dev);
 269        struct m48t59_plat_data *pdata = pdev->dev.platform_data;
 270        struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
 271        unsigned long flags;
 272        int ret = 0;
 273
 274        spin_lock_irqsave(&m48t59->lock, flags);
 275        switch (cmd) {
 276        case RTC_AIE_OFF:       /* alarm interrupt off */
 277                M48T59_WRITE(0x00, M48T59_INTR);
 278                break;
 279        case RTC_AIE_ON:        /* alarm interrupt on */
 280                M48T59_WRITE(M48T59_INTR_AFE, M48T59_INTR);
 281                break;
 282        default:
 283                ret = -ENOIOCTLCMD;
 284                break;
 285        }
 286        spin_unlock_irqrestore(&m48t59->lock, flags);
 287
 288        return ret;
 289}
 290
 291static int m48t59_rtc_proc(struct device *dev, struct seq_file *seq)
 292{
 293        struct platform_device *pdev = to_platform_device(dev);
 294        struct m48t59_plat_data *pdata = pdev->dev.platform_data;
 295        struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
 296        unsigned long flags;
 297        u8 val;
 298
 299        spin_lock_irqsave(&m48t59->lock, flags);
 300        val = M48T59_READ(M48T59_FLAGS);
 301        spin_unlock_irqrestore(&m48t59->lock, flags);
 302
 303        seq_printf(seq, "battery\t\t: %s\n",
 304                 (val & M48T59_FLAGS_BF) ? "low" : "normal");
 305        return 0;
 306}
 307
 308/*
 309 * IRQ handler for the RTC
 310 */
 311static irqreturn_t m48t59_rtc_interrupt(int irq, void *dev_id)
 312{
 313        struct device *dev = (struct device *)dev_id;
 314        struct platform_device *pdev = to_platform_device(dev);
 315        struct m48t59_plat_data *pdata = pdev->dev.platform_data;
 316        struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
 317        u8 event;
 318
 319        spin_lock(&m48t59->lock);
 320        event = M48T59_READ(M48T59_FLAGS);
 321        spin_unlock(&m48t59->lock);
 322
 323        if (event & M48T59_FLAGS_AF) {
 324                rtc_update_irq(m48t59->rtc, 1, (RTC_AF | RTC_IRQF));
 325                return IRQ_HANDLED;
 326        }
 327
 328        return IRQ_NONE;
 329}
 330
 331static const struct rtc_class_ops m48t59_rtc_ops = {
 332        .ioctl          = m48t59_rtc_ioctl,
 333        .read_time      = m48t59_rtc_read_time,
 334        .set_time       = m48t59_rtc_set_time,
 335        .read_alarm     = m48t59_rtc_readalarm,
 336        .set_alarm      = m48t59_rtc_setalarm,
 337        .proc           = m48t59_rtc_proc,
 338};
 339
 340static const struct rtc_class_ops m48t02_rtc_ops = {
 341        .read_time      = m48t59_rtc_read_time,
 342        .set_time       = m48t59_rtc_set_time,
 343};
 344
 345static ssize_t m48t59_nvram_read(struct kobject *kobj,
 346                                struct bin_attribute *bin_attr,
 347                                char *buf, loff_t pos, size_t size)
 348{
 349        struct device *dev = container_of(kobj, struct device, kobj);
 350        struct platform_device *pdev = to_platform_device(dev);
 351        struct m48t59_plat_data *pdata = pdev->dev.platform_data;
 352        struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
 353        ssize_t cnt = 0;
 354        unsigned long flags;
 355
 356        for (; size > 0 && pos < pdata->offset; cnt++, size--) {
 357                spin_lock_irqsave(&m48t59->lock, flags);
 358                *buf++ = M48T59_READ(cnt);
 359                spin_unlock_irqrestore(&m48t59->lock, flags);
 360        }
 361
 362        return cnt;
 363}
 364
 365static ssize_t m48t59_nvram_write(struct kobject *kobj,
 366                                struct bin_attribute *bin_attr,
 367                                char *buf, loff_t pos, size_t size)
 368{
 369        struct device *dev = container_of(kobj, struct device, kobj);
 370        struct platform_device *pdev = to_platform_device(dev);
 371        struct m48t59_plat_data *pdata = pdev->dev.platform_data;
 372        struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
 373        ssize_t cnt = 0;
 374        unsigned long flags;
 375
 376        for (; size > 0 && pos < pdata->offset; cnt++, size--) {
 377                spin_lock_irqsave(&m48t59->lock, flags);
 378                M48T59_WRITE(*buf++, cnt);
 379                spin_unlock_irqrestore(&m48t59->lock, flags);
 380        }
 381
 382        return cnt;
 383}
 384
 385static struct bin_attribute m48t59_nvram_attr = {
 386        .attr = {
 387                .name = "nvram",
 388                .mode = S_IRUGO | S_IWUSR,
 389        },
 390        .read = m48t59_nvram_read,
 391        .write = m48t59_nvram_write,
 392};
 393
 394static int __devinit m48t59_rtc_probe(struct platform_device *pdev)
 395{
 396        struct m48t59_plat_data *pdata = pdev->dev.platform_data;
 397        struct m48t59_private *m48t59 = NULL;
 398        struct resource *res;
 399        int ret = -ENOMEM;
 400        char *name;
 401        const struct rtc_class_ops *ops;
 402
 403        /* This chip could be memory-mapped or I/O-mapped */
 404        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 405        if (!res) {
 406                res = platform_get_resource(pdev, IORESOURCE_IO, 0);
 407                if (!res)
 408                        return -EINVAL;
 409        }
 410
 411        if (res->flags & IORESOURCE_IO) {
 412                /* If we are I/O-mapped, the platform should provide
 413                 * the operations accessing chip registers.
 414                 */
 415                if (!pdata || !pdata->write_byte || !pdata->read_byte)
 416                        return -EINVAL;
 417        } else if (res->flags & IORESOURCE_MEM) {
 418                /* we are memory-mapped */
 419                if (!pdata) {
 420                        pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
 421                        if (!pdata)
 422                                return -ENOMEM;
 423                        /* Ensure we only kmalloc platform data once */
 424                        pdev->dev.platform_data = pdata;
 425                }
 426                if (!pdata->type)
 427                        pdata->type = M48T59RTC_TYPE_M48T59;
 428
 429                /* Try to use the generic memory read/write ops */
 430                if (!pdata->write_byte)
 431                        pdata->write_byte = m48t59_mem_writeb;
 432                if (!pdata->read_byte)
 433                        pdata->read_byte = m48t59_mem_readb;
 434        }
 435
 436        m48t59 = kzalloc(sizeof(*m48t59), GFP_KERNEL);
 437        if (!m48t59)
 438                return -ENOMEM;
 439
 440        m48t59->ioaddr = pdata->ioaddr;
 441
 442        if (!m48t59->ioaddr) {
 443                /* ioaddr not mapped externally */
 444                m48t59->ioaddr = ioremap(res->start, res->end - res->start + 1);
 445                if (!m48t59->ioaddr)
 446                        goto out;
 447        }
 448
 449        /* Try to get irq number. We also can work in
 450         * the mode without IRQ.
 451         */
 452        m48t59->irq = platform_get_irq(pdev, 0);
 453        if (m48t59->irq <= 0)
 454                m48t59->irq = NO_IRQ;
 455
 456        if (m48t59->irq != NO_IRQ) {
 457                ret = request_irq(m48t59->irq, m48t59_rtc_interrupt,
 458                        IRQF_SHARED, "rtc-m48t59", &pdev->dev);
 459                if (ret)
 460                        goto out;
 461        }
 462        switch (pdata->type) {
 463        case M48T59RTC_TYPE_M48T59:
 464                name = "m48t59";
 465                ops = &m48t59_rtc_ops;
 466                pdata->offset = 0x1ff0;
 467                break;
 468        case M48T59RTC_TYPE_M48T02:
 469                name = "m48t02";
 470                ops = &m48t02_rtc_ops;
 471                pdata->offset = 0x7f0;
 472                break;
 473        case M48T59RTC_TYPE_M48T08:
 474                name = "m48t08";
 475                ops = &m48t02_rtc_ops;
 476                pdata->offset = 0x1ff0;
 477                break;
 478        default:
 479                dev_err(&pdev->dev, "Unknown RTC type\n");
 480                ret = -ENODEV;
 481                goto out;
 482        }
 483
 484        m48t59->rtc = rtc_device_register(name, &pdev->dev, ops, THIS_MODULE);
 485        if (IS_ERR(m48t59->rtc)) {
 486                ret = PTR_ERR(m48t59->rtc);
 487                goto out;
 488        }
 489
 490        m48t59_nvram_attr.size = pdata->offset;
 491
 492        ret = sysfs_create_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr);
 493        if (ret)
 494                goto out;
 495
 496        spin_lock_init(&m48t59->lock);
 497        platform_set_drvdata(pdev, m48t59);
 498        return 0;
 499
 500out:
 501        if (!IS_ERR(m48t59->rtc))
 502                rtc_device_unregister(m48t59->rtc);
 503        if (m48t59->irq != NO_IRQ)
 504                free_irq(m48t59->irq, &pdev->dev);
 505        if (m48t59->ioaddr)
 506                iounmap(m48t59->ioaddr);
 507        if (m48t59)
 508                kfree(m48t59);
 509        return ret;
 510}
 511
 512static int __devexit m48t59_rtc_remove(struct platform_device *pdev)
 513{
 514        struct m48t59_private *m48t59 = platform_get_drvdata(pdev);
 515        struct m48t59_plat_data *pdata = pdev->dev.platform_data;
 516
 517        sysfs_remove_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr);
 518        if (!IS_ERR(m48t59->rtc))
 519                rtc_device_unregister(m48t59->rtc);
 520        if (m48t59->ioaddr && !pdata->ioaddr)
 521                iounmap(m48t59->ioaddr);
 522        if (m48t59->irq != NO_IRQ)
 523                free_irq(m48t59->irq, &pdev->dev);
 524        platform_set_drvdata(pdev, NULL);
 525        kfree(m48t59);
 526        return 0;
 527}
 528
 529/* work with hotplug and coldplug */
 530MODULE_ALIAS("platform:rtc-m48t59");
 531
 532static struct platform_driver m48t59_rtc_driver = {
 533        .driver         = {
 534                .name   = "rtc-m48t59",
 535                .owner  = THIS_MODULE,
 536        },
 537        .probe          = m48t59_rtc_probe,
 538        .remove         = __devexit_p(m48t59_rtc_remove),
 539};
 540
 541static int __init m48t59_rtc_init(void)
 542{
 543        return platform_driver_register(&m48t59_rtc_driver);
 544}
 545
 546static void __exit m48t59_rtc_exit(void)
 547{
 548        platform_driver_unregister(&m48t59_rtc_driver);
 549}
 550
 551module_init(m48t59_rtc_init);
 552module_exit(m48t59_rtc_exit);
 553
 554MODULE_AUTHOR("Mark Zhan <rongkai.zhan@windriver.com>");
 555MODULE_DESCRIPTION("M48T59/M48T02/M48T08 RTC driver");
 556MODULE_LICENSE("GPL");
 557