diff options
-rw-r--r-- | arch/arm/boot/dts/exynos4210.dtsi | 6 | ||||
-rw-r--r-- | arch/arm/boot/dts/exynos5250.dtsi | 6 | ||||
-rw-r--r-- | arch/arm/mach-exynos/common.c | 28 | ||||
-rw-r--r-- | arch/arm/mach-exynos/include/mach/irqs.h | 13 | ||||
-rw-r--r-- | arch/arm/plat-samsung/devs.c | 2 | ||||
-rw-r--r-- | drivers/irqchip/exynos-combiner.c | 80 |
6 files changed, 113 insertions, 22 deletions
diff --git a/arch/arm/boot/dts/exynos4210.dtsi b/arch/arm/boot/dts/exynos4210.dtsi index ff23ae29f5cf..15143bdbafb8 100644 --- a/arch/arm/boot/dts/exynos4210.dtsi +++ b/arch/arm/boot/dts/exynos4210.dtsi | |||
@@ -77,6 +77,12 @@ | |||
77 | #clock-cells = <1>; | 77 | #clock-cells = <1>; |
78 | }; | 78 | }; |
79 | 79 | ||
80 | pmu { | ||
81 | compatible = "arm,cortex-a9-pmu"; | ||
82 | interrupt-parent = <&combiner>; | ||
83 | interrupts = <2 2>, <3 2>; | ||
84 | }; | ||
85 | |||
80 | pinctrl_0: pinctrl@11400000 { | 86 | pinctrl_0: pinctrl@11400000 { |
81 | compatible = "samsung,exynos4210-pinctrl"; | 87 | compatible = "samsung,exynos4210-pinctrl"; |
82 | reg = <0x11400000 0x1000>; | 88 | reg = <0x11400000 0x1000>; |
diff --git a/arch/arm/boot/dts/exynos5250.dtsi b/arch/arm/boot/dts/exynos5250.dtsi index f8c9964f367c..24c52e681b58 100644 --- a/arch/arm/boot/dts/exynos5250.dtsi +++ b/arch/arm/boot/dts/exynos5250.dtsi | |||
@@ -109,6 +109,12 @@ | |||
109 | }; | 109 | }; |
110 | }; | 110 | }; |
111 | 111 | ||
112 | pmu { | ||
113 | compatible = "arm,cortex-a15-pmu"; | ||
114 | interrupt-parent = <&combiner>; | ||
115 | interrupts = <1 2>, <22 4>; | ||
116 | }; | ||
117 | |||
112 | watchdog { | 118 | watchdog { |
113 | compatible = "samsung,s3c2410-wdt"; | 119 | compatible = "samsung,s3c2410-wdt"; |
114 | reg = <0x101D0000 0x100>; | 120 | reg = <0x101D0000 0x100>; |
diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c index d3efd6768ff8..939bda77defa 100644 --- a/arch/arm/mach-exynos/common.c +++ b/arch/arm/mach-exynos/common.c | |||
@@ -39,6 +39,7 @@ | |||
39 | #include <mach/regs-irq.h> | 39 | #include <mach/regs-irq.h> |
40 | #include <mach/regs-pmu.h> | 40 | #include <mach/regs-pmu.h> |
41 | #include <mach/regs-gpio.h> | 41 | #include <mach/regs-gpio.h> |
42 | #include <mach/irqs.h> | ||
42 | 43 | ||
43 | #include <plat/cpu.h> | 44 | #include <plat/cpu.h> |
44 | #include <plat/devs.h> | 45 | #include <plat/devs.h> |
@@ -851,3 +852,30 @@ static int __init exynos_init_irq_eint(void) | |||
851 | return 0; | 852 | return 0; |
852 | } | 853 | } |
853 | arch_initcall(exynos_init_irq_eint); | 854 | arch_initcall(exynos_init_irq_eint); |
855 | |||
856 | static struct resource exynos4_pmu_resource[] = { | ||
857 | DEFINE_RES_IRQ(EXYNOS4_IRQ_PMU), | ||
858 | DEFINE_RES_IRQ(EXYNOS4_IRQ_PMU_CPU1), | ||
859 | #if defined(CONFIG_SOC_EXYNOS4412) | ||
860 | DEFINE_RES_IRQ(EXYNOS4_IRQ_PMU_CPU2), | ||
861 | DEFINE_RES_IRQ(EXYNOS4_IRQ_PMU_CPU3), | ||
862 | #endif | ||
863 | }; | ||
864 | |||
865 | static struct platform_device exynos4_device_pmu = { | ||
866 | .name = "arm-pmu", | ||
867 | .num_resources = ARRAY_SIZE(exynos4_pmu_resource), | ||
868 | .resource = exynos4_pmu_resource, | ||
869 | }; | ||
870 | |||
871 | static int __init exynos_armpmu_init(void) | ||
872 | { | ||
873 | if (!of_have_populated_dt()) { | ||
874 | if (soc_is_exynos4210() || soc_is_exynos4212()) | ||
875 | exynos4_device_pmu.num_resources = 2; | ||
876 | platform_device_register(&exynos4_device_pmu); | ||
877 | } | ||
878 | |||
879 | return 0; | ||
880 | } | ||
881 | arch_initcall(exynos_armpmu_init); | ||
diff --git a/arch/arm/mach-exynos/include/mach/irqs.h b/arch/arm/mach-exynos/include/mach/irqs.h index c0e75d8dd737..35fe6d52d230 100644 --- a/arch/arm/mach-exynos/include/mach/irqs.h +++ b/arch/arm/mach-exynos/include/mach/irqs.h | |||
@@ -126,7 +126,7 @@ | |||
126 | #define EXYNOS4_IRQ_ADC1 IRQ_SPI(107) | 126 | #define EXYNOS4_IRQ_ADC1 IRQ_SPI(107) |
127 | #define EXYNOS4_IRQ_PEN1 IRQ_SPI(108) | 127 | #define EXYNOS4_IRQ_PEN1 IRQ_SPI(108) |
128 | #define EXYNOS4_IRQ_KEYPAD IRQ_SPI(109) | 128 | #define EXYNOS4_IRQ_KEYPAD IRQ_SPI(109) |
129 | #define EXYNOS4_IRQ_PMU IRQ_SPI(110) | 129 | #define EXYNOS4_IRQ_POWER_PMU IRQ_SPI(110) |
130 | #define EXYNOS4_IRQ_GPS IRQ_SPI(111) | 130 | #define EXYNOS4_IRQ_GPS IRQ_SPI(111) |
131 | #define EXYNOS4_IRQ_INTFEEDCTRL_SSS IRQ_SPI(112) | 131 | #define EXYNOS4_IRQ_INTFEEDCTRL_SSS IRQ_SPI(112) |
132 | #define EXYNOS4_IRQ_SLIMBUS IRQ_SPI(113) | 132 | #define EXYNOS4_IRQ_SLIMBUS IRQ_SPI(113) |
@@ -134,6 +134,11 @@ | |||
134 | #define EXYNOS4_IRQ_TSI IRQ_SPI(115) | 134 | #define EXYNOS4_IRQ_TSI IRQ_SPI(115) |
135 | #define EXYNOS4_IRQ_SATA IRQ_SPI(116) | 135 | #define EXYNOS4_IRQ_SATA IRQ_SPI(116) |
136 | 136 | ||
137 | #define EXYNOS4_IRQ_PMU COMBINER_IRQ(2, 2) | ||
138 | #define EXYNOS4_IRQ_PMU_CPU1 COMBINER_IRQ(3, 2) | ||
139 | #define EXYNOS4_IRQ_PMU_CPU2 COMBINER_IRQ(18, 2) | ||
140 | #define EXYNOS4_IRQ_PMU_CPU3 COMBINER_IRQ(19, 2) | ||
141 | |||
137 | #define EXYNOS4_IRQ_TMU_TRIG0 COMBINER_IRQ(2, 4) | 142 | #define EXYNOS4_IRQ_TMU_TRIG0 COMBINER_IRQ(2, 4) |
138 | #define EXYNOS4_IRQ_TMU_TRIG1 COMBINER_IRQ(3, 4) | 143 | #define EXYNOS4_IRQ_TMU_TRIG1 COMBINER_IRQ(3, 4) |
139 | 144 | ||
@@ -166,7 +171,10 @@ | |||
166 | #define EXYNOS4_IRQ_FIMD0_VSYNC COMBINER_IRQ(11, 1) | 171 | #define EXYNOS4_IRQ_FIMD0_VSYNC COMBINER_IRQ(11, 1) |
167 | #define EXYNOS4_IRQ_FIMD0_SYSTEM COMBINER_IRQ(11, 2) | 172 | #define EXYNOS4_IRQ_FIMD0_SYSTEM COMBINER_IRQ(11, 2) |
168 | 173 | ||
169 | #define EXYNOS4_MAX_COMBINER_NR 16 | 174 | #define EXYNOS4210_MAX_COMBINER_NR 16 |
175 | #define EXYNOS4212_MAX_COMBINER_NR 18 | ||
176 | #define EXYNOS4412_MAX_COMBINER_NR 20 | ||
177 | #define EXYNOS4_MAX_COMBINER_NR EXYNOS4412_MAX_COMBINER_NR | ||
170 | 178 | ||
171 | #define EXYNOS4_IRQ_GPIO1_NR_GROUPS 16 | 179 | #define EXYNOS4_IRQ_GPIO1_NR_GROUPS 16 |
172 | #define EXYNOS4_IRQ_GPIO2_NR_GROUPS 9 | 180 | #define EXYNOS4_IRQ_GPIO2_NR_GROUPS 9 |
@@ -231,7 +239,6 @@ | |||
231 | #define IRQ_TC EXYNOS4_IRQ_PEN0 | 239 | #define IRQ_TC EXYNOS4_IRQ_PEN0 |
232 | 240 | ||
233 | #define IRQ_KEYPAD EXYNOS4_IRQ_KEYPAD | 241 | #define IRQ_KEYPAD EXYNOS4_IRQ_KEYPAD |
234 | #define IRQ_PMU EXYNOS4_IRQ_PMU | ||
235 | 242 | ||
236 | #define IRQ_FIMD0_FIFO EXYNOS4_IRQ_FIMD0_FIFO | 243 | #define IRQ_FIMD0_FIFO EXYNOS4_IRQ_FIMD0_FIFO |
237 | #define IRQ_FIMD0_VSYNC EXYNOS4_IRQ_FIMD0_VSYNC | 244 | #define IRQ_FIMD0_VSYNC EXYNOS4_IRQ_FIMD0_VSYNC |
diff --git a/arch/arm/plat-samsung/devs.c b/arch/arm/plat-samsung/devs.c index 51afedda9ab6..e1124d9fd2b0 100644 --- a/arch/arm/plat-samsung/devs.c +++ b/arch/arm/plat-samsung/devs.c | |||
@@ -1113,7 +1113,7 @@ struct platform_device s5p_device_onenand = { | |||
1113 | 1113 | ||
1114 | /* PMU */ | 1114 | /* PMU */ |
1115 | 1115 | ||
1116 | #ifdef CONFIG_PLAT_S5P | 1116 | #if defined(CONFIG_PLAT_S5P) && !defined(CONFIG_ARCH_EXYNOS) |
1117 | static struct resource s5p_pmu_resource[] = { | 1117 | static struct resource s5p_pmu_resource[] = { |
1118 | DEFINE_RES_IRQ(IRQ_PMU) | 1118 | DEFINE_RES_IRQ(IRQ_PMU) |
1119 | }; | 1119 | }; |
diff --git a/drivers/irqchip/exynos-combiner.c b/drivers/irqchip/exynos-combiner.c index 04d86a9803f4..e8501dbaa0b7 100644 --- a/drivers/irqchip/exynos-combiner.c +++ b/drivers/irqchip/exynos-combiner.c | |||
@@ -31,6 +31,7 @@ struct combiner_chip_data { | |||
31 | unsigned int irq_offset; | 31 | unsigned int irq_offset; |
32 | unsigned int irq_mask; | 32 | unsigned int irq_mask; |
33 | void __iomem *base; | 33 | void __iomem *base; |
34 | unsigned int parent_irq; | ||
34 | }; | 35 | }; |
35 | 36 | ||
36 | static struct irq_domain *combiner_irq_domain; | 37 | static struct irq_domain *combiner_irq_domain; |
@@ -87,22 +88,46 @@ static void combiner_handle_cascade_irq(unsigned int irq, struct irq_desc *desc) | |||
87 | chained_irq_exit(chip, desc); | 88 | chained_irq_exit(chip, desc); |
88 | } | 89 | } |
89 | 90 | ||
91 | #ifdef CONFIG_SMP | ||
92 | static int combiner_set_affinity(struct irq_data *d, | ||
93 | const struct cpumask *mask_val, bool force) | ||
94 | { | ||
95 | struct combiner_chip_data *chip_data = irq_data_get_irq_chip_data(d); | ||
96 | struct irq_chip *chip = irq_get_chip(chip_data->parent_irq); | ||
97 | struct irq_data *data = irq_get_irq_data(chip_data->parent_irq); | ||
98 | |||
99 | if (chip && chip->irq_set_affinity) | ||
100 | return chip->irq_set_affinity(data, mask_val, force); | ||
101 | else | ||
102 | return -EINVAL; | ||
103 | } | ||
104 | #endif | ||
105 | |||
90 | static struct irq_chip combiner_chip = { | 106 | static struct irq_chip combiner_chip = { |
91 | .name = "COMBINER", | 107 | .name = "COMBINER", |
92 | .irq_mask = combiner_mask_irq, | 108 | .irq_mask = combiner_mask_irq, |
93 | .irq_unmask = combiner_unmask_irq, | 109 | .irq_unmask = combiner_unmask_irq, |
110 | #ifdef CONFIG_SMP | ||
111 | .irq_set_affinity = combiner_set_affinity, | ||
112 | #endif | ||
94 | }; | 113 | }; |
95 | 114 | ||
96 | static void __init combiner_cascade_irq(unsigned int combiner_nr, unsigned int irq) | 115 | static unsigned int max_combiner_nr(void) |
97 | { | 116 | { |
98 | unsigned int max_nr; | ||
99 | |||
100 | if (soc_is_exynos5250()) | 117 | if (soc_is_exynos5250()) |
101 | max_nr = EXYNOS5_MAX_COMBINER_NR; | 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; | ||
102 | else | 123 | else |
103 | max_nr = EXYNOS4_MAX_COMBINER_NR; | 124 | return EXYNOS4210_MAX_COMBINER_NR; |
125 | } | ||
104 | 126 | ||
105 | if (combiner_nr >= max_nr) | 127 | static void __init combiner_cascade_irq(unsigned int combiner_nr, |
128 | unsigned int irq) | ||
129 | { | ||
130 | if (combiner_nr >= max_combiner_nr()) | ||
106 | BUG(); | 131 | BUG(); |
107 | if (irq_set_handler_data(irq, &combiner_data[combiner_nr]) != 0) | 132 | if (irq_set_handler_data(irq, &combiner_data[combiner_nr]) != 0) |
108 | BUG(); | 133 | BUG(); |
@@ -110,12 +135,13 @@ static void __init combiner_cascade_irq(unsigned int combiner_nr, unsigned int i | |||
110 | } | 135 | } |
111 | 136 | ||
112 | static void __init combiner_init_one(unsigned int combiner_nr, | 137 | static void __init combiner_init_one(unsigned int combiner_nr, |
113 | void __iomem *base) | 138 | void __iomem *base, unsigned int irq) |
114 | { | 139 | { |
115 | combiner_data[combiner_nr].base = base; | 140 | combiner_data[combiner_nr].base = base; |
116 | combiner_data[combiner_nr].irq_offset = irq_find_mapping( | 141 | combiner_data[combiner_nr].irq_offset = irq_find_mapping( |
117 | combiner_irq_domain, combiner_nr * MAX_IRQ_IN_COMBINER); | 142 | combiner_irq_domain, combiner_nr * MAX_IRQ_IN_COMBINER); |
118 | combiner_data[combiner_nr].irq_mask = 0xff << ((combiner_nr % 4) << 3); | 143 | combiner_data[combiner_nr].irq_mask = 0xff << ((combiner_nr % 4) << 3); |
144 | combiner_data[combiner_nr].parent_irq = irq; | ||
119 | 145 | ||
120 | /* Disable all interrupts */ | 146 | /* Disable all interrupts */ |
121 | __raw_writel(combiner_data[combiner_nr].irq_mask, | 147 | __raw_writel(combiner_data[combiner_nr].irq_mask, |
@@ -166,23 +192,38 @@ static struct irq_domain_ops combiner_irq_domain_ops = { | |||
166 | .map = combiner_irq_domain_map, | 192 | .map = combiner_irq_domain_map, |
167 | }; | 193 | }; |
168 | 194 | ||
195 | static unsigned int exynos4x12_combiner_extra_irq(int group) | ||
196 | { | ||
197 | switch (group) { | ||
198 | case 16: | ||
199 | return IRQ_SPI(107); | ||
200 | case 17: | ||
201 | return IRQ_SPI(108); | ||
202 | case 18: | ||
203 | return IRQ_SPI(48); | ||
204 | case 19: | ||
205 | return IRQ_SPI(42); | ||
206 | default: | ||
207 | return 0; | ||
208 | } | ||
209 | } | ||
210 | |||
169 | void __init combiner_init(void __iomem *combiner_base, | 211 | void __init combiner_init(void __iomem *combiner_base, |
170 | struct device_node *np) | 212 | struct device_node *np) |
171 | { | 213 | { |
172 | int i, irq, irq_base; | 214 | int i, irq, irq_base; |
173 | unsigned int max_nr, nr_irq; | 215 | unsigned int max_nr, nr_irq; |
174 | 216 | ||
217 | max_nr = max_combiner_nr(); | ||
218 | |||
175 | if (np) { | 219 | if (np) { |
176 | if (of_property_read_u32(np, "samsung,combiner-nr", &max_nr)) { | 220 | if (of_property_read_u32(np, "samsung,combiner-nr", &max_nr)) { |
177 | pr_warning("%s: number of combiners not specified, " | 221 | pr_info("%s: number of combiners not specified, " |
178 | "setting default as %d.\n", | 222 | "setting default as %d.\n", |
179 | __func__, EXYNOS4_MAX_COMBINER_NR); | 223 | __func__, max_nr); |
180 | max_nr = EXYNOS4_MAX_COMBINER_NR; | ||
181 | } | 224 | } |
182 | } else { | ||
183 | max_nr = soc_is_exynos5250() ? EXYNOS5_MAX_COMBINER_NR : | ||
184 | EXYNOS4_MAX_COMBINER_NR; | ||
185 | } | 225 | } |
226 | |||
186 | nr_irq = max_nr * MAX_IRQ_IN_COMBINER; | 227 | nr_irq = max_nr * MAX_IRQ_IN_COMBINER; |
187 | 228 | ||
188 | irq_base = irq_alloc_descs(COMBINER_IRQ(0, 0), 1, nr_irq, 0); | 229 | irq_base = irq_alloc_descs(COMBINER_IRQ(0, 0), 1, nr_irq, 0); |
@@ -199,12 +240,15 @@ void __init combiner_init(void __iomem *combiner_base, | |||
199 | } | 240 | } |
200 | 241 | ||
201 | for (i = 0; i < max_nr; i++) { | 242 | for (i = 0; i < max_nr; i++) { |
202 | combiner_init_one(i, combiner_base + (i >> 2) * 0x10); | 243 | if (i < EXYNOS4210_MAX_COMBINER_NR || soc_is_exynos5250()) |
203 | irq = IRQ_SPI(i); | 244 | irq = IRQ_SPI(i); |
245 | else | ||
246 | irq = exynos4x12_combiner_extra_irq(i); | ||
204 | #ifdef CONFIG_OF | 247 | #ifdef CONFIG_OF |
205 | if (np) | 248 | if (np) |
206 | irq = irq_of_parse_and_map(np, i); | 249 | irq = irq_of_parse_and_map(np, i); |
207 | #endif | 250 | #endif |
251 | combiner_init_one(i, combiner_base + (i >> 2) * 0x10, irq); | ||
208 | combiner_cascade_irq(i, irq); | 252 | combiner_cascade_irq(i, irq); |
209 | } | 253 | } |
210 | } | 254 | } |