xref: /openbmc/linux/drivers/rtc/rtc-sa1100.c (revision 23019a733bb83c8499f192fb428b7e6e81c95a34)
1e842f1c8SRichard Purdie /*
2e842f1c8SRichard Purdie  * Real Time Clock interface for StrongARM SA1x00 and XScale PXA2xx
3e842f1c8SRichard Purdie  *
4e842f1c8SRichard Purdie  * Copyright (c) 2000 Nils Faerber
5e842f1c8SRichard Purdie  *
6e842f1c8SRichard Purdie  * Based on rtc.c by Paul Gortmaker
7e842f1c8SRichard Purdie  *
8e842f1c8SRichard Purdie  * Original Driver by Nils Faerber <nils@kernelconcepts.de>
9e842f1c8SRichard Purdie  *
10e842f1c8SRichard Purdie  * Modifications from:
11e842f1c8SRichard Purdie  *   CIH <cih@coventive.com>
122f82af08SNicolas Pitre  *   Nicolas Pitre <nico@fluxnic.net>
13e842f1c8SRichard Purdie  *   Andrew Christian <andrew.christian@hp.com>
14e842f1c8SRichard Purdie  *
15e842f1c8SRichard Purdie  * Converted to the RTC subsystem and Driver Model
16e842f1c8SRichard Purdie  *   by Richard Purdie <rpurdie@rpsys.net>
17e842f1c8SRichard Purdie  *
18e842f1c8SRichard Purdie  * This program is free software; you can redistribute it and/or
19e842f1c8SRichard Purdie  * modify it under the terms of the GNU General Public License
20e842f1c8SRichard Purdie  * as published by the Free Software Foundation; either version
21e842f1c8SRichard Purdie  * 2 of the License, or (at your option) any later version.
22e842f1c8SRichard Purdie  */
23e842f1c8SRichard Purdie 
24e842f1c8SRichard Purdie #include <linux/platform_device.h>
25e842f1c8SRichard Purdie #include <linux/module.h>
26e842f1c8SRichard Purdie #include <linux/rtc.h>
27e842f1c8SRichard Purdie #include <linux/init.h>
28e842f1c8SRichard Purdie #include <linux/fs.h>
29e842f1c8SRichard Purdie #include <linux/interrupt.h>
30a0164a57SRussell King #include <linux/string.h>
31e842f1c8SRichard Purdie #include <linux/pm.h>
32a0164a57SRussell King #include <linux/bitops.h>
33*23019a73SRob Herring #include <linux/io.h>
34e842f1c8SRichard Purdie 
35a09e64fbSRussell King #include <mach/hardware.h>
36e842f1c8SRichard Purdie #include <asm/irq.h>
37e842f1c8SRichard Purdie 
38a0164a57SRussell King #ifdef CONFIG_ARCH_PXA
39a0164a57SRussell King #include <mach/regs-rtc.h>
40a0164a57SRussell King #endif
41a0164a57SRussell King 
42a404ad1fSMarcelo Roberto Jimenez #define RTC_DEF_DIVIDER		(32768 - 1)
43e842f1c8SRichard Purdie #define RTC_DEF_TRIM		0
44e842f1c8SRichard Purdie 
45a0164a57SRussell King static const unsigned long RTC_FREQ = 1024;
46a0164a57SRussell King static struct rtc_time rtc_alarm;
47a0164a57SRussell King static DEFINE_SPINLOCK(sa1100_rtc_lock);
48e842f1c8SRichard Purdie 
4957270fcdSRussell King static inline int rtc_periodic_alarm(struct rtc_time *tm)
5057270fcdSRussell King {
5157270fcdSRussell King 	return  (tm->tm_year == -1) ||
5257270fcdSRussell King 		((unsigned)tm->tm_mon >= 12) ||
5357270fcdSRussell King 		((unsigned)(tm->tm_mday - 1) >= 31) ||
5457270fcdSRussell King 		((unsigned)tm->tm_hour > 23) ||
5557270fcdSRussell King 		((unsigned)tm->tm_min > 59) ||
5657270fcdSRussell King 		((unsigned)tm->tm_sec > 59);
5757270fcdSRussell King }
5857270fcdSRussell King 
59797276ecSRussell King /*
60797276ecSRussell King  * Calculate the next alarm time given the requested alarm time mask
61797276ecSRussell King  * and the current time.
62797276ecSRussell King  */
63a404ad1fSMarcelo Roberto Jimenez static void rtc_next_alarm_time(struct rtc_time *next, struct rtc_time *now,
64a404ad1fSMarcelo Roberto Jimenez 	struct rtc_time *alrm)
65797276ecSRussell King {
66797276ecSRussell King 	unsigned long next_time;
67797276ecSRussell King 	unsigned long now_time;
68797276ecSRussell King 
69797276ecSRussell King 	next->tm_year = now->tm_year;
70797276ecSRussell King 	next->tm_mon = now->tm_mon;
71797276ecSRussell King 	next->tm_mday = now->tm_mday;
72797276ecSRussell King 	next->tm_hour = alrm->tm_hour;
73797276ecSRussell King 	next->tm_min = alrm->tm_min;
74797276ecSRussell King 	next->tm_sec = alrm->tm_sec;
75797276ecSRussell King 
76797276ecSRussell King 	rtc_tm_to_time(now, &now_time);
77797276ecSRussell King 	rtc_tm_to_time(next, &next_time);
78797276ecSRussell King 
79797276ecSRussell King 	if (next_time < now_time) {
80797276ecSRussell King 		/* Advance one day */
81797276ecSRussell King 		next_time += 60 * 60 * 24;
82797276ecSRussell King 		rtc_time_to_tm(next_time, next);
83797276ecSRussell King 	}
84797276ecSRussell King }
85797276ecSRussell King 
8657270fcdSRussell King static int rtc_update_alarm(struct rtc_time *alrm)
8757270fcdSRussell King {
8857270fcdSRussell King 	struct rtc_time alarm_tm, now_tm;
8957270fcdSRussell King 	unsigned long now, time;
9057270fcdSRussell King 	int ret;
9157270fcdSRussell King 
9257270fcdSRussell King 	do {
9357270fcdSRussell King 		now = RCNR;
9457270fcdSRussell King 		rtc_time_to_tm(now, &now_tm);
9557270fcdSRussell King 		rtc_next_alarm_time(&alarm_tm, &now_tm, alrm);
9657270fcdSRussell King 		ret = rtc_tm_to_time(&alarm_tm, &time);
9757270fcdSRussell King 		if (ret != 0)
9857270fcdSRussell King 			break;
9957270fcdSRussell King 
10057270fcdSRussell King 		RTSR = RTSR & (RTSR_HZE|RTSR_ALE|RTSR_AL);
10157270fcdSRussell King 		RTAR = time;
10257270fcdSRussell King 	} while (now != RCNR);
10357270fcdSRussell King 
10457270fcdSRussell King 	return ret;
10557270fcdSRussell King }
10657270fcdSRussell King 
1077d12e780SDavid Howells static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id)
108e842f1c8SRichard Purdie {
109e842f1c8SRichard Purdie 	struct platform_device *pdev = to_platform_device(dev_id);
110a0164a57SRussell King 	struct rtc_device *rtc = platform_get_drvdata(pdev);
111e842f1c8SRichard Purdie 	unsigned int rtsr;
112e842f1c8SRichard Purdie 	unsigned long events = 0;
113e842f1c8SRichard Purdie 
114a0164a57SRussell King 	spin_lock(&sa1100_rtc_lock);
115e842f1c8SRichard Purdie 
116a0164a57SRussell King 	rtsr = RTSR;
117e842f1c8SRichard Purdie 	/* clear interrupt sources */
118a0164a57SRussell King 	RTSR = 0;
1197decaa55SMarcelo Roberto Jimenez 	/* Fix for a nasty initialization problem the in SA11xx RTSR register.
1207decaa55SMarcelo Roberto Jimenez 	 * See also the comments in sa1100_rtc_probe(). */
1217decaa55SMarcelo Roberto Jimenez 	if (rtsr & (RTSR_ALE | RTSR_HZE)) {
1227decaa55SMarcelo Roberto Jimenez 		/* This is the original code, before there was the if test
1237decaa55SMarcelo Roberto Jimenez 		 * above. This code does not clear interrupts that were not
1247decaa55SMarcelo Roberto Jimenez 		 * enabled. */
125a0164a57SRussell King 		RTSR = (RTSR_AL | RTSR_HZ) & (rtsr >> 2);
1267decaa55SMarcelo Roberto Jimenez 	} else {
1277decaa55SMarcelo Roberto Jimenez 		/* For some reason, it is possible to enter this routine
1287decaa55SMarcelo Roberto Jimenez 		 * without interruptions enabled, it has been tested with
1297decaa55SMarcelo Roberto Jimenez 		 * several units (Bug in SA11xx chip?).
1307decaa55SMarcelo Roberto Jimenez 		 *
1317decaa55SMarcelo Roberto Jimenez 		 * This situation leads to an infinite "loop" of interrupt
1327decaa55SMarcelo Roberto Jimenez 		 * routine calling and as a result the processor seems to
1337decaa55SMarcelo Roberto Jimenez 		 * lock on its first call to open(). */
134a0164a57SRussell King 		RTSR = RTSR_AL | RTSR_HZ;
1357decaa55SMarcelo Roberto Jimenez 	}
136e842f1c8SRichard Purdie 
137e842f1c8SRichard Purdie 	/* clear alarm interrupt if it has occurred */
138e842f1c8SRichard Purdie 	if (rtsr & RTSR_AL)
139e842f1c8SRichard Purdie 		rtsr &= ~RTSR_ALE;
140a0164a57SRussell King 	RTSR = rtsr & (RTSR_ALE | RTSR_HZE);
141e842f1c8SRichard Purdie 
142e842f1c8SRichard Purdie 	/* update irq data & counter */
143e842f1c8SRichard Purdie 	if (rtsr & RTSR_AL)
144e842f1c8SRichard Purdie 		events |= RTC_AF | RTC_IRQF;
145e842f1c8SRichard Purdie 	if (rtsr & RTSR_HZ)
146e842f1c8SRichard Purdie 		events |= RTC_UF | RTC_IRQF;
147e842f1c8SRichard Purdie 
148a0164a57SRussell King 	rtc_update_irq(rtc, 1, events);
149e842f1c8SRichard Purdie 
15057270fcdSRussell King 	if (rtsr & RTSR_AL && rtc_periodic_alarm(&rtc_alarm))
15157270fcdSRussell King 		rtc_update_alarm(&rtc_alarm);
15257270fcdSRussell King 
153a0164a57SRussell King 	spin_unlock(&sa1100_rtc_lock);
154e842f1c8SRichard Purdie 
155e842f1c8SRichard Purdie 	return IRQ_HANDLED;
156e842f1c8SRichard Purdie }
157e842f1c8SRichard Purdie 
158e842f1c8SRichard Purdie static int sa1100_rtc_open(struct device *dev)
159e842f1c8SRichard Purdie {
160e842f1c8SRichard Purdie 	int ret;
161a0164a57SRussell King 	struct platform_device *plat_dev = to_platform_device(dev);
162a0164a57SRussell King 	struct rtc_device *rtc = platform_get_drvdata(plat_dev);
163e842f1c8SRichard Purdie 
164a0164a57SRussell King 	ret = request_irq(IRQ_RTC1Hz, sa1100_rtc_interrupt, IRQF_DISABLED,
165a0164a57SRussell King 		"rtc 1Hz", dev);
166e842f1c8SRichard Purdie 	if (ret) {
167a0164a57SRussell King 		dev_err(dev, "IRQ %d already in use.\n", IRQ_RTC1Hz);
168e842f1c8SRichard Purdie 		goto fail_ui;
169e842f1c8SRichard Purdie 	}
170a0164a57SRussell King 	ret = request_irq(IRQ_RTCAlrm, sa1100_rtc_interrupt, IRQF_DISABLED,
171a0164a57SRussell King 		"rtc Alrm", dev);
172e842f1c8SRichard Purdie 	if (ret) {
173a0164a57SRussell King 		dev_err(dev, "IRQ %d already in use.\n", IRQ_RTCAlrm);
174e842f1c8SRichard Purdie 		goto fail_ai;
175e842f1c8SRichard Purdie 	}
176a0164a57SRussell King 	rtc->max_user_freq = RTC_FREQ;
177a0164a57SRussell King 	rtc_irq_set_freq(rtc, NULL, RTC_FREQ);
178d2ccb52dSMarcelo Roberto Jimenez 
179e842f1c8SRichard Purdie 	return 0;
180e842f1c8SRichard Purdie 
181e842f1c8SRichard Purdie  fail_ai:
182a0164a57SRussell King 	free_irq(IRQ_RTC1Hz, dev);
183e842f1c8SRichard Purdie  fail_ui:
184e842f1c8SRichard Purdie 	return ret;
185e842f1c8SRichard Purdie }
186e842f1c8SRichard Purdie 
187e842f1c8SRichard Purdie static void sa1100_rtc_release(struct device *dev)
188e842f1c8SRichard Purdie {
189a0164a57SRussell King 	spin_lock_irq(&sa1100_rtc_lock);
190a0164a57SRussell King 	RTSR = 0;
191a0164a57SRussell King 	spin_unlock_irq(&sa1100_rtc_lock);
192e842f1c8SRichard Purdie 
193a0164a57SRussell King 	free_irq(IRQ_RTCAlrm, dev);
194a0164a57SRussell King 	free_irq(IRQ_RTC1Hz, dev);
195e842f1c8SRichard Purdie }
196e842f1c8SRichard Purdie 
19716380c15SJohn Stultz static int sa1100_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
19816380c15SJohn Stultz {
199a0164a57SRussell King 	spin_lock_irq(&sa1100_rtc_lock);
20016380c15SJohn Stultz 	if (enabled)
201a0164a57SRussell King 		RTSR |= RTSR_ALE;
20216380c15SJohn Stultz 	else
203a0164a57SRussell King 		RTSR &= ~RTSR_ALE;
204a0164a57SRussell King 	spin_unlock_irq(&sa1100_rtc_lock);
20516380c15SJohn Stultz 	return 0;
20616380c15SJohn Stultz }
20716380c15SJohn Stultz 
208e842f1c8SRichard Purdie static int sa1100_rtc_read_time(struct device *dev, struct rtc_time *tm)
209e842f1c8SRichard Purdie {
210a0164a57SRussell King 	rtc_time_to_tm(RCNR, tm);
211e842f1c8SRichard Purdie 	return 0;
212e842f1c8SRichard Purdie }
213e842f1c8SRichard Purdie 
214e842f1c8SRichard Purdie static int sa1100_rtc_set_time(struct device *dev, struct rtc_time *tm)
215e842f1c8SRichard Purdie {
216e842f1c8SRichard Purdie 	unsigned long time;
217e842f1c8SRichard Purdie 	int ret;
218e842f1c8SRichard Purdie 
219e842f1c8SRichard Purdie 	ret = rtc_tm_to_time(tm, &time);
220e842f1c8SRichard Purdie 	if (ret == 0)
221a0164a57SRussell King 		RCNR = time;
222e842f1c8SRichard Purdie 	return ret;
223e842f1c8SRichard Purdie }
224e842f1c8SRichard Purdie 
225e842f1c8SRichard Purdie static int sa1100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
226e842f1c8SRichard Purdie {
227a0164a57SRussell King 	u32	rtsr;
22832b49da4SDavid Brownell 
229a0164a57SRussell King 	memcpy(&alrm->time, &rtc_alarm, sizeof(struct rtc_time));
230a0164a57SRussell King 	rtsr = RTSR;
23132b49da4SDavid Brownell 	alrm->enabled = (rtsr & RTSR_ALE) ? 1 : 0;
23232b49da4SDavid Brownell 	alrm->pending = (rtsr & RTSR_AL) ? 1 : 0;
233e842f1c8SRichard Purdie 	return 0;
234e842f1c8SRichard Purdie }
235e842f1c8SRichard Purdie 
236e842f1c8SRichard Purdie static int sa1100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
237e842f1c8SRichard Purdie {
238a0164a57SRussell King 	int ret;
239e842f1c8SRichard Purdie 
240a0164a57SRussell King 	spin_lock_irq(&sa1100_rtc_lock);
24157270fcdSRussell King 	ret = rtc_update_alarm(&alrm->time);
24257270fcdSRussell King 	if (ret == 0) {
243e842f1c8SRichard Purdie 		if (alrm->enabled)
244a0164a57SRussell King 			RTSR |= RTSR_ALE;
245e842f1c8SRichard Purdie 		else
246a0164a57SRussell King 			RTSR &= ~RTSR_ALE;
24757270fcdSRussell King 	}
248a0164a57SRussell King 	spin_unlock_irq(&sa1100_rtc_lock);
249e842f1c8SRichard Purdie 
250a0164a57SRussell King 	return ret;
251e842f1c8SRichard Purdie }
252e842f1c8SRichard Purdie 
253e842f1c8SRichard Purdie static int sa1100_rtc_proc(struct device *dev, struct seq_file *seq)
254e842f1c8SRichard Purdie {
255a0164a57SRussell King 	seq_printf(seq, "trim/divider\t\t: 0x%08x\n", (u32) RTTR);
256a0164a57SRussell King 	seq_printf(seq, "RTSR\t\t\t: 0x%08x\n", (u32)RTSR);
257e842f1c8SRichard Purdie 
258e842f1c8SRichard Purdie 	return 0;
259e842f1c8SRichard Purdie }
260e842f1c8SRichard Purdie 
261ff8371acSDavid Brownell static const struct rtc_class_ops sa1100_rtc_ops = {
262e842f1c8SRichard Purdie 	.open = sa1100_rtc_open,
263e842f1c8SRichard Purdie 	.release = sa1100_rtc_release,
264e842f1c8SRichard Purdie 	.read_time = sa1100_rtc_read_time,
265e842f1c8SRichard Purdie 	.set_time = sa1100_rtc_set_time,
266e842f1c8SRichard Purdie 	.read_alarm = sa1100_rtc_read_alarm,
267e842f1c8SRichard Purdie 	.set_alarm = sa1100_rtc_set_alarm,
268e842f1c8SRichard Purdie 	.proc = sa1100_rtc_proc,
26916380c15SJohn Stultz 	.alarm_irq_enable = sa1100_rtc_alarm_irq_enable,
270e842f1c8SRichard Purdie };
271e842f1c8SRichard Purdie 
272e842f1c8SRichard Purdie static int sa1100_rtc_probe(struct platform_device *pdev)
273e842f1c8SRichard Purdie {
274a0164a57SRussell King 	struct rtc_device *rtc;
275e842f1c8SRichard Purdie 
276e842f1c8SRichard Purdie 	/*
277e842f1c8SRichard Purdie 	 * According to the manual we should be able to let RTTR be zero
278e842f1c8SRichard Purdie 	 * and then a default diviser for a 32.768KHz clock is used.
279e842f1c8SRichard Purdie 	 * Apparently this doesn't work, at least for my SA1110 rev 5.
280e842f1c8SRichard Purdie 	 * If the clock divider is uninitialized then reset it to the
281e842f1c8SRichard Purdie 	 * default value to get the 1Hz clock.
282e842f1c8SRichard Purdie 	 */
283a0164a57SRussell King 	if (RTTR == 0) {
284a0164a57SRussell King 		RTTR = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16);
285a0164a57SRussell King 		dev_warn(&pdev->dev, "warning: "
286a0164a57SRussell King 			"initializing default clock divider/trim value\n");
287e842f1c8SRichard Purdie 		/* The current RTC value probably doesn't make sense either */
288a0164a57SRussell King 		RCNR = 0;
289e842f1c8SRichard Purdie 	}
290e842f1c8SRichard Purdie 
291e5a2c9ccSUli Luckas 	device_init_wakeup(&pdev->dev, 1);
292e5a2c9ccSUli Luckas 
293a0164a57SRussell King 	rtc = rtc_device_register(pdev->name, &pdev->dev, &sa1100_rtc_ops,
294a0164a57SRussell King 		THIS_MODULE);
295a0164a57SRussell King 
296a0164a57SRussell King 	if (IS_ERR(rtc))
297a0164a57SRussell King 		return PTR_ERR(rtc);
298a0164a57SRussell King 
299a0164a57SRussell King 	platform_set_drvdata(pdev, rtc);
300a0164a57SRussell King 
3017decaa55SMarcelo Roberto Jimenez 	/* Fix for a nasty initialization problem the in SA11xx RTSR register.
3027decaa55SMarcelo Roberto Jimenez 	 * See also the comments in sa1100_rtc_interrupt().
3037decaa55SMarcelo Roberto Jimenez 	 *
3047decaa55SMarcelo Roberto Jimenez 	 * Sometimes bit 1 of the RTSR (RTSR_HZ) will wake up 1, which means an
3057decaa55SMarcelo Roberto Jimenez 	 * interrupt pending, even though interrupts were never enabled.
3067decaa55SMarcelo Roberto Jimenez 	 * In this case, this bit it must be reset before enabling
3077decaa55SMarcelo Roberto Jimenez 	 * interruptions to avoid a nonexistent interrupt to occur.
3087decaa55SMarcelo Roberto Jimenez 	 *
3097decaa55SMarcelo Roberto Jimenez 	 * In principle, the same problem would apply to bit 0, although it has
3107decaa55SMarcelo Roberto Jimenez 	 * never been observed to happen.
3117decaa55SMarcelo Roberto Jimenez 	 *
3127decaa55SMarcelo Roberto Jimenez 	 * This issue is addressed both here and in sa1100_rtc_interrupt().
3137decaa55SMarcelo Roberto Jimenez 	 * If the issue is not addressed here, in the times when the processor
3147decaa55SMarcelo Roberto Jimenez 	 * wakes up with the bit set there will be one spurious interrupt.
3157decaa55SMarcelo Roberto Jimenez 	 *
3167decaa55SMarcelo Roberto Jimenez 	 * The issue is also dealt with in sa1100_rtc_interrupt() to be on the
3177decaa55SMarcelo Roberto Jimenez 	 * safe side, once the condition that lead to this strange
3187decaa55SMarcelo Roberto Jimenez 	 * initialization is unknown and could in principle happen during
3197decaa55SMarcelo Roberto Jimenez 	 * normal processing.
3207decaa55SMarcelo Roberto Jimenez 	 *
3217decaa55SMarcelo Roberto Jimenez 	 * Notice that clearing bit 1 and 0 is accomplished by writting ONES to
3227decaa55SMarcelo Roberto Jimenez 	 * the corresponding bits in RTSR. */
323a0164a57SRussell King 	RTSR = RTSR_AL | RTSR_HZ;
3247decaa55SMarcelo Roberto Jimenez 
325e842f1c8SRichard Purdie 	return 0;
326e842f1c8SRichard Purdie }
327e842f1c8SRichard Purdie 
328e842f1c8SRichard Purdie static int sa1100_rtc_remove(struct platform_device *pdev)
329e842f1c8SRichard Purdie {
330a0164a57SRussell King 	struct rtc_device *rtc = platform_get_drvdata(pdev);
331e842f1c8SRichard Purdie 
332a0164a57SRussell King 	if (rtc)
333a0164a57SRussell King 		rtc_device_unregister(rtc);
334a0164a57SRussell King 
335e842f1c8SRichard Purdie 	return 0;
336e842f1c8SRichard Purdie }
337e842f1c8SRichard Purdie 
3386bc54e69SRussell King #ifdef CONFIG_PM
3395d027cd2SHaojian Zhuang static int sa1100_rtc_suspend(struct device *dev)
3406bc54e69SRussell King {
3415d027cd2SHaojian Zhuang 	if (device_may_wakeup(dev))
342a0164a57SRussell King 		enable_irq_wake(IRQ_RTCAlrm);
3436bc54e69SRussell King 	return 0;
3446bc54e69SRussell King }
3456bc54e69SRussell King 
3465d027cd2SHaojian Zhuang static int sa1100_rtc_resume(struct device *dev)
3476bc54e69SRussell King {
3485d027cd2SHaojian Zhuang 	if (device_may_wakeup(dev))
349a0164a57SRussell King 		disable_irq_wake(IRQ_RTCAlrm);
3506bc54e69SRussell King 	return 0;
3516bc54e69SRussell King }
3525d027cd2SHaojian Zhuang 
35347145210SAlexey Dobriyan static const struct dev_pm_ops sa1100_rtc_pm_ops = {
3545d027cd2SHaojian Zhuang 	.suspend	= sa1100_rtc_suspend,
3555d027cd2SHaojian Zhuang 	.resume		= sa1100_rtc_resume,
3565d027cd2SHaojian Zhuang };
3576bc54e69SRussell King #endif
3586bc54e69SRussell King 
359e842f1c8SRichard Purdie static struct platform_driver sa1100_rtc_driver = {
360e842f1c8SRichard Purdie 	.probe		= sa1100_rtc_probe,
361e842f1c8SRichard Purdie 	.remove		= sa1100_rtc_remove,
362e842f1c8SRichard Purdie 	.driver		= {
363e842f1c8SRichard Purdie 		.name	= "sa1100-rtc",
3645d027cd2SHaojian Zhuang #ifdef CONFIG_PM
3655d027cd2SHaojian Zhuang 		.pm	= &sa1100_rtc_pm_ops,
3665d027cd2SHaojian Zhuang #endif
367e842f1c8SRichard Purdie 	},
368e842f1c8SRichard Purdie };
369e842f1c8SRichard Purdie 
3700c4eae66SAxel Lin module_platform_driver(sa1100_rtc_driver);
371e842f1c8SRichard Purdie 
372e842f1c8SRichard Purdie MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>");
373e842f1c8SRichard Purdie MODULE_DESCRIPTION("SA11x0/PXA2xx Realtime Clock Driver (RTC)");
374e842f1c8SRichard Purdie MODULE_LICENSE("GPL");
375ad28a07bSKay Sievers MODULE_ALIAS("platform:sa1100-rtc");
376