Skip to contentSkip to conversation

OMAP3+: PRCM chain handler

PATCH Superseded Tero Kristo 4 participants 27 messages Dec 12, 2011 – Dec 14, 2011

Subsystems (6)

v11 of 12 Superseded Latest is v12 →

lore
Share & tools
lore
#0 lore raw

v11 cover OMAP3+: PRCM chain handler

Hi,

PRCM chain handler is adding a support to the omap3+ kernel that allows different drivers to use PRCM interrupt events for their own purposes, typically this means IO wakeups. This work was attempted to integrate as its own driver at some point of the evolution of this set, however this was now postponed as the lacking support is basically blocking a few drivers.

This is the version 11 of this set, now posted to linux-arm-kernel also as cc. Contains just a couple of minor changes compared to previous version proposed by Kevin Hilman.

Also, patch 8 is new (posted as a separate patch to l-o list earlier), for supporting different irqs for different pads on the same hwmod. This is needed at least by USB driver.

This version tested on omap3 beagle board, dynamic idle + suspend, with and without off-mode. I have pushed two branches on a public git tree:

git://gitorious.org/~kristo/omap-pm/omap-pm-work.git

branch: chain-prcm-v11
branch2: chain-prcm-v11-debug

Debug branch contains a few debugging related patches I've used for testing purposes.

-Tero

#1 lore raw

PATCH v11 1/8 ARM: OMAP2+: hwmod: Add API to enable IO ring wakeup.

From: R, Govindraj <[email protected]>

Add API to enable IO pad wakeup capability based on mux dynamic pad and wake_up enable flag available from hwmod_mux initialization.

Use the wakeup_enable flag and enable wakeup capability for the given pads. Wakeup capability will be enabled/disabled during hwmod idle transition based on whether wakeup_flag is set or cleared.

Map the enable/disable pad wakeup API's to hwmod_wakeup_enable/disable.

---
 arch/arm/mach-omap2/omap_hwmod.c |   59 ++++++++++++++++++++++++++++++++++++++
 1 files changed, 59 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/omap_hwmod.c +59 -0
index 6b3088d..8d37d83 100644
@@ -2059,6 +2059,34 @@ static int __init omap_hwmod_setup_all(void)
 core_initcall(omap_hwmod_setup_all);
 
 /**
+ * omap_hwmod_set_ioring_wakeup - enable io pad wakeup flag.
+ * @oh: struct omap_hwmod *
+ * @set: bool value indicating to set or clear wakeup status.
+ *
+ * Set or Clear wakeup flag for the io_pad.
+ */
+static int omap_hwmod_set_ioring_wakeup(struct omap_hwmod *oh, bool set_wake)
+{
+	struct omap_device_pad *pad;
+	int ret = -EINVAL, j;
+
+	if (oh->mux && oh->mux->enabled) {
+		for (j = 0; j < oh->mux->nr_pads_dynamic; j++) {
+			pad = oh->mux->pads_dynamic[j];
+			if (pad->flags & OMAP_DEVICE_PAD_WAKEUP) {
+				if (set_wake)
+					pad->idle |= OMAP_WAKEUP_EN;
+				else
+					pad->idle &= ~OMAP_WAKEUP_EN;
+				ret = 0;
+			}
+		}
+	}
+
+	return ret;
+}
+
+/**
  * omap_hwmod_enable - enable an omap_hwmod
  * @oh: struct omap_hwmod *
  *
@@ -2390,6 +2418,35 @@ int omap_hwmod_del_initiator_dep(struct omap_hwmod *oh,
 {
 	return _del_initiator_dep(oh, init_oh);
 }
+/**
+ * omap_hwmod_enable_ioring_wakeup - Set wakeup flag for iopad.
+ * @oh: struct omap_hwmod *
+ *
+ * Traverse through dynamic pads, if pad is enabled then
+ * set wakeup enable bit flag for the mux pin. Wakeup pad bit
+ * will be set during hwmod idle transistion.
+ * Return error if pads are not enabled or not available.
+ */
+int omap_hwmod_enable_ioring_wakeup(struct omap_hwmod *oh)
+{
+	/* Enable pad wake-up capability */
+	return omap_hwmod_set_ioring_wakeup(oh, true);
+}
+
+/**
+ * omap_hwmod_disable_ioring_wakeup - Clear wakeup flag for iopad.
+ * @oh: struct omap_hwmod *
+ *
+ * Traverse through dynamic pads, if pad is enabled then
+ * clear wakeup enable bit flag for the mux pin. Wakeup pad bit
+ * will be set during hwmod idle transistion.
+ * Return error if pads are not enabled or not available.
+ */
+int omap_hwmod_disable_ioring_wakeup(struct omap_hwmod *oh)
+{
+	/* Disable pad wakeup capability */
+	return omap_hwmod_set_ioring_wakeup(oh, false);
+}
 
 /**
  * omap_hwmod_enable_wakeup - allow device to wake up the system
@@ -2416,6 +2473,7 @@ int omap_hwmod_enable_wakeup(struct omap_hwmod *oh)
 	v = oh->_sysc_cache;
 	_enable_wakeup(oh, &v);
 	_write_sysconfig(v, oh);
+	omap_hwmod_enable_ioring_wakeup(oh);
 	spin_unlock_irqrestore(&oh->_lock, flags);
 
 	return 0;
@@ -2446,6 +2504,7 @@ int omap_hwmod_disable_wakeup(struct omap_hwmod *oh)
 	v = oh->_sysc_cache;
 	_disable_wakeup(oh, &v);
 	_write_sysconfig(v, oh);
+	omap_hwmod_disable_ioring_wakeup(oh);
 	spin_unlock_irqrestore(&oh->_lock, flags);
 
 	return 0;
Signature · 1 line
1.7.4.1
maintainer
#2 lore raw

PATCH v11 1/8 ARM: OMAP2+: hwmod: Add API to enable IO ring wakeup.

Hi Tero

Quoted 5 lines · Tero Kristo

From: R, Govindraj <[email protected]>

Add API to enable IO pad wakeup capability based on mux dynamic pad and wake_up enable flag available from hwmod_mux initialization.

Quoted 8 lines

Use the wakeup_enable flag and enable wakeup capability for the given pads. Wakeup capability will be enabled/disabled during hwmod idle transition based on whether wakeup_flag is set or cleared.

Map the enable/disable pad wakeup API's to hwmod_wakeup_enable/disable.

Since you're in the submitter chain for these patches, I'll need your Signed-off-by on this patch and the next one. Okay to add it?

- Paul

maintainer
#3 lore raw

PATCH v11 1/8 ARM: OMAP2+: hwmod: Add API to enable IO ring wakeup.

In reply to Tero Kristo

Hi

Quoted 5 lines · Tero Kristo

From: R, Govindraj <[email protected]>

Add API to enable IO pad wakeup capability based on mux dynamic pad and wake_up enable flag available from hwmod_mux initialization.

Quoted 8 lines

Use the wakeup_enable flag and enable wakeup capability for the given pads. Wakeup capability will be enabled/disabled during hwmod idle transition based on whether wakeup_flag is set or cleared.

Map the enable/disable pad wakeup API's to hwmod_wakeup_enable/disable.

A few changes have been made to this patch:

- The documentation has been improved

- omap_hwmod_{enable,disable}_ioring_wakeup() have been removed, since they are not called outside the omap_hwmod code and were missing function prototypes in omap_hwmod.h

- The omap_hwmod_set_ioring_wakeup() function has been modified to not return anything, and indentation depth has been reduced

I still don't think this patch is 100% correct. For example, if omap_hwmod_enable_wakeup() or omap_hwmod_disable_wakeup() is called on an idle hwmod, shouldn't the caller expect the SCM PADCONF registers to be updated immediately? The current code merely changes the dynamic mux data. If there is some rationale for not updating the hardware registers at this point, I'd like to know what it is.

Modified patch is below; please let me know if you have any comments. I may modify it again to synchronize the hardware with the in-memory settings immediately.

- Paul

From: Govindraj R <[email protected]>
Date: Tue, 13 Dec 2011 13:50:23 -0700
Subject: [PATCH] ARM: OMAP2+: hwmod: Add API to enable IO ring wakeup

Add API to enable IO pad wakeup capability based on mux dynamic pad and wake_up enable flag available from hwmod_mux initialization.

Use the wakeup_enable flag and enable wakeup capability for the given pads. Wakeup capability will be enabled/disabled during hwmod idle transition based on whether wakeup_flag is set or cleared.

XXX Tero's sign-off?
[paul at pwsan.com: rearranged code to limit indentation, cleaned up
documentation, removed unused non-static functions]

---
 arch/arm/mach-omap2/omap_hwmod.c |   39 ++++++++++++++++++++++++++++++++++++++
 1 files changed, 39 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/omap_hwmod.c +39 -0
index 207a2ff..ec19841 100644
@@ -381,6 +381,43 @@ static int _set_module_autoidle(struct omap_hwmod *oh, u8 autoidle,
 }
 
 /**
+ * _set_ioring_wakeup - enable/disable IO pad wakeup flag for dynamic muxing
+ * @oh: struct omap_hwmod *
+ * @set_wake: bool value indicating to set (true) or clear (false) wakeup enable
+ *
+ * Set or clear the I/O pad wakeup flag in the dynamic mux entries for
+ * the hwmod @oh.  This function does not change anything in the
+ * hardware.  Rather, the @oh->mux->pads_dynamic array is changed, and
+ * these settings are later written to the SCM PADCTRL registers when
+ * the hwmod is enabled or idled.  No return value.
+ *
+ * XXX Shouldn't the dynamic pad changes affect hwmod shutdown as
+ * well?
+ * XXX Shouldn't this function update the hardware SCM PADCONF registers if
+ * anything has changed?
+ */
+static void _set_ioring_wakeup(struct omap_hwmod *oh, bool set_wake)
+{
+	struct omap_device_pad *pad;
+	int j;
+
+	if (!oh->mux || !oh->mux->enabled)
+		return;
+
+	for (j = 0; j < oh->mux->nr_pads_dynamic; j++) {
+		pad = oh->mux->pads_dynamic[j];
+
+		if (!(pad->flags & OMAP_DEVICE_PAD_WAKEUP))
+			continue;
+
+		if (set_wake)
+			pad->idle |= OMAP_WAKEUP_EN;
+		else
+			pad->idle &= ~OMAP_WAKEUP_EN;
+	}
+}
+
+/**
  * _enable_wakeup: set OCP_SYSCONFIG.ENAWAKEUP bit in the hardware
  * @oh: struct omap_hwmod *
  *
@@ -2416,6 +2453,7 @@ int omap_hwmod_enable_wakeup(struct omap_hwmod *oh)
 	v = oh->_sysc_cache;
 	_enable_wakeup(oh, &v);
 	_write_sysconfig(v, oh);
+	_set_ioring_wakeup(oh, true);
 	spin_unlock_irqrestore(&oh->_lock, flags);
 
 	return 0;
@@ -2446,6 +2484,7 @@ int omap_hwmod_disable_wakeup(struct omap_hwmod *oh)
 	v = oh->_sysc_cache;
 	_disable_wakeup(oh, &v);
 	_write_sysconfig(v, oh);
+	_set_ioring_wakeup(oh, false);
 	spin_unlock_irqrestore(&oh->_lock, flags);
 
 	return 0;
Signature · 1 line
1.7.7.3
maintainer
#4 lore raw

PATCH v11 1/8 ARM: OMAP2+: hwmod: Add API to enable IO ring wakeup.

Hi Govindraj, Tero,

another question about this patch:

Quoted 33 lines · Paul Walmsley
arch/arm/mach-omap2/omap_hwmod.c +25 -0
index 207a2ff..ec19841 100644
@@ -381,6 +381,43 @@ static int _set_module_autoidle(struct omap_hwmod *oh, u8 autoidle,
 }
 
 /**
+ * _set_ioring_wakeup - enable/disable IO pad wakeup flag for dynamic muxing
+ * @oh: struct omap_hwmod *
+ * @set_wake: bool value indicating to set (true) or clear (false) wakeup enable
+ *
+ * Set or clear the I/O pad wakeup flag in the dynamic mux entries for
+ * the hwmod @oh.  This function does not change anything in the
+ * hardware.  Rather, the @oh->mux->pads_dynamic array is changed, and
+ * these settings are later written to the SCM PADCTRL registers when
+ * the hwmod is enabled or idled.  No return value.
+ *
+ * XXX Shouldn't the dynamic pad changes affect hwmod shutdown as
+ * well?
+ * XXX Shouldn't this function update the hardware SCM PADCONF registers if
+ * anything has changed?
+ */
+static void _set_ioring_wakeup(struct omap_hwmod *oh, bool set_wake)
+{
+	struct omap_device_pad *pad;
+	int j;
+
+	if (!oh->mux || !oh->mux->enabled)
+		return;
+
+	for (j = 0; j < oh->mux->nr_pads_dynamic; j++) {
+		pad = oh->mux->pads_dynamic[j];

arch/arm/mach-omap2/omap_hwmod.c static int _set_module_autoidle(struct omap_hwmod *oh, u8 autoidle, · line 418

Quoted 10 lines
arch/arm/mach-omap2/omap_hwmod.c +10 -0
+
+		if (!(pad->flags & OMAP_DEVICE_PAD_WAKEUP))
+			continue;
+
+		if (set_wake)
+			pad->idle |= OMAP_WAKEUP_EN;
+		else
+			pad->idle &= ~OMAP_WAKEUP_EN;
+	}
+}

It appears that this loop only affects dynamic mux entries. Should it also affect static mux entries?

- Paul

maintainer
#5 lore raw

PATCH v11 1/8 ARM: OMAP2+: hwmod: Add API to enable IO ring wakeup.

In reply to Tero Kristo

Hi

so I've updated this patch to change the SCM PADCTRL registers if the hwmod is currently idle, and _set_idle_ioring_wakeup() is called. Otherwise calling _set_idle_ioring_wakeup() would be useless under those conditions, since the new I/O ring wakeup values wouldn't be written back to the hardware until the hwmod had gone through an idle->enabled and enabled->idle transition.

Please try to consider the function's appropriate behavior under which these functions can be called...

Updated patch below. Will update internally once I get Tero's Signed-off-by:.

- Paul

From: Govindraj R <[email protected]>
Date: Tue, 13 Dec 2011 13:50:23 -0700
Subject: [PATCH] ARM: OMAP2+: hwmod: Add API to enable IO ring wakeup

Add API to enable IO pad wakeup capability based on mux pad and wake_up enable flag available from hwmod_mux initialization.

Use the wakeup_enable flag and enable wakeup capability for the given pads. Wakeup capability will be enabled/disabled during hwmod idle transition based on whether wakeup_flag is set or cleared. If the hwmod is currently idled, and any mux values were changed by _set_idle_ioring_wakeup(), the SCM PADCTRL registers will be updated.

XXX Tero's sign-off?
[paul at pwsan.com: rearranged code to limit indentation; cleaned up
function documentation; removed unused non-static functions; modified to search all hwmod pads, not just dynamic remuxing ones; modified to update SCM regs if hwmod is currently idle and any pads have changed]

---
 arch/arm/mach-omap2/omap_hwmod.c |   47 ++++++++++++++++++++++++++++++++++++++
 1 files changed, 47 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/omap_hwmod.c +47 -0
index 207a2ff..21ffd8a 100644
@@ -381,6 +381,51 @@ static int _set_module_autoidle(struct omap_hwmod *oh, u8 autoidle,
 }
 
 /**
+ * _set_idle_ioring_wakeup - enable/disable IO pad wakeup on hwmod idle for mux
+ * @oh: struct omap_hwmod *
+ * @set_wake: bool value indicating to set (true) or clear (false) wakeup enable
+ *
+ * Set or clear the I/O pad wakeup flag in the mux entries for the
+ * hwmod @oh.  This function changes the @oh->mux->pads_dynamic array
+ * in memory.  If the hwmod is currently idled, and the new idle
+ * values don't match the previous ones, this function will also
+ * update the SCM PADCTRL registers.  Otherwise, if the hwmod is not
+ * currently idled, this function won't touch the hardware: the new
+ * mux settings are written to the SCM PADCTRL registers when the
+ * hwmod is idled.  No return value.
+ */
+static void _set_idle_ioring_wakeup(struct omap_hwmod *oh, bool set_wake)
+{
+	struct omap_device_pad *pad;
+	bool change = false;
+	u16 prev_idle;
+	int j;
+
+	if (!oh->mux || !oh->mux->enabled)
+		return;
+
+	for (j = 0; j < oh->mux->nr_pads_dynamic; j++) {
+		pad = oh->mux->pads_dynamic[j];
+
+		if (!(pad->flags & OMAP_DEVICE_PAD_WAKEUP))
+			continue;
+
+		prev_idle = pad->idle;
+
+		if (set_wake)
+			pad->idle |= OMAP_WAKEUP_EN;
+		else
+			pad->idle &= ~OMAP_WAKEUP_EN;
+
+		if (prev_idle != pad->idle)
+			change = true;
+	}
+
+	if (change && oh->_state == _HWMOD_STATE_IDLE)
+		omap_hwmod_mux(oh->mux, _HWMOD_STATE_IDLE);
+}
+
+/**
  * _enable_wakeup: set OCP_SYSCONFIG.ENAWAKEUP bit in the hardware
  * @oh: struct omap_hwmod *
  *
@@ -2416,6 +2461,7 @@ int omap_hwmod_enable_wakeup(struct omap_hwmod *oh)
 	v = oh->_sysc_cache;
 	_enable_wakeup(oh, &v);
 	_write_sysconfig(v, oh);
+	_set_idle_ioring_wakeup(oh, true);
 	spin_unlock_irqrestore(&oh->_lock, flags);
 
 	return 0;
@@ -2446,6 +2492,7 @@ int omap_hwmod_disable_wakeup(struct omap_hwmod *oh)
 	v = oh->_sysc_cache;
 	_disable_wakeup(oh, &v);
 	_write_sysconfig(v, oh);
+	_set_idle_ioring_wakeup(oh, false);
 	spin_unlock_irqrestore(&oh->_lock, flags);
 
 	return 0;
Signature · 1 line
1.7.7.3
#6 lore raw

PATCH v11 1/8 ARM: OMAP2+: hwmod: Add API to enable IO ring wakeup.

Quoted 9 lines · Paul Walmsley

Hi

so I've updated this patch to change the SCM PADCTRL registers if the hwmod is currently idle, and _set_idle_ioring_wakeup() is called. Otherwise calling _set_idle_ioring_wakeup() would be useless under those conditions, since the new I/O ring wakeup values wouldn't be written back to the hardware until the hwmod had gone through an idle->enabled and enabled->idle transition.

Quoted 5 lines

Please try to consider the function's appropriate behavior under which these functions can be called...

Updated patch below. Will update internally once I get Tero's Signed-off-by:.

Hi Paul,

Patch looks okay to me, I also quickly tested it out and it works.

Quoted 100 lines

- Paul

From: Govindraj R <[email protected]>
Date: Tue, 13 Dec 2011 13:50:23 -0700
Subject: [PATCH] ARM: OMAP2+: hwmod: Add API to enable IO ring wakeup

Add API to enable IO pad wakeup capability based on mux pad and wake_up enable flag available from hwmod_mux initialization.

Use the wakeup_enable flag and enable wakeup capability for the given pads. Wakeup capability will be enabled/disabled during hwmod idle transition based on whether wakeup_flag is set or cleared. If the hwmod is currently idled, and any mux values were changed by _set_idle_ioring_wakeup(), the SCM PADCTRL registers will be updated.

XXX Tero's sign-off?
[paul at pwsan.com: rearranged code to limit indentation; cleaned up
function documentation; removed unused non-static functions; modified to search all hwmod pads, not just dynamic remuxing ones; modified to update SCM regs if hwmod is currently idle and any pads have changed]

---
 arch/arm/mach-omap2/omap_hwmod.c |   47 ++++++++++++++++++++++++++++++++++++++
 1 files changed, 47 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/omap_hwmod.c +47 -0
index 207a2ff..21ffd8a 100644
@@ -381,6 +381,51 @@ static int _set_module_autoidle(struct omap_hwmod *oh, u8 autoidle,
 }
 
 /**
+ * _set_idle_ioring_wakeup - enable/disable IO pad wakeup on hwmod idle for mux
+ * @oh: struct omap_hwmod *
+ * @set_wake: bool value indicating to set (true) or clear (false) wakeup enable
+ *
+ * Set or clear the I/O pad wakeup flag in the mux entries for the
+ * hwmod @oh.  This function changes the @oh->mux->pads_dynamic array
+ * in memory.  If the hwmod is currently idled, and the new idle
+ * values don't match the previous ones, this function will also
+ * update the SCM PADCTRL registers.  Otherwise, if the hwmod is not
+ * currently idled, this function won't touch the hardware: the new
+ * mux settings are written to the SCM PADCTRL registers when the
+ * hwmod is idled.  No return value.
+ */
+static void _set_idle_ioring_wakeup(struct omap_hwmod *oh, bool set_wake)
+{
+	struct omap_device_pad *pad;
+	bool change = false;
+	u16 prev_idle;
+	int j;
+
+	if (!oh->mux || !oh->mux->enabled)
+		return;
+
+	for (j = 0; j < oh->mux->nr_pads_dynamic; j++) {
+		pad = oh->mux->pads_dynamic[j];
+
+		if (!(pad->flags & OMAP_DEVICE_PAD_WAKEUP))
+			continue;
+
+		prev_idle = pad->idle;
+
+		if (set_wake)
+			pad->idle |= OMAP_WAKEUP_EN;
+		else
+			pad->idle &= ~OMAP_WAKEUP_EN;
+
+		if (prev_idle != pad->idle)
+			change = true;
+	}
+
+	if (change && oh->_state == _HWMOD_STATE_IDLE)
+		omap_hwmod_mux(oh->mux, _HWMOD_STATE_IDLE);
+}
+
+/**
  * _enable_wakeup: set OCP_SYSCONFIG.ENAWAKEUP bit in the hardware
  * @oh: struct omap_hwmod *
  *
@@ -2416,6 +2461,7 @@ int omap_hwmod_enable_wakeup(struct omap_hwmod *oh)
 	v = oh->_sysc_cache;
 	_enable_wakeup(oh, &v);
 	_write_sysconfig(v, oh);
+	_set_idle_ioring_wakeup(oh, true);
 	spin_unlock_irqrestore(&oh->_lock, flags);
 
 	return 0;
@@ -2446,6 +2492,7 @@ int omap_hwmod_disable_wakeup(struct omap_hwmod *oh)
 	v = oh->_sysc_cache;
 	_disable_wakeup(oh, &v);
 	_write_sysconfig(v, oh);
+	_set_idle_ioring_wakeup(oh, false);
 	spin_unlock_irqrestore(&oh->_lock, flags);
 
 	return 0;
#7 lore raw

PATCH v11 2/8 ARM: OMAP2+: hwmod: Add API to check IO PAD wakeup status

In reply to Tero Kristo

From: R, Govindraj <[email protected]>

Add API to determine IO-PAD wakeup event status for a given hwmod dynamic_mux pad.

---
 arch/arm/mach-omap2/mux.c                    |   30 ++++++++++++++++++++++++++
 arch/arm/mach-omap2/mux.h                    |   13 +++++++++++
 arch/arm/mach-omap2/omap_hwmod.c             |    7 ++++++
 arch/arm/plat-omap/include/plat/omap_hwmod.h |    1 +
 4 files changed, 51 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/mux.c +30 -0
index 655e948..5f15ab8 100644
@@ -351,6 +351,36 @@ err1:
 	return NULL;
 }
 
+/**
+ * omap_hwmod_mux_get_wake_status - omap hwmod check pad wakeup
+ * @hmux:		Pads for a hwmod
+ *
+ * Gets the wakeup status of given pad from omap-hwmod.
+ * Returns true if wakeup event is set for pad else false
+ * if wakeup is not occured or pads are not avialable.
+ */
+bool omap_hwmod_mux_get_wake_status(struct omap_hwmod_mux_info *hmux)
+{
+	int i;
+	unsigned int val;
+	u8 ret = false;
+
+	for (i = 0; i < hmux->nr_pads; i++) {
+		struct omap_device_pad *pad = &hmux->pads[i];
+
+		if (pad->flags & OMAP_DEVICE_PAD_WAKEUP) {
+			val = omap_mux_read(pad->partition,
+					pad->mux->reg_offset);
+			if (val & OMAP_WAKEUP_EVENT) {
+				ret = true;
+				break;
+			}
+		}
+	}
+
+	return ret;
+}
+
 /* Assumes the calling function takes care of locking */
 void omap_hwmod_mux(struct omap_hwmod_mux_info *hmux, u8 state)
 {
arch/arm/mach-omap2/mux.h +13 -0
index 2132308..8b2150a 100644
@@ -225,8 +225,21 @@ omap_hwmod_mux_init(struct omap_device_pad *bpads, int nr_pads);
  */
 void omap_hwmod_mux(struct omap_hwmod_mux_info *hmux, u8 state);
 
+/**
+ * omap_hwmod_mux_get_wake_status - omap hwmod check pad wakeup
+ * @hmux:		Pads for a hwmod
+ *
+ * Called only from omap_hwmod.c, do not use.
+ */
+bool omap_hwmod_mux_get_wake_status(struct omap_hwmod_mux_info *hmux);
 #else
 
+static inline bool
+omap_hwmod_mux_get_wake_status(struct omap_hwmod_mux_info *hmux)
+{
+	return 0;
+}
+
 static inline int omap_mux_init_gpio(int gpio, int val)
 {
 	return 0;
arch/arm/mach-omap2/omap_hwmod.c +7 -0
index 8d37d83..d7f4623 100644
@@ -2721,3 +2721,10 @@ int omap_hwmod_no_setup_reset(struct omap_hwmod *oh)
 
 	return 0;
 }
+
+int omap_hwmod_pad_get_wakeup_status(struct omap_hwmod *oh)
+{
+	if (oh && oh->mux)
+		return omap_hwmod_mux_get_wake_status(oh->mux);
+	return -EINVAL;
+}
arch/arm/plat-omap/include/plat/omap_hwmod.h +1 -0
index 8b372ed..1b81dfb 100644
@@ -604,6 +604,7 @@ int omap_hwmod_get_context_loss_count(struct omap_hwmod *oh);
 
 int omap_hwmod_no_setup_reset(struct omap_hwmod *oh);
 
+int omap_hwmod_pad_get_wakeup_status(struct omap_hwmod *oh);
 /*
  * Chip variant-specific hwmod init routines - XXX should be converted
  * to use initcalls once the initial boot ordering is straightened out
Signature · 1 line
1.7.4.1
maintainer
#9 lore raw

PATCH v11 2/8 ARM: OMAP2+: hwmod: Add API to check IO PAD wakeup status

In reply to Tero Kristo

Hi

a question

On Mon, 12 Dec 2011, Tero Kristo wrote:

So the patch description says:

Quoted 4 lines

From: R, Govindraj <[email protected]>

Add API to determine IO-PAD wakeup event status for a given hwmod dynamic_mux pad.

But the code does:

arch/arm/mach-omap2/mux.c err1: · line 369

Quoted 2 lines
arch/arm/mach-omap2/mux.c +2 -0
+	for (i = 0; i < hmux->nr_pads; i++) {
+		struct omap_device_pad *pad = &hmux->pads[i];

which is going to check all of the pads, not just the dynamic ones.

So it seems to me that we need to decide whether this code should be testing all the pads, or just the dynamically remuxed ones. The same thing should be decided for the code in patch 1.

Na?vely it seems to me that we want to test all of the pads in both patches 1 and 2, not just the dynamically remuxable ones. Comments?

- Paul

maintainer
#10 lore raw

PATCH v11 2/8 ARM: OMAP2+: hwmod: Add API to check IO PAD wakeup status

Quoted 20 lines · Paul Walmsley

Hi

a question

On Mon, 12 Dec 2011, Tero Kristo wrote:

So the patch description says:

Quoted 4 lines

From: R, Govindraj <[email protected]>

Add API to determine IO-PAD wakeup event status for a given hwmod dynamic_mux pad.

But the code does:

arch/arm/mach-omap2/mux.c err1: · line 369

Quoted 2 lines
arch/arm/mach-omap2/mux.c +2 -0
+	for (i = 0; i < hmux->nr_pads; i++) {
+		struct omap_device_pad *pad = &hmux->pads[i];

which is going to check all of the pads, not just the dynamic ones.

Quoted 6 lines

So it seems to me that we need to decide whether this code should be testing all the pads, or just the dynamically remuxed ones. The same thing should be decided for the code in patch 1.

Na?vely it seems to me that we want to test all of the pads in both patches 1 and 2, not just the dynamically remuxable ones. Comments?

You're right, it should be only the dynamic ones.

Tony

maintainer
#11 lore raw

PATCH v11 2/8 ARM: OMAP2+: hwmod: Add API to check IO PAD wakeup status

Quoted 18 lines · Tony Lindgren
Quoted 17 lines · Paul Walmsley

On Mon, 12 Dec 2011, Tero Kristo wrote:

So the patch description says:

Quoted 4 lines

From: R, Govindraj <[email protected]>

Add API to determine IO-PAD wakeup event status for a given hwmod dynamic_mux pad.

But the code does:

arch/arm/mach-omap2/mux.c err1: · line 369

Quoted 2 lines
arch/arm/mach-omap2/mux.c +2 -0
+	for (i = 0; i < hmux->nr_pads; i++) {
+		struct omap_device_pad *pad = &hmux->pads[i];

which is going to check all of the pads, not just the dynamic ones.

Quoted 8 lines
Quoted 6 lines

So it seems to me that we need to decide whether this code should be testing all the pads, or just the dynamically remuxed ones. The same thing should be decided for the code in patch 1.

Na?vely it seems to me that we want to test all of the pads in both patches 1 and 2, not just the dynamically remuxable ones. Comments?

You're right, it should be only the dynamic ones.

Hmm, looks to me like it should check all of them? Can't a pad be marked with OMAP_DEVICE_PAD_WAKEUP, but not be marked with OMAP_DEVICE_PAD_REMUX? In that case it would not end up on the dynamic list, right?

- Paul

maintainer
#12 lore raw

PATCH v11 2/8 ARM: OMAP2+: hwmod: Add API to check IO PAD wakeup status

Quoted 24 lines · Paul Walmsley
Quoted 22 lines · Tony Lindgren
Quoted 21 lines · Paul Walmsley

On Mon, 12 Dec 2011, Tero Kristo wrote:

So the patch description says:

Quoted 4 lines

From: R, Govindraj <[email protected]>

Add API to determine IO-PAD wakeup event status for a given hwmod dynamic_mux pad.

But the code does:

arch/arm/mach-omap2/mux.c err1: · line 369

Quoted 2 lines
arch/arm/mach-omap2/mux.c +2 -0
+	for (i = 0; i < hmux->nr_pads; i++) {
+		struct omap_device_pad *pad = &hmux->pads[i];

which is going to check all of the pads, not just the dynamic ones.

So it seems to me that we need to decide whether this code should be testing all the pads, or just the dynamically remuxed ones. The same thing should be decided for the code in patch 1.

Quoted 8 lines
Quoted 4 lines
Quoted 2 lines

Na?vely it seems to me that we want to test all of the pads in both patches 1 and 2, not just the dynamically remuxable ones. Comments?

You're right, it should be only the dynamic ones.

Hmm, looks to me like it should check all of them? Can't a pad be marked with OMAP_DEVICE_PAD_WAKEUP, but not be marked with OMAP_DEVICE_PAD_REMUX? In that case it would not end up on the dynamic list, right?

Hmm yes that's even more true :) Maybe the right approach would be to copy the OMAP_DEVICE_PAD_WAKEUP pins also to the dynamic list to avoid going through all of them.

Tony

maintainer
#13 lore raw

PATCH v11 2/8 ARM: OMAP2+: hwmod: Add API to check IO PAD wakeup status

Quoted 3 lines · Tony Lindgren

Hmm yes that's even more true :) Maybe the right approach would be to copy the OMAP_DEVICE_PAD_WAKEUP pins also to the dynamic list to avoid going through all of them.

Looking at this further, it seems that the best thing to do for now is to just add hwmod mux entries with OMAP_DEVICE_PAD_WAKEUP into the dynamic list. Otherwise massive changes will be needed to omap_hwmod_mux() and related functions, since those currently only iterate over the dynamic mux entries. Will post the mux patch to do this.

- Paul

#14 lore raw

PATCH v11 2/8 ARM: OMAP2+: hwmod: Add API to check IO PAD wakeup status

In reply to Tony Lindgren
Quoted 30 lines · Tony Lindgren
Quoted 29 lines · Paul Walmsley
Quoted 26 lines · Tony Lindgren
Quoted 17 lines · Paul Walmsley

On Mon, 12 Dec 2011, Tero Kristo wrote:

So the patch description says:

Quoted 4 lines

From: R, Govindraj <[email protected]>

Add API to determine IO-PAD wakeup event status for a given hwmod dynamic_mux pad.

But the code does:

arch/arm/mach-omap2/mux.c err1: · line 369

Quoted 2 lines
arch/arm/mach-omap2/mux.c +2 -0
+	for (i = 0; i < hmux->nr_pads; i++) {
+		struct omap_device_pad *pad = &hmux->pads[i];

which is going to check all of the pads, not just the dynamic ones.

Quoted 6 lines

So it seems to me that we need to decide whether this code should be testing all the pads, or just the dynamically remuxed ones. The same thing should be decided for the code in patch 1.

Na?vely it seems to me that we want to test all of the pads in both patches 1 and 2, not just the dynamically remuxable ones. Comments?

You're right, it should be only the dynamic ones.

Quoted 7 lines
Quoted 3 lines

Hmm, looks to me like it should check all of them? Can't a pad be marked with OMAP_DEVICE_PAD_WAKEUP, but not be marked with OMAP_DEVICE_PAD_REMUX? In that case it would not end up on the dynamic list, right?

Hmm yes that's even more true :) Maybe the right approach would be to copy the OMAP_DEVICE_PAD_WAKEUP pins also to the dynamic list to avoid going through all of them.

Yea, all pads that have WAKEUP capability should be checked. Not sure if this comment is valid anymore seeing patch 2 is kind of irrelevant with patch 8, but the code that scans wakeups should check them all.

-Tero

maintainer
#15 lore raw

PATCH v11 2/8 ARM: OMAP2+: hwmod: Add API to check IO PAD wakeup status

In reply to Tero Kristo

Hi Tero

looking at this patch:

Quoted 6 lines · Tero Kristo

From: R, Govindraj <[email protected]>

Add API to determine IO-PAD wakeup event status for a given hwmod dynamic_mux pad.

It seems that your last patch drops the following code that this patch adds:

Quoted 20 lines
arch/arm/mach-omap2/omap_hwmod.c +7 -0
index 8d37d83..d7f4623 100644
@@ -2721,3 +2721,10 @@ int omap_hwmod_no_setup_reset(struct omap_hwmod *oh)
 
 	return 0;
 }
+
+int omap_hwmod_pad_get_wakeup_status(struct omap_hwmod *oh)
+{
+	if (oh && oh->mux)
+		return omap_hwmod_mux_get_wake_status(oh->mux);
+	return -EINVAL;
+}
arch/arm/plat-omap/include/plat/omap_hwmod.h +0 -0
index 8b372ed..1b81dfb 100644

arch/arm/plat-omap/include/plat/omap_hwmod.h int omap_hwmod_get_context_loss_count(struct omap_hwmod *oh); · line 610

Quoted 7 lines
arch/arm/plat-omap/include/plat/omap_hwmod.h +1 -0
@@ -604,6 +604,7 @@ int omap_hwmod_get_context_loss_count(struct omap_hwmod *oh);
 
 int omap_hwmod_no_setup_reset(struct omap_hwmod *oh);
 
+int omap_hwmod_pad_get_wakeup_status(struct omap_hwmod *oh);
 /*
  * Chip variant-specific hwmod init routines - XXX should be converted
  * to use initcalls once the initial boot ordering is straightened out

It's best in these circumstances to modify this patch not to add the code in the first place. Otherwise this creates needless churn which plenty of people are quite sensitized to. So, dropping these from patch 2.

- Paul

#16 lore raw

PATCH v11 2/8 ARM: OMAP2+: hwmod: Add API to check IO PAD wakeup status

Quoted 8 lines · Paul Walmsley

Hi Tero

looking at this patch:

Quoted 2 lines · Tero Kristo

From: R, Govindraj <[email protected]>

Quoted 7 lines
Quoted 4 lines

Add API to determine IO-PAD wakeup event status for a given hwmod dynamic_mux pad.

It seems that your last patch drops the following code that this patch adds:

Hmm yea true, it seems like the code in patch 2 does not exist anymore after patch 8, and well, the code in patch 2 was never used for anything anyway. Sorry for not spotting this myself, I added patch 8 in hurry to this set.

Quoted 24 lines
Quoted 24 lines
arch/arm/mach-omap2/omap_hwmod.c +7 -0
index 8d37d83..d7f4623 100644
@@ -2721,3 +2721,10 @@ int omap_hwmod_no_setup_reset(struct omap_hwmod *oh)
 
 	return 0;
 }
+
+int omap_hwmod_pad_get_wakeup_status(struct omap_hwmod *oh)
+{
+	if (oh && oh->mux)
+		return omap_hwmod_mux_get_wake_status(oh->mux);
+	return -EINVAL;
+}
arch/arm/plat-omap/include/plat/omap_hwmod.h +0 -0
index 8b372ed..1b81dfb 100644
@@ -604,6 +604,7 @@ int omap_hwmod_get_context_loss_count(struct omap_hwmod *oh);
 
 int omap_hwmod_no_setup_reset(struct omap_hwmod *oh);
 
Quoted 8 lines

arch/arm/plat-omap/include/plat/omap_hwmod.h int omap_hwmod_get_context_loss_count(struct omap_hwmod *oh); · line 610

Quoted 4 lines
arch/arm/plat-omap/include/plat/omap_hwmod.h +1 -0
+int omap_hwmod_pad_get_wakeup_status(struct omap_hwmod *oh);
 /*
  * Chip variant-specific hwmod init routines - XXX should be converted
  * to use initcalls once the initial boot ordering is straightened out

It's best in these circumstances to modify this patch not to add the code in the first place. Otherwise this creates needless churn which plenty of people are quite sensitized to. So, dropping these from patch 2.

Yeah, good call.

-Tero

#17 lore raw

PATCH v11 3/8 ARM: OMAP: prm: add support for chain interrupt handler

In reply to Tero Kristo

Introduce a chained interrupt handler mechanism for the PRCM interrupt, so that individual PRCM event can cleanly be handled by handlers in separate drivers. We do this by introducing PRCM event names, which are then matched to the particular PRCM interrupt bit depending on the specific OMAP SoC being used.

PRCM interrupts have two priority levels, high or normal. High priority is needed for IO event handling, so that we can be sure that IO events are processed before other events. This reduces latency for IO event customers and also prevents incorrect ack sequence on OMAP3.

Cc Paul Walmsley <[email protected]>
Cc Kevin Hilman <[email protected]>
Cc Avinash.H.M <[email protected]>
Cc Cousson, Benoit <[email protected]>
Cc Tony Lindgren <[email protected]>
Cc Govindraj.R <[email protected]>
---
 arch/arm/mach-omap2/prcm-common.h  |   29 +++++
 arch/arm/mach-omap2/prcm.c         |  229 ++++++++++++++++++++++++++++++++++++
 arch/arm/mach-omap2/prm2xxx_3xxx.c |   21 ++++
 arch/arm/mach-omap2/prm44xx.c      |   21 ++++
 4 files changed, 300 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/prcm-common.h +29 -0
index 0363dcb..3c54e3c 100644
@@ -408,6 +408,35 @@
 extern void __iomem *prm_base;
 extern void __iomem *cm_base;
 extern void __iomem *cm2_base;
+
+struct omap_prcm_irq {
+	const char *name;
+	unsigned int offset;
+	bool priority;
+};
+
+struct omap_prcm_irq_setup {
+	u32 ack;
+	u32 mask;
+	int nr_regs;
+	int nr_irqs;
+	const struct omap_prcm_irq *irqs;
+	u32 *saved_mask;
+	u32 *priority_mask;
+	int base_irq;
+	int irq;
+};
+
+#define OMAP_PRCM_IRQ(_name, _offset, _priority) {	\
+	.name = _name,					\
+	.offset = _offset,				\
+	.priority = _priority				\
+	}
+
+extern void omap_prcm_irq_cleanup(void);
+extern int omap_prcm_register_chain_handler(
+	struct omap_prcm_irq_setup *irq_setup);
+extern int omap_prcm_event_to_irq(const char *event);
 # endif
 
 #endif
arch/arm/mach-omap2/prcm.c +229 -0

244 lines not on this page · raw message

arch/arm/mach-omap2/prm2xxx_3xxx.c +21 -0
index f02d87f..9f1aad3 100644
@@ -27,6 +27,20 @@
 #include "prm-regbits-24xx.h"
 #include "prm-regbits-34xx.h"
 
+static const struct omap_prcm_irq omap3_prcm_irqs[] = {
+	OMAP_PRCM_IRQ("wkup",	0,	0),
+	OMAP_PRCM_IRQ("io",	9,	1),
+};
+
+static struct omap_prcm_irq_setup omap3_prcm_irq_setup = {
+	.ack		= OMAP3_PRM_IRQSTATUS_MPU_OFFSET,
+	.mask		= OMAP3_PRM_IRQENABLE_MPU_OFFSET,
+	.nr_regs	= 1,
+	.irqs		= omap3_prcm_irqs,
+	.nr_irqs	= ARRAY_SIZE(omap3_prcm_irqs),
+	.irq		= INT_34XX_PRCM_MPU_IRQ,
+};
+
 u32 omap2_prm_read_mod_reg(s16 module, u16 idx)
 {
 	return __raw_readl(prm_base + module + idx);
@@ -212,3 +226,10 @@ u32 omap3_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset)
 {
 	return omap2_prm_rmw_mod_reg_bits(mask, bits, OMAP3430_GR_MOD, offset);
 }
+
+static int __init omap3xxx_prcm_init(void)
+{
+	if (cpu_is_omap34xx())
+		return omap_prcm_register_chain_handler(&omap3_prcm_irq_setup);
+	return 0;
+}
arch/arm/mach-omap2/prm44xx.c +21 -0
index 495a31a..17614f7 100644
@@ -27,6 +27,20 @@
 #include "prcm44xx.h"
 #include "prminst44xx.h"
 
+static const struct omap_prcm_irq omap4_prcm_irqs[] = {
+	OMAP_PRCM_IRQ("wkup",   0,      0),
+	OMAP_PRCM_IRQ("io",     9,      1),
+};
+
+static struct omap_prcm_irq_setup omap4_prcm_irq_setup = {
+	.ack		= OMAP4_PRM_IRQSTATUS_MPU_OFFSET,
+	.mask		= OMAP4_PRM_IRQENABLE_MPU_OFFSET,
+	.nr_regs	= 2,
+	.irqs		= omap4_prcm_irqs,
+	.nr_irqs	= ARRAY_SIZE(omap4_prcm_irqs),
+	.irq		= OMAP44XX_IRQ_PRCM,
+};
+
 /* PRM low-level functions */
 
 /* Read a register in a CM/PRM instance in the PRM module */
@@ -121,3 +135,10 @@ u32 omap4_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset)
 					       OMAP4430_PRM_DEVICE_INST,
 					       offset);
 }
+
+static int __init omap4xxx_prcm_init(void)
+{
+	if (cpu_is_omap44xx())
+		return omap_prcm_register_chain_handler(&omap4_prcm_irq_setup);
+	return 0;
+}
Signature · 1 line
1.7.4.1
maintainer
#18 lore raw

PATCH v11 3/8 ARM: OMAP: prm: add support for chain interrupt handler

Quoted 11 lines · Tero Kristo

Introduce a chained interrupt handler mechanism for the PRCM interrupt, so that individual PRCM event can cleanly be handled by handlers in separate drivers. We do this by introducing PRCM event names, which are then matched to the particular PRCM interrupt bit depending on the specific OMAP SoC being used.

PRCM interrupts have two priority levels, high or normal. High priority is needed for IO event handling, so that we can be sure that IO events are processed before other events. This reduces latency for IO event customers and also prevents incorrect ack sequence on OMAP3.

Quoted 7 lines
Cc Paul Walmsley <[email protected]>
Cc Kevin Hilman <[email protected]>
Cc Avinash.H.M <[email protected]>
Cc Cousson, Benoit <[email protected]>
Cc Tony Lindgren <[email protected]>
Cc Govindraj.R <[email protected]>

Assuming Paul will queue these:

#19 lore raw

PATCH v11 4/8 ARM: OMAP: prcm: add suspend prepare / finish support

In reply to Tero Kristo

PRCM chain handler needs to disable forwarding of interrupts during suspend, because runtime PM is disabled and most of the drivers are potentially not able to handle interrupts coming at this time.

This patch masks all the PRCM interrupt events if a PRCM interrupt occurs during suspend, but does not ack them. Once suspend finish is called, all the masked events will be re-enabled, which causes immediate PRCM interrupt and handles the postponed event.

The suspend prepare and complete callbacks will be called from pm34xx.c / pm44xx.c files in the following patches.

The functions defined in this patch should eventually be moved to suspend->prepare and suspend->finish driver hooks, once the PRCM chain handler will be made as its own driver.

Cc Kevin Hilman <[email protected]>
Cc Paul Walmsley <[email protected]>
---
 arch/arm/mach-omap2/prcm-common.h |    4 +++
 arch/arm/mach-omap2/prcm.c        |   46 ++++++++++++++++++++++++++++++++++++-
 2 files changed, 49 insertions(+), 1 deletions(-)
arch/arm/mach-omap2/prcm-common.h +4 -0
index 3c54e3c..6cb0daf 100644
@@ -425,6 +425,8 @@ struct omap_prcm_irq_setup {
 	u32 *priority_mask;
 	int base_irq;
 	int irq;
+	bool suspended;
+	bool suspend_save_flag;
 };
 
 #define OMAP_PRCM_IRQ(_name, _offset, _priority) {	\
@@ -437,6 +439,8 @@ extern void omap_prcm_irq_cleanup(void);
 extern int omap_prcm_register_chain_handler(
 	struct omap_prcm_irq_setup *irq_setup);
 extern int omap_prcm_event_to_irq(const char *event);
+extern void omap_prcm_irq_prepare(void);
+extern void omap_prcm_irq_complete(void);
 # endif
 
 #endif
arch/arm/mach-omap2/prcm.c +45 -1

63 lines not on this page · raw message

Signature · 1 line
1.7.4.1
#20 lore raw

PATCH v11 5/8 ARM: OMAP2+: mux: add support for PAD wakeup interrupts

In reply to Tero Kristo

OMAP mux now parses active wakeup events from pad registers and calls corresponding hwmod ISRs once a wakeup is detected. This is accomplished by registering an interrupt handler for PRCM IO event, which is raised every time the HW detects wakeups.

---
 arch/arm/mach-omap2/mux.c |   38 ++++++++++++++++++++++++++++++++++++++
 1 files changed, 38 insertions(+), 0 deletions(-)
arch/arm/mach-omap2/mux.c +38 -0
index 5f15ab8..0d1962e 100644
@@ -32,6 +32,8 @@
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
 #include <linux/uaccess.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
 
 #include <asm/system.h>
 
@@ -39,6 +41,7 @@
 
 #include "control.h"
 #include "mux.h"
+#include "prcm-common.h"
 
 #define OMAP_MUX_BASE_OFFSET		0x30	/* Offset from CTRL_BASE */
 #define OMAP_MUX_BASE_SZ		0x5ca
@@ -381,6 +384,33 @@ bool omap_hwmod_mux_get_wake_status(struct omap_hwmod_mux_info *hmux)
 	return ret;
 }
 
+/**
+ * omap_hwmod_mux_handle_irq - Process wakeup events for a single hwmod
+ *
+ * Checks a single hwmod for every wakeup capable pad to see if there is an
+ * active wakeup event. If this is the case, call the corresponding ISR.
+ */
+static int _omap_hwmod_mux_handle_irq(struct omap_hwmod *oh, void *data)
+{
+	if (!oh->mux || !oh->mux->enabled)
+		return 0;
+	if (omap_hwmod_mux_get_wake_status(oh->mux))
+		generic_handle_irq(oh->mpu_irqs[0].irq);
+	return 0;
+}
+
+/**
+ * omap_hwmod_mux_handle_irq - Process pad wakeup irqs.
+ *
+ * Calls a function for each registered omap_hwmod to check
+ * pad wakeup statuses.
+ */
+static irqreturn_t omap_hwmod_mux_handle_irq(int irq, void *unused)
+{
+	omap_hwmod_for_each(_omap_hwmod_mux_handle_irq, NULL);
+	return IRQ_HANDLED;
+}
+
 /* Assumes the calling function takes care of locking */
 void omap_hwmod_mux(struct omap_hwmod_mux_info *hmux, u8 state)
 {
@@ -745,6 +775,7 @@ static void __init omap_mux_free_names(struct omap_mux *m)
 static int __init omap_mux_late_init(void)
 {
 	struct omap_mux_partition *partition;
+	int ret;
 
 	list_for_each_entry(partition, &mux_partitions, node) {
 		struct omap_mux_entry *e, *tmp;
@@ -765,6 +796,13 @@ static int __init omap_mux_late_init(void)
 		}
 	}
 
+	ret = request_irq(omap_prcm_event_to_irq("io"),
+		omap_hwmod_mux_handle_irq, IRQF_SHARED | IRQF_NO_SUSPEND,
+			"hwmod_io", omap_mux_late_init);
+
+	if (ret)
+		printk(KERN_WARNING "Failed to setup hwmod io irq %d\n", ret);
+
 	omap_mux_dbg_init();
 
 	return 0;
Signature · 1 line
1.7.4.1
maintainer
#21 lore raw

PATCH v11 5/8 ARM: OMAP2+: mux: add support for PAD wakeup interrupts

Quoted 6 lines · Tero Kristo

OMAP mux now parses active wakeup events from pad registers and calls corresponding hwmod ISRs once a wakeup is detected. This is accomplished by registering an interrupt handler for PRCM IO event, which is raised every time the HW detects wakeups.

This will need to be updated once we are using the pinctrl framework, for now this looks good to me:

#22 lore raw

PATCH v11 6/8 ARM: OMAP3: pm: use prcm chain handler

In reply to Tero Kristo

PM interrupt handling is now done through the PRCM chain handler. The interrupt handling logic is also split in two parts, to serve IO and WKUP events separately. This allows us to handle IO chain events in a clean way.

Core event code is also changed in accordance to this, as PRCM interrupt handling is done by independent handlers, and the core handler should not clear the IO events anymore.

---
 arch/arm/mach-omap2/pm34xx.c       |  111 ++++++++++++++----------------------
 arch/arm/mach-omap2/prm2xxx_3xxx.c |    1 +
 2 files changed, 45 insertions(+), 67 deletions(-)
arch/arm/mach-omap2/pm34xx.c +44 -67
index efa6649..5fd99e5 100644
@@ -194,7 +194,7 @@ static void omap3_save_secure_ram_context(void)
  * that any peripheral wake-up events occurring while attempting to
  * clear the PM_WKST_x are detected and cleared.
  */
-static int prcm_clear_mod_irqs(s16 module, u8 regs)
+static int prcm_clear_mod_irqs(s16 module, u8 regs, u32 ignore_bits)
 {
 	u32 wkst, fclk, iclk, clken;
 	u16 wkst_off = (regs == 3) ? OMAP3430ES2_PM_WKST3 : PM_WKST1;
@@ -206,6 +206,7 @@ static int prcm_clear_mod_irqs(s16 module, u8 regs)
 
 	wkst = omap2_prm_read_mod_reg(module, wkst_off);
 	wkst &= omap2_prm_read_mod_reg(module, grpsel_off);
+	wkst &= ~ignore_bits;
 	if (wkst) {
 		iclk = omap2_cm_read_mod_reg(module, iclk_off);
 		fclk = omap2_cm_read_mod_reg(module, fclk_off);
@@ -221,6 +222,7 @@ static int prcm_clear_mod_irqs(s16 module, u8 regs)
 			omap2_cm_set_mod_reg_bits(clken, module, fclk_off);
 			omap2_prm_write_mod_reg(wkst, module, wkst_off);
 			wkst = omap2_prm_read_mod_reg(module, wkst_off);
+			wkst &= ~ignore_bits;
 			c++;
 		}
 		omap2_cm_write_mod_reg(iclk, module, iclk_off);
@@ -230,76 +232,35 @@ static int prcm_clear_mod_irqs(s16 module, u8 regs)
 	return c;
 }
 
-static int _prcm_int_handle_wakeup(void)
+static irqreturn_t _prcm_int_handle_io(int irq, void *unused)
 {
 	int c;
 
-	c = prcm_clear_mod_irqs(WKUP_MOD, 1);
-	c += prcm_clear_mod_irqs(CORE_MOD, 1);
-	c += prcm_clear_mod_irqs(OMAP3430_PER_MOD, 1);
-	if (omap_rev() > OMAP3430_REV_ES1_0) {
-		c += prcm_clear_mod_irqs(CORE_MOD, 3);
-		c += prcm_clear_mod_irqs(OMAP3430ES2_USBHOST_MOD, 1);
-	}
+	c = prcm_clear_mod_irqs(WKUP_MOD, 1,
+		~(OMAP3430_ST_IO_MASK | OMAP3430_ST_IO_CHAIN_MASK));
 
-	return c;
+	return c ? IRQ_HANDLED : IRQ_NONE;
 }
 
-/*
- * PRCM Interrupt Handler
- *
- * The PRM_IRQSTATUS_MPU register indicates if there are any pending
- * interrupts from the PRCM for the MPU. These bits must be cleared in
- * order to clear the PRCM interrupt. The PRCM interrupt handler is
- * implemented to simply clear the PRM_IRQSTATUS_MPU in order to clear
- * the PRCM interrupt. Please note that bit 0 of the PRM_IRQSTATUS_MPU
- * register indicates that a wake-up event is pending for the MPU and
- * this bit can only be cleared if the all the wake-up events latched
- * in the various PM_WKST_x registers have been cleared. The interrupt
- * handler is implemented using a do-while loop so that if a wake-up
- * event occurred during the processing of the prcm interrupt handler
- * (setting a bit in the corresponding PM_WKST_x register and thus
- * preventing us from clearing bit 0 of the PRM_IRQSTATUS_MPU register)
- * this would be handled.
- */
-static irqreturn_t prcm_interrupt_handler (int irq, void *dev_id)
+static irqreturn_t _prcm_int_handle_wakeup(int irq, void *unused)
 {
-	u32 irqenable_mpu, irqstatus_mpu;
-	int c = 0;
-
-	irqenable_mpu = omap2_prm_read_mod_reg(OCP_MOD,
-					 OMAP3_PRM_IRQENABLE_MPU_OFFSET);
-	irqstatus_mpu = omap2_prm_read_mod_reg(OCP_MOD,
-					 OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
-	irqstatus_mpu &= irqenable_mpu;
-
-	do {
-		if (irqstatus_mpu & (OMAP3430_WKUP_ST_MASK |
-				     OMAP3430_IO_ST_MASK)) {
-			c = _prcm_int_handle_wakeup();
-
-			/*
-			 * Is the MPU PRCM interrupt handler racing with the
-			 * IVA2 PRCM interrupt handler ?
-			 */
-			WARN(c == 0, "prcm: WARNING: PRCM indicated MPU wakeup "
-			     "but no wakeup sources are marked\n");
-		} else {
-			/* XXX we need to expand our PRCM interrupt handler */
-			WARN(1, "prcm: WARNING: PRCM interrupt received, but "
-			     "no code to handle it (%08x)\n", irqstatus_mpu);
-		}
-
-		omap2_prm_write_mod_reg(irqstatus_mpu, OCP_MOD,
-					OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
-
-		irqstatus_mpu = omap2_prm_read_mod_reg(OCP_MOD,
-					OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
-		irqstatus_mpu &= irqenable_mpu;
+	int c;
 
-	} while (irqstatus_mpu);
+	/*
+	 * Clear all except ST_IO and ST_IO_CHAIN for wkup module,
+	 * these are handled in a separate handler to avoid acking
+	 * IO events before parsing in mux code
+	 */
+	c = prcm_clear_mod_irqs(WKUP_MOD, 1,
+		OMAP3430_ST_IO_MASK | OMAP3430_ST_IO_CHAIN_MASK);
+	c += prcm_clear_mod_irqs(CORE_MOD, 1, 0);
+	c += prcm_clear_mod_irqs(OMAP3430_PER_MOD, 1, 0);
+	if (omap_rev() > OMAP3430_REV_ES1_0) {
+		c += prcm_clear_mod_irqs(CORE_MOD, 3, 0);
+		c += prcm_clear_mod_irqs(OMAP3430ES2_USBHOST_MOD, 1, 0);
+	}
 
-	return IRQ_HANDLED;
+	return c ? IRQ_HANDLED : IRQ_NONE;
 }
 
 static void omap34xx_save_context(u32 *save)
@@ -580,6 +541,7 @@ static int omap3_pm_begin(suspend_state_t state)
 	disable_hlt();
 	suspend_state = state;
 	omap_uart_enable_irqs(0);
+	omap_prcm_irq_prepare();
 	return 0;
 }
 
@@ -591,10 +553,16 @@ static void omap3_pm_end(void)
 	return;
 }
 
+static void omap3_pm_finish(void)
+{
+	omap_prcm_irq_complete();
+}
+
 static const struct platform_suspend_ops omap_pm_ops = {
 	.begin		= omap3_pm_begin,
 	.end		= omap3_pm_end,
 	.enter		= omap3_pm_enter,
+	.finish		= omap3_pm_finish,
 	.valid		= suspend_valid_only_mem,
 };
 #endif /* CONFIG_SUSPEND */
@@ -880,12 +848,21 @@ static int __init omap3_pm_init(void)
 	 * supervised mode for powerdomains */
 	prcm_setup_regs();
 
-	ret = request_irq(INT_34XX_PRCM_MPU_IRQ,
-			  (irq_handler_t)prcm_interrupt_handler,
-			  IRQF_DISABLED, "prcm", NULL);
+	ret = request_irq(omap_prcm_event_to_irq("wkup"),
+		_prcm_int_handle_wakeup, IRQF_NO_SUSPEND, "pm_wkup", NULL);
+
+	if (ret) {
+		printk(KERN_ERR "Failed to request pm_wkup irq\n");
+		goto err1;
+	}
+
+	/* IO interrupt is shared with mux code */
+	ret = request_irq(omap_prcm_event_to_irq("io"),
+		_prcm_int_handle_io, IRQF_SHARED | IRQF_NO_SUSPEND, "pm_io",
+		omap3_pm_init);
+
 	if (ret) {
-		printk(KERN_ERR "request_irq failed to register for 0x%x\n",
-		       INT_34XX_PRCM_MPU_IRQ);
+		printk(KERN_ERR "Failed to request pm_io irq\n");
 		goto err1;
 	}
 
arch/arm/mach-omap2/prm2xxx_3xxx.c +1 -0
index 9f1aad3..0fc72a4 100644
@@ -233,3 +233,4 @@ static int __init omap3xxx_prcm_init(void)
 		return omap_prcm_register_chain_handler(&omap3_prcm_irq_setup);
 	return 0;
 }
+subsys_initcall(omap3xxx_prcm_init);
Signature · 1 line
1.7.4.1
#23 lore raw

PATCH v11 7/8 ARM: OMAP3: pm: do not enable PRCM MPU interrupts manually

In reply to Tero Kristo

This is handled automatically by the PRCM chain interrupt mechanism now.

---
 arch/arm/mach-omap2/pm34xx.c |    4 ----
 1 files changed, 0 insertions(+), 4 deletions(-)
arch/arm/mach-omap2/pm34xx.c +0 -4
index 5fd99e5..d5ce8d2 100644
@@ -668,10 +668,6 @@ static void __init prcm_setup_regs(void)
 			  OMAP3430_GRPSEL_GPT1_MASK |
 			  OMAP3430_GRPSEL_GPT12_MASK,
 			  WKUP_MOD, OMAP3430_PM_MPUGRPSEL);
-	/* For some reason IO doesn't generate wakeup event even if
-	 * it is selected to mpu wakeup goup */
-	omap2_prm_write_mod_reg(OMAP3430_IO_EN_MASK | OMAP3430_WKUP_EN_MASK,
-			  OCP_MOD, OMAP3_PRM_IRQENABLE_MPU_OFFSET);
 
 	/* Enable PM_WKEN to support DSS LPR */
 	omap2_prm_write_mod_reg(OMAP3430_PM_WKEN_DSS_EN_DSS_MASK,
Signature · 1 line
1.7.4.1
#24 lore raw

PATCH v11 8/8 ARM: OMAP: mux: add support for selecting mpu_irq for each wakeup pad

In reply to Tero Kristo

By default all registered pads will trigger mpu_irqs[0]. Now there is an API for selecting used mpu_irq on pad basis, which can be used to trigger different irq handlers for different pads in the same hwmod. Each pad that requires its interrupt to be re-routed this way must have a separate call to omap_hwmod_pad_route_irq(hwmod, pad, irq).

---
 arch/arm/mach-omap2/mux.c                    |   67 ++++++++++++++++++++++----
 arch/arm/mach-omap2/omap_hwmod.c             |    7 ---
 arch/arm/plat-omap/include/plat/omap_hwmod.h |    4 ++
 3 files changed, 61 insertions(+), 17 deletions(-)
arch/arm/mach-omap2/mux.c +57 -10
index 0d1962e..2da3f3d 100644
@@ -354,19 +354,53 @@ err1:
 	return NULL;
 }
 
+int omap_hwmod_pad_route_irq(struct omap_hwmod *oh, int pad_idx,
+		int irq_idx)
+{
+	int nr_irqs;
+
+	if (!oh || !oh->mux || !oh->mpu_irqs || pad_idx < 0 ||
+	    pad_idx >= oh->mux->nr_pads_dynamic)
+		return -EINVAL;
+
+	/* Check the number of available mpu_irqs */
+	for (nr_irqs = 0; oh->mpu_irqs[nr_irqs].irq >= 0; nr_irqs++)
+		;
+
+	if (irq_idx >= nr_irqs)
+		return -EINVAL;
+
+	if (!oh->mux->irqs) {
+		oh->mux->irqs = kzalloc(sizeof(int) * oh->mux->nr_pads_dynamic,
+			GFP_KERNEL);
+		if (!oh->mux->irqs)
+			return -ENOMEM;
+	}
+	oh->mux->irqs[pad_idx] = irq_idx;
+
+	return 0;
+}
+
 /**
- * omap_hwmod_mux_get_wake_status - omap hwmod check pad wakeup
+ * omap_hwmod_mux_scan_wakeups - omap hwmod scan wakeup pads
  * @hmux:		Pads for a hwmod
+ * @mpu_irqs:		MPU irq array for a hwmod
  *
- * Gets the wakeup status of given pad from omap-hwmod.
- * Returns true if wakeup event is set for pad else false
- * if wakeup is not occured or pads are not avialable.
+ * Scans the wakeup status of pads for a single hwmod.
+ * If an irq array is defined for this mux, the parser
+ * will call the registered ISRs for corresponding pads,
+ * otherwise the parser will stop at the first wakeup
+ * active pad and return.
+ * Returns true if there is a pending and non-served
+ * wakeup event for the mux, otherwise false.
  */
-bool omap_hwmod_mux_get_wake_status(struct omap_hwmod_mux_info *hmux)
+static bool omap_hwmod_mux_scan_wakeups(struct omap_hwmod_mux_info *hmux,
+		struct omap_hwmod_irq_info *mpu_irqs)
 {
 	int i;
 	unsigned int val;
-	u8 ret = false;
+	u32 handled_irqs = 0;
+	int irq;
 
 	for (i = 0; i < hmux->nr_pads; i++) {
 		struct omap_device_pad *pad = &hmux->pads[i];
@@ -375,13 +409,26 @@ bool omap_hwmod_mux_get_wake_status(struct omap_hwmod_mux_info *hmux)
 			val = omap_mux_read(pad->partition,
 					pad->mux->reg_offset);
 			if (val & OMAP_WAKEUP_EVENT) {
-				ret = true;
-				break;
+				if (hmux->irqs) {
+					irq = hmux->irqs[i];
+					/*
+					 * make sure we only handle each
+					 * irq once
+					 */
+					if (handled_irqs & 1 << irq)
+						continue;
+
+					handled_irqs |= 1 << irq;
+
+					generic_handle_irq(mpu_irqs[irq].irq);
+				} else {
+					return true;
+				}
 			}
 		}
 	}
 
-	return ret;
+	return false;
 }
 
 /**
@@ -394,7 +441,7 @@ static int _omap_hwmod_mux_handle_irq(struct omap_hwmod *oh, void *data)
 {
 	if (!oh->mux || !oh->mux->enabled)
 		return 0;
-	if (omap_hwmod_mux_get_wake_status(oh->mux))
+	if (omap_hwmod_mux_scan_wakeups(oh->mux, oh->mpu_irqs))
 		generic_handle_irq(oh->mpu_irqs[0].irq);
 	return 0;
 }
arch/arm/mach-omap2/omap_hwmod.c +0 -7
index d7f4623..8d37d83 100644
@@ -2721,10 +2721,3 @@ int omap_hwmod_no_setup_reset(struct omap_hwmod *oh)
 
 	return 0;
 }
-
-int omap_hwmod_pad_get_wakeup_status(struct omap_hwmod *oh)
-{
-	if (oh && oh->mux)
-		return omap_hwmod_mux_get_wake_status(oh->mux);
-	return -EINVAL;
-}
arch/arm/plat-omap/include/plat/omap_hwmod.h +4 -0
index 1b81dfb..a5f0a5f 100644
@@ -97,6 +97,7 @@ struct omap_hwmod_mux_info {
 	struct omap_device_pad		*pads;
 	int				nr_pads_dynamic;
 	struct omap_device_pad		**pads_dynamic;
+	int				*irqs;
 	bool				enabled;
 };
 
@@ -605,6 +606,9 @@ int omap_hwmod_get_context_loss_count(struct omap_hwmod *oh);
 int omap_hwmod_no_setup_reset(struct omap_hwmod *oh);
 
 int omap_hwmod_pad_get_wakeup_status(struct omap_hwmod *oh);
+
+int omap_hwmod_pad_route_irq(struct omap_hwmod *oh, int pad_idx, int irq_idx);
+
 /*
  * Chip variant-specific hwmod init routines - XXX should be converted
  * to use initcalls once the initial boot ordering is straightened out
Signature · 1 line
1.7.4.1
maintainer
#25 lore raw

PATCH v11 8/8 ARM: OMAP: mux: add support for selecting mpu_irq for each wakeup pad

Quoted 7 lines · Tero Kristo

By default all registered pads will trigger mpu_irqs[0]. Now there is an API for selecting used mpu_irq on pad basis, which can be used to trigger different irq handlers for different pads in the same hwmod. Each pad that requires its interrupt to be re-routed this way must have a separate call to omap_hwmod_pad_route_irq(hwmod, pad, irq).

#26 lore raw

v11 cover OMAP3+: PRCM chain handler

In reply to Tero Kristo
Quoted 10 lines · Tero Kristo

PRCM chain handler is adding a support to the omap3+ kernel that allows different drivers to use PRCM interrupt events for their own purposes, typically this means IO wakeups. This work was attempted to integrate as its own driver at some point of the evolution of this set, however this was now postponed as the lacking support is basically blocking a few drivers.

This is the version 11 of this set, now posted to linux-arm-kernel also as cc. Contains just a couple of minor changes compared to previous version proposed by Kevin Hilman.

Thanks Tero for the quick update.

All of this series can go through Paul, so from my side

Kevin