Message ID | 20190215115640.2501-1-rosysong@rosinson.com |
---|---|
State | Superseded |
Delegated to: | Daniel Schwierzeck |
Headers | show |
Series | [U-Boot,1/3] drivers: ag7xxx: add support for qca956x-s17 | expand |
Am 15.02.19 um 12:56 schrieb Rosy Song: > Signed-off-by: Rosy Song <rosysong@rosinson.com> > --- > 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 | 70 +++ > 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 +++++++++++++ > arch/mips/mach-ath79/qca956x/lowlevel_init.S | 79 ++++ > .../mips/mach-ath79/qca956x/qca956x-ddr-tap.S | 194 ++++++++ > arch/mips/mach-ath79/reset.c | 271 +++++++++++ > board/qca/ap152/Kconfig | 27 ++ > board/qca/ap152/MAINTAINERS | 6 + > board/qca/ap152/Makefile | 3 + > board/qca/ap152/ap152.c | 81 ++++ > configs/ap152_defconfig | 55 +++ > include/configs/ap152.h | 54 +++ > 20 files changed, 1735 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/lowlevel_init.S > 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 <rosysong@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 <rosysong@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..380f387a26 100644 > --- a/arch/mips/mach-ath79/include/mach/ar71xx_regs.h > +++ b/arch/mips/mach-ath79/include/mach/ar71xx_regs.h > @@ -201,6 +201,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 +282,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 +535,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 +779,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 +1133,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 +1217,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 +1318,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 <rosysong@rosinson.com> > * Copyright (C) 2015-2016 Wills Wang <wills.wang@live.com> > * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org> > * Copyright (C) 2008 Imre Kaloz <kaloz@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 <rosysong@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 <rosysong@rosinson.com> > + */ > + > +#include <common.h> > + > +/* The lowlevel_init() is not needed on QCA956X */ > +void lowlevel_init(void) {} why? Below you add a lowlevel_init.S? > diff --git a/arch/mips/mach-ath79/qca956x/ddr.c b/arch/mips/mach-ath79/qca956x/ddr.c > new file mode 100644 > index 0000000000..b6ea0f9654 > --- /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 <rosysong@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 no C++ style comments > + 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/lowlevel_init.S b/arch/mips/mach-ath79/qca956x/lowlevel_init.S > new file mode 100644 > index 0000000000..0580e238bc > --- /dev/null > +++ b/arch/mips/mach-ath79/qca956x/lowlevel_init.S > @@ -0,0 +1,79 @@ > +/* SPDX-License-Identifier: GPL-2.0+ */ > +/* > + * Copyright (C) 2018-1029 Rosy Song <rosysong@rosinson.com> > + * Based on Atheros LSDK/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> > + > + .text this is implied by LEAF() and can be removed > + .set noreorder > + > +LEAF(lowlevel_init) > + li t0, CKSEG1ADDR(QCA956X_SRIF_BASE) all instruction parameters should only be separated by ", " > + li t1, 0x54486000 > + sw t1, QCA953X_SRIF_BB_DPLL2_REG(t0) > + > + li t1, 0x2e406000 > + sw t1, QCA956X_SRIF_CPU_DPLL2_REG(t0) > + > + li t1, 0x54406000 > + sw t1, QCA956X_SRIF_DDR_DPLL2_REG(t0) > + > + li t1, 0x88586000 > + sw t1, QCA956X_SRIF_PCIE_DPLL2_REG(t0) > + > +init_cpu_pll: remove all unused jump labels > + li t0, CKSEG1ADDR(AR71XX_PLL_BASE) > + li t1, 0x00001000 > + sw t1, QCA956X_PLL_CPU_CONFIG_REG(t0) > + li t1, 0x007c0000 > + sw t1, QCA956X_PLL_CPU_CONFIG1_REG(t0) > + > +init_ddr_pll: > + li t1, 0x00010000 > + sw t1, QCA956X_PLL_DDR_CONFIG_REG(t0) > + li t1, 0x00680000 > + sw t1, QCA956X_PLL_DDR_CONFIG1_REG(t0) > + > +init_ahb_pll: > + li t1, 0x00010000 > + sw t1, QCA956X_PLL_CLK_CTRL_REG(t0) > + > +ddr_pll_dither_unset: > + li t1, 0x00000000 > + sw t1, QCA956X_PLL_DDR_DIT_FRAC_REG(t0) > + > + li t1, 0x00000000 > + sw t1, QCA956X_PLL_DDR_DIT2_FRAC_REG(t0) > + > +cpu_pll_dither_unset: > + li t1, 0x00000000 > + sw t1, QCA956X_PLL_CPU_DIT_FRAC_REG(t0) > + > + li t1, 0x00000000 > + sw t1, QCA956X_PLL_CPU_DIT2_FRAC_REG(t0) > + > +check_cpu_pll_locked: > + li t7, KSEG1ADDR(AR71XX_PLL_BASE); you already have this address stored in t0 (after init_cpu_pll: ) > + lw t8, QCA956X_PLL_CPU_CONFIG_REG(t7); > + li t9, 0x8000000; > + and t8, t8, t9; > + bne zero, t8, check_cpu_pll_locked; this needs a "nop" in the delay slot > + > +check_ddr_pll_locked: > + li t7, KSEG1ADDR(AR71XX_PLL_BASE); you already have this address stored in t0 (after init_cpu_pll: ) > + lw t8, QCA956X_PLL_DDR_CONFIG_REG(t7); > + li t9, 0x8000000; > + and t8, t8, t9; > + bne zero, t8, check_ddr_pll_locked; > + remove this blank line ... > + nop ... and add one here, also all instructions in delay slots should be indended by an extra space character > + jr ra > + nop > + END(lowlevel_init) > 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..fa5f6c1a76 > --- /dev/null > +++ b/arch/mips/mach-ath79/qca956x/qca956x-ddr-tap.S > @@ -0,0 +1,194 @@ > +// SPDX-License-Identifier: GPL-2.0+ > +/* > + * Copyright (C) 2019 Rosy Song <rosysong@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> > + > + .text this is implied by LEAF() and can be removed > + .set noreorder > + > +LEAF(ddr_tap_tuning) > + li a0, 0xbd001f00 all instruction parameters should only be separated by ", " > + sw zero, 0x0(a0) // Place where the tap values are saved and used for SWEEP again no C++ style comments > + 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, 0xb8060000 // RESET_BASE_ADDRESS no magic values, use something like CKSEG1ADDR(QCA956X_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, 0xb8107000 // RTC_BASE_ADDRESS no magic values, use something like CKSEG1ADDR(QCA956X_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 all instructions in delay slots should be indended by an extra space character > + > +_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.wang@live.com> > + * Copyright (C) 2018-2019 Rosy Song <rosysong@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..a3d82780fe > --- /dev/null > +++ b/board/qca/ap152/Kconfig > @@ -0,0 +1,27 @@ > +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 > + > +config SYS_DCACHE_SIZE > + default 32768 > + > +config SYS_DCACHE_LINE_SIZE > + default 32 > + > +config SYS_ICACHE_SIZE > + default 65536 > + > +config SYS_ICACHE_LINE_SIZE > + default 32 don't define this and try to use the automatic cache size detection > + > +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 <rosysong@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 <rosysong@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..383c48b03d > --- /dev/null > +++ b/configs/ap152_defconfig > @@ -0,0 +1,55 @@ > +CONFIG_MIPS=y > +CONFIG_SYS_TEXT_BASE=0x9F000000 > +CONFIG_SYS_MALLOC_F_LEN=0x800 > +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" doesn't use the Linux serial driver something like "ttyATH0" ? > +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_ATMEL=y > +CONFIG_SPI_FLASH_EON=y > +CONFIG_SPI_FLASH_GIGADEVICE=y > +CONFIG_SPI_FLASH_MACRONIX=y > +CONFIG_SPI_FLASH_SPANSION=y > +CONFIG_SPI_FLASH_STMICRO=y > +CONFIG_SPI_FLASH_SST=y > +CONFIG_SPI_FLASH_WINBOND=y > +CONFIG_SPI_FLASH_DATAFLASH=y do you really need all possible flash vendors? > +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 <rosysong@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 */ >
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 <rosysong@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 <rosysong@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..380f387a26 100644 --- a/arch/mips/mach-ath79/include/mach/ar71xx_regs.h +++ b/arch/mips/mach-ath79/include/mach/ar71xx_regs.h @@ -201,6 +201,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 +282,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 +535,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 +779,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 +1133,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 +1217,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 +1318,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 <rosysong@rosinson.com> * Copyright (C) 2015-2016 Wills Wang <wills.wang@live.com> * Copyright (C) 2008-2011 Gabor Juhos <juhosg@openwrt.org> * Copyright (C) 2008 Imre Kaloz <kaloz@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 <rosysong@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 <rosysong@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..b6ea0f9654 --- /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 <rosysong@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/lowlevel_init.S b/arch/mips/mach-ath79/qca956x/lowlevel_init.S new file mode 100644 index 0000000000..0580e238bc --- /dev/null +++ b/arch/mips/mach-ath79/qca956x/lowlevel_init.S @@ -0,0 +1,79 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2018-1029 Rosy Song <rosysong@rosinson.com> + * Based on Atheros LSDK/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> + + .text + .set noreorder + +LEAF(lowlevel_init) + li t0, CKSEG1ADDR(QCA956X_SRIF_BASE) + li t1, 0x54486000 + sw t1, QCA953X_SRIF_BB_DPLL2_REG(t0) + + li t1, 0x2e406000 + sw t1, QCA956X_SRIF_CPU_DPLL2_REG(t0) + + li t1, 0x54406000 + sw t1, QCA956X_SRIF_DDR_DPLL2_REG(t0) + + li t1, 0x88586000 + sw t1, QCA956X_SRIF_PCIE_DPLL2_REG(t0) + +init_cpu_pll: + li t0, CKSEG1ADDR(AR71XX_PLL_BASE) + li t1, 0x00001000 + sw t1, QCA956X_PLL_CPU_CONFIG_REG(t0) + li t1, 0x007c0000 + sw t1, QCA956X_PLL_CPU_CONFIG1_REG(t0) + +init_ddr_pll: + li t1, 0x00010000 + sw t1, QCA956X_PLL_DDR_CONFIG_REG(t0) + li t1, 0x00680000 + sw t1, QCA956X_PLL_DDR_CONFIG1_REG(t0) + +init_ahb_pll: + li t1, 0x00010000 + sw t1, QCA956X_PLL_CLK_CTRL_REG(t0) + +ddr_pll_dither_unset: + li t1, 0x00000000 + sw t1, QCA956X_PLL_DDR_DIT_FRAC_REG(t0) + + li t1, 0x00000000 + sw t1, QCA956X_PLL_DDR_DIT2_FRAC_REG(t0) + +cpu_pll_dither_unset: + li t1, 0x00000000 + sw t1, QCA956X_PLL_CPU_DIT_FRAC_REG(t0) + + li t1, 0x00000000 + sw t1, QCA956X_PLL_CPU_DIT2_FRAC_REG(t0) + +check_cpu_pll_locked: + li t7, KSEG1ADDR(AR71XX_PLL_BASE); + lw t8, QCA956X_PLL_CPU_CONFIG_REG(t7); + li t9, 0x8000000; + and t8, t8, t9; + bne zero, t8, check_cpu_pll_locked; + +check_ddr_pll_locked: + li t7, KSEG1ADDR(AR71XX_PLL_BASE); + lw t8, QCA956X_PLL_DDR_CONFIG_REG(t7); + li t9, 0x8000000; + and t8, t8, t9; + bne zero, t8, check_ddr_pll_locked; + + nop + jr ra + nop + END(lowlevel_init) 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..fa5f6c1a76 --- /dev/null +++ b/arch/mips/mach-ath79/qca956x/qca956x-ddr-tap.S @@ -0,0 +1,194 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2019 Rosy Song <rosysong@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> + + .text + .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, 0xb8060000 // 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, 0xb8107000 // 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.wang@live.com> + * Copyright (C) 2018-2019 Rosy Song <rosysong@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..a3d82780fe --- /dev/null +++ b/board/qca/ap152/Kconfig @@ -0,0 +1,27 @@ +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 + +config SYS_DCACHE_SIZE + default 32768 + +config SYS_DCACHE_LINE_SIZE + default 32 + +config SYS_ICACHE_SIZE + default 65536 + +config SYS_ICACHE_LINE_SIZE + default 32 + +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 <rosysong@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 <rosysong@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..383c48b03d --- /dev/null +++ b/configs/ap152_defconfig @@ -0,0 +1,55 @@ +CONFIG_MIPS=y +CONFIG_SYS_TEXT_BASE=0x9F000000 +CONFIG_SYS_MALLOC_F_LEN=0x800 +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_ATMEL=y +CONFIG_SPI_FLASH_EON=y +CONFIG_SPI_FLASH_GIGADEVICE=y +CONFIG_SPI_FLASH_MACRONIX=y +CONFIG_SPI_FLASH_SPANSION=y +CONFIG_SPI_FLASH_STMICRO=y +CONFIG_SPI_FLASH_SST=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 <rosysong@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 */
Signed-off-by: Rosy Song <rosysong@rosinson.com> --- 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 | 70 +++ 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 +++++++++++++ arch/mips/mach-ath79/qca956x/lowlevel_init.S | 79 ++++ .../mips/mach-ath79/qca956x/qca956x-ddr-tap.S | 194 ++++++++ arch/mips/mach-ath79/reset.c | 271 +++++++++++ board/qca/ap152/Kconfig | 27 ++ board/qca/ap152/MAINTAINERS | 6 + board/qca/ap152/Makefile | 3 + board/qca/ap152/ap152.c | 81 ++++ configs/ap152_defconfig | 55 +++ include/configs/ap152.h | 54 +++ 20 files changed, 1735 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/lowlevel_init.S 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