Commit ad3b8a83933e83e5a2a08956211343bda269e778
Committed by
Olof Johansson
1 parent
1fb372f88e
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
ARM: PRIMA2: fix irq domain size and IRQ mask of internal interrupt controller
the old codes will cause 3.4 kernel warning as irq domain size is wrong: ------------[ cut here ]------------ WARNING: at kernel/irq/irqdomain.c:74 irq_domain_legacy_revmap+0x24/0x48() Modules linked in: [<c0013f50>] (unwind_backtrace+0x0/0xf8) from [<c001e7d8>] (warn_slowpath_common+0x54/0x64) [<c001e7d8>] (warn_slowpath_common+0x54/0x64) from [<c001e804>] (warn_slowpath_null+0x1c/0x24) [<c001e804>] (warn_slowpath_null+0x1c/0x24) from [<c005c3c4>] (irq_domain_legacy_revmap+0x24/0x48) [<c005c3c4>] (irq_domain_legacy_revmap+0x24/0x48) from [<c005c704>] (irq_create_mapping+0x20/0x120) [<c005c704>] (irq_create_mapping+0x20/0x120) from [<c005c880>] (irq_create_of_mapping+0x7c/0xf0) [<c005c880>] (irq_create_of_mapping+0x7c/0xf0) from [<c01a6c48>] (irq_of_parse_and_map+0x2c/0x34) [<c01a6c48>] (irq_of_parse_and_map+0x2c/0x34) from [<c01a6c68>] (of_irq_to_resource+0x18/0x74) [<c01a6c68>] (of_irq_to_resource+0x18/0x74) from [<c01a6ce8>] (of_irq_count+0x24/0x34) [<c01a6ce8>] (of_irq_count+0x24/0x34) from [<c01a7220>] (of_device_alloc+0x58/0x158) [<c01a7220>] (of_device_alloc+0x58/0x158) from [<c01a735c>] (of_platform_device_create_pdata+0x3c/0x80) [<c01a735c>] (of_platform_device_create_pdata+0x3c/0x80) from [<c01a7468>] (of_platform_bus_create+0xc8/0x190) [<c01a7468>] (of_platform_bus_create+0xc8/0x190) from [<c01a74cc>] (of_platform_bus_create+0x12c/0x190) ---[ end trace 1b75b31a2719ed32 ]--- Signed-off-by: Barry Song <Baohua.Song@csr.com> Signed-off-by: Olof Johansson <olof@lixom.net>
Showing 1 changed file with 4 additions and 2 deletions Inline Diff
arch/arm/mach-prima2/irq.c
1 | /* | 1 | /* |
2 | * interrupt controller support for CSR SiRFprimaII | 2 | * interrupt controller support for CSR SiRFprimaII |
3 | * | 3 | * |
4 | * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. | 4 | * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. |
5 | * | 5 | * |
6 | * Licensed under GPLv2 or later. | 6 | * Licensed under GPLv2 or later. |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/init.h> | 9 | #include <linux/init.h> |
10 | #include <linux/io.h> | 10 | #include <linux/io.h> |
11 | #include <linux/irq.h> | 11 | #include <linux/irq.h> |
12 | #include <mach/hardware.h> | 12 | #include <mach/hardware.h> |
13 | #include <asm/mach/irq.h> | 13 | #include <asm/mach/irq.h> |
14 | #include <linux/of.h> | 14 | #include <linux/of.h> |
15 | #include <linux/of_address.h> | 15 | #include <linux/of_address.h> |
16 | #include <linux/irqdomain.h> | 16 | #include <linux/irqdomain.h> |
17 | #include <linux/syscore_ops.h> | 17 | #include <linux/syscore_ops.h> |
18 | 18 | ||
19 | #define SIRFSOC_INT_RISC_MASK0 0x0018 | 19 | #define SIRFSOC_INT_RISC_MASK0 0x0018 |
20 | #define SIRFSOC_INT_RISC_MASK1 0x001C | 20 | #define SIRFSOC_INT_RISC_MASK1 0x001C |
21 | #define SIRFSOC_INT_RISC_LEVEL0 0x0020 | 21 | #define SIRFSOC_INT_RISC_LEVEL0 0x0020 |
22 | #define SIRFSOC_INT_RISC_LEVEL1 0x0024 | 22 | #define SIRFSOC_INT_RISC_LEVEL1 0x0024 |
23 | 23 | ||
24 | void __iomem *sirfsoc_intc_base; | 24 | void __iomem *sirfsoc_intc_base; |
25 | 25 | ||
26 | static __init void | 26 | static __init void |
27 | sirfsoc_alloc_gc(void __iomem *base, unsigned int irq_start, unsigned int num) | 27 | sirfsoc_alloc_gc(void __iomem *base, unsigned int irq_start, unsigned int num) |
28 | { | 28 | { |
29 | struct irq_chip_generic *gc; | 29 | struct irq_chip_generic *gc; |
30 | struct irq_chip_type *ct; | 30 | struct irq_chip_type *ct; |
31 | 31 | ||
32 | gc = irq_alloc_generic_chip("SIRFINTC", 1, irq_start, base, handle_level_irq); | 32 | gc = irq_alloc_generic_chip("SIRFINTC", 1, irq_start, base, handle_level_irq); |
33 | ct = gc->chip_types; | 33 | ct = gc->chip_types; |
34 | 34 | ||
35 | ct->chip.irq_mask = irq_gc_mask_clr_bit; | 35 | ct->chip.irq_mask = irq_gc_mask_clr_bit; |
36 | ct->chip.irq_unmask = irq_gc_mask_set_bit; | 36 | ct->chip.irq_unmask = irq_gc_mask_set_bit; |
37 | ct->regs.mask = SIRFSOC_INT_RISC_MASK0; | 37 | ct->regs.mask = SIRFSOC_INT_RISC_MASK0; |
38 | 38 | ||
39 | irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE, IRQ_NOREQUEST, 0); | 39 | irq_setup_generic_chip(gc, IRQ_MSK(num), IRQ_GC_INIT_MASK_CACHE, IRQ_NOREQUEST, 0); |
40 | } | 40 | } |
41 | 41 | ||
42 | static __init void sirfsoc_irq_init(void) | 42 | static __init void sirfsoc_irq_init(void) |
43 | { | 43 | { |
44 | sirfsoc_alloc_gc(sirfsoc_intc_base, 0, 32); | 44 | sirfsoc_alloc_gc(sirfsoc_intc_base, 0, 32); |
45 | sirfsoc_alloc_gc(sirfsoc_intc_base + 4, 32, SIRFSOC_INTENAL_IRQ_END - 32); | 45 | sirfsoc_alloc_gc(sirfsoc_intc_base + 4, 32, |
46 | SIRFSOC_INTENAL_IRQ_END + 1 - 32); | ||
46 | 47 | ||
47 | writel_relaxed(0, sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL0); | 48 | writel_relaxed(0, sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL0); |
48 | writel_relaxed(0, sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL1); | 49 | writel_relaxed(0, sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL1); |
49 | 50 | ||
50 | writel_relaxed(0, sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK0); | 51 | writel_relaxed(0, sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK0); |
51 | writel_relaxed(0, sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK1); | 52 | writel_relaxed(0, sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK1); |
52 | } | 53 | } |
53 | 54 | ||
54 | static struct of_device_id intc_ids[] = { | 55 | static struct of_device_id intc_ids[] = { |
55 | { .compatible = "sirf,prima2-intc" }, | 56 | { .compatible = "sirf,prima2-intc" }, |
56 | {}, | 57 | {}, |
57 | }; | 58 | }; |
58 | 59 | ||
59 | void __init sirfsoc_of_irq_init(void) | 60 | void __init sirfsoc_of_irq_init(void) |
60 | { | 61 | { |
61 | struct device_node *np; | 62 | struct device_node *np; |
62 | 63 | ||
63 | np = of_find_matching_node(NULL, intc_ids); | 64 | np = of_find_matching_node(NULL, intc_ids); |
64 | if (!np) | 65 | if (!np) |
65 | panic("unable to find compatible intc node in dtb\n"); | 66 | panic("unable to find compatible intc node in dtb\n"); |
66 | 67 | ||
67 | sirfsoc_intc_base = of_iomap(np, 0); | 68 | sirfsoc_intc_base = of_iomap(np, 0); |
68 | if (!sirfsoc_intc_base) | 69 | if (!sirfsoc_intc_base) |
69 | panic("unable to map intc cpu registers\n"); | 70 | panic("unable to map intc cpu registers\n"); |
70 | 71 | ||
71 | irq_domain_add_legacy(np, 32, 0, 0, &irq_domain_simple_ops, NULL); | 72 | irq_domain_add_legacy(np, SIRFSOC_INTENAL_IRQ_END + 1, 0, 0, |
73 | &irq_domain_simple_ops, NULL); | ||
72 | 74 | ||
73 | of_node_put(np); | 75 | of_node_put(np); |
74 | 76 | ||
75 | sirfsoc_irq_init(); | 77 | sirfsoc_irq_init(); |
76 | } | 78 | } |
77 | 79 | ||
78 | struct sirfsoc_irq_status { | 80 | struct sirfsoc_irq_status { |
79 | u32 mask0; | 81 | u32 mask0; |
80 | u32 mask1; | 82 | u32 mask1; |
81 | u32 level0; | 83 | u32 level0; |
82 | u32 level1; | 84 | u32 level1; |
83 | }; | 85 | }; |
84 | 86 | ||
85 | static struct sirfsoc_irq_status sirfsoc_irq_st; | 87 | static struct sirfsoc_irq_status sirfsoc_irq_st; |
86 | 88 | ||
87 | static int sirfsoc_irq_suspend(void) | 89 | static int sirfsoc_irq_suspend(void) |
88 | { | 90 | { |
89 | sirfsoc_irq_st.mask0 = readl_relaxed(sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK0); | 91 | sirfsoc_irq_st.mask0 = readl_relaxed(sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK0); |
90 | sirfsoc_irq_st.mask1 = readl_relaxed(sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK1); | 92 | sirfsoc_irq_st.mask1 = readl_relaxed(sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK1); |
91 | sirfsoc_irq_st.level0 = readl_relaxed(sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL0); | 93 | sirfsoc_irq_st.level0 = readl_relaxed(sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL0); |
92 | sirfsoc_irq_st.level1 = readl_relaxed(sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL1); | 94 | sirfsoc_irq_st.level1 = readl_relaxed(sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL1); |
93 | 95 | ||
94 | return 0; | 96 | return 0; |
95 | } | 97 | } |
96 | 98 | ||
97 | static void sirfsoc_irq_resume(void) | 99 | static void sirfsoc_irq_resume(void) |
98 | { | 100 | { |
99 | writel_relaxed(sirfsoc_irq_st.mask0, sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK0); | 101 | writel_relaxed(sirfsoc_irq_st.mask0, sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK0); |
100 | writel_relaxed(sirfsoc_irq_st.mask1, sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK1); | 102 | writel_relaxed(sirfsoc_irq_st.mask1, sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK1); |
101 | writel_relaxed(sirfsoc_irq_st.level0, sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL0); | 103 | writel_relaxed(sirfsoc_irq_st.level0, sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL0); |
102 | writel_relaxed(sirfsoc_irq_st.level1, sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL1); | 104 | writel_relaxed(sirfsoc_irq_st.level1, sirfsoc_intc_base + SIRFSOC_INT_RISC_LEVEL1); |
103 | } | 105 | } |
104 | 106 | ||
105 | static struct syscore_ops sirfsoc_irq_syscore_ops = { | 107 | static struct syscore_ops sirfsoc_irq_syscore_ops = { |
106 | .suspend = sirfsoc_irq_suspend, | 108 | .suspend = sirfsoc_irq_suspend, |
107 | .resume = sirfsoc_irq_resume, | 109 | .resume = sirfsoc_irq_resume, |
108 | }; | 110 | }; |
109 | 111 | ||
110 | static int __init sirfsoc_irq_pm_init(void) | 112 | static int __init sirfsoc_irq_pm_init(void) |
111 | { | 113 | { |
112 | register_syscore_ops(&sirfsoc_irq_syscore_ops); | 114 | register_syscore_ops(&sirfsoc_irq_syscore_ops); |
113 | return 0; | 115 | return 0; |
114 | } | 116 | } |
115 | device_initcall(sirfsoc_irq_pm_init); | 117 | device_initcall(sirfsoc_irq_pm_init); |
116 | 118 |