summaryrefslogtreecommitdiff
path: root/drivers/irqchip
diff options
context:
space:
mode:
authorScott Wood <scottwood@freescale.com>2014-04-07 23:49:35 (GMT)
committerScott Wood <scottwood@freescale.com>2014-04-07 23:49:35 (GMT)
commit62b8c978ee6b8d135d9e7953221de58000dba986 (patch)
tree683b04b2e627f6710c22c151b23c8cc9a165315e /drivers/irqchip
parent78fd82238d0e5716578c326404184a27ba67fd6e (diff)
downloadlinux-fsl-qoriq-62b8c978ee6b8d135d9e7953221de58000dba986.tar.xz
Rewind v3.13-rc3+ (78fd82238d0e5716) to v3.12
Diffstat (limited to 'drivers/irqchip')
-rw-r--r--drivers/irqchip/irq-armada-370-xp.c202
-rw-r--r--drivers/irqchip/irq-bcm2835.c22
-rw-r--r--drivers/irqchip/irq-gic.c160
-rw-r--r--drivers/irqchip/irq-vic.c7
4 files changed, 25 insertions, 366 deletions
diff --git a/drivers/irqchip/irq-armada-370-xp.c b/drivers/irqchip/irq-armada-370-xp.c
index 433cc85..bb328a3 100644
--- a/drivers/irqchip/irq-armada-370-xp.c
+++ b/drivers/irqchip/irq-armada-370-xp.c
@@ -21,10 +21,7 @@
#include <linux/io.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
-#include <linux/of_pci.h>
#include <linux/irqdomain.h>
-#include <linux/slab.h>
-#include <linux/msi.h>
#include <asm/mach/arch.h>
#include <asm/exception.h>
#include <asm/smp_plat.h>
@@ -54,22 +51,12 @@
#define IPI_DOORBELL_START (0)
#define IPI_DOORBELL_END (8)
#define IPI_DOORBELL_MASK 0xFF
-#define PCI_MSI_DOORBELL_START (16)
-#define PCI_MSI_DOORBELL_NR (16)
-#define PCI_MSI_DOORBELL_END (32)
-#define PCI_MSI_DOORBELL_MASK 0xFFFF0000
static DEFINE_RAW_SPINLOCK(irq_controller_lock);
static void __iomem *per_cpu_int_base;
static void __iomem *main_int_base;
static struct irq_domain *armada_370_xp_mpic_domain;
-#ifdef CONFIG_PCI_MSI
-static struct irq_domain *armada_370_xp_msi_domain;
-static DECLARE_BITMAP(msi_used, PCI_MSI_DOORBELL_NR);
-static DEFINE_MUTEX(msi_used_lock);
-static phys_addr_t msi_doorbell_addr;
-#endif
/*
* In SMP mode:
@@ -100,144 +87,6 @@ static void armada_370_xp_irq_unmask(struct irq_data *d)
ARMADA_370_XP_INT_CLEAR_MASK_OFFS);
}
-#ifdef CONFIG_PCI_MSI
-
-static int armada_370_xp_alloc_msi(void)
-{
- int hwirq;
-
- mutex_lock(&msi_used_lock);
- hwirq = find_first_zero_bit(&msi_used, PCI_MSI_DOORBELL_NR);
- if (hwirq >= PCI_MSI_DOORBELL_NR)
- hwirq = -ENOSPC;
- else
- set_bit(hwirq, msi_used);
- mutex_unlock(&msi_used_lock);
-
- return hwirq;
-}
-
-static void armada_370_xp_free_msi(int hwirq)
-{
- mutex_lock(&msi_used_lock);
- if (!test_bit(hwirq, msi_used))
- pr_err("trying to free unused MSI#%d\n", hwirq);
- else
- clear_bit(hwirq, msi_used);
- mutex_unlock(&msi_used_lock);
-}
-
-static int armada_370_xp_setup_msi_irq(struct msi_chip *chip,
- struct pci_dev *pdev,
- struct msi_desc *desc)
-{
- struct msi_msg msg;
- irq_hw_number_t hwirq;
- int virq;
-
- hwirq = armada_370_xp_alloc_msi();
- if (hwirq < 0)
- return hwirq;
-
- virq = irq_create_mapping(armada_370_xp_msi_domain, hwirq);
- if (!virq) {
- armada_370_xp_free_msi(hwirq);
- return -EINVAL;
- }
-
- irq_set_msi_desc(virq, desc);
-
- msg.address_lo = msi_doorbell_addr;
- msg.address_hi = 0;
- msg.data = 0xf00 | (hwirq + 16);
-
- write_msi_msg(virq, &msg);
- return 0;
-}
-
-static void armada_370_xp_teardown_msi_irq(struct msi_chip *chip,
- unsigned int irq)
-{
- struct irq_data *d = irq_get_irq_data(irq);
- irq_dispose_mapping(irq);
- armada_370_xp_free_msi(d->hwirq);
-}
-
-static struct irq_chip armada_370_xp_msi_irq_chip = {
- .name = "armada_370_xp_msi_irq",
- .irq_enable = unmask_msi_irq,
- .irq_disable = mask_msi_irq,
- .irq_mask = mask_msi_irq,
- .irq_unmask = unmask_msi_irq,
-};
-
-static int armada_370_xp_msi_map(struct irq_domain *domain, unsigned int virq,
- irq_hw_number_t hw)
-{
- irq_set_chip_and_handler(virq, &armada_370_xp_msi_irq_chip,
- handle_simple_irq);
- set_irq_flags(virq, IRQF_VALID);
-
- return 0;
-}
-
-static const struct irq_domain_ops armada_370_xp_msi_irq_ops = {
- .map = armada_370_xp_msi_map,
-};
-
-static int armada_370_xp_msi_init(struct device_node *node,
- phys_addr_t main_int_phys_base)
-{
- struct msi_chip *msi_chip;
- u32 reg;
- int ret;
-
- msi_doorbell_addr = main_int_phys_base +
- ARMADA_370_XP_SW_TRIG_INT_OFFS;
-
- msi_chip = kzalloc(sizeof(*msi_chip), GFP_KERNEL);
- if (!msi_chip)
- return -ENOMEM;
-
- msi_chip->setup_irq = armada_370_xp_setup_msi_irq;
- msi_chip->teardown_irq = armada_370_xp_teardown_msi_irq;
- msi_chip->of_node = node;
-
- armada_370_xp_msi_domain =
- irq_domain_add_linear(NULL, PCI_MSI_DOORBELL_NR,
- &armada_370_xp_msi_irq_ops,
- NULL);
- if (!armada_370_xp_msi_domain) {
- kfree(msi_chip);
- return -ENOMEM;
- }
-
- ret = of_pci_msi_chip_add(msi_chip);
- if (ret < 0) {
- irq_domain_remove(armada_370_xp_msi_domain);
- kfree(msi_chip);
- return ret;
- }
-
- reg = readl(per_cpu_int_base + ARMADA_370_XP_IN_DRBEL_MSK_OFFS)
- | PCI_MSI_DOORBELL_MASK;
-
- writel(reg, per_cpu_int_base +
- ARMADA_370_XP_IN_DRBEL_MSK_OFFS);
-
- /* Unmask IPI interrupt */
- writel(1, per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS);
-
- return 0;
-}
-#else
-static inline int armada_370_xp_msi_init(struct device_node *node,
- phys_addr_t main_int_phys_base)
-{
- return 0;
-}
-#endif
-
#ifdef CONFIG_SMP
static int armada_xp_set_affinity(struct irq_data *d,
const struct cpumask *mask_val, bool force)
@@ -365,39 +214,12 @@ armada_370_xp_handle_irq(struct pt_regs *regs)
if (irqnr > 1022)
break;
- if (irqnr > 1) {
+ if (irqnr > 0) {
irqnr = irq_find_mapping(armada_370_xp_mpic_domain,
irqnr);
handle_IRQ(irqnr, regs);
continue;
}
-
-#ifdef CONFIG_PCI_MSI
- /* MSI handling */
- if (irqnr == 1) {
- u32 msimask, msinr;
-
- msimask = readl_relaxed(per_cpu_int_base +
- ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS)
- & PCI_MSI_DOORBELL_MASK;
-
- writel(~PCI_MSI_DOORBELL_MASK, per_cpu_int_base +
- ARMADA_370_XP_IN_DRBEL_CAUSE_OFFS);
-
- for (msinr = PCI_MSI_DOORBELL_START;
- msinr < PCI_MSI_DOORBELL_END; msinr++) {
- int irq;
-
- if (!(msimask & BIT(msinr)))
- continue;
-
- irq = irq_find_mapping(armada_370_xp_msi_domain,
- msinr - 16);
- handle_IRQ(irq, regs);
- }
- }
-#endif
-
#ifdef CONFIG_SMP
/* IPI Handling */
if (irqnr == 0) {
@@ -426,25 +248,12 @@ armada_370_xp_handle_irq(struct pt_regs *regs)
static int __init armada_370_xp_mpic_of_init(struct device_node *node,
struct device_node *parent)
{
- struct resource main_int_res, per_cpu_int_res;
u32 control;
- BUG_ON(of_address_to_resource(node, 0, &main_int_res));
- BUG_ON(of_address_to_resource(node, 1, &per_cpu_int_res));
-
- BUG_ON(!request_mem_region(main_int_res.start,
- resource_size(&main_int_res),
- node->full_name));
- BUG_ON(!request_mem_region(per_cpu_int_res.start,
- resource_size(&per_cpu_int_res),
- node->full_name));
+ main_int_base = of_iomap(node, 0);
+ per_cpu_int_base = of_iomap(node, 1);
- main_int_base = ioremap(main_int_res.start,
- resource_size(&main_int_res));
BUG_ON(!main_int_base);
-
- per_cpu_int_base = ioremap(per_cpu_int_res.start,
- resource_size(&per_cpu_int_res));
BUG_ON(!per_cpu_int_base);
control = readl(main_int_base + ARMADA_370_XP_INT_CONTROL);
@@ -453,7 +262,8 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node,
irq_domain_add_linear(node, (control >> 2) & 0x3ff,
&armada_370_xp_mpic_irq_ops, NULL);
- BUG_ON(!armada_370_xp_mpic_domain);
+ if (!armada_370_xp_mpic_domain)
+ panic("Unable to add Armada_370_Xp MPIC irq domain (DT)\n");
irq_set_default_host(armada_370_xp_mpic_domain);
@@ -470,8 +280,6 @@ static int __init armada_370_xp_mpic_of_init(struct device_node *node,
#endif
- armada_370_xp_msi_init(node, main_int_res.start);
-
set_handle_irq(armada_370_xp_handle_irq);
return 0;
diff --git a/drivers/irqchip/irq-bcm2835.c b/drivers/irqchip/irq-bcm2835.c
index 1693b8e..16c78f1 100644
--- a/drivers/irqchip/irq-bcm2835.c
+++ b/drivers/irqchip/irq-bcm2835.c
@@ -49,11 +49,9 @@
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/irqdomain.h>
+#include <linux/irqchip/bcm2835.h>
#include <asm/exception.h>
-#include <asm/mach/irq.h>
-
-#include "irqchip.h"
/* Put the bank and irq (32 bits) into the hwirq */
#define MAKE_HWIRQ(b, n) ((b << 5) | (n))
@@ -95,8 +93,6 @@ struct armctrl_ic {
};
static struct armctrl_ic intc __read_mostly;
-static asmlinkage void __exception_irq_entry bcm2835_handle_irq(
- struct pt_regs *regs);
static void armctrl_mask_irq(struct irq_data *d)
{
@@ -168,11 +164,19 @@ static int __init armctrl_of_init(struct device_node *node,
set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
}
}
-
- set_handle_irq(bcm2835_handle_irq);
return 0;
}
+static struct of_device_id irq_of_match[] __initconst = {
+ { .compatible = "brcm,bcm2835-armctrl-ic", .data = armctrl_of_init },
+ { }
+};
+
+void __init bcm2835_init_irq(void)
+{
+ of_irq_init(irq_of_match);
+}
+
/*
* Handle each interrupt across the entire interrupt controller. This reads the
* status register before handling each interrupt, which is necessary given that
@@ -196,7 +200,7 @@ static void armctrl_handle_shortcut(int bank, struct pt_regs *regs,
handle_IRQ(irq_linear_revmap(intc.domain, irq), regs);
}
-static asmlinkage void __exception_irq_entry bcm2835_handle_irq(
+asmlinkage void __exception_irq_entry bcm2835_handle_irq(
struct pt_regs *regs)
{
u32 stat, irq;
@@ -218,5 +222,3 @@ static asmlinkage void __exception_irq_entry bcm2835_handle_irq(
}
}
}
-
-IRQCHIP_DECLARE(bcm2835_armctrl_ic, "brcm,bcm2835-armctrl-ic", armctrl_of_init);
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index 341c601..d0e9480 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -253,9 +253,10 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
if (cpu >= NR_GIC_CPU_IF || cpu >= nr_cpu_ids)
return -EINVAL;
- raw_spin_lock(&irq_controller_lock);
mask = 0xff << shift;
bit = gic_cpu_map[cpu] << shift;
+
+ raw_spin_lock(&irq_controller_lock);
val = readl_relaxed(reg) & ~mask;
writel_relaxed(val | bit, reg);
raw_spin_unlock(&irq_controller_lock);
@@ -651,9 +652,7 @@ static void __init gic_pm_init(struct gic_chip_data *gic)
void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
{
int cpu;
- unsigned long flags, map = 0;
-
- raw_spin_lock_irqsave(&irq_controller_lock, flags);
+ unsigned long map = 0;
/* Convert our logical CPU mask into a physical one. */
for_each_cpu(cpu, mask)
@@ -667,151 +666,9 @@ void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
/* this always happens on GIC0 */
writel_relaxed(map << 16 | irq, gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT);
-
- raw_spin_unlock_irqrestore(&irq_controller_lock, flags);
}
#endif
-#ifdef CONFIG_BL_SWITCHER
-/*
- * gic_send_sgi - send a SGI directly to given CPU interface number
- *
- * cpu_id: the ID for the destination CPU interface
- * irq: the IPI number to send a SGI for
- */
-void gic_send_sgi(unsigned int cpu_id, unsigned int irq)
-{
- BUG_ON(cpu_id >= NR_GIC_CPU_IF);
- cpu_id = 1 << cpu_id;
- /* this always happens on GIC0 */
- writel_relaxed((cpu_id << 16) | irq, gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT);
-}
-
-/*
- * gic_get_cpu_id - get the CPU interface ID for the specified CPU
- *
- * @cpu: the logical CPU number to get the GIC ID for.
- *
- * Return the CPU interface ID for the given logical CPU number,
- * or -1 if the CPU number is too large or the interface ID is
- * unknown (more than one bit set).
- */
-int gic_get_cpu_id(unsigned int cpu)
-{
- unsigned int cpu_bit;
-
- if (cpu >= NR_GIC_CPU_IF)
- return -1;
- cpu_bit = gic_cpu_map[cpu];
- if (cpu_bit & (cpu_bit - 1))
- return -1;
- return __ffs(cpu_bit);
-}
-
-/*
- * gic_migrate_target - migrate IRQs to another CPU interface
- *
- * @new_cpu_id: the CPU target ID to migrate IRQs to
- *
- * Migrate all peripheral interrupts with a target matching the current CPU
- * to the interface corresponding to @new_cpu_id. The CPU interface mapping
- * is also updated. Targets to other CPU interfaces are unchanged.
- * This must be called with IRQs locally disabled.
- */
-void gic_migrate_target(unsigned int new_cpu_id)
-{
- unsigned int cur_cpu_id, gic_irqs, gic_nr = 0;
- void __iomem *dist_base;
- int i, ror_val, cpu = smp_processor_id();
- u32 val, cur_target_mask, active_mask;
-
- if (gic_nr >= MAX_GIC_NR)
- BUG();
-
- dist_base = gic_data_dist_base(&gic_data[gic_nr]);
- if (!dist_base)
- return;
- gic_irqs = gic_data[gic_nr].gic_irqs;
-
- cur_cpu_id = __ffs(gic_cpu_map[cpu]);
- cur_target_mask = 0x01010101 << cur_cpu_id;
- ror_val = (cur_cpu_id - new_cpu_id) & 31;
-
- raw_spin_lock(&irq_controller_lock);
-
- /* Update the target interface for this logical CPU */
- gic_cpu_map[cpu] = 1 << new_cpu_id;
-
- /*
- * Find all the peripheral interrupts targetting the current
- * CPU interface and migrate them to the new CPU interface.
- * We skip DIST_TARGET 0 to 7 as they are read-only.
- */
- for (i = 8; i < DIV_ROUND_UP(gic_irqs, 4); i++) {
- val = readl_relaxed(dist_base + GIC_DIST_TARGET + i * 4);
- active_mask = val & cur_target_mask;
- if (active_mask) {
- val &= ~active_mask;
- val |= ror32(active_mask, ror_val);
- writel_relaxed(val, dist_base + GIC_DIST_TARGET + i*4);
- }
- }
-
- raw_spin_unlock(&irq_controller_lock);
-
- /*
- * Now let's migrate and clear any potential SGIs that might be
- * pending for us (cur_cpu_id). Since GIC_DIST_SGI_PENDING_SET
- * is a banked register, we can only forward the SGI using
- * GIC_DIST_SOFTINT. The original SGI source is lost but Linux
- * doesn't use that information anyway.
- *
- * For the same reason we do not adjust SGI source information
- * for previously sent SGIs by us to other CPUs either.
- */
- for (i = 0; i < 16; i += 4) {
- int j;
- val = readl_relaxed(dist_base + GIC_DIST_SGI_PENDING_SET + i);
- if (!val)
- continue;
- writel_relaxed(val, dist_base + GIC_DIST_SGI_PENDING_CLEAR + i);
- for (j = i; j < i + 4; j++) {
- if (val & 0xff)
- writel_relaxed((1 << (new_cpu_id + 16)) | j,
- dist_base + GIC_DIST_SOFTINT);
- val >>= 8;
- }
- }
-}
-
-/*
- * gic_get_sgir_physaddr - get the physical address for the SGI register
- *
- * REturn the physical address of the SGI register to be used
- * by some early assembly code when the kernel is not yet available.
- */
-static unsigned long gic_dist_physaddr;
-
-unsigned long gic_get_sgir_physaddr(void)
-{
- if (!gic_dist_physaddr)
- return 0;
- return gic_dist_physaddr + GIC_DIST_SOFTINT;
-}
-
-void __init gic_init_physaddr(struct device_node *node)
-{
- struct resource res;
- if (of_address_to_resource(node, 0, &res) == 0) {
- gic_dist_physaddr = res.start;
- pr_info("GIC physical location is %#lx\n", gic_dist_physaddr);
- }
-}
-
-#else
-#define gic_init_physaddr(node) do { } while (0)
-#endif
-
static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq,
irq_hw_number_t hw)
{
@@ -957,13 +814,12 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start,
if (WARN_ON(!gic->domain))
return;
- if (gic_nr == 0) {
#ifdef CONFIG_SMP
- set_smp_cross_call(gic_raise_softirq);
- register_cpu_notifier(&gic_cpu_notifier);
+ set_smp_cross_call(gic_raise_softirq);
+ register_cpu_notifier(&gic_cpu_notifier);
#endif
- set_handle_irq(gic_handle_irq);
- }
+
+ set_handle_irq(gic_handle_irq);
gic_chip.flags |= gic_arch_extn.flags;
gic_dist_init(gic);
@@ -994,8 +850,6 @@ int __init gic_of_init(struct device_node *node, struct device_node *parent)
percpu_offset = 0;
gic_init_bases(gic_cnt, -1, dist_base, cpu_base, percpu_offset, node);
- if (!gic_cnt)
- gic_init_physaddr(node);
if (parent) {
irq = irq_of_parse_and_map(node, 0);
diff --git a/drivers/irqchip/irq-vic.c b/drivers/irqchip/irq-vic.c
index 8e21ae0..2bbb004 100644
--- a/drivers/irqchip/irq-vic.c
+++ b/drivers/irqchip/irq-vic.c
@@ -469,8 +469,6 @@ void __init vic_init(void __iomem *base, unsigned int irq_start,
int __init vic_of_init(struct device_node *node, struct device_node *parent)
{
void __iomem *regs;
- u32 interrupt_mask = ~0;
- u32 wakeup_mask = ~0;
if (WARN(parent, "non-root VICs are not supported"))
return -EINVAL;
@@ -479,13 +477,10 @@ int __init vic_of_init(struct device_node *node, struct device_node *parent)
if (WARN_ON(!regs))
return -EIO;
- of_property_read_u32(node, "valid-mask", &interrupt_mask);
- of_property_read_u32(node, "valid-wakeup-mask", &wakeup_mask);
-
/*
* Passing 0 as first IRQ makes the simple domain allocate descriptors
*/
- __vic_init(regs, 0, interrupt_mask, wakeup_mask, node);
+ __vic_init(regs, 0, ~0, ~0, node);
return 0;
}