pcf_ebus.c revision 130320
1/*- 2 * Copyright (c) 2004 Marius Strobl, Joerg Wunsch 3 * 4 * derived from sys/i386/isa/pcf.c which is: 5 * 6 * Copyright (c) 1998 Nicolas Souchu, Marc Bouget 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30#include <sys/cdefs.h> 31__FBSDID("$FreeBSD: head/sys/dev/pcf/pcf_ebus.c 130320 2004-06-10 21:56:52Z marius $"); 32 33/* 34 * Device specific driver for the EBus i2c devices found on some sun4u 35 * systems. On systems not having a boot-bus controller the i2c devices 36 * are PCF8584. 37 * 38 * Known onboard slave devices on the primary bus are: 39 * 40 * AXe: 41 * 0x40 PCF8574 I/O fan status (CPU fans 1+2) 42 * 0x9e PCF8591 A/D temperature (CPU + hotspot) 43 * 44 * AXmp: 45 * 0x70 PCF8574 I/O fan status (fans 1-4) 46 * 0x78 PCF8574 I/O fan fail interrupt 47 * 0x9a PCF8591 A/D voltage (CPU core) 48 * 0x9c PCF8591 A/D temperature (hotspots 1+2, aux. analog 1+2) 49 * 0x9e PCF8591 A/D temperature (CPUs 1-4) 50 * 51 * CP1400: 52 * 0x70 PCF8574 I/O reserved for factory use 53 * 0x9e PCF8591 A/D temperature (CPU) 54 * 55 * CP1500: 56 * 0x70 PCF8574 I/O reserved for factory use 57 * 0x72 PCF8574 I/O geographic address + power supply status lines 58 * 0x9e PCF8591 A/D temperature (CPU) 59 * 0xa0 AT24C01A hostid 60 * 61 * For AXmp, CP1400 and CP1500 these are described in more detail in: 62 * http://www.sun.com/oem/products/manuals/805-7581-04.pdf 63 * 64 */ 65 66#include <sys/param.h> 67#include <sys/systm.h> 68#include <sys/bus.h> 69#include <sys/kernel.h> 70#include <sys/module.h> 71#include <sys/resource.h> 72 73#include <machine/bus.h> 74#include <machine/resource.h> 75 76#include <sys/rman.h> 77 78#include <dev/ofw/openfirm.h> 79 80#include <sparc64/ebus/ebusvar.h> 81 82#include <dev/iicbus/iiconf.h> 83#include <dev/pcf/pcfvar.h> 84#include "iicbus_if.h" 85 86#define PCF_NAME "pcf" 87 88static int pcf_ebus_probe(device_t); 89static int pcf_ebus_attach(device_t); 90static int pcf_ebus_detach(device_t); 91 92static device_method_t pcf_ebus_methods[] = { 93 /* device interface */ 94 DEVMETHOD(device_probe, pcf_ebus_probe), 95 DEVMETHOD(device_attach, pcf_ebus_attach), 96 DEVMETHOD(device_detach, pcf_ebus_detach), 97 98 /* iicbus interface */ 99 DEVMETHOD(iicbus_callback, iicbus_null_callback), 100 DEVMETHOD(iicbus_repeated_start, pcf_repeated_start), 101 DEVMETHOD(iicbus_start, pcf_start), 102 DEVMETHOD(iicbus_stop, pcf_stop), 103 DEVMETHOD(iicbus_write, pcf_write), 104 DEVMETHOD(iicbus_read, pcf_read), 105 DEVMETHOD(iicbus_reset, pcf_rst_card), 106 { 0, 0 } 107}; 108 109static devclass_t pcf_ebus_devclass; 110 111static driver_t pcf_ebus_driver = { 112 PCF_NAME, 113 pcf_ebus_methods, 114 sizeof(struct pcf_softc), 115}; 116 117static int 118pcf_ebus_probe(device_t dev) 119{ 120 char *compat; 121 122 /* 123 * We must not attach to this i2c device if this is a system with 124 * a boot-bus controller. Additionally testing the compatibility 125 * property will hopefully take care of this. 126 */ 127 if (strcmp("i2c", ebus_get_name(dev)) == 0) { 128 compat = ebus_get_compat(dev); 129 if (compat != NULL && strcmp("i2cpcf,8584", compat) == 0) { 130 device_set_desc(dev, "PCF8584 I2C bus controller"); 131 return (0); 132 } 133 } 134 return (ENXIO); 135} 136 137static int 138pcf_ebus_attach(device_t dev) 139{ 140 struct pcf_softc *sc; 141 int rv = ENXIO; 142 phandle_t node; 143 uint64_t own_addr; 144 145 sc = DEVTOSOFTC(dev); 146 bzero(sc, sizeof(struct pcf_softc)); 147 148 /* get OFW node of the pcf */ 149 if ((node = ebus_get_node(dev)) <= 0) { 150 device_printf(dev, "cannot get OFW node\n"); 151 goto error; 152 } 153 154 /* IO port is mandatory */ 155 sc->res_ioport = bus_alloc_resource_any(dev, SYS_RES_IOPORT, 156 &sc->rid_ioport, RF_ACTIVE); 157 if (sc->res_ioport == 0) { 158 device_printf(dev, "cannot reserve I/O port range\n"); 159 goto error; 160 } 161 162 sc->pcf_flags = device_get_flags(dev); 163 164 /* 165 * XXX use poll-mode property? 166 */ 167 if (!(sc->pcf_flags & IIC_POLLED)) { 168 sc->res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, 169 &sc->rid_irq, RF_ACTIVE); 170 if (sc->res_irq == 0) { 171 device_printf(dev, "can't reserve irq, polled mode.\n"); 172 sc->pcf_flags |= IIC_POLLED; 173 } 174 } 175 176 /* 177 * XXX on AXmp there's probably a second IRQ which is the fan fail 178 * interrupt genererated by the PCF8574 at 0x78. 179 */ 180 181 /* get address of the pcf */ 182 if (OF_getprop(node, "own-address", &own_addr, sizeof(own_addr)) == 183 -1) { 184 device_printf(dev, "cannot get own address\n"); 185 goto error; 186 } 187 if (bootverbose) 188 device_printf(dev, "PCF8584 address: 0x%08llx\n", (unsigned 189 long long)own_addr); 190 191 /* reset the chip */ 192 pcf_rst_card(dev, IIC_FASTEST, own_addr, NULL); 193 194 if (sc->res_irq) { 195 rv = BUS_SETUP_INTR(device_get_parent(dev), dev, sc->res_irq, 196 INTR_TYPE_NET /* | INTR_ENTROPY */, pcf_intr, sc, 197 &sc->intr_cookie); 198 if (rv) { 199 device_printf(dev, "could not setup IRQ\n"); 200 goto error; 201 } 202 } 203 204 if ((sc->iicbus = device_add_child(dev, "iicbus", -1)) == NULL) 205 device_printf(dev, "could not allocate iicbus instance\n"); 206 207 /* probe and attach the iicbus */ 208 bus_generic_attach(dev); 209 210 return (0); 211 212error: 213 if (sc->res_irq != 0) { 214 bus_deactivate_resource(dev, SYS_RES_IRQ, sc->rid_irq, 215 sc->res_irq); 216 bus_release_resource(dev, SYS_RES_IRQ, sc->rid_irq, 217 sc->res_irq); 218 } 219 if (sc->res_ioport != 0) { 220 bus_deactivate_resource(dev, SYS_RES_IOPORT, sc->rid_ioport, 221 sc->res_ioport); 222 bus_release_resource(dev, SYS_RES_IOPORT, sc->rid_ioport, 223 sc->res_ioport); 224 } 225 return (rv); 226} 227 228static int 229pcf_ebus_detach(device_t dev) 230{ 231 struct pcf_softc *sc; 232 int rv; 233 234 sc = DEVTOSOFTC(dev); 235 236 if ((rv = bus_generic_detach(dev)) != 0) 237 return (rv); 238 239 if ((rv = device_delete_child(dev, sc->iicbus)) != 0) 240 return (rv); 241 242 if (sc->res_irq != 0) { 243 BUS_TEARDOWN_INTR(device_get_parent(dev), dev, sc->res_irq, 244 sc->intr_cookie); 245 bus_deactivate_resource(dev, SYS_RES_IRQ, sc->rid_irq, 246 sc->res_irq); 247 bus_release_resource(dev, SYS_RES_IRQ, sc->rid_irq, 248 sc->res_irq); 249 } 250 251 bus_deactivate_resource(dev, SYS_RES_IOPORT, sc->rid_ioport, 252 sc->res_ioport); 253 bus_release_resource(dev, SYS_RES_IOPORT, sc->rid_ioport, 254 sc->res_ioport); 255 256 return (0); 257} 258 259DRIVER_MODULE(pcf_ebus, ebus, pcf_ebus_driver, pcf_ebus_devclass, 0, 0); 260MODULE_DEPEND(pcf_ebus, iicbus, PCF_MINVER, PCF_PREFVER, PCF_MAXVER); 261MODULE_VERSION(pcf_ebus, PCF_MODVER); 262