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

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [rtc/] [rtc-omap.c] - Blame information for rev 78

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * TI OMAP1 Real Time Clock interface for Linux
3
 *
4
 * Copyright (C) 2003 MontaVista Software, Inc.
5
 * Author: George G. Davis <gdavis@mvista.com> or <source@mvista.com>
6
 *
7
 * Copyright (C) 2006 David Brownell (new RTC framework)
8
 *
9
 * This program is free software; you can redistribute it and/or
10
 * modify it under the terms of the GNU General Public License
11
 * as published by the Free Software Foundation; either version
12
 * 2 of the License, or (at your option) any later version.
13
 */
14
 
15
#include <linux/kernel.h>
16
#include <linux/init.h>
17
#include <linux/module.h>
18
#include <linux/ioport.h>
19
#include <linux/delay.h>
20
#include <linux/rtc.h>
21
#include <linux/bcd.h>
22
#include <linux/platform_device.h>
23
 
24
#include <asm/io.h>
25
#include <asm/mach/time.h>
26
 
27
 
28
/* The OMAP1 RTC is a year/month/day/hours/minutes/seconds BCD clock
29
 * with century-range alarm matching, driven by the 32kHz clock.
30
 *
31
 * The main user-visible ways it differs from PC RTCs are by omitting
32
 * "don't care" alarm fields and sub-second periodic IRQs, and having
33
 * an autoadjust mechanism to calibrate to the true oscillator rate.
34
 *
35
 * Board-specific wiring options include using split power mode with
36
 * RTC_OFF_NOFF used as the reset signal (so the RTC won't be reset),
37
 * and wiring RTC_WAKE_INT (so the RTC alarm can wake the system from
38
 * low power modes).  See the BOARD-SPECIFIC CUSTOMIZATION comment.
39
 */
40
 
41
#define OMAP_RTC_BASE                   0xfffb4800
42
 
43
/* RTC registers */
44
#define OMAP_RTC_SECONDS_REG            0x00
45
#define OMAP_RTC_MINUTES_REG            0x04
46
#define OMAP_RTC_HOURS_REG              0x08
47
#define OMAP_RTC_DAYS_REG               0x0C
48
#define OMAP_RTC_MONTHS_REG             0x10
49
#define OMAP_RTC_YEARS_REG              0x14
50
#define OMAP_RTC_WEEKS_REG              0x18
51
 
52
#define OMAP_RTC_ALARM_SECONDS_REG      0x20
53
#define OMAP_RTC_ALARM_MINUTES_REG      0x24
54
#define OMAP_RTC_ALARM_HOURS_REG        0x28
55
#define OMAP_RTC_ALARM_DAYS_REG         0x2c
56
#define OMAP_RTC_ALARM_MONTHS_REG       0x30
57
#define OMAP_RTC_ALARM_YEARS_REG        0x34
58
 
59
#define OMAP_RTC_CTRL_REG               0x40
60
#define OMAP_RTC_STATUS_REG             0x44
61
#define OMAP_RTC_INTERRUPTS_REG         0x48
62
 
63
#define OMAP_RTC_COMP_LSB_REG           0x4c
64
#define OMAP_RTC_COMP_MSB_REG           0x50
65
#define OMAP_RTC_OSC_REG                0x54
66
 
67
/* OMAP_RTC_CTRL_REG bit fields: */
68
#define OMAP_RTC_CTRL_SPLIT             (1<<7)
69
#define OMAP_RTC_CTRL_DISABLE           (1<<6)
70
#define OMAP_RTC_CTRL_SET_32_COUNTER    (1<<5)
71
#define OMAP_RTC_CTRL_TEST              (1<<4)
72
#define OMAP_RTC_CTRL_MODE_12_24        (1<<3)
73
#define OMAP_RTC_CTRL_AUTO_COMP         (1<<2)
74
#define OMAP_RTC_CTRL_ROUND_30S         (1<<1)
75
#define OMAP_RTC_CTRL_STOP              (1<<0)
76
 
77
/* OMAP_RTC_STATUS_REG bit fields: */
78
#define OMAP_RTC_STATUS_POWER_UP        (1<<7)
79
#define OMAP_RTC_STATUS_ALARM           (1<<6)
80
#define OMAP_RTC_STATUS_1D_EVENT        (1<<5)
81
#define OMAP_RTC_STATUS_1H_EVENT        (1<<4)
82
#define OMAP_RTC_STATUS_1M_EVENT        (1<<3)
83
#define OMAP_RTC_STATUS_1S_EVENT        (1<<2)
84
#define OMAP_RTC_STATUS_RUN             (1<<1)
85
#define OMAP_RTC_STATUS_BUSY            (1<<0)
86
 
87
/* OMAP_RTC_INTERRUPTS_REG bit fields: */
88
#define OMAP_RTC_INTERRUPTS_IT_ALARM    (1<<3)
89
#define OMAP_RTC_INTERRUPTS_IT_TIMER    (1<<2)
90
 
91
 
92
#define rtc_read(addr)          omap_readb(OMAP_RTC_BASE + (addr))
93
#define rtc_write(val, addr)    omap_writeb(val, OMAP_RTC_BASE + (addr))
94
 
95
 
96
/* platform_bus isn't hotpluggable, so for static linkage it'd be safe
97
 * to get rid of probe() and remove() code ... too bad the driver struct
98
 * remembers probe(), that's about 25% of the runtime footprint!!
99
 */
100
#ifndef MODULE
101
#undef  __devexit
102
#undef  __devexit_p
103
#define __devexit       __exit
104
#define __devexit_p     __exit_p
105
#endif
106
 
107
 
108
/* we rely on the rtc framework to handle locking (rtc->ops_lock),
109
 * so the only other requirement is that register accesses which
110
 * require BUSY to be clear are made with IRQs locally disabled
111
 */
112
static void rtc_wait_not_busy(void)
113
{
114
        int     count = 0;
115
        u8      status;
116
 
117
        /* BUSY may stay active for 1/32768 second (~30 usec) */
118
        for (count = 0; count < 50; count++) {
119
                status = rtc_read(OMAP_RTC_STATUS_REG);
120
                if ((status & (u8)OMAP_RTC_STATUS_BUSY) == 0)
121
                        break;
122
                udelay(1);
123
        }
124
        /* now we have ~15 usec to read/write various registers */
125
}
126
 
127
static irqreturn_t rtc_irq(int irq, void *rtc)
128
{
129
        unsigned long           events = 0;
130
        u8                      irq_data;
131
 
132
        irq_data = rtc_read(OMAP_RTC_STATUS_REG);
133
 
134
        /* alarm irq? */
135
        if (irq_data & OMAP_RTC_STATUS_ALARM) {
136
                rtc_write(OMAP_RTC_STATUS_ALARM, OMAP_RTC_STATUS_REG);
137
                events |= RTC_IRQF | RTC_AF;
138
        }
139
 
140
        /* 1/sec periodic/update irq? */
141
        if (irq_data & OMAP_RTC_STATUS_1S_EVENT)
142
                events |= RTC_IRQF | RTC_UF;
143
 
144
        rtc_update_irq(rtc, 1, events);
145
 
146
        return IRQ_HANDLED;
147
}
148
 
149
#ifdef  CONFIG_RTC_INTF_DEV
150
 
151
static int
152
omap_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
153
{
154
        u8 reg;
155
 
156
        switch (cmd) {
157
        case RTC_AIE_OFF:
158
        case RTC_AIE_ON:
159
        case RTC_UIE_OFF:
160
        case RTC_UIE_ON:
161
                break;
162
        default:
163
                return -ENOIOCTLCMD;
164
        }
165
 
166
        local_irq_disable();
167
        rtc_wait_not_busy();
168
        reg = rtc_read(OMAP_RTC_INTERRUPTS_REG);
169
        switch (cmd) {
170
        /* AIE = Alarm Interrupt Enable */
171
        case RTC_AIE_OFF:
172
                reg &= ~OMAP_RTC_INTERRUPTS_IT_ALARM;
173
                break;
174
        case RTC_AIE_ON:
175
                reg |= OMAP_RTC_INTERRUPTS_IT_ALARM;
176
                break;
177
        /* UIE = Update Interrupt Enable (1/second) */
178
        case RTC_UIE_OFF:
179
                reg &= ~OMAP_RTC_INTERRUPTS_IT_TIMER;
180
                break;
181
        case RTC_UIE_ON:
182
                reg |= OMAP_RTC_INTERRUPTS_IT_TIMER;
183
                break;
184
        }
185
        rtc_wait_not_busy();
186
        rtc_write(reg, OMAP_RTC_INTERRUPTS_REG);
187
        local_irq_enable();
188
 
189
        return 0;
190
}
191
 
192
#else
193
#define omap_rtc_ioctl  NULL
194
#endif
195
 
196
/* this hardware doesn't support "don't care" alarm fields */
197
static int tm2bcd(struct rtc_time *tm)
198
{
199
        if (rtc_valid_tm(tm) != 0)
200
                return -EINVAL;
201
 
202
        tm->tm_sec = BIN2BCD(tm->tm_sec);
203
        tm->tm_min = BIN2BCD(tm->tm_min);
204
        tm->tm_hour = BIN2BCD(tm->tm_hour);
205
        tm->tm_mday = BIN2BCD(tm->tm_mday);
206
 
207
        tm->tm_mon = BIN2BCD(tm->tm_mon + 1);
208
 
209
        /* epoch == 1900 */
210
        if (tm->tm_year < 100 || tm->tm_year > 199)
211
                return -EINVAL;
212
        tm->tm_year = BIN2BCD(tm->tm_year - 100);
213
 
214
        return 0;
215
}
216
 
217
static void bcd2tm(struct rtc_time *tm)
218
{
219
        tm->tm_sec = BCD2BIN(tm->tm_sec);
220
        tm->tm_min = BCD2BIN(tm->tm_min);
221
        tm->tm_hour = BCD2BIN(tm->tm_hour);
222
        tm->tm_mday = BCD2BIN(tm->tm_mday);
223
        tm->tm_mon = BCD2BIN(tm->tm_mon) - 1;
224
        /* epoch == 1900 */
225
        tm->tm_year = BCD2BIN(tm->tm_year) + 100;
226
}
227
 
228
 
229
static int omap_rtc_read_time(struct device *dev, struct rtc_time *tm)
230
{
231
        /* we don't report wday/yday/isdst ... */
232
        local_irq_disable();
233
        rtc_wait_not_busy();
234
 
235
        tm->tm_sec = rtc_read(OMAP_RTC_SECONDS_REG);
236
        tm->tm_min = rtc_read(OMAP_RTC_MINUTES_REG);
237
        tm->tm_hour = rtc_read(OMAP_RTC_HOURS_REG);
238
        tm->tm_mday = rtc_read(OMAP_RTC_DAYS_REG);
239
        tm->tm_mon = rtc_read(OMAP_RTC_MONTHS_REG);
240
        tm->tm_year = rtc_read(OMAP_RTC_YEARS_REG);
241
 
242
        local_irq_enable();
243
 
244
        bcd2tm(tm);
245
        return 0;
246
}
247
 
248
static int omap_rtc_set_time(struct device *dev, struct rtc_time *tm)
249
{
250
        if (tm2bcd(tm) < 0)
251
                return -EINVAL;
252
        local_irq_disable();
253
        rtc_wait_not_busy();
254
 
255
        rtc_write(tm->tm_year, OMAP_RTC_YEARS_REG);
256
        rtc_write(tm->tm_mon, OMAP_RTC_MONTHS_REG);
257
        rtc_write(tm->tm_mday, OMAP_RTC_DAYS_REG);
258
        rtc_write(tm->tm_hour, OMAP_RTC_HOURS_REG);
259
        rtc_write(tm->tm_min, OMAP_RTC_MINUTES_REG);
260
        rtc_write(tm->tm_sec, OMAP_RTC_SECONDS_REG);
261
 
262
        local_irq_enable();
263
 
264
        return 0;
265
}
266
 
267
static int omap_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
268
{
269
        local_irq_disable();
270
        rtc_wait_not_busy();
271
 
272
        alm->time.tm_sec = rtc_read(OMAP_RTC_ALARM_SECONDS_REG);
273
        alm->time.tm_min = rtc_read(OMAP_RTC_ALARM_MINUTES_REG);
274
        alm->time.tm_hour = rtc_read(OMAP_RTC_ALARM_HOURS_REG);
275
        alm->time.tm_mday = rtc_read(OMAP_RTC_ALARM_DAYS_REG);
276
        alm->time.tm_mon = rtc_read(OMAP_RTC_ALARM_MONTHS_REG);
277
        alm->time.tm_year = rtc_read(OMAP_RTC_ALARM_YEARS_REG);
278
 
279
        local_irq_enable();
280
 
281
        bcd2tm(&alm->time);
282
        alm->enabled = !!(rtc_read(OMAP_RTC_INTERRUPTS_REG)
283
                        & OMAP_RTC_INTERRUPTS_IT_ALARM);
284
 
285
        return 0;
286
}
287
 
288
static int omap_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
289
{
290
        u8 reg;
291
 
292
        if (tm2bcd(&alm->time) < 0)
293
                return -EINVAL;
294
 
295
        local_irq_disable();
296
        rtc_wait_not_busy();
297
 
298
        rtc_write(alm->time.tm_year, OMAP_RTC_ALARM_YEARS_REG);
299
        rtc_write(alm->time.tm_mon, OMAP_RTC_ALARM_MONTHS_REG);
300
        rtc_write(alm->time.tm_mday, OMAP_RTC_ALARM_DAYS_REG);
301
        rtc_write(alm->time.tm_hour, OMAP_RTC_ALARM_HOURS_REG);
302
        rtc_write(alm->time.tm_min, OMAP_RTC_ALARM_MINUTES_REG);
303
        rtc_write(alm->time.tm_sec, OMAP_RTC_ALARM_SECONDS_REG);
304
 
305
        reg = rtc_read(OMAP_RTC_INTERRUPTS_REG);
306
        if (alm->enabled)
307
                reg |= OMAP_RTC_INTERRUPTS_IT_ALARM;
308
        else
309
                reg &= ~OMAP_RTC_INTERRUPTS_IT_ALARM;
310
        rtc_write(reg, OMAP_RTC_INTERRUPTS_REG);
311
 
312
        local_irq_enable();
313
 
314
        return 0;
315
}
316
 
317
static struct rtc_class_ops omap_rtc_ops = {
318
        .ioctl          = omap_rtc_ioctl,
319
        .read_time      = omap_rtc_read_time,
320
        .set_time       = omap_rtc_set_time,
321
        .read_alarm     = omap_rtc_read_alarm,
322
        .set_alarm      = omap_rtc_set_alarm,
323
};
324
 
325
static int omap_rtc_alarm;
326
static int omap_rtc_timer;
327
 
328
static int __devinit omap_rtc_probe(struct platform_device *pdev)
329
{
330
        struct resource         *res, *mem;
331
        struct rtc_device       *rtc;
332
        u8                      reg, new_ctrl;
333
 
334
        omap_rtc_timer = platform_get_irq(pdev, 0);
335
        if (omap_rtc_timer <= 0) {
336
                pr_debug("%s: no update irq?\n", pdev->name);
337
                return -ENOENT;
338
        }
339
 
340
        omap_rtc_alarm = platform_get_irq(pdev, 1);
341
        if (omap_rtc_alarm <= 0) {
342
                pr_debug("%s: no alarm irq?\n", pdev->name);
343
                return -ENOENT;
344
        }
345
 
346
        /* NOTE:  using static mapping for RTC registers */
347
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
348
        if (res && res->start != OMAP_RTC_BASE) {
349
                pr_debug("%s: RTC registers at %08x, expected %08x\n",
350
                        pdev->name, (unsigned) res->start, OMAP_RTC_BASE);
351
                return -ENOENT;
352
        }
353
 
354
        if (res)
355
                mem = request_mem_region(res->start,
356
                                res->end - res->start + 1,
357
                                pdev->name);
358
        else
359
                mem = NULL;
360
        if (!mem) {
361
                pr_debug("%s: RTC registers at %08x are not free\n",
362
                        pdev->name, OMAP_RTC_BASE);
363
                return -EBUSY;
364
        }
365
 
366
        rtc = rtc_device_register(pdev->name, &pdev->dev,
367
                        &omap_rtc_ops, THIS_MODULE);
368
        if (IS_ERR(rtc)) {
369
                pr_debug("%s: can't register RTC device, err %ld\n",
370
                        pdev->name, PTR_ERR(rtc));
371
                goto fail;
372
        }
373
        platform_set_drvdata(pdev, rtc);
374
        dev_set_drvdata(&rtc->dev, mem);
375
 
376
        /* clear pending irqs, and set 1/second periodic,
377
         * which we'll use instead of update irqs
378
         */
379
        rtc_write(0, OMAP_RTC_INTERRUPTS_REG);
380
 
381
        /* clear old status */
382
        reg = rtc_read(OMAP_RTC_STATUS_REG);
383
        if (reg & (u8) OMAP_RTC_STATUS_POWER_UP) {
384
                pr_info("%s: RTC power up reset detected\n",
385
                        pdev->name);
386
                rtc_write(OMAP_RTC_STATUS_POWER_UP, OMAP_RTC_STATUS_REG);
387
        }
388
        if (reg & (u8) OMAP_RTC_STATUS_ALARM)
389
                rtc_write(OMAP_RTC_STATUS_ALARM, OMAP_RTC_STATUS_REG);
390
 
391
        /* handle periodic and alarm irqs */
392
        if (request_irq(omap_rtc_timer, rtc_irq, IRQF_DISABLED,
393
                        rtc->dev.bus_id, rtc)) {
394
                pr_debug("%s: RTC timer interrupt IRQ%d already claimed\n",
395
                        pdev->name, omap_rtc_timer);
396
                goto fail0;
397
        }
398
        if (request_irq(omap_rtc_alarm, rtc_irq, IRQF_DISABLED,
399
                        rtc->dev.bus_id, rtc)) {
400
                pr_debug("%s: RTC alarm interrupt IRQ%d already claimed\n",
401
                        pdev->name, omap_rtc_alarm);
402
                goto fail1;
403
        }
404
 
405
        /* On boards with split power, RTC_ON_NOFF won't reset the RTC */
406
        reg = rtc_read(OMAP_RTC_CTRL_REG);
407
        if (reg & (u8) OMAP_RTC_CTRL_STOP)
408
                pr_info("%s: already running\n", pdev->name);
409
 
410
        /* force to 24 hour mode */
411
        new_ctrl = reg & ~(OMAP_RTC_CTRL_SPLIT|OMAP_RTC_CTRL_AUTO_COMP);
412
        new_ctrl |= OMAP_RTC_CTRL_STOP;
413
 
414
        /* BOARD-SPECIFIC CUSTOMIZATION CAN GO HERE:
415
         *
416
         *  - Boards wired so that RTC_WAKE_INT does something, and muxed
417
         *    right (W13_1610_RTC_WAKE_INT is the default after chip reset),
418
         *    should initialize the device wakeup flag appropriately.
419
         *
420
         *  - Boards wired so RTC_ON_nOFF is used as the reset signal,
421
         *    rather than nPWRON_RESET, should forcibly enable split
422
         *    power mode.  (Some chip errata report that RTC_CTRL_SPLIT
423
         *    is write-only, and always reads as zero...)
424
         */
425
        device_init_wakeup(&pdev->dev, 0);
426
 
427
        if (new_ctrl & (u8) OMAP_RTC_CTRL_SPLIT)
428
                pr_info("%s: split power mode\n", pdev->name);
429
 
430
        if (reg != new_ctrl)
431
                rtc_write(new_ctrl, OMAP_RTC_CTRL_REG);
432
 
433
        return 0;
434
 
435
fail1:
436
        free_irq(omap_rtc_timer, NULL);
437
fail0:
438
        rtc_device_unregister(rtc);
439
fail:
440
        release_resource(mem);
441
        return -EIO;
442
}
443
 
444
static int __devexit omap_rtc_remove(struct platform_device *pdev)
445
{
446
        struct rtc_device       *rtc = platform_get_drvdata(pdev);;
447
 
448
        device_init_wakeup(&pdev->dev, 0);
449
 
450
        /* leave rtc running, but disable irqs */
451
        rtc_write(0, OMAP_RTC_INTERRUPTS_REG);
452
 
453
        free_irq(omap_rtc_timer, rtc);
454
        free_irq(omap_rtc_alarm, rtc);
455
 
456
        release_resource(dev_get_drvdata(&rtc->dev));
457
        rtc_device_unregister(rtc);
458
        return 0;
459
}
460
 
461
#ifdef CONFIG_PM
462
 
463
static u8 irqstat;
464
 
465
static int omap_rtc_suspend(struct platform_device *pdev, pm_message_t state)
466
{
467
        irqstat = rtc_read(OMAP_RTC_INTERRUPTS_REG);
468
 
469
        /* FIXME the RTC alarm is not currently acting as a wakeup event
470
         * source, and in fact this enable() call is just saving a flag
471
         * that's never used...
472
         */
473
        if (device_may_wakeup(&pdev->dev))
474
                enable_irq_wake(omap_rtc_alarm);
475
        else
476
                rtc_write(0, OMAP_RTC_INTERRUPTS_REG);
477
 
478
        return 0;
479
}
480
 
481
static int omap_rtc_resume(struct platform_device *pdev)
482
{
483
        if (device_may_wakeup(&pdev->dev))
484
                disable_irq_wake(omap_rtc_alarm);
485
        else
486
                rtc_write(irqstat, OMAP_RTC_INTERRUPTS_REG);
487
        return 0;
488
}
489
 
490
#else
491
#define omap_rtc_suspend NULL
492
#define omap_rtc_resume  NULL
493
#endif
494
 
495
static void omap_rtc_shutdown(struct platform_device *pdev)
496
{
497
        rtc_write(0, OMAP_RTC_INTERRUPTS_REG);
498
}
499
 
500
MODULE_ALIAS("omap_rtc");
501
static struct platform_driver omap_rtc_driver = {
502
        .probe          = omap_rtc_probe,
503
        .remove         = __devexit_p(omap_rtc_remove),
504
        .suspend        = omap_rtc_suspend,
505
        .resume         = omap_rtc_resume,
506
        .shutdown       = omap_rtc_shutdown,
507
        .driver         = {
508
                .name   = "omap_rtc",
509
                .owner  = THIS_MODULE,
510
        },
511
};
512
 
513
static int __init rtc_init(void)
514
{
515
        return platform_driver_register(&omap_rtc_driver);
516
}
517
module_init(rtc_init);
518
 
519
static void __exit rtc_exit(void)
520
{
521
        platform_driver_unregister(&omap_rtc_driver);
522
}
523
module_exit(rtc_exit);
524
 
525
MODULE_AUTHOR("George G. Davis (and others)");
526
MODULE_LICENSE("GPL");

powered by: WebSVN 2.1.0

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