2 * Copyright (C) 2010 Google, Inc.
5 * Colin Cross <ccross@google.com>
7 * Copyright (C) 2010, NVIDIA Corporation
9 * This software is licensed under the terms of the GNU General Public
10 * License version 2, as published by the Free Software Foundation, and
11 * may be copied, distributed, and modified under those terms.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
20 #include <linux/kernel.h>
21 #include <linux/delay.h>
22 #include <linux/init.h>
23 #include <linux/interrupt.h>
24 #include <linux/irq.h>
27 #include <asm/hardware/gic.h>
29 #include <mach/iomap.h>
30 #include <mach/legacy_irq.h>
31 #include <mach/suspend.h>
36 #define PMC_CTRL_LATCH_WAKEUPS (1 << 5)
37 #define PMC_WAKE_MASK 0xc
38 #define PMC_WAKE_LEVEL 0x10
39 #define PMC_WAKE_STATUS 0x14
40 #define PMC_SW_WAKE_STATUS 0x18
41 #define PMC_DPD_SAMPLE 0x20
43 static void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE);
45 static u32 tegra_lp0_wake_enb;
46 static u32 tegra_lp0_wake_level;
47 static u32 tegra_lp0_wake_level_any;
49 /* ensures that sufficient time is passed for a register write to
50 * serialize into the 32KHz domain */
51 static void pmc_32kwritel(u32 val, unsigned long offs)
53 writel(val, pmc + offs);
57 int tegra_set_lp0_wake(int irq, int enable)
59 int wake = tegra_irq_to_wake(irq);
65 tegra_lp0_wake_enb |= 1 << wake;
67 tegra_lp0_wake_enb &= ~(1 << wake);
72 int tegra_set_lp0_wake_type(int irq, int flow_type)
74 int wake = tegra_irq_to_wake(irq);
80 case IRQF_TRIGGER_FALLING:
81 case IRQF_TRIGGER_LOW:
82 tegra_lp0_wake_level &= ~(1 << wake);
83 tegra_lp0_wake_level_any &= ~(1 << wake);
85 case IRQF_TRIGGER_HIGH:
86 case IRQF_TRIGGER_RISING:
87 tegra_lp0_wake_level |= 1 << wake;
88 tegra_lp0_wake_level_any &= ~(1 << wake);
91 case IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING:
92 tegra_lp0_wake_level_any |= 1 << wake;
102 int tegra_set_lp1_wake(int irq, int enable)
104 return tegra_legacy_irq_set_wake(irq, enable);
107 void tegra_set_lp0_wake_pads(u32 wake_enb, u32 wake_level, u32 wake_any)
113 wake_level &= wake_enb;
114 wake_any &= wake_enb;
116 wake_level |= (tegra_lp0_wake_level & tegra_lp0_wake_enb);
117 wake_any |= (tegra_lp0_wake_level_any & tegra_lp0_wake_enb);
119 wake_enb |= tegra_lp0_wake_enb;
121 pmc_32kwritel(0, PMC_SW_WAKE_STATUS);
122 temp = readl(pmc + PMC_CTRL);
123 temp |= PMC_CTRL_LATCH_WAKEUPS;
124 pmc_32kwritel(temp, PMC_CTRL);
125 temp &= ~PMC_CTRL_LATCH_WAKEUPS;
126 pmc_32kwritel(temp, PMC_CTRL);
127 status = readl(pmc + PMC_SW_WAKE_STATUS);
128 lvl = readl(pmc + PMC_WAKE_LEVEL);
130 /* flip the wakeup trigger for any-edge triggered pads
131 * which are currently asserting as wakeups */
137 writel(wake_level, pmc + PMC_WAKE_LEVEL);
138 /* Enable DPD sample to trigger sampling pads data and direction
139 * in which pad will be driven during lp0 mode*/
140 writel(0x1, pmc + PMC_DPD_SAMPLE);
142 writel(wake_enb, pmc + PMC_WAKE_MASK);
145 static void tegra_irq_handle_wake(void)
149 struct irq_desc *desc;
151 unsigned long wake_status = readl(pmc + PMC_WAKE_STATUS);
152 for_each_set_bit(wake, &wake_status, sizeof(wake_status) * 8) {
153 irq = tegra_wake_to_irq(wake);
155 pr_info("Resume caused by WAKE%d\n", wake);
159 desc = irq_to_desc(irq);
160 if (!desc || !desc->action || !desc->action->name) {
161 pr_info("Resume caused by WAKE%d, irq %d\n", wake, irq);
165 pr_info("Resume caused by WAKE%d, %s\n", wake,
168 generic_handle_irq(irq);
172 static void tegra_mask(unsigned int irq)
175 tegra_legacy_mask_irq(irq);
178 static void tegra_unmask(unsigned int irq)
181 tegra_legacy_unmask_irq(irq);
184 static int tegra_set_wake(unsigned int irq, unsigned int enable)
187 ret = tegra_set_lp1_wake(irq, enable);
191 if (tegra_get_suspend_mode() == TEGRA_SUSPEND_LP0)
192 return tegra_set_lp0_wake(irq, enable);
197 static int tegra_set_type(unsigned int irq, unsigned int flow_type)
199 if (tegra_get_suspend_mode() == TEGRA_SUSPEND_LP0)
200 return tegra_set_lp0_wake_type(irq, flow_type);
205 static void tegra_ack(unsigned int irq)
207 tegra_legacy_force_irq_clr(irq);
211 static int tegra_retrigger(unsigned int irq)
213 tegra_legacy_force_irq_set(irq);
217 static struct irq_chip tegra_irq = {
221 .unmask = tegra_unmask,
222 .set_wake = tegra_set_wake,
223 .set_type = tegra_set_type,
225 .set_affinity = gic_set_cpu,
227 .retrigger = tegra_retrigger,
230 void __init tegra_init_irq(void)
235 tegra_init_legacy_irq();
237 gic_dist_init(0, IO_ADDRESS(TEGRA_ARM_INT_DIST_BASE), 29);
238 gic_cpu_init(0, IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x100));
240 for (i = 0; i < INT_MAIN_NR; i++) {
241 irq = INT_PRI_BASE + i;
242 set_irq_chip(irq, &tegra_irq);
243 set_irq_handler(irq, handle_level_irq);
244 set_irq_flags(irq, IRQF_VALID);
248 void tegra_irq_suspend(void)
250 tegra_legacy_irq_suspend();
253 void tegra_irq_resume(void)
255 tegra_legacy_irq_resume();
256 tegra_irq_handle_wake();