xref: /freebsd/sys/dev/quicc/quicc_core.c (revision 9dbf5b0e)
1e1ef7811SRafal Jaworowski /*-
2718cf2ccSPedro F. Giffuni  * SPDX-License-Identifier: BSD-3-Clause
3718cf2ccSPedro F. Giffuni  *
4e1ef7811SRafal Jaworowski  * Copyright 2006 by Juniper Networks.
5e1ef7811SRafal Jaworowski  * All rights reserved.
6e1ef7811SRafal Jaworowski  *
7e1ef7811SRafal Jaworowski  * Redistribution and use in source and binary forms, with or without
8e1ef7811SRafal Jaworowski  * modification, are permitted provided that the following conditions
9e1ef7811SRafal Jaworowski  * are met:
10e1ef7811SRafal Jaworowski  * 1. Redistributions of source code must retain the above copyright
11e1ef7811SRafal Jaworowski  *    notice, this list of conditions and the following disclaimer.
12e1ef7811SRafal Jaworowski  * 2. Redistributions in binary form must reproduce the above copyright
13e1ef7811SRafal Jaworowski  *    notice, this list of conditions and the following disclaimer in the
14e1ef7811SRafal Jaworowski  *    documentation and/or other materials provided with the distribution.
15e1ef7811SRafal Jaworowski  * 3. The name of the author may not be used to endorse or promote products
16e1ef7811SRafal Jaworowski  *    derived from this software without specific prior written permission.
17e1ef7811SRafal Jaworowski  *
18e1ef7811SRafal Jaworowski  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19e1ef7811SRafal Jaworowski  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20e1ef7811SRafal Jaworowski  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21e1ef7811SRafal Jaworowski  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22e1ef7811SRafal Jaworowski  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23e1ef7811SRafal Jaworowski  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24e1ef7811SRafal Jaworowski  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
25e1ef7811SRafal Jaworowski  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26e1ef7811SRafal Jaworowski  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27e1ef7811SRafal Jaworowski  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28e1ef7811SRafal Jaworowski  * SUCH DAMAGE.
29e1ef7811SRafal Jaworowski  */
30e1ef7811SRafal Jaworowski 
31e1ef7811SRafal Jaworowski #include <sys/param.h>
32e1ef7811SRafal Jaworowski #include <sys/systm.h>
33e1ef7811SRafal Jaworowski #include <sys/bus.h>
34e1ef7811SRafal Jaworowski #include <sys/conf.h>
35e1ef7811SRafal Jaworowski #include <sys/endian.h>
36e1ef7811SRafal Jaworowski #include <sys/kernel.h>
37e1ef7811SRafal Jaworowski #include <sys/malloc.h>
38e1ef7811SRafal Jaworowski #include <sys/queue.h>
39e1ef7811SRafal Jaworowski #include <sys/serial.h>
40e1ef7811SRafal Jaworowski 
41e1ef7811SRafal Jaworowski #include <machine/bus.h>
42e1ef7811SRafal Jaworowski #include <machine/resource.h>
43e1ef7811SRafal Jaworowski #include <sys/rman.h>
44e1ef7811SRafal Jaworowski 
45e1ef7811SRafal Jaworowski #include <dev/ic/quicc.h>
46e1ef7811SRafal Jaworowski 
47e1ef7811SRafal Jaworowski #include <dev/quicc/quicc_bfe.h>
48e1ef7811SRafal Jaworowski #include <dev/quicc/quicc_bus.h>
49e1ef7811SRafal Jaworowski 
50e1ef7811SRafal Jaworowski #define	quicc_read2(r, o)	\
51e1ef7811SRafal Jaworowski 	bus_space_read_2((r)->r_bustag, (r)->r_bushandle, o)
52e1ef7811SRafal Jaworowski #define	quicc_read4(r, o)	\
53e1ef7811SRafal Jaworowski 	bus_space_read_4((r)->r_bustag, (r)->r_bushandle, o)
54e1ef7811SRafal Jaworowski 
55e1ef7811SRafal Jaworowski #define	quicc_write2(r, o, v)	\
56e1ef7811SRafal Jaworowski 	bus_space_write_2((r)->r_bustag, (r)->r_bushandle, o, v)
57e1ef7811SRafal Jaworowski #define	quicc_write4(r, o, v)	\
58e1ef7811SRafal Jaworowski 	bus_space_write_4((r)->r_bustag, (r)->r_bushandle, o, v)
59e1ef7811SRafal Jaworowski 
60e1ef7811SRafal Jaworowski char quicc_driver_name[] = "quicc";
61e1ef7811SRafal Jaworowski 
62d745c852SEd Schouten static MALLOC_DEFINE(M_QUICC, "QUICC", "QUICC driver");
63e1ef7811SRafal Jaworowski 
64e1ef7811SRafal Jaworowski struct quicc_device {
65e1ef7811SRafal Jaworowski 	struct rman	*qd_rman;
66e1ef7811SRafal Jaworowski 	struct resource_list qd_rlist;
67e1ef7811SRafal Jaworowski 	device_t	qd_dev;
68e1ef7811SRafal Jaworowski 	int		qd_devtype;
69e1ef7811SRafal Jaworowski 
70e1ef7811SRafal Jaworowski 	driver_filter_t	*qd_ih;
71e1ef7811SRafal Jaworowski 	void		*qd_ih_arg;
72e1ef7811SRafal Jaworowski };
73e1ef7811SRafal Jaworowski 
74e1ef7811SRafal Jaworowski static int
quicc_bfe_intr(void * arg)75e1ef7811SRafal Jaworowski quicc_bfe_intr(void *arg)
76e1ef7811SRafal Jaworowski {
77e1ef7811SRafal Jaworowski 	struct quicc_device *qd;
78e1ef7811SRafal Jaworowski 	struct quicc_softc *sc = arg;
79e1ef7811SRafal Jaworowski 	uint32_t sipnr;
80e1ef7811SRafal Jaworowski 
81e1ef7811SRafal Jaworowski 	sipnr = quicc_read4(sc->sc_rres, QUICC_REG_SIPNR_L);
82e1ef7811SRafal Jaworowski 	if (sipnr & 0x00f00000)
83e1ef7811SRafal Jaworowski 		qd = sc->sc_device;
84e1ef7811SRafal Jaworowski 	else
85e1ef7811SRafal Jaworowski 		qd = NULL;
86e1ef7811SRafal Jaworowski 
87e1ef7811SRafal Jaworowski 	if (qd == NULL || qd->qd_ih == NULL) {
88e1ef7811SRafal Jaworowski 		device_printf(sc->sc_dev, "Stray interrupt %08x\n", sipnr);
89e1ef7811SRafal Jaworowski 		return (FILTER_STRAY);
90e1ef7811SRafal Jaworowski 	}
91e1ef7811SRafal Jaworowski 
92e1ef7811SRafal Jaworowski 	return ((*qd->qd_ih)(qd->qd_ih_arg));
93e1ef7811SRafal Jaworowski }
94e1ef7811SRafal Jaworowski 
95e1ef7811SRafal Jaworowski int
quicc_bfe_attach(device_t dev)96e1ef7811SRafal Jaworowski quicc_bfe_attach(device_t dev)
97e1ef7811SRafal Jaworowski {
98e1ef7811SRafal Jaworowski 	struct quicc_device *qd;
99e1ef7811SRafal Jaworowski 	struct quicc_softc *sc;
100e1ef7811SRafal Jaworowski 	struct resource_list_entry *rle;
101e1ef7811SRafal Jaworowski 	const char *sep;
1022dd1bdf1SJustin Hibbits 	rman_res_t size, start;
103e1ef7811SRafal Jaworowski 	int error;
104e1ef7811SRafal Jaworowski 
105e1ef7811SRafal Jaworowski 	sc = device_get_softc(dev);
106e1ef7811SRafal Jaworowski 
107e1ef7811SRafal Jaworowski 	/*
108e1ef7811SRafal Jaworowski 	 * Re-allocate. We expect that the softc contains the information
109e1ef7811SRafal Jaworowski 	 * collected by quicc_bfe_probe() intact.
110e1ef7811SRafal Jaworowski 	 */
11143cd6160SJustin Hibbits 	sc->sc_rres = bus_alloc_resource_any(dev, sc->sc_rtype, &sc->sc_rrid,
11243cd6160SJustin Hibbits 	    RF_ACTIVE);
113e1ef7811SRafal Jaworowski 	if (sc->sc_rres == NULL)
114e1ef7811SRafal Jaworowski 		return (ENXIO);
115e1ef7811SRafal Jaworowski 
116e1ef7811SRafal Jaworowski 	start = rman_get_start(sc->sc_rres);
117e1ef7811SRafal Jaworowski 	size = rman_get_size(sc->sc_rres);
118e1ef7811SRafal Jaworowski 
119e1ef7811SRafal Jaworowski 	sc->sc_rman.rm_start = start;
120e1ef7811SRafal Jaworowski 	sc->sc_rman.rm_end = start + size - 1;
121e1ef7811SRafal Jaworowski 	sc->sc_rman.rm_type = RMAN_ARRAY;
122e1ef7811SRafal Jaworowski 	sc->sc_rman.rm_descr = "QUICC resources";
123e1ef7811SRafal Jaworowski 	error = rman_init(&sc->sc_rman);
124e1ef7811SRafal Jaworowski 	if (!error)
125e1ef7811SRafal Jaworowski 		error = rman_manage_region(&sc->sc_rman, start,
126e1ef7811SRafal Jaworowski 		    start + size - 1);
127e1ef7811SRafal Jaworowski 	if (error) {
128e1ef7811SRafal Jaworowski 		bus_release_resource(dev, sc->sc_rtype, sc->sc_rrid,
129e1ef7811SRafal Jaworowski 		    sc->sc_rres);
130e1ef7811SRafal Jaworowski 		return (error);
131e1ef7811SRafal Jaworowski 	}
132e1ef7811SRafal Jaworowski 
133e1ef7811SRafal Jaworowski 	/*
134e1ef7811SRafal Jaworowski 	 * Allocate interrupt resource.
135e1ef7811SRafal Jaworowski 	 */
136e1ef7811SRafal Jaworowski 	sc->sc_irid = 0;
137e1ef7811SRafal Jaworowski 	sc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_irid,
138e1ef7811SRafal Jaworowski 	    RF_ACTIVE | RF_SHAREABLE);
139e1ef7811SRafal Jaworowski 
140e1ef7811SRafal Jaworowski 	if (sc->sc_ires != NULL) {
141e1ef7811SRafal Jaworowski 		error = bus_setup_intr(dev, sc->sc_ires,
142e1ef7811SRafal Jaworowski 		    INTR_TYPE_TTY, quicc_bfe_intr, NULL, sc, &sc->sc_icookie);
143e1ef7811SRafal Jaworowski 		if (error) {
144e1ef7811SRafal Jaworowski 			error = bus_setup_intr(dev, sc->sc_ires,
145e1ef7811SRafal Jaworowski 			    INTR_TYPE_TTY | INTR_MPSAFE, NULL,
146e1ef7811SRafal Jaworowski 			    (driver_intr_t *)quicc_bfe_intr, sc,
147e1ef7811SRafal Jaworowski 			    &sc->sc_icookie);
148e1ef7811SRafal Jaworowski 		} else
149e1ef7811SRafal Jaworowski 			sc->sc_fastintr = 1;
150e1ef7811SRafal Jaworowski 		if (error) {
151e1ef7811SRafal Jaworowski 			device_printf(dev, "could not activate interrupt\n");
152e1ef7811SRafal Jaworowski 			bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid,
153e1ef7811SRafal Jaworowski 			    sc->sc_ires);
154e1ef7811SRafal Jaworowski 			sc->sc_ires = NULL;
155e1ef7811SRafal Jaworowski 		}
156e1ef7811SRafal Jaworowski 	}
157e1ef7811SRafal Jaworowski 
158e1ef7811SRafal Jaworowski 	if (sc->sc_ires == NULL)
159e1ef7811SRafal Jaworowski 		sc->sc_polled = 1;
160e1ef7811SRafal Jaworowski 
161e1ef7811SRafal Jaworowski 	if (bootverbose && (sc->sc_fastintr || sc->sc_polled)) {
162e1ef7811SRafal Jaworowski 		sep = "";
163e1ef7811SRafal Jaworowski 		device_print_prettyname(dev);
164e1ef7811SRafal Jaworowski 		if (sc->sc_fastintr) {
165e1ef7811SRafal Jaworowski 			printf("%sfast interrupt", sep);
166e1ef7811SRafal Jaworowski 			sep = ", ";
167e1ef7811SRafal Jaworowski 		}
168e1ef7811SRafal Jaworowski 		if (sc->sc_polled) {
169e1ef7811SRafal Jaworowski 			printf("%spolled mode", sep);
170e1ef7811SRafal Jaworowski 			sep = ", ";
171e1ef7811SRafal Jaworowski 		}
172e1ef7811SRafal Jaworowski 		printf("\n");
173e1ef7811SRafal Jaworowski 	}
174e1ef7811SRafal Jaworowski 
175e1ef7811SRafal Jaworowski 	sc->sc_device = qd = malloc(sizeof(struct quicc_device), M_QUICC,
176e1ef7811SRafal Jaworowski 	    M_WAITOK | M_ZERO);
177e1ef7811SRafal Jaworowski 
178e1ef7811SRafal Jaworowski 	qd->qd_devtype = QUICC_DEVTYPE_SCC;
179e1ef7811SRafal Jaworowski 	qd->qd_rman = &sc->sc_rman;
180e1ef7811SRafal Jaworowski 	resource_list_init(&qd->qd_rlist);
181e1ef7811SRafal Jaworowski 
182e1ef7811SRafal Jaworowski 	resource_list_add(&qd->qd_rlist, sc->sc_rtype, 0, start,
183e1ef7811SRafal Jaworowski 	    start + size - 1, size);
184e1ef7811SRafal Jaworowski 
185e1ef7811SRafal Jaworowski 	resource_list_add(&qd->qd_rlist, SYS_RES_IRQ, 0, 0xf00, 0xf00, 1);
186e1ef7811SRafal Jaworowski 	rle = resource_list_find(&qd->qd_rlist, SYS_RES_IRQ, 0);
187e1ef7811SRafal Jaworowski 	rle->res = sc->sc_ires;
188e1ef7811SRafal Jaworowski 
189e1ef7811SRafal Jaworowski 	qd->qd_dev = device_add_child(dev, NULL, -1);
190e1ef7811SRafal Jaworowski 	device_set_ivars(qd->qd_dev, (void *)qd);
191e1ef7811SRafal Jaworowski 	error = device_probe_and_attach(qd->qd_dev);
192e1ef7811SRafal Jaworowski 
193e1ef7811SRafal Jaworowski 	/* Enable all SCC interrupts. */
194e1ef7811SRafal Jaworowski 	quicc_write4(sc->sc_rres, QUICC_REG_SIMR_L, 0x00f00000);
195e1ef7811SRafal Jaworowski 
196e1ef7811SRafal Jaworowski 	/* Clear all pending interrupts. */
197e1ef7811SRafal Jaworowski 	quicc_write4(sc->sc_rres, QUICC_REG_SIPNR_H, ~0);
198e1ef7811SRafal Jaworowski 	quicc_write4(sc->sc_rres, QUICC_REG_SIPNR_L, ~0);
199e1ef7811SRafal Jaworowski 	return (error);
200e1ef7811SRafal Jaworowski }
201e1ef7811SRafal Jaworowski 
202e1ef7811SRafal Jaworowski int
quicc_bfe_detach(device_t dev)203e1ef7811SRafal Jaworowski quicc_bfe_detach(device_t dev)
204e1ef7811SRafal Jaworowski {
205e1ef7811SRafal Jaworowski 	struct quicc_softc *sc;
206e1ef7811SRafal Jaworowski 
207e1ef7811SRafal Jaworowski 	sc = device_get_softc(dev);
208e1ef7811SRafal Jaworowski 
209e1ef7811SRafal Jaworowski 	bus_teardown_intr(dev, sc->sc_ires, sc->sc_icookie);
210e1ef7811SRafal Jaworowski 	bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid, sc->sc_ires);
211e1ef7811SRafal Jaworowski 	bus_release_resource(dev, sc->sc_rtype, sc->sc_rrid, sc->sc_rres);
212e1ef7811SRafal Jaworowski 	return (0);
213e1ef7811SRafal Jaworowski }
214e1ef7811SRafal Jaworowski 
215e1ef7811SRafal Jaworowski int
quicc_bfe_probe(device_t dev,u_int clock)216e1ef7811SRafal Jaworowski quicc_bfe_probe(device_t dev, u_int clock)
217e1ef7811SRafal Jaworowski {
218e1ef7811SRafal Jaworowski 	struct quicc_softc *sc;
219e1ef7811SRafal Jaworowski 	uint16_t rev;
220e1ef7811SRafal Jaworowski 
221e1ef7811SRafal Jaworowski 	sc = device_get_softc(dev);
222e1ef7811SRafal Jaworowski 	sc->sc_dev = dev;
223e1ef7811SRafal Jaworowski 	if (device_get_desc(dev) == NULL)
224e1ef7811SRafal Jaworowski 		device_set_desc(dev,
225e1ef7811SRafal Jaworowski 		    "Quad integrated communications controller");
226e1ef7811SRafal Jaworowski 
227e1ef7811SRafal Jaworowski 	sc->sc_rrid = 0;
228e1ef7811SRafal Jaworowski 	sc->sc_rtype = SYS_RES_MEMORY;
22943cd6160SJustin Hibbits 	sc->sc_rres = bus_alloc_resource_any(dev, sc->sc_rtype, &sc->sc_rrid,
23043cd6160SJustin Hibbits 	    RF_ACTIVE);
231e1ef7811SRafal Jaworowski 	if (sc->sc_rres == NULL) {
232e1ef7811SRafal Jaworowski 		sc->sc_rrid = 0;
233e1ef7811SRafal Jaworowski 		sc->sc_rtype = SYS_RES_IOPORT;
23443cd6160SJustin Hibbits 		sc->sc_rres = bus_alloc_resource_any(dev, sc->sc_rtype,
23543cd6160SJustin Hibbits 		    &sc->sc_rrid, RF_ACTIVE);
236e1ef7811SRafal Jaworowski 		if (sc->sc_rres == NULL)
237e1ef7811SRafal Jaworowski 			return (ENXIO);
238e1ef7811SRafal Jaworowski 	}
239e1ef7811SRafal Jaworowski 
240e1ef7811SRafal Jaworowski 	sc->sc_clock = clock;
241e1ef7811SRafal Jaworowski 
242e1ef7811SRafal Jaworowski 	/*
243e1ef7811SRafal Jaworowski 	 * Check that the microcode revision is 0x00e8, as documented
244e1ef7811SRafal Jaworowski 	 * in the MPC8555E PowerQUICC III Integrated Processor Family
245e1ef7811SRafal Jaworowski 	 * Reference Manual.
246e1ef7811SRafal Jaworowski 	 */
247e1ef7811SRafal Jaworowski 	rev = quicc_read2(sc->sc_rres, QUICC_PRAM_REV_NUM);
248e1ef7811SRafal Jaworowski 
249e1ef7811SRafal Jaworowski 	bus_release_resource(dev, sc->sc_rtype, sc->sc_rrid, sc->sc_rres);
250e1ef7811SRafal Jaworowski 	return ((rev == 0x00e8) ? BUS_PROBE_DEFAULT : ENXIO);
251e1ef7811SRafal Jaworowski }
252e1ef7811SRafal Jaworowski 
253e1ef7811SRafal Jaworowski struct resource *
quicc_bus_alloc_resource(device_t dev,device_t child,int type,int * rid,rman_res_t start,rman_res_t end,rman_res_t count,u_int flags)254e1ef7811SRafal Jaworowski quicc_bus_alloc_resource(device_t dev, device_t child, int type, int *rid,
2552dd1bdf1SJustin Hibbits     rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
256e1ef7811SRafal Jaworowski {
257e1ef7811SRafal Jaworowski 	struct quicc_device *qd;
258e1ef7811SRafal Jaworowski 	struct resource_list_entry *rle;
259e1ef7811SRafal Jaworowski 
260e1ef7811SRafal Jaworowski 	if (device_get_parent(child) != dev)
261e1ef7811SRafal Jaworowski 		return (NULL);
262e1ef7811SRafal Jaworowski 
263e1ef7811SRafal Jaworowski 	/* We only support default allocations. */
26482ed3cb0SJustin Hibbits 	if (!RMAN_IS_DEFAULT_RANGE(start, end))
265e1ef7811SRafal Jaworowski 		return (NULL);
266e1ef7811SRafal Jaworowski 
267e1ef7811SRafal Jaworowski 	qd = device_get_ivars(child);
268e1ef7811SRafal Jaworowski 	rle = resource_list_find(&qd->qd_rlist, type, *rid);
269e1ef7811SRafal Jaworowski 	if (rle == NULL)
270e1ef7811SRafal Jaworowski 		return (NULL);
271e1ef7811SRafal Jaworowski 
272e1ef7811SRafal Jaworowski 	if (rle->res == NULL) {
273e1ef7811SRafal Jaworowski 		rle->res = rman_reserve_resource(qd->qd_rman, rle->start,
274e1ef7811SRafal Jaworowski 		    rle->start + rle->count - 1, rle->count, flags, child);
275e1ef7811SRafal Jaworowski 		if (rle->res != NULL) {
276e1ef7811SRafal Jaworowski 			rman_set_bustag(rle->res, &bs_be_tag);
277e1ef7811SRafal Jaworowski 			rman_set_bushandle(rle->res, rle->start);
278e1ef7811SRafal Jaworowski 		}
279e1ef7811SRafal Jaworowski 	}
280e1ef7811SRafal Jaworowski 	return (rle->res);
281e1ef7811SRafal Jaworowski }
282e1ef7811SRafal Jaworowski 
283e1ef7811SRafal Jaworowski int
quicc_bus_get_resource(device_t dev,device_t child,int type,int rid,rman_res_t * startp,rman_res_t * countp)284e1ef7811SRafal Jaworowski quicc_bus_get_resource(device_t dev, device_t child, int type, int rid,
2852dd1bdf1SJustin Hibbits     rman_res_t *startp, rman_res_t *countp)
286e1ef7811SRafal Jaworowski {
287e1ef7811SRafal Jaworowski 	struct quicc_device *qd;
288e1ef7811SRafal Jaworowski 	struct resource_list_entry *rle;
289e1ef7811SRafal Jaworowski 
290e1ef7811SRafal Jaworowski 	if (device_get_parent(child) != dev)
291e1ef7811SRafal Jaworowski 		return (EINVAL);
292e1ef7811SRafal Jaworowski 
293e1ef7811SRafal Jaworowski 	qd = device_get_ivars(child);
294e1ef7811SRafal Jaworowski 	rle = resource_list_find(&qd->qd_rlist, type, rid);
295e1ef7811SRafal Jaworowski 	if (rle == NULL)
296e1ef7811SRafal Jaworowski 		return (EINVAL);
297e1ef7811SRafal Jaworowski 
298e1ef7811SRafal Jaworowski 	if (startp != NULL)
299e1ef7811SRafal Jaworowski 		*startp = rle->start;
300e1ef7811SRafal Jaworowski 	if (countp != NULL)
301e1ef7811SRafal Jaworowski 		*countp = rle->count;
302e1ef7811SRafal Jaworowski 	return (0);
303e1ef7811SRafal Jaworowski }
304e1ef7811SRafal Jaworowski 
305e1ef7811SRafal Jaworowski int
quicc_bus_read_ivar(device_t dev,device_t child,int index,uintptr_t * result)306e1ef7811SRafal Jaworowski quicc_bus_read_ivar(device_t dev, device_t child, int index, uintptr_t *result)
307e1ef7811SRafal Jaworowski {
308e1ef7811SRafal Jaworowski 	struct quicc_device *qd;
309e1ef7811SRafal Jaworowski 	struct quicc_softc *sc;
310e1ef7811SRafal Jaworowski 	uint32_t sccr;
311e1ef7811SRafal Jaworowski 
312e1ef7811SRafal Jaworowski 	if (device_get_parent(child) != dev)
313e1ef7811SRafal Jaworowski 		return (EINVAL);
314e1ef7811SRafal Jaworowski 
315e1ef7811SRafal Jaworowski 	sc = device_get_softc(dev);
316e1ef7811SRafal Jaworowski 	qd = device_get_ivars(child);
317e1ef7811SRafal Jaworowski 
318e1ef7811SRafal Jaworowski 	switch (index) {
319e1ef7811SRafal Jaworowski 	case QUICC_IVAR_CLOCK:
320e1ef7811SRafal Jaworowski 		*result = sc->sc_clock;
321e1ef7811SRafal Jaworowski 		break;
322e1ef7811SRafal Jaworowski 	case QUICC_IVAR_BRGCLK:
323e1ef7811SRafal Jaworowski 		sccr = quicc_read4(sc->sc_rres, QUICC_REG_SCCR) & 3;
324e1ef7811SRafal Jaworowski 		*result = sc->sc_clock / ((1 << (sccr + 1)) << sccr);
325e1ef7811SRafal Jaworowski 		break;
326e1ef7811SRafal Jaworowski 	case QUICC_IVAR_DEVTYPE:
327e1ef7811SRafal Jaworowski 		*result = qd->qd_devtype;
328e1ef7811SRafal Jaworowski 		break;
329e1ef7811SRafal Jaworowski 	default:
330e1ef7811SRafal Jaworowski 		return (EINVAL);
331e1ef7811SRafal Jaworowski 	}
332e1ef7811SRafal Jaworowski 	return (0);
333e1ef7811SRafal Jaworowski }
334e1ef7811SRafal Jaworowski 
335e1ef7811SRafal Jaworowski int
quicc_bus_release_resource(device_t dev,device_t child,struct resource * res)3369dbf5b0eSJohn Baldwin quicc_bus_release_resource(device_t dev, device_t child, struct resource *res)
337e1ef7811SRafal Jaworowski {
338e1ef7811SRafal Jaworowski 	struct quicc_device *qd;
339e1ef7811SRafal Jaworowski 	struct resource_list_entry *rle;
340e1ef7811SRafal Jaworowski 
341e1ef7811SRafal Jaworowski 	if (device_get_parent(child) != dev)
342e1ef7811SRafal Jaworowski 		return (EINVAL);
343e1ef7811SRafal Jaworowski 
344e1ef7811SRafal Jaworowski 	qd = device_get_ivars(child);
3459dbf5b0eSJohn Baldwin 	rle = resource_list_find(&qd->qd_rlist, rman_get_type(res),
3469dbf5b0eSJohn Baldwin 	    rman_get_rid(res));
347e1ef7811SRafal Jaworowski 	return ((rle == NULL) ? EINVAL : 0);
348e1ef7811SRafal Jaworowski }
349e1ef7811SRafal Jaworowski 
350e1ef7811SRafal Jaworowski int
quicc_bus_setup_intr(device_t dev,device_t child,struct resource * r,int flags,driver_filter_t * filt,void (* ihand)(void *),void * arg,void ** cookiep)351e1ef7811SRafal Jaworowski quicc_bus_setup_intr(device_t dev, device_t child, struct resource *r,
352e1ef7811SRafal Jaworowski     int flags, driver_filter_t *filt, void (*ihand)(void *), void *arg,
353e1ef7811SRafal Jaworowski     void **cookiep)
354e1ef7811SRafal Jaworowski {
355e1ef7811SRafal Jaworowski 	struct quicc_device *qd;
356e1ef7811SRafal Jaworowski 	struct quicc_softc *sc;
357e1ef7811SRafal Jaworowski 
358e1ef7811SRafal Jaworowski 	if (device_get_parent(child) != dev)
359e1ef7811SRafal Jaworowski 		return (EINVAL);
360e1ef7811SRafal Jaworowski 
361e1ef7811SRafal Jaworowski 	/* Interrupt handlers must be FAST or MPSAFE. */
362e1ef7811SRafal Jaworowski 	if (filt == NULL && !(flags & INTR_MPSAFE))
363e1ef7811SRafal Jaworowski 		return (EINVAL);
364e1ef7811SRafal Jaworowski 
365e1ef7811SRafal Jaworowski 	sc = device_get_softc(dev);
366e1ef7811SRafal Jaworowski 	if (sc->sc_polled)
367e1ef7811SRafal Jaworowski 		return (ENXIO);
368e1ef7811SRafal Jaworowski 
369e1ef7811SRafal Jaworowski 	if (sc->sc_fastintr && filt == NULL) {
370e1ef7811SRafal Jaworowski 		sc->sc_fastintr = 0;
371e1ef7811SRafal Jaworowski 		bus_teardown_intr(dev, sc->sc_ires, sc->sc_icookie);
372e1ef7811SRafal Jaworowski 		bus_setup_intr(dev, sc->sc_ires, INTR_TYPE_TTY | INTR_MPSAFE,
373e1ef7811SRafal Jaworowski 		    NULL, (driver_intr_t *)quicc_bfe_intr, sc, &sc->sc_icookie);
374e1ef7811SRafal Jaworowski 	}
375e1ef7811SRafal Jaworowski 
376e1ef7811SRafal Jaworowski 	qd = device_get_ivars(child);
377e1ef7811SRafal Jaworowski 	qd->qd_ih = (filt != NULL) ? filt : (driver_filter_t *)ihand;
378e1ef7811SRafal Jaworowski 	qd->qd_ih_arg = arg;
379e1ef7811SRafal Jaworowski 	*cookiep = ihand;
380e1ef7811SRafal Jaworowski 	return (0);
381e1ef7811SRafal Jaworowski }
382e1ef7811SRafal Jaworowski 
383e1ef7811SRafal Jaworowski int
quicc_bus_teardown_intr(device_t dev,device_t child,struct resource * r,void * cookie)384e1ef7811SRafal Jaworowski quicc_bus_teardown_intr(device_t dev, device_t child, struct resource *r,
385e1ef7811SRafal Jaworowski     void *cookie)
386e1ef7811SRafal Jaworowski {
387e1ef7811SRafal Jaworowski 	struct quicc_device *qd;
388e1ef7811SRafal Jaworowski 
389e1ef7811SRafal Jaworowski 	if (device_get_parent(child) != dev)
390e1ef7811SRafal Jaworowski 		return (EINVAL);
391e1ef7811SRafal Jaworowski 
392e1ef7811SRafal Jaworowski 	qd = device_get_ivars(child);
393e1ef7811SRafal Jaworowski 	if (qd->qd_ih != cookie)
394e1ef7811SRafal Jaworowski 		return (EINVAL);
395e1ef7811SRafal Jaworowski 
396e1ef7811SRafal Jaworowski 	qd->qd_ih = NULL;
397e1ef7811SRafal Jaworowski 	qd->qd_ih_arg = NULL;
398e1ef7811SRafal Jaworowski 	return (0);
399e1ef7811SRafal Jaworowski }
400