ichsmb_pci.c revision 131070
1279315Strasz/*- 2279315Strasz * ichsmb_pci.c 3279315Strasz * 4279315Strasz * Author: Archie Cobbs <archie@freebsd.org> 5279315Strasz * Copyright (c) 2000 Whistle Communications, Inc. 6279315Strasz * All rights reserved. 7279315Strasz * Author: Archie Cobbs <archie@freebsd.org> 8279315Strasz * 9279315Strasz * Subject to the following obligations and disclaimer of warranty, use and 10279315Strasz * redistribution of this software, in source or object code forms, with or 11279315Strasz * without modifications are expressly permitted by Whistle Communications; 12279315Strasz * provided, however, that: 13279315Strasz * 1. Any and all reproductions of the source or object code must include the 14279315Strasz * copyright notice above and the following disclaimer of warranties; and 15279315Strasz * 2. No rights are granted, in any manner or form, to use Whistle 16279315Strasz * Communications, Inc. trademarks, including the mark "WHISTLE 17279315Strasz * COMMUNICATIONS" on advertising, endorsements, or otherwise except as 18279315Strasz * such appears in the above copyright notice or in the software. 19279315Strasz * 20279315Strasz * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND 21279315Strasz * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO 22279315Strasz * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE, 23279315Strasz * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF 24279315Strasz * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. 25279315Strasz * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY 26279315Strasz * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS 27279315Strasz * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE. 28279315Strasz * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES 29279315Strasz * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING 30279315Strasz * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 31279315Strasz * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR 32279315Strasz * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY 33279315Strasz * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34279315Strasz * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 35279315Strasz * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY 36279315Strasz * OF SUCH DAMAGE. 37279315Strasz */ 38279315Strasz 39279315Strasz#include <sys/cdefs.h> 40279315Strasz__FBSDID("$FreeBSD: head/sys/dev/ichsmb/ichsmb_pci.c 131070 2004-06-24 18:21:28Z ambrisko $"); 41279315Strasz 42279315Strasz/* 43279315Strasz * Support for the SMBus controller logical device which is part of the 44279315Strasz * Intel 81801AA/AB/BA/CA/DC/EB (ICH/ICH[02345]) I/O controller hub chips. 45279315Strasz */ 46279315Strasz 47279315Strasz#include <sys/param.h> 48279315Strasz#include <sys/systm.h> 49279315Strasz#include <sys/kernel.h> 50279315Strasz#include <sys/module.h> 51279315Strasz#include <sys/errno.h> 52279315Strasz#include <sys/lock.h> 53279315Strasz#include <sys/mutex.h> 54279315Strasz#include <sys/syslog.h> 55279315Strasz#include <sys/bus.h> 56279315Strasz 57279315Strasz#include <machine/bus.h> 58279315Strasz#include <sys/rman.h> 59279315Strasz#include <machine/resource.h> 60279315Strasz 61279315Strasz#include <dev/pci/pcivar.h> 62279315Strasz#include <dev/pci/pcireg.h> 63279315Strasz 64279315Strasz#include <dev/smbus/smbconf.h> 65279315Strasz 66279315Strasz#include <dev/ichsmb/ichsmb_var.h> 67279315Strasz#include <dev/ichsmb/ichsmb_reg.h> 68279315Strasz 69279315Strasz/* PCI unique identifiers */ 70279315Strasz#define ID_82801AA 0x24138086 71279315Strasz#define ID_82801AB 0x24238086 72279315Strasz#define ID_82801BA 0x24438086 73279315Strasz#define ID_82801CA 0x24838086 74279315Strasz#define ID_82801DC 0x24C38086 75279315Strasz#define ID_82801EB 0x24D38086 76279315Strasz#define ID_6300ESB 0x25a48086 77279315Strasz 78279315Strasz#define PCIS_SERIALBUS_SMBUS_PROGIF 0x00 79279315Strasz 80279315Strasz/* Internal functions */ 81279315Straszstatic int ichsmb_pci_probe(device_t dev); 82279315Straszstatic int ichsmb_pci_attach(device_t dev); 83279315Strasz 84279315Strasz/* Device methods */ 85279315Straszstatic device_method_t ichsmb_pci_methods[] = { 86279315Strasz /* Device interface */ 87279315Strasz DEVMETHOD(device_probe, ichsmb_pci_probe), 88279315Strasz DEVMETHOD(device_attach, ichsmb_pci_attach), 89279315Strasz 90279315Strasz /* Bus methods */ 91279315Strasz DEVMETHOD(bus_print_child, bus_generic_print_child), 92279315Strasz 93279315Strasz /* SMBus methods */ 94279315Strasz DEVMETHOD(smbus_callback, ichsmb_callback), 95279315Strasz DEVMETHOD(smbus_quick, ichsmb_quick), 96279315Strasz DEVMETHOD(smbus_sendb, ichsmb_sendb), 97279315Strasz DEVMETHOD(smbus_recvb, ichsmb_recvb), 98279315Strasz DEVMETHOD(smbus_writeb, ichsmb_writeb), 99279315Strasz DEVMETHOD(smbus_writew, ichsmb_writew), 100279315Strasz DEVMETHOD(smbus_readb, ichsmb_readb), 101279315Strasz DEVMETHOD(smbus_readw, ichsmb_readw), 102279315Strasz DEVMETHOD(smbus_pcall, ichsmb_pcall), 103279315Strasz DEVMETHOD(smbus_bwrite, ichsmb_bwrite), 104279315Strasz DEVMETHOD(smbus_bread, ichsmb_bread), 105279315Strasz { 0, 0 } 106279315Strasz}; 107279315Strasz 108279315Straszstatic driver_t ichsmb_pci_driver = { 109279315Strasz "ichsmb", 110279315Strasz ichsmb_pci_methods, 111279315Strasz sizeof(struct ichsmb_softc) 112279315Strasz}; 113279315Strasz 114279315Straszstatic devclass_t ichsmb_pci_devclass; 115279315Strasz 116279315StraszDRIVER_MODULE(ichsmb, pci, ichsmb_pci_driver, ichsmb_pci_devclass, 0, 0); 117279315Strasz 118279315Straszstatic int 119279315Straszichsmb_pci_probe(device_t dev) 120279315Strasz{ 121279315Strasz /* Check PCI identifier */ 122279315Strasz switch (pci_get_devid(dev)) { 123279315Strasz case ID_82801AA: 124279315Strasz device_set_desc(dev, "Intel 82801AA (ICH) SMBus controller"); 125279315Strasz break; 126279315Strasz case ID_82801AB: 127279315Strasz device_set_desc(dev, "Intel 82801AB (ICH0) SMBus controller"); 128279315Strasz break; 129279315Strasz case ID_82801BA: 130279315Strasz device_set_desc(dev, "Intel 82801BA (ICH2) SMBus controller"); 131279315Strasz break; 132279315Strasz case ID_82801CA: 133279315Strasz device_set_desc(dev, "Intel 82801CA (ICH3) SMBus controller"); 134279315Strasz break; 135279315Strasz case ID_82801DC: 136279315Strasz device_set_desc(dev, "Intel 82801DC (ICH4) SMBus controller"); 137279315Strasz break; 138279315Strasz case ID_82801EB: 139279315Strasz device_set_desc(dev, "Intel 82801EB (ICH5) SMBus controller"); 140279315Strasz break; 141279315Strasz case ID_6300ESB: 142279315Strasz device_set_desc(dev, "Intel 6300ESB (ICH) SMBus controller"); 143279315Strasz break; 144279315Strasz default: 145279315Strasz if (pci_get_class(dev) == PCIC_SERIALBUS 146279315Strasz && pci_get_subclass(dev) == PCIS_SERIALBUS_SMBUS 147279315Strasz && pci_get_progif(dev) == PCIS_SERIALBUS_SMBUS_PROGIF) { 148279315Strasz device_set_desc(dev, "SMBus controller"); 149279315Strasz return (-2); /* XXX */ 150279315Strasz } 151279315Strasz return (ENXIO); 152279315Strasz } 153279315Strasz 154279315Strasz /* Done */ 155279315Strasz return (ichsmb_probe(dev)); 156279315Strasz} 157279315Strasz 158279315Straszstatic int 159279315Straszichsmb_pci_attach(device_t dev) 160279315Strasz{ 161279315Strasz const sc_p sc = device_get_softc(dev); 162279315Strasz u_int32_t cmd; 163279315Strasz int error; 164279315Strasz 165279315Strasz /* Initialize private state */ 166279315Strasz bzero(sc, sizeof(*sc)); 167279315Strasz sc->ich_cmd = -1; 168279315Strasz sc->dev = dev; 169279315Strasz 170279315Strasz /* Allocate an I/O range */ 171279315Strasz sc->io_rid = ICH_SMB_BASE; 172279315Strasz sc->io_res = bus_alloc_resource(dev, SYS_RES_IOPORT, 173279315Strasz &sc->io_rid, 0, ~0, 16, RF_ACTIVE); 174279315Strasz if (sc->io_res == NULL) 175279315Strasz sc->io_res = bus_alloc_resource(dev, SYS_RES_IOPORT, 176279315Strasz &sc->io_rid, 0, ~0, 32, RF_ACTIVE); 177279315Strasz if (sc->io_res == NULL) { 178279315Strasz log(LOG_ERR, "%s: can't map I/O\n", device_get_nameunit(dev)); 179279315Strasz error = ENXIO; 180279315Strasz goto fail; 181279315Strasz } 182279315Strasz sc->io_bst = rman_get_bustag(sc->io_res); 183279315Strasz sc->io_bsh = rman_get_bushandle(sc->io_res); 184279315Strasz 185279315Strasz /* Allocate interrupt */ 186279315Strasz sc->irq_rid = 0; 187279315Strasz sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, 188279315Strasz &sc->irq_rid, RF_ACTIVE | RF_SHAREABLE); 189279315Strasz if (sc->irq_res == NULL) { 190279315Strasz log(LOG_ERR, "%s: can't get IRQ\n", device_get_nameunit(dev)); 191279315Strasz error = ENXIO; 192279315Strasz goto fail; 193279315Strasz } 194279315Strasz 195279315Strasz /* Set up interrupt handler */ 196279315Strasz error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC, 197279315Strasz ichsmb_device_intr, sc, &sc->irq_handle); 198279315Strasz if (error != 0) { 199279315Strasz log(LOG_ERR, "%s: can't setup irq\n", device_get_nameunit(dev)); 200279315Strasz goto fail; 201279315Strasz } 202279315Strasz 203279315Strasz /* Enable I/O mapping */ 204279315Strasz cmd = pci_read_config(dev, PCIR_COMMAND, 4); 205279315Strasz cmd |= PCIM_CMD_PORTEN; 206279315Strasz pci_write_config(dev, PCIR_COMMAND, cmd, 4); 207279315Strasz cmd = pci_read_config(dev, PCIR_COMMAND, 4); 208279315Strasz if ((cmd & PCIM_CMD_PORTEN) == 0) { 209279315Strasz log(LOG_ERR, "%s: can't enable memory map\n", 210279315Strasz device_get_nameunit(dev)); 211279315Strasz error = ENXIO; 212279315Strasz goto fail; 213279315Strasz } 214279315Strasz 215279315Strasz /* Enable device */ 216279315Strasz pci_write_config(dev, ICH_HOSTC, ICH_HOSTC_HST_EN, 1); 217279315Strasz 218279315Strasz /* Done */ 219279315Strasz return (ichsmb_attach(dev)); 220279315Strasz 221279315Straszfail: 222279315Strasz /* Attach failed, release resources */ 223279315Strasz ichsmb_release_resources(sc); 224279315Strasz return (error); 225279315Strasz} 226279315Strasz 227279315Strasz