From 248056457287afe742c5a81abd0bdd3ce002750d Mon Sep 17 00:00:00 2001 From: Amelie Delaunay Date: Thu, 19 Apr 2018 15:21:40 +0200 Subject: rtc: stm32: fix copyright and adopt SPDX identifier Fix copyright by removing "SA" and "for STMicroelectronics", not required. Adopt SPDX identifier. Signed-off-by: Amelie Delaunay Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-stm32.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers/rtc/rtc-stm32.c') diff --git a/drivers/rtc/rtc-stm32.c b/drivers/rtc/rtc-stm32.c index f25dabe8fd02..79d9e8673279 100644 --- a/drivers/rtc/rtc-stm32.c +++ b/drivers/rtc/rtc-stm32.c @@ -1,7 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0 /* - * Copyright (C) STMicroelectronics SA 2017 - * Author: Amelie Delaunay for STMicroelectronics. - * License terms: GNU General Public License (GPL), version 2 + * Copyright (C) STMicroelectronics 2017 + * Author: Amelie Delaunay */ #include -- cgit From d213217d213e0e5648448fc2a5da977a74dc6ad9 Mon Sep 17 00:00:00 2001 From: Amelie Delaunay Date: Thu, 19 Apr 2018 15:21:41 +0200 Subject: rtc: stm32: fix alarm interrupt flags by removing IRQF_TRIGGER_RISING RTC alarm interrupt is active high and already configured by device tree. So remove IRQF_TRIGGER_RISING from driver. Signed-off-by: Amelie Delaunay Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-stm32.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/rtc/rtc-stm32.c') diff --git a/drivers/rtc/rtc-stm32.c b/drivers/rtc/rtc-stm32.c index 79d9e8673279..6a060780f797 100644 --- a/drivers/rtc/rtc-stm32.c +++ b/drivers/rtc/rtc-stm32.c @@ -663,8 +663,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", -- cgit From 22cb47c1ea2040c0424073c9d67dd0e644334a7c Mon Sep 17 00:00:00 2001 From: Amelie Delaunay Date: Thu, 19 Apr 2018 15:21:43 +0200 Subject: rtc: stm32: get DBP register and mask from DT st, syscfg property RTC driver should not be aware of the PWR registers offset and bits position. Furthermore, we can imagine that DBP relative register and bit mask could change depending on the SoC. So this patch introduces 2 parameters, dbp_reg and dbp_mask, allowing to get PWR_CR and PWR_CR_DBP from device tree. And it prepares next RTC version, backup domain write protection is disabled only if needed. Signed-off-by: Amelie Delaunay Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-stm32.c | 59 +++++++++++++++++++++++++++++++------------------ 1 file changed, 37 insertions(+), 22 deletions(-) (limited to 'drivers/rtc/rtc-stm32.c') diff --git a/drivers/rtc/rtc-stm32.c b/drivers/rtc/rtc-stm32.c index 6a060780f797..de49b5b12951 100644 --- a/drivers/rtc/rtc-stm32.c +++ b/drivers/rtc/rtc-stm32.c @@ -85,23 +85,17 @@ #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) - struct stm32_rtc_data { bool has_pclk; + bool need_dbp; }; struct stm32_rtc { struct rtc_device *rtc_dev; void __iomem *base; struct regmap *dbp; + unsigned int dbp_reg; + unsigned int dbp_mask; struct stm32_rtc_data *data; struct clk *pclk; struct clk *rtc_ck; @@ -498,10 +492,12 @@ static const struct rtc_class_ops stm32_rtc_ops = { static const struct stm32_rtc_data stm32_rtc_data = { .has_pclk = false, + .need_dbp = true, }; static const struct stm32_rtc_data stm32h7_rtc_data = { .has_pclk = true, + .need_dbp = true, }; static const struct of_device_id stm32_rtc_of_match[] = { @@ -576,7 +572,6 @@ static int stm32_rtc_probe(struct platform_device *pdev) { struct stm32_rtc *rtc; struct resource *res; - const struct of_device_id *match; int ret; rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL); @@ -588,15 +583,31 @@ 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); + + 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); + } - 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", + 1, &rtc->dbp_reg); + if (ret) { + dev_err(&pdev->dev, "can't read DBP register offset\n"); + return ret; + } + + 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,7 +635,9 @@ 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 @@ -684,7 +697,8 @@ err: 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); device_init_wakeup(&pdev->dev, false); @@ -707,8 +721,9 @@ static int stm32_rtc_remove(struct platform_device *pdev) 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); device_init_wakeup(&pdev->dev, false); -- cgit From 819cbde5218689d33e0405ebe71bed07bc21f28e Mon Sep 17 00:00:00 2001 From: Amelie Delaunay Date: Thu, 17 May 2018 14:04:23 +0200 Subject: rtc: stm32: fix misspelling and misalignment issues This patch cleans the following checkpatch complaints: CHECK: 'initalized' may be misspelled - perhaps 'initialized'? #644: FILE: drivers/rtc/rtc-stm32.c:644: + * the calendar has been initalized or not. INITS flag is reset by a CHECK: Alignment should match open parenthesis #669: FILE: drivers/rtc/rtc-stm32.c:669: + rtc->rtc_dev = devm_rtc_device_register(&pdev->dev, pdev->name, + &stm32_rtc_ops, THIS_MODULE); Signed-off-by: Amelie Delaunay Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-stm32.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/rtc/rtc-stm32.c') diff --git a/drivers/rtc/rtc-stm32.c b/drivers/rtc/rtc-stm32.c index de49b5b12951..d41f8047bee4 100644 --- a/drivers/rtc/rtc-stm32.c +++ b/drivers/rtc/rtc-stm32.c @@ -641,7 +641,7 @@ static int stm32_rtc_probe(struct platform_device *pdev) /* * 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 @@ -666,7 +666,7 @@ static int stm32_rtc_probe(struct platform_device *pdev) "alarm won't be able to wake up the system"); 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", -- cgit From 02b0cc345c2a1b7f1c590796a02d84e49e51ded0 Mon Sep 17 00:00:00 2001 From: Amelie Delaunay Date: Thu, 17 May 2018 14:04:24 +0200 Subject: rtc: stm32: rework register management to prepare other version of RTC 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 Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-stm32.c | 184 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 127 insertions(+), 57 deletions(-) (limited to 'drivers/rtc/rtc-stm32.c') diff --git a/drivers/rtc/rtc-stm32.c b/drivers/rtc/rtc-stm32.c index d41f8047bee4..8254e38ec7cf 100644 --- a/drivers/rtc/rtc-stm32.c +++ b/drivers/rtc/rtc-stm32.c @@ -16,15 +16,6 @@ #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) @@ -85,7 +76,26 @@ #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); -- cgit From b72252b6580c9c7ad74644642378e2a9a86b2283 Mon Sep 17 00:00:00 2001 From: Amelie Delaunay Date: Thu, 17 May 2018 14:04:26 +0200 Subject: rtc: stm32: add stm32mp1 rtc support This patch adds support for stm32mp1 RTC. Some common registers with previous RTC version have a different offset. It is the case for Control Register (CR) and ALaRMA Register (ALRMAR). There are also new registers regarding event flags: now, Alarm event flag is in Status Register (SR) and write 1 in Status Clear Register (SCR) is required to clear the event. Signed-off-by: Amelie Delaunay Signed-off-by: Alexandre Belloni --- drivers/rtc/rtc-stm32.c | 103 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 89 insertions(+), 14 deletions(-) (limited to 'drivers/rtc/rtc-stm32.c') diff --git a/drivers/rtc/rtc-stm32.c b/drivers/rtc/rtc-stm32.c index 8254e38ec7cf..c5908cfea234 100644 --- a/drivers/rtc/rtc-stm32.c +++ b/drivers/rtc/rtc-stm32.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -39,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) @@ -71,21 +72,36 @@ #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 +/* Max STM32 RTC register offset is 0x3FC */ +#define UNDEF_REG 0xFFFF + struct stm32_rtc; struct stm32_rtc_registers { - u8 tr; - u8 dr; - u8 cr; - u8 isr; - u8 prer; - u8 alrmar; - u8 wpr; + u16 tr; + u16 dr; + u16 cr; + u16 isr; + u16 prer; + u16 alrmar; + u16 wpr; + u16 sr; + u16 scr; + u16 verr; }; struct stm32_rtc_events { @@ -98,6 +114,7 @@ struct stm32_rtc_data { void (*clear_events)(struct stm32_rtc *rtc, unsigned int flags); bool has_pclk; bool need_dbp; + bool has_wakeirq; }; struct stm32_rtc { @@ -110,6 +127,7 @@ struct stm32_rtc { 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) @@ -193,7 +211,7 @@ static irqreturn_t stm32_rtc_alarm_irq(int irq, void *dev_id) mutex_lock(&rtc->rtc_dev->ops_lock); - status = readl_relaxed(rtc->base + regs->isr); + status = readl_relaxed(rtc->base + regs->sr); cr = readl_relaxed(rtc->base + regs->cr); if ((status & evts->alra) && @@ -325,7 +343,7 @@ static int stm32_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) alrmar = readl_relaxed(rtc->base + regs->alrmar); cr = readl_relaxed(rtc->base + regs->cr); - status = readl_relaxed(rtc->base + regs->isr); + status = readl_relaxed(rtc->base + regs->sr); if (alrmar & STM32_RTC_ALRMXR_DATE_MASK) { /* @@ -533,6 +551,7 @@ static void stm32_rtc_clear_events(struct stm32_rtc *rtc, static const struct stm32_rtc_data stm32_rtc_data = { .has_pclk = false, .need_dbp = true, + .has_wakeirq = false, .regs = { .tr = 0x00, .dr = 0x04, @@ -541,6 +560,9 @@ static const struct stm32_rtc_data stm32_rtc_data = { .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, @@ -551,6 +573,7 @@ static const struct stm32_rtc_data stm32_rtc_data = { static const struct stm32_rtc_data stm32h7_rtc_data = { .has_pclk = true, .need_dbp = true, + .has_wakeirq = false, .regs = { .tr = 0x00, .dr = 0x04, @@ -559,6 +582,9 @@ static const struct stm32_rtc_data stm32h7_rtc_data = { .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, @@ -566,9 +592,41 @@ static const struct stm32_rtc_data stm32h7_rtc_data = { .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); @@ -727,12 +785,19 @@ 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); @@ -760,6 +825,14 @@ static int stm32_rtc_probe(struct platform_device *pdev) 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) @@ -769,6 +842,7 @@ err: 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; @@ -795,6 +869,7 @@ static int stm32_rtc_remove(struct platform_device *pdev) 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; -- cgit