diff mbox

[v2,9/9] rtc: hym8563: make sure hym8563 can be normal work

Message ID 1442486368-1912-1-git-send-email-zhengxing@rock-chips.com
State Rejected
Headers show

Commit Message

Xing Zheng Sept. 17, 2015, 10:39 a.m. UTC
The rtc hym8563 maybe failed to register if first startup or rtc
powerdown:
[    0.988540 ] rtc-hym8563 1-0051: no valid clock/calendar values available
[    0.995642 ] rtc-hym8563 1-0051: rtc core: registered hym8563 as rtc0
[    1.078985 ] rtc-hym8563 1-0051: no valid clock/calendar values available
[    1.085698 ] rtc-hym8563 1-0051: hctosys: unable to read the hardware clock

We can set initial time for rtc and register it:
[    0.995678 ] rtc-hym8563 1-0051: rtc core: registered hym8563 as rtc0
[    1.080313 ] rtc-hym8563 1-0051: setting system clock to 2000-01-01 00:02:00 UTC (946684920)

---

Changes in v2:
Signed-off-by: Xing Zheng <zhengxing@rock-chips.com>

 drivers/rtc/rtc-hym8563.c |   93 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 93 insertions(+)

Comments

Heiko Stuebner Sept. 17, 2015, 12:07 p.m. UTC | #1
Am Donnerstag, 17. September 2015, 18:39:28 schrieb Xing Zheng:
> The rtc hym8563 maybe failed to register if first startup or rtc
> powerdown:
> [    0.988540 ] rtc-hym8563 1-0051: no valid clock/calendar values available
> [    0.995642 ] rtc-hym8563 1-0051: rtc core: registered hym8563 as rtc0 [ 
>   1.078985 ] rtc-hym8563 1-0051: no valid clock/calendar values available [
>    1.085698 ] rtc-hym8563 1-0051: hctosys: unable to read the hardware
> clock
> 
> We can set initial time for rtc and register it:
> [    0.995678 ] rtc-hym8563 1-0051: rtc core: registered hym8563 as rtc0
> [    1.080313 ] rtc-hym8563 1-0051: setting system clock to 2000-01-01
> 00:02:00 UTC (946684920)

hmm, not setting a false date was actually intentional when I did the driver.

In my mind it is better to shout and keep programs from using wrong values 
than to set some arbitary date and let programs silently use this wrong value.


But I guess we'll let the rtc maintainers decide what is actually the better 
approach.


Heiko

> 
> ---
> 
> Changes in v2:
> Signed-off-by: Xing Zheng <zhengxing@rock-chips.com>
> 
>  drivers/rtc/rtc-hym8563.c |   93
> +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93
> insertions(+)
> 
> diff --git a/drivers/rtc/rtc-hym8563.c b/drivers/rtc/rtc-hym8563.c
> index 097325d..ea37fdf 100644
> --- a/drivers/rtc/rtc-hym8563.c
> +++ b/drivers/rtc/rtc-hym8563.c
> @@ -83,6 +83,8 @@
> 
>  #define HYM8563_TMR_CNT		0x0f
> 
> +#define HYM8563_RTC_SECTION_LEN	0x07
> +
>  struct hym8563 {
>  	struct i2c_client	*client;
>  	struct rtc_device	*rtc;
> @@ -527,9 +529,77 @@ static int hym8563_resume(struct device *dev)
> 
>  static SIMPLE_DEV_PM_OPS(hym8563_pm_ops, hym8563_suspend, hym8563_resume);
> 
> +static int hym8563_set_time(struct i2c_client *client, struct rtc_time *tm)
> +{
> +	u8 regs[HYM8563_RTC_SECTION_LEN] = {0};
> +	u8 mon_day;
> +	int ret = 0;
> +
> +	dev_dbg(&client->dev, "%s -- %4d-%02d-%02d(%d) %02d:%02d:%02d\n",
> __func__, +		1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday, tm-
>tm_wday,
> +		tm->tm_hour, tm->tm_min, tm->tm_sec);
> +
> +	mon_day = rtc_month_days((tm->tm_mon), tm->tm_year + 1900);
> +
> +	if (tm->tm_sec >= 60 || tm->tm_sec < 0)
> +		regs[0x00] = bin2bcd(0x00);
> +	else
> +		regs[0x00] = bin2bcd(tm->tm_sec);
> +
> +	if (tm->tm_min >= 60 || tm->tm_min < 0)
> +		regs[0x01] = bin2bcd(0x00);
> +	else
> +		regs[0x01] = bin2bcd(tm->tm_min);
> +
> +	if (tm->tm_hour >= 24 || tm->tm_hour < 0)
> +		regs[0x02] = bin2bcd(0x00);
> +	else
> +		regs[0x02] = bin2bcd(tm->tm_hour);
> +
> +	if ((tm->tm_mday) > mon_day)
> +		regs[0x03] = bin2bcd(mon_day);
> +	else if ((tm->tm_mday) > 0)
> +		regs[0x03] = bin2bcd(tm->tm_mday);
> +	else if ((tm->tm_mday) <= 0)
> +		regs[0x03] = bin2bcd(0x01);
> +
> +	if (tm->tm_year >= 200)
> +		regs[0x06] = bin2bcd(99);
> +	else if (tm->tm_year >= 100)
> +		regs[0x06] = bin2bcd(tm->tm_year - 100);
> +	else if (tm->tm_year >= 0) {
> +		regs[0x06] = bin2bcd(tm->tm_year);
> +		regs[0x05] |= 0x80;
> +	} else {
> +		regs[0x06] = bin2bcd(0);
> +		regs[0x05] |= 0x80;
> +	}
> +
> +	regs[0x04] = bin2bcd(tm->tm_wday);
> +	regs[0x05] = (regs[0x05] & 0x80) | (bin2bcd(tm->tm_mon + 1) & 0x7F);
> +
> +	ret = i2c_smbus_write_byte_data(client, HYM8563_SEC, *regs);
> +	if (ret < 0) {
> +		dev_err(&client->dev, "%s: error writing i2c data %d\n",
> +			__func__, ret);
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
>  static int hym8563_probe(struct i2c_client *client,
>  			 const struct i2c_device_id *id)
>  {
> +	struct rtc_time tm_read, tm = {
> +		.tm_sec = 0,
> +		.tm_min = 0,
> +		.tm_hour = 12,
> +		.tm_mday = 1,
> +		.tm_mon = 0,
> +		.tm_year = 111,
> +		.tm_wday = 6,
> +	};
>  	struct hym8563 *hym8563;
>  	int ret;
> 
> @@ -562,6 +632,7 @@ static int hym8563_probe(struct i2c_client *client,
> 
>  	/* check state of calendar information */
>  	ret = i2c_smbus_read_byte_data(client, HYM8563_SEC);
> +
>  	if (ret < 0)
>  		return ret;
> 
> @@ -569,6 +640,28 @@ static int hym8563_probe(struct i2c_client *client,
>  	dev_dbg(&client->dev, "rtc information is %s\n",
>  		hym8563->valid ? "valid" : "invalid");
> 
> +	if (!hym8563->valid) {
> +		ret = hym8563_set_time(client, &tm);
> +		if (ret < 0) {
> +			dev_err(&client->dev, "rtc set time failed, %d\n", ret);
> +			return ret;
> +		}
> +
> +		hym8563->valid = true;
> +	}
> +
> +	/* read current time */
> +	ret = hym8563_rtc_read_time(&client->dev, &tm_read);
> +	if (ret < 0) {
> +		dev_err(&client->dev, "rtc read time failed, %d\n", ret);
> +		return ret;
> +	}
> +
> +	dev_dbg(&client->dev, "tm_sec = %d, tm_min = %d, tm_hour = %d,tm_mday =
> %d\n", +		tm_read.tm_sec, tm_read.tm_min, tm_read.tm_hour,
> tm_read.tm_mday); +	dev_dbg(&client->dev, "tm_mon = %d, tm_year = %d,
> tm_wday = %d\n", +		tm_read.tm_mon, tm_read.tm_year, tm_read.tm_wday);
> +
>  	hym8563->rtc = devm_rtc_device_register(&client->dev, client->name,
>  						&hym8563_rtc_ops, THIS_MODULE);
>  	if (IS_ERR(hym8563->rtc))
Alexandre Belloni Sept. 17, 2015, 12:31 p.m. UTC | #2
Hi,

On 17/09/2015 at 14:07:47 +0200, Heiko Stübner wrote :
> Am Donnerstag, 17. September 2015, 18:39:28 schrieb Xing Zheng:
> > The rtc hym8563 maybe failed to register if first startup or rtc
> > powerdown:
> > [    0.988540 ] rtc-hym8563 1-0051: no valid clock/calendar values available
> > [    0.995642 ] rtc-hym8563 1-0051: rtc core: registered hym8563 as rtc0 [ 
> >   1.078985 ] rtc-hym8563 1-0051: no valid clock/calendar values available [
> >    1.085698 ] rtc-hym8563 1-0051: hctosys: unable to read the hardware
> > clock
> > 
> > We can set initial time for rtc and register it:
> > [    0.995678 ] rtc-hym8563 1-0051: rtc core: registered hym8563 as rtc0
> > [    1.080313 ] rtc-hym8563 1-0051: setting system clock to 2000-01-01
> > 00:02:00 UTC (946684920)
> 
> hmm, not setting a false date was actually intentional when I did the driver.
> 
> In my mind it is better to shout and keep programs from using wrong values 
> than to set some arbitary date and let programs silently use this wrong value.
> 

Indeed, I find it worse to set a wrong value instead of returning an
error. Userspace has to define its policy when reading the time fails.
Xing Zheng Sept. 17, 2015, 12:44 p.m. UTC | #3
On 2015年09月17日 20:31, Alexandre Belloni wrote:
> Hi,
>
> On 17/09/2015 at 14:07:47 +0200, Heiko Stübner wrote :
>> Am Donnerstag, 17. September 2015, 18:39:28 schrieb Xing Zheng:
>>> The rtc hym8563 maybe failed to register if first startup or rtc
>>> powerdown:
>>> [    0.988540 ] rtc-hym8563 1-0051: no valid clock/calendar values available
>>> [    0.995642 ] rtc-hym8563 1-0051: rtc core: registered hym8563 as rtc0 [
>>>    1.078985 ] rtc-hym8563 1-0051: no valid clock/calendar values available [
>>>     1.085698 ] rtc-hym8563 1-0051: hctosys: unable to read the hardware
>>> clock
>>>
>>> We can set initial time for rtc and register it:
>>> [    0.995678 ] rtc-hym8563 1-0051: rtc core: registered hym8563 as rtc0
>>> [    1.080313 ] rtc-hym8563 1-0051: setting system clock to 2000-01-01
>>> 00:02:00 UTC (946684920)
>> hmm, not setting a false date was actually intentional when I did the driver.
>>
>> In my mind it is better to shout and keep programs from using wrong values
>> than to set some arbitary date and let programs silently use this wrong value.
>>
> Indeed, I find it worse to set a wrong value instead of returning an
> error. Userspace has to define its policy when reading the time fails.
>
OK, I got it, this patch will be abandoned at next version.
Thanks.
diff mbox

Patch

diff --git a/drivers/rtc/rtc-hym8563.c b/drivers/rtc/rtc-hym8563.c
index 097325d..ea37fdf 100644
--- a/drivers/rtc/rtc-hym8563.c
+++ b/drivers/rtc/rtc-hym8563.c
@@ -83,6 +83,8 @@ 
 
 #define HYM8563_TMR_CNT		0x0f
 
+#define HYM8563_RTC_SECTION_LEN	0x07
+
 struct hym8563 {
 	struct i2c_client	*client;
 	struct rtc_device	*rtc;
@@ -527,9 +529,77 @@  static int hym8563_resume(struct device *dev)
 
 static SIMPLE_DEV_PM_OPS(hym8563_pm_ops, hym8563_suspend, hym8563_resume);
 
+static int hym8563_set_time(struct i2c_client *client, struct rtc_time *tm)
+{
+	u8 regs[HYM8563_RTC_SECTION_LEN] = {0};
+	u8 mon_day;
+	int ret = 0;
+
+	dev_dbg(&client->dev, "%s -- %4d-%02d-%02d(%d) %02d:%02d:%02d\n", __func__,
+		1900 + tm->tm_year, tm->tm_mon + 1, tm->tm_mday, tm->tm_wday,
+		tm->tm_hour, tm->tm_min, tm->tm_sec);
+
+	mon_day = rtc_month_days((tm->tm_mon), tm->tm_year + 1900);
+
+	if (tm->tm_sec >= 60 || tm->tm_sec < 0)
+		regs[0x00] = bin2bcd(0x00);
+	else
+		regs[0x00] = bin2bcd(tm->tm_sec);
+
+	if (tm->tm_min >= 60 || tm->tm_min < 0)
+		regs[0x01] = bin2bcd(0x00);
+	else
+		regs[0x01] = bin2bcd(tm->tm_min);
+
+	if (tm->tm_hour >= 24 || tm->tm_hour < 0)
+		regs[0x02] = bin2bcd(0x00);
+	else
+		regs[0x02] = bin2bcd(tm->tm_hour);
+
+	if ((tm->tm_mday) > mon_day)
+		regs[0x03] = bin2bcd(mon_day);
+	else if ((tm->tm_mday) > 0)
+		regs[0x03] = bin2bcd(tm->tm_mday);
+	else if ((tm->tm_mday) <= 0)
+		regs[0x03] = bin2bcd(0x01);
+
+	if (tm->tm_year >= 200)
+		regs[0x06] = bin2bcd(99);
+	else if (tm->tm_year >= 100)
+		regs[0x06] = bin2bcd(tm->tm_year - 100);
+	else if (tm->tm_year >= 0) {
+		regs[0x06] = bin2bcd(tm->tm_year);
+		regs[0x05] |= 0x80;
+	} else {
+		regs[0x06] = bin2bcd(0);
+		regs[0x05] |= 0x80;
+	}
+
+	regs[0x04] = bin2bcd(tm->tm_wday);
+	regs[0x05] = (regs[0x05] & 0x80) | (bin2bcd(tm->tm_mon + 1) & 0x7F);
+
+	ret = i2c_smbus_write_byte_data(client, HYM8563_SEC, *regs);
+	if (ret < 0) {
+		dev_err(&client->dev, "%s: error writing i2c data %d\n",
+			__func__, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
 static int hym8563_probe(struct i2c_client *client,
 			 const struct i2c_device_id *id)
 {
+	struct rtc_time tm_read, tm = {
+		.tm_sec = 0,
+		.tm_min = 0,
+		.tm_hour = 12,
+		.tm_mday = 1,
+		.tm_mon = 0,
+		.tm_year = 111,
+		.tm_wday = 6,
+	};
 	struct hym8563 *hym8563;
 	int ret;
 
@@ -562,6 +632,7 @@  static int hym8563_probe(struct i2c_client *client,
 
 	/* check state of calendar information */
 	ret = i2c_smbus_read_byte_data(client, HYM8563_SEC);
+
 	if (ret < 0)
 		return ret;
 
@@ -569,6 +640,28 @@  static int hym8563_probe(struct i2c_client *client,
 	dev_dbg(&client->dev, "rtc information is %s\n",
 		hym8563->valid ? "valid" : "invalid");
 
+	if (!hym8563->valid) {
+		ret = hym8563_set_time(client, &tm);
+		if (ret < 0) {
+			dev_err(&client->dev, "rtc set time failed, %d\n", ret);
+			return ret;
+		}
+
+		hym8563->valid = true;
+	}
+
+	/* read current time */
+	ret = hym8563_rtc_read_time(&client->dev, &tm_read);
+	if (ret < 0) {
+		dev_err(&client->dev, "rtc read time failed, %d\n", ret);
+		return ret;
+	}
+
+	dev_dbg(&client->dev, "tm_sec = %d, tm_min = %d, tm_hour = %d,tm_mday = %d\n",
+		tm_read.tm_sec, tm_read.tm_min, tm_read.tm_hour, tm_read.tm_mday);
+	dev_dbg(&client->dev, "tm_mon = %d, tm_year = %d, tm_wday = %d\n",
+		tm_read.tm_mon, tm_read.tm_year, tm_read.tm_wday);
+
 	hym8563->rtc = devm_rtc_device_register(&client->dev, client->name,
 						&hym8563_rtc_ops, THIS_MODULE);
 	if (IS_ERR(hym8563->rtc))