From a8f721865de13fdf796dd7a371aed217c14710fa Mon Sep 17 00:00:00 2001 From: nsouch Date: Sat, 31 Oct 1998 11:31:07 +0000 Subject: iicbb is generic support for I2C bit-banging. Other files: timeout management added to the I2C framework. --- sys/dev/iicbus/iicbus.c | 127 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 96 insertions(+), 31 deletions(-) (limited to 'sys/dev/iicbus/iicbus.c') diff --git a/sys/dev/iicbus/iicbus.c b/sys/dev/iicbus/iicbus.c index 41a0cea..930858f 100644 --- a/sys/dev/iicbus/iicbus.c +++ b/sys/dev/iicbus/iicbus.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: iicbus.c,v 1.1.2.7 1998/08/29 16:54:16 son Exp $ + * $Id: iicbus.c,v 1.1.1.1 1998/09/03 20:51:50 nsouch Exp $ * */ @@ -54,6 +54,7 @@ struct iicbus_device { 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 */ }; @@ -61,8 +62,8 @@ struct iicbus_device { * Common I2C addresses */ #define I2C_GENERAL_CALL 0x0 -#define I2C_MASTER_ADDRESS 0xaa -#define I2C_INET_ADDRESS 0xaa +#define PCF_MASTER_ADDRESS 0xaa +#define FIRST_SLAVE_ADDR 0x2 #define MAXSLAVE 256 @@ -74,11 +75,13 @@ struct iicbus_device { * list of known devices */ struct iicbus_device iicbus_children[] = { - { "iic", IICBUS_DRIVER_CLASS, "General Call", I2C_GENERAL_CALL }, { "iicsmb", IICBUS_DRIVER_CLASS, "I2C to SMB bridge" }, { "iic", IICBUS_DEVICE_CLASS, "PCF8574 I2C to 8 bits parallel i/o", 64}, - { "iic", IICBUS_DEVICE_CLASS, "PCF8584 as slave", I2C_MASTER_ADDRESS }, - { "ic", IICBUS_DEVICE_CLASS, "network interface", I2C_INET_ADDRESS }, + { "iic", IICBUS_DEVICE_CLASS, "PCF8584 as slave", PCF_MASTER_ADDRESS }, + { "ic", IICBUS_DEVICE_CLASS, "network interface", PCF_MASTER_ADDRESS }, +#if 0 + { "iic", IICBUS_DRIVER_CLASS, "General Call", I2C_GENERAL_CALL }, +#endif { NULL, 0 } }; @@ -91,6 +94,7 @@ static int iicbus_probe(device_t); static int iicbus_attach(device_t); static void 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 device_method_t iicbus_methods[] = { /* device interface */ @@ -102,7 +106,7 @@ static device_method_t iicbus_methods[] = { /* bus interface */ DEVMETHOD(bus_print_child, iicbus_print_child), DEVMETHOD(bus_read_ivar, iicbus_read_ivar), - DEVMETHOD(bus_write_ivar, bus_generic_write_ivar), + DEVMETHOD(bus_write_ivar, iicbus_write_ivar), DEVMETHOD(bus_create_intr, bus_generic_create_intr), DEVMETHOD(bus_connect_intr, bus_generic_connect_intr), @@ -116,50 +120,85 @@ static driver_t iicbus_driver = { sizeof(struct iicbus_softc), }; +static int +iicbus_probe(device_t dev) +{ + /* always present if probed */ + return (0); +} + +#define MAXADDR 256 +static int iicdev_found[MAXADDR]; + +static int +iic_probe_device(device_t dev, u_char addr) +{ + int count; + char byte; + + if ((addr & 1) == 0) { + /* is device writable? */ + if (!iicbus_start(dev, (u_char)addr, 0)) { + iicbus_stop(dev); + return (1); + } + } else { + /* is device readable? */ + if (!iicbus_block_read(dev, (u_char)addr, &byte, 1, &count)) + return (1); + } + + return (0); +} + /* - * At 'probe' time, we add all the devices which we know about to the - * bus. The generic attach routine will probe and attach them if they - * are alive. + * We add all the devices which we know about. + * The generic attach routine will attach them if they are alive. */ static int -iicbus_probe(device_t dev) +iicbus_attach(device_t dev) { struct iicbus_softc *sc = device_get_softc(dev); struct iicbus_device *iicdev; device_t child; + int addr, count; + char byte; - /* XXX should query parent */ - sc->ownaddr = I2C_MASTER_ADDRESS; + iicbus_reset(dev, IIC_FASTEST, 0, NULL); - iicbus_reset(dev, IIC_FASTEST); + printf("Probing for devices on iicbus%d:", device_get_unit(dev)); - for (iicdev = iicbus_children; iicdev->iicd_name; iicdev++) { + /* probe any devices */ + for (addr = FIRST_SLAVE_ADDR; addr < MAXADDR; addr++) { + if (iic_probe_device(dev, (u_char)addr)) { + printf(" <%x>", addr); + } + } + printf("\n"); + /* attach known devices */ + for (iicdev = iicbus_children; iicdev->iicd_name; iicdev++) { /* probe devices, not drivers */ switch (iicdev->iicd_class) { case IICBUS_DEVICE_CLASS: - if (!iicbus_start(dev, iicdev->iicd_addr)) { - iicbus_stop(dev); + if (iic_probe_device(dev, iicdev->iicd_addr)) iicdev->iicd_alive = 1; - } break; + case IICBUS_DRIVER_CLASS: - iicdev->iicd_addr = sc->ownaddr; + iicdev->iicd_alive = 1; break; + default: panic("%s: unknown class!", __FUNCTION__); } - child = device_add_child(dev, iicdev->iicd_name, -1, iicdev); - device_set_desc(child, iicdev->iicd_desc); + if (iicdev->iicd_alive) { + child = device_add_child(dev, iicdev->iicd_name, + -1, iicdev); + device_set_desc(child, iicdev->iicd_desc); + } } - - return (0); -} - -static int -iicbus_attach(device_t dev) -{ bus_generic_attach(dev); return (0); @@ -171,6 +210,18 @@ iicbus_generic_intr(device_t dev, int event, char *buf) return (0); } +int +iicbus_null_callback(device_t dev, int index, caddr_t data) +{ + return (0); +} + +int +iicbus_null_repeated_start(device_t dev, u_char addr) +{ + return (IIC_ENOTSUPP); +} + static void iicbus_print_child(device_t bus, device_t dev) { @@ -178,9 +229,8 @@ iicbus_print_child(device_t bus, device_t dev) switch (iicdev->iicd_class) { case IICBUS_DEVICE_CLASS: - printf(" on %s%d addr %d %s", device_get_name(bus), - device_get_unit(bus), iicdev->iicd_addr, - (iicdev->iicd_alive) ? "found" : "not found"); + printf(" on %s%d addr 0x%x", device_get_name(bus), + device_get_unit(bus), iicdev->iicd_addr); break; case IICBUS_DRIVER_CLASS: @@ -212,4 +262,19 @@ iicbus_read_ivar(device_t bus, device_t dev, int index, u_long* result) return (0); } +static int +iicbus_write_ivar(device_t bus, device_t dev, int index, u_long val) +{ + struct iicbus_device* iicdev = DEVTOIICBUS(dev); + + 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); -- cgit v1.1