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