diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-11-22 20:58:23 -1000 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-11-22 20:58:23 -1000 |
commit | 1b8c5cd890e274781a8ef61585ae03614be9ccd8 (patch) | |
tree | cf8a6735bd8970f311daee3c6874a4fdc7de0356 /drivers/rtc/rtc-pcf8523.c | |
parent | 14b661ebb6cfa386afa5a5247eb09e24d420af3a (diff) | |
parent | 87c9fd81825363237ac5560822e2261535800597 (diff) |
Merge tag 'rtc-4.15' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux
Pull RTC updates from Alexandre Belloni:
"There is nothing scary this cycle, mostly driver fixes and updates.
The core fix has been in for a while and has been tested on multiple
kernel revisions by multiple teams.
Core:
- Fix setting the alarm to the next expiring timer
New drivers:
- Mediatek MT7622 RTC
- NXP PCF85363
- Spreadtrum SC27xx PMIC RTC
Drivers updates:
- Use generic nvmem to expose the Non volatile ram for ds1305,
ds1511, m48t86 and omap
- abx80x: solve possible race condition at probe
- armada38x: support trimming the RTC oscillator
- at91rm9200: fix reading the alarm value at boot
- ds1511: allow waking platform
- m41t80: rework square wave output
- pcf8523: support trimming the RTC oscillator
- pcf8563: fix clock output rate
- pl031: make interrupt optional
- xgene: fix suspend/resume"
* tag 'rtc-4.15' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux: (50 commits)
dt-bindings: rtc: imxdi: Improve the bindings text
rtc: sc27xx: Add Spreadtrum SC27xx PMIC RTC driver
dt-bindings: rtc: Add Spreadtrum SC27xx RTC documentation
rtc: at91rm9200: fix reading alarm value
rtc: at91rm9200: stop calculating yday in at91_rtc_readalarm
rtc: sysfs: Use time64_t variables to set time/alarm
rtc: xgene: mark PM functions as __maybe_unused
rtc: xgene: Fix suspend/resume
rtc: pcf8563: don't alway enable the alarm
rtc: pcf8563: fix output clock rate
rtc: rx8010: Fix for incorrect return value
rtc: rx8010: Specify correct address for RX8010_RESV31
rtc: rx8010: Remove duplicate define
rtc: m41t80: remove unneeded checks from m41t80_sqw_set_rate
rtc: m41t80: avoid i2c read in m41t80_sqw_is_prepared
rtc: m41t80: avoid i2c read in m41t80_sqw_recalc_rate
rtc: m41t80: fix m41t80_sqw_round_rate return value
rtc: m41t80: m41t80_sqw_set_rate should return 0 on success
rtc: add support for NXP PCF85363 real-time clock
rtc: omap: Support scratch registers
...
Diffstat (limited to 'drivers/rtc/rtc-pcf8523.c')
-rw-r--r-- | drivers/rtc/rtc-pcf8523.c | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/drivers/rtc/rtc-pcf8523.c b/drivers/rtc/rtc-pcf8523.c index 28c48b3c1946..c312af0db729 100644 --- a/drivers/rtc/rtc-pcf8523.c +++ b/drivers/rtc/rtc-pcf8523.c @@ -35,6 +35,9 @@ #define REG_MONTHS 0x08 #define REG_YEARS 0x09 +#define REG_OFFSET 0x0e +#define REG_OFFSET_MODE BIT(7) + struct pcf8523 { struct rtc_device *rtc; }; @@ -272,10 +275,47 @@ static int pcf8523_rtc_ioctl(struct device *dev, unsigned int cmd, #define pcf8523_rtc_ioctl NULL #endif +static int pcf8523_rtc_read_offset(struct device *dev, long *offset) +{ + struct i2c_client *client = to_i2c_client(dev); + int err; + u8 value; + s8 val; + + err = pcf8523_read(client, REG_OFFSET, &value); + if (err < 0) + return err; + + /* sign extend the 7-bit offset value */ + val = value << 1; + *offset = (value & REG_OFFSET_MODE ? 4069 : 4340) * (val >> 1); + + return 0; +} + +static int pcf8523_rtc_set_offset(struct device *dev, long offset) +{ + struct i2c_client *client = to_i2c_client(dev); + long reg_m0, reg_m1; + u8 value; + + reg_m0 = clamp(DIV_ROUND_CLOSEST(offset, 4340), -64L, 63L); + reg_m1 = clamp(DIV_ROUND_CLOSEST(offset, 4069), -64L, 63L); + + if (abs(reg_m0 * 4340 - offset) < abs(reg_m1 * 4069 - offset)) + value = reg_m0 & 0x7f; + else + value = (reg_m1 & 0x7f) | REG_OFFSET_MODE; + + return pcf8523_write(client, REG_OFFSET, value); +} + static const struct rtc_class_ops pcf8523_rtc_ops = { .read_time = pcf8523_rtc_read_time, .set_time = pcf8523_rtc_set_time, .ioctl = pcf8523_rtc_ioctl, + .read_offset = pcf8523_rtc_read_offset, + .set_offset = pcf8523_rtc_set_offset, }; static int pcf8523_probe(struct i2c_client *client, |