2 * drivers/rtc/rtc-pl031.c
4 * Real Time Clock interface for ARM AMBA PrimeCell 031 RTC
6 * Author: Deepak Saxena <dsaxena@plexity.net>
8 * Copyright 2006 (c) MontaVista Software, Inc.
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version
13 * 2 of the License, or (at your option) any later version.
15 #include <linux/module.h>
16 #include <linux/rtc.h>
17 #include <linux/init.h>
18 #include <linux/interrupt.h>
19 #include <linux/amba/bus.h>
23 * Register definitions
25 #define RTC_DR 0x00 /* Data read register */
26 #define RTC_MR 0x04 /* Match register */
27 #define RTC_LR 0x08 /* Data load register */
28 #define RTC_CR 0x0c /* Control register */
29 #define RTC_IMSC 0x10 /* Interrupt mask and set register */
30 #define RTC_RIS 0x14 /* Raw interrupt status register */
31 #define RTC_MIS 0x18 /* Masked interrupt status register */
32 #define RTC_ICR 0x1c /* Interrupt clear register */
35 struct rtc_device
*rtc
;
39 static irqreturn_t
pl031_interrupt(int irq
, void *dev_id
)
41 struct rtc_device
*rtc
= dev_id
;
43 rtc_update_irq(rtc
, 1, RTC_AF
);
48 static int pl031_open(struct device
*dev
)
51 * We request IRQ in pl031_probe, so nothing to do here...
56 static void pl031_release(struct device
*dev
)
60 static int pl031_ioctl(struct device
*dev
, unsigned int cmd
, unsigned long arg
)
62 struct pl031_local
*ldata
= dev_get_drvdata(dev
);
66 __raw_writel(1, ldata
->base
+ RTC_MIS
);
69 __raw_writel(0, ldata
->base
+ RTC_MIS
);
76 static int pl031_read_time(struct device
*dev
, struct rtc_time
*tm
)
78 struct pl031_local
*ldata
= dev_get_drvdata(dev
);
80 rtc_time_to_tm(__raw_readl(ldata
->base
+ RTC_DR
), tm
);
85 static int pl031_set_time(struct device
*dev
, struct rtc_time
*tm
)
88 struct pl031_local
*ldata
= dev_get_drvdata(dev
);
90 rtc_tm_to_time(tm
, &time
);
91 __raw_writel(time
, ldata
->base
+ RTC_LR
);
96 static int pl031_read_alarm(struct device
*dev
, struct rtc_wkalrm
*alarm
)
98 struct pl031_local
*ldata
= dev_get_drvdata(dev
);
100 rtc_time_to_tm(__raw_readl(ldata
->base
+ RTC_MR
), &alarm
->time
);
101 alarm
->pending
= __raw_readl(ldata
->base
+ RTC_RIS
);
102 alarm
->enabled
= __raw_readl(ldata
->base
+ RTC_IMSC
);
107 static int pl031_set_alarm(struct device
*dev
, struct rtc_wkalrm
*alarm
)
109 struct pl031_local
*ldata
= dev_get_drvdata(dev
);
112 rtc_tm_to_time(&alarm
->time
, &time
);
114 __raw_writel(time
, ldata
->base
+ RTC_MR
);
115 __raw_writel(!alarm
->enabled
, ldata
->base
+ RTC_MIS
);
120 static const struct rtc_class_ops pl031_ops
= {
122 .release
= pl031_release
,
123 .ioctl
= pl031_ioctl
,
124 .read_time
= pl031_read_time
,
125 .set_time
= pl031_set_time
,
126 .read_alarm
= pl031_read_alarm
,
127 .set_alarm
= pl031_set_alarm
,
130 static int pl031_remove(struct amba_device
*adev
)
132 struct pl031_local
*ldata
= dev_get_drvdata(&adev
->dev
);
134 amba_set_drvdata(adev
, NULL
);
135 free_irq(adev
->irq
[0], ldata
->rtc
);
136 rtc_device_unregister(ldata
->rtc
);
137 iounmap(ldata
->base
);
139 amba_release_regions(adev
);
144 static int pl031_probe(struct amba_device
*adev
, void *id
)
147 struct pl031_local
*ldata
;
149 ret
= amba_request_regions(adev
, NULL
);
153 ldata
= kmalloc(sizeof(struct pl031_local
), GFP_KERNEL
);
159 ldata
->base
= ioremap(adev
->res
.start
,
160 adev
->res
.end
- adev
->res
.start
+ 1);
166 amba_set_drvdata(adev
, ldata
);
168 if (request_irq(adev
->irq
[0], pl031_interrupt
, IRQF_DISABLED
,
169 "rtc-pl031", ldata
->rtc
)) {
174 ldata
->rtc
= rtc_device_register("pl031", &adev
->dev
, &pl031_ops
,
176 if (IS_ERR(ldata
->rtc
)) {
177 ret
= PTR_ERR(ldata
->rtc
);
184 free_irq(adev
->irq
[0], ldata
->rtc
);
186 iounmap(ldata
->base
);
187 amba_set_drvdata(adev
, NULL
);
191 amba_release_regions(adev
);
196 static struct amba_id pl031_ids
[] __initdata
= {
199 .mask
= 0x000fffff, },
203 static struct amba_driver pl031_driver
= {
207 .id_table
= pl031_ids
,
208 .probe
= pl031_probe
,
209 .remove
= pl031_remove
,
212 static int __init
pl031_init(void)
214 return amba_driver_register(&pl031_driver
);
217 static void __exit
pl031_exit(void)
219 amba_driver_unregister(&pl031_driver
);
222 module_init(pl031_init
);
223 module_exit(pl031_exit
);
225 MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net");
226 MODULE_DESCRIPTION("ARM AMBA PL031 RTC Driver");
227 MODULE_LICENSE("GPL");