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