[U-Boot] [linux-sunxi] [PATCH v2 3/7] sunxi: H6: move LPDDR3 timing definition into separate file

Icenowy Zheng
2019-07-02T10:25:59Z

于 2019年7月2日 GMT+08:00 下午5:51:44, Andre Przywara <andre.przywara@arm.com> 写到:
>Currently the H6 DRAM driver only supports one kind of LPDDR3 DRAM.
>Split the timing parameters for LPDDR3-1333 into a separate file, to

I don't think it's 1333.

H6 memory controller says 800MHz maximum for LPDDR3 and 933
for DDR3/DDR4.

And currently we run at 744MHz on Pine H64.

>allow selecting an alternative later at compile time (as the sunxi-dw
>driver does).
>
>Signed-off-by: Andre Przywara <andre.przywara@arm.com>
>---
> .../include/asm/arch-sunxi/dram_sun50i_h6.h | 28 ++++
> arch/arm/mach-sunxi/Kconfig | 10 +-
> arch/arm/mach-sunxi/Makefile | 1 +
> arch/arm/mach-sunxi/dram_sun50i_h6.c | 150 +-----------------
> arch/arm/mach-sunxi/dram_timings/Makefile | 1 +
> .../mach-sunxi/dram_timings/h6_lpddr3_1333.c | 132 +++++++++++++++
> configs/orangepi_one_plus_defconfig | 1 +
> configs/pine_h64_defconfig | 1 +
> 8 files changed, 176 insertions(+), 148 deletions(-)
> create mode 100644 arch/arm/mach-sunxi/dram_timings/h6_lpddr3_1333.c
>
>diff --git a/arch/arm/include/asm/arch-sunxi/dram_sun50i_h6.h
>b/arch/arm/include/asm/arch-sunxi/dram_sun50i_h6.h
>index eeb4da5c3f..b28ae583c9 100644
>--- a/arch/arm/include/asm/arch-sunxi/dram_sun50i_h6.h
>+++ b/arch/arm/include/asm/arch-sunxi/dram_sun50i_h6.h
>@@ -287,6 +287,32 @@ check_member(sunxi_mctl_phy_reg,
>dx[3].reserved_0xf0, 0xaf0);
> #define DCR_DDR4 (4 << 0)
> #define DCR_DDR8BANK BIT(3)
>
>+
>+/*
>+ * The delay parameters below allow to allegedly specify delay times
>of some
>+ * unknown unit for each individual bit trace in each of the four data
>bytes
>+ * the 32-bit wide access consists of. Also three control signals can
>be
>+ * adjusted individually.
>+ */
>+#define NR_OF_BYTE_LANES (32 / BITS_PER_BYTE)
>+/* The eight data lines (DQn) plus DM, DQS, DQS/DM/DQ Output Enable
>and DQSN */
>+#define WR_LINES_PER_BYTE_LANE (BITS_PER_BYTE + 4)
>+/*
>+ * The eight data lines (DQn) plus DM, DQS, DQS/DM/DQ Output Enable,
>DQSN,
>+ * Termination and Power down
>+ */
>+#define RD_LINES_PER_BYTE_LANE (BITS_PER_BYTE + 6)
>+struct dram_para {
>+ u32 clk;
>+ enum sunxi_dram_type type;
>+ u8 cols;
>+ u8 rows;
>+ u8 ranks;
>+ const u8 dx_read_delays[NR_OF_BYTE_LANES][RD_LINES_PER_BYTE_LANE];
>+ const u8 dx_write_delays[NR_OF_BYTE_LANES][WR_LINES_PER_BYTE_LANE];
>+};
>+
>+
> static inline int ns_to_t(int nanoseconds)
> {
> const unsigned int ctrl_freq = CONFIG_DRAM_CLK / 2;
>@@ -294,4 +320,6 @@ static inline int ns_to_t(int nanoseconds)
> return DIV_ROUND_UP(ctrl_freq * nanoseconds, 1000);
> }
>
>+void mctl_set_timing_params(struct dram_para *para);
>+
> #endif /* _SUNXI_DRAM_SUN50I_H6_H */
>diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig
>index 1669e62a6d..e01cb6a09a 100644
>--- a/arch/arm/mach-sunxi/Kconfig
>+++ b/arch/arm/mach-sunxi/Kconfig
>@@ -340,7 +340,7 @@ config ARM_BOOT_HOOK_RMR
> This allows both the SPL and the U-Boot proper to be entered in
> either mode and switch to AArch64 if needed.
>
>-if SUNXI_DRAM_DW
>+if SUNXI_DRAM_DW || DRAM_SUN50I_H6
> config SUNXI_DRAM_DDR3
> bool
>
>@@ -370,6 +370,14 @@ config SUNXI_DRAM_LPDDR3_STOCK
> This option is the LPDDR3 timing used by the stock boot0 by
> Allwinner.
>
>+config SUNXI_DRAM_H6_LPDDR3
>+ bool "LPDDR3-1333 on the H6 DRAM controller"
>+ select SUNXI_DRAM_LPDDR3
>+ depends on DRAM_SUN50I_H6
>+ ---help---
>+ This option is the LPDDR3 timing used by the stock boot0 by
>+ Allwinner.
>+
> config SUNXI_DRAM_DDR2_V3S
> bool "DDR2 found in V3s chip"
> select SUNXI_DRAM_DDR2
>diff --git a/arch/arm/mach-sunxi/Makefile
>b/arch/arm/mach-sunxi/Makefile
>index 43a93e3085..d129f33479 100644
>--- a/arch/arm/mach-sunxi/Makefile
>+++ b/arch/arm/mach-sunxi/Makefile
>@@ -39,4 +39,5 @@ obj-$(CONFIG_SPL_SPI_SUNXI) += spl_spi_sunxi.o
> obj-$(CONFIG_SUNXI_DRAM_DW) += dram_sunxi_dw.o
> obj-$(CONFIG_SUNXI_DRAM_DW) += dram_timings/
> obj-$(CONFIG_DRAM_SUN50I_H6) += dram_sun50i_h6.o
>+obj-$(CONFIG_DRAM_SUN50I_H6) += dram_timings/
> endif
>diff --git a/arch/arm/mach-sunxi/dram_sun50i_h6.c
>b/arch/arm/mach-sunxi/dram_sun50i_h6.c
>index 7a8b724f08..697b8af4ce 100644
>--- a/arch/arm/mach-sunxi/dram_sun50i_h6.c
>+++ b/arch/arm/mach-sunxi/dram_sun50i_h6.c
>@@ -32,33 +32,8 @@
> * similar PHY is ZynqMP.
> */
>
>-/*
>- * The delay parameters below allow to allegedly specify delay times
>of some
>- * unknown unit for each individual bit trace in each of the four data
>bytes
>- * the 32-bit wide access consists of. Also three control signals can
>be
>- * adjusted individually.
>- */
>-#define NR_OF_BYTE_LANES (32 / BITS_PER_BYTE)
>-/* The eight data lines (DQn) plus DM, DQS, DQS/DM/DQ Output Enable
>and DQSN */
>-#define WR_LINES_PER_BYTE_LANE (BITS_PER_BYTE + 4)
>-/*
>- * The eight data lines (DQn) plus DM, DQS, DQS/DM/DQ Output Enable,
>DQSN,
>- * Termination and Power down
>- */
>-#define RD_LINES_PER_BYTE_LANE (BITS_PER_BYTE + 6)
>-struct dram_para {
>- u32 clk;
>- enum sunxi_dram_type type;
>- u8 cols;
>- u8 rows;
>- u8 ranks;
>- const u8 dx_read_delays[NR_OF_BYTE_LANES][RD_LINES_PER_BYTE_LANE];
>- const u8 dx_write_delays[NR_OF_BYTE_LANES][WR_LINES_PER_BYTE_LANE];
>-};
>-
> static void mctl_sys_init(struct dram_para *para);
> static void mctl_com_init(struct dram_para *para);
>-static void mctl_set_timing_lpddr3(struct dram_para *para);
> static void mctl_channel_init(struct dram_para *para);
>
> static void mctl_core_init(struct dram_para *para)
>@@ -67,7 +42,7 @@ static void mctl_core_init(struct dram_para *para)
> mctl_com_init(para);
> switch (para->type) {
> case SUNXI_DRAM_TYPE_LPDDR3:
>- mctl_set_timing_lpddr3(para);
>+ mctl_set_timing_params(para);
> break;
> default:
> panic("Unsupported DRAM type!");
>@@ -171,127 +146,6 @@ static void mctl_set_master_priority(void)
> MBUS_CONF(HDCP2, true, HIGH, 2, 100, 64, 32);
> }
>
>-static u32 mr_lpddr3[12] = {
>- 0x00000000, 0x00000043, 0x0000001a, 0x00000001,
>- 0x00000000, 0x00000000, 0x00000048, 0x00000000,
>- 0x00000000, 0x00000000, 0x00000000, 0x00000003,
>-};
>-
>-/* TODO: flexible timing */
>-static void mctl_set_timing_lpddr3(struct dram_para *para)
>-{
>- struct sunxi_mctl_ctl_reg * const mctl_ctl =
>- (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
>- struct sunxi_mctl_phy_reg * const mctl_phy =
>- (struct sunxi_mctl_phy_reg *)SUNXI_DRAM_PHY0_BASE;
>- int i;
>-
>- u8 tccd = 2;
>- u8 tfaw = max(ns_to_t(50), 4);
>- u8 trrd = max(ns_to_t(10), 2);
>- u8 trcd = max(ns_to_t(24), 2);
>- u8 trc = ns_to_t(70);
>- u8 txp = max(ns_to_t(8), 2);
>- u8 twtr = max(ns_to_t(8), 2);
>- u8 trtp = max(ns_to_t(8), 2);
>- u8 twr = max(ns_to_t(15), 2);
>- u8 trp = ns_to_t(18);
>- u8 tras = ns_to_t(42);
>- u8 twtr_sa = ns_to_t(5);
>- u8 tcksrea = ns_to_t(11);
>- u16 trefi = ns_to_t(3900) / 32;
>- u16 trfc = ns_to_t(210);
>- u16 txsr = ns_to_t(220);
>-
>- if (CONFIG_DRAM_CLK % 400 == 0) {
>- /* Round up these parameters */
>- twtr_sa++;
>- tcksrea++;
>- }
>-
>- u8 tmrw = 5;
>- u8 tmrd = 5;
>- u8 tmod = 12;
>- u8 tcke = 3;
>- u8 tcksrx = 5;
>- u8 tcksre = 5;
>- u8 tckesr = 5;
>- u8 trasmax = CONFIG_DRAM_CLK / 60;
>- u8 txs = 4;
>- u8 txsdll = 4;
>- u8 txsabort = 4;
>- u8 txsfast = 4;
>-
>- u8 tcl = 5; /* CL 10 */
>- u8 tcwl = 3; /* CWL 6 */
>- u8 t_rdata_en = twtr_sa + 8;
>-
>- u32 tdinit0 = (200 * CONFIG_DRAM_CLK) + 1; /* 200us */
>- u32 tdinit1 = (100 * CONFIG_DRAM_CLK) / 1000 + 1; /* 100ns */
>- u32 tdinit2 = (11 * CONFIG_DRAM_CLK) + 1; /* 11us */
>- u32 tdinit3 = (1 * CONFIG_DRAM_CLK) + 1; /* 1us */
>-
>- u8 twtp = tcwl + 4 + twr + 1;
>- /*
>- * The code below for twr2rd and trd2wr follows the IP core's
>- * document from ZynqMP and i.MX7. The BSP has both number
>- * substracted by 2.
>- */
>- u8 twr2rd = tcwl + 4 + 1 + twtr;
>- u8 trd2wr = tcl + 4 + (tcksrea >> 1) - tcwl + 1;
>-
>- /* set mode registers */
>- for (i = 0; i < ARRAY_SIZE(mr_lpddr3); i++)
>- writel(mr_lpddr3[i], &mctl_phy->mr[i]);
>-
>- /* 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(txsr, &mctl_ctl->dramtmg[14]);
>-
>- clrsetbits_le32(&mctl_ctl->init[0], (3 << 30), (1 << 30));
>- writel(0, &mctl_ctl->dfimisc);
>- clrsetbits_le32(&mctl_ctl->rankctl, 0xff0, 0x660);
>-
>- /*
>- * Set timing registers of the PHY.
>- * Note: the PHY is clocked 2x from the DRAM frequency.
>- */
>- writel((trrd << 25) | (tras << 17) | (trp << 9) | (trtp << 1),
>- &mctl_phy->dtpr[0]);
>- writel((tfaw << 17) | 0x28000400 | (tmrd << 1), &mctl_phy->dtpr[1]);
>- writel(((txs << 6) - 1) | (tcke << 17), &mctl_phy->dtpr[2]);
>- writel(((txsdll << 22) - (0x1 << 16)) | twtr_sa | (tcksrea << 8),
>- &mctl_phy->dtpr[3]);
>- writel((txp << 1) | (trfc << 17) | 0x800, &mctl_phy->dtpr[4]);
>- writel((trc << 17) | (trcd << 9) | (twtr << 1), &mctl_phy->dtpr[5]);
>- writel(0x0505, &mctl_phy->dtpr[6]);
>-
>- /* Configure DFI timing */
>- writel(tcl | 0x2000200 | (t_rdata_en << 16) | 0x808000,
>- &mctl_ctl->dfitmg0);
>- writel(0x040201, &mctl_ctl->dfitmg1);
>-
>- /* Configure PHY timing */
>- writel(tdinit0 | (tdinit1 << 20), &mctl_phy->ptr[3]);
>- writel(tdinit2 | (tdinit3 << 18), &mctl_phy->ptr[4]);
>-
>- /* set refresh timing */
>- writel((trefi << 16) | trfc, &mctl_ctl->rfshtmg);
>-}
>-
> static void mctl_sys_init(struct dram_para *para)
> {
> struct sunxi_ccm_reg * const ccm =
>@@ -735,12 +589,14 @@ unsigned long sunxi_dram_init(void)
> (struct sunxi_mctl_com_reg *)SUNXI_DRAM_COM_BASE;
> struct dram_para para = {
> .clk = CONFIG_DRAM_CLK,
>+#ifdef CONFIG_SUNXI_DRAM_H6_LPDDR3
> .type = SUNXI_DRAM_TYPE_LPDDR3,
> .ranks = 2,
> .cols = 11,
> .rows = 14,
> .dx_read_delays = SUN50I_H6_DX_READ_DELAYS,
> .dx_write_delays = SUN50I_H6_DX_WRITE_DELAYS,
>+#endif
> };
>
> unsigned long size;
>diff --git a/arch/arm/mach-sunxi/dram_timings/Makefile
>b/arch/arm/mach-sunxi/dram_timings/Makefile
>index 278a8a14cc..c3e74362eb 100644
>--- a/arch/arm/mach-sunxi/dram_timings/Makefile
>+++ b/arch/arm/mach-sunxi/dram_timings/Makefile
>@@ -1,3 +1,4 @@
> obj-$(CONFIG_SUNXI_DRAM_DDR3_1333) += ddr3_1333.o
> obj-$(CONFIG_SUNXI_DRAM_LPDDR3_STOCK) += lpddr3_stock.o
> obj-$(CONFIG_SUNXI_DRAM_DDR2_V3S) += ddr2_v3s.o
>+obj-$(CONFIG_SUNXI_DRAM_H6_LPDDR3) += h6_lpddr3_1333.o
>diff --git a/arch/arm/mach-sunxi/dram_timings/h6_lpddr3_1333.c
>b/arch/arm/mach-sunxi/dram_timings/h6_lpddr3_1333.c
>new file mode 100644
>index 0000000000..1000860113
>--- /dev/null
>+++ b/arch/arm/mach-sunxi/dram_timings/h6_lpddr3_1333.c
>@@ -0,0 +1,132 @@
>+/*
>+ * sun50i H6 LPDDR3 timings
>+ *
>+ * (C) Copyright 2017 Icenowy Zheng <icenowy@aosc.io>
>+ *
>+ * SPDX-License-Identifier: GPL-2.0+
>+ */
>+
>+#include <common.h>
>+#include <asm/arch/dram.h>
>+#include <asm/arch/cpu.h>
>+
>+static u32 mr_lpddr3[12] = {
>+ 0x00000000, 0x00000043, 0x0000001a, 0x00000001,
>+ 0x00000000, 0x00000000, 0x00000048, 0x00000000,
>+ 0x00000000, 0x00000000, 0x00000000, 0x00000003,
>+};
>+
>+/* TODO: flexible timing */
>+void mctl_set_timing_params(struct dram_para *para)
>+{
>+ struct sunxi_mctl_ctl_reg * const mctl_ctl =
>+ (struct sunxi_mctl_ctl_reg *)SUNXI_DRAM_CTL0_BASE;
>+ struct sunxi_mctl_phy_reg * const mctl_phy =
>+ (struct sunxi_mctl_phy_reg *)SUNXI_DRAM_PHY0_BASE;
>+ int i;
>+
>+ u8 tccd = 2;
>+ u8 tfaw = max(ns_to_t(50), 4);
>+ u8 trrd = max(ns_to_t(10), 2);
>+ u8 trcd = max(ns_to_t(24), 2);
>+ u8 trc = ns_to_t(70);
>+ u8 txp = max(ns_to_t(8), 2);
>+ u8 twtr = max(ns_to_t(8), 2);
>+ u8 trtp = max(ns_to_t(8), 2);
>+ u8 twr = max(ns_to_t(15), 2);
>+ u8 trp = ns_to_t(18);
>+ u8 tras = ns_to_t(42);
>+ u8 twtr_sa = ns_to_t(5);
>+ u8 tcksrea = ns_to_t(11);
>+ u16 trefi = ns_to_t(3900) / 32;
>+ u16 trfc = ns_to_t(210);
>+ u16 txsr = ns_to_t(220);
>+
>+ if (CONFIG_DRAM_CLK % 400 == 0) {
>+ /* Round up these parameters */
>+ twtr_sa++;
>+ tcksrea++;
>+ }
>+
>+ u8 tmrw = 5;
>+ u8 tmrd = 5;
>+ u8 tmod = 12;
>+ u8 tcke = 3;
>+ u8 tcksrx = 5;
>+ u8 tcksre = 5;
>+ u8 tckesr = 5;
>+ u8 trasmax = CONFIG_DRAM_CLK / 60;
>+ u8 txs = 4;
>+ u8 txsdll = 4;
>+ u8 txsabort = 4;
>+ u8 txsfast = 4;
>+
>+ u8 tcl = 5; /* CL 10 */
>+ u8 tcwl = 3; /* CWL 6 */
>+ u8 t_rdata_en = twtr_sa + 8;
>+
>+ u32 tdinit0 = (200 * CONFIG_DRAM_CLK) + 1; /* 200us */
>+ u32 tdinit1 = (100 * CONFIG_DRAM_CLK) / 1000 + 1; /* 100ns */
>+ u32 tdinit2 = (11 * CONFIG_DRAM_CLK) + 1; /* 11us */
>+ u32 tdinit3 = (1 * CONFIG_DRAM_CLK) + 1; /* 1us */
>+
>+ u8 twtp = tcwl + 4 + twr + 1;
>+ /*
>+ * The code below for twr2rd and trd2wr follows the IP core's
>+ * document from ZynqMP and i.MX7. The BSP has both number
>+ * substracted by 2.
>+ */
>+ u8 twr2rd = tcwl + 4 + 1 + twtr;
>+ u8 trd2wr = tcl + 4 + (tcksrea >> 1) - tcwl + 1;
>+
>+ /* set mode registers */
>+ for (i = 0; i < ARRAY_SIZE(mr_lpddr3); i++)
>+ writel(mr_lpddr3[i], &mctl_phy->mr[i]);
>+
>+ /* 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(txsr, &mctl_ctl->dramtmg[14]);
>+
>+ clrsetbits_le32(&mctl_ctl->init[0], (3 << 30), (1 << 30));
>+ writel(0, &mctl_ctl->dfimisc);
>+ clrsetbits_le32(&mctl_ctl->rankctl, 0xff0, 0x660);
>+
>+ /*
>+ * Set timing registers of the PHY.
>+ * Note: the PHY is clocked 2x from the DRAM frequency.
>+ */
>+ writel((trrd << 25) | (tras << 17) | (trp << 9) | (trtp << 1),
>+ &mctl_phy->dtpr[0]);
>+ writel((tfaw << 17) | 0x28000400 | (tmrd << 1), &mctl_phy->dtpr[1]);
>+ writel(((txs << 6) - 1) | (tcke << 17), &mctl_phy->dtpr[2]);
>+ writel(((txsdll << 22) - (0x1 << 16)) | twtr_sa | (tcksrea << 8),
>+ &mctl_phy->dtpr[3]);
>+ writel((txp << 1) | (trfc << 17) | 0x800, &mctl_phy->dtpr[4]);
>+ writel((trc << 17) | (trcd << 9) | (twtr << 1), &mctl_phy->dtpr[5]);
>+ writel(0x0505, &mctl_phy->dtpr[6]);
>+
>+ /* Configure DFI timing */
>+ writel(tcl | 0x2000200 | (t_rdata_en << 16) | 0x808000,
>+ &mctl_ctl->dfitmg0);
>+ writel(0x040201, &mctl_ctl->dfitmg1);
>+
>+ /* Configure PHY timing */
>+ writel(tdinit0 | (tdinit1 << 20), &mctl_phy->ptr[3]);
>+ writel(tdinit2 | (tdinit3 << 18), &mctl_phy->ptr[4]);
>+
>+ /* set refresh timing */
>+ writel((trefi << 16) | trfc, &mctl_ctl->rfshtmg);
>+}
>diff --git a/configs/orangepi_one_plus_defconfig
>b/configs/orangepi_one_plus_defconfig
>index 65537c422f..e4b9f3a1c8 100644
>--- a/configs/orangepi_one_plus_defconfig
>+++ b/configs/orangepi_one_plus_defconfig
>@@ -3,6 +3,7 @@ CONFIG_ARCH_SUNXI=y
> CONFIG_NR_DRAM_BANKS=1
> CONFIG_SPL=y
> CONFIG_MACH_SUN50I_H6=y
>+CONFIG_SUNXI_DRAM_H6_LPDDR3=y
> CONFIG_MMC0_CD_PIN="PF6"
> # CONFIG_PSCI_RESET is not set
> # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set
>diff --git a/configs/pine_h64_defconfig b/configs/pine_h64_defconfig
>index 5ac89b462c..d88a6b1fd8 100644
>--- a/configs/pine_h64_defconfig
>+++ b/configs/pine_h64_defconfig
>@@ -3,6 +3,7 @@ CONFIG_ARCH_SUNXI=y
> CONFIG_NR_DRAM_BANKS=1
> CONFIG_SPL=y
> CONFIG_MACH_SUN50I_H6=y
>+CONFIG_SUNXI_DRAM_H6_LPDDR3=y
> CONFIG_MMC0_CD_PIN="PF6"
> CONFIG_MMC_SUNXI_SLOT_EXTRA=2
> # CONFIG_PSCI_RESET is not set

--
使用 K-9 Mail 发送自我的Android设备。