Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F145351051
D45600.1777698975.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
22 KB
Referenced Files
None
Subscribers
None
D45600.1777698975.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D45600: Add StarFive JH7110's Ethernet (eqos & mcommphy modifications, a new board specific file)
Attached
Detach File
Event Timeline
Log In to Comment