diff options
author | 2020-06-07 16:11:23 -0700 | |
---|---|---|
committer | 2020-06-07 16:11:23 -0700 | |
commit | e8dff03aef6a76c5c9184ed1dd3c770d4ce9c885 (patch) | |
tree | fe96dbed37472dfc2fe812b7ca825e27d2ca8a6a | |
parent | Merge tag 'ntb-5.8' of git://github.com/jonmason/ntb (diff) | |
parent | rtc: pcf2127: watchdog: handle nowayout feature (diff) | |
download | linux-e8dff03aef6a76c5c9184ed1dd3c770d4ce9c885.tar.gz linux-e8dff03aef6a76c5c9184ed1dd3c770d4ce9c885.tar.bz2 linux-e8dff03aef6a76c5c9184ed1dd3c770d4ce9c885.zip |
Merge tag 'rtc-5.8' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux
Pull RTC updates from Alexandre Belloni:
"Not much this cycle apart from the ingenic rtc driver rework.
The fixes are mainly minor issues reported by coccinelle rather than
real world issues.
Subsystem:
- new VL flag for backup switch over
Drivers:
- ingenic: only support device tree
- pcf2127: report battery switch over, handle nowayout"
* tag 'rtc-5.8' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux: (29 commits)
rtc: pcf2127: watchdog: handle nowayout feature
rtc: fsl-ftm-alarm: fix freeze(s2idle) failed to wake
rtc: abx80x: Provide debug feedback for invalid dt properties
rtc: abx80x: Add Device Tree matching table
rtc: rv3028: Add missed check for devm_regmap_init_i2c()
rtc: mpc5121: Use correct return value for mpc5121_rtc_probe()
rtc: goldfish: Use correct return value for goldfish_rtc_probe()
rtc: snvs: Add necessary clock operations for RTC APIs
rtc: snvs: Make SNVS clock always prepared
rtc: ingenic: Reset regulator register in probe
rtc: ingenic: Fix masking of error code
rtc: ingenic: Remove unused fields from private structure
rtc: ingenic: Set wakeup params in probe
rtc: ingenic: Enable clock in probe
rtc: ingenic: Use local 'dev' variable in probe
rtc: ingenic: Only support probing from devicetree
rtc: mc13xxx: fix a double-unlock issue
rtc: stmp3xxx: update contact email
rtc: max77686: Use single-byte writes on MAX77620
rtc: pcf2127: report battery switch over
...
-rw-r--r-- | drivers/rtc/Kconfig | 1 | ||||
-rw-r--r-- | drivers/rtc/rtc-88pm860x.c | 6 | ||||
-rw-r--r-- | drivers/rtc/rtc-abx80x.c | 66 | ||||
-rw-r--r-- | drivers/rtc/rtc-fsl-ftm-alarm.c | 10 | ||||
-rw-r--r-- | drivers/rtc/rtc-goldfish.c | 2 | ||||
-rw-r--r-- | drivers/rtc/rtc-jz4740.c | 173 | ||||
-rw-r--r-- | drivers/rtc/rtc-lpc24xx.c | 4 | ||||
-rw-r--r-- | drivers/rtc/rtc-max77686.c | 22 | ||||
-rw-r--r-- | drivers/rtc/rtc-mc13xxx.c | 4 | ||||
-rw-r--r-- | drivers/rtc/rtc-mpc5121.c | 2 | ||||
-rw-r--r-- | drivers/rtc/rtc-mt2712.c | 16 | ||||
-rw-r--r-- | drivers/rtc/rtc-pcf2127.c | 31 | ||||
-rw-r--r-- | drivers/rtc/rtc-rc5t619.c | 4 | ||||
-rw-r--r-- | drivers/rtc/rtc-rv3028.c | 2 | ||||
-rw-r--r-- | drivers/rtc/rtc-snvs.c | 59 | ||||
-rw-r--r-- | drivers/rtc/rtc-stmp3xxx.c | 2 | ||||
-rw-r--r-- | include/uapi/linux/rtc.h | 1 |
17 files changed, 256 insertions, 149 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 527957d9c6ce..b54d87d45c89 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -1680,6 +1680,7 @@ config RTC_DRV_MPC5121 config RTC_DRV_JZ4740 tristate "Ingenic JZ4740 SoC" depends on MIPS || COMPILE_TEST + depends on OF help If you say yes here you get support for the Ingenic JZ47xx SoCs RTC controllers. diff --git a/drivers/rtc/rtc-88pm860x.c b/drivers/rtc/rtc-88pm860x.c index cc9b14ef90f1..c90457d001e9 100644 --- a/drivers/rtc/rtc-88pm860x.c +++ b/drivers/rtc/rtc-88pm860x.c @@ -106,12 +106,6 @@ static int pm860x_rtc_set_time(struct device *dev, struct rtc_time *tm) unsigned char buf[4]; unsigned long ticks, base, data; - if (tm->tm_year > 206) { - dev_dbg(info->dev, "Set time %d out of range. " - "Please set time between 1970 to 2106.\n", - 1900 + tm->tm_year); - return -EINVAL; - } ticks = rtc_tm_to_time64(tm); /* load 32-bit read-only counter */ diff --git a/drivers/rtc/rtc-abx80x.c b/drivers/rtc/rtc-abx80x.c index 3521d8e8dc38..803725b3a02c 100644 --- a/drivers/rtc/rtc-abx80x.c +++ b/drivers/rtc/rtc-abx80x.c @@ -13,6 +13,7 @@ #include <linux/bcd.h> #include <linux/i2c.h> #include <linux/module.h> +#include <linux/of_device.h> #include <linux/rtc.h> #include <linux/watchdog.h> @@ -554,8 +555,9 @@ static const struct rtc_class_ops abx80x_rtc_ops = { .ioctl = abx80x_ioctl, }; -static int abx80x_dt_trickle_cfg(struct device_node *np) +static int abx80x_dt_trickle_cfg(struct i2c_client *client) { + struct device_node *np = client->dev.of_node; const char *diode; int trickle_cfg = 0; int i, ret; @@ -565,12 +567,14 @@ static int abx80x_dt_trickle_cfg(struct device_node *np) if (ret) return ret; - if (!strcmp(diode, "standard")) + if (!strcmp(diode, "standard")) { trickle_cfg |= ABX8XX_TRICKLE_STANDARD_DIODE; - else if (!strcmp(diode, "schottky")) + } else if (!strcmp(diode, "schottky")) { trickle_cfg |= ABX8XX_TRICKLE_SCHOTTKY_DIODE; - else + } else { + dev_dbg(&client->dev, "Invalid tc-diode value: %s\n", diode); return -EINVAL; + } ret = of_property_read_u32(np, "abracon,tc-resistor", &tmp); if (ret) @@ -580,8 +584,10 @@ static int abx80x_dt_trickle_cfg(struct device_node *np) if (trickle_resistors[i] == tmp) break; - if (i == sizeof(trickle_resistors)) + if (i == sizeof(trickle_resistors)) { + dev_dbg(&client->dev, "Invalid tc-resistor value: %u\n", tmp); return -EINVAL; + } return (trickle_cfg | i); } @@ -793,7 +799,7 @@ static int abx80x_probe(struct i2c_client *client, } if (np && abx80x_caps[part].has_tc) - trickle_cfg = abx80x_dt_trickle_cfg(np); + trickle_cfg = abx80x_dt_trickle_cfg(client); if (trickle_cfg > 0) { dev_info(&client->dev, "Enabling trickle charger: %02x\n", @@ -863,9 +869,57 @@ static const struct i2c_device_id abx80x_id[] = { }; MODULE_DEVICE_TABLE(i2c, abx80x_id); +#ifdef CONFIG_OF +static const struct of_device_id abx80x_of_match[] = { + { + .compatible = "abracon,abx80x", + .data = (void *)ABX80X + }, + { + .compatible = "abracon,ab0801", + .data = (void *)AB0801 + }, + { + .compatible = "abracon,ab0803", + .data = (void *)AB0803 + }, + { + .compatible = "abracon,ab0804", + .data = (void *)AB0804 + }, + { + .compatible = "abracon,ab0805", + .data = (void *)AB0805 + }, + { + .compatible = "abracon,ab1801", + .data = (void *)AB1801 + }, + { + .compatible = "abracon,ab1803", + .data = (void *)AB1803 + }, + { + .compatible = "abracon,ab1804", + .data = (void *)AB1804 + }, + { + .compatible = "abracon,ab1805", + .data = (void *)AB1805 + }, + { + .compatible = "microcrystal,rv1805", + .data = (void *)RV1805 + }, + { } +}; +MODULE_DEVICE_TABLE(of, abx80x_of_match); +#endif + static struct i2c_driver abx80x_driver = { .driver = { .name = "rtc-abx80x", + .of_match_table = of_match_ptr(abx80x_of_match), }, .probe = abx80x_probe, .id_table = abx80x_id, diff --git a/drivers/rtc/rtc-fsl-ftm-alarm.c b/drivers/rtc/rtc-fsl-ftm-alarm.c index 756af62b0486..68f0a1801a2e 100644 --- a/drivers/rtc/rtc-fsl-ftm-alarm.c +++ b/drivers/rtc/rtc-fsl-ftm-alarm.c @@ -21,6 +21,7 @@ #include <linux/rtc.h> #include <linux/time.h> #include <linux/acpi.h> +#include <linux/pm_wakeirq.h> #define FTM_SC_CLK(c) ((c) << FTM_SC_CLK_MASK_SHIFT) @@ -268,13 +269,11 @@ static int ftm_rtc_probe(struct platform_device *pdev) } irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "can't get irq number\n"); + if (irq < 0) return irq; - } ret = devm_request_irq(&pdev->dev, irq, ftm_rtc_alarm_interrupt, - IRQF_NO_SUSPEND, dev_name(&pdev->dev), rtc); + 0, dev_name(&pdev->dev), rtc); if (ret < 0) { dev_err(&pdev->dev, "failed to request irq\n"); return ret; @@ -287,6 +286,9 @@ static int ftm_rtc_probe(struct platform_device *pdev) rtc->rtc_dev->ops = &ftm_rtc_ops; device_init_wakeup(&pdev->dev, true); + ret = dev_pm_set_wake_irq(&pdev->dev, irq); + if (ret) + dev_err(&pdev->dev, "failed to enable irq wake\n"); ret = rtc_register_device(rtc->rtc_dev); if (ret) { diff --git a/drivers/rtc/rtc-goldfish.c b/drivers/rtc/rtc-goldfish.c index cb6b0ad7ec3f..27797157fcb3 100644 --- a/drivers/rtc/rtc-goldfish.c +++ b/drivers/rtc/rtc-goldfish.c @@ -174,7 +174,7 @@ static int goldfish_rtc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, rtcdrv); rtcdrv->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(rtcdrv->base)) - return -ENODEV; + return PTR_ERR(rtcdrv->base); rtcdrv->irq = platform_get_irq(pdev, 0); if (rtcdrv->irq < 0) diff --git a/drivers/rtc/rtc-jz4740.c b/drivers/rtc/rtc-jz4740.c index e4c719085c31..9607e6b6e0b3 100644 --- a/drivers/rtc/rtc-jz4740.c +++ b/drivers/rtc/rtc-jz4740.c @@ -55,14 +55,8 @@ struct jz4740_rtc { enum jz4740_rtc_type type; struct rtc_device *rtc; - struct clk *clk; - - int irq; spinlock_t lock; - - unsigned int min_wakeup_pin_assert_time; - unsigned int reset_pin_assert_time; }; static struct device *dev_for_power_off; @@ -259,156 +253,157 @@ static void jz4740_rtc_poweroff(struct device *dev) static void jz4740_rtc_power_off(void) { - struct jz4740_rtc *rtc = dev_get_drvdata(dev_for_power_off); - unsigned long rtc_rate; - unsigned long wakeup_filter_ticks; - unsigned long reset_counter_ticks; + jz4740_rtc_poweroff(dev_for_power_off); + kernel_halt(); +} - clk_prepare_enable(rtc->clk); +static void jz4740_rtc_clk_disable(void *data) +{ + clk_disable_unprepare(data); +} - rtc_rate = clk_get_rate(rtc->clk); +static const struct of_device_id jz4740_rtc_of_match[] = { + { .compatible = "ingenic,jz4740-rtc", .data = (void *)ID_JZ4740 }, + { .compatible = "ingenic,jz4760-rtc", .data = (void *)ID_JZ4760 }, + { .compatible = "ingenic,jz4780-rtc", .data = (void *)ID_JZ4780 }, + {}, +}; +MODULE_DEVICE_TABLE(of, jz4740_rtc_of_match); + +static void jz4740_rtc_set_wakeup_params(struct jz4740_rtc *rtc, + struct device_node *np, + unsigned long rate) +{ + unsigned long wakeup_ticks, reset_ticks; + unsigned int min_wakeup_pin_assert_time = 60; /* Default: 60ms */ + unsigned int reset_pin_assert_time = 100; /* Default: 100ms */ + + of_property_read_u32(np, "ingenic,reset-pin-assert-time-ms", + &reset_pin_assert_time); + of_property_read_u32(np, "ingenic,min-wakeup-pin-assert-time-ms", + &min_wakeup_pin_assert_time); /* * Set minimum wakeup pin assertion time: 100 ms. * Range is 0 to 2 sec if RTC is clocked at 32 kHz. */ - wakeup_filter_ticks = - (rtc->min_wakeup_pin_assert_time * rtc_rate) / 1000; - if (wakeup_filter_ticks < JZ_RTC_WAKEUP_FILTER_MASK) - wakeup_filter_ticks &= JZ_RTC_WAKEUP_FILTER_MASK; + wakeup_ticks = (min_wakeup_pin_assert_time * rate) / 1000; + if (wakeup_ticks < JZ_RTC_WAKEUP_FILTER_MASK) + wakeup_ticks &= JZ_RTC_WAKEUP_FILTER_MASK; else - wakeup_filter_ticks = JZ_RTC_WAKEUP_FILTER_MASK; - jz4740_rtc_reg_write(rtc, - JZ_REG_RTC_WAKEUP_FILTER, wakeup_filter_ticks); + wakeup_ticks = JZ_RTC_WAKEUP_FILTER_MASK; + jz4740_rtc_reg_write(rtc, JZ_REG_RTC_WAKEUP_FILTER, wakeup_ticks); /* * Set reset pin low-level assertion time after wakeup: 60 ms. * Range is 0 to 125 ms if RTC is clocked at 32 kHz. */ - reset_counter_ticks = (rtc->reset_pin_assert_time * rtc_rate) / 1000; - if (reset_counter_ticks < JZ_RTC_RESET_COUNTER_MASK) - reset_counter_ticks &= JZ_RTC_RESET_COUNTER_MASK; + reset_ticks = (reset_pin_assert_time * rate) / 1000; + if (reset_ticks < JZ_RTC_RESET_COUNTER_MASK) + reset_ticks &= JZ_RTC_RESET_COUNTER_MASK; else - reset_counter_ticks = JZ_RTC_RESET_COUNTER_MASK; - jz4740_rtc_reg_write(rtc, - JZ_REG_RTC_RESET_COUNTER, reset_counter_ticks); - - jz4740_rtc_poweroff(dev_for_power_off); - kernel_halt(); + reset_ticks = JZ_RTC_RESET_COUNTER_MASK; + jz4740_rtc_reg_write(rtc, JZ_REG_RTC_RESET_COUNTER, reset_ticks); } -static const struct of_device_id jz4740_rtc_of_match[] = { - { .compatible = "ingenic,jz4740-rtc", .data = (void *)ID_JZ4740 }, - { .compatible = "ingenic,jz4760-rtc", .data = (void *)ID_JZ4760 }, - { .compatible = "ingenic,jz4780-rtc", .data = (void *)ID_JZ4780 }, - {}, -}; -MODULE_DEVICE_TABLE(of, jz4740_rtc_of_match); - static int jz4740_rtc_probe(struct platform_device *pdev) { - int ret; + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; struct jz4740_rtc *rtc; - const struct platform_device_id *id = platform_get_device_id(pdev); - const struct of_device_id *of_id = of_match_device( - jz4740_rtc_of_match, &pdev->dev); - struct device_node *np = pdev->dev.of_node; + unsigned long rate; + struct clk *clk; + int ret, irq; - rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL); + rtc = devm_kzalloc(dev, sizeof(*rtc), GFP_KERNEL); if (!rtc) return -ENOMEM; - if (of_id) - rtc->type = (enum jz4740_rtc_type)of_id->data; - else - rtc->type = id->driver_data; + rtc->type = (enum jz4740_rtc_type)device_get_match_data(dev); - rtc->irq = platform_get_irq(pdev, 0); - if (rtc->irq < 0) - return -ENOENT; + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; rtc->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(rtc->base)) return PTR_ERR(rtc->base); - rtc->clk = devm_clk_get(&pdev->dev, "rtc"); - if (IS_ERR(rtc->clk)) { - dev_err(&pdev->dev, "Failed to get RTC clock\n"); - return PTR_ERR(rtc->clk); + clk = devm_clk_get(dev, "rtc"); + if (IS_ERR(clk)) { + dev_err(dev, "Failed to get RTC clock\n"); + return PTR_ERR(clk); + } + + ret = clk_prepare_enable(clk); + if (ret) { + dev_err(dev, "Failed to enable clock\n"); + return ret; + } + + ret = devm_add_action_or_reset(dev, jz4740_rtc_clk_disable, clk); + if (ret) { + dev_err(dev, "Failed to register devm action\n"); + return ret; } spin_lock_init(&rtc->lock); platform_set_drvdata(pdev, rtc); - device_init_wakeup(&pdev->dev, 1); + device_init_wakeup(dev, 1); - ret = dev_pm_set_wake_irq(&pdev->dev, rtc->irq); + ret = dev_pm_set_wake_irq(dev, irq); if (ret) { - dev_err(&pdev->dev, "Failed to set wake irq: %d\n", ret); + dev_err(dev, "Failed to set wake irq: %d\n", ret); return ret; } - rtc->rtc = devm_rtc_allocate_device(&pdev->dev); + rtc->rtc = devm_rtc_allocate_device(dev); if (IS_ERR(rtc->rtc)) { ret = PTR_ERR(rtc->rtc); - dev_err(&pdev->dev, "Failed to allocate rtc device: %d\n", ret); + dev_err(dev, "Failed to allocate rtc device: %d\n", ret); return ret; } rtc->rtc->ops = &jz4740_rtc_ops; rtc->rtc->range_max = U32_MAX; + rate = clk_get_rate(clk); + jz4740_rtc_set_wakeup_params(rtc, np, rate); + + /* Each 1 Hz pulse should happen after (rate) ticks */ + jz4740_rtc_reg_write(rtc, JZ_REG_RTC_REGULATOR, rate - 1); + ret = rtc_register_device(rtc->rtc); if (ret) return ret; - ret = devm_request_irq(&pdev->dev, rtc->irq, jz4740_rtc_irq, 0, - pdev->name, rtc); + ret = devm_request_irq(dev, irq, jz4740_rtc_irq, 0, + pdev->name, rtc); if (ret) { - dev_err(&pdev->dev, "Failed to request rtc irq: %d\n", ret); + dev_err(dev, "Failed to request rtc irq: %d\n", ret); return ret; } - if (np && of_device_is_system_power_controller(np)) { - if (!pm_power_off) { - /* Default: 60ms */ - rtc->reset_pin_assert_time = 60; - of_property_read_u32(np, - "ingenic,reset-pin-assert-time-ms", - &rtc->reset_pin_assert_time); - - /* Default: 100ms */ - rtc->min_wakeup_pin_assert_time = 100; - of_property_read_u32(np, - "ingenic,min-wakeup-pin-assert-time-ms", - &rtc->min_wakeup_pin_assert_time); - - dev_for_power_off = &pdev->dev; + if (of_device_is_system_power_controller(np)) { + dev_for_power_off = dev; + + if (!pm_power_off) pm_power_off = jz4740_rtc_power_off; - } else { - dev_warn(&pdev->dev, - "Poweroff handler already present!\n"); - } + else + dev_warn(dev, "Poweroff handler already present!\n"); } return 0; } -static const struct platform_device_id jz4740_rtc_ids[] = { - { "jz4740-rtc", ID_JZ4740 }, - { "jz4780-rtc", ID_JZ4780 }, - {} -}; -MODULE_DEVICE_TABLE(platform, jz4740_rtc_ids); - static struct platform_driver jz4740_rtc_driver = { .probe = jz4740_rtc_probe, .driver = { .name = "jz4740-rtc", - .of_match_table = of_match_ptr(jz4740_rtc_of_match), + .of_match_table = jz4740_rtc_of_match, }, - .id_table = jz4740_rtc_ids, }; module_platform_driver(jz4740_rtc_driver); diff --git a/drivers/rtc/rtc-lpc24xx.c b/drivers/rtc/rtc-lpc24xx.c index 00ef16ba9480..eec881a81067 100644 --- a/drivers/rtc/rtc-lpc24xx.c +++ b/drivers/rtc/rtc-lpc24xx.c @@ -205,10 +205,8 @@ static int lpc24xx_rtc_probe(struct platform_device *pdev) return PTR_ERR(rtc->rtc_base); irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_warn(&pdev->dev, "can't get interrupt resource\n"); + if (irq < 0) return irq; - } rtc->clk_rtc = devm_clk_get(&pdev->dev, "rtc"); if (IS_ERR(rtc->clk_rtc)) { diff --git a/drivers/rtc/rtc-max77686.c b/drivers/rtc/rtc-max77686.c index d5a0e27dd0a0..03ebcf1c0f3d 100644 --- a/drivers/rtc/rtc-max77686.c +++ b/drivers/rtc/rtc-max77686.c @@ -78,6 +78,8 @@ struct max77686_rtc_driver_data { int alarm_pending_status_reg; /* RTC IRQ CHIP for regmap */ const struct regmap_irq_chip *rtc_irq_chip; + /* regmap configuration for the chip */ + const struct regmap_config *regmap_config; }; struct max77686_rtc_info { @@ -182,6 +184,11 @@ static const struct regmap_irq_chip max77686_rtc_irq_chip = { .num_irqs = ARRAY_SIZE(max77686_rtc_irqs), }; +static const struct regmap_config max77686_rtc_regmap_config = { + .reg_bits = 8, + .val_bits = 8, +}; + static const struct max77686_rtc_driver_data max77686_drv_data = { .delay = 16000, .mask = 0x7f, @@ -191,6 +198,13 @@ static const struct max77686_rtc_driver_data max77686_drv_data = { .alarm_pending_status_reg = MAX77686_REG_STATUS2, .rtc_i2c_addr = MAX77686_I2C_ADDR_RTC, .rtc_irq_chip = &max77686_rtc_irq_chip, + .regmap_config = &max77686_rtc_regmap_config, +}; + +static const struct regmap_config max77620_rtc_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .use_single_write = true, }; static const struct max77686_rtc_driver_data max77620_drv_data = { @@ -202,6 +216,7 @@ static const struct max77686_rtc_driver_data max77620_drv_data = { .alarm_pending_status_reg = MAX77686_INVALID_REG, .rtc_i2c_addr = MAX77620_I2C_ADDR_RTC, .rtc_irq_chip = &max77686_rtc_irq_chip, + .regmap_config = &max77620_rtc_regmap_config, }; static const unsigned int max77802_map[REG_RTC_END] = { @@ -658,11 +673,6 @@ static int max77686_rtc_init_reg(struct max77686_rtc_info *info) return ret; } -static const struct regmap_config max77686_rtc_regmap_config = { - .reg_bits = 8, - .val_bits = 8, -}; - static int max77686_init_rtc_regmap(struct max77686_rtc_info *info) { struct device *parent = info->dev->parent; @@ -698,7 +708,7 @@ static int max77686_init_rtc_regmap(struct max77686_rtc_info *info) } info->rtc_regmap = devm_regmap_init_i2c(info->rtc, - &max77686_rtc_regmap_config); + info->drv_data->regmap_config); if (IS_ERR(info->rtc_regmap)) { ret = PTR_ERR(info->rtc_regmap); dev_err(info->dev, "Failed to allocate RTC regmap: %d\n", ret); diff --git a/drivers/rtc/rtc-mc13xxx.c b/drivers/rtc/rtc-mc13xxx.c index afce2c0b4bd6..d6802e6191cb 100644 --- a/drivers/rtc/rtc-mc13xxx.c +++ b/drivers/rtc/rtc-mc13xxx.c @@ -308,8 +308,10 @@ static int __init mc13xxx_rtc_probe(struct platform_device *pdev) mc13xxx_unlock(mc13xxx); ret = rtc_register_device(priv->rtc); - if (ret) + if (ret) { + mc13xxx_lock(mc13xxx); goto err_irq_request; + } return 0; diff --git a/drivers/rtc/rtc-mpc5121.c b/drivers/rtc/rtc-mpc5121.c index 3040844129ce..5c2ce71aa044 100644 --- a/drivers/rtc/rtc-mpc5121.c +++ b/drivers/rtc/rtc-mpc5121.c @@ -316,7 +316,7 @@ static int mpc5121_rtc_probe(struct platform_device *op) rtc->regs = devm_platform_ioremap_resource(op, 0); if (IS_ERR(rtc->regs)) { dev_err(&op->dev, "%s: couldn't map io space\n", __func__); - return -ENOSYS; + return PTR_ERR(rtc->regs); } device_init_wakeup(&op->dev, 1); diff --git a/drivers/rtc/rtc-mt2712.c b/drivers/rtc/rtc-mt2712.c index 581b8731fb8a..d5f691c8a035 100644 --- a/drivers/rtc/rtc-mt2712.c +++ b/drivers/rtc/rtc-mt2712.c @@ -310,7 +310,6 @@ static const struct rtc_class_ops mt2712_rtc_ops = { static int mt2712_rtc_probe(struct platform_device *pdev) { - struct resource *res; struct mt2712_rtc *mt2712_rtc; int ret; @@ -319,8 +318,7 @@ static int mt2712_rtc_probe(struct platform_device *pdev) if (!mt2712_rtc) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - mt2712_rtc->base = devm_ioremap_resource(&pdev->dev, res); + mt2712_rtc->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(mt2712_rtc->base)) return PTR_ERR(mt2712_rtc->base); @@ -328,10 +326,8 @@ static int mt2712_rtc_probe(struct platform_device *pdev) mt2712_rtc_hw_init(mt2712_rtc); mt2712_rtc->irq = platform_get_irq(pdev, 0); - if (mt2712_rtc->irq < 0) { - dev_err(&pdev->dev, "No IRQ resource\n"); + if (mt2712_rtc->irq < 0) return mt2712_rtc->irq; - } platform_set_drvdata(pdev, mt2712_rtc); @@ -356,13 +352,7 @@ static int mt2712_rtc_probe(struct platform_device *pdev) mt2712_rtc->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; mt2712_rtc->rtc->range_max = MT2712_RTC_TIMESTAMP_END_2127; - ret = rtc_register_device(mt2712_rtc->rtc); - if (ret) { - dev_err(&pdev->dev, "register rtc device failed\n"); - return ret; - } - - return 0; + return rtc_register_device(mt2712_rtc->rtc); } #ifdef CONFIG_PM_SLEEP diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c index 4e50d6768f13..9c5670776c68 100644 --- a/drivers/rtc/rtc-pcf2127.c +++ b/drivers/rtc/rtc-pcf2127.c @@ -137,8 +137,7 @@ static int pcf2127_rtc_read_time(struct device *dev, struct rtc_time *tm) tm->tm_wday = buf[PCF2127_REG_DW] & 0x07; tm->tm_mon = bcd2bin(buf[PCF2127_REG_MO] & 0x1F) - 1; /* rtc mn 1-12 */ tm->tm_year = bcd2bin(buf[PCF2127_REG_YR]); - if (tm->tm_year < 70) - tm->tm_year += 100; /* assume we are in 1970...2069 */ + tm->tm_year += 100; dev_dbg(dev, "%s: tm is secs=%d, mins=%d, hours=%d, " "mday=%d, mon=%d, year=%d, wday=%d\n", @@ -172,7 +171,7 @@ static int pcf2127_rtc_set_time(struct device *dev, struct rtc_time *tm) buf[i++] = bin2bcd(tm->tm_mon + 1); /* year */ - buf[i++] = bin2bcd(tm->tm_year % 100); + buf[i++] = bin2bcd(tm->tm_year - 100); /* write register's data */ err = regmap_bulk_write(pcf2127->regmap, PCF2127_REG_SC, buf, i); @@ -185,30 +184,35 @@ static int pcf2127_rtc_set_time(struct device *dev, struct rtc_time *tm) return 0; } -#ifdef CONFIG_RTC_INTF_DEV static int pcf2127_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) { struct pcf2127 *pcf2127 = dev_get_drvdata(dev); - int touser; + int val, touser = 0; int ret; switch (cmd) { case RTC_VL_READ: - ret = regmap_read(pcf2127->regmap, PCF2127_REG_CTRL3, &touser); + ret = regmap_read(pcf2127->regmap, PCF2127_REG_CTRL3, &val); if (ret) return ret; - touser = touser & PCF2127_BIT_CTRL3_BLF ? RTC_VL_BACKUP_LOW : 0; + if (val & PCF2127_BIT_CTRL3_BLF) + touser |= RTC_VL_BACKUP_LOW; + + if (val & PCF2127_BIT_CTRL3_BF) + touser |= RTC_VL_BACKUP_SWITCH; return put_user(touser, (unsigned int __user *)arg); + + case RTC_VL_CLR: + return regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL3, + PCF2127_BIT_CTRL3_BF, 0); + default: return -ENOIOCTLCMD; } } -#else -#define pcf2127_rtc_ioctl NULL -#endif static const struct rtc_class_ops pcf2127_rtc_ops = { .ioctl = pcf2127_rtc_ioctl, @@ -433,6 +437,9 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap, return PTR_ERR(pcf2127->rtc); pcf2127->rtc->ops = &pcf2127_rtc_ops; + pcf2127->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; + pcf2127->rtc->range_max = RTC_TIMESTAMP_END_2099; + pcf2127->rtc->set_start_time = true; /* Sets actual start to 1970 */ pcf2127->wdd.parent = dev; pcf2127->wdd.info = &pcf2127_wdt_info; @@ -441,6 +448,7 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap, pcf2127->wdd.max_timeout = PCF2127_WD_VAL_MAX; pcf2127->wdd.timeout = PCF2127_WD_VAL_DEFAULT; pcf2127->wdd.min_hw_heartbeat_ms = 500; + pcf2127->wdd.status = WATCHDOG_NOWAYOUT_INIT_STATUS; watchdog_set_drvdata(&pcf2127->wdd, pcf2127); @@ -495,7 +503,6 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap, */ ret = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL3, PCF2127_BIT_CTRL3_BTSE | - PCF2127_BIT_CTRL3_BF | PCF2127_BIT_CTRL3_BIE | PCF2127_BIT_CTRL3_BLIE, 0); if (ret) { @@ -636,6 +643,7 @@ static int pcf2127_i2c_probe(struct i2c_client *client, static const struct regmap_config config = { .reg_bits = 8, .val_bits = 8, + .max_register = 0x1d, }; if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) @@ -703,6 +711,7 @@ static int pcf2127_spi_probe(struct spi_device *spi) .val_bits = 8, .read_flag_mask = 0xa0, .write_flag_mask = 0x20, + .max_register = 0x1d, }; struct regmap *regmap; diff --git a/drivers/rtc/rtc-rc5t619.c b/drivers/rtc/rtc-rc5t619.c index 24e386ecbc7e..dd1a20977478 100644 --- a/drivers/rtc/rtc-rc5t619.c +++ b/drivers/rtc/rtc-rc5t619.c @@ -356,10 +356,8 @@ static int rc5t619_rtc_probe(struct platform_device *pdev) int err; rtc = devm_kzalloc(dev, sizeof(*rtc), GFP_KERNEL); - if (IS_ERR(rtc)) { - err = PTR_ERR(rtc); + if (!rtc) return -ENOMEM; - } rtc->rn5t618 = rn5t618; diff --git a/drivers/rtc/rtc-rv3028.c b/drivers/rtc/rtc-rv3028.c index a0ddc86c975a..ec84db0b3d7a 100644 --- a/drivers/rtc/rtc-rv3028.c +++ b/drivers/rtc/rtc-rv3028.c @@ -755,6 +755,8 @@ static int rv3028_probe(struct i2c_client *client) return -ENOMEM; rv3028->regmap = devm_regmap_init_i2c(client, ®map_config); + if (IS_ERR(rv3028->regmap)) + return PTR_ERR(rv3028->regmap); i2c_set_clientdata(client, rv3028); diff --git a/drivers/rtc/rtc-snvs.c b/drivers/rtc/rtc-snvs.c index 35ee08aa7584..0263d996b8a8 100644 --- a/drivers/rtc/rtc-snvs.c +++ b/drivers/rtc/rtc-snvs.c @@ -148,10 +148,21 @@ static int snvs_rtc_enable(struct snvs_rtc_data *data, bool enable) static int snvs_rtc_read_time(struct device *dev, struct rtc_time *tm) { struct snvs_rtc_data *data = dev_get_drvdata(dev); - unsigned long time = rtc_read_lp_counter(data); + unsigned long time; + int ret; + + if (data->clk) { + ret = clk_enable(data->clk); + if (ret) + return ret; + } + time = rtc_read_lp_counter(data); rtc_time64_to_tm(time, tm); + if (data->clk) + clk_disable(data->clk); + return 0; } @@ -161,6 +172,12 @@ static int snvs_rtc_set_time(struct device *dev, struct rtc_time *tm) unsigned long time = rtc_tm_to_time64(tm); int ret; + if (data->clk) { + ret = clk_enable(data->clk); + if (ret) + return ret; + } + /* Disable RTC first */ ret = snvs_rtc_enable(data, false); if (ret) @@ -173,6 +190,9 @@ static int snvs_rtc_set_time(struct device *dev, struct rtc_time *tm) /* Enable RTC again */ ret = snvs_rtc_enable(data, true); + if (data->clk) + clk_disable(data->clk); + return ret; } @@ -180,6 +200,13 @@ static int snvs_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) { struct snvs_rtc_data *data = dev_get_drvdata(dev); u32 lptar, lpsr; + int ret; + + if (data->clk) { + ret = clk_enable(data->clk); + if (ret) + return ret; + } regmap_read(data->regmap, data->offset + SNVS_LPTAR, &lptar); rtc_time64_to_tm(lptar, &alrm->time); @@ -187,18 +214,33 @@ static int snvs_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) regmap_read(data->regmap, data->offset + SNVS_LPSR, &lpsr); alrm->pending = (lpsr & SNVS_LPSR_LPTA) ? 1 : 0; + if (data->clk) + clk_disable(data->clk); + return 0; } static int snvs_rtc_alarm_irq_enable(struct device *dev, unsigned int enable) { struct snvs_rtc_data *data = dev_get_drvdata(dev); + int ret; + + if (data->clk) { + ret = clk_enable(data->clk); + if (ret) + return ret; + } regmap_update_bits(data->regmap, data->offset + SNVS_LPCR, (SNVS_LPCR_LPTA_EN | SNVS_LPCR_LPWUI_EN), enable ? (SNVS_LPCR_LPTA_EN | SNVS_LPCR_LPWUI_EN) : 0); - return rtc_write_sync_lp(data); + ret = rtc_write_sync_lp(data); + + if (data->clk) + clk_disable(data->clk); + + return ret; } static int snvs_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) @@ -207,6 +249,12 @@ static int snvs_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) unsigned long time = rtc_tm_to_time64(&alrm->time); int ret; + if (data->clk) { + ret = clk_enable(data->clk); + if (ret) + return ret; + } + regmap_update_bits(data->regmap, data->offset + SNVS_LPCR, SNVS_LPCR_LPTA_EN, 0); ret = rtc_write_sync_lp(data); if (ret) @@ -216,6 +264,9 @@ static int snvs_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) /* Clear alarm interrupt status bit */ regmap_write(data->regmap, data->offset + SNVS_LPSR, SNVS_LPSR_LPTA); + if (data->clk) + clk_disable(data->clk); + return snvs_rtc_alarm_irq_enable(dev, alrm->enabled); } @@ -362,7 +413,7 @@ static int __maybe_unused snvs_rtc_suspend_noirq(struct device *dev) struct snvs_rtc_data *data = dev_get_drvdata(dev); if (data->clk) - clk_disable_unprepare(data->clk); + clk_disable(data->clk); return 0; } @@ -372,7 +423,7 @@ static int __maybe_unused snvs_rtc_resume_noirq(struct device *dev) struct snvs_rtc_data *data = dev_get_drvdata(dev); if (data->clk) - return clk_prepare_enable(data->clk); + return clk_enable(data->clk); return 0; } diff --git a/drivers/rtc/rtc-stmp3xxx.c b/drivers/rtc/rtc-stmp3xxx.c index ff6488be385f..c9bc3d4a1e66 100644 --- a/drivers/rtc/rtc-stmp3xxx.c +++ b/drivers/rtc/rtc-stmp3xxx.c @@ -416,5 +416,5 @@ module_platform_driver(stmp3xxx_rtcdrv); MODULE_DESCRIPTION("STMP3xxx RTC Driver"); MODULE_AUTHOR("dmitry pervushin <dpervushin@embeddedalley.com> and " - "Wolfram Sang <w.sang@pengutronix.de>"); + "Wolfram Sang <kernel@pengutronix.de>"); MODULE_LICENSE("GPL"); diff --git a/include/uapi/linux/rtc.h b/include/uapi/linux/rtc.h index 83bba58d47f4..fa9aff91cbf2 100644 --- a/include/uapi/linux/rtc.h +++ b/include/uapi/linux/rtc.h @@ -99,6 +99,7 @@ struct rtc_pll_info { #define RTC_VL_BACKUP_LOW _BITUL(1) /* Backup voltage is low */ #define RTC_VL_BACKUP_EMPTY _BITUL(2) /* Backup empty or not present */ #define RTC_VL_ACCURACY_LOW _BITUL(3) /* Voltage is low, RTC accuracy is reduced */ +#define RTC_VL_BACKUP_SWITCH _BITUL(4) /* Backup switchover happened */ #define RTC_VL_READ _IOR('p', 0x13, unsigned int) /* Voltage low detection */ #define RTC_VL_CLR _IO('p', 0x14) /* Clear voltage low information */ |