summaryrefslogtreecommitdiffstats
path: root/sys/dev/iicbus
diff options
context:
space:
mode:
authornsouch <nsouch@FreeBSD.org>1999-01-09 18:08:24 +0000
committernsouch <nsouch@FreeBSD.org>1999-01-09 18:08:24 +0000
commite670443158fa0f8567cc666000f1cf5819c156ca (patch)
treedc9371aa53218a6e6b09f54a5dd8c837e4342de9 /sys/dev/iicbus
parent674988520c88d8bdd31977e29964f169a47a72b1 (diff)
downloadFreeBSD-src-e670443158fa0f8567cc666000f1cf5819c156ca.zip
FreeBSD-src-e670443158fa0f8567cc666000f1cf5819c156ca.tar.gz
Change /dev/smb and /dev/iic interface to allow user programs to interact with
devices dynamically. That means, + only one /dev/iic or /dev/smb device for each smb/iic bus to access + I2C/SMB device address must be given to any ioctl + new devices may be plugged and accessed after boot, which was impossible previously (device addresses were hardcoded into the kernel)
Diffstat (limited to 'sys/dev/iicbus')
-rw-r--r--sys/dev/iicbus/iic.c16
-rw-r--r--sys/dev/iicbus/iic.h19
-rw-r--r--sys/dev/iicbus/iicbus.c35
-rw-r--r--sys/dev/iicbus/iicbus.h4
-rw-r--r--sys/dev/iicbus/iiconf.c99
-rw-r--r--sys/dev/iicbus/iiconf.h18
6 files changed, 157 insertions, 34 deletions
diff --git a/sys/dev/iicbus/iic.c b/sys/dev/iicbus/iic.c
index e2d59fd..e41d08b 100644
--- a/sys/dev/iicbus/iic.c
+++ b/sys/dev/iicbus/iic.c
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: iic.c,v 1.4 1998/10/31 11:31:07 nsouch Exp $
+ * $Id: iic.c,v 1.5 1998/12/07 21:58:16 archie Exp $
*
*/
#include <sys/param.h>
@@ -40,6 +40,7 @@
#include <dev/iicbus/iiconf.h>
#include <dev/iicbus/iicbus.h>
+
#include <machine/iic.h>
#include "iicbus_if.h"
@@ -209,15 +210,16 @@ iicioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p)
{
device_t iicdev = IIC_DEVICE(minor(dev));
struct iic_softc *sc = IIC_SOFTC(minor(dev));
- int error;
device_t parent = device_get_parent(iicdev);
+ struct iiccmd *s = (struct iiccmd *)data;
+ int error, count;
if (!sc)
return (EINVAL);
switch (cmd) {
case I2CSTART:
- error = iicbus_start(parent, sc->sc_addr, 0);
+ error = iicbus_start(parent, s->slave, 0);
break;
case I2CSTOP:
@@ -228,6 +230,14 @@ iicioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p)
error = iicbus_reset(parent, 0, 0, NULL);
break;
+ case I2CWRITE:
+ error = iicbus_write(parent, s->buf, s->count, &count, 0);
+ break;
+
+ case I2CREAD:
+ error = iicbus_read(parent, s->buf, s->count, &count, s->last, 0);
+ break;
+
default:
error = ENODEV;
}
diff --git a/sys/dev/iicbus/iic.h b/sys/dev/iicbus/iic.h
index 1744326..6649821 100644
--- a/sys/dev/iicbus/iic.h
+++ b/sys/dev/iicbus/iic.h
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: iic.h,v 1.1.2.1 1998/07/17 00:54:01 son Exp $
+ * $Id: iic.h,v 1.1 1998/09/03 21:00:08 nsouch Exp $
*
*/
#ifndef __IIC_H
@@ -31,10 +31,17 @@
#include <sys/ioccom.h>
-#define I2CSTART _IO('i', 1) /* start condition */
-#define I2CSTOP _IO('i', 2) /* stop condition */
-#define I2CADDRESS _IOW('i', 3, long) /* address bus */
-#define I2CRSTCARD _IOW('i', 4, long) /* reset the card */
+struct iiccmd {
+ u_char slave;
+ int count;
+ int last;
+ char *buf;
+};
-#endif
+#define I2CSTART _IOW('i', 1, struct iiccmd) /* start condition */
+#define I2CSTOP _IO('i', 2) /* stop condition */
+#define I2CRSTCARD _IOW('i', 3, struct iiccmd) /* reset the card */
+#define I2CWRITE _IOW('i', 4, struct iiccmd) /* send data */
+#define I2CREAD _IOW('i', 5, struct iiccmd) /* receive data */
+#endif
diff --git a/sys/dev/iicbus/iicbus.c b/sys/dev/iicbus/iicbus.c
index fd982ce..cf9f6ba 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.5 1998/11/22 22:01:42 nsouch Exp $
+ * $Id: iicbus.c,v 1.6 1998/12/07 21:58:16 archie Exp $
*
*/
@@ -73,14 +73,14 @@ struct iicbus_device {
/*
* list of known devices
+ *
+ * XXX only one smb driver should exist for each I2C interface
*/
struct iicbus_device iicbus_children[] = {
{ "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", PCF_MASTER_ADDRESS },
- { "ic", IICBUS_DEVICE_CLASS, "network interface", PCF_MASTER_ADDRESS },
+ { "iic", IICBUS_DRIVER_CLASS, "I2C general purpose I/O" },
#if 0
- { "iic", IICBUS_DRIVER_CLASS, "General Call", I2C_GENERAL_CALL },
+ { "ic", IICBUS_DEVICE_CLASS, "network interface", PCF_MASTER_ADDRESS },
#endif
{ NULL, 0 }
};
@@ -121,10 +121,12 @@ static driver_t iicbus_driver = {
static int
iicbus_probe(device_t dev)
{
- /* always present if probed */
+ device_set_desc(dev, "Philips I2C bus");
+
return (0);
}
+#if 0
static int
iic_probe_device(device_t dev, u_char addr)
{
@@ -145,6 +147,7 @@ iic_probe_device(device_t dev, u_char addr)
return (0);
}
+#endif
/*
* We add all the devices which we know about.
@@ -155,10 +158,15 @@ iicbus_attach(device_t dev)
{
struct iicbus_device *iicdev;
device_t child;
- int addr;
iicbus_reset(dev, IIC_FASTEST, 0, NULL);
+ /* device probing is meaningless since the bus is supposed to be
+ * hot-plug. Moreover, some I2C chips do not appreciate random
+ * accesses like stop after start to fast, reads for less than
+ * x bytes...
+ */
+#if 0
printf("Probing for devices on iicbus%d:", device_get_unit(dev));
/* probe any devices */
@@ -168,21 +176,27 @@ iicbus_attach(device_t dev)
}
}
printf("\n");
+#endif
/* attach known devices */
for (iicdev = iicbus_children; iicdev->iicd_name; iicdev++) {
switch (iicdev->iicd_class) {
case IICBUS_DEVICE_CLASS:
/* check if the devclass exists */
- if (devclass_find(iicdev->iicd_name) &&
- iic_probe_device(dev, iicdev->iicd_addr))
+ 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))
+ 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:
@@ -272,4 +286,3 @@ iicbus_write_ivar(device_t bus, device_t dev, int index, u_long val)
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);
-DRIVER_MODULE(iicbus, smbtx, iicbus_driver, iicbus_devclass, 0, 0);
diff --git a/sys/dev/iicbus/iicbus.h b/sys/dev/iicbus/iicbus.h
index 21c0f97..3c23095 100644
--- a/sys/dev/iicbus/iicbus.h
+++ b/sys/dev/iicbus/iicbus.h
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: iicbus.h,v 1.1.1.1 1998/09/03 20:51:50 nsouch Exp $
+ * $Id: iicbus.h,v 1.2 1998/10/31 11:31:07 nsouch Exp $
*
*/
#ifndef __IICBUS_H
@@ -32,6 +32,8 @@
struct iicbus_softc {
device_t owner; /* iicbus owner device structure */
+ u_char started; /* address of the 'started' slave
+ * 0 if no start condition succeeded */
};
extern devclass_t iicbus_devclass;
diff --git a/sys/dev/iicbus/iiconf.c b/sys/dev/iicbus/iiconf.c
index f4056ce..47f1686 100644
--- a/sys/dev/iicbus/iiconf.c
+++ b/sys/dev/iicbus/iiconf.c
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: iiconf.c,v 1.2 1998/10/31 11:31:07 nsouch Exp $
+ * $Id: iiconf.c,v 1.3 1998/11/22 22:01:42 nsouch Exp $
*
*/
#include <sys/param.h>
@@ -65,9 +65,6 @@ iicbus_alloc_bus(device_t parent)
/* add the bus to the parent */
child = device_add_child(parent, "iicbus", -1, NULL);
- if (child)
- device_set_desc(child, "Philips I2C bus");
-
return (child);
}
@@ -164,6 +161,99 @@ iicbus_release_bus(device_t bus, device_t dev)
}
/*
+ * iicbus_started()
+ *
+ * Test if the iicbus is started by the controller
+ */
+int
+iicbus_started(device_t bus)
+{
+ struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus);
+
+ return (sc->started);
+}
+
+/*
+ * iicbus_start()
+ *
+ * Send start condition to the slave addressed by 'slave'
+ */
+int
+iicbus_start(device_t bus, u_char slave, int timeout)
+{
+ struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus);
+ int error = 0;
+
+ if (sc->started)
+ return (EINVAL); /* bus already started */
+
+ if (!(error = IICBUS_START(device_get_parent(bus), slave, timeout)))
+ sc->started = slave;
+ else
+ sc->started = 0;
+
+ return (error);
+}
+
+/*
+ * iicbus_stop()
+ *
+ * Send stop condition to the bus
+ */
+int
+iicbus_stop(device_t bus)
+{
+ struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus);
+ int error = 0;
+
+ if (!sc->started)
+ return (EINVAL); /* bus not started */
+
+ error = IICBUS_STOP(device_get_parent(bus));
+
+ /* refuse any further access */
+ sc->started = 0;
+
+ return (error);
+}
+
+/*
+ * iicbus_write()
+ *
+ * Write a block of data to the slave previously started by
+ * iicbus_start() call
+ */
+int
+iicbus_write(device_t bus, char *buf, int len, int *sent, int timeout)
+{
+ struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus);
+
+ /* a slave must have been started with the appropriate address */
+ if (!sc->started || (sc->started & LSB))
+ return (EINVAL);
+
+ return (IICBUS_WRITE(device_get_parent(bus), buf, len, sent, timeout));
+}
+
+/*
+ * iicbus_read()
+ *
+ * Read a block of data from the slave previously started by
+ * iicbus_read() call
+ */
+int
+iicbus_read(device_t bus, char *buf, int len, int *read, int last, int delay)
+{
+ struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus);
+
+ /* a slave must have been started with the appropriate address */
+ if (!sc->started || !(sc->started & LSB))
+ return (EINVAL);
+
+ return (IICBUS_READ(device_get_parent(bus), buf, len, read, last, delay));
+}
+
+/*
* iicbus_block_write()
*
* Write a block of data to slave ; start/stop protocol managed
@@ -220,3 +310,4 @@ iicbus_get_addr(device_t dev)
return ((u_char)addr);
}
+
diff --git a/sys/dev/iicbus/iiconf.h b/sys/dev/iicbus/iiconf.h
index 874ecd4..0b548fb 100644
--- a/sys/dev/iicbus/iiconf.h
+++ b/sys/dev/iicbus/iiconf.h
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: iiconf.h,v 1.1.1.1 1998/09/03 20:51:50 nsouch Exp $
+ * $Id: iiconf.h,v 1.2 1998/10/31 11:31:07 nsouch Exp $
*/
#ifndef __IICONF_H
#define __IICONF_H
@@ -108,17 +108,17 @@ extern int iicbus_null_callback(device_t, int, caddr_t);
#define iicbus_repeated_start(bus,slave,timeout) \
(IICBUS_REPEATED_START(device_get_parent(bus), slave, timeout))
-#define iicbus_start(bus,slave,timeout) \
- (IICBUS_START(device_get_parent(bus), slave, timeout))
-#define iicbus_stop(bus) \
- (IICBUS_STOP(device_get_parent(bus)))
#define iicbus_reset(bus,speed,addr,oldaddr) \
(IICBUS_RESET(device_get_parent(bus), speed, addr, oldaddr))
-#define iicbus_write(bus,buf,len,sent,timeout) \
- (IICBUS_WRITE(device_get_parent(bus), buf, len, sent, timeout))
-#define iicbus_read(bus,buf,len,sent,last,delay) \
- (IICBUS_READ(device_get_parent(bus), buf, len, sent, last, delay))
+/* basic I2C operations */
+extern int iicbus_started(device_t);
+extern int iicbus_start(device_t, u_char, int);
+extern int iicbus_stop(device_t);
+extern int iicbus_write(device_t, char *, int, int *, int);
+extern int iicbus_read(device_t, char *, int, int *, int, int);
+
+/* Read/write operations with start/stop conditions managed */
extern int iicbus_block_write(device_t, u_char, char *, int, int *);
extern int iicbus_block_read(device_t, u_char, char *, int, int *);
OpenPOWER on IntegriCloud