summaryrefslogtreecommitdiffstats
path: root/sys/pci
diff options
context:
space:
mode:
authornsouch <nsouch@FreeBSD.org>2002-03-23 15:49:15 +0000
committernsouch <nsouch@FreeBSD.org>2002-03-23 15:49:15 +0000
commit82395b7295123f4d9a786ebd89495ef101103a61 (patch)
treef78e24d69b8d02162ae886a610fb85cac8989741 /sys/pci
parent0dcefe7b55beecbfaeba7c0b20e4b1277b781733 (diff)
downloadFreeBSD-src-82395b7295123f4d9a786ebd89495ef101103a61.zip
FreeBSD-src-82395b7295123f4d9a786ebd89495ef101103a61.tar.gz
Major rework of the iicbus/smbus framework:
- VIA chipset SMBus controllers added - alpm driver updated - Support for dynamic modules added - bktr FreeBSD smbus updated but not tested - cleanup
Diffstat (limited to 'sys/pci')
-rw-r--r--sys/pci/alpm.c329
-rw-r--r--sys/pci/intpm.c4
-rw-r--r--sys/pci/viapm.c924
3 files changed, 1070 insertions, 187 deletions
diff --git a/sys/pci/alpm.c b/sys/pci/alpm.c
index a99f5f2..ae12197f 100644
--- a/sys/pci/alpm.c
+++ b/sys/pci/alpm.c
@@ -37,7 +37,6 @@
#include <sys/bus.h>
#include <sys/uio.h>
-
#include <machine/bus_pio.h>
#include <machine/bus_memio.h>
#include <machine/bus.h>
@@ -122,107 +121,62 @@ static int alpm_debug = 0;
#define SMBCLOCK_111K 0xa0
#define SMBCLOCK_55K 0xc0
-struct alpm_data {
+struct alpm_softc {
int base;
+ struct resource *res;
bus_space_tag_t smbst;
bus_space_handle_t smbsh;
-};
-
-struct alsmb_softc {
- int base;
device_t smbus;
- struct alpm_data *alpm;
};
-#define ALPM_SMBINB(alsmb,register) \
- (bus_space_read_1(alsmb->alpm->smbst, alsmb->alpm->smbsh, register))
-#define ALPM_SMBOUTB(alsmb,register,value) \
- (bus_space_write_1(alsmb->alpm->smbst, alsmb->alpm->smbsh, register, value))
-
-static int alsmb_probe(device_t);
-static int alsmb_attach(device_t);
-static int alsmb_smb_callback(device_t, int, caddr_t *);
-static int alsmb_smb_quick(device_t dev, u_char slave, int how);
-static int alsmb_smb_sendb(device_t dev, u_char slave, char byte);
-static int alsmb_smb_recvb(device_t dev, u_char slave, char *byte);
-static int alsmb_smb_writeb(device_t dev, u_char slave, char cmd, char byte);
-static int alsmb_smb_readb(device_t dev, u_char slave, char cmd, char *byte);
-static int alsmb_smb_writew(device_t dev, u_char slave, char cmd, short word);
-static int alsmb_smb_readw(device_t dev, u_char slave, char cmd, short *word);
-static int alsmb_smb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf);
-static int alsmb_smb_bread(device_t dev, u_char slave, char cmd, u_char count, char *byte);
-
-static devclass_t alsmb_devclass;
-
-static device_method_t alsmb_methods[] = {
- /* device interface */
- DEVMETHOD(device_probe, alsmb_probe),
- DEVMETHOD(device_attach, alsmb_attach),
-
- /* bus interface */
- DEVMETHOD(bus_print_child, bus_generic_print_child),
-
- /* smbus interface */
- DEVMETHOD(smbus_callback, alsmb_smb_callback),
- DEVMETHOD(smbus_quick, alsmb_smb_quick),
- DEVMETHOD(smbus_sendb, alsmb_smb_sendb),
- DEVMETHOD(smbus_recvb, alsmb_smb_recvb),
- DEVMETHOD(smbus_writeb, alsmb_smb_writeb),
- DEVMETHOD(smbus_readb, alsmb_smb_readb),
- DEVMETHOD(smbus_writew, alsmb_smb_writew),
- DEVMETHOD(smbus_readw, alsmb_smb_readw),
- DEVMETHOD(smbus_bwrite, alsmb_smb_bwrite),
- DEVMETHOD(smbus_bread, alsmb_smb_bread),
-
- { 0, 0 }
-};
+#define ALPM_SMBINB(alpm,register) \
+ (bus_space_read_1(alpm->smbst, alpm->smbsh, register))
+#define ALPM_SMBOUTB(alpm,register,value) \
+ (bus_space_write_1(alpm->smbst, alpm->smbsh, register, value))
-static driver_t alsmb_driver = {
- "alsmb",
- alsmb_methods,
- sizeof(struct alsmb_softc),
-};
+static int
+alpm_probe(device_t dev)
+{
+#ifdef ALPM_SMBIO_BASE_ADDR
+ u_int32_t l;
+#endif
-static int alpm_pci_probe(device_t dev);
-static int alpm_pci_attach(device_t dev);
+ if (pci_get_devid(dev) == ACER_M1543_PMU_ID) {
+ device_set_desc(dev, "AcerLabs M15x3 Power Management Unit");
-static devclass_t alpm_devclass;
+#ifdef ALPM_SMBIO_BASE_ADDR
+ if (bootverbose || alpm_debug)
+ device_printf(dev, "forcing base I/O at 0x%x\n",
+ ALPM_SMBIO_BASE_ADDR);
-static device_method_t alpm_pci_methods[] = {
- /* device interface */
- DEVMETHOD(device_probe, alpm_pci_probe),
- DEVMETHOD(device_attach, alpm_pci_attach),
-
- { 0, 0 }
-};
+ /* disable I/O */
+ l = pci_read_config(dev, COM, 2);
+ pci_write_config(dev, COM, l & ~COM_ENABLE_IO, 2);
-static driver_t alpm_pci_driver = {
- "alpm",
- alpm_pci_methods,
- sizeof(struct alpm_data)
-};
+ /* set the I/O base address */
+ pci_write_config(dev, SMBBA, ALPM_SMBIO_BASE_ADDR | 0x1, 4);
+ /* enable I/O */
+ pci_write_config(dev, COM, l | COM_ENABLE_IO, 2);
-static int
-alpm_pci_probe(device_t dev)
-{
- if (pci_get_devid(dev) == ACER_M1543_PMU_ID) {
- device_set_desc(dev,
- "AcerLabs M15x3 Power Management Unit");
- return 0;
- } else {
- return ENXIO;
+ if (bus_set_resource(dev, SYS_RES_IOPORT, SMBBA,
+ ALPM_SMBIO_BASE_ADDR, 256)) {
+ device_printf(dev, "could not set bus resource\n");
+ return (ENXIO);
+ }
+#endif
+ return (0);
}
+
+ return (ENXIO);
}
static int
-alpm_pci_attach(device_t dev)
+alpm_attach(device_t dev)
{
int rid, unit;
u_int32_t l;
- struct alpm_data *alpm;
- struct resource *res;
- device_t smbinterface;
+ struct alpm_softc *alpm;
alpm = device_get_softc(dev);
unit = device_get_unit(dev);
@@ -239,9 +193,9 @@ alpm_pci_attach(device_t dev)
pci_write_config(dev, SMBHCBC, l, 1);
*/
- if (bootverbose) {
+ if (bootverbose || alpm_debug) {
l = pci_read_config(dev, SMBHSI, 1);
- printf("alsmb%d: %s/%s", unit,
+ device_printf(dev, "%s/%s",
(l & SMBHSI_HOST) ? "host":"nohost",
(l & SMBHSI_SLAVE) ? "slave":"noslave");
@@ -265,76 +219,49 @@ alpm_pci_attach(device_t dev)
case SMBCLOCK_55K:
printf(" 55K");
break;
+ default:
+ printf("unkown");
+ break;
}
+ printf("\n");
}
-#ifdef ALPM_SMBIO_BASE_ADDR
- /* XX will this even work anymore? */
- /* disable I/O */
- l = pci_read_config(dev, COM, 2);
- pci_write_config(dev, COM, l & ~COM_ENABLE_IO, 2);
-
- /* set the I/O base address */
- pci_write_config(dev, SMBBA, ALPM_SMBIO_BASE_ADDR | 0x1, 4);
-
- /* enable I/O */
- pci_write_config(dev, COM, l | COM_ENABLE_IO, 2);
-
-#endif
rid = SMBBA;
- res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
- 0,~0,1,RF_ACTIVE);
- if (res == NULL) {
+ alpm->res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
+ 0, ~0, 1, RF_ACTIVE);
+
+ if (alpm->res == NULL) {
device_printf(dev,"Could not allocate Bus space\n");
- return ENXIO;
+ return (ENXIO);
}
- alpm->smbst = rman_get_bustag(res);
- alpm->smbsh = rman_get_bushandle(res);
+ alpm->smbst = rman_get_bustag(alpm->res);
+ alpm->smbsh = rman_get_bushandle(alpm->res);
- if (bootverbose)
- printf(" at 0x%x\n", alpm->smbsh);
-
- smbinterface = device_add_child(dev, "alsmb", unit);
- if (!smbinterface)
- device_printf(dev, "could not add SMBus device\n");
- else
- device_probe_and_attach(smbinterface);
- return 0;
-}
-
-/*
- * Not a real probe, we know the device exists since the device has
- * been added after the successfull pci probe.
- */
-static int
-alsmb_probe(device_t dev)
-{
- struct alsmb_softc *sc = (struct alsmb_softc *)device_get_softc(dev);
-
- /* allocate a new smbus device */
- sc->smbus = smbus_alloc_bus(dev);
- if (!sc->smbus)
- return (EINVAL);
- device_set_desc(dev, "Aladdin IV/V/Pro2 SMBus controller");
+ /* attach the smbus */
+ alpm->smbus = device_add_child(dev, "smbus", -1);
+ bus_generic_attach(dev);
return (0);
}
static int
-alsmb_attach(device_t dev)
+alpm_detach(device_t dev)
{
- struct alsmb_softc *sc = (struct alsmb_softc *)device_get_softc(dev);
+ struct alpm_softc *alpm = device_get_softc(dev);
- sc->alpm = device_get_softc(device_get_parent(dev));
+ if (alpm->smbus) {
+ device_delete_child(dev, alpm->smbus);
+ alpm->smbus = NULL;
+ }
- /* probe and attach the smbus */
- device_probe_and_attach(sc->smbus);
+ if (alpm->res)
+ bus_release_resource(dev, SYS_RES_IOPORT, SMBBA, alpm->res);
return (0);
}
static int
-alsmb_smb_callback(device_t dev, int index, caddr_t *data)
+alpm_callback(device_t dev, int index, caddr_t *data)
{
int error = 0;
@@ -351,7 +278,7 @@ alsmb_smb_callback(device_t dev, int index, caddr_t *data)
}
static int
-alsmb_clear(struct alsmb_softc *sc)
+alpm_clear(struct alpm_softc *sc)
{
ALPM_SMBOUTB(sc, SMBSTS, 0xff);
DELAY(10);
@@ -361,7 +288,7 @@ alsmb_clear(struct alsmb_softc *sc)
#if 0
static int
-alsmb_abort(struct alsmb_softc *sc)
+alpm_abort(struct alpm_softc *sc)
{
ALPM_SMBOUTB(sc, SMBCMD, T_OUT_CMD | ABORT_HOST);
@@ -370,7 +297,7 @@ alsmb_abort(struct alsmb_softc *sc)
#endif
static int
-alsmb_idle(struct alsmb_softc *sc)
+alpm_idle(struct alpm_softc *sc)
{
u_char sts;
@@ -385,7 +312,7 @@ alsmb_idle(struct alsmb_softc *sc)
* Poll the SMBus controller
*/
static int
-alsmb_wait(struct alsmb_softc *sc)
+alpm_wait(struct alpm_softc *sc)
{
int count = 10000;
u_char sts = 0;
@@ -416,19 +343,19 @@ alsmb_wait(struct alsmb_softc *sc)
error |= SMB_EBUSERR;
if (error != SMB_ENOERR)
- alsmb_clear(sc);
+ alpm_clear(sc);
return (error);
}
static int
-alsmb_smb_quick(device_t dev, u_char slave, int how)
+alpm_quick(device_t dev, u_char slave, int how)
{
- struct alsmb_softc *sc = (struct alsmb_softc *)device_get_softc(dev);
+ struct alpm_softc *sc = (struct alpm_softc *)device_get_softc(dev);
int error;
- alsmb_clear(sc);
- if (!alsmb_idle(sc))
+ alpm_clear(sc);
+ if (!alpm_idle(sc))
return (EBUSY);
switch (how) {
@@ -447,7 +374,7 @@ alsmb_smb_quick(device_t dev, u_char slave, int how)
ALPM_SMBOUTB(sc, SMBCMD, SMBQUICK);
ALPM_SMBOUTB(sc, SMBSTART, 0xff);
- error = alsmb_wait(sc);
+ error = alpm_wait(sc);
ALPM_DEBUG(printf(", error=0x%x\n", error));
@@ -455,13 +382,13 @@ alsmb_smb_quick(device_t dev, u_char slave, int how)
}
static int
-alsmb_smb_sendb(device_t dev, u_char slave, char byte)
+alpm_sendb(device_t dev, u_char slave, char byte)
{
- struct alsmb_softc *sc = (struct alsmb_softc *)device_get_softc(dev);
+ struct alpm_softc *sc = (struct alpm_softc *)device_get_softc(dev);
int error;
- alsmb_clear(sc);
- if (!alsmb_idle(sc))
+ alpm_clear(sc);
+ if (!alpm_idle(sc))
return (SMB_EBUSY);
ALPM_SMBOUTB(sc, SMBHADDR, slave & ~LSB);
@@ -469,7 +396,7 @@ alsmb_smb_sendb(device_t dev, u_char slave, char byte)
ALPM_SMBOUTB(sc, SMBHDATA, byte);
ALPM_SMBOUTB(sc, SMBSTART, 0xff);
- error = alsmb_wait(sc);
+ error = alpm_wait(sc);
ALPM_DEBUG(printf("alpm: SENDB to 0x%x, byte=0x%x, error=0x%x\n", slave, byte, error));
@@ -477,20 +404,20 @@ alsmb_smb_sendb(device_t dev, u_char slave, char byte)
}
static int
-alsmb_smb_recvb(device_t dev, u_char slave, char *byte)
+alpm_recvb(device_t dev, u_char slave, char *byte)
{
- struct alsmb_softc *sc = (struct alsmb_softc *)device_get_softc(dev);
+ struct alpm_softc *sc = (struct alpm_softc *)device_get_softc(dev);
int error;
- alsmb_clear(sc);
- if (!alsmb_idle(sc))
+ alpm_clear(sc);
+ if (!alpm_idle(sc))
return (SMB_EBUSY);
ALPM_SMBOUTB(sc, SMBHADDR, slave | LSB);
ALPM_SMBOUTB(sc, SMBCMD, SMBSRBYTE);
ALPM_SMBOUTB(sc, SMBSTART, 0xff);
- if ((error = alsmb_wait(sc)) == SMB_ENOERR)
+ if ((error = alpm_wait(sc)) == SMB_ENOERR)
*byte = ALPM_SMBINB(sc, SMBHDATA);
ALPM_DEBUG(printf("alpm: RECVB from 0x%x, byte=0x%x, error=0x%x\n", slave, *byte, error));
@@ -499,13 +426,13 @@ alsmb_smb_recvb(device_t dev, u_char slave, char *byte)
}
static int
-alsmb_smb_writeb(device_t dev, u_char slave, char cmd, char byte)
+alpm_writeb(device_t dev, u_char slave, char cmd, char byte)
{
- struct alsmb_softc *sc = (struct alsmb_softc *)device_get_softc(dev);
+ struct alpm_softc *sc = (struct alpm_softc *)device_get_softc(dev);
int error;
- alsmb_clear(sc);
- if (!alsmb_idle(sc))
+ alpm_clear(sc);
+ if (!alpm_idle(sc))
return (SMB_EBUSY);
ALPM_SMBOUTB(sc, SMBHADDR, slave & ~LSB);
@@ -514,7 +441,7 @@ alsmb_smb_writeb(device_t dev, u_char slave, char cmd, char byte)
ALPM_SMBOUTB(sc, SMBHCMD, cmd);
ALPM_SMBOUTB(sc, SMBSTART, 0xff);
- error = alsmb_wait(sc);
+ error = alpm_wait(sc);
ALPM_DEBUG(printf("alpm: WRITEB to 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, byte, error));
@@ -522,13 +449,13 @@ alsmb_smb_writeb(device_t dev, u_char slave, char cmd, char byte)
}
static int
-alsmb_smb_readb(device_t dev, u_char slave, char cmd, char *byte)
+alpm_readb(device_t dev, u_char slave, char cmd, char *byte)
{
- struct alsmb_softc *sc = (struct alsmb_softc *)device_get_softc(dev);
+ struct alpm_softc *sc = (struct alpm_softc *)device_get_softc(dev);
int error;
- alsmb_clear(sc);
- if (!alsmb_idle(sc))
+ alpm_clear(sc);
+ if (!alpm_idle(sc))
return (SMB_EBUSY);
ALPM_SMBOUTB(sc, SMBHADDR, slave | LSB);
@@ -536,7 +463,7 @@ alsmb_smb_readb(device_t dev, u_char slave, char cmd, char *byte)
ALPM_SMBOUTB(sc, SMBHCMD, cmd);
ALPM_SMBOUTB(sc, SMBSTART, 0xff);
- if ((error = alsmb_wait(sc)) == SMB_ENOERR)
+ if ((error = alpm_wait(sc)) == SMB_ENOERR)
*byte = ALPM_SMBINB(sc, SMBHDATA);
ALPM_DEBUG(printf("alpm: READB from 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, *byte, error));
@@ -545,13 +472,13 @@ alsmb_smb_readb(device_t dev, u_char slave, char cmd, char *byte)
}
static int
-alsmb_smb_writew(device_t dev, u_char slave, char cmd, short word)
+alpm_writew(device_t dev, u_char slave, char cmd, short word)
{
- struct alsmb_softc *sc = (struct alsmb_softc *)device_get_softc(dev);
+ struct alpm_softc *sc = (struct alpm_softc *)device_get_softc(dev);
int error;
- alsmb_clear(sc);
- if (!alsmb_idle(sc))
+ alpm_clear(sc);
+ if (!alpm_idle(sc))
return (SMB_EBUSY);
ALPM_SMBOUTB(sc, SMBHADDR, slave & ~LSB);
@@ -561,7 +488,7 @@ alsmb_smb_writew(device_t dev, u_char slave, char cmd, short word)
ALPM_SMBOUTB(sc, SMBHCMD, cmd);
ALPM_SMBOUTB(sc, SMBSTART, 0xff);
- error = alsmb_wait(sc);
+ error = alpm_wait(sc);
ALPM_DEBUG(printf("alpm: WRITEW to 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, word, error));
@@ -569,14 +496,14 @@ alsmb_smb_writew(device_t dev, u_char slave, char cmd, short word)
}
static int
-alsmb_smb_readw(device_t dev, u_char slave, char cmd, short *word)
+alpm_readw(device_t dev, u_char slave, char cmd, short *word)
{
- struct alsmb_softc *sc = (struct alsmb_softc *)device_get_softc(dev);
+ struct alpm_softc *sc = (struct alpm_softc *)device_get_softc(dev);
int error;
u_char high, low;
- alsmb_clear(sc);
- if (!alsmb_idle(sc))
+ alpm_clear(sc);
+ if (!alpm_idle(sc))
return (SMB_EBUSY);
ALPM_SMBOUTB(sc, SMBHADDR, slave | LSB);
@@ -584,7 +511,7 @@ alsmb_smb_readw(device_t dev, u_char slave, char cmd, short *word)
ALPM_SMBOUTB(sc, SMBHCMD, cmd);
ALPM_SMBOUTB(sc, SMBSTART, 0xff);
- if ((error = alsmb_wait(sc)) == SMB_ENOERR) {
+ if ((error = alpm_wait(sc)) == SMB_ENOERR) {
low = ALPM_SMBINB(sc, SMBHDATA);
high = ALPM_SMBINB(sc, SMBHDATB);
@@ -597,14 +524,14 @@ alsmb_smb_readw(device_t dev, u_char slave, char cmd, short *word)
}
static int
-alsmb_smb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf)
+alpm_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf)
{
- struct alsmb_softc *sc = (struct alsmb_softc *)device_get_softc(dev);
+ struct alpm_softc *sc = (struct alpm_softc *)device_get_softc(dev);
u_char remain, len, i;
int error = SMB_ENOERR;
- alsmb_clear(sc);
- if(!alsmb_idle(sc))
+ alpm_clear(sc);
+ if(!alpm_idle(sc))
return (SMB_EBUSY);
remain = count;
@@ -627,7 +554,7 @@ alsmb_smb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf)
ALPM_SMBOUTB(sc, SMBHCMD, cmd);
ALPM_SMBOUTB(sc, SMBSTART, 0xff);
- if ((error = alsmb_wait(sc)) != SMB_ENOERR)
+ if ((error = alpm_wait(sc)) != SMB_ENOERR)
goto error;
remain -= len;
@@ -640,14 +567,14 @@ error:
}
static int
-alsmb_smb_bread(device_t dev, u_char slave, char cmd, u_char count, char *buf)
+alpm_bread(device_t dev, u_char slave, char cmd, u_char count, char *buf)
{
- struct alsmb_softc *sc = (struct alsmb_softc *)device_get_softc(dev);
+ struct alpm_softc *sc = (struct alpm_softc *)device_get_softc(dev);
u_char remain, len, i;
int error = SMB_ENOERR;
- alsmb_clear(sc);
- if (!alsmb_idle(sc))
+ alpm_clear(sc);
+ if (!alpm_idle(sc))
return (SMB_EBUSY);
remain = count;
@@ -661,7 +588,7 @@ alsmb_smb_bread(device_t dev, u_char slave, char cmd, u_char count, char *buf)
ALPM_SMBOUTB(sc, SMBHCMD, cmd);
ALPM_SMBOUTB(sc, SMBSTART, 0xff);
- if ((error = alsmb_wait(sc)) != SMB_ENOERR)
+ if ((error = alpm_wait(sc)) != SMB_ENOERR)
goto error;
len = ALPM_SMBINB(sc, SMBHDATA);
@@ -680,5 +607,35 @@ error:
return (error);
}
-DRIVER_MODULE(alpm, pci, alpm_pci_driver, alpm_devclass, 0, 0);
-DRIVER_MODULE(alsmb, alpm, alsmb_driver, alsmb_devclass, 0, 0);
+static devclass_t alpm_devclass;
+
+static device_method_t alpm_methods[] = {
+ /* device interface */
+ DEVMETHOD(device_probe, alpm_probe),
+ DEVMETHOD(device_attach, alpm_attach),
+ DEVMETHOD(device_detach, alpm_detach),
+
+ /* smbus interface */
+ DEVMETHOD(smbus_callback, alpm_callback),
+ DEVMETHOD(smbus_quick, alpm_quick),
+ DEVMETHOD(smbus_sendb, alpm_sendb),
+ DEVMETHOD(smbus_recvb, alpm_recvb),
+ DEVMETHOD(smbus_writeb, alpm_writeb),
+ DEVMETHOD(smbus_readb, alpm_readb),
+ DEVMETHOD(smbus_writew, alpm_writew),
+ DEVMETHOD(smbus_readw, alpm_readw),
+ DEVMETHOD(smbus_bwrite, alpm_bwrite),
+ DEVMETHOD(smbus_bread, alpm_bread),
+
+ { 0, 0 }
+};
+
+static driver_t alpm_driver = {
+ "alpm",
+ alpm_methods,
+ sizeof(struct alpm_softc)
+};
+
+DRIVER_MODULE(alpm, pci, alpm_driver, alpm_devclass, 0, 0);
+MODULE_DEPEND(alpm, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER);
+MODULE_VERSION(alpm, 1);
diff --git a/sys/pci/intpm.c b/sys/pci/intpm.c
index a3c780f..747f192 100644
--- a/sys/pci/intpm.c
+++ b/sys/pci/intpm.c
@@ -150,7 +150,7 @@ static int
intsmb_probe(device_t dev)
{
struct intsmb_softc *sc =(struct intsmb_softc *) device_get_softc(dev);
- sc->smbus=smbus_alloc_bus(dev);
+ sc->smbus=device_add_child(dev, "smbus", -1);
if (!sc->smbus)
return (EINVAL); /* XXX don't know what to return else */
device_set_desc(dev,"Intel PIIX4 SMBUS Interface");
@@ -739,6 +739,8 @@ intpm_probe(device_t dev)
}
}
DRIVER_MODULE(intpm, pci , intpm_pci_driver, intpm_devclass, 0, 0);
+MODULE_DEPEND(intpm, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER);
+MODULE_VERSION(intpm, 1);
static void intpm_intr(void *arg)
{
diff --git a/sys/pci/viapm.c b/sys/pci/viapm.c
new file mode 100644
index 0000000..d18f64d
--- /dev/null
+++ b/sys/pci/viapm.c
@@ -0,0 +1,924 @@
+/*-
+ * Copyright (c) 2001 Alcove - Nicolas Souchu
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ *
+ */
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/uio.h>
+
+#include <machine/bus_pio.h>
+#include <machine/bus_memio.h>
+#include <machine/bus.h>
+#include <machine/clock.h> /* for DELAY */
+#include <machine/resource.h>
+#include <sys/rman.h>
+
+#include <pci/pcivar.h>
+#include <pci/pcireg.h>
+
+#include <dev/iicbus/iiconf.h>
+#include <dev/iicbus/iicbus.h>
+
+#include <dev/smbus/smbconf.h>
+#include <dev/smbus/smbus.h>
+
+#include "iicbb_if.h"
+#include "smbus_if.h"
+
+#define VIAPM_DEBUG(x) if (viapm_debug) (x)
+
+#ifdef DEBUG
+static int viapm_debug = 1;
+#else
+static int viapm_debug = 0;
+#endif
+
+#define VIA_586B_PMU_ID 0x30401106
+#define VIA_596A_PMU_ID 0x30501106
+#define VIA_596B_PMU_ID 0x30511106
+#define VIA_686A_PMU_ID 0x30571106
+#define VIA_8233_PMU_ID 0x30741106
+
+#define VIAPM_INB(port) \
+ ((u_char)bus_space_read_1(viapm->st, viapm->sh, port))
+#define VIAPM_OUTB(port,val) \
+ (bus_space_write_1(viapm->st, viapm->sh, port, (u_char)val))
+
+#define VIAPM_TYP_UNKNOWN 0
+#define VIAPM_TYP_586B_3040E 1
+#define VIAPM_TYP_586B_3040F 2
+#define VIAPM_TYP_596B 3
+#define VIAPM_TYP_686A 4
+#define VIAPM_TYP_8233 5
+
+struct viapm_softc {
+ int type;
+ u_int32_t base;
+ bus_space_tag_t st;
+ bus_space_handle_t sh;
+ int iorid;
+ int irqrid;
+ struct resource *iores;
+ struct resource *irqres;
+ void *irqih;
+
+ device_t iicbb;
+ device_t smbus;
+};
+
+static devclass_t viapm_devclass;
+static devclass_t viapropm_devclass;
+
+/*
+ * VT82C586B definitions
+ */
+
+#define VIAPM_586B_REVID 0x08
+
+#define VIAPM_586B_3040E_BASE 0x20
+#define VIAPM_586B_3040E_ACTIV 0x4 /* 16 bits */
+
+#define VIAPM_586B_3040F_BASE 0x48
+#define VIAPM_586B_3040F_ACTIV 0x41 /* 8 bits */
+
+#define VIAPM_586B_OEM_REV_E 0x00
+#define VIAPM_586B_OEM_REV_F 0x01
+#define VIAPM_586B_PROD_REV_A 0x10
+
+#define VIAPM_586B_BA_MASK 0x0000ff00
+
+#define GPIO_DIR 0x40
+#define GPIO_VAL 0x42
+#define EXTSMI_VAL 0x44
+
+#define VIAPM_SCL 0x02 /* GPIO1_VAL */
+#define VIAPM_SDA 0x04 /* GPIO2_VAL */
+
+/*
+ * VIAPRO common definitions
+ */
+
+#define VIAPM_PRO_BA_MASK 0x0000fff0
+#define VIAPM_PRO_SMBCTRL 0xd2
+#define VIAPM_PRO_REVID 0xd6
+
+/*
+ * VT82C686A definitions
+ */
+
+#define VIAPM_PRO_BASE 0x90
+
+#define SMBHST 0x0
+#define SMBHSL 0x1
+#define SMBHCTRL 0x2
+#define SMBHCMD 0x3
+#define SMBHADDR 0x4
+#define SMBHDATA0 0x5
+#define SMBHDATA1 0x6
+#define SMBHBLOCK 0x7
+
+#define SMBSST 0x1
+#define SMBSCTRL 0x8
+#define SMBSSDWCMD 0x9
+#define SMBSEVENT 0xa
+#define SMBSDATA 0xc
+
+#define SMBHST_RESERVED 0xef /* reserved bits */
+#define SMBHST_FAILED 0x10 /* failed bus transaction */
+#define SMBHST_COLLID 0x08 /* bus collision */
+#define SMBHST_ERROR 0x04 /* device error */
+#define SMBHST_INTR 0x02 /* command completed */
+#define SMBHST_BUSY 0x01 /* host busy */
+
+#define SMBHCTRL_START 0x40 /* start command */
+#define SMBHCTRL_PROTO 0x1c /* command protocol mask */
+#define SMBHCTRL_QUICK 0x00
+#define SMBHCTRL_SENDRECV 0x04
+#define SMBHCTRL_BYTE 0x08
+#define SMBHCTRL_WORD 0x0c
+#define SMBHCTRL_BLOCK 0x14
+#define SMBHCTRL_KILL 0x02 /* stop the current transaction */
+#define SMBHCTRL_ENABLE 0x01 /* enable interrupts */
+
+#define SMBSCTRL_ENABLE 0x01 /* enable slave */
+
+
+/*
+ * VIA8233 definitions
+ */
+
+#define VIAPM_8233_BASE 0xD0
+
+static int
+viapm_586b_probe(device_t dev)
+{
+ struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
+ u_int32_t l;
+ u_int16_t s;
+ u_int8_t c;
+
+ switch (pci_get_devid(dev)) {
+ case VIA_586B_PMU_ID:
+
+ bzero(viapm, sizeof(struct viapm_softc));
+
+ l = pci_read_config(dev, VIAPM_586B_REVID, 1);
+ switch (l) {
+ case VIAPM_586B_OEM_REV_E:
+ viapm->type = VIAPM_TYP_586B_3040E;
+ viapm->iorid = VIAPM_586B_3040E_BASE;
+
+ /* Activate IO block access */
+ s = pci_read_config(dev, VIAPM_586B_3040E_ACTIV, 2);
+ pci_write_config(dev, VIAPM_586B_3040E_ACTIV, s | 0x1, 2);
+ break;
+
+ case VIAPM_586B_OEM_REV_F:
+ case VIAPM_586B_PROD_REV_A:
+ default:
+ viapm->type = VIAPM_TYP_586B_3040F;
+ viapm->iorid = VIAPM_586B_3040F_BASE;
+
+ /* Activate IO block access */
+ c = pci_read_config(dev, VIAPM_586B_3040F_ACTIV, 1);
+ pci_write_config(dev, VIAPM_586B_3040F_ACTIV, c | 0x80, 1);
+ break;
+ }
+
+ viapm->base = pci_read_config(dev, viapm->iorid, 4) &
+ VIAPM_586B_BA_MASK;
+
+ /*
+ * We have to set the I/O resources by hand because it is
+ * described outside the viapmope of the traditional maps
+ */
+ if (bus_set_resource(dev, SYS_RES_IOPORT, viapm->iorid,
+ viapm->base, 256)) {
+ device_printf(dev, "could not set bus resource\n");
+ return ENXIO;
+ }
+ device_set_desc(dev, "VIA VT82C586B Power Management Unit");
+ return 0;
+
+ default:
+ break;
+ }
+
+ return ENXIO;
+}
+
+
+static int
+viapm_pro_probe(device_t dev)
+{
+ struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
+#ifdef VIAPM_BASE_ADDR
+ u_int32_t l;
+#endif
+ u_int32_t base_cfgreg;
+ char *desc;
+
+ switch (pci_get_devid(dev)) {
+ case VIA_596A_PMU_ID:
+ desc = "VIA VT82C596A Power Management Unit";
+ viapm->type = VIAPM_TYP_596B;
+ base_cfgreg = VIAPM_PRO_BASE;
+ goto viapro;
+
+ case VIA_596B_PMU_ID:
+ desc = "VIA VT82C596B Power Management Unit";
+ viapm->type = VIAPM_TYP_596B;
+ base_cfgreg = VIAPM_PRO_BASE;
+ goto viapro;
+
+ case VIA_686A_PMU_ID:
+ desc = "VIA VT82C686A Power Management Unit";
+ viapm->type = VIAPM_TYP_686A;
+ base_cfgreg = VIAPM_PRO_BASE;
+ goto viapro;
+
+ case VIA_8233_PMU_ID:
+ desc = "VIA VT8233 Power Management Unit";
+ viapm->type = VIAPM_TYP_UNKNOWN;
+ base_cfgreg = VIAPM_8233_BASE;
+ goto viapro;
+
+ viapro:
+
+#ifdef VIAPM_BASE_ADDR
+ /* force VIAPM I/O base address */
+
+ /* enable the SMBus controller function */
+ l = pci_read_config(dev, VIAPM_PRO_SMBCTRL, 1);
+ pci_write_config(dev, VIAPM_PRO_SMBCTRL, l | 1, 1);
+
+ /* write the base address */
+ pci_write_config(dev, base_cfgreg,
+ VIAPM_BASE_ADDR & VIAPM_PRO_BA_MASK, 4);
+#endif
+
+ viapm->base = pci_read_config(dev, base_cfgreg, 4) & VIAPM_PRO_BA_MASK;
+
+ /*
+ * We have to set the I/O resources by hand because it is
+ * described outside the viapmope of the traditional maps
+ */
+ viapm->iorid = base_cfgreg;
+ if (bus_set_resource(dev, SYS_RES_IOPORT, viapm->iorid,
+ viapm->base, 16)) {
+ device_printf(dev, "could not set bus resource 0x%x\n",
+ viapm->base);
+ return ENXIO;
+ }
+
+ if (1 || bootverbose) {
+ device_printf(dev, "SMBus I/O base at 0x%x\n", viapm->base);
+ }
+
+ device_set_desc(dev, desc);
+ return 0;
+
+ default:
+ break;
+ }
+
+ return ENXIO;
+}
+
+static int
+viapm_pro_attach(device_t dev)
+{
+ struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
+ u_int32_t l;
+
+ if (!(viapm->iores = bus_alloc_resource(dev, SYS_RES_IOPORT,
+ &viapm->iorid, 0l, ~0l, 1, RF_ACTIVE))) {
+ device_printf(dev, "could not allocate bus space\n");
+ goto error;
+ }
+ viapm->st = rman_get_bustag(viapm->iores);
+ viapm->sh = rman_get_bushandle(viapm->iores);
+
+#if notyet
+ /* force irq 9 */
+ l = pci_read_config(dev, VIAPM_PRO_SMBCTRL, 1);
+ pci_write_config(dev, VIAPM_PRO_SMBCTRL, l | 0x80, 1);
+
+ viapm->irqrid = 0;
+ if (!(viapm->irqres = bus_alloc_resource(dev, SYS_RES_IRQ,
+ &viapm->irqrid, 9, 9, 1,
+ RF_SHAREABLE | RF_ACTIVE))) {
+ device_printf(dev, "could not allocate irq\n");
+ goto error;
+ }
+
+ if (bus_setup_intr(dev, viapm->irqres, INTR_TYPE_MISC,
+ (driver_intr_t *) viasmb_intr, viapm, &viapm->irqih)) {
+ device_printf(dev, "could not setup irq\n");
+ goto error;
+ }
+#endif
+
+ if (1 | bootverbose) {
+ l = pci_read_config(dev, VIAPM_PRO_REVID, 1);
+ device_printf(dev, "SMBus revision code 0x%x\n", l);
+ }
+
+ viapm->smbus = device_add_child(dev, "smbus", -1);
+
+ /* probe and attach the smbus */
+ bus_generic_attach(dev);
+
+ /* disable slave function */
+ VIAPM_OUTB(SMBSCTRL, VIAPM_INB(SMBSCTRL) & ~SMBSCTRL_ENABLE);
+
+ /* enable the SMBus controller function */
+ l = pci_read_config(dev, VIAPM_PRO_SMBCTRL, 1);
+ pci_write_config(dev, VIAPM_PRO_SMBCTRL, l | 1, 1);
+
+#if notyet
+ /* enable interrupts */
+ VIAPM_OUTB(SMBHCTRL, VIAPM_INB(SMBHCTRL) | SMBHCTRL_ENABLE);
+#endif
+
+ return 0;
+
+error:
+ if (viapm->iores)
+ bus_release_resource(dev, SYS_RES_IOPORT, viapm->iorid, viapm->iores);
+#if notyet
+ if (viapm->irqres)
+ bus_release_resource(dev, SYS_RES_IRQ, viapm->irqrid, viapm->irqres);
+#endif
+
+ return ENXIO;
+}
+
+static int
+viapm_586b_attach(device_t dev)
+{
+ struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
+
+ if (!(viapm->iores = bus_alloc_resource(dev, SYS_RES_IOPORT,
+ &viapm->iorid, 0ul, ~0ul, 1, RF_ACTIVE | RF_SHAREABLE))) {
+ device_printf(dev, "could not allocate bus resource\n");
+ return ENXIO;
+ }
+ viapm->st = rman_get_bustag(viapm->iores);
+ viapm->sh = rman_get_bushandle(viapm->iores);
+
+ VIAPM_OUTB(GPIO_DIR, VIAPM_INB(GPIO_DIR) | VIAPM_SCL | VIAPM_SDA);
+
+ /* add generic bit-banging code */
+ if (!(viapm->iicbb = device_add_child(dev, "iicbb", -1)))
+ goto error;
+
+ bus_generic_attach(dev);
+
+ return 0;
+
+error:
+ if (viapm->iores)
+ bus_release_resource(dev, SYS_RES_IOPORT,
+ viapm->iorid, viapm->iores);
+ return ENXIO;
+}
+
+static int
+viapm_586b_detach(device_t dev)
+{
+ struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
+ int error;
+
+ bus_generic_detach(dev);
+ if (viapm->iicbb) {
+ device_delete_child(dev, viapm->iicbb);
+ }
+
+ if (viapm->iores && (error = bus_release_resource(dev, SYS_RES_IOPORT,
+ viapm->iorid, viapm->iores)))
+ return (error);
+
+ return 0;
+}
+
+static int
+viapm_pro_detach(device_t dev)
+{
+ struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
+ int error;
+
+ bus_generic_detach(dev);
+ if (viapm->smbus) {
+ device_delete_child(dev, viapm->smbus);
+ }
+
+ if ((error = bus_release_resource(dev, SYS_RES_IOPORT,
+ viapm->iorid, viapm->iores)))
+ return (error);
+
+#if notyet
+ if ((error = bus_release_resource(dev, SYS_RES_IRQ,
+ viapm->irqrid, viapm->irqres))
+ return (error);
+#endif
+
+ return 0;
+}
+
+static int
+viabb_callback(device_t dev, int index, caddr_t *data)
+{
+ return 0;
+}
+
+static void
+viabb_setscl(device_t dev, int ctrl)
+{
+ struct viapm_softc *viapm = device_get_softc(dev);
+ u_char val;
+
+ val = VIAPM_INB(GPIO_VAL);
+
+ if (ctrl)
+ val |= VIAPM_SCL;
+ else
+ val &= ~VIAPM_SCL;
+
+ VIAPM_OUTB(GPIO_VAL, val);
+
+ return;
+}
+
+static void
+viabb_setsda(device_t dev, int data)
+{
+ struct viapm_softc *viapm = device_get_softc(dev);
+ u_char val;
+
+ val = VIAPM_INB(GPIO_VAL);
+
+ if (data)
+ val |= VIAPM_SDA;
+ else
+ val &= ~VIAPM_SDA;
+
+ VIAPM_OUTB(GPIO_VAL, val);
+
+ return;
+}
+
+static int
+viabb_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr)
+{
+ /* reset bus */
+ viabb_setsda(dev, 1);
+ viabb_setscl(dev, 1);
+
+ return (IIC_ENOADDR);
+}
+
+static int
+viabb_getscl(device_t dev)
+{
+ struct viapm_softc *viapm = device_get_softc(dev);
+
+ return ((VIAPM_INB(EXTSMI_VAL) & VIAPM_SCL) != 0);
+}
+
+static int
+viabb_getsda(device_t dev)
+{
+ struct viapm_softc *viapm = device_get_softc(dev);
+
+ return ((VIAPM_INB(EXTSMI_VAL) & VIAPM_SDA) != 0);
+}
+
+static int
+viapm_abort(struct viapm_softc *viapm)
+{
+ VIAPM_OUTB(SMBHCTRL, SMBHCTRL_KILL);
+ DELAY(10);
+
+ return (0);
+}
+
+static int
+viapm_clear(struct viapm_softc *viapm)
+{
+ VIAPM_OUTB(SMBHST, SMBHST_FAILED | SMBHST_COLLID |
+ SMBHST_ERROR | SMBHST_INTR);
+ DELAY(10);
+
+ return (0);
+}
+
+static int
+viapm_busy(struct viapm_softc *viapm)
+{
+ u_char sts;
+
+ sts = VIAPM_INB(SMBHST);
+
+ VIAPM_DEBUG(printf("viapm: idle? STS=0x%x\n", sts));
+
+ return (sts & SMBHST_BUSY);
+}
+
+/*
+ * Poll the SMBus controller
+ */
+static int
+viapm_wait(struct viapm_softc *viapm)
+{
+ int count = 10000;
+ u_char sts = 0;
+ int error;
+
+ /* wait for command to complete and SMBus controller is idle */
+ while(count--) {
+ DELAY(10);
+ sts = VIAPM_INB(SMBHST);
+
+ /* check if the controller is processing a command */
+ if (!(sts & SMBHST_BUSY) && (sts & SMBHST_INTR))
+ break;
+ }
+
+ VIAPM_DEBUG(printf("viapm: SMBHST=0x%x\n", sts));
+
+ error = SMB_ENOERR;
+
+ if (!count)
+ error |= SMB_ETIMEOUT;
+
+ if (sts & SMBHST_FAILED)
+ error |= SMB_EABORT;
+
+ if (sts & SMBHST_COLLID)
+ error |= SMB_ENOACK;
+
+ if (sts & SMBHST_ERROR)
+ error |= SMB_EBUSERR;
+
+ if (error != SMB_ENOERR)
+ viapm_abort(viapm);
+
+ viapm_clear(viapm);
+
+ return (error);
+}
+
+static int
+viasmb_callback(device_t dev, int index, caddr_t *data)
+{
+ int error = 0;
+
+ switch (index) {
+ case SMB_REQUEST_BUS:
+ case SMB_RELEASE_BUS:
+ /* ok, bus allocation accepted */
+ break;
+ default:
+ error = EINVAL;
+ }
+
+ return (error);
+}
+
+static int
+viasmb_quick(device_t dev, u_char slave, int how)
+{
+ struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
+ int error;
+
+ viapm_clear(viapm);
+ if (viapm_busy(viapm))
+ return (EBUSY);
+
+ switch (how) {
+ case SMB_QWRITE:
+ VIAPM_DEBUG(printf("viapm: QWRITE to 0x%x", slave));
+ VIAPM_OUTB(SMBHADDR, slave & ~LSB);
+ break;
+ case SMB_QREAD:
+ VIAPM_DEBUG(printf("viapm: QREAD to 0x%x", slave));
+ VIAPM_OUTB(SMBHADDR, slave | LSB);
+ break;
+ default:
+ panic("%s: unknown QUICK command (%x)!", __FUNCTION__,
+ how);
+ }
+
+ VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_QUICK);
+
+ error = viapm_wait(viapm);
+
+ return (error);
+}
+
+static int
+viasmb_sendb(device_t dev, u_char slave, char byte)
+{
+ struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
+ int error;
+
+ viapm_clear(viapm);
+ if (viapm_busy(viapm))
+ return (EBUSY);
+
+ VIAPM_OUTB(SMBHADDR, slave & ~ LSB);
+ VIAPM_OUTB(SMBHCMD, byte);
+
+ VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_SENDRECV);
+
+ error = viapm_wait(viapm);
+
+ VIAPM_DEBUG(printf("viapm: SENDB to 0x%x, byte=0x%x, error=0x%x\n", slave, byte, error));
+
+ return (error);
+}
+
+static int
+viasmb_recvb(device_t dev, u_char slave, char *byte)
+{
+ struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
+ int error;
+
+ viapm_clear(viapm);
+ if (viapm_busy(viapm))
+ return (EBUSY);
+
+ VIAPM_OUTB(SMBHADDR, slave | LSB);
+
+ VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_SENDRECV);
+
+ if ((error = viapm_wait(viapm)) == SMB_ENOERR)
+ *byte = VIAPM_INB(SMBHDATA0);
+
+ VIAPM_DEBUG(printf("viapm: RECVB from 0x%x, byte=0x%x, error=0x%x\n", slave, *byte, error));
+
+ return (error);
+}
+
+static int
+viasmb_writeb(device_t dev, u_char slave, char cmd, char byte)
+{
+ struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
+ int error;
+
+ viapm_clear(viapm);
+ if (viapm_busy(viapm))
+ return (EBUSY);
+
+ VIAPM_OUTB(SMBHADDR, slave & ~ LSB);
+ VIAPM_OUTB(SMBHCMD, cmd);
+ VIAPM_OUTB(SMBHDATA0, byte);
+
+ VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_BYTE);
+
+ error = viapm_wait(viapm);
+
+ VIAPM_DEBUG(printf("viapm: WRITEB to 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, byte, error));
+
+ return (error);
+}
+
+static int
+viasmb_readb(device_t dev, u_char slave, char cmd, char *byte)
+{
+ struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
+ int error;
+
+ viapm_clear(viapm);
+ if (viapm_busy(viapm))
+ return (EBUSY);
+
+ VIAPM_OUTB(SMBHADDR, slave | LSB);
+ VIAPM_OUTB(SMBHCMD, cmd);
+
+ VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_BYTE);
+
+ if ((error = viapm_wait(viapm)) == SMB_ENOERR)
+ *byte = VIAPM_INB(SMBHDATA0);
+
+ VIAPM_DEBUG(printf("viapm: READB from 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, *byte, error));
+
+ return (error);
+}
+
+static int
+viasmb_writew(device_t dev, u_char slave, char cmd, short word)
+{
+ struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
+ int error;
+
+ viapm_clear(viapm);
+ if (viapm_busy(viapm))
+ return (EBUSY);
+
+ VIAPM_OUTB(SMBHADDR, slave & ~ LSB);
+ VIAPM_OUTB(SMBHCMD, cmd);
+ VIAPM_OUTB(SMBHDATA0, word & 0x00ff);
+ VIAPM_OUTB(SMBHDATA1, (word & 0xff00) >> 8);
+
+ VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_WORD);
+
+ error = viapm_wait(viapm);
+
+ VIAPM_DEBUG(printf("viapm: WRITEW to 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, word, error));
+
+ return (error);
+}
+
+static int
+viasmb_readw(device_t dev, u_char slave, char cmd, short *word)
+{
+ struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
+ int error;
+ u_char high, low;
+
+ viapm_clear(viapm);
+ if (viapm_busy(viapm))
+ return (EBUSY);
+
+ VIAPM_OUTB(SMBHADDR, slave | LSB);
+ VIAPM_OUTB(SMBHCMD, cmd);
+
+ VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_WORD);
+
+ if ((error = viapm_wait(viapm)) == SMB_ENOERR) {
+ low = VIAPM_INB(SMBHDATA0);
+ high = VIAPM_INB(SMBHDATA1);
+
+ *word = ((high & 0xff) << 8) | (low & 0xff);
+ }
+
+ VIAPM_DEBUG(printf("viapm: READW from 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, *word, error));
+
+ return (error);
+}
+
+static int
+viasmb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf)
+{
+ struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
+ u_char remain, len, i;
+ int error = SMB_ENOERR;
+
+ viapm_clear(viapm);
+ if (viapm_busy(viapm))
+ return (EBUSY);
+
+ remain = count;
+ while (remain) {
+ len = min(remain, 32);
+
+ VIAPM_OUTB(SMBHADDR, slave & ~LSB);
+ VIAPM_OUTB(SMBHCMD, cmd);
+ VIAPM_OUTB(SMBHDATA0, len);
+ i = VIAPM_INB(SMBHCTRL);
+
+ /* fill the 32-byte internal buffer */
+ for (i=0; i<len; i++) {
+ VIAPM_OUTB(SMBHBLOCK, buf[count-remain+i]);
+ DELAY(2);
+ }
+ VIAPM_OUTB(SMBHCMD, cmd);
+ VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_BLOCK);
+
+ if ((error = viapm_wait(viapm)) != SMB_ENOERR)
+ goto error;
+
+ remain -= len;
+ }
+
+error:
+ VIAPM_DEBUG(printf("viapm: WRITEBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, count, cmd, error));
+
+ return (error);
+
+}
+
+static int
+viasmb_bread(device_t dev, u_char slave, char cmd, u_char count, char *buf)
+{
+ struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev);
+ u_char remain, len, i;
+ int error = SMB_ENOERR;
+
+ viapm_clear(viapm);
+ if (viapm_busy(viapm))
+ return (EBUSY);
+
+ remain = count;
+ while (remain) {
+ VIAPM_OUTB(SMBHADDR, slave | LSB);
+ VIAPM_OUTB(SMBHCMD, cmd);
+ VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_BLOCK);
+
+ if ((error = viapm_wait(viapm)) != SMB_ENOERR)
+ goto error;
+
+ len = VIAPM_INB(SMBHDATA0);
+ i = VIAPM_INB(SMBHCTRL); /* reset counter */
+
+ len = min(len, remain);
+
+ /* read the 32-byte internal buffer */
+ for (i=0; i<len; i++) {
+ buf[count-remain+i] = VIAPM_INB(SMBHBLOCK);
+ DELAY(2);
+ }
+
+ remain -= len;
+ }
+error:
+ VIAPM_DEBUG(printf("viapm: READBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, count, cmd, error));
+
+ return (error);
+}
+
+static device_method_t viapm_methods[] = {
+ /* device interface */
+ DEVMETHOD(device_probe, viapm_586b_probe),
+ DEVMETHOD(device_attach, viapm_586b_attach),
+ DEVMETHOD(device_detach, viapm_586b_detach),
+
+ /* iicbb interface */
+ DEVMETHOD(iicbb_callback, viabb_callback),
+ DEVMETHOD(iicbb_setscl, viabb_setscl),
+ DEVMETHOD(iicbb_setsda, viabb_setsda),
+ DEVMETHOD(iicbb_getscl, viabb_getscl),
+ DEVMETHOD(iicbb_getsda, viabb_getsda),
+ DEVMETHOD(iicbb_reset, viabb_reset),
+
+ { 0, 0 }
+};
+
+static driver_t viapm_driver = {
+ "viapm",
+ viapm_methods,
+ sizeof(struct viapm_softc),
+};
+
+static device_method_t viapropm_methods[] = {
+ /* device interface */
+ DEVMETHOD(device_probe, viapm_pro_probe),
+ DEVMETHOD(device_attach, viapm_pro_attach),
+ DEVMETHOD(device_detach, viapm_pro_detach),
+
+ /* smbus interface */
+ DEVMETHOD(smbus_callback, viasmb_callback),
+ DEVMETHOD(smbus_quick, viasmb_quick),
+ DEVMETHOD(smbus_sendb, viasmb_sendb),
+ DEVMETHOD(smbus_recvb, viasmb_recvb),
+ DEVMETHOD(smbus_writeb, viasmb_writeb),
+ DEVMETHOD(smbus_readb, viasmb_readb),
+ DEVMETHOD(smbus_writew, viasmb_writew),
+ DEVMETHOD(smbus_readw, viasmb_readw),
+ DEVMETHOD(smbus_bwrite, viasmb_bwrite),
+ DEVMETHOD(smbus_bread, viasmb_bread),
+
+ { 0, 0 }
+};
+
+static driver_t viapropm_driver = {
+ "viapropm",
+ viapropm_methods,
+ sizeof(struct viapm_softc),
+};
+
+DRIVER_MODULE(viapm, pci, viapm_driver, viapm_devclass, 0, 0);
+DRIVER_MODULE(viapropm, pci, viapropm_driver, viapropm_devclass, 0, 0);
+
+MODULE_DEPEND(viapm, iicbb, IICBB_MINVER, IICBB_PREFVER, IICBB_MAXVER);
+MODULE_DEPEND(viapropm, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER);
+MODULE_VERSION(viapm, 1);
OpenPOWER on IntegriCloud