1136301Syongari/*- 2136301Syongari * Copyright (c) 2004 Pyun YongHyeon 3136301Syongari * All rights reserved. 4136301Syongari * 5136301Syongari * Redistribution and use in source and binary forms, with or without 6136301Syongari * modification, are permitted provided that the following conditions 7136301Syongari * are met: 8136301Syongari * 1. Redistributions of source code must retain the above copyright 9136301Syongari * notice, this list of conditions and the following disclaimer. 10136301Syongari * 2. Redistributions in binary form must reproduce the above copyright 11136301Syongari * notice, this list of conditions and the following disclaimer in the 12136301Syongari * documentation and/or other materials provided with the distribution. 13136301Syongari * 14136301Syongari * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15136301Syongari * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16136301Syongari * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17136301Syongari * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18136301Syongari * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19136301Syongari * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20136301Syongari * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21136301Syongari * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22136301Syongari * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23136301Syongari * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24136301Syongari * SUCH DAMAGE. 25136301Syongari * 26136301Syongari */ 27136301Syongari 28136301Syongari/* $NetBSD: auxio.c,v 1.11 2003/07/15 03:36:04 lukem Exp $ */ 29136301Syongari 30139749Simp/*- 31136301Syongari * Copyright (c) 2000, 2001 Matthew R. Green 32136301Syongari * All rights reserved. 33136301Syongari * 34136301Syongari * Redistribution and use in source and binary forms, with or without 35136301Syongari * modification, are permitted provided that the following conditions 36136301Syongari * are met: 37136301Syongari * 1. Redistributions of source code must retain the above copyright 38136301Syongari * notice, this list of conditions and the following disclaimer. 39136301Syongari * 2. Redistributions in binary form must reproduce the above copyright 40136301Syongari * notice, this list of conditions and the following disclaimer in the 41136301Syongari * documentation and/or other materials provided with the distribution. 42136301Syongari * 3. The name of the author may not be used to endorse or promote products 43136301Syongari * derived from this software without specific prior written permission. 44136301Syongari * 45136301Syongari * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 46136301Syongari * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 47136301Syongari * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 48136301Syongari * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 49136301Syongari * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 50136301Syongari * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 51136301Syongari * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 52136301Syongari * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 53136301Syongari * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 54136301Syongari * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 55136301Syongari * SUCH DAMAGE. 56136301Syongari */ 57136301Syongari 58136301Syongari/* 59200815Smarius * AUXIO registers support on the SBus & EBus2, used for the floppy driver 60136301Syongari * and to control the system LED, for the BLINK option. 61136301Syongari */ 62136301Syongari 63136301Syongari#include <sys/cdefs.h> 64136301Syongari__FBSDID("$FreeBSD$"); 65136301Syongari 66136301Syongari#include <sys/param.h> 67136301Syongari#include <sys/systm.h> 68136301Syongari#include <sys/bus.h> 69136301Syongari#include <sys/kernel.h> 70136301Syongari#include <sys/lock.h> 71136301Syongari#include <sys/module.h> 72136301Syongari#include <sys/mutex.h> 73136301Syongari#include <sys/resource.h> 74136301Syongari#include <sys/rman.h> 75136301Syongari 76136301Syongari#include <dev/led/led.h> 77136301Syongari#include <dev/ofw/ofw_bus.h> 78136301Syongari#include <dev/ofw/openfirm.h> 79136301Syongari 80136301Syongari#include <machine/bus.h> 81136301Syongari#include <machine/ofw_machdep.h> 82136301Syongari#include <machine/resource.h> 83136301Syongari 84136301Syongari#include <sparc64/sbus/sbusvar.h> 85136301Syongari#include <dev/auxio/auxioreg.h> 86136301Syongari 87136301Syongari/* 88200815Smarius * On sun4u, auxio exists with one register (LED) on the SBus, and 5 89200815Smarius * registers on the EBus2 (pci) (LED, PCIMODE, FREQUENCY, SCSI 90136301Syongari * OSCILLATOR, and TEMP SENSE. 91136301Syongari */ 92136301Syongari 93136301Syongari#define AUXIO_PCIO_LED 0 94136301Syongari#define AUXIO_PCIO_PCI 1 95136301Syongari#define AUXIO_PCIO_FREQ 2 96136301Syongari#define AUXIO_PCIO_OSC 3 97136301Syongari#define AUXIO_PCIO_TEMP 4 98147877Smarius#define AUXIO_PCIO_NREG 5 99136301Syongari 100136301Syongaristruct auxio_softc { 101136301Syongari struct device *sc_dev; 102136301Syongari 103136301Syongari int sc_nauxio; 104147877Smarius struct resource *sc_res[AUXIO_PCIO_NREG]; 105147877Smarius int sc_rid[AUXIO_PCIO_NREG]; 106147877Smarius bus_space_tag_t sc_regt[AUXIO_PCIO_NREG]; 107147877Smarius bus_space_handle_t sc_regh[AUXIO_PCIO_NREG]; 108136301Syongari struct cdev *sc_led_dev; 109136301Syongari u_int32_t sc_led_stat; 110136301Syongari 111136301Syongari int sc_flags; 112136301Syongari#define AUXIO_LEDONLY 0x1 113136301Syongari#define AUXIO_EBUS 0x2 114136301Syongari#define AUXIO_SBUS 0x4 115136301Syongari 116136301Syongari struct mtx sc_lock; 117136301Syongari}; 118136301Syongari 119136301Syongaristatic void auxio_led_func(void *arg, int onoff); 120146965Smariusstatic int auxio_attach_common(struct auxio_softc *); 121136301Syongaristatic int auxio_bus_probe(device_t); 122136301Syongaristatic int auxio_sbus_attach(device_t); 123136301Syongaristatic int auxio_ebus_attach(device_t); 124136301Syongaristatic int auxio_bus_detach(device_t); 125136301Syongaristatic void auxio_free_resource(struct auxio_softc *); 126136301Syongaristatic __inline u_int32_t auxio_led_read(struct auxio_softc *); 127136301Syongaristatic __inline void auxio_led_write(struct auxio_softc *, u_int32_t); 128136301Syongari 129136301Syongari/* SBus */ 130136301Syongaristatic device_method_t auxio_sbus_methods[] = { 131136301Syongari DEVMETHOD(device_probe, auxio_bus_probe), 132136301Syongari DEVMETHOD(device_attach, auxio_sbus_attach), 133136301Syongari DEVMETHOD(device_detach, auxio_bus_detach), 134246128Ssbz 135246128Ssbz DEVMETHOD_END 136136301Syongari}; 137136301Syongari 138136301Syongaristatic driver_t auxio_sbus_driver = { 139136301Syongari "auxio", 140136301Syongari auxio_sbus_methods, 141136301Syongari sizeof(struct auxio_softc) 142136301Syongari}; 143136301Syongari 144136301Syongaristatic devclass_t auxio_devclass; 145200874Smarius/* The probe order is handled by sbus(4). */ 146200874SmariusEARLY_DRIVER_MODULE(auxio, sbus, auxio_sbus_driver, auxio_devclass, 0, 0, 147200874Smarius BUS_PASS_DEFAULT); 148200815SmariusMODULE_DEPEND(auxio, sbus, 1, 1, 1); 149136301Syongari 150136301Syongari/* EBus */ 151136301Syongaristatic device_method_t auxio_ebus_methods[] = { 152136301Syongari DEVMETHOD(device_probe, auxio_bus_probe), 153136301Syongari DEVMETHOD(device_attach, auxio_ebus_attach), 154136301Syongari DEVMETHOD(device_detach, auxio_bus_detach), 155246128Ssbz 156246128Ssbz DEVMETHOD_END 157136301Syongari}; 158136301Syongari 159136301Syongaristatic driver_t auxio_ebus_driver = { 160136301Syongari "auxio", 161136301Syongari auxio_ebus_methods, 162136301Syongari sizeof(struct auxio_softc) 163136301Syongari}; 164136301Syongari 165200874SmariusEARLY_DRIVER_MODULE(auxio, ebus, auxio_ebus_driver, auxio_devclass, 0, 0, 166200874Smarius BUS_PASS_DEFAULT); 167200815SmariusMODULE_DEPEND(auxio, ebus, 1, 1, 1); 168136301SyongariMODULE_VERSION(auxio, 1); 169136301Syongari 170136301Syongari#define AUXIO_LOCK_INIT(sc) \ 171136301Syongari mtx_init(&sc->sc_lock, "auxio mtx", NULL, MTX_DEF) 172136301Syongari#define AUXIO_LOCK(sc) mtx_lock(&sc->sc_lock) 173136301Syongari#define AUXIO_UNLOCK(sc) mtx_unlock(&sc->sc_lock) 174136301Syongari#define AUXIO_LOCK_DESTROY(sc) mtx_destroy(&sc->sc_lock) 175136301Syongari 176136301Syongaristatic __inline void 177136301Syongariauxio_led_write(struct auxio_softc *sc, u_int32_t v) 178136301Syongari{ 179136301Syongari if (sc->sc_flags & AUXIO_EBUS) 180136301Syongari bus_space_write_4(sc->sc_regt[AUXIO_PCIO_LED], 181136301Syongari sc->sc_regh[AUXIO_PCIO_LED], 0, v); 182136301Syongari else 183136301Syongari bus_space_write_1(sc->sc_regt[AUXIO_PCIO_LED], 184136301Syongari sc->sc_regh[AUXIO_PCIO_LED], 0, v); 185136301Syongari} 186136301Syongari 187136301Syongaristatic __inline u_int32_t 188136301Syongariauxio_led_read(struct auxio_softc *sc) 189136301Syongari{ 190136301Syongari u_int32_t led; 191136301Syongari 192136301Syongari if (sc->sc_flags & AUXIO_EBUS) 193136301Syongari led = bus_space_read_4(sc->sc_regt[AUXIO_PCIO_LED], 194136301Syongari sc->sc_regh[AUXIO_PCIO_LED], 0); 195136301Syongari else 196136301Syongari led = bus_space_read_1(sc->sc_regt[AUXIO_PCIO_LED], 197136301Syongari sc->sc_regh[AUXIO_PCIO_LED], 0); 198136301Syongari 199136301Syongari return (led); 200136301Syongari} 201136301Syongari 202136301Syongaristatic void 203136301Syongariauxio_led_func(void *arg, int onoff) 204136301Syongari{ 205136301Syongari struct auxio_softc *sc; 206136301Syongari u_int32_t led; 207136301Syongari 208136301Syongari sc = (struct auxio_softc *)arg; 209136301Syongari 210136301Syongari AUXIO_LOCK(sc); 211154864Smarius /* 212154864Smarius * NB: We must not touch the other bits of the SBus AUXIO reg. 213154864Smarius */ 214154864Smarius led = auxio_led_read(sc); 215154864Smarius if (onoff) 216154864Smarius led |= AUXIO_LED_LED; 217154864Smarius else 218154864Smarius led &= ~AUXIO_LED_LED; 219136301Syongari auxio_led_write(sc, led); 220136301Syongari AUXIO_UNLOCK(sc); 221136301Syongari} 222136301Syongari 223136301Syongaristatic int 224136301Syongariauxio_bus_probe(device_t dev) 225136301Syongari{ 226136301Syongari const char *name; 227136301Syongari 228136301Syongari name = ofw_bus_get_name(dev); 229136301Syongari if (strcmp("auxio", name) == 0) { 230136301Syongari device_set_desc(dev, "Sun Auxiliary I/O"); 231136301Syongari return (0); 232136301Syongari } 233136301Syongari 234136301Syongari return (ENXIO); 235136301Syongari} 236136301Syongari 237136301Syongaristatic int 238136301Syongariauxio_ebus_attach(device_t dev) 239136301Syongari{ 240136301Syongari struct auxio_softc *sc; 241136301Syongari 242136301Syongari sc = device_get_softc(dev); 243136301Syongari sc->sc_dev = dev; 244136301Syongari 245136301Syongari AUXIO_LOCK_INIT(sc); 246147877Smarius sc->sc_nauxio = AUXIO_PCIO_NREG; 247146965Smarius sc->sc_flags = AUXIO_LEDONLY | AUXIO_EBUS; 248146965Smarius 249146965Smarius return(auxio_attach_common(sc)); 250146965Smarius} 251146965Smarius 252146965Smariusstatic int 253146965Smariusauxio_attach_common(struct auxio_softc *sc) 254146965Smarius{ 255146965Smarius struct resource *res; 256146965Smarius int i; 257146965Smarius 258146965Smarius for (i = 0; i < sc->sc_nauxio; i++) { 259146965Smarius sc->sc_rid[i] = i; 260146965Smarius res = bus_alloc_resource_any(sc->sc_dev, SYS_RES_MEMORY, 261136301Syongari &sc->sc_rid[i], RF_ACTIVE); 262136301Syongari if (res == NULL) { 263136301Syongari device_printf(sc->sc_dev, 264136301Syongari "could not allocate resources\n"); 265136301Syongari goto attach_fail; 266136301Syongari } 267136301Syongari sc->sc_res[i] = res; 268136301Syongari sc->sc_regt[i] = rman_get_bustag(res); 269136301Syongari sc->sc_regh[i] = rman_get_bushandle(res); 270136301Syongari } 271136301Syongari 272154864Smarius sc->sc_led_stat = auxio_led_read(sc) & AUXIO_LED_LED; 273146965Smarius sc->sc_led_dev = led_create(auxio_led_func, sc, "auxioled"); 274146965Smarius /* turn on the LED */ 275146965Smarius auxio_led_func(sc, 1); 276146965Smarius 277136301Syongari return (0); 278136301Syongari 279136301Syongariattach_fail: 280136301Syongari auxio_free_resource(sc); 281136301Syongari 282136301Syongari return (ENXIO); 283136301Syongari} 284136301Syongari 285136301Syongaristatic int 286136301Syongariauxio_bus_detach(device_t dev) 287136301Syongari{ 288136301Syongari struct auxio_softc *sc; 289136301Syongari 290136301Syongari sc = device_get_softc(dev); 291136301Syongari led_destroy(sc->sc_led_dev); 292136301Syongari auxio_led_func(sc, sc->sc_led_stat); 293136301Syongari auxio_free_resource(sc); 294136301Syongari 295136301Syongari return (0); 296136301Syongari} 297136301Syongari 298136301Syongaristatic void 299136301Syongariauxio_free_resource(struct auxio_softc *sc) 300136301Syongari{ 301146965Smarius int i; 302136301Syongari 303146965Smarius for (i = 0; i < sc->sc_nauxio; i++) 304136301Syongari if (sc->sc_res[i]) 305146965Smarius bus_release_resource(sc->sc_dev, SYS_RES_MEMORY, 306146965Smarius sc->sc_rid[i], sc->sc_res[i]); 307136301Syongari AUXIO_LOCK_DESTROY(sc); 308136301Syongari} 309136301Syongari 310136301Syongaristatic int 311136301Syongariauxio_sbus_attach(device_t dev) 312136301Syongari{ 313136301Syongari struct auxio_softc *sc; 314136301Syongari 315136301Syongari sc = device_get_softc(dev); 316136301Syongari sc->sc_dev = dev; 317136301Syongari 318136301Syongari AUXIO_LOCK_INIT(sc); 319136301Syongari sc->sc_nauxio = 1; 320136301Syongari sc->sc_flags = AUXIO_LEDONLY | AUXIO_SBUS; 321136301Syongari 322146965Smarius return (auxio_attach_common(sc)); 323136301Syongari} 324