linux/drivers/rtc/rtc-davinci.c
<<
>>
Prefs
   1/*
   2 * DaVinci Power Management and Real Time Clock Driver for TI platforms
   3 *
   4 * Copyright (C) 2009 Texas Instruments, Inc
   5 *
   6 * Author: Miguel Aguilar <miguel.aguilar@ridgerun.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 as published by
  10 * the Free Software Foundation; either version 2 of the License, or
  11 * (at your option) any later version.
  12 *
  13 * This program is distributed in the hope that it will be useful,
  14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16 * GNU General Public License for more details.
  17 *
  18 * You should have received a copy of the GNU General Public License
  19 * along with this program; if not, write to the Free Software
  20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  21 */
  22#include <linux/kernel.h>
  23#include <linux/init.h>
  24#include <linux/module.h>
  25#include <linux/ioport.h>
  26#include <linux/delay.h>
  27#include <linux/spinlock.h>
  28#include <linux/rtc.h>
  29#include <linux/bcd.h>
  30#include <linux/platform_device.h>
  31#include <linux/io.h>
  32#include <linux/slab.h>
  33
  34/*
  35 * The DaVinci RTC is a simple RTC with the following
  36 * Sec: 0 - 59 : BCD count
  37 * Min: 0 - 59 : BCD count
  38 * Hour: 0 - 23 : BCD count
  39 * Day: 0 - 0x7FFF(32767) : Binary count ( Over 89 years )
  40 */
  41
  42/* PRTC interface registers */
  43#define DAVINCI_PRTCIF_PID              0x00
  44#define PRTCIF_CTLR                     0x04
  45#define PRTCIF_LDATA                    0x08
  46#define PRTCIF_UDATA                    0x0C
  47#define PRTCIF_INTEN                    0x10
  48#define PRTCIF_INTFLG                   0x14
  49
  50/* PRTCIF_CTLR bit fields */
  51#define PRTCIF_CTLR_BUSY                BIT(31)
  52#define PRTCIF_CTLR_SIZE                BIT(25)
  53#define PRTCIF_CTLR_DIR                 BIT(24)
  54#define PRTCIF_CTLR_BENU_MSB            BIT(23)
  55#define PRTCIF_CTLR_BENU_3RD_BYTE       BIT(22)
  56#define PRTCIF_CTLR_BENU_2ND_BYTE       BIT(21)
  57#define PRTCIF_CTLR_BENU_LSB            BIT(20)
  58#define PRTCIF_CTLR_BENU_MASK           (0x00F00000)
  59#define PRTCIF_CTLR_BENL_MSB            BIT(19)
  60#define PRTCIF_CTLR_BENL_3RD_BYTE       BIT(18)
  61#define PRTCIF_CTLR_BENL_2ND_BYTE       BIT(17)
  62#define PRTCIF_CTLR_BENL_LSB            BIT(16)
  63#define PRTCIF_CTLR_BENL_MASK           (0x000F0000)
  64
  65/* PRTCIF_INTEN bit fields */
  66#define PRTCIF_INTEN_RTCSS              BIT(1)
  67#define PRTCIF_INTEN_RTCIF              BIT(0)
  68#define PRTCIF_INTEN_MASK               (PRTCIF_INTEN_RTCSS \
  69                                        | PRTCIF_INTEN_RTCIF)
  70
  71/* PRTCIF_INTFLG bit fields */
  72#define PRTCIF_INTFLG_RTCSS             BIT(1)
  73#define PRTCIF_INTFLG_RTCIF             BIT(0)
  74#define PRTCIF_INTFLG_MASK              (PRTCIF_INTFLG_RTCSS \
  75                                        | PRTCIF_INTFLG_RTCIF)
  76
  77/* PRTC subsystem registers */
  78#define PRTCSS_RTC_INTC_EXTENA1         (0x0C)
  79#define PRTCSS_RTC_CTRL                 (0x10)
  80#define PRTCSS_RTC_WDT                  (0x11)
  81#define PRTCSS_RTC_TMR0                 (0x12)
  82#define PRTCSS_RTC_TMR1                 (0x13)
  83#define PRTCSS_RTC_CCTRL                (0x14)
  84#define PRTCSS_RTC_SEC                  (0x15)
  85#define PRTCSS_RTC_MIN                  (0x16)
  86#define PRTCSS_RTC_HOUR                 (0x17)
  87#define PRTCSS_RTC_DAY0                 (0x18)
  88#define PRTCSS_RTC_DAY1                 (0x19)
  89#define PRTCSS_RTC_AMIN                 (0x1A)
  90#define PRTCSS_RTC_AHOUR                (0x1B)
  91#define PRTCSS_RTC_ADAY0                (0x1C)
  92#define PRTCSS_RTC_ADAY1                (0x1D)
  93#define PRTCSS_RTC_CLKC_CNT             (0x20)
  94
  95/* PRTCSS_RTC_INTC_EXTENA1 */
  96#define PRTCSS_RTC_INTC_EXTENA1_MASK    (0x07)
  97
  98/* PRTCSS_RTC_CTRL bit fields */
  99#define PRTCSS_RTC_CTRL_WDTBUS          BIT(7)
 100#define PRTCSS_RTC_CTRL_WEN             BIT(6)
 101#define PRTCSS_RTC_CTRL_WDRT            BIT(5)
 102#define PRTCSS_RTC_CTRL_WDTFLG          BIT(4)
 103#define PRTCSS_RTC_CTRL_TE              BIT(3)
 104#define PRTCSS_RTC_CTRL_TIEN            BIT(2)
 105#define PRTCSS_RTC_CTRL_TMRFLG          BIT(1)
 106#define PRTCSS_RTC_CTRL_TMMD            BIT(0)
 107
 108/* PRTCSS_RTC_CCTRL bit fields */
 109#define PRTCSS_RTC_CCTRL_CALBUSY        BIT(7)
 110#define PRTCSS_RTC_CCTRL_DAEN           BIT(5)
 111#define PRTCSS_RTC_CCTRL_HAEN           BIT(4)
 112#define PRTCSS_RTC_CCTRL_MAEN           BIT(3)
 113#define PRTCSS_RTC_CCTRL_ALMFLG         BIT(2)
 114#define PRTCSS_RTC_CCTRL_AIEN           BIT(1)
 115#define PRTCSS_RTC_CCTRL_CAEN           BIT(0)
 116
 117static DEFINE_SPINLOCK(davinci_rtc_lock);
 118
 119struct davinci_rtc {
 120        struct rtc_device               *rtc;
 121        void __iomem                    *base;
 122        resource_size_t                 pbase;
 123        size_t                          base_size;
 124        int                             irq;
 125};
 126
 127static inline void rtcif_write(struct davinci_rtc *davinci_rtc,
 128                               u32 val, u32 addr)
 129{
 130        writel(val, davinci_rtc->base + addr);
 131}
 132
 133static inline u32 rtcif_read(struct davinci_rtc *davinci_rtc, u32 addr)
 134{
 135        return readl(davinci_rtc->base + addr);
 136}
 137
 138static inline void rtcif_wait(struct davinci_rtc *davinci_rtc)
 139{
 140        while (rtcif_read(davinci_rtc, PRTCIF_CTLR) & PRTCIF_CTLR_BUSY)
 141                cpu_relax();
 142}
 143
 144static inline void rtcss_write(struct davinci_rtc *davinci_rtc,
 145                               unsigned long val, u8 addr)
 146{
 147        rtcif_wait(davinci_rtc);
 148
 149        rtcif_write(davinci_rtc, PRTCIF_CTLR_BENL_LSB | addr, PRTCIF_CTLR);
 150        rtcif_write(davinci_rtc, val, PRTCIF_LDATA);
 151
 152        rtcif_wait(davinci_rtc);
 153}
 154
 155static inline u8 rtcss_read(struct davinci_rtc *davinci_rtc, u8 addr)
 156{
 157        rtcif_wait(davinci_rtc);
 158
 159        rtcif_write(davinci_rtc, PRTCIF_CTLR_DIR | PRTCIF_CTLR_BENL_LSB | addr,
 160                    PRTCIF_CTLR);
 161
 162        rtcif_wait(davinci_rtc);
 163
 164        return rtcif_read(davinci_rtc, PRTCIF_LDATA);
 165}
 166
 167static inline void davinci_rtcss_calendar_wait(struct davinci_rtc *davinci_rtc)
 168{
 169        while (rtcss_read(davinci_rtc, PRTCSS_RTC_CCTRL) &
 170               PRTCSS_RTC_CCTRL_CALBUSY)
 171                cpu_relax();
 172}
 173
 174static irqreturn_t davinci_rtc_interrupt(int irq, void *class_dev)
 175{
 176        struct davinci_rtc *davinci_rtc = class_dev;
 177        unsigned long events = 0;
 178        u32 irq_flg;
 179        u8 alm_irq, tmr_irq;
 180        u8 rtc_ctrl, rtc_cctrl;
 181        int ret = IRQ_NONE;
 182
 183        irq_flg = rtcif_read(davinci_rtc, PRTCIF_INTFLG) &
 184                  PRTCIF_INTFLG_RTCSS;
 185
 186        alm_irq = rtcss_read(davinci_rtc, PRTCSS_RTC_CCTRL) &
 187                  PRTCSS_RTC_CCTRL_ALMFLG;
 188
 189        tmr_irq = rtcss_read(davinci_rtc, PRTCSS_RTC_CTRL) &
 190                  PRTCSS_RTC_CTRL_TMRFLG;
 191
 192        if (irq_flg) {
 193                if (alm_irq) {
 194                        events |= RTC_IRQF | RTC_AF;
 195                        rtc_cctrl = rtcss_read(davinci_rtc, PRTCSS_RTC_CCTRL);
 196                        rtc_cctrl |=  PRTCSS_RTC_CCTRL_ALMFLG;
 197                        rtcss_write(davinci_rtc, rtc_cctrl, PRTCSS_RTC_CCTRL);
 198                } else if (tmr_irq) {
 199                        events |= RTC_IRQF | RTC_PF;
 200                        rtc_ctrl = rtcss_read(davinci_rtc, PRTCSS_RTC_CTRL);
 201                        rtc_ctrl |=  PRTCSS_RTC_CTRL_TMRFLG;
 202                        rtcss_write(davinci_rtc, rtc_ctrl, PRTCSS_RTC_CTRL);
 203                }
 204
 205                rtcif_write(davinci_rtc, PRTCIF_INTFLG_RTCSS,
 206                                    PRTCIF_INTFLG);
 207                rtc_update_irq(davinci_rtc->rtc, 1, events);
 208
 209                ret = IRQ_HANDLED;
 210        }
 211
 212        return ret;
 213}
 214
 215static int
 216davinci_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
 217{
 218        struct davinci_rtc *davinci_rtc = dev_get_drvdata(dev);
 219        u8 rtc_ctrl;
 220        unsigned long flags;
 221        int ret = 0;
 222
 223        spin_lock_irqsave(&davinci_rtc_lock, flags);
 224
 225        rtc_ctrl = rtcss_read(davinci_rtc, PRTCSS_RTC_CTRL);
 226
 227        switch (cmd) {
 228        case RTC_WIE_ON:
 229                rtc_ctrl |= PRTCSS_RTC_CTRL_WEN | PRTCSS_RTC_CTRL_WDTFLG;
 230                break;
 231        case RTC_WIE_OFF:
 232                rtc_ctrl &= ~PRTCSS_RTC_CTRL_WEN;
 233                break;
 234        default:
 235                ret = -ENOIOCTLCMD;
 236        }
 237
 238        rtcss_write(davinci_rtc, rtc_ctrl, PRTCSS_RTC_CTRL);
 239
 240        spin_unlock_irqrestore(&davinci_rtc_lock, flags);
 241
 242        return ret;
 243}
 244
 245static int convertfromdays(u16 days, struct rtc_time *tm)
 246{
 247        int tmp_days, year, mon;
 248
 249        for (year = 2000;; year++) {
 250                tmp_days = rtc_year_days(1, 12, year);
 251                if (days >= tmp_days)
 252                        days -= tmp_days;
 253                else {
 254                        for (mon = 0;; mon++) {
 255                                tmp_days = rtc_month_days(mon, year);
 256                                if (days >= tmp_days) {
 257                                        days -= tmp_days;
 258                                } else {
 259                                        tm->tm_year = year - 1900;
 260                                        tm->tm_mon = mon;
 261                                        tm->tm_mday = days + 1;
 262                                        break;
 263                                }
 264                        }
 265                        break;
 266                }
 267        }
 268        return 0;
 269}
 270
 271static int convert2days(u16 *days, struct rtc_time *tm)
 272{
 273        int i;
 274        *days = 0;
 275
 276        /* epoch == 1900 */
 277        if (tm->tm_year < 100 || tm->tm_year > 199)
 278                return -EINVAL;
 279
 280        for (i = 2000; i < 1900 + tm->tm_year; i++)
 281                *days += rtc_year_days(1, 12, i);
 282
 283        *days += rtc_year_days(tm->tm_mday, tm->tm_mon, 1900 + tm->tm_year);
 284
 285        return 0;
 286}
 287
 288static int davinci_rtc_read_time(struct device *dev, struct rtc_time *tm)
 289{
 290        struct davinci_rtc *davinci_rtc = dev_get_drvdata(dev);
 291        u16 days = 0;
 292        u8 day0, day1;
 293        unsigned long flags;
 294
 295        spin_lock_irqsave(&davinci_rtc_lock, flags);
 296
 297        davinci_rtcss_calendar_wait(davinci_rtc);
 298        tm->tm_sec = bcd2bin(rtcss_read(davinci_rtc, PRTCSS_RTC_SEC));
 299
 300        davinci_rtcss_calendar_wait(davinci_rtc);
 301        tm->tm_min = bcd2bin(rtcss_read(davinci_rtc, PRTCSS_RTC_MIN));
 302
 303        davinci_rtcss_calendar_wait(davinci_rtc);
 304        tm->tm_hour = bcd2bin(rtcss_read(davinci_rtc, PRTCSS_RTC_HOUR));
 305
 306        davinci_rtcss_calendar_wait(davinci_rtc);
 307        day0 = rtcss_read(davinci_rtc, PRTCSS_RTC_DAY0);
 308
 309        davinci_rtcss_calendar_wait(davinci_rtc);
 310        day1 = rtcss_read(davinci_rtc, PRTCSS_RTC_DAY1);
 311
 312        spin_unlock_irqrestore(&davinci_rtc_lock, flags);
 313
 314        days |= day1;
 315        days <<= 8;
 316        days |= day0;
 317
 318        if (convertfromdays(days, tm) < 0)
 319                return -EINVAL;
 320
 321        return 0;
 322}
 323
 324static int davinci_rtc_set_time(struct device *dev, struct rtc_time *tm)
 325{
 326        struct davinci_rtc *davinci_rtc = dev_get_drvdata(dev);
 327        u16 days;
 328        u8 rtc_cctrl;
 329        unsigned long flags;
 330
 331        if (convert2days(&days, tm) < 0)
 332                return -EINVAL;
 333
 334        spin_lock_irqsave(&davinci_rtc_lock, flags);
 335
 336        davinci_rtcss_calendar_wait(davinci_rtc);
 337        rtcss_write(davinci_rtc, bin2bcd(tm->tm_sec), PRTCSS_RTC_SEC);
 338
 339        davinci_rtcss_calendar_wait(davinci_rtc);
 340        rtcss_write(davinci_rtc, bin2bcd(tm->tm_min), PRTCSS_RTC_MIN);
 341
 342        davinci_rtcss_calendar_wait(davinci_rtc);
 343        rtcss_write(davinci_rtc, bin2bcd(tm->tm_hour), PRTCSS_RTC_HOUR);
 344
 345        davinci_rtcss_calendar_wait(davinci_rtc);
 346        rtcss_write(davinci_rtc, days & 0xFF, PRTCSS_RTC_DAY0);
 347
 348        davinci_rtcss_calendar_wait(davinci_rtc);
 349        rtcss_write(davinci_rtc, (days & 0xFF00) >> 8, PRTCSS_RTC_DAY1);
 350
 351        rtc_cctrl = rtcss_read(davinci_rtc, PRTCSS_RTC_CCTRL);
 352        rtc_cctrl |= PRTCSS_RTC_CCTRL_CAEN;
 353        rtcss_write(davinci_rtc, rtc_cctrl, PRTCSS_RTC_CCTRL);
 354
 355        spin_unlock_irqrestore(&davinci_rtc_lock, flags);
 356
 357        return 0;
 358}
 359
 360static int davinci_rtc_alarm_irq_enable(struct device *dev,
 361                                        unsigned int enabled)
 362{
 363        struct davinci_rtc *davinci_rtc = dev_get_drvdata(dev);
 364        unsigned long flags;
 365        u8 rtc_cctrl = rtcss_read(davinci_rtc, PRTCSS_RTC_CCTRL);
 366
 367        spin_lock_irqsave(&davinci_rtc_lock, flags);
 368
 369        if (enabled)
 370                rtc_cctrl |= PRTCSS_RTC_CCTRL_DAEN |
 371                             PRTCSS_RTC_CCTRL_HAEN |
 372                             PRTCSS_RTC_CCTRL_MAEN |
 373                             PRTCSS_RTC_CCTRL_ALMFLG |
 374                             PRTCSS_RTC_CCTRL_AIEN;
 375        else
 376                rtc_cctrl &= ~PRTCSS_RTC_CCTRL_AIEN;
 377
 378        davinci_rtcss_calendar_wait(davinci_rtc);
 379        rtcss_write(davinci_rtc, rtc_cctrl, PRTCSS_RTC_CCTRL);
 380
 381        spin_unlock_irqrestore(&davinci_rtc_lock, flags);
 382
 383        return 0;
 384}
 385
 386static int davinci_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
 387{
 388        struct davinci_rtc *davinci_rtc = dev_get_drvdata(dev);
 389        u16 days = 0;
 390        u8 day0, day1;
 391        unsigned long flags;
 392
 393        spin_lock_irqsave(&davinci_rtc_lock, flags);
 394
 395        davinci_rtcss_calendar_wait(davinci_rtc);
 396        alm->time.tm_min = bcd2bin(rtcss_read(davinci_rtc, PRTCSS_RTC_AMIN));
 397
 398        davinci_rtcss_calendar_wait(davinci_rtc);
 399        alm->time.tm_hour = bcd2bin(rtcss_read(davinci_rtc, PRTCSS_RTC_AHOUR));
 400
 401        davinci_rtcss_calendar_wait(davinci_rtc);
 402        day0 = rtcss_read(davinci_rtc, PRTCSS_RTC_ADAY0);
 403
 404        davinci_rtcss_calendar_wait(davinci_rtc);
 405        day1 = rtcss_read(davinci_rtc, PRTCSS_RTC_ADAY1);
 406
 407        spin_unlock_irqrestore(&davinci_rtc_lock, flags);
 408        days |= day1;
 409        days <<= 8;
 410        days |= day0;
 411
 412        if (convertfromdays(days, &alm->time) < 0)
 413                return -EINVAL;
 414
 415        alm->pending = !!(rtcss_read(davinci_rtc,
 416                          PRTCSS_RTC_CCTRL) &
 417                        PRTCSS_RTC_CCTRL_AIEN);
 418        alm->enabled = alm->pending && device_may_wakeup(dev);
 419
 420        return 0;
 421}
 422
 423static int davinci_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
 424{
 425        struct davinci_rtc *davinci_rtc = dev_get_drvdata(dev);
 426        unsigned long flags;
 427        u16 days;
 428
 429        if (alm->time.tm_mday <= 0 && alm->time.tm_mon < 0
 430            && alm->time.tm_year < 0) {
 431                struct rtc_time tm;
 432                unsigned long now, then;
 433
 434                davinci_rtc_read_time(dev, &tm);
 435                rtc_tm_to_time(&tm, &now);
 436
 437                alm->time.tm_mday = tm.tm_mday;
 438                alm->time.tm_mon = tm.tm_mon;
 439                alm->time.tm_year = tm.tm_year;
 440                rtc_tm_to_time(&alm->time, &then);
 441
 442                if (then < now) {
 443                        rtc_time_to_tm(now + 24 * 60 * 60, &tm);
 444                        alm->time.tm_mday = tm.tm_mday;
 445                        alm->time.tm_mon = tm.tm_mon;
 446                        alm->time.tm_year = tm.tm_year;
 447                }
 448        }
 449
 450        if (convert2days(&days, &alm->time) < 0)
 451                return -EINVAL;
 452
 453        spin_lock_irqsave(&davinci_rtc_lock, flags);
 454
 455        davinci_rtcss_calendar_wait(davinci_rtc);
 456        rtcss_write(davinci_rtc, bin2bcd(alm->time.tm_min), PRTCSS_RTC_AMIN);
 457
 458        davinci_rtcss_calendar_wait(davinci_rtc);
 459        rtcss_write(davinci_rtc, bin2bcd(alm->time.tm_hour), PRTCSS_RTC_AHOUR);
 460
 461        davinci_rtcss_calendar_wait(davinci_rtc);
 462        rtcss_write(davinci_rtc, days & 0xFF, PRTCSS_RTC_ADAY0);
 463
 464        davinci_rtcss_calendar_wait(davinci_rtc);
 465        rtcss_write(davinci_rtc, (days & 0xFF00) >> 8, PRTCSS_RTC_ADAY1);
 466
 467        spin_unlock_irqrestore(&davinci_rtc_lock, flags);
 468
 469        return 0;
 470}
 471
 472static struct rtc_class_ops davinci_rtc_ops = {
 473        .ioctl                  = davinci_rtc_ioctl,
 474        .read_time              = davinci_rtc_read_time,
 475        .set_time               = davinci_rtc_set_time,
 476        .alarm_irq_enable       = davinci_rtc_alarm_irq_enable,
 477        .read_alarm             = davinci_rtc_read_alarm,
 478        .set_alarm              = davinci_rtc_set_alarm,
 479};
 480
 481static int __init davinci_rtc_probe(struct platform_device *pdev)
 482{
 483        struct device *dev = &pdev->dev;
 484        struct davinci_rtc *davinci_rtc;
 485        struct resource *res, *mem;
 486        int ret = 0;
 487
 488        davinci_rtc = devm_kzalloc(&pdev->dev, sizeof(struct davinci_rtc), GFP_KERNEL);
 489        if (!davinci_rtc) {
 490                dev_dbg(dev, "could not allocate memory for private data\n");
 491                return -ENOMEM;
 492        }
 493
 494        davinci_rtc->irq = platform_get_irq(pdev, 0);
 495        if (davinci_rtc->irq < 0) {
 496                dev_err(dev, "no RTC irq\n");
 497                return davinci_rtc->irq;
 498        }
 499
 500        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 501        if (!res) {
 502                dev_err(dev, "no mem resource\n");
 503                return -EINVAL;
 504        }
 505
 506        davinci_rtc->pbase = res->start;
 507        davinci_rtc->base_size = resource_size(res);
 508
 509        mem = devm_request_mem_region(dev, davinci_rtc->pbase,
 510                                davinci_rtc->base_size, pdev->name);
 511        if (!mem) {
 512                dev_err(dev, "RTC registers at %08x are not free\n",
 513                        davinci_rtc->pbase);
 514                return -EBUSY;
 515        }
 516
 517        davinci_rtc->base = devm_ioremap(dev, davinci_rtc->pbase,
 518                                        davinci_rtc->base_size);
 519        if (!davinci_rtc->base) {
 520                dev_err(dev, "unable to ioremap MEM resource\n");
 521                return -ENOMEM;
 522        }
 523
 524        platform_set_drvdata(pdev, davinci_rtc);
 525
 526        davinci_rtc->rtc = rtc_device_register(pdev->name, &pdev->dev,
 527                                    &davinci_rtc_ops, THIS_MODULE);
 528        if (IS_ERR(davinci_rtc->rtc)) {
 529                ret = PTR_ERR(davinci_rtc->rtc);
 530                dev_err(dev, "unable to register RTC device, err %d\n",
 531                                ret);
 532                goto fail1;
 533        }
 534
 535        rtcif_write(davinci_rtc, PRTCIF_INTFLG_RTCSS, PRTCIF_INTFLG);
 536        rtcif_write(davinci_rtc, 0, PRTCIF_INTEN);
 537        rtcss_write(davinci_rtc, 0, PRTCSS_RTC_INTC_EXTENA1);
 538
 539        rtcss_write(davinci_rtc, 0, PRTCSS_RTC_CTRL);
 540        rtcss_write(davinci_rtc, 0, PRTCSS_RTC_CCTRL);
 541
 542        ret = devm_request_irq(dev, davinci_rtc->irq, davinci_rtc_interrupt,
 543                          0, "davinci_rtc", davinci_rtc);
 544        if (ret < 0) {
 545                dev_err(dev, "unable to register davinci RTC interrupt\n");
 546                goto fail2;
 547        }
 548
 549        /* Enable interrupts */
 550        rtcif_write(davinci_rtc, PRTCIF_INTEN_RTCSS, PRTCIF_INTEN);
 551        rtcss_write(davinci_rtc, PRTCSS_RTC_INTC_EXTENA1_MASK,
 552                            PRTCSS_RTC_INTC_EXTENA1);
 553
 554        rtcss_write(davinci_rtc, PRTCSS_RTC_CCTRL_CAEN, PRTCSS_RTC_CCTRL);
 555
 556        device_init_wakeup(&pdev->dev, 0);
 557
 558        return 0;
 559
 560fail2:
 561        rtc_device_unregister(davinci_rtc->rtc);
 562fail1:
 563        platform_set_drvdata(pdev, NULL);
 564        return ret;
 565}
 566
 567static int davinci_rtc_remove(struct platform_device *pdev)
 568{
 569        struct davinci_rtc *davinci_rtc = platform_get_drvdata(pdev);
 570
 571        device_init_wakeup(&pdev->dev, 0);
 572
 573        rtcif_write(davinci_rtc, 0, PRTCIF_INTEN);
 574
 575        rtc_device_unregister(davinci_rtc->rtc);
 576
 577        platform_set_drvdata(pdev, NULL);
 578
 579        return 0;
 580}
 581
 582static struct platform_driver davinci_rtc_driver = {
 583        .probe          = davinci_rtc_probe,
 584        .remove         = davinci_rtc_remove,
 585        .driver         = {
 586                .name = "rtc_davinci",
 587                .owner = THIS_MODULE,
 588        },
 589};
 590
 591static int __init rtc_init(void)
 592{
 593        return platform_driver_probe(&davinci_rtc_driver, davinci_rtc_probe);
 594}
 595module_init(rtc_init);
 596
 597static void __exit rtc_exit(void)
 598{
 599        platform_driver_unregister(&davinci_rtc_driver);
 600}
 601module_exit(rtc_exit);
 602
 603MODULE_AUTHOR("Miguel Aguilar <miguel.aguilar@ridgerun.com>");
 604MODULE_DESCRIPTION("Texas Instruments DaVinci PRTC Driver");
 605MODULE_LICENSE("GPL");
 606
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.