1/*- 2 * Copyright (C) 2012 Margarida Gouveia 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 19 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 20 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 21 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26#include <sys/cdefs.h> 27__FBSDID("$FreeBSD: releng/10.3/sys/powerpc/wii/wii_pic.c 249826 2013-04-24 01:36:35Z rpaulo $"); 28 29#include <sys/param.h> 30#include <sys/systm.h> 31#include <sys/module.h> 32#include <sys/bus.h> 33#include <sys/conf.h> 34#include <sys/kernel.h> 35#include <sys/malloc.h> 36#include <sys/rman.h> 37#include <sys/reboot.h> 38 39#include <machine/bus.h> 40#include <machine/platform.h> 41#include <machine/intr_machdep.h> 42#include <machine/resource.h> 43 44#include <powerpc/wii/wii_picreg.h> 45 46#include "pic_if.h" 47 48static int wiipic_probe(device_t); 49static int wiipic_attach(device_t); 50static void wiipic_dispatch(device_t, struct trapframe *); 51static void wiipic_enable(device_t, unsigned int, unsigned int); 52static void wiipic_eoi(device_t, unsigned int); 53static void wiipic_mask(device_t, unsigned int); 54static void wiipic_unmask(device_t, unsigned int); 55static void wiipic_intr(void *); 56 57struct wiipic_softc { 58 device_t sc_dev; 59 struct resource *sc_rres; 60 bus_space_tag_t sc_bt; 61 bus_space_handle_t sc_bh; 62 int sc_rrid; 63 int sc_irqid; 64 struct resource *sc_irq; 65 void *sc_irqctx; 66 int sc_vector[WIIPIC_NIRQ]; 67}; 68 69static device_method_t wiipic_methods[] = { 70 /* Device interface */ 71 DEVMETHOD(device_probe, wiipic_probe), 72 DEVMETHOD(device_attach, wiipic_attach), 73 74 /* PIC interface */ 75 DEVMETHOD(pic_dispatch, wiipic_dispatch), 76 DEVMETHOD(pic_enable, wiipic_enable), 77 DEVMETHOD(pic_eoi, wiipic_eoi), 78 DEVMETHOD(pic_mask, wiipic_mask), 79 DEVMETHOD(pic_unmask, wiipic_unmask), 80 81 DEVMETHOD_END 82}; 83 84static driver_t wiipic_driver = { 85 "wiipic", 86 wiipic_methods, 87 sizeof(struct wiipic_softc) 88}; 89 90static devclass_t wiipic_devclass; 91 92DRIVER_MODULE(wiipic, wiibus, wiipic_driver, wiipic_devclass, 0, 0); 93 94static __inline uint32_t 95wiipic_imr_read(struct wiipic_softc *sc) 96{ 97 98 return (bus_space_read_4(sc->sc_bt, sc->sc_bh, WIIPIC_IMR)); 99} 100 101static __inline void 102wiipic_imr_write(struct wiipic_softc *sc, uint32_t imr) 103{ 104 105 bus_space_write_4(sc->sc_bt, sc->sc_bh, WIIPIC_IMR, imr); 106} 107 108static __inline uint32_t 109wiipic_icr_read(struct wiipic_softc *sc) 110{ 111 112 return (bus_space_read_4(sc->sc_bt, sc->sc_bh, WIIPIC_ICR)); 113} 114 115static __inline void 116wiipic_icr_write(struct wiipic_softc *sc, uint32_t icr) 117{ 118 119 bus_space_write_4(sc->sc_bt, sc->sc_bh, WIIPIC_ICR, icr); 120} 121 122static int 123wiipic_probe(device_t dev) 124{ 125 device_set_desc(dev, "Nintendo Wii PIC"); 126 127 return (BUS_PROBE_NOWILDCARD); 128} 129 130static int 131wiipic_attach(device_t dev) 132{ 133 struct wiipic_softc *sc; 134 135 sc = device_get_softc(dev); 136 sc->sc_dev = dev; 137 138 sc->sc_rrid = 0; 139 sc->sc_rres = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 140 &sc->sc_rrid, RF_ACTIVE); 141 if (sc->sc_rres == NULL) { 142 device_printf(dev, "could not alloc mem resource\n"); 143 return (ENXIO); 144 } 145 sc->sc_bt = rman_get_bustag(sc->sc_rres); 146 sc->sc_bh = rman_get_bushandle(sc->sc_rres); 147 148 /* Turn off all interrupts */ 149 wiipic_imr_write(sc, 0x00000000); 150 wiipic_icr_write(sc, 0xffffffff); 151 152 powerpc_register_pic(dev, 0, WIIPIC_NIRQ, 0, FALSE); 153 154 /* 155 * Setup the interrupt handler. 156 */ 157 sc->sc_irqid = 0; 158 sc->sc_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_irqid, 159 RF_ACTIVE); 160 if (sc->sc_irq == NULL) { 161 device_printf(dev, "could not alloc IRQ resource\n"); 162 return (ENXIO); 163 } 164 bus_setup_intr(dev, sc->sc_irq, INTR_TYPE_MISC | INTR_MPSAFE, 165 NULL, wiipic_intr, sc, &sc->sc_irqctx); 166 167 return (0); 168} 169 170static void 171wiipic_dispatch(device_t dev, struct trapframe *tf) 172{ 173 struct wiipic_softc *sc; 174 uint32_t irq; 175 176 sc = device_get_softc(dev); 177 irq = wiipic_icr_read(sc) & wiipic_imr_read(sc); 178 if (irq == 0) 179 return; 180 irq = ffs(irq) - 1; 181 KASSERT(irq < WIIPIC_NIRQ, ("bogus irq %d", irq)); 182 powerpc_dispatch_intr(sc->sc_vector[irq], tf); 183} 184 185static void 186wiipic_enable(device_t dev, unsigned int irq, unsigned int vector) 187{ 188 struct wiipic_softc *sc; 189 190 KASSERT(irq < WIIPIC_NIRQ, ("bogus irq %d", irq)); 191 sc = device_get_softc(dev); 192 sc->sc_vector[irq] = vector; 193 wiipic_unmask(dev, irq); 194} 195 196static void 197wiipic_eoi(device_t dev, unsigned int irq) 198{ 199 struct wiipic_softc *sc; 200 uint32_t icr; 201 202 sc = device_get_softc(dev); 203 icr = wiipic_icr_read(sc); 204 icr |= (1 << irq); 205 wiipic_icr_write(sc, icr); 206} 207 208static void 209wiipic_mask(device_t dev, unsigned int irq) 210{ 211 struct wiipic_softc *sc; 212 uint32_t imr; 213 214 sc = device_get_softc(dev); 215 imr = wiipic_imr_read(sc); 216 imr &= ~(1 << irq); 217 wiipic_imr_write(sc, imr); 218} 219 220static void 221wiipic_unmask(device_t dev, unsigned int irq) 222{ 223 struct wiipic_softc *sc; 224 uint32_t imr; 225 226 sc = device_get_softc(dev); 227 imr = wiipic_imr_read(sc); 228 imr |= (1 << irq); 229 wiipic_imr_write(sc, imr); 230} 231 232/* 233 * Reset button interrupt. 234 */ 235static void 236wiipic_intr(void *xsc) 237{ 238 struct wiipic_softc *sc; 239 240 sc = (struct wiipic_softc *)xsc; 241 if (wiipic_icr_read(sc) & WIIPIC_RBS) 242 shutdown_nice(RB_AUTOBOOT); 243} 244 245