Message ID | 4c4a5102-b045-4c9d-9852-77e2b118380b@a32g2000yqm.googlegroups.com |
---|---|
State | Rejected |
Headers | show |
On Thu, 28 Jan 2010 03:54:02 -0800 (PST) mcherkashin <mikhailcher@gmail.com> wrote: > > Fixes an ds1307 rtc driver by adding a detect method to it. > Also epson 3231 chip detection is supported by reading a temperature > register. > > This patch is for a 2.6.31 kernel. Hi, i2c chips aren't detected anymore, they must be declared in the p[latform code. > Signed-off-by: Mikhail Cherkashin <cherkashin@gmail.com> > Index: rtc-ds1307.c > =================================================================== > --- rtc-ds1307.c (revision 459) > +++ rtc-ds1307.c (working copy) > @@ -1,14 +1,14 @@ > /* > - * rtc-ds1307.c - RTC driver for some mostly-compatible I2C chips. > - * > - * Copyright (C) 2005 James Chapman (ds1337 core) > - * Copyright (C) 2006 David Brownell > - * Copyright (C) 2009 Matthias Fuchs (rx8025 support) > - * > - * 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. > - */ > +* rtc-ds1307.c - RTC driver for some mostly-compatible I2C chips. > +* > +* Copyright (C) 2005 James Chapman (ds1337 core) > +* Copyright (C) 2006 David Brownell > +* Copyright (C) 2009 Matthias Fuchs (rx8025 support) > +* > +* 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> > #include <linux/init.h> > @@ -18,6 +18,8 @@ > #include <linux/rtc.h> > #include <linux/bcd.h> > > +static const unsigned short normal_i2c[] = { 0x68, I2C_CLIENT_END }; > +I2C_CLIENT_INSMOD; > > > /* We can't determine type by probing, but if we expect pre-Linux > code > @@ -95,6 +97,9 @@ > # define RX8025_BIT_VDET 0x40 > # define RX8025_BIT_XST 0x20 > > +/* DS3231 temperature registers */ > +#define DS3231_REG_TEMPHI 0x11 > +#define DS3231_REG_TEMPLO 0x12 > > struct ds1307 { > u8 offset; /* register's offset */ > @@ -620,6 +625,129 @@ > > static struct i2c_driver ds1307_driver; > > +/* Return 0 if detection is successful, -ENODEV otherwise */ > +static int ds1307_detect(struct i2c_client *new_client, int kind, > + struct i2c_board_info *info) > +{ > + int err = -ENODEV; > + u8 type; > + struct i2c_adapter *adapter = new_client->adapter; > + s32 (*read_block_data)(struct i2c_client *client, u8 command, > + u8 length, u8 *values); > + s32 (*write_block_data)(struct i2c_client *client, u8 command, > + u8 length, const u8 *values); > + int tmp; > + u8 buf[11]; > + static const int bbsqi_bitpos[] = { > + [ds_1337] = 0, > + [ds_1339] = DS1339_BIT_BBSQI, > + [ds_3231] = DS3231_BIT_BBSQW, > + }; > + int want_irq = false; > + const char *name = ""; > + > + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA) > + && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) > + return -EIO; > + > + if (i2c_check_functionality(adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { > + read_block_data = i2c_smbus_read_i2c_block_data; > + write_block_data = i2c_smbus_write_i2c_block_data; > + } else { > + read_block_data = ds1307_read_block_data; > + write_block_data = ds1307_write_block_data; > + } > + > + if (kind >= 0) { > + type = ds_1337; > + tmp = read_block_data(new_client, > + DS1337_REG_CONTROL, 2, buf); > + if (tmp != 2) { > + pr_debug("read error %d\n", tmp); > + err = -EIO; > + goto exit; > + } > + > + /* oscillator off? turn it on, so clock can tick. */ > + if ((buf[0] & DS1337_BIT_nEOSC) > + || (buf[1] & DS1337_BIT_OSF)) { > + printk(KERN_ERR "no ds1337 oscillator code\n"); > + goto exit; > + } > + } else { > + tmp = read_block_data(new_client, > + DS3231_REG_TEMPHI, 2, buf); > + if (tmp != 2) { > + pr_debug("read error %d\n", tmp); > + err = -EIO; > + goto exit; > + } > + if (tmp == 2 && buf[0] && > + (buf[1] & 0x3f) == 0) > + type = ds_3231; > + else > + type = ds_1307; > + > + } > + > +read_rtc: > + /* read RTC registers */ > + tmp = read_block_data(new_client, 0, 8, buf); > + if (tmp != 8) { > + pr_debug("read error %d\n", tmp); > + err = -EIO; > + goto exit; > + } > + > + /* minimal sanity checking; some chips (like DS1340) don't > + * specify the extra bits as must-be-zero, but there are > + * still a few values that are clearly out-of-range. > + */ > + tmp = buf[DS1307_REG_SECS]; > + /* clock halted? turn it on, so clock can tick. */ > + if (tmp & DS1307_BIT_CH) { > + if (type && type != ds_1307) { > + pr_debug("not a ds1307?\n"); > + goto exit; > + } > + type = ds_1307; > + > + /* this partial initialization should work for ds1307, > + * ds1338, ds1340, st m41t00, and more. > + */ > + dev_warn(&new_client->dev, "SET TIME!\n"); > + i2c_smbus_write_byte_data(new_client, DS1307_REG_SECS, 0); > + goto read_rtc; > + } > + > + /* Fill the i2c board info */ > + if (type == ds_1307) > + name = "ds1307"; > + else if (type == ds_1337) > + name = "ds1337"; > + else if (type == ds_1338) > + name = "ds1338"; > + else if (type == ds_1339) > + name = "ds1339"; > + else if (type == ds_1340) > + name = "ds1340"; > + else if (type == ds_1388) > + name = "ds1388"; > + else if (type == ds_3231) > + name = "ds3231"; > + else if (type == m41t00) > + name = "im411t00"; > + else if (type == rx_8025) > + name = "rx8025"; > + strlcpy(info->type, name, I2C_NAME_SIZE); > + > + return 0; > + > +exit: > + return err; > + > +} > + > static int __devinit ds1307_probe(struct i2c_client *client, > const struct i2c_device_id *id) > { > @@ -636,6 +764,7 @@ > [ds_3231] = DS3231_BIT_BBSQW, > }; > > + > if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA) > && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) > return -EIO; > @@ -925,10 +1054,12 @@ > .name = "rtc-ds1307", > .owner = THIS_MODULE, > }, > + .detect = ds1307_detect, > .probe = ds1307_probe, > .remove = __devexit_p(ds1307_remove), > .id_table = ds1307_id, > + .address_data = &addr_data, > }; > > static int __init ds1307_init(void) > { > > -- > 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: rtc-ds1307.c =================================================================== --- rtc-ds1307.c (revision 459) +++ rtc-ds1307.c (working copy) @@ -1,14 +1,14 @@ /* - * rtc-ds1307.c - RTC driver for some mostly-compatible I2C chips. - * - * Copyright (C) 2005 James Chapman (ds1337 core) - * Copyright (C) 2006 David Brownell - * Copyright (C) 2009 Matthias Fuchs (rx8025 support) - * - * 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. - */ +* rtc-ds1307.c - RTC driver for some mostly-compatible I2C chips. +* +* Copyright (C) 2005 James Chapman (ds1337 core) +* Copyright (C) 2006 David Brownell +* Copyright (C) 2009 Matthias Fuchs (rx8025 support) +* +* 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. +*/
Fixes an ds1307 rtc driver by adding a detect method to it. Also epson 3231 chip detection is supported by reading a temperature register. This patch is for a 2.6.31 kernel. Signed-off-by: Mikhail Cherkashin <cherkashin@gmail.com> #include <linux/module.h> #include <linux/init.h> @@ -18,6 +18,8 @@ #include <linux/rtc.h> #include <linux/bcd.h> +static const unsigned short normal_i2c[] = { 0x68, I2C_CLIENT_END }; +I2C_CLIENT_INSMOD; /* We can't determine type by probing, but if we expect pre-Linux code @@ -95,6 +97,9 @@ # define RX8025_BIT_VDET 0x40 # define RX8025_BIT_XST 0x20 +/* DS3231 temperature registers */ +#define DS3231_REG_TEMPHI 0x11 +#define DS3231_REG_TEMPLO 0x12 struct ds1307 { u8 offset; /* register's offset */ @@ -620,6 +625,129 @@ static struct i2c_driver ds1307_driver; +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int ds1307_detect(struct i2c_client *new_client, int kind, + struct i2c_board_info *info) +{ + int err = -ENODEV; + u8 type; + struct i2c_adapter *adapter = new_client->adapter; + s32 (*read_block_data)(struct i2c_client *client, u8 command, + u8 length, u8 *values); + s32 (*write_block_data)(struct i2c_client *client, u8 command, + u8 length, const u8 *values); + int tmp; + u8 buf[11]; + static const int bbsqi_bitpos[] = { + [ds_1337] = 0, + [ds_1339] = DS1339_BIT_BBSQI, + [ds_3231] = DS3231_BIT_BBSQW, + }; + int want_irq = false; + const char *name = ""; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA) + && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) + return -EIO; + + if (i2c_check_functionality(adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) { + read_block_data = i2c_smbus_read_i2c_block_data; + write_block_data = i2c_smbus_write_i2c_block_data; + } else { + read_block_data = ds1307_read_block_data; + write_block_data = ds1307_write_block_data; + } + + if (kind >= 0) { + type = ds_1337; + tmp = read_block_data(new_client, + DS1337_REG_CONTROL, 2, buf); + if (tmp != 2) { + pr_debug("read error %d\n", tmp); + err = -EIO; + goto exit; + } + + /* oscillator off? turn it on, so clock can tick. */ + if ((buf[0] & DS1337_BIT_nEOSC) + || (buf[1] & DS1337_BIT_OSF)) { + printk(KERN_ERR "no ds1337 oscillator code\n"); + goto exit; + } + } else { + tmp = read_block_data(new_client, + DS3231_REG_TEMPHI, 2, buf); + if (tmp != 2) { + pr_debug("read error %d\n", tmp); + err = -EIO; + goto exit; + } + if (tmp == 2 && buf[0] && + (buf[1] & 0x3f) == 0) + type = ds_3231; + else + type = ds_1307; + + } + +read_rtc: + /* read RTC registers */ + tmp = read_block_data(new_client, 0, 8, buf); + if (tmp != 8) { + pr_debug("read error %d\n", tmp); + err = -EIO; + goto exit; + } + + /* minimal sanity checking; some chips (like DS1340) don't + * specify the extra bits as must-be-zero, but there are + * still a few values that are clearly out-of-range. + */ + tmp = buf[DS1307_REG_SECS]; + /* clock halted? turn it on, so clock can tick. */ + if (tmp & DS1307_BIT_CH) { + if (type && type != ds_1307) { + pr_debug("not a ds1307?\n"); + goto exit; + } + type = ds_1307; + + /* this partial initialization should work for ds1307, + * ds1338, ds1340, st m41t00, and more. + */ + dev_warn(&new_client->dev, "SET TIME!\n"); + i2c_smbus_write_byte_data(new_client, DS1307_REG_SECS, 0); + goto read_rtc; + } + + /* Fill the i2c board info */ + if (type == ds_1307) + name = "ds1307"; + else if (type == ds_1337) + name = "ds1337"; + else if (type == ds_1338) + name = "ds1338"; + else if (type == ds_1339) + name = "ds1339"; + else if (type == ds_1340) + name = "ds1340"; + else if (type == ds_1388) + name = "ds1388"; + else if (type == ds_3231) + name = "ds3231"; + else if (type == m41t00) + name = "im411t00"; + else if (type == rx_8025) + name = "rx8025"; + strlcpy(info->type, name, I2C_NAME_SIZE); + + return 0; + +exit: + return err; + +} + static int __devinit ds1307_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -636,6 +764,7 @@ [ds_3231] = DS3231_BIT_BBSQW, }; + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA) && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_I2C_BLOCK)) return -EIO; @@ -925,10 +1054,12 @@ .name = "rtc-ds1307", .owner = THIS_MODULE, }, + .detect = ds1307_detect, .probe = ds1307_probe, .remove = __devexit_p(ds1307_remove), .id_table = ds1307_id, + .address_data = &addr_data, }; static int __init ds1307_init(void) {