Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 3 Dec 2011 14:48:33 +0100
From:      Stefan Bethke <stb@lassitu.de>
To:        Adrian Chadd <adrian@freebsd.org>
Cc:        Aleksandr Rybalko <ray@dlink.ua>, freebsd-embedded@freebsd.org
Subject:   Re: TL-WR1043: switch
Message-ID:  <2DB1EAFF-BFEA-4104-8F5A-E4D00BFDF8F9@lassitu.de>
In-Reply-To: <CAJ-Vmo=YMTuk6gOsjp15QWpRuBPkdDvM3JvamE6E38MhCsL7iw@mail.gmail.com>
References:  <68ABED76-CB1F-405A-8036-EC254F7511FA@lassitu.de> <3B3DB17D-BF87-40EE-B1C1-445F178E8844@lassitu.de> <86030CEE-6839-4B96-ACDC-2BA9AC1E4AE4@lassitu.de> <2D625CC9-A0E3-47AA-A504-CE8FB2F90245@lassitu.de> <203BF1C8-D528-40C9-8611-9C7AC7E43BAB@lassitu.de> <3C0E9CA3-E130-4E9A-ABCC-1782E28999D1@lassitu.de> <2B8826C7-00C7-4117-B424-4A86F1346DFF@bsdimp.com> <20111130231311.4a154bc5.ray@ddteam.net> <CAJ-Vmon8-yo-UQ%2B81feLT-Yr%2BJimMsEbLHWfd9kZP_s4804%2BtA@mail.gmail.com> <20111202164539.fff3ea91.ray@dlink.ua> <20111202191122.GK25601@funkthat.com> <E29B1787-FF42-4462-81C0-8185F70C45B6@lassitu.de> <CAJ-Vmo=YMTuk6gOsjp15QWpRuBPkdDvM3JvamE6E38MhCsL7iw@mail.gmail.com>

next in thread | previous in thread | raw e-mail | index | archive | help

--Apple-Mail=_AB0956E1-BED7-4759-848C-82B934189B43
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain;
	charset=iso-8859-1

Am 03.12.2011 um 01:36 schrieb Adrian Chadd:

> On 3 December 2011 08:02, Stefan Bethke <stb@lassitu.de> wrote:
>> I see two ways to make iicbus play with the Realtek "System =
Management Interface" protocol: either make the patch I suggested =
optional via a hint, or let a slave device somehow indicate that it =
wants the relaxed semantics.  The hint is likely the option that is =
easier to implement.  Writing a new go-between bus driver is likely too =
complicated for me to accomplish right now.
>=20
> I think exposing it via a quirk somehow, so the iicbus code knows that
> for this particular child device, the relaxed semantics are required.
>=20
> That way an i2c eeprom will be fine using the existing code and
> semantics; the switch PHY child will use your relaxed semantics.
> As there's a few more realtek switch PHYs to write code for, I can
> only see this as being needed. :)
>=20
> Think you could code that up for review?


Attached, as well as at =
http://www.lassitu.de/freebsd/iicbus-for-realtek.patch


The relevant hints are:

# GPIO
hint.gpio.0.at=3D"apb0"
hint.gpio.0.maddr=3D0x18040000
hint.gpio.0.msize=3D0x10000
hint.gpio.0.irq=3D2
=
hint.gpio.0.pins=3D"1=3Do:usb,2=3Do:sys,3=3Di:reset,5=3Do:qss,7=3Di:qss,9=3D=
o:wlan,18=3Di:sda,19=3Di:scl"

hint.iicbus.0.strict=3D0

and you need this in your kernel config:

device      gpio
device      gpioiic
device      iicbb
device      iicbus
device      iic


Stefan

--=20
Stefan Bethke <stb@lassitu.de>   Fon +49 151 14070811



--Apple-Mail=_AB0956E1-BED7-4759-848C-82B934189B43
Content-Disposition: attachment;
	filename=iicbus-for-realtek.patch
Content-Type: application/octet-stream;
	name="iicbus-for-realtek.patch"
Content-Transfer-Encoding: 7bit

Index: sys/dev/iicbus/iiconf.c
===================================================================
--- sys/dev/iicbus/iiconf.c	(revision 228073)
+++ sys/dev/iicbus/iiconf.c	(working copy)
@@ -243,8 +243,8 @@
 {
 	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 @@
 {
 	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));
Index: sys/dev/iicbus/iicbus.c
===================================================================
--- sys/dev/iicbus/iicbus.c	(revision 228073)
+++ sys/dev/iicbus/iicbus.c	(working copy)
@@ -92,10 +92,17 @@
 	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_printf(dev, "strict=%d\n", sc->strict);
 
 	/* device probing is meaningless since the bus is supposed to be
 	 * hot-plug. Moreover, some I2C chips do not appreciate random
Index: sys/dev/iicbus/iicbus.h
===================================================================
--- sys/dev/iicbus/iicbus.h	(revision 228073)
+++ sys/dev/iicbus/iicbus.h	(working copy)
@@ -41,6 +41,8 @@
 	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;
 };
 
Index: sys/dev/gpio/gpioiic.c
===================================================================
--- sys/dev/gpio/gpioiic.c	(revision 228073)
+++ sys/dev/gpio/gpioiic.c	(working copy)
@@ -48,8 +48,6 @@
 
 #include "iicbb_if.h"
 
-#define	SCL_PIN		0	/* gpiobus mapped pin 6 */
-#define	SDA_PIN		1	/* gpiobus mapped pin 7 */
 
 struct gpioiic_softc 
 {
@@ -57,6 +55,8 @@
 	device_t	sc_busdev;
 	struct mtx	sc_mtx;
 	struct cdev	*sc_leddev;
+	int		scl_pin;
+	int		sda_pin;
 };
 
 static int gpioiic_probe(device_t);
@@ -88,6 +88,14 @@
 
 	sc->sc_dev = dev;
 	sc->sc_busdev = device_get_parent(dev);
+	device_printf(dev, "parent %s\n", device_get_name(device_get_parent(dev)));
+	if (resource_int_value(device_get_name(dev),
+        device_get_unit(dev), "scl", &sc->scl_pin))
+		sc->scl_pin = 0;
+	if (resource_int_value(device_get_name(dev),
+        device_get_unit(dev), "sda", &sc->sda_pin))
+		sc->sda_pin = 1;
+	device_printf(dev, "scl=%d, sda=%d\n", sc->scl_pin, sc->sda_pin);
 
 	/* add generic bit-banging code */
 	bitbang = device_add_child(dev, "iicbb", -1);
@@ -105,9 +113,9 @@
 {
 	struct gpioiic_softc		*sc = device_get_softc(dev);
 
-	GPIOBUS_PIN_SETFLAGS(sc->sc_busdev, sc->sc_dev, SDA_PIN,
+	GPIOBUS_PIN_SETFLAGS(sc->sc_busdev, sc->sc_dev, sc->sda_pin,
 	    GPIO_PIN_INPUT);
-	GPIOBUS_PIN_SETFLAGS(sc->sc_busdev, sc->sc_dev, SCL_PIN,
+	GPIOBUS_PIN_SETFLAGS(sc->sc_busdev, sc->sc_dev, sc->scl_pin,
 	    GPIO_PIN_INPUT);
 }
 
@@ -142,11 +150,11 @@
 
 	GPIOBUS_LOCK_BUS(sc->sc_busdev);
 	if (val == 0) {
-		GPIOBUS_PIN_SET(sc->sc_busdev, sc->sc_dev, SDA_PIN, 0);
-		GPIOBUS_PIN_SETFLAGS(sc->sc_busdev, sc->sc_dev, SDA_PIN,
+		GPIOBUS_PIN_SET(sc->sc_busdev, sc->sc_dev, sc->sda_pin, 0);
+		GPIOBUS_PIN_SETFLAGS(sc->sc_busdev, sc->sc_dev, sc->sda_pin,
 		    GPIO_PIN_OUTPUT);
 	} else {
-		GPIOBUS_PIN_SETFLAGS(sc->sc_busdev, sc->sc_dev, SDA_PIN,
+		GPIOBUS_PIN_SETFLAGS(sc->sc_busdev, sc->sc_dev, sc->sda_pin,
 		    GPIO_PIN_INPUT);
 	}
 	GPIOBUS_UNLOCK_BUS(sc->sc_busdev);
@@ -159,11 +167,11 @@
 
 	GPIOBUS_LOCK_BUS(sc->sc_busdev);
 	if (val == 0) {
-		GPIOBUS_PIN_SET(sc->sc_busdev, sc->sc_dev, SCL_PIN, 0);
-		GPIOBUS_PIN_SETFLAGS(sc->sc_busdev, sc->sc_dev, SCL_PIN,
+		GPIOBUS_PIN_SET(sc->sc_busdev, sc->sc_dev, sc->scl_pin, 0);
+		GPIOBUS_PIN_SETFLAGS(sc->sc_busdev, sc->sc_dev, sc->scl_pin,
 		    GPIO_PIN_OUTPUT);
 	} else {
-		GPIOBUS_PIN_SETFLAGS(sc->sc_busdev, sc->sc_dev, SCL_PIN,
+		GPIOBUS_PIN_SETFLAGS(sc->sc_busdev, sc->sc_dev, sc->scl_pin,
 		    GPIO_PIN_INPUT);
 	}
 	GPIOBUS_UNLOCK_BUS(sc->sc_busdev);
@@ -176,9 +184,9 @@
 	unsigned int			val;
 
 	GPIOBUS_LOCK_BUS(sc->sc_busdev);
-	GPIOBUS_PIN_SETFLAGS(sc->sc_busdev, sc->sc_dev, SCL_PIN,
+	GPIOBUS_PIN_SETFLAGS(sc->sc_busdev, sc->sc_dev, sc->scl_pin,
 	    GPIO_PIN_INPUT);
-	GPIOBUS_PIN_GET(sc->sc_busdev, sc->sc_dev, SCL_PIN, &val);
+	GPIOBUS_PIN_GET(sc->sc_busdev, sc->sc_dev, sc->scl_pin, &val);
 	GPIOBUS_UNLOCK_BUS(sc->sc_busdev);
 
 	return ((int)val);
@@ -191,9 +199,9 @@
 	unsigned int			val;
 
 	GPIOBUS_LOCK_BUS(sc->sc_busdev);
-	GPIOBUS_PIN_SETFLAGS(sc->sc_busdev, sc->sc_dev, SDA_PIN,
+	GPIOBUS_PIN_SETFLAGS(sc->sc_busdev, sc->sc_dev, sc->sda_pin,
 	    GPIO_PIN_INPUT);
-	GPIOBUS_PIN_GET(sc->sc_busdev, sc->sc_dev, SDA_PIN, &val);
+	GPIOBUS_PIN_GET(sc->sc_busdev, sc->sc_dev, sc->sda_pin, &val);
 	GPIOBUS_UNLOCK_BUS(sc->sc_busdev);
 
 	return ((int)val);
Index: sys/mips/atheros/ar71xx_gpio.c
===================================================================
--- sys/mips/atheros/ar71xx_gpio.c	(revision 228073)
+++ sys/mips/atheros/ar71xx_gpio.c	(working copy)
@@ -349,6 +349,48 @@
 }
 
 static int
+ar71xx_gpio_configure_from_hint(device_t dev)
+{
+	struct ar71xx_gpio_softc *sc = device_get_softc(dev);
+	const char *c, *d;
+	int i, caps;
+	
+	if (resource_string_value(device_get_name(dev), 
+	    device_get_unit(dev), "pins", &c))
+		return (ENXIO);
+	i = 0;
+	/* "1=o:usb,2=o:sys" */
+	while (c) {
+		d = strchr(c, '=');
+		if (d == NULL)
+			return (ENXIO);
+		sc->gpio_pins[i].gp_pin = strtol(c, NULL, 10);
+		sc->gpio_pins[i].gp_caps = DEFAULT_CAPS;
+		sc->gpio_pins[i].gp_flags = 0;
+		d++;
+		if (d[0] != 'i' && d[0] != 'o' && d[1] != ':')
+			return (ENXIO);
+		caps = d[0] == 'o' ? GPIO_PIN_OUTPUT : GPIO_PIN_INPUT;
+		d += 2;
+		c = d;
+		d = strchr(d, ',');
+		if (d != NULL) {
+	        strncpy(sc->gpio_pins[i].gp_name, c,
+				d - c < GPIOMAXNAME ? d - c : GPIOMAXNAME);
+			c = d;
+			c++;
+		} else {
+	        strncpy(sc->gpio_pins[i].gp_name, c, GPIOMAXNAME);
+			c = NULL;
+		}
+		ar71xx_gpio_pin_configure(sc, &sc->gpio_pins[i], caps);
+		i++;
+	}
+	sc->gpio_npins = i;
+	return (0);
+}
+
+static int
 ar71xx_gpio_attach(device_t dev)
 {
 	struct ar71xx_gpio_softc *sc = device_get_softc(dev);
@@ -393,20 +435,21 @@
 	/* Configure all pins as input */
 	/* disable interrupts for all pins */
 	GPIO_WRITE(sc, AR71XX_GPIO_INT_MASK, 0);
-	pinp = ar71xx_gpio_pins;
-	i = 0;
-	while (pinp->name) {
-		strncpy(sc->gpio_pins[i].gp_name, pinp->name, GPIOMAXNAME);
-		sc->gpio_pins[i].gp_pin = pinp->pin;
-		sc->gpio_pins[i].gp_caps = DEFAULT_CAPS;
-		sc->gpio_pins[i].gp_flags = 0;
-		ar71xx_gpio_pin_configure(sc, &sc->gpio_pins[i], pinp->flags);
-		pinp++;
-		i++;
+	if (ar71xx_gpio_configure_from_hint(dev)) {
+        pinp = ar71xx_gpio_pins;
+        i = 0;
+        while (pinp->name) {
+            strncpy(sc->gpio_pins[i].gp_name, pinp->name, GPIOMAXNAME);
+            sc->gpio_pins[i].gp_pin = pinp->pin;
+            sc->gpio_pins[i].gp_caps = DEFAULT_CAPS;
+            sc->gpio_pins[i].gp_flags = 0;
+            ar71xx_gpio_pin_configure(sc, &sc->gpio_pins[i], pinp->flags);
+            pinp++;
+            i++;
+        }
+        sc->gpio_npins = i;
 	}
 
-	sc->gpio_npins = i;
-
 	device_add_child(dev, "gpioc", device_get_unit(dev));
 	device_add_child(dev, "gpiobus", device_get_unit(dev));
 	return (bus_generic_attach(dev));

--Apple-Mail=_AB0956E1-BED7-4759-848C-82B934189B43--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?2DB1EAFF-BFEA-4104-8F5A-E4D00BFDF8F9>