[U-Boot] [PATCH 1/2] mpc83xx: Fix ipic structure definition

Signed-off-by: Joe Hershberger joe.hershberger@ni.com Cc: Joe Hershberger joe.hershberger@gmail.com Cc: Kim Phillips kim.phillips@freescale.com --- arch/powerpc/include/asm/immap_83xx.h | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/arch/powerpc/include/asm/immap_83xx.h b/arch/powerpc/include/asm/immap_83xx.h index cc0293a..8e2a551 100644 --- a/arch/powerpc/include/asm/immap_83xx.h +++ b/arch/powerpc/include/asm/immap_83xx.h @@ -154,7 +154,7 @@ typedef struct ipic83xx { u32 siprr_d; /* System Internal Interrupt Group D Priority Register */ u32 simsr_h; /* System Internal Interrupt Mask Register - High */ u32 simsr_l; /* System Internal Interrupt Mask Register - Low */ - u8 res1[4]; + u32 sicnr; /* System Internal Interrupt Control Register */ u32 sepnr; /* System External Interrupt Pending Register */ u32 smprr_a; /* System Mixed Interrupt Group A Priority Register */ u32 smprr_b; /* System Mixed Interrupt Group B Priority Register */ @@ -163,14 +163,14 @@ typedef struct ipic83xx { u32 sersr; /* System Error Status Register */ u32 sermr; /* System Error Mask Register */ u32 sercr; /* System Error Control Register */ - u8 res2[4]; + u8 res1[4]; u32 sifcr_h; /* System Internal Interrupt Force Register - High */ u32 sifcr_l; /* System Internal Interrupt Force Register - Low */ u32 sefcr; /* System External Interrupt Force Register */ u32 serfr; /* System Error Force Register */ u32 scvcr; /* System Critical Interrupt Vector Register */ u32 smvcr; /* System Management Interrupt Vector Register */ - u8 res3[0x98]; + u8 res2[0x98]; } ipic83xx_t;
/*

Signed-off-by: Joe Hershberger joe.hershberger@ni.com Cc: Joe Hershberger joe.hershberger@gmail.com Cc: Kim Phillips kim.phillips@freescale.com --- 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 <common.h> #include <command.h> #include <mpc83xx.h> +#include <asm/io.h> +#include <asm/mpc83xx_irq.h> #include <asm/processor.h>
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..28804b7 --- /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 Register */ +#define IPIC_SIVCR 0x04 /* System Global Interrupt Vector Register */ +#define IPIC_SIPNR_H 0x08 /* System Internal Interrupt Pending Register (HIGH) */ +#define IPIC_SIPNR_L 0x0C /* System Internal Interrupt Pending Register (LOW) */ +#define IPIC_SIMSR_H 0x20 /* System Internal Interrupt Mask Register (HIGH) */ +#define IPIC_SIMSR_L 0x24 /* System Internal Interrupt Mask Register (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 */

Dear Joe Hershberger,
In message 1317856455-30829-2-git-send-email-joe.hershberger@ni.com you wrote:
Signed-off-by: Joe Hershberger joe.hershberger@ni.com Cc: Joe Hershberger joe.hershberger@gmail.com Cc: Kim Phillips kim.phillips@freescale.com
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
Checkpatch says:
total: 0 errors, 5 warnings, 560 lines checked
Please clean up and resubmit. Thanks.
Best regards,
Wolfgang Denk

On Thu, Oct 6, 2011 at 4:03 PM, Wolfgang Denk wd@denx.de wrote:
Dear Joe Hershberger,
In message 1317856455-30829-2-git-send-email-joe.hershberger@ni.com you wrote:
Signed-off-by: Joe Hershberger joe.hershberger@ni.com Cc: Joe Hershberger joe.hershberger@gmail.com Cc: Kim Phillips kim.phillips@freescale.com
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
Checkpatch says:
total: 0 errors, 5 warnings, 560 lines checked
Please clean up and resubmit. Thanks.
Hi Wolfgang,
Done. Sorry about that... figured that it would be an exception since it was copied from Linux.
Best, -Joe

Dear Joe Hershberger,
In message CANr=Z=YVvLY+05xYmkESzYV+257bOwSxjFHpP5FSvQXUarjcRQ@mail.gmail.com you wrote:
Checkpatch says:
total: 0 errors, 5 warnings, 560 lines checked
Please clean up and resubmit. =A0Thanks.
Done. Sorry about that... figured that it would be an exception since it was copied from Linux.
If needed, the kernel code should be cleaned up in sync.
BTW: if this is copied from Linux, then you failed to provide exact reference - see bullet # 4 at http://www.denx.de/wiki/view/U-Boot/Patches#Attributing_Code_Copyrights_Sign
Best regards,
Wolfgang Denk

Signed-off-by: Joe Hershberger joe.hershberger@ni.com Cc: Joe Hershberger joe.hershberger@gmail.com Cc: Kim Phillips kim.phillips@freescale.com --- Changes for v2: Changes for v3:
arch/powerpc/include/asm/immap_83xx.h | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/arch/powerpc/include/asm/immap_83xx.h b/arch/powerpc/include/asm/immap_83xx.h index 8d4c9cb..d6becc9 100644 --- a/arch/powerpc/include/asm/immap_83xx.h +++ b/arch/powerpc/include/asm/immap_83xx.h @@ -154,7 +154,7 @@ typedef struct ipic83xx { u32 siprr_d; /* System Internal Interrupt Group D Priority Register */ u32 simsr_h; /* System Internal Interrupt Mask Register - High */ u32 simsr_l; /* System Internal Interrupt Mask Register - Low */ - u8 res1[4]; + u32 sicnr; /* System Internal Interrupt Control Register */ u32 sepnr; /* System External Interrupt Pending Register */ u32 smprr_a; /* System Mixed Interrupt Group A Priority Register */ u32 smprr_b; /* System Mixed Interrupt Group B Priority Register */ @@ -163,14 +163,14 @@ typedef struct ipic83xx { u32 sersr; /* System Error Status Register */ u32 sermr; /* System Error Mask Register */ u32 sercr; /* System Error Control Register */ - u8 res2[4]; + u8 res1[4]; u32 sifcr_h; /* System Internal Interrupt Force Register - High */ u32 sifcr_l; /* System Internal Interrupt Force Register - Low */ u32 sefcr; /* System External Interrupt Force Register */ u32 serfr; /* System Error Force Register */ u32 scvcr; /* System Critical Interrupt Vector Register */ u32 smvcr; /* System Management Interrupt Vector Register */ - u8 res3[0x98]; + u8 res2[0x98]; } ipic83xx_t;
/*

Some core ipic code from Linux - commit bbf25010f1a6b761914430f5fca081ec8c7accd1
Signed-off-by: Joe Hershberger joe.hershberger@ni.com Cc: Joe Hershberger joe.hershberger@gmail.com Cc: Kim Phillips kim.phillips@freescale.com --- 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 <common.h> #include <command.h> #include <mpc83xx.h> +#include <asm/io.h> +#include <asm/mpc83xx_irq.h> #include <asm/processor.h>
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 */

On Tue, 11 Oct 2011 21:46:05 -0500 Joe Hershberger joe.hershberger@ni.com wrote:
Some core ipic code from Linux - commit bbf25010f1a6b761914430f5fca081ec8c7accd1
commit bbf25010f1a6b761914430f5fca081ec8c7accd1 Author: Linus Torvalds torvalds@woody.linux-foundation.org Date: Tue Oct 9 13:31:38 2007 -0700
Linux 2.6.23
...any particular reason to pull in such an old version?
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
- */
And why hasn't the Freescale copyright info been retained???
- This list is specific to the mpc8313e for now.
it shouldn't have to be. How is this list used outside of interrupts.c?
- */
+#define IPIC_INT_UART1 (0x09)
Is it possible to avoid the list altogether somehow? Use an embedded device tree? See doc/README.fdt-control.
Kim

Hi Kim,
On Thu, Nov 3, 2011 at 3:48 PM, Kim Phillips kim.phillips@freescale.com wrote:
On Tue, 11 Oct 2011 21:46:05 -0500 Joe Hershberger joe.hershberger@ni.com wrote:
Some core ipic code from Linux - commit bbf25010f1a6b761914430f5fca081ec8c7accd1
commit bbf25010f1a6b761914430f5fca081ec8c7accd1 Author: Linus Torvalds torvalds@woody.linux-foundation.org Date: Tue Oct 9 13:31:38 2007 -0700
Linux 2.6.23
...any particular reason to pull in such an old version?
That was the current version when I implemented the interrupt support.
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
- */
And why hasn't the Freescale copyright info been retained???
Oversight. Sorry.
- This list is specific to the mpc8313e for now.
it shouldn't have to be. How is this list used outside of interrupts.c?
Simply because I didn't audit every other SoC in the family to determine how to make it generic.
- */
+#define IPIC_INT_UART1 (0x09)
Is it possible to avoid the list altogether somehow? Use an embedded device tree? See doc/README.fdt-control.
Perhaps that is a good long-term approach. I'm not sure I'm up for that retrofit just now. ;)
Thanks, -Joe

On Mon, 7 Nov 2011 20:08:49 -0600 Joe Hershberger joe.hershberger@gmail.com wrote:
Hi Kim,
On Thu, Nov 3, 2011 at 3:48 PM, Kim Phillips kim.phillips@freescale.com wrote:
On Tue, 11 Oct 2011 21:46:05 -0500 Joe Hershberger joe.hershberger@ni.com wrote:
Some core ipic code from Linux - commit bbf25010f1a6b761914430f5fca081ec8c7accd1
commit bbf25010f1a6b761914430f5fca081ec8c7accd1 Author: Linus Torvalds torvalds@woody.linux-foundation.org Date: Tue Oct 9 13:31:38 2007 -0700
Linux 2.6.23
...any particular reason to pull in such an old version?
That was the current version when I implemented the interrupt support.
well it would have worked back then ;). A lot of vectors for the later 83xx SoCs have been added in upstream linux since then.
- */
+#define IPIC_INT_UART1 (0x09)
Is it possible to avoid the list altogether somehow? Use an embedded device tree? See doc/README.fdt-control.
Perhaps that is a good long-term approach. I'm not sure I'm up for that retrofit just now. ;)
understood. Dropping this table is important because of things like TSEC IRQ numbers changing in between revisions of the 8313 (see commit 7120c88 (which doubles as a good example of how to extract the IRQ numbers from the device tree :)).
Kim

On Wed, Oct 5, 2011 at 6:14 PM, Joe Hershberger joe.hershberger@ni.com wrote:
Signed-off-by: Joe Hershberger joe.hershberger@ni.com Cc: Joe Hershberger joe.hershberger@gmail.com Cc: Kim Phillips kim.phillips@freescale.com
Where's the patch description? You need to explain how this patch works.

Signed-off-by: Joe Hershberger joe.hershberger@ni.com Cc: Joe Hershberger joe.hershberger@gmail.com Cc: Kim Phillips kim.phillips@freescale.com --- Changes for v2:
arch/powerpc/include/asm/immap_83xx.h | 6 +++--- 1 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/arch/powerpc/include/asm/immap_83xx.h b/arch/powerpc/include/asm/immap_83xx.h index 8d4c9cb..d6becc9 100644 --- a/arch/powerpc/include/asm/immap_83xx.h +++ b/arch/powerpc/include/asm/immap_83xx.h @@ -154,7 +154,7 @@ typedef struct ipic83xx { u32 siprr_d; /* System Internal Interrupt Group D Priority Register */ u32 simsr_h; /* System Internal Interrupt Mask Register - High */ u32 simsr_l; /* System Internal Interrupt Mask Register - Low */ - u8 res1[4]; + u32 sicnr; /* System Internal Interrupt Control Register */ u32 sepnr; /* System External Interrupt Pending Register */ u32 smprr_a; /* System Mixed Interrupt Group A Priority Register */ u32 smprr_b; /* System Mixed Interrupt Group B Priority Register */ @@ -163,14 +163,14 @@ typedef struct ipic83xx { u32 sersr; /* System Error Status Register */ u32 sermr; /* System Error Mask Register */ u32 sercr; /* System Error Control Register */ - u8 res2[4]; + u8 res1[4]; u32 sifcr_h; /* System Internal Interrupt Force Register - High */ u32 sifcr_l; /* System Internal Interrupt Force Register - Low */ u32 sefcr; /* System External Interrupt Force Register */ u32 serfr; /* System Error Force Register */ u32 scvcr; /* System Critical Interrupt Vector Register */ u32 smvcr; /* System Management Interrupt Vector Register */ - u8 res3[0x98]; + u8 res2[0x98]; } ipic83xx_t;
/*

Signed-off-by: Joe Hershberger joe.hershberger@ni.com Cc: Joe Hershberger joe.hershberger@gmail.com Cc: Kim Phillips kim.phillips@freescale.com --- Changes for v2: - Shorten some lines containing constants copied from Linux
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 <common.h> #include <command.h> #include <mpc83xx.h> +#include <asm/io.h> +#include <asm/mpc83xx_irq.h> #include <asm/processor.h>
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 */

On Wed, 5 Oct 2011 18:14:14 -0500 Joe Hershberger joe.hershberger@ni.com wrote:
Signed-off-by: Joe Hershberger joe.hershberger@ni.com Cc: Joe Hershberger joe.hershberger@gmail.com Cc: Kim Phillips kim.phillips@freescale.com
applied after adding siprr_{b,c} and sepcr for completeness.
Kim
participants (5)
-
Joe Hershberger
-
Joe Hershberger
-
Kim Phillips
-
Tabi Timur-B04825
-
Wolfgang Denk