summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/linux/nslu2-kernel/2.6.15/00-memory-h-page-shift.patch74
-rw-r--r--packages/linux/nslu2-kernel/2.6.15/01-i2c-ixp4xx.patch29
-rw-r--r--packages/linux/nslu2-kernel/2.6.15/35-x1205-fix-osc.patch204
-rw-r--r--packages/linux/nslu2-kernel/2.6.15/40-rtc-class.patch2719
-rw-r--r--packages/linux/nslu2-kernel/2.6.15/55-rtc-x1205.patch193
-rw-r--r--packages/linux/nslu2-kernel/2.6.15/80-nslu2-io.patch4
-rw-r--r--packages/linux/nslu2-kernel/2.6.15/81-nslu2-class-device-create.patch20
-rw-r--r--packages/linux/nslu2-kernel/2.6.15/85-timer.patch285
-rw-r--r--packages/linux/nslu2-kernel/2.6.15/defconfig29
-rw-r--r--packages/linux/nslu2-kernel/2.6/40-scsi-idle.patch44
-rw-r--r--packages/linux/nslu2-kernel_2.6.15.bb (renamed from packages/linux/nslu2-kernel_2.6.15-rc5.bb)11
11 files changed, 3341 insertions, 271 deletions
diff --git a/packages/linux/nslu2-kernel/2.6.15/00-memory-h-page-shift.patch b/packages/linux/nslu2-kernel/2.6.15/00-memory-h-page-shift.patch
index 29b048e27a..4ec8f0475f 100644
--- a/packages/linux/nslu2-kernel/2.6.15/00-memory-h-page-shift.patch
+++ b/packages/linux/nslu2-kernel/2.6.15/00-memory-h-page-shift.patch
@@ -1,10 +1,68 @@
---- linux-2.6.15/include/asm-arm/arch-ixp4xx/memory.h 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.15/include/asm-arm/arch-ixp4xx/memory.h 1970-01-01 00:00:00.000000000 +0000
-@@ -8,6 +8,7 @@
- #define __ASM_ARCH_MEMORY_H
+--- linux-2.6.15-rc7/include/asm-arm/arch-ixp4xx/memory.h~ 2005-12-30 05:18:27.000000000 +1030
++++ linux-2.6.15-rc7/include/asm-arm/arch-ixp4xx/memory.h 2005-12-30 05:36:04.000000000 +1030
+@@ -16,31 +16,10 @@
- #include <asm/sizes.h>
-+#include <asm/page.h>
+ #ifndef __ASSEMBLY__
- /*
- * Physical DRAM offset.
+-/*
+- * Only first 64MB of memory can be accessed via PCI.
+- * We use GFP_DMA to allocate safe buffers to do map/unmap.
+- * This is really ugly and we need a better way of specifying
+- * DMA-capable regions of memory.
+- */
+-static inline void __arch_adjust_zones(int node, unsigned long *zone_size,
+- unsigned long *zhole_size)
+-{
+- unsigned int sz = SZ_64M >> PAGE_SHIFT;
+-
+- /*
+- * Only adjust if > 64M on current system
+- */
+- if (node || (zone_size[0] <= sz))
+- return;
+-
+- zone_size[1] = zone_size[0] - sz;
+- zone_size[0] = sz;
+- zhole_size[1] = zhole_size[0];
+- zhole_size[0] = 0;
+-}
++void ixp4xx_adjust_zones(int node, unsigned long *size, unsigned long *holes);
+
+ #define arch_adjust_zones(node, size, holes) \
+- __arch_adjust_zones(node, size, holes)
++ ixp4xx_adjust_zones(node, size, holes)
+
+ #define ISA_DMA_THRESHOLD (SZ_64M - 1)
+
+--- linux-2.6.15-rc7/arch/arm/mach-ixp4xx/common-pci.c~ 2005-12-30 05:16:03.000000000 +1030
++++ linux-2.6.15-rc7/arch/arm/mach-ixp4xx/common-pci.c 2005-12-30 05:43:55.000000000 +1030
+@@ -341,6 +341,29 @@ int dma_needs_bounce(struct device *dev,
+ return (dev->bus == &pci_bus_type ) && ((dma_addr + size) >= SZ_64M);
+ }
+
++/*
++ * Only first 64MB of memory can be accessed via PCI.
++ * We use GFP_DMA to allocate safe buffers to do map/unmap.
++ * This is really ugly and we need a better way of specifying
++ * DMA-capable regions of memory.
++ */
++void __init ixp4xx_adjust_zones(int node, unsigned long *zone_size,
++ unsigned long *zhole_size)
++{
++ unsigned int sz = SZ_64M >> PAGE_SHIFT;
++
++ /*
++ * Only adjust if > 64M on current system
++ */
++ if (node || (zone_size[0] <= sz))
++ return;
++
++ zone_size[1] = zone_size[0] - sz;
++ zone_size[0] = sz;
++ zhole_size[1] = zhole_size[0];
++ zhole_size[0] = 0;
++}
++
+ void __init ixp4xx_pci_preinit(void)
+ {
+ unsigned long processor_id;
diff --git a/packages/linux/nslu2-kernel/2.6.15/01-i2c-ixp4xx.patch b/packages/linux/nslu2-kernel/2.6.15/01-i2c-ixp4xx.patch
deleted file mode 100644
index 16426bdee6..0000000000
--- a/packages/linux/nslu2-kernel/2.6.15/01-i2c-ixp4xx.patch
+++ /dev/null
@@ -1,29 +0,0 @@
---- linux-2.6.15/drivers/i2c/busses/i2c-ixp4xx.c 1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.15/drivers/i2c/busses/i2c-ixp4xx.c 1970-01-01 00:00:00.000000000 +0000
-@@ -35,7 +35,7 @@
-
- #include <asm/hardware.h> /* Pick up IXP4xx-specific bits */
-
--static struct device_driver ixp4xx_i2c_driver;
-+static struct platform_driver ixp4xx_i2c_driver;
-
- static inline int ixp4xx_scl_pin(void *data)
- {
-@@ -128,7 +128,7 @@ static int ixp4xx_i2c_probe(struct platf
- drv_data->algo_data.timeout = 100;
-
- drv_data->adapter.id = I2C_HW_B_IXP4XX;
-- strlcpy(drv_data->adapter.name, ixp4xx_i2c_driver.name,
-+ strlcpy(drv_data->adapter.name, ixp4xx_i2c_driver.driver.name,
- I2C_NAME_SIZE);
- drv_data->adapter.algo_data = &drv_data->algo_data;
-
-@@ -140,7 +140,7 @@ static int ixp4xx_i2c_probe(struct platf
- gpio_line_set(gpio->sda_pin, 0);
-
- if ((err = i2c_bit_add_bus(&drv_data->adapter) != 0)) {
-- printk(KERN_ERR "ERROR: Could not install %s\n", dev->bus_id);
-+ printk(KERN_ERR "ERROR: Could not install %s\n", ixp4xx_i2c_driver.driver.name);
-
- kfree(drv_data);
- return err;
diff --git a/packages/linux/nslu2-kernel/2.6.15/35-x1205-fix-osc.patch b/packages/linux/nslu2-kernel/2.6.15/35-x1205-fix-osc.patch
new file mode 100644
index 0000000000..44f2636c5c
--- /dev/null
+++ b/packages/linux/nslu2-kernel/2.6.15/35-x1205-fix-osc.patch
@@ -0,0 +1,204 @@
+ drivers/i2c/chips/x1205.c | 116 ++++++++++++++++++++++++++++++----------------
+ 1 file changed, 76 insertions(+), 40 deletions(-)
+
+--- linux-nslu2.orig/drivers/i2c/chips/x1205.c 2005-12-12 18:59:07.000000000 +0100
++++ linux-nslu2/drivers/i2c/chips/x1205.c 2005-12-13 21:31:32.000000000 +0100
+@@ -22,9 +22,9 @@
+ #include <linux/string.h>
+ #include <linux/bcd.h>
+ #include <linux/rtc.h>
++#include <linux/delay.h>
+
+-
+-#define DRV_VERSION "1.0.0"
++#define DRV_VERSION "1.0.1"
+
+ /* Addresses to scan: none. This chip is located at
+ * 0x6f and uses a two bytes register addressing.
+@@ -141,35 +141,19 @@ static int x1205_validate_tm(struct rtc_
+ * Epoch is initialized as 2000. Time is set to UTC.
+ */
+ static int x1205_get_datetime(struct i2c_client *client, struct rtc_time *tm,
+- u8 reg_base)
++ unsigned char reg_base)
+ {
+ unsigned char dt_addr[2] = { 0, reg_base };
+- static unsigned char sr_addr[2] = { 0, X1205_REG_SR };
+
+- unsigned char buf[8], sr;
++ unsigned char buf[8];
+
+ struct i2c_msg msgs[] = {
+- { client->addr, 0, 2, sr_addr }, /* setup read ptr */
+- { client->addr, I2C_M_RD, 1, &sr }, /* read status */
+ { client->addr, 0, 2, dt_addr }, /* setup read ptr */
+ { client->addr, I2C_M_RD, 8, buf }, /* read date */
+ };
+
+- /* read status register */
+- if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
+- dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
+- return -EIO;
+- }
+-
+- /* check for battery failure */
+- if (sr & X1205_SR_RTCF) {
+- dev_warn(&client->dev,
+- "Clock had a power failure, you must set the date.\n");
+- return -EINVAL;
+- }
+-
+ /* read date registers */
+- if ((i2c_transfer(client->adapter, &msgs[2], 2)) != 2) {
++ if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
+ dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
+ return -EIO;
+ }
+@@ -199,11 +183,28 @@ static int x1205_get_datetime(struct i2c
+ return 0;
+ }
+
++static int x1205_get_status(struct i2c_client *client, unsigned char *sr)
++{
++ static unsigned char sr_addr[2] = { 0, X1205_REG_SR };
++
++ struct i2c_msg msgs[] = {
++ { client->addr, 0, 2, sr_addr }, /* setup read ptr */
++ { client->addr, I2C_M_RD, 1, sr }, /* read status */
++ };
++
++ /* read status register */
++ if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) {
++ dev_err(&client->dev, "%s: read error\n", __FUNCTION__);
++ return -EIO;
++ }
++
++ return 0;
++}
++
+ static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm,
+ int datetoo, u8 reg_base)
+ {
+- int i, err, xfer;
+-
++ int i, xfer;
+ unsigned char buf[8];
+
+ static const unsigned char wel[3] = { 0, X1205_REG_SR,
+@@ -214,15 +215,10 @@ static int x1205_set_datetime(struct i2c
+
+ static const unsigned char diswe[3] = { 0, X1205_REG_SR, 0 };
+
+- /* check if all values in the tm struct are correct */
+- if ((err = x1205_validate_tm(tm)) < 0)
+- return err;
+-
+- dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, "
+- "mday=%d, mon=%d, year=%d, wday=%d\n",
++ dev_dbg(&client->dev,
++ "%s: secs=%d, mins=%d, hours=%d\n",
+ __FUNCTION__,
+- tm->tm_sec, tm->tm_min, tm->tm_hour,
+- tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
++ tm->tm_sec, tm->tm_min, tm->tm_hour);
+
+ buf[CCR_SEC] = BIN2BCD(tm->tm_sec);
+ buf[CCR_MIN] = BIN2BCD(tm->tm_min);
+@@ -232,6 +228,11 @@ static int x1205_set_datetime(struct i2c
+
+ /* should we also set the date? */
+ if (datetoo) {
++ dev_dbg(&client->dev,
++ "%s: mday=%d, mon=%d, year=%d, wday=%d\n",
++ __FUNCTION__,
++ tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
++
+ buf[CCR_MDAY] = BIN2BCD(tm->tm_mday);
+
+ /* month, 0 - 11 */
+@@ -280,6 +281,22 @@ static int x1205_set_datetime(struct i2c
+ return 0;
+ }
+
++static int x1205_fix_osc(struct i2c_client *client)
++{
++ int err;
++ struct rtc_time tm;
++
++ tm.tm_hour = 0;
++ tm.tm_min = 0;
++ tm.tm_sec = 0;
++
++ if ((err = x1205_set_datetime(client, &tm, 0, X1205_CCR_BASE)) < 0)
++ dev_err(&client->dev,
++ "unable to restart the clock\n");
++
++ return err;
++}
++
+ static int x1205_get_dtrim(struct i2c_client *client, int *trim)
+ {
+ unsigned char dtr;
+@@ -352,14 +369,17 @@ static int x1205_hctosys(struct i2c_clie
+
+ struct rtc_time tm;
+ struct timespec tv;
++ unsigned char sr;
+
++ if ((err = x1205_get_status(client, &sr)) < 0)
++ return err;
+
+- err = x1205_get_datetime(client, &tm, X1205_CCR_BASE);
+- if (err) {
+- dev_err(&client->dev,
+- "Unable to set the system clock\n");
++ /* Don't set if we had a power failure */
++ if (sr & X1205_SR_RTCF)
++ return -EINVAL;
++
++ if ((err = x1205_get_datetime(client, &tm, X1205_CCR_BASE)) < 0)
+ return err;
+- }
+
+ /* IMPORTANT: the RTC only stores whole seconds. It is arbitrary
+ * whether it stores the most close value or the value with partial
+@@ -506,9 +526,9 @@ static int x1205_attach(struct i2c_adapt
+
+ static int x1205_probe(struct i2c_adapter *adapter, int address, int kind)
+ {
+- struct i2c_client *client;
+-
+ int err = 0;
++ unsigned char sr;
++ struct i2c_client *client;
+
+ dev_dbg(&adapter->dev, "%s\n", __FUNCTION__);
+
+@@ -543,9 +563,25 @@ static int x1205_probe(struct i2c_adapte
+
+ dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n");
+
++ /* Check for power failures and eventualy enable the osc */
++ if ((err = x1205_get_status(client, &sr)) == 0) {
++ if (sr & X1205_SR_RTCF) {
++ dev_err(&client->dev,
++ "power failure detected, "
++ "please set the clock\n");
++ udelay(50);
++ x1205_fix_osc(client);
++ }
++ }
++ else
++ dev_err(&client->dev, "couldn't read status\n");
++
+ /* If requested, set the system time */
+- if (hctosys)
+- x1205_hctosys(client);
++ if (hctosys) {
++ if ((err = x1205_hctosys(client)) < 0)
++ dev_err(&client->dev,
++ "unable to set the system clock\n");
++ }
+
+ return 0;
+
diff --git a/packages/linux/nslu2-kernel/2.6.15/40-rtc-class.patch b/packages/linux/nslu2-kernel/2.6.15/40-rtc-class.patch
new file mode 100644
index 0000000000..feea3f2f8b
--- /dev/null
+++ b/packages/linux/nslu2-kernel/2.6.15/40-rtc-class.patch
@@ -0,0 +1,2719 @@
+--- linux-nslu2.orig/include/linux/rtc.h 2006-01-03 15:31:18.000000000 +0100
++++ linux-nslu2/include/linux/rtc.h 2006-01-03 15:34:24.000000000 +0100
+@@ -91,8 +91,81 @@ struct rtc_pll_info {
+ #define RTC_PLL_GET _IOR('p', 0x11, struct rtc_pll_info) /* Get PLL correction */
+ #define RTC_PLL_SET _IOW('p', 0x12, struct rtc_pll_info) /* Set PLL correction */
+
++/* interrupt flags */
++#define RTC_IRQF 0x80 /* any of the following is active */
++#define RTC_PF 0x40
++#define RTC_AF 0x20
++#define RTC_UF 0x10
++
+ #ifdef __KERNEL__
+
++#include <linux/device.h>
++#include <linux/seq_file.h>
++#include <linux/cdev.h>
++#include <linux/poll.h>
++
++struct rtc_class_ops {
++ int (*open)(struct device *);
++ void (*release)(struct device *);
++ int (*ioctl)(struct device *, unsigned int, unsigned long);
++ int (*read_time)(struct device *, struct rtc_time *);
++ int (*set_time)(struct device *, struct rtc_time *);
++ int (*read_alarm)(struct device *, struct rtc_wkalrm *);
++ int (*set_alarm)(struct device *, struct rtc_wkalrm *);
++ int (*proc)(struct device *, struct seq_file *);
++ int (*set_mmss)(struct device *, unsigned long secs);
++ int (*irq_set_state)(struct device *, int enabled);
++ int (*irq_set_freq)(struct device *, int freq);
++};
++
++#define RTC_DEVICE_NAME_SIZE 20
++struct rtc_task;
++
++struct rtc_device
++{
++ int id;
++ struct module *owner;
++ struct rw_semaphore lock;
++ struct class_device class_dev;
++ struct rtc_class_ops *ops;
++ char name[RTC_DEVICE_NAME_SIZE];
++
++ struct cdev char_dev;
++ struct semaphore char_sem;
++
++ unsigned long irq_data;
++ spinlock_t irq_lock;
++ wait_queue_head_t irq_queue;
++ struct fasync_struct *async_queue;
++
++ spinlock_t irq_task_lock;
++ struct rtc_task *irq_task;
++ int irq_freq;
++};
++#define to_rtc_device(d) container_of(d, struct rtc_device, class_dev)
++
++extern struct rtc_device *rtc_device_register(char *name,
++ struct device *dev,
++ struct rtc_class_ops *ops,
++ struct module *owner);
++extern void rtc_device_unregister(struct rtc_device *rdev);
++extern int rtc_interface_register(struct class_interface *intf);
++
++
++extern int rtc_month_days(unsigned int month, unsigned int year);
++extern int rtc_valid_tm(struct rtc_time *tm);
++extern int rtc_tm_to_time(struct rtc_time *tm, unsigned long *time);
++extern void rtc_time_to_tm(unsigned long time, struct rtc_time *tm);
++
++extern int rtc_read_time(struct class_device *class_dev, struct rtc_time *tm);
++extern int rtc_set_time(struct class_device *class_dev, struct rtc_time *tm);
++extern int rtc_read_alarm(struct class_device *class_dev,
++ struct rtc_wkalrm *alrm);
++extern int rtc_set_alarm(struct class_device *class_dev,
++ struct rtc_wkalrm *alrm);
++extern void rtc_update_irq(struct class_device *class_dev,
++ unsigned long num, unsigned long events);
++
+ typedef struct rtc_task {
+ void (*func)(void *private_data);
+ void *private_data;
+--- linux-nslu2.orig/drivers/Kconfig 2006-01-03 15:31:19.000000000 +0100
++++ linux-nslu2/drivers/Kconfig 2006-01-04 01:27:31.000000000 +0100
+@@ -66,4 +66,6 @@ source "drivers/infiniband/Kconfig"
+
+ source "drivers/sn/Kconfig"
+
++source "drivers/rtc/Kconfig"
++
+ endmenu
+--- linux-nslu2.orig/drivers/Makefile 2006-01-03 15:33:32.000000000 +0100
++++ linux-nslu2/drivers/Makefile 2006-01-04 01:27:31.000000000 +0100
+@@ -54,6 +54,7 @@ obj-$(CONFIG_USB_GADGET) += usb/gadget/
+ obj-$(CONFIG_GAMEPORT) += input/gameport/
+ obj-$(CONFIG_INPUT) += input/
+ obj-$(CONFIG_I2O) += message/
++obj-y += rtc/
+ obj-$(CONFIG_I2C) += i2c/
+ obj-$(CONFIG_W1) += w1/
+ obj-$(CONFIG_HWMON) += hwmon/
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ linux-nslu2/drivers/rtc/class.c 2006-01-03 15:45:19.000000000 +0100
+@@ -0,0 +1,141 @@
++/*
++ * RTC subsystem, base class
++ *
++ * Copyright (C) 2005 Tower Technologies
++ * Author: Alessandro Zummo <a.zummo@towertech.it>
++ *
++ * class skeleton from drivers/hwmon/hwmon.c
++ *
++ * 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; version 2 of the License.
++*/
++
++#include <linux/module.h>
++#include <linux/rtc.h>
++#include <linux/kdev_t.h>
++#include <linux/idr.h>
++
++static DEFINE_IDR(rtc_idr);
++static DECLARE_MUTEX(idr_lock);
++struct class *rtc_class;
++
++static void rtc_device_release(struct class_device *class_dev)
++{
++ struct rtc_device *rtc = to_rtc_device(class_dev);
++ down(&idr_lock);
++ idr_remove(&rtc_idr, rtc->id);
++ up(&idr_lock);
++ kfree(rtc);
++}
++
++/**
++ * rtc_device_register - register w/ RTC class
++ * @dev: the device to register
++ *
++ * rtc_device_unregister() must be called when the class device is no
++ * longer needed.
++ *
++ * Returns the pointer to the new struct class device.
++ */
++struct rtc_device *rtc_device_register(char *name, struct device *dev,
++ struct rtc_class_ops *ops,
++ struct module *owner)
++{
++ struct rtc_device *rtc;
++ int id, err;
++
++ if (idr_pre_get(&rtc_idr, GFP_KERNEL) == 0) {
++ err = -ENOMEM;
++ goto exit;
++ }
++
++
++ down(&idr_lock);
++ err = idr_get_new(&rtc_idr, NULL, &id);
++ up(&idr_lock);
++
++ if (err < 0)
++ goto exit;
++
++ id = id & MAX_ID_MASK;
++
++ if ((rtc = kzalloc(sizeof(struct rtc_device), GFP_KERNEL)) == NULL) {
++ err = -ENOMEM;
++ goto exit_idr;
++ }
++
++ rtc->id = id;
++ rtc->ops = ops;
++ rtc->owner = owner;
++ rtc->class_dev.dev = dev;
++ rtc->class_dev.class = rtc_class;
++ rtc->class_dev.release = rtc_device_release;
++
++ init_rwsem(&rtc->lock);
++ spin_lock_init(&rtc->irq_lock);
++ spin_lock_init(&rtc->irq_task_lock);
++
++ strlcpy(rtc->name, name, RTC_DEVICE_NAME_SIZE);
++ snprintf(rtc->class_dev.class_id, BUS_ID_SIZE, "rtc%d", id);
++
++ if ((err = class_device_register(&rtc->class_dev)))
++ goto exit_kfree;
++
++ dev_info(dev, "rtc core: registered %s as %s\n",
++ rtc->name, rtc->class_dev.class_id);
++
++ return rtc;
++
++exit_kfree:
++ kfree(rtc);
++
++exit_idr:
++ idr_remove(&rtc_idr, id);
++
++exit:
++ return ERR_PTR(err);
++}
++EXPORT_SYMBOL_GPL(rtc_device_register);
++
++
++/**
++ * rtc_device_unregister - removes the previously registered RTC class device
++ *
++ * @rtc: the RTC class device to destroy
++ */
++void rtc_device_unregister(struct rtc_device *rtc)
++{
++ down_write(&rtc->lock);
++ class_device_unregister(&rtc->class_dev);
++}
++EXPORT_SYMBOL_GPL(rtc_device_unregister);
++
++int rtc_interface_register(struct class_interface *intf)
++{
++ intf->class = rtc_class;
++ return class_interface_register(intf);
++}
++EXPORT_SYMBOL_GPL(rtc_interface_register);
++
++static int __init rtc_init(void)
++{
++ rtc_class = class_create(THIS_MODULE, "rtc");
++ if (IS_ERR(rtc_class)) {
++ printk(KERN_ERR "%s: couldn't create class\n", __FILE__);
++ return PTR_ERR(rtc_class);
++ }
++ return 0;
++}
++
++static void __exit rtc_exit(void)
++{
++ class_destroy(rtc_class);
++}
++
++module_init(rtc_init);
++module_exit(rtc_exit);
++
++MODULE_AUTHOR("Alessandro Zummo <a.zummo@towerteh.it>");
++MODULE_DESCRIPTION("RTC class support");
++MODULE_LICENSE("GPL");
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ linux-nslu2/drivers/rtc/Kconfig 2006-01-04 01:27:21.000000000 +0100
+@@ -0,0 +1,93 @@
++#
++# RTC class/drivers configuration
++#
++
++menu "Real Time Clock"
++
++config RTC_CLASS
++ tristate "RTC class"
++ depends on EXPERIMENTAL
++ default y
++ help
++ Generic RTC class support. If you say yes here, you will
++ be allowed to plug one or more RTCs to your system. You will
++ probably want to enable one of more of the interfaces below.
++
++ This driver can also be built as a module. If so, the module
++ will be called rtc-class.
++
++comment "RTC interfaces"
++ depends on RTC_CLASS
++
++config RTC_INTF_SYSFS
++ tristate "sysfs"
++ depends on RTC_CLASS && SYSFS
++ default RTC_CLASS
++ help
++ Say yes here if you want to use your RTC using the sysfs
++ interface, /sys/class/rtc/rtcX .
++
++ This driver can also be built as a module. If so, the module
++ will be called rtc-sysfs.
++
++config RTC_INTF_PROC
++ tristate "proc"
++ depends on RTC_CLASS && PROC_FS
++ default RTC_CLASS
++ help
++ Say yes here if you want to use your RTC using the proc
++ interface, /proc/driver/rtc .
++
++ This driver can also be built as a module. If so, the module
++ will be called rtc-proc.
++
++config RTC_INTF_DEV
++ tristate "dev"
++ depends on RTC_CLASS
++ default RTC_CLASS
++ help
++ Say yes here if you want to use your RTC using the dev
++ interface, /dev/rtc .
++
++ This driver can also be built as a module. If so, the module
++ will be called rtc-dev.
++
++comment "RTC drivers"
++ depends on RTC_CLASS
++
++config RTC_DRV_X1205
++ tristate "Xicor/Intersil X1205 RTC chip"
++ depends on RTC_CLASS && I2C
++ help
++ If you say yes here you get support for the
++ Xicor/Intersil X1205 RTC chip.
++
++ This driver can also be built as a module. If so, the module
++ will be called rtc-x1205.
++
++config RTC_DRV_DS1672
++ tristate "Dallas/Maxim DS1672"
++ depends on RTC_CLASS && I2C
++ help
++ If you say yes here you get support for the
++ Dallas/Maxim DS1672 timekeeping chip.
++
++ This driver can also be built as a module. If so, the module
++ will be called rtc-ds1672.
++
++config RTC_DRV_TEST
++ tristate "Test driver/device"
++ depends on RTC_CLASS
++ help
++ If you say yes here you get support for the
++ RTC test driver. It's a software RTC which can be
++ used to test the RTC subsystem APIs. It gets
++ the time from the system clock.
++ You want this driver only if you are doing development
++ on the RTC subsystem. Please read the source code
++ for further details.
++
++ This driver can also be built as a module. If so, the module
++ will be called rtc-test.
++
++endmenu
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ linux-nslu2/drivers/rtc/Makefile 2006-01-04 01:27:21.000000000 +0100
+@@ -0,0 +1,15 @@
++#
++# Makefile for RTC class/drivers.
++#
++
++obj-y += utils.o
++obj-$(CONFIG_RTC_CLASS) += rtc-core.o
++rtc-core-y := class.o interface.o
++obj-$(CONFIG_RTC_INTF_SYSFS) += rtc-sysfs.o
++obj-$(CONFIG_RTC_INTF_PROC) += rtc-proc.o
++obj-$(CONFIG_RTC_INTF_DEV) += rtc-dev.o
++
++obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o
++obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o
++obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o
++
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ linux-nslu2/drivers/rtc/interface.c 2006-01-03 15:34:24.000000000 +0100
+@@ -0,0 +1,189 @@
++/*
++ * RTC subsystem, interface functions
++ *
++ * Copyright (C) 2005 Tower Technologies
++ * Author: Alessandro Zummo <a.zummo@towertech.it>
++ *
++ * based on arch/arm/common/rtctime.c
++ *
++ * 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; version 2 of the License.
++*/
++
++#include <linux/rtc.h>
++
++extern struct class *rtc_class;
++
++int rtc_read_time(struct class_device *class_dev, struct rtc_time *tm)
++{
++ int err = -EINVAL;
++ struct rtc_class_ops *ops = to_rtc_device(class_dev)->ops;
++
++ if (ops->read_time) {
++ memset(tm, 0, sizeof(struct rtc_time));
++ err = ops->read_time(class_dev->dev, tm);
++ }
++ return err;
++}
++EXPORT_SYMBOL(rtc_read_time);
++
++int rtc_set_time(struct class_device *class_dev, struct rtc_time *tm)
++{
++ int err;
++ struct rtc_class_ops *ops = to_rtc_device(class_dev)->ops;
++
++ err = rtc_valid_tm(tm);
++ if (err == 0 && ops->set_time)
++ err = ops->set_time(class_dev->dev, tm);
++
++ return err;
++}
++EXPORT_SYMBOL(rtc_set_time);
++
++int rtc_read_alarm(struct class_device *class_dev, struct rtc_wkalrm *alarm)
++{
++ struct rtc_class_ops *ops = to_rtc_device(class_dev)->ops;
++ int err = -EINVAL;
++
++ if (ops->read_alarm) {
++ memset(alarm, 0, sizeof(struct rtc_wkalrm));
++ err = ops->read_alarm(class_dev->dev, alarm);
++ }
++ return err;
++}
++EXPORT_SYMBOL(rtc_read_alarm);
++
++int rtc_set_alarm(struct class_device *class_dev, struct rtc_wkalrm *alarm)
++{
++ int err = -EINVAL;
++ struct rtc_class_ops *ops = to_rtc_device(class_dev)->ops;
++
++ if (ops->set_alarm)
++ err = ops->set_alarm(class_dev->dev, alarm);
++ return err;
++}
++EXPORT_SYMBOL(rtc_set_alarm);
++
++void rtc_update_irq(struct class_device *class_dev,
++ unsigned long num, unsigned long events)
++{
++ struct rtc_device *rtc = to_rtc_device(class_dev);
++
++ spin_lock(&rtc->irq_lock);
++ rtc->irq_data = (rtc->irq_data + (num << 8)) | events;
++ spin_unlock(&rtc->irq_lock);
++
++ spin_lock(&rtc->irq_task_lock);
++ if (rtc->irq_task)
++ rtc->irq_task->func(rtc->irq_task->private_data);
++ spin_unlock(&rtc->irq_task_lock);
++
++ wake_up_interruptible(&rtc->irq_queue);
++ kill_fasync(&rtc->async_queue, SIGIO, POLL_IN);
++}
++EXPORT_SYMBOL(rtc_update_irq);
++
++struct class_device *rtc_open(char *name)
++{
++ struct class_device *class_dev = NULL,
++ *class_dev_tmp;
++
++ down(&rtc_class->sem);
++ list_for_each_entry(class_dev_tmp, &rtc_class->children, node) {
++ if (strncmp(class_dev_tmp->class_id, name, BUS_ID_SIZE) == 0) {
++ class_dev = class_dev_tmp;
++ break;
++ }
++ }
++ up(&rtc_class->sem);
++
++ return class_dev;
++}
++EXPORT_SYMBOL(rtc_open);
++
++void rtc_close(struct class_device *class_dev)
++{
++}
++EXPORT_SYMBOL(rtc_close);
++
++int rtc_irq_register(struct class_device *class_dev, struct rtc_task *task)
++{
++ int retval = -EBUSY;
++ struct rtc_device *rtc = to_rtc_device(class_dev);
++
++ if (task == NULL || task->func == NULL)
++ return -EINVAL;
++
++ spin_lock(&rtc->irq_task_lock);
++ if (rtc->irq_task == NULL) {
++ rtc->irq_task = task;
++ retval = 0;
++ }
++ spin_unlock(&rtc->irq_task_lock);
++
++ return retval;
++}
++EXPORT_SYMBOL(rtc_irq_register);
++
++void rtc_irq_unregister(struct class_device *class_dev, struct rtc_task *task)
++{
++ struct rtc_device *rtc = to_rtc_device(class_dev);
++
++ spin_lock(&rtc->irq_task_lock);
++ if (rtc->irq_task == task)
++ rtc->irq_task = NULL;
++ spin_unlock(&rtc->irq_task_lock);
++}
++EXPORT_SYMBOL(rtc_irq_unregister);
++
++int rtc_irq_set_state(struct class_device *class_dev, struct rtc_task *task, int enabled)
++{
++ int err = 0;
++ unsigned long flags;
++ struct rtc_device *rtc = to_rtc_device(class_dev);
++
++ spin_lock_irqsave(&rtc->irq_task_lock, flags);
++ if (rtc->irq_task != task)
++ err = -ENXIO;
++ spin_unlock_irqrestore(&rtc->irq_task_lock, flags);
++
++ if (err == 0)
++ err = rtc->ops->irq_set_state(class_dev->dev, enabled);
++
++ return err;
++}
++EXPORT_SYMBOL(rtc_irq_set_state);
++
++int rtc_irq_set_freq(struct class_device *class_dev, struct rtc_task *task, int freq)
++{
++ int err = 0, tmp = 0;
++ unsigned long flags;
++ struct rtc_device *rtc = to_rtc_device(class_dev);
++
++ /* allowed range is 2-8192 */
++ if (freq < 2 || freq > 8192)
++ return -EINVAL;
++
++/* if ((freq > rtc_max_user_freq) && (!capable(CAP_SYS_RESOURCE)))
++ return -EACCES;
++*/
++ /* check if freq is a power of 2 */
++ while (freq > (1 << tmp))
++ tmp++;
++
++ if (freq != (1 << tmp))
++ return -EINVAL;
++
++ spin_lock_irqsave(&rtc->irq_task_lock, flags);
++ if (rtc->irq_task != task)
++ err = -ENXIO;
++ spin_unlock_irqrestore(&rtc->irq_task_lock, flags);
++
++ if (err == 0) {
++ if ((err = rtc->ops->irq_set_freq(class_dev->dev, freq)) == 0)
++ rtc->irq_freq = freq;
++ }
++ return err;
++
++}
+--- /dev/null 1970-01-01 00:00:00.000000000 +0000
++++ linux-nslu2/drivers/rtc/utils.c 2006-01-03 15:34:24.000000000 +0100
+@@ -0,0 +1,97 @@
++/*
++ * RTC subsystem, utility functions
++ *
++ * Copyright (C) 2005 Tower Technologies
++ * Author: Alessandro Zummo <a.zummo@towertech.it>
++ *
++ * based on arch/arm/common/rtctime.c
++ *
++ * 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; version 2 of the License.
++*/
++
++#include <linux/rtc.h>
++
++static const unsigned char rtc_days_in_month[] = {
++ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
++};
++
++#define LEAPS_THRU_END_OF(y) ((y)/4 - (y)/100 + (y)/400)
++#define LEAP_YEAR(year) ((!(year % 4) && (year % 100)) || !(year % 400))
++
++int rtc_month_days(unsigned int month, unsigned int year)
++{
++ return rtc_days_in_month[month] + (LEAP_YEAR(year) && month == 1);
++}
++EXPORT_SYMBOL(rtc_month_days);
++
++/*
++ * Convert seconds since 01-01-1970 00:00:00 to Gregorian date.
++ */
++void rtc_time_to_tm(unsigned long time, struct rtc_time *tm)
++{
++ int days, month, year;
++
++ days = time / 86400;
++ time -= days * 86400;
++
++ tm->tm_wday = (days + 4) % 7;
++
++ year = 1970 + days / 365;
++ days -= (year - 1970) * 365
++ + LEAPS_THRU_END_OF(year - 1)
++ - LEAPS_THRU_END_OF(1970 - 1);
++ if (days < 0) {
++ year -= 1;
++ days += 365 + LEAP_YEAR(year);
++ }
++ tm->tm_year = year - 1900;
++ tm->tm_yday = days + 1;
++
++ for (month = 0; month < 11; month++) {
++ int newdays;
++
++ newdays = days - rtc_month_days(month, year);
++ if (newdays < 0)
++ break;
++ days = newdays;
++ }
++ tm->tm_mon = month;
++ tm->tm_mday = days + 1;
++
++ tm->tm_hour = time / 3600;
++ time -= tm->tm_hour * 3600;
++ tm->tm_min = time / 60;
++ tm->tm_sec = time - tm->tm_min * 60;
++}
++EXPORT_SYMBOL(rtc_time_to_tm);
++
++/*
++ * Does the rtc_time represent a valid date/time?
++ */
++int rtc_valid_tm(struct rtc_time *tm)
++{
++ if (tm->tm_year < 70 ||
++ tm->tm_mon >= 12 ||
++ tm->tm_mday < 1 ||
++ tm->tm_mday > rtc_month_days(tm->tm_mon, tm->tm_year + 1900) ||
++ tm->tm_hour >= 24 ||
++ tm->tm_min >= 60 ||
++ tm->tm_sec >= 60)
++ return -EINVAL;
++
++ return 0;
++}
++EXPORT_SYMBOL(rtc_valid_tm);
++
++/*
++ * Convert Gregorian date to seconds since 01-01-1970 00:00:00.
++ */
++int rtc_tm_to_time(struct rtc_time *tm, unsigned long *time)
++{
++ *time = mktime(tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
++ tm->tm_hour, tm->tm_min, tm->tm_sec);
++ return 0;
++}
++EXPORT_SYMBOL(rtc_tm_to_time);
+--- linux-nslu2.orig/arch/arm/Kconfig 2006-01-04 01:27:04.000000000 +0100
++++ linux-nslu2/arch/arm/Kconfig 2006-01-04 01:27:31.000000000 +0100
+@@ -750,6 +750,8 @@ source "drivers/usb/Kconfig"
+
+ source "drivers/mmc/Kconfig"
+
++source "drivers/rtc/Kconfig"
++
+ endmenu
+
+ source "fs/Kconfig"
+--- linux-nslu2.orig/arch/arm/common/rtctime.c 2006-01-04 01:27:04.000000000 +0100
++++ linux-nslu2/arch/arm/common/rtctime.c 2006-01-04 01:27:09.000000000 +0100
+@@ -40,89 +40,6 @@ static struct rtc_ops *rtc_ops;
+
+ #define rtc_epoch 1900UL
+
+-static const unsigned char days_in_month[] = {
+- 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+-};
+-
+-#define LEAPS_THRU_END_OF(y) ((y)/4 - (y)/100 + (y)/400)
+-#define LEAP_YEAR(year) ((!(year % 4) && (year % 100)) || !(year % 400))
+-
+-static int month_days(unsigned int month, unsigned int year)
+-{
+- return days_in_month[month] + (LEAP_YEAR(year) && month == 1);
+-}
+-
+-/*
+- * Convert seconds since 01-01-1970 00:00:00 to Gregorian date.
+- */
+-void rtc_time_to_tm(unsigned long time, struct rtc_time *tm)
+-{
+- int days, month, year;
+-
+- days = time / 86400;
+- time -= days * 86400;
+-
+- tm->tm_wday = (days + 4) % 7;
+-
+- year = 1970 + days / 365;
+- days -= (year - 1970) * 365
+- + LEAPS_THRU_END_OF(year - 1)
+- - LEAPS_THRU_END_OF(1970 - 1);
+- if (days < 0) {
+- year -= 1;
+- days += 365 + LEAP_YEAR(year);
+- }
+- tm->tm_year = year - 1900;
+- tm->tm_yday = days + 1;
+-
+- for (month = 0; month < 11; month++) {
+- int newdays;
+-
+- newdays = days - month_days(month, year);
+- if (newdays < 0)
+- break;
+- days = newdays;
+- }
+- tm->tm_mon = month;
+- tm->tm_mday = days + 1;
+-
+- tm->tm_hour = time / 3600;
+- time -= tm->tm_hour * 3600;
+- tm->tm_min = time / 60;
+- tm->tm_sec = time - tm->tm_min * 60;
+-}
+-EXPORT_SYMBOL(rtc_time_to_tm);
+-
+-/*
+- * Does the rtc_time represent a valid date/time?
+- */
+-int rtc_valid_tm(struct rtc_time *tm)
+-{
+- if (tm->tm_year < 70 ||
+- tm->tm_mon >= 12 ||
+- tm->tm_mday < 1 ||
+- tm->tm_mday > month_days(