Skip to content

Commit

Permalink
ARM: OMAP2+: mux: add support for PAD wakeup interrupts
Browse files Browse the repository at this point in the history
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.

[paul@pwsan.com: This patch is a merge of Govindraj R's "ARM: OMAP2+:
hwmod: Add API to check IO PAD wakeup status" patch, Tero Kristo's
"ARM: OMAP2+: mux: add support for PAD wakeup interrupts" patch, and
part of Tero's "ARM: OMAP: mux: add support for selecting mpu_irq for
each wakeup pad" patch.]

Signed-off-by: Tero Kristo <t-kristo@ti.com>
Cc: Govindraj.R <govindraj.raja@ti.com>
Tested-by: Kevin Hilman <khilman@ti.com>
Reviewed-by: Kevin Hilman <khilman@ti.com>
Acked-by: Tony Lindgren <tony@atomide.com>
[paul@pwsan.com: reduced indentation level; renamed omap_hwmod function;
 improved function documentation; modified to iterate only through dynamic
 pads; modified to skip pads where idle mode doesn't enable wakeups; split
 patches]
Signed-off-by: Paul Walmsley <paul@pwsan.com>
  • Loading branch information
Tero Kristo authored and Paul Walmsley committed Dec 16, 2011
1 parent 91285b6 commit 13a3fe5
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 0 deletions.
83 changes: 83 additions & 0 deletions arch/arm/mach-omap2/mux.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,16 @@
#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>

#include <plat/omap_hwmod.h>

#include "control.h"
#include "mux.h"
#include "prm.h"

#define OMAP_MUX_BASE_OFFSET 0x30 /* Offset from CTRL_BASE */
#define OMAP_MUX_BASE_SZ 0x5ca
Expand Down Expand Up @@ -353,6 +356,78 @@ omap_hwmod_mux_init(struct omap_device_pad *bpads, int nr_pads)
return NULL;
}

/**
* omap_hwmod_mux_scan_wakeups - omap hwmod scan wakeup pads
* @hmux: Pads for a hwmod
* @mpu_irqs: MPU irq array for a hwmod
*
* 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.
*/
static bool omap_hwmod_mux_scan_wakeups(struct omap_hwmod_mux_info *hmux,
struct omap_hwmod_irq_info *mpu_irqs)
{
int i, irq;
unsigned int val;
u32 handled_irqs = 0;

for (i = 0; i < hmux->nr_pads_dynamic; i++) {
struct omap_device_pad *pad = hmux->pads_dynamic[i];

if (!(pad->flags & OMAP_DEVICE_PAD_WAKEUP) ||
!(pad->idle & OMAP_WAKEUP_EN))
continue;

val = omap_mux_read(pad->partition, pad->mux->reg_offset);
if (!(val & OMAP_WAKEUP_EVENT))
continue;

if (!hmux->irqs)
return true;

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);
}

return false;
}

/**
* _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_scan_wakeups(oh->mux, oh->mpu_irqs))
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)
{
Expand Down Expand Up @@ -717,6 +792,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;
Expand All @@ -737,6 +813,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)
pr_warning("mux: Failed to setup hwmod io irq %d\n", ret);

omap_mux_dbg_init();

return 0;
Expand Down
1 change: 1 addition & 0 deletions arch/arm/plat-omap/include/plat/omap_hwmod.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};

Expand Down

0 comments on commit 13a3fe5

Please sign in to comment.