Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 4 Dec 2011 11:55:33 +0000 (UTC)
From:      Adrian Chadd <adrian@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r228257 - head/sys/dev/iicbus
Message-ID:  <201112041155.pB4BtXeA085804@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: adrian
Date: Sun Dec  4 11:55:33 2011
New Revision: 228257
URL: http://svn.freebsd.org/changeset/base/228257

Log:
  Allow the i2c node requirements to be slightly relaxed.
  
  These realtek switch PHYs speak a variant of i2c with some slightly
  modified handling.
  
  From the submitter, slightly modified now that some further digging
  has been done:
  
    The I2C framework makes a assumption that the read/not-write bit of the first
    byte (the address) indicates whether reads or writes are to follow.
  
    The RTL8366 family uses the bus: after sending the address+read/not-write byte,
    two register address bytes are sent, then the 16-bit register value is sent
    or received.  While the register write access can be performed as a 4-byte
    write, the read access requires the read bit to be set, but the first two bytes
    for the register address then need to be transmitted.
  
  This patch maintains the i2c protocol behaviour but allows it to be relaxed
  (for these kinds of switch PHYs, and whatever else Realtek may do with this
  almost-but-not-quite i2c bus) - by setting the "strict" hint to 0.
  The "strict" hint defaults to 1.
  
  Submitted by:	Stefan Bethke <stb@lassitu.de>

Modified:
  head/sys/dev/iicbus/iicbus.c
  head/sys/dev/iicbus/iicbus.h
  head/sys/dev/iicbus/iiconf.c

Modified: head/sys/dev/iicbus/iicbus.c
==============================================================================
--- head/sys/dev/iicbus/iicbus.c	Sun Dec  4 07:28:50 2011	(r228256)
+++ head/sys/dev/iicbus/iicbus.c	Sun Dec  4 11:55:33 2011	(r228257)
@@ -92,10 +92,16 @@ iicbus_attach(device_t dev)
 	unsigned char addr;
 #endif
 	struct iicbus_softc *sc = IICBUS_SOFTC(dev);
+	int strict;
 
 	sc->dev = dev;
 	mtx_init(&sc->lock, "iicbus", NULL, MTX_DEF);
 	iicbus_reset(dev, IIC_FASTEST, 0, NULL);
+	if (resource_int_value(device_get_name(dev),
+		device_get_unit(dev), "strict", &strict) == 0)
+		sc->strict = strict;
+	else
+		sc->strict = 1;
 
 	/* device probing is meaningless since the bus is supposed to be
 	 * hot-plug. Moreover, some I2C chips do not appreciate random

Modified: head/sys/dev/iicbus/iicbus.h
==============================================================================
--- head/sys/dev/iicbus/iicbus.h	Sun Dec  4 07:28:50 2011	(r228256)
+++ head/sys/dev/iicbus/iicbus.h	Sun Dec  4 11:55:33 2011	(r228257)
@@ -41,6 +41,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 */
+	u_char strict;		/* deny operations that violate the
+				 * I2C protocol */
 	struct mtx lock;
 };
 

Modified: head/sys/dev/iicbus/iiconf.c
==============================================================================
--- head/sys/dev/iicbus/iiconf.c	Sun Dec  4 07:28:50 2011	(r228256)
+++ head/sys/dev/iicbus/iiconf.c	Sun Dec  4 11:55:33 2011	(r228257)
@@ -243,8 +243,8 @@ iicbus_write(device_t bus, const char *b
 {
 	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))
+	/* a slave must have been started for writing */
+	if (sc->started == 0 || (sc->strict != 0 && (sc->started & LSB) != 0))
 		return (EINVAL);
 
 	return (IICBUS_WRITE(device_get_parent(bus), buf, len, sent, timeout));
@@ -261,8 +261,8 @@ iicbus_read(device_t bus, char *buf, int
 {
 	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))
+	/* a slave must have been started for reading */
+	if (sc->started == 0 || (sc->strict != 0 && (sc->started & LSB) == 0))
 		return (EINVAL);
 
 	return (IICBUS_READ(device_get_parent(bus), buf, len, read, last, delay));



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201112041155.pB4BtXeA085804>