LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
* [PATCH v2 0/3] Introduce STM32MP1 RTC
@ 2018-05-09 15:46 Amelie Delaunay
2018-05-09 15:46 ` [PATCH v2 1/3] rtc: stm32: rework register management to prepare other version of RTC Amelie Delaunay
` (2 more replies)
0 siblings, 3 replies; 9+ messages in thread
From: Amelie Delaunay @ 2018-05-09 15:46 UTC (permalink / raw)
To: Alessandro Zummo, Alexandre Belloni, Rob Herring, Mark Rutland,
Maxime Coquelin, Alexandre Torgue
Cc: linux-rtc, devicetree, linux-arm-kernel, linux-kernel, Amelie Delaunay
This series introduces STM32MP1 RTC.
On STM32MP1:
- two clocks are needed, plck and rtc_ck;
- to wakeup the system, a wakeup alarm interrupt is needed;
- some registers or bits have moved, but the operation is the same;
- the Backup Domain Protection (DBP) is not managed by RTC driver.
---
Changes in v2:
* One compatible per line in bindings file
* Remove unnecessary comment under rtc_ck as this clock is required for all
* Remove interrupts-extended and add stm32mp1 rtc alarm wakeup interrupt in
interrupts property description
Amelie Delaunay (3):
rtc: stm32: rework register management to prepare other version of RTC
dt-bindings: rtc: update stm32-rtc documentation for stm32mp1 rtc
rtc: stm32: add stm32mp1 rtc support
.../devicetree/bindings/rtc/st,stm32-rtc.txt | 27 +-
drivers/rtc/rtc-stm32.c | 272 ++++++++++++++++-----
2 files changed, 228 insertions(+), 71 deletions(-)
--
2.7.4
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v2 1/3] rtc: stm32: rework register management to prepare other version of RTC
2018-05-09 15:46 [PATCH v2 0/3] Introduce STM32MP1 RTC Amelie Delaunay
@ 2018-05-09 15:46 ` Amelie Delaunay
2018-05-16 20:25 ` Alexandre Belloni
2018-05-09 15:46 ` [PATCH v2 2/3] dt-bindings: rtc: update stm32-rtc documentation for stm32mp1 rtc Amelie Delaunay
2018-05-09 15:46 ` [PATCH v2 3/3] rtc: stm32: add stm32mp1 rtc support Amelie Delaunay
2 siblings, 1 reply; 9+ messages in thread
From: Amelie Delaunay @ 2018-05-09 15:46 UTC (permalink / raw)
To: Alessandro Zummo, Alexandre Belloni, Rob Herring, Mark Rutland,
Maxime Coquelin, Alexandre Torgue
Cc: linux-rtc, devicetree, linux-arm-kernel, linux-kernel, Amelie Delaunay
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>
---
drivers/rtc/rtc-stm32.c | 188 +++++++++++++++++++++++++++++++++---------------
1 file changed, 129 insertions(+), 59 deletions(-)
diff --git a/drivers/rtc/rtc-stm32.c b/drivers/rtc/rtc-stm32.c
index de49b5b..52ee027 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);
+ 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);
+ 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);
+ 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);
+ 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);
+ 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;
+ struct stm32_rtc_registers regs = rtc->data->regs;
+ 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);
+ 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);
+ 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 @@ static int stm32_rtc_set_time(struct device *dev, struct rtc_time *tm)
static int stm32_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
{
struct stm32_rtc *rtc = dev_get_drvdata(dev);
+ struct stm32_rtc_registers regs = rtc->data->regs;
+ 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;
+ struct stm32_rtc_registers regs = rtc->data->regs;
+ 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)
{
+ 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);
+ 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)
+{
+ 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)
{
+ 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 @@ static int stm32_rtc_init(struct platform_device *pdev,
static int stm32_rtc_probe(struct platform_device *pdev)
{
struct stm32_rtc *rtc;
+ 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,
@@ -641,7 +710,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 +735,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",
@@ -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 @@ static int stm32_rtc_probe(struct platform_device *pdev)
static int stm32_rtc_remove(struct platform_device *pdev)
{
struct stm32_rtc *rtc = platform_get_drvdata(pdev);
+ 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);
--
2.7.4
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v2 2/3] dt-bindings: rtc: update stm32-rtc documentation for stm32mp1 rtc
2018-05-09 15:46 [PATCH v2 0/3] Introduce STM32MP1 RTC Amelie Delaunay
2018-05-09 15:46 ` [PATCH v2 1/3] rtc: stm32: rework register management to prepare other version of RTC Amelie Delaunay
@ 2018-05-09 15:46 ` Amelie Delaunay
2018-05-09 15:46 ` [PATCH v2 3/3] rtc: stm32: add stm32mp1 rtc support Amelie Delaunay
2 siblings, 0 replies; 9+ messages in thread
From: Amelie Delaunay @ 2018-05-09 15:46 UTC (permalink / raw)
To: Alessandro Zummo, Alexandre Belloni, Rob Herring, Mark Rutland,
Maxime Coquelin, Alexandre Torgue
Cc: linux-rtc, devicetree, linux-arm-kernel, linux-kernel, Amelie Delaunay
RTC embedded in stm32mp1 SoC is slightly different from stm32h7 one, it
doesn't require to disable backup domain write protection, and rtc_ck
parent clock assignment isn't allowed.
To sum up, stm32mp1 RTC requires 2 clocks, pclk and rtc_ck, and an RTC
alarm interrupt.
Signed-off-by: Amelie Delaunay <amelie.delaunay@st.com>
---
.../devicetree/bindings/rtc/st,stm32-rtc.txt | 27 ++++++++++++++++------
1 file changed, 20 insertions(+), 7 deletions(-)
diff --git a/Documentation/devicetree/bindings/rtc/st,stm32-rtc.txt b/Documentation/devicetree/bindings/rtc/st,stm32-rtc.txt
index 00f8b5d..c920e27 100644
--- a/Documentation/devicetree/bindings/rtc/st,stm32-rtc.txt
+++ b/Documentation/devicetree/bindings/rtc/st,stm32-rtc.txt
@@ -1,25 +1,29 @@
STM32 Real Time Clock
Required properties:
-- compatible: can be either "st,stm32-rtc" or "st,stm32h7-rtc", depending on
- the device is compatible with stm32(f4/f7) or stm32h7.
+- compatible: can be one of the following:
+ - "st,stm32-rtc" for devices compatible with stm32(f4/f7).
+ - "st,stm32h7-rtc" for devices compatible with stm32h7.
+ - "st,stm32mp1-rtc" for devices compatible with stm32mp1.
- reg: address range of rtc register set.
- clocks: can use up to two clocks, depending on part used:
- "rtc_ck": RTC clock source.
- It is required on stm32(f4/f7) and stm32h7.
- "pclk": RTC APB interface clock.
It is not present on stm32(f4/f7).
- It is required on stm32h7.
+ It is required on stm32(h7/mp1).
- clock-names: must be "rtc_ck" and "pclk".
- It is required only on stm32h7.
+ It is required on stm32(h7/mp1).
- interrupt-parent: phandle for the interrupt controller.
-- interrupts: rtc alarm interrupt.
+ It is required on stm32(f4/f7/h7).
+- interrupts: rtc alarm interrupt. On stm32mp1, a second interrupt is required
+ for rtc alarm wakeup interrupt.
- st,syscfg: phandle/offset/mask triplet. The phandle to pwrcfg used to
access control register at offset, and change the dbp (Disable Backup
Protection) bit represented by the mask, mandatory to disable/enable backup
domain (RTC registers) write protection.
+ It is required on stm32(f4/f7/h7).
-Optional properties (to override default rtc_ck parent clock):
+Optional properties (to override default rtc_ck parent clock on stm32(f4/f7/h7):
- assigned-clocks: reference to the rtc_ck clock entry.
- assigned-clock-parents: phandle of the new parent clock of rtc_ck.
@@ -48,3 +52,12 @@ Example:
interrupt-names = "alarm";
st,syscfg = <&pwrcfg 0x00 0x100>;
};
+
+ rtc: rtc@5c004000 {
+ compatible = "st,stm32mp1-rtc";
+ reg = <0x5c004000 0x400>;
+ clocks = <&rcc RTCAPB>, <&rcc RTC>;
+ clock-names = "pclk", "rtc_ck";
+ interrupts-extended = <&intc GIC_SPI 3 IRQ_TYPE_NONE>,
+ <&exti 19 1>;
+ };
--
2.7.4
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v2 3/3] rtc: stm32: add stm32mp1 rtc support
2018-05-09 15:46 [PATCH v2 0/3] Introduce STM32MP1 RTC Amelie Delaunay
2018-05-09 15:46 ` [PATCH v2 1/3] rtc: stm32: rework register management to prepare other version of RTC Amelie Delaunay
2018-05-09 15:46 ` [PATCH v2 2/3] dt-bindings: rtc: update stm32-rtc documentation for stm32mp1 rtc Amelie Delaunay
@ 2018-05-09 15:46 ` Amelie Delaunay
2018-05-10 11:40 ` kbuild test robot
2018-05-16 20:32 ` Alexandre Belloni
2 siblings, 2 replies; 9+ messages in thread
From: Amelie Delaunay @ 2018-05-09 15:46 UTC (permalink / raw)
To: Alessandro Zummo, Alexandre Belloni, Rob Herring, Mark Rutland,
Maxime Coquelin, Alexandre Torgue
Cc: linux-rtc, devicetree, linux-arm-kernel, linux-kernel, Amelie Delaunay
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 <amelie.delaunay@st.com>
---
drivers/rtc/rtc-stm32.c | 88 +++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 81 insertions(+), 7 deletions(-)
diff --git a/drivers/rtc/rtc-stm32.c b/drivers/rtc/rtc-stm32.c
index 52ee027..45e0175 100644
--- a/drivers/rtc/rtc-stm32.c
+++ b/drivers/rtc/rtc-stm32.c
@@ -11,6 +11,7 @@
#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>
@@ -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,11 +72,22 @@
#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
+#define UNDEF_REG ~0
+
struct stm32_rtc;
struct stm32_rtc_registers {
@@ -86,6 +98,9 @@ struct stm32_rtc_registers {
u8 prer;
u8 alrmar;
u8 wpr;
+ u8 sr;
+ u8 scr;
+ u16 verr;
};
struct stm32_rtc_events {
@@ -98,6 +113,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 +126,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 +210,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 +342,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 +550,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 +559,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 +572,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 +581,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 +591,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 +784,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 +824,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 +841,7 @@ static int stm32_rtc_probe(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 ret;
@@ -795,6 +868,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;
--
2.7.4
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH v2 3/3] rtc: stm32: add stm32mp1 rtc support
2018-05-09 15:46 ` [PATCH v2 3/3] rtc: stm32: add stm32mp1 rtc support Amelie Delaunay
@ 2018-05-10 11:40 ` kbuild test robot
2018-05-16 20:32 ` Alexandre Belloni
1 sibling, 0 replies; 9+ messages in thread
From: kbuild test robot @ 2018-05-10 11:40 UTC (permalink / raw)
To: Amelie Delaunay
Cc: kbuild-all, Alessandro Zummo, Alexandre Belloni, Rob Herring,
Mark Rutland, Maxime Coquelin, Alexandre Torgue, linux-rtc,
devicetree, linux-arm-kernel, linux-kernel, Amelie Delaunay
Hi Amelie,
Thank you for the patch! Perhaps something to improve:
[auto build test WARNING on abelloni/rtc-next]
[also build test WARNING on next-20180510]
[cannot apply to v4.17-rc4]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Amelie-Delaunay/Introduce-STM32MP1-RTC/20180510-054013
base: https://git.kernel.org/pub/scm/linux/kernel/git/abelloni/linux.git rtc-next
smatch warnings:
drivers/rtc/rtc-stm32.c:827 stm32_rtc_probe() warn: always true condition '(regs.verr != ~0) => (0-u16max != (-1))'
vim +827 drivers/rtc/rtc-stm32.c
694
695 static int stm32_rtc_probe(struct platform_device *pdev)
696 {
697 struct stm32_rtc *rtc;
698 struct stm32_rtc_registers regs;
699 struct resource *res;
700 int ret;
701
702 rtc = devm_kzalloc(&pdev->dev, sizeof(*rtc), GFP_KERNEL);
703 if (!rtc)
704 return -ENOMEM;
705
706 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
707 rtc->base = devm_ioremap_resource(&pdev->dev, res);
708 if (IS_ERR(rtc->base))
709 return PTR_ERR(rtc->base);
710
711 rtc->data = (struct stm32_rtc_data *)
712 of_device_get_match_data(&pdev->dev);
713 regs = rtc->data->regs;
714
715 if (rtc->data->need_dbp) {
716 rtc->dbp = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
717 "st,syscfg");
718 if (IS_ERR(rtc->dbp)) {
719 dev_err(&pdev->dev, "no st,syscfg\n");
720 return PTR_ERR(rtc->dbp);
721 }
722
723 ret = of_property_read_u32_index(pdev->dev.of_node, "st,syscfg",
724 1, &rtc->dbp_reg);
725 if (ret) {
726 dev_err(&pdev->dev, "can't read DBP register offset\n");
727 return ret;
728 }
729
730 ret = of_property_read_u32_index(pdev->dev.of_node, "st,syscfg",
731 2, &rtc->dbp_mask);
732 if (ret) {
733 dev_err(&pdev->dev, "can't read DBP register mask\n");
734 return ret;
735 }
736 }
737
738 if (!rtc->data->has_pclk) {
739 rtc->pclk = NULL;
740 rtc->rtc_ck = devm_clk_get(&pdev->dev, NULL);
741 } else {
742 rtc->pclk = devm_clk_get(&pdev->dev, "pclk");
743 if (IS_ERR(rtc->pclk)) {
744 dev_err(&pdev->dev, "no pclk clock");
745 return PTR_ERR(rtc->pclk);
746 }
747 rtc->rtc_ck = devm_clk_get(&pdev->dev, "rtc_ck");
748 }
749 if (IS_ERR(rtc->rtc_ck)) {
750 dev_err(&pdev->dev, "no rtc_ck clock");
751 return PTR_ERR(rtc->rtc_ck);
752 }
753
754 if (rtc->data->has_pclk) {
755 ret = clk_prepare_enable(rtc->pclk);
756 if (ret)
757 return ret;
758 }
759
760 ret = clk_prepare_enable(rtc->rtc_ck);
761 if (ret)
762 goto err;
763
764 if (rtc->data->need_dbp)
765 regmap_update_bits(rtc->dbp, rtc->dbp_reg,
766 rtc->dbp_mask, rtc->dbp_mask);
767
768 /*
769 * After a system reset, RTC_ISR.INITS flag can be read to check if
770 * the calendar has been initialized or not. INITS flag is reset by a
771 * power-on reset (no vbat, no power-supply). It is not reset if
772 * rtc_ck parent clock has changed (so RTC prescalers need to be
773 * changed). That's why we cannot rely on this flag to know if RTC
774 * init has to be done.
775 */
776 ret = stm32_rtc_init(pdev, rtc);
777 if (ret)
778 goto err;
779
780 rtc->irq_alarm = platform_get_irq(pdev, 0);
781 if (rtc->irq_alarm <= 0) {
782 dev_err(&pdev->dev, "no alarm irq\n");
783 ret = rtc->irq_alarm;
784 goto err;
785 }
786
787 ret = device_init_wakeup(&pdev->dev, true);
788 if (rtc->data->has_wakeirq) {
789 rtc->wakeirq_alarm = platform_get_irq(pdev, 1);
790 if (rtc->wakeirq_alarm <= 0)
791 ret = rtc->wakeirq_alarm;
792 else
793 ret = dev_pm_set_dedicated_wake_irq(&pdev->dev,
794 rtc->wakeirq_alarm);
795 }
796 if (ret)
797 dev_warn(&pdev->dev, "alarm can't wake up the system: %d", ret);
798
799 platform_set_drvdata(pdev, rtc);
800
801 rtc->rtc_dev = devm_rtc_device_register(&pdev->dev, pdev->name,
802 &stm32_rtc_ops, THIS_MODULE);
803 if (IS_ERR(rtc->rtc_dev)) {
804 ret = PTR_ERR(rtc->rtc_dev);
805 dev_err(&pdev->dev, "rtc device registration failed, err=%d\n",
806 ret);
807 goto err;
808 }
809
810 /* Handle RTC alarm interrupts */
811 ret = devm_request_threaded_irq(&pdev->dev, rtc->irq_alarm, NULL,
812 stm32_rtc_alarm_irq, IRQF_ONESHOT,
813 pdev->name, rtc);
814 if (ret) {
815 dev_err(&pdev->dev, "IRQ%d (alarm interrupt) already claimed\n",
816 rtc->irq_alarm);
817 goto err;
818 }
819
820 /*
821 * If INITS flag is reset (calendar year field set to 0x00), calendar
822 * must be initialized
823 */
824 if (!(readl_relaxed(rtc->base + regs.isr) & STM32_RTC_ISR_INITS))
825 dev_warn(&pdev->dev, "Date/Time must be initialized\n");
826
> 827 if (regs.verr != UNDEF_REG) {
828 u32 ver = readl_relaxed(rtc->base + regs.verr);
829
830 dev_info(&pdev->dev, "registered rev:%d.%d\n",
831 (ver >> STM32_RTC_VERR_MAJREV_SHIFT) & 0xF,
832 (ver >> STM32_RTC_VERR_MINREV_SHIFT) & 0xF);
833 }
834
835 return 0;
836 err:
837 if (rtc->data->has_pclk)
838 clk_disable_unprepare(rtc->pclk);
839 clk_disable_unprepare(rtc->rtc_ck);
840
841 if (rtc->data->need_dbp)
842 regmap_update_bits(rtc->dbp, rtc->dbp_reg, rtc->dbp_mask, 0);
843
844 dev_pm_clear_wake_irq(&pdev->dev);
845 device_init_wakeup(&pdev->dev, false);
846
847 return ret;
848 }
849
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v2 1/3] rtc: stm32: rework register management to prepare other version of RTC
2018-05-09 15:46 ` [PATCH v2 1/3] rtc: stm32: rework register management to prepare other version of RTC Amelie Delaunay
@ 2018-05-16 20:25 ` Alexandre Belloni
2018-05-17 10:01 ` Amelie DELAUNAY
0 siblings, 1 reply; 9+ messages in thread
From: Alexandre Belloni @ 2018-05-16 20:25 UTC (permalink / raw)
To: Amelie Delaunay
Cc: Alessandro Zummo, Rob Herring, Mark Rutland, Maxime Coquelin,
Alexandre Torgue, linux-rtc, devicetree, linux-arm-kernel,
linux-kernel
Hi,
On 09/05/2018 17:46:08+0200, Amelie Delaunay wrote:
> 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);
> + struct stm32_rtc_registers regs = rtc->data->regs;
regs should probably be a pointer to ensure that no copy is made. I've
actually checked and it doesn't make a difference because gcc is smart
enough to not make the copy.
> +
> + writel_relaxed(RTC_WPR_1ST_KEY, rtc->base + regs.wpr);
> + writel_relaxed(RTC_WPR_2ND_KEY, rtc->base + regs.wpr);
> }
>
...
> 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;
> + struct stm32_rtc_registers regs = rtc->data->regs;
> + struct stm32_rtc_events evts = rtc->data->events;
Ditto for evts.
> + 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");
...
> @@ -641,7 +710,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 +735,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",
Those two changes should go into a separate cleanup patch.
--
Alexandre Belloni, Bootlin (formerly Free Electrons)
Embedded Linux and Kernel engineering
https://bootlin.com
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v2 3/3] rtc: stm32: add stm32mp1 rtc support
2018-05-09 15:46 ` [PATCH v2 3/3] rtc: stm32: add stm32mp1 rtc support Amelie Delaunay
2018-05-10 11:40 ` kbuild test robot
@ 2018-05-16 20:32 ` Alexandre Belloni
2018-05-17 10:03 ` Amelie DELAUNAY
1 sibling, 1 reply; 9+ messages in thread
From: Alexandre Belloni @ 2018-05-16 20:32 UTC (permalink / raw)
To: Amelie Delaunay
Cc: Alessandro Zummo, Rob Herring, Mark Rutland, Maxime Coquelin,
Alexandre Torgue, linux-rtc, devicetree, linux-arm-kernel,
linux-kernel
On 09/05/2018 17:46:10+0200, Amelie Delaunay wrote:
> struct stm32_rtc_registers {
> @@ -86,6 +98,9 @@ struct stm32_rtc_registers {
> u8 prer;
> u8 alrmar;
> u8 wpr;
> + u8 sr;
> + u8 scr;
> + u16 verr;
All those offsets should probably be u16 or u32...
> + if (regs.verr != UNDEF_REG) {
...else, this is not working, as reported by kbuild
> + 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);
> + }
> +
--
Alexandre Belloni, Bootlin (formerly Free Electrons)
Embedded Linux and Kernel engineering
https://bootlin.com
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v2 1/3] rtc: stm32: rework register management to prepare other version of RTC
2018-05-16 20:25 ` Alexandre Belloni
@ 2018-05-17 10:01 ` Amelie DELAUNAY
0 siblings, 0 replies; 9+ messages in thread
From: Amelie DELAUNAY @ 2018-05-17 10:01 UTC (permalink / raw)
To: Alexandre Belloni
Cc: Alessandro Zummo, Rob Herring, Mark Rutland, Maxime Coquelin,
Alexandre TORGUE, linux-rtc, devicetree, linux-arm-kernel,
linux-kernel
Hi,
On 05/16/2018 10:25 PM, Alexandre Belloni wrote:
> Hi,
>
> On 09/05/2018 17:46:08+0200, Amelie Delaunay wrote:
>> 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);
>> + struct stm32_rtc_registers regs = rtc->data->regs;
>
> regs should probably be a pointer to ensure that no copy is made. I've
> actually checked and it doesn't make a difference because gcc is smart
> enough to not make the copy.
>
...
>> 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;
>> + struct stm32_rtc_registers regs = rtc->data->regs;
>> + struct stm32_rtc_events evts = rtc->data->events;
>
> Ditto for evts.
>
I prepare a v3 with const struct stm32_rtc_registers *regs and const
struct stm32_rtc_events *evts.
>> + 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");
>
> ...
>
>> @@ -641,7 +710,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 +735,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",
>
> Those two changes should go into a separate cleanup patch.
>
OK, new patch for these two changes in v3.
Thanks for reviewing,
Amelie
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v2 3/3] rtc: stm32: add stm32mp1 rtc support
2018-05-16 20:32 ` Alexandre Belloni
@ 2018-05-17 10:03 ` Amelie DELAUNAY
0 siblings, 0 replies; 9+ messages in thread
From: Amelie DELAUNAY @ 2018-05-17 10:03 UTC (permalink / raw)
To: Alexandre Belloni
Cc: Alessandro Zummo, Rob Herring, Mark Rutland, Maxime Coquelin,
Alexandre TORGUE, linux-rtc, devicetree, linux-arm-kernel,
linux-kernel
On 05/16/2018 10:32 PM, Alexandre Belloni wrote:
> On 09/05/2018 17:46:10+0200, Amelie Delaunay wrote:
>> struct stm32_rtc_registers {
>> @@ -86,6 +98,9 @@ struct stm32_rtc_registers {
>> u8 prer;
>> u8 alrmar;
>> u8 wpr;
>> + u8 sr;
>> + u8 scr;
>> + u16 verr;
>
> All those offsets should probably be u16 or u32...
>
OK, those offsets will be all u16 in v3, the maximum STM32 RTC register
offset value being 0x3FC.
>> + if (regs.verr != UNDEF_REG) {
>
> ...else, this is not working, as reported by kbuild
>
Yes, in v3, UNDEF_REG will be the maximum u16 value (0xFFFF) instead of ~0.
>> + 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);
>> + }
>> +
>
Thanks,
Amelie
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2018-05-17 10:04 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-05-09 15:46 [PATCH v2 0/3] Introduce STM32MP1 RTC Amelie Delaunay
2018-05-09 15:46 ` [PATCH v2 1/3] rtc: stm32: rework register management to prepare other version of RTC Amelie Delaunay
2018-05-16 20:25 ` Alexandre Belloni
2018-05-17 10:01 ` Amelie DELAUNAY
2018-05-09 15:46 ` [PATCH v2 2/3] dt-bindings: rtc: update stm32-rtc documentation for stm32mp1 rtc Amelie Delaunay
2018-05-09 15:46 ` [PATCH v2 3/3] rtc: stm32: add stm32mp1 rtc support Amelie Delaunay
2018-05-10 11:40 ` kbuild test robot
2018-05-16 20:32 ` Alexandre Belloni
2018-05-17 10:03 ` Amelie DELAUNAY
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).