mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
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:
commit
6aa2fdb87c
90 files changed
+2577
-890
No files matched your search
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>;
|
||||
};
|
||||
};
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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 */
|
||||
@@ -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
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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 */
|
||||
@@ -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__
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
{
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
Reference in new issue
Block a user