diff options
author | nsouch <nsouch@FreeBSD.org> | 2002-03-23 15:49:15 +0000 |
---|---|---|
committer | nsouch <nsouch@FreeBSD.org> | 2002-03-23 15:49:15 +0000 |
commit | 82395b7295123f4d9a786ebd89495ef101103a61 (patch) | |
tree | f78e24d69b8d02162ae886a610fb85cac8989741 /sys/dev/bktr | |
parent | 0dcefe7b55beecbfaeba7c0b20e4b1277b781733 (diff) | |
download | FreeBSD-src-82395b7295123f4d9a786ebd89495ef101103a61.zip FreeBSD-src-82395b7295123f4d9a786ebd89495ef101103a61.tar.gz |
Major rework of the iicbus/smbus framework:
- VIA chipset SMBus controllers added
- alpm driver updated
- Support for dynamic modules added
- bktr FreeBSD smbus updated but not tested
- cleanup
Diffstat (limited to 'sys/dev/bktr')
-rw-r--r-- | sys/dev/bktr/bktr_i2c.c | 300 | ||||
-rw-r--r-- | sys/dev/bktr/bktr_i2c.h | 17 | ||||
-rw-r--r-- | sys/dev/bktr/bktr_os.c | 38 | ||||
-rw-r--r-- | sys/dev/bktr/bktr_reg.h | 18 |
4 files changed, 158 insertions, 215 deletions
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 |