Page MenuHomeFreeBSD

D45600.1777698975.diff
No OneTemporary

Size
22 KB
Referenced Files
None
Subscribers
None

D45600.1777698975.diff

diff --git a/sys/dev/eqos/if_eqos.c b/sys/dev/eqos/if_eqos.c
--- a/sys/dev/eqos/if_eqos.c
+++ b/sys/dev/eqos/if_eqos.c
@@ -26,7 +26,6 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: eqos.c 1059 2022-12-08 19:32:32Z sos $
*/
/*
@@ -80,7 +79,7 @@
#define TX_DESC_COUNT EQOS_DMA_DESC_COUNT
#define TX_DESC_SIZE (TX_DESC_COUNT * DESC_ALIGN)
#define TX_MAX_SEGS (TX_DESC_COUNT / 2)
-#define TX_NEXT(n) (((n) + 1 ) % TX_DESC_COUNT)
+#define TX_NEXT(n) (((n) + 1) % TX_DESC_COUNT)
#define TX_QUEUED(h, t) ((((h) - (t)) + TX_DESC_COUNT) % TX_DESC_COUNT)
#define RX_DESC_COUNT EQOS_DMA_DESC_COUNT
@@ -195,7 +194,7 @@
reg |= GMAC_MAC_CONFIGURATION_FES;
break;
case IFM_1000_T:
- case IFM_1000_SX:
+ case IFM_1000_SX:
reg &= ~GMAC_MAC_CONFIGURATION_PS;
reg &= ~GMAC_MAC_CONFIGURATION_FES;
break;
@@ -241,7 +240,7 @@
int error;
EQOS_LOCK(sc);
- error = mii_mediachg(device_get_softc(sc->miibus));
+ error = mii_mediachg(device_get_softc(sc->miibus));
EQOS_UNLOCK(sc);
return (error);
}
@@ -456,7 +455,7 @@
int retry;
WR4(sc, GMAC_DMA_MODE, GMAC_DMA_MODE_SWR);
- for (retry = 2000; retry > 0; retry--) {
+ for (retry = 10000; retry > 0; retry--) {
DELAY(1000);
val = RD4(sc, GMAC_DMA_MODE);
if (!(val & GMAC_DMA_MODE_SWR))
@@ -491,7 +490,7 @@
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 +507,18 @@
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 +531,19 @@
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);
@@ -578,7 +590,7 @@
if (!sc->link_up)
return;
- if ((if_getdrvflags(ifp) & (IFF_DRV_RUNNING|IFF_DRV_OACTIVE)) !=
+ if ((if_getdrvflags(ifp) & (IFF_DRV_RUNNING | IFF_DRV_OACTIVE)) !=
IFF_DRV_RUNNING)
return;
@@ -713,8 +725,7 @@
if ((m = eqos_alloc_mbufcl(sc))) {
if ((error = eqos_setup_rxbuf(sc, sc->rx.head, m)))
printf("ERROR: Hole in RX ring!!\n");
- }
- else
+ } else
if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
if_inc_counter(ifp, IFCOUNTER_IPACKETS, 1);
@@ -878,17 +889,14 @@
if (if_getflags(ifp) & IFF_UP) {
if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) {
flags = if_getflags(ifp);
- if ((flags & (IFF_PROMISC|IFF_ALLMULTI))) {
+ if ((flags & (IFF_PROMISC | IFF_ALLMULTI))) {
EQOS_LOCK(sc);
eqos_setup_rxfilter(sc);
EQOS_UNLOCK(sc);
}
- }
- else {
+ } else
eqos_init(sc);
- }
- }
- else {
+ } else {
if (if_getdrvflags(ifp) & IFF_DRV_RUNNING)
eqos_stop(sc);
}
@@ -1006,7 +1014,7 @@
}
if ((error = bus_dmamem_alloc(sc->tx.desc_tag,
- (void**)&sc->tx.desc_ring,
+ (void **)&sc->tx.desc_ring,
BUS_DMA_COHERENT | BUS_DMA_WAITOK | BUS_DMA_ZERO,
&sc->tx.desc_map))) {
device_printf(sc->dev,
@@ -1025,7 +1033,7 @@
if ((error = bus_dma_tag_create(bus_get_dma_tag(sc->dev), 1, 0,
BUS_SPACE_MAXADDR_32BIT,
BUS_SPACE_MAXADDR, NULL, NULL,
- MCLBYTES*TX_MAX_SEGS, TX_MAX_SEGS,
+ MCLBYTES * TX_MAX_SEGS, TX_MAX_SEGS,
MCLBYTES, 0, NULL, NULL,
&sc->tx.buf_tag))) {
device_printf(sc->dev, "could not create TX buffer DMA tag.\n");
@@ -1112,6 +1120,14 @@
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");
@@ -1123,14 +1139,15 @@
return (error);
sc->dev = dev;
- ver = RD4(sc, GMAC_MAC_VERSION);
+
+ ver = RD4(sc, GMAC_MAC_VERSION);
userver = (ver & GMAC_MAC_VERSION_USERVER_MASK) >>
GMAC_MAC_VERSION_USERVER_SHIFT;
snpsver = ver & GMAC_MAC_VERSION_SNPSVER_MASK;
- if (snpsver != 0x51) {
- device_printf(dev, "EQOS version 0x%02x not supported\n",
- snpsver);
+ if (snpsver != 0x51 && snpsver != 0x52) {
+ device_printf(dev,
+ "EQOS version 0x%02x not supported\n", snpsver);
return (ENXIO);
}
diff --git a/sys/dev/eqos/if_eqos_reg.h b/sys/dev/eqos/if_eqos_reg.h
--- a/sys/dev/eqos/if_eqos_reg.h
+++ b/sys/dev/eqos/if_eqos_reg.h
@@ -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)
diff --git a/sys/dev/eqos/if_eqos_var.h b/sys/dev/eqos/if_eqos_var.h
--- a/sys/dev/eqos/if_eqos_var.h
+++ b/sys/dev/eqos/if_eqos_var.h
@@ -85,6 +85,13 @@
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;
@@ -94,6 +101,8 @@
struct eqos_ring rx;
};
+int eqos_phy_reset(device_t dev);
+
DECLARE_CLASS(eqos_driver);
#endif
diff --git a/sys/dev/mii/mcommphy.c b/sys/dev/mii/mcommphy.c
--- a/sys/dev/mii/mcommphy.c
+++ b/sys/dev/mii/mcommphy.c
@@ -1,6 +1,7 @@
/*
* Copyright (c) 2022 Jared McNeill <jmcneill@invisible.ca>
* Copyright (c) 2022 Soren Schmidt <sos@deepcore.dk>
+ * Copyright (c) 2024 Jari Sihvola <jsihv@gmx.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -26,7 +27,8 @@
*/
/*
- * Motorcomm YT8511C / YT8511H Integrated 10/100/1000 Gigabit Ethernet phy
+ * Motorcomm YT8511C/YT8511H/YT8531
+ * Integrated 10/100/1000 Gigabit Ethernet phy
*/
#include <sys/param.h>
@@ -42,12 +44,16 @@
#include <dev/mii/mii.h>
#include <dev/mii/miivar.h>
+#include <dev/mii/mii_fdt.h>
+#include "miidevs.h"
#include "miibus_if.h"
-#define MCOMMPHY_OUI 0x000000
-#define MCOMMPHY_MODEL 0x10
-#define MCOMMPHY_REV 0x0a
+#define MCOMMPHY_YT8511_OUI 0x000000
+#define MCOMMPHY_YT8511_MODEL 0x10
+#define MCOMMPHY_YT8511_REV 0x0a
+
+#define MCOMMPHY_YT8531_MODEL 0x11
#define EXT_REG_ADDR 0x1e
#define EXT_REG_DATA 0x1f
@@ -61,9 +67,49 @@
#define PHY_SLEEP_CONTROL1_REG 0x27
#define PLLON_IN_SLP 0x4000
+/* Registers and values for YT8531 */
+#define YT8531_CHIP_CONFIG 0xa001
+#define RXC_DLY_EN (1 << 8)
+
+#define YT8531_PAD_DRSTR_CFG 0xa010
+#define PAD_RXC_MASK 0x7
+#define PAD_RXC_SHIFT 13
+#define JH7110_RGMII_RXC_STRENGTH 6
+
+#define YT8531_RGMII_CONFIG1 0xa003
+#define RX_DELAY_SEL_SHIFT 10
+#define RX_DELAY_SEL_MASK 0xf
+#define RXC_DLY_THRESH 2250
+#define RXC_DLY_ADDON 1900
+#define TX_DELAY_SEL_FE_MASK 0xf
+#define TX_DELAY_SEL_FE_SHIFT 4
+#define TX_DELAY_SEL_MASK 0xf
+#define TX_DELAY_SEL_SHIFT 0
+#define TX_CLK_SEL (1 << 14)
+#define INTERNAL_DLY_DIV 150
+
+#define YT8531_SYNCE_CFG 0xa012
+#define EN_SYNC_E (1 << 6)
+
#define LOWEST_SET_BIT(mask) ((((mask) - 1) & (mask)) ^ (mask))
#define SHIFTIN(x, mask) ((x) * LOWEST_SET_BIT(mask))
+static const struct mii_phydesc mcommphys[] = {
+ MII_PHY_DESC(MOTORCOMM, YT8511),
+ MII_PHY_DESC(MOTORCOMM2, YT8531),
+ MII_PHY_END
+};
+
+struct mcommphy_softc {
+ mii_softc_t mii_sc;
+ device_t dev;
+ bool tx_10_inv;
+ bool tx_100_inv;
+ bool tx_1000_inv;
+};
+
+static void mcommphy_yt8531_speed_adjustment(struct mii_softc *sc);
+
static int
mcommphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
{
@@ -79,11 +125,22 @@
if (mii_phy_tick(sc) == EJUSTRETURN)
return (0);
break;
+
}
/* Update the media status. */
PHY_STATUS(sc);
+ /*
+ * For the needs of JH7110 which has two Ethernet devices with
+ * different TX inverted configuration depending on speed used
+ */
+ if (sc->mii_mpd_model == MCOMMPHY_YT8531_MODEL &&
+ sc->mii_media_active != mii->mii_media_active &&
+ sc->mii_media_status != mii->mii_media_status) {
+ mcommphy_yt8531_speed_adjustment(sc);
+ }
+
/* Callback if something changed. */
mii_phy_update(sc, cmd);
@@ -105,26 +162,22 @@
* The YT8511C reports an OUI of 0. Best we can do here is to match
* exactly the contents of the PHY identification registers.
*/
- if (MII_OUI(ma->mii_id1, ma->mii_id2) == MCOMMPHY_OUI &&
- MII_MODEL(ma->mii_id2) == MCOMMPHY_MODEL &&
- MII_REV(ma->mii_id2) == MCOMMPHY_REV) {
+ if (MII_OUI(ma->mii_id1, ma->mii_id2) == MCOMMPHY_YT8511_OUI &&
+ MII_MODEL(ma->mii_id2) == MCOMMPHY_YT8511_MODEL &&
+ MII_REV(ma->mii_id2) == MCOMMPHY_YT8511_REV) {
device_set_desc(dev, "Motorcomm YT8511 media interface");
- return BUS_PROBE_DEFAULT;
+ return (BUS_PROBE_DEFAULT);
}
- return (ENXIO);
+
+ /* YT8531 follows a conventional procedure */
+ return (mii_phy_dev_probe(dev, mcommphys, BUS_PROBE_DEFAULT));
}
-static int
-mcommphy_attach(device_t dev)
+static void
+mcommphy_yt8511_setup(struct mii_softc *sc)
{
- struct mii_softc *sc = device_get_softc(dev);
uint16_t oldaddr, data;
- mii_phy_dev_attach(dev, MIIF_NOMANPAUSE, &mcommphy_funcs, 0);
-
- PHY_RESET(sc);
-
- /* begin chip stuff */
oldaddr = PHY_READ(sc, EXT_REG_ADDR);
PHY_WRITE(sc, EXT_REG_ADDR, PHY_CLOCK_GATING_REG);
@@ -150,21 +203,187 @@
PHY_WRITE(sc, EXT_REG_DATA, data);
PHY_WRITE(sc, EXT_REG_ADDR, oldaddr);
- /* end chip stuff */
+}
+
+static void
+mcommphy_yt8531_speed_adjustment(struct mii_softc *sc)
+{
+ struct mcommphy_softc *mcomm_sc = (struct mcommphy_softc *)sc;
+ struct mii_data *mii = sc->mii_pdata;
+ bool tx_clk_inv = false;
+ uint16_t reg, oldaddr;
+
+ /*
+ * Due to conflict between Callout API's lock and waiting malloc in
+ * mii_fdt_get_config() the device tree cannot be read here and its
+ * data is stored beforehand
+ */
+
+ if ((mii->mii_media_active & IFM_1000_T) != 0 &&
+ mcomm_sc->tx_1000_inv == true)
+ tx_clk_inv = true;
+ else if ((mii->mii_media_active & IFM_100_TX) != 0 &&
+ mcomm_sc->tx_100_inv == true)
+ tx_clk_inv = true;
+ else if ((mii->mii_media_active & IFM_10_T) != 0 &&
+ mcomm_sc->tx_10_inv == true)
+ tx_clk_inv = true;
+
+ oldaddr = PHY_READ(sc, EXT_REG_ADDR);
+
+ PHY_WRITE(sc, EXT_REG_ADDR, YT8531_RGMII_CONFIG1);
+ reg = PHY_READ(sc, EXT_REG_DATA);
+ if (tx_clk_inv == true)
+ reg |= TX_CLK_SEL;
+ else
+ reg &= ~TX_CLK_SEL;
+ PHY_WRITE(sc, EXT_REG_DATA, reg);
+
+ PHY_WRITE(sc, EXT_REG_ADDR, oldaddr);
+
+ return;
+}
+
+static int
+mcommphy_yt8531_setup_delay(struct mii_softc *sc)
+{
+ struct mcommphy_softc *mcomm_sc = (struct mcommphy_softc *)sc;
+ mii_fdt_phy_config_t *cfg = mii_fdt_get_config(mcomm_sc->dev);
+ pcell_t val;
+ uint16_t reg, oldaddr;
+ int rx_delay, tx_delay = 0;
+ bool rxc_dly_en_off = false;
+
+ if (OF_getencprop(cfg->phynode, "rx-internal-delay-ps", &val,
+ sizeof(val)) > 0) {
+ if (val <= RXC_DLY_THRESH && val % INTERNAL_DLY_DIV == 0) {
+ rx_delay = val / INTERNAL_DLY_DIV;
+ rxc_dly_en_off = true;
+ } else {
+ rx_delay = (val - RXC_DLY_ADDON) / INTERNAL_DLY_DIV;
+ if ((val - RXC_DLY_ADDON) % INTERNAL_DLY_DIV != 0)
+ return (ENXIO);
+ }
+ }
+
+ if (OF_getencprop(cfg->phynode, "tx-internal-delay-ps", &val,
+ sizeof(val)) > 0) {
+ tx_delay = val / INTERNAL_DLY_DIV;
+ if (val % INTERNAL_DLY_DIV != 0)
+ return (ENXIO);
+ }
+
+ mii_fdt_free_config(cfg);
+
+ oldaddr = PHY_READ(sc, EXT_REG_ADDR);
+
+ /* Modifying Chip Config register */
+ PHY_WRITE(sc, EXT_REG_ADDR, YT8531_CHIP_CONFIG);
+ reg = PHY_READ(sc, EXT_REG_DATA);
+ if (rxc_dly_en_off == true)
+ reg &= ~(RXC_DLY_EN);
+ PHY_WRITE(sc, EXT_REG_DATA, reg);
+
+ /* Modifying RGMII Config1 register */
+ PHY_WRITE(sc, EXT_REG_ADDR, YT8531_RGMII_CONFIG1);
+ reg = PHY_READ(sc, EXT_REG_DATA);
+ reg &= ~(RX_DELAY_SEL_MASK << RX_DELAY_SEL_SHIFT);
+ reg |= rx_delay << RX_DELAY_SEL_SHIFT;
+ reg &= ~(TX_DELAY_SEL_MASK << TX_DELAY_SEL_SHIFT);
+ reg |= tx_delay << TX_DELAY_SEL_SHIFT;
+ PHY_WRITE(sc, EXT_REG_DATA, reg);
+
+ PHY_WRITE(sc, EXT_REG_ADDR, oldaddr);
+
+ return (0);
+}
+
+static int
+mcommphy_yt8531_setup(struct mii_softc *sc)
+{
+ struct mcommphy_softc *mcomm_sc = (struct mcommphy_softc *)sc;
+ mii_fdt_phy_config_t *cfg = mii_fdt_get_config(mcomm_sc->dev);
+ uint16_t reg, oldaddr;
+
+ if (OF_hasprop(cfg->phynode, "motorcomm,tx-clk-10-inverted"))
+ mcomm_sc->tx_10_inv = true;
+ else
+ mcomm_sc->tx_10_inv = false;
+
+ if (OF_hasprop(cfg->phynode, "motorcomm,tx-clk-100-inverted"))
+ mcomm_sc->tx_100_inv = true;
+ else
+ mcomm_sc->tx_100_inv = false;
+
+ if (OF_hasprop(cfg->phynode, "motorcomm,tx-clk-1000-inverted"))
+ mcomm_sc->tx_1000_inv = true;
+ else
+ mcomm_sc->tx_1000_inv = false;
+
+ mii_fdt_free_config(cfg);
+
+ oldaddr = PHY_READ(sc, EXT_REG_ADDR);
+
+ /* Modifying Pad Drive Strength register */
+ PHY_WRITE(sc, EXT_REG_ADDR, YT8531_PAD_DRSTR_CFG);
+ reg = PHY_READ(sc, EXT_REG_DATA);
+ reg &= ~(PAD_RXC_MASK << PAD_RXC_SHIFT);
+ reg |= (JH7110_RGMII_RXC_STRENGTH << PAD_RXC_SHIFT);
+ PHY_WRITE(sc, EXT_REG_DATA, reg);
+
+ /* Modifying SyncE Config register */
+ PHY_WRITE(sc, EXT_REG_ADDR, YT8531_SYNCE_CFG);
+ reg = PHY_READ(sc, EXT_REG_DATA);
+ reg &= ~(EN_SYNC_E);
+ PHY_WRITE(sc, EXT_REG_DATA, reg);
+
+ PHY_WRITE(sc, EXT_REG_ADDR, oldaddr);
+
+ if (mcommphy_yt8531_setup_delay(sc) != 0)
+ return (ENXIO);
+
+ return (0);
+}
- sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & sc->mii_capmask;
- if (sc->mii_capabilities & BMSR_EXTSTAT)
- sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR);
+static int
+mcommphy_attach(device_t dev)
+{
+ struct mcommphy_softc *mcomm_sc = device_get_softc(dev);
+ mii_softc_t *mii_sc = &mcomm_sc->mii_sc;
+ int ret = 0;
+
+ mcomm_sc->dev = dev;
+
+ mii_phy_dev_attach(dev, MIIF_NOMANPAUSE, &mcommphy_funcs, 0);
+
+ PHY_RESET(mii_sc);
+
+ if (mii_sc->mii_mpd_model == MCOMMPHY_YT8511_MODEL)
+ mcommphy_yt8511_setup(mii_sc);
+ else if (mii_sc->mii_mpd_model == MCOMMPHY_YT8531_MODEL)
+ ret = mcommphy_yt8531_setup(mii_sc);
+ else {
+ device_printf(dev, "no PHY model detected\n");
+ return (ENXIO);
+ }
+ if (ret) {
+ device_printf(dev, "PHY setup failed, error: %d\n", ret);
+ return (ret);
+ }
+
+ mii_sc->mii_capabilities = PHY_READ(mii_sc, MII_BMSR) &
+ mii_sc->mii_capmask;
+ if (mii_sc->mii_capabilities & BMSR_EXTSTAT)
+ mii_sc->mii_extcapabilities = PHY_READ(mii_sc, MII_EXTSR);
device_printf(dev, " ");
- mii_phy_add_media(sc);
+ mii_phy_add_media(mii_sc);
printf("\n");
- MIIBUS_MEDIAINIT(sc->mii_dev);
+ MIIBUS_MEDIAINIT(mii_sc->mii_dev);
return (0);
}
-
static device_method_t mcommphy_methods[] = {
/* device interface */
DEVMETHOD(device_probe, mcommphy_probe),
@@ -177,7 +396,7 @@
static driver_t mcommphy_driver = {
"mcommphy",
mcommphy_methods,
- sizeof(struct mii_softc)
+ sizeof(struct mcommphy_softc)
};
DRIVER_MODULE(mcommphy, miibus, mcommphy_driver, 0, 0);
diff --git a/sys/dev/mii/miidevs b/sys/dev/mii/miidevs
--- a/sys/dev/mii/miidevs
+++ b/sys/dev/mii/miidevs
@@ -63,6 +63,7 @@
oui MARVELL 0x005043 Marvell Semiconductor
oui MICREL 0x0010a1 Micrel
oui MOTORCOMM 0x000000 Motorcomm
+oui MOTORCOMM2 0xc82b5e Motorcomm
oui MYSON 0x00c0b4 Myson Technology
oui NATSEMI 0x080017 National Semiconductor
oui PMCSIERRA 0x00e004 PMC-Sierra
@@ -295,6 +296,7 @@
/* Motorcomm PHYs */
model MOTORCOMM YT8511 0x010a Motorcomm YT8511 10/100/1000 PHY
+model MOTORCOMM2 YT8531 0x0011 Motorcomm YT8531 10/100/1000 PHY
/* Myson Technology PHYs */
model xxMYSON MTD972 0x0000 MTD972 10/100 media interface
diff --git a/sys/riscv/starfive/starfive_if_eqos.c b/sys/riscv/starfive/starfive_if_eqos.c
new file mode 100644
--- /dev/null
+++ b/sys/riscv/starfive/starfive_if_eqos.c
@@ -0,0 +1,220 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2021 Mitchell Horne <mhorne@FreeBSD.org>
+ * 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);

File Metadata

Mime Type
text/plain
Expires
Sat, May 2, 5:16 AM (10 h, 10 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28536794
Default Alt Text
D45600.1777698975.diff (22 KB)

Event Timeline