Linux-2.6.12-rc2

Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.

Let it rip!
diff --git a/arch/arm/mach-integrator/time.c b/arch/arm/mach-integrator/time.c
new file mode 100644
index 0000000..20729de
--- /dev/null
+++ b/arch/arm/mach-integrator/time.c
@@ -0,0 +1,213 @@
+/*
+ *  linux/arch/arm/mach-integrator/time.c
+ *
+ *  Copyright (C) 2000-2001 Deep Blue Solutions Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/time.h>
+#include <linux/mc146818rtc.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/device.h>
+
+#include <asm/hardware/amba.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/rtc.h>
+
+#include <asm/mach/time.h>
+
+#define RTC_DR		(0)
+#define RTC_MR		(4)
+#define RTC_STAT	(8)
+#define RTC_EOI		(8)
+#define RTC_LR		(12)
+#define RTC_CR		(16)
+#define RTC_CR_MIE	(1 << 0)
+
+extern int (*set_rtc)(void);
+static void __iomem *rtc_base;
+
+static int integrator_set_rtc(void)
+{
+	__raw_writel(xtime.tv_sec, rtc_base + RTC_LR);
+	return 1;
+}
+
+static void rtc_read_alarm(struct rtc_wkalrm *alrm)
+{
+	rtc_time_to_tm(readl(rtc_base + RTC_MR), &alrm->time);
+}
+
+static int rtc_set_alarm(struct rtc_wkalrm *alrm)
+{
+	unsigned long time;
+	int ret;
+
+	ret = rtc_tm_to_time(&alrm->time, &time);
+	if (ret == 0)
+		writel(time, rtc_base + RTC_MR);
+	return ret;
+}
+
+static void rtc_read_time(struct rtc_time *tm)
+{
+	rtc_time_to_tm(readl(rtc_base + RTC_DR), tm);
+}
+
+/*
+ * Set the RTC time.  Unfortunately, we can't accurately set
+ * the point at which the counter updates.
+ *
+ * Also, since RTC_LR is transferred to RTC_CR on next rising
+ * edge of the 1Hz clock, we must write the time one second
+ * in advance.
+ */
+static int rtc_set_time(struct rtc_time *tm)
+{
+	unsigned long time;
+	int ret;
+
+	ret = rtc_tm_to_time(tm, &time);
+	if (ret == 0)
+		writel(time + 1, rtc_base + RTC_LR);
+
+	return ret;
+}
+
+static struct rtc_ops rtc_ops = {
+	.owner		= THIS_MODULE,
+	.read_time	= rtc_read_time,
+	.set_time	= rtc_set_time,
+	.read_alarm	= rtc_read_alarm,
+	.set_alarm	= rtc_set_alarm,
+};
+
+static irqreturn_t rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	writel(0, rtc_base + RTC_EOI);
+	return IRQ_HANDLED;
+}
+
+static int rtc_probe(struct amba_device *dev, void *id)
+{
+	int ret;
+
+	if (rtc_base)
+		return -EBUSY;
+
+	ret = amba_request_regions(dev, NULL);
+	if (ret)
+		goto out;
+
+	rtc_base = ioremap(dev->res.start, SZ_4K);
+	if (!rtc_base) {
+		ret = -ENOMEM;
+		goto res_out;
+	}
+
+	__raw_writel(0, rtc_base + RTC_CR);
+	__raw_writel(0, rtc_base + RTC_EOI);
+
+	xtime.tv_sec = __raw_readl(rtc_base + RTC_DR);
+
+	ret = request_irq(dev->irq[0], rtc_interrupt, SA_INTERRUPT,
+			  "rtc-pl030", dev);
+	if (ret)
+		goto map_out;
+
+	ret = register_rtc(&rtc_ops);
+	if (ret)
+		goto irq_out;
+
+	set_rtc = integrator_set_rtc;
+	return 0;
+
+ irq_out:
+	free_irq(dev->irq[0], dev);
+ map_out:
+	iounmap(rtc_base);
+	rtc_base = NULL;
+ res_out:
+	amba_release_regions(dev);
+ out:
+	return ret;
+}
+
+static int rtc_remove(struct amba_device *dev)
+{
+	set_rtc = NULL;
+
+	writel(0, rtc_base + RTC_CR);
+
+	free_irq(dev->irq[0], dev);
+	unregister_rtc(&rtc_ops);
+
+	iounmap(rtc_base);
+	rtc_base = NULL;
+	amba_release_regions(dev);
+
+	return 0;
+}
+
+static struct timespec rtc_delta;
+
+static int rtc_suspend(struct amba_device *dev, pm_message_t state)
+{
+	struct timespec rtc;
+
+	rtc.tv_sec = readl(rtc_base + RTC_DR);
+	rtc.tv_nsec = 0;
+	save_time_delta(&rtc_delta, &rtc);
+
+	return 0;
+}
+
+static int rtc_resume(struct amba_device *dev)
+{
+	struct timespec rtc;
+
+	rtc.tv_sec = readl(rtc_base + RTC_DR);
+	rtc.tv_nsec = 0;
+	restore_time_delta(&rtc_delta, &rtc);
+
+	return 0;
+}
+
+static struct amba_id rtc_ids[] = {
+	{
+		.id	= 0x00041030,
+		.mask	= 0x000fffff,
+	},
+	{ 0, 0 },
+};
+
+static struct amba_driver rtc_driver = {
+	.drv		= {
+		.name	= "rtc-pl030",
+	},
+	.probe		= rtc_probe,
+	.remove		= rtc_remove,
+	.suspend	= rtc_suspend,
+	.resume		= rtc_resume,
+	.id_table	= rtc_ids,
+};
+
+static int __init integrator_rtc_init(void)
+{
+	return amba_driver_register(&rtc_driver);
+}
+
+static void __exit integrator_rtc_exit(void)
+{
+	amba_driver_unregister(&rtc_driver);
+}
+
+module_init(integrator_rtc_init);
+module_exit(integrator_rtc_exit);