Yoshinori Sato | f36af3fd | 2006-11-05 16:21:09 +0900 | [diff] [blame] | 1 | /* |
| 2 | * linux/arch/sh/boards/se/7206/irq.c |
| 3 | * |
| 4 | * Copyright (C) 2005,2006 Yoshinori Sato |
| 5 | * |
| 6 | * Hitachi SolutionEngine Support. |
| 7 | * |
| 8 | */ |
Yoshinori Sato | f36af3fd | 2006-11-05 16:21:09 +0900 | [diff] [blame] | 9 | #include <linux/init.h> |
| 10 | #include <linux/irq.h> |
Paul Mundt | 710ee0c | 2006-11-05 16:48:42 +0900 | [diff] [blame] | 11 | #include <linux/io.h> |
Yoshinori Sato | 780a156 | 2006-12-07 18:01:23 +0900 | [diff] [blame] | 12 | #include <linux/interrupt.h> |
Paul Mundt | 939a24a | 2008-07-29 21:41:37 +0900 | [diff] [blame] | 13 | #include <mach-se/mach/se7206.h> |
Yoshinori Sato | f36af3fd | 2006-11-05 16:21:09 +0900 | [diff] [blame] | 14 | |
| 15 | #define INTSTS0 0x31800000 |
| 16 | #define INTSTS1 0x31800002 |
| 17 | #define INTMSK0 0x31800004 |
| 18 | #define INTMSK1 0x31800006 |
| 19 | #define INTSEL 0x31800008 |
| 20 | |
Yoshinori Sato | 780a156 | 2006-12-07 18:01:23 +0900 | [diff] [blame] | 21 | #define IRQ0_IRQ 64 |
| 22 | #define IRQ1_IRQ 65 |
| 23 | #define IRQ3_IRQ 67 |
| 24 | |
| 25 | #define INTC_IPR01 0xfffe0818 |
| 26 | #define INTC_ICR1 0xfffe0802 |
| 27 | |
Yoshinori Sato | f36af3fd | 2006-11-05 16:21:09 +0900 | [diff] [blame] | 28 | static void disable_se7206_irq(unsigned int irq) |
| 29 | { |
| 30 | unsigned short val; |
| 31 | unsigned short mask = 0xffff ^ (0x0f << 4 * (3 - (IRQ0_IRQ - irq))); |
| 32 | unsigned short msk0,msk1; |
| 33 | |
| 34 | /* Set the priority in IPR to 0 */ |
| 35 | val = ctrl_inw(INTC_IPR01); |
| 36 | val &= mask; |
| 37 | ctrl_outw(val, INTC_IPR01); |
| 38 | /* FPGA mask set */ |
| 39 | msk0 = ctrl_inw(INTMSK0); |
| 40 | msk1 = ctrl_inw(INTMSK1); |
| 41 | |
| 42 | switch (irq) { |
| 43 | case IRQ0_IRQ: |
| 44 | msk0 |= 0x0010; |
| 45 | break; |
| 46 | case IRQ1_IRQ: |
| 47 | msk0 |= 0x000f; |
| 48 | break; |
Yoshinori Sato | 780a156 | 2006-12-07 18:01:23 +0900 | [diff] [blame] | 49 | case IRQ3_IRQ: |
Yoshinori Sato | f36af3fd | 2006-11-05 16:21:09 +0900 | [diff] [blame] | 50 | msk0 |= 0x0f00; |
| 51 | msk1 |= 0x00ff; |
| 52 | break; |
| 53 | } |
| 54 | ctrl_outw(msk0, INTMSK0); |
| 55 | ctrl_outw(msk1, INTMSK1); |
| 56 | } |
| 57 | |
| 58 | static void enable_se7206_irq(unsigned int irq) |
| 59 | { |
| 60 | unsigned short val; |
| 61 | unsigned short value = (0x0001 << 4 * (3 - (IRQ0_IRQ - irq))); |
| 62 | unsigned short msk0,msk1; |
| 63 | |
| 64 | /* Set priority in IPR back to original value */ |
| 65 | val = ctrl_inw(INTC_IPR01); |
| 66 | val |= value; |
| 67 | ctrl_outw(val, INTC_IPR01); |
| 68 | |
| 69 | /* FPGA mask reset */ |
| 70 | msk0 = ctrl_inw(INTMSK0); |
| 71 | msk1 = ctrl_inw(INTMSK1); |
| 72 | |
| 73 | switch (irq) { |
| 74 | case IRQ0_IRQ: |
| 75 | msk0 &= ~0x0010; |
| 76 | break; |
| 77 | case IRQ1_IRQ: |
| 78 | msk0 &= ~0x000f; |
| 79 | break; |
Yoshinori Sato | 780a156 | 2006-12-07 18:01:23 +0900 | [diff] [blame] | 80 | case IRQ3_IRQ: |
Yoshinori Sato | f36af3fd | 2006-11-05 16:21:09 +0900 | [diff] [blame] | 81 | msk0 &= ~0x0f00; |
| 82 | msk1 &= ~0x00ff; |
| 83 | break; |
| 84 | } |
| 85 | ctrl_outw(msk0, INTMSK0); |
| 86 | ctrl_outw(msk1, INTMSK1); |
| 87 | } |
| 88 | |
Paul Mundt | 710ee0c | 2006-11-05 16:48:42 +0900 | [diff] [blame] | 89 | static void eoi_se7206_irq(unsigned int irq) |
Yoshinori Sato | f36af3fd | 2006-11-05 16:21:09 +0900 | [diff] [blame] | 90 | { |
| 91 | unsigned short sts0,sts1; |
| 92 | |
| 93 | if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) |
| 94 | enable_se7206_irq(irq); |
| 95 | /* FPGA isr clear */ |
| 96 | sts0 = ctrl_inw(INTSTS0); |
| 97 | sts1 = ctrl_inw(INTSTS1); |
| 98 | |
| 99 | switch (irq) { |
| 100 | case IRQ0_IRQ: |
| 101 | sts0 &= ~0x0010; |
| 102 | break; |
| 103 | case IRQ1_IRQ: |
| 104 | sts0 &= ~0x000f; |
| 105 | break; |
Yoshinori Sato | 780a156 | 2006-12-07 18:01:23 +0900 | [diff] [blame] | 106 | case IRQ3_IRQ: |
Yoshinori Sato | f36af3fd | 2006-11-05 16:21:09 +0900 | [diff] [blame] | 107 | sts0 &= ~0x0f00; |
| 108 | sts1 &= ~0x00ff; |
| 109 | break; |
| 110 | } |
| 111 | ctrl_outw(sts0, INTSTS0); |
| 112 | ctrl_outw(sts1, INTSTS1); |
| 113 | } |
| 114 | |
Paul Mundt | 710ee0c | 2006-11-05 16:48:42 +0900 | [diff] [blame] | 115 | static struct irq_chip se7206_irq_chip __read_mostly = { |
Yoshinori Sato | 780a156 | 2006-12-07 18:01:23 +0900 | [diff] [blame] | 116 | .name = "SE7206-FPGA", |
Paul Mundt | 710ee0c | 2006-11-05 16:48:42 +0900 | [diff] [blame] | 117 | .mask = disable_se7206_irq, |
| 118 | .unmask = enable_se7206_irq, |
| 119 | .mask_ack = disable_se7206_irq, |
| 120 | .eoi = eoi_se7206_irq, |
Yoshinori Sato | f36af3fd | 2006-11-05 16:21:09 +0900 | [diff] [blame] | 121 | }; |
| 122 | |
| 123 | static void make_se7206_irq(unsigned int irq) |
| 124 | { |
| 125 | disable_irq_nosync(irq); |
Paul Mundt | 710ee0c | 2006-11-05 16:48:42 +0900 | [diff] [blame] | 126 | set_irq_chip_and_handler_name(irq, &se7206_irq_chip, |
| 127 | handle_level_irq, "level"); |
Yoshinori Sato | f36af3fd | 2006-11-05 16:21:09 +0900 | [diff] [blame] | 128 | disable_se7206_irq(irq); |
| 129 | } |
| 130 | |
| 131 | /* |
| 132 | * Initialize IRQ setting |
| 133 | */ |
| 134 | void __init init_se7206_IRQ(void) |
| 135 | { |
| 136 | make_se7206_irq(IRQ0_IRQ); /* SMC91C111 */ |
| 137 | make_se7206_irq(IRQ1_IRQ); /* ATA */ |
| 138 | make_se7206_irq(IRQ3_IRQ); /* SLOT / PCM */ |
| 139 | ctrl_outw(inw(INTC_ICR1) | 0x000b ,INTC_ICR1 ) ; /* ICR1 */ |
| 140 | |
| 141 | /* FPGA System register setup*/ |
| 142 | ctrl_outw(0x0000,INTSTS0); /* Clear INTSTS0 */ |
| 143 | ctrl_outw(0x0000,INTSTS1); /* Clear INTSTS1 */ |
| 144 | /* IRQ0=LAN, IRQ1=ATA, IRQ3=SLT,PCM */ |
| 145 | ctrl_outw(0x0001,INTSEL); |
| 146 | } |