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 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 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 189*5b56413dSWarner Losh qd->qd_dev = device_add_child(dev, NULL, DEVICE_UNIT_ANY); 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 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 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 * 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 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 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 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 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 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