diff options
Diffstat (limited to 'arch/powerpc/sysdev/mpic.c')
-rw-r--r-- | arch/powerpc/sysdev/mpic.c | 70 |
1 files changed, 57 insertions, 13 deletions
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index 212a94f5d34b..6ffdda244bb1 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c | |||
@@ -83,6 +83,7 @@ static u32 mpic_infos[][MPIC_IDX_END] = { | |||
83 | MPIC_CPU_WHOAMI, | 83 | MPIC_CPU_WHOAMI, |
84 | MPIC_CPU_INTACK, | 84 | MPIC_CPU_INTACK, |
85 | MPIC_CPU_EOI, | 85 | MPIC_CPU_EOI, |
86 | MPIC_CPU_MCACK, | ||
86 | 87 | ||
87 | MPIC_IRQ_BASE, | 88 | MPIC_IRQ_BASE, |
88 | MPIC_IRQ_STRIDE, | 89 | MPIC_IRQ_STRIDE, |
@@ -121,6 +122,7 @@ static u32 mpic_infos[][MPIC_IDX_END] = { | |||
121 | TSI108_CPU_WHOAMI, | 122 | TSI108_CPU_WHOAMI, |
122 | TSI108_CPU_INTACK, | 123 | TSI108_CPU_INTACK, |
123 | TSI108_CPU_EOI, | 124 | TSI108_CPU_EOI, |
125 | TSI108_CPU_MCACK, | ||
124 | 126 | ||
125 | TSI108_IRQ_BASE, | 127 | TSI108_IRQ_BASE, |
126 | TSI108_IRQ_STRIDE, | 128 | TSI108_IRQ_STRIDE, |
@@ -265,7 +267,7 @@ static inline void _mpic_irq_write(struct mpic *mpic, unsigned int src_no, | |||
265 | */ | 267 | */ |
266 | 268 | ||
267 | 269 | ||
268 | static void _mpic_map_mmio(struct mpic *mpic, unsigned long phys_addr, | 270 | static void _mpic_map_mmio(struct mpic *mpic, phys_addr_t phys_addr, |
269 | struct mpic_reg_bank *rb, unsigned int offset, | 271 | struct mpic_reg_bank *rb, unsigned int offset, |
270 | unsigned int size) | 272 | unsigned int size) |
271 | { | 273 | { |
@@ -285,7 +287,7 @@ static void _mpic_map_dcr(struct mpic *mpic, struct mpic_reg_bank *rb, | |||
285 | BUG_ON(!DCR_MAP_OK(rb->dhost)); | 287 | BUG_ON(!DCR_MAP_OK(rb->dhost)); |
286 | } | 288 | } |
287 | 289 | ||
288 | static inline void mpic_map(struct mpic *mpic, unsigned long phys_addr, | 290 | static inline void mpic_map(struct mpic *mpic, phys_addr_t phys_addr, |
289 | struct mpic_reg_bank *rb, unsigned int offset, | 291 | struct mpic_reg_bank *rb, unsigned int offset, |
290 | unsigned int size) | 292 | unsigned int size) |
291 | { | 293 | { |
@@ -612,12 +614,11 @@ static inline void mpic_eoi(struct mpic *mpic) | |||
612 | } | 614 | } |
613 | 615 | ||
614 | #ifdef CONFIG_SMP | 616 | #ifdef CONFIG_SMP |
615 | static irqreturn_t mpic_ipi_action(int irq, void *dev_id) | 617 | static irqreturn_t mpic_ipi_action(int irq, void *data) |
616 | { | 618 | { |
617 | struct mpic *mpic; | 619 | long ipi = (long)data; |
618 | 620 | ||
619 | mpic = mpic_find(irq, NULL); | 621 | smp_message_recv(ipi); |
620 | smp_message_recv(mpic_irq_to_hw(irq) - mpic->ipi_vecs[0]); | ||
621 | 622 | ||
622 | return IRQ_HANDLED; | 623 | return IRQ_HANDLED; |
623 | } | 624 | } |
@@ -842,6 +843,24 @@ int mpic_set_irq_type(unsigned int virq, unsigned int flow_type) | |||
842 | return 0; | 843 | return 0; |
843 | } | 844 | } |
844 | 845 | ||
846 | void mpic_set_vector(unsigned int virq, unsigned int vector) | ||
847 | { | ||
848 | struct mpic *mpic = mpic_from_irq(virq); | ||
849 | unsigned int src = mpic_irq_to_hw(virq); | ||
850 | unsigned int vecpri; | ||
851 | |||
852 | DBG("mpic: set_vector(mpic:@%p,virq:%d,src:%d,vector:0x%x)\n", | ||
853 | mpic, virq, src, vector); | ||
854 | |||
855 | if (src >= mpic->irq_count) | ||
856 | return; | ||
857 | |||
858 | vecpri = mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)); | ||
859 | vecpri = vecpri & ~MPIC_INFO(VECPRI_VECTOR_MASK); | ||
860 | vecpri |= vector; | ||
861 | mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI), vecpri); | ||
862 | } | ||
863 | |||
845 | static struct irq_chip mpic_irq_chip = { | 864 | static struct irq_chip mpic_irq_chip = { |
846 | .mask = mpic_mask_irq, | 865 | .mask = mpic_mask_irq, |
847 | .unmask = mpic_unmask_irq, | 866 | .unmask = mpic_unmask_irq, |
@@ -1109,6 +1128,11 @@ struct mpic * __init mpic_alloc(struct device_node *node, | |||
1109 | mb(); | 1128 | mb(); |
1110 | } | 1129 | } |
1111 | 1130 | ||
1131 | if (flags & MPIC_ENABLE_MCK) | ||
1132 | mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0), | ||
1133 | mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0)) | ||
1134 | | MPIC_GREG_GCONF_MCK); | ||
1135 | |||
1112 | /* Read feature register, calculate num CPUs and, for non-ISU | 1136 | /* Read feature register, calculate num CPUs and, for non-ISU |
1113 | * MPICs, num sources as well. On ISU MPICs, sources are counted | 1137 | * MPICs, num sources as well. On ISU MPICs, sources are counted |
1114 | * as ISUs are added | 1138 | * as ISUs are added |
@@ -1230,6 +1254,8 @@ void __init mpic_init(struct mpic *mpic) | |||
1230 | mpic_u3msi_init(mpic); | 1254 | mpic_u3msi_init(mpic); |
1231 | } | 1255 | } |
1232 | 1256 | ||
1257 | mpic_pasemi_msi_init(mpic); | ||
1258 | |||
1233 | for (i = 0; i < mpic->num_sources; i++) { | 1259 | for (i = 0; i < mpic->num_sources; i++) { |
1234 | /* start with vector = source number, and masked */ | 1260 | /* start with vector = source number, and masked */ |
1235 | u32 vecpri = MPIC_VECPRI_MASK | i | | 1261 | u32 vecpri = MPIC_VECPRI_MASK | i | |
@@ -1253,6 +1279,11 @@ void __init mpic_init(struct mpic *mpic) | |||
1253 | mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0)) | 1279 | mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0)) |
1254 | | MPIC_GREG_GCONF_8259_PTHROU_DIS); | 1280 | | MPIC_GREG_GCONF_8259_PTHROU_DIS); |
1255 | 1281 | ||
1282 | if (mpic->flags & MPIC_NO_BIAS) | ||
1283 | mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0), | ||
1284 | mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0)) | ||
1285 | | MPIC_GREG_GCONF_NO_BIAS); | ||
1286 | |||
1256 | /* Set current processor priority to 0 */ | 1287 | /* Set current processor priority to 0 */ |
1257 | mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), 0); | 1288 | mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), 0); |
1258 | 1289 | ||
@@ -1419,13 +1450,13 @@ void mpic_send_ipi(unsigned int ipi_no, unsigned int cpu_mask) | |||
1419 | mpic_physmask(cpu_mask & cpus_addr(cpu_online_map)[0])); | 1450 | mpic_physmask(cpu_mask & cpus_addr(cpu_online_map)[0])); |
1420 | } | 1451 | } |
1421 | 1452 | ||
1422 | unsigned int mpic_get_one_irq(struct mpic *mpic) | 1453 | static unsigned int _mpic_get_one_irq(struct mpic *mpic, int reg) |
1423 | { | 1454 | { |
1424 | u32 src; | 1455 | u32 src; |
1425 | 1456 | ||
1426 | src = mpic_cpu_read(MPIC_INFO(CPU_INTACK)) & MPIC_INFO(VECPRI_VECTOR_MASK); | 1457 | src = mpic_cpu_read(reg) & MPIC_INFO(VECPRI_VECTOR_MASK); |
1427 | #ifdef DEBUG_LOW | 1458 | #ifdef DEBUG_LOW |
1428 | DBG("%s: get_one_irq(): %d\n", mpic->name, src); | 1459 | DBG("%s: get_one_irq(reg 0x%x): %d\n", mpic->name, reg, src); |
1429 | #endif | 1460 | #endif |
1430 | if (unlikely(src == mpic->spurious_vec)) { | 1461 | if (unlikely(src == mpic->spurious_vec)) { |
1431 | if (mpic->flags & MPIC_SPV_EOI) | 1462 | if (mpic->flags & MPIC_SPV_EOI) |
@@ -1443,6 +1474,11 @@ unsigned int mpic_get_one_irq(struct mpic *mpic) | |||
1443 | return irq_linear_revmap(mpic->irqhost, src); | 1474 | return irq_linear_revmap(mpic->irqhost, src); |
1444 | } | 1475 | } |
1445 | 1476 | ||
1477 | unsigned int mpic_get_one_irq(struct mpic *mpic) | ||
1478 | { | ||
1479 | return _mpic_get_one_irq(mpic, MPIC_INFO(CPU_INTACK)); | ||
1480 | } | ||
1481 | |||
1446 | unsigned int mpic_get_irq(void) | 1482 | unsigned int mpic_get_irq(void) |
1447 | { | 1483 | { |
1448 | struct mpic *mpic = mpic_primary; | 1484 | struct mpic *mpic = mpic_primary; |
@@ -1452,12 +1488,20 @@ unsigned int mpic_get_irq(void) | |||
1452 | return mpic_get_one_irq(mpic); | 1488 | return mpic_get_one_irq(mpic); |
1453 | } | 1489 | } |
1454 | 1490 | ||
1491 | unsigned int mpic_get_mcirq(void) | ||
1492 | { | ||
1493 | struct mpic *mpic = mpic_primary; | ||
1494 | |||
1495 | BUG_ON(mpic == NULL); | ||
1496 | |||
1497 | return _mpic_get_one_irq(mpic, MPIC_INFO(CPU_MCACK)); | ||
1498 | } | ||
1455 | 1499 | ||
1456 | #ifdef CONFIG_SMP | 1500 | #ifdef CONFIG_SMP |
1457 | void mpic_request_ipis(void) | 1501 | void mpic_request_ipis(void) |
1458 | { | 1502 | { |
1459 | struct mpic *mpic = mpic_primary; | 1503 | struct mpic *mpic = mpic_primary; |
1460 | int i, err; | 1504 | long i, err; |
1461 | static char *ipi_names[] = { | 1505 | static char *ipi_names[] = { |
1462 | "IPI0 (call function)", | 1506 | "IPI0 (call function)", |
1463 | "IPI1 (reschedule)", | 1507 | "IPI1 (reschedule)", |
@@ -1472,14 +1516,14 @@ void mpic_request_ipis(void) | |||
1472 | unsigned int vipi = irq_create_mapping(mpic->irqhost, | 1516 | unsigned int vipi = irq_create_mapping(mpic->irqhost, |
1473 | mpic->ipi_vecs[0] + i); | 1517 | mpic->ipi_vecs[0] + i); |
1474 | if (vipi == NO_IRQ) { | 1518 | if (vipi == NO_IRQ) { |
1475 | printk(KERN_ERR "Failed to map IPI %d\n", i); | 1519 | printk(KERN_ERR "Failed to map IPI %ld\n", i); |
1476 | break; | 1520 | break; |
1477 | } | 1521 | } |
1478 | err = request_irq(vipi, mpic_ipi_action, | 1522 | err = request_irq(vipi, mpic_ipi_action, |
1479 | IRQF_DISABLED|IRQF_PERCPU, | 1523 | IRQF_DISABLED|IRQF_PERCPU, |
1480 | ipi_names[i], mpic); | 1524 | ipi_names[i], (void *)i); |
1481 | if (err) { | 1525 | if (err) { |
1482 | printk(KERN_ERR "Request of irq %d for IPI %d failed\n", | 1526 | printk(KERN_ERR "Request of irq %d for IPI %ld failed\n", |
1483 | vipi, i); | 1527 | vipi, i); |
1484 | break; | 1528 | break; |
1485 | } | 1529 | } |