From 9dd5f2f30aec3141ed782e55b6671058e7239901 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jeremy=20Lain=C3=A9?= Date: Wed, 17 Dec 2008 17:39:59 +0100 Subject: linux-2.6.26: update patches for boc01 --- .../linux-2.6.26/boc01/005-081127-isl12024.patch | 946 --------------------- .../linux-2.6.26/boc01/005-081217-isl12024.patch | 940 ++++++++++++++++++++ .../linux-2.6.26/boc01/006-081105-at24c32.patch | 284 ------- .../linux-2.6.26/boc01/006-081216-at24c32.patch | 361 ++++++++ .../linux/linux-2.6.26/boc01/007-081127-lm73.patch | 275 ------ .../linux/linux-2.6.26/boc01/007-081216-lm73.patch | 278 ++++++ .../linux/linux-2.6.26/boc01/011-081105-gpio.patch | 161 ---- .../linux/linux-2.6.26/boc01/011-081202-gpio.patch | 365 ++++++++ .../linux/linux-2.6.26/boc01/013-081127-lcd.patch | 663 --------------- .../linux/linux-2.6.26/boc01/013-081212-lcd.patch | 751 ++++++++++++++++ packages/linux/linux-2.6.26/boc01/defconfig | 8 +- packages/linux/linux_2.6.26.bb | 12 +- 12 files changed, 2705 insertions(+), 2339 deletions(-) delete mode 100644 packages/linux/linux-2.6.26/boc01/005-081127-isl12024.patch create mode 100644 packages/linux/linux-2.6.26/boc01/005-081217-isl12024.patch delete mode 100644 packages/linux/linux-2.6.26/boc01/006-081105-at24c32.patch create mode 100644 packages/linux/linux-2.6.26/boc01/006-081216-at24c32.patch delete mode 100644 packages/linux/linux-2.6.26/boc01/007-081127-lm73.patch create mode 100644 packages/linux/linux-2.6.26/boc01/007-081216-lm73.patch delete mode 100644 packages/linux/linux-2.6.26/boc01/011-081105-gpio.patch create mode 100644 packages/linux/linux-2.6.26/boc01/011-081202-gpio.patch delete mode 100644 packages/linux/linux-2.6.26/boc01/013-081127-lcd.patch create mode 100644 packages/linux/linux-2.6.26/boc01/013-081212-lcd.patch diff --git a/packages/linux/linux-2.6.26/boc01/005-081127-isl12024.patch b/packages/linux/linux-2.6.26/boc01/005-081127-isl12024.patch deleted file mode 100644 index 5e9f198b47..0000000000 --- a/packages/linux/linux-2.6.26/boc01/005-081127-isl12024.patch +++ /dev/null @@ -1,946 +0,0 @@ -diff -Nru linux-2.6.26-officiel/drivers/i2c/chips/isl12024-eeprom.c /home/guilig/workspace/kernel-goobie-2.6.26/src/drivers/i2c/chips/isl12024-eeprom.c ---- linux-2.6.26-officiel/drivers/i2c/chips/isl12024-eeprom.c 1970-01-01 01:00:00.000000000 +0100 -+++ /home/guilig/workspace/kernel-goobie-2.6.26/src/drivers/i2c/chips/isl12024-eeprom.c 2008-11-06 10:41:46.000000000 +0100 -@@ -0,0 +1,254 @@ -+/* -+ * Intersil ISL12024 EEPROM class driver -+ * -+ * -+ * Copyright (C) 2007, CenoSYS (www.cenosys.com). -+ * Guillaume Ligneul -+ * Guillaume.ligneul@gmail.com -+ * -+ * Code is based on eeprom.c -+ * -+ * This software program is licensed subject to the GNU General Public License -+ * (GPL).Version 2,June 1991, available at http://www.fsf.org/copyleft/gpl.html -+ */ -+ -+#include -+#include -+#include -+//#include -+//#include -+#include -+#include -+#include -+ -+/* Addresses to scan */ -+static const unsigned short normal_i2c[] = { ISL12024_I2C_EEPROM_ADDR, I2C_CLIENT_END }; -+ -+/* Insmod parameters */ -+I2C_CLIENT_INSMOD_1(eeprom); -+ -+ -+/* Size of EEPROM in bytes */ -+#define EEPROM_SIZE 4096 -+ -+/* Each client has this additional data */ -+struct eeprom_data { -+ struct i2c_client client; -+ struct mutex update_lock; -+}; -+ -+int -+isl12024_i2c_read(struct i2c_client *client, u8 reg, u8 buf[], -+ unsigned len) -+{ -+ int ret; -+ u8 dt_addr[2]; -+ -+ struct i2c_msg msgs[2] = { -+ { -+ .addr = client->addr, -+ .flags = 0, -+ .len = 2, -+ .buf = dt_addr, -+ }, -+ { -+ .addr = client->addr, -+ .flags = I2C_M_RD, -+ .len = len , -+ .buf = buf , -+ }, -+ }; -+ -+ dt_addr[0] = 0; -+ dt_addr[1] = reg; -+ -+ ret = i2c_transfer(client->adapter, msgs, 2); -+ if ( ret < 0) { -+ dev_err(&client->dev, "read error\n"); -+ return -EIO; -+ } -+ return ret; -+} -+ -+ -+int -+isl12024_i2c_write(struct i2c_client *client, u8 reg, u8 const buf[], -+ unsigned len) -+{ -+ int ret; -+ u8 i2c_buf[EEPROM_SIZE]; -+ -+ struct i2c_msg msgs[1] = { -+ { -+ .addr = client->addr, -+ .flags = 0, -+ .len = len+2, -+ .buf = i2c_buf, -+ }, -+ }; -+ -+ i2c_buf[0] = 0; -+ i2c_buf[1] = reg; -+ -+ -+ memcpy(&i2c_buf[2], &buf[0], len ); -+ -+ -+ ret = i2c_transfer(client->adapter, msgs, 1); -+ printk(KERN_INFO "i2c_transfer %d\n",ret); -+ return ret; -+} -+static int eeprom_attach_adapter(struct i2c_adapter *adapter); -+static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind); -+static int eeprom_detach_client(struct i2c_client *client); -+ -+/* This is the driver that will be inserted */ -+static struct i2c_driver eeprom_driver = { -+ .driver = { -+ .name = "isl12024-eeprom", -+ }, -+ .attach_adapter = eeprom_attach_adapter, -+ .detach_client = eeprom_detach_client, -+}; -+ -+static ssize_t eeprom_read(struct kobject *kobj, struct bin_attribute *bin_attr, -+ char *buf, loff_t off, size_t count) -+{ -+ struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj)); -+ struct eeprom_data *data = i2c_get_clientdata(client); -+ int rc; -+ -+ mutex_lock(&data->update_lock); -+ -+ if (off >= EEPROM_SIZE) -+ return 0; -+ -+ if (off + count > EEPROM_SIZE) -+ count = EEPROM_SIZE - off; -+ -+ rc = isl12024_i2c_read(client,0,buf,EEPROM_SIZE); -+ -+ if (rc < 0){ -+ mutex_unlock(&data->update_lock); -+ return -EIO; -+ } -+ -+ mutex_unlock(&data->update_lock); -+ return count; -+} -+ -+static ssize_t eeprom_write(struct kobject *kobj, struct bin_attribute *attr, -+ char *buf, loff_t off, size_t count) -+{ -+ struct i2c_client *client = kobj_to_i2c_client(kobj); -+ struct eeprom_data *data = i2c_get_clientdata(client); -+ -+ if (off >= 256) -+ return -ENOSPC; -+ -+ if (off + count > 256) -+ count = 256 - off; -+ -+ mutex_unlock(&data->update_lock); -+ if (isl12024_i2c_write(client, off, buf, count) < 0) -+ { -+ mutex_unlock(&data->update_lock); -+ return -EIO; -+ } -+ -+ mutex_unlock(&data->update_lock); -+ return count; -+} -+ -+static struct bin_attribute eeprom_attr = { -+ .attr = { -+ .name = "eeprom", -+ .mode = S_IRUGO, -+ }, -+ .size = EEPROM_SIZE, -+ .read = eeprom_read, -+ .write= eeprom_write, -+}; -+ -+static int eeprom_attach_adapter(struct i2c_adapter *adapter) -+{ -+ return i2c_probe(adapter, &addr_data, eeprom_detect); -+} -+ -+/* This function is called by i2c_probe */ -+static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind) -+{ -+ struct i2c_client *new_client; -+ struct eeprom_data *data; -+ int err = 0; -+ -+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE_DATA -+ | I2C_FUNC_SMBUS_BYTE)) -+ goto exit; -+ -+ if (!(data = kzalloc(sizeof(struct eeprom_data), GFP_KERNEL))) { -+ err = -ENOMEM; -+ goto exit; -+ } -+ -+ new_client = &data->client; -+ i2c_set_clientdata(new_client, data); -+ new_client->addr = address; -+ new_client->adapter = adapter; -+ new_client->driver = &eeprom_driver; -+ new_client->flags = 0; -+ -+ strlcpy(new_client->name, "isl12024-eeprom", I2C_NAME_SIZE); -+ mutex_init(&data->update_lock); -+ -+ /* Tell the I2C layer a new client has arrived */ -+ if ((err = i2c_attach_client(new_client))) -+ goto exit_kfree; -+ -+ /* create the sysfs eeprom file */ -+ err = sysfs_create_bin_file(&new_client->dev.kobj, &eeprom_attr); -+ if (err) -+ goto exit_detach; -+ -+ return 0; -+ -+exit_detach: -+ i2c_detach_client(new_client); -+exit_kfree: -+ kfree(data); -+exit: -+ return err; -+} -+ -+static int eeprom_detach_client(struct i2c_client *client) -+{ -+ int err; -+ -+ sysfs_remove_bin_file(&client->dev.kobj, &eeprom_attr); -+ -+ err = i2c_detach_client(client); -+ if (err) -+ return err; -+ -+ kfree(i2c_get_clientdata(client)); -+ -+ return 0; -+} -+ -+static int __init eeprom_init(void) -+{ -+ return i2c_add_driver(&eeprom_driver); -+} -+ -+static void __exit eeprom_exit(void) -+{ -+ i2c_del_driver(&eeprom_driver); -+} -+ -+ -+MODULE_AUTHOR("Guillaume Ligneul "); -+MODULE_DESCRIPTION("I2C Intersil12024 EEPROM driver"); -+MODULE_LICENSE("GPL"); -+ -+module_init(eeprom_init); -+module_exit(eeprom_exit); -diff -Nru linux-2.6.26-officiel/drivers/i2c/chips/Kconfig /home/guilig/workspace/kernel-goobie-2.6.26/src/drivers/i2c/chips/Kconfig ---- linux-2.6.26-officiel/drivers/i2c/chips/Kconfig 2008-07-13 23:51:29.000000000 +0200 -+++ /home/guilig/workspace/kernel-goobie-2.6.26/src/drivers/i2c/chips/Kconfig 2008-11-05 15:49:03.000000000 +0100 -@@ -4,6 +4,12 @@ - - menu "Miscellaneous I2C Chip support" - -+config AT24C32 -+ tristate "24C32 EEPROM" -+ depends on SYSFS && EXPERIMENTAL -+ help -+ help not needed :) -+ - config DS1682 - tristate "Dallas DS1682 Total Elapsed Time Recorder with Alarm" - depends on EXPERIMENTAL -@@ -14,6 +20,15 @@ - This driver can also be built as a module. If so, the module - will be called ds1682. - -+config ISL12024EEPROM -+ tristate "Intersil 12024 EEPROM" -+ depends on RTC_DRV_ISL12024 -+ help -+ If you say yes here you get support for Intersil12024 EEPROM. -+ -+ This driver can also be built as a module. If so, the module -+ will be called isl12024-eeprom. -+ - config SENSORS_EEPROM - tristate "EEPROM reader" - depends on EXPERIMENTAL -diff -Nru linux-2.6.26-officiel/drivers/i2c/chips/Makefile /home/guilig/workspace/kernel-goobie-2.6.26/src/drivers/i2c/chips/Makefile ---- linux-2.6.26-officiel/drivers/i2c/chips/Makefile 2008-07-13 23:51:29.000000000 +0200 -+++ /home/guilig/workspace/kernel-goobie-2.6.26/src/drivers/i2c/chips/Makefile 2008-11-06 11:04:27.000000000 +0100 -@@ -9,6 +9,8 @@ - # * I/O expander drivers go to drivers/gpio - # - -+ -+obj-$(CONFIG_ISL12024EEPROM) += isl12024-eeprom.o - obj-$(CONFIG_DS1682) += ds1682.o - obj-$(CONFIG_SENSORS_EEPROM) += eeprom.o - obj-$(CONFIG_SENSORS_MAX6875) += max6875.o -diff -Nru linux-2.6.26-officiel/drivers/rtc/Kconfig /home/guilig/workspace/kernel-goobie-2.6.26/src/drivers/rtc/Kconfig ---- linux-2.6.26-officiel/drivers/rtc/Kconfig 2008-07-13 23:51:29.000000000 +0200 -+++ /home/guilig/workspace/kernel-goobie-2.6.26/src/drivers/rtc/Kconfig 2008-09-26 13:53:16.000000000 +0200 -@@ -124,6 +124,12 @@ - - if I2C - -+config RTC_DRV_ISL12024 -+ tristate "Intersil 12024 RTC/ UniqueID" -+ help -+ If you say yes .... -+ This driver can also be built as a module. -+ - config RTC_DRV_DS1307 - tristate "Dallas/Maxim DS1307/37/38/39/40, ST M41T00" - help -diff -Nru linux-2.6.26-officiel/drivers/rtc/Makefile /home/guilig/workspace/kernel-goobie-2.6.26/src/drivers/rtc/Makefile ---- linux-2.6.26-officiel/drivers/rtc/Makefile 2008-07-13 23:51:29.000000000 +0200 -+++ /home/guilig/workspace/kernel-goobie-2.6.26/src/drivers/rtc/Makefile 2008-09-26 14:25:25.000000000 +0200 -@@ -33,6 +33,7 @@ - obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o - obj-$(CONFIG_RTC_DRV_FM3130) += rtc-fm3130.o - obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o -+obj-$(CONFIG_RTC_DRV_ISL12024) += rtc-isl12024.o - obj-$(CONFIG_RTC_DRV_M41T80) += rtc-m41t80.o - obj-$(CONFIG_RTC_DRV_M48T59) += rtc-m48t59.o - obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o -diff -Nru linux-2.6.26/drivers/rtc/rtc-isl12024.c linux-2.6.26.mod/drivers/rtc/rtc-isl12024.c ---- linux-2.6.26/drivers/rtc/rtc-isl12024.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.26.mod/drivers/rtc/rtc-isl12024.c 2008-11-27 12:05:37.000000000 +0100 -@@ -0,0 +1,516 @@ -+/* -+ * Intersil ISL12024 class driver -+ * -+ * -+ * Copyright (C) 2007, CenoSYS (www.cenosys.com). -+ * Guillaume Ligneul -+ * Guillaume.ligneul@gmail.com -+ * -+ * This software program is licensed subject to the GNU General Public License -+ * (GPL).Version 2,June 1991, available at http://www.fsf.org/copyleft/gpl.html -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+ -+#define DBG 1 -+#undef DBG -+ -+static u8 buf_id[ISL12024_RTC_SECTION_LEN] = { 0 ,}; -+ -+#define DRV_NAME "isl12024" -+#define DRV_VERSION "0.1" -+ -+/* i2c configuration */ -+ -+static const unsigned short normal_i2c[] = { -+ ISL12024_I2C_ADDR >>1, I2C_CLIENT_END -+}; -+I2C_CLIENT_INSMOD; -+ -+/* Procfs management */ -+static struct proc_dir_entry * root_proc = NULL; -+static struct proc_dir_entry * entry_proc = NULL; -+static int read_proc (char * page, char ** start, off_t off, int count, int * eof, void * data); -+ -+static int isl12024_get_status(struct i2c_client *client, unsigned char *sr); -+static int isl12024_fix_osc(struct i2c_client *client); -+ -+ -+static int isl12024_attach_adapter(struct i2c_adapter *adapter); -+static int isl12024_detach_client(struct i2c_client *client); -+ -+// To debug (may be add in includ/linux/i2c-id.h) -+#define I2C_DRIVERID_ISL12024 97 -+ -+static struct i2c_driver isl12024_driver = { -+ .driver = { -+ .name = DRV_NAME, -+ }, -+ .id = I2C_DRIVERID_ISL12024, -+ .attach_adapter = &isl12024_attach_adapter, -+ .detach_client = &isl12024_detach_client, -+}; -+ -+int -+isl12024_i2c_read_regs(struct i2c_client *client, u8 reg, u8 buf[], -+ unsigned len) -+{ -+ int ret; -+ u8 dt_addr[2]; -+ -+ struct i2c_msg msgs[2] = { -+ { -+ .addr = client->addr, -+ .flags = 0, -+ .len = 2, -+ .buf = dt_addr, -+ }, -+ { -+ .addr = client->addr, -+ .flags = I2C_M_RD, -+ .len = len , -+ .buf = buf , -+ }, -+ }; -+ -+ dt_addr[0] = 0; -+ dt_addr[1] = reg; -+ -+ ret = i2c_transfer(client->adapter, msgs, 2); -+ if ( ret < 0) { -+ dev_err(&client->dev, "read error\n"); -+ return -EIO; -+ } -+ return ret; -+} -+ -+EXPORT_SYMBOL(isl12024_i2c_read_regs); -+ -+ -+int -+isl12024_i2c_set_regs(struct i2c_client *client, u8 reg, u8 const buf[], -+ unsigned len) -+{ -+ int ret; -+ u8 i2c_buf[10]; -+ -+ struct i2c_msg msgs[1] = { -+ { -+ .addr = client->addr, -+ .flags = 0, -+ .len = len+2, -+ .buf = i2c_buf, -+ }, -+ }; -+ -+ i2c_buf[0] = 0; -+ i2c_buf[1] = reg; -+ -+ -+ memcpy(&i2c_buf[2], &buf[0], len ); -+ -+ -+ ret = i2c_transfer(client->adapter, msgs, 1); -+ printk(KERN_INFO "i2c_transfer %d\n",ret); -+ return ret; -+} -+ -+EXPORT_SYMBOL(isl12024_i2c_set_regs); -+ -+static int isl12024_i2c_validate_client(struct i2c_client *client) -+{ -+ u8 regs[ISL12024_RTC_SECTION_LEN] = { 0, }; -+ u8 zero_mask[ISL12024_RTC_SECTION_LEN] = { -+ 0x80, 0x80, 0x40, 0xc0, 0xe0, 0x00, 0xf8, 0xc6 -+ }; -+ -+ int i; -+ int ret; -+ -+ ret = isl12024_i2c_read_regs(client, ISL12024_REG_SC, regs, ISL12024_RTC_SECTION_LEN); -+ -+ if (ret < 0) -+ return ret; -+ -+ for (i = 0; i < ISL12024_RTC_SECTION_LEN; ++i) { -+ if (regs[i] & zero_mask[i]) /* check if bits are cleared */ -+ return -ENODEV; -+ -+ } -+ -+ return 0; -+} -+ -+static int isl12024_read_time(struct i2c_client *client, -+ struct rtc_time *tm) -+{ -+ unsigned char sr; -+ int err; -+ u8 regs[ISL12024_RTC_SECTION_LEN] = { 0, }; -+ -+ printk(KERN_INFO "%s\n ",__FUNCTION__ ); -+ -+ -+ if (isl12024_get_status(client, &sr) < 0) { -+ dev_err(&client->dev, "%s: reading SR failed\n", __func__); -+ return -EIO; -+ } -+ -+ err = isl12024_i2c_read_regs(client, ISL12024_REG_SC, regs, ISL12024_RTC_SECTION_LEN); -+ -+#ifdef DBG -+ int i; -+ for(i=0; idev, "%s: reading RTC section failed\n", -+ __func__); -+ return sr; -+ } -+ -+ tm->tm_sec = BCD2BIN(regs[0]); -+ tm->tm_min = BCD2BIN(regs[1]); -+ -+ { /* HR field has a more complex interpretation */ -+ const u8 _hr = regs[2]; -+ if (_hr & ISL12024_REG_HR_MIL) /* 24h format */ -+ tm->tm_hour = BCD2BIN(_hr & 0x3f); -+ else { // 12h format -+ tm->tm_hour = BCD2BIN(_hr & 0x1f); -+ if (_hr & ISL12024_REG_HR_PM) /* PM flag set */ -+ tm->tm_hour += 12; -+ } -+ } -+ -+ tm->tm_mday = BCD2BIN(regs[3]); -+ tm->tm_mon = BCD2BIN(regs[4]); -+ tm->tm_year = BCD2BIN(regs[5]) + 100; -+ tm->tm_wday = BCD2BIN(regs[6]); -+ -+ return rtc_valid_tm(tm); -+} -+ -+static int isl12024_get_status(struct i2c_client *client, unsigned char *sr) -+{ -+ static unsigned char sr_addr[2] = { 0, ISL12024_REG_SR }; -+ -+ struct i2c_msg msgs[] = { -+ { client->addr, 0, 2, sr_addr }, /* setup read ptr */ -+ { client->addr, I2C_M_RD, 1, sr }, /* read status */ -+ }; -+ -+ /* read status register */ -+ if (i2c_transfer(client->adapter, &msgs[0], 2) != 2) { -+ dev_err(&client->dev, "%s: read error\n", __func__); -+ return -EIO; -+ } -+ -+ return 0; -+} -+ -+static int isl12024_set_datetime(struct i2c_client *client, struct rtc_time *tm, -+ int datetoo, u8 reg_base, unsigned char alm_enable) -+{ -+ int i, xfer, nbytes; -+ unsigned char buf[8]; -+ unsigned char rdata[10] = { 0, reg_base }; -+ -+ static const unsigned char wel[3] = { 0, ISL12024_REG_SR, -+ ISL12024_SR_WEL }; -+ -+ static const unsigned char rwel[3] = { 0, ISL12024_REG_SR, -+ ISL12024_SR_WEL | ISL12024_SR_RWEL }; -+ -+ static const unsigned char diswe[3] = { 0, ISL12024_REG_SR, 0 }; -+ -+ dev_dbg(&client->dev, -+ "%s: secs=%d, mins=%d, hours=%d\n", -+ __func__, -+ tm->tm_sec, tm->tm_min, tm->tm_hour); -+ -+ 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) | ISL12024_HR_MIL; -+ -+ /* should we also set the date? */ -+ if (datetoo) { -+ dev_dbg(&client->dev, -+ "%s: mday=%d, mon=%d, year=%d, wday=%d\n", -+ __func__, -+ tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); -+ -+ buf[CCR_MDAY] = BIN2BCD(tm->tm_mday); -+ -+ /* month, 1 - 12 */ -+ buf[CCR_MONTH] = BIN2BCD(tm->tm_mon); -+ -+ /* year, since the rtc epoch*/ -+ buf[CCR_YEAR] = BIN2BCD(tm->tm_year % 100); -+ buf[CCR_WDAY] = tm->tm_wday & 0x07; -+ buf[CCR_Y2K] = BIN2BCD(tm->tm_year / 100); -+ } -+ -+ /* If writing alarm registers, set compare bits on registers 0-4 */ -+ if (reg_base < ISL12024_CCR_BASE) -+ for (i = 0; i <= 4; i++) -+ buf[i] |= 0x80; -+ -+ /* this sequence is required to unlock the chip */ -+ if ((xfer = i2c_master_send(client, wel, 3)) != 3) { -+ dev_err(&client->dev, "%s: wel - %d\n", __func__, xfer); -+ return -EIO; -+ } -+ -+ if ((xfer = i2c_master_send(client, rwel, 3)) != 3) { -+ dev_err(&client->dev, "%s: rwel - %d\n", __func__, xfer); -+ return -EIO; -+ } -+ -+ -+ /* write register's data */ -+ if (datetoo) -+ nbytes = 8; -+ else -+ nbytes = 3; -+ for (i = 0; i < nbytes; i++) -+ rdata[2+i] = buf[i]; -+ -+ xfer = i2c_master_send(client, rdata, nbytes+2); -+ if (xfer != nbytes+2) { -+ dev_err(&client->dev, -+ "%s: result=%d addr=%02x, data=%02x\n", -+ __func__, -+ xfer, rdata[1], rdata[2]); -+ return -EIO; -+ } -+ -+ /* If we wrote to the nonvolatile region, wait 10msec for write cycle*/ -+ if (reg_base < ISL12024_CCR_BASE) { -+ unsigned char al0e[3] = { 0, ISL12024_REG_INT, 0 }; -+ -+ msleep(10); -+ -+ /* ...and set or clear the AL0E bit in the INT register */ -+ -+ /* Need to set RWEL again as the write has cleared it */ -+ xfer = i2c_master_send(client, rwel, 3); -+ if (xfer != 3) { -+ dev_err(&client->dev, -+ "%s: aloe rwel - %d\n", -+ __func__, -+ xfer); -+ return -EIO; -+ } -+ -+ if (alm_enable) -+ al0e[2] = ISL12024_INT_AL0E; -+ -+ xfer = i2c_master_send(client, al0e, 3); -+ if (xfer != 3) { -+ dev_err(&client->dev, -+ "%s: al0e - %d\n", -+ __func__, -+ xfer); -+ return -EIO; -+ } -+ -+ /* and wait 10msec again for this write to complete */ -+ msleep(10); -+ } -+ -+ /* disable further writes */ -+ if ((xfer = i2c_master_send(client, diswe, 3)) != 3) { -+ dev_err(&client->dev, "%s: diswe - %d\n", __func__, xfer); -+ return -EIO; -+ } -+ -+ return 0; -+} -+ -+static int isl12024_fix_osc(struct i2c_client *client) -+{ -+ int err; -+ struct rtc_time tm; -+ -+ tm.tm_hour = tm.tm_min = tm.tm_sec = 0; -+ -+ err = isl12024_set_datetime(client, &tm, 0, ISL12024_CCR_BASE, 0); -+ if (err < 0) -+ printk(KERN_INFO "unable to restart the oscillator\n"); -+ -+ return err; -+} -+ -+static int isl12024_rtc_read_time(struct device *dev, struct rtc_time *tm) -+{ -+ return isl12024_read_time(to_i2c_client(dev), tm); -+ -+} -+ -+static int isl12024_rtc_set_time(struct device *dev, struct rtc_time *tm) -+{ -+ return isl12024_set_datetime(to_i2c_client(dev), -+ tm, 1, ISL12024_CCR_BASE, 0); -+} -+ -+static int -+isl12024_rtc_proc(struct device *dev, struct seq_file *seq) -+{ -+ -+ /* Nothing to do */ -+ -+ return 0; -+} -+ -+static const struct rtc_class_ops isl12024_rtc_ops = { -+ .proc = isl12024_rtc_proc, -+ .read_time = isl12024_rtc_read_time, -+ .set_time = isl12024_rtc_set_time, -+}; -+ -+static int read_proc (char * page, char ** start, off_t off, int count, int * eof, void * data) -+{ -+ int i=0; -+ -+ printk("id: 0x"); -+ for(i=0;iaddr = addr; -+ new_client->adapter = adapter; -+ new_client->driver = &isl12024_driver; -+ new_client->flags = 0; -+ strcpy(new_client->name, DRV_NAME); -+ -+ if (kind < 0) { -+ rc = isl12024_i2c_validate_client(new_client); -+ if (rc < 0) -+ goto failout; -+ } -+ -+ rc = i2c_attach_client(new_client); -+ if (rc < 0) -+ goto failout; -+ -+ rtc = rtc_device_register(isl12024_driver.driver.name, -+ &new_client->dev, -+ &isl12024_rtc_ops, THIS_MODULE); -+ -+ if (IS_ERR(rtc)) { -+ printk("Error during rtc registration\n"); -+ rc = PTR_ERR(rtc); -+ goto failout; -+ } -+ -+ i2c_set_clientdata(new_client, rtc); -+ -+ /* Check for power failures and eventualy enable the osc */ -+ if ((err = isl12024_get_status(new_client, &sr)) == 0) { -+ if (sr & ISL12024_SR_RTCF) { -+ printk(KERN_INFO "power failure detected, " -+ "please set the clock\n"); -+ udelay(50); -+ isl12024_fix_osc(new_client); -+ } -+ } -+ else -+ printk(KERN_INFO "couldn't read status\n"); -+ -+ root_proc = proc_mkdir( "isl12024", 0 ); -+ entry_proc = create_proc_entry("id", S_IFREG | S_IRUGO | S_IWUSR, root_proc); -+ -+ if (entry_proc == NULL) -+ return -1; -+ -+ entry_proc->owner = THIS_MODULE; -+ entry_proc->read_proc = read_proc; -+ -+ /* read unique id from eeprom */ -+ isl12024_i2c_read_regs(new_client, ISL12024_REG_ID, buf_id, sizeof(buf_id)); -+ -+ -+ return 0; -+ -+ failout: -+ kfree(new_client); -+ return rc; -+} -+ -+static int -+isl12024_attach_adapter (struct i2c_adapter *adapter) -+{ -+ return i2c_probe(adapter, &addr_data, isl12024_probe); -+} -+ -+static int -+isl12024_detach_client(struct i2c_client *client) -+{ -+ int rc; -+ struct rtc_device *const rtc = i2c_get_clientdata(client); -+ -+ if (rtc) -+ rtc_device_unregister(rtc); -+ -+ rc = i2c_detach_client(client); -+ if (rc) -+ return rc; -+ -+ kfree(client); -+ -+ return 0; -+} -+ -+/* module init/exit */ -+ -+static int __init isl12024_init(void) -+{ -+ return i2c_add_driver(&isl12024_driver); -+} -+ -+static void __exit isl12024_exit(void) -+{ -+ i2c_del_driver(&isl12024_driver); -+} -+ -+MODULE_AUTHOR("Guillaume Ligneul "); -+MODULE_DESCRIPTION("Intersil ISL12024 driver"); -+MODULE_LICENSE("GPL"); -+MODULE_VERSION(DRV_VERSION); -+ -+module_init(isl12024_init); -+module_exit(isl12024_exit); -diff -Nru linux-2.6.26-officiel/include/i2c/isl12024.h /home/guilig/workspace/kernel-goobie-2.6.26/src/include/linux/i2c/isl12024.h ---- linux-2.6.26-officiel/include/i2c/isl12024.h 1970-01-01 01:00:00.000000000 +0100 -+++ /home/guilig/workspace/kernel-goobie-2.6.26/src/include/linux/i2c/isl12024.h 2008-10-21 10:36:19.000000000 +0200 -@@ -0,0 +1,93 @@ -+#ifndef ISL12024_H_ -+#define ISL12024_H_ -+ -+ -+ -+#define ISL12024_REG_SR 0x3F /* status register */ -+#define ISL12024_REG_Y2K 0x37 -+#define ISL12024_REG_DW 0x36 -+#define ISL12024_REG_YR 0x35 -+#define ISL12024_REG_MO 0x34 -+#define ISL12024_REG_DT 0x33 -+#define ISL12024_REG_HR 0x32 -+#define ISL12024_REG_MN 0x31 -+#define ISL12024_REG_SC 0x30 -+#define ISL12024_REG_DTR 0x13 -+#define ISL12024_REG_ATR 0x12 -+#define ISL12024_REG_INT 0x11 -+#define ISL12024_REG_0 0x10 -+#define ISL12024_REG_Y2K1 0x0F -+#define ISL12024_REG_DWA1 0x0E -+#define ISL12024_REG_YRA1 0x0D -+#define ISL12024_REG_MOA1 0x0C -+#define ISL12024_REG_DTA1 0x0B -+#define ISL12024_REG_HRA1 0x0A -+#define ISL12024_REG_MNA1 0x09 -+#define ISL12024_REG_SCA1 0x08 -+#define ISL12024_REG_Y2K0 0x07 -+#define ISL12024_REG_DWA0 0x06 -+#define ISL12024_REG_YRA0 0x05 -+#define ISL12024_REG_MOA0 0x04 -+#define ISL12024_REG_DTA0 0x03 -+#define ISL12024_REG_HRA0 0x02 -+#define ISL12024_REG_MNA0 0x01 -+#define ISL12024_REG_SCA0 0x00 -+ -+#define ISL12024_CCR_BASE 0x30 /* Base address of CCR */ -+#define ISL12024_ALM0_BASE 0x00 /* Base address of ALARM0 */ -+ -+#define ISL12024_SR_RTCF 0x01 /* Clock failure */ -+#define ISL12024_SR_WEL 0x02 /* Write Enable Latch */ -+#define ISL12024_SR_RWEL 0x04 /* Register Write Enable */ -+#define ISL12024_SR_AL0 0x20 /* Alarm 0 match */ -+ -+#define ISL12024_DTR_DTR0 0x01 -+#define ISL12024_DTR_DTR1 0x02 -+#define ISL12024_DTR_DTR2 0x04 -+ -+#define ISL12024_HR_MIL 0x80 /* Set in ccr.hour for 24 hr mode */ -+ -+#define ISL12024_INT_AL0E 0x20 /* Alarm 0 enable */ -+/* I2C ADDRESS */ -+#define ISL12024_I2C_ADDR 0xDE -+#define ISL12024_I2C_EEPROM_ADDR 0x57 -+/* device id section */ -+#define ISL12024_REG_ID 0x20 -+/* Register map */ -+/* rtc section */ -+//#define ISL12024_REG_MSB 0x00 -+//#define ISL12024_REG_SC 0x30 /* Seconds */ -+//#define ISL12024_REG_MN 0x31 /* Minutes */ -+//#define ISL12024_REG_HR 0x32 /* Hours */ -+#define ISL12024_REG_HR_MIL (1<<7) /* 24h/12h mode */ -+#define ISL12024_REG_HR_PM (1<<5) /* PM/AM bit in 12h mode */ -+//#define ISL12024_REG_DT 0x33 /* Date */ -+//#define ISL12024_REG_MO 0x34 /* Month */ -+//#define ISL12024_REG_YR 0x35 /* Year */ -+//#define ISL12024_REG_DW 0x36 -+//#define ISL12024_REG_Y2K 0x37 -+#define ISL12024_RTC_SECTION_LEN 8 -+ -+ -+ -+/* control/status section */ -+//#define ISL12024_REG_SR 0x3F -+//#define ISL12024_REG_SR_BAT (1<<7) /* battery */ -+//#define ISL12024_REG_SR_AL1 (1<<6) /* alarm 0 */ -+//#define ISL12024_REG_SR_AL0 (1<<5) /* alarm 1 */ -+//#define ISL12024_REG_SR_OSCF (1<<4) /* oscillator fail */ -+//#define ISL12024_REG_SR_RWEL (1<<2) /* register write enable latch */ -+//#define ISL12024_REG_SR_WEL (1<<1) /* write enable latch */ -+//#define ISL12024_REG_SR_RTCF (1<<0) /* rtc fail */ -+//#define ISL12024_REG_INT 0x11 -+ -+#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 -+ -+#endif /*ISL12024_H_*/ diff --git a/packages/linux/linux-2.6.26/boc01/005-081217-isl12024.patch b/packages/linux/linux-2.6.26/boc01/005-081217-isl12024.patch new file mode 100644 index 0000000000..bcbc2b35db --- /dev/null +++ b/packages/linux/linux-2.6.26/boc01/005-081217-isl12024.patch @@ -0,0 +1,940 @@ +Index: linux-2.6.26-NEW/drivers/i2c/chips/isl12024-eeprom.c +=================================================================== +--- /dev/null ++++ linux-2.6.26-NEW/drivers/i2c/chips/isl12024-eeprom.c +@@ -0,0 +1,254 @@ ++/* ++ * Intersil ISL12024 EEPROM class driver ++ * ++ * ++ * Copyright (C) 2007, CenoSYS (www.cenosys.com). ++ * Guillaume Ligneul ++ * Guillaume.ligneul@gmail.com ++ * ++ * Code is based on eeprom.c ++ * ++ * This software program is licensed subject to the GNU General Public License ++ * (GPL).Version 2,June 1991, available at http://www.fsf.org/copyleft/gpl.html ++ */ ++ ++#include ++#include ++#include ++//#include ++//#include ++#include ++#include ++#include ++ ++/* Addresses to scan */ ++static const unsigned short normal_i2c[] = { ISL12024_I2C_EEPROM_ADDR, I2C_CLIENT_END }; ++ ++/* Insmod parameters */ ++I2C_CLIENT_INSMOD_1(eeprom); ++ ++ ++/* Size of EEPROM in bytes */ ++#define EEPROM_SIZE 4096 ++ ++/* Each client has this additional data */ ++struct eeprom_data { ++ struct i2c_client client; ++ struct mutex update_lock; ++}; ++ ++int ++isl12024_i2c_read(struct i2c_client *client, u8 reg, u8 buf[], ++ unsigned len) ++{ ++ int ret; ++ u8 dt_addr[2]; ++ ++ struct i2c_msg msgs[2] = { ++ { ++ .addr = client->addr, ++ .flags = 0, ++ .len = 2, ++ .buf = dt_addr, ++ }, ++ { ++ .addr = client->addr, ++ .flags = I2C_M_RD, ++ .len = len , ++ .buf = buf , ++ }, ++ }; ++ ++ dt_addr[0] = 0; ++ dt_addr[1] = reg; ++ ++ ret = i2c_transfer(client->adapter, msgs, 2); ++ if ( ret < 0) { ++ dev_err(&client->dev, "read error\n"); ++ return -EIO; ++ } ++ return ret; ++} ++ ++ ++int ++isl12024_i2c_write(struct i2c_client *client, u8 reg, u8 const buf[], ++ unsigned len) ++{ ++ int ret; ++ u8 i2c_buf[EEPROM_SIZE]; ++ ++ struct i2c_msg msgs[1] = { ++ { ++ .addr = client->addr, ++ .flags = 0, ++ .len = len+2, ++ .buf = i2c_buf, ++ }, ++ }; ++ ++ i2c_buf[0] = 0; ++ i2c_buf[1] = reg; ++ ++ ++ memcpy(&i2c_buf[2], &buf[0], len ); ++ ++ ++ ret = i2c_transfer(client->adapter, msgs, 1); ++ printk(KERN_INFO "i2c_transfer %d\n",ret); ++ return ret; ++} ++static int eeprom_attach_adapter(struct i2c_adapter *adapter); ++static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind); ++static int eeprom_detach_client(struct i2c_client *client); ++ ++/* This is the driver that will be inserted */ ++static struct i2c_driver eeprom_driver = { ++ .driver = { ++ .name = "isl12024-eeprom", ++ }, ++ .attach_adapter = eeprom_attach_adapter, ++ .detach_client = eeprom_detach_client, ++}; ++ ++static ssize_t eeprom_read(struct kobject *kobj, struct bin_attribute *bin_attr, ++ char *buf, loff_t off, size_t count) ++{ ++ struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj)); ++ struct eeprom_data *data = i2c_get_clientdata(client); ++ int rc; ++ ++ mutex_lock(&data->update_lock); ++ ++ if (off >= EEPROM_SIZE) ++ return 0; ++ ++ if (off + count > EEPROM_SIZE) ++ count = EEPROM_SIZE - off; ++ ++ rc = isl12024_i2c_read(client,0,buf,EEPROM_SIZE); ++ ++ if (rc < 0){ ++ mutex_unlock(&data->update_lock); ++ return -EIO; ++ } ++ ++ mutex_unlock(&data->update_lock); ++ return count; ++} ++ ++static ssize_t eeprom_write(struct kobject *kobj, struct bin_attribute *attr, ++ char *buf, loff_t off, size_t count) ++{ ++ struct i2c_client *client = kobj_to_i2c_client(kobj); ++ struct eeprom_data *data = i2c_get_clientdata(client); ++ ++ if (off >= 256) ++ return -ENOSPC; ++ ++ if (off + count > 256) ++ count = 256 - off; ++ ++ mutex_unlock(&data->update_lock); ++ if (isl12024_i2c_write(client, off, buf, count) < 0) ++ { ++ mutex_unlock(&data->update_lock); ++ return -EIO; ++ } ++ ++ mutex_unlock(&data->update_lock); ++ return count; ++} ++ ++static struct bin_attribute eeprom_attr = { ++ .attr = { ++ .name = "eeprom", ++ .mode = S_IRUGO, ++ }, ++ .size = EEPROM_SIZE, ++ .read = eeprom_read, ++ .write= eeprom_write, ++}; ++ ++static int eeprom_attach_adapter(struct i2c_adapter *adapter) ++{ ++ return i2c_probe(adapter, &addr_data, eeprom_detect); ++} ++ ++/* This function is called by i2c_probe */ ++static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind) ++{ ++ struct i2c_client *new_client; ++ struct eeprom_data *data; ++ int err = 0; ++ ++ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE_DATA ++ | I2C_FUNC_SMBUS_BYTE)) ++ goto exit; ++ ++ if (!(data = kzalloc(sizeof(struct eeprom_data), GFP_KERNEL))) { ++ err = -ENOMEM; ++ goto exit; ++ } ++ ++ new_client = &data->client; ++ i2c_set_clientdata(new_client, data); ++ new_client->addr = address; ++ new_client->adapter = adapter; ++ new_client->driver = &eeprom_driver; ++ new_client->flags = 0; ++ ++ strlcpy(new_client->name, "isl12024-eeprom", I2C_NAME_SIZE); ++ mutex_init(&data->update_lock); ++ ++ /* Tell the I2C layer a new client has arrived */ ++ if ((err = i2c_attach_client(new_client))) ++ goto exit_kfree; ++ ++ /* create the sysfs eeprom file */ ++ err = sysfs_create_bin_file(&new_client->dev.kobj, &eeprom_attr); ++ if (err) ++ goto exit_detach; ++ ++ return 0; ++ ++exit_detach: ++ i2c_detach_client(new_client); ++exit_kfree: ++ kfree(data); ++exit: ++ return err; ++} ++ ++static int eeprom_detach_client(struct i2c_client *client) ++{ ++ int err; ++ ++ sysfs_remove_bin_file(&client->dev.kobj, &eeprom_attr); ++ ++ err = i2c_detach_client(client); ++ if (err) ++ return err; ++ ++ kfree(i2c_get_clientdata(client)); ++ ++ return 0; ++} ++ ++static int __init eeprom_init(void) ++{ ++ return i2c_add_driver(&eeprom_driver); ++} ++ ++static void __exit eeprom_exit(void) ++{ ++ i2c_del_driver(&eeprom_driver); ++} ++ ++ ++MODULE_AUTHOR("Guillaume Ligneul "); ++MODULE_DESCRIPTION("I2C Intersil12024 EEPROM driver"); ++MODULE_LICENSE("GPL"); ++ ++module_init(eeprom_init); ++module_exit(eeprom_exit); +Index: linux-2.6.26-NEW/drivers/i2c/chips/Kconfig +=================================================================== +--- linux-2.6.26-NEW.orig/drivers/i2c/chips/Kconfig ++++ linux-2.6.26-NEW/drivers/i2c/chips/Kconfig +@@ -14,6 +14,15 @@ config DS1682 + This driver can also be built as a module. If so, the module + will be called ds1682. + ++config ISL12024EEPROM ++ tristate "Intersil 12024 EEPROM" ++ depends on RTC_DRV_ISL12024 ++ help ++ If you say yes here you get support for Intersil12024 EEPROM. ++ ++ This driver can also be built as a module. If so, the module ++ will be called isl12024-eeprom. ++ + config SENSORS_EEPROM + tristate "EEPROM reader" + depends on EXPERIMENTAL +Index: linux-2.6.26-NEW/drivers/i2c/chips/Makefile +=================================================================== +--- linux-2.6.26-NEW.orig/drivers/i2c/chips/Makefile ++++ linux-2.6.26-NEW/drivers/i2c/chips/Makefile +@@ -9,6 +9,8 @@ + # * I/O expander drivers go to drivers/gpio + # + ++ ++obj-$(CONFIG_ISL12024EEPROM) += isl12024-eeprom.o + obj-$(CONFIG_DS1682) += ds1682.o + obj-$(CONFIG_SENSORS_EEPROM) += eeprom.o + obj-$(CONFIG_SENSORS_MAX6875) += max6875.o +Index: linux-2.6.26-NEW/drivers/rtc/Kconfig +=================================================================== +--- linux-2.6.26-NEW.orig/drivers/rtc/Kconfig ++++ linux-2.6.26-NEW/drivers/rtc/Kconfig +@@ -124,6 +124,12 @@ comment "I2C RTC drivers" + + if I2C + ++config RTC_DRV_ISL12024 ++ tristate "Intersil 12024 RTC/ UniqueID" ++ help ++ If you say yes .... ++ This driver can also be built as a module. ++ + config RTC_DRV_DS1307 + tristate "Dallas/Maxim DS1307/37/38/39/40, ST M41T00" + help +Index: linux-2.6.26-NEW/drivers/rtc/Makefile +=================================================================== +--- linux-2.6.26-NEW.orig/drivers/rtc/Makefile ++++ linux-2.6.26-NEW/drivers/rtc/Makefile +@@ -33,6 +33,7 @@ obj-$(CONFIG_RTC_DRV_DS1742) += rtc-ds17 + obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o + obj-$(CONFIG_RTC_DRV_FM3130) += rtc-fm3130.o + obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o ++obj-$(CONFIG_RTC_DRV_ISL12024) += rtc-isl12024.o + obj-$(CONFIG_RTC_DRV_M41T80) += rtc-m41t80.o + obj-$(CONFIG_RTC_DRV_M48T59) += rtc-m48t59.o + obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o +Index: linux-2.6.26-NEW/drivers/rtc/rtc-isl12024.c +=================================================================== +--- /dev/null ++++ linux-2.6.26-NEW/drivers/rtc/rtc-isl12024.c +@@ -0,0 +1,516 @@ ++/* ++ * Intersil ISL12024 class driver ++ * ++ * ++ * Copyright (C) 2007, CenoSYS (www.cenosys.com). ++ * Guillaume Ligneul ++ * Guillaume.ligneul@gmail.com ++ * ++ * This software program is licensed subject to the GNU General Public License ++ * (GPL).Version 2,June 1991, available at http://www.fsf.org/copyleft/gpl.html ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++#define DBG 1 ++#undef DBG ++ ++static u8 buf_id[ISL12024_RTC_SECTION_LEN] = { 0 ,}; ++ ++#define DRV_NAME "isl12024" ++#define DRV_VERSION "0.1" ++ ++/* i2c configuration */ ++ ++static const unsigned short normal_i2c[] = { ++ ISL12024_I2C_ADDR >>1, I2C_CLIENT_END ++}; ++I2C_CLIENT_INSMOD; ++ ++/* Procfs management */ ++static struct proc_dir_entry * root_proc = NULL; ++static struct proc_dir_entry * entry_proc = NULL; ++static int read_proc (char * page, char ** start, off_t off, int count, int * eof, void * data); ++ ++static int isl12024_get_status(struct i2c_client *client, unsigned char *sr); ++static int isl12024_fix_osc(struct i2c_client *client); ++ ++ ++static int isl12024_attach_adapter(struct i2c_adapter *adapter); ++static int isl12024_detach_client(struct i2c_client *client); ++ ++// To debug (may be add in includ/linux/i2c-id.h) ++#define I2C_DRIVERID_ISL12024 97 ++ ++static struct i2c_driver isl12024_driver = { ++ .driver = { ++ .name = DRV_NAME, ++ }, ++ .id = I2C_DRIVERID_ISL12024, ++ .attach_adapter = &isl12024_attach_adapter, ++ .detach_client = &isl12024_detach_client, ++}; ++ ++int ++isl12024_i2c_read_regs(struct i2c_client *client, u8 reg, u8 buf[], ++ unsigned len) ++{ ++ int ret; ++ u8 dt_addr[2]; ++ ++ struct i2c_msg msgs[2] = { ++ { ++ .addr = client->addr, ++ .flags = 0, ++ .len = 2, ++ .buf = dt_addr, ++ }, ++ { ++ .addr = client->addr, ++ .flags = I2C_M_RD, ++ .len = len , ++ .buf = buf , ++ }, ++ }; ++ ++ dt_addr[0] = 0; ++ dt_addr[1] = reg; ++ ++ ret = i2c_transfer(client->adapter, msgs, 2); ++ if ( ret < 0) { ++ dev_err(&client->dev, "read error\n"); ++ return -EIO; ++ } ++ return ret; ++} ++ ++EXPORT_SYMBOL(isl12024_i2c_read_regs); ++ ++ ++int ++isl12024_i2c_set_regs(struct i2c_client *client, u8 reg, u8 const buf[], ++ unsigned len) ++{ ++ int ret; ++ u8 i2c_buf[10]; ++ ++ struct i2c_msg msgs[1] = { ++ { ++ .addr = client->addr, ++ .flags = 0, ++ .len = len+2, ++ .buf = i2c_buf, ++ }, ++ }; ++ ++ i2c_buf[0] = 0; ++ i2c_buf[1] = reg; ++ ++ ++ memcpy(&i2c_buf[2], &buf[0], len ); ++ ++ ++ ret = i2c_transfer(client->adapter, msgs, 1); ++ printk(KERN_INFO "i2c_transfer %d\n",ret); ++ return ret; ++} ++ ++EXPORT_SYMBOL(isl12024_i2c_set_regs); ++ ++static int isl12024_i2c_validate_client(struct i2c_client *client) ++{ ++ u8 regs[ISL12024_RTC_SECTION_LEN] = { 0, }; ++ u8 zero_mask[ISL12024_RTC_SECTION_LEN] = { ++ 0x80, 0x80, 0x40, 0xc0, 0xe0, 0x00, 0xf8, 0xc6 ++ }; ++ ++ int i; ++ int ret; ++ ++ ret = isl12024_i2c_read_regs(client, ISL12024_REG_SC, regs, ISL12024_RTC_SECTION_LEN); ++ ++ if (ret < 0) ++ return ret; ++ ++ for (i = 0; i < ISL12024_RTC_SECTION_LEN; ++i) { ++ if (regs[i] & zero_mask[i]) /* check if bits are cleared */ ++ return -ENODEV; ++ ++ } ++ ++ return 0; ++} ++ ++static int isl12024_read_time(struct i2c_client *client, ++ struct rtc_time *tm) ++{ ++ unsigned char sr; ++ int err; ++ u8 regs[ISL12024_RTC_SECTION_LEN] = { 0, }; ++ ++ printk(KERN_INFO "%s\n ",__FUNCTION__ ); ++ ++ ++ if (isl12024_get_status(client, &sr) < 0) { ++ dev_err(&client->dev, "%s: reading SR failed\n", __func__); ++ return -EIO; ++ } ++ ++ err = isl12024_i2c_read_regs(client, ISL12024_REG_SC, regs, ISL12024_RTC_SECTION_LEN); ++ ++#ifdef DBG ++ int i; ++ for(i=0; idev, "%s: reading RTC section failed\n", ++ __func__); ++ return sr; ++ } ++ ++ tm->tm_sec = BCD2BIN(regs[0]); ++ tm->tm_min = BCD2BIN(regs[1]); ++ ++ { /* HR field has a more complex interpretation */ ++ const u8 _hr = regs[2]; ++ if (_hr & ISL12024_REG_HR_MIL) /* 24h format */ ++ tm->tm_hour = BCD2BIN(_hr & 0x3f); ++ else { // 12h format ++ tm->tm_hour = BCD2BIN(_hr & 0x1f); ++ if (_hr & ISL12024_REG_HR_PM) /* PM flag set */ ++ tm->tm_hour += 12; ++ } ++ } ++ ++ tm->tm_mday = BCD2BIN(regs[3]); ++ tm->tm_mon = BCD2BIN(regs[4]); ++ tm->tm_year = BCD2BIN(regs[5]) + 100; ++ tm->tm_wday = BCD2BIN(regs[6]); ++ ++ return rtc_valid_tm(tm); ++} ++ ++static int isl12024_get_status(struct i2c_client *client, unsigned char *sr) ++{ ++ static unsigned char sr_addr[2] = { 0, ISL12024_REG_SR }; ++ ++ struct i2c_msg msgs[] = { ++ { client->addr, 0, 2, sr_addr }, /* setup read ptr */ ++ { client->addr, I2C_M_RD, 1, sr }, /* read status */ ++ }; ++ ++ /* read status register */ ++ if (i2c_transfer(client->adapter, &msgs[0], 2) != 2) { ++ dev_err(&client->dev, "%s: read error\n", __func__); ++ return -EIO; ++ } ++ ++ return 0; ++} ++ ++static int isl12024_set_datetime(struct i2c_client *client, struct rtc_time *tm, ++ int datetoo, u8 reg_base, unsigned char alm_enable) ++{ ++ int i, xfer, nbytes; ++ unsigned char buf[8]; ++ unsigned char rdata[10] = { 0, reg_base }; ++ ++ static const unsigned char wel[3] = { 0, ISL12024_REG_SR, ++ ISL12024_SR_WEL }; ++ ++ static const unsigned char rwel[3] = { 0, ISL12024_REG_SR, ++ ISL12024_SR_WEL | ISL12024_SR_RWEL }; ++ ++ static const unsigned char diswe[3] = { 0, ISL12024_REG_SR, 0 }; ++ ++ dev_dbg(&client->dev, ++ "%s: secs=%d, mins=%d, hours=%d\n", ++ __func__, ++ tm->tm_sec, tm->tm_min, tm->tm_hour); ++ ++ 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) | ISL12024_HR_MIL; ++ ++ /* should we also set the date? */ ++ if (datetoo) { ++ dev_dbg(&client->dev, ++ "%s: mday=%d, mon=%d, year=%d, wday=%d\n", ++ __func__, ++ tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); ++ ++ buf[CCR_MDAY] = BIN2BCD(tm->tm_mday); ++ ++ /* month, 1 - 12 */ ++ buf[CCR_MONTH] = BIN2BCD(tm->tm_mon); ++ ++ /* year, since the rtc epoch*/ ++ buf[CCR_YEAR] = BIN2BCD(tm->tm_year % 100); ++ buf[CCR_WDAY] = tm->tm_wday & 0x07; ++ buf[CCR_Y2K] = BIN2BCD(tm->tm_year / 100); ++ } ++ ++ /* If writing alarm registers, set compare bits on registers 0-4 */ ++ if (reg_base < ISL12024_CCR_BASE) ++ for (i = 0; i <= 4; i++) ++ buf[i] |= 0x80; ++ ++ /* this sequence is required to unlock the chip */ ++ if ((xfer = i2c_master_send(client, wel, 3)) != 3) { ++ dev_err(&client->dev, "%s: wel - %d\n", __func__, xfer); ++ return -EIO; ++ } ++ ++ if ((xfer = i2c_master_send(client, rwel, 3)) != 3) { ++ dev_err(&client->dev, "%s: rwel - %d\n", __func__, xfer); ++ return -EIO; ++ } ++ ++ ++ /* write register's data */ ++ if (datetoo) ++ nbytes = 8; ++ else ++ nbytes = 3; ++ for (i = 0; i < nbytes; i++) ++ rdata[2+i] = buf[i]; ++ ++ xfer = i2c_master_send(client, rdata, nbytes+2); ++ if (xfer != nbytes+2) { ++ dev_err(&client->dev, ++ "%s: result=%d addr=%02x, data=%02x\n", ++ __func__, ++ xfer, rdata[1], rdata[2]); ++ return -EIO; ++ } ++ ++ /* If we wrote to the nonvolatile region, wait 10msec for write cycle*/ ++ if (reg_base < ISL12024_CCR_BASE) { ++ unsigned char al0e[3] = { 0, ISL12024_REG_INT, 0 }; ++ ++ msleep(10); ++ ++ /* ...and set or clear the AL0E bit in the INT register */ ++ ++ /* Need to set RWEL again as the write has cleared it */ ++ xfer = i2c_master_send(client, rwel, 3); ++ if (xfer != 3) { ++ dev_err(&client->dev, ++ "%s: aloe rwel - %d\n", ++ __func__, ++ xfer); ++ return -EIO; ++ } ++ ++ if (alm_enable) ++ al0e[2] = ISL12024_INT_AL0E; ++ ++ xfer = i2c_master_send(client, al0e, 3); ++ if (xfer != 3) { ++ dev_err(&client->dev, ++ "%s: al0e - %d\n", ++ __func__, ++ xfer); ++ return -EIO; ++ } ++ ++ /* and wait 10msec again for this write to complete */ ++ msleep(10); ++ } ++ ++ /* disable further writes */ ++ if ((xfer = i2c_master_send(client, diswe, 3)) != 3) { ++ dev_err(&client->dev, "%s: diswe - %d\n", __func__, xfer); ++ return -EIO; ++ } ++ ++ return 0; ++} ++ ++static int isl12024_fix_osc(struct i2c_client *client) ++{ ++ int err; ++ struct rtc_time tm; ++ ++ tm.tm_hour = tm.tm_min = tm.tm_sec = 0; ++ ++ err = isl12024_set_datetime(client, &tm, 0, ISL12024_CCR_BASE, 0); ++ if (err < 0) ++ printk(KERN_INFO "unable to restart the oscillator\n"); ++ ++ return err; ++} ++ ++static int isl12024_rtc_read_time(struct device *dev, struct rtc_time *tm) ++{ ++ return isl12024_read_time(to_i2c_client(dev), tm); ++ ++} ++ ++static int isl12024_rtc_set_time(struct device *dev, struct rtc_time *tm) ++{ ++ return isl12024_set_datetime(to_i2c_client(dev), ++ tm, 1, ISL12024_CCR_BASE, 0); ++} ++ ++static int ++isl12024_rtc_proc(struct device *dev, struct seq_file *seq) ++{ ++ ++ /* Nothing to do */ ++ ++ return 0; ++} ++ ++static const struct rtc_class_ops isl12024_rtc_ops = { ++ .proc = isl12024_rtc_proc, ++ .read_time = isl12024_rtc_read_time, ++ .set_time = isl12024_rtc_set_time, ++}; ++ ++static int read_proc (char * page, char ** start, off_t off, int count, int * eof, void * data) ++{ ++ int i=0; ++ ++ printk("id: 0x"); ++ for(i=0;iaddr = addr; ++ new_client->adapter = adapter; ++ new_client->driver = &isl12024_driver; ++ new_client->flags = 0; ++ strcpy(new_client->name, DRV_NAME); ++ ++ if (kind < 0) { ++ rc = isl12024_i2c_validate_client(new_client); ++ if (rc < 0) ++ goto failout; ++ } ++ ++ rc = i2c_attach_client(new_client); ++ if (rc < 0) ++ goto failout; ++ ++ rtc = rtc_device_register(isl12024_driver.driver.name, ++ &new_client->dev, ++ &isl12024_rtc_ops, THIS_MODULE); ++ ++ if (IS_ERR(rtc)) { ++ printk("Error during rtc registration\n"); ++ rc = PTR_ERR(rtc); ++ goto failout; ++ } ++ ++ i2c_set_clientdata(new_client, rtc); ++ ++ /* Check for power failures and eventualy enable the osc */ ++ if ((err = isl12024_get_status(new_client, &sr)) == 0) { ++ if (sr & ISL12024_SR_RTCF) { ++ printk(KERN_INFO "power failure detected, " ++ "please set the clock\n"); ++ udelay(50); ++ isl12024_fix_osc(new_client); ++ } ++ } ++ else ++ printk(KERN_INFO "couldn't read status\n"); ++ ++ root_proc = proc_mkdir( "isl12024", 0 ); ++ entry_proc = create_proc_entry("id", S_IFREG | S_IRUGO | S_IWUSR, root_proc); ++ ++ if (entry_proc == NULL) ++ return -1; ++ ++ entry_proc->owner = THIS_MODULE; ++ entry_proc->read_proc = read_proc; ++ ++ /* read unique id from eeprom */ ++ isl12024_i2c_read_regs(new_client, ISL12024_REG_ID, buf_id, sizeof(buf_id)); ++ ++ ++ return 0; ++ ++ failout: ++ kfree(new_client); ++ return rc; ++} ++ ++static int ++isl12024_attach_adapter (struct i2c_adapter *adapter) ++{ ++ return i2c_probe(adapter, &addr_data, isl12024_probe); ++} ++ ++static int ++isl12024_detach_client(struct i2c_client *client) ++{ ++ int rc; ++ struct rtc_device *const rtc = i2c_get_clientdata(client); ++ ++ if (rtc) ++ rtc_device_unregister(rtc); ++ ++ rc = i2c_detach_client(client); ++ if (rc) ++ return rc; ++ ++ kfree(client); ++ ++ return 0; ++} ++ ++/* module init/exit */ ++ ++static int __init isl12024_init(void) ++{ ++ return i2c_add_driver(&isl12024_driver); ++} ++ ++static void __exit isl12024_exit(void) ++{ ++ i2c_del_driver(&isl12024_driver); ++} ++ ++MODULE_AUTHOR("Guillaume Ligneul "); ++MODULE_DESCRIPTION("Intersil ISL12024 driver"); ++MODULE_LICENSE("GPL"); ++MODULE_VERSION(DRV_VERSION); ++ ++module_init(isl12024_init); ++module_exit(isl12024_exit); +Index: linux-2.6.26-NEW/include/i2c/isl12024.h +=================================================================== +--- /dev/null ++++ linux-2.6.26-NEW/include/i2c/isl12024.h +@@ -0,0 +1,93 @@ ++#ifndef ISL12024_H_ ++#define ISL12024_H_ ++ ++ ++ ++#define ISL12024_REG_SR 0x3F /* status register */ ++#define ISL12024_REG_Y2K 0x37 ++#define ISL12024_REG_DW 0x36 ++#define ISL12024_REG_YR 0x35 ++#define ISL12024_REG_MO 0x34 ++#define ISL12024_REG_DT 0x33 ++#define ISL12024_REG_HR 0x32 ++#define ISL12024_REG_MN 0x31 ++#define ISL12024_REG_SC 0x30 ++#define ISL12024_REG_DTR 0x13 ++#define ISL12024_REG_ATR 0x12 ++#define ISL12024_REG_INT 0x11 ++#define ISL12024_REG_0 0x10 ++#define ISL12024_REG_Y2K1 0x0F ++#define ISL12024_REG_DWA1 0x0E ++#define ISL12024_REG_YRA1 0x0D ++#define ISL12024_REG_MOA1 0x0C ++#define ISL12024_REG_DTA1 0x0B ++#define ISL12024_REG_HRA1 0x0A ++#define ISL12024_REG_MNA1 0x09 ++#define ISL12024_REG_SCA1 0x08 ++#define ISL12024_REG_Y2K0 0x07 ++#define ISL12024_REG_DWA0 0x06 ++#define ISL12024_REG_YRA0 0x05 ++#define ISL12024_REG_MOA0 0x04 ++#define ISL12024_REG_DTA0 0x03 ++#define ISL12024_REG_HRA0 0x02 ++#define ISL12024_REG_MNA0 0x01 ++#define ISL12024_REG_SCA0 0x00 ++ ++#define ISL12024_CCR_BASE 0x30 /* Base address of CCR */ ++#define ISL12024_ALM0_BASE 0x00 /* Base address of ALARM0 */ ++ ++#define ISL12024_SR_RTCF 0x01 /* Clock failure */ ++#define ISL12024_SR_WEL 0x02 /* Write Enable Latch */ ++#define ISL12024_SR_RWEL 0x04 /* Register Write Enable */ ++#define ISL12024_SR_AL0 0x20 /* Alarm 0 match */ ++ ++#define ISL12024_DTR_DTR0 0x01 ++#define ISL12024_DTR_DTR1 0x02 ++#define ISL12024_DTR_DTR2 0x04 ++ ++#define ISL12024_HR_MIL 0x80 /* Set in ccr.hour for 24 hr mode */ ++ ++#define ISL12024_INT_AL0E 0x20 /* Alarm 0 enable */ ++/* I2C ADDRESS */ ++#define ISL12024_I2C_ADDR 0xDE ++#define ISL12024_I2C_EEPROM_ADDR 0x57 ++/* device id section */ ++#define ISL12024_REG_ID 0x20 ++/* Register map */ ++/* rtc section */ ++//#define ISL12024_REG_MSB 0x00 ++//#define ISL12024_REG_SC 0x30 /* Seconds */ ++//#define ISL12024_REG_MN 0x31 /* Minutes */ ++//#define ISL12024_REG_HR 0x32 /* Hours */ ++#define ISL12024_REG_HR_MIL (1<<7) /* 24h/12h mode */ ++#define ISL12024_REG_HR_PM (1<<5) /* PM/AM bit in 12h mode */ ++//#define ISL12024_REG_DT 0x33 /* Date */ ++//#define ISL12024_REG_MO 0x34 /* Month */ ++//#define ISL12024_REG_YR 0x35 /* Year */ ++//#define ISL12024_REG_DW 0x36 ++//#define ISL12024_REG_Y2K 0x37 ++#define ISL12024_RTC_SECTION_LEN 8 ++ ++ ++ ++/* control/status section */ ++//#define ISL12024_REG_SR 0x3F ++//#define ISL12024_REG_SR_BAT (1<<7) /* battery */ ++//#define ISL12024_REG_SR_AL1 (1<<6) /* alarm 0 */ ++//#define ISL12024_REG_SR_AL0 (1<<5) /* alarm 1 */ ++//#define ISL12024_REG_SR_OSCF (1<<4) /* oscillator fail */ ++//#define ISL12024_REG_SR_RWEL (1<<2) /* register write enable latch */ ++//#define ISL12024_REG_SR_WEL (1<<1) /* write enable latch */ ++//#define ISL12024_REG_SR_RTCF (1<<0) /* rtc fail */ ++//#define ISL12024_REG_INT 0x11 ++ ++#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 ++ ++#endif /*ISL12024_H_*/ diff --git a/packages/linux/linux-2.6.26/boc01/006-081105-at24c32.patch b/packages/linux/linux-2.6.26/boc01/006-081105-at24c32.patch deleted file mode 100644 index 1cd70feb4a..0000000000 --- a/packages/linux/linux-2.6.26/boc01/006-081105-at24c32.patch +++ /dev/null @@ -1,284 +0,0 @@ -diff -Nru linux-2.6.26-officiel/drivers/i2c/chips/at24c32.c /home/guilig/workspace/kernel-goobie-2.6.26/src/drivers/i2c/chips/at24c32.c ---- linux-2.6.26-officiel/drivers/i2c/chips/at24c32.c 1970-01-01 01:00:00.000000000 +0100 -+++ /home/guilig/workspace/kernel-goobie-2.6.26/src/drivers/i2c/chips/at24c32.c 2008-11-06 10:45:30.000000000 +0100 -@@ -0,0 +1,268 @@ -+/* -+ * at24c32.c - Based on eeprom.c -+ * -+ * Copyright (C) 2007, CenoSYS (www.cenosys.com). -+ * Guillaume Ligneul -+ * Guillaume.ligneul@gmail.com -+ * -+ * Code is based on eeprom.c -+ * -+ * This software program is licensed subject to the GNU General Public License -+ * (GPL).Version 2,June 1991, available at http://www.fsf.org/copyleft/gpl.html -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/* Addresses to scan */ -+static const unsigned short normal_i2c[] = { 0x50, 0x51, 0x52, 0x53, 0x54, -+ 0x55, 0x56, I2C_CLIENT_END }; -+ -+/* Insmod parameters */ -+I2C_CLIENT_INSMOD_1(eeprom); -+ -+ -+/* Size of EEPROM in bytes */ -+#define EEPROM_SIZE 32768 -+ -+/* possible types of eeprom devices */ -+enum eeprom_nature { -+ UNKNOWN, -+ VAIO, -+}; -+ -+/* Each client has this additional data */ -+struct eeprom_data { -+ struct i2c_client client; -+ struct mutex update_lock; -+ u8 valid; /* bitfield, bit!=0 if slice is valid */ -+ unsigned long last_updated[8]; /* In jiffies, 8 slices */ -+ u8 data[EEPROM_SIZE]; /* Register values */ -+ enum eeprom_nature nature; -+}; -+ -+ -+static int eeprom_attach_adapter(struct i2c_adapter *adapter); -+static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind); -+static int eeprom_detach_client(struct i2c_client *client); -+ -+/* This is the driver that will be inserted */ -+static struct i2c_driver eeprom_driver = { -+ .driver = { -+ .name = "eeprom", -+ }, -+ .attach_adapter = eeprom_attach_adapter, -+ .detach_client = eeprom_detach_client, -+}; -+ -+static ssize_t eeprom_write(struct kobject *kobj, struct bin_attribute *bin_attr, -+ char *buf, loff_t off, size_t count) -+{ -+ struct i2c_client *client = kobj_to_i2c_client(kobj); -+ struct eeprom_data *data = i2c_get_clientdata(client); -+ int ret; -+ u8 i2c_buf[256]; -+ -+ if (off >= 32) -+ return -ENOSPC; -+ -+ if (off + count > 32) -+ count = 32 - off; -+ -+ mutex_unlock(&data->update_lock); -+ -+ struct i2c_msg msgs[1] = { -+ { -+ .addr = client->addr, -+ .flags = 0, -+ .len = count+2, -+ .buf = i2c_buf, -+ }, -+ }; -+ -+ i2c_buf[0] = 0; -+ i2c_buf[1] = off; -+ -+ -+ memcpy(&i2c_buf[2], &buf[0], count ); -+ -+ -+ ret = i2c_transfer(client->adapter, msgs, 1); -+ -+ if(ret<0) -+ { -+ mutex_unlock(&data->update_lock); -+ return -EIO; -+ } -+ -+ mutex_unlock(&data->update_lock); -+ return count; -+} -+ -+int -+i2c_read(struct i2c_client *client, u8 reg, u8 buf[], -+ unsigned len) -+{ -+ int ret; -+ u8 dt_addr[2]; -+ -+ struct i2c_msg msgs[2] = { -+ { -+ .addr = client->addr, -+ .flags = 0, -+ .len = 2, -+ .buf = dt_addr, -+ }, -+ { -+ .addr = client->addr, -+ .flags = I2C_M_RD, -+ .len = len , -+ .buf = buf , -+ }, -+ }; -+ -+ dt_addr[0] = 0; -+ dt_addr[1] = reg; -+ -+ ret = i2c_transfer(client->adapter, msgs, 2); -+ if ( ret < 0) { -+ dev_err(&client->dev, "read error\n"); -+ return -EIO; -+ } -+ return ret; -+} -+ -+static ssize_t eeprom_read(struct kobject *kobj, struct bin_attribute *bin_attr, -+ char *buf, loff_t off, size_t count) -+{ -+ struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj)); -+ struct eeprom_data *data = i2c_get_clientdata(client); -+ int rc; -+ -+ mutex_lock(&data->update_lock); -+ -+ if (off >= EEPROM_SIZE) -+ return 0; -+ -+ if (off + count > EEPROM_SIZE) -+ count = EEPROM_SIZE - off; -+ -+ rc = i2c_read(client,off,buf,count); -+ if (rc < 0){ -+ mutex_unlock(&data->update_lock); -+ return -EIO; -+ } -+ -+ mutex_unlock(&data->update_lock); -+ return count; -+} -+ -+static struct bin_attribute eeprom_attr = { -+ .attr = { -+ .name = "eeprom", -+ .mode = S_IRUGO, -+ }, -+ .size = EEPROM_SIZE, -+ .read = eeprom_read, -+ .write = eeprom_write, -+ -+}; -+ -+static int eeprom_attach_adapter(struct i2c_adapter *adapter) -+{ -+ return i2c_probe(adapter, &addr_data, eeprom_detect); -+} -+ -+/* This function is called by i2c_probe */ -+static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind) -+{ -+ struct i2c_client *new_client; -+ struct eeprom_data *data; -+ int err = 0; -+ -+ /* There are three ways we can read the EEPROM data: -+ (1) I2C block reads (faster, but unsupported by most adapters) -+ (2) Consecutive byte reads (100% overhead) -+ (3) Regular byte data reads (200% overhead) -+ The third method is not implemented by this driver because all -+ known adapters support at least the second. */ -+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE_DATA -+ | I2C_FUNC_SMBUS_BYTE)) -+ goto exit; -+ -+ if (!(data = kzalloc(sizeof(struct eeprom_data), GFP_KERNEL))) { -+ err = -ENOMEM; -+ goto exit; -+ } -+ -+ new_client = &data->client; -+ memset(data->data, 0xff, EEPROM_SIZE); -+ i2c_set_clientdata(new_client, data); -+ new_client->addr = address; -+ new_client->adapter = adapter; -+ new_client->driver = &eeprom_driver; -+ new_client->flags = 0; -+ -+ /* Fill in the remaining client fields */ -+ strlcpy(new_client->name, "eeprom", I2C_NAME_SIZE); -+ data->valid = 0; -+ mutex_init(&data->update_lock); -+ data->nature = 0x00; -+ -+ /* Tell the I2C layer a new client has arrived */ -+ if ((err = i2c_attach_client(new_client))) -+ goto exit_kfree; -+ -+ /* create the sysfs eeprom file */ -+ err = sysfs_create_bin_file(&new_client->dev.kobj, &eeprom_attr); -+ if (err) -+ goto exit_detach; -+ -+ return 0; -+ -+exit_detach: -+ i2c_detach_client(new_client); -+exit_kfree: -+ kfree(data); -+exit: -+ return err; -+} -+ -+static int eeprom_detach_client(struct i2c_client *client) -+{ -+ int err; -+ -+ sysfs_remove_bin_file(&client->dev.kobj, &eeprom_attr); -+ -+ err = i2c_detach_client(client); -+ if (err) -+ return err; -+ -+ kfree(i2c_get_clientdata(client)); -+ -+ return 0; -+} -+ -+static int __init eeprom_init(void) -+{ -+ return i2c_add_driver(&eeprom_driver); -+ -+} -+ -+static void __exit eeprom_exit(void) -+{ -+ i2c_del_driver(&eeprom_driver); -+} -+ -+ -+MODULE_AUTHOR("Guillaume Ligneul guillaume.ligneul@gmail.com"); -+MODULE_DESCRIPTION("I2C EEPROM driver for AT24C32"); -+MODULE_LICENSE("GPL"); -+ -+module_init(eeprom_init); -+module_exit(eeprom_exit); -diff -Nru linux-2.6.26-officiel/drivers/i2c/chips/Makefile /home/guilig/workspace/kernel-goobie-2.6.26/src/drivers/i2c/chips/Makefile ---- linux-2.6.26-officiel/drivers/i2c/chips/Makefile 2008-11-06 11:12:07.000000000 +0100 -+++ /home/guilig/workspace/kernel-goobie-2.6.26/src/drivers/i2c/chips/Makefile 2008-11-06 11:18:20.000000000 +0100 -@@ -9,7 +9,7 @@ - # * I/O expander drivers go to drivers/gpio - # - -- -+obj-$(CONFIG_AT24C32) += at24c32.o - obj-$(CONFIG_ISL12024EEPROM) += isl12024-eeprom.o - obj-$(CONFIG_DS1682) += ds1682.o - obj-$(CONFIG_SENSORS_EEPROM) += eeprom.o diff --git a/packages/linux/linux-2.6.26/boc01/006-081216-at24c32.patch b/packages/linux/linux-2.6.26/boc01/006-081216-at24c32.patch new file mode 100644 index 0000000000..0ffec7f742 --- /dev/null +++ b/packages/linux/linux-2.6.26/boc01/006-081216-at24c32.patch @@ -0,0 +1,361 @@ +Index: linux-2.6.26-NEW/drivers/i2c/chips/Makefile +=================================================================== +--- linux-2.6.26-NEW.orig/drivers/i2c/chips/Makefile ++++ linux-2.6.26-NEW/drivers/i2c/chips/Makefile +@@ -9,7 +9,6 @@ + # * I/O expander drivers go to drivers/gpio + # + +- + obj-$(CONFIG_ISL12024EEPROM) += isl12024-eeprom.o + obj-$(CONFIG_DS1682) += ds1682.o + obj-$(CONFIG_SENSORS_EEPROM) += eeprom.o +@@ -22,6 +21,7 @@ obj-$(CONFIG_ISP1301_OMAP) += isp1301_om + obj-$(CONFIG_TPS65010) += tps65010.o + obj-$(CONFIG_MENELAUS) += menelaus.o + obj-$(CONFIG_SENSORS_TSL2550) += tsl2550.o ++obj-$(CONFIG_EEPROM_RW) += eeprom-rw.o + + ifeq ($(CONFIG_I2C_DEBUG_CHIP),y) + EXTRA_CFLAGS += -DDEBUG +Index: linux-2.6.26-NEW/drivers/i2c/chips/eeprom-rw.c +=================================================================== +--- /dev/null ++++ linux-2.6.26-NEW/drivers/i2c/chips/eeprom-rw.c +@@ -0,0 +1,319 @@ ++/* ++ eeprom-rw.c ++ ++ Mostly rewritten Feb 2008 by Davide Rizzo <[EMAIL PROTECTED]> ++ Starting from drivers/i2c/chips/eeprom.c ++ ++ Copyright (C) 1998, 1999 Frodo Looijaard <[EMAIL PROTECTED]> and ++ Philip Edelbrock <[EMAIL PROTECTED]> ++ Copyright (C) 2003 Greg Kroah-Hartman <[EMAIL PROTECTED]> ++ Copyright (C) 2003 IBM Corp. ++ ++ 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. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the Free Software ++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++*/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++/* To avoid false aliases, it scans only address 0x50. ++ Drawback: it cannot manage chips with hardware strapped address != 0 */ ++static unsigned short normal_i2c[] = {0x50, I2C_CLIENT_END}; ++ ++/* Insmod parameters */ ++I2C_CLIENT_INSMOD_1(eeprom); ++ ++struct eeprom_device { ++ int double_address, total_size, page_size, virt_device_len; ++ int pin_address_mask; ++ const char *name; ++}; ++ ++static char *eeprom_name = "2432"; ++module_param_named(CHIP, eeprom_name, charp, S_IRUGO | S_IWUSR); ++MODULE_PARM_DESC(CHIP, "Eeprom type (ex.2408,2416...)"); ++ ++static const struct eeprom_device eeproms[] = { ++ {0, 16, 1, 16, 0, "2400"}, ++ {0, 128, 8, 128, 0, "2401"}, ++ {0, 128, 16, 128, 7, "24014"}, ++ {0, 256, 8, 256, 0, "2402"}, ++ {0, 256, 16, 256, 7, "24024"}, ++ {0, 256, 16, 256, 7, "24025"}, ++ {0, 512, 16, 256, 0, "2404"}, ++ {0, 1024, 16, 256, 0, "2408"}, ++ {0, 2048, 16, 256, 0, "2416"}, ++ {1, 4096, 32, 4096, 7, "2432"}, ++ {1, 8192, 32, 8192, 7, "2464"}, ++ {1, 8192, 64, 8192, 7, "2465"}, ++ {1, 16384, 64, 16384, 7, "24128"}, ++ {1, 32768, 64, 32768, 7, "24256"}, ++ {1, 65536, 128, 65536, 7, "24512"}, ++ {1, 65536, 64, 32768, 3, "24515"}, ++ {1, 131072, 256, 65536, 2, "241024"}, ++ {1, 131072, 128, 65536, 3, "241025"}, ++ {0, 0, 0, 0, 0, NULL} ++}; ++ ++#define MAX_EEPROM_PAGE_SIZE 256 ++ ++/* Each client has this additional data */ ++struct eeprom_info { ++ struct i2c_client client; ++ struct mutex update_lock; ++ const struct eeprom_device *selected_eeprom; ++ char buf[MAX_EEPROM_PAGE_SIZE + 2]; ++}; ++ ++static ssize_t eeprom_read(struct kobject *kobj, struct bin_attribute *t, ++ char *buf, loff_t loff, size_t count) ++{ ++ struct i2c_client *client = ++ to_i2c_client(container_of(kobj, struct device, kobj)); ++ struct eeprom_info *info = i2c_get_clientdata(client); ++ char offset[2]; ++ int ret, off = (int)loff; ++ struct i2c_msg msgrd[2]; ++ if (off >= info->selected_eeprom->total_size) ++ return(-EINVAL); ++ if (off + count > info->selected_eeprom->total_size) ++ count = info->selected_eeprom->total_size - off; ++ if (count == 0) ++ return(-EINVAL); ++ mutex_lock(&info->update_lock); ++ offset[0] = off >> 8; ++ offset[1] = off & 0xFF; ++ msgrd[0].addr = msgrd[1].addr = client->addr + off / ++ info->selected_eeprom->virt_device_len; ++ msgrd[0].flags = 0; ++ if (info->selected_eeprom->double_address) { ++ msgrd[0].len = 2; ++ msgrd[0].buf = offset; ++ } else { ++ msgrd[0].len = 1; ++ msgrd[0].buf = &offset[1]; ++ } ++ msgrd[1].flags = I2C_M_RD; /* |I2C_M_NOSTART; */ ++ msgrd[1].len = count; ++ msgrd[1].buf = buf; ++ ret = i2c_transfer(client->adapter, msgrd, 2); ++ mutex_unlock(&info->update_lock); ++ return (ret == 2) ? count : ret; ++} ++ ++static ssize_t eeprom_write(struct kobject *kobj, struct bin_attribute *t, ++ char *buf, loff_t loff, size_t count) ++{ ++ struct i2c_client *client = ++ to_i2c_client(container_of(kobj, struct device, kobj)); ++ struct eeprom_info *info = i2c_get_clientdata(client); ++ struct i2c_msg msgwr, msgack; ++ int i, tx = 0, off = (int)loff; ++ if (off >= info->selected_eeprom->total_size) ++ return -EINVAL; ++ if ((off + count) > info->selected_eeprom->total_size) ++ count = info->selected_eeprom->total_size-off; ++ if (count == 0) ++ return -EINVAL; ++ msgwr.flags = 0; ++ msgack.flags = 0; ++ msgack.len = 0; ++ mutex_lock(&info->update_lock); ++ while (count) { ++ int len = info->selected_eeprom->page_size - ++ (off % info->selected_eeprom->page_size); ++ if (len > count) ++ len = count; ++ msgwr.addr = msgack.addr = client->addr + ++ off / info->selected_eeprom->virt_device_len; ++ info->buf[0] = off >> 8; ++ info->buf[1] = off & 0xFF; ++ memcpy(info->buf + 2, buf, len); ++ if (info->selected_eeprom->double_address) { ++ msgwr.buf = info->buf; ++ msgwr.len = len + 2; ++ } else { ++ msgwr.buf = 1 + info->buf; ++ msgwr.len = len + 1; ++ } ++ if (i2c_transfer(client->adapter, &msgwr, 1) != 1) ++ break; ++ for (i = 0; i < 20; i++) { ++ if (i2c_transfer(client->adapter, &msgack, 1) == 1) ++ break; ++ mdelay(1); ++ } ++ if (i >= 20) ++ break; ++ count -= len; ++ off += len; ++ buf += len; ++ tx += len; ++ } ++ mutex_unlock(&info->update_lock); ++ return tx; ++} ++ ++static struct bin_attribute eeprom_attr = { ++ .attr = ++ { ++ .name = "data", ++ .mode = S_IRUGO | S_IWUSR, ++ .owner = THIS_MODULE, ++ }, ++/* .size = selected_eeprom->total_size, */ ++ .read = eeprom_read, ++ .write = eeprom_write, ++}; ++ ++static ssize_t chip_show(struct device *dev, struct device_attribute *attr, ++ char *buffer) ++{ ++ struct eeprom_info *info = (struct eeprom_info *)dev_get_drvdata(dev); ++ return sprintf(buffer, "%s\n", info->selected_eeprom->name); ++} ++ ++static ssize_t chip_store(struct device *dev, struct device_attribute *attr, ++ const char *buffer, size_t count) ++{ ++ struct eeprom_info *info = (struct eeprom_info *)dev_get_drvdata(dev); ++ const struct eeprom_device *ei_pt; ++ if (buffer[count - 1] == '\n') ++ count--; ++ for (ei_pt = eeproms; ei_pt->name; ei_pt++) ++ if (strncasecmp(buffer, ei_pt->name, count) == 0) { ++ mutex_lock(&info->update_lock); ++ info->selected_eeprom = ei_pt; ++ sysfs_remove_bin_file(&info->client.dev.kobj, ++ &eeprom_attr); ++ eeprom_attr.size = info->selected_eeprom->total_size; ++ sysfs_create_bin_file(&info->client.dev.kobj, ++ &eeprom_attr); ++ mutex_unlock(&info->update_lock); ++ } ++ return count; ++} ++ ++static DEVICE_ATTR(chip, S_IRUGO | S_IWUSR, chip_show, chip_store); ++ ++static int eeprom_attach_adapter(struct i2c_adapter *adapter); ++static int eeprom_detach_client(struct i2c_client *client); ++ ++/* This is the driver that will be inserted */ ++static struct i2c_driver eeprom_driver = { ++ .driver = ++ { ++ .name = "eeprom", ++ }, ++ .attach_adapter = eeprom_attach_adapter, ++ .detach_client = eeprom_detach_client, ++}; ++ ++/* This function is called by i2c_probe */ ++static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind) ++{ ++ struct i2c_client *new_client; ++ struct eeprom_info *info; ++ struct i2c_msg msg; ++ int err = 0; ++ const struct eeprom_device *ei_pt; ++ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE_DATA | ++ I2C_FUNC_SMBUS_BYTE)) ++ goto exit; ++ for (ei_pt = eeproms; ei_pt->name; ei_pt++) ++ if (strcasecmp(eeprom_name, ei_pt->name) == 0) ++ break; ++/* if((address&0x07)%(ei_pt->total_size/ei_pt->virt_device_len)!=0) ++ goto exit; */ ++ msg.addr = address; ++ msg.flags = 0; ++ msg.len = 0; ++ if (i2c_transfer(adapter, &msg, 1) != 1) ++ goto exit; ++ info = kzalloc(sizeof(struct eeprom_info), GFP_KERNEL); ++ if (!info) { ++ err = -ENOMEM; ++ goto exit; ++ } ++ info->selected_eeprom = ei_pt; ++ new_client = &info->client; ++ new_client->addr = address; ++ new_client->adapter = adapter; ++ new_client->driver = &eeprom_driver; ++ new_client->flags = 0; ++ strlcpy(new_client->name, "eeprom", I2C_NAME_SIZE); ++ mutex_init(&info->update_lock); ++ i2c_set_clientdata(new_client, info); ++ err = i2c_attach_client(new_client); ++ if (err) ++ goto exit_kfree; ++ eeprom_attr.size = ei_pt->total_size; ++ err = sysfs_create_bin_file(&new_client->dev.kobj, &eeprom_attr); ++ if (err) ++ goto exit_detach; ++ err = sysfs_create_file(&new_client->dev.kobj, &dev_attr_chip.attr); ++ if (err) ++ goto exit_detach2; ++ return 0; ++exit_detach2: ++ sysfs_remove_bin_file(&new_client->dev.kobj, &eeprom_attr); ++exit_detach: ++ i2c_detach_client(new_client); ++exit_kfree: ++ kfree(info); ++exit: ++ return err; ++} ++ ++static int eeprom_attach_adapter(struct i2c_adapter *adapter) ++{ ++ return(i2c_probe(adapter, &addr_data, eeprom_detect)); ++} ++ ++static int eeprom_detach_client(struct i2c_client *client) ++{ ++ int err; ++ sysfs_remove_bin_file(&client->dev.kobj, &eeprom_attr); ++ sysfs_remove_file(&client->dev.kobj, &dev_attr_chip.attr); ++ err = i2c_detach_client(client); ++ if (err) ++ return(err); ++ kfree(i2c_get_clientdata(client)); ++ return 0; ++} ++ ++static int __init eeprom_init(void) ++{ ++ return(i2c_add_driver(&eeprom_driver)); ++} ++ ++static void __exit eeprom_exit(void) ++{ ++ i2c_del_driver(&eeprom_driver); ++} ++ ++MODULE_AUTHOR("Davide Rizzo <[EMAIL PROTECTED]>"); ++MODULE_DESCRIPTION("I2C EEPROM driver"); ++MODULE_LICENSE("GPL"); ++ ++module_init(eeprom_init); ++module_exit(eeprom_exit); ++ +Index: linux-2.6.26-NEW/drivers/i2c/chips/Kconfig +=================================================================== +--- linux-2.6.26-NEW.orig/drivers/i2c/chips/Kconfig ++++ linux-2.6.26-NEW/drivers/i2c/chips/Kconfig +@@ -148,4 +148,12 @@ config MENELAUS + and other features that are often used in portable devices like + cell phones and PDAs. + ++config EEPROM_RW ++ tristate "EEPROM" ++ help ++ If you say yes here you get read/write access to the EEPROM data ++ ++ This driver can also be built as a module. If so, the module ++ will be called eeprom-rw. ++ + endmenu diff --git a/packages/linux/linux-2.6.26/boc01/007-081127-lm73.patch b/packages/linux/linux-2.6.26/boc01/007-081127-lm73.patch deleted file mode 100644 index 14787f8b04..0000000000 --- a/packages/linux/linux-2.6.26/boc01/007-081127-lm73.patch +++ /dev/null @@ -1,275 +0,0 @@ -diff -Nru linux-2.6.26/drivers/hwmon/Kconfig linux-2.6.26.mod/drivers/hwmon/Kconfig ---- linux-2.6.26/drivers/hwmon/Kconfig 2008-07-13 23:51:29.000000000 +0200 -+++ linux-2.6.26.mod/drivers/hwmon/Kconfig 2008-11-18 11:54:04.000000000 +0100 -@@ -390,6 +390,15 @@ - This driver can also be built as a module. If so, the module - will be called lm70. - -+config SENSORS_LM73 -+ tristate "National Semiconductor LM73" -+ depends on I2C -+ help -+ If you say yes here you get support for National Semiconductor LM73 -+ sensor chips -+ This driver can also be built as a module. If so, the module -+ will be called lm73. -+ - config SENSORS_LM75 - tristate "National Semiconductor LM75 and compatibles" - depends on I2C -diff -Nru linux-2.6.26/drivers/hwmon/lm73.c linux-2.6.26.mod/drivers/hwmon/lm73.c ---- linux-2.6.26/drivers/hwmon/lm73.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.26.mod/drivers/hwmon/lm73.c 2008-11-27 11:46:31.000000000 +0100 -@@ -0,0 +1,241 @@ -+ /* -+ * LM73 Sensor driver -+ * Based on LM75 -+ * -+ * -+ * Copyright (C) 2007, CenoSYS (www.cenosys.com). -+ * Guillaume Ligneul -+ * Guillaume.ligneul@gmail.com -+ * -+ * This software program is licensed subject to the GNU General Public License -+ * (GPL).Version 2,June 1991, available at http://www.fsf.org/copyleft/gpl.html -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+ -+/* Addresses to scan */ -+static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 0x4c, -+ 0x4d, 0x4e, 0x4f, I2C_CLIENT_END }; -+ -+/* Insmod parameters */ -+I2C_CLIENT_INSMOD_1(lm73); -+ -+/* LM73 registers */ -+#define LM73_REG_INPUT 0x00 -+#define LM73_REG_CONF 0x01 -+#define LM73_REG_T_HIGH 0x02 -+#define LM73_REG_T_LOW 0x03 -+ -+static const u8 LM73_REG_TEMP[3] = { -+ LM73_REG_INPUT, /* input */ -+ LM73_REG_T_HIGH, /* max */ -+ LM73_REG_T_LOW, /* min */ -+}; -+ -+/* Each client has this additional data */ -+struct lm73_data { -+ struct i2c_client client; -+ struct device *hwmon_dev; -+ struct mutex update_lock; -+ char valid; /* !=0 if following fields are valid */ -+ unsigned long last_updated; /* In jiffies */ -+ u16 temp[3]; /* Register values, -+ 0 = input -+ 1 = max -+ 2 = min */ -+}; -+ -+static int lm73_attach_adapter(struct i2c_adapter *adapter); -+static int lm73_detect(struct i2c_adapter *adapter, int address, int kind); -+static int lm73_detach_client(struct i2c_client *client); -+static int lm73_read_value(struct i2c_client *client, u8 reg); -+static int lm73_write_value(struct i2c_client *client, u8 reg, short value); -+ -+/* This is the driver that will be inserted */ -+static struct i2c_driver lm73_driver = { -+ .driver = { -+ .name = "lm73", -+ }, -+ .attach_adapter = lm73_attach_adapter, -+ .detach_client = lm73_detach_client, -+}; -+ -+static ssize_t show_temp(struct device *dev, struct device_attribute *da, -+ char *buf) -+{ -+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da); -+ struct i2c_client *client = to_i2c_client(dev); -+ int iTemp = 0; -+ -+ iTemp = lm73_read_value(client, LM73_REG_TEMP[attr->index]); -+ -+ return sprintf(buf, "%d\n", iTemp); -+ -+ -+} -+ -+static ssize_t set_temp(struct device *dev, struct device_attribute *da, -+ const char *buf, size_t count) -+{ -+ struct sensor_device_attribute *attr = to_sensor_dev_attr(da); -+ struct i2c_client *client = to_i2c_client(dev); -+ int nr = attr->index; -+ -+ long tmp = simple_strtol(buf, NULL, 10); -+ -+ lm73_write_value(client, LM73_REG_TEMP[nr], tmp); -+ return count; -+} -+ -+static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, -+ show_temp, set_temp, 1); -+static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, -+ show_temp, set_temp, 2); -+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); -+ -+static int lm73_attach_adapter(struct i2c_adapter *adapter) -+{ -+ if (!(adapter->class & I2C_CLASS_HWMON)) -+ return 0; -+ -+ return i2c_probe(adapter, &addr_data, lm73_detect); -+} -+ -+static struct attribute *lm73_attributes[] = { -+ &sensor_dev_attr_temp1_input.dev_attr.attr, -+ &sensor_dev_attr_temp1_max.dev_attr.attr, -+ &sensor_dev_attr_temp1_min.dev_attr.attr, -+ -+ NULL -+}; -+ -+static const struct attribute_group lm73_group = { -+ .attrs = lm73_attributes, -+}; -+ -+/* This function is called by i2c_probe */ -+static int lm73_detect(struct i2c_adapter *adapter, int address, int kind) -+{ -+ struct i2c_client *new_client; -+ struct lm73_data *data; -+ int err = 0; -+ const char *name = ""; -+ -+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | -+ I2C_FUNC_SMBUS_WORD_DATA)) -+ goto exit; -+ -+ if (!(data = kzalloc(sizeof(struct lm73_data), GFP_KERNEL))) { -+ err = -ENOMEM; -+ goto exit; -+ } -+ -+ new_client = &data->client; -+ i2c_set_clientdata(new_client, data); -+ new_client->addr = address; -+ new_client->adapter = adapter; -+ new_client->driver = &lm73_driver; -+ new_client->flags = 0; -+ -+ name = "lm73"; -+ -+ /* Fill in the remaining client fields and put it into the global list */ -+ strlcpy(new_client->name, name, I2C_NAME_SIZE); -+ data->valid = 0; -+ mutex_init(&data->update_lock); -+ -+ /* Tell the I2C layer a new client has arrived */ -+ if ((err = i2c_attach_client(new_client))) -+ goto exit_free; -+ -+ /* Register sysfs hooks */ -+ if ((err = sysfs_create_group(&new_client->dev.kobj, &lm73_group))) -+ goto exit_detach; -+ -+ data->hwmon_dev = hwmon_device_register(&new_client->dev); -+ if (IS_ERR(data->hwmon_dev)) { -+ err = PTR_ERR(data->hwmon_dev); -+ goto exit_remove; -+ } -+ -+ return 0; -+ -+exit_remove: -+ sysfs_remove_group(&new_client->dev.kobj, &lm73_group); -+exit_detach: -+ i2c_detach_client(new_client); -+exit_free: -+ kfree(data); -+exit: -+ return err; -+} -+ -+static int lm73_detach_client(struct i2c_client *client) -+{ -+ struct lm73_data *data = i2c_get_clientdata(client); -+ hwmon_device_unregister(data->hwmon_dev); -+ sysfs_remove_group(&client->dev.kobj, &lm73_group); -+ i2c_detach_client(client); -+ kfree(data); -+ return 0; -+} -+ -+static int lm73_read_value(struct i2c_client *client, u8 reg) -+{ -+ short sVal; -+ -+ if (reg == LM73_REG_CONF) -+ return i2c_smbus_read_byte_data(client, reg); -+ else -+ { -+ sVal = swab16(i2c_smbus_read_word_data(client, reg)); -+ sVal = sVal >> 7; -+ -+ if(sVal & 0xFFFF) -+ { -+ sVal = sVal - 0x1; -+ sVal = ~sVal; -+ -+ return -sVal; -+ } -+ } -+ -+} -+ -+static int lm73_write_value(struct i2c_client *client, u8 reg, short value) -+{ -+ if (reg == LM73_REG_CONF) -+ return i2c_smbus_write_byte_data(client, reg, value); -+ else -+ { -+ value = value<<7; -+ return i2c_smbus_write_word_data(client, reg, swab16(value)); -+ -+ } -+} -+ -+static int __init sensors_lm73_init(void) -+{ -+ return i2c_add_driver(&lm73_driver); -+} -+ -+static void __exit sensors_lm73_exit(void) -+{ -+ i2c_del_driver(&lm73_driver); -+} -+ -+MODULE_AUTHOR("Ligneul Guillaume "); -+MODULE_DESCRIPTION("LM73 driver"); -+MODULE_LICENSE("GPL"); -+ -+module_init(sensors_lm73_init); -+module_exit(sensors_lm73_exit); -diff -Nru linux-2.6.26/drivers/hwmon/Makefile linux-2.6.26.mod/drivers/hwmon/Makefile ---- linux-2.6.26/drivers/hwmon/Makefile 2008-07-13 23:51:29.000000000 +0200 -+++ linux-2.6.26.mod/drivers/hwmon/Makefile 2008-11-18 11:54:04.000000000 +0100 -@@ -47,6 +47,7 @@ - obj-$(CONFIG_SENSORS_K8TEMP) += k8temp.o - obj-$(CONFIG_SENSORS_LM63) += lm63.o - obj-$(CONFIG_SENSORS_LM70) += lm70.o -+obj-$(CONFIG_SENSORS_LM73) += lm73.o - obj-$(CONFIG_SENSORS_LM75) += lm75.o - obj-$(CONFIG_SENSORS_LM77) += lm77.o - obj-$(CONFIG_SENSORS_LM78) += lm78.o diff --git a/packages/linux/linux-2.6.26/boc01/007-081216-lm73.patch b/packages/linux/linux-2.6.26/boc01/007-081216-lm73.patch new file mode 100644 index 0000000000..93d1a18121 --- /dev/null +++ b/packages/linux/linux-2.6.26/boc01/007-081216-lm73.patch @@ -0,0 +1,278 @@ +Index: linux-2.6.26-NEW/drivers/hwmon/Kconfig +=================================================================== +--- linux-2.6.26-NEW.orig/drivers/hwmon/Kconfig ++++ linux-2.6.26-NEW/drivers/hwmon/Kconfig +@@ -390,6 +390,15 @@ config SENSORS_LM70 + This driver can also be built as a module. If so, the module + will be called lm70. + ++config SENSORS_LM73 ++ tristate "National Semiconductor LM73" ++ depends on I2C ++ help ++ If you say yes here you get support for National Semiconductor LM73 ++ sensor chips ++ This driver can also be built as a module. If so, the module ++ will be called lm73. ++ + config SENSORS_LM75 + tristate "National Semiconductor LM75 and compatibles" + depends on I2C +Index: linux-2.6.26-NEW/drivers/hwmon/Makefile +=================================================================== +--- linux-2.6.26-NEW.orig/drivers/hwmon/Makefile ++++ linux-2.6.26-NEW/drivers/hwmon/Makefile +@@ -47,6 +47,7 @@ obj-$(CONFIG_SENSORS_IT87) += it87.o + obj-$(CONFIG_SENSORS_K8TEMP) += k8temp.o + obj-$(CONFIG_SENSORS_LM63) += lm63.o + obj-$(CONFIG_SENSORS_LM70) += lm70.o ++obj-$(CONFIG_SENSORS_LM73) += lm73.o + obj-$(CONFIG_SENSORS_LM75) += lm75.o + obj-$(CONFIG_SENSORS_LM77) += lm77.o + obj-$(CONFIG_SENSORS_LM78) += lm78.o +Index: linux-2.6.26-NEW/drivers/hwmon/lm73.c +=================================================================== +--- /dev/null ++++ linux-2.6.26-NEW/drivers/hwmon/lm73.c +@@ -0,0 +1,241 @@ ++ /* ++ * LM73 Sensor driver ++ * Based on LM75 ++ * ++ * ++ * Copyright (C) 2007, CenoSYS (www.cenosys.com). ++ * Guillaume Ligneul ++ * Guillaume.ligneul@gmail.com ++ * ++ * This software program is licensed subject to the GNU General Public License ++ * (GPL).Version 2,June 1991, available at http://www.fsf.org/copyleft/gpl.html ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ ++/* Addresses to scan */ ++static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 0x4c, ++ 0x4d, 0x4e, 0x4f, I2C_CLIENT_END }; ++ ++/* Insmod parameters */ ++I2C_CLIENT_INSMOD_1(lm73); ++ ++/* LM73 registers */ ++#define LM73_REG_INPUT 0x00 ++#define LM73_REG_CONF 0x01 ++#define LM73_REG_T_HIGH 0x02 ++#define LM73_REG_T_LOW 0x03 ++ ++static const u8 LM73_REG_TEMP[3] = { ++ LM73_REG_INPUT, /* input */ ++ LM73_REG_T_HIGH, /* max */ ++ LM73_REG_T_LOW, /* min */ ++}; ++ ++/* Each client has this additional data */ ++struct lm73_data { ++ struct i2c_client client; ++ struct device *hwmon_dev; ++ struct mutex update_lock; ++ char valid; /* !=0 if following fields are valid */ ++ unsigned long last_updated; /* In jiffies */ ++ u16 temp[3]; /* Register values, ++ 0 = input ++ 1 = max ++ 2 = min */ ++}; ++ ++static int lm73_attach_adapter(struct i2c_adapter *adapter); ++static int lm73_detect(struct i2c_adapter *adapter, int address, int kind); ++static int lm73_detach_client(struct i2c_client *client); ++static int lm73_read_value(struct i2c_client *client, u8 reg); ++static int lm73_write_value(struct i2c_client *client, u8 reg, short value); ++ ++/* This is the driver that will be inserted */ ++static struct i2c_driver lm73_driver = { ++ .driver = { ++ .name = "lm73", ++ }, ++ .attach_adapter = lm73_attach_adapter, ++ .detach_client = lm73_detach_client, ++}; ++ ++static ssize_t show_temp(struct device *dev, struct device_attribute *da, ++ char *buf) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(da); ++ struct i2c_client *client = to_i2c_client(dev); ++ int iTemp = 0; ++ ++ iTemp = lm73_read_value(client, LM73_REG_TEMP[attr->index]); ++ ++ return sprintf(buf, "%d\n", iTemp); ++ ++ ++} ++ ++static ssize_t set_temp(struct device *dev, struct device_attribute *da, ++ const char *buf, size_t count) ++{ ++ struct sensor_device_attribute *attr = to_sensor_dev_attr(da); ++ struct i2c_client *client = to_i2c_client(dev); ++ int nr = attr->index; ++ ++ long tmp = simple_strtol(buf, NULL, 10); ++ ++ lm73_write_value(client, LM73_REG_TEMP[nr], tmp); ++ return count; ++} ++ ++static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, ++ show_temp, set_temp, 1); ++static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, ++ show_temp, set_temp, 2); ++static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); ++ ++static int lm73_attach_adapter(struct i2c_adapter *adapter) ++{ ++ if (!(adapter->class & I2C_CLASS_HWMON)) ++ return 0; ++ ++ return i2c_probe(adapter, &addr_data, lm73_detect); ++} ++ ++static struct attribute *lm73_attributes[] = { ++ &sensor_dev_attr_temp1_input.dev_attr.attr, ++ &sensor_dev_attr_temp1_max.dev_attr.attr, ++ &sensor_dev_attr_temp1_min.dev_attr.attr, ++ ++ NULL ++}; ++ ++static const struct attribute_group lm73_group = { ++ .attrs = lm73_attributes, ++}; ++ ++/* This function is called by i2c_probe */ ++static int lm73_detect(struct i2c_adapter *adapter, int address, int kind) ++{ ++ struct i2c_client *new_client; ++ struct lm73_data *data; ++ int err = 0; ++ const char *name = ""; ++ ++ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | ++ I2C_FUNC_SMBUS_WORD_DATA)) ++ goto exit; ++ ++ if (!(data = kzalloc(sizeof(struct lm73_data), GFP_KERNEL))) { ++ err = -ENOMEM; ++ goto exit; ++ } ++ ++ new_client = &data->client; ++ i2c_set_clientdata(new_client, data); ++ new_client->addr = address; ++ new_client->adapter = adapter; ++ new_client->driver = &lm73_driver; ++ new_client->flags = 0; ++ ++ name = "lm73"; ++ ++ /* Fill in the remaining client fields and put it into the global list */ ++ strlcpy(new_client->name, name, I2C_NAME_SIZE); ++ data->valid = 0; ++ mutex_init(&data->update_lock); ++ ++ /* Tell the I2C layer a new client has arrived */ ++ if ((err = i2c_attach_client(new_client))) ++ goto exit_free; ++ ++ /* Register sysfs hooks */ ++ if ((err = sysfs_create_group(&new_client->dev.kobj, &lm73_group))) ++ goto exit_detach; ++ ++ data->hwmon_dev = hwmon_device_register(&new_client->dev); ++ if (IS_ERR(data->hwmon_dev)) { ++ err = PTR_ERR(data->hwmon_dev); ++ goto exit_remove; ++ } ++ ++ return 0; ++ ++exit_remove: ++ sysfs_remove_group(&new_client->dev.kobj, &lm73_group); ++exit_detach: ++ i2c_detach_client(new_client); ++exit_free: ++ kfree(data); ++exit: ++ return err; ++} ++ ++static int lm73_detach_client(struct i2c_client *client) ++{ ++ struct lm73_data *data = i2c_get_clientdata(client); ++ hwmon_device_unregister(data->hwmon_dev); ++ sysfs_remove_group(&client->dev.kobj, &lm73_group); ++ i2c_detach_client(client); ++ kfree(data); ++ return 0; ++} ++ ++static int lm73_read_value(struct i2c_client *client, u8 reg) ++{ ++ short sVal; ++ ++ if (reg == LM73_REG_CONF) ++ return i2c_smbus_read_byte_data(client, reg); ++ else ++ { ++ sVal = swab16(i2c_smbus_read_word_data(client, reg)); ++ sVal = sVal >> 7; ++ ++ if ( sVal & 0xFFFF ) { ++ sVal = sVal - 0x1; ++ sVal = ~sVal; ++ ++ return -sVal; ++ } ++ else { ++ return sVal; ++ } ++ } ++} ++ ++static int lm73_write_value(struct i2c_client *client, u8 reg, short value) ++{ ++ if (reg == LM73_REG_CONF) ++ return i2c_smbus_write_byte_data(client, reg, value); ++ else ++ { ++ value = value<<7; ++ return i2c_smbus_write_word_data(client, reg, swab16(value)); ++ } ++} ++ ++static int __init sensors_lm73_init(void) ++{ ++ return i2c_add_driver(&lm73_driver); ++} ++ ++static void __exit sensors_lm73_exit(void) ++{ ++ i2c_del_driver(&lm73_driver); ++} ++ ++MODULE_AUTHOR("Ligneul Guillaume "); ++MODULE_DESCRIPTION("LM73 driver"); ++MODULE_LICENSE("GPL"); ++ ++module_init(sensors_lm73_init); ++module_exit(sensors_lm73_exit); diff --git a/packages/linux/linux-2.6.26/boc01/011-081105-gpio.patch b/packages/linux/linux-2.6.26/boc01/011-081105-gpio.patch deleted file mode 100644 index 86bf4ff84b..0000000000 --- a/packages/linux/linux-2.6.26/boc01/011-081105-gpio.patch +++ /dev/null @@ -1,161 +0,0 @@ -diff -Nru linux-2.6.26-officiel/drivers/char/Kconfig /home/guilig/workspace/kernel-goobie-2.6.26/src/drivers/char/Kconfig ---- linux-2.6.26-officiel/drivers/char/Kconfig 2008-07-13 23:51:29.000000000 +0200 -+++ /home/guilig/workspace/kernel-goobie-2.6.26/src/drivers/char/Kconfig 2008-09-26 14:44:59.000000000 +0200 -@@ -1006,6 +1006,14 @@ - tristate "NEC VR4100 series General-purpose I/O Unit support" - depends on CPU_VR41XX - -+config GPIO_MPC8313 -+ tristate "mpc8313e gpio" -+ depends on PPC_MPC831x -+ select INPUT -+ default y -+ help -+ test -+ - config RAW_DRIVER - tristate "RAW driver (/dev/raw/rawN)" - depends on BLOCK -diff -Nru linux-2.6.26-officiel/drivers/char/Makefile /home/guilig/workspace/kernel-goobie-2.6.26/src/drivers/char/Makefile ---- linux-2.6.26-officiel/drivers/char/Makefile 2008-07-13 23:51:29.000000000 +0200 -+++ /home/guilig/workspace/kernel-goobie-2.6.26/src/drivers/char/Makefile 2008-09-26 14:44:59.000000000 +0200 -@@ -111,6 +111,8 @@ - obj-$(CONFIG_PS3_FLASH) += ps3flash.o - - obj-$(CONFIG_JS_RTC) += js-rtc.o -+ -+obj-$(CONFIG_GPIO_MPC8313) += mpc8313e_gpio.o - js-rtc-y = rtc.o - - # Files generated that shall be removed upon make clean -diff -Nru linux-2.6.26-officiel/drivers/char/mpc8313e_gpio.c /home/guilig/workspace/kernel-goobie-2.6.26/src/drivers/char/mpc8313e_gpio.c ---- linux-2.6.26-officiel/drivers/char/mpc8313e_gpio.c 1970-01-01 01:00:00.000000000 +0100 -+++ /home/guilig/workspace/kernel-goobie-2.6.26/src/drivers/char/mpc8313e_gpio.c 2008-09-26 14:44:59.000000000 +0200 -@@ -0,0 +1,127 @@ -+/* linux/drivers/char/mpc8313e_gpio.c -+ -+ Allows a user space process to control the GPIO pins. -+ -+ -+*/ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+MODULE_AUTHOR("Alexandre Coffignal "); -+MODULE_DESCRIPTION("mpc8313e GPIO"); -+MODULE_LICENSE("GPL"); -+ -+static int major = 0; -+struct gpio { -+ __be32 gpdir; -+ __be32 gpodr; -+ __be32 gpdat; -+ __be32 gpier; -+ __be32 gpimr; -+ __be32 gpicr; -+} __attribute__ ((packed)); -+static struct gpio *gpio_regs; -+ -+static ssize_t mpc8313e_gpio_write(struct file *file, const char __user *data, size_t len, loff_t *ppos) -+{ -+ unsigned m = iminor(file->f_path.dentry->d_inode); -+ size_t i; -+ int err = 0; -+ -+ for (i = 0; i < len; ++i) { -+ char c; -+ if (get_user(c, data + i)) -+ return -EFAULT; -+ /* set GPIO as output */ -+ setbits32(&gpio_regs->gpdir, 1 << (31 - m)); -+ clrbits32(&gpio_regs->gpodr, 1 << (31 - m)); -+ switch (c) { -+ case '0': -+ /*Set GPIO level */ -+ clrbits32(&gpio_regs->gpdat, 1 << (31 - m)); -+ break; -+ case '1': -+ /*Set GPIO level */ -+ setbits32(&gpio_regs->gpdat, 1 << (31 - m)); -+ break; -+ default: -+ printk(KERN_DEBUG "io%2d bad setting: chr<0x%2x>\n", -+ m, (int)c); -+ err++; -+ } -+ } -+ if (err) -+ return -EINVAL; -+ -+ return len; -+} -+ -+static ssize_t mpc8313e_gpio_read(struct file *file, char __user * buf, size_t len, loff_t * ppos) -+{ -+ unsigned m = iminor(file->f_path.dentry->d_inode); -+ int value; -+ value=in_be32(&gpio_regs->gpdat)&(1 << (31 - m)); -+ if (value) -+ put_user(1, buf); -+ else -+ put_user(0, buf); -+ -+ return 0; -+ -+} -+ -+static int mpc8313e_gpio_open(struct inode *inode, struct file *file) -+{ -+ return 0; -+} -+ -+static int mpc8313e_gpio_close(struct inode *inode, struct file *file) -+{ -+ printk(KERN_DEBUG "close()\n"); -+ return 0; -+} -+ -+struct file_operations fops = -+{ -+ .read = mpc8313e_gpio_read, -+ .write = mpc8313e_gpio_write, -+ .open = mpc8313e_gpio_open, -+ .release = mpc8313e_gpio_close /* correspond a close */ -+}; -+ -+static int __init mpc8313e_gpio_init(void) -+{ -+ int ret; -+ -+ ret = register_chrdev(major, "gpio", &fops); -+ if(ret < 0) -+ { -+ printk(KERN_WARNING "Probleme sur le major\n"); -+ return ret; -+ } -+ -+ /* System I/O Configuration Register Low */ -+ gpio_regs = ioremap(get_immrbase() + 0xc00, 0x20); -+ if (!gpio_regs) -+ return -ENOMEM; -+ return 0; -+ -+} -+ -+static void __exit mpc8313e_gpio_cleanup(void) -+{ -+ unregister_chrdev(major, "gpio"); -+} -+ -+module_init(mpc8313e_gpio_init); -+module_exit(mpc8313e_gpio_cleanup); -+ -+ diff --git a/packages/linux/linux-2.6.26/boc01/011-081202-gpio.patch b/packages/linux/linux-2.6.26/boc01/011-081202-gpio.patch new file mode 100644 index 0000000000..e106526b93 --- /dev/null +++ b/packages/linux/linux-2.6.26/boc01/011-081202-gpio.patch @@ -0,0 +1,365 @@ +diff -Nru linux-2.6.26-010/drivers/char/Kconfig linux-2.6.26-011/drivers/char/Kconfig +--- linux-2.6.26-010/drivers/char/Kconfig 2008-07-13 23:51:29.000000000 +0200 ++++ linux-2.6.26-011/drivers/char/Kconfig 2008-12-02 09:45:08.000000000 +0100 +@@ -1006,6 +1006,23 @@ + tristate "NEC VR4100 series General-purpose I/O Unit support" + depends on CPU_VR41XX + ++config GPIO_MPC8313 ++ tristate "mpc8313e gpio" ++ depends on PPC_MPC831x ++ select INPUT ++ default y ++ help ++ Give userspace access to the GPIO pins on the MPC8313E devices. ++ ++config EXIO_MPC8313 ++ tristate "mpc8313e exio" ++ depends on PPC_MPC831x ++ select INPUT ++ default y ++ help ++ Give userspace access to the Extenrder IO pins on the CPE board. ++ ++ + config RAW_DRIVER + tristate "RAW driver (/dev/raw/rawN)" + depends on BLOCK +diff -Nru linux-2.6.26-010/drivers/char/Makefile linux-2.6.26-011/drivers/char/Makefile +--- linux-2.6.26-010/drivers/char/Makefile 2008-07-13 23:51:29.000000000 +0200 ++++ linux-2.6.26-011/drivers/char/Makefile 2008-12-02 09:45:25.000000000 +0100 +@@ -111,6 +111,8 @@ + obj-$(CONFIG_PS3_FLASH) += ps3flash.o + + obj-$(CONFIG_JS_RTC) += js-rtc.o ++obj-$(CONFIG_GPIO_MPC8313) += mpc8313e_gpio.o ++obj-$(CONFIG_EXIO_MPC8313) += mpc8313e_exio.o + js-rtc-y = rtc.o + + # Files generated that shall be removed upon make clean +diff -Nru linux-2.6.26-010/drivers/char/mpc8313e_exio.c linux-2.6.26-011/drivers/char/mpc8313e_exio.c +--- linux-2.6.26-010/drivers/char/mpc8313e_exio.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.26-011/drivers/char/mpc8313e_exio.c 2008-12-02 10:46:31.000000000 +0100 +@@ -0,0 +1,170 @@ ++/* ++* CPE Extender io driver ++* ++* ++* Copyright (C) 2007, CenoSYS (www.cenosys.com). ++* Alexandre Coffignal ++* alexandre.coffignal@cenosys.com ++* ++* This software program is licensed subject to the GNU General Public License ++* (GPL).Version 2,June 1991, available at http://www.fsf.org/copyleft/gpl.html ++* ++* Allows a user space process to control the EXIO pins. ++* ++*/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static char module_name[] = "exio"; ++ ++ ++#define NB_EXIO 8 ++#define DEFAULT_STATE 0x58 ++#define EXIO_BASE 0xfa000000 ++#define EXIO_SIZE 0x2 ++ ++static int major = 0; ++static u8 exio_state = DEFAULT_STATE; ++static void *exio_io = NULL; ++static struct resource *exio_mem = NULL; ++ ++static ssize_t mpc8313e_exio_write(struct file *file, const char __user *data, size_t len, loff_t *ppos) ++{ ++ unsigned m = iminor(file->f_path.dentry->d_inode); ++ size_t i; ++ char mask; ++ int err = 0; ++ ++ for (i = 0; i < len; ++i) { ++ char c; ++ if (get_user(c, data + i)) ++ return -EFAULT; ++ //TODO write ++ ++ mask=(1<<(7-m)); ++ switch (c) { ++ case '0': ++ /*Clear exio level */ ++ exio_state&=~mask; ++ iowrite8(exio_state, exio_io); ++ break; ++ case '1': ++ /*Set exio level */ ++ exio_state|=mask; ++ iowrite8(exio_state, exio_io); ++ break; ++ default: ++ printk(KERN_DEBUG "exio%2d bad setting: chr<0x%2x>\n", ++ m, (int)c); ++ err++; ++ } ++ } ++ if (err) ++ return -EINVAL; ++ ++ return len; ++} ++ ++ ++static ssize_t mpc8313e_exio_read(struct file *file, char __user * buf, ++ size_t len, loff_t * ppos) ++{ ++ unsigned m = iminor(file->f_path.dentry->d_inode); ++ int value; ++ char mask; ++ char state=ioread8(exio_io); ++ ++ mask=(1<<(7-m)); ++ value=state&mask; ++ if (put_user(value ? '1' : '0', buf)) ++ return -EFAULT; ++ return 1; ++ ++} ++ ++static int mpc8313e_exio_open(struct inode *inode, struct file *file) ++{ ++ return 0; ++} ++ ++static int mpc8313e_exio_close(struct inode *inode, struct file *file) ++{ ++ printk(KERN_DEBUG "close()\n"); ++ return 0; ++} ++ ++struct file_operations mpc8313e_exio_fops = ++{ ++ .owner = THIS_MODULE, ++ .read = mpc8313e_exio_read, ++ .write = mpc8313e_exio_write, ++ .open = mpc8313e_exio_open, ++ .release = mpc8313e_exio_close /* correspond a close */ ++}; ++ ++static struct class * exio_class; ++ ++static int __init mpc8313e_exio_init(void) ++{ ++ int rc,i; ++ ++ rc = register_chrdev(major, module_name, &mpc8313e_exio_fops); ++ if (rc < 0) { ++ return rc; ++ } ++ ++ if (major == 0) { ++ major = rc; /* accept dynamic major number */ ++ printk(KERN_INFO "%s: successfully loaded with major %d\n",module_name, major); ++ } ++ ++ exio_class = class_create(THIS_MODULE, "exio"); ++ ++ for (i = 0; i < NB_EXIO; i++) ++ { ++ device_create(exio_class, NULL, MKDEV(major, i) , "%s%i", module_name,i); ++ ++ } ++ ++ /* System I/O Configuration Register Low */ ++ if (!(exio_mem = request_mem_region(EXIO_BASE, EXIO_SIZE, "mpc8313-exio"))) ++ return -ENOMEM; ++ ++ if (!(exio_io = ioremap(EXIO_BASE, EXIO_SIZE))) ++ { ++ release_mem_region(EXIO_BASE, EXIO_SIZE); ++ exio_mem = NULL; ++ return -ENOMEM; ++ } ++ iowrite8(exio_state, exio_io); ++ ++ return 0; ++} ++ ++static void __exit mpc8313e_exio_cleanup(void) ++{ ++ if (exio_mem) release_mem_region(EXIO_BASE, EXIO_SIZE); ++ exio_mem = NULL; ++ ++ unregister_chrdev(major, module_name); ++} ++ ++module_param(major, int, 0644); ++MODULE_PARM_DESC(major, "Static major number (none = dynamic)"); ++MODULE_AUTHOR("Alexandre Coffignal "); ++MODULE_DESCRIPTION("mpc8313e exio"); ++MODULE_LICENSE("GPL"); ++ ++module_init(mpc8313e_exio_init); ++module_exit(mpc8313e_exio_cleanup); ++ ++ +diff -Nru linux-2.6.26-010/drivers/char/mpc8313e_gpio.c linux-2.6.26-011/drivers/char/mpc8313e_gpio.c +--- linux-2.6.26-010/drivers/char/mpc8313e_gpio.c 1970-01-01 01:00:00.000000000 +0100 ++++ linux-2.6.26-011/drivers/char/mpc8313e_gpio.c 2008-12-02 10:46:35.000000000 +0100 +@@ -0,0 +1,148 @@ ++/* ++* mpc8313e gpio driver ++* ++* ++* Copyright (C) 2007, CenoSYS (www.cenosys.com). ++* Alexandre Coffignal ++* alexandre.coffignal@cenosys.com ++* ++* This software program is licensed subject to the GNU General Public License ++* (GPL).Version 2,June 1991, available at http://www.fsf.org/copyleft/gpl.html ++* ++* Allows a user space process to control the GPIO pins. ++* ++*/ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static char module_name[] = "gpio"; ++#define NB_GPIO 8 ++static int major = 0; ++struct gpio { ++ __be32 gpdir; ++ __be32 gpodr; ++ __be32 gpdat; ++ __be32 gpier; ++ __be32 gpimr; ++ __be32 gpicr; ++} __attribute__ ((packed)); ++static struct gpio *gpio_regs; ++ ++static ssize_t mpc8313e_gpio_write(struct file *file, const char __user *data, size_t len, loff_t *ppos) ++{ ++ unsigned m = iminor(file->f_path.dentry->d_inode); ++ size_t i; ++ int err = 0; ++ ++ for (i = 0; i < len; ++i) { ++ char c; ++ if (get_user(c, data + i)) ++ return -EFAULT; ++ /* set GPIO as output */ ++ setbits32(&gpio_regs->gpdir, 1 << (31 - m)); ++ clrbits32(&gpio_regs->gpodr, 1 << (31 - m)); ++ switch (c) { ++ case '0': ++ /*Set GPIO level */ ++ clrbits32(&gpio_regs->gpdat, 1 << (31 - m)); ++ break; ++ case '1': ++ /*Set GPIO level */ ++ setbits32(&gpio_regs->gpdat, 1 << (31 - m)); ++ break; ++ default: ++ printk(KERN_DEBUG "io%2d bad setting: chr<0x%2x>\n", ++ m, (int)c); ++ err++; ++ } ++ } ++ if (err) ++ return -EINVAL; ++ ++ return len; ++} ++ ++static ssize_t mpc8313e_gpio_read(struct file *file, char __user * buf, size_t len, loff_t * ppos) ++{ ++ unsigned m = iminor(file->f_path.dentry->d_inode); ++ int value; ++ value=in_be32(&gpio_regs->gpdat)&(1 << (31 - m)); ++ if (put_user(value ? '1' : '0', buf)) ++ return -EFAULT; ++ return 1; ++ ++ ++} ++ ++ ++ ++static int mpc8313e_gpio_open(struct inode *inode, struct file *file) ++{ ++ return 0; ++} ++ ++static int mpc8313e_gpio_close(struct inode *inode, struct file *file) ++{ ++ return 0; ++} ++ ++struct file_operations mpc8313e_gpio_fops = ++{ ++ .owner = THIS_MODULE, ++ .read = mpc8313e_gpio_read, ++ .write = mpc8313e_gpio_write, ++ .open = mpc8313e_gpio_open, ++ .release = mpc8313e_gpio_close ++}; ++static struct class * gpio_class; ++static int __init mpc8313e_gpio_init(void) ++{ ++ int rc,i; ++ ++ rc = register_chrdev(major, module_name, &mpc8313e_gpio_fops); ++ if (rc < 0) { ++ return rc; ++ } ++ ++ if (major == 0) { ++ major = rc; /* accept dynamic major number */ ++ printk(KERN_INFO "%s: successfully loaded with major %d\n",module_name, major); ++ ++ } ++ gpio_class = class_create(THIS_MODULE, "gpio"); ++ ++ for (i = 0; i < NB_GPIO; i++) ++ { ++ device_create(gpio_class, NULL, MKDEV(major, i) , "%s%i", module_name,i); ++ ++ } ++ ++ /* System I/O Configuration Register Low */ ++ gpio_regs = ioremap(get_immrbase() + 0xc00, 0x20); ++ if (!gpio_regs) ++ return -ENOMEM; ++ return 0; ++} ++ ++static void __exit mpc8313e_gpio_cleanup(void) ++{ ++ unregister_chrdev(major, module_name); ++} ++module_param(major, int, 0644); ++MODULE_PARM_DESC(major, "Static major number (none = dynamic)"); ++MODULE_AUTHOR("Alexandre Coffignal "); ++MODULE_DESCRIPTION("mpc8313e GPIO"); ++MODULE_LICENSE("GPL"); ++ ++module_init(mpc8313e_gpio_init); ++module_exit(mpc8313e_gpio_cleanup); ++ ++ diff --git a/packages/linux/linux-2.6.26/boc01/013-081127-lcd.patch b/packages/linux/linux-2.6.26/boc01/013-081127-lcd.patch deleted file mode 100644 index 258ad6f9c9..0000000000 --- a/packages/linux/linux-2.6.26/boc01/013-081127-lcd.patch +++ /dev/null @@ -1,663 +0,0 @@ -diff -uNr linux-2.6.26_orig/drivers/video/Kconfig linux-2.6.26/drivers/video/Kconfig ---- linux-2.6.26_orig/drivers/video/Kconfig 2008-07-13 23:51:29.000000000 +0200 -+++ linux-2.6.26/drivers/video/Kconfig 2008-11-27 18:54:42.000000000 +0100 -@@ -480,6 +480,17 @@ - this driver, say Y or M; otherwise say N. You must specify the - GPIO IO address to be used for setting control and data. - -+config FB_NOVA -+ tristate "Nova 7506 Monochrome LCD board support" -+ depends on FB -+ select FB_SYS_FILLRECT -+ select FB_SYS_COPYAREA -+ select FB_SYS_IMAGEBLIT -+ select FB_SYS_FOPS -+ help -+ This enables support for the Nova 7506 Monochrome LCD board. The board -+ is based on the NT7506 lcd controller. -+ - config FB_ATARI - bool "Atari native chipset support" - depends on (FB = y) && ATARI -diff -uNr linux-2.6.26_orig/drivers/video/Makefile linux-2.6.26/drivers/video/Makefile ---- linux-2.6.26_orig/drivers/video/Makefile 2008-07-13 23:51:29.000000000 +0200 -+++ linux-2.6.26/drivers/video/Makefile 2008-11-27 18:54:57.000000000 +0100 -@@ -13,8 +13,8 @@ - - obj-$(CONFIG_VT) += console/ - obj-$(CONFIG_LOGO) += logo/ --obj-y += backlight/ display/ -- -+obj-y += backlight/ display/ -+obj-$(CONFIG_FB_NOVA) += N7506fb.o - obj-$(CONFIG_FB_CFB_FILLRECT) += cfbfillrect.o - obj-$(CONFIG_FB_CFB_COPYAREA) += cfbcopyarea.o - obj-$(CONFIG_FB_CFB_IMAGEBLIT) += cfbimgblt.o -diff -uNr linux-2.6.26_orig/drivers/video/N7506fb.c linux-2.6.26/drivers/video/N7506fb.c ---- linux-2.6.26_orig/drivers/video/N7506fb.c 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.26/drivers/video/N7506fb.c 2008-11-27 18:41:29.000000000 +0100 -@@ -0,0 +1,550 @@ -+/* -+ * linux/drivers/video/N7506fb.c -- FB driver for Nova NT7506 monochrome LCD board -+ * -+ * Copyright (C) 2008, Alexandre Coffignal -+ * -+ * This file is subject to the terms and conditions of the GNU General Public -+ * License. See the file COPYING in the main directory of this archive for -+ * more details. -+ * -+ * Layout is based on arcfb.c by Jaya Kumar -+ * -+ * This driver was written to be used with the Nova 7506 LCD board. -+ * -+ * -+ * -+ * -+ * Nova uses a -+ * set of NT7506 chips that control individual 128x128 LCD matrices. -+ * The interface between the board and the host is TTL based GPIO. -+ * -+ * General notes: -+ * - User must set tuhold. It's in microseconds. According to the 108 spec, -+ * the hold time is supposed to be at least 1 microsecond. -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+ -+#define floor8(a) (a&(~0x07)) -+#define floorXres(a,xres) (a&(~(xres - 1))) -+#define iceil8(a) (((int)((a+7)/8))*8) -+#define ceil128(a) (a|0x7F) -+#define ceilXres(a,xres) (a|(xres - 1)) -+ -+//NT7506 Hardware -+#define LCD_RST 0x08 -+#define LCD_RSTN 0x00 -+#define LCD_BCKLIGH 0x04 -+#define LCD_BCKLIGHN 0x00 -+#define LCD_RS 0x02 -+#define LCD_RSN 0x00 -+#define LCD_ERD 0x01 -+#define LCD_ERDN 0x00 -+ -+//Base address -+#define LCD_BASE 0xf0000000 -+#define LCD_SIZE 0x2 -+ -+#define CONTRASTE 0xF -+#define FRAME_PER_SECOND 5 -+ -+static struct resource *lcd_mem = NULL; -+static void * _lcd_io = NULL; -+static unsigned long tuhold; -+struct fb_info *info; -+static struct timer_list fb_timer; -+ -+struct novafb_par { -+ atomic_t ref_count; -+ unsigned char cslut[9]; -+ struct fb_info *info; -+ unsigned int irq; -+ spinlock_t lock; -+}; -+ -+static struct fb_fix_screeninfo novafb_fix __initdata = { -+ .id = "novafb", -+ .type = FB_TYPE_PACKED_PIXELS, -+ .visual = FB_VISUAL_MONO01, -+ .xpanstep = 1, -+ .ypanstep = 1, -+ .ywrapstep = 0, -+ .line_length=16, -+ .accel = FB_ACCEL_NONE, -+}; -+ -+static struct fb_var_screeninfo novafb_var __initdata = { -+ .xres = 128, -+ .yres = 128, -+ .xres_virtual = 128, -+ .yres_virtual = 128, -+ .bits_per_pixel = 1, -+ .nonstd = 1, -+}; -+ -+ -+static void NT7506_init_lcd(char ael); -+ -+static void NT7506_writeb_ctl(unsigned char value) -+{ -+ unsigned short svalue; -+ svalue=value<<8 | LCD_RSN | LCD_RST | LCD_ERDN | LCD_BCKLIGH; -+ iowrite16(svalue, _lcd_io); -+ udelay(tuhold); -+ //The data on DB0/7 are latched at the falling edge of the E_RD signal -+ svalue=value<<8 | LCD_RSN | LCD_RST | LCD_ERD | LCD_BCKLIGH; -+ iowrite16(svalue, _lcd_io); -+ udelay(tuhold); -+} -+ -+static void NT7506_writeb_data(unsigned char value) -+{ -+ unsigned short svalue; -+ svalue=value<<8|LCD_RS |LCD_RST | LCD_ERD | LCD_BCKLIGH ; -+ iowrite16(svalue, _lcd_io); -+ udelay(tuhold); -+ //The data on DB0/7 are latched at the falling edge of the E_RD signal -+ svalue=value<<8|LCD_RS |LCD_RST | LCD_ERDN | LCD_BCKLIGH; -+ iowrite16(svalue, _lcd_io); -+ udelay(tuhold); -+} -+ -+static void NT7506_set_start_line(unsigned char y) -+{ -+ NT7506_writeb_ctl(NT_START_LINE); -+ NT7506_writeb_ctl(y); -+} -+ -+static void NT7506_set_yaddr(unsigned char y) -+{ -+ NT7506_writeb_ctl(NT_PAGE_ADDR+y); -+} -+ -+static void NT7506_set_xaddr(unsigned char x) -+{ -+ NT7506_writeb_ctl(NT_COL_MSB | (x >> 0x04) ); //Send high nibble -+ NT7506_writeb_ctl(NT_COL_LSB | (x & 0x0F) ); //Send low nibble -+} -+ -+/* main novafb functions */ -+ -+static int novafb_open(struct fb_info *info, int user) -+{ -+ struct novafb_par *par = info->par; -+ atomic_inc(&par->ref_count); -+ return 0; -+} -+ -+static int novafb_release(struct fb_info *info, int user) -+{ -+ struct novafb_par *par = info->par; -+ int count = atomic_read(&par->ref_count); -+ if (!count) -+ return -EINVAL; -+ atomic_dec(&par->ref_count); -+ return 0; -+} -+ -+static int novafb_pan_display(struct fb_var_screeninfo *var, -+ struct fb_info *info) -+{ -+ if ((var->vmode & FB_VMODE_YWRAP) && (var->yoffset < 128) -+ && (info->var.yres <= 128)) -+ { -+ NT7506_set_start_line(var->yoffset); -+ info->var.yoffset = var->yoffset; -+ return 0; -+ } -+ -+ return -EINVAL; -+} -+ -+static void novafb_lcd_update(struct novafb_par *par, unsigned int dx, -+ unsigned int dy, unsigned int w, unsigned int h) -+{ -+ int bit,x,y,xfb,yfb,width,height,i; -+ char mask=0; -+ char dest[2048]; -+ char * src; -+ char value; -+ src = (unsigned char __force *) par->info->screen_base; -+ for(i=0;i<2048;i++) -+ { -+ dest[i]=0; -+ } -+ for(x=0;x<128/*(width)*/;x++) -+ { -+ for(y=0;y<16/*height/8*/;y++) -+ { -+ xfb=x/8; -+ yfb=y*8; -+ -+ for(bit=0;bit<8;yfb++,bit++) -+ { -+ mask = (1<<(7-(x%8))); -+ if(((src[yfb*16+xfb]&mask))) -+ value=1; -+ else -+ value=0; -+ -+ dest[y*128+x]+= (value<par; -+ -+ int xfb,yfb,i=0; -+ char * src = (unsigned char __force *) par->info->screen_base; -+ -+ for(yfb=image->dy;yfb<(image->height+image->dy);yfb++) -+ { -+ for(xfb=(image->dx)/8;xfb<(image->dx+image->width)/8;xfb++) -+ { -+ src[yfb*16+xfb]=image->data[i++]; -+ } -+ } -+ -+} -+ -+/* -+ * this is the access path from userspace. they can seek and write to -+ * the fb. it's inefficient for them to do anything less than 128*8 -+ * writes since we update the lcd in each write() anyway. -+ */ -+static ssize_t novafb_write(struct fb_info *info, const char __user *buf, -+ size_t count, loff_t *ppos) -+{ -+ unsigned long p; -+ int err=-EINVAL; -+ unsigned int fbmemlength ; -+ struct novafb_par *par; -+ unsigned int xres; -+ p = *ppos; -+ par = info->par; -+ xres = info->var.xres; -+ fbmemlength = (xres * info->var.yres)/8; -+ -+ if (p > fbmemlength) -+ { -+ return -ENOSPC; -+ } -+ err = 0; -+ if ((count + p) > fbmemlength) { -+ count = fbmemlength - p; -+ err = -ENOSPC; -+ } -+ -+ if (count) { -+ char *base_addr; -+ base_addr = (char __force *)info->screen_base; -+ count -= copy_from_user(base_addr + p, buf, count); -+ *ppos += count; -+ err = -EFAULT; -+ } -+ if (count) -+ { -+ return count; -+ } -+ return err; -+} -+ -+static int novafb_mmap(struct fb_info *info, struct vm_area_struct *vma) -+{ -+ unsigned long off; -+ unsigned long start; -+ u32 len; -+ -+ if (vma->vm_end - vma->vm_start == 0) -+ return 0; -+ if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) -+ return -EINVAL; -+ off = vma->vm_pgoff << PAGE_SHIFT; -+ start = info->fix.smem_start; -+ len = info->fix.smem_len; -+ if (off >= len) -+ { -+ return -EINVAL; -+ -+ } -+ if ((vma->vm_end - vma->vm_start + off) > len) -+ { -+ return -EINVAL; -+ } -+ off += start; -+ vma->vm_pgoff = off >> PAGE_SHIFT; -+ if (remap_pfn_range(vma, vma->vm_start, virt_to_phys((void *)info->fix.smem_start) >> PAGE_SHIFT, -+ info->fix.smem_len, vma->vm_page_prot)) -+ -+ { -+ return -EAGAIN; -+ } -+ return 0; -+ -+} -+ -+static struct fb_ops novafb_ops = { -+ .owner = THIS_MODULE, -+ .fb_open = novafb_open, -+ .fb_read = fb_sys_read, -+ .fb_write = novafb_write, -+ .fb_release = novafb_release, -+ .fb_pan_display = novafb_pan_display, -+ .fb_fillrect = novafb_fillrect, -+ .fb_copyarea = novafb_copyarea, -+ .fb_imageblit = novafb_imageblit, -+// .fb_ioctl = novafb_ioctl, -+ .fb_mmap =novafb_mmap, -+}; -+ -+ -+static void -+novafb_refresh(int ignore_me ) -+{ -+ struct novafb_par *par = info->par; -+ novafb_lcd_update(par, 0, 0, 128,128); -+ fb_timer.expires = jiffies + (HZ/FRAME_PER_SECOND); -+ add_timer(&fb_timer); -+} -+ -+static int -+__init novafb_probe(struct platform_device *dev) -+{ -+ -+ int retval = -ENOMEM; -+ char * src; -+ int i; -+ -+ struct novafb_par *par; -+ static unsigned char *videomemory; -+ static int videomemorysize; -+ -+ NT7506_init_lcd(CONTRASTE); -+ -+ videomemorysize = (128*128/8)*2; -+ -+ if (!(videomemory = kmalloc(videomemorysize,GFP_ATOMIC))) -+ return retval; -+ memset(videomemory, 0, videomemorysize); -+ -+ info = framebuffer_alloc(sizeof(struct novafb_par), &dev->dev); -+ -+ if (!info) -+ goto err; -+ info->screen_base = (char __iomem *)videomemory; -+ info->fbops = &novafb_ops; -+ -+ info->var = novafb_var; -+ info->fix = novafb_fix; -+ info->fix.smem_start=(unsigned long)videomemory; -+ info->fix.smem_len = videomemorysize; -+ -+ par = info->par; -+ par->info = info; -+ par->cslut[0] = 0x00; -+ par->cslut[1] = 0x06; -+ src = (unsigned char __force *) par->info->screen_base; -+ for(i=0;iflags = FBINFO_FLAG_DEFAULT; -+ spin_lock_init(&par->lock); -+ platform_set_drvdata(dev, info); -+ retval = register_framebuffer(info); -+ if (retval < 0) -+ goto err1; -+ -+ init_timer(&fb_timer); -+ fb_timer.function = novafb_refresh; -+ fb_timer.expires = jiffies + (HZ / FRAME_PER_SECOND); -+ add_timer(&fb_timer); -+ -+ printk(KERN_INFO -+ "fb%d: nova frame buffer device, using %dK of video memory\n", -+ info->node, videomemorysize >> 10); -+ return 0; -+err1: -+ framebuffer_release(info); -+err: -+ vfree(videomemory); -+ return retval; -+} -+ -+static int novafb_remove(struct platform_device *dev) -+{ -+ struct fb_info *info = platform_get_drvdata(dev); -+ -+ if (info) { -+ unregister_framebuffer(info); -+ vfree((void __force *)info->screen_base); -+ framebuffer_release(info); -+ } -+ return 0; -+} -+ -+static struct platform_driver novafb_driver = { -+ .probe = novafb_probe, -+ .remove = novafb_remove, -+ .driver = { -+ .name = "novafb", -+ }, -+}; -+ -+static struct platform_device *novafb_device; -+ -+static int __init novafb_init(void) -+{ -+ int ret; -+ -+ -+ if (!(lcd_mem = request_mem_region(LCD_BASE, LCD_SIZE, "mpc8313-lcd"))) -+ return -ENOMEM; -+ -+ if (!(_lcd_io = ioremap(LCD_BASE, LCD_SIZE))) -+ { -+ release_mem_region(LCD_BASE, LCD_SIZE); -+ lcd_mem = NULL; -+ return -ENOMEM; -+ } -+ ret = platform_driver_register(&novafb_driver); -+ -+ if (!ret) { -+ novafb_device = platform_device_alloc("novafb", 0); -+ if (novafb_device) -+ { -+ ret = platform_device_add(novafb_device); -+ } -+ else -+ { -+ ret = -ENOMEM; -+ } -+ if (ret) -+ { -+ platform_device_put(novafb_device); -+ platform_driver_unregister(&novafb_driver); -+ } -+ -+ } -+ -+ -+ return ret; -+ -+} -+ -+ -+static void NT7506_init_lcd(char ael) -+{ -+ /* this resets the lcd*/ -+ iowrite16(LCD_RSTN | LCD_ERD | LCD_BCKLIGH, _lcd_io); -+ udelay(100); -+ iowrite16(LCD_RST| LCD_ERD | LCD_BCKLIGH, _lcd_io); -+ udelay(200); -+ /* Soft reset*/ -+ NT7506_writeb_ctl(NT_RESET); -+ /* Disable ICON display*/ -+ NT7506_writeb_ctl(NT_ICON|OFF); -+ /* Sets the duty ratio 1/128*/ -+ NT7506_writeb_ctl(NT_DUTY); NT7506_writeb_ctl(DUTY_1_128); -+ /* Sets reverse direction between RAM column address and segment driver*/ -+ NT7506_writeb_ctl(NT_ADC_REV); -+ NT7506_writeb_ctl(NT_SHL_NOR); -+ /* Enales the built in Oscillator circuit.*/ -+ NT7506_writeb_ctl(NT_OSC); -+ /* Set Initial row to 0*/ -+ NT7506_writeb_ctl(NT_COM0); NT7506_writeb_ctl(0); -+ /* Sets DC-DC*/ -+ NT7506_writeb_ctl(NT_DCDC|TIME6); -+ /* Selects resistance ratio of the internal resistor*/ -+ NT7506_writeb_ctl(NT_REG_RES|RES_7_2); -+ /* set Reference Voltage mode*/ -+ NT7506_writeb_ctl(NT_ELEC_VOL); NT7506_writeb_ctl(ael); -+ /* Selects LCD bias ratio*/ -+ NT7506_writeb_ctl(NT_BIAS|BIAS_1_11); -+ -+ NT7506_writeb_ctl(NT_DATA_DIR); NT7506_writeb_ctl(0); -+ NT7506_writeb_ctl(NT_FRC_PWM|PWM15); -+ /* Select power circuit functions */ -+ NT7506_writeb_ctl(NT_POWER|VC); -+ udelay(5000); -+ NT7506_writeb_ctl(NT_POWER|VC|VR); -+ udelay(5000); -+ NT7506_writeb_ctl(NT_POWER|VC|VR|VF); -+ udelay(5000); -+ /* Reverses the display status on LCD panel */ -+ NT7506_writeb_ctl(NT_REV_DISP|OFF); -+ /* Forces the whole LCD points to be turned on regardless of the contents of the display data RAM*/ -+ NT7506_writeb_ctl(NT_DISP|ON); -+ /* Set Initial Start Line Address */ -+ NT7506_writeb_ctl(NT_START_LINE); NT7506_writeb_ctl(0x00); -+ -+} -+ -+static void __exit novafb_exit(void) -+{ -+ if (lcd_mem) -+ release_mem_region(LCD_BASE, LCD_SIZE); -+ lcd_mem = NULL; -+ platform_device_unregister(novafb_device); -+ platform_driver_unregister(&novafb_driver); -+} -+ -+module_param(tuhold, ulong, 0); -+MODULE_PARM_DESC(tuhold, "Time to hold between strobing data to Nova board"); -+ -+module_init(novafb_init); -+module_exit(novafb_exit); -+ -+MODULE_DESCRIPTION("fbdev driver for nova NT7506 monochrome LCD board"); -+MODULE_AUTHOR("Alexandre Coffignal"); -+MODULE_LICENSE("GPL"); -+ -diff -uNr linux-2.6.26_orig/include/linux/NT7506.h linux-2.6.26/include/linux/NT7506.h ---- linux-2.6.26_orig/include/linux/NT7506.h 1970-01-01 01:00:00.000000000 +0100 -+++ linux-2.6.26/include/linux/NT7506.h 2008-11-13 12:46:05.000000000 +0100 -@@ -0,0 +1,70 @@ -+ -+/* -+ * (C) Copyright 2008 -+ * Alexandre Coffignal, CénoSYS, alexandre.coffignal@cenosys.com -+ * -+ * See file CREDITS for list of people who contributed to this -+ * project. -+ * -+ * 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. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, -+ * MA 02111-1307 USA -+ * -+ */ -+ -+#ifndef __LINUX_NOVAFB_H__ -+#define __LINUX_NOVAFB_H__ -+ -+ -+//NT7506 Instructions -+#define NT_ICON 0xA2 -+#define NT_PAGE_ADDR 0xB0 -+#define NT_COL_MSB 0x10 -+#define NT_COL_LSB 0x00 -+#define NT_DISP 0xAE -+#define NT_START_LINE 0x40 -+#define NT_COM0 0x44 -+#define NT_DUTY 0x48 -+#define DUTY_1_128 0x80 -+#define NT_REV_DISP 0xA6 -+#define NT_POWER 0x28 -+#define VC 0x04 -+#define VR 0x02 -+#define VF 0x01 -+#define NT_DCDC 0x64 -+#define TIME6 0x03 -+#define NT_REG_RES 0x20 -+#define RES_7_2 0x07 -+#define NT_ELEC_VOL 0x81 -+#define NT_BIAS 0x50 -+#define BIAS_1_11 0x06 -+#define NT_ADC_NOR 0xA0 -+#define NT_ADC_REV 0xA1 -+#define NT_SHL_NOR 0xC0 -+#define NT_SHL_REV 0xC8 -+#define NT_OSC 0xAB -+#define NT_RESET 0xE2 -+#define NT_DATA_DIR 0xe8 -+#define NT_FRC_PWM 0x90 -+#define PWM15 0x03 -+ -+#define ON 0x01 -+#define OFF 0x00 -+ -+ -+ -+ -+ -+#endif -+ diff --git a/packages/linux/linux-2.6.26/boc01/013-081212-lcd.patch b/packages/linux/linux-2.6.26/boc01/013-081212-lcd.patch new file mode 100644 index 0000000000..340a157f3a --- /dev/null +++ b/packages/linux/linux-2.6.26/boc01/013-081212-lcd.patch @@ -0,0 +1,751 @@ +Index: linux-2.6.26/drivers/video/Kconfig +=================================================================== +--- linux-2.6.26.orig/drivers/video/Kconfig 2008-07-13 23:51:29.000000000 +0200 ++++ linux-2.6.26/drivers/video/Kconfig 2008-12-09 10:01:14.000000000 +0100 +@@ -480,6 +480,17 @@ + this driver, say Y or M; otherwise say N. You must specify the + GPIO IO address to be used for setting control and data. + ++config FB_NOVA ++ tristate "Nova 7506 Monochrome LCD board support" ++ depends on FB ++ select FB_SYS_FILLRECT ++ select FB_SYS_COPYAREA ++ select FB_SYS_IMAGEBLIT ++ select FB_SYS_FOPS ++ help ++ This enables support for the Nova 7506 Monochrome LCD board. The board ++ is based on the NT7506 lcd controller. ++ + config FB_ATARI + bool "Atari native chipset support" + depends on (FB = y) && ATARI +Index: linux-2.6.26/drivers/video/Makefile +=================================================================== +--- linux-2.6.26.orig/drivers/video/Makefile 2008-07-13 23:51:29.000000000 +0200 ++++ linux-2.6.26/drivers/video/Makefile 2008-12-09 10:01:14.000000000 +0100 +@@ -13,8 +13,8 @@ + + obj-$(CONFIG_VT) += console/ + obj-$(CONFIG_LOGO) += logo/ +-obj-y += backlight/ display/ +- ++obj-y += backlight/ display/ ++obj-$(CONFIG_FB_NOVA) += N7506fb.o + obj-$(CONFIG_FB_CFB_FILLRECT) += cfbfillrect.o + obj-$(CONFIG_FB_CFB_COPYAREA) += cfbcopyarea.o + obj-$(CONFIG_FB_CFB_IMAGEBLIT) += cfbimgblt.o +Index: linux-2.6.26/drivers/video/N7506fb.c +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ linux-2.6.26/drivers/video/N7506fb.c 2008-12-09 10:03:34.000000000 +0100 +@@ -0,0 +1,631 @@ ++/* ++ * linux/drivers/video/N7506fb.c -- FB driver for Nova NT7506 monochrome LCD board ++ * ++ * Copyright (C) 2008, Alexandre Coffignal ++ * ++ * This file is subject to the terms and conditions of the GNU General Public ++ * License. See the file COPYING in the main directory of this archive for ++ * more details. ++ * ++ * Layout is based on arcfb.c by Jaya Kumar ++ * ++ * This driver was written to be used with the Nova 7506 LCD board. ++ * ++ * ++ * ++ * ++ * Nova uses a ++ * set of NT7506 chips that control individual 128x128 LCD matrices. ++ * The interface between the board and the host is TTL based GPIO. ++ * ++ * General notes: ++ * - User must set tuhold. It's in microseconds. According to the 108 spec, ++ * the hold time is supposed to be at least 1 microsecond. ++ * ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++ ++#define floor8(a) (a&(~0x07)) ++#define floorXres(a,xres) (a&(~(xres - 1))) ++#define iceil8(a) (((int)((a+7)/8))*8) ++#define ceil128(a) (a|0x7F) ++#define ceilXres(a,xres) (a|(xres - 1)) ++ ++//NT7506 Hardware ++#define LCD_RST 0x08 ++#define LCD_RSTN 0x00 ++#define LCD_BCKLIGH 0x04 ++#define LCD_BCKLIGHN 0x00 ++#define LCD_RS 0x02 ++#define LCD_RSN 0x00 ++#define LCD_ERD 0x01 ++#define LCD_ERDN 0x00 ++ ++//Base address ++#define LCD_BASE 0xf0000000 ++#define LCD_SIZE 0x2 ++ ++#define CONTRASTE 0xF ++#define FRAME_PER_SECOND 5 ++ ++static struct resource *lcd_mem = NULL; ++static void * _lcd_io = NULL; ++static unsigned long tuhold; ++struct fb_info *info; ++static struct timer_list fb_timer; ++static char _refresh; ++static char _fps =FRAME_PER_SECOND; ++static char _backlight=1; ++ ++struct novafb_par { ++ atomic_t ref_count; ++ unsigned char cslut[9]; ++ struct fb_info *info; ++ unsigned int irq; ++ spinlock_t lock; ++}; ++ ++static struct fb_fix_screeninfo novafb_fix __initdata = { ++ .id = "novafb", ++ .type = FB_TYPE_PACKED_PIXELS, ++ .visual = FB_VISUAL_MONO01, ++ .xpanstep = 1, ++ .ypanstep = 1, ++ .ywrapstep = 0, ++ .line_length=16, ++ .accel = FB_ACCEL_NONE, ++}; ++ ++static struct fb_var_screeninfo novafb_var __initdata = { ++ .xres = 128, ++ .yres = 128, ++ .xres_virtual = 128, ++ .yres_virtual = 128, ++ .bits_per_pixel = 1, ++ .nonstd = 1, ++}; ++ ++ ++static void NT7506_init_lcd(char ael); ++ ++static void NT7506_writeb_ctl(unsigned char value,char backlight) ++{ ++ unsigned short svalue; ++ char bl; ++ if(backlight) ++ bl=LCD_BCKLIGH; ++ else ++ bl=LCD_BCKLIGHN; ++ ++ svalue=value<<8 | LCD_RSN | LCD_RST | LCD_ERDN | bl; ++ iowrite16(svalue, _lcd_io); ++ udelay(tuhold); ++ //The data on DB0/7 are latched at the falling edge of the E_RD signal ++ svalue=value<<8 | LCD_RSN | LCD_RST | LCD_ERD | bl; ++ iowrite16(svalue, _lcd_io); ++ udelay(tuhold); ++} ++ ++static void NT7506_writeb_data(unsigned char value,char backlight) ++{ ++ unsigned short svalue; ++ char bl; ++ if(backlight) ++ bl=LCD_BCKLIGH; ++ else ++ bl=LCD_BCKLIGHN; ++ svalue=value<<8|LCD_RS |LCD_RST | LCD_ERD | bl ; ++ iowrite16(svalue, _lcd_io); ++ udelay(tuhold); ++ //The data on DB0/7 are latched at the falling edge of the E_RD signal ++ svalue=value<<8|LCD_RS |LCD_RST | LCD_ERDN | bl; ++ iowrite16(svalue, _lcd_io); ++ udelay(tuhold); ++} ++ ++static void NT7506_set_start_line(unsigned char y) ++{ ++ NT7506_writeb_ctl(NT_START_LINE,_backlight); ++ NT7506_writeb_ctl(y,_backlight); ++} ++ ++static void NT7506_set_yaddr(unsigned char y) ++{ ++ NT7506_writeb_ctl(NT_PAGE_ADDR+y,_backlight); ++} ++ ++static void NT7506_set_xaddr(unsigned char x) ++{ ++ NT7506_writeb_ctl(NT_COL_MSB | (x >> 0x04),_backlight); //Send high nibble ++ NT7506_writeb_ctl(NT_COL_LSB | (x & 0x0F) ,_backlight); //Send low nibble ++} ++ ++/* main novafb functions */ ++ ++static int novafb_open(struct fb_info *info, int user) ++{ ++ struct novafb_par *par = info->par; ++ atomic_inc(&par->ref_count); ++ return 0; ++} ++ ++static int novafb_release(struct fb_info *info, int user) ++{ ++ struct novafb_par *par = info->par; ++ int count = atomic_read(&par->ref_count); ++ if (!count) ++ return -EINVAL; ++ atomic_dec(&par->ref_count); ++ return 0; ++} ++ ++static int novafb_pan_display(struct fb_var_screeninfo *var, ++ struct fb_info *info) ++{ ++ if ((var->vmode & FB_VMODE_YWRAP) && (var->yoffset < 128) ++ && (info->var.yres <= 128)) ++ { ++ NT7506_set_start_line(var->yoffset); ++ info->var.yoffset = var->yoffset; ++ return 0; ++ } ++ ++ return -EINVAL; ++} ++ ++static void novafb_lcd_update(struct novafb_par *par, unsigned int dx, ++ unsigned int dy, unsigned int w, unsigned int h) ++{ ++ int bit,x,y,xfb,yfb,width,height,i; ++ char mask=0; ++ char dest[2048]; ++ char * src; ++ char value; ++ src = (unsigned char __force *) par->info->screen_base; ++ for(i=0;i<2048;i++) ++ { ++ dest[i]=0; ++ } ++ for(x=0;x<128/*(width)*/;x++) ++ { ++ for(y=0;y<16/*height/8*/;y++) ++ { ++ xfb=x/8; ++ yfb=y*8; ++ ++ for(bit=0;bit<8;yfb++,bit++) ++ { ++ mask = (1<<(7-(x%8))); ++ if(((src[yfb*16+xfb]&mask))) ++ value=1; ++ else ++ value=0; ++ ++ dest[y*128+x]+= (value<par; ++ ++ int xfb,yfb,i=0; ++ char * src = (unsigned char __force *) par->info->screen_base; ++ ++ for(yfb=image->dy;yfb<(image->height+image->dy);yfb++) ++ { ++ for(xfb=(image->dx)/8;xfb<(image->dx+image->width)/8;xfb++) ++ { ++ src[yfb*16+xfb]=image->data[i++]; ++ } ++ } ++ ++} ++ ++/* ++ * this is the access path from userspace. they can seek and write to ++ * the fb. it's inefficient for them to do anything less than 128*8 ++ * writes since we update the lcd in each write() anyway. ++ */ ++static ssize_t novafb_write(struct fb_info *info, const char __user *buf, ++ size_t count, loff_t *ppos) ++{ ++ unsigned long p; ++ int err=-EINVAL; ++ unsigned int fbmemlength ; ++ struct novafb_par *par; ++ unsigned int xres; ++ p = *ppos; ++ par = info->par; ++ xres = info->var.xres; ++ fbmemlength = (xres * info->var.yres)/8; ++ ++ if (p > fbmemlength) ++ { ++ return -ENOSPC; ++ } ++ err = 0; ++ if ((count + p) > fbmemlength) { ++ count = fbmemlength - p; ++ err = -ENOSPC; ++ } ++ ++ if (count) { ++ char *base_addr; ++ base_addr = (char __force *)info->screen_base; ++ count -= copy_from_user(base_addr + p, buf, count); ++ *ppos += count; ++ err = -EFAULT; ++ } ++ if (count) ++ { ++ return count; ++ } ++ return err; ++} ++ ++static int novafb_mmap(struct fb_info *info, struct vm_area_struct *vma) ++{ ++ unsigned long off; ++ unsigned long start; ++ u32 len; ++ ++ if (vma->vm_end - vma->vm_start == 0) ++ return 0; ++ if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) ++ return -EINVAL; ++ off = vma->vm_pgoff << PAGE_SHIFT; ++ start = info->fix.smem_start; ++ len = info->fix.smem_len; ++ if (off >= len) ++ { ++ return -EINVAL; ++ ++ } ++ if ((vma->vm_end - vma->vm_start + off) > len) ++ { ++ return -EINVAL; ++ } ++ off += start; ++ vma->vm_pgoff = off >> PAGE_SHIFT; ++ if (remap_pfn_range(vma, vma->vm_start, virt_to_phys((void *)info->fix.smem_start) >> PAGE_SHIFT, ++ info->fix.smem_len, vma->vm_page_prot)) ++ ++ { ++ return -EAGAIN; ++ } ++ return 0; ++ ++} ++static int novafb_ioctl(struct fb_info *info, ++ unsigned int cmd, unsigned long arg) ++{ ++ unsigned char contrast; ++ unsigned char frame_rate; ++ unsigned char backlight; ++ switch (cmd) ++ { ++ case FBIO_FRAMERATE: ++ { ++ ++ if (get_user(frame_rate, (unsigned char *)arg)) ++ return -EFAULT; ++ printk(KERN_INFO "fb0: framerate=%d Hz\n",frame_rate); ++ _fps=frame_rate; ++ return 0; ++ } ++ case FBIO_CONTRAST: ++ { ++ _refresh=0; ++ if (get_user(contrast, (unsigned char *)arg)) ++ return -EFAULT; ++ printk(KERN_INFO "fb0: contrast=%d\n",contrast); ++ NT7506_writeb_ctl(NT_ELEC_VOL,_backlight); NT7506_writeb_ctl(contrast,_backlight); ++ _refresh=1; ++ return 0; ++ } ++ case FBIO_BACKLIGHT: ++ { ++ _refresh=0; ++ if (get_user(backlight, (unsigned char *)arg)) ++ return -EFAULT; ++ if(backlight) ++ { ++ printk(KERN_INFO "fb0: Backlight ON\n"); ++ _backlight=1; ++ } ++ else ++ { ++ printk(KERN_INFO "fb0: Backlight OFF\n"); ++ _backlight=0; ++ } ++ _refresh=1; ++ return 0; ++ ++ } ++ ++ ++ default: ++ return -EINVAL; ++ } ++ ++} ++ ++static struct fb_ops novafb_ops = { ++ .owner = THIS_MODULE, ++ .fb_open = novafb_open, ++ .fb_read = fb_sys_read, ++ .fb_write = novafb_write, ++ .fb_release = novafb_release, ++ .fb_pan_display = novafb_pan_display, ++ .fb_fillrect = novafb_fillrect, ++ .fb_copyarea = novafb_copyarea, ++ .fb_imageblit = novafb_imageblit, ++ .fb_ioctl = novafb_ioctl, ++ .fb_mmap =novafb_mmap, ++}; ++ ++ ++static void ++novafb_refresh(int ignore_me ) ++{ ++ struct novafb_par *par = info->par; ++ if(_refresh) ++ { ++ novafb_lcd_update(par, 0, 0, 128,128); ++ fb_timer.expires = jiffies + (HZ/_fps); ++ add_timer(&fb_timer); ++ } ++ else ++ { ++ fb_timer.expires = jiffies + (HZ/_fps); ++ add_timer(&fb_timer); ++ } ++} ++ ++static int ++__init novafb_probe(struct platform_device *dev) ++{ ++ ++ int retval = -ENOMEM; ++ char * src; ++ int i; ++ ++ struct novafb_par *par; ++ static unsigned char *videomemory; ++ static int videomemorysize; ++ ++ NT7506_init_lcd(CONTRASTE); ++ ++ videomemorysize = (128*128/8)*2; ++ ++ if (!(videomemory = kmalloc(videomemorysize,GFP_ATOMIC))) ++ return retval; ++ memset(videomemory, 0, videomemorysize); ++ ++ info = framebuffer_alloc(sizeof(struct novafb_par), &dev->dev); ++ ++ if (!info) ++ goto err; ++ info->screen_base = (char __iomem *)videomemory; ++ info->fbops = &novafb_ops; ++ ++ info->var = novafb_var; ++ info->fix = novafb_fix; ++ info->fix.smem_start=(unsigned long)videomemory; ++ info->fix.smem_len = videomemorysize; ++ ++ par = info->par; ++ par->info = info; ++ par->cslut[0] = 0x00; ++ par->cslut[1] = 0x06; ++ src = (unsigned char __force *) par->info->screen_base; ++ for(i=0;iflags = FBINFO_FLAG_DEFAULT; ++ spin_lock_init(&par->lock); ++ platform_set_drvdata(dev, info); ++ retval = register_framebuffer(info); ++ if (retval < 0) ++ goto err1; ++ ++ init_timer(&fb_timer); ++ fb_timer.function = novafb_refresh; ++ fb_timer.expires = jiffies + (HZ / _fps); ++ add_timer(&fb_timer); ++ ++ printk(KERN_INFO ++ "fb%d: nova frame buffer device, using %dK of video memory\n", ++ info->node, videomemorysize >> 10); ++ return 0; ++err1: ++ framebuffer_release(info); ++err: ++ vfree(videomemory); ++ return retval; ++} ++ ++static int novafb_remove(struct platform_device *dev) ++{ ++ struct fb_info *info = platform_get_drvdata(dev); ++ ++ if (info) { ++ unregister_framebuffer(info); ++ vfree((void __force *)info->screen_base); ++ framebuffer_release(info); ++ } ++ return 0; ++} ++ ++static struct platform_driver novafb_driver = { ++ .probe = novafb_probe, ++ .remove = novafb_remove, ++ .driver = { ++ .name = "novafb", ++ }, ++}; ++ ++static struct platform_device *novafb_device; ++ ++static int __init novafb_init(void) ++{ ++ int ret; ++ ++ ++ if (!(lcd_mem = request_mem_region(LCD_BASE, LCD_SIZE, "mpc8313-lcd"))) ++ return -ENOMEM; ++ ++ if (!(_lcd_io = ioremap(LCD_BASE, LCD_SIZE))) ++ { ++ release_mem_region(LCD_BASE, LCD_SIZE); ++ lcd_mem = NULL; ++ return -ENOMEM; ++ } ++ ret = platform_driver_register(&novafb_driver); ++ ++ if (!ret) { ++ novafb_device = platform_device_alloc("novafb", 0); ++ if (novafb_device) ++ { ++ ret = platform_device_add(novafb_device); ++ } ++ else ++ { ++ ret = -ENOMEM; ++ } ++ if (ret) ++ { ++ platform_device_put(novafb_device); ++ platform_driver_unregister(&novafb_driver); ++ } ++ ++ } ++ ++ ++ return ret; ++ ++} ++ ++ ++static void NT7506_init_lcd(char ael) ++{ ++ /* this resets the lcd*/ ++ char bl; ++ if(_backlight) ++ bl=LCD_BCKLIGH; ++ else ++ bl=LCD_BCKLIGHN; ++ ++ iowrite16(LCD_RSTN | LCD_ERD | bl, _lcd_io); ++ udelay(100); ++ iowrite16(LCD_RST| LCD_ERD | bl, _lcd_io); ++ udelay(200); ++ /* Soft reset*/ ++ NT7506_writeb_ctl(NT_RESET,_backlight); ++ /* Disable ICON display*/ ++ NT7506_writeb_ctl(NT_ICON|OFF,_backlight); ++ /* Sets the duty ratio 1/128*/ ++ NT7506_writeb_ctl(NT_DUTY,_backlight); NT7506_writeb_ctl(DUTY_1_128,_backlight); ++ /* Sets reverse direction between RAM column address and segment driver*/ ++ NT7506_writeb_ctl(NT_ADC_REV,_backlight); ++ NT7506_writeb_ctl(NT_SHL_NOR,_backlight); ++ /* Enales the built in Oscillator circuit.*/ ++ NT7506_writeb_ctl(NT_OSC,_backlight); ++ /* Set Initial row to 0*/ ++ NT7506_writeb_ctl(NT_COM0,_backlight); NT7506_writeb_ctl(0,_backlight); ++ /* Sets DC-DC*/ ++ NT7506_writeb_ctl(NT_DCDC|TIME6,_backlight); ++ /* Selects resistance ratio of the internal resistor*/ ++ NT7506_writeb_ctl(NT_REG_RES|RES_7_2,_backlight); ++ /* set Reference Voltage mode*/ ++ NT7506_writeb_ctl(NT_ELEC_VOL,_backlight); NT7506_writeb_ctl(ael,_backlight); ++ /* Selects LCD bias ratio*/ ++ NT7506_writeb_ctl(NT_BIAS|BIAS_1_11,_backlight); ++ ++ NT7506_writeb_ctl(NT_DATA_DIR,_backlight); NT7506_writeb_ctl(0,_backlight); ++ NT7506_writeb_ctl(NT_FRC_PWM|PWM15,_backlight); ++ /* Select power circuit functions */ ++ NT7506_writeb_ctl(NT_POWER|VC,_backlight); ++ udelay(5000); ++ NT7506_writeb_ctl(NT_POWER|VC|VR,_backlight); ++ udelay(5000); ++ NT7506_writeb_ctl(NT_POWER|VC|VR|VF,_backlight); ++ udelay(5000); ++ /* Reverses the display status on LCD panel */ ++ NT7506_writeb_ctl(NT_REV_DISP|OFF,_backlight); ++ /* Forces the whole LCD points to be turned on regardless of the contents of the display data RAM*/ ++ NT7506_writeb_ctl(NT_DISP|ON,_backlight); ++ /* Set Initial Start Line Address */ ++ NT7506_writeb_ctl(NT_START_LINE,_backlight); NT7506_writeb_ctl(0x00,_backlight); ++ _refresh=1; ++} ++ ++static void __exit novafb_exit(void) ++{ ++ if (lcd_mem) ++ release_mem_region(LCD_BASE, LCD_SIZE); ++ lcd_mem = NULL; ++ platform_device_unregister(novafb_device); ++ platform_driver_unregister(&novafb_driver); ++} ++ ++module_param(tuhold, ulong, 0); ++MODULE_PARM_DESC(tuhold, "Time to hold between strobing data to Nova board"); ++ ++module_init(novafb_init); ++module_exit(novafb_exit); ++ ++MODULE_DESCRIPTION("fbdev driver for nova NT7506 monochrome LCD board"); ++MODULE_AUTHOR("Alexandre Coffignal"); ++MODULE_LICENSE("GPL"); ++ +Index: linux-2.6.26/include/linux/NT7506.h +=================================================================== +--- /dev/null 1970-01-01 00:00:00.000000000 +0000 ++++ linux-2.6.26/include/linux/NT7506.h 2008-12-09 10:04:16.000000000 +0100 +@@ -0,0 +1,73 @@ ++ ++/* ++ * (C) Copyright 2008 ++ * Alexandre Coffignal, CénoSYS, alexandre.coffignal@cenosys.com ++ * ++ * See file CREDITS for list of people who contributed to this ++ * project. ++ * ++ * 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. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, ++ * MA 02111-1307 USA ++ * ++ */ ++ ++#ifndef __LINUX_NOVAFB_H__ ++#define __LINUX_NOVAFB_H__ ++ ++ ++//NT7506 Instructions ++#define NT_ICON 0xA2 ++#define NT_PAGE_ADDR 0xB0 ++#define NT_COL_MSB 0x10 ++#define NT_COL_LSB 0x00 ++#define NT_DISP 0xAE ++#define NT_START_LINE 0x40 ++#define NT_COM0 0x44 ++#define NT_DUTY 0x48 ++#define DUTY_1_128 0x80 ++#define NT_REV_DISP 0xA6 ++#define NT_POWER 0x28 ++#define VC 0x04 ++#define VR 0x02 ++#define VF 0x01 ++#define NT_DCDC 0x64 ++#define TIME6 0x03 ++#define NT_REG_RES 0x20 ++#define RES_7_2 0x07 ++#define NT_ELEC_VOL 0x81 ++#define NT_BIAS 0x50 ++#define BIAS_1_11 0x06 ++#define NT_ADC_NOR 0xA0 ++#define NT_ADC_REV 0xA1 ++#define NT_SHL_NOR 0xC0 ++#define NT_SHL_REV 0xC8 ++#define NT_OSC 0xAB ++#define NT_RESET 0xE2 ++#define NT_DATA_DIR 0xe8 ++#define NT_FRC_PWM 0x90 ++#define PWM15 0x03 ++ ++#define ON 0x01 ++#define OFF 0x00 ++ ++ ++ ++#define FBIO_FRAMERATE _IOR('f', 1, char) ++#define FBIO_CONTRAST _IOR('f', 2, char) ++#define FBIO_BACKLIGHT _IOR('f', 3, char) ++ ++ ++#endif ++ diff --git a/packages/linux/linux-2.6.26/boc01/defconfig b/packages/linux/linux-2.6.26/boc01/defconfig index a61f6121fc..726e955a2d 100644 --- a/packages/linux/linux-2.6.26/boc01/defconfig +++ b/packages/linux/linux-2.6.26/boc01/defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit # Linux kernel version: 2.6.26 -# Tue Dec 9 15:33:40 2008 +# Wed Dec 17 12:15:19 2008 # # CONFIG_PPC64 is not set @@ -1038,6 +1038,7 @@ CONFIG_HW_RANDOM=y # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set CONFIG_GPIO_MPC8313=y +CONFIG_EXIO_MPC8313=y # CONFIG_RAW_DRIVER is not set # CONFIG_TCG_TPM is not set CONFIG_DEVPORT=y @@ -1077,7 +1078,6 @@ CONFIG_I2C_MPC=y # # Miscellaneous I2C Chip support # -CONFIG_AT24C32=y # CONFIG_DS1682 is not set CONFIG_ISL12024EEPROM=y # CONFIG_SENSORS_EEPROM is not set @@ -1086,6 +1086,7 @@ CONFIG_ISL12024EEPROM=y # CONFIG_SENSORS_PCF8591 is not set # CONFIG_SENSORS_MAX6875 is not set # CONFIG_SENSORS_TSL2550 is not set +CONFIG_EEPROM_RW=y # CONFIG_I2C_DEBUG_CORE is not set # CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set @@ -1282,8 +1283,7 @@ CONFIG_FB_NOVA=y # # Console display driver support # -CONFIG_VGA_CONSOLE=y -# CONFIG_VGACON_SOFT_SCROLLBACK is not set +# CONFIG_VGA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y CONFIG_FRAMEBUFFER_CONSOLE=y CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y diff --git a/packages/linux/linux_2.6.26.bb b/packages/linux/linux_2.6.26.bb index bb4df19c3a..c3fa981292 100644 --- a/packages/linux/linux_2.6.26.bb +++ b/packages/linux/linux_2.6.26.bb @@ -1,6 +1,6 @@ require linux.inc -PR = "r3" +PR = "r4" # Mark archs/machines that this kernel supports DEFAULT_PREFERENCE = "-1" @@ -17,14 +17,14 @@ SRC_URI_append_boc01 = "\ file://fsl-elbc-nand-backport.patch;patch=1 \ file://002-081105-headers.patch;patch=1 \ file://004-081105-usb.patch;patch=1 \ - file://005-081127-isl12024.patch;patch=1 \ - file://006-081105-at24c32.patch;patch=1 \ - file://007-081127-lm73.patch;patch=1 \ + file://005-081217-isl12024.patch;patch=1 \ + file://006-081216-at24c32.patch;patch=1 \ + file://007-081216-lm73.patch;patch=1 \ file://008-081127-spi.patch;patch=1 \ file://010-081105-mii.patch;patch=1 \ - file://011-081105-gpio.patch;patch=1 \ + file://011-081202-gpio.patch;patch=1 \ file://012-081121-cy3218-btns.patch;patch=1 \ - file://013-081127-lcd.patch;patch=1 \ + file://013-081212-lcd.patch;patch=1 \ " SRC_URI_append_mpc8313e-rdb = "\ -- cgit v1.2.3