The PCS exists only in GMAC1 and relates to SGMII interface and is used to control the SGMII PHY.
Signed-off-by: Jim Liu <jjl...@nuvoton.com> --- arch/arm/include/asm/arch-npcm8xx/gmac.h | 18 ++++++++++++++++ drivers/net/designware.c | 27 ++++++++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 arch/arm/include/asm/arch-npcm8xx/gmac.h diff --git a/arch/arm/include/asm/arch-npcm8xx/gmac.h b/arch/arm/include/asm/arch-npcm8xx/gmac.h new file mode 100644 index 00000000000..f84eedddc22 --- /dev/null +++ b/arch/arm/include/asm/arch-npcm8xx/gmac.h @@ -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 diff --git a/drivers/net/designware.c b/drivers/net/designware.c index 0a1fff38727..771c1672ae9 100644 --- a/drivers/net/designware.c +++ b/drivers/net/designware.c @@ -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) { @@ -328,6 +331,7 @@ static int dw_adjust_link(struct dw_eth_dev *priv, struct eth_mac_regs *mac_p, struct phy_device *phydev) { u32 conf = readl(&mac_p->conf) | FRAMEBURSTENABLE | DISABLERXOWN; + unsigned int start; if (!phydev->link) { printf("%s: No link.\n", phydev->dev->name); @@ -352,6 +356,29 @@ 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) { + /* 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)); -- 2.34.1