From patchwork Tue Jan 27 01:04:23 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: x86: i2c rtc instead of cmos rtc Date: Mon, 26 Jan 2009 15:04:23 -0000 From: Ed Swierk X-Patchwork-Id: 20364 Message-Id: <1233018263.14510.112.camel@localhost.localdomain> To: a.zummo@towertech.it, rtc-linux@googlegroups.com, tglx@linutronix.de, mingo@redhat.com, linux-kernel@vger.kernel.org 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 --- --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to "rtc-linux". Membership options at http://groups.google.com/group/rtc-linux . Please read http://groups.google.com/group/rtc-linux/web/checklist before submitting a driver. -~----------~----~----~----~------~----~------~--~--- 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 + +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);