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/mpic.c | |
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/mpic.c')
-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)); |