mvsoc_intr.c revision 1.4 1 /* $NetBSD: mvsoc_intr.c,v 1.4 2012/07/22 17:14:18 jakllsch Exp $ */
2 /*
3 * Copyright (c) 2010 KIYOHARA Takashi
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
19 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
23 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
24 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
26 */
27
28 #include <sys/cdefs.h>
29 __KERNEL_RCSID(0, "$NetBSD: mvsoc_intr.c,v 1.4 2012/07/22 17:14:18 jakllsch Exp $");
30
31 #define _INTR_PRIVATE
32
33 #include <sys/param.h>
34 #include <sys/proc.h>
35
36 #include <machine/intr.h>
37
38 #include <arm/cpu.h>
39 #include <arm/pic/picvar.h>
40 #include <arm/marvell/mvsocreg.h>
41 #include <arm/marvell/mvsocvar.h>
42
43
44 static void mvsoc_bridge_pic_unblock_irqs(struct pic_softc *, size_t, uint32_t);
45 static void mvsoc_bridge_pic_block_irqs(struct pic_softc *, size_t, uint32_t);
46 static int mvsoc_bridge_pic_find_pending_irqs(struct pic_softc *);
47 static void mvsoc_bridge_pic_establish_irq(struct pic_softc *,
48 struct intrsource *);
49 static void mvsoc_bridge_pic_source_name(struct pic_softc *, int, char *,
50 size_t);
51
52 static const char * const sources[] = {
53 "CPUSelfInt", "CPUTimer0IntReq", "CPUTimer1IntReq", "CPUWDTimerIntReq",
54 "AccessErr", "Bit64Err",
55 };
56
57 static struct pic_ops mvsoc_bridge_picops = {
58 .pic_unblock_irqs = mvsoc_bridge_pic_unblock_irqs,
59 .pic_block_irqs = mvsoc_bridge_pic_block_irqs,
60 .pic_find_pending_irqs = mvsoc_bridge_pic_find_pending_irqs,
61 .pic_establish_irq = mvsoc_bridge_pic_establish_irq,
62 .pic_source_name = mvsoc_bridge_pic_source_name,
63 };
64
65 struct pic_softc mvsoc_bridge_pic = {
66 .pic_ops = &mvsoc_bridge_picops,
67 .pic_maxsources = MVSOC_MLMB_MLMBI_NIRQ,
68 .pic_name = "mvsoc_bridge",
69 };
70
71
72 void
73 mvsoc_irq_handler(void *frame)
74 {
75 struct cpu_info * const ci = curcpu();
76 const int oldipl = ci->ci_cpl;
77 const uint32_t oldipl_mask = __BIT(oldipl);
78 int ipl_mask = 0;
79
80 ci->ci_data.cpu_nintr++;
81
82 ipl_mask = find_pending_irqs();
83
84 /*
85 * Record the pending_ipls and deliver them if we can.
86 */
87 if ((ipl_mask & ~oldipl_mask) > oldipl_mask)
88 pic_do_pending_ints(I32_bit, oldipl, frame);
89 }
90
91 /*
92 * Mbus-L to Mbus bridge
93 */
94
95 void *
96 mvsoc_bridge_intr_establish(int ih, int ipl, int (*ih_func)(void *), void *arg)
97 {
98
99 return intr_establish(mvsoc_bridge_pic.pic_irqbase + ih, ipl,
100 IST_LEVEL_HIGH, ih_func, arg);
101 }
102
103 /* ARGSUSED */
104 static void
105 mvsoc_bridge_pic_unblock_irqs(struct pic_softc *pic, size_t irqbase,
106 uint32_t irq_mask)
107 {
108
109 write_mlmbreg(MVSOC_MLMB_MLMBICR,
110 read_mlmbreg(MVSOC_MLMB_MLMBICR) & ~irq_mask);
111 write_mlmbreg(MVSOC_MLMB_MLMBIMR,
112 read_mlmbreg(MVSOC_MLMB_MLMBIMR) | irq_mask);
113 }
114
115 /* ARGSUSED */
116 static void
117 mvsoc_bridge_pic_block_irqs(struct pic_softc *pic, size_t irqbase,
118 uint32_t irq_mask)
119 {
120
121 write_mlmbreg(MVSOC_MLMB_MLMBIMR,
122 read_mlmbreg(MVSOC_MLMB_MLMBIMR) & ~irq_mask);
123 }
124
125 static int
126 mvsoc_bridge_pic_find_pending_irqs(struct pic_softc *pic)
127 {
128 uint32_t pending;
129
130 pending =
131 read_mlmbreg(MVSOC_MLMB_MLMBICR) & read_mlmbreg(MVSOC_MLMB_MLMBIMR);
132
133 if (pending == 0)
134 return 0;
135
136 return pic_mark_pending_sources(pic, 0, pending);
137 }
138
139 /* ARGSUSED */
140 static void
141 mvsoc_bridge_pic_establish_irq(struct pic_softc *pic, struct intrsource *is)
142 {
143 /* Nothing */
144 }
145
146 static void
147 mvsoc_bridge_pic_source_name(struct pic_softc *pic, int irq, char *buf,
148 size_t len)
149 {
150
151 strlcpy(buf, sources[irq], len);
152 }
153