diff options
author | J. Bruce Fields <bfields@redhat.com> | 2012-10-09 18:35:22 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2012-10-09 18:35:22 -0400 |
commit | f474af7051212b4efc8267583fad9c4ebf33ccff (patch) | |
tree | 1aa46ebc8065a341f247c2a2d9af2f624ad1d4f8 /arch/powerpc/sysdev/mpic.c | |
parent | 0d22f68f02c10d5d10ec5712917e5828b001a822 (diff) | |
parent | e3dd9a52cb5552c46c2a4ca7ccdfb4dab5c72457 (diff) |
nfs: disintegrate UAPI for nfs
This is to complete part of the Userspace API (UAPI) disintegration for which
the preparatory patches were pulled recently. After these patches, userspace
headers will be segregated into:
include/uapi/linux/.../foo.h
for the userspace interface stuff, and:
include/linux/.../foo.h
for the strictly kernel internal stuff.
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'arch/powerpc/sysdev/mpic.c')
-rw-r--r-- | arch/powerpc/sysdev/mpic.c | 102 |
1 files changed, 85 insertions, 17 deletions
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index bfc6211e542..9c6e535daad 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c @@ -6,7 +6,7 @@ * with various broken implementations of this HW. * * Copyright (C) 2004 Benjamin Herrenschmidt, IBM Corp. - * Copyright 2010-2011 Freescale Semiconductor, Inc. + * Copyright 2010-2012 Freescale Semiconductor, Inc. * * This file is subject to the terms and conditions of the GNU General Public * 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 _mpic_write(mpic->reg_type, &mpic->gregs, offset, value); } -static inline u32 _mpic_tm_read(struct mpic *mpic, unsigned int tm) +static inline unsigned int mpic_tm_offset(struct mpic *mpic, unsigned int tm) { - unsigned int offset = MPIC_INFO(TIMER_VECTOR_PRI) + - ((tm & 3) * MPIC_INFO(TIMER_STRIDE)); + return (tm >> 2) * MPIC_TIMER_GROUP_STRIDE + + (tm & 3) * MPIC_INFO(TIMER_STRIDE); +} - if (tm >= 4) - offset += 0x1000 / 4; +static inline u32 _mpic_tm_read(struct mpic *mpic, unsigned int tm) +{ + unsigned int offset = mpic_tm_offset(mpic, tm) + + MPIC_INFO(TIMER_VECTOR_PRI); return _mpic_read(mpic->reg_type, &mpic->tmregs, offset); } static inline void _mpic_tm_write(struct mpic *mpic, unsigned int tm, u32 value) { - unsigned int offset = MPIC_INFO(TIMER_VECTOR_PRI) + - ((tm & 3) * MPIC_INFO(TIMER_STRIDE)); - - if (tm >= 4) - offset += 0x1000 / 4; + unsigned int offset = mpic_tm_offset(mpic, tm) + + MPIC_INFO(TIMER_VECTOR_PRI); _mpic_write(mpic->reg_type, &mpic->tmregs, offset, value); } @@ -1026,6 +1026,9 @@ static int mpic_host_map(struct irq_domain *h, unsigned int virq, return 0; } + if (mpic_map_error_int(mpic, virq, hw)) + return 0; + if (hw >= mpic->num_sources) return -EINVAL; @@ -1085,7 +1088,16 @@ static int mpic_host_xlate(struct irq_domain *h, struct device_node *ct, */ switch (intspec[2]) { case 0: - case 1: /* no EISR/EIMR support for now, treat as shared IRQ */ + break; + case 1: + if (!(mpic->flags & MPIC_FSL_HAS_EIMR)) + break; + + if (intspec[3] >= ARRAY_SIZE(mpic->err_int_vecs)) + return -EINVAL; + + *out_hwirq = mpic->err_int_vecs[intspec[3]]; + break; case 2: if (intspec[0] >= ARRAY_SIZE(mpic->ipi_vecs)) @@ -1301,6 +1313,42 @@ struct mpic * __init mpic_alloc(struct device_node *node, mpic_map(mpic, mpic->paddr, &mpic->gregs, MPIC_INFO(GREG_BASE), 0x1000); mpic_map(mpic, mpic->paddr, &mpic->tmregs, MPIC_INFO(TIMER_BASE), 0x1000); + if (mpic->flags & MPIC_FSL) { + u32 brr1, version; + int ret; + + /* + * Yes, Freescale really did put global registers in the + * magic per-cpu area -- and they don't even show up in the + * non-magic per-cpu copies that this driver normally uses. + */ + mpic_map(mpic, mpic->paddr, &mpic->thiscpuregs, + MPIC_CPU_THISBASE, 0x1000); + + brr1 = _mpic_read(mpic->reg_type, &mpic->thiscpuregs, + MPIC_FSL_BRR1); + version = brr1 & MPIC_FSL_BRR1_VER; + + /* Error interrupt mask register (EIMR) is required for + * handling individual device error interrupts. EIMR + * was added in MPIC version 4.1. + * + * Over here we reserve vector number space for error + * interrupt vectors. This space is stolen from the + * global vector number space, as in case of ipis + * and timer interrupts. + * + * Available vector space = intvec_top - 12, where 12 + * is the number of vectors which have been consumed by + * ipis and timer interrupts. + */ + if (version >= 0x401) { + ret = mpic_setup_error_int(mpic, intvec_top - 12); + if (ret) + return NULL; + } + } + /* Reset */ /* When using a device-node, reset requests are only honored if the MPIC @@ -1440,6 +1488,7 @@ void __init mpic_assign_isu(struct mpic *mpic, unsigned int isu_num, void __init mpic_init(struct mpic *mpic) { int i, cpu; + int num_timers = 4; BUG_ON(mpic->num_sources == 0); @@ -1448,15 +1497,34 @@ void __init mpic_init(struct mpic *mpic) /* Set current processor priority to max */ mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), 0xf); + if (mpic->flags & MPIC_FSL) { + u32 brr1 = _mpic_read(mpic->reg_type, &mpic->thiscpuregs, + MPIC_FSL_BRR1); + u32 version = brr1 & MPIC_FSL_BRR1_VER; + + /* + * Timer group B is present at the latest in MPIC 3.1 (e.g. + * mpc8536). It is not present in MPIC 2.0 (e.g. mpc8544). + * I don't know about the status of intermediate versions (or + * whether they even exist). + */ + if (version >= 0x0301) + num_timers = 8; + } + + /* FSL mpic error interrupt intialization */ + if (mpic->flags & MPIC_FSL_HAS_EIMR) + mpic_err_int_init(mpic, MPIC_FSL_ERR_INT); + /* Initialize timers to our reserved vectors and mask them for now */ - for (i = 0; i < 4; i++) { + for (i = 0; i < num_timers; i++) { + unsigned int offset = mpic_tm_offset(mpic, i); + mpic_write(mpic->tmregs, - i * MPIC_INFO(TIMER_STRIDE) + - MPIC_INFO(TIMER_DESTINATION), + offset + MPIC_INFO(TIMER_DESTINATION), 1 << hard_smp_processor_id()); mpic_write(mpic->tmregs, - i * MPIC_INFO(TIMER_STRIDE) + - MPIC_INFO(TIMER_VECTOR_PRI), + offset + MPIC_INFO(TIMER_VECTOR_PRI), MPIC_VECPRI_MASK | (9 << MPIC_VECPRI_PRIORITY_SHIFT) | (mpic->timer_vecs[0] + i)); |