diff options
author | Stephen Rothwell <sfr@canb.auug.org.au> | 2018-09-18 13:48:05 +1000 |
---|---|---|
committer | Stephen Rothwell <sfr@canb.auug.org.au> | 2018-09-18 13:48:05 +1000 |
commit | 86e0a7c7a59d95ee6caa1158cd4fcbf2ea62145c (patch) | |
tree | 3058e6a006b25ab727a1ee89e9143854e322b9c3 | |
parent | c1d12234fef4ef2d75ee11ef31d779a848ee1e32 (diff) | |
parent | 03df75dd03301307ec578ccd4e8c1c0117b8e65c (diff) | |
download | linux-next-86e0a7c7a59d95ee6caa1158cd4fcbf2ea62145c.tar.gz |
Merge remote-tracking branch 'rtc/rtc-next'
-rw-r--r-- | arch/mips/Kconfig | 2 | ||||
-rw-r--r-- | drivers/char/Kconfig | 2 | ||||
-rw-r--r-- | drivers/mfd/menelaus.c | 13 | ||||
-rw-r--r-- | drivers/rtc/Kconfig | 3 | ||||
-rw-r--r-- | drivers/rtc/class.c | 12 | ||||
-rw-r--r-- | drivers/rtc/interface.c | 3 | ||||
-rw-r--r-- | drivers/rtc/rtc-abx80x.c | 143 | ||||
-rw-r--r-- | drivers/rtc/rtc-isl1208.c | 11 | ||||
-rw-r--r-- | drivers/rtc/rtc-mrst.c | 5 | ||||
-rw-r--r-- | drivers/rtc/rtc-mt6397.c | 13 | ||||
-rw-r--r-- | drivers/rtc/rtc-omap.c | 28 | ||||
-rw-r--r-- | drivers/rtc/rtc-pl030.c | 15 | ||||
-rw-r--r-- | drivers/rtc/rtc-pl031.c | 18 | ||||
-rw-r--r-- | drivers/rtc/rtc-rv8803.c | 7 | ||||
-rw-r--r-- | drivers/rtc/rtc-sun6i.c | 3 | ||||
-rw-r--r-- | drivers/rtc/rtc-sysfs.c | 4 | ||||
-rw-r--r-- | include/linux/rtc.h | 5 |
17 files changed, 203 insertions, 84 deletions
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index f744d25f7423..1b5fa1a2b41a 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -75,7 +75,7 @@ config MIPS select MODULES_USE_ELF_RELA if MODULES && 64BIT select MODULES_USE_ELF_REL if MODULES select PERF_USE_VMALLOC - select RTC_LIB if !MACH_LOONGSON64 + select RTC_LIB select SYSCTL_EXCEPTION_TRACE select VIRT_TO_BUS select NO_BOOTMEM diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 40728491f37b..9d03b2ff5df6 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -268,7 +268,7 @@ if RTC_LIB=n config RTC tristate "Enhanced Real Time Clock Support (legacy PC RTC driver)" - depends on ALPHA || (MIPS && MACH_LOONGSON64) + depends on ALPHA ---help--- If you say Y here and create a character special file /dev/rtc with major number 10 and minor number 135 using mknod ("man mknod"), you diff --git a/drivers/mfd/menelaus.c b/drivers/mfd/menelaus.c index 29b7164a823b..d28ebe7ecd21 100644 --- a/drivers/mfd/menelaus.c +++ b/drivers/mfd/menelaus.c @@ -1094,6 +1094,7 @@ static void menelaus_rtc_alarm_work(struct menelaus_chip *m) static inline void menelaus_rtc_init(struct menelaus_chip *m) { int alarm = (m->client->irq > 0); + int err; /* assume 32KDETEN pin is pulled high */ if (!(menelaus_read_reg(MENELAUS_OSC_CTRL) & 0x80)) { @@ -1101,6 +1102,12 @@ static inline void menelaus_rtc_init(struct menelaus_chip *m) return; } + m->rtc = devm_rtc_allocate_device(&m->client->dev); + if (IS_ERR(m->rtc)) + return; + + m->rtc->ops = &menelaus_rtc_ops; + /* support RTC alarm; it can issue wakeups */ if (alarm) { if (menelaus_add_irq_work(MENELAUS_RTCALM_IRQ, @@ -1125,10 +1132,8 @@ static inline void menelaus_rtc_init(struct menelaus_chip *m) menelaus_write_reg(MENELAUS_RTC_CTRL, m->rtc_control); } - m->rtc = rtc_device_register(DRIVER_NAME, - &m->client->dev, - &menelaus_rtc_ops, THIS_MODULE); - if (IS_ERR(m->rtc)) { + err = rtc_register_device(m->rtc); + if (err) { if (alarm) { menelaus_remove_irq_work(MENELAUS_RTCALM_IRQ); device_init_wakeup(&m->client->dev, 0); diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 7d7be60a2413..4df9a3ec064b 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -187,6 +187,7 @@ config RTC_DRV_ABB5ZES3 config RTC_DRV_ABX80X tristate "Abracon ABx80x" + select WATCHDOG_CORE if WATCHDOG help If you say yes here you get support for Abracon AB080X and AB180X families of ultra-low-power battery- and capacitor-backed real-time @@ -1587,7 +1588,7 @@ config RTC_DRV_MPC5121 config RTC_DRV_JZ4740 tristate "Ingenic JZ4740 SoC" - depends on MACH_INGENIC || COMPILE_TEST + depends on MIPS || COMPILE_TEST help If you say yes here you get support for the Ingenic JZ47xx SoCs RTC controllers. diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index 0fca4d74c76b..3b43787f154b 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c @@ -286,9 +286,10 @@ static void rtc_device_get_offset(struct rtc_device *rtc) * * Returns the pointer to the new struct class device. */ -struct rtc_device *rtc_device_register(const char *name, struct device *dev, - const struct rtc_class_ops *ops, - struct module *owner) +static struct rtc_device *rtc_device_register(const char *name, + struct device *dev, + const struct rtc_class_ops *ops, + struct module *owner) { struct rtc_device *rtc; struct rtc_wkalrm alrm; @@ -351,15 +352,13 @@ exit: name, err); return ERR_PTR(err); } -EXPORT_SYMBOL_GPL(rtc_device_register); - /** * rtc_device_unregister - removes the previously registered RTC class device * * @rtc: the RTC class device to destroy */ -void rtc_device_unregister(struct rtc_device *rtc) +static void rtc_device_unregister(struct rtc_device *rtc) { mutex_lock(&rtc->ops_lock); /* @@ -372,7 +371,6 @@ void rtc_device_unregister(struct rtc_device *rtc) mutex_unlock(&rtc->ops_lock); put_device(&rtc->dev); } -EXPORT_SYMBOL_GPL(rtc_device_unregister); static void devm_rtc_device_release(struct device *dev, void *res) { diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 3d577e259e91..612a83d3ddcc 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -596,7 +596,6 @@ EXPORT_SYMBOL_GPL(rtc_update_irq_enable); * This function is called when an AIE, UIE or PIE mode interrupt * has occurred (or been emulated). * - * Triggers the registered irq_task function callback. */ void rtc_handle_legacy_irq(struct rtc_device *rtc, int num, int mode) { @@ -741,7 +740,6 @@ static int rtc_update_hrtimer(struct rtc_device *rtc, int enabled) /** * rtc_irq_set_state - enable/disable 2^N Hz periodic IRQs * @rtc: the rtc device - * @task: currently registered with rtc_irq_register() * @enabled: true to enable periodic IRQs * Context: any * @@ -764,7 +762,6 @@ int rtc_irq_set_state(struct rtc_device *rtc, int enabled) /** * rtc_irq_set_freq - set 2^N Hz periodic IRQ frequency for IRQ * @rtc: the rtc device - * @task: currently registered with rtc_irq_register() * @freq: positive frequency * Context: any * diff --git a/drivers/rtc/rtc-abx80x.c b/drivers/rtc/rtc-abx80x.c index 2cefa67a1132..d8e94edcb0ba 100644 --- a/drivers/rtc/rtc-abx80x.c +++ b/drivers/rtc/rtc-abx80x.c @@ -17,6 +17,7 @@ #include <linux/i2c.h> #include <linux/module.h> #include <linux/rtc.h> +#include <linux/watchdog.h> #define ABX8XX_REG_HTH 0x00 #define ABX8XX_REG_SC 0x01 @@ -37,6 +38,7 @@ #define ABX8XX_REG_STATUS 0x0f #define ABX8XX_STATUS_AF BIT(2) +#define ABX8XX_STATUS_WDT BIT(6) #define ABX8XX_REG_CTRL1 0x10 #define ABX8XX_CTRL_WRITE BIT(0) @@ -61,6 +63,14 @@ #define ABX8XX_OSS_OF BIT(1) #define ABX8XX_OSS_OMODE BIT(4) +#define ABX8XX_REG_WDT 0x1b +#define ABX8XX_WDT_WDS BIT(7) +#define ABX8XX_WDT_BMB_MASK 0x7c +#define ABX8XX_WDT_BMB_SHIFT 2 +#define ABX8XX_WDT_MAX_TIME (ABX8XX_WDT_BMB_MASK >> ABX8XX_WDT_BMB_SHIFT) +#define ABX8XX_WDT_WRB_MASK 0x03 +#define ABX8XX_WDT_WRB_1HZ 0x02 + #define ABX8XX_REG_CFG_KEY 0x1f #define ABX8XX_CFG_KEY_OSC 0xa1 #define ABX8XX_CFG_KEY_MISC 0x9d @@ -80,20 +90,27 @@ enum abx80x_chip {AB0801, AB0803, AB0804, AB0805, struct abx80x_cap { u16 pn; bool has_tc; + bool has_wdog; }; static struct abx80x_cap abx80x_caps[] = { [AB0801] = {.pn = 0x0801}, [AB0803] = {.pn = 0x0803}, - [AB0804] = {.pn = 0x0804, .has_tc = true}, - [AB0805] = {.pn = 0x0805, .has_tc = true}, + [AB0804] = {.pn = 0x0804, .has_tc = true, .has_wdog = true}, + [AB0805] = {.pn = 0x0805, .has_tc = true, .has_wdog = true}, [AB1801] = {.pn = 0x1801}, [AB1803] = {.pn = 0x1803}, - [AB1804] = {.pn = 0x1804, .has_tc = true}, - [AB1805] = {.pn = 0x1805, .has_tc = true}, + [AB1804] = {.pn = 0x1804, .has_tc = true, .has_wdog = true}, + [AB1805] = {.pn = 0x1805, .has_tc = true, .has_wdog = true}, [ABX80X] = {.pn = 0} }; +struct abx80x_priv { + struct rtc_device *rtc; + struct i2c_client *client; + struct watchdog_device wdog; +}; + static int abx80x_is_rc_mode(struct i2c_client *client) { int flags = 0; @@ -218,7 +235,8 @@ static int abx80x_rtc_set_time(struct device *dev, struct rtc_time *tm) static irqreturn_t abx80x_handle_irq(int irq, void *dev_id) { struct i2c_client *client = dev_id; - struct rtc_device *rtc = i2c_get_clientdata(client); + struct abx80x_priv *priv = i2c_get_clientdata(client); + struct rtc_device *rtc = priv->rtc; int status; status = i2c_smbus_read_byte_data(client, ABX8XX_REG_STATUS); @@ -228,6 +246,13 @@ static irqreturn_t abx80x_handle_irq(int irq, void *dev_id) if (status & ABX8XX_STATUS_AF) rtc_update_irq(rtc, 1, RTC_AF | RTC_IRQF); + /* + * It is unclear if we'll get an interrupt before the external + * reset kicks in. + */ + if (status & ABX8XX_STATUS_WDT) + dev_alert(&client->dev, "watchdog timeout interrupt.\n"); + i2c_smbus_write_byte_data(client, ABX8XX_REG_STATUS, 0); return IRQ_HANDLED; @@ -529,11 +554,94 @@ static void rtc_calib_remove_sysfs_group(void *_dev) sysfs_remove_group(&dev->kobj, &rtc_calib_attr_group); } +#ifdef CONFIG_WATCHDOG + +static inline u8 timeout_bits(unsigned int timeout) +{ + return ((timeout << ABX8XX_WDT_BMB_SHIFT) & ABX8XX_WDT_BMB_MASK) | + ABX8XX_WDT_WRB_1HZ; +} + +static int __abx80x_wdog_set_timeout(struct watchdog_device *wdog, + unsigned int timeout) +{ + struct abx80x_priv *priv = watchdog_get_drvdata(wdog); + u8 val = ABX8XX_WDT_WDS | timeout_bits(timeout); + + /* + * Writing any timeout to the WDT register resets the watchdog timer. + * Writing 0 disables it. + */ + return i2c_smbus_write_byte_data(priv->client, ABX8XX_REG_WDT, val); +} + +static int abx80x_wdog_set_timeout(struct watchdog_device *wdog, + unsigned int new_timeout) +{ + int err = 0; + + if (watchdog_hw_running(wdog)) + err = __abx80x_wdog_set_timeout(wdog, new_timeout); + + if (err == 0) + wdog->timeout = new_timeout; + + return err; +} + +static int abx80x_wdog_ping(struct watchdog_device *wdog) +{ + return __abx80x_wdog_set_timeout(wdog, wdog->timeout); +} + +static int abx80x_wdog_start(struct watchdog_device *wdog) +{ + return __abx80x_wdog_set_timeout(wdog, wdog->timeout); +} + +static int abx80x_wdog_stop(struct watchdog_device *wdog) +{ + return __abx80x_wdog_set_timeout(wdog, 0); +} + +static const struct watchdog_info abx80x_wdog_info = { + .identity = "abx80x watchdog", + .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, +}; + +static const struct watchdog_ops abx80x_wdog_ops = { + .owner = THIS_MODULE, + .start = abx80x_wdog_start, + .stop = abx80x_wdog_stop, + .ping = abx80x_wdog_ping, + .set_timeout = abx80x_wdog_set_timeout, +}; + +static int abx80x_setup_watchdog(struct abx80x_priv *priv) +{ + priv->wdog.parent = &priv->client->dev; + priv->wdog.ops = &abx80x_wdog_ops; + priv->wdog.info = &abx80x_wdog_info; + priv->wdog.min_timeout = 1; + priv->wdog.max_timeout = ABX8XX_WDT_MAX_TIME; + priv->wdog.timeout = ABX8XX_WDT_MAX_TIME; + + watchdog_set_drvdata(&priv->wdog, priv); + + return devm_watchdog_register_device(&priv->client->dev, &priv->wdog); +} +#else +static int abx80x_setup_watchdog(struct abx80x_priv *priv) +{ + return 0; +} +#endif + static int abx80x_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct device_node *np = client->dev.of_node; - struct rtc_device *rtc; + struct abx80x_priv *priv; int i, data, err, trickle_cfg = -EINVAL; char buf[7]; unsigned int part = id->driver_data; @@ -610,13 +718,24 @@ static int abx80x_probe(struct i2c_client *client, if (err) return err; - rtc = devm_rtc_allocate_device(&client->dev); - if (IS_ERR(rtc)) - return PTR_ERR(rtc); + priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL); + if (priv == NULL) + return -ENOMEM; + + priv->rtc = devm_rtc_allocate_device(&client->dev); + if (IS_ERR(priv->rtc)) + return PTR_ERR(priv->rtc); + + priv->rtc->ops = &abx80x_rtc_ops; + priv->client = client; - rtc->ops = &abx80x_rtc_ops; + i2c_set_clientdata(client, priv); - i2c_set_clientdata(client, rtc); + if (abx80x_caps[part].has_wdog) { + err = abx80x_setup_watchdog(priv); + if (err) + return err; + } if (client->irq > 0) { dev_info(&client->dev, "IRQ %d supplied\n", client->irq); @@ -649,7 +768,7 @@ static int abx80x_probe(struct i2c_client *client, return err; } - err = rtc_register_device(rtc); + err = rtc_register_device(priv->rtc); return err; } diff --git a/drivers/rtc/rtc-isl1208.c b/drivers/rtc/rtc-isl1208.c index ea18a8f4bce0..e1e9434c9972 100644 --- a/drivers/rtc/rtc-isl1208.c +++ b/drivers/rtc/rtc-isl1208.c @@ -804,7 +804,7 @@ isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id) evdet_irq = of_irq_get_byname(np, "evdet"); } - rc = sysfs_create_group(&client->dev.kobj, &isl1208_rtc_sysfs_files); + rc = rtc_add_group(rtc, &isl1208_rtc_sysfs_files); if (rc) return rc; @@ -821,14 +821,6 @@ isl1208_probe(struct i2c_client *client, const struct i2c_device_id *id) return rtc_register_device(rtc); } -static int -isl1208_remove(struct i2c_client *client) -{ - sysfs_remove_group(&client->dev.kobj, &isl1208_rtc_sysfs_files); - - return 0; -} - static const struct i2c_device_id isl1208_id[] = { { "isl1208", TYPE_ISL1208 }, { "isl1218", TYPE_ISL1218 }, @@ -851,7 +843,6 @@ static struct i2c_driver isl1208_driver = { .of_match_table = of_match_ptr(isl1208_of_match), }, .probe = isl1208_probe, - .remove = isl1208_remove, .id_table = isl1208_id, }; diff --git a/drivers/rtc/rtc-mrst.c b/drivers/rtc/rtc-mrst.c index 1925aaf09093..daf354a6a853 100644 --- a/drivers/rtc/rtc-mrst.c +++ b/drivers/rtc/rtc-mrst.c @@ -90,7 +90,7 @@ static int mrst_read_time(struct device *dev, struct rtc_time *time) unsigned long flags; if (vrtc_is_updating()) - mdelay(20); + msleep(20); spin_lock_irqsave(&rtc_lock, flags); time->tm_sec = vrtc_cmos_read(RTC_SECONDS); @@ -261,11 +261,10 @@ static int mrst_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) static int mrst_procfs(struct device *dev, struct seq_file *seq) { - unsigned char rtc_control, valid; + unsigned char rtc_control; spin_lock_irq(&rtc_lock); rtc_control = vrtc_cmos_read(RTC_CONTROL); - valid = vrtc_cmos_read(RTC_VALID); spin_unlock_irq(&rtc_lock); seq_printf(seq, diff --git a/drivers/rtc/rtc-mt6397.c b/drivers/rtc/rtc-mt6397.c index 385f8303bb41..e9a25ec4d434 100644 --- a/drivers/rtc/rtc-mt6397.c +++ b/drivers/rtc/rtc-mt6397.c @@ -332,6 +332,10 @@ static int mtk_rtc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, rtc); + rtc->rtc_dev = devm_rtc_allocate_device(rtc->dev); + if (IS_ERR(rtc->rtc_dev)) + return PTR_ERR(rtc->rtc_dev); + ret = request_threaded_irq(rtc->irq, NULL, mtk_rtc_irq_handler_thread, IRQF_ONESHOT | IRQF_TRIGGER_HIGH, @@ -344,11 +348,11 @@ static int mtk_rtc_probe(struct platform_device *pdev) device_init_wakeup(&pdev->dev, 1); - rtc->rtc_dev = rtc_device_register("mt6397-rtc", &pdev->dev, - &mtk_rtc_ops, THIS_MODULE); - if (IS_ERR(rtc->rtc_dev)) { + rtc->rtc_dev->ops = &mtk_rtc_ops; + + ret = rtc_register_device(rtc->rtc_dev); + if (ret) { dev_err(&pdev->dev, "register rtc device failed\n"); - ret = PTR_ERR(rtc->rtc_dev); goto out_free_irq; } @@ -365,7 +369,6 @@ static int mtk_rtc_remove(struct platform_device *pdev) { struct mt6397_rtc *rtc = platform_get_drvdata(pdev); - rtc_device_unregister(rtc->rtc_dev); free_irq(rtc->irq, rtc->rtc_dev); irq_dispose_mapping(rtc->irq); diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c index 323ff55cc165..320b4a520eb3 100644 --- a/drivers/rtc/rtc-omap.c +++ b/drivers/rtc/rtc-omap.c @@ -421,12 +421,6 @@ static struct omap_rtc *omap_rtc_power_off_rtc; * The RTC can be used to control an external PMIC via the pmic_power_en pin, * which can be configured to transition to OFF on ALARM2 events. * - * Notes: - * The two-second alarm offset is the shortest offset possible as the alarm - * registers must be set before the next timer update and the offset - * calculation is too heavy for everything to be done within a single access - * period (~15 us). - * * Called with local interrupts disabled. */ static void omap_rtc_power_off(void) @@ -434,6 +428,7 @@ static void omap_rtc_power_off(void) struct omap_rtc *rtc = omap_rtc_power_off_rtc; struct rtc_time tm; unsigned long now; + int seconds; u32 val; rtc->type->unlock(rtc); @@ -441,11 +436,13 @@ static void omap_rtc_power_off(void) val = rtc_readl(rtc, OMAP_RTC_PMIC_REG); rtc_writel(rtc, OMAP_RTC_PMIC_REG, val | OMAP_RTC_PMIC_POWER_EN_EN); - /* set alarm two seconds from now */ +again: + /* set alarm one second from now */ omap_rtc_read_time_raw(rtc, &tm); + seconds = tm.tm_sec; bcd2tm(&tm); rtc_tm_to_time(&tm, &now); - rtc_time_to_tm(now + 2, &tm); + rtc_time_to_tm(now + 1, &tm); if (tm2bcd(&tm) < 0) { dev_err(&rtc->rtc->dev, "power off failed\n"); @@ -470,14 +467,22 @@ static void omap_rtc_power_off(void) val = rtc_read(rtc, OMAP_RTC_INTERRUPTS_REG); rtc_writel(rtc, OMAP_RTC_INTERRUPTS_REG, val | OMAP_RTC_INTERRUPTS_IT_ALARM2); + + /* Retry in case roll over happened before alarm was armed. */ + if (rtc_read(rtc, OMAP_RTC_SECONDS_REG) != seconds) { + val = rtc_read(rtc, OMAP_RTC_STATUS_REG); + if (!(val & OMAP_RTC_STATUS_ALARM2)) + goto again; + } + rtc->type->lock(rtc); /* - * Wait for alarm to trigger (within two seconds) and external PMIC to + * Wait for alarm to trigger (within one second) and external PMIC to * power off the system. Add a 500 ms margin for external latencies * (e.g. debounce circuits). */ - mdelay(2500); + mdelay(1500); } static const struct rtc_class_ops omap_rtc_ops = { @@ -721,8 +726,7 @@ static int omap_rtc_probe(struct platform_device *pdev) if (of_id) { rtc->type = of_id->data; rtc->is_pmic_controller = rtc->type->has_pmic_mode && - of_property_read_bool(pdev->dev.of_node, - "system-power-controller"); + of_device_is_system_power_controller(pdev->dev.of_node); } else { id_entry = platform_get_device_id(pdev); rtc->type = (void *)id_entry->driver_data; diff --git a/drivers/rtc/rtc-pl030.c b/drivers/rtc/rtc-pl030.c index f85a1a93e669..343bb6ed1783 100644 --- a/drivers/rtc/rtc-pl030.c +++ b/drivers/rtc/rtc-pl030.c @@ -112,6 +112,13 @@ static int pl030_probe(struct amba_device *dev, const struct amba_id *id) goto err_rtc; } + rtc->rtc = devm_rtc_allocate_device(&dev->dev); + if (IS_ERR(rtc->rtc)) { + ret = PTR_ERR(rtc->rtc); + goto err_rtc; + } + + rtc->rtc->ops = &pl030_ops; rtc->base = ioremap(dev->res.start, resource_size(&dev->res)); if (!rtc->base) { ret = -ENOMEM; @@ -128,12 +135,9 @@ static int pl030_probe(struct amba_device *dev, const struct amba_id *id) if (ret) goto err_irq; - rtc->rtc = rtc_device_register("pl030", &dev->dev, &pl030_ops, - THIS_MODULE); - if (IS_ERR(rtc->rtc)) { - ret = PTR_ERR(rtc->rtc); + ret = rtc_register_device(rtc->rtc); + if (ret) goto err_reg; - } return 0; @@ -154,7 +158,6 @@ static int pl030_remove(struct amba_device *dev) writel(0, rtc->base + RTC_CR); free_irq(dev->irq[0], rtc); - rtc_device_unregister(rtc->rtc); iounmap(rtc->base); amba_release_regions(dev); diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c index 82eb7da2c478..30943d200c5e 100644 --- a/drivers/rtc/rtc-pl031.c +++ b/drivers/rtc/rtc-pl031.c @@ -310,7 +310,6 @@ static int pl031_remove(struct amba_device *adev) device_init_wakeup(&adev->dev, false); if (adev->irq[0]) free_irq(adev->irq[0], ldata); - rtc_device_unregister(ldata->rtc); amba_release_regions(adev); return 0; @@ -383,24 +382,25 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id) } device_init_wakeup(&adev->dev, true); - ldata->rtc = rtc_device_register("pl031", &adev->dev, ops, - THIS_MODULE); - if (IS_ERR(ldata->rtc)) { - ret = PTR_ERR(ldata->rtc); + ldata->rtc = devm_rtc_allocate_device(&adev->dev); + if (IS_ERR(ldata->rtc)) + return PTR_ERR(ldata->rtc); + + ldata->rtc->ops = ops; + + ret = rtc_register_device(ldata->rtc); + if (ret) goto out; - } if (adev->irq[0]) { ret = request_irq(adev->irq[0], pl031_interrupt, vendor->irqflags, "rtc-pl031", ldata); if (ret) - goto out_no_irq; + goto out; dev_pm_set_wake_irq(&adev->dev, adev->irq[0]); } return 0; -out_no_irq: - rtc_device_unregister(ldata->rtc); out: amba_release_regions(adev); err_req: diff --git a/drivers/rtc/rtc-rv8803.c b/drivers/rtc/rtc-rv8803.c index 29fc3d210392..450a0b831a2d 100644 --- a/drivers/rtc/rtc-rv8803.c +++ b/drivers/rtc/rtc-rv8803.c @@ -615,6 +615,7 @@ static int rv8803_probe(struct i2c_client *client, static const struct i2c_device_id rv8803_id[] = { { "rv8803", rv_8803 }, + { "rx8803", rv_8803 }, { "rx8900", rx_8900 }, { } }; @@ -623,7 +624,11 @@ MODULE_DEVICE_TABLE(i2c, rv8803_id); static const struct of_device_id rv8803_of_match[] = { { .compatible = "microcrystal,rv8803", - .data = (void *)rx_8900 + .data = (void *)rv_8803 + }, + { + .compatible = "epson,rx8803", + .data = (void *)rv_8803 }, { .compatible = "epson,rx8900", diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c index 2cd5a7b1a2e3..fe07310952df 100644 --- a/drivers/rtc/rtc-sun6i.c +++ b/drivers/rtc/rtc-sun6i.c @@ -199,8 +199,7 @@ static void __init sun6i_rtc_clk_init(struct device_node *node) if (!rtc) return; - clk_data = kzalloc(sizeof(*clk_data) + (sizeof(*clk_data->hws) * 2), - GFP_KERNEL); + clk_data = kzalloc(struct_size(clk_data, hws, 2), GFP_KERNEL); if (!clk_data) { kfree(rtc); return; diff --git a/drivers/rtc/rtc-sysfs.c b/drivers/rtc/rtc-sysfs.c index f1ff30ade534..9746c32eee2e 100644 --- a/drivers/rtc/rtc-sysfs.c +++ b/drivers/rtc/rtc-sysfs.c @@ -338,8 +338,8 @@ int rtc_add_groups(struct rtc_device *rtc, const struct attribute_group **grps) new_cnt = old_cnt + add_cnt + 1; groups = devm_kcalloc(&rtc->dev, new_cnt, sizeof(*groups), GFP_KERNEL); - if (IS_ERR_OR_NULL(groups)) - return PTR_ERR(groups); + if (!groups) + return -ENOMEM; memcpy(groups, rtc->dev.groups, old_cnt * sizeof(*groups)); memcpy(groups + old_cnt, grps, add_cnt * sizeof(*groups)); groups[old_cnt + add_cnt] = NULL; diff --git a/include/linux/rtc.h b/include/linux/rtc.h index 6aedc30003e7..faf00a1472d4 100644 --- a/include/linux/rtc.h +++ b/include/linux/rtc.h @@ -167,17 +167,12 @@ struct rtc_device { #define RTC_TIMESTAMP_BEGIN_2000 946684800LL /* 2000-01-01 00:00:00 */ #define RTC_TIMESTAMP_END_2099 4102444799LL /* 2099-12-31 23:59:59 */ -extern struct rtc_device *rtc_device_register(const char *name, - struct device *dev, - const struct rtc_class_ops *ops, - struct module *owner); extern struct rtc_device *devm_rtc_device_register(struct device *dev, const char *name, const struct rtc_class_ops *ops, struct module *owner); struct rtc_device *devm_rtc_allocate_device(struct device *dev); int __rtc_register_device(struct module *owner, struct rtc_device *rtc); -extern void rtc_device_unregister(struct rtc_device *rtc); extern void devm_rtc_device_unregister(struct device *dev, struct rtc_device *rtc); |