mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-18 02:04:05 +08:00
Merge branch irq/gic-v3-5.19 into irq/irqchip-next
* irq/gic-v3-5.19: : . : Misc improvements for GICv3: : : - Minimise the number of cases where we need to poll RWP : : - Allow the use of MMIO-based invalidation for LPIs : : - Track GICD/GICR mappings in /proc/iomem : : - Tighten the GICv3 DT binding to avoid endless discussions : on the list... : . irqchip/gic-v3: Claim iomem resources dt-bindings: interrupt-controller: arm,gic-v3: Make the v2 compat requirements explicit irqchip/gic-v3: Relax polling of GIC{R,D}_CTLR.RWP irqchip/gic-v3: Detect LPI invalidation MMIO registers irqchip/gic-v3: Exposes bit values for GICR_CTLR.{IR, CES} Signed-off-by: Marc Zyngier <maz@kernel.org>
This commit is contained in:
commit
a6ad8551b8
@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
title: ARM Generic Interrupt Controller, version 3
|
||||
|
||||
maintainers:
|
||||
- Marc Zyngier <marc.zyngier@arm.com>
|
||||
- Marc Zyngier <maz@kernel.org>
|
||||
|
||||
description: |
|
||||
AArch64 SMP cores are often associated with a GICv3, providing Private
|
||||
@ -78,7 +78,11 @@ properties:
|
||||
- GIC Hypervisor interface (GICH)
|
||||
- GIC Virtual CPU interface (GICV)
|
||||
|
||||
GICC, GICH and GICV are optional.
|
||||
GICC, GICH and GICV are optional, but must be described if the CPUs
|
||||
support them. Examples of such CPUs are ARM's implementations of the
|
||||
ARMv8.0 architecture such as Cortex-A32, A34, A35, A53, A57, A72 and
|
||||
A73 (this list is not exhaustive).
|
||||
|
||||
minItems: 2
|
||||
maxItems: 4096 # Should be enough?
|
||||
|
||||
|
@ -352,28 +352,27 @@ static int gic_peek_irq(struct irq_data *d, u32 offset)
|
||||
|
||||
static void gic_poke_irq(struct irq_data *d, u32 offset)
|
||||
{
|
||||
void (*rwp_wait)(void);
|
||||
void __iomem *base;
|
||||
u32 index, mask;
|
||||
|
||||
offset = convert_offset_index(d, offset, &index);
|
||||
mask = 1 << (index % 32);
|
||||
|
||||
if (gic_irq_in_rdist(d)) {
|
||||
if (gic_irq_in_rdist(d))
|
||||
base = gic_data_rdist_sgi_base();
|
||||
rwp_wait = gic_redist_wait_for_rwp;
|
||||
} else {
|
||||
else
|
||||
base = gic_data.dist_base;
|
||||
rwp_wait = gic_dist_wait_for_rwp;
|
||||
}
|
||||
|
||||
writel_relaxed(mask, base + offset + (index / 32) * 4);
|
||||
rwp_wait();
|
||||
}
|
||||
|
||||
static void gic_mask_irq(struct irq_data *d)
|
||||
{
|
||||
gic_poke_irq(d, GICD_ICENABLER);
|
||||
if (gic_irq_in_rdist(d))
|
||||
gic_redist_wait_for_rwp();
|
||||
else
|
||||
gic_dist_wait_for_rwp();
|
||||
}
|
||||
|
||||
static void gic_eoimode1_mask_irq(struct irq_data *d)
|
||||
@ -420,7 +419,11 @@ static int gic_irq_set_irqchip_state(struct irq_data *d,
|
||||
break;
|
||||
|
||||
case IRQCHIP_STATE_MASKED:
|
||||
reg = val ? GICD_ICENABLER : GICD_ISENABLER;
|
||||
if (val) {
|
||||
gic_mask_irq(d);
|
||||
return 0;
|
||||
}
|
||||
reg = GICD_ISENABLER;
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -574,7 +577,6 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
|
||||
{
|
||||
enum gic_intid_range range;
|
||||
unsigned int irq = gic_irq(d);
|
||||
void (*rwp_wait)(void);
|
||||
void __iomem *base;
|
||||
u32 offset, index;
|
||||
int ret;
|
||||
@ -590,17 +592,14 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
|
||||
type != IRQ_TYPE_LEVEL_HIGH && type != IRQ_TYPE_EDGE_RISING)
|
||||
return -EINVAL;
|
||||
|
||||
if (gic_irq_in_rdist(d)) {
|
||||
if (gic_irq_in_rdist(d))
|
||||
base = gic_data_rdist_sgi_base();
|
||||
rwp_wait = gic_redist_wait_for_rwp;
|
||||
} else {
|
||||
else
|
||||
base = gic_data.dist_base;
|
||||
rwp_wait = gic_dist_wait_for_rwp;
|
||||
}
|
||||
|
||||
offset = convert_offset_index(d, GICD_ICFGR, &index);
|
||||
|
||||
ret = gic_configure_irq(index, type, base + offset, rwp_wait);
|
||||
ret = gic_configure_irq(index, type, base + offset, NULL);
|
||||
if (ret && (range == PPI_RANGE || range == EPPI_RANGE)) {
|
||||
/* Misconfigured PPIs are usually not fatal */
|
||||
pr_warn("GIC: PPI INTID%d is secure or misconfigured\n", irq);
|
||||
@ -807,8 +806,8 @@ static void __init gic_dist_init(void)
|
||||
for (i = 0; i < GIC_ESPI_NR; i += 4)
|
||||
writel_relaxed(GICD_INT_DEF_PRI_X4, base + GICD_IPRIORITYRnE + i);
|
||||
|
||||
/* Now do the common stuff, and wait for the distributor to drain */
|
||||
gic_dist_config(base, GIC_LINE_NR, gic_dist_wait_for_rwp);
|
||||
/* Now do the common stuff */
|
||||
gic_dist_config(base, GIC_LINE_NR, NULL);
|
||||
|
||||
val = GICD_CTLR_ARE_NS | GICD_CTLR_ENABLE_G1A | GICD_CTLR_ENABLE_G1;
|
||||
if (gic_data.rdists.gicd_typer2 & GICD_TYPER2_nASSGIcap) {
|
||||
@ -816,8 +815,9 @@ static void __init gic_dist_init(void)
|
||||
val |= GICD_CTLR_nASSGIreq;
|
||||
}
|
||||
|
||||
/* Enable distributor with ARE, Group1 */
|
||||
/* Enable distributor with ARE, Group1, and wait for it to drain */
|
||||
writel_relaxed(val, base + GICD_CTLR);
|
||||
gic_dist_wait_for_rwp();
|
||||
|
||||
/*
|
||||
* Set all global interrupts to the boot CPU only. ARE must be
|
||||
@ -919,6 +919,7 @@ static int __gic_update_rdist_properties(struct redist_region *region,
|
||||
void __iomem *ptr)
|
||||
{
|
||||
u64 typer = gic_read_typer(ptr + GICR_TYPER);
|
||||
u32 ctlr = readl_relaxed(ptr + GICR_CTLR);
|
||||
|
||||
/* Boot-time cleanip */
|
||||
if ((typer & GICR_TYPER_VLPIS) && (typer & GICR_TYPER_RVPEID)) {
|
||||
@ -938,9 +939,18 @@ static int __gic_update_rdist_properties(struct redist_region *region,
|
||||
|
||||
gic_data.rdists.has_vlpis &= !!(typer & GICR_TYPER_VLPIS);
|
||||
|
||||
/* RVPEID implies some form of DirectLPI, no matter what the doc says... :-/ */
|
||||
/*
|
||||
* TYPER.RVPEID implies some form of DirectLPI, no matter what the
|
||||
* doc says... :-/ And CTLR.IR implies another subset of DirectLPI
|
||||
* that the ITS driver can make use of for LPIs (and not VLPIs).
|
||||
*
|
||||
* These are 3 different ways to express the same thing, depending
|
||||
* on the revision of the architecture and its relaxations over
|
||||
* time. Just group them under the 'direct_lpi' banner.
|
||||
*/
|
||||
gic_data.rdists.has_rvpeid &= !!(typer & GICR_TYPER_RVPEID);
|
||||
gic_data.rdists.has_direct_lpi &= (!!(typer & GICR_TYPER_DirectLPIS) |
|
||||
!!(ctlr & GICR_CTLR_IR) |
|
||||
gic_data.rdists.has_rvpeid);
|
||||
gic_data.rdists.has_vpend_valid_dirty &= !!(typer & GICR_TYPER_DIRTY);
|
||||
|
||||
@ -962,7 +972,11 @@ static void gic_update_rdist_properties(void)
|
||||
gic_iterate_rdists(__gic_update_rdist_properties);
|
||||
if (WARN_ON(gic_data.ppi_nr == UINT_MAX))
|
||||
gic_data.ppi_nr = 0;
|
||||
pr_info("%d PPIs implemented\n", gic_data.ppi_nr);
|
||||
pr_info("GICv3 features: %d PPIs%s%s\n",
|
||||
gic_data.ppi_nr,
|
||||
gic_data.has_rss ? ", RSS" : "",
|
||||
gic_data.rdists.has_direct_lpi ? ", DirectLPI" : "");
|
||||
|
||||
if (gic_data.rdists.has_vlpis)
|
||||
pr_info("GICv4 features: %s%s%s\n",
|
||||
gic_data.rdists.has_direct_lpi ? "DirectLPI " : "",
|
||||
@ -1284,8 +1298,6 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
|
||||
*/
|
||||
if (enabled)
|
||||
gic_unmask_irq(d);
|
||||
else
|
||||
gic_dist_wait_for_rwp();
|
||||
|
||||
irq_data_update_effective_affinity(d, cpumask_of(cpu));
|
||||
|
||||
@ -1803,8 +1815,6 @@ static int __init gic_init_bases(void __iomem *dist_base,
|
||||
irq_domain_update_bus_token(gic_data.domain, DOMAIN_BUS_WIRED);
|
||||
|
||||
gic_data.has_rss = !!(typer & GICD_TYPER_RSS);
|
||||
pr_info("Distributor has %sRange Selector support\n",
|
||||
gic_data.has_rss ? "" : "no ");
|
||||
|
||||
if (typer & GICD_TYPER_MBIS) {
|
||||
err = mbi_init(handle, gic_data.domain);
|
||||
@ -1980,10 +1990,10 @@ static int __init gic_of_init(struct device_node *node, struct device_node *pare
|
||||
u32 nr_redist_regions;
|
||||
int err, i;
|
||||
|
||||
dist_base = of_iomap(node, 0);
|
||||
if (!dist_base) {
|
||||
dist_base = of_io_request_and_map(node, 0, "GICD");
|
||||
if (IS_ERR(dist_base)) {
|
||||
pr_err("%pOF: unable to map gic dist registers\n", node);
|
||||
return -ENXIO;
|
||||
return PTR_ERR(dist_base);
|
||||
}
|
||||
|
||||
err = gic_validate_dist_version(dist_base);
|
||||
@ -2007,8 +2017,8 @@ static int __init gic_of_init(struct device_node *node, struct device_node *pare
|
||||
int ret;
|
||||
|
||||
ret = of_address_to_resource(node, 1 + i, &res);
|
||||
rdist_regs[i].redist_base = of_iomap(node, 1 + i);
|
||||
if (ret || !rdist_regs[i].redist_base) {
|
||||
rdist_regs[i].redist_base = of_io_request_and_map(node, 1 + i, "GICR");
|
||||
if (ret || IS_ERR(rdist_regs[i].redist_base)) {
|
||||
pr_err("%pOF: couldn't map region %d\n", node, i);
|
||||
err = -ENODEV;
|
||||
goto out_unmap_rdist;
|
||||
@ -2034,7 +2044,7 @@ static int __init gic_of_init(struct device_node *node, struct device_node *pare
|
||||
|
||||
out_unmap_rdist:
|
||||
for (i = 0; i < nr_redist_regions; i++)
|
||||
if (rdist_regs[i].redist_base)
|
||||
if (rdist_regs[i].redist_base && !IS_ERR(rdist_regs[i].redist_base))
|
||||
iounmap(rdist_regs[i].redist_base);
|
||||
kfree(rdist_regs);
|
||||
out_unmap_dist:
|
||||
@ -2081,6 +2091,7 @@ gic_acpi_parse_madt_redist(union acpi_subtable_headers *header,
|
||||
pr_err("Couldn't map GICR region @%llx\n", redist->base_address);
|
||||
return -ENOMEM;
|
||||
}
|
||||
request_mem_region(redist->base_address, redist->length, "GICR");
|
||||
|
||||
gic_acpi_register_redist(redist->base_address, redist_base);
|
||||
return 0;
|
||||
@ -2103,6 +2114,7 @@ gic_acpi_parse_madt_gicc(union acpi_subtable_headers *header,
|
||||
redist_base = ioremap(gicc->gicr_base_address, size);
|
||||
if (!redist_base)
|
||||
return -ENOMEM;
|
||||
request_mem_region(gicc->gicr_base_address, size, "GICR");
|
||||
|
||||
gic_acpi_register_redist(gicc->gicr_base_address, redist_base);
|
||||
return 0;
|
||||
@ -2304,6 +2316,7 @@ gic_acpi_init(union acpi_subtable_headers *header, const unsigned long end)
|
||||
pr_err("Unable to map GICD registers\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
request_mem_region(dist->base_address, ACPI_GICV3_DIST_MEM_SIZE, "GICD");
|
||||
|
||||
err = gic_validate_dist_version(acpi_data.dist_base);
|
||||
if (err) {
|
||||
|
@ -127,6 +127,8 @@
|
||||
#define GICR_PIDR2 GICD_PIDR2
|
||||
|
||||
#define GICR_CTLR_ENABLE_LPIS (1UL << 0)
|
||||
#define GICR_CTLR_CES (1UL << 1)
|
||||
#define GICR_CTLR_IR (1UL << 2)
|
||||
#define GICR_CTLR_RWP (1UL << 3)
|
||||
|
||||
#define GICR_TYPER_CPU_NUMBER(r) (((r) >> 8) & 0xffff)
|
||||
|
Loading…
Reference in New Issue
Block a user