Browse Source

ipq40xx: add DSA switch driver

Qualcomm IPQ40xx SoC-s have a variant of QCA8337N switch built-in.

It shares most of the stuff with its external counterpart, however it is
modified for the SoC.
Namely, it doesn't have second CPU port (Port 6), so it has 6 ports
instead of 7.
It also has no built-in PHY-s but rather requires external PSGMII based
companion PHY-s (QCA8072 and QCA8075) for which it first needs to carry
out calibration before using them.
PSGMII has a SoC built-in PHY that is used to connect to the PHY-s which
unfortunately requires some magic values as the datasheet doesnt document
the bits that are being set or the register at all.

Since its built-in it is MMIO like other peripherals and doesn't have its
own MDIO bus but depends on the SoC provided one.

CPU connection is at Port 0 and it uses some kind of a internal connection
and no traditional RGMII/SGMII.
It also doesn't use in-band tagging like other qca8k switches so a shinfo
based tagger is used.

This is based on the current OpenWrt qca8k version that has been imported
from generic target.

Signed-off-by: Robert Marko <[email protected]>
Robert Marko 4 years ago
parent
commit
b1f21329d4

File diff suppressed because it is too large
+ 110 - 787
target/linux/ipq40xx/files/drivers/net/dsa/qca/qca8k-ipq4019.c


+ 29 - 73
target/linux/ipq40xx/files/drivers/net/dsa/qca/qca8k-ipq4019.h

@@ -8,19 +8,12 @@
 #ifndef __QCA8K_H
 #define __QCA8K_H
 
-#include <linux/delay.h>
 #include <linux/regmap.h>
-#include <linux/gpio.h>
 
-#define QCA8K_NUM_PORTS					7
-#define QCA8K_NUM_CPU_PORTS				2
+#define QCA8K_NUM_PORTS					6
+#define QCA8K_CPU_PORT					0
 #define QCA8K_MAX_MTU					9000
 
-#define PHY_ID_QCA8327					0x004dd034
-#define QCA8K_ID_QCA8327				0x12
-#define PHY_ID_QCA8337					0x004dd036
-#define QCA8K_ID_QCA8337				0x13
-
 #define QCA8K_BUSY_WAIT_TIMEOUT				2000
 
 #define QCA8K_NUM_FDB_RECORDS				2048
@@ -33,46 +26,26 @@
 #define   QCA8K_MASK_CTRL_REV_ID(x)			((x) >> 0)
 #define   QCA8K_MASK_CTRL_DEVICE_ID_MASK		GENMASK(15, 8)
 #define   QCA8K_MASK_CTRL_DEVICE_ID(x)			((x) >> 8)
-#define QCA8K_REG_PORT0_PAD_CTRL			0x004
-#define   QCA8K_PORT0_PAD_SGMII_RXCLK_FALLING_EDGE	BIT(19)
-#define   QCA8K_PORT0_PAD_SGMII_TXCLK_FALLING_EDGE	BIT(18)
-#define QCA8K_REG_PORT5_PAD_CTRL			0x008
-#define QCA8K_REG_PORT6_PAD_CTRL			0x00c
-#define   QCA8K_PORT_PAD_RGMII_EN			BIT(26)
-#define   QCA8K_PORT_PAD_RGMII_TX_DELAY_MASK		GENMASK(23, 22)
-#define   QCA8K_PORT_PAD_RGMII_TX_DELAY(x)		((x) << 22)
-#define   QCA8K_PORT_PAD_RGMII_RX_DELAY_MASK		GENMASK(21, 20)
-#define   QCA8K_PORT_PAD_RGMII_RX_DELAY(x)		((x) << 20)
-#define	  QCA8K_PORT_PAD_RGMII_TX_DELAY_EN		BIT(25)
-#define   QCA8K_PORT_PAD_RGMII_RX_DELAY_EN		BIT(24)
-#define   QCA8K_MAX_DELAY				3
-#define   QCA8K_PORT_PAD_SGMII_EN			BIT(7)
-#define QCA8K_REG_PWS					0x010
-#define   QCA8K_PWS_POWER_ON_SEL			BIT(31)
-/* This reg is only valid for QCA832x and toggle the package
- * type from 176 pin (by default) to 148 pin used on QCA8327
+#define QCA8K_REG_RGMII_CTRL				0x004
+#define   QCA8K_RGMII_CTRL_RGMII_RXC			GENMASK(1, 0)
+#define   QCA8K_RGMII_CTRL_RGMII_TXC			GENMASK(9, 8)
+/* Some kind of CLK selection
+ * 0: gcc_ess_dly2ns
+ * 1: gcc_ess_clk
  */
-#define   QCA8327_PWS_PACKAGE148_EN			BIT(30)
-#define   QCA8K_PWS_LED_OPEN_EN_CSR			BIT(24)
-#define   QCA8K_PWS_SERDES_AEN_DIS			BIT(7)
+#define   QCA8K_RGMII_CTRL_CLK				BIT(10)
+#define   QCA8K_RGMII_CTRL_DELAY_RMII0			GENMASK(17, 16)
+#define   QCA8K_RGMII_CTRL_INVERT_RMII0_REF_CLK		BIT(18)
+#define   QCA8K_RGMII_CTRL_DELAY_RMII1			GENMASK(20, 19)
+#define   QCA8K_RGMII_CTRL_INVERT_RMII1_REF_CLK		BIT(21)
+#define   QCA8K_RGMII_CTRL_INVERT_RMII0_MASTER_EN	BIT(24)
+#define   QCA8K_RGMII_CTRL_INVERT_RMII1_MASTER_EN	BIT(25)
 #define QCA8K_REG_MODULE_EN				0x030
 #define   QCA8K_MODULE_EN_MIB				BIT(0)
 #define QCA8K_REG_MIB					0x034
 #define   QCA8K_MIB_FLUSH				BIT(24)
 #define   QCA8K_MIB_CPU_KEEP				BIT(20)
 #define   QCA8K_MIB_BUSY				BIT(17)
-#define QCA8K_MDIO_MASTER_CTRL				0x3c
-#define   QCA8K_MDIO_MASTER_BUSY			BIT(31)
-#define   QCA8K_MDIO_MASTER_EN				BIT(30)
-#define   QCA8K_MDIO_MASTER_READ			BIT(27)
-#define   QCA8K_MDIO_MASTER_WRITE			0
-#define   QCA8K_MDIO_MASTER_SUP_PRE			BIT(26)
-#define   QCA8K_MDIO_MASTER_PHY_ADDR(x)			((x) << 21)
-#define   QCA8K_MDIO_MASTER_REG_ADDR(x)			((x) << 16)
-#define   QCA8K_MDIO_MASTER_DATA(x)			(x)
-#define   QCA8K_MDIO_MASTER_DATA_MASK			GENMASK(15, 0)
-#define   QCA8K_MDIO_MASTER_MAX_PORTS			5
-#define   QCA8K_MDIO_MASTER_MAX_REG			32
 #define QCA8K_GOL_MAC_ADDR0				0x60
 #define QCA8K_GOL_MAC_ADDR1				0x64
 #define QCA8K_MAX_FRAME_SIZE				0x78
@@ -109,11 +82,6 @@
 #define   QCA8K_SGMII_MODE_CTRL_PHY			(1 << 22)
 #define   QCA8K_SGMII_MODE_CTRL_MAC			(2 << 22)
 
-/* MAC_PWR_SEL registers */
-#define QCA8K_REG_MAC_PWR_SEL				0x0e4
-#define   QCA8K_MAC_PWR_RGMII1_1_8V			BIT(18)
-#define   QCA8K_MAC_PWR_RGMII0_1_8V			BIT(19)
-
 /* EEE control registers */
 #define QCA8K_REG_EEE_CTRL				0x100
 #define  QCA8K_REG_EEE_CTRL_LPI_EN(_i)			((_i + 1) * 2)
@@ -228,9 +196,15 @@
 /* MIB registers */
 #define QCA8K_PORT_MIB_COUNTER(_i)			(0x1000 + (_i) * 0x100)
 
-/* QCA specific MII registers */
-#define MII_ATH_MMD_ADDR				0x0d
-#define MII_ATH_MMD_DATA				0x0e
+/* IPQ4019 PSGMII PHY registers */
+#define PSGMIIPHY_MODE_CONTROL				0x1b4
+#define   PSGMIIPHY_MODE_ATHR_CSCO_MODE_25M		BIT(0)
+#define PSGMIIPHY_TX_CONTROL				0x288
+#define   PSGMIIPHY_TX_CONTROL_MAGIC_VALUE		0x8380
+#define PSGMIIPHY_VCO_CALIBRATION_CONTROL_REGISTER_1	0x9c
+#define   PSGMIIPHY_REG_PLL_VCO_CALIB_RESTART		BIT(14)
+#define PSGMIIPHY_VCO_CALIBRATION_CONTROL_REGISTER_2	0xa0
+#define   PSGMIIPHY_REG_PLL_VCO_CALIB_READY		BIT(0)
 
 enum {
 	QCA8K_PORT_SPEED_10M = 0,
@@ -260,29 +234,7 @@ struct ar8xxx_port_status {
 	int enabled;
 };
 
-struct qca8k_match_data {
-	u8 id;
-	bool reduced_package;
-};
-
-enum {
-	QCA8K_CPU_PORT0,
-	QCA8K_CPU_PORT6,
-};
-
-struct qca8k_ports_config {
-	bool sgmii_rx_clk_falling_edge;
-	bool sgmii_tx_clk_falling_edge;
-	bool sgmii_enable_pll;
-	u8 rgmii_rx_delay[QCA8K_NUM_CPU_PORTS]; /* 0: CPU port0, 1: CPU port6 */
-	u8 rgmii_tx_delay[QCA8K_NUM_CPU_PORTS]; /* 0: CPU port0, 1: CPU port6 */
-};
-
 struct qca8k_priv {
-	u8 switch_id;
-	u8 switch_revision;
-	bool legacy_phy_port_mapping;
-	struct qca8k_ports_config ports_config;
 	struct regmap *regmap;
 	struct mii_bus *bus;
 	struct ar8xxx_port_status port_sts[QCA8K_NUM_PORTS];
@@ -290,8 +242,12 @@ struct qca8k_priv {
 	struct mutex reg_mutex;
 	struct device *dev;
 	struct dsa_switch_ops ops;
-	struct gpio_desc *reset_gpio;
 	unsigned int port_mtu[QCA8K_NUM_PORTS];
+
+	/* IPQ4019 specific */
+	struct regmap *psgmii;
+	bool psgmii_calibrated;
+	struct phy_device *psgmii_ethphy;
 };
 
 struct qca8k_mib_desc {

+ 53 - 0
target/linux/ipq40xx/patches-5.10/705-net-dsa-add-Qualcomm-IPQ4019-built-in-switch-support.patch

@@ -0,0 +1,53 @@
+From b5f71652b85a85ea53162e9e2b760b84fd0d254f Mon Sep 17 00:00:00 2001
+From: Robert Marko <[email protected]>
+Date: Mon, 1 Nov 2021 18:10:28 +0100
+Subject: [PATCH] net: dsa: add Qualcomm IPQ4019 built-in switch support
+
+Qualcomm IPQ40xx SoC-s have a variant of QCA8337N switch built-in.
+
+It shares most of the stuff with its external counterpart, however it is
+modified for the SoC.
+Namely, it doesn't have second CPU port (Port 6), so it has 6 ports
+instead of 7.
+It also has no built-in PHY-s but rather requires external PSGMII based
+companion PHY-s (QCA8072 and QCA8075) for which it first needs to carry
+out calibration before using them.
+PSGMII has a SoC built-in PHY that is used to connect to the PHY-s which
+unfortunately requires some magic values as the datasheet doesnt document
+the bits that are being set or the register at all.
+
+Since its built-in it is MMIO like other peripherals and doesn't have its
+own MDIO bus but depends on the SoC provided one.
+
+CPU connection is at Port 0 and it uses some kind of a internal connection
+and no traditional RGMII/SGMII.
+It also doesn't use in-band tagging like other qca8k switches so a shinfo
+based tagger is used.
+
+Signed-off-by: Robert Marko <[email protected]>
+---
+ drivers/net/dsa/qca/Kconfig  | 9 +++++++++
+ drivers/net/dsa/qca/Makefile | 1 +
+ 2 files changed, 10 insertions(+)
+
+--- a/drivers/net/dsa/qca/Kconfig
++++ b/drivers/net/dsa/qca/Kconfig
+@@ -7,3 +7,12 @@ config NET_DSA_AR9331
+ 	help
+ 	  This enables support for the Qualcomm Atheros AR9331 built-in Ethernet
+ 	  switch.
++
++config NET_DSA_QCA8K_IPQ4019
++	tristate "Qualcomm Atheros IPQ4019 built-in Ethernet switch support"
++	depends on HAS_IOMEM && NET_DSA
++	select NET_DSA_TAG_IPQ4019
++	select REGMAP
++	help
++	  This enables support for the Qualcomm Atheros IPQ4019 SoC built-in
++	  Ethernet switch.
+--- a/drivers/net/dsa/qca/Makefile
++++ b/drivers/net/dsa/qca/Makefile
+@@ -1,2 +1,3 @@
+ # SPDX-License-Identifier: GPL-2.0-only
+ obj-$(CONFIG_NET_DSA_AR9331)	+= ar9331.o
++obj-$(CONFIG_NET_DSA_QCA8K_IPQ4019)	+= qca8k-ipq4019.o

+ 98 - 0
target/linux/ipq40xx/patches-5.10/706-arm-dts-ipq4019-add-switch-node.patch

@@ -0,0 +1,98 @@
+From ebb62523990a27b3a25e422fa575619f7f725a20 Mon Sep 17 00:00:00 2001
+From: Robert Marko <[email protected]>
+Date: Mon, 1 Nov 2021 18:15:04 +0100
+Subject: [PATCH] arm: dts: ipq4019: add switch node
+
+Since the built-in IPQ40xx switch now has a driver, add the required node
+for it to work.
+
+Signed-off-by: Robert Marko <[email protected]>
+---
+ arch/arm/boot/dts/qcom-ipq4019.dtsi | 78 +++++++++++++++++++++++++++++
+ 1 file changed, 78 insertions(+)
+
+--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi
++++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi
+@@ -590,6 +590,82 @@
+ 			status = "disabled";
+ 		};
+ 
++		switch: switch@c000000 {
++			compatible = "qca,ipq4019-qca8337n";
++			reg = <0xc000000 0x80000>, <0x98000 0x800>;
++			reg-names = "base", "psgmii_phy";
++			resets = <&gcc ESS_PSGMII_ARES>;
++			reset-names = "psgmii_rst";
++			mdio = <&mdio>;
++			psgmii-ethphy = <&psgmiiphy>;
++
++			status = "disabled";
++
++			ports {
++				#address-cells = <1>;
++				#size-cells = <0>;
++
++				port@0 { /* MAC0 */
++					reg = <0>;
++					label = "cpu";
++					ethernet = <&gmac>;
++					phy-mode = "internal";
++
++					fixed-link {
++						speed = <1000>;
++						full-duplex;
++						pause;
++						asym-pause;
++					};
++				};
++
++				swport1: port@1 { /* MAC1 */
++					reg = <1>;
++					label = "lan1";
++					phy-handle = <&ethphy0>;
++					phy-mode = "psgmii";
++
++					status = "disabled";
++				};
++
++				swport2: port@2 { /* MAC2 */
++					reg = <2>;
++					label = "lan2";
++					phy-handle = <&ethphy1>;
++					phy-mode = "psgmii";
++
++					status = "disabled";
++				};
++
++				swport3: port@3 { /* MAC3 */
++					reg = <3>;
++					label = "lan3";
++					phy-handle = <&ethphy2>;
++					phy-mode = "psgmii";
++
++					status = "disabled";
++				};
++
++				swport4: port@4 { /* MAC4 */
++					reg = <4>;
++					label = "lan4";
++					phy-handle = <&ethphy3>;
++					phy-mode = "psgmii";
++
++					status = "disabled";
++				};
++
++				swport5: port@5 { /* MAC5 */
++					reg = <5>;
++					label = "wan";
++					phy-handle = <&ethphy4>;
++					phy-mode = "psgmii";
++
++					status = "disabled";
++				};
++			};
++		};
++
+ 		gmac: ethernet@c080000 {
+ 			compatible = "qcom,ipq4019-ess-edma";
+ 			reg = <0xc080000 0x8000>;

+ 0 - 0
target/linux/ipq40xx/patches-5.10/706-dt-bindings-net-add-QCA807x-PHY.patch → target/linux/ipq40xx/patches-5.10/707-dt-bindings-net-add-QCA807x-PHY.patch


+ 0 - 0
target/linux/ipq40xx/patches-5.10/707-net-phy-Add-Qualcom-QCA807x-driver.patch → target/linux/ipq40xx/patches-5.10/708-net-phy-Add-Qualcom-QCA807x-driver.patch


+ 1 - 1
target/linux/ipq40xx/patches-5.10/708-arm-dts-ipq4019-QCA807x-properties.patch → target/linux/ipq40xx/patches-5.10/709-arm-dts-ipq4019-QCA807x-properties.patch

@@ -20,7 +20,7 @@ Signed-off-by: Robert Marko <[email protected]>
  
  / {
  	#address-cells = <1>;
-@@ -645,22 +646,39 @@
+@@ -726,22 +727,38 @@
  
  			ethphy0: ethernet-phy@0 {
  				reg = <0>;

+ 56 - 0
target/linux/ipq40xx/patches-5.15/705-net-dsa-add-Qualcomm-IPQ4019-built-in-switch-support.patch

@@ -0,0 +1,56 @@
+From b5f71652b85a85ea53162e9e2b760b84fd0d254f Mon Sep 17 00:00:00 2001
+From: Robert Marko <[email protected]>
+Date: Mon, 1 Nov 2021 18:10:28 +0100
+Subject: [PATCH] net: dsa: add Qualcomm IPQ4019 built-in switch support
+
+Qualcomm IPQ40xx SoC-s have a variant of QCA8337N switch built-in.
+
+It shares most of the stuff with its external counterpart, however it is
+modified for the SoC.
+Namely, it doesn't have second CPU port (Port 6), so it has 6 ports
+instead of 7.
+It also has no built-in PHY-s but rather requires external PSGMII based
+companion PHY-s (QCA8072 and QCA8075) for which it first needs to carry
+out calibration before using them.
+PSGMII has a SoC built-in PHY that is used to connect to the PHY-s which
+unfortunately requires some magic values as the datasheet doesnt document
+the bits that are being set or the register at all.
+
+Since its built-in it is MMIO like other peripherals and doesn't have its
+own MDIO bus but depends on the SoC provided one.
+
+CPU connection is at Port 0 and it uses some kind of a internal connection
+and no traditional RGMII/SGMII.
+It also doesn't use in-band tagging like other qca8k switches so a shinfo
+based tagger is used.
+
+Signed-off-by: Robert Marko <[email protected]>
+---
+ drivers/net/dsa/qca/Kconfig  | 9 +++++++++
+ drivers/net/dsa/qca/Makefile | 1 +
+ 2 files changed, 10 insertions(+)
+
+--- a/drivers/net/dsa/qca/Kconfig
++++ b/drivers/net/dsa/qca/Kconfig
+@@ -15,3 +15,13 @@ config NET_DSA_QCA8K
+ 	help
+ 	  This enables support for the Qualcomm Atheros QCA8K Ethernet
+ 	  switch chips.
++
++config NET_DSA_QCA8K_IPQ4019
++	tristate "Qualcomm Atheros IPQ4019 built-in Ethernet switch support"
++	depends on HAS_IOMEM && NET_DSA
++	select NET_DSA_TAG_IPQ4019
++	select REGMAP
++	help
++	  This enables support for the Qualcomm Atheros IPQ4019 SoC built-in
++	  Ethernet switch.
++
+--- a/drivers/net/dsa/qca/Makefile
++++ b/drivers/net/dsa/qca/Makefile
+@@ -1,4 +1,5 @@
+ # SPDX-License-Identifier: GPL-2.0-only
+ obj-$(CONFIG_NET_DSA_AR9331)	+= ar9331.o
++obj-$(CONFIG_NET_DSA_QCA8K_IPQ4019)	+= qca8k-ipq4019.o
+ obj-$(CONFIG_NET_DSA_QCA8K)	+= qca8k.o
+ qca8k-y 			+= qca8k-common.o qca8k-8xxx.o

+ 98 - 0
target/linux/ipq40xx/patches-5.15/706-arm-dts-ipq4019-add-switch-node.patch

@@ -0,0 +1,98 @@
+From ebb62523990a27b3a25e422fa575619f7f725a20 Mon Sep 17 00:00:00 2001
+From: Robert Marko <[email protected]>
+Date: Mon, 1 Nov 2021 18:15:04 +0100
+Subject: [PATCH] arm: dts: ipq4019: add switch node
+
+Since the built-in IPQ40xx switch now has a driver, add the required node
+for it to work.
+
+Signed-off-by: Robert Marko <[email protected]>
+---
+ arch/arm/boot/dts/qcom-ipq4019.dtsi | 78 +++++++++++++++++++++++++++++
+ 1 file changed, 78 insertions(+)
+
+--- a/arch/arm/boot/dts/qcom-ipq4019.dtsi
++++ b/arch/arm/boot/dts/qcom-ipq4019.dtsi
+@@ -590,6 +590,82 @@
+ 			status = "disabled";
+ 		};
+ 
++		switch: switch@c000000 {
++			compatible = "qca,ipq4019-qca8337n";
++			reg = <0xc000000 0x80000>, <0x98000 0x800>;
++			reg-names = "base", "psgmii_phy";
++			resets = <&gcc ESS_PSGMII_ARES>;
++			reset-names = "psgmii_rst";
++			mdio = <&mdio>;
++			psgmii-ethphy = <&psgmiiphy>;
++
++			status = "disabled";
++
++			ports {
++				#address-cells = <1>;
++				#size-cells = <0>;
++
++				port@0 { /* MAC0 */
++					reg = <0>;
++					label = "cpu";
++					ethernet = <&gmac>;
++					phy-mode = "internal";
++
++					fixed-link {
++						speed = <1000>;
++						full-duplex;
++						pause;
++						asym-pause;
++					};
++				};
++
++				swport1: port@1 { /* MAC1 */
++					reg = <1>;
++					label = "lan1";
++					phy-handle = <&ethphy0>;
++					phy-mode = "psgmii";
++
++					status = "disabled";
++				};
++
++				swport2: port@2 { /* MAC2 */
++					reg = <2>;
++					label = "lan2";
++					phy-handle = <&ethphy1>;
++					phy-mode = "psgmii";
++
++					status = "disabled";
++				};
++
++				swport3: port@3 { /* MAC3 */
++					reg = <3>;
++					label = "lan3";
++					phy-handle = <&ethphy2>;
++					phy-mode = "psgmii";
++
++					status = "disabled";
++				};
++
++				swport4: port@4 { /* MAC4 */
++					reg = <4>;
++					label = "lan4";
++					phy-handle = <&ethphy3>;
++					phy-mode = "psgmii";
++
++					status = "disabled";
++				};
++
++				swport5: port@5 { /* MAC5 */
++					reg = <5>;
++					label = "wan";
++					phy-handle = <&ethphy4>;
++					phy-mode = "psgmii";
++
++					status = "disabled";
++				};
++			};
++		};
++
+ 		gmac: ethernet@c080000 {
+ 			compatible = "qcom,ipq4019-ess-edma";
+ 			reg = <0xc080000 0x8000>;

+ 0 - 0
target/linux/ipq40xx/patches-5.15/706-dt-bindings-net-add-QCA807x-PHY.patch → target/linux/ipq40xx/patches-5.15/707-dt-bindings-net-add-QCA807x-PHY.patch


+ 0 - 0
target/linux/ipq40xx/patches-5.15/707-net-phy-Add-Qualcom-QCA807x-driver.patch → target/linux/ipq40xx/patches-5.15/708-net-phy-Add-Qualcom-QCA807x-driver.patch


+ 1 - 1
target/linux/ipq40xx/patches-5.15/708-arm-dts-ipq4019-QCA807x-properties.patch → target/linux/ipq40xx/patches-5.15/709-arm-dts-ipq4019-QCA807x-properties.patch

@@ -20,7 +20,7 @@ Signed-off-by: Robert Marko <[email protected]>
  
  / {
  	#address-cells = <1>;
-@@ -598,22 +599,38 @@
+@@ -726,22 +727,38 @@
  
  			ethphy0: ethernet-phy@0 {
  				reg = <0>;

Some files were not shown because too many files changed in this diff