diff options
Diffstat (limited to 'arch/powerpc/sysdev/mpic.c')
-rw-r--r-- | arch/powerpc/sysdev/mpic.c | 53 |
1 files changed, 27 insertions, 26 deletions
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index 74c64c0d3b71..893e65439e85 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c | |||
@@ -156,8 +156,7 @@ static inline u32 _mpic_read(enum mpic_reg_type type, | |||
156 | switch(type) { | 156 | switch(type) { |
157 | #ifdef CONFIG_PPC_DCR | 157 | #ifdef CONFIG_PPC_DCR |
158 | case mpic_access_dcr: | 158 | case mpic_access_dcr: |
159 | return dcr_read(rb->dhost, | 159 | return dcr_read(rb->dhost, rb->dhost.base + reg); |
160 | rb->dbase + reg + rb->doff); | ||
161 | #endif | 160 | #endif |
162 | case mpic_access_mmio_be: | 161 | case mpic_access_mmio_be: |
163 | return in_be32(rb->base + (reg >> 2)); | 162 | return in_be32(rb->base + (reg >> 2)); |
@@ -174,8 +173,7 @@ static inline void _mpic_write(enum mpic_reg_type type, | |||
174 | switch(type) { | 173 | switch(type) { |
175 | #ifdef CONFIG_PPC_DCR | 174 | #ifdef CONFIG_PPC_DCR |
176 | case mpic_access_dcr: | 175 | case mpic_access_dcr: |
177 | return dcr_write(rb->dhost, | 176 | return dcr_write(rb->dhost, rb->dhost.base + reg, value); |
178 | rb->dbase + reg + rb->doff, value); | ||
179 | #endif | 177 | #endif |
180 | case mpic_access_mmio_be: | 178 | case mpic_access_mmio_be: |
181 | return out_be32(rb->base + (reg >> 2), value); | 179 | return out_be32(rb->base + (reg >> 2), value); |
@@ -228,8 +226,13 @@ static inline u32 _mpic_irq_read(struct mpic *mpic, unsigned int src_no, unsigne | |||
228 | unsigned int isu = src_no >> mpic->isu_shift; | 226 | unsigned int isu = src_no >> mpic->isu_shift; |
229 | unsigned int idx = src_no & mpic->isu_mask; | 227 | unsigned int idx = src_no & mpic->isu_mask; |
230 | 228 | ||
231 | return _mpic_read(mpic->reg_type, &mpic->isus[isu], | 229 | #ifdef CONFIG_MPIC_BROKEN_REGREAD |
232 | reg + (idx * MPIC_INFO(IRQ_STRIDE))); | 230 | if (reg == 0) |
231 | return mpic->isu_reg0_shadow[idx]; | ||
232 | else | ||
233 | #endif | ||
234 | return _mpic_read(mpic->reg_type, &mpic->isus[isu], | ||
235 | reg + (idx * MPIC_INFO(IRQ_STRIDE))); | ||
233 | } | 236 | } |
234 | 237 | ||
235 | static inline void _mpic_irq_write(struct mpic *mpic, unsigned int src_no, | 238 | static inline void _mpic_irq_write(struct mpic *mpic, unsigned int src_no, |
@@ -240,6 +243,11 @@ static inline void _mpic_irq_write(struct mpic *mpic, unsigned int src_no, | |||
240 | 243 | ||
241 | _mpic_write(mpic->reg_type, &mpic->isus[isu], | 244 | _mpic_write(mpic->reg_type, &mpic->isus[isu], |
242 | reg + (idx * MPIC_INFO(IRQ_STRIDE)), value); | 245 | reg + (idx * MPIC_INFO(IRQ_STRIDE)), value); |
246 | |||
247 | #ifdef CONFIG_MPIC_BROKEN_REGREAD | ||
248 | if (reg == 0) | ||
249 | mpic->isu_reg0_shadow[idx] = value; | ||
250 | #endif | ||
243 | } | 251 | } |
244 | 252 | ||
245 | #define mpic_read(b,r) _mpic_read(mpic->reg_type,&(b),(r)) | 253 | #define mpic_read(b,r) _mpic_read(mpic->reg_type,&(b),(r)) |
@@ -269,9 +277,11 @@ static void _mpic_map_mmio(struct mpic *mpic, unsigned long phys_addr, | |||
269 | static void _mpic_map_dcr(struct mpic *mpic, struct mpic_reg_bank *rb, | 277 | static void _mpic_map_dcr(struct mpic *mpic, struct mpic_reg_bank *rb, |
270 | unsigned int offset, unsigned int size) | 278 | unsigned int offset, unsigned int size) |
271 | { | 279 | { |
272 | rb->dbase = mpic->dcr_base; | 280 | const u32 *dbasep; |
273 | rb->doff = offset; | 281 | |
274 | rb->dhost = dcr_map(mpic->of_node, rb->dbase + rb->doff, size); | 282 | dbasep = of_get_property(mpic->irqhost->of_node, "dcr-reg", NULL); |
283 | |||
284 | rb->dhost = dcr_map(mpic->irqhost->of_node, *dbasep + offset, size); | ||
275 | BUG_ON(!DCR_MAP_OK(rb->dhost)); | 285 | BUG_ON(!DCR_MAP_OK(rb->dhost)); |
276 | } | 286 | } |
277 | 287 | ||
@@ -758,7 +768,7 @@ static void mpic_end_ipi(unsigned int irq) | |||
758 | 768 | ||
759 | #endif /* CONFIG_SMP */ | 769 | #endif /* CONFIG_SMP */ |
760 | 770 | ||
761 | static void mpic_set_affinity(unsigned int irq, cpumask_t cpumask) | 771 | void mpic_set_affinity(unsigned int irq, cpumask_t cpumask) |
762 | { | 772 | { |
763 | struct mpic *mpic = mpic_from_irq(irq); | 773 | struct mpic *mpic = mpic_from_irq(irq); |
764 | unsigned int src = mpic_irq_to_hw(irq); | 774 | unsigned int src = mpic_irq_to_hw(irq); |
@@ -861,10 +871,8 @@ static struct irq_chip mpic_irq_ht_chip = { | |||
861 | 871 | ||
862 | static int mpic_host_match(struct irq_host *h, struct device_node *node) | 872 | static int mpic_host_match(struct irq_host *h, struct device_node *node) |
863 | { | 873 | { |
864 | struct mpic *mpic = h->host_data; | ||
865 | |||
866 | /* Exact match, unless mpic node is NULL */ | 874 | /* Exact match, unless mpic node is NULL */ |
867 | return mpic->of_node == NULL || mpic->of_node == node; | 875 | return h->of_node == NULL || h->of_node == node; |
868 | } | 876 | } |
869 | 877 | ||
870 | static int mpic_host_map(struct irq_host *h, unsigned int virq, | 878 | static int mpic_host_map(struct irq_host *h, unsigned int virq, |
@@ -985,10 +993,9 @@ struct mpic * __init mpic_alloc(struct device_node *node, | |||
985 | 993 | ||
986 | memset(mpic, 0, sizeof(struct mpic)); | 994 | memset(mpic, 0, sizeof(struct mpic)); |
987 | mpic->name = name; | 995 | mpic->name = name; |
988 | mpic->of_node = of_node_get(node); | ||
989 | 996 | ||
990 | mpic->irqhost = irq_alloc_host(IRQ_HOST_MAP_LINEAR, isu_size, | 997 | mpic->irqhost = irq_alloc_host(of_node_get(node), IRQ_HOST_MAP_LINEAR, |
991 | &mpic_host_ops, | 998 | isu_size, &mpic_host_ops, |
992 | flags & MPIC_LARGE_VECTORS ? 2048 : 256); | 999 | flags & MPIC_LARGE_VECTORS ? 2048 : 256); |
993 | if (mpic->irqhost == NULL) { | 1000 | if (mpic->irqhost == NULL) { |
994 | of_node_put(node); | 1001 | of_node_put(node); |
@@ -1068,20 +1075,14 @@ struct mpic * __init mpic_alloc(struct device_node *node, | |||
1068 | BUG_ON(paddr == 0 && node == NULL); | 1075 | BUG_ON(paddr == 0 && node == NULL); |
1069 | 1076 | ||
1070 | /* If no physical address passed in, check if it's dcr based */ | 1077 | /* If no physical address passed in, check if it's dcr based */ |
1071 | if (paddr == 0 && of_get_property(node, "dcr-reg", NULL) != NULL) | 1078 | if (paddr == 0 && of_get_property(node, "dcr-reg", NULL) != NULL) { |
1072 | mpic->flags |= MPIC_USES_DCR; | ||
1073 | |||
1074 | #ifdef CONFIG_PPC_DCR | 1079 | #ifdef CONFIG_PPC_DCR |
1075 | if (mpic->flags & MPIC_USES_DCR) { | 1080 | mpic->flags |= MPIC_USES_DCR; |
1076 | const u32 *dbasep; | ||
1077 | dbasep = of_get_property(node, "dcr-reg", NULL); | ||
1078 | BUG_ON(dbasep == NULL); | ||
1079 | mpic->dcr_base = *dbasep; | ||
1080 | mpic->reg_type = mpic_access_dcr; | 1081 | mpic->reg_type = mpic_access_dcr; |
1081 | } | ||
1082 | #else | 1082 | #else |
1083 | BUG_ON (mpic->flags & MPIC_USES_DCR); | 1083 | BUG(); |
1084 | #endif /* CONFIG_PPC_DCR */ | 1084 | #endif /* CONFIG_PPC_DCR */ |
1085 | } | ||
1085 | 1086 | ||
1086 | /* If the MPIC is not DCR based, and no physical address was passed | 1087 | /* If the MPIC is not DCR based, and no physical address was passed |
1087 | * in, try to obtain one | 1088 | * in, try to obtain one |