Commit eee87d31 authored by Adrian Bunk's avatar Adrian Bunk Committed by Jean Delvare

i2c: the scheduled I2C RTC driver removal

This patch contains the scheduled removal of legacy I2C RTC drivers with 
replacement drivers.
Signed-off-by: default avatarAdrian Bunk <bunk@kernel.org>
Signed-off-by: default avatarJean Delvare <khali@linux-fr.org>
parent 569be443
...@@ -266,13 +266,6 @@ Who: Tejun Heo <htejun@gmail.com> ...@@ -266,13 +266,6 @@ Who: Tejun Heo <htejun@gmail.com>
--------------------------- ---------------------------
What: Legacy RTC drivers (under drivers/i2c/chips)
When: November 2007
Why: Obsolete. We have a RTC subsystem with better drivers.
Who: Jean Delvare <khali@linux-fr.org>
---------------------------
What: iptables SAME target What: iptables SAME target
When: 1.1. 2008 When: 1.1. 2008
Files: net/ipv4/netfilter/ipt_SAME.c, include/linux/netfilter_ipv4/ipt_SAME.h Files: net/ipv4/netfilter/ipt_SAME.c, include/linux/netfilter_ipv4/ipt_SAME.h
......
...@@ -224,26 +224,6 @@ mpc834x_sys_init_IRQ(void) ...@@ -224,26 +224,6 @@ mpc834x_sys_init_IRQ(void)
ipic_set_default_priority(); ipic_set_default_priority();
} }
#if defined(CONFIG_I2C_MPC) && defined(CONFIG_SENSORS_DS1374)
extern ulong ds1374_get_rtc_time(void);
extern int ds1374_set_rtc_time(ulong);
static int __init
mpc834x_rtc_hookup(void)
{
struct timespec tv;
ppc_md.get_rtc_time = ds1374_get_rtc_time;
ppc_md.set_rtc_time = ds1374_set_rtc_time;
tv.tv_nsec = 0;
tv.tv_sec = (ppc_md.get_rtc_time)();
do_settimeofday(&tv);
return 0;
}
late_initcall(mpc834x_rtc_hookup);
#endif
static __inline__ void static __inline__ void
mpc834x_sys_set_bat(void) mpc834x_sys_set_bat(void)
{ {
......
...@@ -258,27 +258,6 @@ int tqm85xx_show_cpuinfo(struct seq_file *m) ...@@ -258,27 +258,6 @@ int tqm85xx_show_cpuinfo(struct seq_file *m)
return 0; return 0;
} }
#if defined(CONFIG_I2C) && defined(CONFIG_SENSORS_DS1337)
extern ulong ds1337_get_rtc_time(void);
extern int ds1337_set_rtc_time(unsigned long nowtime);
static int __init
tqm85xx_rtc_hookup(void)
{
struct timespec tv;
ppc_md.set_rtc_time = ds1337_set_rtc_time;
ppc_md.get_rtc_time = ds1337_get_rtc_time;
tv.tv_nsec = 0;
tv.tv_sec = (ppc_md.get_rtc_time)();
do_settimeofday(&tv);
return 0;
}
late_initcall(tqm85xx_rtc_hookup);
#endif
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
/* /*
* interrupt routing * interrupt routing
......
...@@ -838,27 +838,6 @@ katana_find_end_of_memory(void) ...@@ -838,27 +838,6 @@ katana_find_end_of_memory(void)
return bdp->bi_memsize; return bdp->bi_memsize;
} }
#if defined(CONFIG_I2C_MV64XXX) && defined(CONFIG_SENSORS_M41T00)
extern ulong m41t00_get_rtc_time(void);
extern int m41t00_set_rtc_time(ulong);
static int __init
katana_rtc_hookup(void)
{
struct timespec tv;
ppc_md.get_rtc_time = m41t00_get_rtc_time;
ppc_md.set_rtc_time = m41t00_set_rtc_time;
tv.tv_nsec = 0;
tv.tv_sec = (ppc_md.get_rtc_time)();
do_settimeofday(&tv);
return 0;
}
late_initcall(katana_rtc_hookup);
#endif
#if defined(CONFIG_SERIAL_TEXT_DEBUG) && defined(CONFIG_SERIAL_MPSC_CONSOLE) #if defined(CONFIG_SERIAL_TEXT_DEBUG) && defined(CONFIG_SERIAL_MPSC_CONSOLE)
static void __init static void __init
katana_map_io(void) katana_map_io(void)
......
...@@ -4,32 +4,6 @@ ...@@ -4,32 +4,6 @@
menu "Miscellaneous I2C Chip support" menu "Miscellaneous I2C Chip support"
config SENSORS_DS1337
tristate "Dallas DS1337 and DS1339 Real Time Clock (DEPRECATED)"
depends on EXPERIMENTAL
help
If you say yes here you get support for Dallas Semiconductor
DS1337 and DS1339 real-time clock chips.
This driver can also be built as a module. If so, the module
will be called ds1337.
This driver is deprecated and will be dropped soon. Use
rtc-ds1307 instead.
config SENSORS_DS1374
tristate "Dallas DS1374 Real Time Clock (DEPRECATED)"
depends on EXPERIMENTAL
help
If you say yes here you get support for Dallas Semiconductor
DS1374 real-time clock chips.
This driver can also be built as a module. If so, the module
will be called ds1374.
This driver is deprecated and will be dropped soon. Use
rtc-ds1374 instead.
config DS1682 config DS1682
tristate "Dallas DS1682 Total Elapsed Time Recorder with Alarm" tristate "Dallas DS1682 Total Elapsed Time Recorder with Alarm"
depends on EXPERIMENTAL depends on EXPERIMENTAL
...@@ -130,18 +104,6 @@ config TPS65010 ...@@ -130,18 +104,6 @@ config TPS65010
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called tps65010. will be called tps65010.
config SENSORS_M41T00
tristate "ST M41T00 RTC chip (DEPRECATED)"
depends on PPC32
help
If you say yes here you get support for the ST M41T00 RTC chip.
This driver can also be built as a module. If so, the module
will be called m41t00.
This driver is deprecated and will be dropped soon. Use
rtc-ds1307 or rtc-m41t80 instead.
config SENSORS_MAX6875 config SENSORS_MAX6875
tristate "Maxim MAX6875 Power supply supervisor" tristate "Maxim MAX6875 Power supply supervisor"
depends on EXPERIMENTAL depends on EXPERIMENTAL
......
...@@ -2,12 +2,9 @@ ...@@ -2,12 +2,9 @@
# Makefile for miscellaneous I2C chip drivers. # Makefile for miscellaneous I2C chip drivers.
# #
obj-$(CONFIG_SENSORS_DS1337) += ds1337.o
obj-$(CONFIG_SENSORS_DS1374) += ds1374.o
obj-$(CONFIG_DS1682) += ds1682.o obj-$(CONFIG_DS1682) += ds1682.o
obj-$(CONFIG_SENSORS_EEPROM) += eeprom.o obj-$(CONFIG_SENSORS_EEPROM) += eeprom.o
obj-$(CONFIG_SENSORS_MAX6875) += max6875.o obj-$(CONFIG_SENSORS_MAX6875) += max6875.o
obj-$(CONFIG_SENSORS_M41T00) += m41t00.o
obj-$(CONFIG_SENSORS_PCA9539) += pca9539.o obj-$(CONFIG_SENSORS_PCA9539) += pca9539.o
obj-$(CONFIG_SENSORS_PCF8574) += pcf8574.o obj-$(CONFIG_SENSORS_PCF8574) += pcf8574.o
obj-$(CONFIG_PCF8575) += pcf8575.o obj-$(CONFIG_PCF8575) += pcf8575.o
......
This diff is collapsed.
/*
* 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");
/*
* I2C client/driver for the ST M41T00 family of i2c rtc chips.
*
* Author: Mark A. Greer <mgreer@mvista.com>
*
* 2005, 2006 (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.
*/
#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/workqueue.h>
#include <linux/platform_device.h>
#include <linux/m41t00.h>
#include <asm/time.h>
#include <asm/rtc.h>
static struct i2c_driver m41t00_driver;
static struct i2c_client *save_client;
static unsigned short ignore[] = { I2C_CLIENT_END };
static unsigned short normal_addr[] = { I2C_CLIENT_END, I2C_CLIENT_END };
static struct i2c_client_address_data addr_data = {
.normal_i2c = normal_addr,
.probe = ignore,
.ignore = ignore,
};
struct m41t00_chip_info {
u8 type;
char *name;
u8 read_limit;
u8 sec; /* Offsets for chip regs */
u8 min;
u8 hour;
u8 day;
u8 mon;
u8 year;
u8 alarm_mon;
u8 alarm_hour;
u8 sqw;
u8 sqw_freq;
};
static struct m41t00_chip_info m41t00_chip_info_tbl[] = {
{
.type = M41T00_TYPE_M41T00,
.name = "m41t00",
.read_limit = 5,
.sec = 0,
.min = 1,
.hour = 2,
.day = 4,
.mon = 5,
.year = 6,
},
{
.type = M41T00_TYPE_M41T81,
.name = "m41t81",
.read_limit = 1,
.sec = 1,
.min = 2,
.hour = 3,
.day = 5,
.mon = 6,
.year = 7,
.alarm_mon = 0xa,
.alarm_hour = 0xc,
.sqw = 0x13,
},
{
.type = M41T00_TYPE_M41T85,
.name = "m41t85",
.read_limit = 1,
.sec = 1,
.min = 2,
.hour = 3,
.day = 5,
.mon = 6,
.year = 7,
.alarm_mon = 0xa,
.alarm_hour = 0xc,
.sqw = 0x13,
},
};
static struct m41t00_chip_info *m41t00_chip;
ulong
m41t00_get_rtc_time(void)
{
s32 sec, min, hour, day, mon, year;
s32 sec1, min1, hour1, day1, mon1, year1;
u8 reads = 0;
u8 buf[8], msgbuf[1] = { 0 }; /* offset into rtc's regs */
struct i2c_msg msgs[] = {
{
.addr = save_client->addr,
.flags = 0,
.len = 1,
.buf = msgbuf,
},
{
.addr = save_client->addr,
.flags = I2C_M_RD,
.len = 8,
.buf = buf,
},
};
sec = min = hour = day = mon = year = 0;
do {
if (i2c_transfer(save_client->adapter, msgs, 2) < 0)
goto read_err;
sec1 = sec;
min1 = min;
hour1 = hour;
day1 = day;
mon1 = mon;
year1 = year;
sec = buf[m41t00_chip->sec] & 0x7f;
min = buf[m41t00_chip->min] & 0x7f;
hour = buf[m41t00_chip->hour] & 0x3f;
day = buf[m41t00_chip->day] & 0x3f;
mon = buf[m41t00_chip->mon] & 0x1f;
year = buf[m41t00_chip->year];
} while ((++reads < m41t00_chip->read_limit) && ((sec != sec1)
|| (min != min1) || (hour != hour1) || (day != day1)
|| (mon != mon1) || (year != year1)));
if ((m41t00_chip->read_limit > 1) && ((sec != sec1) || (min != min1)
|| (hour != hour1) || (day != day1) || (mon != mon1)
|| (year != year1)))
goto read_err;
sec = BCD2BIN(sec);
min = BCD2BIN(min);
hour = BCD2BIN(hour);
day = BCD2BIN(day);
mon = BCD2BIN(mon);
year = BCD2BIN(year);
year += 1900;
if (year < 1970)
year += 100;
return mktime(year, mon, day, hour, min, sec);
read_err:
dev_err(&save_client->dev, "m41t00_get_rtc_time: Read error\n");
return 0;
}
EXPORT_SYMBOL_GPL(m41t00_get_rtc_time);
static void
m41t00_set(void *arg)
{
struct rtc_time tm;
int nowtime = *(int *)arg;
s32 sec, min, hour, day, mon, year;
u8 wbuf[9], *buf = &wbuf[1], msgbuf[1] = { 0 };
struct i2c_msg msgs[] = {
{
.addr = save_client->addr,
.flags = 0,
.len = 1,
.buf = msgbuf,
},
{
.addr = save_client->addr,
.flags = I2C_M_RD,
.len = 8,
.buf = buf,
},
};
to_tm(nowtime, &tm);
tm.tm_year = (tm.tm_year - 1900) % 100;
sec = BIN2BCD(tm.tm_sec);
min = BIN2BCD(tm.tm_min);
hour = BIN2BCD(tm.tm_hour);
day = BIN2BCD(tm.tm_mday);
mon = BIN2BCD(tm.tm_mon);
year = BIN2BCD(tm.tm_year);
/* Read reg values into buf[0..7]/wbuf[1..8] */
if (i2c_transfer(save_client->adapter, msgs, 2) < 0) {
dev_err(&save_client->dev, "m41t00_set: Read error\n");
return;
}
wbuf[0] = 0; /* offset into rtc's regs */
buf[m41t00_chip->sec] = (buf[m41t00_chip->sec] & ~0x7f) | (sec & 0x7f);
buf[m41t00_chip->min] = (buf[m41t00_chip->min] & ~0x7f) | (min & 0x7f);
buf[m41t00_chip->hour] = (buf[m41t00_chip->hour] & ~0x3f) | (hour& 0x3f);
buf[m41t00_chip->day] = (buf[m41t00_chip->day] & ~0x3f) | (day & 0x3f);
buf[m41t00_chip->mon] = (buf[m41t00_chip->mon] & ~0x1f) | (mon & 0x1f);
buf[m41t00_chip->year] = year;
if (i2c_master_send(save_client, wbuf, 9) < 0)
dev_err(&save_client->dev, "m41t00_set: Write error\n");
}
static ulong new_time;
/* well, isn't this API just _lovely_? */
static void
m41t00_barf(struct work_struct *unusable)
{
m41t00_set(&new_time);
}
static struct workqueue_struct *m41t00_wq;
static DECLARE_WORK(m41t00_work, m41t00_barf);
int
m41t00_set_rtc_time(ulong nowtime)
{
new_time = nowtime;
if (in_interrupt())
queue_work(m41t00_wq, &m41t00_work);
else
m41t00_set(&new_time);
return 0;
}
EXPORT_SYMBOL_GPL(m41t00_set_rtc_time);
/*
*****************************************************************************
*
* platform_data Driver Interface
*
*****************************************************************************
*/
static int __init
m41t00_platform_probe(struct platform_device *pdev)
{
struct m41t00_platform_data *pdata;
int i;
if (pdev && (pdata = pdev->dev.platform_data)) {
normal_addr[0] = pdata->i2c_addr;
for (i=0; i<ARRAY_SIZE(m41t00_chip_info_tbl); i++)
if (m41t00_chip_info_tbl[i].type == pdata->type) {
m41t00_chip = &m41t00_chip_info_tbl[i];
m41t00_chip->sqw_freq = pdata->sqw_freq;
return 0;
}
}
return -ENODEV;
}
static int __exit
m41t00_platform_remove(struct platform_device *pdev)
{
return 0;
}
static struct platform_driver m41t00_platform_driver = {
.probe = m41t00_platform_probe,
.remove = m41t00_platform_remove,
.driver = {
.owner = THIS_MODULE,
.name = M41T00_DRV_NAME,
},
};
/*
*****************************************************************************
*
* Driver Interface
*
*****************************************************************************
*/
static int
m41t00_probe(struct i2c_adapter *adap, int addr, int kind)
{
struct i2c_client *client;
int rc;
if (!i2c_check_functionality(adap, I2C_FUNC_I2C
| I2C_FUNC_SMBUS_BYTE_DATA))
return 0;
client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
if (!client)
return -ENOMEM;
strlcpy(client->name, m41t00_chip->name, I2C_NAME_SIZE);
client->addr = addr;
client->adapter = adap;
client->driver = &m41t00_driver;
if ((rc = i2c_attach_client(client)))
goto attach_err;
if (m41t00_chip->type != M41T00_TYPE_M41T00) {
/* If asked, disable SQW, set SQW frequency & re-enable */
if (m41t00_chip->sqw_freq)
if (((rc = i2c_smbus_read_byte_data(client,
m41t00_chip->alarm_mon)) < 0)
|| ((rc = i2c_smbus_write_byte_data(client,
m41t00_chip->alarm_mon, rc & ~0x40)) <0)
|| ((rc = i2c_smbus_write_byte_data(client,
m41t00_chip->sqw,
m41t00_chip->sqw_freq)) < 0)
|| ((rc = i2c_smbus_write_byte_data(client,
m41t00_chip->alarm_mon, rc | 0x40)) <0))
goto sqw_err;
/* Make sure HT (Halt Update) bit is cleared */
if ((rc = i2c_smbus_read_byte_data(client,
m41t00_chip->alarm_hour)) < 0)
goto ht_err;
if (rc & 0x40)
if ((rc = i2c_smbus_write_byte_data(client,
m41t00_chip->alarm_hour, rc & ~0x40))<0)
goto ht_err;
}
/* Make sure ST (stop) bit is cleared */
if ((rc = i2c_smbus_read_byte_data(client, m41t00_chip->sec)) < 0)
goto st_err;
if (rc & 0x80)
if ((rc = i2c_smbus_write_byte_data(client, m41t00_chip->sec,
rc & ~0x80)) < 0)
goto st_err;
m41t00_wq = create_singlethread_workqueue(m41t00_chip->name);
save_client = client;
return 0;
st_err:
dev_err(&client->dev, "m41t00_probe: Can't clear ST bit\n");
goto attach_err;
ht_err:
dev_err(&client->dev, "m41t00_probe: Can't clear HT bit\n");
goto attach_err;
sqw_err:
dev_err(&client->dev, "m41t00_probe: Can't set SQW Frequency\n");
attach_err:
kfree(client);
return rc;
}
static int
m41t00_attach(struct i2c_adapter *adap)
{
return i2c_probe(adap, &addr_data, m41t00_probe);
}
static int
m41t00_detach(struct i2c_client *client)
{
int rc;
if ((rc = i2c_detach_client(client)) == 0) {
kfree(client);
destroy_workqueue(m41t00_wq);
}
return rc;
}
static struct i2c_driver m41t00_driver = {
.driver = {
.name = M41T00_DRV_NAME,
},
.id = I2C_DRIVERID_STM41T00,
.attach_adapter = m41t00_attach,
.detach_client = m41t00_detach,
};
static int __init
m41t00_init(void)
{
int rc;
if (!(rc = platform_driver_register(&m41t00_platform_driver)))
rc = i2c_add_driver(&m41t00_driver);
return rc;
}
static void __exit
m41t00_exit(void)
{
i2c_del_driver(&m41t00_driver);
platform_driver_unregister(&m41t00_platform_driver);
}
module_init(m41t00_init);
module_exit(m41t00_exit);
MODULE_AUTHOR("Mark A. Greer <mgreer@mvista.com>");
MODULE_DESCRIPTION("ST Microelectronics M41T00 RTC I2C Client Driver");
MODULE_LICENSE("GPL");
...@@ -83,7 +83,6 @@ ...@@ -83,7 +83,6 @@
#define I2C_DRIVERID_SAA7114 49 /* video decoder */ #define I2C_DRIVERID_SAA7114 49 /* video decoder */
#define I2C_DRIVERID_ZR36120 50 /* Zoran 36120 video encoder */ #define I2C_DRIVERID_ZR36120 50 /* Zoran 36120 video encoder */
#define I2C_DRIVERID_24LC32A 51 /* Microchip 24LC32A 32k EEPROM */ #define I2C_DRIVERID_24LC32A 51 /* Microchip 24LC32A 32k EEPROM */
#define I2C_DRIVERID_STM41T00 52 /* real time clock */
#define I2C_DRIVERID_UDA1342 53 /* UDA1342 audio codec */ #define I2C_DRIVERID_UDA1342 53 /* UDA1342 audio codec */
#define I2C_DRIVERID_ADV7170 54 /* video encoder */ #define I2C_DRIVERID_ADV7170 54 /* video encoder */
#define I2C_DRIVERID_MAX1617 56 /* temp sensor */ #define I2C_DRIVERID_MAX1617 56 /* temp sensor */
...@@ -95,7 +94,6 @@ ...@@ -95,7 +94,6 @@
#define I2C_DRIVERID_TDA7313 62 /* TDA7313 audio processor */ #define I2C_DRIVERID_TDA7313 62 /* TDA7313 audio processor */
#define I2C_DRIVERID_MAX6900 63 /* MAX6900 real-time clock */ #define I2C_DRIVERID_MAX6900 63 /* MAX6900 real-time clock */
#define I2C_DRIVERID_SAA7114H 64 /* video decoder */ #define I2C_DRIVERID_SAA7114H 64 /* video decoder */
#define I2C_DRIVERID_DS1374 65 /* DS1374 real time clock */
#define I2C_DRIVERID_TDA9874 66 /* TV sound decoder */ #define I2C_DRIVERID_TDA9874 66 /* TV sound decoder */
#define I2C_DRIVERID_SAA6752HS 67 /* MPEG2 encoder */ #define I2C_DRIVERID_SAA6752HS 67 /* MPEG2 encoder */
#define I2C_DRIVERID_TVEEPROM 68 /* TV EEPROM */ #define I2C_DRIVERID_TVEEPROM 68 /* TV EEPROM */
......
/*
* Definitions for the ST M41T00 family of i2c rtc chips.
*
* Author: Mark A. Greer <mgreer@mvista.com>
*
* 2005, 2006 (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.
*/
#ifndef _M41T00_H
#define _M41T00_H
#define M41T00_DRV_NAME "m41t00"
#define M41T00_I2C_ADDR 0x68
#define M41T00_TYPE_M41T00 0
#define M41T00_TYPE_M41T81 81
#define M41T00_TYPE_M41T85 85
struct m41t00_platform_data {
u8 type;
u8 i2c_addr;
u8 sqw_freq;
};
/* SQW output disabled, this is default value by power on */
#define M41T00_SQW_DISABLE (0)
#define M41T00_SQW_32KHZ (1<<4) /* 32.768 KHz */
#define M41T00_SQW_8KHZ (2<<4) /* 8.192 KHz */
#define M41T00_SQW_4KHZ (3<<4) /* 4.096 KHz */
#define M41T00_SQW_2KHZ (4<<4) /* 2.048 KHz */
#define M41T00_SQW_1KHZ (5<<4) /* 1.024 KHz */
#define M41T00_SQW_512HZ (6<<4) /* 512 Hz */
#define M41T00_SQW_256HZ (7<<4) /* 256 Hz */
#define M41T00_SQW_128HZ (8<<4) /* 128 Hz */
#define M41T00_SQW_64HZ (9<<4) /* 64 Hz */
#define M41T00_SQW_32HZ (10<<4) /* 32 Hz */
#define M41T00_SQW_16HZ (11<<4) /* 16 Hz */
#define M41T00_SQW_8HZ (12<<4) /* 8 Hz */
#define M41T00_SQW_4HZ (13<<4) /* 4 Hz */
#define M41T00_SQW_2HZ (14<<4) /* 2 Hz */
#define M41T00_SQW_1HZ (15<<4) /* 1 Hz */
extern ulong m41t00_get_rtc_time(void);
extern int m41t00_set_rtc_time(ulong nowtime);
#endif /* _M41T00_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment