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 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.