Commit 9869848d12601cdddf097a36aebe0b10dc5d177b

Authored by Lars-Peter Clausen
Committed by Ralf Baechle
1 parent 570a0bb82f

MIPS: JZ4740: Add IRQ handler code

Add support for IRQ handling on a JZ4740 SoC.

Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
Cc: linux-mips@linux-mips.org
Cc: linux-kernel@vger.kernel.org
Patchwork: https://patchwork.linux-mips.org/patch/1465/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>

Showing 3 changed files with 245 additions and 0 deletions Side-by-side Diff

arch/mips/include/asm/mach-jz4740/irq.h
  1 +/*
  2 + * Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
  3 + * JZ4740 IRQ definitions
  4 + *
  5 + * This program is free software; you can redistribute it and/or modify it
  6 + * under the terms of the GNU General Public License as published by the
  7 + * Free Software Foundation; either version 2 of the License, or (at your
  8 + * option) any later version.
  9 + *
  10 + * You should have received a copy of the GNU General Public License along
  11 + * with this program; if not, write to the Free Software Foundation, Inc.,
  12 + * 675 Mass Ave, Cambridge, MA 02139, USA.
  13 + *
  14 + */
  15 +
  16 +#ifndef __ASM_MACH_JZ4740_IRQ_H__
  17 +#define __ASM_MACH_JZ4740_IRQ_H__
  18 +
  19 +#define MIPS_CPU_IRQ_BASE 0
  20 +#define JZ4740_IRQ_BASE 8
  21 +
  22 +/* 1st-level interrupts */
  23 +#define JZ4740_IRQ(x) (JZ4740_IRQ_BASE + (x))
  24 +#define JZ4740_IRQ_I2C JZ4740_IRQ(1)
  25 +#define JZ4740_IRQ_UHC JZ4740_IRQ(3)
  26 +#define JZ4740_IRQ_UART1 JZ4740_IRQ(8)
  27 +#define JZ4740_IRQ_UART0 JZ4740_IRQ(9)
  28 +#define JZ4740_IRQ_SADC JZ4740_IRQ(12)
  29 +#define JZ4740_IRQ_MSC JZ4740_IRQ(14)
  30 +#define JZ4740_IRQ_RTC JZ4740_IRQ(15)
  31 +#define JZ4740_IRQ_SSI JZ4740_IRQ(16)
  32 +#define JZ4740_IRQ_CIM JZ4740_IRQ(17)
  33 +#define JZ4740_IRQ_AIC JZ4740_IRQ(18)
  34 +#define JZ4740_IRQ_ETH JZ4740_IRQ(19)
  35 +#define JZ4740_IRQ_DMAC JZ4740_IRQ(20)
  36 +#define JZ4740_IRQ_TCU2 JZ4740_IRQ(21)
  37 +#define JZ4740_IRQ_TCU1 JZ4740_IRQ(22)
  38 +#define JZ4740_IRQ_TCU0 JZ4740_IRQ(23)
  39 +#define JZ4740_IRQ_UDC JZ4740_IRQ(24)
  40 +#define JZ4740_IRQ_GPIO3 JZ4740_IRQ(25)
  41 +#define JZ4740_IRQ_GPIO2 JZ4740_IRQ(26)
  42 +#define JZ4740_IRQ_GPIO1 JZ4740_IRQ(27)
  43 +#define JZ4740_IRQ_GPIO0 JZ4740_IRQ(28)
  44 +#define JZ4740_IRQ_IPU JZ4740_IRQ(29)
  45 +#define JZ4740_IRQ_LCD JZ4740_IRQ(30)
  46 +
  47 +/* 2nd-level interrupts */
  48 +#define JZ4740_IRQ_DMA(x) (JZ4740_IRQ(32) + (X))
  49 +
  50 +#define JZ4740_IRQ_INTC_GPIO(x) (JZ4740_IRQ_GPIO0 - (x))
  51 +#define JZ4740_IRQ_GPIO(x) (JZ4740_IRQ(48) + (x))
  52 +
  53 +#define JZ4740_IRQ_ADC_BASE JZ4740_IRQ(176)
  54 +
  55 +#define NR_IRQS (JZ4740_IRQ_ADC_BASE + 6)
  56 +
  57 +#endif
arch/mips/jz4740/irq.c
  1 +/*
  2 + * Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
  3 + * JZ4740 platform IRQ support
  4 + *
  5 + * This program is free software; you can redistribute it and/or modify it
  6 + * under the terms of the GNU General Public License as published by the
  7 + * Free Software Foundation; either version 2 of the License, or (at your
  8 + * option) any later version.
  9 + *
  10 + * You should have received a copy of the GNU General Public License along
  11 + * with this program; if not, write to the Free Software Foundation, Inc.,
  12 + * 675 Mass Ave, Cambridge, MA 02139, USA.
  13 + *
  14 + */
  15 +
  16 +#include <linux/errno.h>
  17 +#include <linux/init.h>
  18 +#include <linux/types.h>
  19 +#include <linux/interrupt.h>
  20 +#include <linux/ioport.h>
  21 +#include <linux/timex.h>
  22 +#include <linux/slab.h>
  23 +#include <linux/delay.h>
  24 +
  25 +#include <linux/debugfs.h>
  26 +#include <linux/seq_file.h>
  27 +
  28 +#include <asm/io.h>
  29 +#include <asm/mipsregs.h>
  30 +#include <asm/irq_cpu.h>
  31 +
  32 +#include <asm/mach-jz4740/base.h>
  33 +
  34 +static void __iomem *jz_intc_base;
  35 +static uint32_t jz_intc_wakeup;
  36 +static uint32_t jz_intc_saved;
  37 +
  38 +#define JZ_REG_INTC_STATUS 0x00
  39 +#define JZ_REG_INTC_MASK 0x04
  40 +#define JZ_REG_INTC_SET_MASK 0x08
  41 +#define JZ_REG_INTC_CLEAR_MASK 0x0c
  42 +#define JZ_REG_INTC_PENDING 0x10
  43 +
  44 +#define IRQ_BIT(x) BIT((x) - JZ4740_IRQ_BASE)
  45 +
  46 +static void intc_irq_unmask(unsigned int irq)
  47 +{
  48 + writel(IRQ_BIT(irq), jz_intc_base + JZ_REG_INTC_CLEAR_MASK);
  49 +}
  50 +
  51 +static void intc_irq_mask(unsigned int irq)
  52 +{
  53 + writel(IRQ_BIT(irq), jz_intc_base + JZ_REG_INTC_SET_MASK);
  54 +}
  55 +
  56 +static int intc_irq_set_wake(unsigned int irq, unsigned int on)
  57 +{
  58 + if (on)
  59 + jz_intc_wakeup |= IRQ_BIT(irq);
  60 + else
  61 + jz_intc_wakeup &= ~IRQ_BIT(irq);
  62 +
  63 + return 0;
  64 +}
  65 +
  66 +static struct irq_chip intc_irq_type = {
  67 + .name = "INTC",
  68 + .mask = intc_irq_mask,
  69 + .mask_ack = intc_irq_mask,
  70 + .unmask = intc_irq_unmask,
  71 + .set_wake = intc_irq_set_wake,
  72 +};
  73 +
  74 +static irqreturn_t jz4740_cascade(int irq, void *data)
  75 +{
  76 + uint32_t irq_reg;
  77 +
  78 + irq_reg = readl(jz_intc_base + JZ_REG_INTC_PENDING);
  79 +
  80 + if (irq_reg)
  81 + generic_handle_irq(__fls(irq_reg) + JZ4740_IRQ_BASE);
  82 +
  83 + return IRQ_HANDLED;
  84 +}
  85 +
  86 +static struct irqaction jz4740_cascade_action = {
  87 + .handler = jz4740_cascade,
  88 + .name = "JZ4740 cascade interrupt",
  89 +};
  90 +
  91 +void __init arch_init_irq(void)
  92 +{
  93 + int i;
  94 + mips_cpu_irq_init();
  95 +
  96 + jz_intc_base = ioremap(JZ4740_INTC_BASE_ADDR, 0x14);
  97 +
  98 + for (i = JZ4740_IRQ_BASE; i < JZ4740_IRQ_BASE + 32; i++) {
  99 + intc_irq_mask(i);
  100 + set_irq_chip_and_handler(i, &intc_irq_type, handle_level_irq);
  101 + }
  102 +
  103 + setup_irq(2, &jz4740_cascade_action);
  104 +}
  105 +
  106 +asmlinkage void plat_irq_dispatch(void)
  107 +{
  108 + unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM;
  109 + if (pending & STATUSF_IP2)
  110 + do_IRQ(2);
  111 + else if (pending & STATUSF_IP3)
  112 + do_IRQ(3);
  113 + else
  114 + spurious_interrupt();
  115 +}
  116 +
  117 +void jz4740_intc_suspend(void)
  118 +{
  119 + jz_intc_saved = readl(jz_intc_base + JZ_REG_INTC_MASK);
  120 + writel(~jz_intc_wakeup, jz_intc_base + JZ_REG_INTC_SET_MASK);
  121 + writel(jz_intc_wakeup, jz_intc_base + JZ_REG_INTC_CLEAR_MASK);
  122 +}
  123 +
  124 +void jz4740_intc_resume(void)
  125 +{
  126 + writel(~jz_intc_saved, jz_intc_base + JZ_REG_INTC_CLEAR_MASK);
  127 + writel(jz_intc_saved, jz_intc_base + JZ_REG_INTC_SET_MASK);
  128 +}
  129 +
  130 +#ifdef CONFIG_DEBUG_FS
  131 +
  132 +static inline void intc_seq_reg(struct seq_file *s, const char *name,
  133 + unsigned int reg)
  134 +{
  135 + seq_printf(s, "%s:\t\t%08x\n", name, readl(jz_intc_base + reg));
  136 +}
  137 +
  138 +static int intc_regs_show(struct seq_file *s, void *unused)
  139 +{
  140 + intc_seq_reg(s, "Status", JZ_REG_INTC_STATUS);
  141 + intc_seq_reg(s, "Mask", JZ_REG_INTC_MASK);
  142 + intc_seq_reg(s, "Pending", JZ_REG_INTC_PENDING);
  143 +
  144 + return 0;
  145 +}
  146 +
  147 +static int intc_regs_open(struct inode *inode, struct file *file)
  148 +{
  149 + return single_open(file, intc_regs_show, NULL);
  150 +}
  151 +
  152 +static const struct file_operations intc_regs_operations = {
  153 + .open = intc_regs_open,
  154 + .read = seq_read,
  155 + .llseek = seq_lseek,
  156 + .release = single_release,
  157 +};
  158 +
  159 +static int __init intc_debugfs_init(void)
  160 +{
  161 + (void) debugfs_create_file("jz_regs_intc", S_IFREG | S_IRUGO,
  162 + NULL, NULL, &intc_regs_operations);
  163 + return 0;
  164 +}
  165 +subsys_initcall(intc_debugfs_init);
  166 +
  167 +#endif
arch/mips/jz4740/irq.h
  1 +/*
  2 + * Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
  3 + *
  4 + * This program is free software; you can redistribute it and/or modify it
  5 + * under the terms of the GNU General Public License as published by the
  6 + * Free Software Foundation; either version 2 of the License, or (at your
  7 + * option) any later version.
  8 + *
  9 + * You should have received a copy of the GNU General Public License along
  10 + * with this program; if not, write to the Free Software Foundation, Inc.,
  11 + * 675 Mass Ave, Cambridge, MA 02139, USA.
  12 + *
  13 + */
  14 +
  15 +#ifndef __MIPS_JZ4740_IRQ_H__
  16 +#define __MIPS_JZ4740_IRQ_H__
  17 +
  18 +extern void jz4740_intc_suspend(void);
  19 +extern void jz4740_intc_resume(void);
  20 +
  21 +#endif