diff options
| author | Varun Sethi <Varun.Sethi@freescale.com> | 2012-07-09 04:45:42 -0400 |
|---|---|---|
| committer | Kumar Gala <galak@kernel.crashing.org> | 2012-09-12 15:57:07 -0400 |
| commit | 03bcb7e35f7e5f759fe03f10a12cd4060dabe60d (patch) | |
| tree | da831db282105b46a434db47143b51d4a274909f /arch/powerpc/sysdev | |
| parent | 34f84b5b5bc83f4fc208cc278f572e6d926f976b (diff) | |
powerpc/mpic: finish supporting timer group B on Freescale chips
Previously, these interrupts would be mapped, but the offset calculation
was broken, and only the first group was initialized.
Signed-off-by: Varun Sethi <Varun.Sethi@freescale.com>
Signed-off-by: Scott Wood <scottwood@freescale.com>
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/sysdev')
| -rw-r--r-- | arch/powerpc/sysdev/mpic.c | 58 |
1 files changed, 42 insertions, 16 deletions
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index bfc6211e5422..7e32db7e7b0d 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | * with various broken implementations of this HW. | 6 | * with various broken implementations of this HW. |
| 7 | * | 7 | * |
| 8 | * Copyright (C) 2004 Benjamin Herrenschmidt, IBM Corp. | 8 | * Copyright (C) 2004 Benjamin Herrenschmidt, IBM Corp. |
| 9 | * Copyright 2010-2011 Freescale Semiconductor, Inc. | 9 | * Copyright 2010-2012 Freescale Semiconductor, Inc. |
| 10 | * | 10 | * |
| 11 | * This file is subject to the terms and conditions of the GNU General Public | 11 | * This file is subject to the terms and conditions of the GNU General Public |
| 12 | * License. See the file COPYING in the main directory of this archive | 12 | * License. See the file COPYING in the main directory of this archive |
| @@ -221,24 +221,24 @@ static inline void _mpic_ipi_write(struct mpic *mpic, unsigned int ipi, u32 valu | |||
| 221 | _mpic_write(mpic->reg_type, &mpic->gregs, offset, value); | 221 | _mpic_write(mpic->reg_type, &mpic->gregs, offset, value); |
| 222 | } | 222 | } |
| 223 | 223 | ||
| 224 | static inline u32 _mpic_tm_read(struct mpic *mpic, unsigned int tm) | 224 | static inline unsigned int mpic_tm_offset(struct mpic *mpic, unsigned int tm) |
| 225 | { | 225 | { |
| 226 | unsigned int offset = MPIC_INFO(TIMER_VECTOR_PRI) + | 226 | return (tm >> 2) * MPIC_TIMER_GROUP_STRIDE + |
| 227 | ((tm & 3) * MPIC_INFO(TIMER_STRIDE)); | 227 | (tm & 3) * MPIC_INFO(TIMER_STRIDE); |
| 228 | } | ||
| 228 | 229 | ||
| 229 | if (tm >= 4) | 230 | static inline u32 _mpic_tm_read(struct mpic *mpic, unsigned int tm) |
| 230 | offset += 0x1000 / 4; | 231 | { |
| 232 | unsigned int offset = mpic_tm_offset(mpic, tm) + | ||
| 233 | MPIC_INFO(TIMER_VECTOR_PRI); | ||
| 231 | 234 | ||
| 232 | return _mpic_read(mpic->reg_type, &mpic->tmregs, offset); | 235 | return _mpic_read(mpic->reg_type, &mpic->tmregs, offset); |
| 233 | } | 236 | } |
| 234 | 237 | ||
| 235 | static inline void _mpic_tm_write(struct mpic *mpic, unsigned int tm, u32 value) | 238 | static inline void _mpic_tm_write(struct mpic *mpic, unsigned int tm, u32 value) |
| 236 | { | 239 | { |
| 237 | unsigned int offset = MPIC_INFO(TIMER_VECTOR_PRI) + | 240 | unsigned int offset = mpic_tm_offset(mpic, tm) + |
| 238 | ((tm & 3) * MPIC_INFO(TIMER_STRIDE)); | 241 | MPIC_INFO(TIMER_VECTOR_PRI); |
| 239 | |||
| 240 | if (tm >= 4) | ||
| 241 | offset += 0x1000 / 4; | ||
| 242 | 242 | ||
| 243 | _mpic_write(mpic->reg_type, &mpic->tmregs, offset, value); | 243 | _mpic_write(mpic->reg_type, &mpic->tmregs, offset, value); |
| 244 | } | 244 | } |
| @@ -1301,6 +1301,16 @@ struct mpic * __init mpic_alloc(struct device_node *node, | |||
| 1301 | mpic_map(mpic, mpic->paddr, &mpic->gregs, MPIC_INFO(GREG_BASE), 0x1000); | 1301 | mpic_map(mpic, mpic->paddr, &mpic->gregs, MPIC_INFO(GREG_BASE), 0x1000); |
| 1302 | mpic_map(mpic, mpic->paddr, &mpic->tmregs, MPIC_INFO(TIMER_BASE), 0x1000); | 1302 | mpic_map(mpic, mpic->paddr, &mpic->tmregs, MPIC_INFO(TIMER_BASE), 0x1000); |
| 1303 | 1303 | ||
| 1304 | if (mpic->flags & MPIC_FSL) { | ||
| 1305 | /* | ||
| 1306 | * Yes, Freescale really did put global registers in the | ||
| 1307 | * magic per-cpu area -- and they don't even show up in the | ||
| 1308 | * non-magic per-cpu copies that this driver normally uses. | ||
| 1309 | */ | ||
| 1310 | mpic_map(mpic, mpic->paddr, &mpic->thiscpuregs, | ||
| 1311 | MPIC_CPU_THISBASE, 0x1000); | ||
| 1312 | } | ||
| 1313 | |||
| 1304 | /* Reset */ | 1314 | /* Reset */ |
| 1305 | 1315 | ||
| 1306 | /* When using a device-node, reset requests are only honored if the MPIC | 1316 | /* When using a device-node, reset requests are only honored if the MPIC |
| @@ -1440,6 +1450,7 @@ void __init mpic_assign_isu(struct mpic *mpic, unsigned int isu_num, | |||
| 1440 | void __init mpic_init(struct mpic *mpic) | 1450 | void __init mpic_init(struct mpic *mpic) |
| 1441 | { | 1451 | { |
| 1442 | int i, cpu; | 1452 | int i, cpu; |
| 1453 | int num_timers = 4; | ||
| 1443 | 1454 | ||
| 1444 | BUG_ON(mpic->num_sources == 0); | 1455 | BUG_ON(mpic->num_sources == 0); |
| 1445 | 1456 | ||
| @@ -1448,15 +1459,30 @@ void __init mpic_init(struct mpic *mpic) | |||
| 1448 | /* Set current processor priority to max */ | 1459 | /* Set current processor priority to max */ |
| 1449 | mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), 0xf); | 1460 | mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), 0xf); |
| 1450 | 1461 | ||
| 1462 | if (mpic->flags & MPIC_FSL) { | ||
| 1463 | u32 brr1 = _mpic_read(mpic->reg_type, &mpic->thiscpuregs, | ||
| 1464 | MPIC_FSL_BRR1); | ||
| 1465 | u32 version = brr1 & MPIC_FSL_BRR1_VER; | ||
| 1466 | |||
| 1467 | /* | ||
| 1468 | * Timer group B is present at the latest in MPIC 3.1 (e.g. | ||
| 1469 | * mpc8536). It is not present in MPIC 2.0 (e.g. mpc8544). | ||
| 1470 | * I don't know about the status of intermediate versions (or | ||
| 1471 | * whether they even exist). | ||
| 1472 | */ | ||
| 1473 | if (version >= 0x0301) | ||
| 1474 | num_timers = 8; | ||
| 1475 | } | ||
| 1476 | |||
| 1451 | /* Initialize timers to our reserved vectors and mask them for now */ | 1477 | /* Initialize timers to our reserved vectors and mask them for now */ |
| 1452 | for (i = 0; i < 4; i++) { | 1478 | for (i = 0; i < num_timers; i++) { |
| 1479 | unsigned int offset = mpic_tm_offset(mpic, i); | ||
| 1480 | |||
| 1453 | mpic_write(mpic->tmregs, | 1481 | mpic_write(mpic->tmregs, |
| 1454 | i * MPIC_INFO(TIMER_STRIDE) + | 1482 | offset + MPIC_INFO(TIMER_DESTINATION), |
| 1455 | MPIC_INFO(TIMER_DESTINATION), | ||
| 1456 | 1 << hard_smp_processor_id()); | 1483 | 1 << hard_smp_processor_id()); |
| 1457 | mpic_write(mpic->tmregs, | 1484 | mpic_write(mpic->tmregs, |
| 1458 | i * MPIC_INFO(TIMER_STRIDE) + | 1485 | offset + MPIC_INFO(TIMER_VECTOR_PRI), |
| 1459 | MPIC_INFO(TIMER_VECTOR_PRI), | ||
| 1460 | MPIC_VECPRI_MASK | | 1486 | MPIC_VECPRI_MASK | |
| 1461 | (9 << MPIC_VECPRI_PRIORITY_SHIFT) | | 1487 | (9 << MPIC_VECPRI_PRIORITY_SHIFT) | |
| 1462 | (mpic->timer_vecs[0] + i)); | 1488 | (mpic->timer_vecs[0] + i)); |
