envctrl.c revision 133522
10Sstevel@tonic-gate/*- 20Sstevel@tonic-gate * Copyright (c) 2004 Joerg Wunsch 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * derived from sys/i386/isa/pcf.c which is: 51663Spriyanka * 61663Spriyanka * Copyright (c) 1998 Nicolas Souchu, Marc Bouget 70Sstevel@tonic-gate * All rights reserved. 80Sstevel@tonic-gate * 90Sstevel@tonic-gate * Redistribution and use in source and binary forms, with or without 100Sstevel@tonic-gate * modification, are permitted provided that the following conditions 110Sstevel@tonic-gate * are met: 120Sstevel@tonic-gate * 1. Redistributions of source code must retain the above copyright 130Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer. 140Sstevel@tonic-gate * 2. Redistributions in binary form must reproduce the above copyright 150Sstevel@tonic-gate * notice, this list of conditions and the following disclaimer in the 160Sstevel@tonic-gate * documentation and/or other materials provided with the distribution. 170Sstevel@tonic-gate * 180Sstevel@tonic-gate * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 190Sstevel@tonic-gate * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 200Sstevel@tonic-gate * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 210Sstevel@tonic-gate * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 228485SPeter.Memishian@Sun.COM * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 230Sstevel@tonic-gate * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 240Sstevel@tonic-gate * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 250Sstevel@tonic-gate * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 260Sstevel@tonic-gate * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 270Sstevel@tonic-gate * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 280Sstevel@tonic-gate * SUCH DAMAGE. 290Sstevel@tonic-gate */ 300Sstevel@tonic-gate#include <sys/cdefs.h> 310Sstevel@tonic-gate__FBSDID("$FreeBSD: head/sys/dev/pcf/envctrl.c 133522 2004-08-11 21:19:31Z marius $"); 320Sstevel@tonic-gate 330Sstevel@tonic-gate/* 340Sstevel@tonic-gate * Device specific driver for the SUNW,envctrl device found on some 350Sstevel@tonic-gate * UltraSPARC Sun systems. This device is a Philips PCF8584 sitting 360Sstevel@tonic-gate * on the Ebus2. 370Sstevel@tonic-gate */ 380Sstevel@tonic-gate 390Sstevel@tonic-gate#include <sys/param.h> 400Sstevel@tonic-gate#include <sys/systm.h> 410Sstevel@tonic-gate#include <sys/bus.h> 420Sstevel@tonic-gate#include <sys/conf.h> 4311042SErik.Nordmark@Sun.COM#include <sys/kernel.h> 440Sstevel@tonic-gate#include <sys/malloc.h> 450Sstevel@tonic-gate#include <sys/module.h> 460Sstevel@tonic-gate#include <sys/resource.h> 470Sstevel@tonic-gate#include <sys/uio.h> 480Sstevel@tonic-gate 490Sstevel@tonic-gate#include <machine/bus.h> 500Sstevel@tonic-gate#include <machine/resource.h> 510Sstevel@tonic-gate 520Sstevel@tonic-gate#include <sys/rman.h> 530Sstevel@tonic-gate 5411042SErik.Nordmark@Sun.COM#include <dev/ofw/openfirm.h> 5511042SErik.Nordmark@Sun.COM 5611042SErik.Nordmark@Sun.COM#include <sparc64/ebus/ebusvar.h> 570Sstevel@tonic-gate 5811042SErik.Nordmark@Sun.COM#include <dev/iicbus/iiconf.h> 5911042SErik.Nordmark@Sun.COM#include <dev/pcf/pcfvar.h> 600Sstevel@tonic-gate#include "iicbus_if.h" 610Sstevel@tonic-gate 620Sstevel@tonic-gate#undef PCF_DEFAULT_ADDR 630Sstevel@tonic-gate#define PCF_DEFAULT_ADDR 0x55 /* SUNW,pcf default */ 640Sstevel@tonic-gate 650Sstevel@tonic-gatestatic int envctrl_probe(device_t); 6611042SErik.Nordmark@Sun.COMstatic int envctrl_attach(device_t); 670Sstevel@tonic-gatestatic int envctrl_detach(device_t); 680Sstevel@tonic-gate 6911042SErik.Nordmark@Sun.COMstatic device_method_t envctrl_methods[] = { 7011042SErik.Nordmark@Sun.COM /* device interface */ 7111042SErik.Nordmark@Sun.COM DEVMETHOD(device_probe, envctrl_probe), 7211042SErik.Nordmark@Sun.COM DEVMETHOD(device_attach, envctrl_attach), 738612SAnders.Persson@Sun.COM DEVMETHOD(device_detach, envctrl_detach), 7411042SErik.Nordmark@Sun.COM 758612SAnders.Persson@Sun.COM /* iicbus interface */ 7611042SErik.Nordmark@Sun.COM DEVMETHOD(iicbus_callback, iicbus_null_callback), 770Sstevel@tonic-gate DEVMETHOD(iicbus_repeated_start, pcf_repeated_start), 7811042SErik.Nordmark@Sun.COM DEVMETHOD(iicbus_start, pcf_start), 791673Sgt145670 DEVMETHOD(iicbus_stop, pcf_stop), 8011042SErik.Nordmark@Sun.COM DEVMETHOD(iicbus_write, pcf_write), 812263Ssommerfe DEVMETHOD(iicbus_read, pcf_read), 8211042SErik.Nordmark@Sun.COM DEVMETHOD(iicbus_reset, pcf_rst_card), 8310934Ssommerfeld@sun.com { 0, 0 } 842263Ssommerfe}; 8511042SErik.Nordmark@Sun.COM 862263Ssommerfestatic devclass_t envctrl_devclass; 8711042SErik.Nordmark@Sun.COM 880Sstevel@tonic-gatestatic driver_t envctrl_driver = { 890Sstevel@tonic-gate "envctrl", 9011042SErik.Nordmark@Sun.COM envctrl_methods, 918348SEric.Yu@Sun.COM sizeof(struct pcf_softc), 920Sstevel@tonic-gate}; 9311042SErik.Nordmark@Sun.COM 948348SEric.Yu@Sun.COMstatic int 950Sstevel@tonic-gateenvctrl_probe(device_t dev) 9611042SErik.Nordmark@Sun.COM{ 970Sstevel@tonic-gate 9811042SErik.Nordmark@Sun.COM if (strcmp("SUNW,envctrl", ebus_get_name(dev)) == 0) { 9911042SErik.Nordmark@Sun.COM device_set_desc(dev, "EBus SUNW,envctrl"); 10011042SErik.Nordmark@Sun.COM return (0); 1010Sstevel@tonic-gate } 10211042SErik.Nordmark@Sun.COM return (ENXIO); 1030Sstevel@tonic-gate} 1040Sstevel@tonic-gate 10511042SErik.Nordmark@Sun.COMstatic int 1060Sstevel@tonic-gateenvctrl_attach(device_t dev) 1070Sstevel@tonic-gate{ 10811042SErik.Nordmark@Sun.COM struct pcf_softc *sc; 1090Sstevel@tonic-gate int rv = ENXIO; 1100Sstevel@tonic-gate 11111042SErik.Nordmark@Sun.COM sc = DEVTOSOFTC(dev); 1120Sstevel@tonic-gate bzero(sc, sizeof(struct pcf_softc)); 1130Sstevel@tonic-gate 11411042SErik.Nordmark@Sun.COM /* IO port is mandatory */ 1150Sstevel@tonic-gate sc->res_ioport = bus_alloc_resource_any(dev, SYS_RES_IOPORT, 1160Sstevel@tonic-gate &sc->rid_ioport, RF_ACTIVE); 11711042SErik.Nordmark@Sun.COM if (sc->res_ioport == 0) { 1180Sstevel@tonic-gate device_printf(dev, "cannot reserve I/O port range\n"); 1190Sstevel@tonic-gate goto error; 12011042SErik.Nordmark@Sun.COM } 1210Sstevel@tonic-gate sc->bt_ioport = rman_get_bustag(sc->res_ioport); 1220Sstevel@tonic-gate sc->bh_ioport = rman_get_bushandle(sc->res_ioport); 1230Sstevel@tonic-gate 12411042SErik.Nordmark@Sun.COM sc->pcf_flags = device_get_flags(dev); 1250Sstevel@tonic-gate 1260Sstevel@tonic-gate if (!(sc->pcf_flags & IIC_POLLED)) { 12711042SErik.Nordmark@Sun.COM sc->res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->rid_irq, 1280Sstevel@tonic-gate RF_ACTIVE); 12911042SErik.Nordmark@Sun.COM if (sc->res_irq == 0) { 1300Sstevel@tonic-gate device_printf(dev, "can't reserve irq, polled mode.\n"); 1310Sstevel@tonic-gate sc->pcf_flags |= IIC_POLLED; 13211042SErik.Nordmark@Sun.COM } 1330Sstevel@tonic-gate } 1340Sstevel@tonic-gate 13511042SErik.Nordmark@Sun.COM /* reset the chip */ 1360Sstevel@tonic-gate pcf_rst_card(dev, IIC_FASTEST, PCF_DEFAULT_ADDR, NULL); 1370Sstevel@tonic-gate 1385455Smeem rv = BUS_SETUP_INTR(device_get_parent(dev), dev, sc->res_irq, 1395455Smeem INTR_TYPE_NET /* | INTR_ENTROPY */, 1405455Smeem pcf_intr, sc, &sc->intr_cookie); 14111042SErik.Nordmark@Sun.COM if (rv) { 1420Sstevel@tonic-gate device_printf(dev, "could not setup IRQ\n"); 1433318Srshoaib goto error; 14411042SErik.Nordmark@Sun.COM } 1453318Srshoaib 1463318Srshoaib if ((sc->iicbus = device_add_child(dev, "iicbus", -1)) == NULL) 14711042SErik.Nordmark@Sun.COM device_printf(dev, "could not allocate iicbus instance\n"); 14811042SErik.Nordmark@Sun.COM 14911042SErik.Nordmark@Sun.COM /* probe and attach the iicbus */ 1503318Srshoaib bus_generic_attach(dev); 1511663Spriyanka 1520Sstevel@tonic-gate return (0); 15311042SErik.Nordmark@Sun.COM 1540Sstevel@tonic-gateerror: 1550Sstevel@tonic-gate if (sc->res_irq != 0) { 1560Sstevel@tonic-gate bus_deactivate_resource(dev, SYS_RES_IRQ, sc->rid_irq, 15711042SErik.Nordmark@Sun.COM sc->res_irq); 1580Sstevel@tonic-gate bus_release_resource(dev, SYS_RES_IRQ, sc->rid_irq, 15911042SErik.Nordmark@Sun.COM sc->res_irq); 1600Sstevel@tonic-gate } 1610Sstevel@tonic-gate if (sc->res_ioport != 0) { 16211042SErik.Nordmark@Sun.COM bus_deactivate_resource(dev, SYS_RES_IOPORT, sc->rid_ioport, 1630Sstevel@tonic-gate sc->res_ioport); 1640Sstevel@tonic-gate bus_release_resource(dev, SYS_RES_IOPORT, sc->rid_ioport, 16511042SErik.Nordmark@Sun.COM sc->res_ioport); 1660Sstevel@tonic-gate } 1670Sstevel@tonic-gate return (rv); 16811042SErik.Nordmark@Sun.COM} 1690Sstevel@tonic-gate 1700Sstevel@tonic-gatestatic int 17111042SErik.Nordmark@Sun.COMenvctrl_detach(device_t dev) 1720Sstevel@tonic-gate{ 1730Sstevel@tonic-gate struct pcf_softc *sc; 1740Sstevel@tonic-gate int rv; 17511042SErik.Nordmark@Sun.COM 1760Sstevel@tonic-gate sc = DEVTOSOFTC(dev); 1770Sstevel@tonic-gate 1780Sstevel@tonic-gate if ((rv = bus_generic_detach(dev)) != 0) 17911042SErik.Nordmark@Sun.COM return (rv); 1800Sstevel@tonic-gate 1810Sstevel@tonic-gate if ((rv = device_delete_child(dev, sc->iicbus)) != 0) 18211042SErik.Nordmark@Sun.COM return (rv); 1830Sstevel@tonic-gate 1840Sstevel@tonic-gate if (sc->res_irq != 0) { 18511042SErik.Nordmark@Sun.COM BUS_TEARDOWN_INTR(device_get_parent(dev), dev, sc->res_irq, 1860Sstevel@tonic-gate sc->intr_cookie); 1870Sstevel@tonic-gate bus_deactivate_resource(dev, SYS_RES_IRQ, sc->rid_irq, sc->res_irq); 18811042SErik.Nordmark@Sun.COM bus_release_resource(dev, SYS_RES_IRQ, sc->rid_irq, sc->res_irq); 1890Sstevel@tonic-gate } 1900Sstevel@tonic-gate 19111042SErik.Nordmark@Sun.COM bus_deactivate_resource(dev, SYS_RES_IOPORT, sc->rid_ioport, sc->res_ioport); 1920Sstevel@tonic-gate bus_release_resource(dev, SYS_RES_IOPORT, sc->rid_ioport, sc->res_ioport); 1930Sstevel@tonic-gate 19411042SErik.Nordmark@Sun.COM return (0); 1950Sstevel@tonic-gate} 1960Sstevel@tonic-gate 19711042SErik.Nordmark@Sun.COMDRIVER_MODULE(envctrl, ebus, envctrl_driver, envctrl_devclass, 0, 0); 1980Sstevel@tonic-gateMODULE_DEPEND(envctrl, iicbus, PCF_MINVER, PCF_PREFVER, PCF_MAXVER); 1990Sstevel@tonic-gateMODULE_VERSION(envctrl, PCF_MODVER); 2000Sstevel@tonic-gate