193023Snsouch/*-
293023Snsouch * Copyright (c) 2001 Alcove - Nicolas Souchu
393023Snsouch * All rights reserved.
493023Snsouch *
593023Snsouch * Redistribution and use in source and binary forms, with or without
693023Snsouch * modification, are permitted provided that the following conditions
793023Snsouch * are met:
893023Snsouch * 1. Redistributions of source code must retain the above copyright
993023Snsouch *    notice, this list of conditions and the following disclaimer.
1093023Snsouch * 2. Redistributions in binary form must reproduce the above copyright
1193023Snsouch *    notice, this list of conditions and the following disclaimer in the
1293023Snsouch *    documentation and/or other materials provided with the distribution.
1393023Snsouch *
1493023Snsouch * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1593023Snsouch * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1693023Snsouch * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1793023Snsouch * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1893023Snsouch * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1993023Snsouch * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2093023Snsouch * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2193023Snsouch * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2293023Snsouch * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2393023Snsouch * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2493023Snsouch * SUCH DAMAGE.
2593023Snsouch */
26116192Sobrien
27116192Sobrien#include <sys/cdefs.h>
28116192Sobrien__FBSDID("$FreeBSD$");
29116192Sobrien
30151900Sjhb#include "opt_isa.h"
31151900Sjhb
3293023Snsouch#include <sys/param.h>
33165951Sjhb#include <sys/bus.h>
3493023Snsouch#include <sys/kernel.h>
35165951Sjhb#include <sys/lock.h>
36165951Sjhb#include <sys/module.h>
37165951Sjhb#include <sys/mutex.h>
3893023Snsouch#include <sys/systm.h>
3993023Snsouch
4093023Snsouch#include <machine/bus.h>
4193023Snsouch#include <machine/resource.h>
4293023Snsouch#include <sys/rman.h>
4393023Snsouch
44151900Sjhb#ifdef DEV_ISA
45151900Sjhb#include <isa/isavar.h>
46151900Sjhb#include <isa/isa_common.h>
47151900Sjhb#endif
48119288Simp#include <dev/pci/pcivar.h>
49119288Simp#include <dev/pci/pcireg.h>
5093023Snsouch
5193023Snsouch#include <dev/iicbus/iiconf.h>
5293023Snsouch
5393023Snsouch#include <dev/smbus/smbconf.h>
5493023Snsouch
5593023Snsouch#include "iicbb_if.h"
5693023Snsouch#include "smbus_if.h"
5793023Snsouch
5893023Snsouch#define VIAPM_DEBUG(x)	if (viapm_debug) (x)
5993023Snsouch
6093023Snsouch#ifdef DEBUG
6193023Snsouchstatic int viapm_debug = 1;
6293023Snsouch#else
6393023Snsouchstatic int viapm_debug = 0;
6493023Snsouch#endif
6593023Snsouch
6693023Snsouch#define VIA_586B_PMU_ID		0x30401106
6793023Snsouch#define VIA_596A_PMU_ID		0x30501106
6893023Snsouch#define VIA_596B_PMU_ID		0x30511106
6993023Snsouch#define VIA_686A_PMU_ID		0x30571106
7093023Snsouch#define VIA_8233_PMU_ID		0x30741106
71116671Smdodd#define	VIA_8233A_PMU_ID	0x31471106
72151901Sjhb#define	VIA_8235_PMU_ID		0x31771106
73179933Sgonzo#define	VIA_8237_PMU_ID		0x32271106
74171693Skevlo#define	VIA_CX700_PMU_ID	0x83241106
7593023Snsouch
7693023Snsouch#define VIAPM_INB(port) \
77179622Sjhb	((u_char)bus_read_1(viapm->iores, port))
7893023Snsouch#define VIAPM_OUTB(port,val) \
79179622Sjhb	(bus_write_1(viapm->iores, port, (u_char)(val)))
8093023Snsouch
8193023Snsouch#define VIAPM_TYP_UNKNOWN	0
8293023Snsouch#define VIAPM_TYP_586B_3040E	1
8393023Snsouch#define VIAPM_TYP_586B_3040F	2
8493023Snsouch#define VIAPM_TYP_596B		3
8593023Snsouch#define VIAPM_TYP_686A		4
8693023Snsouch#define VIAPM_TYP_8233		5
8793023Snsouch
88165951Sjhb#define	VIAPM_LOCK(sc)		mtx_lock(&(sc)->lock)
89165951Sjhb#define	VIAPM_UNLOCK(sc)	mtx_unlock(&(sc)->lock)
90165951Sjhb#define	VIAPM_LOCK_ASSERT(sc)	mtx_assert(&(sc)->lock, MA_OWNED)
91165951Sjhb
9293023Snsouchstruct viapm_softc {
9393023Snsouch	int type;
9493023Snsouch	u_int32_t base;
9593023Snsouch	int iorid;
9693023Snsouch	int irqrid;
9793023Snsouch	struct resource *iores;
9893023Snsouch	struct resource *irqres;
9993023Snsouch	void *irqih;
10093023Snsouch	device_t iicbb;
10193023Snsouch	device_t smbus;
102165951Sjhb	struct mtx lock;
10393023Snsouch};
10493023Snsouch
10593023Snsouchstatic devclass_t viapm_devclass;
10693023Snsouchstatic devclass_t viapropm_devclass;
10793023Snsouch
10893023Snsouch/*
10993023Snsouch * VT82C586B definitions
11093023Snsouch */
11193023Snsouch
11293023Snsouch#define VIAPM_586B_REVID	0x08
11393023Snsouch
11493023Snsouch#define VIAPM_586B_3040E_BASE	0x20
11593023Snsouch#define VIAPM_586B_3040E_ACTIV	0x4		/* 16 bits */
11693023Snsouch
11793023Snsouch#define VIAPM_586B_3040F_BASE	0x48
11893023Snsouch#define VIAPM_586B_3040F_ACTIV	0x41		/* 8 bits */
11993023Snsouch
12093023Snsouch#define VIAPM_586B_OEM_REV_E	0x00
12193023Snsouch#define VIAPM_586B_OEM_REV_F	0x01
12293023Snsouch#define VIAPM_586B_PROD_REV_A	0x10
12393023Snsouch
12493023Snsouch#define VIAPM_586B_BA_MASK	0x0000ff00
12593023Snsouch
12693023Snsouch#define GPIO_DIR	0x40
12793023Snsouch#define GPIO_VAL	0x42
12893023Snsouch#define EXTSMI_VAL	0x44
12993023Snsouch
13093023Snsouch#define VIAPM_SCL	0x02			/* GPIO1_VAL */
13193023Snsouch#define VIAPM_SDA	0x04			/* GPIO2_VAL */
13293023Snsouch
13393023Snsouch/*
13493023Snsouch * VIAPRO common definitions
13593023Snsouch */
13693023Snsouch
13793023Snsouch#define VIAPM_PRO_BA_MASK	0x0000fff0
13893023Snsouch#define VIAPM_PRO_SMBCTRL	0xd2
13993023Snsouch#define VIAPM_PRO_REVID		0xd6
14093023Snsouch
14193023Snsouch/*
14293023Snsouch * VT82C686A definitions
14393023Snsouch */
14493023Snsouch
14593023Snsouch#define VIAPM_PRO_BASE		0x90
14693023Snsouch
14793023Snsouch#define SMBHST			0x0
14893023Snsouch#define SMBHSL			0x1
14993023Snsouch#define SMBHCTRL		0x2
15093023Snsouch#define SMBHCMD			0x3
15193023Snsouch#define SMBHADDR		0x4
15293023Snsouch#define SMBHDATA0		0x5
15393023Snsouch#define SMBHDATA1		0x6
15493023Snsouch#define SMBHBLOCK		0x7
15593023Snsouch
15693023Snsouch#define SMBSST			0x1
15793023Snsouch#define SMBSCTRL		0x8
15893023Snsouch#define SMBSSDWCMD		0x9
15993023Snsouch#define SMBSEVENT		0xa
16093023Snsouch#define SMBSDATA		0xc
16193023Snsouch
16293023Snsouch#define SMBHST_RESERVED		0xef	/* reserved bits */
16393023Snsouch#define SMBHST_FAILED		0x10	/* failed bus transaction */
16493023Snsouch#define SMBHST_COLLID		0x08	/* bus collision */
16593023Snsouch#define SMBHST_ERROR		0x04	/* device error */
16693023Snsouch#define SMBHST_INTR		0x02	/* command completed */
16793023Snsouch#define SMBHST_BUSY		0x01	/* host busy */
16893023Snsouch
16993023Snsouch#define SMBHCTRL_START		0x40	/* start command */
17093023Snsouch#define SMBHCTRL_PROTO		0x1c	/* command protocol mask */
17193023Snsouch#define SMBHCTRL_QUICK		0x00
17293023Snsouch#define SMBHCTRL_SENDRECV	0x04
17393023Snsouch#define SMBHCTRL_BYTE		0x08
17493023Snsouch#define SMBHCTRL_WORD		0x0c
17593023Snsouch#define SMBHCTRL_BLOCK		0x14
17693023Snsouch#define SMBHCTRL_KILL		0x02	/* stop the current transaction */
17793023Snsouch#define SMBHCTRL_ENABLE		0x01	/* enable interrupts */
17893023Snsouch
17993023Snsouch#define SMBSCTRL_ENABLE		0x01	/* enable slave */
18093023Snsouch
18193023Snsouch
18293023Snsouch/*
18393023Snsouch * VIA8233 definitions
18493023Snsouch */
18593023Snsouch
18693023Snsouch#define VIAPM_8233_BASE		0xD0
18793023Snsouch
18893023Snsouchstatic int
18993023Snsouchviapm_586b_probe(device_t dev)
19093023Snsouch{
19193023Snsouch	struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
19293023Snsouch	u_int32_t l;
19393023Snsouch	u_int16_t s;
19493023Snsouch	u_int8_t c;
19593023Snsouch
19693023Snsouch	switch (pci_get_devid(dev)) {
19793023Snsouch	case VIA_586B_PMU_ID:
19893023Snsouch
19993023Snsouch		bzero(viapm, sizeof(struct viapm_softc));
20093023Snsouch
20193023Snsouch		l = pci_read_config(dev, VIAPM_586B_REVID, 1);
20293023Snsouch		switch (l) {
20393023Snsouch		case VIAPM_586B_OEM_REV_E:
20493023Snsouch			viapm->type = VIAPM_TYP_586B_3040E;
20593023Snsouch			viapm->iorid = VIAPM_586B_3040E_BASE;
20693023Snsouch
20793023Snsouch			/* Activate IO block access */
20893023Snsouch			s = pci_read_config(dev, VIAPM_586B_3040E_ACTIV, 2);
20993023Snsouch			pci_write_config(dev, VIAPM_586B_3040E_ACTIV, s | 0x1, 2);
21093023Snsouch			break;
21193023Snsouch
21293023Snsouch		case VIAPM_586B_OEM_REV_F:
21393023Snsouch		case VIAPM_586B_PROD_REV_A:
21493023Snsouch		default:
21593023Snsouch			viapm->type = VIAPM_TYP_586B_3040F;
21693023Snsouch			viapm->iorid = VIAPM_586B_3040F_BASE;
21793023Snsouch
21893023Snsouch			/* Activate IO block access */
21993023Snsouch			c = pci_read_config(dev, VIAPM_586B_3040F_ACTIV, 1);
22093023Snsouch			pci_write_config(dev, VIAPM_586B_3040F_ACTIV, c | 0x80, 1);
22193023Snsouch			break;
22293023Snsouch		}
22393023Snsouch
22493023Snsouch		viapm->base = pci_read_config(dev, viapm->iorid, 4) &
22593023Snsouch				VIAPM_586B_BA_MASK;
22693023Snsouch
22793023Snsouch		/*
22893023Snsouch		 * We have to set the I/O resources by hand because it is
22993023Snsouch		 * described outside the viapmope of the traditional maps
23093023Snsouch		 */
23193023Snsouch		if (bus_set_resource(dev, SYS_RES_IOPORT, viapm->iorid,
23293023Snsouch							viapm->base, 256)) {
23393023Snsouch			device_printf(dev, "could not set bus resource\n");
23493023Snsouch			return ENXIO;
23593023Snsouch		}
23693023Snsouch		device_set_desc(dev, "VIA VT82C586B Power Management Unit");
237142398Simp		return (BUS_PROBE_DEFAULT);
23893023Snsouch
23993023Snsouch	default:
24093023Snsouch		break;
24193023Snsouch	}
24293023Snsouch
24393023Snsouch	return ENXIO;
24493023Snsouch}
24593023Snsouch
24693023Snsouch
24793023Snsouchstatic int
24893023Snsouchviapm_pro_probe(device_t dev)
24993023Snsouch{
25093023Snsouch	struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
25193023Snsouch#ifdef VIAPM_BASE_ADDR
25293023Snsouch	u_int32_t l;
25393023Snsouch#endif
25493023Snsouch	u_int32_t base_cfgreg;
25593023Snsouch	char *desc;
25693023Snsouch
25793023Snsouch	switch (pci_get_devid(dev)) {
25893023Snsouch	case VIA_596A_PMU_ID:
25993023Snsouch		desc = "VIA VT82C596A Power Management Unit";
26093023Snsouch		viapm->type = VIAPM_TYP_596B;
26193023Snsouch		base_cfgreg = VIAPM_PRO_BASE;
26293023Snsouch		goto viapro;
26393023Snsouch
26493023Snsouch	case VIA_596B_PMU_ID:
26593023Snsouch		desc = "VIA VT82C596B Power Management Unit";
26693023Snsouch		viapm->type = VIAPM_TYP_596B;
26793023Snsouch		base_cfgreg = VIAPM_PRO_BASE;
26893023Snsouch		goto viapro;
26993023Snsouch
27093023Snsouch	case VIA_686A_PMU_ID:
27193023Snsouch		desc = "VIA VT82C686A Power Management Unit";
27293023Snsouch		viapm->type = VIAPM_TYP_686A;
27393023Snsouch		base_cfgreg = VIAPM_PRO_BASE;
27493023Snsouch		goto viapro;
27593023Snsouch
27693023Snsouch	case VIA_8233_PMU_ID:
277116671Smdodd	case VIA_8233A_PMU_ID:
27893023Snsouch		desc = "VIA VT8233 Power Management Unit";
27993023Snsouch		viapm->type = VIAPM_TYP_UNKNOWN;
28093023Snsouch		base_cfgreg = VIAPM_8233_BASE;
28193023Snsouch		goto viapro;
28293023Snsouch
283151901Sjhb	case VIA_8235_PMU_ID:
284151901Sjhb		desc = "VIA VT8235 Power Management Unit";
285151901Sjhb		viapm->type = VIAPM_TYP_UNKNOWN;
286151901Sjhb		base_cfgreg = VIAPM_8233_BASE;
287151901Sjhb		goto viapro;
288151901Sjhb
289179933Sgonzo	case VIA_8237_PMU_ID:
290179933Sgonzo		desc = "VIA VT8237 Power Management Unit";
291179933Sgonzo		viapm->type = VIAPM_TYP_UNKNOWN;
292179933Sgonzo		base_cfgreg = VIAPM_8233_BASE;
293179933Sgonzo		goto viapro;
294179933Sgonzo
295171693Skevlo	case VIA_CX700_PMU_ID:
296171693Skevlo		desc = "VIA CX700 Power Management Unit";
297171693Skevlo		viapm->type = VIAPM_TYP_UNKNOWN;
298171693Skevlo		base_cfgreg = VIAPM_8233_BASE;
299171693Skevlo		goto viapro;
300171693Skevlo
30193023Snsouch	viapro:
30293023Snsouch
30393023Snsouch#ifdef VIAPM_BASE_ADDR
30493023Snsouch		/* force VIAPM I/O base address */
30593023Snsouch
30693023Snsouch		/* enable the SMBus controller function */
30793023Snsouch		l = pci_read_config(dev, VIAPM_PRO_SMBCTRL, 1);
30893023Snsouch		pci_write_config(dev, VIAPM_PRO_SMBCTRL, l | 1, 1);
30993023Snsouch
31093023Snsouch		/* write the base address */
31193023Snsouch		pci_write_config(dev, base_cfgreg,
31293023Snsouch				 VIAPM_BASE_ADDR & VIAPM_PRO_BA_MASK, 4);
31393023Snsouch#endif
31493023Snsouch
31593023Snsouch		viapm->base = pci_read_config(dev, base_cfgreg, 4) & VIAPM_PRO_BA_MASK;
31693023Snsouch
31793023Snsouch		/*
31893023Snsouch		 * We have to set the I/O resources by hand because it is
31993023Snsouch		 * described outside the viapmope of the traditional maps
32093023Snsouch		 */
32193023Snsouch		viapm->iorid = base_cfgreg;
32293023Snsouch		if (bus_set_resource(dev, SYS_RES_IOPORT, viapm->iorid,
32393023Snsouch				     viapm->base, 16)) {
32493023Snsouch			device_printf(dev, "could not set bus resource 0x%x\n",
32593023Snsouch					viapm->base);
32693023Snsouch			return ENXIO;
32793023Snsouch		}
32893023Snsouch
329171693Skevlo		if (bootverbose) {
33093023Snsouch			device_printf(dev, "SMBus I/O base at 0x%x\n", viapm->base);
33193023Snsouch		}
33293023Snsouch
33393023Snsouch		device_set_desc(dev, desc);
334142398Simp		return (BUS_PROBE_DEFAULT);
33593023Snsouch
33693023Snsouch	default:
33793023Snsouch		break;
33893023Snsouch	}
33993023Snsouch
34093023Snsouch	return ENXIO;
34193023Snsouch}
34293023Snsouch
34393023Snsouchstatic int
34493023Snsouchviapm_pro_attach(device_t dev)
34593023Snsouch{
34693023Snsouch	struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
34793023Snsouch	u_int32_t l;
34893023Snsouch
349165951Sjhb	mtx_init(&viapm->lock, device_get_nameunit(dev), "viapm", MTX_DEF);
350127135Snjl	if (!(viapm->iores = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
351127135Snjl		&viapm->iorid, RF_ACTIVE))) {
35293023Snsouch		device_printf(dev, "could not allocate bus space\n");
35393023Snsouch		goto error;
35493023Snsouch	}
35593023Snsouch
356153084Sru#ifdef notyet
35793023Snsouch	/* force irq 9 */
35893023Snsouch	l = pci_read_config(dev, VIAPM_PRO_SMBCTRL, 1);
35993023Snsouch	pci_write_config(dev, VIAPM_PRO_SMBCTRL, l | 0x80, 1);
36093023Snsouch
36193023Snsouch	viapm->irqrid = 0;
36293023Snsouch	if (!(viapm->irqres = bus_alloc_resource(dev, SYS_RES_IRQ,
36393023Snsouch				&viapm->irqrid, 9, 9, 1,
36493023Snsouch				RF_SHAREABLE | RF_ACTIVE))) {
36593023Snsouch		device_printf(dev, "could not allocate irq\n");
36693023Snsouch		goto error;
36793023Snsouch	}
36893023Snsouch
369179622Sjhb	if (bus_setup_intr(dev, viapm->irqres, INTR_TYPE_MISC | INTR_MPSAFE,
37093023Snsouch			(driver_intr_t *) viasmb_intr, viapm, &viapm->irqih)) {
37193023Snsouch		device_printf(dev, "could not setup irq\n");
37293023Snsouch		goto error;
37393023Snsouch	}
37493023Snsouch#endif
37593023Snsouch
376171693Skevlo	if (bootverbose) {
37793023Snsouch		l = pci_read_config(dev, VIAPM_PRO_REVID, 1);
37893023Snsouch		device_printf(dev, "SMBus revision code 0x%x\n", l);
37993023Snsouch	}
38093023Snsouch
38193023Snsouch	viapm->smbus = device_add_child(dev, "smbus", -1);
38293023Snsouch
38393023Snsouch	/* probe and attach the smbus */
38493023Snsouch	bus_generic_attach(dev);
38593023Snsouch
38693023Snsouch	/* disable slave function */
38793023Snsouch	VIAPM_OUTB(SMBSCTRL, VIAPM_INB(SMBSCTRL) & ~SMBSCTRL_ENABLE);
38893023Snsouch
38993023Snsouch	/* enable the SMBus controller function */
39093023Snsouch	l = pci_read_config(dev, VIAPM_PRO_SMBCTRL, 1);
39193023Snsouch	pci_write_config(dev, VIAPM_PRO_SMBCTRL, l | 1, 1);
39293023Snsouch
393153084Sru#ifdef notyet
39493023Snsouch	/* enable interrupts */
39593023Snsouch	VIAPM_OUTB(SMBHCTRL, VIAPM_INB(SMBHCTRL) | SMBHCTRL_ENABLE);
39693023Snsouch#endif
39793023Snsouch
398151900Sjhb#ifdef DEV_ISA
399151900Sjhb	/* If this device is a PCI-ISA bridge, then attach an ISA bus. */
400151900Sjhb	if ((pci_get_class(dev) == PCIC_BRIDGE) &&
401151900Sjhb	    (pci_get_subclass(dev) == PCIS_BRIDGE_ISA))
402151900Sjhb		isab_attach(dev);
403151900Sjhb#endif
40493023Snsouch	return 0;
40593023Snsouch
40693023Snsoucherror:
40793023Snsouch	if (viapm->iores)
40893023Snsouch		bus_release_resource(dev, SYS_RES_IOPORT, viapm->iorid, viapm->iores);
409153084Sru#ifdef notyet
41093023Snsouch	if (viapm->irqres)
41193023Snsouch		bus_release_resource(dev, SYS_RES_IRQ, viapm->irqrid, viapm->irqres);
41293023Snsouch#endif
413165951Sjhb	mtx_destroy(&viapm->lock);
41493023Snsouch
41593023Snsouch	return ENXIO;
41693023Snsouch}
41793023Snsouch
41893023Snsouchstatic int
41993023Snsouchviapm_586b_attach(device_t dev)
42093023Snsouch{
42193023Snsouch	struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
422165951Sjhb
423165951Sjhb	mtx_init(&viapm->lock, device_get_nameunit(dev), "viapm", MTX_DEF);
424127135Snjl	if (!(viapm->iores = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
425127135Snjl		&viapm->iorid, RF_ACTIVE | RF_SHAREABLE))) {
42693023Snsouch		device_printf(dev, "could not allocate bus resource\n");
427165951Sjhb		goto error;
42893023Snsouch	}
42993023Snsouch
43093023Snsouch	VIAPM_OUTB(GPIO_DIR, VIAPM_INB(GPIO_DIR) | VIAPM_SCL | VIAPM_SDA);
43193023Snsouch
43293023Snsouch	/* add generic bit-banging code */
43393023Snsouch	if (!(viapm->iicbb = device_add_child(dev, "iicbb", -1)))
43493023Snsouch		goto error;
43593023Snsouch
43693023Snsouch	bus_generic_attach(dev);
43793023Snsouch
43893023Snsouch	return 0;
43993023Snsouch
44093023Snsoucherror:
44193023Snsouch	if (viapm->iores)
44293023Snsouch		bus_release_resource(dev, SYS_RES_IOPORT,
44393023Snsouch					viapm->iorid, viapm->iores);
444165951Sjhb	mtx_destroy(&viapm->lock);
44593023Snsouch	return ENXIO;
44693023Snsouch}
44793023Snsouch
44893023Snsouchstatic int
44993023Snsouchviapm_586b_detach(device_t dev)
45093023Snsouch{
45193023Snsouch	struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
45293023Snsouch
45393023Snsouch	bus_generic_detach(dev);
45493023Snsouch	if (viapm->iicbb) {
45593023Snsouch		device_delete_child(dev, viapm->iicbb);
45693023Snsouch	}
45793023Snsouch
458165951Sjhb	if (viapm->iores)
459165951Sjhb		bus_release_resource(dev, SYS_RES_IOPORT, viapm->iorid,
460165951Sjhb		    viapm->iores);
461165951Sjhb	mtx_destroy(&viapm->lock);
46293023Snsouch
46393023Snsouch	return 0;
46493023Snsouch}
46593023Snsouch
46693023Snsouchstatic int
46793023Snsouchviapm_pro_detach(device_t dev)
46893023Snsouch{
46993023Snsouch	struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
47093023Snsouch
47193023Snsouch	bus_generic_detach(dev);
47293023Snsouch	if (viapm->smbus) {
47393023Snsouch		device_delete_child(dev, viapm->smbus);
47493023Snsouch	}
47593023Snsouch
476165951Sjhb	bus_release_resource(dev, SYS_RES_IOPORT, viapm->iorid, viapm->iores);
47793023Snsouch
478153084Sru#ifdef notyet
479165951Sjhb	bus_release_resource(dev, SYS_RES_IRQ, viapm->irqrid, viapm->irqres);
48093023Snsouch#endif
481165951Sjhb	mtx_destroy(&viapm->lock);
48293023Snsouch
48393023Snsouch	return 0;
48493023Snsouch}
48593023Snsouch
48693023Snsouchstatic int
487189317Simpviabb_callback(device_t dev, int index, caddr_t data)
48893023Snsouch{
48993023Snsouch	return 0;
49093023Snsouch}
49193023Snsouch
49293023Snsouchstatic void
49393023Snsouchviabb_setscl(device_t dev, int ctrl)
49493023Snsouch{
49593023Snsouch	struct viapm_softc *viapm = device_get_softc(dev);
49693023Snsouch	u_char val;
49793023Snsouch
498165951Sjhb	VIAPM_LOCK(viapm);
49993023Snsouch	val = VIAPM_INB(GPIO_VAL);
50093023Snsouch
50193023Snsouch	if (ctrl)
50293023Snsouch		val |= VIAPM_SCL;
50393023Snsouch	else
50493023Snsouch		val &= ~VIAPM_SCL;
50593023Snsouch
50693023Snsouch	VIAPM_OUTB(GPIO_VAL, val);
507165951Sjhb	VIAPM_UNLOCK(viapm);
50893023Snsouch
50993023Snsouch	return;
51093023Snsouch}
51193023Snsouch
51293023Snsouchstatic void
51393023Snsouchviabb_setsda(device_t dev, int data)
51493023Snsouch{
51593023Snsouch	struct viapm_softc *viapm = device_get_softc(dev);
51693023Snsouch	u_char val;
51793023Snsouch
518165951Sjhb	VIAPM_LOCK(viapm);
51993023Snsouch	val = VIAPM_INB(GPIO_VAL);
52093023Snsouch
52193023Snsouch	if (data)
52293023Snsouch		val |= VIAPM_SDA;
52393023Snsouch	else
52493023Snsouch		val &= ~VIAPM_SDA;
52593023Snsouch
52693023Snsouch	VIAPM_OUTB(GPIO_VAL, val);
527165951Sjhb	VIAPM_UNLOCK(viapm);
52893023Snsouch
52993023Snsouch	return;
53093023Snsouch}
53193023Snsouch
53293023Snsouchstatic int
53393023Snsouchviabb_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr)
53493023Snsouch{
53593023Snsouch	/* reset bus */
53693023Snsouch	viabb_setsda(dev, 1);
53793023Snsouch	viabb_setscl(dev, 1);
53893023Snsouch
53993023Snsouch	return (IIC_ENOADDR);
54093023Snsouch}
54193023Snsouch
54293023Snsouchstatic int
54393023Snsouchviabb_getscl(device_t dev)
54493023Snsouch{
54593023Snsouch	struct viapm_softc *viapm = device_get_softc(dev);
546165951Sjhb	u_char val;
54793023Snsouch
548165951Sjhb	VIAPM_LOCK(viapm);
549165951Sjhb	val = VIAPM_INB(EXTSMI_VAL);
550165951Sjhb	VIAPM_UNLOCK(viapm);
551165951Sjhb	return ((val & VIAPM_SCL) != 0);
55293023Snsouch}
55393023Snsouch
55493023Snsouchstatic int
55593023Snsouchviabb_getsda(device_t dev)
55693023Snsouch{
55793023Snsouch	struct viapm_softc *viapm = device_get_softc(dev);
558165951Sjhb	u_char val;
55993023Snsouch
560165951Sjhb	VIAPM_LOCK(viapm);
561165951Sjhb	val = VIAPM_INB(EXTSMI_VAL);
562165951Sjhb	VIAPM_UNLOCK(viapm);
563165951Sjhb	return ((val & VIAPM_SDA) != 0);
56493023Snsouch}
56593023Snsouch
56693023Snsouchstatic int
56793023Snsouchviapm_abort(struct viapm_softc *viapm)
56893023Snsouch{
56993023Snsouch	VIAPM_OUTB(SMBHCTRL, SMBHCTRL_KILL);
57093023Snsouch	DELAY(10);
57193023Snsouch
57293023Snsouch	return (0);
57393023Snsouch}
57493023Snsouch
57593023Snsouchstatic int
57693023Snsouchviapm_clear(struct viapm_softc *viapm)
57793023Snsouch{
57893023Snsouch	VIAPM_OUTB(SMBHST, SMBHST_FAILED | SMBHST_COLLID |
57993023Snsouch		SMBHST_ERROR | SMBHST_INTR);
58093023Snsouch	DELAY(10);
58193023Snsouch
58293023Snsouch	return (0);
58393023Snsouch}
58493023Snsouch
58593023Snsouchstatic int
58693023Snsouchviapm_busy(struct viapm_softc *viapm)
58793023Snsouch{
58893023Snsouch	u_char sts;
58993023Snsouch
59093023Snsouch	sts = VIAPM_INB(SMBHST);
59193023Snsouch
59293023Snsouch	VIAPM_DEBUG(printf("viapm: idle? STS=0x%x\n", sts));
59393023Snsouch
59493023Snsouch	return (sts & SMBHST_BUSY);
59593023Snsouch}
59693023Snsouch
59793023Snsouch/*
59893023Snsouch * Poll the SMBus controller
59993023Snsouch */
60093023Snsouchstatic int
60193023Snsouchviapm_wait(struct viapm_softc *viapm)
60293023Snsouch{
60393023Snsouch	int count = 10000;
60493023Snsouch	u_char sts = 0;
60593023Snsouch	int error;
60693023Snsouch
607165951Sjhb	VIAPM_LOCK_ASSERT(viapm);
608165951Sjhb
60993023Snsouch	/* wait for command to complete and SMBus controller is idle */
61093023Snsouch	while(count--) {
61193023Snsouch		DELAY(10);
61293023Snsouch		sts = VIAPM_INB(SMBHST);
61393023Snsouch
61493023Snsouch		/* check if the controller is processing a command */
61593023Snsouch		if (!(sts & SMBHST_BUSY) && (sts & SMBHST_INTR))
61693023Snsouch			break;
61793023Snsouch	}
61893023Snsouch
61993023Snsouch	VIAPM_DEBUG(printf("viapm: SMBHST=0x%x\n", sts));
62093023Snsouch
62193023Snsouch	error = SMB_ENOERR;
62293023Snsouch
62393023Snsouch	if (!count)
62493023Snsouch		error |= SMB_ETIMEOUT;
62593023Snsouch
62693023Snsouch	if (sts & SMBHST_FAILED)
62793023Snsouch		error |= SMB_EABORT;
62893023Snsouch
62993023Snsouch	if (sts & SMBHST_COLLID)
63093023Snsouch		error |= SMB_ENOACK;
63193023Snsouch
63293023Snsouch	if (sts & SMBHST_ERROR)
63393023Snsouch		error |= SMB_EBUSERR;
63493023Snsouch
63593023Snsouch	if (error != SMB_ENOERR)
63693023Snsouch		viapm_abort(viapm);
63793023Snsouch
63893023Snsouch	viapm_clear(viapm);
63993023Snsouch
64093023Snsouch	return (error);
64193023Snsouch}
64293023Snsouch
64393023Snsouchstatic int
644189317Simpviasmb_callback(device_t dev, int index, void *data)
64593023Snsouch{
64693023Snsouch	int error = 0;
64793023Snsouch
64893023Snsouch	switch (index) {
64993023Snsouch	case SMB_REQUEST_BUS:
65093023Snsouch	case SMB_RELEASE_BUS:
65193023Snsouch		/* ok, bus allocation accepted */
65293023Snsouch		break;
65393023Snsouch	default:
65493023Snsouch		error = EINVAL;
65593023Snsouch	}
65693023Snsouch
65793023Snsouch	return (error);
65893023Snsouch}
65993023Snsouch
66093023Snsouchstatic int
66193023Snsouchviasmb_quick(device_t dev, u_char slave, int how)
66293023Snsouch{
66393023Snsouch	struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
66493023Snsouch	int error;
66593023Snsouch
666165951Sjhb	VIAPM_LOCK(viapm);
66793023Snsouch	viapm_clear(viapm);
668165951Sjhb	if (viapm_busy(viapm)) {
669165951Sjhb		VIAPM_UNLOCK(viapm);
670162234Sjhb		return (SMB_EBUSY);
671165951Sjhb	}
67293023Snsouch
67393023Snsouch	switch (how) {
67493023Snsouch	case SMB_QWRITE:
67593023Snsouch		VIAPM_DEBUG(printf("viapm: QWRITE to 0x%x", slave));
67693023Snsouch		VIAPM_OUTB(SMBHADDR, slave & ~LSB);
67793023Snsouch		break;
67893023Snsouch	case SMB_QREAD:
67993023Snsouch		VIAPM_DEBUG(printf("viapm: QREAD to 0x%x", slave));
68093023Snsouch		VIAPM_OUTB(SMBHADDR, slave | LSB);
68193023Snsouch		break;
68293023Snsouch	default:
683135577Sstefanf		panic("%s: unknown QUICK command (%x)!", __func__, how);
68493023Snsouch	}
68593023Snsouch
68693023Snsouch	VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_QUICK);
68793023Snsouch
68893023Snsouch	error = viapm_wait(viapm);
689165951Sjhb	VIAPM_UNLOCK(viapm);
69093023Snsouch
69193023Snsouch	return (error);
69293023Snsouch}
69393023Snsouch
69493023Snsouchstatic int
69593023Snsouchviasmb_sendb(device_t dev, u_char slave, char byte)
69693023Snsouch{
69793023Snsouch	struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
69893023Snsouch	int error;
69993023Snsouch
700165951Sjhb	VIAPM_LOCK(viapm);
70193023Snsouch	viapm_clear(viapm);
702165951Sjhb	if (viapm_busy(viapm)) {
703165951Sjhb		VIAPM_UNLOCK(viapm);
704162234Sjhb		return (SMB_EBUSY);
705165951Sjhb	}
70693023Snsouch
70793023Snsouch	VIAPM_OUTB(SMBHADDR, slave & ~ LSB);
70893023Snsouch	VIAPM_OUTB(SMBHCMD, byte);
70993023Snsouch
71093023Snsouch	VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_SENDRECV);
71193023Snsouch
71293023Snsouch	error = viapm_wait(viapm);
71393023Snsouch
71493023Snsouch	VIAPM_DEBUG(printf("viapm: SENDB to 0x%x, byte=0x%x, error=0x%x\n", slave, byte, error));
715165951Sjhb	VIAPM_UNLOCK(viapm);
71693023Snsouch
71793023Snsouch	return (error);
71893023Snsouch}
71993023Snsouch
72093023Snsouchstatic int
72193023Snsouchviasmb_recvb(device_t dev, u_char slave, char *byte)
72293023Snsouch{
72393023Snsouch	struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
72493023Snsouch	int error;
72593023Snsouch
726165951Sjhb	VIAPM_LOCK(viapm);
72793023Snsouch	viapm_clear(viapm);
728165951Sjhb	if (viapm_busy(viapm)) {
729165951Sjhb		VIAPM_UNLOCK(viapm);
730162234Sjhb		return (SMB_EBUSY);
731165951Sjhb	}
73293023Snsouch
73393023Snsouch	VIAPM_OUTB(SMBHADDR, slave | LSB);
73493023Snsouch
73593023Snsouch	VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_SENDRECV);
73693023Snsouch
73793023Snsouch	if ((error = viapm_wait(viapm)) == SMB_ENOERR)
73893023Snsouch		*byte = VIAPM_INB(SMBHDATA0);
73993023Snsouch
74093023Snsouch	VIAPM_DEBUG(printf("viapm: RECVB from 0x%x, byte=0x%x, error=0x%x\n", slave, *byte, error));
741165951Sjhb	VIAPM_UNLOCK(viapm);
74293023Snsouch
74393023Snsouch	return (error);
74493023Snsouch}
74593023Snsouch
74693023Snsouchstatic int
74793023Snsouchviasmb_writeb(device_t dev, u_char slave, char cmd, char byte)
74893023Snsouch{
74993023Snsouch	struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
75093023Snsouch	int error;
75193023Snsouch
752165951Sjhb	VIAPM_LOCK(viapm);
75393023Snsouch	viapm_clear(viapm);
754165951Sjhb	if (viapm_busy(viapm)) {
755165951Sjhb		VIAPM_UNLOCK(viapm);
756162234Sjhb		return (SMB_EBUSY);
757165951Sjhb	}
75893023Snsouch
75993023Snsouch	VIAPM_OUTB(SMBHADDR, slave & ~ LSB);
76093023Snsouch	VIAPM_OUTB(SMBHCMD, cmd);
76193023Snsouch	VIAPM_OUTB(SMBHDATA0, byte);
76293023Snsouch
76393023Snsouch	VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_BYTE);
76493023Snsouch
76593023Snsouch	error = viapm_wait(viapm);
76693023Snsouch
76793023Snsouch	VIAPM_DEBUG(printf("viapm: WRITEB to 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, byte, error));
768165951Sjhb	VIAPM_UNLOCK(viapm);
76993023Snsouch
77093023Snsouch	return (error);
77193023Snsouch}
77293023Snsouch
77393023Snsouchstatic int
77493023Snsouchviasmb_readb(device_t dev, u_char slave, char cmd, char *byte)
77593023Snsouch{
77693023Snsouch	struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
77793023Snsouch	int error;
77893023Snsouch
779165951Sjhb	VIAPM_LOCK(viapm);
78093023Snsouch	viapm_clear(viapm);
781165951Sjhb	if (viapm_busy(viapm)) {
782165951Sjhb		VIAPM_UNLOCK(viapm);
783162234Sjhb		return (SMB_EBUSY);
784165951Sjhb	}
78593023Snsouch
78693023Snsouch	VIAPM_OUTB(SMBHADDR, slave | LSB);
78793023Snsouch	VIAPM_OUTB(SMBHCMD, cmd);
78893023Snsouch
78993023Snsouch	VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_BYTE);
79093023Snsouch
79193023Snsouch	if ((error = viapm_wait(viapm)) == SMB_ENOERR)
79293023Snsouch		*byte = VIAPM_INB(SMBHDATA0);
79393023Snsouch
79493023Snsouch	VIAPM_DEBUG(printf("viapm: READB from 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, *byte, error));
795165951Sjhb	VIAPM_UNLOCK(viapm);
79693023Snsouch
79793023Snsouch	return (error);
79893023Snsouch}
79993023Snsouch
80093023Snsouchstatic int
80193023Snsouchviasmb_writew(device_t dev, u_char slave, char cmd, short word)
80293023Snsouch{
80393023Snsouch	struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
80493023Snsouch	int error;
80593023Snsouch
806165951Sjhb	VIAPM_LOCK(viapm);
80793023Snsouch	viapm_clear(viapm);
808165951Sjhb	if (viapm_busy(viapm)) {
809165951Sjhb		VIAPM_UNLOCK(viapm);
810162234Sjhb		return (SMB_EBUSY);
811165951Sjhb	}
81293023Snsouch
81393023Snsouch	VIAPM_OUTB(SMBHADDR, slave & ~ LSB);
81493023Snsouch	VIAPM_OUTB(SMBHCMD, cmd);
81593023Snsouch	VIAPM_OUTB(SMBHDATA0, word & 0x00ff);
81693023Snsouch	VIAPM_OUTB(SMBHDATA1, (word & 0xff00) >> 8);
81793023Snsouch
81893023Snsouch	VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_WORD);
81993023Snsouch
82093023Snsouch	error = viapm_wait(viapm);
82193023Snsouch
82293023Snsouch	VIAPM_DEBUG(printf("viapm: WRITEW to 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, word, error));
823165951Sjhb	VIAPM_UNLOCK(viapm);
82493023Snsouch
82593023Snsouch	return (error);
82693023Snsouch}
82793023Snsouch
82893023Snsouchstatic int
82993023Snsouchviasmb_readw(device_t dev, u_char slave, char cmd, short *word)
83093023Snsouch{
83193023Snsouch	struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
83293023Snsouch	int error;
83393023Snsouch	u_char high, low;
83493023Snsouch
835165951Sjhb	VIAPM_LOCK(viapm);
83693023Snsouch	viapm_clear(viapm);
837165951Sjhb	if (viapm_busy(viapm)) {
838165951Sjhb		VIAPM_UNLOCK(viapm);
839162234Sjhb		return (SMB_EBUSY);
840165951Sjhb	}
84193023Snsouch
84293023Snsouch	VIAPM_OUTB(SMBHADDR, slave | LSB);
84393023Snsouch	VIAPM_OUTB(SMBHCMD, cmd);
84493023Snsouch
84593023Snsouch	VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_WORD);
84693023Snsouch
84793023Snsouch	if ((error = viapm_wait(viapm)) == SMB_ENOERR) {
84893023Snsouch		low = VIAPM_INB(SMBHDATA0);
84993023Snsouch		high = VIAPM_INB(SMBHDATA1);
85093023Snsouch
85193023Snsouch		*word = ((high & 0xff) << 8) | (low & 0xff);
85293023Snsouch	}
85393023Snsouch
85493023Snsouch	VIAPM_DEBUG(printf("viapm: READW from 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, *word, error));
855165951Sjhb	VIAPM_UNLOCK(viapm);
85693023Snsouch
85793023Snsouch	return (error);
85893023Snsouch}
85993023Snsouch
86093023Snsouchstatic int
86193023Snsouchviasmb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf)
86293023Snsouch{
86393023Snsouch	struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
864162234Sjhb	u_char i;
865162234Sjhb	int error;
86693023Snsouch
867162234Sjhb	if (count < 1 || count > 32)
868162234Sjhb		return (SMB_EINVAL);
869162234Sjhb
870165951Sjhb	VIAPM_LOCK(viapm);
87193023Snsouch	viapm_clear(viapm);
872165951Sjhb	if (viapm_busy(viapm)) {
873165951Sjhb		VIAPM_UNLOCK(viapm);
874162234Sjhb		return (SMB_EBUSY);
875165951Sjhb	}
87693023Snsouch
877162234Sjhb	VIAPM_OUTB(SMBHADDR, slave & ~LSB);
878162234Sjhb	VIAPM_OUTB(SMBHCMD, cmd);
879162234Sjhb	VIAPM_OUTB(SMBHDATA0, count);
880162234Sjhb	i = VIAPM_INB(SMBHCTRL);
88193023Snsouch
882162234Sjhb	/* fill the 32-byte internal buffer */
883162234Sjhb	for (i = 0; i < count; i++) {
884162234Sjhb		VIAPM_OUTB(SMBHBLOCK, buf[i]);
885162234Sjhb		DELAY(2);
886162234Sjhb	}
887162234Sjhb	VIAPM_OUTB(SMBHCMD, cmd);
888162234Sjhb	VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_BLOCK);
88993023Snsouch
890162234Sjhb	error = viapm_wait(viapm);
89193023Snsouch
89293023Snsouch	VIAPM_DEBUG(printf("viapm: WRITEBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, count, cmd, error));
893165951Sjhb	VIAPM_UNLOCK(viapm);
89493023Snsouch
89593023Snsouch	return (error);
89693023Snsouch
89793023Snsouch}
89893023Snsouch
89993023Snsouchstatic int
900162234Sjhbviasmb_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf)
90193023Snsouch{
90293023Snsouch	struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
903162234Sjhb	u_char data, len, i;
904162234Sjhb	int error;
90593023Snsouch
906162234Sjhb	if (*count < 1 || *count > 32)
907162234Sjhb		return (SMB_EINVAL);
908162234Sjhb
909165951Sjhb	VIAPM_LOCK(viapm);
91093023Snsouch	viapm_clear(viapm);
911165951Sjhb	if (viapm_busy(viapm)) {
912165951Sjhb		VIAPM_UNLOCK(viapm);
913162234Sjhb		return (SMB_EBUSY);
914165951Sjhb	}
91593023Snsouch
916162234Sjhb	VIAPM_OUTB(SMBHADDR, slave | LSB);
917162234Sjhb	VIAPM_OUTB(SMBHCMD, cmd);
918162234Sjhb	VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_BLOCK);
91993023Snsouch
920162234Sjhb	if ((error = viapm_wait(viapm)) != SMB_ENOERR)
921162234Sjhb		goto error;
92293023Snsouch
923162234Sjhb	len = VIAPM_INB(SMBHDATA0);
924162234Sjhb	i = VIAPM_INB(SMBHCTRL); 		/* reset counter */
92593023Snsouch
926162234Sjhb	/* read the 32-byte internal buffer */
927162234Sjhb	for (i = 0; i < len; i++) {
928162234Sjhb		data = VIAPM_INB(SMBHBLOCK);
929162234Sjhb		if (i < *count)
930162234Sjhb			buf[i] = data;
931162234Sjhb		DELAY(2);
932162234Sjhb	}
933162234Sjhb	*count = len;
93493023Snsouch
93593023Snsoucherror:
936162234Sjhb	VIAPM_DEBUG(printf("viapm: READBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, *count, cmd, error));
937165951Sjhb	VIAPM_UNLOCK(viapm);
93893023Snsouch
93993023Snsouch	return (error);
94093023Snsouch}
94193023Snsouch
94293023Snsouchstatic device_method_t viapm_methods[] = {
94393023Snsouch	/* device interface */
94493023Snsouch	DEVMETHOD(device_probe,		viapm_586b_probe),
94593023Snsouch	DEVMETHOD(device_attach,	viapm_586b_attach),
94693023Snsouch	DEVMETHOD(device_detach,	viapm_586b_detach),
94793023Snsouch
94893023Snsouch	/* iicbb interface */
94993023Snsouch	DEVMETHOD(iicbb_callback,	viabb_callback),
95093023Snsouch	DEVMETHOD(iicbb_setscl,		viabb_setscl),
95193023Snsouch	DEVMETHOD(iicbb_setsda,		viabb_setsda),
95293023Snsouch	DEVMETHOD(iicbb_getscl,		viabb_getscl),
95393023Snsouch	DEVMETHOD(iicbb_getsda,		viabb_getsda),
95493023Snsouch	DEVMETHOD(iicbb_reset,		viabb_reset),
95593023Snsouch
956151900Sjhb	/* Bus interface */
957151900Sjhb	DEVMETHOD(bus_alloc_resource,	bus_generic_alloc_resource),
958151900Sjhb	DEVMETHOD(bus_release_resource,	bus_generic_release_resource),
959151900Sjhb	DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
960151900Sjhb	DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
961151900Sjhb	DEVMETHOD(bus_setup_intr,	bus_generic_setup_intr),
962151900Sjhb	DEVMETHOD(bus_teardown_intr,	bus_generic_teardown_intr),
963151900Sjhb
964227843Smarius	DEVMETHOD_END
96593023Snsouch};
96693023Snsouch
96793023Snsouchstatic driver_t viapm_driver = {
96893023Snsouch	"viapm",
96993023Snsouch	viapm_methods,
97093023Snsouch	sizeof(struct viapm_softc),
97193023Snsouch};
97293023Snsouch
97393023Snsouchstatic device_method_t viapropm_methods[] = {
97493023Snsouch	/* device interface */
97593023Snsouch	DEVMETHOD(device_probe,		viapm_pro_probe),
97693023Snsouch	DEVMETHOD(device_attach,	viapm_pro_attach),
97793023Snsouch	DEVMETHOD(device_detach,	viapm_pro_detach),
97893023Snsouch
97993023Snsouch	/* smbus interface */
98093023Snsouch	DEVMETHOD(smbus_callback,	viasmb_callback),
98193023Snsouch	DEVMETHOD(smbus_quick,		viasmb_quick),
98293023Snsouch	DEVMETHOD(smbus_sendb,		viasmb_sendb),
98393023Snsouch	DEVMETHOD(smbus_recvb,		viasmb_recvb),
98493023Snsouch	DEVMETHOD(smbus_writeb,		viasmb_writeb),
98593023Snsouch	DEVMETHOD(smbus_readb,		viasmb_readb),
98693023Snsouch	DEVMETHOD(smbus_writew,		viasmb_writew),
98793023Snsouch	DEVMETHOD(smbus_readw,		viasmb_readw),
98893023Snsouch	DEVMETHOD(smbus_bwrite,		viasmb_bwrite),
98993023Snsouch	DEVMETHOD(smbus_bread,		viasmb_bread),
99093023Snsouch
991151900Sjhb	/* Bus interface */
992151900Sjhb	DEVMETHOD(bus_alloc_resource,	bus_generic_alloc_resource),
993151900Sjhb	DEVMETHOD(bus_release_resource,	bus_generic_release_resource),
994151900Sjhb	DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
995151900Sjhb	DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
996151900Sjhb	DEVMETHOD(bus_setup_intr,	bus_generic_setup_intr),
997151900Sjhb	DEVMETHOD(bus_teardown_intr,	bus_generic_teardown_intr),
998151900Sjhb
999227843Smarius	DEVMETHOD_END
100093023Snsouch};
100193023Snsouch
100293023Snsouchstatic driver_t viapropm_driver = {
100393023Snsouch	"viapropm",
100493023Snsouch	viapropm_methods,
100593023Snsouch	sizeof(struct viapm_softc),
100693023Snsouch};
100793023Snsouch
100893023SnsouchDRIVER_MODULE(viapm, pci, viapm_driver, viapm_devclass, 0, 0);
100993023SnsouchDRIVER_MODULE(viapropm, pci, viapropm_driver, viapropm_devclass, 0, 0);
1010181303SjhbDRIVER_MODULE(iicbb, viapm, iicbb_driver, iicbb_devclass, 0, 0);
1011162234SjhbDRIVER_MODULE(smbus, viapropm, smbus_driver, smbus_devclass, 0, 0);
101293023Snsouch
1013113506SmdoddMODULE_DEPEND(viapm, pci, 1, 1, 1);
1014151900SjhbMODULE_DEPEND(viapropm, pci, 1, 1, 1);
101593023SnsouchMODULE_DEPEND(viapm, iicbb, IICBB_MINVER, IICBB_PREFVER, IICBB_MAXVER);
101693023SnsouchMODULE_DEPEND(viapropm, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER);
101793023SnsouchMODULE_VERSION(viapm, 1);
1018151900Sjhb
1019151900Sjhb#ifdef DEV_ISA
1020151900SjhbDRIVER_MODULE(isa, viapm, isa_driver, isa_devclass, 0, 0);
1021151900SjhbDRIVER_MODULE(isa, viapropm, isa_driver, isa_devclass, 0, 0);
1022151900SjhbMODULE_DEPEND(viapm, isa, 1, 1, 1);
1023151900SjhbMODULE_DEPEND(viapropm, isa, 1, 1, 1);
1024151900Sjhb#endif
1025