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