[RFC PATCH] rtc-omap: Fix alarm interrupts on DRA7xx

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On DRA7xx chips (and maybe others), the reset configuration of the RTC
does not allow it to wake up from idle when it's ready to generate an
interrupt.  It only generates an interrupt when register access takes
it out of idle, which in means most RTC operations will hang.  We need
to change the IDLEMODE field to make alarm interrupts work properly.
---
The following worked for me, but I don't know whether this register
field should really be set in the RTC driver or somewhere in OMAP
platform code.

Also, given that DRA7xx is based on OMAP5 I would guess that the same
fix is needed for OMAP5, but I don't have the reference manual for it.
Can someone confirm whether it has the same register field?

Finally, I realise that the new compatible string, whatever it should
be, will need to be documented.

Ben.
---
--- a/drivers/rtc/rtc-omap.c
+++ b/drivers/rtc/rtc-omap.c
@@ -69,6 +69,7 @@
 #define OMAP_RTC_KICK0_REG		0x6c
 #define OMAP_RTC_KICK1_REG		0x70
 
+#define OMAP_RTC_SYSCONFIG_REG		0x78
 #define OMAP_RTC_IRQWAKEEN		0x7c
 
 #define OMAP_RTC_ALARM2_SECONDS_REG	0x80
@@ -110,6 +111,13 @@
 #define OMAP_RTC_OSC_32KCLK_EN		BIT(6)
 #define OMAP_RTC_OSC_SEL_32KCLK_SRC	BIT(3)
 
+/* OMAP_RTC_SYSCONFIG_REG bit fields: */
+#define OMAP_RTC_IDLEMODE_MASK		3
+#define OMAP_RTC_IDLEMODE_FORCE		0
+#define OMAP_RTC_IDLEMODE_DISABLE	1
+#define OMAP_RTC_IDLEMODE_SMART		2
+#define OMAP_RTC_IDLEMODE_SMART_WAKEUP	3
+
 /* OMAP_RTC_IRQWAKEEN bit fields: */
 #define OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN	BIT(1)
 
@@ -127,6 +135,7 @@ struct omap_rtc_device_type {
 	bool has_irqwakeen;
 	bool has_pmic_mode;
 	bool has_power_up_reset;
+	bool has_idlemode;
 	void (*lock)(struct omap_rtc *rtc);
 	void (*unlock)(struct omap_rtc *rtc);
 };
@@ -496,6 +505,15 @@ static const struct omap_rtc_device_type
 	.unlock		= am3352_rtc_unlock,
 };
 
+static const struct omap_rtc_device_type omap_rtc_dra7_type = {
+	.has_32kclk_en	= true,
+	.has_irqwakeen	= true,
+	.has_pmic_mode	= true,
+	.has_idlemode	= true,
+	.lock		= am3352_rtc_lock,
+	.unlock		= am3352_rtc_unlock,
+};
+
 static const struct platform_device_id omap_rtc_id_table[] = {
 	{
 		.name	= "omap_rtc",
@@ -520,6 +538,9 @@ static const struct of_device_id omap_rt
 		.compatible	= "ti,da830-rtc",
 		.data		= &omap_rtc_da830_type,
 	}, {
+		.compatible	= "ti,dra7-rtc",
+		.data		= &omap_rtc_dra7_type,
+	}, {
 		/* sentinel */
 	}
 };
@@ -650,6 +671,18 @@ static int omap_rtc_probe(struct platfor
 			  reg | OMAP_RTC_OSC_SEL_32KCLK_SRC);
 	}
 
+	if (rtc->type->has_idlemode) {
+		/*
+		 * Allow the RTC to come out of idle whenever it's ready to
+		 * generate an interrupt
+		 */
+		u32 sysconfig = rtc_readl(rtc, OMAP_RTC_SYSCONFIG_REG);
+
+		sysconfig &= ~OMAP_RTC_IDLEMODE_MASK;
+		sysconfig |= OMAP_RTC_IDLEMODE_SMART_WAKEUP;
+		rtc_writel(rtc, OMAP_RTC_SYSCONFIG_REG, sysconfig);
+	}
+
 	rtc->type->lock(rtc);
 
 	device_init_wakeup(&pdev->dev, true);
--- a/arch/arm/boot/dts/dra7.dtsi
+++ b/arch/arm/boot/dts/dra7.dtsi
@@ -1290,7 +1290,7 @@
 		};
 
 		rtc: rtc@48838000 {
-			compatible = "ti,am3352-rtc";
+			compatible = "ti,dra7-rtc", "ti,am3352-rtc";
 			reg = <0x48838000 0x100>;
 			interrupts = <GIC_SPI 217 IRQ_TYPE_LEVEL_HIGH>,
 				     <GIC_SPI 217 IRQ_TYPE_LEVEL_HIGH>;

-- 
Ben Hutchings
Software Developer, Codethink Ltd.


--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Arm (vger)]     [ARM Kernel]     [ARM MSM]     [Linux Tegra]     [Linux WPAN Networking]     [Linux Wireless Networking]     [Maemo Users]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux