aboutsummaryrefslogtreecommitdiff
path: root/arch/arm/mach-sunxi/dram_timings
diff options
context:
space:
mode:
authorMikhail Kalashnikov2023-11-11 12:10:00 +0300
committerAndre Przywara2023-11-12 18:04:32 +0000
commit4b02f0120a4bb2a5d7081aef8cef6a4ca57e9db2 (patch)
treef7c5cfc88b43a7597d7be30d7651322d65ae0be2 /arch/arm/mach-sunxi/dram_timings
parentb71129ca3b469ccb22182c34d8cc05a742795582 (diff)
sunxi: H616: add LPDDR4 DRAM support
The H616 SoC family has support for several types of DRAM: DDR3, LPDDR3, DDR4 and LPDDR4. At the moment, the driver only supports DDR3 and LPDDR3 memory. Let's extend the driver to support the LPDDR4 memory. This type of memory widely used in device with T507(-H) SoC and new orangepi zero3 with H618. The compatibility with T507 is not yet complete, because there is difference in the phy_init array. The LPDDR4-2133 timings correspond to DRAM Rayson RS1G32LO4D2BDS-53BT found on the NOR SPI from the Orangepi Zero 3 4GB. Signed-off-by: Mikhail Kalashnikov <iuncuim@gmail.com> Tested-by: Piotr Oniszczuk <piotr.oniszczuk@gmail.com> Reviewed-by: Jernej Skrabec <jernej.skrabec@gmail.com> Acked-by: Andre Przywara <andre.przywara@arm.com>
Diffstat (limited to 'arch/arm/mach-sunxi/dram_timings')
-rw-r--r--arch/arm/mach-sunxi/dram_timings/Makefile1
-rw-r--r--arch/arm/mach-sunxi/dram_timings/h616_lpddr4_2133.c95
2 files changed, 96 insertions, 0 deletions
diff --git a/arch/arm/mach-sunxi/dram_timings/Makefile b/arch/arm/mach-sunxi/dram_timings/Makefile
index 8bfd99448a8..5f203419240 100644
--- a/arch/arm/mach-sunxi/dram_timings/Makefile
+++ b/arch/arm/mach-sunxi/dram_timings/Makefile
@@ -5,3 +5,4 @@ obj-$(CONFIG_SUNXI_DRAM_H6_LPDDR3) += h6_lpddr3.o
obj-$(CONFIG_SUNXI_DRAM_H6_DDR3_1333) += h6_ddr3_1333.o
obj-$(CONFIG_SUNXI_DRAM_H616_DDR3_1333) += h616_ddr3_1333.o
obj-$(CONFIG_SUNXI_DRAM_H616_LPDDR3) += h616_lpddr3.o
+obj-$(CONFIG_SUNXI_DRAM_H616_LPDDR4) += h616_lpddr4_2133.o
diff --git a/arch/arm/mach-sunxi/dram_timings/h616_lpddr4_2133.c b/arch/arm/mach-sunxi/dram_timings/h616_lpddr4_2133.c
new file mode 100644
index 00000000000..c11cb8678f6
--- /dev/null
+++ b/arch/arm/mach-sunxi/dram_timings/h616_lpddr4_2133.c
@@ -0,0 +1,95 @@
+/*
+ * sun50i H616 LPDDR4-2133 timings, as programmed by Allwinner's boot0
+ * for orangepi zero3 with the H618 and LPDDR4 memory.
+ *
+ * (C) Copyright 2023 Mikhail Kalashnikov <iuncuim@gmail.com>
+ * Based on H6 DDR3 timings:
+ * (C) Copyright 2020 Jernej Skrabec <jernej.skrabec@siol.net>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <asm/arch/dram.h>
+#include <asm/arch/cpu.h>
+
+void mctl_set_timing_params(const struct dram_para *para)
+{
+ struct sunxi_mctl_ctl_reg * const mctl_ctl =
+ (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
+
+ u8 tccd = 4;
+ u8 tfaw = ns_to_t(40);
+ u8 trrd = max(ns_to_t(10), 2);
+ u8 trcd = max(ns_to_t(18), 2);
+ u8 trc = ns_to_t(65);
+ u8 txp = max(ns_to_t(8), 2);
+ u8 trtp = max(ns_to_t(8), 4);
+ u8 trp = ns_to_t(21);
+ u8 tras = ns_to_t(42);
+ u16 trefi = ns_to_t(3904) / 32;
+ u16 trfc = ns_to_t(280);
+ u16 txsr = ns_to_t(190);
+
+ u8 tmrw = max(ns_to_t(14), 5);
+ u8 tmrd = tmrw;
+ u8 tmod = 12;
+ u8 tcke = max(ns_to_t(15), 2);
+ u8 tcksrx = max(ns_to_t(2), 2);
+ u8 tcksre = max(ns_to_t(5), 2);
+ u8 tckesr = tcke;
+ u8 trasmax = (trefi * 9) / 32;
+ u8 txs = 4;
+ u8 txsdll = 16;
+ u8 txsabort = 4;
+ u8 txsfast = 4;
+ u8 tcl = 10;
+ u8 tcwl = 5;
+ u8 t_rdata_en = 17;
+ u8 tphy_wrlat = 5;
+
+ u8 twtp = 24;
+ u8 twr2rd = max(trrd, (u8)4) + 14;
+ u8 trd2wr = (ns_to_t(4) + 17) - ns_to_t(1);
+
+ /* set DRAM timing */
+ writel((twtp << 24) | (tfaw << 16) | (trasmax << 8) | tras,
+ &mctl_ctl->dramtmg[0]);
+ writel((txp << 16) | (trtp << 8) | trc, &mctl_ctl->dramtmg[1]);
+ writel((tcwl << 24) | (tcl << 16) | (trd2wr << 8) | twr2rd,
+ &mctl_ctl->dramtmg[2]);
+ writel((tmrw << 20) | (tmrd << 12) | tmod, &mctl_ctl->dramtmg[3]);
+ writel((trcd << 24) | (tccd << 16) | (trrd << 8) | trp,
+ &mctl_ctl->dramtmg[4]);
+ writel((tcksrx << 24) | (tcksre << 16) | (tckesr << 8) | tcke,
+ &mctl_ctl->dramtmg[5]);
+ /* Value suggested by ZynqMP manual and used by libdram */
+ writel((txp + 2) | 0x02020000, &mctl_ctl->dramtmg[6]);
+ writel((txsfast << 24) | (txsabort << 16) | (txsdll << 8) | txs,
+ &mctl_ctl->dramtmg[8]);
+ writel(0x00020208, &mctl_ctl->dramtmg[9]);
+ writel(0xE0C05, &mctl_ctl->dramtmg[10]);
+ writel(0x440C021C, &mctl_ctl->dramtmg[11]);
+ writel(8, &mctl_ctl->dramtmg[12]);
+ writel(0xA100002, &mctl_ctl->dramtmg[13]);
+ writel(txsr, &mctl_ctl->dramtmg[14]);
+
+ clrsetbits_le32(&mctl_ctl->init[0], 0xC0000FFF, 0x3f0);
+ writel(0x01f20000, &mctl_ctl->init[1]);
+ writel(0x00000d05, &mctl_ctl->init[2]);
+ writel(0, &mctl_ctl->dfimisc);
+ writel(0x0034001b, &mctl_ctl->init[3]);
+ writel(0x00330000, &mctl_ctl->init[4]);
+ writel(0x00040072, &mctl_ctl->init[6]);
+ writel(0x00240009, &mctl_ctl->init[7]);
+
+ clrsetbits_le32(&mctl_ctl->rankctl, 0xff0, 0x660);
+
+ /* Configure DFI timing */
+ writel(tphy_wrlat | 0x2000000 | (t_rdata_en << 16) | 0x808000,
+ &mctl_ctl->dfitmg0);
+ writel(0x100202, &mctl_ctl->dfitmg1);
+
+ /* set refresh timing */
+ writel((trefi << 16) | trfc, &mctl_ctl->rfshtmg);
+}