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