Commit c3cbc146 authored by Marek Behun's avatar Marek Behun

arm: mvebu: turris_omnia: user RAM freq 667 MHz if failed at 800 MHz

For some unknown reasons some boards with four 512 MiB RAM chips
(= 2 GiB RAM) sometimes fail to train correctly at 800 MHz with the new
DDR training algorithm. Use the EEPROM to count how many times the
training failed and if the training failed more than 3 times, train at
667 MHz.
Signed-off-by: Marek Behun's avatarMarek Behún <marek.behun@nic.cz>
parent e5ff53d1
......@@ -123,7 +123,11 @@ void board_init_f(ulong dummy)
serdes_phy_config();
/* Setup DDR */
ddr3_init();
if (ddr3_init()) {
bool omnia_ram_fails_inc(void);
omnia_ram_fails_inc();
reset_cpu(0);
}
#endif
/* Initialize Auto Voltage Scaling */
......
......@@ -232,6 +232,64 @@ static bool omnia_read_eeprom(struct omnia_eeprom *oep)
return true;
}
static int omnia_ram_fails(void)
{
struct udevice *chip;
u8 fails;
int ret;
chip = omnia_get_i2c_chip("EEPROM", OMNIA_I2C_EEPROM_CHIP_ADDR,
OMNIA_I2C_EEPROM_CHIP_LEN);
if (!chip)
return -1;
ret = dm_i2c_read(chip, 0x1000, (void *)&fails, sizeof(fails));
if (ret) {
printf("dm_i2c_read failed: %i, cannot read EEPROM\n", ret);
return -1;
}
if (fails == 0xff)
fails = 0;
return fails;
}
bool omnia_ram_fails_inc(void)
{
struct udevice *chip;
u8 fails;
int ret;
chip = omnia_get_i2c_chip("EEPROM", OMNIA_I2C_EEPROM_CHIP_ADDR,
OMNIA_I2C_EEPROM_CHIP_LEN);
if (!chip)
return false;
ret = dm_i2c_read(chip, 0x1000, (void *)&fails, sizeof(fails));
if (ret) {
printf("dm_i2c_read failed: %i, cannot read EEPROM\n", ret);
return false;
}
if (fails == 0xff)
fails = 0;
++fails;
ret = dm_i2c_write(chip, 0x10, (void *)&fails, sizeof(fails));
if (ret) {
printf("dm_i2c_write failed: %i, cannot write EEPROM\n", ret);
return false;
}
if (fails > 3)
printf("RAM training failed 3 times, from now on try 667 MHz");
return true;
}
static int omnia_get_ram_size_gb(void)
{
static int ram_size;
......@@ -306,12 +364,52 @@ static struct mv_ddr_topology_map board_topology_map_2g = {
{0} /* timing parameters */
};
static struct mv_ddr_topology_map board_topology_map_2g_1333F = {
DEBUG_LEVEL_ERROR,
0x1, /* active interfaces */
/* cs_mask, mirror, dqs_swap, ck_swap X PUPs */
{ { { {0x1, 0, 0, 0},
{0x1, 0, 0, 0},
{0x1, 0, 0, 0},
{0x1, 0, 0, 0},
{0x1, 0, 0, 0} },
SPEED_BIN_DDR_1333F, /* speed_bin */
MV_DDR_DEV_WIDTH_16BIT, /* memory_width */
MV_DDR_DIE_CAP_8GBIT, /* mem_size */
MV_DDR_FREQ_667, /* frequency */
0, 0, /* cas_wl cas_l */
MV_DDR_TEMP_NORMAL, /* temperature */
MV_DDR_TIM_2T} }, /* timing */
BUS_MASK_32BIT, /* Busses mask */
MV_DDR_CFG_DEFAULT, /* ddr configuration data source */
{ {0} }, /* raw spd data */
{0} /* timing parameters */
};
struct mv_ddr_topology_map *mv_ddr_topology_map_get(void)
{
if (omnia_get_ram_size_gb() == 2)
return &board_topology_map_2g;
else
return &board_topology_map_1g;
static struct mv_ddr_topology_map *result;
/*
* drivers/ddr/marvell/a38x training code calls this functions many
* times, we therefore cache the result
*/
if (result)
return result;
if (omnia_get_ram_size_gb() == 2) {
int fails;
fails = omnia_ram_fails();
if (fails > 3)
result = &board_topology_map_2g_1333F;
else
result = &board_topology_map_2g;
} else {
result = &board_topology_map_1g;
}
return result;
}
#ifndef CONFIG_SPL_BUILD
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment