~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to drivers/rtc/rtc-davinci.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
117
static DEFINE_SPINLOCK(davinci_rtc_lock);
 
118
 
 
119
struct 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
 
 
127
static inline void rtcif_write(struct davinci_rtc *davinci_rtc,
 
128
                               u32 val, u32 addr)
 
129
{
 
130
        writel(val, davinci_rtc->base + addr);
 
131
}
 
132
 
 
133
static inline u32 rtcif_read(struct davinci_rtc *davinci_rtc, u32 addr)
 
134
{
 
135
        return readl(davinci_rtc->base + addr);
 
136
}
 
137
 
 
138
static 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
 
 
144
static 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
 
 
155
static 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
 
 
167
static 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
 
 
174
static 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
 
 
215
static int
 
216
davinci_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
 
 
245
static 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
 
 
271
static 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
 
 
288
static 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
 
 
324
static 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
 
 
360
static 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
 
 
386
static 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
 
 
423
static 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
 
 
472
static 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
 
 
481
static 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 = kzalloc(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
                ret = davinci_rtc->irq;
 
498
                goto fail1;
 
499
        }
 
500
 
 
501
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 
502
        if (!res) {
 
503
                dev_err(dev, "no mem resource\n");
 
504
                ret = -EINVAL;
 
505
                goto fail1;
 
506
        }
 
507
 
 
508
        davinci_rtc->pbase = res->start;
 
509
        davinci_rtc->base_size = resource_size(res);
 
510
 
 
511
        mem = request_mem_region(davinci_rtc->pbase, davinci_rtc->base_size,
 
512
                                 pdev->name);
 
513
        if (!mem) {
 
514
                dev_err(dev, "RTC registers at %08x are not free\n",
 
515
                        davinci_rtc->pbase);
 
516
                ret = -EBUSY;
 
517
                goto fail1;
 
518
        }
 
519
 
 
520
        davinci_rtc->base = ioremap(davinci_rtc->pbase, davinci_rtc->base_size);
 
521
        if (!davinci_rtc->base) {
 
522
                dev_err(dev, "unable to ioremap MEM resource\n");
 
523
                ret = -ENOMEM;
 
524
                goto fail2;
 
525
        }
 
526
 
 
527
        platform_set_drvdata(pdev, davinci_rtc);
 
528
 
 
529
        davinci_rtc->rtc = rtc_device_register(pdev->name, &pdev->dev,
 
530
                                    &davinci_rtc_ops, THIS_MODULE);
 
531
        if (IS_ERR(davinci_rtc->rtc)) {
 
532
                dev_err(dev, "unable to register RTC device, err %ld\n",
 
533
                                PTR_ERR(davinci_rtc->rtc));
 
534
                goto fail3;
 
535
        }
 
536
 
 
537
        rtcif_write(davinci_rtc, PRTCIF_INTFLG_RTCSS, PRTCIF_INTFLG);
 
538
        rtcif_write(davinci_rtc, 0, PRTCIF_INTEN);
 
539
        rtcss_write(davinci_rtc, 0, PRTCSS_RTC_INTC_EXTENA1);
 
540
 
 
541
        rtcss_write(davinci_rtc, 0, PRTCSS_RTC_CTRL);
 
542
        rtcss_write(davinci_rtc, 0, PRTCSS_RTC_CCTRL);
 
543
 
 
544
        ret = request_irq(davinci_rtc->irq, davinci_rtc_interrupt,
 
545
                          IRQF_DISABLED, "davinci_rtc", davinci_rtc);
 
546
        if (ret < 0) {
 
547
                dev_err(dev, "unable to register davinci RTC interrupt\n");
 
548
                goto fail4;
 
549
        }
 
550
 
 
551
        /* Enable interrupts */
 
552
        rtcif_write(davinci_rtc, PRTCIF_INTEN_RTCSS, PRTCIF_INTEN);
 
553
        rtcss_write(davinci_rtc, PRTCSS_RTC_INTC_EXTENA1_MASK,
 
554
                            PRTCSS_RTC_INTC_EXTENA1);
 
555
 
 
556
        rtcss_write(davinci_rtc, PRTCSS_RTC_CCTRL_CAEN, PRTCSS_RTC_CCTRL);
 
557
 
 
558
        device_init_wakeup(&pdev->dev, 0);
 
559
 
 
560
        return 0;
 
561
 
 
562
fail4:
 
563
        rtc_device_unregister(davinci_rtc->rtc);
 
564
fail3:
 
565
        platform_set_drvdata(pdev, NULL);
 
566
        iounmap(davinci_rtc->base);
 
567
fail2:
 
568
        release_mem_region(davinci_rtc->pbase, davinci_rtc->base_size);
 
569
fail1:
 
570
        kfree(davinci_rtc);
 
571
 
 
572
        return ret;
 
573
}
 
574
 
 
575
static int __devexit davinci_rtc_remove(struct platform_device *pdev)
 
576
{
 
577
        struct davinci_rtc *davinci_rtc = platform_get_drvdata(pdev);
 
578
 
 
579
        device_init_wakeup(&pdev->dev, 0);
 
580
 
 
581
        rtcif_write(davinci_rtc, 0, PRTCIF_INTEN);
 
582
 
 
583
        free_irq(davinci_rtc->irq, davinci_rtc);
 
584
 
 
585
        rtc_device_unregister(davinci_rtc->rtc);
 
586
 
 
587
        iounmap(davinci_rtc->base);
 
588
        release_mem_region(davinci_rtc->pbase, davinci_rtc->base_size);
 
589
 
 
590
        platform_set_drvdata(pdev, NULL);
 
591
 
 
592
        kfree(davinci_rtc);
 
593
 
 
594
        return 0;
 
595
}
 
596
 
 
597
static struct platform_driver davinci_rtc_driver = {
 
598
        .probe          = davinci_rtc_probe,
 
599
        .remove         = __devexit_p(davinci_rtc_remove),
 
600
        .driver         = {
 
601
                .name = "rtc_davinci",
 
602
                .owner = THIS_MODULE,
 
603
        },
 
604
};
 
605
 
 
606
static int __init rtc_init(void)
 
607
{
 
608
        return platform_driver_probe(&davinci_rtc_driver, davinci_rtc_probe);
 
609
}
 
610
module_init(rtc_init);
 
611
 
 
612
static void __exit rtc_exit(void)
 
613
{
 
614
        platform_driver_unregister(&davinci_rtc_driver);
 
615
}
 
616
module_exit(rtc_exit);
 
617
 
 
618
MODULE_AUTHOR("Miguel Aguilar <miguel.aguilar@ridgerun.com>");
 
619
MODULE_DESCRIPTION("Texas Instruments DaVinci PRTC Driver");
 
620
MODULE_LICENSE("GPL");