Merge branch 'android-2.6.36' into android-tegra-2.6.36
[firefly-linux-kernel-4.4.55.git] / arch / arm / mach-tegra / irq.c
1 /*
2  * Copyright (C) 2010 Google, Inc.
3  *
4  * Author:
5  *      Colin Cross <ccross@google.com>
6  *
7  * Copyright (C) 2010, NVIDIA Corporation
8  *
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.
12  *
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.
17  *
18  */
19
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>
25 #include <linux/io.h>
26
27 #include <asm/hardware/gic.h>
28
29 #include <mach/iomap.h>
30 #include <mach/legacy_irq.h>
31 #include <mach/suspend.h>
32
33 #include "board.h"
34
35 #define PMC_CTRL                0x0
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
42
43 static void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE);
44
45 static u32 tegra_lp0_wake_enb;
46 static u32 tegra_lp0_wake_level;
47 static u32 tegra_lp0_wake_level_any;
48
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)
52 {
53         writel(val, pmc + offs);
54         udelay(130);
55 }
56
57 int tegra_set_lp0_wake(int irq, int enable)
58 {
59         int wake = tegra_irq_to_wake(irq);
60
61         if (wake < 0)
62                 return -EINVAL;
63
64         if (enable)
65                 tegra_lp0_wake_enb |= 1 << wake;
66         else
67                 tegra_lp0_wake_enb &= ~(1 << wake);
68
69         return 0;
70 }
71
72 int tegra_set_lp0_wake_type(int irq, int flow_type)
73 {
74         int wake = tegra_irq_to_wake(irq);
75
76         if (wake < 0)
77                 return 0;
78
79         switch (flow_type) {
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);
84                 break;
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);
89                 break;
90
91         case IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING:
92                 tegra_lp0_wake_level_any |= 1 << wake;
93                 break;
94         default:
95                 return -EINVAL;
96         }
97
98         return 0;
99 }
100
101
102 int tegra_set_lp1_wake(int irq, int enable)
103 {
104         return tegra_legacy_irq_set_wake(irq, enable);
105 }
106
107 void tegra_set_lp0_wake_pads(u32 wake_enb, u32 wake_level, u32 wake_any)
108 {
109         u32 temp;
110         u32 status;
111         u32 lvl;
112
113         wake_level &= wake_enb;
114         wake_any &= wake_enb;
115
116         wake_level |= (tegra_lp0_wake_level & tegra_lp0_wake_enb);
117         wake_any |= (tegra_lp0_wake_level_any & tegra_lp0_wake_enb);
118
119         wake_enb |= tegra_lp0_wake_enb;
120
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);
129
130         /* flip the wakeup trigger for any-edge triggered pads
131          * which are currently asserting as wakeups */
132         lvl ^= status;
133         lvl &= wake_any;
134
135         wake_level |= lvl;
136
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);
141
142         writel(wake_enb, pmc + PMC_WAKE_MASK);
143 }
144
145 static void tegra_irq_handle_wake(void)
146 {
147         int wake;
148         int irq;
149         struct irq_desc *desc;
150
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);
154                 if (!irq) {
155                         pr_info("Resume caused by WAKE%d\n", wake);
156                         continue;
157                 }
158
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);
162                         continue;
163                 }
164
165                 pr_info("Resume caused by WAKE%d, %s\n", wake,
166                         desc->action->name);
167
168                 generic_handle_irq(irq);
169         }
170 }
171
172 static void tegra_mask(unsigned int irq)
173 {
174         gic_mask_irq(irq);
175         tegra_legacy_mask_irq(irq);
176 }
177
178 static void tegra_unmask(unsigned int irq)
179 {
180         gic_unmask_irq(irq);
181         tegra_legacy_unmask_irq(irq);
182 }
183
184 static int tegra_set_wake(unsigned int irq, unsigned int enable)
185 {
186         int ret;
187         ret = tegra_set_lp1_wake(irq, enable);
188         if (ret)
189                 return ret;
190
191         if (tegra_get_suspend_mode() == TEGRA_SUSPEND_LP0)
192                 return tegra_set_lp0_wake(irq, enable);
193
194         return 0;
195 }
196
197 static int tegra_set_type(unsigned int irq, unsigned int flow_type)
198 {
199         if (tegra_get_suspend_mode() == TEGRA_SUSPEND_LP0)
200                 return tegra_set_lp0_wake_type(irq, flow_type);
201
202         return 0;
203 }
204
205 static void tegra_ack(unsigned int irq)
206 {
207         tegra_legacy_force_irq_clr(irq);
208         gic_ack_irq(irq);
209 }
210
211 static int tegra_retrigger(unsigned int irq)
212 {
213         tegra_legacy_force_irq_set(irq);
214         return 1;
215 }
216
217 static struct irq_chip tegra_irq = {
218         .name           = "PPI",
219         .ack            = tegra_ack,
220         .mask           = tegra_mask,
221         .unmask         = tegra_unmask,
222         .set_wake       = tegra_set_wake,
223         .set_type       = tegra_set_type,
224 #ifdef CONFIG_SMP
225         .set_affinity   = gic_set_cpu,
226 #endif
227         .retrigger      = tegra_retrigger,
228 };
229
230 void __init tegra_init_irq(void)
231 {
232         unsigned int i;
233         int irq;
234
235         tegra_init_legacy_irq();
236
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));
239
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);
245         }
246 }
247
248 void tegra_irq_suspend(void)
249 {
250         tegra_legacy_irq_suspend();
251 }
252
253 void tegra_irq_resume(void)
254 {
255         tegra_legacy_irq_resume();
256         tegra_irq_handle_wake();
257 }