blob: b9c97b9923f2a062c9889ce0a2162bb1fd115614 [file] [log] [blame]
#include <linux/init.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/syscore_ops.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/irq.h>
#include <linux/bitops.h>
#include <asm/exception.h>
#include <mach/irqs.h>
static const void __iomem *base = (void *)0xee41a400;
#define IRQBIT(irq) BIT((irq) & 0x1f)
#define IRQWD(irq) (base + (((irq) >> 5) << 2))
void brcmstb_mask_irq(struct irq_data *d)
{
__raw_writel(IRQBIT(d->irq), IRQWD(d->irq) + 0x18);
}
void brcmstb_unmask_irq(struct irq_data *d)
{
__raw_writel(IRQBIT(d->irq), IRQWD(d->irq) + 0x24);
}
static struct irq_chip brcmstb_internal_irq_chip = {
.name = "HIF_L1",
.irq_ack = brcmstb_mask_irq,
.irq_mask = brcmstb_mask_irq,
.irq_unmask = brcmstb_unmask_irq,
};
#define do_IRQ(x) handle_IRQ((x) - 1, regs)
#define flip_tp(x) do { } while (0)
asmlinkage void __exception_irq_entry brcmstb_handle_irq(struct pt_regs *regs)
{
u32 pend, shift;
pend = __raw_readl(IRQWD(0) + 0x00) & ~__raw_readl(IRQWD(0) + 0x0c);
while ((shift = ffs(pend)) != 0) {
pend ^= (1 << (shift - 1));
do_IRQ(shift);
flip_tp(shift);
}
pend = __raw_readl(IRQWD(32) + 0x00) & ~__raw_readl(IRQWD(32) + 0x0c);
while ((shift = ffs(pend)) != 0) {
pend ^= (1 << (shift - 1));
shift += 32;
do_IRQ(shift);
flip_tp(shift);
}
pend = __raw_readl(IRQWD(64) + 0x00) & ~__raw_readl(IRQWD(64) + 0x0c);
while ((shift = ffs(pend)) != 0) {
pend ^= (1 << (shift - 1));
shift += 64;
do_IRQ(shift);
flip_tp(shift);
}
}
#define BPHYSADDR(x) ((x) + 0xe0000000)
static struct resource irq_resource = {
.name = "HIF_L1",
.start = BPHYSADDR(0x0041a400),
.end = BPHYSADDR(0x0041a42f),
};
void __init brcmstb_init_irq(void)
{
int i, n;
request_resource(&iomem_resource, &irq_resource);
for (n = 0; n < NR_IRQS; n += 32) {
__raw_writel(0xffffffff, IRQWD(n) + 0x18);
for (i = n; (i < (n + 32)) && (i < NR_IRQS); i++) {
irq_set_chip_and_handler(i, &brcmstb_internal_irq_chip,
handle_level_irq);
//irq_set_chip_data(i, base);
set_irq_flags(i, IRQF_VALID);
}
}
}