aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephen Rothwell <sfr@canb.auug.org.au>2015-05-15 17:04:07 +1000
committerStephen Rothwell <sfr@canb.auug.org.au>2015-05-15 17:04:07 +1000
commitd608cb95d20a55228c29d4d6012e29df857c81be (patch)
tree6347495992502433ba3342bad460b7c7e5ab6184
parentec28790b341a2abc2795eacf3490445c86acabcf (diff)
parent9a8c5c0750423d1adb528975e68669cf05d05e59 (diff)
Merge remote-tracking branch 'rtc/rtc-next'
-rw-r--r--MAINTAINERS7
-rw-r--r--drivers/mfd/mt6397-core.c18
-rw-r--r--drivers/rtc/Kconfig11
-rw-r--r--drivers/rtc/Makefile1
-rw-r--r--drivers/rtc/interface.c4
-rw-r--r--drivers/rtc/rtc-ab8500.c2
-rw-r--r--drivers/rtc/rtc-at32ap700x.c2
-rw-r--r--drivers/rtc/rtc-efi.c4
-rw-r--r--drivers/rtc/rtc-hid-sensor-time.c2
-rw-r--r--drivers/rtc/rtc-imxdi.c438
-rw-r--r--drivers/rtc/rtc-mc13xxx.c2
-rw-r--r--drivers/rtc/rtc-mt6397.c395
-rw-r--r--drivers/rtc/rtc-mxc.c2
-rw-r--r--drivers/rtc/rtc-s3c.c14
-rw-r--r--include/linux/rtc.h11
15 files changed, 826 insertions, 87 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 8985b676c70c..3d5ab5350e31 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1230,6 +1230,13 @@ W: http://www.digriz.org.uk/ts78xx/kernel
S: Maintained
F: arch/arm/mach-orion5x/ts78xx-*
+ARM/Mediatek RTC DRIVER
+M: Eddie Huang <eddie.huang@mediatek.com>
+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+L: linux-mediatek@lists.infradead.org (moderated for non-subscribers)
+S: Maintained
+F: drivers/rtc/rtc-mt6397.c
+
ARM/Mediatek SoC support
M: Matthias Brugger <matthias.bgg@gmail.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
diff --git a/drivers/mfd/mt6397-core.c b/drivers/mfd/mt6397-core.c
index 32775ebbce18..fd7a3da7e54b 100644
--- a/drivers/mfd/mt6397-core.c
+++ b/drivers/mfd/mt6397-core.c
@@ -21,9 +21,27 @@
#include <linux/mfd/mt6397/core.h>
#include <linux/mfd/mt6397/registers.h>
+#define MT6397_RTC_BASE 0xe000
+#define MT6397_RTC_SIZE 0x3e
+
+static const struct resource mt6397_rtc_resources[] = {
+ {
+ .start = MT6397_RTC_BASE,
+ .end = MT6397_RTC_BASE + MT6397_RTC_SIZE,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = MT6397_IRQ_RTC,
+ .end = MT6397_IRQ_RTC,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
static const struct mfd_cell mt6397_devs[] = {
{
.name = "mt6397-rtc",
+ .num_resources = ARRAY_SIZE(mt6397_rtc_resources),
+ .resources = mt6397_rtc_resources,
.of_compatible = "mediatek,mt6397-rtc",
}, {
.name = "mt6397-regulator",
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 5e963df9e565..44c5c175b6c5 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -1541,9 +1541,20 @@ config RTC_DRV_MOXART
This driver can also be built as a module. If so, the module
will be called rtc-moxart
+config RTC_DRV_MT6397
+ tristate "Mediatek Real Time Clock driver"
+ depends on MFD_MT6397 || COMPILE_TEST
+ help
+ This selects the Mediatek(R) RTC driver. RTC is part of Mediatek
+ MT6397 PMIC. You should enable MT6397 PMIC MFD before select
+ Mediatek(R) RTC driver.
+
+ If you want to use Mediatek(R) RTC interface, select Y or M here.
+
config RTC_DRV_XGENE
tristate "APM X-Gene RTC"
depends on HAS_IOMEM
+ depends on ARCH_XGENE || COMPILE_TEST
help
If you say yes here you get support for the APM X-Gene SoC real time
clock.
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index ebe2c085d01c..697dc5c4f078 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -156,3 +156,4 @@ obj-$(CONFIG_RTC_DRV_XGENE) += rtc-xgene.o
obj-$(CONFIG_RTC_DRV_SIRFSOC) += rtc-sirfsoc.o
obj-$(CONFIG_RTC_DRV_ST_LPC) += rtc-st-lpc.o
obj-$(CONFIG_RTC_DRV_MOXART) += rtc-moxart.o
+obj-$(CONFIG_RTC_DRV_MT6397) += rtc-mt6397.o
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c
index 166fc60d8b55..a6b14c24d7e3 100644
--- a/drivers/rtc/interface.c
+++ b/drivers/rtc/interface.c
@@ -976,14 +976,12 @@ int rtc_timer_start(struct rtc_device *rtc, struct rtc_timer *timer,
*
* Kernel interface to cancel an rtc_timer
*/
-int rtc_timer_cancel(struct rtc_device *rtc, struct rtc_timer *timer)
+void rtc_timer_cancel(struct rtc_device *rtc, struct rtc_timer *timer)
{
- int ret = 0;
mutex_lock(&rtc->ops_lock);
if (timer->enabled)
rtc_timer_remove(rtc, timer);
mutex_unlock(&rtc->ops_lock);
- return ret;
}
diff --git a/drivers/rtc/rtc-ab8500.c b/drivers/rtc/rtc-ab8500.c
index 6856f0a3a3d5..133d2e2e1a25 100644
--- a/drivers/rtc/rtc-ab8500.c
+++ b/drivers/rtc/rtc-ab8500.c
@@ -442,7 +442,7 @@ static const struct rtc_class_ops ab8540_rtc_ops = {
.alarm_irq_enable = ab8500_rtc_irq_enable,
};
-static struct platform_device_id ab85xx_rtc_ids[] = {
+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, },
};
diff --git a/drivers/rtc/rtc-at32ap700x.c b/drivers/rtc/rtc-at32ap700x.c
index d618d6c7ef93..83ac2337c0f7 100644
--- a/drivers/rtc/rtc-at32ap700x.c
+++ b/drivers/rtc/rtc-at32ap700x.c
@@ -282,6 +282,6 @@ static struct platform_driver at32_rtc_driver = {
module_platform_driver_probe(at32_rtc_driver, at32_rtc_probe);
-MODULE_AUTHOR("Hans-Christian Egtvedt <hcegtvedt@atmel.com>");
+MODULE_AUTHOR("Hans-Christian Egtvedt <egtvedt@samfundet.no>");
MODULE_DESCRIPTION("Real time clock for AVR32 AT32AP700x");
MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-efi.c b/drivers/rtc/rtc-efi.c
index cb989cd00b14..c5fbabb1e0fc 100644
--- a/drivers/rtc/rtc-efi.c
+++ b/drivers/rtc/rtc-efi.c
@@ -3,7 +3,7 @@
*
* Copyright (C) 2009 Hewlett-Packard Development Company, L.P.
*
- * Author: dann frazier <dannf@hp.com>
+ * Author: dann frazier <dannf@dannf.org>
* Based on efirtc.c by Stephane Eranian
*
* This program is free software; you can redistribute it and/or modify it
@@ -233,7 +233,7 @@ static struct platform_driver efi_rtc_driver = {
module_platform_driver_probe(efi_rtc_driver, efi_rtc_probe);
MODULE_ALIAS("platform:rtc-efi");
-MODULE_AUTHOR("dann frazier <dannf@hp.com>");
+MODULE_AUTHOR("dann frazier <dannf@dannf.org>");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("EFI RTC driver");
MODULE_ALIAS("platform:rtc-efi");
diff --git a/drivers/rtc/rtc-hid-sensor-time.c b/drivers/rtc/rtc-hid-sensor-time.c
index af4f85a66b39..c398f74234c6 100644
--- a/drivers/rtc/rtc-hid-sensor-time.c
+++ b/drivers/rtc/rtc-hid-sensor-time.c
@@ -318,7 +318,7 @@ static int hid_time_remove(struct platform_device *pdev)
return 0;
}
-static struct platform_device_id hid_time_ids[] = {
+static const struct platform_device_id hid_time_ids[] = {
{
/* Format: HID-SENSOR-usage_id_in_hex_lowercase */
.name = "HID-SENSOR-2000a0",
diff --git a/drivers/rtc/rtc-imxdi.c b/drivers/rtc/rtc-imxdi.c
index c666eab98273..7bffd7f0e306 100644
--- a/drivers/rtc/rtc-imxdi.c
+++ b/drivers/rtc/rtc-imxdi.c
@@ -129,6 +129,324 @@ struct imxdi_dev {
struct work_struct work;
};
+/* Some background:
+ *
+ * The DryIce unit is a complex security/tamper monitor device. To be able do
+ * its job in a useful manner it runs a bigger statemachine to bring it into
+ * security/tamper failure state and once again to bring it out of this state.
+ *
+ * This unit can be in one of three states:
+ *
+ * - "NON-VALID STATE"
+ * always after the battery power was removed
+ * - "FAILURE STATE"
+ * if one of the enabled security events has happened
+ * - "VALID STATE"
+ * if the unit works as expected
+ *
+ * Everything stops when the unit enters the failure state including the RTC
+ * counter (to be able to detect the time the security event happened).
+ *
+ * The following events (when enabled) let the DryIce unit enter the failure
+ * state:
+ *
+ * - wire-mesh-tamper detect
+ * - external tamper B detect
+ * - external tamper A detect
+ * - temperature tamper detect
+ * - clock tamper detect
+ * - voltage tamper detect
+ * - RTC counter overflow
+ * - monotonic counter overflow
+ * - external boot
+ *
+ * If we find the DryIce unit in "FAILURE STATE" and the TDCHL cleared, we
+ * can only detect this state. In this case the unit is completely locked and
+ * must force a second "SYSTEM POR" to bring the DryIce into the
+ * "NON-VALID STATE" + "FAILURE STATE" where a recovery is possible.
+ * If the TDCHL is set in the "FAILURE STATE" we are out of luck. In this case
+ * a battery power cycle is required.
+ *
+ * In the "NON-VALID STATE" + "FAILURE STATE" we can clear the "FAILURE STATE"
+ * and recover the DryIce unit. By clearing the "NON-VALID STATE" as the last
+ * task, we bring back this unit into life.
+ */
+
+/*
+ * Do a write into the unit without interrupt support.
+ * We do not need to check the WEF here, because the only reason this kind of
+ * write error can happen is if we write to the unit twice within the 122 us
+ * interval. This cannot happen, since we are using this function only while
+ * setting up the unit.
+ */
+static void di_write_busy_wait(const struct imxdi_dev *imxdi, u32 val,
+ unsigned reg)
+{
+ /* do the register write */
+ writel(val, imxdi->ioaddr + reg);
+
+ /*
+ * now it takes four 32,768 kHz clock cycles to take
+ * the change into effect = 122 us
+ */
+ usleep_range(130, 200);
+}
+
+static void di_report_tamper_info(struct imxdi_dev *imxdi, u32 dsr)
+{
+ u32 dtcr;
+
+ dtcr = readl(imxdi->ioaddr + DTCR);
+
+ dev_emerg(&imxdi->pdev->dev, "DryIce tamper event detected\n");
+ /* the following flags force a transition into the "FAILURE STATE" */
+ if (dsr & DSR_VTD)
+ dev_emerg(&imxdi->pdev->dev, "%sVoltage Tamper Event\n",
+ dtcr & DTCR_VTE ? "" : "Spurious ");
+
+ if (dsr & DSR_CTD)
+ dev_emerg(&imxdi->pdev->dev, "%s32768 Hz Clock Tamper Event\n",
+ dtcr & DTCR_CTE ? "" : "Spurious ");
+
+ if (dsr & DSR_TTD)
+ dev_emerg(&imxdi->pdev->dev, "%sTemperature Tamper Event\n",
+ dtcr & DTCR_TTE ? "" : "Spurious ");
+
+ if (dsr & DSR_SAD)
+ dev_emerg(&imxdi->pdev->dev,
+ "%sSecure Controller Alarm Event\n",
+ dtcr & DTCR_SAIE ? "" : "Spurious ");
+
+ if (dsr & DSR_EBD)
+ dev_emerg(&imxdi->pdev->dev, "%sExternal Boot Tamper Event\n",
+ dtcr & DTCR_EBE ? "" : "Spurious ");
+
+ if (dsr & DSR_ETAD)
+ dev_emerg(&imxdi->pdev->dev, "%sExternal Tamper A Event\n",
+ dtcr & DTCR_ETAE ? "" : "Spurious ");
+
+ if (dsr & DSR_ETBD)
+ dev_emerg(&imxdi->pdev->dev, "%sExternal Tamper B Event\n",
+ dtcr & DTCR_ETBE ? "" : "Spurious ");
+
+ if (dsr & DSR_WTD)
+ dev_emerg(&imxdi->pdev->dev, "%sWire-mesh Tamper Event\n",
+ dtcr & DTCR_WTE ? "" : "Spurious ");
+
+ if (dsr & DSR_MCO)
+ dev_emerg(&imxdi->pdev->dev,
+ "%sMonotonic-counter Overflow Event\n",
+ dtcr & DTCR_MOE ? "" : "Spurious ");
+
+ if (dsr & DSR_TCO)
+ dev_emerg(&imxdi->pdev->dev, "%sTimer-counter Overflow Event\n",
+ dtcr & DTCR_TOE ? "" : "Spurious ");
+}
+
+static void di_what_is_to_be_done(struct imxdi_dev *imxdi,
+ const char *power_supply)
+{
+ dev_emerg(&imxdi->pdev->dev, "Please cycle the %s power supply in order to get the DryIce/RTC unit working again\n",
+ power_supply);
+}
+
+static int di_handle_failure_state(struct imxdi_dev *imxdi, u32 dsr)
+{
+ u32 dcr;
+
+ dev_dbg(&imxdi->pdev->dev, "DSR register reports: %08X\n", dsr);
+
+ /* report the cause */
+ di_report_tamper_info(imxdi, dsr);
+
+ dcr = readl(imxdi->ioaddr + DCR);
+
+ if (dcr & DCR_FSHL) {
+ /* we are out of luck */
+ di_what_is_to_be_done(imxdi, "battery");
+ return -ENODEV;
+ }
+ /*
+ * with the next SYSTEM POR we will transit from the "FAILURE STATE"
+ * into the "NON-VALID STATE" + "FAILURE STATE"
+ */
+ di_what_is_to_be_done(imxdi, "main");
+
+ return -ENODEV;
+}
+
+static int di_handle_valid_state(struct imxdi_dev *imxdi, u32 dsr)
+{
+ /* initialize alarm */
+ di_write_busy_wait(imxdi, DCAMR_UNSET, DCAMR);
+ di_write_busy_wait(imxdi, 0, DCALR);
+
+ /* clear alarm flag */
+ if (dsr & DSR_CAF)
+ di_write_busy_wait(imxdi, DSR_CAF, DSR);
+
+ return 0;
+}
+
+static int di_handle_invalid_state(struct imxdi_dev *imxdi, u32 dsr)
+{
+ u32 dcr, sec;
+
+ /*
+ * lets disable all sources which can force the DryIce unit into
+ * the "FAILURE STATE" for now
+ */
+ di_write_busy_wait(imxdi, 0x00000000, DTCR);
+ /* and lets protect them at runtime from any change */
+ di_write_busy_wait(imxdi, DCR_TDCSL, DCR);
+
+ sec = readl(imxdi->ioaddr + DTCMR);
+ if (sec != 0)
+ dev_warn(&imxdi->pdev->dev,
+ "The security violation has happend at %u seconds\n",
+ sec);
+ /*
+ * the timer cannot be set/modified if
+ * - the TCHL or TCSL bit is set in DCR
+ */
+ dcr = readl(imxdi->ioaddr + DCR);
+ if (!(dcr & DCR_TCE)) {
+ if (dcr & DCR_TCHL) {
+ /* we are out of luck */
+ di_what_is_to_be_done(imxdi, "battery");
+ return -ENODEV;
+ }
+ if (dcr & DCR_TCSL) {
+ di_what_is_to_be_done(imxdi, "main");
+ return -ENODEV;
+ }
+ }
+ /*
+ * - the timer counter stops/is stopped if
+ * - its overflow flag is set (TCO in DSR)
+ * -> clear overflow bit to make it count again
+ * - NVF is set in DSR
+ * -> clear non-valid bit to make it count again
+ * - its TCE (DCR) is cleared
+ * -> set TCE to make it count
+ * - it was never set before
+ * -> write a time into it (required again if the NVF was set)
+ */
+ /* state handled */
+ di_write_busy_wait(imxdi, DSR_NVF, DSR);
+ /* clear overflow flag */
+ di_write_busy_wait(imxdi, DSR_TCO, DSR);
+ /* enable the counter */
+ di_write_busy_wait(imxdi, dcr | DCR_TCE, DCR);
+ /* set and trigger it to make it count */
+ di_write_busy_wait(imxdi, sec, DTCMR);
+
+ /* now prepare for the valid state */
+ return di_handle_valid_state(imxdi, __raw_readl(imxdi->ioaddr + DSR));
+}
+
+static int di_handle_invalid_and_failure_state(struct imxdi_dev *imxdi, u32 dsr)
+{
+ u32 dcr;
+
+ /*
+ * now we must first remove the tamper sources in order to get the
+ * device out of the "FAILURE STATE"
+ * To disable any of the following sources we need to modify the DTCR
+ */
+ if (dsr & (DSR_WTD | DSR_ETBD | DSR_ETAD | DSR_EBD | DSR_SAD |
+ DSR_TTD | DSR_CTD | DSR_VTD | DSR_MCO | DSR_TCO)) {
+ dcr = __raw_readl(imxdi->ioaddr + DCR);
+ if (dcr & DCR_TDCHL) {
+ /*
+ * the tamper register is locked. We cannot disable the
+ * tamper detection. The TDCHL can only be reset by a
+ * DRYICE POR, but we cannot force a DRYICE POR in
+ * softwere because we are still in "FAILURE STATE".
+ * We need a DRYICE POR via battery power cycling....
+ */
+ /*
+ * out of luck!
+ * we cannot disable them without a DRYICE POR
+ */
+ di_what_is_to_be_done(imxdi, "battery");
+ return -ENODEV;
+ }
+ if (dcr & DCR_TDCSL) {
+ /* a soft lock can be removed by a SYSTEM POR */
+ di_what_is_to_be_done(imxdi, "main");
+ return -ENODEV;
+ }
+ }
+
+ /* disable all sources */
+ di_write_busy_wait(imxdi, 0x00000000, DTCR);
+
+ /* clear the status bits now */
+ di_write_busy_wait(imxdi, dsr & (DSR_WTD | DSR_ETBD | DSR_ETAD |
+ DSR_EBD | DSR_SAD | DSR_TTD | DSR_CTD | DSR_VTD |
+ DSR_MCO | DSR_TCO), DSR);
+
+ dsr = readl(imxdi->ioaddr + DSR);
+ if ((dsr & ~(DSR_NVF | DSR_SVF | DSR_WBF | DSR_WNF |
+ DSR_WCF | DSR_WEF)) != 0)
+ dev_warn(&imxdi->pdev->dev,
+ "There are still some sources of pain in DSR: %08x!\n",
+ dsr & ~(DSR_NVF | DSR_SVF | DSR_WBF | DSR_WNF |
+ DSR_WCF | DSR_WEF));
+
+ /*
+ * now we are trying to clear the "Security-violation flag" to
+ * get the DryIce out of this state
+ */
+ di_write_busy_wait(imxdi, DSR_SVF, DSR);
+
+ /* success? */
+ dsr = readl(imxdi->ioaddr + DSR);
+ if (dsr & DSR_SVF) {
+ dev_crit(&imxdi->pdev->dev,
+ "Cannot clear the security violation flag. We are ending up in an endless loop!\n");
+ /* last resort */
+ di_what_is_to_be_done(imxdi, "battery");
+ return -ENODEV;
+ }
+
+ /*
+ * now we have left the "FAILURE STATE" and ending up in the
+ * "NON-VALID STATE" time to recover everything
+ */
+ return di_handle_invalid_state(imxdi, dsr);
+}
+
+static int di_handle_state(struct imxdi_dev *imxdi)
+{
+ int rc;
+ u32 dsr;
+
+ dsr = readl(imxdi->ioaddr + DSR);
+
+ switch (dsr & (DSR_NVF | DSR_SVF)) {
+ case DSR_NVF:
+ dev_warn(&imxdi->pdev->dev, "Invalid stated unit detected\n");
+ rc = di_handle_invalid_state(imxdi, dsr);
+ break;
+ case DSR_SVF:
+ dev_warn(&imxdi->pdev->dev, "Failure stated unit detected\n");
+ rc = di_handle_failure_state(imxdi, dsr);
+ break;
+ case DSR_NVF | DSR_SVF:
+ dev_warn(&imxdi->pdev->dev,
+ "Failure+Invalid stated unit detected\n");
+ rc = di_handle_invalid_and_failure_state(imxdi, dsr);
+ break;
+ default:
+ dev_notice(&imxdi->pdev->dev, "Unlocked unit detected\n");
+ rc = di_handle_valid_state(imxdi, dsr);
+ }
+
+ return rc;
+}
+
/*
* enable a dryice interrupt
*/
@@ -137,8 +455,8 @@ static void di_int_enable(struct imxdi_dev *imxdi, u32 intr)
unsigned long flags;
spin_lock_irqsave(&imxdi->irq_lock, flags);
- __raw_writel(__raw_readl(imxdi->ioaddr + DIER) | intr,
- imxdi->ioaddr + DIER);
+ writel(readl(imxdi->ioaddr + DIER) | intr,
+ imxdi->ioaddr + DIER);
spin_unlock_irqrestore(&imxdi->irq_lock, flags);
}
@@ -150,8 +468,8 @@ static void di_int_disable(struct imxdi_dev *imxdi, u32 intr)
unsigned long flags;
spin_lock_irqsave(&imxdi->irq_lock, flags);
- __raw_writel(__raw_readl(imxdi->ioaddr + DIER) & ~intr,
- imxdi->ioaddr + DIER);
+ writel(readl(imxdi->ioaddr + DIER) & ~intr,
+ imxdi->ioaddr + DIER);
spin_unlock_irqrestore(&imxdi->irq_lock, flags);
}
@@ -169,11 +487,11 @@ static void clear_write_error(struct imxdi_dev *imxdi)
dev_warn(&imxdi->pdev->dev, "WARNING: Register write error!\n");
/* clear the write error flag */
- __raw_writel(DSR_WEF, imxdi->ioaddr + DSR);
+ writel(DSR_WEF, imxdi->ioaddr + DSR);
/* wait for it to take effect */
for (cnt = 0; cnt < 1000; cnt++) {
- if ((__raw_readl(imxdi->ioaddr + DSR) & DSR_WEF) == 0)
+ if ((readl(imxdi->ioaddr + DSR) & DSR_WEF) == 0)
return;
udelay(10);
}
@@ -201,7 +519,7 @@ static int di_write_wait(struct imxdi_dev *imxdi, u32 val, int reg)
imxdi->dsr = 0;
/* do the register write */
- __raw_writel(val, imxdi->ioaddr + reg);
+ writel(val, imxdi->ioaddr + reg);
/* wait for the write to finish */
ret = wait_event_interruptible_timeout(imxdi->write_wait,
@@ -235,7 +553,7 @@ static int dryice_rtc_read_time(struct device *dev, struct rtc_time *tm)
struct imxdi_dev *imxdi = dev_get_drvdata(dev);
unsigned long now;
- now = __raw_readl(imxdi->ioaddr + DTCMR);
+ now = readl(imxdi->ioaddr + DTCMR);
rtc_time_to_tm(now, tm);
return 0;
@@ -248,14 +566,35 @@ static int dryice_rtc_read_time(struct device *dev, struct rtc_time *tm)
static int dryice_rtc_set_mmss(struct device *dev, unsigned long secs)
{
struct imxdi_dev *imxdi = dev_get_drvdata(dev);
+ u32 dcr, dsr;
int rc;
+ dcr = readl(imxdi->ioaddr + DCR);
+ dsr = readl(imxdi->ioaddr + DSR);
+
+ if (!(dcr & DCR_TCE) || (dsr & DSR_SVF)) {
+ if (dcr & DCR_TCHL) {
+ /* we are even more out of luck */
+ di_what_is_to_be_done(imxdi, "battery");
+ return -EPERM;
+ }
+ if ((dcr & DCR_TCSL) || (dsr & DSR_SVF)) {
+ /* we are out of luck for now */
+ di_what_is_to_be_done(imxdi, "main");
+ return -EPERM;
+ }
+ }
+
/* zero the fractional part first */
rc = di_write_wait(imxdi, 0, DTCLR);
- if (rc == 0)
- rc = di_write_wait(imxdi, secs, DTCMR);
+ if (rc != 0)
+ return rc;
- return rc;
+ rc = di_write_wait(imxdi, secs, DTCMR);
+ if (rc != 0)
+ return rc;
+
+ return di_write_wait(imxdi, readl(imxdi->ioaddr + DCR) | DCR_TCE, DCR);
}
static int dryice_rtc_alarm_irq_enable(struct device *dev,
@@ -280,17 +619,17 @@ static int dryice_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
struct imxdi_dev *imxdi = dev_get_drvdata(dev);
u32 dcamr;
- dcamr = __raw_readl(imxdi->ioaddr + DCAMR);
+ dcamr = readl(imxdi->ioaddr + DCAMR);
rtc_time_to_tm(dcamr, &alarm->time);
/* alarm is enabled if the interrupt is enabled */
- alarm->enabled = (__raw_readl(imxdi->ioaddr + DIER) & DIER_CAIE) != 0;
+ alarm->enabled = (readl(imxdi->ioaddr + DIER) & DIER_CAIE) != 0;
/* don't allow the DSR read to mess up DSR_WCF */
mutex_lock(&imxdi->write_mutex);
/* alarm is pending if the alarm flag is set */
- alarm->pending = (__raw_readl(imxdi->ioaddr + DSR) & DSR_CAF) != 0;
+ alarm->pending = (readl(imxdi->ioaddr + DSR) & DSR_CAF) != 0;
mutex_unlock(&imxdi->write_mutex);
@@ -312,7 +651,7 @@ static int dryice_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
return rc;
/* don't allow setting alarm in the past */
- now = __raw_readl(imxdi->ioaddr + DTCMR);
+ now = readl(imxdi->ioaddr + DTCMR);
if (alarm_time < now)
return -EINVAL;
@@ -346,7 +685,26 @@ static irqreturn_t dryice_norm_irq(int irq, void *dev_id)
u32 dsr, dier;
irqreturn_t rc = IRQ_NONE;
- dier = __raw_readl(imxdi->ioaddr + DIER);
+ dier = readl(imxdi->ioaddr + DIER);
+ dsr = readl(imxdi->ioaddr + DSR);
+
+ /* handle the security violation event */
+ if (dier & DIER_SVIE) {
+ if (dsr & DSR_SVF) {
+ /*
+ * Disable the interrupt when this kind of event has
+ * happened.
+ * There cannot be more than one event of this type,
+ * because it needs a complex state change
+ * including a main power cycle to get again out of
+ * this state.
+ */
+ di_int_disable(imxdi, DIER_SVIE);
+ /* report the violation */
+ di_report_tamper_info(imxdi, dsr);
+ rc = IRQ_HANDLED;
+ }
+ }
/* handle write complete and write error cases */
if (dier & DIER_WCIE) {
@@ -357,7 +715,6 @@ static irqreturn_t dryice_norm_irq(int irq, void *dev_id)
return rc;
/* DSR_WCF clears itself on DSR read */
- dsr = __raw_readl(imxdi->ioaddr + DSR);
if (dsr & (DSR_WCF | DSR_WEF)) {
/* mask the interrupt */
di_int_disable(imxdi, DIER_WCIE);
@@ -373,7 +730,6 @@ static irqreturn_t dryice_norm_irq(int irq, void *dev_id)
/* handle the alarm case */
if (dier & DIER_CAIE) {
/* DSR_WCF clears itself on DSR read */
- dsr = __raw_readl(imxdi->ioaddr + DSR);
if (dsr & DSR_CAF) {
/* mask the interrupt */
di_int_disable(imxdi, DIER_CAIE);
@@ -446,7 +802,11 @@ static int __init dryice_rtc_probe(struct platform_device *pdev)
*/
/* mask all interrupts */
- __raw_writel(0, imxdi->ioaddr + DIER);
+ writel(0, imxdi->ioaddr + DIER);
+
+ rc = di_handle_state(imxdi);
+ if (rc != 0)
+ goto err;
rc = devm_request_irq(&pdev->dev, imxdi->irq, dryice_norm_irq,
IRQF_SHARED, pdev->name, imxdi);
@@ -455,44 +815,6 @@ static int __init dryice_rtc_probe(struct platform_device *pdev)
goto err;
}
- /* put dryice into valid state */
- if (__raw_readl(imxdi->ioaddr + DSR) & DSR_NVF) {
- rc = di_write_wait(imxdi, DSR_NVF | DSR_SVF, DSR);
- if (rc)
- goto err;
- }
-
- /* initialize alarm */
- rc = di_write_wait(imxdi, DCAMR_UNSET, DCAMR);
- if (rc)
- goto err;
- rc = di_write_wait(imxdi, 0, DCALR);
- if (rc)
- goto err;
-
- /* clear alarm flag */
- if (__raw_readl(imxdi->ioaddr + DSR) & DSR_CAF) {
- rc = di_write_wait(imxdi, DSR_CAF, DSR);
- if (rc)
- goto err;
- }
-
- /* the timer won't count if it has never been written to */
- if (__raw_readl(imxdi->ioaddr + DTCMR) == 0) {
- rc = di_write_wait(imxdi, 0, DTCMR);
- if (rc)
- goto err;
- }
-
- /* start keeping time */
- if (!(__raw_readl(imxdi->ioaddr + DCR) & DCR_TCE)) {
- rc = di_write_wait(imxdi,
- __raw_readl(imxdi->ioaddr + DCR) | DCR_TCE,
- DCR);
- if (rc)
- goto err;
- }
-
platform_set_drvdata(pdev, imxdi);
imxdi->rtc = devm_rtc_device_register(&pdev->dev, pdev->name,
&dryice_rtc_ops, THIS_MODULE);
@@ -516,7 +838,7 @@ static int __exit dryice_rtc_remove(struct platform_device *pdev)
flush_work(&imxdi->work);
/* mask all interrupts */
- __raw_writel(0, imxdi->ioaddr + DIER);
+ writel(0, imxdi->ioaddr + DIER);
clk_disable_unprepare(imxdi->clk);
diff --git a/drivers/rtc/rtc-mc13xxx.c b/drivers/rtc/rtc-mc13xxx.c
index 32df1d812367..a65868065743 100644
--- a/drivers/rtc/rtc-mc13xxx.c
+++ b/drivers/rtc/rtc-mc13xxx.c
@@ -216,7 +216,7 @@ static int mc13xxx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
s1970 = rtc_tm_to_time64(&alarm->time);
- dev_dbg(dev, "%s: o%2.s %lld\n", __func__, alarm->enabled ? "n" : "ff",
+ dev_dbg(dev, "%s: %s %lld\n", __func__, alarm->enabled ? "on" : "off",
(long long)s1970);
ret = mc13xxx_rtc_irq_enable_unlocked(dev, alarm->enabled,
diff --git a/drivers/rtc/rtc-mt6397.c b/drivers/rtc/rtc-mt6397.c
new file mode 100644
index 000000000000..c0090b698ff3
--- /dev/null
+++ b/drivers/rtc/rtc-mt6397.c
@@ -0,0 +1,395 @@
+/*
+* Copyright (c) 2014-2015 MediaTek Inc.
+* Author: Tianping.Fang <tianping.fang@mediatek.com>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 as
+* published by the Free Software Foundation.
+*
+* This program is distributed in the hope that 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.
+*/
+
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/rtc.h>
+#include <linux/irqdomain.h>
+#include <linux/platform_device.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/io.h>
+#include <linux/mfd/mt6397/core.h>
+
+#define RTC_BBPU 0x0000
+#define RTC_BBPU_CBUSY BIT(6)
+
+#define RTC_WRTGR 0x003c
+
+#define RTC_IRQ_STA 0x0002
+#define RTC_IRQ_STA_AL BIT(0)
+#define RTC_IRQ_STA_LP BIT(3)
+
+#define RTC_IRQ_EN 0x0004
+#define RTC_IRQ_EN_AL BIT(0)
+#define RTC_IRQ_EN_ONESHOT BIT(2)
+#define RTC_IRQ_EN_LP BIT(3)
+#define RTC_IRQ_EN_ONESHOT_AL (RTC_IRQ_EN_ONESHOT | RTC_IRQ_EN_AL)
+
+#define RTC_AL_MASK 0x0008
+#define RTC_AL_MASK_DOW BIT(4)
+
+#define RTC_TC_SEC 0x000a
+/* Min, Hour, Dom... register offset to RTC_TC_SEC */
+#define RTC_OFFSET_SEC 0
+#define RTC_OFFSET_MIN 1
+#define RTC_OFFSET_HOUR 2
+#define RTC_OFFSET_DOM 3
+#define RTC_OFFSET_DOW 4
+#define RTC_OFFSET_MTH 5
+#define RTC_OFFSET_YEAR 6
+#define RTC_OFFSET_COUNT 7
+
+#define RTC_AL_SEC 0x0018
+
+#define RTC_PDN2 0x002e
+#define RTC_PDN2_PWRON_ALARM BIT(4)
+
+#define RTC_MIN_YEAR 1968
+#define RTC_BASE_YEAR 1900
+#define RTC_NUM_YEARS 128
+#define RTC_MIN_YEAR_OFFSET (RTC_MIN_YEAR - RTC_BASE_YEAR)
+
+struct mt6397_rtc {
+ struct device *dev;
+ struct rtc_device *rtc_dev;
+ struct mutex lock;
+ struct regmap *regmap;
+ int irq;
+ u32 addr_base;
+};
+
+static int mtk_rtc_write_trigger(struct mt6397_rtc *rtc)
+{
+ unsigned long timeout = jiffies + HZ;
+ int ret;
+ u32 data;
+
+ ret = regmap_write(rtc->regmap, rtc->addr_base + RTC_WRTGR, 1);
+ if (ret < 0)
+ return ret;
+
+ while (1) {
+ ret = regmap_read(rtc->regmap, rtc->addr_base + RTC_BBPU,
+ &data);
+ if (ret < 0)
+ break;
+ if (!(data & RTC_BBPU_CBUSY))
+ break;
+ if (time_after(jiffies, timeout)) {
+ ret = -ETIMEDOUT;
+ break;
+ }
+ cpu_relax();
+ }
+
+ return ret;
+}
+
+static irqreturn_t mtk_rtc_irq_handler_thread(int irq, void *data)
+{
+ struct mt6397_rtc *rtc = data;
+ u32 irqsta, irqen;
+ int ret;
+
+ ret = regmap_read(rtc->regmap, rtc->addr_base + RTC_IRQ_STA, &irqsta);
+ if ((ret >= 0) && (irqsta & RTC_IRQ_STA_AL)) {
+ rtc_update_irq(rtc->rtc_dev, 1, RTC_IRQF | RTC_AF);
+ irqen = irqsta & ~RTC_IRQ_EN_AL;
+ mutex_lock(&rtc->lock);
+ if (regmap_write(rtc->regmap, rtc->addr_base + RTC_IRQ_EN,
+ irqen) < 0)
+ mtk_rtc_write_trigger(rtc);
+ mutex_unlock(&rtc->lock);
+
+ return IRQ_HANDLED;
+ }
+
+ return IRQ_NONE;
+}
+
+static int __mtk_rtc_read_time(struct mt6397_rtc *rtc,
+ struct rtc_time *tm, int *sec)
+{
+ int ret;
+ u16 data[RTC_OFFSET_COUNT];
+
+ mutex_lock(&rtc->lock);
+ ret = regmap_bulk_read(rtc->regmap, rtc->addr_base + RTC_TC_SEC,
+ data, RTC_OFFSET_COUNT);
+ if (ret < 0)
+ goto exit;
+
+ tm->tm_sec = data[RTC_OFFSET_SEC];
+ tm->tm_min = data[RTC_OFFSET_MIN];
+ tm->tm_hour = data[RTC_OFFSET_HOUR];
+ tm->tm_mday = data[RTC_OFFSET_DOM];
+ tm->tm_mon = data[RTC_OFFSET_MTH];
+ tm->tm_year = data[RTC_OFFSET_YEAR];
+
+ ret = regmap_read(rtc->regmap, rtc->addr_base + RTC_TC_SEC, sec);
+exit:
+ mutex_unlock(&rtc->lock);
+ return ret;
+}
+
+static int mtk_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+ time64_t time;
+ struct mt6397_rtc *rtc = dev_get_drvdata(dev);
+ int days, sec, ret;
+
+ do {
+ ret = __mtk_rtc_read_time(rtc, tm, &sec);
+ if (ret < 0)
+ goto exit;
+ } while (sec < tm->tm_sec);
+
+ /* HW register use 7 bits to store year data, minus
+ * RTC_MIN_YEAR_OFFSET before write year data to register, and plus
+ * RTC_MIN_YEAR_OFFSET back after read year from register
+ */
+ tm->tm_year += RTC_MIN_YEAR_OFFSET;
+
+ /* HW register start mon from one, but tm_mon start from zero. */
+ tm->tm_mon--;
+ time = rtc_tm_to_time64(tm);
+
+ /* rtc_tm_to_time64 covert Gregorian date to seconds since
+ * 01-01-1970 00:00:00, and this date is Thursday.
+ */
+ days = div_s64(time, 86400);
+ tm->tm_wday = (days + 4) % 7;
+
+exit:
+ return ret;
+}
+
+static int mtk_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+ struct mt6397_rtc *rtc = dev_get_drvdata(dev);
+ int ret;
+ u16 data[RTC_OFFSET_COUNT];
+
+ tm->tm_year -= RTC_MIN_YEAR_OFFSET;
+ tm->tm_mon++;
+
+ data[RTC_OFFSET_SEC] = tm->tm_sec;
+ data[RTC_OFFSET_MIN] = tm->tm_min;
+ data[RTC_OFFSET_HOUR] = tm->tm_hour;
+ data[RTC_OFFSET_DOM] = tm->tm_mday;
+ data[RTC_OFFSET_MTH] = tm->tm_mon;
+ data[RTC_OFFSET_YEAR] = tm->tm_year;
+
+ mutex_lock(&rtc->lock);
+ ret = regmap_bulk_write(rtc->regmap, rtc->addr_base + RTC_TC_SEC,
+ data, RTC_OFFSET_COUNT);
+ if (ret < 0)
+ goto exit;
+
+ /* Time register write to hardware after call trigger function */
+ ret = mtk_rtc_write_trigger(rtc);
+
+exit:
+ mutex_unlock(&rtc->lock);
+ return ret;
+}
+
+static int mtk_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
+{
+ struct rtc_time *tm = &alm->time;
+ struct mt6397_rtc *rtc = dev_get_drvdata(dev);
+ u32 irqen, pdn2;
+ int ret;
+ u16 data[RTC_OFFSET_COUNT];
+
+ mutex_lock(&rtc->lock);
+ ret = regmap_read(rtc->regmap, rtc->addr_base + RTC_IRQ_EN, &irqen);
+ if (ret < 0)
+ goto err_exit;
+ ret = regmap_read(rtc->regmap, rtc->addr_base + RTC_PDN2, &pdn2);
+ if (ret < 0)
+ goto err_exit;
+
+ ret = regmap_bulk_read(rtc->regmap, rtc->addr_base + RTC_AL_SEC,
+ data, RTC_OFFSET_COUNT);
+ if (ret < 0)
+ goto err_exit;
+
+ alm->enabled = !!(irqen & RTC_IRQ_EN_AL);
+ alm->pending = !!(pdn2 & RTC_PDN2_PWRON_ALARM);
+ mutex_unlock(&rtc->lock);
+
+ tm->tm_sec = data[RTC_OFFSET_SEC];
+ tm->tm_min = data[RTC_OFFSET_MIN];
+ tm->tm_hour = data[RTC_OFFSET_HOUR];
+ tm->tm_mday = data[RTC_OFFSET_DOM];
+ tm->tm_mon = data[RTC_OFFSET_MTH];
+ tm->tm_year = data[RTC_OFFSET_YEAR];
+
+ tm->tm_year += RTC_MIN_YEAR_OFFSET;
+ tm->tm_mon--;
+
+ return 0;
+err_exit:
+ mutex_unlock(&rtc->lock);
+ return ret;
+}
+
+static int mtk_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
+{
+ struct rtc_time *tm = &alm->time;
+ struct mt6397_rtc *rtc = dev_get_drvdata(dev);
+ int ret;
+ u16 data[RTC_OFFSET_COUNT];
+
+ tm->tm_year -= RTC_MIN_YEAR_OFFSET;
+ tm->tm_mon++;
+
+ data[RTC_OFFSET_SEC] = tm->tm_sec;
+ data[RTC_OFFSET_MIN] = tm->tm_min;
+ data[RTC_OFFSET_HOUR] = tm->tm_hour;
+ data[RTC_OFFSET_DOM] = tm->tm_mday;
+ data[RTC_OFFSET_MTH] = tm->tm_mon;
+ data[RTC_OFFSET_YEAR] = tm->tm_year;
+
+ mutex_lock(&rtc->lock);
+ if (alm->enabled) {
+ ret = regmap_bulk_write(rtc->regmap,
+ rtc->addr_base + RTC_AL_SEC,
+ data, RTC_OFFSET_COUNT);
+ if (ret < 0)
+ goto exit;
+ ret = regmap_write(rtc->regmap, rtc->addr_base + RTC_AL_MASK,
+ RTC_AL_MASK_DOW);
+ if (ret < 0)
+ goto exit;
+ ret = regmap_update_bits(rtc->regmap,
+ rtc->addr_base + RTC_IRQ_EN,
+ RTC_IRQ_EN_ONESHOT_AL,
+ RTC_IRQ_EN_ONESHOT_AL);
+ if (ret < 0)
+ goto exit;
+ } else {
+ ret = regmap_update_bits(rtc->regmap,
+ rtc->addr_base + RTC_IRQ_EN,
+ RTC_IRQ_EN_ONESHOT_AL, 0);
+ if (ret < 0)
+ goto exit;
+ }
+
+ /* All alarm time register write to hardware after calling
+ * mtk_rtc_write_trigger. This can avoid race condition if alarm
+ * occur happen during writing alarm time register.
+ */
+ ret = mtk_rtc_write_trigger(rtc);
+exit:
+ mutex_unlock(&rtc->lock);
+ return ret;
+}
+
+static struct rtc_class_ops mtk_rtc_ops = {
+ .read_time = mtk_rtc_read_time,
+ .set_time = mtk_rtc_set_time,
+ .read_alarm = mtk_rtc_read_alarm,
+ .set_alarm = mtk_rtc_set_alarm,
+};
+
+static int mtk_rtc_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ struct mt6397_chip *mt6397_chip = dev_get_drvdata(pdev->dev.parent);
+ struct mt6397_rtc *rtc;
+ int ret;
+
+ rtc = devm_kzalloc(&pdev->dev, sizeof(struct mt6397_rtc), GFP_KERNEL);
+ if (!rtc)
+ return -ENOMEM;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ rtc->addr_base = res->start;
+
+ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ rtc->irq = irq_create_mapping(mt6397_chip->irq_domain, res->start);
+ if (rtc->irq <= 0)
+ return -EINVAL;
+
+ rtc->regmap = mt6397_chip->regmap;
+ rtc->dev = &pdev->dev;
+ mutex_init(&rtc->lock);
+
+ platform_set_drvdata(pdev, rtc);
+
+ ret = request_threaded_irq(rtc->irq, NULL,
+ mtk_rtc_irq_handler_thread,
+ IRQF_ONESHOT | IRQF_TRIGGER_HIGH,
+ "mt6397-rtc", rtc);
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to request alarm IRQ: %d: %d\n",
+ rtc->irq, ret);
+ goto out_dispose_irq;
+ }
+
+ rtc->rtc_dev = rtc_device_register("mt6397-rtc", &pdev->dev,
+ &mtk_rtc_ops, THIS_MODULE);
+ if (IS_ERR(rtc->rtc_dev)) {
+ dev_err(&pdev->dev, "register rtc device failed\n");
+ ret = PTR_ERR(rtc->rtc_dev);
+ goto out_free_irq;
+ }
+
+ device_init_wakeup(&pdev->dev, 1);
+
+ return 0;
+
+out_free_irq:
+ free_irq(rtc->irq, rtc->rtc_dev);
+out_dispose_irq:
+ irq_dispose_mapping(rtc->irq);
+ return ret;
+}
+
+static int mtk_rtc_remove(struct platform_device *pdev)
+{
+ struct mt6397_rtc *rtc = platform_get_drvdata(pdev);
+
+ rtc_device_unregister(rtc->rtc_dev);
+ free_irq(rtc->irq, rtc->rtc_dev);
+ irq_dispose_mapping(rtc->irq);
+
+ return 0;
+}
+
+static const struct of_device_id mt6397_rtc_of_match[] = {
+ { .compatible = "mediatek,mt6397-rtc", },
+ { }
+};
+
+static struct platform_driver mtk_rtc_driver = {
+ .driver = {
+ .name = "mt6397-rtc",
+ .of_match_table = mt6397_rtc_of_match,
+ },
+ .probe = mtk_rtc_probe,
+ .remove = mtk_rtc_remove,
+};
+
+module_platform_driver(mtk_rtc_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Tianping Fang <tianping.fang@mediatek.com>");
+MODULE_DESCRIPTION("RTC Driver for MediaTek MT6397 PMIC");
+MODULE_ALIAS("platform:mt6397-rtc");
diff --git a/drivers/rtc/rtc-mxc.c b/drivers/rtc/rtc-mxc.c
index 09d422b9f7f7..5fc292c2dfdf 100644
--- a/drivers/rtc/rtc-mxc.c
+++ b/drivers/rtc/rtc-mxc.c
@@ -84,7 +84,7 @@ struct rtc_plat_data {
enum imx_rtc_type devtype;
};
-static struct platform_device_id imx_rtc_devtype[] = {
+static const struct platform_device_id imx_rtc_devtype[] = {
{
.name = "imx1-rtc",
.driver_data = IMX1_RTC,
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c
index 76cbad7a99d3..a0f832362199 100644
--- a/drivers/rtc/rtc-s3c.c
+++ b/drivers/rtc/rtc-s3c.c
@@ -772,18 +772,6 @@ static struct s3c_rtc_data const s3c6410_rtc_data = {
.disable = s3c6410_rtc_disable,
};
-static struct s3c_rtc_data const exynos3250_rtc_data = {
- .max_user_freq = 32768,
- .needs_src_clk = true,
- .irq_handler = s3c6410_rtc_irq,
- .set_freq = s3c6410_rtc_setfreq,
- .enable_tick = s3c6410_rtc_enable_tick,
- .save_tick_cnt = s3c6410_rtc_save_tick_cnt,
- .restore_tick_cnt = s3c6410_rtc_restore_tick_cnt,
- .enable = s3c24xx_rtc_enable,
- .disable = s3c6410_rtc_disable,
-};
-
static const struct of_device_id s3c_rtc_dt_match[] = {
{
.compatible = "samsung,s3c2410-rtc",
@@ -799,7 +787,7 @@ static const struct of_device_id s3c_rtc_dt_match[] = {
.data = (void *)&s3c6410_rtc_data,
}, {
.compatible = "samsung,exynos3250-rtc",
- .data = (void *)&exynos3250_rtc_data,
+ .data = (void *)&s3c6410_rtc_data,
},
{ /* sentinel */ },
};
diff --git a/include/linux/rtc.h b/include/linux/rtc.h
index 8dcf6825fa88..587017e7939c 100644
--- a/include/linux/rtc.h
+++ b/include/linux/rtc.h
@@ -101,8 +101,7 @@ struct rtc_timer {
/* flags */
#define RTC_DEV_BUSY 0
-struct rtc_device
-{
+struct rtc_device {
struct device dev;
struct module *owner;
@@ -198,10 +197,10 @@ int rtc_register(rtc_task_t *task);
int rtc_unregister(rtc_task_t *task);
int rtc_control(rtc_task_t *t, unsigned int cmd, unsigned long arg);
-void rtc_timer_init(struct rtc_timer *timer, void (*f)(void* p), void* data);
-int rtc_timer_start(struct rtc_device *rtc, struct rtc_timer* timer,
- ktime_t expires, ktime_t period);
-int rtc_timer_cancel(struct rtc_device *rtc, struct rtc_timer* timer);
+void rtc_timer_init(struct rtc_timer *timer, void (*f)(void *p), void *data);
+int rtc_timer_start(struct rtc_device *rtc, struct rtc_timer *timer,
+ ktime_t expires, ktime_t period);
+void rtc_timer_cancel(struct rtc_device *rtc, struct rtc_timer *timer);
void rtc_timer_do_work(struct work_struct *work);
static inline bool is_leap_year(unsigned int year)