From: Rosy Song <rosys...@rosinson.com>

QCA9563 is CPU used on AP152 board :

    Clock speed : 750 MHz ,
    Arch :  Mips 74Kc,
    Eth : SGMII interface,
    MIMO config : 3 * 3 450M,
    2 * USB 2.0,

Signed-off-by: Rosy Song <rosys...@rosinson.com>

Changes for v2:
   - coding Style cleanup
   - remove ununsed flash chip in defconfig
   - enable automatic icache / dcache size in defconfig

Changes for v3:
   - add detailed information for qca956x in commit message
---
 arch/mips/dts/Makefile                        |   1 +
 arch/mips/dts/ap152.dts                       |  48 ++
 arch/mips/dts/qca956x.dtsi                    |  87 ++++
 arch/mips/mach-ath79/Kconfig                  |  14 +
 arch/mips/mach-ath79/Makefile                 |   1 +
 .../mach-ath79/include/mach/ar71xx_regs.h     |  73 +++
 arch/mips/mach-ath79/include/mach/ath79.h     |   3 +
 arch/mips/mach-ath79/qca956x/Makefile         |   5 +
 arch/mips/mach-ath79/qca956x/clk.c            | 419 ++++++++++++++++++
 arch/mips/mach-ath79/qca956x/cpu.c            |   9 +
 arch/mips/mach-ath79/qca956x/ddr.c            | 308 +++++++++++++
 .../mips/mach-ath79/qca956x/qca956x-ddr-tap.S | 193 ++++++++
 arch/mips/mach-ath79/reset.c                  | 271 +++++++++++
 board/qca/ap152/Kconfig                       |  15 +
 board/qca/ap152/MAINTAINERS                   |   6 +
 board/qca/ap152/Makefile                      |   3 +
 board/qca/ap152/ap152.c                       |  81 ++++
 configs/ap152_defconfig                       |  49 ++
 include/configs/ap152.h                       |  54 +++
 19 files changed, 1640 insertions(+)
 create mode 100644 arch/mips/dts/ap152.dts
 create mode 100644 arch/mips/dts/qca956x.dtsi
 create mode 100644 arch/mips/mach-ath79/qca956x/Makefile
 create mode 100644 arch/mips/mach-ath79/qca956x/clk.c
 create mode 100644 arch/mips/mach-ath79/qca956x/cpu.c
 create mode 100644 arch/mips/mach-ath79/qca956x/ddr.c
 create mode 100644 arch/mips/mach-ath79/qca956x/qca956x-ddr-tap.S
 create mode 100644 board/qca/ap152/Kconfig
 create mode 100644 board/qca/ap152/MAINTAINERS
 create mode 100644 board/qca/ap152/Makefile
 create mode 100644 board/qca/ap152/ap152.c
 create mode 100644 configs/ap152_defconfig
 create mode 100644 include/configs/ap152.h

diff --git a/arch/mips/dts/Makefile b/arch/mips/dts/Makefile
index b94b582837..621c35f0ef 100644
--- a/arch/mips/dts/Makefile
+++ b/arch/mips/dts/Makefile
@@ -2,6 +2,7 @@
 
 dtb-$(CONFIG_TARGET_AP121) += ap121.dtb
 dtb-$(CONFIG_TARGET_AP143) += ap143.dtb
+dtb-$(CONFIG_TARGET_AP152) += ap152.dtb
 dtb-$(CONFIG_TARGET_BOSTON) += img,boston.dtb
 dtb-$(CONFIG_TARGET_MALTA) += mti,malta.dtb
 dtb-$(CONFIG_TARGET_PIC32MZDASK) += pic32mzda_sk.dtb
diff --git a/arch/mips/dts/ap152.dts b/arch/mips/dts/ap152.dts
new file mode 100644
index 0000000000..1722290c73
--- /dev/null
+++ b/arch/mips/dts/ap152.dts
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Rosy Song <rosys...@rosinson.com>
+ */
+
+/dts-v1/;
+#include "qca956x.dtsi"
+
+/ {
+       model = "AP152 Reference Board";
+       compatible = "qca,ap152", "qca,qca956x";
+
+       aliases {
+               spi0 = &spi0;
+               serial0 = &uart0;
+       };
+
+       chosen {
+               stdout-path = "serial0:115200n8";
+       };
+};
+
+&gmac0 {
+       phy-mode = "sgmii";
+       status = "okay";
+};
+
+&xtal {
+       clock-frequency = <25000000>;
+};
+
+&uart0 {
+       clock-frequency = <25000000>;
+       status = "okay";
+};
+
+&spi0 {
+       spi-max-frequency = <25000000>;
+       status = "okay";
+       spi-flash@0 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "spi-flash";
+               memory-map = <0x9f000000 0x01000000>;
+               spi-max-frequency = <25000000>;
+               reg = <0>;
+       };
+};
diff --git a/arch/mips/dts/qca956x.dtsi b/arch/mips/dts/qca956x.dtsi
new file mode 100644
index 0000000000..6cb360b3f8
--- /dev/null
+++ b/arch/mips/dts/qca956x.dtsi
@@ -0,0 +1,87 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Rosy Song <rosys...@rosinson.com>
+ */
+
+#include "skeleton.dtsi"
+
+/ {
+       compatible = "qca,qca956x";
+
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               cpu@0 {
+                       device_type = "cpu";
+                       compatible = "mips,mips74Kc";
+                       reg = <0>;
+               };
+       };
+
+       clocks {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
+
+               xtal: xtal {
+                       #clock-cells = <0>;
+                       compatible = "fixed-clock";
+                       clock-output-names = "xtal";
+               };
+       };
+
+       ahb {
+               compatible = "simple-bus";
+               ranges;
+
+               #address-cells = <1>;
+               #size-cells = <1>;
+
+               apb {
+                       compatible = "simple-bus";
+                       ranges;
+
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+
+                       uart0: uart@18020000 {
+                               compatible = "ns16550";
+                               reg = <0x18020000 0x20>;
+                               reg-shift = <2>;
+
+                               status = "disabled";
+                       };
+
+                       gmac0: eth@0x19000000 {
+                               compatible = "qca,ag956x-mac";
+                               reg = <0x19000000 0x200>;
+                               phy = <&phy0>;
+                               phy-mode = "sgmii";
+
+                               status = "disabled";
+
+                               mdio {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       phy0: ethernet-phy@0 {
+                                               reg = <0>;
+                                       };
+                               };
+                       };
+               };
+
+               spi0: spi@1f000000 {
+                       compatible = "qca,ar7100-spi";
+                       reg = <0x1f000000 0x10>;
+
+                       status = "disabled";
+
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+       };
+};
diff --git a/arch/mips/mach-ath79/Kconfig b/arch/mips/mach-ath79/Kconfig
index bc86f591df..bdb23b5765 100644
--- a/arch/mips/mach-ath79/Kconfig
+++ b/arch/mips/mach-ath79/Kconfig
@@ -33,6 +33,15 @@ config SOC_QCA953X
        help
          This supports QCA/Atheros qca953x family SOCs.
 
+config SOC_QCA956X
+       bool
+       select MIPS_TUNE_74KC
+       select SUPPORTS_BIG_ENDIAN
+       select SUPPORTS_CPU_MIPS32_R1
+       select SUPPORTS_CPU_MIPS32_R2
+       help
+         This supports QCA/Atheros qca956x family SOCs.
+
 choice
        prompt "Board select"
 
@@ -44,6 +53,10 @@ config TARGET_AP143
        bool "AP143 Reference Board"
        select SOC_QCA953X
 
+config TARGET_AP152
+       bool "AP152 Reference Board"
+       select SOC_QCA956X
+
 config BOARD_TPLINK_WDR4300
        bool "TP-Link WDR4300 Board"
        select SOC_AR934X
@@ -52,6 +65,7 @@ endchoice
 
 source "board/qca/ap121/Kconfig"
 source "board/qca/ap143/Kconfig"
+source "board/qca/ap152/Kconfig"
 source "board/tplink/wdr4300/Kconfig"
 
 endmenu
diff --git a/arch/mips/mach-ath79/Makefile b/arch/mips/mach-ath79/Makefile
index 7aa40c65d3..fbd40c02be 100644
--- a/arch/mips/mach-ath79/Makefile
+++ b/arch/mips/mach-ath79/Makefile
@@ -7,3 +7,4 @@ obj-y += dram.o
 obj-$(CONFIG_SOC_AR933X)       += ar933x/
 obj-$(CONFIG_SOC_AR934X)       += ar934x/
 obj-$(CONFIG_SOC_QCA953X)      += qca953x/
+obj-$(CONFIG_SOC_QCA956X)      += qca956x/
diff --git a/arch/mips/mach-ath79/include/mach/ar71xx_regs.h 
b/arch/mips/mach-ath79/include/mach/ar71xx_regs.h
index 5d371bb582..7cd16b8d81 100644
--- a/arch/mips/mach-ath79/include/mach/ar71xx_regs.h
+++ b/arch/mips/mach-ath79/include/mach/ar71xx_regs.h
@@ -194,6 +194,9 @@
 #define QCA956X_WMAC_BASE \
        (AR71XX_APB_BASE + 0x00100000)
 #define QCA956X_WMAC_SIZE                              0x20000
+#define QCA956X_RTC_BASE \
+       (AR71XX_APB_BASE + 0x00107000)
+#define QCA956X_RTC_SIZE                                       0x1000
 #define QCA956X_EHCI0_BASE                             0x1b000000
 #define QCA956X_EHCI1_BASE                             0x1b400000
 #define QCA956X_EHCI_SIZE                              0x200
@@ -201,6 +204,10 @@
        (AR71XX_APB_BASE + 0x00070000)
 #define QCA956X_GMAC_SIZE                              0x64
 
+#define QCA956X_SRIF_BASE \
+       (AR71XX_APB_BASE + 0x00116000)
+#define QCA956X_SRIF_SIZE                              0x1000
+
 /*
  * DDR_CTRL block
  */
@@ -278,6 +285,18 @@
 #define QCA953X_DDR_REG_CTL_CONF                       0x108
 #define QCA953X_DDR_REG_CONFIG3                                0x15c
 
+#define QCA956X_DDR_REG_TAP_CTRL2                      0x24
+#define QCA956X_DDR_REG_TAP_CTRL3                      0x28
+#define QCA956X_DDR_REG_DDR2_CONFIG                    0xb8
+#define QCA956X_DDR_REG_DDR2_EMR2                      0xbc
+#define QCA956X_DDR_REG_DDR2_EMR3                      0xc0
+#define QCA956X_DDR_REG_BURST                          0xc4
+#define QCA956X_DDR_REG_BURST2                         0xc8
+#define QCA956X_DDR_REG_TIMEOUT_MAX                    0xcc
+#define QCA956X_DDR_REG_FSM_WAIT_CTRL                  0xe4
+#define QCA956X_DDR_REG_CTL_CONF                       0x108
+#define QCA956X_DDR_REG_DDR3_CONFIG                    0x15c
+
 /*
  * PLL block
  */
@@ -519,6 +538,13 @@
 #define QCA956X_PLL_DDR_CONFIG_REG                     0x08
 #define QCA956X_PLL_DDR_CONFIG1_REG                    0x0c
 #define QCA956X_PLL_CLK_CTRL_REG                       0x10
+#define QCA956X_PLL_SWITCH_CLK_CTRL_REG                        0x28
+#define QCA956X_PLL_ETH_XMII_CTRL_REG                  0x30
+#define QCA956X_PLL_DDR_DIT_FRAC_REG                   0x38
+#define QCA956X_PLL_DDR_DIT2_FRAC_REG                  0x3c
+#define QCA956X_PLL_CPU_DIT_FRAC_REG                   0x40
+#define QCA956X_PLL_CPU_DIT2_FRAC_REG                  0x44
+#define QCA956X_PLL_ETH_SGMII_SERDES_REG               0x4c
 
 #define QCA956X_PLL_CPU_CONFIG_REFDIV_SHIFT            12
 #define QCA956X_PLL_CPU_CONFIG_REFDIV_MASK             0x1f
@@ -756,6 +782,17 @@
 #define QCA955X_RESET_MBOX                             BIT(1)
 #define QCA955X_RESET_I2S                              BIT(0)
 
+#define QCA956X_RESET_EXTERNAL                         BIT(28)
+#define QCA956X_RESET_FULL_CHIP                                BIT(24)
+#define QCA956X_RESET_GE1_MDIO                         BIT(23) /* Reserved in 
datasheet */
+#define QCA956X_RESET_GE0_MDIO                         BIT(22)
+#define QCA956X_RESET_GE1_MAC                          BIT(13) /* Reserved in 
datasheet */
+#define QCA956X_RESET_SGMII_ASSERT                     BIT(12)
+#define QCA956X_RESET_GE0_MAC                          BIT(9)
+#define QCA956X_RESET_SGMII                            BIT(8)
+#define QCA956X_RESET_SGMII_ANALOG                             BIT(2)
+#define QCA956X_RESET_SWITCH                           BIT(0)
+
 #define AR933X_BOOTSTRAP_MDIO_GPIO_EN                  BIT(18)
 #define AR933X_BOOTSTRAP_DDR2                          BIT(13)
 #define AR933X_BOOTSTRAP_EEPBUSY                       BIT(4)
@@ -1099,8 +1136,12 @@
 #define QCA953X_GPIO_IN_MUX_UART0_SIN                  9
 #define QCA953X_GPIO_IN_MUX_SPI_DATA_IN                        8
 
+#define QCA956X_GPIO(x)                                        BIT(x)
+#define QCA956X_GPIO_MUX_MASK(x)                       (0xff << (x))
 #define QCA956X_GPIO_OUT_MUX_GE0_MDO                   32
 #define QCA956X_GPIO_OUT_MUX_GE0_MDC                   33
+#define QCA956X_GPIO_IN_MUX_UART0_SIN                  0x12
+#define QCA956X_GPIO_OUT_MUX_UART0_SOUT                        0x16
 
 #define AR71XX_GPIO_COUNT                              16
 #define AR7240_GPIO_COUNT                              18
@@ -1179,6 +1220,25 @@
 #define QCA953X_SRIF_DPLL2_OUTDIV_SHIFT                        13
 #define QCA953X_SRIF_DPLL2_OUTDIV_MASK                 0x7
 
+#define QCA956X_SRIF_BB_DPLL1_REG                      0x180
+#define QCA956X_SRIF_BB_DPLL2_REG                      0x184
+#define QCA956X_SRIF_BB_DPLL3_REG                      0x188
+
+#define QCA956X_SRIF_CPU_DPLL1_REG                     0xf00
+#define QCA956X_SRIF_CPU_DPLL2_REG                     0xf04
+#define QCA956X_SRIF_CPU_DPLL3_REG                     0xf08
+
+#define QCA956X_SRIF_DDR_DPLL1_REG                     0xec0
+#define QCA956X_SRIF_DDR_DPLL2_REG                     0xec4
+#define QCA956X_SRIF_DDR_DPLL3_REG                     0xec8
+
+#define QCA956X_SRIF_PCIE_DPLL1_REG                    0xc80
+#define QCA956X_SRIF_PCIE_DPLL2_REG                    0xc84
+#define QCA956X_SRIF_PCIE_DPLL3_REG                    0xc88
+
+#define QCA956X_SRIF_PMU1_REG                          0xcc0
+#define QCA956X_SRIF_PMU2_REG                          0xcc4
+
 /*
  * MII_CTRL block
  */
@@ -1261,4 +1321,17 @@
 #define QCA955X_ETH_CFG_RGMII_EN                       BIT(0)
 #define QCA955X_ETH_CFG_GE0_SGMII                      BIT(6)
 
+/*
+ * QCA956X GMAC Interface
+ */
+
+#define QCA956X_GMAC_REG_ETH_CFG                       0x00
+#define QCA956X_GMAC_REG_SGMII_RESET                   0x14
+#define QCA956X_GMAC_REG_SGMII_SERDES                  0x18
+#define QCA956X_GMAC_REG_MR_AN_CTRL                    0x1c
+#define QCA956X_GMAC_REG_SGMII_CONFIG                  0x34
+#define QCA956X_GMAC_REG_SGMII_DEBUG                   0x58
+
+#define QCA956X_ETH_CFG_GE0_SGMII                      BIT(6)
+
 #endif /* __ASM_AR71XX_H */
diff --git a/arch/mips/mach-ath79/include/mach/ath79.h 
b/arch/mips/mach-ath79/include/mach/ath79.h
index 5de7a43f79..0fde5079b1 100644
--- a/arch/mips/mach-ath79/include/mach/ath79.h
+++ b/arch/mips/mach-ath79/include/mach/ath79.h
@@ -2,6 +2,7 @@
 /*
  * Atheros AR71XX/AR724X/AR913X common definitions
  *
+ * Copyright (C) 2018-2019 Rosy Song <rosys...@rosinson.com>
  * Copyright (C) 2015-2016 Wills Wang <wills.w...@live.com>
  * Copyright (C) 2008-2011 Gabor Juhos <juh...@openwrt.org>
  * Copyright (C) 2008 Imre Kaloz <ka...@openwrt.org>
@@ -146,4 +147,6 @@ int ath79_usb_reset(void);
 void ar934x_pll_init(const u16 cpu_mhz, const u16 ddr_mhz, const u16 ahb_mhz);
 void ar934x_ddr_init(const u16 cpu_mhz, const u16 ddr_mhz, const u16 ahb_mhz);
 
+void qca956x_pll_init(void);
+void qca956x_ddr_init(void);
 #endif /* __ASM_MACH_ATH79_H */
diff --git a/arch/mips/mach-ath79/qca956x/Makefile 
b/arch/mips/mach-ath79/qca956x/Makefile
new file mode 100644
index 0000000000..3f5fc0363f
--- /dev/null
+++ b/arch/mips/mach-ath79/qca956x/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+obj-y += cpu.o
+obj-y += clk.o
+obj-y += ddr.o qca956x-ddr-tap.o
diff --git a/arch/mips/mach-ath79/qca956x/clk.c 
b/arch/mips/mach-ath79/qca956x/clk.c
new file mode 100644
index 0000000000..ca956d1291
--- /dev/null
+++ b/arch/mips/mach-ath79/qca956x/clk.c
@@ -0,0 +1,419 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Rosy Song <rosys...@rosinson.com>
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/addrspace.h>
+#include <asm/types.h>
+#include <mach/ar71xx_regs.h>
+#include <mach/ath79.h>
+#include <wait_bit.h>
+
+#define PLL_SRIF_DPLL2_KI_LSB 29
+#define PLL_SRIF_DPLL2_KI_MASK 0x60000000
+#define PLL_SRIF_DPLL2_KI_SET(x) \
+       (((x) << PLL_SRIF_DPLL2_KI_LSB) & PLL_SRIF_DPLL2_KI_MASK)
+#define PLL_SRIF_DPLL2_KD_LSB 25
+#define PLL_SRIF_DPLL2_KD_MASK 0x1e000000
+#define PLL_SRIF_DPLL2_KD_SET(x) \
+       (((x) << PLL_SRIF_DPLL2_KD_LSB) & PLL_SRIF_DPLL2_KD_MASK)
+#define PLL_SRIF_DPLL2_PLL_PWD_LSB 22
+#define PLL_SRIF_DPLL2_PLL_PWD_MASK 0x00400000
+#define PLL_SRIF_DPLL2_PLL_PWD_SET(x) \
+       (((x) << PLL_SRIF_DPLL2_PLL_PWD_LSB) & PLL_SRIF_DPLL2_PLL_PWD_MASK)
+#define PLL_SRIF_DPLL2_OUTDIV_LSB 19
+#define PLL_SRIF_DPLL2_OUTDIV_MASK 0x00380000
+#define PLL_SRIF_DPLL2_OUTDIV_SET(x) \
+       (((x) << PLL_SRIF_DPLL2_OUTDIV_LSB) & PLL_SRIF_DPLL2_OUTDIV_MASK)
+#define PLL_SRIF_DPLL2_PHASE_SHIFT_LSB 12
+#define PLL_SRIF_DPLL2_PHASE_SHIFT_MASK 0x0007f000
+#define PLL_SRIF_DPLL2_PHASE_SHIFT_SET(x) \
+       (((x) << PLL_SRIF_DPLL2_PHASE_SHIFT_LSB) & 
PLL_SRIF_DPLL2_PHASE_SHIFT_MASK)
+#define CPU_PLL_CONFIG_PLLPWD_LSB 30
+#define CPU_PLL_CONFIG_PLLPWD_MASK 0x40000000
+#define CPU_PLL_CONFIG_PLLPWD_SET(x) \
+       (((x) << CPU_PLL_CONFIG_PLLPWD_LSB) & CPU_PLL_CONFIG_PLLPWD_MASK)
+#define CPU_PLL_CONFIG_OUTDIV_LSB 19
+#define CPU_PLL_CONFIG_OUTDIV_MASK 0x00380000
+#define CPU_PLL_CONFIG_OUTDIV_SET(x) \
+       (((x) << CPU_PLL_CONFIG_OUTDIV_LSB) & CPU_PLL_CONFIG_OUTDIV_MASK)
+#define CPU_PLL_CONFIG_RANGE_LSB 17
+#define CPU_PLL_CONFIG_RANGE_MASK 0x00060000
+#define CPU_PLL_CONFIG_RANGE_SET(x) \
+       (((x) << CPU_PLL_CONFIG_RANGE_LSB) & CPU_PLL_CONFIG_RANGE_MASK)
+#define CPU_PLL_CONFIG_REFDIV_LSB 12
+#define CPU_PLL_CONFIG_REFDIV_MASK 0x0001f000
+#define CPU_PLL_CONFIG_REFDIV_SET(x) \
+       (((x) << CPU_PLL_CONFIG_REFDIV_LSB) & CPU_PLL_CONFIG_REFDIV_MASK)
+#define CPU_PLL_CONFIG1_NINT_LSB 18
+#define CPU_PLL_CONFIG1_NINT_MASK 0x07fc0000
+#define CPU_PLL_CONFIG1_NINT_SET(x) \
+       (((x) << CPU_PLL_CONFIG1_NINT_LSB) & CPU_PLL_CONFIG1_NINT_MASK)
+#define CPU_PLL_DITHER1_DITHER_EN_LSB 31
+#define CPU_PLL_DITHER1_DITHER_EN_MASK 0x80000000
+#define CPU_PLL_DITHER1_DITHER_EN_SET(x) \
+       (((x) << CPU_PLL_DITHER1_DITHER_EN_LSB) & 
CPU_PLL_DITHER1_DITHER_EN_MASK)
+#define CPU_PLL_DITHER1_UPDATE_COUNT_LSB 24
+#define CPU_PLL_DITHER1_UPDATE_COUNT_MASK 0x3f000000
+#define CPU_PLL_DITHER1_UPDATE_COUNT_SET(x) \
+       (((x) << CPU_PLL_DITHER1_UPDATE_COUNT_LSB) & 
CPU_PLL_DITHER1_UPDATE_COUNT_MASK)
+#define CPU_PLL_DITHER1_NFRAC_STEP_LSB 18
+#define CPU_PLL_DITHER1_NFRAC_STEP_MASK 0x00fc0000
+#define CPU_PLL_DITHER1_NFRAC_STEP_SET(x) \
+       (((x) << CPU_PLL_DITHER1_NFRAC_STEP_LSB) & 
CPU_PLL_DITHER1_NFRAC_STEP_MASK)
+#define CPU_PLL_DITHER1_NFRAC_MIN_LSB 0
+#define CPU_PLL_DITHER1_NFRAC_MIN_MASK 0x0003ffff
+#define CPU_PLL_DITHER1_NFRAC_MIN_SET(x) \
+       (((x) << CPU_PLL_DITHER1_NFRAC_MIN_LSB) & 
CPU_PLL_DITHER1_NFRAC_MIN_MASK)
+#define CPU_PLL_DITHER2_NFRAC_MAX_LSB 0
+#define CPU_PLL_DITHER2_NFRAC_MAX_MASK 0x0003ffff
+#define CPU_PLL_DITHER2_NFRAC_MAX_SET(x) \
+       (((x) << CPU_PLL_DITHER2_NFRAC_MAX_LSB) & 
CPU_PLL_DITHER2_NFRAC_MAX_MASK)
+#define DDR_PLL_CONFIG_PLLPWD_LSB 30
+#define DDR_PLL_CONFIG_PLLPWD_MASK 0x40000000
+#define DDR_PLL_CONFIG_PLLPWD_SET(x) \
+       (((x) << DDR_PLL_CONFIG_PLLPWD_LSB) & DDR_PLL_CONFIG_PLLPWD_MASK)
+#define DDR_PLL_CONFIG_OUTDIV_LSB 23
+#define DDR_PLL_CONFIG_OUTDIV_MASK 0x03800000
+#define DDR_PLL_CONFIG_OUTDIV_SET(x) \
+       (((x) << DDR_PLL_CONFIG_OUTDIV_LSB) & DDR_PLL_CONFIG_OUTDIV_MASK)
+#define DDR_PLL_CONFIG_RANGE_LSB 21
+#define DDR_PLL_CONFIG_RANGE_MASK 0x00600000
+#define DDR_PLL_CONFIG_RANGE_SET(x) \
+       (((x) << DDR_PLL_CONFIG_RANGE_LSB) & DDR_PLL_CONFIG_RANGE_MASK)
+#define DDR_PLL_CONFIG_REFDIV_LSB 16
+#define DDR_PLL_CONFIG_REFDIV_MASK 0x001f0000
+#define DDR_PLL_CONFIG_REFDIV_SET(x) \
+       (((x) << DDR_PLL_CONFIG_REFDIV_LSB) & DDR_PLL_CONFIG_REFDIV_MASK)
+#define DDR_PLL_CONFIG1_NINT_LSB 18
+#define DDR_PLL_CONFIG1_NINT_MASK 0x07fc0000
+#define DDR_PLL_CONFIG1_NINT_SET(x) \
+       (((x) << DDR_PLL_CONFIG1_NINT_LSB) & DDR_PLL_CONFIG1_NINT_MASK)
+#define DDR_PLL_DITHER1_DITHER_EN_LSB 31
+#define DDR_PLL_DITHER1_DITHER_EN_MASK 0x80000000
+#define DDR_PLL_DITHER1_DITHER_EN_SET(x) \
+       (((x) << DDR_PLL_DITHER1_DITHER_EN_LSB) & 
DDR_PLL_DITHER1_DITHER_EN_MASK)
+#define DDR_PLL_DITHER1_UPDATE_COUNT_LSB 27
+#define DDR_PLL_DITHER1_UPDATE_COUNT_MASK 0x78000000
+#define DDR_PLL_DITHER1_UPDATE_COUNT_SET(x) \
+       (((x) << DDR_PLL_DITHER1_UPDATE_COUNT_LSB) & 
DDR_PLL_DITHER1_UPDATE_COUNT_MASK)
+#define DDR_PLL_DITHER1_NFRAC_STEP_LSB 20
+#define DDR_PLL_DITHER1_NFRAC_STEP_MASK 0x07f00000
+#define DDR_PLL_DITHER1_NFRAC_STEP_SET(x) \
+       (((x) << DDR_PLL_DITHER1_NFRAC_STEP_LSB) & 
DDR_PLL_DITHER1_NFRAC_STEP_MASK)
+#define DDR_PLL_DITHER1_NFRAC_MIN_LSB 0
+#define DDR_PLL_DITHER1_NFRAC_MIN_MASK 0x0003ffff
+#define DDR_PLL_DITHER1_NFRAC_MIN_SET(x) \
+       (((x) << DDR_PLL_DITHER1_NFRAC_MIN_LSB) & 
DDR_PLL_DITHER1_NFRAC_MIN_MASK)
+#define DDR_PLL_DITHER2_NFRAC_MAX_LSB 0
+#define DDR_PLL_DITHER2_NFRAC_MAX_MASK 0x0003ffff
+#define DDR_PLL_DITHER2_NFRAC_MAX_SET(x) \
+       (((x) << DDR_PLL_DITHER2_NFRAC_MAX_LSB) & 
DDR_PLL_DITHER2_NFRAC_MAX_MASK)
+#define CPU_DDR_CLOCK_CONTROL_AHBCLK_FROM_DDRPLL_LSB 24
+#define CPU_DDR_CLOCK_CONTROL_AHBCLK_FROM_DDRPLL_MASK 0x01000000
+#define CPU_DDR_CLOCK_CONTROL_AHBCLK_FROM_DDRPLL_SET(x) \
+       (((x) << CPU_DDR_CLOCK_CONTROL_AHBCLK_FROM_DDRPLL_LSB) & 
CPU_DDR_CLOCK_CONTROL_AHBCLK_FROM_DDRPLL_MASK)
+#define CPU_DDR_CLOCK_CONTROL_CPU_DDR_CLK_FROM_CPUPLL_LSB 21
+#define CPU_DDR_CLOCK_CONTROL_CPU_DDR_CLK_FROM_CPUPLL_MASK 0x00200000
+#define CPU_DDR_CLOCK_CONTROL_CPU_DDR_CLK_FROM_CPUPLL_SET(x) \
+       (((x) << CPU_DDR_CLOCK_CONTROL_CPU_DDR_CLK_FROM_CPUPLL_LSB) & 
CPU_DDR_CLOCK_CONTROL_CPU_DDR_CLK_FROM_CPUPLL_MASK)
+#define CPU_DDR_CLOCK_CONTROL_CPU_DDR_CLK_FROM_DDRPLL_LSB 20
+#define CPU_DDR_CLOCK_CONTROL_CPU_DDR_CLK_FROM_DDRPLL_MASK 0x00100000
+#define CPU_DDR_CLOCK_CONTROL_CPU_DDR_CLK_FROM_DDRPLL_SET(x) \
+       (((x) << CPU_DDR_CLOCK_CONTROL_CPU_DDR_CLK_FROM_DDRPLL_LSB) & 
CPU_DDR_CLOCK_CONTROL_CPU_DDR_CLK_FROM_DDRPLL_MASK)
+#define CPU_DDR_CLOCK_CONTROL_AHB_POST_DIV_LSB 15
+#define CPU_DDR_CLOCK_CONTROL_AHB_POST_DIV_MASK 0x000f8000
+#define CPU_DDR_CLOCK_CONTROL_AHB_POST_DIV_SET(x) \
+       (((x) << CPU_DDR_CLOCK_CONTROL_AHB_POST_DIV_LSB) & 
CPU_DDR_CLOCK_CONTROL_AHB_POST_DIV_MASK)
+#define CPU_DDR_CLOCK_CONTROL_DDR_POST_DIV_LSB 10
+#define CPU_DDR_CLOCK_CONTROL_DDR_POST_DIV_MASK 0x00007c00
+#define CPU_DDR_CLOCK_CONTROL_DDR_POST_DIV_SET(x) \
+       (((x) << CPU_DDR_CLOCK_CONTROL_DDR_POST_DIV_LSB) & 
CPU_DDR_CLOCK_CONTROL_DDR_POST_DIV_MASK)
+#define CPU_DDR_CLOCK_CONTROL_CPU_POST_DIV_LSB 5
+#define CPU_DDR_CLOCK_CONTROL_CPU_POST_DIV_MASK 0x000003e0
+#define CPU_DDR_CLOCK_CONTROL_CPU_POST_DIV_SET(x) \
+       (((x) << CPU_DDR_CLOCK_CONTROL_CPU_POST_DIV_LSB) & 
CPU_DDR_CLOCK_CONTROL_CPU_POST_DIV_MASK)
+#define CPU_DDR_CLOCK_CONTROL_AHB_PLL_BYPASS_LSB 4
+#define CPU_DDR_CLOCK_CONTROL_AHB_PLL_BYPASS_MASK 0x00000010
+#define CPU_DDR_CLOCK_CONTROL_AHB_PLL_BYPASS_SET(x) \
+       (((x) << CPU_DDR_CLOCK_CONTROL_AHB_PLL_BYPASS_LSB) & 
CPU_DDR_CLOCK_CONTROL_AHB_PLL_BYPASS_MASK)
+#define CPU_DDR_CLOCK_CONTROL_DDR_PLL_BYPASS_LSB 3
+#define CPU_DDR_CLOCK_CONTROL_DDR_PLL_BYPASS_MASK 0x00000008
+#define CPU_DDR_CLOCK_CONTROL_DDR_PLL_BYPASS_SET(x) \
+       (((x) << CPU_DDR_CLOCK_CONTROL_DDR_PLL_BYPASS_LSB) & 
CPU_DDR_CLOCK_CONTROL_DDR_PLL_BYPASS_MASK)
+#define CPU_DDR_CLOCK_CONTROL_CPU_PLL_BYPASS_LSB 2
+#define CPU_DDR_CLOCK_CONTROL_CPU_PLL_BYPASS_MASK 0x00000004
+#define CPU_DDR_CLOCK_CONTROL_CPU_PLL_BYPASS_SET(x) \
+       (((x) << CPU_DDR_CLOCK_CONTROL_CPU_PLL_BYPASS_LSB) & 
CPU_DDR_CLOCK_CONTROL_CPU_PLL_BYPASS_MASK)
+
+#define CPU_PLL_CONFIG1_NINT_VAL CPU_PLL_CONFIG1_NINT_SET(0x1f)
+#define CPU_PLL_CONFIG_REF_DIV_VAL CPU_PLL_CONFIG_REFDIV_SET(0x1)
+#define CPU_PLL_CONFIG_RANGE_VAL CPU_PLL_CONFIG_RANGE_SET(0)
+#define CPU_PLL_CONFIG_OUT_DIV_VAL1 CPU_PLL_CONFIG_OUTDIV_SET(0)
+#define CPU_PLL_CONFIG_OUT_DIV_VAL2 CPU_PLL_CONFIG_OUTDIV_SET(0)
+#define CPU_PLL_DITHER1_VAL CPU_PLL_DITHER1_DITHER_EN_SET(0) | \
+       CPU_PLL_DITHER1_NFRAC_MIN_SET(0) | \
+       CPU_PLL_DITHER1_NFRAC_STEP_SET(0) | \
+       CPU_PLL_DITHER1_UPDATE_COUNT_SET(0x0)
+#define CPU_PLL_DITHER2_VAL CPU_PLL_DITHER2_NFRAC_MAX_SET(0x0)
+#define DDR_PLL_CONFIG1_NINT_VAL DDR_PLL_CONFIG1_NINT_SET(0x1a)
+#define DDR_PLL_CONFIG_REF_DIV_VAL DDR_PLL_CONFIG_REFDIV_SET(0x1)
+#define DDR_PLL_CONFIG_RANGE_VAL DDR_PLL_CONFIG_RANGE_SET(0)
+#define DDR_PLL_CONFIG_OUT_DIV_VAL1 DDR_PLL_CONFIG_OUTDIV_SET(0)
+#define DDR_PLL_CONFIG_OUT_DIV_VAL2 DDR_PLL_CONFIG_OUTDIV_SET(0)
+#define DDR_PLL_DITHER1_VAL DDR_PLL_DITHER1_DITHER_EN_SET(0) | \
+       DDR_PLL_DITHER1_NFRAC_MIN_SET(0) | \
+       DDR_PLL_DITHER1_NFRAC_STEP_SET(0) | \
+       DDR_PLL_DITHER1_UPDATE_COUNT_SET(0x0)
+#define DDR_PLL_DITHER2_VAL DDR_PLL_DITHER2_NFRAC_MAX_SET(0x0)
+#define AHB_CLK_FROM_DDR CPU_DDR_CLOCK_CONTROL_AHBCLK_FROM_DDRPLL_SET(0)
+#define CPU_AND_DDR_CLK_FROM_DDR \
+       CPU_DDR_CLOCK_CONTROL_CPU_DDR_CLK_FROM_DDRPLL_SET(0)
+#define CPU_AND_DDR_CLK_FROM_CPU \
+       CPU_DDR_CLOCK_CONTROL_CPU_DDR_CLK_FROM_CPUPLL_SET(0)
+#define CPU_DDR_CLOCK_CONTROL_AHB_DIV_VAL \
+       CPU_DDR_CLOCK_CONTROL_AHB_POST_DIV_SET(0x2)
+#define CPU_DDR_CLOCK_CONTROL_DDR_POST_DIV \
+       CPU_DDR_CLOCK_CONTROL_DDR_POST_DIV_SET(0)
+#define CPU_DDR_CLOCK_CONTROL_CPU_POST_DIV \
+       CPU_DDR_CLOCK_CONTROL_CPU_POST_DIV_SET(0)
+
+static inline void set_val(u32 _reg, u32 _mask, u32 _val)
+{
+       void __iomem *pll_regs = map_physmem(AR71XX_PLL_BASE,
+                                            AR71XX_PLL_SIZE, MAP_NOCACHE);
+       writel((readl(pll_regs + _reg) & (~(_mask))) | _val, pll_regs + _reg);
+}
+
+#define cpu_pll_set(_mask, _val)       \
+       set_val(QCA956X_PLL_CPU_CONFIG_REG, _mask, _val)
+
+#define ddr_pll_set(_mask, _val)       \
+       set_val(QCA956X_PLL_DDR_CONFIG_REG, _mask, _val)
+
+#define cpu_ddr_control_set(_mask, _val)       \
+       set_val(QCA956X_PLL_CLK_CTRL_REG, _mask, _val)
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static u32 qca956x_get_xtal(void)
+{
+       u32 val;
+
+       val = ath79_get_bootstrap();
+       if (val & QCA956X_BOOTSTRAP_REF_CLK_40)
+               return 40000000;
+       else
+               return 25000000;
+}
+
+int get_serial_clock(void)
+{
+       return qca956x_get_xtal();
+}
+
+void qca956x_pll_init(void)
+{
+       void __iomem *srif_regs = map_physmem(QCA956X_SRIF_BASE,
+                                             QCA956X_SRIF_SIZE, MAP_NOCACHE);
+       void __iomem *pll_regs = map_physmem(AR71XX_PLL_BASE,
+                                            AR71XX_PLL_SIZE, MAP_NOCACHE);
+
+       /* 8.16.2 Baseband DPLL2 */
+       writel(PLL_SRIF_DPLL2_KI_SET(2) | PLL_SRIF_DPLL2_KD_SET(0xa) |
+               PLL_SRIF_DPLL2_PLL_PWD_SET(1) | PLL_SRIF_DPLL2_OUTDIV_SET(1) |
+               PLL_SRIF_DPLL2_PHASE_SHIFT_SET(6), srif_regs + 
QCA956X_SRIF_BB_DPLL2_REG);
+
+       /* 8.16.2 PCIE DPLL2 */
+       writel(PLL_SRIF_DPLL2_KI_SET(2) | PLL_SRIF_DPLL2_KD_SET(0xa) |
+               PLL_SRIF_DPLL2_PLL_PWD_SET(1) | PLL_SRIF_DPLL2_OUTDIV_SET(3) |
+               PLL_SRIF_DPLL2_PHASE_SHIFT_SET(6), srif_regs + 
QCA956X_SRIF_PCIE_DPLL2_REG);
+
+       /* 8.16.2 DDR DPLL2 */
+       writel(PLL_SRIF_DPLL2_KI_SET(2) | PLL_SRIF_DPLL2_KD_SET(0xa) |
+               PLL_SRIF_DPLL2_PLL_PWD_SET(1) | 
PLL_SRIF_DPLL2_PHASE_SHIFT_SET(6),
+               srif_regs + QCA956X_SRIF_DDR_DPLL2_REG);
+
+       /* 8.16.2 CPU DPLL2 */
+       writel(PLL_SRIF_DPLL2_KI_SET(1) | PLL_SRIF_DPLL2_KD_SET(7) |
+                         PLL_SRIF_DPLL2_PLL_PWD_SET(1) | 
PLL_SRIF_DPLL2_PHASE_SHIFT_SET(6),
+                         srif_regs + QCA956X_SRIF_CPU_DPLL2_REG);
+
+       /* pll_bypass_set */
+       cpu_ddr_control_set(CPU_DDR_CLOCK_CONTROL_CPU_PLL_BYPASS_MASK,
+                          CPU_DDR_CLOCK_CONTROL_CPU_PLL_BYPASS_SET(1));
+       cpu_ddr_control_set(CPU_DDR_CLOCK_CONTROL_DDR_PLL_BYPASS_MASK,
+                          CPU_DDR_CLOCK_CONTROL_DDR_PLL_BYPASS_SET(1));
+       cpu_ddr_control_set(CPU_DDR_CLOCK_CONTROL_AHB_PLL_BYPASS_MASK,
+                          CPU_DDR_CLOCK_CONTROL_AHB_PLL_BYPASS_SET(1));
+
+       /* init_cpu_pll */
+       cpu_pll_set(CPU_PLL_CONFIG_PLLPWD_MASK,  CPU_PLL_CONFIG_PLLPWD_SET(1));
+       cpu_pll_set(CPU_PLL_CONFIG_REFDIV_MASK, CPU_PLL_CONFIG_REF_DIV_VAL);
+       cpu_pll_set(CPU_PLL_CONFIG_RANGE_MASK, CPU_PLL_CONFIG_RANGE_VAL);
+       cpu_pll_set(CPU_PLL_CONFIG_OUTDIV_MASK, CPU_PLL_CONFIG_OUT_DIV_VAL1);
+       set_val(QCA956X_PLL_CPU_CONFIG1_REG, CPU_PLL_CONFIG1_NINT_MASK, \
+               CPU_PLL_CONFIG1_NINT_VAL);
+
+       /* init_ddr_pll */
+       ddr_pll_set(DDR_PLL_CONFIG_PLLPWD_MASK,  DDR_PLL_CONFIG_PLLPWD_SET(1));
+       ddr_pll_set(DDR_PLL_CONFIG_REFDIV_MASK, DDR_PLL_CONFIG_REF_DIV_VAL);
+       ddr_pll_set(DDR_PLL_CONFIG_RANGE_MASK, DDR_PLL_CONFIG_RANGE_VAL);
+       ddr_pll_set(DDR_PLL_CONFIG_OUTDIV_MASK, DDR_PLL_CONFIG_OUT_DIV_VAL1);
+       set_val(QCA956X_PLL_DDR_CONFIG1_REG, DDR_PLL_CONFIG1_NINT_MASK,
+               DDR_PLL_CONFIG1_NINT_VAL);
+
+       /* init_ahb_pll */
+       writel(CPU_DDR_CLOCK_CONTROL_AHB_DIV_VAL | AHB_CLK_FROM_DDR |
+               CPU_AND_DDR_CLK_FROM_DDR | CPU_AND_DDR_CLK_FROM_CPU |
+               CPU_DDR_CLOCK_CONTROL_DDR_POST_DIV | 
CPU_DDR_CLOCK_CONTROL_CPU_POST_DIV |
+               CPU_DDR_CLOCK_CONTROL_CPU_PLL_BYPASS_SET(1) |
+               CPU_DDR_CLOCK_CONTROL_DDR_PLL_BYPASS_SET(1) |
+               CPU_DDR_CLOCK_CONTROL_AHB_PLL_BYPASS_SET(1), pll_regs + 
QCA956X_PLL_CLK_CTRL_REG);
+
+       /* ddr_pll_dither_unset */
+       writel(DDR_PLL_DITHER1_VAL, pll_regs + QCA956X_PLL_DDR_DIT_FRAC_REG);
+       writel(DDR_PLL_DITHER2_VAL, pll_regs + QCA956X_PLL_DDR_DIT2_FRAC_REG);
+
+       /* cpu_pll_dither_unset */
+       writel(CPU_PLL_DITHER1_VAL, pll_regs + QCA956X_PLL_CPU_DIT_FRAC_REG);
+       writel(CPU_PLL_DITHER2_VAL, pll_regs + QCA956X_PLL_CPU_DIT2_FRAC_REG);
+
+       /* pll_pwd_unset */
+       cpu_pll_set(CPU_PLL_CONFIG_PLLPWD_MASK, CPU_PLL_CONFIG_PLLPWD_SET(0));
+       ddr_pll_set(DDR_PLL_CONFIG_PLLPWD_MASK, DDR_PLL_CONFIG_PLLPWD_SET(0));
+
+       /* outdiv_unset */
+       cpu_pll_set(CPU_PLL_CONFIG_OUTDIV_MASK, CPU_PLL_CONFIG_OUT_DIV_VAL2);
+       ddr_pll_set(DDR_PLL_CONFIG_OUTDIV_MASK, DDR_PLL_CONFIG_OUT_DIV_VAL2);
+
+       /* pll_bypass_unset */
+       cpu_ddr_control_set(CPU_DDR_CLOCK_CONTROL_CPU_PLL_BYPASS_MASK,
+                          CPU_DDR_CLOCK_CONTROL_CPU_PLL_BYPASS_SET(0));
+       cpu_ddr_control_set(CPU_DDR_CLOCK_CONTROL_DDR_PLL_BYPASS_MASK,
+                          CPU_DDR_CLOCK_CONTROL_DDR_PLL_BYPASS_SET(0));
+       cpu_ddr_control_set(CPU_DDR_CLOCK_CONTROL_AHB_PLL_BYPASS_MASK,
+                          CPU_DDR_CLOCK_CONTROL_AHB_PLL_BYPASS_SET(0));
+
+       while (readl(pll_regs + QCA956X_PLL_CPU_CONFIG_REG) & 0x8000000)
+               /* NOP */;
+
+       while (readl(pll_regs + QCA956X_PLL_DDR_CONFIG_REG) & 0x8000000)
+               /* NOP */;
+}
+
+int get_clocks(void)
+{
+       void __iomem *regs;
+       u32 ref_rate, cpu_rate, ddr_rate, ahb_rate;
+       u32 out_div, ref_div, postdiv, nint, hfrac, lfrac, clk_ctrl;
+       u32 pll, cpu_pll, ddr_pll, misc;
+
+       /*
+        * QCA956x timer init workaround has to be applied right before setting
+        * up the clock. Else, there will be no jiffies
+        */
+       regs = map_physmem(AR71XX_RESET_BASE, AR71XX_RESET_SIZE,
+                         MAP_NOCACHE);
+       misc = readl(regs + AR71XX_RESET_REG_MISC_INT_ENABLE);
+       misc |= MISC_INT_MIPS_SI_TIMERINT_MASK;
+       writel(misc, regs + AR71XX_RESET_REG_MISC_INT_ENABLE);
+
+       regs = map_physmem(AR71XX_PLL_BASE, AR71XX_PLL_SIZE,
+                         MAP_NOCACHE);
+       pll = readl(regs + QCA956X_PLL_CPU_CONFIG_REG);
+       out_div = (pll >> QCA956X_PLL_CPU_CONFIG_OUTDIV_SHIFT) &
+                         QCA956X_PLL_CPU_CONFIG_OUTDIV_MASK;
+       ref_div = (pll >> QCA956X_PLL_CPU_CONFIG_REFDIV_SHIFT) &
+                         QCA956X_PLL_CPU_CONFIG_REFDIV_MASK;
+
+       pll = readl(regs + QCA956X_PLL_CPU_CONFIG1_REG);
+       nint = (pll >> QCA956X_PLL_CPU_CONFIG1_NINT_SHIFT) &
+                         QCA956X_PLL_CPU_CONFIG1_NINT_MASK;
+       hfrac = (pll >> QCA956X_PLL_CPU_CONFIG1_NFRAC_H_SHIFT) &
+                         QCA956X_PLL_CPU_CONFIG1_NFRAC_H_MASK;
+       lfrac = (pll >> QCA956X_PLL_CPU_CONFIG1_NFRAC_L_SHIFT) &
+                         QCA956X_PLL_CPU_CONFIG1_NFRAC_L_MASK;
+
+       ref_rate = qca956x_get_xtal();
+
+       cpu_pll = nint * ref_rate / ref_div;
+       cpu_pll += (lfrac * ref_rate) / ((ref_div * 25) << 13);
+       cpu_pll += (hfrac >> 13) * ref_rate / ref_div;
+       cpu_pll /= (1 << out_div);
+
+       pll = readl(regs + QCA956X_PLL_DDR_CONFIG_REG);
+       out_div = (pll >> QCA956X_PLL_DDR_CONFIG_OUTDIV_SHIFT) &
+                         QCA956X_PLL_DDR_CONFIG_OUTDIV_MASK;
+       ref_div = (pll >> QCA956X_PLL_DDR_CONFIG_REFDIV_SHIFT) &
+                         QCA956X_PLL_DDR_CONFIG_REFDIV_MASK;
+       pll = readl(regs + QCA956X_PLL_DDR_CONFIG1_REG);
+       nint = (pll >> QCA956X_PLL_DDR_CONFIG1_NINT_SHIFT) &
+               QCA956X_PLL_DDR_CONFIG1_NINT_MASK;
+       hfrac = (pll >> QCA956X_PLL_DDR_CONFIG1_NFRAC_H_SHIFT) &
+               QCA956X_PLL_DDR_CONFIG1_NFRAC_H_MASK;
+       lfrac = (pll >> QCA956X_PLL_DDR_CONFIG1_NFRAC_L_SHIFT) &
+               QCA956X_PLL_DDR_CONFIG1_NFRAC_L_MASK;
+
+       ddr_pll = nint * ref_rate / ref_div;
+       ddr_pll += (lfrac * ref_rate) / ((ref_div * 25) << 13);
+       ddr_pll += (hfrac >> 13) * ref_rate / ref_div;
+       ddr_pll /= (1 << out_div);
+
+       clk_ctrl = readl(regs + QCA956X_PLL_CLK_CTRL_REG);
+
+       postdiv = (clk_ctrl >> QCA956X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT) &
+                 QCA956X_PLL_CLK_CTRL_CPU_POST_DIV_MASK;
+
+       if (clk_ctrl & QCA956X_PLL_CLK_CTRL_CPU_PLL_BYPASS)
+               cpu_rate = ref_rate;
+       else if (clk_ctrl & QCA956X_PLL_CLK_CTRL_CPU_DDRCLK_FROM_CPUPLL)
+               cpu_rate = ddr_pll / (postdiv + 1);
+       else
+               cpu_rate = cpu_pll / (postdiv + 1);
+
+       postdiv = (clk_ctrl >> QCA956X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT) &
+                 QCA956X_PLL_CLK_CTRL_DDR_POST_DIV_MASK;
+
+       if (clk_ctrl & QCA956X_PLL_CLK_CTRL_DDR_PLL_BYPASS)
+               ddr_rate = ref_rate;
+       else if (clk_ctrl & QCA956X_PLL_CLK_CTRL_CPU_DDRCLK_FROM_DDRPLL)
+               ddr_rate = cpu_pll / (postdiv + 1);
+       else
+               ddr_rate = ddr_pll / (postdiv + 1);
+
+       postdiv = (clk_ctrl >> QCA956X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT) &
+                 QCA956X_PLL_CLK_CTRL_AHB_POST_DIV_MASK;
+
+       if (clk_ctrl & QCA956X_PLL_CLK_CTRL_AHB_PLL_BYPASS)
+               ahb_rate = ref_rate;
+       else if (clk_ctrl & QCA956X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL)
+               ahb_rate = ddr_pll / (postdiv + 1);
+       else
+               ahb_rate = cpu_pll / (postdiv + 1);
+
+       gd->cpu_clk = cpu_rate;
+       gd->mem_clk = ddr_rate;
+       gd->bus_clk = ahb_rate;
+
+       debug("cpu_clk=%u, ddr_clk=%u, bus_clk=%u\n",
+               cpu_rate, ddr_rate, ahb_rate);
+
+       return 0;
+}
+
+ulong get_bus_freq(ulong dummy)
+{
+       if (!gd->bus_clk)
+               get_clocks();
+       return gd->bus_clk;
+}
+
+ulong get_ddr_freq(ulong dummy)
+{
+       if (!gd->mem_clk)
+               get_clocks();
+       return gd->mem_clk;
+}
diff --git a/arch/mips/mach-ath79/qca956x/cpu.c 
b/arch/mips/mach-ath79/qca956x/cpu.c
new file mode 100644
index 0000000000..08a8c84e72
--- /dev/null
+++ b/arch/mips/mach-ath79/qca956x/cpu.c
@@ -0,0 +1,9 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Rosy Song <rosys...@rosinson.com>
+ */
+
+#include <common.h>
+
+/* The lowlevel_init() is not needed on QCA956X */
+void lowlevel_init(void) {}
diff --git a/arch/mips/mach-ath79/qca956x/ddr.c 
b/arch/mips/mach-ath79/qca956x/ddr.c
new file mode 100644
index 0000000000..fb2230430c
--- /dev/null
+++ b/arch/mips/mach-ath79/qca956x/ddr.c
@@ -0,0 +1,308 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Rosy Song <rosys...@rosinson.com>
+ *
+ * Based on QSDK
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/addrspace.h>
+#include <asm/types.h>
+#include <mach/ar71xx_regs.h>
+#include <mach/ath79.h>
+
+#define DDR_FSM_WAIT_CTRL_VAL 0xa12
+#define DDR_CTL_CONFIG_SRAM_TSEL_LSB 30
+#define DDR_CTL_CONFIG_SRAM_TSEL_MASK 0xc0000000
+#define DDR_CTL_CONFIG_SRAM_TSEL_SET(x) \
+       (((x) << DDR_CTL_CONFIG_SRAM_TSEL_LSB) & DDR_CTL_CONFIG_SRAM_TSEL_MASK)
+#define DDR_CTL_CONFIG_GE0_SRAM_SYNC_LSB 20
+#define DDR_CTL_CONFIG_GE0_SRAM_SYNC_MASK 0x00100000
+#define DDR_CTL_CONFIG_GE0_SRAM_SYNC_SET(x) \
+       (((x) << DDR_CTL_CONFIG_GE0_SRAM_SYNC_LSB) & 
DDR_CTL_CONFIG_GE0_SRAM_SYNC_MASK)
+#define DDR_CTL_CONFIG_GE1_SRAM_SYNC_LSB 19
+#define DDR_CTL_CONFIG_GE1_SRAM_SYNC_MASK 0x00080000
+#define DDR_CTL_CONFIG_GE1_SRAM_SYNC_SET(x) \
+       (((x) << DDR_CTL_CONFIG_GE1_SRAM_SYNC_LSB) & 
DDR_CTL_CONFIG_GE1_SRAM_SYNC_MASK)
+#define DDR_CTL_CONFIG_USB_SRAM_SYNC_LSB 18
+#define DDR_CTL_CONFIG_USB_SRAM_SYNC_MASK 0x00040000
+#define DDR_CTL_CONFIG_USB_SRAM_SYNC_SET(x) \
+       (((x) << DDR_CTL_CONFIG_USB_SRAM_SYNC_LSB) & 
DDR_CTL_CONFIG_USB_SRAM_SYNC_MASK)
+#define DDR_CTL_CONFIG_PCIE_SRAM_SYNC_LSB 17
+#define DDR_CTL_CONFIG_PCIE_SRAM_SYNC_MASK 0x00020000
+#define DDR_CTL_CONFIG_PCIE_SRAM_SYNC_SET(x) \
+       (((x) << DDR_CTL_CONFIG_PCIE_SRAM_SYNC_LSB) & 
DDR_CTL_CONFIG_PCIE_SRAM_SYNC_MASK)
+#define DDR_CTL_CONFIG_WMAC_SRAM_SYNC_LSB 16
+#define DDR_CTL_CONFIG_WMAC_SRAM_SYNC_MASK 0x00010000
+#define DDR_CTL_CONFIG_WMAC_SRAM_SYNC_SET(x) \
+       (((x) << DDR_CTL_CONFIG_WMAC_SRAM_SYNC_LSB) & 
DDR_CTL_CONFIG_WMAC_SRAM_SYNC_MASK)
+#define DDR_CTL_CONFIG_MISC_SRC1_SRAM_SYNC_LSB 15
+#define DDR_CTL_CONFIG_MISC_SRC1_SRAM_SYNC_MASK 0x00008000
+#define DDR_CTL_CONFIG_MISC_SRC1_SRAM_SYNC_SET(x) \
+       (((x) << DDR_CTL_CONFIG_MISC_SRC1_SRAM_SYNC_LSB) & 
DDR_CTL_CONFIG_MISC_SRC1_SRAM_SYNC_MASK)
+#define DDR_CTL_CONFIG_MISC_SRC2_SRAM_SYNC_LSB 14
+#define DDR_CTL_CONFIG_MISC_SRC2_SRAM_SYNC_MASK 0x00004000
+#define DDR_CTL_CONFIG_MISC_SRC2_SRAM_SYNC_SET(x) \
+       (((x) << DDR_CTL_CONFIG_MISC_SRC2_SRAM_SYNC_LSB) & 
DDR_CTL_CONFIG_MISC_SRC2_SRAM_SYNC_MASK)
+#define DDR_CTL_CONFIG_PAD_DDR2_SEL_LSB 6
+#define DDR_CTL_CONFIG_PAD_DDR2_SEL_MASK 0x00000040
+#define DDR_CTL_CONFIG_PAD_DDR2_SEL_SET(x) \
+       (((x) << DDR_CTL_CONFIG_PAD_DDR2_SEL_LSB) & 
DDR_CTL_CONFIG_PAD_DDR2_SEL_MASK)
+#define DDR_CTL_CONFIG_CPU_DDR_SYNC_LSB 2
+#define DDR_CTL_CONFIG_CPU_DDR_SYNC_MASK 0x00000004
+#define DDR_CTL_CONFIG_CPU_DDR_SYNC_SET(x) \
+       (((x) << DDR_CTL_CONFIG_CPU_DDR_SYNC_LSB) & 
DDR_CTL_CONFIG_CPU_DDR_SYNC_MASK)
+#define DDR_CTL_CONFIG_HALF_WIDTH_LSB 1
+#define DDR_CTL_CONFIG_HALF_WIDTH_MASK 0x00000002
+#define DDR_CTL_CONFIG_HALF_WIDTH_SET(x) \
+       (((x) << DDR_CTL_CONFIG_HALF_WIDTH_LSB) & 
DDR_CTL_CONFIG_HALF_WIDTH_MASK)
+#define DDR_CONFIG_CAS_LATENCY_MSB_LSB 31
+#define DDR_CONFIG_CAS_LATENCY_MSB_MASK 0x80000000
+#define DDR_CONFIG_CAS_LATENCY_MSB_SET(x) \
+       (((x) << DDR_CONFIG_CAS_LATENCY_MSB_LSB) & 
DDR_CONFIG_CAS_LATENCY_MSB_MASK)
+#define DDR_CONFIG_OPEN_PAGE_LSB 30
+#define DDR_CONFIG_OPEN_PAGE_MASK 0x40000000
+#define DDR_CONFIG_OPEN_PAGE_SET(x) \
+       (((x) << DDR_CONFIG_OPEN_PAGE_LSB) & DDR_CONFIG_OPEN_PAGE_MASK)
+#define DDR_CONFIG_CAS_LATENCY_LSB 27
+#define DDR_CONFIG_CAS_LATENCY_MASK 0x38000000
+#define DDR_CONFIG_CAS_LATENCY_SET(x) \
+       (((x) << DDR_CONFIG_CAS_LATENCY_LSB) & DDR_CONFIG_CAS_LATENCY_MASK)
+#define DDR_CONFIG_TMRD_LSB 23
+#define DDR_CONFIG_TMRD_MASK 0x07800000
+#define DDR_CONFIG_TMRD_SET(x) \
+       (((x) << DDR_CONFIG_TMRD_LSB) & DDR_CONFIG_TMRD_MASK)
+#define DDR_CONFIG_TRFC_LSB 17
+#define DDR_CONFIG_TRFC_MASK 0x007e0000
+#define DDR_CONFIG_TRFC_SET(x) \
+       (((x) << DDR_CONFIG_TRFC_LSB) & DDR_CONFIG_TRFC_MASK)
+#define DDR_CONFIG_TRRD_LSB 13
+#define DDR_CONFIG_TRRD_MASK 0x0001e000
+#define DDR_CONFIG_TRRD_SET(x) \
+       (((x) << DDR_CONFIG_TRRD_LSB) & DDR_CONFIG_TRRD_MASK)
+#define DDR_CONFIG_TRP_LSB 9
+#define DDR_CONFIG_TRP_MASK 0x00001e00
+#define DDR_CONFIG_TRP_SET(x) \
+       (((x) << DDR_CONFIG_TRP_LSB) & DDR_CONFIG_TRP_MASK)
+#define DDR_CONFIG_TRCD_LSB 5
+#define DDR_CONFIG_TRCD_MASK 0x000001e0
+#define DDR_CONFIG_TRCD_SET(x) \
+       (((x) << DDR_CONFIG_TRCD_LSB) & DDR_CONFIG_TRCD_MASK)
+#define DDR_CONFIG_TRAS_LSB 0
+#define DDR_CONFIG_TRAS_MASK 0x0000001f
+#define DDR_CONFIG_TRAS_SET(x) \
+       (((x) << DDR_CONFIG_TRAS_LSB) & DDR_CONFIG_TRAS_MASK)
+#define DDR_CONFIG2_HALF_WIDTH_LOW_LSB 31
+#define DDR_CONFIG2_HALF_WIDTH_LOW_MASK 0x80000000
+#define DDR_CONFIG2_HALF_WIDTH_LOW_SET(x) \
+       (((x) << DDR_CONFIG2_HALF_WIDTH_LOW_LSB) & 
DDR_CONFIG2_HALF_WIDTH_LOW_MASK)
+#define DDR_CONFIG2_SWAP_A26_A27_LSB 30
+#define DDR_CONFIG2_SWAP_A26_A27_MASK 0x40000000
+#define DDR_CONFIG2_SWAP_A26_A27_SET(x) \
+       (((x) << DDR_CONFIG2_SWAP_A26_A27_LSB) & DDR_CONFIG2_SWAP_A26_A27_MASK)
+#define DDR_CONFIG2_GATE_OPEN_LATENCY_LSB 26
+#define DDR_CONFIG2_GATE_OPEN_LATENCY_MASK 0x3c000000
+#define DDR_CONFIG2_GATE_OPEN_LATENCY_SET(x) \
+       (((x) << DDR_CONFIG2_GATE_OPEN_LATENCY_LSB) & 
DDR_CONFIG2_GATE_OPEN_LATENCY_MASK)
+#define DDR_CONFIG2_TWTR_LSB 21
+#define DDR_CONFIG2_TWTR_MASK 0x03e00000
+#define DDR_CONFIG2_TWTR_SET(x) \
+       (((x) << DDR_CONFIG2_TWTR_LSB) & DDR_CONFIG2_TWTR_MASK)
+#define DDR_CONFIG2_TRTP_LSB 17
+#define DDR_CONFIG2_TRTP_MASK 0x001e0000
+#define DDR_CONFIG2_TRTP_SET(x) \
+       (((x) << DDR_CONFIG2_TRTP_LSB) & DDR_CONFIG2_TRTP_MASK)
+#define DDR_CONFIG2_TRTW_LSB 12
+#define DDR_CONFIG2_TRTW_MASK 0x0001f000
+#define DDR_CONFIG2_TRTW_SET(x) \
+       (((x) << DDR_CONFIG2_TRTW_LSB) & DDR_CONFIG2_TRTW_MASK)
+#define DDR_CONFIG2_TWR_LSB 8
+#define DDR_CONFIG2_TWR_MASK 0x00000f00
+#define DDR_CONFIG2_TWR_SET(x) \
+       (((x) << DDR_CONFIG2_TWR_LSB) & DDR_CONFIG2_TWR_MASK)
+#define DDR_CONFIG2_CKE_LSB 7
+#define DDR_CONFIG2_CKE_MASK 0x00000080
+#define DDR_CONFIG2_CKE_SET(x) \
+       (((x) << DDR_CONFIG2_CKE_LSB) & DDR_CONFIG2_CKE_MASK)
+#define DDR_CONFIG2_CNTL_OE_EN_LSB 5
+#define DDR_CONFIG2_CNTL_OE_EN_MASK 0x00000020
+#define DDR_CONFIG2_CNTL_OE_EN_SET(x) \
+       (((x) << DDR_CONFIG2_CNTL_OE_EN_LSB) & DDR_CONFIG2_CNTL_OE_EN_MASK)
+#define DDR_CONFIG2_BURST_LENGTH_LSB 0
+#define DDR_CONFIG2_BURST_LENGTH_MASK 0x0000000f
+#define DDR_CONFIG2_BURST_LENGTH_SET(x) \
+       (((x) << DDR_CONFIG2_BURST_LENGTH_LSB) & DDR_CONFIG2_BURST_LENGTH_MASK)
+#define RST_BOOTSTRAP_ADDRESS          0x180600b0
+#define PMU2_SWREGMSB_LSB 22
+#define PMU2_SWREGMSB_MASK 0xffc00000
+#define PMU2_SWREGMSB_SET(x) \
+       (((x) << PMU2_SWREGMSB_LSB) & PMU2_SWREGMSB_MASK)
+#define PMU2_PGM_LSB 21
+#define PMU2_PGM_MASK 0x00200000
+#define PMU2_PGM_SET(x) \
+       (((x) << PMU2_PGM_LSB) & PMU2_PGM_MASK)
+
+#define CPU_DDR_SYNC_MODE DDR_CTL_CONFIG_CPU_DDR_SYNC_SET(0)
+
+/*
+* DDR2                      DDR1
+* 0x40c3   25MHz            0x4186   25Mhz
+* 0x4138   40MHz            0x4270   40Mhz
+*/
+#define CFG_DDR2_REFRESH_VAL 0x40c3
+#define CFG_DDR2_CONFIG_VAL DDR_CONFIG_CAS_LATENCY_MSB_SET(0x1) | \
+       DDR_CONFIG_OPEN_PAGE_SET(0x1) | DDR_CONFIG_CAS_LATENCY_SET(0x4) | \
+       DDR_CONFIG_TMRD_SET(0x6) | DDR_CONFIG_TRFC_SET(0x16) | \
+       DDR_CONFIG_TRRD_SET(0x7) | DDR_CONFIG_TRP_SET(0xb) | \
+       DDR_CONFIG_TRCD_SET(0xb) | DDR_CONFIG_TRAS_SET(0)
+#define CFG_DDR2_CONFIG2_VAL DDR_CONFIG2_HALF_WIDTH_LOW_SET(0x1) | \
+       DDR_CONFIG2_SWAP_A26_A27_SET(0x0) | 
DDR_CONFIG2_GATE_OPEN_LATENCY_SET(0xa) | \
+       DDR_CONFIG2_TWTR_SET(0x16) | DDR_CONFIG2_TRTP_SET(0xa) | \
+       DDR_CONFIG2_TRTW_SET(0xe) | DDR_CONFIG2_TWR_SET(0x2) | \
+       DDR_CONFIG2_CKE_SET(0x1) | DDR_CONFIG2_CNTL_OE_EN_SET(0x1) | \
+       DDR_CONFIG2_BURST_LENGTH_SET(0x8)
+
+#define CFG_DDR2_CONFIG3_VAL 0x0000000e
+#define CFG_DDR2_EXT_MODE_VAL1 0x782
+#define CFG_DDR2_EXT_MODE_VAL2 0x402
+#define CFG_DDR2_MODE_VAL_INIT 0xb53
+#define CFG_DDR2_MODE_VAL 0xa53
+#define CFG_DDR2_TAP_VAL 0x10
+#define CFG_DDR2_EN_TWL_VAL 0x00001e91
+#define CFG_DDR2_RD_DATA_THIS_CYCLE_VAL_16 0xffff
+
+#define CFG_DDR_CTL_CONFIG DDR_CTL_CONFIG_SRAM_TSEL_SET(0x1) | \
+       DDR_CTL_CONFIG_GE0_SRAM_SYNC_SET(0x1) | \
+       DDR_CTL_CONFIG_GE1_SRAM_SYNC_SET(0x1) | \
+       DDR_CTL_CONFIG_USB_SRAM_SYNC_SET(0x1) | \
+       DDR_CTL_CONFIG_PCIE_SRAM_SYNC_SET(0x1) | \
+       DDR_CTL_CONFIG_WMAC_SRAM_SYNC_SET(0x1) | \
+       DDR_CTL_CONFIG_MISC_SRC1_SRAM_SYNC_SET(0x1) | \
+       DDR_CTL_CONFIG_MISC_SRC2_SRAM_SYNC_SET(0x1)
+
+DECLARE_GLOBAL_DATA_PTR;
+
+void qca956x_ddr_init(void)
+{
+       u32 ddr_config, ddr_config2, ddr_config3, mod_val, \
+               mod_val_init, cycle_val, tap_val, ctl_config;
+       void __iomem *ddr_regs = map_physmem(AR71XX_DDR_CTRL_BASE, 
AR71XX_DDR_CTRL_SIZE,
+                              MAP_NOCACHE);
+       void __iomem *srif_regs = map_physmem(QCA956X_SRIF_BASE, 
QCA956X_SRIF_SIZE,
+                              MAP_NOCACHE);
+
+       ddr_config = CFG_DDR2_CONFIG_VAL;
+       ddr_config2 = CFG_DDR2_CONFIG2_VAL;
+       ddr_config3 = CFG_DDR2_CONFIG3_VAL;
+       mod_val_init = CFG_DDR2_MODE_VAL_INIT;
+       mod_val = CFG_DDR2_MODE_VAL;
+       tap_val = CFG_DDR2_TAP_VAL;
+       cycle_val = CFG_DDR2_RD_DATA_THIS_CYCLE_VAL_16;
+       ctl_config = CFG_DDR_CTL_CONFIG | DDR_CTL_CONFIG_PAD_DDR2_SEL_SET(0x1) |
+                        DDR_CTL_CONFIG_HALF_WIDTH_SET(0x1) | CPU_DDR_SYNC_MODE;
+
+       writel(0x10, ddr_regs + AR71XX_DDR_REG_CONTROL);
+       udelay(10);
+
+       writel(0x20, ddr_regs + AR71XX_DDR_REG_CONTROL);
+       udelay(10);
+
+       writel(ctl_config, ddr_regs + QCA956X_DDR_REG_CTL_CONF);
+       udelay(10);
+
+       writel(cycle_val, ddr_regs + AR71XX_DDR_REG_RD_CYCLE);
+       udelay(100);
+
+       writel(0x74444444, ddr_regs + QCA956X_DDR_REG_BURST);
+       udelay(100);
+
+       writel(0x44444444, ddr_regs + QCA956X_DDR_REG_BURST2);
+       udelay(100);
+
+       writel(DDR_FSM_WAIT_CTRL_VAL, ddr_regs + QCA956X_DDR_REG_FSM_WAIT_CTRL);
+       udelay(100);
+
+       writel(0xfffff, ddr_regs + QCA956X_DDR_REG_TIMEOUT_MAX);
+       udelay(100);
+
+       writel(ddr_config, ddr_regs + AR71XX_DDR_REG_CONFIG);
+       udelay(100);
+
+       writel(ddr_config2, ddr_regs + AR71XX_DDR_REG_CONFIG2);
+       udelay(100);
+
+       writel(ddr_config3, ddr_regs + QCA956X_DDR_REG_DDR3_CONFIG);
+       udelay(100);
+
+       writel(CFG_DDR2_EN_TWL_VAL, ddr_regs + QCA956X_DDR_REG_DDR2_CONFIG);
+       udelay(100);
+
+       writel(ddr_config2 | 0x80, ddr_regs + AR71XX_DDR_REG_CONFIG2);  /* CKE 
Enable */
+       udelay(100);
+
+       writel(0x8, ddr_regs + AR71XX_DDR_REG_CONTROL); /* Precharge */
+       udelay(10);
+
+       writel(0, ddr_regs + QCA956X_DDR_REG_DDR2_EMR2);
+       writel(0x10, ddr_regs + AR71XX_DDR_REG_CONTROL);        /* EMR2 */
+       udelay(10);
+
+       writel(0, ddr_regs + QCA956X_DDR_REG_DDR2_EMR3);
+       writel(0x20, ddr_regs + AR71XX_DDR_REG_CONTROL);        /* EMR3 */
+       udelay(10);
+
+       /* EMR DLL enable, Reduced Driver Impedance control, Differential DQS 
disabled */
+       writel(CFG_DDR2_EXT_MODE_VAL2, ddr_regs + AR71XX_DDR_REG_EMR);
+       udelay(100);
+
+       writel(0x2, ddr_regs + AR71XX_DDR_REG_CONTROL); /* EMR write */
+       udelay(10);
+
+       writel(mod_val_init, ddr_regs + AR71XX_DDR_REG_MODE);
+       udelay(1000);
+
+       writel(0x1, ddr_regs + AR71XX_DDR_REG_CONTROL); /* MR Write */
+       udelay(10);
+
+       writel(0x8, ddr_regs + AR71XX_DDR_REG_CONTROL); /* Precharge */
+       udelay(10);
+
+       writel(0x4, ddr_regs + AR71XX_DDR_REG_CONTROL); /* Auto Refresh */
+       udelay(10);
+
+       writel(0x4, ddr_regs + AR71XX_DDR_REG_CONTROL); /* Auto Refresh */
+       udelay(10);
+
+       /* Issue MRS to remove DLL out-of-reset */
+       writel(mod_val, ddr_regs + AR71XX_DDR_REG_MODE);
+       udelay(100);
+
+       writel(0x1, ddr_regs + AR71XX_DDR_REG_CONTROL); /* MR write */
+       udelay(100);
+
+       writel(CFG_DDR2_EXT_MODE_VAL1, ddr_regs + AR71XX_DDR_REG_EMR);
+       udelay(100);
+
+       writel(0x2, ddr_regs + AR71XX_DDR_REG_CONTROL); /* EMR write */
+       udelay(100);
+
+       writel(CFG_DDR2_EXT_MODE_VAL2, ddr_regs + AR71XX_DDR_REG_EMR);
+       udelay(100);
+
+       writel(0x2, ddr_regs + AR71XX_DDR_REG_CONTROL); /* EMR write */
+       udelay(100);
+
+       writel(CFG_DDR2_REFRESH_VAL, ddr_regs + AR71XX_DDR_REG_REFRESH);
+       udelay(100);
+
+       writel(tap_val, ddr_regs + AR71XX_DDR_REG_TAP_CTRL0);
+       writel(tap_val, ddr_regs + AR71XX_DDR_REG_TAP_CTRL1);
+       writel(tap_val, ddr_regs + QCA956X_DDR_REG_TAP_CTRL2);
+       writel(tap_val, ddr_regs + QCA956X_DDR_REG_TAP_CTRL3);
+
+       writel(0x633c8176, srif_regs + QCA956X_SRIF_PMU1_REG);
+       /* Set DDR2 Voltage to 1.8 volts */
+       writel(PMU2_SWREGMSB_SET(0x40) | PMU2_PGM_SET(0x1),
+              srif_regs + QCA956X_SRIF_PMU2_REG);
+}
diff --git a/arch/mips/mach-ath79/qca956x/qca956x-ddr-tap.S 
b/arch/mips/mach-ath79/qca956x/qca956x-ddr-tap.S
new file mode 100644
index 0000000000..db54b575fb
--- /dev/null
+++ b/arch/mips/mach-ath79/qca956x/qca956x-ddr-tap.S
@@ -0,0 +1,193 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2019 Rosy Song <rosys...@rosinson.com>
+ *
+ * Based on QSDK
+ */
+
+#include <config.h>
+#include <asm/asm.h>
+#include <asm/regdef.h>
+#include <asm/mipsregs.h>
+#include <asm/addrspace.h>
+#include <mach/ar71xx_regs.h>
+
+    .set noreorder
+
+LEAF(ddr_tap_tuning)
+       li      a0, 0xbd001f00
+       sw      zero, 0x0(a0)                   /* Place where the tap values 
are saved and used for SWEEP */
+       sw      zero, 0x4(a0)                   /* Place where the number of 
passing taps are saved. */
+       sw      zero, 0x14(a0)          /* Place where the last pass tap value 
is stored */
+       li      a1, 0xaa55aa55          /* Indicates that the First pass tap 
value is not found */
+       sw      a1, 0x10(a0)            /* Place where the First pass tap value 
is stored */
+        nop
+
+       li      a0, CKSEG1ADDR(AR71XX_RESET_BASE)               /* 
RESET_BASE_ADDRESS */
+       lw      a1, 0x1c(a0)            /* Reading the RST_RESET_ADDRESS */
+       li      a2, 0x08000000          /* Setting the RST_RESET_RTC_RESET */
+       or      a1, a1, a2
+       sw      a1, 0x1c(a0)
+
+       li      a3, 0xffffffff
+       xor     a2, a2, a3
+       and     a1, a1, a2
+       sw      a1, 0x1c(a0)            /* Taking the RTC out of RESET */
+        nop
+
+       li      a0, CKSEG1ADDR(QCA956X_RTC_BASE)                /* 
RTC_BASE_ADDRESS */
+       li      a1, 0x1
+       sw      a1, 0x0040(a0)          /* RTC_SYNC_RESET_ADDRESS */
+
+       li      a2, 0x2
+
+_poll_for_RTC_ON:
+       lw      a1, 0x0044(a0)          /* RTC_SYNC_STATUS_ADDRESS */
+       and     a1, a2, a1
+       bne     a1, a2, _poll_for_RTC_ON
+         nop
+
+_CHANGE_TAPS:
+       li      t0, 0xbd001f00          /* Read the current value of the TAP 
for programming */
+       lw      t1, 0x0(t0)
+       li      t2, 0x00000000
+       or      t3, t1, t2
+
+       li      t0, 0xb8000000          /* DDR_BASE_ADDRESS */
+       sw      t3, 0x1c(t0)            /* TAP_CONTROL_0_ADDRESS */
+       sw      t3, 0x20(t0)            /* TAP_CONTROL_1_ADDRESS */
+       sw      t3, 0x24(t0)            /* TAP_CONTROL_2_ADDRESS */
+       sw      t3, 0x28(t0)            /* TAP_CONTROL_3_ADDRESS */
+
+       li      t1, 0x00000010          /* Running the test 8 times */
+       sw      t1, 0x0068(t0)          /* PERF_COMP_ADDR_1_ADDRESS */
+
+       li      t1, 0xfa5de83f          /* 4 Row Address Bits, 4 Column Address 
Bits, 2 BA bits */
+       sw      t1, 0x002c(t0)          /* PERF_MASK_ADDR_0_ADDRESS */
+
+       li      t1, 0x0000ffff
+       sw      t1, 0x0070(t0)          /* PERF_COMP_AHB_GE0_1_ADDRESS */
+
+       li      t1, 0x0000ffff
+       sw      t1, 0x0040(t0)          /* PERF_COMP_AHB_GE1_0_ADDRESS */
+
+       li      t1, 0x0000ffff
+       sw      t1, 0x0078(t0)          /* PERF_COMP_AHB_GE1_1_ADDRESS */
+
+       li      t1, 0x0000ffff
+       sw      t1, 0x0034(t0)          /* PERF_MASK_AHB_GE0_0_ADDRESS */
+
+       li      t1, 0x0000ffff
+       sw      t1, 0x006c(t0)          /* PERF_MASK_AHB_GE0_1_ADDRESS */
+
+       li      t1, 0x0000ffff
+       sw      t1, 0x003c(t0)          /* PERF_MASK_AHB_GE1_0_ADDRESS */
+
+       li      t1, 0x0000ffff
+       sw      t1, 0x0074(t0)          /* PERF_MASK_AHB_GE1_1_ADDRESS */
+
+       li      t1, 0x0000ffff
+       sw      t1, 0x0038(t0)          /* PERF_COMP_AHB_GE0_0_ADDRESS */
+
+       li      t1, 0x00000001
+       sw      t1, 0x011c(t0)          /* DDR_BIST_ADDRESS */
+
+       li      t2, 0x1
+
+_bist_done_poll:
+       lw      t1, 0x0120(t0)          /* DDR_BIST_STATUS_ADDRESS */
+       and     t1, t1, t2
+       bne     t1, t2, _bist_done_poll
+        nop
+
+       lw      t1, 0x0120(t0)          /* DDR_BIST_STATUS_ADDRESS */
+       li      t4, 0x000001fe
+       and     t2, t1, t4
+       srl     t2, t2, 0x1             /* no. of Pass Runs */
+
+       li      t5, 0x00000000
+       sw      t5, 0x011c(t0)          /* DDR_BIST_ADDRESS     - Stop the DDR 
BIST test */
+
+       li      t5, 0x0001fe00
+       and     t5, t5, t1
+       bnez    t5, _iterate_tap                /* This is a redundant compare 
but nevertheless - Comparing the FAILS */
+        nop
+
+       lw      t1, 0x0068(t0)          /* PERF_COMP_ADDR_1_ADDRESS */
+       li      t3, 0x000001fe
+       and     t3, t3, t1
+       srl     t3, t3, 0x1             /* No. of runs in the config register. 
*/
+       bne     t3, t2, _iterate_tap
+        nop
+
+pass_tap:
+       li      t0, 0xbd001f00
+       lw      t1, 0x4(t0)
+       addiu   t1, t1, 0x1
+       sw      t1, 0x4(t0)
+
+       li      t0, 0xbd001f10
+       lw      t1, 0x0(t0)
+       li      t2, 0xaa55aa55
+       beq     t1, t2, _first_pass
+        nop
+
+       li      t0, 0xbd001f00
+       lw      t1, 0x0(t0)
+       li      t0, 0xbd001f10
+       sw      t1, 0x4(t0)
+        nop
+       b       _iterate_tap
+        nop
+
+_first_pass:
+       li      t0, 0xbd001f00
+       lw      t1, 0x0(t0)
+       li      t0, 0xbd001f10
+       sw      t1, 0x0(t0)
+       sw      t1, 0x4(t0)
+        nop
+
+_iterate_tap:
+       li      t0, 0xbd001f00
+       lw      t1, 0x0(t0)
+       li      t2, 0x3f
+       beq     t1, t2, _STOP_TEST
+        nop
+
+       addiu   t1, t1, 0x1
+       sw      t1, 0x0(t0)
+        nop
+       b       _CHANGE_TAPS
+        nop
+
+_STOP_TEST:
+       li      t0, 0xbd001f00
+       lw      t1, 0x4(t0)
+       bnez    t1, _load_center_tap
+        nop
+
+       li      t3, 0x8                 /* Default Tap to be used */
+       b       _load_tap_into_reg
+        nop
+
+_load_center_tap:
+       li      t0, 0xbd001f10
+       lw      t1, 0x0(t0)
+       lw      t2, 0x4(t0)
+       add     t3, t1, t2
+       srl     t3, t3, 0x1
+       li      t4, 0x3f
+       and     t3, t3, t4
+
+_load_tap_into_reg:
+       li      t0, 0xb8000000
+       sw      t3, 0x1c(t0)            /* TAP_CONTROL_0_ADDRESS */
+       sw      t3, 0x20(t0)            /* TAP_CONTROL_1_ADDRESS */
+       sw      t3, 0x24(t0)            /* TAP_CONTROL_2_ADDRESS */
+       sw      t3, 0x28(t0)            /* TAP_CONTROL_3_ADDRESS */
+
+        nop
+       jr ra
+        nop
+    END(ddr_tap_tuning)
diff --git a/arch/mips/mach-ath79/reset.c b/arch/mips/mach-ath79/reset.c
index 6a94d886f9..0ab3ab6383 100644
--- a/arch/mips/mach-ath79/reset.c
+++ b/arch/mips/mach-ath79/reset.c
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
  * Copyright (C) 2015-2016 Wills Wang <wills.w...@live.com>
+ * Copyright (C) 2018-2019 Rosy Song <rosys...@rosinson.com>
  */
 
 #include <common.h>
@@ -11,6 +12,44 @@
 #include <mach/ath79.h>
 #include <mach/ar71xx_regs.h>
 
+/* QCA956X ETH_SGMII_SERDES Registers */
+#define SGMII_SERDES_RES_CALIBRATION_LSB 23
+#define SGMII_SERDES_RES_CALIBRATION_MASK 0x07800000
+#define SGMII_SERDES_RES_CALIBRATION_SET(x) \
+       (((x) << SGMII_SERDES_RES_CALIBRATION_LSB) & 
SGMII_SERDES_RES_CALIBRATION_MASK)
+#define SGMII_SERDES_CDR_BW_LSB 1
+#define SGMII_SERDES_CDR_BW_MASK 0x00000006
+#define SGMII_SERDES_CDR_BW_SET(x) \
+       (((x) << SGMII_SERDES_CDR_BW_LSB) & SGMII_SERDES_CDR_BW_MASK)
+#define SGMII_SERDES_TX_DR_CTRL_LSB 4
+#define SGMII_SERDES_TX_DR_CTRL_MASK 0x00000070
+#define SGMII_SERDES_TX_DR_CTRL_SET(x) \
+       (((x) << SGMII_SERDES_TX_DR_CTRL_LSB) & SGMII_SERDES_TX_DR_CTRL_MASK)
+#define SGMII_SERDES_PLL_BW_LSB 8
+#define SGMII_SERDES_PLL_BW_MASK 0x00000100
+#define SGMII_SERDES_PLL_BW_SET(x) \
+       (((x) << SGMII_SERDES_PLL_BW_LSB) & SGMII_SERDES_PLL_BW_MASK)
+#define SGMII_SERDES_EN_SIGNAL_DETECT_LSB 16
+#define SGMII_SERDES_EN_SIGNAL_DETECT_MASK 0x00010000
+#define SGMII_SERDES_EN_SIGNAL_DETECT_SET(x) \
+       (((x) << SGMII_SERDES_EN_SIGNAL_DETECT_LSB) & 
SGMII_SERDES_EN_SIGNAL_DETECT_MASK)
+#define SGMII_SERDES_FIBER_SDO_LSB 17
+#define SGMII_SERDES_FIBER_SDO_MASK 0x00020000
+#define SGMII_SERDES_FIBER_SDO_SET(x) \
+       (((x) << SGMII_SERDES_FIBER_SDO_LSB) & SGMII_SERDES_FIBER_SDO_MASK)
+#define SGMII_SERDES_VCO_REG_LSB 27
+#define SGMII_SERDES_VCO_REG_MASK 0x78000000
+#define SGMII_SERDES_VCO_REG_SET(x) \
+       (((x) << SGMII_SERDES_VCO_REG_LSB) & SGMII_SERDES_VCO_REG_MASK)
+#define SGMII_SERDES_VCO_FAST_LSB 9
+#define SGMII_SERDES_VCO_FAST_MASK 0x00000200
+#define SGMII_SERDES_VCO_FAST_GET(x) \
+       (((x) & SGMII_SERDES_VCO_FAST_MASK) >> SGMII_SERDES_VCO_FAST_LSB)
+#define SGMII_SERDES_VCO_SLOW_LSB 10
+#define SGMII_SERDES_VCO_SLOW_MASK 0x00000400
+#define SGMII_SERDES_VCO_SLOW_GET(x) \
+       (((x) & SGMII_SERDES_VCO_SLOW_MASK) >> SGMII_SERDES_VCO_SLOW_LSB)
+
 void _machine_restart(void)
 {
        void __iomem *base;
@@ -152,6 +191,236 @@ static int eth_init_qca953x(void)
        return 0;
 }
 
+static int qca956x_sgmii_cal(void)
+{
+       int i;
+       u32 reg, rev_sgmii_val;
+       u32 vco_fast, vco_slow;
+       u32 start_val = 0, end_val = 0;
+       void __iomem *gregs = map_physmem(AR71XX_MII_BASE, AR71XX_MII_SIZE,
+                                         MAP_NOCACHE);
+       void __iomem *pregs = map_physmem(AR71XX_PLL_BASE, AR71XX_PLL_SIZE,
+                                         MAP_NOCACHE);
+       void __iomem *rregs = map_physmem(AR71XX_RESET_BASE, AR71XX_RESET_SIZE,
+                                         MAP_NOCACHE);
+       const u32 mask = QCA956X_RESET_SGMII_ASSERT | QCA956X_RESET_SGMII;
+
+       writel(BIT(2) | BIT(0), pregs + QCA956X_PLL_ETH_SGMII_SERDES_REG);
+
+       reg = readl(gregs + QCA956X_GMAC_REG_SGMII_SERDES);
+       vco_fast = SGMII_SERDES_VCO_FAST_GET(reg);
+       vco_slow = SGMII_SERDES_VCO_SLOW_GET(reg);
+
+       /* Set resistor calibration from 0000 to 1111 */
+       for (i = 0; i < 0x10; i++) {
+               reg = (readl(gregs + QCA956X_GMAC_REG_SGMII_SERDES) &
+                     ~SGMII_SERDES_RES_CALIBRATION_MASK) |
+                     SGMII_SERDES_RES_CALIBRATION_SET(i);
+               writel(reg, gregs + QCA956X_GMAC_REG_SGMII_SERDES);
+
+               udelay(50);
+
+               reg = readl(gregs + QCA956X_GMAC_REG_SGMII_SERDES);
+               if (vco_fast != SGMII_SERDES_VCO_FAST_GET(reg) ||
+                   vco_slow != SGMII_SERDES_VCO_SLOW_GET(reg)) {
+                       if (start_val == 0) {
+                               start_val = i;
+                               end_val = i;
+                       } else {
+                               end_val = i;
+                       }
+               }
+               vco_fast = SGMII_SERDES_VCO_FAST_GET(reg);
+               vco_slow = SGMII_SERDES_VCO_SLOW_GET(reg);
+       }
+
+       if (start_val == 0)
+               rev_sgmii_val = 0x7;
+       else
+               rev_sgmii_val = (start_val + end_val) >> 1;
+
+       writel((readl(gregs + QCA956X_GMAC_REG_SGMII_SERDES) &
+              ~SGMII_SERDES_RES_CALIBRATION_MASK) |
+              SGMII_SERDES_RES_CALIBRATION_SET(rev_sgmii_val),
+              gregs + QCA956X_GMAC_REG_SGMII_SERDES);
+
+       writel(BIT(2) | BIT(0), pregs + QCA956X_PLL_ETH_SGMII_SERDES_REG);
+
+       reg = readl(gregs + QCA956X_GMAC_REG_SGMII_SERDES);
+       writel(SGMII_SERDES_CDR_BW_SET(3) | SGMII_SERDES_TX_DR_CTRL_SET(1) |
+              SGMII_SERDES_PLL_BW_SET(1) | 
SGMII_SERDES_EN_SIGNAL_DETECT_SET(1) |
+              SGMII_SERDES_FIBER_SDO_SET(1) | SGMII_SERDES_VCO_REG_SET(3) | 
reg,
+              gregs + QCA956X_GMAC_REG_SGMII_SERDES);
+
+       setbits_be32(rregs + QCA956X_RESET_REG_RESET_MODULE, mask);
+       mdelay(1);
+       clrbits_be32(rregs + QCA956X_RESET_REG_RESET_MODULE, mask);
+       mdelay(1);
+
+       while (!(readl(gregs + QCA956X_GMAC_REG_SGMII_SERDES) & BIT(15)))
+               /* NOP */;
+
+       return 0;
+}
+
+static int qca956x_sgmii_setup(void)
+{
+       int i;
+       u32 s = 0, reg = 0;
+       u32 _regs[] = {
+               BIT(4), /* HW_RX_125M_N */
+               BIT(2), /* RX_125M_N */
+               BIT(3), /* TX_125M_N */
+               BIT(0), /* RX_CLK_N */
+               BIT(1), /* TX_CLK_N */
+       };
+       void __iomem *gregs = map_physmem(AR71XX_MII_BASE, AR71XX_MII_SIZE,
+                                         MAP_NOCACHE);
+
+       /* Force sgmii mode */
+       writel(BIT(6) | BIT(15) | BIT(8), gregs + QCA956X_GMAC_REG_MR_AN_CTRL);
+       udelay(10);
+       writel(0x2 | BIT(5) | (0x2 << 6), gregs + 
QCA956X_GMAC_REG_SGMII_CONFIG);
+
+       /* SGMII reset sequence sugguest by qca systems team. */
+       writel(0, gregs + QCA956X_GMAC_REG_SGMII_RESET);
+       for (i = 0; i < ARRAY_SIZE(_regs); i++) {
+               reg |= _regs[i];
+               writel(reg, gregs + QCA956X_GMAC_REG_SGMII_RESET);
+       }
+
+       writel(readl(gregs + QCA956X_GMAC_REG_MR_AN_CTRL) & ~BIT(15),
+              gregs + QCA956X_GMAC_REG_MR_AN_CTRL);
+
+       /*
+        * WARNING: Across resets SGMII link status goes to weird state.
+        * if 0xb8070058 (SGMII_DEBUG Register) reads other than 0xf or 0x10
+        * for sure we are in bad state.
+        * Issue a PHY RESET in MR_AN_CONTROL_ADDRESS to keep going.
+        */
+       i = 0;
+       s = (readl(gregs + QCA956X_GMAC_REG_SGMII_DEBUG) & 0xff);
+       while (!(s == 0xf || s == 0x10)) {
+               writel(readl(gregs + QCA956X_GMAC_REG_MR_AN_CTRL) | BIT(15),
+                      gregs + QCA956X_GMAC_REG_MR_AN_CTRL);
+               udelay(100);
+               writel(readl(gregs + QCA956X_GMAC_REG_MR_AN_CTRL) & ~BIT(15),
+                      gregs + QCA956X_GMAC_REG_MR_AN_CTRL);
+               if (i++ == 10)
+                       break;
+               s = (readl(gregs + QCA956X_GMAC_REG_SGMII_DEBUG) & 0xff);
+       }
+
+       return 0;
+}
+
+static int qca956x_s17_reset(void)
+{
+       void __iomem *regs = map_physmem(AR71XX_GPIO_BASE, AR71XX_GPIO_SIZE,
+                                         MAP_NOCACHE);
+       void __iomem *rregs = map_physmem(AR71XX_RESET_BASE, AR71XX_RESET_SIZE,
+                                         MAP_NOCACHE);
+       const u32 mask = QCA956X_RESET_SGMII_ASSERT | QCA956X_RESET_SGMII |
+                        QCA956X_RESET_EXTERNAL | QCA956X_RESET_SGMII_ANALOG |
+                        QCA956X_RESET_SWITCH;
+       /* Bits(Reserved in datasheet) should be set to 1 */
+       const u32 mask_r = QCA956X_RESET_SGMII_ASSERT | QCA956X_RESET_SGMII |
+                        QCA956X_RESET_EXTERNAL;
+
+       setbits_be32(rregs + QCA956X_RESET_REG_RESET_MODULE, mask);
+       mdelay(1);
+       clrbits_be32(rregs + QCA956X_RESET_REG_RESET_MODULE, mask_r);
+       mdelay(1);
+
+       /* Reset s17 switch(GPIO11) SYS_RST_L */
+       writel(readl(regs + AR71XX_GPIO_REG_OE) & ~BIT(11),
+              regs + AR71XX_GPIO_REG_OE);
+       udelay(100);
+
+       writel(readl(regs + AR71XX_GPIO_REG_OUT) & ~BIT(11),
+              regs + AR71XX_GPIO_REG_OUT);
+       udelay(100);
+       writel(readl(regs + AR71XX_GPIO_REG_OUT) | BIT(11),
+              regs + AR71XX_GPIO_REG_OUT);
+
+       return 0;
+}
+
+static int qca956x_init_mdio(void)
+{
+       u32 reg;
+       void __iomem *regs = map_physmem(AR71XX_GPIO_BASE, AR71XX_GPIO_SIZE,
+                                               MAP_NOCACHE);
+       void __iomem *rregs = map_physmem(AR71XX_RESET_BASE, AR71XX_RESET_SIZE,
+                                         MAP_NOCACHE);
+       const u32 mask = QCA956X_RESET_GE0_MDIO | QCA956X_RESET_GE0_MAC |
+                        QCA956X_RESET_GE1_MDIO | QCA956X_RESET_GE1_MAC;
+
+       setbits_be32(rregs + QCA956X_RESET_REG_RESET_MODULE, mask);
+       mdelay(1);
+       clrbits_be32(rregs + QCA956X_RESET_REG_RESET_MODULE, mask);
+       mdelay(1);
+
+       /* GPIO4 as MDI */
+       reg = readl(regs + QCA956X_GPIO_REG_IN_ENABLE3);
+       reg &= ~(0xff << 16);
+       reg |= (0x4 << 16);
+       writel(reg, regs + QCA956X_GPIO_REG_IN_ENABLE3);
+
+       /* GPIO4 as MDO */
+       reg = readl(regs + QCA956X_GPIO_REG_OUT_FUNC1);
+       reg &= ~0xff;
+       reg |= 0x20;
+       writel(reg, regs + QCA956X_GPIO_REG_OUT_FUNC1);
+
+       /* Init MDC(GPIO3) / MDIO(GPIO4) */
+       reg = readl(regs + AR71XX_GPIO_REG_OE);
+       reg &= ~BIT(4);
+       writel(reg, regs + AR71XX_GPIO_REG_OE);
+       udelay(100);
+
+       reg = readl(regs + AR71XX_GPIO_REG_OE);
+       reg &= ~BIT(3);
+       writel(reg, regs + AR71XX_GPIO_REG_OE);
+       udelay(100);
+
+       /* GPIO3 as MDI */
+       reg = readl(regs + QCA956X_GPIO_REG_OUT_FUNC0);
+       reg &= ~(0xff << 24);
+       reg |= (0x21 << 24);
+       writel(reg, regs + QCA956X_GPIO_REG_OUT_FUNC0);
+
+       return 0;
+}
+
+static int eth_init_qca956x(void)
+{
+       void __iomem *pregs = map_physmem(AR71XX_PLL_BASE, AR71XX_PLL_SIZE,
+                                         MAP_NOCACHE);
+       void __iomem *gregs = map_physmem(AR71XX_MII_BASE, AR71XX_MII_SIZE,
+                                         MAP_NOCACHE);
+
+       qca956x_sgmii_cal();
+       qca956x_s17_reset();
+       qca956x_init_mdio();
+
+       if (ath79_get_bootstrap() & QCA956X_BOOTSTRAP_REF_CLK_40)
+               writel(0x45500, pregs + QCA956X_PLL_SWITCH_CLK_CTRL_REG);
+       else
+               writel(0xc5200, pregs + QCA956X_PLL_SWITCH_CLK_CTRL_REG);
+
+       qca956x_sgmii_setup();
+
+       writel((3 << 16) | (3 << 14) | (1 << 0) | (1 << 6),
+              gregs + QCA956X_GMAC_REG_ETH_CFG);
+
+       writel((1 << 31) | (2 << 28) | (2 << 26) | (1 << 25),
+              pregs + QCA956X_PLL_ETH_XMII_CTRL_REG);
+       mdelay(1);
+
+       return 0;
+}
+
 int ath79_eth_reset(void)
 {
        /*
@@ -164,6 +433,8 @@ int ath79_eth_reset(void)
                return eth_init_ar934x();
        if (soc_is_qca953x())
                return eth_init_qca953x();
+       if (soc_is_qca956x())
+               return eth_init_qca956x();
 
        return -EINVAL;
 }
diff --git a/board/qca/ap152/Kconfig b/board/qca/ap152/Kconfig
new file mode 100644
index 0000000000..f6ad498e85
--- /dev/null
+++ b/board/qca/ap152/Kconfig
@@ -0,0 +1,15 @@
+if TARGET_AP152
+
+config SYS_VENDOR
+       default "qca"
+
+config SYS_BOARD
+       default "ap152"
+
+config SYS_CONFIG_NAME
+       default "ap152"
+
+config SYS_TEXT_BASE
+       default 0x9f000000
+
+endif
diff --git a/board/qca/ap152/MAINTAINERS b/board/qca/ap152/MAINTAINERS
new file mode 100644
index 0000000000..785ec2766d
--- /dev/null
+++ b/board/qca/ap152/MAINTAINERS
@@ -0,0 +1,6 @@
+AP152 BOARD
+M:     Rosy Song <rosys...@rosinson.com>
+S:     Maintained
+F:     board/qca/ap152/
+F:     include/configs/ap152.h
+F:     configs/ap152_defconfig
diff --git a/board/qca/ap152/Makefile b/board/qca/ap152/Makefile
new file mode 100644
index 0000000000..4270afa129
--- /dev/null
+++ b/board/qca/ap152/Makefile
@@ -0,0 +1,3 @@
+# SPDX-License-Identifier: GPL-2.0+
+
+obj-y  = ap152.o
diff --git a/board/qca/ap152/ap152.c b/board/qca/ap152/ap152.c
new file mode 100644
index 0000000000..30cd56563b
--- /dev/null
+++ b/board/qca/ap152/ap152.c
@@ -0,0 +1,81 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018 Rosy Song <rosys...@rosinson.com>
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/addrspace.h>
+#include <asm/types.h>
+#include <mach/ar71xx_regs.h>
+#include <mach/ddr.h>
+#include <mach/ath79.h>
+#include <debug_uart.h>
+
+#define RST_RESET_RTC_RESET_LSB 27
+#define RST_RESET_RTC_RESET_MASK 0x08000000
+#define RST_RESET_RTC_RESET_SET(x) \
+       (((x) << RST_RESET_RTC_RESET_LSB) & RST_RESET_RTC_RESET_MASK)
+
+#ifdef CONFIG_DEBUG_UART_BOARD_INIT
+void board_debug_uart_init(void)
+{
+       void __iomem *regs;
+       u32 val;
+
+       regs = map_physmem(AR71XX_GPIO_BASE, AR71XX_GPIO_SIZE,
+                          MAP_NOCACHE);
+
+       /* UART : RX18, TX22 done
+        * GPIO18 as input, GPIO22 as output
+        */
+       val = readl(regs + AR71XX_GPIO_REG_OE);
+       val |= QCA956X_GPIO(18);
+       val &= ~QCA956X_GPIO(22);
+       writel(val, regs + AR71XX_GPIO_REG_OE);
+
+       /*
+        * Enable GPIO22 as UART0_SOUT
+        */
+       val = readl(regs + QCA956X_GPIO_REG_OUT_FUNC5);
+       val &= ~QCA956X_GPIO_MUX_MASK(16);
+       val |= QCA956X_GPIO_OUT_MUX_UART0_SOUT << 16;
+       writel(val, regs + QCA956X_GPIO_REG_OUT_FUNC5);
+
+       /*
+        * Enable GPIO18 as UART0_SIN
+        */
+       val = readl(regs + QCA956X_GPIO_REG_IN_ENABLE0);
+       val &= ~QCA956X_GPIO_MUX_MASK(8);
+       val |= QCA956X_GPIO_IN_MUX_UART0_SIN << 8;
+       writel(val, regs + QCA956X_GPIO_REG_IN_ENABLE0);
+
+       /*
+        * Enable GPIO22 output
+        */
+       val = readl(regs + AR71XX_GPIO_REG_OUT);
+       val |= QCA956X_GPIO(22);
+       writel(val, regs + AR71XX_GPIO_REG_OUT);
+}
+#endif
+
+int board_early_init_f(void)
+{
+       u32 reg;
+       void __iomem *rst_regs = map_physmem(AR71XX_RESET_BASE,
+                                                        AR71XX_RESET_SIZE, 
MAP_NOCACHE);
+
+#ifndef CONFIG_SKIP_LOWLEVEL_INIT
+       /* CPU:775, DDR:650, AHB:258 */
+       qca956x_pll_init();
+       qca956x_ddr_init();
+#endif
+
+       /* Take WMAC out of reset */
+       reg = readl(rst_regs + QCA956X_RESET_REG_RESET_MODULE);
+       reg &= (~RST_RESET_RTC_RESET_SET(1));
+       writel(reg, rst_regs + QCA956X_RESET_REG_RESET_MODULE);
+
+       ath79_eth_reset();
+       return 0;
+}
diff --git a/configs/ap152_defconfig b/configs/ap152_defconfig
new file mode 100644
index 0000000000..21cb6eb742
--- /dev/null
+++ b/configs/ap152_defconfig
@@ -0,0 +1,49 @@
+CONFIG_MIPS=y
+CONFIG_SYS_TEXT_BASE=0x9F000000
+CONFIG_SYS_MALLOC_F_LEN=0x800
+CONFIG_SYS_CACHE_SIZE_AUTO=y
+CONFIG_DEBUG_UART_BOARD_INIT=y
+CONFIG_DEBUG_UART_BASE=0xb8020000
+CONFIG_DEBUG_UART_CLOCK=25000000
+CONFIG_ARCH_ATH79=y
+CONFIG_TARGET_AP152=y
+CONFIG_DEBUG_UART=y
+CONFIG_BOOTDELAY=3
+CONFIG_USE_BOOTARGS=y
+CONFIG_BOOTARGS="console=ttyS0,115200 root=/dev/mtdblock2 rootfstype=squashfs"
+CONFIG_DISPLAY_CPUINFO=y
+CONFIG_BOARD_EARLY_INIT_F=y
+CONFIG_SYS_PROMPT="ap152 # "
+# CONFIG_CMD_BDI is not set
+# CONFIG_CMD_CONSOLE is not set
+# CONFIG_CMD_ELF is not set
+# CONFIG_CMD_XIMG is not set
+# CONFIG_CMD_EXPORTENV is not set
+# CONFIG_CMD_IMPORTENV is not set
+# CONFIG_CMD_EDITENV is not set
+# CONFIG_CMD_CRC32 is not set
+CONFIG_CMD_MEMTEST=y
+# CONFIG_CMD_FLASH is not set
+CONFIG_CMD_SF=y
+CONFIG_CMD_SPI=y
+CONFIG_CMD_MTDPARTS=y
+CONFIG_MTDIDS_DEFAULT="nor0=spi-flash.0"
+CONFIG_MTDPARTS_DEFAULT="mtdparts=spi-flash.0:256k(u-boot),64k(u-boot-env),6336k(rootfs),1472k(uImage),64k(ART)"
+# CONFIG_ISO_PARTITION is not set
+CONFIG_DEFAULT_DEVICE_TREE="ap152"
+CONFIG_ENV_IS_IN_SPI_FLASH=y
+# CONFIG_NET is not set
+CONFIG_DM_SPI_FLASH=y
+CONFIG_SPI_FLASH=y
+CONFIG_SPI_FLASH_BAR=y
+CONFIG_SPI_FLASH_WINBOND=y
+CONFIG_SPI_FLASH_DATAFLASH=y
+CONFIG_SPI_FLASH_MTD=y
+CONFIG_PINCTRL=y
+CONFIG_DM_SERIAL=y
+CONFIG_DEBUG_UART_SHIFT=2
+CONFIG_SYS_NS16550=y
+CONFIG_SPI=y
+CONFIG_DM_SPI=y
+CONFIG_ATH79_SPI=y
+CONFIG_LZMA=y
diff --git a/include/configs/ap152.h b/include/configs/ap152.h
new file mode 100644
index 0000000000..bc88506dff
--- /dev/null
+++ b/include/configs/ap152.h
@@ -0,0 +1,54 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2018 Rosy Song <rosys...@rosinson.com>
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+#define CONFIG_SYS_HZ                   1000
+#define CONFIG_SYS_MHZ                  375
+#define CONFIG_SYS_MIPS_TIMER_FREQ      (CONFIG_SYS_MHZ * 1000000)
+
+#define CONFIG_SYS_MONITOR_BASE         CONFIG_SYS_TEXT_BASE
+
+#define CONFIG_SYS_MALLOC_LEN           0x40000
+#define CONFIG_SYS_BOOTPARAMS_LEN       0x20000
+
+#define CONFIG_SYS_SDRAM_BASE           0x80000000
+#define CONFIG_SYS_LOAD_ADDR            0x81000000
+
+#define CONFIG_SYS_INIT_RAM_ADDR        0xbd000000
+#define CONFIG_SYS_INIT_RAM_SIZE        0x2000
+#define CONFIG_SYS_INIT_SP_ADDR \
+       (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_INIT_RAM_SIZE - 1)
+
+/*
+ * Serial Port
+ */
+#define CONFIG_SYS_NS16550_CLK          25000000
+#define CONFIG_SYS_BAUDRATE_TABLE \
+       {9600, 19200, 38400, 57600, 115200}
+
+#define CONFIG_BOOTCOMMAND              "sf probe;" \
+                                       "mtdparts default;" \
+                                       "bootm 0x9f060000"
+
+#define CONFIG_EXTRA_ENV_SETTINGS \
+       "ipaddr=192.168.1.1\0" \
+       "serverip=192.168.1.10\0" \
+
+#define CONFIG_ENV_SPI_MAX_HZ           25000000
+#define CONFIG_ENV_OFFSET               0x40000
+#define CONFIG_ENV_SECT_SIZE            0x10000
+#define CONFIG_ENV_SIZE                 0x10000
+
+/* Miscellaneous configurable options */
+
+/*
+ * Diagnostics
+ */
+#define CONFIG_SYS_MEMTEST_START        0x80100000
+#define CONFIG_SYS_MEMTEST_END          0x83f00000
+
+#endif  /* __CONFIG_H */
-- 
2.17.1

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
https://lists.denx.de/listinfo/u-boot

Reply via email to