libdmx: Add fso-specs to DEPENDS
[openembedded.git] / recipes / linux / linux-gumstix-2.6.15 / rmk-2022-2-rtctime-sa110-pxa255-driver.patch
blob87f4ebdc38031dec87130056096136ea0629039e
1 Index: linux-2.6.15gum/drivers/char/sa1100-rtc.c
2 ===================================================================
3 --- /dev/null
4 +++ linux-2.6.15gum/drivers/char/sa1100-rtc.c
5 @@ -0,0 +1,297 @@
6 +/*
7 + * Real Time Clock interface for Linux on StrongARM SA1100
8 + *
9 + * Copyright (c) 2000 Nils Faerber
10 + *
11 + * Based on rtc.c by Paul Gortmaker
12 + * Date/time conversion routines taken from arch/arm/kernel/time.c
13 + * by Linus Torvalds and Russel King
14 + * and the GNU C Library
15 + * ( ... I love the GPL ... just take what you need! ;)
16 + *
17 + * This program is free software; you can redistribute it and/or
18 + * modify it under the terms of the GNU General Public License
19 + * as published by the Free Software Foundation; either version
20 + * 2 of the License, or (at your option) any later version.
21 + *
22 + * 1.00 2001-06-08 Nicolas Pitre <nico@cam.org>
23 + * - added periodic timer capability using OSMR1
24 + * - flag compatibility with other RTC chips
25 + * - permission checks for ioctls
26 + * - major cleanup, partial rewrite
27 + *
28 + * 0.03 2001-03-07 CIH <cih@coventive.com>
29 + * - Modify the bug setups RTC clock.
30 + *
31 + * 0.02 2001-02-27 Nils Faerber <nils@@kernelconcepts.de>
32 + * - removed mktime(), added alarm irq clear
33 + *
34 + * 0.01 2000-10-01 Nils Faerber <nils@@kernelconcepts.de>
35 + * - initial release
36 + */
38 +#include <linux/module.h>
39 +#include <linux/fs.h>
40 +#include <linux/miscdevice.h>
41 +#include <linux/string.h>
42 +#include <linux/init.h>
43 +#include <linux/poll.h>
44 +#include <linux/proc_fs.h>
45 +#include <linux/interrupt.h>
46 +#include <linux/rtc.h>
48 +#ifdef CONFIG_ARCH_PXA
49 +#include <asm/arch/pxa-regs.h>
50 +#endif
52 +#include <asm/bitops.h>
53 +#include <asm/hardware.h>
54 +#include <asm/irq.h>
55 +#include <asm/rtc.h>
57 +#define TIMER_FREQ 3686400
59 +#define RTC_DEF_DIVIDER 32768 - 1
60 +#define RTC_DEF_TRIM 0
62 +/* Those are the bits from a classic RTC we want to mimic */
63 +#define RTC_IRQF 0x80 /* any of the following 3 is active */
64 +#define RTC_PF 0x40
65 +#define RTC_AF 0x20
66 +#define RTC_UF 0x10
68 +static unsigned long rtc_freq = 1024;
69 +static struct rtc_time rtc_alarm = {
70 + .tm_year = 0,
71 + .tm_mon = 0,
72 + .tm_mday = 0,
73 + .tm_hour = 0,
74 + .tm_mon = 0,
75 + .tm_sec = 0,
76 +};
78 +extern spinlock_t rtc_lock;
80 +static int rtc_update_alarm(struct rtc_time *alrm)
82 + struct rtc_time alarm_tm, now_tm;
83 + unsigned long now, time;
84 + int ret;
86 + printk("Updating alarm\n");
87 + do {
88 + now = RCNR;
89 + rtc_time_to_tm(now, &now_tm);
90 + rtc_next_alarm_time(&alarm_tm, &now_tm, alrm);
91 + ret = rtc_tm_to_time(&alarm_tm, &time);
92 + if (ret != 0)
93 + break;
95 + RTSR = RTSR & (RTSR_HZE|RTSR_ALE|RTSR_AL);
96 + RTAR = time;
97 + } while (now != RCNR);
98 + printk("set RTAR to %lx, now is %lx\n", time, now);
100 + return ret;
103 +static irqreturn_t rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
105 + unsigned int rtsr;
106 + unsigned long events = 0;
108 + spin_lock(&rtc_lock);
110 + rtsr = RTSR;
111 + /* clear interrupt sources */
112 + RTSR = 0;
113 + RTSR = (RTSR_AL|RTSR_HZ) & (rtsr >> 2);
115 + printk(KERN_CRIT "rtc_interrupt: rtsr = %x\n", rtsr);
117 + /* clear alarm interrupt if it has occurred */
118 + if (rtsr & RTSR_AL) {
119 + printk(KERN_CRIT "ALARM INTRRUPT\n");
120 + rtsr &= ~RTSR_ALE;
122 + RTSR = rtsr & (RTSR_ALE|RTSR_HZE);
124 + /* update irq data & counter */
125 + if (rtsr & RTSR_AL)
126 + events |= (RTC_AF|RTC_IRQF);
127 + if (rtsr & RTSR_HZ)
128 + events |= (RTC_UF|RTC_IRQF);
130 + rtc_update(1, events);
132 + if (rtsr & RTSR_AL && rtc_periodic_alarm(&rtc_alarm))
133 + rtc_update_alarm(&rtc_alarm);
135 + spin_unlock(&rtc_lock);
137 + return IRQ_HANDLED;
141 +static int sa1100_rtc_open(void)
143 + int ret;
145 + ret = request_irq(IRQ_RTC1Hz, rtc_interrupt, SA_INTERRUPT, "rtc 1Hz", NULL);
146 + if (ret) {
147 + printk(KERN_ERR "rtc: IRQ%d already in use.\n", IRQ_RTC1Hz);
148 + goto fail_ui;
150 + ret = request_irq(IRQ_RTCAlrm, rtc_interrupt, SA_INTERRUPT, "rtc Alrm", NULL);
151 + if (ret) {
152 + printk(KERN_ERR "rtc: IRQ%d already in use.\n", IRQ_RTCAlrm);
153 + goto fail_ai;
155 + return 0;
157 + fail_ai:
158 + free_irq(IRQ_RTC1Hz, NULL);
159 + fail_ui:
160 + return ret;
163 +static void sa1100_rtc_release(void)
165 + spin_lock_irq (&rtc_lock);
166 + RTSR = 0;
167 + OIER &= ~OIER_E1;
168 + OSSR = OSSR_M1;
169 + spin_unlock_irq (&rtc_lock);
171 + free_irq(IRQ_RTCAlrm, NULL);
172 + free_irq(IRQ_RTC1Hz, NULL);
175 +static int sa1100_rtc_ioctl(unsigned int cmd, unsigned long arg)
177 + switch (cmd) {
178 + case RTC_AIE_OFF:
179 + spin_lock_irq(&rtc_lock);
180 + RTSR &= ~RTSR_ALE;
181 + spin_unlock_irq(&rtc_lock);
182 + return 0;
183 + case RTC_AIE_ON:
184 + spin_lock_irq(&rtc_lock);
185 + RTSR |= RTSR_ALE;
186 + spin_unlock_irq(&rtc_lock);
187 + return 0;
188 + case RTC_UIE_OFF:
189 + spin_lock_irq(&rtc_lock);
190 + RTSR &= ~RTSR_HZE;
191 + spin_unlock_irq(&rtc_lock);
192 + return 0;
193 + case RTC_UIE_ON:
194 + spin_lock_irq(&rtc_lock);
195 + RTSR |= RTSR_HZE;
196 + spin_unlock_irq(&rtc_lock);
197 + return 0;
199 + return -EINVAL;
202 +static void sa1100_rtc_read_time(struct rtc_time *tm)
204 + rtc_time_to_tm(RCNR, tm);
207 +static int sa1100_rtc_set_time(struct rtc_time *tm)
209 + unsigned long time;
210 + int ret;
212 + ret = rtc_tm_to_time(tm, &time);
213 + if (ret == 0)
214 + RCNR = time;
215 + return ret;
218 +static void sa1100_rtc_read_alarm(struct rtc_wkalrm *alrm)
220 + memcpy(&alrm->time, &rtc_alarm, sizeof(struct rtc_time));
221 + alrm->pending = RTSR & RTSR_AL ? 1 : 0;
224 +static int sa1100_rtc_set_alarm(struct rtc_wkalrm *alrm)
226 + int ret;
228 + printk("sa1100_rtc_set_alarm\n");
230 + spin_lock_irq(&rtc_lock);
231 + ret = rtc_update_alarm(&alrm->time);
232 + if (ret == 0) {
233 + memcpy(&rtc_alarm, &alrm->time, sizeof(struct rtc_time));
235 + if (alrm->enabled)
236 + enable_irq_wake(IRQ_RTCAlrm);
237 + else
238 + disable_irq_wake(IRQ_RTCAlrm);
240 + spin_unlock_irq(&rtc_lock);
242 + return ret;
245 +static int sa1100_rtc_proc(char *buf)
247 + char *p = buf;
249 + p += sprintf(p, "trim/divider\t: 0x%08x\n", RTTR);
250 + p += sprintf(p, "alarm_IRQ\t: %s\n", (RTSR & RTSR_ALE) ? "yes" : "no" );
251 + p += sprintf(p, "update_IRQ\t: %s\n", (RTSR & RTSR_HZE) ? "yes" : "no");
252 + p += sprintf(p, "periodic_IRQ\t: %s\n", (OIER & OIER_E1) ? "yes" : "no");
253 + p += sprintf(p, "periodic_freq\t: %ld\n", rtc_freq);
255 + return p - buf;
258 +static struct rtc_ops sa1100_rtc_ops = {
259 + .owner = THIS_MODULE,
260 + .open = sa1100_rtc_open,
261 + .release = sa1100_rtc_release,
262 + .ioctl = sa1100_rtc_ioctl,
264 + .read_time = sa1100_rtc_read_time,
265 + .set_time = sa1100_rtc_set_time,
266 + .read_alarm = sa1100_rtc_read_alarm,
267 + .set_alarm = sa1100_rtc_set_alarm,
268 + .proc = sa1100_rtc_proc,
271 +static int __init rtc_init(void)
273 + /*
274 + * According to the manual we should be able to let RTTR be zero
275 + * and then a default diviser for a 32.768KHz clock is used.
276 + * Apparently this doesn't work, at least for my SA1110 rev 5.
277 + * If the clock divider is uninitialized then reset it to the
278 + * default value to get the 1Hz clock.
279 + */
280 + if (RTTR == 0) {
281 + RTTR = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16);
282 + printk(KERN_WARNING "rtc: warning: initializing default clock divider/trim value\n");
283 + /* The current RTC value probably doesn't make sense either */
284 + RCNR = 0;
287 + register_rtc(&sa1100_rtc_ops);
289 + return 0;
292 +static void __exit rtc_exit(void)
294 + unregister_rtc(&sa1100_rtc_ops);
297 +module_init(rtc_init);
298 +module_exit(rtc_exit);
300 +MODULE_AUTHOR("Nils Faerber <nils@@kernelconcepts.de>");
301 +MODULE_DESCRIPTION("SA1100 Realtime Clock Driver (RTC)");
302 +MODULE_LICENSE("GPL"); /* so says the header */
303 Index: linux-2.6.15gum/drivers/char/Makefile
304 ===================================================================
305 --- linux-2.6.15gum.orig/drivers/char/Makefile
306 +++ linux-2.6.15gum/drivers/char/Makefile
307 @@ -60,6 +60,7 @@ obj-$(CONFIG_RTC) += rtc.o
308 obj-$(CONFIG_HPET) += hpet.o
309 obj-$(CONFIG_GEN_RTC) += genrtc.o
310 obj-$(CONFIG_EFI_RTC) += efirtc.o
311 +obj-$(CONFIG_SA1100_RTC) += sa1100-rtc.o
312 obj-$(CONFIG_SGI_DS1286) += ds1286.o
313 obj-$(CONFIG_SGI_IP27_RTC) += ip27-rtc.o
314 obj-$(CONFIG_DS1302) += ds1302.o
315 Index: linux-2.6.15gum/drivers/char/Kconfig
316 ===================================================================
317 --- linux-2.6.15gum.orig/drivers/char/Kconfig
318 +++ linux-2.6.15gum/drivers/char/Kconfig
319 @@ -790,6 +790,10 @@ config COBALT_LCD
320 This option enables support for the LCD display and buttons found
321 on Cobalt systems through a misc device.
323 +config SA1100_RTC
324 + tristate "SA1100/PXA2xx Real Time Clock"
325 + depends on ARCH_SA1100 || ARCH_PXA
327 config DTLK
328 tristate "Double Talk PC internal speech card support"
329 help