udelay(100);
}
+static void ag71xx_bit_set(void __iomem *reg, u32 bit)
+{
+ u32 val;
+
+ val = __raw_readl(reg) | bit;
+ __raw_writel(val, reg);
+ __raw_readl(reg);
+}
+
+static void ag71xx_bit_clear(void __iomem *reg, u32 bit)
+{
+ u32 val;
+
+ val = __raw_readl(reg) & ~bit;
+ __raw_writel(val, reg);
+ __raw_readl(reg);
+}
+
+static void ag71xx_sgmii_init_qca955x(struct device_node *np)
+{
+ struct device_node *np_dev;
+ void __iomem *gmac_base;
+ u32 mr_an_status;
+ u32 sgmii_status;
+ u8 tries = 0;
+ int err = 0;
+
+ np = of_get_child_by_name(np, "gmac-config");
+ if (!np)
+ return;
+
+ np_dev = of_parse_phandle(np, "device", 0);
+ if (!np_dev)
+ goto out;
+
+ gmac_base = of_iomap(np_dev, 0);
+ if (!gmac_base) {
+ pr_err("%pOF: can't map GMAC registers\n", np_dev);
+ err = -ENOMEM;
+ goto err_iomap;
+ }
+
+ mr_an_status = __raw_readl(gmac_base + QCA955X_GMAC_REG_MR_AN_STATUS);
+ if (!(mr_an_status & QCA955X_MR_AN_STATUS_AN_ABILITY))
+ goto sgmii_out;
+
+ /* SGMII reset sequence */
+ __raw_writel(QCA955X_SGMII_RESET_RX_CLK_N_RESET,
+ gmac_base + QCA955X_GMAC_REG_SGMII_RESET);
+ __raw_readl(gmac_base + QCA955X_GMAC_REG_SGMII_RESET);
+ udelay(10);
+
+ ag71xx_bit_set(gmac_base + QCA955X_GMAC_REG_SGMII_RESET,
+ QCA955X_SGMII_RESET_HW_RX_125M_N);
+ udelay(10);
+
+ ag71xx_bit_set(gmac_base + QCA955X_GMAC_REG_SGMII_RESET,
+ QCA955X_SGMII_RESET_RX_125M_N);
+ udelay(10);
+
+ ag71xx_bit_set(gmac_base + QCA955X_GMAC_REG_SGMII_RESET,
+ QCA955X_SGMII_RESET_TX_125M_N);
+ udelay(10);
+
+ ag71xx_bit_set(gmac_base + QCA955X_GMAC_REG_SGMII_RESET,
+ QCA955X_SGMII_RESET_RX_CLK_N);
+ udelay(10);
+
+ ag71xx_bit_set(gmac_base + QCA955X_GMAC_REG_SGMII_RESET,
+ QCA955X_SGMII_RESET_TX_CLK_N);
+ udelay(10);
+
+ /*
+ * The following is what QCA has to say about what happens here:
+ *
+ * Across resets SGMII link status goes to weird state.
+ * If SGMII_DEBUG register reads other than 0x1f or 0x10,
+ * we are for sure in a bad state.
+ *
+ * Issue a PHY reset in MR_AN_CONTROL to keep going.
+ */
+ do {
+ ag71xx_bit_set(gmac_base + QCA955X_GMAC_REG_MR_AN_CONTROL,
+ QCA955X_MR_AN_CONTROL_PHY_RESET |
+ QCA955X_MR_AN_CONTROL_AN_ENABLE);
+ udelay(200);
+ ag71xx_bit_clear(gmac_base + QCA955X_GMAC_REG_MR_AN_CONTROL,
+ QCA955X_MR_AN_CONTROL_PHY_RESET);
+ mdelay(300);
+ sgmii_status = __raw_readl(gmac_base + QCA955X_GMAC_REG_SGMII_DEBUG) &
+ QCA955X_SGMII_DEBUG_TX_STATE_MASK;
+
+ if (tries++ >= 20) {
+ pr_err("ag71xx: max retries for SGMII fixup exceeded\n");
+ break;
+ }
+ } while (!(sgmii_status == 0xf || sgmii_status == 0x10));
+
+sgmii_out:
+ iounmap(gmac_base);
+err_iomap:
+ of_node_put(np_dev);
+out:
+ of_node_put(np);
+}
+
static void ath79_mii_ctrl_set_if(struct ag71xx *ag, unsigned int mii_if)
{
u32 t;
of_device_is_compatible(np, "qca,qca9550-eth") ||
of_device_is_compatible(np, "qca,qca9560-eth")) {
ath79_set_pllval(ag);
+ if (of_property_read_bool(np, "qca955x-sgmii-fixup"))
+ ag71xx_sgmii_init_qca955x(np);
}
}
--- /dev/null
+From 60efe35257b063ce584968f9f80b437030ce6ba6 Mon Sep 17 00:00:00 2001
+From: David Bauer <mail@david-bauer.net>
+Date: Mon, 18 Mar 2019 00:54:06 +0100
+Subject: [PATCH] MIPS: ath79: add missing QCA955x GMAC registers
+
+This adds missing GMAC register definitions for the Qualcomm Atheros
+QCA955X series MIPS SoCs.
+
+They originate from the platforms U-Boot code and the AVM FRITZ!WLAN
+Repeater 450E's GPL tarball.
+
+Signed-off-by: David Bauer <mail@david-bauer.net>
+---
+ .../mips/include/asm/mach-ath79/ar71xx_regs.h | 54 +++++++++++++++++++
+ 1 file changed, 54 insertions(+)
+
+--- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
++++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
+@@ -1245,7 +1245,12 @@
+ */
+
+ #define QCA955X_GMAC_REG_ETH_CFG 0x00
++#define QCA955X_GMAC_REG_SGMII_RESET 0x14
+ #define QCA955X_GMAC_REG_SGMII_SERDES 0x18
++#define QCA955X_GMAC_REG_MR_AN_CONTROL 0x1c
++#define QCA955X_GMAC_REG_MR_AN_STATUS 0x20
++#define QCA955X_GMAC_REG_SGMII_CONFIG 0x34
++#define QCA955X_GMAC_REG_SGMII_DEBUG 0x58
+
+ #define QCA955X_ETH_CFG_RGMII_EN BIT(0)
+ #define QCA955X_ETH_CFG_MII_GE0 BIT(1)
+@@ -1267,9 +1272,58 @@
+ #define QCA955X_ETH_CFG_TXE_DELAY_MASK 0x3
+ #define QCA955X_ETH_CFG_TXE_DELAY_SHIFT 20
+
++#define QCA955X_SGMII_RESET_RX_CLK_N_RESET 0
++#define QCA955X_SGMII_RESET_RX_CLK_N BIT(0)
++#define QCA955X_SGMII_RESET_TX_CLK_N BIT(1)
++#define QCA955X_SGMII_RESET_RX_125M_N BIT(2)
++#define QCA955X_SGMII_RESET_TX_125M_N BIT(3)
++#define QCA955X_SGMII_RESET_HW_RX_125M_N BIT(4)
++
+ #define QCA955X_SGMII_SERDES_LOCK_DETECT_STATUS BIT(15)
+ #define QCA955X_SGMII_SERDES_RES_CALIBRATION_SHIFT 23
+ #define QCA955X_SGMII_SERDES_RES_CALIBRATION_MASK 0xf
++
++#define QCA955X_MR_AN_CONTROL_SPEED_SEL1 BIT(6)
++#define QCA955X_MR_AN_CONTROL_DUPLEX_MODE BIT(8)
++#define QCA955X_MR_AN_CONTROL_RESTART_AN BIT(9)
++#define QCA955X_MR_AN_CONTROL_POWER_DOWN BIT(11)
++#define QCA955X_MR_AN_CONTROL_AN_ENABLE BIT(12)
++#define QCA955X_MR_AN_CONTROL_SPEED_SEL0 BIT(13)
++#define QCA955X_MR_AN_CONTROL_LOOPBACK BIT(14)
++#define QCA955X_MR_AN_CONTROL_PHY_RESET BIT(15)
++
++#define QCA955X_MR_AN_STATUS_EXT_CAP BIT(0)
++#define QCA955X_MR_AN_STATUS_LINK_UP BIT(2)
++#define QCA955X_MR_AN_STATUS_AN_ABILITY BIT(3)
++#define QCA955X_MR_AN_STATUS_REMOTE_FAULT BIT(4)
++#define QCA955X_MR_AN_STATUS_AN_COMPLETE BIT(5)
++#define QCA955X_MR_AN_STATUS_NO_PREAMBLE BIT(6)
++#define QCA955X_MR_AN_STATUS_BASE_PAGE BIT(7)
++
++#define QCA955X_SGMII_CONFIG_MODE_CTRL_SHIFT 0
++#define QCA955X_SGMII_CONFIG_MODE_CTRL_MASK 0x7
++#define QCA955X_SGMII_CONFIG_ENABLE_SGMII_TX_PAUSE BIT(3)
++#define QCA955X_SGMII_CONFIG_MR_REG4_CHANGED BIT(4)
++#define QCA955X_SGMII_CONFIG_FORCE_SPEED BIT(5)
++#define QCA955X_SGMII_CONFIG_SPEED_SHIFT 6
++#define QCA955X_SGMII_CONFIG_SPEED_MASK 0xc0
++#define QCA955X_SGMII_CONFIG_REMOTE_PHY_LOOPBACK BIT(8)
++#define QCA955X_SGMII_CONFIG_NEXT_PAGE_LOADED BIT(9)
++#define QCA955X_SGMII_CONFIG_MDIO_ENABLE BIT(10)
++#define QCA955X_SGMII_CONFIG_MDIO_PULSE BIT(11)
++#define QCA955X_SGMII_CONFIG_MDIO_COMPLETE BIT(12)
++#define QCA955X_SGMII_CONFIG_PRBS_ENABLE BIT(13)
++#define QCA955X_SGMII_CONFIG_BERT_ENABLE BIT(14)
++
++#define QCA955X_SGMII_DEBUG_TX_STATE_MASK 0xff
++#define QCA955X_SGMII_DEBUG_TX_STATE_SHIFT 0
++#define QCA955X_SGMII_DEBUG_RX_STATE_MASK 0xff00
++#define QCA955X_SGMII_DEBUG_RX_STATE_SHIFT 8
++#define QCA955X_SGMII_DEBUG_RX_SYNC_STATE_MASK 0xff0000
++#define QCA955X_SGMII_DEBUG_RX_SYNC_STATE_SHIFT 16
++#define QCA955X_SGMII_DEBUG_ARB_STATE_MASK 0xf000000
++#define QCA955X_SGMII_DEBUG_ARB_STATE_SHIFT 24
++
+ /*
+ * QCA956X GMAC Interface
+ */
+
--- /dev/null
+From 60efe35257b063ce584968f9f80b437030ce6ba6 Mon Sep 17 00:00:00 2001
+From: David Bauer <mail@david-bauer.net>
+Date: Mon, 18 Mar 2019 00:54:06 +0100
+Subject: [PATCH] MIPS: ath79: add missing QCA955x GMAC registers
+
+This adds missing GMAC register definitions for the Qualcomm Atheros
+QCA955X series MIPS SoCs.
+
+They originate from the platforms U-Boot code and the AVM FRITZ!WLAN
+Repeater 450E's GPL tarball.
+
+Signed-off-by: David Bauer <mail@david-bauer.net>
+---
+ .../mips/include/asm/mach-ath79/ar71xx_regs.h | 54 +++++++++++++++++++
+ 1 file changed, 54 insertions(+)
+
+--- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
++++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
+@@ -1245,7 +1245,12 @@
+ */
+
+ #define QCA955X_GMAC_REG_ETH_CFG 0x00
++#define QCA955X_GMAC_REG_SGMII_RESET 0x14
+ #define QCA955X_GMAC_REG_SGMII_SERDES 0x18
++#define QCA955X_GMAC_REG_MR_AN_CONTROL 0x1c
++#define QCA955X_GMAC_REG_MR_AN_STATUS 0x20
++#define QCA955X_GMAC_REG_SGMII_CONFIG 0x34
++#define QCA955X_GMAC_REG_SGMII_DEBUG 0x58
+
+ #define QCA955X_ETH_CFG_RGMII_EN BIT(0)
+ #define QCA955X_ETH_CFG_MII_GE0 BIT(1)
+@@ -1267,9 +1272,58 @@
+ #define QCA955X_ETH_CFG_TXE_DELAY_MASK 0x3
+ #define QCA955X_ETH_CFG_TXE_DELAY_SHIFT 20
+
++#define QCA955X_SGMII_RESET_RX_CLK_N_RESET 0
++#define QCA955X_SGMII_RESET_RX_CLK_N BIT(0)
++#define QCA955X_SGMII_RESET_TX_CLK_N BIT(1)
++#define QCA955X_SGMII_RESET_RX_125M_N BIT(2)
++#define QCA955X_SGMII_RESET_TX_125M_N BIT(3)
++#define QCA955X_SGMII_RESET_HW_RX_125M_N BIT(4)
++
+ #define QCA955X_SGMII_SERDES_LOCK_DETECT_STATUS BIT(15)
+ #define QCA955X_SGMII_SERDES_RES_CALIBRATION_SHIFT 23
+ #define QCA955X_SGMII_SERDES_RES_CALIBRATION_MASK 0xf
++
++#define QCA955X_MR_AN_CONTROL_SPEED_SEL1 BIT(6)
++#define QCA955X_MR_AN_CONTROL_DUPLEX_MODE BIT(8)
++#define QCA955X_MR_AN_CONTROL_RESTART_AN BIT(9)
++#define QCA955X_MR_AN_CONTROL_POWER_DOWN BIT(11)
++#define QCA955X_MR_AN_CONTROL_AN_ENABLE BIT(12)
++#define QCA955X_MR_AN_CONTROL_SPEED_SEL0 BIT(13)
++#define QCA955X_MR_AN_CONTROL_LOOPBACK BIT(14)
++#define QCA955X_MR_AN_CONTROL_PHY_RESET BIT(15)
++
++#define QCA955X_MR_AN_STATUS_EXT_CAP BIT(0)
++#define QCA955X_MR_AN_STATUS_LINK_UP BIT(2)
++#define QCA955X_MR_AN_STATUS_AN_ABILITY BIT(3)
++#define QCA955X_MR_AN_STATUS_REMOTE_FAULT BIT(4)
++#define QCA955X_MR_AN_STATUS_AN_COMPLETE BIT(5)
++#define QCA955X_MR_AN_STATUS_NO_PREAMBLE BIT(6)
++#define QCA955X_MR_AN_STATUS_BASE_PAGE BIT(7)
++
++#define QCA955X_SGMII_CONFIG_MODE_CTRL_SHIFT 0
++#define QCA955X_SGMII_CONFIG_MODE_CTRL_MASK 0x7
++#define QCA955X_SGMII_CONFIG_ENABLE_SGMII_TX_PAUSE BIT(3)
++#define QCA955X_SGMII_CONFIG_MR_REG4_CHANGED BIT(4)
++#define QCA955X_SGMII_CONFIG_FORCE_SPEED BIT(5)
++#define QCA955X_SGMII_CONFIG_SPEED_SHIFT 6
++#define QCA955X_SGMII_CONFIG_SPEED_MASK 0xc0
++#define QCA955X_SGMII_CONFIG_REMOTE_PHY_LOOPBACK BIT(8)
++#define QCA955X_SGMII_CONFIG_NEXT_PAGE_LOADED BIT(9)
++#define QCA955X_SGMII_CONFIG_MDIO_ENABLE BIT(10)
++#define QCA955X_SGMII_CONFIG_MDIO_PULSE BIT(11)
++#define QCA955X_SGMII_CONFIG_MDIO_COMPLETE BIT(12)
++#define QCA955X_SGMII_CONFIG_PRBS_ENABLE BIT(13)
++#define QCA955X_SGMII_CONFIG_BERT_ENABLE BIT(14)
++
++#define QCA955X_SGMII_DEBUG_TX_STATE_MASK 0xff
++#define QCA955X_SGMII_DEBUG_TX_STATE_SHIFT 0
++#define QCA955X_SGMII_DEBUG_RX_STATE_MASK 0xff00
++#define QCA955X_SGMII_DEBUG_RX_STATE_SHIFT 8
++#define QCA955X_SGMII_DEBUG_RX_SYNC_STATE_MASK 0xff0000
++#define QCA955X_SGMII_DEBUG_RX_SYNC_STATE_SHIFT 16
++#define QCA955X_SGMII_DEBUG_ARB_STATE_MASK 0xf000000
++#define QCA955X_SGMII_DEBUG_ARB_STATE_SHIFT 24
++
+ /*
+ * QCA956X GMAC Interface
+ */
+