aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rtc
diff options
context:
space:
mode:
authorHaojian Zhuang <haojian.zhuang@marvell.com>2012-02-20 22:51:13 -0500
committerHaojian Zhuang <haojian.zhuang@marvell.com>2012-02-27 21:07:50 -0500
commit3888c09074db2ca561c74571dcbd777949a856b8 (patch)
tree5aa1919517a274176dd13b4030141eba9df68a3c /drivers/rtc
parent1d8c38c3d1b48eeb9cfaa42a8be13a1423569eb2 (diff)
rtc: sa1100: declare irq in resource
Avoid to hard coded irq in rtc-sa1100 driver since we could share it among arch-sa1100/arch-pxa/arch-mmp. We still keep hard coded register address since the requirement is enabling both rtc-sa1100 and rtc-pxa driver. The register addresses are conflict since they're only two wrappers on the same rtc device. Signed-off-by: Haojian Zhuang <haojian.zhuang@marvell.com> Reviewed-by: Arnd Bergmann <arnd@arndb.de>
Diffstat (limited to 'drivers/rtc')
-rw-r--r--drivers/rtc/Kconfig4
-rw-r--r--drivers/rtc/rtc-sa1100.c98
2 files changed, 69 insertions, 33 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 3a125b835546..59efc63c4e48 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -773,8 +773,8 @@ config RTC_DRV_EP93XX
773 will be called rtc-ep93xx. 773 will be called rtc-ep93xx.
774 774
775config RTC_DRV_SA1100 775config RTC_DRV_SA1100
776 tristate "SA11x0/PXA2xx" 776 tristate "SA11x0/PXA2xx/PXA910"
777 depends on ARCH_SA1100 || ARCH_PXA 777 depends on ARCH_SA1100 || ARCH_PXA || ARCH_MMP
778 help 778 help
779 If you say Y here you will get access to the real time clock 779 If you say Y here you will get access to the real time clock
780 built into your SA11x0 or PXA2xx CPU. 780 built into your SA11x0 or PXA2xx CPU.
diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c
index 91d58bdc7f88..0a36c7ee3b40 100644
--- a/drivers/rtc/rtc-sa1100.c
+++ b/drivers/rtc/rtc-sa1100.c
@@ -27,6 +27,7 @@
27#include <linux/init.h> 27#include <linux/init.h>
28#include <linux/fs.h> 28#include <linux/fs.h>
29#include <linux/interrupt.h> 29#include <linux/interrupt.h>
30#include <linux/slab.h>
30#include <linux/string.h> 31#include <linux/string.h>
31#include <linux/pm.h> 32#include <linux/pm.h>
32#include <linux/bitops.h> 33#include <linux/bitops.h>
@@ -34,24 +35,29 @@
34#include <mach/hardware.h> 35#include <mach/hardware.h>
35#include <asm/irq.h> 36#include <asm/irq.h>
36 37
37#ifdef CONFIG_ARCH_PXA 38#if defined(CONFIG_ARCH_PXA) || defined(CONFIG_ARCH_MMP)
38#include <mach/regs-rtc.h> 39#include <mach/regs-rtc.h>
39#endif 40#endif
40 41
41#define RTC_DEF_DIVIDER (32768 - 1) 42#define RTC_DEF_DIVIDER (32768 - 1)
42#define RTC_DEF_TRIM 0 43#define RTC_DEF_TRIM 0
44#define RTC_FREQ 1024
43 45
44static const unsigned long RTC_FREQ = 1024; 46struct sa1100_rtc {
45static DEFINE_SPINLOCK(sa1100_rtc_lock); 47 spinlock_t lock;
48 int irq_1hz;
49 int irq_alarm;
50 struct rtc_device *rtc;
51};
46 52
47static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id) 53static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id)
48{ 54{
49 struct platform_device *pdev = to_platform_device(dev_id); 55 struct sa1100_rtc *info = dev_get_drvdata(dev_id);
50 struct rtc_device *rtc = platform_get_drvdata(pdev); 56 struct rtc_device *rtc = info->rtc;
51 unsigned int rtsr; 57 unsigned int rtsr;
52 unsigned long events = 0; 58 unsigned long events = 0;
53 59
54 spin_lock(&sa1100_rtc_lock); 60 spin_lock(&info->lock);
55 61
56 rtsr = RTSR; 62 rtsr = RTSR;
57 /* clear interrupt sources */ 63 /* clear interrupt sources */
@@ -87,27 +93,27 @@ static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id)
87 93
88 rtc_update_irq(rtc, 1, events); 94 rtc_update_irq(rtc, 1, events);
89 95
90 spin_unlock(&sa1100_rtc_lock); 96 spin_unlock(&info->lock);
91 97
92 return IRQ_HANDLED; 98 return IRQ_HANDLED;
93} 99}
94 100
95static int sa1100_rtc_open(struct device *dev) 101static int sa1100_rtc_open(struct device *dev)
96{ 102{
103 struct sa1100_rtc *info = dev_get_drvdata(dev);
104 struct rtc_device *rtc = info->rtc;
97 int ret; 105 int ret;
98 struct platform_device *plat_dev = to_platform_device(dev);
99 struct rtc_device *rtc = platform_get_drvdata(plat_dev);
100 106
101 ret = request_irq(IRQ_RTC1Hz, sa1100_rtc_interrupt, IRQF_DISABLED, 107 ret = request_irq(info->irq_1hz, sa1100_rtc_interrupt, IRQF_DISABLED,
102 "rtc 1Hz", dev); 108 "rtc 1Hz", dev);
103 if (ret) { 109 if (ret) {
104 dev_err(dev, "IRQ %d already in use.\n", IRQ_RTC1Hz); 110 dev_err(dev, "IRQ %d already in use.\n", info->irq_1hz);
105 goto fail_ui; 111 goto fail_ui;
106 } 112 }
107 ret = request_irq(IRQ_RTCAlrm, sa1100_rtc_interrupt, IRQF_DISABLED, 113 ret = request_irq(info->irq_alarm, sa1100_rtc_interrupt, IRQF_DISABLED,
108 "rtc Alrm", dev); 114 "rtc Alrm", dev);
109 if (ret) { 115 if (ret) {
110 dev_err(dev, "IRQ %d already in use.\n", IRQ_RTCAlrm); 116 dev_err(dev, "IRQ %d already in use.\n", info->irq_alarm);
111 goto fail_ai; 117 goto fail_ai;
112 } 118 }
113 rtc->max_user_freq = RTC_FREQ; 119 rtc->max_user_freq = RTC_FREQ;
@@ -116,29 +122,33 @@ static int sa1100_rtc_open(struct device *dev)
116 return 0; 122 return 0;
117 123
118 fail_ai: 124 fail_ai:
119 free_irq(IRQ_RTC1Hz, dev); 125 free_irq(info->irq_1hz, dev);
120 fail_ui: 126 fail_ui:
121 return ret; 127 return ret;
122} 128}
123 129
124static void sa1100_rtc_release(struct device *dev) 130static void sa1100_rtc_release(struct device *dev)
125{ 131{
126 spin_lock_irq(&sa1100_rtc_lock); 132 struct sa1100_rtc *info = dev_get_drvdata(dev);
133
134 spin_lock_irq(&info->lock);
127 RTSR = 0; 135 RTSR = 0;
128 spin_unlock_irq(&sa1100_rtc_lock); 136 spin_unlock_irq(&info->lock);
129 137
130 free_irq(IRQ_RTCAlrm, dev); 138 free_irq(info->irq_alarm, dev);
131 free_irq(IRQ_RTC1Hz, dev); 139 free_irq(info->irq_1hz, dev);
132} 140}
133 141
134static int sa1100_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) 142static int sa1100_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
135{ 143{
136 spin_lock_irq(&sa1100_rtc_lock); 144 struct sa1100_rtc *info = dev_get_drvdata(dev);
145
146 spin_lock_irq(&info->lock);
137 if (enabled) 147 if (enabled)
138 RTSR |= RTSR_ALE; 148 RTSR |= RTSR_ALE;
139 else 149 else
140 RTSR &= ~RTSR_ALE; 150 RTSR &= ~RTSR_ALE;
141 spin_unlock_irq(&sa1100_rtc_lock); 151 spin_unlock_irq(&info->lock);
142 return 0; 152 return 0;
143} 153}
144 154
@@ -171,10 +181,11 @@ static int sa1100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
171 181
172static int sa1100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) 182static int sa1100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
173{ 183{
184 struct sa1100_rtc *info = dev_get_drvdata(dev);
174 unsigned long time; 185 unsigned long time;
175 int ret; 186 int ret;
176 187
177 spin_lock_irq(&sa1100_rtc_lock); 188 spin_lock_irq(&info->lock);
178 ret = rtc_tm_to_time(&alrm->time, &time); 189 ret = rtc_tm_to_time(&alrm->time, &time);
179 if (ret != 0) 190 if (ret != 0)
180 goto out; 191 goto out;
@@ -185,7 +196,7 @@ static int sa1100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
185 else 196 else
186 RTSR &= ~RTSR_ALE; 197 RTSR &= ~RTSR_ALE;
187out: 198out:
188 spin_unlock_irq(&sa1100_rtc_lock); 199 spin_unlock_irq(&info->lock);
189 200
190 return ret; 201 return ret;
191} 202}
@@ -212,6 +223,21 @@ static const struct rtc_class_ops sa1100_rtc_ops = {
212static int sa1100_rtc_probe(struct platform_device *pdev) 223static int sa1100_rtc_probe(struct platform_device *pdev)
213{ 224{
214 struct rtc_device *rtc; 225 struct rtc_device *rtc;
226 struct sa1100_rtc *info;
227 int irq_1hz, irq_alarm, ret = 0;
228
229 irq_1hz = platform_get_irq_byname(pdev, "rtc 1Hz");
230 irq_alarm = platform_get_irq_byname(pdev, "rtc alarm");
231 if (irq_1hz < 0 || irq_alarm < 0)
232 return -ENODEV;
233
234 info = kzalloc(sizeof(struct sa1100_rtc), GFP_KERNEL);
235 if (!info)
236 return -ENOMEM;
237 info->irq_1hz = irq_1hz;
238 info->irq_alarm = irq_alarm;
239 spin_lock_init(&info->lock);
240 platform_set_drvdata(pdev, info);
215 241
216 /* 242 /*
217 * According to the manual we should be able to let RTTR be zero 243 * According to the manual we should be able to let RTTR be zero
@@ -233,10 +259,11 @@ static int sa1100_rtc_probe(struct platform_device *pdev)
233 rtc = rtc_device_register(pdev->name, &pdev->dev, &sa1100_rtc_ops, 259 rtc = rtc_device_register(pdev->name, &pdev->dev, &sa1100_rtc_ops,
234 THIS_MODULE); 260 THIS_MODULE);
235 261
236 if (IS_ERR(rtc)) 262 if (IS_ERR(rtc)) {
237 return PTR_ERR(rtc); 263 ret = PTR_ERR(rtc);
238 264 goto err_dev;
239 platform_set_drvdata(pdev, rtc); 265 }
266 info->rtc = rtc;
240 267
241 /* Fix for a nasty initialization problem the in SA11xx RTSR register. 268 /* Fix for a nasty initialization problem the in SA11xx RTSR register.
242 * See also the comments in sa1100_rtc_interrupt(). 269 * See also the comments in sa1100_rtc_interrupt().
@@ -263,14 +290,21 @@ static int sa1100_rtc_probe(struct platform_device *pdev)
263 RTSR = RTSR_AL | RTSR_HZ; 290 RTSR = RTSR_AL | RTSR_HZ;
264 291
265 return 0; 292 return 0;
293err_dev:
294 platform_set_drvdata(pdev, NULL);
295 kfree(info);
296 return ret;
266} 297}
267 298
268static int sa1100_rtc_remove(struct platform_device *pdev) 299static int sa1100_rtc_remove(struct platform_device *pdev)
269{ 300{
270 struct rtc_device *rtc = platform_get_drvdata(pdev); 301 struct sa1100_rtc *info = platform_get_drvdata(pdev);
271 302
272 if (rtc) 303 if (info) {
273 rtc_device_unregister(rtc); 304 rtc_device_unregister(info->rtc);
305 platform_set_drvdata(pdev, NULL);
306 kfree(info);
307 }
274 308
275 return 0; 309 return 0;
276} 310}
@@ -278,15 +312,17 @@ static int sa1100_rtc_remove(struct platform_device *pdev)
278#ifdef CONFIG_PM 312#ifdef CONFIG_PM
279static int sa1100_rtc_suspend(struct device *dev) 313static int sa1100_rtc_suspend(struct device *dev)
280{ 314{
315 struct sa1100_rtc *info = dev_get_drvdata(dev);
281 if (device_may_wakeup(dev)) 316 if (device_may_wakeup(dev))
282 enable_irq_wake(IRQ_RTCAlrm); 317 enable_irq_wake(info->irq_alarm);
283 return 0; 318 return 0;
284} 319}
285 320
286static int sa1100_rtc_resume(struct device *dev) 321static int sa1100_rtc_resume(struct device *dev)
287{ 322{
323 struct sa1100_rtc *info = dev_get_drvdata(dev);
288 if (device_may_wakeup(dev)) 324 if (device_may_wakeup(dev))
289 disable_irq_wake(IRQ_RTCAlrm); 325 disable_irq_wake(info->irq_alarm);
290 return 0; 326 return 0;
291} 327}
292 328