blob: 4ef0cb513c8321ae67aeb830be7f14a960d7bfd8 [file] [log] [blame]
Kukjin Kimcc511b82011-12-27 08:18:36 +01001/*
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>
Linus Torvalds7affca32012-01-07 12:03:30 -080016#include <linux/device.h>
Kukjin Kimcc511b82011-12-27 08:18:36 +010017#include <linux/gpio.h>
18#include <linux/sched.h>
19#include <linux/serial_core.h>
Arnd Bergmann237c78b2012-01-07 12:30:20 +000020#include <linux/of.h>
21#include <linux/of_irq.h>
Kukjin Kimcc511b82011-12-27 08:18:36 +010022
23#include <asm/proc-fns.h>
Arnd Bergmann40ba95f2012-01-07 11:51:28 +000024#include <asm/exception.h>
Kukjin Kimcc511b82011-12-27 08:18:36 +010025#include <asm/hardware/cache-l2x0.h>
26#include <asm/hardware/gic.h>
27#include <asm/mach/map.h>
28#include <asm/mach/irq.h>
29
30#include <mach/regs-irq.h>
31#include <mach/regs-pmu.h>
32#include <mach/regs-gpio.h>
33
34#include <plat/cpu.h>
35#include <plat/clock.h>
36#include <plat/devs.h>
37#include <plat/pm.h>
Kukjin Kimcc511b82011-12-27 08:18:36 +010038#include <plat/sdhci.h>
39#include <plat/gpio-cfg.h>
40#include <plat/adc-core.h>
41#include <plat/fb-core.h>
42#include <plat/fimc-core.h>
43#include <plat/iic-core.h>
44#include <plat/tv-core.h>
45#include <plat/regs-serial.h>
46
47#include "common.h"
48
Kukjin Kimcc511b82011-12-27 08:18:36 +010049static const char name_exynos4210[] = "EXYNOS4210";
50static const char name_exynos4212[] = "EXYNOS4212";
51static const char name_exynos4412[] = "EXYNOS4412";
Kukjin Kim94c7ca72012-02-11 22:15:45 +090052static const char name_exynos5250[] = "EXYNOS5250";
Kukjin Kimcc511b82011-12-27 08:18:36 +010053
Kukjin Kim906c7892012-02-11 21:27:08 +090054static void exynos4_map_io(void);
Kukjin Kim94c7ca72012-02-11 22:15:45 +090055static void exynos5_map_io(void);
Kukjin Kim906c7892012-02-11 21:27:08 +090056static void exynos4_init_clocks(int xtal);
Kukjin Kim94c7ca72012-02-11 22:15:45 +090057static void exynos5_init_clocks(int xtal);
Kukjin Kim920f4882012-01-24 20:52:52 +090058static void exynos_init_uarts(struct s3c2410_uartcfg *cfg, int no);
Kukjin Kim906c7892012-02-11 21:27:08 +090059static int exynos_init(void);
60
Kukjin Kimcc511b82011-12-27 08:18:36 +010061static struct cpu_table cpu_ids[] __initdata = {
62 {
63 .idcode = EXYNOS4210_CPU_ID,
64 .idmask = EXYNOS4_CPU_MASK,
65 .map_io = exynos4_map_io,
66 .init_clocks = exynos4_init_clocks,
Kukjin Kim920f4882012-01-24 20:52:52 +090067 .init_uarts = exynos_init_uarts,
Kukjin Kimcc511b82011-12-27 08:18:36 +010068 .init = exynos_init,
69 .name = name_exynos4210,
70 }, {
71 .idcode = EXYNOS4212_CPU_ID,
72 .idmask = EXYNOS4_CPU_MASK,
73 .map_io = exynos4_map_io,
74 .init_clocks = exynos4_init_clocks,
Kukjin Kim920f4882012-01-24 20:52:52 +090075 .init_uarts = exynos_init_uarts,
Kukjin Kimcc511b82011-12-27 08:18:36 +010076 .init = exynos_init,
77 .name = name_exynos4212,
78 }, {
79 .idcode = EXYNOS4412_CPU_ID,
80 .idmask = EXYNOS4_CPU_MASK,
81 .map_io = exynos4_map_io,
82 .init_clocks = exynos4_init_clocks,
Kukjin Kim920f4882012-01-24 20:52:52 +090083 .init_uarts = exynos_init_uarts,
Kukjin Kimcc511b82011-12-27 08:18:36 +010084 .init = exynos_init,
85 .name = name_exynos4412,
Kukjin Kim94c7ca72012-02-11 22:15:45 +090086 }, {
87 .idcode = EXYNOS5250_SOC_ID,
88 .idmask = EXYNOS5_SOC_MASK,
89 .map_io = exynos5_map_io,
90 .init_clocks = exynos5_init_clocks,
91 .init_uarts = exynos_init_uarts,
92 .init = exynos_init,
93 .name = name_exynos5250,
Kukjin Kimcc511b82011-12-27 08:18:36 +010094 },
95};
96
97/* Initial IO mappings */
98
99static struct map_desc exynos_iodesc[] __initdata = {
100 {
101 .virtual = (unsigned long)S5P_VA_CHIPID,
Kukjin Kim94c7ca72012-02-11 22:15:45 +0900102 .pfn = __phys_to_pfn(EXYNOS_PA_CHIPID),
Kukjin Kimcc511b82011-12-27 08:18:36 +0100103 .length = SZ_4K,
104 .type = MT_DEVICE,
Kukjin Kim94c7ca72012-02-11 22:15:45 +0900105 },
106};
107
108static struct map_desc exynos4_iodesc[] __initdata = {
109 {
Kukjin Kimcc511b82011-12-27 08:18:36 +0100110 .virtual = (unsigned long)S3C_VA_SYS,
111 .pfn = __phys_to_pfn(EXYNOS4_PA_SYSCON),
112 .length = SZ_64K,
113 .type = MT_DEVICE,
114 }, {
115 .virtual = (unsigned long)S3C_VA_TIMER,
116 .pfn = __phys_to_pfn(EXYNOS4_PA_TIMER),
117 .length = SZ_16K,
118 .type = MT_DEVICE,
119 }, {
120 .virtual = (unsigned long)S3C_VA_WATCHDOG,
121 .pfn = __phys_to_pfn(EXYNOS4_PA_WATCHDOG),
122 .length = SZ_4K,
123 .type = MT_DEVICE,
124 }, {
125 .virtual = (unsigned long)S5P_VA_SROMC,
126 .pfn = __phys_to_pfn(EXYNOS4_PA_SROMC),
127 .length = SZ_4K,
128 .type = MT_DEVICE,
129 }, {
130 .virtual = (unsigned long)S5P_VA_SYSTIMER,
131 .pfn = __phys_to_pfn(EXYNOS4_PA_SYSTIMER),
132 .length = SZ_4K,
133 .type = MT_DEVICE,
134 }, {
135 .virtual = (unsigned long)S5P_VA_PMU,
136 .pfn = __phys_to_pfn(EXYNOS4_PA_PMU),
137 .length = SZ_64K,
138 .type = MT_DEVICE,
139 }, {
140 .virtual = (unsigned long)S5P_VA_COMBINER_BASE,
141 .pfn = __phys_to_pfn(EXYNOS4_PA_COMBINER),
142 .length = SZ_4K,
143 .type = MT_DEVICE,
144 }, {
145 .virtual = (unsigned long)S5P_VA_GIC_CPU,
146 .pfn = __phys_to_pfn(EXYNOS4_PA_GIC_CPU),
147 .length = SZ_64K,
148 .type = MT_DEVICE,
149 }, {
150 .virtual = (unsigned long)S5P_VA_GIC_DIST,
151 .pfn = __phys_to_pfn(EXYNOS4_PA_GIC_DIST),
152 .length = SZ_64K,
153 .type = MT_DEVICE,
154 }, {
155 .virtual = (unsigned long)S3C_VA_UART,
156 .pfn = __phys_to_pfn(EXYNOS4_PA_UART),
157 .length = SZ_512K,
158 .type = MT_DEVICE,
Kukjin Kim94c7ca72012-02-11 22:15:45 +0900159 }, {
Kukjin Kimcc511b82011-12-27 08:18:36 +0100160 .virtual = (unsigned long)S5P_VA_CMU,
161 .pfn = __phys_to_pfn(EXYNOS4_PA_CMU),
162 .length = SZ_128K,
163 .type = MT_DEVICE,
164 }, {
165 .virtual = (unsigned long)S5P_VA_COREPERI_BASE,
166 .pfn = __phys_to_pfn(EXYNOS4_PA_COREPERI),
167 .length = SZ_8K,
168 .type = MT_DEVICE,
169 }, {
170 .virtual = (unsigned long)S5P_VA_L2CC,
171 .pfn = __phys_to_pfn(EXYNOS4_PA_L2CC),
172 .length = SZ_4K,
173 .type = MT_DEVICE,
174 }, {
175 .virtual = (unsigned long)S5P_VA_GPIO1,
176 .pfn = __phys_to_pfn(EXYNOS4_PA_GPIO1),
177 .length = SZ_4K,
178 .type = MT_DEVICE,
179 }, {
180 .virtual = (unsigned long)S5P_VA_GPIO2,
181 .pfn = __phys_to_pfn(EXYNOS4_PA_GPIO2),
182 .length = SZ_4K,
183 .type = MT_DEVICE,
184 }, {
185 .virtual = (unsigned long)S5P_VA_GPIO3,
186 .pfn = __phys_to_pfn(EXYNOS4_PA_GPIO3),
187 .length = SZ_256,
188 .type = MT_DEVICE,
189 }, {
190 .virtual = (unsigned long)S5P_VA_DMC0,
191 .pfn = __phys_to_pfn(EXYNOS4_PA_DMC0),
192 .length = SZ_4K,
193 .type = MT_DEVICE,
194 }, {
Kukjin Kimcc511b82011-12-27 08:18:36 +0100195 .virtual = (unsigned long)S3C_VA_USB_HSPHY,
196 .pfn = __phys_to_pfn(EXYNOS4_PA_HSPHY),
197 .length = SZ_4K,
198 .type = MT_DEVICE,
199 },
200};
201
202static struct map_desc exynos4_iodesc0[] __initdata = {
203 {
204 .virtual = (unsigned long)S5P_VA_SYSRAM,
205 .pfn = __phys_to_pfn(EXYNOS4_PA_SYSRAM0),
206 .length = SZ_4K,
207 .type = MT_DEVICE,
208 },
209};
210
211static struct map_desc exynos4_iodesc1[] __initdata = {
212 {
213 .virtual = (unsigned long)S5P_VA_SYSRAM,
214 .pfn = __phys_to_pfn(EXYNOS4_PA_SYSRAM1),
215 .length = SZ_4K,
216 .type = MT_DEVICE,
217 },
218};
219
Kukjin Kim94c7ca72012-02-11 22:15:45 +0900220static struct map_desc exynos5_iodesc[] __initdata = {
221 {
222 .virtual = (unsigned long)S3C_VA_SYS,
223 .pfn = __phys_to_pfn(EXYNOS5_PA_SYSCON),
224 .length = SZ_64K,
225 .type = MT_DEVICE,
226 }, {
227 .virtual = (unsigned long)S3C_VA_TIMER,
228 .pfn = __phys_to_pfn(EXYNOS5_PA_TIMER),
229 .length = SZ_16K,
230 .type = MT_DEVICE,
231 }, {
232 .virtual = (unsigned long)S3C_VA_WATCHDOG,
233 .pfn = __phys_to_pfn(EXYNOS5_PA_WATCHDOG),
234 .length = SZ_4K,
235 .type = MT_DEVICE,
236 }, {
237 .virtual = (unsigned long)S5P_VA_SROMC,
238 .pfn = __phys_to_pfn(EXYNOS5_PA_SROMC),
239 .length = SZ_4K,
240 .type = MT_DEVICE,
241 }, {
242 .virtual = (unsigned long)S5P_VA_SYSTIMER,
243 .pfn = __phys_to_pfn(EXYNOS5_PA_SYSTIMER),
244 .length = SZ_4K,
245 .type = MT_DEVICE,
246 }, {
247 .virtual = (unsigned long)S5P_VA_SYSRAM,
248 .pfn = __phys_to_pfn(EXYNOS5_PA_SYSRAM),
249 .length = SZ_4K,
250 .type = MT_DEVICE,
251 }, {
252 .virtual = (unsigned long)S5P_VA_CMU,
253 .pfn = __phys_to_pfn(EXYNOS5_PA_CMU),
254 .length = 144 * SZ_1K,
255 .type = MT_DEVICE,
256 }, {
257 .virtual = (unsigned long)S5P_VA_PMU,
258 .pfn = __phys_to_pfn(EXYNOS5_PA_PMU),
259 .length = SZ_64K,
260 .type = MT_DEVICE,
261 }, {
262 .virtual = (unsigned long)S5P_VA_COMBINER_BASE,
263 .pfn = __phys_to_pfn(EXYNOS5_PA_COMBINER),
264 .length = SZ_4K,
265 .type = MT_DEVICE,
266 }, {
267 .virtual = (unsigned long)S3C_VA_UART,
268 .pfn = __phys_to_pfn(EXYNOS5_PA_UART),
269 .length = SZ_512K,
270 .type = MT_DEVICE,
271 }, {
272 .virtual = (unsigned long)S5P_VA_GIC_CPU,
273 .pfn = __phys_to_pfn(EXYNOS5_PA_GIC_CPU),
274 .length = SZ_64K,
275 .type = MT_DEVICE,
276 }, {
277 .virtual = (unsigned long)S5P_VA_GIC_DIST,
278 .pfn = __phys_to_pfn(EXYNOS5_PA_GIC_DIST),
279 .length = SZ_64K,
280 .type = MT_DEVICE,
281 },
282};
283
Russell King9eb48592012-01-03 11:56:53 +0100284void exynos4_restart(char mode, const char *cmd)
Kukjin Kimcc511b82011-12-27 08:18:36 +0100285{
286 __raw_writel(0x1, S5P_SWRESET);
287}
288
Kukjin Kim94c7ca72012-02-11 22:15:45 +0900289void exynos5_restart(char mode, const char *cmd)
290{
291 __raw_writel(0x1, EXYNOS_SWRESET);
292}
293
Kukjin Kimcc511b82011-12-27 08:18:36 +0100294/*
295 * exynos_map_io
296 *
297 * register the standard cpu IO areas
298 */
299
300void __init exynos_init_io(struct map_desc *mach_desc, int size)
301{
302 /* initialize the io descriptors we need for initialization */
303 iotable_init(exynos_iodesc, ARRAY_SIZE(exynos_iodesc));
304 if (mach_desc)
305 iotable_init(mach_desc, size);
306
307 /* detect cpu id and rev. */
308 s5p_init_cpu(S5P_VA_CHIPID);
309
310 s3c_init_cpu(samsung_cpu_id, cpu_ids, ARRAY_SIZE(cpu_ids));
311}
312
Kukjin Kim906c7892012-02-11 21:27:08 +0900313static void __init exynos4_map_io(void)
Kukjin Kimcc511b82011-12-27 08:18:36 +0100314{
315 iotable_init(exynos4_iodesc, ARRAY_SIZE(exynos4_iodesc));
316
317 if (soc_is_exynos4210() && samsung_rev() == EXYNOS4210_REV_0)
318 iotable_init(exynos4_iodesc0, ARRAY_SIZE(exynos4_iodesc0));
319 else
320 iotable_init(exynos4_iodesc1, ARRAY_SIZE(exynos4_iodesc1));
321
322 /* initialize device information early */
323 exynos4_default_sdhci0();
324 exynos4_default_sdhci1();
325 exynos4_default_sdhci2();
326 exynos4_default_sdhci3();
327
328 s3c_adc_setname("samsung-adc-v3");
329
330 s3c_fimc_setname(0, "exynos4-fimc");
331 s3c_fimc_setname(1, "exynos4-fimc");
332 s3c_fimc_setname(2, "exynos4-fimc");
333 s3c_fimc_setname(3, "exynos4-fimc");
334
335 /* The I2C bus controllers are directly compatible with s3c2440 */
336 s3c_i2c0_setname("s3c2440-i2c");
337 s3c_i2c1_setname("s3c2440-i2c");
338 s3c_i2c2_setname("s3c2440-i2c");
339
340 s5p_fb_setname(0, "exynos4-fb");
341 s5p_hdmi_setname("exynos4-hdmi");
342}
343
Kukjin Kim94c7ca72012-02-11 22:15:45 +0900344static void __init exynos5_map_io(void)
345{
346 iotable_init(exynos5_iodesc, ARRAY_SIZE(exynos5_iodesc));
347
Kukjin Kimbb19a752012-01-25 13:48:11 +0900348 s3c_device_i2c0.resource[0].start = EXYNOS5_PA_IIC(0);
349 s3c_device_i2c0.resource[0].end = EXYNOS5_PA_IIC(0) + SZ_4K - 1;
350 s3c_device_i2c0.resource[1].start = EXYNOS5_IRQ_IIC;
351 s3c_device_i2c0.resource[1].end = EXYNOS5_IRQ_IIC;
352
Kukjin Kim94c7ca72012-02-11 22:15:45 +0900353 /* The I2C bus controllers are directly compatible with s3c2440 */
354 s3c_i2c0_setname("s3c2440-i2c");
355 s3c_i2c1_setname("s3c2440-i2c");
356 s3c_i2c2_setname("s3c2440-i2c");
357}
358
Kukjin Kim906c7892012-02-11 21:27:08 +0900359static void __init exynos4_init_clocks(int xtal)
Kukjin Kimcc511b82011-12-27 08:18:36 +0100360{
361 printk(KERN_DEBUG "%s: initializing clocks\n", __func__);
362
363 s3c24xx_register_baseclocks(xtal);
364 s5p_register_clocks(xtal);
365
366 if (soc_is_exynos4210())
367 exynos4210_register_clocks();
368 else if (soc_is_exynos4212() || soc_is_exynos4412())
369 exynos4212_register_clocks();
370
371 exynos4_register_clocks();
372 exynos4_setup_clocks();
373}
374
Kukjin Kim94c7ca72012-02-11 22:15:45 +0900375static void __init exynos5_init_clocks(int xtal)
376{
377 printk(KERN_DEBUG "%s: initializing clocks\n", __func__);
378
379 s3c24xx_register_baseclocks(xtal);
380 s5p_register_clocks(xtal);
381
382 exynos5_register_clocks();
383 exynos5_setup_clocks();
384}
385
Kukjin Kimcc511b82011-12-27 08:18:36 +0100386#define COMBINER_ENABLE_SET 0x0
387#define COMBINER_ENABLE_CLEAR 0x4
388#define COMBINER_INT_STATUS 0xC
389
390static DEFINE_SPINLOCK(irq_controller_lock);
391
392struct combiner_chip_data {
393 unsigned int irq_offset;
394 unsigned int irq_mask;
395 void __iomem *base;
396};
397
398static struct combiner_chip_data combiner_data[MAX_COMBINER_NR];
399
400static inline void __iomem *combiner_base(struct irq_data *data)
401{
402 struct combiner_chip_data *combiner_data =
403 irq_data_get_irq_chip_data(data);
404
405 return combiner_data->base;
406}
407
408static void combiner_mask_irq(struct irq_data *data)
409{
410 u32 mask = 1 << (data->irq % 32);
411
412 __raw_writel(mask, combiner_base(data) + COMBINER_ENABLE_CLEAR);
413}
414
415static void combiner_unmask_irq(struct irq_data *data)
416{
417 u32 mask = 1 << (data->irq % 32);
418
419 __raw_writel(mask, combiner_base(data) + COMBINER_ENABLE_SET);
420}
421
422static void combiner_handle_cascade_irq(unsigned int irq, struct irq_desc *desc)
423{
424 struct combiner_chip_data *chip_data = irq_get_handler_data(irq);
425 struct irq_chip *chip = irq_get_chip(irq);
426 unsigned int cascade_irq, combiner_irq;
427 unsigned long status;
428
429 chained_irq_enter(chip, desc);
430
431 spin_lock(&irq_controller_lock);
432 status = __raw_readl(chip_data->base + COMBINER_INT_STATUS);
433 spin_unlock(&irq_controller_lock);
434 status &= chip_data->irq_mask;
435
436 if (status == 0)
437 goto out;
438
439 combiner_irq = __ffs(status);
440
441 cascade_irq = combiner_irq + (chip_data->irq_offset & ~31);
442 if (unlikely(cascade_irq >= NR_IRQS))
443 do_bad_IRQ(cascade_irq, desc);
444 else
445 generic_handle_irq(cascade_irq);
446
447 out:
448 chained_irq_exit(chip, desc);
449}
450
451static struct irq_chip combiner_chip = {
452 .name = "COMBINER",
453 .irq_mask = combiner_mask_irq,
454 .irq_unmask = combiner_unmask_irq,
455};
456
457static void __init combiner_cascade_irq(unsigned int combiner_nr, unsigned int irq)
458{
Kukjin Kimbb19a752012-01-25 13:48:11 +0900459 unsigned int max_nr;
460
461 if (soc_is_exynos5250())
462 max_nr = EXYNOS5_MAX_COMBINER_NR;
463 else
464 max_nr = EXYNOS4_MAX_COMBINER_NR;
465
466 if (combiner_nr >= max_nr)
Kukjin Kimcc511b82011-12-27 08:18:36 +0100467 BUG();
468 if (irq_set_handler_data(irq, &combiner_data[combiner_nr]) != 0)
469 BUG();
470 irq_set_chained_handler(irq, combiner_handle_cascade_irq);
471}
472
473static void __init combiner_init(unsigned int combiner_nr, void __iomem *base,
474 unsigned int irq_start)
475{
476 unsigned int i;
Kukjin Kimbb19a752012-01-25 13:48:11 +0900477 unsigned int max_nr;
Kukjin Kimcc511b82011-12-27 08:18:36 +0100478
Kukjin Kimbb19a752012-01-25 13:48:11 +0900479 if (soc_is_exynos5250())
480 max_nr = EXYNOS5_MAX_COMBINER_NR;
481 else
482 max_nr = EXYNOS4_MAX_COMBINER_NR;
483
484 if (combiner_nr >= max_nr)
Kukjin Kimcc511b82011-12-27 08:18:36 +0100485 BUG();
486
487 combiner_data[combiner_nr].base = base;
488 combiner_data[combiner_nr].irq_offset = irq_start;
489 combiner_data[combiner_nr].irq_mask = 0xff << ((combiner_nr % 4) << 3);
490
491 /* Disable all interrupts */
492
493 __raw_writel(combiner_data[combiner_nr].irq_mask,
494 base + COMBINER_ENABLE_CLEAR);
495
496 /* Setup the Linux IRQ subsystem */
497
498 for (i = irq_start; i < combiner_data[combiner_nr].irq_offset
499 + MAX_IRQ_IN_COMBINER; i++) {
500 irq_set_chip_and_handler(i, &combiner_chip, handle_level_irq);
501 irq_set_chip_data(i, &combiner_data[combiner_nr]);
502 set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
503 }
504}
505
Arnd Bergmann237c78b2012-01-07 12:30:20 +0000506#ifdef CONFIG_OF
507static const struct of_device_id exynos4_dt_irq_match[] = {
508 { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
509 {},
510};
511#endif
Kukjin Kimcc511b82011-12-27 08:18:36 +0100512
513void __init exynos4_init_irq(void)
514{
515 int irq;
Arnd Bergmann40ba95f2012-01-07 11:51:28 +0000516 unsigned int gic_bank_offset;
Kukjin Kimcc511b82011-12-27 08:18:36 +0100517
518 gic_bank_offset = soc_is_exynos4412() ? 0x4000 : 0x8000;
519
Arnd Bergmann237c78b2012-01-07 12:30:20 +0000520 if (!of_have_populated_dt())
521 gic_init_bases(0, IRQ_PPI(0), S5P_VA_GIC_DIST, S5P_VA_GIC_CPU, gic_bank_offset);
522#ifdef CONFIG_OF
523 else
524 of_irq_init(exynos4_dt_irq_match);
525#endif
Kukjin Kimcc511b82011-12-27 08:18:36 +0100526
Kukjin Kimbb19a752012-01-25 13:48:11 +0900527 for (irq = 0; irq < EXYNOS4_MAX_COMBINER_NR; irq++) {
Kukjin Kimcc511b82011-12-27 08:18:36 +0100528
529 combiner_init(irq, (void __iomem *)S5P_VA_COMBINER(irq),
530 COMBINER_IRQ(irq, 0));
531 combiner_cascade_irq(irq, IRQ_SPI(irq));
532 }
533
534 /*
535 * The parameters of s5p_init_irq() are for VIC init.
536 * Theses parameters should be NULL and 0 because EXYNOS4
537 * uses GIC instead of VIC.
538 */
539 s5p_init_irq(NULL, 0);
540}
541
Kukjin Kim94c7ca72012-02-11 22:15:45 +0900542void __init exynos5_init_irq(void)
543{
544 int irq;
545
546 gic_init(0, IRQ_PPI(0), S5P_VA_GIC_DIST, S5P_VA_GIC_CPU);
547
Kukjin Kimbb19a752012-01-25 13:48:11 +0900548 for (irq = 0; irq < EXYNOS5_MAX_COMBINER_NR; irq++) {
Kukjin Kim94c7ca72012-02-11 22:15:45 +0900549 combiner_init(irq, (void __iomem *)S5P_VA_COMBINER(irq),
550 COMBINER_IRQ(irq, 0));
551 combiner_cascade_irq(irq, IRQ_SPI(irq));
552 }
553
554 /*
555 * The parameters of s5p_init_irq() are for VIC init.
556 * Theses parameters should be NULL and 0 because EXYNOS4
557 * uses GIC instead of VIC.
558 */
559 s5p_init_irq(NULL, 0);
560}
561
Linus Torvalds7affca32012-01-07 12:03:30 -0800562struct bus_type exynos4_subsys = {
563 .name = "exynos4-core",
564 .dev_name = "exynos4-core",
Kukjin Kimcc511b82011-12-27 08:18:36 +0100565};
566
Kukjin Kim94c7ca72012-02-11 22:15:45 +0900567struct bus_type exynos5_subsys = {
568 .name = "exynos5-core",
569 .dev_name = "exynos5-core",
570};
571
Linus Torvalds7affca32012-01-07 12:03:30 -0800572static struct device exynos4_dev = {
573 .bus = &exynos4_subsys,
Kukjin Kimcc511b82011-12-27 08:18:36 +0100574};
575
Kukjin Kim94c7ca72012-02-11 22:15:45 +0900576static struct device exynos5_dev = {
577 .bus = &exynos5_subsys,
578};
579
580static int __init exynos_core_init(void)
Kukjin Kimcc511b82011-12-27 08:18:36 +0100581{
Kukjin Kim94c7ca72012-02-11 22:15:45 +0900582 if (soc_is_exynos5250())
583 return subsys_system_register(&exynos5_subsys, NULL);
584 else
585 return subsys_system_register(&exynos4_subsys, NULL);
Kukjin Kimcc511b82011-12-27 08:18:36 +0100586}
Kukjin Kim94c7ca72012-02-11 22:15:45 +0900587core_initcall(exynos_core_init);
Kukjin Kimcc511b82011-12-27 08:18:36 +0100588
589#ifdef CONFIG_CACHE_L2X0
590static int __init exynos4_l2x0_cache_init(void)
591{
Kukjin Kim94c7ca72012-02-11 22:15:45 +0900592 if (soc_is_exynos5250())
593 return 0;
594
Kukjin Kimcc511b82011-12-27 08:18:36 +0100595 /* TAG, Data Latency Control: 2cycle */
596 __raw_writel(0x110, S5P_VA_L2CC + L2X0_TAG_LATENCY_CTRL);
597
598 if (soc_is_exynos4210())
599 __raw_writel(0x110, S5P_VA_L2CC + L2X0_DATA_LATENCY_CTRL);
600 else if (soc_is_exynos4212() || soc_is_exynos4412())
601 __raw_writel(0x120, S5P_VA_L2CC + L2X0_DATA_LATENCY_CTRL);
602
603 /* L2X0 Prefetch Control */
604 __raw_writel(0x30000007, S5P_VA_L2CC + L2X0_PREFETCH_CTRL);
605
606 /* L2X0 Power Control */
607 __raw_writel(L2X0_DYNAMIC_CLK_GATING_EN | L2X0_STNDBY_MODE_EN,
608 S5P_VA_L2CC + L2X0_POWER_CTRL);
609
610 l2x0_init(S5P_VA_L2CC, 0x7C470001, 0xC200ffff);
611
612 return 0;
613}
Kukjin Kimcc511b82011-12-27 08:18:36 +0100614early_initcall(exynos4_l2x0_cache_init);
615#endif
616
Kukjin Kim94c7ca72012-02-11 22:15:45 +0900617static int __init exynos5_l2_cache_init(void)
618{
619 unsigned int val;
620
621 if (!soc_is_exynos5250())
622 return 0;
623
624 asm volatile("mrc p15, 0, %0, c1, c0, 0\n"
625 "bic %0, %0, #(1 << 2)\n" /* cache disable */
626 "mcr p15, 0, %0, c1, c0, 0\n"
627 "mrc p15, 1, %0, c9, c0, 2\n"
628 : "=r"(val));
629
630 val |= (1 << 9) | (1 << 5) | (2 << 6) | (2 << 0);
631
632 asm volatile("mcr p15, 1, %0, c9, c0, 2\n" : : "r"(val));
633 asm volatile("mrc p15, 0, %0, c1, c0, 0\n"
634 "orr %0, %0, #(1 << 2)\n" /* cache enable */
635 "mcr p15, 0, %0, c1, c0, 0\n"
636 : : "r"(val));
637
638 return 0;
639}
640early_initcall(exynos5_l2_cache_init);
641
Kukjin Kim906c7892012-02-11 21:27:08 +0900642static int __init exynos_init(void)
Kukjin Kimcc511b82011-12-27 08:18:36 +0100643{
644 printk(KERN_INFO "EXYNOS: Initializing architecture\n");
Kukjin Kim94c7ca72012-02-11 22:15:45 +0900645
646 if (soc_is_exynos5250())
647 return device_register(&exynos5_dev);
648 else
649 return device_register(&exynos4_dev);
Kukjin Kimcc511b82011-12-27 08:18:36 +0100650}
651
Kukjin Kimcc511b82011-12-27 08:18:36 +0100652/* uart registration process */
653
Kukjin Kim920f4882012-01-24 20:52:52 +0900654static void __init exynos_init_uarts(struct s3c2410_uartcfg *cfg, int no)
Kukjin Kimcc511b82011-12-27 08:18:36 +0100655{
656 struct s3c2410_uartcfg *tcfg = cfg;
657 u32 ucnt;
658
Arnd Bergmann237c78b2012-01-07 12:30:20 +0000659 for (ucnt = 0; ucnt < no; ucnt++, tcfg++)
660 tcfg->has_fracval = 1;
Kukjin Kimcc511b82011-12-27 08:18:36 +0100661
Kukjin Kim171c0672012-02-10 11:57:53 +0900662 if (soc_is_exynos5250())
663 s3c24xx_init_uartdevs("exynos4210-uart", exynos5_uart_resources, cfg, no);
664 else
665 s3c24xx_init_uartdevs("exynos4210-uart", exynos4_uart_resources, cfg, no);
Kukjin Kimcc511b82011-12-27 08:18:36 +0100666}
667
668static DEFINE_SPINLOCK(eint_lock);
669
670static unsigned int eint0_15_data[16];
671
Kukjin Kimbb19a752012-01-25 13:48:11 +0900672static unsigned int exynos4_eint0_15_src_int[16] = {
673 EXYNOS4_IRQ_EINT0,
674 EXYNOS4_IRQ_EINT1,
675 EXYNOS4_IRQ_EINT2,
676 EXYNOS4_IRQ_EINT3,
677 EXYNOS4_IRQ_EINT4,
678 EXYNOS4_IRQ_EINT5,
679 EXYNOS4_IRQ_EINT6,
680 EXYNOS4_IRQ_EINT7,
681 EXYNOS4_IRQ_EINT8,
682 EXYNOS4_IRQ_EINT9,
683 EXYNOS4_IRQ_EINT10,
684 EXYNOS4_IRQ_EINT11,
685 EXYNOS4_IRQ_EINT12,
686 EXYNOS4_IRQ_EINT13,
687 EXYNOS4_IRQ_EINT14,
688 EXYNOS4_IRQ_EINT15,
689};
Kukjin Kimcc511b82011-12-27 08:18:36 +0100690
Kukjin Kimbb19a752012-01-25 13:48:11 +0900691static unsigned int exynos5_eint0_15_src_int[16] = {
692 EXYNOS5_IRQ_EINT0,
693 EXYNOS5_IRQ_EINT1,
694 EXYNOS5_IRQ_EINT2,
695 EXYNOS5_IRQ_EINT3,
696 EXYNOS5_IRQ_EINT4,
697 EXYNOS5_IRQ_EINT5,
698 EXYNOS5_IRQ_EINT6,
699 EXYNOS5_IRQ_EINT7,
700 EXYNOS5_IRQ_EINT8,
701 EXYNOS5_IRQ_EINT9,
702 EXYNOS5_IRQ_EINT10,
703 EXYNOS5_IRQ_EINT11,
704 EXYNOS5_IRQ_EINT12,
705 EXYNOS5_IRQ_EINT13,
706 EXYNOS5_IRQ_EINT14,
707 EXYNOS5_IRQ_EINT15,
708};
Kukjin Kimcc511b82011-12-27 08:18:36 +0100709static inline void exynos4_irq_eint_mask(struct irq_data *data)
710{
711 u32 mask;
712
713 spin_lock(&eint_lock);
714 mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(data->irq)));
715 mask |= eint_irq_to_bit(data->irq);
716 __raw_writel(mask, S5P_EINT_MASK(EINT_REG_NR(data->irq)));
717 spin_unlock(&eint_lock);
718}
719
720static void exynos4_irq_eint_unmask(struct irq_data *data)
721{
722 u32 mask;
723
724 spin_lock(&eint_lock);
725 mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(data->irq)));
726 mask &= ~(eint_irq_to_bit(data->irq));
727 __raw_writel(mask, S5P_EINT_MASK(EINT_REG_NR(data->irq)));
728 spin_unlock(&eint_lock);
729}
730
731static inline void exynos4_irq_eint_ack(struct irq_data *data)
732{
733 __raw_writel(eint_irq_to_bit(data->irq),
734 S5P_EINT_PEND(EINT_REG_NR(data->irq)));
735}
736
737static void exynos4_irq_eint_maskack(struct irq_data *data)
738{
739 exynos4_irq_eint_mask(data);
740 exynos4_irq_eint_ack(data);
741}
742
743static int exynos4_irq_eint_set_type(struct irq_data *data, unsigned int type)
744{
745 int offs = EINT_OFFSET(data->irq);
746 int shift;
747 u32 ctrl, mask;
748 u32 newvalue = 0;
749
750 switch (type) {
751 case IRQ_TYPE_EDGE_RISING:
752 newvalue = S5P_IRQ_TYPE_EDGE_RISING;
753 break;
754
755 case IRQ_TYPE_EDGE_FALLING:
756 newvalue = S5P_IRQ_TYPE_EDGE_FALLING;
757 break;
758
759 case IRQ_TYPE_EDGE_BOTH:
760 newvalue = S5P_IRQ_TYPE_EDGE_BOTH;
761 break;
762
763 case IRQ_TYPE_LEVEL_LOW:
764 newvalue = S5P_IRQ_TYPE_LEVEL_LOW;
765 break;
766
767 case IRQ_TYPE_LEVEL_HIGH:
768 newvalue = S5P_IRQ_TYPE_LEVEL_HIGH;
769 break;
770
771 default:
772 printk(KERN_ERR "No such irq type %d", type);
773 return -EINVAL;
774 }
775
776 shift = (offs & 0x7) * 4;
777 mask = 0x7 << shift;
778
779 spin_lock(&eint_lock);
780 ctrl = __raw_readl(S5P_EINT_CON(EINT_REG_NR(data->irq)));
781 ctrl &= ~mask;
782 ctrl |= newvalue << shift;
783 __raw_writel(ctrl, S5P_EINT_CON(EINT_REG_NR(data->irq)));
784 spin_unlock(&eint_lock);
785
786 switch (offs) {
787 case 0 ... 7:
788 s3c_gpio_cfgpin(EINT_GPIO_0(offs & 0x7), EINT_MODE);
789 break;
790 case 8 ... 15:
791 s3c_gpio_cfgpin(EINT_GPIO_1(offs & 0x7), EINT_MODE);
792 break;
793 case 16 ... 23:
794 s3c_gpio_cfgpin(EINT_GPIO_2(offs & 0x7), EINT_MODE);
795 break;
796 case 24 ... 31:
797 s3c_gpio_cfgpin(EINT_GPIO_3(offs & 0x7), EINT_MODE);
798 break;
799 default:
800 printk(KERN_ERR "No such irq number %d", offs);
801 }
802
803 return 0;
804}
805
806static struct irq_chip exynos4_irq_eint = {
807 .name = "exynos4-eint",
808 .irq_mask = exynos4_irq_eint_mask,
809 .irq_unmask = exynos4_irq_eint_unmask,
810 .irq_mask_ack = exynos4_irq_eint_maskack,
811 .irq_ack = exynos4_irq_eint_ack,
812 .irq_set_type = exynos4_irq_eint_set_type,
813#ifdef CONFIG_PM
814 .irq_set_wake = s3c_irqext_wake,
815#endif
816};
817
818/*
819 * exynos4_irq_demux_eint
820 *
821 * This function demuxes the IRQ from from EINTs 16 to 31.
822 * It is designed to be inlined into the specific handler
823 * s5p_irq_demux_eintX_Y.
824 *
825 * Each EINT pend/mask registers handle eight of them.
826 */
827static inline void exynos4_irq_demux_eint(unsigned int start)
828{
829 unsigned int irq;
830
831 u32 status = __raw_readl(S5P_EINT_PEND(EINT_REG_NR(start)));
832 u32 mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(start)));
833
834 status &= ~mask;
835 status &= 0xff;
836
837 while (status) {
838 irq = fls(status) - 1;
839 generic_handle_irq(irq + start);
840 status &= ~(1 << irq);
841 }
842}
843
844static void exynos4_irq_demux_eint16_31(unsigned int irq, struct irq_desc *desc)
845{
846 struct irq_chip *chip = irq_get_chip(irq);
847 chained_irq_enter(chip, desc);
848 exynos4_irq_demux_eint(IRQ_EINT(16));
849 exynos4_irq_demux_eint(IRQ_EINT(24));
850 chained_irq_exit(chip, desc);
851}
852
Kukjin Kimbb19a752012-01-25 13:48:11 +0900853static void exynos_irq_eint0_15(unsigned int irq, struct irq_desc *desc)
Kukjin Kimcc511b82011-12-27 08:18:36 +0100854{
855 u32 *irq_data = irq_get_handler_data(irq);
856 struct irq_chip *chip = irq_get_chip(irq);
857
858 chained_irq_enter(chip, desc);
859 chip->irq_mask(&desc->irq_data);
860
861 if (chip->irq_ack)
862 chip->irq_ack(&desc->irq_data);
863
864 generic_handle_irq(*irq_data);
865
866 chip->irq_unmask(&desc->irq_data);
867 chained_irq_exit(chip, desc);
868}
869
Kukjin Kime745e062012-01-21 10:47:14 +0900870static int __init exynos4_init_irq_eint(void)
Kukjin Kimcc511b82011-12-27 08:18:36 +0100871{
872 int irq;
873
Kukjin Kim94c7ca72012-02-11 22:15:45 +0900874 if (soc_is_exynos5250())
875 return 0;
876
Kukjin Kimcc511b82011-12-27 08:18:36 +0100877 for (irq = 0 ; irq <= 31 ; irq++) {
878 irq_set_chip_and_handler(IRQ_EINT(irq), &exynos4_irq_eint,
879 handle_level_irq);
880 set_irq_flags(IRQ_EINT(irq), IRQF_VALID);
881 }
882
Kukjin Kimbb19a752012-01-25 13:48:11 +0900883 irq_set_chained_handler(EXYNOS_IRQ_EINT16_31, exynos4_irq_demux_eint16_31);
Kukjin Kimcc511b82011-12-27 08:18:36 +0100884
885 for (irq = 0 ; irq <= 15 ; irq++) {
886 eint0_15_data[irq] = IRQ_EINT(irq);
887
Kukjin Kimbb19a752012-01-25 13:48:11 +0900888 if (soc_is_exynos5250()) {
889 irq_set_handler_data(exynos5_eint0_15_src_int[irq],
890 &eint0_15_data[irq]);
891 irq_set_chained_handler(exynos5_eint0_15_src_int[irq],
892 exynos_irq_eint0_15);
893 } else {
894 irq_set_handler_data(exynos4_eint0_15_src_int[irq],
895 &eint0_15_data[irq]);
896 irq_set_chained_handler(exynos4_eint0_15_src_int[irq],
897 exynos_irq_eint0_15);
898 }
Kukjin Kimcc511b82011-12-27 08:18:36 +0100899 }
900
901 return 0;
902}
903arch_initcall(exynos4_init_irq_eint);