Skip to content

Commit

Permalink
Merge tag 'tags/deps-irqchip-gic-3.17' into irqchip/core
Browse files Browse the repository at this point in the history
From local branch irqchip/gic, this is topic branch that was set up to
facilitate merging other changes depending on the new GICv3 driver.
  • Loading branch information
Jason Cooper committed Jul 18, 2014
2 parents 885d078 + 021f653 commit 20c0c60
Show file tree
Hide file tree
Showing 10 changed files with 1,065 additions and 56 deletions.
1 change: 1 addition & 0 deletions arch/arm64/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ config ARM64
select ARM_AMBA
select ARM_ARCH_TIMER
select ARM_GIC
select ARM_GIC_V3
select BUILDTIME_EXTABLE_SORT
select CLONE_BACKWARDS
select COMMON_CLK
Expand Down
18 changes: 18 additions & 0 deletions arch/arm64/kernel/head.S
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

#include <linux/linkage.h>
#include <linux/init.h>
#include <linux/irqchip/arm-gic-v3.h>

#include <asm/assembler.h>
#include <asm/ptrace.h>
Expand Down Expand Up @@ -296,6 +297,23 @@ CPU_LE( bic x0, x0, #(3 << 24) ) // Clear the EE and E0E bits for EL1
msr cnthctl_el2, x0
msr cntvoff_el2, xzr // Clear virtual offset

#ifdef CONFIG_ARM_GIC_V3
/* GICv3 system register access */
mrs x0, id_aa64pfr0_el1
ubfx x0, x0, #24, #4
cmp x0, #1
b.ne 3f

mrs x0, ICC_SRE_EL2
orr x0, x0, #ICC_SRE_EL2_SRE // Set ICC_SRE_EL2.SRE==1
orr x0, x0, #ICC_SRE_EL2_ENABLE // Set ICC_SRE_EL2.Enable==1
msr ICC_SRE_EL2, x0
isb // Make sure SRE is now set
msr ICH_HCR_EL2, xzr // Reset ICC_HCR_EL2 to defaults

3:
#endif

/* Populate ID registers. */
mrs x0, midr_el1
mrs x1, mpidr_el1
Expand Down
1 change: 1 addition & 0 deletions arch/arm64/kernel/hyp-stub.S
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

#include <linux/init.h>
#include <linux/linkage.h>
#include <linux/irqchip/arm-gic-v3.h>

#include <asm/assembler.h>
#include <asm/ptrace.h>
Expand Down
5 changes: 5 additions & 0 deletions drivers/irqchip/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ config ARM_GIC
config GIC_NON_BANKED
bool

config ARM_GIC_V3
bool
select IRQ_DOMAIN
select MULTI_IRQ_HANDLER

config ARM_NVIC
bool
select IRQ_DOMAIN
Expand Down
3 changes: 2 additions & 1 deletion drivers/irqchip/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ obj-$(CONFIG_ORION_IRQCHIP) += irq-orion.o
obj-$(CONFIG_ARCH_SUNXI) += irq-sun4i.o
obj-$(CONFIG_ARCH_SUNXI) += irq-sunxi-nmi.o
obj-$(CONFIG_ARCH_SPEAR3XX) += spear-shirq.o
obj-$(CONFIG_ARM_GIC) += irq-gic.o
obj-$(CONFIG_ARM_GIC) += irq-gic.o irq-gic-common.o
obj-$(CONFIG_ARM_GIC_V3) += irq-gic-v3.o irq-gic-common.o
obj-$(CONFIG_ARM_NVIC) += irq-nvic.o
obj-$(CONFIG_ARM_VIC) += irq-vic.o
obj-$(CONFIG_IMGPDC_IRQ) += irq-imgpdc.o
Expand Down
115 changes: 115 additions & 0 deletions drivers/irqchip/irq-gic-common.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/*
* Copyright (C) 2002 ARM Limited, All Rights Reserved.
*
* 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/>.
*/

#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/irq.h>
#include <linux/irqchip/arm-gic.h>

#include "irq-gic-common.h"

void gic_configure_irq(unsigned int irq, unsigned int type,
void __iomem *base, void (*sync_access)(void))
{
u32 enablemask = 1 << (irq % 32);
u32 enableoff = (irq / 32) * 4;
u32 confmask = 0x2 << ((irq % 16) * 2);
u32 confoff = (irq / 16) * 4;
bool enabled = false;
u32 val;

/*
* Read current configuration register, and insert the config
* for "irq", depending on "type".
*/
val = readl_relaxed(base + GIC_DIST_CONFIG + confoff);
if (type == IRQ_TYPE_LEVEL_HIGH)
val &= ~confmask;
else if (type == IRQ_TYPE_EDGE_RISING)
val |= confmask;

/*
* As recommended by the spec, disable the interrupt before changing
* the configuration
*/
if (readl_relaxed(base + GIC_DIST_ENABLE_SET + enableoff) & enablemask) {
writel_relaxed(enablemask, base + GIC_DIST_ENABLE_CLEAR + enableoff);
if (sync_access)
sync_access();
enabled = true;
}

/*
* Write back the new configuration, and possibly re-enable
* the interrupt.
*/
writel_relaxed(val, base + GIC_DIST_CONFIG + confoff);

if (enabled)
writel_relaxed(enablemask, base + GIC_DIST_ENABLE_SET + enableoff);

if (sync_access)
sync_access();
}

void __init gic_dist_config(void __iomem *base, int gic_irqs,
void (*sync_access)(void))
{
unsigned int i;

/*
* Set all global interrupts to be level triggered, active low.
*/
for (i = 32; i < gic_irqs; i += 16)
writel_relaxed(0, base + GIC_DIST_CONFIG + i / 4);

/*
* Set priority on all global interrupts.
*/
for (i = 32; i < gic_irqs; i += 4)
writel_relaxed(0xa0a0a0a0, base + GIC_DIST_PRI + i);

/*
* Disable all interrupts. Leave the PPI and SGIs alone
* as they are enabled by redistributor registers.
*/
for (i = 32; i < gic_irqs; i += 32)
writel_relaxed(0xffffffff, base + GIC_DIST_ENABLE_CLEAR + i / 8);

if (sync_access)
sync_access();
}

void gic_cpu_config(void __iomem *base, void (*sync_access)(void))
{
int i;

/*
* Deal with the banked PPI and SGI interrupts - disable all
* PPI interrupts, ensure all SGI interrupts are enabled.
*/
writel_relaxed(0xffff0000, base + GIC_DIST_ENABLE_CLEAR);
writel_relaxed(0x0000ffff, base + GIC_DIST_ENABLE_SET);

/*
* Set priority on PPI and SGI interrupts
*/
for (i = 0; i < 32; i += 4)
writel_relaxed(0xa0a0a0a0, base + GIC_DIST_PRI + i * 4 / 4);

if (sync_access)
sync_access();
}
29 changes: 29 additions & 0 deletions drivers/irqchip/irq-gic-common.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright (C) 2002 ARM Limited, All Rights Reserved.
*
* 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 _IRQ_GIC_COMMON_H
#define _IRQ_GIC_COMMON_H

#include <linux/of.h>
#include <linux/irqdomain.h>

void gic_configure_irq(unsigned int irq, unsigned int type,
void __iomem *base, void (*sync_access)(void));
void gic_dist_config(void __iomem *base, int gic_irqs,
void (*sync_access)(void));
void gic_cpu_config(void __iomem *base, void (*sync_access)(void));

#endif /* _IRQ_GIC_COMMON_H */
Loading

0 comments on commit 20c0c60

Please sign in to comment.