Merge branch linux-tegra-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/debugfs.h>
23 #include <linux/init.h>
24 #include <linux/interrupt.h>
25 #include <linux/irq.h>
26 #include <linux/io.h>
27 #include <linux/seq_file.h>
28
29 #include <asm/hardware/gic.h>
30
31 #include <mach/iomap.h>
32 #include <mach/legacy_irq.h>
33 #include <mach/suspend.h>
34
35 #include "board.h"
36
37 #define PMC_CTRL                0x0
38 #define PMC_CTRL_LATCH_WAKEUPS  (1 << 5)
39 #define PMC_WAKE_MASK           0xc
40 #define PMC_WAKE_LEVEL          0x10
41 #define PMC_WAKE_STATUS         0x14
42 #define PMC_SW_WAKE_STATUS      0x18
43 #define PMC_DPD_SAMPLE          0x20
44
45 static void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE);
46
47 static u32 tegra_lp0_wake_enb;
48 static u32 tegra_lp0_wake_level;
49 static u32 tegra_lp0_wake_level_any;
50
51 static unsigned int tegra_wake_irq_count[32];
52
53 /* ensures that sufficient time is passed for a register write to
54  * serialize into the 32KHz domain */
55 static void pmc_32kwritel(u32 val, unsigned long offs)
56 {
57         writel(val, pmc + offs);
58         udelay(130);
59 }
60
61 int tegra_set_lp0_wake(int irq, int enable)
62 {
63         int wake = tegra_irq_to_wake(irq);
64
65         if (wake < 0)
66                 return -EINVAL;
67
68         if (enable)
69                 tegra_lp0_wake_enb |= 1 << wake;
70         else
71                 tegra_lp0_wake_enb &= ~(1 << wake);
72
73         return 0;
74 }
75
76 int tegra_set_lp0_wake_type(int irq, int flow_type)
77 {
78         int wake = tegra_irq_to_wake(irq);
79
80         if (wake < 0)
81                 return 0;
82
83         switch (flow_type) {
84         case IRQF_TRIGGER_FALLING:
85         case IRQF_TRIGGER_LOW:
86                 tegra_lp0_wake_level &= ~(1 << wake);
87                 tegra_lp0_wake_level_any &= ~(1 << wake);
88                 break;
89         case IRQF_TRIGGER_HIGH:
90         case IRQF_TRIGGER_RISING:
91                 tegra_lp0_wake_level |= 1 << wake;
92                 tegra_lp0_wake_level_any &= ~(1 << wake);
93                 break;
94
95         case IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING:
96                 tegra_lp0_wake_level_any |= 1 << wake;
97                 break;
98         default:
99                 return -EINVAL;
100         }
101
102         return 0;
103 }
104
105
106 int tegra_set_lp1_wake(int irq, int enable)
107 {
108         return tegra_legacy_irq_set_wake(irq, enable);
109 }
110
111 void tegra_set_lp0_wake_pads(u32 wake_enb, u32 wake_level, u32 wake_any)
112 {
113         u32 temp;
114         u32 status;
115         u32 lvl;
116
117         wake_level &= wake_enb;
118         wake_any &= wake_enb;
119
120         wake_level |= (tegra_lp0_wake_level & tegra_lp0_wake_enb);
121         wake_any |= (tegra_lp0_wake_level_any & tegra_lp0_wake_enb);
122
123         wake_enb |= tegra_lp0_wake_enb;
124
125         pmc_32kwritel(0, PMC_SW_WAKE_STATUS);
126         temp = readl(pmc + PMC_CTRL);
127         temp |= PMC_CTRL_LATCH_WAKEUPS;
128         pmc_32kwritel(temp, PMC_CTRL);
129         temp &= ~PMC_CTRL_LATCH_WAKEUPS;
130         pmc_32kwritel(temp, PMC_CTRL);
131         status = readl(pmc + PMC_SW_WAKE_STATUS);
132         lvl = readl(pmc + PMC_WAKE_LEVEL);
133
134         /* flip the wakeup trigger for any-edge triggered pads
135          * which are currently asserting as wakeups */
136         lvl ^= status;
137         lvl &= wake_any;
138
139         wake_level |= lvl;
140
141         writel(wake_level, pmc + PMC_WAKE_LEVEL);
142         /* Enable DPD sample to trigger sampling pads data and direction
143          * in which pad will be driven during lp0 mode*/
144         writel(0x1, pmc + PMC_DPD_SAMPLE);
145
146         writel(wake_enb, pmc + PMC_WAKE_MASK);
147 }
148
149 static void tegra_irq_handle_wake(void)
150 {
151         int wake;
152         int irq;
153         struct irq_desc *desc;
154
155         unsigned long wake_status = readl(pmc + PMC_WAKE_STATUS);
156         for_each_set_bit(wake, &wake_status, sizeof(wake_status) * 8) {
157                 irq = tegra_wake_to_irq(wake);
158                 if (!irq) {
159                         pr_info("Resume caused by WAKE%d\n", wake);
160                         continue;
161                 }
162
163                 desc = irq_to_desc(irq);
164                 if (!desc || !desc->action || !desc->action->name) {
165                         pr_info("Resume caused by WAKE%d, irq %d\n", wake, irq);
166                         continue;
167                 }
168
169                 pr_info("Resume caused by WAKE%d, %s\n", wake,
170                         desc->action->name);
171
172                 tegra_wake_irq_count[wake]++;
173
174                 generic_handle_irq(irq);
175         }
176 }
177
178 static void tegra_mask(unsigned int irq)
179 {
180         gic_mask_irq(irq);
181         tegra_legacy_mask_irq(irq);
182 }
183
184 static void tegra_unmask(unsigned int irq)
185 {
186         gic_unmask_irq(irq);
187         tegra_legacy_unmask_irq(irq);
188 }
189
190 static int tegra_set_wake(unsigned int irq, unsigned int enable)
191 {
192         int ret;
193         ret = tegra_set_lp1_wake(irq, enable);
194         if (ret)
195                 return ret;
196
197         if (tegra_get_suspend_mode() == TEGRA_SUSPEND_LP0)
198                 return tegra_set_lp0_wake(irq, enable);
199
200         return 0;
201 }
202
203 static int tegra_set_type(unsigned int irq, unsigned int flow_type)
204 {
205         if (tegra_get_suspend_mode() == TEGRA_SUSPEND_LP0)
206                 return tegra_set_lp0_wake_type(irq, flow_type);
207
208         return 0;
209 }
210
211 static void tegra_ack(unsigned int irq)
212 {
213         tegra_legacy_force_irq_clr(irq);
214         gic_ack_irq(irq);
215 }
216
217 static int tegra_retrigger(unsigned int irq)
218 {
219         tegra_legacy_force_irq_set(irq);
220         return 1;
221 }
222
223 static struct irq_chip tegra_irq = {
224         .name           = "PPI",
225         .ack            = tegra_ack,
226         .mask           = tegra_mask,
227         .unmask         = tegra_unmask,
228         .set_wake       = tegra_set_wake,
229         .set_type       = tegra_set_type,
230 #ifdef CONFIG_SMP
231         .set_affinity   = gic_set_cpu,
232 #endif
233         .retrigger      = tegra_retrigger,
234 };
235
236 void __init tegra_init_irq(void)
237 {
238         unsigned int i;
239         int irq;
240
241         tegra_init_legacy_irq();
242
243         gic_dist_init(0, IO_ADDRESS(TEGRA_ARM_INT_DIST_BASE), 29);
244         gic_cpu_init(0, IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x100));
245
246         for (i = 0; i < INT_MAIN_NR; i++) {
247                 irq = INT_PRI_BASE + i;
248                 set_irq_chip(irq, &tegra_irq);
249                 set_irq_handler(irq, handle_level_irq);
250                 set_irq_flags(irq, IRQF_VALID);
251         }
252 }
253
254 void tegra_irq_suspend(void)
255 {
256         tegra_legacy_irq_suspend();
257 }
258
259 void tegra_irq_resume(void)
260 {
261         tegra_legacy_irq_resume();
262         tegra_irq_handle_wake();
263 }
264
265 #ifdef CONFIG_DEBUG_FS
266 static int tegra_wake_irq_debug_show(struct seq_file *s, void *data)
267 {
268         int wake;
269         int irq;
270         struct irq_desc *desc;
271         const char *irq_name;
272
273         seq_printf(s, "wake  irq  count  name\n");
274         seq_printf(s, "----------------------\n");
275         for (wake = 0; wake < 32; wake++) {
276                 irq = tegra_wake_to_irq(wake);
277                 if (irq < 0)
278                         continue;
279
280                 desc = irq_to_desc(irq);
281                 if (tegra_wake_irq_count[wake] == 0 && desc->action == NULL)
282                         continue;
283
284                 if (!(desc->status & IRQ_WAKEUP))
285                         continue;
286
287                 irq_name = (desc->action && desc->action->name) ?
288                         desc->action->name : "???";
289
290                 seq_printf(s, "%4d  %3d  %5d  %s\n",
291                         wake, irq, tegra_wake_irq_count[wake], irq_name);
292         }
293         return 0;
294 }
295
296 static int tegra_wake_irq_debug_open(struct inode *inode, struct file *file)
297 {
298         return single_open(file, tegra_wake_irq_debug_show, NULL);
299 }
300
301 static const struct file_operations tegra_wake_irq_debug_fops = {
302         .open           = tegra_wake_irq_debug_open,
303         .read           = seq_read,
304         .llseek         = seq_lseek,
305         .release        = single_release,
306 };
307
308 static int __init tegra_irq_debug_init(void)
309 {
310         struct dentry *d;
311
312         d = debugfs_create_file("wake_irq", 0755, NULL, NULL,
313                 &tegra_wake_irq_debug_fops);
314         if (!d) {
315                 pr_info("Failed to create suspend_mode debug file\n");
316                 return -ENOMEM;
317         }
318
319         return 0;
320 }
321
322 late_initcall(tegra_irq_debug_init);
323 #endif