Yoshinori Sato | f36af3f | 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 | f36af3f | 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 | f36af3f | 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 | f36af3f | 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 */ |
Paul Mundt | 9d56dd3 | 2010-01-26 12:58:40 +0900 | [diff] [blame] | 35 | val = __raw_readw(INTC_IPR01); |
Yoshinori Sato | f36af3f | 2006-11-05 16:21:09 +0900 | [diff] [blame] | 36 | val &= mask; |
Paul Mundt | 9d56dd3 | 2010-01-26 12:58:40 +0900 | [diff] [blame] | 37 | __raw_writew(val, INTC_IPR01); |
Yoshinori Sato | f36af3f | 2006-11-05 16:21:09 +0900 | [diff] [blame] | 38 | /* FPGA mask set */ |
Paul Mundt | 9d56dd3 | 2010-01-26 12:58:40 +0900 | [diff] [blame] | 39 | msk0 = __raw_readw(INTMSK0); |
| 40 | msk1 = __raw_readw(INTMSK1); |
Yoshinori Sato | f36af3f | 2006-11-05 16:21:09 +0900 | [diff] [blame] | 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 | f36af3f | 2006-11-05 16:21:09 +0900 | [diff] [blame] | 50 | msk0 |= 0x0f00; |
| 51 | msk1 |= 0x00ff; |
| 52 | break; |
| 53 | } |
Paul Mundt | 9d56dd3 | 2010-01-26 12:58:40 +0900 | [diff] [blame] | 54 | __raw_writew(msk0, INTMSK0); |
| 55 | __raw_writew(msk1, INTMSK1); |
Yoshinori Sato | f36af3f | 2006-11-05 16:21:09 +0900 | [diff] [blame] | 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 */ |
Paul Mundt | 9d56dd3 | 2010-01-26 12:58:40 +0900 | [diff] [blame] | 65 | val = __raw_readw(INTC_IPR01); |
Yoshinori Sato | f36af3f | 2006-11-05 16:21:09 +0900 | [diff] [blame] | 66 | val |= value; |
Paul Mundt | 9d56dd3 | 2010-01-26 12:58:40 +0900 | [diff] [blame] | 67 | __raw_writew(val, INTC_IPR01); |
Yoshinori Sato | f36af3f | 2006-11-05 16:21:09 +0900 | [diff] [blame] | 68 | |
| 69 | /* FPGA mask reset */ |
Paul Mundt | 9d56dd3 | 2010-01-26 12:58:40 +0900 | [diff] [blame] | 70 | msk0 = __raw_readw(INTMSK0); |
| 71 | msk1 = __raw_readw(INTMSK1); |
Yoshinori Sato | f36af3f | 2006-11-05 16:21:09 +0900 | [diff] [blame] | 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 | f36af3f | 2006-11-05 16:21:09 +0900 | [diff] [blame] | 81 | msk0 &= ~0x0f00; |
| 82 | msk1 &= ~0x00ff; |
| 83 | break; |
| 84 | } |
Paul Mundt | 9d56dd3 | 2010-01-26 12:58:40 +0900 | [diff] [blame] | 85 | __raw_writew(msk0, INTMSK0); |
| 86 | __raw_writew(msk1, INTMSK1); |
Yoshinori Sato | f36af3f | 2006-11-05 16:21:09 +0900 | [diff] [blame] | 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 | f36af3f | 2006-11-05 16:21:09 +0900 | [diff] [blame] | 90 | { |
| 91 | unsigned short sts0,sts1; |
Paul Mundt | 97b1977 | 2010-01-30 11:04:38 +0900 | [diff] [blame] | 92 | struct irq_desc *desc = irq_to_desc(irq); |
Yoshinori Sato | f36af3f | 2006-11-05 16:21:09 +0900 | [diff] [blame] | 93 | |
Paul Mundt | 97b1977 | 2010-01-30 11:04:38 +0900 | [diff] [blame] | 94 | if (!(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS))) |
Yoshinori Sato | f36af3f | 2006-11-05 16:21:09 +0900 | [diff] [blame] | 95 | enable_se7206_irq(irq); |
| 96 | /* FPGA isr clear */ |
Paul Mundt | 9d56dd3 | 2010-01-26 12:58:40 +0900 | [diff] [blame] | 97 | sts0 = __raw_readw(INTSTS0); |
| 98 | sts1 = __raw_readw(INTSTS1); |
Yoshinori Sato | f36af3f | 2006-11-05 16:21:09 +0900 | [diff] [blame] | 99 | |
| 100 | switch (irq) { |
| 101 | case IRQ0_IRQ: |
| 102 | sts0 &= ~0x0010; |
| 103 | break; |
| 104 | case IRQ1_IRQ: |
| 105 | sts0 &= ~0x000f; |
| 106 | break; |
Yoshinori Sato | 780a156 | 2006-12-07 18:01:23 +0900 | [diff] [blame] | 107 | case IRQ3_IRQ: |
Yoshinori Sato | f36af3f | 2006-11-05 16:21:09 +0900 | [diff] [blame] | 108 | sts0 &= ~0x0f00; |
| 109 | sts1 &= ~0x00ff; |
| 110 | break; |
| 111 | } |
Paul Mundt | 9d56dd3 | 2010-01-26 12:58:40 +0900 | [diff] [blame] | 112 | __raw_writew(sts0, INTSTS0); |
| 113 | __raw_writew(sts1, INTSTS1); |
Yoshinori Sato | f36af3f | 2006-11-05 16:21:09 +0900 | [diff] [blame] | 114 | } |
| 115 | |
Paul Mundt | 710ee0c | 2006-11-05 16:48:42 +0900 | [diff] [blame] | 116 | static struct irq_chip se7206_irq_chip __read_mostly = { |
Yoshinori Sato | 780a156 | 2006-12-07 18:01:23 +0900 | [diff] [blame] | 117 | .name = "SE7206-FPGA", |
Paul Mundt | 710ee0c | 2006-11-05 16:48:42 +0900 | [diff] [blame] | 118 | .mask = disable_se7206_irq, |
| 119 | .unmask = enable_se7206_irq, |
| 120 | .mask_ack = disable_se7206_irq, |
| 121 | .eoi = eoi_se7206_irq, |
Yoshinori Sato | f36af3f | 2006-11-05 16:21:09 +0900 | [diff] [blame] | 122 | }; |
| 123 | |
| 124 | static void make_se7206_irq(unsigned int irq) |
| 125 | { |
| 126 | disable_irq_nosync(irq); |
Paul Mundt | 710ee0c | 2006-11-05 16:48:42 +0900 | [diff] [blame] | 127 | set_irq_chip_and_handler_name(irq, &se7206_irq_chip, |
| 128 | handle_level_irq, "level"); |
Yoshinori Sato | f36af3f | 2006-11-05 16:21:09 +0900 | [diff] [blame] | 129 | disable_se7206_irq(irq); |
| 130 | } |
| 131 | |
| 132 | /* |
| 133 | * Initialize IRQ setting |
| 134 | */ |
| 135 | void __init init_se7206_IRQ(void) |
| 136 | { |
| 137 | make_se7206_irq(IRQ0_IRQ); /* SMC91C111 */ |
| 138 | make_se7206_irq(IRQ1_IRQ); /* ATA */ |
| 139 | make_se7206_irq(IRQ3_IRQ); /* SLOT / PCM */ |
Paul Mundt | 9d56dd3 | 2010-01-26 12:58:40 +0900 | [diff] [blame] | 140 | __raw_writew(inw(INTC_ICR1) | 0x000b ,INTC_ICR1 ) ; /* ICR1 */ |
Yoshinori Sato | f36af3f | 2006-11-05 16:21:09 +0900 | [diff] [blame] | 141 | |
| 142 | /* FPGA System register setup*/ |
Paul Mundt | 9d56dd3 | 2010-01-26 12:58:40 +0900 | [diff] [blame] | 143 | __raw_writew(0x0000,INTSTS0); /* Clear INTSTS0 */ |
| 144 | __raw_writew(0x0000,INTSTS1); /* Clear INTSTS1 */ |
Yoshinori Sato | f36af3f | 2006-11-05 16:21:09 +0900 | [diff] [blame] | 145 | /* IRQ0=LAN, IRQ1=ATA, IRQ3=SLT,PCM */ |
Paul Mundt | 9d56dd3 | 2010-01-26 12:58:40 +0900 | [diff] [blame] | 146 | __raw_writew(0x0001,INTSEL); |
Yoshinori Sato | f36af3f | 2006-11-05 16:21:09 +0900 | [diff] [blame] | 147 | } |