From f143febe3e368614fe975e26e879084ddcff36b6 Mon Sep 17 00:00:00 2001 From: Rod Whitby Date: Tue, 21 Feb 2006 02:11:15 +0000 Subject: Added I2C support for the Loft --- .../ixp4xx-kernel/2.6.16/50-hwmon-ad741x.patch | 378 +++++++++++++++++++++ .../2.6.16/50-i2c-bus-ixp4xx-hwmon.patch | 14 + packages/linux/ixp4xx-kernel/2.6.16/defconfig | 3 +- 3 files changed, 394 insertions(+), 1 deletion(-) create mode 100644 packages/linux/ixp4xx-kernel/2.6.16/50-hwmon-ad741x.patch create mode 100644 packages/linux/ixp4xx-kernel/2.6.16/50-i2c-bus-ixp4xx-hwmon.patch (limited to 'packages/linux') diff --git a/packages/linux/ixp4xx-kernel/2.6.16/50-hwmon-ad741x.patch b/packages/linux/ixp4xx-kernel/2.6.16/50-hwmon-ad741x.patch new file mode 100644 index 0000000000..9d0a35b3fa --- /dev/null +++ b/packages/linux/ixp4xx-kernel/2.6.16/50-hwmon-ad741x.patch @@ -0,0 +1,378 @@ +--- + drivers/hwmon/Kconfig | 10 + + drivers/hwmon/Makefile | 1 + drivers/hwmon/ad741x.c | 340 +++++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 351 insertions(+) + +--- linux-ixp4xx.orig/drivers/hwmon/Makefile 2006-02-19 17:45:45.000000000 +0100 ++++ linux-ixp4xx/drivers/hwmon/Makefile 2006-02-19 17:46:12.000000000 +0100 +@@ -44,6 +44,7 @@ obj-$(CONFIG_SENSORS_VIA686A) += via686a + obj-$(CONFIG_SENSORS_VT8231) += vt8231.o + obj-$(CONFIG_SENSORS_W83627EHF) += w83627ehf.o + obj-$(CONFIG_SENSORS_W83L785TS) += w83l785ts.o ++obj-$(CONFIG_SENSORS_AD741X) += ad741x.o + + ifeq ($(CONFIG_HWMON_DEBUG_CHIP),y) + EXTRA_CFLAGS += -DDEBUG +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ linux-ixp4xx/drivers/hwmon/ad741x.c 2006-02-19 17:45:59.000000000 +0100 +@@ -0,0 +1,340 @@ ++/* ++ * An hwmon driver for the Analog Devices AD7417/18 ++ * Copyright 2006 Tower Technologies ++ * ++ * Author: Alessandro Zummo ++ * ++ * Based on lm75.c ++ * Copyright 1998-99 Frodo Looijaard ++ * ++ * 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; either version 2 of the License, or ++ * (at your option) any later version. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define DRV_VERSION "0.1" ++ ++/* straight from the datasheet */ ++#define AD741X_TEMP_MIN (-55000) ++#define AD741X_TEMP_MAX 125000 ++ ++/* Addresses to scan */ ++static unsigned short normal_i2c[] = { 0x28, 0x29, 0x2A, 0x2B, 0x2C, ++ 0x2D, 0x2E, 0x2F, I2C_CLIENT_END }; ++ ++/* Insmod parameters */ ++I2C_CLIENT_INSMOD; ++ ++/* AD741X registers */ ++#define AD741X_REG_TEMP 0x00 ++#define AD741X_REG_CONF 0x01 ++#define AD741X_REG_TEMP_HYST 0x02 ++#define AD741X_REG_TEMP_OS 0x03 ++#define AD741X_REG_ADC 0x04 ++#define AD741X_REG_CONF2 0x05 ++ ++#define AD741X_REG_ADC_CH(x) (x << 5) ++ ++#define AD741X_CH_TEMP AD741X_REG_ADC_CH(0) ++#define AD741X_CH_AIN1 AD741X_REG_ADC_CH(1) ++#define AD741X_CH_AIN2 AD741X_REG_ADC_CH(2) ++#define AD741X_CH_AIN3 AD741X_REG_ADC_CH(3) ++#define AD741X_CH_AIN4 AD741X_REG_ADC_CH(4) ++ ++struct ad741x_data { ++ struct i2c_client client; ++ struct class_device *class_dev; ++ struct mutex lock; ++ char valid; /* !=0 if following fields are valid */ ++ unsigned long last_updated; /* In jiffies */ ++ u16 temp_input; /* Register values */ ++ u16 temp_max; ++ u16 temp_hyst; ++ u16 in1; ++ u16 in2; ++ u16 in3; ++ u16 in4; ++}; ++ ++static int ad741x_attach_adapter(struct i2c_adapter *adapter); ++static int ad741x_detect(struct i2c_adapter *adapter, int address, int kind); ++static int ad741x_detach_client(struct i2c_client *client); ++ ++static struct i2c_driver ad741x_driver = { ++ .driver = { ++ .name = "ad741x", ++ }, ++ .attach_adapter = ad741x_attach_adapter, ++ .detach_client = ad741x_detach_client, ++}; ++ ++/* TEMP: 0.001C/bit (-55C to +125C) ++ * REG: (0.5C/bit, two's complement) << 7 ++ */ ++static inline u16 AD741X_TEMP_TO_REG(int temp) ++{ ++ int ntemp = SENSORS_LIMIT(temp, AD741X_TEMP_MIN, AD741X_TEMP_MAX); ++ ntemp += (ntemp < 0 ? -250 : 250); ++ return (u16)((ntemp / 500) << 7); ++} ++ ++static inline int AD741X_TEMP_FROM_REG(u16 reg) ++{ ++ /* use integer division instead of equivalent right shift to ++ * guarantee arithmetic shift and preserve the sign ++ */ ++ return ((s16)reg / 128) * 500; ++} ++ ++/* All registers are word-sized, except for the configuration registers. ++ * AD741X uses a high-byte first convention, which is exactly opposite to ++ * the usual practice. ++ */ ++static int ad741x_read(struct i2c_client *client, u8 reg) ++{ ++ if (reg == AD741X_REG_CONF || reg == AD741X_REG_CONF2) ++ return i2c_smbus_read_byte_data(client, reg); ++ else ++ return swab16(i2c_smbus_read_word_data(client, reg)); ++} ++ ++static int ad741x_write(struct i2c_client *client, u8 reg, u16 value) ++{ ++ if (reg == AD741X_REG_CONF || reg == AD741X_REG_CONF2) ++ return i2c_smbus_write_byte_data(client, reg, value); ++ else ++ return i2c_smbus_write_word_data(client, reg, swab16(value)); ++} ++ ++static void ad741x_init_client(struct i2c_client *client) ++{ ++ /* Enable if in shutdown mode */ ++ int reg = ad741x_read(client, AD741X_REG_CONF); ++ if (reg >= 0 && (reg & 0x01)) ++ ad741x_write(client, AD741X_REG_CONF, reg & 0xfe); ++} ++ ++static struct ad741x_data *ad741x_update_device(struct device *dev) ++{ ++ struct i2c_client *client = to_i2c_client(dev); ++ struct ad741x_data *data = i2c_get_clientdata(client); ++ ++ mutex_lock(&data->lock); ++ ++ if (time_after(jiffies, data->last_updated + HZ + HZ / 2) ++ || !data->valid) { ++ u8 cfg; ++ dev_dbg(&client->dev, "starting ad741x update\n"); ++ ++ data->temp_input = ad741x_read(client, AD741X_REG_TEMP); ++ data->temp_max = ad741x_read(client, AD741X_REG_TEMP_OS); ++ data->temp_hyst = ad741x_read(client, AD741X_REG_TEMP_HYST); ++ ++ /* read config register and clear channel bits */ ++ cfg = ad741x_read(client, AD741X_REG_CONF); ++ cfg &= 0x1F; ++ ++ ad741x_write(client, AD741X_REG_CONF, cfg | AD741X_CH_AIN1); ++ data->in1 = ad741x_read(client, AD741X_REG_ADC); ++ ++ ad741x_write(client, AD741X_REG_CONF, cfg | AD741X_CH_AIN2); ++ data->in2 = ad741x_read(client, AD741X_REG_ADC); ++ ++ ad741x_write(client, AD741X_REG_CONF, cfg | AD741X_CH_AIN3); ++ data->in3 = ad741x_read(client, AD741X_REG_ADC); ++ ++ ad741x_write(client, AD741X_REG_CONF, cfg | AD741X_CH_AIN4); ++ data->in4 = ad741x_read(client, AD741X_REG_ADC); ++ ++ /* restore old configuration value */ ++ ad741x_write(client, AD741X_REG_CONF, cfg); ++ ++ data->last_updated = jiffies; ++ data->valid = 1; ++ } ++ ++ mutex_unlock(&data->lock); ++ ++ return data; ++} ++ ++#define show(value) \ ++static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \ ++{ \ ++ struct ad741x_data *data = ad741x_update_device(dev); \ ++ return sprintf(buf, "%d\n", AD741X_TEMP_FROM_REG(data->value)); \ ++} ++show(temp_max); ++show(temp_hyst); ++show(temp_input); ++ ++#define show_adc(value) \ ++static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \ ++{ \ ++ struct ad741x_data *data = ad741x_update_device(dev); \ ++ return sprintf(buf, "%d\n", data->value >> 6); \ ++} ++ ++show_adc(in1); ++show_adc(in2); ++show_adc(in3); ++show_adc(in4); ++ ++#define set(value, reg) \ ++static ssize_t set_##value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) \ ++{ \ ++ struct i2c_client *client = to_i2c_client(dev); \ ++ struct ad741x_data *data = i2c_get_clientdata(client); \ ++ int temp = simple_strtoul(buf, NULL, 10); \ ++ \ ++ mutex_lock(&data->lock); \ ++ data->value = AD741X_TEMP_TO_REG(temp); \ ++ ad741x_write(client, reg, data->value); \ ++ mutex_unlock(&data->lock); \ ++ return count; \ ++} ++set(temp_max, AD741X_REG_TEMP_OS); ++set(temp_hyst, AD741X_REG_TEMP_HYST); ++ ++static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max, set_temp_max); ++static DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, show_temp_hyst, set_temp_hyst); ++static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_input, NULL); ++ ++static DEVICE_ATTR(in1, S_IRUGO, show_in1, NULL); ++static DEVICE_ATTR(in2, S_IRUGO, show_in2, NULL); ++static DEVICE_ATTR(in3, S_IRUGO, show_in3, NULL); ++static DEVICE_ATTR(in4, S_IRUGO, show_in4, NULL); ++ ++static int ad741x_attach_adapter(struct i2c_adapter *adapter) ++{ ++ if (!(adapter->class & I2C_CLASS_HWMON)) ++ return 0; ++ return i2c_probe(adapter, &addr_data, ad741x_detect); ++} ++ ++static int ad741x_detect(struct i2c_adapter *adapter, int address, int kind) ++{ ++ struct i2c_client *client; ++ struct ad741x_data *data; ++ int err = 0; ++ ++ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | ++ I2C_FUNC_SMBUS_WORD_DATA)) ++ goto exit; ++ ++ if (!(data = kzalloc(sizeof(struct ad741x_data), GFP_KERNEL))) { ++ err = -ENOMEM; ++ goto exit; ++ } ++ ++ client = &data->client; ++ client->addr = address; ++ client->adapter = adapter; ++ client->driver = &ad741x_driver; ++ client->flags = 0; ++ ++ i2c_set_clientdata(client, data); ++ ++ mutex_init(&data->lock); ++ ++ /* AD7418 has a curious behaviour on registers 6 and 7. They ++ * both always read 0xC071 and are not documented on the datasheet. ++ * We use them to detect the chip. ++ */ ++ if (kind < 0) { ++ int reg; ++ ++ reg = i2c_smbus_read_word_data(client, 0x06); ++ if (reg != 0xC071) { ++ dev_dbg(&adapter->dev, "failed detection at %d: %x\n", 6, reg); ++ err = -ENODEV; ++ goto exit_free; ++ } ++ ++ reg = i2c_smbus_read_word_data(client, 0x07); ++ if (reg != 0xC071) { ++ dev_dbg(&adapter->dev, "failed detection at %d: %x\n", 7, reg); ++ err = -ENODEV; ++ goto exit_free; ++ } ++ ++ reg = i2c_smbus_read_byte_data(client, AD741X_REG_CONF2); ++ ++ /* bits 0-5 must be at 0 */ ++ if (reg & 0x3F) { ++ dev_dbg(&adapter->dev, "failed detection at %d: %x\n", ++ AD741X_REG_CONF2, reg); ++ err = -ENODEV; ++ goto exit_free; ++ } ++ } ++ ++ strlcpy(client->name, ad741x_driver.driver.name, I2C_NAME_SIZE); ++ ++ if ((err = i2c_attach_client(client))) ++ goto exit_free; ++ ++ dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); ++ ++ /* Initialize the AD741X chip */ ++ ad741x_init_client(client); ++ ++ /* Register sysfs hooks */ ++ data->class_dev = hwmon_device_register(&client->dev); ++ if (IS_ERR(data->class_dev)) { ++ err = PTR_ERR(data->class_dev); ++ goto exit_detach; ++ } ++ ++ device_create_file(&client->dev, &dev_attr_temp1_max); ++ device_create_file(&client->dev, &dev_attr_temp1_max_hyst); ++ device_create_file(&client->dev, &dev_attr_temp1_input); ++ device_create_file(&client->dev, &dev_attr_in1); ++ device_create_file(&client->dev, &dev_attr_in2); ++ device_create_file(&client->dev, &dev_attr_in3); ++ device_create_file(&client->dev, &dev_attr_in4); ++ ++ return 0; ++ ++exit_detach: ++ i2c_detach_client(client); ++exit_free: ++ kfree(data); ++exit: ++ return err; ++} ++ ++static int ad741x_detach_client(struct i2c_client *client) ++{ ++ struct ad741x_data *data = i2c_get_clientdata(client); ++ hwmon_device_unregister(data->class_dev); ++ i2c_detach_client(client); ++ kfree(data); ++ return 0; ++} ++ ++static int __init ad741x_init(void) ++{ ++ return i2c_add_driver(&ad741x_driver); ++} ++ ++static void __exit ad741x_exit(void) ++{ ++ i2c_del_driver(&ad741x_driver); ++} ++ ++MODULE_AUTHOR("Alessandro Zummo "); ++MODULE_DESCRIPTION("AD741X driver"); ++MODULE_LICENSE("GPL"); ++MODULE_VERSION(DRV_VERSION); ++ ++module_init(ad741x_init); ++module_exit(ad741x_exit); +--- linux-ixp4xx.orig/drivers/hwmon/Kconfig 2006-02-19 17:45:45.000000000 +0100 ++++ linux-ixp4xx/drivers/hwmon/Kconfig 2006-02-19 17:47:07.000000000 +0100 +@@ -433,6 +433,16 @@ config SENSORS_W83627EHF + This driver can also be built as a module. If so, the module + will be called w83627ehf. + ++config SENSORS_AD741X ++ tristate "Analog Devices AD7417/18" ++ depends on HWMON && I2C && EXPERIMENTAL ++ help ++ If you say yes here you get support for the Analog Devices AD7417 ++ and AD7418 chips. ++ ++ This driver can also be built as a module. If so, the module ++ will be called ad741x. ++ + config SENSORS_HDAPS + tristate "IBM Hard Drive Active Protection System (hdaps)" + depends on HWMON && INPUT && X86 diff --git a/packages/linux/ixp4xx-kernel/2.6.16/50-i2c-bus-ixp4xx-hwmon.patch b/packages/linux/ixp4xx-kernel/2.6.16/50-i2c-bus-ixp4xx-hwmon.patch new file mode 100644 index 0000000000..d7fb8e55dc --- /dev/null +++ b/packages/linux/ixp4xx-kernel/2.6.16/50-i2c-bus-ixp4xx-hwmon.patch @@ -0,0 +1,14 @@ +--- + drivers/i2c/busses/i2c-ixp4xx.c | 1 + + 1 file changed, 1 insertion(+) + +--- linux-ixp4xx.orig/drivers/i2c/busses/i2c-ixp4xx.c 2006-02-11 15:18:29.000000000 +0100 ++++ linux-ixp4xx/drivers/i2c/busses/i2c-ixp4xx.c 2006-02-18 16:20:12.000000000 +0100 +@@ -126,6 +126,7 @@ static int ixp4xx_i2c_probe(struct platf + drv_data->algo_data.timeout = 100; + + drv_data->adapter.id = I2C_HW_B_IXP4XX; ++ drv_data->adapter.class = I2C_CLASS_HWMON; + strlcpy(drv_data->adapter.name, plat_dev->dev.driver->name, + I2C_NAME_SIZE); + drv_data->adapter.algo_data = &drv_data->algo_data; diff --git a/packages/linux/ixp4xx-kernel/2.6.16/defconfig b/packages/linux/ixp4xx-kernel/2.6.16/defconfig index 0862199528..472a692a32 100644 --- a/packages/linux/ixp4xx-kernel/2.6.16/defconfig +++ b/packages/linux/ixp4xx-kernel/2.6.16/defconfig @@ -1469,6 +1469,7 @@ CONFIG_RTC_INTF_DEV=y CONFIG_RTC_DRV_X1205=y CONFIG_RTC_DRV_DS1672=y CONFIG_RTC_DRV_PCF8563=y +CONFIG_RTC_DRV_RS5C372=y # CONFIG_RTC_DRV_TEST is not set # @@ -1596,7 +1597,7 @@ CONFIG_CIFS_XATTR=y CONFIG_CIFS_POSIX=y # CONFIG_CIFS_EXPERIMENTAL is not set # CONFIG_NCP_FS is not set -CONFIG_CODA_FS=m +# CONFIG_CODA_FS is not set # CONFIG_AFS_FS is not set # CONFIG_9P_FS is not set -- cgit v1.2.3 From 3c492671634a9273b4e79b8c4b1f03039002d47e Mon Sep 17 00:00:00 2001 From: Rod Whitby Date: Tue, 21 Feb 2006 02:14:09 +0000 Subject: ixp4xx-kernel: Updated for 2.6.16-rc4 from CVS patch repo --- .../2.6.16/06-remove-extraversion.patch | 2 +- .../linux/ixp4xx-kernel/2.6.16/40-rtc-class.patch | 2076 ++- .../linux/ixp4xx-kernel/2.6.16/91-maclist.patch | 405 +- .../ixp4xx-kernel/2.6.16/94-nas100d-setup.patch | 2 +- .../2.6.16/951-ixp4xx-leds-cpu-activity.patch | 57 +- .../ixp4xx-kernel/2.6.16/96-nas100d-leds.patch | 3 +- .../ixp4xx-kernel/2.6.16/97-ds101-buttons.patch | 122 + .../ixp4xx-kernel/2.6.16/97-ds101-includes.patch | 139 +- .../linux/ixp4xx-kernel/2.6.16/97-ds101-misc.patch | 36 +- .../linux/ixp4xx-kernel/2.6.16/97-ds101-pci.patch | 13 +- .../ixp4xx-kernel/2.6.16/97-ds101-power.patch | 75 - .../ixp4xx-kernel/2.6.16/97-ds101-setup.patch | 360 +- .../linux/ixp4xx-kernel/2.6.16/leds-class.patch | 2069 +++ .../ixp4xx-kernel/2.6.16/patch-2.6.16-rc4-ide1 | 18260 +++++++++++++++++++ packages/linux/ixp4xx-kernel_2.6.16-rc2.bb | 64 - packages/linux/ixp4xx-kernel_2.6.16-rc4.bb | 54 + 16 files changed, 22911 insertions(+), 826 deletions(-) create mode 100644 packages/linux/ixp4xx-kernel/2.6.16/97-ds101-buttons.patch delete mode 100644 packages/linux/ixp4xx-kernel/2.6.16/97-ds101-power.patch create mode 100644 packages/linux/ixp4xx-kernel/2.6.16/leds-class.patch create mode 100644 packages/linux/ixp4xx-kernel/2.6.16/patch-2.6.16-rc4-ide1 delete mode 100644 packages/linux/ixp4xx-kernel_2.6.16-rc2.bb create mode 100644 packages/linux/ixp4xx-kernel_2.6.16-rc4.bb (limited to 'packages/linux') diff --git a/packages/linux/ixp4xx-kernel/2.6.16/06-remove-extraversion.patch b/packages/linux/ixp4xx-kernel/2.6.16/06-remove-extraversion.patch index 65aba13703..8f2ce831b2 100644 --- a/packages/linux/ixp4xx-kernel/2.6.16/06-remove-extraversion.patch +++ b/packages/linux/ixp4xx-kernel/2.6.16/06-remove-extraversion.patch @@ -4,7 +4,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 16 --EXTRAVERSION =-rc2 +-EXTRAVERSION =-rc4 +EXTRAVERSION = NAME=Sliding Snow Leopard diff --git a/packages/linux/ixp4xx-kernel/2.6.16/40-rtc-class.patch b/packages/linux/ixp4xx-kernel/2.6.16/40-rtc-class.patch index 38359a1bc0..3cc84b2a9b 100644 --- a/packages/linux/ixp4xx-kernel/2.6.16/40-rtc-class.patch +++ b/packages/linux/ixp4xx-kernel/2.6.16/40-rtc-class.patch @@ -1,6 +1,6 @@ ---- linux-nslu2.orig/include/linux/rtc.h 2006-02-06 20:37:43.000000000 +0100 -+++ linux-nslu2/include/linux/rtc.h 2006-02-06 21:41:39.000000000 +0100 -@@ -93,8 +93,91 @@ struct rtc_pll_info { +--- linux-rtc.orig/include/linux/rtc.h 2006-02-19 23:33:10.000000000 +0100 ++++ linux-rtc/include/linux/rtc.h 2006-02-19 23:33:15.000000000 +0100 +@@ -93,8 +93,97 @@ 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 */ @@ -16,6 +16,7 @@ +#include +#include +#include ++#include + +struct rtc_class_ops { + int (*open)(struct device *); @@ -29,6 +30,7 @@ + int (*set_mmss)(struct device *, unsigned long secs); + int (*irq_set_state)(struct device *, int enabled); + int (*irq_set_freq)(struct device *, int freq); ++ int (*read_callback)(struct device *, int data); +}; + +#define RTC_DEVICE_NAME_SIZE 20 @@ -36,23 +38,25 @@ + +struct rtc_device +{ -+ int id; -+ struct module *owner; + struct class_device class_dev; -+ struct semaphore ops_lock; -+ struct rtc_class_ops *ops; ++ struct module *owner; ++ ++ int id; + char name[RTC_DEVICE_NAME_SIZE]; + ++ struct rtc_class_ops *ops; ++ struct mutex ops_lock; ++ + struct cdev char_dev; -+ struct semaphore char_sem; ++ struct mutex char_lock; + + 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; ++ spinlock_t irq_task_lock; + int irq_freq; +}; +#define to_rtc_device(d) container_of(d, struct rtc_device, class_dev) @@ -71,15 +75,17 @@ + +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_set_mmss(struct class_device *class_dev, unsigned long secs); +extern int rtc_read_alarm(struct class_device *class_dev, -+ struct rtc_wkalrm *alrm); ++ 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); + -+extern struct class_device *rtc_open(char *name); -+extern void rtc_close(struct class_device *class_dev); ++extern struct class_device *rtc_class_open(char *name); ++extern void rtc_class_close(struct class_device *class_dev); ++ +extern int rtc_irq_register(struct class_device *class_dev, + struct rtc_task *task); +extern void rtc_irq_unregister(struct class_device *class_dev, @@ -92,8 +98,8 @@ typedef struct rtc_task { void (*func)(void *private_data); void *private_data; ---- linux-nslu2.orig/drivers/Kconfig 2006-02-06 20:37:14.000000000 +0100 -+++ linux-nslu2/drivers/Kconfig 2006-02-06 21:11:33.000000000 +0100 +--- linux-rtc.orig/drivers/Kconfig 2006-02-19 23:33:10.000000000 +0100 ++++ linux-rtc/drivers/Kconfig 2006-02-19 23:33:15.000000000 +0100 @@ -70,4 +70,6 @@ source "drivers/sn/Kconfig" source "drivers/edac/Kconfig" @@ -101,8 +107,8 @@ +source "drivers/rtc/Kconfig" + endmenu ---- linux-nslu2.orig/drivers/Makefile 2006-02-06 20:37:14.000000000 +0100 -+++ linux-nslu2/drivers/Makefile 2006-02-06 21:11:33.000000000 +0100 +--- linux-rtc.orig/drivers/Makefile 2006-02-19 23:33:10.000000000 +0100 ++++ linux-rtc/drivers/Makefile 2006-02-19 23:33:15.000000000 +0100 @@ -56,6 +56,7 @@ obj-$(CONFIG_USB_GADGET) += usb/gadget/ obj-$(CONFIG_GAMEPORT) += input/gameport/ obj-$(CONFIG_INPUT) += input/ @@ -112,7 +118,7 @@ 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-02-06 21:41:25.000000000 +0100 ++++ linux-rtc/drivers/rtc/class.c 2006-02-19 23:33:15.000000000 +0100 @@ -0,0 +1,143 @@ +/* + * RTC subsystem, base class @@ -133,15 +139,15 @@ +#include + +static DEFINE_IDR(rtc_idr); -+static DECLARE_MUTEX(idr_lock); ++static DEFINE_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); ++ mutex_lock(&idr_lock); + idr_remove(&rtc_idr, rtc->id); -+ up(&idr_lock); ++ mutex_unlock(&idr_lock); + kfree(rtc); +} + @@ -167,9 +173,9 @@ + } + + -+ down(&idr_lock); ++ mutex_lock(&idr_lock); + err = idr_get_new(&rtc_idr, NULL, &id); -+ up(&idr_lock); ++ mutex_unlock(&idr_lock); + + if (err < 0) + goto exit; @@ -188,7 +194,7 @@ + rtc->class_dev.class = rtc_class; + rtc->class_dev.release = rtc_device_release; + -+ init_MUTEX(&rtc->ops_lock); ++ mutex_init(&rtc->ops_lock); + spin_lock_init(&rtc->irq_lock); + spin_lock_init(&rtc->irq_task_lock); + @@ -222,9 +228,9 @@ + */ +void rtc_device_unregister(struct rtc_device *rtc) +{ -+ down(&rtc->ops_lock); ++ mutex_lock(&rtc->ops_lock); + rtc->ops = NULL; -+ up(&rtc->ops_lock); ++ mutex_unlock(&rtc->ops_lock); + class_device_unregister(&rtc->class_dev); +} +EXPORT_SYMBOL_GPL(rtc_device_unregister); @@ -258,8 +264,8 @@ +MODULE_DESCRIPTION("RTC class support"); +MODULE_LICENSE("GPL"); --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-nslu2/drivers/rtc/Kconfig 2006-02-06 23:58:32.000000000 +0100 -@@ -0,0 +1,121 @@ ++++ linux-rtc/drivers/rtc/Kconfig 2006-02-21 00:36:43.000000000 +0100 +@@ -0,0 +1,131 @@ +# +# RTC class/drivers configuration +# @@ -365,6 +371,16 @@ + This driver can also be built as a module. If so, the module + will be called rtc-pcf8563. + ++config RTC_DRV_RS5C372 ++ tristate "Ricoh RS5C372A/B" ++ depends on RTC_CLASS && I2C ++ help ++ If you say yes here you get support for the ++ Ricoh RS5C372A and RS5C372B RTC chips. ++ ++ This driver can also be built as a module. If so, the module ++ will be called rtc-rs5c372. ++ +config RTC_DRV_TEST + tristate "Test driver/device" + depends on RTC_CLASS @@ -382,8 +398,8 @@ + +endmenu --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-nslu2/drivers/rtc/Makefile 2006-02-06 23:58:32.000000000 +0100 -@@ -0,0 +1,17 @@ ++++ linux-rtc/drivers/rtc/Makefile 2006-02-21 00:36:43.000000000 +0100 +@@ -0,0 +1,18 @@ +# +# Makefile for RTC class/drivers. +# @@ -400,10 +416,11 @@ +obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o +obj-$(CONFIG_RTC_DRV_DS1672) += rtc-ds1672.o +obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o ++obj-$(CONFIG_RTC_DRV_RS5C372) += rtc-rs5c372.o + --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-nslu2/drivers/rtc/interface.c 2006-02-07 01:32:10.000000000 +0100 -@@ -0,0 +1,232 @@ ++++ linux-rtc/drivers/rtc/interface.c 2006-02-19 23:33:15.000000000 +0100 +@@ -0,0 +1,274 @@ +/* + * RTC subsystem, interface functions + * @@ -426,7 +443,7 @@ + int err; + struct rtc_device *rtc = to_rtc_device(class_dev); + -+ if ((err = down_interruptible(&rtc->ops_lock))) ++ if ((err = mutex_lock_interruptible(&rtc->ops_lock))) + return err; + + if (!rtc->ops) @@ -438,7 +455,7 @@ + err = rtc->ops->read_time(class_dev->dev, tm); + } + -+ up(&rtc->ops_lock); ++ mutex_unlock(&rtc->ops_lock); + return err; +} +EXPORT_SYMBOL(rtc_read_time); @@ -451,7 +468,7 @@ + if ((err = rtc_valid_tm(tm)) != 0) + return err; + -+ if ((err = down_interruptible(&rtc->ops_lock))) ++ if ((err = mutex_lock_interruptible(&rtc->ops_lock))) + return err; + + if (!rtc->ops) @@ -461,17 +478,59 @@ + else + err = rtc->ops->set_time(class_dev->dev, tm); + -+ up(&rtc->ops_lock); ++ mutex_unlock(&rtc->ops_lock); + return err; +} +EXPORT_SYMBOL(rtc_set_time); + ++int rtc_set_mmss(struct class_device *class_dev, unsigned long secs) ++{ ++ int err; ++ struct rtc_device *rtc = to_rtc_device(class_dev); ++ ++ if ((err = mutex_lock_interruptible(&rtc->ops_lock))) ++ return err; ++ ++ if (!rtc->ops) ++ err = -ENODEV; ++ else if (!rtc->ops->set_mmss) { ++ if (rtc->ops->read_time && rtc->ops->set_time) { ++ struct rtc_time new, old; ++ ++ new.tm_sec = secs % 60; ++ secs /= 60; ++ new.tm_min = secs % 60; ++ secs /= 60; ++ new.tm_hour = secs % 24; ++ ++ /* ++ * avoid writing when we're going to change the day ++ * of the month. We will retry in the next minute. ++ * This basically means that if the RTC must not drift ++ * by more than 1 minute in 11 minutes. ++ */ ++ if (!((old.tm_hour == 23 && old.tm_min == 59) || ++ (new.tm_hour == 23 && new.tm_min == 59))) ++ err = rtc->ops->set_time(class_dev->dev, &new); ++ } ++ else ++ err = -EINVAL; ++ } ++ else ++ err = rtc->ops->set_mmss(class_dev->dev, secs); ++ ++ mutex_unlock(&rtc->ops_lock); ++ ++ return err; ++} ++EXPORT_SYMBOL(rtc_set_mmss); ++ +int rtc_read_alarm(struct class_device *class_dev, struct rtc_wkalrm *alarm) +{ + int err; + struct rtc_device *rtc = to_rtc_device(class_dev); + -+ if ((err = down_interruptible(&rtc->ops_lock))) ++ if ((err = mutex_lock_interruptible(&rtc->ops_lock))) + return err; + + if (rtc->ops == NULL) @@ -483,7 +542,7 @@ + err = rtc->ops->read_alarm(class_dev->dev, alarm); + } + -+ up(&rtc->ops_lock); ++ mutex_unlock(&rtc->ops_lock); + return err; +} +EXPORT_SYMBOL(rtc_read_alarm); @@ -493,7 +552,7 @@ + int err; + struct rtc_device *rtc = to_rtc_device(class_dev); + -+ if ((err = down_interruptible(&rtc->ops_lock))) ++ if ((err = mutex_lock_interruptible(&rtc->ops_lock))) + return err; + + if (!rtc->ops) @@ -503,7 +562,7 @@ + else + err = rtc->ops->set_alarm(class_dev->dev, alarm); + -+ up(&rtc->ops_lock); ++ mutex_unlock(&rtc->ops_lock); + return err; +} +EXPORT_SYMBOL(rtc_set_alarm); @@ -527,7 +586,7 @@ +} +EXPORT_SYMBOL(rtc_update_irq); + -+struct class_device *rtc_open(char *name) ++struct class_device *rtc_class_open(char *name) +{ + struct class_device *class_dev = NULL, + *class_dev_tmp; @@ -548,13 +607,13 @@ + + return class_dev; +} -+EXPORT_SYMBOL(rtc_open); ++EXPORT_SYMBOL(rtc_class_open); + -+void rtc_close(struct class_device *class_dev) ++void rtc_class_close(struct class_device *class_dev) +{ + module_put(to_rtc_device(class_dev)->owner); +} -+EXPORT_SYMBOL(rtc_close); ++EXPORT_SYMBOL(rtc_class_close); + +int rtc_irq_register(struct class_device *class_dev, struct rtc_task *task) +{ @@ -637,7 +696,7 @@ + +} --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-nslu2/drivers/rtc/utils.c 2006-02-06 21:11:33.000000000 +0100 ++++ linux-rtc/drivers/rtc/utils.c 2006-02-19 23:33:15.000000000 +0100 @@ -0,0 +1,97 @@ +/* + * RTC subsystem, utility functions @@ -737,8 +796,8 @@ +} +EXPORT_SYMBOL(rtc_tm_to_time); --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-nslu2/drivers/rtc/hctosys.c 2006-02-06 21:11:33.000000000 +0100 -@@ -0,0 +1,62 @@ ++++ linux-rtc/drivers/rtc/hctosys.c 2006-02-21 00:34:57.000000000 +0100 +@@ -0,0 +1,67 @@ +/* + * RTC subsystem, initialize system time on startup + * @@ -766,12 +825,17 @@ +static int __init rtc_hctosys(void) +{ + int err; -+ struct class_device *class_dev = rtc_open(CONFIG_RTC_HCTOSYS_DEVICE); ++ struct rtc_time tm; ++ struct class_device *class_dev = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE); + -+ if (class_dev) { -+ struct rtc_time tm; ++ if (class_dev == NULL) { ++ printk("%s: unable to open rtc device (%s)\n", ++ __FILE__, CONFIG_RTC_HCTOSYS_DEVICE); ++ return -ENODEV; ++ } + -+ if ((err = rtc_read_time(class_dev, &tm)) == 0) { ++ if ((err = rtc_read_time(class_dev, &tm)) == 0) { ++ if (rtc_valid_tm(&tm) == 0) { + struct timespec tv; + + tv.tv_nsec = NSEC_PER_SEC >> 1; @@ -789,21 +853,21 @@ + } + else + dev_err(class_dev->dev, -+ "unable to set the system clock\n"); -+ -+ rtc_close(class_dev); ++ "hctosys: invalid date/time\n"); + } + else -+ printk("%s: unable to open rtc device (%s)\n", -+ __FILE__, CONFIG_RTC_HCTOSYS_DEVICE); ++ dev_err(class_dev->dev, ++ "hctosys: unable to read the hardware clock\n"); ++ ++ rtc_class_close(class_dev); + + return 0; +} + +late_initcall(rtc_hctosys); ---- linux-nslu2.orig/arch/arm/Kconfig 2006-02-06 23:52:28.000000000 +0100 -+++ linux-nslu2/arch/arm/Kconfig 2006-02-06 23:53:25.000000000 +0100 -@@ -784,6 +784,8 @@ source "drivers/usb/Kconfig" +--- linux-rtc.orig/arch/arm/Kconfig 2006-02-21 00:34:27.000000000 +0100 ++++ linux-rtc/arch/arm/Kconfig 2006-02-21 00:36:42.000000000 +0100 +@@ -817,6 +817,8 @@ source "drivers/usb/Kconfig" source "drivers/mmc/Kconfig" @@ -812,8 +876,8 @@ endmenu source "fs/Kconfig" ---- linux-nslu2.orig/arch/arm/common/rtctime.c 2006-02-06 23:52:28.000000000 +0100 -+++ linux-nslu2/arch/arm/common/rtctime.c 2006-02-06 23:53:25.000000000 +0100 +--- linux-rtc.orig/arch/arm/common/rtctime.c 2006-02-21 00:34:27.000000000 +0100 ++++ linux-rtc/arch/arm/common/rtctime.c 2006-02-21 00:36:42.000000000 +0100 @@ -42,89 +42,6 @@ static struct rtc_ops *rtc_ops; #define rtc_epoch 1900UL @@ -984,24 +1048,6 @@ if (ret) break; ret = copy_to_user(uarg, &alrm, sizeof(alrm)); -@@ -353,7 +270,7 @@ static int rtc_ioctl(struct inode *inode - return ret; - } - --static int rtc_open(struct inode *inode, struct file *file) -+static int rtc_arm_open(struct inode *inode, struct file *file) - { - int ret; - -@@ -408,7 +325,7 @@ static struct file_operations rtc_fops = - .read = rtc_read, - .poll = rtc_poll, - .ioctl = rtc_ioctl, -- .open = rtc_open, -+ .open = rtc_arm_open, - .release = rtc_release, - .fasync = rtc_fasync, - }; @@ -427,7 +344,7 @@ static int rtc_read_proc(char *page, cha struct rtc_time tm; char *p = page; @@ -1020,8 +1066,8 @@ 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-02-06 23:52:28.000000000 +0100 -+++ linux-nslu2/include/asm-arm/rtc.h 2006-02-06 23:53:25.000000000 +0100 +--- linux-rtc.orig/include/asm-arm/rtc.h 2006-02-21 00:34:27.000000000 +0100 ++++ linux-rtc/include/asm-arm/rtc.h 2006-02-21 00:36:42.000000000 +0100 @@ -25,9 +25,6 @@ struct rtc_ops { int (*proc)(char *buf); }; @@ -1032,9 +1078,1269 @@ 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 *); +--- linux-rtc.orig/drivers/char/Kconfig 2006-02-21 00:34:27.000000000 +0100 ++++ linux-rtc/drivers/char/Kconfig 2006-02-21 00:36:42.000000000 +0100 +@@ -695,7 +695,7 @@ config NVRAM + + config RTC + tristate "Enhanced Real Time Clock Support" +- depends on !PPC32 && !PARISC && !IA64 && !M68K && (!SPARC || PCI) && !FRV ++ depends on !PPC32 && !PARISC && !IA64 && !M68K && (!SPARC || PCI) && !FRV && !ARM + ---help--- + If you say Y here and create a character special file /dev/rtc with + major number 10 and minor number 135 using mknod ("man mknod"), you +--- linux-rtc.orig/drivers/i2c/chips/x1205.c 2006-02-21 00:34:27.000000000 +0100 ++++ /dev/null 1970-01-01 00:00:00.000000000 +0000 +@@ -1,698 +0,0 @@ +-/* +- * x1205.c - An i2c driver for the Xicor X1205 RTC +- * Copyright 2004 Karen Spearel +- * Copyright 2005 Alessandro Zummo +- * +- * please send all reports to: +- * kas11 at tampabay dot rr dot com +- * a dot zummo at towertech dot it +- * +- * based on the other drivers in this same directory. +- * +- * 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; either version 2 of the License, or +- * (at your option) any later version. +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +- +-#define DRV_VERSION "0.9.9" +- +-/* Addresses to scan: none. This chip is located at +- * 0x6f and uses a two bytes register addressing. +- * Two bytes need to be written to read a single register, +- * while most other chips just require one and take the second +- * one as the data to be written. To prevent corrupting +- * unknown chips, the user must explicitely set the probe parameter. +- */ +- +-static unsigned short normal_i2c[] = { I2C_CLIENT_END }; +- +-/* Insmod parameters */ +-I2C_CLIENT_INSMOD; +-I2C_CLIENT_MODULE_PARM(hctosys, +- "Set the system time from the hardware clock upon initialization"); +- +-/* offsets into CCR area */ +- +-#define CCR_SEC 0 +-#define CCR_MIN 1 +-#define CCR_HOUR 2 +-#define CCR_MDAY 3 +-#define CCR_MONTH 4 +-#define CCR_YEAR 5 +-#define CCR_WDAY 6 +-#define CCR_Y2K 7 +- +-#define X1205_REG_SR 0x3F /* status register */ +-#define X1205_REG_Y2K 0x37 +-#define X1205_REG_DW 0x36 +-#define X1205_REG_YR 0x35 +-#define X1205_REG_MO 0x34 +-#define X1205_REG_DT 0x33 +-#define X1205_REG_HR 0x32 +-#define X1205_REG_MN 0x31 +-#define X1205_REG_SC 0x30 +-#define X1205_REG_DTR 0x13 +-#define X1205_REG_ATR 0x12 +-#define X1205_REG_INT 0x11 +-#define X1205_REG_0 0x10 +-#define X1205_REG_Y2K1 0x0F +-#define X1205_REG_DWA1 0x0E +-#define X1205_REG_YRA1 0x0D +-#define X1205_REG_MOA1 0x0C +-#define X1205_REG_DTA1 0x0B +-#define X1205_REG_HRA1 0x0A +-#define X1205_REG_MNA1 0x09 +-#define X1205_REG_SCA1 0x08 +-#define X1205_REG_Y2K0 0x07 +-#define X1205_REG_DWA0 0x06 +-#define X1205_REG_YRA0 0x05 +-#define X1205_REG_MOA0 0x04 +-#define X1205_REG_DTA0 0x03 +-#define X1205_REG_HRA0 0x02 +-#define X1205_REG_MNA0 0x01 +-#define X1205_REG_SCA0 0x00 +- +-#define X1205_CCR_BASE 0x30 /* Base address of CCR */ +-#define X1205_ALM0_BASE 0x00 /* Base address of ALARM0 */ +- +-#define X1205_SR_RTCF 0x01 /* Clock failure */ +-#define X1205_SR_WEL 0x02 /* Write Enable Latch */ +-#define X1205_SR_RWEL 0x04 /* Register Write Enable */ +- +-#define X1205_DTR_DTR0 0x01 +-#define X1205_DTR_DTR1 0x02 +-#define X1205_DTR_DTR2 0x04 +- +-#define X1205_HR_MIL 0x80 /* Set in ccr.hour for 24 hr mode */ +- +-/* Prototypes */ +-static int x1205_attach(struct i2c_adapter *adapter); +-static int x1205_detach(struct i2c_client *client); +-static int x1205_probe(struct i2c_adapter *adapter, int address, int kind); +-static int x1205_command(struct i2c_client *client, unsigned int cmd, +- void *arg); +- +-static struct i2c_driver x1205_driver = { +- .driver = { +- .name = "x1205", +- }, +- .attach_adapter = &x1205_attach, +- .detach_client = &x1205_detach, +-}; +- +-struct x1205_data { +- struct i2c_client client; +- struct list_head list; +- unsigned int epoch; +-}; +- +-static const unsigned char days_in_mo[] = +- { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; +- +-static LIST_HEAD(x1205_clients); +- +-/* Workaround until the I2C subsytem will allow to send +- * commands to a specific client. This function will send the command +- * to the first client. +- */ +-int x1205_do_command(unsigned int cmd, void *arg) +-{ +- struct list_head *walk; +- struct list_head *tmp; +- struct x1205_data *data; +- +- list_for_each_safe(walk, tmp, &x1205_clients) { +- data = list_entry(walk, struct x1205_data, list); +- return x1205_command(&data->client, cmd, arg); +- } +- +- return -ENODEV; +-} +- +-#define is_leap(year) \ +- ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0)) +- +-/* make sure the rtc_time values are in bounds */ +-static int x1205_validate_tm(struct rtc_time *tm) +-{ +- int year = tm->tm_year + 1900; +- +- if ((tm->tm_year < 70) || (tm->tm_year > 255)) +- return -EINVAL; +- +- if ((tm->tm_mon > 11) || (tm->tm_mday == 0)) +- return -EINVAL; +- +- if (tm->tm_mday > days_in_mo[tm->tm_mon] +- + ((tm->tm_mon == 1) && is_leap(year))) +- return -EINVAL; +- +- if ((tm->tm_hour >= 24) || (tm->tm_min >= 60) || (tm->tm_sec >= 60)) +- return -EINVAL; +- +- return 0; +-} +- +-/* +- * In the routines that deal directly with the x1205 hardware, we use +- * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch +- * 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 dt_addr[2] = { 0, reg_base }; +- static unsigned char sr_addr[2] = { 0, X1205_REG_SR }; +- +- unsigned char buf[8], sr; +- +- 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 */ +- }; +- +- struct x1205_data *data = i2c_get_clientdata(client); +- +- /* 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) { +- dev_err(&client->dev, "%s: read error\n", __FUNCTION__); +- return -EIO; +- } +- +- dev_dbg(&client->dev, +- "%s: raw read data - sec=%02x, min=%02x, hr=%02x, " +- "mday=%02x, mon=%02x, year=%02x, wday=%02x, y2k=%02x\n", +- __FUNCTION__, +- buf[0], buf[1], buf[2], buf[3], +- buf[4], buf[5], buf[6], buf[7]); +- +- tm->tm_sec = BCD2BIN(buf[CCR_SEC]); +- tm->tm_min = BCD2BIN(buf[CCR_MIN]); +- tm->tm_hour = BCD2BIN(buf[CCR_HOUR] & 0x3F); /* hr is 0-23 */ +- tm->tm_mday = BCD2BIN(buf[CCR_MDAY]); +- tm->tm_mon = BCD2BIN(buf[CCR_MONTH]); +- data->epoch = BCD2BIN(buf[CCR_Y2K]) * 100; +- tm->tm_year = BCD2BIN(buf[CCR_YEAR]) + data->epoch - 1900; +- tm->tm_wday = buf[CCR_WDAY]; +- +- dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, " +- "mday=%d, mon=%d, year=%d, wday=%d\n", +- __FUNCTION__, +- tm->tm_sec, tm->tm_min, tm->tm_hour, +- tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); +- +- return 0; +-} +- +-static int x1205_set_datetime(struct i2c_client *client, struct rtc_time *tm, +- int datetoo, u8 reg_base) +-{ +- int i, err, xfer; +- +- unsigned char buf[8]; +- +- static const unsigned char wel[3] = { 0, X1205_REG_SR, +- X1205_SR_WEL }; +- +- static const unsigned char rwel[3] = { 0, X1205_REG_SR, +- X1205_SR_WEL | X1205_SR_RWEL }; +- +- static const unsigned char diswe[3] = { 0, X1205_REG_SR, 0 }; +- +- struct x1205_data *data = i2c_get_clientdata(client); +- +- /* 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", +- __FUNCTION__, +- tm->tm_sec, tm->tm_min, tm->tm_hour, +- tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); +- +- buf[CCR_SEC] = BIN2BCD(tm->tm_sec); +- buf[CCR_MIN] = BIN2BCD(tm->tm_min); +- +- /* set hour and 24hr bit */ +- buf[CCR_HOUR] = BIN2BCD(tm->tm_hour) | X1205_HR_MIL; +- +- /* should we also set the date? */ +- if (datetoo) { +- buf[CCR_MDAY] = BIN2BCD(tm->tm_mday); +- +- /* month, 0 - 11 */ +- buf[CCR_MONTH] = BIN2BCD(tm->tm_mon); +- +- /* year, since 1900 */ +- buf[CCR_YEAR] = BIN2BCD(tm->tm_year + 1900 - data->epoch); +- buf[CCR_WDAY] = tm->tm_wday & 0x07; +- buf[CCR_Y2K] = BIN2BCD(data->epoch / 100); +- } +- +- /* this sequence is required to unlock the chip */ +- xfer = i2c_master_send(client, wel, 3); +- if (xfer != 3) { +- dev_err(&client->dev, "%s: wel - %d\n", __FUNCTION__, xfer); +- return -EIO; +- } +- +- xfer = i2c_master_send(client, rwel, 3); +- if (xfer != 3) { +- dev_err(&client->dev, "%s: rwel - %d\n", __FUNCTION__, xfer); +- return -EIO; +- } +- +- /* write register's data */ +- for (i = 0; i < (datetoo ? 8 : 3); i++) { +- unsigned char rdata[3] = { 0, reg_base + i, buf[i] }; +- +- xfer = i2c_master_send(client, rdata, 3); +- if (xfer != 3) { +- dev_err(&client->dev, +- "%s: xfer=%d addr=%02x, data=%02x\n", +- __FUNCTION__, +- xfer, rdata[1], rdata[2]); +- return -EIO; +- } +- }; +- +- /* disable further writes */ +- xfer = i2c_master_send(client, diswe, 3); +- if (xfer != 3) { +- dev_err(&client->dev, "%s: diswe - %d\n", __FUNCTION__, xfer); +- return -EIO; +- } +- +- return 0; +-} +- +-static int x1205_get_dtrim(struct i2c_client *client, int *trim) +-{ +- unsigned char dtr; +- static unsigned char dtr_addr[2] = { 0, X1205_REG_DTR }; +- +- struct i2c_msg msgs[] = { +- { client->addr, 0, 2, dtr_addr }, /* setup read ptr */ +- { client->addr, I2C_M_RD, 1, &dtr }, /* read dtr */ +- }; +- +- /* read dtr register */ +- if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) { +- dev_err(&client->dev, "%s: read error\n", __FUNCTION__); +- return -EIO; +- } +- +- dev_dbg(&client->dev, "%s: raw dtr=%x\n", __FUNCTION__, dtr); +- +- *trim = 0; +- +- if (dtr & X1205_DTR_DTR0) +- *trim += 20; +- +- if (dtr & X1205_DTR_DTR1) +- *trim += 10; +- +- if (dtr & X1205_DTR_DTR2) +- *trim = -*trim; +- +- return 0; +-} +- +-static int x1205_get_atrim(struct i2c_client *client, int *trim) +-{ +- s8 atr; +- static unsigned char atr_addr[2] = { 0, X1205_REG_ATR }; +- +- struct i2c_msg msgs[] = { +- { client->addr, 0, 2, atr_addr }, /* setup read ptr */ +- { client->addr, I2C_M_RD, 1, &atr }, /* read atr */ +- }; +- +- /* read atr register */ +- if ((i2c_transfer(client->adapter, &msgs[0], 2)) != 2) { +- dev_err(&client->dev, "%s: read error\n", __FUNCTION__); +- return -EIO; +- } +- +- dev_dbg(&client->dev, "%s: raw atr=%x\n", __FUNCTION__, atr); +- +- /* atr is a two's complement value on 6 bits, +- * perform sign extension. The formula is +- * Catr = (atr * 0.25pF) + 11.00pF. +- */ +- if (atr & 0x20) +- atr |= 0xC0; +- +- dev_dbg(&client->dev, "%s: raw atr=%x (%d)\n", __FUNCTION__, atr, atr); +- +- *trim = (atr * 250) + 11000; +- +- dev_dbg(&client->dev, "%s: real=%d\n", __FUNCTION__, *trim); +- +- return 0; +-} +- +-static int x1205_hctosys(struct i2c_client *client) +-{ +- int err; +- +- struct rtc_time tm; +- struct timespec tv; +- +- err = x1205_command(client, X1205_CMD_GETDATETIME, &tm); +- +- if (err) { +- dev_err(&client->dev, +- "Unable to set the system clock\n"); +- return err; +- } +- +- /* IMPORTANT: the RTC only stores whole seconds. It is arbitrary +- * whether it stores the most close value or the value with partial +- * seconds truncated. However, it is important that we use it to store +- * the truncated value. This is because otherwise it is necessary, +- * in an rtc sync function, to read both xtime.tv_sec and +- * xtime.tv_nsec. On some processors (i.e. ARM), an atomic read +- * of >32bits is not possible. So storing the most close value would +- * slow down the sync API. So here we have the truncated value and +- * the best guess is to add 0.5s. +- */ +- +- tv.tv_nsec = NSEC_PER_SEC >> 1; +- +- /* WARNING: this is not the C library 'mktime' call, it is a built in +- * inline function from include/linux/time.h. It expects (requires) +- * the month to be in the range 1-12 +- */ +- +- tv.tv_sec = mktime(tm.tm_year + 1900, tm.tm_mon + 1, +- tm.tm_mday, tm.tm_hour, +- tm.tm_min, tm.tm_sec); +- +- do_settimeofday(&tv); +- +- dev_info(&client->dev, +- "setting the system clock to %d-%d-%d %d:%d:%d\n", +- tm.tm_year + 1900, tm.tm_mon + 1, +- tm.tm_mday, tm.tm_hour, tm.tm_min, +- tm.tm_sec); +- +- return 0; +-} +- +-struct x1205_limit +-{ +- unsigned char reg; +- unsigned char mask; +- unsigned char min; +- unsigned char max; +-}; +- +-static int x1205_validate_client(struct i2c_client *client) +-{ +- int i, xfer; +- +- /* Probe array. We will read the register at the specified +- * address and check if the given bits are zero. +- */ +- static const unsigned char probe_zero_pattern[] = { +- /* register, mask */ +- X1205_REG_SR, 0x18, +- X1205_REG_DTR, 0xF8, +- X1205_REG_ATR, 0xC0, +- X1205_REG_INT, 0x18, +- X1205_REG_0, 0xFF, +- }; +- +- static const struct x1205_limit probe_limits_pattern[] = { +- /* register, mask, min, max */ +- { X1205_REG_Y2K, 0xFF, 19, 20 }, +- { X1205_REG_DW, 0xFF, 0, 6 }, +- { X1205_REG_YR, 0xFF, 0, 99 }, +- { X1205_REG_MO, 0xFF, 0, 12 }, +- { X1205_REG_DT, 0xFF, 0, 31 }, +- { X1205_REG_HR, 0x7F, 0, 23 }, +- { X1205_REG_MN, 0xFF, 0, 59 }, +- { X1205_REG_SC, 0xFF, 0, 59 }, +- { X1205_REG_Y2K1, 0xFF, 19, 20 }, +- { X1205_REG_Y2K0, 0xFF, 19, 20 }, +- }; +- +- /* check that registers have bits a 0 where expected */ +- for (i = 0; i < ARRAY_SIZE(probe_zero_pattern); i += 2) { +- unsigned char buf; +- +- unsigned char addr[2] = { 0, probe_zero_pattern[i] }; +- +- struct i2c_msg msgs[2] = { +- { client->addr, 0, 2, addr }, +- { client->addr, I2C_M_RD, 1, &buf }, +- }; +- +- xfer = i2c_transfer(client->adapter, msgs, 2); +- if (xfer != 2) { +- dev_err(&client->adapter->dev, +- "%s: could not read register %x\n", +- __FUNCTION__, addr[1]); +- +- return -EIO; +- } +- +- if ((buf & probe_zero_pattern[i+1]) != 0) { +- dev_err(&client->adapter->dev, +- "%s: register=%02x, zero pattern=%d, value=%x\n", +- __FUNCTION__, addr[1], i, buf); +- +- return -ENODEV; +- } +- } +- +- /* check limits (only registers with bcd values) */ +- for (i = 0; i < ARRAY_SIZE(probe_limits_pattern); i++) { +- unsigned char reg, value; +- +- unsigned char addr[2] = { 0, probe_limits_pattern[i].reg }; +- +- struct i2c_msg msgs[2] = { +- { client->addr, 0, 2, addr }, +- { client->addr, I2C_M_RD, 1, ® }, +- }; +- +- xfer = i2c_transfer(client->adapter, msgs, 2); +- +- if (xfer != 2) { +- dev_err(&client->adapter->dev, +- "%s: could not read register %x\n", +- __FUNCTION__, addr[1]); +- +- return -EIO; +- } +- +- value = BCD2BIN(reg & probe_limits_pattern[i].mask); +- +- if (value > probe_limits_pattern[i].max || +- value < probe_limits_pattern[i].min) { +- dev_dbg(&client->adapter->dev, +- "%s: register=%x, lim pattern=%d, value=%d\n", +- __FUNCTION__, addr[1], i, value); +- +- return -ENODEV; +- } +- } +- +- return 0; +-} +- +-static int x1205_attach(struct i2c_adapter *adapter) +-{ +- dev_dbg(&adapter->dev, "%s\n", __FUNCTION__); +- +- return i2c_probe(adapter, &addr_data, x1205_probe); +-} +- +-int x1205_direct_attach(int adapter_id, +- struct i2c_client_address_data *address_data) +-{ +- int err; +- struct i2c_adapter *adapter = i2c_get_adapter(adapter_id); +- +- if (adapter) { +- err = i2c_probe(adapter, +- address_data, x1205_probe); +- +- i2c_put_adapter(adapter); +- +- return err; +- } +- +- return -ENODEV; +-} +- +-static int x1205_probe(struct i2c_adapter *adapter, int address, int kind) +-{ +- struct i2c_client *client; +- struct x1205_data *data; +- +- int err = 0; +- +- dev_dbg(&adapter->dev, "%s\n", __FUNCTION__); +- +- if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) { +- err = -ENODEV; +- goto exit; +- } +- +- if (!(data = kzalloc(sizeof(struct x1205_data), GFP_KERNEL))) { +- err = -ENOMEM; +- goto exit; +- } +- +- /* Initialize our structures */ +- data->epoch = 2000; +- +- client = &data->client; +- client->addr = address; +- client->driver = &x1205_driver; +- client->adapter = adapter; +- +- strlcpy(client->name, "x1205", I2C_NAME_SIZE); +- +- i2c_set_clientdata(client, data); +- +- /* Verify the chip is really an X1205 */ +- if (kind < 0) { +- if (x1205_validate_client(client) < 0) { +- err = -ENODEV; +- goto exit_kfree; +- } +- } +- +- /* Inform the i2c layer */ +- if ((err = i2c_attach_client(client))) +- goto exit_kfree; +- +- list_add(&data->list, &x1205_clients); +- +- dev_info(&client->dev, "chip found, driver version " DRV_VERSION "\n"); +- +- /* If requested, set the system time */ +- if (hctosys) +- x1205_hctosys(client); +- +- return 0; +- +-exit_kfree: +- kfree(data); +- +-exit: +- return err; +-} +- +-static int x1205_detach(struct i2c_client *client) +-{ +- int err; +- struct x1205_data *data = i2c_get_clientdata(client); +- +- dev_dbg(&client->dev, "%s\n", __FUNCTION__); +- +- if ((err = i2c_detach_client(client))) +- return err; +- +- list_del(&data->list); +- +- kfree(data); +- +- return 0; +-} +- +-static int x1205_command(struct i2c_client *client, unsigned int cmd, +- void *param) +-{ +- if (param == NULL) +- return -EINVAL; +- +- if (!capable(CAP_SYS_TIME)) +- return -EACCES; +- +- dev_dbg(&client->dev, "%s: cmd=%d\n", __FUNCTION__, cmd); +- +- switch (cmd) { +- case X1205_CMD_GETDATETIME: +- return x1205_get_datetime(client, param, X1205_CCR_BASE); +- +- case X1205_CMD_SETTIME: +- return x1205_set_datetime(client, param, 0, +- X1205_CCR_BASE); +- +- case X1205_CMD_SETDATETIME: +- return x1205_set_datetime(client, param, 1, +- X1205_CCR_BASE); +- +- case X1205_CMD_GETALARM: +- return x1205_get_datetime(client, param, X1205_ALM0_BASE); +- +- case X1205_CMD_SETALARM: +- return x1205_set_datetime(client, param, 1, +- X1205_ALM0_BASE); +- +- case X1205_CMD_GETDTRIM: +- return x1205_get_dtrim(client, param); +- +- case X1205_CMD_GETATRIM: +- return x1205_get_atrim(client, param); +- +- default: +- return -EINVAL; +- } +-} +- +-static int __init x1205_init(void) +-{ +- return i2c_add_driver(&x1205_driver); +-} +- +-static void __exit x1205_exit(void) +-{ +- i2c_del_driver(&x1205_driver); +-} +- +-MODULE_AUTHOR( +- "Karen Spearel , " +- "Alessandro Zummo "); +-MODULE_DESCRIPTION("Xicor X1205 RTC driver"); +-MODULE_LICENSE("GPL"); +-MODULE_VERSION(DRV_VERSION); +- +-EXPORT_SYMBOL_GPL(x1205_do_command); +-EXPORT_SYMBOL_GPL(x1205_direct_attach); +- +-module_init(x1205_init); +-module_exit(x1205_exit); +--- linux-rtc.orig/drivers/i2c/chips/Makefile 2006-02-21 00:34:27.000000000 +0100 ++++ linux-rtc/drivers/i2c/chips/Makefile 2006-02-21 00:36:43.000000000 +0100 +@@ -10,10 +10,8 @@ obj-$(CONFIG_SENSORS_M41T00) += m41t00.o + obj-$(CONFIG_SENSORS_PCA9539) += pca9539.o + obj-$(CONFIG_SENSORS_PCF8574) += pcf8574.o + obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o +-obj-$(CONFIG_SENSORS_RTC8564) += rtc8564.o + obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o + obj-$(CONFIG_TPS65010) += tps65010.o +-obj-$(CONFIG_RTC_X1205_I2C) += x1205.o + + ifeq ($(CONFIG_I2C_DEBUG_CHIP),y) + EXTRA_CFLAGS += -DDEBUG +--- linux-rtc.orig/drivers/i2c/chips/rtc8564.c 2006-02-21 00:34:27.000000000 +0100 ++++ /dev/null 1970-01-01 00:00:00.000000000 +0000 +@@ -1,385 +0,0 @@ +-/* +- * linux/drivers/i2c/chips/rtc8564.c +- * +- * Copyright (C) 2002-2004 Stefan Eletzhofer +- * +- * based on linux/drivers/acron/char/pcf8583.c +- * Copyright (C) 2000 Russell King +- * +- * 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. +- * +- * Driver for system3's EPSON RTC 8564 chip +- */ +-#include +-#include +-#include +-#include +-#include +-#include +-#include /* get the user-level API */ +-#include +- +-#include "rtc8564.h" +- +-#ifdef DEBUG +-# define _DBG(x, fmt, args...) do{ if (debug>=x) printk(KERN_DEBUG"%s: " fmt "\n", __FUNCTION__, ##args); } while(0); +-#else +-# define _DBG(x, fmt, args...) do { } while(0); +-#endif +- +-#define _DBGRTCTM(x, rtctm) if (debug>=x) printk("%s: secs=%d, mins=%d, hours=%d, mday=%d, " \ +- "mon=%d, year=%d, wday=%d VL=%d\n", __FUNCTION__, \ +- (rtctm).secs, (rtctm).mins, (rtctm).hours, (rtctm).mday, \ +- (rtctm).mon, (rtctm).year, (rtctm).wday, (rtctm).vl); +- +-struct rtc8564_data { +- struct i2c_client client; +- u16 ctrl; +-}; +- +-static inline u8 _rtc8564_ctrl1(struct i2c_client *client) +-{ +- struct rtc8564_data *data = i2c_get_clientdata(client); +- return data->ctrl & 0xff; +-} +-static inline u8 _rtc8564_ctrl2(struct i2c_client *client) +-{ +- struct rtc8564_data *data = i2c_get_clientdata(client); +- return (data->ctrl & 0xff00) >> 8; +-} +- +-#define CTRL1(c) _rtc8564_ctrl1(c) +-#define CTRL2(c) _rtc8564_ctrl2(c) +- +-static int debug;; +-module_param(debug, int, S_IRUGO | S_IWUSR); +- +-static struct i2c_driver rtc8564_driver; +- +-static unsigned short ignore[] = { I2C_CLIENT_END }; +-static unsigned short normal_addr[] = { 0x51, I2C_CLIENT_END }; +- +-static struct i2c_client_address_data addr_data = { +- .normal_i2c = normal_addr, +- .probe = ignore, +- .ignore = ignore, +-}; +- +-static int rtc8564_read_mem(struct i2c_client *client, struct mem *mem); +-static int rtc8564_write_mem(struct i2c_client *client, struct mem *mem); +- +-static int rtc8564_read(struct i2c_client *client, unsigned char adr, +- unsigned char *buf, unsigned char len) +-{ +- int ret = -EIO; +- unsigned char addr[1] = { adr }; +- struct i2c_msg msgs[2] = { +- {client->addr, 0, 1, addr}, +- {client->addr, I2C_M_RD, len, buf} +- }; +- +- _DBG(1, "client=%p, adr=%d, buf=%p, len=%d", client, adr, buf, len); +- +- if (!buf) { +- ret = -EINVAL; +- goto done; +- } +- +- ret = i2c_transfer(client->adapter, msgs, 2); +- if (ret == 2) { +- ret = 0; +- } +- +-done: +- return ret; +-} +- +-static int rtc8564_write(struct i2c_client *client, unsigned char adr, +- unsigned char *data, unsigned char len) +-{ +- int ret = 0; +- unsigned char _data[16]; +- struct i2c_msg wr; +- int i; +- +- if (!data || len > 15) { +- ret = -EINVAL; +- goto done; +- } +- +- _DBG(1, "client=%p, adr=%d, buf=%p, len=%d", client, adr, data, len); +- +- _data[0] = adr; +- for (i = 0; i < len; i++) { +- _data[i + 1] = data[i]; +- _DBG(5, "data[%d] = 0x%02x (%d)", i, data[i], data[i]); +- } +- +- wr.addr = client->addr; +- wr.flags = 0; +- wr.len = len + 1; +- wr.buf = _data; +- +- ret = i2c_transfer(client->adapter, &wr, 1); +- if (ret == 1) { +- ret = 0; +- } +- +-done: +- return ret; +-} +- +-static int rtc8564_attach(struct i2c_adapter *adap, int addr, int kind) +-{ +- int ret; +- struct i2c_client *new_client; +- struct rtc8564_data *d; +- unsigned char data[10]; +- unsigned char ad[1] = { 0 }; +- struct i2c_msg ctrl_wr[1] = { +- {addr, 0, 2, data} +- }; +- struct i2c_msg ctrl_rd[2] = { +- {addr, 0, 1, ad}, +- {addr, I2C_M_RD, 2, data} +- }; +- +- d = kzalloc(sizeof(struct rtc8564_data), GFP_KERNEL); +- if (!d) { +- ret = -ENOMEM; +- goto done; +- } +- new_client = &d->client; +- +- strlcpy(new_client->name, "RTC8564", I2C_NAME_SIZE); +- i2c_set_clientdata(new_client, d); +- new_client->addr = addr; +- new_client->adapter = adap; +- new_client->driver = &rtc8564_driver; +- +- _DBG(1, "client=%p", new_client); +- +- /* init ctrl1 reg */ +- data[0] = 0; +- data[1] = 0; +- ret = i2c_transfer(new_client->adapter, ctrl_wr, 1); +- if (ret != 1) { +- printk(KERN_INFO "rtc8564: cant init ctrl1\n"); +- ret = -ENODEV; +- goto done; +- } +- +- /* read back ctrl1 and ctrl2 */ +- ret = i2c_transfer(new_client->adapter, ctrl_rd, 2); +- if (ret != 2) { +- printk(KERN_INFO "rtc8564: cant read ctrl\n"); +- ret = -ENODEV; +- goto done; +- } +- +- d->ctrl = data[0] | (data[1] << 8); +- +- _DBG(1, "RTC8564_REG_CTRL1=%02x, RTC8564_REG_CTRL2=%02x", +- data[0], data[1]); +- +- ret = i2c_attach_client(new_client); +-done: +- if (ret) { +- kfree(d); +- } +- return ret; +-} +- +-static int rtc8564_probe(struct i2c_adapter *adap) +-{ +- return i2c_probe(adap, &addr_data, rtc8564_attach); +-} +- +-static int rtc8564_detach(struct i2c_client *client) +-{ +- i2c_detach_client(client); +- kfree(i2c_get_clientdata(client)); +- return 0; +-} +- +-static int rtc8564_get_datetime(struct i2c_client *client, struct rtc_tm *dt) +-{ +- int ret = -EIO; +- unsigned char buf[15]; +- +- _DBG(1, "client=%p, dt=%p", client, dt); +- +- if (!dt) +- return -EINVAL; +- +- memset(buf, 0, sizeof(buf)); +- +- ret = rtc8564_read(client, 0, buf, 15); +- if (ret) +- return ret; +- +- /* century stored in minute alarm reg */ +- dt->year = BCD2BIN(buf[RTC8564_REG_YEAR]); +- dt->year += 100 * BCD2BIN(buf[RTC8564_REG_AL_MIN] & 0x3f); +- dt->mday = BCD2BIN(buf[RTC8564_REG_DAY] & 0x3f); +- dt->wday = BCD2BIN(buf[RTC8564_REG_WDAY] & 7); +- dt->mon = BCD2BIN(buf[RTC8564_REG_MON_CENT] & 0x1f); +- +- dt->secs = BCD2BIN(buf[RTC8564_REG_SEC] & 0x7f); +- dt->vl = (buf[RTC8564_REG_SEC] & 0x80) == 0x80; +- dt->mins = BCD2BIN(buf[RTC8564_REG_MIN] & 0x7f); +- dt->hours = BCD2BIN(buf[RTC8564_REG_HR] & 0x3f); +- +- _DBGRTCTM(2, *dt); +- +- return 0; +-} +- +-static int +-rtc8564_set_datetime(struct i2c_client *client, struct rtc_tm *dt, int datetoo) +-{ +- int ret, len = 5; +- unsigned char buf[15]; +- +- _DBG(1, "client=%p, dt=%p", client, dt); +- +- if (!dt) +- return -EINVAL; +- +- _DBGRTCTM(2, *dt); +- +- buf[RTC8564_REG_CTRL1] = CTRL1(client) | RTC8564_CTRL1_STOP; +- buf[RTC8564_REG_CTRL2] = CTRL2(client); +- buf[RTC8564_REG_SEC] = BIN2BCD(dt->secs); +- buf[RTC8564_REG_MIN] = BIN2BCD(dt->mins); +- buf[RTC8564_REG_HR] = BIN2BCD(dt->hours); +- +- if (datetoo) { +- len += 5; +- buf[RTC8564_REG_DAY] = BIN2BCD(dt->mday); +- buf[RTC8564_REG_WDAY] = BIN2BCD(dt->wday); +- buf[RTC8564_REG_MON_CENT] = BIN2BCD(dt->mon) & 0x1f; +- /* century stored in minute alarm reg */ +- buf[RTC8564_REG_YEAR] = BIN2BCD(dt->year % 100); +- buf[RTC8564_REG_AL_MIN] = BIN2BCD(dt->year / 100); +- } +- +- ret = rtc8564_write(client, 0, buf, len); +- if (ret) { +- _DBG(1, "error writing data! %d", ret); +- } +- +- buf[RTC8564_REG_CTRL1] = CTRL1(client); +- ret = rtc8564_write(client, 0, buf, 1); +- if (ret) { +- _DBG(1, "error writing data! %d", ret); +- } +- +- return ret; +-} +- +-static int rtc8564_get_ctrl(struct i2c_client *client, unsigned int *ctrl) +-{ +- struct rtc8564_data *data = i2c_get_clientdata(client); +- +- if (!ctrl) +- return -1; +- +- *ctrl = data->ctrl; +- return 0; +-} +- +-static int rtc8564_set_ctrl(struct i2c_client *client, unsigned int *ctrl) +-{ +- struct rtc8564_data *data = i2c_get_clientdata(client); +- unsigned char buf[2]; +- +- if (!ctrl) +- return -1; +- +- buf[0] = *ctrl & 0xff; +- buf[1] = (*ctrl & 0xff00) >> 8; +- data->ctrl = *ctrl; +- +- return rtc8564_write(client, 0, buf, 2); +-} +- +-static int rtc8564_read_mem(struct i2c_client *client, struct mem *mem) +-{ +- +- if (!mem) +- return -EINVAL; +- +- return rtc8564_read(client, mem->loc, mem->data, mem->nr); +-} +- +-static int rtc8564_write_mem(struct i2c_client *client, struct mem *mem) +-{ +- +- if (!mem) +- return -EINVAL; +- +- return rtc8564_write(client, mem->loc, mem->data, mem->nr); +-} +- +-static int +-rtc8564_command(struct i2c_client *client, unsigned int cmd, void *arg) +-{ +- +- _DBG(1, "cmd=%d", cmd); +- +- switch (cmd) { +- case RTC_GETDATETIME: +- return rtc8564_get_datetime(client, arg); +- +- case RTC_SETTIME: +- return rtc8564_set_datetime(client, arg, 0); +- +- case RTC_SETDATETIME: +- return rtc8564_set_datetime(client, arg, 1); +- +- case RTC_GETCTRL: +- return rtc8564_get_ctrl(client, arg); +- +- case RTC_SETCTRL: +- return rtc8564_set_ctrl(client, arg); +- +- case MEM_READ: +- return rtc8564_read_mem(client, arg); +- +- case MEM_WRITE: +- return rtc8564_write_mem(client, arg); +- +- default: +- return -EINVAL; +- } +-} +- +-static struct i2c_driver rtc8564_driver = { +- .driver = { +- .name = "RTC8564", +- }, +- .id = I2C_DRIVERID_RTC8564, +- .attach_adapter = rtc8564_probe, +- .detach_client = rtc8564_detach, +- .command = rtc8564_command +-}; +- +-static __init int rtc8564_init(void) +-{ +- return i2c_add_driver(&rtc8564_driver); +-} +- +-static __exit void rtc8564_exit(void) +-{ +- i2c_del_driver(&rtc8564_driver); +-} +- +-MODULE_AUTHOR("Stefan Eletzhofer "); +-MODULE_DESCRIPTION("EPSON RTC8564 Driver"); +-MODULE_LICENSE("GPL"); +- +-module_init(rtc8564_init); +-module_exit(rtc8564_exit); +--- linux-rtc.orig/drivers/i2c/chips/rtc8564.h 2006-02-21 00:34:27.000000000 +0100 ++++ /dev/null 1970-01-01 00:00:00.000000000 +0000 +@@ -1,78 +0,0 @@ +-/* +- * linux/drivers/i2c/chips/rtc8564.h +- * +- * Copyright (C) 2002-2004 Stefan Eletzhofer +- * +- * based on linux/drivers/acron/char/pcf8583.h +- * Copyright (C) 2000 Russell King +- * +- * 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. +- */ +-struct rtc_tm { +- unsigned char secs; +- unsigned char mins; +- unsigned char hours; +- unsigned char mday; +- unsigned char mon; +- unsigned short year; /* xxxx 4 digits :) */ +- unsigned char wday; +- unsigned char vl; +-}; +- +-struct mem { +- unsigned int loc; +- unsigned int nr; +- unsigned char *data; +-}; +- +-#define RTC_GETDATETIME 0 +-#define RTC_SETTIME 1 +-#define RTC_SETDATETIME 2 +-#define RTC_GETCTRL 3 +-#define RTC_SETCTRL 4 +-#define MEM_READ 5 +-#define MEM_WRITE 6 +- +-#define RTC8564_REG_CTRL1 0x0 /* T 0 S 0 | T 0 0 0 */ +-#define RTC8564_REG_CTRL2 0x1 /* 0 0 0 TI/TP | AF TF AIE TIE */ +-#define RTC8564_REG_SEC 0x2 /* VL 4 2 1 | 8 4 2 1 */ +-#define RTC8564_REG_MIN 0x3 /* x 4 2 1 | 8 4 2 1 */ +-#define RTC8564_REG_HR 0x4 /* x x 2 1 | 8 4 2 1 */ +-#define RTC8564_REG_DAY 0x5 /* x x 2 1 | 8 4 2 1 */ +-#define RTC8564_REG_WDAY 0x6 /* x x x x | x 4 2 1 */ +-#define RTC8564_REG_MON_CENT 0x7 /* C x x 1 | 8 4 2 1 */ +-#define RTC8564_REG_YEAR 0x8 /* 8 4 2 1 | 8 4 2 1 */ +-#define RTC8564_REG_AL_MIN 0x9 /* AE 4 2 1 | 8 4 2 1 */ +-#define RTC8564_REG_AL_HR 0xa /* AE 4 2 1 | 8 4 2 1 */ +-#define RTC8564_REG_AL_DAY 0xb /* AE x 2 1 | 8 4 2 1 */ +-#define RTC8564_REG_AL_WDAY 0xc /* AE x x x | x 4 2 1 */ +-#define RTC8564_REG_CLKOUT 0xd /* FE x x x | x x FD1 FD0 */ +-#define RTC8564_REG_TCTL 0xe /* TE x x x | x x FD1 FD0 */ +-#define RTC8564_REG_TIMER 0xf /* 8 bit binary */ +- +-/* Control reg */ +-#define RTC8564_CTRL1_TEST1 (1<<3) +-#define RTC8564_CTRL1_STOP (1<<5) +-#define RTC8564_CTRL1_TEST2 (1<<7) +- +-#define RTC8564_CTRL2_TIE (1<<0) +-#define RTC8564_CTRL2_AIE (1<<1) +-#define RTC8564_CTRL2_TF (1<<2) +-#define RTC8564_CTRL2_AF (1<<3) +-#define RTC8564_CTRL2_TI_TP (1<<4) +- +-/* CLKOUT frequencies */ +-#define RTC8564_FD_32768HZ (0x0) +-#define RTC8564_FD_1024HZ (0x1) +-#define RTC8564_FD_32 (0x2) +-#define RTC8564_FD_1HZ (0x3) +- +-/* Timer CTRL */ +-#define RTC8564_TD_4096HZ (0x0) +-#define RTC8564_TD_64HZ (0x1) +-#define RTC8564_TD_1HZ (0x2) +-#define RTC8564_TD_1_60HZ (0x3) +- +-#define I2C_DRIVERID_RTC8564 0xf000 +--- linux-rtc.orig/include/linux/x1205.h 2006-02-21 00:34:27.000000000 +0100 ++++ /dev/null 1970-01-01 00:00:00.000000000 +0000 +@@ -1,31 +0,0 @@ +-/* +- * x1205.h - defines for drivers/i2c/chips/x1205.c +- * Copyright 2004 Karen Spearel +- * Copyright 2005 Alessandro Zummo +- * +- * 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; either version 2 of the License, or +- * (at your option) any later version. +- */ +- +-#ifndef __LINUX_X1205_H__ +-#define __LINUX_X1205_H__ +- +-/* commands */ +- +-#define X1205_CMD_GETDATETIME 0 +-#define X1205_CMD_SETTIME 1 +-#define X1205_CMD_SETDATETIME 2 +-#define X1205_CMD_GETALARM 3 +-#define X1205_CMD_SETALARM 4 +-#define X1205_CMD_GETDTRIM 5 +-#define X1205_CMD_SETDTRIM 6 +-#define X1205_CMD_GETATRIM 7 +-#define X1205_CMD_SETATRIM 8 +- +-extern int x1205_do_command(unsigned int cmd, void *arg); +-extern int x1205_direct_attach(int adapter_id, +- struct i2c_client_address_data *address_data); +- +-#endif /* __LINUX_X1205_H__ */ +--- linux-rtc.orig/drivers/i2c/chips/Kconfig 2006-02-21 00:34:27.000000000 +0100 ++++ linux-rtc/drivers/i2c/chips/Kconfig 2006-02-21 00:36:43.000000000 +0100 +@@ -65,15 +65,6 @@ config SENSORS_PCF8591 + This driver can also be built as a module. If so, the module + will be called pcf8591. + +-config SENSORS_RTC8564 +- tristate "Epson 8564 RTC chip" +- depends on I2C && EXPERIMENTAL +- help +- If you say yes here you get support for the Epson 8564 RTC chip. +- +- This driver can also be built as a module. If so, the module +- will be called i2c-rtc8564. +- + config ISP1301_OMAP + tristate "Philips ISP1301 with OMAP OTG" + depends on I2C && ARCH_OMAP_OTG +@@ -126,13 +117,4 @@ config SENSORS_MAX6875 + This driver can also be built as a module. If so, the module + will be called max6875. + +-config RTC_X1205_I2C +- tristate "Xicor X1205 RTC chip"