diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2019-09-22 21:05:43 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2019-09-22 21:05:43 +0300 |
commit | 9dbd83f665298c9dcf647f20d6d6488e9019114b (patch) | |
tree | 538712c8f87137989743b22fb4a4ad4345e80572 /drivers/rtc | |
parent | 379bb045171dea3e2ee01b32fe88f2afe1fe2fa8 (diff) | |
parent | b99a3120f9a30e1429d8d634e18da8dff93340c6 (diff) | |
download | linux-9dbd83f665298c9dcf647f20d6d6488e9019114b.tar.xz |
Merge tag 'rtc-5.4' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux
Pull RTC updates from Alexandre Belloni:
"Two new drivers and the new pcf2127 feature make the bulk of the
additions. The rest are the usual fixes and new features.
Subsystem:
- add debug message when registration fails
New drivers:
- Amlogic Virtual Wake
- Freescale FlexTimer Module alarm
Drivers:
- remove superfluous error messages
- convert to i2c_new_dummy_device and devm_i2c_new_dummy_device
- Remove dev_err() usage after platform_get_irq()
- Set RTC range for: pcf2123, pcf8563, snvs.
- pcf2127: tamper detection and watchdog support
- pcf85363: fix regmap issue
- sun6i: H6 support
- remove w90x900/nuc900 driver"
* tag 'rtc-5.4' of git://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux: (51 commits)
rtc: meson: mark PM functions as __maybe_unused
rtc: sc27xx: Remove clearing SPRD_RTC_POWEROFF_ALM_FLAG flag
dt-bindings: rtc: ds1307: add rx8130 compatible
rtc: sun6i: Allow using as wakeup source from suspend
rtc: pcf8563: let the core handle range offsetting
rtc: pcf8563: remove useless indirection
rtc: pcf8563: convert to devm_rtc_allocate_device
rtc: pcf8563: add Microcrystal RV8564 compatible
rtc: pcf8563: add Epson RTC8564 compatible
rtc: s35390a: convert to devm_i2c_new_dummy_device()
rtc: max77686: convert to devm_i2c_new_dummy_device()
rtc: pcf85363/pcf85263: fix regmap error in set_time
rtc: snvs: switch to rtc_time64_to_tm/rtc_tm_to_time64
rtc: snvs: set range
rtc: snvs: fix possible race condition
rtc: pcf2127: bugfix: watchdog build dependency
rtc: pcf2127: add tamper detection support
rtc: pcf2127: add watchdog feature support
rtc: pcf2127: bugfix: read rtc disables watchdog
rtc: pcf2127: cleanup register and bit defines
...
Diffstat (limited to 'drivers/rtc')
58 files changed, 1136 insertions, 722 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index a45175fd8cc4..1adf9f815652 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -373,6 +373,17 @@ config RTC_DRV_MAX77686 This driver can also be built as a module. If so, the module will be called rtc-max77686. +config RTC_DRV_MESON_VRTC + tristate "Amlogic Meson Virtual RTC" + depends on ARCH_MESON || COMPILE_TEST + default m if ARCH_MESON + help + If you say yes here you will get support for the + Virtual RTC of Amlogic SoCs. + + This driver can also be built as a module. If so, the module + will be called rtc-meson-vrtc. + config RTC_DRV_RK808 tristate "Rockchip RK805/RK808/RK809/RK817/RK818 RTC" depends on MFD_RK808 @@ -500,6 +511,7 @@ config RTC_DRV_M41T80_WDT watchdog timer in the ST M41T60 and M41T80 RTC chips series. config RTC_DRV_BD70528 tristate "ROHM BD70528 PMIC RTC" + depends on MFD_ROHM_BD70528 && (BD70528_WATCHDOG || !BD70528_WATCHDOG) help If you say Y here you will get support for the RTC on ROHM BD70528 Power Management IC. @@ -874,9 +886,15 @@ config RTC_DRV_DS3232_HWMON config RTC_DRV_PCF2127 tristate "NXP PCF2127" depends on RTC_I2C_AND_SPI + select WATCHDOG_CORE if WATCHDOG help If you say yes here you get support for the NXP PCF2127/29 RTC - chips. + chips with integrated quartz crystal for industrial applications. + Both chips also have watchdog timer and tamper switch detection + features. + + PCF2127 has an additional feature of 512 bytes battery backed + memory that's accessible using nvmem interface. This driver can also be built as a module. If so, the module will be called rtc-pcf2127. @@ -1247,13 +1265,6 @@ config RTC_DRV_AB8500 Select this to enable the ST-Ericsson AB8500 power management IC RTC support. This chip contains a battery- and capacitor-backed RTC. -config RTC_DRV_NUC900 - tristate "NUC910/NUC920 RTC driver" - depends on ARCH_W90X900 || COMPILE_TEST - help - If you say yes here you get support for the RTC subsystem of the - NUC910/NUC920 used in embedded systems. - config RTC_DRV_OPAL tristate "IBM OPAL RTC driver" depends on PPC_POWERNV @@ -1323,6 +1334,21 @@ config RTC_DRV_IMXDI This driver can also be built as a module, if so, the module will be called "rtc-imxdi". +config RTC_DRV_FSL_FTM_ALARM + tristate "Freescale FlexTimer alarm timer" + depends on ARCH_LAYERSCAPE || SOC_LS1021A + select FSL_RCPM + default y + help + For the FlexTimer in LS1012A, LS1021A, LS1028A, LS1043A, LS1046A, + LS1088A, LS208xA, we can use FTM as the wakeup source. + + Say y here to enable FTM alarm support. The FTM alarm provides + alarm functions for wakeup system from deep sleep. + + This driver can also be built as a module, if so, the module + will be called "rtc-fsl-ftm-alarm". + config RTC_DRV_MESON tristate "Amlogic Meson RTC" depends on (ARM && ARCH_MESON) || COMPILE_TEST diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 6b09c21dc1b6..4ac8f19fb631 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -73,6 +73,7 @@ obj-$(CONFIG_RTC_DRV_EFI) += rtc-efi.o obj-$(CONFIG_RTC_DRV_EM3027) += rtc-em3027.o obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o obj-$(CONFIG_RTC_DRV_FM3130) += rtc-fm3130.o +obj-$(CONFIG_RTC_DRV_FSL_FTM_ALARM) += rtc-fsl-ftm-alarm.o obj-$(CONFIG_RTC_DRV_FTRTC010) += rtc-ftrtc010.o obj-$(CONFIG_RTC_DRV_GENERIC) += rtc-generic.o obj-$(CONFIG_RTC_DRV_GOLDFISH) += rtc-goldfish.o @@ -102,6 +103,7 @@ obj-$(CONFIG_RTC_DRV_MAX8907) += rtc-max8907.o obj-$(CONFIG_RTC_DRV_MAX8925) += rtc-max8925.o obj-$(CONFIG_RTC_DRV_MAX8997) += rtc-max8997.o obj-$(CONFIG_RTC_DRV_MAX8998) += rtc-max8998.o +obj-$(CONFIG_RTC_DRV_MESON_VRTC)+= rtc-meson-vrtc.o obj-$(CONFIG_RTC_DRV_MC13XXX) += rtc-mc13xxx.o obj-$(CONFIG_RTC_DRV_MCP795) += rtc-mcp795.o obj-$(CONFIG_RTC_DRV_MESON) += rtc-meson.o @@ -113,7 +115,6 @@ obj-$(CONFIG_RTC_DRV_MT7622) += rtc-mt7622.o obj-$(CONFIG_RTC_DRV_MV) += rtc-mv.o obj-$(CONFIG_RTC_DRV_MXC) += rtc-mxc.o obj-$(CONFIG_RTC_DRV_MXC_V2) += rtc-mxc_v2.o -obj-$(CONFIG_RTC_DRV_NUC900) += rtc-nuc900.o obj-$(CONFIG_RTC_DRV_OMAP) += rtc-omap.o obj-$(CONFIG_RTC_DRV_OPAL) += rtc-opal.o obj-$(CONFIG_RTC_DRV_PALMAS) += rtc-palmas.o diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index 0f492b0940b3..9458e6d6686a 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c @@ -346,8 +346,10 @@ int __rtc_register_device(struct module *owner, struct rtc_device *rtc) struct rtc_wkalrm alrm; int err; - if (!rtc->ops) + if (!rtc->ops) { + dev_dbg(&rtc->dev, "no ops set\n"); return -EINVAL; + } rtc->owner = owner; rtc_device_get_offset(rtc); diff --git a/drivers/rtc/rtc-88pm80x.c b/drivers/rtc/rtc-88pm80x.c index e4d5a19fd1c9..75779e8501a3 100644 --- a/drivers/rtc/rtc-88pm80x.c +++ b/drivers/rtc/rtc-88pm80x.c @@ -264,7 +264,6 @@ static int pm80x_rtc_probe(struct platform_device *pdev) return -ENOMEM; info->irq = platform_get_irq(pdev, 0); if (info->irq < 0) { - dev_err(&pdev->dev, "No IRQ resource!\n"); ret = -EINVAL; goto out; } @@ -296,10 +295,9 @@ static int pm80x_rtc_probe(struct platform_device *pdev) info->rtc_dev->range_max = U32_MAX; ret = rtc_register_device(info->rtc_dev); - if (ret) { - dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret); + if (ret) goto out_rtc; - } + /* * enable internal XO instead of internal 3.25MHz clock since it can * free running in PMIC power-down state. diff --git a/drivers/rtc/rtc-88pm860x.c b/drivers/rtc/rtc-88pm860x.c index 434285f495e0..4743b16a8d84 100644 --- a/drivers/rtc/rtc-88pm860x.c +++ b/drivers/rtc/rtc-88pm860x.c @@ -328,10 +328,8 @@ static int pm860x_rtc_probe(struct platform_device *pdev) if (!info) return -ENOMEM; info->irq = platform_get_irq(pdev, 0); - if (info->irq < 0) { - dev_err(&pdev->dev, "No IRQ resource!\n"); + if (info->irq < 0) return info->irq; - } info->chip = chip; info->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion; diff --git a/drivers/rtc/rtc-ab-eoz9.c b/drivers/rtc/rtc-ab-eoz9.c index e4f6e0061ccf..d690985caa4c 100644 --- a/drivers/rtc/rtc-ab-eoz9.c +++ b/drivers/rtc/rtc-ab-eoz9.c @@ -390,35 +390,31 @@ static int abeoz9_probe(struct i2c_client *client, if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C | I2C_FUNC_SMBUS_BYTE_DATA | - I2C_FUNC_SMBUS_I2C_BLOCK)) { - ret = -ENODEV; - goto err; - } + I2C_FUNC_SMBUS_I2C_BLOCK)) + return -ENODEV; regmap = devm_regmap_init_i2c(client, &abeoz9_rtc_regmap_config); if (IS_ERR(regmap)) { ret = PTR_ERR(regmap); dev_err(dev, "regmap allocation failed: %d\n", ret); - goto err; + return ret; } data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); - if (!data) { - ret = -ENOMEM; - goto err; - } + if (!data) + return -ENOMEM; data->regmap = regmap; dev_set_drvdata(dev, data); ret = abeoz9_rtc_setup(dev, client->dev.of_node); if (ret) - goto err; + return ret; data->rtc = devm_rtc_allocate_device(dev); ret = PTR_ERR_OR_ZERO(data->rtc); if (ret) - goto err; + return ret; data->rtc->ops = &rtc_ops; data->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; @@ -426,14 +422,10 @@ static int abeoz9_probe(struct i2c_client *client, ret = rtc_register_device(data->rtc); if (ret) - goto err; + return ret; abeoz9_hwmon_register(dev, data); return 0; - -err: - dev_err(dev, "unable to register RTC device (%d)\n", ret); - return ret; } #ifdef CONFIG_OF diff --git a/drivers/rtc/rtc-ac100.c b/drivers/rtc/rtc-ac100.c index 2e5a8b15b222..29223931aba7 100644 --- a/drivers/rtc/rtc-ac100.c +++ b/drivers/rtc/rtc-ac100.c @@ -578,10 +578,8 @@ static int ac100_rtc_probe(struct platform_device *pdev) chip->regmap = ac100->regmap; chip->irq = platform_get_irq(pdev, 0); - if (chip->irq < 0) { - dev_err(&pdev->dev, "No IRQ resource\n"); + if (chip->irq < 0) return chip->irq; - } chip->rtc = devm_rtc_allocate_device(&pdev->dev); if (IS_ERR(chip->rtc)) @@ -612,15 +610,7 @@ static int ac100_rtc_probe(struct platform_device *pdev) if (ret) return ret; - ret = rtc_register_device(chip->rtc); - if (ret) { - dev_err(&pdev->dev, "unable to register device\n"); - return ret; - } - - dev_info(&pdev->dev, "RTC enabled\n"); - - return 0; + return rtc_register_device(chip->rtc); } static int ac100_rtc_remove(struct platform_device *pdev) diff --git a/drivers/rtc/rtc-armada38x.c b/drivers/rtc/rtc-armada38x.c index 19d6980e90fb..9351bd52477e 100644 --- a/drivers/rtc/rtc-armada38x.c +++ b/drivers/rtc/rtc-armada38x.c @@ -502,7 +502,6 @@ static __init int armada38x_rtc_probe(struct platform_device *pdev) struct resource *res; struct armada38x_rtc *rtc; const struct of_device_id *match; - int ret; match = of_match_device(armada38x_rtc_of_match_table, &pdev->dev); if (!match) @@ -530,11 +529,8 @@ static __init int armada38x_rtc_probe(struct platform_device *pdev) return PTR_ERR(rtc->regs_soc); rtc->irq = platform_get_irq(pdev, 0); - - if (rtc->irq < 0) { - dev_err(&pdev->dev, "no irq\n"); + if (rtc->irq < 0) return rtc->irq; - } rtc->rtc_dev = devm_rtc_allocate_device(&pdev->dev); if (IS_ERR(rtc->rtc_dev)) @@ -564,11 +560,7 @@ static __init int armada38x_rtc_probe(struct platform_device *pdev) rtc->rtc_dev->range_max = U32_MAX; - ret = rtc_register_device(rtc->rtc_dev); - if (ret) - dev_err(&pdev->dev, "Failed to register RTC device: %d\n", ret); - - return ret; + return rtc_register_device(rtc->rtc_dev); } #ifdef CONFIG_PM_SLEEP diff --git a/drivers/rtc/rtc-asm9260.c b/drivers/rtc/rtc-asm9260.c index d45a44936308..10413d803caa 100644 --- a/drivers/rtc/rtc-asm9260.c +++ b/drivers/rtc/rtc-asm9260.c @@ -257,10 +257,8 @@ static int asm9260_rtc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, priv); irq_alarm = platform_get_irq(pdev, 0); - if (irq_alarm < 0) { - dev_err(dev, "No alarm IRQ resource defined\n"); + if (irq_alarm < 0) return irq_alarm; - } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); priv->iobase = devm_ioremap_resource(dev, res); diff --git a/drivers/rtc/rtc-aspeed.c b/drivers/rtc/rtc-aspeed.c index af3eb676d7c3..e351d35b29a3 100644 --- a/drivers/rtc/rtc-aspeed.c +++ b/drivers/rtc/rtc-aspeed.c @@ -86,7 +86,6 @@ static int aspeed_rtc_probe(struct platform_device *pdev) { struct aspeed_rtc *rtc; struct resource *res; - int ret; rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL); if (!rtc) @@ -107,11 +106,7 @@ static int aspeed_rtc_probe(struct platform_device *pdev) rtc->rtc_dev->range_min = RTC_TIMESTAMP_BEGIN_1900; rtc->rtc_dev->range_max = 38814989399LL; /* 3199-12-31 23:59:59 */ - ret = rtc_register_device(rtc->rtc_dev); - if (ret) - return ret; - - return 0; + return rtc_register_device(rtc->rtc_dev); } static const struct of_device_id aspeed_rtc_match[] = { diff --git a/drivers/rtc/rtc-at91rm9200.c b/drivers/rtc/rtc-at91rm9200.c index 82a54e93ff04..d119c6e6353e 100644 --- a/drivers/rtc/rtc-at91rm9200.c +++ b/drivers/rtc/rtc-at91rm9200.c @@ -378,10 +378,8 @@ static int __init at91_rtc_probe(struct platform_device *pdev) } irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "no irq resource defined\n"); + if (irq < 0) return -ENXIO; - } at91_rtc_regs = devm_ioremap(&pdev->dev, regs->start, resource_size(regs)); diff --git a/drivers/rtc/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c index 4daf3789b978..bb3ba7bfe6a5 100644 --- a/drivers/rtc/rtc-at91sam9.c +++ b/drivers/rtc/rtc-at91sam9.c @@ -342,10 +342,8 @@ static int at91_rtc_probe(struct platform_device *pdev) struct of_phandle_args args; irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "failed to get interrupt resource\n"); + if (irq < 0) return irq; - } rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL); if (!rtc) diff --git a/drivers/rtc/rtc-bd70528.c b/drivers/rtc/rtc-bd70528.c index f9bdd555e1a2..7744333b0f40 100644 --- a/drivers/rtc/rtc-bd70528.c +++ b/drivers/rtc/rtc-bd70528.c @@ -416,11 +416,8 @@ static int bd70528_probe(struct platform_device *pdev) bd_rtc->dev = &pdev->dev; irq = platform_get_irq_byname(pdev, "bd70528-rtc-alm"); - - if (irq < 0) { - dev_err(&pdev->dev, "Failed to get irq\n"); + if (irq < 0) return irq; - } platform_set_drvdata(pdev, bd_rtc); @@ -479,11 +476,7 @@ static int bd70528_probe(struct platform_device *pdev) return ret; } - ret = rtc_register_device(rtc); - if (ret) - dev_err(&pdev->dev, "Registering RTC failed\n"); - - return ret; + return rtc_register_device(rtc); } static struct platform_driver bd70528_rtc = { diff --git a/drivers/rtc/rtc-brcmstb-waketimer.c b/drivers/rtc/rtc-brcmstb-waketimer.c index 2f65943867f5..3e9800f9878a 100644 --- a/drivers/rtc/rtc-brcmstb-waketimer.c +++ b/drivers/rtc/rtc-brcmstb-waketimer.c @@ -255,10 +255,8 @@ static int brcmstb_waketmr_probe(struct platform_device *pdev) timer->rtc->range_max = U32_MAX; ret = rtc_register_device(timer->rtc); - if (ret) { - dev_err(dev, "unable to register device\n"); + if (ret) goto err_notifier; - } dev_info(dev, "registered, with irq %d\n", timer->irq); diff --git a/drivers/rtc/rtc-cadence.c b/drivers/rtc/rtc-cadence.c index 3b7d643c8a63..592aae23cbaf 100644 --- a/drivers/rtc/rtc-cadence.c +++ b/drivers/rtc/rtc-cadence.c @@ -289,12 +289,8 @@ static int cdns_rtc_probe(struct platform_device *pdev) } crtc->rtc_dev = devm_rtc_allocate_device(&pdev->dev); - if (IS_ERR(crtc->rtc_dev)) { - ret = PTR_ERR(crtc->rtc_dev); - dev_err(&pdev->dev, - "Failed to allocate the RTC device, %d\n", ret); - return ret; - } + if (IS_ERR(crtc->rtc_dev)) + return PTR_ERR(crtc->rtc_dev); platform_set_drvdata(pdev, crtc); @@ -343,11 +339,8 @@ static int cdns_rtc_probe(struct platform_device *pdev) writel(CDNS_RTC_KRTCR_KRTC, crtc->regs + CDNS_RTC_KRTCR); ret = rtc_register_device(crtc->rtc_dev); - if (ret) { - dev_err(&pdev->dev, - "Failed to register the RTC device, %d\n", ret); + if (ret) goto err_disable_wakeup; - } return 0; diff --git a/drivers/rtc/rtc-davinci.c b/drivers/rtc/rtc-davinci.c index fcb71bf4d492..d8e0db2e7fc6 100644 --- a/drivers/rtc/rtc-davinci.c +++ b/drivers/rtc/rtc-davinci.c @@ -477,10 +477,8 @@ static int __init davinci_rtc_probe(struct platform_device *pdev) return -ENOMEM; davinci_rtc->irq = platform_get_irq(pdev, 0); - if (davinci_rtc->irq < 0) { - dev_err(dev, "no RTC irq\n"); + if (davinci_rtc->irq < 0) return davinci_rtc->irq; - } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); davinci_rtc->base = devm_ioremap_resource(dev, res); diff --git a/drivers/rtc/rtc-ds1305.c b/drivers/rtc/rtc-ds1305.c index e04d6e862c42..4420fbf2f8fe 100644 --- a/drivers/rtc/rtc-ds1305.c +++ b/drivers/rtc/rtc-ds1305.c @@ -690,19 +690,16 @@ static int ds1305_probe(struct spi_device *spi) /* register RTC ... from here on, ds1305->ctrl needs locking */ ds1305->rtc = devm_rtc_allocate_device(&spi->dev); - if (IS_ERR(ds1305->rtc)) { + if (IS_ERR(ds1305->rtc)) return PTR_ERR(ds1305->rtc); - } ds1305->rtc->ops = &ds1305_ops; ds1305_nvmem_cfg.priv = ds1305; ds1305->rtc->nvram_old_abi = true; status = rtc_register_device(ds1305->rtc); - if (status) { - dev_dbg(&spi->dev, "register rtc --> %d\n", status); + if (status) return status; - } rtc_nvmem_register(ds1305->rtc, &ds1305_nvmem_cfg); diff --git a/drivers/rtc/rtc-ds1672.c b/drivers/rtc/rtc-ds1672.c index e9e8d02743ee..9da84df9f152 100644 --- a/drivers/rtc/rtc-ds1672.c +++ b/drivers/rtc/rtc-ds1672.c @@ -128,9 +128,6 @@ static int ds1672_probe(struct i2c_client *client, if (err) return err; - if (IS_ERR(rtc)) - return PTR_ERR(rtc); - i2c_set_clientdata(client, rtc); return 0; diff --git a/drivers/rtc/rtc-fsl-ftm-alarm.c b/drivers/rtc/rtc-fsl-ftm-alarm.c new file mode 100644 index 000000000000..8df2075af9a2 --- /dev/null +++ b/drivers/rtc/rtc-fsl-ftm-alarm.c @@ -0,0 +1,337 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Freescale FlexTimer Module (FTM) alarm device driver. + * + * Copyright 2014 Freescale Semiconductor, Inc. + * Copyright 2019 NXP + * + */ + +#include <linux/device.h> +#include <linux/err.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> +#include <linux/platform_device.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/module.h> +#include <linux/fsl/ftm.h> +#include <linux/rtc.h> +#include <linux/time.h> + +#define FTM_SC_CLK(c) ((c) << FTM_SC_CLK_MASK_SHIFT) + +/* + * Select Fixed frequency clock (32KHz) as clock source + * of FlexTimer Module + */ +#define FTM_SC_CLKS_FIXED_FREQ 0x02 +#define FIXED_FREQ_CLK 32000 + +/* Select 128 (2^7) as divider factor */ +#define MAX_FREQ_DIV (1 << FTM_SC_PS_MASK) + +/* Maximum counter value in FlexTimer's CNT registers */ +#define MAX_COUNT_VAL 0xffff + +struct ftm_rtc { + struct rtc_device *rtc_dev; + void __iomem *base; + bool big_endian; + u32 alarm_freq; +}; + +static inline u32 rtc_readl(struct ftm_rtc *dev, u32 reg) +{ + if (dev->big_endian) + return ioread32be(dev->base + reg); + else + return ioread32(dev->base + reg); +} + +static inline void rtc_writel(struct ftm_rtc *dev, u32 reg, u32 val) +{ + if (dev->big_endian) + iowrite32be(val, dev->base + reg); + else + iowrite32(val, dev->base + reg); +} + +static inline void ftm_counter_enable(struct ftm_rtc *rtc) +{ + u32 val; + + /* select and enable counter clock source */ + val = rtc_readl(rtc, FTM_SC); + val &= ~(FTM_SC_PS_MASK | FTM_SC_CLK_MASK); + val |= (FTM_SC_PS_MASK | FTM_SC_CLK(FTM_SC_CLKS_FIXED_FREQ)); + rtc_writel(rtc, FTM_SC, val); +} + +static inline void ftm_counter_disable(struct ftm_rtc *rtc) +{ + u32 val; + + /* disable counter clock source */ + val = rtc_readl(rtc, FTM_SC); + val &= ~(FTM_SC_PS_MASK | FTM_SC_CLK_MASK); + rtc_writel(rtc, FTM_SC, val); +} + +static inline void ftm_irq_acknowledge(struct ftm_rtc *rtc) +{ + unsigned int timeout = 100; + + /* + *Fix errata A-007728 for flextimer + * If the FTM counter reaches the FTM_MOD value between + * the reading of the TOF bit and the writing of 0 to + * the TOF bit, the process of clearing the TOF bit + * does not work as expected when FTMx_CONF[NUMTOF] != 0 + * and the current TOF count is less than FTMx_CONF[NUMTOF]. + * If the above condition is met, the TOF bit remains set. + * If the TOF interrupt is enabled (FTMx_SC[TOIE] = 1),the + * TOF interrupt also remains asserted. + * + * Above is the errata discription + * + * In one word: software clearing TOF bit not works when + * FTMx_CONF[NUMTOF] was seted as nonzero and FTM counter + * reaches the FTM_MOD value. + * + * The workaround is clearing TOF bit until it works + * (FTM counter doesn't always reache the FTM_MOD anyway), + * which may cost some cycles. + */ + while ((FTM_SC_TOF & rtc_readl(rtc, FTM_SC)) && timeout--) + rtc_writel(rtc, FTM_SC, rtc_readl(rtc, FTM_SC) & (~FTM_SC_TOF)); +} + +static inline void ftm_irq_enable(struct ftm_rtc *rtc) +{ + u32 val; + + val = rtc_readl(rtc, FTM_SC); + val |= FTM_SC_TOIE; + rtc_writel(rtc, FTM_SC, val); +} + +static inline void ftm_irq_disable(struct ftm_rtc *rtc) +{ + u32 val; + + val = rtc_readl(rtc, FTM_SC); + val &= ~FTM_SC_TOIE; + rtc_writel(rtc, FTM_SC, val); +} + +static inline void ftm_reset_counter(struct ftm_rtc *rtc) +{ + /* + * The CNT register contains the FTM counter value. + * Reset clears the CNT register. Writing any value to COUNT + * updates the counter with its initial value, CNTIN. + */ + rtc_writel(rtc, FTM_CNT, 0x00); +} + +static void ftm_clean_alarm(struct ftm_rtc *rtc) +{ + ftm_counter_disable(rtc); + + rtc_writel(rtc, FTM_CNTIN, 0x00); + rtc_writel(rtc, FTM_MOD, ~0U); + + ftm_reset_counter(rtc); +} + +static irqreturn_t ftm_rtc_alarm_interrupt(int irq, void *dev) +{ + struct ftm_rtc *rtc = dev; + + ftm_irq_acknowledge(rtc); + ftm_irq_disable(rtc); + ftm_clean_alarm(rtc); + + return IRQ_HANDLED; +} + +static int ftm_rtc_alarm_irq_enable(struct device *dev, + unsigned int enabled) +{ + struct ftm_rtc *rtc = dev_get_drvdata(dev); + + if (enabled) + ftm_irq_enable(rtc); + else + ftm_irq_disable(rtc); + + return 0; +} + +/* + * Note: + * The function is not really getting time from the RTC + * since FlexTimer is not a RTC device, but we need to + * get time to setup alarm, so we are using system time + * for now. + */ +static int ftm_rtc_read_time(struct device *dev, struct rtc_time *tm) +{ + struct timespec64 ts64; + + ktime_get_real_ts64(&ts64); + rtc_time_to_tm(ts64.tv_sec, tm); + + return 0; +} + +static int ftm_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) +{ + return 0; +} + +/* + * 1. Select fixed frequency clock (32KHz) as clock source; + * 2. Select 128 (2^7) as divider factor; + * So clock is 250 Hz (32KHz/128). + * + * 3. FlexTimer's CNT register is a 32bit register, + * but the register's 16 bit as counter value,it's other 16 bit + * is reserved.So minimum counter value is 0x0,maximum counter + * value is 0xffff. + * So max alarm value is 262 (65536 / 250) seconds + */ +static int ftm_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) +{ + struct rtc_time tm; + unsigned long now, alm_time, cycle; + struct ftm_rtc *rtc = dev_get_drvdata(dev); + + ftm_rtc_read_time(dev, &tm); + rtc_tm_to_time(&tm, &now); + rtc_tm_to_time(&alm->time, &alm_time); + + ftm_clean_alarm(rtc); + cycle = (alm_time - now) * rtc->alarm_freq; + if (cycle > MAX_COUNT_VAL) { + pr_err("Out of alarm range {0~262} seconds.\n"); + return -ERANGE; + } + + ftm_irq_disable(rtc); + + /* + * The counter increments until the value of MOD is reached, + * at which point the counter is reloaded with the value of CNTIN. + * The TOF (the overflow flag) bit is set when the FTM counter + * changes from MOD to CNTIN. So we should using the cycle - 1. + */ + rtc_writel(rtc, FTM_MOD, cycle - 1); + + ftm_counter_enable(rtc); + ftm_irq_enable(rtc); + + return 0; + +} + +static const struct rtc_class_ops ftm_rtc_ops = { + .read_time = ftm_rtc_read_time, + .read_alarm = ftm_rtc_read_alarm, + .set_alarm = ftm_rtc_set_alarm, + .alarm_irq_enable = ftm_rtc_alarm_irq_enable, +}; + +static int ftm_rtc_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct resource *r; + int irq; + int ret; + struct ftm_rtc *rtc; + + rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL); + if (unlikely(!rtc)) { + dev_err(&pdev->dev, "cannot alloc memory for rtc\n"); + return -ENOMEM; + } + + platform_set_drvdata(pdev, rtc); + + rtc->rtc_dev = devm_rtc_allocate_device(&pdev->dev); + if (IS_ERR(rtc->rtc_dev)) + return PTR_ERR(rtc->rtc_dev); + + r = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!r) { + dev_err(&pdev->dev, "cannot get resource for rtc\n"); + return -ENODEV; + } + + rtc->base = devm_ioremap_resource(&pdev->dev, r); + if (IS_ERR(rtc->base)) { + dev_err(&pdev->dev, "cannot ioremap resource for rtc\n"); + return PTR_ERR(rtc->base); + } + + irq = irq_of_parse_and_map(np, 0); + if (irq <= 0) { + dev_err(&pdev->dev, "unable to get IRQ from DT, %d\n", irq); + return -EINVAL; + } + + ret = devm_request_irq(&pdev->dev, irq, ftm_rtc_alarm_interrupt, + IRQF_NO_SUSPEND, dev_name(&pdev->dev), rtc); + if (ret < 0) { + dev_err(&pdev->dev, "failed to request irq\n"); + return ret; + } + + rtc->big_endian = of_property_read_bool(np, "big-endian"); + rtc->alarm_freq = (u32)FIXED_FREQ_CLK / (u32)MAX_FREQ_DIV; + rtc->rtc_dev->ops = &ftm_rtc_ops; + + device_init_wakeup(&pdev->dev, true); + + ret = rtc_register_device(rtc->rtc_dev); + if (ret) { + dev_err(&pdev->dev, "can't register rtc device\n"); + return ret; + } + + return 0; +} + +static const struct of_device_id ftm_rtc_match[] = { + { .compatible = "fsl,ls1012a-ftm-alarm", }, + { .compatible = "fsl,ls1021a-ftm-alarm", }, + { .compatible = "fsl,ls1028a-ftm-alarm", }, + { .compatible = "fsl,ls1043a-ftm-alarm", }, + { .compatible = "fsl,ls1046a-ftm-alarm", }, + { .compatible = "fsl,ls1088a-ftm-alarm", }, + { .compatible = "fsl,ls208xa-ftm-alarm", }, + { .compatible = "fsl,lx2160a-ftm-alarm", }, + { }, +}; + +static struct platform_driver ftm_rtc_driver = { + .probe = ftm_rtc_probe, + .driver = { + .name = "ftm-alarm", + .of_match_table = ftm_rtc_match, + }, +}; + +static int __init ftm_alarm_init(void) +{ + return platform_driver_register(&ftm_rtc_driver); +} + +device_initcall(ftm_alarm_init); + +MODULE_DESCRIPTION("NXP/Freescale FlexTimer alarm driver"); +MODULE_AUTHOR("Biwen Li <biwen.li@nxp.com>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/rtc-imx-sc.c b/drivers/rtc/rtc-imx-sc.c index c933045fe04b..cf2c12107f2b 100644 --- a/drivers/rtc/rtc-imx-sc.c +++ b/drivers/rtc/rtc-imx-sc.c @@ -167,10 +167,8 @@ static int imx_sc_rtc_probe(struct platform_device *pdev) imx_sc_rtc->range_max = U32_MAX; ret = rtc_register_device(imx_sc_rtc); - if (ret) { - dev_err(&pdev->dev, "failed to register rtc: %d\n", ret); + if (ret) return ret; - } imx_scu_irq_register_notifier(&imx_sc_rtc_alarm_sc_notifier); diff --git a/drivers/rtc/rtc-imxdi.c b/drivers/rtc/rtc-imxdi.c index 3f3d652a0b0f..f21dc6b16d88 100644 --- a/drivers/rtc/rtc-imxdi.c +++ b/drivers/rtc/rtc-imxdi.c @@ -740,7 +740,6 @@ static void dryice_work(struct work_struct *work) */ static int __init dryice_rtc_probe(struct platform_device *pdev) { - struct resource *res; struct imxdi_dev *imxdi; int norm_irq, sec_irq; int rc; @@ -751,8 +750,7 @@ static int __init dryice_rtc_probe(struct platform_device *pdev) imxdi->pdev = pdev; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - imxdi->ioaddr = devm_ioremap_resource(&pdev->dev, res); + imxdi->ioaddr = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(imxdi->ioaddr)) return PTR_ERR(imxdi->ioaddr); diff --git a/drivers/rtc/rtc-isl12026.c b/drivers/rtc/rtc-isl12026.c index 97f594f9667c..5b6b17fb6d62 100644 --- a/drivers/rtc/rtc-isl12026.c +++ b/drivers/rtc/rtc-isl12026.c @@ -454,9 +454,9 @@ static int isl12026_probe_new(struct i2c_client *client) isl12026_force_power_modes(client); - priv->nvm_client = i2c_new_dummy(client->adapter, ISL12026_EEPROM_ADDR); - if (!priv->nvm_client) - return -ENOMEM; + priv->nvm_client = i2c_new_dummy_device(client->adapter, ISL12026_EEPROM_ADDR); + if (IS_ERR(priv->nvm_client)) + return PTR_ERR(priv->nvm_client); priv->rtc = devm_rtc_allocate_device(&client->dev); ret = PTR_ERR_OR_ZERO(priv->rtc); diff --git a/drivers/rtc/rtc-jz4740.c b/drivers/rtc/rtc-jz4740.c index 9e7b3a04debc..3089645e0ce8 100644 --- a/drivers/rtc/rtc-jz4740.c +++ b/drivers/rtc/rtc-jz4740.c @@ -323,10 +323,8 @@ static int jz4740_rtc_probe(struct platform_device *pdev) rtc->type = id->driver_data; rtc->irq = platform_get_irq(pdev, 0); - if (rtc->irq < 0) { - dev_err(&pdev->dev, "Failed to get platform irq\n"); + if (rtc->irq < 0) return -ENOENT; - } mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); rtc->base = devm_ioremap_resource(&pdev->dev, mem); @@ -362,10 +360,8 @@ static int jz4740_rtc_probe(struct platform_device *pdev) rtc->rtc->range_max = U32_MAX; ret = rtc_register_device(rtc->rtc); - if (ret) { - dev_err(&pdev->dev, "Failed to register rtc device: %d\n", ret); + if (ret) return ret; - } ret = devm_request_irq(&pdev->dev, rtc->irq, jz4740_rtc_irq, 0, pdev->name, rtc); diff --git a/drivers/rtc/rtc-max77686.c b/drivers/rtc/rtc-max77686.c index 4aff349ae301..d5a0e27dd0a0 100644 --- a/drivers/rtc/rtc-max77686.c +++ b/drivers/rtc/rtc-max77686.c @@ -673,11 +673,8 @@ static int max77686_init_rtc_regmap(struct max77686_rtc_info *info) struct platform_device *pdev = to_platform_device(info->dev); info->rtc_irq = platform_get_irq(pdev, 0); - if (info->rtc_irq < 0) { - dev_err(info->dev, "Failed to get rtc interrupts: %d\n", - info->rtc_irq); + if (info->rtc_irq < 0) return info->rtc_irq; - } } else { info->rtc_irq = parent_i2c->irq; } @@ -693,11 +690,11 @@ static int max77686_init_rtc_regmap(struct max77686_rtc_info *info) goto add_rtc_irq; } - info->rtc = i2c_new_dummy(parent_i2c->adapter, - info->drv_data->rtc_i2c_addr); - if (!info->rtc) { + info->rtc = devm_i2c_new_dummy_device(info->dev, parent_i2c->adapter, + info->drv_data->rtc_i2c_addr); + if (IS_ERR(info->rtc)) { dev_err(info->dev, "Failed to allocate I2C device for RTC\n"); - return -ENODEV; + return PTR_ERR(info->rtc); } info->rtc_regmap = devm_regmap_init_i2c(info->rtc, @@ -705,7 +702,7 @@ static int max77686_init_rtc_regmap(struct max77686_rtc_info *info) if (IS_ERR(info->rtc_regmap)) { ret = PTR_ERR(info->rtc_regmap); dev_err(info->dev, "Failed to allocate RTC regmap: %d\n", ret); - goto err_unregister_i2c; + return ret; } add_rtc_irq: @@ -715,15 +712,10 @@ add_rtc_irq: &info->rtc_irq_data); if (ret < 0) { dev_err(info->dev, "Failed to add RTC irq chip: %d\n", ret); - goto err_unregister_i2c; + return ret; } return 0; - -err_unregister_i2c: - if (info->rtc) - i2c_unregister_device(info->rtc); - return ret; } static int max77686_rtc_probe(struct platform_device *pdev) @@ -786,8 +778,6 @@ static int max77686_rtc_probe(struct platform_device *pdev) err_rtc: regmap_del_irq_chip(info->rtc_irq, info->rtc_irq_data); - if (info->rtc) - i2c_unregister_device(info->rtc); return ret; } @@ -798,8 +788,6 @@ static int max77686_rtc_remove(struct platform_device *pdev) free_irq(info->virq, info); regmap_del_irq_chip(info->rtc_irq, info->rtc_irq_data); - if (info->rtc) - i2c_unregister_device(info->rtc); return 0; } diff --git a/drivers/rtc/rtc-meson-vrtc.c b/drivers/rtc/rtc-meson-vrtc.c new file mode 100644 index 000000000000..89e5ba0dae69 --- /dev/null +++ b/drivers/rtc/rtc-meson-vrtc.c @@ -0,0 +1,155 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2019 BayLibre, SAS + * Author: Neil Armstrong <narmstrong@baylibre.com> + * Copyright (C) 2015 Amlogic, Inc. All rights reserved. + */ +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/rtc.h> +#include <linux/io.h> +#include <linux/of.h> +#include <linux/time64.h> + +struct meson_vrtc_data { + void __iomem *io_alarm; + struct rtc_device *rtc; + unsigned long alarm_time; + bool enabled; +}; + +static int meson_vrtc_read_time(struct device *dev, struct rtc_time *tm) +{ + struct timespec64 time; + + dev_dbg(dev, "%s\n", __func__); + ktime_get_raw_ts64(&time); + rtc_time64_to_tm(time.tv_sec, tm); + + return 0; +} + +static void meson_vrtc_set_wakeup_time(struct meson_vrtc_data *vrtc, + unsigned long time) +{ + writel_relaxed(time, vrtc->io_alarm); +} + +static int meson_vrtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) +{ + struct meson_vrtc_data *vrtc = dev_get_drvdata(dev); + + dev_dbg(dev, "%s: alarm->enabled=%d\n", __func__, alarm->enabled); + if (alarm->enabled) + vrtc->alarm_time = rtc_tm_to_time64(&alarm->time); + else + vrtc->alarm_time = 0; + + return 0; +} + +static int meson_vrtc_alarm_irq_enable(struct device *dev, unsigned int enabled) +{ + struct meson_vrtc_data *vrtc = dev_get_drvdata(dev); + + vrtc->enabled = enabled; + return 0; +} + +static const struct rtc_class_ops meson_vrtc_ops = { + .read_time = meson_vrtc_read_time, + .set_alarm = meson_vrtc_set_alarm, + .alarm_irq_enable = meson_vrtc_alarm_irq_enable, +}; + +static int meson_vrtc_probe(struct platform_device *pdev) +{ + struct meson_vrtc_data *vrtc; + int ret; + + vrtc = devm_kzalloc(&pdev->dev, sizeof(*vrtc), GFP_KERNEL); + if (!vrtc) + return -ENOMEM; + + vrtc->io_alarm = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(vrtc->io_alarm)) + return PTR_ERR(vrtc->io_alarm); + + device_init_wakeup(&pdev->dev, 1); + + platform_set_drvdata(pdev, vrtc); + + vrtc->rtc = devm_rtc_allocate_device(&pdev->dev); + if (IS_ERR(vrtc->rtc)) + return PTR_ERR(vrtc->rtc); + + vrtc->rtc->ops = &meson_vrtc_ops; + ret = rtc_register_device(vrtc->rtc); + if (ret) + return ret; + + return 0; +} + +static int __maybe_unused meson_vrtc_suspend(struct device *dev) +{ + struct meson_vrtc_data *vrtc = dev_get_drvdata(dev); + + dev_dbg(dev, "%s\n", __func__); + if (vrtc->alarm_time) { + unsigned long local_time; + long alarm_secs; + struct timespec64 time; + + ktime_get_raw_ts64(&time); + local_time = time.tv_sec; + + dev_dbg(dev, "alarm_time = %lus, local_time=%lus\n", + vrtc->alarm_time, local_time); + alarm_secs = vrtc->alarm_time - local_time; + if (alarm_secs > 0) { + meson_vrtc_set_wakeup_time(vrtc, alarm_secs); + dev_dbg(dev, "system will wakeup in %lds.\n", + alarm_secs); + } else { + dev_err(dev, "alarm time already passed: %lds.\n", + alarm_secs); + } + } + + return 0; +} + +static int __maybe_unused meson_vrtc_resume(struct device *dev) +{ + struct meson_vrtc_data *vrtc = dev_get_drvdata(dev); + + dev_dbg(dev, "%s\n", __func__); + + vrtc->alarm_time = 0; + meson_vrtc_set_wakeup_time(vrtc, 0); + return 0; +} + +static SIMPLE_DEV_PM_OPS(meson_vrtc_pm_ops, + meson_vrtc_suspend, meson_vrtc_resume); + +static const struct of_device_id meson_vrtc_dt_match[] = { + { .compatible = "amlogic,meson-vrtc"}, + {}, +}; +MODULE_DEVICE_TABLE(of, meson_vrtc_dt_match); + +static struct platform_driver meson_vrtc_driver = { + .probe = meson_vrtc_probe, + .driver = { + .name = "meson-vrtc", + .of_match_table = meson_vrtc_dt_match, + .pm = &meson_vrtc_pm_ops, + }, +}; + +module_platform_driver(meson_vrtc_driver); + +MODULE_DESCRIPTION("Amlogic Virtual Wakeup RTC Timer driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/rtc/rtc-mt6397.c b/drivers/rtc/rtc-mt6397.c index b46ed4dc7015..704229eb0cac 100644 --- a/drivers/rtc/rtc-mt6397.c +++ b/drivers/rtc/rtc-mt6397.c @@ -343,10 +343,8 @@ static int mtk_rtc_probe(struct platform_device *pdev) 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"); + if (ret) goto out_free_irq; - } return 0; diff --git a/drivers/rtc/rtc-mt7622.c b/drivers/rtc/rtc-mt7622.c index 82b0816ec6c1..16bd26b5aa6f 100644 --- a/drivers/rtc/rtc-mt7622.c +++ b/drivers/rtc/rtc-mt7622.c @@ -329,7 +329,6 @@ static int mtk_rtc_probe(struct platform_device *pdev) hw->irq = platform_get_irq(pdev, 0); if (hw->irq < 0) { - dev_err(&pdev->dev, "No IRQ resource\n"); ret = hw->irq; goto err; } diff --git a/drivers/rtc/rtc-mxc.c b/drivers/rtc/rtc-mxc.c index e697e96612bb..902d57dcd0d4 100644 --- a/drivers/rtc/rtc-mxc.c +++ b/drivers/rtc/rtc-mxc.c @@ -184,8 +184,9 @@ static void mxc_rtc_irq_enable(struct device *dev, unsigned int bit, struct rtc_plat_data *pdata = dev_get_drvdata(dev); void __iomem *ioaddr = pdata->ioaddr; u32 reg; + unsigned long flags; - spin_lock_irq(&pdata->rtc->irq_lock); + spin_lock_irqsave(&pdata->rtc->irq_lock, flags); reg = readw(ioaddr + RTC_RTCIENR); if (enabled) @@ -194,7 +195,7 @@ static void mxc_rtc_irq_enable(struct device *dev, unsigned int bit, reg &= ~bit; writew(reg, ioaddr + RTC_RTCIENR); - spin_unlock_irq(&pdata->rtc->irq_lock); + spin_unlock_irqrestore(&pdata->rtc->irq_lock, flags); } /* This function is the RTC interrupt service routine. */ diff --git a/drivers/rtc/rtc-mxc_v2.c b/drivers/rtc/rtc-mxc_v2.c index 5b970a816631..91534560fe2a 100644 --- a/drivers/rtc/rtc-mxc_v2.c +++ b/drivers/rtc/rtc-mxc_v2.c @@ -279,7 +279,6 @@ static int mxc_rtc_wait_for_flag(void __iomem *ioaddr, int flag) static int mxc_rtc_probe(struct platform_device *pdev) { struct mxc_rtc_data *pdata; - struct resource *res; void __iomem *ioaddr; int ret = 0; @@ -287,8 +286,7 @@ static int mxc_rtc_probe(struct platform_device *pdev) if (!pdata) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - pdata->ioaddr = devm_ioremap_resource(&pdev->dev, res); + pdata->ioaddr = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(pdata->ioaddr)) return PTR_ERR(pdata->ioaddr); diff --git a/drivers/rtc/rtc-nuc900.c b/drivers/rtc/rtc-nuc900.c deleted file mode 100644 index 49cc4058614d..000000000000 --- a/drivers/rtc/rtc-nuc900.c +++ /dev/null @@ -1,271 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2008-2009 Nuvoton technology corporation. - * - * Wan ZongShun <mcuos.com@gmail.com> - */ - -#include <linux/module.h> -#include <linux/init.h> -#include <linux/platform_device.h> -#include <linux/slab.h> -#include <linux/rtc.h> -#include <linux/delay.h> -#include <linux/io.h> -#include <linux/bcd.h> - -/* RTC Control Registers */ -#define REG_RTC_INIR 0x00 -#define REG_RTC_AER 0x04 -#define REG_RTC_FCR 0x08 -#define REG_RTC_TLR 0x0C -#define REG_RTC_CLR 0x10 -#define REG_RTC_TSSR 0x14 -#define REG_RTC_DWR 0x18 -#define REG_RTC_TAR 0x1C -#define REG_RTC_CAR 0x20 -#define REG_RTC_LIR 0x24 -#define REG_RTC_RIER 0x28 -#define REG_RTC_RIIR 0x2C -#define REG_RTC_TTR 0x30 - -#define RTCSET 0x01 -#define AERRWENB 0x10000 -#define INIRRESET 0xa5eb1357 -#define AERPOWERON 0xA965 -#define AERPOWEROFF 0x0000 -#define LEAPYEAR 0x0001 -#define TICKENB 0x80 -#define TICKINTENB 0x0002 -#define ALARMINTENB 0x0001 -#define MODE24 0x0001 - -struct nuc900_rtc { - int irq_num; - void __iomem *rtc_reg; - struct rtc_device *rtcdev; -}; - -struct nuc900_bcd_time { - int bcd_sec; - int bcd_min; - int bcd_hour; - int bcd_mday; - int bcd_mon; - int bcd_year; -}; - -static irqreturn_t nuc900_rtc_interrupt(int irq, void *_rtc) -{ - struct nuc900_rtc *rtc = _rtc; - unsigned long events = 0, rtc_irq; - - rtc_irq = __raw_readl(rtc->rtc_reg + REG_RTC_RIIR); - - if (rtc_irq & ALARMINTENB) { - rtc_irq &= ~ALARMINTENB; - __raw_writel(rtc_irq, rtc->rtc_reg + REG_RTC_RIIR); - events |= RTC_AF | RTC_IRQF; - } - - if (rtc_irq & TICKINTENB) { - rtc_irq &= ~TICKINTENB; - __raw_writel(rtc_irq, rtc->rtc_reg + REG_RTC_RIIR); - events |= RTC_UF | RTC_IRQF; - } - - rtc_update_irq(rtc->rtcdev, 1, events); - - return IRQ_HANDLED; -} - -static int *check_rtc_access_enable(struct nuc900_rtc *nuc900_rtc) -{ - unsigned int timeout = 0x1000; - __raw_writel(INIRRESET, nuc900_rtc->rtc_reg + REG_RTC_INIR); - - mdelay(10); - - __raw_writel(AERPOWERON, nuc900_rtc->rtc_reg + REG_RTC_AER); - - while (!(__raw_readl(nuc900_rtc->rtc_reg + REG_RTC_AER) & AERRWENB) - && --timeout) - mdelay(1); - - if (!timeout) - return ERR_PTR(-EPERM); - - return NULL; -} - -static void nuc900_rtc_bcd2bin(unsigned int timereg, - unsigned int calreg, struct rtc_time *tm) -{ - tm->tm_mday = bcd2bin(calreg >> 0); - tm->tm_mon = bcd2bin(calreg >> 8); - tm->tm_year = bcd2bin(calreg >> 16) + 100; - - tm->tm_sec = bcd2bin(timereg >> 0); - tm->tm_min = bcd2bin(timereg >> 8); - tm->tm_hour = bcd2bin(timereg >> 16); -} - -static void nuc900_rtc_bin2bcd(struct device *dev, struct rtc_time *settm, - struct nuc900_bcd_time *gettm) -{ - gettm->bcd_mday = bin2bcd(settm->tm_mday) << 0; - gettm->bcd_mon = bin2bcd(settm->tm_mon) << 8; - - if (settm->tm_year < 100) { - dev_warn(dev, "The year will be between 1970-1999, right?\n"); - gettm->bcd_year = bin2bcd(settm->tm_year) << 16; - } else { - gettm->bcd_year = bin2bcd(settm->tm_year - 100) << 16; - } - - gettm->bcd_sec = bin2bcd(settm->tm_sec) << 0; - gettm->bcd_min = bin2bcd(settm->tm_min) << 8; - gettm->bcd_hour = bin2bcd(settm->tm_hour) << 16; -} - -static int nuc900_alarm_irq_enable(struct device *dev, unsigned int enabled) -{ - struct nuc900_rtc *rtc = dev_get_drvdata(dev); - - if (enabled) - __raw_writel(__raw_readl(rtc->rtc_reg + REG_RTC_RIER)| - (ALARMINTENB), rtc->rtc_reg + REG_RTC_RIER); - else - __raw_writel(__raw_readl(rtc->rtc_reg + REG_RTC_RIER)& - (~ALARMINTENB), rtc->rtc_reg + REG_RTC_RIER); - - return 0; -} - -static int nuc900_rtc_read_time(struct device *dev, struct rtc_time *tm) -{ - struct nuc900_rtc *rtc = dev_get_drvdata(dev); - unsigned int timeval, clrval; - - timeval = __raw_readl(rtc->rtc_reg + REG_RTC_TLR); - clrval = __raw_readl(rtc->rtc_reg + REG_RTC_CLR); - - nuc900_rtc_bcd2bin(timeval, clrval, tm); - - return 0; -} - -static int nuc900_rtc_set_time(struct device *dev, struct rtc_time *tm) -{ - struct nuc900_rtc *rtc = dev_get_drvdata(dev); - struct nuc900_bcd_time gettm; - unsigned long val; - int *err; - - nuc900_rtc_bin2bcd(dev, tm, &gettm); - - err = check_rtc_access_enable(rtc); - if (IS_ERR(err)) - return PTR_ERR(err); - - val = gettm.bcd_mday | gettm.bcd_mon | gettm.bcd_year; - __raw_writel(val, rtc->rtc_reg + REG_RTC_CLR); - - val = gettm.bcd_sec | gettm.bcd_min | gettm.bcd_hour; - __raw_writel(val, rtc->rtc_reg + REG_RTC_TLR); - - return 0; -} - -static int nuc900_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) -{ - struct nuc900_rtc *rtc = dev_get_drvdata(dev); - unsigned int timeval, carval; - - timeval = __raw_readl(rtc->rtc_reg + REG_RTC_TAR); - carval = __raw_readl(rtc->rtc_reg + REG_RTC_CAR); - - nuc900_rtc_bcd2bin(timeval, carval, &alrm->time); - - return rtc_valid_tm(&alrm->time); -} - -static int nuc900_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) -{ - struct nuc900_rtc *rtc = dev_get_drvdata(dev); - struct nuc900_bcd_time tm; - unsigned long val; - int *err; - - nuc900_rtc_bin2bcd(dev, &alrm->time, &tm); - - err = check_rtc_access_enable(rtc); - if (IS_ERR(err)) - return PTR_ERR(err); - - val = tm.bcd_mday | tm.bcd_mon | tm.bcd_year; - __raw_writel(val, rtc->rtc_reg + REG_RTC_CAR); - - val = tm.bcd_sec | tm.bcd_min | tm.bcd_hour; - __raw_writel(val, rtc->rtc_reg + REG_RTC_TAR); - - return 0; -} - -static const struct rtc_class_ops nuc900_rtc_ops = { - .read_time = nuc900_rtc_read_time, - .set_time = nuc900_rtc_set_time, - .read_alarm = nuc900_rtc_read_alarm, - .set_alarm = nuc900_rtc_set_alarm, - .alarm_irq_enable = nuc900_alarm_irq_enable, -}; - -static int __init nuc900_rtc_probe(struct platform_device *pdev) -{ - struct resource *res; - struct nuc900_rtc *nuc900_rtc; - - nuc900_rtc = devm_kzalloc(&pdev->dev, sizeof(struct nuc900_rtc), - GFP_KERNEL); - if (!nuc900_rtc) - return -ENOMEM; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - nuc900_rtc->rtc_reg = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(nuc900_rtc->rtc_reg)) - return PTR_ERR(nuc900_rtc->rtc_reg); - - platform_set_drvdata(pdev, nuc900_rtc); - - nuc900_rtc->rtcdev = devm_rtc_device_register(&pdev->dev, pdev->name, - &nuc900_rtc_ops, THIS_MODULE); - if (IS_ERR(nuc900_rtc->rtcdev)) { - dev_err(&pdev->dev, "rtc device register failed\n"); - return PTR_ERR(nuc900_rtc->rtcdev); - } - - __raw_writel(__raw_readl(nuc900_rtc->rtc_reg + REG_RTC_TSSR) | MODE24, - nuc900_rtc->rtc_reg + REG_RTC_TSSR); - - nuc900_rtc->irq_num = platform_get_irq(pdev, 0); - if (devm_request_irq(&pdev->dev, nuc900_rtc->irq_num, - nuc900_rtc_interrupt, 0, "nuc900rtc", nuc900_rtc)) { - dev_err(&pdev->dev, "NUC900 RTC request irq failed\n"); - return -EBUSY; - } - - return 0; -} - -static struct platform_driver nuc900_rtc_driver = { - .driver = { - .name = "nuc900-rtc", - }, -}; - -module_platform_driver_probe(nuc900_rtc_driver, nuc900_rtc_probe); - -MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>"); -MODULE_DESCRIPTION("nuc910/nuc920 RTC driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:nuc900-rtc"); diff --git a/drivers/rtc/rtc-pcf2123.c b/drivers/rtc/rtc-pcf2123.c index fb542a930bf0..c3691fa4210e 100644 --- a/drivers/rtc/rtc-pcf2123.c +++ b/drivers/rtc/rtc-pcf2123.c @@ -82,7 +82,7 @@ #define OSC_HAS_STOPPED BIT(7) /* Clock has been stopped */ /* PCF2123_REG_ALRM_XX BITS */ -#define ALRM_ENABLE BIT(7) /* MN, HR, DM, or DW alarm enable */ +#define ALRM_DISABLE BIT(7) /* MN, HR, DM, or DW alarm matching */ /* PCF2123_REG_TMR_CLKOUT BITS */ #define CD_TMR_4096KHZ (0) /* 4096 KHz countdown timer */ @@ -104,7 +104,7 @@ static struct spi_driver pcf2123_driver; -struct pcf2123_plat_data { +struct pcf2123_data { struct rtc_device *rtc; struct regmap *map; }; @@ -119,11 +119,11 @@ static const struct regmap_config pcf2123_regmap_config = { static int pcf2123_read_offset(struct device *dev, long *offset) { - struct pcf2123_plat_data *pdata = dev_get_platdata(dev); + struct pcf2123_data *pcf2123 = dev_get_drvdata(dev); int ret, val; unsigned int reg; - ret = regmap_read(pdata->map, PCF2123_REG_OFFSET, ®); + ret = regmap_read(pcf2123->map, PCF2123_REG_OFFSET, ®); if (ret) return ret; @@ -149,7 +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); + struct pcf2123_data *pcf2123 = dev_get_drvdata(dev); s8 reg; if (offset > OFFSET_STEP * 127) @@ -169,16 +169,16 @@ static int pcf2123_set_offset(struct device *dev, long offset) reg |= OFFSET_COARSE; } - return regmap_write(pdata->map, PCF2123_REG_OFFSET, (unsigned int)reg); + return regmap_write(pcf2123->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); + struct pcf2123_data *pcf2123 = dev_get_drvdata(dev); u8 rxbuf[7]; int ret; - ret = regmap_bulk_read(pdata->map, PCF2123_REG_SC, rxbuf, + ret = regmap_bulk_read(pcf2123->map, PCF2123_REG_SC, rxbuf, sizeof(rxbuf)); if (ret) return ret; @@ -194,9 +194,7 @@ static int pcf2123_rtc_read_time(struct device *dev, struct rtc_time *tm) tm->tm_mday = bcd2bin(rxbuf[3] & 0x3F); tm->tm_wday = rxbuf[4] & 0x07; tm->tm_mon = bcd2bin(rxbuf[5] & 0x1F) - 1; /* rtc mn 1-12 */ - tm->tm_year = bcd2bin(rxbuf[6]); - if (tm->tm_year < 70) - tm->tm_year += 100; /* assume we are in 1970...2069 */ + tm->tm_year = bcd2bin(rxbuf[6]) + 100; dev_dbg(dev, "%s: tm is %ptR\n", __func__, tm); @@ -205,14 +203,14 @@ static int pcf2123_rtc_read_time(struct device *dev, struct rtc_time *tm) static int pcf2123_rtc_set_time(struct device *dev, struct rtc_time *tm) { - struct pcf2123_plat_data *pdata = dev_get_platdata(dev); + struct pcf2123_data *pcf2123 = dev_get_drvdata(dev); u8 txbuf[7]; int ret; dev_dbg(dev, "%s: tm is %ptR\n", __func__, tm); /* Stop the counter first */ - ret = regmap_write(pdata->map, PCF2123_REG_CTRL1, CTRL1_STOP); + ret = regmap_write(pcf2123->map, PCF2123_REG_CTRL1, CTRL1_STOP); if (ret) return ret; @@ -223,29 +221,37 @@ static int pcf2123_rtc_set_time(struct device *dev, struct rtc_time *tm) 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); + txbuf[6] = bin2bcd(tm->tm_year - 100); - ret = regmap_bulk_write(pdata->map, PCF2123_REG_SC, txbuf, + ret = regmap_bulk_write(pcf2123->map, PCF2123_REG_SC, txbuf, sizeof(txbuf)); if (ret) return ret; /* Start the counter */ - ret = regmap_write(pdata->map, PCF2123_REG_CTRL1, CTRL1_CLEAR); + ret = regmap_write(pcf2123->map, PCF2123_REG_CTRL1, CTRL1_CLEAR); if (ret) return ret; return 0; } +static int pcf2123_rtc_alarm_irq_enable(struct device *dev, unsigned int en) +{ + struct pcf2123_data *pcf2123 = dev_get_drvdata(dev); + + return regmap_update_bits(pcf2123->map, PCF2123_REG_CTRL2, CTRL2_AIE, + en ? CTRL2_AIE : 0); +} + static int pcf2123_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) { - struct pcf2123_plat_data *pdata = dev_get_platdata(dev); + struct pcf2123_data *pcf2123 = dev_get_drvdata(dev); u8 rxbuf[4]; int ret; unsigned int val = 0; - ret = regmap_bulk_read(pdata->map, PCF2123_REG_ALRM_MN, rxbuf, + ret = regmap_bulk_read(pcf2123->map, PCF2123_REG_ALRM_MN, rxbuf, sizeof(rxbuf)); if (ret) return ret; @@ -257,7 +263,7 @@ static int pcf2123_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) dev_dbg(dev, "%s: alm is %ptR\n", __func__, &alm->time); - ret = regmap_read(pdata->map, PCF2123_REG_CTRL2, &val); + ret = regmap_read(pcf2123->map, PCF2123_REG_CTRL2, &val); if (ret) return ret; @@ -268,19 +274,19 @@ static int pcf2123_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) static int pcf2123_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) { - struct pcf2123_plat_data *pdata = dev_get_platdata(dev); + struct pcf2123_data *pcf2123 = dev_get_drvdata(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); + /* Disable alarm interrupt */ + ret = regmap_update_bits(pcf2123->map, PCF2123_REG_CTRL2, CTRL2_AIE, 0); if (ret) return ret; - /* Disable alarm interrupt */ - ret = regmap_update_bits(pdata->map, PCF2123_REG_CTRL2, CTRL2_AIE, 0); + /* Ensure alarm flag is clear */ + ret = regmap_update_bits(pcf2123->map, PCF2123_REG_CTRL2, CTRL2_AF, 0); if (ret) return ret; @@ -288,42 +294,34 @@ static int pcf2123_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) 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); + txbuf[3] = ALRM_DISABLE; - ret = regmap_bulk_write(pdata->map, PCF2123_REG_ALRM_MN, txbuf, + ret = regmap_bulk_write(pcf2123->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; + return pcf2123_rtc_alarm_irq_enable(dev, alm->enabled); } 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; + struct pcf2123_data *pcf2123 = dev_get_drvdata(dev); + struct mutex *lock = &pcf2123->rtc->ops_lock; unsigned int val = 0; int ret = IRQ_NONE; mutex_lock(lock); - regmap_read(pdata->map, PCF2123_REG_CTRL2, &val); + regmap_read(pcf2123->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); + regmap_update_bits(pcf2123->map, PCF2123_REG_CTRL2, CTRL2_AF, 0); - rtc_update_irq(pdata->rtc, 1, RTC_IRQF | RTC_AF); + rtc_update_irq(pcf2123->rtc, 1, RTC_IRQF | RTC_AF); } mutex_unlock(lock); @@ -333,23 +331,23 @@ static irqreturn_t pcf2123_rtc_irq(int irq, void *dev) static int pcf2123_reset(struct device *dev) { - struct pcf2123_plat_data *pdata = dev_get_platdata(dev); + struct pcf2123_data *pcf2123 = dev_get_drvdata(dev); int ret; unsigned int val = 0; - ret = regmap_write(pdata->map, PCF2123_REG_CTRL1, CTRL1_SW_RESET); + ret = regmap_write(pcf2123->map, PCF2123_REG_CTRL1, CTRL1_SW_RESET); if (ret) return ret; /* Stop the counter */ dev_dbg(dev, "stopping RTC\n"); - ret = regmap_write(pdata->map, PCF2123_REG_CTRL1, CTRL1_STOP); + ret = regmap_write(pcf2123->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 = regmap_read(pdata->map, PCF2123_REG_CTRL1, &val); + ret = regmap_read(pcf2123->map, PCF2123_REG_CTRL1, &val); if (ret) return ret; @@ -358,7 +356,7 @@ static int pcf2123_reset(struct device *dev) return -ENODEV; /* Start the counter */ - ret = regmap_write(pdata->map, PCF2123_REG_CTRL1, CTRL1_CLEAR); + ret = regmap_write(pcf2123->map, PCF2123_REG_CTRL1, CTRL1_CLEAR); if (ret) return ret; @@ -372,26 +370,27 @@ static const struct rtc_class_ops pcf2123_rtc_ops = { .set_offset = pcf2123_set_offset, .read_alarm = pcf2123_rtc_read_alarm, .set_alarm = pcf2123_rtc_set_alarm, + .alarm_irq_enable = pcf2123_rtc_alarm_irq_enable, }; static int pcf2123_probe(struct spi_device *spi) { struct rtc_device *rtc; struct rtc_time tm; - struct pcf2123_plat_data *pdata; + struct pcf2123_data *pcf2123; int ret = 0; - pdata = devm_kzalloc(&spi->dev, sizeof(struct pcf2123_plat_data), + pcf2123 = devm_kzalloc(&spi->dev, sizeof(struct pcf2123_data), GFP_KERNEL); - if (!pdata) + if (!pcf2123) return -ENOMEM; - spi->dev.platform_data = pdata; - pdata->map = devm_regmap_init_spi(spi, &pcf2123_regmap_config); + dev_set_drvdata(&spi->dev, pcf2123); - if (IS_ERR(pdata->map)) { + pcf2123->map = devm_regmap_init_spi(spi, &pcf2123_regmap_config); + if (IS_ERR(pcf2123->map)) { dev_err(&spi->dev, "regmap init failed.\n"); - goto kfree_exit; + return PTR_ERR(pcf2123->map); } ret = pcf2123_rtc_read_time(&spi->dev, &tm); @@ -399,7 +398,7 @@ static int pcf2123_probe(struct spi_device *spi) ret = pcf2123_reset(&spi->dev); if (ret < 0) { dev_err(&spi->dev, "chip not found\n"); - goto kfree_exit; + return ret; } } @@ -407,16 +406,11 @@ static int pcf2123_probe(struct spi_device *spi) (spi->max_speed_hz + 500) / 1000); /* Finalize the initialization */ - rtc = devm_rtc_device_register(&spi->dev, pcf2123_driver.driver.name, - &pcf2123_rtc_ops, THIS_MODULE); - - if (IS_ERR(rtc)) { - dev_err(&spi->dev, "failed to register.\n"); - ret = PTR_ERR(rtc); - goto kfree_exit; - } + rtc = devm_rtc_allocate_device(&spi->dev); + if (IS_ERR(rtc)) + return PTR_ERR(rtc); - pdata->rtc = rtc; + pcf2123->rtc = rtc; /* Register alarm irq */ if (spi->irq > 0) { @@ -434,19 +428,25 @@ static int pcf2123_probe(struct spi_device *spi) * support to this driver to generate interrupts more than once * per minute. */ - pdata->rtc->uie_unsupported = 1; + rtc->uie_unsupported = 1; + rtc->ops = &pcf2123_rtc_ops; + rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; + rtc->range_max = RTC_TIMESTAMP_END_2099; + rtc->set_start_time = true; - return 0; + ret = rtc_register_device(rtc); + if (ret) + return ret; -kfree_exit: - spi->dev.platform_data = NULL; - return ret; + return 0; } #ifdef CONFIG_OF static const struct of_device_id pcf2123_dt_ids[] = { - { .compatible = "nxp,rtc-pcf2123", }, + { .compatible = "nxp,pcf2123", }, { .compatible = "microcrystal,rv2123", }, + /* Deprecated, do not use */ + { .compatible = "nxp,rtc-pcf2123", }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, pcf2123_dt_ids); diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c index 8632f58fed43..02b069caffd5 100644 --- a/drivers/rtc/rtc-pcf2127.c +++ b/drivers/rtc/rtc-pcf2127.c @@ -5,6 +5,9 @@ * * Author: Renaud Cerrato <r.cerrato@til-technologies.fr> * + * Watchdog and tamper functions + * Author: Bruno Thomsen <bruno.thomsen@gmail.com> + * * based on the other drivers in this same directory. * * Datasheet: http://cache.nxp.com/documents/data_sheet/PCF2127.pdf @@ -18,30 +21,67 @@ #include <linux/module.h> #include <linux/of.h> #include <linux/regmap.h> +#include <linux/watchdog.h> + +/* Control register 1 */ +#define PCF2127_REG_CTRL1 0x00 +#define PCF2127_BIT_CTRL1_TSF1 BIT(4) +/* Control register 2 */ +#define PCF2127_REG_CTRL2 0x01 +#define PCF2127_BIT_CTRL2_TSIE BIT(2) +#define PCF2127_BIT_CTRL2_TSF2 BIT(5) +/* Control register 3 */ +#define PCF2127_REG_CTRL3 0x02 +#define PCF2127_BIT_CTRL3_BLIE BIT(0) +#define PCF2127_BIT_CTRL3_BIE BIT(1) +#define PCF2127_BIT_CTRL3_BLF BIT(2) +#define PCF2127_BIT_CTRL3_BF BIT(3) +#define PCF2127_BIT_CTRL3_BTSE BIT(4) +/* Time and date registers */ +#define PCF2127_REG_SC 0x03 +#define PCF2127_BIT_SC_OSF BIT(7) +#define PCF2127_REG_MN 0x04 +#define PCF2127_REG_HR 0x05 +#define PCF2127_REG_DM 0x06 +#define PCF2127_REG_DW 0x07 +#define PCF2127_REG_MO 0x08 +#define PCF2127_REG_YR 0x09 +/* Watchdog registers */ +#define PCF2127_REG_WD_CTL 0x10 +#define PCF2127_BIT_WD_CTL_TF0 BIT(0) +#define PCF2127_BIT_WD_CTL_TF1 BIT(1) +#define PCF2127_BIT_WD_CTL_CD0 BIT(6) +#define PCF2127_BIT_WD_CTL_CD1 BIT(7) +#define PCF2127_REG_WD_VAL 0x11 +/* Tamper timestamp registers */ +#define PCF2127_REG_TS_CTRL 0x12 +#define PCF2127_BIT_TS_CTRL_TSOFF BIT(6) +#define PCF2127_BIT_TS_CTRL_TSM BIT(7) +#define PCF2127_REG_TS_SC 0x13 +#define PCF2127_REG_TS_MN 0x14 +#define PCF2127_REG_TS_HR 0x15 +#define PCF2127_REG_TS_DM 0x16 +#define PCF2127_REG_TS_MO 0x17 +#define PCF2127_REG_TS_YR 0x18 +/* + * RAM registers + * PCF2127 has 512 bytes general-purpose static RAM (SRAM) that is + * battery backed and can survive a power outage. + * PCF2129 doesn't have this feature. + */ +#define PCF2127_REG_RAM_ADDR_MSB 0x1A +#define PCF2127_REG_RAM_WRT_CMD 0x1C +#define PCF2127_REG_RAM_RD_CMD 0x1D -#define PCF2127_REG_CTRL1 (0x00) /* Control Register 1 */ -#define PCF2127_REG_CTRL2 (0x01) /* Control Register 2 */ - -#define PCF2127_REG_CTRL3 (0x02) /* Control Register 3 */ -#define PCF2127_REG_CTRL3_BLF BIT(2) - -#define PCF2127_REG_SC (0x03) /* datetime */ -#define PCF2127_REG_MN (0x04) -#define PCF2127_REG_HR (0x05) -#define PCF2127_REG_DM (0x06) -#define PCF2127_REG_DW (0x07) -#define PCF2127_REG_MO (0x08) -#define PCF2127_REG_YR (0x09) - -/* the pcf2127 has 512 bytes nvmem, pcf2129 doesn't */ -#define PCF2127_REG_RAM_addr_MSB 0x1a -#define PCF2127_REG_RAM_wrt_cmd 0x1c -#define PCF2127_REG_RAM_rd_cmd 0x1d - -#define PCF2127_OSF BIT(7) /* Oscillator Fail flag */ +/* Watchdog timer value constants */ +#define PCF2127_WD_VAL_STOP 0 +#define PCF2127_WD_VAL_MIN 2 +#define PCF2127_WD_VAL_MAX 255 +#define PCF2127_WD_VAL_DEFAULT 60 struct pcf2127 { struct rtc_device *rtc; + struct watchdog_device wdd; struct regmap *regmap; }; @@ -54,30 +94,25 @@ static int pcf2127_rtc_read_time(struct device *dev, struct rtc_time *tm) struct pcf2127 *pcf2127 = dev_get_drvdata(dev); unsigned char buf[10]; int ret; - int i; - for (i = 0; i <= PCF2127_REG_CTRL3; i++) { - ret = regmap_read(pcf2127->regmap, PCF2127_REG_CTRL1 + i, - (unsigned int *)(buf + i)); - if (ret) { - dev_err(dev, "%s: read error\n", __func__); - return ret; - } - } - - ret = regmap_bulk_read(pcf2127->regmap, PCF2127_REG_SC, - (buf + PCF2127_REG_SC), - ARRAY_SIZE(buf) - PCF2127_REG_SC); + /* + * Avoid reading CTRL2 register as it causes WD_VAL register + * value to reset to 0 which means watchdog is stopped. + */ + ret = regmap_bulk_read(pcf2127->regmap, PCF2127_REG_CTRL3, + (buf + PCF2127_REG_CTRL3), + ARRAY_SIZE(buf) - PCF2127_REG_CTRL3); if (ret) { dev_err(dev, "%s: read error\n", __func__); return ret; } - if (buf[PCF2127_REG_CTRL3] & PCF2127_REG_CTRL3_BLF) + if (buf[PCF2127_REG_CTRL3] & PCF2127_BIT_CTRL3_BLF) dev_info(dev, "low voltage detected, check/replace RTC battery.\n"); - if (buf[PCF2127_REG_SC] & PCF2127_OSF) { + /* Clock integrity is not guaranteed when OSF flag is set. */ + if (buf[PCF2127_REG_SC] & PCF2127_BIT_SC_OSF) { /* * no need clear the flag here, * it will be cleared once the new date is saved @@ -88,14 +123,12 @@ static int pcf2127_rtc_read_time(struct device *dev, struct rtc_time *tm) } dev_dbg(dev, - "%s: raw data is cr1=%02x, cr2=%02x, cr3=%02x, " - "sec=%02x, min=%02x, hr=%02x, " + "%s: raw data is cr3=%02x, sec=%02x, min=%02x, hr=%02x, " "mday=%02x, wday=%02x, mon=%02x, year=%02x\n", - __func__, - buf[0], buf[1], buf[2], - buf[3], buf[4], buf[5], - buf[6], buf[7], buf[8], buf[9]); - + __func__, buf[PCF2127_REG_CTRL3], buf[PCF2127_REG_SC], + buf[PCF2127_REG_MN], buf[PCF2127_REG_HR], + buf[PCF2127_REG_DM], buf[PCF2127_REG_DW], + buf[PCF2127_REG_MO], buf[PCF2127_REG_YR]); tm->tm_sec = bcd2bin(buf[PCF2127_REG_SC] & 0x7F); tm->tm_min = bcd2bin(buf[PCF2127_REG_MN] & 0x7F); @@ -166,7 +199,7 @@ static int pcf2127_rtc_ioctl(struct device *dev, if (ret) return ret; - touser = touser & PCF2127_REG_CTRL3_BLF ? 1 : 0; + touser = touser & PCF2127_BIT_CTRL3_BLF ? 1 : 0; if (copy_to_user((void __user *)arg, &touser, sizeof(int))) return -EFAULT; @@ -192,12 +225,12 @@ static int pcf2127_nvmem_read(void *priv, unsigned int offset, int ret; unsigned char offsetbuf[] = { offset >> 8, offset }; - ret = regmap_bulk_write(pcf2127->regmap, PCF2127_REG_RAM_addr_MSB, + ret = regmap_bulk_write(pcf2127->regmap, PCF2127_REG_RAM_ADDR_MSB, offsetbuf, 2); if (ret) return ret; - ret = regmap_bulk_read(pcf2127->regmap, PCF2127_REG_RAM_rd_cmd, + ret = regmap_bulk_read(pcf2127->regmap, PCF2127_REG_RAM_RD_CMD, val, bytes); return ret ?: bytes; @@ -210,17 +243,176 @@ static int pcf2127_nvmem_write(void *priv, unsigned int offset, int ret; unsigned char offsetbuf[] = { offset >> 8, offset }; - ret = regmap_bulk_write(pcf2127->regmap, PCF2127_REG_RAM_addr_MSB, + ret = regmap_bulk_write(pcf2127->regmap, PCF2127_REG_RAM_ADDR_MSB, offsetbuf, 2); if (ret) return ret; - ret = regmap_bulk_write(pcf2127->regmap, PCF2127_REG_RAM_wrt_cmd, + ret = regmap_bulk_write(pcf2127->regmap, PCF2127_REG_RAM_WRT_CMD, val, bytes); return ret ?: bytes; } +/* watchdog driver */ + +static int pcf2127_wdt_ping(struct watchdog_device *wdd) +{ + struct pcf2127 *pcf2127 = watchdog_get_drvdata(wdd); + + return regmap_write(pcf2127->regmap, PCF2127_REG_WD_VAL, wdd->timeout); +} + +/* + * Restart watchdog timer if feature is active. + * + * Note: Reading CTRL2 register causes watchdog to stop which is unfortunate, + * since register also contain control/status flags for other features. + * Always call this function after reading CTRL2 register. + */ +static int pcf2127_wdt_active_ping(struct watchdog_device *wdd) +{ + int ret = 0; + + if (watchdog_active(wdd)) { + ret = pcf2127_wdt_ping(wdd); + if (ret) + dev_err(wdd->parent, + "%s: watchdog restart failed, ret=%d\n", + __func__, ret); + } + + return ret; +} + +static int pcf2127_wdt_start(struct watchdog_device *wdd) +{ + return pcf2127_wdt_ping(wdd); +} + +static int pcf2127_wdt_stop(struct watchdog_device *wdd) +{ + struct pcf2127 *pcf2127 = watchdog_get_drvdata(wdd); + + return regmap_write(pcf2127->regmap, PCF2127_REG_WD_VAL, + PCF2127_WD_VAL_STOP); +} + +static int pcf2127_wdt_set_timeout(struct watchdog_device *wdd, + unsigned int new_timeout) +{ + dev_dbg(wdd->parent, "new watchdog timeout: %is (old: %is)\n", + new_timeout, wdd->timeout); + + wdd->timeout = new_timeout; + + return pcf2127_wdt_active_ping(wdd); +} + +static const struct watchdog_info pcf2127_wdt_info = { + .identity = "NXP PCF2127/PCF2129 Watchdog", + .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT, +}; + +static const struct watchdog_ops pcf2127_watchdog_ops = { + .owner = THIS_MODULE, + .start = pcf2127_wdt_start, + .stop = pcf2127_wdt_stop, + .ping = pcf2127_wdt_ping, + .set_timeout = pcf2127_wdt_set_timeout, +}; + +/* sysfs interface */ + +static ssize_t timestamp0_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct pcf2127 *pcf2127 = dev_get_drvdata(dev->parent); + int ret; + + ret = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL1, + PCF2127_BIT_CTRL1_TSF1, 0); + if (ret) { + dev_err(dev, "%s: update ctrl1 ret=%d\n", __func__, ret); + return ret; + } + + ret = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL2, + PCF2127_BIT_CTRL2_TSF2, 0); + if (ret) { + dev_err(dev, "%s: update ctrl2 ret=%d\n", __func__, ret); + return ret; + } + + ret = pcf2127_wdt_active_ping(&pcf2127->wdd); + if (ret) + return ret; + + return count; +}; + +static ssize_t timestamp0_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct pcf2127 *pcf2127 = dev_get_drvdata(dev->parent); + struct rtc_time tm; + int ret; + unsigned char data[25]; + + ret = regmap_bulk_read(pcf2127->regmap, PCF2127_REG_CTRL1, data, + sizeof(data)); + if (ret) { + dev_err(dev, "%s: read error ret=%d\n", __func__, ret); + return ret; + } + + dev_dbg(dev, + "%s: raw data is cr1=%02x, cr2=%02x, cr3=%02x, ts_sc=%02x, " + "ts_mn=%02x, ts_hr=%02x, ts_dm=%02x, ts_mo=%02x, ts_yr=%02x\n", + __func__, data[PCF2127_REG_CTRL1], data[PCF2127_REG_CTRL2], + data[PCF2127_REG_CTRL3], data[PCF2127_REG_TS_SC], + data[PCF2127_REG_TS_MN], data[PCF2127_REG_TS_HR], + data[PCF2127_REG_TS_DM], data[PCF2127_REG_TS_MO], + data[PCF2127_REG_TS_YR]); + + ret = pcf2127_wdt_active_ping(&pcf2127->wdd); + if (ret) + return ret; + + if (!(data[PCF2127_REG_CTRL1] & PCF2127_BIT_CTRL1_TSF1) && + !(data[PCF2127_REG_CTRL2] & PCF2127_BIT_CTRL2_TSF2)) + return 0; + + tm.tm_sec = bcd2bin(data[PCF2127_REG_TS_SC] & 0x7F); + tm.tm_min = bcd2bin(data[PCF2127_REG_TS_MN] & 0x7F); + tm.tm_hour = bcd2bin(data[PCF2127_REG_TS_HR] & 0x3F); + tm.tm_mday = bcd2bin(data[PCF2127_REG_TS_DM] & 0x3F); + /* TS_MO register (month) value range: 1-12 */ + tm.tm_mon = bcd2bin(data[PCF2127_REG_TS_MO] & 0x1F) - 1; + tm.tm_year = bcd2bin(data[PCF2127_REG_TS_YR]); + if (tm.tm_year < 70) + tm.tm_year += 100; /* assume we are in 1970...2069 */ + + ret = rtc_valid_tm(&tm); + if (ret) + return ret; + + return sprintf(buf, "%llu\n", + (unsigned long long)rtc_tm_to_time64(&tm)); +}; + +static DEVICE_ATTR_RW(timestamp0); + +static struct attribute *pcf2127_attrs[] = { + &dev_attr_timestamp0.attr, + NULL +}; + +static const struct attribute_group pcf2127_attr_group = { + .attrs = pcf2127_attrs, +}; + static int pcf2127_probe(struct device *dev, struct regmap *regmap, const char *name, bool has_nvmem) { @@ -237,11 +429,22 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap, dev_set_drvdata(dev, pcf2127); - pcf2127->rtc = devm_rtc_device_register(dev, name, &pcf2127_rtc_ops, - THIS_MODULE); + pcf2127->rtc = devm_rtc_allocate_device(dev); if (IS_ERR(pcf2127->rtc)) return PTR_ERR(pcf2127->rtc); + pcf2127->rtc->ops = &pcf2127_rtc_ops; + + pcf2127->wdd.parent = dev; + pcf2127->wdd.info = &pcf2127_wdt_info; + pcf2127->wdd.ops = &pcf2127_watchdog_ops; + pcf2127->wdd.min_timeout = PCF2127_WD_VAL_MIN; + pcf2127->wdd.max_timeout = PCF2127_WD_VAL_MAX; + pcf2127->wdd.timeout = PCF2127_WD_VAL_DEFAULT; + pcf2127->wdd.min_hw_heartbeat_ms = 500; + + watchdog_set_drvdata(&pcf2127->wdd, pcf2127); + if (has_nvmem) { struct nvmem_config nvmem_cfg = { .priv = pcf2127, @@ -253,7 +456,84 @@ static int pcf2127_probe(struct device *dev, struct regmap *regmap, ret = rtc_nvmem_register(pcf2127->rtc, &nvmem_cfg); } - return ret; + /* + * Watchdog timer enabled and reset pin /RST activated when timed out. + * Select 1Hz clock source for watchdog timer. + * Timer is not started until WD_VAL is loaded with a valid value. + * Note: Countdown timer disabled and not available. + */ + ret = regmap_update_bits(pcf2127->regmap, PCF2127_REG_WD_CTL, + PCF2127_BIT_WD_CTL_CD1 | + PCF2127_BIT_WD_CTL_CD0 | + PCF2127_BIT_WD_CTL_TF1 | + PCF2127_BIT_WD_CTL_TF0, + PCF2127_BIT_WD_CTL_CD1 | + PCF2127_BIT_WD_CTL_CD0 | + PCF2127_BIT_WD_CTL_TF1); + if (ret) { + dev_err(dev, "%s: watchdog config (wd_ctl) failed\n", __func__); + return ret; + } + +#ifdef CONFIG_WATCHDOG + ret = devm_watchdog_register_device(dev, &pcf2127->wdd); + if (ret) + return ret; +#endif /* CONFIG_WATCHDOG */ + + /* + * Disable battery low/switch-over timestamp and interrupts. + * Clear battery interrupt flags which can block new trigger events. + * Note: This is the default chip behaviour but added to ensure + * correct tamper timestamp and interrupt function. + */ + 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) { + dev_err(dev, "%s: interrupt config (ctrl3) failed\n", + __func__); + return ret; + } + + /* + * Enable timestamp function and store timestamp of first trigger + * event until TSF1 and TFS2 interrupt flags are cleared. + */ + ret = regmap_update_bits(pcf2127->regmap, PCF2127_REG_TS_CTRL, + PCF2127_BIT_TS_CTRL_TSOFF | + PCF2127_BIT_TS_CTRL_TSM, + PCF2127_BIT_TS_CTRL_TSM); + if (ret) { + dev_err(dev, "%s: tamper detection config (ts_ctrl) failed\n", + __func__); + return ret; + } + + /* + * Enable interrupt generation when TSF1 or TSF2 timestamp flags + * are set. Interrupt signal is an open-drain output and can be + * left floating if unused. + */ + ret = regmap_update_bits(pcf2127->regmap, PCF2127_REG_CTRL2, + PCF2127_BIT_CTRL2_TSIE, + PCF2127_BIT_CTRL2_TSIE); + if (ret) { + dev_err(dev, "%s: tamper detection config (ctrl2) failed\n", + __func__); + return ret; + } + + ret = rtc_add_group(pcf2127->rtc, &pcf2127_attr_group); + if (ret) { + dev_err(dev, "%s: tamper sysfs registering failed\n", + __func__); + return ret; + } + + return rtc_register_device(pcf2127->rtc); } #ifdef CONFIG_OF diff --git a/drivers/rtc/rtc-pcf85363.c b/drivers/rtc/rtc-pcf85363.c index a075e77617dc..3450d615974d 100644 --- a/drivers/rtc/rtc-pcf85363.c +++ b/drivers/rtc/rtc-pcf85363.c @@ -166,7 +166,12 @@ static int pcf85363_rtc_set_time(struct device *dev, struct rtc_time *tm) buf[DT_YEARS] = bin2bcd(tm->tm_year % 100); ret = regmap_bulk_write(pcf85363->regmap, CTRL_STOP_EN, - tmp, sizeof(tmp)); + tmp, 2); + if (ret) + return ret; + + ret = regmap_bulk_write(pcf85363->regmap, DT_100THS, + buf, sizeof(tmp) - 2); if (ret) return ret; diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c index ac159d24286d..24baa4767b11 100644 --- a/drivers/rtc/rtc-pcf8563.c +++ b/drivers/rtc/rtc-pcf8563.c @@ -196,8 +196,9 @@ static irqreturn_t pcf8563_irq(int irq, void *dev_id) * In the routines that deal directly with the pcf8563 hardware, we use * rtc_time -- month 0-11, hour 0-23, yr = calendar year-epoch. */ -static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm) +static int pcf8563_rtc_read_time(struct device *dev, struct rtc_time *tm) { + struct i2c_client *client = to_i2c_client(dev); struct pcf8563 *pcf8563 = i2c_get_clientdata(client); unsigned char buf[9]; int err; @@ -228,9 +229,7 @@ static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm) tm->tm_mday = bcd2bin(buf[PCF8563_REG_DM] & 0x3F); tm->tm_wday = buf[PCF8563_REG_DW] & 0x07; tm->tm_mon = bcd2bin(buf[PCF8563_REG_MO] & 0x1F) - 1; /* rtc mn 1-12 */ - tm->tm_year = bcd2bin(buf[PCF8563_REG_YR]); - if (tm->tm_year < 70) - tm->tm_year += 100; /* assume we are in 1970...2069 */ + tm->tm_year = bcd2bin(buf[PCF8563_REG_YR]) + 100; /* detect the polarity heuristically. see note above. */ pcf8563->c_polarity = (buf[PCF8563_REG_MO] & PCF8563_MO_C) ? (tm->tm_year >= 100) : (tm->tm_year < 100); @@ -244,8 +243,9 @@ static int pcf8563_get_datetime(struct i2c_client *client, struct rtc_time *tm) return 0; } -static int pcf8563_set_datetime(struct i2c_client *client, struct rtc_time *tm) +static int pcf8563_rtc_set_time(struct device *dev, struct rtc_time *tm) { + struct i2c_client *client = to_i2c_client(dev); struct pcf8563 *pcf8563 = i2c_get_clientdata(client); unsigned char buf[9]; @@ -266,7 +266,7 @@ static int pcf8563_set_datetime(struct i2c_client *client, struct rtc_time *tm) buf[PCF8563_REG_MO] = bin2bcd(tm->tm_mon + 1); /* year and century */ - buf[PCF8563_REG_YR] = bin2bcd(tm->tm_year % 100); + buf[PCF8563_REG_YR] = bin2bcd(tm->tm_year - 100); if (pcf8563->c_polarity ? (tm->tm_year >= 100) : (tm->tm_year < 100)) buf[PCF8563_REG_MO] |= PCF8563_MO_C; @@ -299,8 +299,8 @@ static int pcf8563_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long * because of the cached voltage_low value but do it * anyway for consistency. */ - if (pcf8563_get_datetime(to_i2c_client(dev), &tm)) - pcf8563_set_datetime(to_i2c_client(dev), &tm); + if (pcf8563_rtc_read_time(dev, &tm)) + pcf8563_rtc_set_time(dev, &tm); /* Clear the cached value. */ pcf8563->voltage_low = 0; @@ -314,16 +314,6 @@ static int pcf8563_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long #define pcf8563_rtc_ioctl NULL #endif -static int pcf8563_rtc_read_time(struct device *dev, struct rtc_time *tm) -{ - return pcf8563_get_datetime(to_i2c_client(dev), tm); -} - -static int pcf8563_rtc_set_time(struct device *dev, struct rtc_time *tm) -{ - return pcf8563_set_datetime(to_i2c_client(dev), tm); -} - static int pcf8563_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *tm) { struct i2c_client *client = to_i2c_client(dev); @@ -591,13 +581,17 @@ static int pcf8563_probe(struct i2c_client *client, return err; } - pcf8563->rtc = devm_rtc_device_register(&client->dev, - pcf8563_driver.driver.name, - &pcf8563_rtc_ops, THIS_MODULE); - + pcf8563->rtc = devm_rtc_allocate_device(&client->dev); if (IS_ERR(pcf8563->rtc)) return PTR_ERR(pcf8563->rtc); + pcf8563->rtc->ops = &pcf8563_rtc_ops; + /* the pcf8563 alarm only supports a minute accuracy */ + pcf8563->rtc->uie_unsupported = 1; + pcf8563->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; + pcf8563->rtc->range_max = RTC_TIMESTAMP_END_2099; + pcf8563->rtc->set_start_time = true; + if (client->irq > 0) { err = devm_request_threaded_irq(&client->dev, client->irq, NULL, pcf8563_irq, @@ -608,17 +602,17 @@ static int pcf8563_probe(struct i2c_client *client, client->irq); return err; } - } + err = rtc_register_device(pcf8563->rtc); + if (err) + return err; + #ifdef CONFIG_COMMON_CLK /* register clk in common clk framework */ pcf8563_clkout_register_clk(pcf8563); #endif - /* the pcf8563 alarm only supports a minute accuracy */ - pcf8563->rtc->uie_unsupported = 1; - return 0; } @@ -632,6 +626,8 @@ MODULE_DEVICE_TABLE(i2c, pcf8563_id); #ifdef CONFIG_OF static const struct of_device_id pcf8563_of_match[] = { { .compatible = "nxp,pcf8563" }, + { .compatible = "epson,rtc8564" }, + { .compatible = "microcrystal,rv8564" }, {} }; MODULE_DEVICE_TABLE(of, pcf8563_of_match); diff --git a/drivers/rtc/rtc-pic32.c b/drivers/rtc/rtc-pic32.c index 1c4de6e90da0..17653ed52ebb 100644 --- a/drivers/rtc/rtc-pic32.c +++ b/drivers/rtc/rtc-pic32.c @@ -308,10 +308,8 @@ static int pic32_rtc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, pdata); pdata->alarm_irq = platform_get_irq(pdev, 0); - if (pdata->alarm_irq < 0) { - dev_err(&pdev->dev, "no irq for alarm\n"); + if (pdata->alarm_irq < 0) return pdata->alarm_irq; - } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); pdata->reg_base = devm_ioremap_resource(&pdev->dev, res); diff --git a/drivers/rtc/rtc-pm8xxx.c b/drivers/rtc/rtc-pm8xxx.c index 9f9839c47e2f..f5a30e0f16c2 100644 --- a/drivers/rtc/rtc-pm8xxx.c +++ b/drivers/rtc/rtc-pm8xxx.c @@ -468,10 +468,8 @@ static int pm8xxx_rtc_probe(struct platform_device *pdev) } rtc_dd->rtc_alarm_irq = platform_get_irq(pdev, 0); - if (rtc_dd->rtc_alarm_irq < 0) { - dev_err(&pdev->dev, "Alarm IRQ resource absent!\n"); + if (rtc_dd->rtc_alarm_irq < 0) return -ENXIO; - } rtc_dd->allow_set_time = of_property_read_bool(pdev->dev.of_node, "allow-set-time"); diff --git a/drivers/rtc/rtc-puv3.c b/drivers/rtc/rtc-puv3.c index 63b9e73fb97d..89ff713163dd 100644 --- a/drivers/rtc/rtc-puv3.c +++ b/drivers/rtc/rtc-puv3.c @@ -186,16 +186,12 @@ static int puv3_rtc_probe(struct platform_device *pdev) /* find the IRQs */ puv3_rtc_tickno = platform_get_irq(pdev, 1); - if (puv3_rtc_tickno < 0) { - dev_err(&pdev->dev, "no irq for rtc tick\n"); + if (puv3_rtc_tickno < 0) return -ENOENT; - } puv3_rtc_alarmno = platform_get_irq(pdev, 0); - if (puv3_rtc_alarmno < 0) { - dev_err(&pdev->dev, "no irq for alarm\n"); + if (puv3_rtc_alarmno < 0) return -ENOENT; - } dev_dbg(&pdev->dev, "PKUnity_rtc: tick irq %d, alarm irq %d\n", puv3_rtc_tickno, puv3_rtc_alarmno); @@ -239,10 +235,8 @@ static int puv3_rtc_probe(struct platform_device *pdev) /* register RTC and exit */ rtc->ops = &puv3_rtcops; ret = rtc_register_device(rtc); - if (ret) { - dev_err(&pdev->dev, "cannot attach rtc\n"); + if (ret) goto err_nortc; - } /* platform setup code should have handled this; sigh */ if (!device_can_wakeup(&pdev->dev)) diff --git a/drivers/rtc/rtc-pxa.c b/drivers/rtc/rtc-pxa.c index a7827fe7fb7b..d2f1d8f754bf 100644 --- a/drivers/rtc/rtc-pxa.c +++ b/drivers/rtc/rtc-pxa.c @@ -324,15 +324,11 @@ static int __init pxa_rtc_probe(struct platform_device *pdev) } sa1100_rtc->irq_1hz = platform_get_irq(pdev, 0); - if (sa1100_rtc->irq_1hz < 0) { - dev_err(dev, "No 1Hz IRQ resource defined\n"); + if (sa1100_rtc->irq_1hz < 0) return -ENXIO; - } sa1100_rtc->irq_alarm = platform_get_irq(pdev, 1); - if (sa1100_rtc->irq_alarm < 0) { - dev_err(dev, "No alarm IRQ resource defined\n"); + if (sa1100_rtc->irq_alarm < 0) return -ENXIO; - } pxa_rtc->base = devm_ioremap(dev, pxa_rtc->ress->start, resource_size(pxa_rtc->ress)); diff --git a/drivers/rtc/rtc-rk808.c b/drivers/rtc/rtc-rk808.c index c34540baa12a..c0334c602e88 100644 --- a/drivers/rtc/rtc-rk808.c +++ b/drivers/rtc/rtc-rk808.c @@ -434,12 +434,8 @@ static int rk808_rtc_probe(struct platform_device *pdev) rk808_rtc->rtc->ops = &rk808_rtc_ops; rk808_rtc->irq = platform_get_irq(pdev, 0); - if (rk808_rtc->irq < 0) { - if (rk808_rtc->irq != -EPROBE_DEFER) - dev_err(&pdev->dev, "Wake up is not possible as irq = %d\n", - rk808_rtc->irq); + if (rk808_rtc->irq < 0) return rk808_rtc->irq; - } /* request alarm irq of rk808 */ ret = devm_request_threaded_irq(&pdev->dev, rk808_rtc->irq, NULL, diff --git a/drivers/rtc/rtc-rv3028.c b/drivers/rtc/rtc-rv3028.c index 06884ebb7a61..2b316661a578 100644 --- a/drivers/rtc/rtc-rv3028.c +++ b/drivers/rtc/rtc-rv3028.c @@ -639,9 +639,8 @@ static int rv3028_probe(struct i2c_client *client) dev_warn(&client->dev, "An alarm may have been missed.\n"); rv3028->rtc = devm_rtc_allocate_device(&client->dev); - if (IS_ERR(rv3028->rtc)) { + if (IS_ERR(rv3028->rtc)) return PTR_ERR(rv3028->rtc); - } if (client->irq > 0) { ret = devm_request_threaded_irq(&client->dev, client->irq, diff --git a/drivers/rtc/rtc-rv3029c2.c b/drivers/rtc/rtc-rv3029c2.c index 4a0e8ec015cc..4cdf6588e1d9 100644 --- a/drivers/rtc/rtc-rv3029c2.c +++ b/drivers/rtc/rtc-rv3029c2.c @@ -278,13 +278,13 @@ static int rv3029_eeprom_read(struct device *dev, u8 reg, static int rv3029_eeprom_write(struct device *dev, u8 reg, u8 const buf[], size_t len) { - int ret; + int ret, err; size_t i; u8 tmp; - ret = rv3029_eeprom_enter(dev); - if (ret < 0) - return ret; + err = rv3029_eeprom_enter(dev); + if (err < 0) + return err; for (i = 0; i < len; i++, reg++) { ret = rv3029_read_regs(dev, reg, &tmp, 1); @@ -300,11 +300,11 @@ static int rv3029_eeprom_write(struct device *dev, u8 reg, break; } - ret = rv3029_eeprom_exit(dev); - if (ret < 0) - return ret; + err = rv3029_eeprom_exit(dev); + if (err < 0) + return err; - return 0; + return ret; } static int rv3029_eeprom_update_bits(struct device *dev, diff --git a/drivers/rtc/rtc-rv8803.c b/drivers/rtc/rtc-rv8803.c index fc5243400108..4960f0a2b249 100644 --- a/drivers/rtc/rtc-rv8803.c +++ b/drivers/rtc/rtc-rv8803.c @@ -564,9 +564,8 @@ static int rv8803_probe(struct i2c_client *client, dev_warn(&client->dev, "An alarm maybe have been missed.\n"); rv8803->rtc = devm_rtc_allocate_device(&client->dev); - if (IS_ERR(rv8803->rtc)) { + if (IS_ERR(rv8803->rtc)) return PTR_ERR(rv8803->rtc); - } if (client->irq > 0) { err = devm_request_threaded_irq(&client->dev, client->irq, diff --git a/drivers/rtc/rtc-s35390a.c b/drivers/rtc/rtc-s35390a.c index 84806ff763cf..da34cfd70f95 100644 --- a/drivers/rtc/rtc-s35390a.c +++ b/drivers/rtc/rtc-s35390a.c @@ -434,37 +434,32 @@ static int s35390a_probe(struct i2c_client *client, char buf, status1; struct device *dev = &client->dev; - if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { - err = -ENODEV; - goto exit; - } + if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) + return -ENODEV; s35390a = devm_kzalloc(dev, sizeof(struct s35390a), GFP_KERNEL); - if (!s35390a) { - err = -ENOMEM; - goto exit; - } + if (!s35390a) + return -ENOMEM; s35390a->client[0] = client; i2c_set_clientdata(client, s35390a); /* This chip uses multiple addresses, use dummy devices for them */ for (i = 1; i < 8; ++i) { - s35390a->client[i] = i2c_new_dummy(client->adapter, - client->addr + i); - if (!s35390a->client[i]) { + s35390a->client[i] = devm_i2c_new_dummy_device(dev, + client->adapter, + client->addr + i); + if (IS_ERR(s35390a->client[i])) { dev_err(dev, "Address %02x unavailable\n", client->addr + i); - err = -EBUSY; - goto exit_dummy; + return PTR_ERR(s35390a->client[i]); } } err_read = s35390a_read_status(s35390a, &status1); if (err_read < 0) { - err = err_read; dev_err(dev, "error resetting chip\n"); - goto exit_dummy; + return err_read; } if (status1 & S35390A_FLAG_24H) @@ -478,13 +473,13 @@ static int s35390a_probe(struct i2c_client *client, err = s35390a_set_reg(s35390a, S35390A_CMD_STATUS2, &buf, 1); if (err < 0) { dev_err(dev, "error disabling alarm"); - goto exit_dummy; + return err; } } else { err = s35390a_disable_test_mode(s35390a); if (err < 0) { dev_err(dev, "error disabling test mode\n"); - goto exit_dummy; + return err; } } @@ -493,10 +488,8 @@ static int s35390a_probe(struct i2c_client *client, 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; - } + if (IS_ERR(s35390a->rtc)) + return PTR_ERR(s35390a->rtc); /* supports per-minute alarms only, therefore set uie_unsupported */ s35390a->rtc->uie_unsupported = 1; @@ -505,26 +498,6 @@ static int s35390a_probe(struct i2c_client *client, rtc_update_irq(s35390a->rtc, 1, RTC_AF); return 0; - -exit_dummy: - for (i = 1; i < 8; ++i) - if (s35390a->client[i]) - i2c_unregister_device(s35390a->client[i]); - -exit: - return err; -} - -static int s35390a_remove(struct i2c_client *client) -{ - unsigned int i; - struct s35390a *s35390a = i2c_get_clientdata(client); - - for (i = 1; i < 8; ++i) - if (s35390a->client[i]) - i2c_unregister_device(s35390a->client[i]); - - return 0; } static struct i2c_driver s35390a_driver = { @@ -533,7 +506,6 @@ static struct i2c_driver s35390a_driver = { .of_match_table = of_match_ptr(s35390a_of_match), }, .probe = s35390a_probe, - .remove = s35390a_remove, .id_table = s35390a_id, }; diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c index 74bf6473a05d..7801249c254b 100644 --- a/drivers/rtc/rtc-s3c.c +++ b/drivers/rtc/rtc-s3c.c @@ -453,10 +453,8 @@ static int s3c_rtc_probe(struct platform_device *pdev) /* find the IRQs */ info->irq_tick = platform_get_irq(pdev, 1); - if (info->irq_tick < 0) { - dev_err(&pdev->dev, "no irq for rtc tick\n"); + if (info->irq_tick < 0) return info->irq_tick; - } info->dev = &pdev->dev; info->data = of_device_get_match_data(&pdev->dev); @@ -470,10 +468,8 @@ static int s3c_rtc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, info); info->irq_alarm = platform_get_irq(pdev, 0); - if (info->irq_alarm < 0) { - dev_err(&pdev->dev, "no irq for alarm\n"); + if (info->irq_alarm < 0) return info->irq_alarm; - } dev_dbg(&pdev->dev, "s3c2410_rtc: tick irq %d, alarm irq %d\n", info->irq_tick, info->irq_alarm); diff --git a/drivers/rtc/rtc-s5m.c b/drivers/rtc/rtc-s5m.c index c7f1bf823ea0..eb9dde4095a9 100644 --- a/drivers/rtc/rtc-s5m.c +++ b/drivers/rtc/rtc-s5m.c @@ -760,10 +760,10 @@ static int s5m_rtc_probe(struct platform_device *pdev) return -ENODEV; } - info->i2c = i2c_new_dummy(s5m87xx->i2c->adapter, RTC_I2C_ADDR); - if (!info->i2c) { + info->i2c = i2c_new_dummy_device(s5m87xx->i2c->adapter, RTC_I2C_ADDR); + if (IS_ERR(info->i2c)) { dev_err(&pdev->dev, "Failed to allocate I2C for RTC\n"); - return -ENODEV; + return PTR_ERR(info->i2c); } info->regmap = devm_regmap_init_i2c(info->i2c, regmap_cfg); diff --git a/drivers/rtc/rtc-sc27xx.c b/drivers/rtc/rtc-sc27xx.c index b4eb3b3c6c2c..b95676899750 100644 --- a/drivers/rtc/rtc-sc27xx.c +++ b/drivers/rtc/rtc-sc27xx.c @@ -138,7 +138,7 @@ static int sprd_rtc_lock_alarm(struct sprd_rtc *rtc, bool lock) if (ret) return ret; - val &= ~(SPRD_RTC_ALMLOCK_MASK | SPRD_RTC_POWEROFF_ALM_FLAG); + val &= ~SPRD_RTC_ALMLOCK_MASK; if (lock) val |= SPRD_RTC_ALM_LOCK; else @@ -614,10 +614,8 @@ static int sprd_rtc_probe(struct platform_device *pdev) } rtc->irq = platform_get_irq(pdev, 0); - if (rtc->irq < 0) { - dev_err(&pdev->dev, "failed to get RTC irq number\n"); + if (rtc->irq < 0) return rtc->irq; - } rtc->rtc = devm_rtc_allocate_device(&pdev->dev); if (IS_ERR(rtc->rtc)) @@ -656,7 +654,6 @@ static int sprd_rtc_probe(struct platform_device *pdev) rtc->rtc->range_max = 5662310399LL; ret = rtc_register_device(rtc->rtc); if (ret) { - dev_err(&pdev->dev, "failed to register rtc device\n"); device_init_wakeup(&pdev->dev, 0); return ret; } diff --git a/drivers/rtc/rtc-sd3078.c b/drivers/rtc/rtc-sd3078.c index 42cb90db7f94..a7aa943c1183 100644 --- a/drivers/rtc/rtc-sd3078.c +++ b/drivers/rtc/rtc-sd3078.c @@ -193,10 +193,8 @@ static int sd3078_probe(struct i2c_client *client, sd3078->rtc->range_max = RTC_TIMESTAMP_END_2099; ret = rtc_register_device(sd3078->rtc); - if (ret) { - dev_err(&client->dev, "failed to register rtc device\n"); + if (ret) return ret; - } sd3078_enable_reg_write(sd3078); diff --git a/drivers/rtc/rtc-snvs.c b/drivers/rtc/rtc-snvs.c index 7ee673a25fd0..757f4daa7181 100644 --- a/drivers/rtc/rtc-snvs.c +++ b/drivers/rtc/rtc-snvs.c @@ -151,7 +151,7 @@ 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); - rtc_time_to_tm(time, tm); + rtc_time64_to_tm(time, tm); return 0; } @@ -159,11 +159,9 @@ static int snvs_rtc_read_time(struct device *dev, struct rtc_time *tm) static int snvs_rtc_set_time(struct device *dev, struct rtc_time *tm) { struct snvs_rtc_data *data = dev_get_drvdata(dev); - unsigned long time; + unsigned long time = rtc_tm_to_time64(tm); int ret; - rtc_tm_to_time(tm, &time); - /* Disable RTC first */ ret = snvs_rtc_enable(data, false); if (ret) @@ -185,7 +183,7 @@ static int snvs_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) u32 lptar, lpsr; regmap_read(data->regmap, data->offset + SNVS_LPTAR, &lptar); - rtc_time_to_tm(lptar, &alrm->time); + rtc_time64_to_tm(lptar, &alrm->time); regmap_read(data->regmap, data->offset + SNVS_LPSR, &lpsr); alrm->pending = (lpsr & SNVS_LPSR_LPTA) ? 1 : 0; @@ -207,12 +205,9 @@ static int snvs_rtc_alarm_irq_enable(struct device *dev, unsigned int enable) static int snvs_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) { struct snvs_rtc_data *data = dev_get_drvdata(dev); - struct rtc_time *alrm_tm = &alrm->time; - unsigned long time; + unsigned long time = rtc_tm_to_time64(&alrm->time); int ret; - rtc_tm_to_time(alrm_tm, &time); - regmap_update_bits(data->regmap, data->offset + SNVS_LPCR, SNVS_LPCR_LPTA_EN, 0); ret = rtc_write_sync_lp(data); if (ret) @@ -279,6 +274,10 @@ static int snvs_rtc_probe(struct platform_device *pdev) if (!data) return -ENOMEM; + data->rtc = devm_rtc_allocate_device(&pdev->dev); + if (IS_ERR(data->rtc)) + return PTR_ERR(data->rtc); + data->regmap = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, "regmap"); if (IS_ERR(data->regmap)) { @@ -343,10 +342,10 @@ static int snvs_rtc_probe(struct platform_device *pdev) goto error_rtc_device_register; } - data->rtc = devm_rtc_device_register(&pdev->dev, pdev->name, - &snvs_rtc_ops, THIS_MODULE); - if (IS_ERR(data->rtc)) { - ret = PTR_ERR(data->rtc); + data->rtc->ops = &snvs_rtc_ops; + data->rtc->range_max = U32_MAX; + ret = rtc_register_device(data->rtc); + if (ret) { dev_err(&pdev->dev, "failed to register rtc: %d\n", ret); goto error_rtc_device_register; } diff --git a/drivers/rtc/rtc-spear.c b/drivers/rtc/rtc-spear.c index 0567944fd4f8..9f23b24f466c 100644 --- a/drivers/rtc/rtc-spear.c +++ b/drivers/rtc/rtc-spear.c @@ -358,10 +358,8 @@ static int spear_rtc_probe(struct platform_device *pdev) /* alarm irqs */ irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "no update irq?\n"); + if (irq < 0) return irq; - } status = devm_request_irq(&pdev->dev, irq, spear_rtc_irq, 0, pdev->name, config); diff --git a/drivers/rtc/rtc-stm32.c b/drivers/rtc/rtc-stm32.c index 773a1990b93f..2999e33a7e37 100644 --- a/drivers/rtc/rtc-stm32.c +++ b/drivers/rtc/rtc-stm32.c @@ -776,7 +776,6 @@ static int stm32_rtc_probe(struct platform_device *pdev) rtc->irq_alarm = platform_get_irq(pdev, 0); if (rtc->irq_alarm <= 0) { - dev_err(&pdev->dev, "no alarm irq\n"); ret = rtc->irq_alarm; goto err; } diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c index d50ee023b559..5e2bd9f1d01e 100644 --- a/drivers/rtc/rtc-sun6i.c +++ b/drivers/rtc/rtc-sun6i.c @@ -32,9 +32,11 @@ /* Control register */ #define SUN6I_LOSC_CTRL 0x0000 #define SUN6I_LOSC_CTRL_KEY (0x16aa << 16) +#define SUN6I_LOSC_CTRL_AUTO_SWT_BYPASS BIT(15) #define SUN6I_LOSC_CTRL_ALM_DHMS_ACC BIT(9) #define SUN6I_LOSC_CTRL_RTC_HMS_ACC BIT(8) #define SUN6I_LOSC_CTRL_RTC_YMD_ACC BIT(7) +#define SUN6I_LOSC_CTRL_EXT_LOSC_EN BIT(4) #define SUN6I_LOSC_CTRL_EXT_OSC BIT(0) #define SUN6I_LOSC_CTRL_ACC_MASK GENMASK(9, 7) @@ -128,6 +130,8 @@ struct sun6i_rtc_clk_data { unsigned int has_prescaler : 1; unsigned int has_out_clk : 1; unsigned int export_iosc : 1; + unsigned int has_losc_en : 1; + unsigned int has_auto_swt : 1; }; struct sun6i_rtc_dev { @@ -190,6 +194,10 @@ static int sun6i_rtc_osc_set_parent(struct clk_hw *hw, u8 index) val &= ~SUN6I_LOSC_CTRL_EXT_OSC; val |= SUN6I_LOSC_CTRL_KEY; val |= index ? SUN6I_LOSC_CTRL_EXT_OSC : 0; + if (rtc->data->has_losc_en) { + val &= ~SUN6I_LOSC_CTRL_EXT_LOSC_EN; + val |= index ? SUN6I_LOSC_CTRL_EXT_LOSC_EN : 0; + } writel(val, rtc->base + SUN6I_LOSC_CTRL); spin_unlock_irqrestore(&rtc->lock, flags); @@ -215,6 +223,7 @@ static void __init sun6i_rtc_clk_init(struct device_node *node, const char *iosc_name = "rtc-int-osc"; const char *clkout_name = "osc32k-out"; const char *parents[2]; + u32 reg; rtc = kzalloc(sizeof(*rtc), GFP_KERNEL); if (!rtc) @@ -235,9 +244,18 @@ static void __init sun6i_rtc_clk_init(struct device_node *node, goto err; } + reg = SUN6I_LOSC_CTRL_KEY; + if (rtc->data->has_auto_swt) { + /* Bypass auto-switch to int osc, on ext losc failure */ + reg |= SUN6I_LOSC_CTRL_AUTO_SWT_BYPASS; + writel(reg, rtc->base + SUN6I_LOSC_CTRL); + } + /* Switch to the external, more precise, oscillator */ - writel(SUN6I_LOSC_CTRL_KEY | SUN6I_LOSC_CTRL_EXT_OSC, - rtc->base + SUN6I_LOSC_CTRL); + reg |= SUN6I_LOSC_CTRL_EXT_OSC; + if (rtc->data->has_losc_en) + reg |= SUN6I_LOSC_CTRL_EXT_LOSC_EN; + writel(reg, rtc->base + SUN6I_LOSC_CTRL); /* Yes, I know, this is ugly. */ sun6i_rtc = rtc; @@ -345,6 +363,23 @@ CLK_OF_DECLARE_DRIVER(sun8i_h3_rtc_clk, "allwinner,sun8i-h3-rtc", CLK_OF_DECLARE_DRIVER(sun50i_h5_rtc_clk, "allwinner,sun50i-h5-rtc", sun8i_h3_rtc_clk_init); +static const struct sun6i_rtc_clk_data sun50i_h6_rtc_data = { + .rc_osc_rate = 16000000, + .fixed_prescaler = 32, + .has_prescaler = 1, + .has_out_clk = 1, + .export_iosc = 1, + .has_losc_en = 1, + .has_auto_swt = 1, +}; + +static void __init sun50i_h6_rtc_clk_init(struct device_node *node) +{ + sun6i_rtc_clk_init(node, &sun50i_h6_rtc_data); +} +CLK_OF_DECLARE_DRIVER(sun50i_h6_rtc_clk, "allwinner,sun50i-h6-rtc", + sun50i_h6_rtc_clk_init); + static const struct sun6i_rtc_clk_data sun8i_v3_rtc_data = { .rc_osc_rate = 32000, .has_out_clk = 1, @@ -598,6 +633,33 @@ static const struct rtc_class_ops sun6i_rtc_ops = { .alarm_irq_enable = sun6i_rtc_alarm_irq_enable }; +#ifdef CONFIG_PM_SLEEP +/* Enable IRQ wake on suspend, to wake up from RTC. */ +static int sun6i_rtc_suspend(struct device *dev) +{ + struct sun6i_rtc_dev *chip = dev_get_drvdata(dev); + + if (device_may_wakeup(dev)) + enable_irq_wake(chip->irq); + + return 0; +} + +/* Disable IRQ wake on resume. */ +static int sun6i_rtc_resume(struct device *dev) +{ + struct sun6i_rtc_dev *chip = dev_get_drvdata(dev); + + if (device_may_wakeup(dev)) + disable_irq_wake(chip->irq); + + return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(sun6i_rtc_pm_ops, + sun6i_rtc_suspend, sun6i_rtc_resume); + static int sun6i_rtc_probe(struct platform_device *pdev) { struct sun6i_rtc_dev *chip = sun6i_rtc; @@ -610,10 +672,8 @@ static int sun6i_rtc_probe(struct platform_device *pdev) chip->dev = &pdev->dev; chip->irq = platform_get_irq(pdev, 0); - if (chip->irq < 0) { - dev_err(&pdev->dev, "No IRQ resource\n"); + if (chip->irq < 0) return chip->irq; - } ret = devm_request_irq(&pdev->dev, chip->irq, sun6i_rtc_alarmirq, 0, dev_name(&pdev->dev), chip); @@ -650,6 +710,8 @@ static int sun6i_rtc_probe(struct platform_device *pdev) clk_prepare_enable(chip->losc); + device_init_wakeup(&pdev->dev, 1); + chip->rtc = devm_rtc_device_register(&pdev->dev, "rtc-sun6i", &sun6i_rtc_ops, THIS_MODULE); if (IS_ERR(chip->rtc)) { @@ -675,6 +737,7 @@ static const struct of_device_id sun6i_rtc_dt_ids[] = { { .compatible = "allwinner,sun8i-r40-rtc" }, { .compatible = "allwinner,sun8i-v3-rtc" }, { .compatible = "allwinner,sun50i-h5-rtc" }, + { .compatible = "allwinner,sun50i-h6-rtc" }, { /* sentinel */ }, }; MODULE_DEVICE_TABLE(of, sun6i_rtc_dt_ids); @@ -684,6 +747,7 @@ static struct platform_driver sun6i_rtc_driver = { .driver = { .name = "sun6i-rtc", .of_match_table = sun6i_rtc_dt_ids, + .pm = &sun6i_rtc_pm_ops, }, }; builtin_platform_driver(sun6i_rtc_driver); diff --git a/drivers/rtc/rtc-sunxi.c b/drivers/rtc/rtc-sunxi.c index 6eeabb81106f..9b6f2483c1c6 100644 --- a/drivers/rtc/rtc-sunxi.c +++ b/drivers/rtc/rtc-sunxi.c @@ -442,10 +442,8 @@ static int sunxi_rtc_probe(struct platform_device *pdev) return PTR_ERR(chip->base); chip->irq = platform_get_irq(pdev, 0); - if (chip->irq < 0) { - dev_err(&pdev->dev, "No IRQ resource\n"); + if (chip->irq < 0) return chip->irq; - } ret = devm_request_irq(&pdev->dev, chip->irq, sunxi_rtc_alarmirq, 0, dev_name(&pdev->dev), chip); if (ret) { @@ -474,15 +472,7 @@ static int sunxi_rtc_probe(struct platform_device *pdev) chip->rtc->ops = &sunxi_rtc_ops; - ret = rtc_register_device(chip->rtc); - if (ret) { - dev_err(&pdev->dev, "unable to register device\n"); - return ret; - } - - dev_info(&pdev->dev, "RTC enabled\n"); - - return 0; + return rtc_register_device(chip->rtc); } static struct platform_driver sunxi_rtc_driver = { diff --git a/drivers/rtc/rtc-tegra.c b/drivers/rtc/rtc-tegra.c index 8fa1b3febf69..69d695bf9500 100644 --- a/drivers/rtc/rtc-tegra.c +++ b/drivers/rtc/rtc-tegra.c @@ -290,10 +290,8 @@ static int tegra_rtc_probe(struct platform_device *pdev) return PTR_ERR(info->base); ret = platform_get_irq(pdev, 0); - if (ret <= 0) { - dev_err(&pdev->dev, "failed to get platform IRQ: %d\n", ret); + if (ret <= 0) return ret; - } info->irq = ret; @@ -334,10 +332,8 @@ static int tegra_rtc_probe(struct platform_device *pdev) } ret = rtc_register_device(info->rtc); - if (ret) { - dev_err(&pdev->dev, "failed to register device: %d\n", ret); + if (ret) goto disable_clk; - } dev_notice(&pdev->dev, "Tegra internal Real Time Clock\n"); diff --git a/drivers/rtc/rtc-tps6586x.c b/drivers/rtc/rtc-tps6586x.c index d6434e514a52..859d901fa6cb 100644 --- a/drivers/rtc/rtc-tps6586x.c +++ b/drivers/rtc/rtc-tps6586x.c @@ -259,7 +259,6 @@ static int tps6586x_rtc_probe(struct platform_device *pdev) rtc->rtc = devm_rtc_allocate_device(&pdev->dev); if (IS_ERR(rtc->rtc)) { ret = PTR_ERR(rtc->rtc); - dev_err(&pdev->dev, "RTC allocate device: ret %d\n", ret); goto fail_rtc_register; } @@ -280,10 +279,8 @@ static int tps6586x_rtc_probe(struct platform_device *pdev) disable_irq(rtc->irq); ret = rtc_register_device(rtc->rtc); - if (ret) { - dev_err(&pdev->dev, "RTC device register: ret %d\n", ret); + if (ret) goto fail_rtc_register; - } return 0; diff --git a/drivers/rtc/rtc-tps65910.c b/drivers/rtc/rtc-tps65910.c index 7078f6da1cbc..2c0467a9e717 100644 --- a/drivers/rtc/rtc-tps65910.c +++ b/drivers/rtc/rtc-tps65910.c @@ -425,13 +425,7 @@ static int tps65910_rtc_probe(struct platform_device *pdev) tps_rtc->rtc->range_min = RTC_TIMESTAMP_BEGIN_2000; tps_rtc->rtc->range_max = RTC_TIMESTAMP_END_2099; - ret = rtc_register_device(tps_rtc->rtc); - if (ret) { - dev_err(&pdev->dev, "RTC device register: err %d\n", ret); - return ret; - } - - return 0; + return rtc_register_device(tps_rtc->rtc); } #ifdef CONFIG_PM_SLEEP diff --git a/drivers/rtc/rtc-vt8500.c b/drivers/rtc/rtc-vt8500.c index f59d232810de..d5d14cf86e0d 100644 --- a/drivers/rtc/rtc-vt8500.c +++ b/drivers/rtc/rtc-vt8500.c @@ -212,10 +212,8 @@ static int vt8500_rtc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, vt8500_rtc); vt8500_rtc->irq_alarm = platform_get_irq(pdev, 0); - if (vt8500_rtc->irq_alarm < 0) { - dev_err(&pdev->dev, "No alarm IRQ resource defined\n"); + if (vt8500_rtc->irq_alarm < 0) return vt8500_rtc->irq_alarm; - } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); vt8500_rtc->regbase = devm_ioremap_resource(&pdev->dev, res); diff --git a/drivers/rtc/rtc-xgene.c b/drivers/rtc/rtc-xgene.c index 9888383f0088..9683fbf7c78d 100644 --- a/drivers/rtc/rtc-xgene.c +++ b/drivers/rtc/rtc-xgene.c @@ -157,10 +157,8 @@ static int xgene_rtc_probe(struct platform_device *pdev) return PTR_ERR(pdata->rtc); irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "No IRQ resource\n"); + if (irq < 0) return irq; - } ret = devm_request_irq(&pdev->dev, irq, xgene_rtc_interrupt, 0, dev_name(&pdev->dev), pdata); if (ret) { diff --git a/drivers/rtc/rtc-zynqmp.c b/drivers/rtc/rtc-zynqmp.c index 00639594de0c..2c762757fb54 100644 --- a/drivers/rtc/rtc-zynqmp.c +++ b/drivers/rtc/rtc-zynqmp.c @@ -218,10 +218,8 @@ static int xlnx_rtc_probe(struct platform_device *pdev) return PTR_ERR(xrtcdev->reg_base); xrtcdev->alarm_irq = platform_get_irq_byname(pdev, "alarm"); - if (xrtcdev->alarm_irq < 0) { - dev_err(&pdev->dev, "no irq resource\n"); + if (xrtcdev->alarm_irq < 0) return xrtcdev->alarm_irq; - } ret = devm_request_irq(&pdev->dev, xrtcdev->alarm_irq, xlnx_rtc_interrupt, 0, dev_name(&pdev->dev), xrtcdev); @@ -231,10 +229,8 @@ static int xlnx_rtc_probe(struct platform_device *pdev) } xrtcdev->sec_irq = platform_get_irq_byname(pdev, "sec"); - if (xrtcdev->sec_irq < 0) { - dev_err(&pdev->dev, "no irq resource\n"); + if (xrtcdev->sec_irq < 0) return xrtcdev->sec_irq; - } ret = devm_request_irq(&pdev->dev, xrtcdev->sec_irq, xlnx_rtc_interrupt, 0, dev_name(&pdev->dev), xrtcdev); |