rtc: stm32: rework register management to prepare other version of RTC
authorAmelie Delaunay <amelie.delaunay@st.com>
Thu, 17 May 2018 12:04:24 +0000 (14:04 +0200)
committerAlexandre Belloni <alexandre.belloni@bootlin.com>
Tue, 22 May 2018 18:10:52 +0000 (20:10 +0200)
This patch reworks register/bits management because next version of RTC
uses the same way of working but with different register's offset or bits
moved in new registers.

Signed-off-by: Amelie Delaunay <amelie.delaunay@st.com>
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
drivers/rtc/rtc-stm32.c

index d41f804..8254e38 100644 (file)
 
 #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)
 #define RTC_WPR_2ND_KEY                        0x53
 #define RTC_WPR_WRONG_KEY              0xFF
 
+struct stm32_rtc;
+
+struct stm32_rtc_registers {
+       u8 tr;
+       u8 dr;
+       u8 cr;
+       u8 isr;
+       u8 prer;
+       u8 alrmar;
+       u8 wpr;
+};
+
+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;
 };
@@ -96,30 +106,35 @@ struct stm32_rtc {
        struct regmap *dbp;
        unsigned int dbp_reg;
        unsigned int dbp_mask;
-       struct stm32_rtc_data *data;
        struct clk *pclk;
        struct clk *rtc_ck;
+       const struct stm32_rtc_data *data;
        int irq_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
@@ -128,7 +143,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);
        }
@@ -138,40 +153,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->isr);
+       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");
@@ -179,9 +204,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);
@@ -228,11 +252,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;
@@ -253,6 +278,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;
 
@@ -277,8 +303,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);
 
@@ -292,12 +318,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->isr);
 
        if (alrmar & STM32_RTC_ALRMXR_DATE_MASK) {
                /*
@@ -350,7 +378,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;
 }
@@ -358,9 +386,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);
 
@@ -369,12 +399,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);
 
@@ -383,9 +411,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;
@@ -419,6 +448,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;
@@ -450,15 +480,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);
@@ -469,7 +499,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);
@@ -490,14 +520,50 @@ 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,
+       .regs = {
+               .tr = 0x00,
+               .dr = 0x04,
+               .cr = 0x08,
+               .isr = 0x0C,
+               .prer = 0x10,
+               .alrmar = 0x1C,
+               .wpr = 0x24,
+       },
+       .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,
+       .regs = {
+               .tr = 0x00,
+               .dr = 0x04,
+               .cr = 0x08,
+               .isr = 0x0C,
+               .prer = 0x10,
+               .alrmar = 0x1C,
+               .wpr = 0x24,
+       },
+       .events = {
+               .alra = STM32_RTC_ISR_ALRAF,
+       },
+       .clear_events = stm32_rtc_clear_events,
 };
 
 static const struct of_device_id stm32_rtc_of_match[] = {
@@ -510,6 +576,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;
@@ -550,14 +617,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);
 
@@ -571,6 +638,7 @@ end:
 static int stm32_rtc_probe(struct platform_device *pdev)
 {
        struct stm32_rtc *rtc;
+       const struct stm32_rtc_registers *regs;
        struct resource *res;
        int ret;
 
@@ -585,6 +653,7 @@ static int stm32_rtc_probe(struct platform_device *pdev)
 
        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,
@@ -688,7 +757,7 @@ 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");
 
        return 0;
@@ -708,13 +777,14 @@ 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);