auxio.c revision 136301
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 30136301Syongari/* 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/* 59136301Syongari * 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: head/sys/dev/auxio/auxio.c 136301 2004-10-09 07:31:03Z yongari $"); 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/* 88136301Syongari * on sun4u, auxio exists with one register (LED) on the sbus, and 5 89136301Syongari * 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 98136301Syongari#define AUXIO_PCIO_MAX 8 99136301Syongari 100136301Syongaristruct auxio_softc { 101136301Syongari struct device *sc_dev; 102136301Syongari 103136301Syongari int sc_nauxio; 104136301Syongari struct resource *sc_res[AUXIO_PCIO_MAX]; 105136301Syongari int sc_rid[AUXIO_PCIO_MAX]; 106136301Syongari bus_space_tag_t sc_regt[AUXIO_PCIO_MAX]; 107136301Syongari bus_space_handle_t sc_regh[AUXIO_PCIO_MAX]; 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); 120136301Syongaristatic void 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), 134136301Syongari {0, 0} 135136301Syongari}; 136136301Syongari 137136301Syongaristatic driver_t auxio_sbus_driver = { 138136301Syongari "auxio", 139136301Syongari auxio_sbus_methods, 140136301Syongari sizeof(struct auxio_softc) 141136301Syongari}; 142136301Syongari 143136301Syongaristatic devclass_t auxio_devclass; 144136301SyongariDRIVER_MODULE(auxio, sbus, auxio_sbus_driver, auxio_devclass, 0, 0); 145136301Syongari 146136301Syongari/* EBus */ 147136301Syongaristatic device_method_t auxio_ebus_methods[] = { 148136301Syongari DEVMETHOD(device_probe, auxio_bus_probe), 149136301Syongari DEVMETHOD(device_attach, auxio_ebus_attach), 150136301Syongari DEVMETHOD(device_detach, auxio_bus_detach), 151136301Syongari {0, 0} 152136301Syongari}; 153136301Syongari 154136301Syongaristatic driver_t auxio_ebus_driver = { 155136301Syongari "auxio", 156136301Syongari auxio_ebus_methods, 157136301Syongari sizeof(struct auxio_softc) 158136301Syongari}; 159136301Syongari 160136301SyongariDRIVER_MODULE(auxio, ebus, auxio_ebus_driver, auxio_devclass, 0, 0); 161136301SyongariMODULE_VERSION(auxio, 1); 162136301Syongari 163136301Syongari#define AUXIO_LOCK_INIT(sc) \ 164136301Syongari mtx_init(&sc->sc_lock, "auxio mtx", NULL, MTX_DEF) 165136301Syongari#define AUXIO_LOCK(sc) mtx_lock(&sc->sc_lock) 166136301Syongari#define AUXIO_UNLOCK(sc) mtx_unlock(&sc->sc_lock) 167136301Syongari#define AUXIO_LOCK_DESTROY(sc) mtx_destroy(&sc->sc_lock) 168136301Syongari 169136301Syongaristatic __inline void 170136301Syongariauxio_led_write(struct auxio_softc *sc, u_int32_t v) 171136301Syongari{ 172136301Syongari if (sc->sc_flags & AUXIO_EBUS) 173136301Syongari bus_space_write_4(sc->sc_regt[AUXIO_PCIO_LED], 174136301Syongari sc->sc_regh[AUXIO_PCIO_LED], 0, v); 175136301Syongari else 176136301Syongari bus_space_write_1(sc->sc_regt[AUXIO_PCIO_LED], 177136301Syongari sc->sc_regh[AUXIO_PCIO_LED], 0, v); 178136301Syongari} 179136301Syongari 180136301Syongaristatic __inline u_int32_t 181136301Syongariauxio_led_read(struct auxio_softc *sc) 182136301Syongari{ 183136301Syongari u_int32_t led; 184136301Syongari 185136301Syongari if (sc->sc_flags & AUXIO_EBUS) 186136301Syongari led = bus_space_read_4(sc->sc_regt[AUXIO_PCIO_LED], 187136301Syongari sc->sc_regh[AUXIO_PCIO_LED], 0); 188136301Syongari else 189136301Syongari led = bus_space_read_1(sc->sc_regt[AUXIO_PCIO_LED], 190136301Syongari sc->sc_regh[AUXIO_PCIO_LED], 0); 191136301Syongari 192136301Syongari return (led); 193136301Syongari} 194136301Syongari 195136301Syongaristatic void 196136301Syongariauxio_led_func(void *arg, int onoff) 197136301Syongari{ 198136301Syongari struct auxio_softc *sc; 199136301Syongari u_int32_t led; 200136301Syongari 201136301Syongari sc = (struct auxio_softc *)arg; 202136301Syongari 203136301Syongari led = onoff ? AUXIO_LED_LED : 0; 204136301Syongari AUXIO_LOCK(sc); 205136301Syongari auxio_led_write(sc, led); 206136301Syongari AUXIO_UNLOCK(sc); 207136301Syongari} 208136301Syongari 209136301Syongaristatic int 210136301Syongariauxio_bus_probe(device_t dev) 211136301Syongari{ 212136301Syongari const char *name; 213136301Syongari 214136301Syongari name = ofw_bus_get_name(dev); 215136301Syongari if (strcmp("auxio", name) == 0) { 216136301Syongari device_set_desc(dev, "Sun Auxiliary I/O"); 217136301Syongari return (0); 218136301Syongari } 219136301Syongari 220136301Syongari return (ENXIO); 221136301Syongari} 222136301Syongari 223136301Syongaristatic int 224136301Syongariauxio_ebus_attach(device_t dev) 225136301Syongari{ 226136301Syongari struct auxio_softc *sc; 227136301Syongari struct resource *res; 228136301Syongari u_long start, count; 229136301Syongari int i; 230136301Syongari 231136301Syongari sc = device_get_softc(dev); 232136301Syongari bzero(sc, sizeof(*sc)); 233136301Syongari sc->sc_dev = dev; 234136301Syongari 235136301Syongari AUXIO_LOCK_INIT(sc); 236136301Syongari sc->sc_nauxio = AUXIO_PCIO_MAX; 237136301Syongari sc->sc_flags = AUXIO_LEDONLY | AUXIO_EBUS; 238136301Syongari for (i = 0; 239136301Syongari i < AUXIO_PCIO_MAX && 240136301Syongari bus_get_resource(dev, SYS_RES_IOPORT, i, &start, &count) == 0; 241136301Syongari i++) { 242136301Syongari sc->sc_rid[i] = i; 243136301Syongari if (bootverbose) 244136301Syongari device_printf(sc->sc_dev, 245136301Syongari "Got rid %d, start %#lx, count %#lx\n", 246136301Syongari i, start, count); 247136301Syongari res = bus_alloc_resource_any(dev, SYS_RES_IOPORT, 248136301Syongari &sc->sc_rid[i], RF_ACTIVE); 249136301Syongari if (res == NULL) { 250136301Syongari device_printf(sc->sc_dev, 251136301Syongari "could not allocate resources\n"); 252136301Syongari goto attach_fail; 253136301Syongari } 254136301Syongari sc->sc_res[i] = res; 255136301Syongari sc->sc_regt[i] = rman_get_bustag(res); 256136301Syongari sc->sc_regh[i] = rman_get_bushandle(res); 257136301Syongari } 258136301Syongari sc->sc_nauxio = i; 259136301Syongari auxio_attach_common(sc); 260136301Syongari 261136301Syongari return (0); 262136301Syongari 263136301Syongariattach_fail: 264136301Syongari auxio_free_resource(sc); 265136301Syongari 266136301Syongari return (ENXIO); 267136301Syongari} 268136301Syongari 269136301Syongaristatic void 270136301Syongariauxio_attach_common(struct auxio_softc *sc) 271136301Syongari{ 272136301Syongari sc->sc_led_stat = auxio_led_read(sc); 273136301Syongari sc->sc_led_dev = led_create(auxio_led_func, sc, "auxioled"); 274136301Syongari /* turn on the LED */ 275136301Syongari auxio_led_func(sc, 1); 276136301Syongari} 277136301Syongari 278136301Syongaristatic int 279136301Syongariauxio_bus_detach(device_t dev) 280136301Syongari{ 281136301Syongari struct auxio_softc *sc; 282136301Syongari 283136301Syongari sc = device_get_softc(dev); 284136301Syongari led_destroy(sc->sc_led_dev); 285136301Syongari auxio_led_func(sc, sc->sc_led_stat); 286136301Syongari auxio_free_resource(sc); 287136301Syongari 288136301Syongari return (0); 289136301Syongari} 290136301Syongari 291136301Syongaristatic void 292136301Syongariauxio_free_resource(struct auxio_softc *sc) 293136301Syongari{ 294136301Syongari int i, n; 295136301Syongari 296136301Syongari n = sc->sc_nauxio; 297136301Syongari for (i = 0; i < n; i++) 298136301Syongari if (sc->sc_res[i]) 299136301Syongari bus_release_resource(sc->sc_dev, 300136301Syongari (sc->sc_flags & AUXIO_SBUS) ? SYS_RES_MEMORY : 301136301Syongari SYS_RES_IOPORT, sc->sc_rid[i], sc->sc_res[i]); 302136301Syongari AUXIO_LOCK_DESTROY(sc); 303136301Syongari} 304136301Syongari 305136301Syongaristatic int 306136301Syongariauxio_sbus_attach(device_t dev) 307136301Syongari{ 308136301Syongari struct auxio_softc *sc; 309136301Syongari struct resource *res; 310136301Syongari 311136301Syongari sc = device_get_softc(dev); 312136301Syongari bzero(sc, sizeof(*sc)); 313136301Syongari sc->sc_dev = dev; 314136301Syongari 315136301Syongari AUXIO_LOCK_INIT(sc); 316136301Syongari sc->sc_nauxio = 1; 317136301Syongari sc->sc_flags = AUXIO_LEDONLY | AUXIO_SBUS; 318136301Syongari sc->sc_rid[AUXIO_PCIO_LED] = 0; 319136301Syongari res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 320136301Syongari &sc->sc_rid[AUXIO_PCIO_LED], RF_ACTIVE); 321136301Syongari if (res == NULL) { 322136301Syongari device_printf(sc->sc_dev, "could not allocate resources\n"); 323136301Syongari goto attach_fail; 324136301Syongari } 325136301Syongari sc->sc_res[AUXIO_PCIO_LED] = res; 326136301Syongari sc->sc_regt[AUXIO_PCIO_LED] = rman_get_bustag(res); 327136301Syongari sc->sc_regh[AUXIO_PCIO_LED] = rman_get_bushandle(res); 328136301Syongari auxio_attach_common(sc); 329136301Syongari return (0); 330136301Syongari 331136301Syongariattach_fail: 332136301Syongari auxio_free_resource(sc); 333136301Syongari 334136301Syongari return (ENXIO); 335136301Syongari} 336