From owner-freebsd-embedded@FreeBSD.ORG Sat Dec 3 13:48:35 2011 Return-Path: Delivered-To: freebsd-embedded@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 76947106564A; Sat, 3 Dec 2011 13:48:35 +0000 (UTC) (envelope-from stb@lassitu.de) Received: from gilb.zs64.net (gilb.zs64.net [IPv6:2001:470:1f0b:105e::1ea]) by mx1.freebsd.org (Postfix) with ESMTP id D8C9F8FC0A; Sat, 3 Dec 2011 13:48:34 +0000 (UTC) Received: by gilb.zs64.net (Postfix, from stb@lassitu.de) id B36EA113AE5; Sat, 3 Dec 2011 14:48:33 +0100 (CET) Mime-Version: 1.0 (Apple Message framework v1251.1) Content-Type: multipart/mixed; boundary="Apple-Mail=_AB0956E1-BED7-4759-848C-82B934189B43" From: Stefan Bethke In-Reply-To: Date: Sat, 3 Dec 2011 14:48:33 +0100 Message-Id: <2DB1EAFF-BFEA-4104-8F5A-E4D00BFDF8F9@lassitu.de> 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> <20111202164539.fff3ea91.ray@dlink.ua> <20111202191122.GK25601@funkthat.com> To: Adrian Chadd X-Mailer: Apple Mail (2.1251.1) Cc: Aleksandr Rybalko , freebsd-embedded@freebsd.org Subject: Re: TL-WR1043: switch X-BeenThere: freebsd-embedded@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Dedicated and Embedded Systems List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 03 Dec 2011 13:48:35 -0000 --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 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 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--