Commit 9dbd83f6 authored by Linus Torvalds's avatar Linus Torvalds

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
  ...
parents 379bb045 b99a3120
......@@ -25,6 +25,7 @@ properties:
- items:
- const: allwinner,sun50i-a64-rtc
- const: allwinner,sun8i-h3-rtc
- const: allwinner,sun50i-h6-rtc
reg:
maxItems: 1
......@@ -92,6 +93,18 @@ allOf:
minItems: 3
maxItems: 3
- if:
properties:
compatible:
contains:
const: allwinner,sun50i-h6-rtc
then:
properties:
clock-output-names:
minItems: 3
maxItems: 3
- if:
properties:
compatible:
......
NXP PCF2123 SPI Real Time Clock
Required properties:
- compatible: should be: "nxp,rtc-pcf2123"
- compatible: should be: "nxp,pcf2123"
or "microcrystal,rv2123"
- reg: should be the SPI slave chipselect address
......@@ -11,7 +11,7 @@ Optional properties:
Example:
pcf2123: rtc@3 {
compatible = "nxp,rtc-pcf2123"
compatible = "nxp,pcf2123"
reg = <3>
spi-cs-high;
};
......@@ -3,7 +3,9 @@
Philips PCF8563/Epson RTC8564 Real Time Clock
Required properties:
- compatible: Should contain "nxp,pcf8563".
- compatible: Should contain "nxp,pcf8563",
"epson,rtc8564" or
"microcrystal,rv8564"
- reg: I2C address for chip.
Optional property:
......
......@@ -19,6 +19,7 @@ Required properties:
"pericom,pt7c4338",
"epson,rx8025",
"isil,isl12057"
"epson,rx8130"
- reg: I2C bus address of the device
Optional properties:
......
Freescale FlexTimer Module (FTM) Alarm
Required properties:
- compatible : Should be "fsl,<chip>-ftm-alarm", the
supported chips include
"fsl,ls1012a-ftm-alarm"
"fsl,ls1021a-ftm-alarm"
"fsl,ls1028a-ftm-alarm"
"fsl,ls1043a-ftm-alarm"
"fsl,ls1046a-ftm-alarm"
"fsl,ls1088a-ftm-alarm"
"fsl,ls208xa-ftm-alarm"
"fsl,lx2160a-ftm-alarm"
- reg : Specifies base physical address and size of the register sets for the
FlexTimer Module.
- interrupts : Should be the FlexTimer Module interrupt.
- fsl,rcpm-wakeup property and rcpm node : Please refer
Documentation/devicetree/bindings/soc/fsl/rcpm.txt
Optional properties:
- big-endian: If the host controller is big-endian mode, specify this property.
The default endian mode is little-endian.
Example:
rcpm: rcpm@1e34040 {
compatible = "fsl,ls1088a-rcpm", "fsl,qoriq-rcpm-2.1+";
reg = <0x0 0x1e34040 0x0 0x18>;
#fsl,rcpm-wakeup-cells = <6>;
};
ftm_alarm0: timer@2800000 {
compatible = "fsl,ls1088a-ftm-alarm";
reg = <0x0 0x2800000 0x0 0x10000>;
fsl,rcpm-wakeup = <&rcpm 0x0 0x0 0x0 0x0 0x4000 0x0>;
interrupts = <0 44 4>;
};
* Amlogic Virtual RTC (VRTC)
This is a Linux interface to an RTC managed by firmware, hence it's
virtual from a Linux perspective. The interface is 1 register where
an alarm time (in seconds) is to be written.
Required properties:
- compatible: should be "amlogic,meson-vrtc"
- reg: physical address for the alarm register
The alarm register is a simple scratch register shared between the
application processors (AP) and the secure co-processor (SCP.) When
the AP suspends, the SCP will use the value of this register to
program an always-on timer before going sleep. When the timer expires,
the SCP will wake up and will then wake the AP.
Example:
vrtc: rtc@0a8 {
compatible = "amlogic,meson-vrtc";
reg = <0x0 0x000a8 0x0 0x4>;
};
......@@ -52,8 +52,6 @@ properties:
- nxp,pcf2127
# Real-time clock
- nxp,pcf2129
# Real-time clock/calendar
- nxp,pcf8563
# Real-time Clock Module
- pericom,pt7c4338
# I2C bus SERIAL INTERFACE REAL-TIME CLOCK IC
......
......@@ -1466,6 +1466,7 @@ F: arch/arm64/boot/dts/amlogic/
F: drivers/pinctrl/meson/
F: drivers/mmc/host/meson*
F: drivers/soc/amlogic/
F: drivers/rtc/rtc-meson*
N: meson
ARM/Amlogic Meson SoC Sound Drivers
......
......@@ -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
......
......@@ -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
......
......@@ -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);
......
......@@ -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.
......
......@@ -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;
......
......@@ -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
......
......@@ -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)
......
......@@ -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
......
......@@ -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);
......
......@@ -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[] = {
......
......@@ -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));
......
......@@ -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)
......
......@@ -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 = {
......
......@@ -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);
......
......@@ -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;
......
......@@ -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);
......
......@@ -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);
......
......@@ -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;
......
// 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");
......@@ -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);
......
......@@ -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);
......
......@@ -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);
......
......@@ -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);
......
......@@ -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 @@ static int max77686_init_rtc_regmap(struct max77686_rtc_info *info)
&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;
}
......
// 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");
......@@ -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;
......
......@@ -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;
}
......
......@@ -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. */
......
......@@ -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);
......
// 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");
......@@ -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, &reg);
ret = regmap_read(pcf2123->map, PCF2123_REG_OFFSET, &reg);
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);
......
......@@ -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
......
......@@ -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;
......
......@@ -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);
......
......@@ -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);
......
......@@ -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");
......
......@@ -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))
......
......@@ -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));
......
......@@ -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,
......
......@@ -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,
......
......@@ -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,
......
......@@ -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,
......
......@@ -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,
};
......
......@@ -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);
......
......@@ -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);
......
......@@ -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;
}
......
......@@ -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);
......
......@@ -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;
}
......
......@@ -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);
......
......@@ -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;
}
......
......@@ -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);
......@@ -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 = {
......
......@@ -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");
......
......@@ -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;
......
......@@ -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
......
......@@ -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);
......
......@@ -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) {
......
......@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment