};
};
+ pcie_pins: pcie {
+ pcie_reset {
+ groups = "perst";
+ function = "perst";
+ };
+ };
+
refclk_pins: refclk {
refclk {
groups = "refclk";
pcie: pcie@10140000 {
compatible = "mediatek,mt7620-pci";
reg = <0x10140000 0x100
- 0x10142000 0x100>;
+ 0x10142000 0x8000>;
#address-cells = <3>;
#size-cells = <2>;
interrupt-parent = <&cpuintc>;
interrupts = <4>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pcie_pins>;
+
resets = <&sysc 26>;
reset-names = "pcie0";
--- /dev/null
+From: Shiji Yang <yangshiji66@outlook.com>
+Date: Mon, 17 Mar 2025 20:35:44 +0800
+Subject: [PATCH 1/3] mips: pci-mt7620: fix bridge register access
+
+Host bridge registers and PCI RC control registers have different
+memory base. pcie_m32() is used to write the RC control registers
+instead of bridge registers. This patch introduces bridge_m32()
+and use it to operate bridge registers to fix the access issue.
+
+Signed-off-by: Shiji Yang <yangshiji66@outlook.com>
+---
+ arch/mips/pci/pci-mt7620.c | 15 ++++++++++++---
+ 1 file changed, 12 insertions(+), 3 deletions(-)
+
+--- a/arch/mips/pci/pci-mt7620.c
++++ b/arch/mips/pci/pci-mt7620.c
+@@ -87,6 +87,15 @@ static inline u32 bridge_r32(unsigned re
+ return ioread32(bridge_base + reg);
+ }
+
++static inline void bridge_m32(u32 clr, u32 set, unsigned reg)
++{
++ u32 val = bridge_r32(reg);
++
++ val &= ~clr;
++ val |= set;
++ bridge_w32(val, reg);
++}
++
+ static inline void pcie_w32(u32 val, unsigned reg)
+ {
+ iowrite32(val, pcie_base + reg);
+@@ -228,7 +237,7 @@ static int mt7620_pci_hw_init(struct pla
+ pcie_phy(0x68, 0xB4);
+
+ /* put core into reset */
+- pcie_m32(0, PCIRST, RALINK_PCI_PCICFG_ADDR);
++ bridge_m32(PCIRST, PCIRST, RALINK_PCI_PCICFG_ADDR);
+ reset_control_assert(rstpcie0);
+
+ /* disable power and all clocks */
+@@ -318,7 +327,7 @@ static int mt7620_pci_probe(struct platf
+ mdelay(50);
+
+ /* enable write access */
+- pcie_m32(PCIRST, 0, RALINK_PCI_PCICFG_ADDR);
++ bridge_m32(PCIRST, 0, RALINK_PCI_PCICFG_ADDR);
+ mdelay(100);
+
+ /* check if there is a card present */
+@@ -340,7 +349,7 @@ static int mt7620_pci_probe(struct platf
+ pcie_w32(0x06040001, RALINK_PCI0_CLASS);
+
+ /* enable interrupts */
+- pcie_m32(0, PCIINT2, RALINK_PCI_PCIENA);
++ bridge_m32(PCIINT2, PCIINT2, RALINK_PCI_PCIENA);
+
+ /* voodoo from the SDK driver */
+ pci_config_read(NULL, 0, 4, 4, &val);
--- /dev/null
+From: Shiji Yang <yangshiji66@outlook.com>
+Date: Mon, 17 Mar 2025 20:54:24 +0800
+Subject: [PATCH 2/3] mips: pci-mt7620: add more register init values
+
+These missing register init values are ported from the vendor SDK.
+It should have some stability enhancements. Tested on both MT7620
+and MT7628.
+
+Signed-off-by: Shiji Yang <yangshiji66@outlook.com>
+---
+ arch/mips/pci/pci-mt7620.c | 59 +++++++++++++++++++++++++++++---------
+ 1 file changed, 46 insertions(+), 13 deletions(-)
+
+--- a/arch/mips/pci/pci-mt7620.c
++++ b/arch/mips/pci/pci-mt7620.c
+@@ -26,6 +26,8 @@
+
+ #define RALINK_INT_PCIE0 4
+
++#define RALINK_SYSCFG0 0x10
++#define RALINK_SYSCFG0_XTAL40 BIT(6)
+ #define RALINK_CLKCFG1 0x30
+ #define RALINK_GPIOMODE 0x60
+
+@@ -62,7 +64,7 @@
+
+ #define PCIEPHY0_CFG 0x90
+
+-#define RALINK_PCIEPHY_P0_CTL_OFFSET 0x7498
++#define RALINK_PCIEPHY_P0_CTL_OFFSET 0x7000
+ #define RALINK_PCIE0_CLK_EN BIT(26)
+
+ #define BUSY 0x80000000
+@@ -115,6 +117,14 @@ static inline void pcie_m32(u32 clr, u32
+ pcie_w32(val, reg);
+ }
+
++static inline void
++pcie_phyctrl_set(unsigned offset, u32 b_start, u32 bits, u32 val)
++{
++ pcie_m32(GENMASK(b_start + bits - 1, b_start),
++ val << b_start,
++ RALINK_PCIEPHY_P0_CTL_OFFSET + offset);
++}
++
+ static int wait_pciephy_busy(void)
+ {
+ unsigned long reg_value = 0x0, retry = 0;
+@@ -263,10 +273,8 @@ static int mt7620_pci_hw_init(struct pla
+ return 0;
+ }
+
+-static int mt7628_pci_hw_init(struct platform_device *pdev)
++static void mt7628_pci_hw_init(struct platform_device *pdev)
+ {
+- u32 val = 0;
+-
+ /* bring the core out of reset */
+ rt_sysc_m32(BIT(16), 0, RALINK_GPIOMODE);
+ reset_control_deassert(rstpcie0);
+@@ -276,14 +284,33 @@ static int mt7628_pci_hw_init(struct pla
+ mdelay(100);
+
+ /* voodoo from the SDK driver */
+- pcie_m32(~0xff, 0x5, RALINK_PCIEPHY_P0_CTL_OFFSET);
+-
+- pci_config_read(NULL, 0, 0x70c, 4, &val);
+- val &= ~(0xff) << 8;
+- val |= 0x50 << 8;
+- pci_config_write(NULL, 0, 0x70c, 4, val);
++ pcie_phyctrl_set(0x400, 8, 1, 0x1);
++ pcie_phyctrl_set(0x400, 9, 2, 0x0);
++ pcie_phyctrl_set(0x000, 4, 1, 0x1);
++ pcie_phyctrl_set(0x000, 5, 1, 0x0);
++ pcie_phyctrl_set(0x4ac, 16, 3, 0x3);
++
++ if (rt_sysc_r32(RALINK_SYSCFG0) & RALINK_SYSCFG0_XTAL40) {
++ pcie_phyctrl_set(0x4bc, 24, 8, 0x7d);
++ pcie_phyctrl_set(0x490, 12, 4, 0x08);
++ pcie_phyctrl_set(0x490, 6, 2, 0x01);
++ pcie_phyctrl_set(0x4c0, 0, 32, 0x1f400000);
++ pcie_phyctrl_set(0x4a4, 0, 16, 0x013d);
++ pcie_phyctrl_set(0x4a8, 16, 16, 0x74);
++ pcie_phyctrl_set(0x4a8, 0, 16, 0x74);
++ } else {
++ pcie_phyctrl_set(0x4bc, 24, 8, 0x64);
++ pcie_phyctrl_set(0x490, 12, 4, 0x0a);
++ pcie_phyctrl_set(0x490, 6, 2, 0x00);
++ pcie_phyctrl_set(0x4c0, 0, 32, 0x19000000);
++ pcie_phyctrl_set(0x4a4, 0, 16, 0x018d);
++ pcie_phyctrl_set(0x4a8, 16, 16, 0x4a);
++ pcie_phyctrl_set(0x4a8, 0, 16, 0x4a);
++ }
+
+- return 0;
++ pcie_phyctrl_set(0x498, 0, 8, 0x5);
++ pcie_phyctrl_set(0x000, 5, 1, 0x1);
++ pcie_phyctrl_set(0x000, 4, 1, 0x0);
+ }
+
+ static int mt7620_pci_probe(struct platform_device *pdev)
+@@ -316,8 +343,7 @@ static int mt7620_pci_probe(struct platf
+
+ case MT762X_SOC_MT7628AN:
+ case MT762X_SOC_MT7688:
+- if (mt7628_pci_hw_init(pdev))
+- return -1;
++ mt7628_pci_hw_init(pdev);
+ break;
+
+ default:
+@@ -336,6 +362,8 @@ static int mt7620_pci_probe(struct platf
+ rt_sysc_m32(RALINK_PCIE0_CLK_EN, 0, RALINK_CLKCFG1);
+ if (ralink_soc == MT762X_SOC_MT7620A)
+ rt_sysc_m32(LC_CKDRVPD, PDRV_SW_SET, PPLL_DRV);
++ else
++ pcie_phyctrl_set(0x000, 0, 32, 0x10);
+ dev_info(&pdev->dev, "PCIE0 no card, disable it(RST&CLK)\n");
+ return -1;
+ }
+@@ -355,6 +383,11 @@ static int mt7620_pci_probe(struct platf
+ pci_config_read(NULL, 0, 4, 4, &val);
+ pci_config_write(NULL, 0, 4, 4, val | 0x7);
+
++ pci_config_read(NULL, 0, 0x70c, 4, &val);
++ val &= ~(0xff) << 8;
++ val |= 0x50 << 8;
++ pci_config_write(NULL, 0, 0x70c, 4, val);
++
+ pci_load_of_ranges(&mt7620_controller, pdev->dev.of_node);
+ register_pci_controller(&mt7620_controller);
+
--- /dev/null
+From: Shiji Yang <yangshiji66@outlook.com>
+Date: Mon, 17 Mar 2025 23:55:24 +0800
+Subject: [PATCH 3/3] mips: pci-mt7620: rework initialization procedure
+
+Move the reset operation to the common part to reduce the code
+redundancy. They are actually the same and needed for all SoCs.
+Disabling power and clock are unnecessary for MT7620 and will be
+removed. In vendor SDK, it's used to save the power when the PCI
+driver is not selected. The MT7628 GPIO pinctrl has been removed
+because this should be done in device-tree. Some delay intervals
+have also been increased to follow the recommendations of the SoC
+SDK and datasheet. Tested on both MT7620 and MT7628.
+
+Signed-off-by: Shiji Yang <yangshiji66@outlook.com>
+---
+ arch/mips/pci/pci-mt7620.c | 38 +++++++++++++-------------------------
+ 1 file changed, 13 insertions(+), 25 deletions(-)
+
+--- a/arch/mips/pci/pci-mt7620.c
++++ b/arch/mips/pci/pci-mt7620.c
+@@ -29,7 +29,6 @@
+ #define RALINK_SYSCFG0 0x10
+ #define RALINK_SYSCFG0_XTAL40 BIT(6)
+ #define RALINK_CLKCFG1 0x30
+-#define RALINK_GPIOMODE 0x60
+
+ #define PPLL_CFG1 0x9c
+ #define PPLL_LD BIT(23)
+@@ -246,19 +245,6 @@ static int mt7620_pci_hw_init(struct pla
+ /* Elastic buffer control */
+ pcie_phy(0x68, 0xB4);
+
+- /* put core into reset */
+- bridge_m32(PCIRST, PCIRST, RALINK_PCI_PCICFG_ADDR);
+- reset_control_assert(rstpcie0);
+-
+- /* disable power and all clocks */
+- rt_sysc_m32(RALINK_PCIE0_CLK_EN, 0, RALINK_CLKCFG1);
+- rt_sysc_m32(LC_CKDRVPD, PDRV_SW_SET, PPLL_DRV);
+-
+- /* bring core out of reset */
+- reset_control_deassert(rstpcie0);
+- rt_sysc_m32(0, RALINK_PCIE0_CLK_EN, RALINK_CLKCFG1);
+- mdelay(100);
+-
+ if (!(rt_sysc_r32(PPLL_CFG1) & PPLL_LD)) {
+ dev_err(&pdev->dev, "pcie PLL not locked, aborting init\n");
+ reset_control_assert(rstpcie0);
+@@ -275,14 +261,6 @@ static int mt7620_pci_hw_init(struct pla
+
+ static void mt7628_pci_hw_init(struct platform_device *pdev)
+ {
+- /* bring the core out of reset */
+- rt_sysc_m32(BIT(16), 0, RALINK_GPIOMODE);
+- reset_control_deassert(rstpcie0);
+-
+- /* enable the pci clk */
+- rt_sysc_m32(0, RALINK_PCIE0_CLK_EN, RALINK_CLKCFG1);
+- mdelay(100);
+-
+ /* voodoo from the SDK driver */
+ pcie_phyctrl_set(0x400, 8, 1, 0x1);
+ pcie_phyctrl_set(0x400, 9, 2, 0x0);
+@@ -334,6 +312,16 @@ static int mt7620_pci_probe(struct platf
+ ioport_resource.start = 0;
+ ioport_resource.end = ~0;
+
++ /* reset PCIe controller */
++ reset_control_assert(rstpcie0);
++ msleep(100);
++ reset_control_deassert(rstpcie0);
++ rt_sysc_m32(0, RALINK_PCIE0_CLK_EN, RALINK_CLKCFG1);
++ msleep(100);
++
++ /* assert PERST_N pin */
++ bridge_m32(PCIRST, PCIRST, RALINK_PCI_PCICFG_ADDR);
++
+ /* bring up the pci core */
+ switch (ralink_soc) {
+ case MT762X_SOC_MT7620A:
+@@ -350,11 +338,11 @@ static int mt7620_pci_probe(struct platf
+ dev_err(&pdev->dev, "pcie is not supported on this hardware\n");
+ return -1;
+ }
+- mdelay(50);
++ msleep(500);
+
+- /* enable write access */
++ /* deassert PERST_N pin and wait PCIe peripheral init */
+ bridge_m32(PCIRST, 0, RALINK_PCI_PCICFG_ADDR);
+- mdelay(100);
++ msleep(1000);
+
+ /* check if there is a card present */
+ if ((pcie_r32(RALINK_PCI0_STATUS) & PCIE_LINK_UP_ST) == 0) {
--- /dev/null
+From: Shiji Yang <yangshiji66@outlook.com>
+Date: Mon, 17 Mar 2025 20:35:44 +0800
+Subject: [PATCH 1/3] mips: pci-mt7620: fix bridge register access
+
+Host bridge registers and PCI RC control registers have different
+memory base. pcie_m32() is used to write the RC control registers
+instead of bridge registers. This patch introduces bridge_m32()
+and use it to operate bridge registers to fix the access issue.
+
+Signed-off-by: Shiji Yang <yangshiji66@outlook.com>
+---
+ arch/mips/pci/pci-mt7620.c | 15 ++++++++++++---
+ 1 file changed, 12 insertions(+), 3 deletions(-)
+
+--- a/arch/mips/pci/pci-mt7620.c
++++ b/arch/mips/pci/pci-mt7620.c
+@@ -87,6 +87,15 @@ static inline u32 bridge_r32(unsigned re
+ return ioread32(bridge_base + reg);
+ }
+
++static inline void bridge_m32(u32 clr, u32 set, unsigned reg)
++{
++ u32 val = bridge_r32(reg);
++
++ val &= ~clr;
++ val |= set;
++ bridge_w32(val, reg);
++}
++
+ static inline void pcie_w32(u32 val, unsigned reg)
+ {
+ iowrite32(val, pcie_base + reg);
+@@ -228,7 +237,7 @@ static int mt7620_pci_hw_init(struct pla
+ pcie_phy(0x68, 0xB4);
+
+ /* put core into reset */
+- pcie_m32(0, PCIRST, RALINK_PCI_PCICFG_ADDR);
++ bridge_m32(PCIRST, PCIRST, RALINK_PCI_PCICFG_ADDR);
+ reset_control_assert(rstpcie0);
+
+ /* disable power and all clocks */
+@@ -318,7 +327,7 @@ static int mt7620_pci_probe(struct platf
+ mdelay(50);
+
+ /* enable write access */
+- pcie_m32(PCIRST, 0, RALINK_PCI_PCICFG_ADDR);
++ bridge_m32(PCIRST, 0, RALINK_PCI_PCICFG_ADDR);
+ mdelay(100);
+
+ /* check if there is a card present */
+@@ -340,7 +349,7 @@ static int mt7620_pci_probe(struct platf
+ pcie_w32(0x06040001, RALINK_PCI0_CLASS);
+
+ /* enable interrupts */
+- pcie_m32(0, PCIINT2, RALINK_PCI_PCIENA);
++ bridge_m32(PCIINT2, PCIINT2, RALINK_PCI_PCIENA);
+
+ /* voodoo from the SDK driver */
+ pci_config_read(NULL, 0, 4, 4, &val);
--- /dev/null
+From: Shiji Yang <yangshiji66@outlook.com>
+Date: Mon, 17 Mar 2025 20:54:24 +0800
+Subject: [PATCH 2/3] mips: pci-mt7620: add more register init values
+
+These missing register init values are ported from the vendor SDK.
+It should have some stability enhancements. Tested on both MT7620
+and MT7628.
+
+Signed-off-by: Shiji Yang <yangshiji66@outlook.com>
+---
+ arch/mips/pci/pci-mt7620.c | 59 +++++++++++++++++++++++++++++---------
+ 1 file changed, 46 insertions(+), 13 deletions(-)
+
+--- a/arch/mips/pci/pci-mt7620.c
++++ b/arch/mips/pci/pci-mt7620.c
+@@ -26,6 +26,8 @@
+
+ #define RALINK_INT_PCIE0 4
+
++#define RALINK_SYSCFG0 0x10
++#define RALINK_SYSCFG0_XTAL40 BIT(6)
+ #define RALINK_CLKCFG1 0x30
+ #define RALINK_GPIOMODE 0x60
+
+@@ -62,7 +64,7 @@
+
+ #define PCIEPHY0_CFG 0x90
+
+-#define RALINK_PCIEPHY_P0_CTL_OFFSET 0x7498
++#define RALINK_PCIEPHY_P0_CTL_OFFSET 0x7000
+ #define RALINK_PCIE0_CLK_EN BIT(26)
+
+ #define BUSY 0x80000000
+@@ -115,6 +117,14 @@ static inline void pcie_m32(u32 clr, u32
+ pcie_w32(val, reg);
+ }
+
++static inline void
++pcie_phyctrl_set(unsigned offset, u32 b_start, u32 bits, u32 val)
++{
++ pcie_m32(GENMASK(b_start + bits - 1, b_start),
++ val << b_start,
++ RALINK_PCIEPHY_P0_CTL_OFFSET + offset);
++}
++
+ static int wait_pciephy_busy(void)
+ {
+ unsigned long reg_value = 0x0, retry = 0;
+@@ -263,10 +273,8 @@ static int mt7620_pci_hw_init(struct pla
+ return 0;
+ }
+
+-static int mt7628_pci_hw_init(struct platform_device *pdev)
++static void mt7628_pci_hw_init(struct platform_device *pdev)
+ {
+- u32 val = 0;
+-
+ /* bring the core out of reset */
+ rt_sysc_m32(BIT(16), 0, RALINK_GPIOMODE);
+ reset_control_deassert(rstpcie0);
+@@ -276,14 +284,33 @@ static int mt7628_pci_hw_init(struct pla
+ mdelay(100);
+
+ /* voodoo from the SDK driver */
+- pcie_m32(~0xff, 0x5, RALINK_PCIEPHY_P0_CTL_OFFSET);
+-
+- pci_config_read(NULL, 0, 0x70c, 4, &val);
+- val &= ~(0xff) << 8;
+- val |= 0x50 << 8;
+- pci_config_write(NULL, 0, 0x70c, 4, val);
++ pcie_phyctrl_set(0x400, 8, 1, 0x1);
++ pcie_phyctrl_set(0x400, 9, 2, 0x0);
++ pcie_phyctrl_set(0x000, 4, 1, 0x1);
++ pcie_phyctrl_set(0x000, 5, 1, 0x0);
++ pcie_phyctrl_set(0x4ac, 16, 3, 0x3);
++
++ if (rt_sysc_r32(RALINK_SYSCFG0) & RALINK_SYSCFG0_XTAL40) {
++ pcie_phyctrl_set(0x4bc, 24, 8, 0x7d);
++ pcie_phyctrl_set(0x490, 12, 4, 0x08);
++ pcie_phyctrl_set(0x490, 6, 2, 0x01);
++ pcie_phyctrl_set(0x4c0, 0, 32, 0x1f400000);
++ pcie_phyctrl_set(0x4a4, 0, 16, 0x013d);
++ pcie_phyctrl_set(0x4a8, 16, 16, 0x74);
++ pcie_phyctrl_set(0x4a8, 0, 16, 0x74);
++ } else {
++ pcie_phyctrl_set(0x4bc, 24, 8, 0x64);
++ pcie_phyctrl_set(0x490, 12, 4, 0x0a);
++ pcie_phyctrl_set(0x490, 6, 2, 0x00);
++ pcie_phyctrl_set(0x4c0, 0, 32, 0x19000000);
++ pcie_phyctrl_set(0x4a4, 0, 16, 0x018d);
++ pcie_phyctrl_set(0x4a8, 16, 16, 0x4a);
++ pcie_phyctrl_set(0x4a8, 0, 16, 0x4a);
++ }
+
+- return 0;
++ pcie_phyctrl_set(0x498, 0, 8, 0x5);
++ pcie_phyctrl_set(0x000, 5, 1, 0x1);
++ pcie_phyctrl_set(0x000, 4, 1, 0x0);
+ }
+
+ static int mt7620_pci_probe(struct platform_device *pdev)
+@@ -316,8 +343,7 @@ static int mt7620_pci_probe(struct platf
+
+ case MT762X_SOC_MT7628AN:
+ case MT762X_SOC_MT7688:
+- if (mt7628_pci_hw_init(pdev))
+- return -1;
++ mt7628_pci_hw_init(pdev);
+ break;
+
+ default:
+@@ -336,6 +362,8 @@ static int mt7620_pci_probe(struct platf
+ rt_sysc_m32(RALINK_PCIE0_CLK_EN, 0, RALINK_CLKCFG1);
+ if (ralink_soc == MT762X_SOC_MT7620A)
+ rt_sysc_m32(LC_CKDRVPD, PDRV_SW_SET, PPLL_DRV);
++ else
++ pcie_phyctrl_set(0x000, 0, 32, 0x10);
+ dev_info(&pdev->dev, "PCIE0 no card, disable it(RST&CLK)\n");
+ return -1;
+ }
+@@ -355,6 +383,11 @@ static int mt7620_pci_probe(struct platf
+ pci_config_read(NULL, 0, 4, 4, &val);
+ pci_config_write(NULL, 0, 4, 4, val | 0x7);
+
++ pci_config_read(NULL, 0, 0x70c, 4, &val);
++ val &= ~(0xff) << 8;
++ val |= 0x50 << 8;
++ pci_config_write(NULL, 0, 0x70c, 4, val);
++
+ pci_load_of_ranges(&mt7620_controller, pdev->dev.of_node);
+ register_pci_controller(&mt7620_controller);
+
--- /dev/null
+From: Shiji Yang <yangshiji66@outlook.com>
+Date: Mon, 17 Mar 2025 23:55:24 +0800
+Subject: [PATCH 3/3] mips: pci-mt7620: rework initialization procedure
+
+Move the reset operation to the common part to reduce the code
+redundancy. They are actually the same and needed for all SoCs.
+Disabling power and clock are unnecessary for MT7620 and will be
+removed. In vendor SDK, it's used to save the power when the PCI
+driver is not selected. The MT7628 GPIO pinctrl has been removed
+because this should be done in device-tree. Some delay intervals
+have also been increased to follow the recommendations of the SoC
+SDK and datasheet. Tested on both MT7620 and MT7628.
+
+Signed-off-by: Shiji Yang <yangshiji66@outlook.com>
+---
+ arch/mips/pci/pci-mt7620.c | 38 +++++++++++++-------------------------
+ 1 file changed, 13 insertions(+), 25 deletions(-)
+
+--- a/arch/mips/pci/pci-mt7620.c
++++ b/arch/mips/pci/pci-mt7620.c
+@@ -29,7 +29,6 @@
+ #define RALINK_SYSCFG0 0x10
+ #define RALINK_SYSCFG0_XTAL40 BIT(6)
+ #define RALINK_CLKCFG1 0x30
+-#define RALINK_GPIOMODE 0x60
+
+ #define PPLL_CFG1 0x9c
+ #define PPLL_LD BIT(23)
+@@ -246,19 +245,6 @@ static int mt7620_pci_hw_init(struct pla
+ /* Elastic buffer control */
+ pcie_phy(0x68, 0xB4);
+
+- /* put core into reset */
+- bridge_m32(PCIRST, PCIRST, RALINK_PCI_PCICFG_ADDR);
+- reset_control_assert(rstpcie0);
+-
+- /* disable power and all clocks */
+- rt_sysc_m32(RALINK_PCIE0_CLK_EN, 0, RALINK_CLKCFG1);
+- rt_sysc_m32(LC_CKDRVPD, PDRV_SW_SET, PPLL_DRV);
+-
+- /* bring core out of reset */
+- reset_control_deassert(rstpcie0);
+- rt_sysc_m32(0, RALINK_PCIE0_CLK_EN, RALINK_CLKCFG1);
+- mdelay(100);
+-
+ if (!(rt_sysc_r32(PPLL_CFG1) & PPLL_LD)) {
+ dev_err(&pdev->dev, "pcie PLL not locked, aborting init\n");
+ reset_control_assert(rstpcie0);
+@@ -275,14 +261,6 @@ static int mt7620_pci_hw_init(struct pla
+
+ static void mt7628_pci_hw_init(struct platform_device *pdev)
+ {
+- /* bring the core out of reset */
+- rt_sysc_m32(BIT(16), 0, RALINK_GPIOMODE);
+- reset_control_deassert(rstpcie0);
+-
+- /* enable the pci clk */
+- rt_sysc_m32(0, RALINK_PCIE0_CLK_EN, RALINK_CLKCFG1);
+- mdelay(100);
+-
+ /* voodoo from the SDK driver */
+ pcie_phyctrl_set(0x400, 8, 1, 0x1);
+ pcie_phyctrl_set(0x400, 9, 2, 0x0);
+@@ -334,6 +312,16 @@ static int mt7620_pci_probe(struct platf
+ ioport_resource.start = 0;
+ ioport_resource.end = ~0;
+
++ /* reset PCIe controller */
++ reset_control_assert(rstpcie0);
++ msleep(100);
++ reset_control_deassert(rstpcie0);
++ rt_sysc_m32(0, RALINK_PCIE0_CLK_EN, RALINK_CLKCFG1);
++ msleep(100);
++
++ /* assert PERST_N pin */
++ bridge_m32(PCIRST, PCIRST, RALINK_PCI_PCICFG_ADDR);
++
+ /* bring up the pci core */
+ switch (ralink_soc) {
+ case MT762X_SOC_MT7620A:
+@@ -350,11 +338,11 @@ static int mt7620_pci_probe(struct platf
+ dev_err(&pdev->dev, "pcie is not supported on this hardware\n");
+ return -1;
+ }
+- mdelay(50);
++ msleep(500);
+
+- /* enable write access */
++ /* deassert PERST_N pin and wait PCIe peripheral init */
+ bridge_m32(PCIRST, 0, RALINK_PCI_PCICFG_ADDR);
+- mdelay(100);
++ msleep(1000);
+
+ /* check if there is a card present */
+ if ((pcie_r32(RALINK_PCI0_STATUS) & PCIE_LINK_UP_ST) == 0) {