From 2d081addb537ac3dc41d61487561458c7733c7ba Mon Sep 17 00:00:00 2001
From: Chuanhong Guo <gch981213@gmail.com>
Date: Tue, 17 Jul 2018 17:09:13 +0800
Subject: [PATCH] ath79: ag71xx: Split gmac config into separated file and add
 support for ar934x/qca955x.

Signed-off-by: Chuanhong Guo <gch981213@gmail.com>
---
 target/linux/ath79/dts/qca9557.dtsi           |   5 +
 .../net/ethernet/atheros/ag71xx/Makefile      |   1 +
 .../net/ethernet/atheros/ag71xx/ag71xx.h      |   2 +
 .../net/ethernet/atheros/ag71xx/ag71xx_gmac.c | 113 ++++++++++++++++++
 .../net/ethernet/atheros/ag71xx/ag71xx_main.c |  58 ---------
 5 files changed, 121 insertions(+), 58 deletions(-)
 create mode 100644 target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_gmac.c

diff --git a/target/linux/ath79/dts/qca9557.dtsi b/target/linux/ath79/dts/qca9557.dtsi
index 802f2da725..980629c939 100644
--- a/target/linux/ath79/dts/qca9557.dtsi
+++ b/target/linux/ath79/dts/qca9557.dtsi
@@ -220,6 +220,11 @@
 				status = "disabled";
 			};
 
+			gmac: gmac@18070000 {
+				compatible = "qca,qca9550-gmac";
+				reg = <0x18070000 0x14>;
+			};
+
 			wmac: wmac@18100000 {
 				compatible = "qca,qca9550-wmac";
 				reg = <0x18100000 0x10000>;
diff --git a/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/Makefile b/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/Makefile
index 7f396ad46e..ed74e3b5e6 100644
--- a/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/Makefile
+++ b/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/Makefile
@@ -3,6 +3,7 @@
 #
 
 ag71xx-y	+= ag71xx_main.o
+ag71xx-y	+= ag71xx_gmac.o
 ag71xx-y	+= ag71xx_ethtool.o
 ag71xx-y	+= ag71xx_phy.o
 ag71xx-y	+= ag71xx_mdio.o
diff --git a/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx.h b/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx.h
index 22b22522a3..b0780a1ba9 100644
--- a/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx.h
+++ b/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx.h
@@ -447,6 +447,8 @@ void ag71xx_mdio_cleanup(struct ag71xx *ag);
 int ag71xx_mdio_mii_read(struct mii_bus *bus, int addr, int reg);
 int ag71xx_mdio_mii_write(struct mii_bus *bus, int addr, int reg, u16 val);
 
+int ag71xx_setup_gmac(struct device_node *np);
+
 int ar7240sw_phy_read(struct mii_bus *mii, int addr, int reg);
 int ar7240sw_phy_write(struct mii_bus *mii, int addr, int reg, u16 val);
 
diff --git a/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_gmac.c b/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_gmac.c
new file mode 100644
index 0000000000..55a8f57f15
--- /dev/null
+++ b/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_gmac.c
@@ -0,0 +1,113 @@
+/*
+ *  Atheros AR71xx built-in ethernet mac driver
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License version 2 as published
+ *  by the Free Software Foundation.
+ */
+
+#include <linux/sizes.h>
+#include <linux/of_address.h>
+#include "ag71xx.h"
+
+static void ag71xx_of_set(struct device_node *np, const char *prop,
+			  u32 *reg, u32 shift, u32 mask)
+{
+	u32 val;
+
+	if (of_property_read_u32(np, prop, &val))
+		return;
+
+	*reg &= ~(mask << shift);
+	*reg |= ((val & mask) << shift);
+}
+
+static void ag71xx_of_bit(struct device_node *np, const char *prop,
+			  u32 *reg, u32 mask)
+{
+	u32 val;
+
+	if (of_property_read_u32(np, prop, &val))
+		return;
+
+	if (val)
+		*reg |= mask;
+	else
+		*reg &= ~mask;
+}
+
+static void ag71xx_setup_gmac_933x(struct device_node *np, void __iomem *base)
+{
+	u32 val = __raw_readl(base + AR933X_GMAC_REG_ETH_CFG);
+
+	ag71xx_of_bit(np, "switch-phy-swap", &val, AR933X_ETH_CFG_SW_PHY_SWAP);
+	ag71xx_of_bit(np, "switch-phy-addr-swap", &val,
+		AR933X_ETH_CFG_SW_PHY_ADDR_SWAP);
+
+	__raw_writel(val, base + AR933X_GMAC_REG_ETH_CFG);
+}
+
+static void ag71xx_setup_gmac_934x(struct device_node *np, void __iomem *base)
+{
+	u32 val = __raw_readl(base + AR934X_GMAC_REG_ETH_CFG);
+
+	ag71xx_of_bit(np, "rgmii-gmac0", &val, AR934X_ETH_CFG_RGMII_GMAC0);
+	ag71xx_of_bit(np, "mii-gmac0", &val, AR934X_ETH_CFG_MII_GMAC0);
+	ag71xx_of_bit(np, "gmii-gmac0", &val, AR934X_ETH_CFG_GMII_GMAC0);
+	ag71xx_of_bit(np, "switch-phy-swap", &val, AR934X_ETH_CFG_SW_PHY_SWAP);
+	ag71xx_of_bit(np, "switch-only-mode", &val,
+		AR934X_ETH_CFG_SW_ONLY_MODE);
+
+	__raw_writel(val, base + AR934X_GMAC_REG_ETH_CFG);
+}
+
+static void ag71xx_setup_gmac_955x(struct device_node *np, void __iomem *base)
+{
+	u32 val = __raw_readl(base + QCA955X_GMAC_REG_ETH_CFG);
+
+	ag71xx_of_bit(np, "rgmii-enabled", &val, QCA955X_ETH_CFG_RGMII_EN);
+	ag71xx_of_bit(np, "ge0-sgmii", &val, QCA955X_ETH_CFG_GE0_SGMII);
+	ag71xx_of_set(np, "txen-delay", &val, QCA955X_ETH_CFG_TXE_DELAY_SHIFT, 0x3);
+	ag71xx_of_set(np, "txd-delay", &val, QCA955X_ETH_CFG_TXD_DELAY_SHIFT, 0x3);
+	ag71xx_of_set(np, "rxdv-delay", &val, QCA955X_ETH_CFG_RDV_DELAY_SHIFT, 0x3);
+	ag71xx_of_set(np, "rxd-delay", &val, QCA955X_ETH_CFG_RXD_DELAY_SHIFT, 0x3);
+
+	__raw_writel(val, base + QCA955X_GMAC_REG_ETH_CFG);
+}
+
+int ag71xx_setup_gmac(struct device_node *np)
+{
+	struct device_node *np_dev;
+	void __iomem *base;
+	int err = 0;
+
+	np = of_get_child_by_name(np, "gmac-config");
+	if (!np)
+		return 0;
+
+	np_dev = of_parse_phandle(np, "device", 0);
+	if (!np_dev)
+		goto out;
+
+	base = of_iomap(np_dev, 0);
+	if (!base) {
+		pr_err("%pOF: can't map GMAC registers\n", np_dev);
+		err = -ENOMEM;
+		goto err_iomap;
+	}
+
+	if (of_device_is_compatible(np_dev, "qca,ar9330-gmac"))
+		ag71xx_setup_gmac_933x(np, base);
+	else if (of_device_is_compatible(np_dev, "qca,ar9340-gmac"))
+		ag71xx_setup_gmac_934x(np, base);
+	else if (of_device_is_compatible(np_dev, "qca,qca9550-gmac"))
+		ag71xx_setup_gmac_955x(np, base);
+
+	iounmap(base);
+
+err_iomap:
+	of_node_put(np_dev);
+out:
+	of_node_put(np);
+	return err;
+}
diff --git a/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c b/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c
index 635c3b9127..acc0f089d0 100644
--- a/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c
+++ b/target/linux/ath79/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_main.c
@@ -1271,64 +1271,6 @@ static const char *ag71xx_get_phy_if_mode_name(phy_interface_t mode)
 	return "unknown";
 }
 
-static void ag71xx_of_bit(struct device_node *np, const char *prop,
-			  u32 *reg, u32 mask)
-{
-	u32 val;
-
-	if (of_property_read_u32(np, prop, &val))
-		return;
-
-	if (val)
-		*reg |= mask;
-	else
-		*reg &= ~mask;
-}
-
-static void ag71xx_setup_gmac_933x(struct device_node *np, void __iomem *base)
-{
-	u32 val = __raw_readl(base + AR933X_GMAC_REG_ETH_CFG);
-
-	ag71xx_of_bit(np, "switch-phy-swap", &val, AR933X_ETH_CFG_SW_PHY_SWAP);
-	ag71xx_of_bit(np, "switch-phy-addr-swap", &val,
-		      AR933X_ETH_CFG_SW_PHY_ADDR_SWAP);
-
-	__raw_writel(val, base + AR933X_GMAC_REG_ETH_CFG);
-}
-
-static int ag71xx_setup_gmac(struct device_node *np)
-{
-	struct device_node *np_dev;
-	void __iomem *base;
-	int err = 0;
-
-	np = of_get_child_by_name(np, "gmac-config");
-	if (!np)
-		return 0;
-
-	np_dev = of_parse_phandle(np, "device", 0);
-	if (!np_dev)
-		goto out;
-
-	base = of_iomap(np_dev, 0);
-	if (!base) {
-		pr_err("%pOF: can't map GMAC registers\n", np_dev);
-		err = -ENOMEM;
-		goto err_iomap;
-	}
-
-	if (of_device_is_compatible(np_dev, "qca,ar9330-gmac"))
-		ag71xx_setup_gmac_933x(np, base);
-
-	iounmap(base);
-
-err_iomap:
-	of_node_put(np_dev);
-out:
-	of_node_put(np);
-	return err;
-}
-
 static int ag71xx_probe(struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
-- 
2.30.2