[PATCH u-boot-marvell 3/3] arm: mvebu: turris_omnia: Switch DDR speed to 1333H when reset 9 is selected

Stefan Roese sr at denx.de
Tue Sep 3 09:06:29 CEST 2024


On 8/29/24 10:08, Marek Behún wrote:
> Users experiencing random kernel crashes due to new versions of
> Marvell's DDR training algorithm can solve the issue by setting DDR
> speed to 1333H.
> 
> But if kernel crashes, it has to be done in U-Boot, which is impossible
> without UART connection.
> 
> In order to make it easier for users, use the rescue button mechanism:
> when rescue mode 9 is selected (that is when 10 LEDs are ON), U-Boot
> will train DDR in 1333H mode and also update EEPROM so that subsequent
> boot will use this mode.
> 
> User has to use the `eeprom` command in U-Boot or `omnia-eeprom` command
> in OS to switch back to 1600K mode.
> 
> Signed-off-by: Marek Behún <kabel at kernel.org>
> ---
>   board/CZ.NIC/turris_omnia/turris_omnia.c | 90 ++++++++++++++++++++----
>   1 file changed, 77 insertions(+), 13 deletions(-)
> 
> diff --git a/board/CZ.NIC/turris_omnia/turris_omnia.c b/board/CZ.NIC/turris_omnia/turris_omnia.c
> index 46f20f05c05..eb88ee7f1ed 100644
> --- a/board/CZ.NIC/turris_omnia/turris_omnia.c
> +++ b/board/CZ.NIC/turris_omnia/turris_omnia.c
> @@ -47,6 +47,9 @@ DECLARE_GLOBAL_DATA_PTR;
>   #define OMNIA_I2C_EEPROM_CHIP_LEN	2
>   #define OMNIA_I2C_EEPROM_MAGIC		0x0341a034
>   
> +#define OMNIA_RESET_TO_LOWER_DDR_SPEED	9
> +#define OMNIA_LOWER_DDR_SPEED		"1333H"
> +
>   #define A385_SYS_RSTOUT_MASK		MVEBU_REGISTER(0x18260)
>   #define   A385_SYS_RSTOUT_MASK_WD	BIT(10)
>   
> @@ -206,6 +209,20 @@ static u32 omnia_mcu_crc32(const void *p, size_t len)
>   	return ~bitrev32(crc);
>   }
>   
> +static int omnia_mcu_get_reset(void)
> +{
> +	u8 reset_status;
> +	int ret;
> +
> +	ret = omnia_mcu_read(CMD_GET_RESET, &reset_status, 1);
> +	if (ret) {
> +		printf("omnia_mcu_read failed: %i, reset status unknown!\n", ret);
> +		return ret;
> +	}
> +
> +	return reset_status;
> +}
> +
>   /* Can only be called after relocation, since it needs cleared BSS */
>   static int omnia_mcu_board_info(char *serial, u8 *mac, char *version)
>   {
> @@ -463,14 +480,17 @@ static bool check_eeprom_crc(const void *buf, size_t size, u32 expected,
>   	return true;
>   }
>   
> +static struct udevice *omnia_get_eeprom(void)
> +{
> +	return omnia_get_i2c_chip("EEPROM", OMNIA_I2C_EEPROM_CHIP_ADDR,
> +				  OMNIA_I2C_EEPROM_CHIP_LEN);
> +}
> +
>   static bool omnia_read_eeprom(struct omnia_eeprom *oep)
>   {
> -	struct udevice *eeprom;
> +	struct udevice *eeprom = omnia_get_eeprom();
>   	int ret;
>   
> -	eeprom = omnia_get_i2c_chip("EEPROM", OMNIA_I2C_EEPROM_CHIP_ADDR,
> -				    OMNIA_I2C_EEPROM_CHIP_LEN);
> -
>   	if (!eeprom)
>   		return false;
>   
> @@ -502,6 +522,35 @@ static bool omnia_read_eeprom(struct omnia_eeprom *oep)
>   	return true;
>   }
>   
> +static void omnia_eeprom_set_lower_ddr_speed(void)
> +{
> +	struct udevice *eeprom = omnia_get_eeprom();
> +	struct omnia_eeprom oep;
> +	int ret;
> +
> +	if (!eeprom || !omnia_read_eeprom(&oep))
> +		return;
> +
> +	puts("Setting DDR speed to " OMNIA_LOWER_DDR_SPEED " in EEPROM as requested by reset button... ");
> +
> +	/* check if already set */
> +	if (!strncmp(oep.ddr_speed, OMNIA_LOWER_DDR_SPEED, sizeof(oep.ddr_speed)) &&
> +	    (oep.old_ddr_training == 0 || oep.old_ddr_training == 0xff)) {
> +		puts("was already set\n");
> +		return;
> +	}
> +
> +	strncpy(oep.ddr_speed, OMNIA_LOWER_DDR_SPEED, sizeof(oep.ddr_speed));
> +	oep.old_ddr_training = 0xff;
> +	oep.crc2 = crc32(0, (const void *)&oep, offsetof(struct omnia_eeprom, crc2));
> +
> +	ret = i2c_eeprom_write(eeprom, 0, (const void *)&oep, sizeof(oep));
> +	if (ret)
> +		printf("cannot write EEPROM: %d\n", ret);
> +	else
> +		puts("done\n");
> +}
> +
>   int omnia_get_ram_size_gb(void)
>   {
>   	static int ram_size;
> @@ -531,6 +580,13 @@ bool board_use_old_ddr3_training(void)
>   {
>   	struct omnia_eeprom oep;
>   
> +	/*
> +	 * If lower DDR speed is requested by reset button, we can't use old DDR
> +	 * training algorithm.
> +	 */
> +	if (omnia_mcu_get_reset() == OMNIA_RESET_TO_LOWER_DDR_SPEED)
> +		return false;
> +
>   	if (!omnia_read_eeprom(&oep))
>   		return false;
>   
> @@ -711,13 +767,19 @@ static void fixup_speed_in_ddr_topology(struct mv_ddr_topology_map *topology)
>   	const struct omnia_ddr_speed *setting;
>   	const char *speed;
>   	static bool done;
> +	int reset_status;
>   
>   	if (done)
>   		return;
>   
>   	done = true;
>   
> -	speed = omnia_get_ddr_speed();
> +	reset_status = omnia_mcu_get_reset();
> +	if (reset_status == OMNIA_RESET_TO_LOWER_DDR_SPEED)
> +		speed = OMNIA_LOWER_DDR_SPEED;
> +	else
> +		speed = omnia_get_ddr_speed();
> +
>   	if (!speed)
>   		return;
>   
> @@ -734,7 +796,10 @@ static void fixup_speed_in_ddr_topology(struct mv_ddr_topology_map *topology)
>   	if (params->speed_bin_index == setting->speed_bin)
>   		return;
>   
> -	printf("Fixing up DDR3 speed (EEPROM defines %s)\n", speed);
> +	if (reset_status == OMNIA_RESET_TO_LOWER_DDR_SPEED)
> +		printf("Fixing up DDR3 speed to %s as requested by reset button\n", speed);
> +	else
> +		printf("Fixing up DDR3 speed (EEPROM defines %s)\n", speed);
>   
>   	params->speed_bin_index = setting->speed_bin;
>   	params->memory_freq = setting->freq;
> @@ -771,8 +836,7 @@ static int set_regdomain(void)
>   static void handle_reset_button(void)
>   {
>   	const char * const vars[1] = { "bootcmd_rescue", };
> -	int ret;
> -	u8 reset_status;
> +	int reset_status;
>   
>   	/*
>   	 * Ensure that bootcmd_rescue has always stock value, so that running
> @@ -781,12 +845,12 @@ static void handle_reset_button(void)
>   	 */
>   	env_set_default_vars(1, (char * const *)vars, 0);
>   
> -	ret = omnia_mcu_read(CMD_GET_RESET, &reset_status, 1);
> -	if (ret) {
> -		printf("omnia_mcu_read failed: %i, reset status unknown!\n",
> -		       ret);
> +	reset_status = omnia_mcu_get_reset();
> +	if (reset_status < 0)
>   		return;
> -	}
> +
> +	if (reset_status == OMNIA_RESET_TO_LOWER_DDR_SPEED)
> +		return omnia_eeprom_set_lower_ddr_speed();
>   
>   	env_set_ulong("omnia_reset", reset_status);
>   

Reviewed-by: Stefan Roese <sr at denx.de>

Thanks,
Stefan


More information about the U-Boot mailing list