diff options
author | nsouch <nsouch@FreeBSD.org> | 2002-03-23 15:49:15 +0000 |
---|---|---|
committer | nsouch <nsouch@FreeBSD.org> | 2002-03-23 15:49:15 +0000 |
commit | 82395b7295123f4d9a786ebd89495ef101103a61 (patch) | |
tree | f78e24d69b8d02162ae886a610fb85cac8989741 /sys/dev/iicbus | |
parent | 0dcefe7b55beecbfaeba7c0b20e4b1277b781733 (diff) | |
download | FreeBSD-src-82395b7295123f4d9a786ebd89495ef101103a61.zip FreeBSD-src-82395b7295123f4d9a786ebd89495ef101103a61.tar.gz |
Major rework of the iicbus/smbus framework:
- VIA chipset SMBus controllers added
- alpm driver updated
- Support for dynamic modules added
- bktr FreeBSD smbus updated but not tested
- cleanup
Diffstat (limited to 'sys/dev/iicbus')
-rw-r--r-- | sys/dev/iicbus/if_ic.c | 10 | ||||
-rw-r--r-- | sys/dev/iicbus/iic.c | 69 | ||||
-rw-r--r-- | sys/dev/iicbus/iicbb.c | 126 | ||||
-rw-r--r-- | sys/dev/iicbus/iicbb_if.m | 27 | ||||
-rw-r--r-- | sys/dev/iicbus/iicbus.c | 166 | ||||
-rw-r--r-- | sys/dev/iicbus/iiconf.c | 33 | ||||
-rw-r--r-- | sys/dev/iicbus/iiconf.h | 12 | ||||
-rw-r--r-- | sys/dev/iicbus/iicsmb.c | 106 |
8 files changed, 283 insertions, 266 deletions
diff --git a/sys/dev/iicbus/if_ic.c b/sys/dev/iicbus/if_ic.c index 2db1841..28b3d1a 100644 --- a/sys/dev/iicbus/if_ic.c +++ b/sys/dev/iicbus/if_ic.c @@ -1,5 +1,5 @@ /*- - * 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 @@ -30,7 +30,6 @@ * I2C bus IP driver */ -#ifdef _KERNEL #include <sys/param.h> #include <sys/systm.h> #include <sys/mbuf.h> @@ -47,7 +46,6 @@ #include <net/if_types.h> #include <net/netisr.h> -#endif #include <sys/mbuf.h> #include <sys/socket.h> #include <net/netisr.h> @@ -65,6 +63,8 @@ #include "iicbus_if.h" +#define PCF_MASTER_ADDRESS 0xaa + #define ICHDRLEN sizeof(u_int) #define ICMTU 1500 /* default mtu */ @@ -130,7 +130,7 @@ icattach(device_t dev) 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; ifp->if_name = "ic"; @@ -448,3 +448,5 @@ error: } DRIVER_MODULE(ic, iicbus, ic_driver, ic_devclass, 0, 0); +MODULE_DEPEND(ic, iicbus, IICBUS_MINVER, IICBUS_PREFVER, IICBUS_MAXVER); +MODULE_VERSION(ic, 1); diff --git a/sys/dev/iicbus/iic.c b/sys/dev/iicbus/iic.c index a8d731e..37d0660 100644 --- a/sys/dev/iicbus/iic.c +++ b/sys/dev/iicbus/iic.c @@ -1,5 +1,5 @@ /*- - * 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 @@ -47,11 +47,13 @@ struct iic_softc { - u_char sc_addr; /* address on iicbus */ + 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 */ + + dev_t sc_devnode; }; #define IIC_SOFTC(unit) \ @@ -62,13 +64,17 @@ struct iic_softc { 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), @@ -105,30 +111,44 @@ static struct cdevsw iic_cdevsw = { /* flags */ 0, }; -/* - * iicprobe() - */ +static void +iic_identify(driver_t *driver, device_t parent) +{ + BUS_ADD_CHILD(parent, 0, "iic", 0); +} + 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); - - /* 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_cdevsw, device_get_unit(dev), /* XXX cleanup */ + struct iic_softc *sc = (struct iic_softc *)device_get_softc(dev); + + if (!sc) + return (ENOMEM); + + bzero(sc, sizeof(struct iic_softc)); + + sc->sc_devnode = make_dev(&iic_cdevsw, device_get_unit(dev), UID_ROOT, GID_WHEEL, 0600, "iic%d", device_get_unit(dev)); + + return (0); +} + +static int +iic_detach(device_t dev) +{ + struct iic_softc *sc = (struct iic_softc *)device_get_softc(dev); + + if (sc->sc_devnode) + destroy_dev(sc->sc_devnode); + return (0); } @@ -174,7 +194,7 @@ iicwrite(dev_t dev, struct uio * uio, int ioflag) struct iic_softc *sc = IIC_SOFTC(minor(dev)); int sent, error, count; - if (!sc || !iicdev) + if (!sc || !iicdev || !sc->sc_addr) return (EINVAL); if (sc->sc_count == 0) @@ -202,7 +222,7 @@ iicread(dev_t dev, struct uio * uio, int ioflag) int len, error = 0; int bufsize; - if (!sc || !iicdev) + if (!sc || !iicdev || !sc->sc_addr) return (EINVAL); if (sc->sc_count == 0) @@ -246,6 +266,15 @@ iicioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct thread *td) switch (cmd) { case I2CSTART: 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; + break; case I2CSTOP: @@ -257,11 +286,11 @@ iicioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct thread *td) break; case I2CWRITE: - error = iicbus_write(parent, s->buf, s->count, &count, 0); + error = iicbus_write(parent, s->buf, s->count, &count, 10); break; case I2CREAD: - error = iicbus_read(parent, s->buf, s->count, &count, s->last, 0); + error = iicbus_read(parent, s->buf, s->count, &count, s->last, 10); break; default: @@ -274,3 +303,5 @@ iicioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct thread *td) } DRIVER_MODULE(iic, iicbus, iic_driver, iic_devclass, 0, 0); +MODULE_DEPEND(iic, iicbus, IICBUS_MINVER, IICBUS_PREFVER, IICBUS_MAXVER); +MODULE_VERSION(iic, 1); diff --git a/sys/dev/iicbus/iicbb.c b/sys/dev/iicbus/iicbb.c index 56bc390..436626c 100644 --- a/sys/dev/iicbus/iicbb.c +++ b/sys/dev/iicbus/iicbb.c @@ -1,5 +1,5 @@ /*- - * 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 @@ -41,7 +41,6 @@ * 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> @@ -61,11 +60,12 @@ #include "iicbb_if.h" struct iicbb_softc { - int dummy; + device_t iicbus; }; static int iicbb_probe(device_t); static int iicbb_attach(device_t); +static int iicbb_detach(device_t); static int iicbb_print_child(device_t, device_t); static int iicbb_callback(device_t, int, caddr_t); @@ -79,7 +79,7 @@ static device_method_t iicbb_methods[] = { /* device interface */ DEVMETHOD(device_probe, iicbb_probe), DEVMETHOD(device_attach, iicbb_attach), - DEVMETHOD(device_detach, bus_generic_detach), + DEVMETHOD(device_detach, iicbb_detach), /* bus interface */ DEVMETHOD(bus_print_child, iicbb_print_child), @@ -106,13 +106,36 @@ static devclass_t iicbb_devclass; static int iicbb_probe(device_t dev) { - device_set_desc(dev, "I2C generic bit-banging driver"); + device_set_desc(dev, "I2C bit-banging driver"); return (0); } static int iicbb_attach(device_t dev) { + struct iicbb_softc *sc = (struct iicbb_softc *)device_get_softc(dev); + + bzero(sc, sizeof(struct iicbb_softc)); + + sc->iicbus = device_add_child(dev, "iicbus", -1); + + if (!sc->iicbus) + return (ENXIO); + + bus_generic_attach(dev); + + return (0); +} + +static int iicbb_detach(device_t dev) +{ + struct iicbb_softc *sc = (struct iicbb_softc *)device_get_softc(dev); + + if (sc->iicbus) { + bus_generic_detach(dev); + device_delete_child(dev, sc->iicbus); + } + return (0); } @@ -140,15 +163,51 @@ iicbb_print_child(device_t bus, device_t 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_GETSDA(dev) (IICBB_GETSDA(device_get_parent(dev))) -#define I2C_GET(dev) (IICBB_GETDATALINE(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) -static void iicbb_one(device_t dev) +#define I2C_LOG(format,args...) do { \ + printf(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, int timeout) { I2C_SET(dev,0,1); I2C_SET(dev,1,1); @@ -156,7 +215,7 @@ static void iicbb_one(device_t dev) return; } -static void iicbb_zero(device_t dev) +static void iicbb_zero(device_t dev, int timeout) { I2C_SET(dev,0,0); I2C_SET(dev,1,0); @@ -181,17 +240,17 @@ static void iicbb_zero(device_t dev) static int 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(printf("%c ",noack?'-':'+')); @@ -199,18 +258,22 @@ static int iicbb_ack(device_t dev, int timeout) return (noack); } -static void iicbb_sendbyte(device_t dev, u_char data) +static void 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(printf("w%02x",(int)data)); return; } -static u_char iicbb_readbyte(device_t dev, int last) +static u_char iicbb_readbyte(device_t dev, int last, int timeout) { int i; unsigned char data=0; @@ -219,11 +282,15 @@ static u_char iicbb_readbyte(device_t dev, int last) 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(printf("r%02x%c ",(int)data,last?'-':'+')); return data; } @@ -244,13 +311,12 @@ static int iicbb_start(device_t dev, u_char slave, int timeout) I2C_DEBUG(printf("<")); - 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)) { @@ -282,7 +348,7 @@ static int iicbb_write(device_t dev, char * buf, int len, int *sent, 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)) { @@ -306,7 +372,7 @@ static int iicbb_read(device_t dev, char * buf, int len, int *read, 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 --; @@ -316,5 +382,9 @@ static int iicbb_read(device_t dev, char * buf, int len, int *read, return (0); } -DRIVER_MODULE(iicbb, bti2c, iicbb_driver, iicbb_devclass, 0, 0); +DRIVER_MODULE(iicbb, bktr, 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); diff --git a/sys/dev/iicbus/iicbb_if.m b/sys/dev/iicbus/iicbb_if.m index 94baa41..5642741 100644 --- a/sys/dev/iicbus/iicbb_if.m +++ b/sys/dev/iicbus/iicbb_if.m @@ -40,19 +40,34 @@ METHOD int callback { }; # -# Set I2C bus lines +# Set I2C bus data line # -METHOD void setlines { +METHOD void setsda { device_t dev; - int ctrl; - int data; + int val; }; # -# Get I2C bus lines +# Set I2C bus clock line +# +METHOD void setscl { + device_t dev; + int val; +}; + +# +# Get I2C bus data line +# +# +METHOD int getsda { + device_t dev; +}; + +# +# Get I2C bus clock line # # -METHOD int getdataline { +METHOD int getscl { device_t dev; }; diff --git a/sys/dev/iicbus/iicbus.c b/sys/dev/iicbus/iicbus.c index 1a20543..f20c658 100644 --- a/sys/dev/iicbus/iicbus.c +++ b/sys/dev/iicbus/iicbus.c @@ -1,5 +1,5 @@ /*- - * 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 @@ -45,45 +45,6 @@ #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 } -}; - static devclass_t iicbus_devclass; /* @@ -91,21 +52,19 @@ static devclass_t iicbus_devclass; */ 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), { 0, 0 } }; @@ -154,9 +113,6 @@ iic_probe_device(device_t dev, u_char addr) static int iicbus_attach(device_t dev) { - struct iicbus_device *iicdev; - device_t child; - iicbus_reset(dev, IIC_FASTEST, 0, NULL); /* device probing is meaningless since the bus is supposed to be @@ -175,42 +131,34 @@ iicbus_attach(device_t dev) } printf("\n"); #endif + + /* attach any known device */ + device_add_child(dev, NULL, -1); - /* 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) - printf("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) - printf("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); - } - } bus_generic_attach(dev); return (0); } + +static int +iicbus_detach(device_t dev) +{ + iicbus_reset(dev, IIC_FASTEST, 0, NULL); + + bus_generic_detach(dev); + + return (0); +} + +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_generic_intr(device_t dev, int event, char *buf) @@ -230,59 +178,7 @@ iicbus_null_repeated_start(device_t dev, u_char addr) return (IIC_ENOTSUPP); } -static int -iicbus_print_child(device_t bus, device_t dev) -{ - 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 += printf(" 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); -} - -static int -iicbus_read_ivar(device_t bus, device_t dev, int index, u_long* result) -{ - 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) -{ - switch (index) { - default: - return (ENOENT); - } - - return (0); -} - 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); diff --git a/sys/dev/iicbus/iiconf.c b/sys/dev/iicbus/iiconf.c index c3156d2..8927792 100644 --- a/sys/dev/iicbus/iiconf.c +++ b/sys/dev/iicbus/iiconf.c @@ -50,22 +50,6 @@ iicbus_intr(device_t bus, int event, char *buf) 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) { @@ -346,20 +330,3 @@ iicbus_block_read(device_t bus, u_char slave, char *buf, int len, int *read) return (error); } - -/* - * iicbus_get_addr() - * - * Get the I2C 7 bits address of the device - */ -u_char -iicbus_get_addr(device_t dev) -{ - uintptr_t addr; - device_t parent = device_get_parent(dev); - - BUS_READ_IVAR(parent, dev, IICBUS_IVAR_ADDR, &addr); - - return ((u_char)addr); -} - diff --git a/sys/dev/iicbus/iiconf.h b/sys/dev/iicbus/iiconf.h index 03a4a76..a9e6d76 100644 --- a/sys/dev/iicbus/iiconf.h +++ b/sys/dev/iicbus/iiconf.h @@ -1,5 +1,5 @@ /*- - * 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 @@ -127,4 +127,14 @@ extern int iicbus_block_read(device_t, u_char, char *, int, int *); extern u_char iicbus_get_addr(device_t); +#define IICBUS_MODVER 1 +#define IICBUS_MINVER 1 +#define IICBUS_MAXVER 1 +#define IICBUS_PREFVER IICBUS_MODVER + +#define IICBB_MODVER 1 +#define IICBB_MINVER 1 +#define IICBB_MAXVER 1 +#define IICBB_PREFVER IICBB_MODVER + #endif diff --git a/sys/dev/iicbus/iicsmb.c b/sys/dev/iicbus/iicsmb.c index a38845bdb..9bc4d86 100644 --- a/sys/dev/iicbus/iicsmb.c +++ b/sys/dev/iicbus/iicsmb.c @@ -1,5 +1,5 @@ /*- - * 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 @@ -79,6 +79,8 @@ struct iicsmb_softc { 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); @@ -97,11 +99,13 @@ 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 */ @@ -129,16 +133,18 @@ static driver_t iicsmb_driver = { sizeof(struct iicsmb_softc), }; +#define IICBUS_TIMEOUT 100 /* us */ + +static void +iicsmb_identify(driver_t *driver, device_t parent) +{ + BUS_ADD_CHILD(parent, 0, "iicsmb", 0); +} + static int iicsmb_probe(device_t dev) { - struct iicsmb_softc *sc = (struct iicsmb_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, "SMBus over I2C bridge"); return (0); } @@ -147,8 +153,25 @@ iicsmb_attach(device_t dev) { struct iicsmb_softc *sc = (struct iicsmb_softc *)device_get_softc(dev); + bzero(sc, sizeof(*sc)); + + sc->smbus = device_add_child(dev, "smbus", -1); + /* probe and attach the smbus */ - device_probe_and_attach(sc->smbus); + bus_generic_attach(dev); + + return (0); +} + +static int +iicsmb_detach(device_t dev) +{ + struct iicsmb_softc *sc = (struct iicsmb_softc *)device_get_softc(dev); + + bus_generic_detach(dev); + if (sc->smbus) { + device_delete_child(dev, sc->smbus); + } return (0); } @@ -259,11 +282,11 @@ iicsmb_quick(device_t dev, u_char slave, int how) 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: @@ -283,10 +306,10 @@ iicsmb_sendb(device_t dev, u_char slave, char byte) 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); } @@ -303,7 +326,7 @@ iicsmb_recvb(device_t dev, u_char slave, char *byte) 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); } @@ -320,8 +343,8 @@ iicsmb_writeb(device_t dev, u_char slave, char cmd, char byte) 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); } @@ -341,9 +364,9 @@ iicsmb_writew(device_t dev, u_char slave, char cmd, short word) 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); } @@ -357,16 +380,16 @@ iicsmb_readb(device_t dev, u_char slave, char cmd, char *byte) 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: @@ -384,16 +407,16 @@ iicsmb_readw(device_t dev, u_char slave, char cmd, short *word) 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 */ @@ -411,23 +434,23 @@ iicsmb_pcall(device_t dev, u_char slave, char cmd, short sdata, short *rdata) 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 */ @@ -444,13 +467,13 @@ iicsmb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf) 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))) @@ -466,17 +489,17 @@ 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))) + IIC_LAST_READ, IICBUS_TIMEOUT))) goto error; error: @@ -485,3 +508,6 @@ error: } DRIVER_MODULE(iicsmb, iicbus, iicsmb_driver, iicsmb_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); |