diff options
author | Weijie Gao <weijie.gao@mediatek.com> | 2024-01-22 10:08:11 +0800 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2024-03-01 16:35:52 -0500 |
commit | 85d1968e759f603e00f04412db75804a3307496a (patch) | |
tree | 5ab81952ed7259a3102d942b01ef32705a0fd7ea /drivers/net/mtk_eth.c | |
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>
Diffstat (limited to 'drivers/net/mtk_eth.c')
-rw-r--r-- | drivers/net/mtk_eth.c | 35 |
1 files changed, 35 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; |