From: Jean Delvare <khali@linux-fr.org>
To: Mark Zhan <rongkai.zhan@windriver.com>
Cc: i2c@lm-sensors.org, linux-mips@linux-mips.org,
rtc-linux@googlegroups.com, a.zummo@towertech.it,
ralf@linux-mips.org
Subject: Re: [i2c] [PATCH 3/4] RTC: add Xicor 1241 driver
Date: Mon, 1 Oct 2007 15:59:38 +0200 [thread overview]
Message-ID: <20071001155938.0590fc3a@hyperion.delvare> (raw)
In-Reply-To: <46FF7279.3020102@windriver.com>
Hi Mark,
On Sun, 30 Sep 2007 17:55:05 +0800, Mark Zhan wrote:
> This patch add the Xicor 1241 RTC driver which is used in
> MIPS Sibyte 1250/1480 boards.
So this chip is using two-byte register addressing, which isn't
compatible with SMBus. Which explains why the register reads and writes
in your driver look strange. I don't think it's quite correct.
> +/*
> + * 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);
If I read the datasheet properly, this should be:
i2c_smbus_write_byte_data(client, 0, X1241_SEC);
The SC register is at 0x0030, not 0x3030.
> + 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);
You are using the "Current Address Read" mode here, right? If so, you
aren't supposed to send any address information at all, i.e. you should
use i2c_smbus_read_byte() instead of i2c_smbus_read_byte_data(). You
are probably just lucky that the chip ignores the extra byte you're
sending.
> (...)
> +static int xicor1241_set_time(struct device *dev, struct rtc_time *tm)
> +{
> (...)
> + /* 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);
Here again I am surprised. I expected:
i2c_smbus_write_word_data(client, 0, (sec << 8) | X1241_SEC);
So that you write to register 0x0030, not 0x3030. Same for all the
other register writes. Or am I misreading the datasheet?
> +
> + 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;
> + }
This check isn't sufficient, you must check for
I2C_FUNC_SMBUS_WRITE_WORD_DATA as well, and possibly
I2C_FUNC_SMBUS_READ_BYTE if my comment above is correct.
--
Jean Delvare
prev parent reply other threads:[~2007-10-01 14:00 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-09-30 9:55 [PATCH 3/4] RTC: add Xicor 1241 driver Mark Zhan
2007-10-01 13:59 ` Jean Delvare [this message]
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=20071001155938.0590fc3a@hyperion.delvare \
--to=khali@linux-fr.org \
--cc=a.zummo@towertech.it \
--cc=i2c@lm-sensors.org \
--cc=linux-mips@linux-mips.org \
--cc=ralf@linux-mips.org \
--cc=rongkai.zhan@windriver.com \
--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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox