9da1459a7d292e42f77bd8f50f6fcfc9e16a8539
[openwrt/openwrt.git] / package / boot / uboot-mvebu / patches / 011-ddr-marvell-a38x-fix-synchronous-asynchronous-mode.patch
1 From eadc4f512fb43bba2fa4e842c982da919da664be Mon Sep 17 00:00:00 2001
2 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= <marek.behun@nic.cz>
3 Date: Tue, 4 Jan 2022 15:57:49 +0100
4 Subject: [PATCH] ddr: marvell: a38x: Fix Synchronous vs Asynchronous mode
5 determination
6 MIME-Version: 1.0
7 Content-Type: text/plain; charset=UTF-8
8 Content-Transfer-Encoding: 8bit
9
10 Before commit 4c289425752f ("mv_ddr: a38x: add support for ddr async
11 mode"), Asynchornous Mode was only used when the CPU Subsystem Clock
12 Options[4:0] field in the SAR1 register was set to value 0x13: CPU at
13 2 GHz and DDR at 933 MHz.
14
15 Then commit 4c289425752f ("mv_ddr: a38x: add support for ddr async
16 mode") added support for Asynchornous Modes with frequencies other than
17 933 MHz (but at least 467 MHz), but the code it added to check for
18 whether Asynchornous Mode should be used is wrong: it checks whether the
19 frequency setting in board DDR topology map is set to value other than
20 MV_DDR_FREQ_SAR.
21
22 Thus boards which define a specific value, greater than 400 MHz, for DDR
23 frequency in their board topology (e.g. Turris Omnia defines
24 MV_DDR_FREQ_800), are incorrectly put into Asynchornous Mode after that
25 commit.
26
27 The A38x Functional Specification, section 10.12 DRAM Clocking, says:
28 In Synchornous mode, the DRAM and CPU clocks are edge aligned and run
29 in 1:2 or 1:3 CPU to DRAM frequency ratios.
30
31 Change the check for whether Asynchornous Mode should be used according
32 to this explanation in Functional Specification.
33
34 Signed-off-by: Marek BehĂșn <marek.behun@nic.cz>
35 Tested-by: Chris Packham <judge.packham@gmail.com>
36 Reviewed-by: Stefan Roese <sr@denx.de>
37 ---
38 drivers/ddr/marvell/a38x/mv_ddr_plat.c | 19 ++++++++-----------
39 1 file changed, 8 insertions(+), 11 deletions(-)
40
41 --- a/drivers/ddr/marvell/a38x/mv_ddr_plat.c
42 +++ b/drivers/ddr/marvell/a38x/mv_ddr_plat.c
43 @@ -167,8 +167,6 @@ static u16 a38x_vco_freq_per_sar_ref_clk
44 };
45
46
47 -static u32 async_mode_at_tf;
48 -
49 static u32 dq_bit_map_2_phy_pin[] = {
50 1, 0, 2, 6, 9, 8, 3, 7, /* 0 */
51 8, 9, 1, 7, 2, 6, 3, 0, /* 1 */
52 @@ -734,7 +732,8 @@ static int ddr3_tip_a38x_set_divider(u8
53 u32 divider = 0;
54 u32 sar_val, ref_clk_satr;
55 u32 async_val;
56 - u32 freq = mv_ddr_freq_get(frequency);
57 + u32 cpu_freq;
58 + u32 ddr_freq = mv_ddr_freq_get(frequency);
59
60 if (if_id != 0) {
61 DEBUG_TRAINING_ACCESS(DEBUG_LEVEL_ERROR,
62 @@ -751,11 +750,14 @@ static int ddr3_tip_a38x_set_divider(u8
63 ref_clk_satr = reg_read(DEVICE_SAMPLE_AT_RESET2_REG);
64 if (((ref_clk_satr >> DEVICE_SAMPLE_AT_RESET2_REG_REFCLK_OFFSET) & 0x1) ==
65 DEVICE_SAMPLE_AT_RESET2_REG_REFCLK_25MHZ)
66 - divider = a38x_vco_freq_per_sar_ref_clk_25_mhz[sar_val] / freq;
67 + cpu_freq = a38x_vco_freq_per_sar_ref_clk_25_mhz[sar_val];
68 else
69 - divider = a38x_vco_freq_per_sar_ref_clk_40_mhz[sar_val] / freq;
70 + cpu_freq = a38x_vco_freq_per_sar_ref_clk_40_mhz[sar_val];
71 +
72 + divider = cpu_freq / ddr_freq;
73
74 - if ((async_mode_at_tf == 1) && (freq > 400)) {
75 + if (((cpu_freq % ddr_freq != 0) || (divider != 2 && divider != 3)) &&
76 + (ddr_freq > 400)) {
77 /* Set async mode */
78 dunit_write(0x20220, 0x1000, 0x1000);
79 dunit_write(0xe42f4, 0x200, 0x200);
80 @@ -869,8 +871,6 @@ int ddr3_tip_ext_write(u32 dev_num, u32
81
82 int mv_ddr_early_init(void)
83 {
84 - struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
85 -
86 /* FIXME: change this configuration per ddr type
87 * configure a380 and a390 to work with receiver odt timing
88 * the odt_config is defined:
89 @@ -882,9 +882,6 @@ int mv_ddr_early_init(void)
90
91 mv_ddr_sw_db_init(0, 0);
92
93 - if (tm->interface_params[0].memory_freq != MV_DDR_FREQ_SAR)
94 - async_mode_at_tf = 1;
95 -
96 return MV_OK;
97 }
98