diff options
Diffstat (limited to 'packages/linux')
15 files changed, 3915 insertions, 969 deletions
diff --git a/packages/linux/nas100d-kernel/2.6.15/00-memory-h-page-shift.patch b/packages/linux/nas100d-kernel/2.6.15/00-memory-h-page-shift.patch index 29b048e27a..4ec8f0475f 100644 --- a/packages/linux/nas100d-kernel/2.6.15/00-memory-h-page-shift.patch +++ b/packages/linux/nas100d-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/nas100d-kernel/2.6.15/01-i2c-ixp4xx.patch b/packages/linux/nas100d-kernel/2.6.15/01-i2c-ixp4xx.patch deleted file mode 100644 index 16426bdee6..0000000000 --- a/packages/linux/nas100d-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/nas100d-kernel/2.6.15/40-rtc-class.patch b/packages/linux/nas100d-kernel/2.6.15/40-rtc-class.patch new file mode 100644 index 0000000000..feea3f2f8b --- /dev/null +++ b/packages/linux/nas100d-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(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); +- + /* + * Calculate the next alarm time given the requested alarm time mask + * and the current time. +@@ -141,13 +58,13 @@ void rtc_next_alarm_time(struct rtc_time + next->tm_sec = alrm->tm_sec; + } + +-static inline int rtc_read_time(struct rtc_ops *ops, struct rtc_time *tm) ++static inline int rtc_arm_read_time(struct rtc_ops *ops, struct rtc_time *tm) + { + memset(tm, 0, sizeof(struct rtc_time)); + return ops->read_time(tm); + } + +-static inline int rtc_set_time(struct rtc_ops *ops, struct rtc_time *tm) ++static inline int rtc_arm_set_time(struct rtc_ops *ops, struct rtc_time *tm) + { + int ret; + +@@ -158,7 +75,7 @@ static inline int rtc_set_time(struct rt + return ret; + } + +-static inline int rtc_read_alarm(struct rtc_ops *ops, struct rtc_wkalrm *alrm) ++static inline int rtc_arm_read_alarm(struct rtc_ops *ops, struct rtc_wkalrm *alrm) + { + int ret = -EINVAL; + if (ops->read_alarm) { +@@ -168,7 +85,7 @@ static inline int rtc_read_alarm(struct + return ret; + } + +-static inline int rtc_set_alarm(struct rtc_ops *ops, struct rtc_wkalrm *alrm) ++static inline int rtc_arm_set_alarm(struct rtc_ops *ops, struct rtc_wkalrm *alrm) + { + int ret = -EINVAL; + if (ops->set_alarm) +@@ -256,7 +173,7 @@ static int rtc_ioctl(struct inode *inode + + switch (cmd) { + case RTC_ALM_READ: +- ret = rtc_read_alarm(ops, &alrm); ++ ret = rtc_arm_read_alarm(ops, &alrm); + if (ret) + break; + ret = copy_to_user(uarg, &alrm.time, sizeof(tm)); +@@ -278,11 +195,11 @@ static int rtc_ioctl(struct inode *inode + alrm.time.tm_wday = -1; + alrm.time.tm_yday = -1; + alrm.time.tm_isdst = -1; +- ret = rtc_set_alarm(ops, &alrm); ++ ret = rtc_arm_set_alarm(ops, &alrm); + break; + + case RTC_RD_TIME: +- ret = rtc_read_time(ops, &tm); ++ ret = rtc_arm_read_time(ops, &tm); + if (ret) + break; + ret = copy_to_user(uarg, &tm, sizeof(tm)); +@@ -300,7 +217,7 @@ static int rtc_ioctl(struct inode *inode + ret = -EFAULT; + break; + } +- ret = rtc_set_time(ops, &tm); ++ ret = rtc_arm_set_time(ops, &tm); + break; + + case RTC_EPOCH_SET: +@@ -331,11 +248,11 @@ static int rtc_ioctl(struct inode *inode + ret = -EFAULT; + break; + } +- ret = rtc_set_alarm(ops, &alrm); ++ ret = rtc_arm_set_alarm(ops, &alrm); + break; + + case RTC_WKALM_RD: +- ret = rtc_read_alarm(ops, &alrm); ++ ret = rtc_arm_read_alarm(ops, &alrm); + if (ret) + break; + ret = copy_to_user(uarg, &alrm, sizeof(alrm)); +@@ -425,7 +342,7 @@ static int rtc_read_proc(char *page, cha + struct rtc_time tm; + char *p = page; + +- if (rtc_read_time(ops, &tm) == 0) { ++ if (rtc_arm_read_time(ops, &tm) == 0) { + p += sprintf(p, + "rtc_time\t: %02d:%02d:%02d\n" + "rtc_date\t: %04d-%02d-%02d\n" +@@ -435,7 +352,7 @@ static int rtc_read_proc(char *page, cha + rtc_epoch); + } + +- if (rtc_read_alarm(ops, &alrm) == 0) { ++ if (rtc_arm_read_alarm(ops, &alrm) == 0) { + p += sprintf(p, "alrm_time\t: "); + if ((unsigned int)alrm.time.tm_hour <= 24) + p += sprintf(p, "%02d:", alrm.time.tm_hour); +--- linux-nslu2.orig/include/asm-arm/rtc.h 2006-01-04 01:27:04.000000000 +0100 ++++ linux-nslu2/include/asm-arm/rtc.h 2006-01-04 01:27:09.000000000 +0100 +@@ -25,9 +25,6 @@ struct rtc_ops { + int (*proc)(char *buf); + }; + +-void rtc_time_to_tm(unsigned long, struct rtc_time *); +-int rtc_tm_to_time(struct rtc_time *, unsigned long *); +-int rtc_valid_tm(struct rtc_time *); + void rtc_next_alarm_time(struct rtc_time *, struct rtc_time *, struct rtc_time *); + void rtc_update(unsigned long, unsigned long); + int register_rtc(struct rtc_ops *); +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ linux-nslu2/drivers/rtc/rtc-sysfs.c 2006-01-04 01:27:12.000000000 +0100 +@@ -0,0 +1,125 @@ ++/* ++ * RTC subsystem, sysfs interface ++ * ++ * Copyright (C) 2005 Tower Technologies ++ * Author: Alessandro Zummo <a.zummo@towertech.it> ++ * ++ * 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> ++ ++/* device attributes */ ++ ++static ssize_t rtc_sysfs_show_name(struct class_device *dev, char *buf) ++{ ++ return sprintf(buf, "%s\n", to_rtc_device(dev)->name); ++} ++static CLASS_DEVICE_ATTR(name, S_IRUGO, rtc_sysfs_show_name, NULL); ++ ++static ssize_t rtc_sysfs_show_date(struct class_device *dev, char *buf) ++{ ++ ssize_t retval = 0; |
