[v2,3/3] rtc: stm32: add stm32mp1 rtc support

Message ID 1525880770-22263-4-git-send-email-amelie.delaunay@st.com
State Superseded
Headers show
Series
  • Introduce STM32MP1 RTC
Related show

Commit Message

Amelie DELAUNAY May 9, 2018, 3:46 p.m.
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(-)

Comments

kbuild test robot May 10, 2018, 11:40 a.m. | #1
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
Alexandre Belloni May 16, 2018, 8:32 p.m. | #2
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);
> +	}
> +
Amelie DELAUNAY May 17, 2018, 10:03 a.m. | #3
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

Patch

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;