From mboxrd@z Thu Jan 1 00:00:00 1970 From: Kuo-Jung Su Date: Tue, 7 May 2013 14:25:09 +0800 Subject: [U-Boot] [PATCH v4 3/7] arm: add Faraday interrupt controller support In-Reply-To: <1367907913-11859-1-git-send-email-dantesu@gmail.com> References: <1367907913-11859-1-git-send-email-dantesu@gmail.com> Message-ID: <1367907913-11859-4-git-send-email-dantesu@gmail.com> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de From: Kuo-Jung Su Signed-off-by: Kuo-Jung Su CC: Albert Aribaud --- Changes for v4: - Coding Style cleanup. - Break up from [arm: add Faraday A36x SoC platform support] Changes for v3: - Coding Style cleanup. - Drop macros for wirtel()/readl(), call them directly. - Always insert a blank line between declarations and code. - Add '__iomem' to all the declaration of HW register pointers. Changes for v2: - Coding Style cleanup. - Use readl(), writel(), clrsetbits_le32() to replace REG() macros. - Use structure based hardware registers to replace the macro constants. - Replace BIT() with BIT_MASK(). arch/arm/cpu/faraday/Makefile | 2 +- arch/arm/cpu/faraday/interrupts.c | 151 +++++++++++++++++++++++++++++++++++++ include/common.h | 5 ++ include/faraday/ftintc020.h | 37 +++++++++ 4 files changed, 194 insertions(+), 1 deletion(-) create mode 100644 arch/arm/cpu/faraday/interrupts.c create mode 100644 include/faraday/ftintc020.h diff --git a/arch/arm/cpu/faraday/Makefile b/arch/arm/cpu/faraday/Makefile index ecb240a..77cc373 100644 --- a/arch/arm/cpu/faraday/Makefile +++ b/arch/arm/cpu/faraday/Makefile @@ -25,7 +25,7 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(CPU).o -src-y := cpu.o +src-y := cpu.o interrupts.o START = start.o COBJS = $(src-y) diff --git a/arch/arm/cpu/faraday/interrupts.c b/arch/arm/cpu/faraday/interrupts.c new file mode 100644 index 0000000..25f6dec --- /dev/null +++ b/arch/arm/cpu/faraday/interrupts.c @@ -0,0 +1,151 @@ +/* + * arch/arm/cpu/faraday/interrupts.c + * + * (C) Copyright 2010 Faraday Technology + * Dante Su + * + * This file is released under the terms of GPL v2 and any later version. + * See the file COPYING in the root directory of the source tree for details. + */ + +#include +#include + +#include + +#ifdef CONFIG_USE_IRQ + +static struct ftintc020_regs __iomem *regs + = (void __iomem *)CONFIG_PIC_BASE; + +struct _irq_handler { + void *data; + void (*func)(void *data); +}; + +static struct _irq_handler IRQ_HANDLER[64]; + +static inline void irq_acknowledge(int irq) +{ + uint32_t mask = BIT_MASK(irq); + + if (irq < 32) + writel(mask, ®s->irq32.scr); + else + writel(mask, ®s->irq64.scr); +} + +void irq_enable(int irq) +{ + uint32_t mask = BIT_MASK(irq); + + if (irq < 32) + setbits_le32(®s->irq32.ena, mask); + else + setbits_le32(®s->irq64.ena, mask); +} + +void irq_disable(int irq) +{ + uint32_t mask = BIT_MASK(irq); + + if (irq < 32) + clrbits_le32(®s->irq32.ena, mask); + else + clrbits_le32(®s->irq64.ena, mask); +} + +void irq_set_trigger(int irq, int edge, int low) +{ + uint32_t mask = BIT_MASK(irq); + + if (edge) { + if (irq < 32) + setbits_le32(®s->irq32.tmr, mask); + else + setbits_le32(®s->irq64.tmr, mask); + } else { + if (irq < 32) + clrbits_le32(®s->irq32.tmr, mask); + else + clrbits_le32(®s->irq64.tmr, mask); + } + + if (low) { + if (irq < 32) + setbits_le32(®s->irq32.tlr, mask); + else + setbits_le32(®s->irq64.tlr, mask); + } else { + if (irq < 32) + clrbits_le32(®s->irq32.tlr, mask); + else + clrbits_le32(®s->irq64.tlr, mask); + } +} + +void do_irq(struct pt_regs *pt_regs) +{ + int irq; + uint32_t stat; + + irq = 32; + stat = readl(®s->irq64.sr); /* IRQ 32 ~ 63 */ + if (!stat) { + irq = 0; + stat = readl(®s->irq32.sr); /* IRQ 0 ~ 31 */ + } + irq += ffs(stat) - 1; + + if (irq < 0) { + printf("interrupts: no irq!?\n"); + } else { + irq_acknowledge(irq); + IRQ_HANDLER[irq].func(IRQ_HANDLER[irq].data); + } +} + +static void default_isr(void *data) +{ + printf("default_isr(): called for IRQ %d\n", (int)data); +} + +void irq_install_handler(int irq, interrupt_handler_t *hndl, void *data) +{ + if (irq >= 0 && irq < 64) { + IRQ_HANDLER[irq].func = hndl; + IRQ_HANDLER[irq].data = data; + } +} + +void irq_free_handler(int irq) +{ + if (irq >= 0 && irq < 64) { + IRQ_HANDLER[irq].func = default_isr; + IRQ_HANDLER[irq].data = (void *)irq; + irq_disable(irq); + } +} + +int arch_interrupt_init(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(IRQ_HANDLER); ++i) + irq_free_handler(i); + + /* hardware reset */ + writel(0x00000000, ®s->irq32.ena); + writel(0xffffffff, ®s->irq32.scr); + writel(0x00000000, ®s->irq32.tmr); + writel(0x00000000, ®s->irq32.tlr); + + writel(0x00000000, ®s->irq64.ena); + writel(0xffffffff, ®s->irq64.scr); + writel(0x00000000, ®s->irq64.tmr); + writel(0x00000000, ®s->irq64.tlr); + + return 0; +} + +#endif /* #ifdef CONFIG_USE_IRQ */ diff --git a/include/common.h b/include/common.h index 17d9043..2cdb7f3 100644 --- a/include/common.h +++ b/include/common.h @@ -263,6 +263,11 @@ typedef void (interrupt_handler_t)(void *); #ifdef CONFIG_FARADAY /* board/faraday/xxx/clk.c */ ulong clk_get_rate(char *id); + +/* arch/arm/cpu/faraday/xxx/interrupt.c */ +void irq_set_trigger(int irq, int edge, int low); +void irq_enable(int irq); +void irq_disable(int irq); #endif /* diff --git a/include/faraday/ftintc020.h b/include/faraday/ftintc020.h new file mode 100644 index 0000000..e23d1e7 --- /dev/null +++ b/include/faraday/ftintc020.h @@ -0,0 +1,37 @@ +/* + * arch/arm/cpu/faraday/ftintc020.h + * + * (C) Copyright 2010 Faraday Technology + * Dante Su + * + * This file is released under the terms of GPL v2 and any later version. + * See the file COPYING in the root directory of the source tree for details. + */ + +#ifndef ARCH_ARM_CPU_FARADAY_FTINTC020_H +#define ARCH_ARM_CPU_FARADAY_FTINTC020_H + +struct ftintc020_pic_regs { + uint32_t src; /* source register */ + uint32_t ena; /* enable register */ + uint32_t scr; /* status clear register */ + uint32_t tmr; /* trigger mode register */ + uint32_t tlr; /* trigger level register */ + uint32_t sr; /* status register */ + uint32_t rsvd[2]; +}; + +struct ftintc020_regs { + /* IRQ/FIQ: 0 ~ 31 */ + struct ftintc020_pic_regs irq32; /* 0x00 - 0x1C: IRQ 0 ~ 31 */ + struct ftintc020_pic_regs fiq32; /* 0x20 - 0x3C: FIQ 0 ~ 31 */ + uint32_t rsvd1[4]; /* 0x40 - 0x4C: Reserved */ + uint32_t revision; /* 0x50: Revision Register */ + uint32_t feature; /* 0x54: Feature Register */ + uint32_t rsvd2[2]; /* 0x58 - 0x5C: Reserved */ + /* IRQ/FIQ: 32 ~ 63 */ + struct ftintc020_pic_regs irq64; /* 0x60 - 0x7C: IRQ 32 ~ 63 */ + struct ftintc020_pic_regs fiq64; /* 0x80 - 0x9C: FIQ 32 ~ 63 */ +}; + +#endif -- 1.7.9.5