Blame view

drivers/rtc/rtc-sa1100.c 11.9 KB
e842f1c8f   Richard Purdie   [PATCH] RTC subsy...
1
2
3
4
5
6
7
8
9
10
11
  /*
   * Real Time Clock interface for StrongARM SA1x00 and XScale PXA2xx
   *
   * Copyright (c) 2000 Nils Faerber
   *
   * Based on rtc.c by Paul Gortmaker
   *
   * Original Driver by Nils Faerber <nils@kernelconcepts.de>
   *
   * Modifications from:
   *   CIH <cih@coventive.com>
2f82af08f   Nicolas Pitre   Nicolas Pitre has...
12
   *   Nicolas Pitre <nico@fluxnic.net>
e842f1c8f   Richard Purdie   [PATCH] RTC subsy...
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
   *   Andrew Christian <andrew.christian@hp.com>
   *
   * Converted to the RTC subsystem and Driver Model
   *   by Richard Purdie <rpurdie@rpsys.net>
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public License
   * as published by the Free Software Foundation; either version
   * 2 of the License, or (at your option) any later version.
   */
  
  #include <linux/platform_device.h>
  #include <linux/module.h>
  #include <linux/rtc.h>
  #include <linux/init.h>
  #include <linux/fs.h>
  #include <linux/interrupt.h>
e842f1c8f   Richard Purdie   [PATCH] RTC subsy...
30
  #include <linux/pm.h>
7cea00657   Jett.Zhou   RTC: sa1100: supp...
31
32
33
  #include <linux/slab.h>
  #include <linux/clk.h>
  #include <linux/io.h>
e842f1c8f   Richard Purdie   [PATCH] RTC subsy...
34

a09e64fbc   Russell King   [ARM] Move includ...
35
  #include <mach/hardware.h>
e842f1c8f   Richard Purdie   [PATCH] RTC subsy...
36
  #include <asm/irq.h>
e842f1c8f   Richard Purdie   [PATCH] RTC subsy...
37

a404ad1ff   Marcelo Roberto Jimenez   ARM: 6452/1: Fix ...
38
  #define RTC_DEF_DIVIDER		(32768 - 1)
e842f1c8f   Richard Purdie   [PATCH] RTC subsy...
39
  #define RTC_DEF_TRIM		0
7cea00657   Jett.Zhou   RTC: sa1100: supp...
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
  #define RTC_FREQ		1024
  
  #define RCNR		0x00	/* RTC Count Register */
  #define RTAR		0x04	/* RTC Alarm Register */
  #define RTSR		0x08	/* RTC Status Register */
  #define RTTR		0x0c	/* RTC Timer Trim Register */
  
  #define RTSR_HZE	(1 << 3)	/* HZ interrupt enable */
  #define RTSR_ALE	(1 << 2)	/* RTC alarm interrupt enable */
  #define RTSR_HZ		(1 << 1)	/* HZ rising-edge detected */
  #define RTSR_AL		(1 << 0)	/* RTC alarm detected */
  
  #define rtc_readl(sa1100_rtc, reg)	\
  	readl_relaxed((sa1100_rtc)->base + (reg))
  #define rtc_writel(sa1100_rtc, reg, value)	\
  	writel_relaxed((value), (sa1100_rtc)->base + (reg))
  
  struct sa1100_rtc {
  	struct resource		*ress;
  	void __iomem		*base;
  	struct clk		*clk;
  	int			irq_1Hz;
  	int			irq_Alrm;
  	struct rtc_device	*rtc;
  	spinlock_t		lock;		/* Protects this structure */
  };
797276ec9   Russell King   [RTC] rtc-sa1100:...
66
67
68
69
  /*
   * Calculate the next alarm time given the requested alarm time mask
   * and the current time.
   */
a404ad1ff   Marcelo Roberto Jimenez   ARM: 6452/1: Fix ...
70
71
  static void rtc_next_alarm_time(struct rtc_time *next, struct rtc_time *now,
  	struct rtc_time *alrm)
797276ec9   Russell King   [RTC] rtc-sa1100:...
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
  {
  	unsigned long next_time;
  	unsigned long now_time;
  
  	next->tm_year = now->tm_year;
  	next->tm_mon = now->tm_mon;
  	next->tm_mday = now->tm_mday;
  	next->tm_hour = alrm->tm_hour;
  	next->tm_min = alrm->tm_min;
  	next->tm_sec = alrm->tm_sec;
  
  	rtc_tm_to_time(now, &now_time);
  	rtc_tm_to_time(next, &next_time);
  
  	if (next_time < now_time) {
  		/* Advance one day */
  		next_time += 60 * 60 * 24;
  		rtc_time_to_tm(next_time, next);
  	}
  }
7d12e780e   David Howells   IRQ: Maintain reg...
92
  static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id)
e842f1c8f   Richard Purdie   [PATCH] RTC subsy...
93
94
  {
  	struct platform_device *pdev = to_platform_device(dev_id);
7cea00657   Jett.Zhou   RTC: sa1100: supp...
95
  	struct sa1100_rtc *sa1100_rtc = platform_get_drvdata(pdev);
e842f1c8f   Richard Purdie   [PATCH] RTC subsy...
96
97
  	unsigned int rtsr;
  	unsigned long events = 0;
7cea00657   Jett.Zhou   RTC: sa1100: supp...
98
  	spin_lock(&sa1100_rtc->lock);
e842f1c8f   Richard Purdie   [PATCH] RTC subsy...
99

e842f1c8f   Richard Purdie   [PATCH] RTC subsy...
100
  	/* clear interrupt sources */
7cea00657   Jett.Zhou   RTC: sa1100: supp...
101
102
  	rtsr = rtc_readl(sa1100_rtc, RTSR);
  	rtc_writel(sa1100_rtc, RTSR, 0);
7decaa557   Marcelo Roberto Jimenez   ARM: 6454/1: sa11...
103
104
105
106
107
108
  	/* Fix for a nasty initialization problem the in SA11xx RTSR register.
  	 * See also the comments in sa1100_rtc_probe(). */
  	if (rtsr & (RTSR_ALE | RTSR_HZE)) {
  		/* This is the original code, before there was the if test
  		 * above. This code does not clear interrupts that were not
  		 * enabled. */
7cea00657   Jett.Zhou   RTC: sa1100: supp...
109
  		rtc_writel(sa1100_rtc, RTSR, (RTSR_AL | RTSR_HZ) & (rtsr >> 2));
7decaa557   Marcelo Roberto Jimenez   ARM: 6454/1: sa11...
110
111
112
113
114
115
116
117
  	} else {
  		/* For some reason, it is possible to enter this routine
  		 * without interruptions enabled, it has been tested with
  		 * several units (Bug in SA11xx chip?).
  		 *
  		 * This situation leads to an infinite "loop" of interrupt
  		 * routine calling and as a result the processor seems to
  		 * lock on its first call to open(). */
7cea00657   Jett.Zhou   RTC: sa1100: supp...
118
  		rtc_writel(sa1100_rtc, RTSR, (RTSR_AL | RTSR_HZ));
7decaa557   Marcelo Roberto Jimenez   ARM: 6454/1: sa11...
119
  	}
e842f1c8f   Richard Purdie   [PATCH] RTC subsy...
120
121
122
123
  
  	/* clear alarm interrupt if it has occurred */
  	if (rtsr & RTSR_AL)
  		rtsr &= ~RTSR_ALE;
7cea00657   Jett.Zhou   RTC: sa1100: supp...
124
  	rtc_writel(sa1100_rtc, RTSR, rtsr & (RTSR_ALE | RTSR_HZE));
e842f1c8f   Richard Purdie   [PATCH] RTC subsy...
125
126
127
128
129
130
  
  	/* update irq data & counter */
  	if (rtsr & RTSR_AL)
  		events |= RTC_AF | RTC_IRQF;
  	if (rtsr & RTSR_HZ)
  		events |= RTC_UF | RTC_IRQF;
7cea00657   Jett.Zhou   RTC: sa1100: supp...
131
  	rtc_update_irq(sa1100_rtc->rtc, 1, events);
e842f1c8f   Richard Purdie   [PATCH] RTC subsy...
132

7cea00657   Jett.Zhou   RTC: sa1100: supp...
133
  	spin_unlock(&sa1100_rtc->lock);
e842f1c8f   Richard Purdie   [PATCH] RTC subsy...
134
135
136
  
  	return IRQ_HANDLED;
  }
e842f1c8f   Richard Purdie   [PATCH] RTC subsy...
137
138
  static int sa1100_rtc_open(struct device *dev)
  {
7cea00657   Jett.Zhou   RTC: sa1100: supp...
139
  	struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev);
e842f1c8f   Richard Purdie   [PATCH] RTC subsy...
140
  	int ret;
7cea00657   Jett.Zhou   RTC: sa1100: supp...
141
142
  	ret = request_irq(sa1100_rtc->irq_1Hz, sa1100_rtc_interrupt,
  				IRQF_DISABLED, "rtc 1Hz", dev);
e842f1c8f   Richard Purdie   [PATCH] RTC subsy...
143
  	if (ret) {
7cea00657   Jett.Zhou   RTC: sa1100: supp...
144
145
  		dev_err(dev, "IRQ %d already in use.
  ", sa1100_rtc->irq_1Hz);
e842f1c8f   Richard Purdie   [PATCH] RTC subsy...
146
147
  		goto fail_ui;
  	}
7cea00657   Jett.Zhou   RTC: sa1100: supp...
148
149
  	ret = request_irq(sa1100_rtc->irq_Alrm, sa1100_rtc_interrupt,
  				IRQF_DISABLED, "rtc Alrm", dev);
e842f1c8f   Richard Purdie   [PATCH] RTC subsy...
150
  	if (ret) {
7cea00657   Jett.Zhou   RTC: sa1100: supp...
151
152
  		dev_err(dev, "IRQ %d already in use.
  ", sa1100_rtc->irq_Alrm);
e842f1c8f   Richard Purdie   [PATCH] RTC subsy...
153
154
  		goto fail_ai;
  	}
7cea00657   Jett.Zhou   RTC: sa1100: supp...
155
156
  	sa1100_rtc->rtc->max_user_freq = RTC_FREQ;
  	rtc_irq_set_freq(sa1100_rtc->rtc, NULL, RTC_FREQ);
d2ccb52d8   Marcelo Roberto Jimenez   ARM: 6455/2: Bett...
157

e842f1c8f   Richard Purdie   [PATCH] RTC subsy...
158
  	return 0;
e842f1c8f   Richard Purdie   [PATCH] RTC subsy...
159
   fail_ai:
7cea00657   Jett.Zhou   RTC: sa1100: supp...
160
  	free_irq(sa1100_rtc->irq_1Hz, dev);
e842f1c8f   Richard Purdie   [PATCH] RTC subsy...
161
162
163
164
165
166
   fail_ui:
  	return ret;
  }
  
  static void sa1100_rtc_release(struct device *dev)
  {
7cea00657   Jett.Zhou   RTC: sa1100: supp...
167
  	struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev);
e842f1c8f   Richard Purdie   [PATCH] RTC subsy...
168

7cea00657   Jett.Zhou   RTC: sa1100: supp...
169
170
171
172
173
174
  	spin_lock_irq(&sa1100_rtc->lock);
  	rtc_writel(sa1100_rtc, RTSR, 0);
  	spin_unlock_irq(&sa1100_rtc->lock);
  
  	free_irq(sa1100_rtc->irq_Alrm, dev);
  	free_irq(sa1100_rtc->irq_1Hz, dev);
e842f1c8f   Richard Purdie   [PATCH] RTC subsy...
175
  }
16380c153   John Stultz   RTC: Convert rtc ...
176
177
  static int sa1100_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
  {
7cea00657   Jett.Zhou   RTC: sa1100: supp...
178
179
180
181
182
183
  	struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev);
  	unsigned int rtsr;
  
  	spin_lock_irq(&sa1100_rtc->lock);
  
  	rtsr = rtc_readl(sa1100_rtc, RTSR);
16380c153   John Stultz   RTC: Convert rtc ...
184
  	if (enabled)
7cea00657   Jett.Zhou   RTC: sa1100: supp...
185
  		rtsr |= RTSR_ALE;
16380c153   John Stultz   RTC: Convert rtc ...
186
  	else
7cea00657   Jett.Zhou   RTC: sa1100: supp...
187
188
189
190
  		rtsr &= ~RTSR_ALE;
  	rtc_writel(sa1100_rtc, RTSR, rtsr);
  
  	spin_unlock_irq(&sa1100_rtc->lock);
16380c153   John Stultz   RTC: Convert rtc ...
191
192
  	return 0;
  }
e842f1c8f   Richard Purdie   [PATCH] RTC subsy...
193
194
  static int sa1100_rtc_read_time(struct device *dev, struct rtc_time *tm)
  {
7cea00657   Jett.Zhou   RTC: sa1100: supp...
195
196
197
  	struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev);
  
  	rtc_time_to_tm(rtc_readl(sa1100_rtc, RCNR), tm);
e842f1c8f   Richard Purdie   [PATCH] RTC subsy...
198
199
200
201
202
  	return 0;
  }
  
  static int sa1100_rtc_set_time(struct device *dev, struct rtc_time *tm)
  {
7cea00657   Jett.Zhou   RTC: sa1100: supp...
203
  	struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev);
e842f1c8f   Richard Purdie   [PATCH] RTC subsy...
204
205
206
207
208
  	unsigned long time;
  	int ret;
  
  	ret = rtc_tm_to_time(tm, &time);
  	if (ret == 0)
7cea00657   Jett.Zhou   RTC: sa1100: supp...
209
  		rtc_writel(sa1100_rtc, RCNR, time);
e842f1c8f   Richard Purdie   [PATCH] RTC subsy...
210
211
212
213
214
  	return ret;
  }
  
  static int sa1100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
  {
7cea00657   Jett.Zhou   RTC: sa1100: supp...
215
216
217
  	struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev);
  	unsigned long time;
  	unsigned int rtsr;
32b49da46   David Brownell   [PATCH] rtc-sa110...
218

7cea00657   Jett.Zhou   RTC: sa1100: supp...
219
220
221
  	time = rtc_readl(sa1100_rtc, RCNR);
  	rtc_time_to_tm(time, &alrm->time);
  	rtsr = rtc_readl(sa1100_rtc, RTSR);
32b49da46   David Brownell   [PATCH] rtc-sa110...
222
223
  	alrm->enabled = (rtsr & RTSR_ALE) ? 1 : 0;
  	alrm->pending = (rtsr & RTSR_AL) ? 1 : 0;
e842f1c8f   Richard Purdie   [PATCH] RTC subsy...
224
225
226
227
228
  	return 0;
  }
  
  static int sa1100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
  {
7cea00657   Jett.Zhou   RTC: sa1100: supp...
229
  	struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev);
42874759d   Jett.Zhou   RTC: sa1100: remo...
230
  	struct rtc_time now_tm, alarm_tm;
7cea00657   Jett.Zhou   RTC: sa1100: supp...
231
232
233
234
  	unsigned long time, alarm;
  	unsigned int rtsr;
  
  	spin_lock_irq(&sa1100_rtc->lock);
e842f1c8f   Richard Purdie   [PATCH] RTC subsy...
235

7cea00657   Jett.Zhou   RTC: sa1100: supp...
236
237
238
239
240
  	time = rtc_readl(sa1100_rtc, RCNR);
  	rtc_time_to_tm(time, &now_tm);
  	rtc_next_alarm_time(&alarm_tm, &now_tm, &alrm->time);
  	rtc_tm_to_time(&alarm_tm, &alarm);
  	rtc_writel(sa1100_rtc, RTAR, alarm);
42874759d   Jett.Zhou   RTC: sa1100: remo...
241

7cea00657   Jett.Zhou   RTC: sa1100: supp...
242
  	rtsr = rtc_readl(sa1100_rtc, RTSR);
42874759d   Jett.Zhou   RTC: sa1100: remo...
243
  	if (alrm->enabled)
7cea00657   Jett.Zhou   RTC: sa1100: supp...
244
  		rtsr |= RTSR_ALE;
42874759d   Jett.Zhou   RTC: sa1100: remo...
245
  	else
7cea00657   Jett.Zhou   RTC: sa1100: supp...
246
247
  		rtsr &= ~RTSR_ALE;
  	rtc_writel(sa1100_rtc, RTSR, rtsr);
42874759d   Jett.Zhou   RTC: sa1100: remo...
248

7cea00657   Jett.Zhou   RTC: sa1100: supp...
249
  	spin_unlock_irq(&sa1100_rtc->lock);
e842f1c8f   Richard Purdie   [PATCH] RTC subsy...
250

7cea00657   Jett.Zhou   RTC: sa1100: supp...
251
  	return 0;
e842f1c8f   Richard Purdie   [PATCH] RTC subsy...
252
253
254
255
  }
  
  static int sa1100_rtc_proc(struct device *dev, struct seq_file *seq)
  {
7cea00657   Jett.Zhou   RTC: sa1100: supp...
256
  	struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev);
e842f1c8f   Richard Purdie   [PATCH] RTC subsy...
257

7cea00657   Jett.Zhou   RTC: sa1100: supp...
258
259
260
261
262
263
  	seq_printf(seq, "trim/divider\t\t: 0x%08x
  ",
  			rtc_readl(sa1100_rtc, RTTR));
  	seq_printf(seq, "RTSR\t\t\t: 0x%08x
  ",
  			rtc_readl(sa1100_rtc, RTSR));
e842f1c8f   Richard Purdie   [PATCH] RTC subsy...
264
265
  	return 0;
  }
ff8371ac9   David Brownell   [PATCH] constify ...
266
  static const struct rtc_class_ops sa1100_rtc_ops = {
e842f1c8f   Richard Purdie   [PATCH] RTC subsy...
267
  	.open = sa1100_rtc_open,
e842f1c8f   Richard Purdie   [PATCH] RTC subsy...
268
  	.release = sa1100_rtc_release,
e842f1c8f   Richard Purdie   [PATCH] RTC subsy...
269
270
271
272
273
  	.read_time = sa1100_rtc_read_time,
  	.set_time = sa1100_rtc_set_time,
  	.read_alarm = sa1100_rtc_read_alarm,
  	.set_alarm = sa1100_rtc_set_alarm,
  	.proc = sa1100_rtc_proc,
16380c153   John Stultz   RTC: Convert rtc ...
274
  	.alarm_irq_enable = sa1100_rtc_alarm_irq_enable,
e842f1c8f   Richard Purdie   [PATCH] RTC subsy...
275
276
277
278
  };
  
  static int sa1100_rtc_probe(struct platform_device *pdev)
  {
7cea00657   Jett.Zhou   RTC: sa1100: supp...
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
  	struct sa1100_rtc *sa1100_rtc;
  	unsigned int rttr;
  	int ret;
  
  	sa1100_rtc = kzalloc(sizeof(struct sa1100_rtc), GFP_KERNEL);
  	if (!sa1100_rtc)
  		return -ENOMEM;
  
  	spin_lock_init(&sa1100_rtc->lock);
  	platform_set_drvdata(pdev, sa1100_rtc);
  
  	ret = -ENXIO;
  	sa1100_rtc->ress = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  	if (!sa1100_rtc->ress) {
  		dev_err(&pdev->dev, "No I/O memory resource defined
  ");
  		goto err_ress;
  	}
  
  	sa1100_rtc->irq_1Hz = platform_get_irq(pdev, 0);
  	if (sa1100_rtc->irq_1Hz < 0) {
  		dev_err(&pdev->dev, "No 1Hz IRQ resource defined
  ");
  		goto err_ress;
  	}
  	sa1100_rtc->irq_Alrm = platform_get_irq(pdev, 1);
  	if (sa1100_rtc->irq_Alrm < 0) {
  		dev_err(&pdev->dev, "No alarm IRQ resource defined
  ");
  		goto err_ress;
  	}
  
  	ret = -ENOMEM;
  	sa1100_rtc->base = ioremap(sa1100_rtc->ress->start,
  				resource_size(sa1100_rtc->ress));
  	if (!sa1100_rtc->base) {
  		dev_err(&pdev->dev, "Unable to map pxa RTC I/O memory
  ");
  		goto err_map;
  	}
  
  	sa1100_rtc->clk = clk_get(&pdev->dev, NULL);
  	if (IS_ERR(sa1100_rtc->clk)) {
  		dev_err(&pdev->dev, "failed to find rtc clock source
  ");
  		ret = PTR_ERR(sa1100_rtc->clk);
  		goto err_clk;
  	}
  	clk_prepare(sa1100_rtc->clk);
  	clk_enable(sa1100_rtc->clk);
e842f1c8f   Richard Purdie   [PATCH] RTC subsy...
329
330
331
332
333
334
335
336
  
  	/*
  	 * According to the manual we should be able to let RTTR be zero
  	 * and then a default diviser for a 32.768KHz clock is used.
  	 * Apparently this doesn't work, at least for my SA1110 rev 5.
  	 * If the clock divider is uninitialized then reset it to the
  	 * default value to get the 1Hz clock.
  	 */
7cea00657   Jett.Zhou   RTC: sa1100: supp...
337
338
339
340
341
342
  	if (rtc_readl(sa1100_rtc, RTTR) == 0) {
  		rttr = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16);
  		rtc_writel(sa1100_rtc, RTTR, rttr);
  		dev_warn(&pdev->dev, "warning: initializing default clock"
  			 " divider/trim value
  ");
e842f1c8f   Richard Purdie   [PATCH] RTC subsy...
343
  		/* The current RTC value probably doesn't make sense either */
7cea00657   Jett.Zhou   RTC: sa1100: supp...
344
  		rtc_writel(sa1100_rtc, RCNR, 0);
e842f1c8f   Richard Purdie   [PATCH] RTC subsy...
345
  	}
e5a2c9ccb   Uli Luckas   [ARM] 5109/1: Mar...
346
  	device_init_wakeup(&pdev->dev, 1);
7cea00657   Jett.Zhou   RTC: sa1100: supp...
347
348
349
350
351
352
353
354
  	sa1100_rtc->rtc = rtc_device_register(pdev->name, &pdev->dev,
  						&sa1100_rtc_ops, THIS_MODULE);
  	if (IS_ERR(sa1100_rtc->rtc)) {
  		dev_err(&pdev->dev, "Failed to register RTC device -> %d
  ",
  			ret);
  		goto err_rtc_reg;
  	}
7decaa557   Marcelo Roberto Jimenez   ARM: 6454/1: sa11...
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
  	/* Fix for a nasty initialization problem the in SA11xx RTSR register.
  	 * See also the comments in sa1100_rtc_interrupt().
  	 *
  	 * Sometimes bit 1 of the RTSR (RTSR_HZ) will wake up 1, which means an
  	 * interrupt pending, even though interrupts were never enabled.
  	 * In this case, this bit it must be reset before enabling
  	 * interruptions to avoid a nonexistent interrupt to occur.
  	 *
  	 * In principle, the same problem would apply to bit 0, although it has
  	 * never been observed to happen.
  	 *
  	 * This issue is addressed both here and in sa1100_rtc_interrupt().
  	 * If the issue is not addressed here, in the times when the processor
  	 * wakes up with the bit set there will be one spurious interrupt.
  	 *
  	 * The issue is also dealt with in sa1100_rtc_interrupt() to be on the
  	 * safe side, once the condition that lead to this strange
  	 * initialization is unknown and could in principle happen during
  	 * normal processing.
  	 *
  	 * Notice that clearing bit 1 and 0 is accomplished by writting ONES to
  	 * the corresponding bits in RTSR. */
7cea00657   Jett.Zhou   RTC: sa1100: supp...
377
  	rtc_writel(sa1100_rtc, RTSR, (RTSR_AL | RTSR_HZ));
7decaa557   Marcelo Roberto Jimenez   ARM: 6454/1: sa11...
378

e842f1c8f   Richard Purdie   [PATCH] RTC subsy...
379
  	return 0;
7cea00657   Jett.Zhou   RTC: sa1100: supp...
380
381
382
383
384
385
386
387
  
  err_rtc_reg:
  err_clk:
  	iounmap(sa1100_rtc->base);
  err_ress:
  err_map:
  	kfree(sa1100_rtc);
  	return ret;
e842f1c8f   Richard Purdie   [PATCH] RTC subsy...
388
389
390
391
  }
  
  static int sa1100_rtc_remove(struct platform_device *pdev)
  {
7cea00657   Jett.Zhou   RTC: sa1100: supp...
392
  	struct sa1100_rtc *sa1100_rtc = platform_get_drvdata(pdev);
e842f1c8f   Richard Purdie   [PATCH] RTC subsy...
393

7cea00657   Jett.Zhou   RTC: sa1100: supp...
394
395
396
397
  	rtc_device_unregister(sa1100_rtc->rtc);
  	clk_disable(sa1100_rtc->clk);
  	clk_unprepare(sa1100_rtc->clk);
  	iounmap(sa1100_rtc->base);
e842f1c8f   Richard Purdie   [PATCH] RTC subsy...
398
399
  	return 0;
  }
6bc54e699   Russell King   [ARM] pxa/sa1100:...
400
  #ifdef CONFIG_PM
5d027cd22   Haojian Zhuang   [ARM] pxa: update...
401
  static int sa1100_rtc_suspend(struct device *dev)
6bc54e699   Russell King   [ARM] pxa/sa1100:...
402
  {
7cea00657   Jett.Zhou   RTC: sa1100: supp...
403
  	struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev);
5d027cd22   Haojian Zhuang   [ARM] pxa: update...
404
  	if (device_may_wakeup(dev))
7cea00657   Jett.Zhou   RTC: sa1100: supp...
405
  		enable_irq_wake(sa1100_rtc->irq_Alrm);
6bc54e699   Russell King   [ARM] pxa/sa1100:...
406
407
  	return 0;
  }
5d027cd22   Haojian Zhuang   [ARM] pxa: update...
408
  static int sa1100_rtc_resume(struct device *dev)
6bc54e699   Russell King   [ARM] pxa/sa1100:...
409
  {
7cea00657   Jett.Zhou   RTC: sa1100: supp...
410
  	struct sa1100_rtc *sa1100_rtc = dev_get_drvdata(dev);
5d027cd22   Haojian Zhuang   [ARM] pxa: update...
411
  	if (device_may_wakeup(dev))
7cea00657   Jett.Zhou   RTC: sa1100: supp...
412
  		disable_irq_wake(sa1100_rtc->irq_Alrm);
6bc54e699   Russell King   [ARM] pxa/sa1100:...
413
414
  	return 0;
  }
5d027cd22   Haojian Zhuang   [ARM] pxa: update...
415

471452104   Alexey Dobriyan   const: constify r...
416
  static const struct dev_pm_ops sa1100_rtc_pm_ops = {
5d027cd22   Haojian Zhuang   [ARM] pxa: update...
417
418
419
  	.suspend	= sa1100_rtc_suspend,
  	.resume		= sa1100_rtc_resume,
  };
6bc54e699   Russell King   [ARM] pxa/sa1100:...
420
  #endif
e842f1c8f   Richard Purdie   [PATCH] RTC subsy...
421
422
423
424
  static struct platform_driver sa1100_rtc_driver = {
  	.probe		= sa1100_rtc_probe,
  	.remove		= sa1100_rtc_remove,
  	.driver		= {
5d027cd22   Haojian Zhuang   [ARM] pxa: update...
425
426
427
428
  		.name	= "sa1100-rtc",
  #ifdef CONFIG_PM
  		.pm	= &sa1100_rtc_pm_ops,
  #endif
e842f1c8f   Richard Purdie   [PATCH] RTC subsy...
429
430
  	},
  };
0c4eae665   Axel Lin   rtc: convert driv...
431
  module_platform_driver(sa1100_rtc_driver);
e842f1c8f   Richard Purdie   [PATCH] RTC subsy...
432
433
434
435
  
  MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>");
  MODULE_DESCRIPTION("SA11x0/PXA2xx Realtime Clock Driver (RTC)");
  MODULE_LICENSE("GPL");
ad28a07bc   Kay Sievers   rtc: fix platform...
436
  MODULE_ALIAS("platform:sa1100-rtc");