[mips] [rt2880] Add oldest Ralink MIPS SOC RT2880 support code.

* Target module have ic plus etherswitch ip175c.
* Also add etherswitch support code on rt driver.

Reviewed by:	mizhka
Differential Revision:	https://reviews.freebsd.org/D10336
This commit is contained in:
Adrian Chadd 2017-05-06 06:20:34 +00:00
parent 5c99cda025
commit 01c914420d
10 changed files with 436 additions and 20 deletions

View File

@ -152,6 +152,7 @@ RT3050F opt_rt305x.h
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.

View File

@ -70,6 +70,12 @@ __FBSDID("$FreeBSD$");
#include <dev/mii/mii.h>
#include <dev/mii/miivar.h>
#ifdef RT_MDIO
#include <dev/mdio/mdio.h>
#include <dev/etherswitch/miiproxy.h>
#include "mdio_if.h"
#endif
#if 0
#include <mips/rt305x/rt305x_sysctlvar.h>
#include <mips/rt305x/rt305xreg.h>
@ -91,6 +97,7 @@ __FBSDID("$FreeBSD$");
#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 @@ __FBSDID("$FreeBSD$");
#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_dma_map_addr(void *arg, bus_dma_segment_t *segs,
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 @@ rt_attach(device_t dev)
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 @@ rt_attach(device_t dev)
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 @@ rt_sysctl_attach(struct rt_softc *sc)
"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 @@ rt_miibus_readreg(device_t dev, int phy, int reg)
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 @@ static int
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 @@ DRIVER_MODULE(rt, simplebus, rt_driver, rt_dev_class, 0, 0);
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

View File

@ -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

View File

@ -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";
};
};
&ethernet {
mtd-mac-address = <&factory 0x28>;
};
&wmac {
ralink,mtd-eeprom = <&factory 0>;
};

View File

@ -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 {

77
sys/mips/conf/RT2880_FDT Normal file
View File

@ -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

View File

@ -146,7 +146,11 @@ mips_init(void)
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...

View File

@ -53,6 +53,7 @@ static uint32_t mtk_soc_cpuclk = MTK_CPU_CLK_880MHZ;
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 },
@ -76,6 +77,30 @@ static const struct ofw_compat_data compat_data[] = {
{ NULL, MTK_SOC_UNKNOWN },
};
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)
{
@ -260,7 +285,9 @@ mtk_soc_try_early_detect(void)
}
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 @@ mtk_soc_try_early_detect(void)
/* 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 @@ mtk_soc_try_early_detect(void)
}
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:

View File

@ -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 @@ enum mtk_soc_id {
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 @@ enum mtk_soc_id {
#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 @@ enum mtk_soc_id {
#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

View File

@ -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