aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/boot/dts/exynos4210.dtsi6
-rw-r--r--arch/arm/boot/dts/exynos5250.dtsi6
-rw-r--r--arch/arm/mach-exynos/common.c28
-rw-r--r--arch/arm/mach-exynos/include/mach/irqs.h13
-rw-r--r--arch/arm/plat-samsung/devs.c2
-rw-r--r--drivers/irqchip/exynos-combiner.c80
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}
853arch_initcall(exynos_init_irq_eint); 854arch_initcall(exynos_init_irq_eint);
855
856static 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
865static 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
871static 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}
881arch_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)
1117static struct resource s5p_pmu_resource[] = { 1117static 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
36static struct irq_domain *combiner_irq_domain; 37static 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
92static 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
90static struct irq_chip combiner_chip = { 106static 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
96static void __init combiner_cascade_irq(unsigned int combiner_nr, unsigned int irq) 115static 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) 127static 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
112static void __init combiner_init_one(unsigned int combiner_nr, 137static 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
195static 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
169void __init combiner_init(void __iomem *combiner_base, 211void __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}