[OpenWrt-Devel] [PATCH 1/2] ath79: add QCA9550 reset sequence

David Bauer mail at david-bauer.net
Wed Apr 15 12:47:18 EDT 2020


The QCA9550 family of SoCs have a slightly different reset
sequence compared to older chips.

Normally the bootloader performs this sequence, however
some bootloader implementation expect the operating system
to clear the reset. Also get the PCIe resets from OF to
support the second RC of the QCA9558.

This is required for the AVM FRITZ!WLAN Repeater 1750E to work,
as EVA leaves the PCIe bus in reset.

Tested: AVM FRITZ!WLAN Repeater 1750E - OCEDO Koala

Signed-off-by: David Bauer <mail at david-bauer.net>
---
 target/linux/ath79/dts/ar724x.dtsi            |   3 +
 target/linux/ath79/dts/ar9344.dtsi            |   3 +
 target/linux/ath79/dts/qca953x.dtsi           |   3 +
 target/linux/ath79/dts/qca9557.dtsi           |  10 +-
 target/linux/ath79/dts/qca956x.dtsi           |   3 +
 ...ci-ar724x-add-QCA9550-reset-sequence.patch | 130 ++++++++++++++++++
 ...ci-ar724x-add-QCA9550-reset-sequence.patch | 130 ++++++++++++++++++
 7 files changed, 280 insertions(+), 2 deletions(-)
 create mode 100644 target/linux/ath79/patches-4.19/0062-MIPS-pci-ar724x-add-QCA9550-reset-sequence.patch
 create mode 100644 target/linux/ath79/patches-5.4/0062-MIPS-pci-ar724x-add-QCA9550-reset-sequence.patch

diff --git a/target/linux/ath79/dts/ar724x.dtsi b/target/linux/ath79/dts/ar724x.dtsi
index 95832d998a..2d7383c36d 100644
--- a/target/linux/ath79/dts/ar724x.dtsi
+++ b/target/linux/ath79/dts/ar724x.dtsi
@@ -130,6 +130,9 @@
 				interrupt-parent = <&cpuintc>;
 				interrupts = <2>;
 
+				resets = <&rst 6>, <&rst 7>;
+				reset-names = "hc", "phy";
+
 				interrupt-controller;
 				#interrupt-cells = <1>;
 
diff --git a/target/linux/ath79/dts/ar9344.dtsi b/target/linux/ath79/dts/ar9344.dtsi
index de118e9a3b..e99d962933 100644
--- a/target/linux/ath79/dts/ar9344.dtsi
+++ b/target/linux/ath79/dts/ar9344.dtsi
@@ -46,6 +46,9 @@
 		interrupt-parent = <&intc2>;
 		interrupts = <1>;
 
+		resets = <&rst 6>, <&rst 7>;
+		reset-names = "hc", "phy";
+
 		interrupt-controller;
 		#interrupt-cells = <1>;
 
diff --git a/target/linux/ath79/dts/qca953x.dtsi b/target/linux/ath79/dts/qca953x.dtsi
index e359badd2b..f7e0703e4e 100644
--- a/target/linux/ath79/dts/qca953x.dtsi
+++ b/target/linux/ath79/dts/qca953x.dtsi
@@ -164,6 +164,9 @@
 			interrupt-parent = <&intc2>;
 			interrupts = <1>;
 
+			resets = <&rst 6>, <&rst 7>;
+			reset-names = "hc", "phy";
+
 			interrupt-controller;
 			#interrupt-cells = <1>;
 
diff --git a/target/linux/ath79/dts/qca9557.dtsi b/target/linux/ath79/dts/qca9557.dtsi
index 69ea639804..ede658af6d 100644
--- a/target/linux/ath79/dts/qca9557.dtsi
+++ b/target/linux/ath79/dts/qca9557.dtsi
@@ -202,7 +202,7 @@
 		};
 
 		pcie0: pcie-controller at 180c0000 {
-			compatible = "qcom,ar7240-pci";
+			compatible = "qcom,qca9550-pci", "qcom,ar7240-pci";
 			#address-cells = <3>;
 			#size-cells = <2>;
 			bus-range = <0x0 0x0>;
@@ -215,6 +215,9 @@
 			interrupt-parent = <&intc2>;
 			interrupts = <1>;
 
+			resets = <&rst 6>, <&rst 7>;
+			reset-names = "hc", "phy";
+
 			interrupt-controller;
 			#interrupt-cells = <1>;
 
@@ -234,7 +237,7 @@
 		};
 
 		pcie1: pcie-controller at 18250000 {
-			compatible = "qcom,ar7240-pci";
+			compatible = "qcom,qca9550-pci", "qcom,ar7240-pci";
 			#address-cells = <3>;
 			#size-cells = <2>;
 			bus-range = <0x0 0x0>;
@@ -247,6 +250,9 @@
 			interrupt-parent = <&intc3>;
 			interrupts = <0>;
 
+			resets = <&rst2 6>, <&rst2 7>;
+			reset-names = "hc", "phy";
+
 			interrupt-controller;
 			#interrupt-cells = <1>;
 
diff --git a/target/linux/ath79/dts/qca956x.dtsi b/target/linux/ath79/dts/qca956x.dtsi
index d0ce952ef4..333428443f 100644
--- a/target/linux/ath79/dts/qca956x.dtsi
+++ b/target/linux/ath79/dts/qca956x.dtsi
@@ -168,6 +168,9 @@
 			interrupt-parent = <&intc3>;
 			interrupts = <0>;
 
+			resets = <&rst 6>, <&rst 7>;
+			reset-names = "hc", "phy";
+
 			interrupt-controller;
 			#interrupt-cells = <1>;
 
diff --git a/target/linux/ath79/patches-4.19/0062-MIPS-pci-ar724x-add-QCA9550-reset-sequence.patch b/target/linux/ath79/patches-4.19/0062-MIPS-pci-ar724x-add-QCA9550-reset-sequence.patch
new file mode 100644
index 0000000000..2c9120f771
--- /dev/null
+++ b/target/linux/ath79/patches-4.19/0062-MIPS-pci-ar724x-add-QCA9550-reset-sequence.patch
@@ -0,0 +1,130 @@
+From: David Bauer <mail at david-bauer.net>
+Date: Sat, 11 Apr 2020 14:03:12 +0200
+Subject: MIPS: pci-ar724x: add QCA9550 reset sequence
+
+The QCA9550 family of SoCs have a slightly different reset
+sequence compared to older chips.
+
+Normally the bootloader performs this sequence, however
+some bootloader implementation expect the operating system
+to clear the reset.
+
+Also get the resets from OF to support handling of the second
+PCIe root-complex on the QCA9558.
+
+Signed-off-by: David Bauer <mail at david-bauer.net>
+
+--- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
++++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
+@@ -394,6 +394,7 @@
+ #define QCA955X_PLL_CPU_CONFIG_REG		0x00
+ #define QCA955X_PLL_DDR_CONFIG_REG		0x04
+ #define QCA955X_PLL_CLK_CTRL_REG		0x08
++#define QCA955X_PLL_PCIE_CONFIG_REG		0x0c
+ #define QCA955X_PLL_ETH_XMII_CONTROL_REG	0x28
+ #define QCA955X_PLL_ETH_SGMII_CONTROL_REG	0x48
+ #define QCA955X_PLL_ETH_SGMII_SERDES_REG	0x4c
+@@ -479,6 +480,9 @@
+ #define QCA956X_PLL_CLK_CTRL_CPU_DDRCLK_FROM_CPUPLL	BIT(21)
+ #define QCA956X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL		BIT(24)
+ 
++#define QCA955X_PLL_PCIE_CONFIG_PLL_PWD			BIT(30)
++#define QCA955X_PLL_PCIE_CONFIG_PLL_BYPASS		BIT(16)
++
+ #define QCA956X_PLL_SWITCH_CLOCK_SPARE_I2C_CLK_SELB		BIT(5)
+ #define QCA956X_PLL_SWITCH_CLOCK_SPARE_MDIO_CLK_SEL0_1		BIT(6)
+ #define QCA956X_PLL_SWITCH_CLOCK_SPARE_UART1_CLK_SEL		BIT(7)
+--- a/arch/mips/pci/pci-ar724x.c
++++ b/arch/mips/pci/pci-ar724x.c
+@@ -11,6 +11,7 @@
+ 
+ #include <linux/irq.h>
+ #include <linux/pci.h>
++#include <linux/reset.h>
+ #include <linux/init.h>
+ #include <linux/delay.h>
+ #include <linux/platform_device.h>
+@@ -58,6 +59,9 @@ struct ar724x_pci_controller {
+ 	struct irq_domain *domain;
+ 	struct resource io_res;
+ 	struct resource mem_res;
++
++	struct reset_control *hc_reset;
++	struct reset_control *phy_reset;
+ };
+ 
+ static struct irq_chip ar724x_pci_irq_chip;
+@@ -343,18 +347,30 @@ static void ar724x_pci_hw_init(struct ar
+ 	int wait = 0;
+ 
+ 	/* deassert PCIe host controller and PCIe PHY reset */
+-	ath79_device_reset_clear(AR724X_RESET_PCIE);
+-	ath79_device_reset_clear(AR724X_RESET_PCIE_PHY);
++	reset_control_deassert(apc->hc_reset);
++	reset_control_deassert(apc->phy_reset);
+ 
+-	/* remove the reset of the PCIE PLL */
+-	ppl = ath79_pll_rr(AR724X_PLL_REG_PCIE_CONFIG);
+-	ppl &= ~AR724X_PLL_REG_PCIE_CONFIG_PPL_RESET;
+-	ath79_pll_wr(AR724X_PLL_REG_PCIE_CONFIG, ppl);
+-
+-	/* deassert bypass for the PCIE PLL */
+-	ppl = ath79_pll_rr(AR724X_PLL_REG_PCIE_CONFIG);
+-	ppl &= ~AR724X_PLL_REG_PCIE_CONFIG_PPL_BYPASS;
+-	ath79_pll_wr(AR724X_PLL_REG_PCIE_CONFIG, ppl);
++	if (of_device_is_compatible(apc->np, "qcom,qca9550-pci")) {
++		/* remove the reset of the PCIE PLL */
++		ppl = ath79_pll_rr(QCA955X_PLL_PCIE_CONFIG_REG);
++		ppl &= ~QCA955X_PLL_PCIE_CONFIG_PLL_PWD;
++		ath79_pll_wr(QCA955X_PLL_PCIE_CONFIG_REG, ppl);
++
++		/* deassert bypass for the PCIE PLL */
++		ppl = ath79_pll_rr(QCA955X_PLL_PCIE_CONFIG_REG);
++		ppl &= ~QCA955X_PLL_PCIE_CONFIG_PLL_BYPASS;
++		ath79_pll_wr(QCA955X_PLL_PCIE_CONFIG_REG, ppl);
++	} else {
++		/* remove the reset of the PCIE PLL */
++		ppl = ath79_pll_rr(AR724X_PLL_REG_PCIE_CONFIG);
++		ppl &= ~AR724X_PLL_REG_PCIE_CONFIG_PPL_RESET;
++		ath79_pll_wr(AR724X_PLL_REG_PCIE_CONFIG, ppl);
++
++		/* deassert bypass for the PCIE PLL */
++		ppl = ath79_pll_rr(AR724X_PLL_REG_PCIE_CONFIG);
++		ppl &= ~AR724X_PLL_REG_PCIE_CONFIG_PPL_BYPASS;
++		ath79_pll_wr(AR724X_PLL_REG_PCIE_CONFIG, ppl);
++	}
+ 
+ 	/* set PCIE Application Control to ready */
+ 	app = __raw_readl(apc->ctrl_base + AR724X_PCI_REG_APP);
+@@ -402,6 +418,14 @@ static int ar724x_pci_probe(struct platf
+ 	if (apc->irq < 0)
+ 		return -EINVAL;
+ 
++	apc->hc_reset = devm_reset_control_get_exclusive(&pdev->dev, "hc");
++	if (IS_ERR(apc->hc_reset))
++		return PTR_ERR(apc->hc_reset);
++
++	apc->phy_reset = devm_reset_control_get_exclusive(&pdev->dev, "phy");
++	if (IS_ERR(apc->phy_reset))
++		return PTR_ERR(apc->phy_reset);
++
+ 	apc->np = pdev->dev.of_node;
+ 	apc->pci_controller.pci_ops = &ar724x_pci_ops;
+ 	apc->pci_controller.io_resource = &apc->io_res;
+@@ -412,7 +436,7 @@ static int ar724x_pci_probe(struct platf
+ 	 * Do the full PCIE Root Complex Initialization Sequence if the PCIe
+ 	 * host controller is in reset.
+ 	 */
+-	if (ath79_reset_rr(AR724X_RESET_REG_RESET_MODULE) & AR724X_RESET_PCIE)
++	if (reset_control_status(apc->hc_reset))
+ 		ar724x_pci_hw_init(apc);
+ 
+ 	apc->link_up = ar724x_pci_check_link(apc);
+@@ -430,6 +454,7 @@ static int ar724x_pci_probe(struct platf
+ 
+ static const struct of_device_id ar724x_pci_ids[] = {
+ 	{ .compatible = "qcom,ar7240-pci" },
++	{ .compatible = "qcom,qca9550-pci" },
+ 	{},
+ };
+ 
diff --git a/target/linux/ath79/patches-5.4/0062-MIPS-pci-ar724x-add-QCA9550-reset-sequence.patch b/target/linux/ath79/patches-5.4/0062-MIPS-pci-ar724x-add-QCA9550-reset-sequence.patch
new file mode 100644
index 0000000000..13955c62a2
--- /dev/null
+++ b/target/linux/ath79/patches-5.4/0062-MIPS-pci-ar724x-add-QCA9550-reset-sequence.patch
@@ -0,0 +1,130 @@
+From: David Bauer <mail at david-bauer.net>
+Date: Sat, 11 Apr 2020 14:03:12 +0200
+Subject: MIPS: pci-ar724x: add QCA9550 reset sequence
+
+The QCA9550 family of SoCs have a slightly different reset
+sequence compared to older chips.
+
+Normally the bootloader performs this sequence, however
+some bootloader implementation expect the operating system
+to clear the reset.
+
+Also get the resets from OF to support handling of the second
+PCIe root-complex on the QCA9558.
+
+Signed-off-by: David Bauer <mail at david-bauer.net>
+
+--- a/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
++++ b/arch/mips/include/asm/mach-ath79/ar71xx_regs.h
+@@ -391,6 +391,7 @@
+ #define QCA955X_PLL_CPU_CONFIG_REG		0x00
+ #define QCA955X_PLL_DDR_CONFIG_REG		0x04
+ #define QCA955X_PLL_CLK_CTRL_REG		0x08
++#define QCA955X_PLL_PCIE_CONFIG_REG		0x0c
+ #define QCA955X_PLL_ETH_XMII_CONTROL_REG	0x28
+ #define QCA955X_PLL_ETH_SGMII_CONTROL_REG	0x48
+ #define QCA955X_PLL_ETH_SGMII_SERDES_REG	0x4c
+@@ -476,6 +477,9 @@
+ #define QCA956X_PLL_CLK_CTRL_CPU_DDRCLK_FROM_CPUPLL	BIT(21)
+ #define QCA956X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL		BIT(24)
+ 
++#define QCA955X_PLL_PCIE_CONFIG_PLL_PWD			BIT(30)
++#define QCA955X_PLL_PCIE_CONFIG_PLL_BYPASS		BIT(16)
++
+ #define QCA956X_PLL_SWITCH_CLOCK_SPARE_I2C_CLK_SELB		BIT(5)
+ #define QCA956X_PLL_SWITCH_CLOCK_SPARE_MDIO_CLK_SEL0_1		BIT(6)
+ #define QCA956X_PLL_SWITCH_CLOCK_SPARE_UART1_CLK_SEL		BIT(7)
+--- a/arch/mips/pci/pci-ar724x.c
++++ b/arch/mips/pci/pci-ar724x.c
+@@ -8,6 +8,7 @@
+ 
+ #include <linux/irq.h>
+ #include <linux/pci.h>
++#include <linux/reset.h>
+ #include <linux/init.h>
+ #include <linux/delay.h>
+ #include <linux/platform_device.h>
+@@ -55,6 +56,9 @@ struct ar724x_pci_controller {
+ 	struct irq_domain *domain;
+ 	struct resource io_res;
+ 	struct resource mem_res;
++
++	struct reset_control *hc_reset;
++	struct reset_control *phy_reset;
+ };
+ 
+ static struct irq_chip ar724x_pci_irq_chip;
+@@ -340,18 +344,30 @@ static void ar724x_pci_hw_init(struct ar
+ 	int wait = 0;
+ 
+ 	/* deassert PCIe host controller and PCIe PHY reset */
+-	ath79_device_reset_clear(AR724X_RESET_PCIE);
+-	ath79_device_reset_clear(AR724X_RESET_PCIE_PHY);
++	reset_control_deassert(apc->hc_reset);
++	reset_control_deassert(apc->phy_reset);
+ 
+-	/* remove the reset of the PCIE PLL */
+-	ppl = ath79_pll_rr(AR724X_PLL_REG_PCIE_CONFIG);
+-	ppl &= ~AR724X_PLL_REG_PCIE_CONFIG_PPL_RESET;
+-	ath79_pll_wr(AR724X_PLL_REG_PCIE_CONFIG, ppl);
+-
+-	/* deassert bypass for the PCIE PLL */
+-	ppl = ath79_pll_rr(AR724X_PLL_REG_PCIE_CONFIG);
+-	ppl &= ~AR724X_PLL_REG_PCIE_CONFIG_PPL_BYPASS;
+-	ath79_pll_wr(AR724X_PLL_REG_PCIE_CONFIG, ppl);
++	if (of_device_is_compatible(apc->np, "qcom,qca9550-pci")) {
++		/* remove the reset of the PCIE PLL */
++		ppl = ath79_pll_rr(QCA955X_PLL_PCIE_CONFIG_REG);
++		ppl &= ~QCA955X_PLL_PCIE_CONFIG_PLL_PWD;
++		ath79_pll_wr(QCA955X_PLL_PCIE_CONFIG_REG, ppl);
++
++		/* deassert bypass for the PCIE PLL */
++		ppl = ath79_pll_rr(QCA955X_PLL_PCIE_CONFIG_REG);
++		ppl &= ~QCA955X_PLL_PCIE_CONFIG_PLL_BYPASS;
++		ath79_pll_wr(QCA955X_PLL_PCIE_CONFIG_REG, ppl);
++	} else {
++		/* remove the reset of the PCIE PLL */
++		ppl = ath79_pll_rr(AR724X_PLL_REG_PCIE_CONFIG);
++		ppl &= ~AR724X_PLL_REG_PCIE_CONFIG_PPL_RESET;
++		ath79_pll_wr(AR724X_PLL_REG_PCIE_CONFIG, ppl);
++
++		/* deassert bypass for the PCIE PLL */
++		ppl = ath79_pll_rr(AR724X_PLL_REG_PCIE_CONFIG);
++		ppl &= ~AR724X_PLL_REG_PCIE_CONFIG_PPL_BYPASS;
++		ath79_pll_wr(AR724X_PLL_REG_PCIE_CONFIG, ppl);
++	}
+ 
+ 	/* set PCIE Application Control to ready */
+ 	app = __raw_readl(apc->ctrl_base + AR724X_PCI_REG_APP);
+@@ -399,6 +415,14 @@ static int ar724x_pci_probe(struct platf
+ 	if (apc->irq < 0)
+ 		return -EINVAL;
+ 
++	apc->hc_reset = devm_reset_control_get_exclusive(&pdev->dev, "hc");
++	if (IS_ERR(apc->hc_reset))
++		return PTR_ERR(apc->hc_reset);
++
++	apc->phy_reset = devm_reset_control_get_exclusive(&pdev->dev, "phy");
++	if (IS_ERR(apc->phy_reset))
++		return PTR_ERR(apc->phy_reset);
++
+ 	apc->np = pdev->dev.of_node;
+ 	apc->pci_controller.pci_ops = &ar724x_pci_ops;
+ 	apc->pci_controller.io_resource = &apc->io_res;
+@@ -409,7 +433,7 @@ static int ar724x_pci_probe(struct platf
+ 	 * Do the full PCIE Root Complex Initialization Sequence if the PCIe
+ 	 * host controller is in reset.
+ 	 */
+-	if (ath79_reset_rr(AR724X_RESET_REG_RESET_MODULE) & AR724X_RESET_PCIE)
++	if (reset_control_status(apc->hc_reset))
+ 		ar724x_pci_hw_init(apc);
+ 
+ 	apc->link_up = ar724x_pci_check_link(apc);
+@@ -427,6 +451,7 @@ static int ar724x_pci_probe(struct platf
+ 
+ static const struct of_device_id ar724x_pci_ids[] = {
+ 	{ .compatible = "qcom,ar7240-pci" },
++	{ .compatible = "qcom,qca9550-pci" },
+ 	{},
+ };
+ 
-- 
2.26.0


_______________________________________________
openwrt-devel mailing list
openwrt-devel at lists.openwrt.org
https://lists.openwrt.org/mailman/listinfo/openwrt-devel



More information about the openwrt-devel mailing list