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