Index: sys/boot/fdt/dts/mips/MZK-W300NAG.dts =================================================================== --- /dev/null +++ sys/boot/fdt/dts/mips/MZK-W300NAG.dts @@ -0,0 +1,104 @@ +/dts-v1/; + +#include "rt2880.dtsi" + +/ { + compatible = "MZK-W300NAG", "ralink,rt2880-soc"; + model = "Planex MZK-W300NAG"; + + memory@0 { + device_type = "memory"; + reg = <0x08000000 0x1000000>; + }; + + cfi@1f000000 { + compatible = "cfi-flash"; + reg = <0x1f000000 0x800000>; + bank-width = <2>; + device-width = <2>; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "Bootloader"; + reg = <0x0 0x30000>; + read-only; + }; + + devdata: partition@30000 { + label = "Config"; + reg = <0x00030000 0x00010000>; + read-only; + }; + + factory: partition@40000 { + label = "Factory"; + reg = <0x00040000 0x00010000>; + read-only; + }; + kernel: partition@50000 { + label = "kernel"; + reg = <0x00050000 0x000f0000>; + read-only; + }; + rootfs: partition@160000 { + label = "rootfs"; + reg = <0x00140000 0x002a0000>; + read-only; + }; + cimage: partition@3e0000 { + label = "Cimage"; + reg = <0x003e0000 0x00020000>; + read-only; + }; + }; + + gpio-leds { + compatible = "gpio-leds"; + + status { + label = "status"; + gpios = <&gpio0 12 0>; + }; + + }; + gpio-keys-polled { + compatible = "gpio-keys-polled"; + #address-cells = <1>; + #size-cells = <0>; + poll-interval = <20>; + + reset { + label = "reset"; + gpios = <&gpio0 10 1>; + linux,code = <0x198>; + }; + + }; + + gpioiic { + compatible = "gpioiic"; + gpios = <&gpio0 23 0 + &gpio0 22 0>; + gpio-names = "scl", "sda"; + }; + + rtl8366rb { + compatible = "realtek,rtl8366rb"; + }; + +}; + +ðernet { + mtd-mac-address = <&factory 0x28>; + port-mode = "gigasw"; +}; + +&wmac { + ralink,mtd-eeprom = <&factory 0>; +}; + +&i2c { + status = "okay"; +}; + Index: sys/conf/files =================================================================== --- sys/conf/files +++ sys/conf/files @@ -1757,7 +1757,8 @@ dependency "gpiobus_if.h" dev/gpio/gpioc.c optional gpio \ dependency "gpio_if.h" -dev/gpio/gpioiic.c optional gpioiic +dev/gpio/gpioiic.c optional gpioiic !fdt +dev/gpio/gpioiic_fdt.c optional gpioiic fdt dev/gpio/gpioled.c optional gpioled !fdt dev/gpio/gpioled_fdt.c optional gpioled fdt dev/gpio/gpiopower.c optional gpiopower fdt Index: sys/dev/etherswitch/rtl8366/rtl8366rb.c =================================================================== --- sys/dev/etherswitch/rtl8366/rtl8366rb.c +++ sys/dev/etherswitch/rtl8366/rtl8366rb.c @@ -27,6 +27,7 @@ * $FreeBSD$ */ +#include "opt_platform.h" #include "opt_etherswitch.h" #include @@ -59,6 +60,12 @@ #include #include +#ifdef FDT +#include +#include +#include +#endif + #include "mdio_if.h" #include "iicbus_if.h" #include "miibus_if.h" @@ -143,9 +150,21 @@ rtl8366rb_probe(device_t dev) { struct rtl8366rb_softc *sc; +#ifdef FDT + phandle_t rtl8366_node; - sc = device_get_softc(dev); + if (!ofw_bus_status_okay(dev)) + return (ENXIO); + + rtl8366_node = fdt_find_compatible(OF_finddevice("/"), + "realtek,rtl8366rb", 0); + + if (rtl8366_node == 0) + return (ENXIO); +#endif + sc = device_get_softc(dev); + bzero(sc, sizeof(*sc)); if (smi_probe(dev) != 0) return (ENXIO); @@ -952,9 +971,13 @@ DRIVER_MODULE(rtl8366rb, iicbus, rtl8366rb_driver, rtl8366rb_devclass, 0, 0); DRIVER_MODULE(miibus, rtl8366rb, miibus_driver, miibus_devclass, 0, 0); -DRIVER_MODULE(mdio, rtl8366rb, mdio_driver, mdio_devclass, 0, 0); DRIVER_MODULE(etherswitch, rtl8366rb, etherswitch_driver, etherswitch_devclass, 0, 0); MODULE_VERSION(rtl8366rb, 1); +#ifdef FDT +MODULE_DEPEND(rtl8366rb, ofwbus, 1, 1, 1); /* XXX which versions? */ +#else +DRIVER_MODULE(mdio, rtl8366rb, mdio_driver, mdio_devclass, 0, 0); MODULE_DEPEND(rtl8366rb, iicbus, 1, 1, 1); /* XXX which versions? */ MODULE_DEPEND(rtl8366rb, miibus, 1, 1, 1); /* XXX which versions? */ MODULE_DEPEND(rtl8366rb, etherswitch, 1, 1, 1); /* XXX which versions? */ +#endif Index: sys/dev/gpio/gpioiic_fdt.c =================================================================== --- /dev/null +++ sys/dev/gpio/gpioiic_fdt.c @@ -0,0 +1,243 @@ +/*- + * Copyright (c) 2009 Oleksandr Tymoshenko + * Copyright (c) 2010 Luiz Otavio O Souza + * Copyright (c) 2017 Hiroki Mori + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include "opt_platform.h" + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include "gpiobus_if.h" +#include "iicbb_if.h" + +#define GPIOIIC_SCL_DFLT 0 +#define GPIOIIC_SDA_DFLT 1 +#define GPIOIIC_MIN_PINS 2 + +struct gpioiic_softc +{ + device_t sc_dev; + device_t sc_busdev; + gpio_pin_t scl_pin; + gpio_pin_t sda_pin; +}; + +static int gpioiic_probe(device_t); +static int gpioiic_attach(device_t); + +/* iicbb interface */ +static void gpioiic_reset_bus(device_t); +static void gpioiic_setsda(device_t, int); +static void gpioiic_setscl(device_t, int); +static int gpioiic_getsda(device_t); +static int gpioiic_getscl(device_t); +static int gpioiic_reset(device_t, u_char, u_char, u_char *); + +static int +gpioiic_probe(device_t dev) +{ + if (!ofw_bus_status_okay(dev)) + return (ENXIO); + if (!ofw_bus_is_compatible(dev, "gpioiic")) + return (ENXIO); + + device_set_desc(dev, "GPIO I2C bit-banging FDT driver"); + + return (BUS_PROBE_DEFAULT); +} + +static int +gpioiic_attach(device_t dev) +{ + device_t bitbang; + phandle_t node; + int err; + struct gpioiic_softc *sc; + + sc = device_get_softc(dev); + sc->sc_dev = dev; + sc->sc_busdev = device_get_parent(dev); + + node = ofw_bus_get_node(sc->sc_dev); + err = gpio_pin_get_by_ofw_name(sc->sc_dev, node, "scl", &sc->scl_pin); + if (err != 0) { + device_printf(sc->sc_dev, "cannot get pin scl\n"); + return (ENXIO); + } + err = gpio_pin_get_by_ofw_name(sc->sc_dev, node, "sda", &sc->sda_pin); + if (err != 0) { + device_printf(sc->sc_dev, "cannot get pin sda\n"); + return (ENXIO); + } + + /* add generic bit-banging code */ + bitbang = device_add_child(dev, "iicbb", -1); + device_probe_and_attach(bitbang); + + return (0); +} + +/* + * Reset bus by setting SDA first and then SCL. + * Must always be called with gpio bus locked. + */ +static void +gpioiic_reset_bus(device_t dev) +{ + struct gpioiic_softc *sc; + + sc = device_get_softc(dev); + + gpio_pin_setflags(sc->sda_pin, GPIO_PIN_INPUT); + gpio_pin_setflags(sc->scl_pin, GPIO_PIN_INPUT); +} + +static void +gpioiic_setsda(device_t dev, int val) +{ + struct gpioiic_softc *sc; + + sc = device_get_softc(dev); + + if (val == 0) { + gpio_pin_set_active(sc->sda_pin, 0); + gpio_pin_setflags(sc->sda_pin, GPIO_PIN_OUTPUT); + } else { + gpio_pin_set_active(sc->sda_pin, 1); + gpio_pin_setflags(sc->sda_pin, GPIO_PIN_OUTPUT); + } +} + +static void +gpioiic_setscl(device_t dev, int val) +{ + struct gpioiic_softc *sc; + + sc = device_get_softc(dev); + + if (val == 0) { + gpio_pin_set_active(sc->scl_pin, 0); + gpio_pin_setflags(sc->scl_pin, GPIO_PIN_OUTPUT); + } else { + gpio_pin_set_active(sc->scl_pin, 1); + gpio_pin_setflags(sc->scl_pin, GPIO_PIN_OUTPUT); + } +} + +static int +gpioiic_getscl(device_t dev) +{ + struct gpioiic_softc *sc; + + sc = device_get_softc(dev); + + bool val; + gpio_pin_setflags(sc->scl_pin, GPIO_PIN_INPUT); + gpio_pin_is_active(sc->scl_pin, &val); + + return ((int)val); +} + +static int +gpioiic_getsda(device_t dev) +{ + struct gpioiic_softc *sc; + + sc = device_get_softc(dev); + + bool val; + gpio_pin_setflags(sc->sda_pin, GPIO_PIN_INPUT); + gpio_pin_is_active(sc->sda_pin, &val); + + return ((int)val); +} + +static int +gpioiic_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr) +{ + struct gpioiic_softc *sc; + + sc = device_get_softc(dev); + gpioiic_reset_bus(sc->sc_dev); + + return (IIC_ENOADDR); +} + +static phandle_t +gpioiic_get_node(device_t bus, device_t dev) +{ + + /* We only have one child, the iicbb, which needs our own node. */ + return (ofw_bus_get_node(bus)); +} + +static devclass_t gpioiic_devclass; + +static device_method_t gpioiic_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, gpioiic_probe), + DEVMETHOD(device_attach, gpioiic_attach), + DEVMETHOD(device_detach, bus_generic_detach), + + /* iicbb interface */ + DEVMETHOD(iicbb_setsda, gpioiic_setsda), + DEVMETHOD(iicbb_setscl, gpioiic_setscl), + DEVMETHOD(iicbb_getsda, gpioiic_getsda), + DEVMETHOD(iicbb_getscl, gpioiic_getscl), + DEVMETHOD(iicbb_reset, gpioiic_reset), + + /* OFW bus interface */ + DEVMETHOD(ofw_bus_get_node, gpioiic_get_node), + + DEVMETHOD_END +}; + +static driver_t gpioiic_driver = { + "gpioiic", + gpioiic_methods, + sizeof(struct gpioiic_softc), +}; + +DRIVER_MODULE(gpioiic, ofwbus, gpioiic_driver, gpioiic_devclass, 0, 0); +DRIVER_MODULE(gpioiic, gpiobus, gpioiic_driver, gpioiic_devclass, 0, 0); +DRIVER_MODULE(iicbb, gpioiic, iicbb_driver, iicbb_devclass, 0, 0); +MODULE_DEPEND(gpioiic, iicbb, IICBB_MINVER, IICBB_PREFVER, IICBB_MAXVER); +MODULE_DEPEND(gpioiic, gpiobus, 1, 1, 1); Index: sys/dev/rt/if_rt.c =================================================================== --- sys/dev/rt/if_rt.c +++ sys/dev/rt/if_rt.c @@ -352,10 +352,18 @@ struct rt_softc *sc; struct ifnet *ifp; int error, i; +#ifdef FDT + phandle_t node; + char fdtval[32]; +#endif sc = device_get_softc(dev); sc->dev = dev; +#ifdef FDT + node = ofw_bus_get_node(sc->dev); +#endif + mtx_init(&sc->lock, device_get_nameunit(dev), MTX_NETWORK_LOCK, MTX_DEF | MTX_RECURSE); @@ -477,8 +485,16 @@ GDM_DST_PORT_CPU << GDM_OFRC_P_SHIFT /* fwd Other to CPU */ )); - if (sc->rt_chipid == RT_CHIPID_RT2880) - RT_WRITE(sc, MDIO_CFG, MDIO_2880_100T_INIT); + /* RT2880 is only support FDT */ +#ifdef FDT + if (sc->rt_chipid == RT_CHIPID_RT2880) { + if (OF_getprop(node, "port-mode", fdtval, sizeof(fdtval)) > 0 && + strcmp(fdtval, "gigasw") == 0) + RT_WRITE(sc, MDIO_CFG, MDIO_2880_GIGA_INIT); + else + RT_WRITE(sc, MDIO_CFG, MDIO_2880_100T_INIT); + } +#endif /* allocate Tx and Rx rings */ for (i = 0; i < RT_SOFTC_TX_RING_COUNT; i++) { @@ -2909,7 +2925,7 @@ if (!ofw_bus_is_compatible(dev, "ralink,rt2880-mdio")) return (ENXIO); - device_set_desc(dev, "FV built-in ethernet interface, MDIO controller"); + device_set_desc(dev, "RT built-in ethernet interface, MDIO controller"); return(0); }