From: Mark Zhan <rongkai.zhan@windriver.com>
To: i2c@lm-sensors.org, linux-mips@linux-mips.org,
rtc-linux@googlegroups.com
Cc: ralf@linux-mips.org, a.zummo@towertech.it, rongkai.zhan@windriver.com
Subject: [PATCH 3/4] RTC: add Xicor 1241 driver
Date: Sun, 30 Sep 2007 17:55:05 +0800 [thread overview]
Message-ID: <46FF7279.3020102@windriver.com> (raw)
This patch add the Xicor 1241 RTC driver which is used in
MIPS Sibyte 1250/1480 boards.
Signed-off-by: Mark Zhan <rongkai.zhan@windriver.com>
---
drivers/rtc/Kconfig | 10 ++
drivers/rtc/Makefile | 2
drivers/rtc/rtc-xicor1241.c | 184 ++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 196 insertions(+)
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -184,6 +184,16 @@ config RTC_DRV_X1205
This driver can also be built as a module. If so, the module
will be called rtc-x1205.
+config RTC_DRV_XICOR1241
+ tristate "Xicor 1241"
+ depends on RTC_CLASS && I2C && MIPS
+ help
+ If you say yes here you get support for the
+ Xicor 1241 RTC chip.
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-xicor1241.
+
config RTC_DRV_PCF8563
tristate "Philips PCF8563/Epson RTC8564"
help
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -48,3 +48,5 @@ obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o
obj-$(CONFIG_RTC_DRV_V3020) += rtc-v3020.o
obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o
obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o
+obj-$(CONFIG_RTC_DRV_XICOR1241) += rtc-xicor1241.o
+
--- /dev/null
+++ b/drivers/rtc/rtc-xicor1241.c
@@ -0,0 +1,184 @@
+/*
+ * Xicor 1241 RTC driver
+ *
+ * Copyright (c) 2007 Wind River Systems, Inc.
+ *
+ * Author: Mark Zhan <rongkai.zhan@windriver.com>
+ *
+ * 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/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/bcd.h>
+#include <linux/rtc.h>
+#include <linux/i2c.h>
+
+/*
+ * Register bits
+ */
+#define X1241_SR_BAT 0x80 /* currently on battery power */
+#define X1241_SR_RWEL 0x04 /* r/w latch is enabled, can write RTC */
+#define X1241_SR_WEL 0x02 /* r/w latch is unlocked, can enable r/w now */
+#define X1241_SR_RTCF 0x01 /* clock failed */
+#define X1241_HR_MIL 0x80 /* 24 hours format */
+
+/*
+ * Register Offset
+ */
+#define X1241_SEC 0x30 /* Seconds */
+#define X1241_MIN 0x31 /* Minutes */
+#define X1241_HOUR 0x32 /* Hours */
+#define X1241_MDAY 0x33 /* Day of month */
+#define X1241_MON 0x34 /* Month */
+#define X1241_YEAR 0x35 /* Year */
+#define X1241_WDAY 0x36 /* Day of Week */
+#define X1241_Y2K 0x37 /* Year 2K */
+#define X1241_SR 0x3F /* Status register */
+
+DEFINE_SPINLOCK(xicor1241_lock);
+
+static int xicor1241_get_time(struct device *dev, struct rtc_time *tm)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ unsigned int y2k, year, mon, mday, wday, hour, min, sec;
+ unsigned long flags;
+
+ spin_lock_irqsave(&xicor1241_lock, flags);
+
+ i2c_smbus_write_byte_data(client, X1241_SEC, X1241_SEC);
+ sec = i2c_smbus_read_byte_data(client, X1241_SEC);
+ min = i2c_smbus_read_byte_data(client, X1241_MIN);
+ hour = i2c_smbus_read_byte_data(client, X1241_HOUR);
+ mday = i2c_smbus_read_byte_data(client, X1241_MDAY);
+ mon = i2c_smbus_read_byte_data(client, X1241_MON);
+ year = i2c_smbus_read_byte_data(client, X1241_YEAR);
+ wday = i2c_smbus_read_byte_data(client, X1241_WDAY);
+ y2k = i2c_smbus_read_byte_data(client, X1241_Y2K);
+
+ spin_unlock_irqrestore(&xicor1241_lock, flags);
+
+ dev_dbg(dev, "X1241 read reg: y2k=%02x,year=%02x,mon=%02x,"
+ "mday=%02x,wday=%02x,hour=%02x,min=%02x,sec=%02x\n",
+ y2k, year, mon, mday, wday, hour, min, sec);
+
+ tm->tm_sec = BCD2BIN(sec);
+ tm->tm_min = BCD2BIN(min);
+ tm->tm_hour = BCD2BIN(hour & 0x3F); /* hr is 0-23 */
+ tm->tm_mday = BCD2BIN(mday);
+ tm->tm_wday = BCD2BIN(wday);
+ tm->tm_mon = BCD2BIN(mon) - 1; /* tm_mon is 0-11 */
+ tm->tm_year = BCD2BIN(year);
+ tm->tm_year += (BCD2BIN(y2k) * 100) - 1900;
+
+ dev_dbg(dev, "RTC read time %04d-%02d-%02d %02d:%02d:%02d, y2k=%02d\n",
+ tm->tm_year + 1900, tm->tm_mon+1, tm->tm_mday,
+ tm->tm_hour, tm->tm_min, tm->tm_sec, y2k);
+ return 0;
+}
+
+static int xicor1241_set_time(struct device *dev, struct rtc_time *tm)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ unsigned int y2k, year, mon, mday, wday, hour, min, sec;
+ unsigned long flags;
+
+ dev_dbg(dev, "RTC set time %04d-%02d-%02d %02d:%02d:%02d\n",
+ tm->tm_year + 1900, tm->tm_mon+1, tm->tm_mday,
+ tm->tm_hour, tm->tm_min, tm->tm_sec);
+
+ sec = BIN2BCD(tm->tm_sec);
+ min = BIN2BCD(tm->tm_min);
+ hour = BIN2BCD(tm->tm_hour) | X1241_HR_MIL; /* 24 hours format */
+ mday = BIN2BCD(tm->tm_mday);
+ wday = BIN2BCD(tm->tm_wday);
+ mon = BIN2BCD(tm->tm_mon + 1); /* tm_mon is 0-11 */
+ year = BIN2BCD(tm->tm_year % 100);
+ y2k = BIN2BCD((tm->tm_year / 100) + 19);
+
+ dev_dbg(dev, "X1241 write reg: y2k=%02x,year=%02x,mon=%02x,"
+ "mday=%02x,wday=%02x,hour=%02x,min=%02x,sec=%02x\n",
+ y2k, year, mon, mday, wday, hour, min, sec);
+
+ spin_lock_irqsave(&xicor1241_lock, flags);
+
+ /* unlock writes to the CCR */
+ i2c_smbus_write_word_data(client, X1241_SR,
+ (X1241_SR_WEL << 8) | X1241_SR);
+ i2c_smbus_write_word_data(client, X1241_SR,
+ ((X1241_SR_WEL | X1241_SR_RWEL) << 8) | X1241_SR);
+
+ i2c_smbus_write_word_data(client, X1241_SEC, (sec << 8) | X1241_SEC);
+ i2c_smbus_write_word_data(client, X1241_MIN, (min << 8) | X1241_MIN);
+ i2c_smbus_write_word_data(client, X1241_HOUR, (hour << 8) | X1241_HOUR);
+ i2c_smbus_write_word_data(client, X1241_MDAY, (mday << 8) | X1241_MDAY);
+ i2c_smbus_write_word_data(client, X1241_WDAY, (wday << 8) | X1241_WDAY);
+ i2c_smbus_write_word_data(client, X1241_MON, (mon << 8) | X1241_MON);
+ i2c_smbus_write_word_data(client, X1241_YEAR, (year << 8) | X1241_YEAR);
+ i2c_smbus_write_word_data(client, X1241_Y2K, (y2k << 8) | X1241_Y2K);
+
+ i2c_smbus_write_word_data(client, X1241_SR, (0 << 8) | X1241_SR);
+
+ spin_unlock_irqrestore(&xicor1241_lock, flags);
+ return 0;
+}
+
+static const struct rtc_class_ops xicor1241_rtc_ops = {
+ .read_time = xicor1241_get_time,
+ .set_time = xicor1241_set_time,
+};
+
+static int __devinit xicor1241_rtc_probe(struct i2c_client *client)
+{
+ struct rtc_device *rtc;
+
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
+ dev_dbg(&client->dev, "I2C adapter function check failure!\n");
+ return -ENODEV;
+ }
+
+ rtc = rtc_device_register(client->name, &client->dev,
+ &xicor1241_rtc_ops, THIS_MODULE);
+ if (IS_ERR(rtc))
+ return PTR_ERR(rtc);
+
+ i2c_set_clientdata(client, rtc);
+ return 0;
+}
+
+static int __devexit xicor1241_rtc_remove(struct i2c_client *client)
+{
+ struct rtc_device *rtc = i2c_get_clientdata(client);
+
+ rtc_device_unregister(rtc);
+ return 0;
+}
+
+static struct i2c_driver xicor1241_i2c_driver = {
+ .driver = {
+ .name = "rtc-xicor1241",
+ .owner = THIS_MODULE,
+ },
+ .probe = xicor1241_rtc_probe,
+ .remove = __devexit_p(xicor1241_rtc_remove),
+};
+
+static int __init xicor1241_rtc_init(void)
+{
+ return i2c_add_driver(&xicor1241_i2c_driver);
+}
+
+static void __exit xicor1241_rtc_exit(void)
+{
+ i2c_del_driver(&xicor1241_i2c_driver);
+}
+
+module_init(xicor1241_rtc_init);
+module_exit(xicor1241_rtc_exit);
+
+MODULE_AUTHOR("Mark Zhan <rongkai.zhan@windriver.com>");
+MODULE_DESCRIPTION("Xicor1241 RTC driver");
+MODULE_LICENSE("GPL");
next reply other threads:[~2007-09-30 9:56 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-09-30 9:55 Mark Zhan [this message]
2007-10-01 13:59 ` [i2c] [PATCH 3/4] RTC: add Xicor 1241 driver Jean Delvare
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=46FF7279.3020102@windriver.com \
--to=rongkai.zhan@windriver.com \
--cc=a.zummo@towertech.it \
--cc=i2c@lm-sensors.org \
--cc=linux-mips@linux-mips.org \
--cc=ralf@linux-mips.org \
--cc=rtc-linux@googlegroups.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.