[ARM] tegra: irq: Add set_wake and set_type support for suspend

Change-Id: Ic18e0c92462a590b759752662bd7d67aaf8a371a
Signed-off-by: Colin Cross <ccross@android.com>
This commit is contained in:
Colin Cross
2010-10-04 00:25:16 -07:00
parent 75a8c9a008
commit 23a6890fa8
3 changed files with 110 additions and 3 deletions

View File

@@ -31,5 +31,6 @@ int tegra_legacy_irq_set_wake(int irq, int enable);
void tegra_legacy_irq_set_lp1_wake_mask(void);
void tegra_legacy_irq_restore_mask(void);
void tegra_init_legacy_irq(void);
void tegra_legacy_irq_suspend(void);
void tegra_legacy_irq_resume(void);
#endif

View File

@@ -54,6 +54,51 @@ static void pmc_32kwritel(u32 val, unsigned long offs)
udelay(130);
}
int tegra_set_lp0_wake(int irq, int enable)
{
int wake = tegra_irq_to_wake(irq);
if (wake < 0)
return -EINVAL;
if (enable)
tegra_lp0_wake_enb |= 1 << wake;
else
tegra_lp0_wake_enb &= ~(1 << wake);
return 0;
}
int tegra_set_lp0_wake_type(int irq, int flow_type)
{
int wake = tegra_irq_to_wake(irq);
if (wake < 0)
return 0;
switch (flow_type) {
case IRQF_TRIGGER_FALLING:
case IRQF_TRIGGER_LOW:
tegra_lp0_wake_level &= ~(1 << wake);
tegra_lp0_wake_level_any &= ~(1 << wake);
break;
case IRQF_TRIGGER_HIGH:
case IRQF_TRIGGER_RISING:
tegra_lp0_wake_level |= 1 << wake;
tegra_lp0_wake_level_any &= ~(1 << wake);
break;
case IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING:
tegra_lp0_wake_level_any |= 1 << wake;
break;
default:
return -EINVAL;
}
return 0;
}
int tegra_set_lp1_wake(int irq, int enable)
{
return tegra_legacy_irq_set_wake(irq, enable);
@@ -97,6 +142,33 @@ void tegra_set_lp0_wake_pads(u32 wake_enb, u32 wake_level, u32 wake_any)
writel(wake_enb, pmc + PMC_WAKE_MASK);
}
static void tegra_irq_handle_wake(void)
{
int wake;
int irq;
struct irq_desc *desc;
unsigned long wake_status = readl(pmc + PMC_WAKE_STATUS);
for_each_set_bit(wake, &wake_status, sizeof(wake_status) * 8) {
irq = tegra_wake_to_irq(wake);
if (!irq) {
pr_info("Resume caused by WAKE%d\n", wake);
continue;
}
desc = irq_to_desc(irq);
if (!desc || !desc->action || !desc->action->name) {
pr_info("Resume caused by WAKE%d, irq %d\n", wake, irq);
continue;
}
pr_info("Resume caused by WAKE%d, %s\n", wake,
desc->action->name);
generic_handle_irq(irq);
}
}
static void tegra_mask(unsigned int irq)
{
gic_mask_irq(irq);
@@ -109,11 +181,34 @@ static void tegra_unmask(unsigned int irq)
tegra_legacy_unmask_irq(irq);
}
static int tegra_set_wake(unsigned int irq, unsigned int enable)
{
int ret;
ret = tegra_set_lp1_wake(irq, enable);
if (ret)
return ret;
if (tegra_get_suspend_mode() == TEGRA_SUSPEND_LP0)
return tegra_set_lp0_wake(irq, enable);
return 0;
}
static int tegra_set_type(unsigned int irq, unsigned int flow_type)
{
if (tegra_get_suspend_mode() == TEGRA_SUSPEND_LP0)
return tegra_set_lp0_wake_type(irq, flow_type);
return 0;
}
static struct irq_chip tegra_irq = {
.name = "PPI",
.ack = gic_ack_irq,
.mask = tegra_mask,
.unmask = tegra_unmask,
.set_wake = tegra_set_wake,
.set_type = tegra_set_type,
#ifdef CONFIG_SMP
.set_affinity = gic_set_cpu,
#endif
@@ -136,3 +231,14 @@ void __init tegra_init_irq(void)
set_irq_flags(irq, IRQF_VALID);
}
}
void tegra_irq_suspend(void)
{
tegra_legacy_irq_suspend();
}
void tegra_irq_resume(void)
{
tegra_legacy_irq_resume();
tegra_irq_handle_wake();
}

View File

@@ -179,7 +179,7 @@ static u32 cop_ier[NUM_ICTLRS];
static u32 cpu_ier[NUM_ICTLRS];
static u32 cpu_iep[NUM_ICTLRS];
void tegra_irq_suspend(void)
void tegra_legacy_irq_suspend(void)
{
unsigned long flags;
int i;
@@ -195,7 +195,7 @@ void tegra_irq_suspend(void)
local_irq_restore(flags);
}
void tegra_irq_resume(void)
void tegra_legacy_irq_resume(void)
{
unsigned long flags;
int i;