mirror of
https://github.com/opnsense/src.git
synced 2026-06-11 09:41:03 -04:00
eqos: Add StarFive JH7110 variant
Found on the VisionFive v2 SBC, and similar. Reviewed by: mhorne Tested by: mhorne Discussed with: sos Differential Revision: https://reviews.freebsd.org/D45600
This commit is contained in:
parent
e69623451e
commit
cd92dd2324
6 changed files with 260 additions and 6 deletions
|
|
@ -456,7 +456,7 @@ eqos_reset(struct eqos_softc *sc)
|
|||
int retry;
|
||||
|
||||
WR4(sc, GMAC_DMA_MODE, GMAC_DMA_MODE_SWR);
|
||||
for (retry = 2000; retry > 0; retry--) {
|
||||
for (retry = 5000; retry > 0; retry--) {
|
||||
DELAY(1000);
|
||||
val = RD4(sc, GMAC_DMA_MODE);
|
||||
if (!(val & GMAC_DMA_MODE_SWR))
|
||||
|
|
@ -491,7 +491,7 @@ eqos_init(void *if_softc)
|
|||
struct eqos_softc *sc = if_softc;
|
||||
if_t ifp = sc->ifp;
|
||||
struct mii_data *mii = device_get_softc(sc->miibus);
|
||||
uint32_t val;
|
||||
uint32_t val, mtl_tx_val, mtl_rx_val;
|
||||
|
||||
if (if_getdrvflags(ifp) & IFF_DRV_RUNNING)
|
||||
return;
|
||||
|
|
@ -508,13 +508,18 @@ eqos_init(void *if_softc)
|
|||
val = RD4(sc, GMAC_DMA_CHAN0_CONTROL);
|
||||
val &= ~GMAC_DMA_CHAN0_CONTROL_DSL_MASK;
|
||||
val |= ((DESC_ALIGN - 16) / 8) << GMAC_DMA_CHAN0_CONTROL_DSL_SHIFT;
|
||||
val |= GMAC_DMA_CHAN0_CONTROL_PBLX8;
|
||||
if (sc->pblx8)
|
||||
val |= GMAC_DMA_CHAN0_CONTROL_PBLX8;
|
||||
WR4(sc, GMAC_DMA_CHAN0_CONTROL, val);
|
||||
val = RD4(sc, GMAC_DMA_CHAN0_TX_CONTROL);
|
||||
if (sc->txpbl > 0)
|
||||
val |= (sc->txpbl << GMAC_DMA_CHAN0_TXRX_PBL_SHIFT);
|
||||
val |= GMAC_DMA_CHAN0_TX_CONTROL_OSP;
|
||||
val |= GMAC_DMA_CHAN0_TX_CONTROL_START;
|
||||
WR4(sc, GMAC_DMA_CHAN0_TX_CONTROL, val);
|
||||
val = RD4(sc, GMAC_DMA_CHAN0_RX_CONTROL);
|
||||
if (sc->rxpbl > 0)
|
||||
val |= (sc->rxpbl << GMAC_DMA_CHAN0_TXRX_PBL_SHIFT);
|
||||
val &= ~GMAC_DMA_CHAN0_RX_CONTROL_RBSZ_MASK;
|
||||
val |= (MCLBYTES << GMAC_DMA_CHAN0_RX_CONTROL_RBSZ_SHIFT);
|
||||
val |= GMAC_DMA_CHAN0_RX_CONTROL_START;
|
||||
|
|
@ -527,11 +532,19 @@ eqos_init(void *if_softc)
|
|||
GMAC_MMC_CONTROL_CNTPRSTLVL);
|
||||
|
||||
/* Configure operation modes */
|
||||
if (sc->thresh_dma_mode) {
|
||||
mtl_tx_val = sc->ttc;
|
||||
mtl_rx_val = sc->rtc;
|
||||
} else {
|
||||
mtl_tx_val = GMAC_MTL_TXQ0_OPERATION_MODE_TSF;
|
||||
mtl_rx_val = GMAC_MTL_RXQ0_OPERATION_MODE_RSF;
|
||||
}
|
||||
|
||||
WR4(sc, GMAC_MTL_TXQ0_OPERATION_MODE,
|
||||
GMAC_MTL_TXQ0_OPERATION_MODE_TSF |
|
||||
mtl_tx_val |
|
||||
GMAC_MTL_TXQ0_OPERATION_MODE_TXQEN_EN);
|
||||
WR4(sc, GMAC_MTL_RXQ0_OPERATION_MODE,
|
||||
GMAC_MTL_RXQ0_OPERATION_MODE_RSF |
|
||||
mtl_rx_val |
|
||||
GMAC_MTL_RXQ0_OPERATION_MODE_FEP |
|
||||
GMAC_MTL_RXQ0_OPERATION_MODE_FUP);
|
||||
|
||||
|
|
@ -1112,6 +1125,14 @@ eqos_attach(device_t dev)
|
|||
int error;
|
||||
int n;
|
||||
|
||||
/* default values */
|
||||
sc->thresh_dma_mode = false;
|
||||
sc->pblx8 = true;
|
||||
sc->txpbl = 0;
|
||||
sc->rxpbl = 0;
|
||||
sc->ttc = 0x10;
|
||||
sc->rtc = 0;
|
||||
|
||||
/* setup resources */
|
||||
if (bus_alloc_resources(dev, eqos_spec, sc->res)) {
|
||||
device_printf(dev, "Could not allocate resources\n");
|
||||
|
|
@ -1128,7 +1149,7 @@ eqos_attach(device_t dev)
|
|||
GMAC_MAC_VERSION_USERVER_SHIFT;
|
||||
snpsver = ver & GMAC_MAC_VERSION_SNPSVER_MASK;
|
||||
|
||||
if (snpsver != 0x51) {
|
||||
if (snpsver != 0x51 && snpsver != 0x52) {
|
||||
device_printf(dev, "EQOS version 0x%02x not supported\n",
|
||||
snpsver);
|
||||
return (ENXIO);
|
||||
|
|
|
|||
|
|
@ -241,6 +241,7 @@
|
|||
#define GMAC_DMA_CHAN0_RX_END_ADDR 0x1128
|
||||
#define GMAC_DMA_CHAN0_TX_RING_LEN 0x112C
|
||||
#define GMAC_DMA_CHAN0_RX_RING_LEN 0x1130
|
||||
#define GMAC_DMA_CHAN0_TXRX_PBL_SHIFT 16
|
||||
#define GMAC_DMA_CHAN0_INTR_ENABLE 0x1134
|
||||
#define GMAC_DMA_CHAN0_INTR_ENABLE_NIE (1U << 15)
|
||||
#define GMAC_DMA_CHAN0_INTR_ENABLE_AIE (1U << 14)
|
||||
|
|
|
|||
219
sys/dev/eqos/if_eqos_starfive.c
Normal file
219
sys/dev/eqos/if_eqos_starfive.c
Normal file
|
|
@ -0,0 +1,219 @@
|
|||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2024 Jari Sihvola <jsihv@gmx.com>
|
||||
*/
|
||||
|
||||
#include "opt_platform.h"
|
||||
#include <sys/cdefs.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/endian.h>
|
||||
#include <sys/gpio.h>
|
||||
#include <sys/rman.h>
|
||||
#include <sys/socket.h>
|
||||
#include <machine/bus.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/if_media.h>
|
||||
#include <dev/mii/mii.h>
|
||||
#include <dev/mii/miivar.h>
|
||||
|
||||
#include <dev/ofw/ofw_bus.h>
|
||||
#include <dev/ofw/ofw_bus_subr.h>
|
||||
|
||||
#include <dev/hwreset/hwreset.h>
|
||||
#include <dev/regulator/regulator.h>
|
||||
|
||||
#include <dev/eqos/if_eqos_var.h>
|
||||
|
||||
#include "if_eqos_if.h"
|
||||
#include "gpio_if.h"
|
||||
|
||||
#include <dev/clk/clk.h>
|
||||
|
||||
/* JH7110's board specific code for eqos Ethernet controller driver */
|
||||
|
||||
#define JH7110_CSR_FREQ 198000000
|
||||
|
||||
#define WR4(sc, o, v) bus_write_4(sc->base.res[EQOS_RES_MEM], (o), (v))
|
||||
|
||||
static const struct ofw_compat_data compat_data[] = {
|
||||
{"starfive,jh7110-dwmac", 1},
|
||||
{ NULL, 0}
|
||||
};
|
||||
|
||||
struct if_eqos_starfive_softc {
|
||||
struct eqos_softc base;
|
||||
clk_t gtx;
|
||||
clk_t tx;
|
||||
clk_t stmmaceth;
|
||||
clk_t pclk;
|
||||
};
|
||||
|
||||
static int
|
||||
if_eqos_starfive_set_speed(device_t dev, int speed)
|
||||
{
|
||||
struct if_eqos_starfive_softc *sc = device_get_softc(dev);
|
||||
uint64_t freq;
|
||||
int err;
|
||||
|
||||
switch (speed) {
|
||||
case IFM_1000_T:
|
||||
case IFM_1000_SX:
|
||||
freq = 125000000;
|
||||
break;
|
||||
case IFM_100_TX:
|
||||
freq = 25000000;
|
||||
break;
|
||||
case IFM_10_T:
|
||||
freq = 2500000;
|
||||
break;
|
||||
default:
|
||||
device_printf(dev, "unsupported media %u\n", speed);
|
||||
return (-EINVAL);
|
||||
}
|
||||
|
||||
clk_set_freq(sc->gtx, freq, 0);
|
||||
err = clk_enable(sc->gtx);
|
||||
if (err != 0) {
|
||||
device_printf(dev, "Could not enable clock %s\n",
|
||||
clk_get_name(sc->gtx));
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int
|
||||
if_eqos_starfive_clk_init(device_t dev)
|
||||
{
|
||||
struct if_eqos_starfive_softc *sc = device_get_softc(dev);
|
||||
int err;
|
||||
|
||||
if (clk_get_by_ofw_name(dev, 0, "gtx", &sc->gtx) != 0) {
|
||||
device_printf(sc->base.dev, "could not get gtx clock\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
if (clk_get_by_ofw_name(dev, 0, "tx", &sc->tx) == 0) {
|
||||
err = clk_enable(sc->tx);
|
||||
if (err != 0) {
|
||||
device_printf(dev, "Could not enable clock %s\n",
|
||||
clk_get_name(sc->tx));
|
||||
}
|
||||
}
|
||||
if (clk_get_by_ofw_name(dev, 0, "stmmaceth", &sc->stmmaceth) == 0) {
|
||||
err = clk_enable(sc->stmmaceth);
|
||||
if (err != 0) {
|
||||
device_printf(dev, "Could not enable clock %s\n",
|
||||
clk_get_name(sc->stmmaceth));
|
||||
}
|
||||
}
|
||||
if (clk_get_by_ofw_name(dev, 0, "pclk", &sc->pclk) == 0) {
|
||||
err = clk_enable(sc->pclk);
|
||||
if (err != 0) {
|
||||
device_printf(dev, "Could not enable clock %s\n",
|
||||
clk_get_name(sc->pclk));
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
if_eqos_starfive_init(device_t dev)
|
||||
{
|
||||
struct if_eqos_starfive_softc *sc = device_get_softc(dev);
|
||||
hwreset_t rst_ahb, rst_stmmaceth;
|
||||
phandle_t node;
|
||||
|
||||
node = ofw_bus_get_node(dev);
|
||||
|
||||
sc->base.ttc = 0x10;
|
||||
sc->base.rtc = 0;
|
||||
|
||||
if (OF_hasprop(node, "snps,force_thresh_dma_mode"))
|
||||
sc->base.thresh_dma_mode = true;
|
||||
|
||||
if (OF_hasprop(node, "snps,no-pbl-x8"))
|
||||
sc->base.pblx8 = false;
|
||||
|
||||
if (OF_hasprop(node, "snps,txpbl")) {
|
||||
OF_getencprop(node, "snps,txpbl", &sc->base.txpbl,
|
||||
sizeof(sc->base.txpbl));
|
||||
}
|
||||
if (OF_hasprop(node, "snps,rxpbl")) {
|
||||
OF_getencprop(node, "snps,rxpbl", &sc->base.rxpbl,
|
||||
sizeof(sc->base.rxpbl));
|
||||
}
|
||||
|
||||
if (hwreset_get_by_ofw_name(dev, 0, "ahb", &rst_ahb)) {
|
||||
device_printf(dev, "Cannot get ahb reset\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
if (hwreset_assert(rst_ahb) != 0) {
|
||||
device_printf(dev, "Cannot assert ahb reset\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
if (hwreset_get_by_ofw_name(dev, 0, "stmmaceth", &rst_stmmaceth)) {
|
||||
device_printf(dev, "Cannot get stmmaceth reset\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
if (hwreset_assert(rst_stmmaceth) != 0) {
|
||||
device_printf(dev, "Cannot assert stmmaceth reset\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
sc->base.csr_clock = JH7110_CSR_FREQ;
|
||||
sc->base.csr_clock_range = GMAC_MAC_MDIO_ADDRESS_CR_150_250;
|
||||
|
||||
if (if_eqos_starfive_clk_init(dev) != 0) {
|
||||
device_printf(dev, "Clock initialization failed\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
if (hwreset_deassert(rst_ahb) != 0) {
|
||||
device_printf(dev, "Cannot deassert rst_ahb\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
if (hwreset_deassert(rst_stmmaceth) != 0) {
|
||||
device_printf(dev, "Cannot deassert rst_stmmaceth\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
eqos_starfive_probe(device_t dev)
|
||||
{
|
||||
if (!ofw_bus_status_okay(dev))
|
||||
return (ENXIO);
|
||||
if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
|
||||
return (ENXIO);
|
||||
|
||||
device_set_desc(dev, "DesignWare EQOS Gigabit Ethernet for JH7110");
|
||||
|
||||
return (BUS_PROBE_DEFAULT);
|
||||
}
|
||||
|
||||
|
||||
static device_method_t eqos_starfive_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, eqos_starfive_probe),
|
||||
|
||||
/* EQOS interface */
|
||||
DEVMETHOD(if_eqos_init, if_eqos_starfive_init),
|
||||
DEVMETHOD(if_eqos_set_speed, if_eqos_starfive_set_speed),
|
||||
|
||||
DEVMETHOD_END
|
||||
};
|
||||
|
||||
DEFINE_CLASS_1(eqos, eqos_starfive_driver, eqos_starfive_methods,
|
||||
sizeof(struct if_eqos_starfive_softc), eqos_driver);
|
||||
DRIVER_MODULE(eqos_starfive, simplebus, eqos_starfive_driver, 0, 0);
|
||||
|
|
@ -85,6 +85,13 @@ struct eqos_softc {
|
|||
bool link_up;
|
||||
int tx_watchdog;
|
||||
|
||||
bool thresh_dma_mode;
|
||||
bool pblx8;
|
||||
uint32_t txpbl;
|
||||
uint32_t rxpbl;
|
||||
uint32_t ttc;
|
||||
uint32_t rtc;
|
||||
|
||||
struct ifnet *ifp;
|
||||
device_t miibus;
|
||||
struct mtx lock;
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
device uart_snps # DesignWare Synopsis UART driver
|
||||
|
||||
device eqos
|
||||
|
||||
# MMC/SD/SDIO Card slot support
|
||||
device dwmmc
|
||||
device dwmmc_starfive
|
||||
|
|
|
|||
|
|
@ -5,4 +5,8 @@ dev/clk/starfive/jh7110_clk_sys.c standard
|
|||
dev/clk/starfive/jh7110_clk_stg.c standard
|
||||
dev/mmc/host/dwmmc_starfive.c optional dwmmc_starfive fdt
|
||||
|
||||
dev/eqos/if_eqos.c optional eqos
|
||||
dev/eqos/if_eqos_if.m optional eqos
|
||||
dev/eqos/if_eqos_starfive.c optional eqos
|
||||
|
||||
riscv/starfive/starfive_syscon.c standard
|
||||
|
|
|
|||
Loading…
Reference in a new issue