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 | |
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')
42 files changed, 1759 insertions, 820 deletions
diff --git a/sys/amd64/pci/pci_bus.c b/sys/amd64/pci/pci_bus.c index 56f023b..91bee0c 100644 --- a/sys/amd64/pci/pci_bus.c +++ b/sys/amd64/pci/pci_bus.c @@ -493,6 +493,19 @@ DRIVER_MODULE(pcib, nexus, nexus_pcib_driver, pcib_devclass, 0, 0); static int pci_hostb_probe(device_t dev) { + u_int32_t id; + + id = pci_get_devid(dev); + + switch (id) { + + /* VIA VT82C596 Power Managment Function */ + case 0x30501106: + return ENXIO; + + default: + break; + } if (pci_get_class(dev) == PCIC_BRIDGE && pci_get_subclass(dev) == PCIS_BRIDGE_HOST) { diff --git a/sys/conf/NOTES b/sys/conf/NOTES index b6c703f..7cec293 100644 --- a/sys/conf/NOTES +++ b/sys/conf/NOTES @@ -2378,11 +2378,16 @@ device nmdm device meteor 1 +# +# options BKTR_USE_FREEBSD_SMBUS +# Compile with FreeBSD SMBus implementation +# # Brooktree driver has been ported to the new I2C framework. Thus, # you'll need to have the following 3 lines in the kernel config. # device smbus # device iicbus # device iicbb +# device iicsmb # The iic and smb devices are only needed if you want to control other # I2C slaves connected to the external connector of some cards. # diff --git a/sys/conf/files b/sys/conf/files index c6c73a6..10fb24d 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1260,6 +1260,7 @@ pci/ncr.c optional ncr pci/ohci_pci.c optional ohci pci/simos.c optional simos pci/uhci_pci.c optional uhci +pci/viapm.c optional viapm pci/xrpu.c optional xrpu posix4/ksched.c optional _kposix_priority_scheduling posix4/p1003_1b.c standard diff --git a/sys/conf/options b/sys/conf/options index fede7fd..58e4fe3 100644 --- a/sys/conf/options +++ b/sys/conf/options @@ -441,6 +441,7 @@ BKTR_GPIO_ACCESS opt_bktr.h BKTR_NO_MSP_RESET opt_bktr.h BKTR_430_FX_MODE opt_bktr.h BKTR_SIS_VIA_MODE opt_bktr.h +BKTR_USE_FREEBSD_SMBUS opt_bktr.h # meteor opt_meteor.h METEOR_ALLOC_PAGES opt_meteor.h diff --git a/sys/dev/bktr/bktr_i2c.c b/sys/dev/bktr/bktr_i2c.c index 4f61e5c..20342d1 100644 --- a/sys/dev/bktr/bktr_i2c.c +++ b/sys/dev/bktr/bktr_i2c.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 @@ -33,10 +33,13 @@ * From brooktree848.c <fsmp@freefall.org> */ +#include "opt_bktr.h" + #include "bktr.h" #include <sys/param.h> #include <sys/kernel.h> +#include <sys/malloc.h> #include <sys/systm.h> #include <sys/module.h> #include <sys/bus.h> @@ -62,196 +65,91 @@ #include <pci/pcireg.h> #include <machine/ioctl_meteor.h> #include <machine/ioctl_bt848.h> /* extensions to ioctl_meteor.h */ -#include <dev/bktr/bktr_reg.h> +#include <dev/bktr/bktr_reg.h> #include <dev/bktr/bktr_i2c.h> -#include <dev/iicbus/iiconf.h> -#include <dev/iicbus/iicbus.h> - #include <dev/smbus/smbconf.h> - -#include "iicbb_if.h" -#include "smbus_if.h" - - +#include <dev/iicbus/iiconf.h> #define I2C_DELAY 40 #define BTI2C_DEBUG(x) if (bti2c_debug) (x) static int bti2c_debug = 0; -struct bti2c_softc { - - bus_space_tag_t memt; /* Bus space register access */ - bus_space_handle_t memh; /* Bus space register access */ - - int iic_owned; /* 1 if we own the iicbus */ - int smb_owned; /* 1 if we own the smbbus */ - - device_t smbus; - device_t iicbus; -}; - -struct bt_data { - bus_space_tag_t memt; - bus_space_handle_t memh; -}; -struct bt_data btdata[NBKTR]; - -static int bti2c_probe(device_t); -static int bti2c_attach(device_t); - -static int bti2c_iic_callback(device_t, int, caddr_t *); -static void bti2c_iic_setlines(device_t, int, int); -static int bti2c_iic_getdataline(device_t); -static int bti2c_iic_reset(device_t, u_char, u_char, u_char *); - -static int bti2c_smb_callback(device_t, int, caddr_t *); -static int bti2c_smb_writeb(device_t dev, u_char slave, char cmd, char byte); -static int bti2c_smb_writew(device_t dev, u_char slave, char cmd, short word); -static int bti2c_smb_readb(device_t dev, u_char slave, char cmd, char *byte); - -static devclass_t bti2c_devclass; - -static device_method_t bti2c_methods[] = { - /* device interface */ - DEVMETHOD(device_probe, bti2c_probe), - DEVMETHOD(device_attach, bti2c_attach), - - /* bus interface */ - DEVMETHOD(bus_print_child, bus_generic_print_child), - - /* iicbb interface */ - DEVMETHOD(iicbb_callback, bti2c_iic_callback), - DEVMETHOD(iicbb_setlines, bti2c_iic_setlines), - DEVMETHOD(iicbb_getdataline, bti2c_iic_getdataline), - DEVMETHOD(iicbb_reset, bti2c_iic_reset), - - /* smbus interface */ - DEVMETHOD(smbus_callback, bti2c_smb_callback), - DEVMETHOD(smbus_writeb, bti2c_smb_writeb), - DEVMETHOD(smbus_writew, bti2c_smb_writew), - DEVMETHOD(smbus_readb, bti2c_smb_readb), - - { 0, 0 } -}; - -#if (__FreeBSD_version < 400000) -/* FreeBSD 3.x needs DRIVER_TYPE_MISC */ -static driver_t bti2c_driver = { - "bti2c", - bti2c_methods, - DRIVER_TYPE_MISC, - sizeof(struct bti2c_softc), -}; -#endif - -#if (__FreeBSD_version >=400000) - static driver_t bti2c_driver = { - "bti2c", - bti2c_methods, - sizeof(struct bti2c_softc), -}; -#endif - /* * Call this to pass the address of the bktr device to the * bti2c_i2c layer and initialize all the I2C bus architecture */ -int -bt848_i2c_attach(int unit, struct bktr_softc * bktr, struct bktr_i2c_softc *i2c_sc) +int bt848_i2c_attach(device_t dev) { - device_t interface; - device_t bitbang; + struct bktr_softc *bktr_sc = (struct bktr_softc *)device_get_softc(dev); + struct bktr_i2c_softc *sc = &bktr_sc->i2c_sc; - btdata[unit].memh = bktr->memh; - btdata[unit].memt = bktr->memt; + device_t *list; + int count; - /* XXX add the I2C interface to the root_bus until pcibus is ready */ -#if (__FreeBSD_version < 400000) - interface = device_add_child(root_bus, "bti2c", unit, NULL); -#else - interface = device_add_child(root_bus, "bti2c", unit); -#endif + sc->smbus = device_add_child(dev, "smbus", -1); + sc->iicbb = device_add_child(dev, "iicbb", -1); - /* add bit-banging generic code onto bti2c interface */ -#if (__FreeBSD_version < 400000) - bitbang = device_add_child(interface, "iicbb", -1, NULL); -#else - bitbang = device_add_child(interface, "iicbb", -1); -#endif - - /* probe and attach the interface, we need it NOW - * bit-banging code is also probed and attached */ - device_probe_and_attach(interface); - device_probe_and_attach(bitbang); + if (!sc->iicbb || !sc->smbus) + return ENXIO; - /* smb and i2c interfaces are available for the bt848 chip - * connect bit-banging generic code to an iicbus */ - if ((i2c_sc->iicbus = iicbus_alloc_bus(bitbang))) - device_probe_and_attach(i2c_sc->iicbus); + bus_generic_attach(dev); - /* hardware i2c is actually smb over the bti2c interface */ - if ((i2c_sc->smbus = smbus_alloc_bus(interface))) - device_probe_and_attach(i2c_sc->smbus); + /* the iicbus is the first child of device iicbb */ + device_get_children(sc->iicbb, &list, &count); + if (count) { + sc->iicbus = list[0]; + free(list, M_TEMP); + } return (0); }; -/* - * Not a real probe, we know the device exists since the device has - * been added after the successfull pci probe. - */ -static int -bti2c_probe(device_t dev) +int bt848_i2c_detach(device_t dev) { - device_set_desc(dev, "bt848 Hard/Soft I2C controller"); + struct bktr_softc *bktr_sc = (struct bktr_softc *)device_get_softc(dev); + struct bktr_i2c_softc *sc = &bktr_sc->i2c_sc; + int error = 0; - return (0); -} + if ((error = bus_generic_detach(dev))) + goto error; -static int -bti2c_attach(device_t dev) -{ - struct bti2c_softc *sc = (struct bti2c_softc *)device_get_softc(dev); + if (sc->iicbb && (error = device_delete_child(dev, sc->iicbb))) + goto error; - /* XXX should use ivars with pcibus or pcibus methods to access - * onboard memory */ - sc->memh = btdata[device_get_unit(dev)].memh; - sc->memt = btdata[device_get_unit(dev)].memt; + if (sc->smbus && (error = device_delete_child(dev, sc->smbus))) + goto error; - return (0); +error: + return (error); } -static int -bti2c_smb_callback(device_t dev, int index, caddr_t *data) +int bti2c_smb_callback(device_t dev, int index, caddr_t *data) { - struct bti2c_softc *sc = (struct bti2c_softc *)device_get_softc(dev); + struct bktr_softc *bktr_sc = (struct bktr_softc *)device_get_softc(dev); + struct bktr_i2c_softc *sc = &bktr_sc->i2c_sc; int error = 0; - int how; /* test each time if we already have/haven't the iicbus * to avoid deadlocks */ switch (index) { case SMB_REQUEST_BUS: - if (!sc->iic_owned) { - /* request the iicbus */ - how = *(int *)data; - error = iicbus_request_bus(sc->iicbus, dev, how); - if (!error) - sc->iic_owned = 1; - } + /* XXX test & set */ + if (!sc->bus_owned) { + sc->bus_owned = 1; + } else + error = EWOULDBLOCK; break; case SMB_RELEASE_BUS: - if (sc->iic_owned) { - /* release the iicbus */ - error = iicbus_release_bus(sc->iicbus, dev); - if (!error) - sc->iic_owned = 0; - } + /* XXX test & set */ + if (sc->bus_owned) { + sc->bus_owned = 0; + } else + error = EINVAL; break; default: @@ -261,34 +159,30 @@ bti2c_smb_callback(device_t dev, int index, caddr_t *data) return (error); } -static int -bti2c_iic_callback(device_t dev, int index, caddr_t *data) +int bti2c_iic_callback(device_t dev, int index, caddr_t *data) { - struct bti2c_softc *sc = (struct bti2c_softc *)device_get_softc(dev); + struct bktr_softc *bktr_sc = (struct bktr_softc *)device_get_softc(dev); + struct bktr_i2c_softc *sc = &bktr_sc->i2c_sc; int error = 0; - int how; /* test each time if we already have/haven't the smbus * to avoid deadlocks */ switch (index) { case IIC_REQUEST_BUS: - if (!sc->smb_owned) { - /* request the smbus */ - how = *(int *)data; - error = smbus_request_bus(sc->smbus, dev, how); - if (!error) - sc->smb_owned = 1; - } + /* XXX test & set */ + if (!sc->bus_owned) { + sc->bus_owned = 1; + } else + error = EWOULDBLOCK; break; case IIC_RELEASE_BUS: - if (sc->smb_owned) { - /* release the smbus */ - error = smbus_release_bus(sc->smbus, dev); - if (!error) - sc->smb_owned = 0; - } + /* XXX test & set */ + if (sc->bus_owned) { + sc->bus_owned = 0; + } else + error = EINVAL; break; default: @@ -298,8 +192,7 @@ bti2c_iic_callback(device_t dev, int index, caddr_t *data) return (error); } -static int -bti2c_iic_reset(device_t dev, u_char speed, u_char addr, u_char * oldaddr) +int bti2c_iic_reset(device_t dev, u_char speed, u_char addr, u_char * oldaddr) { if (oldaddr) *oldaddr = 0; /* XXX */ @@ -307,48 +200,77 @@ bti2c_iic_reset(device_t dev, u_char speed, u_char addr, u_char * oldaddr) return (IIC_ENOADDR); } -static void -bti2c_iic_setlines(device_t dev, int ctrl, int data) +void bti2c_iic_setsda(device_t dev, int val) { - struct bti2c_softc *sc = (struct bti2c_softc *)device_get_softc(dev); + struct bktr_softc *sc = (struct bktr_softc *)device_get_softc(dev); + int clock; + + clock = INL(sc, BKTR_I2C_DATA_CTL) & 0x2; + + if (val) + OUTL(sc, BKTR_I2C_DATA_CTL, clock | 1); + else + OUTL(sc, BKTR_I2C_DATA_CTL, clock); - OUTL(sc, BKTR_I2C_DATA_CTL, (ctrl << 1) | data);; DELAY(I2C_DELAY); return; } -static int -bti2c_iic_getdataline(device_t dev) +void bti2c_iic_setscl(device_t dev, int val) { - struct bti2c_softc *sc = (struct bti2c_softc *)device_get_softc(dev); + struct bktr_softc *sc = (struct bktr_softc *)device_get_softc(dev); + int data; + + data = INL(sc, BKTR_I2C_DATA_CTL) & 0x1; + + if (val) + OUTL(sc, BKTR_I2C_DATA_CTL, 0x2 | data); + else + OUTL(sc, BKTR_I2C_DATA_CTL, data); - return ( INL(sc,BKTR_I2C_DATA_CTL) & 0x1); + DELAY(I2C_DELAY); + + return; +} + +int +bti2c_iic_getsda(device_t dev) +{ + struct bktr_softc *sc = (struct bktr_softc *)device_get_softc(dev); + + return (INL(sc,BKTR_I2C_DATA_CTL) & 0x1); +} + +int +bti2c_iic_getscl(device_t dev) +{ + return (0); } static int -bti2c_write(struct bti2c_softc* bti2c_sc, u_long data) +bti2c_write(struct bktr_softc *sc, u_long data) { u_long x; /* clear status bits */ - OUTL(bti2c_sc, BKTR_INT_STAT, (BT848_INT_RACK | BT848_INT_I2CDONE)); + OUTL(sc, BKTR_INT_STAT, (BT848_INT_RACK | BT848_INT_I2CDONE)); BTI2C_DEBUG(printf("w%lx", data)); /* write the address and data */ - OUTL(bti2c_sc, BKTR_I2C_DATA_CTL, data); + OUTL(sc, BKTR_I2C_DATA_CTL, data); /* wait for completion */ for ( x = 0x7fffffff; x; --x ) { /* safety valve */ - if ( INL(bti2c_sc, BKTR_INT_STAT) & BT848_INT_I2CDONE ) + if ( INL(sc, BKTR_INT_STAT) & BT848_INT_I2CDONE ) break; } /* check for ACK */ - if ( !x || !( INL(bti2c_sc, BKTR_INT_STAT) & BT848_INT_RACK) ) { + if ( !x || !( INL(sc, BKTR_INT_STAT) & BT848_INT_RACK) ) { BTI2C_DEBUG(printf("%c%c", (!x)?'+':'-', - (!( INL(bti2c_sc, BKTR_INT_STAT) & BT848_INT_RACK))?'+':'-')); + (!( INL(sc, BKTR_INT_STAT) & BT848_INT_RACK))?'+':'-')); return (SMB_ENOACK); } BTI2C_DEBUG(printf("+")); @@ -357,10 +279,10 @@ bti2c_write(struct bti2c_softc* bti2c_sc, u_long data) return( 0 ); } -static int +int bti2c_smb_writeb(device_t dev, u_char slave, char cmd, char byte) { - struct bti2c_softc *sc = (struct bti2c_softc *)device_get_softc(dev); + struct bktr_softc *sc = (struct bktr_softc *)device_get_softc(dev); u_long data; data = ((slave & 0xff) << 24) | ((byte & 0xff) << 16) | (u_char)cmd; @@ -372,10 +294,10 @@ bti2c_smb_writeb(device_t dev, u_char slave, char cmd, char byte) * byte1 becomes low byte of word * byte2 becomes high byte of word */ -static int +int bti2c_smb_writew(device_t dev, u_char slave, char cmd, short word) { - struct bti2c_softc *sc = (struct bti2c_softc *)device_get_softc(dev); + struct bktr_softc *sc = (struct bktr_softc *)device_get_softc(dev); u_long data; char low, high; @@ -391,10 +313,10 @@ bti2c_smb_writew(device_t dev, u_char slave, char cmd, short word) /* * The Bt878 and Bt879 differed on the treatment of i2c commands */ -static int +int bti2c_smb_readb(device_t dev, u_char slave, char cmd, char *byte) { - struct bti2c_softc *sc = (struct bti2c_softc *)device_get_softc(dev); + struct bktr_softc *sc = (struct bktr_softc *)device_get_softc(dev); u_long x; /* clear status bits */ @@ -422,5 +344,3 @@ bti2c_smb_readb(device_t dev, u_char slave, char cmd, char *byte) return (0); } - -DRIVER_MODULE(bti2c, root, bti2c_driver, bti2c_devclass, 0, 0); diff --git a/sys/dev/bktr/bktr_i2c.h b/sys/dev/bktr/bktr_i2c.h index f687e4c..a833351 100644 --- a/sys/dev/bktr/bktr_i2c.h +++ b/sys/dev/bktr/bktr_i2c.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 @@ -29,6 +29,19 @@ #ifndef _BT848_I2C_H #define _BT848_I2C_H -extern int bt848_i2c_attach(int, struct bktr_softc *bktr, struct bktr_i2c_softc *); +extern int bt848_i2c_attach(device_t); +extern int bt848_i2c_detach(device_t); + +extern int bti2c_iic_callback(device_t, int, caddr_t *); +extern void bti2c_iic_setsda(device_t, int); +extern void bti2c_iic_setscl(device_t, int); +extern int bti2c_iic_getsda(device_t); +extern int bti2c_iic_getscl(device_t); +extern int bti2c_iic_reset(device_t, u_char, u_char, u_char *); + +extern int bti2c_smb_callback(device_t, int, caddr_t *); +extern int bti2c_smb_writeb(device_t dev, u_char slave, char cmd, char byte); +extern int bti2c_smb_writew(device_t dev, u_char slave, char cmd, short word); +extern int bti2c_smb_readb(device_t dev, u_char slave, char cmd, char *byte); #endif diff --git a/sys/dev/bktr/bktr_os.c b/sys/dev/bktr/bktr_os.c index 0de052f..8cc1368 100644 --- a/sys/dev/bktr/bktr_os.c +++ b/sys/dev/bktr/bktr_os.c @@ -83,7 +83,7 @@ #include <vm/pmap.h> #include <vm/vm_extern.h> -#if (__FreeBSD_version >=400000) || (NSMBUS > 0) +#if (__FreeBSD_version >=400000) #include <sys/bus.h> /* used by smbus and newbus */ #endif @@ -190,13 +190,16 @@ int bktr_debug = 0; #include <dev/bktr/bktr_audio.h> #include <dev/bktr/bktr_core.h> #include <dev/bktr/bktr_os.h> + #if defined(BKTR_USE_FREEBSD_SMBUS) #include <dev/bktr/bktr_i2c.h> + +#include "iicbb_if.h" +#include "smbus_if.h" #endif #endif - /****************************/ /* *** FreeBSD 4.x code *** */ /****************************/ @@ -215,6 +218,22 @@ static device_method_t bktr_methods[] = { DEVMETHOD(device_detach, bktr_detach), DEVMETHOD(device_shutdown, bktr_shutdown), +#if defined(BKTR_USE_FREEBSD_SMBUS) + /* iicbb interface */ + DEVMETHOD(iicbb_callback, bti2c_iic_callback), + DEVMETHOD(iicbb_setsda, bti2c_iic_setsda), + DEVMETHOD(iicbb_setscl, bti2c_iic_setscl), + DEVMETHOD(iicbb_getsda, bti2c_iic_getsda), + DEVMETHOD(iicbb_getscl, bti2c_iic_getscl), + DEVMETHOD(iicbb_reset, bti2c_iic_reset), + + /* smbus interface */ + DEVMETHOD(smbus_callback, bti2c_smb_callback), + DEVMETHOD(smbus_writeb, bti2c_smb_writeb), + DEVMETHOD(smbus_writew, bti2c_smb_writew), + DEVMETHOD(smbus_readb, bti2c_smb_readb), +#endif + { 0, 0 } }; @@ -392,14 +411,11 @@ bktr_attach( device_t dev ) #endif pci_write_config(dev, 0x40, fun, 2); - - /* XXX call bt848_i2c dependent attach() routine */ #if defined(BKTR_USE_FREEBSD_SMBUS) - if (bt848_i2c_attach(unit, bktr, &bktr->i2c_sc)) + if (bt848_i2c_attach(dev)) printf("bktr%d: i2c_attach: can't attach\n", unit); #endif - /* * PCI latency timer. 32 is a good value for 4 bus mastering slots, if * you have more than four, then 16 would probably be a better value. @@ -477,6 +493,11 @@ bktr_detach( device_t dev ) OUTL(bktr, BKTR_INT_MASK, ALL_INTS_DISABLED); OUTW(bktr, BKTR_GPIO_DMA_CTL, FIFO_RISC_DISABLED); +#if defined(BKTR_USE_FREEBSD_SMBUS) + if (bt848_i2c_detach(dev)) + printf("bktr%d: i2c_attach: can't attach\n", unit); +#endif + /* Note: We do not free memory for RISC programs, grab buffer, vbi buffers */ /* The memory is retained by the bktr_mem module so we can unload and */ /* then reload the main bktr driver module */ @@ -965,14 +986,11 @@ bktr_attach( pcici_t tag, int unit ) #endif pci_conf_write(tag, 0x40, fun); - - /* XXX call bt848_i2c dependent attach() routine */ #if defined(BKTR_USE_FREEBSD_SMBUS) - if (bt848_i2c_attach(unit, bktr, &bktr->i2c_sc)) + if (bt848_i2c_attach(dev)) printf("bktr%d: i2c_attach: can't attach\n", unit); #endif - /* * PCI latency timer. 32 is a good value for 4 bus mastering slots, if * you have more than four, then 16 would probably be a better value. diff --git a/sys/dev/bktr/bktr_reg.h b/sys/dev/bktr/bktr_reg.h index ab9bd6e..874a367 100644 --- a/sys/dev/bktr/bktr_reg.h +++ b/sys/dev/bktr/bktr_reg.h @@ -34,17 +34,6 @@ * */ -#ifdef __FreeBSD__ -# if (__FreeBSD_version >= 310000) -# include "smbus.h" -# else -# define NSMBUS 0 /* FreeBSD before 3.1 does not have SMBUS */ -# endif -# if (NSMBUS > 0) -# define BKTR_USE_FREEBSD_SMBUS -# endif -#endif - #ifdef __NetBSD__ #include <machine/bus.h> /* struct device */ #include <sys/device.h> @@ -457,6 +446,9 @@ struct format_params { #if defined(BKTR_USE_FREEBSD_SMBUS) struct bktr_i2c_softc { + int bus_owned; + + device_t iicbb; device_t iicbus; device_t smbus; }; @@ -556,9 +548,9 @@ struct bktr_softc { bus_space_handle_t memh; /* Bus space register access functions */ bus_size_t obmemsz;/* Size of card (bytes) */ #endif - #if (NSMBUS > 0) +#if defined(BKTR_USE_FREEBSD_SMBUS) struct bktr_i2c_softc i2c_sc; /* bt848_i2c device */ - #endif +#endif char bktr_xname[7]; /* device name and unit number */ #endif 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); diff --git a/sys/dev/ppbus/lpbb.c b/sys/dev/ppbus/lpbb.c index 5fd99df..0284f07 100644 --- a/sys/dev/ppbus/lpbb.c +++ b/sys/dev/ppbus/lpbb.c @@ -1,5 +1,5 @@ /*- - * 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 @@ -75,19 +75,12 @@ 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); } @@ -124,24 +117,30 @@ lpbb_callback(device_t dev, int index, caddr_t *data) #define ALIM 0x20 #define I2CKEY 0x50 -static int getSDA(device_t ppbus) +static int lpbb_getscl(device_t dev) +{ + return ((ppb_rstr(device_get_parent(dev)) & SCL_in) == SCL_in); +} + +static int lpbb_getsda(device_t dev) { - if((ppb_rstr(ppbus)&SDA_in)==SDA_in) - return 1; - else - return 0; + return ((ppb_rstr(device_get_parent(dev)) & SDA_in) == SDA_in); } -static void setSDA(device_t ppbus, char val) +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 @@ -158,8 +157,8 @@ static int lpbb_detect(device_t dev) } /* 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)) { @@ -178,28 +177,18 @@ lpbb_reset(device_t dev, u_char speed, u_char addr, u_char * oldaddr) { 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); } static devclass_t lpbb_devclass; @@ -215,8 +204,10 @@ static device_method_t lpbb_methods[] = { /* 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 } @@ -229,3 +220,5 @@ static driver_t lpbb_driver = { }; DRIVER_MODULE(lpbb, ppbus, lpbb_driver, lpbb_devclass, 0, 0); +MODULE_DEPEND(lpbb, iicbb, IICBB_MINVER, IICBB_PREFVER, IICBB_MAXVER); +MODULE_VERSION(lpbb, 1); diff --git a/sys/dev/smbus/smb.c b/sys/dev/smbus/smb.c index beb3c4a..e07d4b4 100644 --- a/sys/dev/smbus/smb.c +++ b/sys/dev/smbus/smb.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 @@ -46,13 +46,8 @@ 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 */ + dev_t sc_devnode; }; #define IIC_SOFTC(unit) \ @@ -63,13 +58,17 @@ struct smb_softc { static int smb_probe(device_t); static int smb_attach(device_t); +static int smb_detach(device_t); +static void smb_identify(driver_t *driver, device_t parent); 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), @@ -106,30 +105,45 @@ static struct cdevsw smb_cdevsw = { /* flags */ 0, }; -/* - * smbprobe() - */ +static void +smb_identify(driver_t *driver, device_t parent) +{ + BUS_ADD_CHILD(parent, 0, "smb", 0); +} + static int smb_probe(device_t dev) { - struct smb_softc *sc = (struct smb_softc *)device_get_softc(dev); - - sc->sc_addr = smbus_get_addr(dev); - - /* XXX detect chip with start/stop conditions */ + device_set_desc(dev, "SMBus generic I/O"); return (0); } -/* - * smbattach() - */ static int smb_attach(device_t dev) { - make_dev(&smb_cdevsw, device_get_unit(dev), /* XXX cleanup */ + struct smb_softc *sc = (struct smb_softc *)device_get_softc(dev); + + if (!sc) + return (ENOMEM); + + bzero(sc, sizeof(struct smb_softc *)); + + sc->sc_devnode = make_dev(&smb_cdevsw, device_get_unit(dev), UID_ROOT, GID_WHEEL, 0600, "smb%d", device_get_unit(dev)); + + return (0); +} + +static int +smb_detach(device_t dev) +{ + struct smb_softc *sc = (struct smb_softc *)device_get_softc(dev); + + if (sc->sc_devnode) + destroy_dev(sc->sc_devnode); + return (0); } @@ -267,3 +281,5 @@ smbioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct thread *td) } DRIVER_MODULE(smb, smbus, smb_driver, smb_devclass, 0, 0); +MODULE_DEPEND(smb, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER); +MODULE_VERSION(smb, 1); diff --git a/sys/dev/smbus/smbconf.c b/sys/dev/smbus/smbconf.c index b91f3d3..9e9a2cb 100644 --- a/sys/dev/smbus/smbconf.c +++ b/sys/dev/smbus/smbconf.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 @@ -78,22 +78,6 @@ smbus_error(int smb_error) 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) { @@ -190,19 +174,3 @@ smbus_release_bus(device_t bus, device_t dev) 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); -} diff --git a/sys/dev/smbus/smbconf.h b/sys/dev/smbus/smbconf.h index 40289f7..64b0a33 100644 --- a/sys/dev/smbus/smbconf.h +++ b/sys/dev/smbus/smbconf.h @@ -101,4 +101,9 @@ extern u_char smbus_get_addr(device_t); #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 + #endif diff --git a/sys/dev/smbus/smbus.c b/sys/dev/smbus/smbus.c index 4650608..99b7ca3 100644 --- a/sys/dev/smbus/smbus.c +++ b/sys/dev/smbus/smbus.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,22 +41,6 @@ #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; /* @@ -64,22 +48,17 @@ static devclass_t smbus_devclass; */ 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_add_child(device_t dev, int order, const char *name, int unit); 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), /* bus interface */ + DEVMETHOD(bus_add_child, smbus_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 } }; @@ -106,48 +85,33 @@ smbus_probe(device_t dev) 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) - printf("smbus: %s devclass not found\n", - smbdev->smbd_name); - } + device_add_child(dev, NULL, -1); bus_generic_attach(dev); return (0); } -void -smbus_generic_intr(device_t dev, u_char devaddr, char low, char high) +static int +smbus_add_child(device_t dev, int order, const char *name, int unit) { - return; + device_add_child_ordered(dev, order, name, unit); + + bus_generic_attach(dev); + + return (0); } -#if 0 -static int -smbus_read_ivar(device_t bus, device_t dev, int index, u_long* result) +void +smbus_generic_intr(device_t dev, u_char devaddr, char low, char high) { - struct smbus_device* smbdev = DEVTOSMBUS(dev); - - switch (index) { - default: - break; - } - return (ENOENT); + return; } -#endif DRIVER_MODULE(smbus, iicsmb, smbus_driver, smbus_devclass, 0, 0); -DRIVER_MODULE(smbus, bti2c, smbus_driver, smbus_devclass, 0, 0); +DRIVER_MODULE(smbus, bktr, 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, alpm, 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, amdpm, smbus_driver, smbus_devclass, 0, 0); +DRIVER_MODULE(smbus, viapropm, smbus_driver, smbus_devclass, 0, 0); +MODULE_VERSION(smbus, SMBUS_MODVER); diff --git a/sys/i386/conf/NOTES b/sys/i386/conf/NOTES index b6c703f..7cec293 100644 --- a/sys/i386/conf/NOTES +++ b/sys/i386/conf/NOTES @@ -2378,11 +2378,16 @@ device nmdm device meteor 1 +# +# options BKTR_USE_FREEBSD_SMBUS +# Compile with FreeBSD SMBus implementation +# # Brooktree driver has been ported to the new I2C framework. Thus, # you'll need to have the following 3 lines in the kernel config. # device smbus # device iicbus # device iicbb +# device iicsmb # The iic and smb devices are only needed if you want to control other # I2C slaves connected to the external connector of some cards. # diff --git a/sys/i386/pci/pci_bus.c b/sys/i386/pci/pci_bus.c index 56f023b..91bee0c 100644 --- a/sys/i386/pci/pci_bus.c +++ b/sys/i386/pci/pci_bus.c @@ -493,6 +493,19 @@ DRIVER_MODULE(pcib, nexus, nexus_pcib_driver, pcib_devclass, 0, 0); static int pci_hostb_probe(device_t dev) { + u_int32_t id; + + id = pci_get_devid(dev); + + switch (id) { + + /* VIA VT82C596 Power Managment Function */ + case 0x30501106: + return ENXIO; + + default: + break; + } if (pci_get_class(dev) == PCIC_BRIDGE && pci_get_subclass(dev) == PCIS_BRIDGE_HOST) { diff --git a/sys/modules/bktr/bktr/Makefile b/sys/modules/bktr/bktr/Makefile index 8076f5a..f8574df 100644 --- a/sys/modules/bktr/bktr/Makefile +++ b/sys/modules/bktr/bktr/Makefile @@ -8,15 +8,10 @@ KMOD= bktr SRCS= bktr_core.c bktr_os.c bktr_audio.c bktr_tuner.c bktr_card.c \ bktr.h opt_devfs.h opt_bktr.h smbus.h bus_if.h device_if.h \ pci_if.h vnode_if.h -CLEANFILES= bktr.h smbus.h +CLEANFILES= bktr.h bktr.h: echo "#define NBKTR 1" > bktr.h echo "#define BKTR_FREEBSD_MODULE 1" >> bktr.h -# Does not use SMBUS/IICBUS. Uses the old i2c code self contained in -# the bt848 driver. -smbus.h: - echo "#define NSMBUS 0" > smbus.h - .include <bsd.kmod.mk> diff --git a/sys/modules/i2c/Makefile b/sys/modules/i2c/Makefile new file mode 100644 index 0000000..7ba1f43 --- /dev/null +++ b/sys/modules/i2c/Makefile @@ -0,0 +1,6 @@ +# $FreeBSD$ + +SUBDIR = +SUBDIR += controllers if_ic smbus iicbus iicbb iicsmb iic smb + +.include <bsd.subdir.mk> diff --git a/sys/modules/i2c/controllers/Makefile b/sys/modules/i2c/controllers/Makefile new file mode 100644 index 0000000..5fd2427 --- /dev/null +++ b/sys/modules/i2c/controllers/Makefile @@ -0,0 +1,5 @@ +# $FreeBSD$ + +SUBDIR = alpm intpm viapm lpbb pcf + +.include <bsd.subdir.mk> diff --git a/sys/modules/i2c/controllers/alpm/Makefile b/sys/modules/i2c/controllers/alpm/Makefile new file mode 100644 index 0000000..5429b9c --- /dev/null +++ b/sys/modules/i2c/controllers/alpm/Makefile @@ -0,0 +1,9 @@ +# $FreeBSD$ + +.PATH: ${.CURDIR}/../../../../pci +KMOD = alpm +CFLAGS += -DALPM_SMBIO_BASE_ADDR=0xbc00 +SRCS = device_if.h bus_if.h iicbus_if.h smbus_if.h pci_if.h \ + alpm.c + +.include <bsd.kmod.mk> diff --git a/sys/modules/i2c/controllers/amdpm/Makefile b/sys/modules/i2c/controllers/amdpm/Makefile new file mode 100644 index 0000000..5f6d7ed --- /dev/null +++ b/sys/modules/i2c/controllers/amdpm/Makefile @@ -0,0 +1,8 @@ +# $FreeBSD$ + +.PATH: ${.CURDIR}/../../../../pci +KMOD = amdpm +SRCS = device_if.h bus_if.h pci_if.h smbus_if.h \ + amdpm.c + +.include <bsd.kmod.mk> diff --git a/sys/modules/i2c/controllers/intpm/Makefile b/sys/modules/i2c/controllers/intpm/Makefile new file mode 100644 index 0000000..7cef578 --- /dev/null +++ b/sys/modules/i2c/controllers/intpm/Makefile @@ -0,0 +1,8 @@ +# $FreeBSD$ + +.PATH: ${.CURDIR}/../../../../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> diff --git a/sys/modules/i2c/controllers/lpbb/Makefile b/sys/modules/i2c/controllers/lpbb/Makefile new file mode 100644 index 0000000..c81ed26 --- /dev/null +++ b/sys/modules/i2c/controllers/lpbb/Makefile @@ -0,0 +1,8 @@ +# $FreeBSD$ + +.PATH: ${.CURDIR}/../../../../dev/ppbus +KMOD = pcf +SRCS = device_if.h bus_if.h iicbb_if.h ppbus_if.h \ + lpbb.c + +.include <bsd.kmod.mk> diff --git a/sys/modules/i2c/controllers/pcf/Makefile b/sys/modules/i2c/controllers/pcf/Makefile new file mode 100644 index 0000000..4fecd1f --- /dev/null +++ b/sys/modules/i2c/controllers/pcf/Makefile @@ -0,0 +1,8 @@ +# $FreeBSD$ + +.PATH: ${.CURDIR}/../../../../i386/isa +KMOD = pcf +SRCS = device_if.h bus_if.h iicbus_if.h isa_if.h \ + opt_compat_oldisa.h pcf.c + +.include <bsd.kmod.mk> diff --git a/sys/modules/i2c/controllers/viapm/Makefile b/sys/modules/i2c/controllers/viapm/Makefile new file mode 100644 index 0000000..4c3e3a6 --- /dev/null +++ b/sys/modules/i2c/controllers/viapm/Makefile @@ -0,0 +1,9 @@ +# $FreeBSD$ + +.PATH: ${.CURDIR}/../../../../pci +KMOD = viapm +SRCS = device_if.h bus_if.h iicbb_if.h pci_if.h smbus_if.h \ + viapm.c +CFLAGS += -DVIAPM_BASE_ADDR=0x6000 + +.include <bsd.kmod.mk> diff --git a/sys/modules/i2c/if_ic/Makefile b/sys/modules/i2c/if_ic/Makefile new file mode 100644 index 0000000..67dd734 --- /dev/null +++ b/sys/modules/i2c/if_ic/Makefile @@ -0,0 +1,8 @@ +# $FreeBSD$ + +.PATH: ${.CURDIR}/../../../dev/iicbus +KMOD = if_ic +SRCS = device_if.h bus_if.h iicbus_if.h \ + if_ic.c + +.include <bsd.kmod.mk> diff --git a/sys/modules/i2c/iic/Makefile b/sys/modules/i2c/iic/Makefile new file mode 100644 index 0000000..0ac8678 --- /dev/null +++ b/sys/modules/i2c/iic/Makefile @@ -0,0 +1,8 @@ +# $FreeBSD$ + +.PATH: ${.CURDIR}/../../../dev/iicbus +KMOD = iic +SRCS = device_if.h bus_if.h iicbus_if.h \ + iic.c + +.include <bsd.kmod.mk> diff --git a/sys/modules/i2c/iicbb/Makefile b/sys/modules/i2c/iicbb/Makefile new file mode 100644 index 0000000..ea991e0 --- /dev/null +++ b/sys/modules/i2c/iicbb/Makefile @@ -0,0 +1,8 @@ +# $FreeBSD$ + +.PATH: ${.CURDIR}/../../../dev/iicbus +KMOD = iicbb +SRCS = device_if.h bus_if.h iicbus_if.h \ + iicbb_if.h iicbb_if.c iicbb.c + +.include <bsd.kmod.mk> diff --git a/sys/modules/i2c/iicbus/Makefile b/sys/modules/i2c/iicbus/Makefile new file mode 100644 index 0000000..c3fc8e3 --- /dev/null +++ b/sys/modules/i2c/iicbus/Makefile @@ -0,0 +1,8 @@ +# $FreeBSD$ + +.PATH: ${.CURDIR}/../../../dev/iicbus +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> diff --git a/sys/modules/i2c/iicsmb/Makefile b/sys/modules/i2c/iicsmb/Makefile new file mode 100644 index 0000000..d0c6764 --- /dev/null +++ b/sys/modules/i2c/iicsmb/Makefile @@ -0,0 +1,8 @@ +# $FreeBSD$ + +.PATH: ${.CURDIR}/../../../dev/iicbus +KMOD = iicsmb +SRCS = device_if.h bus_if.h iicbus_if.h \ + smbus_if.h iicsmb.c + +.include <bsd.kmod.mk> diff --git a/sys/modules/i2c/smb/Makefile b/sys/modules/i2c/smb/Makefile new file mode 100644 index 0000000..f6f960c --- /dev/null +++ b/sys/modules/i2c/smb/Makefile @@ -0,0 +1,8 @@ +# $FreeBSD$ + +.PATH: ${.CURDIR}/../../../dev/smbus +KMOD = smb +SRCS = device_if.h bus_if.h smbus_if.h \ + smb.c + +.include <bsd.kmod.mk> diff --git a/sys/modules/i2c/smbus/Makefile b/sys/modules/i2c/smbus/Makefile new file mode 100644 index 0000000..24462d0 --- /dev/null +++ b/sys/modules/i2c/smbus/Makefile @@ -0,0 +1,8 @@ +# $FreeBSD$ + +.PATH: ${.CURDIR}/../../../dev/smbus +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> diff --git a/sys/pci/alpm.c b/sys/pci/alpm.c index a99f5f2..ae12197f 100644 --- a/sys/pci/alpm.c +++ b/sys/pci/alpm.c @@ -37,7 +37,6 @@ #include <sys/bus.h> #include <sys/uio.h> - #include <machine/bus_pio.h> #include <machine/bus_memio.h> #include <machine/bus.h> @@ -122,107 +121,62 @@ static int alpm_debug = 0; #define SMBCLOCK_111K 0xa0 #define SMBCLOCK_55K 0xc0 -struct alpm_data { +struct alpm_softc { int base; + struct resource *res; bus_space_tag_t smbst; bus_space_handle_t smbsh; -}; - -struct alsmb_softc { - int base; device_t smbus; - struct alpm_data *alpm; }; -#define ALPM_SMBINB(alsmb,register) \ - (bus_space_read_1(alsmb->alpm->smbst, alsmb->alpm->smbsh, register)) -#define ALPM_SMBOUTB(alsmb,register,value) \ - (bus_space_write_1(alsmb->alpm->smbst, alsmb->alpm->smbsh, register, value)) - -static int alsmb_probe(device_t); -static int alsmb_attach(device_t); -static int alsmb_smb_callback(device_t, int, caddr_t *); -static int alsmb_smb_quick(device_t dev, u_char slave, int how); -static int alsmb_smb_sendb(device_t dev, u_char slave, char byte); -static int alsmb_smb_recvb(device_t dev, u_char slave, char *byte); -static int alsmb_smb_writeb(device_t dev, u_char slave, char cmd, char byte); -static int alsmb_smb_readb(device_t dev, u_char slave, char cmd, char *byte); -static int alsmb_smb_writew(device_t dev, u_char slave, char cmd, short word); -static int alsmb_smb_readw(device_t dev, u_char slave, char cmd, short *word); -static int alsmb_smb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf); -static int alsmb_smb_bread(device_t dev, u_char slave, char cmd, u_char count, char *byte); - -static devclass_t alsmb_devclass; - -static device_method_t alsmb_methods[] = { - /* device interface */ - DEVMETHOD(device_probe, alsmb_probe), - DEVMETHOD(device_attach, alsmb_attach), - - /* bus interface */ - DEVMETHOD(bus_print_child, bus_generic_print_child), - - /* smbus interface */ - DEVMETHOD(smbus_callback, alsmb_smb_callback), - DEVMETHOD(smbus_quick, alsmb_smb_quick), - DEVMETHOD(smbus_sendb, alsmb_smb_sendb), - DEVMETHOD(smbus_recvb, alsmb_smb_recvb), - DEVMETHOD(smbus_writeb, alsmb_smb_writeb), - DEVMETHOD(smbus_readb, alsmb_smb_readb), - DEVMETHOD(smbus_writew, alsmb_smb_writew), - DEVMETHOD(smbus_readw, alsmb_smb_readw), - DEVMETHOD(smbus_bwrite, alsmb_smb_bwrite), - DEVMETHOD(smbus_bread, alsmb_smb_bread), - - { 0, 0 } -}; +#define ALPM_SMBINB(alpm,register) \ + (bus_space_read_1(alpm->smbst, alpm->smbsh, register)) +#define ALPM_SMBOUTB(alpm,register,value) \ + (bus_space_write_1(alpm->smbst, alpm->smbsh, register, value)) -static driver_t alsmb_driver = { - "alsmb", - alsmb_methods, - sizeof(struct alsmb_softc), -}; +static int +alpm_probe(device_t dev) +{ +#ifdef ALPM_SMBIO_BASE_ADDR + u_int32_t l; +#endif -static int alpm_pci_probe(device_t dev); -static int alpm_pci_attach(device_t dev); + if (pci_get_devid(dev) == ACER_M1543_PMU_ID) { + device_set_desc(dev, "AcerLabs M15x3 Power Management Unit"); -static devclass_t alpm_devclass; +#ifdef ALPM_SMBIO_BASE_ADDR + if (bootverbose || alpm_debug) + device_printf(dev, "forcing base I/O at 0x%x\n", + ALPM_SMBIO_BASE_ADDR); -static device_method_t alpm_pci_methods[] = { - /* device interface */ - DEVMETHOD(device_probe, alpm_pci_probe), - DEVMETHOD(device_attach, alpm_pci_attach), - - { 0, 0 } -}; + /* disable I/O */ + l = pci_read_config(dev, COM, 2); + pci_write_config(dev, COM, l & ~COM_ENABLE_IO, 2); -static driver_t alpm_pci_driver = { - "alpm", - alpm_pci_methods, - sizeof(struct alpm_data) -}; + /* set the I/O base address */ + pci_write_config(dev, SMBBA, ALPM_SMBIO_BASE_ADDR | 0x1, 4); + /* enable I/O */ + pci_write_config(dev, COM, l | COM_ENABLE_IO, 2); -static int -alpm_pci_probe(device_t dev) -{ - if (pci_get_devid(dev) == ACER_M1543_PMU_ID) { - device_set_desc(dev, - "AcerLabs M15x3 Power Management Unit"); - return 0; - } else { - return ENXIO; + if (bus_set_resource(dev, SYS_RES_IOPORT, SMBBA, + ALPM_SMBIO_BASE_ADDR, 256)) { + device_printf(dev, "could not set bus resource\n"); + return (ENXIO); + } +#endif + return (0); } + + return (ENXIO); } static int -alpm_pci_attach(device_t dev) +alpm_attach(device_t dev) { int rid, unit; u_int32_t l; - struct alpm_data *alpm; - struct resource *res; - device_t smbinterface; + struct alpm_softc *alpm; alpm = device_get_softc(dev); unit = device_get_unit(dev); @@ -239,9 +193,9 @@ alpm_pci_attach(device_t dev) pci_write_config(dev, SMBHCBC, l, 1); */ - if (bootverbose) { + if (bootverbose || alpm_debug) { l = pci_read_config(dev, SMBHSI, 1); - printf("alsmb%d: %s/%s", unit, + device_printf(dev, "%s/%s", (l & SMBHSI_HOST) ? "host":"nohost", (l & SMBHSI_SLAVE) ? "slave":"noslave"); @@ -265,76 +219,49 @@ alpm_pci_attach(device_t dev) case SMBCLOCK_55K: printf(" 55K"); break; + default: + printf("unkown"); + break; } + printf("\n"); } -#ifdef ALPM_SMBIO_BASE_ADDR - /* XX will this even work anymore? */ - /* disable I/O */ - l = pci_read_config(dev, COM, 2); - pci_write_config(dev, COM, l & ~COM_ENABLE_IO, 2); - - /* set the I/O base address */ - pci_write_config(dev, SMBBA, ALPM_SMBIO_BASE_ADDR | 0x1, 4); - - /* enable I/O */ - pci_write_config(dev, COM, l | COM_ENABLE_IO, 2); - -#endif rid = SMBBA; - res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, - 0,~0,1,RF_ACTIVE); - if (res == NULL) { + alpm->res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, + 0, ~0, 1, RF_ACTIVE); + + if (alpm->res == NULL) { device_printf(dev,"Could not allocate Bus space\n"); - return ENXIO; + return (ENXIO); } - alpm->smbst = rman_get_bustag(res); - alpm->smbsh = rman_get_bushandle(res); + alpm->smbst = rman_get_bustag(alpm->res); + alpm->smbsh = rman_get_bushandle(alpm->res); - if (bootverbose) - printf(" at 0x%x\n", alpm->smbsh); - - smbinterface = device_add_child(dev, "alsmb", unit); - if (!smbinterface) - device_printf(dev, "could not add SMBus device\n"); - else - device_probe_and_attach(smbinterface); - return 0; -} - -/* - * Not a real probe, we know the device exists since the device has - * been added after the successfull pci probe. - */ -static int -alsmb_probe(device_t dev) -{ - struct alsmb_softc *sc = (struct alsmb_softc *)device_get_softc(dev); - - /* allocate a new smbus device */ - sc->smbus = smbus_alloc_bus(dev); - if (!sc->smbus) - return (EINVAL); - device_set_desc(dev, "Aladdin IV/V/Pro2 SMBus controller"); + /* attach the smbus */ + alpm->smbus = device_add_child(dev, "smbus", -1); + bus_generic_attach(dev); return (0); } static int -alsmb_attach(device_t dev) +alpm_detach(device_t dev) { - struct alsmb_softc *sc = (struct alsmb_softc *)device_get_softc(dev); + struct alpm_softc *alpm = device_get_softc(dev); - sc->alpm = device_get_softc(device_get_parent(dev)); + if (alpm->smbus) { + device_delete_child(dev, alpm->smbus); + alpm->smbus = NULL; + } - /* probe and attach the smbus */ - device_probe_and_attach(sc->smbus); + if (alpm->res) + bus_release_resource(dev, SYS_RES_IOPORT, SMBBA, alpm->res); return (0); } static int -alsmb_smb_callback(device_t dev, int index, caddr_t *data) +alpm_callback(device_t dev, int index, caddr_t *data) { int error = 0; @@ -351,7 +278,7 @@ alsmb_smb_callback(device_t dev, int index, caddr_t *data) } static int -alsmb_clear(struct alsmb_softc *sc) +alpm_clear(struct alpm_softc *sc) { ALPM_SMBOUTB(sc, SMBSTS, 0xff); DELAY(10); @@ -361,7 +288,7 @@ alsmb_clear(struct alsmb_softc *sc) #if 0 static int -alsmb_abort(struct alsmb_softc *sc) +alpm_abort(struct alpm_softc *sc) { ALPM_SMBOUTB(sc, SMBCMD, T_OUT_CMD | ABORT_HOST); @@ -370,7 +297,7 @@ alsmb_abort(struct alsmb_softc *sc) #endif static int -alsmb_idle(struct alsmb_softc *sc) +alpm_idle(struct alpm_softc *sc) { u_char sts; @@ -385,7 +312,7 @@ alsmb_idle(struct alsmb_softc *sc) * Poll the SMBus controller */ static int -alsmb_wait(struct alsmb_softc *sc) +alpm_wait(struct alpm_softc *sc) { int count = 10000; u_char sts = 0; @@ -416,19 +343,19 @@ alsmb_wait(struct alsmb_softc *sc) error |= SMB_EBUSERR; if (error != SMB_ENOERR) - alsmb_clear(sc); + alpm_clear(sc); return (error); } static int -alsmb_smb_quick(device_t dev, u_char slave, int how) +alpm_quick(device_t dev, u_char slave, int how) { - struct alsmb_softc *sc = (struct alsmb_softc *)device_get_softc(dev); + struct alpm_softc *sc = (struct alpm_softc *)device_get_softc(dev); int error; - alsmb_clear(sc); - if (!alsmb_idle(sc)) + alpm_clear(sc); + if (!alpm_idle(sc)) return (EBUSY); switch (how) { @@ -447,7 +374,7 @@ alsmb_smb_quick(device_t dev, u_char slave, int how) ALPM_SMBOUTB(sc, SMBCMD, SMBQUICK); ALPM_SMBOUTB(sc, SMBSTART, 0xff); - error = alsmb_wait(sc); + error = alpm_wait(sc); ALPM_DEBUG(printf(", error=0x%x\n", error)); @@ -455,13 +382,13 @@ alsmb_smb_quick(device_t dev, u_char slave, int how) } static int -alsmb_smb_sendb(device_t dev, u_char slave, char byte) +alpm_sendb(device_t dev, u_char slave, char byte) { - struct alsmb_softc *sc = (struct alsmb_softc *)device_get_softc(dev); + struct alpm_softc *sc = (struct alpm_softc *)device_get_softc(dev); int error; - alsmb_clear(sc); - if (!alsmb_idle(sc)) + alpm_clear(sc); + if (!alpm_idle(sc)) return (SMB_EBUSY); ALPM_SMBOUTB(sc, SMBHADDR, slave & ~LSB); @@ -469,7 +396,7 @@ alsmb_smb_sendb(device_t dev, u_char slave, char byte) ALPM_SMBOUTB(sc, SMBHDATA, byte); ALPM_SMBOUTB(sc, SMBSTART, 0xff); - error = alsmb_wait(sc); + error = alpm_wait(sc); ALPM_DEBUG(printf("alpm: SENDB to 0x%x, byte=0x%x, error=0x%x\n", slave, byte, error)); @@ -477,20 +404,20 @@ alsmb_smb_sendb(device_t dev, u_char slave, char byte) } static int -alsmb_smb_recvb(device_t dev, u_char slave, char *byte) +alpm_recvb(device_t dev, u_char slave, char *byte) { - struct alsmb_softc *sc = (struct alsmb_softc *)device_get_softc(dev); + struct alpm_softc *sc = (struct alpm_softc *)device_get_softc(dev); int error; - alsmb_clear(sc); - if (!alsmb_idle(sc)) + alpm_clear(sc); + if (!alpm_idle(sc)) return (SMB_EBUSY); ALPM_SMBOUTB(sc, SMBHADDR, slave | LSB); ALPM_SMBOUTB(sc, SMBCMD, SMBSRBYTE); ALPM_SMBOUTB(sc, SMBSTART, 0xff); - if ((error = alsmb_wait(sc)) == SMB_ENOERR) + if ((error = alpm_wait(sc)) == SMB_ENOERR) *byte = ALPM_SMBINB(sc, SMBHDATA); ALPM_DEBUG(printf("alpm: RECVB from 0x%x, byte=0x%x, error=0x%x\n", slave, *byte, error)); @@ -499,13 +426,13 @@ alsmb_smb_recvb(device_t dev, u_char slave, char *byte) } static int -alsmb_smb_writeb(device_t dev, u_char slave, char cmd, char byte) +alpm_writeb(device_t dev, u_char slave, char cmd, char byte) { - struct alsmb_softc *sc = (struct alsmb_softc *)device_get_softc(dev); + struct alpm_softc *sc = (struct alpm_softc *)device_get_softc(dev); int error; - alsmb_clear(sc); - if (!alsmb_idle(sc)) + alpm_clear(sc); + if (!alpm_idle(sc)) return (SMB_EBUSY); ALPM_SMBOUTB(sc, SMBHADDR, slave & ~LSB); @@ -514,7 +441,7 @@ alsmb_smb_writeb(device_t dev, u_char slave, char cmd, char byte) ALPM_SMBOUTB(sc, SMBHCMD, cmd); ALPM_SMBOUTB(sc, SMBSTART, 0xff); - error = alsmb_wait(sc); + error = alpm_wait(sc); ALPM_DEBUG(printf("alpm: WRITEB to 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, byte, error)); @@ -522,13 +449,13 @@ alsmb_smb_writeb(device_t dev, u_char slave, char cmd, char byte) } static int -alsmb_smb_readb(device_t dev, u_char slave, char cmd, char *byte) +alpm_readb(device_t dev, u_char slave, char cmd, char *byte) { - struct alsmb_softc *sc = (struct alsmb_softc *)device_get_softc(dev); + struct alpm_softc *sc = (struct alpm_softc *)device_get_softc(dev); int error; - alsmb_clear(sc); - if (!alsmb_idle(sc)) + alpm_clear(sc); + if (!alpm_idle(sc)) return (SMB_EBUSY); ALPM_SMBOUTB(sc, SMBHADDR, slave | LSB); @@ -536,7 +463,7 @@ alsmb_smb_readb(device_t dev, u_char slave, char cmd, char *byte) ALPM_SMBOUTB(sc, SMBHCMD, cmd); ALPM_SMBOUTB(sc, SMBSTART, 0xff); - if ((error = alsmb_wait(sc)) == SMB_ENOERR) + if ((error = alpm_wait(sc)) == SMB_ENOERR) *byte = ALPM_SMBINB(sc, SMBHDATA); ALPM_DEBUG(printf("alpm: READB from 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, *byte, error)); @@ -545,13 +472,13 @@ alsmb_smb_readb(device_t dev, u_char slave, char cmd, char *byte) } static int -alsmb_smb_writew(device_t dev, u_char slave, char cmd, short word) +alpm_writew(device_t dev, u_char slave, char cmd, short word) { - struct alsmb_softc *sc = (struct alsmb_softc *)device_get_softc(dev); + struct alpm_softc *sc = (struct alpm_softc *)device_get_softc(dev); int error; - alsmb_clear(sc); - if (!alsmb_idle(sc)) + alpm_clear(sc); + if (!alpm_idle(sc)) return (SMB_EBUSY); ALPM_SMBOUTB(sc, SMBHADDR, slave & ~LSB); @@ -561,7 +488,7 @@ alsmb_smb_writew(device_t dev, u_char slave, char cmd, short word) ALPM_SMBOUTB(sc, SMBHCMD, cmd); ALPM_SMBOUTB(sc, SMBSTART, 0xff); - error = alsmb_wait(sc); + error = alpm_wait(sc); ALPM_DEBUG(printf("alpm: WRITEW to 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, word, error)); @@ -569,14 +496,14 @@ alsmb_smb_writew(device_t dev, u_char slave, char cmd, short word) } static int -alsmb_smb_readw(device_t dev, u_char slave, char cmd, short *word) +alpm_readw(device_t dev, u_char slave, char cmd, short *word) { - struct alsmb_softc *sc = (struct alsmb_softc *)device_get_softc(dev); + struct alpm_softc *sc = (struct alpm_softc *)device_get_softc(dev); int error; u_char high, low; - alsmb_clear(sc); - if (!alsmb_idle(sc)) + alpm_clear(sc); + if (!alpm_idle(sc)) return (SMB_EBUSY); ALPM_SMBOUTB(sc, SMBHADDR, slave | LSB); @@ -584,7 +511,7 @@ alsmb_smb_readw(device_t dev, u_char slave, char cmd, short *word) ALPM_SMBOUTB(sc, SMBHCMD, cmd); ALPM_SMBOUTB(sc, SMBSTART, 0xff); - if ((error = alsmb_wait(sc)) == SMB_ENOERR) { + if ((error = alpm_wait(sc)) == SMB_ENOERR) { low = ALPM_SMBINB(sc, SMBHDATA); high = ALPM_SMBINB(sc, SMBHDATB); @@ -597,14 +524,14 @@ alsmb_smb_readw(device_t dev, u_char slave, char cmd, short *word) } static int -alsmb_smb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf) +alpm_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf) { - struct alsmb_softc *sc = (struct alsmb_softc *)device_get_softc(dev); + struct alpm_softc *sc = (struct alpm_softc *)device_get_softc(dev); u_char remain, len, i; int error = SMB_ENOERR; - alsmb_clear(sc); - if(!alsmb_idle(sc)) + alpm_clear(sc); + if(!alpm_idle(sc)) return (SMB_EBUSY); remain = count; @@ -627,7 +554,7 @@ alsmb_smb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf) ALPM_SMBOUTB(sc, SMBHCMD, cmd); ALPM_SMBOUTB(sc, SMBSTART, 0xff); - if ((error = alsmb_wait(sc)) != SMB_ENOERR) + if ((error = alpm_wait(sc)) != SMB_ENOERR) goto error; remain -= len; @@ -640,14 +567,14 @@ error: } static int -alsmb_smb_bread(device_t dev, u_char slave, char cmd, u_char count, char *buf) +alpm_bread(device_t dev, u_char slave, char cmd, u_char count, char *buf) { - struct alsmb_softc *sc = (struct alsmb_softc *)device_get_softc(dev); + struct alpm_softc *sc = (struct alpm_softc *)device_get_softc(dev); u_char remain, len, i; int error = SMB_ENOERR; - alsmb_clear(sc); - if (!alsmb_idle(sc)) + alpm_clear(sc); + if (!alpm_idle(sc)) return (SMB_EBUSY); remain = count; @@ -661,7 +588,7 @@ alsmb_smb_bread(device_t dev, u_char slave, char cmd, u_char count, char *buf) ALPM_SMBOUTB(sc, SMBHCMD, cmd); ALPM_SMBOUTB(sc, SMBSTART, 0xff); - if ((error = alsmb_wait(sc)) != SMB_ENOERR) + if ((error = alpm_wait(sc)) != SMB_ENOERR) goto error; len = ALPM_SMBINB(sc, SMBHDATA); @@ -680,5 +607,35 @@ error: return (error); } -DRIVER_MODULE(alpm, pci, alpm_pci_driver, alpm_devclass, 0, 0); -DRIVER_MODULE(alsmb, alpm, alsmb_driver, alsmb_devclass, 0, 0); +static devclass_t alpm_devclass; + +static device_method_t alpm_methods[] = { + /* device interface */ + DEVMETHOD(device_probe, alpm_probe), + DEVMETHOD(device_attach, alpm_attach), + DEVMETHOD(device_detach, alpm_detach), + + /* smbus interface */ + DEVMETHOD(smbus_callback, alpm_callback), + DEVMETHOD(smbus_quick, alpm_quick), + DEVMETHOD(smbus_sendb, alpm_sendb), + DEVMETHOD(smbus_recvb, alpm_recvb), + DEVMETHOD(smbus_writeb, alpm_writeb), + DEVMETHOD(smbus_readb, alpm_readb), + DEVMETHOD(smbus_writew, alpm_writew), + DEVMETHOD(smbus_readw, alpm_readw), + DEVMETHOD(smbus_bwrite, alpm_bwrite), + DEVMETHOD(smbus_bread, alpm_bread), + + { 0, 0 } +}; + +static driver_t alpm_driver = { + "alpm", + alpm_methods, + sizeof(struct alpm_softc) +}; + +DRIVER_MODULE(alpm, pci, alpm_driver, alpm_devclass, 0, 0); +MODULE_DEPEND(alpm, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER); +MODULE_VERSION(alpm, 1); diff --git a/sys/pci/intpm.c b/sys/pci/intpm.c index a3c780f..747f192 100644 --- a/sys/pci/intpm.c +++ b/sys/pci/intpm.c @@ -150,7 +150,7 @@ static int intsmb_probe(device_t dev) { struct intsmb_softc *sc =(struct intsmb_softc *) device_get_softc(dev); - sc->smbus=smbus_alloc_bus(dev); + sc->smbus=device_add_child(dev, "smbus", -1); if (!sc->smbus) return (EINVAL); /* XXX don't know what to return else */ device_set_desc(dev,"Intel PIIX4 SMBUS Interface"); @@ -739,6 +739,8 @@ intpm_probe(device_t dev) } } DRIVER_MODULE(intpm, pci , intpm_pci_driver, intpm_devclass, 0, 0); +MODULE_DEPEND(intpm, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER); +MODULE_VERSION(intpm, 1); static void intpm_intr(void *arg) { diff --git a/sys/pci/viapm.c b/sys/pci/viapm.c new file mode 100644 index 0000000..d18f64d --- /dev/null +++ b/sys/pci/viapm.c @@ -0,0 +1,924 @@ +/*- + * Copyright (c) 2001 Alcove - Nicolas Souchu + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + * + */ +#include <sys/param.h> +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/module.h> +#include <sys/bus.h> +#include <sys/uio.h> + +#include <machine/bus_pio.h> +#include <machine/bus_memio.h> +#include <machine/bus.h> +#include <machine/clock.h> /* for DELAY */ +#include <machine/resource.h> +#include <sys/rman.h> + +#include <pci/pcivar.h> +#include <pci/pcireg.h> + +#include <dev/iicbus/iiconf.h> +#include <dev/iicbus/iicbus.h> + +#include <dev/smbus/smbconf.h> +#include <dev/smbus/smbus.h> + +#include "iicbb_if.h" +#include "smbus_if.h" + +#define VIAPM_DEBUG(x) if (viapm_debug) (x) + +#ifdef DEBUG +static int viapm_debug = 1; +#else +static int viapm_debug = 0; +#endif + +#define VIA_586B_PMU_ID 0x30401106 +#define VIA_596A_PMU_ID 0x30501106 +#define VIA_596B_PMU_ID 0x30511106 +#define VIA_686A_PMU_ID 0x30571106 +#define VIA_8233_PMU_ID 0x30741106 + +#define VIAPM_INB(port) \ + ((u_char)bus_space_read_1(viapm->st, viapm->sh, port)) +#define VIAPM_OUTB(port,val) \ + (bus_space_write_1(viapm->st, viapm->sh, port, (u_char)val)) + +#define VIAPM_TYP_UNKNOWN 0 +#define VIAPM_TYP_586B_3040E 1 +#define VIAPM_TYP_586B_3040F 2 +#define VIAPM_TYP_596B 3 +#define VIAPM_TYP_686A 4 +#define VIAPM_TYP_8233 5 + +struct viapm_softc { + int type; + u_int32_t base; + bus_space_tag_t st; + bus_space_handle_t sh; + int iorid; + int irqrid; + struct resource *iores; + struct resource *irqres; + void *irqih; + + device_t iicbb; + device_t smbus; +}; + +static devclass_t viapm_devclass; +static devclass_t viapropm_devclass; + +/* + * VT82C586B definitions + */ + +#define VIAPM_586B_REVID 0x08 + +#define VIAPM_586B_3040E_BASE 0x20 +#define VIAPM_586B_3040E_ACTIV 0x4 /* 16 bits */ + +#define VIAPM_586B_3040F_BASE 0x48 +#define VIAPM_586B_3040F_ACTIV 0x41 /* 8 bits */ + +#define VIAPM_586B_OEM_REV_E 0x00 +#define VIAPM_586B_OEM_REV_F 0x01 +#define VIAPM_586B_PROD_REV_A 0x10 + +#define VIAPM_586B_BA_MASK 0x0000ff00 + +#define GPIO_DIR 0x40 +#define GPIO_VAL 0x42 +#define EXTSMI_VAL 0x44 + +#define VIAPM_SCL 0x02 /* GPIO1_VAL */ +#define VIAPM_SDA 0x04 /* GPIO2_VAL */ + +/* + * VIAPRO common definitions + */ + +#define VIAPM_PRO_BA_MASK 0x0000fff0 +#define VIAPM_PRO_SMBCTRL 0xd2 +#define VIAPM_PRO_REVID 0xd6 + +/* + * VT82C686A definitions + */ + +#define VIAPM_PRO_BASE 0x90 + +#define SMBHST 0x0 +#define SMBHSL 0x1 +#define SMBHCTRL 0x2 +#define SMBHCMD 0x3 +#define SMBHADDR 0x4 +#define SMBHDATA0 0x5 +#define SMBHDATA1 0x6 +#define SMBHBLOCK 0x7 + +#define SMBSST 0x1 +#define SMBSCTRL 0x8 +#define SMBSSDWCMD 0x9 +#define SMBSEVENT 0xa +#define SMBSDATA 0xc + +#define SMBHST_RESERVED 0xef /* reserved bits */ +#define SMBHST_FAILED 0x10 /* failed bus transaction */ +#define SMBHST_COLLID 0x08 /* bus collision */ +#define SMBHST_ERROR 0x04 /* device error */ +#define SMBHST_INTR 0x02 /* command completed */ +#define SMBHST_BUSY 0x01 /* host busy */ + +#define SMBHCTRL_START 0x40 /* start command */ +#define SMBHCTRL_PROTO 0x1c /* command protocol mask */ +#define SMBHCTRL_QUICK 0x00 +#define SMBHCTRL_SENDRECV 0x04 +#define SMBHCTRL_BYTE 0x08 +#define SMBHCTRL_WORD 0x0c +#define SMBHCTRL_BLOCK 0x14 +#define SMBHCTRL_KILL 0x02 /* stop the current transaction */ +#define SMBHCTRL_ENABLE 0x01 /* enable interrupts */ + +#define SMBSCTRL_ENABLE 0x01 /* enable slave */ + + +/* + * VIA8233 definitions + */ + +#define VIAPM_8233_BASE 0xD0 + +static int +viapm_586b_probe(device_t dev) +{ + struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev); + u_int32_t l; + u_int16_t s; + u_int8_t c; + + switch (pci_get_devid(dev)) { + case VIA_586B_PMU_ID: + + bzero(viapm, sizeof(struct viapm_softc)); + + l = pci_read_config(dev, VIAPM_586B_REVID, 1); + switch (l) { + case VIAPM_586B_OEM_REV_E: + viapm->type = VIAPM_TYP_586B_3040E; + viapm->iorid = VIAPM_586B_3040E_BASE; + + /* Activate IO block access */ + s = pci_read_config(dev, VIAPM_586B_3040E_ACTIV, 2); + pci_write_config(dev, VIAPM_586B_3040E_ACTIV, s | 0x1, 2); + break; + + case VIAPM_586B_OEM_REV_F: + case VIAPM_586B_PROD_REV_A: + default: + viapm->type = VIAPM_TYP_586B_3040F; + viapm->iorid = VIAPM_586B_3040F_BASE; + + /* Activate IO block access */ + c = pci_read_config(dev, VIAPM_586B_3040F_ACTIV, 1); + pci_write_config(dev, VIAPM_586B_3040F_ACTIV, c | 0x80, 1); + break; + } + + viapm->base = pci_read_config(dev, viapm->iorid, 4) & + VIAPM_586B_BA_MASK; + + /* + * We have to set the I/O resources by hand because it is + * described outside the viapmope of the traditional maps + */ + if (bus_set_resource(dev, SYS_RES_IOPORT, viapm->iorid, + viapm->base, 256)) { + device_printf(dev, "could not set bus resource\n"); + return ENXIO; + } + device_set_desc(dev, "VIA VT82C586B Power Management Unit"); + return 0; + + default: + break; + } + + return ENXIO; +} + + +static int +viapm_pro_probe(device_t dev) +{ + struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev); +#ifdef VIAPM_BASE_ADDR + u_int32_t l; +#endif + u_int32_t base_cfgreg; + char *desc; + + switch (pci_get_devid(dev)) { + case VIA_596A_PMU_ID: + desc = "VIA VT82C596A Power Management Unit"; + viapm->type = VIAPM_TYP_596B; + base_cfgreg = VIAPM_PRO_BASE; + goto viapro; + + case VIA_596B_PMU_ID: + desc = "VIA VT82C596B Power Management Unit"; + viapm->type = VIAPM_TYP_596B; + base_cfgreg = VIAPM_PRO_BASE; + goto viapro; + + case VIA_686A_PMU_ID: + desc = "VIA VT82C686A Power Management Unit"; + viapm->type = VIAPM_TYP_686A; + base_cfgreg = VIAPM_PRO_BASE; + goto viapro; + + case VIA_8233_PMU_ID: + desc = "VIA VT8233 Power Management Unit"; + viapm->type = VIAPM_TYP_UNKNOWN; + base_cfgreg = VIAPM_8233_BASE; + goto viapro; + + viapro: + +#ifdef VIAPM_BASE_ADDR + /* force VIAPM I/O base address */ + + /* enable the SMBus controller function */ + l = pci_read_config(dev, VIAPM_PRO_SMBCTRL, 1); + pci_write_config(dev, VIAPM_PRO_SMBCTRL, l | 1, 1); + + /* write the base address */ + pci_write_config(dev, base_cfgreg, + VIAPM_BASE_ADDR & VIAPM_PRO_BA_MASK, 4); +#endif + + viapm->base = pci_read_config(dev, base_cfgreg, 4) & VIAPM_PRO_BA_MASK; + + /* + * We have to set the I/O resources by hand because it is + * described outside the viapmope of the traditional maps + */ + viapm->iorid = base_cfgreg; + if (bus_set_resource(dev, SYS_RES_IOPORT, viapm->iorid, + viapm->base, 16)) { + device_printf(dev, "could not set bus resource 0x%x\n", + viapm->base); + return ENXIO; + } + + if (1 || bootverbose) { + device_printf(dev, "SMBus I/O base at 0x%x\n", viapm->base); + } + + device_set_desc(dev, desc); + return 0; + + default: + break; + } + + return ENXIO; +} + +static int +viapm_pro_attach(device_t dev) +{ + struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev); + u_int32_t l; + + if (!(viapm->iores = bus_alloc_resource(dev, SYS_RES_IOPORT, + &viapm->iorid, 0l, ~0l, 1, RF_ACTIVE))) { + device_printf(dev, "could not allocate bus space\n"); + goto error; + } + viapm->st = rman_get_bustag(viapm->iores); + viapm->sh = rman_get_bushandle(viapm->iores); + +#if notyet + /* force irq 9 */ + l = pci_read_config(dev, VIAPM_PRO_SMBCTRL, 1); + pci_write_config(dev, VIAPM_PRO_SMBCTRL, l | 0x80, 1); + + viapm->irqrid = 0; + if (!(viapm->irqres = bus_alloc_resource(dev, SYS_RES_IRQ, + &viapm->irqrid, 9, 9, 1, + RF_SHAREABLE | RF_ACTIVE))) { + device_printf(dev, "could not allocate irq\n"); + goto error; + } + + if (bus_setup_intr(dev, viapm->irqres, INTR_TYPE_MISC, + (driver_intr_t *) viasmb_intr, viapm, &viapm->irqih)) { + device_printf(dev, "could not setup irq\n"); + goto error; + } +#endif + + if (1 | bootverbose) { + l = pci_read_config(dev, VIAPM_PRO_REVID, 1); + device_printf(dev, "SMBus revision code 0x%x\n", l); + } + + viapm->smbus = device_add_child(dev, "smbus", -1); + + /* probe and attach the smbus */ + bus_generic_attach(dev); + + /* disable slave function */ + VIAPM_OUTB(SMBSCTRL, VIAPM_INB(SMBSCTRL) & ~SMBSCTRL_ENABLE); + + /* enable the SMBus controller function */ + l = pci_read_config(dev, VIAPM_PRO_SMBCTRL, 1); + pci_write_config(dev, VIAPM_PRO_SMBCTRL, l | 1, 1); + +#if notyet + /* enable interrupts */ + VIAPM_OUTB(SMBHCTRL, VIAPM_INB(SMBHCTRL) | SMBHCTRL_ENABLE); +#endif + + return 0; + +error: + if (viapm->iores) + bus_release_resource(dev, SYS_RES_IOPORT, viapm->iorid, viapm->iores); +#if notyet + if (viapm->irqres) + bus_release_resource(dev, SYS_RES_IRQ, viapm->irqrid, viapm->irqres); +#endif + + return ENXIO; +} + +static int +viapm_586b_attach(device_t dev) +{ + struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev); + + if (!(viapm->iores = bus_alloc_resource(dev, SYS_RES_IOPORT, + &viapm->iorid, 0ul, ~0ul, 1, RF_ACTIVE | RF_SHAREABLE))) { + device_printf(dev, "could not allocate bus resource\n"); + return ENXIO; + } + viapm->st = rman_get_bustag(viapm->iores); + viapm->sh = rman_get_bushandle(viapm->iores); + + VIAPM_OUTB(GPIO_DIR, VIAPM_INB(GPIO_DIR) | VIAPM_SCL | VIAPM_SDA); + + /* add generic bit-banging code */ + if (!(viapm->iicbb = device_add_child(dev, "iicbb", -1))) + goto error; + + bus_generic_attach(dev); + + return 0; + +error: + if (viapm->iores) + bus_release_resource(dev, SYS_RES_IOPORT, + viapm->iorid, viapm->iores); + return ENXIO; +} + +static int +viapm_586b_detach(device_t dev) +{ + struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev); + int error; + + bus_generic_detach(dev); + if (viapm->iicbb) { + device_delete_child(dev, viapm->iicbb); + } + + if (viapm->iores && (error = bus_release_resource(dev, SYS_RES_IOPORT, + viapm->iorid, viapm->iores))) + return (error); + + return 0; +} + +static int +viapm_pro_detach(device_t dev) +{ + struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev); + int error; + + bus_generic_detach(dev); + if (viapm->smbus) { + device_delete_child(dev, viapm->smbus); + } + + if ((error = bus_release_resource(dev, SYS_RES_IOPORT, + viapm->iorid, viapm->iores))) + return (error); + +#if notyet + if ((error = bus_release_resource(dev, SYS_RES_IRQ, + viapm->irqrid, viapm->irqres)) + return (error); +#endif + + return 0; +} + +static int +viabb_callback(device_t dev, int index, caddr_t *data) +{ + return 0; +} + +static void +viabb_setscl(device_t dev, int ctrl) +{ + struct viapm_softc *viapm = device_get_softc(dev); + u_char val; + + val = VIAPM_INB(GPIO_VAL); + + if (ctrl) + val |= VIAPM_SCL; + else + val &= ~VIAPM_SCL; + + VIAPM_OUTB(GPIO_VAL, val); + + return; +} + +static void +viabb_setsda(device_t dev, int data) +{ + struct viapm_softc *viapm = device_get_softc(dev); + u_char val; + + val = VIAPM_INB(GPIO_VAL); + + if (data) + val |= VIAPM_SDA; + else + val &= ~VIAPM_SDA; + + VIAPM_OUTB(GPIO_VAL, val); + + return; +} + +static int +viabb_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr) +{ + /* reset bus */ + viabb_setsda(dev, 1); + viabb_setscl(dev, 1); + + return (IIC_ENOADDR); +} + +static int +viabb_getscl(device_t dev) +{ + struct viapm_softc *viapm = device_get_softc(dev); + + return ((VIAPM_INB(EXTSMI_VAL) & VIAPM_SCL) != 0); +} + +static int +viabb_getsda(device_t dev) +{ + struct viapm_softc *viapm = device_get_softc(dev); + + return ((VIAPM_INB(EXTSMI_VAL) & VIAPM_SDA) != 0); +} + +static int +viapm_abort(struct viapm_softc *viapm) +{ + VIAPM_OUTB(SMBHCTRL, SMBHCTRL_KILL); + DELAY(10); + + return (0); +} + +static int +viapm_clear(struct viapm_softc *viapm) +{ + VIAPM_OUTB(SMBHST, SMBHST_FAILED | SMBHST_COLLID | + SMBHST_ERROR | SMBHST_INTR); + DELAY(10); + + return (0); +} + +static int +viapm_busy(struct viapm_softc *viapm) +{ + u_char sts; + + sts = VIAPM_INB(SMBHST); + + VIAPM_DEBUG(printf("viapm: idle? STS=0x%x\n", sts)); + + return (sts & SMBHST_BUSY); +} + +/* + * Poll the SMBus controller + */ +static int +viapm_wait(struct viapm_softc *viapm) +{ + int count = 10000; + u_char sts = 0; + int error; + + /* wait for command to complete and SMBus controller is idle */ + while(count--) { + DELAY(10); + sts = VIAPM_INB(SMBHST); + + /* check if the controller is processing a command */ + if (!(sts & SMBHST_BUSY) && (sts & SMBHST_INTR)) + break; + } + + VIAPM_DEBUG(printf("viapm: SMBHST=0x%x\n", sts)); + + error = SMB_ENOERR; + + if (!count) + error |= SMB_ETIMEOUT; + + if (sts & SMBHST_FAILED) + error |= SMB_EABORT; + + if (sts & SMBHST_COLLID) + error |= SMB_ENOACK; + + if (sts & SMBHST_ERROR) + error |= SMB_EBUSERR; + + if (error != SMB_ENOERR) + viapm_abort(viapm); + + viapm_clear(viapm); + + return (error); +} + +static int +viasmb_callback(device_t dev, int index, caddr_t *data) +{ + int error = 0; + + switch (index) { + case SMB_REQUEST_BUS: + case SMB_RELEASE_BUS: + /* ok, bus allocation accepted */ + break; + default: + error = EINVAL; + } + + return (error); +} + +static int +viasmb_quick(device_t dev, u_char slave, int how) +{ + struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev); + int error; + + viapm_clear(viapm); + if (viapm_busy(viapm)) + return (EBUSY); + + switch (how) { + case SMB_QWRITE: + VIAPM_DEBUG(printf("viapm: QWRITE to 0x%x", slave)); + VIAPM_OUTB(SMBHADDR, slave & ~LSB); + break; + case SMB_QREAD: + VIAPM_DEBUG(printf("viapm: QREAD to 0x%x", slave)); + VIAPM_OUTB(SMBHADDR, slave | LSB); + break; + default: + panic("%s: unknown QUICK command (%x)!", __FUNCTION__, + how); + } + + VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_QUICK); + + error = viapm_wait(viapm); + + return (error); +} + +static int +viasmb_sendb(device_t dev, u_char slave, char byte) +{ + struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev); + int error; + + viapm_clear(viapm); + if (viapm_busy(viapm)) + return (EBUSY); + + VIAPM_OUTB(SMBHADDR, slave & ~ LSB); + VIAPM_OUTB(SMBHCMD, byte); + + VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_SENDRECV); + + error = viapm_wait(viapm); + + VIAPM_DEBUG(printf("viapm: SENDB to 0x%x, byte=0x%x, error=0x%x\n", slave, byte, error)); + + return (error); +} + +static int +viasmb_recvb(device_t dev, u_char slave, char *byte) +{ + struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev); + int error; + + viapm_clear(viapm); + if (viapm_busy(viapm)) + return (EBUSY); + + VIAPM_OUTB(SMBHADDR, slave | LSB); + + VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_SENDRECV); + + if ((error = viapm_wait(viapm)) == SMB_ENOERR) + *byte = VIAPM_INB(SMBHDATA0); + + VIAPM_DEBUG(printf("viapm: RECVB from 0x%x, byte=0x%x, error=0x%x\n", slave, *byte, error)); + + return (error); +} + +static int +viasmb_writeb(device_t dev, u_char slave, char cmd, char byte) +{ + struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev); + int error; + + viapm_clear(viapm); + if (viapm_busy(viapm)) + return (EBUSY); + + VIAPM_OUTB(SMBHADDR, slave & ~ LSB); + VIAPM_OUTB(SMBHCMD, cmd); + VIAPM_OUTB(SMBHDATA0, byte); + + VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_BYTE); + + error = viapm_wait(viapm); + + VIAPM_DEBUG(printf("viapm: WRITEB to 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, byte, error)); + + return (error); +} + +static int +viasmb_readb(device_t dev, u_char slave, char cmd, char *byte) +{ + struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev); + int error; + + viapm_clear(viapm); + if (viapm_busy(viapm)) + return (EBUSY); + + VIAPM_OUTB(SMBHADDR, slave | LSB); + VIAPM_OUTB(SMBHCMD, cmd); + + VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_BYTE); + + if ((error = viapm_wait(viapm)) == SMB_ENOERR) + *byte = VIAPM_INB(SMBHDATA0); + + VIAPM_DEBUG(printf("viapm: READB from 0x%x, cmd=0x%x, byte=0x%x, error=0x%x\n", slave, cmd, *byte, error)); + + return (error); +} + +static int +viasmb_writew(device_t dev, u_char slave, char cmd, short word) +{ + struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev); + int error; + + viapm_clear(viapm); + if (viapm_busy(viapm)) + return (EBUSY); + + VIAPM_OUTB(SMBHADDR, slave & ~ LSB); + VIAPM_OUTB(SMBHCMD, cmd); + VIAPM_OUTB(SMBHDATA0, word & 0x00ff); + VIAPM_OUTB(SMBHDATA1, (word & 0xff00) >> 8); + + VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_WORD); + + error = viapm_wait(viapm); + + VIAPM_DEBUG(printf("viapm: WRITEW to 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, word, error)); + + return (error); +} + +static int +viasmb_readw(device_t dev, u_char slave, char cmd, short *word) +{ + struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev); + int error; + u_char high, low; + + viapm_clear(viapm); + if (viapm_busy(viapm)) + return (EBUSY); + + VIAPM_OUTB(SMBHADDR, slave | LSB); + VIAPM_OUTB(SMBHCMD, cmd); + + VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_WORD); + + if ((error = viapm_wait(viapm)) == SMB_ENOERR) { + low = VIAPM_INB(SMBHDATA0); + high = VIAPM_INB(SMBHDATA1); + + *word = ((high & 0xff) << 8) | (low & 0xff); + } + + VIAPM_DEBUG(printf("viapm: READW from 0x%x, cmd=0x%x, word=0x%x, error=0x%x\n", slave, cmd, *word, error)); + + return (error); +} + +static int +viasmb_bwrite(device_t dev, u_char slave, char cmd, u_char count, char *buf) +{ + struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev); + u_char remain, len, i; + int error = SMB_ENOERR; + + viapm_clear(viapm); + if (viapm_busy(viapm)) + return (EBUSY); + + remain = count; + while (remain) { + len = min(remain, 32); + + VIAPM_OUTB(SMBHADDR, slave & ~LSB); + VIAPM_OUTB(SMBHCMD, cmd); + VIAPM_OUTB(SMBHDATA0, len); + i = VIAPM_INB(SMBHCTRL); + + /* fill the 32-byte internal buffer */ + for (i=0; i<len; i++) { + VIAPM_OUTB(SMBHBLOCK, buf[count-remain+i]); + DELAY(2); + } + VIAPM_OUTB(SMBHCMD, cmd); + VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_BLOCK); + + if ((error = viapm_wait(viapm)) != SMB_ENOERR) + goto error; + + remain -= len; + } + +error: + VIAPM_DEBUG(printf("viapm: WRITEBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, count, cmd, error)); + + return (error); + +} + +static int +viasmb_bread(device_t dev, u_char slave, char cmd, u_char count, char *buf) +{ + struct viapm_softc *viapm = (struct viapm_softc *)device_get_softc(dev); + u_char remain, len, i; + int error = SMB_ENOERR; + + viapm_clear(viapm); + if (viapm_busy(viapm)) + return (EBUSY); + + remain = count; + while (remain) { + VIAPM_OUTB(SMBHADDR, slave | LSB); + VIAPM_OUTB(SMBHCMD, cmd); + VIAPM_OUTB(SMBHCTRL, SMBHCTRL_START | SMBHCTRL_BLOCK); + + if ((error = viapm_wait(viapm)) != SMB_ENOERR) + goto error; + + len = VIAPM_INB(SMBHDATA0); + i = VIAPM_INB(SMBHCTRL); /* reset counter */ + + len = min(len, remain); + + /* read the 32-byte internal buffer */ + for (i=0; i<len; i++) { + buf[count-remain+i] = VIAPM_INB(SMBHBLOCK); + DELAY(2); + } + + remain -= len; + } +error: + VIAPM_DEBUG(printf("viapm: READBLK to 0x%x, count=0x%x, cmd=0x%x, error=0x%x", slave, count, cmd, error)); + + return (error); +} + +static device_method_t viapm_methods[] = { + /* device interface */ + DEVMETHOD(device_probe, viapm_586b_probe), + DEVMETHOD(device_attach, viapm_586b_attach), + DEVMETHOD(device_detach, viapm_586b_detach), + + /* iicbb interface */ + DEVMETHOD(iicbb_callback, viabb_callback), + DEVMETHOD(iicbb_setscl, viabb_setscl), + DEVMETHOD(iicbb_setsda, viabb_setsda), + DEVMETHOD(iicbb_getscl, viabb_getscl), + DEVMETHOD(iicbb_getsda, viabb_getsda), + DEVMETHOD(iicbb_reset, viabb_reset), + + { 0, 0 } +}; + +static driver_t viapm_driver = { + "viapm", + viapm_methods, + sizeof(struct viapm_softc), +}; + +static device_method_t viapropm_methods[] = { + /* device interface */ + DEVMETHOD(device_probe, viapm_pro_probe), + DEVMETHOD(device_attach, viapm_pro_attach), + DEVMETHOD(device_detach, viapm_pro_detach), + + /* smbus interface */ + DEVMETHOD(smbus_callback, viasmb_callback), + DEVMETHOD(smbus_quick, viasmb_quick), + DEVMETHOD(smbus_sendb, viasmb_sendb), + DEVMETHOD(smbus_recvb, viasmb_recvb), + DEVMETHOD(smbus_writeb, viasmb_writeb), + DEVMETHOD(smbus_readb, viasmb_readb), + DEVMETHOD(smbus_writew, viasmb_writew), + DEVMETHOD(smbus_readw, viasmb_readw), + DEVMETHOD(smbus_bwrite, viasmb_bwrite), + DEVMETHOD(smbus_bread, viasmb_bread), + + { 0, 0 } +}; + +static driver_t viapropm_driver = { + "viapropm", + viapropm_methods, + sizeof(struct viapm_softc), +}; + +DRIVER_MODULE(viapm, pci, viapm_driver, viapm_devclass, 0, 0); +DRIVER_MODULE(viapropm, pci, viapropm_driver, viapropm_devclass, 0, 0); + +MODULE_DEPEND(viapm, iicbb, IICBB_MINVER, IICBB_PREFVER, IICBB_MAXVER); +MODULE_DEPEND(viapropm, smbus, SMBUS_MINVER, SMBUS_PREFVER, SMBUS_MAXVER); +MODULE_VERSION(viapm, 1); |