diff options
Diffstat (limited to 'drivers/i2c/chips/ds1374.c')
-rw-r--r-- | drivers/i2c/chips/ds1374.c | 267 |
1 files changed, 0 insertions, 267 deletions
diff --git a/drivers/i2c/chips/ds1374.c b/drivers/i2c/chips/ds1374.c deleted file mode 100644 index 8a2ff0c114d..00000000000 --- a/drivers/i2c/chips/ds1374.c +++ /dev/null @@ -1,267 +0,0 @@ -/* - * drivers/i2c/chips/ds1374.c - * - * I2C client/driver for the Maxim/Dallas DS1374 Real-Time Clock - * - * Author: Randy Vinson <rvinson@mvista.com> - * - * Based on the m41t00.c by Mark Greer <mgreer@mvista.com> - * - * 2005 (c) MontaVista Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2. This program - * is licensed "as is" without any warranty of any kind, whether express - * or implied. - */ -/* - * This i2c client/driver wedges between the drivers/char/genrtc.c RTC - * interface and the SMBus interface of the i2c subsystem. - * It would be more efficient to use i2c msgs/i2c_transfer directly but, as - * recommened in .../Documentation/i2c/writing-clients section - * "Sending and receiving", using SMBus level communication is preferred. - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/interrupt.h> -#include <linux/i2c.h> -#include <linux/rtc.h> -#include <linux/bcd.h> -#include <linux/mutex.h> -#include <linux/workqueue.h> - -#define DS1374_REG_TOD0 0x00 -#define DS1374_REG_TOD1 0x01 -#define DS1374_REG_TOD2 0x02 -#define DS1374_REG_TOD3 0x03 -#define DS1374_REG_WDALM0 0x04 -#define DS1374_REG_WDALM1 0x05 -#define DS1374_REG_WDALM2 0x06 -#define DS1374_REG_CR 0x07 -#define DS1374_REG_SR 0x08 -#define DS1374_REG_SR_OSF 0x80 -#define DS1374_REG_TCR 0x09 - -#define DS1374_DRV_NAME "ds1374" - -static DEFINE_MUTEX(ds1374_mutex); - -static struct i2c_driver ds1374_driver; -static struct i2c_client *save_client; - -static unsigned short ignore[] = { I2C_CLIENT_END }; -static unsigned short normal_addr[] = { 0x68, I2C_CLIENT_END }; - -static struct i2c_client_address_data addr_data = { - .normal_i2c = normal_addr, - .probe = ignore, - .ignore = ignore, -}; - -static ulong ds1374_read_rtc(void) -{ - ulong time = 0; - int reg = DS1374_REG_WDALM0; - - while (reg--) { - s32 tmp; - if ((tmp = i2c_smbus_read_byte_data(save_client, reg)) < 0) { - dev_warn(&save_client->dev, - "can't read from rtc chip\n"); - return 0; - } - time = (time << 8) | (tmp & 0xff); - } - return time; -} - -static void ds1374_write_rtc(ulong time) -{ - int reg; - - for (reg = DS1374_REG_TOD0; reg < DS1374_REG_WDALM0; reg++) { - if (i2c_smbus_write_byte_data(save_client, reg, time & 0xff) - < 0) { - dev_warn(&save_client->dev, - "can't write to rtc chip\n"); - break; - } - time = time >> 8; - } -} - -static void ds1374_check_rtc_status(void) -{ - s32 tmp; - - tmp = i2c_smbus_read_byte_data(save_client, DS1374_REG_SR); - if (tmp < 0) { - dev_warn(&save_client->dev, - "can't read status from rtc chip\n"); - return; - } - if (tmp & DS1374_REG_SR_OSF) { - dev_warn(&save_client->dev, - "oscillator discontinuity flagged, time unreliable\n"); - tmp &= ~DS1374_REG_SR_OSF; - tmp = i2c_smbus_write_byte_data(save_client, DS1374_REG_SR, - tmp & 0xff); - if (tmp < 0) - dev_warn(&save_client->dev, - "can't clear discontinuity notification\n"); - } -} - -ulong ds1374_get_rtc_time(void) -{ - ulong t1, t2; - int limit = 10; /* arbitrary retry limit */ - - mutex_lock(&ds1374_mutex); - - /* - * Since the reads are being performed one byte at a time using - * the SMBus vs a 4-byte i2c transfer, there is a chance that a - * carry will occur during the read. To detect this, 2 reads are - * performed and compared. - */ - do { - t1 = ds1374_read_rtc(); - t2 = ds1374_read_rtc(); - } while (t1 != t2 && limit--); - - mutex_unlock(&ds1374_mutex); - - if (t1 != t2) { - dev_warn(&save_client->dev, - "can't get consistent time from rtc chip\n"); - t1 = 0; - } - - return t1; -} - -static ulong new_time; - -static void ds1374_set_work(struct work_struct *work) -{ - ulong t1, t2; - int limit = 10; /* arbitrary retry limit */ - - t1 = new_time; - - mutex_lock(&ds1374_mutex); - - /* - * Since the writes are being performed one byte at a time using - * the SMBus vs a 4-byte i2c transfer, there is a chance that a - * carry will occur during the write. To detect this, the write - * value is read back and compared. - */ - do { - ds1374_write_rtc(t1); - t2 = ds1374_read_rtc(); - } while (t1 != t2 && limit--); - - mutex_unlock(&ds1374_mutex); - - if (t1 != t2) - dev_warn(&save_client->dev, - "can't confirm time set from rtc chip\n"); -} - -static struct workqueue_struct *ds1374_workqueue; - -static DECLARE_WORK(ds1374_work, ds1374_set_work); - -int ds1374_set_rtc_time(ulong nowtime) -{ - new_time = nowtime; - - if (in_interrupt()) - queue_work(ds1374_workqueue, &ds1374_work); - else - ds1374_set_work(NULL); - - return 0; -} - -/* - ***************************************************************************** - * - * Driver Interface - * - ***************************************************************************** - */ -static int ds1374_probe(struct i2c_adapter *adap, int addr, int kind) -{ - struct i2c_client *client; - int rc; - - client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); - if (!client) - return -ENOMEM; - - strncpy(client->name, DS1374_DRV_NAME, I2C_NAME_SIZE); - client->addr = addr; - client->adapter = adap; - client->driver = &ds1374_driver; - - ds1374_workqueue = create_singlethread_workqueue("ds1374"); - if (!ds1374_workqueue) { - kfree(client); - return -ENOMEM; /* most expected reason */ - } - - if ((rc = i2c_attach_client(client)) != 0) { - kfree(client); - return rc; - } - - save_client = client; - - ds1374_check_rtc_status(); - - return 0; -} - -static int ds1374_attach(struct i2c_adapter *adap) -{ - return i2c_probe(adap, &addr_data, ds1374_probe); -} - -static int ds1374_detach(struct i2c_client *client) -{ - int rc; - - if ((rc = i2c_detach_client(client)) == 0) { - kfree(i2c_get_clientdata(client)); - destroy_workqueue(ds1374_workqueue); - } - return rc; -} - -static struct i2c_driver ds1374_driver = { - .driver = { - .name = DS1374_DRV_NAME, - }, - .id = I2C_DRIVERID_DS1374, - .attach_adapter = ds1374_attach, - .detach_client = ds1374_detach, -}; - -static int __init ds1374_init(void) -{ - return i2c_add_driver(&ds1374_driver); -} - -static void __exit ds1374_exit(void) -{ - i2c_del_driver(&ds1374_driver); -} - -module_init(ds1374_init); -module_exit(ds1374_exit); - -MODULE_AUTHOR("Randy Vinson <rvinson@mvista.com>"); -MODULE_DESCRIPTION("Maxim/Dallas DS1374 RTC I2C Client Driver"); -MODULE_LICENSE("GPL"); |