diff options
author | Jeremy Lainé <jeremy.laine@m4x.org> | 2009-11-03 11:39:07 +0100 |
---|---|---|
committer | Jeremy Lainé <jeremy.laine@m4x.org> | 2009-11-03 11:39:07 +0100 |
commit | b8f658eb9142bd89cb1cf5b5261a980f3ebf841c (patch) | |
tree | e803b7c4262f769f65c2a30ba902c1ddbf6c11b8 /recipes/linux/linux-2.6.31/boc01 | |
parent | f0792ef5d7d067718450ba9584283844b324ee87 (diff) |
linux-2.6.31: update boc01 RTC driver for upstream submission
Diffstat (limited to 'recipes/linux/linux-2.6.31/boc01')
-rw-r--r-- | recipes/linux/linux-2.6.31/boc01/005-091103-isl12024.patch (renamed from recipes/linux/linux-2.6.31/boc01/005-091008-isl12024.patch) | 339 |
1 files changed, 169 insertions, 170 deletions
diff --git a/recipes/linux/linux-2.6.31/boc01/005-091008-isl12024.patch b/recipes/linux/linux-2.6.31/boc01/005-091103-isl12024.patch index 401ce4d9c8..9daab5acaa 100644 --- a/recipes/linux/linux-2.6.31/boc01/005-091008-isl12024.patch +++ b/recipes/linux/linux-2.6.31/boc01/005-091103-isl12024.patch @@ -1,37 +1,44 @@ +Support for the ISL12024 RTC, EEPROM and unique ID. + +Signed-off-by: Jeremy Laine <jeremy.laine@m4x.org> + Index: linux-2.6.31/drivers/misc/eeprom/at24.c =================================================================== ---- linux-2.6.31.orig/drivers/misc/eeprom/at24.c 2009-10-19 16:55:01.000000000 +0200 -+++ linux-2.6.31/drivers/misc/eeprom/at24.c 2009-10-19 16:55:05.000000000 +0200 +--- linux-2.6.31.orig/drivers/misc/eeprom/at24.c 2009-09-10 00:13:59.000000000 +0200 ++++ linux-2.6.31/drivers/misc/eeprom/at24.c 2009-11-03 11:17:22.000000000 +0100 @@ -115,6 +115,8 @@ { "spd", AT24_DEVICE_MAGIC(2048 / 8, AT24_FLAG_READONLY | AT24_FLAG_IRUGO) }, { "24c04", AT24_DEVICE_MAGIC(4096 / 8, 0) }, -+ /* Intersil RTC/Unique-ID isl12024 eeprom handled here */ ++ /* Intersil isl12024 eeprom */ + { "isl12024-eeprom", AT24_DEVICE_MAGIC(4096 / 8, AT24_FLAG_ADDR16) }, /* 24rf08 quirk is handled at i2c-core */ { "24c08", AT24_DEVICE_MAGIC(8192 / 8, 0) }, { "24c16", AT24_DEVICE_MAGIC(16384 / 8, 0) }, Index: linux-2.6.31/drivers/rtc/Kconfig =================================================================== ---- linux-2.6.31.orig/drivers/rtc/Kconfig 2009-10-19 16:55:01.000000000 +0200 -+++ linux-2.6.31/drivers/rtc/Kconfig 2009-10-19 16:55:05.000000000 +0200 -@@ -128,6 +128,12 @@ - - if I2C +--- linux-2.6.31.orig/drivers/rtc/Kconfig 2009-09-10 00:13:59.000000000 +0200 ++++ linux-2.6.31/drivers/rtc/Kconfig 2009-11-03 11:13:42.000000000 +0100 +@@ -193,6 +193,15 @@ + This driver can also be built as a module. If so, the module + will be called rtc-isl1208. +config RTC_DRV_ISL12024 -+ tristate "Intersil 12024 RTC/Unique-ID" ++ tristate "Intersil 12024" + help -+ If you say yes .... -+ This driver can also be built as a module. ++ If you say yes here you get support for the Intersil ISL12024 ++ RTC chip. This driver also exposes the chip's unique ID. ++ ++ This driver can also be built as a module. If so, the module ++ will be called rtc-isl12024. + - config RTC_DRV_DS1307 - tristate "Dallas/Maxim DS1307/37/38/39/40, ST M41T00, EPSON RX-8025" + config RTC_DRV_X1205 + tristate "Xicor/Intersil X1205" help Index: linux-2.6.31/drivers/rtc/Makefile =================================================================== ---- linux-2.6.31.orig/drivers/rtc/Makefile 2009-10-19 16:55:01.000000000 +0200 -+++ linux-2.6.31/drivers/rtc/Makefile 2009-10-19 16:55:05.000000000 +0200 +--- linux-2.6.31.orig/drivers/rtc/Makefile 2009-09-10 00:13:59.000000000 +0200 ++++ linux-2.6.31/drivers/rtc/Makefile 2009-11-03 11:13:42.000000000 +0100 @@ -40,6 +40,7 @@ obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o obj-$(CONFIG_RTC_DRV_FM3130) += rtc-fm3130.o @@ -43,20 +50,23 @@ Index: linux-2.6.31/drivers/rtc/Makefile Index: linux-2.6.31/drivers/rtc/rtc-isl12024.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-2.6.31/drivers/rtc/rtc-isl12024.c 2009-10-19 16:57:37.000000000 +0200 -@@ -0,0 +1,465 @@ ++++ linux-2.6.31/drivers/rtc/rtc-isl12024.c 2009-11-03 11:14:33.000000000 +0100 +@@ -0,0 +1,457 @@ +/* -+ * Intersil ISL12024 class driver -+ * ++ * Intersil ISL12024 rtc class driver + * + * Copyright (C) 2007, CenoSYS (www.cenosys.com). -+ * ++ * Copyright (C) 2009, Bollore telecom (www.bolloretelecom.eu). ++ * + * Guillaume Ligneul <guillaume.ligneul@gmail.com> + * Sylvain Giroudon <sylvain.giroudon@goobie.fr> + * Jeremy Laine <jeremy.laine@bolloretelecom.eu> + * -+ * 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 ++ * Based on rtc-x1205. ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. + */ + +#include <linux/module.h> @@ -67,36 +77,7 @@ Index: linux-2.6.31/drivers/rtc/rtc-isl12024.c + +#define DRV_VERSION "0.3" + -+#define ISL12024_CCR_BASE 0x30 /* Base address of CCR */ -+#define ISL12024_ALM0_BASE 0x00 /* Base address of ALARM0 */ -+#define ISL12024_INT_AL0E 0x20 /* Alarm 0 enable */ -+ -+/* Register map */ -+ -+/* device id section */ -+#define ISL12024_REG_ID 0x20 -+ -+/* rtc section */ -+#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_SC 0x30 -+#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 ++/* offsets into CCR area */ + +#define CCR_SEC 0 +#define CCR_MIN 1 @@ -107,8 +88,31 @@ Index: linux-2.6.31/drivers/rtc/rtc-isl12024.c +#define CCR_WDAY 6 +#define CCR_Y2K 7 + -+static int isl12024_get_status(struct i2c_client *client, unsigned char *sr); -+static int isl12024_fix_osc(struct i2c_client *client); ++/* alarm0 section */ ++#define ISL12024_REG_ALARM0 0x08 /* Base address of ALARM0 */ ++ ++/* device id section */ ++#define ISL12024_REG_ID 0x20 ++#define ISL12024_ID_SECTION_LEN 8 ++ ++/* rtc section */ ++#define ISL12024_REG_RTC 0x30 /* Base address of RTC */ ++#define ISL12024_REG_HR_MIL (1<<7) /* 24h/12h mode */ ++#define ISL12024_REG_HR_PM (1<<5) /* AM/PM bit in 12h mode */ ++#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 ISL12024_INT_AL0E 0x20 /* Alarm 0 enable */ + +static struct i2c_driver isl12024_driver; + @@ -117,70 +121,68 @@ Index: linux-2.6.31/drivers/rtc/rtc-isl12024.c + unsigned len) +{ + int ret; -+ u8 dt_addr[2]; ++ 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, -+ }, ++ { ++ .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; ++ if (ret < 0) { ++ dev_err(&client->dev, "read error (%i)\n", ret); ++ return ret; + } -+ return ret; ++ return 0; +} + -+static int isl12024_i2c_validate_client(struct i2c_client *client) ++static int ++isl12024_i2c_set_regs(struct i2c_client *client, u8 reg, u8 const buf[], ++ unsigned len) +{ -+ 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; ++ u8 i2c_buf[10]; + -+ ret = isl12024_i2c_read_regs(client, ISL12024_REG_SC, regs, ISL12024_RTC_SECTION_LEN); -+ -+ if (ret < 0) -+ return ret; ++ i2c_buf[0] = 0; ++ i2c_buf[1] = reg; ++ memcpy(&i2c_buf[2], &buf[0], len); + -+ for (i = 0; i < ISL12024_RTC_SECTION_LEN; ++i) { -+ if (regs[i] & zero_mask[i]) /* check if bits are cleared */ -+ return -ENODEV; ++ ret = i2c_master_send(client, i2c_buf, len + 2); ++ if (ret != len + 2) { ++ dev_err(&client->dev, "write error (%d)\n", ret); ++ return -EIO; + } -+ + return 0; +} + +static int isl12024_read_time(struct i2c_client *client, -+ struct rtc_time *tm) ++ struct rtc_time *tm, u8 reg_base) +{ + unsigned char sr; + int err; + u8 regs[ISL12024_RTC_SECTION_LEN] = { 0, }; + -+ if (isl12024_get_status(client, &sr) < 0) { ++ if (isl12024_i2c_read_regs(client, ISL12024_REG_SR, &sr, ++ sizeof(sr)) < 0) { + dev_err(&client->dev, "reading SR failed\n"); + return -EIO; + } + -+ err = isl12024_i2c_read_regs(client, ISL12024_REG_SC, regs, ISL12024_RTC_SECTION_LEN); ++ err = isl12024_i2c_read_regs(client, reg_base, regs, ++ ISL12024_RTC_SECTION_LEN); + + if (err < 0) { + dev_err(&client->dev, "reading RTC section failed\n"); @@ -190,15 +192,15 @@ Index: linux-2.6.31/drivers/rtc/rtc-isl12024.c + 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; -+ } ++ /* HR field has a more complex interpretation */ ++ if (regs[2] & ISL12024_REG_HR_MIL) { ++ /* 24h format */ ++ tm->tm_hour = bcd2bin(regs[2] & 0x3f); ++ } else { ++ /* 12h format */ ++ tm->tm_hour = bcd2bin(regs[2] & 0x1f); ++ if (regs[2] & ISL12024_REG_HR_PM) /* PM flag set */ ++ tm->tm_hour += 12; + } + + tm->tm_mday = bcd2bin(regs[3]); @@ -209,36 +211,18 @@ Index: linux-2.6.31/drivers/rtc/rtc-isl12024.c + 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 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_REG_SR_WEL }; ++ ISL12024_REG_SR_WEL }; + + static const unsigned char rwel[3] = { 0, ISL12024_REG_SR, -+ ISL12024_REG_SR_WEL | ISL12024_REG_SR_RWEL }; ++ ISL12024_REG_SR_WEL | ISL12024_REG_SR_RWEL }; + + static const unsigned char diswe[3] = { 0, ISL12024_REG_SR, 0 }; + @@ -272,17 +256,19 @@ Index: linux-2.6.31/drivers/rtc/rtc-isl12024.c + } + + /* If writing alarm registers, set compare bits on registers 0-4 */ -+ if (reg_base < ISL12024_CCR_BASE) ++ if (reg_base == ISL12024_REG_ALARM0) + 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) { ++ xfer = i2c_master_send(client, wel, 3); ++ if (xfer != 3) { + dev_err(&client->dev, "%s: wel - %d\n", __func__, xfer); + return -EIO; + } + -+ if ((xfer = i2c_master_send(client, rwel, 3)) != 3) { ++ xfer = i2c_master_send(client, rwel, 3); ++ if (xfer != 3) { + dev_err(&client->dev, "%s: rwel - %d\n", __func__, xfer); + return -EIO; + } @@ -292,20 +278,12 @@ Index: linux-2.6.31/drivers/rtc/rtc-isl12024.c + 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; -+ } ++ xfer = isl12024_i2c_set_regs(client, reg_base, buf, nbytes); ++ if (xfer < 0) ++ return xfer; + + /* If we wrote to the nonvolatile region, wait 10msec for write cycle*/ -+ if (reg_base < ISL12024_CCR_BASE) { ++ if (reg_base == ISL12024_REG_ALARM0) { + unsigned char al0e[3] = { 0, ISL12024_REG_INT, 0 }; + + msleep(10); @@ -316,7 +294,7 @@ Index: linux-2.6.31/drivers/rtc/rtc-isl12024.c + xfer = i2c_master_send(client, rwel, 3); + if (xfer != 3) { + dev_err(&client->dev, -+ "%s: aloe rwel - %d\n", ++ "%s: al0e rwel - %d\n", + __func__, + xfer); + return -EIO; @@ -339,7 +317,8 @@ Index: linux-2.6.31/drivers/rtc/rtc-isl12024.c + } + + /* disable further writes */ -+ if ((xfer = i2c_master_send(client, diswe, 3)) != 3) { ++ xfer = i2c_master_send(client, diswe, 3); ++ if (xfer != 3) { + dev_err(&client->dev, "%s: diswe - %d\n", __func__, xfer); + return -EIO; + } @@ -354,31 +333,51 @@ Index: linux-2.6.31/drivers/rtc/rtc-isl12024.c + + tm.tm_hour = tm.tm_min = tm.tm_sec = 0; + -+ err = isl12024_set_datetime(client, &tm, 0, ISL12024_CCR_BASE, 0); -+ if ( err < 0 ) -+ dev_err(&client->dev, "unable to restart the oscillator (%d)\n", err); ++ err = isl12024_set_datetime(client, &tm, 0, ISL12024_REG_RTC, 0); ++ if (err < 0) ++ dev_err(&client->dev, ++ "unable to restart the oscillator (%d)\n", err); + + return err; +} + +static int isl12024_rtc_read_time(struct device *dev, struct rtc_time *tm) +{ -+ return isl12024_read_time(to_i2c_client(dev), tm); -+ ++ return isl12024_read_time(to_i2c_client(dev), tm, ++ ISL12024_REG_RTC); +} + +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); ++ return isl12024_set_datetime(to_i2c_client(dev), tm, 1, ++ ISL12024_REG_RTC, 0); ++} ++ ++static int isl12024_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) ++{ ++ unsigned char intr; ++ int err; ++ struct i2c_client *client = to_i2c_client(dev); ++ ++ err = isl12024_i2c_read_regs(client, ISL12024_REG_INT, &intr, ++ sizeof(intr)); ++ if (err < 0) ++ return err; ++ alrm->enabled = (intr & ISL12024_INT_AL0E) ? 1 : 0; ++ ++ return isl12024_read_time(client, &alrm->time, ISL12024_REG_ALARM0); ++} ++ ++static int isl12024_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) ++{ ++ return isl12024_set_datetime(to_i2c_client(dev), &alrm->time, 1, ++ ISL12024_REG_ALARM0, alrm->enabled); +} + +static int +isl12024_rtc_proc(struct device *dev, struct seq_file *seq) +{ -+ + /* Nothing to do */ -+ + return 0; +} + @@ -386,19 +385,23 @@ Index: linux-2.6.31/drivers/rtc/rtc-isl12024.c + .proc = isl12024_rtc_proc, + .read_time = isl12024_rtc_read_time, + .set_time = isl12024_rtc_set_time, ++ .read_alarm = isl12024_rtc_read_alarm, ++ .set_alarm = isl12024_rtc_set_alarm, +}; + -+static ssize_t isl12024_show_id(struct device *dev, struct device_attribute *attr, -+ char *buf) ++static ssize_t isl12024_show_id(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + int err; -+ int len = 0; ++ ssize_t len = 0; + int i; -+ u8 id_buffer[ISL12024_RTC_SECTION_LEN]; ++ u8 id_buffer[ISL12024_ID_SECTION_LEN]; + + /* Read unique id from eeprom */ -+ err = isl12024_i2c_read_regs(client, ISL12024_REG_ID, id_buffer, sizeof(id_buffer)); ++ err = isl12024_i2c_read_regs(client, ISL12024_REG_ID, id_buffer, ++ sizeof(id_buffer)); + if (err < 0) { + dev_err(&client->dev, "reading RTC section failed\n"); + return err; @@ -423,26 +426,22 @@ Index: linux-2.6.31/drivers/rtc/rtc-isl12024.c + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) + return -ENODEV; + -+ if (isl12024_i2c_validate_client(client) < 0) -+ return -ENODEV; -+ -+ dev_info(&client->dev, -+ "chip found, driver version " DRV_VERSION "\n"); ++ dev_info(&client->dev, ++ "chip found, driver version " DRV_VERSION "\n"); + + rtc = rtc_device_register(isl12024_driver.driver.name, + &client->dev, &isl12024_rtc_ops, + THIS_MODULE); -+ + if (IS_ERR(rtc)) + return PTR_ERR(rtc); + + i2c_set_clientdata(client, rtc); + -+ rc = isl12024_get_status(client, &sr); -+ if (rc < 0) { -+ dev_err(&client->dev, "reading status failed\n"); -+ goto exit_unregister; -+ } ++ rc = isl12024_i2c_read_regs(client, ISL12024_REG_SR, &sr, sizeof(sr)); ++ if (rc < 0) { ++ dev_err(&client->dev, "reading status failed\n"); ++ goto exit_unregister; ++ } + + /* Check for power failures and enable the osc */ + if (sr & ISL12024_REG_SR_RTCF) { @@ -477,18 +476,18 @@ Index: linux-2.6.31/drivers/rtc/rtc-isl12024.c +} + +static const struct i2c_device_id isl12024_id[] = { -+ { "isl12024", 0 }, -+ { } ++ { "isl12024", 0 }, ++ { } +}; +MODULE_DEVICE_TABLE(i2c, isl12024_id); + +static struct i2c_driver isl12024_driver = { -+ .driver = { -+ .name = "rtc-isl12024", -+ }, -+ .probe = isl12024_probe, -+ .remove = isl12024_remove, -+ .id_table = isl12024_id, ++ .driver = { ++ .name = "rtc-isl12024", ++ }, ++ .probe = isl12024_probe, ++ .remove = isl12024_remove, ++ .id_table = isl12024_id, +}; + +/* module init/exit */ |