From patchwork Wed Oct 12 02:46:05 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joe Hershberger X-Patchwork-Id: 119088 X-Patchwork-Delegate: kim.phillips@freescale.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id 2B8D0B6F71 for ; Wed, 12 Oct 2011 11:52:19 +1100 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 1BAC6284ED; Wed, 12 Oct 2011 02:52:11 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 4J-8NvF26xZ1; Wed, 12 Oct 2011 02:52:10 +0200 (CEST) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id DB007284D9; Wed, 12 Oct 2011 02:52:02 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 9BF24284D9 for ; Wed, 12 Oct 2011 02:51:59 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id JvHJ-X9QJmi9 for ; Wed, 12 Oct 2011 02:51:56 +0200 (CEST) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from spamkiller05.natinst.com (mailserver5.natinst.com [130.164.80.5]) by theia.denx.de (Postfix) with ESMTP id EAE88284DC for ; Wed, 12 Oct 2011 02:51:54 +0200 (CEST) Received: from mailserv59-us.natinst.com (nb-hsrp-1338.natinst.com [130.164.19.133]) by spamkiller05.natinst.com (8.14.4/8.14.4) with ESMTP id p9C0ppNi019410; Tue, 11 Oct 2011 19:51:51 -0500 Received: from localhost.localdomain ([130.164.14.197]) by mailserv59-us.natinst.com (Lotus Domino Release 8.5.2FP1) with ESMTP id 2011101119515113-96109 ; Tue, 11 Oct 2011 19:51:51 -0500 From: Joe Hershberger To: u-boot@lists.denx.de Date: Tue, 11 Oct 2011 21:46:05 -0500 Message-Id: <1318387565-1411-2-git-send-email-joe.hershberger@ni.com> X-Mailer: git-send-email 1.6.0.2 In-Reply-To: <20111007055918.C11A01408752@gemini.denx.de> References: <20111007055918.C11A01408752@gemini.denx.de> X-MIMETrack: Itemize by SMTP Server on MailServ59-US/AUS/H/NIC(Release 8.5.2FP1|November 29, 2010) at 10/11/2011 07:51:51 PM, Serialize by Router on MailServ59-US/AUS/H/NIC(Release 8.5.2FP1|November 29, 2010) at 10/11/2011 07:51:51 PM, Serialize complete at 10/11/2011 07:51:51 PM X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:5.4.6813, 1.0.211, 0.0.0000 definitions=2011-10-11_06:2011-10-11, 2011-10-11, 1970-01-01 signatures=0 Cc: Joe Hershberger , Kim Phillips Subject: [U-Boot] [PATCH v3 2/2] mpc83xx: Implement interrupt support for mpc83xx X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.9 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de Some core ipic code from Linux - commit bbf25010f1a6b761914430f5fca081ec8c7accd1 Signed-off-by: Joe Hershberger Cc: Joe Hershberger Cc: Kim Phillips --- Changes for v2: - Shorten some lines containing constants copied from Linux Changes for v3: - Explicitly identify the Linux commit that ipic source came from arch/powerpc/cpu/mpc83xx/interrupts.c | 447 ++++++++++++++++++++++++++++++-- arch/powerpc/include/asm/mpc83xx_irq.h | 72 +++++ 2 files changed, 499 insertions(+), 20 deletions(-) create mode 100644 arch/powerpc/include/asm/mpc83xx_irq.h diff --git a/arch/powerpc/cpu/mpc83xx/interrupts.c b/arch/powerpc/cpu/mpc83xx/interrupts.c index 446af27..5661421 100644 --- a/arch/powerpc/cpu/mpc83xx/interrupts.c +++ b/arch/powerpc/cpu/mpc83xx/interrupts.c @@ -26,17 +26,385 @@ #include #include #include +#include +#include #include DECLARE_GLOBAL_DATA_PTR; +/* + * Some ipic code copied from the linux 2.6 kernel: + * /arch/powerpc/sysdev/ipic.* + * /arch/powerpc/include/asm/ipic.h + */ +static struct ipic_info_t ipic_info[] = { + [1] = { + .mask = IPIC_SIMSR_H, + .bit = 16, + }, + [2] = { + .mask = IPIC_SIMSR_H, + .bit = 17, + }, + [3] = { + .mask = IPIC_SIMSR_H, + .bit = 18, + }, + [4] = { + .mask = IPIC_SIMSR_H, + .bit = 19, + }, + [5] = { + .mask = IPIC_SIMSR_H, + .bit = 20, + }, + [6] = { + .mask = IPIC_SIMSR_H, + .bit = 21, + }, + [7] = { + .mask = IPIC_SIMSR_H, + .bit = 22, + }, + [8] = { + .mask = IPIC_SIMSR_H, + .bit = 23, + }, + [IPIC_INT_UART1] = { + .mask = IPIC_SIMSR_H, + .bit = 24, + }, + [IPIC_INT_UART2] = { + .mask = IPIC_SIMSR_H, + .bit = 25, + }, + [IPIC_INT_SEC] = { + .mask = IPIC_SIMSR_H, + .bit = 26, + }, + [IPIC_INT_1588_1] = { + .mask = IPIC_SIMSR_H, + .bit = 27, + }, + [IPIC_INT_1588_2] = { + .mask = IPIC_SIMSR_H, + .bit = 28, + }, + [IPIC_INT_I2C1] = { + .mask = IPIC_SIMSR_H, + .bit = 29, + }, + [IPIC_INT_I2C2] = { + .mask = IPIC_SIMSR_H, + .bit = 30, + }, + [IPIC_INT_SPI] = { + .mask = IPIC_SIMSR_H, + .bit = 31, + }, + [IPIC_INT_IRQ1] = { + .ack = IPIC_SEPNR, + .mask = IPIC_SEMSR, + .bit = 1, + }, + [IPIC_INT_IRQ2] = { + .ack = IPIC_SEPNR, + .mask = IPIC_SEMSR, + .bit = 2, + }, + [IPIC_INT_IRQ3] = { + .ack = IPIC_SEPNR, + .mask = IPIC_SEMSR, + .bit = 3, + }, + [IPIC_INT_IRQ4] = { + .ack = IPIC_SEPNR, + .mask = IPIC_SEMSR, + .bit = 4, + }, + [21] = { + .ack = IPIC_SEPNR, + .mask = IPIC_SEMSR, + .bit = 5, + }, + [22] = { + .ack = IPIC_SEPNR, + .mask = IPIC_SEMSR, + .bit = 6, + }, + [23] = { + .ack = IPIC_SEPNR, + .mask = IPIC_SEMSR, + .bit = 7, + }, + [IPIC_INT_TSEC1_TX] = { + .mask = IPIC_SIMSR_H, + .bit = 0, + }, + [IPIC_INT_TSEC1_RX] = { + .mask = IPIC_SIMSR_H, + .bit = 1, + }, + [IPIC_INT_TSEC1_ERR] = { + .mask = IPIC_SIMSR_H, + .bit = 2, + }, + [IPIC_INT_TSEC2_TX] = { + .mask = IPIC_SIMSR_H, + .bit = 3, + }, + [IPIC_INT_TSEC2_RX] = { + .mask = IPIC_SIMSR_H, + .bit = 4, + }, + [IPIC_INT_TSEC2_ERR] = { + .mask = IPIC_SIMSR_H, + .bit = 5, + }, + [IPIC_INT_USB_DR] = { + .mask = IPIC_SIMSR_H, + .bit = 6, + }, + [39] = { + .mask = IPIC_SIMSR_H, + .bit = 7, + }, + [40] = { + .mask = IPIC_SIMSR_H, + .bit = 8, + }, + [41] = { + .mask = IPIC_SIMSR_H, + .bit = 9, + }, + [42] = { + .mask = IPIC_SIMSR_H, + .bit = 10, + }, + [43] = { + .mask = IPIC_SIMSR_H, + .bit = 11, + }, + [44] = { + .mask = IPIC_SIMSR_H, + .bit = 12, + }, + [45] = { + .mask = IPIC_SIMSR_H, + .bit = 13, + }, + [46] = { + .mask = IPIC_SIMSR_H, + .bit = 14, + }, + [47] = { + .mask = IPIC_SIMSR_H, + .bit = 15, + }, + [IPIC_INT_IRQ0] = { + .ack = IPIC_SEPNR, + .mask = IPIC_SEMSR, + .bit = 0, + }, + [IPIC_INT_RTC_SEC] = { + .mask = IPIC_SIMSR_L, + .bit = 0, + }, + [IPIC_INT_PIT] = { + .mask = IPIC_SIMSR_L, + .bit = 1, + }, + [IPIC_INT_PCI] = { + .mask = IPIC_SIMSR_L, + .bit = 2, + }, + [67] = { + .mask = IPIC_SIMSR_L, + .bit = 3, + }, + [IPIC_INT_RTC_ALR] = { + .mask = IPIC_SIMSR_L, + .bit = 4, + }, + [IPIC_INT_MU] = { + .mask = IPIC_SIMSR_L, + .bit = 5, + }, + [IPIC_INT_SBA] = { + .mask = IPIC_SIMSR_L, + .bit = 6, + }, + [IPIC_INT_DMA] = { + .mask = IPIC_SIMSR_L, + .bit = 7, + }, + [IPIC_INT_GTM4] = { + .mask = IPIC_SIMSR_L, + .bit = 8, + }, + [IPIC_INT_GTM8] = { + .mask = IPIC_SIMSR_L, + .bit = 9, + }, + [IPIC_INT_GPIO] = { + .mask = IPIC_SIMSR_L, + .bit = 10, + }, + [75] = { + .mask = IPIC_SIMSR_L, + .bit = 11, + }, + [IPIC_INT_DDR] = { + .mask = IPIC_SIMSR_L, + .bit = 12, + }, + [IPIC_INT_LBC] = { + .mask = IPIC_SIMSR_L, + .bit = 13, + }, + [IPIC_INT_GTM2] = { + .mask = IPIC_SIMSR_L, + .bit = 14, + }, + [IPIC_INT_GTM6] = { + .mask = IPIC_SIMSR_L, + .bit = 15, + }, + [IPIC_INT_PMC] = { + .mask = IPIC_SIMSR_L, + .bit = 16, + }, + [81] = { + .mask = IPIC_SIMSR_L, + .bit = 17, + }, + [82] = { + .mask = IPIC_SIMSR_L, + .bit = 18, + }, + [83] = { + .mask = IPIC_SIMSR_L, + .bit = 19, + }, + [IPIC_INT_GTM3] = { + .mask = IPIC_SIMSR_L, + .bit = 20, + }, + [IPIC_INT_GTM7] = { + .mask = IPIC_SIMSR_L, + .bit = 21, + }, + [86] = { + .mask = IPIC_SIMSR_L, + .bit = 22, + }, + [87] = { + .mask = IPIC_SIMSR_L, + .bit = 23, + }, + [88] = { + .mask = IPIC_SIMSR_L, + .bit = 24, + }, + [89] = { + .mask = IPIC_SIMSR_L, + .bit = 25, + }, + [IPIC_INT_GTM1] = { + .mask = IPIC_SIMSR_L, + .bit = 26, + }, + [IPIC_INT_GTM5] = { + .mask = IPIC_SIMSR_L, + .bit = 27, + }, + [92] = { + .mask = IPIC_SIMSR_L, + .bit = 28, + }, + [93] = { + .mask = IPIC_SIMSR_L, + .bit = 29, + }, + [94] = { + .mask = IPIC_SIMSR_L, + .bit = 30, + }, +}; + +static inline u32 ipic_read(u32 reg) +{ + immap_t *immr = (immap_t *) CONFIG_SYS_IMMR; + return in_be32((u32 *)&immr->ipic + (reg >> 2)); +} + +static inline void ipic_write(u32 reg, u32 value) +{ + immap_t *immr = (immap_t *) CONFIG_SYS_IMMR; + out_be32((u32 *)&immr->ipic + (reg >> 2), value); +} + +#define MAKE_MASK(bit) (1 << (31 - (bit))) + +static void ipic_unmask_irq(u32 irq) +{ + u32 temp; + + temp = ipic_read(ipic_info[irq].mask); + temp |= MAKE_MASK(ipic_info[irq].bit); + ipic_write(ipic_info[irq].mask, temp); +} + +static void ipic_mask_irq(u32 irq) +{ + u32 temp; + + temp = ipic_read(ipic_info[irq].mask); + temp &= ~MAKE_MASK(ipic_info[irq].bit); + ipic_write(ipic_info[irq].mask, temp); +} + +static void ipic_ack_irq(u32 irq) +{ + u32 temp; + + if (ipic_info[irq].ack) { + temp = MAKE_MASK(ipic_info[irq].bit); + ipic_write(ipic_info[irq].ack, temp); + } +} + +static void ipic_mask_irq_and_ack(u32 irq) +{ + ipic_mask_irq(irq); + ipic_ack_irq(irq); +} + +u32 ipic_get_irq(void) +{ + int irq; + + #define IPIC_SIVCR_VECTOR_MASK 0x7f + irq = ipic_read(IPIC_SIVCR) & IPIC_SIVCR_VECTOR_MASK; + + /* 0 --> no irq is pending */ + + return irq; +} + +/* + * End code copied from Linux + */ + struct irq_action { interrupt_handler_t *handler; void *arg; ulong count; }; -int interrupt_init_cpu (unsigned *decrementer_count) +static struct irq_action irq_handlers[NR_IRQS]; + +int interrupt_init_cpu(unsigned *decrementer_count) { volatile immap_t *immr = (immap_t *) CONFIG_SYS_IMMR; @@ -54,44 +422,83 @@ int interrupt_init_cpu (unsigned *decrementer_count) * Handle external interrupts */ -void external_interrupt (struct pt_regs *regs) +void external_interrupt(struct pt_regs *regs) { -} + int irq, unmask = 1; + irq = ipic_get_irq(); -/* - * Install and free an interrupt handler. - */ + ipic_mask_irq_and_ack(irq); -void -irq_install_handler (int irq, interrupt_handler_t * handler, void *arg) -{ -} + if (irq_handlers[irq].handler != NULL) { + (*irq_handlers[irq].handler) (irq_handlers[irq].arg); + } else { + printf("\nBogus External Interrupt IRQ %d\n", irq); + /* + * turn off the bogus interrupt, otherwise it + * might repeat forever + */ + unmask = 0; + } + enable_interrupts(); -void irq_free_handler (int irq) -{ + if (unmask) + ipic_unmask_irq(irq); } -void timer_interrupt_cpu (struct pt_regs *regs) +/* + * timer_interrupt - gets called when the decrementer overflows, + * with interrupts disabled. + */ +void timer_interrupt_cpu(struct pt_regs *regs) { /* nothing to do here */ return; } -#if defined(CONFIG_CMD_IRQ) - -/* ripped this out of ppc4xx/interrupts.c */ - /* - * irqinfo - print information about PCI devices + * Install and free an interrupt handler. */ -void -do_irqinfo(cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char * const argv[]) +void irq_install_handler(int irq, interrupt_handler_t *handler, void *arg) +{ + if (irq < 0 || irq >= NR_IRQS) { + printf("irq_install_handler: bad irq number %d\n", irq); + return; + } + + if (irq_handlers[irq].handler != NULL) + printf("irq_install_handler: 0x%08lx replacing 0x%08lx\n", + (ulong) handler, (ulong) irq_handlers[irq].handler); + + irq_handlers[irq].handler = handler; + irq_handlers[irq].arg = arg; + + ipic_unmask_irq(irq); +} + + +void irq_free_handler(int irq) { + if (irq < 0 || irq >= NR_IRQS) { + printf("irq_free_handler: bad irq number %d\n", irq); + return; + } + + ipic_mask_irq(irq); + + irq_handlers[irq].handler = NULL; + irq_handlers[irq].arg = NULL; } + +#if defined(CONFIG_CMD_IRQ) +void do_irqinfo(cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) +{ +} #endif + + diff --git a/arch/powerpc/include/asm/mpc83xx_irq.h b/arch/powerpc/include/asm/mpc83xx_irq.h new file mode 100644 index 0000000..fc77134 --- /dev/null +++ b/arch/powerpc/include/asm/mpc83xx_irq.h @@ -0,0 +1,72 @@ +#ifndef _MPC83xx_IRQ_H +#define _MPC83xx_IRQ_H + +#define NR_IRQS 128 + +/* + * Some ipic code copied from the linux 2.6 kernel: + * /arch/powerpc/sysdev/ipic.* + * /arch/powerpc/include/asm/ipic.h + */ +#define IPIC_SICFR 0x00 /* System Global Interrupt Configuration Reg */ +#define IPIC_SIVCR 0x04 /* System Global Interrupt Vector Register */ +#define IPIC_SIPNR_H 0x08 /* System Internal Interrupt Pending Reg (HIGH) */ +#define IPIC_SIPNR_L 0x0C /* System Internal Interrupt Pending Reg (LOW) */ +#define IPIC_SIMSR_H 0x20 /* System Internal Interrupt Mask Reg (HIGH) */ +#define IPIC_SIMSR_L 0x24 /* System Internal Interrupt Mask Reg (LOW) */ +#define IPIC_SEPNR 0x2C /* System External Interrupt Pending Register */ +#define IPIC_SEMSR 0x38 /* System External Interrupt Mask Register */ + +struct ipic_info_t { + u8 ack; /* pending register offset from base if the irq + supports ack operation */ + u8 mask; /* mask register offset from base */ + u8 bit; /* register bit position (as per doc) + bit mask = 1 << (31 - bit) */ +}; + + +/* + * This list is specific to the mpc8313e for now. + */ +#define IPIC_INT_UART1 (0x09) +#define IPIC_INT_UART2 (0x0A) +#define IPIC_INT_SEC (0x0B) +#define IPIC_INT_1588_1 (0x0C) +#define IPIC_INT_1588_2 (0x0D) +#define IPIC_INT_I2C1 (0x0E) +#define IPIC_INT_I2C2 (0x0F) +#define IPIC_INT_SPI (0x10) +#define IPIC_INT_IRQ1 (0x11) +#define IPIC_INT_IRQ2 (0x12) +#define IPIC_INT_IRQ3 (0x13) +#define IPIC_INT_IRQ4 (0x14) +#define IPIC_INT_TSEC1_TX (0x20) +#define IPIC_INT_TSEC1_RX (0x21) +#define IPIC_INT_TSEC1_ERR (0x22) +#define IPIC_INT_TSEC2_TX (0x23) +#define IPIC_INT_TSEC2_RX (0x24) +#define IPIC_INT_TSEC2_ERR (0x25) +#define IPIC_INT_USB_DR (0x26) +#define IPIC_INT_IRQ0 (0x30) +#define IPIC_INT_RTC_SEC (0x40) +#define IPIC_INT_PIT (0x41) +#define IPIC_INT_PCI (0x42) +#define IPIC_INT_RTC_ALR (0x44) +#define IPIC_INT_MU (0x45) +#define IPIC_INT_SBA (0x46) +#define IPIC_INT_DMA (0x47) +#define IPIC_INT_GTM4 (0x48) +#define IPIC_INT_GTM8 (0x49) +#define IPIC_INT_GPIO (0x4A) +#define IPIC_INT_DDR (0x4C) +#define IPIC_INT_LBC (0x4D) +#define IPIC_INT_GTM2 (0x4E) +#define IPIC_INT_GTM6 (0x4F) +#define IPIC_INT_PMC (0x50) +#define IPIC_INT_GTM3 (0x54) +#define IPIC_INT_GTM7 (0x55) +#define IPIC_INT_GTM1 (0x5A) +#define IPIC_INT_GTM5 (0x5B) + +#endif /* _MPC83xx_IRQ_H */