devicetree.vger.kernel.org archive mirror
 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, Amelie Delaunay, linux-kernel, linux-arm-kernel

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, Amelie Delaunay, linux-kernel, linux-arm-kernel

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)
  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: Mark Rutland, Alessandro Zummo, Alexandre TORGUE, devicetree,
	linux-kernel, Rob Herring, Maxime Coquelin, linux-arm-kernel,
	linux-rtc

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:03 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).