Source
x
static void armada_370_xp_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
/*
* Marvell Armada 370 and Armada XP SoC IRQ handling
*
* Copyright (C) 2012 Marvell
*
* Lior Amsalem <alior@marvell.com>
* Gregory CLEMENT <gregory.clement@free-electrons.com>
* Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
* Ben Dooks <ben.dooks@codethink.co.uk>
*
* This file is licensed under the terms of the GNU General Public
* License version 2. This program is licensed "as is" without any
* warranty of any kind, whether express or implied.
*/
/*
* Overall diagram of the Armada XP interrupt controller:
*
* To CPU 0 To CPU 1
*
* /\ /\
* || ||
* +---------------+ +---------------+
* | | | |
* | per-CPU | | per-CPU |
* | mask/unmask | | mask/unmask |
* | CPU0 | | CPU1 |
* | | | |
* +---------------+ +---------------+
* /\ /\
* || ||
* \\_______________________//
* ||
* +-------------------+
* | |
* | Global interrupt |
* | mask/unmask |
* | |
* +-------------------+
* /\
* ||
* interrupt from
* device
*
* The "global interrupt mask/unmask" is modified using the
* ARMADA_370_XP_INT_SET_ENABLE_OFFS and
* ARMADA_370_XP_INT_CLEAR_ENABLE_OFFS registers, which are relative
* to "main_int_base".
*
* The "per-CPU mask/unmask" is modified using the
* ARMADA_370_XP_INT_SET_MASK_OFFS and
* ARMADA_370_XP_INT_CLEAR_MASK_OFFS registers, which are relative to
* "per_cpu_int_base". This base address points to a special address,
* which automatically accesses the registers of the current CPU.
*
* The per-CPU mask/unmask can also be adjusted using the global
* per-interrupt ARMADA_370_XP_INT_SOURCE_CTL register, which we use
* to configure interrupt affinity.
*
* Due to this model, all interrupts need to be mask/unmasked at two
* different levels: at the global level and at the per-CPU level.
*
* This driver takes the following approach to deal with this:
*
* - For global interrupts:
*
* At ->map() time, a global interrupt is unmasked at the per-CPU
* mask/unmask level. It is therefore unmasked at this level for
* the current CPU, running the ->map() code. This allows to have
* the interrupt unmasked at this level in non-SMP
* configurations. In SMP configurations, the ->set_affinity()