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 | } |
