aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-mvebu
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-02-28 23:09:24 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2013-02-28 23:09:24 -0500
commit1a32c58bb945970e56f27a1cfb61625a3ac0b88e (patch)
treef49ac4bebcb62416494c0e5bade076c7f7f3bc56 /arch/arm/mach-mvebu
parent7307c00f335a4e986586b12334696098d2fc2bcd (diff)
parent564991205956d869db0e45dfabe23a31b596fa15 (diff)
Merge tag 'late-mvebu-rebased' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM SoC mvebu platform changes from Olof Johansson: "This series contains changes for the Marvell EBU platforms (mvebu, orion, kirkwood, dove) that were not part of the first set of pull requests because of dependencies on the MMC tree, and being submitted a little late. Notable changes are: - More devices get moved out of board files into device tree descriptions. The remaining devices listed in there have patches that will get sent for 3.10, after which we can remove a lot of the board files entirely. We are doing the pinctrl and mmc drivers here, ethernet and PCI still remain. - SMP support for mvebu is improved with support for the local interrupt controller. - The Guruplug board file gets replaced with a DT description. Unfortunately, the dependency on the MMC tree turned out to be a much larger problem than expected, when the MMC maintainer rebased the patches in his tree that all of the patches in this branch are based on, which caused merge conflicts between the new and old versions of those patches. To work around the merge conflicts, this branch rebases all patches on top of the respective MMC patches that did get merged into 3.9. The patches are all identical to the versions that were part of linux-next, but have a new commit date." * tag 'late-mvebu-rebased' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (90 commits) arm: mvebu: enable the SD card slot on Armada 370 Reference Design board ARM: kirkwood: topkick: init mvsdio via DT ARM: kirkwood: nsa310: convert to pinctrl ARM: Kirkwood: topkick: Enable i2c bus. ARM: kirkwood: topkick: convert to pinctrl ARM: dove: convert serial DT nodes to clocks property arm: mvebu: Add SPI flash on Armada 370 DB board arm: mvebu: Add SPI flash on Armada XP-DB board arm: mvebu: Add SPI flash on Armada XP-GP board arm: mvebu: Add support for SPI controller in Armada 370/XP clocksource: update and move armada-370-xp-timer documentation to timer directory arm: mvebu: update DT to support local timers ARM: Dove: convert usb host controller to DT arm: mvebu: Enable USB controllers on Armada 370/XP boards arm: mvebu: Add support for USB host controllers in Armada 370/XP arm: mvebu: add button for OpenBlocks AX3-4 ARM: Kirkwood: Convert NS2 to gpio-poweroff. ARM: Kirkwood: Convert NSA310 I2C to device tree ARM: Kirkwood: Convert NSA310 to use gpio-poweroff driver ARM: Kirkwood: Convert NSA310 to DT based regulators. ...
Diffstat (limited to 'arch/arm/mach-mvebu')
-rw-r--r--arch/arm/mach-mvebu/irq-armada-370-xp.c87
1 files changed, 83 insertions, 4 deletions
diff --git a/arch/arm/mach-mvebu/irq-armada-370-xp.c b/arch/arm/mach-mvebu/irq-armada-370-xp.c
index 8e3fb082c3c6..274ff58271de 100644
--- a/arch/arm/mach-mvebu/irq-armada-370-xp.c
+++ b/arch/arm/mach-mvebu/irq-armada-370-xp.c
@@ -34,6 +34,7 @@
34#define ARMADA_370_XP_INT_CONTROL (0x00) 34#define ARMADA_370_XP_INT_CONTROL (0x00)
35#define ARMADA_370_XP_INT_SET_ENABLE_OFFS (0x30) 35#define ARMADA_370_XP_INT_SET_ENABLE_OFFS (0x30)
36#define ARMADA_370_XP_INT_CLEAR_ENABLE_OFFS (0x34) 36#define ARMADA_370_XP_INT_CLEAR_ENABLE_OFFS (0x34)
37#define ARMADA_370_XP_INT_SOURCE_CTL(irq) (0x100 + irq*4)
37 38
38#define ARMADA_370_XP_CPU_INTACK_OFFS (0x44) 39#define ARMADA_370_XP_CPU_INTACK_OFFS (0x44)
39 40
@@ -41,28 +42,90 @@
41#define ARMADA_370_XP_IN_DRBEL_MSK_OFFS (0xc) 42#define ARMADA_370_XP_IN_DRBEL_MSK_OFFS (0xc)
42#define ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS (0x8) 43#define ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS (0x8)
43 44
45#define ARMADA_370_XP_MAX_PER_CPU_IRQS (28)
46
44#define ACTIVE_DOORBELLS (8) 47#define ACTIVE_DOORBELLS (8)
45 48
49static DEFINE_RAW_SPINLOCK(irq_controller_lock);
50
46static void __iomem *per_cpu_int_base; 51static void __iomem *per_cpu_int_base;
47static void __iomem *main_int_base; 52static void __iomem *main_int_base;
48static struct irq_domain *armada_370_xp_mpic_domain; 53static struct irq_domain *armada_370_xp_mpic_domain;
49 54
55/*
56 * In SMP mode:
57 * For shared global interrupts, mask/unmask global enable bit
58 * For CPU interrtups, mask/unmask the calling CPU's bit
59 */
50static void armada_370_xp_irq_mask(struct irq_data *d) 60static void armada_370_xp_irq_mask(struct irq_data *d)
51{ 61{
62#ifdef CONFIG_SMP
63 irq_hw_number_t hwirq = irqd_to_hwirq(d);
64
65 if (hwirq > ARMADA_370_XP_MAX_PER_CPU_IRQS)
66 writel(hwirq, main_int_base +
67 ARMADA_370_XP_INT_CLEAR_ENABLE_OFFS);
68 else
69 writel(hwirq, per_cpu_int_base +
70 ARMADA_370_XP_INT_SET_MASK_OFFS);
71#else
52 writel(irqd_to_hwirq(d), 72 writel(irqd_to_hwirq(d),
53 per_cpu_int_base + ARMADA_370_XP_INT_SET_MASK_OFFS); 73 per_cpu_int_base + ARMADA_370_XP_INT_SET_MASK_OFFS);
74#endif
54} 75}
55 76
56static void armada_370_xp_irq_unmask(struct irq_data *d) 77static void armada_370_xp_irq_unmask(struct irq_data *d)
57{ 78{
79#ifdef CONFIG_SMP
80 irq_hw_number_t hwirq = irqd_to_hwirq(d);
81
82 if (hwirq > ARMADA_370_XP_MAX_PER_CPU_IRQS)
83 writel(hwirq, main_int_base +
84 ARMADA_370_XP_INT_SET_ENABLE_OFFS);
85 else
86 writel(hwirq, per_cpu_int_base +
87 ARMADA_370_XP_INT_CLEAR_MASK_OFFS);
88#else
58 writel(irqd_to_hwirq(d), 89 writel(irqd_to_hwirq(d),
59 per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS); 90 per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS);
91#endif
60} 92}
61 93
62#ifdef CONFIG_SMP 94#ifdef CONFIG_SMP
63static int armada_xp_set_affinity(struct irq_data *d, 95static int armada_xp_set_affinity(struct irq_data *d,
64 const struct cpumask *mask_val, bool force) 96 const struct cpumask *mask_val, bool force)
65{ 97{
98 unsigned long reg;
99 unsigned long new_mask = 0;
100 unsigned long online_mask = 0;
101 unsigned long count = 0;
102 irq_hw_number_t hwirq = irqd_to_hwirq(d);
103 int cpu;
104
105 for_each_cpu(cpu, mask_val) {
106 new_mask |= 1 << cpu_logical_map(cpu);
107 count++;
108 }
109
110 /*
111 * Forbid mutlicore interrupt affinity
112 * This is required since the MPIC HW doesn't limit
113 * several CPUs from acknowledging the same interrupt.
114 */
115 if (count > 1)
116 return -EINVAL;
117
118 for_each_cpu(cpu, cpu_online_mask)
119 online_mask |= 1 << cpu_logical_map(cpu);
120
121 raw_spin_lock(&irq_controller_lock);
122
123 reg = readl(main_int_base + ARMADA_370_XP_INT_SOURCE_CTL(hwirq));
124 reg = (reg & (~online_mask)) | new_mask;
125 writel(reg, main_int_base + ARMADA_370_XP_INT_SOURCE_CTL(hwirq));
126
127 raw_spin_unlock(&irq_controller_lock);
128
66 return 0; 129 return 0;
67} 130}
68#endif 131#endif
@@ -82,10 +145,17 @@ static int armada_370_xp_mpic_irq_map(struct irq_domain *h,
82{ 145{
83 armada_370_xp_irq_mask(irq_get_irq_data(virq)); 146 armada_370_xp_irq_mask(irq_get_irq_data(virq));
84 writel(hw, main_int_base + ARMADA_370_XP_INT_SET_ENABLE_OFFS); 147 writel(hw, main_int_base + ARMADA_370_XP_INT_SET_ENABLE_OFFS);
85
86 irq_set_chip_and_handler(virq, &armada_370_xp_irq_chip,
87 handle_level_irq);
88 irq_set_status_flags(virq, IRQ_LEVEL); 148 irq_set_status_flags(virq, IRQ_LEVEL);
149
150 if (hw < ARMADA_370_XP_MAX_PER_CPU_IRQS) {
151 irq_set_percpu_devid(virq);
152 irq_set_chip_and_handler(virq, &armada_370_xp_irq_chip,
153 handle_percpu_devid_irq);
154
155 } else {
156 irq_set_chip_and_handler(virq, &armada_370_xp_irq_chip,
157 handle_level_irq);
158 }
89 set_irq_flags(virq, IRQF_VALID | IRQF_PROBE); 159 set_irq_flags(virq, IRQF_VALID | IRQF_PROBE);
90 160
91 return 0; 161 return 0;
@@ -155,6 +225,15 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node,
155 225
156#ifdef CONFIG_SMP 226#ifdef CONFIG_SMP
157 armada_xp_mpic_smp_cpu_init(); 227 armada_xp_mpic_smp_cpu_init();
228
229 /*
230 * Set the default affinity from all CPUs to the boot cpu.
231 * This is required since the MPIC doesn't limit several CPUs
232 * from acknowledging the same interrupt.
233 */
234 cpumask_clear(irq_default_affinity);
235 cpumask_set_cpu(smp_processor_id(), irq_default_affinity);
236
158#endif 237#endif
159 238
160 return 0; 239 return 0;
@@ -173,7 +252,7 @@ asmlinkage void __exception_irq_entry armada_370_xp_handle_irq(struct pt_regs
173 if (irqnr > 1022) 252 if (irqnr > 1022)
174 break; 253 break;
175 254
176 if (irqnr >= 8) { 255 if (irqnr > 0) {
177 irqnr = irq_find_mapping(armada_370_xp_mpic_domain, 256 irqnr = irq_find_mapping(armada_370_xp_mpic_domain,
178 irqnr); 257 irqnr);
179 handle_IRQ(irqnr, regs); 258 handle_IRQ(irqnr, regs);