diff options
author | Arnd Bergmann <arnd@arndb.de> | 2013-04-19 17:15:58 -0400 |
---|---|---|
committer | Arnd Bergmann <arnd@arndb.de> | 2013-04-19 18:35:17 -0400 |
commit | 2254c36ddeb87d4975d2e4709413dd275a913e83 (patch) | |
tree | f0b8c52e5d3a0727e8e75f41085fd6b0819d8daf | |
parent | 22cf644e03419b4c3d002109b021c7482306f0bf (diff) | |
parent | 20adee8fa06ef69012bc277739e9e3762c78b7b7 (diff) |
Merge branch 'samsung/exynos-multiplatform-drivers' into late/multiplatform
This series contains the final pieces for Exynos multiplatform support:
Most of the patches are about the exynos-combiner irqchip, which is
converted to not rely on platform provided constants.
* samsung/exynos-multiplatform-drivers:
ARM: exynos: restore mach/regs-clock.h for exynos5
irqchip: exynos: look up irq using irq_find_mapping
irqchip: exynos: pass irq_base from platform
irqchip: exynos: localize irq lookup for ATAGS
irqchip: exynos: allocate combiner_data dynamically
irqchip: exynos: pass max combiner number to combiner_init
ARM: exynos: add missing properties for combiner IRQs
clocksource: exynos_mct: remove platform header dependency
clk: exynos: prepare for multiplatform
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
-rw-r--r-- | arch/arm/boot/dts/exynos4210.dtsi | 1 | ||||
-rw-r--r-- | arch/arm/boot/dts/exynos4212.dtsi | 9 | ||||
-rw-r--r-- | arch/arm/boot/dts/exynos4412.dtsi | 9 | ||||
-rw-r--r-- | arch/arm/mach-exynos/common.c | 20 | ||||
-rw-r--r-- | arch/arm/mach-exynos/common.h | 7 | ||||
-rw-r--r-- | drivers/clk/samsung/clk-exynos4.c | 93 | ||||
-rw-r--r-- | drivers/clk/samsung/clk-exynos5250.c | 1 | ||||
-rw-r--r-- | drivers/clk/samsung/clk-exynos5440.c | 1 | ||||
-rw-r--r-- | drivers/clk/samsung/clk.h | 2 | ||||
-rw-r--r-- | drivers/clocksource/exynos_mct.c | 21 | ||||
-rw-r--r-- | drivers/irqchip/exynos-combiner.c | 125 |
11 files changed, 152 insertions, 137 deletions
diff --git a/arch/arm/boot/dts/exynos4210.dtsi b/arch/arm/boot/dts/exynos4210.dtsi index 15143bdbafb8..5feccffae409 100644 --- a/arch/arm/boot/dts/exynos4210.dtsi +++ b/arch/arm/boot/dts/exynos4210.dtsi | |||
@@ -41,6 +41,7 @@ | |||
41 | }; | 41 | }; |
42 | 42 | ||
43 | combiner:interrupt-controller@10440000 { | 43 | combiner:interrupt-controller@10440000 { |
44 | samsung,combiner-nr = <16>; | ||
44 | interrupts = <0 0 0>, <0 1 0>, <0 2 0>, <0 3 0>, | 45 | interrupts = <0 0 0>, <0 1 0>, <0 2 0>, <0 3 0>, |
45 | <0 4 0>, <0 5 0>, <0 6 0>, <0 7 0>, | 46 | <0 4 0>, <0 5 0>, <0 6 0>, <0 7 0>, |
46 | <0 8 0>, <0 9 0>, <0 10 0>, <0 11 0>, | 47 | <0 8 0>, <0 9 0>, <0 10 0>, <0 11 0>, |
diff --git a/arch/arm/boot/dts/exynos4212.dtsi b/arch/arm/boot/dts/exynos4212.dtsi index 36d4299789ef..c0f60f49cea6 100644 --- a/arch/arm/boot/dts/exynos4212.dtsi +++ b/arch/arm/boot/dts/exynos4212.dtsi | |||
@@ -26,6 +26,15 @@ | |||
26 | cpu-offset = <0x8000>; | 26 | cpu-offset = <0x8000>; |
27 | }; | 27 | }; |
28 | 28 | ||
29 | interrupt-controller@10440000 { | ||
30 | samsung,combiner-nr = <18>; | ||
31 | interrupts = <0 0 0>, <0 1 0>, <0 2 0>, <0 3 0>, | ||
32 | <0 4 0>, <0 5 0>, <0 6 0>, <0 7 0>, | ||
33 | <0 8 0>, <0 9 0>, <0 10 0>, <0 11 0>, | ||
34 | <0 12 0>, <0 13 0>, <0 14 0>, <0 15 0>, | ||
35 | <0 107 0>, <0 108 0>; | ||
36 | }; | ||
37 | |||
29 | mct@10050000 { | 38 | mct@10050000 { |
30 | compatible = "samsung,exynos4412-mct"; | 39 | compatible = "samsung,exynos4412-mct"; |
31 | reg = <0x10050000 0x800>; | 40 | reg = <0x10050000 0x800>; |
diff --git a/arch/arm/boot/dts/exynos4412.dtsi b/arch/arm/boot/dts/exynos4412.dtsi index d75c047e80a9..f433206bd3c5 100644 --- a/arch/arm/boot/dts/exynos4412.dtsi +++ b/arch/arm/boot/dts/exynos4412.dtsi | |||
@@ -26,6 +26,15 @@ | |||
26 | cpu-offset = <0x4000>; | 26 | cpu-offset = <0x4000>; |
27 | }; | 27 | }; |
28 | 28 | ||
29 | interrupt-controller@10440000 { | ||
30 | samsung,combiner-nr = <20>; | ||
31 | interrupts = <0 0 0>, <0 1 0>, <0 2 0>, <0 3 0>, | ||
32 | <0 4 0>, <0 5 0>, <0 6 0>, <0 7 0>, | ||
33 | <0 8 0>, <0 9 0>, <0 10 0>, <0 11 0>, | ||
34 | <0 12 0>, <0 13 0>, <0 14 0>, <0 15 0>, | ||
35 | <0 107 0>, <0 108 0>, <0 48 0>, <0 42 0>; | ||
36 | }; | ||
37 | |||
29 | mct@10050000 { | 38 | mct@10050000 { |
30 | compatible = "samsung,exynos4412-mct"; | 39 | compatible = "samsung,exynos4412-mct"; |
31 | reg = <0x10050000 0x800>; | 40 | reg = <0x10050000 0x800>; |
diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c index a3ab0ecc7c6a..9208079d5d52 100644 --- a/arch/arm/mach-exynos/common.c +++ b/arch/arm/mach-exynos/common.c | |||
@@ -413,13 +413,26 @@ void __init exynos_init_time(void) | |||
413 | } else { | 413 | } else { |
414 | /* todo: remove after migrating legacy E4 platforms to dt */ | 414 | /* todo: remove after migrating legacy E4 platforms to dt */ |
415 | #ifdef CONFIG_ARCH_EXYNOS4 | 415 | #ifdef CONFIG_ARCH_EXYNOS4 |
416 | exynos4_clk_init(NULL); | 416 | exynos4_clk_init(NULL, !soc_is_exynos4210(), S5P_VA_CMU, readl(S5P_VA_CHIPID + 8) & 1); |
417 | exynos4_clk_register_fixed_ext(xxti_f, xusbxti_f); | 417 | exynos4_clk_register_fixed_ext(xxti_f, xusbxti_f); |
418 | #endif | 418 | #endif |
419 | mct_init(); | 419 | mct_init(S5P_VA_SYSTIMER, EXYNOS4_IRQ_MCT_G0, EXYNOS4_IRQ_MCT_L0, EXYNOS4_IRQ_MCT_L1); |
420 | } | 420 | } |
421 | } | 421 | } |
422 | 422 | ||
423 | static unsigned int max_combiner_nr(void) | ||
424 | { | ||
425 | if (soc_is_exynos5250()) | ||
426 | return EXYNOS5_MAX_COMBINER_NR; | ||
427 | else if (soc_is_exynos4412()) | ||
428 | return EXYNOS4412_MAX_COMBINER_NR; | ||
429 | else if (soc_is_exynos4212()) | ||
430 | return EXYNOS4212_MAX_COMBINER_NR; | ||
431 | else | ||
432 | return EXYNOS4210_MAX_COMBINER_NR; | ||
433 | } | ||
434 | |||
435 | |||
423 | void __init exynos4_init_irq(void) | 436 | void __init exynos4_init_irq(void) |
424 | { | 437 | { |
425 | unsigned int gic_bank_offset; | 438 | unsigned int gic_bank_offset; |
@@ -434,7 +447,8 @@ void __init exynos4_init_irq(void) | |||
434 | #endif | 447 | #endif |
435 | 448 | ||
436 | if (!of_have_populated_dt()) | 449 | if (!of_have_populated_dt()) |
437 | combiner_init(S5P_VA_COMBINER_BASE, NULL); | 450 | combiner_init(S5P_VA_COMBINER_BASE, NULL, |
451 | max_combiner_nr(), COMBINER_IRQ(0, 0)); | ||
438 | 452 | ||
439 | /* | 453 | /* |
440 | * The parameters of s5p_init_irq() are for VIC init. | 454 | * The parameters of s5p_init_irq() are for VIC init. |
diff --git a/arch/arm/mach-exynos/common.h b/arch/arm/mach-exynos/common.h index cb89ab886950..3e72d03a385e 100644 --- a/arch/arm/mach-exynos/common.h +++ b/arch/arm/mach-exynos/common.h | |||
@@ -14,7 +14,7 @@ | |||
14 | 14 | ||
15 | #include <linux/of.h> | 15 | #include <linux/of.h> |
16 | 16 | ||
17 | extern void mct_init(void); | 17 | void mct_init(void __iomem *base, int irq_g0, int irq_l0, int irq_l1); |
18 | void exynos_init_time(void); | 18 | void exynos_init_time(void); |
19 | extern unsigned long xxti_f, xusbxti_f; | 19 | extern unsigned long xxti_f, xusbxti_f; |
20 | 20 | ||
@@ -27,7 +27,7 @@ void exynos5_restart(char mode, const char *cmd); | |||
27 | void exynos_init_late(void); | 27 | void exynos_init_late(void); |
28 | 28 | ||
29 | /* ToDo: remove these after migrating legacy exynos4 platforms to dt */ | 29 | /* ToDo: remove these after migrating legacy exynos4 platforms to dt */ |
30 | void exynos4_clk_init(struct device_node *np); | 30 | void exynos4_clk_init(struct device_node *np, int is_exynos4210, void __iomem *reg_base, unsigned long xom); |
31 | void exynos4_clk_register_fixed_ext(unsigned long, unsigned long); | 31 | void exynos4_clk_register_fixed_ext(unsigned long, unsigned long); |
32 | 32 | ||
33 | #ifdef CONFIG_PM_GENERIC_DOMAINS | 33 | #ifdef CONFIG_PM_GENERIC_DOMAINS |
@@ -69,7 +69,8 @@ void exynos4212_register_clocks(void); | |||
69 | #endif | 69 | #endif |
70 | 70 | ||
71 | struct device_node; | 71 | struct device_node; |
72 | void combiner_init(void __iomem *combiner_base, struct device_node *np); | 72 | void combiner_init(void __iomem *combiner_base, struct device_node *np, |
73 | unsigned int max_nr, int irq_base); | ||
73 | 74 | ||
74 | extern struct smp_operations exynos_smp_ops; | 75 | extern struct smp_operations exynos_smp_ops; |
75 | 76 | ||
diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c index 71046694d9dd..d0940e69d034 100644 --- a/drivers/clk/samsung/clk-exynos4.c +++ b/drivers/clk/samsung/clk-exynos4.c | |||
@@ -16,7 +16,6 @@ | |||
16 | #include <linux/of.h> | 16 | #include <linux/of.h> |
17 | #include <linux/of_address.h> | 17 | #include <linux/of_address.h> |
18 | 18 | ||
19 | #include <plat/cpu.h> | ||
20 | #include "clk.h" | 19 | #include "clk.h" |
21 | #include "clk-pll.h" | 20 | #include "clk-pll.h" |
22 | 21 | ||
@@ -910,16 +909,6 @@ struct samsung_gate_clock exynos4x12_gate_clks[] __initdata = { | |||
910 | CLK_IGNORE_UNUSED, 0), | 909 | CLK_IGNORE_UNUSED, 0), |
911 | }; | 910 | }; |
912 | 911 | ||
913 | #ifdef CONFIG_OF | ||
914 | static struct of_device_id exynos4_clk_ids[] __initdata = { | ||
915 | { .compatible = "samsung,exynos4210-clock", | ||
916 | .data = (void *)EXYNOS4210, }, | ||
917 | { .compatible = "samsung,exynos4412-clock", | ||
918 | .data = (void *)EXYNOS4X12, }, | ||
919 | { }, | ||
920 | }; | ||
921 | #endif | ||
922 | |||
923 | /* | 912 | /* |
924 | * The parent of the fin_pll clock is selected by the XOM[0] bit. This bit | 913 | * The parent of the fin_pll clock is selected by the XOM[0] bit. This bit |
925 | * resides in chipid register space, outside of the clock controller memory | 914 | * resides in chipid register space, outside of the clock controller memory |
@@ -927,33 +916,40 @@ static struct of_device_id exynos4_clk_ids[] __initdata = { | |||
927 | * controller is first remapped and the value of XOM[0] bit is read to | 916 | * controller is first remapped and the value of XOM[0] bit is read to |
928 | * determine the parent clock. | 917 | * determine the parent clock. |
929 | */ | 918 | */ |
930 | static void __init exynos4_clk_register_finpll(void) | 919 | static unsigned long exynos4_get_xom(void) |
931 | { | 920 | { |
932 | struct samsung_fixed_rate_clock fclk; | 921 | unsigned long xom = 0; |
922 | void __iomem *chipid_base; | ||
933 | struct device_node *np; | 923 | struct device_node *np; |
934 | struct clk *clk; | ||
935 | void __iomem *chipid_base = S5P_VA_CHIPID; | ||
936 | unsigned long xom, finpll_f = 24000000; | ||
937 | char *parent_name; | ||
938 | 924 | ||
939 | np = of_find_compatible_node(NULL, NULL, "samsung,exynos4210-chipid"); | 925 | np = of_find_compatible_node(NULL, NULL, "samsung,exynos4210-chipid"); |
940 | if (np) | 926 | if (np) { |
941 | chipid_base = of_iomap(np, 0); | 927 | chipid_base = of_iomap(np, 0); |
942 | 928 | ||
943 | if (chipid_base) { | 929 | if (chipid_base) |
944 | xom = readl(chipid_base + 8); | 930 | xom = readl(chipid_base + 8); |
945 | parent_name = xom & 1 ? "xusbxti" : "xxti"; | 931 | |
946 | clk = clk_get(NULL, parent_name); | 932 | iounmap(chipid_base); |
947 | if (IS_ERR(clk)) { | 933 | } |
948 | pr_err("%s: failed to lookup parent clock %s, assuming " | 934 | |
949 | "fin_pll clock frequency is 24MHz\n", __func__, | 935 | return xom; |
950 | parent_name); | 936 | } |
951 | } else { | 937 | |
952 | finpll_f = clk_get_rate(clk); | 938 | static void __init exynos4_clk_register_finpll(unsigned long xom) |
953 | } | 939 | { |
940 | struct samsung_fixed_rate_clock fclk; | ||
941 | struct clk *clk; | ||
942 | unsigned long finpll_f = 24000000; | ||
943 | char *parent_name; | ||
944 | |||
945 | parent_name = xom & 1 ? "xusbxti" : "xxti"; | ||
946 | clk = clk_get(NULL, parent_name); | ||
947 | if (IS_ERR(clk)) { | ||
948 | pr_err("%s: failed to lookup parent clock %s, assuming " | ||
949 | "fin_pll clock frequency is 24MHz\n", __func__, | ||
950 | parent_name); | ||
954 | } else { | 951 | } else { |
955 | pr_err("%s: failed to map chipid registers, assuming " | 952 | finpll_f = clk_get_rate(clk); |
956 | "fin_pll clock frequency is 24MHz\n", __func__); | ||
957 | } | 953 | } |
958 | 954 | ||
959 | fclk.id = fin_pll; | 955 | fclk.id = fin_pll; |
@@ -963,8 +959,6 @@ static void __init exynos4_clk_register_finpll(void) | |||
963 | fclk.fixed_rate = finpll_f; | 959 | fclk.fixed_rate = finpll_f; |
964 | samsung_clk_register_fixed_rate(&fclk, 1); | 960 | samsung_clk_register_fixed_rate(&fclk, 1); |
965 | 961 | ||
966 | if (np) | ||
967 | iounmap(chipid_base); | ||
968 | } | 962 | } |
969 | 963 | ||
970 | /* | 964 | /* |
@@ -988,28 +982,14 @@ static __initdata struct of_device_id ext_clk_match[] = { | |||
988 | }; | 982 | }; |
989 | 983 | ||
990 | /* register exynos4 clocks */ | 984 | /* register exynos4 clocks */ |
991 | void __init exynos4_clk_init(struct device_node *np) | 985 | void __init exynos4_clk_init(struct device_node *np, enum exynos4_soc exynos4_soc, void __iomem *reg_base, unsigned long xom) |
992 | { | 986 | { |
993 | void __iomem *reg_base; | ||
994 | struct clk *apll, *mpll, *epll, *vpll; | 987 | struct clk *apll, *mpll, *epll, *vpll; |
995 | u32 exynos4_soc; | ||
996 | 988 | ||
997 | if (np) { | 989 | if (np) { |
998 | const struct of_device_id *match; | ||
999 | match = of_match_node(exynos4_clk_ids, np); | ||
1000 | exynos4_soc = (u32)match->data; | ||
1001 | |||
1002 | reg_base = of_iomap(np, 0); | 990 | reg_base = of_iomap(np, 0); |
1003 | if (!reg_base) | 991 | if (!reg_base) |
1004 | panic("%s: failed to map registers\n", __func__); | 992 | panic("%s: failed to map registers\n", __func__); |
1005 | } else { | ||
1006 | reg_base = S5P_VA_CMU; | ||
1007 | if (soc_is_exynos4210()) | ||
1008 | exynos4_soc = EXYNOS4210; | ||
1009 | else if (soc_is_exynos4212() || soc_is_exynos4412()) | ||
1010 | exynos4_soc = EXYNOS4X12; | ||
1011 | else | ||
1012 | panic("%s: unable to determine soc\n", __func__); | ||
1013 | } | 993 | } |
1014 | 994 | ||
1015 | if (exynos4_soc == EXYNOS4210) | 995 | if (exynos4_soc == EXYNOS4210) |
@@ -1026,7 +1006,7 @@ void __init exynos4_clk_init(struct device_node *np) | |||
1026 | ARRAY_SIZE(exynos4_fixed_rate_ext_clks), | 1006 | ARRAY_SIZE(exynos4_fixed_rate_ext_clks), |
1027 | ext_clk_match); | 1007 | ext_clk_match); |
1028 | 1008 | ||
1029 | exynos4_clk_register_finpll(); | 1009 | exynos4_clk_register_finpll(xom); |
1030 | 1010 | ||
1031 | if (exynos4_soc == EXYNOS4210) { | 1011 | if (exynos4_soc == EXYNOS4210) { |
1032 | apll = samsung_clk_register_pll45xx("fout_apll", "fin_pll", | 1012 | apll = samsung_clk_register_pll45xx("fout_apll", "fin_pll", |
@@ -1087,5 +1067,16 @@ void __init exynos4_clk_init(struct device_node *np) | |||
1087 | _get_rate("sclk_epll"), _get_rate("sclk_vpll"), | 1067 | _get_rate("sclk_epll"), _get_rate("sclk_vpll"), |
1088 | _get_rate("arm_clk")); | 1068 | _get_rate("arm_clk")); |
1089 | } | 1069 | } |
1090 | CLK_OF_DECLARE(exynos4210_clk, "samsung,exynos4210-clock", exynos4_clk_init); | 1070 | |
1091 | CLK_OF_DECLARE(exynos4412_clk, "samsung,exynos4412-clock", exynos4_clk_init); | 1071 | |
1072 | static void __init exynos4210_clk_init(struct device_node *np) | ||
1073 | { | ||
1074 | exynos4_clk_init(np, EXYNOS4210, NULL, exynos4_get_xom()); | ||
1075 | } | ||
1076 | CLK_OF_DECLARE(exynos4210_clk, "samsung,exynos4210-clock", exynos4210_clk_init); | ||
1077 | |||
1078 | static void __init exynos4412_clk_init(struct device_node *np) | ||
1079 | { | ||
1080 | exynos4_clk_init(np, EXYNOS4X12, NULL, exynos4_get_xom()); | ||
1081 | } | ||
1082 | CLK_OF_DECLARE(exynos4412_clk, "samsung,exynos4412-clock", exynos4412_clk_init); | ||
diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c index 7290faa518d2..61068cda2ab3 100644 --- a/drivers/clk/samsung/clk-exynos5250.c +++ b/drivers/clk/samsung/clk-exynos5250.c | |||
@@ -16,7 +16,6 @@ | |||
16 | #include <linux/of.h> | 16 | #include <linux/of.h> |
17 | #include <linux/of_address.h> | 17 | #include <linux/of_address.h> |
18 | 18 | ||
19 | #include <plat/cpu.h> | ||
20 | #include "clk.h" | 19 | #include "clk.h" |
21 | #include "clk-pll.h" | 20 | #include "clk-pll.h" |
22 | 21 | ||
diff --git a/drivers/clk/samsung/clk-exynos5440.c b/drivers/clk/samsung/clk-exynos5440.c index a0a094c06f19..7d5434167a96 100644 --- a/drivers/clk/samsung/clk-exynos5440.c +++ b/drivers/clk/samsung/clk-exynos5440.c | |||
@@ -15,7 +15,6 @@ | |||
15 | #include <linux/of.h> | 15 | #include <linux/of.h> |
16 | #include <linux/of_address.h> | 16 | #include <linux/of_address.h> |
17 | 17 | ||
18 | #include <plat/cpu.h> | ||
19 | #include "clk.h" | 18 | #include "clk.h" |
20 | #include "clk-pll.h" | 19 | #include "clk-pll.h" |
21 | 20 | ||
diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h index 10b2111f0c0f..e4ad6ea9aa76 100644 --- a/drivers/clk/samsung/clk.h +++ b/drivers/clk/samsung/clk.h | |||
@@ -20,8 +20,6 @@ | |||
20 | #include <linux/of.h> | 20 | #include <linux/of.h> |
21 | #include <linux/of_address.h> | 21 | #include <linux/of_address.h> |
22 | 22 | ||
23 | #include <mach/map.h> | ||
24 | |||
25 | /** | 23 | /** |
26 | * struct samsung_clock_alias: information about mux clock | 24 | * struct samsung_clock_alias: information about mux clock |
27 | * @id: platform specific id of the clock. | 25 | * @id: platform specific id of the clock. |
diff --git a/drivers/clocksource/exynos_mct.c b/drivers/clocksource/exynos_mct.c index 661026834b23..a6ca0fb06939 100644 --- a/drivers/clocksource/exynos_mct.c +++ b/drivers/clocksource/exynos_mct.c | |||
@@ -26,11 +26,6 @@ | |||
26 | 26 | ||
27 | #include <asm/arch_timer.h> | 27 | #include <asm/arch_timer.h> |
28 | #include <asm/localtimer.h> | 28 | #include <asm/localtimer.h> |
29 | |||
30 | #include <plat/cpu.h> | ||
31 | |||
32 | #include <mach/map.h> | ||
33 | #include <mach/irqs.h> | ||
34 | #include <asm/mach/time.h> | 29 | #include <asm/mach/time.h> |
35 | 30 | ||
36 | #define EXYNOS4_MCTREG(x) (x) | 31 | #define EXYNOS4_MCTREG(x) (x) |
@@ -511,18 +506,14 @@ static void __init exynos4_timer_resources(struct device_node *np, void __iomem | |||
511 | #endif /* CONFIG_LOCAL_TIMERS */ | 506 | #endif /* CONFIG_LOCAL_TIMERS */ |
512 | } | 507 | } |
513 | 508 | ||
514 | void __init mct_init(void) | 509 | void __init mct_init(void __iomem *base, int irq_g0, int irq_l0, int irq_l1) |
515 | { | 510 | { |
516 | if (soc_is_exynos4210()) { | 511 | mct_irqs[MCT_G0_IRQ] = irq_g0; |
517 | mct_irqs[MCT_G0_IRQ] = EXYNOS4_IRQ_MCT_G0; | 512 | mct_irqs[MCT_L0_IRQ] = irq_l0; |
518 | mct_irqs[MCT_L0_IRQ] = EXYNOS4_IRQ_MCT_L0; | 513 | mct_irqs[MCT_L1_IRQ] = irq_l1; |
519 | mct_irqs[MCT_L1_IRQ] = EXYNOS4_IRQ_MCT_L1; | 514 | mct_int_type = MCT_INT_SPI; |
520 | mct_int_type = MCT_INT_SPI; | ||
521 | } else { | ||
522 | panic("unable to determine mct controller type\n"); | ||
523 | } | ||
524 | 515 | ||
525 | exynos4_timer_resources(NULL, S5P_VA_SYSTIMER); | 516 | exynos4_timer_resources(NULL, base); |
526 | exynos4_clocksource_init(); | 517 | exynos4_clocksource_init(); |
527 | exynos4_clockevent_init(); | 518 | exynos4_clockevent_init(); |
528 | } | 519 | } |
diff --git a/drivers/irqchip/exynos-combiner.c b/drivers/irqchip/exynos-combiner.c index e8501dbaa0b7..494c2e21b538 100644 --- a/drivers/irqchip/exynos-combiner.c +++ b/drivers/irqchip/exynos-combiner.c | |||
@@ -12,12 +12,15 @@ | |||
12 | #include <linux/export.h> | 12 | #include <linux/export.h> |
13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
14 | #include <linux/io.h> | 14 | #include <linux/io.h> |
15 | #include <linux/slab.h> | ||
15 | #include <linux/irqdomain.h> | 16 | #include <linux/irqdomain.h> |
16 | #include <linux/of_address.h> | 17 | #include <linux/of_address.h> |
17 | #include <linux/of_irq.h> | 18 | #include <linux/of_irq.h> |
18 | #include <asm/mach/irq.h> | 19 | #include <asm/mach/irq.h> |
19 | 20 | ||
21 | #ifdef CONFIG_EXYNOS_ATAGS | ||
20 | #include <plat/cpu.h> | 22 | #include <plat/cpu.h> |
23 | #endif | ||
21 | 24 | ||
22 | #include "irqchip.h" | 25 | #include "irqchip.h" |
23 | 26 | ||
@@ -25,17 +28,18 @@ | |||
25 | #define COMBINER_ENABLE_CLEAR 0x4 | 28 | #define COMBINER_ENABLE_CLEAR 0x4 |
26 | #define COMBINER_INT_STATUS 0xC | 29 | #define COMBINER_INT_STATUS 0xC |
27 | 30 | ||
31 | #define IRQ_IN_COMBINER 8 | ||
32 | |||
28 | static DEFINE_SPINLOCK(irq_controller_lock); | 33 | static DEFINE_SPINLOCK(irq_controller_lock); |
29 | 34 | ||
30 | struct combiner_chip_data { | 35 | struct combiner_chip_data { |
31 | unsigned int irq_offset; | 36 | unsigned int hwirq_offset; |
32 | unsigned int irq_mask; | 37 | unsigned int irq_mask; |
33 | void __iomem *base; | 38 | void __iomem *base; |
34 | unsigned int parent_irq; | 39 | unsigned int parent_irq; |
35 | }; | 40 | }; |
36 | 41 | ||
37 | static struct irq_domain *combiner_irq_domain; | 42 | static struct irq_domain *combiner_irq_domain; |
38 | static struct combiner_chip_data combiner_data[MAX_COMBINER_NR]; | ||
39 | 43 | ||
40 | static inline void __iomem *combiner_base(struct irq_data *data) | 44 | static inline void __iomem *combiner_base(struct irq_data *data) |
41 | { | 45 | { |
@@ -76,11 +80,11 @@ static void combiner_handle_cascade_irq(unsigned int irq, struct irq_desc *desc) | |||
76 | if (status == 0) | 80 | if (status == 0) |
77 | goto out; | 81 | goto out; |
78 | 82 | ||
79 | combiner_irq = __ffs(status); | 83 | combiner_irq = chip_data->hwirq_offset + __ffs(status); |
84 | cascade_irq = irq_find_mapping(combiner_irq_domain, combiner_irq); | ||
80 | 85 | ||
81 | cascade_irq = combiner_irq + (chip_data->irq_offset & ~31); | 86 | if (unlikely(!cascade_irq)) |
82 | if (unlikely(cascade_irq >= NR_IRQS)) | 87 | do_bad_IRQ(irq, desc); |
83 | do_bad_IRQ(cascade_irq, desc); | ||
84 | else | 88 | else |
85 | generic_handle_irq(cascade_irq); | 89 | generic_handle_irq(cascade_irq); |
86 | 90 | ||
@@ -112,40 +116,25 @@ static struct irq_chip combiner_chip = { | |||
112 | #endif | 116 | #endif |
113 | }; | 117 | }; |
114 | 118 | ||
115 | static unsigned int max_combiner_nr(void) | 119 | static void __init combiner_cascade_irq(struct combiner_chip_data *combiner_data, |
116 | { | ||
117 | if (soc_is_exynos5250()) | ||
118 | return EXYNOS5_MAX_COMBINER_NR; | ||
119 | else if (soc_is_exynos4412()) | ||
120 | return EXYNOS4412_MAX_COMBINER_NR; | ||
121 | else if (soc_is_exynos4212()) | ||
122 | return EXYNOS4212_MAX_COMBINER_NR; | ||
123 | else | ||
124 | return EXYNOS4210_MAX_COMBINER_NR; | ||
125 | } | ||
126 | |||
127 | static void __init combiner_cascade_irq(unsigned int combiner_nr, | ||
128 | unsigned int irq) | 120 | unsigned int irq) |
129 | { | 121 | { |
130 | if (combiner_nr >= max_combiner_nr()) | 122 | if (irq_set_handler_data(irq, combiner_data) != 0) |
131 | BUG(); | ||
132 | if (irq_set_handler_data(irq, &combiner_data[combiner_nr]) != 0) | ||
133 | BUG(); | 123 | BUG(); |
134 | irq_set_chained_handler(irq, combiner_handle_cascade_irq); | 124 | irq_set_chained_handler(irq, combiner_handle_cascade_irq); |
135 | } | 125 | } |
136 | 126 | ||
137 | static void __init combiner_init_one(unsigned int combiner_nr, | 127 | static void __init combiner_init_one(struct combiner_chip_data *combiner_data, |
128 | unsigned int combiner_nr, | ||
138 | void __iomem *base, unsigned int irq) | 129 | void __iomem *base, unsigned int irq) |
139 | { | 130 | { |
140 | combiner_data[combiner_nr].base = base; | 131 | combiner_data->base = base; |
141 | combiner_data[combiner_nr].irq_offset = irq_find_mapping( | 132 | combiner_data->hwirq_offset = (combiner_nr & ~3) * IRQ_IN_COMBINER; |
142 | combiner_irq_domain, combiner_nr * MAX_IRQ_IN_COMBINER); | 133 | combiner_data->irq_mask = 0xff << ((combiner_nr % 4) << 3); |
143 | combiner_data[combiner_nr].irq_mask = 0xff << ((combiner_nr % 4) << 3); | 134 | combiner_data->parent_irq = irq; |
144 | combiner_data[combiner_nr].parent_irq = irq; | ||
145 | 135 | ||
146 | /* Disable all interrupts */ | 136 | /* Disable all interrupts */ |
147 | __raw_writel(combiner_data[combiner_nr].irq_mask, | 137 | __raw_writel(combiner_data->irq_mask, base + COMBINER_ENABLE_CLEAR); |
148 | base + COMBINER_ENABLE_CLEAR); | ||
149 | } | 138 | } |
150 | 139 | ||
151 | #ifdef CONFIG_OF | 140 | #ifdef CONFIG_OF |
@@ -161,7 +150,7 @@ static int combiner_irq_domain_xlate(struct irq_domain *d, | |||
161 | if (intsize < 2) | 150 | if (intsize < 2) |
162 | return -EINVAL; | 151 | return -EINVAL; |
163 | 152 | ||
164 | *out_hwirq = intspec[0] * MAX_IRQ_IN_COMBINER + intspec[1]; | 153 | *out_hwirq = intspec[0] * IRQ_IN_COMBINER + intspec[1]; |
165 | *out_type = 0; | 154 | *out_type = 0; |
166 | 155 | ||
167 | return 0; | 156 | return 0; |
@@ -180,6 +169,8 @@ static int combiner_irq_domain_xlate(struct irq_domain *d, | |||
180 | static int combiner_irq_domain_map(struct irq_domain *d, unsigned int irq, | 169 | static int combiner_irq_domain_map(struct irq_domain *d, unsigned int irq, |
181 | irq_hw_number_t hw) | 170 | irq_hw_number_t hw) |
182 | { | 171 | { |
172 | struct combiner_chip_data *combiner_data = d->host_data; | ||
173 | |||
183 | irq_set_chip_and_handler(irq, &combiner_chip, handle_level_irq); | 174 | irq_set_chip_and_handler(irq, &combiner_chip, handle_level_irq); |
184 | irq_set_chip_data(irq, &combiner_data[hw >> 3]); | 175 | irq_set_chip_data(irq, &combiner_data[hw >> 3]); |
185 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); | 176 | set_irq_flags(irq, IRQF_VALID | IRQF_PROBE); |
@@ -192,8 +183,12 @@ static struct irq_domain_ops combiner_irq_domain_ops = { | |||
192 | .map = combiner_irq_domain_map, | 183 | .map = combiner_irq_domain_map, |
193 | }; | 184 | }; |
194 | 185 | ||
195 | static unsigned int exynos4x12_combiner_extra_irq(int group) | 186 | static unsigned int combiner_lookup_irq(int group) |
196 | { | 187 | { |
188 | #ifdef CONFIG_EXYNOS_ATAGS | ||
189 | if (group < EXYNOS4210_MAX_COMBINER_NR || soc_is_exynos5250()) | ||
190 | return IRQ_SPI(group); | ||
191 | |||
197 | switch (group) { | 192 | switch (group) { |
198 | case 16: | 193 | case 16: |
199 | return IRQ_SPI(107); | 194 | return IRQ_SPI(107); |
@@ -203,53 +198,46 @@ static unsigned int exynos4x12_combiner_extra_irq(int group) | |||
203 | return IRQ_SPI(48); | 198 | return IRQ_SPI(48); |
204 | case 19: | 199 | case 19: |
205 | return IRQ_SPI(42); | 200 | return IRQ_SPI(42); |
206 | default: | ||
207 | return 0; | ||
208 | } | 201 | } |
202 | #endif | ||
203 | return 0; | ||
209 | } | 204 | } |
210 | 205 | ||
211 | void __init combiner_init(void __iomem *combiner_base, | 206 | void __init combiner_init(void __iomem *combiner_base, |
212 | struct device_node *np) | 207 | struct device_node *np, |
208 | unsigned int max_nr, | ||
209 | int irq_base) | ||
213 | { | 210 | { |
214 | int i, irq, irq_base; | 211 | int i, irq; |
215 | unsigned int max_nr, nr_irq; | 212 | unsigned int nr_irq; |
213 | struct combiner_chip_data *combiner_data; | ||
216 | 214 | ||
217 | max_nr = max_combiner_nr(); | 215 | nr_irq = max_nr * IRQ_IN_COMBINER; |
218 | 216 | ||
219 | if (np) { | 217 | combiner_data = kcalloc(max_nr, sizeof (*combiner_data), GFP_KERNEL); |
220 | if (of_property_read_u32(np, "samsung,combiner-nr", &max_nr)) { | 218 | if (!combiner_data) { |
221 | pr_info("%s: number of combiners not specified, " | 219 | pr_warning("%s: could not allocate combiner data\n", __func__); |
222 | "setting default as %d.\n", | 220 | return; |
223 | __func__, max_nr); | ||
224 | } | ||
225 | } | ||
226 | |||
227 | nr_irq = max_nr * MAX_IRQ_IN_COMBINER; | ||
228 | |||
229 | irq_base = irq_alloc_descs(COMBINER_IRQ(0, 0), 1, nr_irq, 0); | ||
230 | if (IS_ERR_VALUE(irq_base)) { | ||
231 | irq_base = COMBINER_IRQ(0, 0); | ||
232 | pr_warning("%s: irq desc alloc failed. Continuing with %d as linux irq base\n", __func__, irq_base); | ||
233 | } | 221 | } |
234 | 222 | ||
235 | combiner_irq_domain = irq_domain_add_legacy(np, nr_irq, irq_base, 0, | 223 | combiner_irq_domain = irq_domain_add_simple(np, nr_irq, irq_base, |
236 | &combiner_irq_domain_ops, &combiner_data); | 224 | &combiner_irq_domain_ops, combiner_data); |
237 | if (WARN_ON(!combiner_irq_domain)) { | 225 | if (WARN_ON(!combiner_irq_domain)) { |
238 | pr_warning("%s: irq domain init failed\n", __func__); | 226 | pr_warning("%s: irq domain init failed\n", __func__); |
239 | return; | 227 | return; |
240 | } | 228 | } |
241 | 229 | ||
242 | for (i = 0; i < max_nr; i++) { | 230 | for (i = 0; i < max_nr; i++) { |
243 | if (i < EXYNOS4210_MAX_COMBINER_NR || soc_is_exynos5250()) | ||
244 | irq = IRQ_SPI(i); | ||
245 | else | ||
246 | irq = exynos4x12_combiner_extra_irq(i); | ||
247 | #ifdef CONFIG_OF | 231 | #ifdef CONFIG_OF |
248 | if (np) | 232 | if (np) |
249 | irq = irq_of_parse_and_map(np, i); | 233 | irq = irq_of_parse_and_map(np, i); |
234 | else | ||
250 | #endif | 235 | #endif |
251 | combiner_init_one(i, combiner_base + (i >> 2) * 0x10, irq); | 236 | irq = combiner_lookup_irq(i); |
252 | combiner_cascade_irq(i, irq); | 237 | |
238 | combiner_init_one(&combiner_data[i], i, | ||
239 | combiner_base + (i >> 2) * 0x10, irq); | ||
240 | combiner_cascade_irq(&combiner_data[i], irq); | ||
253 | } | 241 | } |
254 | } | 242 | } |
255 | 243 | ||
@@ -258,6 +246,8 @@ static int __init combiner_of_init(struct device_node *np, | |||
258 | struct device_node *parent) | 246 | struct device_node *parent) |
259 | { | 247 | { |
260 | void __iomem *combiner_base; | 248 | void __iomem *combiner_base; |
249 | unsigned int max_nr = 20; | ||
250 | int irq_base = -1; | ||
261 | 251 | ||
262 | combiner_base = of_iomap(np, 0); | 252 | combiner_base = of_iomap(np, 0); |
263 | if (!combiner_base) { | 253 | if (!combiner_base) { |
@@ -265,7 +255,20 @@ static int __init combiner_of_init(struct device_node *np, | |||
265 | return -ENXIO; | 255 | return -ENXIO; |
266 | } | 256 | } |
267 | 257 | ||
268 | combiner_init(combiner_base, np); | 258 | if (of_property_read_u32(np, "samsung,combiner-nr", &max_nr)) { |
259 | pr_info("%s: number of combiners not specified, " | ||
260 | "setting default as %d.\n", | ||
261 | __func__, max_nr); | ||
262 | } | ||
263 | |||
264 | /* | ||
265 | * FIXME: This is a hardwired COMBINER_IRQ(0,0). Once all devices | ||
266 | * get their IRQ from DT, remove this in order to get dynamic | ||
267 | * allocation. | ||
268 | */ | ||
269 | irq_base = 160; | ||
270 | |||
271 | combiner_init(combiner_base, np, max_nr, irq_base); | ||
269 | 272 | ||
270 | return 0; | 273 | return 0; |
271 | } | 274 | } |