]> git.openfabrics.org - ~shefty/rdma-dev.git/blob - arch/arm/mach-exynos/common.c
5de4214fa78ff9fe26f3acb9cdf4c263d9cbc9a3
[~shefty/rdma-dev.git] / arch / arm / mach-exynos / common.c
1 /*
2  * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
3  *              http://www.samsung.com
4  *
5  * Common Codes for EXYNOS
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License version 2 as
9  * published by the Free Software Foundation.
10  */
11
12 #include <linux/kernel.h>
13 #include <linux/interrupt.h>
14 #include <linux/irq.h>
15 #include <linux/io.h>
16 #include <linux/sysdev.h>
17 #include <linux/gpio.h>
18 #include <linux/sched.h>
19 #include <linux/serial_core.h>
20
21 #include <asm/proc-fns.h>
22 #include <asm/exception.h>
23 #include <asm/hardware/cache-l2x0.h>
24 #include <asm/hardware/gic.h>
25 #include <asm/mach/map.h>
26 #include <asm/mach/irq.h>
27
28 #include <mach/regs-irq.h>
29 #include <mach/regs-pmu.h>
30 #include <mach/regs-gpio.h>
31
32 #include <plat/cpu.h>
33 #include <plat/clock.h>
34 #include <plat/devs.h>
35 #include <plat/pm.h>
36 #include <plat/sdhci.h>
37 #include <plat/gpio-cfg.h>
38 #include <plat/adc-core.h>
39 #include <plat/fb-core.h>
40 #include <plat/fimc-core.h>
41 #include <plat/iic-core.h>
42 #include <plat/tv-core.h>
43 #include <plat/regs-serial.h>
44
45 #include "common.h"
46
47 static const char name_exynos4210[] = "EXYNOS4210";
48 static const char name_exynos4212[] = "EXYNOS4212";
49 static const char name_exynos4412[] = "EXYNOS4412";
50
51 static struct cpu_table cpu_ids[] __initdata = {
52         {
53                 .idcode         = EXYNOS4210_CPU_ID,
54                 .idmask         = EXYNOS4_CPU_MASK,
55                 .map_io         = exynos4_map_io,
56                 .init_clocks    = exynos4_init_clocks,
57                 .init_uarts     = exynos4_init_uarts,
58                 .init           = exynos_init,
59                 .name           = name_exynos4210,
60         }, {
61                 .idcode         = EXYNOS4212_CPU_ID,
62                 .idmask         = EXYNOS4_CPU_MASK,
63                 .map_io         = exynos4_map_io,
64                 .init_clocks    = exynos4_init_clocks,
65                 .init_uarts     = exynos4_init_uarts,
66                 .init           = exynos_init,
67                 .name           = name_exynos4212,
68         }, {
69                 .idcode         = EXYNOS4412_CPU_ID,
70                 .idmask         = EXYNOS4_CPU_MASK,
71                 .map_io         = exynos4_map_io,
72                 .init_clocks    = exynos4_init_clocks,
73                 .init_uarts     = exynos4_init_uarts,
74                 .init           = exynos_init,
75                 .name           = name_exynos4412,
76         },
77 };
78
79 /* Initial IO mappings */
80
81 static struct map_desc exynos_iodesc[] __initdata = {
82         {
83                 .virtual        = (unsigned long)S5P_VA_CHIPID,
84                 .pfn            = __phys_to_pfn(EXYNOS4_PA_CHIPID),
85                 .length         = SZ_4K,
86                 .type           = MT_DEVICE,
87         }, {
88                 .virtual        = (unsigned long)S3C_VA_SYS,
89                 .pfn            = __phys_to_pfn(EXYNOS4_PA_SYSCON),
90                 .length         = SZ_64K,
91                 .type           = MT_DEVICE,
92         }, {
93                 .virtual        = (unsigned long)S3C_VA_TIMER,
94                 .pfn            = __phys_to_pfn(EXYNOS4_PA_TIMER),
95                 .length         = SZ_16K,
96                 .type           = MT_DEVICE,
97         }, {
98                 .virtual        = (unsigned long)S3C_VA_WATCHDOG,
99                 .pfn            = __phys_to_pfn(EXYNOS4_PA_WATCHDOG),
100                 .length         = SZ_4K,
101                 .type           = MT_DEVICE,
102         }, {
103                 .virtual        = (unsigned long)S5P_VA_SROMC,
104                 .pfn            = __phys_to_pfn(EXYNOS4_PA_SROMC),
105                 .length         = SZ_4K,
106                 .type           = MT_DEVICE,
107         }, {
108                 .virtual        = (unsigned long)S5P_VA_SYSTIMER,
109                 .pfn            = __phys_to_pfn(EXYNOS4_PA_SYSTIMER),
110                 .length         = SZ_4K,
111                 .type           = MT_DEVICE,
112         }, {
113                 .virtual        = (unsigned long)S5P_VA_PMU,
114                 .pfn            = __phys_to_pfn(EXYNOS4_PA_PMU),
115                 .length         = SZ_64K,
116                 .type           = MT_DEVICE,
117         }, {
118                 .virtual        = (unsigned long)S5P_VA_COMBINER_BASE,
119                 .pfn            = __phys_to_pfn(EXYNOS4_PA_COMBINER),
120                 .length         = SZ_4K,
121                 .type           = MT_DEVICE,
122         }, {
123                 .virtual        = (unsigned long)S5P_VA_GIC_CPU,
124                 .pfn            = __phys_to_pfn(EXYNOS4_PA_GIC_CPU),
125                 .length         = SZ_64K,
126                 .type           = MT_DEVICE,
127         }, {
128                 .virtual        = (unsigned long)S5P_VA_GIC_DIST,
129                 .pfn            = __phys_to_pfn(EXYNOS4_PA_GIC_DIST),
130                 .length         = SZ_64K,
131                 .type           = MT_DEVICE,
132         }, {
133                 .virtual        = (unsigned long)S3C_VA_UART,
134                 .pfn            = __phys_to_pfn(EXYNOS4_PA_UART),
135                 .length         = SZ_512K,
136                 .type           = MT_DEVICE,
137         },
138 };
139
140 static struct map_desc exynos4_iodesc[] __initdata = {
141         {
142                 .virtual        = (unsigned long)S5P_VA_CMU,
143                 .pfn            = __phys_to_pfn(EXYNOS4_PA_CMU),
144                 .length         = SZ_128K,
145                 .type           = MT_DEVICE,
146         }, {
147                 .virtual        = (unsigned long)S5P_VA_COREPERI_BASE,
148                 .pfn            = __phys_to_pfn(EXYNOS4_PA_COREPERI),
149                 .length         = SZ_8K,
150                 .type           = MT_DEVICE,
151         }, {
152                 .virtual        = (unsigned long)S5P_VA_L2CC,
153                 .pfn            = __phys_to_pfn(EXYNOS4_PA_L2CC),
154                 .length         = SZ_4K,
155                 .type           = MT_DEVICE,
156         }, {
157                 .virtual        = (unsigned long)S5P_VA_GPIO1,
158                 .pfn            = __phys_to_pfn(EXYNOS4_PA_GPIO1),
159                 .length         = SZ_4K,
160                 .type           = MT_DEVICE,
161         }, {
162                 .virtual        = (unsigned long)S5P_VA_GPIO2,
163                 .pfn            = __phys_to_pfn(EXYNOS4_PA_GPIO2),
164                 .length         = SZ_4K,
165                 .type           = MT_DEVICE,
166         }, {
167                 .virtual        = (unsigned long)S5P_VA_GPIO3,
168                 .pfn            = __phys_to_pfn(EXYNOS4_PA_GPIO3),
169                 .length         = SZ_256,
170                 .type           = MT_DEVICE,
171         }, {
172                 .virtual        = (unsigned long)S5P_VA_DMC0,
173                 .pfn            = __phys_to_pfn(EXYNOS4_PA_DMC0),
174                 .length         = SZ_4K,
175                 .type           = MT_DEVICE,
176         }, {
177                 .virtual        = (unsigned long)S5P_VA_SROMC,
178                 .pfn            = __phys_to_pfn(EXYNOS4_PA_SROMC),
179                 .length         = SZ_4K,
180                 .type           = MT_DEVICE,
181         }, {
182                 .virtual        = (unsigned long)S3C_VA_USB_HSPHY,
183                 .pfn            = __phys_to_pfn(EXYNOS4_PA_HSPHY),
184                 .length         = SZ_4K,
185                 .type           = MT_DEVICE,
186         },
187 };
188
189 static struct map_desc exynos4_iodesc0[] __initdata = {
190         {
191                 .virtual        = (unsigned long)S5P_VA_SYSRAM,
192                 .pfn            = __phys_to_pfn(EXYNOS4_PA_SYSRAM0),
193                 .length         = SZ_4K,
194                 .type           = MT_DEVICE,
195         },
196 };
197
198 static struct map_desc exynos4_iodesc1[] __initdata = {
199         {
200                 .virtual        = (unsigned long)S5P_VA_SYSRAM,
201                 .pfn            = __phys_to_pfn(EXYNOS4_PA_SYSRAM1),
202                 .length         = SZ_4K,
203                 .type           = MT_DEVICE,
204         },
205 };
206
207 static void exynos_idle(void)
208 {
209         if (!need_resched())
210                 cpu_do_idle();
211
212         local_irq_enable();
213 }
214
215 void exynos4_restart(char mode, const char *cmd)
216 {
217         __raw_writel(0x1, S5P_SWRESET);
218 }
219
220 /*
221  * exynos_map_io
222  *
223  * register the standard cpu IO areas
224  */
225
226 void __init exynos_init_io(struct map_desc *mach_desc, int size)
227 {
228         /* initialize the io descriptors we need for initialization */
229         iotable_init(exynos_iodesc, ARRAY_SIZE(exynos_iodesc));
230         if (mach_desc)
231                 iotable_init(mach_desc, size);
232
233         /* detect cpu id and rev. */
234         s5p_init_cpu(S5P_VA_CHIPID);
235
236         s3c_init_cpu(samsung_cpu_id, cpu_ids, ARRAY_SIZE(cpu_ids));
237 }
238
239 void __init exynos4_map_io(void)
240 {
241         iotable_init(exynos4_iodesc, ARRAY_SIZE(exynos4_iodesc));
242
243         if (soc_is_exynos4210() && samsung_rev() == EXYNOS4210_REV_0)
244                 iotable_init(exynos4_iodesc0, ARRAY_SIZE(exynos4_iodesc0));
245         else
246                 iotable_init(exynos4_iodesc1, ARRAY_SIZE(exynos4_iodesc1));
247
248         /* initialize device information early */
249         exynos4_default_sdhci0();
250         exynos4_default_sdhci1();
251         exynos4_default_sdhci2();
252         exynos4_default_sdhci3();
253
254         s3c_adc_setname("samsung-adc-v3");
255
256         s3c_fimc_setname(0, "exynos4-fimc");
257         s3c_fimc_setname(1, "exynos4-fimc");
258         s3c_fimc_setname(2, "exynos4-fimc");
259         s3c_fimc_setname(3, "exynos4-fimc");
260
261         /* The I2C bus controllers are directly compatible with s3c2440 */
262         s3c_i2c0_setname("s3c2440-i2c");
263         s3c_i2c1_setname("s3c2440-i2c");
264         s3c_i2c2_setname("s3c2440-i2c");
265
266         s5p_fb_setname(0, "exynos4-fb");
267         s5p_hdmi_setname("exynos4-hdmi");
268 }
269
270 void __init exynos4_init_clocks(int xtal)
271 {
272         printk(KERN_DEBUG "%s: initializing clocks\n", __func__);
273
274         s3c24xx_register_baseclocks(xtal);
275         s5p_register_clocks(xtal);
276
277         if (soc_is_exynos4210())
278                 exynos4210_register_clocks();
279         else if (soc_is_exynos4212() || soc_is_exynos4412())
280                 exynos4212_register_clocks();
281
282         exynos4_register_clocks();
283         exynos4_setup_clocks();
284 }
285
286 #define COMBINER_ENABLE_SET     0x0
287 #define COMBINER_ENABLE_CLEAR   0x4
288 #define COMBINER_INT_STATUS     0xC
289
290 static DEFINE_SPINLOCK(irq_controller_lock);
291
292 struct combiner_chip_data {
293         unsigned int irq_offset;
294         unsigned int irq_mask;
295         void __iomem *base;
296 };
297
298 static struct combiner_chip_data combiner_data[MAX_COMBINER_NR];
299
300 static inline void __iomem *combiner_base(struct irq_data *data)
301 {
302         struct combiner_chip_data *combiner_data =
303                 irq_data_get_irq_chip_data(data);
304
305         return combiner_data->base;
306 }
307
308 static void combiner_mask_irq(struct irq_data *data)
309 {
310         u32 mask = 1 << (data->irq % 32);
311
312         __raw_writel(mask, combiner_base(data) + COMBINER_ENABLE_CLEAR);
313 }
314
315 static void combiner_unmask_irq(struct irq_data *data)
316 {
317         u32 mask = 1 << (data->irq % 32);
318
319         __raw_writel(mask, combiner_base(data) + COMBINER_ENABLE_SET);
320 }
321
322 static void combiner_handle_cascade_irq(unsigned int irq, struct irq_desc *desc)
323 {
324         struct combiner_chip_data *chip_data = irq_get_handler_data(irq);
325         struct irq_chip *chip = irq_get_chip(irq);
326         unsigned int cascade_irq, combiner_irq;
327         unsigned long status;
328
329         chained_irq_enter(chip, desc);
330
331         spin_lock(&irq_controller_lock);
332         status = __raw_readl(chip_data->base + COMBINER_INT_STATUS);
333         spin_unlock(&irq_controller_lock);
334         status &= chip_data->irq_mask;
335
336         if (status == 0)
337                 goto out;
338
339         combiner_irq = __ffs(status);
340
341         cascade_irq = combiner_irq + (chip_data->irq_offset & ~31);
342         if (unlikely(cascade_irq >= NR_IRQS))
343                 do_bad_IRQ(cascade_irq, desc);
344         else
345                 generic_handle_irq(cascade_irq);
346
347  out:
348         chained_irq_exit(chip, desc);
349 }
350
351 static struct irq_chip combiner_chip = {
352         .name           = "COMBINER",
353         .irq_mask       = combiner_mask_irq,
354         .irq_unmask     = combiner_unmask_irq,
355 };
356
357 static void __init combiner_cascade_irq(unsigned int combiner_nr, unsigned int irq)
358 {
359         if (combiner_nr >= MAX_COMBINER_NR)
360                 BUG();
361         if (irq_set_handler_data(irq, &combiner_data[combiner_nr]) != 0)
362                 BUG();
363         irq_set_chained_handler(irq, combiner_handle_cascade_irq);
364 }
365
366 static void __init combiner_init(unsigned int combiner_nr, void __iomem *base,
367                           unsigned int irq_start)
368 {
369         unsigned int i;
370
371         if (combiner_nr >= MAX_COMBINER_NR)
372                 BUG();
373
374         combiner_data[combiner_nr].base = base;
375         combiner_data[combiner_nr].irq_offset = irq_start;
376         combiner_data[combiner_nr].irq_mask = 0xff << ((combiner_nr % 4) << 3);
377
378         /* Disable all interrupts */
379
380         __raw_writel(combiner_data[combiner_nr].irq_mask,
381                      base + COMBINER_ENABLE_CLEAR);
382
383         /* Setup the Linux IRQ subsystem */
384
385         for (i = irq_start; i < combiner_data[combiner_nr].irq_offset
386                                 + MAX_IRQ_IN_COMBINER; i++) {
387                 irq_set_chip_and_handler(i, &combiner_chip, handle_level_irq);
388                 irq_set_chip_data(i, &combiner_data[combiner_nr]);
389                 set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
390         }
391 }
392
393 void __init exynos4_init_irq(void)
394 {
395         int irq;
396         unsigned int gic_bank_offset;
397
398         gic_bank_offset = soc_is_exynos4412() ? 0x4000 : 0x8000;
399
400         gic_init_bases(0, IRQ_PPI(0), S5P_VA_GIC_DIST, S5P_VA_GIC_CPU, gic_bank_offset);
401
402         for (irq = 0; irq < MAX_COMBINER_NR; irq++) {
403
404                 combiner_init(irq, (void __iomem *)S5P_VA_COMBINER(irq),
405                                 COMBINER_IRQ(irq, 0));
406                 combiner_cascade_irq(irq, IRQ_SPI(irq));
407         }
408
409         /*
410          * The parameters of s5p_init_irq() are for VIC init.
411          * Theses parameters should be NULL and 0 because EXYNOS4
412          * uses GIC instead of VIC.
413          */
414         s5p_init_irq(NULL, 0);
415 }
416
417 struct sysdev_class exynos4_sysclass = {
418         .name   = "exynos4-core",
419 };
420
421 static struct sys_device exynos4_sysdev = {
422         .cls    = &exynos4_sysclass,
423 };
424
425 static int __init exynos4_core_init(void)
426 {
427         return sysdev_class_register(&exynos4_sysclass);
428 }
429 core_initcall(exynos4_core_init);
430
431 #ifdef CONFIG_CACHE_L2X0
432 static int __init exynos4_l2x0_cache_init(void)
433 {
434         /* TAG, Data Latency Control: 2cycle */
435         __raw_writel(0x110, S5P_VA_L2CC + L2X0_TAG_LATENCY_CTRL);
436
437         if (soc_is_exynos4210())
438                 __raw_writel(0x110, S5P_VA_L2CC + L2X0_DATA_LATENCY_CTRL);
439         else if (soc_is_exynos4212() || soc_is_exynos4412())
440                 __raw_writel(0x120, S5P_VA_L2CC + L2X0_DATA_LATENCY_CTRL);
441
442         /* L2X0 Prefetch Control */
443         __raw_writel(0x30000007, S5P_VA_L2CC + L2X0_PREFETCH_CTRL);
444
445         /* L2X0 Power Control */
446         __raw_writel(L2X0_DYNAMIC_CLK_GATING_EN | L2X0_STNDBY_MODE_EN,
447                      S5P_VA_L2CC + L2X0_POWER_CTRL);
448
449         l2x0_init(S5P_VA_L2CC, 0x7C470001, 0xC200ffff);
450
451         return 0;
452 }
453
454 early_initcall(exynos4_l2x0_cache_init);
455 #endif
456
457 int __init exynos_init(void)
458 {
459         printk(KERN_INFO "EXYNOS: Initializing architecture\n");
460
461         /* set idle function */
462         pm_idle = exynos_idle;
463
464         return sysdev_register(&exynos4_sysdev);
465 }
466
467 static struct s3c24xx_uart_clksrc exynos4_serial_clocks[] = {
468         [0] = {
469                 .name           = "uclk1",
470                 .divisor        = 1,
471                 .min_baud       = 0,
472                 .max_baud       = 0,
473         },
474 };
475
476 /* uart registration process */
477
478 void __init exynos4_init_uarts(struct s3c2410_uartcfg *cfg, int no)
479 {
480         struct s3c2410_uartcfg *tcfg = cfg;
481         u32 ucnt;
482
483         for (ucnt = 0; ucnt < no; ucnt++, tcfg++) {
484                 if (!tcfg->clocks) {
485                         tcfg->has_fracval = 1;
486                         tcfg->clocks = exynos4_serial_clocks;
487                         tcfg->clocks_size = ARRAY_SIZE(exynos4_serial_clocks);
488                 }
489                 tcfg->flags |= NO_NEED_CHECK_CLKSRC;
490         }
491
492         s3c24xx_init_uartdevs("s5pv210-uart", s5p_uart_resources, cfg, no);
493 }
494
495 static DEFINE_SPINLOCK(eint_lock);
496
497 static unsigned int eint0_15_data[16];
498
499 static unsigned int exynos4_get_irq_nr(unsigned int number)
500 {
501         u32 ret = 0;
502
503         switch (number) {
504         case 0 ... 3:
505                 ret = (number + IRQ_EINT0);
506                 break;
507         case 4 ... 7:
508                 ret = (number + (IRQ_EINT4 - 4));
509                 break;
510         case 8 ... 15:
511                 ret = (number + (IRQ_EINT8 - 8));
512                 break;
513         default:
514                 printk(KERN_ERR "number available : %d\n", number);
515         }
516
517         return ret;
518 }
519
520 static inline void exynos4_irq_eint_mask(struct irq_data *data)
521 {
522         u32 mask;
523
524         spin_lock(&eint_lock);
525         mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(data->irq)));
526         mask |= eint_irq_to_bit(data->irq);
527         __raw_writel(mask, S5P_EINT_MASK(EINT_REG_NR(data->irq)));
528         spin_unlock(&eint_lock);
529 }
530
531 static void exynos4_irq_eint_unmask(struct irq_data *data)
532 {
533         u32 mask;
534
535         spin_lock(&eint_lock);
536         mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(data->irq)));
537         mask &= ~(eint_irq_to_bit(data->irq));
538         __raw_writel(mask, S5P_EINT_MASK(EINT_REG_NR(data->irq)));
539         spin_unlock(&eint_lock);
540 }
541
542 static inline void exynos4_irq_eint_ack(struct irq_data *data)
543 {
544         __raw_writel(eint_irq_to_bit(data->irq),
545                      S5P_EINT_PEND(EINT_REG_NR(data->irq)));
546 }
547
548 static void exynos4_irq_eint_maskack(struct irq_data *data)
549 {
550         exynos4_irq_eint_mask(data);
551         exynos4_irq_eint_ack(data);
552 }
553
554 static int exynos4_irq_eint_set_type(struct irq_data *data, unsigned int type)
555 {
556         int offs = EINT_OFFSET(data->irq);
557         int shift;
558         u32 ctrl, mask;
559         u32 newvalue = 0;
560
561         switch (type) {
562         case IRQ_TYPE_EDGE_RISING:
563                 newvalue = S5P_IRQ_TYPE_EDGE_RISING;
564                 break;
565
566         case IRQ_TYPE_EDGE_FALLING:
567                 newvalue = S5P_IRQ_TYPE_EDGE_FALLING;
568                 break;
569
570         case IRQ_TYPE_EDGE_BOTH:
571                 newvalue = S5P_IRQ_TYPE_EDGE_BOTH;
572                 break;
573
574         case IRQ_TYPE_LEVEL_LOW:
575                 newvalue = S5P_IRQ_TYPE_LEVEL_LOW;
576                 break;
577
578         case IRQ_TYPE_LEVEL_HIGH:
579                 newvalue = S5P_IRQ_TYPE_LEVEL_HIGH;
580                 break;
581
582         default:
583                 printk(KERN_ERR "No such irq type %d", type);
584                 return -EINVAL;
585         }
586
587         shift = (offs & 0x7) * 4;
588         mask = 0x7 << shift;
589
590         spin_lock(&eint_lock);
591         ctrl = __raw_readl(S5P_EINT_CON(EINT_REG_NR(data->irq)));
592         ctrl &= ~mask;
593         ctrl |= newvalue << shift;
594         __raw_writel(ctrl, S5P_EINT_CON(EINT_REG_NR(data->irq)));
595         spin_unlock(&eint_lock);
596
597         switch (offs) {
598         case 0 ... 7:
599                 s3c_gpio_cfgpin(EINT_GPIO_0(offs & 0x7), EINT_MODE);
600                 break;
601         case 8 ... 15:
602                 s3c_gpio_cfgpin(EINT_GPIO_1(offs & 0x7), EINT_MODE);
603                 break;
604         case 16 ... 23:
605                 s3c_gpio_cfgpin(EINT_GPIO_2(offs & 0x7), EINT_MODE);
606                 break;
607         case 24 ... 31:
608                 s3c_gpio_cfgpin(EINT_GPIO_3(offs & 0x7), EINT_MODE);
609                 break;
610         default:
611                 printk(KERN_ERR "No such irq number %d", offs);
612         }
613
614         return 0;
615 }
616
617 static struct irq_chip exynos4_irq_eint = {
618         .name           = "exynos4-eint",
619         .irq_mask       = exynos4_irq_eint_mask,
620         .irq_unmask     = exynos4_irq_eint_unmask,
621         .irq_mask_ack   = exynos4_irq_eint_maskack,
622         .irq_ack        = exynos4_irq_eint_ack,
623         .irq_set_type   = exynos4_irq_eint_set_type,
624 #ifdef CONFIG_PM
625         .irq_set_wake   = s3c_irqext_wake,
626 #endif
627 };
628
629 /*
630  * exynos4_irq_demux_eint
631  *
632  * This function demuxes the IRQ from from EINTs 16 to 31.
633  * It is designed to be inlined into the specific handler
634  * s5p_irq_demux_eintX_Y.
635  *
636  * Each EINT pend/mask registers handle eight of them.
637  */
638 static inline void exynos4_irq_demux_eint(unsigned int start)
639 {
640         unsigned int irq;
641
642         u32 status = __raw_readl(S5P_EINT_PEND(EINT_REG_NR(start)));
643         u32 mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(start)));
644
645         status &= ~mask;
646         status &= 0xff;
647
648         while (status) {
649                 irq = fls(status) - 1;
650                 generic_handle_irq(irq + start);
651                 status &= ~(1 << irq);
652         }
653 }
654
655 static void exynos4_irq_demux_eint16_31(unsigned int irq, struct irq_desc *desc)
656 {
657         struct irq_chip *chip = irq_get_chip(irq);
658         chained_irq_enter(chip, desc);
659         exynos4_irq_demux_eint(IRQ_EINT(16));
660         exynos4_irq_demux_eint(IRQ_EINT(24));
661         chained_irq_exit(chip, desc);
662 }
663
664 static void exynos4_irq_eint0_15(unsigned int irq, struct irq_desc *desc)
665 {
666         u32 *irq_data = irq_get_handler_data(irq);
667         struct irq_chip *chip = irq_get_chip(irq);
668
669         chained_irq_enter(chip, desc);
670         chip->irq_mask(&desc->irq_data);
671
672         if (chip->irq_ack)
673                 chip->irq_ack(&desc->irq_data);
674
675         generic_handle_irq(*irq_data);
676
677         chip->irq_unmask(&desc->irq_data);
678         chained_irq_exit(chip, desc);
679 }
680
681 int __init exynos4_init_irq_eint(void)
682 {
683         int irq;
684
685         for (irq = 0 ; irq <= 31 ; irq++) {
686                 irq_set_chip_and_handler(IRQ_EINT(irq), &exynos4_irq_eint,
687                                          handle_level_irq);
688                 set_irq_flags(IRQ_EINT(irq), IRQF_VALID);
689         }
690
691         irq_set_chained_handler(IRQ_EINT16_31, exynos4_irq_demux_eint16_31);
692
693         for (irq = 0 ; irq <= 15 ; irq++) {
694                 eint0_15_data[irq] = IRQ_EINT(irq);
695
696                 irq_set_handler_data(exynos4_get_irq_nr(irq),
697                                      &eint0_15_data[irq]);
698                 irq_set_chained_handler(exynos4_get_irq_nr(irq),
699                                         exynos4_irq_eint0_15);
700         }
701
702         return 0;
703 }
704 arch_initcall(exynos4_init_irq_eint);