Merge branch 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull irq updates from Thomas Gleixner:
 "The irq departement delivers:

   - Rework the irqdomain core infrastructure to accomodate ACPI based
     systems.  This is required to support ARM64 without creating
     artificial device tree nodes.

   - Sanitize the ACPI based ARM GIC initialization by making use of the
     new firmware independent irqdomain core

   - Further improvements to the generic MSI management

   - Generalize the irq migration on CPU hotplug

   - Improvements to the threaded interrupt infrastructure

   - Allow the migration of "chained" low level interrupt handlers

   - Allow optional force masking of interrupts in disable_irq[_nosysnc]

   - Support for two new interrupt chips - Sigh!

   - A larger set of errata fixes for ARM gicv3

   - The usual pile of fixes, updates, improvements and cleanups all
     over the place"

* 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (71 commits)
  Document that IRQ_NONE should be returned when IRQ not actually handled
  PCI/MSI: Allow the MSI domain to be device-specific
  PCI: Add per-device MSI domain hook
  of/irq: Use the msi-map property to provide device-specific MSI domain
  of/irq: Split of_msi_map_rid to reuse msi-map lookup
  irqchip/gic-v3-its: Parse new version of msi-parent property
  PCI/MSI: Use of_msi_get_domain instead of open-coded "msi-parent" parsing
  of/irq: Use of_msi_get_domain instead of open-coded "msi-parent" parsing
  of/irq: Add support code for multi-parent version of "msi-parent"
  irqchip/gic-v3-its: Add handling of PCI requester id.
  PCI/MSI: Add helper function pci_msi_domain_get_msi_rid().
  of/irq: Add new function of_msi_map_rid()
  Docs: dt: Add PCI MSI map bindings
  irqchip/gic-v2m: Add support for multiple MSI frames
  irqchip/gic-v3: Fix translation of LPIs after conversion to irq_fwspec
  irqchip/mxs: Add Alphascale ASM9260 support
  irqchip/mxs: Prepare driver for hardware with different offsets
  irqchip/mxs: Panic if ioremap or domain creation fails
  irqdomain: Documentation updates
  irqdomain/msi: Use fwnode instead of of_node
  ...
This commit is contained in:
Linus Torvalds committed 2015-11-03 14:40:01 -08:00
commit 6aa2fdb87c
90 files changed
+2577 -890

No files matched your search

+4 -4
View File
@@ -32,9 +32,9 @@ top of the irq_alloc_desc*() API. An irq_domain to manage mapping is
preferred over interrupt controller drivers open coding their own
reverse mapping scheme.
irq_domain also implements translation from Device Tree interrupt
specifiers to hwirq numbers, and can be easily extended to support
other IRQ topology data sources.
irq_domain also implements translation from an abstract irq_fwspec
structure to hwirq numbers (Device Tree and ACPI GSI so far), and can
be easily extended to support other IRQ topology data sources.
=== irq_domain usage ===
An interrupt controller driver creates and registers an irq_domain by
@@ -184,7 +184,7 @@ There are four major interfaces to use hierarchy irq_domain:
related resources associated with these interrupts.
3) irq_domain_activate_irq(): activate interrupt controller hardware to
deliver the interrupt.
3) irq_domain_deactivate_irq(): deactivate interrupt controller hardware
4) irq_domain_deactivate_irq(): deactivate interrupt controller hardware
to stop delivering the interrupt.
Following changes are needed to support hierarchy irq_domain.
+10 -1
View File
@@ -173,13 +173,22 @@ Before jumping into the kernel, the following conditions must be met:
the kernel image will be entered must be initialised by software at a
higher exception level to prevent execution in an UNKNOWN state.
For systems with a GICv3 interrupt controller:
For systems with a GICv3 interrupt controller to be used in v3 mode:
- If EL3 is present:
ICC_SRE_EL3.Enable (bit 3) must be initialiased to 0b1.
ICC_SRE_EL3.SRE (bit 0) must be initialised to 0b1.
- If the kernel is entered at EL1:
ICC.SRE_EL2.Enable (bit 3) must be initialised to 0b1
ICC_SRE_EL2.SRE (bit 0) must be initialised to 0b1.
- The DT or ACPI tables must describe a GICv3 interrupt controller.
For systems with a GICv3 interrupt controller to be used in
compatibility (v2) mode:
- If EL3 is present:
ICC_SRE_EL3.SRE (bit 0) must be initialised to 0b0.
- If the kernel is entered at EL1:
ICC_SRE_EL2.SRE (bit 0) must be initialised to 0b0.
- The DT or ACPI tables must describe a GICv2 interrupt controller.
The requirements described above for CPU mode, caches, MMUs, architected
timers, coherency and system registers apply to all CPUs. All CPUs must
+22 -6
View File
@@ -11,13 +11,14 @@ have PPIs or SGIs.
Main node required properties:
- compatible : should be one of:
"arm,gic-400"
"arm,cortex-a15-gic"
"arm,cortex-a9-gic"
"arm,cortex-a7-gic"
"arm,arm11mp-gic"
"brcm,brahma-b15-gic"
"arm,arm1176jzf-devchip-gic"
"arm,arm11mp-gic"
"arm,cortex-a15-gic"
"arm,cortex-a7-gic"
"arm,cortex-a9-gic"
"arm,gic-400"
"arm,pl390"
"brcm,brahma-b15-gic"
"qcom,msm-8660-qgic"
"qcom,msm-qgic2"
- interrupt-controller : Identifies the node as an interrupt controller
@@ -58,6 +59,21 @@ Optional
regions, used when the GIC doesn't have banked registers. The offset is
cpu-offset * cpu-nr.
- clocks : List of phandle and clock-specific pairs, one for each entry
in clock-names.
- clock-names : List of names for the GIC clock input(s). Valid clock names
depend on the GIC variant:
"ic_clk" (for "arm,arm11mp-gic")
"PERIPHCLKEN" (for "arm,cortex-a15-gic")
"PERIPHCLK", "PERIPHCLKEN" (for "arm,cortex-a9-gic")
"clk" (for "arm,gic-400")
"gclk" (for "arm,pl390")
- power-domains : A phandle and PM domain specifier as defined by bindings of
the power controller specified by phandle, used when the GIC
is part of a Power or Clock Domain.
Example:
intc: interrupt-controller@fff11000 {
@@ -10,6 +10,7 @@ Required properties:
- "renesas,irqc-r8a7792" (R-Car V2H)
- "renesas,irqc-r8a7793" (R-Car M2-N)
- "renesas,irqc-r8a7794" (R-Car E2)
- "renesas,intc-ex-r8a7795" (R-Car H3)
- #interrupt-cells: has to be <2>: an interrupt index and flags, as defined in
interrupts.txt in this directory
- clocks: Must contain a reference to the functional clock.
@@ -0,0 +1,220 @@
This document describes the generic device tree binding for describing the
relationship between PCI devices and MSI controllers.
Each PCI device under a root complex is uniquely identified by its Requester ID
(AKA RID). A Requester ID is a triplet of a Bus number, Device number, and
Function number.
For the purpose of this document, when treated as a numeric value, a RID is
formatted such that:
* Bits [15:8] are the Bus number.
* Bits [7:3] are the Device number.
* Bits [2:0] are the Function number.
* Any other bits required for padding must be zero.
MSIs may be distinguished in part through the use of sideband data accompanying
writes. In the case of PCI devices, this sideband data may be derived from the
Requester ID. A mechanism is required to associate a device with both the MSI
controllers it can address, and the sideband data that will be associated with
its writes to those controllers.
For generic MSI bindings, see
Documentation/devicetree/bindings/interrupt-controller/msi.txt.
PCI root complex
================
Optional properties
-------------------
- msi-map: Maps a Requester ID to an MSI controller and associated
msi-specifier data. The property is an arbitrary number of tuples of
(rid-base,msi-controller,msi-base,length), where:
* rid-base is a single cell describing the first RID matched by the entry.
* msi-controller is a single phandle to an MSI controller
* msi-base is an msi-specifier describing the msi-specifier produced for the
first RID matched by the entry.
* length is a single cell describing how many consecutive RIDs are matched
following the rid-base.
Any RID r in the interval [rid-base, rid-base + length) is associated with
the listed msi-controller, with the msi-specifier (r - rid-base + msi-base).
- msi-map-mask: A mask to be applied to each Requester ID prior to being mapped
to an msi-specifier per the msi-map property.
- msi-parent: Describes the MSI parent of the root complex itself. Where
the root complex and MSI controller do not pass sideband data with MSI
writes, this property may be used to describe the MSI controller(s)
used by PCI devices under the root complex, if defined as such in the
binding for the root complex.
Example (1)
===========
/ {
#address-cells = <1>;
#size-cells = <1>;
msi: msi-controller@a {
reg = <0xa 0x1>;
compatible = "vendor,some-controller";
msi-controller;
#msi-cells = <1>;
};
pci: pci@f {
reg = <0xf 0x1>;
compatible = "vendor,pcie-root-complex";
device_type = "pci";
/*
* The sideband data provided to the MSI controller is
* the RID, identity-mapped.
*/
msi-map = <0x0 &msi_a 0x0 0x10000>,
};
};
Example (2)
===========
/ {
#address-cells = <1>;
#size-cells = <1>;
msi: msi-controller@a {
reg = <0xa 0x1>;
compatible = "vendor,some-controller";
msi-controller;
#msi-cells = <1>;
};
pci: pci@f {
reg = <0xf 0x1>;
compatible = "vendor,pcie-root-complex";
device_type = "pci";
/*
* The sideband data provided to the MSI controller is
* the RID, masked to only the device and function bits.
*/
msi-map = <0x0 &msi_a 0x0 0x100>,
msi-map-mask = <0xff>
};
};
Example (3)
===========
/ {
#address-cells = <1>;
#size-cells = <1>;
msi: msi-controller@a {
reg = <0xa 0x1>;
compatible = "vendor,some-controller";
msi-controller;
#msi-cells = <1>;
};
pci: pci@f {
reg = <0xf 0x1>;
compatible = "vendor,pcie-root-complex";
device_type = "pci";
/*
* The sideband data provided to the MSI controller is
* the RID, but the high bit of the bus number is
* ignored.
*/
msi-map = <0x0000 &msi 0x0000 0x8000>,
<0x8000 &msi 0x0000 0x8000>;
};
};
Example (4)
===========
/ {
#address-cells = <1>;
#size-cells = <1>;
msi: msi-controller@a {
reg = <0xa 0x1>;
compatible = "vendor,some-controller";
msi-controller;
#msi-cells = <1>;
};
pci: pci@f {
reg = <0xf 0x1>;
compatible = "vendor,pcie-root-complex";
device_type = "pci";
/*
* The sideband data provided to the MSI controller is
* the RID, but the high bit of the bus number is
* negated.
*/
msi-map = <0x0000 &msi 0x8000 0x8000>,
<0x8000 &msi 0x0000 0x8000>;
};
};
Example (5)
===========
/ {
#address-cells = <1>;
#size-cells = <1>;
msi_a: msi-controller@a {
reg = <0xa 0x1>;
compatible = "vendor,some-controller";
msi-controller;
#msi-cells = <1>;
};
msi_b: msi-controller@b {
reg = <0xb 0x1>;
compatible = "vendor,some-controller";
msi-controller;
#msi-cells = <1>;
};
msi_c: msi-controller@c {
reg = <0xc 0x1>;
compatible = "vendor,some-controller";
msi-controller;
#msi-cells = <1>;
};
pci: pci@c {
reg = <0xf 0x1>;
compatible = "vendor,pcie-root-complex";
device_type = "pci";
/*
* The sideband data provided to MSI controller a is the
* RID, but the high bit of the bus number is negated.
* The sideband data provided to MSI controller b is the
* RID, identity-mapped.
* MSI controller c is not addressable.
*/
msi-map = <0x0000 &msi_a 0x8000 0x08000>,
<0x8000 &msi_a 0x0000 0x08000>,
<0x0000 &msi_b 0x0000 0x10000>;
};
};
+1
View File
@@ -820,6 +820,7 @@ config ARCH_VIRT
bool "Dummy Virtual Machine" if ARCH_MULTI_V7
select ARM_AMBA
select ARM_GIC
select ARM_GIC_V3
select ARM_PSCI
select HAVE_ARM_ARCH_TIMER
+188
View File
@@ -0,0 +1,188 @@
/*
* arch/arm/include/asm/arch_gicv3.h
*
* Copyright (C) 2015 ARM Ltd.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __ASM_ARCH_GICV3_H
#define __ASM_ARCH_GICV3_H
#ifndef __ASSEMBLY__
#include <linux/io.h>
#define __ACCESS_CP15(CRn, Op1, CRm, Op2) p15, Op1, %0, CRn, CRm, Op2
#define __ACCESS_CP15_64(Op1, CRm) p15, Op1, %Q0, %R0, CRm
#define ICC_EOIR1 __ACCESS_CP15(c12, 0, c12, 1)
#define ICC_DIR __ACCESS_CP15(c12, 0, c11, 1)
#define ICC_IAR1 __ACCESS_CP15(c12, 0, c12, 0)
#define ICC_SGI1R __ACCESS_CP15_64(0, c12)
#define ICC_PMR __ACCESS_CP15(c4, 0, c6, 0)
#define ICC_CTLR __ACCESS_CP15(c12, 0, c12, 4)
#define ICC_SRE __ACCESS_CP15(c12, 0, c12, 5)
#define ICC_IGRPEN1 __ACCESS_CP15(c12, 0, c12, 7)
#define ICC_HSRE __ACCESS_CP15(c12, 4, c9, 5)
#define ICH_VSEIR __ACCESS_CP15(c12, 4, c9, 4)
#define ICH_HCR __ACCESS_CP15(c12, 4, c11, 0)
#define ICH_VTR __ACCESS_CP15(c12, 4, c11, 1)
#define ICH_MISR __ACCESS_CP15(c12, 4, c11, 2)
#define ICH_EISR __ACCESS_CP15(c12, 4, c11, 3)
#define ICH_ELSR __ACCESS_CP15(c12, 4, c11, 5)
#define ICH_VMCR __ACCESS_CP15(c12, 4, c11, 7)
#define __LR0(x) __ACCESS_CP15(c12, 4, c12, x)
#define __LR8(x) __ACCESS_CP15(c12, 4, c13, x)
#define ICH_LR0 __LR0(0)
#define ICH_LR1 __LR0(1)
#define ICH_LR2 __LR0(2)
#define ICH_LR3 __LR0(3)
#define ICH_LR4 __LR0(4)
#define ICH_LR5 __LR0(5)
#define ICH_LR6 __LR0(6)
#define ICH_LR7 __LR0(7)
#define ICH_LR8 __LR8(0)
#define ICH_LR9 __LR8(1)
#define ICH_LR10 __LR8(2)
#define ICH_LR11 __LR8(3)
#define ICH_LR12 __LR8(4)
#define ICH_LR13 __LR8(5)
#define ICH_LR14 __LR8(6)
#define ICH_LR15 __LR8(7)
/* LR top half */
#define __LRC0(x) __ACCESS_CP15(c12, 4, c14, x)
#define __LRC8(x) __ACCESS_CP15(c12, 4, c15, x)
#define ICH_LRC0 __LRC0(0)
#define ICH_LRC1 __LRC0(1)
#define ICH_LRC2 __LRC0(2)
#define ICH_LRC3 __LRC0(3)
#define ICH_LRC4 __LRC0(4)
#define ICH_LRC5 __LRC0(5)
#define ICH_LRC6 __LRC0(6)
#define ICH_LRC7 __LRC0(7)
#define ICH_LRC8 __LRC8(0)
#define ICH_LRC9 __LRC8(1)
#define ICH_LRC10 __LRC8(2)
#define ICH_LRC11 __LRC8(3)
#define ICH_LRC12 __LRC8(4)
#define ICH_LRC13 __LRC8(5)
#define ICH_LRC14 __LRC8(6)
#define ICH_LRC15 __LRC8(7)
#define __AP0Rx(x) __ACCESS_CP15(c12, 4, c8, x)
#define ICH_AP0R0 __AP0Rx(0)
#define ICH_AP0R1 __AP0Rx(1)
#define ICH_AP0R2 __AP0Rx(2)
#define ICH_AP0R3 __AP0Rx(3)
#define __AP1Rx(x) __ACCESS_CP15(c12, 4, c9, x)
#define ICH_AP1R0 __AP1Rx(0)
#define ICH_AP1R1 __AP1Rx(1)
#define ICH_AP1R2 __AP1Rx(2)
#define ICH_AP1R3 __AP1Rx(3)
/* Low-level accessors */
static inline void gic_write_eoir(u32 irq)
{
asm volatile("mcr " __stringify(ICC_EOIR1) : : "r" (irq));
isb();
}
static inline void gic_write_dir(u32 val)
{
asm volatile("mcr " __stringify(ICC_DIR) : : "r" (val));
isb();
}
static inline u32 gic_read_iar(void)
{
u32 irqstat;
asm volatile("mrc " __stringify(ICC_IAR1) : "=r" (irqstat));
return irqstat;
}
static inline void gic_write_pmr(u32 val)
{
asm volatile("mcr " __stringify(ICC_PMR) : : "r" (val));
}
static inline void gic_write_ctlr(u32 val)
{
asm volatile("mcr " __stringify(ICC_CTLR) : : "r" (val));
isb();
}
static inline void gic_write_grpen1(u32 val)
{
asm volatile("mcr " __stringify(ICC_IGRPEN1) : : "r" (val));
isb();
}
static inline void gic_write_sgi1r(u64 val)
{
asm volatile("mcrr " __stringify(ICC_SGI1R) : : "r" (val));
}
static inline u32 gic_read_sre(void)
{
u32 val;
asm volatile("mrc " __stringify(ICC_SRE) : "=r" (val));
return val;
}
static inline void gic_write_sre(u32 val)
{
asm volatile("mcr " __stringify(ICC_SRE) : : "r" (val));
isb();
}
/*
* Even in 32bit systems that use LPAE, there is no guarantee that the I/O
* interface provides true 64bit atomic accesses, so using strd/ldrd doesn't
* make much sense.
* Moreover, 64bit I/O emulation is extremely difficult to implement on
* AArch32, since the syndrome register doesn't provide any information for
* them.
* Consequently, the following IO helpers use 32bit accesses.
*
* There are only two registers that need 64bit accesses in this driver:
* - GICD_IROUTERn, contain the affinity values associated to each interrupt.
* The upper-word (aff3) will always be 0, so there is no need for a lock.
* - GICR_TYPER is an ID register and doesn't need atomicity.
*/
static inline void gic_write_irouter(u64 val, volatile void __iomem *addr)
{
writel_relaxed((u32)val, addr);
writel_relaxed((u32)(val >> 32), addr + 4);
}
static inline u64 gic_read_typer(const volatile void __iomem *addr)
{
u64 val;
val = readl_relaxed(addr);
val |= (u64)readl_relaxed(addr + 4) << 32;
return val;
}
#endif /* !__ASSEMBLY__ */
#endif /* !__ASM_ARCH_GICV3_H */
+29 -26
View File
@@ -177,54 +177,57 @@ static struct irq_chip exynos_pmu_chip = {
#endif
};
static int exynos_pmu_domain_xlate(struct irq_domain *domain,
struct device_node *controller,
const u32 *intspec,
unsigned int intsize,
unsigned long *out_hwirq,
unsigned int *out_type)
static int exynos_pmu_domain_translate(struct irq_domain *d,
struct irq_fwspec *fwspec,
unsigned long *hwirq,
unsigned int *type)
{
if (domain->of_node != controller)
return -EINVAL; /* Shouldn't happen, really... */
if (intsize != 3)
return -EINVAL; /* Not GIC compliant */
if (intspec[0] != 0)
return -EINVAL; /* No PPI should point to this domain */
if (is_of_node(fwspec->fwnode)) {
if (fwspec->param_count != 3)
return -EINVAL;
*out_hwirq = intspec[1];
*out_type = intspec[2];
return 0;
/* No PPI should point to this domain */
if (fwspec->param[0] != 0)
return -EINVAL;
*hwirq = fwspec->param[1];
*type = fwspec->param[2];
return 0;
}
return -EINVAL;
}
static int exynos_pmu_domain_alloc(struct irq_domain *domain,
unsigned int virq,
unsigned int nr_irqs, void *data)
{
struct of_phandle_args *args = data;
struct of_phandle_args parent_args;
struct irq_fwspec *fwspec = data;
struct irq_fwspec parent_fwspec;
irq_hw_number_t hwirq;
int i;
if (args->args_count != 3)
if (fwspec->param_count != 3)
return -EINVAL; /* Not GIC compliant */
if (args->args[0] != 0)
if (fwspec->param[0] != 0)
return -EINVAL; /* No PPI should point to this domain */
hwirq = args->args[1];
hwirq = fwspec->param[1];
for (i = 0; i < nr_irqs; i++)
irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
&exynos_pmu_chip, NULL);
parent_args = *args;
parent_args.np = domain->parent->of_node;
return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &parent_args);
parent_fwspec = *fwspec;
parent_fwspec.fwnode = domain->parent->fwnode;
return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs,
&parent_fwspec);
}
static const struct irq_domain_ops exynos_pmu_domain_ops = {
.xlate = exynos_pmu_domain_xlate,
.alloc = exynos_pmu_domain_alloc,
.free = irq_domain_free_irqs_common,
.translate = exynos_pmu_domain_translate,
.alloc = exynos_pmu_domain_alloc,
.free = irq_domain_free_irqs_common,
};
static int __init exynos_pmu_irq_init(struct device_node *node,
+29 -26
View File
@@ -181,40 +181,42 @@ static struct irq_chip imx_gpc_chip = {
#endif
};
static int imx_gpc_domain_xlate(struct irq_domain *domain,
struct device_node *controller,
const u32 *intspec,
unsigned int intsize,
unsigned long *out_hwirq,
unsigned int *out_type)
static int imx_gpc_domain_translate(struct irq_domain *d,
struct irq_fwspec *fwspec,
unsigned long *hwirq,
unsigned int *type)
{
if (domain->of_node != controller)
return -EINVAL; /* Shouldn't happen, really... */
if (intsize != 3)
return -EINVAL; /* Not GIC compliant */
if (intspec[0] != 0)
return -EINVAL; /* No PPI should point to this domain */
if (is_of_node(fwspec->fwnode)) {
if (fwspec->param_count != 3)
return -EINVAL;
*out_hwirq = intspec[1];
*out_type = intspec[2];
return 0;
/* No PPI should point to this domain */
if (fwspec->param[0] != 0)
return -EINVAL;
*hwirq = fwspec->param[1];
*type = fwspec->param[2];
return 0;
}
return -EINVAL;
}
static int imx_gpc_domain_alloc(struct irq_domain *domain,
unsigned int irq,
unsigned int nr_irqs, void *data)
{
struct of_phandle_args *args = data;
struct of_phandle_args parent_args;
struct irq_fwspec *fwspec = data;
struct irq_fwspec parent_fwspec;
irq_hw_number_t hwirq;
int i;
if (args->args_count != 3)
if (fwspec->param_count != 3)
return -EINVAL; /* Not GIC compliant */
if (args->args[0] != 0)
if (fwspec->param[0] != 0)
return -EINVAL; /* No PPI should point to this domain */
hwirq = args->args[1];
hwirq = fwspec->param[1];
if (hwirq >= GPC_MAX_IRQS)
return -EINVAL; /* Can't deal with this */
@@ -222,15 +224,16 @@ static int imx_gpc_domain_alloc(struct irq_domain *domain,
irq_domain_set_hwirq_and_chip(domain, irq + i, hwirq + i,
&imx_gpc_chip, NULL);
parent_args = *args;
parent_args.np = domain->parent->of_node;
return irq_domain_alloc_irqs_parent(domain, irq, nr_irqs, &parent_args);
parent_fwspec = *fwspec;
parent_fwspec.fwnode = domain->parent->fwnode;
return irq_domain_alloc_irqs_parent(domain, irq, nr_irqs,
&parent_fwspec);
}
static const struct irq_domain_ops imx_gpc_domain_ops = {
.xlate = imx_gpc_domain_xlate,
.alloc = imx_gpc_domain_alloc,
.free = irq_domain_free_irqs_common,
.translate = imx_gpc_domain_translate,
.alloc = imx_gpc_domain_alloc,
.free = irq_domain_free_irqs_common,
};
static int __init imx_gpc_init(struct device_node *node,
+29 -26
View File
@@ -399,40 +399,42 @@ static struct irq_chip wakeupgen_chip = {
#endif
};
static int wakeupgen_domain_xlate(struct irq_domain *domain,
struct device_node *controller,
const u32 *intspec,
unsigned int intsize,
unsigned long *out_hwirq,
unsigned int *out_type)
static int wakeupgen_domain_translate(struct irq_domain *d,
struct irq_fwspec *fwspec,
unsigned long *hwirq,
unsigned int *type)
{
if (domain->of_node != controller)
return -EINVAL; /* Shouldn't happen, really... */
if (intsize != 3)
return -EINVAL; /* Not GIC compliant */
if (intspec[0] != 0)
return -EINVAL; /* No PPI should point to this domain */
if (is_of_node(fwspec->fwnode)) {
if (fwspec->param_count != 3)
return -EINVAL;
*out_hwirq = intspec[1];
*out_type = intspec[2];
return 0;
/* No PPI should point to this domain */
if (fwspec->param[0] != 0)
return -EINVAL;
*hwirq = fwspec->param[1];
*type = fwspec->param[2];
return 0;
}
return -EINVAL;
}
static int wakeupgen_domain_alloc(struct irq_domain *domain,
unsigned int virq,
unsigned int nr_irqs, void *data)
{
struct of_phandle_args *args = data;
struct of_phandle_args parent_args;
struct irq_fwspec *fwspec = data;
struct irq_fwspec parent_fwspec;
irq_hw_number_t hwirq;
int i;
if (args->args_count != 3)
if (fwspec->param_count != 3)
return -EINVAL; /* Not GIC compliant */
if (args->args[0] != 0)
if (fwspec->param[0] != 0)
return -EINVAL; /* No PPI should point to this domain */
hwirq = args->args[1];
hwirq = fwspec->param[1];
if (hwirq >= MAX_IRQS)
return -EINVAL; /* Can't deal with this */
@@ -440,15 +442,16 @@ static int wakeupgen_domain_alloc(struct irq_domain *domain,
irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
&wakeupgen_chip, NULL);
parent_args = *args;
parent_args.np = domain->parent->of_node;
return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &parent_args);
parent_fwspec = *fwspec;
parent_fwspec.fwnode = domain->parent->fwnode;
return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs,
&parent_fwspec);
}
static const struct irq_domain_ops wakeupgen_domain_ops = {
.xlate = wakeupgen_domain_xlate,
.alloc = wakeupgen_domain_alloc,
.free = irq_domain_free_irqs_common,
.translate = wakeupgen_domain_translate,
.alloc = wakeupgen_domain_alloc,
.free = irq_domain_free_irqs_common,
};
/*
+27
View File
@@ -348,6 +348,33 @@ config ARM64_ERRATUM_843419
If unsure, say Y.
config CAVIUM_ERRATUM_22375
bool "Cavium erratum 22375, 24313"
default y
help
Enable workaround for erratum 22375, 24313.
This implements two gicv3-its errata workarounds for ThunderX. Both
with small impact affecting only ITS table allocation.
erratum 22375: only alloc 8MB table size
erratum 24313: ignore memory access type
The fixes are in ITS initialization and basically ignore memory access
type and table size provided by the TYPER and BASER registers.
If unsure, say Y.
config CAVIUM_ERRATUM_23154
bool "Cavium erratum 23154: Access to ICC_IAR1_EL1 is not sync'ed"
default y
help
The gicv3 of ThunderX requires a modified version for
reading the IAR status to ensure data synchronization
(access to icc_iar1_el1 is not sync'ed before and after).
If unsure, say Y.
endmenu
+170
View File
@@ -0,0 +1,170 @@
/*
* arch/arm64/include/asm/arch_gicv3.h
*
* Copyright (C) 2015 ARM Ltd.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __ASM_ARCH_GICV3_H
#define __ASM_ARCH_GICV3_H
#include <asm/sysreg.h>
#define ICC_EOIR1_EL1 sys_reg(3, 0, 12, 12, 1)
#define ICC_DIR_EL1 sys_reg(3, 0, 12, 11, 1)
#define ICC_IAR1_EL1 sys_reg(3, 0, 12, 12, 0)
#define ICC_SGI1R_EL1 sys_reg(3, 0, 12, 11, 5)
#define ICC_PMR_EL1 sys_reg(3, 0, 4, 6, 0)
#define ICC_CTLR_EL1 sys_reg(3, 0, 12, 12, 4)
#define ICC_SRE_EL1 sys_reg(3, 0, 12, 12, 5)
#define ICC_GRPEN1_EL1 sys_reg(3, 0, 12, 12, 7)
#define ICC_SRE_EL2 sys_reg(3, 4, 12, 9, 5)
/*
* System register definitions
*/
#define ICH_VSEIR_EL2 sys_reg(3, 4, 12, 9, 4)
#define ICH_HCR_EL2 sys_reg(3, 4, 12, 11, 0)
#define ICH_VTR_EL2 sys_reg(3, 4, 12, 11, 1)
#define ICH_MISR_EL2 sys_reg(3, 4, 12, 11, 2)
#define ICH_EISR_EL2 sys_reg(3, 4, 12, 11, 3)
#define ICH_ELSR_EL2 sys_reg(3, 4, 12, 11, 5)
#define ICH_VMCR_EL2 sys_reg(3, 4, 12, 11, 7)
#define __LR0_EL2(x) sys_reg(3, 4, 12, 12, x)
#define __LR8_EL2(x) sys_reg(3, 4, 12, 13, x)
#define ICH_LR0_EL2 __LR0_EL2(0)
#define ICH_LR1_EL2 __LR0_EL2(1)
#define ICH_LR2_EL2 __LR0_EL2(2)
#define ICH_LR3_EL2 __LR0_EL2(3)
#define ICH_LR4_EL2 __LR0_EL2(4)
#define ICH_LR5_EL2 __LR0_EL2(5)
#define ICH_LR6_EL2 __LR0_EL2(6)
#define ICH_LR7_EL2 __LR0_EL2(7)
#define ICH_LR8_EL2 __LR8_EL2(0)
#define ICH_LR9_EL2 __LR8_EL2(1)
#define ICH_LR10_EL2 __LR8_EL2(2)
#define ICH_LR11_EL2 __LR8_EL2(3)
#define ICH_LR12_EL2 __LR8_EL2(4)
#define ICH_LR13_EL2 __LR8_EL2(5)
#define ICH_LR14_EL2 __LR8_EL2(6)
#define ICH_LR15_EL2 __LR8_EL2(7)
#define __AP0Rx_EL2(x) sys_reg(3, 4, 12, 8, x)
#define ICH_AP0R0_EL2 __AP0Rx_EL2(0)
#define ICH_AP0R1_EL2 __AP0Rx_EL2(1)
#define ICH_AP0R2_EL2 __AP0Rx_EL2(2)
#define ICH_AP0R3_EL2 __AP0Rx_EL2(3)
#define __AP1Rx_EL2(x) sys_reg(3, 4, 12, 9, x)
#define ICH_AP1R0_EL2 __AP1Rx_EL2(0)
#define ICH_AP1R1_EL2 __AP1Rx_EL2(1)
#define ICH_AP1R2_EL2 __AP1Rx_EL2(2)
#define ICH_AP1R3_EL2 __AP1Rx_EL2(3)
#ifndef __ASSEMBLY__
#include <linux/stringify.h>
/*
* Low-level accessors
*
* These system registers are 32 bits, but we make sure that the compiler
* sets the GP register's most significant bits to 0 with an explicit cast.
*/
static inline void gic_write_eoir(u32 irq)
{
asm volatile("msr_s " __stringify(ICC_EOIR1_EL1) ", %0" : : "r" ((u64)irq));
isb();
}
static inline void gic_write_dir(u32 irq)
{
asm volatile("msr_s " __stringify(ICC_DIR_EL1) ", %0" : : "r" ((u64)irq));
isb();
}
static inline u64 gic_read_iar_common(void)
{
u64 irqstat;
asm volatile("mrs_s %0, " __stringify(ICC_IAR1_EL1) : "=r" (irqstat));
return irqstat;
}
/*
* Cavium ThunderX erratum 23154
*
* The gicv3 of ThunderX requires a modified version for reading the
* IAR status to ensure data synchronization (access to icc_iar1_el1
* is not sync'ed before and after).
*/
static inline u64 gic_read_iar_cavium_thunderx(void)
{
u64 irqstat;
asm volatile(
"nop;nop;nop;nop\n\t"
"nop;nop;nop;nop\n\t"
"mrs_s %0, " __stringify(ICC_IAR1_EL1) "\n\t"
"nop;nop;nop;nop"
: "=r" (irqstat));
mb();
return irqstat;
}
static inline void gic_write_pmr(u32 val)
{
asm volatile("msr_s " __stringify(ICC_PMR_EL1) ", %0" : : "r" ((u64)val));
}
static inline void gic_write_ctlr(u32 val)
{
asm volatile("msr_s " __stringify(ICC_CTLR_EL1) ", %0" : : "r" ((u64)val));
isb();
}
static inline void gic_write_grpen1(u32 val)
{
asm volatile("msr_s " __stringify(ICC_GRPEN1_EL1) ", %0" : : "r" ((u64)val));
isb();
}
static inline void gic_write_sgi1r(u64 val)
{
asm volatile("msr_s " __stringify(ICC_SGI1R_EL1) ", %0" : : "r" (val));
}
static inline u32 gic_read_sre(void)
{
u64 val;
asm volatile("mrs_s %0, " __stringify(ICC_SRE_EL1) : "=r" (val));
return val;
}
static inline void gic_write_sre(u32 val)
{
asm volatile("msr_s " __stringify(ICC_SRE_EL1) ", %0" : : "r" ((u64)val));
isb();
}
#define gic_read_typer(c) readq_relaxed(c)
#define gic_write_irouter(v, c) writeq_relaxed(v, c)
#endif /* __ASSEMBLY__ */
#endif /* __ASM_ARCH_GICV3_H */
+2 -1
View File
@@ -27,8 +27,9 @@
#define ARM64_HAS_SYSREG_GIC_CPUIF 3
#define ARM64_HAS_PAN 4
#define ARM64_HAS_LSE_ATOMICS 5
#define ARM64_WORKAROUND_CAVIUM_23154 6
#define ARM64_NCAPS 6
#define ARM64_NCAPS 7
#ifndef __ASSEMBLY__
+10 -7
View File
@@ -62,15 +62,18 @@
(0xf << MIDR_ARCHITECTURE_SHIFT) | \
((partnum) << MIDR_PARTNUM_SHIFT))
#define ARM_CPU_IMP_ARM 0x41
#define ARM_CPU_IMP_APM 0x50
#define ARM_CPU_IMP_ARM 0x41
#define ARM_CPU_IMP_APM 0x50
#define ARM_CPU_IMP_CAVIUM 0x43
#define ARM_CPU_PART_AEM_V8 0xD0F
#define ARM_CPU_PART_FOUNDATION 0xD00
#define ARM_CPU_PART_CORTEX_A57 0xD07
#define ARM_CPU_PART_CORTEX_A53 0xD03
#define ARM_CPU_PART_AEM_V8 0xD0F
#define ARM_CPU_PART_FOUNDATION 0xD00
#define ARM_CPU_PART_CORTEX_A57 0xD07
#define ARM_CPU_PART_CORTEX_A53 0xD03
#define APM_CPU_PART_POTENZA 0x000
#define APM_CPU_PART_POTENZA 0x000
#define CAVIUM_CPU_PART_THUNDERX 0x0A1
#define ID_AA64MMFR0_BIGENDEL0_SHIFT 16
#define ID_AA64MMFR0_BIGENDEL0_MASK (0xf << ID_AA64MMFR0_BIGENDEL0_SHIFT)
+9
View File
@@ -23,6 +23,7 @@
#define MIDR_CORTEX_A53 MIDR_CPU_PART(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A53)
#define MIDR_CORTEX_A57 MIDR_CPU_PART(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A57)
#define MIDR_THUNDERX MIDR_CPU_PART(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX)
#define CPU_MODEL_MASK (MIDR_IMPLEMENTOR_MASK | MIDR_PARTNUM_MASK | \
MIDR_ARCHITECTURE_MASK)
@@ -81,6 +82,14 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
.capability = ARM64_WORKAROUND_845719,
MIDR_RANGE(MIDR_CORTEX_A53, 0x00, 0x04),
},
#endif
#ifdef CONFIG_CAVIUM_ERRATUM_23154
{
/* Cavium ThunderX, pass 1.x */
.desc = "Cavium erratum 23154",
.capability = ARM64_WORKAROUND_CAVIUM_23154,
MIDR_RANGE(MIDR_THUNDERX, 0x00, 0x01),
},
#endif
{
}
+18 -1
View File
@@ -23,6 +23,8 @@
#include <asm/cpufeature.h>
#include <asm/processor.h>
#include <linux/irqchip/arm-gic-v3.h>
static bool
feature_matches(u64 reg, const struct arm64_cpu_capabilities *entry)
{
@@ -45,11 +47,26 @@ __ID_FEAT_CHK(id_aa64pfr0);
__ID_FEAT_CHK(id_aa64mmfr1);
__ID_FEAT_CHK(id_aa64isar0);
static bool has_useable_gicv3_cpuif(const struct arm64_cpu_capabilities *entry)
{
bool has_sre;
if (!has_id_aa64pfr0_feature(entry))
return false;
has_sre = gic_enable_sre();
if (!has_sre)
pr_warn_once("%s present but disabled by higher exception level\n",
entry->desc);
return has_sre;
}
static const struct arm64_cpu_capabilities arm64_features[] = {
{
.desc = "GIC system register CPU interface",
.capability = ARM64_HAS_SYSREG_GIC_CPUIF,
.matches = has_id_aa64pfr0_feature,
.matches = has_useable_gicv3_cpuif,
.field_pos = 24,
.min_field_value = 1,
},
+2
View File
@@ -498,6 +498,8 @@ CPU_LE( bic x0, x0, #(3 << 24) ) // Clear the EE and E0E bits for EL1
orr x0, x0, #ICC_SRE_EL2_ENABLE // Set ICC_SRE_EL2.Enable==1
msr_s ICC_SRE_EL2, x0
isb // Make sure SRE is now set
mrs_s x0, ICC_SRE_EL2 // Read SRE back,
tbz x0, #0, 3f // and check that it sticks
msr_s ICH_HCR_EL2, xzr // Reset ICC_HCR_EL2 to defaults
3:
+4
View File
@@ -16,6 +16,9 @@ menuconfig VIRTUALIZATION
if VIRTUALIZATION
config KVM_ARM_VGIC_V3
bool
config KVM
bool "Kernel-based Virtual Machine (KVM) support"
depends on OF
@@ -31,6 +34,7 @@ config KVM
select KVM_VFIO
select HAVE_KVM_EVENTFD
select HAVE_KVM_IRQFD
select KVM_ARM_VGIC_V3
---help---
Support hosting virtualized guest machines.
+1 -1
View File
@@ -178,7 +178,7 @@ static void __init set_megamod_mux(struct megamod_pic *pic, int src, int output)
static void __init parse_priority_map(struct megamod_pic *pic,
int *mapping, int size)
{
struct device_node *np = pic->irqhost->of_node;
struct device_node *np = irq_domain_get_of_node(pic->irqhost);
const __be32 *map;
int i, maplen;
u32 val;
+2 -2
View File
@@ -1094,7 +1094,7 @@ static int octeon_irq_gpio_xlat(struct irq_domain *d,
unsigned int pin;
unsigned int trigger;
if (d->of_node != node)
if (irq_domain_get_of_node(d) != node)
return -EINVAL;
if (intsize < 2)
@@ -2163,7 +2163,7 @@ static int octeon_irq_cib_map(struct irq_domain *d,
if (hw >= host_data->max_bits) {
pr_err("ERROR: %s mapping %u is to big!\n",
d->of_node->name, (unsigned)hw);
irq_domain_get_of_node(d)->name, (unsigned)hw);
return -EINVAL;
}
Loaded 20 of 90 files, more files were not shown because too many files have changed in this diff. Show more