forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'sh/dynamic-irq-cleanup' into sh-latest
Conflicts: drivers/sh/intc/dynamic.c Signed-off-by: Paul Mundt <[email protected]>
- Loading branch information
Showing
14 changed files
with
260 additions
and
259 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,86 +1,129 @@ | ||
/* | ||
* linux/arch/sh/boards/se/7343/irq.c | ||
* Hitachi UL SolutionEngine 7343 FPGA IRQ Support. | ||
* | ||
* Copyright (C) 2008 Yoshihiro Shimoda | ||
* Copyright (C) 2012 Paul Mundt | ||
* | ||
* Based on linux/arch/sh/boards/se/7722/irq.c | ||
* Based on linux/arch/sh/boards/se/7343/irq.c | ||
* Copyright (C) 2007 Nobuhiro Iwamatsu | ||
* | ||
* This file is subject to the terms and conditions of the GNU General Public | ||
* License. See the file "COPYING" in the main directory of this archive | ||
* for more details. | ||
*/ | ||
#define DRV_NAME "SE7343-FPGA" | ||
#define pr_fmt(fmt) DRV_NAME ": " fmt | ||
|
||
#define irq_reg_readl ioread16 | ||
#define irq_reg_writel iowrite16 | ||
|
||
#include <linux/init.h> | ||
#include <linux/irq.h> | ||
#include <linux/interrupt.h> | ||
#include <linux/irqdomain.h> | ||
#include <linux/io.h> | ||
#include <asm/sizes.h> | ||
#include <mach-se/mach/se7343.h> | ||
|
||
unsigned int se7343_fpga_irq[SE7343_FPGA_IRQ_NR] = { 0, }; | ||
#define PA_CPLD_BASE_ADDR 0x11400000 | ||
#define PA_CPLD_ST_REG 0x08 /* CPLD Interrupt status register */ | ||
#define PA_CPLD_IMSK_REG 0x0a /* CPLD Interrupt mask register */ | ||
|
||
static void disable_se7343_irq(struct irq_data *data) | ||
{ | ||
unsigned int bit = (unsigned int)irq_data_get_irq_chip_data(data); | ||
__raw_writew(__raw_readw(PA_CPLD_IMSK) | 1 << bit, PA_CPLD_IMSK); | ||
} | ||
static void __iomem *se7343_irq_regs; | ||
struct irq_domain *se7343_irq_domain; | ||
|
||
static void enable_se7343_irq(struct irq_data *data) | ||
static void se7343_irq_demux(unsigned int irq, struct irq_desc *desc) | ||
{ | ||
unsigned int bit = (unsigned int)irq_data_get_irq_chip_data(data); | ||
__raw_writew(__raw_readw(PA_CPLD_IMSK) & ~(1 << bit), PA_CPLD_IMSK); | ||
} | ||
struct irq_data *data = irq_get_irq_data(irq); | ||
struct irq_chip *chip = irq_data_get_irq_chip(data); | ||
unsigned long mask; | ||
int bit; | ||
|
||
static struct irq_chip se7343_irq_chip __read_mostly = { | ||
.name = "SE7343-FPGA", | ||
.irq_mask = disable_se7343_irq, | ||
.irq_unmask = enable_se7343_irq, | ||
}; | ||
chip->irq_mask_ack(data); | ||
|
||
static void se7343_irq_demux(unsigned int irq, struct irq_desc *desc) | ||
mask = ioread16(se7343_irq_regs + PA_CPLD_ST_REG); | ||
|
||
for_each_set_bit(bit, &mask, SE7343_FPGA_IRQ_NR) | ||
generic_handle_irq(irq_linear_revmap(se7343_irq_domain, bit)); | ||
|
||
chip->irq_unmask(data); | ||
} | ||
|
||
static void __init se7343_domain_init(void) | ||
{ | ||
unsigned short intv = __raw_readw(PA_CPLD_ST); | ||
unsigned int ext_irq = 0; | ||
int i; | ||
|
||
intv &= (1 << SE7343_FPGA_IRQ_NR) - 1; | ||
se7343_irq_domain = irq_domain_add_linear(NULL, SE7343_FPGA_IRQ_NR, | ||
&irq_domain_simple_ops, NULL); | ||
if (unlikely(!se7343_irq_domain)) { | ||
printk("Failed to get IRQ domain\n"); | ||
return; | ||
} | ||
|
||
for (; intv; intv >>= 1, ext_irq++) { | ||
if (!(intv & 1)) | ||
continue; | ||
for (i = 0; i < SE7343_FPGA_IRQ_NR; i++) { | ||
int irq = irq_create_mapping(se7343_irq_domain, i); | ||
|
||
generic_handle_irq(se7343_fpga_irq[ext_irq]); | ||
if (unlikely(irq == 0)) { | ||
printk("Failed to allocate IRQ %d\n", i); | ||
return; | ||
} | ||
} | ||
} | ||
|
||
/* | ||
* Initialize IRQ setting | ||
*/ | ||
void __init init_7343se_IRQ(void) | ||
static void __init se7343_gc_init(void) | ||
{ | ||
int i, irq; | ||
struct irq_chip_generic *gc; | ||
struct irq_chip_type *ct; | ||
unsigned int irq_base; | ||
|
||
__raw_writew(0, PA_CPLD_IMSK); /* disable all irqs */ | ||
__raw_writew(0x2000, 0xb03fffec); /* mrshpc irq enable */ | ||
irq_base = irq_linear_revmap(se7343_irq_domain, 0); | ||
|
||
for (i = 0; i < SE7343_FPGA_IRQ_NR; i++) { | ||
irq = create_irq(); | ||
if (irq < 0) | ||
return; | ||
se7343_fpga_irq[i] = irq; | ||
gc = irq_alloc_generic_chip(DRV_NAME, 1, irq_base, se7343_irq_regs, | ||
handle_level_irq); | ||
if (unlikely(!gc)) | ||
return; | ||
|
||
irq_set_chip_and_handler_name(se7343_fpga_irq[i], | ||
&se7343_irq_chip, | ||
handle_level_irq, | ||
"level"); | ||
ct = gc->chip_types; | ||
ct->chip.irq_mask = irq_gc_mask_set_bit; | ||
ct->chip.irq_unmask = irq_gc_mask_clr_bit; | ||
|
||
irq_set_chip_data(se7343_fpga_irq[i], (void *)i); | ||
} | ||
ct->regs.mask = PA_CPLD_IMSK_REG; | ||
|
||
irq_setup_generic_chip(gc, IRQ_MSK(SE7343_FPGA_IRQ_NR), | ||
IRQ_GC_INIT_MASK_CACHE, | ||
IRQ_NOREQUEST | IRQ_NOPROBE, 0); | ||
|
||
irq_set_chained_handler(IRQ0_IRQ, se7343_irq_demux); | ||
irq_set_irq_type(IRQ0_IRQ, IRQ_TYPE_LEVEL_LOW); | ||
|
||
irq_set_chained_handler(IRQ1_IRQ, se7343_irq_demux); | ||
irq_set_irq_type(IRQ1_IRQ, IRQ_TYPE_LEVEL_LOW); | ||
|
||
irq_set_chained_handler(IRQ4_IRQ, se7343_irq_demux); | ||
irq_set_irq_type(IRQ4_IRQ, IRQ_TYPE_LEVEL_LOW); | ||
|
||
irq_set_chained_handler(IRQ5_IRQ, se7343_irq_demux); | ||
irq_set_irq_type(IRQ5_IRQ, IRQ_TYPE_LEVEL_LOW); | ||
} | ||
|
||
/* | ||
* Initialize IRQ setting | ||
*/ | ||
void __init init_7343se_IRQ(void) | ||
{ | ||
se7343_irq_regs = ioremap(PA_CPLD_BASE_ADDR, SZ_16); | ||
if (unlikely(!se7343_irq_regs)) { | ||
pr_err("Failed to remap CPLD\n"); | ||
return; | ||
} | ||
|
||
/* | ||
* All FPGA IRQs disabled by default | ||
*/ | ||
iowrite16(0, se7343_irq_regs + PA_CPLD_IMSK_REG); | ||
|
||
__raw_writew(0x2000, 0xb03fffec); /* mrshpc irq enable */ | ||
|
||
se7343_domain_init(); | ||
se7343_gc_init(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.