1373bbe25SRafal Jaworowski /*-
2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
3af3dc4a7SPedro F. Giffuni *
4373bbe25SRafal Jaworowski * Copyright (c) 2006 Benno Rice.
5373bbe25SRafal Jaworowski * Copyright (C) 2007-2008 MARVELL INTERNATIONAL LTD.
6373bbe25SRafal Jaworowski * All rights reserved.
7373bbe25SRafal Jaworowski *
8373bbe25SRafal Jaworowski * Adapted and extended to Marvell SoCs by Semihalf.
9373bbe25SRafal Jaworowski *
10373bbe25SRafal Jaworowski * Redistribution and use in source and binary forms, with or without
11373bbe25SRafal Jaworowski * modification, are permitted provided that the following conditions
12373bbe25SRafal Jaworowski * are met:
13373bbe25SRafal Jaworowski * 1. Redistributions of source code must retain the above copyright
14373bbe25SRafal Jaworowski * notice, this list of conditions and the following disclaimer.
15373bbe25SRafal Jaworowski * 2. Redistributions in binary form must reproduce the above copyright
16373bbe25SRafal Jaworowski * notice, this list of conditions and the following disclaimer in the
17373bbe25SRafal Jaworowski * documentation and/or other materials provided with the distribution.
18373bbe25SRafal Jaworowski *
19373bbe25SRafal Jaworowski * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20373bbe25SRafal Jaworowski * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21373bbe25SRafal Jaworowski * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22373bbe25SRafal Jaworowski * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23373bbe25SRafal Jaworowski * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24373bbe25SRafal Jaworowski * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25373bbe25SRafal Jaworowski * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26373bbe25SRafal Jaworowski * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27373bbe25SRafal Jaworowski * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28373bbe25SRafal Jaworowski * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29373bbe25SRafal Jaworowski *
30373bbe25SRafal Jaworowski * from: FreeBSD: //depot/projects/arm/src/sys/arm/xscale/pxa2x0/pxa2x0_icu.c, rev 1
31373bbe25SRafal Jaworowski */
32373bbe25SRafal Jaworowski
33373bbe25SRafal Jaworowski #include <sys/param.h>
34373bbe25SRafal Jaworowski #include <sys/systm.h>
35373bbe25SRafal Jaworowski #include <sys/bus.h>
36373bbe25SRafal Jaworowski #include <sys/kernel.h>
37078b894cSMarcel Moolenaar #include <sys/ktr.h>
38373bbe25SRafal Jaworowski #include <sys/module.h>
39373bbe25SRafal Jaworowski #include <sys/rman.h>
40373bbe25SRafal Jaworowski #include <machine/bus.h>
41373bbe25SRafal Jaworowski #include <machine/intr.h>
42373bbe25SRafal Jaworowski
43db5ef4fcSRafal Jaworowski #include <dev/ofw/ofw_bus.h>
44db5ef4fcSRafal Jaworowski #include <dev/ofw/ofw_bus_subr.h>
45db5ef4fcSRafal Jaworowski
46373bbe25SRafal Jaworowski #include <arm/mv/mvreg.h>
47373bbe25SRafal Jaworowski #include <arm/mv/mvvar.h>
48373bbe25SRafal Jaworowski
49373bbe25SRafal Jaworowski struct mv_ic_softc {
50373bbe25SRafal Jaworowski struct resource * ic_res[1];
51373bbe25SRafal Jaworowski bus_space_tag_t ic_bst;
52373bbe25SRafal Jaworowski bus_space_handle_t ic_bsh;
53373bbe25SRafal Jaworowski int ic_high_regs;
54373bbe25SRafal Jaworowski int ic_error_regs;
55373bbe25SRafal Jaworowski };
56373bbe25SRafal Jaworowski
57373bbe25SRafal Jaworowski static struct resource_spec mv_ic_spec[] = {
58373bbe25SRafal Jaworowski { SYS_RES_MEMORY, 0, RF_ACTIVE },
59373bbe25SRafal Jaworowski { -1, 0 }
60373bbe25SRafal Jaworowski };
61373bbe25SRafal Jaworowski
62373bbe25SRafal Jaworowski static struct mv_ic_softc *mv_ic_sc = NULL;
63373bbe25SRafal Jaworowski
64373bbe25SRafal Jaworowski static int mv_ic_probe(device_t);
65373bbe25SRafal Jaworowski static int mv_ic_attach(device_t);
66373bbe25SRafal Jaworowski
67373bbe25SRafal Jaworowski uint32_t mv_ic_get_cause(void);
68373bbe25SRafal Jaworowski uint32_t mv_ic_get_mask(void);
69373bbe25SRafal Jaworowski void mv_ic_set_mask(uint32_t);
70373bbe25SRafal Jaworowski uint32_t mv_ic_get_cause_hi(void);
71373bbe25SRafal Jaworowski uint32_t mv_ic_get_mask_hi(void);
72373bbe25SRafal Jaworowski void mv_ic_set_mask_hi(uint32_t);
73373bbe25SRafal Jaworowski uint32_t mv_ic_get_cause_error(void);
74373bbe25SRafal Jaworowski uint32_t mv_ic_get_mask_error(void);
75373bbe25SRafal Jaworowski void mv_ic_set_mask_error(uint32_t);
76373bbe25SRafal Jaworowski static void arm_mask_irq_all(void);
77373bbe25SRafal Jaworowski
78373bbe25SRafal Jaworowski static int
mv_ic_probe(device_t dev)79373bbe25SRafal Jaworowski mv_ic_probe(device_t dev)
80373bbe25SRafal Jaworowski {
81373bbe25SRafal Jaworowski
82add35ed5SIan Lepore if (!ofw_bus_status_okay(dev))
83add35ed5SIan Lepore return (ENXIO);
84add35ed5SIan Lepore
85db5ef4fcSRafal Jaworowski if (!ofw_bus_is_compatible(dev, "mrvl,pic"))
86db5ef4fcSRafal Jaworowski return (ENXIO);
87db5ef4fcSRafal Jaworowski
88373bbe25SRafal Jaworowski device_set_desc(dev, "Marvell Integrated Interrupt Controller");
89373bbe25SRafal Jaworowski return (0);
90373bbe25SRafal Jaworowski }
91373bbe25SRafal Jaworowski
92373bbe25SRafal Jaworowski static int
mv_ic_attach(device_t dev)93373bbe25SRafal Jaworowski mv_ic_attach(device_t dev)
94373bbe25SRafal Jaworowski {
95373bbe25SRafal Jaworowski struct mv_ic_softc *sc;
96373bbe25SRafal Jaworowski uint32_t dev_id, rev_id;
97373bbe25SRafal Jaworowski int error;
98373bbe25SRafal Jaworowski
99373bbe25SRafal Jaworowski sc = (struct mv_ic_softc *)device_get_softc(dev);
100373bbe25SRafal Jaworowski
101373bbe25SRafal Jaworowski if (mv_ic_sc != NULL)
102373bbe25SRafal Jaworowski return (ENXIO);
103373bbe25SRafal Jaworowski mv_ic_sc = sc;
104373bbe25SRafal Jaworowski
105373bbe25SRafal Jaworowski soc_id(&dev_id, &rev_id);
106373bbe25SRafal Jaworowski
107373bbe25SRafal Jaworowski sc->ic_high_regs = 0;
108373bbe25SRafal Jaworowski sc->ic_error_regs = 0;
109373bbe25SRafal Jaworowski
110c8953e12SHiroki Sato if (dev_id == MV_DEV_88F6281 ||
111c8953e12SHiroki Sato dev_id == MV_DEV_88F6282 ||
112c8953e12SHiroki Sato dev_id == MV_DEV_MV78100 ||
113bc26e2e3SRafal Jaworowski dev_id == MV_DEV_MV78100_Z0)
114373bbe25SRafal Jaworowski sc->ic_high_regs = 1;
115373bbe25SRafal Jaworowski
116bc26e2e3SRafal Jaworowski if (dev_id == MV_DEV_MV78100 || dev_id == MV_DEV_MV78100_Z0)
117373bbe25SRafal Jaworowski sc->ic_error_regs = 1;
118373bbe25SRafal Jaworowski
119373bbe25SRafal Jaworowski error = bus_alloc_resources(dev, mv_ic_spec, sc->ic_res);
120373bbe25SRafal Jaworowski if (error) {
121373bbe25SRafal Jaworowski device_printf(dev, "could not allocate resources\n");
122373bbe25SRafal Jaworowski return (ENXIO);
123373bbe25SRafal Jaworowski }
124373bbe25SRafal Jaworowski
125373bbe25SRafal Jaworowski sc->ic_bst = rman_get_bustag(sc->ic_res[0]);
126373bbe25SRafal Jaworowski sc->ic_bsh = rman_get_bushandle(sc->ic_res[0]);
127373bbe25SRafal Jaworowski
128373bbe25SRafal Jaworowski /* Mask all interrupts */
129373bbe25SRafal Jaworowski arm_mask_irq_all();
130373bbe25SRafal Jaworowski
131373bbe25SRafal Jaworowski return (0);
132373bbe25SRafal Jaworowski }
133373bbe25SRafal Jaworowski
134373bbe25SRafal Jaworowski static device_method_t mv_ic_methods[] = {
135373bbe25SRafal Jaworowski DEVMETHOD(device_probe, mv_ic_probe),
136373bbe25SRafal Jaworowski DEVMETHOD(device_attach, mv_ic_attach),
137373bbe25SRafal Jaworowski { 0, 0 }
138373bbe25SRafal Jaworowski };
139373bbe25SRafal Jaworowski
140373bbe25SRafal Jaworowski static driver_t mv_ic_driver = {
141373bbe25SRafal Jaworowski "ic",
142373bbe25SRafal Jaworowski mv_ic_methods,
143373bbe25SRafal Jaworowski sizeof(struct mv_ic_softc),
144373bbe25SRafal Jaworowski };
145373bbe25SRafal Jaworowski
146a3b866cbSJohn Baldwin DRIVER_MODULE(ic, simplebus, mv_ic_driver, 0, 0);
147373bbe25SRafal Jaworowski
148373bbe25SRafal Jaworowski int
arm_get_next_irq(int last)149078b894cSMarcel Moolenaar arm_get_next_irq(int last)
150373bbe25SRafal Jaworowski {
151078b894cSMarcel Moolenaar u_int filt, irq;
152078b894cSMarcel Moolenaar int next;
153373bbe25SRafal Jaworowski
154078b894cSMarcel Moolenaar filt = ~((last >= 0) ? (2 << last) - 1 : 0);
155373bbe25SRafal Jaworowski irq = mv_ic_get_cause() & mv_ic_get_mask();
156078b894cSMarcel Moolenaar if (irq & filt) {
157078b894cSMarcel Moolenaar next = ffs(irq & filt) - 1;
158078b894cSMarcel Moolenaar goto out;
159078b894cSMarcel Moolenaar }
160373bbe25SRafal Jaworowski if (mv_ic_sc->ic_high_regs) {
161078b894cSMarcel Moolenaar filt = ~((last >= 32) ? (2 << (last - 32)) - 1 : 0);
162373bbe25SRafal Jaworowski irq = mv_ic_get_cause_hi() & mv_ic_get_mask_hi();
163078b894cSMarcel Moolenaar if (irq & filt) {
164078b894cSMarcel Moolenaar next = ffs(irq & filt) + 31;
165078b894cSMarcel Moolenaar goto out;
166373bbe25SRafal Jaworowski }
167078b894cSMarcel Moolenaar }
168373bbe25SRafal Jaworowski if (mv_ic_sc->ic_error_regs) {
169078b894cSMarcel Moolenaar filt = ~((last >= 64) ? (2 << (last - 64)) - 1 : 0);
170373bbe25SRafal Jaworowski irq = mv_ic_get_cause_error() & mv_ic_get_mask_error();
171078b894cSMarcel Moolenaar if (irq & filt) {
172078b894cSMarcel Moolenaar next = ffs(irq & filt) + 63;
173078b894cSMarcel Moolenaar goto out;
174373bbe25SRafal Jaworowski }
175078b894cSMarcel Moolenaar }
176078b894cSMarcel Moolenaar next = -1;
177373bbe25SRafal Jaworowski
178078b894cSMarcel Moolenaar out:
179078b894cSMarcel Moolenaar CTR3(KTR_INTR, "%s: last=%d, next=%d", __func__, last, next);
180078b894cSMarcel Moolenaar return (next);
181373bbe25SRafal Jaworowski }
182373bbe25SRafal Jaworowski
183373bbe25SRafal Jaworowski static void
arm_mask_irq_all(void)184373bbe25SRafal Jaworowski arm_mask_irq_all(void)
185373bbe25SRafal Jaworowski {
186373bbe25SRafal Jaworowski
187373bbe25SRafal Jaworowski mv_ic_set_mask(0);
188373bbe25SRafal Jaworowski
189373bbe25SRafal Jaworowski if (mv_ic_sc->ic_high_regs)
190373bbe25SRafal Jaworowski mv_ic_set_mask_hi(0);
191373bbe25SRafal Jaworowski
192373bbe25SRafal Jaworowski if (mv_ic_sc->ic_error_regs)
193373bbe25SRafal Jaworowski mv_ic_set_mask_error(0);
194373bbe25SRafal Jaworowski }
195373bbe25SRafal Jaworowski
196373bbe25SRafal Jaworowski void
arm_mask_irq(uintptr_t nb)197373bbe25SRafal Jaworowski arm_mask_irq(uintptr_t nb)
198373bbe25SRafal Jaworowski {
199373bbe25SRafal Jaworowski uint32_t mr;
200373bbe25SRafal Jaworowski
201373bbe25SRafal Jaworowski if (nb < 32) {
202373bbe25SRafal Jaworowski mr = mv_ic_get_mask();
203373bbe25SRafal Jaworowski mr &= ~(1 << nb);
204373bbe25SRafal Jaworowski mv_ic_set_mask(mr);
205373bbe25SRafal Jaworowski
206373bbe25SRafal Jaworowski } else if ((nb < 64) && mv_ic_sc->ic_high_regs) {
207373bbe25SRafal Jaworowski mr = mv_ic_get_mask_hi();
208373bbe25SRafal Jaworowski mr &= ~(1 << (nb - 32));
209373bbe25SRafal Jaworowski mv_ic_set_mask_hi(mr);
210373bbe25SRafal Jaworowski
211373bbe25SRafal Jaworowski } else if ((nb < 96) && mv_ic_sc->ic_error_regs) {
212373bbe25SRafal Jaworowski mr = mv_ic_get_mask_error();
213373bbe25SRafal Jaworowski mr &= ~(1 << (nb - 64));
214373bbe25SRafal Jaworowski mv_ic_set_mask_error(mr);
215373bbe25SRafal Jaworowski }
216373bbe25SRafal Jaworowski }
217373bbe25SRafal Jaworowski
218373bbe25SRafal Jaworowski void
arm_unmask_irq(uintptr_t nb)219373bbe25SRafal Jaworowski arm_unmask_irq(uintptr_t nb)
220373bbe25SRafal Jaworowski {
221373bbe25SRafal Jaworowski uint32_t mr;
222373bbe25SRafal Jaworowski
223373bbe25SRafal Jaworowski if (nb < 32) {
224373bbe25SRafal Jaworowski mr = mv_ic_get_mask();
225373bbe25SRafal Jaworowski mr |= (1 << nb);
226373bbe25SRafal Jaworowski mv_ic_set_mask(mr);
227373bbe25SRafal Jaworowski
228373bbe25SRafal Jaworowski } else if ((nb < 64) && mv_ic_sc->ic_high_regs) {
229373bbe25SRafal Jaworowski mr = mv_ic_get_mask_hi();
230373bbe25SRafal Jaworowski mr |= (1 << (nb - 32));
231373bbe25SRafal Jaworowski mv_ic_set_mask_hi(mr);
232373bbe25SRafal Jaworowski
233373bbe25SRafal Jaworowski } else if ((nb < 96) && mv_ic_sc->ic_error_regs) {
234373bbe25SRafal Jaworowski mr = mv_ic_get_mask_error();
235373bbe25SRafal Jaworowski mr |= (1 << (nb - 64));
236373bbe25SRafal Jaworowski mv_ic_set_mask_error(mr);
237373bbe25SRafal Jaworowski }
238373bbe25SRafal Jaworowski }
239373bbe25SRafal Jaworowski
240373bbe25SRafal Jaworowski void
mv_ic_set_mask(uint32_t val)241373bbe25SRafal Jaworowski mv_ic_set_mask(uint32_t val)
242373bbe25SRafal Jaworowski {
243373bbe25SRafal Jaworowski
244373bbe25SRafal Jaworowski bus_space_write_4(mv_ic_sc->ic_bst, mv_ic_sc->ic_bsh,
245373bbe25SRafal Jaworowski IRQ_MASK, val);
246373bbe25SRafal Jaworowski }
247373bbe25SRafal Jaworowski
248373bbe25SRafal Jaworowski uint32_t
mv_ic_get_mask(void)249373bbe25SRafal Jaworowski mv_ic_get_mask(void)
250373bbe25SRafal Jaworowski {
251373bbe25SRafal Jaworowski
252373bbe25SRafal Jaworowski return (bus_space_read_4(mv_ic_sc->ic_bst,
253373bbe25SRafal Jaworowski mv_ic_sc->ic_bsh, IRQ_MASK));
254373bbe25SRafal Jaworowski }
255373bbe25SRafal Jaworowski
256373bbe25SRafal Jaworowski uint32_t
mv_ic_get_cause(void)257373bbe25SRafal Jaworowski mv_ic_get_cause(void)
258373bbe25SRafal Jaworowski {
259373bbe25SRafal Jaworowski
260373bbe25SRafal Jaworowski return (bus_space_read_4(mv_ic_sc->ic_bst,
261373bbe25SRafal Jaworowski mv_ic_sc->ic_bsh, IRQ_CAUSE));
262373bbe25SRafal Jaworowski }
263373bbe25SRafal Jaworowski
264373bbe25SRafal Jaworowski void
mv_ic_set_mask_hi(uint32_t val)265373bbe25SRafal Jaworowski mv_ic_set_mask_hi(uint32_t val)
266373bbe25SRafal Jaworowski {
267373bbe25SRafal Jaworowski
268373bbe25SRafal Jaworowski bus_space_write_4(mv_ic_sc->ic_bst, mv_ic_sc->ic_bsh,
269373bbe25SRafal Jaworowski IRQ_MASK_HI, val);
270373bbe25SRafal Jaworowski }
271373bbe25SRafal Jaworowski
272373bbe25SRafal Jaworowski uint32_t
mv_ic_get_mask_hi(void)273373bbe25SRafal Jaworowski mv_ic_get_mask_hi(void)
274373bbe25SRafal Jaworowski {
275373bbe25SRafal Jaworowski
276373bbe25SRafal Jaworowski return (bus_space_read_4(mv_ic_sc->ic_bst,
277373bbe25SRafal Jaworowski mv_ic_sc->ic_bsh, IRQ_MASK_HI));
278373bbe25SRafal Jaworowski }
279373bbe25SRafal Jaworowski
280373bbe25SRafal Jaworowski uint32_t
mv_ic_get_cause_hi(void)281373bbe25SRafal Jaworowski mv_ic_get_cause_hi(void)
282373bbe25SRafal Jaworowski {
283373bbe25SRafal Jaworowski
284373bbe25SRafal Jaworowski return (bus_space_read_4(mv_ic_sc->ic_bst,
285373bbe25SRafal Jaworowski mv_ic_sc->ic_bsh, IRQ_CAUSE_HI));
286373bbe25SRafal Jaworowski }
287373bbe25SRafal Jaworowski
288373bbe25SRafal Jaworowski void
mv_ic_set_mask_error(uint32_t val)289373bbe25SRafal Jaworowski mv_ic_set_mask_error(uint32_t val)
290373bbe25SRafal Jaworowski {
291373bbe25SRafal Jaworowski
292373bbe25SRafal Jaworowski bus_space_write_4(mv_ic_sc->ic_bst, mv_ic_sc->ic_bsh,
293373bbe25SRafal Jaworowski IRQ_MASK_ERROR, val);
294373bbe25SRafal Jaworowski }
295373bbe25SRafal Jaworowski
296373bbe25SRafal Jaworowski uint32_t
mv_ic_get_mask_error(void)297373bbe25SRafal Jaworowski mv_ic_get_mask_error(void)
298373bbe25SRafal Jaworowski {
299373bbe25SRafal Jaworowski
300373bbe25SRafal Jaworowski return (bus_space_read_4(mv_ic_sc->ic_bst,
301373bbe25SRafal Jaworowski mv_ic_sc->ic_bsh, IRQ_MASK_ERROR));
302373bbe25SRafal Jaworowski }
303373bbe25SRafal Jaworowski
304373bbe25SRafal Jaworowski uint32_t
mv_ic_get_cause_error(void)305373bbe25SRafal Jaworowski mv_ic_get_cause_error(void)
306373bbe25SRafal Jaworowski {
307373bbe25SRafal Jaworowski
308373bbe25SRafal Jaworowski return (bus_space_read_4(mv_ic_sc->ic_bst,
309373bbe25SRafal Jaworowski mv_ic_sc->ic_bsh, IRQ_CAUSE_ERROR));
310373bbe25SRafal Jaworowski }
311