diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-03-08 09:54:55 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-03-08 09:54:55 -0800 |
commit | f8d35403ebf5a6cce6a2347015f465a4da470f7b (patch) | |
tree | 6fd0b4dd87df0ef933febac578c25cac438be15d /drivers/rtc/rtc-rs5c372.c | |
parent | 9f24a81e2e5daf8820c8654afcd8512e797c41f2 (diff) | |
parent | e91b94fd2bc411b5926031496bbc3de9a96bb1c6 (diff) | |
download | linux-f8d35403ebf5a6cce6a2347015f465a4da470f7b.tar.bz2 |
Merge tag 'rtc-5.1' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux
Pull RTC updates from Alexandre Belloni:
"There is an unusual amount of new drivers this cycle, and this
explains the number of insertions.
Other than that, the changes are the usual fixes and feature addition.
Subsystem updates:
- new quartz-load-femtofarads DT property for quartz load capacitance
- remove rtc_class_ops.read_callback
New drivers:
- Abracon AB-RTCMC-32.768kHz-EOZ9
- Amlogic Meson RTC
- Cadence RTC IP
- Microcrystal RV3028
- Whwave sd3078
Driver updates:
- cmos: ignore bogus century byte
- ds1307: rework rx8130 support
- isl1208: add isl1209 support, nvmem support
- rs5C372: report invalid time when the oscillator stopped
- rx8581: add rx8571 support"
* tag 'rtc-5.1' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux: (66 commits)
rtc: pic32: convert to SPDX identifier
rtc: pic32: let the core handle range
rtc: pic32: convert to devm_rtc_allocate_device
rtc: update my email address
rtc: rv8803: convert to SPDX identifier
rtc: rv8803: let the core handle range
rtc: tx4939: convert to SPDX identifier
rtc: tx4939: use .set_time
rtc: tx4939: switch to rtc_time64_to_tm/rtc_tm_to_time64
rtc: tx4939: set range
rtc: tx4939: remove useless test
rtc: zynqmp: let the core handle range
rtc: zynqmp: fix possible race condition
rtc: imx-sc: use rtc_time64_to_tm
rtc: rx8581: Add support for Epson rx8571 RTC
dt-bindings: rtc: add rx8571 compatible
rtc: pcf85063: remove dead code
rtc: remove rtc_class_ops.read_callback
rtc: add AB-RTCMC-32.768kHz-EOZ9 RTC support
dt-bindings: rtc: add ABEOZ9
...
Diffstat (limited to 'drivers/rtc/rtc-rs5c372.c')
-rw-r--r-- | drivers/rtc/rtc-rs5c372.c | 76 |
1 files changed, 63 insertions, 13 deletions
diff --git a/drivers/rtc/rtc-rs5c372.c b/drivers/rtc/rtc-rs5c372.c index c5038329058c..66a473a3c3fe 100644 --- a/drivers/rtc/rtc-rs5c372.c +++ b/drivers/rtc/rtc-rs5c372.c @@ -52,8 +52,10 @@ # define RS5C_CTRL1_CT4 (4 << 0) /* 1 Hz level irq */ #define RS5C_REG_CTRL2 15 # define RS5C372_CTRL2_24 (1 << 5) -# define R2025_CTRL2_XST (1 << 5) -# define RS5C_CTRL2_XSTP (1 << 4) /* only if !R2025S/D */ +# define RS5C_CTRL2_XSTP (1 << 4) /* only if !R2x2x */ +# define R2x2x_CTRL2_VDET (1 << 6) /* only if R2x2x */ +# define R2x2x_CTRL2_XSTP (1 << 5) /* only if R2x2x */ +# define R2x2x_CTRL2_PON (1 << 4) /* only if R2x2x */ # define RS5C_CTRL2_CTFG (1 << 2) # define RS5C_CTRL2_AAFG (1 << 1) /* or WAFG */ # define RS5C_CTRL2_BAFG (1 << 0) /* or DAFG */ @@ -212,10 +214,27 @@ static int rs5c372_rtc_read_time(struct device *dev, struct rtc_time *tm) struct i2c_client *client = to_i2c_client(dev); struct rs5c372 *rs5c = i2c_get_clientdata(client); int status = rs5c_get_regs(rs5c); + unsigned char ctrl2 = rs5c->regs[RS5C_REG_CTRL2]; if (status < 0) return status; + switch (rs5c->type) { + case rtc_r2025sd: + case rtc_r2221tl: + if ((rs5c->type == rtc_r2025sd && !(ctrl2 & R2x2x_CTRL2_XSTP)) || + (rs5c->type == rtc_r2221tl && (ctrl2 & R2x2x_CTRL2_XSTP))) { + dev_warn(&client->dev, "rtc oscillator interruption detected. Please reset the rtc clock.\n"); + return -EINVAL; + } + break; + default: + if (ctrl2 & RS5C_CTRL2_XSTP) { + dev_warn(&client->dev, "rtc oscillator interruption detected. Please reset the rtc clock.\n"); + return -EINVAL; + } + } + tm->tm_sec = bcd2bin(rs5c->regs[RS5C372_REG_SECS] & 0x7f); tm->tm_min = bcd2bin(rs5c->regs[RS5C372_REG_MINS] & 0x7f); tm->tm_hour = rs5c_reg2hr(rs5c, rs5c->regs[RS5C372_REG_HOURS]); @@ -243,6 +262,7 @@ static int rs5c372_rtc_set_time(struct device *dev, struct rtc_time *tm) struct i2c_client *client = to_i2c_client(dev); struct rs5c372 *rs5c = i2c_get_clientdata(client); unsigned char buf[7]; + unsigned char ctrl2; int addr; dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d " @@ -261,7 +281,32 @@ static int rs5c372_rtc_set_time(struct device *dev, struct rtc_time *tm) buf[6] = bin2bcd(tm->tm_year - 100); if (i2c_smbus_write_i2c_block_data(client, addr, sizeof(buf), buf) < 0) { - dev_err(&client->dev, "%s: write error\n", __func__); + dev_dbg(&client->dev, "%s: write error in line %i\n", + __func__, __LINE__); + return -EIO; + } + + addr = RS5C_ADDR(RS5C_REG_CTRL2); + ctrl2 = i2c_smbus_read_byte_data(client, addr); + + /* clear rtc warning bits */ + switch (rs5c->type) { + case rtc_r2025sd: + case rtc_r2221tl: + ctrl2 &= ~(R2x2x_CTRL2_VDET | R2x2x_CTRL2_PON); + if (rs5c->type == rtc_r2025sd) + ctrl2 |= R2x2x_CTRL2_XSTP; + else + ctrl2 &= ~R2x2x_CTRL2_XSTP; + break; + default: + ctrl2 &= ~RS5C_CTRL2_XSTP; + break; + } + + if (i2c_smbus_write_byte_data(client, addr, ctrl2) < 0) { + dev_dbg(&client->dev, "%s: write error in line %i\n", + __func__, __LINE__); return -EIO; } @@ -519,20 +564,25 @@ static int rs5c_oscillator_setup(struct rs5c372 *rs5c372) unsigned char buf[2]; int addr, i, ret = 0; - if (rs5c372->type == rtc_r2025sd) { - if (rs5c372->regs[RS5C_REG_CTRL2] & R2025_CTRL2_XST) - return ret; - rs5c372->regs[RS5C_REG_CTRL2] |= R2025_CTRL2_XST; - } else { - if (!(rs5c372->regs[RS5C_REG_CTRL2] & RS5C_CTRL2_XSTP)) - return ret; - rs5c372->regs[RS5C_REG_CTRL2] &= ~RS5C_CTRL2_XSTP; - } - addr = RS5C_ADDR(RS5C_REG_CTRL1); buf[0] = rs5c372->regs[RS5C_REG_CTRL1]; buf[1] = rs5c372->regs[RS5C_REG_CTRL2]; + switch (rs5c372->type) { + case rtc_r2025sd: + if (buf[1] & R2x2x_CTRL2_XSTP) + return ret; + break; + case rtc_r2221tl: + if (!(buf[1] & R2x2x_CTRL2_XSTP)) + return ret; + break; + default: + if (!(buf[1] & RS5C_CTRL2_XSTP)) + return ret; + break; + } + /* use 24hr mode */ switch (rs5c372->type) { case rtc_rs5c372a: |