Johannes Weiner | 000af2c | 2009-03-04 16:21:32 +0100 | [diff] [blame] | 1 | /* |
| 2 | * s6000 irq crossbar |
| 3 | * |
| 4 | * Copyright (c) 2009 emlix GmbH |
| 5 | * Authors: Johannes Weiner <jw@emlix.com> |
| 6 | * Oskar Schirmer <os@emlix.com> |
| 7 | */ |
| 8 | #include <linux/io.h> |
| 9 | #include <asm/irq.h> |
| 10 | #include <variant/hardware.h> |
| 11 | |
| 12 | /* S6_REG_INTC */ |
| 13 | #define INTC_STATUS 0x000 |
| 14 | #define INTC_RAW 0x010 |
| 15 | #define INTC_STATUS_AG 0x100 |
| 16 | #define INTC_CFG(n) (0x200 + 4 * (n)) |
| 17 | |
| 18 | /* |
| 19 | * The s6000 has a crossbar that multiplexes interrupt output lines |
| 20 | * from the peripherals to input lines on the xtensa core. |
| 21 | * |
| 22 | * We leave the mapping decisions to the platform as it depends on the |
| 23 | * actually connected peripherals which distribution makes sense. |
| 24 | */ |
| 25 | extern const signed char *platform_irq_mappings[NR_IRQS]; |
| 26 | |
| 27 | static unsigned long scp_to_intc_enable[] = { |
| 28 | #define TO_INTC_ENABLE(n) (((n) << 1) + 1) |
| 29 | TO_INTC_ENABLE(0), |
| 30 | TO_INTC_ENABLE(1), |
| 31 | TO_INTC_ENABLE(2), |
| 32 | TO_INTC_ENABLE(3), |
| 33 | TO_INTC_ENABLE(4), |
| 34 | TO_INTC_ENABLE(5), |
| 35 | TO_INTC_ENABLE(6), |
| 36 | TO_INTC_ENABLE(7), |
| 37 | TO_INTC_ENABLE(8), |
| 38 | TO_INTC_ENABLE(9), |
| 39 | TO_INTC_ENABLE(10), |
| 40 | TO_INTC_ENABLE(11), |
| 41 | TO_INTC_ENABLE(12), |
| 42 | -1, |
| 43 | -1, |
| 44 | TO_INTC_ENABLE(13), |
| 45 | -1, |
| 46 | TO_INTC_ENABLE(14), |
| 47 | -1, |
| 48 | TO_INTC_ENABLE(15), |
| 49 | #undef TO_INTC_ENABLE |
| 50 | }; |
| 51 | |
| 52 | static void irq_set(unsigned int irq, int enable) |
| 53 | { |
| 54 | unsigned long en; |
| 55 | const signed char *m = platform_irq_mappings[irq]; |
| 56 | |
| 57 | if (!m) |
| 58 | return; |
| 59 | en = enable ? scp_to_intc_enable[irq] : 0; |
| 60 | while (*m >= 0) { |
| 61 | writel(en, S6_REG_INTC + INTC_CFG(*m)); |
| 62 | m++; |
| 63 | } |
| 64 | } |
| 65 | |
| 66 | void variant_irq_enable(unsigned int irq) |
| 67 | { |
| 68 | irq_set(irq, 1); |
| 69 | } |
| 70 | |
| 71 | void variant_irq_disable(unsigned int irq) |
| 72 | { |
| 73 | irq_set(irq, 0); |
| 74 | } |