[][kernel][common][eth][Add MDC divider support]
[Description]
Add MDC divider support.
User can specify MDC speed by adding mdc-max-frequency property
to the mdio nodes.
================================================================
mdio: mdio-bus {
#address-cells = <1>;
#size-cells = <0>;
mdc-max-frequency = <10500000>;
phy0: ethernet-phy@0 {
reg = <0>;
compatible = "ethernet-phy-ieee802.3-c45";
...
};
...
};
================================================================
Example: PHY device support 10.5MHz Maximum MDC clock.
User just need to declare this information in the DTS, driver will
find out a proper MDC divider(25MHz/3=8.33MHz) and setup
controller automatically.
If without this patch, MDC always running on 2.5MHz.
[Release-log]
N/A
Change-Id: If9171730373692243f02ceb9077bb496a774c8d0
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/6756759
diff --git a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c
index 080e53e..6015127 100755
--- a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -814,7 +814,9 @@
static int mtk_mdio_init(struct mtk_eth *eth)
{
struct device_node *mii_np;
+ int clk = 25000000, max_clk = 2500000, divider = 1;
int ret;
+ u32 val;
mii_np = of_get_child_by_name(eth->dev->of_node, "mdio-bus");
if (!mii_np) {
@@ -844,6 +846,36 @@
ret = -ENOMEM;
goto err_put_node;
}
+
+ if (!of_property_read_u32(mii_np, "mdc-max-frequency", &val))
+ max_clk = val;
+
+ while (clk / divider > max_clk) {
+ if (divider >= 63)
+ break;
+
+ divider++;
+ };
+
+ /* Configure MDC Turbo Mode */
+ if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V3)) {
+ val = mtk_r32(eth, MTK_MAC_MISC);
+ val |= MISC_MDC_TURBO;
+ mtk_w32(eth, val, MTK_MAC_MISC);
+ } else {
+ val = mtk_r32(eth, MTK_PPSC);
+ val |= PPSC_MDC_TURBO;
+ mtk_w32(eth, val, MTK_PPSC);
+ }
+
+ /* Configure MDC Divider */
+ val = mtk_r32(eth, MTK_PPSC);
+ val &= ~PPSC_MDC_CFG;
+ val |= FIELD_PREP(PPSC_MDC_CFG, divider);
+ mtk_w32(eth, val, MTK_PPSC);
+
+ dev_info(eth->dev, "MDC is running on %d Hz\n", clk / divider);
+
ret = of_mdiobus_register(eth->mii_bus, mii_np);
err_put_node:
diff --git a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.h b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.h
index a961042..d1e1d65 100755
--- a/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+++ b/target/linux/mediatek/files-5.4/drivers/net/ethernet/mediatek/mtk_eth_soc.h
@@ -602,6 +602,11 @@
#define RX_DMA_GET_AGG_CNT_V2(_x) (((_x) >> 16) & 0xff)
#define RX_DMA_GET_TOPS_CRSN(_x) (((_x) >> 24) & 0xff)
+/* PHY Polling and SMI Master Control registers */
+#define MTK_PPSC 0x10000
+#define PPSC_MDC_CFG GENMASK(29, 24)
+#define PPSC_MDC_TURBO BIT(20)
+
/* PHY Indirect Access Control registers */
#define MTK_PHY_IAC 0x10004
#define PHY_IAC_ACCESS BIT(31)
@@ -615,7 +620,12 @@
#define PHY_IAC_REG_SHIFT 25
#define PHY_IAC_TIMEOUT HZ
+#if defined(CONFIG_MEDIATEK_NETSYS_V3)
+#define MTK_MAC_MISC 0x10010
+#else
#define MTK_MAC_MISC 0x1000c
+#endif
+#define MISC_MDC_TURBO BIT(4)
#define MTK_MUX_TO_ESW BIT(0)
/* XMAC status registers */