Merge branch 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus

Pull MIPS updates from Ralf Baechle:

 - Improvements to the tlb_dump code
 - KVM fixes
 - Add support for appended DTB
 - Minor improvements to the R12000 support
 - Minor improvements to the R12000 support
 - Various platform improvments for BCM47xx
 - The usual pile of minor cleanups
 - A number of BPF fixes and improvments
 - Some improvments to the support for R3000 and DECstations
 - Some improvments to the ATH79 platform support
 - A major patchset for the JZ4740 SOC adding support for the CI20 platform
 - Add support for the Pistachio SOC
 - Minor BMIPS/BCM63xx platform support improvments.
 - Avoid "SYNC 0" as memory barrier when unlocking spinlocks
 - Add support for the XWR-1750 board.
 - Paul's __cpuinit/__cpuinitdata cleanups.
 - New Malta CPU board support large memory so enable ZONE_DMA32.

* 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus: (131 commits)
  MIPS: spinlock: Adjust arch_spin_lock back-off time
  MIPS: asmmacro: Ensure 64-bit FP registers are used with MSA
  MIPS: BCM47xx: Simplify handling SPROM revisions
  MIPS: Cobalt Don't use module_init in non-modular MTD registration.
  MIPS: BCM47xx: Move NVRAM driver to the drivers/firmware/
  MIPS: use for_each_sg()
  MIPS: BCM47xx: Don't select BCMA_HOST_PCI
  MIPS: BCM47xx: Add helper variable for storing NVRAM length
  MIPS: IRQ/IP27: Move IRQ allocation API to platform code.
  MIPS: Replace smp_mb with release barrier function in unlocks.
  MIPS: i8259: DT support
  MIPS: Malta: Basic DT plumbing
  MIPS: include errno.h for ENODEV in mips-cm.h
  MIPS: Define GCR_GIC_STATUS register fields
  MIPS: BPF: Introduce BPF ASM helpers
  MIPS: BPF: Use BPF register names to describe the ABI
  MIPS: BPF: Move register definition to the BPF header
  MIPS: net: BPF: Replace RSIZE with SZREG
  MIPS: BPF: Free up some callee-saved registers
  MIPS: Xtalk: Update xwidget.h with known Xtalk device numbers
  ...
This commit is contained in:
Linus Torvalds 2015-06-27 12:44:34 -07:00
commit 78c10e556e
281 changed files with 6271 additions and 2321 deletions

View file

@ -86,6 +86,11 @@ config IMGPDC_IRQ
select GENERIC_IRQ_CHIP
select IRQ_DOMAIN
config IRQ_MIPS_CPU
bool
select GENERIC_IRQ_CHIP
select IRQ_DOMAIN
config CLPS711X_IRQCHIP
bool
depends on ARCH_CLPS711X
@ -160,10 +165,15 @@ config MIPS_GIC
bool
select MIPS_CM
config INGENIC_IRQ
bool
depends on MACH_INGENIC
default y
config RENESAS_H8300H_INTC
bool
select IRQ_DOMAIN
config RENESAS_H8S_INTC
bool
select IRQ_DOMAIN
select IRQ_DOMAIN

View file

@ -28,6 +28,7 @@ obj-$(CONFIG_ARM_VIC) += irq-vic.o
obj-$(CONFIG_ATMEL_AIC_IRQ) += irq-atmel-aic-common.o irq-atmel-aic.o
obj-$(CONFIG_ATMEL_AIC5_IRQ) += irq-atmel-aic-common.o irq-atmel-aic5.o
obj-$(CONFIG_IMGPDC_IRQ) += irq-imgpdc.o
obj-$(CONFIG_IRQ_MIPS_CPU) += irq-mips-cpu.o
obj-$(CONFIG_SIRF_IRQ) += irq-sirfsoc.o
obj-$(CONFIG_RENESAS_INTC_IRQPIN) += irq-renesas-intc-irqpin.o
obj-$(CONFIG_RENESAS_IRQC) += irq-renesas-irqc.o
@ -50,3 +51,4 @@ obj-$(CONFIG_ARCH_DIGICOLOR) += irq-digicolor.o
obj-$(CONFIG_RENESAS_H8300H_INTC) += irq-renesas-h8300h.o
obj-$(CONFIG_RENESAS_H8S_INTC) += irq-renesas-h8s.o
obj-$(CONFIG_ARCH_SA1100) += irq-sa11x0.o
obj-$(CONFIG_INGENIC_IRQ) += irq-ingenic.o

View file

@ -0,0 +1,177 @@
/*
* Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
* JZ4740 platform IRQ support
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/irqchip/ingenic.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/timex.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <asm/io.h>
#include <asm/mach-jz4740/irq.h>
#include "irqchip.h"
struct ingenic_intc_data {
void __iomem *base;
unsigned num_chips;
};
#define JZ_REG_INTC_STATUS 0x00
#define JZ_REG_INTC_MASK 0x04
#define JZ_REG_INTC_SET_MASK 0x08
#define JZ_REG_INTC_CLEAR_MASK 0x0c
#define JZ_REG_INTC_PENDING 0x10
#define CHIP_SIZE 0x20
static irqreturn_t intc_cascade(int irq, void *data)
{
struct ingenic_intc_data *intc = irq_get_handler_data(irq);
uint32_t irq_reg;
unsigned i;
for (i = 0; i < intc->num_chips; i++) {
irq_reg = readl(intc->base + (i * CHIP_SIZE) +
JZ_REG_INTC_PENDING);
if (!irq_reg)
continue;
generic_handle_irq(__fls(irq_reg) + (i * 32) + JZ4740_IRQ_BASE);
}
return IRQ_HANDLED;
}
static void intc_irq_set_mask(struct irq_chip_generic *gc, uint32_t mask)
{
struct irq_chip_regs *regs = &gc->chip_types->regs;
writel(mask, gc->reg_base + regs->enable);
writel(~mask, gc->reg_base + regs->disable);
}
void ingenic_intc_irq_suspend(struct irq_data *data)
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data);
intc_irq_set_mask(gc, gc->wake_active);
}
void ingenic_intc_irq_resume(struct irq_data *data)
{
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data);
intc_irq_set_mask(gc, gc->mask_cache);
}
static struct irqaction intc_cascade_action = {
.handler = intc_cascade,
.name = "SoC intc cascade interrupt",
};
static int __init ingenic_intc_of_init(struct device_node *node,
unsigned num_chips)
{
struct ingenic_intc_data *intc;
struct irq_chip_generic *gc;
struct irq_chip_type *ct;
struct irq_domain *domain;
int parent_irq, err = 0;
unsigned i;
intc = kzalloc(sizeof(*intc), GFP_KERNEL);
if (!intc) {
err = -ENOMEM;
goto out_err;
}
parent_irq = irq_of_parse_and_map(node, 0);
if (!parent_irq) {
err = -EINVAL;
goto out_free;
}
err = irq_set_handler_data(parent_irq, intc);
if (err)
goto out_unmap_irq;
intc->num_chips = num_chips;
intc->base = of_iomap(node, 0);
if (!intc->base) {
err = -ENODEV;
goto out_unmap_irq;
}
for (i = 0; i < num_chips; i++) {
/* Mask all irqs */
writel(0xffffffff, intc->base + (i * CHIP_SIZE) +
JZ_REG_INTC_SET_MASK);
gc = irq_alloc_generic_chip("INTC", 1,
JZ4740_IRQ_BASE + (i * 32),
intc->base + (i * CHIP_SIZE),
handle_level_irq);
gc->wake_enabled = IRQ_MSK(32);
ct = gc->chip_types;
ct->regs.enable = JZ_REG_INTC_CLEAR_MASK;
ct->regs.disable = JZ_REG_INTC_SET_MASK;
ct->chip.irq_unmask = irq_gc_unmask_enable_reg;
ct->chip.irq_mask = irq_gc_mask_disable_reg;
ct->chip.irq_mask_ack = irq_gc_mask_disable_reg;
ct->chip.irq_set_wake = irq_gc_set_wake;
ct->chip.irq_suspend = ingenic_intc_irq_suspend;
ct->chip.irq_resume = ingenic_intc_irq_resume;
irq_setup_generic_chip(gc, IRQ_MSK(32), 0, 0,
IRQ_NOPROBE | IRQ_LEVEL);
}
domain = irq_domain_add_legacy(node, num_chips * 32, JZ4740_IRQ_BASE, 0,
&irq_domain_simple_ops, NULL);
if (!domain)
pr_warn("unable to register IRQ domain\n");
setup_irq(parent_irq, &intc_cascade_action);
return 0;
out_unmap_irq:
irq_dispose_mapping(parent_irq);
out_free:
kfree(intc);
out_err:
return err;
}
static int __init intc_1chip_of_init(struct device_node *node,
struct device_node *parent)
{
return ingenic_intc_of_init(node, 1);
}
IRQCHIP_DECLARE(jz4740_intc, "ingenic,jz4740-intc", intc_1chip_of_init);
static int __init intc_2chip_of_init(struct device_node *node,
struct device_node *parent)
{
return ingenic_intc_of_init(node, 2);
}
IRQCHIP_DECLARE(jz4770_intc, "ingenic,jz4770-intc", intc_2chip_of_init);
IRQCHIP_DECLARE(jz4775_intc, "ingenic,jz4775-intc", intc_2chip_of_init);
IRQCHIP_DECLARE(jz4780_intc, "ingenic,jz4780-intc", intc_2chip_of_init);

View file

@ -0,0 +1,172 @@
/*
* Copyright 2001 MontaVista Software Inc.
* Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
*
* Copyright (C) 2001 Ralf Baechle
* Copyright (C) 2005 MIPS Technologies, Inc. All rights reserved.
* Author: Maciej W. Rozycki <macro@mips.com>
*
* This file define the irq handler for MIPS CPU interrupts.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
/*
* Almost all MIPS CPUs define 8 interrupt sources. They are typically
* level triggered (i.e., cannot be cleared from CPU; must be cleared from
* device). The first two are software interrupts which we don't really
* use or support. The last one is usually the CPU timer interrupt if
* counter register is present or, for CPUs with an external FPU, by
* convention it's the FPU exception interrupt.
*
* Don't even think about using this on SMP. You have been warned.
*
* This file exports one global function:
* void mips_cpu_irq_init(void);
*/
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/irq.h>
#include <linux/irqdomain.h>
#include <asm/irq_cpu.h>
#include <asm/mipsregs.h>
#include <asm/mipsmtregs.h>
#include <asm/setup.h>
#include "irqchip.h"
static inline void unmask_mips_irq(struct irq_data *d)
{
set_c0_status(0x100 << (d->irq - MIPS_CPU_IRQ_BASE));
irq_enable_hazard();
}
static inline void mask_mips_irq(struct irq_data *d)
{
clear_c0_status(0x100 << (d->irq - MIPS_CPU_IRQ_BASE));
irq_disable_hazard();
}
static struct irq_chip mips_cpu_irq_controller = {
.name = "MIPS",
.irq_ack = mask_mips_irq,
.irq_mask = mask_mips_irq,
.irq_mask_ack = mask_mips_irq,
.irq_unmask = unmask_mips_irq,
.irq_eoi = unmask_mips_irq,
.irq_disable = mask_mips_irq,
.irq_enable = unmask_mips_irq,
};
/*
* Basically the same as above but taking care of all the MT stuff
*/
static unsigned int mips_mt_cpu_irq_startup(struct irq_data *d)
{
unsigned int vpflags = dvpe();
clear_c0_cause(0x100 << (d->irq - MIPS_CPU_IRQ_BASE));
evpe(vpflags);
unmask_mips_irq(d);
return 0;
}
/*
* While we ack the interrupt interrupts are disabled and thus we don't need
* to deal with concurrency issues. Same for mips_cpu_irq_end.
*/
static void mips_mt_cpu_irq_ack(struct irq_data *d)
{
unsigned int vpflags = dvpe();
clear_c0_cause(0x100 << (d->irq - MIPS_CPU_IRQ_BASE));
evpe(vpflags);
mask_mips_irq(d);
}
static struct irq_chip mips_mt_cpu_irq_controller = {
.name = "MIPS",
.irq_startup = mips_mt_cpu_irq_startup,
.irq_ack = mips_mt_cpu_irq_ack,
.irq_mask = mask_mips_irq,
.irq_mask_ack = mips_mt_cpu_irq_ack,
.irq_unmask = unmask_mips_irq,
.irq_eoi = unmask_mips_irq,
.irq_disable = mask_mips_irq,
.irq_enable = unmask_mips_irq,
};
asmlinkage void __weak plat_irq_dispatch(void)
{
unsigned long pending = read_c0_cause() & read_c0_status() & ST0_IM;
int irq;
if (!pending) {
spurious_interrupt();
return;
}
pending >>= CAUSEB_IP;
while (pending) {
irq = fls(pending) - 1;
do_IRQ(MIPS_CPU_IRQ_BASE + irq);
pending &= ~BIT(irq);
}
}
static int mips_cpu_intc_map(struct irq_domain *d, unsigned int irq,
irq_hw_number_t hw)
{
static struct irq_chip *chip;
if (hw < 2 && cpu_has_mipsmt) {
/* Software interrupts are used for MT/CMT IPI */
chip = &mips_mt_cpu_irq_controller;
} else {
chip = &mips_cpu_irq_controller;
}
if (cpu_has_vint)
set_vi_handler(hw, plat_irq_dispatch);
irq_set_chip_and_handler(irq, chip, handle_percpu_irq);
return 0;
}
static const struct irq_domain_ops mips_cpu_intc_irq_domain_ops = {
.map = mips_cpu_intc_map,
.xlate = irq_domain_xlate_onecell,
};
static void __init __mips_cpu_irq_init(struct device_node *of_node)
{
struct irq_domain *domain;
/* Mask interrupts. */
clear_c0_status(ST0_IM);
clear_c0_cause(CAUSEF_IP);
domain = irq_domain_add_legacy(of_node, 8, MIPS_CPU_IRQ_BASE, 0,
&mips_cpu_intc_irq_domain_ops, NULL);
if (!domain)
panic("Failed to add irqdomain for MIPS CPU");
}
void __init mips_cpu_irq_init(void)
{
__mips_cpu_irq_init(NULL);
}
int __init mips_cpu_irq_of_init(struct device_node *of_node,
struct device_node *parent)
{
__mips_cpu_irq_init(of_node);
return 0;
}
IRQCHIP_DECLARE(cpu_intc, "mti,cpu-interrupt-controller", mips_cpu_irq_of_init);