mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-29 19:21:31 -04:00
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:
commit
78c10e556e
281 changed files with 6271 additions and 2321 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
177
drivers/irqchip/irq-ingenic.c
Normal file
177
drivers/irqchip/irq-ingenic.c
Normal 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);
|
||||
172
drivers/irqchip/irq-mips-cpu.c
Normal file
172
drivers/irqchip/irq-mips-cpu.c
Normal 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);
|
||||
Loading…
Reference in a new issue