[U-Boot] [PATCH V2 7/9] mips: ath79: Add support for ungating ethernet on ar933x and ar934x

Marek Vasut marex at denx.de
Fri May 6 20:10:39 CEST 2016


Add code to ungate the ethernet controller on ar933x and ar934x .

Signed-off-by: Marek Vasut <marex at denx.de>
Cc: Daniel Schwierzeck <daniel.schwierzeck at gmail.com>
Cc: Wills Wang <wills.wang at live.com>
---
V2: Drop the map_physmem() return value check
---
 arch/mips/mach-ath79/include/mach/ar71xx_regs.h |  1 +
 arch/mips/mach-ath79/include/mach/ath79.h       |  1 +
 arch/mips/mach-ath79/reset.c                    | 78 +++++++++++++++++++++++++
 3 files changed, 80 insertions(+)

diff --git a/arch/mips/mach-ath79/include/mach/ar71xx_regs.h b/arch/mips/mach-ath79/include/mach/ar71xx_regs.h
index bff9d05..a9630c0 100644
--- a/arch/mips/mach-ath79/include/mach/ar71xx_regs.h
+++ b/arch/mips/mach-ath79/include/mach/ar71xx_regs.h
@@ -622,6 +622,7 @@
 #define AR933X_RESET_GE1_MAC				BIT(13)
 #define AR933X_RESET_WMAC				BIT(11)
 #define AR933X_RESET_GE0_MAC				BIT(9)
+#define AR933X_RESET_ETH_SWITCH				BIT(8)
 #define AR933X_RESET_USB_HOST				BIT(5)
 #define AR933X_RESET_USB_PHY				BIT(4)
 #define AR933X_RESET_USBSUS_OVERRIDE			BIT(3)
diff --git a/arch/mips/mach-ath79/include/mach/ath79.h b/arch/mips/mach-ath79/include/mach/ath79.h
index 682b6a2..2c6c118 100644
--- a/arch/mips/mach-ath79/include/mach/ath79.h
+++ b/arch/mips/mach-ath79/include/mach/ath79.h
@@ -140,6 +140,7 @@ static inline int soc_is_qca956x(void)
 	return soc_is_tp9343() || soc_is_qca9561();
 }
 
+int ath79_eth_reset(void);
 int ath79_usb_reset(void);
 
 #endif /* __ASM_MACH_ATH79_H */
diff --git a/arch/mips/mach-ath79/reset.c b/arch/mips/mach-ath79/reset.c
index 1538e32..188eccb 100644
--- a/arch/mips/mach-ath79/reset.c
+++ b/arch/mips/mach-ath79/reset.c
@@ -71,6 +71,84 @@ u32 get_bootstrap(void)
 	return 0;
 }
 
+static int eth_init_ar933x(void)
+{
+	void __iomem *rregs = map_physmem(AR71XX_RESET_BASE, AR71XX_RESET_SIZE,
+					  MAP_NOCACHE);
+	void __iomem *pregs = map_physmem(AR71XX_PLL_BASE, AR71XX_PLL_SIZE,
+					  MAP_NOCACHE);
+	void __iomem *gregs = map_physmem(AR933X_GMAC_BASE, AR933X_GMAC_SIZE,
+					  MAP_NOCACHE);
+	const u32 mask = AR933X_RESET_GE0_MAC | AR933X_RESET_GE0_MDIO |
+			 AR933X_RESET_GE1_MAC | AR933X_RESET_GE1_MDIO |
+			 AR933X_RESET_ETH_SWITCH;
+
+	/* Clear MDIO slave EN bit. */
+	clrbits_be32(rregs + AR933X_RESET_REG_BOOTSTRAP, BIT(17));
+	mdelay(10);
+
+	/* Get Atheros S26 PHY out of reset. */
+	clrsetbits_be32(pregs + AR934X_PLL_SWITCH_CLOCK_CONTROL_REG,
+			0x1f, 0x10);
+	mdelay(10);
+
+	setbits_be32(rregs + AR933X_RESET_REG_RESET_MODULE, mask);
+	mdelay(10);
+	clrbits_be32(rregs + AR933X_RESET_REG_RESET_MODULE, mask);
+	mdelay(10);
+
+	/* Configure AR93xx GMAC register. */
+	clrsetbits_be32(gregs + AR933X_GMAC_REG_ETH_CFG,
+			AR933X_ETH_CFG_MII_GE0_MASTER |
+			AR933X_ETH_CFG_MII_GE0_SLAVE,
+			AR933X_ETH_CFG_MII_GE0_SLAVE);
+	return 0;
+}
+
+static int eth_init_ar934x(void)
+{
+	void __iomem *rregs = map_physmem(AR71XX_RESET_BASE, AR71XX_RESET_SIZE,
+					  MAP_NOCACHE);
+	void __iomem *pregs = map_physmem(AR71XX_PLL_BASE, AR71XX_PLL_SIZE,
+					  MAP_NOCACHE);
+	void __iomem *gregs = map_physmem(AR934X_GMAC_BASE, AR934X_GMAC_SIZE,
+					  MAP_NOCACHE);
+	const u32 mask = AR934X_RESET_GE0_MAC | AR934X_RESET_GE0_MDIO |
+			 AR934X_RESET_GE1_MAC | AR934X_RESET_GE1_MDIO |
+			 AR934X_RESET_ETH_SWITCH_ANALOG;
+	u32 reg;
+
+	reg = readl(rregs + AR934X_RESET_REG_BOOTSTRAP);
+	if (reg & AR934X_BOOTSTRAP_REF_CLK_40)
+		writel(0x570, pregs + AR934X_PLL_SWITCH_CLOCK_CONTROL_REG);
+	else
+		writel(0x271, pregs + AR934X_PLL_SWITCH_CLOCK_CONTROL_REG);
+	writel(BIT(26) | BIT(25), pregs + AR934X_PLL_ETH_XMII_CONTROL_REG);
+
+	setbits_be32(rregs + AR934X_RESET_REG_RESET_MODULE, mask);
+	mdelay(1);
+	clrbits_be32(rregs + AR934X_RESET_REG_RESET_MODULE, mask);
+	mdelay(1);
+
+	/* Configure AR934x GMAC register. */
+	writel(AR934X_ETH_CFG_RGMII_GMAC0, gregs + AR934X_GMAC_REG_ETH_CFG);
+	return 0;
+}
+
+int ath79_eth_reset(void)
+{
+	/*
+	 * Un-reset ethernet. DM still doesn't have any notion of reset
+	 * framework, so we do it by hand here.
+	 */
+	if (soc_is_ar933x())
+		return eth_init_ar933x();
+	if (soc_is_ar934x())
+		return eth_init_ar934x();
+
+	return -EINVAL;
+}
+
 static int usb_reset_ar933x(void __iomem *reset_regs)
 {
 	/* Ungate the USB block */
-- 
2.7.0



More information about the U-Boot mailing list