OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [rtc/] [rtc-at91rm9200.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 *      Real Time Clock interface for Linux on Atmel AT91RM9200
3
 *
4
 *      Copyright (C) 2002 Rick Bronson
5
 *
6
 *      Converted to RTC class model by Andrew Victor
7
 *
8
 *      Ported to Linux 2.6 by Steven Scholz
9
 *      Based on s3c2410-rtc.c Simtec Electronics
10
 *
11
 *      Based on sa1100-rtc.c by Nils Faerber
12
 *      Based on rtc.c by Paul Gortmaker
13
 *
14
 *      This program is free software; you can redistribute it and/or
15
 *      modify it under the terms of the GNU General Public License
16
 *      as published by the Free Software Foundation; either version
17
 *      2 of the License, or (at your option) any later version.
18
 *
19
 */
20
 
21
#include <linux/module.h>
22
#include <linux/kernel.h>
23
#include <linux/platform_device.h>
24
#include <linux/time.h>
25
#include <linux/rtc.h>
26
#include <linux/bcd.h>
27
#include <linux/interrupt.h>
28
#include <linux/ioctl.h>
29
#include <linux/completion.h>
30
 
31
#include <asm/uaccess.h>
32
#include <asm/rtc.h>
33
 
34
#include <asm/mach/time.h>
35
 
36
#include <asm/arch/at91_rtc.h>
37
 
38
 
39
#define AT91_RTC_FREQ           1
40
#define AT91_RTC_EPOCH          1900UL  /* just like arch/arm/common/rtctime.c */
41
 
42
static DECLARE_COMPLETION(at91_rtc_updated);
43
static unsigned int at91_alarm_year = AT91_RTC_EPOCH;
44
 
45
/*
46
 * Decode time/date into rtc_time structure
47
 */
48
static void at91_rtc_decodetime(unsigned int timereg, unsigned int calreg,
49
                                struct rtc_time *tm)
50
{
51
        unsigned int time, date;
52
 
53
        /* must read twice in case it changes */
54
        do {
55
                time = at91_sys_read(timereg);
56
                date = at91_sys_read(calreg);
57
        } while ((time != at91_sys_read(timereg)) ||
58
                        (date != at91_sys_read(calreg)));
59
 
60
        tm->tm_sec  = BCD2BIN((time & AT91_RTC_SEC) >> 0);
61
        tm->tm_min  = BCD2BIN((time & AT91_RTC_MIN) >> 8);
62
        tm->tm_hour = BCD2BIN((time & AT91_RTC_HOUR) >> 16);
63
 
64
        /*
65
         * The Calendar Alarm register does not have a field for
66
         * the year - so these will return an invalid value.  When an
67
         * alarm is set, at91_alarm_year wille store the current year.
68
         */
69
        tm->tm_year  = BCD2BIN(date & AT91_RTC_CENT) * 100;     /* century */
70
        tm->tm_year += BCD2BIN((date & AT91_RTC_YEAR) >> 8);    /* year */
71
 
72
        tm->tm_wday = BCD2BIN((date & AT91_RTC_DAY) >> 21) - 1; /* day of the week [0-6], Sunday=0 */
73
        tm->tm_mon  = BCD2BIN((date & AT91_RTC_MONTH) >> 16) - 1;
74
        tm->tm_mday = BCD2BIN((date & AT91_RTC_DATE) >> 24);
75
}
76
 
77
/*
78
 * Read current time and date in RTC
79
 */
80
static int at91_rtc_readtime(struct device *dev, struct rtc_time *tm)
81
{
82
        at91_rtc_decodetime(AT91_RTC_TIMR, AT91_RTC_CALR, tm);
83
        tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year);
84
        tm->tm_year = tm->tm_year - 1900;
85
 
86
        pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __FUNCTION__,
87
                1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
88
                tm->tm_hour, tm->tm_min, tm->tm_sec);
89
 
90
        return 0;
91
}
92
 
93
/*
94
 * Set current time and date in RTC
95
 */
96
static int at91_rtc_settime(struct device *dev, struct rtc_time *tm)
97
{
98
        unsigned long cr;
99
 
100
        pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __FUNCTION__,
101
                1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
102
                tm->tm_hour, tm->tm_min, tm->tm_sec);
103
 
104
        /* Stop Time/Calendar from counting */
105
        cr = at91_sys_read(AT91_RTC_CR);
106
        at91_sys_write(AT91_RTC_CR, cr | AT91_RTC_UPDCAL | AT91_RTC_UPDTIM);
107
 
108
        at91_sys_write(AT91_RTC_IER, AT91_RTC_ACKUPD);
109
        wait_for_completion(&at91_rtc_updated); /* wait for ACKUPD interrupt */
110
        at91_sys_write(AT91_RTC_IDR, AT91_RTC_ACKUPD);
111
 
112
        at91_sys_write(AT91_RTC_TIMR,
113
                          BIN2BCD(tm->tm_sec) << 0
114
                        | BIN2BCD(tm->tm_min) << 8
115
                        | BIN2BCD(tm->tm_hour) << 16);
116
 
117
        at91_sys_write(AT91_RTC_CALR,
118
                          BIN2BCD((tm->tm_year + 1900) / 100)   /* century */
119
                        | BIN2BCD(tm->tm_year % 100) << 8       /* year */
120
                        | BIN2BCD(tm->tm_mon + 1) << 16         /* tm_mon starts at zero */
121
                        | BIN2BCD(tm->tm_wday + 1) << 21        /* day of the week [0-6], Sunday=0 */
122
                        | BIN2BCD(tm->tm_mday) << 24);
123
 
124
        /* Restart Time/Calendar */
125
        cr = at91_sys_read(AT91_RTC_CR);
126
        at91_sys_write(AT91_RTC_CR, cr & ~(AT91_RTC_UPDCAL | AT91_RTC_UPDTIM));
127
 
128
        return 0;
129
}
130
 
131
/*
132
 * Read alarm time and date in RTC
133
 */
134
static int at91_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
135
{
136
        struct rtc_time *tm = &alrm->time;
137
 
138
        at91_rtc_decodetime(AT91_RTC_TIMALR, AT91_RTC_CALALR, tm);
139
        tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year);
140
        tm->tm_year = at91_alarm_year - 1900;
141
 
142
        alrm->enabled = (at91_sys_read(AT91_RTC_IMR) & AT91_RTC_ALARM)
143
                        ? 1 : 0;
144
 
145
        pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __FUNCTION__,
146
                1900 + tm->tm_year, tm->tm_mon, tm->tm_mday,
147
                tm->tm_hour, tm->tm_min, tm->tm_sec);
148
 
149
        return 0;
150
}
151
 
152
/*
153
 * Set alarm time and date in RTC
154
 */
155
static int at91_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
156
{
157
        struct rtc_time tm;
158
 
159
        at91_rtc_decodetime(AT91_RTC_TIMR, AT91_RTC_CALR, &tm);
160
 
161
        at91_alarm_year = tm.tm_year;
162
 
163
        tm.tm_hour = alrm->time.tm_hour;
164
        tm.tm_min = alrm->time.tm_min;
165
        tm.tm_sec = alrm->time.tm_sec;
166
 
167
        at91_sys_write(AT91_RTC_IDR, AT91_RTC_ALARM);
168
        at91_sys_write(AT91_RTC_TIMALR,
169
                  BIN2BCD(tm.tm_sec) << 0
170
                | BIN2BCD(tm.tm_min) << 8
171
                | BIN2BCD(tm.tm_hour) << 16
172
                | AT91_RTC_HOUREN | AT91_RTC_MINEN | AT91_RTC_SECEN);
173
        at91_sys_write(AT91_RTC_CALALR,
174
                  BIN2BCD(tm.tm_mon + 1) << 16          /* tm_mon starts at zero */
175
                | BIN2BCD(tm.tm_mday) << 24
176
                | AT91_RTC_DATEEN | AT91_RTC_MTHEN);
177
 
178
        if (alrm->enabled)
179
                at91_sys_write(AT91_RTC_IER, AT91_RTC_ALARM);
180
 
181
        pr_debug("%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __FUNCTION__,
182
                at91_alarm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour,
183
                tm.tm_min, tm.tm_sec);
184
 
185
        return 0;
186
}
187
 
188
/*
189
 * Handle commands from user-space
190
 */
191
static int at91_rtc_ioctl(struct device *dev, unsigned int cmd,
192
                        unsigned long arg)
193
{
194
        int ret = 0;
195
 
196
        pr_debug("%s(): cmd=%08x, arg=%08lx.\n", __FUNCTION__, cmd, arg);
197
 
198
        switch (cmd) {
199
        case RTC_AIE_OFF:       /* alarm off */
200
                at91_sys_write(AT91_RTC_IDR, AT91_RTC_ALARM);
201
                break;
202
        case RTC_AIE_ON:        /* alarm on */
203
                at91_sys_write(AT91_RTC_IER, AT91_RTC_ALARM);
204
                break;
205
        case RTC_UIE_OFF:       /* update off */
206
        case RTC_PIE_OFF:       /* periodic off */
207
                at91_sys_write(AT91_RTC_IDR, AT91_RTC_SECEV);
208
                break;
209
        case RTC_UIE_ON:        /* update on */
210
        case RTC_PIE_ON:        /* periodic on */
211
                at91_sys_write(AT91_RTC_IER, AT91_RTC_SECEV);
212
                break;
213
        case RTC_IRQP_READ:     /* read periodic alarm frequency */
214
                ret = put_user(AT91_RTC_FREQ, (unsigned long *) arg);
215
                break;
216
        case RTC_IRQP_SET:      /* set periodic alarm frequency */
217
                if (arg != AT91_RTC_FREQ)
218
                        ret = -EINVAL;
219
                break;
220
        default:
221
                ret = -ENOIOCTLCMD;
222
                break;
223
        }
224
 
225
        return ret;
226
}
227
 
228
/*
229
 * Provide additional RTC information in /proc/driver/rtc
230
 */
231
static int at91_rtc_proc(struct device *dev, struct seq_file *seq)
232
{
233
        unsigned long imr = at91_sys_read(AT91_RTC_IMR);
234
 
235
        seq_printf(seq, "update_IRQ\t: %s\n",
236
                        (imr & AT91_RTC_ACKUPD) ? "yes" : "no");
237
        seq_printf(seq, "periodic_IRQ\t: %s\n",
238
                        (imr & AT91_RTC_SECEV) ? "yes" : "no");
239
        seq_printf(seq, "periodic_freq\t: %ld\n",
240
                        (unsigned long) AT91_RTC_FREQ);
241
 
242
        return 0;
243
}
244
 
245
/*
246
 * IRQ handler for the RTC
247
 */
248
static irqreturn_t at91_rtc_interrupt(int irq, void *dev_id)
249
{
250
        struct platform_device *pdev = dev_id;
251
        struct rtc_device *rtc = platform_get_drvdata(pdev);
252
        unsigned int rtsr;
253
        unsigned long events = 0;
254
 
255
        rtsr = at91_sys_read(AT91_RTC_SR) & at91_sys_read(AT91_RTC_IMR);
256
        if (rtsr) {             /* this interrupt is shared!  Is it ours? */
257
                if (rtsr & AT91_RTC_ALARM)
258
                        events |= (RTC_AF | RTC_IRQF);
259
                if (rtsr & AT91_RTC_SECEV)
260
                        events |= (RTC_UF | RTC_IRQF);
261
                if (rtsr & AT91_RTC_ACKUPD)
262
                        complete(&at91_rtc_updated);
263
 
264
                at91_sys_write(AT91_RTC_SCCR, rtsr);    /* clear status reg */
265
 
266
                rtc_update_irq(rtc, 1, events);
267
 
268
                pr_debug("%s(): num=%ld, events=0x%02lx\n", __FUNCTION__,
269
                        events >> 8, events & 0x000000FF);
270
 
271
                return IRQ_HANDLED;
272
        }
273
        return IRQ_NONE;                /* not handled */
274
}
275
 
276
static const struct rtc_class_ops at91_rtc_ops = {
277
        .ioctl          = at91_rtc_ioctl,
278
        .read_time      = at91_rtc_readtime,
279
        .set_time       = at91_rtc_settime,
280
        .read_alarm     = at91_rtc_readalarm,
281
        .set_alarm      = at91_rtc_setalarm,
282
        .proc           = at91_rtc_proc,
283
};
284
 
285
/*
286
 * Initialize and install RTC driver
287
 */
288
static int __init at91_rtc_probe(struct platform_device *pdev)
289
{
290
        struct rtc_device *rtc;
291
        int ret;
292
 
293
        at91_sys_write(AT91_RTC_CR, 0);
294
        at91_sys_write(AT91_RTC_MR, 0);          /* 24 hour mode */
295
 
296
        /* Disable all interrupts */
297
        at91_sys_write(AT91_RTC_IDR, AT91_RTC_ACKUPD | AT91_RTC_ALARM |
298
                                        AT91_RTC_SECEV | AT91_RTC_TIMEV |
299
                                        AT91_RTC_CALEV);
300
 
301
        ret = request_irq(AT91_ID_SYS, at91_rtc_interrupt,
302
                                IRQF_DISABLED | IRQF_SHARED,
303
                                "at91_rtc", pdev);
304
        if (ret) {
305
                printk(KERN_ERR "at91_rtc: IRQ %d already in use.\n",
306
                                AT91_ID_SYS);
307
                return ret;
308
        }
309
 
310
        /* cpu init code should really have flagged this device as
311
         * being wake-capable; if it didn't, do that here.
312
         */
313
        if (!device_can_wakeup(&pdev->dev))
314
                device_init_wakeup(&pdev->dev, 1);
315
 
316
        rtc = rtc_device_register(pdev->name, &pdev->dev,
317
                                &at91_rtc_ops, THIS_MODULE);
318
        if (IS_ERR(rtc)) {
319
                free_irq(AT91_ID_SYS, pdev);
320
                return PTR_ERR(rtc);
321
        }
322
        platform_set_drvdata(pdev, rtc);
323
 
324
        printk(KERN_INFO "AT91 Real Time Clock driver.\n");
325
        return 0;
326
}
327
 
328
/*
329
 * Disable and remove the RTC driver
330
 */
331
static int __exit at91_rtc_remove(struct platform_device *pdev)
332
{
333
        struct rtc_device *rtc = platform_get_drvdata(pdev);
334
 
335
        /* Disable all interrupts */
336
        at91_sys_write(AT91_RTC_IDR, AT91_RTC_ACKUPD | AT91_RTC_ALARM |
337
                                        AT91_RTC_SECEV | AT91_RTC_TIMEV |
338
                                        AT91_RTC_CALEV);
339
        free_irq(AT91_ID_SYS, pdev);
340
 
341
        rtc_device_unregister(rtc);
342
        platform_set_drvdata(pdev, NULL);
343
 
344
        return 0;
345
}
346
 
347
#ifdef CONFIG_PM
348
 
349
/* AT91RM9200 RTC Power management control */
350
 
351
static u32 at91_rtc_imr;
352
 
353
static int at91_rtc_suspend(struct platform_device *pdev, pm_message_t state)
354
{
355
        /* this IRQ is shared with DBGU and other hardware which isn't
356
         * necessarily doing PM like we are...
357
         */
358
        at91_rtc_imr = at91_sys_read(AT91_RTC_IMR)
359
                        & (AT91_RTC_ALARM|AT91_RTC_SECEV);
360
        if (at91_rtc_imr) {
361
                if (device_may_wakeup(&pdev->dev))
362
                        enable_irq_wake(AT91_ID_SYS);
363
                else
364
                        at91_sys_write(AT91_RTC_IDR, at91_rtc_imr);
365
        }
366
        return 0;
367
}
368
 
369
static int at91_rtc_resume(struct platform_device *pdev)
370
{
371
        if (at91_rtc_imr) {
372
                if (device_may_wakeup(&pdev->dev))
373
                        disable_irq_wake(AT91_ID_SYS);
374
                else
375
                        at91_sys_write(AT91_RTC_IER, at91_rtc_imr);
376
        }
377
        return 0;
378
}
379
#else
380
#define at91_rtc_suspend NULL
381
#define at91_rtc_resume  NULL
382
#endif
383
 
384
static struct platform_driver at91_rtc_driver = {
385
        .remove         = __exit_p(at91_rtc_remove),
386
        .suspend        = at91_rtc_suspend,
387
        .resume         = at91_rtc_resume,
388
        .driver         = {
389
                .name   = "at91_rtc",
390
                .owner  = THIS_MODULE,
391
        },
392
};
393
 
394
static int __init at91_rtc_init(void)
395
{
396
        return platform_driver_probe(&at91_rtc_driver, at91_rtc_probe);
397
}
398
 
399
static void __exit at91_rtc_exit(void)
400
{
401
        platform_driver_unregister(&at91_rtc_driver);
402
}
403
 
404
module_init(at91_rtc_init);
405
module_exit(at91_rtc_exit);
406
 
407
MODULE_AUTHOR("Rick Bronson");
408
MODULE_DESCRIPTION("RTC driver for Atmel AT91RM9200");
409
MODULE_LICENSE("GPL");

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.