aboutsummaryrefslogtreecommitdiffstats
path: root/arch/microblaze
diff options
context:
space:
mode:
authorMichal Simek <michal.simek@xilinx.com>2014-02-24 08:56:32 -0500
committerMichal Simek <michal.simek@xilinx.com>2014-04-07 05:58:32 -0400
commit1aa1243c339d4c902c0f9c1ced45742729a86e6a (patch)
tree6d355c9ec0234982540e4b647f1b3c00abd70598 /arch/microblaze
parentcff2ee046e063d887a3af432c23e7ec214b6d09d (diff)
microblaze: Make intc driver endian aware
Detect endianess directly on the hardware and use ioread/iowrite functions. Signed-off-by: Michal Simek <michal.simek@xilinx.com>
Diffstat (limited to 'arch/microblaze')
-rw-r--r--arch/microblaze/kernel/intc.c51
1 files changed, 41 insertions, 10 deletions
diff --git a/arch/microblaze/kernel/intc.c b/arch/microblaze/kernel/intc.c
index 581451ad4687..15c7c12ea0e7 100644
--- a/arch/microblaze/kernel/intc.c
+++ b/arch/microblaze/kernel/intc.c
@@ -32,6 +32,29 @@ static void __iomem *intc_baseaddr;
32#define MER_ME (1<<0) 32#define MER_ME (1<<0)
33#define MER_HIE (1<<1) 33#define MER_HIE (1<<1)
34 34
35static unsigned int (*read_fn)(void __iomem *);
36static void (*write_fn)(u32, void __iomem *);
37
38static void intc_write32(u32 val, void __iomem *addr)
39{
40 iowrite32(val, addr);
41}
42
43static unsigned int intc_read32(void __iomem *addr)
44{
45 return ioread32(addr);
46}
47
48static void intc_write32_be(u32 val, void __iomem *addr)
49{
50 iowrite32be(val, addr);
51}
52
53static unsigned int intc_read32_be(void __iomem *addr)
54{
55 return ioread32be(addr);
56}
57
35static void intc_enable_or_unmask(struct irq_data *d) 58static void intc_enable_or_unmask(struct irq_data *d)
36{ 59{
37 unsigned long mask = 1 << d->hwirq; 60 unsigned long mask = 1 << d->hwirq;
@@ -43,21 +66,21 @@ static void intc_enable_or_unmask(struct irq_data *d)
43 * acks the irq before calling the interrupt handler 66 * acks the irq before calling the interrupt handler
44 */ 67 */
45 if (irqd_is_level_type(d)) 68 if (irqd_is_level_type(d))
46 out_be32(intc_baseaddr + IAR, mask); 69 write_fn(mask, intc_baseaddr + IAR);
47 70
48 out_be32(intc_baseaddr + SIE, mask); 71 write_fn(mask, intc_baseaddr + SIE);
49} 72}
50 73
51static void intc_disable_or_mask(struct irq_data *d) 74static void intc_disable_or_mask(struct irq_data *d)
52{ 75{
53 pr_debug("disable: %ld\n", d->hwirq); 76 pr_debug("disable: %ld\n", d->hwirq);
54 out_be32(intc_baseaddr + CIE, 1 << d->hwirq); 77 write_fn(1 << d->hwirq, intc_baseaddr + CIE);
55} 78}
56 79
57static void intc_ack(struct irq_data *d) 80static void intc_ack(struct irq_data *d)
58{ 81{
59 pr_debug("ack: %ld\n", d->hwirq); 82 pr_debug("ack: %ld\n", d->hwirq);
60 out_be32(intc_baseaddr + IAR, 1 << d->hwirq); 83 write_fn(1 << d->hwirq, intc_baseaddr + IAR);
61} 84}
62 85
63static void intc_mask_ack(struct irq_data *d) 86static void intc_mask_ack(struct irq_data *d)
@@ -65,8 +88,8 @@ static void intc_mask_ack(struct irq_data *d)
65 unsigned long mask = 1 << d->hwirq; 88 unsigned long mask = 1 << d->hwirq;
66 89
67 pr_debug("disable_and_ack: %ld\n", d->hwirq); 90 pr_debug("disable_and_ack: %ld\n", d->hwirq);
68 out_be32(intc_baseaddr + CIE, mask); 91 write_fn(mask, intc_baseaddr + CIE);
69 out_be32(intc_baseaddr + IAR, mask); 92 write_fn(mask, intc_baseaddr + IAR);
70} 93}
71 94
72static struct irq_chip intc_dev = { 95static struct irq_chip intc_dev = {
@@ -83,7 +106,7 @@ unsigned int get_irq(void)
83{ 106{
84 unsigned int hwirq, irq = -1; 107 unsigned int hwirq, irq = -1;
85 108
86 hwirq = in_be32(intc_baseaddr + IVR); 109 hwirq = read_fn(intc_baseaddr + IVR);
87 if (hwirq != -1U) 110 if (hwirq != -1U)
88 irq = irq_find_mapping(root_domain, hwirq); 111 irq = irq_find_mapping(root_domain, hwirq);
89 112
@@ -140,17 +163,25 @@ static int __init xilinx_intc_of_init(struct device_node *intc,
140 pr_info("%s: num_irq=%d, edge=0x%x\n", 163 pr_info("%s: num_irq=%d, edge=0x%x\n",
141 intc->full_name, nr_irq, intr_mask); 164 intc->full_name, nr_irq, intr_mask);
142 165
166 write_fn = intc_write32;
167 read_fn = intc_read32;
168
143 /* 169 /*
144 * Disable all external interrupts until they are 170 * Disable all external interrupts until they are
145 * explicity requested. 171 * explicity requested.
146 */ 172 */
147 out_be32(intc_baseaddr + IER, 0); 173 write_fn(0, intc_baseaddr + IER);
148 174
149 /* Acknowledge any pending interrupts just in case. */ 175 /* Acknowledge any pending interrupts just in case. */
150 out_be32(intc_baseaddr + IAR, 0xffffffff); 176 write_fn(0xffffffff, intc_baseaddr + IAR);
151 177
152 /* Turn on the Master Enable. */ 178 /* Turn on the Master Enable. */
153 out_be32(intc_baseaddr + MER, MER_HIE | MER_ME); 179 write_fn(MER_HIE | MER_ME, intc_baseaddr + MER);
180 if (!(read_fn(intc_baseaddr + MER) & (MER_HIE | MER_ME))) {
181 write_fn = intc_write32_be;
182 read_fn = intc_read32_be;
183 write_fn(MER_HIE | MER_ME, intc_baseaddr + MER);
184 }
154 185
155 /* Yeah, okay, casting the intr_mask to a void* is butt-ugly, but I'm 186 /* Yeah, okay, casting the intr_mask to a void* is butt-ugly, but I'm
156 * lazy and Michal can clean it up to something nicer when he tests 187 * lazy and Michal can clean it up to something nicer when he tests