uboot-ath79: add initial support for QCA955x SoCs
authorINAGAKI Hiroshi <musashino.open@gmail.com>
Sat, 31 Aug 2024 08:42:53 +0000 (17:42 +0900)
committerHauke Mehrtens <hauke@hauke-m.de>
Sat, 19 Oct 2024 15:56:46 +0000 (17:56 +0200)
Add initial support for Qualcomm Atheros QCA955x series SoCs.
This support was based on the QCA956x support, QSDK, GPL tar of TP-Link
Archer C5 v1.20.

Signed-off-by: INAGAKI Hiroshi <musashino.open@gmail.com>
Link: https://github.com/openwrt/openwrt/pull/16297
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
package/boot/uboot-ath79/patches/001-mips-ath79-add-initial-support-for-QCA955x-SoCs.patch [new file with mode: 0644]

diff --git a/package/boot/uboot-ath79/patches/001-mips-ath79-add-initial-support-for-QCA955x-SoCs.patch b/package/boot/uboot-ath79/patches/001-mips-ath79-add-initial-support-for-QCA955x-SoCs.patch
new file mode 100644 (file)
index 0000000..7d6075c
--- /dev/null
@@ -0,0 +1,1020 @@
+From 7c59f0fe98eb20db8dfbf4d3c67d6043a9efe116 Mon Sep 17 00:00:00 2001
+From: INAGAKI Hiroshi <musashino.open@gmail.com>
+Date: Sat, 22 Jun 2024 20:45:31 +0900
+Subject: [PATCH 1/2] mips: ath79: add initial support for QCA955x SoCs
+
+---
+ arch/mips/dts/qca955x.dtsi                    |  70 +++++
+ arch/mips/mach-ath79/Kconfig                  |   9 +
+ arch/mips/mach-ath79/Makefile                 |   1 +
+ .../mach-ath79/include/mach/ar71xx_regs.h     |  63 ++++
+ arch/mips/mach-ath79/include/mach/ath79.h     |   3 +
+ arch/mips/mach-ath79/qca955x/Makefile         |   5 +
+ arch/mips/mach-ath79/qca955x/clk.c            | 286 ++++++++++++++++++
+ arch/mips/mach-ath79/qca955x/cpu.c            |   7 +
+ arch/mips/mach-ath79/qca955x/ddr.c            | 222 ++++++++++++++
+ .../mips/mach-ath79/qca955x/qca955x-ddr-tap.S | 191 ++++++++++++
+ 10 files changed, 857 insertions(+)
+ create mode 100644 arch/mips/dts/qca955x.dtsi
+ create mode 100644 arch/mips/mach-ath79/qca955x/Makefile
+ create mode 100644 arch/mips/mach-ath79/qca955x/clk.c
+ create mode 100644 arch/mips/mach-ath79/qca955x/cpu.c
+ create mode 100644 arch/mips/mach-ath79/qca955x/ddr.c
+ create mode 100644 arch/mips/mach-ath79/qca955x/qca955x-ddr-tap.S
+
+diff --git a/arch/mips/dts/qca955x.dtsi b/arch/mips/dts/qca955x.dtsi
+new file mode 100644
+index 0000000000..93bc659743
+--- /dev/null
++++ b/arch/mips/dts/qca955x.dtsi
+@@ -0,0 +1,70 @@
++// SPDX-License-Identifier: GPL-2.0+
++/*
++ * Copyright (C) 2024 INAGAKI Hiroshi <musashino.open@gmail.com>
++ */
++
++#include "skeleton.dtsi"
++
++/ {
++      compatible = "qca,qca955x";
++
++      #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";
++                      };
++              };
++
++              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 2fa628568a..21ac4b9f95 100644
+--- a/arch/mips/mach-ath79/Kconfig
++++ b/arch/mips/mach-ath79/Kconfig
+@@ -34,6 +34,15 @@ config SOC_QCA953X
+       help
+         This supports QCA/Atheros qca953x family SOCs.
++config SOC_QCA955X
++      bool
++      select MIPS_TUNE_74KC
++      select SUPPORT_BIG_ENDIAN
++      select SUPPORTS_CPU_MIPS32_R1
++      select SUPPORTS_CPU_MIPS32_R2
++      help
++        This supports QCA/Atheros qca955x family SOCs.
++
+ config SOC_QCA956X
+       bool
+       select MIPS_TUNE_74KC
+diff --git a/arch/mips/mach-ath79/Makefile b/arch/mips/mach-ath79/Makefile
+index fbd40c02be..cd8c1f0334 100644
+--- a/arch/mips/mach-ath79/Makefile
++++ b/arch/mips/mach-ath79/Makefile
+@@ -7,4 +7,5 @@ obj-y += dram.o
+ obj-$(CONFIG_SOC_AR933X)      += ar933x/
+ obj-$(CONFIG_SOC_AR934X)      += ar934x/
+ obj-$(CONFIG_SOC_QCA953X)     += qca953x/
++obj-$(CONFIG_SOC_QCA955X)     += qca955x/
+ 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 5888f6eb28..1e4860ec9c 100644
+--- a/arch/mips/mach-ath79/include/mach/ar71xx_regs.h
++++ b/arch/mips/mach-ath79/include/mach/ar71xx_regs.h
+@@ -174,11 +174,17 @@
+ #define QCA955X_WMAC_BASE \
+       (AR71XX_APB_BASE + 0x00100000)
+ #define QCA955X_WMAC_SIZE                             0x20000
++#define QCA955X_RTC_BASE \
++      (AR71XX_APB_BASE + 0x00107000)
++#define QCA955X_RTC_SIZE                              0x1000
+ #define QCA955X_EHCI0_BASE                            0x1b000000
+ #define QCA955X_EHCI1_BASE                            0x1b400000
+ #define QCA955X_EHCI_SIZE                             0x1000
+ #define QCA955X_NFC_BASE                              0x1b800200
+ #define QCA955X_NFC_SIZE                              0xb8
++#define QCA955X_SRIF_BASE \
++      (AR71XX_APB_BASE + 0x00116000)
++#define QCA955X_SRIF_SIZE                             0x1000
+ #define QCA956X_PCI_MEM_BASE1                         0x12000000
+ #define QCA956X_PCI_MEM_SIZE                          0x02000000
+@@ -285,6 +291,17 @@
+ #define QCA953X_DDR_REG_CTL_CONF                      0x108
+ #define QCA953X_DDR_REG_CONFIG3                               0x15c
++#define QCA955X_DDR_REG_TAP_CTRL2                     0x24
++#define QCA955X_DDR_REG_TAP_CTRL3                     0x28
++#define QCA955X_DDR_REG_DDR2_CONFIG                   0xb8
++#define QCA955X_DDR_REG_DDR2_EMR2                     0xbc
++#define QCA955X_DDR_REG_DDR2_EMR3                     0xc0
++#define QCA955X_DDR_REG_BURST                         0xc4
++#define QCA955X_DDR_REG_BURST2                                0xc8
++#define QCA955X_DDR_REG_TIMEOUT_MAX                   0xcc
++#define QCA955X_DDR_REG_CTL_CONF                      0x108
++#define QCA955X_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
+@@ -500,6 +517,8 @@
+ #define QCA955X_PLL_DDR_CONFIG_REG                    0x04
+ #define QCA955X_PLL_CLK_CTRL_REG                      0x08
+ #define QCA955X_PLL_ETH_XMII_CONTROL_REG              0x28
++#define QCA955X_PLL_DDR_DIT_FRAC_REG                  0x40
++#define QCA955X_PLL_CPU_DIT_FRAC_REG                  0x44
+ #define QCA955X_PLL_ETH_SGMII_CONTROL_REG             0x48
+ #define QCA955X_PLL_CPU_CONFIG_NFRAC_SHIFT            0
+@@ -508,8 +527,11 @@
+ #define QCA955X_PLL_CPU_CONFIG_NINT_MASK              0x3f
+ #define QCA955X_PLL_CPU_CONFIG_REFDIV_SHIFT           12
+ #define QCA955X_PLL_CPU_CONFIG_REFDIV_MASK            0x1f
++#define QCA955X_PLL_CPU_CONFIG_RANGE_SHIFT            17
++#define QCA955X_PLL_CPU_CONFIG_RANGE_MASK             0x3
+ #define QCA955X_PLL_CPU_CONFIG_OUTDIV_SHIFT           19
+ #define QCA955X_PLL_CPU_CONFIG_OUTDIV_MASK            0x3
++#define QCA955X_PLL_CPU_CONFIG_PLLPWD                 BIT(30)
+ #define QCA955X_PLL_DDR_CONFIG_NFRAC_SHIFT            0
+ #define QCA955X_PLL_DDR_CONFIG_NFRAC_MASK             0x3ff
+@@ -517,8 +539,11 @@
+ #define QCA955X_PLL_DDR_CONFIG_NINT_MASK              0x3f
+ #define QCA955X_PLL_DDR_CONFIG_REFDIV_SHIFT           16
+ #define QCA955X_PLL_DDR_CONFIG_REFDIV_MASK            0x1f
++#define QCA955X_PLL_DDR_CONFIG_RANGE_SHIFT            21
++#define QCA955X_PLL_DDR_CONFIG_RANGE_MASK             0x3
+ #define QCA955X_PLL_DDR_CONFIG_OUTDIV_SHIFT           23
+ #define QCA955X_PLL_DDR_CONFIG_OUTDIV_MASK            0x7
++#define QCA955X_PLL_DDR_CONFIG_PLLPWD                 BIT(30)
+ #define QCA955X_PLL_CLK_CTRL_CPU_PLL_BYPASS           BIT(2)
+ #define QCA955X_PLL_CLK_CTRL_DDR_PLL_BYPASS           BIT(3)
+@@ -533,6 +558,24 @@
+ #define QCA955X_PLL_CLK_CTRL_DDRCLK_FROM_DDRPLL               BIT(21)
+ #define QCA955X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL               BIT(24)
++#define QCA955X_PLL_DDR_DIT_NFRAC_MAX_SHIFT           0
++#define QCA955X_PLL_DDR_DIT_NFRAC_MAX_MASK            0x3ff
++#define QCA955X_PLL_DDR_DIT_NFRAC_MIN_SHIFT           10
++#define QCA955X_PLL_DDR_DIT_NFRAC_MIN_MASK            0x3ff
++#define QCA955X_PLL_DDR_DIT_NFRAC_STEP_SHIFT          20
++#define QCA955X_PLL_DDR_DIT_NFRAC_STEP_MASK           0x7f
++#define QCA955X_PLL_DDR_DIT_UPD_CNT_SHIFT             27
++#define QCA955X_PLL_DDR_DIT_UPD_CNT_MASK              0xf
++
++#define QCA955X_PLL_CPU_DIT_NFRAC_MAX_SHIFT           0
++#define QCA955X_PLL_CPU_DIT_NFRAC_MAX_MASK            0x3f
++#define QCA955X_PLL_CPU_DIT_NFRAC_MIN_SHIFT           6
++#define QCA955X_PLL_CPU_DIT_NFRAC_MIN_MASK            0x3f
++#define QCA955X_PLL_CPU_DIT_NFRAC_STEP_SHIFT          12
++#define QCA955X_PLL_CPU_DIT_NFRAC_STEP_MASK           0x3f
++#define QCA955X_PLL_CPU_DIT_UPD_CNT_SHIFT             18
++#define QCA955X_PLL_CPU_DIT_UPD_CNT_MASK              0x3f
++
+ #define QCA956X_PLL_CPU_CONFIG_REG                    0x00
+ #define QCA956X_PLL_CPU_CONFIG1_REG                   0x04
+ #define QCA956X_PLL_DDR_CONFIG_REG                    0x08
+@@ -1027,6 +1070,7 @@
+ #define QCA955X_GPIO_REG_OUT_FUNC3                    0x38
+ #define QCA955X_GPIO_REG_OUT_FUNC4                    0x3c
+ #define QCA955X_GPIO_REG_OUT_FUNC5                    0x40
++#define QCA955X_GPIO_REG_IN_ENABLE0                   0x44
+ #define QCA955X_GPIO_REG_FUNC                         0x6c
+ #define QCA956X_GPIO_REG_OUT_FUNC0                    0x2c
+@@ -1220,6 +1264,25 @@
+ #define QCA953X_SRIF_DPLL2_OUTDIV_SHIFT                       13
+ #define QCA953X_SRIF_DPLL2_OUTDIV_MASK                        0x7
++#define QCA955X_SRIF_BB_DPLL1_REG                     0x180
++#define QCA955X_SRIF_BB_DPLL2_REG                     0x184
++#define QCA955X_SRIF_BB_DPLL3_REG                     0x188
++
++#define QCA955X_SRIF_CPU_DPLL1_REG                    0xf00
++#define QCA955X_SRIF_CPU_DPLL2_REG                    0xf04
++#define QCA955X_SRIF_CPU_DPLL3_REG                    0xf08
++
++#define QCA955X_SRIF_DDR_DPLL1_REG                    0xec0
++#define QCA955X_SRIF_DDR_DPLL2_REG                    0xec4
++#define QCA955X_SRIF_DDR_DPLL3_REG                    0xec8
++
++#define QCA955X_SRIF_PCIE_DPLL1_REG                   0xc80
++#define QCA955X_SRIF_PCIE_DPLL2_REG                   0xc84
++#define QCA955X_SRIF_PCIE_DPLL3_REG                   0xc88
++
++#define QCA955X_SRIF_PMU1_REG                         0xcc0
++#define QCA955X_SRIF_PMU2_REG                         0xcc4
++
+ #define QCA956X_SRIF_BB_DPLL1_REG                     0x180
+ #define QCA956X_SRIF_BB_DPLL2_REG                     0x184
+ #define QCA956X_SRIF_BB_DPLL3_REG                     0x188
+diff --git a/arch/mips/mach-ath79/include/mach/ath79.h b/arch/mips/mach-ath79/include/mach/ath79.h
+index 2eda38885e..445cb2711b 100644
+--- a/arch/mips/mach-ath79/include/mach/ath79.h
++++ b/arch/mips/mach-ath79/include/mach/ath79.h
+@@ -148,6 +148,9 @@ 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 qca955x_pll_init(void);
++void qca955x_ddr_init(void);
++
+ void qca956x_pll_init(void);
+ void qca956x_ddr_init(void);
+ #endif /* __ASM_MACH_ATH79_H */
+diff --git a/arch/mips/mach-ath79/qca955x/Makefile b/arch/mips/mach-ath79/qca955x/Makefile
+new file mode 100644
+index 0000000000..a405f9a12d
+--- /dev/null
++++ b/arch/mips/mach-ath79/qca955x/Makefile
+@@ -0,0 +1,5 @@
++# SPDX-License-Identifier: GPL-2.0+
++
++obj-y += cpu.o
++obj-y += clk.o
++obj-y += ddr.o qca955x-ddr-tap.o
+diff --git a/arch/mips/mach-ath79/qca955x/clk.c b/arch/mips/mach-ath79/qca955x/clk.c
+new file mode 100644
+index 0000000000..20c93de163
+--- /dev/null
++++ b/arch/mips/mach-ath79/qca955x/clk.c
+@@ -0,0 +1,286 @@
++// SPDX-License-Identifier: GPL-2.0+
++/*
++ * Copyright (C) 2024 INAGAKI Hiroshi <musashino.open@gmail.com>
++ *
++ * based on QCA956x support and QSDK
++ */
++
++#include <clock_legacy.h>
++#include <log.h>
++#include <asm/global_data.h>
++#include <asm/io.h>
++#include <asm/addrspace.h>
++#include <asm/types.h>
++#include <linux/bitfield.h>
++#include <linux/bitops.h>
++#include <mach/ar71xx_regs.h>
++#include <mach/ath79.h>
++#include <wait_bit.h>
++
++#define QCA955X_PLL_CPU_CONFIG_OUTDIV_FMASK           \
++              QCA955X_PLL_CPU_CONFIG_OUTDIV_MASK      \
++              << QCA955X_PLL_CPU_CONFIG_OUTDIV_SHIFT
++#define QCA955X_PLL_CPU_CONFIG_RANGE_FMASK            \
++              QCA955X_PLL_CPU_CONFIG_RANGE_MASK       \
++              << QCA955X_PLL_CPU_CONFIG_RANGE_SHIFT
++#define QCA955X_PLL_CPU_CONFIG_REFDIV_FMASK           \
++              QCA955X_PLL_CPU_CONFIG_REFDIV_MASK      \
++              << QCA955X_PLL_CPU_CONFIG_REFDIV_SHIFT
++#define QCA955X_PLL_CPU_CONFIG_NINT_FMASK             \
++              QCA955X_PLL_CPU_CONFIG_NINT_MASK        \
++              << QCA955X_PLL_CPU_CONFIG_NINT_SHIFT
++#define QCA955X_PLL_CPU_CONFIG_NFRAC_FMASK            \
++              QCA955X_PLL_CPU_CONFIG_NFRAC_MASK       \
++              << QCA955X_PLL_CPU_CONFIG_NFRAC_SHIFT
++
++#define QCA955X_PLL_DDR_CONFIG_OUTDIV_FMASK           \
++              QCA955X_PLL_DDR_CONFIG_OUTDIV_MASK      \
++              << QCA955X_PLL_DDR_CONFIG_OUTDIV_SHIFT
++#define QCA955X_PLL_DDR_CONFIG_RANGE_FMASK            \
++              QCA955X_PLL_DDR_CONFIG_RANGE_MASK       \
++              << QCA955X_PLL_DDR_CONFIG_RANGE_SHIFT
++#define QCA955X_PLL_DDR_CONFIG_REFDIV_FMASK           \
++              QCA955X_PLL_DDR_CONFIG_REFDIV_MASK      \
++              << QCA955X_PLL_DDR_CONFIG_REFDIV_SHIFT
++#define QCA955X_PLL_DDR_CONFIG_NINT_FMASK             \
++              QCA955X_PLL_DDR_CONFIG_NINT_MASK        \
++              << QCA955X_PLL_DDR_CONFIG_NINT_SHIFT
++#define QCA955X_PLL_DDR_CONFIG_NFRAC_FMASK            \
++              QCA955X_PLL_DDR_CONFIG_NFRAC_MASK       \
++              << QCA955X_PLL_DDR_CONFIG_NFRAC_SHIFT
++
++#define QCA955X_PLL_CLK_CTRL_AHB_POST_DIV_FMASK               \
++              QCA955X_PLL_CLK_CTRL_AHB_POST_DIV_MASK  \
++              << QCA955X_PLL_CLK_CTRL_AHB_POST_DIV_SHIFT
++#define QCA955X_PLL_CLK_CTRL_DDR_POST_DIV_FMASK               \
++              QCA955X_PLL_CLK_CTRL_DDR_POST_DIV_MASK  \
++              << QCA955X_PLL_CLK_CTRL_DDR_POST_DIV_SHIFT
++#define QCA955X_PLL_CLK_CTRL_CPU_POST_DIV_FMASK               \
++              QCA955X_PLL_CLK_CTRL_CPU_POST_DIV_MASK  \
++              << QCA955X_PLL_CLK_CTRL_CPU_POST_DIV_SHIFT
++
++#define QCA955X_PLL_DDR_DIT_UPD_CNT_FMASK             \
++              QCA955X_PLL_DDR_DIT_UPD_CNT_MASK        \
++              << QCA955X_PLL_DDR_DIT_UPD_CNT_SHIFT
++#define QCA955X_PLL_DDR_DIT_NFRAC_STEP_FMASK          \
++              QCA955X_PLL_DDR_DIT_NFRAC_STEP_MASK     \
++              << QCA955X_PLL_DDR_DIT_NFRAC_STEP_SHIFT
++#define QCA955X_PLL_DDR_DIT_NFRAC_MIN_FMASK           \
++              QCA955X_PLL_DDR_DIT_NFRAC_MIN_MASK      \
++              << QCA955X_PLL_DDR_DIT_NFRAC_MIN_SHIFT
++#define QCA955X_PLL_DDR_DIT_NFRAC_MAX_FMASK           \
++              QCA955X_PLL_DDR_DIT_NFRAC_MAX_MASK      \
++              << QCA955X_PLL_DDR_DIT_NFRAC_MAX_SHIFT
++
++#define QCA955X_PLL_CPU_DIT_UPD_CNT_FMASK             \
++              QCA955X_PLL_CPU_DIT_UPD_CNT_MASK        \
++              << QCA955X_PLL_CPU_DIT_UPD_CNT_SHIFT
++#define QCA955X_PLL_CPU_DIT_NFRAC_STEP_FMASK          \
++              QCA955X_PLL_CPU_DIT_NFRAC_STEP_MASK     \
++              << QCA955X_PLL_CPU_DIT_NFRAC_STEP_SHIFT
++#define QCA955X_PLL_CPU_DIT_NFRAC_MIN_FMASK           \
++              QCA955X_PLL_CPU_DIT_NFRAC_MIN_MASK      \
++              << QCA955X_PLL_CPU_DIT_NFRAC_MIN_SHIFT
++#define QCA955X_PLL_CPU_DIT_NFRAC_MAX_FMASK           \
++              QCA955X_PLL_CPU_DIT_NFRAC_MAX_MASK      \
++              << QCA955X_PLL_CPU_DIT_NFRAC_MAX_SHIFT
++
++#define PLL_SRIF_DPLL2_KI_MASK                                GENMASK(29, 26)
++#define PLL_SRIF_DPLL2_KD_MASK                                GENMASK(25, 19)
++#define PLL_SRIF_DPLL2_PLL_PWD_MASK                   BIT(16)
++#define PLL_SRIF_DPLL2_DELTA_MASK                     GENMASK(12, 7)
++
++#define PLL_SRIF_DPLL2_DEFAULT                \
++              FIELD_PREP(PLL_SRIF_DPLL2_KI_MASK, 0x4) | \
++              FIELD_PREP(PLL_SRIF_DPLL2_KD_MASK, 0x60) | \
++              FIELD_PREP(PLL_SRIF_DPLL2_PLL_PWD_MASK, 0x1) | \
++              FIELD_PREP(PLL_SRIF_DPLL2_DELTA_MASK, 0x1e)
++
++DECLARE_GLOBAL_DATA_PTR;
++
++static u32 qca955x_get_xtal(void)
++{
++      u32 val;
++
++      val = ath79_get_bootstrap();
++      if (val & QCA955X_BOOTSTRAP_REF_CLK_40)
++              return 40000000;
++      else
++              return 25000000;
++}
++
++int get_serial_clock(void)
++{
++      return qca955x_get_xtal();
++}
++
++void qca955x_pll_init(void)
++{
++      void __iomem *srif_regs = map_physmem(QCA955X_SRIF_BASE,
++                                            QCA955X_SRIF_SIZE, MAP_NOCACHE);
++      void __iomem *pll_regs = map_physmem(AR71XX_PLL_BASE,
++                                           AR71XX_PLL_SIZE, MAP_NOCACHE);
++
++      /* 10.33.2 Baseband DPLL2 */
++      writel(PLL_SRIF_DPLL2_DEFAULT,
++             srif_regs + QCA955X_SRIF_BB_DPLL2_REG);
++
++      /* 10.33.2 PCIE DPLL2 */
++      writel(PLL_SRIF_DPLL2_DEFAULT,
++             srif_regs + QCA955X_SRIF_PCIE_DPLL2_REG);
++
++      /* 10.33.2 DDR DPLL2 */
++      writel(PLL_SRIF_DPLL2_DEFAULT,
++             srif_regs + QCA955X_SRIF_DDR_DPLL2_REG);
++
++      /* 10.33.2 CPU DPLL2 */
++      writel(PLL_SRIF_DPLL2_DEFAULT,
++             srif_regs + QCA955X_SRIF_CPU_DPLL2_REG);
++
++      /* pll_bypass_set */
++      setbits_be32(pll_regs + QCA955X_PLL_CLK_CTRL_REG,
++                   QCA955X_PLL_CLK_CTRL_CPU_PLL_BYPASS);
++      setbits_be32(pll_regs + QCA955X_PLL_CLK_CTRL_REG,
++                   QCA955X_PLL_CLK_CTRL_DDR_PLL_BYPASS);
++      setbits_be32(pll_regs + QCA955X_PLL_CLK_CTRL_REG,
++                   QCA955X_PLL_CLK_CTRL_AHB_PLL_BYPASS);
++
++      /* init_cpu_pll (720_600_240) */
++      writel(QCA955X_PLL_CPU_CONFIG_PLLPWD |
++             FIELD_PREP(QCA955X_PLL_CPU_CONFIG_OUTDIV_FMASK, 0x0) |
++             FIELD_PREP(QCA955X_PLL_CPU_CONFIG_RANGE_FMASK, 0x1) |
++             FIELD_PREP(QCA955X_PLL_CPU_CONFIG_REFDIV_FMASK, 0x1) |
++             FIELD_PREP(QCA955X_PLL_CPU_CONFIG_NINT_FMASK, 0x12),
++             pll_regs + QCA955X_PLL_CPU_CONFIG_REG);
++
++      /* init_ddr_pll (720_600_240) */
++      writel(QCA955X_PLL_DDR_CONFIG_PLLPWD |
++             FIELD_PREP(QCA955X_PLL_DDR_CONFIG_OUTDIV_FMASK, 0x0) |
++             FIELD_PREP(QCA955X_PLL_DDR_CONFIG_RANGE_FMASK, 0x1) |
++             FIELD_PREP(QCA955X_PLL_DDR_CONFIG_REFDIV_FMASK, 0x1) |
++             FIELD_PREP(QCA955X_PLL_DDR_CONFIG_NINT_FMASK, 0xf),
++             pll_regs + QCA955X_PLL_DDR_CONFIG_REG);
++
++      /* init_ahb_pll (720_600_240) */
++      writel(/* use CPU PLL for AHB (0) */
++             /* use DDR PLL for DDR (0) */
++             /* use CPU PLL for CPU (0) */
++             FIELD_PREP(QCA955X_PLL_CLK_CTRL_AHB_POST_DIV_FMASK, 0x2) |
++             FIELD_PREP(QCA955X_PLL_CLK_CTRL_DDR_POST_DIV_FMASK, 0x0) |
++             FIELD_PREP(QCA955X_PLL_CLK_CTRL_CPU_POST_DIV_FMASK, 0x0) |
++             QCA955X_PLL_CLK_CTRL_AHB_PLL_BYPASS |
++             QCA955X_PLL_CLK_CTRL_DDR_PLL_BYPASS |
++             QCA955X_PLL_CLK_CTRL_CPU_PLL_BYPASS,
++             pll_regs + QCA955X_PLL_CLK_CTRL_REG);
++
++      /* pll_pwd_unset */
++      clrbits_be32(pll_regs + QCA955X_PLL_CPU_CONFIG_REG,
++                   QCA955X_PLL_CPU_CONFIG_PLLPWD);
++      clrbits_be32(pll_regs + QCA955X_PLL_DDR_CONFIG_REG,
++                   QCA955X_PLL_DDR_CONFIG_PLLPWD);
++
++      /* outdiv_unset */
++      clrbits_be32(pll_regs + QCA955X_PLL_CPU_CONFIG_REG,
++                   QCA955X_PLL_CPU_CONFIG_OUTDIV_FMASK);
++      clrbits_be32(pll_regs + QCA955X_PLL_DDR_CONFIG_REG,
++                   QCA955X_PLL_DDR_CONFIG_OUTDIV_FMASK);
++
++      /* pll_bypass_unset */
++      clrbits_be32(pll_regs + QCA955X_PLL_CLK_CTRL_REG,
++                   QCA955X_PLL_CLK_CTRL_CPU_PLL_BYPASS);
++      clrbits_be32(pll_regs + QCA955X_PLL_CLK_CTRL_REG,
++                   QCA955X_PLL_CLK_CTRL_DDR_PLL_BYPASS);
++      clrbits_be32(pll_regs + QCA955X_PLL_CLK_CTRL_REG,
++                   QCA955X_PLL_CLK_CTRL_AHB_PLL_BYPASS);
++
++      /* ddr_pll_dither_unset */
++      writel(FIELD_PREP(QCA955X_PLL_DDR_DIT_UPD_CNT_FMASK, 0xf) |
++             FIELD_PREP(QCA955X_PLL_DDR_DIT_NFRAC_STEP_FMASK, 0x1) |
++             FIELD_PREP(QCA955X_PLL_DDR_DIT_NFRAC_MIN_FMASK, 0x0) |
++             FIELD_PREP(QCA955X_PLL_DDR_DIT_NFRAC_MAX_FMASK, 0x3ff),
++             pll_regs + QCA955X_PLL_DDR_DIT_FRAC_REG);
++
++      /* cpu_pll_dither_unset */
++      writel(FIELD_PREP(QCA955X_PLL_CPU_DIT_UPD_CNT_FMASK, 0xf) |
++             FIELD_PREP(QCA955X_PLL_CPU_DIT_NFRAC_STEP_FMASK, 0x1) |
++             FIELD_PREP(QCA955X_PLL_CPU_DIT_NFRAC_MIN_FMASK, 0x0) |
++             FIELD_PREP(QCA955X_PLL_CPU_DIT_NFRAC_MAX_FMASK, 0x3f),
++             pll_regs + QCA955X_PLL_CPU_DIT_FRAC_REG);
++}
++
++int get_clocks(void)
++{
++      void __iomem *regs;
++      u32 pll, cpu_pll, ddr_pll, clk_ctrl;
++      u32 cpu_clk, ddr_clk, ahb_clk;
++      u32 outdiv, refdiv, nint, nfrac, postdiv;
++      u32 xtal = qca955x_get_xtal();
++
++      regs = map_physmem(AR71XX_PLL_BASE, AR71XX_PLL_SIZE,
++                         MAP_NOCACHE);
++      pll = readl(regs + QCA955X_PLL_CPU_CONFIG_REG);
++      outdiv = FIELD_GET(QCA955X_PLL_CPU_CONFIG_OUTDIV_FMASK, pll);
++      refdiv = FIELD_GET(QCA955X_PLL_CPU_CONFIG_REFDIV_FMASK, pll);
++      nint   = FIELD_GET(QCA955X_PLL_CPU_CONFIG_NINT_FMASK, pll);
++      nfrac  = FIELD_GET(QCA955X_PLL_CPU_CONFIG_NFRAC_FMASK, pll);
++
++      cpu_pll = (xtal * (nint + (nfrac >> 9))) / (refdiv * (1 << outdiv));
++
++      pll = readl(regs + QCA955X_PLL_DDR_CONFIG_REG);
++      outdiv = FIELD_GET(QCA955X_PLL_DDR_CONFIG_OUTDIV_FMASK, pll);
++      refdiv = FIELD_GET(QCA955X_PLL_DDR_CONFIG_REFDIV_FMASK, pll);
++      nint   = FIELD_GET(QCA955X_PLL_DDR_CONFIG_NINT_FMASK, pll);
++      nfrac  = FIELD_GET(QCA955X_PLL_DDR_CONFIG_NFRAC_FMASK, pll);
++
++      ddr_pll = (xtal * (nint + (nfrac >> 9))) / (refdiv * (1 << outdiv));
++
++      clk_ctrl = readl(regs + QCA955X_PLL_CLK_CTRL_REG);
++
++      postdiv = FIELD_GET(QCA955X_PLL_CLK_CTRL_CPU_POST_DIV_FMASK, clk_ctrl);
++      if (clk_ctrl & QCA955X_PLL_CLK_CTRL_CPU_PLL_BYPASS)
++              cpu_clk = xtal;
++      else if (clk_ctrl & QCA955X_PLL_CLK_CTRL_CPUCLK_FROM_CPUPLL)
++              cpu_clk = ddr_pll / (postdiv + 1);
++      else
++              cpu_clk = cpu_pll / (postdiv + 1);
++
++      postdiv = FIELD_GET(QCA955X_PLL_CLK_CTRL_DDR_POST_DIV_FMASK, clk_ctrl);
++      if (clk_ctrl & QCA955X_PLL_CLK_CTRL_DDR_PLL_BYPASS)
++              ddr_clk = xtal;
++      else if (clk_ctrl & QCA955X_PLL_CLK_CTRL_DDRCLK_FROM_DDRPLL)
++              ddr_clk = cpu_pll / (postdiv + 1);
++      else
++              ddr_clk = ddr_pll / (postdiv + 1);
++
++      postdiv = FIELD_GET(QCA955X_PLL_CLK_CTRL_AHB_POST_DIV_FMASK, clk_ctrl);
++      if (clk_ctrl & QCA955X_PLL_CLK_CTRL_AHB_PLL_BYPASS)
++              ahb_clk = xtal;
++      else if (clk_ctrl & QCA955X_PLL_CLK_CTRL_AHBCLK_FROM_DDRPLL)
++              ahb_clk = ddr_pll;
++      else
++              ahb_clk = cpu_pll;
++      ahb_clk /= (postdiv + 1);
++
++      gd->cpu_clk = cpu_clk;
++      gd->mem_clk = ddr_clk;
++      gd->bus_clk = ahb_clk;
++
++      debug("cpu_clk=%u, ddr_clk=%u, bus_clk=%u\n",
++            cpu_clk, ddr_clk, ahb_clk);
++
++      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/qca955x/cpu.c b/arch/mips/mach-ath79/qca955x/cpu.c
+new file mode 100644
+index 0000000000..9405871444
+--- /dev/null
++++ b/arch/mips/mach-ath79/qca955x/cpu.c
+@@ -0,0 +1,7 @@
++// SPDX-License-Identifier: GPL-2.0+
++/*
++ * Copyright (C) 2024 INAGAKI Hiroshi <musashino.open@gmail.com>
++ */
++
++/* The lowlevel_init() is not needed on QCA955X */
++void lowlevel_init(void) {}
+diff --git a/arch/mips/mach-ath79/qca955x/ddr.c b/arch/mips/mach-ath79/qca955x/ddr.c
+new file mode 100644
+index 0000000000..654a410d95
+--- /dev/null
++++ b/arch/mips/mach-ath79/qca955x/ddr.c
+@@ -0,0 +1,222 @@
++// SPDX-License-Identifier: GPL-2.0+
++/*
++ * Copyright (C) 2024 INAGAKI Hiroshi <musashino.open@gmail.com>
++ *
++ * Based on QCA956x support and QSDK
++ */
++
++#include <asm/global_data.h>
++#include <asm/io.h>
++#include <asm/addrspace.h>
++#include <asm/types.h>
++#include <linux/bitfield.h>
++#include <linux/bitops.h>
++#include <linux/delay.h>
++#include <mach/ar71xx_regs.h>
++#include <mach/ath79.h>
++
++#define DDR_CONFIG_CAS_LATENCY_MSB_MASK               BIT(31)
++#define DDR_CONFIG_OPEN_PAGE_MASK             BIT(30)
++#define DDR_CONFIG_CAS_LATENCY_MASK           GENMASK(29, 27)
++#define DDR_CONFIG_TMRD_MASK                  GENMASK(26, 23)
++#define DDR_CONFIG_TRFC_MASK                  GENMASK(22, 17)
++#define DDR_CONFIG_TRRD_MASK                  GENMASK(16, 13)
++#define DDR_CONFIG_TRP_MASK                   GENMASK(12, 9)
++#define DDR_CONFIG_TRCD_MASK                  GENMASK(8, 5)
++#define DDR_CONFIG_TRAS_MASK                  GENMASK(4, 0)
++
++#define DDR_CONFIG2_HALF_WIDTH_LOW_MASK               BIT(31)
++#define DDR_CONFIG2_SWAP_A26_A27_MASK         BIT(30)
++#define DDR_CONFIG2_GATE_OPEN_LATENCY_MASK    GENMASK(29, 26)
++#define DDR_CONFIG2_TWTR_MASK                 GENMASK(25, 21)
++#define DDR_CONFIG2_TRTP_MASK                 GENMASK(20, 17)
++#define DDR_CONFIG2_TRTW_MASK                 GENMASK(16, 12)
++#define DDR_CONFIG2_TWR_MASK                  GENMASK(11, 8)
++#define DDR_CONFIG2_CKE_MASK                  BIT(7)
++#define DDR_CONFIG2_CNTL_OE_EN_MASK           BIT(5)
++#define DDR_CONFIG2_BURST_LENGTH_MASK         GENMASK(3, 0)
++
++#define DDR_CTL_CONFIG_SRAM_TSEL_MASK         GENMASK(31, 30)
++#define DDR_CTL_CONFIG_GE0_SRAM_SYNC_MASK     BIT(20)
++#define DDR_CTL_CONFIG_GE1_SRAM_SYNC_MASK     BIT(19)
++#define DDR_CTL_CONFIG_USB_SRAM_SYNC_MASK     BIT(18)
++#define DDR_CTL_CONFIG_PCIE_SRAM_SYNC_MASK    BIT(17)
++#define DDR_CTL_CONFIG_WMAC_SRAM_SYNC_MASK    BIT(16)
++#define DDR_CTL_CONFIG_MISC_SRC1_SRAM_SYNC_MASK       BIT(15)
++#define DDR_CTL_CONFIG_MISC_SRC2_SRAM_SYNC_MASK       BIT(14)
++#define DDR_CTL_CONFIG_PAD_DDR2_SEL_MASK      BIT(6)
++#define DDR_CTL_CONFIG_CPU_DDR_SYNC_MASK      BIT(2)
++#define DDR_CTL_CONFIG_HALF_WIDTH_MASK                BIT(1)
++
++#define RST_BOOTSTRAP_DDR_WIDTH_MASK          BIT(3)
++
++#define PMU2_PGM_MASK                         BIT(21)
++#define PMU2_LDO_TUNE_MASK                    GENMASK(20, 19)
++
++/*
++* DDR2                      DDR1
++* 0x40c3   25MHz            0x4186   25Mhz
++* 0x4138   40MHz            0x4270   40Mhz
++*/
++#define CFG_DDR2_REFRESH_VAL 0x4138
++
++#define CFG_DDR2_CONFIG_VAL   \
++              DDR_CONFIG_CAS_LATENCY_MSB_MASK | DDR_CONFIG_OPEN_PAGE_MASK | \
++              FIELD_PREP(DDR_CONFIG_CAS_LATENCY_MASK, 0x4) | \
++              FIELD_PREP(DDR_CONFIG_TMRD_MASK, 0xf) | \
++              FIELD_PREP(DDR_CONFIG_TRFC_MASK, 0x15) | \
++              FIELD_PREP(DDR_CONFIG_TRRD_MASK, 0x7) | \
++              FIELD_PREP(DDR_CONFIG_TRP_MASK, 0x9) | \
++              FIELD_PREP(DDR_CONFIG_TRCD_MASK, 0x9) | \
++              FIELD_PREP(DDR_CONFIG_TRAS_MASK, 0x1b)
++
++#define CFG_DDR2_CONFIG2_VAL  \
++              DDR_CONFIG2_HALF_WIDTH_LOW_MASK | /* SWAP_A26_A27 is off */ \
++              FIELD_PREP(DDR_CONFIG2_GATE_OPEN_LATENCY_MASK, 0xb) | \
++              FIELD_PREP(DDR_CONFIG2_TWTR_MASK, 0x15) | \
++              FIELD_PREP(DDR_CONFIG2_TRTP_MASK, 0x9) | \
++              FIELD_PREP(DDR_CONFIG2_TRTW_MASK, 0xe) | \
++              FIELD_PREP(DDR_CONFIG2_TWR_MASK, 0x1) | \
++              DDR_CONFIG2_CKE_MASK | DDR_CONFIG2_CNTL_OE_EN_MASK | \
++              FIELD_PREP(DDR_CONFIG2_BURST_LENGTH_MASK, 0x8)
++
++#define CFG_DDR2_CONFIG3_VAL                  0x0000000a
++#define CFG_DDR2_EXT_MODE_VAL1                        0x782
++#define CFG_DDR2_EXT_MODE_VAL2                        0x402
++#define CFG_DDR2_MODE_VAL_INIT                        0x153
++#define CFG_DDR2_MODE_VAL                     0x53
++#define CFG_DDR2_TAP_VAL                      0x10
++#define CFG_DDR2_EN_TWL_VAL                   0x00001e7d
++#define CFG_DDR2_RD_DATA_THIS_CYCLE_VAL_16    0xffff
++#define CFG_DDR2_RD_DATA_THIS_CYCLE_VAL_32    0xff
++
++#define CFG_DDR_CTL_CONFIG    \
++              FIELD_PREP(DDR_CTL_CONFIG_SRAM_TSEL_MASK, 0x1) | \
++              DDR_CTL_CONFIG_GE0_SRAM_SYNC_MASK | \
++              DDR_CTL_CONFIG_GE1_SRAM_SYNC_MASK | \
++              DDR_CTL_CONFIG_USB_SRAM_SYNC_MASK | \
++              DDR_CTL_CONFIG_PCIE_SRAM_SYNC_MASK | \
++              DDR_CTL_CONFIG_WMAC_SRAM_SYNC_MASK | \
++              DDR_CTL_CONFIG_MISC_SRC1_SRAM_SYNC_MASK | \
++              DDR_CTL_CONFIG_MISC_SRC2_SRAM_SYNC_MASK | \
++              DDR_CTL_CONFIG_PAD_DDR2_SEL_MASK /* for DDR2 */
++              /* CPU_DDR_SYNC is off (CPU clk != DDR clk) */
++
++DECLARE_GLOBAL_DATA_PTR;
++
++void qca955x_ddr_init(void)
++{
++      u32 cycle_val = CFG_DDR2_RD_DATA_THIS_CYCLE_VAL_32;
++      u32 ctl_config = CFG_DDR_CTL_CONFIG;
++      void __iomem *ddr_regs = map_physmem(AR71XX_DDR_CTRL_BASE, AR71XX_DDR_CTRL_SIZE,
++                             MAP_NOCACHE);
++      void __iomem *srif_regs = map_physmem(QCA955X_SRIF_BASE, QCA955X_SRIF_SIZE,
++                             MAP_NOCACHE);
++
++      /* 16bit */
++      if (!(ath79_get_bootstrap() & RST_BOOTSTRAP_DDR_WIDTH_MASK))
++      {
++              ctl_config |= DDR_CTL_CONFIG_HALF_WIDTH_MASK;
++              cycle_val = CFG_DDR2_RD_DATA_THIS_CYCLE_VAL_16;
++      }
++
++      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 + QCA955X_DDR_REG_CTL_CONF);
++      udelay(10);
++
++      writel(cycle_val, ddr_regs + AR71XX_DDR_REG_RD_CYCLE);
++      udelay(100);
++
++      writel(0x74444444, ddr_regs + QCA955X_DDR_REG_BURST);
++      udelay(100);
++
++      writel(0x44444444, ddr_regs + QCA955X_DDR_REG_BURST2);
++      udelay(100);
++
++      writel(0xfffff, ddr_regs + QCA955X_DDR_REG_TIMEOUT_MAX);
++      udelay(100);
++
++      writel(CFG_DDR2_CONFIG_VAL, ddr_regs + AR71XX_DDR_REG_CONFIG);
++      udelay(100);
++
++      writel(CFG_DDR2_CONFIG2_VAL, ddr_regs + AR71XX_DDR_REG_CONFIG2);
++      udelay(100);
++
++      writel(CFG_DDR2_CONFIG3_VAL, ddr_regs + QCA955X_DDR_REG_CONFIG3);
++      udelay(100);
++
++      writel(CFG_DDR2_EN_TWL_VAL, ddr_regs + QCA955X_DDR_REG_DDR2_CONFIG);
++      udelay(100);
++
++      writel(CFG_DDR2_CONFIG2_VAL | 0x80,
++              ddr_regs + AR71XX_DDR_REG_CONFIG2);     /* CKE Enable */
++      udelay(100);
++
++      writel(0x8, ddr_regs + AR71XX_DDR_REG_CONTROL); /* Precharge */
++      udelay(10);
++
++      writel(0x10, ddr_regs + AR71XX_DDR_REG_CONTROL);        /* EMR2 */
++      udelay(10);
++
++      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(CFG_DDR2_MODE_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(CFG_DDR2_MODE_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(CFG_DDR2_TAP_VAL, ddr_regs + AR71XX_DDR_REG_TAP_CTRL0);
++      writel(CFG_DDR2_TAP_VAL, ddr_regs + AR71XX_DDR_REG_TAP_CTRL1);
++      writel(CFG_DDR2_TAP_VAL, ddr_regs + QCA955X_DDR_REG_TAP_CTRL2);
++      writel(CFG_DDR2_TAP_VAL, ddr_regs + QCA955X_DDR_REG_TAP_CTRL3);
++
++      writel(0x633c8176, srif_regs + QCA955X_SRIF_PMU1_REG);
++      /* Set DDR2 Voltage to 1.8 volts */
++      writel(PMU2_PGM_MASK | FIELD_PREP(PMU2_LDO_TUNE_MASK, 0x3),
++             srif_regs + QCA955X_SRIF_PMU2_REG);
++}
+diff --git a/arch/mips/mach-ath79/qca955x/qca955x-ddr-tap.S b/arch/mips/mach-ath79/qca955x/qca955x-ddr-tap.S
+new file mode 100644
+index 0000000000..1c117a5b69
+--- /dev/null
++++ b/arch/mips/mach-ath79/qca955x/qca955x-ddr-tap.S
+@@ -0,0 +1,191 @@
++// SPDX-License-Identifier: GPL-2.0+
++/*
++ * Copyright (C) 2024 INAGAKI Hiroshi <musashino.open@gmail.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, 0xbd007f00
++      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)
++      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(QCA955X_RTC_BASE)
++      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, 0xbd007f00          /* Read the current value of the TAP for programming */
++      lw      t1, 0x0(t0)
++      li      t2, 0x00000000
++      or      t3, t1, t2
++
++      li      t0, CKSEG1ADDR(AR71XX_DDR_CTRL_BASE)
++      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, 0x545fc332
++      sw      t1, 0x0070(t0)          /* PERF_COMP_AHB_GE0_1_ADDRESS */
++
++      li      t1, 0xaba03ccd
++      sw      t1, 0x0040(t0)          /* PERF_COMP_AHB_GE1_0_ADDRESS */
++
++      li      t1, 0x545fc332
++      sw      t1, 0x0078(t0)          /* PERF_COMP_AHB_GE1_1_ADDRESS */
++
++      li      t1, 0xaba03ccd
++      sw      t1, 0x0034(t0)          /* PERF_MASK_AHB_GE0_0_ADDRESS */
++
++      li      t1, 0x545fc332
++      sw      t1, 0x006c(t0)          /* PERF_MASK_AHB_GE0_1_ADDRESS */
++
++      li      t1, 0xaba03ccd
++      sw      t1, 0x003c(t0)          /* PERF_MASK_AHB_GE1_0_ADDRESS */
++
++      li      t1, 0x545fc332
++      sw      t1, 0x0074(t0)          /* PERF_MASK_AHB_GE1_1_ADDRESS */
++
++      li      t1, 0xaba03ccd
++      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, 0xbd007f00
++      lw      t1, 0x4(t0)
++      addiu   t1, t1, 0x1
++      sw      t1, 0x4(t0)
++
++      li      t0, 0xbd007f10
++      lw      t1, 0x0(t0)
++      li      t2, 0xaa55aa55
++      beq     t1, t2, _first_pass
++       nop
++
++      li      t0, 0xbd007f00
++      lw      t1, 0x0(t0)
++      li      t0, 0xbd007f10
++      sw      t1, 0x4(t0)
++       nop
++      b       _iterate_tap
++       nop
++
++_first_pass:
++      li      t0, 0xbd007f00
++      lw      t1, 0x0(t0)
++      li      t0, 0xbd007f10
++      sw      t1, 0x0(t0)
++      sw      t1, 0x4(t0)
++       nop
++
++_iterate_tap:
++      li      t0, 0xbd007f00
++      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, 0xbd007f00
++      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, 0xbd007f10
++      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, CKSEG1ADDR(AR71XX_DDR_CTRL_BASE)
++      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)
+-- 
+2.43.0
+