linux/drivers/rtc/rtc-pl031.c
<<
>>
Prefs
   1/*
   2 * drivers/rtc/rtc-pl031.c
   3 *
   4 * Real Time Clock interface for ARM AMBA PrimeCell 031 RTC
   5 *
   6 * Author: Deepak Saxena <dsaxena@plexity.net>
   7 *
   8 * Copyright 2006 (c) MontaVista Software, Inc.
   9 *
  10 * Author: Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com>
  11 * Copyright 2010 (c) ST-Ericsson AB
  12 *
  13 * This program is free software; you can redistribute it and/or
  14 * modify it under the terms of the GNU General Public License
  15 * as published by the Free Software Foundation; either version
  16 * 2 of the License, or (at your option) any later version.
  17 */
  18#include <linux/module.h>
  19#include <linux/rtc.h>
  20#include <linux/init.h>
  21#include <linux/interrupt.h>
  22#include <linux/amba/bus.h>
  23#include <linux/io.h>
  24#include <linux/bcd.h>
  25#include <linux/delay.h>
  26#include <linux/pm_wakeirq.h>
  27#include <linux/slab.h>
  28
  29/*
  30 * Register definitions
  31 */
  32#define RTC_DR          0x00    /* Data read register */
  33#define RTC_MR          0x04    /* Match register */
  34#define RTC_LR          0x08    /* Data load register */
  35#define RTC_CR          0x0c    /* Control register */
  36#define RTC_IMSC        0x10    /* Interrupt mask and set register */
  37#define RTC_RIS         0x14    /* Raw interrupt status register */
  38#define RTC_MIS         0x18    /* Masked interrupt status register */
  39#define RTC_ICR         0x1c    /* Interrupt clear register */
  40/* ST variants have additional timer functionality */
  41#define RTC_TDR         0x20    /* Timer data read register */
  42#define RTC_TLR         0x24    /* Timer data load register */
  43#define RTC_TCR         0x28    /* Timer control register */
  44#define RTC_YDR         0x30    /* Year data read register */
  45#define RTC_YMR         0x34    /* Year match register */
  46#define RTC_YLR         0x38    /* Year data load register */
  47
  48#define RTC_CR_EN       (1 << 0)        /* counter enable bit */
  49#define RTC_CR_CWEN     (1 << 26)       /* Clockwatch enable bit */
  50
  51#define RTC_TCR_EN      (1 << 1) /* Periodic timer enable bit */
  52
  53/* Common bit definitions for Interrupt status and control registers */
  54#define RTC_BIT_AI      (1 << 0) /* Alarm interrupt bit */
  55#define RTC_BIT_PI      (1 << 1) /* Periodic interrupt bit. ST variants only. */
  56
  57/* Common bit definations for ST v2 for reading/writing time */
  58#define RTC_SEC_SHIFT 0
  59#define RTC_SEC_MASK (0x3F << RTC_SEC_SHIFT) /* Second [0-59] */
  60#define RTC_MIN_SHIFT 6
  61#define RTC_MIN_MASK (0x3F << RTC_MIN_SHIFT) /* Minute [0-59] */
  62#define RTC_HOUR_SHIFT 12
  63#define RTC_HOUR_MASK (0x1F << RTC_HOUR_SHIFT) /* Hour [0-23] */
  64#define RTC_WDAY_SHIFT 17
  65#define RTC_WDAY_MASK (0x7 << RTC_WDAY_SHIFT) /* Day of Week [1-7] 1=Sunday */
  66#define RTC_MDAY_SHIFT 20
  67#define RTC_MDAY_MASK (0x1F << RTC_MDAY_SHIFT) /* Day of Month [1-31] */
  68#define RTC_MON_SHIFT 25
  69#define RTC_MON_MASK (0xF << RTC_MON_SHIFT) /* Month [1-12] 1=January */
  70
  71#define RTC_TIMER_FREQ 32768
  72
  73/**
  74 * struct pl031_vendor_data - per-vendor variations
  75 * @ops: the vendor-specific operations used on this silicon version
  76 * @clockwatch: if this is an ST Microelectronics silicon version with a
  77 *      clockwatch function
  78 * @st_weekday: if this is an ST Microelectronics silicon version that need
  79 *      the weekday fix
  80 * @irqflags: special IRQ flags per variant
  81 */
  82struct pl031_vendor_data {
  83        struct rtc_class_ops ops;
  84        bool clockwatch;
  85        bool st_weekday;
  86        unsigned long irqflags;
  87};
  88
  89struct pl031_local {
  90        struct pl031_vendor_data *vendor;
  91        struct rtc_device *rtc;
  92        void __iomem *base;
  93};
  94
  95static int pl031_alarm_irq_enable(struct device *dev,
  96        unsigned int enabled)
  97{
  98        struct pl031_local *ldata = dev_get_drvdata(dev);
  99        unsigned long imsc;
 100
 101        /* Clear any pending alarm interrupts. */
 102        writel(RTC_BIT_AI, ldata->base + RTC_ICR);
 103
 104        imsc = readl(ldata->base + RTC_IMSC);
 105
 106        if (enabled == 1)
 107                writel(imsc | RTC_BIT_AI, ldata->base + RTC_IMSC);
 108        else
 109                writel(imsc & ~RTC_BIT_AI, ldata->base + RTC_IMSC);
 110
 111        return 0;
 112}
 113
 114/*
 115 * Convert Gregorian date to ST v2 RTC format.
 116 */
 117static int pl031_stv2_tm_to_time(struct device *dev,
 118                                 struct rtc_time *tm, unsigned long *st_time,
 119        unsigned long *bcd_year)
 120{
 121        int year = tm->tm_year + 1900;
 122        int wday = tm->tm_wday;
 123
 124        /* wday masking is not working in hardware so wday must be valid */
 125        if (wday < -1 || wday > 6) {
 126                dev_err(dev, "invalid wday value %d\n", tm->tm_wday);
 127                return -EINVAL;
 128        } else if (wday == -1) {
 129                /* wday is not provided, calculate it here */
 130                unsigned long time;
 131                struct rtc_time calc_tm;
 132
 133                rtc_tm_to_time(tm, &time);
 134                rtc_time_to_tm(time, &calc_tm);
 135                wday = calc_tm.tm_wday;
 136        }
 137
 138        *bcd_year = (bin2bcd(year % 100) | bin2bcd(year / 100) << 8);
 139
 140        *st_time = ((tm->tm_mon + 1) << RTC_MON_SHIFT)
 141                        |       (tm->tm_mday << RTC_MDAY_SHIFT)
 142                        |       ((wday + 1) << RTC_WDAY_SHIFT)
 143                        |       (tm->tm_hour << RTC_HOUR_SHIFT)
 144                        |       (tm->tm_min << RTC_MIN_SHIFT)
 145                        |       (tm->tm_sec << RTC_SEC_SHIFT);
 146
 147        return 0;
 148}
 149
 150/*
 151 * Convert ST v2 RTC format to Gregorian date.
 152 */
 153static int pl031_stv2_time_to_tm(unsigned long st_time, unsigned long bcd_year,
 154        struct rtc_time *tm)
 155{
 156        tm->tm_year = bcd2bin(bcd_year) + (bcd2bin(bcd_year >> 8) * 100);
 157        tm->tm_mon  = ((st_time & RTC_MON_MASK) >> RTC_MON_SHIFT) - 1;
 158        tm->tm_mday = ((st_time & RTC_MDAY_MASK) >> RTC_MDAY_SHIFT);
 159        tm->tm_wday = ((st_time & RTC_WDAY_MASK) >> RTC_WDAY_SHIFT) - 1;
 160        tm->tm_hour = ((st_time & RTC_HOUR_MASK) >> RTC_HOUR_SHIFT);
 161        tm->tm_min  = ((st_time & RTC_MIN_MASK) >> RTC_MIN_SHIFT);
 162        tm->tm_sec  = ((st_time & RTC_SEC_MASK) >> RTC_SEC_SHIFT);
 163
 164        tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year);
 165        tm->tm_year -= 1900;
 166
 167        return 0;
 168}
 169
 170static int pl031_stv2_read_time(struct device *dev, struct rtc_time *tm)
 171{
 172        struct pl031_local *ldata = dev_get_drvdata(dev);
 173
 174        pl031_stv2_time_to_tm(readl(ldata->base + RTC_DR),
 175                        readl(ldata->base + RTC_YDR), tm);
 176
 177        return 0;
 178}
 179
 180static int pl031_stv2_set_time(struct device *dev, struct rtc_time *tm)
 181{
 182        unsigned long time;
 183        unsigned long bcd_year;
 184        struct pl031_local *ldata = dev_get_drvdata(dev);
 185        int ret;
 186
 187        ret = pl031_stv2_tm_to_time(dev, tm, &time, &bcd_year);
 188        if (ret == 0) {
 189                writel(bcd_year, ldata->base + RTC_YLR);
 190                writel(time, ldata->base + RTC_LR);
 191        }
 192
 193        return ret;
 194}
 195
 196static int pl031_stv2_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
 197{
 198        struct pl031_local *ldata = dev_get_drvdata(dev);
 199        int ret;
 200
 201        ret = pl031_stv2_time_to_tm(readl(ldata->base + RTC_MR),
 202                        readl(ldata->base + RTC_YMR), &alarm->time);
 203
 204        alarm->pending = readl(ldata->base + RTC_RIS) & RTC_BIT_AI;
 205        alarm->enabled = readl(ldata->base + RTC_IMSC) & RTC_BIT_AI;
 206
 207        return ret;
 208}
 209
 210static int pl031_stv2_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
 211{
 212        struct pl031_local *ldata = dev_get_drvdata(dev);
 213        unsigned long time;
 214        unsigned long bcd_year;
 215        int ret;
 216
 217        /* At the moment, we can only deal with non-wildcarded alarm times. */
 218        ret = rtc_valid_tm(&alarm->time);
 219        if (ret == 0) {
 220                ret = pl031_stv2_tm_to_time(dev, &alarm->time,
 221                                            &time, &bcd_year);
 222                if (ret == 0) {
 223                        writel(bcd_year, ldata->base + RTC_YMR);
 224                        writel(time, ldata->base + RTC_MR);
 225
 226                        pl031_alarm_irq_enable(dev, alarm->enabled);
 227                }
 228        }
 229
 230        return ret;
 231}
 232
 233static irqreturn_t pl031_interrupt(int irq, void *dev_id)
 234{
 235        struct pl031_local *ldata = dev_id;
 236        unsigned long rtcmis;
 237        unsigned long events = 0;
 238
 239        rtcmis = readl(ldata->base + RTC_MIS);
 240        if (rtcmis & RTC_BIT_AI) {
 241                writel(RTC_BIT_AI, ldata->base + RTC_ICR);
 242                events |= (RTC_AF | RTC_IRQF);
 243                rtc_update_irq(ldata->rtc, 1, events);
 244
 245                return IRQ_HANDLED;
 246        }
 247
 248        return IRQ_NONE;
 249}
 250
 251static int pl031_read_time(struct device *dev, struct rtc_time *tm)
 252{
 253        struct pl031_local *ldata = dev_get_drvdata(dev);
 254
 255        rtc_time_to_tm(readl(ldata->base + RTC_DR), tm);
 256
 257        return 0;
 258}
 259
 260static int pl031_set_time(struct device *dev, struct rtc_time *tm)
 261{
 262        unsigned long time;
 263        struct pl031_local *ldata = dev_get_drvdata(dev);
 264        int ret;
 265
 266        ret = rtc_tm_to_time(tm, &time);
 267
 268        if (ret == 0)
 269                writel(time, ldata->base + RTC_LR);
 270
 271        return ret;
 272}
 273
 274static int pl031_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
 275{
 276        struct pl031_local *ldata = dev_get_drvdata(dev);
 277
 278        rtc_time_to_tm(readl(ldata->base + RTC_MR), &alarm->time);
 279
 280        alarm->pending = readl(ldata->base + RTC_RIS) & RTC_BIT_AI;
 281        alarm->enabled = readl(ldata->base + RTC_IMSC) & RTC_BIT_AI;
 282
 283        return 0;
 284}
 285
 286static int pl031_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
 287{
 288        struct pl031_local *ldata = dev_get_drvdata(dev);
 289        unsigned long time;
 290        int ret;
 291
 292        /* At the moment, we can only deal with non-wildcarded alarm times. */
 293        ret = rtc_valid_tm(&alarm->time);
 294        if (ret == 0) {
 295                ret = rtc_tm_to_time(&alarm->time, &time);
 296                if (ret == 0) {
 297                        writel(time, ldata->base + RTC_MR);
 298                        pl031_alarm_irq_enable(dev, alarm->enabled);
 299                }
 300        }
 301
 302        return ret;
 303}
 304
 305static int pl031_remove(struct amba_device *adev)
 306{
 307        struct pl031_local *ldata = dev_get_drvdata(&adev->dev);
 308
 309        dev_pm_clear_wake_irq(&adev->dev);
 310        device_init_wakeup(&adev->dev, false);
 311        if (adev->irq[0])
 312                free_irq(adev->irq[0], ldata);
 313        rtc_device_unregister(ldata->rtc);
 314        amba_release_regions(adev);
 315
 316        return 0;
 317}
 318
 319static int pl031_probe(struct amba_device *adev, const struct amba_id *id)
 320{
 321        int ret;
 322        struct pl031_local *ldata;
 323        struct pl031_vendor_data *vendor = id->data;
 324        struct rtc_class_ops *ops;
 325        unsigned long time, data;
 326
 327        ret = amba_request_regions(adev, NULL);
 328        if (ret)
 329                goto err_req;
 330
 331        ldata = devm_kzalloc(&adev->dev, sizeof(struct pl031_local),
 332                             GFP_KERNEL);
 333        ops = devm_kmemdup(&adev->dev, &vendor->ops, sizeof(vendor->ops),
 334                           GFP_KERNEL);
 335        if (!ldata || !ops) {
 336                ret = -ENOMEM;
 337                goto out;
 338        }
 339
 340        ldata->vendor = vendor;
 341        ldata->base = devm_ioremap(&adev->dev, adev->res.start,
 342                                   resource_size(&adev->res));
 343        if (!ldata->base) {
 344                ret = -ENOMEM;
 345                goto out;
 346        }
 347
 348        amba_set_drvdata(adev, ldata);
 349
 350        dev_dbg(&adev->dev, "designer ID = 0x%02x\n", amba_manf(adev));
 351        dev_dbg(&adev->dev, "revision = 0x%01x\n", amba_rev(adev));
 352
 353        data = readl(ldata->base + RTC_CR);
 354        /* Enable the clockwatch on ST Variants */
 355        if (vendor->clockwatch)
 356                data |= RTC_CR_CWEN;
 357        else
 358                data |= RTC_CR_EN;
 359        writel(data, ldata->base + RTC_CR);
 360
 361        /*
 362         * On ST PL031 variants, the RTC reset value does not provide correct
 363         * weekday for 2000-01-01. Correct the erroneous sunday to saturday.
 364         */
 365        if (vendor->st_weekday) {
 366                if (readl(ldata->base + RTC_YDR) == 0x2000) {
 367                        time = readl(ldata->base + RTC_DR);
 368                        if ((time &
 369                             (RTC_MON_MASK | RTC_MDAY_MASK | RTC_WDAY_MASK))
 370                            == 0x02120000) {
 371                                time = time | (0x7 << RTC_WDAY_SHIFT);
 372                                writel(0x2000, ldata->base + RTC_YLR);
 373                                writel(time, ldata->base + RTC_LR);
 374                        }
 375                }
 376        }
 377
 378        if (!adev->irq[0]) {
 379                /* When there's no interrupt, no point in exposing the alarm */
 380                ops->read_alarm = NULL;
 381                ops->set_alarm = NULL;
 382                ops->alarm_irq_enable = NULL;
 383        }
 384
 385        device_init_wakeup(&adev->dev, true);
 386        ldata->rtc = rtc_device_register("pl031", &adev->dev, ops,
 387                                        THIS_MODULE);
 388        if (IS_ERR(ldata->rtc)) {
 389                ret = PTR_ERR(ldata->rtc);
 390                goto out;
 391        }
 392
 393        if (adev->irq[0]) {
 394                ret = request_irq(adev->irq[0], pl031_interrupt,
 395                                  vendor->irqflags, "rtc-pl031", ldata);
 396                if (ret)
 397                        goto out_no_irq;
 398                dev_pm_set_wake_irq(&adev->dev, adev->irq[0]);
 399        }
 400        return 0;
 401
 402out_no_irq:
 403        rtc_device_unregister(ldata->rtc);
 404out:
 405        amba_release_regions(adev);
 406err_req:
 407
 408        return ret;
 409}
 410
 411/* Operations for the original ARM version */
 412static struct pl031_vendor_data arm_pl031 = {
 413        .ops = {
 414                .read_time = pl031_read_time,
 415                .set_time = pl031_set_time,
 416                .read_alarm = pl031_read_alarm,
 417                .set_alarm = pl031_set_alarm,
 418                .alarm_irq_enable = pl031_alarm_irq_enable,
 419        },
 420};
 421
 422/* The First ST derivative */
 423static struct pl031_vendor_data stv1_pl031 = {
 424        .ops = {
 425                .read_time = pl031_read_time,
 426                .set_time = pl031_set_time,
 427                .read_alarm = pl031_read_alarm,
 428                .set_alarm = pl031_set_alarm,
 429                .alarm_irq_enable = pl031_alarm_irq_enable,
 430        },
 431        .clockwatch = true,
 432        .st_weekday = true,
 433};
 434
 435/* And the second ST derivative */
 436static struct pl031_vendor_data stv2_pl031 = {
 437        .ops = {
 438                .read_time = pl031_stv2_read_time,
 439                .set_time = pl031_stv2_set_time,
 440                .read_alarm = pl031_stv2_read_alarm,
 441                .set_alarm = pl031_stv2_set_alarm,
 442                .alarm_irq_enable = pl031_alarm_irq_enable,
 443        },
 444        .clockwatch = true,
 445        .st_weekday = true,
 446        /*
 447         * This variant shares the IRQ with another block and must not
 448         * suspend that IRQ line.
 449         * TODO check if it shares with IRQF_NO_SUSPEND user, else we can
 450         * remove IRQF_COND_SUSPEND
 451         */
 452        .irqflags = IRQF_SHARED | IRQF_COND_SUSPEND,
 453};
 454
 455static const struct amba_id pl031_ids[] = {
 456        {
 457                .id = 0x00041031,
 458                .mask = 0x000fffff,
 459                .data = &arm_pl031,
 460        },
 461        /* ST Micro variants */
 462        {
 463                .id = 0x00180031,
 464                .mask = 0x00ffffff,
 465                .data = &stv1_pl031,
 466        },
 467        {
 468                .id = 0x00280031,
 469                .mask = 0x00ffffff,
 470                .data = &stv2_pl031,
 471        },
 472        {0, 0},
 473};
 474
 475MODULE_DEVICE_TABLE(amba, pl031_ids);
 476
 477static struct amba_driver pl031_driver = {
 478        .drv = {
 479                .name = "rtc-pl031",
 480        },
 481        .id_table = pl031_ids,
 482        .probe = pl031_probe,
 483        .remove = pl031_remove,
 484};
 485
 486module_amba_driver(pl031_driver);
 487
 488MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net>");
 489MODULE_DESCRIPTION("ARM AMBA PL031 RTC Driver");
 490MODULE_LICENSE("GPL");
 491