| 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); |
| @@ -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" }, |
| {}, |
| }; |
| |