xref: /freebsd-src/sys/arm/mv/ic.c (revision fdafd315ad0d0f28a11b9fb4476a9ab059c62b92)
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