Commit 8af750e3 authored by Hebbar Gururaja's avatar Hebbar Gururaja Committed by Linus Torvalds
Browse files

drivers/rtc/rtc-omap.c: add rtc wakeup support to alarm events



On some platforms (like AM33xx), a special register (RTC_IRQWAKEEN) is
available to enable Alarm Wakeup feature.  This register needs to be
properly handled for the rtcwake to work properly.

Platforms using such IP should set "ti,am3352-rtc" in rtc device dt
compatibility node.

Signed-off-by: default avatarHebbar Gururaja <gururaja.hebbar@ti.com>
Acked-by: default avatarKevin Hilman <khilman@linaro.org>
Acked-by: default avatarSekhar Nori <nsekhar@ti.com>
Cc: Grant Likely <grant.likely@linaro.org>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: Rob Landley <rob@landley.net>
Cc: Alessandro Zummo <a.zummo@towertech.it>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 453b4c6d
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
TI Real Time Clock

Required properties:
- compatible: "ti,da830-rtc"
- compatible:
	- "ti,da830-rtc"  - for RTC IP used similar to that on DA8xx SoC family.
	- "ti,am3352-rtc" - for RTC IP used similar to that on AM335x SoC family.
			    This RTC IP has special WAKE-EN Register to enable
			    Wakeup generation for event Alarm.
- reg: Address range of rtc register set
- interrupts: rtc timer, alarm interrupts in order
- interrupt-parent: phandle for the interrupt controller
+52 −8
Original line number Diff line number Diff line
@@ -70,6 +70,8 @@
#define OMAP_RTC_KICK0_REG		0x6c
#define OMAP_RTC_KICK1_REG		0x70

#define OMAP_RTC_IRQWAKEEN		0x7c

/* OMAP_RTC_CTRL_REG bit fields: */
#define OMAP_RTC_CTRL_SPLIT		(1<<7)
#define OMAP_RTC_CTRL_DISABLE		(1<<6)
@@ -94,12 +96,21 @@
#define OMAP_RTC_INTERRUPTS_IT_ALARM    (1<<3)
#define OMAP_RTC_INTERRUPTS_IT_TIMER    (1<<2)

/* OMAP_RTC_IRQWAKEEN bit fields: */
#define OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN    (1<<1)

/* OMAP_RTC_KICKER values */
#define	KICK0_VALUE			0x83e70b13
#define	KICK1_VALUE			0x95a4f1e0

#define	OMAP_RTC_HAS_KICKER		0x1

/*
 * Few RTC IP revisions has special WAKE-EN Register to enable Wakeup
 * generation for event Alarm.
 */
#define	OMAP_RTC_HAS_IRQWAKEEN		0x2

static void __iomem	*rtc_base;

#define rtc_read(addr)		readb(rtc_base + (addr))
@@ -299,12 +310,18 @@ static struct rtc_class_ops omap_rtc_ops = {
static int omap_rtc_alarm;
static int omap_rtc_timer;

#define	OMAP_RTC_DATA_DA830_IDX	1
#define	OMAP_RTC_DATA_AM3352_IDX	1
#define	OMAP_RTC_DATA_DA830_IDX		2

static struct platform_device_id omap_rtc_devtype[] = {
	{
		.name	= DRIVER_NAME,
	}, {
	},
	[OMAP_RTC_DATA_AM3352_IDX] = {
		.name	= "am3352-rtc",
		.driver_data = OMAP_RTC_HAS_KICKER | OMAP_RTC_HAS_IRQWAKEEN,
	},
	[OMAP_RTC_DATA_DA830_IDX] = {
		.name	= "da830-rtc",
		.driver_data = OMAP_RTC_HAS_KICKER,
	},
@@ -316,6 +333,9 @@ static const struct of_device_id omap_rtc_of_match[] = {
	{	.compatible	= "ti,da830-rtc",
		.data		= &omap_rtc_devtype[OMAP_RTC_DATA_DA830_IDX],
	},
	{	.compatible	= "ti,am3352-rtc",
		.data		= &omap_rtc_devtype[OMAP_RTC_DATA_AM3352_IDX],
	},
	{},
};
MODULE_DEVICE_TABLE(of, omap_rtc_of_match);
@@ -464,16 +484,28 @@ static u8 irqstat;

static int omap_rtc_suspend(struct device *dev)
{
	u8 irqwake_stat;
	struct platform_device *pdev = to_platform_device(dev);
	const struct platform_device_id *id_entry =
					platform_get_device_id(pdev);

	irqstat = rtc_read(OMAP_RTC_INTERRUPTS_REG);

	/* FIXME the RTC alarm is not currently acting as a wakeup event
	 * source, and in fact this enable() call is just saving a flag
	 * that's never used...
	 * source on some platforms, and in fact this enable() call is just
	 * saving a flag that's never used...
	 */
	if (device_may_wakeup(dev))
	if (device_may_wakeup(dev)) {
		enable_irq_wake(omap_rtc_alarm);
	else

		if (id_entry->driver_data & OMAP_RTC_HAS_IRQWAKEEN) {
			irqwake_stat = rtc_read(OMAP_RTC_IRQWAKEEN);
			irqwake_stat |= OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN;
			rtc_write(irqwake_stat, OMAP_RTC_IRQWAKEEN);
		}
	} else {
		rtc_write(0, OMAP_RTC_INTERRUPTS_REG);
	}

	/* Disable the clock/module */
	pm_runtime_put_sync(dev);
@@ -483,13 +515,25 @@ static int omap_rtc_suspend(struct device *dev)

static int omap_rtc_resume(struct device *dev)
{
	u8 irqwake_stat;
	struct platform_device *pdev = to_platform_device(dev);
	const struct platform_device_id *id_entry =
				platform_get_device_id(pdev);

	/* Enable the clock/module so that we can access the registers */
	pm_runtime_get_sync(dev);

	if (device_may_wakeup(dev))
	if (device_may_wakeup(dev)) {
		disable_irq_wake(omap_rtc_alarm);
	else

		if (id_entry->driver_data & OMAP_RTC_HAS_IRQWAKEEN) {
			irqwake_stat = rtc_read(OMAP_RTC_IRQWAKEEN);
			irqwake_stat &= ~OMAP_RTC_IRQWAKEEN_ALARM_WAKEEN;
			rtc_write(irqwake_stat, OMAP_RTC_IRQWAKEEN);
		}
	} else {
		rtc_write(irqstat, OMAP_RTC_INTERRUPTS_REG);
	}
	return 0;
}
#endif