From patchwork Thu Jan 28 11:54:02 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: mcherkashin X-Patchwork-Id: 43857 Return-Path: <32nphSwsJCQIokmjcknejgtiockn.eqotve-nkpwziqqingitqwru.eqo@groups.bounces.google.com> X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from mail-yx0-f148.google.com (mail-yx0-f148.google.com [209.85.210.148]) by ozlabs.org (Postfix) with ESMTP id 35A61B7D02 for ; Thu, 28 Jan 2010 22:54:04 +1100 (EST) Received: by yxe12 with SMTP id 12sf1951433yxe.1 for ; Thu, 28 Jan 2010 03:54:03 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlegroups.com; s=beta; h=domainkey-signature:received:x-beenthere:received:received:received :received:received-spf:received:mime-version:received:date:x-ip :user-agent:x-http-via:x-http-useragent:message-id:subject:from:to :x-original-authentication-results:x-original-sender:reply-to :precedence:mailing-list:list-id:list-post:list-help:list-archive :x-thread-url:x-message-url:sender:list-subscribe:list-unsubscribe :content-type; bh=ZMtI4lIKGTTk5ZITPLQaPyPO15lPDwDjsFJAl1UiL1w=; b=dn8/1dRbG5mVR2759C5q2re4up4AlVhBna73jXmAn8ZsuqsG2Fn7ip01/VJ2BDIE+l edlxtoRjUDPtAPlBDzrPxY8C4G6fT+tNi7GS2JcuuRvPYPql4fISknzKSmB9egSYM3fP vSTSvMLCUluIGYhJx/Kw7eSrOSvSjZSEvYznc= DomainKey-Signature: a=rsa-sha1; c=nofws; d=googlegroups.com; s=beta; h=x-beenthere:received-spf:mime-version:date:x-ip:user-agent :x-http-via:x-http-useragent:message-id:subject:from:to :x-original-authentication-results:x-original-sender:reply-to :precedence:mailing-list:list-id:list-post:list-help:list-archive :x-thread-url:x-message-url:sender:list-subscribe:list-unsubscribe :content-type; b=JQG9bN3lKRpjMY07ba7iOdQ/WWUxfUyeGc4SEoxQKUsMs9YuLBzkbCqIyTBgbhob5P wC6tHnMzMdYHVcs+j882o2hGH7adBxsvN9RVh7NYTdxktQOrbpmrSp/bJgB7CESKOR+d qyuglvTxG6aoR8caVsMNw8+iFBEnlSKSh8rYk= Received: by 10.101.176.29 with SMTP id d29mr570587anp.0.1264679642790; Thu, 28 Jan 2010 03:54:02 -0800 (PST) X-BeenThere: rtc-linux@googlegroups.com Received: by 10.91.26.32 with SMTP id d32ls747526agj.1.p; Thu, 28 Jan 2010 03:54:02 -0800 (PST) Received: by 10.91.148.11 with SMTP id a11mr1282785ago.9.1264679642294; Thu, 28 Jan 2010 03:54:02 -0800 (PST) Received: by 10.91.148.11 with SMTP id a11mr1282784ago.9.1264679642234; Thu, 28 Jan 2010 03:54:02 -0800 (PST) Received: from mail-yw0-f138.google.com (mail-yw0-f138.google.com [209.85.211.138]) by gmr-mx.google.com with ESMTP id 17si105227gxk.0.2010.01.28.03.54.02; Thu, 28 Jan 2010 03:54:02 -0800 (PST) Received-SPF: pass (google.com: domain of mikhailcher@gmail.com designates 209.85.211.138 as permitted sender) client-ip=209.85.211.138; Received: by mail-yw0-f138.google.com with SMTP id 2so1478665ywh.8 for ; Thu, 28 Jan 2010 03:54:02 -0800 (PST) MIME-Version: 1.0 Received: by 10.101.179.34 with SMTP id g34mr744118anp.22.1264679642046; Thu, 28 Jan 2010 03:54:02 -0800 (PST) Date: Thu, 28 Jan 2010 03:54:02 -0800 (PST) X-IP: 77.108.106.130 User-Agent: G2/1.0 X-HTTP-Via: 1.1 GWUP X-HTTP-UserAgent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.5pre) Gecko/2008120802 Firefox/3.0.4,gzip(gfe),gzip(gfe) Message-ID: <4c4a5102-b045-4c9d-9852-77e2b118380b@a32g2000yqm.googlegroups.com> Subject: [rtc-linux] rtc: detect() method for ds1307 rtc driver. From: mcherkashin To: rtc-linux X-Original-Authentication-Results: gmr-mx.google.com; spf=pass (google.com: domain of mikhailcher@gmail.com designates 209.85.211.138 as permitted sender) smtp.mail=mikhailcher@gmail.com X-Original-Sender: mikhailcher@gmail.com Reply-To: rtc-linux@googlegroups.com Precedence: list Mailing-list: list rtc-linux@googlegroups.com; contact rtc-linux+owners@googlegroups.com List-ID: List-Post: , List-Help: , List-Archive: X-Thread-Url: http://groups.google.com/group/rtc-linux/t/dfcd0915677df964 X-Message-Url: http://groups.google.com/group/rtc-linux/msg/d2a572817d0d998b Sender: rtc-linux@googlegroups.com List-Subscribe: , List-Unsubscribe: , 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 #include #include @@ -18,6 +18,8 @@ #include #include +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) { 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. +*/