From 91e57a42e240a620f9d96cdfe927bf7e40af4582 Mon Sep 17 00:00:00 2001 From: INAGAKI Hiroshi Date: Sat, 31 Aug 2024 17:42:53 +0900 Subject: [PATCH] uboot-ath79: add initial support for QCA955x SoCs 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 Link: https://github.com/openwrt/openwrt/pull/16297 Signed-off-by: Hauke Mehrtens --- ...add-initial-support-for-QCA955x-SoCs.patch | 1020 +++++++++++++++++ 1 file changed, 1020 insertions(+) create mode 100644 package/boot/uboot-ath79/patches/001-mips-ath79-add-initial-support-for-QCA955x-SoCs.patch 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 index 0000000000..7d6075c9f6 --- /dev/null +++ b/package/boot/uboot-ath79/patches/001-mips-ath79-add-initial-support-for-QCA955x-SoCs.patch @@ -0,0 +1,1020 @@ +From 7c59f0fe98eb20db8dfbf4d3c67d6043a9efe116 Mon Sep 17 00:00:00 2001 +From: INAGAKI Hiroshi +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 ++ */ ++ ++#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 ++ * ++ * based on QCA956x support and QSDK ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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 ++ */ ++ ++/* 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 ++ * ++ * Based on QCA956x support and QSDK ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#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 ++ * ++ * Based on QSDK ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++ ++ .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 + -- 2.30.2