Index: sys/conf/options.mips =================================================================== --- sys/conf/options.mips +++ sys/conf/options.mips @@ -152,6 +152,7 @@ RT305X opt_rt305x.h RT305X_UBOOT opt_rt305x.h RT305X_USE_UART opt_rt305x.h +RT_MDIO opt_rt305x.h # # Options that affect the pmap. Index: sys/dev/rt/if_rt.c =================================================================== --- sys/dev/rt/if_rt.c +++ sys/dev/rt/if_rt.c @@ -70,6 +70,12 @@ #include #include +#ifdef RT_MDIO +#include +#include +#include "mdio_if.h" +#endif + #if 0 #include #include @@ -91,6 +97,7 @@ #define RT_TX_WATCHDOG_TIMEOUT 5 +#define RT_CHIPID_RT2880 0x2880 #define RT_CHIPID_RT3050 0x3050 #define RT_CHIPID_RT5350 0x5350 #define RT_CHIPID_MT7620 0x7620 @@ -99,6 +106,7 @@ #ifdef FDT /* more specific and new models should go first */ static const struct ofw_compat_data rt_compat_data[] = { + { "ralink,rt2880-eth", RT_CHIPID_RT2880 }, { "ralink,rt3050-eth", RT_CHIPID_RT3050 }, { "ralink,rt3352-eth", RT_CHIPID_RT3050 }, { "ralink,rt3883-eth", RT_CHIPID_RT3050 }, @@ -166,6 +174,8 @@ static void rt_sysctl_attach(struct rt_softc *sc); #ifdef IF_RT_PHY_SUPPORT void rt_miibus_statchg(device_t); +#endif +#if defined(IF_RT_PHY_SUPPORT) || defined(RT_MDIO) static int rt_miibus_readreg(device_t, int, int); static int rt_miibus_writereg(device_t, int, int, int); #endif @@ -351,7 +361,7 @@ sc->mem_rid = 0; sc->mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->mem_rid, - RF_ACTIVE); + RF_ACTIVE | RF_SHAREABLE); if (sc->mem == NULL) { device_printf(dev, "could not allocate memory resource\n"); error = ENXIO; @@ -467,6 +477,9 @@ 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); + /* allocate Tx and Rx rings */ for (i = 0; i < RT_SOFTC_TX_RING_COUNT; i++) { error = rt_alloc_tx_ring(sc, &sc->tx_ring[i], i); @@ -2733,16 +2746,20 @@ "Tx collision count for GDMA ports"); } -#ifdef IF_RT_PHY_SUPPORT +#if defined(IF_RT_PHY_SUPPORT) || defined(RT_MDIO) +/* This code is only work RT2880 and same chip. */ +/* TODO: make RT3052 and later support code. But nobody need it? */ static int rt_miibus_readreg(device_t dev, int phy, int reg) { struct rt_softc *sc = device_get_softc(dev); + int dat; /* * PSEUDO_PHYAD is a special value for indicate switch attached. * No one PHY use PSEUDO_PHYAD (0x1e) address. */ +#ifndef RT_MDIO if (phy == 31) { /* Fake PHY ID for bfeswitch attach */ switch (reg) { @@ -2754,13 +2771,14 @@ return (0x6250); /* bfeswitch */ } } +#endif /* Wait prev command done if any */ while (RT_READ(sc, MDIO_ACCESS) & MDIO_CMD_ONGO); - RT_WRITE(sc, MDIO_ACCESS, - MDIO_CMD_ONGO || - ((phy << MDIO_PHY_ADDR_SHIFT) & MDIO_PHY_ADDR_MASK) || - ((reg << MDIO_PHYREG_ADDR_SHIFT) & MDIO_PHYREG_ADDR_MASK)); + dat = ((phy << MDIO_PHY_ADDR_SHIFT) & MDIO_PHY_ADDR_MASK) | + ((reg << MDIO_PHYREG_ADDR_SHIFT) & MDIO_PHYREG_ADDR_MASK); + RT_WRITE(sc, MDIO_ACCESS, dat); + RT_WRITE(sc, MDIO_ACCESS, dat | MDIO_CMD_ONGO); while (RT_READ(sc, MDIO_ACCESS) & MDIO_CMD_ONGO); return (RT_READ(sc, MDIO_ACCESS) & MDIO_PHY_DATA_MASK); @@ -2770,19 +2788,23 @@ rt_miibus_writereg(device_t dev, int phy, int reg, int val) { struct rt_softc *sc = device_get_softc(dev); + int dat; /* Wait prev command done if any */ while (RT_READ(sc, MDIO_ACCESS) & MDIO_CMD_ONGO); - RT_WRITE(sc, MDIO_ACCESS, - MDIO_CMD_ONGO || MDIO_CMD_WR || - ((phy << MDIO_PHY_ADDR_SHIFT) & MDIO_PHY_ADDR_MASK) || - ((reg << MDIO_PHYREG_ADDR_SHIFT) & MDIO_PHYREG_ADDR_MASK) || - (val & MDIO_PHY_DATA_MASK)); + dat = MDIO_CMD_WR | + ((phy << MDIO_PHY_ADDR_SHIFT) & MDIO_PHY_ADDR_MASK) | + ((reg << MDIO_PHYREG_ADDR_SHIFT) & MDIO_PHYREG_ADDR_MASK) | + (val & MDIO_PHY_DATA_MASK); + RT_WRITE(sc, MDIO_ACCESS, dat); + RT_WRITE(sc, MDIO_ACCESS, dat | MDIO_CMD_ONGO); while (RT_READ(sc, MDIO_ACCESS) & MDIO_CMD_ONGO); return (0); } +#endif +#ifdef IF_RT_PHY_SUPPORT void rt_miibus_statchg(device_t dev) { @@ -2842,3 +2864,85 @@ MODULE_DEPEND(rt, ether, 1, 1, 1); MODULE_DEPEND(rt, miibus, 1, 1, 1); +#ifdef RT_MDIO +MODULE_DEPEND(rt, mdio, 1, 1, 1); + +static int rtmdio_probe(device_t); +static int rtmdio_attach(device_t); +static int rtmdio_detach(device_t); + +static struct mtx miibus_mtx; + +MTX_SYSINIT(miibus_mtx, &miibus_mtx, "rt mii lock", MTX_DEF); + +/* + * Declare an additional, separate driver for accessing the MDIO bus. + */ +static device_method_t rtmdio_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, rtmdio_probe), + DEVMETHOD(device_attach, rtmdio_attach), + DEVMETHOD(device_detach, rtmdio_detach), + + /* bus interface */ + DEVMETHOD(bus_add_child, device_add_child_ordered), + + /* MDIO access */ + DEVMETHOD(mdio_readreg, rt_miibus_readreg), + DEVMETHOD(mdio_writereg, rt_miibus_writereg), +}; + +DEFINE_CLASS_0(rtmdio, rtmdio_driver, rtmdio_methods, + sizeof(struct rt_softc)); +static devclass_t rtmdio_devclass; + +DRIVER_MODULE(miiproxy, rt, miiproxy_driver, miiproxy_devclass, 0, 0); +DRIVER_MODULE(rtmdio, simplebus, rtmdio_driver, rtmdio_devclass, 0, 0); +DRIVER_MODULE(mdio, rtmdio, mdio_driver, mdio_devclass, 0, 0); + +static int +rtmdio_probe(device_t dev) +{ + if (!ofw_bus_status_okay(dev)) + return (ENXIO); + + if (!ofw_bus_is_compatible(dev, "ralink,rt2880-mdio")) + return (ENXIO); + + device_set_desc(dev, "FV built-in ethernet interface, MDIO controller"); + return(0); +} + +static int +rtmdio_attach(device_t dev) +{ + struct rt_softc *sc; + int error; + + sc = device_get_softc(dev); + sc->dev = dev; + sc->mem_rid = 0; + sc->mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, + &sc->mem_rid, RF_ACTIVE | RF_SHAREABLE); + if (sc->mem == NULL) { + device_printf(dev, "couldn't map memory\n"); + error = ENXIO; + goto fail; + } + + sc->bst = rman_get_bustag(sc->mem); + sc->bsh = rman_get_bushandle(sc->mem); + + bus_generic_probe(dev); + bus_enumerate_hinted_children(dev); + error = bus_generic_attach(dev); +fail: + return(error); +} + +static int +rtmdio_detach(device_t dev) +{ + return(0); +} +#endif Index: sys/dev/rt/if_rtreg.h =================================================================== --- sys/dev/rt/if_rtreg.h +++ sys/dev/rt/if_rtreg.h @@ -48,6 +48,10 @@ #define MDIO_PHY_DATA_MASK 0x0000ffff #define MDIO_PHY_DATA_SHIFT 0 +#define MDIO_CFG 0x04 +#define MDIO_2880_100T_INIT 0x1001BC01 +#define MDIO_2880_GIGA_INIT 0x1F01DC01 + #define FE_GLO_CFG 0x08 /*Frame Engine Global Configuration */ #define EXT_VLAN_TYPE_MASK 0xffff0000 #define EXT_VLAN_TYPE_SHIFT 16 Index: sys/gnu/dts/mips/MZK-W04N-XX.dts =================================================================== --- /dev/null +++ sys/gnu/dts/mips/MZK-W04N-XX.dts @@ -0,0 +1,94 @@ +/dts-v1/; + +#include "rt2880.dtsi" + +/ { + compatible = "MZK-WNH", "ralink,rt2880-soc"; + model = "Planex MZK-WNH"; + +/* + memory@0 { + device_type = "memory"; + reg = <0x0 0x2000000>; + }; +*/ + + 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 0x002c0000>; + read-only; + }; + upgrade: partition@400000 { + label = "upgrade"; + reg = <0x00050000 0x003b0000>; + 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>; + }; + + }; + + ip17x@0 { + compatible = "icplus,ip17x"; + }; + +}; + +ðernet { + mtd-mac-address = <&factory 0x28>; +}; + +&wmac { + ralink,mtd-eeprom = <&factory 0>; +}; Index: sys/gnu/dts/mips/rt2880.dtsi =================================================================== --- sys/gnu/dts/mips/rt2880.dtsi +++ sys/gnu/dts/mips/rt2880.dtsi @@ -5,7 +5,7 @@ cpus { cpu@0 { - compatible = "mips,mips24KEc"; + compatible = "mips,mips4KEc"; }; }; @@ -80,6 +80,9 @@ ralink,register-map = [ 00 04 08 0c 20 24 28 2c 30 34 ]; + + interrupt-parent = <&intc>; + interrupts = <7>; }; gpio1: gpio@638 { @@ -182,13 +185,13 @@ compatible = "ralink,rt2880-port", "mediatek,eth-port"; reg = <0>; }; + }; - mdio-bus { - #address-cells = <1>; - #size-cells = <0>; - - status = "disabled"; - }; + mdio-bus { + compatible = "ralink,rt2880-mdio"; + reg = <0x00400000 0x10000>; + #address-cells = <1>; + #size-cells = <0>; }; wmac: wmac@480000 { Index: sys/mips/conf/RT2880_FDT =================================================================== --- /dev/null +++ sys/mips/conf/RT2880_FDT @@ -0,0 +1,77 @@ +# +# RT2880_FDT -- Kernel configuration file for FreeBSD/MIPS RT2880 SoC +# +# This includes all the configurable parts of the kernel. +# +# $FreeBSD$ +# + +#NO_UNIVERSE + +# +# FDT_DTS_FILE should be modified to suit the target board type. +# +#makeoptions FDT_DTS_FILE=MZK-W04N-XX.dts + +# Start with a base configuration +include "../mediatek/std.rt2880" + +ident RT2880 +cpu CPU_MIPS4KC + +# Don't build any modules by default +makeoptions MODULES_OVERRIDE="" + +# Default rootfs device configuration, should be changed to suit target board +options ROOTDEVNAME=\""ufs:md0.uzip\" + +# Support geom_uzip(4) compressed disk images +device geom_map +options GEOM_UZIP + +# Support md(4) and md-based rootfs +device md +options MD_ROOT + +# Interrupt controller support +device mtk_intr_v1 + +# UART device support +nodevice uart_ns8250 +device uart_dev_mtk + +# SPI and SPI flash support +device mtk_spi_v1 +device spibus +device mx25l + +# CFI support +device cfi +device cfid + +# GPIO and gpioled support +device mtk_gpio_v1 +device gpio +device gpioled + +# USB (dwcotg) support +device usb +device mtk_usb_phy +device dwcotg + +# USB umass(4) storage and da(4) support +device umass +device da + +# CAM support, required if umass(4) is enabled above +device pass +device scbus + +# Ethernet, BPF and bridge support +device rt +device bpf +device if_bridge + +# Extres +options EXT_RESOURCES +device clk Index: sys/mips/mediatek/mtk_machdep.c =================================================================== --- sys/mips/mediatek/mtk_machdep.c +++ sys/mips/mediatek/mtk_machdep.c @@ -146,7 +146,11 @@ ctob(physmem) / (1024 * 1024)); } - if (ctob(physmem) < (448 * 1024 * 1024)) { + if (mtk_soc_get_socid() == MTK_SOC_RT2880) { + /* RT2880 memory start is 88000000 */ + dump_avail[1] = phys_avail[1] = ctob(physmem) + + 0x08000000; + } else if (ctob(physmem) < (448 * 1024 * 1024)) { /* * Anything up to 448MB is assumed to be directly * mappable as low memory... Index: sys/mips/mediatek/mtk_soc.h =================================================================== --- sys/mips/mediatek/mtk_soc.h +++ sys/mips/mediatek/mtk_soc.h @@ -32,6 +32,7 @@ enum mtk_soc_id { MTK_SOC_UNKNOWN, + MTK_SOC_RT2880, MTK_SOC_RT3050, MTK_SOC_RT3052, MTK_SOC_RT3350, @@ -47,6 +48,8 @@ MTK_SOC_MAX }; +#define RT2880_CPU_CLKSEL_OFF 20 +#define RT2880_CPU_CLKSEL_MSK 0x3 #define RT305X_CPU_CLKSEL_OFF 18 #define RT305X_CPU_CLKSEL_MSK 0x1 #define RT3352_CPU_CLKSEL_OFF 8 @@ -91,7 +94,10 @@ #define MTK_MHZ(x) ((x) * 1000 * 1000) #define MTK_CPU_CLK_UNKNOWN 0 +#define MTK_CPU_CLK_233MHZ 233333333 #define MTK_CPU_CLK_250MHZ 250000000 +#define MTK_CPU_CLK_266MHZ 266666666 +#define MTK_CPU_CLK_280MHZ 280000000 #define MTK_CPU_CLK_300MHZ 300000000 #define MTK_CPU_CLK_320MHZ 320000000 #define MTK_CPU_CLK_360MHZ 360000000 @@ -111,6 +117,7 @@ #define MTK_UARTDIV_3 3 #define MTK_DEFAULT_BASE 0x10000000 +#define MTK_RT2880_BASE 0x00300000 #define MTK_MT7621_BASE 0x1e000000 #define MTK_DEFAULT_SIZE 0x6000 Index: sys/mips/mediatek/mtk_soc.c =================================================================== --- sys/mips/mediatek/mtk_soc.c +++ sys/mips/mediatek/mtk_soc.c @@ -53,6 +53,7 @@ static uint32_t mtk_soc_timerclk = MTK_CPU_CLK_880MHZ / 2; static const struct ofw_compat_data compat_data[] = { + { "ralink,rt2880-soc", MTK_SOC_RT2880 }, { "ralink,rt3050-soc", MTK_SOC_RT3050 }, { "ralink,rt3052-soc", MTK_SOC_RT3052 }, { "ralink,rt3350-soc", MTK_SOC_RT3350 }, @@ -77,6 +78,30 @@ }; static uint32_t +mtk_detect_cpuclk_rt2880(bus_space_tag_t bst, bus_space_handle_t bsh) +{ + uint32_t val; + + val = bus_space_read_4(bst, bsh, SYSCTL_SYSCFG); + val >>= RT2880_CPU_CLKSEL_OFF; + val &= RT2880_CPU_CLKSEL_MSK; + + switch (val) { + case 0: + return (MTK_CPU_CLK_250MHZ); + case 1: + return (MTK_CPU_CLK_266MHZ); + case 2: + return (MTK_CPU_CLK_280MHZ); + case 3: + return (MTK_CPU_CLK_300MHZ); + } + + /* Never reached */ + return (0); +} + +static uint32_t mtk_detect_cpuclk_rt305x(bus_space_tag_t bst, bus_space_handle_t bsh) { uint32_t val; @@ -260,7 +285,9 @@ } bst = fdtbus_bs_tag; - if (mtk_soc_socid == MTK_SOC_MT7621) + if (mtk_soc_socid == MTK_SOC_RT2880) + base = MTK_RT2880_BASE; + else if (mtk_soc_socid == MTK_SOC_MT7621) base = MTK_MT7621_BASE; else base = MTK_DEFAULT_BASE; @@ -270,6 +297,9 @@ /* First, figure out the CPU clock */ switch (mtk_soc_socid) { + case MTK_SOC_RT2880: + mtk_soc_cpuclk = mtk_detect_cpuclk_rt2880(bst, bsh); + break; case MTK_SOC_RT3050: /* fallthrough */ case MTK_SOC_RT3052: case MTK_SOC_RT3350: @@ -327,6 +357,9 @@ } switch (mtk_soc_socid) { + case MTK_SOC_RT2880: + mtk_soc_uartclk = mtk_soc_cpuclk / MTK_UARTDIV_2; + break; case MTK_SOC_RT3350: /* fallthrough */ case MTK_SOC_RT3050: /* fallthrough */ case MTK_SOC_RT3052: Index: sys/mips/mediatek/std.rt2880 =================================================================== --- /dev/null +++ sys/mips/mediatek/std.rt2880 @@ -0,0 +1,89 @@ +# +# std.rt2880 -- Base kernel configuration file for FreeBSD/MIPS RT2800 SoC +# +# This includes all the required drivers for the SoCs. +# +# $FreeBSD$ +# + +# Include the standard file list for Mediatek SoCs. +files "../mediatek/files.mediatek" + +# Building a mips/mipsel kernel +machine mips mipsel + +# Little-endian machine +makeoptions MIPS_LITTLE_ENDIAN=defined + +# Default kernel load address +makeoptions KERNLOADADDR=0x88001000 + +# Mediatek/Ralink SoC support depends on FDT (with static DTB for the moment) +options FDT +options FDT_DTB_STATIC + +# We rely on INTRNG code +options INTRNG +options MIPS_NIRQ=256 + +# We rely on NEW_PCIB code +options NEW_PCIB + +# Build kernel with gdb(1) debug symbols +makeoptions DEBUG=-g + +# Support for DDB and KDB +options DDB +options KDB + +# Debugging for use in -current +options INVARIANTS +options INVARIANT_SUPPORT +options WITNESS +options WITNESS_SKIPSPIN +options DEBUG_REDZONE +options DEBUG_MEMGUARD + +# For small memory footprints +options VM_KMEM_SIZE_SCALE=1 + +# General options, including scheduler, etc. +options SCHED_ULE # ULE scheduler +options INET # InterNETworking +#options INET6 # IPv6 +options PSEUDOFS # Pseude-filesystem framework +options FFS # Berkeley Fast Filesystem +#options SOFTUPDATES # Enable FFS soft updates support +#options UFS_ACL # Support for access control lists +#options UFS_DIRHASH # Improve big directory performance +#options MSDOSFS # Enable support for MSDOS filesystems +options _KPOSIX_PRIORITY_SCHEDULING # Posix P1003_1B real-time ext. + +# +# Standard drivers section +# +# The drivers in the following section are required in order to successfully +# compile the kernel. +# + +# FDT clock and pinctrl framework +device fdt_clock +device fdt_pinctrl + +# UART support +device uart + +# random support +device random + +# loop device support +device loop + +# ether device support +device ether + +# ether switch support +#device etherswitch +#device miibus +#device ip17x +#device mdio