linux/drivers/rtc/rtc-ds1286.c
<<
>>
Prefs
   1/*
   2 * DS1286 Real Time Clock interface for Linux
   3 *
   4 * Copyright (C) 1998, 1999, 2000 Ralf Baechle
   5 * Copyright (C) 2008 Thomas Bogendoerfer
   6 *
   7 * Based on code written by Paul Gortmaker.
   8 *
   9 * This program is free software; you can redistribute it and/or modify it
  10 * under the terms of the GNU General Public License as published by the
  11 * Free Software Foundation; either version 2 of the License, or (at your
  12 * option) any later version.
  13 */
  14
  15#include <linux/module.h>
  16#include <linux/rtc.h>
  17#include <linux/platform_device.h>
  18#include <linux/bcd.h>
  19#include <linux/ds1286.h>
  20#include <linux/io.h>
  21#include <linux/slab.h>
  22
  23#define DRV_VERSION             "1.0"
  24
  25struct ds1286_priv {
  26        struct rtc_device *rtc;
  27        u32 __iomem *rtcregs;
  28        size_t size;
  29        unsigned long baseaddr;
  30        spinlock_t lock;
  31};
  32
  33static inline u8 ds1286_rtc_read(struct ds1286_priv *priv, int reg)
  34{
  35        return __raw_readl(&priv->rtcregs[reg]) & 0xff;
  36}
  37
  38static inline void ds1286_rtc_write(struct ds1286_priv *priv, u8 data, int reg)
  39{
  40        __raw_writel(data, &priv->rtcregs[reg]);
  41}
  42
  43
  44static int ds1286_alarm_irq_enable(struct device *dev, unsigned int enabled)
  45{
  46        struct ds1286_priv *priv = dev_get_drvdata(dev);
  47        unsigned long flags;
  48        unsigned char val;
  49
  50        /* Allow or mask alarm interrupts */
  51        spin_lock_irqsave(&priv->lock, flags);
  52        val = ds1286_rtc_read(priv, RTC_CMD);
  53        if (enabled)
  54                val &=  ~RTC_TDM;
  55        else
  56                val |=  RTC_TDM;
  57        ds1286_rtc_write(priv, val, RTC_CMD);
  58        spin_unlock_irqrestore(&priv->lock, flags);
  59
  60        return 0;
  61}
  62
  63#ifdef CONFIG_RTC_INTF_DEV
  64
  65static int ds1286_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
  66{
  67        struct ds1286_priv *priv = dev_get_drvdata(dev);
  68        unsigned long flags;
  69        unsigned char val;
  70
  71        switch (cmd) {
  72        case RTC_WIE_OFF:
  73                /* Mask watchdog int. enab. bit */
  74                spin_lock_irqsave(&priv->lock, flags);
  75                val = ds1286_rtc_read(priv, RTC_CMD);
  76                val |= RTC_WAM;
  77                ds1286_rtc_write(priv, val, RTC_CMD);
  78                spin_unlock_irqrestore(&priv->lock, flags);
  79                break;
  80        case RTC_WIE_ON:
  81                /* Allow watchdog interrupts.   */
  82                spin_lock_irqsave(&priv->lock, flags);
  83                val = ds1286_rtc_read(priv, RTC_CMD);
  84                val &= ~RTC_WAM;
  85                ds1286_rtc_write(priv, val, RTC_CMD);
  86                spin_unlock_irqrestore(&priv->lock, flags);
  87                break;
  88        default:
  89                return -ENOIOCTLCMD;
  90        }
  91        return 0;
  92}
  93
  94#else
  95#define ds1286_ioctl    NULL
  96#endif
  97
  98#ifdef CONFIG_PROC_FS
  99
 100static int ds1286_proc(struct device *dev, struct seq_file *seq)
 101{
 102        struct ds1286_priv *priv = dev_get_drvdata(dev);
 103        unsigned char month, cmd, amode;
 104        const char *s;
 105
 106        month = ds1286_rtc_read(priv, RTC_MONTH);
 107        seq_printf(seq,
 108                   "oscillator\t: %s\n"
 109                   "square_wave\t: %s\n",
 110                   (month & RTC_EOSC) ? "disabled" : "enabled",
 111                   (month & RTC_ESQW) ? "disabled" : "enabled");
 112
 113        amode = ((ds1286_rtc_read(priv, RTC_MINUTES_ALARM) & 0x80) >> 5) |
 114                ((ds1286_rtc_read(priv, RTC_HOURS_ALARM) & 0x80) >> 6) |
 115                ((ds1286_rtc_read(priv, RTC_DAY_ALARM) & 0x80) >> 7);
 116        switch (amode) {
 117        case 7:
 118                s = "each minute";
 119                break;
 120        case 3:
 121                s = "minutes match";
 122                break;
 123        case 1:
 124                s = "hours and minutes match";
 125                break;
 126        case 0:
 127                s = "days, hours and minutes match";
 128                break;
 129        default:
 130                s = "invalid";
 131                break;
 132        }
 133        seq_printf(seq, "alarm_mode\t: %s\n", s);
 134
 135        cmd = ds1286_rtc_read(priv, RTC_CMD);
 136        seq_printf(seq,
 137                   "alarm_enable\t: %s\n"
 138                   "wdog_alarm\t: %s\n"
 139                   "alarm_mask\t: %s\n"
 140                   "wdog_alarm_mask\t: %s\n"
 141                   "interrupt_mode\t: %s\n"
 142                   "INTB_mode\t: %s_active\n"
 143                   "interrupt_pins\t: %s\n",
 144                   (cmd & RTC_TDF) ? "yes" : "no",
 145                   (cmd & RTC_WAF) ? "yes" : "no",
 146                   (cmd & RTC_TDM) ? "disabled" : "enabled",
 147                   (cmd & RTC_WAM) ? "disabled" : "enabled",
 148                   (cmd & RTC_PU_LVL) ? "pulse" : "level",
 149                   (cmd & RTC_IBH_LO) ? "low" : "high",
 150                   (cmd & RTC_IPSW) ? "unswapped" : "swapped");
 151        return 0;
 152}
 153
 154#else
 155#define ds1286_proc     NULL
 156#endif
 157
 158static int ds1286_read_time(struct device *dev, struct rtc_time *tm)
 159{
 160        struct ds1286_priv *priv = dev_get_drvdata(dev);
 161        unsigned char save_control;
 162        unsigned long flags;
 163        unsigned long uip_watchdog = jiffies;
 164
 165        /*
 166         * read RTC once any update in progress is done. The update
 167         * can take just over 2ms. We wait 10 to 20ms. There is no need to
 168         * to poll-wait (up to 1s - eeccch) for the falling edge of RTC_UIP.
 169         * If you need to know *exactly* when a second has started, enable
 170         * periodic update complete interrupts, (via ioctl) and then
 171         * immediately read /dev/rtc which will block until you get the IRQ.
 172         * Once the read clears, read the RTC time (again via ioctl). Easy.
 173         */
 174
 175        if (ds1286_rtc_read(priv, RTC_CMD) & RTC_TE)
 176                while (time_before(jiffies, uip_watchdog + 2*HZ/100))
 177                        barrier();
 178
 179        /*
 180         * Only the values that we read from the RTC are set. We leave
 181         * tm_wday, tm_yday and tm_isdst untouched. Even though the
 182         * RTC has RTC_DAY_OF_WEEK, we ignore it, as it is only updated
 183         * by the RTC when initially set to a non-zero value.
 184         */
 185        spin_lock_irqsave(&priv->lock, flags);
 186        save_control = ds1286_rtc_read(priv, RTC_CMD);
 187        ds1286_rtc_write(priv, (save_control|RTC_TE), RTC_CMD);
 188
 189        tm->tm_sec = ds1286_rtc_read(priv, RTC_SECONDS);
 190        tm->tm_min = ds1286_rtc_read(priv, RTC_MINUTES);
 191        tm->tm_hour = ds1286_rtc_read(priv, RTC_HOURS) & 0x3f;
 192        tm->tm_mday = ds1286_rtc_read(priv, RTC_DATE);
 193        tm->tm_mon = ds1286_rtc_read(priv, RTC_MONTH) & 0x1f;
 194        tm->tm_year = ds1286_rtc_read(priv, RTC_YEAR);
 195
 196        ds1286_rtc_write(priv, save_control, RTC_CMD);
 197        spin_unlock_irqrestore(&priv->lock, flags);
 198
 199        tm->tm_sec = bcd2bin(tm->tm_sec);
 200        tm->tm_min = bcd2bin(tm->tm_min);
 201        tm->tm_hour = bcd2bin(tm->tm_hour);
 202        tm->tm_mday = bcd2bin(tm->tm_mday);
 203        tm->tm_mon = bcd2bin(tm->tm_mon);
 204        tm->tm_year = bcd2bin(tm->tm_year);
 205
 206        /*
 207         * Account for differences between how the RTC uses the values
 208         * and how they are defined in a struct rtc_time;
 209         */
 210        if (tm->tm_year < 45)
 211                tm->tm_year += 30;
 212        tm->tm_year += 40;
 213        if (tm->tm_year < 70)
 214                tm->tm_year += 100;
 215
 216        tm->tm_mon--;
 217
 218        return rtc_valid_tm(tm);
 219}
 220
 221static int ds1286_set_time(struct device *dev, struct rtc_time *tm)
 222{
 223        struct ds1286_priv *priv = dev_get_drvdata(dev);
 224        unsigned char mon, day, hrs, min, sec;
 225        unsigned char save_control;
 226        unsigned int yrs;
 227        unsigned long flags;
 228
 229        yrs = tm->tm_year + 1900;
 230        mon = tm->tm_mon + 1;   /* tm_mon starts at zero */
 231        day = tm->tm_mday;
 232        hrs = tm->tm_hour;
 233        min = tm->tm_min;
 234        sec = tm->tm_sec;
 235
 236        if (yrs < 1970)
 237                return -EINVAL;
 238
 239        yrs -= 1940;
 240        if (yrs > 255)    /* They are unsigned */
 241                return -EINVAL;
 242
 243        if (yrs >= 100)
 244                yrs -= 100;
 245
 246        sec = bin2bcd(sec);
 247        min = bin2bcd(min);
 248        hrs = bin2bcd(hrs);
 249        day = bin2bcd(day);
 250        mon = bin2bcd(mon);
 251        yrs = bin2bcd(yrs);
 252
 253        spin_lock_irqsave(&priv->lock, flags);
 254        save_control = ds1286_rtc_read(priv, RTC_CMD);
 255        ds1286_rtc_write(priv, (save_control|RTC_TE), RTC_CMD);
 256
 257        ds1286_rtc_write(priv, yrs, RTC_YEAR);
 258        ds1286_rtc_write(priv, mon, RTC_MONTH);
 259        ds1286_rtc_write(priv, day, RTC_DATE);
 260        ds1286_rtc_write(priv, hrs, RTC_HOURS);
 261        ds1286_rtc_write(priv, min, RTC_MINUTES);
 262        ds1286_rtc_write(priv, sec, RTC_SECONDS);
 263        ds1286_rtc_write(priv, 0, RTC_HUNDREDTH_SECOND);
 264
 265        ds1286_rtc_write(priv, save_control, RTC_CMD);
 266        spin_unlock_irqrestore(&priv->lock, flags);
 267        return 0;
 268}
 269
 270static int ds1286_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
 271{
 272        struct ds1286_priv *priv = dev_get_drvdata(dev);
 273        unsigned char cmd;
 274        unsigned long flags;
 275
 276        /*
 277         * Only the values that we read from the RTC are set. That
 278         * means only tm_wday, tm_hour, tm_min.
 279         */
 280        spin_lock_irqsave(&priv->lock, flags);
 281        alm->time.tm_min = ds1286_rtc_read(priv, RTC_MINUTES_ALARM) & 0x7f;
 282        alm->time.tm_hour = ds1286_rtc_read(priv, RTC_HOURS_ALARM)  & 0x1f;
 283        alm->time.tm_wday = ds1286_rtc_read(priv, RTC_DAY_ALARM)    & 0x07;
 284        cmd = ds1286_rtc_read(priv, RTC_CMD);
 285        spin_unlock_irqrestore(&priv->lock, flags);
 286
 287        alm->time.tm_min = bcd2bin(alm->time.tm_min);
 288        alm->time.tm_hour = bcd2bin(alm->time.tm_hour);
 289        alm->time.tm_sec = 0;
 290        return 0;
 291}
 292
 293static int ds1286_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
 294{
 295        struct ds1286_priv *priv = dev_get_drvdata(dev);
 296        unsigned char hrs, min, sec;
 297
 298        hrs = alm->time.tm_hour;
 299        min = alm->time.tm_min;
 300        sec = alm->time.tm_sec;
 301
 302        if (hrs >= 24)
 303                hrs = 0xff;
 304
 305        if (min >= 60)
 306                min = 0xff;
 307
 308        if (sec != 0)
 309                return -EINVAL;
 310
 311        min = bin2bcd(min);
 312        hrs = bin2bcd(hrs);
 313
 314        spin_lock(&priv->lock);
 315        ds1286_rtc_write(priv, hrs, RTC_HOURS_ALARM);
 316        ds1286_rtc_write(priv, min, RTC_MINUTES_ALARM);
 317        spin_unlock(&priv->lock);
 318
 319        return 0;
 320}
 321
 322static const struct rtc_class_ops ds1286_ops = {
 323        .ioctl          = ds1286_ioctl,
 324        .proc           = ds1286_proc,
 325        .read_time      = ds1286_read_time,
 326        .set_time       = ds1286_set_time,
 327        .read_alarm     = ds1286_read_alarm,
 328        .set_alarm      = ds1286_set_alarm,
 329        .alarm_irq_enable = ds1286_alarm_irq_enable,
 330};
 331
 332static int ds1286_probe(struct platform_device *pdev)
 333{
 334        struct rtc_device *rtc;
 335        struct resource *res;
 336        struct ds1286_priv *priv;
 337        int ret = 0;
 338
 339        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 340        if (!res)
 341                return -ENODEV;
 342        priv = kzalloc(sizeof(struct ds1286_priv), GFP_KERNEL);
 343        if (!priv)
 344                return -ENOMEM;
 345
 346        priv->size = resource_size(res);
 347        if (!request_mem_region(res->start, priv->size, pdev->name)) {
 348                ret = -EBUSY;
 349                goto out;
 350        }
 351        priv->baseaddr = res->start;
 352        priv->rtcregs = ioremap(priv->baseaddr, priv->size);
 353        if (!priv->rtcregs) {
 354                ret = -ENOMEM;
 355                goto out;
 356        }
 357        spin_lock_init(&priv->lock);
 358        platform_set_drvdata(pdev, priv);
 359        rtc = rtc_device_register("ds1286", &pdev->dev,
 360                                  &ds1286_ops, THIS_MODULE);
 361        if (IS_ERR(rtc)) {
 362                ret = PTR_ERR(rtc);
 363                goto out;
 364        }
 365        priv->rtc = rtc;
 366        return 0;
 367
 368out:
 369        if (priv->rtc)
 370                rtc_device_unregister(priv->rtc);
 371        if (priv->rtcregs)
 372                iounmap(priv->rtcregs);
 373        if (priv->baseaddr)
 374                release_mem_region(priv->baseaddr, priv->size);
 375        kfree(priv);
 376        return ret;
 377}
 378
 379static int ds1286_remove(struct platform_device *pdev)
 380{
 381        struct ds1286_priv *priv = platform_get_drvdata(pdev);
 382
 383        rtc_device_unregister(priv->rtc);
 384        iounmap(priv->rtcregs);
 385        release_mem_region(priv->baseaddr, priv->size);
 386        kfree(priv);
 387        return 0;
 388}
 389
 390static struct platform_driver ds1286_platform_driver = {
 391        .driver         = {
 392                .name   = "rtc-ds1286",
 393                .owner  = THIS_MODULE,
 394        },
 395        .probe          = ds1286_probe,
 396        .remove         = ds1286_remove,
 397};
 398
 399module_platform_driver(ds1286_platform_driver);
 400
 401MODULE_AUTHOR("Thomas Bogendoerfer <tsbogend@alpha.franken.de>");
 402MODULE_DESCRIPTION("DS1286 RTC driver");
 403MODULE_LICENSE("GPL");
 404MODULE_VERSION(DRV_VERSION);
 405MODULE_ALIAS("platform:rtc-ds1286");
 406
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.