[PATCH] x86: i2c rtc instead of cmos rtc

From: Ed Swierk
Date: Mon Jan 26 2009 - 20:04:54 EST


Allows the user to ignore the cmos real-time clock normally found on x86
boards, and to use an i2c rtc in its place. This is intended to be used
with with CONFIG_RTC_HCTOSYS=y to set the system clock from the rtc
automatically during boot, and with CONFIG_RTC_SYSTOHC=y to have ntpd
update the rtc (see separate patch).

Passing rtc.cmos=0 on the kernel command line ignores the cmos rtc, and
passing a parameter like rtc.i2c=ds1339,1,0x68 enables the i2c rtc named
ds1339 on i2c bus 1, device address 0x68. The appropriate driver must
be compiled into the kernel to be available when the initcall is
triggered (device_initcall_sync to ensure the i2c device has already
been added).

Signed-off-by: Ed Swierk <eswierk@xxxxxxxxxxxxxxxxxx>

---
Index: linux-2.6.28.2/arch/x86/kernel/rtc.c
===================================================================
--- linux-2.6.28.2.orig/arch/x86/kernel/rtc.c
+++ linux-2.6.28.2/arch/x86/kernel/rtc.c
@@ -220,6 +220,9 @@ static struct platform_device rtc_device
.num_resources = ARRAY_SIZE(rtc_resources),
};

+static int cmos = 1;
+module_param(cmos, bool, 0);
+
static __init int add_rtc_cmos(void)
{
#ifdef CONFIG_PNP
@@ -228,7 +231,11 @@ static __init int add_rtc_cmos(void)
struct pnp_dev *dev;
struct pnp_id *id;
int i;
+#endif

+ if (!cmos)
+ return 0;
+#ifdef CONFIG_PNP
pnp_for_each_dev(dev) {
for (id = dev->id; id; id = id->next) {
for (i = 0; i < ARRAY_SIZE(ids); i++) {
@@ -245,3 +252,41 @@ static __init int add_rtc_cmos(void)
return 0;
}
device_initcall(add_rtc_cmos);
+
+#include <linux/i2c.h>
+
+static char *i2c[3] = { NULL, NULL, NULL };
+module_param_array(i2c, charp, NULL, 0);
+
+static int setup_rtc_i2c(void)
+{
+ struct i2c_adapter *adapter;
+ struct i2c_board_info info = {};
+ int adapter_id;
+ unsigned short addrs[] = { 0, I2C_CLIENT_END };
+ struct i2c_client *c;
+ unsigned long num;
+
+ if (!i2c[0] || !i2c[1] || !i2c[2])
+ return 0;
+
+ strlcpy(info.type, i2c[0], I2C_NAME_SIZE);
+ if (strict_strtoul(i2c[1], 0, &num))
+ return 0;
+ adapter_id = num;
+ if (strict_strtoul(i2c[2], 0, &num))
+ return 0;
+ addrs[0] = num;
+
+ adapter = i2c_get_adapter(adapter_id);
+ if (!adapter)
+ return 0;
+
+ c = i2c_new_probed_device(adapter, &info, addrs);
+ if (c && c->driver == NULL) {
+ i2c_unregister_device(c);
+ }
+ i2c_put_adapter(adapter);
+ return 0;
+}
+device_initcall_sync(setup_rtc_i2c);


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/