On Wed, Jan 25, 2006 at 07:01:33PM -0700, Mark A. Greer wrote: > Andrey, et. al., how does this look & work? > Diff'd against linux-2.6.16-rc1-mm2. Oops, had a minor mess up in the previous patch. This one replaces that one. Mark --- diff -Nurp linux-2.6.16-rc1-mm2/drivers/i2c/chips/Kconfig linux-2.6.16-rc1-mm2-m41txx/drivers/i2c/chips/Kconfig --- linux-2.6.16-rc1-mm2/drivers/i2c/chips/Kconfig 2006-01-17 00:44:47.000000000 -0700 +++ linux-2.6.16-rc1-mm2-m41txx/drivers/i2c/chips/Kconfig 2006-01-23 18:35:36.000000000 -0700 @@ -102,15 +102,6 @@ config TPS65010 This driver can also be built as a module. If so, the module will be called tps65010. -config SENSORS_M41T00 - tristate "ST M41T00 RTC chip" - depends on I2C && 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. - config SENSORS_MAX6875 tristate "Maxim MAX6875 Power supply supervisor" depends on I2C && EXPERIMENTAL @@ -135,4 +126,14 @@ config RTC_X1205_I2C This driver can also be built as a module. If so, the module will be called x1205. +config RTC_M41TXX_I2C + tristate "ST M41TXX Family of I2C RTC chips" + depends on I2C + help + If you say yes here you get support for the ST M41TXX family + of I2C RTC chips. + + This driver can also be built as a module. If so, the module + will be called m41txx. + endmenu diff -Nurp linux-2.6.16-rc1-mm2/drivers/i2c/chips/m41t00.c linux-2.6.16-rc1-mm2-m41txx/drivers/i2c/chips/m41t00.c --- linux-2.6.16-rc1-mm2/drivers/i2c/chips/m41t00.c 2006-01-23 15:02:47.000000000 -0700 +++ linux-2.6.16-rc1-mm2-m41txx/drivers/i2c/chips/m41t00.c 1969-12-31 17:00:00.000000000 -0700 @@ -1,241 +0,0 @@ -/* - * drivers/i2c/chips/m41t00.c - * - * I2C client/driver for the ST M41T00 Real-Time Clock chip. - * - * Author: Mark A. Greer <mgreer at 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 <asm/time.h> -#include <asm/rtc.h> - -#define M41T00_DRV_NAME "m41t00" - -static DEFINE_MUTEX(m41t00_mutex); - -static struct i2c_driver m41t00_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, -}; - -ulong -m41t00_get_rtc_time(void) -{ - s32 sec, min, hour, day, mon, year; - s32 sec1, min1, hour1, day1, mon1, year1; - ulong limit = 10; - - sec = min = hour = day = mon = year = 0; - sec1 = min1 = hour1 = day1 = mon1 = year1 = 0; - - mutex_lock(&m41t00_mutex); - do { - if (((sec = i2c_smbus_read_byte_data(save_client, 0)) >= 0) - && ((min = i2c_smbus_read_byte_data(save_client, 1)) - >= 0) - && ((hour = i2c_smbus_read_byte_data(save_client, 2)) - >= 0) - && ((day = i2c_smbus_read_byte_data(save_client, 4)) - >= 0) - && ((mon = i2c_smbus_read_byte_data(save_client, 5)) - >= 0) - && ((year = i2c_smbus_read_byte_data(save_client, 6)) - >= 0) - && ((sec == sec1) && (min == min1) && (hour == hour1) - && (day == day1) && (mon == mon1) - && (year == year1))) - - break; - - sec1 = sec; - min1 = min; - hour1 = hour; - day1 = day; - mon1 = mon; - year1 = year; - } while (--limit > 0); - mutex_unlock(&m41t00_mutex); - - if (limit == 0) { - dev_warn(&save_client->dev, - "m41t00: can't read rtc chip\n"); - sec = min = hour = day = mon = year = 0; - } - - sec &= 0x7f; - min &= 0x7f; - hour &= 0x3f; - day &= 0x3f; - mon &= 0x1f; - year &= 0xff; - - BCD_TO_BIN(sec); - BCD_TO_BIN(min); - BCD_TO_BIN(hour); - BCD_TO_BIN(day); - BCD_TO_BIN(mon); - BCD_TO_BIN(year); - - year += 1900; - if (year < 1970) - year += 100; - - return mktime(year, mon, day, hour, min, sec); -} - -static void -m41t00_set_tlet(ulong arg) -{ - struct rtc_time tm; - ulong nowtime = *(ulong *)arg; - - to_tm(nowtime, &tm); - tm.tm_year = (tm.tm_year - 1900) % 100; - - BIN_TO_BCD(tm.tm_sec); - BIN_TO_BCD(tm.tm_min); - BIN_TO_BCD(tm.tm_hour); - BIN_TO_BCD(tm.tm_mon); - BIN_TO_BCD(tm.tm_mday); - BIN_TO_BCD(tm.tm_year); - - mutex_lock(&m41t00_mutex); - if ((i2c_smbus_write_byte_data(save_client, 0, tm.tm_sec & 0x7f) < 0) - || (i2c_smbus_write_byte_data(save_client, 1, tm.tm_min & 0x7f) - < 0) - || (i2c_smbus_write_byte_data(save_client, 2, tm.tm_hour & 0x7f) - < 0) - || (i2c_smbus_write_byte_data(save_client, 4, tm.tm_mday & 0x7f) - < 0) - || (i2c_smbus_write_byte_data(save_client, 5, tm.tm_mon & 0x7f) - < 0) - || (i2c_smbus_write_byte_data(save_client, 6, tm.tm_year & 0x7f) - < 0)) - - dev_warn(&save_client->dev,"m41t00: can't write to rtc chip\n"); - - mutex_unlock(&m41t00_mutex); - return; -} - -static ulong new_time; - -DECLARE_TASKLET_DISABLED(m41t00_tasklet, m41t00_set_tlet, (ulong)&new_time); - -int -m41t00_set_rtc_time(ulong nowtime) -{ - new_time = nowtime; - - if (in_interrupt()) - tasklet_schedule(&m41t00_tasklet); - else - m41t00_set_tlet((ulong)&new_time); - - return 0; -} - -/* - ***************************************************************************** - * - * Driver Interface - * - ***************************************************************************** - */ -static int -m41t00_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, M41T00_DRV_NAME, I2C_NAME_SIZE); - client->addr = addr; - client->adapter = adap; - client->driver = &m41t00_driver; - - if ((rc = i2c_attach_client(client)) != 0) { - kfree(client); - return rc; - } - - save_client = client; - return 0; -} - -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); - tasklet_kill(&m41t00_tasklet); - } - 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) -{ - return i2c_add_driver(&m41t00_driver); -} - -static void __exit -m41t00_exit(void) -{ - i2c_del_driver(&m41t00_driver); - return; -} - -module_init(m41t00_init); -module_exit(m41t00_exit); - -MODULE_AUTHOR("Mark A. Greer <mgreer at mvista.com>"); -MODULE_DESCRIPTION("ST Microelectronics M41T00 RTC I2C Client Driver"); -MODULE_LICENSE("GPL"); diff -Nurp linux-2.6.16-rc1-mm2/drivers/i2c/chips/m41txx.c linux-2.6.16-rc1-mm2-m41txx/drivers/i2c/chips/m41txx.c --- linux-2.6.16-rc1-mm2/drivers/i2c/chips/m41txx.c 1969-12-31 17:00:00.000000000 -0700 +++ linux-2.6.16-rc1-mm2-m41txx/drivers/i2c/chips/m41txx.c 2006-01-26 13:19:23.000000000 -0700 @@ -0,0 +1,365 @@ +/* + * I2C client/driver for the ST M41Txx family of i2c rtc chips. + * + * Author: Mark A. Greer <mgreer at 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. + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/interrupt.h> +#include <linux/i2c.h> +#include <linux/rtc.h> +#include <linux/m41txx.h> +#include <linux/bcd.h> +#include <linux/workqueue.h> +#include <linux/platform_device.h> + +#include <asm/time.h> +#include <asm/rtc.h> + +static struct work_struct set_rtc_time_task; + +static struct i2c_driver m41txx_driver; +static struct i2c_client *save_client; + +static unsigned short ignore[] = { I2C_CLIENT_END }; +static unsigned short normal_addr[] = { 0, I2C_CLIENT_END }; + +static struct i2c_client_address_data addr_data = { + .normal_i2c = normal_addr, + .probe = ignore, + .ignore = ignore, +}; + +struct m41txx_chip_info { + u16 type; + u16 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; + u32 sqw_freq; +}; + +static struct m41txx_chip_info m41txx_chip_info_tbl[] = { + { M41TXX_TYPE_M41T00, 5, 0, 1, 2, 4, 5, 6, 0, 0, 0, 0 }, + { M41TXX_TYPE_M41T81, 1, 1, 2, 3, 5, 6, 7, 0xa, 0xc, 0x13, 0 }, + { M41TXX_TYPE_M41T85, 1, 1, 2, 3, 5, 6, 7, 0xa, 0xc, 0x13, 0 }, +}; +static struct m41txx_chip_info *m41txx_chip; + +unsigned long +m41txx_get_rtc_time(void) +{ + s32 sec, min, hour, day, mon, year; + s32 sec1, min1, hour1, day1, mon1, year1; + u16 reads = 0; + u8 buf[8], msgbuf[1] = { 0 }; /* offset into rtc's regs */ + struct i2c_msg msgs[] = { + { save_client->addr, 0, 1, msgbuf }, + { save_client->addr, I2C_M_RD, 8, 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[m41txx_chip->sec] & 0x7f; + min = buf[m41txx_chip->min] & 0x7f; + hour = buf[m41txx_chip->hour] & 0x3f; + day = buf[m41txx_chip->day] & 0x3f; + mon = buf[m41txx_chip->mon] & 0x1f; + year = buf[m41txx_chip->year] & 0xff; + } while ((++reads < m41txx_chip->read_limit) && ((sec != sec1) + || (min != min1) || (hour != hour1) || (day != day1) + || (mon != mon1) || (year != year1))); + + if ((m41txx_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, "m41txx_get_rtc_time: Read error\n"); + return 0; +} + +static void +m41txx_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[] = { + { save_client->addr, 0, 1, msgbuf }, + { save_client->addr, I2C_M_RD, 8, 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, "m41txx_set: Read error\n"); + return; + } + + wbuf[0] = 0; /* offset into rtc's regs */ + buf[m41txx_chip->sec] = (buf[m41txx_chip->sec] & ~0x7f) | (sec & 0x7f); + buf[m41txx_chip->min] = (buf[m41txx_chip->min] & ~0x7f) | (min & 0x7f); + buf[m41txx_chip->hour] = (buf[m41txx_chip->hour]& ~0x3f) | (hour& 0x3f); + buf[m41txx_chip->day] = (buf[m41txx_chip->day] & ~0x3f) | (day & 0x3f); + buf[m41txx_chip->mon] = (buf[m41txx_chip->mon] & ~0x1f) | (mon & 0x1f); + + if (i2c_master_send(save_client, wbuf, 9) < 0) + dev_err(&save_client->dev, "m41txx_set: Write error\n"); +} + +static u32 new_time; + +int +m41txx_set_rtc_time(unsigned long nowtime) +{ + new_time = nowtime; + + if (in_interrupt()) + schedule_work(&set_rtc_time_task); + else + m41txx_set((void *)&new_time); + return 0; +} + +/* + ***************************************************************************** + * + * platform_data Driver Interface + * + ***************************************************************************** + */ +static int __init +m41txx_platform_probe(struct platform_device *pdev) +{ + struct m41txx_platform_data *pdata; + int i; + + if (pdev && (pdata = pdev->dev.platform_data)) { + normal_addr[0] = pdata->i2c_addr; + + for (i=0; i<ARRAY_SIZE(m41txx_chip_info_tbl); i++) + if (m41txx_chip_info_tbl[i].type == pdata->type) { + m41txx_chip = &m41txx_chip_info_tbl[i]; + m41txx_chip->sqw_freq = pdata->sqw_freq; + return 0; + } + } + return -ENODEV; +} + +static int __exit +m41txx_platform_remove(struct platform_device *pdev) +{ + return 0; +} + +static struct platform_driver m41txx_platform_driver = { + .probe = m41txx_platform_probe, + .remove = m41txx_platform_remove, + .driver = { + .owner = THIS_MODULE, + .name = M41TXX_DRV_NAME, + }, +}; + +/* + ***************************************************************************** + * + * Driver Interface + * + ***************************************************************************** + */ +static int +m41txx_probe(struct i2c_adapter *adap, int addr, int kind) +{ + struct i2c_client *client; + int rc; + u8 rbuf[1], wbuf[2], msgbuf[1] = { 0 }; /* offset into rtc's regs */ + struct i2c_msg msgs[] = { + { 0, 0, 1, msgbuf }, + { 0, I2C_M_RD, 1, rbuf } + }; + + client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); + if (!client) + return -ENOMEM; + + strlcpy(client->name, m41txx_driver.driver.name, I2C_NAME_SIZE); + client->addr = addr; + client->adapter = adap; + client->driver = &m41txx_driver; + + if ((rc = i2c_attach_client(client)) != 0) + goto attach_err; + + msgs[0].addr = addr; + msgs[1].addr = addr; + + if (m41txx_chip->type != M41TXX_TYPE_M41T00) { + /* If asked, set SQW frequency & enable */ + if (m41txx_chip->sqw_freq) { + msgbuf[0] = m41txx_chip->alarm_mon; + if ((rc = i2c_transfer(client->adapter, msgs, 2)) < 0) + goto sqw_err; + + wbuf[0] = m41txx_chip->alarm_mon; + wbuf[1] = rbuf[0] & ~0x40; + if ((rc = i2c_master_send(client, wbuf, 2)) < 0) + goto sqw_err; + + wbuf[0] = m41txx_chip->sqw; + wbuf[1] = m41txx_chip->sqw_freq; + if ((rc = i2c_master_send(client, wbuf, 2)) < 0) + goto sqw_err; + + wbuf[0] = m41txx_chip->alarm_mon; + wbuf[1] = rbuf[0] | 0x40; + if ((rc = i2c_master_send(client, wbuf, 2)) < 0) + goto sqw_err; + } + + /* Make sure HT (Halt Update) bit is cleared */ + msgbuf[0] = m41txx_chip->alarm_hour; + if ((rc = i2c_transfer(client->adapter, msgs, 2)) < 0) + goto ht_err; + + if (rbuf[0] & 0x40) { + wbuf[0] = m41txx_chip->alarm_hour; + wbuf[1] = rbuf[0] & ~0x40; + if ((rc = i2c_master_send(client, wbuf, 2)) < 0) + goto ht_err; + } + } + + /* Make sure ST (stop) bit is cleared */ + msgbuf[0] = m41txx_chip->sec; + if ((rc = i2c_transfer(client->adapter, msgs, 2)) < 0) + goto st_err; + + if (rbuf[0] & 0x80) { + wbuf[0] = m41txx_chip->sec; + wbuf[1] = rbuf[0] & ~0x80; + if ((rc = i2c_master_send(client, wbuf, 2)) < 0) + goto st_err; + } + + INIT_WORK(&set_rtc_time_task, &m41txx_set, &new_time); + save_client = client; + return 0; + +st_err: + dev_err(&client->dev, "m41txx_probe: Can't clear ST bit\n"); + goto attach_err; +ht_err: + dev_err(&client->dev, "m41txx_probe: Can't clear HT bit\n"); + goto attach_err; +sqw_err: + dev_err(&client->dev, "m41txx_probe: Can't set SQW Frequency\n"); +attach_err: + kfree(client); + return rc; +} + +static int +m41txx_attach(struct i2c_adapter *adap) +{ + return i2c_probe(adap, &addr_data, m41txx_probe); +} + +static int +m41txx_detach(struct i2c_client *client) +{ + int rc; + + if ((rc = i2c_detach_client(client)) == 0) { + kfree(client); + flush_scheduled_work(); + } + return rc; +} + +static struct i2c_driver m41txx_driver = { + .driver = { + .owner = THIS_MODULE, + .name = M41TXX_DRV_NAME, + }, + .id = I2C_DRIVERID_STM41TXX, + .attach_adapter = m41txx_attach, + .detach_client = m41txx_detach, +}; + +static int __init +m41txx_init(void) +{ + int rc; + + if (!(rc = platform_driver_register(&m41txx_platform_driver))) + rc = i2c_add_driver(&m41txx_driver); + return rc; +} + +static void __exit +m41txx_exit(void) +{ + i2c_del_driver(&m41txx_driver); + platform_driver_unregister(&m41txx_platform_driver); +} + +module_init(m41txx_init); +module_exit(m41txx_exit); + +MODULE_AUTHOR("Mark A. Greer <mgreer at mvista.com>"); +MODULE_DESCRIPTION("ST Microelectronics M41TXX RTC I2C Client Driver"); +MODULE_LICENSE("GPL"); diff -Nurp linux-2.6.16-rc1-mm2/drivers/i2c/chips/Makefile linux-2.6.16-rc1-mm2-m41txx/drivers/i2c/chips/Makefile --- linux-2.6.16-rc1-mm2/drivers/i2c/chips/Makefile 2006-01-17 00:44:47.000000000 -0700 +++ linux-2.6.16-rc1-mm2-m41txx/drivers/i2c/chips/Makefile 2006-01-23 18:18:26.000000000 -0700 @@ -6,7 +6,6 @@ obj-$(CONFIG_SENSORS_DS1337) += ds1337.o obj-$(CONFIG_SENSORS_DS1374) += ds1374.o obj-$(CONFIG_SENSORS_EEPROM) += eeprom.o obj-$(CONFIG_SENSORS_MAX6875) += max6875.o -obj-$(CONFIG_SENSORS_M41T00) += m41t00.o obj-$(CONFIG_SENSORS_PCA9539) += pca9539.o obj-$(CONFIG_SENSORS_PCF8574) += pcf8574.o obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o @@ -14,6 +13,7 @@ obj-$(CONFIG_SENSORS_RTC8564) += rtc8564 obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o obj-$(CONFIG_TPS65010) += tps65010.o obj-$(CONFIG_RTC_X1205_I2C) += x1205.o +obj-$(CONFIG_RTC_M41TXX_I2C) += m41txx.o ifeq ($(CONFIG_I2C_DEBUG_CHIP),y) EXTRA_CFLAGS += -DDEBUG diff -Nurp linux-2.6.16-rc1-mm2/include/linux/i2c-id.h linux-2.6.16-rc1-mm2-m41txx/include/linux/i2c-id.h --- linux-2.6.16-rc1-mm2/include/linux/i2c-id.h 2006-01-17 00:44:47.000000000 -0700 +++ linux-2.6.16-rc1-mm2-m41txx/include/linux/i2c-id.h 2006-01-23 18:18:26.000000000 -0700 @@ -79,7 +79,7 @@ #define I2C_DRIVERID_SAA7114 49 /* video decoder */ #define I2C_DRIVERID_ZR36120 50 /* Zoran 36120 video encoder */ #define I2C_DRIVERID_24LC32A 51 /* Microchip 24LC32A 32k EEPROM */ -#define I2C_DRIVERID_STM41T00 52 /* real time clock */ +#define I2C_DRIVERID_STM41TXX 52 /* real time clock */ #define I2C_DRIVERID_UDA1342 53 /* UDA1342 audio codec */ #define I2C_DRIVERID_ADV7170 54 /* video encoder */ #define I2C_DRIVERID_RADEON 55 /* I2C bus on Radeon boards */ diff -Nurp linux-2.6.16-rc1-mm2/include/linux/m41txx.h linux-2.6.16-rc1-mm2-m41txx/include/linux/m41txx.h --- linux-2.6.16-rc1-mm2/include/linux/m41txx.h 1969-12-31 17:00:00.000000000 -0700 +++ linux-2.6.16-rc1-mm2-m41txx/include/linux/m41txx.h 2006-01-23 18:39:56.000000000 -0700 @@ -0,0 +1,47 @@ +/* + * Definitions for the ST M41Txx family of i2c rtc chips. + * + * Author: Mark A. Greer <mgreer at 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. + */ + +#ifndef _M41TXX_H +#define _M41TXX_H + +#define M41TXX_DRV_NAME "m41txx rtc" +#define M41TXX_I2C_ADDR 0x68 + +#define M41TXX_TYPE_M41T00 0 +#define M41TXX_TYPE_M41T81 81 +#define M41TXX_TYPE_M41T85 85 + +struct m41txx_platform_data { + u16 type; + u16 i2c_addr; + u32 sqw_freq; +}; + +/* SQW output disabled, this is default value by power on*/ +#define SQW_FREQ_DISABLE (0) + +#define SQW_FREQ_32KHZ (1<<4) /* 32.768 KHz */ +#define SQW_FREQ_8KHZ (2<<4) /* 8.192 KHz */ +#define SQW_FREQ_4KHZ (3<<4) /* 4.096 KHz */ +#define SQW_FREQ_2KHZ (4<<4) /* 2.048 KHz */ +#define SQW_FREQ_1KHZ (5<<4) /* 1.024 KHz */ +#define SQW_FREQ_512HZ (6<<4) /* 512 Hz */ +#define SQW_FREQ_256HZ (7<<4) /* 256 Hz */ +#define SQW_FREQ_128HZ (8<<4) /* 128 Hz */ +#define SQW_FREQ_64HZ (9<<4) /* 64 Hz */ +#define SQW_FREQ_32HZ (10<<4) /* 32 Hz */ +#define SQW_FREQ_16HZ (11<<4) /* 16 Hz */ +#define SQW_FREQ_8HZ (12<<4) /* 8 Hz */ +#define SQW_FREQ_4HZ (13<<4) /* 4 Hz */ +#define SQW_FREQ_2HZ (14<<4) /* 2 Hz */ +#define SQW_FREQ_1HZ (15<<4) /* 1 Hz */ + +#endif /* _M41TXX_H */