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