131 lines
4.5 KiB
Diff
131 lines
4.5 KiB
Diff
From: David Bauer <mail@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@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);
|
|
@@ -396,6 +412,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;
|
|
@@ -406,7 +430,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);
|
|
@@ -424,6 +448,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" },
|
|
{},
|
|
};
|
|
|