summaryrefslogtreecommitdiff
path: root/drivers/rtc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/rtc')
-rw-r--r--drivers/rtc/Kconfig38
-rw-r--r--drivers/rtc/Makefile2
-rw-r--r--drivers/rtc/class.c33
-rw-r--r--drivers/rtc/interface.c2
-rw-r--r--drivers/rtc/rtc-88pm80x.c28
-rw-r--r--drivers/rtc/rtc-ab-b5ze-s3.c2
-rw-r--r--drivers/rtc/rtc-ab8500.c2
-rw-r--r--drivers/rtc/rtc-armada38x.c33
-rw-r--r--drivers/rtc/rtc-as3722.c4
-rw-r--r--drivers/rtc/rtc-at91rm9200.c43
-rw-r--r--drivers/rtc/rtc-at91sam9.c45
-rw-r--r--drivers/rtc/rtc-bfin.c2
-rw-r--r--drivers/rtc/rtc-bq32k.c3
-rw-r--r--drivers/rtc/rtc-cmos.c125
-rw-r--r--drivers/rtc/rtc-coh901331.c1
-rw-r--r--drivers/rtc/rtc-core.h19
-rw-r--r--drivers/rtc/rtc-da9063.c392
-rw-r--r--drivers/rtc/rtc-dev.c1
-rw-r--r--drivers/rtc/rtc-ds1305.c18
-rw-r--r--drivers/rtc/rtc-ds1307.c120
-rw-r--r--drivers/rtc/rtc-ds1343.c12
-rw-r--r--drivers/rtc/rtc-ds1374.c12
-rw-r--r--drivers/rtc/rtc-ds1511.c42
-rw-r--r--drivers/rtc/rtc-ds1553.c4
-rw-r--r--drivers/rtc/rtc-ds1685.c22
-rw-r--r--drivers/rtc/rtc-ds1742.c4
-rw-r--r--drivers/rtc/rtc-ds3232.c8
-rw-r--r--drivers/rtc/rtc-fm3130.c1
-rw-r--r--drivers/rtc/rtc-gemini.c5
-rw-r--r--drivers/rtc/rtc-hym8563.c1
-rw-r--r--drivers/rtc/rtc-isl12022.c8
-rw-r--r--drivers/rtc/rtc-isl12057.c2
-rw-r--r--drivers/rtc/rtc-lpc24xx.c310
-rw-r--r--drivers/rtc/rtc-m48t59.c18
-rw-r--r--drivers/rtc/rtc-max8997.c1
-rw-r--r--drivers/rtc/rtc-moxart.c1
-rw-r--r--drivers/rtc/rtc-mpc5121.c1
-rw-r--r--drivers/rtc/rtc-mt6397.c27
-rw-r--r--drivers/rtc/rtc-mv.c1
-rw-r--r--drivers/rtc/rtc-mxc.c60
-rw-r--r--drivers/rtc/rtc-omap.c33
-rw-r--r--drivers/rtc/rtc-opal.c10
-rw-r--r--drivers/rtc/rtc-pcf2123.c8
-rw-r--r--drivers/rtc/rtc-pcf2127.c35
-rw-r--r--drivers/rtc/rtc-pcf85063.c1
-rw-r--r--drivers/rtc/rtc-pcf8523.c1
-rw-r--r--drivers/rtc/rtc-pcf8563.c1
-rw-r--r--drivers/rtc/rtc-pcf8583.c1
-rw-r--r--drivers/rtc/rtc-pl031.c2
-rw-r--r--drivers/rtc/rtc-pxa.c55
-rw-r--r--drivers/rtc/rtc-rp5c01.c4
-rw-r--r--drivers/rtc/rtc-rx8025.c277
-rw-r--r--drivers/rtc/rtc-rx8581.c1
-rw-r--r--drivers/rtc/rtc-s3c.c4
-rw-r--r--drivers/rtc/rtc-s5m.c1
-rw-r--r--drivers/rtc/rtc-sa1100.c139
-rw-r--r--drivers/rtc/rtc-sa1100.h23
-rw-r--r--drivers/rtc/rtc-sirfsoc.c107
-rw-r--r--drivers/rtc/rtc-snvs.c132
-rw-r--r--drivers/rtc/rtc-st-lpc.c2
-rw-r--r--drivers/rtc/rtc-stk17ta8.c4
-rw-r--r--drivers/rtc/rtc-sysfs.c72
-rw-r--r--drivers/rtc/rtc-tx4939.c6
-rw-r--r--drivers/rtc/rtc-vt8500.c1
-rw-r--r--drivers/rtc/rtc-zynqmp.c279
65 files changed, 1724 insertions, 928 deletions
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 83b4b89b9..9d4290617 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -945,11 +945,11 @@ config RTC_DRV_DA9055
will be called rtc-da9055
config RTC_DRV_DA9063
- tristate "Dialog Semiconductor DA9063 RTC"
- depends on MFD_DA9063
+ tristate "Dialog Semiconductor DA9063/DA9062 RTC"
+ depends on MFD_DA9063 || MFD_DA9062
help
If you say yes here you will get support for the RTC subsystem
- of the Dialog Semiconductor DA9063.
+ for the Dialog Semiconductor PMIC chips DA9063 and DA9062.
This driver can also be built as a module. If so, the module
will be called "rtc-da9063".
@@ -1116,6 +1116,13 @@ config RTC_DRV_OPAL
This driver can also be built as a module. If so, the module
will be called rtc-opal.
+config RTC_DRV_ZYNQMP
+ tristate "Xilinx Zynq Ultrascale+ MPSoC RTC"
+ depends on OF
+ help
+ If you say yes here you get support for the RTC controller found on
+ Xilinx Zynq Ultrascale+ MPSoC.
+
comment "on-CPU RTC drivers"
config RTC_DRV_DAVINCI
@@ -1306,11 +1313,13 @@ config RTC_DRV_GENERIC
just say Y.
config RTC_DRV_PXA
- tristate "PXA27x/PXA3xx"
- depends on ARCH_PXA
- help
- If you say Y here you will get access to the real time clock
- built into your PXA27x or PXA3xx CPU.
+ tristate "PXA27x/PXA3xx"
+ depends on ARCH_PXA
+ select RTC_DRV_SA1100
+ help
+ If you say Y here you will get access to the real time clock
+ built into your PXA27x or PXA3xx CPU. This RTC is actually 2 RTCs
+ consisting of an SA1100 compatible RTC and the extended PXA RTC.
This RTC driver uses PXA RTC registers available since pxa27x
series (RDxR, RYxR) instead of legacy RCNR, RTAR.
@@ -1456,6 +1465,18 @@ config RTC_DRV_JZ4740
This driver can also be buillt as a module. If so, the module
will be called rtc-jz4740.
+config RTC_DRV_LPC24XX
+ tristate "NXP RTC for LPC178x/18xx/408x/43xx"
+ depends on ARCH_LPC18XX || COMPILE_TEST
+ depends on OF && HAS_IOMEM
+ help
+ This enables support for the NXP RTC found which can be found on
+ NXP LPC178x/18xx/408x/43xx devices.
+
+ If you have one of the devices above enable this driver to use
+ the hardware RTC. This driver can also be buillt as a module. If
+ so, the module will be called rtc-lpc24xx.
+
config RTC_DRV_LPC32XX
depends on ARCH_LPC32XX
tristate "NXP LPC32XX RTC"
@@ -1523,6 +1544,7 @@ config RTC_DRV_MXC
config RTC_DRV_SNVS
tristate "Freescale SNVS RTC support"
+ select REGMAP_MMIO
depends on HAS_IOMEM
depends on OF
help
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 1b09a62fc..e491eb524 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -74,6 +74,7 @@ obj-$(CONFIG_RTC_DRV_ISL12057) += rtc-isl12057.o
obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o
obj-$(CONFIG_RTC_DRV_JZ4740) += rtc-jz4740.o
obj-$(CONFIG_RTC_DRV_LP8788) += rtc-lp8788.o
+obj-$(CONFIG_RTC_DRV_LPC24XX) += rtc-lpc24xx.o
obj-$(CONFIG_RTC_DRV_LPC32XX) += rtc-lpc32xx.o
obj-$(CONFIG_RTC_DRV_LOONGSON1) += rtc-ls1x.o
obj-$(CONFIG_RTC_DRV_M41T80) += rtc-m41t80.o
@@ -158,3 +159,4 @@ obj-$(CONFIG_RTC_DRV_WM831X) += rtc-wm831x.o
obj-$(CONFIG_RTC_DRV_WM8350) += rtc-wm8350.o
obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o
obj-$(CONFIG_RTC_DRV_XGENE) += rtc-xgene.o
+obj-$(CONFIG_RTC_DRV_ZYNQMP) += rtc-zynqmp.o
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c
index ea2a315df..de86578bc 100644
--- a/drivers/rtc/class.c
+++ b/drivers/rtc/class.c
@@ -202,6 +202,7 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev,
rtc->max_user_freq = 64;
rtc->dev.parent = dev;
rtc->dev.class = rtc_class;
+ rtc->dev.groups = rtc_get_dev_attribute_groups();
rtc->dev.release = rtc_device_release;
mutex_init(&rtc->ops_lock);
@@ -234,12 +235,12 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev,
err = device_register(&rtc->dev);
if (err) {
+ /* This will free both memory and the ID */
put_device(&rtc->dev);
- goto exit_kfree;
+ goto exit;
}
rtc_dev_add_device(rtc);
- rtc_sysfs_add_device(rtc);
rtc_proc_add_device(rtc);
dev_info(dev, "rtc core: registered %s as %s\n",
@@ -247,9 +248,6 @@ struct rtc_device *rtc_device_register(const char *name, struct device *dev,
return rtc;
-exit_kfree:
- kfree(rtc);
-
exit_ida:
ida_simple_remove(&rtc_ida, id);
@@ -268,19 +266,17 @@ EXPORT_SYMBOL_GPL(rtc_device_register);
*/
void rtc_device_unregister(struct rtc_device *rtc)
{
- if (get_device(&rtc->dev) != NULL) {
- mutex_lock(&rtc->ops_lock);
- /* remove innards of this RTC, then disable it, before
- * letting any rtc_class_open() users access it again
- */
- rtc_sysfs_del_device(rtc);
- rtc_dev_del_device(rtc);
- rtc_proc_del_device(rtc);
- device_unregister(&rtc->dev);
- rtc->ops = NULL;
- mutex_unlock(&rtc->ops_lock);
- put_device(&rtc->dev);
- }
+ mutex_lock(&rtc->ops_lock);
+ /*
+ * Remove innards of this RTC, then disable it, before
+ * letting any rtc_class_open() users access it again
+ */
+ rtc_dev_del_device(rtc);
+ rtc_proc_del_device(rtc);
+ device_del(&rtc->dev);
+ rtc->ops = NULL;
+ mutex_unlock(&rtc->ops_lock);
+ put_device(&rtc->dev);
}
EXPORT_SYMBOL_GPL(rtc_device_unregister);
@@ -363,7 +359,6 @@ static int __init rtc_init(void)
}
rtc_class->pm = RTC_CLASS_DEV_PM_OPS;
rtc_dev_init();
- rtc_sysfs_init(rtc_class);
return 0;
}
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c
index 11b639067..5836751b8 100644
--- a/drivers/rtc/interface.c
+++ b/drivers/rtc/interface.c
@@ -564,7 +564,7 @@ enum hrtimer_restart rtc_pie_update_irq(struct hrtimer *timer)
void rtc_update_irq(struct rtc_device *rtc,
unsigned long num, unsigned long events)
{
- if (unlikely(IS_ERR_OR_NULL(rtc)))
+ if (IS_ERR_OR_NULL(rtc))
return;
pm_stay_awake(rtc->dev.parent);
diff --git a/drivers/rtc/rtc-88pm80x.c b/drivers/rtc/rtc-88pm80x.c
index 7df0579d9..466bf7f9a 100644
--- a/drivers/rtc/rtc-88pm80x.c
+++ b/drivers/rtc/rtc-88pm80x.c
@@ -251,17 +251,26 @@ static SIMPLE_DEV_PM_OPS(pm80x_rtc_pm_ops, pm80x_rtc_suspend, pm80x_rtc_resume);
static int pm80x_rtc_probe(struct platform_device *pdev)
{
struct pm80x_chip *chip = dev_get_drvdata(pdev->dev.parent);
- struct pm80x_platform_data *pm80x_pdata =
- dev_get_platdata(pdev->dev.parent);
- struct pm80x_rtc_pdata *pdata = NULL;
+ struct pm80x_rtc_pdata *pdata = dev_get_platdata(&pdev->dev);
struct pm80x_rtc_info *info;
+ struct device_node *node = pdev->dev.of_node;
struct rtc_time tm;
unsigned long ticks = 0;
int ret;
- pdata = dev_get_platdata(&pdev->dev);
- if (pdata == NULL)
- dev_warn(&pdev->dev, "No platform data!\n");
+ if (!pdata && !node) {
+ dev_err(&pdev->dev,
+ "pm80x-rtc requires platform data or of_node\n");
+ return -EINVAL;
+ }
+
+ if (!pdata) {
+ pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata) {
+ dev_err(&pdev->dev, "failed to allocate memory\n");
+ return -ENOMEM;
+ }
+ }
info =
devm_kzalloc(&pdev->dev, sizeof(struct pm80x_rtc_info), GFP_KERNEL);
@@ -327,11 +336,8 @@ static int pm80x_rtc_probe(struct platform_device *pdev)
regmap_update_bits(info->map, PM800_RTC_CONTROL, PM800_RTC1_USE_XO,
PM800_RTC1_USE_XO);
- if (pm80x_pdata) {
- pdata = pm80x_pdata->rtc;
- if (pdata)
- info->rtc_dev->dev.platform_data = &pdata->rtc_wakeup;
- }
+ /* remember whether this power up is caused by PMIC RTC or not */
+ info->rtc_dev->dev.platform_data = &pdata->rtc_wakeup;
device_init_wakeup(&pdev->dev, 1);
diff --git a/drivers/rtc/rtc-ab-b5ze-s3.c b/drivers/rtc/rtc-ab-b5ze-s3.c
index b5cbc1bf5..a319bf1e4 100644
--- a/drivers/rtc/rtc-ab-b5ze-s3.c
+++ b/drivers/rtc/rtc-ab-b5ze-s3.c
@@ -1009,6 +1009,7 @@ static const struct of_device_id abb5zes3_dt_match[] = {
{ .compatible = "abracon,abb5zes3" },
{ },
};
+MODULE_DEVICE_TABLE(of, abb5zes3_dt_match);
#endif
static const struct i2c_device_id abb5zes3_id[] = {
@@ -1020,7 +1021,6 @@ MODULE_DEVICE_TABLE(i2c, abb5zes3_id);
static struct i2c_driver abb5zes3_driver = {
.driver = {
.name = DRV_NAME,
- .owner = THIS_MODULE,
.pm = &abb5zes3_rtc_pm_ops,
.of_match_table = of_match_ptr(abb5zes3_dt_match),
},
diff --git a/drivers/rtc/rtc-ab8500.c b/drivers/rtc/rtc-ab8500.c
index 133d2e2e1..51407c4c7 100644
--- a/drivers/rtc/rtc-ab8500.c
+++ b/drivers/rtc/rtc-ab8500.c
@@ -445,7 +445,9 @@ static const struct rtc_class_ops ab8540_rtc_ops = {
static const struct platform_device_id ab85xx_rtc_ids[] = {
{ "ab8500-rtc", (kernel_ulong_t)&ab8500_rtc_ops, },
{ "ab8540-rtc", (kernel_ulong_t)&ab8540_rtc_ops, },
+ { /* sentinel */ }
};
+MODULE_DEVICE_TABLE(platform, ab85xx_rtc_ids);
static int ab8500_rtc_probe(struct platform_device *pdev)
{
diff --git a/drivers/rtc/rtc-armada38x.c b/drivers/rtc/rtc-armada38x.c
index 2b08cac62..9a3f2a6f5 100644
--- a/drivers/rtc/rtc-armada38x.c
+++ b/drivers/rtc/rtc-armada38x.c
@@ -40,13 +40,6 @@ struct armada38x_rtc {
void __iomem *regs;
void __iomem *regs_soc;
spinlock_t lock;
- /*
- * While setting the time, the RTC TIME register should not be
- * accessed. Setting the RTC time involves sleeping during
- * 100ms, so a mutex instead of a spinlock is used to protect
- * it
- */
- struct mutex mutex_time;
int irq;
};
@@ -64,9 +57,9 @@ static void rtc_delayed_write(u32 val, struct armada38x_rtc *rtc, int offset)
static int armada38x_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
struct armada38x_rtc *rtc = dev_get_drvdata(dev);
- unsigned long time, time_check;
+ unsigned long time, time_check, flags;
- mutex_lock(&rtc->mutex_time);
+ spin_lock_irqsave(&rtc->lock, flags);
time = readl(rtc->regs + RTC_TIME);
/*
* WA for failing time set attempts. As stated in HW ERRATA if
@@ -77,7 +70,7 @@ static int armada38x_rtc_read_time(struct device *dev, struct rtc_time *tm)
if ((time_check - time) > 1)
time_check = readl(rtc->regs + RTC_TIME);
- mutex_unlock(&rtc->mutex_time);
+ spin_unlock_irqrestore(&rtc->lock, flags);
rtc_time_to_tm(time_check, tm);
@@ -88,23 +81,23 @@ static int armada38x_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
struct armada38x_rtc *rtc = dev_get_drvdata(dev);
int ret = 0;
- unsigned long time;
+ unsigned long time, flags;
ret = rtc_tm_to_time(tm, &time);
if (ret)
goto out;
/*
- * Setting the RTC time not always succeeds. According to the
- * errata we need to first write on the status register and
- * then wait for 100ms before writing to the time register to be
- * sure that the data will be taken into account.
+ * According to errata FE-3124064, Write to RTC TIME register
+ * may fail. As a workaround, after writing to RTC TIME
+ * register, issue a dummy write of 0x0 twice to RTC Status
+ * register.
*/
- mutex_lock(&rtc->mutex_time);
- rtc_delayed_write(0, rtc, RTC_STATUS);
- msleep(100);
+ spin_lock_irqsave(&rtc->lock, flags);
rtc_delayed_write(time, rtc, RTC_TIME);
- mutex_unlock(&rtc->mutex_time);
+ rtc_delayed_write(0, rtc, RTC_STATUS);
+ rtc_delayed_write(0, rtc, RTC_STATUS);
+ spin_unlock_irqrestore(&rtc->lock, flags);
out:
return ret;
@@ -229,7 +222,6 @@ static __init int armada38x_rtc_probe(struct platform_device *pdev)
return -ENOMEM;
spin_lock_init(&rtc->lock);
- mutex_init(&rtc->mutex_time);
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rtc");
rtc->regs = devm_ioremap_resource(&pdev->dev, res);
@@ -303,6 +295,7 @@ static const struct of_device_id armada38x_rtc_of_match_table[] = {
{ .compatible = "marvell,armada-380-rtc", },
{}
};
+MODULE_DEVICE_TABLE(of, armada38x_rtc_of_match_table);
#endif
static struct platform_driver armada38x_rtc_driver = {
diff --git a/drivers/rtc/rtc-as3722.c b/drivers/rtc/rtc-as3722.c
index 9f38eda69..56cc58211 100644
--- a/drivers/rtc/rtc-as3722.c
+++ b/drivers/rtc/rtc-as3722.c
@@ -45,7 +45,7 @@ static void as3722_time_to_reg(u8 *rbuff, struct rtc_time *tm)
rbuff[1] = bin2bcd(tm->tm_min);
rbuff[2] = bin2bcd(tm->tm_hour);
rbuff[3] = bin2bcd(tm->tm_mday);
- rbuff[4] = bin2bcd(tm->tm_mon);
+ rbuff[4] = bin2bcd(tm->tm_mon + 1);
rbuff[5] = bin2bcd(tm->tm_year - (AS3722_RTC_START_YEAR - 1900));
}
@@ -55,7 +55,7 @@ static void as3722_reg_to_time(u8 *rbuff, struct rtc_time *tm)
tm->tm_min = bcd2bin(rbuff[1] & 0x7F);
tm->tm_hour = bcd2bin(rbuff[2] & 0x3F);
tm->tm_mday = bcd2bin(rbuff[3] & 0x3F);
- tm->tm_mon = bcd2bin(rbuff[4] & 0x1F);
+ tm->tm_mon = bcd2bin(rbuff[4] & 0x1F) - 1;
tm->tm_year = (AS3722_RTC_START_YEAR - 1900) + bcd2bin(rbuff[5] & 0x7F);
return;
}
diff --git a/drivers/rtc/rtc-at91rm9200.c b/drivers/rtc/rtc-at91rm9200.c
index 35efd3f75..cb62e214b 100644
--- a/drivers/rtc/rtc-at91rm9200.c
+++ b/drivers/rtc/rtc-at91rm9200.c
@@ -18,20 +18,21 @@
*
*/
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/time.h>
-#include <linux/rtc.h>
#include <linux/bcd.h>
+#include <linux/clk.h>
+#include <linux/completion.h>
#include <linux/interrupt.h>
-#include <linux/spinlock.h>
#include <linux/ioctl.h>
-#include <linux/completion.h>
#include <linux/io.h>
-#include <linux/of.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/of_device.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/rtc.h>
+#include <linux/spinlock.h>
#include <linux/suspend.h>
+#include <linux/time.h>
#include <linux/uaccess.h>
#include "rtc-at91rm9200.h"
@@ -59,6 +60,7 @@ static bool suspended;
static DEFINE_SPINLOCK(suspended_lock);
static unsigned long cached_events;
static u32 at91_rtc_imr;
+static struct clk *sclk;
static void at91_rtc_write_ier(u32 mask)
{
@@ -407,6 +409,16 @@ static int __init at91_rtc_probe(struct platform_device *pdev)
return -ENOMEM;
}
+ sclk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(sclk))
+ return PTR_ERR(sclk);
+
+ ret = clk_prepare_enable(sclk);
+ if (ret) {
+ dev_err(&pdev->dev, "Could not enable slow clock\n");
+ return ret;
+ }
+
at91_rtc_write(AT91_RTC_CR, 0);
at91_rtc_write(AT91_RTC_MR, 0); /* 24 hour mode */
@@ -420,7 +432,7 @@ static int __init at91_rtc_probe(struct platform_device *pdev)
"at91_rtc", pdev);
if (ret) {
dev_err(&pdev->dev, "IRQ %d already in use.\n", irq);
- return ret;
+ goto err_clk;
}
/* cpu init code should really have flagged this device as
@@ -431,8 +443,10 @@ static int __init at91_rtc_probe(struct platform_device *pdev)
rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
&at91_rtc_ops, THIS_MODULE);
- if (IS_ERR(rtc))
- return PTR_ERR(rtc);
+ if (IS_ERR(rtc)) {
+ ret = PTR_ERR(rtc);
+ goto err_clk;
+ }
platform_set_drvdata(pdev, rtc);
/* enable SECEV interrupt in order to initialize at91_rtc_upd_rdy
@@ -442,6 +456,11 @@ static int __init at91_rtc_probe(struct platform_device *pdev)
dev_info(&pdev->dev, "AT91 Real Time Clock driver.\n");
return 0;
+
+err_clk:
+ clk_disable_unprepare(sclk);
+
+ return ret;
}
/*
@@ -454,6 +473,8 @@ static int __exit at91_rtc_remove(struct platform_device *pdev)
AT91_RTC_SECEV | AT91_RTC_TIMEV |
AT91_RTC_CALEV);
+ clk_disable_unprepare(sclk);
+
return 0;
}
diff --git a/drivers/rtc/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c
index 5ccaee32d..7206e2fa4 100644
--- a/drivers/rtc/rtc-at91sam9.c
+++ b/drivers/rtc/rtc-at91sam9.c
@@ -11,20 +11,20 @@
* 2 of the License, or (at your option) any later version.
*/
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/time.h>
-#include <linux/rtc.h>
+#include <linux/clk.h>
#include <linux/interrupt.h>
#include <linux/ioctl.h>
-#include <linux/slab.h>
-#include <linux/platform_data/atmel.h>
#include <linux/io.h>
+#include <linux/kernel.h>
#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
#include <linux/regmap.h>
+#include <linux/rtc.h>
+#include <linux/slab.h>
#include <linux/suspend.h>
-#include <linux/clk.h>
+#include <linux/time.h>
/*
* This driver uses two configurable hardware resources that live in the
@@ -425,18 +425,19 @@ static int at91_rtc_probe(struct platform_device *pdev)
if (IS_ERR(rtc->sclk))
return PTR_ERR(rtc->sclk);
- sclk_rate = clk_get_rate(rtc->sclk);
- if (!sclk_rate || sclk_rate > AT91_RTT_RTPRES) {
- dev_err(&pdev->dev, "Invalid slow clock rate\n");
- return -EINVAL;
- }
-
ret = clk_prepare_enable(rtc->sclk);
if (ret) {
dev_err(&pdev->dev, "Could not enable slow clock\n");
return ret;
}
+ sclk_rate = clk_get_rate(rtc->sclk);
+ if (!sclk_rate || sclk_rate > AT91_RTT_RTPRES) {
+ dev_err(&pdev->dev, "Invalid slow clock rate\n");
+ ret = -EINVAL;
+ goto err_clk;
+ }
+
mr = rtt_readl(rtc, MR);
/* unless RTT is counting at 1 Hz, re-initialize it */
@@ -451,8 +452,10 @@ static int at91_rtc_probe(struct platform_device *pdev)
rtc->rtcdev = devm_rtc_device_register(&pdev->dev, pdev->name,
&at91_rtc_ops, THIS_MODULE);
- if (IS_ERR(rtc->rtcdev))
- return PTR_ERR(rtc->rtcdev);
+ if (IS_ERR(rtc->rtcdev)) {
+ ret = PTR_ERR(rtc->rtcdev);
+ goto err_clk;
+ }
/* register irq handler after we know what name we'll use */
ret = devm_request_irq(&pdev->dev, rtc->irq, at91_rtc_interrupt,
@@ -460,7 +463,7 @@ static int at91_rtc_probe(struct platform_device *pdev)
dev_name(&rtc->rtcdev->dev), rtc);
if (ret) {
dev_dbg(&pdev->dev, "can't share IRQ %d?\n", rtc->irq);
- return ret;
+ goto err_clk;
}
/* NOTE: sam9260 rev A silicon has a ROM bug which resets the
@@ -474,6 +477,11 @@ static int at91_rtc_probe(struct platform_device *pdev)
dev_name(&rtc->rtcdev->dev));
return 0;
+
+err_clk:
+ clk_disable_unprepare(rtc->sclk);
+
+ return ret;
}
/*
@@ -487,8 +495,7 @@ static int at91_rtc_remove(struct platform_device *pdev)
/* disable all interrupts */
rtt_writel(rtc, MR, mr & ~(AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN));
- if (!IS_ERR(rtc->sclk))
- clk_disable_unprepare(rtc->sclk);
+ clk_disable_unprepare(rtc->sclk);
return 0;
}
diff --git a/drivers/rtc/rtc-bfin.c b/drivers/rtc/rtc-bfin.c
index 3d44b1172..535a5f933 100644
--- a/drivers/rtc/rtc-bfin.c
+++ b/drivers/rtc/rtc-bfin.c
@@ -361,7 +361,7 @@ static int bfin_rtc_probe(struct platform_device *pdev)
/* Register our RTC with the RTC framework */
rtc->rtc_dev = devm_rtc_device_register(dev, pdev->name, &bfin_rtc_ops,
THIS_MODULE);
- if (unlikely(IS_ERR(rtc->rtc_dev)))
+ if (IS_ERR(rtc->rtc_dev))
return PTR_ERR(rtc->rtc_dev);
/* Grab the IRQ and init the hardware */
diff --git a/drivers/rtc/rtc-bq32k.c b/drivers/rtc/rtc-bq32k.c
index 92679df6d..0299988b4 100644
--- a/drivers/rtc/rtc-bq32k.c
+++ b/drivers/rtc/rtc-bq32k.c
@@ -212,7 +212,7 @@ static int bq32k_probe(struct i2c_client *client,
if (error)
return error;
- if (client && client->dev.of_node)
+ if (client->dev.of_node)
trickle_charger_of_init(dev, client->dev.of_node);
rtc = devm_rtc_device_register(&client->dev, bq32k_driver.driver.name,
@@ -234,7 +234,6 @@ MODULE_DEVICE_TABLE(i2c, bq32k_id);
static struct i2c_driver bq32k_driver = {
.driver = {
.name = "bq32k",
- .owner = THIS_MODULE,
},
.probe = bq32k_probe,
.id_table = bq32k_id,
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c
index a82556a07..8f7034ba7 100644
--- a/drivers/rtc/rtc-cmos.c
+++ b/drivers/rtc/rtc-cmos.c
@@ -41,7 +41,6 @@
#include <linux/pm.h>
#include <linux/of.h>
#include <linux/of_platform.h>
-#include <linux/dmi.h>
/* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */
#include <asm-generic/rtc.h>
@@ -51,6 +50,7 @@ struct cmos_rtc {
struct device *dev;
int irq;
struct resource *iomem;
+ time64_t alarm_expires;
void (*wake_on)(struct device *);
void (*wake_off)(struct device *);
@@ -377,53 +377,11 @@ static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t)
spin_unlock_irq(&rtc_lock);
- return 0;
-}
-
-/*
- * Do not disable RTC alarm on shutdown - workaround for b0rked BIOSes.
- */
-static bool alarm_disable_quirk;
+ cmos->alarm_expires = rtc_tm_to_time64(&t->time);
-static int __init set_alarm_disable_quirk(const struct dmi_system_id *id)
-{
- alarm_disable_quirk = true;
- pr_info("BIOS has alarm-disable quirk - RTC alarms disabled\n");
return 0;
}
-static const struct dmi_system_id rtc_quirks[] __initconst = {
- /* https://bugzilla.novell.com/show_bug.cgi?id=805740 */
- {
- .callback = set_alarm_disable_quirk,
- .ident = "IBM Truman",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
- DMI_MATCH(DMI_PRODUCT_NAME, "4852570"),
- },
- },
- /* https://bugzilla.novell.com/show_bug.cgi?id=812592 */
- {
- .callback = set_alarm_disable_quirk,
- .ident = "Gigabyte GA-990XA-UD3",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR,
- "Gigabyte Technology Co., Ltd."),
- DMI_MATCH(DMI_PRODUCT_NAME, "GA-990XA-UD3"),
- },
- },
- /* http://permalink.gmane.org/gmane.linux.kernel/1604474 */
- {
- .callback = set_alarm_disable_quirk,
- .ident = "Toshiba Satellite L300",
- .matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
- DMI_MATCH(DMI_PRODUCT_NAME, "Satellite L300"),
- },
- },
- {}
-};
-
static int cmos_alarm_irq_enable(struct device *dev, unsigned int enabled)
{
struct cmos_rtc *cmos = dev_get_drvdata(dev);
@@ -432,9 +390,6 @@ static int cmos_alarm_irq_enable(struct device *dev, unsigned int enabled)
if (!is_valid_irq(cmos->irq))
return -EINVAL;
- if (alarm_disable_quirk)
- return 0;
-
spin_lock_irqsave(&rtc_lock, flags);
if (enabled)
@@ -512,13 +467,6 @@ cmos_nvram_read(struct file *filp, struct kobject *kobj,
{
int retval;
- if (unlikely(off >= attr->size))
- return 0;
- if (unlikely(off < 0))
- return -EINVAL;
- if ((off + count) > attr->size)
- count = attr->size - off;
-
off += NVRAM_OFFSET;
spin_lock_irq(&rtc_lock);
for (retval = 0; count; count--, off++, retval++) {
@@ -543,12 +491,6 @@ cmos_nvram_write(struct file *filp, struct kobject *kobj,
int retval;
cmos = dev_get_drvdata(container_of(kobj, struct device, kobj));
- if (unlikely(off >= attr->size))
- return -EFBIG;
- if (unlikely(off < 0))
- return -EINVAL;
- if ((off + count) > attr->size)
- count = attr->size - off;
/* NOTE: on at least PCs and Ataris, the boot firmware uses a
* checksum on part of the NVRAM data. That's currently ignored
@@ -860,6 +802,51 @@ static void __exit cmos_do_remove(struct device *dev)
cmos->dev = NULL;
}
+static int cmos_aie_poweroff(struct device *dev)
+{
+ struct cmos_rtc *cmos = dev_get_drvdata(dev);
+ struct rtc_time now;
+ time64_t t_now;
+ int retval = 0;
+ unsigned char rtc_control;
+
+ if (!cmos->alarm_expires)
+ return -EINVAL;
+
+ spin_lock_irq(&rtc_lock);
+ rtc_control = CMOS_READ(RTC_CONTROL);
+ spin_unlock_irq(&rtc_lock);
+
+ /* We only care about the situation where AIE is disabled. */
+ if (rtc_control & RTC_AIE)
+ return -EBUSY;
+
+ cmos_read_time(dev, &now);
+ t_now = rtc_tm_to_time64(&now);
+
+ /*
+ * When enabling "RTC wake-up" in BIOS setup, the machine reboots
+ * automatically right after shutdown on some buggy boxes.
+ * This automatic rebooting issue won't happen when the alarm
+ * time is larger than now+1 seconds.
+ *
+ * If the alarm time is equal to now+1 seconds, the issue can be
+ * prevented by cancelling the alarm.
+ */
+ if (cmos->alarm_expires == t_now + 1) {
+ struct rtc_wkalrm alarm;
+
+ /* Cancel the AIE timer by configuring the past time. */
+ rtc_time64_to_tm(t_now - 1, &alarm.time);
+ alarm.enabled = 0;
+ retval = cmos_set_alarm(dev, &alarm);
+ } else if (cmos->alarm_expires > t_now + 1) {
+ retval = -EBUSY;
+ }
+
+ return retval;
+}
+
#ifdef CONFIG_PM
static int cmos_suspend(struct device *dev)
@@ -1094,8 +1081,12 @@ static void cmos_pnp_shutdown(struct pnp_dev *pnp)
struct device *dev = &pnp->dev;
struct cmos_rtc *cmos = dev_get_drvdata(dev);
- if (system_state == SYSTEM_POWER_OFF && !cmos_poweroff(dev))
- return;
+ if (system_state == SYSTEM_POWER_OFF) {
+ int retval = cmos_poweroff(dev);
+
+ if (cmos_aie_poweroff(dev) < 0 && !retval)
+ return;
+ }
cmos_do_shutdown(cmos->irq);
}
@@ -1200,8 +1191,12 @@ static void cmos_platform_shutdown(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct cmos_rtc *cmos = dev_get_drvdata(dev);
- if (system_state == SYSTEM_POWER_OFF && !cmos_poweroff(dev))
- return;
+ if (system_state == SYSTEM_POWER_OFF) {
+ int retval = cmos_poweroff(dev);
+
+ if (cmos_aie_poweroff(dev) < 0 && !retval)
+ return;
+ }
cmos_do_shutdown(cmos->irq);
}
@@ -1243,8 +1238,6 @@ static int __init cmos_init(void)
platform_driver_registered = true;
}
- dmi_check_system(rtc_quirks);
-
if (retval == 0)
return 0;
diff --git a/drivers/rtc/rtc-coh901331.c b/drivers/rtc/rtc-coh901331.c
index 56343b2fb..101b7a240 100644
--- a/drivers/rtc/rtc-coh901331.c
+++ b/drivers/rtc/rtc-coh901331.c
@@ -263,6 +263,7 @@ static const struct of_device_id coh901331_dt_match[] = {
{ .compatible = "stericsson,coh901331" },
{},
};
+MODULE_DEVICE_TABLE(of, coh901331_dt_match);
static struct platform_driver coh901331_driver = {
.driver = {
diff --git a/drivers/rtc/rtc-core.h b/drivers/rtc/rtc-core.h
index 5f9df7430..a098aea19 100644
--- a/drivers/rtc/rtc-core.h
+++ b/drivers/rtc/rtc-core.h
@@ -48,23 +48,10 @@ static inline void rtc_proc_del_device(struct rtc_device *rtc)
#endif
#ifdef CONFIG_RTC_INTF_SYSFS
-
-extern void __init rtc_sysfs_init(struct class *);
-extern void rtc_sysfs_add_device(struct rtc_device *rtc);
-extern void rtc_sysfs_del_device(struct rtc_device *rtc);
-
+const struct attribute_group **rtc_get_dev_attribute_groups(void);
#else
-
-static inline void rtc_sysfs_init(struct class *rtc)
-{
-}
-
-static inline void rtc_sysfs_add_device(struct rtc_device *rtc)
+static inline const struct attribute_group **rtc_get_dev_attribute_groups(void)
{
+ return NULL;
}
-
-static inline void rtc_sysfs_del_device(struct rtc_device *rtc)
-{
-}
-
#endif
diff --git a/drivers/rtc/rtc-da9063.c b/drivers/rtc/rtc-da9063.c
index 7ffc5707f..00a8f7f4f 100644
--- a/drivers/rtc/rtc-da9063.c
+++ b/drivers/rtc/rtc-da9063.c
@@ -12,15 +12,18 @@
* Library General Public License for more details.
*/
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/init.h>
+#include <linux/of.h>
#include <linux/platform_device.h>
-#include <linux/interrupt.h>
+#include <linux/regmap.h>
#include <linux/rtc.h>
#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/regmap.h>
+
+#include <linux/mfd/da9062/registers.h>
#include <linux/mfd/da9063/registers.h>
#include <linux/mfd/da9063/core.h>
@@ -29,99 +32,231 @@
#define YEARS_FROM_DA9063(year) ((year) + 100)
#define MONTHS_FROM_DA9063(month) ((month) - 1)
-#define RTC_ALARM_DATA_LEN (DA9063_AD_REG_ALARM_Y - DA9063_AD_REG_ALARM_MI + 1)
-
-#define RTC_DATA_LEN (DA9063_REG_COUNT_Y - DA9063_REG_COUNT_S + 1)
-#define RTC_SEC 0
-#define RTC_MIN 1
-#define RTC_HOUR 2
-#define RTC_DAY 3
-#define RTC_MONTH 4
-#define RTC_YEAR 5
-
-struct da9063_rtc {
- struct rtc_device *rtc_dev;
- struct da9063 *hw;
- struct rtc_time alarm_time;
- bool rtc_sync;
- int alarm_year;
- int alarm_start;
- int alarm_len;
- int data_start;
+enum {
+ RTC_SEC = 0,
+ RTC_MIN = 1,
+ RTC_HOUR = 2,
+ RTC_DAY = 3,
+ RTC_MONTH = 4,
+ RTC_YEAR = 5,
+ RTC_DATA_LEN
+};
+
+struct da9063_compatible_rtc_regmap {
+ /* REGS */
+ int rtc_enable_reg;
+ int rtc_enable_32k_crystal_reg;
+ int rtc_alarm_secs_reg;
+ int rtc_alarm_year_reg;
+ int rtc_count_secs_reg;
+ int rtc_count_year_reg;
+ int rtc_event_reg;
+ /* MASKS */
+ int rtc_enable_mask;
+ int rtc_crystal_mask;
+ int rtc_event_alarm_mask;
+ int rtc_alarm_on_mask;
+ int rtc_alarm_status_mask;
+ int rtc_tick_on_mask;
+ int rtc_ready_to_read_mask;
+ int rtc_count_sec_mask;
+ int rtc_count_min_mask;
+ int rtc_count_hour_mask;
+ int rtc_count_day_mask;
+ int rtc_count_month_mask;
+ int rtc_count_year_mask;
+ /* ALARM CONFIG */
+ int rtc_data_start;
+ int rtc_alarm_len;
+};
+
+struct da9063_compatible_rtc {
+ struct rtc_device *rtc_dev;
+ struct rtc_time alarm_time;
+ struct regmap *regmap;
+ const struct da9063_compatible_rtc_regmap *config;
+ bool rtc_sync;
+};
+
+static const struct da9063_compatible_rtc_regmap da9063_ad_regs = {
+ /* REGS */
+ .rtc_enable_reg = DA9063_REG_CONTROL_E,
+ .rtc_alarm_secs_reg = DA9063_AD_REG_ALARM_MI,
+ .rtc_alarm_year_reg = DA9063_AD_REG_ALARM_Y,
+ .rtc_count_secs_reg = DA9063_REG_COUNT_S,
+ .rtc_count_year_reg = DA9063_REG_COUNT_Y,
+ .rtc_event_reg = DA9063_REG_EVENT_A,
+ /* MASKS */
+ .rtc_enable_mask = DA9063_RTC_EN,
+ .rtc_crystal_mask = DA9063_CRYSTAL,
+ .rtc_enable_32k_crystal_reg = DA9063_REG_EN_32K,
+ .rtc_event_alarm_mask = DA9063_E_ALARM,
+ .rtc_alarm_on_mask = DA9063_ALARM_ON,
+ .rtc_alarm_status_mask = DA9063_ALARM_STATUS_ALARM |
+ DA9063_ALARM_STATUS_TICK,
+ .rtc_tick_on_mask = DA9063_TICK_ON,
+ .rtc_ready_to_read_mask = DA9063_RTC_READ,
+ .rtc_count_sec_mask = DA9063_COUNT_SEC_MASK,
+ .rtc_count_min_mask = DA9063_COUNT_MIN_MASK,
+ .rtc_count_hour_mask = DA9063_COUNT_HOUR_MASK,
+ .rtc_count_day_mask = DA9063_COUNT_DAY_MASK,
+ .rtc_count_month_mask = DA9063_COUNT_MONTH_MASK,
+ .rtc_count_year_mask = DA9063_COUNT_YEAR_MASK,
+ /* ALARM CONFIG */
+ .rtc_data_start = RTC_MIN,
+ .rtc_alarm_len = RTC_DATA_LEN - 1,
+};
+
+static const struct da9063_compatible_rtc_regmap da9063_bb_regs = {
+ /* REGS */
+ .rtc_enable_reg = DA9063_REG_CONTROL_E,
+ .rtc_alarm_secs_reg = DA9063_BB_REG_ALARM_S,
+ .rtc_alarm_year_reg = DA9063_BB_REG_ALARM_Y,
+ .rtc_count_secs_reg = DA9063_REG_COUNT_S,
+ .rtc_count_year_reg = DA9063_REG_COUNT_Y,
+ .rtc_event_reg = DA9063_REG_EVENT_A,
+ /* MASKS */
+ .rtc_enable_mask = DA9063_RTC_EN,
+ .rtc_crystal_mask = DA9063_CRYSTAL,
+ .rtc_enable_32k_crystal_reg = DA9063_REG_EN_32K,
+ .rtc_event_alarm_mask = DA9063_E_ALARM,
+ .rtc_alarm_on_mask = DA9063_ALARM_ON,
+ .rtc_alarm_status_mask = DA9063_ALARM_STATUS_ALARM |
+ DA9063_ALARM_STATUS_TICK,
+ .rtc_tick_on_mask = DA9063_TICK_ON,
+ .rtc_ready_to_read_mask = DA9063_RTC_READ,
+ .rtc_count_sec_mask = DA9063_COUNT_SEC_MASK,
+ .rtc_count_min_mask = DA9063_COUNT_MIN_MASK,
+ .rtc_count_hour_mask = DA9063_COUNT_HOUR_MASK,
+ .rtc_count_day_mask = DA9063_COUNT_DAY_MASK,
+ .rtc_count_month_mask = DA9063_COUNT_MONTH_MASK,
+ .rtc_count_year_mask = DA9063_COUNT_YEAR_MASK,
+ /* ALARM CONFIG */
+ .rtc_data_start = RTC_SEC,
+ .rtc_alarm_len = RTC_DATA_LEN,
+};
+
+static const struct da9063_compatible_rtc_regmap da9062_aa_regs = {
+ /* REGS */
+ .rtc_enable_reg = DA9062AA_CONTROL_E,
+ .rtc_alarm_secs_reg = DA9062AA_ALARM_S,
+ .rtc_alarm_year_reg = DA9062AA_ALARM_Y,
+ .rtc_count_secs_reg = DA9062AA_COUNT_S,
+ .rtc_count_year_reg = DA9062AA_COUNT_Y,
+ .rtc_event_reg = DA9062AA_EVENT_A,
+ /* MASKS */
+ .rtc_enable_mask = DA9062AA_RTC_EN_MASK,
+ .rtc_crystal_mask = DA9062AA_CRYSTAL_MASK,
+ .rtc_enable_32k_crystal_reg = DA9062AA_EN_32K,
+ .rtc_event_alarm_mask = DA9062AA_M_ALARM_MASK,
+ .rtc_alarm_on_mask = DA9062AA_ALARM_ON_MASK,
+ .rtc_alarm_status_mask = (0x02 << 6),
+ .rtc_tick_on_mask = DA9062AA_TICK_ON_MASK,
+ .rtc_ready_to_read_mask = DA9062AA_RTC_READ_MASK,
+ .rtc_count_sec_mask = DA9062AA_COUNT_SEC_MASK,
+ .rtc_count_min_mask = DA9062AA_COUNT_MIN_MASK,
+ .rtc_count_hour_mask = DA9062AA_COUNT_HOUR_MASK,
+ .rtc_count_day_mask = DA9062AA_COUNT_DAY_MASK,
+ .rtc_count_month_mask = DA9062AA_COUNT_MONTH_MASK,
+ .rtc_count_year_mask = DA9062AA_COUNT_YEAR_MASK,
+ /* ALARM CONFIG */
+ .rtc_data_start = RTC_SEC,
+ .rtc_alarm_len = RTC_DATA_LEN,
+};
+
+static const struct of_device_id da9063_compatible_reg_id_table[] = {
+ { .compatible = "dlg,da9063-rtc", .data = &da9063_bb_regs },
+ { .compatible = "dlg,da9062-rtc", .data = &da9062_aa_regs },
+ { },
};
+MODULE_DEVICE_TABLE(of, da9063_compatible_reg_id_table);
-static void da9063_data_to_tm(u8 *data, struct rtc_time *tm)
+static void da9063_data_to_tm(u8 *data, struct rtc_time *tm,
+ struct da9063_compatible_rtc *rtc)
{
- tm->tm_sec = data[RTC_SEC] & DA9063_COUNT_SEC_MASK;
- tm->tm_min = data[RTC_MIN] & DA9063_COUNT_MIN_MASK;
- tm->tm_hour = data[RTC_HOUR] & DA9063_COUNT_HOUR_MASK;
- tm->tm_mday = data[RTC_DAY] & DA9063_COUNT_DAY_MASK;
+ const struct da9063_compatible_rtc_regmap *config = rtc->config;
+
+ tm->tm_sec = data[RTC_SEC] & config->rtc_count_sec_mask;
+ tm->tm_min = data[RTC_MIN] & config->rtc_count_min_mask;
+ tm->tm_hour = data[RTC_HOUR] & config->rtc_count_hour_mask;
+ tm->tm_mday = data[RTC_DAY] & config->rtc_count_day_mask;
tm->tm_mon = MONTHS_FROM_DA9063(data[RTC_MONTH] &
- DA9063_COUNT_MONTH_MASK);
+ config->rtc_count_month_mask);
tm->tm_year = YEARS_FROM_DA9063(data[RTC_YEAR] &
- DA9063_COUNT_YEAR_MASK);
+ config->rtc_count_year_mask);
}
-static void da9063_tm_to_data(struct rtc_time *tm, u8 *data)
+static void da9063_tm_to_data(struct rtc_time *tm, u8 *data,
+ struct da9063_compatible_rtc *rtc)
{
- data[RTC_SEC] &= ~DA9063_COUNT_SEC_MASK;
- data[RTC_SEC] |= tm->tm_sec & DA9063_COUNT_SEC_MASK;
+ const struct da9063_compatible_rtc_regmap *config = rtc->config;
+
+ data[RTC_SEC] &= ~config->rtc_count_sec_mask;
+ data[RTC_SEC] |= tm->tm_sec & config->rtc_count_sec_mask;
- data[RTC_MIN] &= ~DA9063_COUNT_MIN_MASK;
- data[RTC_MIN] |= tm->tm_min & DA9063_COUNT_MIN_MASK;
+ data[RTC_MIN] &= ~config->rtc_count_min_mask;
+ data[RTC_MIN] |= tm->tm_min & config->rtc_count_min_mask;
- data[RTC_HOUR] &= ~DA9063_COUNT_HOUR_MASK;
- data[RTC_HOUR] |= tm->tm_hour & DA9063_COUNT_HOUR_MASK;
+ data[RTC_HOUR] &= ~config->rtc_count_hour_mask;
+ data[RTC_HOUR] |= tm->tm_hour & config->rtc_count_hour_mask;
- data[RTC_DAY] &= ~DA9063_COUNT_DAY_MASK;
- data[RTC_DAY] |= tm->tm_mday & DA9063_COUNT_DAY_MASK;
+ data[RTC_DAY] &= ~config->rtc_count_day_mask;
+ data[RTC_DAY] |= tm->tm_mday & config->rtc_count_day_mask;
- data[RTC_MONTH] &= ~DA9063_COUNT_MONTH_MASK;
+ data[RTC_MONTH] &= ~config->rtc_count_month_mask;
data[RTC_MONTH] |= MONTHS_TO_DA9063(tm->tm_mon) &
- DA9063_COUNT_MONTH_MASK;
+ config->rtc_count_month_mask;
- data[RTC_YEAR] &= ~DA9063_COUNT_YEAR_MASK;
+ data[RTC_YEAR] &= ~config->rtc_count_year_mask;
data[RTC_YEAR] |= YEARS_TO_DA9063(tm->tm_year) &
- DA9063_COUNT_YEAR_MASK;
+ config->rtc_count_year_mask;
}
static int da9063_rtc_stop_alarm(struct device *dev)
{
- struct da9063_rtc *rtc = dev_get_drvdata(dev);
+ struct da9063_compatible_rtc *rtc = dev_get_drvdata(dev);
+ const struct da9063_compatible_rtc_regmap *config = rtc->config;
- return regmap_update_bits(rtc->hw->regmap, rtc->alarm_year,
- DA9063_ALARM_ON, 0);
+ return regmap_update_bits(rtc->regmap,
+ config->rtc_alarm_year_reg,
+ config->rtc_alarm_on_mask,
+ 0);
}
static int da9063_rtc_start_alarm(struct device *dev)
{
- struct da9063_rtc *rtc = dev_get_drvdata(dev);
+ struct da9063_compatible_rtc *rtc = dev_get_drvdata(dev);
+ const struct da9063_compatible_rtc_regmap *config = rtc->config;
- return regmap_update_bits(rtc->hw->regmap, rtc->alarm_year,
- DA9063_ALARM_ON, DA9063_ALARM_ON);
+ return regmap_update_bits(rtc->regmap,
+ config->rtc_alarm_year_reg,
+ config->rtc_alarm_on_mask,
+ config->rtc_alarm_on_mask);
}
static int da9063_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
- struct da9063_rtc *rtc = dev_get_drvdata(dev);
+ struct da9063_compatible_rtc *rtc = dev_get_drvdata(dev);
+ const struct da9063_compatible_rtc_regmap *config = rtc->config;
unsigned long tm_secs;
unsigned long al_secs;
u8 data[RTC_DATA_LEN];
int ret;
- ret = regmap_bulk_read(rtc->hw->regmap, DA9063_REG_COUNT_S,
+ ret = regmap_bulk_read(rtc->regmap,
+ config->rtc_count_secs_reg,
data, RTC_DATA_LEN);
if (ret < 0) {
dev_err(dev, "Failed to read RTC time data: %d\n", ret);
return ret;
}
- if (!(data[RTC_SEC] & DA9063_RTC_READ)) {
+ if (!(data[RTC_SEC] & config->rtc_ready_to_read_mask)) {
dev_dbg(dev, "RTC not yet ready to be read by the host\n");
return -EINVAL;
}
- da9063_data_to_tm(data, tm);
+ da9063_data_to_tm(data, tm, rtc);
rtc_tm_to_time(tm, &tm_secs);
rtc_tm_to_time(&rtc->alarm_time, &al_secs);
@@ -137,12 +272,14 @@ static int da9063_rtc_read_time(struct device *dev, struct rtc_time *tm)
static int da9063_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
- struct da9063_rtc *rtc = dev_get_drvdata(dev);
+ struct da9063_compatible_rtc *rtc = dev_get_drvdata(dev);
+ const struct da9063_compatible_rtc_regmap *config = rtc->config;
u8 data[RTC_DATA_LEN];
int ret;
- da9063_tm_to_data(tm, data);
- ret = regmap_bulk_write(rtc->hw->regmap, DA9063_REG_COUNT_S,
+ da9063_tm_to_data(tm, data, rtc);
+ ret = regmap_bulk_write(rtc->regmap,
+ config->rtc_count_secs_reg,
data, RTC_DATA_LEN);
if (ret < 0)
dev_err(dev, "Failed to set RTC time data: %d\n", ret);
@@ -152,26 +289,31 @@ static int da9063_rtc_set_time(struct device *dev, struct rtc_time *tm)
static int da9063_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
- struct da9063_rtc *rtc = dev_get_drvdata(dev);
+ struct da9063_compatible_rtc *rtc = dev_get_drvdata(dev);
+ const struct da9063_compatible_rtc_regmap *config = rtc->config;
u8 data[RTC_DATA_LEN];
int ret;
unsigned int val;
data[RTC_SEC] = 0;
- ret = regmap_bulk_read(rtc->hw->regmap, rtc->alarm_start,
- &data[rtc->data_start], rtc->alarm_len);
+ ret = regmap_bulk_read(rtc->regmap,
+ config->rtc_alarm_secs_reg,
+ &data[config->rtc_data_start],
+ config->rtc_alarm_len);
if (ret < 0)
return ret;
- da9063_data_to_tm(data, &alrm->time);
+ da9063_data_to_tm(data, &alrm->time, rtc);
- alrm->enabled = !!(data[RTC_YEAR] & DA9063_ALARM_ON);
+ alrm->enabled = !!(data[RTC_YEAR] & config->rtc_alarm_on_mask);
- ret = regmap_read(rtc->hw->regmap, DA9063_REG_EVENT_A, &val);
+ ret = regmap_read(rtc->regmap,
+ config->rtc_event_reg,
+ &val);
if (ret < 0)
return ret;
- if (val & (DA9063_E_ALARM))
+ if (val & config->rtc_event_alarm_mask)
alrm->pending = 1;
else
alrm->pending = 0;
@@ -181,11 +323,12 @@ static int da9063_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
static int da9063_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
- struct da9063_rtc *rtc = dev_get_drvdata(dev);
+ struct da9063_compatible_rtc *rtc = dev_get_drvdata(dev);
+ const struct da9063_compatible_rtc_regmap *config = rtc->config;
u8 data[RTC_DATA_LEN];
int ret;
- da9063_tm_to_data(&alrm->time, data);
+ da9063_tm_to_data(&alrm->time, data, rtc);
ret = da9063_rtc_stop_alarm(dev);
if (ret < 0) {
@@ -193,14 +336,16 @@ static int da9063_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
return ret;
}
- ret = regmap_bulk_write(rtc->hw->regmap, rtc->alarm_start,
- &data[rtc->data_start], rtc->alarm_len);
+ ret = regmap_bulk_write(rtc->regmap,
+ config->rtc_alarm_secs_reg,
+ &data[config->rtc_data_start],
+ config->rtc_alarm_len);
if (ret < 0) {
dev_err(dev, "Failed to write alarm: %d\n", ret);
return ret;
}
- da9063_data_to_tm(data, &rtc->alarm_time);
+ da9063_data_to_tm(data, &rtc->alarm_time, rtc);
if (alrm->enabled) {
ret = da9063_rtc_start_alarm(dev);
@@ -213,7 +358,8 @@ static int da9063_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
return ret;
}
-static int da9063_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
+static int da9063_rtc_alarm_irq_enable(struct device *dev,
+ unsigned int enabled)
{
if (enabled)
return da9063_rtc_start_alarm(dev);
@@ -223,10 +369,13 @@ static int da9063_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
static irqreturn_t da9063_alarm_event(int irq, void *data)
{
- struct da9063_rtc *rtc = data;
+ struct da9063_compatible_rtc *rtc = data;
+ const struct da9063_compatible_rtc_regmap *config = rtc->config;
- regmap_update_bits(rtc->hw->regmap, rtc->alarm_year,
- DA9063_ALARM_ON, 0);
+ regmap_update_bits(rtc->regmap,
+ config->rtc_alarm_year_reg,
+ config->rtc_alarm_on_mask,
+ 0);
rtc->rtc_sync = true;
rtc_update_irq(rtc->rtc_dev, 1, RTC_IRQF | RTC_AF);
@@ -244,72 +393,92 @@ static const struct rtc_class_ops da9063_rtc_ops = {
static int da9063_rtc_probe(struct platform_device *pdev)
{
- struct da9063 *da9063 = dev_get_drvdata(pdev->dev.parent);
- struct da9063_rtc *rtc;
+ struct da9063_compatible_rtc *rtc;
+ const struct da9063_compatible_rtc_regmap *config;
+ const struct of_device_id *match;
int irq_alarm;
u8 data[RTC_DATA_LEN];
int ret;
- ret = regmap_update_bits(da9063->regmap, DA9063_REG_CONTROL_E,
- DA9063_RTC_EN, DA9063_RTC_EN);
- if (ret < 0) {
- dev_err(&pdev->dev, "Failed to enable RTC\n");
- goto err;
- }
+ if (!pdev->dev.of_node)
+ return -ENXIO;
- ret = regmap_update_bits(da9063->regmap, DA9063_REG_EN_32K,
- DA9063_CRYSTAL, DA9063_CRYSTAL);
- if (ret < 0) {
- dev_err(&pdev->dev, "Failed to run 32kHz oscillator\n");
- goto err;
- }
+ match = of_match_node(da9063_compatible_reg_id_table,
+ pdev->dev.of_node);
rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
if (!rtc)
return -ENOMEM;
- if (da9063->variant_code == PMIC_DA9063_AD) {
- rtc->alarm_year = DA9063_AD_REG_ALARM_Y;
- rtc->alarm_start = DA9063_AD_REG_ALARM_MI;
- rtc->alarm_len = RTC_ALARM_DATA_LEN;
- rtc->data_start = RTC_MIN;
- } else {
- rtc->alarm_year = DA9063_BB_REG_ALARM_Y;
- rtc->alarm_start = DA9063_BB_REG_ALARM_S;
- rtc->alarm_len = RTC_DATA_LEN;
- rtc->data_start = RTC_SEC;
+ rtc->config = match->data;
+ if (of_device_is_compatible(pdev->dev.of_node, "dlg,da9063-rtc")) {
+ struct da9063 *chip = dev_get_drvdata(pdev->dev.parent);
+
+ if (chip->variant_code == PMIC_DA9063_AD)
+ rtc->config = &da9063_ad_regs;
}
- ret = regmap_update_bits(da9063->regmap, rtc->alarm_start,
- DA9063_ALARM_STATUS_TICK | DA9063_ALARM_STATUS_ALARM,
- 0);
+ rtc->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+ if (!rtc->regmap) {
+ dev_warn(&pdev->dev, "Parent regmap unavailable.\n");
+ return -ENXIO;
+ }
+
+ config = rtc->config;
+ ret = regmap_update_bits(rtc->regmap,
+ config->rtc_enable_reg,
+ config->rtc_enable_mask,
+ config->rtc_enable_mask);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Failed to enable RTC\n");
+ return ret;
+ }
+
+ ret = regmap_update_bits(rtc->regmap,
+ config->rtc_enable_32k_crystal_reg,
+ config->rtc_crystal_mask,
+ config->rtc_crystal_mask);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "Failed to run 32kHz oscillator\n");
+ return ret;
+ }
+
+ ret = regmap_update_bits(rtc->regmap,
+ config->rtc_alarm_secs_reg,
+ config->rtc_alarm_status_mask,
+ 0);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to access RTC alarm register\n");
- goto err;
+ return ret;
}
- ret = regmap_update_bits(da9063->regmap, rtc->alarm_start,
+ ret = regmap_update_bits(rtc->regmap,
+ config->rtc_alarm_secs_reg,
DA9063_ALARM_STATUS_ALARM,
DA9063_ALARM_STATUS_ALARM);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to access RTC alarm register\n");
- goto err;
+ return ret;
}
- ret = regmap_update_bits(da9063->regmap, rtc->alarm_year,
- DA9063_TICK_ON, 0);
+ ret = regmap_update_bits(rtc->regmap,
+ config->rtc_alarm_year_reg,
+ config->rtc_tick_on_mask,
+ 0);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to disable TICKs\n");
- goto err;
+ return ret;
}
data[RTC_SEC] = 0;
- ret = regmap_bulk_read(da9063->regmap, rtc->alarm_start,
- &data[rtc->data_start], rtc->alarm_len);
+ ret = regmap_bulk_read(rtc->regmap,
+ config->rtc_alarm_secs_reg,
+ &data[config->rtc_data_start],
+ config->rtc_alarm_len);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to read initial alarm data: %d\n",
ret);
- goto err;
+ return ret;
}
platform_set_drvdata(pdev, rtc);
@@ -322,18 +491,16 @@ static int da9063_rtc_probe(struct platform_device *pdev)
if (ret) {
dev_err(&pdev->dev, "Failed to request ALARM IRQ %d: %d\n",
irq_alarm, ret);
- goto err;
+ return ret;
}
- rtc->hw = da9063;
rtc->rtc_dev = devm_rtc_device_register(&pdev->dev, DA9063_DRVNAME_RTC,
&da9063_rtc_ops, THIS_MODULE);
if (IS_ERR(rtc->rtc_dev))
return PTR_ERR(rtc->rtc_dev);
- da9063_data_to_tm(data, &rtc->alarm_time);
+ da9063_data_to_tm(data, &rtc->alarm_time, rtc);
rtc->rtc_sync = false;
-err:
return ret;
}
@@ -341,6 +508,7 @@ static struct platform_driver da9063_rtc_driver = {
.probe = da9063_rtc_probe,
.driver = {
.name = DA9063_DRVNAME_RTC,
+ .of_match_table = da9063_compatible_reg_id_table,
},
};
diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c
index 799c34bcb..a6d9434ad 100644
--- a/drivers/rtc/rtc-dev.c
+++ b/drivers/rtc/rtc-dev.c
@@ -477,6 +477,7 @@ void rtc_dev_prepare(struct rtc_device *rtc)
cdev_init(&rtc->char_dev, &rtc_dev_fops);
rtc->char_dev.owner = rtc->owner;
+ rtc->char_dev.kobj.parent = &rtc->dev.kobj;
}
void rtc_dev_add_device(struct rtc_device *rtc)
diff --git a/drivers/rtc/rtc-ds1305.c b/drivers/rtc/rtc-ds1305.c
index 12b07158a..baa5d047f 100644
--- a/drivers/rtc/rtc-ds1305.c
+++ b/drivers/rtc/rtc-ds1305.c
@@ -538,15 +538,6 @@ ds1305_nvram_read(struct file *filp, struct kobject *kobj,
spi = container_of(kobj, struct spi_device, dev.kobj);
- if (unlikely(off >= DS1305_NVRAM_LEN))
- return 0;
- if (count >= DS1305_NVRAM_LEN)
- count = DS1305_NVRAM_LEN;
- if ((off + count) > DS1305_NVRAM_LEN)
- count = DS1305_NVRAM_LEN - off;
- if (unlikely(!count))
- return count;
-
addr = DS1305_NVRAM + off;
msg_init(&m, x, &addr, count, NULL, buf);
@@ -569,15 +560,6 @@ ds1305_nvram_write(struct file *filp, struct kobject *kobj,
spi = container_of(kobj, struct spi_device, dev.kobj);
- if (unlikely(off >= DS1305_NVRAM_LEN))
- return -EFBIG;
- if (count >= DS1305_NVRAM_LEN)
- count = DS1305_NVRAM_LEN;
- if ((off + count) > DS1305_NVRAM_LEN)
- count = DS1305_NVRAM_LEN - off;
- if (unlikely(!count))
- return count;
-
addr = (DS1305_WRITE | DS1305_NVRAM) + off;
msg_init(&m, x, &addr, count, buf, NULL);
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index 6e76de185..a705e6490 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -11,14 +11,17 @@
* published by the Free Software Foundation.
*/
-#include <linux/module.h>
+#include <linux/bcd.h>
+#include <linux/i2c.h>
#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+#include <linux/pm_wakeirq.h>
+#include <linux/rtc/ds1307.h>
+#include <linux/rtc.h>
#include <linux/slab.h>
-#include <linux/i2c.h>
#include <linux/string.h>
-#include <linux/rtc.h>
-#include <linux/bcd.h>
-#include <linux/rtc/ds1307.h>
/*
* We can't determine type by probing, but if we expect pre-Linux code
@@ -114,7 +117,7 @@ struct ds1307 {
#define HAS_ALARM 1 /* bit 1 == irq claimed */
struct i2c_client *client;
struct rtc_device *rtc;
- struct work_struct work;
+ int wakeirq;
s32 (*read_block_data)(const struct i2c_client *client, u8 command,
u8 length, u8 *values);
s32 (*write_block_data)(const struct i2c_client *client, u8 command,
@@ -311,27 +314,17 @@ static s32 ds1307_native_smbus_read_block_data(const struct i2c_client *client,
/*----------------------------------------------------------------------*/
/*
- * The IRQ logic includes a "real" handler running in IRQ context just
- * long enough to schedule this workqueue entry. We need a task context
- * to talk to the RTC, since I2C I/O calls require that; and disable the
- * IRQ until we clear its status on the chip, so that this handler can
- * work with any type of triggering (not just falling edge).
- *
* The ds1337 and ds1339 both have two alarms, but we only use the first
* one (with a "seconds" field). For ds1337 we expect nINTA is our alarm
* signal; ds1339 chips have only one alarm signal.
*/
-static void ds1307_work(struct work_struct *work)
+static irqreturn_t ds1307_irq(int irq, void *dev_id)
{
- struct ds1307 *ds1307;
- struct i2c_client *client;
- struct mutex *lock;
+ struct i2c_client *client = dev_id;
+ struct ds1307 *ds1307 = i2c_get_clientdata(client);
+ struct mutex *lock = &ds1307->rtc->ops_lock;
int stat, control;
- ds1307 = container_of(work, struct ds1307, work);
- client = ds1307->client;
- lock = &ds1307->rtc->ops_lock;
-
mutex_lock(lock);
stat = i2c_smbus_read_byte_data(client, DS1337_REG_STATUS);
if (stat < 0)
@@ -352,18 +345,8 @@ static void ds1307_work(struct work_struct *work)
}
out:
- if (test_bit(HAS_ALARM, &ds1307->flags))
- enable_irq(client->irq);
mutex_unlock(lock);
-}
-static irqreturn_t ds1307_irq(int irq, void *dev_id)
-{
- struct i2c_client *client = dev_id;
- struct ds1307 *ds1307 = i2c_get_clientdata(client);
-
- disable_irq_nosync(irq);
- schedule_work(&ds1307->work);
return IRQ_HANDLED;
}
@@ -634,13 +617,14 @@ static const struct rtc_class_ops ds13xx_rtc_ops = {
MCP794XX_BIT_ALMX_C1 | \
MCP794XX_BIT_ALMX_C2)
-static void mcp794xx_work(struct work_struct *work)
+static irqreturn_t mcp794xx_irq(int irq, void *dev_id)
{
- struct ds1307 *ds1307 = container_of(work, struct ds1307, work);
- struct i2c_client *client = ds1307->client;
+ struct i2c_client *client = dev_id;
+ struct ds1307 *ds1307 = i2c_get_clientdata(client);
+ struct mutex *lock = &ds1307->rtc->ops_lock;
int reg, ret;
- mutex_lock(&ds1307->rtc->ops_lock);
+ mutex_lock(lock);
/* Check and clear alarm 0 interrupt flag. */
reg = i2c_smbus_read_byte_data(client, MCP794XX_REG_ALARM0_CTRL);
@@ -665,9 +649,9 @@ static void mcp794xx_work(struct work_struct *work)
rtc_update_irq(ds1307->rtc, 1, RTC_AF | RTC_IRQF);
out:
- if (test_bit(HAS_ALARM, &ds1307->flags))
- enable_irq(client->irq);
- mutex_unlock(&ds1307->rtc->ops_lock);
+ mutex_unlock(lock);
+
+ return IRQ_HANDLED;
}
static int mcp794xx_read_alarm(struct device *dev, struct rtc_wkalrm *t)
@@ -798,13 +782,6 @@ ds1307_nvram_read(struct file *filp, struct kobject *kobj,
client = kobj_to_i2c_client(kobj);
ds1307 = i2c_get_clientdata(client);
- if (unlikely(off >= ds1307->nvram->size))
- return 0;
- if ((off + count) > ds1307->nvram->size)
- count = ds1307->nvram->size - off;
- if (unlikely(!count))
- return count;
-
result = ds1307->read_block_data(client, ds1307->nvram_offset + off,
count, buf);
if (result < 0)
@@ -824,13 +801,6 @@ ds1307_nvram_write(struct file *filp, struct kobject *kobj,
client = kobj_to_i2c_client(kobj);
ds1307 = i2c_get_clientdata(client);
- if (unlikely(off >= ds1307->nvram->size))
- return -EFBIG;
- if ((off + count) > ds1307->nvram->size)
- count = ds1307->nvram->size - off;
- if (unlikely(!count))
- return count;
-
result = ds1307->write_block_data(client, ds1307->nvram_offset + off,
count, buf);
if (result < 0) {
@@ -896,6 +866,8 @@ static int ds1307_probe(struct i2c_client *client,
bool want_irq = false;
unsigned char *buf;
struct ds1307_platform_data *pdata = dev_get_platdata(&client->dev);
+ irq_handler_t irq_handler = ds1307_irq;
+
static const int bbsqi_bitpos[] = {
[ds_1337] = 0,
[ds_1339] = DS1339_BIT_BBSQI,
@@ -962,8 +934,6 @@ static int ds1307_probe(struct i2c_client *client,
* running on Vbackup (BBSQI/BBSQW)
*/
if (ds1307->client->irq > 0 && chip->alarm) {
- INIT_WORK(&ds1307->work, ds1307_work);
-
ds1307->regs[0] |= DS1337_BIT_INTCN
| bbsqi_bitpos[ds1307->type];
ds1307->regs[0] &= ~(DS1337_BIT_A2IE | DS1337_BIT_A1IE);
@@ -1053,7 +1023,7 @@ static int ds1307_probe(struct i2c_client *client,
case mcp794xx:
rtc_ops = &mcp794xx_rtc_ops;
if (ds1307->client->irq > 0 && chip->alarm) {
- INIT_WORK(&ds1307->work, mcp794xx_work);
+ irq_handler = mcp794xx_irq;
want_irq = true;
}
break;
@@ -1176,18 +1146,43 @@ read_rtc:
}
if (want_irq) {
- err = request_irq(client->irq, ds1307_irq, IRQF_SHARED,
- ds1307->rtc->name, client);
+ struct device_node *node = client->dev.of_node;
+
+ err = devm_request_threaded_irq(&client->dev,
+ client->irq, NULL, irq_handler,
+ IRQF_SHARED | IRQF_ONESHOT,
+ ds1307->rtc->name, client);
if (err) {
client->irq = 0;
dev_err(&client->dev, "unable to request IRQ!\n");
- } else {
+ goto no_irq;
+ }
+
+ set_bit(HAS_ALARM, &ds1307->flags);
+ dev_dbg(&client->dev, "got IRQ %d\n", client->irq);
+
+ /* Currently supported by OF code only! */
+ if (!node)
+ goto no_irq;
+
+ err = of_irq_get(node, 1);
+ if (err <= 0) {
+ if (err == -EPROBE_DEFER)
+ goto exit;
+ goto no_irq;
+ }
+ ds1307->wakeirq = err;
- set_bit(HAS_ALARM, &ds1307->flags);
- dev_dbg(&client->dev, "got IRQ %d\n", client->irq);
+ err = dev_pm_set_dedicated_wake_irq(&client->dev,
+ ds1307->wakeirq);
+ if (err) {
+ dev_err(&client->dev, "unable to setup wakeIRQ %d!\n",
+ err);
+ goto exit;
}
}
+no_irq:
if (chip->nvram_size) {
ds1307->nvram = devm_kzalloc(&client->dev,
@@ -1231,10 +1226,8 @@ static int ds1307_remove(struct i2c_client *client)
{
struct ds1307 *ds1307 = i2c_get_clientdata(client);
- if (test_and_clear_bit(HAS_ALARM, &ds1307->flags)) {
- free_irq(client->irq, client);
- cancel_work_sync(&ds1307->work);
- }
+ if (ds1307->wakeirq)
+ dev_pm_clear_wake_irq(&client->dev);
if (test_and_clear_bit(HAS_NVRAM, &ds1307->flags))
sysfs_remove_bin_file(&client->dev.kobj, ds1307->nvram);
@@ -1245,7 +1238,6 @@ static int ds1307_remove(struct i2c_client *client)
static struct i2c_driver ds1307_driver = {
.driver = {
.name = "rtc-ds1307",
- .owner = THIS_MODULE,
},
.probe = ds1307_probe,
.remove = ds1307_remove,
diff --git a/drivers/rtc/rtc-ds1343.c b/drivers/rtc/rtc-ds1343.c
index ae9f99722..79a06dd3c 100644
--- a/drivers/rtc/rtc-ds1343.c
+++ b/drivers/rtc/rtc-ds1343.c
@@ -162,12 +162,6 @@ static ssize_t ds1343_nvram_write(struct file *filp, struct kobject *kobj,
struct device *dev = kobj_to_dev(kobj);
struct ds1343_priv *priv = dev_get_drvdata(dev);
- if (unlikely(!count))
- return count;
-
- if ((count + off) > DS1343_NVRAM_LEN)
- count = DS1343_NVRAM_LEN - off;
-
address = DS1343_NVRAM + off;
ret = regmap_bulk_write(priv->map, address, buf, count);
@@ -187,12 +181,6 @@ static ssize_t ds1343_nvram_read(struct file *filp, struct kobject *kobj,
struct device *dev = kobj_to_dev(kobj);
struct ds1343_priv *priv = dev_get_drvdata(dev);
- if (unlikely(!count))
- return count;
-
- if ((count + off) > DS1343_NVRAM_LEN)
- count = DS1343_NVRAM_LEN - off;
-
address = DS1343_NVRAM + off;
ret = regmap_bulk_read(priv->map, address, buf, count);
diff --git a/drivers/rtc/rtc-ds1374.c b/drivers/rtc/rtc-ds1374.c
index 167783fa7..3b3049c8c 100644
--- a/drivers/rtc/rtc-ds1374.c
+++ b/drivers/rtc/rtc-ds1374.c
@@ -664,11 +664,8 @@ static int ds1374_remove(struct i2c_client *client)
{
struct ds1374 *ds1374 = i2c_get_clientdata(client);
#ifdef CONFIG_RTC_DRV_DS1374_WDT
- int res;
-
- res = misc_deregister(&ds1374_miscdev);
- if (!res)
- ds1374_miscdev.parent = NULL;
+ misc_deregister(&ds1374_miscdev);
+ ds1374_miscdev.parent = NULL;
unregister_reboot_notifier(&ds1374_wdt_notifier);
#endif
@@ -689,7 +686,7 @@ static int ds1374_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
- if (client->irq >= 0 && device_may_wakeup(&client->dev))
+ if (client->irq > 0 && device_may_wakeup(&client->dev))
enable_irq_wake(client->irq);
return 0;
}
@@ -698,7 +695,7 @@ static int ds1374_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
- if (client->irq >= 0 && device_may_wakeup(&client->dev))
+ if (client->irq > 0 && device_may_wakeup(&client->dev))
disable_irq_wake(client->irq);
return 0;
}
@@ -709,7 +706,6 @@ static SIMPLE_DEV_PM_OPS(ds1374_pm, ds1374_suspend, ds1374_resume);
static struct i2c_driver ds1374_driver = {
.driver = {
.name = "rtc-ds1374",
- .owner = THIS_MODULE,
.pm = &ds1374_pm,
},
.probe = ds1374_probe,
diff --git a/drivers/rtc/rtc-ds1511.c b/drivers/rtc/rtc-ds1511.c
index 7415c2b4d..da3d04ce8 100644
--- a/drivers/rtc/rtc-ds1511.c
+++ b/drivers/rtc/rtc-ds1511.c
@@ -64,7 +64,7 @@ enum ds1511reg {
#define DS1511_KIE 0x04
#define DS1511_WDE 0x02
#define DS1511_WDS 0x01
-#define DS1511_RAM_MAX 0xff
+#define DS1511_RAM_MAX 0x100
#define RTC_CMD DS1511_CONTROL_B
#define RTC_CMD1 DS1511_CONTROL_A
@@ -159,7 +159,7 @@ ds1511_wdog_set(unsigned long deciseconds)
/*
* set wdog enable and wdog 'steering' bit to issue a reset
*/
- rtc_write(DS1511_WDE | DS1511_WDS, RTC_CMD);
+ rtc_write(rtc_read(RTC_CMD) | DS1511_WDE | DS1511_WDS, RTC_CMD);
}
void
@@ -407,26 +407,10 @@ ds1511_nvram_read(struct file *filp, struct kobject *kobj,
{
ssize_t count;
- /*
- * if count is more than one, turn on "burst" mode
- * turn it off when you're done
- */
- if (size > 1)
- rtc_write((rtc_read(RTC_CMD) | DS1511_BME), RTC_CMD);
-
- if (pos > DS1511_RAM_MAX)
- pos = DS1511_RAM_MAX;
-
- if (size + pos > DS1511_RAM_MAX + 1)
- size = DS1511_RAM_MAX - pos + 1;
-
rtc_write(pos, DS1511_RAMADDR_LSB);
- for (count = 0; size > 0; count++, size--)
+ for (count = 0; count < size; count++)
*buf++ = rtc_read(DS1511_RAMDATA);
- if (count > 1)
- rtc_write((rtc_read(RTC_CMD) & ~DS1511_BME), RTC_CMD);
-
return count;
}
@@ -437,26 +421,10 @@ ds1511_nvram_write(struct file *filp, struct kobject *kobj,
{
ssize_t count;
- /*
- * if count is more than one, turn on "burst" mode
- * turn it off when you're done
- */
- if (size > 1)
- rtc_write((rtc_read(RTC_CMD) | DS1511_BME), RTC_CMD);
-
- if (pos > DS1511_RAM_MAX)
- pos = DS1511_RAM_MAX;
-
- if (size + pos > DS1511_RAM_MAX + 1)
- size = DS1511_RAM_MAX - pos + 1;
-
rtc_write(pos, DS1511_RAMADDR_LSB);
- for (count = 0; size > 0; count++, size--)
+ for (count = 0; count < size; count++)
rtc_write(*buf++, DS1511_RAMDATA);
- if (count > 1)
- rtc_write((rtc_read(RTC_CMD) & ~DS1511_BME), RTC_CMD);
-
return count;
}
@@ -490,7 +458,7 @@ static int ds1511_rtc_probe(struct platform_device *pdev)
/*
* turn on the clock and the crystal, etc.
*/
- rtc_write(0, RTC_CMD);
+ rtc_write(DS1511_BME, RTC_CMD);
rtc_write(0, RTC_CMD1);
/*
* clear the wdog counter
diff --git a/drivers/rtc/rtc-ds1553.c b/drivers/rtc/rtc-ds1553.c
index a24e091bc..38422ab4e 100644
--- a/drivers/rtc/rtc-ds1553.c
+++ b/drivers/rtc/rtc-ds1553.c
@@ -245,7 +245,7 @@ static ssize_t ds1553_nvram_read(struct file *filp, struct kobject *kobj,
void __iomem *ioaddr = pdata->ioaddr;
ssize_t count;
- for (count = 0; size > 0 && pos < RTC_OFFSET; count++, size--)
+ for (count = 0; count < size; count++)
*buf++ = readb(ioaddr + pos++);
return count;
}
@@ -260,7 +260,7 @@ static ssize_t ds1553_nvram_write(struct file *filp, struct kobject *kobj,
void __iomem *ioaddr = pdata->ioaddr;
ssize_t count;
- for (count = 0; size > 0 && pos < RTC_OFFSET; count++, size--)
+ for (count = 0; count < size; count++)
writeb(*buf++, ioaddr + pos++);
return count;
}
diff --git a/drivers/rtc/rtc-ds1685.c b/drivers/rtc/rtc-ds1685.c
index 818a3635a..05a51ef52 100644
--- a/drivers/rtc/rtc-ds1685.c
+++ b/drivers/rtc/rtc-ds1685.c
@@ -2145,27 +2145,7 @@ static struct platform_driver ds1685_rtc_driver = {
.probe = ds1685_rtc_probe,
.remove = ds1685_rtc_remove,
};
-
-/**
- * ds1685_rtc_init - rtc module init.
- */
-static int __init
-ds1685_rtc_init(void)
-{
- return platform_driver_register(&ds1685_rtc_driver);
-}
-
-/**
- * ds1685_rtc_exit - rtc module exit.
- */
-static void __exit
-ds1685_rtc_exit(void)
-{
- platform_driver_unregister(&ds1685_rtc_driver);
-}
-
-module_init(ds1685_rtc_init);
-module_exit(ds1685_rtc_exit);
+module_platform_driver(ds1685_rtc_driver);
/* ----------------------------------------------------------------------- */
diff --git a/drivers/rtc/rtc-ds1742.c b/drivers/rtc/rtc-ds1742.c
index 0f8d8ace1..c5168b3bc 100644
--- a/drivers/rtc/rtc-ds1742.c
+++ b/drivers/rtc/rtc-ds1742.c
@@ -134,7 +134,7 @@ static ssize_t ds1742_nvram_read(struct file *filp, struct kobject *kobj,
void __iomem *ioaddr = pdata->ioaddr_nvram;
ssize_t count;
- for (count = 0; size > 0 && pos < pdata->size_nvram; count++, size--)
+ for (count = 0; count < size; count++)
*buf++ = readb(ioaddr + pos++);
return count;
}
@@ -149,7 +149,7 @@ static ssize_t ds1742_nvram_write(struct file *filp, struct kobject *kobj,
void __iomem *ioaddr = pdata->ioaddr_nvram;
ssize_t count;
- for (count = 0; size > 0 && pos < pdata->size_nvram; count++, size--)
+ for (count = 0; count < size; count++)
writeb(*buf++, ioaddr + pos++);
return count;
}
diff --git a/drivers/rtc/rtc-ds3232.c b/drivers/rtc/rtc-ds3232.c
index 7e48e5322..4e99ace66 100644
--- a/drivers/rtc/rtc-ds3232.c
+++ b/drivers/rtc/rtc-ds3232.c
@@ -443,7 +443,7 @@ static int ds3232_remove(struct i2c_client *client)
{
struct ds3232 *ds3232 = i2c_get_clientdata(client);
- if (client->irq >= 0) {
+ if (client->irq > 0) {
mutex_lock(&ds3232->mutex);
ds3232->exiting = 1;
mutex_unlock(&ds3232->mutex);
@@ -463,7 +463,10 @@ static int ds3232_suspend(struct device *dev)
if (device_can_wakeup(dev)) {
ds3232->suspended = true;
- irq_set_irq_wake(client->irq, 1);
+ if (irq_set_irq_wake(client->irq, 1)) {
+ dev_warn_once(dev, "Cannot set wakeup source\n");
+ ds3232->suspended = false;
+ }
}
return 0;
@@ -500,7 +503,6 @@ MODULE_DEVICE_TABLE(i2c, ds3232_id);
static struct i2c_driver ds3232_driver = {
.driver = {
.name = "rtc-ds3232",
- .owner = THIS_MODULE,
.pm = &ds3232_pm_ops,
},
.probe = ds3232_probe,
diff --git a/drivers/rtc/rtc-fm3130.c b/drivers/rtc/rtc-fm3130.c
index 83c3b3029..576eadbba 100644
--- a/drivers/rtc/rtc-fm3130.c
+++ b/drivers/rtc/rtc-fm3130.c
@@ -523,7 +523,6 @@ exit_free:
static struct i2c_driver fm3130_driver = {
.driver = {
.name = "rtc-fm3130",
- .owner = THIS_MODULE,
},
.probe = fm3130_probe,
.id_table = fm3130_id,
diff --git a/drivers/rtc/rtc-gemini.c b/drivers/rtc/rtc-gemini.c
index 35f448673..e84184647 100644
--- a/drivers/rtc/rtc-gemini.c
+++ b/drivers/rtc/rtc-gemini.c
@@ -148,10 +148,7 @@ static int gemini_rtc_probe(struct platform_device *pdev)
rtc->rtc_dev = rtc_device_register(pdev->name, dev,
&gemini_rtc_ops, THIS_MODULE);
- if (likely(IS_ERR(rtc->rtc_dev)))
- return PTR_ERR(rtc->rtc_dev);
-
- return 0;
+ return PTR_ERR_OR_ZERO(rtc->rtc_dev);
}
static int gemini_rtc_remove(struct platform_device *pdev)
diff --git a/drivers/rtc/rtc-hym8563.c b/drivers/rtc/rtc-hym8563.c
index e9da7959d..097325d96 100644
--- a/drivers/rtc/rtc-hym8563.c
+++ b/drivers/rtc/rtc-hym8563.c
@@ -599,7 +599,6 @@ MODULE_DEVICE_TABLE(of, hym8563_dt_idtable);
static struct i2c_driver hym8563_driver = {
.driver = {
.name = "rtc-hym8563",
- .owner = THIS_MODULE,
.pm = &hym8563_pm_ops,
.of_match_table = hym8563_dt_idtable,
},
diff --git a/drivers/rtc/rtc-isl12022.c b/drivers/rtc/rtc-isl12022.c
index f9b082784..839d1fd63 100644
--- a/drivers/rtc/rtc-isl12022.c
+++ b/drivers/rtc/rtc-isl12022.c
@@ -151,12 +151,7 @@ static int isl12022_get_datetime(struct i2c_client *client, struct rtc_time *tm)
tm->tm_sec, tm->tm_min, tm->tm_hour,
tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
- /* The clock can give out invalid datetime, but we cannot return
- * -EINVAL otherwise hwclock will refuse to set the time on bootup. */
- if (rtc_valid_tm(tm) < 0)
- dev_err(&client->dev, "retrieved date and time is invalid.\n");
-
- return 0;
+ return rtc_valid_tm(tm);
}
static int isl12022_set_datetime(struct i2c_client *client, struct rtc_time *tm)
@@ -279,6 +274,7 @@ static const struct of_device_id isl12022_dt_match[] = {
{ .compatible = "isil,isl12022" },
{ },
};
+MODULE_DEVICE_TABLE(of, isl12022_dt_match);
#endif
static const struct i2c_device_id isl12022_id[] = {
diff --git a/drivers/rtc/rtc-isl12057.c b/drivers/rtc/rtc-isl12057.c
index da818d333..a0462e543 100644
--- a/drivers/rtc/rtc-isl12057.c
+++ b/drivers/rtc/rtc-isl12057.c
@@ -648,6 +648,7 @@ static const struct of_device_id isl12057_dt_match[] = {
{ .compatible = "isil,isl12057" },
{ },
};
+MODULE_DEVICE_TABLE(of, isl12057_dt_match);
#endif
static const struct i2c_device_id isl12057_id[] = {
@@ -659,7 +660,6 @@ MODULE_DEVICE_TABLE(i2c, isl12057_id);
static struct i2c_driver isl12057_driver = {
.driver = {
.name = DRV_NAME,
- .owner = THIS_MODULE,
.pm = &isl12057_rtc_pm_ops,
.of_match_table = of_match_ptr(isl12057_dt_match),
},
diff --git a/drivers/rtc/rtc-lpc24xx.c b/drivers/rtc/rtc-lpc24xx.c
new file mode 100644
index 000000000..59d99596f
--- /dev/null
+++ b/drivers/rtc/rtc-lpc24xx.c
@@ -0,0 +1,310 @@
+/*
+ * RTC driver for NXP LPC178x/18xx/43xx Real-Time Clock (RTC)
+ *
+ * Copyright (C) 2011 NXP Semiconductors
+ * Copyright (C) 2015 Joachim Eastwood <manabian@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/rtc.h>
+
+/* LPC24xx RTC register offsets and bits */
+#define LPC24XX_ILR 0x00
+#define LPC24XX_RTCCIF BIT(0)
+#define LPC24XX_RTCALF BIT(1)
+#define LPC24XX_CTC 0x04
+#define LPC24XX_CCR 0x08
+#define LPC24XX_CLKEN BIT(0)
+#define LPC178X_CCALEN BIT(4)
+#define LPC24XX_CIIR 0x0c
+#define LPC24XX_AMR 0x10
+#define LPC24XX_ALARM_DISABLE 0xff
+#define LPC24XX_CTIME0 0x14
+#define LPC24XX_CTIME1 0x18
+#define LPC24XX_CTIME2 0x1c
+#define LPC24XX_SEC 0x20
+#define LPC24XX_MIN 0x24
+#define LPC24XX_HOUR 0x28
+#define LPC24XX_DOM 0x2c
+#define LPC24XX_DOW 0x30
+#define LPC24XX_DOY 0x34
+#define LPC24XX_MONTH 0x38
+#define LPC24XX_YEAR 0x3c
+#define LPC24XX_ALSEC 0x60
+#define LPC24XX_ALMIN 0x64
+#define LPC24XX_ALHOUR 0x68
+#define LPC24XX_ALDOM 0x6c
+#define LPC24XX_ALDOW 0x70
+#define LPC24XX_ALDOY 0x74
+#define LPC24XX_ALMON 0x78
+#define LPC24XX_ALYEAR 0x7c
+
+/* Macros to read fields in consolidated time (CT) registers */
+#define CT0_SECS(x) (((x) >> 0) & 0x3f)
+#define CT0_MINS(x) (((x) >> 8) & 0x3f)
+#define CT0_HOURS(x) (((x) >> 16) & 0x1f)
+#define CT0_DOW(x) (((x) >> 24) & 0x07)
+#define CT1_DOM(x) (((x) >> 0) & 0x1f)
+#define CT1_MONTH(x) (((x) >> 8) & 0x0f)
+#define CT1_YEAR(x) (((x) >> 16) & 0xfff)
+#define CT2_DOY(x) (((x) >> 0) & 0xfff)
+
+#define rtc_readl(dev, reg) readl((dev)->rtc_base + (reg))
+#define rtc_writel(dev, reg, val) writel((val), (dev)->rtc_base + (reg))
+
+struct lpc24xx_rtc {
+ void __iomem *rtc_base;
+ struct rtc_device *rtc;
+ struct clk *clk_rtc;
+ struct clk *clk_reg;
+};
+
+static int lpc24xx_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+ struct lpc24xx_rtc *rtc = dev_get_drvdata(dev);
+
+ /* Disable RTC during update */
+ rtc_writel(rtc, LPC24XX_CCR, LPC178X_CCALEN);
+
+ rtc_writel(rtc, LPC24XX_SEC, tm->tm_sec);
+ rtc_writel(rtc, LPC24XX_MIN, tm->tm_min);
+ rtc_writel(rtc, LPC24XX_HOUR, tm->tm_hour);
+ rtc_writel(rtc, LPC24XX_DOW, tm->tm_wday);
+ rtc_writel(rtc, LPC24XX_DOM, tm->tm_mday);
+ rtc_writel(rtc, LPC24XX_DOY, tm->tm_yday);
+ rtc_writel(rtc, LPC24XX_MONTH, tm->tm_mon);
+ rtc_writel(rtc, LPC24XX_YEAR, tm->tm_year);
+
+ rtc_writel(rtc, LPC24XX_CCR, LPC24XX_CLKEN | LPC178X_CCALEN);
+
+ return 0;
+}
+
+static int lpc24xx_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+ struct lpc24xx_rtc *rtc = dev_get_drvdata(dev);
+ u32 ct0, ct1, ct2;
+
+ ct0 = rtc_readl(rtc, LPC24XX_CTIME0);
+ ct1 = rtc_readl(rtc, LPC24XX_CTIME1);
+ ct2 = rtc_readl(rtc, LPC24XX_CTIME2);
+
+ tm->tm_sec = CT0_SECS(ct0);
+ tm->tm_min = CT0_MINS(ct0);
+ tm->tm_hour = CT0_HOURS(ct0);
+ tm->tm_wday = CT0_DOW(ct0);
+ tm->tm_mon = CT1_MONTH(ct1);
+ tm->tm_mday = CT1_DOM(ct1);
+ tm->tm_year = CT1_YEAR(ct1);
+ tm->tm_yday = CT2_DOY(ct2);
+
+ return rtc_valid_tm(tm);
+}
+
+static int lpc24xx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
+{
+ struct lpc24xx_rtc *rtc = dev_get_drvdata(dev);
+ struct rtc_time *tm = &wkalrm->time;
+
+ tm->tm_sec = rtc_readl(rtc, LPC24XX_ALSEC);
+ tm->tm_min = rtc_readl(rtc, LPC24XX_ALMIN);
+ tm->tm_hour = rtc_readl(rtc, LPC24XX_ALHOUR);
+ tm->tm_mday = rtc_readl(rtc, LPC24XX_ALDOM);
+ tm->tm_wday = rtc_readl(rtc, LPC24XX_ALDOW);
+ tm->tm_yday = rtc_readl(rtc, LPC24XX_ALDOY);
+ tm->tm_mon = rtc_readl(rtc, LPC24XX_ALMON);
+ tm->tm_year = rtc_readl(rtc, LPC24XX_ALYEAR);
+
+ wkalrm->enabled = rtc_readl(rtc, LPC24XX_AMR) == 0;
+ wkalrm->pending = !!(rtc_readl(rtc, LPC24XX_ILR) & LPC24XX_RTCCIF);
+
+ return rtc_valid_tm(&wkalrm->time);
+}
+
+static int lpc24xx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
+{
+ struct lpc24xx_rtc *rtc = dev_get_drvdata(dev);
+ struct rtc_time *tm = &wkalrm->time;
+
+ /* Disable alarm irq during update */
+ rtc_writel(rtc, LPC24XX_AMR, LPC24XX_ALARM_DISABLE);
+
+ rtc_writel(rtc, LPC24XX_ALSEC, tm->tm_sec);
+ rtc_writel(rtc, LPC24XX_ALMIN, tm->tm_min);
+ rtc_writel(rtc, LPC24XX_ALHOUR, tm->tm_hour);
+ rtc_writel(rtc, LPC24XX_ALDOM, tm->tm_mday);
+ rtc_writel(rtc, LPC24XX_ALDOW, tm->tm_wday);
+ rtc_writel(rtc, LPC24XX_ALDOY, tm->tm_yday);
+ rtc_writel(rtc, LPC24XX_ALMON, tm->tm_mon);
+ rtc_writel(rtc, LPC24XX_ALYEAR, tm->tm_year);
+
+ if (wkalrm->enabled)
+ rtc_writel(rtc, LPC24XX_AMR, 0);
+
+ return 0;
+}
+
+static int lpc24xx_rtc_alarm_irq_enable(struct device *dev, unsigned int enable)
+{
+ struct lpc24xx_rtc *rtc = dev_get_drvdata(dev);
+
+ if (enable)
+ rtc_writel(rtc, LPC24XX_AMR, 0);
+ else
+ rtc_writel(rtc, LPC24XX_AMR, LPC24XX_ALARM_DISABLE);
+
+ return 0;
+}
+
+static irqreturn_t lpc24xx_rtc_interrupt(int irq, void *data)
+{
+ unsigned long events = RTC_IRQF;
+ struct lpc24xx_rtc *rtc = data;
+ u32 rtc_iir;
+
+ /* Check interrupt cause */
+ rtc_iir = rtc_readl(rtc, LPC24XX_ILR);
+ if (rtc_iir & LPC24XX_RTCALF) {
+ events |= RTC_AF;
+ rtc_writel(rtc, LPC24XX_AMR, LPC24XX_ALARM_DISABLE);
+ }
+
+ /* Clear interrupt status and report event */
+ rtc_writel(rtc, LPC24XX_ILR, rtc_iir);
+ rtc_update_irq(rtc->rtc, 1, events);
+
+ return IRQ_HANDLED;
+}
+
+static const struct rtc_class_ops lpc24xx_rtc_ops = {
+ .read_time = lpc24xx_rtc_read_time,
+ .set_time = lpc24xx_rtc_set_time,
+ .read_alarm = lpc24xx_rtc_read_alarm,
+ .set_alarm = lpc24xx_rtc_set_alarm,
+ .alarm_irq_enable = lpc24xx_rtc_alarm_irq_enable,
+};
+
+static int lpc24xx_rtc_probe(struct platform_device *pdev)
+{
+ struct lpc24xx_rtc *rtc;
+ struct resource *res;
+ int irq, ret;
+
+ rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
+ if (!rtc)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ rtc->rtc_base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(rtc->rtc_base))
+ return PTR_ERR(rtc->rtc_base);
+
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ dev_warn(&pdev->dev, "can't get interrupt resource\n");
+ return irq;
+ }
+
+ rtc->clk_rtc = devm_clk_get(&pdev->dev, "rtc");
+ if (IS_ERR(rtc->clk_rtc)) {
+ dev_err(&pdev->dev, "error getting rtc clock\n");
+ return PTR_ERR(rtc->clk_rtc);
+ }
+
+ rtc->clk_reg = devm_clk_get(&pdev->dev, "reg");
+ if (IS_ERR(rtc->clk_reg)) {
+ dev_err(&pdev->dev, "error getting reg clock\n");
+ return PTR_ERR(rtc->clk_reg);
+ }
+
+ ret = clk_prepare_enable(rtc->clk_rtc);
+ if (ret) {
+ dev_err(&pdev->dev, "unable to enable rtc clock\n");
+ return ret;
+ }
+
+ ret = clk_prepare_enable(rtc->clk_reg);
+ if (ret) {
+ dev_err(&pdev->dev, "unable to enable reg clock\n");
+ goto disable_rtc_clk;
+ }
+
+ platform_set_drvdata(pdev, rtc);
+
+ /* Clear any pending interrupts */
+ rtc_writel(rtc, LPC24XX_ILR, LPC24XX_RTCCIF | LPC24XX_RTCALF);
+
+ /* Enable RTC count */
+ rtc_writel(rtc, LPC24XX_CCR, LPC24XX_CLKEN | LPC178X_CCALEN);
+
+ ret = devm_request_irq(&pdev->dev, irq, lpc24xx_rtc_interrupt, 0,
+ pdev->name, rtc);
+ if (ret < 0) {
+ dev_warn(&pdev->dev, "can't request interrupt\n");
+ goto disable_clks;
+ }
+
+ rtc->rtc = devm_rtc_device_register(&pdev->dev, "lpc24xx-rtc",
+ &lpc24xx_rtc_ops, THIS_MODULE);
+ if (IS_ERR(rtc->rtc)) {
+ dev_err(&pdev->dev, "can't register rtc device\n");
+ ret = PTR_ERR(rtc->rtc);
+ goto disable_clks;
+ }
+
+ return 0;
+
+disable_clks:
+ clk_disable_unprepare(rtc->clk_reg);
+disable_rtc_clk:
+ clk_disable_unprepare(rtc->clk_rtc);
+ return ret;
+}
+
+static int lpc24xx_rtc_remove(struct platform_device *pdev)
+{
+ struct lpc24xx_rtc *rtc = platform_get_drvdata(pdev);
+
+ /* Ensure all interrupt sources are masked */
+ rtc_writel(rtc, LPC24XX_AMR, LPC24XX_ALARM_DISABLE);
+ rtc_writel(rtc, LPC24XX_CIIR, 0);
+
+ rtc_writel(rtc, LPC24XX_CCR, LPC178X_CCALEN);
+
+ clk_disable_unprepare(rtc->clk_rtc);
+ clk_disable_unprepare(rtc->clk_reg);
+
+ return 0;
+}
+
+static const struct of_device_id lpc24xx_rtc_match[] = {
+ { .compatible = "nxp,lpc1788-rtc" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, lpc24xx_rtc_match);
+
+static struct platform_driver lpc24xx_rtc_driver = {
+ .probe = lpc24xx_rtc_probe,
+ .remove = lpc24xx_rtc_remove,
+ .driver = {
+ .name = "lpc24xx-rtc",
+ .of_match_table = lpc24xx_rtc_match,
+ },
+};
+module_platform_driver(lpc24xx_rtc_driver);
+
+MODULE_AUTHOR("Kevin Wells <wellsk40@gmail.com>");
+MODULE_DESCRIPTION("RTC driver for the LPC178x/18xx/408x/43xx SoCs");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-m48t59.c b/drivers/rtc/rtc-m48t59.c
index 90abb5bd5..d99a705be 100644
--- a/drivers/rtc/rtc-m48t59.c
+++ b/drivers/rtc/rtc-m48t59.c
@@ -345,11 +345,12 @@ static ssize_t m48t59_nvram_read(struct file *filp, struct kobject *kobj,
ssize_t cnt = 0;
unsigned long flags;
- for (; size > 0 && pos < pdata->offset; cnt++, size--) {
- spin_lock_irqsave(&m48t59->lock, flags);
+ spin_lock_irqsave(&m48t59->lock, flags);
+
+ for (; cnt < size; cnt++)
*buf++ = M48T59_READ(cnt);
- spin_unlock_irqrestore(&m48t59->lock, flags);
- }
+
+ spin_unlock_irqrestore(&m48t59->lock, flags);
return cnt;
}
@@ -365,11 +366,12 @@ static ssize_t m48t59_nvram_write(struct file *filp, struct kobject *kobj,
ssize_t cnt = 0;
unsigned long flags;
- for (; size > 0 && pos < pdata->offset; cnt++, size--) {
- spin_lock_irqsave(&m48t59->lock, flags);
+ spin_lock_irqsave(&m48t59->lock, flags);
+
+ for (; cnt < size; cnt++)
M48T59_WRITE(*buf++, cnt);
- spin_unlock_irqrestore(&m48t59->lock, flags);
- }
+
+ spin_unlock_irqrestore(&m48t59->lock, flags);
return cnt;
}
diff --git a/drivers/rtc/rtc-max8997.c b/drivers/rtc/rtc-max8997.c
index 9e02bcda0..db984d4bf 100644
--- a/drivers/rtc/rtc-max8997.c
+++ b/drivers/rtc/rtc-max8997.c
@@ -521,6 +521,7 @@ static const struct platform_device_id rtc_id[] = {
{ "max8997-rtc", 0 },
{},
};
+MODULE_DEVICE_TABLE(platform, rtc_id);
static struct platform_driver max8997_rtc_driver = {
.driver = {
diff --git a/drivers/rtc/rtc-moxart.c b/drivers/rtc/rtc-moxart.c
index 73759c9a4..07b30a373 100644
--- a/drivers/rtc/rtc-moxart.c
+++ b/drivers/rtc/rtc-moxart.c
@@ -312,6 +312,7 @@ static const struct of_device_id moxart_rtc_match[] = {
{ .compatible = "moxa,moxart-rtc" },
{ },
};
+MODULE_DEVICE_TABLE(of, moxart_rtc_match);
static struct platform_driver moxart_rtc_driver = {
.probe = moxart_rtc_probe,
diff --git a/drivers/rtc/rtc-mpc5121.c b/drivers/rtc/rtc-mpc5121.c
index 1767e18d5..4ca4daa0b 100644
--- a/drivers/rtc/rtc-mpc5121.c
+++ b/drivers/rtc/rtc-mpc5121.c
@@ -406,6 +406,7 @@ static const struct of_device_id mpc5121_rtc_match[] = {
{ .compatible = "fsl,mpc5200-rtc", },
{},
};
+MODULE_DEVICE_TABLE(of, mpc5121_rtc_match);
#endif
static struct platform_driver mpc5121_rtc_driver = {
diff --git a/drivers/rtc/rtc-mt6397.c b/drivers/rtc/rtc-mt6397.c
index eab230be5..06a5c52b2 100644
--- a/drivers/rtc/rtc-mt6397.c
+++ b/drivers/rtc/rtc-mt6397.c
@@ -373,15 +373,42 @@ static int mtk_rtc_remove(struct platform_device *pdev)
return 0;
}
+#ifdef CONFIG_PM_SLEEP
+static int mt6397_rtc_suspend(struct device *dev)
+{
+ struct mt6397_rtc *rtc = dev_get_drvdata(dev);
+
+ if (device_may_wakeup(dev))
+ enable_irq_wake(rtc->irq);
+
+ return 0;
+}
+
+static int mt6397_rtc_resume(struct device *dev)
+{
+ struct mt6397_rtc *rtc = dev_get_drvdata(dev);
+
+ if (device_may_wakeup(dev))
+ disable_irq_wake(rtc->irq);
+
+ return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(mt6397_pm_ops, mt6397_rtc_suspend,
+ mt6397_rtc_resume);
+
static const struct of_device_id mt6397_rtc_of_match[] = {
{ .compatible = "mediatek,mt6397-rtc", },
{ }
};
+MODULE_DEVICE_TABLE(of, mt6397_rtc_of_match);
static struct platform_driver mtk_rtc_driver = {
.driver = {
.name = "mt6397-rtc",
.of_match_table = mt6397_rtc_of_match,
+ .pm = &mt6397_pm_ops,
},
.probe = mtk_rtc_probe,
.remove = mtk_rtc_remove,
diff --git a/drivers/rtc/rtc-mv.c b/drivers/rtc/rtc-mv.c
index 7f50d2ef7..79bb28617 100644
--- a/drivers/rtc/rtc-mv.c
+++ b/drivers/rtc/rtc-mv.c
@@ -324,6 +324,7 @@ static const struct of_device_id rtc_mv_of_match_table[] = {
{ .compatible = "marvell,orion-rtc", },
{}
};
+MODULE_DEVICE_TABLE(of, rtc_mv_of_match_table);
#endif
static struct platform_driver mv_rtc_driver = {
diff --git a/drivers/rtc/rtc-mxc.c b/drivers/rtc/rtc-mxc.c
index 5fc292c2d..7bd89d900 100644
--- a/drivers/rtc/rtc-mxc.c
+++ b/drivers/rtc/rtc-mxc.c
@@ -16,6 +16,8 @@
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
#define RTC_INPUT_CLK_32768HZ (0x00 << 5)
#define RTC_INPUT_CLK_32000HZ (0x01 << 5)
@@ -79,7 +81,8 @@ struct rtc_plat_data {
struct rtc_device *rtc;
void __iomem *ioaddr;
int irq;
- struct clk *clk;
+ struct clk *clk_ref;
+ struct clk *clk_ipg;
struct rtc_time g_rtc_alarm;
enum imx_rtc_type devtype;
};
@@ -97,6 +100,15 @@ static const struct platform_device_id imx_rtc_devtype[] = {
};
MODULE_DEVICE_TABLE(platform, imx_rtc_devtype);
+#ifdef CONFIG_OF
+static const struct of_device_id imx_rtc_dt_ids[] = {
+ { .compatible = "fsl,imx1-rtc", .data = (const void *)IMX1_RTC },
+ { .compatible = "fsl,imx21-rtc", .data = (const void *)IMX21_RTC },
+ {}
+};
+MODULE_DEVICE_TABLE(of, imx_rtc_dt_ids);
+#endif
+
static inline int is_imx1_rtc(struct rtc_plat_data *data)
{
return data->devtype == IMX1_RTC;
@@ -361,29 +373,45 @@ static int mxc_rtc_probe(struct platform_device *pdev)
u32 reg;
unsigned long rate;
int ret;
+ const struct of_device_id *of_id;
pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata)
return -ENOMEM;
- pdata->devtype = pdev->id_entry->driver_data;
+ of_id = of_match_device(imx_rtc_dt_ids, &pdev->dev);
+ if (of_id)
+ pdata->devtype = (enum imx_rtc_type)of_id->data;
+ else
+ pdata->devtype = pdev->id_entry->driver_data;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
pdata->ioaddr = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(pdata->ioaddr))
return PTR_ERR(pdata->ioaddr);
- pdata->clk = devm_clk_get(&pdev->dev, NULL);
- if (IS_ERR(pdata->clk)) {
- dev_err(&pdev->dev, "unable to get clock!\n");
- return PTR_ERR(pdata->clk);
+ pdata->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
+ if (IS_ERR(pdata->clk_ipg)) {
+ dev_err(&pdev->dev, "unable to get ipg clock!\n");
+ return PTR_ERR(pdata->clk_ipg);
}
- ret = clk_prepare_enable(pdata->clk);
+ ret = clk_prepare_enable(pdata->clk_ipg);
if (ret)
return ret;
- rate = clk_get_rate(pdata->clk);
+ pdata->clk_ref = devm_clk_get(&pdev->dev, "ref");
+ if (IS_ERR(pdata->clk_ref)) {
+ dev_err(&pdev->dev, "unable to get ref clock!\n");
+ ret = PTR_ERR(pdata->clk_ref);
+ goto exit_put_clk_ipg;
+ }
+
+ ret = clk_prepare_enable(pdata->clk_ref);
+ if (ret)
+ goto exit_put_clk_ipg;
+
+ rate = clk_get_rate(pdata->clk_ref);
if (rate == 32768)
reg = RTC_INPUT_CLK_32768HZ;
@@ -394,7 +422,7 @@ static int mxc_rtc_probe(struct platform_device *pdev)
else {
dev_err(&pdev->dev, "rtc clock is not valid (%lu)\n", rate);
ret = -EINVAL;
- goto exit_put_clk;
+ goto exit_put_clk_ref;
}
reg |= RTC_ENABLE_BIT;
@@ -402,7 +430,7 @@ static int mxc_rtc_probe(struct platform_device *pdev)
if (((readw(pdata->ioaddr + RTC_RTCCTL)) & RTC_ENABLE_BIT) == 0) {
dev_err(&pdev->dev, "hardware module can't be enabled!\n");
ret = -EIO;
- goto exit_put_clk;
+ goto exit_put_clk_ref;
}
platform_set_drvdata(pdev, pdata);
@@ -424,15 +452,17 @@ static int mxc_rtc_probe(struct platform_device *pdev)
THIS_MODULE);
if (IS_ERR(rtc)) {
ret = PTR_ERR(rtc);
- goto exit_put_clk;
+ goto exit_put_clk_ref;
}
pdata->rtc = rtc;
return 0;
-exit_put_clk:
- clk_disable_unprepare(pdata->clk);
+exit_put_clk_ref:
+ clk_disable_unprepare(pdata->clk_ref);
+exit_put_clk_ipg:
+ clk_disable_unprepare(pdata->clk_ipg);
return ret;
}
@@ -441,7 +471,8 @@ static int mxc_rtc_remove(struct platform_device *pdev)
{
struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
- clk_disable_unprepare(pdata->clk);
+ clk_disable_unprepare(pdata->clk_ref);
+ clk_disable_unprepare(pdata->clk_ipg);
return 0;
}
@@ -473,6 +504,7 @@ static SIMPLE_DEV_PM_OPS(mxc_rtc_pm_ops, mxc_rtc_suspend, mxc_rtc_resume);
static struct platform_driver mxc_rtc_driver = {
.driver = {
.name = "mxc_rtc",
+ .of_match_table = of_match_ptr(imx_rtc_dt_ids),
.pm = &mxc_rtc_pm_ops,
},
.id_table = imx_rtc_devtype,
diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c
index 8b6355ffa..ec2e9c5fb 100644
--- a/drivers/rtc/rtc-omap.c
+++ b/drivers/rtc/rtc-omap.c
@@ -25,6 +25,7 @@
#include <linux/of_device.h>
#include <linux/pm_runtime.h>
#include <linux/io.h>
+#include <linux/clk.h>
/*
* The OMAP RTC is a year/month/day/hours/minutes/seconds BCD clock
@@ -107,6 +108,7 @@
/* OMAP_RTC_OSC_REG bit fields: */
#define OMAP_RTC_OSC_32KCLK_EN BIT(6)
+#define OMAP_RTC_OSC_SEL_32KCLK_SRC BIT(3)
/* OMAP_RTC_IRQWAKEEN bit fields: */
#define OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN BIT(1)
@@ -132,10 +134,12 @@ struct omap_rtc_device_type {
struct omap_rtc {
struct rtc_device *rtc;
void __iomem *base;
+ struct clk *clk;
int irq_alarm;
int irq_timer;
u8 interrupts_reg;
bool is_pmic_controller;
+ bool has_ext_clk;
const struct omap_rtc_device_type *type;
};
@@ -553,6 +557,15 @@ static int omap_rtc_probe(struct platform_device *pdev)
if (rtc->irq_alarm <= 0)
return -ENOENT;
+ rtc->clk = devm_clk_get(&pdev->dev, "ext-clk");
+ if (!IS_ERR(rtc->clk))
+ rtc->has_ext_clk = true;
+ else
+ rtc->clk = devm_clk_get(&pdev->dev, "int-clk");
+
+ if (!IS_ERR(rtc->clk))
+ clk_prepare_enable(rtc->clk);
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
rtc->base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(rtc->base))
@@ -627,6 +640,16 @@ static int omap_rtc_probe(struct platform_device *pdev)
if (reg != new_ctrl)
rtc_write(rtc, OMAP_RTC_CTRL_REG, new_ctrl);
+ /*
+ * If we have the external clock then switch to it so we can keep
+ * ticking across suspend.
+ */
+ if (rtc->has_ext_clk) {
+ reg = rtc_read(rtc, OMAP_RTC_OSC_REG);
+ rtc_write(rtc, OMAP_RTC_OSC_REG,
+ reg | OMAP_RTC_OSC_SEL_32KCLK_SRC);
+ }
+
rtc->type->lock(rtc);
device_init_wakeup(&pdev->dev, true);
@@ -672,6 +695,7 @@ err:
static int __exit omap_rtc_remove(struct platform_device *pdev)
{
struct omap_rtc *rtc = platform_get_drvdata(pdev);
+ u8 reg;
if (pm_power_off == omap_rtc_power_off &&
omap_rtc_power_off_rtc == rtc) {
@@ -681,10 +705,19 @@ static int __exit omap_rtc_remove(struct platform_device *pdev)
device_init_wakeup(&pdev->dev, 0);
+ if (!IS_ERR(rtc->clk))
+ clk_disable_unprepare(rtc->clk);
+
rtc->type->unlock(rtc);
/* leave rtc running, but disable irqs */
rtc_write(rtc, OMAP_RTC_INTERRUPTS_REG, 0);
+ if (rtc->has_ext_clk) {
+ reg = rtc_read(rtc, OMAP_RTC_OSC_REG);
+ reg &= ~OMAP_RTC_OSC_SEL_32KCLK_SRC;
+ rtc_write(rtc, OMAP_RTC_OSC_REG, reg);
+ }
+
rtc->type->lock(rtc);
/* Disable the clock/module */
diff --git a/drivers/rtc/rtc-opal.c b/drivers/rtc/rtc-opal.c
index 7061dcae2..6fbf9e617 100644
--- a/drivers/rtc/rtc-opal.c
+++ b/drivers/rtc/rtc-opal.c
@@ -190,11 +190,9 @@ exit:
return rc;
}
-static const struct rtc_class_ops opal_rtc_ops = {
+static struct rtc_class_ops opal_rtc_ops = {
.read_time = opal_get_rtc_time,
.set_time = opal_set_rtc_time,
- .read_alarm = opal_get_tpo_time,
- .set_alarm = opal_set_tpo_time,
};
static int opal_rtc_probe(struct platform_device *pdev)
@@ -202,8 +200,11 @@ static int opal_rtc_probe(struct platform_device *pdev)
struct rtc_device *rtc;
if (pdev->dev.of_node && of_get_property(pdev->dev.of_node, "has-tpo",
- NULL))
+ NULL)) {
device_set_wakeup_capable(&pdev->dev, true);
+ opal_rtc_ops.read_alarm = opal_get_tpo_time;
+ opal_rtc_ops.set_alarm = opal_set_tpo_time;
+ }
rtc = devm_rtc_device_register(&pdev->dev, DRVNAME, &opal_rtc_ops,
THIS_MODULE);
@@ -236,7 +237,6 @@ static struct platform_driver opal_rtc_driver = {
.id_table = opal_rtc_driver_ids,
.driver = {
.name = DRVNAME,
- .owner = THIS_MODULE,
.of_match_table = opal_rtc_match,
},
};
diff --git a/drivers/rtc/rtc-pcf2123.c b/drivers/rtc/rtc-pcf2123.c
index 8a7556cbc..1c47650fe 100644
--- a/drivers/rtc/rtc-pcf2123.c
+++ b/drivers/rtc/rtc-pcf2123.c
@@ -165,13 +165,7 @@ static int pcf2123_rtc_read_time(struct device *dev, struct rtc_time *tm)
tm->tm_sec, tm->tm_min, tm->tm_hour,
tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
- /* the clock can give out invalid datetime, but we cannot return
- * -EINVAL otherwise hwclock will refuse to set the time on bootup.
- */
- if (rtc_valid_tm(tm) < 0)
- dev_err(dev, "retrieved date/time is not valid.\n");
-
- return 0;
+ return rtc_valid_tm(tm);
}
static int pcf2123_rtc_set_time(struct device *dev, struct rtc_time *tm)
diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c
index 9bd842e97..4b11d31f7 100644
--- a/drivers/rtc/rtc-pcf2127.c
+++ b/drivers/rtc/rtc-pcf2127.c
@@ -33,11 +33,14 @@
#define PCF2127_REG_MO (0x08)
#define PCF2127_REG_YR (0x09)
+#define PCF2127_OSF BIT(7) /* Oscillator Fail flag */
+
static struct i2c_driver pcf2127_driver;
struct pcf2127 {
struct rtc_device *rtc;
int voltage_low; /* indicates if a low_voltage was detected */
+ int oscillator_failed; /* OSF was detected and date is unreliable */
};
/*
@@ -59,7 +62,18 @@ static int pcf2127_get_datetime(struct i2c_client *client, struct rtc_time *tm)
if (buf[PCF2127_REG_CTRL3] & 0x04) {
pcf2127->voltage_low = 1;
dev_info(&client->dev,
- "low voltage detected, date/time is not reliable.\n");
+ "low voltage detected, check/replace RTC battery.\n");
+ }
+
+ if (buf[PCF2127_REG_SC] & PCF2127_OSF) {
+ /*
+ * no need clear the flag here,
+ * it will be cleared once the new date is saved
+ */
+ pcf2127->oscillator_failed = 1;
+ dev_warn(&client->dev,
+ "oscillator stop detected, date/time is not reliable\n");
+ return -EINVAL;
}
dev_dbg(&client->dev,
@@ -88,17 +102,12 @@ static int pcf2127_get_datetime(struct i2c_client *client, struct rtc_time *tm)
tm->tm_sec, tm->tm_min, tm->tm_hour,
tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday);
- /* the clock can give out invalid datetime, but we cannot return
- * -EINVAL otherwise hwclock will refuse to set the time on bootup.
- */
- if (rtc_valid_tm(tm) < 0)
- dev_err(&client->dev, "retrieved date/time is not valid.\n");
-
- return 0;
+ return rtc_valid_tm(tm);
}
static int pcf2127_set_datetime(struct i2c_client *client, struct rtc_time *tm)
{
+ struct pcf2127 *pcf2127 = i2c_get_clientdata(client);
unsigned char buf[8];
int i = 0, err;
@@ -112,7 +121,7 @@ static int pcf2127_set_datetime(struct i2c_client *client, struct rtc_time *tm)
buf[i++] = PCF2127_REG_SC;
/* hours, minutes and seconds */
- buf[i++] = bin2bcd(tm->tm_sec);
+ buf[i++] = bin2bcd(tm->tm_sec); /* this will also clear OSF flag */
buf[i++] = bin2bcd(tm->tm_min);
buf[i++] = bin2bcd(tm->tm_hour);
buf[i++] = bin2bcd(tm->tm_mday);
@@ -132,6 +141,9 @@ static int pcf2127_set_datetime(struct i2c_client *client, struct rtc_time *tm)
return -EIO;
}
+ /* clear OSF flag in client data */
+ pcf2127->oscillator_failed = 0;
+
return 0;
}
@@ -144,7 +156,9 @@ static int pcf2127_rtc_ioctl(struct device *dev,
switch (cmd) {
case RTC_VL_READ:
if (pcf2127->voltage_low)
- dev_info(dev, "low voltage detected, date/time is not reliable.\n");
+ dev_info(dev, "low voltage detected, check/replace battery\n");
+ if (pcf2127->oscillator_failed)
+ dev_info(dev, "oscillator stop detected, date/time is not reliable\n");
if (copy_to_user((void __user *)arg, &pcf2127->voltage_low,
sizeof(int)))
@@ -217,7 +231,6 @@ MODULE_DEVICE_TABLE(of, pcf2127_of_match);
static struct i2c_driver pcf2127_driver = {
.driver = {
.name = "rtc-pcf2127",
- .owner = THIS_MODULE,
.of_match_table = of_match_ptr(pcf2127_of_match),
},
.probe = pcf2127_probe,
diff --git a/drivers/rtc/rtc-pcf85063.c b/drivers/rtc/rtc-pcf85063.c
index 6a12bf62c..b6d73dd88 100644
--- a/drivers/rtc/rtc-pcf85063.c
+++ b/drivers/rtc/rtc-pcf85063.c
@@ -189,7 +189,6 @@ MODULE_DEVICE_TABLE(of, pcf85063_of_match);
static struct i2c_driver pcf85063_driver = {
.driver = {
.name = "rtc-pcf85063",
- .owner = THIS_MODULE,
.of_match_table = of_match_ptr(pcf85063_of_match),
},
.probe = pcf85063_probe,
diff --git a/drivers/rtc/rtc-pcf8523.c b/drivers/rtc/rtc-pcf8523.c
index 4cdb64be0..e7ebcc0b7 100644
--- a/drivers/rtc/rtc-pcf8523.c
+++ b/drivers/rtc/rtc-pcf8523.c
@@ -334,7 +334,6 @@ MODULE_DEVICE_TABLE(of, pcf8523_of_match);
static struct i2c_driver pcf8523_driver = {
.driver = {
.name = DRIVER_NAME,
- .owner = THIS_MODULE,
.of_match_table = of_match_ptr(pcf8523_of_match),
},
.probe = pcf8523_probe,
diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c
index 8bba022be..e569243db 100644
--- a/drivers/rtc/rtc-pcf8563.c
+++ b/drivers/rtc/rtc-pcf8563.c
@@ -483,7 +483,6 @@ MODULE_DEVICE_TABLE(of, pcf8563_of_match);
static struct i2c_driver pcf8563_driver = {
.driver = {
.name = "rtc-pcf8563",
- .owner = THIS_MODULE,
.of_match_table = of_match_ptr(pcf8563_of_match),
},
.probe = pcf8563_probe,
diff --git a/drivers/rtc/rtc-pcf8583.c b/drivers/rtc/rtc-pcf8583.c
index 5911a6dca..7ca9e8871 100644
--- a/drivers/rtc/rtc-pcf8583.c
+++ b/drivers/rtc/rtc-pcf8583.c
@@ -309,7 +309,6 @@ MODULE_DEVICE_TABLE(i2c, pcf8583_id);
static struct i2c_driver pcf8583_driver = {
.driver = {
.name = "pcf8583",
- .owner = THIS_MODULE,
},
.probe = pcf8583_probe,
.id_table = pcf8583_id,
diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c
index 99181fff8..41dcb7ddb 100644
--- a/drivers/rtc/rtc-pl031.c
+++ b/drivers/rtc/rtc-pl031.c
@@ -476,6 +476,6 @@ static struct amba_driver pl031_driver = {
module_amba_driver(pl031_driver);
-MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net");
+MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net>");
MODULE_DESCRIPTION("ARM AMBA PL031 RTC Driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-pxa.c b/drivers/rtc/rtc-pxa.c
index 4561f3753..fe4985b54 100644
--- a/drivers/rtc/rtc-pxa.c
+++ b/drivers/rtc/rtc-pxa.c
@@ -32,6 +32,8 @@
#include <mach/hardware.h>
+#include "rtc-sa1100.h"
+
#define RTC_DEF_DIVIDER (32768 - 1)
#define RTC_DEF_TRIM 0
#define MAXFREQ_PERIODIC 1000
@@ -86,10 +88,9 @@
__raw_writel((value), (pxa_rtc)->base + (reg))
struct pxa_rtc {
+ struct sa1100_rtc sa1100_rtc;
struct resource *ress;
void __iomem *base;
- int irq_1Hz;
- int irq_Alrm;
struct rtc_device *rtc;
spinlock_t lock; /* Protects this structure */
};
@@ -184,25 +185,25 @@ static int pxa_rtc_open(struct device *dev)
struct pxa_rtc *pxa_rtc = dev_get_drvdata(dev);
int ret;
- ret = request_irq(pxa_rtc->irq_1Hz, pxa_rtc_irq, 0,
+ ret = request_irq(pxa_rtc->sa1100_rtc.irq_1hz, pxa_rtc_irq, 0,
"rtc 1Hz", dev);
if (ret < 0) {
- dev_err(dev, "can't get irq %i, err %d\n", pxa_rtc->irq_1Hz,
- ret);
+ dev_err(dev, "can't get irq %i, err %d\n",
+ pxa_rtc->sa1100_rtc.irq_1hz, ret);
goto err_irq_1Hz;
}
- ret = request_irq(pxa_rtc->irq_Alrm, pxa_rtc_irq, 0,
+ ret = request_irq(pxa_rtc->sa1100_rtc.irq_alarm, pxa_rtc_irq, 0,
"rtc Alrm", dev);
if (ret < 0) {
- dev_err(dev, "can't get irq %i, err %d\n", pxa_rtc->irq_Alrm,
- ret);
+ dev_err(dev, "can't get irq %i, err %d\n",
+ pxa_rtc->sa1100_rtc.irq_alarm, ret);
goto err_irq_Alrm;
}
return 0;
err_irq_Alrm:
- free_irq(pxa_rtc->irq_1Hz, dev);
+ free_irq(pxa_rtc->sa1100_rtc.irq_1hz, dev);
err_irq_1Hz:
return ret;
}
@@ -215,8 +216,8 @@ static void pxa_rtc_release(struct device *dev)
rtsr_clear_bits(pxa_rtc, RTSR_PIALE | RTSR_RDALE1 | RTSR_HZE);
spin_unlock_irq(&pxa_rtc->lock);
- free_irq(pxa_rtc->irq_Alrm, dev);
- free_irq(pxa_rtc->irq_1Hz, dev);
+ free_irq(pxa_rtc->sa1100_rtc.irq_1hz, dev);
+ free_irq(pxa_rtc->sa1100_rtc.irq_alarm, dev);
}
static int pxa_alarm_irq_enable(struct device *dev, unsigned int enabled)
@@ -320,12 +321,13 @@ static int __init pxa_rtc_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct pxa_rtc *pxa_rtc;
+ struct sa1100_rtc *sa1100_rtc;
int ret;
- u32 rttr;
pxa_rtc = devm_kzalloc(dev, sizeof(*pxa_rtc), GFP_KERNEL);
if (!pxa_rtc)
return -ENOMEM;
+ sa1100_rtc = &pxa_rtc->sa1100_rtc;
spin_lock_init(&pxa_rtc->lock);
platform_set_drvdata(pdev, pxa_rtc);
@@ -336,13 +338,13 @@ static int __init pxa_rtc_probe(struct platform_device *pdev)
return -ENXIO;
}
- pxa_rtc->irq_1Hz = platform_get_irq(pdev, 0);
- if (pxa_rtc->irq_1Hz < 0) {
+ sa1100_rtc->irq_1hz = platform_get_irq(pdev, 0);
+ if (sa1100_rtc->irq_1hz < 0) {
dev_err(dev, "No 1Hz IRQ resource defined\n");
return -ENXIO;
}
- pxa_rtc->irq_Alrm = platform_get_irq(pdev, 1);
- if (pxa_rtc->irq_Alrm < 0) {
+ sa1100_rtc->irq_alarm = platform_get_irq(pdev, 1);
+ if (sa1100_rtc->irq_alarm < 0) {
dev_err(dev, "No alarm IRQ resource defined\n");
return -ENXIO;
}
@@ -354,15 +356,14 @@ static int __init pxa_rtc_probe(struct platform_device *pdev)
return -ENOMEM;
}
- /*
- * If the clock divider is uninitialized then reset it to the
- * default value to get the 1Hz clock.
- */
- if (rtc_readl(pxa_rtc, RTTR) == 0) {
- rttr = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16);
- rtc_writel(pxa_rtc, RTTR, rttr);
- dev_warn(dev, "warning: initializing default clock"
- " divider/trim value\n");
+ sa1100_rtc->rcnr = pxa_rtc->base + 0x0;
+ sa1100_rtc->rtsr = pxa_rtc->base + 0x8;
+ sa1100_rtc->rtar = pxa_rtc->base + 0x4;
+ sa1100_rtc->rttr = pxa_rtc->base + 0xc;
+ ret = sa1100_rtc_init(pdev, sa1100_rtc);
+ if (!ret) {
+ dev_err(dev, "Unable to init SA1100 RTC sub-device\n");
+ return ret;
}
rtsr_clear_bits(pxa_rtc, RTSR_PIALE | RTSR_RDALE1 | RTSR_HZE);
@@ -402,7 +403,7 @@ static int pxa_rtc_suspend(struct device *dev)
struct pxa_rtc *pxa_rtc = dev_get_drvdata(dev);
if (device_may_wakeup(dev))
- enable_irq_wake(pxa_rtc->irq_Alrm);
+ enable_irq_wake(pxa_rtc->sa1100_rtc.irq_alarm);
return 0;
}
@@ -411,7 +412,7 @@ static int pxa_rtc_resume(struct device *dev)
struct pxa_rtc *pxa_rtc = dev_get_drvdata(dev);
if (device_may_wakeup(dev))
- disable_irq_wake(pxa_rtc->irq_Alrm);
+ disable_irq_wake(pxa_rtc->sa1100_rtc.irq_alarm);
return 0;
}
#endif
diff --git a/drivers/rtc/rtc-rp5c01.c b/drivers/rtc/rtc-rp5c01.c
index b548551f3..026035373 100644
--- a/drivers/rtc/rtc-rp5c01.c
+++ b/drivers/rtc/rtc-rp5c01.c
@@ -170,7 +170,7 @@ static ssize_t rp5c01_nvram_read(struct file *filp, struct kobject *kobj,
spin_lock_irq(&priv->lock);
- for (count = 0; size > 0 && pos < RP5C01_MODE; count++, size--) {
+ for (count = 0; count < size; count++) {
u8 data;
rp5c01_write(priv,
@@ -200,7 +200,7 @@ static ssize_t rp5c01_nvram_write(struct file *filp, struct kobject *kobj,
spin_lock_irq(&priv->lock);
- for (count = 0; size > 0 && pos < RP5C01_MODE; count++, size--) {
+ for (count = 0; count < size; count++) {
u8 data = *buf++;
rp5c01_write(priv,
diff --git a/drivers/rtc/rtc-rx8025.c b/drivers/rtc/rtc-rx8025.c
index e6298e02b..24c3d69ce 100644
--- a/drivers/rtc/rtc-rx8025.c
+++ b/drivers/rtc/rtc-rx8025.c
@@ -18,13 +18,11 @@
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*/
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/init.h>
#include <linux/bcd.h>
+#include <linux/bitops.h>
#include <linux/i2c.h>
-#include <linux/list.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/rtc.h>
/* Register definitions */
@@ -48,17 +46,17 @@
#define RX8025_BIT_CTRL1_CT (7 << 0)
/* 1 Hz periodic level irq */
#define RX8025_BIT_CTRL1_CT_1HZ 4
-#define RX8025_BIT_CTRL1_TEST (1 << 3)
-#define RX8025_BIT_CTRL1_1224 (1 << 5)
-#define RX8025_BIT_CTRL1_DALE (1 << 6)
-#define RX8025_BIT_CTRL1_WALE (1 << 7)
-
-#define RX8025_BIT_CTRL2_DAFG (1 << 0)
-#define RX8025_BIT_CTRL2_WAFG (1 << 1)
-#define RX8025_BIT_CTRL2_CTFG (1 << 2)
-#define RX8025_BIT_CTRL2_PON (1 << 4)
-#define RX8025_BIT_CTRL2_XST (1 << 5)
-#define RX8025_BIT_CTRL2_VDET (1 << 6)
+#define RX8025_BIT_CTRL1_TEST BIT(3)
+#define RX8025_BIT_CTRL1_1224 BIT(5)
+#define RX8025_BIT_CTRL1_DALE BIT(6)
+#define RX8025_BIT_CTRL1_WALE BIT(7)
+
+#define RX8025_BIT_CTRL2_DAFG BIT(0)
+#define RX8025_BIT_CTRL2_WAFG BIT(1)
+#define RX8025_BIT_CTRL2_CTFG BIT(2)
+#define RX8025_BIT_CTRL2_PON BIT(4)
+#define RX8025_BIT_CTRL2_XST BIT(5)
+#define RX8025_BIT_CTRL2_VDET BIT(6)
/* Clock precision adjustment */
#define RX8025_ADJ_RESOLUTION 3050 /* in ppb */
@@ -74,84 +72,84 @@ MODULE_DEVICE_TABLE(i2c, rx8025_id);
struct rx8025_data {
struct i2c_client *client;
struct rtc_device *rtc;
- struct work_struct work;
u8 ctrl1;
- unsigned exiting:1;
};
-static int rx8025_read_reg(struct i2c_client *client, int number, u8 *value)
+static s32 rx8025_read_reg(const struct i2c_client *client, u8 number)
{
- int ret = i2c_smbus_read_byte_data(client, (number << 4) | 0x08);
-
- if (ret < 0) {
- dev_err(&client->dev, "Unable to read register #%d\n", number);
- return ret;
- }
-
- *value = ret;
- return 0;
+ return i2c_smbus_read_byte_data(client, number << 4);
}
-static int rx8025_read_regs(struct i2c_client *client,
- int number, u8 length, u8 *values)
+static int rx8025_read_regs(const struct i2c_client *client,
+ u8 number, u8 length, u8 *values)
{
- int ret = i2c_smbus_read_i2c_block_data(client, (number << 4) | 0x08,
- length, values);
-
- if (ret != length) {
- dev_err(&client->dev, "Unable to read registers #%d..#%d\n",
- number, number + length - 1);
+ int ret = i2c_smbus_read_i2c_block_data(client, number << 4, length,
+ values);
+ if (ret != length)
return ret < 0 ? ret : -EIO;
- }
return 0;
}
-static int rx8025_write_reg(struct i2c_client *client, int number, u8 value)
+static s32 rx8025_write_reg(const struct i2c_client *client, u8 number,
+ u8 value)
{
- int ret = i2c_smbus_write_byte_data(client, number << 4, value);
-
- if (ret)
- dev_err(&client->dev, "Unable to write register #%d\n",
- number);
+ return i2c_smbus_write_byte_data(client, number << 4, value);
+}
- return ret;
+static s32 rx8025_write_regs(const struct i2c_client *client,
+ u8 number, u8 length, const u8 *values)
+{
+ return i2c_smbus_write_i2c_block_data(client, number << 4,
+ length, values);
}
-static int rx8025_write_regs(struct i2c_client *client,
- int number, u8 length, u8 *values)
+static int rx8025_check_validity(struct device *dev)
{
- int ret = i2c_smbus_write_i2c_block_data(client, (number << 4) | 0x08,
- length, values);
+ struct rx8025_data *rx8025 = dev_get_drvdata(dev);
+ int ctrl2;
+
+ ctrl2 = rx8025_read_reg(rx8025->client, RX8025_REG_CTRL2);
+ if (ctrl2 < 0)
+ return ctrl2;
+
+ if (ctrl2 & RX8025_BIT_CTRL2_VDET)
+ dev_warn(dev, "power voltage drop detected\n");
+
+ if (ctrl2 & RX8025_BIT_CTRL2_PON) {
+ dev_warn(dev, "power-on reset detected, date is invalid\n");
+ return -EINVAL;
+ }
- if (ret)
- dev_err(&client->dev, "Unable to write registers #%d..#%d\n",
- number, number + length - 1);
+ if (!(ctrl2 & RX8025_BIT_CTRL2_XST)) {
+ dev_warn(dev, "crystal stopped, date is invalid\n");
+ return -EINVAL;
+ }
- return ret;
+ return 0;
}
-static irqreturn_t rx8025_irq(int irq, void *dev_id)
+static int rx8025_reset_validity(struct i2c_client *client)
{
- struct i2c_client *client = dev_id;
- struct rx8025_data *rx8025 = i2c_get_clientdata(client);
+ int ctrl2 = rx8025_read_reg(client, RX8025_REG_CTRL2);
- disable_irq_nosync(irq);
- schedule_work(&rx8025->work);
- return IRQ_HANDLED;
+ if (ctrl2 < 0)
+ return ctrl2;
+
+ ctrl2 &= ~(RX8025_BIT_CTRL2_PON | RX8025_BIT_CTRL2_VDET);
+
+ return rx8025_write_reg(client, RX8025_REG_CTRL2,
+ ctrl2 | RX8025_BIT_CTRL2_XST);
}
-static void rx8025_work(struct work_struct *work)
+static irqreturn_t rx8025_handle_irq(int irq, void *dev_id)
{
- struct rx8025_data *rx8025 = container_of(work, struct rx8025_data,
- work);
- struct i2c_client *client = rx8025->client;
- struct mutex *lock = &rx8025->rtc->ops_lock;
- u8 status;
-
- mutex_lock(lock);
+ struct i2c_client *client = dev_id;
+ struct rx8025_data *rx8025 = i2c_get_clientdata(client);
+ int status;
- if (rx8025_read_reg(client, RX8025_REG_CTRL2, &status))
+ status = rx8025_read_reg(client, RX8025_REG_CTRL2);
+ if (status < 0)
goto out;
if (!(status & RX8025_BIT_CTRL2_XST))
@@ -161,9 +159,7 @@ static void rx8025_work(struct work_struct *work)
if (status & RX8025_BIT_CTRL2_CTFG) {
/* periodic */
status &= ~RX8025_BIT_CTRL2_CTFG;
- local_irq_disable();
rtc_update_irq(rx8025->rtc, 1, RTC_PF | RTC_IRQF);
- local_irq_enable();
}
if (status & RX8025_BIT_CTRL2_DAFG) {
@@ -172,20 +168,11 @@ static void rx8025_work(struct work_struct *work)
if (rx8025_write_reg(client, RX8025_REG_CTRL1,
rx8025->ctrl1 & ~RX8025_BIT_CTRL1_DALE))
goto out;
- local_irq_disable();
rtc_update_irq(rx8025->rtc, 1, RTC_AF | RTC_IRQF);
- local_irq_enable();
}
- /* acknowledge IRQ */
- rx8025_write_reg(client, RX8025_REG_CTRL2,
- status | RX8025_BIT_CTRL2_XST);
-
out:
- if (!rx8025->exiting)
- enable_irq(client->irq);
-
- mutex_unlock(lock);
+ return IRQ_HANDLED;
}
static int rx8025_get_time(struct device *dev, struct rtc_time *dt)
@@ -194,6 +181,10 @@ static int rx8025_get_time(struct device *dev, struct rtc_time *dt)
u8 date[7];
int err;
+ err = rx8025_check_validity(dev);
+ if (err)
+ return err;
+
err = rx8025_read_regs(rx8025->client, RX8025_REG_SEC, 7, date);
if (err)
return err;
@@ -213,10 +204,7 @@ static int rx8025_get_time(struct device *dev, struct rtc_time *dt)
dt->tm_mday = bcd2bin(date[RX8025_REG_MDAY] & 0x3f);
dt->tm_mon = bcd2bin(date[RX8025_REG_MONTH] & 0x1f) - 1;
- dt->tm_year = bcd2bin(date[RX8025_REG_YEAR]);
-
- if (dt->tm_year < 70)
- dt->tm_year += 100;
+ dt->tm_year = bcd2bin(date[RX8025_REG_YEAR]) + 100;
dev_dbg(dev, "%s: date %ds %dm %dh %dmd %dm %dy\n", __func__,
dt->tm_sec, dt->tm_min, dt->tm_hour,
@@ -229,12 +217,10 @@ static int rx8025_set_time(struct device *dev, struct rtc_time *dt)
{
struct rx8025_data *rx8025 = dev_get_drvdata(dev);
u8 date[7];
+ int ret;
- /*
- * BUG: The HW assumes every year that is a multiple of 4 to be a leap
- * year. Next time this is wrong is 2100, which will not be a leap
- * year.
- */
+ if ((dt->tm_year < 100) || (dt->tm_year > 199))
+ return -EINVAL;
/*
* Here the read-only bits are written as "0". I'm not sure if that
@@ -251,17 +237,21 @@ static int rx8025_set_time(struct device *dev, struct rtc_time *dt)
date[RX8025_REG_WDAY] = bin2bcd(dt->tm_wday);
date[RX8025_REG_MDAY] = bin2bcd(dt->tm_mday);
date[RX8025_REG_MONTH] = bin2bcd(dt->tm_mon + 1);
- date[RX8025_REG_YEAR] = bin2bcd(dt->tm_year % 100);
+ date[RX8025_REG_YEAR] = bin2bcd(dt->tm_year - 100);
dev_dbg(dev,
"%s: write 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
__func__,
date[0], date[1], date[2], date[3], date[4], date[5], date[6]);
- return rx8025_write_regs(rx8025->client, RX8025_REG_SEC, 7, date);
+ ret = rx8025_write_regs(rx8025->client, RX8025_REG_SEC, 7, date);
+ if (ret < 0)
+ return ret;
+
+ return rx8025_reset_validity(rx8025->client);
}
-static int rx8025_init_client(struct i2c_client *client, int *need_reset)
+static int rx8025_init_client(struct i2c_client *client)
{
struct rx8025_data *rx8025 = i2c_get_clientdata(client);
u8 ctrl[2], ctrl2;
@@ -275,38 +265,18 @@ static int rx8025_init_client(struct i2c_client *client, int *need_reset)
/* Keep test bit zero ! */
rx8025->ctrl1 = ctrl[0] & ~RX8025_BIT_CTRL1_TEST;
- if (ctrl[1] & RX8025_BIT_CTRL2_PON) {
- dev_warn(&client->dev, "power-on reset was detected, "
- "you may have to readjust the clock\n");
- *need_reset = 1;
- }
-
- if (ctrl[1] & RX8025_BIT_CTRL2_VDET) {
- dev_warn(&client->dev, "a power voltage drop was detected, "
- "you may have to readjust the clock\n");
- *need_reset = 1;
- }
-
- if (!(ctrl[1] & RX8025_BIT_CTRL2_XST)) {
- dev_warn(&client->dev, "Oscillation stop was detected,"
- "you may have to readjust the clock\n");
- *need_reset = 1;
- }
-
if (ctrl[1] & (RX8025_BIT_CTRL2_DAFG | RX8025_BIT_CTRL2_WAFG)) {
dev_warn(&client->dev, "Alarm was detected\n");
need_clear = 1;
}
- if (!(ctrl[1] & RX8025_BIT_CTRL2_CTFG))
+ if (ctrl[1] & RX8025_BIT_CTRL2_CTFG)
need_clear = 1;
- if (*need_reset || need_clear) {
- ctrl2 = ctrl[0];
- ctrl2 &= ~(RX8025_BIT_CTRL2_PON | RX8025_BIT_CTRL2_VDET |
- RX8025_BIT_CTRL2_CTFG | RX8025_BIT_CTRL2_WAFG |
+ if (need_clear) {
+ ctrl2 = ctrl[1];
+ ctrl2 &= ~(RX8025_BIT_CTRL2_CTFG | RX8025_BIT_CTRL2_WAFG |
RX8025_BIT_CTRL2_DAFG);
- ctrl2 |= RX8025_BIT_CTRL2_XST;
err = rx8025_write_reg(client, RX8025_REG_CTRL2, ctrl2);
}
@@ -319,8 +289,8 @@ static int rx8025_read_alarm(struct device *dev, struct rtc_wkalrm *t)
{
struct rx8025_data *rx8025 = dev_get_drvdata(dev);
struct i2c_client *client = rx8025->client;
- u8 ctrl2, ald[2];
- int err;
+ u8 ald[2];
+ int ctrl2, err;
if (client->irq <= 0)
return -EINVAL;
@@ -329,9 +299,9 @@ static int rx8025_read_alarm(struct device *dev, struct rtc_wkalrm *t)
if (err)
return err;
- err = rx8025_read_reg(client, RX8025_REG_CTRL2, &ctrl2);
- if (err)
- return err;
+ ctrl2 = rx8025_read_reg(client, RX8025_REG_CTRL2);
+ if (ctrl2 < 0)
+ return ctrl2;
dev_dbg(dev, "%s: read alarm 0x%02x 0x%02x ctrl2 %02x\n",
__func__, ald[0], ald[1], ctrl2);
@@ -452,12 +422,11 @@ static struct rtc_class_ops rx8025_rtc_ops = {
static int rx8025_get_clock_adjust(struct device *dev, int *adj)
{
struct i2c_client *client = to_i2c_client(dev);
- u8 digoff;
- int err;
+ int digoff;
- err = rx8025_read_reg(client, RX8025_REG_DIGOFF, &digoff);
- if (err)
- return err;
+ digoff = rx8025_read_reg(client, RX8025_REG_DIGOFF);
+ if (digoff < 0)
+ return digoff;
*adj = digoff >= 64 ? digoff - 128 : digoff;
if (*adj > 0)
@@ -539,88 +508,53 @@ static int rx8025_probe(struct i2c_client *client,
{
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
struct rx8025_data *rx8025;
- int err, need_reset = 0;
+ int err = 0;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA
| I2C_FUNC_SMBUS_I2C_BLOCK)) {
dev_err(&adapter->dev,
"doesn't support required functionality\n");
- err = -EIO;
- goto errout;
+ return -EIO;
}
rx8025 = devm_kzalloc(&client->dev, sizeof(*rx8025), GFP_KERNEL);
if (!rx8025) {
- err = -ENOMEM;
- goto errout;
+ return -ENOMEM;
}
rx8025->client = client;
i2c_set_clientdata(client, rx8025);
- INIT_WORK(&rx8025->work, rx8025_work);
- err = rx8025_init_client(client, &need_reset);
+ err = rx8025_init_client(client);
if (err)
- goto errout;
-
- if (need_reset) {
- struct rtc_time tm;
- dev_info(&client->dev,
- "bad conditions detected, resetting date\n");
- rtc_time_to_tm(0, &tm); /* 1970/1/1 */
- rx8025_set_time(&client->dev, &tm);
- }
+ return err;
rx8025->rtc = devm_rtc_device_register(&client->dev, client->name,
&rx8025_rtc_ops, THIS_MODULE);
if (IS_ERR(rx8025->rtc)) {
- err = PTR_ERR(rx8025->rtc);
dev_err(&client->dev, "unable to register the class device\n");
- goto errout;
+ return PTR_ERR(rx8025->rtc);
}
if (client->irq > 0) {
dev_info(&client->dev, "IRQ %d supplied\n", client->irq);
- err = request_irq(client->irq, rx8025_irq,
- 0, "rx8025", client);
+ err = devm_request_threaded_irq(&client->dev, client->irq, NULL,
+ rx8025_handle_irq, 0, "rx8025",
+ client);
if (err) {
- dev_err(&client->dev, "unable to request IRQ\n");
- goto errout;
+ dev_err(&client->dev, "unable to request IRQ, alarms disabled\n");
+ client->irq = 0;
}
}
- rx8025->rtc->irq_freq = 1;
rx8025->rtc->max_user_freq = 1;
err = rx8025_sysfs_register(&client->dev);
- if (err)
- goto errout_irq;
-
- return 0;
-
-errout_irq:
- if (client->irq > 0)
- free_irq(client->irq, client);
-
-errout:
- dev_err(&adapter->dev, "probing for rx8025 failed\n");
return err;
}
static int rx8025_remove(struct i2c_client *client)
{
- struct rx8025_data *rx8025 = i2c_get_clientdata(client);
- struct mutex *lock = &rx8025->rtc->ops_lock;
-
- if (client->irq > 0) {
- mutex_lock(lock);
- rx8025->exiting = 1;
- mutex_unlock(lock);
-
- free_irq(client->irq, client);
- cancel_work_sync(&rx8025->work);
- }
-
rx8025_sysfs_unregister(&client->dev);
return 0;
}
@@ -628,7 +562,6 @@ static int rx8025_remove(struct i2c_client *client)
static struct i2c_driver rx8025_driver = {
.driver = {
.name = "rtc-rx8025",
- .owner = THIS_MODULE,
},
.probe = rx8025_probe,
.remove = rx8025_remove,
diff --git a/drivers/rtc/rtc-rx8581.c b/drivers/rtc/rtc-rx8581.c
index de8d9c427..161e25d01 100644
--- a/drivers/rtc/rtc-rx8581.c
+++ b/drivers/rtc/rtc-rx8581.c
@@ -315,7 +315,6 @@ MODULE_DEVICE_TABLE(i2c, rx8581_id);
static struct i2c_driver rx8581_driver = {
.driver = {
.name = "rtc-rx8581",
- .owner = THIS_MODULE,
},
.probe = rx8581_probe,
.id_table = rx8581_id,
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c
index 2e709e239..7cc8f73a3 100644
--- a/drivers/rtc/rtc-s3c.c
+++ b/drivers/rtc/rtc-s3c.c
@@ -422,8 +422,9 @@ static int s3c_rtc_remove(struct platform_device *pdev)
s3c_rtc_setaie(info->dev, 0);
+ if (info->data->needs_src_clk)
+ clk_unprepare(info->rtc_src_clk);
clk_unprepare(info->rtc_clk);
- info->rtc_clk = NULL;
return 0;
}
@@ -494,6 +495,7 @@ static int s3c_rtc_probe(struct platform_device *pdev)
if (IS_ERR(info->rtc_src_clk)) {
dev_err(&pdev->dev,
"failed to find rtc source clock\n");
+ clk_disable_unprepare(info->rtc_clk);
return PTR_ERR(info->rtc_src_clk);
}
clk_prepare_enable(info->rtc_src_clk);
diff --git a/drivers/rtc/rtc-s5m.c b/drivers/rtc/rtc-s5m.c
index ab60287ee..f2504b4ee 100644
--- a/drivers/rtc/rtc-s5m.c
+++ b/drivers/rtc/rtc-s5m.c
@@ -807,6 +807,7 @@ static const struct platform_device_id s5m_rtc_id[] = {
{ "s2mps14-rtc", S2MPS14X },
{ },
};
+MODULE_DEVICE_TABLE(platform, s5m_rtc_id);
static struct platform_driver s5m_rtc_driver = {
.driver = {
diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c
index b6e1ca08c..c2187bf6c 100644
--- a/drivers/rtc/rtc-sa1100.c
+++ b/drivers/rtc/rtc-sa1100.c
@@ -35,24 +35,17 @@
#include <linux/bitops.h>
#include <linux/io.h>
-#include <mach/hardware.h>
-#include <mach/irqs.h>
+#define RTSR_HZE BIT(3) /* HZ interrupt enable */
+#define RTSR_ALE BIT(2) /* RTC alarm interrupt enable */
+#define RTSR_HZ BIT(1) /* HZ rising-edge detected */
+#define RTSR_AL BIT(0) /* RTC alarm detected */
-#if defined(CONFIG_ARCH_PXA) || defined(CONFIG_ARCH_MMP)
-#include <mach/regs-rtc.h>
-#endif
+#include "rtc-sa1100.h"
#define RTC_DEF_DIVIDER (32768 - 1)
#define RTC_DEF_TRIM 0
#define RTC_FREQ 1024
-struct sa1100_rtc {
- spinlock_t lock;
- int irq_1hz;
- int irq_alarm;
- struct rtc_device *rtc;
- struct clk *clk;
-};
static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id)
{
@@ -63,16 +56,16 @@ static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id)
spin_lock(&info->lock);
- rtsr = RTSR;
+ rtsr = readl_relaxed(info->rtsr);
/* clear interrupt sources */
- RTSR = 0;
+ writel_relaxed(0, info->rtsr);
/* Fix for a nasty initialization problem the in SA11xx RTSR register.
* See also the comments in sa1100_rtc_probe(). */
if (rtsr & (RTSR_ALE | RTSR_HZE)) {
/* This is the original code, before there was the if test
* above. This code does not clear interrupts that were not
* enabled. */
- RTSR = (RTSR_AL | RTSR_HZ) & (rtsr >> 2);
+ writel_relaxed((RTSR_AL | RTSR_HZ) & (rtsr >> 2), info->rtsr);
} else {
/* For some reason, it is possible to enter this routine
* without interruptions enabled, it has been tested with
@@ -81,13 +74,13 @@ static irqreturn_t sa1100_rtc_interrupt(int irq, void *dev_id)
* This situation leads to an infinite "loop" of interrupt
* routine calling and as a result the processor seems to
* lock on its first call to open(). */
- RTSR = RTSR_AL | RTSR_HZ;
+ writel_relaxed(RTSR_AL | RTSR_HZ, info->rtsr);
}
/* clear alarm interrupt if it has occurred */
if (rtsr & RTSR_AL)
rtsr &= ~RTSR_ALE;
- RTSR = rtsr & (RTSR_ALE | RTSR_HZE);
+ writel_relaxed(rtsr & (RTSR_ALE | RTSR_HZE), info->rtsr);
/* update irq data & counter */
if (rtsr & RTSR_AL)
@@ -135,7 +128,7 @@ static void sa1100_rtc_release(struct device *dev)
struct sa1100_rtc *info = dev_get_drvdata(dev);
spin_lock_irq(&info->lock);
- RTSR = 0;
+ writel_relaxed(0, info->rtsr);
spin_unlock_irq(&info->lock);
free_irq(info->irq_alarm, dev);
@@ -144,39 +137,46 @@ static void sa1100_rtc_release(struct device *dev)
static int sa1100_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
{
+ u32 rtsr;
struct sa1100_rtc *info = dev_get_drvdata(dev);
spin_lock_irq(&info->lock);
+ rtsr = readl_relaxed(info->rtsr);
if (enabled)
- RTSR |= RTSR_ALE;
+ rtsr |= RTSR_ALE;
else
- RTSR &= ~RTSR_ALE;
+ rtsr &= ~RTSR_ALE;
+ writel_relaxed(rtsr, info->rtsr);
spin_unlock_irq(&info->lock);
return 0;
}
static int sa1100_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
- rtc_time_to_tm(RCNR, tm);
+ struct sa1100_rtc *info = dev_get_drvdata(dev);
+
+ rtc_time_to_tm(readl_relaxed(info->rcnr), tm);
return 0;
}
static int sa1100_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
+ struct sa1100_rtc *info = dev_get_drvdata(dev);
unsigned long time;
int ret;
ret = rtc_tm_to_time(tm, &time);
if (ret == 0)
- RCNR = time;
+ writel_relaxed(time, info->rcnr);
return ret;
}
static int sa1100_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
u32 rtsr;
+ struct sa1100_rtc *info = dev_get_drvdata(dev);
- rtsr = RTSR;
+ rtsr = readl_relaxed(info->rtsr);
alrm->enabled = (rtsr & RTSR_ALE) ? 1 : 0;
alrm->pending = (rtsr & RTSR_AL) ? 1 : 0;
return 0;
@@ -192,12 +192,13 @@ static int sa1100_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
ret = rtc_tm_to_time(&alrm->time, &time);
if (ret != 0)
goto out;
- RTSR = RTSR & (RTSR_HZE|RTSR_ALE|RTSR_AL);
- RTAR = time;
+ writel_relaxed(readl_relaxed(info->rtsr) &
+ (RTSR_HZE | RTSR_ALE | RTSR_AL), info->rtsr);
+ writel_relaxed(time, info->rtar);
if (alrm->enabled)
- RTSR |= RTSR_ALE;
+ writel_relaxed(readl_relaxed(info->rtsr) | RTSR_ALE, info->rtsr);
else
- RTSR &= ~RTSR_ALE;
+ writel_relaxed(readl_relaxed(info->rtsr) & ~RTSR_ALE, info->rtsr);
out:
spin_unlock_irq(&info->lock);
@@ -206,8 +207,10 @@ out:
static int sa1100_rtc_proc(struct device *dev, struct seq_file *seq)
{
- seq_printf(seq, "trim/divider\t\t: 0x%08x\n", (u32) RTTR);
- seq_printf(seq, "RTSR\t\t\t: 0x%08x\n", (u32)RTSR);
+ struct sa1100_rtc *info = dev_get_drvdata(dev);
+
+ seq_printf(seq, "trim/divider\t\t: 0x%08x\n", readl_relaxed(info->rttr));
+ seq_printf(seq, "RTSR\t\t\t: 0x%08x\n", readl_relaxed(info->rtsr));
return 0;
}
@@ -223,29 +226,18 @@ static const struct rtc_class_ops sa1100_rtc_ops = {
.alarm_irq_enable = sa1100_rtc_alarm_irq_enable,
};
-static int sa1100_rtc_probe(struct platform_device *pdev)
+int sa1100_rtc_init(struct platform_device *pdev, struct sa1100_rtc *info)
{
struct rtc_device *rtc;
- struct sa1100_rtc *info;
- int irq_1hz, irq_alarm, ret = 0;
+ int ret;
- irq_1hz = platform_get_irq_byname(pdev, "rtc 1Hz");
- irq_alarm = platform_get_irq_byname(pdev, "rtc alarm");
- if (irq_1hz < 0 || irq_alarm < 0)
- return -ENODEV;
+ spin_lock_init(&info->lock);
- info = devm_kzalloc(&pdev->dev, sizeof(struct sa1100_rtc), GFP_KERNEL);
- if (!info)
- return -ENOMEM;
info->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(info->clk)) {
dev_err(&pdev->dev, "failed to find rtc clock source\n");
return PTR_ERR(info->clk);
}
- info->irq_1hz = irq_1hz;
- info->irq_alarm = irq_alarm;
- spin_lock_init(&info->lock);
- platform_set_drvdata(pdev, info);
ret = clk_prepare_enable(info->clk);
if (ret)
@@ -257,22 +249,19 @@ static int sa1100_rtc_probe(struct platform_device *pdev)
* If the clock divider is uninitialized then reset it to the
* default value to get the 1Hz clock.
*/
- if (RTTR == 0) {
- RTTR = RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16);
+ if (readl_relaxed(info->rttr) == 0) {
+ writel_relaxed(RTC_DEF_DIVIDER + (RTC_DEF_TRIM << 16), info->rttr);
dev_warn(&pdev->dev, "warning: "
"initializing default clock divider/trim value\n");
/* The current RTC value probably doesn't make sense either */
- RCNR = 0;
+ writel_relaxed(0, info->rcnr);
}
- device_init_wakeup(&pdev->dev, 1);
-
rtc = devm_rtc_device_register(&pdev->dev, pdev->name, &sa1100_rtc_ops,
THIS_MODULE);
-
if (IS_ERR(rtc)) {
- ret = PTR_ERR(rtc);
- goto err_dev;
+ clk_disable_unprepare(info->clk);
+ return PTR_ERR(rtc);
}
info->rtc = rtc;
@@ -298,12 +287,52 @@ static int sa1100_rtc_probe(struct platform_device *pdev)
*
* Notice that clearing bit 1 and 0 is accomplished by writting ONES to
* the corresponding bits in RTSR. */
- RTSR = RTSR_AL | RTSR_HZ;
+ writel_relaxed(RTSR_AL | RTSR_HZ, info->rtsr);
return 0;
-err_dev:
- clk_disable_unprepare(info->clk);
- return ret;
+}
+EXPORT_SYMBOL_GPL(sa1100_rtc_init);
+
+static int sa1100_rtc_probe(struct platform_device *pdev)
+{
+ struct sa1100_rtc *info;
+ struct resource *iores;
+ void __iomem *base;
+ int irq_1hz, irq_alarm;
+
+ irq_1hz = platform_get_irq_byname(pdev, "rtc 1Hz");
+ irq_alarm = platform_get_irq_byname(pdev, "rtc alarm");
+ if (irq_1hz < 0 || irq_alarm < 0)
+ return -ENODEV;
+
+ info = devm_kzalloc(&pdev->dev, sizeof(struct sa1100_rtc), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+ info->irq_1hz = irq_1hz;
+ info->irq_alarm = irq_alarm;
+
+ iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ base = devm_ioremap_resource(&pdev->dev, iores);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ if (IS_ENABLED(CONFIG_ARCH_SA1100) ||
+ of_device_is_compatible(pdev->dev.of_node, "mrvl,sa1100-rtc")) {
+ info->rcnr = base + 0x04;
+ info->rtsr = base + 0x10;
+ info->rtar = base + 0x00;
+ info->rttr = base + 0x08;
+ } else {
+ info->rcnr = base + 0x0;
+ info->rtsr = base + 0x8;
+ info->rtar = base + 0x4;
+ info->rttr = base + 0xc;
+ }
+
+ platform_set_drvdata(pdev, info);
+ device_init_wakeup(&pdev->dev, 1);
+
+ return sa1100_rtc_init(pdev, info);
}
static int sa1100_rtc_remove(struct platform_device *pdev)
diff --git a/drivers/rtc/rtc-sa1100.h b/drivers/rtc/rtc-sa1100.h
new file mode 100644
index 000000000..2c79c0c57
--- /dev/null
+++ b/drivers/rtc/rtc-sa1100.h
@@ -0,0 +1,23 @@
+#ifndef __RTC_SA1100_H__
+#define __RTC_SA1100_H__
+
+#include <linux/kernel.h>
+
+struct clk;
+struct platform_device;
+
+struct sa1100_rtc {
+ spinlock_t lock;
+ void __iomem *rcnr;
+ void __iomem *rtar;
+ void __iomem *rtsr;
+ void __iomem *rttr;
+ int irq_1hz;
+ int irq_alarm;
+ struct rtc_device *rtc;
+ struct clk *clk;
+};
+
+int sa1100_rtc_init(struct platform_device *pdev, struct sa1100_rtc *info);
+
+#endif
diff --git a/drivers/rtc/rtc-sirfsoc.c b/drivers/rtc/rtc-sirfsoc.c
index edc3b4328..7367f6171 100644
--- a/drivers/rtc/rtc-sirfsoc.c
+++ b/drivers/rtc/rtc-sirfsoc.c
@@ -13,6 +13,7 @@
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/of.h>
+#include <linux/regmap.h>
#include <linux/rtc/sirfsoc_rtciobrg.h>
@@ -48,12 +49,27 @@ struct sirfsoc_rtc_drv {
/* Overflow for every 8 years extra time */
u32 overflow_rtc;
spinlock_t lock;
+ struct regmap *regmap;
#ifdef CONFIG_PM
u32 saved_counter;
u32 saved_overflow_rtc;
#endif
};
+static u32 sirfsoc_rtc_readl(struct sirfsoc_rtc_drv *rtcdrv, u32 offset)
+{
+ u32 val;
+
+ regmap_read(rtcdrv->regmap, rtcdrv->rtc_base + offset, &val);
+ return val;
+}
+
+static void sirfsoc_rtc_writel(struct sirfsoc_rtc_drv *rtcdrv,
+ u32 offset, u32 val)
+{
+ regmap_write(rtcdrv->regmap, rtcdrv->rtc_base + offset, val);
+}
+
static int sirfsoc_rtc_read_alarm(struct device *dev,
struct rtc_wkalrm *alrm)
{
@@ -64,9 +80,9 @@ static int sirfsoc_rtc_read_alarm(struct device *dev,
spin_lock_irq(&rtcdrv->lock);
- rtc_count = sirfsoc_rtc_iobrg_readl(rtcdrv->rtc_base + RTC_CN);
+ rtc_count = sirfsoc_rtc_readl(rtcdrv, RTC_CN);
- rtc_alarm = sirfsoc_rtc_iobrg_readl(rtcdrv->rtc_base + RTC_ALARM0);
+ rtc_alarm = sirfsoc_rtc_readl(rtcdrv, RTC_ALARM0);
memset(alrm, 0, sizeof(struct rtc_wkalrm));
/*
@@ -82,8 +98,7 @@ static int sirfsoc_rtc_read_alarm(struct device *dev,
rtc_time_to_tm(rtcdrv->overflow_rtc
<< (BITS_PER_LONG - RTC_SHIFT)
| rtc_alarm >> RTC_SHIFT, &(alrm->time));
- if (sirfsoc_rtc_iobrg_readl(
- rtcdrv->rtc_base + RTC_STATUS) & SIRFSOC_RTC_AL0E)
+ if (sirfsoc_rtc_readl(rtcdrv, RTC_STATUS) & SIRFSOC_RTC_AL0E)
alrm->enabled = 1;
spin_unlock_irq(&rtcdrv->lock);
@@ -103,8 +118,7 @@ static int sirfsoc_rtc_set_alarm(struct device *dev,
spin_lock_irq(&rtcdrv->lock);
- rtc_status_reg = sirfsoc_rtc_iobrg_readl(
- rtcdrv->rtc_base + RTC_STATUS);
+ rtc_status_reg = sirfsoc_rtc_readl(rtcdrv, RTC_STATUS);
if (rtc_status_reg & SIRFSOC_RTC_AL0E) {
/*
* An ongoing alarm in progress - ingore it and not
@@ -113,8 +127,7 @@ static int sirfsoc_rtc_set_alarm(struct device *dev,
dev_info(dev, "An old alarm was set, will be replaced by a new one\n");
}
- sirfsoc_rtc_iobrg_writel(
- rtc_alarm << RTC_SHIFT, rtcdrv->rtc_base + RTC_ALARM0);
+ sirfsoc_rtc_writel(rtcdrv, RTC_ALARM0, rtc_alarm << RTC_SHIFT);
rtc_status_reg &= ~0x07; /* mask out the lower status bits */
/*
* This bit RTC_AL sets it as a wake-up source for Sleep Mode
@@ -123,8 +136,7 @@ static int sirfsoc_rtc_set_alarm(struct device *dev,
rtc_status_reg |= SIRFSOC_RTC_AL0;
/* enable the RTC alarm interrupt */
rtc_status_reg |= SIRFSOC_RTC_AL0E;
- sirfsoc_rtc_iobrg_writel(
- rtc_status_reg, rtcdrv->rtc_base + RTC_STATUS);
+ sirfsoc_rtc_writel(rtcdrv, RTC_STATUS, rtc_status_reg);
spin_unlock_irq(&rtcdrv->lock);
} else {
@@ -135,8 +147,7 @@ static int sirfsoc_rtc_set_alarm(struct device *dev,
*/
spin_lock_irq(&rtcdrv->lock);
- rtc_status_reg = sirfsoc_rtc_iobrg_readl(
- rtcdrv->rtc_base + RTC_STATUS);
+ rtc_status_reg = sirfsoc_rtc_readl(rtcdrv, RTC_STATUS);
if (rtc_status_reg & SIRFSOC_RTC_AL0E) {
/* clear the RTC status register's alarm bit */
rtc_status_reg &= ~0x07;
@@ -145,8 +156,8 @@ static int sirfsoc_rtc_set_alarm(struct device *dev,
/* Clear the Alarm enable bit */
rtc_status_reg &= ~(SIRFSOC_RTC_AL0E);
- sirfsoc_rtc_iobrg_writel(rtc_status_reg,
- rtcdrv->rtc_base + RTC_STATUS);
+ sirfsoc_rtc_writel(rtcdrv, RTC_STATUS,
+ rtc_status_reg);
}
spin_unlock_irq(&rtcdrv->lock);
@@ -167,9 +178,9 @@ static int sirfsoc_rtc_read_time(struct device *dev,
* fail, read several times to make sure get stable value.
*/
do {
- tmp_rtc = sirfsoc_rtc_iobrg_readl(rtcdrv->rtc_base + RTC_CN);
+ tmp_rtc = sirfsoc_rtc_readl(rtcdrv, RTC_CN);
cpu_relax();
- } while (tmp_rtc != sirfsoc_rtc_iobrg_readl(rtcdrv->rtc_base + RTC_CN));
+ } while (tmp_rtc != sirfsoc_rtc_readl(rtcdrv, RTC_CN));
rtc_time_to_tm(rtcdrv->overflow_rtc << (BITS_PER_LONG - RTC_SHIFT) |
tmp_rtc >> RTC_SHIFT, tm);
@@ -187,10 +198,8 @@ static int sirfsoc_rtc_set_time(struct device *dev,
rtcdrv->overflow_rtc = rtc_time >> (BITS_PER_LONG - RTC_SHIFT);
- sirfsoc_rtc_iobrg_writel(rtcdrv->overflow_rtc,
- rtcdrv->rtc_base + RTC_SW_VALUE);
- sirfsoc_rtc_iobrg_writel(
- rtc_time << RTC_SHIFT, rtcdrv->rtc_base + RTC_CN);
+ sirfsoc_rtc_writel(rtcdrv, RTC_SW_VALUE, rtcdrv->overflow_rtc);
+ sirfsoc_rtc_writel(rtcdrv, RTC_CN, rtc_time << RTC_SHIFT);
return 0;
}
@@ -222,14 +231,13 @@ static int sirfsoc_rtc_alarm_irq_enable(struct device *dev,
spin_lock_irq(&rtcdrv->lock);
- rtc_status_reg = sirfsoc_rtc_iobrg_readl(
- rtcdrv->rtc_base + RTC_STATUS);
+ rtc_status_reg = sirfsoc_rtc_readl(rtcdrv, RTC_STATUS);
if (enabled)
rtc_status_reg |= SIRFSOC_RTC_AL0E;
else
rtc_status_reg &= ~SIRFSOC_RTC_AL0E;
- sirfsoc_rtc_iobrg_writel(rtc_status_reg, rtcdrv->rtc_base + RTC_STATUS);
+ sirfsoc_rtc_writel(rtcdrv, RTC_STATUS, rtc_status_reg);
spin_unlock_irq(&rtcdrv->lock);
@@ -254,7 +262,7 @@ static irqreturn_t sirfsoc_rtc_irq_handler(int irq, void *pdata)
spin_lock(&rtcdrv->lock);
- rtc_status_reg = sirfsoc_rtc_iobrg_readl(rtcdrv->rtc_base + RTC_STATUS);
+ rtc_status_reg = sirfsoc_rtc_readl(rtcdrv, RTC_STATUS);
/* this bit will be set ONLY if an alarm was active
* and it expired NOW
* So this is being used as an ASSERT
@@ -270,7 +278,8 @@ static irqreturn_t sirfsoc_rtc_irq_handler(int irq, void *pdata)
/* Clear the Alarm enable bit */
rtc_status_reg &= ~(SIRFSOC_RTC_AL0E);
}
- sirfsoc_rtc_iobrg_writel(rtc_status_reg, rtcdrv->rtc_base + RTC_STATUS);
+
+ sirfsoc_rtc_writel(rtcdrv, RTC_STATUS, rtc_status_reg);
spin_unlock(&rtcdrv->lock);
@@ -287,6 +296,13 @@ static const struct of_device_id sirfsoc_rtc_of_match[] = {
{ .compatible = "sirf,prima2-sysrtc"},
{},
};
+
+const struct regmap_config sysrtc_regmap_config = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .fast_io = true,
+};
+
MODULE_DEVICE_TABLE(of, sirfsoc_rtc_of_match);
static int sirfsoc_rtc_probe(struct platform_device *pdev)
@@ -314,27 +330,35 @@ static int sirfsoc_rtc_probe(struct platform_device *pdev)
/* Register rtc alarm as a wakeup source */
device_init_wakeup(&pdev->dev, 1);
+ rtcdrv->regmap = devm_regmap_init_iobg(&pdev->dev,
+ &sysrtc_regmap_config);
+ if (IS_ERR(rtcdrv->regmap)) {
+ err = PTR_ERR(rtcdrv->regmap);
+ dev_err(&pdev->dev, "Failed to allocate register map: %d\n",
+ err);
+ return err;
+ }
+
/*
* Set SYS_RTC counter in RTC_HZ HZ Units
* We are using 32K RTC crystal (32768 / RTC_HZ / 2) -1
* If 16HZ, therefore RTC_DIV = 1023;
*/
rtc_div = ((32768 / RTC_HZ) / 2) - 1;
- sirfsoc_rtc_iobrg_writel(rtc_div, rtcdrv->rtc_base + RTC_DIV);
+ sirfsoc_rtc_writel(rtcdrv, RTC_DIV, rtc_div);
/* 0x3 -> RTC_CLK */
- sirfsoc_rtc_iobrg_writel(SIRFSOC_RTC_CLK,
- rtcdrv->rtc_base + RTC_CLOCK_SWITCH);
+ sirfsoc_rtc_writel(rtcdrv, RTC_CLOCK_SWITCH, SIRFSOC_RTC_CLK);
/* reset SYS RTC ALARM0 */
- sirfsoc_rtc_iobrg_writel(0x0, rtcdrv->rtc_base + RTC_ALARM0);
+ sirfsoc_rtc_writel(rtcdrv, RTC_ALARM0, 0x0);
/* reset SYS RTC ALARM1 */
- sirfsoc_rtc_iobrg_writel(0x0, rtcdrv->rtc_base + RTC_ALARM1);
+ sirfsoc_rtc_writel(rtcdrv, RTC_ALARM1, 0x0);
/* Restore RTC Overflow From Register After Command Reboot */
rtcdrv->overflow_rtc =
- sirfsoc_rtc_iobrg_readl(rtcdrv->rtc_base + RTC_SW_VALUE);
+ sirfsoc_rtc_readl(rtcdrv, RTC_SW_VALUE);
rtcdrv->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
&sirfsoc_rtc_ops, THIS_MODULE);
@@ -372,10 +396,10 @@ static int sirfsoc_rtc_suspend(struct device *dev)
{
struct sirfsoc_rtc_drv *rtcdrv = dev_get_drvdata(dev);
rtcdrv->overflow_rtc =
- sirfsoc_rtc_iobrg_readl(rtcdrv->rtc_base + RTC_SW_VALUE);
+ sirfsoc_rtc_readl(rtcdrv, RTC_SW_VALUE);
rtcdrv->saved_counter =
- sirfsoc_rtc_iobrg_readl(rtcdrv->rtc_base + RTC_CN);
+ sirfsoc_rtc_readl(rtcdrv, RTC_CN);
rtcdrv->saved_overflow_rtc = rtcdrv->overflow_rtc;
if (device_may_wakeup(dev) && !enable_irq_wake(rtcdrv->irq))
rtcdrv->irq_wake = 1;
@@ -392,12 +416,10 @@ static int sirfsoc_rtc_resume(struct device *dev)
* if resume from snapshot and the rtc power is lost,
* restroe the rtc settings
*/
- if (SIRFSOC_RTC_CLK != sirfsoc_rtc_iobrg_readl(
- rtcdrv->rtc_base + RTC_CLOCK_SWITCH)) {
+ if (SIRFSOC_RTC_CLK != sirfsoc_rtc_readl(rtcdrv, RTC_CLOCK_SWITCH)) {
u32 rtc_div;
/* 0x3 -> RTC_CLK */
- sirfsoc_rtc_iobrg_writel(SIRFSOC_RTC_CLK,
- rtcdrv->rtc_base + RTC_CLOCK_SWITCH);
+ sirfsoc_rtc_writel(rtcdrv, RTC_CLOCK_SWITCH, SIRFSOC_RTC_CLK);
/*
* Set SYS_RTC counter in RTC_HZ HZ Units
* We are using 32K RTC crystal (32768 / RTC_HZ / 2) -1
@@ -405,13 +427,13 @@ static int sirfsoc_rtc_resume(struct device *dev)
*/
rtc_div = ((32768 / RTC_HZ) / 2) - 1;
- sirfsoc_rtc_iobrg_writel(rtc_div, rtcdrv->rtc_base + RTC_DIV);
+ sirfsoc_rtc_writel(rtcdrv, RTC_DIV, rtc_div);
/* reset SYS RTC ALARM0 */
- sirfsoc_rtc_iobrg_writel(0x0, rtcdrv->rtc_base + RTC_ALARM0);
+ sirfsoc_rtc_writel(rtcdrv, RTC_ALARM0, 0x0);
/* reset SYS RTC ALARM1 */
- sirfsoc_rtc_iobrg_writel(0x0, rtcdrv->rtc_base + RTC_ALARM1);
+ sirfsoc_rtc_writel(rtcdrv, RTC_ALARM1, 0x0);
}
rtcdrv->overflow_rtc = rtcdrv->saved_overflow_rtc;
@@ -419,15 +441,14 @@ static int sirfsoc_rtc_resume(struct device *dev)
* if current counter is small than previous,
* it means overflow in sleep
*/
- tmp = sirfsoc_rtc_iobrg_readl(rtcdrv->rtc_base + RTC_CN);
+ tmp = sirfsoc_rtc_readl(rtcdrv, RTC_CN);
if (tmp <= rtcdrv->saved_counter)
rtcdrv->overflow_rtc++;
/*
*PWRC Value Be Changed When Suspend, Restore Overflow
* In Memory To Register
*/
- sirfsoc_rtc_iobrg_writel(rtcdrv->overflow_rtc,
- rtcdrv->rtc_base + RTC_SW_VALUE);
+ sirfsoc_rtc_writel(rtcdrv, RTC_SW_VALUE, rtcdrv->overflow_rtc);
if (device_may_wakeup(dev) && rtcdrv->irq_wake) {
disable_irq_wake(rtcdrv->irq);
diff --git a/drivers/rtc/rtc-snvs.c b/drivers/rtc/rtc-snvs.c
index d87a85cef..950c5d0b6 100644
--- a/drivers/rtc/rtc-snvs.c
+++ b/drivers/rtc/rtc-snvs.c
@@ -18,6 +18,10 @@
#include <linux/platform_device.h>
#include <linux/rtc.h>
#include <linux/clk.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
+
+#define SNVS_LPREGISTER_OFFSET 0x34
/* These register offsets are relative to LP (Low Power) range */
#define SNVS_LPCR 0x04
@@ -37,31 +41,36 @@
struct snvs_rtc_data {
struct rtc_device *rtc;
- void __iomem *ioaddr;
+ struct regmap *regmap;
+ int offset;
int irq;
- spinlock_t lock;
struct clk *clk;
};
-static u32 rtc_read_lp_counter(void __iomem *ioaddr)
+static u32 rtc_read_lp_counter(struct snvs_rtc_data *data)
{
u64 read1, read2;
+ u32 val;
do {
- read1 = readl(ioaddr + SNVS_LPSRTCMR);
+ regmap_read(data->regmap, data->offset + SNVS_LPSRTCMR, &val);
+ read1 = val;
read1 <<= 32;
- read1 |= readl(ioaddr + SNVS_LPSRTCLR);
+ regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &val);
+ read1 |= val;
- read2 = readl(ioaddr + SNVS_LPSRTCMR);
+ regmap_read(data->regmap, data->offset + SNVS_LPSRTCMR, &val);
+ read2 = val;
read2 <<= 32;
- read2 |= readl(ioaddr + SNVS_LPSRTCLR);
+ regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &val);
+ read2 |= val;
} while (read1 != read2);
/* Convert 47-bit counter to 32-bit raw second count */
return (u32) (read1 >> CNTR_TO_SECS_SH);
}
-static void rtc_write_sync_lp(void __iomem *ioaddr)
+static void rtc_write_sync_lp(struct snvs_rtc_data *data)
{
u32 count1, count2, count3;
int i;
@@ -69,15 +78,15 @@ static void rtc_write_sync_lp(void __iomem *ioaddr)
/* Wait for 3 CKIL cycles */
for (i = 0; i < 3; i++) {
do {
- count1 = readl(ioaddr + SNVS_LPSRTCLR);
- count2 = readl(ioaddr + SNVS_LPSRTCLR);
+ regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count1);
+ regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count2);
} while (count1 != count2);
/* Now wait until counter value changes */
do {
do {
- count2 = readl(ioaddr + SNVS_LPSRTCLR);
- count3 = readl(ioaddr + SNVS_LPSRTCLR);
+ regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count2);
+ regmap_read(data->regmap, data->offset + SNVS_LPSRTCLR, &count3);
} while (count2 != count3);
} while (count3 == count1);
}
@@ -85,23 +94,14 @@ static void rtc_write_sync_lp(void __iomem *ioaddr)
static int snvs_rtc_enable(struct snvs_rtc_data *data, bool enable)
{
- unsigned long flags;
int timeout = 1000;
u32 lpcr;
- spin_lock_irqsave(&data->lock, flags);
-
- lpcr = readl(data->ioaddr + SNVS_LPCR);
- if (enable)
- lpcr |= SNVS_LPCR_SRTC_ENV;
- else
- lpcr &= ~SNVS_LPCR_SRTC_ENV;
- writel(lpcr, data->ioaddr + SNVS_LPCR);
-
- spin_unlock_irqrestore(&data->lock, flags);
+ regmap_update_bits(data->regmap, data->offset + SNVS_LPCR, SNVS_LPCR_SRTC_ENV,
+ enable ? SNVS_LPCR_SRTC_ENV : 0);
while (--timeout) {
- lpcr = readl(data->ioaddr + SNVS_LPCR);
+ regmap_read(data->regmap, data->offset + SNVS_LPCR, &lpcr);
if (enable) {
if (lpcr & SNVS_LPCR_SRTC_ENV)
@@ -121,7 +121,7 @@ static int snvs_rtc_enable(struct snvs_rtc_data *data, bool enable)
static int snvs_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
struct snvs_rtc_data *data = dev_get_drvdata(dev);
- unsigned long time = rtc_read_lp_counter(data->ioaddr);
+ unsigned long time = rtc_read_lp_counter(data);
rtc_time_to_tm(time, tm);
@@ -139,8 +139,8 @@ static int snvs_rtc_set_time(struct device *dev, struct rtc_time *tm)
snvs_rtc_enable(data, false);
/* Write 32-bit time to 47-bit timer, leaving 15 LSBs blank */
- writel(time << CNTR_TO_SECS_SH, data->ioaddr + SNVS_LPSRTCLR);
- writel(time >> (32 - CNTR_TO_SECS_SH), data->ioaddr + SNVS_LPSRTCMR);
+ regmap_write(data->regmap, data->offset + SNVS_LPSRTCLR, time << CNTR_TO_SECS_SH);
+ regmap_write(data->regmap, data->offset + SNVS_LPSRTCMR, time >> (32 - CNTR_TO_SECS_SH));
/* Enable RTC again */
snvs_rtc_enable(data, true);
@@ -153,10 +153,10 @@ static int snvs_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
struct snvs_rtc_data *data = dev_get_drvdata(dev);
u32 lptar, lpsr;
- lptar = readl(data->ioaddr + SNVS_LPTAR);
+ regmap_read(data->regmap, data->offset + SNVS_LPTAR, &lptar);
rtc_time_to_tm(lptar, &alrm->time);
- lpsr = readl(data->ioaddr + SNVS_LPSR);
+ regmap_read(data->regmap, data->offset + SNVS_LPSR, &lpsr);
alrm->pending = (lpsr & SNVS_LPSR_LPTA) ? 1 : 0;
return 0;
@@ -165,21 +165,12 @@ static int snvs_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
static int snvs_rtc_alarm_irq_enable(struct device *dev, unsigned int enable)
{
struct snvs_rtc_data *data = dev_get_drvdata(dev);
- u32 lpcr;
- unsigned long flags;
-
- spin_lock_irqsave(&data->lock, flags);
- lpcr = readl(data->ioaddr + SNVS_LPCR);
- if (enable)
- lpcr |= (SNVS_LPCR_LPTA_EN | SNVS_LPCR_LPWUI_EN);
- else
- lpcr &= ~(SNVS_LPCR_LPTA_EN | SNVS_LPCR_LPWUI_EN);
- writel(lpcr, data->ioaddr + SNVS_LPCR);
+ regmap_update_bits(data->regmap, data->offset + SNVS_LPCR,
+ (SNVS_LPCR_LPTA_EN | SNVS_LPCR_LPWUI_EN),
+ enable ? (SNVS_LPCR_LPTA_EN | SNVS_LPCR_LPWUI_EN) : 0);
- spin_unlock_irqrestore(&data->lock, flags);
-
- rtc_write_sync_lp(data->ioaddr);
+ rtc_write_sync_lp(data);
return 0;
}
@@ -189,24 +180,14 @@ 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 flags;
- u32 lpcr;
rtc_tm_to_time(alrm_tm, &time);
- spin_lock_irqsave(&data->lock, flags);
-
- /* Have to clear LPTA_EN before programming new alarm time in LPTAR */
- lpcr = readl(data->ioaddr + SNVS_LPCR);
- lpcr &= ~SNVS_LPCR_LPTA_EN;
- writel(lpcr, data->ioaddr + SNVS_LPCR);
-
- spin_unlock_irqrestore(&data->lock, flags);
-
- writel(time, data->ioaddr + SNVS_LPTAR);
+ regmap_update_bits(data->regmap, data->offset + SNVS_LPCR, SNVS_LPCR_LPTA_EN, 0);
+ regmap_write(data->regmap, data->offset + SNVS_LPTAR, time);
/* Clear alarm interrupt status bit */
- writel(SNVS_LPSR_LPTA, data->ioaddr + SNVS_LPSR);
+ regmap_write(data->regmap, data->offset + SNVS_LPSR, SNVS_LPSR_LPTA);
return snvs_rtc_alarm_irq_enable(dev, alrm->enabled);
}
@@ -226,7 +207,7 @@ static irqreturn_t snvs_rtc_irq_handler(int irq, void *dev_id)
u32 lpsr;
u32 events = 0;
- lpsr = readl(data->ioaddr + SNVS_LPSR);
+ regmap_read(data->regmap, data->offset + SNVS_LPSR, &lpsr);
if (lpsr & SNVS_LPSR_LPTA) {
events |= (RTC_AF | RTC_IRQF);
@@ -238,25 +219,48 @@ static irqreturn_t snvs_rtc_irq_handler(int irq, void *dev_id)
}
/* clear interrupt status */
- writel(lpsr, data->ioaddr + SNVS_LPSR);
+ regmap_write(data->regmap, data->offset + SNVS_LPSR, lpsr);
return events ? IRQ_HANDLED : IRQ_NONE;
}
+static const struct regmap_config snvs_rtc_config = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+};
+
static int snvs_rtc_probe(struct platform_device *pdev)
{
struct snvs_rtc_data *data;
struct resource *res;
int ret;
+ void __iomem *mmio;
data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- data->ioaddr = devm_ioremap_resource(&pdev->dev, res);
- if (IS_ERR(data->ioaddr))
- return PTR_ERR(data->ioaddr);
+ data->regmap = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, "regmap");
+
+ if (IS_ERR(data->regmap)) {
+ dev_warn(&pdev->dev, "snvs rtc: you use old dts file, please update it\n");
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+ mmio = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(mmio))
+ return PTR_ERR(mmio);
+
+ data->regmap = devm_regmap_init_mmio(&pdev->dev, mmio, &snvs_rtc_config);
+ } else {
+ data->offset = SNVS_LPREGISTER_OFFSET;
+ of_property_read_u32(pdev->dev.of_node, "offset", &data->offset);
+ }
+
+ if (!data->regmap) {
+ dev_err(&pdev->dev, "Can't find snvs syscon\n");
+ return -ENODEV;
+ }
data->irq = platform_get_irq(pdev, 0);
if (data->irq < 0)
@@ -276,13 +280,11 @@ static int snvs_rtc_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, data);
- spin_lock_init(&data->lock);
-
/* Initialize glitch detect */
- writel(SNVS_LPPGDR_INIT, data->ioaddr + SNVS_LPPGDR);
+ regmap_write(data->regmap, data->offset + SNVS_LPPGDR, SNVS_LPPGDR_INIT);
/* Clear interrupt status */
- writel(0xffffffff, data->ioaddr + SNVS_LPSR);
+ regmap_write(data->regmap, data->offset + SNVS_LPSR, 0xffffffff);
/* Enable RTC */
snvs_rtc_enable(data, true);
diff --git a/drivers/rtc/rtc-st-lpc.c b/drivers/rtc/rtc-st-lpc.c
index 3f9d0acb8..74c0a336c 100644
--- a/drivers/rtc/rtc-st-lpc.c
+++ b/drivers/rtc/rtc-st-lpc.c
@@ -208,7 +208,7 @@ static int st_rtc_probe(struct platform_device *pdev)
return -EINVAL;
}
- /* LPC can either run in RTC or WDT mode */
+ /* LPC can either run as a Clocksource or in RTC or WDT mode */
if (mode != ST_LPC_MODE_RTC)
return -ENODEV;
diff --git a/drivers/rtc/rtc-stk17ta8.c b/drivers/rtc/rtc-stk17ta8.c
index 0e93b714e..ba6a83b5b 100644
--- a/drivers/rtc/rtc-stk17ta8.c
+++ b/drivers/rtc/rtc-stk17ta8.c
@@ -254,7 +254,7 @@ static ssize_t stk17ta8_nvram_read(struct file *filp, struct kobject *kobj,
void __iomem *ioaddr = pdata->ioaddr;
ssize_t count;
- for (count = 0; size > 0 && pos < RTC_OFFSET; count++, size--)
+ for (count = 0; count < size; count++)
*buf++ = readb(ioaddr + pos++);
return count;
}
@@ -269,7 +269,7 @@ static ssize_t stk17ta8_nvram_write(struct file *filp, struct kobject *kobj,
void __iomem *ioaddr = pdata->ioaddr;
ssize_t count;
- for (count = 0; size > 0 && pos < RTC_OFFSET; count++, size--)
+ for (count = 0; count < size; count++)
writeb(*buf++, ioaddr + pos++);
return count;
}
diff --git a/drivers/rtc/rtc-sysfs.c b/drivers/rtc/rtc-sysfs.c
index babd43bf3..7273855ed 100644
--- a/drivers/rtc/rtc-sysfs.c
+++ b/drivers/rtc/rtc-sysfs.c
@@ -122,20 +122,8 @@ hctosys_show(struct device *dev, struct device_attribute *attr, char *buf)
}
static DEVICE_ATTR_RO(hctosys);
-static struct attribute *rtc_attrs[] = {
- &dev_attr_name.attr,
- &dev_attr_date.attr,
- &dev_attr_time.attr,
- &dev_attr_since_epoch.attr,
- &dev_attr_max_user_freq.attr,
- &dev_attr_hctosys.attr,
- NULL,
-};
-ATTRIBUTE_GROUPS(rtc);
-
static ssize_t
-rtc_sysfs_show_wakealarm(struct device *dev, struct device_attribute *attr,
- char *buf)
+wakealarm_show(struct device *dev, struct device_attribute *attr, char *buf)
{
ssize_t retval;
unsigned long alarm;
@@ -159,7 +147,7 @@ rtc_sysfs_show_wakealarm(struct device *dev, struct device_attribute *attr,
}
static ssize_t
-rtc_sysfs_set_wakealarm(struct device *dev, struct device_attribute *attr,
+wakealarm_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t n)
{
ssize_t retval;
@@ -221,45 +209,57 @@ rtc_sysfs_set_wakealarm(struct device *dev, struct device_attribute *attr,
retval = rtc_set_alarm(rtc, &alm);
return (retval < 0) ? retval : n;
}
-static DEVICE_ATTR(wakealarm, S_IRUGO | S_IWUSR,
- rtc_sysfs_show_wakealarm, rtc_sysfs_set_wakealarm);
+static DEVICE_ATTR_RW(wakealarm);
+static struct attribute *rtc_attrs[] = {
+ &dev_attr_name.attr,
+ &dev_attr_date.attr,
+ &dev_attr_time.attr,
+ &dev_attr_since_epoch.attr,
+ &dev_attr_max_user_freq.attr,
+ &dev_attr_hctosys.attr,
+ &dev_attr_wakealarm.attr,
+ NULL,
+};
/* The reason to trigger an alarm with no process watching it (via sysfs)
* is its side effect: waking from a system state like suspend-to-RAM or
* suspend-to-disk. So: no attribute unless that side effect is possible.
* (Userspace may disable that mechanism later.)
*/
-static inline int rtc_does_wakealarm(struct rtc_device *rtc)
+static bool rtc_does_wakealarm(struct rtc_device *rtc)
{
if (!device_can_wakeup(rtc->dev.parent))
- return 0;
+ return false;
+
return rtc->ops->set_alarm != NULL;
}
-
-void rtc_sysfs_add_device(struct rtc_device *rtc)
+static umode_t rtc_attr_is_visible(struct kobject *kobj,
+ struct attribute *attr, int n)
{
- int err;
+ struct device *dev = container_of(kobj, struct device, kobj);
+ struct rtc_device *rtc = to_rtc_device(dev);
+ umode_t mode = attr->mode;
- /* not all RTCs support both alarms and wakeup */
- if (!rtc_does_wakealarm(rtc))
- return;
+ if (attr == &dev_attr_wakealarm.attr)
+ if (!rtc_does_wakealarm(rtc))
+ mode = 0;
- err = device_create_file(&rtc->dev, &dev_attr_wakealarm);
- if (err)
- dev_err(rtc->dev.parent,
- "failed to create alarm attribute, %d\n", err);
+ return mode;
}
-void rtc_sysfs_del_device(struct rtc_device *rtc)
-{
- /* REVISIT did we add it successfully? */
- if (rtc_does_wakealarm(rtc))
- device_remove_file(&rtc->dev, &dev_attr_wakealarm);
-}
+static struct attribute_group rtc_attr_group = {
+ .is_visible = rtc_attr_is_visible,
+ .attrs = rtc_attrs,
+};
+
+static const struct attribute_group *rtc_attr_groups[] = {
+ &rtc_attr_group,
+ NULL
+};
-void __init rtc_sysfs_init(struct class *rtc_class)
+const struct attribute_group **rtc_get_dev_attribute_groups(void)
{
- rtc_class->dev_groups = rtc_groups;
+ return rtc_attr_groups;
}
diff --git a/drivers/rtc/rtc-tx4939.c b/drivers/rtc/rtc-tx4939.c
index cb7f94ede..560d9a5e0 100644
--- a/drivers/rtc/rtc-tx4939.c
+++ b/drivers/rtc/rtc-tx4939.c
@@ -199,8 +199,7 @@ static ssize_t tx4939_rtc_nvram_read(struct file *filp, struct kobject *kobj,
ssize_t count;
spin_lock_irq(&pdata->lock);
- for (count = 0; size > 0 && pos < TX4939_RTC_REG_RAMSIZE;
- count++, size--) {
+ for (count = 0; count < size; count++) {
__raw_writel(pos++, &rtcreg->adr);
*buf++ = __raw_readl(&rtcreg->dat);
}
@@ -218,8 +217,7 @@ static ssize_t tx4939_rtc_nvram_write(struct file *filp, struct kobject *kobj,
ssize_t count;
spin_lock_irq(&pdata->lock);
- for (count = 0; size > 0 && pos < TX4939_RTC_REG_RAMSIZE;
- count++, size--) {
+ for (count = 0; count < size; count++) {
__raw_writel(pos++, &rtcreg->adr);
__raw_writel(*buf++, &rtcreg->dat);
}
diff --git a/drivers/rtc/rtc-vt8500.c b/drivers/rtc/rtc-vt8500.c
index a58b6d17e..27e896995 100644
--- a/drivers/rtc/rtc-vt8500.c
+++ b/drivers/rtc/rtc-vt8500.c
@@ -271,6 +271,7 @@ static const struct of_device_id wmt_dt_ids[] = {
{ .compatible = "via,vt8500-rtc", },
{}
};
+MODULE_DEVICE_TABLE(of, wmt_dt_ids);
static struct platform_driver vt8500_rtc_driver = {
.probe = vt8500_rtc_probe,
diff --git a/drivers/rtc/rtc-zynqmp.c b/drivers/rtc/rtc-zynqmp.c
new file mode 100644
index 000000000..8b28762f0
--- /dev/null
+++ b/drivers/rtc/rtc-zynqmp.c
@@ -0,0 +1,279 @@
+/*
+ * Xilinx Zynq Ultrascale+ MPSoC Real Time Clock Driver
+ *
+ * Copyright (C) 2015 Xilinx, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/rtc.h>
+
+/* RTC Registers */
+#define RTC_SET_TM_WR 0x00
+#define RTC_SET_TM_RD 0x04
+#define RTC_CALIB_WR 0x08
+#define RTC_CALIB_RD 0x0C
+#define RTC_CUR_TM 0x10
+#define RTC_CUR_TICK 0x14
+#define RTC_ALRM 0x18
+#define RTC_INT_STS 0x20
+#define RTC_INT_MASK 0x24
+#define RTC_INT_EN 0x28
+#define RTC_INT_DIS 0x2C
+#define RTC_CTRL 0x40
+
+#define RTC_FR_EN BIT(20)
+#define RTC_FR_DATSHIFT 16
+#define RTC_TICK_MASK 0xFFFF
+#define RTC_INT_SEC BIT(0)
+#define RTC_INT_ALRM BIT(1)
+#define RTC_OSC_EN BIT(24)
+
+#define RTC_CALIB_DEF 0x198233
+#define RTC_CALIB_MASK 0x1FFFFF
+#define RTC_SEC_MAX_VAL 0xFFFFFFFF
+
+struct xlnx_rtc_dev {
+ struct rtc_device *rtc;
+ void __iomem *reg_base;
+ int alarm_irq;
+ int sec_irq;
+};
+
+static int xlnx_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+ struct xlnx_rtc_dev *xrtcdev = dev_get_drvdata(dev);
+ unsigned long new_time;
+
+ new_time = rtc_tm_to_time64(tm);
+
+ if (new_time > RTC_SEC_MAX_VAL)
+ return -EINVAL;
+
+ writel(new_time, xrtcdev->reg_base + RTC_SET_TM_WR);
+
+ return 0;
+}
+
+static int xlnx_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+ struct xlnx_rtc_dev *xrtcdev = dev_get_drvdata(dev);
+
+ rtc_time64_to_tm(readl(xrtcdev->reg_base + RTC_CUR_TM), tm);
+
+ return rtc_valid_tm(tm);
+}
+
+static int xlnx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ struct xlnx_rtc_dev *xrtcdev = dev_get_drvdata(dev);
+
+ rtc_time64_to_tm(readl(xrtcdev->reg_base + RTC_ALRM), &alrm->time);
+ alrm->enabled = readl(xrtcdev->reg_base + RTC_INT_MASK) & RTC_INT_ALRM;
+
+ return 0;
+}
+
+static int xlnx_rtc_alarm_irq_enable(struct device *dev, u32 enabled)
+{
+ struct xlnx_rtc_dev *xrtcdev = dev_get_drvdata(dev);
+
+ if (enabled)
+ writel(RTC_INT_ALRM, xrtcdev->reg_base + RTC_INT_EN);
+ else
+ writel(RTC_INT_ALRM, xrtcdev->reg_base + RTC_INT_DIS);
+
+ return 0;
+}
+
+static int xlnx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+ struct xlnx_rtc_dev *xrtcdev = dev_get_drvdata(dev);
+ unsigned long alarm_time;
+
+ alarm_time = rtc_tm_to_time64(&alrm->time);
+
+ if (alarm_time > RTC_SEC_MAX_VAL)
+ return -EINVAL;
+
+ writel((u32)alarm_time, (xrtcdev->reg_base + RTC_ALRM));
+
+ xlnx_rtc_alarm_irq_enable(dev, alrm->enabled);
+
+ return 0;
+}
+
+static void xlnx_init_rtc(struct xlnx_rtc_dev *xrtcdev, u32 calibval)
+{
+ /*
+ * Based on crystal freq of 33.330 KHz
+ * set the seconds counter and enable, set fractions counter
+ * to default value suggested as per design spec
+ * to correct RTC delay in frequency over period of time.
+ */
+ calibval &= RTC_CALIB_MASK;
+ writel(calibval, (xrtcdev->reg_base + RTC_CALIB_WR));
+}
+
+static const struct rtc_class_ops xlnx_rtc_ops = {
+ .set_time = xlnx_rtc_set_time,
+ .read_time = xlnx_rtc_read_time,
+ .read_alarm = xlnx_rtc_read_alarm,
+ .set_alarm = xlnx_rtc_set_alarm,
+ .alarm_irq_enable = xlnx_rtc_alarm_irq_enable,
+};
+
+static irqreturn_t xlnx_rtc_interrupt(int irq, void *id)
+{
+ struct xlnx_rtc_dev *xrtcdev = (struct xlnx_rtc_dev *)id;
+ unsigned int status;
+
+ status = readl(xrtcdev->reg_base + RTC_INT_STS);
+ /* Check if interrupt asserted */
+ if (!(status & (RTC_INT_SEC | RTC_INT_ALRM)))
+ return IRQ_NONE;
+
+ /* Clear interrupt */
+ writel(status, xrtcdev->reg_base + RTC_INT_STS);
+
+ if (status & RTC_INT_SEC)
+ rtc_update_irq(xrtcdev->rtc, 1, RTC_IRQF | RTC_UF);
+ if (status & RTC_INT_ALRM)
+ rtc_update_irq(xrtcdev->rtc, 1, RTC_IRQF | RTC_AF);
+
+ return IRQ_HANDLED;
+}
+
+static int xlnx_rtc_probe(struct platform_device *pdev)
+{
+ struct xlnx_rtc_dev *xrtcdev;
+ struct resource *res;
+ int ret;
+ unsigned int calibvalue;
+
+ xrtcdev = devm_kzalloc(&pdev->dev, sizeof(*xrtcdev), GFP_KERNEL);
+ if (!xrtcdev)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, xrtcdev);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+ xrtcdev->reg_base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(xrtcdev->reg_base))
+ 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");
+ return xrtcdev->alarm_irq;
+ }
+ ret = devm_request_irq(&pdev->dev, xrtcdev->alarm_irq,
+ xlnx_rtc_interrupt, 0,
+ dev_name(&pdev->dev), xrtcdev);
+ if (ret) {
+ dev_err(&pdev->dev, "request irq failed\n");
+ return ret;
+ }
+
+ xrtcdev->sec_irq = platform_get_irq_byname(pdev, "sec");
+ if (xrtcdev->sec_irq < 0) {
+ dev_err(&pdev->dev, "no irq resource\n");
+ return xrtcdev->sec_irq;
+ }
+ ret = devm_request_irq(&pdev->dev, xrtcdev->sec_irq,
+ xlnx_rtc_interrupt, 0,
+ dev_name(&pdev->dev), xrtcdev);
+ if (ret) {
+ dev_err(&pdev->dev, "request irq failed\n");
+ return ret;
+ }
+
+ ret = of_property_read_u32(pdev->dev.of_node, "calibration",
+ &calibvalue);
+ if (ret)
+ calibvalue = RTC_CALIB_DEF;
+
+ xlnx_init_rtc(xrtcdev, calibvalue);
+
+ device_init_wakeup(&pdev->dev, 1);
+
+ xrtcdev->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
+ &xlnx_rtc_ops, THIS_MODULE);
+ return PTR_ERR_OR_ZERO(xrtcdev->rtc);
+}
+
+static int xlnx_rtc_remove(struct platform_device *pdev)
+{
+ xlnx_rtc_alarm_irq_enable(&pdev->dev, 0);
+ device_init_wakeup(&pdev->dev, 0);
+
+ return 0;
+}
+
+static int __maybe_unused xlnx_rtc_suspend(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct xlnx_rtc_dev *xrtcdev = platform_get_drvdata(pdev);
+
+ if (device_may_wakeup(&pdev->dev))
+ enable_irq_wake(xrtcdev->alarm_irq);
+ else
+ xlnx_rtc_alarm_irq_enable(dev, 0);
+
+ return 0;
+}
+
+static int __maybe_unused xlnx_rtc_resume(struct device *dev)
+{
+ struct platform_device *pdev = to_platform_device(dev);
+ struct xlnx_rtc_dev *xrtcdev = platform_get_drvdata(pdev);
+
+ if (device_may_wakeup(&pdev->dev))
+ disable_irq_wake(xrtcdev->alarm_irq);
+ else
+ xlnx_rtc_alarm_irq_enable(dev, 1);
+
+ return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(xlnx_rtc_pm_ops, xlnx_rtc_suspend, xlnx_rtc_resume);
+
+static const struct of_device_id xlnx_rtc_of_match[] = {
+ {.compatible = "xlnx,zynqmp-rtc" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, xlnx_rtc_of_match);
+
+static struct platform_driver xlnx_rtc_driver = {
+ .probe = xlnx_rtc_probe,
+ .remove = xlnx_rtc_remove,
+ .driver = {
+ .name = KBUILD_MODNAME,
+ .pm = &xlnx_rtc_pm_ops,
+ .of_match_table = xlnx_rtc_of_match,
+ },
+};
+
+module_platform_driver(xlnx_rtc_driver);
+
+MODULE_DESCRIPTION("Xilinx Zynq MPSoC RTC driver");
+MODULE_AUTHOR("Xilinx Inc.");
+MODULE_LICENSE("GPL v2");