xref: /OK3568_Linux_fs/kernel/drivers/irqchip/irq-or1k-pic.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
4*4882a593Smuzhiyun  * Copyright (C) 2014 Stefan Kristansson <stefan.kristiansson@saunalahti.fi>
5*4882a593Smuzhiyun  */
6*4882a593Smuzhiyun 
7*4882a593Smuzhiyun #include <linux/irq.h>
8*4882a593Smuzhiyun #include <linux/irqchip.h>
9*4882a593Smuzhiyun #include <linux/of.h>
10*4882a593Smuzhiyun #include <linux/of_irq.h>
11*4882a593Smuzhiyun #include <linux/of_address.h>
12*4882a593Smuzhiyun 
13*4882a593Smuzhiyun /* OR1K PIC implementation */
14*4882a593Smuzhiyun 
15*4882a593Smuzhiyun struct or1k_pic_dev {
16*4882a593Smuzhiyun 	struct irq_chip chip;
17*4882a593Smuzhiyun 	irq_flow_handler_t handle;
18*4882a593Smuzhiyun 	unsigned long flags;
19*4882a593Smuzhiyun };
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun /*
22*4882a593Smuzhiyun  * We're a couple of cycles faster than the generic implementations with
23*4882a593Smuzhiyun  * these 'fast' versions.
24*4882a593Smuzhiyun  */
25*4882a593Smuzhiyun 
or1k_pic_mask(struct irq_data * data)26*4882a593Smuzhiyun static void or1k_pic_mask(struct irq_data *data)
27*4882a593Smuzhiyun {
28*4882a593Smuzhiyun 	mtspr(SPR_PICMR, mfspr(SPR_PICMR) & ~(1UL << data->hwirq));
29*4882a593Smuzhiyun }
30*4882a593Smuzhiyun 
or1k_pic_unmask(struct irq_data * data)31*4882a593Smuzhiyun static void or1k_pic_unmask(struct irq_data *data)
32*4882a593Smuzhiyun {
33*4882a593Smuzhiyun 	mtspr(SPR_PICMR, mfspr(SPR_PICMR) | (1UL << data->hwirq));
34*4882a593Smuzhiyun }
35*4882a593Smuzhiyun 
or1k_pic_ack(struct irq_data * data)36*4882a593Smuzhiyun static void or1k_pic_ack(struct irq_data *data)
37*4882a593Smuzhiyun {
38*4882a593Smuzhiyun 	mtspr(SPR_PICSR, (1UL << data->hwirq));
39*4882a593Smuzhiyun }
40*4882a593Smuzhiyun 
or1k_pic_mask_ack(struct irq_data * data)41*4882a593Smuzhiyun static void or1k_pic_mask_ack(struct irq_data *data)
42*4882a593Smuzhiyun {
43*4882a593Smuzhiyun 	mtspr(SPR_PICMR, mfspr(SPR_PICMR) & ~(1UL << data->hwirq));
44*4882a593Smuzhiyun 	mtspr(SPR_PICSR, (1UL << data->hwirq));
45*4882a593Smuzhiyun }
46*4882a593Smuzhiyun 
47*4882a593Smuzhiyun /*
48*4882a593Smuzhiyun  * There are two oddities with the OR1200 PIC implementation:
49*4882a593Smuzhiyun  * i)  LEVEL-triggered interrupts are latched and need to be cleared
50*4882a593Smuzhiyun  * ii) the interrupt latch is cleared by writing a 0 to the bit,
51*4882a593Smuzhiyun  *     as opposed to a 1 as mandated by the spec
52*4882a593Smuzhiyun  */
or1k_pic_or1200_ack(struct irq_data * data)53*4882a593Smuzhiyun static void or1k_pic_or1200_ack(struct irq_data *data)
54*4882a593Smuzhiyun {
55*4882a593Smuzhiyun 	mtspr(SPR_PICSR, mfspr(SPR_PICSR) & ~(1UL << data->hwirq));
56*4882a593Smuzhiyun }
57*4882a593Smuzhiyun 
or1k_pic_or1200_mask_ack(struct irq_data * data)58*4882a593Smuzhiyun static void or1k_pic_or1200_mask_ack(struct irq_data *data)
59*4882a593Smuzhiyun {
60*4882a593Smuzhiyun 	mtspr(SPR_PICMR, mfspr(SPR_PICMR) & ~(1UL << data->hwirq));
61*4882a593Smuzhiyun 	mtspr(SPR_PICSR, mfspr(SPR_PICSR) & ~(1UL << data->hwirq));
62*4882a593Smuzhiyun }
63*4882a593Smuzhiyun 
64*4882a593Smuzhiyun static struct or1k_pic_dev or1k_pic_level = {
65*4882a593Smuzhiyun 	.chip = {
66*4882a593Smuzhiyun 		.name = "or1k-PIC-level",
67*4882a593Smuzhiyun 		.irq_unmask = or1k_pic_unmask,
68*4882a593Smuzhiyun 		.irq_mask = or1k_pic_mask,
69*4882a593Smuzhiyun 	},
70*4882a593Smuzhiyun 	.handle = handle_level_irq,
71*4882a593Smuzhiyun 	.flags = IRQ_LEVEL | IRQ_NOPROBE,
72*4882a593Smuzhiyun };
73*4882a593Smuzhiyun 
74*4882a593Smuzhiyun static struct or1k_pic_dev or1k_pic_edge = {
75*4882a593Smuzhiyun 	.chip = {
76*4882a593Smuzhiyun 		.name = "or1k-PIC-edge",
77*4882a593Smuzhiyun 		.irq_unmask = or1k_pic_unmask,
78*4882a593Smuzhiyun 		.irq_mask = or1k_pic_mask,
79*4882a593Smuzhiyun 		.irq_ack = or1k_pic_ack,
80*4882a593Smuzhiyun 		.irq_mask_ack = or1k_pic_mask_ack,
81*4882a593Smuzhiyun 	},
82*4882a593Smuzhiyun 	.handle = handle_edge_irq,
83*4882a593Smuzhiyun 	.flags = IRQ_LEVEL | IRQ_NOPROBE,
84*4882a593Smuzhiyun };
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun static struct or1k_pic_dev or1k_pic_or1200 = {
87*4882a593Smuzhiyun 	.chip = {
88*4882a593Smuzhiyun 		.name = "or1200-PIC",
89*4882a593Smuzhiyun 		.irq_unmask = or1k_pic_unmask,
90*4882a593Smuzhiyun 		.irq_mask = or1k_pic_mask,
91*4882a593Smuzhiyun 		.irq_ack = or1k_pic_or1200_ack,
92*4882a593Smuzhiyun 		.irq_mask_ack = or1k_pic_or1200_mask_ack,
93*4882a593Smuzhiyun 	},
94*4882a593Smuzhiyun 	.handle = handle_level_irq,
95*4882a593Smuzhiyun 	.flags = IRQ_LEVEL | IRQ_NOPROBE,
96*4882a593Smuzhiyun };
97*4882a593Smuzhiyun 
98*4882a593Smuzhiyun static struct irq_domain *root_domain;
99*4882a593Smuzhiyun 
pic_get_irq(int first)100*4882a593Smuzhiyun static inline int pic_get_irq(int first)
101*4882a593Smuzhiyun {
102*4882a593Smuzhiyun 	int hwirq;
103*4882a593Smuzhiyun 
104*4882a593Smuzhiyun 	hwirq = ffs(mfspr(SPR_PICSR) >> first);
105*4882a593Smuzhiyun 	if (!hwirq)
106*4882a593Smuzhiyun 		return NO_IRQ;
107*4882a593Smuzhiyun 	else
108*4882a593Smuzhiyun 		hwirq = hwirq + first - 1;
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun 	return hwirq;
111*4882a593Smuzhiyun }
112*4882a593Smuzhiyun 
or1k_pic_handle_irq(struct pt_regs * regs)113*4882a593Smuzhiyun static void or1k_pic_handle_irq(struct pt_regs *regs)
114*4882a593Smuzhiyun {
115*4882a593Smuzhiyun 	int irq = -1;
116*4882a593Smuzhiyun 
117*4882a593Smuzhiyun 	while ((irq = pic_get_irq(irq + 1)) != NO_IRQ)
118*4882a593Smuzhiyun 		handle_domain_irq(root_domain, irq, regs);
119*4882a593Smuzhiyun }
120*4882a593Smuzhiyun 
or1k_map(struct irq_domain * d,unsigned int irq,irq_hw_number_t hw)121*4882a593Smuzhiyun static int or1k_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
122*4882a593Smuzhiyun {
123*4882a593Smuzhiyun 	struct or1k_pic_dev *pic = d->host_data;
124*4882a593Smuzhiyun 
125*4882a593Smuzhiyun 	irq_set_chip_and_handler(irq, &pic->chip, pic->handle);
126*4882a593Smuzhiyun 	irq_set_status_flags(irq, pic->flags);
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun 	return 0;
129*4882a593Smuzhiyun }
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun static const struct irq_domain_ops or1k_irq_domain_ops = {
132*4882a593Smuzhiyun 	.xlate = irq_domain_xlate_onecell,
133*4882a593Smuzhiyun 	.map = or1k_map,
134*4882a593Smuzhiyun };
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun /*
137*4882a593Smuzhiyun  * This sets up the IRQ domain for the PIC built in to the OpenRISC
138*4882a593Smuzhiyun  * 1000 CPU.  This is the "root" domain as these are the interrupts
139*4882a593Smuzhiyun  * that directly trigger an exception in the CPU.
140*4882a593Smuzhiyun  */
or1k_pic_init(struct device_node * node,struct or1k_pic_dev * pic)141*4882a593Smuzhiyun static int __init or1k_pic_init(struct device_node *node,
142*4882a593Smuzhiyun 				 struct or1k_pic_dev *pic)
143*4882a593Smuzhiyun {
144*4882a593Smuzhiyun 	/* Disable all interrupts until explicitly requested */
145*4882a593Smuzhiyun 	mtspr(SPR_PICMR, (0UL));
146*4882a593Smuzhiyun 
147*4882a593Smuzhiyun 	root_domain = irq_domain_add_linear(node, 32, &or1k_irq_domain_ops,
148*4882a593Smuzhiyun 					    pic);
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun 	set_handle_irq(or1k_pic_handle_irq);
151*4882a593Smuzhiyun 
152*4882a593Smuzhiyun 	return 0;
153*4882a593Smuzhiyun }
154*4882a593Smuzhiyun 
or1k_pic_or1200_init(struct device_node * node,struct device_node * parent)155*4882a593Smuzhiyun static int __init or1k_pic_or1200_init(struct device_node *node,
156*4882a593Smuzhiyun 				       struct device_node *parent)
157*4882a593Smuzhiyun {
158*4882a593Smuzhiyun 	return or1k_pic_init(node, &or1k_pic_or1200);
159*4882a593Smuzhiyun }
160*4882a593Smuzhiyun IRQCHIP_DECLARE(or1k_pic_or1200, "opencores,or1200-pic", or1k_pic_or1200_init);
161*4882a593Smuzhiyun IRQCHIP_DECLARE(or1k_pic, "opencores,or1k-pic", or1k_pic_or1200_init);
162*4882a593Smuzhiyun 
or1k_pic_level_init(struct device_node * node,struct device_node * parent)163*4882a593Smuzhiyun static int __init or1k_pic_level_init(struct device_node *node,
164*4882a593Smuzhiyun 				      struct device_node *parent)
165*4882a593Smuzhiyun {
166*4882a593Smuzhiyun 	return or1k_pic_init(node, &or1k_pic_level);
167*4882a593Smuzhiyun }
168*4882a593Smuzhiyun IRQCHIP_DECLARE(or1k_pic_level, "opencores,or1k-pic-level",
169*4882a593Smuzhiyun 		or1k_pic_level_init);
170*4882a593Smuzhiyun 
or1k_pic_edge_init(struct device_node * node,struct device_node * parent)171*4882a593Smuzhiyun static int __init or1k_pic_edge_init(struct device_node *node,
172*4882a593Smuzhiyun 				     struct device_node *parent)
173*4882a593Smuzhiyun {
174*4882a593Smuzhiyun 	return or1k_pic_init(node, &or1k_pic_edge);
175*4882a593Smuzhiyun }
176*4882a593Smuzhiyun IRQCHIP_DECLARE(or1k_pic_edge, "opencores,or1k-pic-edge", or1k_pic_edge_init);
177