diff options
author | Manuel Lauss <manuel.lauss@googlemail.com> | 2009-10-04 08:55:25 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2010-02-27 06:52:50 -0500 |
commit | 95a437966dba642870a93d16bf82af8926bb2082 (patch) | |
tree | 18e797fc543f9650f03fcb06aae29bf5ca20e585 /arch/mips/alchemy/devboards | |
parent | 9bdcf336d0c061e77f4c45c7b2bc32e3ed6b57e3 (diff) |
MIPS: Alchemy: devboards: factor out PB1200 IRQ cascade code.
Move the PB1200 IRQ cascade code out to the BCSR support code:
upcoming DB1300 support can use it too.
Signed-off-by: Manuel Lauss <manuel.lauss@gmail.com>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/alchemy/devboards')
-rw-r--r-- | arch/mips/alchemy/devboards/bcsr.c | 72 | ||||
-rw-r--r-- | arch/mips/alchemy/devboards/pb1200/irqmap.c | 71 |
2 files changed, 73 insertions, 70 deletions
diff --git a/arch/mips/alchemy/devboards/bcsr.c b/arch/mips/alchemy/devboards/bcsr.c index 85b7715901af..3bc4fd2155d7 100644 --- a/arch/mips/alchemy/devboards/bcsr.c +++ b/arch/mips/alchemy/devboards/bcsr.c | |||
@@ -7,6 +7,7 @@ | |||
7 | * All registers are 16bits wide with 32bit spacing. | 7 | * All registers are 16bits wide with 32bit spacing. |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/interrupt.h> | ||
10 | #include <linux/module.h> | 11 | #include <linux/module.h> |
11 | #include <linux/spinlock.h> | 12 | #include <linux/spinlock.h> |
12 | #include <asm/addrspace.h> | 13 | #include <asm/addrspace.h> |
@@ -18,6 +19,9 @@ static struct bcsr_reg { | |||
18 | spinlock_t lock; | 19 | spinlock_t lock; |
19 | } bcsr_regs[BCSR_CNT]; | 20 | } bcsr_regs[BCSR_CNT]; |
20 | 21 | ||
22 | static void __iomem *bcsr_virt; /* KSEG1 addr of BCSR base */ | ||
23 | static int bcsr_csc_base; /* linux-irq of first cascaded irq */ | ||
24 | |||
21 | void __init bcsr_init(unsigned long bcsr1_phys, unsigned long bcsr2_phys) | 25 | void __init bcsr_init(unsigned long bcsr1_phys, unsigned long bcsr2_phys) |
22 | { | 26 | { |
23 | int i; | 27 | int i; |
@@ -25,6 +29,8 @@ void __init bcsr_init(unsigned long bcsr1_phys, unsigned long bcsr2_phys) | |||
25 | bcsr1_phys = KSEG1ADDR(CPHYSADDR(bcsr1_phys)); | 29 | bcsr1_phys = KSEG1ADDR(CPHYSADDR(bcsr1_phys)); |
26 | bcsr2_phys = KSEG1ADDR(CPHYSADDR(bcsr2_phys)); | 30 | bcsr2_phys = KSEG1ADDR(CPHYSADDR(bcsr2_phys)); |
27 | 31 | ||
32 | bcsr_virt = (void __iomem *)bcsr1_phys; | ||
33 | |||
28 | for (i = 0; i < BCSR_CNT; i++) { | 34 | for (i = 0; i < BCSR_CNT; i++) { |
29 | if (i >= BCSR_HEXLEDS) | 35 | if (i >= BCSR_HEXLEDS) |
30 | bcsr_regs[i].raddr = (void __iomem *)bcsr2_phys + | 36 | bcsr_regs[i].raddr = (void __iomem *)bcsr2_phys + |
@@ -74,3 +80,69 @@ void bcsr_mod(enum bcsr_id reg, unsigned short clr, unsigned short set) | |||
74 | spin_unlock_irqrestore(&bcsr_regs[reg].lock, flags); | 80 | spin_unlock_irqrestore(&bcsr_regs[reg].lock, flags); |
75 | } | 81 | } |
76 | EXPORT_SYMBOL_GPL(bcsr_mod); | 82 | EXPORT_SYMBOL_GPL(bcsr_mod); |
83 | |||
84 | /* | ||
85 | * DB1200/PB1200 CPLD IRQ muxer | ||
86 | */ | ||
87 | static void bcsr_csc_handler(unsigned int irq, struct irq_desc *d) | ||
88 | { | ||
89 | unsigned short bisr = __raw_readw(bcsr_virt + BCSR_REG_INTSTAT); | ||
90 | |||
91 | for ( ; bisr; bisr &= bisr - 1) | ||
92 | generic_handle_irq(bcsr_csc_base + __ffs(bisr)); | ||
93 | } | ||
94 | |||
95 | /* NOTE: both the enable and mask bits must be cleared, otherwise the | ||
96 | * CPLD generates tons of spurious interrupts (at least on my DB1200). | ||
97 | * -- mlau | ||
98 | */ | ||
99 | static void bcsr_irq_mask(unsigned int irq_nr) | ||
100 | { | ||
101 | unsigned short v = 1 << (irq_nr - bcsr_csc_base); | ||
102 | __raw_writew(v, bcsr_virt + BCSR_REG_INTCLR); | ||
103 | __raw_writew(v, bcsr_virt + BCSR_REG_MASKCLR); | ||
104 | wmb(); | ||
105 | } | ||
106 | |||
107 | static void bcsr_irq_maskack(unsigned int irq_nr) | ||
108 | { | ||
109 | unsigned short v = 1 << (irq_nr - bcsr_csc_base); | ||
110 | __raw_writew(v, bcsr_virt + BCSR_REG_INTCLR); | ||
111 | __raw_writew(v, bcsr_virt + BCSR_REG_MASKCLR); | ||
112 | __raw_writew(v, bcsr_virt + BCSR_REG_INTSTAT); /* ack */ | ||
113 | wmb(); | ||
114 | } | ||
115 | |||
116 | static void bcsr_irq_unmask(unsigned int irq_nr) | ||
117 | { | ||
118 | unsigned short v = 1 << (irq_nr - bcsr_csc_base); | ||
119 | __raw_writew(v, bcsr_virt + BCSR_REG_INTSET); | ||
120 | __raw_writew(v, bcsr_virt + BCSR_REG_MASKSET); | ||
121 | wmb(); | ||
122 | } | ||
123 | |||
124 | static struct irq_chip bcsr_irq_type = { | ||
125 | .name = "CPLD", | ||
126 | .mask = bcsr_irq_mask, | ||
127 | .mask_ack = bcsr_irq_maskack, | ||
128 | .unmask = bcsr_irq_unmask, | ||
129 | }; | ||
130 | |||
131 | void __init bcsr_init_irq(int csc_start, int csc_end, int hook_irq) | ||
132 | { | ||
133 | unsigned int irq; | ||
134 | |||
135 | /* mask & disable & ack all */ | ||
136 | __raw_writew(0xffff, bcsr_virt + BCSR_REG_INTCLR); | ||
137 | __raw_writew(0xffff, bcsr_virt + BCSR_REG_MASKCLR); | ||
138 | __raw_writew(0xffff, bcsr_virt + BCSR_REG_INTSTAT); | ||
139 | wmb(); | ||
140 | |||
141 | bcsr_csc_base = csc_start; | ||
142 | |||
143 | for (irq = csc_start; irq <= csc_end; irq++) | ||
144 | set_irq_chip_and_handler_name(irq, &bcsr_irq_type, | ||
145 | handle_level_irq, "level"); | ||
146 | |||
147 | set_irq_chained_handler(hook_irq, bcsr_csc_handler); | ||
148 | } | ||
diff --git a/arch/mips/alchemy/devboards/pb1200/irqmap.c b/arch/mips/alchemy/devboards/pb1200/irqmap.c index f379b02213f1..3beb8046667b 100644 --- a/arch/mips/alchemy/devboards/pb1200/irqmap.c +++ b/arch/mips/alchemy/devboards/pb1200/irqmap.c | |||
@@ -45,69 +45,11 @@ struct au1xxx_irqmap __initdata au1xxx_irq_map[] = { | |||
45 | { AU1000_GPIO_7, IRQF_TRIGGER_LOW, 0 }, | 45 | { AU1000_GPIO_7, IRQF_TRIGGER_LOW, 0 }, |
46 | }; | 46 | }; |
47 | 47 | ||
48 | static void __iomem *bcsr_virt; | ||
49 | |||
50 | /* | ||
51 | * Support for External interrupts on the Pb1200 Development platform. | ||
52 | */ | ||
53 | |||
54 | static void pb1200_cascade_handler(unsigned int irq, struct irq_desc *d) | ||
55 | { | ||
56 | unsigned short bisr = __raw_readw(bcsr_virt + BCSR_REG_INTSTAT); | ||
57 | |||
58 | for ( ; bisr; bisr &= bisr - 1) | ||
59 | generic_handle_irq(PB1200_INT_BEGIN + __ffs(bisr)); | ||
60 | } | ||
61 | |||
62 | /* NOTE: both the enable and mask bits must be cleared, otherwise the | ||
63 | * CPLD generates tons of spurious interrupts (at least on the DB1200). | ||
64 | */ | ||
65 | static void pb1200_mask_irq(unsigned int irq_nr) | ||
66 | { | ||
67 | unsigned short v = 1 << (irq_nr - PB1200_INT_BEGIN); | ||
68 | __raw_writew(v, bcsr_virt + BCSR_REG_INTCLR); | ||
69 | __raw_writew(v, bcsr_virt + BCSR_REG_MASKCLR); | ||
70 | wmb(); | ||
71 | } | ||
72 | |||
73 | static void pb1200_maskack_irq(unsigned int irq_nr) | ||
74 | { | ||
75 | unsigned short v = 1 << (irq_nr - PB1200_INT_BEGIN); | ||
76 | __raw_writew(v, bcsr_virt + BCSR_REG_INTCLR); | ||
77 | __raw_writew(v, bcsr_virt + BCSR_REG_MASKCLR); | ||
78 | __raw_writew(v, bcsr_virt + BCSR_REG_INTSTAT); /* ack */ | ||
79 | wmb(); | ||
80 | } | ||
81 | |||
82 | static void pb1200_unmask_irq(unsigned int irq_nr) | ||
83 | { | ||
84 | unsigned short v = 1 << (irq_nr - PB1200_INT_BEGIN); | ||
85 | __raw_writew(v, bcsr_virt + BCSR_REG_INTSET); | ||
86 | __raw_writew(v, bcsr_virt + BCSR_REG_MASKSET); | ||
87 | wmb(); | ||
88 | } | ||
89 | |||
90 | static struct irq_chip pb1200_cpld_irq_type = { | ||
91 | #ifdef CONFIG_MIPS_PB1200 | ||
92 | .name = "Pb1200 Ext", | ||
93 | #endif | ||
94 | #ifdef CONFIG_MIPS_DB1200 | ||
95 | .name = "Db1200 Ext", | ||
96 | #endif | ||
97 | .mask = pb1200_mask_irq, | ||
98 | .mask_ack = pb1200_maskack_irq, | ||
99 | .unmask = pb1200_unmask_irq, | ||
100 | }; | ||
101 | |||
102 | void __init board_init_irq(void) | 48 | void __init board_init_irq(void) |
103 | { | 49 | { |
104 | unsigned int irq; | ||
105 | |||
106 | au1xxx_setup_irqmap(au1xxx_irq_map, ARRAY_SIZE(au1xxx_irq_map)); | 50 | au1xxx_setup_irqmap(au1xxx_irq_map, ARRAY_SIZE(au1xxx_irq_map)); |
107 | 51 | ||
108 | #ifdef CONFIG_MIPS_PB1200 | 52 | #ifdef CONFIG_MIPS_PB1200 |
109 | bcsr_virt = (void __iomem *)KSEG1ADDR(PB1200_BCSR_PHYS_ADDR); | ||
110 | |||
111 | /* We have a problem with CPLD rev 3. */ | 53 | /* We have a problem with CPLD rev 3. */ |
112 | if (BCSR_WHOAMI_CPLD(bcsr_read(BCSR_WHOAMI)) <= 3) { | 54 | if (BCSR_WHOAMI_CPLD(bcsr_read(BCSR_WHOAMI)) <= 3) { |
113 | printk(KERN_ERR "WARNING!!!\n"); | 55 | printk(KERN_ERR "WARNING!!!\n"); |
@@ -127,18 +69,7 @@ void __init board_init_irq(void) | |||
127 | printk(KERN_ERR "WARNING!!!\n"); | 69 | printk(KERN_ERR "WARNING!!!\n"); |
128 | panic("Game over. Your score is 0."); | 70 | panic("Game over. Your score is 0."); |
129 | } | 71 | } |
130 | #else | ||
131 | bcsr_virt = (void __iomem *)KSEG1ADDR(DB1200_BCSR_PHYS_ADDR); | ||
132 | #endif | 72 | #endif |
133 | 73 | ||
134 | /* mask & disable & ack all */ | 74 | bcsr_init_irq(PB1200_INT_BEGIN, PB1200_INT_END, AU1000_GPIO_7); |
135 | bcsr_write(BCSR_INTCLR, 0xffff); | ||
136 | bcsr_write(BCSR_MASKCLR, 0xffff); | ||
137 | bcsr_write(BCSR_INTSTAT, 0xffff); | ||
138 | |||
139 | for (irq = PB1200_INT_BEGIN; irq <= PB1200_INT_END; irq++) | ||
140 | set_irq_chip_and_handler_name(irq, &pb1200_cpld_irq_type, | ||
141 | handle_level_irq, "level"); | ||
142 | |||
143 | set_irq_chained_handler(AU1000_GPIO_7, pb1200_cascade_handler); | ||
144 | } | 75 | } |