Merge branch 'for-4.19/wiimote' into for-linus
[linux-2.6-microblaze.git] / drivers / rtc / rtc-stm32.c
index f25dabe..c5908cf 100644 (file)
@@ -1,7 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
- * Copyright (C) STMicroelectronics SA 2017
- * Author:  Amelie Delaunay <amelie.delaunay@st.com> for STMicroelectronics.
- * License terms:  GNU General Public License (GPL), version 2
+ * Copyright (C) STMicroelectronics 2017
+ * Author:  Amelie Delaunay <amelie.delaunay@st.com>
  */
 
 #include <linux/bcd.h>
 #include <linux/mfd/syscon.h>
 #include <linux/module.h>
 #include <linux/of_device.h>
+#include <linux/pm_wakeirq.h>
 #include <linux/regmap.h>
 #include <linux/rtc.h>
 
 #define DRIVER_NAME "stm32_rtc"
 
-/* STM32 RTC registers */
-#define STM32_RTC_TR           0x00
-#define STM32_RTC_DR           0x04
-#define STM32_RTC_CR           0x08
-#define STM32_RTC_ISR          0x0C
-#define STM32_RTC_PRER         0x10
-#define STM32_RTC_ALRMAR       0x1C
-#define STM32_RTC_WPR          0x24
-
 /* STM32_RTC_TR bit fields  */
 #define STM32_RTC_TR_SEC_SHIFT         0
 #define STM32_RTC_TR_SEC               GENMASK(6, 0)
@@ -48,7 +40,7 @@
 #define STM32_RTC_CR_ALRAE             BIT(8)
 #define STM32_RTC_CR_ALRAIE            BIT(12)
 
-/* STM32_RTC_ISR bit fields */
+/* STM32_RTC_ISR/STM32_RTC_ICSR bit fields */
 #define STM32_RTC_ISR_ALRAWF           BIT(0)
 #define STM32_RTC_ISR_INITS            BIT(4)
 #define STM32_RTC_ISR_RSF              BIT(5)
 #define STM32_RTC_ALRMXR_WDAY          GENMASK(27, 24)
 #define STM32_RTC_ALRMXR_DATE_MASK     BIT(31)
 
+/* STM32_RTC_SR/_SCR bit fields */
+#define STM32_RTC_SR_ALRA              BIT(0)
+
+/* STM32_RTC_VERR bit fields */
+#define STM32_RTC_VERR_MINREV_SHIFT    0
+#define STM32_RTC_VERR_MINREV          GENMASK(3, 0)
+#define STM32_RTC_VERR_MAJREV_SHIFT    4
+#define STM32_RTC_VERR_MAJREV          GENMASK(7, 4)
+
 /* STM32_RTC_WPR key constants */
 #define RTC_WPR_1ST_KEY                        0xCA
 #define RTC_WPR_2ND_KEY                        0x53
 #define RTC_WPR_WRONG_KEY              0xFF
 
-/*
- * RTC registers are protected against parasitic write access.
- * PWR_CR_DBP bit must be set to enable write access to RTC registers.
- */
-/* STM32_PWR_CR */
-#define PWR_CR                         0x00
-/* STM32_PWR_CR bit field */
-#define PWR_CR_DBP                     BIT(8)
+/* Max STM32 RTC register offset is 0x3FC */
+#define UNDEF_REG                      0xFFFF
+
+struct stm32_rtc;
+
+struct stm32_rtc_registers {
+       u16 tr;
+       u16 dr;
+       u16 cr;
+       u16 isr;
+       u16 prer;
+       u16 alrmar;
+       u16 wpr;
+       u16 sr;
+       u16 scr;
+       u16 verr;
+};
+
+struct stm32_rtc_events {
+       u32 alra;
+};
 
 struct stm32_rtc_data {
+       const struct stm32_rtc_registers regs;
+       const struct stm32_rtc_events events;
+       void (*clear_events)(struct stm32_rtc *rtc, unsigned int flags);
        bool has_pclk;
+       bool need_dbp;
+       bool has_wakeirq;
 };
 
 struct stm32_rtc {
        struct rtc_device *rtc_dev;
        void __iomem *base;
        struct regmap *dbp;
-       struct stm32_rtc_data *data;
+       unsigned int dbp_reg;
+       unsigned int dbp_mask;
        struct clk *pclk;
        struct clk *rtc_ck;
+       const struct stm32_rtc_data *data;
        int irq_alarm;
+       int wakeirq_alarm;
 };
 
 static void stm32_rtc_wpr_unlock(struct stm32_rtc *rtc)
 {
-       writel_relaxed(RTC_WPR_1ST_KEY, rtc->base + STM32_RTC_WPR);
-       writel_relaxed(RTC_WPR_2ND_KEY, rtc->base + STM32_RTC_WPR);
+       const struct stm32_rtc_registers *regs = &rtc->data->regs;
+
+       writel_relaxed(RTC_WPR_1ST_KEY, rtc->base + regs->wpr);
+       writel_relaxed(RTC_WPR_2ND_KEY, rtc->base + regs->wpr);
 }
 
 static void stm32_rtc_wpr_lock(struct stm32_rtc *rtc)
 {
-       writel_relaxed(RTC_WPR_WRONG_KEY, rtc->base + STM32_RTC_WPR);
+       const struct stm32_rtc_registers *regs = &rtc->data->regs;
+
+       writel_relaxed(RTC_WPR_WRONG_KEY, rtc->base + regs->wpr);
 }
 
 static int stm32_rtc_enter_init_mode(struct stm32_rtc *rtc)
 {
-       unsigned int isr = readl_relaxed(rtc->base + STM32_RTC_ISR);
+       const struct stm32_rtc_registers *regs = &rtc->data->regs;
+       unsigned int isr = readl_relaxed(rtc->base + regs->isr);
 
        if (!(isr & STM32_RTC_ISR_INITF)) {
                isr |= STM32_RTC_ISR_INIT;
-               writel_relaxed(isr, rtc->base + STM32_RTC_ISR);
+               writel_relaxed(isr, rtc->base + regs->isr);
 
                /*
                 * It takes around 2 rtc_ck clock cycles to enter in
@@ -134,7 +161,7 @@ static int stm32_rtc_enter_init_mode(struct stm32_rtc *rtc)
                 * 1MHz, we poll every 10 us with a timeout of 100ms.
                 */
                return readl_relaxed_poll_timeout_atomic(
-                                       rtc->base + STM32_RTC_ISR,
+                                       rtc->base + regs->isr,
                                        isr, (isr & STM32_RTC_ISR_INITF),
                                        10, 100000);
        }
@@ -144,40 +171,50 @@ static int stm32_rtc_enter_init_mode(struct stm32_rtc *rtc)
 
 static void stm32_rtc_exit_init_mode(struct stm32_rtc *rtc)
 {
-       unsigned int isr = readl_relaxed(rtc->base + STM32_RTC_ISR);
+       const struct stm32_rtc_registers *regs = &rtc->data->regs;
+       unsigned int isr = readl_relaxed(rtc->base + regs->isr);
 
        isr &= ~STM32_RTC_ISR_INIT;
-       writel_relaxed(isr, rtc->base + STM32_RTC_ISR);
+       writel_relaxed(isr, rtc->base + regs->isr);
 }
 
 static int stm32_rtc_wait_sync(struct stm32_rtc *rtc)
 {
-       unsigned int isr = readl_relaxed(rtc->base + STM32_RTC_ISR);
+       const struct stm32_rtc_registers *regs = &rtc->data->regs;
+       unsigned int isr = readl_relaxed(rtc->base + regs->isr);
 
        isr &= ~STM32_RTC_ISR_RSF;
-       writel_relaxed(isr, rtc->base + STM32_RTC_ISR);
+       writel_relaxed(isr, rtc->base + regs->isr);
 
        /*
         * Wait for RSF to be set to ensure the calendar registers are
         * synchronised, it takes around 2 rtc_ck clock cycles
         */
-       return readl_relaxed_poll_timeout_atomic(rtc->base + STM32_RTC_ISR,
+       return readl_relaxed_poll_timeout_atomic(rtc->base + regs->isr,
                                                 isr,
                                                 (isr & STM32_RTC_ISR_RSF),
                                                 10, 100000);
 }
 
+static void stm32_rtc_clear_event_flags(struct stm32_rtc *rtc,
+                                       unsigned int flags)
+{
+       rtc->data->clear_events(rtc, flags);
+}
+
 static irqreturn_t stm32_rtc_alarm_irq(int irq, void *dev_id)
 {
        struct stm32_rtc *rtc = (struct stm32_rtc *)dev_id;
-       unsigned int isr, cr;
+       const struct stm32_rtc_registers *regs = &rtc->data->regs;
+       const struct stm32_rtc_events *evts = &rtc->data->events;
+       unsigned int status, cr;
 
        mutex_lock(&rtc->rtc_dev->ops_lock);
 
-       isr = readl_relaxed(rtc->base + STM32_RTC_ISR);
-       cr = readl_relaxed(rtc->base + STM32_RTC_CR);
+       status = readl_relaxed(rtc->base + regs->sr);
+       cr = readl_relaxed(rtc->base + regs->cr);
 
-       if ((isr & STM32_RTC_ISR_ALRAF) &&
+       if ((status & evts->alra) &&
            (cr & STM32_RTC_CR_ALRAIE)) {
                /* Alarm A flag - Alarm interrupt */
                dev_dbg(&rtc->rtc_dev->dev, "Alarm occurred\n");
@@ -185,9 +222,8 @@ static irqreturn_t stm32_rtc_alarm_irq(int irq, void *dev_id)
                /* Pass event to the kernel */
                rtc_update_irq(rtc->rtc_dev, 1, RTC_IRQF | RTC_AF);
 
-               /* Clear event flag, otherwise new events won't be received */
-               writel_relaxed(isr & ~STM32_RTC_ISR_ALRAF,
-                              rtc->base + STM32_RTC_ISR);
+               /* Clear event flags, otherwise new events won't be received */
+               stm32_rtc_clear_event_flags(rtc, evts->alra);
        }
 
        mutex_unlock(&rtc->rtc_dev->ops_lock);
@@ -234,11 +270,12 @@ static void bcd2tm(struct rtc_time *tm)
 static int stm32_rtc_read_time(struct device *dev, struct rtc_time *tm)
 {
        struct stm32_rtc *rtc = dev_get_drvdata(dev);
+       const struct stm32_rtc_registers *regs = &rtc->data->regs;
        unsigned int tr, dr;
 
        /* Time and Date in BCD format */
-       tr = readl_relaxed(rtc->base + STM32_RTC_TR);
-       dr = readl_relaxed(rtc->base + STM32_RTC_DR);
+       tr = readl_relaxed(rtc->base + regs->tr);
+       dr = readl_relaxed(rtc->base + regs->dr);
 
        tm->tm_sec = (tr & STM32_RTC_TR_SEC) >> STM32_RTC_TR_SEC_SHIFT;
        tm->tm_min = (tr & STM32_RTC_TR_MIN) >> STM32_RTC_TR_MIN_SHIFT;
@@ -259,6 +296,7 @@ static int stm32_rtc_read_time(struct device *dev, struct rtc_time *tm)
 static int stm32_rtc_set_time(struct device *dev, struct rtc_time *tm)
 {
        struct stm32_rtc *rtc = dev_get_drvdata(dev);
+       const struct stm32_rtc_registers *regs = &rtc->data->regs;
        unsigned int tr, dr;
        int ret = 0;
 
@@ -283,8 +321,8 @@ static int stm32_rtc_set_time(struct device *dev, struct rtc_time *tm)
                goto end;
        }
 
-       writel_relaxed(tr, rtc->base + STM32_RTC_TR);
-       writel_relaxed(dr, rtc->base + STM32_RTC_DR);
+       writel_relaxed(tr, rtc->base + regs->tr);
+       writel_relaxed(dr, rtc->base + regs->dr);
 
        stm32_rtc_exit_init_mode(rtc);
 
@@ -298,12 +336,14 @@ end:
 static int stm32_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 {
        struct stm32_rtc *rtc = dev_get_drvdata(dev);
+       const struct stm32_rtc_registers *regs = &rtc->data->regs;
+       const struct stm32_rtc_events *evts = &rtc->data->events;
        struct rtc_time *tm = &alrm->time;
-       unsigned int alrmar, cr, isr;
+       unsigned int alrmar, cr, status;
 
-       alrmar = readl_relaxed(rtc->base + STM32_RTC_ALRMAR);
-       cr = readl_relaxed(rtc->base + STM32_RTC_CR);
-       isr = readl_relaxed(rtc->base + STM32_RTC_ISR);
+       alrmar = readl_relaxed(rtc->base + regs->alrmar);
+       cr = readl_relaxed(rtc->base + regs->cr);
+       status = readl_relaxed(rtc->base + regs->sr);
 
        if (alrmar & STM32_RTC_ALRMXR_DATE_MASK) {
                /*
@@ -356,7 +396,7 @@ static int stm32_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
        bcd2tm(tm);
 
        alrm->enabled = (cr & STM32_RTC_CR_ALRAE) ? 1 : 0;
-       alrm->pending = (isr & STM32_RTC_ISR_ALRAF) ? 1 : 0;
+       alrm->pending = (status & evts->alra) ? 1 : 0;
 
        return 0;
 }
@@ -364,9 +404,11 @@ static int stm32_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 static int stm32_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
 {
        struct stm32_rtc *rtc = dev_get_drvdata(dev);
-       unsigned int isr, cr;
+       const struct stm32_rtc_registers *regs = &rtc->data->regs;
+       const struct stm32_rtc_events *evts = &rtc->data->events;
+       unsigned int cr;
 
-       cr = readl_relaxed(rtc->base + STM32_RTC_CR);
+       cr = readl_relaxed(rtc->base + regs->cr);
 
        stm32_rtc_wpr_unlock(rtc);
 
@@ -375,12 +417,10 @@ static int stm32_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
                cr |= (STM32_RTC_CR_ALRAIE | STM32_RTC_CR_ALRAE);
        else
                cr &= ~(STM32_RTC_CR_ALRAIE | STM32_RTC_CR_ALRAE);
-       writel_relaxed(cr, rtc->base + STM32_RTC_CR);
+       writel_relaxed(cr, rtc->base + regs->cr);
 
-       /* Clear event flag, otherwise new events won't be received */
-       isr = readl_relaxed(rtc->base + STM32_RTC_ISR);
-       isr &= ~STM32_RTC_ISR_ALRAF;
-       writel_relaxed(isr, rtc->base + STM32_RTC_ISR);
+       /* Clear event flags, otherwise new events won't be received */
+       stm32_rtc_clear_event_flags(rtc, evts->alra);
 
        stm32_rtc_wpr_lock(rtc);
 
@@ -389,9 +429,10 @@ static int stm32_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
 
 static int stm32_rtc_valid_alrm(struct stm32_rtc *rtc, struct rtc_time *tm)
 {
+       const struct stm32_rtc_registers *regs = &rtc->data->regs;
        int cur_day, cur_mon, cur_year, cur_hour, cur_min, cur_sec;
-       unsigned int dr = readl_relaxed(rtc->base + STM32_RTC_DR);
-       unsigned int tr = readl_relaxed(rtc->base + STM32_RTC_TR);
+       unsigned int dr = readl_relaxed(rtc->base + regs->dr);
+       unsigned int tr = readl_relaxed(rtc->base + regs->tr);
 
        cur_day = (dr & STM32_RTC_DR_DATE) >> STM32_RTC_DR_DATE_SHIFT;
        cur_mon = (dr & STM32_RTC_DR_MONTH) >> STM32_RTC_DR_MONTH_SHIFT;
@@ -425,6 +466,7 @@ static int stm32_rtc_valid_alrm(struct stm32_rtc *rtc, struct rtc_time *tm)
 static int stm32_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 {
        struct stm32_rtc *rtc = dev_get_drvdata(dev);
+       const struct stm32_rtc_registers *regs = &rtc->data->regs;
        struct rtc_time *tm = &alrm->time;
        unsigned int cr, isr, alrmar;
        int ret = 0;
@@ -456,15 +498,15 @@ static int stm32_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
        stm32_rtc_wpr_unlock(rtc);
 
        /* Disable Alarm */
-       cr = readl_relaxed(rtc->base + STM32_RTC_CR);
+       cr = readl_relaxed(rtc->base + regs->cr);
        cr &= ~STM32_RTC_CR_ALRAE;
-       writel_relaxed(cr, rtc->base + STM32_RTC_CR);
+       writel_relaxed(cr, rtc->base + regs->cr);
 
        /*
         * Poll Alarm write flag to be sure that Alarm update is allowed: it
         * takes around 2 rtc_ck clock cycles
         */
-       ret = readl_relaxed_poll_timeout_atomic(rtc->base + STM32_RTC_ISR,
+       ret = readl_relaxed_poll_timeout_atomic(rtc->base + regs->isr,
                                                isr,
                                                (isr & STM32_RTC_ISR_ALRAWF),
                                                10, 100000);
@@ -475,7 +517,7 @@ static int stm32_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
        }
 
        /* Write to Alarm register */
-       writel_relaxed(alrmar, rtc->base + STM32_RTC_ALRMAR);
+       writel_relaxed(alrmar, rtc->base + regs->alrmar);
 
        if (alrm->enabled)
                stm32_rtc_alarm_irq_enable(dev, 1);
@@ -496,17 +538,95 @@ static const struct rtc_class_ops stm32_rtc_ops = {
        .alarm_irq_enable = stm32_rtc_alarm_irq_enable,
 };
 
+static void stm32_rtc_clear_events(struct stm32_rtc *rtc,
+                                  unsigned int flags)
+{
+       const struct stm32_rtc_registers *regs = &rtc->data->regs;
+
+       /* Flags are cleared by writing 0 in RTC_ISR */
+       writel_relaxed(readl_relaxed(rtc->base + regs->isr) & ~flags,
+                      rtc->base + regs->isr);
+}
+
 static const struct stm32_rtc_data stm32_rtc_data = {
        .has_pclk = false,
+       .need_dbp = true,
+       .has_wakeirq = false,
+       .regs = {
+               .tr = 0x00,
+               .dr = 0x04,
+               .cr = 0x08,
+               .isr = 0x0C,
+               .prer = 0x10,
+               .alrmar = 0x1C,
+               .wpr = 0x24,
+               .sr = 0x0C, /* set to ISR offset to ease alarm management */
+               .scr = UNDEF_REG,
+               .verr = UNDEF_REG,
+       },
+       .events = {
+               .alra = STM32_RTC_ISR_ALRAF,
+       },
+       .clear_events = stm32_rtc_clear_events,
 };
 
 static const struct stm32_rtc_data stm32h7_rtc_data = {
        .has_pclk = true,
+       .need_dbp = true,
+       .has_wakeirq = false,
+       .regs = {
+               .tr = 0x00,
+               .dr = 0x04,
+               .cr = 0x08,
+               .isr = 0x0C,
+               .prer = 0x10,
+               .alrmar = 0x1C,
+               .wpr = 0x24,
+               .sr = 0x0C, /* set to ISR offset to ease alarm management */
+               .scr = UNDEF_REG,
+               .verr = UNDEF_REG,
+       },
+       .events = {
+               .alra = STM32_RTC_ISR_ALRAF,
+       },
+       .clear_events = stm32_rtc_clear_events,
+};
+
+static void stm32mp1_rtc_clear_events(struct stm32_rtc *rtc,
+                                     unsigned int flags)
+{
+       struct stm32_rtc_registers regs = rtc->data->regs;
+
+       /* Flags are cleared by writing 1 in RTC_SCR */
+       writel_relaxed(flags, rtc->base + regs.scr);
+}
+
+static const struct stm32_rtc_data stm32mp1_data = {
+       .has_pclk = true,
+       .need_dbp = false,
+       .has_wakeirq = true,
+       .regs = {
+               .tr = 0x00,
+               .dr = 0x04,
+               .cr = 0x18,
+               .isr = 0x0C, /* named RTC_ICSR on stm32mp1 */
+               .prer = 0x10,
+               .alrmar = 0x40,
+               .wpr = 0x24,
+               .sr = 0x50,
+               .scr = 0x5C,
+               .verr = 0x3F4,
+       },
+       .events = {
+               .alra = STM32_RTC_SR_ALRA,
+       },
+       .clear_events = stm32mp1_rtc_clear_events,
 };
 
 static const struct of_device_id stm32_rtc_of_match[] = {
        { .compatible = "st,stm32-rtc", .data = &stm32_rtc_data },
        { .compatible = "st,stm32h7-rtc", .data = &stm32h7_rtc_data },
+       { .compatible = "st,stm32mp1-rtc", .data = &stm32mp1_data },
        {}
 };
 MODULE_DEVICE_TABLE(of, stm32_rtc_of_match);
@@ -514,6 +634,7 @@ MODULE_DEVICE_TABLE(of, stm32_rtc_of_match);
 static int stm32_rtc_init(struct platform_device *pdev,
                          struct stm32_rtc *rtc)
 {
+       const struct stm32_rtc_registers *regs = &rtc->data->regs;
        unsigned int prer, pred_a, pred_s, pred_a_max, pred_s_max, cr;
        unsigned int rate;
        int ret = 0;
@@ -554,14 +675,14 @@ static int stm32_rtc_init(struct platform_device *pdev,
        }
 
        prer = (pred_s << STM32_RTC_PRER_PRED_S_SHIFT) & STM32_RTC_PRER_PRED_S;
-       writel_relaxed(prer, rtc->base + STM32_RTC_PRER);
+       writel_relaxed(prer, rtc->base + regs->prer);
        prer |= (pred_a << STM32_RTC_PRER_PRED_A_SHIFT) & STM32_RTC_PRER_PRED_A;
-       writel_relaxed(prer, rtc->base + STM32_RTC_PRER);
+       writel_relaxed(prer, rtc->base + regs->prer);
 
        /* Force 24h time format */
-       cr = readl_relaxed(rtc->base + STM32_RTC_CR);
+       cr = readl_relaxed(rtc->base + regs->cr);
        cr &= ~STM32_RTC_CR_FMT;
-       writel_relaxed(cr, rtc->base + STM32_RTC_CR);
+       writel_relaxed(cr, rtc->base + regs->cr);
 
        stm32_rtc_exit_init_mode(rtc);
 
@@ -575,8 +696,8 @@ end:
 static int stm32_rtc_probe(struct platform_device *pdev)
 {
        struct stm32_rtc *rtc;
+       const struct stm32_rtc_registers *regs;
        struct resource *res;
-       const struct of_device_id *match;
        int ret;
 
        rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
@@ -588,15 +709,32 @@ static int stm32_rtc_probe(struct platform_device *pdev)
        if (IS_ERR(rtc->base))
                return PTR_ERR(rtc->base);
 
-       rtc->dbp = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
-                                                  "st,syscfg");
-       if (IS_ERR(rtc->dbp)) {
-               dev_err(&pdev->dev, "no st,syscfg\n");
-               return PTR_ERR(rtc->dbp);
-       }
+       rtc->data = (struct stm32_rtc_data *)
+                   of_device_get_match_data(&pdev->dev);
+       regs = &rtc->data->regs;
+
+       if (rtc->data->need_dbp) {
+               rtc->dbp = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
+                                                          "st,syscfg");
+               if (IS_ERR(rtc->dbp)) {
+                       dev_err(&pdev->dev, "no st,syscfg\n");
+                       return PTR_ERR(rtc->dbp);
+               }
+
+               ret = of_property_read_u32_index(pdev->dev.of_node, "st,syscfg",
+                                                1, &rtc->dbp_reg);
+               if (ret) {
+                       dev_err(&pdev->dev, "can't read DBP register offset\n");
+                       return ret;
+               }
 
-       match = of_match_device(stm32_rtc_of_match, &pdev->dev);
-       rtc->data = (struct stm32_rtc_data *)match->data;
+               ret = of_property_read_u32_index(pdev->dev.of_node, "st,syscfg",
+                                                2, &rtc->dbp_mask);
+               if (ret) {
+                       dev_err(&pdev->dev, "can't read DBP register mask\n");
+                       return ret;
+               }
+       }
 
        if (!rtc->data->has_pclk) {
                rtc->pclk = NULL;
@@ -624,11 +762,13 @@ static int stm32_rtc_probe(struct platform_device *pdev)
        if (ret)
                goto err;
 
-       regmap_update_bits(rtc->dbp, PWR_CR, PWR_CR_DBP, PWR_CR_DBP);
+       if (rtc->data->need_dbp)
+               regmap_update_bits(rtc->dbp, rtc->dbp_reg,
+                                  rtc->dbp_mask, rtc->dbp_mask);
 
        /*
         * After a system reset, RTC_ISR.INITS flag can be read to check if
-        * the calendar has been initalized or not. INITS flag is reset by a
+        * the calendar has been initialized or not. INITS flag is reset by a
         * power-on reset (no vbat, no power-supply). It is not reset if
         * rtc_ck parent clock has changed (so RTC prescalers need to be
         * changed). That's why we cannot rely on this flag to know if RTC
@@ -645,15 +785,22 @@ static int stm32_rtc_probe(struct platform_device *pdev)
                goto err;
        }
 
-       platform_set_drvdata(pdev, rtc);
-
        ret = device_init_wakeup(&pdev->dev, true);
+       if (rtc->data->has_wakeirq) {
+               rtc->wakeirq_alarm = platform_get_irq(pdev, 1);
+               if (rtc->wakeirq_alarm <= 0)
+                       ret = rtc->wakeirq_alarm;
+               else
+                       ret = dev_pm_set_dedicated_wake_irq(&pdev->dev,
+                                                           rtc->wakeirq_alarm);
+       }
        if (ret)
-               dev_warn(&pdev->dev,
-                        "alarm won't be able to wake up the system");
+               dev_warn(&pdev->dev, "alarm can't wake up the system: %d", ret);
+
+       platform_set_drvdata(pdev, rtc);
 
        rtc->rtc_dev = devm_rtc_device_register(&pdev->dev, pdev->name,
-                       &stm32_rtc_ops, THIS_MODULE);
+                                               &stm32_rtc_ops, THIS_MODULE);
        if (IS_ERR(rtc->rtc_dev)) {
                ret = PTR_ERR(rtc->rtc_dev);
                dev_err(&pdev->dev, "rtc device registration failed, err=%d\n",
@@ -663,8 +810,7 @@ static int stm32_rtc_probe(struct platform_device *pdev)
 
        /* Handle RTC alarm interrupts */
        ret = devm_request_threaded_irq(&pdev->dev, rtc->irq_alarm, NULL,
-                                       stm32_rtc_alarm_irq,
-                                       IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+                                       stm32_rtc_alarm_irq, IRQF_ONESHOT,
                                        pdev->name, rtc);
        if (ret) {
                dev_err(&pdev->dev, "IRQ%d (alarm interrupt) already claimed\n",
@@ -676,17 +822,27 @@ static int stm32_rtc_probe(struct platform_device *pdev)
         * If INITS flag is reset (calendar year field set to 0x00), calendar
         * must be initialized
         */
-       if (!(readl_relaxed(rtc->base + STM32_RTC_ISR) & STM32_RTC_ISR_INITS))
+       if (!(readl_relaxed(rtc->base + regs->isr) & STM32_RTC_ISR_INITS))
                dev_warn(&pdev->dev, "Date/Time must be initialized\n");
 
+       if (regs->verr != UNDEF_REG) {
+               u32 ver = readl_relaxed(rtc->base + regs->verr);
+
+               dev_info(&pdev->dev, "registered rev:%d.%d\n",
+                        (ver >> STM32_RTC_VERR_MAJREV_SHIFT) & 0xF,
+                        (ver >> STM32_RTC_VERR_MINREV_SHIFT) & 0xF);
+       }
+
        return 0;
 err:
        if (rtc->data->has_pclk)
                clk_disable_unprepare(rtc->pclk);
        clk_disable_unprepare(rtc->rtc_ck);
 
-       regmap_update_bits(rtc->dbp, PWR_CR, PWR_CR_DBP, 0);
+       if (rtc->data->need_dbp)
+               regmap_update_bits(rtc->dbp, rtc->dbp_reg, rtc->dbp_mask, 0);
 
+       dev_pm_clear_wake_irq(&pdev->dev);
        device_init_wakeup(&pdev->dev, false);
 
        return ret;
@@ -695,22 +851,25 @@ err:
 static int stm32_rtc_remove(struct platform_device *pdev)
 {
        struct stm32_rtc *rtc = platform_get_drvdata(pdev);
+       const struct stm32_rtc_registers *regs = &rtc->data->regs;
        unsigned int cr;
 
        /* Disable interrupts */
        stm32_rtc_wpr_unlock(rtc);
-       cr = readl_relaxed(rtc->base + STM32_RTC_CR);
+       cr = readl_relaxed(rtc->base + regs->cr);
        cr &= ~STM32_RTC_CR_ALRAIE;
-       writel_relaxed(cr, rtc->base + STM32_RTC_CR);
+       writel_relaxed(cr, rtc->base + regs->cr);
        stm32_rtc_wpr_lock(rtc);
 
        clk_disable_unprepare(rtc->rtc_ck);
        if (rtc->data->has_pclk)
                clk_disable_unprepare(rtc->pclk);
 
-       /* Enable backup domain write protection */
-       regmap_update_bits(rtc->dbp, PWR_CR, PWR_CR_DBP, 0);
+       /* Enable backup domain write protection if needed */
+       if (rtc->data->need_dbp)
+               regmap_update_bits(rtc->dbp, rtc->dbp_reg, rtc->dbp_mask, 0);
 
+       dev_pm_clear_wake_irq(&pdev->dev);
        device_init_wakeup(&pdev->dev, false);
 
        return 0;