mirror of
https://github.com/u-boot/u-boot.git
synced 2025-04-25 23:06:15 +00:00

Import DDR training code from commit 1b69ce2fc0
("arm: mvebu:
ddr3_debug: remove self assignments") into
drivers/ddr/marvell/a38x/old/. The code is not used yet.
Explanation:
Since 2019, on some Turris Omnia boards we have been having problems
with newer versions of Marvell's DDR3 training code for Armada 38x,
which is ported from mv-ddr-marvell [1] to U-Boot into the
drivers/ddr/marvell/a38x/ directory:
- sometimes the DDR3 training fails on some older boards, sometime it
fails on some newer boards
- other times it succeeds, but some boards experience crashes of the
operating system after running for some time.
Using the stock version of Turris Omnia's U-Boot from solved these
issues, but this solution was not satisfactory, since we wanted
features from new U-Boot.
Back in 2020-2022 we have spent several months trying to debug the
issues, working with Marvell, on our own, and also with U-Boot
community, but these issues persist still.
One solution we used back in 2019 was a "hybrid U-Boot": the SPL part
(containing the DDR3 training code) was taken from the stock version,
while the proper part was current U-Boot at the time. This solution also
has its drawbacks, of which the main one is the need to glue binaries
from two separate builds.
Since then there have been some more changes to the DDR3 training code
in upstream mv-ddr-marvell that have been ported to U-Boot. We have
provided our users experimental builds of U-Boot in the TurrisOS so that
they could try upgrading the firmware and let us know if those problems
still exist. And they do.
We do not have the time nor manpower to debug this problem and fix it
properly. Marvell was also no able to provide a solution to this,
probably because they do not have the manpower as well.
I have therefore come up with this "not that pretty" solution: take the
DDR3 training code from an older version of U-Boot that is known to
work, put it into current U-Boot under old/ subdirectory within
drivers/ddr/marvell/a38x/, build into the SPL binary both the old and
new versions and make it possible to select the old version via an env
variable.
[1] https://github.com/MarvellEmbeddedProcessors/mv-ddr-marvell
Signed-off-by: Marek Behún <kabel@kernel.org>
92 lines
2.7 KiB
C
92 lines
2.7 KiB
C
/*
|
|
* Copyright (C) Marvell International Ltd. and its affiliates
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0
|
|
*/
|
|
|
|
#ifndef _XOR_H
|
|
#define _XOR_H
|
|
|
|
#define SRAM_BASE 0x40000000
|
|
|
|
#include "ddr3_hws_hw_training_def.h"
|
|
|
|
#define MV_XOR_MAX_UNIT 2 /* XOR unit == XOR engine */
|
|
#define MV_XOR_MAX_CHAN 4 /* total channels for all units */
|
|
#define MV_XOR_MAX_CHAN_PER_UNIT 2 /* channels for units */
|
|
|
|
#define MV_IS_POWER_OF_2(num) (((num) != 0) && (((num) & ((num) - 1)) == 0))
|
|
|
|
/*
|
|
* This structure describes address space window. Window base can be
|
|
* 64 bit, window size up to 4GB
|
|
*/
|
|
struct addr_win {
|
|
u32 base_low; /* 32bit base low */
|
|
u32 base_high; /* 32bit base high */
|
|
u32 size; /* 32bit size */
|
|
};
|
|
|
|
/* This structure describes SoC units address decode window */
|
|
struct unit_win_info {
|
|
struct addr_win addr_win; /* An address window */
|
|
int enable; /* Address decode window is enabled/disabled */
|
|
u8 attrib; /* chip select attributes */
|
|
u8 target_id; /* Target Id of this MV_TARGET */
|
|
};
|
|
|
|
/*
|
|
* This enumerator describes the type of functionality the XOR channel
|
|
* can have while using the same data structures.
|
|
*/
|
|
enum xor_type {
|
|
MV_XOR, /* XOR channel functions as XOR accelerator */
|
|
MV_DMA, /* XOR channel functions as IDMA channel */
|
|
MV_CRC32 /* XOR channel functions as CRC 32 calculator */
|
|
};
|
|
|
|
enum mv_state {
|
|
MV_IDLE,
|
|
MV_ACTIVE,
|
|
MV_PAUSED,
|
|
MV_UNDEFINED_STATE
|
|
};
|
|
|
|
/*
|
|
* This enumerator describes the set of commands that can be applied on
|
|
* an engine (e.g. IDMA, XOR). Appling a comman depends on the current
|
|
* status (see MV_STATE enumerator)
|
|
*
|
|
* Start can be applied only when status is IDLE
|
|
* Stop can be applied only when status is IDLE, ACTIVE or PAUSED
|
|
* Pause can be applied only when status is ACTIVE
|
|
* Restart can be applied only when status is PAUSED
|
|
*/
|
|
enum mv_command {
|
|
MV_START, /* Start */
|
|
MV_STOP, /* Stop */
|
|
MV_PAUSE, /* Pause */
|
|
MV_RESTART /* Restart */
|
|
};
|
|
|
|
enum xor_override_target {
|
|
SRC_ADDR0, /* Source Address #0 Control */
|
|
SRC_ADDR1, /* Source Address #1 Control */
|
|
SRC_ADDR2, /* Source Address #2 Control */
|
|
SRC_ADDR3, /* Source Address #3 Control */
|
|
SRC_ADDR4, /* Source Address #4 Control */
|
|
SRC_ADDR5, /* Source Address #5 Control */
|
|
SRC_ADDR6, /* Source Address #6 Control */
|
|
SRC_ADDR7, /* Source Address #7 Control */
|
|
XOR_DST_ADDR, /* Destination Address Control */
|
|
XOR_NEXT_DESC /* Next Descriptor Address Control */
|
|
};
|
|
|
|
enum mv_state mv_xor_state_get(u32 chan);
|
|
void mv_xor_hal_init(u32 xor_chan_num);
|
|
int mv_xor_ctrl_set(u32 chan, u32 xor_ctrl);
|
|
int mv_xor_command_set(u32 chan, enum mv_command command);
|
|
int mv_xor_override_set(u32 chan, enum xor_override_target target, u32 win_num,
|
|
int enable);
|
|
|
|
#endif
|