aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/sysdev/mpic.c
diff options
context:
space:
mode:
authorVarun Sethi <Varun.Sethi@freescale.com>2012-08-08 00:06:09 -0400
committerKumar Gala <galak@kernel.crashing.org>2012-09-12 15:57:10 -0400
commit0a4081641d722d3dee140505a86330ecf44db0fe (patch)
treef516459f8da722251d432c5bae2d544da2ab33e4 /arch/powerpc/sysdev/mpic.c
parent688ba1dbee8a49a2efe507cd9ae69634d92bb640 (diff)
powerpc/mpic: FSL MPIC error interrupt support.
All SOC device error interrupts are muxed and delivered to the core as a single MPIC error interrupt. Currently all the device drivers requiring access to device errors have to register for the MPIC error interrupt as a shared interrupt. With this patch we add interrupt demuxing capability in the mpic driver, allowing device drivers to register for their individual error interrupts. This is achieved by handling error interrupts in a cascaded fashion. MPIC error interrupt is handled by the "error_int_handler", which subsequently demuxes it using the EISR and delivers it to the respective drivers. The error interrupt capability is dependent on the MPIC EIMR register, which was introduced in FSL MPIC version 4.1 (P4080 rev2). So, error interrupt demuxing capability is dependent on the MPIC version and can be used for versions >= 4.1. Signed-off-by: Varun Sethi <Varun.Sethi@freescale.com> Signed-off-by: Bogdan Hamciuc <bogdan.hamciuc@freescale.com> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/sysdev/mpic.c')
-rw-r--r--arch/powerpc/sysdev/mpic.c44
1 files changed, 43 insertions, 1 deletions
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index 7e32db7e7b0d..9c6e535daad2 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -1026,6 +1026,9 @@ static int mpic_host_map(struct irq_domain *h, unsigned int virq,
1026 return 0; 1026 return 0;
1027 } 1027 }
1028 1028
1029 if (mpic_map_error_int(mpic, virq, hw))
1030 return 0;
1031
1029 if (hw >= mpic->num_sources) 1032 if (hw >= mpic->num_sources)
1030 return -EINVAL; 1033 return -EINVAL;
1031 1034
@@ -1085,7 +1088,16 @@ static int mpic_host_xlate(struct irq_domain *h, struct device_node *ct,
1085 */ 1088 */
1086 switch (intspec[2]) { 1089 switch (intspec[2]) {
1087 case 0: 1090 case 0:
1088 case 1: /* no EISR/EIMR support for now, treat as shared IRQ */ 1091 break;
1092 case 1:
1093 if (!(mpic->flags & MPIC_FSL_HAS_EIMR))
1094 break;
1095
1096 if (intspec[3] >= ARRAY_SIZE(mpic->err_int_vecs))
1097 return -EINVAL;
1098
1099 *out_hwirq = mpic->err_int_vecs[intspec[3]];
1100
1089 break; 1101 break;
1090 case 2: 1102 case 2:
1091 if (intspec[0] >= ARRAY_SIZE(mpic->ipi_vecs)) 1103 if (intspec[0] >= ARRAY_SIZE(mpic->ipi_vecs))
@@ -1302,6 +1314,9 @@ struct mpic * __init mpic_alloc(struct device_node *node,
1302 mpic_map(mpic, mpic->paddr, &mpic->tmregs, MPIC_INFO(TIMER_BASE), 0x1000); 1314 mpic_map(mpic, mpic->paddr, &mpic->tmregs, MPIC_INFO(TIMER_BASE), 0x1000);
1303 1315
1304 if (mpic->flags & MPIC_FSL) { 1316 if (mpic->flags & MPIC_FSL) {
1317 u32 brr1, version;
1318 int ret;
1319
1305 /* 1320 /*
1306 * Yes, Freescale really did put global registers in the 1321 * Yes, Freescale really did put global registers in the
1307 * magic per-cpu area -- and they don't even show up in the 1322 * magic per-cpu area -- and they don't even show up in the
@@ -1309,6 +1324,29 @@ struct mpic * __init mpic_alloc(struct device_node *node,
1309 */ 1324 */
1310 mpic_map(mpic, mpic->paddr, &mpic->thiscpuregs, 1325 mpic_map(mpic, mpic->paddr, &mpic->thiscpuregs,
1311 MPIC_CPU_THISBASE, 0x1000); 1326 MPIC_CPU_THISBASE, 0x1000);
1327
1328 brr1 = _mpic_read(mpic->reg_type, &mpic->thiscpuregs,
1329 MPIC_FSL_BRR1);
1330 version = brr1 & MPIC_FSL_BRR1_VER;
1331
1332 /* Error interrupt mask register (EIMR) is required for
1333 * handling individual device error interrupts. EIMR
1334 * was added in MPIC version 4.1.
1335 *
1336 * Over here we reserve vector number space for error
1337 * interrupt vectors. This space is stolen from the
1338 * global vector number space, as in case of ipis
1339 * and timer interrupts.
1340 *
1341 * Available vector space = intvec_top - 12, where 12
1342 * is the number of vectors which have been consumed by
1343 * ipis and timer interrupts.
1344 */
1345 if (version >= 0x401) {
1346 ret = mpic_setup_error_int(mpic, intvec_top - 12);
1347 if (ret)
1348 return NULL;
1349 }
1312 } 1350 }
1313 1351
1314 /* Reset */ 1352 /* Reset */
@@ -1474,6 +1512,10 @@ void __init mpic_init(struct mpic *mpic)
1474 num_timers = 8; 1512 num_timers = 8;
1475 } 1513 }
1476 1514
1515 /* FSL mpic error interrupt intialization */
1516 if (mpic->flags & MPIC_FSL_HAS_EIMR)
1517 mpic_err_int_init(mpic, MPIC_FSL_ERR_INT);
1518
1477 /* Initialize timers to our reserved vectors and mask them for now */ 1519 /* Initialize timers to our reserved vectors and mask them for now */
1478 for (i = 0; i < num_timers; i++) { 1520 for (i = 0; i < num_timers; i++) {
1479 unsigned int offset = mpic_tm_offset(mpic, i); 1521 unsigned int offset = mpic_tm_offset(mpic, i);