Supports both GXBB and GXL SoCs. Signed-off-by: Ferass El Hafidi <fundersc...@postmarketos.org> --- arch/arm/include/asm/arch-meson/dram-gx.h | 341 +++++++++++++++++ arch/arm/include/asm/arch-meson/dram-gxbb.h | 168 +++++++++ arch/arm/include/asm/arch-meson/dram-gxl.h | 193 ++++++++++ arch/arm/include/asm/arch-meson/dram-settings-gx.h | 296 +++++++++++++++ arch/arm/include/asm/arch-meson/dram-timings-gx.h | 117 ++++++ arch/arm/mach-meson/Kconfig | 70 ++++ arch/arm/mach-meson/Makefile | 3 + arch/arm/mach-meson/dram-gx.c | 419 +++++++++++++++++++++ arch/arm/mach-meson/dram-gxbb.c | 174 +++++++++ arch/arm/mach-meson/dram-gxl.c | 167 ++++++++ 10 files changed, 1948 insertions(+)
diff --git a/arch/arm/include/asm/arch-meson/dram-gx.h b/arch/arm/include/asm/arch-meson/dram-gx.h new file mode 100644 index 0000000000000000000000000000000000000000..177e0ac1a65699f815e27309f6b3fae605617282 --- /dev/null +++ b/arch/arm/include/asm/arch-meson/dram-gx.h @@ -0,0 +1,341 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2015, Amlogic, Inc. All rights reserved. + * Copyright (C) 2023, Ferass El Hafidi <fundersc...@postmarketos.org> + */ +#ifndef DRAM_GX_H +#define DRAM_GX_H + +/* + * Registers + */ + +/* PCTL */ +#define DDR0_PCTL_BASE 0xc8839000 +/* DDR1_PCTL_BASE is DDR0_PCTL_BASE + 0x400 */ + +/* DMC */ +#define DMC_REG_BASE 0xc8838000 + +#define DMC_REQ_CTRL (DMC_REG_BASE + (0x00 << 2)) +#define DMC_SOFT_RST (DMC_REG_BASE + (0x01 << 2)) +#define DMC_SOFT_RST1 (DMC_REG_BASE + (0x02 << 2)) +#define DMC_RST_STS (DMC_REG_BASE + (0x03 << 2)) +#define DMC_VERSION (DMC_REG_BASE + (0x05 << 2)) + +#define DMC_REFR_CTRL1 (DMC_REG_BASE + (0x23 << 2)) +#define DMC_REFR_CTRL2 (DMC_REG_BASE + (0x24 << 2)) + +#define DMC_PCTL_LP_CTRL (DMC_REG_BASE + (0x46 << 2)) + +#define DMC_AM0_QOS_INC (DMC_REG_BASE + (0x62 << 2)) +#define DMC_AM0_QOS_DEC (DMC_REG_BASE + (0x64 << 2)) +#define DMC_AM0_QOS_DIS (DMC_REG_BASE + (0x66 << 2)) + +#define DMC_AM1_QOS_INC (DMC_REG_BASE + (0x6c << 2)) +#define DMC_AM1_QOS_DEC (DMC_REG_BASE + (0x6e << 2)) +#define DMC_AM1_QOS_DIS (DMC_REG_BASE + (0x70 << 2)) + +#define DMC_AM2_QOS_INC (DMC_REG_BASE + (0x76 << 2)) +#define DMC_AM2_QOS_DEC (DMC_REG_BASE + (0x78 << 2)) +#define DMC_AM2_QOS_DIS (DMC_REG_BASE + (0x7a << 2)) + +#define DMC_AM3_QOS_INC (DMC_REG_BASE + (0x80 << 2)) +#define DMC_AM3_QOS_DEC (DMC_REG_BASE + (0x82 << 2)) +#define DMC_AM3_QOS_DIS (DMC_REG_BASE + (0x84 << 2)) + +#define DMC_AM4_QOS_INC (DMC_REG_BASE + (0x8a << 2)) +#define DMC_AM4_QOS_DEC (DMC_REG_BASE + (0x8c << 2)) +#define DMC_AM4_QOS_DIS (DMC_REG_BASE + (0x8e << 2)) + +#define DMC_AM5_QOS_INC (DMC_REG_BASE + (0x94 << 2)) +#define DMC_AM5_QOS_DEC (DMC_REG_BASE + (0x96 << 2)) +#define DMC_AM5_QOS_DIS (DMC_REG_BASE + (0x98 << 2)) + +#define DMC_AM6_QOS_INC (DMC_REG_BASE + (0x9e << 2)) +#define DMC_AM6_QOS_DEC (DMC_REG_BASE + (0xa0 << 2)) +#define DMC_AM6_QOS_DIS (DMC_REG_BASE + (0xa2 << 2)) + +#define DMC_AM7_QOS_INC (DMC_REG_BASE + (0xa8 << 2)) +#define DMC_AM7_QOS_DEC (DMC_REG_BASE + (0xaa << 2)) +#define DMC_AM7_QOS_DIS (DMC_REG_BASE + (0xac << 2)) + +#define DMC_AXI0_QOS_INC (DMC_REG_BASE + (0xb2 << 2)) +#define DMC_AXI0_QOS_DEC (DMC_REG_BASE + (0xb4 << 2)) +#define DMC_AXI0_QOS_DIS (DMC_REG_BASE + (0xb6 << 2)) +#define DMC_AXI0_QOS_CTRL1 (DMC_REG_BASE + (0xb9 << 2)) + +#define DMC_AXI1_QOS_INC (DMC_REG_BASE + (0xbc << 2)) +#define DMC_AXI1_QOS_DEC (DMC_REG_BASE + (0xbe << 2)) +#define DMC_AXI1_QOS_DIS (DMC_REG_BASE + (0xc0 << 2)) + +#define DMC_AXI2_QOS_INC (DMC_REG_BASE + (0xc6 << 2)) +#define DMC_AXI2_QOS_DEC (DMC_REG_BASE + (0xc8 << 2)) +#define DMC_AXI2_QOS_DIS (DMC_REG_BASE + (0xca << 2)) + +#define DMC_AXI3_QOS_INC (DMC_REG_BASE + (0xd0 << 2)) +#define DMC_AXI3_QOS_DEC (DMC_REG_BASE + (0xd2 << 2)) +#define DMC_AXI3_QOS_DIS (DMC_REG_BASE + (0xd4 << 2)) + +#define DMC_AXI4_QOS_INC (DMC_REG_BASE + (0xda << 2)) +#define DMC_AXI4_QOS_DEC (DMC_REG_BASE + (0xdc << 2)) +#define DMC_AXI4_QOS_DIS (DMC_REG_BASE + (0xde << 2)) + +#define DMC_AXI5_QOS_INC (DMC_REG_BASE + (0xe4 << 2)) +#define DMC_AXI5_QOS_DEC (DMC_REG_BASE + (0xe6 << 2)) +#define DMC_AXI5_QOS_DIS (DMC_REG_BASE + (0xe8 << 2)) + +#define DMC_AXI6_QOS_INC (DMC_REG_BASE + (0xee << 2)) +#define DMC_AXI6_QOS_DEC (DMC_REG_BASE + (0xf0 << 2)) +#define DMC_AXI6_QOS_DIS (DMC_REG_BASE + (0xf2 << 2)) + +#define DMC_AXI7_QOS_INC (DMC_REG_BASE + (0xf8 << 2)) +#define DMC_AXI7_QOS_DEC (DMC_REG_BASE + (0xfa << 2)) +#define DMC_AXI7_QOS_DIS (DMC_REG_BASE + (0xfc << 2)) + +/* DDR MMC */ +#define AM_DDR_PLL_CNTL0 (DDR_MMC_BASE + 0x00) +#define AM_DDR_PLL_CNTL1 (DDR_MMC_BASE + 0x04) +#define AM_DDR_PLL_CNTL2 (DDR_MMC_BASE + 0x08) +#define AM_DDR_PLL_CNTL3 (DDR_MMC_BASE + 0x0c) +#define AM_DDR_PLL_CNTL4 (DDR_MMC_BASE + 0x10) +#if defined(CONFIG_MESON_GXBB) +#define AM_DDR_PLL_STS (DDR_MMC_BASE + 0x14) +#else +#define AM_DDR_PLL_CNTL5 (DDR_MMC_BASE + 0x14) +#endif + +#define DDR0_CLK_CTRL (DDR_MMC_BASE + 0x400) + +/* DMC SEC */ +#define DMC_SEC_REG_BASE 0xda838400 + +#define DMC_SEC_CTRL (DMC_SEC_REG_BASE + (0x00 << 2)) +#define DMC_SEC_RANGE_CTRL (DMC_SEC_REG_BASE + (0x07 << 2)) +#define DMC_SEC_AXI_PORT_CTRL (DMC_SEC_REG_BASE + (0x0e << 2)) + +#define DMC_VDEC_SEC_READ_CTRL (DMC_SEC_REG_BASE + (0x10 << 2)) +#define DMC_VDEC_SEC_WRITE_CTRL (DMC_SEC_REG_BASE + (0x11 << 2)) +#define DMC_VDEC_SEC_CFG (DMC_SEC_REG_BASE + (0x12 << 2)) + +#define DMC_HCODEC_SEC_READ_CTRL (DMC_SEC_REG_BASE + (0x17 << 2)) +#define DMC_HCODEC_SEC_WRITE_CTRL (DMC_SEC_REG_BASE + (0x18 << 2)) +#define DMC_HCODEC_SEC_CFG (DMC_SEC_REG_BASE + (0x19 << 2)) + +#define DMC_HEVC_SEC_READ_CTRL (DMC_SEC_REG_BASE + (0x1e << 2)) +#define DMC_HEVC_SEC_WRITE_CTRL (DMC_SEC_REG_BASE + (0x1f << 2)) +#define DMC_HEVC_SEC_CFG (DMC_SEC_REG_BASE + (0x20 << 2)) + +#define DMC_VPU_SEC_READ_CTRL (DMC_SEC_REG_BASE + (0x32 << 2)) +#define DMC_VPU_SEC_WRITE_CTRL (DMC_SEC_REG_BASE + (0x33 << 2)) +#define DMC_VPU_SEC_CFG (DMC_SEC_REG_BASE + (0x25 << 2)) + +#define DMC_GE2D_SEC_CTRL (DMC_SEC_REG_BASE + (0x34 << 2)) +#define DMC_PARSER_SEC_CTRL (DMC_SEC_REG_BASE + (0x35 << 2)) +#define DMC_DEV_SEC_READ_CTRL (DMC_SEC_REG_BASE + (0x36 << 2)) +#define DMC_DEV_SEC_WRITE_CTRL (DMC_SEC_REG_BASE + (0x37 << 2)) + +#define DMC_WTCH0_CTRL (DMC_SEC_REG_BASE + (0xa9 << 2)) +#define DMC_WTCH1_CTRL (DMC_SEC_REG_BASE + (0xb0 << 2)) + +#define DDR0_ADDRMAP_0 (DMC_SEC_REG_BASE + (0xd0 << 2)) +#define DDR0_ADDRMAP_1 (DMC_SEC_REG_BASE + (0xd1 << 2)) +#define DDR0_ADDRMAP_2 (DMC_SEC_REG_BASE + (0xd2 << 2)) +#define DDR0_ADDRMAP_3 (DMC_SEC_REG_BASE + (0xd3 << 2)) +#define DDR0_ADDRMAP_4 (DMC_SEC_REG_BASE + (0xd4 << 2)) + +#define DDR1_ADDRMAP_0 (DMC_SEC_REG_BASE + (0xd5 << 2)) +#define DDR1_ADDRMAP_1 (DMC_SEC_REG_BASE + (0xd6 << 2)) +#define DDR1_ADDRMAP_2 (DMC_SEC_REG_BASE + (0xd7 << 2)) +#define DDR1_ADDRMAP_3 (DMC_SEC_REG_BASE + (0xd8 << 2)) +#define DDR1_ADDRMAP_4 (DMC_SEC_REG_BASE + (0xd9 << 2)) + +#if defined(CONFIG_MESON_GXL) +#define DMC_DES_KEY0_H (DMC_SEC_REG_BASE + (0x90 << 2)) +#define DMC_DES_KEY0_L (DMC_SEC_REG_BASE + (0x91 << 2)) +#define DMC_DES_KEY1_H (DMC_SEC_REG_BASE + (0x92 << 2)) +#define DMC_DES_KEY1_L (DMC_SEC_REG_BASE + (0x93 << 2)) + +#define DMC_DES_CTRL (DMC_SEC_REG_BASE + (0x9d << 2)) +#endif + +#define DMC_DDR_CTRL (DMC_SEC_REG_BASE + (0xda << 2)) + +#define AM_ANALOG_TOP_REG1 (0xc8834400 + (0x6f << 2)) + +/* Macros */ +#define DQSCORR_DX(dx) \ + if ((readl(dx) & ~(0xe00)) && ((readl(dx) >> 8) & ~(0xe00))) \ + writel((((readl(dx) & ~(0xe00)) * 95) / 100) | \ + (((((readl(dx) >> 8) & ~(0xe00)) * 88) / 100) << 8) | \ + (((((readl(dx) >> 8) & ~(0xe00)) * 88) / 100) << 16), \ + dx); \ + else if (((readl(dx) >> 8) & ~(0xe00))) \ + writel((95 / 100) | \ + (((((readl(dx) >> 8) & ~(0xe00)) * 88) / 100) << 8) | \ + (((((readl(dx) >> 8) & ~(0xe00)) * 88) / 100) << 16), \ + dx); \ + else if (((readl(dx)) & ~(0xe00))) \ + writel((((readl(dx) & ~(0xe00)) * 95) / 100) | \ + (((88) / 100) << 8) | (((88) / 100) << 16), \ + dx); \ + else \ + writel((95 / 100) | \ + ((88 / 100) << 8) | ((88 / 100) << 16), dx) + +#define DMC_ENABLE_REGION(REGION) \ + writel(0xffffffff, REGION## _SEC_CFG); \ + writel(0x55555555, REGION## _SEC_WRITE_CTRL); \ + writel(0x55555555, REGION## _SEC_READ_CTRL) + +/* TODO: Timeout */ +#define WAIT_FOR(a) \ + while (!(readl(a) & 1)) \ + ; \ + if (!(readl(a) & 1)) \ + panic("%s: init failed, err=%d", __func__, -ETIMEDOUT) + +/** + * Register values + **/ + +/* + * PLL + */ +#define DDR_CLK_CNTL_CLKGEN_SOFTRESET BIT(28) +#define DDR_CLK_CNTL_PHY_CLK_ENABLE BIT(29) +#define DDR_CLK_CNTL_DDRPLL_ENABLE BIT(31) + +/* + * PCTL + */ + +/* PCTL_SCTL: state control register (S905X datasheet p.451) */ +#define PCTL_SCTL_CFG_STATE BIT(0) +#define PCTL_SCTL_GO_STATE BIT(1) + +/* PCTL_STAT */ +#define PCTL_STAT_ACCESS (BIT(1) | BIT(0)) + +/* PCTL_POWCTL: power control */ +#define PCTL_POWCTL_POWERON BIT(0) + +/* + * PUB + */ + +/* PUB_PGSR0: PHY General Status Register 0 */ +#define PUB_PGSR0_IDONE BIT(0) /* Initialization Done */ +#define PUB_PGSR0_PLDONE BIT(1) /* PLL Lock Done */ +#define PUB_PGSR0_DCDONE BIT(2) /* DDL Calibration Done */ +#define PUB_PGSR0_ZCDONE BIT(3) /* Impedance Calibration Done */ +#define PUB_PGSR0_DIDONE BIT(4) /* DRAM Initialization Done */ +#define PUB_PGSR0_WLDONE BIT(5) /* Write Leveling Done */ +#define PUB_PGSR0_QSGDONE BIT(6) /* DQS Gate Training Done */ +#define PUB_PGSR0_WLADONE BIT(7) /* Write Leveling Adjust Done */ +#define PUB_PGSR0_RDDONE BIT(8) /* Read Bit Deskew Done */ +#define PUB_PGSR0_WDDONE BIT(9) /* Write Bit Deskew Done */ +#define PUB_PGSR0_REDONE BIT(10) /* Read Eye Training Done */ +#define PUB_PGSR0_WEDONE BIT(11) /* Write Eye Training Done */ +#define PUB_PGSR0_ZCERR BIT(20) /* Impedance Calib Error */ +#define PUB_PGSR0_WLERR BIT(21) /* Write Leveling Error */ +#define PUB_PGSR0_QSGERR BIT(22) /* DQS Gate Training Error */ +#define PUB_PGSR0_WLAERR BIT(23) /* Write Leveling Adj Error */ +#define PUB_PGSR0_RDERR BIT(24) /* Read Bit Deskew Error */ +#define PUB_PGSR0_WDERR BIT(25) /* Write Bit Deskew Error */ +#define PUB_PGSR0_REERR BIT(26) /* Read Eye Training Error */ +#define PUB_PGSR0_WEERR BIT(27) /* Write Eye Training Error */ + +/* PUB_PIR: PHY init register */ +#define PUB_PIR_INIT BIT(0) +#define PUB_PIR_ZCAL BIT(1) +#define PUB_PIR_CA BIT(2) + +#define PUB_PIR_PLLINIT BIT(4) +#define PUB_PIR_DCAL BIT(5) +#define PUB_PIR_PHYRST BIT(6) +#define PUB_PIR_DRAMRST BIT(7) +#define PUB_PIR_DRAMINIT BIT(8) +#define PUB_PIR_WL BIT(9) +#define PUB_PIR_QSGATE BIT(10) +#define PUB_PIR_WLADJ BIT(11) +#define PUB_PIR_RDDSKW BIT(12) +#define PUB_PIR_WRDSKW BIT(13) +#define PUB_PIR_RDEYE BIT(14) +#define PUB_PIR_WREYE BIT(15) +#define PUB_PIR_ICPC BIT(16) +#define PUB_PIR_PLLBYP BIT(17) +#define PUB_PIR_CTLDINIT BIT(18) +#define PUB_PIR_RDIMMINIT BIT(19) +#define PUB_PIR_CLRSR BIT(27) +#define PUB_PIR_LOCKBYP BIT(28) +#define PUB_PIR_DCALBYP BIT(29) +#define PUB_PIR_ZCALBYP BIT(30) +#define PUB_PIR_INITBYP BIT(31) + +#define PUB_PIR_FINAL_STEP (PUB_PIR_INIT | PUB_PIR_ZCAL | \ + PUB_PIR_PLLINIT | PUB_PIR_DCAL | PUB_PIR_PHYRST | PUB_PIR_DRAMRST | \ + PUB_PIR_DRAMINIT | PUB_PIR_WL | PUB_PIR_QSGATE | PUB_PIR_WLADJ | \ + PUB_PIR_RDDSKW | PUB_PIR_WRDSKW | PUB_PIR_RDEYE | PUB_PIR_WREYE) + +/* Struct which holds timings (see dram-settings-gx.h) */ +struct meson_gx_dram_timings { + u8 drv; + u8 odt; + u8 rtp; + u8 wtr; + u8 rp; + u8 rcd; + u8 ras; + u8 rrd; + u8 rc; + u8 mrd; + u8 mod; + u8 faw; + u8 wlmrd; + u8 wlo; + ushort rfc; + u8 xp; + ushort xs; + ushort dllk; + u8 cke; + u8 rtodt; + u8 rtw; + u8 refi; + u8 refi_mddr3; + u8 cl; + u8 wr; + u8 cwl; + u8 al; + u8 dqs; + u8 cksre; + u8 cksrx; + u8 zqcs; + u8 xpdll; + ushort exsr; + ushort zqcl; + ushort zqcsi; + u8 rpab; + u8 rppb; + u8 tccdl; + u8 tdqsck; + u8 tdqsckmax; + u8 tckesr; + u8 tdpd; + u8 taond_aofd; +}; + +#if defined(CONFIG_MESON_GXBB) +# include <asm/arch/dram-gxbb.h> +#elif defined(CONFIG_MESON_GXL) +# include <asm/arch/dram-gxl.h> +#endif + +/* Functions */ +int dram_init(void); +void meson_dram_prepare_pctl(void); +void meson_dram_phy_init(void); +void meson_dram_phy_setup_ranks(void); +void meson_dram_finalise_init(void); +extern const struct meson_gx_dram_timings timings; +#endif diff --git a/arch/arm/include/asm/arch-meson/dram-gxbb.h b/arch/arm/include/asm/arch-meson/dram-gxbb.h new file mode 100644 index 0000000000000000000000000000000000000000..b04f66d63364fab132de6f56702c0b9dbce1dce3 --- /dev/null +++ b/arch/arm/include/asm/arch-meson/dram-gxbb.h @@ -0,0 +1,168 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2015, Amlogic, Inc. All rights reserved. + * Copyright (C) 2023-2025, Ferass El Hafidi <fundersc...@postmarketos.org> + */ +#ifndef DRAM_GXBB_H +#define DRAM_GXBB_H + +/* PUB (not much documented) */ +#define DDR0_PUB_REG_BASE 0xc8836000 + +#define DDR0_PUB_PIR (DDR0_PUB_REG_BASE + (0x01 << 2)) + +#define DDR0_PUB_PGCR1 (DDR0_PUB_REG_BASE + (0x03 << 2)) +#define DDR0_PUB_PGCR2 (DDR0_PUB_REG_BASE + (0x04 << 2)) +#define DDR0_PUB_PGCR3 (DDR0_PUB_REG_BASE + (0x05 << 2)) +#define DDR0_PUB_PGSR0 (DDR0_PUB_REG_BASE + (0x06 << 2)) + +#define DDR0_PUB_ACLCDLR (DDR0_PUB_REG_BASE + (0x0F << 2)) +#define DDR0_PUB_ACBDLR0 (DDR0_PUB_REG_BASE + (0x10 << 2)) +#define DDR0_PUB_ACIOCR1 (DDR0_PUB_REG_BASE + (0x1B << 2)) +#define DDR0_PUB_ACIOCR2 (DDR0_PUB_REG_BASE + (0x1C << 2)) +#define DDR0_PUB_ACIOCR3 (DDR0_PUB_REG_BASE + (0x1D << 2)) +#define DDR0_PUB_ACIOCR4 (DDR0_PUB_REG_BASE + (0x1E << 2)) +#define DDR0_PUB_ACIOCR5 (DDR0_PUB_REG_BASE + (0x1F << 2)) + +#define DDR0_PUB_DXCCR (DDR0_PUB_REG_BASE + (0x20 << 2)) +#define DDR0_PUB_DSGCR (DDR0_PUB_REG_BASE + (0x21 << 2)) +#define DDR0_PUB_DCR (DDR0_PUB_REG_BASE + (0x22 << 2)) + +#define DDR0_PUB_DTPR0 (DDR0_PUB_REG_BASE + (0x23 << 2)) +#define DDR0_PUB_DTPR1 (DDR0_PUB_REG_BASE + (0x24 << 2)) +#define DDR0_PUB_DTPR2 (DDR0_PUB_REG_BASE + (0x25 << 2)) +#define DDR0_PUB_DTPR3 (DDR0_PUB_REG_BASE + (0x26 << 2)) + +#define DDR0_PUB_MR0 (DDR0_PUB_REG_BASE + (0x27 << 2)) +#define DDR0_PUB_MR1 (DDR0_PUB_REG_BASE + (0x28 << 2)) +#define DDR0_PUB_MR2 (DDR0_PUB_REG_BASE + (0x29 << 2)) +#define DDR0_PUB_MR3 (DDR0_PUB_REG_BASE + (0x2A << 2)) + +#define DDR0_PUB_ODTCR (DDR0_PUB_REG_BASE + (0x2B << 2)) + +#define DDR0_PUB_DTCR (DDR0_PUB_REG_BASE + (0x2C << 2)) + +#define DDR0_PUB_DTAR0 (DDR0_PUB_REG_BASE + (0x2D << 2)) +#define DDR0_PUB_DTAR1 (DDR0_PUB_REG_BASE + (0x2E << 2)) +#define DDR0_PUB_DTAR2 (DDR0_PUB_REG_BASE + (0x2F << 2)) +#define DDR0_PUB_DTAR3 (DDR0_PUB_REG_BASE + (0x30 << 2)) + +#define DDR0_PUB_IOVCR0 (DDR0_PUB_REG_BASE + (0x8E << 2)) +#define DDR0_PUB_IOVCR1 (DDR0_PUB_REG_BASE + (0x8F << 2)) + +#define DDR0_PUB_ZQCR (DDR0_PUB_REG_BASE + (0x90 << 2)) + +#define DDR0_PUB_ZQ0PR (DDR0_PUB_REG_BASE + (0x91 << 2)) +#define DDR0_PUB_ZQ1PR (DDR0_PUB_REG_BASE + (0x95 << 2)) +#define DDR0_PUB_ZQ2PR (DDR0_PUB_REG_BASE + (0x99 << 2)) +#define DDR0_PUB_ZQ3PR (DDR0_PUB_REG_BASE + (0x9D << 2)) + +#define DDR0_PUB_DX0GCR1 (DDR0_PUB_REG_BASE + (0xA1 << 2)) +#define DDR0_PUB_DX0GCR2 (DDR0_PUB_REG_BASE + (0xA2 << 2)) +#define DDR0_PUB_DX0GCR3 (DDR0_PUB_REG_BASE + (0xA3 << 2)) + +#define DDR0_PUB_DX0LCDLR0 (DDR0_PUB_REG_BASE + (0xAE << 2)) +#define DDR0_PUB_DX0LCDLR2 (DDR0_PUB_REG_BASE + (0xB0 << 2)) + +#define DDR0_PUB_DX0GTR (DDR0_PUB_REG_BASE + (0xB2 << 2)) +#define DDR0_PUB_DX1GTR (DDR0_PUB_REG_BASE + (0xD2 << 2)) +#define DDR0_PUB_DX2GTR (DDR0_PUB_REG_BASE + (0xF2 << 2)) +#define DDR0_PUB_DX3GTR (DDR0_PUB_REG_BASE + (0x112 << 2)) + +#define DDR0_PUB_DX1GCR1 (DDR0_PUB_REG_BASE + (0xC1 << 2)) +#define DDR0_PUB_DX1GCR2 (DDR0_PUB_REG_BASE + (0xC2 << 2)) +#define DDR0_PUB_DX1GCR3 (DDR0_PUB_REG_BASE + (0xC3 << 2)) +#define DDR0_PUB_DX1LCDLR0 (DDR0_PUB_REG_BASE + (0xCE << 2)) +#define DDR0_PUB_DX1LCDLR2 (DDR0_PUB_REG_BASE + (0xD0 << 2)) + +#define DDR0_PUB_DX2GCR1 (DDR0_PUB_REG_BASE + (0xE1 << 2)) +#define DDR0_PUB_DX2GCR2 (DDR0_PUB_REG_BASE + (0xE2 << 2)) +#define DDR0_PUB_DX2GCR3 (DDR0_PUB_REG_BASE + (0xE3 << 2)) +#define DDR0_PUB_DX2LCDLR2 (DDR0_PUB_REG_BASE + (0xF0 << 2)) + +#define DDR0_PUB_DX3GCR1 (DDR0_PUB_REG_BASE + (0x101 << 2)) +#define DDR0_PUB_DX3GCR2 (DDR0_PUB_REG_BASE + (0x102 << 2)) +#define DDR0_PUB_DX3GCR3 (DDR0_PUB_REG_BASE + (0x103 << 2)) +#define DDR0_PUB_DX3LCDLR0 (DDR0_PUB_REG_BASE + (0x10E << 2)) +#define DDR0_PUB_DX3LCDLR2 (DDR0_PUB_REG_BASE + (0x110 << 2)) + +/* PCTL */ +#define DDR0_PCTL_BASE 0xc8839000 +/* DDR1_PCTL_BASE is DDR0_PCTL_BASE + 0x400 */ + +#define PCTL_SCFG (DDR0_PCTL_BASE + 0x000) +#define PCTL_SCTL (DDR0_PCTL_BASE + (0x1 << 2)) +#define PCTL_STAT (DDR0_PCTL_BASE + (0x2 << 2)) + +#define PCTL_POWSTAT (DDR0_PCTL_BASE + (0x12 << 2)) +#define PCTL_POWCTL (DDR0_PCTL_BASE + (0x11 << 2)) + +#define PCTL_CMDTSTAT (DDR0_PCTL_BASE + (0x13 << 2)) +#define PCTL_CMDTSTATEN (DDR0_PCTL_BASE + (0x14 << 2)) + +#define PCTL_PPCFG (DDR0_PCTL_BASE + (0x21 << 2)) + +#define PCTL_MCFG (DDR0_PCTL_BASE + (0x20 << 2)) +#define PCTL_MCFG1 (DDR0_PCTL_BASE + (0x1f << 2)) + +#define PCTL_TCKSRE (DDR0_PCTL_BASE + (0x49 << 2)) +#define PCTL_TZQCSI (DDR0_PCTL_BASE + (0x47 << 2)) +#define PCTL_TINIT (DDR0_PCTL_BASE + (0x31 << 2)) +#define PCTL_TOGCNT1U (DDR0_PCTL_BASE + (0x30 << 2)) +#define PCTL_TCKE (DDR0_PCTL_BASE + (0x4b << 2)) +#define PCTL_TMOD (DDR0_PCTL_BASE + (0x4c << 2)) +#define PCTL_TEXSR (DDR0_PCTL_BASE + (0x43 << 2)) +#define PCTL_TAL (DDR0_PCTL_BASE + (0x39 << 2)) +#define PCTL_TRTP (DDR0_PCTL_BASE + (0x40 << 2)) +#define PCTL_TCKSRX (DDR0_PCTL_BASE + (0x4a << 2)) +#define PCTL_TRTW (DDR0_PCTL_BASE + (0x38 << 2)) +#define PCTL_TCWL (DDR0_PCTL_BASE + (0x3b << 2)) +#define PCTL_TWR (DDR0_PCTL_BASE + (0x41 << 2)) +#define PCTL_TCL (DDR0_PCTL_BASE + (0x3a << 2)) +#define PCTL_TDQS (DDR0_PCTL_BASE + (0x48 << 2)) +#define PCTL_TRSTH (DDR0_PCTL_BASE + (0x32 << 2)) +#define PCTL_TRCD (DDR0_PCTL_BASE + (0x3e << 2)) +#define PCTL_TXP (DDR0_PCTL_BASE + (0x44 << 2)) +#define PCTL_TOGCNT100N (DDR0_PCTL_BASE + (0x33 << 2)) +#define PCTL_TMRD (DDR0_PCTL_BASE + (0x35 << 2)) +#define PCTL_TREFI (DDR0_PCTL_BASE + (0x34 << 2)) +#define PCTL_TRAS (DDR0_PCTL_BASE + (0x3c << 2)) +#define PCTL_TREFI_MEM_DDR3 (DDR0_PCTL_BASE + (0x52 << 2)) +#define PCTL_TWTR (DDR0_PCTL_BASE + (0x42 << 2)) +#define PCTL_TRC (DDR0_PCTL_BASE + (0x3d << 2)) +#define PCTL_TRFC (DDR0_PCTL_BASE + (0x36 << 2)) +#define PCTL_TCKESR (DDR0_PCTL_BASE + (0x50 << 2)) +#define PCTL_TZQCL (DDR0_PCTL_BASE + (0x4e << 2)) +#define PCTL_TRRD (DDR0_PCTL_BASE + (0x3f << 2)) +#define PCTL_TRP (DDR0_PCTL_BASE + (0x37 << 2)) +#define PCTL_TZQCS (DDR0_PCTL_BASE + (0x46 << 2)) +#define PCTL_TXPDLL (DDR0_PCTL_BASE + (0x45 << 2)) + +#define PCTL_DFIODTCFG (DDR0_PCTL_BASE + (0x91 << 2)) +#define PCTL_DFIODTCFG1 (DDR0_PCTL_BASE + (0x92 << 2)) +#define PCTL_DFITCTRLDELAY (DDR0_PCTL_BASE + (0x90 << 2)) +#define PCTL_DFITPHYWRLAT (DDR0_PCTL_BASE + (0x95 << 2)) +#define PCTL_DFITPHYWRDATA (DDR0_PCTL_BASE + (0x94 << 2)) +#define PCTL_DFITRDDATAEN (DDR0_PCTL_BASE + (0x98 << 2)) +#define PCTL_DFITPHYRDLAT (DDR0_PCTL_BASE + (0x99 << 2)) +#define PCTL_DFITPHYUPDTYPE1 (DDR0_PCTL_BASE + (0x9d << 2)) +#define PCTL_DFISTCFG0 (DDR0_PCTL_BASE + (0xb1 << 2)) +#define PCTL_DFISTCFG1 (DDR0_PCTL_BASE + (0xb2 << 2)) +#define PCTL_DFISTSTAT0 (DDR0_PCTL_BASE + (0xb0 << 2)) +#define PCTL_DFILPCFG0 (DDR0_PCTL_BASE + (0xbc << 2)) +#define PCTL_DFITCTRLUPDMIN (DDR0_PCTL_BASE + (0xa0 << 2)) +#define PCTL_DFITDRAMCLKEN (DDR0_PCTL_BASE + (0xb4 << 2)) +#define PCTL_DFITDRAMCLKDIS (DDR0_PCTL_BASE + (0xb5 << 2)) + +/* DDR MMC (see dram-gx.h for more details) */ +#define DDR_MMC_BASE 0xc8836800 + +#define DDR0_SOFT_RESET (DDR_MMC_BASE + 0x404) +#define DDR_CLK_CNTL (DDR_MMC_BASE + 0x18) +#define DDR0_APD_CTRL (DDR_MMC_BASE + 0x408) + +/* These will get optimized out by the compiler */ +#define AM_DDR_PLL_CNTL5 0 +#define PCTL_TCCD 0 +#define PCTL_TFAW 0 +#endif diff --git a/arch/arm/include/asm/arch-meson/dram-gxl.h b/arch/arm/include/asm/arch-meson/dram-gxl.h new file mode 100644 index 0000000000000000000000000000000000000000..c52ef37c1bf98deb55c9e863b08948370e25f5ca --- /dev/null +++ b/arch/arm/include/asm/arch-meson/dram-gxl.h @@ -0,0 +1,193 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2015, Amlogic, Inc. All rights reserved. + * Copyright (C) 2023-2025, Ferass El Hafidi <fundersc...@postmarketos.org> + */ +#ifndef DRAM_GXL_H +#define DRAM_GXL_H + +/* PUB (not much documented) */ +#define DDR0_PUB_REG_BASE 0xc8836000 + +#define DDR0_PUB_PIR (DDR0_PUB_REG_BASE + (0x01 << 2)) + +#define DDR0_PUB_PGCR1 (DDR0_PUB_REG_BASE + (0x05 << 2)) +#define DDR0_PUB_PGCR2 (DDR0_PUB_REG_BASE + (0x06 << 2)) +#define DDR0_PUB_PGCR3 (DDR0_PUB_REG_BASE + (0x07 << 2)) +#define DDR0_PUB_PGCR4 (DDR0_PUB_REG_BASE + (0x08 << 2)) +#define DDR0_PUB_PGCR5 (DDR0_PUB_REG_BASE + (0x09 << 2)) +#define DDR0_PUB_PGCR6 (DDR0_PUB_REG_BASE + (0x0a << 2)) +#define DDR0_PUB_PGSR0 (DDR0_PUB_REG_BASE + (0x0d << 2)) + +#define DDR0_PUB_ACLCDLR (DDR0_PUB_REG_BASE + (0x160 << 2)) +#define DDR0_PUB_ACMDLR0 (DDR0_PUB_REG_BASE + (0x168 << 2)) +#define DDR0_PUB_ACBDLR0 (DDR0_PUB_REG_BASE + (0x150 << 2)) +#define DDR0_PUB_ACBDLR1 (DDR0_PUB_REG_BASE + (0x151 << 2)) +#define DDR0_PUB_ACBDLR2 (DDR0_PUB_REG_BASE + (0x152 << 2)) +#define DDR0_PUB_ACBDLR3 (DDR0_PUB_REG_BASE + (0x153 << 2)) +#define DDR0_PUB_ACBDLR6 (DDR0_PUB_REG_BASE + (0x156 << 2)) +#define DDR0_PUB_ACBDLR7 (DDR0_PUB_REG_BASE + (0x157 << 2)) +#define DDR0_PUB_ACBDLR8 (DDR0_PUB_REG_BASE + (0x158 << 2)) +#define DDR0_PUB_ACBDLR9 (DDR0_PUB_REG_BASE + (0x159 << 2)) +#define DDR0_PUB_ACIOCR1 (DDR0_PUB_REG_BASE + (0x141 << 2)) +#define DDR0_PUB_ACIOCR2 (DDR0_PUB_REG_BASE + (0x142 << 2)) +#define DDR0_PUB_ACIOCR3 (DDR0_PUB_REG_BASE + (0x143 << 2)) +#define DDR0_PUB_ACIOCR4 (DDR0_PUB_REG_BASE + (0x144 << 2)) +#define DDR0_PUB_ACIOCR5 (DDR0_PUB_REG_BASE + (0x145 << 2)) + +#define DDR0_PUB_PTR3 (DDR0_PUB_REG_BASE + (0x13 << 2)) +#define DDR0_PUB_PTR4 (DDR0_PUB_REG_BASE + (0x14 << 2)) + +#define DDR0_PUB_DXCCR (DDR0_PUB_REG_BASE + (0x22 << 2)) +#define DDR0_PUB_DSGCR (DDR0_PUB_REG_BASE + (0x24 << 2)) +#define DDR0_PUB_DCR (DDR0_PUB_REG_BASE + (0x40 << 2)) + +#define DDR0_PUB_DTPR0 (DDR0_PUB_REG_BASE + (0x44 << 2)) +#define DDR0_PUB_DTPR1 (DDR0_PUB_REG_BASE + (0x45 << 2)) +#define DDR0_PUB_DTPR2 (DDR0_PUB_REG_BASE + (0x46 << 2)) +#define DDR0_PUB_DTPR3 (DDR0_PUB_REG_BASE + (0x47 << 2)) +#define DDR0_PUB_DTPR4 (DDR0_PUB_REG_BASE + (0x48 << 2)) +#define DDR0_PUB_DTPR5 (DDR0_PUB_REG_BASE + (0x49 << 2)) + +#define DDR0_PUB_MR0 (DDR0_PUB_REG_BASE + (0x60 << 2)) +#define DDR0_PUB_MR1 (DDR0_PUB_REG_BASE + (0x61 << 2)) +#define DDR0_PUB_MR2 (DDR0_PUB_REG_BASE + (0x62 << 2)) +#define DDR0_PUB_MR3 (DDR0_PUB_REG_BASE + (0x63 << 2)) +#define DDR0_PUB_MR4 (DDR0_PUB_REG_BASE + (0x64 << 2)) +#define DDR0_PUB_MR5 (DDR0_PUB_REG_BASE + (0x65 << 2)) +#define DDR0_PUB_MR6 (DDR0_PUB_REG_BASE + (0x66 << 2)) +#define DDR0_PUB_MR11 (DDR0_PUB_REG_BASE + (0x6b << 2)) + +#define DDR0_PUB_ODTCR (DDR0_PUB_REG_BASE + (0x26 << 2)) + +#define DDR0_PUB_DTCR (DDR0_PUB_REG_BASE + (0x80 << 2)) +#define DDR0_PUB_DTCR1 (DDR0_PUB_REG_BASE + (0x81 << 2)) + +#define DDR0_PUB_DTAR0 (DDR0_PUB_REG_BASE + (0x82 << 2)) +#define DDR0_PUB_DTAR1 (DDR0_PUB_REG_BASE + (0x83 << 2)) +#define DDR0_PUB_DTAR2 (DDR0_PUB_REG_BASE + (0x84 << 2)) +#define DDR0_PUB_DTAR3 (DDR0_PUB_REG_BASE + (0x85 << 2)) + +#define DDR0_PUB_RANKIDR (DDR0_PUB_REG_BASE + (0x137 << 2)) + +#define DDR0_PUB_IOVCR0 (DDR0_PUB_REG_BASE + (0x148 << 2)) +#define DDR0_PUB_IOVCR1 (DDR0_PUB_REG_BASE + (0x149 << 2)) + +#define DDR0_PUB_VTCR0 (DDR0_PUB_REG_BASE + (0x14a << 2)) +#define DDR0_PUB_VTCR1 (DDR0_PUB_REG_BASE + (0x14b << 2)) + +#define DDR0_PUB_ZQCR (DDR0_PUB_REG_BASE + (0x1a0 << 2)) + +#define DDR0_PUB_ZQ0PR (DDR0_PUB_REG_BASE + (0x1a1 << 2)) +#define DDR0_PUB_ZQ1PR (DDR0_PUB_REG_BASE + (0x1a5 << 2)) +#define DDR0_PUB_ZQ2PR (DDR0_PUB_REG_BASE + (0x1a9 << 2)) +#define DDR0_PUB_ZQ3PR (DDR0_PUB_REG_BASE + (0x1ad << 2)) + +#define DDR0_PUB_DX0GCR1 (DDR0_PUB_REG_BASE + (0x1c1 << 2)) +#define DDR0_PUB_DX0GCR2 (DDR0_PUB_REG_BASE + (0x1c2 << 2)) +#define DDR0_PUB_DX0GCR3 (DDR0_PUB_REG_BASE + (0x1c3 << 2)) +#define DDR0_PUB_DX0GCR4 (DDR0_PUB_REG_BASE + (0x1c4 << 2)) +#define DDR0_PUB_DX0LCDLR0 (DDR0_PUB_REG_BASE + (0x1e0 << 2)) +#define DDR0_PUB_DX0LCDLR2 (DDR0_PUB_REG_BASE + (0x1e2 << 2)) + +#define DDR0_PUB_DX0GTR (DDR0_PUB_REG_BASE + (0x1f0 << 2)) +#define DDR0_PUB_DX1GTR (DDR0_PUB_REG_BASE + (0x230 << 2)) +#define DDR0_PUB_DX2GTR (DDR0_PUB_REG_BASE + (0x270 << 2)) +#define DDR0_PUB_DX3GTR (DDR0_PUB_REG_BASE + (0x2b0 << 2)) + +#define DDR0_PUB_DX1GCR1 (DDR0_PUB_REG_BASE + (0x201 << 2)) +#define DDR0_PUB_DX1GCR2 (DDR0_PUB_REG_BASE + (0x202 << 2)) +#define DDR0_PUB_DX1GCR3 (DDR0_PUB_REG_BASE + (0x203 << 2)) +#define DDR0_PUB_DX1GCR4 (DDR0_PUB_REG_BASE + (0x204 << 2)) +#define DDR0_PUB_DX1LCDLR0 (DDR0_PUB_REG_BASE + (0x220 << 2)) +#define DDR0_PUB_DX1LCDLR2 (DDR0_PUB_REG_BASE + (0x222 << 2)) + +#define DDR0_PUB_DX2GCR0 (DDR0_PUB_REG_BASE + (0x240 << 2)) +#define DDR0_PUB_DX2GCR1 (DDR0_PUB_REG_BASE + (0x241 << 2)) +#define DDR0_PUB_DX2GCR2 (DDR0_PUB_REG_BASE + (0x242 << 2)) +#define DDR0_PUB_DX2GCR3 (DDR0_PUB_REG_BASE + (0x243 << 2)) +#define DDR0_PUB_DX2GCR4 (DDR0_PUB_REG_BASE + (0x244 << 2)) +#define DDR0_PUB_DX2LCDLR0 (DDR0_PUB_REG_BASE + (0x260 << 2)) +#define DDR0_PUB_DX2LCDLR2 (DDR0_PUB_REG_BASE + (0x262 << 2)) + +#define DDR0_PUB_DX3GCR0 (DDR0_PUB_REG_BASE + (0x280 << 2)) +#define DDR0_PUB_DX3GCR1 (DDR0_PUB_REG_BASE + (0x281 << 2)) +#define DDR0_PUB_DX3GCR2 (DDR0_PUB_REG_BASE + (0x282 << 2)) +#define DDR0_PUB_DX3GCR3 (DDR0_PUB_REG_BASE + (0x283 << 2)) +#define DDR0_PUB_DX3GCR4 (DDR0_PUB_REG_BASE + (0x284 << 2)) +#define DDR0_PUB_DX3LCDLR0 (DDR0_PUB_REG_BASE + (0x2a0 << 2)) +#define DDR0_PUB_DX3LCDLR2 (DDR0_PUB_REG_BASE + (0x2a2 << 2)) + +/* PCTL */ +#define DMC_PCTL_BASE 0xc8839000 + +#define PCTL_SCFG (DDR0_PCTL_BASE + 0x000) +#define PCTL_SCTL (DDR0_PCTL_BASE + (0x1 << 2)) +#define PCTL_STAT (DDR0_PCTL_BASE + (0x48 << 2)) + +#define PCTL_CMDTSTAT (DDR0_PCTL_BASE + (0x48 << 2)) + +#define PCTL_PPCFG (DDR0_PCTL_BASE + (0x43 << 2)) +#define PCTL_ZQCFG (DDR0_PCTL_BASE + (0x44 << 2)) + +#define PCTL_MCFG (DDR0_PCTL_BASE + (0x41 << 2)) +#define PCTL_MCFG1 (DDR0_PCTL_BASE + (0x42 << 2)) + +#define PCTL_TCKSRE (DDR0_PCTL_BASE + (0x1a << 2)) +#define PCTL_TZQCSI (DDR0_PCTL_BASE + (0x19 << 2)) +#define PCTL_TCKE (DDR0_PCTL_BASE + (0x1c << 2)) +#define PCTL_TMOD (DDR0_PCTL_BASE + (0x1d << 2)) +#define PCTL_TEXSR (DDR0_PCTL_BASE + (0x15 << 2)) +#define PCTL_TAL (DDR0_PCTL_BASE + (0x50 << 2)) +#define PCTL_TCCD (DDR0_PCTL_BASE + (0x52 << 2)) +#define PCTL_TRTP (DDR0_PCTL_BASE + (0x12 << 2)) +#define PCTL_TFAW (DDR0_PCTL_BASE + (0x11 << 2)) +#define PCTL_TCKSRX (DDR0_PCTL_BASE + (0x1b << 2)) +#define PCTL_TRTW (DDR0_PCTL_BASE + (0x9 << 2)) +#define PCTL_TCWL (DDR0_PCTL_BASE + (0xc << 2)) +#define PCTL_TWR (DDR0_PCTL_BASE + (0x13 << 2)) +#define PCTL_TCL (DDR0_PCTL_BASE + (0xb << 2)) +#define PCTL_TDQS (DDR0_PCTL_BASE + (0x1e << 2)) +#define PCTL_TRCD (DDR0_PCTL_BASE + (0xf << 2)) +#define PCTL_TXP (DDR0_PCTL_BASE + (0x16 << 2)) +#define PCTL_TMRD (DDR0_PCTL_BASE + (0x6 << 2)) +#define PCTL_TRAS (DDR0_PCTL_BASE + (0xd << 2)) +#define PCTL_TREFI_MEM_DDR3 (DDR0_PCTL_BASE + (0x24 << 2)) // replaced by TREFI +#define PCTL_TWTR (DDR0_PCTL_BASE + (0x14 << 2)) +#define PCTL_TRC (DDR0_PCTL_BASE + (0xe << 2)) +#define PCTL_TRFC (DDR0_PCTL_BASE + (0x7 << 2)) +#define PCTL_TCKESR (DDR0_PCTL_BASE + (0x22 << 2)) +#define PCTL_TZQCL (DDR0_PCTL_BASE + (0x20 << 2)) +#define PCTL_TRRD (DDR0_PCTL_BASE + (0x10 << 2)) +#define PCTL_TRP (DDR0_PCTL_BASE + (0x8 << 2)) +#define PCTL_TZQCS (DDR0_PCTL_BASE + (0x18 << 2)) +#define PCTL_TXPDLL (DDR0_PCTL_BASE + (0x17 << 2)) + +#define PCTL_DFIODTCFG (DDR0_PCTL_BASE + (0x27 << 2)) +#define PCTL_DFIODTCFG1 (DDR0_PCTL_BASE + (0x28 << 2)) +#define PCTL_DFITCTRLDELAY (DDR0_PCTL_BASE + (0x26 << 2)) +#define PCTL_DFITPHYWRLAT (DDR0_PCTL_BASE + (0x2b << 2)) +#define PCTL_DFITPHYWRDATA (DDR0_PCTL_BASE + (0x2a << 2)) +#define PCTL_DFITRDDATAEN (DDR0_PCTL_BASE + (0x2c << 2)) +#define PCTL_DFITPHYRDLAT (DDR0_PCTL_BASE + (0x2d << 2)) +#define PCTL_DFITPHYUPDTYPE0 (DDR0_PCTL_BASE + (0x2e << 2)) +#define PCTL_DFITPHYUPDTYPE1 (DDR0_PCTL_BASE + (0x2f << 2)) +#define PCTL_DFIUPDCFG (DDR0_PCTL_BASE + (0x35 << 2)) +#define PCTL_DFISTCFG0 (DDR0_PCTL_BASE + (0x3c << 2)) +#define PCTL_DFISTCFG1 (DDR0_PCTL_BASE + (0x3d << 2)) +#define PCTL_DFISTSTAT0 (DDR0_PCTL_BASE + (0x46 << 2)) +#define PCTL_DFILPCFG0 (DDR0_PCTL_BASE + (0x40 << 2)) +#define PCTL_DFITCTRLUPDMIN (DDR0_PCTL_BASE + (0x32 << 2)) +#define PCTL_DFITCTRLUPDMAX (DDR0_PCTL_BASE + (0x33 << 2)) +#define PCTL_DFITDRAMCLKEN (DDR0_PCTL_BASE + (0x3e << 2)) +#define PCTL_DFITDRAMCLKDIS (DDR0_PCTL_BASE + (0x3f << 2)) + +/* DDR MMC (see dram-gx.h for more details) */ +#define DDR_MMC_BASE 0xc8837000 + +#define DDR0_SOFT_RESET (DDR_MMC_BASE + 0x20) + +#define AM_DDR_PLL_STS (DDR_MMC_BASE + 0x18) +#define DDR_CLK_CNTL (DDR_MMC_BASE + 0x1c) +#define DDR0_APD_CTRL (DDR_MMC_BASE + 0x24) +#endif diff --git a/arch/arm/include/asm/arch-meson/dram-settings-gx.h b/arch/arm/include/asm/arch-meson/dram-settings-gx.h new file mode 100644 index 0000000000000000000000000000000000000000..b4ced2eda67bc51da0ac74bc05dbccfc990beda5 --- /dev/null +++ b/arch/arm/include/asm/arch-meson/dram-settings-gx.h @@ -0,0 +1,296 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2023-2024, Ferass El Hafidi <fundersc...@postmarketos.org> + */ +#ifndef DRAM_SETTINGS_GX_H +#define DRAM_SETTINGS_GX_H +#include <linux/bitops.h> +#include <asm/arch/dram-gx.h> + +/* + * These registers are pretty similar to other DRAM registers found in + * Allwinner A31/sun6i. Some of these registers also exist in some Rockchip + * SoCs and the TI KeyStone3. + */ +/* DMC control register */ +#if defined(CONFIG_DRAM_TWO_IDENTICAL_RANKS) || defined(CONFIG_DRAM_ONE_RANK) +#define DMC_DRAM_SIZE_SHIFT 6 +#else +#define DMC_DRAM_SIZE_SHIFT 7 +#endif +#define DMC_CTRL_CHANNEL BIT(6) /* Channel 0 only */ +#if defined(CONFIG_DRAM_DDR4) +#define DMC_CTRL_DDR_TYPE BIT(22) | BIT(20) /* DDR4 */ +#else +#define DMC_CTRL_DDR_TYPE 0 +#endif +#if defined(CONFIG_DRAM_ONE_RANK) || defined(CONFIG_DRAM_TWO_DIFF_RANKS) +#define DMC_CTRL_RANK BIT(21) /* Enable rank 1 */ +#elif defined(CONFIG_DRAM_TWO_IDENTICAL_RANKS) +#define DMC_CTRL_RANK BIT(22) /* Rank 0 and 1 are identical */ +#elif defined(CONFIG_DRAM_16BIT_RANK) +#define DMC_CTRL_RANK BIT(16) /* 16-bit Rank 0 */ +#endif +#define DMC_CTRL DMC_CTRL_CHANNEL | DMC_CTRL_RANK | DMC_CTRL_DDR_TYPE + +/* Mode Register */ +#if defined(CONFIG_MESON_GXL) && defined(CONFIG_DRAM_DDR4) +#define PUB_MR0 4 | (((((timings.cl - 9) >> 1) & 7) << 4)) | \ + ((((timings.wr - 10) >> 1) & 7) << 9) +#define PUB_MR1 (timings.odt << 8) | (timings.drv << 1) | 0x81 +#define PUB_MR2 (((timings.cwl - 6) >> 1) & 7) << 3 | 0xc0 +#define PUB_MR3 0 +#define PUB_MR4 8 +#else +#define PUB_MR0 (((timings.cl - 4) & 8) >> 1) | \ + (((timings.cl - 4) & 7) << 4) | \ + (((timings.wr <= 8 ? (timings.wr - 4) : (timings.wr >> 1)) & 7) << 9) | 0x1c00 +#define PUB_MR1 (timings.drv << 1) | \ + ((timings.odt & 1) << 2) | \ + (((timings.odt >> 1) & 1) << 6) | \ + (((timings.odt >> 2) & 1) << 9) | \ + BIT(7) | \ + ((timings.al ? ((timings.cl - timings.al) & 3) : 0) << 3) +#define PUB_MR2 BIT(6) | (((timings.cwl - 5) & 7) << 3) +#endif +#define PUB_MR3 0 +#if defined(CONFIG_MESON_GXL) +#if defined(CONFIG_DRAM_DDR3) +#define PUB_MR4 0 +#define PUB_MR5 0x420 +#elif defined(CONFIG_DRAM_DDR4) +#define PUB_MR5 0x400 +#endif +#define PUB_MR6 0x800 +#endif + +/* ODT Configuration Register */ +#if defined(CONFIG_MESON_GXBB) +#define PUB_ODTCR 0x210000 +#elif defined(CONFIG_MESON_GXL) +#define PUB_ODTCR 0x30000 +#endif + +/* DDR Timing Parameter */ +#if defined(CONFIG_MESON_GXBB) +#define PUB_DTPR0 timings.rtp | \ + (timings.wtr << 4) | \ + (timings.rp << 8) | \ + (timings.ras << 16) | \ + (timings.rrd << 22) | \ + (timings.rcd << 26) +#define PUB_DTPR1 (timings.mod << 2) | \ + (timings.faw << 5) | \ + (timings.rfc << 11) | \ + (timings.wlmrd << 20) | \ + (timings.wlo << 26) +#define PUB_DTPR2 timings.xs | \ + (timings.xp << 10) | \ + (timings.dllk << 19) +#define PUB_DTPR3 0 | \ + (0 << 3) | \ + (timings.rc << 6) | \ + (timings.cke << 13) | \ + (timings.mrd << 18) | \ + (0 << 29) +#elif defined(CONFIG_MESON_GXL) +#define PUB_DTPR0 timings.rtp | \ + (timings.rp << 8) | \ + (timings.ras << 16) | \ + (timings.rrd << 24) +#define PUB_DTPR1 (timings.wlmrd << 24) | \ + (timings.faw << 16) | \ + timings.mrd +#define PUB_DTPR2 timings.xs | \ + (timings.cke << 16) +#define PUB_DTPR3 (timings.dllk << 16) | (4 << 28) +#define PUB_DTPR4 timings.xp | BIT(11) | (timings.rfc << 0x10) +#define PUB_DTPR5 (timings.rc << 16) | (timings.rcd << 8) | \ + timings.wtr +#endif + +#if defined(CONFIG_MESON_GXBB) +#define PUB_PGCR0 0x7D81E3F +#define PUB_PGCR1 0x380C6A0 +#define PUB_PGCR2 (0x1F12480 & 0xefffffff) +#define PUB_PGCR3 0xC0AAFE60 +#elif defined(CONFIG_MESON_GXL) +#define PUB_PGCR0 0x7d81e3f +#define PUB_PGCR1 0x2004620 +#define PUB_PGCR2 (0xf05f97 & 0xefffffff) +#if defined(CONFIG_DRAM_DDR3) +#define PUB_PGCR3 0xc0aae860 +#elif defined(CONFIG_DRAM_DDR4) +#define PUB_PGCR3 0xc0aae860 | 0x4000000 +#endif +#endif + +#if defined(CONFIG_MESON_GXBB) +#define PUB_DXCCR 0x181884 +#define PUB_DTCR 0x4300308f +#define PUB_DSGCR 0x20645A + +#define PUB_ZQ0PR 0x69 +#define PUB_ZQ1PR 0x69 +#define PUB_ZQ2PR 0x69 +#define PUB_ZQ3PR 0x69 +#elif defined(CONFIG_MESON_GXL) +#define PUB_DXCCR 0x20c01204 + +#if defined(CONFIG_DRAM_DDR4) +#define PUB_DTCR 0x80003187 | 0x40 +#else +#define PUB_DTCR 0x80003187 +#endif + +#define PUB_DTCR1 0x00010237 /* XXX: Needed? */ +#define PUB_DSGCR (0x20641b | 0x800004) /* Works on DDR4 too? */ + +#if defined(CONFIG_DRAM_DDR3) +#define PUB_ZQ0PR 0x5d95d +#define PUB_ZQ1PR 0x5d95d +#define PUB_ZQ2PR 0x5d95d +#define PUB_ZQ3PR 0x1dd1d +#elif defined(CONFIG_DRAM_DDR4) +#define PUB_ZQ0PR 0x775d +#define PUB_ZQ1PR 0x6fc5d +#define PUB_ZQ2PR 0x6fc5d +#define PUB_ZQ3PR 0x1dd1d +#endif +#endif + +#if defined(CONFIG_DRAM_DDR3) +#define PUB_DCR 0xb +#elif defined(CONFIG_DRAM_DDR4) +#define PUB_DCR 0x1800040c +#endif +#define PUB_DTAR (0 | (0 << 12) | (0 << 28)) /* Uh? */ + +#define PCTL0_1US_PCK 0x1C8 +#define PCTL0_100NS_PCK 0x2D +#define PCTL0_INIT_US 0x2 +#define PCTL0_RSTH_US 0x2 + +/* Mode Config(?) */ +#if defined(CONFIG_MESON_GXBB) +#define PCTL0_MCFG ((((timings.faw + timings.rrd - 1) / timings.rrd) & 3) << 0x12) | \ + (0xa2f21 & 0xfff3ffff) +#define PCTL0_MCFG1 (((timings.rrd - ((timings.faw - (timings.faw / timings.rrd) * \ + timings.rrd) & 0xff)) & 7) << 8) | \ + (0x80200000 & 0xfffffcff) +#elif defined(CONFIG_MESON_GXL) +#if defined(CONFIG_DRAM_DDR3) +#define PCTL0_MCFG_DDRTYPE 0 +#elif defined(CONFIG_DRAM_DDR4) +#define PCTL0_MCFG_DDRTYPE BIT(4) +#endif + +#define PCTL0_MCFG (0xa2f21 & 0xffffff8f) | PCTL0_MCFG_DDRTYPE +/* XXX: What is this? ↓ ??? */ +#define PCTL0_MCFG1 0 +#endif + +#define PCTL0_SCFG 0xF01 + +#if defined(CONFIG_MESON_GXL) && defined(CONFIG_DRAM_16BIT_RANK) +#define PCTL0_PPCFG 0x1fd +#else +#define PCTL0_PPCFG 0x1e0 +#endif + +#define PCTL0_DFISTCFG0 0x4 +#define PCTL0_DFISTCFG1 0x1 + +#define PCTL0_DFITCTRLDELAY 0x2 + +#if defined(CONFIG_MESON_GXBB) +#define PCTL0_DFITPHYWRDATA 0x1 +#else +#define PCTL0_DFITPHYWRDATA 0x2 +#endif + +#if defined(CONFIG_MESON_GXBB) +#define PCTL0_DFITPHYWRLTA (timings.cwl + timings.al - \ + (((timings.cwl + timings.al) % 2) ? 3 : 4)) / 2 +#define PCTL0_DFITRDDATAEN (timings.cl + timings.al - \ + (((timings.cl + timings.al) % 2) ? 3 : 4)) / 2 +#define PCTL0_DFITPHYRDLAT ((timings.cl + timings.al) % 2) ? 14 : 16 +#elif defined(CONFIG_MESON_GXL) +#define PCTL0_DFITPHYWRLTA ((timings.cwl + timings.al) - 2) +#define PCTL0_DFITRDDATAEN ((timings.cl + timings.al) - 4) +#define PCTL0_DFITPHYRDLAT 0x16 +#endif + +#define PCTL0_DFITDRAMCLKDIS 1 +#define PCTL0_DFITDRAMCLKEN 1 +#if defined(CONFIG_MESON_GXBB) +#define PCTL0_DFITPHYUPDTYPE1 0x200 +#else +#define PCTL0_DFITPHYUPDTYPE0 16 +#define PCTL0_DFITPHYUPDTYPE1 16 +#define PCTL0_DFITCTRLUPDMAX 64 +#define PCTL0_DFIUPDCFG 3 +#endif +#define PCTL0_DFITCTRLUPDMIN 16 + +#define PCTL0_CMDTSTATEN 1 + +#if defined(CONFIG_DRAM_ONE_RANK) || defined(CONFIG_DRAM_16BIT_RANK) +#define PCTL0_DFIODTCFG 0x808 +#elif defined(CONFIG_DRAM_TWO_DIFF_RANKS) +#define PCTL0_DFIODTCFG 0xc0c +#elif defined(CONFIG_DRAM_TWO_IDENTICAL_RANKS) +#define PCTL0_DFIODTCFG 0x8 +#endif + +#if defined(CONFIG_MESON_GXBB) +#define PCTL0_DFIODTCFG1 (0 | (6 << 16)) +#elif defined(CONFIG_MESON_GXL) +#if defined(CONFIG_DRAM_16BIT_RANK) +#define PCTL0_DFIODTCFG1 ((6 << 16) | (8 << 16)) +#else +#define PCTL0_DFIODTCFG1 ((6 << 16) | (3 << 25) | (8 << 16)) +#endif +#endif +#define PCTL0_DFILPCFG0 (1 | (3 << 4) | BIT(8) | (3 << 12) | \ + (7 << 16) | BIT(24) | (3 << 28)) + +#if defined(CONFIG_MESON_GXBB) +#define PUB_ACBDLR0 0x10 +#elif defined(CONFIG_MESON_GXL) +#if defined(CONFIG_DRAM_DDR3) +#define PUB_ACBDLR0 0 +#define PUB_ACBDLR3 0 +#define PUB_ACLCDLR 48 +#elif defined(CONFIG_DRAM_DDR4) +#define PUB_ACBDLR0 0x3f +#define PUB_ACBDLR3 0x10 +#define PUB_ACLCDLR 0x28 +#else +#define PUB_ACBDLR0 0 +#define PUB_ACBDLR3 0 +#define PUB_ACLCDLR 48 +#endif +#endif + +#define LPDDR3_CA0 2 +#define LPDDR3_CA1 0 +#define LPDDR3_REMAP 3 +#define LPDDR3_WL 1 + +/* PLL */ +#if defined(CONFIG_MESON_GXBB) +#define DDR_PLL_CNTL1 0x69c80000 +#define DDR_PLL_CNTL2 0xca463823 +#define DDR_PLL_CNTL3 0xc00023 +#define DDR_PLL_CNTL4 0x303500 +#define DDR_PLL_CNTL5 0 /* Unused */ +#elif defined(CONFIG_MESON_GXL) +#define DDR_PLL_CNTL1 0xaa203 +#define DDR_PLL_CNTL2 0x2919a288 +#define DDR_PLL_CNTL3 0x3e3b744 +#define DDR_PLL_CNTL4 0xc0101 +#define DDR_PLL_CNTL5 0xe600001e +#endif + +#endif /* DRAM_SETTINGS_GX_H */ diff --git a/arch/arm/include/asm/arch-meson/dram-timings-gx.h b/arch/arm/include/asm/arch-meson/dram-timings-gx.h new file mode 100644 index 0000000000000000000000000000000000000000..144b727e998ed5daf226143ef01d7ccaed5b9777 --- /dev/null +++ b/arch/arm/include/asm/arch-meson/dram-timings-gx.h @@ -0,0 +1,117 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (C) 2024, Ferass El Hafidi <fundersc...@postmarketos.org> + */ +#ifndef DRAM_TIMINGS_GX_H +#define DRAM_TIMINGS_GX_H + +/* + * DRAM timings + * It looks like those are quite similar in regular boards based on reference + * designs and not using counterfeit RAM chips. Those are hacked around by lowbin + * TV box vendors to support lowbin RAM chips, however. Here, we are hardcoding + * timings, which *will* cause issues on lowbin boards, but should be fine on other + * boards derived from Amlogic reference designs. + */ + +/* + * TODO: + * - Add timings for different DRAM clocks + * - Support overwriting those if board needs different timings (how?) + * - Other things + */ + +#if defined(CONFIG_DRAM_DDR3) +/* DDR3: 912 MHz */ +const struct meson_gx_dram_timings timings = { + .drv = 0, + .odt = 2, + + /* Timings */ + .rtp = 0x7, + .wtr = 0x7, + .rp = 0xd, + .rcd = 0xd, + .ras = 0x25, + .rrd = 0x7, + .rc = 0x34, + .mrd = 0x6, /* Should be < 8 */ + .mod = 0x4, + .faw = 0x21, + .wlmrd = 0x28, + .wlo = 0x7, + .rfc = 0x118, + .xp = 0x7, + .xs = 0x200, + .dllk = 0x200, + .cke = 0x5, + .rtodt = 0x0, + .rtw = 0x7, + .refi = 0x4e, + .refi_mddr3 = 0x4, + .cl = 0xd, + .wr = 0x10, + .cwl = 0x9, + .al = 0x0, + .dqs = 0x17, + .cksre = 0xf, + .cksrx = 0xf, + .zqcs = 0x40, + .xpdll = 0x17, + .exsr = 0x200, /* Should be < 0x3ff */ + .zqcl = 0x88, + .zqcsi = 0x3e8, + .rpab = 0x0, + .rppb = 0x0, + .tdqsck = 0x0, + .tdqsckmax = 0x0, + .tckesr = 0x0, + .tdpd = 0x0, + .taond_aofd = 0x0, + .tccdl = 0, /* Unused on GXBB */ +}; + +#elif defined(CONFIG_DRAM_DDR4) +/* DDR4: 1080 MHz */ +const struct meson_gx_dram_timings timings = { + .drv = 1, + .odt = 1, + + /* Timings */ + .rtp = 9, + .wtr = 9, + .rp = 0x10, // ddr_clk < 1200 + .rcd = 0x10, // ddr_clk < 1200 + .ras = 35 * 1.2, + .rrd = 6, + .rc = 0x3a, + .mrd = 8, + .mod = 24, + .faw = 35 * 1.2, + .rfc = 350 * 1.2, + .wlmrd = 40, + .wlo = 9.5 * 1.2, + .xs = 512, + .xp = 7, + .cke = 5, + .dllk = 1024, + .rtodt = 0, + .rtw = 8, + .refi = 76, + .refi_mddr3 = 4, + .cl = 0x10, // ddr_clk < 1200 + .wr = 0x12, + .cwl = 12, + .al = 0, + .exsr = 1024, + .dqs = 9, + .cksre = 15, + .cksrx = 15, + .zqcs = 128, + .zqcl = 256, + .xpdll = 23, + .zqcsi = 1000, + .tccdl = 6, // ddr_clk < 1200 +}; +#endif +#endif diff --git a/arch/arm/mach-meson/Kconfig b/arch/arm/mach-meson/Kconfig index 8d1bf91e98b49822d036f10b5737a73247bc83c6..ef86129b5354e9700f9a9cc9fdafe05caa531d9e 100644 --- a/arch/arm/mach-meson/Kconfig +++ b/arch/arm/mach-meson/Kconfig @@ -99,6 +99,76 @@ if MESON_GX && SPL config SPL_SYS_MALLOC_F_LEN default 0x2000 +choice + prompt "DRAM rank mode" + help + Choose rank mode. This heavily depends on the board and you should + leave the board default set if you don't know what this is. + If you choose the wrong rank mode DRAM init in SPL may either fail + or in rare occasions require multiple resets before it succeeds. + +config DRAM_ONE_RANK + bool "One rank" + +config DRAM_TWO_IDENTICAL_RANKS + bool "Two identical ranks" + +if MESON_GXBB +config DRAM_TWO_DIFF_RANKS + bool "Two different ranks" +endif + +if MESON_GXL +config DRAM_16BIT_RANK + bool "One 16-bit rank" +endif +endchoice + +choice + prompt "DRAM memory type" + default DRAM_DDR3 + help + Select the DDR type according to your board design. GXBB/S905 + currently only supports DDR3. + +config DRAM_DDR3 + bool "DDR3" + +if MESON_GXL +config DRAM_DDR4 + bool "DDR4" +endif +endchoice + +config DRAM_DQS_CORR + bool "Enable DQS correction" + +config DRAM_CLK + int "DRAM clock" + default 912 + help + This option contains the DRAM clock to use in MHz. + +config DRAM_SIZE + int "DRAM size" + default 1024 + help + This option contains the DRAM size. Units in MB. + +choice + prompt "Enable DRAM 2T mode" + default DRAM_1T_MODE + help + Choose whenever to use 2T mode or not. + +config DRAM_1T_MODE + bool "Use DRAM 1T mode" + +config DRAM_2T_MODE + bool "Use DRAM 2T mode" + +endchoice + choice prompt "Set VDDEE init voltage" default SPL_MESON_GX_VDDEE_1000MV diff --git a/arch/arm/mach-meson/Makefile b/arch/arm/mach-meson/Makefile index 7dc8ec08cfc5fe6e79fc59fc4db745ca3dd2cd93..7074e50d23f884178e195d356b7921f60047f47c 100644 --- a/arch/arm/mach-meson/Makefile +++ b/arch/arm/mach-meson/Makefile @@ -5,6 +5,9 @@ obj-y += board-common.o sm.o board-info.o obj-$(CONFIG_MESON_GX) += board-gx.o ifeq ($(CONFIG_SPL_BUILD),y) +obj-$(CONFIG_MESON_GXBB) += dram-gxbb.o +obj-$(CONFIG_MESON_GXL) += dram-gxl.o +obj-$(CONFIG_MESON_GX) += dram-gx.o obj-$(CONFIG_MESON_GX) += spl-gx.o obj-$(CONFIG_MESON_GX) += spl.o endif diff --git a/arch/arm/mach-meson/dram-gx.c b/arch/arm/mach-meson/dram-gx.c new file mode 100644 index 0000000000000000000000000000000000000000..049beda6ef3da2f4ee7af25e41d8807e86bd6e25 --- /dev/null +++ b/arch/arm/mach-meson/dram-gx.c @@ -0,0 +1,419 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Portions Copyright (C) 2015, Amlogic, Inc. All rights reserved. + * Copyright (C) 2023-2025, Ferass El Hafidi <fundersc...@postmarketos.org> + */ +#include <init.h> +#include <asm/unaligned.h> +#include <linux/libfdt.h> +#include <config.h> +#include <errno.h> +#include <asm/io.h> +#include <asm/arch/dram-gx.h> +#include <asm/arch/gx.h> +#include <asm/arch/clock-gx.h> +#include <asm/arch/dram-settings-gx.h> +#include <asm/arch/dram-timings-gx.h> +#include <linux/delay.h> + +/* + * Meson GX common shared DRAM init code + * + * See dram-gxbb.c and dram-gxl.c for gxbb/gxl-specific code + */ + +void meson_dram_pll_init(void) +{ + setbits_32(AM_ANALOG_TOP_REG1, 1); + setbits_32(GX_HIU_BASE + HHI_MPLL_CNTL5, 1); + + clrbits_32(AM_DDR_PLL_CNTL4, BIT(12)); + setbits_32(AM_DDR_PLL_CNTL4, BIT(12)); + + udelay(10); + + do { + if (IS_ENABLED(CONFIG_MESON_GXBB)) + writel(1 << 29, AM_DDR_PLL_CNTL0); + writel(DDR_PLL_CNTL1, AM_DDR_PLL_CNTL1); + writel(DDR_PLL_CNTL2, AM_DDR_PLL_CNTL2); + writel(DDR_PLL_CNTL3, AM_DDR_PLL_CNTL3); + writel(DDR_PLL_CNTL4, AM_DDR_PLL_CNTL4); + if (IS_ENABLED(CONFIG_MESON_GXBB)) { + if (CONFIG_DRAM_CLK >= 375 && CONFIG_DRAM_CLK <= 749) + writel((1 << 29) | ((2 << 16) | (1 << 9) | + (((CONFIG_DRAM_CLK / 6) * 6) / 12)), AM_DDR_PLL_CNTL0); + else if (CONFIG_DRAM_CLK >= 750 && CONFIG_DRAM_CLK <= 1449) + writel((1 << 29) | ((1 << 16) | (1 << 9) | + (((CONFIG_DRAM_CLK / 12) * 12) / 24)), AM_DDR_PLL_CNTL0); + clrbits_32(AM_DDR_PLL_CNTL0, 1 << 29); + } else if (IS_ENABLED(CONFIG_MESON_GXL)) { + writel(DDR_PLL_CNTL5, AM_DDR_PLL_CNTL5); + if (CONFIG_DRAM_CLK >= 399 && CONFIG_DRAM_CLK <= 799) + writel(((1 << 16) | ((1 << 2) | 1) | + ((CONFIG_DRAM_CLK / 12) << 4)) | + ((1 << 31) | (1 << 29) | (1 << 28)), AM_DDR_PLL_CNTL0); + else if (CONFIG_DRAM_CLK >= 800 && CONFIG_DRAM_CLK <= 1498) + writel(((1 << 16) | (1 << 2) | + ((CONFIG_DRAM_CLK / 24) << 4)) | + ((1 << 31) | (1 << 29) | (1 << 28)), AM_DDR_PLL_CNTL0); + } + udelay(200); + } while (!((readl(AM_DDR_PLL_STS) >> 0x1F) & 1)); + + if (IS_ENABLED(CONFIG_MESON_GXBB)) { + writel(DDR_CLK_CNTL_CLKGEN_SOFTRESET | + DDR_CLK_CNTL_PHY_CLK_ENABLE | + DDR_CLK_CNTL_DDRPLL_ENABLE, DDR_CLK_CNTL); + } else if (IS_ENABLED(CONFIG_MESON_GXL)) { + writel(DDR_CLK_CNTL_CLKGEN_SOFTRESET | + DDR_CLK_CNTL_PHY_CLK_ENABLE | + DDR_CLK_CNTL_DDRPLL_ENABLE | + 0xa005 /* unknown */, DDR_CLK_CNTL); + } + + printf("DRAM clock: %d MHz\n", CONFIG_DRAM_CLK); +} + +void meson_dram_phy_prepare(void) +{ + /* Release reset of DLL */ + writel(0xffffffff, DMC_SOFT_RST); + writel(0xffffffff, DMC_SOFT_RST1); + udelay(10); + + /* Enable UPCTL and PUB clock */ + if (IS_ENABLED(CONFIG_MESON_GXBB)) + writel(0x550620, DMC_PCTL_LP_CTRL); + else if (IS_ENABLED(CONFIG_MESON_GXL)) + writel(0, DMC_PCTL_LP_CTRL); + writel(0xf, DDR0_SOFT_RESET); + udelay(10); +} + +void meson_dram_set_memory_timings(void) +{ + /* Set memory timings */ + writel(timings.rfc, PCTL_TRFC); + if (IS_ENABLED(CONFIG_MESON_GXL)) + writel(timings.faw, PCTL_TFAW); + writel(timings.refi_mddr3, PCTL_TREFI_MEM_DDR3); + writel(timings.mrd, PCTL_TMRD); + if (IS_ENABLED(CONFIG_MESON_GXL)) + writel((timings.rp << 16) | timings.rp, PCTL_TRP); + else /* Meson GXBB */ + writel(timings.rp, PCTL_TRP); + writel(timings.cke + 1, PCTL_TCKESR); + writel(timings.al, PCTL_TAL); + writel(timings.cwl, PCTL_TCWL); + writel(timings.cl, PCTL_TCL); + writel(timings.ras, PCTL_TRAS); + writel(timings.rc, PCTL_TRC); + writel(timings.rcd, PCTL_TRCD); + if (IS_ENABLED(CONFIG_MESON_GXBB)) { + writel(timings.rrd, PCTL_TRRD); + } else { + writel(timings.rrd | ((timings.rrd + 2) * 0x10000), PCTL_TRRD); + writel((timings.tccdl << 16) | 4, PCTL_TCCD); + } + writel(timings.rtp, PCTL_TRTP); + writel(timings.wr, PCTL_TWR); + writel(timings.wtr, PCTL_TWTR); + writel(timings.exsr, PCTL_TEXSR); + writel(timings.xp, PCTL_TXP); + writel(timings.dqs, PCTL_TDQS); + writel(timings.rtw, PCTL_TRTW); + writel(timings.cksre, PCTL_TCKSRE); + writel(timings.cksrx, PCTL_TCKSRX); + writel(timings.mod, PCTL_TMOD); + writel(timings.cke, PCTL_TCKE); + writel(timings.zqcs, PCTL_TZQCS); + writel(timings.zqcl, PCTL_TZQCL); + writel(timings.xpdll, PCTL_TXPDLL); + writel(timings.zqcsi, PCTL_TZQCSI); + + if (IS_ENABLED(CONFIG_MESON_GXBB)) { + /* GXBB: Enter config state */ + writel(PCTL0_SCFG, PCTL_SCFG); + writel(PCTL_SCTL_CFG_STATE, PCTL_SCTL); + } +} + +void meson_dram_set_dfi_timings(void) +{ +#ifdef CONFIG_MESON_GXL + writel(0xab0a560a, PCTL_ZQCFG); +#endif + WAIT_FOR(PCTL_STAT); + + writel(PCTL0_PPCFG, PCTL_PPCFG); + writel(PCTL0_DFISTCFG0, PCTL_DFISTCFG0); + writel(PCTL0_DFISTCFG1, PCTL_DFISTCFG1); + writel(PCTL0_DFITCTRLDELAY, PCTL_DFITCTRLDELAY); + writel(PCTL0_DFITPHYWRDATA, PCTL_DFITPHYWRDATA); + writel(PCTL0_DFITPHYWRLTA, PCTL_DFITPHYWRLAT); + writel(PCTL0_DFITRDDATAEN, PCTL_DFITRDDATAEN); + writel(PCTL0_DFITPHYRDLAT, PCTL_DFITPHYRDLAT); + writel(PCTL0_DFITDRAMCLKDIS, PCTL_DFITDRAMCLKDIS); + writel(PCTL0_DFITDRAMCLKEN, PCTL_DFITDRAMCLKEN); + writel(PCTL0_DFITCTRLUPDMIN, PCTL_DFITCTRLUPDMIN); +#if defined(CONFIG_MESON_GXL) + writel(PCTL0_DFITCTRLUPDMAX, PCTL_DFITCTRLUPDMAX); + writel(PCTL0_DFIUPDCFG, PCTL_DFIUPDCFG); +#endif + writel(PCTL0_DFILPCFG0, PCTL_DFILPCFG0); +#if defined(CONFIG_MESON_GXL) + writel(PCTL0_DFITPHYUPDTYPE0, PCTL_DFITPHYUPDTYPE0); +#endif + writel(PCTL0_DFITPHYUPDTYPE1, PCTL_DFITPHYUPDTYPE1); + writel(PCTL0_DFIODTCFG, PCTL_DFIODTCFG); + writel(PCTL0_DFIODTCFG1, PCTL_DFIODTCFG1); +#if defined(CONFIG_MESON_GXBB) + writel(PCTL0_CMDTSTATEN, PCTL_CMDTSTATEN); +#endif +} + +uint meson_dram_phy_finalise_init(void) +{ + writel(PUB_ZQ0PR, DDR0_PUB_ZQ0PR); + writel(PUB_ZQ1PR, DDR0_PUB_ZQ1PR); + writel(PUB_ZQ2PR, DDR0_PUB_ZQ2PR); +#if defined(CONFIG_MESON_GXBB) + writel(PUB_ZQ3PR, DDR0_PUB_ZQ3PR); +#endif + + writel(PUB_PIR_INIT | PUB_PIR_ZCAL, DDR0_PUB_PIR); + WAIT_FOR(DDR0_PUB_PGSR0); + /* + * Is this needed? + * TODO: test without + */ + writel(readl(DDR0_PUB_ZQCR) | (1 << 2) | (1 << 27), DDR0_PUB_ZQCR); + udelay(10); + writel(readl(DDR0_PUB_ZQCR) & ~((1 << 2) | (1 << 27)), DDR0_PUB_ZQCR); + udelay(30); + +#if defined(CONFIG_MESON_GXL) && defined(CONFIG_DRAM_16BIT_RANK) + clrsetbits_32(DDR0_PUB_DX2GCR0, 0xb0001, 0xb0000); /* Make it neat somehow? */ + clrsetbits_32(DDR0_PUB_DX3GCR0, 0xb0001, 0xb0000); +#endif + + writel(PUB_ACBDLR0, DDR0_PUB_ACBDLR0); +#if defined(CONFIG_MESON_GXL) + writel(PUB_ACBDLR3, DDR0_PUB_ACBDLR3); +#endif + +#if defined(CONFIG_MESON_GXL) && defined(CONFIG_DRAM_2T_MODE) && defined(CONFIG_DRAM_DDR3) + writel(0x10101010, DDR0_PUB_ACBDLR1); + writel(0x10101010, DDR0_PUB_ACBDLR7); + writel(0x20202020, DDR0_PUB_ACBDLR8); + writel(0x30303030, DDR0_PUB_ACBDLR9); + writel(0x3f003f, DDR0_PUB_ACBDLR2); + writel(0, DDR0_PUB_ACBDLR6); +#endif + +#if defined(CONFIG_MESON_GXL) && defined(CONFIG_DRAM_DDR3) + clrsetbits_32(DDR0_PUB_DXCCR, (3 << 5) | (3 << 7) | + (3 << 9) | (3 << 11), (1 << 12) | (1 << 9)); +#endif + + writel(PUB_PIR_FINAL_STEP, DDR0_PUB_PIR); + udelay(1000); + + for (u32 pgsr0 = readl(DDR0_PUB_PGSR0); (pgsr0 != 0xc0000fff) && + (pgsr0 != 0x80000fff); pgsr0 = readl(DDR0_PUB_PGSR0)) { + udelay(20); + debug("Waiting for PGSR0, currently 0x%x\n", pgsr0); + + /* Check for errors */ + if (pgsr0 & PUB_PGSR0_ZCERR) + pr_err("%s: impedance calibration error\n", __func__); + if (pgsr0 & PUB_PGSR0_WLERR) + pr_err("%s: write leveling error\n", __func__); + if (pgsr0 & PUB_PGSR0_QSGERR) + pr_err("%s: DQS gate training error\n", __func__); + if (pgsr0 & PUB_PGSR0_WLAERR) + pr_err("%s: WL Adj error\n", __func__); + if (pgsr0 & PUB_PGSR0_RDERR) + pr_err("%s: read bit deskew error", __func__); + if (pgsr0 & PUB_PGSR0_WDERR) + pr_err("%s: write bit deskew error", __func__); + if (pgsr0 & PUB_PGSR0_REERR) + pr_err("%s: read eye training error", __func__); + if (pgsr0 & PUB_PGSR0_WEERR) + pr_err("%s: write eye training error", __func__); + } + debug("Wait done for PGSR0, currently 0x%x\n", readl(DDR0_PUB_PGSR0)); + + return 0; +} + +void meson_dram_dmc_set_addrmap(void) +{ + if (IS_ENABLED(CONFIG_MESON_GXBB)) { + /* GXBB address map */ + if (IS_ENABLED(CONFIG_DRAM_TWO_IDENTICAL_RANKS) || + IS_ENABLED(CONFIG_DRAM_ONE_RANK)) { + writel(11 | 31 << 5 | 0 << 10 | 14 << 15 | 15 << 20 | 16 << 25, + DDR0_ADDRMAP_1); + writel(30 | 12 << 5 | 13 << 10 | 29 << 15 | 0 << 20 | 0 << 25, + DDR0_ADDRMAP_4); + } else if (IS_ENABLED(CONFIG_DRAM_TWO_DIFF_RANKS)) { + writel(11 | 31 << 5 | 0 << 10 | 14 << 15 | 15 << 20 | 16 << 25, + DDR0_ADDRMAP_1); + writel(0 | 12 << 5 | 13 << 10 | 29 << 15 | 0 << 20 | 30 << 25, + DDR0_ADDRMAP_4); + } + } else if (IS_ENABLED(CONFIG_MESON_GXL) && IS_ENABLED(CONFIG_DRAM_DDR3)) { + /* This applies for GXL + DDR3 RAM (e.g. LePotato) */ + if (IS_ENABLED(CONFIG_DRAM_TWO_IDENTICAL_RANKS) || + IS_ENABLED(CONFIG_DRAM_ONE_RANK)) { + writel(11 | 30 << 5 | 0 << 10 | 15 << 15 | 16 << 20 | 17 << 25, + DDR0_ADDRMAP_1); + writel(18 | 19 << 5 | 20 << 10 | 21 << 15 | 22 << 20 | 23 << 25, + DDR0_ADDRMAP_2); + writel(24 | 25 << 5 | 26 << 10 | 27 << 15 | 28 << 20 | 29 << 25, + DDR0_ADDRMAP_3); + writel(30 | 12 << 5 | 13 << 10 | 14 << 15 | 0 << 20 | 31 << 25, + DDR0_ADDRMAP_4); + + writel(5 | 6 << 5 | 7 << 10 | 8 << 15 | 9 << 20 | 10 << 25, + DDR1_ADDRMAP_0); + writel(11 | 30 << 5 | 0 << 10 | 15 << 15 | 16 << 20 | 17 << 25, + DDR1_ADDRMAP_1); + writel(18 | 19 << 5 | 20 << 10 | 21 << 15 | 22 << 20 | 23 << 25, + DDR1_ADDRMAP_2); + writel(24 | 25 << 5 | 26 << 10 | 27 << 15 | 28 << 20 | 29 << 25, + DDR1_ADDRMAP_3); + writel(30 | 12 << 5 | 13 << 10 | 14 << 15 | 0 << 20 | 31 << 25, + DDR1_ADDRMAP_4); + } + } else if (IS_ENABLED(CONFIG_MESON_GXL) && IS_ENABLED(CONFIG_DRAM_DDR4)) { + /* This applies for GXL + DDR4 RAM (e.g. LaFrite) */ + if (IS_ENABLED(CONFIG_DRAM_TWO_IDENTICAL_RANKS) || + IS_ENABLED(CONFIG_DRAM_ONE_RANK)) { + writel(6 | 7 << 5 | 8 << 10 | 9 << 15 | 10 << 20 | 11 << 25, + DDR0_ADDRMAP_0); + writel(12 | 0 << 5 | 0 << 10 | 15 << 15 | 16 << 20 | 17 << 25, + DDR0_ADDRMAP_1); + writel(18 | 19 << 5 | 20 << 10 | 21 << 15 | 22 << 20 | 23 << 25, + DDR0_ADDRMAP_2); + writel(24 | 25 << 5 | 26 << 10 | 27 << 15 | 28 << 20 | 29 << 25, + DDR0_ADDRMAP_3); + writel(30 | 13 << 5 | 14 << 10 | 5 << 15 | 0 << 20 | 31 << 25, + DDR0_ADDRMAP_4); + + writel(6 | 7 << 5 | 8 << 10 | 9 << 15 | 10 << 20 | 11 << 25, + DDR1_ADDRMAP_0); + writel(12 | 0 << 5 | 0 << 10 | 15 << 15 | 16 << 20 | 17 << 25, + DDR1_ADDRMAP_1); + writel(18 | 19 << 5 | 20 << 10 | 21 << 15 | 22 << 20 | 23 << 25, + DDR1_ADDRMAP_2); + writel(24 | 25 << 5 | 26 << 10 | 27 << 15 | 28 << 20 | 29 << 25, + DDR1_ADDRMAP_3); + writel(30 | 13 << 5 | 14 << 10 | 5 << 15 | 0 << 20 | 31 << 25, + DDR1_ADDRMAP_4); + } else if (IS_ENABLED(CONFIG_DRAM_16BIT_RANK)) { + writel(0 | 6 << 5 | 7 << 10 | 8 << 15 | 9 << 20 | 10 << 25, + DDR0_ADDRMAP_0); + writel(11 | 0 << 5 | 0 << 10 | 14 << 15 | 15 << 20 | 16 << 25, + DDR0_ADDRMAP_1); + writel(17 | 18 << 5 | 19 << 10 | 20 << 15 | 21 << 20 | 22 << 25, + DDR0_ADDRMAP_2); + writel(23 | 24 << 5 | 25 << 10 | 26 << 15 | 27 << 20 | 28 << 25, + DDR0_ADDRMAP_3); + writel(29 | 12 << 5 | 13 << 10 | 5 << 15 | 0 << 20 | 30 << 25, + DDR0_ADDRMAP_4); + + writel(0 | 6 << 5 | 7 << 10 | 8 << 15 | 9 << 20 | 10 << 25, + DDR1_ADDRMAP_0); + writel(11 | 0 << 5 | 0 << 10 | 14 << 15 | 15 << 20 | 16 << 25, + DDR1_ADDRMAP_1); + writel(17 | 18 << 5 | 19 << 10 | 20 << 15 | 21 << 20 | 22 << 25, + DDR1_ADDRMAP_2); + writel(23 | 24 << 5 | 25 << 10 | 26 << 15 | 27 << 20 | 28 << 25, + DDR1_ADDRMAP_3); + writel(29 | 12 << 5 | 13 << 10 | 5 << 15 | 0 << 20 | 30 << 25, + DDR1_ADDRMAP_4); + } + } +} + +void meson_dram_dmc_init(void) +{ + u32 ddr_size_register = 0; + + printf("DMC version: 0x%x\n", readl(DMC_VERSION)); + + for (int i = CONFIG_DRAM_SIZE >> DMC_DRAM_SIZE_SHIFT; + !((i >>= 1) & 1); ddr_size_register++) + ; + + if (IS_ENABLED(CONFIG_DRAM_TWO_IDENTICAL_RANKS) || IS_ENABLED(CONFIG_DRAM_ONE_RANK)) + writel(DMC_CTRL | ddr_size_register | + (ddr_size_register << 3), + DMC_DDR_CTRL); + else + writel(DMC_CTRL | ddr_size_register | + (5 << 3), + DMC_DDR_CTRL); + + meson_dram_dmc_set_addrmap(); + + if (IS_ENABLED(CONFIG_MESON_GXBB)) { + writel(0x440620, DMC_PCTL_LP_CTRL); + writel(BIT(13) | BIT(5), DDR0_APD_CTRL); + writel(0x5, DDR0_CLK_CTRL); + + writel(0x11, DMC_AXI0_QOS_CTRL1); + } else if (IS_ENABLED(CONFIG_MESON_GXL)) { + writel(BIT(13), DDR0_APD_CTRL); + } + + writel(0x0, DMC_SEC_RANGE_CTRL); + writel(0x80000000, DMC_SEC_CTRL); + writel(0x55555555, DMC_SEC_AXI_PORT_CTRL); + writel(0x55555555, DMC_DEV_SEC_READ_CTRL); + writel(0x55555555, DMC_DEV_SEC_WRITE_CTRL); + writel(0x15, DMC_GE2D_SEC_CTRL); + writel(0x5, DMC_PARSER_SEC_CTRL); + DMC_ENABLE_REGION(DMC_VPU); + DMC_ENABLE_REGION(DMC_VDEC); + DMC_ENABLE_REGION(DMC_HCODEC); + DMC_ENABLE_REGION(DMC_HEVC); + + writel(0xffff, DMC_REQ_CTRL); + + dmb(); + isb(); + + debug("dram: memory controller init done\n"); +} + +int dram_init(void) +{ + uint ret; + + debug("SPL: initialising dram\n"); + + meson_dram_pll_init(); + meson_dram_phy_prepare(); + meson_dram_phy_init(); + meson_dram_prepare_pctl(); + meson_dram_set_memory_timings(); + meson_dram_set_dfi_timings(); + ret = meson_dram_phy_finalise_init(); + if (ret < 0) + return ret; + meson_dram_phy_setup_ranks(); + meson_dram_finalise_init(); + meson_dram_dmc_init(); + + /* Write size */ + clrsetbits_32(GX_SEC_AO_SEC_GP_CFG0, GX_AO_MEM_SIZE_MASK, + CONFIG_DRAM_SIZE << GX_AO_MEM_SIZE_SHIFT); + + debug("SPL: dram init done\n"); + + return 0; +} diff --git a/arch/arm/mach-meson/dram-gxbb.c b/arch/arm/mach-meson/dram-gxbb.c new file mode 100644 index 0000000000000000000000000000000000000000..9cfe3bac0711409234e93c53af389f3b44199bae --- /dev/null +++ b/arch/arm/mach-meson/dram-gxbb.c @@ -0,0 +1,174 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Portions Copyright (C) 2015, Amlogic, Inc. All rights reserved. + * Copyright (C) 2023-2025, Ferass El Hafidi <fundersc...@postmarketos.org> + */ +#include <init.h> +#include <asm/unaligned.h> +#include <linux/libfdt.h> +#include <config.h> +#include <errno.h> +#include <asm/io.h> +#include <asm/arch/dram-gx.h> +#include <asm/arch/gx.h> +#include <asm/arch/clock-gx.h> +#include <asm/arch/dram-settings-gx.h> +#include <linux/delay.h> + +/* Meson GXBB specific DRAM init */ + +void meson_dram_prepare_pctl(void) +{ + writel(PCTL0_1US_PCK, PCTL_TOGCNT1U); + writel(PCTL0_100NS_PCK, PCTL_TOGCNT100N); + writel(PCTL0_INIT_US, PCTL_TINIT); + writel(PCTL0_RSTH_US, PCTL_TRSTH); + + writel(PCTL0_MCFG | (CONFIG_DRAM_2T_MODE ? 8 : 0), + PCTL_MCFG); + writel(PCTL0_MCFG1, PCTL_MCFG1); + udelay(500); + + WAIT_FOR(PCTL_DFISTSTAT0); + + /* Ask the DRAM to kindly power on and wait until it is ready */ + writel(PCTL_POWCTL_POWERON, PCTL_POWCTL); + WAIT_FOR(PCTL_POWSTAT); +} + +void meson_dram_phy_init(void) +{ + /* Some unknown magic done by bl2 */ + writel(0x49494949, DDR0_PUB_IOVCR0); + writel(0x49494949, DDR0_PUB_IOVCR1); + + writel(PUB_ODTCR, DDR0_PUB_ODTCR); + + writel(PUB_MR0, DDR0_PUB_MR0); + writel(PUB_MR1, DDR0_PUB_MR1); + writel(PUB_MR2, DDR0_PUB_MR2); + writel(PUB_MR3, DDR0_PUB_MR3); + + /* Configure DRAM timing parameters (DTPR) */ + writel(PUB_DTPR0, DDR0_PUB_DTPR0); + writel(PUB_DTPR1, DDR0_PUB_DTPR1); + writel(PUB_PGCR1, DDR0_PUB_PGCR1); + writel(PUB_DTPR2, DDR0_PUB_DTPR2); + writel(PUB_DTPR3, DDR0_PUB_DTPR3); + + if (IS_ENABLED(CONFIG_DRAM_TWO_IDENTICAL_RANKS)) + writel(PUB_PGCR2 | (1 << 28), DDR0_PUB_PGCR2); + else + writel(PUB_PGCR2, DDR0_PUB_PGCR2); + + writel(PUB_PGCR3, DDR0_PUB_PGCR3); + writel(PUB_DXCCR, DDR0_PUB_DXCCR); + + writel(PUB_DTCR, DDR0_PUB_DTCR); + /* Wait for DLL lock */ + WAIT_FOR(DDR0_PUB_PGSR0); + + writel(0, DDR0_PUB_ACIOCR1); + writel(0, DDR0_PUB_ACIOCR2); + writel(0, DDR0_PUB_ACIOCR3); + writel(0, DDR0_PUB_ACIOCR4); + writel(0, DDR0_PUB_ACIOCR5); + + writel(0, DDR0_PUB_DX0GCR1); + writel(0, DDR0_PUB_DX0GCR2); + writel((1 << 10) | (2 << 12), DDR0_PUB_DX0GCR3); + writel(0, DDR0_PUB_DX1GCR1); + writel(0, DDR0_PUB_DX1GCR2); + writel((1 << 10) | (2 << 12), DDR0_PUB_DX1GCR3); + writel(0, DDR0_PUB_DX2GCR1); + writel(0, DDR0_PUB_DX2GCR2); + writel((1 << 10) | (2 << 12), DDR0_PUB_DX2GCR3); + writel(0, DDR0_PUB_DX3GCR1); + writel(0, DDR0_PUB_DX3GCR2); + writel((1 << 10) | (2 << 12), DDR0_PUB_DX3GCR3); + + writel(PUB_DCR, DDR0_PUB_DCR); + + writel(PUB_DTAR, DDR0_PUB_DTAR0); + writel(PUB_DTAR | 0x8, DDR0_PUB_DTAR1); + writel(PUB_DTAR | 0x10, DDR0_PUB_DTAR2); + writel(PUB_DTAR | 0x18, DDR0_PUB_DTAR3); + + writel(PUB_DSGCR, DDR0_PUB_DSGCR); + + /* Wait for the SDRAM to initialise */ + WAIT_FOR(DDR0_PUB_PGSR0); +} + +void meson_dram_phy_setup_ranks(void) +{ + if (IS_ENABLED(CONFIG_DRAM_ONE_RANK) || IS_ENABLED(CONFIG_DRAM_TWO_DIFF_RANKS)) { + uint i = 0, j = 0; + + writel((readl(DDR0_PUB_DX0LCDLR0) >> 8) | + (readl(DDR0_PUB_DX0LCDLR0) & 0xffffff00), + DDR0_PUB_DX0LCDLR0); + + i = ((readl(DDR0_PUB_DX2GTR) >> 3) & (7 << 0)); + j = ((readl(DDR0_PUB_DX2GTR) >> 14) & (3 << 0)); + writel(i | (i << 3) | (j << 12) | (j << 14), DDR0_PUB_DX2GTR); + + writel((readl(DDR0_PUB_DX2LCDLR2) >> 8) | + (readl(DDR0_PUB_DX2LCDLR2) & 0xffffff00), + DDR0_PUB_DX2LCDLR2); + + writel((readl(DDR0_PUB_DX3LCDLR0) >> 8) | + (readl(DDR0_PUB_DX3LCDLR0) & 0xffffff00), + DDR0_PUB_DX3LCDLR0); + + i = (readl(DDR0_PUB_DX3GTR) >> 3) & (7 << 0); + j = (readl(DDR0_PUB_DX3GTR) >> 14) & (3 << 0); + writel(i | (i << 3) | (j << 12) | (j << 14), DDR0_PUB_DX3GTR); + + writel((readl(DDR0_PUB_DX3LCDLR2) >> 8) | + (readl(DDR0_PUB_DX3LCDLR2) & 0xffffff00), + DDR0_PUB_DX3LCDLR2); + + writel((readl(DDR0_PUB_DX0LCDLR0) << 8) | + (readl(DDR0_PUB_DX0LCDLR0) & 0xffff00ff), + DDR0_PUB_DX0LCDLR0); + + i = (readl(DDR0_PUB_DX0GTR) << 0) & (7 << 0); + j = (readl(DDR0_PUB_DX0GTR) >> 12) & (3 << 0); + writel(i | (i << 3) | (j << 12) | (j << 14), DDR0_PUB_DX0GTR); + + writel((readl(DDR0_PUB_DX0LCDLR2) << 8) | + (readl(DDR0_PUB_DX0LCDLR2) & 0xffff00ff), + DDR0_PUB_DX0LCDLR2); + + writel((readl(DDR0_PUB_DX1LCDLR0) << 8) | + (readl(DDR0_PUB_DX1LCDLR0) & 0xffff00ff), + DDR0_PUB_DX1LCDLR0); + + i = (readl(DDR0_PUB_DX1GTR) << 0) & (7 << 0); + j = (readl(DDR0_PUB_DX1GTR) >> 12) & (3 << 0); + writel(i | (i << 3) | (j << 12) | (j << 14), DDR0_PUB_DX0GTR); + + writel((readl(DDR0_PUB_DX1LCDLR2) >> 8) | + (readl(DDR0_PUB_DX1LCDLR2) & 0xffffff00), + DDR0_PUB_DX1LCDLR2); + } + + writel((~(1 << 28)) & PUB_PGCR2, DDR0_PUB_PGCR2); + + if (IS_ENABLED(CONFIG_DRAM_2T_MODE) && (PUB_DCR & 7) == 3) + writel(0x1f, DDR0_PUB_ACLCDLR); +} + +void meson_dram_finalise_init(void) +{ + WAIT_FOR(PCTL_CMDTSTAT); + writel(PCTL_SCTL_GO_STATE, PCTL_SCTL); + + while (readl(PCTL_STAT) != PCTL_STAT_ACCESS) + ; + writel(0x880019d, DMC_REFR_CTRL1); + writel(0x20100000 | (CONFIG_DRAM_CLK / 20) | + (timings.refi << 8), DMC_REFR_CTRL2); + clrbits_32(DDR0_PUB_ZQCR, 4); +} diff --git a/arch/arm/mach-meson/dram-gxl.c b/arch/arm/mach-meson/dram-gxl.c new file mode 100644 index 0000000000000000000000000000000000000000..60c41632582abfa4238910c0c6cef8756253e3b5 --- /dev/null +++ b/arch/arm/mach-meson/dram-gxl.c @@ -0,0 +1,167 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Portions Copyright (C) 2015, Amlogic, Inc. All rights reserved. + * Copyright (C) 2023-2025, Ferass El Hafidi <fundersc...@postmarketos.org> + */ +#include <init.h> +#include <asm/unaligned.h> +#include <linux/libfdt.h> +#include <config.h> +#include <errno.h> +#include <asm/io.h> +#include <asm/arch/dram-gx.h> +#include <asm/arch/gx.h> +#include <asm/arch/clock-gx.h> +#include <asm/arch/dram-settings-gx.h> +#include <linux/delay.h> + +/* Meson GXL specific DRAM init */ + +void meson_dram_prepare_pctl(void) +{ + writel(CONFIG_DRAM_2T_MODE ? 8 : 0, PCTL_MCFG); + setbits_32(PCTL_MCFG, PCTL0_MCFG); + udelay(500); + + WAIT_FOR(PCTL_DFISTSTAT0); + + /* Enter config state */ + writel(PCTL0_SCFG, PCTL_SCFG); + writel(PCTL_SCTL_CFG_STATE, PCTL_SCTL); + WAIT_FOR(PCTL_STAT); + + writel(0x581, DDR0_PUB_PIR); + WAIT_FOR(DDR0_PUB_PGSR0); +} + +void meson_dram_phy_init(void) +{ + /* Some unknown magic done by bl2 */ + writel(0x190c3500, DDR0_PUB_PTR3); + writel(0x12c493e0, DDR0_PUB_PTR4); + + writel(0x1f090909, DDR0_PUB_IOVCR0); + writel(0x109, DDR0_PUB_IOVCR1); + + writel(0xe09093c, DDR0_PUB_DX0GCR4); + writel(0xe09093c, DDR0_PUB_DX1GCR4); + writel(0xe09093c, DDR0_PUB_DX2GCR4); + writel(0xe09093c, DDR0_PUB_DX3GCR4); + + writel(PUB_ODTCR, DDR0_PUB_ODTCR); + + writel(PUB_MR0, DDR0_PUB_MR0); + writel(PUB_MR1, DDR0_PUB_MR1); + writel(PUB_MR2, DDR0_PUB_MR2); + writel(PUB_MR3, DDR0_PUB_MR3); + writel(PUB_MR4, DDR0_PUB_MR4); + writel(PUB_MR5, DDR0_PUB_MR5); + writel(PUB_MR6, DDR0_PUB_MR6); + + /* Configure DRAM timing parameters (DTPR) */ + writel(timings.odt | (1 << 2), DDR0_PUB_MR11); + writel(PUB_DTPR0, DDR0_PUB_DTPR0); + writel(PUB_DTPR1, DDR0_PUB_DTPR1); + writel(PUB_DTPR2, DDR0_PUB_DTPR2); + writel(PUB_DTPR3, DDR0_PUB_DTPR3); + writel(PUB_DTPR4, DDR0_PUB_DTPR4); + writel(PUB_DTPR5, DDR0_PUB_DTPR5); + + if (IS_ENABLED(CONFIG_DRAM_TWO_IDENTICAL_RANKS)) + writel(PUB_PGCR2 | (1 << 28), DDR0_PUB_PGCR2); + else + writel(PUB_PGCR2, DDR0_PUB_PGCR2); + + writel(PUB_PGCR3, DDR0_PUB_PGCR3); + writel(PUB_DXCCR, DDR0_PUB_DXCCR); + + writel(PUB_DTCR, DDR0_PUB_DTCR); + writel(PUB_DTCR1, DDR0_PUB_DTCR1); + writel(PUB_PGCR1, DDR0_PUB_PGCR1); + + writel(0, DDR0_PUB_ACIOCR1); + writel(0, DDR0_PUB_ACIOCR2); + writel(0, DDR0_PUB_ACIOCR3); + writel(0, DDR0_PUB_ACIOCR4); + writel(0, DDR0_PUB_ACIOCR5); + + writel(0, DDR0_PUB_DX0GCR1); + writel(0, DDR0_PUB_DX0GCR2); + writel(0, DDR0_PUB_DX1GCR1); + writel(0, DDR0_PUB_DX1GCR2); + writel(0, DDR0_PUB_DX2GCR1); + writel(0, DDR0_PUB_DX2GCR2); + writel(0, DDR0_PUB_DX3GCR1); + writel(0, DDR0_PUB_DX3GCR2); + + if (IS_ENABLED(CONFIG_DRAM_16BIT_RANK)) { + writel(0, DDR0_PUB_DX2GCR0); + writel(0, DDR0_PUB_DX3GCR0); + } + writel(0x73, DDR0_PUB_PIR); + WAIT_FOR(DDR0_PUB_PGSR0); + + writel(PUB_DCR | (CONFIG_DRAM_2T_MODE ? 1 << 28 : 0), DDR0_PUB_DCR); + + writel(0xfc00172, DDR0_PUB_VTCR1); + + writel(PUB_DSGCR & ~(0x800004), DDR0_PUB_DSGCR); + + /* Wait for the SDRAM to initialise */ + WAIT_FOR(DDR0_PUB_PGSR0); +} + +void meson_dram_phy_setup_ranks(void) +{ + if (IS_ENABLED(CONFIG_DRAM_2T_MODE)) { + writel(0x3f003f, DDR0_PUB_ACBDLR2); + if (PUB_ACLCDLR <= 62) { + writel(((PUB_ACLCDLR - 24) + (readl(DDR0_PUB_ACMDLR0) & ~(0xe00))) | + (((PUB_ACLCDLR - 24) + (readl(DDR0_PUB_ACMDLR0) & ~(0xe00))) + * 0xffff), DDR0_PUB_ACBDLR2); + } + } + writel((PUB_ACLCDLR - 24) + (readl(DDR0_PUB_ACMDLR0) & ~(0xe00)), DDR0_PUB_ACLCDLR); + + if (IS_ENABLED(CONFIG_DRAM_DQS_CORR)) { + /* DQS correction stuff(?) */ + clrbits_32(DDR0_PUB_ACLCDLR, 0xe00); + if (!readl(DDR0_PUB_ACLCDLR)) + writel(1, DDR0_PUB_ACLCDLR); + + writel(readl(DDR0_PUB_ACLCDLR) & ~(0xe00), DDR0_PUB_ACLCDLR); + + clrbits_32(DDR0_PUB_ACBDLR0, 0xe00); + if (!readl(DDR0_PUB_ACBDLR0)) + writel(1, DDR0_PUB_ACBDLR0); + + writel(readl(DDR0_PUB_ACBDLR0) & ~(0xc0), DDR0_PUB_ACBDLR0); + + DQSCORR_DX(DDR0_PUB_DX0LCDLR0); + DQSCORR_DX(DDR0_PUB_DX1LCDLR0); + DQSCORR_DX(DDR0_PUB_DX2LCDLR0); + DQSCORR_DX(DDR0_PUB_DX3LCDLR0); + } +} + +void meson_dram_finalise_init(void) +{ + writel((0x3f << 12) | 0xf8, DDR0_PUB_PGCR6); + writel(PCTL_SCTL_GO_STATE, PCTL_SCTL); + while ((readl(PCTL_STAT) & 7) != PCTL_STAT_ACCESS) + ; + + writel(0xfffc << 16, DDR0_PUB_DX0GCR3); + writel(0xfffc << 16, DDR0_PUB_DX1GCR3); + writel(0xfffc << 16, DDR0_PUB_DX2GCR3); + writel(0xfffc << 16, DDR0_PUB_DX3GCR3); + + writel(0, DDR0_PUB_RANKIDR); + writel(PUB_DSGCR | 0x800004, DDR0_PUB_DSGCR); + + setbits_32(DDR0_PUB_ZQCR, 4); + writel(0x20100000 | ((CONFIG_DRAM_CLK / 20) - 1) | + (timings.refi << 8), DMC_REFR_CTRL2); + writel(0xf08f, DMC_REFR_CTRL1); +} + -- 2.51.0