ichsmb_pci.c revision 127135
1119418Sobrien/*-
266703Sarchie * ichsmb_pci.c
366703Sarchie *
4119418Sobrien * Author: Archie Cobbs <archie@freebsd.org>
566703Sarchie * Copyright (c) 2000 Whistle Communications, Inc.
666703Sarchie * All rights reserved.
7119418Sobrien * Author: Archie Cobbs <archie@freebsd.org>
866703Sarchie *
966703Sarchie * Subject to the following obligations and disclaimer of warranty, use and
1066703Sarchie * redistribution of this software, in source or object code forms, with or
1166703Sarchie * without modifications are expressly permitted by Whistle Communications;
1266703Sarchie * provided, however, that:
1366703Sarchie * 1. Any and all reproductions of the source or object code must include the
1466703Sarchie *    copyright notice above and the following disclaimer of warranties; and
1566703Sarchie * 2. No rights are granted, in any manner or form, to use Whistle
1666703Sarchie *    Communications, Inc. trademarks, including the mark "WHISTLE
1766703Sarchie *    COMMUNICATIONS" on advertising, endorsements, or otherwise except as
1866703Sarchie *    such appears in the above copyright notice or in the software.
1966703Sarchie *
2066703Sarchie * THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
2166703Sarchie * TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
2266703Sarchie * REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
2366703Sarchie * INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED WARRANTIES OF
2466703Sarchie * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
2566703Sarchie * WHISTLE COMMUNICATIONS DOES NOT WARRANT, GUARANTEE, OR MAKE ANY
2666703Sarchie * REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS OF THE USE OF THIS
2766703Sarchie * SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY, RELIABILITY OR OTHERWISE.
2866703Sarchie * IN NO EVENT SHALL WHISTLE COMMUNICATIONS BE LIABLE FOR ANY DAMAGES
2966703Sarchie * RESULTING FROM OR ARISING OUT OF ANY USE OF THIS SOFTWARE, INCLUDING
3066703Sarchie * WITHOUT LIMITATION, ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
3166703Sarchie * PUNITIVE, OR CONSEQUENTIAL DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR
3266703Sarchie * SERVICES, LOSS OF USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY
3366703Sarchie * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3466703Sarchie * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
3566703Sarchie * THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
3666703Sarchie * OF SUCH DAMAGE.
3766703Sarchie */
3866703Sarchie
39119418Sobrien#include <sys/cdefs.h>
40119418Sobrien__FBSDID("$FreeBSD: head/sys/dev/ichsmb/ichsmb_pci.c 127135 2004-03-17 17:50:55Z njl $");
41119418Sobrien
4266703Sarchie/*
4366703Sarchie * Support for the SMBus controller logical device which is part of the
44119618Snjl * Intel 81801AA/AB/BA/CA/DC/EB (ICH/ICH[02345]) I/O controller hub chips.
4566703Sarchie */
4666703Sarchie
4766703Sarchie#include <sys/param.h>
4866703Sarchie#include <sys/systm.h>
4966703Sarchie#include <sys/kernel.h>
5066703Sarchie#include <sys/errno.h>
5174914Sjhb#include <sys/lock.h>
5269734Sarchie#include <sys/mutex.h>
5366703Sarchie#include <sys/syslog.h>
5466703Sarchie#include <sys/bus.h>
5566703Sarchie
5666703Sarchie#include <machine/bus.h>
5766703Sarchie#include <sys/rman.h>
5866703Sarchie#include <machine/resource.h>
5966703Sarchie
60119280Simp#include <dev/pci/pcivar.h>
61119280Simp#include <dev/pci/pcireg.h>
6266703Sarchie
6366703Sarchie#include <dev/smbus/smbconf.h>
6466703Sarchie
6566703Sarchie#include <dev/ichsmb/ichsmb_var.h>
6666703Sarchie#include <dev/ichsmb/ichsmb_reg.h>
6766703Sarchie
6866703Sarchie/* PCI unique identifiers */
69105394Snyan#define ID_82801AA			0x24138086
70105394Snyan#define ID_82801AB			0x24238086
7166703Sarchie#define ID_82801BA			0x24438086
7296200Sjhb#define ID_82801CA			0x24838086
73101742Smp#define ID_82801DC			0x24C38086
74119600Snjl#define ID_82801EB			0x24D38086
7566703Sarchie
7666703Sarchie#define PCIS_SERIALBUS_SMBUS_PROGIF	0x00
7766703Sarchie
7866703Sarchie/* Internal functions */
7966703Sarchiestatic int	ichsmb_pci_probe(device_t dev);
8066703Sarchiestatic int	ichsmb_pci_attach(device_t dev);
8166703Sarchie
8266703Sarchie/* Device methods */
8366703Sarchiestatic device_method_t ichsmb_pci_methods[] = {
8466703Sarchie	/* Device interface */
8566703Sarchie        DEVMETHOD(device_probe, ichsmb_pci_probe),
8666703Sarchie        DEVMETHOD(device_attach, ichsmb_pci_attach),
8766703Sarchie
8866703Sarchie	/* Bus methods */
8966703Sarchie        DEVMETHOD(bus_print_child, bus_generic_print_child),
9066703Sarchie
9166703Sarchie	/* SMBus methods */
9266703Sarchie        DEVMETHOD(smbus_callback, ichsmb_callback),
9366703Sarchie        DEVMETHOD(smbus_quick, ichsmb_quick),
9466703Sarchie        DEVMETHOD(smbus_sendb, ichsmb_sendb),
9566703Sarchie        DEVMETHOD(smbus_recvb, ichsmb_recvb),
9666703Sarchie        DEVMETHOD(smbus_writeb, ichsmb_writeb),
9766703Sarchie        DEVMETHOD(smbus_writew, ichsmb_writew),
9866703Sarchie        DEVMETHOD(smbus_readb, ichsmb_readb),
9966703Sarchie        DEVMETHOD(smbus_readw, ichsmb_readw),
10066703Sarchie        DEVMETHOD(smbus_pcall, ichsmb_pcall),
10166703Sarchie        DEVMETHOD(smbus_bwrite, ichsmb_bwrite),
10266703Sarchie        DEVMETHOD(smbus_bread, ichsmb_bread),
10366703Sarchie	{ 0, 0 }
10466703Sarchie};
10566703Sarchie
10666703Sarchiestatic driver_t ichsmb_pci_driver = {
10766703Sarchie	"ichsmb",
10866703Sarchie	ichsmb_pci_methods,
10966703Sarchie	sizeof(struct ichsmb_softc)
11066703Sarchie};
11166703Sarchie
11266703Sarchiestatic devclass_t ichsmb_pci_devclass;
11366703Sarchie
11466703SarchieDRIVER_MODULE(ichsmb, pci, ichsmb_pci_driver, ichsmb_pci_devclass, 0, 0);
11566703Sarchie
11666703Sarchiestatic int
11766703Sarchieichsmb_pci_probe(device_t dev)
11866703Sarchie{
11966703Sarchie	/* Check PCI identifier */
12066703Sarchie	switch (pci_get_devid(dev)) {
121105394Snyan	case ID_82801AA:
12266703Sarchie		device_set_desc(dev, "Intel 82801AA (ICH) SMBus controller");
12366703Sarchie		break;
124105394Snyan	case ID_82801AB:
12566703Sarchie		device_set_desc(dev, "Intel 82801AB (ICH0) SMBus controller");
12666703Sarchie		break;
12766703Sarchie	case ID_82801BA:
12866703Sarchie		device_set_desc(dev, "Intel 82801BA (ICH2) SMBus controller");
12966703Sarchie		break;
13096200Sjhb	case ID_82801CA:
13196200Sjhb		device_set_desc(dev, "Intel 82801CA (ICH3) SMBus controller");
13296200Sjhb		break;
133101742Smp	case ID_82801DC:
134101742Smp		device_set_desc(dev, "Intel 82801DC (ICH4) SMBus controller");
135101742Smp		break;
136119600Snjl	case ID_82801EB:
137119600Snjl		device_set_desc(dev, "Intel 82801EB (ICH5) SMBus controller");
138119600Snjl		break;
13966703Sarchie	default:
14066703Sarchie		if (pci_get_class(dev) == PCIC_SERIALBUS
14166703Sarchie		    && pci_get_subclass(dev) == PCIS_SERIALBUS_SMBUS
14266703Sarchie		    && pci_get_progif(dev) == PCIS_SERIALBUS_SMBUS_PROGIF) {
14366703Sarchie			device_set_desc(dev, "SMBus controller");
14466703Sarchie			return (-2);		/* XXX */
14566703Sarchie		}
14666703Sarchie		return (ENXIO);
14766703Sarchie	}
14866703Sarchie
14966703Sarchie	/* Done */
15066703Sarchie	return (ichsmb_probe(dev));
15166703Sarchie}
15266703Sarchie
15366703Sarchiestatic int
15466703Sarchieichsmb_pci_attach(device_t dev)
15566703Sarchie{
15666703Sarchie	const sc_p sc = device_get_softc(dev);
15766703Sarchie	u_int32_t cmd;
15866703Sarchie	int error;
15966703Sarchie
16066703Sarchie	/* Initialize private state */
16166703Sarchie	bzero(sc, sizeof(*sc));
16266703Sarchie	sc->ich_cmd = -1;
16366703Sarchie	sc->dev = dev;
16466703Sarchie
16566703Sarchie	/* Allocate an I/O range */
16666703Sarchie	sc->io_rid = ICH_SMB_BASE;
16766703Sarchie	sc->io_res = bus_alloc_resource(dev, SYS_RES_IOPORT,
16866703Sarchie	    &sc->io_rid, 0, ~0, 16, RF_ACTIVE);
16966703Sarchie	if (sc->io_res == NULL) {
17066703Sarchie		log(LOG_ERR, "%s: can't map I/O\n", device_get_nameunit(dev));
17166703Sarchie		error = ENXIO;
17266703Sarchie		goto fail;
17366703Sarchie	}
17466703Sarchie	sc->io_bst = rman_get_bustag(sc->io_res);
17566703Sarchie	sc->io_bsh = rman_get_bushandle(sc->io_res);
17666703Sarchie
17766703Sarchie	/* Allocate interrupt */
17866703Sarchie	sc->irq_rid = 0;
179127135Snjl	sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
180127135Snjl	    &sc->irq_rid, RF_ACTIVE | RF_SHAREABLE);
18166703Sarchie	if (sc->irq_res == NULL) {
18266703Sarchie		log(LOG_ERR, "%s: can't get IRQ\n", device_get_nameunit(dev));
18366703Sarchie		error = ENXIO;
18466703Sarchie		goto fail;
18566703Sarchie	}
18666703Sarchie
18766703Sarchie	/* Set up interrupt handler */
18866703Sarchie	error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_MISC,
18966703Sarchie	    ichsmb_device_intr, sc, &sc->irq_handle);
19066703Sarchie	if (error != 0) {
19166703Sarchie		log(LOG_ERR, "%s: can't setup irq\n", device_get_nameunit(dev));
19266703Sarchie		goto fail;
19366703Sarchie	}
19466703Sarchie
19566703Sarchie	/* Enable I/O mapping */
19666703Sarchie	cmd = pci_read_config(dev, PCIR_COMMAND, 4);
19766703Sarchie	cmd |= PCIM_CMD_PORTEN;
19866703Sarchie	pci_write_config(dev, PCIR_COMMAND, cmd, 4);
19966703Sarchie	cmd = pci_read_config(dev, PCIR_COMMAND, 4);
20066703Sarchie	if ((cmd & PCIM_CMD_PORTEN) == 0) {
20166703Sarchie		log(LOG_ERR, "%s: can't enable memory map\n",
20266703Sarchie		    device_get_nameunit(dev));
20366703Sarchie		error = ENXIO;
20466703Sarchie		goto fail;
20566703Sarchie	}
20666703Sarchie
20766703Sarchie	/* Enable device */
20866703Sarchie	pci_write_config(dev, ICH_HOSTC, ICH_HOSTC_HST_EN, 1);
20966703Sarchie
21066703Sarchie	/* Done */
21166703Sarchie	return (ichsmb_attach(dev));
21266703Sarchie
21366703Sarchiefail:
21466703Sarchie	/* Attach failed, release resources */
21566703Sarchie	ichsmb_release_resources(sc);
21666703Sarchie	return (error);
21766703Sarchie}
21866703Sarchie
219