diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-07-17 20:03:50 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-07-17 20:03:50 +0300 |
commit | edafb6fe42cfa98f4abf8c63acc5f4db011ed7b9 (patch) | |
tree | 2865672fc0ece89d303e70ff5e5f17a99452a4f1 /drivers | |
parent | 47ebe00b684c2bc183a766bc33c8b5943bc0df85 (diff) | |
parent | f0162d21cc8025c828fafe56ee25801f770f41da (diff) | |
download | linux-edafb6fe42cfa98f4abf8c63acc5f4db011ed7b9.tar.xz |
Merge tag 'rtc-5.3' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux
Pull RTC updates from Alexandre Belloni:
"A quiet cycle this time.
- ds1307: properly handle oscillator failure flags
- imx-sc: alarm support
- pcf2123: alarm support, correct offset handling
- sun6i: add R40 support
- simplify getting the adapter of an i2c client"
* tag 'rtc-5.3' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux: (37 commits)
rtc: wm831x: Add IRQF_ONESHOT flag
rtc: stm32: remove one condition check in stm32_rtc_set_alarm()
rtc: pcf2123: Fix build error
rtc: interface: Change type of 'count' from int to u64
rtc: pcf8563: Clear event flags and disable interrupts before requesting irq
rtc: pcf8563: Fix interrupt trigger method
rtc: pcf2123: fix negative offset rounding
rtc: pcf2123: add alarm support
rtc: pcf2123: use %ptR
rtc: pcf2123: port to regmap
rtc: pcf2123: remove sysfs register view
rtc: rx8025: simplify getting the adapter of a client
rtc: rx8010: simplify getting the adapter of a client
rtc: rv8803: simplify getting the adapter of a client
rtc: m41t80: simplify getting the adapter of a client
rtc: fm3130: simplify getting the adapter of a client
rtc: tegra: Drop MODULE_ALIAS
rtc: sun6i: Add R40 compatible
dt-bindings: rtc: sun6i: Add the R40 RTC compatible
dt-bindings: rtc: Convert Allwinner A31 RTC to a schema
...
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/rtc/Kconfig | 3 | ||||
-rw-r--r-- | drivers/rtc/interface.c | 2 | ||||
-rw-r--r-- | drivers/rtc/rtc-ds1307.c | 129 | ||||
-rw-r--r-- | drivers/rtc/rtc-ds2404.c | 5 | ||||
-rw-r--r-- | drivers/rtc/rtc-fm3130.c | 8 | ||||
-rw-r--r-- | drivers/rtc/rtc-imx-sc.c | 87 | ||||
-rw-r--r-- | drivers/rtc/rtc-m41t80.c | 2 | ||||
-rw-r--r-- | drivers/rtc/rtc-pcf2123.c | 354 | ||||
-rw-r--r-- | drivers/rtc/rtc-pcf8563.c | 13 | ||||
-rw-r--r-- | drivers/rtc/rtc-rv8803.c | 2 | ||||
-rw-r--r-- | drivers/rtc/rtc-rx8010.c | 2 | ||||
-rw-r--r-- | drivers/rtc/rtc-rx8025.c | 2 | ||||
-rw-r--r-- | drivers/rtc/rtc-s35390a.c | 55 | ||||
-rw-r--r-- | drivers/rtc/rtc-st-lpc.c | 4 | ||||
-rw-r--r-- | drivers/rtc/rtc-stm32.c | 6 | ||||
-rw-r--r-- | drivers/rtc/rtc-sun6i.c | 1 | ||||
-rw-r--r-- | drivers/rtc/rtc-tegra.c | 253 | ||||
-rw-r--r-- | drivers/rtc/rtc-test.c | 1 | ||||
-rw-r--r-- | drivers/rtc/rtc-tps65910.c | 2 | ||||
-rw-r--r-- | drivers/rtc/rtc-wm831x.c | 3 |
20 files changed, 501 insertions, 433 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 3254a30ebb1b..e72f65b61176 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -562,7 +562,7 @@ config RTC_DRV_TPS6586X config RTC_DRV_TPS65910 tristate "TI TPS65910 RTC driver" - depends on RTC_CLASS && MFD_TPS65910 + depends on MFD_TPS65910 help If you say yes here you get support for the RTC on the TPS65910 chips. @@ -820,6 +820,7 @@ config RTC_DRV_MAX6902 config RTC_DRV_PCF2123 tristate "NXP PCF2123" + select REGMAP_SPI help If you say yes here you get support for the NXP PCF2123 RTC chip. diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 4124f4dd376b..72b7ddc43116 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -633,7 +633,7 @@ enum hrtimer_restart rtc_pie_update_irq(struct hrtimer *timer) { struct rtc_device *rtc; ktime_t period; - int count; + u64 count; rtc = container_of(timer, struct rtc_device, pie_timer); diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c index 93d338e7732b..1f7e8aefc1eb 100644 --- a/drivers/rtc/rtc-ds1307.c +++ b/drivers/rtc/rtc-ds1307.c @@ -222,6 +222,45 @@ static int ds1307_get_time(struct device *dev, struct rtc_time *t) return -EINVAL; } + tmp = regs[DS1307_REG_SECS]; + switch (ds1307->type) { + case ds_1307: + case m41t0: + case m41t00: + case m41t11: + if (tmp & DS1307_BIT_CH) + return -EINVAL; + break; + case ds_1308: + case ds_1338: + if (tmp & DS1307_BIT_CH) + return -EINVAL; + + ret = regmap_read(ds1307->regmap, DS1307_REG_CONTROL, &tmp); + if (ret) + return ret; + if (tmp & DS1338_BIT_OSF) + return -EINVAL; + break; + case ds_1340: + if (tmp & DS1340_BIT_nEOSC) + return -EINVAL; + + ret = regmap_read(ds1307->regmap, DS1340_REG_FLAG, &tmp); + if (ret) + return ret; + if (tmp & DS1340_BIT_OSF) + return -EINVAL; + break; + case mcp794xx: + if (!(tmp & MCP794XX_BIT_ST)) + return -EINVAL; + + break; + default: + break; + } + t->tm_sec = bcd2bin(regs[DS1307_REG_SECS] & 0x7f); t->tm_min = bcd2bin(regs[DS1307_REG_MIN] & 0x7f); tmp = regs[DS1307_REG_HOUR] & 0x3f; @@ -286,7 +325,17 @@ static int ds1307_set_time(struct device *dev, struct rtc_time *t) if (t->tm_year > 199 && chip->century_bit) regs[chip->century_reg] |= chip->century_bit; - if (ds1307->type == mcp794xx) { + switch (ds1307->type) { + case ds_1308: + case ds_1338: + regmap_update_bits(ds1307->regmap, DS1307_REG_CONTROL, + DS1338_BIT_OSF, 0); + break; + case ds_1340: + regmap_update_bits(ds1307->regmap, DS1340_REG_FLAG, + DS1340_BIT_OSF, 0); + break; + case mcp794xx: /* * these bits were cleared when preparing the date/time * values and need to be set again before writing the @@ -294,6 +343,9 @@ static int ds1307_set_time(struct device *dev, struct rtc_time *t) */ regs[DS1307_REG_SECS] |= MCP794XX_BIT_ST; regs[DS1307_REG_WDAY] |= MCP794XX_BIT_VBATEN; + break; + default: + break; } dev_dbg(dev, "%s: %7ph\n", "write", regs); @@ -1702,7 +1754,6 @@ static int ds1307_probe(struct i2c_client *client, break; } -read_rtc: /* read RTC registers */ err = regmap_bulk_read(ds1307->regmap, chip->offset, regs, sizeof(regs)); @@ -1711,75 +1762,11 @@ read_rtc: goto exit; } - /* - * minimal sanity checking; some chips (like DS1340) don't - * specify the extra bits as must-be-zero, but there are - * still a few values that are clearly out-of-range. - */ - tmp = regs[DS1307_REG_SECS]; - switch (ds1307->type) { - case ds_1307: - case m41t0: - case m41t00: - case m41t11: - /* clock halted? turn it on, so clock can tick. */ - if (tmp & DS1307_BIT_CH) { - regmap_write(ds1307->regmap, DS1307_REG_SECS, 0); - dev_warn(ds1307->dev, "SET TIME!\n"); - goto read_rtc; - } - break; - case ds_1308: - case ds_1338: - /* clock halted? turn it on, so clock can tick. */ - if (tmp & DS1307_BIT_CH) - regmap_write(ds1307->regmap, DS1307_REG_SECS, 0); - - /* oscillator fault? clear flag, and warn */ - if (regs[DS1307_REG_CONTROL] & DS1338_BIT_OSF) { - regmap_write(ds1307->regmap, DS1307_REG_CONTROL, - regs[DS1307_REG_CONTROL] & - ~DS1338_BIT_OSF); - dev_warn(ds1307->dev, "SET TIME!\n"); - goto read_rtc; - } - break; - case ds_1340: - /* clock halted? turn it on, so clock can tick. */ - if (tmp & DS1340_BIT_nEOSC) - regmap_write(ds1307->regmap, DS1307_REG_SECS, 0); - - err = regmap_read(ds1307->regmap, DS1340_REG_FLAG, &tmp); - if (err) { - dev_dbg(ds1307->dev, "read error %d\n", err); - goto exit; - } - - /* oscillator fault? clear flag, and warn */ - if (tmp & DS1340_BIT_OSF) { - regmap_write(ds1307->regmap, DS1340_REG_FLAG, 0); - dev_warn(ds1307->dev, "SET TIME!\n"); - } - break; - case mcp794xx: - /* make sure that the backup battery is enabled */ - if (!(regs[DS1307_REG_WDAY] & MCP794XX_BIT_VBATEN)) { - regmap_write(ds1307->regmap, DS1307_REG_WDAY, - regs[DS1307_REG_WDAY] | - MCP794XX_BIT_VBATEN); - } - - /* clock halted? turn it on, so clock can tick. */ - if (!(tmp & MCP794XX_BIT_ST)) { - regmap_write(ds1307->regmap, DS1307_REG_SECS, - MCP794XX_BIT_ST); - dev_warn(ds1307->dev, "SET TIME!\n"); - goto read_rtc; - } - - break; - default: - break; + if (ds1307->type == mcp794xx && + !(regs[DS1307_REG_WDAY] & MCP794XX_BIT_VBATEN)) { + regmap_write(ds1307->regmap, DS1307_REG_WDAY, + regs[DS1307_REG_WDAY] | + MCP794XX_BIT_VBATEN); } tmp = regs[DS1307_REG_HOUR]; diff --git a/drivers/rtc/rtc-ds2404.c b/drivers/rtc/rtc-ds2404.c index 1e9f429ada64..9df0c44512b8 100644 --- a/drivers/rtc/rtc-ds2404.c +++ b/drivers/rtc/rtc-ds2404.c @@ -182,9 +182,10 @@ static void ds2404_enable_osc(struct device *dev) static int ds2404_read_time(struct device *dev, struct rtc_time *dt) { unsigned long time = 0; + __le32 hw_time = 0; - ds2404_read_memory(dev, 0x203, 4, (u8 *)&time); - time = le32_to_cpu(time); + ds2404_read_memory(dev, 0x203, 4, (u8 *)&hw_time); + time = le32_to_cpu(hw_time); rtc_time64_to_tm(time, dt); return 0; diff --git a/drivers/rtc/rtc-fm3130.c b/drivers/rtc/rtc-fm3130.c index 1caa21b82c7d..677ec2da13d8 100644 --- a/drivers/rtc/rtc-fm3130.c +++ b/drivers/rtc/rtc-fm3130.c @@ -104,8 +104,7 @@ static int fm3130_get_time(struct device *dev, struct rtc_time *t) fm3130_rtc_mode(dev, FM3130_MODE_READ); /* read the RTC date and time registers all at once */ - tmp = i2c_transfer(to_i2c_adapter(fm3130->client->dev.parent), - fm3130->msg, 2); + tmp = i2c_transfer(fm3130->client->adapter, fm3130->msg, 2); if (tmp != 2) { dev_err(dev, "%s error %d\n", "read", tmp); return -EIO; @@ -197,8 +196,7 @@ static int fm3130_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) } /* read the RTC alarm registers all at once */ - tmp = i2c_transfer(to_i2c_adapter(fm3130->client->dev.parent), - &fm3130->msg[2], 2); + tmp = i2c_transfer(fm3130->client->adapter, &fm3130->msg[2], 2); if (tmp != 2) { dev_err(dev, "%s error %d\n", "read", tmp); return -EIO; @@ -348,7 +346,7 @@ static int fm3130_probe(struct i2c_client *client, struct fm3130 *fm3130; int err = -ENODEV; int tmp; - struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); + struct i2c_adapter *adapter = client->adapter; if (!i2c_check_functionality(adapter, I2C_FUNC_I2C | I2C_FUNC_SMBUS_WRITE_BYTE_DATA)) diff --git a/drivers/rtc/rtc-imx-sc.c b/drivers/rtc/rtc-imx-sc.c index 19642bfd913a..c933045fe04b 100644 --- a/drivers/rtc/rtc-imx-sc.c +++ b/drivers/rtc/rtc-imx-sc.c @@ -3,6 +3,7 @@ * Copyright 2018 NXP. */ +#include <dt-bindings/firmware/imx/rsrc.h> #include <linux/arm-smccc.h> #include <linux/firmware/imx/sci.h> #include <linux/module.h> @@ -11,11 +12,15 @@ #include <linux/rtc.h> #define IMX_SC_TIMER_FUNC_GET_RTC_SEC1970 9 +#define IMX_SC_TIMER_FUNC_SET_RTC_ALARM 8 #define IMX_SC_TIMER_FUNC_SET_RTC_TIME 6 #define IMX_SIP_SRTC 0xC2000002 #define IMX_SIP_SRTC_SET_TIME 0x0 +#define SC_IRQ_GROUP_RTC 2 +#define SC_IRQ_RTC 1 + static struct imx_sc_ipc *rtc_ipc_handle; static struct rtc_device *imx_sc_rtc; @@ -24,6 +29,16 @@ struct imx_sc_msg_timer_get_rtc_time { u32 time; } __packed; +struct imx_sc_msg_timer_rtc_set_alarm { + struct imx_sc_rpc_msg hdr; + u16 year; + u8 mon; + u8 day; + u8 hour; + u8 min; + u8 sec; +} __packed; + static int imx_sc_rtc_read_time(struct device *dev, struct rtc_time *tm) { struct imx_sc_msg_timer_get_rtc_time msg; @@ -60,9 +75,77 @@ static int imx_sc_rtc_set_time(struct device *dev, struct rtc_time *tm) return res.a0; } +static int imx_sc_rtc_alarm_irq_enable(struct device *dev, unsigned int enable) +{ + return imx_scu_irq_group_enable(SC_IRQ_GROUP_RTC, SC_IRQ_RTC, enable); +} + +static int imx_sc_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) +{ + /* + * SCU firmware does NOT provide read alarm API, but .read_alarm + * callback is required by RTC framework to support alarm function, + * so just return here. + */ + return 0; +} + +static int imx_sc_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) +{ + struct imx_sc_msg_timer_rtc_set_alarm msg; + struct imx_sc_rpc_msg *hdr = &msg.hdr; + int ret; + struct rtc_time *alrm_tm = &alrm->time; + + hdr->ver = IMX_SC_RPC_VERSION; + hdr->svc = IMX_SC_RPC_SVC_TIMER; + hdr->func = IMX_SC_TIMER_FUNC_SET_RTC_ALARM; + hdr->size = 3; + + msg.year = alrm_tm->tm_year + 1900; + msg.mon = alrm_tm->tm_mon + 1; + msg.day = alrm_tm->tm_mday; + msg.hour = alrm_tm->tm_hour; + msg.min = alrm_tm->tm_min; + msg.sec = alrm_tm->tm_sec; + + ret = imx_scu_call_rpc(rtc_ipc_handle, &msg, true); + if (ret) { + dev_err(dev, "set rtc alarm failed, ret %d\n", ret); + return ret; + } + + ret = imx_sc_rtc_alarm_irq_enable(dev, alrm->enabled); + if (ret) { + dev_err(dev, "enable rtc alarm failed, ret %d\n", ret); + return ret; + } + + return 0; +} + static const struct rtc_class_ops imx_sc_rtc_ops = { .read_time = imx_sc_rtc_read_time, .set_time = imx_sc_rtc_set_time, + .read_alarm = imx_sc_rtc_read_alarm, + .set_alarm = imx_sc_rtc_set_alarm, + .alarm_irq_enable = imx_sc_rtc_alarm_irq_enable, +}; + +static int imx_sc_rtc_alarm_notify(struct notifier_block *nb, + unsigned long event, void *group) +{ + /* ignore non-rtc irq */ + if (!((event & SC_IRQ_RTC) && (*(u8 *)group == SC_IRQ_GROUP_RTC))) + return 0; + + rtc_update_irq(imx_sc_rtc, 1, RTC_IRQF | RTC_AF); + + return 0; +} + +static struct notifier_block imx_sc_rtc_alarm_sc_notifier = { + .notifier_call = imx_sc_rtc_alarm_notify, }; static int imx_sc_rtc_probe(struct platform_device *pdev) @@ -73,6 +156,8 @@ static int imx_sc_rtc_probe(struct platform_device *pdev) if (ret) return ret; + device_init_wakeup(&pdev->dev, true); + imx_sc_rtc = devm_rtc_allocate_device(&pdev->dev); if (IS_ERR(imx_sc_rtc)) return PTR_ERR(imx_sc_rtc); @@ -87,6 +172,8 @@ static int imx_sc_rtc_probe(struct platform_device *pdev) return ret; } + imx_scu_irq_register_notifier(&imx_sc_rtc_alarm_sc_notifier); + return 0; } diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c index 9fdc284c943b..5f46f85f814b 100644 --- a/drivers/rtc/rtc-m41t80.c +++ b/drivers/rtc/rtc-m41t80.c @@ -872,7 +872,7 @@ static struct notifier_block wdt_notifier = { static int m41t80_probe(struct i2c_client *client, const struct i2c_device_id *id) { - struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); + struct i2c_adapter *adapter = client->adapter; int rc = 0; struct rtc_time tm; struct m41t80_data *m41t80_data = NULL; diff --git a/drivers/rtc/rtc-pcf2123.c b/drivers/rtc/rtc-pcf2123.c index f431263e2d39..fb542a930bf0 100644 --- a/drivers/rtc/rtc-pcf2123.c +++ b/drivers/rtc/rtc-pcf2123.c @@ -40,7 +40,7 @@ #include <linux/rtc.h> #include <linux/spi/spi.h> #include <linux/module.h> -#include <linux/sysfs.h> +#include <linux/regmap.h> /* REGISTERS */ #define PCF2123_REG_CTRL1 (0x00) /* Control Register 1 */ @@ -95,6 +95,7 @@ #define OFFSET_SIGN_BIT 6 /* 2's complement sign bit */ #define OFFSET_COARSE BIT(7) /* Coarse mode offset */ #define OFFSET_STEP (2170) /* Offset step in parts per billion */ +#define OFFSET_MASK GENMASK(6, 0) /* Offset value */ /* READ/WRITE ADDRESS BITS */ #define PCF2123_WRITE BIT(4) @@ -103,120 +104,35 @@ static struct spi_driver pcf2123_driver; -struct pcf2123_sysfs_reg { - struct device_attribute attr; - char name[2]; -}; - struct pcf2123_plat_data { struct rtc_device *rtc; - struct pcf2123_sysfs_reg regs[16]; + struct regmap *map; }; -/* - * Causes a 30 nanosecond delay to ensure that the PCF2123 chip select - * is released properly after an SPI write. This function should be - * called after EVERY read/write call over SPI. - */ -static inline void pcf2123_delay_trec(void) -{ - ndelay(30); -} - -static int pcf2123_read(struct device *dev, u8 reg, u8 *rxbuf, size_t size) -{ - struct spi_device *spi = to_spi_device(dev); - int ret; - - reg |= PCF2123_READ; - ret = spi_write_then_read(spi, ®, 1, rxbuf, size); - pcf2123_delay_trec(); - - return ret; -} - -static int pcf2123_write(struct device *dev, u8 *txbuf, size_t size) -{ - struct spi_device *spi = to_spi_device(dev); - int ret; - - txbuf[0] |= PCF2123_WRITE; - ret = spi_write(spi, txbuf, size); - pcf2123_delay_trec(); - - return ret; -} - -static int pcf2123_write_reg(struct device *dev, u8 reg, u8 val) -{ - u8 txbuf[2]; - - txbuf[0] = reg; - txbuf[1] = val; - return pcf2123_write(dev, txbuf, sizeof(txbuf)); -} - -static ssize_t pcf2123_show(struct device *dev, struct device_attribute *attr, - char *buffer) -{ - struct pcf2123_sysfs_reg *r; - u8 rxbuf[1]; - unsigned long reg; - int ret; - - r = container_of(attr, struct pcf2123_sysfs_reg, attr); - - ret = kstrtoul(r->name, 16, ®); - if (ret) - return ret; - - ret = pcf2123_read(dev, reg, rxbuf, 1); - if (ret < 0) - return -EIO; - - return sprintf(buffer, "0x%x\n", rxbuf[0]); -} +static const struct regmap_config pcf2123_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .read_flag_mask = PCF2123_READ, + .write_flag_mask = PCF2123_WRITE, + .max_register = PCF2123_REG_CTDWN_TMR, +}; -static ssize_t pcf2123_store(struct device *dev, struct device_attribute *attr, - const char *buffer, size_t count) +static int pcf2123_read_offset(struct device *dev, long *offset) { - struct pcf2123_sysfs_reg *r; - unsigned long reg; - unsigned long val; - - int ret; + struct pcf2123_plat_data *pdata = dev_get_platdata(dev); + int ret, val; + unsigned int reg; - r = container_of(attr, struct pcf2123_sysfs_reg, attr); - - ret = kstrtoul(r->name, 16, ®); + ret = regmap_read(pdata->map, PCF2123_REG_OFFSET, ®); if (ret) return ret; - ret = kstrtoul(buffer, 10, &val); - if (ret) - return ret; - - ret = pcf2123_write_reg(dev, reg, val); - if (ret < 0) - return -EIO; - return count; -} - -static int pcf2123_read_offset(struct device *dev, long *offset) -{ - int ret; - s8 reg; - - ret = pcf2123_read(dev, PCF2123_REG_OFFSET, ®, 1); - if (ret < 0) - return ret; + val = sign_extend32((reg & OFFSET_MASK), OFFSET_SIGN_BIT); if (reg & OFFSET_COARSE) - reg <<= 1; /* multiply by 2 and sign extend */ - else - reg = sign_extend32(reg, OFFSET_SIGN_BIT); + val *= 2; - *offset = ((long)reg) * OFFSET_STEP; + *offset = ((long)val) * OFFSET_STEP; return 0; } @@ -233,6 +149,7 @@ static int pcf2123_read_offset(struct device *dev, long *offset) */ static int pcf2123_set_offset(struct device *dev, long offset) { + struct pcf2123_plat_data *pdata = dev_get_platdata(dev); s8 reg; if (offset > OFFSET_STEP * 127) @@ -240,7 +157,7 @@ static int pcf2123_set_offset(struct device *dev, long offset) else if (offset < OFFSET_STEP * -128) reg = -128; else - reg = (s8)((offset + (OFFSET_STEP >> 1)) / OFFSET_STEP); + reg = DIV_ROUND_CLOSEST(offset, OFFSET_STEP); /* choose fine offset only for odd values in the normal range */ if (reg & 1 && reg <= 63 && reg >= -64) { @@ -252,16 +169,18 @@ static int pcf2123_set_offset(struct device *dev, long offset) reg |= OFFSET_COARSE; } - return pcf2123_write_reg(dev, PCF2123_REG_OFFSET, reg); + return regmap_write(pdata->map, PCF2123_REG_OFFSET, (unsigned int)reg); } static int pcf2123_rtc_read_time(struct device *dev, struct rtc_time *tm) { + struct pcf2123_plat_data *pdata = dev_get_platdata(dev); u8 rxbuf[7]; int ret; - ret = pcf2123_read(dev, PCF2123_REG_SC, rxbuf, sizeof(rxbuf)); - if (ret < 0) + ret = regmap_bulk_read(pdata->map, PCF2123_REG_SC, rxbuf, + sizeof(rxbuf)); + if (ret) return ret; if (rxbuf[0] & OSC_HAS_STOPPED) { @@ -279,82 +198,168 @@ static int pcf2123_rtc_read_time(struct device *dev, struct rtc_time *tm) if (tm->tm_year < 70) tm->tm_year += 100; /* assume we are in 1970...2069 */ - dev_dbg(dev, "%s: tm is secs=%d, mins=%d, hours=%d, " - "mday=%d, mon=%d, year=%d, wday=%d\n", - __func__, - tm->tm_sec, tm->tm_min, tm->tm_hour, - tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); + dev_dbg(dev, "%s: tm is %ptR\n", __func__, tm); return 0; } static int pcf2123_rtc_set_time(struct device *dev, struct rtc_time *tm) { - u8 txbuf[8]; + struct pcf2123_plat_data *pdata = dev_get_platdata(dev); + u8 txbuf[7]; int ret; - dev_dbg(dev, "%s: tm is secs=%d, mins=%d, hours=%d, " - "mday=%d, mon=%d, year=%d, wday=%d\n", - __func__, - tm->tm_sec, tm->tm_min, tm->tm_hour, - tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); + dev_dbg(dev, "%s: tm is %ptR\n", __func__, tm); /* Stop the counter first */ - ret = pcf2123_write_reg(dev, PCF2123_REG_CTRL1, CTRL1_STOP); - if (ret < 0) + ret = regmap_write(pdata->map, PCF2123_REG_CTRL1, CTRL1_STOP); + if (ret) return ret; /* Set the new time */ - txbuf[0] = PCF2123_REG_SC; - txbuf[1] = bin2bcd(tm->tm_sec & 0x7F); - txbuf[2] = bin2bcd(tm->tm_min & 0x7F); - txbuf[3] = bin2bcd(tm->tm_hour & 0x3F); - txbuf[4] = bin2bcd(tm->tm_mday & 0x3F); - txbuf[5] = tm->tm_wday & 0x07; - txbuf[6] = bin2bcd((tm->tm_mon + 1) & 0x1F); /* rtc mn 1-12 */ - txbuf[7] = bin2bcd(tm->tm_year < 100 ? tm->tm_year : tm->tm_year - 100); - - ret = pcf2123_write(dev, txbuf, sizeof(txbuf)); - if (ret < 0) + txbuf[0] = bin2bcd(tm->tm_sec & 0x7F); + txbuf[1] = bin2bcd(tm->tm_min & 0x7F); + txbuf[2] = bin2bcd(tm->tm_hour & 0x3F); + txbuf[3] = bin2bcd(tm->tm_mday & 0x3F); + txbuf[4] = tm->tm_wday & 0x07; + txbuf[5] = bin2bcd((tm->tm_mon + 1) & 0x1F); /* rtc mn 1-12 */ + txbuf[6] = bin2bcd(tm->tm_year < 100 ? tm->tm_year : tm->tm_year - 100); + + ret = regmap_bulk_write(pdata->map, PCF2123_REG_SC, txbuf, + sizeof(txbuf)); + if (ret) return ret; /* Start the counter */ - ret = pcf2123_write_reg(dev, PCF2123_REG_CTRL1, CTRL1_CLEAR); - if (ret < 0) + ret = regmap_write(pdata->map, PCF2123_REG_CTRL1, CTRL1_CLEAR); + if (ret) + return ret; + + return 0; +} + +static int pcf2123_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) +{ + struct pcf2123_plat_data *pdata = dev_get_platdata(dev); + u8 rxbuf[4]; + int ret; + unsigned int val = 0; + + ret = regmap_bulk_read(pdata->map, PCF2123_REG_ALRM_MN, rxbuf, + sizeof(rxbuf)); + if (ret) + return ret; + + alm->time.tm_min = bcd2bin(rxbuf[0] & 0x7F); + alm->time.tm_hour = bcd2bin(rxbuf[1] & 0x3F); + alm->time.tm_mday = bcd2bin(rxbuf[2] & 0x3F); + alm->time.tm_wday = bcd2bin(rxbuf[3] & 0x07); + + dev_dbg(dev, "%s: alm is %ptR\n", __func__, &alm->time); + + ret = regmap_read(pdata->map, PCF2123_REG_CTRL2, &val); + if (ret) + return ret; + + alm->enabled = !!(val & CTRL2_AIE); + + return 0; +} + +static int pcf2123_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) +{ + struct pcf2123_plat_data *pdata = dev_get_platdata(dev); + u8 txbuf[4]; + int ret; + + dev_dbg(dev, "%s: alm is %ptR\n", __func__, &alm->time); + + /* Ensure alarm flag is clear */ + ret = regmap_update_bits(pdata->map, PCF2123_REG_CTRL2, CTRL2_AF, 0); + if (ret) return ret; + /* Disable alarm interrupt */ + ret = regmap_update_bits(pdata->map, PCF2123_REG_CTRL2, CTRL2_AIE, 0); + if (ret) + return ret; + + /* Set new alarm */ + txbuf[0] = bin2bcd(alm->time.tm_min & 0x7F); + txbuf[1] = bin2bcd(alm->time.tm_hour & 0x3F); + txbuf[2] = bin2bcd(alm->time.tm_mday & 0x3F); + txbuf[3] = bin2bcd(alm->time.tm_wday & 0x07); + + ret = regmap_bulk_write(pdata->map, PCF2123_REG_ALRM_MN, txbuf, + sizeof(txbuf)); + if (ret) + return ret; + + /* Enable alarm interrupt */ + if (alm->enabled) { + ret = regmap_update_bits(pdata->map, PCF2123_REG_CTRL2, + CTRL2_AIE, CTRL2_AIE); + if (ret) + return ret; + } + return 0; } +static irqreturn_t pcf2123_rtc_irq(int irq, void *dev) +{ + struct pcf2123_plat_data *pdata = dev_get_platdata(dev); + struct mutex *lock = &pdata->rtc->ops_lock; + unsigned int val = 0; + int ret = IRQ_NONE; + + mutex_lock(lock); + regmap_read(pdata->map, PCF2123_REG_CTRL2, &val); + + /* Alarm? */ + if (val & CTRL2_AF) { + ret = IRQ_HANDLED; + + /* Clear alarm flag */ + regmap_update_bits(pdata->map, PCF2123_REG_CTRL2, CTRL2_AF, 0); + + rtc_update_irq(pdata->rtc, 1, RTC_IRQF | RTC_AF); + } + + mutex_unlock(lock); + + return ret; +} + static int pcf2123_reset(struct device *dev) { + struct pcf2123_plat_data *pdata = dev_get_platdata(dev); int ret; - u8 rxbuf[2]; + unsigned int val = 0; - ret = pcf2123_write_reg(dev, PCF2123_REG_CTRL1, CTRL1_SW_RESET); - if (ret < 0) + ret = regmap_write(pdata->map, PCF2123_REG_CTRL1, CTRL1_SW_RESET); + if (ret) return ret; /* Stop the counter */ dev_dbg(dev, "stopping RTC\n"); - ret = pcf2123_write_reg(dev, PCF2123_REG_CTRL1, CTRL1_STOP); - if (ret < 0) + ret = regmap_write(pdata->map, PCF2123_REG_CTRL1, CTRL1_STOP); + if (ret) return ret; /* See if the counter was actually stopped */ dev_dbg(dev, "checking for presence of RTC\n"); - ret = pcf2123_read(dev, PCF2123_REG_CTRL1, rxbuf, sizeof(rxbuf)); - if (ret < 0) + ret = regmap_read(pdata->map, PCF2123_REG_CTRL1, &val); + if (ret) return ret; - dev_dbg(dev, "received data from RTC (0x%02X 0x%02X)\n", - rxbuf[0], rxbuf[1]); - if (!(rxbuf[0] & CTRL1_STOP)) + dev_dbg(dev, "received data from RTC (0x%08X)\n", val); + if (!(val & CTRL1_STOP)) return -ENODEV; /* Start the counter */ - ret = pcf2123_write_reg(dev, PCF2123_REG_CTRL1, CTRL1_CLEAR); - if (ret < 0) + ret = regmap_write(pdata->map, PCF2123_REG_CTRL1, CTRL1_CLEAR); + if (ret) return ret; return 0; @@ -365,7 +370,8 @@ static const struct rtc_class_ops pcf2123_rtc_ops = { .set_time = pcf2123_rtc_set_time, .read_offset = pcf2123_read_offset, .set_offset = pcf2123_set_offset, - + .read_alarm = pcf2123_rtc_read_alarm, + .set_alarm = pcf2123_rtc_set_alarm, }; static int pcf2123_probe(struct spi_device *spi) @@ -373,7 +379,7 @@ static int pcf2123_probe(struct spi_device *spi) struct rtc_device *rtc; struct rtc_time tm; struct pcf2123_plat_data *pdata; - int ret, i; + int ret = 0; pdata = devm_kzalloc(&spi->dev, sizeof(struct pcf2123_plat_data), GFP_KERNEL); @@ -381,6 +387,13 @@ static int pcf2123_probe(struct spi_device *spi) return -ENOMEM; spi->dev.platform_data = pdata; + pdata->map = devm_regmap_init_spi(spi, &pcf2123_regmap_config); + + if (IS_ERR(pdata->map)) { + dev_err(&spi->dev, "regmap init failed.\n"); + goto kfree_exit; + } + ret = pcf2123_rtc_read_time(&spi->dev, &tm); if (ret < 0) { ret = pcf2123_reset(&spi->dev); @@ -405,47 +418,31 @@ static int pcf2123_probe(struct spi_device *spi) pdata->rtc = rtc; - for (i = 0; i < 16; i++) { - sysfs_attr_init(&pdata->regs[i].attr.attr); - sprintf(pdata->regs[i].name, "%1x", i); - pdata->regs[i].attr.attr.mode = S_IRUGO | S_IWUSR; - pdata->regs[i].attr.attr.name = pdata->regs[i].name; - pdata->regs[i].attr.show = pcf2123_show; - pdata->regs[i].attr.store = pcf2123_store; - ret = device_create_file(&spi->dev, &pdata->regs[i].attr); - if (ret) { - dev_err(&spi->dev, "Unable to create sysfs %s\n", - pdata->regs[i].name); - goto sysfs_exit; - } + /* Register alarm irq */ + if (spi->irq > 0) { + ret = devm_request_threaded_irq(&spi->dev, spi->irq, NULL, + pcf2123_rtc_irq, + IRQF_TRIGGER_LOW | IRQF_ONESHOT, + pcf2123_driver.driver.name, &spi->dev); + if (!ret) + device_init_wakeup(&spi->dev, true); + else + dev_err(&spi->dev, "could not request irq.\n"); } - return 0; + /* The PCF2123's alarm only has minute accuracy. Must add timer + * support to this driver to generate interrupts more than once + * per minute. + */ + pdata->rtc->uie_unsupported = 1; -sysfs_exit: - for (i--; i >= 0; i--) - device_remove_file(&spi->dev, &pdata->regs[i].attr); + return 0; kfree_exit: spi->dev.platform_data = NULL; return ret; } -static int pcf2123_remove(struct spi_device *spi) -{ - struct pcf2123_plat_data *pdata = dev_get_platdata(&spi->dev); - int i; - - if (pdata) { - for (i = 0; i < 16; i++) - if (pdata->regs[i].name[0]) - device_remove_file(&spi->dev, - &pdata->regs[i].attr); - } - - return 0; -} - #ifdef CONFIG_OF static const struct of_device_id pcf2123_dt_ids[] = { { .compatible = "nxp,rtc-pcf2123", }, @@ -461,7 +458,6 @@ static struct spi_driver pcf2123_driver = { .of_match_table = of_match_ptr(pcf2123_dt_ids), }, .probe = pcf2123_probe, - .remove = pcf2123_remove, }; module_spi_driver(pcf2123_driver); diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c index c569dfe8c2ae..ac159d24286d 100644 --- a/drivers/rtc/rtc-pcf8563.c +++ b/drivers/rtc/rtc-pcf8563.c @@ -560,7 +560,6 @@ static int pcf8563_probe(struct i2c_client *client, struct pcf8563 *pcf8563; int err; unsigned char buf; - unsigned char alm_pending; dev_dbg(&client->dev, "%s\n", __func__); @@ -584,13 +583,13 @@ static int pcf8563_probe(struct i2c_client *client, return err; } - err = pcf8563_get_alarm_mode(client, NULL, &alm_pending); - if (err) { - dev_err(&client->dev, "%s: read error\n", __func__); + /* Clear flags and disable interrupts */ + buf = 0; + err = pcf8563_write_block_data(client, PCF8563_REG_ST2, 1, &buf); + if (err < 0) { + dev_err(&client->dev, "%s: write error\n", __func__); return err; } - if (alm_pending) - pcf8563_set_alarm_mode(client, 0); pcf8563->rtc = devm_rtc_device_register(&client->dev, pcf8563_driver.driver.name, @@ -602,7 +601,7 @@ static int pcf8563_probe(struct i2c_client *client, if (client->irq > 0) { err = devm_request_threaded_irq(&client->dev, client->irq, NULL, pcf8563_irq, - IRQF_SHARED|IRQF_ONESHOT|IRQF_TRIGGER_FALLING, + IRQF_SHARED | IRQF_ONESHOT | IRQF_TRIGGER_LOW, pcf8563_driver.driver.name, client); if (err) { dev_err(&client->dev, "unable to request IRQ %d\n", diff --git a/drivers/rtc/rtc-rv8803.c b/drivers/rtc/rtc-rv8803.c index 0b102c3cf5a4..fc5243400108 100644 --- a/drivers/rtc/rtc-rv8803.c +++ b/drivers/rtc/rtc-rv8803.c @@ -517,7 +517,7 @@ static int rx8900_trickle_charger_init(struct rv8803_data *rv8803) static int rv8803_probe(struct i2c_client *client, const struct i2c_device_id *id) { - struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); + struct i2c_adapter *adapter = client->adapter; struct rv8803_data *rv8803; int err, flags; struct nvmem_config nvmem_cfg = { diff --git a/drivers/rtc/rtc-rx8010.c b/drivers/rtc/rtc-rx8010.c index b15ad8e10938..8102469e27c0 100644 --- a/drivers/rtc/rtc-rx8010.c +++ b/drivers/rtc/rtc-rx8010.c @@ -433,7 +433,7 @@ static struct rtc_class_ops rx8010_rtc_ops = { static int rx8010_probe(struct i2c_client *client, const struct i2c_device_id *id) { - struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); + struct i2c_adapter *adapter = client->adapter; struct rx8010_data *rx8010; int err = 0; diff --git a/drivers/rtc/rtc-rx8025.c b/drivers/rtc/rtc-rx8025.c index cb082ad19471..b9bda10589e0 100644 --- a/drivers/rtc/rtc-rx8025.c +++ b/drivers/rtc/rtc-rx8025.c @@ -501,7 +501,7 @@ static void rx8025_sysfs_unregister(struct device *dev) static int rx8025_probe(struct i2c_client *client, const struct i2c_device_id *id) { - struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); + struct i2c_adapter *adapter = client->adapter; struct rx8025_data *rx8025; int err = 0; diff --git a/drivers/rtc/rtc-s35390a.c b/drivers/rtc/rtc-s35390a.c index 8c37acb4a007..84806ff763cf 100644 --- a/drivers/rtc/rtc-s35390a.c +++ b/drivers/rtc/rtc-s35390a.c @@ -32,21 +32,22 @@ #define S35390A_ALRM_BYTE_MINS 2 /* flags for STATUS1 */ -#define S35390A_FLAG_POC 0x01 -#define S35390A_FLAG_BLD 0x02 -#define S35390A_FLAG_INT2 0x04 -#define S35390A_FLAG_24H 0x40 -#define S35390A_FLAG_RESET 0x80 +#define S35390A_FLAG_POC BIT(0) +#define S35390A_FLAG_BLD BIT(1) +#define S35390A_FLAG_INT2 BIT(2) +#define S35390A_FLAG_24H BIT(6) +#define S35390A_FLAG_RESET BIT(7) /* flag for STATUS2 */ -#define S35390A_FLAG_TEST 0x01 - -#define S35390A_INT2_MODE_MASK 0xF0 +#define S35390A_FLAG_TEST BIT(0) +/* INT2 pin output mode */ +#define S35390A_INT2_MODE_MASK 0x0E #define S35390A_INT2_MODE_NOINTR 0x00 -#define S35390A_INT2_MODE_FREQ 0x10 -#define S35390A_INT2_MODE_ALARM 0x40 -#define S35390A_INT2_MODE_PMIN_EDG 0x20 +#define S35390A_INT2_MODE_ALARM BIT(1) /* INT2AE */ +#define S35390A_INT2_MODE_PMIN_EDG BIT(2) /* INT2ME */ +#define S35390A_INT2_MODE_FREQ BIT(3) /* INT2FE */ +#define S35390A_INT2_MODE_PMIN (BIT(3) | BIT(2)) /* INT2FE | INT2ME */ static const struct i2c_device_id s35390a_id[] = { { "s35390a", 0 }, @@ -284,6 +285,9 @@ static int s35390a_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) alm->time.tm_min, alm->time.tm_hour, alm->time.tm_mday, alm->time.tm_mon, alm->time.tm_year, alm->time.tm_wday); + if (alm->time.tm_sec != 0) + dev_warn(&client->dev, "Alarms are only supported on a per minute basis!\n"); + /* disable interrupt (which deasserts the irq line) */ err = s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, &sts, sizeof(sts)); if (err < 0) @@ -299,9 +303,6 @@ static int s35390a_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) else sts = S35390A_INT2_MODE_NOINTR; - /* This chip expects the bits of each byte to be in reverse order */ - sts = bitrev8(sts); - /* set interupt mode*/ err = s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, &sts, sizeof(sts)); if (err < 0) @@ -339,7 +340,7 @@ static int s35390a_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) if (err < 0) return err; - if ((bitrev8(sts) & S35390A_INT2_MODE_MASK) != S35390A_INT2_MODE_ALARM) { + if ((sts & S35390A_INT2_MODE_MASK) != S35390A_INT2_MODE_ALARM) { /* * When the alarm isn't enabled, the register to configure * the alarm time isn't accessible. @@ -431,14 +432,14 @@ static int s35390a_probe(struct i2c_client *client, unsigned int i; struct s35390a *s35390a; char buf, status1; + struct device *dev = &client->dev; if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { err = -ENODEV; goto exit; } - s35390a = devm_kzalloc(&client->dev, sizeof(struct s35390a), - GFP_KERNEL); + s35390a = devm_kzalloc(dev, sizeof(struct s35390a), GFP_KERNEL); if (!s35390a) { err = -ENOMEM; goto exit; @@ -452,8 +453,8 @@ static int s35390a_probe(struct i2c_client *client, s35390a->client[i] = i2c_new_dummy(client->adapter, client->addr + i); if (!s35390a->client[i]) { - dev_err(&client->dev, "Address %02x unavailable\n", - client->addr + i); + dev_err(dev, "Address %02x unavailable\n", + client->addr + i); err = -EBUSY; goto exit_dummy; } @@ -462,7 +463,7 @@ static int s35390a_probe(struct i2c_client *client, err_read = s35390a_read_status(s35390a, &status1); if (err_read < 0) { err = err_read; - dev_err(&client->dev, "error resetting chip\n"); + dev_err(dev, "error resetting chip\n"); goto exit_dummy; } @@ -476,28 +477,30 @@ static int s35390a_probe(struct i2c_client *client, buf = 0; err = s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, &buf, 1); if (err < 0) { - dev_err(&client->dev, "error disabling alarm"); + dev_err(dev, "error disabling alarm"); goto exit_dummy; } } else { err = s35390a_disable_test_mode(s35390a); if (err < 0) { - dev_err(&client->dev, "error disabling test mode\n"); + dev_err(dev, "error disabling test mode\n"); goto exit_dummy; } } - device_set_wakeup_capable(&client->dev, 1); + device_set_wakeup_capable(dev, 1); - s35390a->rtc = devm_rtc_device_register(&client->dev, - s35390a_driver.driver.name, - &s35390a_rtc_ops, THIS_MODULE); + s35390a->rtc = devm_rtc_device_register(dev, s35390a_driver.driver.name, + &s35390a_rtc_ops, THIS_MODULE); if (IS_ERR(s35390a->rtc)) { err = PTR_ERR(s35390a->rtc); goto exit_dummy; } + /* supports per-minute alarms only, therefore set uie_unsupported */ + s35390a->rtc->uie_unsupported = 1; + if (status1 & S35390A_FLAG_INT2) rtc_update_irq(s35390a->rtc, 1, RTC_AF); diff --git a/drivers/rtc/rtc-st-lpc.c b/drivers/rtc/rtc-st-lpc.c index 5fe021821831..49474a31c66d 100644 --- a/drivers/rtc/rtc-st-lpc.c +++ b/drivers/rtc/rtc-st-lpc.c @@ -162,10 +162,6 @@ static int st_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *t) now_secs = rtc_tm_to_time64(&now); alarm_secs = rtc_tm_to_time64(&t->time); - /* Invalid alarm time */ - if (now_secs > alarm_secs) - return -EINVAL; - memcpy(&rtc->alarm, t, sizeof(struct rtc_wkalrm)); /* Now many secs to fire */ diff --git a/drivers/rtc/rtc-stm32.c b/drivers/rtc/rtc-stm32.c index 8e6c9b3bcc29..773a1990b93f 100644 --- a/drivers/rtc/rtc-stm32.c +++ b/drivers/rtc/rtc-stm32.c @@ -519,11 +519,7 @@ static int stm32_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) /* Write to Alarm register */ writel_relaxed(alrmar, rtc->base + regs->alrmar); - if (alrm->enabled) - stm32_rtc_alarm_irq_enable(dev, 1); - else - stm32_rtc_alarm_irq_enable(dev, 0); - + stm32_rtc_alarm_irq_enable(dev, alrm->enabled); end: stm32_rtc_wpr_lock(rtc); diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c index 8128ec200ba2..c0e75c373605 100644 --- a/drivers/rtc/rtc-sun6i.c +++ b/drivers/rtc/rtc-sun6i.c @@ -672,6 +672,7 @@ static const struct of_device_id sun6i_rtc_dt_ids[] = { { .compatible = "allwinner,sun6i-a31-rtc" }, { .compatible = "allwinner,sun8i-a23-rtc" }, { .compatible = "allwinner,sun8i-h3-rtc" }, + { .compatible = "allwinner,sun8i-r40-rtc" }, { .compatible = "allwinner,sun8i-v3-rtc" }, { .compatible = "allwinner,sun50i-h5-rtc" }, { /* sentinel */ }, diff --git a/drivers/rtc/rtc-tegra.c b/drivers/rtc/rtc-tegra.c index f0ce76865434..8fa1b3febf69 100644 --- a/drivers/rtc/rtc-tegra.c +++ b/drivers/rtc/rtc-tegra.c @@ -2,7 +2,7 @@ /* * An RTC driver for the NVIDIA Tegra 200 series internal RTC. * - * Copyright (c) 2010, NVIDIA Corporation. + * Copyright (c) 2010-2019, NVIDIA Corporation. */ #include <linux/clk.h> @@ -18,10 +18,10 @@ #include <linux/rtc.h> #include <linux/slab.h> -/* set to 1 = busy every eight 32kHz clocks during copy of sec+msec to AHB */ +/* Set to 1 = busy every eight 32 kHz clocks during copy of sec+msec to AHB. */ #define TEGRA_RTC_REG_BUSY 0x004 #define TEGRA_RTC_REG_SECONDS 0x008 -/* when msec is read, the seconds are buffered into shadow seconds. */ +/* When msec is read, the seconds are buffered into shadow seconds. */ #define TEGRA_RTC_REG_SHADOW_SECONDS 0x00c #define TEGRA_RTC_REG_MILLI_SECONDS 0x010 #define TEGRA_RTC_REG_SECONDS_ALARM0 0x014 @@ -46,44 +46,48 @@ #define TEGRA_RTC_INTR_STATUS_SEC_ALARM0 (1<<0) struct tegra_rtc_info { - struct platform_device *pdev; - struct rtc_device *rtc_dev; - void __iomem *rtc_base; /* NULL if not initialized. */ - struct clk *clk; - int tegra_rtc_irq; /* alarm and periodic irq */ - spinlock_t tegra_rtc_lock; + struct platform_device *pdev; + struct rtc_device *rtc; + void __iomem *base; /* NULL if not initialized */ + struct clk *clk; + int irq; /* alarm and periodic IRQ */ + spinlock_t lock; }; -/* RTC hardware is busy when it is updating its values over AHB once - * every eight 32kHz clocks (~250uS). - * outside of these updates the CPU is free to write. - * CPU is always free to read. +/* + * RTC hardware is busy when it is updating its values over AHB once every + * eight 32 kHz clocks (~250 us). Outside of these updates the CPU is free to + * write. CPU is always free to read. */ static inline u32 tegra_rtc_check_busy(struct tegra_rtc_info *info) { - return readl(info->rtc_base + TEGRA_RTC_REG_BUSY) & 1; + return readl(info->base + TEGRA_RTC_REG_BUSY) & 1; } -/* Wait for hardware to be ready for writing. - * This function tries to maximize the amount of time before the next update. - * It does this by waiting for the RTC to become busy with its periodic update, - * then returning once the RTC first becomes not busy. +/* + * Wait for hardware to be ready for writing. This function tries to maximize + * the amount of time before the next update. It does this by waiting for the + * RTC to become busy with its periodic update, then returning once the RTC + * first becomes not busy. + * * This periodic update (where the seconds and milliseconds are copied to the - * AHB side) occurs every eight 32kHz clocks (~250uS). - * The behavior of this function allows us to make some assumptions without - * introducing a race, because 250uS is plenty of time to read/write a value. + * AHB side) occurs every eight 32 kHz clocks (~250 us). The behavior of this + * function allows us to make some assumptions without introducing a race, + * because 250 us is plenty of time to read/write a value. */ static int tegra_rtc_wait_while_busy(struct device *dev) { struct tegra_rtc_info *info = dev_get_drvdata(dev); + int retries = 500; /* ~490 us is the worst case, ~250 us is best */ - int retries = 500; /* ~490 us is the worst case, ~250 us is best. */ - - /* first wait for the RTC to become busy. this is when it - * posts its updated seconds+msec registers to AHB side. */ + /* + * First wait for the RTC to become busy. This is when it posts its + * updated seconds+msec registers to AHB side. + */ while (tegra_rtc_check_busy(info)) { if (!retries--) goto retry_failed; + udelay(1); } @@ -91,28 +95,30 @@ static int tegra_rtc_wait_while_busy(struct device *dev) return 0; retry_failed: - dev_err(dev, "write failed:retry count exceeded.\n"); + dev_err(dev, "write failed: retry count exceeded\n"); return -ETIMEDOUT; } static int tegra_rtc_read_time(struct device *dev, struct rtc_time *tm) { struct tegra_rtc_info *info = dev_get_drvdata(dev); - unsigned long sec, msec; - unsigned long sl_irq_flags; + unsigned long flags; + u32 sec, msec; - /* RTC hardware copies seconds to shadow seconds when a read - * of milliseconds occurs. use a lock to keep other threads out. */ - spin_lock_irqsave(&info->tegra_rtc_lock, sl_irq_flags); + /* + * RTC hardware copies seconds to shadow seconds when a read of + * milliseconds occurs. use a lock to keep other threads out. + */ + spin_lock_irqsave(&info->lock, flags); - msec = readl(info->rtc_base + TEGRA_RTC_REG_MILLI_SECONDS); - sec = readl(info->rtc_base + TEGRA_RTC_REG_SHADOW_SECONDS); + msec = readl(info->base + TEGRA_RTC_REG_MILLI_SECONDS); + sec = readl(info->base + TEGRA_RTC_REG_SHADOW_SECONDS); - spin_unlock_irqrestore(&info->tegra_rtc_lock, sl_irq_flags); + spin_unlock_irqrestore(&info->lock, flags); rtc_time64_to_tm(sec, tm); - dev_vdbg(dev, "time read as %lu. %ptR\n", sec, tm); + dev_vdbg(dev, "time read as %u, %ptR\n", sec, tm); return 0; } @@ -120,21 +126,21 @@ static int tegra_rtc_read_time(struct device *dev, struct rtc_time *tm) static int tegra_rtc_set_time(struct device *dev, struct rtc_time *tm) { struct tegra_rtc_info *info = dev_get_drvdata(dev); - unsigned long sec; + u32 sec; int ret; - /* convert tm to seconds. */ + /* convert tm to seconds */ sec = rtc_tm_to_time64(tm); - dev_vdbg(dev, "time set to %lu. %ptR\n", sec, tm); + dev_vdbg(dev, "time set to %u, %ptR\n", sec, tm); - /* seconds only written if wait succeeded. */ + /* seconds only written if wait succeeded */ ret = tegra_rtc_wait_while_busy(dev); if (!ret) - writel(sec, info->rtc_base + TEGRA_RTC_REG_SECONDS); + writel(sec, info->base + TEGRA_RTC_REG_SECONDS); dev_vdbg(dev, "time read back as %d\n", - readl(info->rtc_base + TEGRA_RTC_REG_SECONDS)); + readl(info->base + TEGRA_RTC_REG_SECONDS)); return ret; } @@ -142,22 +148,21 @@ static int tegra_rtc_set_time(struct device *dev, struct rtc_time *tm) static int tegra_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) { struct tegra_rtc_info *info = dev_get_drvdata(dev); - unsigned long sec; - unsigned tmp; + u32 sec, value; - sec = readl(info->rtc_base + TEGRA_RTC_REG_SECONDS_ALARM0); + sec = readl(info->base + TEGRA_RTC_REG_SECONDS_ALARM0); if (sec == 0) { - /* alarm is disabled. */ + /* alarm is disabled */ alarm->enabled = 0; } else { - /* alarm is enabled. */ + /* alarm is enabled */ alarm->enabled = 1; rtc_time64_to_tm(sec, &alarm->time); } - tmp = readl(info->rtc_base + TEGRA_RTC_REG_INTR_STATUS); - alarm->pending = (tmp & TEGRA_RTC_INTR_STATUS_SEC_ALARM0) != 0; + value = readl(info->base + TEGRA_RTC_REG_INTR_STATUS); + alarm->pending = (value & TEGRA_RTC_INTR_STATUS_SEC_ALARM0) != 0; return 0; } @@ -165,22 +170,22 @@ static int tegra_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) static int tegra_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) { struct tegra_rtc_info *info = dev_get_drvdata(dev); - unsigned status; - unsigned long sl_irq_flags; + unsigned long flags; + u32 status; tegra_rtc_wait_while_busy(dev); - spin_lock_irqsave(&info->tegra_rtc_lock, sl_irq_flags); + spin_lock_irqsave(&info->lock, flags); - /* read the original value, and OR in the flag. */ - status = readl(info->rtc_base + TEGRA_RTC_REG_INTR_MASK); + /* read the original value, and OR in the flag */ + status = readl(info->base + TEGRA_RTC_REG_INTR_MASK); if (enabled) status |= TEGRA_RTC_INTR_MASK_SEC_ALARM0; /* set it */ else status &= ~TEGRA_RTC_INTR_MASK_SEC_ALARM0; /* clear it */ - writel(status, info->rtc_base + TEGRA_RTC_REG_INTR_MASK); + writel(status, info->base + TEGRA_RTC_REG_INTR_MASK); - spin_unlock_irqrestore(&info->tegra_rtc_lock, sl_irq_flags); + spin_unlock_irqrestore(&info->lock, flags); return 0; } @@ -188,7 +193,7 @@ static int tegra_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) static int tegra_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) { struct tegra_rtc_info *info = dev_get_drvdata(dev); - unsigned long sec; + u32 sec; if (alarm->enabled) sec = rtc_tm_to_time64(&alarm->time); @@ -196,16 +201,16 @@ static int tegra_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) sec = 0; tegra_rtc_wait_while_busy(dev); - writel(sec, info->rtc_base + TEGRA_RTC_REG_SECONDS_ALARM0); + writel(sec, info->base + TEGRA_RTC_REG_SECONDS_ALARM0); dev_vdbg(dev, "alarm read back as %d\n", - readl(info->rtc_base + TEGRA_RTC_REG_SECONDS_ALARM0)); + readl(info->base + TEGRA_RTC_REG_SECONDS_ALARM0)); /* if successfully written and alarm is enabled ... */ if (sec) { tegra_rtc_alarm_irq_enable(dev, 1); - dev_vdbg(dev, "alarm set as %lu. %ptR\n", sec, &alarm->time); + dev_vdbg(dev, "alarm set as %u, %ptR\n", sec, &alarm->time); } else { - /* disable alarm if 0 or write error. */ + /* disable alarm if 0 or write error */ dev_vdbg(dev, "alarm disabled\n"); tegra_rtc_alarm_irq_enable(dev, 0); } @@ -227,39 +232,39 @@ static irqreturn_t tegra_rtc_irq_handler(int irq, void *data) { struct device *dev = data; struct tegra_rtc_info *info = dev_get_drvdata(dev); - unsigned long events = 0; - unsigned status; - unsigned long sl_irq_flags; + unsigned long events = 0, flags; + u32 status; - status = readl(info->rtc_base + TEGRA_RTC_REG_INTR_STATUS); + status = readl(info->base + TEGRA_RTC_REG_INTR_STATUS); if (status) { - /* clear the interrupt masks and status on any irq. */ + /* clear the interrupt masks and status on any IRQ */ tegra_rtc_wait_while_busy(dev); - spin_lock_irqsave(&info->tegra_rtc_lock, sl_irq_flags); - writel(0, info->rtc_base + TEGRA_RTC_REG_INTR_MASK); - writel(status, info->rtc_base + TEGRA_RTC_REG_INTR_STATUS); - spin_unlock_irqrestore(&info->tegra_rtc_lock, sl_irq_flags); + + spin_lock_irqsave(&info->lock, flags); + writel(0, info->base + TEGRA_RTC_REG_INTR_MASK); + writel(status, info->base + TEGRA_RTC_REG_INTR_STATUS); + spin_unlock_irqrestore(&info->lock, flags); } - /* check if Alarm */ - if ((status & TEGRA_RTC_INTR_STATUS_SEC_ALARM0)) + /* check if alarm */ + if (status & TEGRA_RTC_INTR_STATUS_SEC_ALARM0) events |= RTC_IRQF | RTC_AF; - /* check if Periodic */ - if ((status & TEGRA_RTC_INTR_STATUS_SEC_CDN_ALARM)) + /* check if periodic */ + if (status & TEGRA_RTC_INTR_STATUS_SEC_CDN_ALARM) events |= RTC_IRQF | RTC_PF; - rtc_update_irq(info->rtc_dev, 1, events); + rtc_update_irq(info->rtc, 1, events); return IRQ_HANDLED; } static const struct rtc_class_ops tegra_rtc_ops = { - .read_time = tegra_rtc_read_time, - .set_time = tegra_rtc_set_time, - .read_alarm = tegra_rtc_read_alarm, - .set_alarm = tegra_rtc_set_alarm, - .proc = tegra_rtc_proc, + .read_time = tegra_rtc_read_time, + .set_time = tegra_rtc_set_time, + .read_alarm = tegra_rtc_read_alarm, + .set_alarm = tegra_rtc_set_alarm, + .proc = tegra_rtc_proc, .alarm_irq_enable = tegra_rtc_alarm_irq_enable, }; @@ -269,21 +274,20 @@ static const struct of_device_id tegra_rtc_dt_match[] = { }; MODULE_DEVICE_TABLE(of, tegra_rtc_dt_match); -static int __init tegra_rtc_probe(struct platform_device *pdev) +static int tegra_rtc_probe(struct platform_device *pdev) { struct tegra_rtc_info *info; struct resource *res; int ret; - info = devm_kzalloc(&pdev->dev, sizeof(struct tegra_rtc_info), - GFP_KERNEL); + info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); if (!info) return -ENOMEM; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - info->rtc_base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(info->rtc_base)) - return PTR_ERR(info->rtc_base); + info->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(info->base)) + return PTR_ERR(info->base); ret = platform_get_irq(pdev, 0); if (ret <= 0) { @@ -291,14 +295,14 @@ static int __init tegra_rtc_probe(struct platform_device *pdev) return ret; } - info->tegra_rtc_irq = ret; + info->irq = ret; - info->rtc_dev = devm_rtc_allocate_device(&pdev->dev); - if (IS_ERR(info->rtc_dev)) - return PTR_ERR(info->rtc_dev); + info->rtc = devm_rtc_allocate_device(&pdev->dev); + if (IS_ERR(info->rtc)) + return PTR_ERR(info->rtc); - info->rtc_dev->ops = &tegra_rtc_ops; - info->rtc_dev->range_max = U32_MAX; + info->rtc->ops = &tegra_rtc_ops; + info->rtc->range_max = U32_MAX; info->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(info->clk)) @@ -308,33 +312,30 @@ static int __init tegra_rtc_probe(struct platform_device *pdev) if (ret < 0) return ret; - /* set context info. */ + /* set context info */ info->pdev = pdev; - spin_lock_init(&info->tegra_rtc_lock); + spin_lock_init(&info->lock); platform_set_drvdata(pdev, info); - /* clear out the hardware. */ - writel(0, info->rtc_base + TEGRA_RTC_REG_SECONDS_ALARM0); - writel(0xffffffff, info->rtc_base + TEGRA_RTC_REG_INTR_STATUS); - writel(0, info->rtc_base + TEGRA_RTC_REG_INTR_MASK); + /* clear out the hardware */ + writel(0, info->base + TEGRA_RTC_REG_SECONDS_ALARM0); + writel(0xffffffff, info->base + TEGRA_RTC_REG_INTR_STATUS); + writel(0, info->base + TEGRA_RTC_REG_INTR_MASK); device_init_wakeup(&pdev->dev, 1); - ret = devm_request_irq(&pdev->dev, info->tegra_rtc_irq, - tegra_rtc_irq_handler, IRQF_TRIGGER_HIGH, - dev_name(&pdev->dev), &pdev->dev); + ret = devm_request_irq(&pdev->dev, info->irq, tegra_rtc_irq_handler, + IRQF_TRIGGER_HIGH, dev_name(&pdev->dev), + &pdev->dev); if (ret) { - dev_err(&pdev->dev, - "Unable to request interrupt for device (err=%d).\n", - ret); + dev_err(&pdev->dev, "failed to request interrupt: %d\n", ret); goto disable_clk; } - ret = rtc_register_device(info->rtc_dev); + ret = rtc_register_device(info->rtc); if (ret) { - dev_err(&pdev->dev, "Unable to register device (err=%d).\n", - ret); + dev_err(&pdev->dev, "failed to register device: %d\n", ret); goto disable_clk; } @@ -363,20 +364,20 @@ static int tegra_rtc_suspend(struct device *dev) tegra_rtc_wait_while_busy(dev); - /* only use ALARM0 as a wake source. */ - writel(0xffffffff, info->rtc_base + TEGRA_RTC_REG_INTR_STATUS); + /* only use ALARM0 as a wake source */ + writel(0xffffffff, info->base + TEGRA_RTC_REG_INTR_STATUS); writel(TEGRA_RTC_INTR_STATUS_SEC_ALARM0, - info->rtc_base + TEGRA_RTC_REG_INTR_MASK); + info->base + TEGRA_RTC_REG_INTR_MASK); dev_vdbg(dev, "alarm sec = %d\n", - readl(info->rtc_base + TEGRA_RTC_REG_SECONDS_ALARM0)); + readl(info->base + TEGRA_RTC_REG_SECONDS_ALARM0)); - dev_vdbg(dev, "Suspend (device_may_wakeup=%d) irq:%d\n", - device_may_wakeup(dev), info->tegra_rtc_irq); + dev_vdbg(dev, "Suspend (device_may_wakeup=%d) IRQ:%d\n", + device_may_wakeup(dev), info->irq); - /* leave the alarms on as a wake source. */ + /* leave the alarms on as a wake source */ if (device_may_wakeup(dev)) - enable_irq_wake(info->tegra_rtc_irq); + enable_irq_wake(info->irq); return 0; } @@ -386,10 +387,11 @@ static int tegra_rtc_resume(struct device *dev) struct tegra_rtc_info *info = dev_get_drvdata(dev); dev_vdbg(dev, "Resume (device_may_wakeup=%d)\n", - device_may_wakeup(dev)); - /* alarms were left on as a wake source, turn them off. */ + device_may_wakeup(dev)); + + /* alarms were left on as a wake source, turn them off */ if (device_may_wakeup(dev)) - disable_irq_wake(info->tegra_rtc_irq); + disable_irq_wake(info->irq); return 0; } @@ -399,22 +401,21 @@ static SIMPLE_DEV_PM_OPS(tegra_rtc_pm_ops, tegra_rtc_suspend, tegra_rtc_resume); static void tegra_rtc_shutdown(struct platform_device *pdev) { - dev_vdbg(&pdev->dev, "disabling interrupts.\n"); + dev_vdbg(&pdev->dev, "disabling interrupts\n"); tegra_rtc_alarm_irq_enable(&pdev->dev, 0); } -MODULE_ALIAS("platform:tegra_rtc"); static struct platform_driver tegra_rtc_driver = { - .remove = tegra_rtc_remove, - .shutdown = tegra_rtc_shutdown, - .driver = { - .name = "tegra_rtc", + .probe = tegra_rtc_probe, + .remove = tegra_rtc_remove, + .shutdown = tegra_rtc_shutdown, + .driver = { + .name = "tegra_rtc", .of_match_table = tegra_rtc_dt_match, - .pm = &tegra_rtc_pm_ops, + .pm = &tegra_rtc_pm_ops, }, }; - -module_platform_driver_probe(tegra_rtc_driver, tegra_rtc_probe); +module_platform_driver(tegra_rtc_driver); MODULE_AUTHOR("Jon Mayo <jmayo@nvidia.com>"); MODULE_DESCRIPTION("driver for Tegra internal RTC"); diff --git a/drivers/rtc/rtc-test.c b/drivers/rtc/rtc-test.c index b298e9902f45..74b3a0603b73 100644 --- a/drivers/rtc/rtc-test.c +++ b/drivers/rtc/rtc-test.c @@ -133,6 +133,7 @@ static int test_probe(struct platform_device *plat_dev) break; default: rtd->rtc->ops = &test_rtc_ops; + device_init_wakeup(&plat_dev->dev, 1); } timer_setup(&rtd->alarm, test_rtc_alarm_handler, 0); diff --git a/drivers/rtc/rtc-tps65910.c b/drivers/rtc/rtc-tps65910.c index 8556d925e52a..7078f6da1cbc 100644 --- a/drivers/rtc/rtc-tps65910.c +++ b/drivers/rtc/rtc-tps65910.c @@ -143,7 +143,7 @@ static int tps65910_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) struct tps65910 *tps = dev_get_drvdata(dev->parent); int ret; - ret = regmap_bulk_read(tps->regmap, TPS65910_SECONDS, alarm_data, + ret = regmap_bulk_read(tps->regmap, TPS65910_ALARM_SECONDS, alarm_data, NUM_TIME_REGS); if (ret < 0) { dev_err(dev, "rtc_read_alarm error %d\n", ret); diff --git a/drivers/rtc/rtc-wm831x.c b/drivers/rtc/rtc-wm831x.c index d2e8b21c90c4..ccef887d2690 100644 --- a/drivers/rtc/rtc-wm831x.c +++ b/drivers/rtc/rtc-wm831x.c @@ -435,7 +435,8 @@ static int wm831x_rtc_probe(struct platform_device *pdev) ret = devm_request_threaded_irq(&pdev->dev, alm_irq, NULL, wm831x_alm_irq, - IRQF_TRIGGER_RISING, "RTC alarm", + IRQF_TRIGGER_RISING | IRQF_ONESHOT, + "RTC alarm", wm831x_rtc); if (ret != 0) { dev_err(&pdev->dev, "Failed to request alarm IRQ %d: %d\n", |