diff options
author | Weijie Gao | 2024-01-22 10:08:11 +0800 |
---|---|---|
committer | Tom Rini | 2024-03-01 16:35:52 -0500 |
commit | 85d1968e759f603e00f04412db75804a3307496a (patch) | |
tree | 5ab81952ed7259a3102d942b01ef32705a0fd7ea | |
parent | 3b51d5b76f86e484dd5a47f7617c2a5222d959de (diff) |
net: mediatek: add support for adjusting MDIO clock
User can assign a specific MDC speed to the eth node as follow:
ð {
...
phy-mode = "usxgmii";
phy-handle = <&phy8>;
mdio {
clock-frequency = <10500000>;
};
phy8: eth-phy@8 {
compatible = "ethernet-phy-id31c3.1c12";
...
};
Signed-off-by: Bo-Cun Chen <bc-bocun.chen@mediatek.com>
Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
-rw-r--r-- | drivers/net/mtk_eth.c | 35 | ||||
-rw-r--r-- | drivers/net/mtk_eth.h | 7 |
2 files changed, 42 insertions, 0 deletions
diff --git a/drivers/net/mtk_eth.c b/drivers/net/mtk_eth.c index 3cfce058451..726aedad3fa 100644 --- a/drivers/net/mtk_eth.c +++ b/drivers/net/mtk_eth.c @@ -137,6 +137,7 @@ struct mtk_eth_priv { int force_mode; int speed; int duplex; + int mdc; bool pn_swap; struct phy_device *phydev; @@ -1607,6 +1608,26 @@ static void mtk_eth_fifo_init(struct mtk_eth_priv *priv) mtk_pdma_write(priv, PDMA_RST_IDX_REG, RST_DTX_IDX0 | RST_DRX_IDX0); } +static void mtk_eth_mdc_init(struct mtk_eth_priv *priv) +{ + u32 divider; + + if (priv->mdc == 0) + return; + + divider = min_t(u32, DIV_ROUND_UP(MDC_MAX_FREQ, priv->mdc), MDC_MAX_DIVIDER); + + /* Configure MDC turbo mode */ + if (MTK_HAS_CAPS(priv->soc->caps, MTK_NETSYS_V3)) + mtk_gmac_rmw(priv, GMAC_MAC_MISC_REG, 0, MISC_MDC_TURBO); + else + mtk_gmac_rmw(priv, GMAC_PPSC_REG, 0, MISC_MDC_TURBO); + + /* Configure MDC divider */ + mtk_gmac_rmw(priv, GMAC_PPSC_REG, PHY_MDC_CFG, + FIELD_PREP(PHY_MDC_CFG, divider)); +} + static int mtk_eth_start(struct udevice *dev) { struct mtk_eth_priv *priv = dev_get_priv(dev); @@ -1803,6 +1824,9 @@ static int mtk_eth_probe(struct udevice *dev) noncached_alloc(priv->soc->rxd_size * NUM_RX_DESC, ARCH_DMA_MINALIGN); + /* Set MDC divider */ + mtk_eth_mdc_init(priv); + /* Set MAC mode */ if (priv->phy_interface == PHY_INTERFACE_MODE_USXGMII) mtk_xmac_init(priv); @@ -1881,6 +1905,17 @@ static int mtk_eth_of_to_plat(struct udevice *dev) priv->gmac_id = dev_read_u32_default(dev, "mediatek,gmac-id", 0); + priv->mdc = 0; + subnode = ofnode_find_subnode(dev_ofnode(dev), "mdio"); + if (ofnode_valid(subnode)) { + priv->mdc = ofnode_read_u32_default(subnode, "clock-frequency", 2500000); + if (priv->mdc > MDC_MAX_FREQ || + priv->mdc < MDC_MAX_FREQ / MDC_MAX_DIVIDER) { + printf("error: MDIO clock frequency out of range\n"); + return -EINVAL; + } + } + /* Interface mode is required */ pdata->phy_interface = dev_read_phy_mode(dev); priv->phy_interface = pdata->phy_interface; diff --git a/drivers/net/mtk_eth.h b/drivers/net/mtk_eth.h index 491cac56a81..45229c0f9a9 100644 --- a/drivers/net/mtk_eth.h +++ b/drivers/net/mtk_eth.h @@ -180,6 +180,12 @@ enum mkt_eth_capabilities { /* GMAC Registers */ +#define GMAC_PPSC_REG 0x0000 +#define PHY_MDC_CFG GENMASK(29, 24) +#define MDC_TURBO BIT(20) +#define MDC_MAX_FREQ 25000000 +#define MDC_MAX_DIVIDER 63 + #define GMAC_PIAC_REG 0x0004 #define PHY_ACS_ST BIT(31) #define MDIO_REG_ADDR_S 25 @@ -197,6 +203,7 @@ enum mkt_eth_capabilities { #define P1_XGMAC_FORCE_LINK BIT(15) #define GMAC_MAC_MISC_REG 0x0010 +#define MISC_MDC_TURBO BIT(4) #define GMAC_GSW_CFG_REG 0x0080 #define GSWTX_IPG_M 0xF0000 |