diff --git a/drivers/rtc/rtc-s35390a.c b/drivers/rtc/rtc-s35390a.c index 575bb256eb25..12ed504db94d 100644 --- a/drivers/rtc/rtc-s35390a.c +++ b/drivers/rtc/rtc-s35390a.c @@ -64,7 +64,6 @@ MODULE_DEVICE_TABLE(of, s35390a_of_match); struct s35390a { struct i2c_client *client[8]; - int twentyfourhour; }; static int s35390a_set_reg(struct s35390a *s35390a, int reg, u8 *buf, int len) @@ -102,9 +101,8 @@ static int s35390a_get_reg(struct s35390a *s35390a, int reg, u8 *buf, int len) return 0; } -static int s35390a_init(struct s35390a *s35390a) +static int s35390a_init(struct s35390a *s35390a, u8 *sts) { - u8 buf; int ret; unsigned initcount = 0; @@ -117,17 +115,17 @@ static int s35390a_init(struct s35390a *s35390a) * The 24H bit is kept over reset, so set it already here. */ initialize: - buf = S35390A_FLAG_RESET | S35390A_FLAG_24H; - ret = s35390a_set_reg(s35390a, S35390A_CMD_STATUS1, &buf, 1); + *sts = S35390A_FLAG_RESET | S35390A_FLAG_24H; + ret = s35390a_set_reg(s35390a, S35390A_CMD_STATUS1, sts, 1); if (ret < 0) return ret; - ret = s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, &buf, 1); + ret = s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, sts, 1); if (ret < 0) return ret; - if (buf & (S35390A_FLAG_POC | S35390A_FLAG_BLD)) { + if (*sts & (S35390A_FLAG_POC | S35390A_FLAG_BLD)) { /* Try up to five times to reset the chip */ if (initcount < 5) { ++initcount; @@ -181,9 +179,9 @@ static int s35390a_disable_test_mode(struct s35390a *s35390a) return s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, buf, sizeof(buf)); } -static char s35390a_hr2reg(struct s35390a *s35390a, int hour) +static char s35390a_hr2reg(int hour, bool twentyfourhour) { - if (s35390a->twentyfourhour) + if (twentyfourhour) return bin2bcd(hour); if (hour < 12) @@ -192,11 +190,11 @@ static char s35390a_hr2reg(struct s35390a *s35390a, int hour) return 0x40 | bin2bcd(hour - 12); } -static int s35390a_reg2hr(struct s35390a *s35390a, char reg) +static int s35390a_reg2hr(char reg, bool twentyfourhour) { unsigned hour; - if (s35390a->twentyfourhour) + if (twentyfourhour) return bcd2bin(reg & 0x3f); hour = bcd2bin(reg & 0x3f); @@ -210,7 +208,7 @@ static int s35390a_rtc_set_time(struct device *dev, struct rtc_time *tm) { struct i2c_client *client = to_i2c_client(dev); struct s35390a *s35390a = i2c_get_clientdata(client); - int i; + int i, err; u8 buf[7], status; dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d mday=%d, " @@ -218,14 +216,18 @@ static int s35390a_rtc_set_time(struct device *dev, struct rtc_time *tm) tm->tm_min, tm->tm_hour, tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); - if (s35390a_read_status(s35390a, &status) == 1) - s35390a_init(s35390a); + err = s35390a_read_status(s35390a, &status); + if (err == 1) + err = s35390a_init(s35390a, &status); + + if (err < 0) + return err; buf[S35390A_BYTE_YEAR] = bin2bcd(tm->tm_year - 100); buf[S35390A_BYTE_MONTH] = bin2bcd(tm->tm_mon + 1); buf[S35390A_BYTE_DAY] = bin2bcd(tm->tm_mday); buf[S35390A_BYTE_WDAY] = bin2bcd(tm->tm_wday); - buf[S35390A_BYTE_HOURS] = s35390a_hr2reg(s35390a, tm->tm_hour); + buf[S35390A_BYTE_HOURS] = s35390a_hr2reg(tm->tm_hour, status & S35390A_FLAG_24H); buf[S35390A_BYTE_MINS] = bin2bcd(tm->tm_min); buf[S35390A_BYTE_SECS] = bin2bcd(tm->tm_sec); @@ -243,8 +245,11 @@ static int s35390a_rtc_read_time(struct device *dev, struct rtc_time *tm) u8 buf[7], status; int i, err; - if (s35390a_read_status(s35390a, &status) == 1) + err = s35390a_read_status(s35390a, &status); + if (err == 1) return -EINVAL; + if (err < 0) + return err; err = s35390a_get_reg(s35390a, S35390A_CMD_TIME1, buf, sizeof(buf)); if (err < 0) @@ -256,7 +261,7 @@ static int s35390a_rtc_read_time(struct device *dev, struct rtc_time *tm) tm->tm_sec = bcd2bin(buf[S35390A_BYTE_SECS]); tm->tm_min = bcd2bin(buf[S35390A_BYTE_MINS]); - tm->tm_hour = s35390a_reg2hr(s35390a, buf[S35390A_BYTE_HOURS]); + tm->tm_hour = s35390a_reg2hr(buf[S35390A_BYTE_HOURS], status & S35390A_FLAG_24H); tm->tm_wday = bcd2bin(buf[S35390A_BYTE_WDAY]); tm->tm_mday = bcd2bin(buf[S35390A_BYTE_DAY]); tm->tm_mon = bcd2bin(buf[S35390A_BYTE_MONTH]) - 1; @@ -292,7 +297,7 @@ static int s35390a_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) { struct i2c_client *client = to_i2c_client(dev); struct s35390a *s35390a = i2c_get_clientdata(client); - u8 buf[3], sts = 0; + u8 buf[3], status1, status2 = 0; int err, i; dev_dbg(&client->dev, "%s: alm is secs=%d, mins=%d, hours=%d mday=%d, "\ @@ -301,22 +306,22 @@ static int s35390a_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) alm->time.tm_mon, alm->time.tm_year, alm->time.tm_wday); /* disable interrupt (which deasserts the irq line) */ - err = s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, &sts, sizeof(sts)); + err = s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, &status2, sizeof(status2)); if (err < 0) return err; /* clear pending interrupt (in STATUS1 only), if any */ - err = s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, &sts, sizeof(sts)); + err = s35390a_get_reg(s35390a, S35390A_CMD_STATUS1, &status1, sizeof(status1)); if (err < 0) return err; if (alm->enabled) - sts = S35390A_INT2_MODE_ALARM; + status2 = S35390A_INT2_MODE_ALARM; else - sts = S35390A_INT2_MODE_NOINTR; + status2 = S35390A_INT2_MODE_NOINTR; /* set interrupt mode*/ - err = s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, &sts, sizeof(sts)); + err = s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, &status2, sizeof(status2)); if (err < 0) return err; @@ -325,8 +330,8 @@ static int s35390a_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) else buf[S35390A_ALRM_BYTE_WDAY] = 0; - buf[S35390A_ALRM_BYTE_HOURS] = s35390a_hr2reg(s35390a, - alm->time.tm_hour) | 0x80; + buf[S35390A_ALRM_BYTE_HOURS] = s35390a_hr2reg(alm->time.tm_hour, + status1 & S35390A_FLAG_24H) | 0x80; buf[S35390A_ALRM_BYTE_MINS] = bin2bcd(alm->time.tm_min) | 0x80; if (alm->time.tm_hour >= 12) @@ -345,14 +350,20 @@ static int s35390a_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) { struct i2c_client *client = to_i2c_client(dev); struct s35390a *s35390a = i2c_get_clientdata(client); - u8 buf[3], sts; + u8 buf[3], status1, status2; int i, err; - err = s35390a_get_reg(s35390a, S35390A_CMD_STATUS2, &sts, sizeof(sts)); + err = s35390a_read_status(s35390a, &status1); + if (err == 1) + return -EINVAL; if (err < 0) return err; - if ((sts & S35390A_INT2_MODE_MASK) != S35390A_INT2_MODE_ALARM) { + err = s35390a_get_reg(s35390a, S35390A_CMD_STATUS2, &status2, sizeof(status2)); + if (err < 0) + return err; + + if ((status2 & S35390A_INT2_MODE_MASK) != S35390A_INT2_MODE_ALARM) { /* * When the alarm isn't enabled, the register to configure * the alarm time isn't accessible. @@ -381,8 +392,8 @@ static int s35390a_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) if (buf[S35390A_ALRM_BYTE_HOURS] & 0x80) alm->time.tm_hour = - s35390a_reg2hr(s35390a, - buf[S35390A_ALRM_BYTE_HOURS] & ~0x80); + s35390a_reg2hr(buf[S35390A_ALRM_BYTE_HOURS] & ~0x80, + status1 & S35390A_FLAG_24H); if (buf[S35390A_ALRM_BYTE_MINS] & 0x80) alm->time.tm_min = bcd2bin(buf[S35390A_ALRM_BYTE_MINS] & ~0x80); @@ -416,7 +427,7 @@ static int s35390a_rtc_ioctl(struct device *dev, unsigned int cmd, break; case RTC_VL_CLR: /* update flag and clear register */ - err = s35390a_init(s35390a); + err = s35390a_init(s35390a, &sts); if (err < 0) return err; break; @@ -503,11 +514,6 @@ static int s35390a_probe(struct i2c_client *client) return err_read; } - if (status1 & S35390A_FLAG_24H) - s35390a->twentyfourhour = 1; - else - s35390a->twentyfourhour = 0; - if (status1 & S35390A_FLAG_INT2) { /* disable alarm (and maybe test mode) */ buf = 0;