.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.\" $FreeBSD: src/share/man/man4/intpm.4,v 1.8.2.4 2001/08/17 13:08:38 ru Exp $
-.\" $DragonFly: src/share/man/man4/intpm.4,v 1.2 2003/06/17 04:36:59 dillon Exp $
+.\" $FreeBSD: src/share/man/man4/intpm.4,v 1.15 2005/02/13 22:25:17 ru Exp $
.\"
.Dd January 8, 1999
.Dt INTPM 4
.Nd Intel PIIX4 Power Management controller driver
.Sh SYNOPSIS
.Cd device smbus
+.Cd device smb
.Cd device intpm
.Sh DESCRIPTION
This driver provides access to
To use this, you should enable
ACPI function in BIOS configuration, or PnP mechanism assigns conflicted
IRQ for PnP ISA card.
-And don't use IRQ 9 for Non-PnP ISA cards.
+And do not use IRQ 9 for Non-PnP ISA cards.
-SUBDIR=cam firewire mmc pccard usb
+SUBDIR=cam firewire iicbus mmc pccard ppbus smbus usb
.include <bsd.subdir.mk>
--- /dev/null
+# $FreeBSD: src/sys/modules/i2c/Makefile,v 1.1 2002/03/23 15:48:36 nsouch Exp $
+
+SUBDIR = iicbus iicbb iicsmb iic pcf
+
+.include <bsd.subdir.mk>
/*-
- * Copyright (c) 1998 Nicolas Souchu
+ * Copyright (c) 1998, 2001 Nicolas Souchu
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/sys/dev/iicbus/iic.c,v 1.18 1999/11/18 05:43:32 peter Exp $
+ * $FreeBSD: src/sys/dev/iicbus/iic.c,v 1.43 2009/01/26 13:53:39 raj Exp $
* $DragonFly: src/sys/bus/iicbus/iic.c,v 1.10 2006/09/10 01:26:32 dillon Exp $
*
*/
#include <sys/param.h>
-#include <sys/kernel.h>
-#include <sys/systm.h>
-#include <sys/module.h>
+#include <sys/buf.h>
#include <sys/bus.h>
#include <sys/conf.h>
-#include <sys/buf.h>
-#include <sys/uio.h>
-#include <sys/malloc.h>
#include <sys/fcntl.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/systm.h>
+#include <sys/uio.h>
-#include <machine/clock.h>
-
-#include "iiconf.h"
-#include "iicbus.h"
-
-#include <machine/iic.h>
+#include <bus/iicbus/iiconf.h>
+#include <bus/iicbus/iicbus.h>
+#include <bus/iicbus/iic.h>
#include "iicbus_if.h"
struct iic_softc {
- u_char sc_addr; /* address on iicbus */
+ device_t sc_dev;
+ u_char sc_addr; /* 7 bit address on iicbus */
int sc_count; /* >0 if device opened */
char sc_buffer[BUFSIZE]; /* output buffer */
char sc_inbuf[BUFSIZE]; /* input buffer */
-};
-#define IIC_SOFTC(unit) \
- ((struct iic_softc *)devclass_get_softc(iic_devclass, (unit)))
+ cdev_t sc_devnode;
+};
-#define IIC_DEVICE(unit) \
- (devclass_get_device(iic_devclass, (unit)))
+#define IIC_LOCK(sc)
+#define IIC_UNLOCK(sc)
static int iic_probe(device_t);
static int iic_attach(device_t);
+static int iic_detach(device_t);
+static void iic_identify(driver_t *driver, device_t parent);
static devclass_t iic_devclass;
static device_method_t iic_methods[] = {
/* device interface */
+ DEVMETHOD(device_identify, iic_identify),
DEVMETHOD(device_probe, iic_probe),
DEVMETHOD(device_attach, iic_attach),
+ DEVMETHOD(device_detach, iic_detach),
/* iicbus interface */
DEVMETHOD(iicbus_intr, iicbus_generic_intr),
static d_read_t iicread;
static d_ioctl_t iicioctl;
-#define CDEV_MAJOR 105
static struct dev_ops iic_ops = {
- { "iic", CDEV_MAJOR, 0 },
+ { "iic", 0, 0 },
.d_open = iicopen,
.d_close = iicclose,
.d_read = iicread,
.d_ioctl = iicioctl,
};
-/*
- * iicprobe()
- */
+static void
+iic_identify(driver_t *driver, device_t parent)
+{
+
+ if (device_find_child(parent, "iic", -1) == NULL)
+ BUS_ADD_CHILD(parent, parent, 0, "iic", -1);
+}
+
static int
iic_probe(device_t dev)
{
- struct iic_softc *sc = (struct iic_softc *)device_get_softc(dev);
-
- sc->sc_addr = iicbus_get_addr(dev);
+ if (iicbus_get_addr(dev) > 0)
+ return (ENXIO);
- /* XXX detect chip with start/stop conditions */
+ device_set_desc(dev, "I2C generic I/O");
return (0);
}
-/*
- * iicattach()
- */
static int
iic_attach(device_t dev)
{
- make_dev(&iic_ops, device_get_unit(dev), /* XXX cleanup */
+ struct iic_softc *sc = (struct iic_softc *)device_get_softc(dev);
+
+ sc->sc_devnode = make_dev(&iic_ops, device_get_unit(dev),
UID_ROOT, GID_WHEEL,
0600, "iic%d", device_get_unit(dev));
+ if (sc->sc_devnode == NULL) {
+ device_printf(dev, "failed to create character device\n");
+ return (ENXIO);
+ }
+ sc->sc_devnode->si_drv1 = sc;
+
return (0);
}
static int
-iicopen (struct dev_open_args *ap)
+iic_detach(device_t dev)
{
- cdev_t dev = ap->a_head.a_dev;
- struct iic_softc *sc = IIC_SOFTC(minor(dev));
+ struct iic_softc *sc = (struct iic_softc *)device_get_softc(dev);
- if (!sc)
- return (EINVAL);
+ if (sc->sc_devnode)
+ dev_ops_remove_minor(&iic_ops, device_get_unit(dev));
+
+ return (0);
+}
+
+static int
+iicopen(struct dev_open_args *ap)
+{
+ cdev_t dev = ap->a_head.a_dev;
+ struct iic_softc *sc = dev->si_drv1;
- if (sc->sc_count > 0)
+ IIC_LOCK(sc);
+ if (sc->sc_count > 0) {
+ IIC_UNLOCK(sc);
return (EBUSY);
+ }
sc->sc_count++;
+ IIC_UNLOCK(sc);
return (0);
}
iicclose(struct dev_close_args *ap)
{
cdev_t dev = ap->a_head.a_dev;
- struct iic_softc *sc = IIC_SOFTC(minor(dev));
-
- if (!sc)
- return (EINVAL);
+ struct iic_softc *sc = dev->si_drv1;
- if (!sc->sc_count)
+ IIC_LOCK(sc);
+ if (!sc->sc_count) {
+ /* XXX: I don't think this can happen. */
+ IIC_UNLOCK(sc);
return (EINVAL);
+ }
sc->sc_count--;
if (sc->sc_count < 0)
panic("%s: iic_count < 0!", __func__);
+ IIC_UNLOCK(sc);
return (0);
}
{
cdev_t dev = ap->a_head.a_dev;
struct uio *uio = ap->a_uio;
- device_t iicdev = IIC_DEVICE(minor(dev));
- struct iic_softc *sc = IIC_SOFTC(minor(dev));
+ struct iic_softc *sc = dev->si_drv1;
+ device_t iicdev = sc->sc_dev;
int sent, error, count;
- if (!sc || !iicdev)
+ IIC_LOCK(sc);
+ if (!sc->sc_addr) {
+ IIC_UNLOCK(sc);
return (EINVAL);
+ }
- if (sc->sc_count == 0)
+ if (sc->sc_count == 0) {
+ /* XXX: I don't think this can happen. */
+ IIC_UNLOCK(sc);
return (EINVAL);
+ }
- if ((error = iicbus_request_bus(device_get_parent(iicdev), iicdev, IIC_DONTWAIT)))
+ error = iicbus_request_bus(device_get_parent(iicdev), iicdev,
+ IIC_DONTWAIT);
+ if (error) {
+ IIC_UNLOCK(sc);
return (error);
+ }
count = (int)szmin(uio->uio_resid, BUFSIZE);
uiomove(sc->sc_buffer, (size_t)count, uio);
sc->sc_buffer, count, &sent);
iicbus_release_bus(device_get_parent(iicdev), iicdev);
+ IIC_UNLOCK(sc);
- return(error);
+ return (error);
}
static int
{
cdev_t dev = ap->a_head.a_dev;
struct uio *uio = ap->a_uio;
- device_t iicdev = IIC_DEVICE(minor(dev));
- struct iic_softc *sc = IIC_SOFTC(minor(dev));
+ struct iic_softc *sc = dev->si_drv1;
+ device_t iicdev = sc->sc_dev;
int len, error = 0;
int bufsize;
- if (!sc || !iicdev)
+ IIC_LOCK(sc);
+ if (!sc->sc_addr) {
+ IIC_UNLOCK(sc);
return (EINVAL);
+ }
- if (sc->sc_count == 0)
+ if (sc->sc_count == 0) {
+ /* XXX: I don't think this can happen. */
+ IIC_UNLOCK(sc);
return (EINVAL);
+ }
- if ((error = iicbus_request_bus(device_get_parent(iicdev), iicdev, IIC_DONTWAIT)))
+ error = iicbus_request_bus(device_get_parent(iicdev), iicdev,
+ IIC_DONTWAIT);
+ if (error) {
+ IIC_UNLOCK(sc);
return (error);
+ }
/* max amount of data to read */
len = (int)szmin(uio->uio_resid, BUFSIZE);
- if ((error = iicbus_block_read(device_get_parent(iicdev), sc->sc_addr,
- sc->sc_inbuf, len, &bufsize)))
+ error = iicbus_block_read(device_get_parent(iicdev), sc->sc_addr,
+ sc->sc_inbuf, len, &bufsize);
+ if (error) {
+ IIC_UNLOCK(sc);
return (error);
+ }
if (bufsize > uio->uio_resid)
panic("%s: too much data read!", __func__);
iicbus_release_bus(device_get_parent(iicdev), iicdev);
- return (uiomove(sc->sc_inbuf, (size_t)bufsize, uio));
+ error = uiomove(sc->sc_inbuf, (size_t)bufsize, uio);
+ IIC_UNLOCK(sc);
+ return (error);
}
static int
iicioctl(struct dev_ioctl_args *ap)
{
cdev_t dev = ap->a_head.a_dev;
- device_t iicdev = IIC_DEVICE(minor(dev));
- struct iic_softc *sc = IIC_SOFTC(minor(dev));
+ u_long cmd = ap->a_cmd;
+ caddr_t data = ap->a_data;
+ int flags = ap->a_fflag;
+ struct iic_softc *sc = dev->si_drv1;
+ device_t iicdev = sc->sc_dev;
device_t parent = device_get_parent(iicdev);
- struct iiccmd *s = (struct iiccmd *)ap->a_data;
- int error, count;
-
- if (!sc)
- return (EINVAL);
+ struct iiccmd *s = (struct iiccmd *)data;
+ struct iic_rdwr_data *d = (struct iic_rdwr_data *)data;
+ struct iic_msg *m;
+ int error, count, i;
+ char *buf = NULL;
+ void **usrbufs = NULL;
if ((error = iicbus_request_bus(device_get_parent(iicdev), iicdev,
- (ap->a_fflag & O_NONBLOCK) ? IIC_DONTWAIT :
+ (flags & O_NONBLOCK) ? IIC_DONTWAIT :
(IIC_WAIT | IIC_INTR))))
return (error);
- switch (ap->a_cmd) {
+ switch (cmd) {
case I2CSTART:
+ IIC_LOCK(sc);
error = iicbus_start(parent, s->slave, 0);
+
+ /*
+ * Implicitly set the chip addr to the slave addr passed as
+ * parameter. Consequently, start/stop shall be called before
+ * the read or the write of a block.
+ */
+ if (!error)
+ sc->sc_addr = s->slave;
+ IIC_UNLOCK(sc);
+
break;
case I2CSTOP:
break;
case I2CRSTCARD:
- error = iicbus_reset(parent, 0, 0, NULL);
+ error = iicbus_reset(parent, IIC_UNKNOWN, 0, NULL);
break;
case I2CWRITE:
- error = iicbus_write(parent, s->buf, s->count, &count, 0);
+ if (s->count <= 0) {
+ error = EINVAL;
+ break;
+ }
+ buf = kmalloc((unsigned long)s->count, M_TEMP, M_WAITOK);
+ error = copyin(s->buf, buf, s->count);
+ if (error)
+ break;
+ error = iicbus_write(parent, buf, s->count, &count, 10);
break;
case I2CREAD:
- error = iicbus_read(parent, s->buf, s->count, &count, s->last, 0);
+ if (s->count <= 0) {
+ error = EINVAL;
+ break;
+ }
+ buf = kmalloc((unsigned long)s->count, M_TEMP, M_WAITOK);
+ error = iicbus_read(parent, buf, s->count, &count, s->last, 10);
+ if (error)
+ break;
+ error = copyout(buf, s->buf, s->count);
+ break;
+
+ case I2CRDWR:
+ buf = kmalloc(sizeof(*d->msgs) * d->nmsgs, M_TEMP, M_WAITOK);
+ usrbufs = kmalloc(sizeof(void *) * d->nmsgs, M_TEMP, M_ZERO | M_WAITOK);
+ error = copyin(d->msgs, buf, sizeof(*d->msgs) * d->nmsgs);
+ if (error)
+ break;
+ /* Alloc kernel buffers for userland data, copyin write data */
+ for (i = 0; i < d->nmsgs; i++) {
+ m = &((struct iic_msg *)buf)[i];
+ usrbufs[i] = m->buf;
+ m->buf = kmalloc(m->len, M_TEMP, M_WAITOK);
+ if (!(m->flags & IIC_M_RD))
+ copyin(usrbufs[i], m->buf, m->len);
+ }
+ error = iicbus_transfer(parent, (struct iic_msg *)buf, d->nmsgs);
+ /* Copyout all read segments, free up kernel buffers */
+ for (i = 0; i < d->nmsgs; i++) {
+ m = &((struct iic_msg *)buf)[i];
+ if (m->flags & IIC_M_RD)
+ copyout(m->buf, usrbufs[i], m->len);
+ kfree(m->buf, M_TEMP);
+ }
+ kfree(usrbufs, M_TEMP);
+ break;
+
+ case I2CRPTSTART:
+ error = iicbus_repeated_start(parent, s->slave, 0);
break;
default:
- error = ENODEV;
+ error = ENOTTY;
}
iicbus_release_bus(device_get_parent(iicdev), iicdev);
+ if (buf != NULL)
+ kfree(buf, M_TEMP);
return (error);
}
DRIVER_MODULE(iic, iicbus, iic_driver, iic_devclass, 0, 0);
+MODULE_DEPEND(iic, iicbus, IICBUS_MINVER, IICBUS_PREFVER, IICBUS_MAXVER);
+MODULE_VERSION(iic, 1);
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/sys/i386/include/iic.h,v 1.3 1999/08/28 00:44:16 peter Exp $
+ * $FreeBSD: src/sys/dev/iicbus/iic.h,v 1.6 2009/01/26 13:53:39 raj Exp $
* $DragonFly: src/sys/platform/pc32/include/iic.h,v 1.4 2006/05/20 02:42:06 dillon Exp $
*
*/
-#ifndef _MACHINE_IIC_H_
-#define _MACHINE_IIC_H_
+#ifndef __IIC_H
+#define __IIC_H
-#ifndef _SYS_TYPES_H_
-#include <sys/types.h>
-#endif
-#ifndef _SYS_IOCCOM_H_
#include <sys/ioccom.h>
-#endif
+
+/* Designed to be compatible with linux's struct i2c_msg */
+struct iic_msg
+{
+ uint16_t slave;
+ uint16_t flags;
+#define IIC_M_WR 0 /* Fake flag for write */
+#define IIC_M_RD 0x0001 /* read vs write */
+ uint16_t len; /* msg legnth */
+ uint8_t * buf;
+};
struct iiccmd {
u_char slave;
char *buf;
};
+struct iic_rdwr_data {
+ struct iic_msg *msgs;
+ uint32_t nmsgs;
+};
+
#define I2CSTART _IOW('i', 1, struct iiccmd) /* start condition */
#define I2CSTOP _IO('i', 2) /* stop condition */
#define I2CRSTCARD _IOW('i', 3, struct iiccmd) /* reset the card */
#define I2CWRITE _IOW('i', 4, struct iiccmd) /* send data */
#define I2CREAD _IOW('i', 5, struct iiccmd) /* receive data */
+#define I2CRDWR _IOW('i', 6, struct iic_rdwr_data) /* General read/write interface */
+#define I2CRPTSTART _IOW('i', 7, struct iiccmd) /* repeated start */
#endif
--- /dev/null
+# $FreeBSD: src/sys/modules/i2c/iic/Makefile,v 1.1 2002/03/23 15:48:51 nsouch Exp $
+
+.PATH: ${.CURDIR}/..
+KMOD = iic
+SRCS = device_if.h bus_if.h iicbus_if.h \
+ iic.c
+
+.include <bsd.kmod.mk>
/*-
- * Copyright (c) 1998 Nicolas Souchu
+ * Copyright (c) 1998, 2001 Nicolas Souchu
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/sys/dev/iicbus/iicbb.c,v 1.6.2.2 2002/04/19 05:52:12 nsouch Exp $
+ * $FreeBSD: src/sys/dev/iicbus/iicbb.c,v 1.21 2009/02/10 22:50:23 imp Exp $
* $DragonFly: src/sys/bus/iicbus/iicbb.c,v 1.5 2006/12/22 23:12:16 swildner Exp $
*
*/
* Example:
*
* iicbus
- * / \
+ * / \
* iicbb pcf
* | \
* bti2c lpbb
* From Linux I2C generic interface
* (c) 1998 Gerd Knorr <kraxel@cs.tu-berlin.de>
*
- * TODO: port Peter's generic bit-banging code <dufault@hda.com>
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/module.h>
#include <sys/bus.h>
-#include <sys/conf.h>
-#include <sys/buf.h>
#include <sys/uio.h>
-#include <sys/malloc.h>
-#include <machine/clock.h>
-
-#include "iiconf.h"
-#include "iicbus.h"
+#include <bus/iicbus/iiconf.h>
+#include <bus/iicbus/iicbus.h>
#include <bus/smbus/smbconf.h>
DEVMETHOD(iicbus_write, iicbb_write),
DEVMETHOD(iicbus_read, iicbb_read),
DEVMETHOD(iicbus_reset, iicbb_reset),
+ DEVMETHOD(iicbus_transfer, iicbus_transfer_gen),
{ 0, 0 }
};
-static driver_t iicbb_driver = {
+driver_t iicbb_driver = {
"iicbb",
iicbb_methods,
sizeof(struct iicbb_softc),
};
-static devclass_t iicbb_devclass;
+devclass_t iicbb_devclass;
static int
iicbb_probe(device_t dev)
}
static void
-iicbb_child_detached(device_t dev, device_t child)
+iicbb_child_detached( device_t dev, device_t child )
{
struct iicbb_softc *sc = (struct iicbb_softc *)device_get_softc(dev);
return (retval);
}
-#define I2C_SET(dev,ctrl,data) \
- IICBB_SETLINES(device_get_parent(dev), ctrl, data)
+#define IIC_DELAY 10
+
+#define I2C_SETSDA(dev,val) do { \
+ IICBB_SETSDA(device_get_parent(dev), val); \
+ DELAY(IIC_DELAY); \
+ } while (0)
+
+#define I2C_SETSCL(dev,val) do { \
+ iicbb_setscl(dev, val, 100); \
+ } while (0)
+
+#define I2C_SET(dev,ctrl,data) do { \
+ I2C_SETSCL(dev, ctrl); \
+ I2C_SETSDA(dev, data); \
+ } while (0)
-#define I2C_GET(dev) (IICBB_GETDATALINE(device_get_parent(dev)))
+#define I2C_GETSDA(dev) (IICBB_GETSDA(device_get_parent(dev)))
+
+#define I2C_GETSCL(dev) (IICBB_GETSCL(device_get_parent(dev)))
static int i2c_debug = 0;
-#define I2C_DEBUG(x) if (i2c_debug) (x)
+#define I2C_DEBUG(x) do { \
+ if (i2c_debug) (x); \
+ } while (0)
+
+#define I2C_LOG(format,args...) do { \
+ kprintf(format, args); \
+ } while (0)
+
+static void
+iicbb_setscl(device_t dev, int val, int timeout)
+{
+ int k = 0;
+
+ IICBB_SETSCL(device_get_parent(dev), val);
+ DELAY(IIC_DELAY);
+
+ while (val && !I2C_GETSCL(dev) && k++ < timeout) {
+ IICBB_SETSCL(device_get_parent(dev), val);
+ DELAY(IIC_DELAY);
+ }
+
+ return;
+}
static void
-iicbb_one(device_t dev)
+iicbb_one(device_t dev, int timeout)
{
I2C_SET(dev,0,1);
I2C_SET(dev,1,1);
}
static void
-iicbb_zero(device_t dev)
+iicbb_zero(device_t dev, int timeout)
{
I2C_SET(dev,0,0);
I2C_SET(dev,1,0);
iicbb_ack(device_t dev, int timeout)
{
int noack;
- int k = timeout/10;
-
+ int k = 0;
+
I2C_SET(dev,0,1);
I2C_SET(dev,1,1);
-
do {
- noack = I2C_GET(dev);
+ noack = I2C_GETSDA(dev);
if (!noack)
break;
- DELAY(10); /* XXX wait 10us */
- } while (k--);
+ DELAY(10);
+ k += 10;
+ } while (k < timeout);
I2C_SET(dev,0,1);
I2C_DEBUG(kprintf("%c ",noack?'-':'+'));
}
static void
-iicbb_sendbyte(device_t dev, u_char data)
+iicbb_sendbyte(device_t dev, u_char data, int timeout)
{
int i;
-
- I2C_SET(dev,0,0);
- for (i=7; i>=0; i--)
- (data&(1<<i)) ? iicbb_one(dev) : iicbb_zero(dev);
+
+ for (i=7; i>=0; i--) {
+ if (data&(1<<i)) {
+ iicbb_one(dev, timeout);
+ } else {
+ iicbb_zero(dev, timeout);
+ }
+ }
I2C_DEBUG(kprintf("w%02x",(int)data));
return;
}
static u_char
-iicbb_readbyte(device_t dev, int last)
+iicbb_readbyte(device_t dev, int last, int timeout)
{
int i;
unsigned char data=0;
-
+
I2C_SET(dev,0,1);
- for (i=7; i>=0; i--)
+ for (i=7; i>=0; i--)
{
I2C_SET(dev,1,1);
- if (I2C_GET(dev))
+ if (I2C_GETSDA(dev))
data |= (1<<i);
I2C_SET(dev,0,1);
}
- last ? iicbb_one(dev) : iicbb_zero(dev);
+ if (last) {
+ iicbb_one(dev, timeout);
+ } else {
+ iicbb_zero(dev, timeout);
+ }
I2C_DEBUG(kprintf("r%02x%c ",(int)data,last?'-':'+'));
return data;
}
I2C_DEBUG(kprintf("<"));
- I2C_SET(dev,0,1);
I2C_SET(dev,1,1);
I2C_SET(dev,1,0);
I2C_SET(dev,0,0);
/* send address */
- iicbb_sendbyte(dev, slave);
+ iicbb_sendbyte(dev, slave, timeout);
/* check for ack */
if (iicbb_ack(dev, timeout)) {
bytes = 0;
while (len) {
/* send byte */
- iicbb_sendbyte(dev,(u_char)*buf++);
+ iicbb_sendbyte(dev,(u_char)*buf++, timeout);
/* check for ack */
if (iicbb_ack(dev, timeout)) {
bytes = 0;
while (len) {
/* XXX should insert delay here */
- *buf++ = (char)iicbb_readbyte(dev, (len == 1) ? last : 0);
+ *buf++ = (char)iicbb_readbyte(dev, (len == 1) ? last : 0, delay);
bytes ++;
len --;
DRIVER_MODULE(iicbb, cxm_iic, iicbb_driver, iicbb_devclass, 0, 0);
DRIVER_MODULE(iicbb, lpbb, iicbb_driver, iicbb_devclass, 0, 0);
DRIVER_MODULE(iicbb, viapm, iicbb_driver, iicbb_devclass, 0, 0);
+
+MODULE_DEPEND(iicbb, iicbus, IICBUS_MINVER, IICBUS_PREFVER, IICBUS_MAXVER);
+MODULE_VERSION(iicbb, IICBB_MODVER);
--- /dev/null
+# $FreeBSD: src/sys/modules/i2c/iicbb/Makefile,v 1.1 2002/03/23 15:48:53 nsouch Exp $
+
+.PATH: ${.CURDIR}/..
+KMOD = iicbb
+SRCS = device_if.h bus_if.h iicbus_if.h \
+ iicbb_if.h iicbb_if.c iicbb.c
+
+.include <bsd.kmod.mk>
-#
+#-
# Copyright (c) 1998 Nicolas Souchu
# All rights reserved.
#
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
-# $FreeBSD: src/sys/dev/iicbus/iicbb_if.m,v 1.3 1999/08/28 00:41:58 peter Exp $
+# $FreeBSD: src/sys/dev/iicbus/iicbb_if.m,v 1.6 2005/01/06 01:42:47 imp Exp $
# $DragonFly: src/sys/bus/iicbus/iicbb_if.m,v 1.3 2003/11/17 00:54:39 asmodai Exp $
#
};
#
-# Set I2C bus lines
+# Set I2C bus data line
+#
+METHOD void setsda {
+ device_t dev;
+ int val;
+};
+
+#
+# Set I2C bus clock line
+#
+METHOD void setscl {
+ device_t dev;
+ int val;
+};
+
+#
+# Get I2C bus data line
+#
#
-METHOD void setlines {
+METHOD int getsda {
device_t dev;
- int ctrl;
- int data;
};
#
-# Get I2C bus lines
+# Get I2C bus clock line
#
#
-METHOD int getdataline {
+METHOD int getscl {
device_t dev;
};
/*-
- * Copyright (c) 1998 Nicolas Souchu
+ * Copyright (c) 1998, 2001 Nicolas Souchu
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/sys/dev/iicbus/iicbus.c,v 1.13 1999/12/03 08:41:02 mdodd Exp $
+ * $FreeBSD: src/sys/dev/iicbus/iicbus.c,v 1.29 2009/02/10 22:50:23 imp Exp $
* $DragonFly: src/sys/bus/iicbus/iicbus.c,v 1.5 2006/12/22 23:12:16 swildner Exp $
*
*/
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/module.h>
-#include <sys/bus.h>
+#include <sys/bus.h>
-#include <machine/clock.h>
-
-#include "iiconf.h"
-#include "iicbus.h"
+#include <bus/iicbus/iiconf.h>
+#include <bus/iicbus/iicbus.h>
#include "iicbus_if.h"
#define DEVTOIICBUS(dev) ((struct iicbus_device*)device_get_ivars(dev))
-/*
- * structure used to attach devices to the I2C bus
- */
-struct iicbus_device {
- const char *iicd_name; /* device name */
- int iicd_class; /* driver or slave device class */
- const char *iicd_desc; /* device descriptor */
- u_char iicd_addr; /* address of the device */
- int iicd_waitack; /* wait for ack timeout or delay */
- int iicd_alive; /* 1 if device found */
-};
-
-/*
- * Common I2C addresses
- */
-#define I2C_GENERAL_CALL 0x0
-#define PCF_MASTER_ADDRESS 0xaa
-#define FIRST_SLAVE_ADDR 0x2
-
-#define LAST_SLAVE_ADDR 255
-
-#define IICBUS_UNKNOWN_CLASS 0
-#define IICBUS_DEVICE_CLASS 1
-#define IICBUS_DRIVER_CLASS 2
-
-/*
- * list of known devices
- *
- * XXX only one smb driver should exist for each I2C interface
- */
-static struct iicbus_device iicbus_children[] = {
- { "iicsmb", IICBUS_DRIVER_CLASS, "I2C to SMB bridge" },
- { "iic", IICBUS_DRIVER_CLASS, "I2C general purpose I/O" },
-#if 0
- { "ic", IICBUS_DEVICE_CLASS, "network interface", PCF_MASTER_ADDRESS },
-#endif
- { NULL, 0 }
-};
+devclass_t iicbus_devclass;
-static devclass_t iicbus_devclass;
+/* See comments below for why auto-scanning is a bad idea. */
+#define SCAN_IICBUS 0
/*
* Device methods
*/
static int iicbus_probe(device_t);
static int iicbus_attach(device_t);
-static int iicbus_print_child(device_t, device_t);
-static int iicbus_read_ivar(device_t , device_t, int, u_long *);
-static int iicbus_write_ivar(device_t , device_t, int, u_long);
+static int iicbus_detach(device_t);
+static int iicbus_add_child(device_t dev, int order, const char *name, int unit);
static device_method_t iicbus_methods[] = {
/* device interface */
DEVMETHOD(device_probe, iicbus_probe),
DEVMETHOD(device_attach, iicbus_attach),
- DEVMETHOD(device_detach, bus_generic_detach),
- DEVMETHOD(device_shutdown, bus_generic_shutdown),
+ DEVMETHOD(device_detach, iicbus_detach),
/* bus interface */
- DEVMETHOD(bus_print_child, iicbus_print_child),
- DEVMETHOD(bus_read_ivar, iicbus_read_ivar),
- DEVMETHOD(bus_write_ivar, iicbus_write_ivar),
+ DEVMETHOD(bus_add_child, iicbus_add_child),
+ DEVMETHOD(bus_driver_added, bus_generic_driver_added),
+ DEVMETHOD(bus_print_child, bus_generic_print_child),
+
+ DEVMETHOD(iicbus_transfer, iicbus_transfer_gen),
{ 0, 0 }
};
-static driver_t iicbus_driver = {
+driver_t iicbus_driver = {
"iicbus",
iicbus_methods,
sizeof(struct iicbus_softc),
static int
iicbus_probe(device_t dev)
{
+
device_set_desc(dev, "Philips I2C bus");
- return (0);
+ /* Allow other subclasses to override this driver. */
+ return (BUS_PROBE_GENERIC);
}
-#if 0
-static int
+#if SCAN_IICBUS
+static int
iic_probe_device(device_t dev, u_char addr)
{
int count;
static int
iicbus_attach(device_t dev)
{
- struct iicbus_device *iicdev;
- device_t child;
+#if SCAN_IICBUS
+ unsigned char addr;
+#endif
iicbus_reset(dev, IIC_FASTEST, 0, NULL);
* accesses like stop after start to fast, reads for less than
* x bytes...
*/
-#if 0
+#if SCAN_IICBUS
kprintf("Probing for devices on iicbus%d:", device_get_unit(dev));
/* probe any devices */
- for (addr = FIRST_SLAVE_ADDR; addr <= LAST_SLAVE_ADDR; addr++) {
+ for (addr = 16; addr < 240; addr++) {
if (iic_probe_device(dev, (u_char)addr)) {
kprintf(" <%x>", addr);
}
kprintf("\n");
#endif
- /* attach known devices */
- for (iicdev = iicbus_children; iicdev->iicd_name; iicdev++) {
- switch (iicdev->iicd_class) {
- case IICBUS_DEVICE_CLASS:
- /* check if the devclass exists */
- if (devclass_find(iicdev->iicd_name))
- iicdev->iicd_alive = 1;
- else if (bootverbose)
- kprintf("iicbus: %s devclass not found\n",
- iicdev->iicd_name);
- break;
-
- case IICBUS_DRIVER_CLASS:
- /* check if the devclass exists */
- if (devclass_find(iicdev->iicd_name))
- iicdev->iicd_alive = 1;
- else if (bootverbose)
- kprintf("iicbus: %s devclass not found\n",
- iicdev->iicd_name);
- break;
-
- default:
- panic("%s: unknown class!", __func__);
- }
-
- if (iicdev->iicd_alive) {
- child = device_add_child(dev, iicdev->iicd_name, -1);
- device_set_ivars(child, iicdev);
- device_set_desc(child, iicdev->iicd_desc);
- }
- }
+ device_add_child(dev, "ic", -1);
+ device_add_child(dev, "iic", -1);
+ device_add_child(dev, "iicsmb", -1);
+#if 0
+ /* attach any known device */
+ device_add_child(dev, "iic", -1);
+#endif
bus_generic_attach(dev);
return (0);
}
-int
-iicbus_generic_intr(device_t dev, int event, char *buf)
+static int
+iicbus_detach(device_t dev)
{
+ iicbus_reset(dev, IIC_FASTEST, 0, NULL);
+ bus_generic_detach(dev);
return (0);
}
-int
-iicbus_null_callback(device_t dev, int index, caddr_t data)
+static int
+iicbus_add_child(device_t dev, int order, const char *name, int unit)
{
+
+ device_add_child_ordered(dev, order, name, unit);
+ bus_generic_attach(dev);
return (0);
}
int
-iicbus_null_repeated_start(device_t dev, u_char addr)
-{
- return (IIC_ENOTSUPP);
-}
-
-static int
-iicbus_print_child(device_t bus, device_t dev)
+iicbus_generic_intr(device_t dev, int event, char *buf)
{
- struct iicbus_device* iicdev = DEVTOIICBUS(dev);
- int retval = 0;
-
- retval += bus_print_child_header(bus, dev);
-
- switch (iicdev->iicd_class) {
- case IICBUS_DEVICE_CLASS:
- retval += kprintf(" on %s addr 0x%x\n",
- device_get_nameunit(bus), iicdev->iicd_addr);
- break;
-
- case IICBUS_DRIVER_CLASS:
- retval += bus_print_child_footer(bus, dev);
- break;
- default:
- panic("%s: unknown class!", __func__);
- }
-
- return (retval);
+ return (0);
}
-static int
-iicbus_read_ivar(device_t bus, device_t dev, int index, u_long* result)
+int
+iicbus_null_callback(device_t dev, int index, caddr_t data)
{
- struct iicbus_device* iicdev = DEVTOIICBUS(dev);
-
- switch (index) {
- case IICBUS_IVAR_ADDR:
- *result = (u_long)iicdev->iicd_addr;
- break;
-
- default:
- return (ENOENT);
- }
return (0);
}
-static int
-iicbus_write_ivar(device_t bus, device_t dev, int index, u_long val)
+int
+iicbus_null_repeated_start(device_t dev, u_char addr)
{
- switch (index) {
- default:
- return (ENOENT);
- }
- return (0);
+ return (IIC_ENOTSUPP);
}
-DRIVER_MODULE(iicbus, pcf, iicbus_driver, iicbus_devclass, 0, 0);
DRIVER_MODULE(iicbus, iicbb, iicbus_driver, iicbus_devclass, 0, 0);
-DRIVER_MODULE(iicbus, bti2c, iicbus_driver, iicbus_devclass, 0, 0);
+MODULE_VERSION(iicbus, IICBUS_MODVER);
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/sys/dev/iicbus/iicbus.h,v 1.4 1999/08/28 00:41:58 peter Exp $
+ * $FreeBSD: src/sys/dev/iicbus/iicbus.h,v 1.8 2008/08/04 21:03:06 jhb Exp $
* $DragonFly: src/sys/bus/iicbus/iicbus.h,v 1.3 2006/09/30 20:03:44 swildner Exp $
*
*/
#ifndef __IICBUS_H
#define __IICBUS_H
-struct iicbus_softc {
+#define IICBUS_IVAR(d) (struct iicbus_ivar *) device_get_ivars(d)
+#define IICBUS_SOFTC(d) (struct iicbus_softc *) device_get_softc(d)
+struct iicbus_softc
+{
+ device_t dev; /* Myself */
device_t owner; /* iicbus owner device structure */
u_char started; /* address of the 'started' slave
* 0 if no start condition succeeded */
};
+struct iicbus_ivar
+{
+ uint32_t addr;
+};
+
+enum {
+ IICBUS_IVAR_ADDR /* Address or base address */
+};
+
+#define IICBUS_ACCESSOR(A, B, T) \
+ __BUS_ACCESSOR(iicbus, A, IICBUS, B, T)
+
+IICBUS_ACCESSOR(addr, ADDR, uint32_t)
+
+#define IICBUS_LOCK(sc)
+#define IICBUS_UNLOCK(sc)
+#define IICBUS_ASSERT_LOCKED(sc)
+
extern int iicbus_generic_intr(device_t dev, int event, char *buf);
+extern driver_t iicbus_driver;
+extern devclass_t iicbus_devclass;
+
#endif
--- /dev/null
+# $FreeBSD: src/sys/modules/i2c/iicbus/Makefile,v 1.1 2002/03/23 15:48:55 nsouch Exp $
+
+.PATH: ${.CURDIR}/..
+KMOD = iicbus
+SRCS = device_if.h bus_if.h iicbus_if.h iicbus_if.c \
+ iiconf.h iiconf.c iicbus.h iicbus.c
+
+.include <bsd.kmod.mk>
-#
+#-
# Copyright (c) 1998 Nicolas Souchu
# All rights reserved.
#
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
-# $FreeBSD: src/sys/dev/iicbus/iicbus_if.m,v 1.4 1999/08/28 00:41:59 peter Exp $
+# $FreeBSD: src/sys/dev/iicbus/iicbus_if.m,v 1.8 2006/12/05 06:19:36 imp Exp $
# $DragonFly: src/sys/bus/iicbus/iicbus_if.m,v 1.3 2003/11/17 00:54:39 asmodai Exp $
#
#include <sys/bus.h>
+#include <bus/iicbus/iic.h>
INTERFACE iicbus;
u_char addr;
u_char *oldaddr;
};
+
+#
+# Generalized Read/Write interface
+#
+METHOD int transfer {
+ device_t dev;
+ struct iic_msg *msgs;
+ uint32_t nmsgs;
+};
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/sys/dev/iicbus/iiconf.c,v 1.10 1999/12/03 08:41:02 mdodd Exp $
+ * $FreeBSD: src/sys/dev/iicbus/iiconf.c,v 1.19 2008/08/23 07:38:00 imp Exp $
* $DragonFly: src/sys/bus/iicbus/iiconf.c,v 1.5 2005/06/02 20:40:36 dillon Exp $
*
*/
#include <sys/param.h>
#include <sys/systm.h>
-#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/module.h>
#include <sys/bus.h>
#include <sys/thread2.h>
-#include "iiconf.h"
-#include "iicbus.h"
+#include <bus/iicbus/iiconf.h>
+#include <bus/iicbus/iicbus.h>
#include "iicbus_if.h"
/*
return;
}
-/*
- * iicbus_alloc_bus()
- *
- * Allocate a new bus connected to the given parent device
- */
-device_t
-iicbus_alloc_bus(device_t parent)
-{
- device_t child;
-
- /* add the bus to the parent */
- child = device_add_child(parent, "iicbus", -1);
-
- return (child);
-}
-
static int
iicbus_poll(struct iicbus_softc *sc, int how)
{
int error;
switch (how) {
- case (IIC_WAIT | IIC_INTR):
+ case IIC_WAIT | IIC_INTR:
error = tsleep(sc, PCATCH, "iicreq", 0);
break;
- case (IIC_WAIT | IIC_NOINTR):
+ case IIC_WAIT | IIC_NOINTR:
error = tsleep(sc, 0, "iicreq", 0);
break;
crit_exit();
return (EACCES);
}
- sc->owner = 0;
+ sc->owner = NULL;
crit_exit();
/* wakeup waiting processes */
}
/*
- * iicbus_get_addr()
+ * iicbus_transfer()
*
- * Get the I2C 7 bits address of the device
+ * Do an aribtrary number of transfers on the iicbus. We pass these
+ * raw requests to the bridge driver. If the bridge driver supports
+ * them directly, then it manages all the details. If not, it can use
+ * the helper function iicbus_transfer_gen() which will do the
+ * transfers at a low level.
+ *
+ * Pointers passed in as part of iic_msg must be kernel pointers.
+ * Callers that have user addresses to manage must do so on their own.
*/
-u_char
-iicbus_get_addr(device_t dev)
+int
+iicbus_transfer(device_t bus, struct iic_msg *msgs, uint32_t nmsgs)
{
- uintptr_t addr;
- device_t parent = device_get_parent(dev);
+ return (IICBUS_TRANSFER(device_get_parent(bus), msgs, nmsgs));
+}
- BUS_READ_IVAR(parent, dev, IICBUS_IVAR_ADDR, &addr);
+/*
+ * Generic version of iicbus_transfer that calls the appropriate
+ * routines to accomplish this. See note above about acceptable
+ * buffer addresses.
+ */
+int
+iicbus_transfer_gen(device_t dev, struct iic_msg *msgs, uint32_t nmsgs)
+{
+ int i, error, lenread, lenwrote, nkid;
+ device_t *children, bus;
- return ((u_char)addr);
+ if ((error = device_get_children(dev, &children, &nkid)) != 0)
+ return (error);
+ if (nkid != 1) {
+ kfree(children, M_TEMP);
+ return (EIO);
+ }
+ bus = children[0];
+ kfree(children, M_TEMP);
+ for (i = 0, error = 0; i < nmsgs && error == 0; i++) {
+ if (msgs[i].flags & IIC_M_RD)
+ error = iicbus_block_read(bus, msgs[i].slave,
+ msgs[i].buf, msgs[i].len, &lenread);
+ else
+ error = iicbus_block_write(bus, msgs[i].slave,
+ msgs[i].buf, msgs[i].len, &lenwrote);
+ }
+ return (error);
}
-
/*-
- * Copyright (c) 1998 Nicolas Souchu
+ * Copyright (c) 1998, 2001 Nicolas Souchu
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/sys/dev/iicbus/iiconf.h,v 1.7 2002/03/23 15:47:17 nsouch Exp $
+ * $FreeBSD: src/sys/dev/iicbus/iiconf.h,v 1.11 2006/12/05 06:19:36 imp Exp $
* $DragonFly: src/sys/bus/iicbus/iiconf.h,v 1.4 2003/11/14 21:46:17 daver Exp $
*/
#ifndef __IICONF_H
#define __IICONF_H
#include <sys/queue.h>
+#include <bus/iicbus/iic.h>
-#define n(flags) (~(flags) & (flags))
+
+#define IICPRI (PZERO+8) /* XXX sleep/wakeup queue priority */
#define LSB 0x1
#define IIC_ENOTSUPP 0x8 /* request not supported */
#define IIC_ENOADDR 0x9 /* no address assigned to the interface */
-/*
- * ivars codes
- */
-#define IICBUS_IVAR_ADDR 0x1 /* I2C address of the device */
-
extern int iicbus_request_bus(device_t, device_t, int);
extern int iicbus_release_bus(device_t, device_t);
-extern device_t iicbus_alloc_bus(device_t);
extern void iicbus_intr(device_t, int, char *);
extern int iicbus_block_write(device_t, u_char, char *, int, int *);
extern int iicbus_block_read(device_t, u_char, char *, int, int *);
-extern u_char iicbus_get_addr(device_t);
+/* vectors of iic operations to pass to bridge */
+int iicbus_transfer(device_t bus, struct iic_msg *msgs, uint32_t nmsgs);
+int iicbus_transfer_gen(device_t bus, struct iic_msg *msgs, uint32_t nmsgs);
+
+#define IICBUS_MODVER 1
+#define IICBUS_MINVER 1
+#define IICBUS_MAXVER 1
+#define IICBUS_PREFVER IICBUS_MODVER
-#define IICBUS_MODVER 1
-#define IICBUS_MINVER 1
-#define IICBUS_MAXVER 1
-#define IICBUS_PREFVER IICBUS_MODVER
+extern driver_t iicbb_driver;
+extern devclass_t iicbb_devclass;
-#define IICBB_MODVER 1
-#define IICBB_MINVER 1
-#define IICBB_MAXVER 1
-#define IICBB_PREFVER IICBB_MODVER
+#define IICBB_MODVER 1
+#define IICBB_MINVER 1
+#define IICBB_MAXVER 1
+#define IICBB_PREFVER IICBB_MODVER
#endif
/*-
- * Copyright (c) 1998 Nicolas Souchu
+ * Copyright (c) 1998, 2001 Nicolas Souchu
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/sys/dev/iicbus/iicsmb.c,v 1.5.2.2 2000/08/09 00:59:27 peter Exp $
+ * $FreeBSD: src/sys/dev/iicbus/iicsmb.c,v 1.18 2009/02/10 22:50:23 imp Exp $
* $DragonFly: src/sys/bus/iicbus/iicsmb.c,v 1.5 2006/12/22 23:12:16 swildner Exp $
*
*/
*/
#include <sys/param.h>
+#include <sys/bus.h>
#include <sys/kernel.h>
-#include <sys/systm.h>
#include <sys/module.h>
-#include <sys/bus.h>
-#include <sys/conf.h>
-#include <sys/buf.h>
+#include <sys/systm.h>
#include <sys/uio.h>
-#include <sys/malloc.h>
-#include <machine/clock.h>
-
-#include "iiconf.h"
-#include "iicbus.h"
+#include <bus/iicbus/iiconf.h>
+#include <bus/iicbus/iicbus.h>
#include <bus/smbus/smbconf.h>
static int iicsmb_probe(device_t);
static int iicsmb_attach(device_t);
+static int iicsmb_detach(device_t);
+static void iicsmb_identify(driver_t *driver, device_t parent);
-static void iicsmb_intr(device_t dev, int event, char *buf);
-static int iicsmb_callback(device_t dev, int index, caddr_t data);
+static int iicsmb_intr(device_t dev, int event, char *buf);
+static int iicsmb_callback(device_t dev, int index, void *data);
static int iicsmb_quick(device_t dev, u_char slave, int how);
static int iicsmb_sendb(device_t dev, u_char slave, char byte);
static int iicsmb_recvb(device_t dev, u_char slave, char *byte);
static int iicsmb_readw(device_t dev, u_char slave, char cmd, short *word);
static int iicsmb_pcall(device_t dev, u_char slave, char cmd, short sdata, short *rdata);
static int iicsmb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf);
-static int iicsmb_bread(device_t dev, u_char slave, char cmd, u_char count, char *buf);
+static int iicsmb_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf);
static devclass_t iicsmb_devclass;
static device_method_t iicsmb_methods[] = {
/* device interface */
+ DEVMETHOD(device_identify, iicsmb_identify),
DEVMETHOD(device_probe, iicsmb_probe),
DEVMETHOD(device_attach, iicsmb_attach),
- DEVMETHOD(device_detach, bus_generic_detach),
+ DEVMETHOD(device_detach, iicsmb_detach),
/* bus interface */
+ DEVMETHOD(bus_driver_added, bus_generic_driver_added),
DEVMETHOD(bus_print_child, bus_generic_print_child),
/* iicbus interface */
DEVMETHOD(smbus_pcall, iicsmb_pcall),
DEVMETHOD(smbus_bwrite, iicsmb_bwrite),
DEVMETHOD(smbus_bread, iicsmb_bread),
-
+
{ 0, 0 }
};
sizeof(struct iicsmb_softc),
};
+#define IICBUS_TIMEOUT 100 /* us */
+
+static void
+iicsmb_identify(driver_t *driver, device_t parent)
+{
+
+ if (device_find_child(parent, "iicsmb", -1) == NULL)
+ BUS_ADD_CHILD(parent, parent, 0, "iicsmb", -1);
+}
+
static int
iicsmb_probe(device_t dev)
{
+ device_set_desc(dev, "SMBus over I2C bridge");
+ return (0);
+}
+
+static int
+iicsmb_attach(device_t dev)
+{
struct iicsmb_softc *sc = (struct iicsmb_softc *)device_get_softc(dev);
- sc->smbus = smbus_alloc_bus(dev);
+ sc->smbus = device_add_child(dev, "smbus", -1);
+
+ /* probe and attach the smbus */
+ bus_generic_attach(dev);
- if (!sc->smbus)
- return (EINVAL); /* XXX don't know what to return else */
-
return (0);
}
static int
-iicsmb_attach(device_t dev)
+iicsmb_detach(device_t dev)
{
struct iicsmb_softc *sc = (struct iicsmb_softc *)device_get_softc(dev);
- /* probe and attach the smbus */
- device_probe_and_attach(sc->smbus);
+ bus_generic_detach(dev);
+ if (sc->smbus) {
+ device_delete_child(dev, sc->smbus);
+ }
return (0);
}
*
* iicbus interrupt handler
*/
-static void
+static int
iicsmb_intr(device_t dev, int event, char *buf)
{
struct iicsmb_softc *sc = (struct iicsmb_softc *)device_get_softc(dev);
panic("%s: unknown event (%d)!", __func__, event);
}
- return;
+ return (0);
}
static int
-iicsmb_callback(device_t dev, int index, caddr_t data)
+iicsmb_callback(device_t dev, int index, void *data)
{
device_t parent = device_get_parent(dev);
int error = 0;
switch (how) {
case SMB_QWRITE:
- error = iicbus_start(parent, slave & ~LSB, 0);
+ error = iicbus_start(parent, slave & ~LSB, IICBUS_TIMEOUT);
break;
case SMB_QREAD:
- error = iicbus_start(parent, slave | LSB, 0);
+ error = iicbus_start(parent, slave | LSB, IICBUS_TIMEOUT);
break;
default:
device_t parent = device_get_parent(dev);
int error, sent;
- error = iicbus_start(parent, slave & ~LSB, 0);
+ error = iicbus_start(parent, slave & ~LSB, IICBUS_TIMEOUT);
if (!error) {
- error = iicbus_write(parent, &byte, 1, &sent, 0);
+ error = iicbus_write(parent, &byte, 1, &sent, IICBUS_TIMEOUT);
iicbus_stop(parent);
}
error = iicbus_start(parent, slave | LSB, 0);
if (!error) {
- error = iicbus_read(parent, byte, 1, &read, IIC_LAST_READ, 0);
+ error = iicbus_read(parent, byte, 1, &read, IIC_LAST_READ, IICBUS_TIMEOUT);
iicbus_stop(parent);
}
error = iicbus_start(parent, slave & ~LSB, 0);
if (!error) {
- if (!(error = iicbus_write(parent, &cmd, 1, &sent, 0)))
- error = iicbus_write(parent, &byte, 1, &sent, 0);
+ if (!(error = iicbus_write(parent, &cmd, 1, &sent, IICBUS_TIMEOUT)))
+ error = iicbus_write(parent, &byte, 1, &sent, IICBUS_TIMEOUT);
iicbus_stop(parent);
}
error = iicbus_start(parent, slave & ~LSB, 0);
if (!error) {
- if (!(error = iicbus_write(parent, &cmd, 1, &sent, 0)))
- if (!(error = iicbus_write(parent, &low, 1, &sent, 0)))
- error = iicbus_write(parent, &high, 1, &sent, 0);
+ if (!(error = iicbus_write(parent, &cmd, 1, &sent, IICBUS_TIMEOUT)))
+ if (!(error = iicbus_write(parent, &low, 1, &sent, IICBUS_TIMEOUT)))
+ error = iicbus_write(parent, &high, 1, &sent, IICBUS_TIMEOUT);
iicbus_stop(parent);
}
device_t parent = device_get_parent(dev);
int error, sent, read;
- if ((error = iicbus_start(parent, slave & ~LSB, 0)))
+ if ((error = iicbus_start(parent, slave & ~LSB, IICBUS_TIMEOUT)))
return (error);
- if ((error = iicbus_write(parent, &cmd, 1, &sent, 0)))
+ if ((error = iicbus_write(parent, &cmd, 1, &sent, IICBUS_TIMEOUT)))
goto error;
- if ((error = iicbus_repeated_start(parent, slave | LSB, 0)))
+ if ((error = iicbus_repeated_start(parent, slave | LSB, IICBUS_TIMEOUT)))
goto error;
- if ((error = iicbus_read(parent, byte, 1, &read, IIC_LAST_READ, 0)))
+ if ((error = iicbus_read(parent, byte, 1, &read, IIC_LAST_READ, IICBUS_TIMEOUT)))
goto error;
error:
int error, sent, read;
char buf[2];
- if ((error = iicbus_start(parent, slave & ~LSB, 0)))
+ if ((error = iicbus_start(parent, slave & ~LSB, IICBUS_TIMEOUT)))
return (error);
- if ((error = iicbus_write(parent, &cmd, 1, &sent, 0)))
+ if ((error = iicbus_write(parent, &cmd, 1, &sent, IICBUS_TIMEOUT)))
goto error;
- if ((error = iicbus_repeated_start(parent, slave | LSB, 0)))
+ if ((error = iicbus_repeated_start(parent, slave | LSB, IICBUS_TIMEOUT)))
goto error;
- if ((error = iicbus_read(parent, buf, 2, &read, IIC_LAST_READ, 0)))
+ if ((error = iicbus_read(parent, buf, 2, &read, IIC_LAST_READ, IICBUS_TIMEOUT)))
goto error;
/* first, receive low, then high byte */
int error, sent, read;
char buf[2];
- if ((error = iicbus_start(parent, slave & ~LSB, 0)))
+ if ((error = iicbus_start(parent, slave & ~LSB, IICBUS_TIMEOUT)))
return (error);
- if ((error = iicbus_write(parent, &cmd, 1, &sent, 0)))
+ if ((error = iicbus_write(parent, &cmd, 1, &sent, IICBUS_TIMEOUT)))
goto error;
/* first, send low, then high byte */
buf[0] = (char)(sdata & 0xff);
buf[1] = (char)((sdata & 0xff00) >> 8);
- if ((error = iicbus_write(parent, buf, 2, &sent, 0)))
+ if ((error = iicbus_write(parent, buf, 2, &sent, IICBUS_TIMEOUT)))
goto error;
- if ((error = iicbus_repeated_start(parent, slave | LSB, 0)))
+ if ((error = iicbus_repeated_start(parent, slave | LSB, IICBUS_TIMEOUT)))
goto error;
- if ((error = iicbus_read(parent, buf, 2, &read, IIC_LAST_READ, 0)))
+ if ((error = iicbus_read(parent, buf, 2, &read, IIC_LAST_READ, IICBUS_TIMEOUT)))
goto error;
/* first, receive low, then high byte */
device_t parent = device_get_parent(dev);
int error, sent;
- if ((error = iicbus_start(parent, slave & ~LSB, 0)))
+ if ((error = iicbus_start(parent, slave & ~LSB, IICBUS_TIMEOUT)))
goto error;
- if ((error = iicbus_write(parent, &cmd, 1, &sent, 0)))
+ if ((error = iicbus_write(parent, &cmd, 1, &sent, IICBUS_TIMEOUT)))
goto error;
- if ((error = iicbus_write(parent, buf, (int)count, &sent, 0)))
+ if ((error = iicbus_write(parent, buf, (int)count, &sent, IICBUS_TIMEOUT)))
goto error;
if ((error = iicbus_stop(parent)))
}
static int
-iicsmb_bread(device_t dev, u_char slave, char cmd, u_char count, char *buf)
+iicsmb_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf)
{
device_t parent = device_get_parent(dev);
int error, sent, read;
- if ((error = iicbus_start(parent, slave & ~LSB, 0)))
+ if ((error = iicbus_start(parent, slave & ~LSB, IICBUS_TIMEOUT)))
return (error);
- if ((error = iicbus_write(parent, &cmd, 1, &sent, 0)))
+ if ((error = iicbus_write(parent, &cmd, 1, &sent, IICBUS_TIMEOUT)))
goto error;
- if ((error = iicbus_repeated_start(parent, slave | LSB, 0)))
+ if ((error = iicbus_repeated_start(parent, slave | LSB, IICBUS_TIMEOUT)))
goto error;
- if ((error = iicbus_read(parent, buf, (int)count, &read,
- IIC_LAST_READ, 0)))
+ if ((error = iicbus_read(parent, buf, (int)*count, &read,
+ IIC_LAST_READ, IICBUS_TIMEOUT)))
goto error;
+ *count = read;
error:
iicbus_stop(parent);
}
DRIVER_MODULE(iicsmb, iicbus, iicsmb_driver, iicsmb_devclass, 0, 0);
+DRIVER_MODULE(smbus, iicsmb, smbus_driver, smbus_devclass, 0, 0);
+MODULE_DEPEND(iicsmb, iicbus, IICBUS_MINVER, IICBUS_PREFVER, IICBUS_MAXVER);
+MODULE_DEPEND(iicsmb, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER);
+MODULE_VERSION(iicsmb, 1);
--- /dev/null
+# $FreeBSD: src/sys/modules/i2c/iicsmb/Makefile,v 1.1 2002/03/23 15:48:56 nsouch Exp $
+
+.PATH: ${.CURDIR}/..
+KMOD = iicsmb
+SRCS = device_if.h bus_if.h iicbus_if.h \
+ smbus_if.h iicsmb.c
+
+.include <bsd.kmod.mk>
--- /dev/null
+# $FreeBSD: src/sys/modules/i2c/controllers/pcf/Makefile,v 1.4 2005/11/22 17:32:51 marius Exp $
+
+.PATH: ${.CURDIR}/..
+
+KMOD= pcf
+SRCS= ${envctrl} pcf.c ${pcf_ebus} ${pcf_isa}
+SRCS+= bus_if.h device_if.h iicbus_if.h ${isa_if} ${ofw_bus_if}
+
+.if ${MACHINE_ARCH} == "i386"
+isa_if= isa_if.h
+pcf_isa= pcf.c
+.endif
+
+.if ${MACHINE_ARCH} == "sparc64"
+envctrl= envctrl.c
+ofw_bus_if= ofw_bus_if.h
+pcf_ebus= pcf_ebus.c
+.endif
+
+.include <bsd.kmod.mk>
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/sys/i386/isa/pcf.c,v 1.14 2000/01/14 00:18:05 nsouch Exp $
- * $DragonFly: src/sys/bus/iicbus/i386/pcf.c,v 1.11 2008/08/02 01:14:38 dillon Exp $
+ * $FreeBSD: src/sys/dev/pcf/pcf.c,v 1.21 2003/06/20 07:22:54 jmg Exp $
*
*/
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/bus.h>
-#include <sys/malloc.h>
-#include <machine/clock.h>
#include <sys/rman.h>
#include <bus/isa/isareg.h>
device_t iicbus; /* the corresponding iicbus */
- int rid_irq, rid_ioport;
+ int rid_irq, rid_ioport;
struct resource *res_irq, *res_ioport;
void *intr_cookie;
};
{
struct pcf_softc *pcf = DEVTOSOFTC(pcfdev);
device_t parent = device_get_parent(pcfdev);
+ uintptr_t base;
device_set_desc(pcfdev, "PCF8584 I2C bus controller");
/* IO port is mandatory */
pcf->res_ioport = bus_alloc_resource(pcfdev, SYS_RES_IOPORT,
- &pcf->rid_ioport, 0ul, ~0ul,
+ &pcf->rid_ioport, 0ul, ~0ul,
IO_PCFSIZE, RF_ACTIVE);
if (pcf->res_ioport == 0) {
device_printf(pcfdev, "cannot reserve I/O port range\n");
goto error;
}
- BUS_READ_IVAR(parent, pcfdev, ISA_IVAR_PORT, &pcf->pcf_base);
+ BUS_READ_IVAR(parent, pcfdev, ISA_IVAR_PORT, &base);
+ pcf->pcf_base = base;
pcf->pcf_flags = device_get_flags(pcfdev);
if (pcf->res_irq) {
/* default to the tty mask for registration */ /* XXX */
- error = BUS_SETUP_INTR(parent, pcfdev, pcf->res_irq,
+ error = BUS_SETUP_INTR(parent, pcfdev, pcf->res_irq,
0, pcfintr, pcfdev,
&pcf->intr_cookie, NULL);
if (error)
return (error);
}
- pcf->iicbus = iicbus_alloc_bus(pcfdev);
+ pcf->iicbus = device_add_child(pcfdev, "iicbus", -1);
/* probe and attach the iicbus */
- device_probe_and_attach(pcf->iicbus);
+ bus_generic_attach(pcfdev);
return (0);
}
/*
* Send STOP condition iff the START condition was previously sent.
- * STOP is sent only once even if a iicbus_stop() is called after
+ * STOP is sent only once even if an iicbus_stop() is called after
* an iicbus_read()... see pcf_read(): the pcf needs to send the stop
* before the last char is read.
*/
device_printf(pcfdev, "spurious interrupt, status=0x%x\n", status & 0xff);
goto error;
- }
+ }
if (status & LAB)
device_printf(pcfdev, "bus arbitration lost!\n");
/* get data from upper code */
iicbus_intr(pcf->iicbus, INTR_TRANSMIT, &data);
- PCF_SET_S0(pcf, data);
- break;
-
+ PCF_SET_S0(pcf, data);
+ break;
+
case SLAVE_RECEIVER:
if (status & AAS) {
addr = PCF_GET_S0(pcf);
pcf->pcf_addr = PCF_DEFAULT_ADDR;
else
pcf->pcf_addr = addr;
-
+
PCF_SET_S1(pcf, PIN); /* initialize S1 */
/* own address S'O<>0 */
--- /dev/null
+# $FreeBSD: src/sys/modules/ppbus/Makefile,v 1.5 2003/11/19 05:08:26 imp Exp $
+
+.PATH: ${.CURDIR}/..
+KMOD= ppbus
+SRCS= bus_if.h device_if.h ppbus_if.h ppbus_if.c \
+ opt_ppb_1284.h \
+ ppb_1284.c ppb_base.c ppb_msq.c ppbconf.c
+
+EXPORT_SYMS= ppb_attach_device \
+ ppb_request_bus \
+ ppb_release_bus \
+ ppb_get_status \
+ ppb_poll_bus \
+ ppb_reset_epp_timeout \
+ ppb_ecp_sync \
+ ppb_get_epp_protocol \
+ ppb_set_mode \
+ ppb_get_mode \
+ ppb_write
+
+.include <bsd.kmod.mk>
--- /dev/null
+# $FreeBSD: src/sys/modules/i2c/Makefile,v 1.1 2002/03/23 15:48:36 nsouch Exp $
+
+SUBDIR =
+SUBDIR += smbus smb
+
+.include <bsd.subdir.mk>
/*-
- * Copyright (c) 1998 Nicolas Souchu
+ * Copyright (c) 1998, 2001 Nicolas Souchu
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/sys/dev/smbus/smb.c,v 1.20 1999/11/18 05:44:56 peter Exp $
+ * $FreeBSD: src/sys/dev/smbus/smb.c,v 1.34.8.2 2006/09/22 19:19:16 jhb Exp $
* $DragonFly: src/sys/bus/smbus/smb.c,v 1.9 2006/09/10 01:26:33 dillon Exp $
*
*/
+
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/systm.h>
+#include <sys/device.h>
#include <sys/module.h>
#include <sys/bus.h>
#include <sys/conf.h>
-#include <sys/buf.h>
#include <sys/uio.h>
-#include <sys/malloc.h>
#include <sys/fcntl.h>
-#include <machine/clock.h>
-
#include "smbconf.h"
#include "smbus.h"
-#include <machine/smb.h>
+#include "smb.h"
#include "smbus_if.h"
struct smb_softc {
- int sc_addr; /* address on smbus */
int sc_count; /* >0 if device opened */
-
- char *sc_cp; /* output buffer pointer */
-
- char sc_buffer[BUFSIZE]; /* output buffer */
- char sc_inbuf[BUFSIZE]; /* input buffer */
+ cdev_t sc_devnode;
};
#define IIC_SOFTC(unit) \
#define IIC_DEVICE(unit) \
(devclass_get_device(smb_devclass, (unit)))
+static void smb_identify(driver_t *driver, device_t parent);
static int smb_probe(device_t);
static int smb_attach(device_t);
+static int smb_detach(device_t);
static devclass_t smb_devclass;
static device_method_t smb_methods[] = {
/* device interface */
+ DEVMETHOD(device_identify, smb_identify),
DEVMETHOD(device_probe, smb_probe),
DEVMETHOD(device_attach, smb_attach),
+ DEVMETHOD(device_detach, smb_detach),
/* smbus interface */
DEVMETHOD(smbus_intr, smbus_generic_intr),
static d_open_t smbopen;
static d_close_t smbclose;
-static d_write_t smbwrite;
-static d_read_t smbread;
static d_ioctl_t smbioctl;
#define CDEV_MAJOR 106
{ "smb", CDEV_MAJOR, 0 },
.d_open = smbopen,
.d_close = smbclose,
- .d_read = smbread,
- .d_write = smbwrite,
.d_ioctl = smbioctl,
};
-/*
- * smbprobe()
- */
+static void
+smb_identify(driver_t *driver, device_t parent)
+{
+ if (device_find_child(parent, "smb", -1) == NULL)
+ BUS_ADD_CHILD(parent, parent, 0, "smb", -1);
+}
+
static int
smb_probe(device_t dev)
{
+ device_set_desc(dev, "SMBus generic I/O");
+
+ return (0);
+}
+
+static int
+smb_attach(device_t dev)
+{
struct smb_softc *sc = (struct smb_softc *)device_get_softc(dev);
- sc->sc_addr = smbus_get_addr(dev);
+ if (!sc)
+ return (ENOMEM);
+
+ bzero(sc, sizeof(struct smb_softc *));
- /* XXX detect chip with start/stop conditions */
+ sc->sc_devnode = make_dev(&smb_ops, device_get_unit(dev),
+ UID_ROOT, GID_WHEEL,
+ 0600, "smb%d", device_get_unit(dev));
return (0);
}
-
-/*
- * smbattach()
- */
+
static int
-smb_attach(device_t dev)
+smb_detach(device_t dev)
{
- make_dev(&smb_ops, device_get_unit(dev),
- UID_ROOT, GID_WHEEL,
- 0600, "smb%d", device_get_unit(dev));
+ struct smb_softc *sc = (struct smb_softc *)device_get_softc(dev);
+
+ if (sc->sc_devnode)
+ dev_ops_remove_minor(&smb_ops, device_get_unit(dev));
+
return (0);
}
cdev_t dev = ap->a_head.a_dev;
struct smb_softc *sc = IIC_SOFTC(minor(dev));
- if (!sc)
- return (EINVAL);
+ if (sc == NULL)
+ return (ENXIO);
- if (sc->sc_count)
+ if (sc->sc_count != 0)
return (EBUSY);
sc->sc_count++;
cdev_t dev = ap->a_head.a_dev;
struct smb_softc *sc = IIC_SOFTC(minor(dev));
- if (!sc)
- return (EINVAL);
+ if (sc == NULL)
+ return (ENXIO);
- if (!sc->sc_count)
- return (EINVAL);
+ if (sc->sc_count == 0)
+ /* This is not supposed to happen. */
+ return (0);
sc->sc_count--;
return (0);
}
+#if 0
static int
smbwrite(struct dev_write_args *ap)
{
{
return (EINVAL);
}
+#endif
static int
smbioctl(struct dev_ioctl_args *ap)
{
cdev_t dev = ap->a_head.a_dev;
- device_t smbdev = IIC_DEVICE(minor(dev));
- struct smb_softc *sc = IIC_SOFTC(minor(dev));
- device_t parent = device_get_parent(smbdev);
-
- int error = 0;
+ char buf[SMB_MAXBLOCKSIZE];
+ device_t parent;
struct smbcmd *s = (struct smbcmd *)ap->a_data;
-
- if (!sc || !s)
+ struct smb_softc *sc = IIC_SOFTC(minor(dev));
+ device_t smbdev = IIC_DEVICE(minor(dev));
+ int error;
+ short w;
+ u_char count;
+ char c;
+
+ if (sc == NULL)
+ return (ENXIO);
+ if (s == NULL)
return (EINVAL);
- /* allocate the bus */
+ parent = device_get_parent(smbdev);
+
+ /* Allocate the bus. */
if ((error = smbus_request_bus(parent, smbdev,
(ap->a_fflag & O_NONBLOCK) ? SMB_DONTWAIT : (SMB_WAIT | SMB_INTR))))
return (error);
break;
case SMB_READB:
- if (s->data.byte_ptr)
+ if (s->data.byte_ptr) {
error = smbus_error(smbus_readb(parent, s->slave,
- s->cmd, s->data.byte_ptr));
+ s->cmd, &c));
+ if (error)
+ break;
+ error = copyout(&c, s->data.byte_ptr,
+ sizeof(*(s->data.byte_ptr)));
+ }
break;
case SMB_READW:
- if (s->data.word_ptr)
+ if (s->data.word_ptr) {
error = smbus_error(smbus_readw(parent, s->slave,
- s->cmd, s->data.word_ptr));
+ s->cmd, &w));
+ if (error == 0) {
+ error = copyout(&w, s->data.word_ptr,
+ sizeof(*(s->data.word_ptr)));
+ }
+ }
break;
case SMB_PCALL:
- if (s->data.process.rdata)
+ if (s->data.process.rdata) {
error = smbus_error(smbus_pcall(parent, s->slave, s->cmd,
- s->data.process.sdata, s->data.process.rdata));
+ s->data.process.sdata, &w));
+ if (error)
+ break;
+ error = copyout(&w, s->data.process.rdata,
+ sizeof(*(s->data.process.rdata)));
+ }
+
break;
case SMB_BWRITE:
- if (s->count && s->data.byte_ptr)
+ if (s->count && s->data.byte_ptr) {
+ if (s->count > SMB_MAXBLOCKSIZE)
+ s->count = SMB_MAXBLOCKSIZE;
+ error = copyin(s->data.byte_ptr, buf, s->count);
+ if (error)
+ break;
error = smbus_error(smbus_bwrite(parent, s->slave,
- s->cmd, s->count, s->data.byte_ptr));
+ s->cmd, s->count, buf));
+ }
break;
+ case SMB_OLD_BREAD:
case SMB_BREAD:
- if (s->count && s->data.byte_ptr)
+ if (s->count && s->data.byte_ptr) {
+ count = min(s->count, SMB_MAXBLOCKSIZE);
error = smbus_error(smbus_bread(parent, s->slave,
- s->cmd, s->count, s->data.byte_ptr));
+ s->cmd, &count, buf));
+ if (error)
+ break;
+ error = copyout(buf, s->data.byte_ptr,
+ min(count, s->count));
+ s->count = count;
+ }
break;
-
+
default:
- error = ENODEV;
+ error = ENOTTY;
}
- /* release the bus */
smbus_release_bus(parent, smbdev);
return (error);
}
DRIVER_MODULE(smb, smbus, smb_driver, smb_devclass, 0, 0);
+MODULE_DEPEND(smb, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER);
+MODULE_VERSION(smb, 1);
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/sys/i386/include/smb.h,v 1.3 1999/08/28 00:44:24 peter Exp $
+ * $FreeBSD: src/sys/dev/smbus/smb.h,v 1.4.8.1 2006/09/22 19:19:16 jhb Exp $
* $DragonFly: src/sys/platform/pc32/include/smb.h,v 1.4 2006/05/20 02:42:06 dillon Exp $
*
*/
-#ifndef _MACHINE_SMB_H_
-#define _MACHINE_SMB_H_
+#ifndef __SMB_H
+#define __SMB_H
-#ifndef _SYS_TYPES_H_
-#include <sys/types.h>
-#endif
-#ifndef _SYS_IOCCOM_H_
#include <sys/ioccom.h>
-#endif
struct smbcmd {
char cmd;
} data;
};
+/*
+ * SMBus spec 2.0 says block transfers may be at most 32 bytes.
+ */
+#define SMB_MAXBLOCKSIZE 32
+
#define SMB_QUICK_WRITE _IOW('i', 1, struct smbcmd)
#define SMB_QUICK_READ _IOW('i', 2, struct smbcmd)
#define SMB_SENDB _IOW('i', 3, struct smbcmd)
-#define SMB_RECVB _IOW('i', 4, struct smbcmd)
+#define SMB_RECVB _IOWR('i', 4, struct smbcmd)
#define SMB_WRITEB _IOW('i', 5, struct smbcmd)
#define SMB_WRITEW _IOW('i', 6, struct smbcmd)
#define SMB_READB _IOW('i', 7, struct smbcmd)
#define SMB_READW _IOW('i', 8, struct smbcmd)
#define SMB_PCALL _IOW('i', 9, struct smbcmd)
#define SMB_BWRITE _IOW('i', 10, struct smbcmd)
-#define SMB_BREAD _IOW('i', 11, struct smbcmd)
+#define SMB_OLD_BREAD _IOW('i', 11, struct smbcmd)
+#define SMB_BREAD _IOWR('i', 11, struct smbcmd)
#endif
--- /dev/null
+# $FreeBSD: src/sys/modules/i2c/smb/Makefile,v 1.1 2002/03/23 15:48:58 nsouch Exp $
+
+.PATH: ${.CURDIR}/..
+KMOD = smb
+SRCS = device_if.h bus_if.h smbus_if.h \
+ smb.c
+
+.include <bsd.kmod.mk>
/*-
- * Copyright (c) 1998 Nicolas Souchu
+ * Copyright (c) 1998, 2001 Nicolas Souchu
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/sys/dev/smbus/smbconf.c,v 1.9 1999/12/03 08:41:08 mdodd Exp $
+ * $FreeBSD: src/sys/dev/smbus/smbconf.c,v 1.13.10.1 2006/09/22 19:19:16 jhb Exp $
* $DragonFly: src/sys/bus/smbus/smbconf.c,v 1.5 2005/06/02 20:40:38 dillon Exp $
*
*/
#include <sys/param.h>
#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/malloc.h>
#include <sys/module.h>
#include <sys/bus.h>
#include <sys/thread2.h>
/* call owner's intr routine */
if (sc->owner)
SMBUS_INTR(sc->owner, devaddr, low, high, error);
-
- return;
}
/*
if (smb_error == SMB_ENOERR)
return (0);
- if (smb_error & (SMB_ENOTSUPP)) {
+ if (smb_error & (SMB_ENOTSUPP))
error = ENODEV;
- } else if (smb_error & (SMB_ENOACK)) {
+ else if (smb_error & (SMB_ENOACK))
error = ENXIO;
- } else if (smb_error & (SMB_ETIMEOUT)) {
+ else if (smb_error & (SMB_ETIMEOUT))
error = EWOULDBLOCK;
- } else if (smb_error & (SMB_EBUSY)) {
+ else if (smb_error & (SMB_EBUSY))
error = EBUSY;
- } else {
+ else if (smb_error & (SMB_EABORT | SMB_EBUSERR | SMB_ECOLLI))
+ error = EIO;
+ else
error = EINVAL;
- }
return (error);
}
-/*
- * smbus_alloc_bus()
- *
- * Allocate a new bus connected to the given parent device
- */
-device_t
-smbus_alloc_bus(device_t parent)
-{
- device_t child;
-
- /* add the bus to the parent */
- child = device_add_child(parent, "smbus", -1);
-
- return (child);
-}
-
static int
smbus_poll(struct smbus_softc *sc, int how)
{
break;
default:
- return (EWOULDBLOCK);
+ error = EWOULDBLOCK;
break;
}
int
smbus_request_bus(device_t bus, device_t dev, int how)
{
- struct smbus_softc *sc = (struct smbus_softc *)device_get_softc(bus);
- int error = 0;
+ struct smbus_softc *sc = device_get_softc(bus);
+ device_t parent;
+ int error;
/* first, ask the underlying layers if the request is ok */
+ parent = device_get_parent(bus);
do {
- error = SMBUS_CALLBACK(device_get_parent(bus),
- SMB_REQUEST_BUS, (caddr_t)&how);
+ error = SMBUS_CALLBACK(parent, SMB_REQUEST_BUS, &how);
if (error)
error = smbus_poll(sc, how);
} while (error == EWOULDBLOCK);
- while (!error) {
+ while (error == 0) {
crit_enter();
if (sc->owner && sc->owner != dev) {
crit_exit();
} else {
sc->owner = dev;
crit_exit();
- return (0);
}
/* free any allocated resource */
if (error)
- SMBUS_CALLBACK(device_get_parent(bus), SMB_RELEASE_BUS,
- (caddr_t)&how);
+ SMBUS_CALLBACK(parent, SMB_RELEASE_BUS, &how);
}
return (error);
return (error);
crit_enter();
- if (sc->owner != dev) {
- crit_exit();
- return (EACCES);
+ if (sc->owner == dev) {
+ sc->owner = NULL;
+
+ /* wakeup waiting processes */
+ wakeup(sc);
+ } else {
+ error = EACCES;
}
- sc->owner = 0;
crit_exit();
/* wakeup waiting processes */
wakeup(sc);
- return (0);
-}
-
-/*
- * smbus_get_addr()
- *
- * Get the I2C 7 bits address of the device
- */
-u_char
-smbus_get_addr(device_t dev)
-{
- uintptr_t addr;
- device_t parent = device_get_parent(dev);
-
- BUS_READ_IVAR(parent, dev, SMBUS_IVAR_ADDR, &addr);
-
- return ((u_char)addr);
+ return (error);
}
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/sys/dev/smbus/smbconf.h,v 1.7 2002/03/23 15:47:28 nsouch Exp $
+ * $FreeBSD: src/sys/dev/smbus/smbconf.h,v 1.7.14.1 2006/09/22 19:19:16 jhb Exp $
* $DragonFly: src/sys/bus/smbus/smbconf.h,v 1.4 2003/11/14 21:46:18 daver Exp $
*/
#ifndef __SMBONF_H
#include <sys/queue.h>
+#define SMBPRI (PZERO+8) /* XXX sleep/wakeup queue priority */
+
#define n(flags) (~(flags) & (flags))
/*
#define SMB_EABORT 0x10
#define SMB_ETIMEOUT 0x20
#define SMB_EBUSY 0x40
+#define SMB_EINVAL 0x100
/*
* How Quick command is executed
/*
* ivars codes
*/
-#define SMBUS_IVAR_ADDR 0x1 /* I2C address of the device */
+#define SMBUS_IVAR_ADDR 0x1 /* slave address of the device */
+
+int smbus_request_bus(device_t, device_t, int);
+int smbus_release_bus(device_t, device_t);
+int smbus_error(int error);
-extern int smbus_request_bus(device_t, device_t, int);
-extern int smbus_release_bus(device_t, device_t);
-extern device_t smbus_alloc_bus(device_t);
-extern int smbus_error(int error);
+void smbus_intr(device_t, u_char, char low, char high, int error);
-extern void smbus_intr(device_t, u_char, char low, char high, int error);
+u_char smbus_get_addr(device_t);
-extern u_char smbus_get_addr(device_t);
+extern driver_t smbus_driver;
+extern devclass_t smbus_devclass;
#define smbus_quick(bus,slave,how) \
(SMBUS_QUICK(device_get_parent(bus), slave, how))
#define smbus_bread(bus,slave,cmd,count,buf) \
(SMBUS_BREAD(device_get_parent(bus), slave, cmd, count, buf))
-#define SMBUS_MODVER 1
-#define SMBUS_MINVER 1
-#define SMBUS_MAXVER 1
-#define SMBUS_PREFVER SMBUS_MODVER
+#define SMBUS_MODVER 1
+#define SMBUS_MINVER 1
+#define SMBUS_MAXVER 1
+#define SMBUS_PREFVER SMBUS_MODVER
#endif
/*-
- * Copyright (c) 1998 Nicolas Souchu
+ * Copyright (c) 1998, 2001 Nicolas Souchu
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/sys/dev/smbus/smbus.c,v 1.12.2.3 2002/04/19 05:52:12 nsouch Exp $
+ * $FreeBSD: src/sys/dev/smbus/smbus.c,v 1.18.10.4 2006/09/26 18:44:56 jhb Exp $
* $DragonFly: src/sys/bus/smbus/smbus.c,v 1.4 2006/12/22 23:12:17 swildner Exp $
*
*/
#include "smbus.h"
/*
- * Autoconfiguration and support routines for the Philips serial I2C bus
+ * Autoconfiguration and support routines for System Management bus
*/
-#define DEVTOSMBUS(dev) ((struct smbus_device*)device_get_ivars(dev))
-
-/*
- * structure used to attach devices to the I2C bus
- */
-struct smbus_device {
- const char *smbd_name; /* device name */
- const char *smbd_desc; /* device descriptor */
-};
-
-/*
- * list of known devices
- */
-struct smbus_device smbus_children[] = {
- { "smb", "SMBus general purpose I/O" },
- { NULL, 0 }
-};
-
-static devclass_t smbus_devclass;
-
/*
* Device methods
*/
static int smbus_probe(device_t);
static int smbus_attach(device_t);
-
-#if 0
-static int smbus_read_ivar(device_t , device_t, int, u_long *);
-#endif
+static int smbus_detach(device_t);
static device_method_t smbus_methods[] = {
/* device interface */
DEVMETHOD(device_probe, smbus_probe),
DEVMETHOD(device_attach, smbus_attach),
- DEVMETHOD(device_detach, bus_generic_detach),
- DEVMETHOD(device_shutdown, bus_generic_shutdown),
+ DEVMETHOD(device_detach, smbus_detach),
/* bus interface */
+ DEVMETHOD(bus_add_child, bus_generic_add_child),
DEVMETHOD(bus_print_child, bus_generic_print_child),
- DEVMETHOD(bus_read_ivar, bus_generic_read_ivar),
- DEVMETHOD(bus_write_ivar, bus_generic_write_ivar),
{ 0, 0 }
};
-static driver_t smbus_driver = {
+driver_t smbus_driver = {
"smbus",
smbus_methods,
sizeof(struct smbus_softc),
};
+devclass_t smbus_devclass;
+
/*
* At 'probe' time, we add all the devices which we know about to the
* bus. The generic attach routine will probe and attach them if they
static int
smbus_attach(device_t dev)
{
- struct smbus_device *smbdev;
-
- /* add known devices */
- for (smbdev = smbus_children; smbdev->smbd_name; smbdev++) {
- device_t child;
-
- if (devclass_find(smbdev->smbd_name)) {
- child = device_add_child(dev, smbdev->smbd_name, -1);
- device_set_ivars(child, smbdev);
- device_set_desc(child, smbdev->smbd_desc);
- } else if (bootverbose)
- kprintf("smbus: %s devclass not found\n",
- smbdev->smbd_name);
- }
+ bus_generic_probe(dev);
bus_generic_attach(dev);
-
- return (0);
-}
-void
-smbus_generic_intr(device_t dev, u_char devaddr, char low, char high)
-{
- return;
+ return (0);
}
-#if 0
static int
-smbus_read_ivar(device_t bus, device_t dev, int index, u_long* result)
+smbus_detach(device_t dev)
{
- struct smbus_device* smbdev = DEVTOSMBUS(dev);
+ int error;
+
+ error = bus_generic_detach(dev);
+ if (error)
+ return (error);
+
+ return (0);
+}
- switch (index) {
- default:
- break;
- }
- return (ENOENT);
+void
+smbus_generic_intr(device_t dev, u_char devaddr, char low, char high)
+{
}
-#endif
-
-DRIVER_MODULE(smbus, iicsmb, smbus_driver, smbus_devclass, 0, 0);
-DRIVER_MODULE(smbus, bti2c, smbus_driver, smbus_devclass, 0, 0);
-DRIVER_MODULE(smbus, intsmb, smbus_driver, smbus_devclass, 0, 0);
-DRIVER_MODULE(smbus, alsmb, smbus_driver, smbus_devclass, 0, 0);
-DRIVER_MODULE(smbus, ichsmb, smbus_driver, smbus_devclass, 0, 0);
-DRIVER_MODULE(smbus, amdsmb, smbus_driver, smbus_devclass, 0, 0);
-DRIVER_MODULE(smbus, viapropm, smbus_driver, smbus_devclass, 0, 0);
+
+MODULE_VERSION(smbus, SMBUS_MODVER);
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/sys/dev/smbus/smbus.h,v 1.2 1999/08/28 00:42:30 peter Exp $
+ * $FreeBSD: src/sys/dev/smbus/smbus.h,v 1.2.34.2 2006/09/22 19:19:16 jhb Exp $
* $DragonFly: src/sys/bus/smbus/smbus.h,v 1.3 2006/09/30 20:03:44 swildner Exp $
*
*/
#define __SMBUS_H
struct smbus_softc {
-
device_t owner; /* smbus owner device structure */
};
-extern void smbus_generic_intr(device_t dev, u_char devaddr, char low, char high);
+void smbus_generic_intr(device_t dev, u_char devaddr, char low, char high);
#endif
--- /dev/null
+# $FreeBSD: src/sys/modules/i2c/smbus/Makefile,v 1.1 2002/03/23 15:48:59 nsouch Exp $
+
+.PATH: ${.CURDIR}/..
+KMOD = smbus
+SRCS = device_if.h bus_if.h smbus_if.h smbus_if.c \
+ smbconf.h smbconf.c smbus.h smbus.c
+
+.include <bsd.kmod.mk>
-#
+#-
# Copyright (c) 1998 Nicolas Souchu
# All rights reserved.
#
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
-# $FreeBSD: src/sys/dev/smbus/smbus_if.m,v 1.5 1999/08/28 00:42:30 peter Exp $
+# $FreeBSD: src/sys/dev/smbus/smbus_if.m,v 1.7.2.1 2006/09/22 19:19:16 jhb Exp $
# $DragonFly: src/sys/bus/smbus/smbus_if.m,v 1.3 2003/11/17 00:54:39 asmodai Exp $
#
METHOD int callback {
device_t dev;
int index;
- caddr_t data;
+ void *data;
};
#
device_t dev;
u_char slave;
char cmd;
- u_char count;
+ u_char *count;
char *buf;
};
dev/misc/pcfclock/pcfclock.c optional pcfclock
dev/misc/cmx/cmx.c optional cmx
dev/misc/cmx/cmx_pccard.c optional cmx pccard
+bus/iicbus/pcf/pcf.c optional pcf
bus/ppbus/ppb_base.c optional ppbus
bus/ppbus/ppb_1284.c optional ppbus
bus/ppbus/ppb_msq.c optional ppbus
dev/netif/vr/if_vr.c optional vr
dev/netif/wb/if_wb.c optional wb
dev/netif/xl/if_xl.c optional xl
-dev/powermng/i386/intpm/intpm.c optional intpm
-dev/powermng/i386/amdpm/amdpm.c optional amdpm
-dev/powermng/i386/viapm/viapm.c optional viapm
+dev/powermng/alpm/alpm.c optional alpm
+dev/powermng/amdpm/amdpm.c optional amdpm
+dev/powermng/intpm/intpm.c optional intpm
+dev/powermng/viapm/viapm.c optional viapm
dev/video/meteor/meteor.c optional meteor pci
dev/disk/ncr/ncr.c optional ncr
dev/disk/sym/sym_hipd.c optional sym \
bus/pci/pcib_if.m optional pci
bus/pci/vga_pci.c optional pci
bus/pci/pci_compat.c optional pci compat_oldpci
-dev/powermng/i386/alpm/alpm.c optional alpm
kern/kern_posix4_mib.c standard
kern/kern_p1003_1b.c standard
kern/kern_sched.c optional _kposix_priority_scheduling
# $DragonFly: src/sys/dev/misc/Makefile,v 1.5 2008/04/23 08:57:10 hasso Exp $
#
-SUBDIR=cmx dcons joy kbdmux pcfclock nmdm syscons snp hotplug
+SUBDIR=cmx dcons joy kbdmux lpbb pcfclock nmdm syscons snp hotplug
.include <bsd.subdir.mk>
--- /dev/null
+# $FreeBSD: src/sys/modules/i2c/controllers/lpbb/Makefile,v 1.2 2003/06/14 20:43:33 jmg Exp $
+
+.PATH: ${.CURDIR}/../../../bus/ppbus
+KMOD = lpbb
+SRCS = device_if.h bus_if.h iicbb_if.h ppbus_if.h \
+ lpbb.c
+
+.include <bsd.kmod.mk>
/*-
- * Copyright (c) 1998 Nicolas Souchu, Marc Bouget
+ * Copyright (c) 1998, 2001 Nicolas Souchu, Marc Bouget
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/sys/dev/ppbus/lpbb.c,v 1.11.2.1 2000/05/24 00:20:57 n_hibma Exp $
+ * $FreeBSD: src/sys/dev/ppbus/lpbb.c,v 1.18.8.1 2006/07/19 16:31:12 kib Exp $
* $DragonFly: src/sys/dev/misc/lpbb/lpbb.c,v 1.4 2005/10/28 03:25:45 dillon Exp $
*
*/
#include <sys/bus.h>
#include <sys/uio.h>
-#include <machine/clock.h>
-
#include <bus/ppbus/ppbconf.h>
#include "ppbus_if.h"
#include <bus/ppbus/ppbio.h>
static int lpbb_detect(device_t dev);
+static void
+lpbb_identify(driver_t *driver, device_t parent)
+{
+
+ device_t dev;
+
+ dev = device_find_child(parent, "lpbb", 0);
+ if (!dev)
+ BUS_ADD_CHILD(parent, parent, 0, "lpbb", -1);
+}
+
static int
lpbb_probe(device_t dev)
{
static int
lpbb_attach(device_t dev)
{
- device_t bitbang, iicbus;
+ device_t bitbang;
/* add generic bit-banging code */
bitbang = device_add_child(dev, "iicbb", -1);
-
- /* add the iicbus to the tree */
- iicbus = iicbus_alloc_bus(bitbang);
-
device_probe_and_attach(bitbang);
- /* XXX should be in iicbb_attach! */
- device_probe_and_attach(iicbus);
-
return (0);
}
#define ALIM 0x20
#define I2CKEY 0x50
-static int getSDA(device_t ppbus)
+static int
+lpbb_getscl(device_t dev)
{
- if((ppb_rstr(ppbus)&SDA_in)==SDA_in)
- return 1;
- else
- return 0;
+ return ((ppb_rstr(device_get_parent(dev)) & SCL_in) == SCL_in);
}
-static void setSDA(device_t ppbus, char val)
+static int
+lpbb_getsda(device_t dev)
+{
+ return ((ppb_rstr(device_get_parent(dev)) & SDA_in) == SDA_in);
+}
+
+static void
+lpbb_setsda(device_t dev, char val)
{
+ device_t ppbus = device_get_parent(dev);
+
if(val==0)
ppb_wdtr(ppbus, (u_char)SDA_out);
else
ppb_wdtr(ppbus, (u_char)~SDA_out);
}
-static void setSCL(device_t ppbus, unsigned char val)
+static void
+lpbb_setscl(device_t dev, unsigned char val)
{
+ device_t ppbus = device_get_parent(dev);
+
if(val==0)
ppb_wctr(ppbus, (u_char)(ppb_rctr(ppbus)&~SCL_out));
else
}
/* reset bus */
- setSDA(ppbus, 1);
- setSCL(ppbus, 1);
+ lpbb_setsda(dev, 1);
+ lpbb_setscl(dev, 1);
if ((ppb_rstr(ppbus) & I2CKEY) ||
((ppb_rstr(ppbus) & ALIM) != ALIM)) {
{
device_t ppbus = device_get_parent(dev);
- /* reset bus */
- setSDA(ppbus, 1);
- setSCL(ppbus, 1);
-
- return (IIC_ENOADDR);
-}
-
-static void
-lpbb_setlines(device_t dev, int ctrl, int data)
-{
- device_t ppbus = device_get_parent(dev);
+ if (ppb_request_bus(ppbus, dev, PPB_DONTWAIT)) {
+ device_printf(dev, "can't allocate ppbus\n");
+ return (0);
+ }
- setSCL(ppbus, ctrl);
- setSDA(ppbus, data);
-}
+ /* reset bus */
+ lpbb_setsda(dev, 1);
+ lpbb_setscl(dev, 1);
-static int
-lpbb_getdataline(device_t dev)
-{
- device_t ppbus = device_get_parent(dev);
+ ppb_release_bus(ppbus, dev);
- return (getSDA(ppbus));
+ return (IIC_ENOADDR);
}
-/*
- * Because lpbb is a static device that always exists under any attached
- * ppbus device, and not scanned by the ppbus device, we need an identify
- * function to install the device.
- */
static devclass_t lpbb_devclass;
static device_method_t lpbb_methods[] = {
/* device interface */
- DEVMETHOD(device_identify, bus_generic_identify),
+ DEVMETHOD(device_identify, lpbb_identify),
DEVMETHOD(device_probe, lpbb_probe),
DEVMETHOD(device_attach, lpbb_attach),
/* iicbb interface */
DEVMETHOD(iicbb_callback, lpbb_callback),
- DEVMETHOD(iicbb_setlines, lpbb_setlines),
- DEVMETHOD(iicbb_getdataline, lpbb_getdataline),
+ DEVMETHOD(iicbb_setsda, lpbb_setsda),
+ DEVMETHOD(iicbb_setscl, lpbb_setscl),
+ DEVMETHOD(iicbb_getsda, lpbb_getsda),
+ DEVMETHOD(iicbb_getscl, lpbb_getscl),
DEVMETHOD(iicbb_reset, lpbb_reset),
{ 0, 0 }
};
DRIVER_MODULE(lpbb, ppbus, lpbb_driver, lpbb_devclass, 0, 0);
+MODULE_DEPEND(lpbb, ppbus, 1, 1, 1);
+MODULE_DEPEND(lpbb, iicbb, IICBB_MINVER, IICBB_PREFVER, IICBB_MAXVER);
+MODULE_VERSION(lpbb, 1);
SUBDIR= an age alc ale ar ath aue axe bce bfe bge \
cue dc ed em ep et fwe \
- fxp iwi iwn jme kue lge lnc mii_layer my msk mxge nfe nge pcn ral re \
- rl rue sbni sbsh sf sis sk sln sr ste stge ti tl tx txp \
+ fxp ic iwi iwn jme kue lge lnc mii_layer my msk mxge nfe nge pcn \
+ ral re rl rue sbni sbsh sf sis sk sln sr ste stge ti tl tx txp \
vge vr vx wb wi wpi xe xl ig_hal emx ae
# XXX need to be updated to the new net80211 stack
--- /dev/null
+# $FreeBSD: src/sys/modules/i2c/if_ic/Makefile,v 1.1 2002/03/23 15:48:48 nsouch Exp $
+
+.PATH: ${.CURDIR}/../../../bus/iicbus
+KMOD = if_ic
+SRCS = device_if.h bus_if.h iicbus_if.h \
+ if_ic.c
+
+.include <bsd.kmod.mk>
#include "iicbus_if.h"
+#define PCF_MASTER_ADDRESS 0xaa
+
#define ICHDRLEN sizeof(uint32_t)
#define ICMTU 1500 /* default mtu */
struct ic_softc *sc = (struct ic_softc *)device_get_softc(dev);
struct ifnet *ifp = &sc->ic_if;
- sc->ic_addr = iicbus_get_addr(dev);
+ sc->ic_addr = PCF_MASTER_ADDRESS; /* XXX only PCF masters */
ifp->if_softc = sc;
if_initname(ifp, "ic", device_get_unit(dev));
return(0);
}
-DECLARE_DUMMY_MODULE(if_ic);
DRIVER_MODULE(if_ic, iicbus, ic_driver, ic_devclass, 0, 0);
-
+MODULE_DEPEND(if_ic, iicbus, IICBUS_MINVER, IICBUS_PREFVER, IICBUS_MAXVER);
+MODULE_VERSION(if_ic, 1);
-SUBDIR= aps coretemp kate km lm wbsio
+SUBDIR= alpm amdpm aps coretemp ichsmb intpm kate km lm viapm wbsio
+
.if ${MACHINE_ARCH} == "i386"
SUBDIR+= powernow
.endif
--- /dev/null
+# $FreeBSD: src/sys/modules/i2c/controllers/alpm/Makefile,v 1.2 2007/06/24 20:35:58 njl Exp $
+
+.PATH: ${.CURDIR}/../../../../bus/pci
+KMOD = alpm
+SRCS = device_if.h bus_if.h iicbus_if.h smbus_if.h pci_if.h \
+ alpm.c
+
+.include <bsd.kmod.mk>
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/sys/pci/alpm.c,v 1.15 2001/01/17 00:38:06 peter Exp $
- * $DragonFly: src/sys/dev/powermng/i386/alpm/alpm.c,v 1.8 2006/12/22 23:26:23 swildner Exp $
+ * $FreeBSD: src/sys/pci/alpm.c,v 1.24 2005/05/29 04:42:29 nyan Exp $
*
*/
#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),
+#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))
- /* 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 }
-};
+static int
+alpm_probe(device_t dev)
+{
+#ifdef ALPM_SMBIO_BASE_ADDR
+ u_int32_t l;
+#endif
-static driver_t alsmb_driver = {
- "alsmb",
- alsmb_methods,
- sizeof(struct alsmb_softc),
-};
+ if(pci_get_devid(dev) == ACER_M1543_PMU_ID) {
+ device_set_desc(dev, "AcerLabs M15x3 Power Management Unit");
-static int alpm_pci_probe(device_t dev);
-static int alpm_pci_attach(device_t dev);
+#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 devclass_t alpm_devclass;
+ /* disable I/O */
+ l = pci_read_config(dev, COM, 2);
+ pci_write_config(dev, COM, l & ~COM_ENABLE_IO, 2);
-static device_method_t alpm_pci_methods[] = {
- /* device interface */
- DEVMETHOD(device_probe, alpm_pci_probe),
- DEVMETHOD(device_attach, alpm_pci_attach),
-
- { 0, 0 }
-};
+ /* set the I/O base address */
+ pci_write_config(dev, SMBBA, ALPM_SMBIO_BASE_ADDR | 0x1, 4);
-static driver_t alpm_pci_driver = {
- "alpm",
- alpm_pci_methods,
- sizeof(struct alpm_data)
-};
+ /* 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 (BUS_PROBE_DEFAULT);
}
+
+ return (ENXIO);
}
static int
-alpm_pci_attach(device_t dev)
+alpm_attach(device_t dev)
{
- int rid, unit;
+ int rid;
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);
/* Unlock SMBIO base register access */
l = pci_read_config(dev, ATPC, 1);
pci_write_config(dev, SMBHCBC, l, 1)
*/
- if (bootverbose) {
+ if (bootverbose || alpm_debug) {
l = pci_read_config(dev, SMBHSI, 1);
- kprintf("alsmb%d: %s/%s", unit,
+ device_printf(dev, "%s/%s",
(l & SMBHSI_HOST) ? "host":"nohost",
(l & SMBHSI_SLAVE) ? "slave":"noslave");
case SMBCLOCK_55K:
kprintf(" 55K");
break;
+ default:
+ kprintf("unkown");
+ break;
}
+ kprintf("\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_any(dev, SYS_RES_IOPORT, &rid,
+ 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);
-
- if (bootverbose)
- kprintf(" 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;
-}
+ alpm->smbst = rman_get_bustag(alpm->res);
+ alpm->smbsh = rman_get_bushandle(alpm->res);
-/*
- * 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;
}
static int
-alsmb_clear(struct alsmb_softc *sc)
+alpm_clear(struct alpm_softc *sc)
{
ALPM_SMBOUTB(sc, SMBSTS, 0xff);
DELAY(10);
#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);
#endif
static int
-alsmb_idle(struct alsmb_softc *sc)
+alpm_idle(struct alpm_softc *sc)
{
u_char sts;
* 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;
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) {
ALPM_SMBOUTB(sc, SMBCMD, SMBQUICK);
ALPM_SMBOUTB(sc, SMBSTART, 0xff);
- error = alsmb_wait(sc);
+ error = alpm_wait(sc);
ALPM_DEBUG(kprintf(", error=0x%x\n", error));
}
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);
ALPM_SMBOUTB(sc, SMBHDATA, byte);
ALPM_SMBOUTB(sc, SMBSTART, 0xff);
- error = alsmb_wait(sc);
+ error = alpm_wait(sc);
ALPM_DEBUG(kprintf("alpm: SENDB to 0x%x, byte=0x%x, error=0x%x\n", slave, byte, error));
}
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(kprintf("alpm: RECVB from 0x%x, byte=0x%x, error=0x%x\n", slave, *byte, error));
}
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);
ALPM_SMBOUTB(sc, SMBHCMD, cmd);
ALPM_SMBOUTB(sc, SMBSTART, 0xff);
- error = alsmb_wait(sc);
+ error = alpm_wait(sc);
ALPM_DEBUG(kprintf("alpm: WRITEB to 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, byte, error));
}
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);
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(kprintf("alpm: READB from 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, *byte, error));
}
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);
ALPM_SMBOUTB(sc, SMBHCMD, cmd);
ALPM_SMBOUTB(sc, SMBSTART, 0xff);
- error = alsmb_wait(sc);
+ error = alpm_wait(sc);
ALPM_DEBUG(kprintf("alpm: WRITEW to 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, word, error));
}
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);
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);
}
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;
len = min(remain, 32);
ALPM_SMBOUTB(sc, SMBHADDR, slave & ~LSB);
-
+
/* set the cmd and reset the
* 32-byte long internal buffer */
ALPM_SMBOUTB(sc, SMBCMD, SMBWRBLOCK | SMB_BLK_CLR);
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;
}
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;
while (remain) {
ALPM_SMBOUTB(sc, SMBHADDR, slave | LSB);
-
+
/* set the cmd and reset the
* 32-byte long internal buffer */
ALPM_SMBOUTB(sc, SMBCMD, SMBWRBLOCK | SMB_BLK_CLR);
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);
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, pci, 1, 1, 1);
+MODULE_DEPEND(alpm, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER);
+MODULE_VERSION(alpm, 1);
--- /dev/null
+# $FreeBSD: src/sys/modules/i2c/controllers/amdpm/Makefile,v 1.1 2002/03/23 15:48:41 nsouch Exp $
+
+.PATH: ${.CURDIR}/../../../../bus/pci
+KMOD = amdpm
+SRCS = device_if.h bus_if.h pci_if.h smbus_if.h \
+ amdpm.c
+
+.include <bsd.kmod.mk>
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/sys/pci/amdpm.c,v 1.1.2.1 2001/10/10 12:10:26 murray Exp $
- * $DragonFly: src/sys/dev/powermng/i386/amdpm/amdpm.c,v 1.7 2006/12/22 23:26:23 swildner Exp $
+ * $FreeBSD: src/sys/pci/amdpm.c,v 1.10 2003/09/06 13:56:56 dfr Exp $
*
*/
#define AMDPM_VENDORID_AMD 0x1022
#define AMDPM_DEVICEID_AMD756PM 0x740b
+#define AMDPM_DEVICEID_AMD766PM 0x7413
+#define AMDPM_DEVICEID_AMD768PM 0x7443
+
+/* nVidia nForce chipset */
+#define AMDPM_VENDORID_NVIDIA 0x10de
+#define AMDPM_DEVICEID_NF_SMB 0x01b4
+
/* PCI Configuration space registers */
#define AMDPCI_PMBASE 0x58
+#define NFPCI_PMBASE 0x14
#define AMDPCI_GEN_CONFIG_PM 0x41
#define AMDPCI_PMIOEN (1<<7)
* I/O registers.
* Base address programmed via AMDPCI_PMBASE.
*/
-#define AMDSMB_GLOBAL_STATUS 0xE0
+
+#define AMDSMB_GLOBAL_STATUS (0x00)
#define AMDSMB_GS_TO_STS (1<<5)
#define AMDSMB_GS_HCYC_STS (1<<4)
#define AMDSMB_GS_HST_STS (1<<3)
#define AMDSMB_GS_ABRT_STS (1<<0)
#define AMDSMB_GS_CLEAR_STS (AMDSMB_GS_TO_STS|AMDSMB_GS_HCYC_STS|AMDSMB_GS_PRERR_STS|AMDSMB_GS_COL_STS|AMDSMB_GS_ABRT_STS)
-#define AMDSMB_GLOBAL_ENABLE 0xE2
+#define AMDSMB_GLOBAL_ENABLE (0x02)
#define AMDSMB_GE_ABORT (1<<5)
#define AMDSMB_GE_HCYC_EN (1<<4)
#define AMDSMB_GE_HOST_STC (1<<3)
#define AMDSMB_GE_CYC_PROCCALL 4
#define AMDSMB_GE_CYC_BLOCK 5
-#define AMDSMB_HSTADDR 0xE4
-#define AMDSMB_HSTDATA 0xE6
-#define AMDSMB_HSTCMD 0xE8
-#define AMDSMB_HSTDFIFO 0xE9
-#define AMDSMB_HSLVDATA 0xEA
-#define AMDSMB_HSLVDA 0xEC
-#define AMDSMB_HSLVDDR 0xEE
-#define AMDSMB_SNPADDR 0xEF
+#define AMDSMB_HSTADDR (0x04)
+#define AMDSMB_HSTDATA (0x06)
+#define AMDSMB_HSTCMD (0x08)
+#define AMDSMB_HSTDFIFO (0x09)
+#define AMDSMB_HSLVDATA (0x0A)
+#define AMDSMB_HSLVDA (0x0C)
+#define AMDSMB_HSLVDDR (0x0E)
+#define AMDSMB_SNPADDR (0x0F)
struct amdpm_softc {
int base;
int rid;
struct resource *res;
- bus_space_tag_t smbst;
- bus_space_handle_t smbsh;
-};
+ bus_space_tag_t smbst;
+ bus_space_handle_t smbsh;
-struct amdsmb_softc {
- int base;
device_t smbus;
- struct amdpm_softc *amdpm;
};
-#define AMDPM_SMBINB(amdsmb,register) \
- (bus_space_read_1(amdsmb->amdpm->smbst, amdsmb->amdpm->smbsh, register))
-#define AMDPM_SMBOUTB(amdsmb,register,value) \
- (bus_space_write_1(amdsmb->amdpm->smbst, amdsmb->amdpm->smbsh, register, value))
-#define AMDPM_SMBINW(amdsmb,register) \
- (bus_space_read_2(amdsmb->amdpm->smbst, amdsmb->amdpm->smbsh, register))
-#define AMDPM_SMBOUTW(amdsmb,register,value) \
- (bus_space_write_2(amdsmb->amdpm->smbst, amdsmb->amdpm->smbsh, register, value))
-
-static int amdsmb_probe(device_t);
-static int amdsmb_attach(device_t);
-static int amdsmb_smb_callback(device_t, int, caddr_t *);
-static int amdsmb_smb_quick(device_t dev, u_char slave, int how);
-static int amdsmb_smb_sendb(device_t dev, u_char slave, char byte);
-static int amdsmb_smb_recvb(device_t dev, u_char slave, char *byte);
-static int amdsmb_smb_writeb(device_t dev, u_char slave, char cmd, char byte);
-static int amdsmb_smb_readb(device_t dev, u_char slave, char cmd, char *byte);
-static int amdsmb_smb_writew(device_t dev, u_char slave, char cmd, short word);
-static int amdsmb_smb_readw(device_t dev, u_char slave, char cmd, short *word);
-static int amdsmb_smb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf);
-static int amdsmb_smb_bread(device_t dev, u_char slave, char cmd, u_char count, char *byte);
-
-static int amdpm_probe(device_t);
-static int amdpm_attach(device_t);
-
+#define AMDPM_SMBINB(amdpm,register) \
+ (bus_space_read_1(amdpm->smbst, amdpm->smbsh, register))
+#define AMDPM_SMBOUTB(amdpm,register,value) \
+ (bus_space_write_1(amdpm->smbst, amdpm->smbsh, register, value))
+#define AMDPM_SMBINW(amdpm,register) \
+ (bus_space_read_2(amdpm->smbst, amdpm->smbsh, register))
+#define AMDPM_SMBOUTW(amdpm,register,value) \
+ (bus_space_write_2(amdpm->smbst, amdpm->smbsh, register, value))
static int
amdpm_probe(device_t dev)
{
u_long base;
-
- if ((pci_get_vendor(dev) == AMDPM_VENDORID_AMD) &&
- (pci_get_device(dev) == AMDPM_DEVICEID_AMD756PM)) {
- device_set_desc(dev, "AMD 756 Power Management Controller");
-
- /*
+ u_int16_t vid;
+ u_int16_t did;
+
+ vid = pci_get_vendor(dev);
+ did = pci_get_device(dev);
+ if ((vid == AMDPM_VENDORID_AMD) &&
+ ((did == AMDPM_DEVICEID_AMD756PM) ||
+ (did == AMDPM_DEVICEID_AMD766PM) ||
+ (did == AMDPM_DEVICEID_AMD768PM))) {
+ device_set_desc(dev, "AMD 756/766/768 Power Management Controller");
+
+ /*
* We have to do this, since the BIOS won't give us the
* resource info (not mine, anyway).
*/
base = pci_read_config(dev, AMDPCI_PMBASE, 4);
base &= 0xff00;
- bus_set_resource(dev, SYS_RES_IOPORT, AMDPCI_PMBASE, base, 256);
+ bus_set_resource(dev, SYS_RES_IOPORT, AMDPCI_PMBASE,
+ base+0xe0, 32);
return (0);
}
+
+ if ((vid == AMDPM_VENDORID_NVIDIA) &&
+ (did == AMDPM_DEVICEID_NF_SMB)) {
+ device_set_desc(dev, "nForce SMBus Controller");
+
+ /*
+ * We have to do this, since the BIOS won't give us the
+ * resource info (not mine, anyway).
+ */
+ base = pci_read_config(dev, NFPCI_PMBASE, 4);
+ base &= 0xff00;
+ bus_set_resource(dev, SYS_RES_IOPORT, NFPCI_PMBASE,
+ base, 32);
+
+ return (0);
+ }
+
return ENXIO;
}
{
struct amdpm_softc *amdpm_sc = device_get_softc(dev);
u_char val_b;
- int unit = device_get_unit(dev);
- device_t smbinterface;
-
+
/* Enable I/O block access */
val_b = pci_read_config(dev, AMDPCI_GEN_CONFIG_PM, 1);
pci_write_config(dev, AMDPCI_GEN_CONFIG_PM, val_b | AMDPCI_PMIOEN, 1);
/* Allocate I/O space */
- amdpm_sc->rid = AMDPCI_PMBASE;
+ if (pci_get_vendor(dev) == AMDPM_VENDORID_AMD)
+ amdpm_sc->rid = AMDPCI_PMBASE;
+ else
+ amdpm_sc->rid = NFPCI_PMBASE;
amdpm_sc->res = bus_alloc_resource(dev, SYS_RES_IOPORT, &amdpm_sc->rid, 0, ~0, 1, RF_ACTIVE);
-
+
if (amdpm_sc->res == NULL) {
device_printf(dev, "could not map i/o space\n");
return (ENXIO);
- }
+ }
amdpm_sc->smbst = rman_get_bustag(amdpm_sc->res);
amdpm_sc->smbsh = rman_get_bushandle(amdpm_sc->res);
-
- smbinterface = device_add_child(dev, "amdsmb", unit);
- if (!smbinterface)
- device_printf(dev, "could not add SMBus device\n");
- else
- device_probe_and_attach(smbinterface);
-
- return (0);
-}
-
-static int
-amdsmb_probe(device_t dev)
-{
- struct amdsmb_softc *amdsmb_sc = (struct amdsmb_softc *)device_get_softc(dev);
/* Allocate a new smbus device */
- amdsmb_sc->smbus = smbus_alloc_bus(dev);
- if (!amdsmb_sc->smbus)
- return (EINVAL);
+ amdpm_sc->smbus = device_add_child(dev, "smbus", -1);
+ if (!amdpm_sc->smbus)
+ return (EINVAL);
- device_set_desc(dev, "AMD 756 SMBus interface");
- device_printf(dev, "AMD 756 SMBus interface\n");
+ bus_generic_attach(dev);
return (0);
}
static int
-amdsmb_attach(device_t dev)
+amdpm_detach(device_t dev)
{
- struct amdsmb_softc *amdsmb_sc = (struct amdsmb_softc *)device_get_softc(dev);
+ struct amdpm_softc *amdpm_sc = device_get_softc(dev);
- amdsmb_sc->amdpm = device_get_softc(device_get_parent(dev));
-
- /* Probe and attach the smbus */
- device_probe_and_attach(amdsmb_sc->smbus);
+ if (amdpm_sc->smbus) {
+ device_delete_child(dev, amdpm_sc->smbus);
+ amdpm_sc->smbus = NULL;
+ }
+
+ if (amdpm_sc->res)
+ bus_release_resource(dev, SYS_RES_IOPORT, amdpm_sc->rid,
+ amdpm_sc->res);
return (0);
}
static int
-amdsmb_smb_callback(device_t dev, int index, caddr_t *data)
+amdpm_callback(device_t dev, int index, caddr_t *data)
{
int error = 0;
}
static int
-amdsmb_clear(struct amdsmb_softc *sc)
+amdpm_clear(struct amdpm_softc *sc)
{
AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_STATUS, AMDSMB_GS_CLEAR_STS);
DELAY(10);
#if 0
static int
-amdsmb_abort(struct amdsmb_softc *sc)
+amdpm_abort(struct amdpm_softc *sc)
{
u_short l;
-
+
l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE);
AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, l | AMDSMB_GE_ABORT);
#endif
static int
-amdsmb_idle(struct amdsmb_softc *sc)
+amdpm_idle(struct amdpm_softc *sc)
{
u_short sts;
* Poll the SMBus controller
*/
static int
-amdsmb_wait(struct amdsmb_softc *sc)
+amdpm_wait(struct amdpm_softc *sc)
{
int count = 10000;
u_short sts = 0;
error |= SMB_EBUSERR;
if (error != SMB_ENOERR)
- amdsmb_clear(sc);
+ amdpm_clear(sc);
return (error);
}
static int
-amdsmb_smb_quick(device_t dev, u_char slave, int how)
+amdpm_quick(device_t dev, u_char slave, int how)
{
- struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev);
+ struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev);
int error;
u_short l;
- amdsmb_clear(sc);
- if (!amdsmb_idle(sc))
+ amdpm_clear(sc);
+ if (!amdpm_idle(sc))
return (EBUSY);
switch (how) {
l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE);
AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_QUICK | AMDSMB_GE_HOST_STC);
- error = amdsmb_wait(sc);
+ error = amdpm_wait(sc);
AMDPM_DEBUG(kprintf(", error=0x%x\n", error));
}
static int
-amdsmb_smb_sendb(device_t dev, u_char slave, char byte)
+amdpm_sendb(device_t dev, u_char slave, char byte)
{
- struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev);
+ struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev);
int error;
u_short l;
- amdsmb_clear(sc);
- if (!amdsmb_idle(sc))
+ amdpm_clear(sc);
+ if (!amdpm_idle(sc))
return (SMB_EBUSY);
AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave & ~LSB);
l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE);
AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_BYTE | AMDSMB_GE_HOST_STC);
- error = amdsmb_wait(sc);
+ error = amdpm_wait(sc);
AMDPM_DEBUG(kprintf("amdpm: SENDB to 0x%x, byte=0x%x, error=0x%x\n", slave, byte, error));
}
static int
-amdsmb_smb_recvb(device_t dev, u_char slave, char *byte)
+amdpm_recvb(device_t dev, u_char slave, char *byte)
{
- struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev);
+ struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev);
int error;
u_short l;
- amdsmb_clear(sc);
- if (!amdsmb_idle(sc))
+ amdpm_clear(sc);
+ if (!amdpm_idle(sc))
return (SMB_EBUSY);
AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave | LSB);
l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE);
AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_BYTE | AMDSMB_GE_HOST_STC);
- if ((error = amdsmb_wait(sc)) == SMB_ENOERR)
+ if ((error = amdpm_wait(sc)) == SMB_ENOERR)
*byte = AMDPM_SMBINW(sc, AMDSMB_HSTDATA);
AMDPM_DEBUG(kprintf("amdpm: RECVB from 0x%x, byte=0x%x, error=0x%x\n", slave, *byte, error));
}
static int
-amdsmb_smb_writeb(device_t dev, u_char slave, char cmd, char byte)
+amdpm_writeb(device_t dev, u_char slave, char cmd, char byte)
{
- struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev);
+ struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev);
int error;
u_short l;
- amdsmb_clear(sc);
- if (!amdsmb_idle(sc))
+ amdpm_clear(sc);
+ if (!amdpm_idle(sc))
return (SMB_EBUSY);
AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave & ~LSB);
l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE);
AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_BDATA | AMDSMB_GE_HOST_STC);
- error = amdsmb_wait(sc);
+ error = amdpm_wait(sc);
AMDPM_DEBUG(kprintf("amdpm: WRITEB to 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, byte, error));
}
static int
-amdsmb_smb_readb(device_t dev, u_char slave, char cmd, char *byte)
+amdpm_readb(device_t dev, u_char slave, char cmd, char *byte)
{
- struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev);
+ struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev);
int error;
u_short l;
- amdsmb_clear(sc);
- if (!amdsmb_idle(sc))
+ amdpm_clear(sc);
+ if (!amdpm_idle(sc))
return (SMB_EBUSY);
AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave | LSB);
l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE);
AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_BDATA | AMDSMB_GE_HOST_STC);
- if ((error = amdsmb_wait(sc)) == SMB_ENOERR)
+ if ((error = amdpm_wait(sc)) == SMB_ENOERR)
*byte = AMDPM_SMBINW(sc, AMDSMB_HSTDATA);
AMDPM_DEBUG(kprintf("amdpm: READB from 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, *byte, error));
}
static int
-amdsmb_smb_writew(device_t dev, u_char slave, char cmd, short word)
+amdpm_writew(device_t dev, u_char slave, char cmd, short word)
{
- struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev);
+ struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev);
int error;
u_short l;
- amdsmb_clear(sc);
- if (!amdsmb_idle(sc))
+ amdpm_clear(sc);
+ if (!amdpm_idle(sc))
return (SMB_EBUSY);
AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave & ~LSB);
l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE);
AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_WDATA | AMDSMB_GE_HOST_STC);
- error = amdsmb_wait(sc);
+ error = amdpm_wait(sc);
AMDPM_DEBUG(kprintf("amdpm: WRITEW to 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, word, error));
}
static int
-amdsmb_smb_readw(device_t dev, u_char slave, char cmd, short *word)
+amdpm_readw(device_t dev, u_char slave, char cmd, short *word)
{
- struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev);
+ struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev);
int error;
u_short l;
- amdsmb_clear(sc);
- if (!amdsmb_idle(sc))
+ amdpm_clear(sc);
+ if (!amdpm_idle(sc))
return (SMB_EBUSY);
AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave | LSB);
l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE);
AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_WDATA | AMDSMB_GE_HOST_STC);
- if ((error = amdsmb_wait(sc)) == SMB_ENOERR)
+ if ((error = amdpm_wait(sc)) == SMB_ENOERR)
*word = AMDPM_SMBINW(sc, AMDSMB_HSTDATA);
AMDPM_DEBUG(kprintf("amdpm: READW from 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, *word, error));
}
static int
-amdsmb_smb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf)
+amdpm_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf)
{
- struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev);
+ struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev);
u_char remain, len, i;
int error = SMB_ENOERR;
u_short l;
- amdsmb_clear(sc);
- if(!amdsmb_idle(sc))
+ amdpm_clear(sc);
+ if(!amdpm_idle(sc))
return (SMB_EBUSY);
remain = count;
len = min(remain, 32);
AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave & ~LSB);
-
+
/*
* Do we have to reset the internal 32-byte buffer?
* Can't see how to do this from the data sheet.
l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE);
AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_BLOCK | AMDSMB_GE_HOST_STC);
- if ((error = amdsmb_wait(sc)) != SMB_ENOERR)
+ if ((error = amdpm_wait(sc)) != SMB_ENOERR)
goto error;
remain -= len;
}
static int
-amdsmb_smb_bread(device_t dev, u_char slave, char cmd, u_char count, char *buf)
+amdpm_bread(device_t dev, u_char slave, char cmd, u_char count, char *buf)
{
- struct amdsmb_softc *sc = (struct amdsmb_softc *)device_get_softc(dev);
+ struct amdpm_softc *sc = (struct amdpm_softc *)device_get_softc(dev);
u_char remain, len, i;
int error = SMB_ENOERR;
u_short l;
- amdsmb_clear(sc);
- if (!amdsmb_idle(sc))
+ amdpm_clear(sc);
+ if (!amdpm_idle(sc))
return (SMB_EBUSY);
remain = count;
while (remain) {
AMDPM_SMBOUTW(sc, AMDSMB_HSTADDR, slave | LSB);
-
+
AMDPM_SMBOUTB(sc, AMDSMB_HSTCMD, cmd);
l = AMDPM_SMBINW(sc, AMDSMB_GLOBAL_ENABLE);
AMDPM_SMBOUTW(sc, AMDSMB_GLOBAL_ENABLE, (l & 0xfff8) | AMDSMB_GE_CYC_BLOCK | AMDSMB_GE_HOST_STC);
-
- if ((error = amdsmb_wait(sc)) != SMB_ENOERR)
+
+ if ((error = amdpm_wait(sc)) != SMB_ENOERR)
goto error;
len = AMDPM_SMBINW(sc, AMDSMB_HSTDATA);
/* Device interface */
DEVMETHOD(device_probe, amdpm_probe),
DEVMETHOD(device_attach, amdpm_attach),
-
+ DEVMETHOD(device_detach, amdpm_detach),
+
+ /* SMBus interface */
+ DEVMETHOD(smbus_callback, amdpm_callback),
+ DEVMETHOD(smbus_quick, amdpm_quick),
+ DEVMETHOD(smbus_sendb, amdpm_sendb),
+ DEVMETHOD(smbus_recvb, amdpm_recvb),
+ DEVMETHOD(smbus_writeb, amdpm_writeb),
+ DEVMETHOD(smbus_readb, amdpm_readb),
+ DEVMETHOD(smbus_writew, amdpm_writew),
+ DEVMETHOD(smbus_readw, amdpm_readw),
+ DEVMETHOD(smbus_bwrite, amdpm_bwrite),
+ DEVMETHOD(smbus_bread, amdpm_bread),
+
{ 0, 0 }
};
sizeof(struct amdpm_softc),
};
-static devclass_t amdsmb_devclass;
-
-static device_method_t amdsmb_methods[] = {
- /* Device interface */
- DEVMETHOD(device_probe, amdsmb_probe),
- DEVMETHOD(device_attach, amdsmb_attach),
-
- /* Bus interface */
- DEVMETHOD(bus_print_child, bus_generic_print_child),
-
- /* SMBus interface */
- DEVMETHOD(smbus_callback, amdsmb_smb_callback),
- DEVMETHOD(smbus_quick, amdsmb_smb_quick),
- DEVMETHOD(smbus_sendb, amdsmb_smb_sendb),
- DEVMETHOD(smbus_recvb, amdsmb_smb_recvb),
- DEVMETHOD(smbus_writeb, amdsmb_smb_writeb),
- DEVMETHOD(smbus_readb, amdsmb_smb_readb),
- DEVMETHOD(smbus_writew, amdsmb_smb_writew),
- DEVMETHOD(smbus_readw, amdsmb_smb_readw),
- DEVMETHOD(smbus_bwrite, amdsmb_smb_bwrite),
- DEVMETHOD(smbus_bread, amdsmb_smb_bread),
-
- { 0, 0 }
-};
-
-static driver_t amdsmb_driver = {
- "amdsmb",
- amdsmb_methods,
- sizeof(struct amdsmb_softc),
-};
-
DRIVER_MODULE(amdpm, pci, amdpm_driver, amdpm_devclass, 0, 0);
-DRIVER_MODULE(amdsmb, amdpm, amdsmb_driver, amdsmb_devclass, 0, 0);
+
+MODULE_DEPEND(amdpm, pci, 1, 1, 1);
+MODULE_DEPEND(amdpm, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER);
+MODULE_VERSION(amdpm, 1);
+++ /dev/null
-/*-
- * Copyright (c) 1998, 1999 Takanori Watanabe
- * 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: src/sys/pci/intpm.c,v 1.16.2.1 2001/12/23 08:17:47 pirzyk Exp $
- * $DragonFly: src/sys/dev/powermng/i386/intpm/intpm.c,v 1.11 2006/12/22 23:26:23 swildner Exp $
- */
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/uio.h>
-#include <sys/module.h>
-#include <sys/bus.h>
-#include <sys/conf.h>
-#include <sys/malloc.h>
-#include <sys/buf.h>
-#include <sys/rman.h>
-#include <sys/thread2.h>
-
-#include <machine/clock.h>
-
-#include <bus/smbus/smbconf.h>
-
-#include "smbus_if.h"
-
-/*This should be removed if force_pci_map_int supported*/
-#include <sys/interrupt.h>
-
-#include <bus/pci/pcireg.h>
-#include <bus/pci/pcivar.h>
-#include "intpmreg.h"
-
-#include "opt_intpm.h"
-
-static struct _pcsid
-{
- pcidi_t type;
- char *desc;
-} pci_ids[] =
-{
- { 0x71138086,"Intel 82371AB Power management controller"},
- { 0x719b8086,"Intel 82443MX Power management controller"},
- { 0x00000000, NULL }
-};
-static int intsmb_probe(device_t);
-static int intsmb_attach(device_t);
-
-static int intsmb_intr(device_t dev);
-static int intsmb_slvintr(device_t dev);
-static void intsmb_alrintr(device_t dev);
-static int intsmb_callback(device_t dev, int index, caddr_t data);
-static int intsmb_quick(device_t dev, u_char slave, int how);
-static int intsmb_sendb(device_t dev, u_char slave, char byte);
-static int intsmb_recvb(device_t dev, u_char slave, char *byte);
-static int intsmb_writeb(device_t dev, u_char slave, char cmd, char byte);
-static int intsmb_writew(device_t dev, u_char slave, char cmd, short word);
-static int intsmb_readb(device_t dev, u_char slave, char cmd, char *byte);
-static int intsmb_readw(device_t dev, u_char slave, char cmd, short *word);
-static int intsmb_pcall(device_t dev, u_char slave, char cmd, short sdata, short *rdata);
-static int intsmb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf);
-static int intsmb_bread(device_t dev, u_char slave, char cmd, u_char count, char *buf);
-static void intsmb_start(device_t dev,u_char cmd,int nointr);
-static int intsmb_stop(device_t dev);
-static int intsmb_stop_poll(device_t dev);
-static int intsmb_free(device_t dev);
-static int intpm_probe (device_t dev);
-static int intpm_attach (device_t dev);
-static devclass_t intsmb_devclass;
-
-static device_method_t intpm_methods[]={
- DEVMETHOD(device_probe,intsmb_probe),
- DEVMETHOD(device_attach,intsmb_attach),
-
- DEVMETHOD(bus_print_child, bus_generic_print_child),
-
- DEVMETHOD(smbus_callback,intsmb_callback),
- DEVMETHOD(smbus_quick,intsmb_quick),
- DEVMETHOD(smbus_sendb,intsmb_sendb),
- DEVMETHOD(smbus_recvb,intsmb_recvb),
- DEVMETHOD(smbus_writeb,intsmb_writeb),
- DEVMETHOD(smbus_writew,intsmb_writew),
- DEVMETHOD(smbus_readb,intsmb_readb),
- DEVMETHOD(smbus_readw,intsmb_readw),
- DEVMETHOD(smbus_pcall,intsmb_pcall),
- DEVMETHOD(smbus_bwrite,intsmb_bwrite),
- DEVMETHOD(smbus_bread,intsmb_bread),
- {0,0}
-};
-
-struct intpm_pci_softc{
- bus_space_tag_t smbst;
- bus_space_handle_t smbsh;
- bus_space_tag_t pmst;
- bus_space_handle_t pmsh;
- pcici_t cfg;
- device_t smbus;
-};
-
-
-struct intsmb_softc{
- struct intpm_pci_softc *pci_sc;
- bus_space_tag_t st;
- bus_space_handle_t sh;
- device_t smbus;
- int isbusy;
-};
-
-static driver_t intpm_driver = {
- "intsmb",
- intpm_methods,
- sizeof(struct intsmb_softc),
-};
-
-static devclass_t intpm_devclass;
-static device_method_t intpm_pci_methods[] = {
- DEVMETHOD(device_probe,intpm_probe),
- DEVMETHOD(device_attach,intpm_attach),
- {0,0}
-};
-static driver_t intpm_pci_driver = {
- "intpm",
- intpm_pci_methods,
- sizeof(struct intpm_pci_softc)
-};
-
-static int
-intsmb_probe(device_t dev)
-{
- struct intsmb_softc *sc =(struct intsmb_softc *) device_get_softc(dev);
- sc->smbus=smbus_alloc_bus(dev);
- if (!sc->smbus)
- return (EINVAL); /* XXX don't know what to return else */
- device_set_desc(dev,"Intel PIIX4 SMBUS Interface");
-
- return (0); /* XXX don't know what to return else */
-}
-static int
-intsmb_attach(device_t dev)
-{
- struct intsmb_softc *sc = (struct intsmb_softc *)device_get_softc(dev);
- sc->pci_sc=device_get_softc(device_get_parent(dev));
- sc->isbusy=0;
- sc->sh=sc->pci_sc->smbsh;
- sc->st=sc->pci_sc->smbst;
- sc->pci_sc->smbus=dev;
- device_probe_and_attach(sc->smbus);
-#ifdef ENABLE_ALART
- /*Enable Arart*/
- bus_space_write_1(sc->st,sc->sh,PIIX4_SMBSLVCNT,
- PIIX4_SMBSLVCNT_ALTEN);
-#endif
- return (0);
-}
-
-static int
-intsmb_callback(device_t dev, int index, caddr_t data)
-{
- int error = 0;
-
- crit_enter();
- switch (index) {
- case SMB_REQUEST_BUS:
- break;
- case SMB_RELEASE_BUS:
- break;
- default:
- error = EINVAL;
- }
- crit_exit();
- return (error);
-}
-/*counterpart of smbtx_smb_free*/
-static int
-intsmb_free(device_t dev){
- struct intsmb_softc *sc = (struct intsmb_softc *)device_get_softc(dev);
- if((bus_space_read_1(sc->st,sc->sh,PIIX4_SMBHSTSTS)&
- PIIX4_SMBHSTSTAT_BUSY)
-#ifdef ENABLE_ALART
- ||(bus_space_read_1(sc->st,sc->sh,PIIX4_SMBSLVSTS)&
- PIIX4_SMBSLVSTS_BUSY)
-#endif
- || sc->isbusy)
- return EBUSY;
- crit_enter();
- sc->isbusy=1;
- /*Disable Intrrupt in slave part*/
-#ifndef ENABLE_ALART
- bus_space_write_1(sc->st,sc->sh,PIIX4_SMBSLVCNT,0);
-#endif
- /*Reset INTR Flag to prepare INTR*/
- bus_space_write_1(sc->st,sc->sh,PIIX4_SMBHSTSTS,
- (PIIX4_SMBHSTSTAT_INTR|
- PIIX4_SMBHSTSTAT_ERR|
- PIIX4_SMBHSTSTAT_BUSC|
- PIIX4_SMBHSTSTAT_FAIL)
- );
- crit_exit();
- return 0;
-}
-
-static int
-intsmb_intr(device_t dev)
-{
- struct intsmb_softc *sc = (struct intsmb_softc *)device_get_softc(dev);
- int status;
- status=bus_space_read_1(sc->st,sc->sh,PIIX4_SMBHSTSTS);
- if(status&PIIX4_SMBHSTSTAT_BUSY){
- return 1;
-
- }
- if(status&(PIIX4_SMBHSTSTAT_INTR|
- PIIX4_SMBHSTSTAT_ERR|
- PIIX4_SMBHSTSTAT_BUSC|
- PIIX4_SMBHSTSTAT_FAIL)){
- int tmp;
- tmp=bus_space_read_1(sc->st,sc->sh,PIIX4_SMBHSTCNT);
- bus_space_write_1(sc->st,sc->sh,PIIX4_SMBHSTCNT,
- tmp&~PIIX4_SMBHSTCNT_INTREN);
- if(sc->isbusy){
- sc->isbusy=0;
- wakeup(sc);
- }
- return 0;
- }
- return 1;/* Not Completed*/
-}
-static int
-intsmb_slvintr(device_t dev)
-{
- struct intsmb_softc *sc = (struct intsmb_softc *)device_get_softc(dev);
- int status,retval;
- retval=1;
- status=bus_space_read_1(sc->st,sc->sh,PIIX4_SMBSLVSTS);
- if(status&PIIX4_SMBSLVSTS_BUSY)
- return retval;
- if(status&PIIX4_SMBSLVSTS_ALART){
- intsmb_alrintr(dev);
- retval=0;
- }else if(status&~(PIIX4_SMBSLVSTS_ALART|PIIX4_SMBSLVSTS_SDW2
- |PIIX4_SMBSLVSTS_SDW1)){
- retval=0;
- }
- /*Reset Status Register*/
- bus_space_write_1(sc->st,sc->sh,PIIX4_SMBSLVSTS,PIIX4_SMBSLVSTS_ALART|
- PIIX4_SMBSLVSTS_SDW2|PIIX4_SMBSLVSTS_SDW1|
- PIIX4_SMBSLVSTS_SLV);
- return retval;
-}
-
-static void intsmb_alrintr(device_t dev)
-{
- struct intsmb_softc *sc = (struct intsmb_softc *)device_get_softc(dev);
- int slvcnt;
-#ifdef ENABLE_ALART
- int error;
-#endif
-
- /*stop generating INTR from ALART*/
- slvcnt=bus_space_read_1(sc->st,sc->sh,PIIX4_SMBSLVCNT);
-#ifdef ENABLE_ALART
- bus_space_write_1(sc->st,sc->sh,PIIX4_SMBSLVCNT,
- slvcnt&~PIIX4_SMBSLVCNT_ALTEN) ;
-#endif
- DELAY(5);
- /*ask bus who assert it and then ask it what's the matter. */
-#ifdef ENABLE_ALART
- error=intsmb_free(dev);
- if(!error){
- bus_space_write_1(sc->st,sc->sh,PIIX4_SMBHSTADD,SMBALTRESP
- |LSB);
- intsmb_start(dev,PIIX4_SMBHSTCNT_PROT_BYTE,1);
- if(!(error=intsmb_stop_poll(dev))){
- uint32_t addr;
- addr = bus_space_read_1(sc->st,sc->sh,
- PIIX4_SMBHSTDAT0);
- kprintf("ALART_RESPONSE: %#x\n", addr);
- }
- }else{
- kprintf("ERROR\n");
- }
-
- /*Re-enable INTR from ALART*/
- bus_space_write_1(sc->st,sc->sh,PIIX4_SMBSLVCNT,
- slvcnt|PIIX4_SMBSLVCNT_ALTEN) ;
- DELAY(5);
-#endif
-
- return;
-}
-static void
-intsmb_start(device_t dev,unsigned char cmd,int nointr)
-{
- struct intsmb_softc *sc = (struct intsmb_softc *)device_get_softc(dev);
- unsigned char tmp;
- tmp=bus_space_read_1(sc->st,sc->sh,PIIX4_SMBHSTCNT);
- tmp&= 0xe0;
- tmp |= cmd;
- tmp |=PIIX4_SMBHSTCNT_START;
- /*While not in autoconfiguration Intrrupt Enabled*/
- if(!cold||!nointr)
- tmp |=PIIX4_SMBHSTCNT_INTREN;
- bus_space_write_1(sc->st,sc->sh,PIIX4_SMBHSTCNT,tmp);
-}
-
-/*Polling Code. Polling is not encouraged
- * because It is required to wait for the device get busy.
- *(29063505.pdf from Intel)
- * But during boot,intrrupt cannot be used.
- * so use polling code while in autoconfiguration.
- */
-
-static int
-intsmb_stop_poll(device_t dev){
- int error,i;
- struct intsmb_softc *sc = (struct intsmb_softc *)device_get_softc(dev);
-
- /*
- * In smbtx driver ,Simply waiting.
- * This loops 100-200 times.
- */
- for(i=0;i<0x7fff;i++){
- if((bus_space_read_1(sc->st,sc->sh,PIIX4_SMBHSTSTS)
- &PIIX4_SMBHSTSTAT_BUSY)){
- break;
- }
- }
- for(i=0;i<0x7fff;i++){
- int status;
- status=bus_space_read_1(sc->st,sc->sh,PIIX4_SMBHSTSTS);
- if(!(status&PIIX4_SMBHSTSTAT_BUSY)){
- sc->isbusy=0;
- error=(status&PIIX4_SMBHSTSTAT_ERR)?EIO :
- (status&PIIX4_SMBHSTSTAT_BUSC)?EBUSY:
- (status&PIIX4_SMBHSTSTAT_FAIL)?EIO:0;
- if(error==0&&!(status&PIIX4_SMBHSTSTAT_INTR)){
- kprintf("unknown cause why?");
- }
- return error;
- }
- }
- {
- int tmp;
- sc->isbusy=0;
- tmp=bus_space_read_1(sc->st,sc->sh,PIIX4_SMBHSTCNT);
- bus_space_write_1(sc->st,sc->sh,PIIX4_SMBHSTCNT,
- tmp&~PIIX4_SMBHSTCNT_INTREN);
- }
- return EIO;
-}
-/*
- *wait for completion and return result.
- */
-static int
-intsmb_stop(device_t dev){
- int error;
- struct intsmb_softc *sc = (struct intsmb_softc *)device_get_softc(dev);
- if(cold){
- /*So that it can use device during probing device on SMBus.*/
- error=intsmb_stop_poll(dev);
- return error;
- }else{
- if(!tsleep(sc, PCATCH, "SMBWAI", hz/8)){
- int status;
- status=bus_space_read_1(sc->st,sc->sh,PIIX4_SMBHSTSTS);
- if(!(status&PIIX4_SMBHSTSTAT_BUSY)){
- error=(status&PIIX4_SMBHSTSTAT_ERR)?EIO :
- (status&PIIX4_SMBHSTSTAT_BUSC)?EBUSY:
- (status&PIIX4_SMBHSTSTAT_FAIL)?EIO:0;
- if(error==0&&!(status&PIIX4_SMBHSTSTAT_INTR)){
- kprintf("intsmb%d:unknown cause why?\n",
- device_get_unit(dev));
- }
-#ifdef ENABLE_ALART
- bus_space_write_1(sc->st,sc->sh,
- PIIX4_SMBSLVCNT,PIIX4_SMBSLVCNT_ALTEN);
-#endif
- return error;
- }
- }
- }
- /*Timeout Procedure*/
- crit_enter();
- sc->isbusy=0;
- /*Re-enable supressed intrrupt from slave part*/
- bus_space_write_1(sc->st,sc->sh,
- PIIX4_SMBSLVCNT,PIIX4_SMBSLVCNT_ALTEN);
- crit_exit();
- return EIO;
-}
-
-static int
-intsmb_quick(device_t dev, u_char slave, int how)
-{
- int error=0;
- u_char data;
- struct intsmb_softc *sc = (struct intsmb_softc *)device_get_softc(dev);
- data=slave;
- /*Quick command is part of Address, I think*/
- switch(how){
- case SMB_QWRITE:
- data&=~LSB;
- break;
- case SMB_QREAD:
- data|=LSB;
- break;
- default:
- error=EINVAL;
- }
- if(!error){
- error=intsmb_free(dev);
- if(!error){
- bus_space_write_1(sc->st,sc->sh,
- PIIX4_SMBHSTADD,data);
- intsmb_start(dev,PIIX4_SMBHSTCNT_PROT_QUICK,0);
- error=intsmb_stop(dev);
- }
- }
-
- return (error);
-}
-
-static int
-intsmb_sendb(device_t dev, u_char slave, char byte)
-{
- int error;
- struct intsmb_softc *sc = (struct intsmb_softc *)device_get_softc(dev);
- error=intsmb_free(dev);
- if(!error){
- bus_space_write_1(sc->st,sc->sh,PIIX4_SMBHSTADD,slave&~LSB);
- bus_space_write_1(sc->st,sc->sh,PIIX4_SMBHSTCMD,byte);
- intsmb_start(dev,PIIX4_SMBHSTCNT_PROT_BYTE,0);
- error=intsmb_stop(dev);
- }
- return (error);
-}
-static int
-intsmb_recvb(device_t dev, u_char slave, char *byte)
-{
- int error;
- struct intsmb_softc *sc = (struct intsmb_softc *)device_get_softc(dev);
- error=intsmb_free(dev);
- if(!error){
- bus_space_write_1(sc->st,sc->sh,PIIX4_SMBHSTADD,slave
- |LSB);
- intsmb_start(dev,PIIX4_SMBHSTCNT_PROT_BYTE,0);
- if(!(error=intsmb_stop(dev))){
-#ifdef RECV_IS_IN_CMD
- /*Linux SMBus stuff also troubles
- Because Intel's datasheet will not make clear.
- */
- *byte=bus_space_read_1(sc->st,sc->sh,
- PIIX4_SMBHSTCMD);
-#else
- *byte=bus_space_read_1(sc->st,sc->sh,
- PIIX4_SMBHSTDAT0);
-#endif
- }
- }
- return (error);
-}
-static int
-intsmb_writeb(device_t dev, u_char slave, char cmd, char byte)
-{
- int error;
- struct intsmb_softc *sc = (struct intsmb_softc *)device_get_softc(dev);
- error=intsmb_free(dev);
- if(!error){
- bus_space_write_1(sc->st,sc->sh,PIIX4_SMBHSTADD,slave&~LSB);
- bus_space_write_1(sc->st,sc->sh,PIIX4_SMBHSTCMD,cmd);
- bus_space_write_1(sc->st,sc->sh,PIIX4_SMBHSTDAT0,byte);
- intsmb_start(dev,PIIX4_SMBHSTCNT_PROT_BDATA,0);
- error=intsmb_stop(dev);
- }
- return (error);
-}
-static int
-intsmb_writew(device_t dev, u_char slave, char cmd, short word)
-{
- int error;
- struct intsmb_softc *sc = (struct intsmb_softc *)device_get_softc(dev);
- error=intsmb_free(dev);
- if(!error){
- bus_space_write_1(sc->st,sc->sh,PIIX4_SMBHSTADD,slave&~LSB);
- bus_space_write_1(sc->st,sc->sh,PIIX4_SMBHSTCMD,cmd);
- bus_space_write_1(sc->st,sc->sh,PIIX4_SMBHSTDAT0,
- word&0xff);
- bus_space_write_1(sc->st,sc->sh,PIIX4_SMBHSTDAT1,
- (word>>8)&0xff);
- intsmb_start(dev,PIIX4_SMBHSTCNT_PROT_WDATA,0);
- error=intsmb_stop(dev);
- }
- return (error);
-}
-
-static int
-intsmb_readb(device_t dev, u_char slave, char cmd, char *byte)
-{
- int error;
- struct intsmb_softc *sc = (struct intsmb_softc *)device_get_softc(dev);
- error=intsmb_free(dev);
- if(!error){
- bus_space_write_1(sc->st,sc->sh,PIIX4_SMBHSTADD,slave|LSB);
- bus_space_write_1(sc->st,sc->sh,PIIX4_SMBHSTCMD,cmd);
- intsmb_start(dev,PIIX4_SMBHSTCNT_PROT_BDATA,0);
- if(!(error=intsmb_stop(dev))){
- *byte=bus_space_read_1(sc->st,sc->sh,
- PIIX4_SMBHSTDAT0);
- }
- }
- return (error);
-}
-static int
-intsmb_readw(device_t dev, u_char slave, char cmd, short *word)
-{
- int error;
- struct intsmb_softc *sc = (struct intsmb_softc *)device_get_softc(dev);
- error=intsmb_free(dev);
- if(!error){
- bus_space_write_1(sc->st,sc->sh,PIIX4_SMBHSTADD,slave|LSB);
- bus_space_write_1(sc->st,sc->sh,PIIX4_SMBHSTCMD,cmd);
- intsmb_start(dev,PIIX4_SMBHSTCNT_PROT_WDATA,0);
- if(!(error=intsmb_stop(dev))){
- *word=bus_space_read_1(sc->st,sc->sh,PIIX4_SMBHSTDAT0)&0xff;
- *word|=(bus_space_read_1(sc->st,sc->sh,PIIX4_SMBHSTDAT1)&0xff)<<8;
- }
- }
- return (error);
-}
-/*
- * Data sheet claims that it implements all function, but also claims
- * that it implements 7 function and not mention PCALL. So I don't know
- * whether it will work.
- */
-static int
-intsmb_pcall(device_t dev, u_char slave, char cmd, short sdata, short *rdata)
-{
-#ifdef PROCCALL_TEST
- int error;
- struct intsmb_softc *sc = (struct intsmb_softc *)device_get_softc(dev);
- error=intsmb_free(dev);
- if(!error){
- bus_space_write_1(sc->st,sc->sh,PIIX4_SMBHSTADD,slave&~LSB);
- bus_space_write_1(sc->st,sc->sh,PIIX4_SMBHSTCMD,cmd);
- bus_space_write_1(sc->st,sc->sh,PIIX4_SMBHSTDAT0,sdata&0xff);
- bus_space_write_1(sc->st,sc->sh,PIIX4_SMBHSTDAT1,(sdata&0xff)>>8);
- intsmb_start(dev,PIIX4_SMBHSTCNT_PROT_WDATA,0);
- }
- if(!(error=intsmb_stop(dev))){
- *rdata=bus_space_read_1(sc->st,sc->sh,PIIX4_SMBHSTDAT0)&0xff;
- *rdata|=(bus_space_read_1(sc->st,sc->sh,PIIX4_SMBHSTDAT1)&0xff)<<8;
- }
- return error;
-#else
- return 0;
-#endif
-}
-static int
-intsmb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf)
-{
- int error,i;
- struct intsmb_softc *sc = (struct intsmb_softc *)device_get_softc(dev);
- error=intsmb_free(dev);
- if(count>SMBBLOCKTRANS_MAX||count==0)
- error=EINVAL;
- if(!error){
- /*Reset internal array index*/
- bus_space_read_1(sc->st,sc->sh,PIIX4_SMBHSTCNT);
-
- bus_space_write_1(sc->st,sc->sh,PIIX4_SMBHSTADD,slave&~LSB);
- bus_space_write_1(sc->st,sc->sh,PIIX4_SMBHSTCMD,cmd);
- for(i=0;i<count;i++){
- bus_space_write_1(sc->st,sc->sh,PIIX4_SMBBLKDAT,buf[i]);
- }
- bus_space_write_1(sc->st,sc->sh,PIIX4_SMBHSTDAT0,count);
- intsmb_start(dev,PIIX4_SMBHSTCNT_PROT_BLOCK,0);
- error=intsmb_stop(dev);
- }
- return (error);
-}
-
-static int
-intsmb_bread(device_t dev, u_char slave, char cmd, u_char count, char *buf)
-{
- int error,i;
- struct intsmb_softc *sc = (struct intsmb_softc *)device_get_softc(dev);
- error=intsmb_free(dev);
- if(count>SMBBLOCKTRANS_MAX||count==0)
- error=EINVAL;
- if(!error){
- /*Reset internal array index*/
- bus_space_read_1(sc->st,sc->sh,PIIX4_SMBHSTCNT);
-
- bus_space_write_1(sc->st,sc->sh,PIIX4_SMBHSTADD,slave|LSB);
- bus_space_write_1(sc->st,sc->sh,PIIX4_SMBHSTCMD,cmd);
- bus_space_write_1(sc->st,sc->sh,PIIX4_SMBHSTDAT0,count);
- intsmb_start(dev,PIIX4_SMBHSTCNT_PROT_BLOCK,0);
- error=intsmb_stop(dev);
- if(!error){
- bzero(buf,count);/*Is it needed?*/
- count= bus_space_read_1(sc->st,sc->sh,
- PIIX4_SMBHSTDAT0);
- if(count!=0&&count<=SMBBLOCKTRANS_MAX){
- for(i=0;i<count;i++){
- buf[i]=bus_space_read_1(sc->st,
- sc->sh,
- PIIX4_SMBBLKDAT);
- }
- }
- else{
- error=EIO;
- }
- }
- }
- return (error);
-}
-
-DRIVER_MODULE(intsmb, intpm , intpm_driver, intsmb_devclass, 0, 0);
-
-
-static void intpm_intr (void *arg);
-static int
-intpm_attach(device_t dev)
-{
- int value;
- int unit=device_get_unit(dev);
- void *ih;
- int error;
- char * str;
- {
- struct intpm_pci_softc *sciic;
- device_t smbinterface;
- int rid;
- struct resource *res;
-
- sciic=device_get_softc(dev);
- if(sciic==NULL){
- return ENOMEM;
- }
-
- rid=PCI_BASE_ADDR_SMB;
- res=bus_alloc_resource(dev,SYS_RES_IOPORT,&rid,
- 0,~0,1,RF_ACTIVE);
- if(res==NULL){
- device_printf(dev,"Could not allocate Bus space\n");
- return ENXIO;
- }
- sciic->smbst=rman_get_bustag(res);
- sciic->smbsh=rman_get_bushandle(res);
-
- device_printf(dev,"%s %x\n",
- (sciic->smbst==I386_BUS_SPACE_IO)?
- "I/O mapped":"Memory",
- sciic->smbsh);
-
-
-#ifndef NO_CHANGE_PCICONF
- pci_write_config(dev,PCIR_INTLINE,0x9,1);
- pci_write_config(dev,PCI_HST_CFG_SMB,
- PCI_INTR_SMB_IRQ9|PCI_INTR_SMB_ENABLE,1);
-#endif
- value=pci_read_config(dev,PCI_HST_CFG_SMB,1);
- switch(value&0xe){
- case PCI_INTR_SMB_SMI:
- str="SMI";
- break;
- case PCI_INTR_SMB_IRQ9:
- str="IRQ 9";
- break;
- default:
- str="BOGUS";
- }
- device_printf(dev,"intr %s %s ",str,((value&1)? "enabled":"disabled"));
- value=pci_read_config(dev,PCI_REVID_SMB,1);
- kprintf("revision %d\n",value);
- /*
- * Install intr HANDLER here
- */
- rid=0;
- res=bus_alloc_resource(dev,SYS_RES_IRQ,&rid,9,9,1,RF_SHAREABLE|RF_ACTIVE);
- if(res==NULL){
- device_printf(dev,"could not allocate irq");
- return ENOMEM;
- }
- error = bus_setup_intr(dev, res, 0,
- (driver_intr_t *)intpm_intr, sciic,
- &ih, NULL);
- if(error){
- device_printf(dev,"Failed to map intr\n");
- return error;
- }
- smbinterface=device_add_child(dev,"intsmb",unit);
- if(!smbinterface){
- kprintf("intsmb%d:could not add SMBus device\n",unit);
- }
- device_probe_and_attach(smbinterface);
- }
-
- value=pci_read_config(dev,PCI_BASE_ADDR_PM,4);
- kprintf("intpm%d: PM %s %x \n",unit,(value&1)?"I/O mapped":"Memory",value&0xfffe);
- return 0;
-}
-static int
-intpm_probe(device_t dev)
-{
- struct _pcsid *ep =pci_ids;
- u_int32_t device_id=pci_get_devid(dev);
-
- while (ep->type && ep->type != device_id)
- ++ep;
- if(ep->desc!=NULL){
- device_set_desc(dev,ep->desc);
- bus_set_resource(dev,SYS_RES_IRQ,0,9,1); /* XXX setup intr resource */
- return 0;
- }else{
- return ENXIO;
- }
-}
-DRIVER_MODULE(intpm, pci , intpm_pci_driver, intpm_devclass, 0, 0);
-
-static void intpm_intr(void *arg)
-{
- struct intpm_pci_softc *sc;
- sc=(struct intpm_pci_softc *)arg;
- intsmb_intr(sc->smbus);
- intsmb_slvintr(sc->smbus);
-
-}
+++ /dev/null
-/*-
- * Copyright (c) 1998, 1999 Takanori Watanabe
- * 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: src/sys/pci/intpmreg.h,v 1.2 1999/08/28 00:51:01 peter Exp $
- * $DragonFly: src/sys/dev/powermng/i386/intpm/intpmreg.h,v 1.2 2003/06/17 04:28:57 dillon Exp $
- */
-
-/*Register Difinition for Intel Chipset with ACPI Support*/
-#define PCI_BASE_ADDR_SMB 0x90 /*Where to MAP IO*/
-#define PCI_BASE_ADDR_PM 0x40
-#define PCI_HST_CFG_SMB 0xd2 /*Host Configuration*/
-#define PCI_INTR_SMB_SMI 0
-#define PCI_INTR_SMB_IRQ9 8
-#define PCI_INTR_SMB_ENABLE 1
-#define PCI_SLV_CMD_SMB 0xd3 /*SLAVE COMMAND*/
-#define PCI_SLV_SDW_SMB_1 0xd4 /*SLAVE SHADOW PORT 1*/
-#define PCI_SLV_SDW_SMB_2 0xd5 /*SLAVE SHADOW PORT 2*/
-#define PCI_REVID_SMB 0xd6
-#define LSB 0x1
-#define PIIX4_SMBHSTSTS 0x00
-#define PIIX4_SMBHSTSTAT_BUSY (1<<0)
-#define PIIX4_SMBHSTSTAT_INTR (1<<1)
-#define PIIX4_SMBHSTSTAT_ERR (1<<2)
-#define PIIX4_SMBHSTSTAT_BUSC (1<<3)
-#define PIIX4_SMBHSTSTAT_FAIL (1<<4)
-#define PIIX4_SMBSLVSTS 0x01
-#define PIIX4_SMBSLVSTS_ALART (1<<5)
-#define PIIX4_SMBSLVSTS_SDW2 (1<<4)
-#define PIIX4_SMBSLVSTS_SDW1 (1<<3)
-#define PIIX4_SMBSLVSTS_SLV (1<<2)
-#define PIIX4_SMBSLVSTS_BUSY (1<<0)
-#define PIIX4_SMBHSTCNT 0x02
-#define PIIX4_SMBHSTCNT_START (1<<6)
-#define PIIX4_SMBHSTCNT_PROT_QUICK 0
-#define PIIX4_SMBHSTCNT_PROT_BYTE (1<<2)
-#define PIIX4_SMBHSTCNT_PROT_BDATA (2<<2)
-#define PIIX4_SMBHSTCNT_PROT_WDATA (3<<2)
-#define PIIX4_SMBHSTCNT_PROT_BLOCK (5<<2)
-#define SMBBLOCKTRANS_MAX 32
-#define PIIX4_SMBHSTCNT_KILL (1<<1)
-#define PIIX4_SMBHSTCNT_INTREN (1)
-#define PIIX4_SMBHSTCMD 0x03
-#define PIIX4_SMBHSTADD 0x04
-#define PIIX4_SMBHSTDAT0 0x05
-#define PIIX4_SMBHSTDAT1 0x06
-#define PIIX4_SMBBLKDAT 0x07
-#define PIIX4_SMBSLVCNT 0x08
-#define PIIX4_SMBSLVCNT_ALTEN (1<<3)
-#define PIIX4_SMBSLVCNT_SD2EN (1<<2)
-#define PIIX4_SMBSLVCNT_SD1EN (1<<1)
-#define PIIX4_SMBSLVCNT_SLVEN (1)
-#define PIIX4_SMBSLVCMD 0x09
-#define PIIX4_SMBSLVEVT 0x0a
-#define PIIX4_SMBSLVDAT 0x0c
-/*This is SMBus alart response address*/
-#define SMBALTRESP 0x18
--- /dev/null
+#$FreeBSD: src/sys/modules/i2c/controllers/ichsmb/Makefile,v 1.1 2005/06/05 11:55:29 takawata Exp $
+
+.PATH: ${.CURDIR}/..
+KMOD = ichsmb
+SRCS = device_if.h bus_if.h iicbb_if.h pci_if.h smbus_if.h \
+ ichsmb.c ichsmb_pci.c ichsmb_reg.h ichsmb_var.h
+
+.include <bsd.kmod.mk>
-
-/*
+/*-
* ichsmb.c
*
+ * Author: Archie Cobbs <archie@freebsd.org>
* Copyright (c) 2000 Whistle Communications, Inc.
* All rights reserved.
- *
+ *
* Subject to the following obligations and disclaimer of warranty, use and
* redistribution of this software, in source or object code forms, with or
* without modifications are expressly permitted by Whistle Communications;
* Communications, Inc. trademarks, including the mark "WHISTLE
* COMMUNICATIONS" on advertising, endorsements, or otherwise except as
* such appears in the above copyright notice or in the software.
- *
+ *
* THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
* REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
* THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
- * Author: Archie Cobbs <archie@freebsd.org>
- *
- * $FreeBSD: src/sys/dev/ichsmb/ichsmb.c,v 1.1.2.1 2000/10/09 00:52:43 archie Exp $
- * $DragonFly: src/sys/dev/powermng/ichsmb/ichsmb.c,v 1.7 2006/10/25 20:56:00 dillon Exp $
+ * $FreeBSD: src/sys/dev/ichsmb/ichsmb.c,v 1.20 2009/02/03 16:14:37 jhb Exp $
*/
/*
* Support for the SMBus controller logical device which is part of the
* Intel 81801AA (ICH) and 81801AB (ICH0) I/O controller hub chips.
+ *
+ * This driver assumes that the generic SMBus code will ensure that
+ * at most one process at a time calls into the SMBus methods below.
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/errno.h>
+#include <sys/globaldata.h>
+#include <sys/lock.h>
+#include <sys/module.h>
#include <sys/syslog.h>
#include <sys/bus.h>
+
#include <sys/rman.h>
-#include <sys/thread2.h>
#include <bus/smbus/smbconf.h>
-#include "ichsmb_var.h"
-#include "ichsmb_reg.h"
+#include <dev/powermng/ichsmb/ichsmb_var.h>
+#include <dev/powermng/ichsmb/ichsmb_reg.h>
/*
* Enable debugging by defining ICHSMB_DEBUG to a non-zero value.
*/
#define ICHSMB_DEBUG 0
-#if ICHSMB_DEBUG != 0 && defined(__GNUC__)
+#if ICHSMB_DEBUG != 0 && defined(__CC_SUPPORTS___FUNC__)
#define DBG(fmt, args...) \
- do { log(LOG_DEBUG, "%s: " fmt, __func__ , ## args); } while (0)
+ do { printf("%s: " fmt, __func__ , ## args); } while (0)
#else
#define DBG(fmt, args...) do { } while (0)
#endif
int
ichsmb_probe(device_t dev)
{
- device_t smb;
-
- /* Add child: an instance of the "smbus" device */
- if ((smb = device_add_child(dev, DRIVER_SMBUS, -1)) == NULL) {
- log(LOG_ERR, "%s: no \"%s\" child found\n",
- device_get_nameunit(dev), DRIVER_SMBUS);
- return (ENXIO);
- }
- return (0);
+ return (BUS_PROBE_DEFAULT);
}
/*
const sc_p sc = device_get_softc(dev);
int error;
+ /* Create mutex */
+ lockinit(&sc->mutex, "ichsmb", 0, LK_CANRECURSE);
+
+ /* Add child: an instance of the "smbus" device */
+ if ((sc->smb = device_add_child(dev, DRIVER_SMBUS, -1)) == NULL) {
+ device_printf(dev, "no \"%s\" child found\n", DRIVER_SMBUS);
+ error = ENXIO;
+ goto fail;
+ }
+
/* Clear interrupt conditions */
- bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_STA, 0xff);
+ bus_write_1(sc->io_res, ICH_HST_STA, 0xff);
+
+ /* Set up interrupt handler */
+ error = bus_setup_intr(dev, sc->irq_res, 0,
+ ichsmb_device_intr, sc, &sc->irq_handle, NULL);
+ if (error != 0) {
+ device_printf(dev, "can't setup irq\n");
+ goto fail;
+ }
- /* Add "smbus" child */
+ /* Attach "smbus" child */
if ((error = bus_generic_attach(dev)) != 0) {
- log(LOG_ERR, "%s: failed to attach child: %d\n",
- device_get_nameunit(dev), error);
- error = ENXIO;
+ device_printf(dev, "failed to attach child: %d\n", error);
+ goto fail;
}
- /* Done */
+ return (0);
+
+fail:
+ lockuninit(&sc->mutex);
return (error);
}
SMBUS METHODS
********************************************************************/
-int
-ichsmb_callback(device_t dev, int index, caddr_t data)
+int
+ichsmb_callback(device_t dev, int index, void *data)
{
int smb_error = 0;
switch (how) {
case SMB_QREAD:
case SMB_QWRITE:
- crit_enter();
+ lockmgr(&sc->mutex, LK_EXCLUSIVE);
sc->ich_cmd = ICH_HST_CNT_SMB_CMD_QUICK;
- bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_XMIT_SLVA,
- (slave << 1) | (how == SMB_QREAD ?
+ bus_write_1(sc->io_res, ICH_XMIT_SLVA,
+ slave | (how == SMB_QREAD ?
ICH_XMIT_SLVA_READ : ICH_XMIT_SLVA_WRITE));
- bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_CNT,
+ bus_write_1(sc->io_res, ICH_HST_CNT,
ICH_HST_CNT_START | ICH_HST_CNT_INTREN | sc->ich_cmd);
smb_error = ichsmb_wait(sc);
- crit_exit();
+ lockmgr(&sc->mutex, LK_RELEASE);
break;
default:
smb_error = SMB_ENOTSUPP;
DBG("slave=0x%02x byte=0x%02x\n", slave, (u_char)byte);
KASSERT(sc->ich_cmd == -1,
("%s: ich_cmd=%d\n", __func__ , sc->ich_cmd));
- crit_enter();
+ lockmgr(&sc->mutex, LK_EXCLUSIVE);
sc->ich_cmd = ICH_HST_CNT_SMB_CMD_BYTE;
- bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_XMIT_SLVA,
- (slave << 1) | ICH_XMIT_SLVA_WRITE);
- bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_CMD, byte);
- bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_CNT,
+ bus_write_1(sc->io_res, ICH_XMIT_SLVA,
+ slave | ICH_XMIT_SLVA_WRITE);
+ bus_write_1(sc->io_res, ICH_HST_CMD, byte);
+ bus_write_1(sc->io_res, ICH_HST_CNT,
ICH_HST_CNT_START | ICH_HST_CNT_INTREN | sc->ich_cmd);
smb_error = ichsmb_wait(sc);
- crit_exit();
+ lockmgr(&sc->mutex, LK_RELEASE);
DBG("smb_error=%d\n", smb_error);
return (smb_error);
}
DBG("slave=0x%02x\n", slave);
KASSERT(sc->ich_cmd == -1,
("%s: ich_cmd=%d\n", __func__ , sc->ich_cmd));
- crit_enter();
+ lockmgr(&sc->mutex, LK_EXCLUSIVE);
sc->ich_cmd = ICH_HST_CNT_SMB_CMD_BYTE;
- bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_XMIT_SLVA,
- (slave << 1) | ICH_XMIT_SLVA_READ);
- bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_CNT,
+ bus_write_1(sc->io_res, ICH_XMIT_SLVA,
+ slave | ICH_XMIT_SLVA_READ);
+ bus_write_1(sc->io_res, ICH_HST_CNT,
ICH_HST_CNT_START | ICH_HST_CNT_INTREN | sc->ich_cmd);
if ((smb_error = ichsmb_wait(sc)) == SMB_ENOERR)
- *byte = bus_space_read_1(sc->io_bst, sc->io_bsh, ICH_D0);
- crit_exit();
+ *byte = bus_read_1(sc->io_res, ICH_D0);
+ lockmgr(&sc->mutex, LK_RELEASE);
DBG("smb_error=%d byte=0x%02x\n", smb_error, (u_char)*byte);
return (smb_error);
}
slave, (u_char)cmd, (u_char)byte);
KASSERT(sc->ich_cmd == -1,
("%s: ich_cmd=%d\n", __func__ , sc->ich_cmd));
- crit_enter();
+ lockmgr(&sc->mutex, LK_EXCLUSIVE);
sc->ich_cmd = ICH_HST_CNT_SMB_CMD_BYTE_DATA;
- bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_XMIT_SLVA,
- (slave << 1) | ICH_XMIT_SLVA_WRITE);
- bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_CMD, cmd);
- bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_D0, byte);
- bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_CNT,
+ bus_write_1(sc->io_res, ICH_XMIT_SLVA,
+ slave | ICH_XMIT_SLVA_WRITE);
+ bus_write_1(sc->io_res, ICH_HST_CMD, cmd);
+ bus_write_1(sc->io_res, ICH_D0, byte);
+ bus_write_1(sc->io_res, ICH_HST_CNT,
ICH_HST_CNT_START | ICH_HST_CNT_INTREN | sc->ich_cmd);
smb_error = ichsmb_wait(sc);
- crit_exit();
+ lockmgr(&sc->mutex, LK_RELEASE);
DBG("smb_error=%d\n", smb_error);
return (smb_error);
}
slave, (u_char)cmd, (u_int16_t)word);
KASSERT(sc->ich_cmd == -1,
("%s: ich_cmd=%d\n", __func__ , sc->ich_cmd));
- crit_enter();
+ lockmgr(&sc->mutex, LK_EXCLUSIVE);
sc->ich_cmd = ICH_HST_CNT_SMB_CMD_WORD_DATA;
- bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_XMIT_SLVA,
- (slave << 1) | ICH_XMIT_SLVA_WRITE);
- bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_CMD, cmd);
- bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_D0, word & 0xff);
- bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_D1, word >> 8);
- bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_CNT,
+ bus_write_1(sc->io_res, ICH_XMIT_SLVA,
+ slave | ICH_XMIT_SLVA_WRITE);
+ bus_write_1(sc->io_res, ICH_HST_CMD, cmd);
+ bus_write_1(sc->io_res, ICH_D0, word & 0xff);
+ bus_write_1(sc->io_res, ICH_D1, word >> 8);
+ bus_write_1(sc->io_res, ICH_HST_CNT,
ICH_HST_CNT_START | ICH_HST_CNT_INTREN | sc->ich_cmd);
smb_error = ichsmb_wait(sc);
- crit_exit();
+ lockmgr(&sc->mutex, LK_RELEASE);
DBG("smb_error=%d\n", smb_error);
return (smb_error);
}
DBG("slave=0x%02x cmd=0x%02x\n", slave, (u_char)cmd);
KASSERT(sc->ich_cmd == -1,
("%s: ich_cmd=%d\n", __func__ , sc->ich_cmd));
- crit_enter();
+ lockmgr(&sc->mutex, LK_EXCLUSIVE);
sc->ich_cmd = ICH_HST_CNT_SMB_CMD_BYTE_DATA;
- bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_XMIT_SLVA,
- (slave << 1) | ICH_XMIT_SLVA_READ);
- bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_CMD, cmd);
- bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_CNT,
+ bus_write_1(sc->io_res, ICH_XMIT_SLVA,
+ slave | ICH_XMIT_SLVA_READ);
+ bus_write_1(sc->io_res, ICH_HST_CMD, cmd);
+ bus_write_1(sc->io_res, ICH_HST_CNT,
ICH_HST_CNT_START | ICH_HST_CNT_INTREN | sc->ich_cmd);
if ((smb_error = ichsmb_wait(sc)) == SMB_ENOERR)
- *byte = bus_space_read_1(sc->io_bst, sc->io_bsh, ICH_D0);
- crit_exit();
+ *byte = bus_read_1(sc->io_res, ICH_D0);
+ lockmgr(&sc->mutex, LK_RELEASE);
DBG("smb_error=%d byte=0x%02x\n", smb_error, (u_char)*byte);
return (smb_error);
}
DBG("slave=0x%02x cmd=0x%02x\n", slave, (u_char)cmd);
KASSERT(sc->ich_cmd == -1,
("%s: ich_cmd=%d\n", __func__ , sc->ich_cmd));
- crit_enter();
+ lockmgr(&sc->mutex, LK_EXCLUSIVE);
sc->ich_cmd = ICH_HST_CNT_SMB_CMD_WORD_DATA;
- bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_XMIT_SLVA,
- (slave << 1) | ICH_XMIT_SLVA_READ);
- bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_CMD, cmd);
- bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_CNT,
+ bus_write_1(sc->io_res, ICH_XMIT_SLVA,
+ slave | ICH_XMIT_SLVA_READ);
+ bus_write_1(sc->io_res, ICH_HST_CMD, cmd);
+ bus_write_1(sc->io_res, ICH_HST_CNT,
ICH_HST_CNT_START | ICH_HST_CNT_INTREN | sc->ich_cmd);
if ((smb_error = ichsmb_wait(sc)) == SMB_ENOERR) {
- *word = (bus_space_read_1(sc->io_bst,
- sc->io_bsh, ICH_D0) & 0xff)
- | (bus_space_read_1(sc->io_bst,
- sc->io_bsh, ICH_D1) << 8);
+ *word = (bus_read_1(sc->io_res,
+ ICH_D0) & 0xff)
+ | (bus_read_1(sc->io_res,
+ ICH_D1) << 8);
}
- crit_exit();
+ lockmgr(&sc->mutex, LK_RELEASE);
DBG("smb_error=%d word=0x%04x\n", smb_error, (u_int16_t)*word);
return (smb_error);
}
slave, (u_char)cmd, (u_int16_t)sdata);
KASSERT(sc->ich_cmd == -1,
("%s: ich_cmd=%d\n", __func__ , sc->ich_cmd));
- crit_enter();
+ lockmgr(&sc->mutex, LK_EXCLUSIVE);
sc->ich_cmd = ICH_HST_CNT_SMB_CMD_PROC_CALL;
- bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_XMIT_SLVA,
- (slave << 1) | ICH_XMIT_SLVA_WRITE);
- bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_CMD, cmd);
- bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_D0, sdata & 0xff);
- bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_D1, sdata >> 8);
- bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_CNT,
+ bus_write_1(sc->io_res, ICH_XMIT_SLVA,
+ slave | ICH_XMIT_SLVA_WRITE);
+ bus_write_1(sc->io_res, ICH_HST_CMD, cmd);
+ bus_write_1(sc->io_res, ICH_D0, sdata & 0xff);
+ bus_write_1(sc->io_res, ICH_D1, sdata >> 8);
+ bus_write_1(sc->io_res, ICH_HST_CNT,
ICH_HST_CNT_START | ICH_HST_CNT_INTREN | sc->ich_cmd);
if ((smb_error = ichsmb_wait(sc)) == SMB_ENOERR) {
- *rdata = (bus_space_read_1(sc->io_bst,
- sc->io_bsh, ICH_D0) & 0xff)
- | (bus_space_read_1(sc->io_bst,
- sc->io_bsh, ICH_D1) << 8);
+ *rdata = (bus_read_1(sc->io_res,
+ ICH_D0) & 0xff)
+ | (bus_read_1(sc->io_res,
+ ICH_D1) << 8);
}
- crit_exit();
+ lockmgr(&sc->mutex, LK_RELEASE);
DBG("smb_error=%d rdata=0x%04x\n", smb_error, (u_int16_t)*rdata);
return (smb_error);
}
DBG("%02x: %02x %02x %02x %02x %02x %02x %02x %02x"
" %c%c%c%c%c%c%c%c", (p - (u_char *)buf),
p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
- DISP(p[0]), DISP(p[1]), DISP(p[2]), DISP(p[3]),
+ DISP(p[0]), DISP(p[1]), DISP(p[2]), DISP(p[3]),
DISP(p[4]), DISP(p[5]), DISP(p[6]), DISP(p[7]));
}
}
KASSERT(sc->ich_cmd == -1,
("%s: ich_cmd=%d\n", __func__ , sc->ich_cmd));
if (count < 1 || count > 32)
- return (EINVAL);
+ return (SMB_EINVAL);
bcopy(buf, sc->block_data, count);
sc->block_count = count;
sc->block_index = 1;
sc->block_write = 1;
- crit_enter();
+ lockmgr(&sc->mutex, LK_EXCLUSIVE);
sc->ich_cmd = ICH_HST_CNT_SMB_CMD_BLOCK;
- bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_XMIT_SLVA,
- (slave << 1) | ICH_XMIT_SLVA_WRITE);
- bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_CMD, cmd);
- bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_D0, count);
- bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_BLOCK_DB, buf[0]);
- bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_CNT,
+ bus_write_1(sc->io_res, ICH_XMIT_SLVA,
+ slave | ICH_XMIT_SLVA_WRITE);
+ bus_write_1(sc->io_res, ICH_HST_CMD, cmd);
+ bus_write_1(sc->io_res, ICH_D0, count);
+ bus_write_1(sc->io_res, ICH_BLOCK_DB, buf[0]);
+ bus_write_1(sc->io_res, ICH_HST_CNT,
ICH_HST_CNT_START | ICH_HST_CNT_INTREN | sc->ich_cmd);
smb_error = ichsmb_wait(sc);
- crit_exit();
+ lockmgr(&sc->mutex, LK_RELEASE);
DBG("smb_error=%d\n", smb_error);
return (smb_error);
}
int
-ichsmb_bread(device_t dev, u_char slave, char cmd, u_char count, char *buf)
+ichsmb_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf)
{
const sc_p sc = device_get_softc(dev);
int smb_error;
DBG("slave=0x%02x cmd=0x%02x count=%d\n", slave, (u_char)cmd, count);
KASSERT(sc->ich_cmd == -1,
("%s: ich_cmd=%d\n", __func__ , sc->ich_cmd));
- if (count < 1 || count > 32)
- return (EINVAL);
+ if (*count < 1 || *count > 32)
+ return (SMB_EINVAL);
bzero(sc->block_data, sizeof(sc->block_data));
- sc->block_count = count;
+ sc->block_count = 0;
sc->block_index = 0;
sc->block_write = 0;
- crit_enter();
+ lockmgr(&sc->mutex, LK_EXCLUSIVE);
sc->ich_cmd = ICH_HST_CNT_SMB_CMD_BLOCK;
- bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_XMIT_SLVA,
- (slave << 1) | ICH_XMIT_SLVA_READ);
- bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_CMD, cmd);
- bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_D0, count); /* XXX? */
- bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_CNT,
+ bus_write_1(sc->io_res, ICH_XMIT_SLVA,
+ slave | ICH_XMIT_SLVA_READ);
+ bus_write_1(sc->io_res, ICH_HST_CMD, cmd);
+ bus_write_1(sc->io_res, ICH_D0, *count); /* XXX? */
+ bus_write_1(sc->io_res, ICH_HST_CNT,
ICH_HST_CNT_START | ICH_HST_CNT_INTREN | sc->ich_cmd);
- if ((smb_error = ichsmb_wait(sc)) == SMB_ENOERR)
- bcopy(sc->block_data, buf, sc->block_count);
- crit_exit();
+ if ((smb_error = ichsmb_wait(sc)) == SMB_ENOERR) {
+ bcopy(sc->block_data, buf, min(sc->block_count, *count));
+ *count = sc->block_count;
+ }
+ lockmgr(&sc->mutex, LK_RELEASE);
DBG("smb_error=%d\n", smb_error);
#if ICHSMB_DEBUG
#define DISP(ch) (((ch) < 0x20 || (ch) >= 0x7e) ? '.' : (ch))
DBG("%02x: %02x %02x %02x %02x %02x %02x %02x %02x"
" %c%c%c%c%c%c%c%c", (p - (u_char *)buf),
p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],
- DISP(p[0]), DISP(p[1]), DISP(p[2]), DISP(p[3]),
+ DISP(p[0]), DISP(p[1]), DISP(p[2]), DISP(p[3]),
DISP(p[4]), DISP(p[5]), DISP(p[6]), DISP(p[7]));
}
}
int cmd_index;
int count;
- crit_enter();
+ lockmgr(&sc->mutex, LK_EXCLUSIVE);
for (count = 0; count < maxloops; count++) {
/* Get and reset status bits */
- status = bus_space_read_1(sc->io_bst, sc->io_bsh, ICH_HST_STA);
+ status = bus_read_1(sc->io_res, ICH_HST_STA);
#if ICHSMB_DEBUG
if ((status & ~(ICH_HST_STA_INUSE_STS | ICH_HST_STA_HOST_BUSY))
|| count > 0) {
ok_bits |= ichsmb_state_irqs[cmd_index];
}
if ((status & ~ok_bits) != 0) {
- log(LOG_ERR, "%s: irq 0x%02x during %d\n",
- device_get_nameunit(dev), status, cmd_index);
- bus_space_write_1(sc->io_bst, sc->io_bsh,
+ device_printf(dev, "irq 0x%02x during %d\n", status,
+ cmd_index);
+ bus_write_1(sc->io_res,
ICH_HST_STA, (status & ~ok_bits));
continue;
}
if (status & ICH_HST_STA_SMBALERT_STS) {
static int smbalert_count = 16;
if (smbalert_count > 0) {
- log(LOG_WARNING, "%s: SMBALERT# rec'd\n",
- device_get_nameunit(dev));
+ device_printf(dev, "SMBALERT# rec'd\n");
if (--smbalert_count == 0) {
- log(LOG_WARNING,
- "%s: not logging anymore\n",
- device_get_nameunit(dev));
+ device_printf(dev,
+ "not logging anymore\n");
}
}
}
if (sc->block_index < sc->block_count) {
/* Write next byte */
- bus_space_write_1(sc->io_bst,
- sc->io_bsh, ICH_BLOCK_DB,
+ bus_write_1(sc->io_res,
+ ICH_BLOCK_DB,
sc->block_data[sc->block_index++]);
}
} else {
/* First interrupt, get the count also */
if (sc->block_index == 0) {
- sc->block_count = bus_space_read_1(
- sc->io_bst, sc->io_bsh, ICH_D0);
+ sc->block_count = bus_read_1(
+ sc->io_res, ICH_D0);
}
/* Get next byte, if any */
/* Read next byte */
sc->block_data[sc->block_index++] =
- bus_space_read_1(sc->io_bst,
- sc->io_bsh, ICH_BLOCK_DB);
+ bus_read_1(sc->io_res,
+ ICH_BLOCK_DB);
/* Set "LAST_BYTE" bit before reading
the last byte of block data */
if (sc->block_index
>= sc->block_count - 1) {
- bus_space_write_1(sc->io_bst,
- sc->io_bsh, ICH_HST_CNT,
+ bus_write_1(sc->io_res,
+ ICH_HST_CNT,
ICH_HST_CNT_LAST_BYTE
| ICH_HST_CNT_INTREN
| sc->ich_cmd);
sc->smb_error = SMB_ENOERR;
finished:
sc->ich_cmd = -1;
- bus_space_write_1(sc->io_bst, sc->io_bsh,
+ bus_write_1(sc->io_res,
ICH_HST_STA, status);
wakeup(sc);
break;
}
/* Clear status bits and try again */
- bus_space_write_1(sc->io_bst, sc->io_bsh, ICH_HST_STA, status);
+ bus_write_1(sc->io_res, ICH_HST_STA, status);
}
- crit_exit();
+ lockmgr(&sc->mutex, LK_RELEASE);
/* Too many loops? */
if (count == maxloops) {
- log(LOG_ERR, "%s: interrupt loop, status=0x%02x\n",
- device_get_nameunit(dev),
- bus_space_read_1(sc->io_bst, sc->io_bsh, ICH_HST_STA));
+ device_printf(dev, "interrupt loop, status=0x%02x\n",
+ bus_read_1(sc->io_res, ICH_HST_STA));
}
}
/*
- * Wait for command completion. Assumes a critical section.
+ * Wait for command completion. Assumes mutex is held.
* Returns an SMB_* error code.
*/
static int
KASSERT(sc->ich_cmd != -1,
("%s: ich_cmd=%d\n", __func__ , sc->ich_cmd));
-sleep:
- error = tsleep(sc, PCATCH, "ichsmb", hz / 4);
- DBG("tsleep -> %d\n", error);
+ KKASSERT(lockstatus(&sc->mutex, curthread) != 0);
+ error = lksleep(sc, &sc->mutex, 0, "ichsmb", hz / 4);
+ DBG("msleep -> %d\n", error);
switch (error) {
- case ERESTART:
- if (sc->ich_cmd != -1)
- goto sleep;
- /* FALLTHROUGH */
case 0:
smb_error = sc->smb_error;
break;
case EWOULDBLOCK:
- log(LOG_ERR, "%s: device timeout, status=0x%02x\n",
- device_get_nameunit(dev),
- bus_space_read_1(sc->io_bst, sc->io_bsh, ICH_HST_STA));
+ device_printf(dev, "device timeout, status=0x%02x\n",
+ bus_read_1(sc->io_res, ICH_HST_STA));
sc->ich_cmd = -1;
smb_error = SMB_ETIMEOUT;
break;
}
}
+int
+ichsmb_detach(device_t dev)
+{
+ const sc_p sc = device_get_softc(dev);
+ int error;
+
+ error = bus_generic_detach(dev);
+ if (error)
+ return (error);
+ device_delete_child(dev, sc->smb);
+ ichsmb_release_resources(sc);
+ lockuninit(&sc->mutex);
+
+ return 0;
+}
+
+DRIVER_MODULE(smbus, ichsmb, smbus_driver, smbus_devclass, 0, 0);
-
-/*
+/*-
* ichsmb_pci.c
*
+ * Author: Archie Cobbs <archie@freebsd.org>
* Copyright (c) 2000 Whistle Communications, Inc.
* All rights reserved.
- *
+ * Author: Archie Cobbs <archie@freebsd.org>
+ *
* Subject to the following obligations and disclaimer of warranty, use and
* redistribution of this software, in source or object code forms, with or
* without modifications are expressly permitted by Whistle Communications;
* Communications, Inc. trademarks, including the mark "WHISTLE
* COMMUNICATIONS" on advertising, endorsements, or otherwise except as
* such appears in the above copyright notice or in the software.
- *
+ *
* THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
* REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
* THIS SOFTWARE, EVEN IF WHISTLE COMMUNICATIONS IS ADVISED OF THE POSSIBILITY
* OF SUCH DAMAGE.
*
- * Author: Archie Cobbs <archie@freebsd.org>
- *
- * $FreeBSD: src/sys/dev/ichsmb/ichsmb_pci.c,v 1.1.2.3 2002/10/20 14:57:19 nyan Exp $
- * $DragonFly: src/sys/dev/powermng/ichsmb/ichsmb_pci.c,v 1.9 2007/09/23 22:06:10 hasso Exp $
+ * $FreeBSD: src/sys/dev/ichsmb/ichsmb_pci.c,v 1.25 2009/12/16 12:25:27 avg Exp $
*/
/*
* Support for the SMBus controller logical device which is part of the
- * Intel 81801AA (ICH) and 81801AB (ICH0) I/O controller hub chips.
+ * Intel 81801AA/AB/BA/CA/DC/EB (ICH/ICH[02345]) I/O controller hub chips.
*/
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
+#include <sys/module.h>
#include <sys/errno.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
#include <sys/syslog.h>
#include <sys/bus.h>
+
#include <sys/rman.h>
#include <bus/pci/pcivar.h>
#include <bus/smbus/smbconf.h>
-#include "ichsmb_var.h"
-#include "ichsmb_reg.h"
+#include <dev/powermng/ichsmb/ichsmb_var.h>
+#include <dev/powermng/ichsmb/ichsmb_reg.h>
/* PCI unique identifiers */
-#define ID_6300ESB 0x25A48086
-#define ID_63xxESB 0x269B8086
#define ID_82801AA 0x24138086
#define ID_82801AB 0x24238086
#define ID_82801BA 0x24438086
-#define ID_82801E 0x24538086
#define ID_82801CA 0x24838086
-#define ID_82801DB 0x24C38086
+#define ID_82801DC 0x24C38086
+#define ID_82801E 0x24538086
#define ID_82801EB 0x24D38086
#define ID_82801FB 0x266A8086
-#define ID_82801G 0x27DA8086
-#define ID_82801H 0x283E8086
+#define ID_82801GB 0x27da8086
+#define ID_82801H 0x283e8086
#define ID_82801I 0x29308086
+#define ID_82801JI 0x3a308086
+#define ID_PCH 0x3b308086
+#define ID_6300ESB 0x25a48086
+#define ID_631xESB 0x269b8086
#define PCIS_SERIALBUS_SMBUS_PROGIF 0x00
/* Internal functions */
static int ichsmb_pci_probe(device_t dev);
static int ichsmb_pci_attach(device_t dev);
+/*Use generic one for now*/
+#if 0
+static int ichsmb_pci_detach(device_t dev);
+#endif
/* Device methods */
static device_method_t ichsmb_pci_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, ichsmb_pci_probe),
DEVMETHOD(device_attach, ichsmb_pci_attach),
+ DEVMETHOD(device_detach, ichsmb_detach),
/* Bus methods */
DEVMETHOD(bus_print_child, bus_generic_print_child),
{
/* Check PCI identifier */
switch (pci_get_devid(dev)) {
- case ID_6300ESB:
- device_set_desc(dev, "Intel 6300ESB (ESB) SMBus controller");
- break;
- case ID_63xxESB:
- device_set_desc(dev, "Intel 63xxESB (ESB2) SMBus controller");
- break;
case ID_82801AA:
device_set_desc(dev, "Intel 82801AA (ICH) SMBus controller");
break;
case ID_82801CA:
device_set_desc(dev, "Intel 82801CA (ICH3) SMBus controller");
break;
- case ID_82801DB:
- device_set_desc(dev, "Intel 82801DB (ICH4) SMBus controller");
+ case ID_82801DC:
+ device_set_desc(dev, "Intel 82801DC (ICH4) SMBus controller");
break;
case ID_82801E:
device_set_desc(dev, "Intel 82801E (C-ICH) SMBus controller");
case ID_82801FB:
device_set_desc(dev, "Intel 82801FB (ICH6) SMBus controller");
break;
- case ID_82801G:
- device_set_desc(dev, "Intel 82801G (ICH7) SMBus controller");
+ case ID_82801GB:
+ device_set_desc(dev, "Intel 82801GB (ICH7) SMBus controller");
break;
case ID_82801H:
device_set_desc(dev, "Intel 82801H (ICH8) SMBus controller");
case ID_82801I:
device_set_desc(dev, "Intel 82801I (ICH9) SMBus controller");
break;
+ case ID_82801JI:
+ device_set_desc(dev, "Intel 82801JI (ICH10) SMBus controller");
+ break;
+ case ID_PCH:
+ device_set_desc(dev, "Intel PCH SMBus controller");
+ break;
+ case ID_6300ESB:
+ device_set_desc(dev, "Intel 6300ESB (ICH) SMBus controller");
+ break;
+ case ID_631xESB:
+ device_set_desc(dev, "Intel 631xESB/6321ESB (ESB2) SMBus controller");
+ break;
default:
- if (pci_get_class(dev) == PCIC_SERIALBUS
- && pci_get_subclass(dev) == PCIS_SERIALBUS_SMBUS
- && pci_get_progif(dev) == PCIS_SERIALBUS_SMBUS_PROGIF) {
- device_set_desc(dev, "SMBus controller");
- return (-2); /* XXX */
- }
return (ENXIO);
}
ichsmb_pci_attach(device_t dev)
{
const sc_p sc = device_get_softc(dev);
- u_int32_t cmd;
int error;
/* Initialize private state */
sc->io_rid = ICH_SMB_BASE;
sc->io_res = bus_alloc_resource(dev, SYS_RES_IOPORT,
&sc->io_rid, 0, ~0, 16, RF_ACTIVE);
+ if (sc->io_res == NULL)
+ sc->io_res = bus_alloc_resource(dev, SYS_RES_IOPORT,
+ &sc->io_rid, 0ul, ~0ul, 32, RF_ACTIVE);
if (sc->io_res == NULL) {
- log(LOG_ERR, "%s: can't map I/O\n", device_get_nameunit(dev));
+ device_printf(dev, "can't map I/O\n");
error = ENXIO;
goto fail;
}
- sc->io_bst = rman_get_bustag(sc->io_res);
- sc->io_bsh = rman_get_bushandle(sc->io_res);
/* Allocate interrupt */
sc->irq_rid = 0;
- sc->irq_res = bus_alloc_resource(dev, SYS_RES_IRQ,
- &sc->irq_rid, 0, ~0, 1, RF_ACTIVE | RF_SHAREABLE);
+ sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ,
+ &sc->irq_rid, RF_ACTIVE | RF_SHAREABLE);
if (sc->irq_res == NULL) {
- log(LOG_ERR, "%s: can't get IRQ\n", device_get_nameunit(dev));
- error = ENXIO;
- goto fail;
- }
-
- /* Set up interrupt handler */
- error = bus_setup_intr(dev, sc->irq_res, 0, ichsmb_device_intr, sc,
- &sc->irq_handle, NULL);
- if (error != 0) {
- log(LOG_ERR, "%s: can't setup irq\n", device_get_nameunit(dev));
- goto fail;
- }
-
- /* Enable I/O mapping */
- cmd = pci_read_config(dev, PCIR_COMMAND, 4);
- cmd |= PCIM_CMD_PORTEN;
- pci_write_config(dev, PCIR_COMMAND, cmd, 4);
- cmd = pci_read_config(dev, PCIR_COMMAND, 4);
- if ((cmd & PCIM_CMD_PORTEN) == 0) {
- log(LOG_ERR, "%s: can't enable memory map\n",
- device_get_nameunit(dev));
+ device_printf(dev, "can't get IRQ\n");
error = ENXIO;
goto fail;
}
pci_write_config(dev, ICH_HOSTC, ICH_HOSTC_HST_EN, 1);
/* Done */
- return (ichsmb_attach(dev));
+ error = ichsmb_attach(dev);
+ if (error)
+ goto fail;
+ return (0);
fail:
/* Attach failed, release resources */
return (error);
}
+
+MODULE_DEPEND(ichsmb, pci, 1, 1, 1);
+MODULE_DEPEND(ichsmb, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER);
+MODULE_VERSION(ichsmb, 1);
-
-/*
+/*-
* ichsmb_reg.h
*
* Copyright (c) 2000 Whistle Communications, Inc.
* All rights reserved.
- *
+ *
* Subject to the following obligations and disclaimer of warranty, use and
* redistribution of this software, in source or object code forms, with or
* without modifications are expressly permitted by Whistle Communications;
* Communications, Inc. trademarks, including the mark "WHISTLE
* COMMUNICATIONS" on advertising, endorsements, or otherwise except as
* such appears in the above copyright notice or in the software.
- *
+ *
* THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
* REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
*
* Author: Archie Cobbs <archie@freebsd.org>
*
- * $FreeBSD: src/sys/dev/ichsmb/ichsmb_reg.h,v 1.1.2.1 2000/10/09 00:52:43 archie Exp $
- * $DragonFly: src/sys/dev/powermng/ichsmb/ichsmb_reg.h,v 1.2 2003/06/17 04:28:27 dillon Exp $
+ * $FreeBSD: src/sys/dev/ichsmb/ichsmb_reg.h,v 1.2 2005/01/06 01:42:45 imp Exp $
*/
#ifndef _DEV_ICHSMB_ICHSMB_REG_H_
-
-/*
+/*-
* ichsmb_var.h
*
* Copyright (c) 2000 Whistle Communications, Inc.
* All rights reserved.
- *
+ *
* Subject to the following obligations and disclaimer of warranty, use and
* redistribution of this software, in source or object code forms, with or
* without modifications are expressly permitted by Whistle Communications;
* Communications, Inc. trademarks, including the mark "WHISTLE
* COMMUNICATIONS" on advertising, endorsements, or otherwise except as
* such appears in the above copyright notice or in the software.
- *
+ *
* THIS SOFTWARE IS BEING PROVIDED BY WHISTLE COMMUNICATIONS "AS IS", AND
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, WHISTLE COMMUNICATIONS MAKES NO
* REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING THIS SOFTWARE,
*
* Author: Archie Cobbs <archie@freebsd.org>
*
- * $FreeBSD: src/sys/dev/ichsmb/ichsmb_var.h,v 1.1.2.1 2000/10/09 00:52:43 archie Exp $
- * $DragonFly: src/sys/dev/powermng/ichsmb/ichsmb_var.h,v 1.2 2003/06/17 04:28:27 dillon Exp $
+ * $FreeBSD: src/sys/dev/ichsmb/ichsmb_var.h,v 1.5 2008/06/06 18:29:56 jhb Exp $
*/
#ifndef _DEV_ICHSMB_ICHSMB_VAR_H
/* Device/bus stuff */
device_t dev; /* this device */
+ device_t smb; /* smb device */
struct resource *io_res; /* i/o port resource */
int io_rid; /* i/o port bus id */
- bus_space_tag_t io_bst; /* bus space tag */
- bus_space_handle_t io_bsh; /* bus space handle */
struct resource *irq_res; /* interrupt resource */
int irq_rid; /* interrupt bus id */
void *irq_handle; /* handle for interrupt code */
int block_index; /* index for block read/write */
u_char block_write; /* 0=read, 1=write */
u_char block_data[32]; /* block read/write data */
+ struct lock mutex; /* device mutex */
};
typedef struct ichsmb_softc *sc_p;
/* SMBus methods */
-extern smbus_callback_t ichsmb_callback;
-extern smbus_quick_t ichsmb_quick;
-extern smbus_sendb_t ichsmb_sendb;
-extern smbus_recvb_t ichsmb_recvb;
-extern smbus_writeb_t ichsmb_writeb;
-extern smbus_writew_t ichsmb_writew;
-extern smbus_readb_t ichsmb_readb;
-extern smbus_readw_t ichsmb_readw;
-extern smbus_pcall_t ichsmb_pcall;
-extern smbus_bwrite_t ichsmb_bwrite;
-extern smbus_bread_t ichsmb_bread;
+extern smbus_callback_t ichsmb_callback;
+extern smbus_quick_t ichsmb_quick;
+extern smbus_sendb_t ichsmb_sendb;
+extern smbus_recvb_t ichsmb_recvb;
+extern smbus_writeb_t ichsmb_writeb;
+extern smbus_writew_t ichsmb_writew;
+extern smbus_readb_t ichsmb_readb;
+extern smbus_readw_t ichsmb_readw;
+extern smbus_pcall_t ichsmb_pcall;
+extern smbus_bwrite_t ichsmb_bwrite;
+extern smbus_bread_t ichsmb_bread;
/* Other functions */
extern void ichsmb_device_intr(void *cookie);
extern void ichsmb_release_resources(sc_p sc);
extern int ichsmb_probe(device_t dev);
extern int ichsmb_attach(device_t dev);
+extern int ichsmb_detach(device_t dev);
#endif /* _DEV_ICHSMB_ICHSMB_VAR_H */
--- /dev/null
+# $FreeBSD: src/sys/modules/i2c/controllers/intpm/Makefile,v 1.1 2002/03/23 15:48:42 nsouch Exp $
+
+.PATH: ${.CURDIR}/../../../../bus/pci
+KMOD = intpm
+SRCS = device_if.h bus_if.h iicbus_if.h smbus_if.h pci_if.h \
+ opt_intpm.h intpmreg.h intpm.c
+
+.include <bsd.kmod.mk>
--- /dev/null
+/*-
+ * Copyright (c) 1998, 1999 Takanori Watanabe
+ * 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: src/sys/pci/intpm.c,v 1.45 2009/09/19 08:56:28 avg Exp $
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/globaldata.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/rman.h>
+#include <bus/smbus/smbconf.h>
+
+#include "smbus_if.h"
+
+#include <bus/pci/pcireg.h>
+#include <bus/pci/pcivar.h>
+#include <dev/powermng/intpm/intpmreg.h>
+
+#include "opt_intpm.h"
+
+struct intsmb_softc {
+ device_t dev;
+ struct resource *io_res;
+ struct resource *irq_res;
+ void *irq_hand;
+ device_t smbus;
+ int isbusy;
+ int cfg_irq9;
+ int poll;
+ struct lock lock;
+};
+
+#define INTSMB_LOCK(sc) lockmgr(&(sc)->lock, LK_EXCLUSIVE)
+#define INTSMB_UNLOCK(sc) lockmgr(&(sc)->lock, LK_RELEASE)
+#define INTSMB_LOCK_ASSERT(sc) KKASSERT(lockstatus(&(sc)->lock, curthread) != 0)
+
+static int intsmb_probe(device_t);
+static int intsmb_attach(device_t);
+static int intsmb_detach(device_t);
+static int intsmb_intr(struct intsmb_softc *sc);
+static int intsmb_slvintr(struct intsmb_softc *sc);
+static void intsmb_alrintr(struct intsmb_softc *sc);
+static int intsmb_callback(device_t dev, int index, void *data);
+static int intsmb_quick(device_t dev, u_char slave, int how);
+static int intsmb_sendb(device_t dev, u_char slave, char byte);
+static int intsmb_recvb(device_t dev, u_char slave, char *byte);
+static int intsmb_writeb(device_t dev, u_char slave, char cmd, char byte);
+static int intsmb_writew(device_t dev, u_char slave, char cmd, short word);
+static int intsmb_readb(device_t dev, u_char slave, char cmd, char *byte);
+static int intsmb_readw(device_t dev, u_char slave, char cmd, short *word);
+static int intsmb_pcall(device_t dev, u_char slave, char cmd, short sdata, short *rdata);
+static int intsmb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf);
+static int intsmb_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf);
+static void intsmb_start(struct intsmb_softc *sc, u_char cmd, int nointr);
+static int intsmb_stop(struct intsmb_softc *sc);
+static int intsmb_stop_poll(struct intsmb_softc *sc);
+static int intsmb_free(struct intsmb_softc *sc);
+static void intsmb_rawintr(void *arg);
+
+static int
+intsmb_probe(device_t dev)
+{
+
+ switch (pci_get_devid(dev)) {
+ case 0x71138086: /* Intel 82371AB */
+ case 0x719b8086: /* Intel 82443MX */
+#if 0
+ /* Not a good idea yet, this stops isab0 functioning */
+ case 0x02001166: /* ServerWorks OSB4 */
+#endif
+ device_set_desc(dev, "Intel PIIX4 SMBUS Interface");
+ break;
+ case 0x43851002:
+ device_set_desc(dev, "AMD SB600/700/710/750 SMBus Controller");
+ /* XXX Maybe force polling right here? */
+ break;
+ default:
+ return (ENXIO);
+ }
+
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+intsmb_attach(device_t dev)
+{
+ struct intsmb_softc *sc = device_get_softc(dev);
+ int error, rid, value;
+ int intr;
+ char *str;
+
+ sc->dev = dev;
+
+ lockinit(&sc->lock, "intsmb", 0, LK_CANRECURSE);
+
+ sc->cfg_irq9 = 0;
+#ifndef NO_CHANGE_PCICONF
+ switch (pci_get_devid(dev)) {
+ case 0x71138086: /* Intel 82371AB */
+ case 0x719b8086: /* Intel 82443MX */
+ /* Changing configuration is allowed. */
+ sc->cfg_irq9 = 1;
+ break;
+ }
+#endif
+
+ rid = PCI_BASE_ADDR_SMB;
+ sc->io_res = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid,
+ RF_ACTIVE);
+ if (sc->io_res == NULL) {
+ device_printf(dev, "Could not allocate I/O space\n");
+ error = ENXIO;
+ goto fail;
+ }
+
+ if (sc->cfg_irq9) {
+ pci_write_config(dev, PCIR_INTLINE, 0x9, 1);
+ pci_write_config(dev, PCI_HST_CFG_SMB,
+ PCI_INTR_SMB_IRQ9 | PCI_INTR_SMB_ENABLE, 1);
+ }
+ value = pci_read_config(dev, PCI_HST_CFG_SMB, 1);
+ sc->poll = (value & PCI_INTR_SMB_ENABLE) == 0;
+ intr = value & PCI_INTR_SMB_MASK;
+ switch (intr) {
+ case PCI_INTR_SMB_SMI:
+ str = "SMI";
+ break;
+ case PCI_INTR_SMB_IRQ9:
+ str = "IRQ 9";
+ break;
+ case PCI_INTR_SMB_IRQ_PCI:
+ str = "PCI IRQ";
+ break;
+ default:
+ str = "BOGUS";
+ }
+
+ device_printf(dev, "intr %s %s ", str,
+ sc->poll == 0 ? "enabled" : "disabled");
+ kprintf("revision %d\n", pci_read_config(dev, PCI_REVID_SMB, 1));
+
+ if (!sc->poll && intr == PCI_INTR_SMB_SMI) {
+ device_printf(dev,
+ "using polling mode when configured interrupt is SMI\n");
+ sc->poll = 1;
+ }
+
+ if (sc->poll)
+ goto no_intr;
+
+ if (intr != PCI_INTR_SMB_IRQ9 && intr != PCI_INTR_SMB_IRQ_PCI) {
+ device_printf(dev, "Unsupported interrupt mode\n");
+ error = ENXIO;
+ goto fail;
+ }
+
+ /* Force IRQ 9. */
+ rid = 0;
+ if (sc->cfg_irq9)
+ bus_set_resource(dev, SYS_RES_IRQ, rid, 9, 1);
+
+ sc->irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ RF_SHAREABLE | RF_ACTIVE);
+ if (sc->irq_res == NULL) {
+ device_printf(dev, "Could not allocate irq\n");
+ error = ENXIO;
+ goto fail;
+ }
+
+ error = bus_setup_intr(dev, sc->irq_res, 0,
+ intsmb_rawintr, sc, &sc->irq_hand, NULL);
+ if (error) {
+ device_printf(dev, "Failed to map intr\n");
+ goto fail;
+ }
+
+no_intr:
+ sc->isbusy = 0;
+ sc->smbus = device_add_child(dev, "smbus", -1);
+ if (sc->smbus == NULL) {
+ error = ENXIO;
+ goto fail;
+ }
+ error = device_probe_and_attach(sc->smbus);
+ if (error)
+ goto fail;
+
+#ifdef ENABLE_ALART
+ /* Enable Arart */
+ bus_write_1(sc->io_res, PIIX4_SMBSLVCNT, PIIX4_SMBSLVCNT_ALTEN);
+#endif
+ return (0);
+
+fail:
+ intsmb_detach(dev);
+ return (error);
+}
+
+static int
+intsmb_detach(device_t dev)
+{
+ struct intsmb_softc *sc = device_get_softc(dev);
+ int error;
+
+ error = bus_generic_detach(dev);
+ if (error)
+ return (error);
+
+ if (sc->smbus)
+ device_delete_child(dev, sc->smbus);
+ if (sc->irq_hand)
+ bus_teardown_intr(dev, sc->irq_res, sc->irq_hand);
+ if (sc->irq_res)
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq_res);
+ if (sc->io_res)
+ bus_release_resource(dev, SYS_RES_IOPORT, PCI_BASE_ADDR_SMB,
+ sc->io_res);
+ lockuninit(&sc->lock);
+ return (0);
+}
+
+static void
+intsmb_rawintr(void *arg)
+{
+ struct intsmb_softc *sc = arg;
+
+ INTSMB_LOCK(sc);
+ intsmb_intr(sc);
+ intsmb_slvintr(sc);
+ INTSMB_UNLOCK(sc);
+}
+
+static int
+intsmb_callback(device_t dev, int index, void *data)
+{
+ int error = 0;
+
+ switch (index) {
+ case SMB_REQUEST_BUS:
+ break;
+ case SMB_RELEASE_BUS:
+ break;
+ default:
+ error = EINVAL;
+ }
+
+ return (error);
+}
+
+/* Counterpart of smbtx_smb_free(). */
+static int
+intsmb_free(struct intsmb_softc *sc)
+{
+
+ INTSMB_LOCK_ASSERT(sc);
+ if ((bus_read_1(sc->io_res, PIIX4_SMBHSTSTS) & PIIX4_SMBHSTSTAT_BUSY) ||
+#ifdef ENABLE_ALART
+ (bus_read_1(sc->io_res, PIIX4_SMBSLVSTS) & PIIX4_SMBSLVSTS_BUSY) ||
+#endif
+ sc->isbusy)
+ return (SMB_EBUSY);
+
+ sc->isbusy = 1;
+ /* Disable Interrupt in slave part. */
+#ifndef ENABLE_ALART
+ bus_write_1(sc->io_res, PIIX4_SMBSLVCNT, 0);
+#endif
+ /* Reset INTR Flag to prepare INTR. */
+ bus_write_1(sc->io_res, PIIX4_SMBHSTSTS,
+ PIIX4_SMBHSTSTAT_INTR | PIIX4_SMBHSTSTAT_ERR |
+ PIIX4_SMBHSTSTAT_BUSC | PIIX4_SMBHSTSTAT_FAIL);
+ return (0);
+}
+
+static int
+intsmb_intr(struct intsmb_softc *sc)
+{
+ int status, tmp;
+
+ status = bus_read_1(sc->io_res, PIIX4_SMBHSTSTS);
+ if (status & PIIX4_SMBHSTSTAT_BUSY)
+ return (1);
+
+ if (status & (PIIX4_SMBHSTSTAT_INTR | PIIX4_SMBHSTSTAT_ERR |
+ PIIX4_SMBHSTSTAT_BUSC | PIIX4_SMBHSTSTAT_FAIL)) {
+
+ tmp = bus_read_1(sc->io_res, PIIX4_SMBHSTCNT);
+ bus_write_1(sc->io_res, PIIX4_SMBHSTCNT,
+ tmp & ~PIIX4_SMBHSTCNT_INTREN);
+ if (sc->isbusy) {
+ sc->isbusy = 0;
+ wakeup(sc);
+ }
+ return (0);
+ }
+ return (1); /* Not Completed */
+}
+
+static int
+intsmb_slvintr(struct intsmb_softc *sc)
+{
+ int status;
+
+ status = bus_read_1(sc->io_res, PIIX4_SMBSLVSTS);
+ if (status & PIIX4_SMBSLVSTS_BUSY)
+ return (1);
+ if (status & PIIX4_SMBSLVSTS_ALART)
+ intsmb_alrintr(sc);
+ else if (status & ~(PIIX4_SMBSLVSTS_ALART | PIIX4_SMBSLVSTS_SDW2
+ | PIIX4_SMBSLVSTS_SDW1)) {
+ }
+
+ /* Reset Status Register */
+ bus_write_1(sc->io_res, PIIX4_SMBSLVSTS,
+ PIIX4_SMBSLVSTS_ALART | PIIX4_SMBSLVSTS_SDW2 |
+ PIIX4_SMBSLVSTS_SDW1 | PIIX4_SMBSLVSTS_SLV);
+ return (0);
+}
+
+static void
+intsmb_alrintr(struct intsmb_softc *sc)
+{
+ int slvcnt;
+#ifdef ENABLE_ALART
+ int error;
+ uint8_t addr;
+#endif
+
+ /* Stop generating INTR from ALART. */
+ slvcnt = bus_read_1(sc->io_res, PIIX4_SMBSLVCNT);
+#ifdef ENABLE_ALART
+ bus_write_1(sc->io_res, PIIX4_SMBSLVCNT,
+ slvcnt & ~PIIX4_SMBSLVCNT_ALTEN);
+#endif
+ DELAY(5);
+
+ /* Ask bus who asserted it and then ask it what's the matter. */
+#ifdef ENABLE_ALART
+ error = intsmb_free(sc);
+ if (error)
+ return;
+
+ bus_write_1(sc->io_res, PIIX4_SMBHSTADD, SMBALTRESP | LSB);
+ intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_BYTE, 1);
+ error = intsmb_stop_poll(sc);
+ if (error)
+ device_printf(sc->dev, "ALART: ERROR\n");
+ else {
+ addr = bus_read_1(sc->io_res, PIIX4_SMBHSTDAT0);
+ device_printf(sc->dev, "ALART_RESPONSE: 0x%x\n", addr);
+ }
+
+ /* Re-enable INTR from ALART. */
+ bus_write_1(sc->io_res, PIIX4_SMBSLVCNT,
+ slvcnt | PIIX4_SMBSLVCNT_ALTEN);
+ DELAY(5);
+#endif
+}
+
+static void
+intsmb_start(struct intsmb_softc *sc, unsigned char cmd, int nointr)
+{
+ unsigned char tmp;
+
+ INTSMB_LOCK_ASSERT(sc);
+ tmp = bus_read_1(sc->io_res, PIIX4_SMBHSTCNT);
+ tmp &= 0xe0;
+ tmp |= cmd;
+ tmp |= PIIX4_SMBHSTCNT_START;
+
+ /* While not in autoconfiguration enable interrupts. */
+ if (!sc->poll && !cold && !nointr)
+ tmp |= PIIX4_SMBHSTCNT_INTREN;
+ bus_write_1(sc->io_res, PIIX4_SMBHSTCNT, tmp);
+}
+
+static int
+intsmb_error(device_t dev, int status)
+{
+ int error = 0;
+
+ if (status & PIIX4_SMBHSTSTAT_ERR)
+ error |= SMB_EBUSERR;
+ if (status & PIIX4_SMBHSTSTAT_BUSC)
+ error |= SMB_ECOLLI;
+ if (status & PIIX4_SMBHSTSTAT_FAIL)
+ error |= SMB_ENOACK;
+
+ if (error != 0 && bootverbose)
+ device_printf(dev, "error = %d, status = %#x\n", error, status);
+
+ return (error);
+}
+
+/*
+ * Polling Code.
+ *
+ * Polling is not encouraged because it requires waiting for the
+ * device if it is busy.
+ * (29063505.pdf from Intel) But during boot, interrupt cannot be used, so use
+ * polling code then.
+ */
+static int
+intsmb_stop_poll(struct intsmb_softc *sc)
+{
+ int error, i, status, tmp;
+
+ INTSMB_LOCK_ASSERT(sc);
+
+ /* First, wait for busy to be set. */
+ for (i = 0; i < 0x7fff; i++)
+ if (bus_read_1(sc->io_res, PIIX4_SMBHSTSTS) &
+ PIIX4_SMBHSTSTAT_BUSY)
+ break;
+
+ /* Wait for busy to clear. */
+ for (i = 0; i < 0x7fff; i++) {
+ status = bus_read_1(sc->io_res, PIIX4_SMBHSTSTS);
+ if (!(status & PIIX4_SMBHSTSTAT_BUSY)) {
+ sc->isbusy = 0;
+ error = intsmb_error(sc->dev, status);
+ return (error);
+ }
+ }
+
+ /* Timed out waiting for busy to clear. */
+ sc->isbusy = 0;
+ tmp = bus_read_1(sc->io_res, PIIX4_SMBHSTCNT);
+ bus_write_1(sc->io_res, PIIX4_SMBHSTCNT, tmp & ~PIIX4_SMBHSTCNT_INTREN);
+ return (SMB_ETIMEOUT);
+}
+
+/*
+ * Wait for completion and return result.
+ */
+static int
+intsmb_stop(struct intsmb_softc *sc)
+{
+ int error, status;
+
+ INTSMB_LOCK_ASSERT(sc);
+
+ if (sc->poll || cold)
+ /* So that it can use device during device probe on SMBus. */
+ return (intsmb_stop_poll(sc));
+
+ error = lksleep(sc, &sc->lock, PCATCH, "SMBWAI", hz / 8);
+ if (error == 0) {
+ status = bus_read_1(sc->io_res, PIIX4_SMBHSTSTS);
+ if (!(status & PIIX4_SMBHSTSTAT_BUSY)) {
+ error = intsmb_error(sc->dev, status);
+ if (error == 0 && !(status & PIIX4_SMBHSTSTAT_INTR))
+ device_printf(sc->dev, "unknown cause why?\n");
+#ifdef ENABLE_ALART
+ bus_write_1(sc->io_res, PIIX4_SMBSLVCNT,
+ PIIX4_SMBSLVCNT_ALTEN);
+#endif
+ return (error);
+ }
+ }
+
+ /* Timeout Procedure. */
+ sc->isbusy = 0;
+
+ /* Re-enable supressed interrupt from slave part. */
+ bus_write_1(sc->io_res, PIIX4_SMBSLVCNT, PIIX4_SMBSLVCNT_ALTEN);
+ if (error == EWOULDBLOCK)
+ return (SMB_ETIMEOUT);
+ else
+ return (SMB_EABORT);
+}
+
+static int
+intsmb_quick(device_t dev, u_char slave, int how)
+{
+ struct intsmb_softc *sc = device_get_softc(dev);
+ int error;
+ u_char data;
+
+ data = slave;
+
+ /* Quick command is part of Address, I think. */
+ switch(how) {
+ case SMB_QWRITE:
+ data &= ~LSB;
+ break;
+ case SMB_QREAD:
+ data |= LSB;
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ INTSMB_LOCK(sc);
+ error = intsmb_free(sc);
+ if (error) {
+ INTSMB_UNLOCK(sc);
+ return (error);
+ }
+ bus_write_1(sc->io_res, PIIX4_SMBHSTADD, data);
+ intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_QUICK, 0);
+ error = intsmb_stop(sc);
+ INTSMB_UNLOCK(sc);
+ return (error);
+}
+
+static int
+intsmb_sendb(device_t dev, u_char slave, char byte)
+{
+ struct intsmb_softc *sc = device_get_softc(dev);
+ int error;
+
+ INTSMB_LOCK(sc);
+ error = intsmb_free(sc);
+ if (error) {
+ INTSMB_UNLOCK(sc);
+ return (error);
+ }
+ bus_write_1(sc->io_res, PIIX4_SMBHSTADD, slave & ~LSB);
+ bus_write_1(sc->io_res, PIIX4_SMBHSTCMD, byte);
+ intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_BYTE, 0);
+ error = intsmb_stop(sc);
+ INTSMB_UNLOCK(sc);
+ return (error);
+}
+
+static int
+intsmb_recvb(device_t dev, u_char slave, char *byte)
+{
+ struct intsmb_softc *sc = device_get_softc(dev);
+ int error;
+
+ INTSMB_LOCK(sc);
+ error = intsmb_free(sc);
+ if (error) {
+ INTSMB_UNLOCK(sc);
+ return (error);
+ }
+ bus_write_1(sc->io_res, PIIX4_SMBHSTADD, slave | LSB);
+ intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_BYTE, 0);
+ error = intsmb_stop(sc);
+ if (error == 0) {
+#ifdef RECV_IS_IN_CMD
+ /*
+ * Linux SMBus stuff also troubles
+ * Because Intel's datasheet does not make clear.
+ */
+ *byte = bus_read_1(sc->io_res, PIIX4_SMBHSTCMD);
+#else
+ *byte = bus_read_1(sc->io_res, PIIX4_SMBHSTDAT0);
+#endif
+ }
+ INTSMB_UNLOCK(sc);
+ return (error);
+}
+
+static int
+intsmb_writeb(device_t dev, u_char slave, char cmd, char byte)
+{
+ struct intsmb_softc *sc = device_get_softc(dev);
+ int error;
+
+ INTSMB_LOCK(sc);
+ error = intsmb_free(sc);
+ if (error) {
+ INTSMB_UNLOCK(sc);
+ return (error);
+ }
+ bus_write_1(sc->io_res, PIIX4_SMBHSTADD, slave & ~LSB);
+ bus_write_1(sc->io_res, PIIX4_SMBHSTCMD, cmd);
+ bus_write_1(sc->io_res, PIIX4_SMBHSTDAT0, byte);
+ intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_BDATA, 0);
+ error = intsmb_stop(sc);
+ INTSMB_UNLOCK(sc);
+ return (error);
+}
+
+static int
+intsmb_writew(device_t dev, u_char slave, char cmd, short word)
+{
+ struct intsmb_softc *sc = device_get_softc(dev);
+ int error;
+
+ INTSMB_LOCK(sc);
+ error = intsmb_free(sc);
+ if (error) {
+ INTSMB_UNLOCK(sc);
+ return (error);
+ }
+ bus_write_1(sc->io_res, PIIX4_SMBHSTADD, slave & ~LSB);
+ bus_write_1(sc->io_res, PIIX4_SMBHSTCMD, cmd);
+ bus_write_1(sc->io_res, PIIX4_SMBHSTDAT0, word & 0xff);
+ bus_write_1(sc->io_res, PIIX4_SMBHSTDAT1, (word >> 8) & 0xff);
+ intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_WDATA, 0);
+ error = intsmb_stop(sc);
+ INTSMB_UNLOCK(sc);
+ return (error);
+}
+
+static int
+intsmb_readb(device_t dev, u_char slave, char cmd, char *byte)
+{
+ struct intsmb_softc *sc = device_get_softc(dev);
+ int error;
+
+ INTSMB_LOCK(sc);
+ error = intsmb_free(sc);
+ if (error) {
+ INTSMB_UNLOCK(sc);
+ return (error);
+ }
+ bus_write_1(sc->io_res, PIIX4_SMBHSTADD, slave | LSB);
+ bus_write_1(sc->io_res, PIIX4_SMBHSTCMD, cmd);
+ intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_BDATA, 0);
+ error = intsmb_stop(sc);
+ if (error == 0)
+ *byte = bus_read_1(sc->io_res, PIIX4_SMBHSTDAT0);
+ INTSMB_UNLOCK(sc);
+ return (error);
+}
+
+static int
+intsmb_readw(device_t dev, u_char slave, char cmd, short *word)
+{
+ struct intsmb_softc *sc = device_get_softc(dev);
+ int error;
+
+ INTSMB_LOCK(sc);
+ error = intsmb_free(sc);
+ if (error) {
+ INTSMB_UNLOCK(sc);
+ return (error);
+ }
+ bus_write_1(sc->io_res, PIIX4_SMBHSTADD, slave | LSB);
+ bus_write_1(sc->io_res, PIIX4_SMBHSTCMD, cmd);
+ intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_WDATA, 0);
+ error = intsmb_stop(sc);
+ if (error == 0) {
+ *word = bus_read_1(sc->io_res, PIIX4_SMBHSTDAT0);
+ *word |= bus_read_1(sc->io_res, PIIX4_SMBHSTDAT1) << 8;
+ }
+ INTSMB_UNLOCK(sc);
+ return (error);
+}
+
+/*
+ * Data sheet claims that it implements all function, but also claims
+ * that it implements 7 function and not mention PCALL. So I don't know
+ * whether it will work.
+ */
+static int
+intsmb_pcall(device_t dev, u_char slave, char cmd, short sdata, short *rdata)
+{
+#ifdef PROCCALL_TEST
+ struct intsmb_softc *sc = device_get_softc(dev);
+ int error;
+
+ INTSMB_LOCK(sc);
+ error = intsmb_free(sc);
+ if (error) {
+ INTSMB_UNLOCK(sc);
+ return (error);
+ }
+ bus_write_1(sc->io_res, PIIX4_SMBHSTADD, slave & ~LSB);
+ bus_write_1(sc->io_res, PIIX4_SMBHSTCMD, cmd);
+ bus_write_1(sc->io_res, PIIX4_SMBHSTDAT0, sdata & 0xff);
+ bus_write_1(sc->io_res, PIIX4_SMBHSTDAT1, (sdata & 0xff) >> 8);
+ intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_WDATA, 0);
+ error = intsmb_stop(sc);
+ if (error == 0) {
+ *rdata = bus_read_1(sc->io_res, PIIX4_SMBHSTDAT0);
+ *rdata |= bus_read_1(sc->io_res, PIIX4_SMBHSTDAT1) << 8;
+ }
+ INTSMB_UNLOCK(sc);
+ return (error);
+#else
+ return (SMB_ENOTSUPP);
+#endif
+}
+
+static int
+intsmb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf)
+{
+ struct intsmb_softc *sc = device_get_softc(dev);
+ int error, i;
+
+ if (count > SMBBLOCKTRANS_MAX || count == 0)
+ return (SMB_EINVAL);
+
+ INTSMB_LOCK(sc);
+ error = intsmb_free(sc);
+ if (error) {
+ INTSMB_UNLOCK(sc);
+ return (error);
+ }
+
+ /* Reset internal array index. */
+ bus_read_1(sc->io_res, PIIX4_SMBHSTCNT);
+
+ bus_write_1(sc->io_res, PIIX4_SMBHSTADD, slave & ~LSB);
+ bus_write_1(sc->io_res, PIIX4_SMBHSTCMD, cmd);
+ for (i = 0; i < count; i++)
+ bus_write_1(sc->io_res, PIIX4_SMBBLKDAT, buf[i]);
+ bus_write_1(sc->io_res, PIIX4_SMBHSTDAT0, count);
+ intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_BLOCK, 0);
+ error = intsmb_stop(sc);
+ INTSMB_UNLOCK(sc);
+ return (error);
+}
+
+static int
+intsmb_bread(device_t dev, u_char slave, char cmd, u_char *count, char *buf)
+{
+ struct intsmb_softc *sc = device_get_softc(dev);
+ int error, i;
+ u_char data, nread;
+
+ if (*count > SMBBLOCKTRANS_MAX || *count == 0)
+ return (SMB_EINVAL);
+
+ INTSMB_LOCK(sc);
+ error = intsmb_free(sc);
+ if (error) {
+ INTSMB_UNLOCK(sc);
+ return (error);
+ }
+
+ /* Reset internal array index. */
+ bus_read_1(sc->io_res, PIIX4_SMBHSTCNT);
+
+ bus_write_1(sc->io_res, PIIX4_SMBHSTADD, slave | LSB);
+ bus_write_1(sc->io_res, PIIX4_SMBHSTCMD, cmd);
+ bus_write_1(sc->io_res, PIIX4_SMBHSTDAT0, *count);
+ intsmb_start(sc, PIIX4_SMBHSTCNT_PROT_BLOCK, 0);
+ error = intsmb_stop(sc);
+ if (error == 0) {
+ nread = bus_read_1(sc->io_res, PIIX4_SMBHSTDAT0);
+ if (nread != 0 && nread <= SMBBLOCKTRANS_MAX) {
+ for (i = 0; i < nread; i++) {
+ data = bus_read_1(sc->io_res, PIIX4_SMBBLKDAT);
+ if (i < *count)
+ buf[i] = data;
+ }
+ *count = nread;
+ } else
+ error = EIO;
+ }
+ INTSMB_UNLOCK(sc);
+ return (error);
+}
+
+static devclass_t intsmb_devclass;
+
+static device_method_t intsmb_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, intsmb_probe),
+ DEVMETHOD(device_attach, intsmb_attach),
+ DEVMETHOD(device_detach, intsmb_detach),
+
+ /* Bus interface */
+ DEVMETHOD(bus_print_child, bus_generic_print_child),
+
+ /* SMBus interface */
+ DEVMETHOD(smbus_callback, intsmb_callback),
+ DEVMETHOD(smbus_quick, intsmb_quick),
+ DEVMETHOD(smbus_sendb, intsmb_sendb),
+ DEVMETHOD(smbus_recvb, intsmb_recvb),
+ DEVMETHOD(smbus_writeb, intsmb_writeb),
+ DEVMETHOD(smbus_writew, intsmb_writew),
+ DEVMETHOD(smbus_readb, intsmb_readb),
+ DEVMETHOD(smbus_readw, intsmb_readw),
+ DEVMETHOD(smbus_pcall, intsmb_pcall),
+ DEVMETHOD(smbus_bwrite, intsmb_bwrite),
+ DEVMETHOD(smbus_bread, intsmb_bread),
+
+ { 0, 0 }
+};
+
+static driver_t intsmb_driver = {
+ "intsmb",
+ intsmb_methods,
+ sizeof(struct intsmb_softc),
+};
+
+DRIVER_MODULE(intsmb, pci, intsmb_driver, intsmb_devclass, 0, 0);
+DRIVER_MODULE(smbus, intsmb, smbus_driver, smbus_devclass, 0, 0);
+MODULE_DEPEND(intsmb, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER);
+MODULE_VERSION(intsmb, 1);
--- /dev/null
+/*-
+ * Copyright (c) 1998, 1999 Takanori Watanabe
+ * 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: src/sys/pci/intpmreg.h,v 1.5 2009/09/12 18:24:31 avg Exp $
+ */
+
+#ifndef __INTPMREG_H__
+#define __INTPMREG_H__
+
+/* Register definitions for non-ICH Intel Chipset SMBUS controllers. */
+
+/* PCI Config Registers. */
+#define PCI_BASE_ADDR_SMB 0x90 /* IO BAR. */
+#define PCI_BASE_ADDR_PM 0x40
+#define PCI_HST_CFG_SMB 0xd2 /* Host Configuration */
+#define PCI_INTR_SMB_MASK 0xe
+#define PCI_INTR_SMB_SMI 0
+#define PCI_INTR_SMB_IRQ_PCI 2
+#define PCI_INTR_SMB_IRQ9 8
+#define PCI_INTR_SMB_ENABLE 1
+#define PCI_SLV_CMD_SMB 0xd3 /*SLAVE COMMAND*/
+#define PCI_SLV_SDW_SMB_1 0xd4 /*SLAVE SHADOW PORT 1*/
+#define PCI_SLV_SDW_SMB_2 0xd5 /*SLAVE SHADOW PORT 2*/
+#define PCI_REVID_SMB 0xd6
+
+/* PIXX4 SMBus Registers in the SMB BAR. */
+#define PIIX4_SMBHSTSTS 0x00
+#define PIIX4_SMBHSTSTAT_BUSY (1<<0)
+#define PIIX4_SMBHSTSTAT_INTR (1<<1)
+#define PIIX4_SMBHSTSTAT_ERR (1<<2)
+#define PIIX4_SMBHSTSTAT_BUSC (1<<3)
+#define PIIX4_SMBHSTSTAT_FAIL (1<<4)
+#define PIIX4_SMBSLVSTS 0x01
+#define PIIX4_SMBSLVSTS_ALART (1<<5)
+#define PIIX4_SMBSLVSTS_SDW2 (1<<4)
+#define PIIX4_SMBSLVSTS_SDW1 (1<<3)
+#define PIIX4_SMBSLVSTS_SLV (1<<2)
+#define PIIX4_SMBSLVSTS_BUSY (1<<0)
+#define PIIX4_SMBHSTCNT 0x02
+#define PIIX4_SMBHSTCNT_START (1<<6)
+#define PIIX4_SMBHSTCNT_PROT_QUICK 0
+#define PIIX4_SMBHSTCNT_PROT_BYTE (1<<2)
+#define PIIX4_SMBHSTCNT_PROT_BDATA (2<<2)
+#define PIIX4_SMBHSTCNT_PROT_WDATA (3<<2)
+#define PIIX4_SMBHSTCNT_PROT_BLOCK (5<<2)
+#define PIIX4_SMBHSTCNT_KILL (1<<1)
+#define PIIX4_SMBHSTCNT_INTREN (1)
+#define PIIX4_SMBHSTCMD 0x03
+#define PIIX4_SMBHSTADD 0x04
+#define LSB 0x1
+#define PIIX4_SMBHSTDAT0 0x05
+#define PIIX4_SMBHSTDAT1 0x06
+#define PIIX4_SMBBLKDAT 0x07
+#define PIIX4_SMBSLVCNT 0x08
+#define PIIX4_SMBSLVCNT_ALTEN (1<<3)
+#define PIIX4_SMBSLVCNT_SD2EN (1<<2)
+#define PIIX4_SMBSLVCNT_SD1EN (1<<1)
+#define PIIX4_SMBSLVCNT_SLVEN (1)
+#define PIIX4_SMBSLVCMD 0x09
+#define PIIX4_SMBSLVEVT 0x0a
+#define PIIX4_SMBSLVDAT 0x0c
+
+/* SMBus alert response address. */
+#define SMBALTRESP 0x18
+
+#define SMBBLOCKTRANS_MAX 32
+
+#endif /* !__INTPMREG_H__ */
--- /dev/null
+# $FreeBSD: src/sys/modules/i2c/controllers/viapm/Makefile,v 1.3 2007/06/24 20:35:59 njl Exp $
+
+.PATH: ${.CURDIR}/../../../../bus/pci
+KMOD = viapm
+SRCS = device_if.h bus_if.h iicbb_if.h isa_if.h pci_if.h smbus_if.h \
+ opt_isa.h viapm.c
+
+.include <bsd.kmod.mk>
/*-
* Copyright (c) 2001 Alcove - Nicolas Souchu
- * Copyright (c) 2002 Nicolas Souchu
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: src/sys/pci/viapm.c,v 1.1.2.1 2002/04/19 05:52:15 nsouch Exp $
- * $DragonFly: src/sys/dev/powermng/i386/viapm/viapm.c,v 1.10 2006/12/22 23:26:23 swildner Exp $
+ * $FreeBSD: src/sys/pci/viapm.c,v 1.10.2.3 2006/09/22 19:19:16 jhb Exp $
*
*/
#include <sys/param.h>
#include <bus/pci/pcireg.h>
#include <bus/iicbus/iiconf.h>
-#include <bus/iicbus/iicbus.h>
#include <bus/smbus/smbconf.h>
-#include <bus/smbus/smbus.h>
#include "iicbb_if.h"
#include "smbus_if.h"
#define VIA_596B_PMU_ID 0x30511106
#define VIA_686A_PMU_ID 0x30571106
#define VIA_8233_PMU_ID 0x30741106
+#define VIA_8233A_PMU_ID 0x31471106
+#define VIA_8235_PMU_ID 0x31771106
#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))
+ (bus_space_write_1(viapm->st, viapm->sh, port, (u_char)(val)))
#define VIAPM_TYP_UNKNOWN 0
#define VIAPM_TYP_586B_3040E 1
return ENXIO;
}
device_set_desc(dev, "VIA VT82C586B Power Management Unit");
- return 0;
+ return (BUS_PROBE_DEFAULT);
default:
break;
goto viapro;
case VIA_8233_PMU_ID:
+ case VIA_8233A_PMU_ID:
desc = "VIA VT8233 Power Management Unit";
viapm->type = VIAPM_TYP_UNKNOWN;
base_cfgreg = VIAPM_8233_BASE;
goto viapro;
+ case VIA_8235_PMU_ID:
+ desc = "VIA VT8235 Power Management Unit";
+ viapm->type = VIAPM_TYP_UNKNOWN;
+ base_cfgreg = VIAPM_8233_BASE;
+ goto viapro;
+
viapro:
#ifdef VIAPM_BASE_ADDR
}
device_set_desc(dev, desc);
- return 0;
+ return (BUS_PROBE_DEFAULT);
default:
break;
}
error = bus_setup_intr(dev, viapm->irqres, 0,
- (driver_intr_t *) viasmb_intr, viapm,
+ (driver_intr_t *) viasmb_intr, viapm,
&viapm->irqih, NULL);
if (error) {
device_printf(dev, "could not setup irq\n");
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;
}
-
+
static int
viabb_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr)
{
return (IIC_ENOADDR);
}
-#if 0
static int
viabb_getscl(device_t dev)
{
return ((VIAPM_INB(EXTSMI_VAL) & VIAPM_SCL) != 0);
}
-#endif
static int
viabb_getsda(device_t dev)
return ((VIAPM_INB(EXTSMI_VAL) & VIAPM_SDA) != 0);
}
-static void
-viabb_setlines(device_t dev, int ctrl, int data)
-{
- viabb_setscl(dev, ctrl);
- viabb_setsda(dev, data);
-
- return;
-}
-
static int
viapm_abort(struct viapm_softc *viapm)
{
viapm_clear(viapm);
if (viapm_busy(viapm))
- return (EBUSY);
+ return (SMB_EBUSY);
switch (how) {
case SMB_QWRITE:
viapm_clear(viapm);
if (viapm_busy(viapm))
- return (EBUSY);
+ return (SMB_EBUSY);
VIAPM_OUTB(SMBHADDR, slave & ~ LSB);
VIAPM_OUTB(SMBHCMD, byte);
viapm_clear(viapm);
if (viapm_busy(viapm))
- return (EBUSY);
+ return (SMB_EBUSY);
VIAPM_OUTB(SMBHADDR, slave | LSB);
viapm_clear(viapm);
if (viapm_busy(viapm))
- return (EBUSY);
+ return (SMB_EBUSY);
VIAPM_OUTB(SMBHADDR, slave & ~ LSB);
VIAPM_OUTB(SMBHCMD, cmd);
viapm_clear(viapm);
if (viapm_busy(viapm))
- return (EBUSY);
+ return (SMB_EBUSY);
VIAPM_OUTB(SMBHADDR, slave | LSB);
VIAPM_OUTB(SMBHCMD, cmd);
viapm_clear(viapm);
if (viapm_busy(viapm))
- return (EBUSY);
+ return (SMB_EBUSY);
VIAPM_OUTB(SMBHADDR, slave & ~ LSB);
VIAPM_OUTB(SMBHCMD, cmd);
viapm_clear(viapm);
if (viapm_busy(viapm))
- return (EBUSY);
+ return (SMB_EBUSY);
VIAPM_OUTB(SMBHADDR, slave | LSB);
VIAPM_OUTB(SMBHCMD, cmd);
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;
+ u_char i;
+ int error;
+
+ if (count < 1 || count > 32)
+ return (SMB_EINVAL);
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);
+ return (SMB_EBUSY);
- if ((error = viapm_wait(viapm)) != SMB_ENOERR)
- goto error;
+ VIAPM_OUTB(SMBHADDR, slave & ~LSB);
+ VIAPM_OUTB(SMBHCMD, cmd);
+ VIAPM_OUTB(SMBHDATA0, count);
+ i = VIAPM_INB(SMBHCTRL);
- remain -= len;
+ /* fill the 32-byte internal buffer */
+ for (i = 0; i < count; i++) {
+ VIAPM_OUTB(SMBHBLOCK, buf[i]);
+ DELAY(2);
}
+ VIAPM_OUTB(SMBHCMD, cmd);
+ VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_BLOCK);
+
+ error = viapm_wait(viapm);
-error:
VIAPM_DEBUG(kprintf("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)
+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;
+ u_char data, len, i;
+ int error;
+
+ if (*count < 1 || *count > 32)
+ return (SMB_EINVAL);
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);
+ return (SMB_EBUSY);
- if ((error = viapm_wait(viapm)) != SMB_ENOERR)
- goto error;
-
- len = VIAPM_INB(SMBHDATA0);
- i = VIAPM_INB(SMBHCTRL); /* reset counter */
+ VIAPM_OUTB(SMBHADDR, slave | LSB);
+ VIAPM_OUTB(SMBHCMD, cmd);
+ VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_BLOCK);
- len = min(len, remain);
+ if ((error = viapm_wait(viapm)) != SMB_ENOERR)
+ goto error;
- /* read the 32-byte internal buffer */
- for (i=0; i<len; i++) {
- buf[count-remain+i] = VIAPM_INB(SMBHBLOCK);
- DELAY(2);
- }
+ len = VIAPM_INB(SMBHDATA0);
+ i = VIAPM_INB(SMBHCTRL); /* reset counter */
- remain -= len;
+ /* read the 32-byte internal buffer */
+ for (i = 0; i < len; i++) {
+ data = VIAPM_INB(SMBHBLOCK);
+ if (i < *count)
+ buf[i] = data;
+ DELAY(2);
}
+ *count = len;
+
error:
- VIAPM_DEBUG(kprintf("viapm: READBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, count, cmd, error));
+ VIAPM_DEBUG(kprintf("viapm: READBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, *count, cmd, error));
return (error);
}
/* iicbb interface */
DEVMETHOD(iicbb_callback, viabb_callback),
- DEVMETHOD(iicbb_setlines, viabb_setlines),
- DEVMETHOD(iicbb_getdataline, viabb_getsda),
+ 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),
+ /* Bus interface */
+ DEVMETHOD(bus_print_child, bus_generic_print_child),
+ DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
+ DEVMETHOD(bus_release_resource, bus_generic_release_resource),
+ DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
+ DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
+ DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
+ DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
+
{ 0, 0 }
};
DEVMETHOD(smbus_readw, viasmb_readw),
DEVMETHOD(smbus_bwrite, viasmb_bwrite),
DEVMETHOD(smbus_bread, viasmb_bread),
-
+
+ /* Bus interface */
+ DEVMETHOD(bus_print_child, bus_generic_print_child),
+ DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
+ DEVMETHOD(bus_release_resource, bus_generic_release_resource),
+ DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
+ DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
+ DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
+ DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
+
{ 0, 0 }
};
DECLARE_DUMMY_MODULE(viapm);
DRIVER_MODULE(viapm, pci, viapm_driver, viapm_devclass, 0, 0);
DRIVER_MODULE(viapropm, pci, viapropm_driver, viapropm_devclass, 0, 0);
+DRIVER_MODULE(smbus, viapropm, smbus_driver, smbus_devclass, 0, 0);
+MODULE_DEPEND(viapm, pci, 1, 1, 1);
+MODULE_DEPEND(viapropm, pci, 1, 1, 1);
MODULE_DEPEND(viapm, iicbb, IICBB_MINVER, IICBB_PREFVER, IICBB_MAXVER);
MODULE_DEPEND(viapropm, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER);
MODULE_VERSION(viapm, 1);
# $DragonFly: src/sys/dev/video/Makefile,v 1.2 2003/10/23 17:32:52 dillon Exp $
#
-SUBDIR=bktr fb ${MACHINE_ARCH}
+SUBDIR=bktr cxm fb ${MACHINE_ARCH}
.include <bsd.subdir.mk>
--- /dev/null
+SUBDIR =
+SUBDIR += cxm
+SUBDIR += cxm_iic
+
+.include <bsd.subdir.mk>
--- /dev/null
+.PATH: ${.CURDIR}/..
+KMOD = cxm
+SRCS = cxm.c cxm.h cxm_dec_fw.c cxm_enc_fw.c cxm_msp34xxx.c cxm_eeprom.c \
+ cxm_ir.c cxm_tuner.c cxm_saa7115.c opt_cxm.h \
+ bus_if.h device_if.h iicbb_if.h pci_if.h
+
+.include <bsd.kmod.mk>
static int cxm_iic_callback(device_t, int, caddr_t *);
static int cxm_iic_reset(device_t, u_char, u_char, u_char *);
-#if 0
static int cxm_iic_getscl(device_t);
-#endif
static int cxm_iic_getsda(device_t);
static void cxm_iic_setscl(device_t, int);
static void cxm_iic_setsda(device_t, int);
-static void cxm_iic_setlines(device_t, int, int);
static device_method_t cxm_iic_methods[] = {
/* Device interface */
/* iicbb interface */
DEVMETHOD(iicbb_callback, cxm_iic_callback),
DEVMETHOD(iicbb_reset, cxm_iic_reset),
- DEVMETHOD(iicbb_getdataline, cxm_iic_getsda),
- DEVMETHOD(iicbb_setlines, cxm_iic_setlines),
+ DEVMETHOD(iicbb_getscl, cxm_iic_getscl),
+ DEVMETHOD(iicbb_getsda, cxm_iic_getsda),
+ DEVMETHOD(iicbb_setscl, cxm_iic_setscl),
+ DEVMETHOD(iicbb_setsda, cxm_iic_setsda),
{ 0, 0 }
};
static devclass_t cxm_iic_devclass;
-MODULE_VERSION(cxm_iic, 1);
DRIVER_MODULE(cxm_iic, cxm, cxm_iic_driver, cxm_iic_devclass, 0, 0);
+MODULE_VERSION(cxm_iic, 1);
+MODULE_DEPEND(cxm_iic, iicbb, IICBB_MINVER, IICBB_PREFVER, IICBB_MAXVER);
/*
}
-#if 0
static int
cxm_iic_getscl(device_t dev)
{
/* Get sda */
return CSR_READ_1(sc, CXM_REG_I2C_GETSCL);
}
-#endif
static int
CSR_READ_4(sc, CXM_REG_I2C_SETSDA);
}
-
-
-static void
-cxm_iic_setlines(device_t dev, int ctrl, int data)
-{
-
- cxm_iic_setscl(dev, ctrl);
- cxm_iic_setsda(dev, data);
-
- /* Wait for 10 usec */
- DELAY(10);
-}
--- /dev/null
+.PATH: ${.CURDIR}/..
+KMOD = cxm_iic
+SRCS = cxm_i2c.c cxm.h \
+ opt_cxm.h bus_if.h device_if.h iicbb_if.h pci_if.h
+
+.include <bsd.kmod.mk>
dev/misc/labpc/labpc.c optional labpc
dev/misc/mse/mse.c optional mse
platform/pc32/isa/npx.c mandatory npx
-bus/iicbus/i386/pcf.c optional pcf
bus/pci/i386/legacy.c optional pci
bus/pci/i386/pci_bus.c optional pci
bus/pci/i386/pci_cfgreg.c optional pci