net: designware: Add npcm8xx sgmii pcs support
authorJim Liu <jim.t90615@gmail.com>
Tue, 11 Feb 2025 02:02:01 +0000 (10:02 +0800)
committerTom Rini <trini@konsulko.com>
Tue, 18 Feb 2025 22:32:24 +0000 (16:32 -0600)
The PCS exists only in GMAC1 and relates to SGMII interface and
is used to control the SGMII PHY.

Signed-off-by: Jim Liu <JJLIU0@nuvoton.com>
[trini: Adjust slightly for white space and to move 'start' to within if
        block]

arch/arm/include/asm/arch-npcm8xx/gmac.h [new file with mode: 0644]
drivers/net/designware.c

diff --git a/arch/arm/include/asm/arch-npcm8xx/gmac.h b/arch/arm/include/asm/arch-npcm8xx/gmac.h
new file mode 100644 (file)
index 0000000..f84eedd
--- /dev/null
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
+#ifndef _NPCM_GMAC_H_
+#define _NPCM_GMAC_H_
+
+/* PCS registers */
+#define PCS_BA                 0xF0780000
+#define PCS_IND_AC             0x1FE
+#define SR_MII_MMD             0x3E0000
+#define SR_MII_MMD_CTRL                0x0
+#define SR_MII_MMD_STS         0x2
+#define VR_MII_MMD             0x3F0000
+#define VR_MII_MMD_CTRL1       0x0
+#define VR_MII_MMD_AN_CTRL     0x2
+
+#define LINK_UP_TIMEOUT                (3 * CONFIG_SYS_HZ)
+
+#endif
index 0a1fff3..2ab0301 100644 (file)
@@ -33,6 +33,9 @@
 #include <linux/printk.h>
 #include <power/regulator.h>
 #include "designware.h"
+#if IS_ENABLED(CONFIG_ARCH_NPCM8XX)
+#include <asm/arch/gmac.h>
+#endif
 
 static int dw_mdio_read(struct mii_dev *bus, int addr, int devad, int reg)
 {
@@ -352,10 +355,35 @@ static int dw_adjust_link(struct dw_eth_dev *priv, struct eth_mac_regs *mac_p,
               (phydev->port == PORT_FIBRE) ? ", fiber mode" : "");
 
 #ifdef CONFIG_ARCH_NPCM8XX
+       if (phydev->interface == PHY_INTERFACE_MODE_SGMII) {
+               unsigned int start;
+
+               /* Indirect access to VR_MII_MMD registers */
+               writew((VR_MII_MMD >> 9), PCS_BA + PCS_IND_AC);
+               /* Set PCS_Mode to SGMII */
+               clrsetbits_le16(PCS_BA + VR_MII_MMD_AN_CTRL, BIT(1), BIT(2));
+               /* Set Auto Speed Mode Change */
+               setbits_le16(PCS_BA + VR_MII_MMD_CTRL1, BIT(9));
+               /* Indirect access to SR_MII_MMD registers */
+               writew((SR_MII_MMD >> 9), PCS_BA + PCS_IND_AC);
+               /* Restart Auto-Negotiation */
+               setbits_le16(PCS_BA + SR_MII_MMD_CTRL, BIT(9) | BIT(12));
+
+               printf("SGMII PHY Wait for link up \n");
+               /* SGMII PHY Wait for link up */
+               start = get_timer(0);
+               while (!(readw(PCS_BA + SR_MII_MMD_STS) & BIT(2))) {
+                       if (get_timer(start) >= LINK_UP_TIMEOUT) {
+                               printf("PHY link up timeout\n");
+                               return -ETIMEDOUT;
+                       }
+                       mdelay(1);
+               };
+       }
        /* Pass all Multicast Frames */
        setbits_le32(&mac_p->framefilt, BIT(4));
-
 #endif
+
        return 0;
 }