[U-Boot] rockchip: add support for backing to bootrom download mode

Dr. Philipp Tomsich philipp.tomsich at theobroma-systems.com
Wed Sep 13 09:17:54 UTC 2017


> On 13 Sep 2017, at 10:50, Dr. Philipp Tomsich <philipp.tomsich at theobroma-systems.com> wrote:
> 
> 
>> On 13 Sep 2017, at 10:36, Andy Yan <andy.yan at rock-chips.com> wrote:
>> 
>>>>> 
>>>>> If you just always save the boot_params and check the download flag later from C code, then you could have this implemented in C. This will remove the need to write two separate assembly functions (for AArch64 and AArch32) and generally be more readable. Please revise.
>>>> 
>>>>   We can't predict how many settings the TPL/SPL startup code changed now and future
>>>> will affect the bootrom download function, So back to bootrom download mode before
>>>> anything been changed is a simple way.
>>> 
>>> Ok. I’d still like to have this in C.
>>> The only requirement for this will be having a valid stack-pointer, so we should be able to do this early (before the various initialisation runs).
>>> I think board_init_f() would be a suitable place.
>> 
>> 
>>    When I hack this function first time, I indeed wrote a c implemented code in board_init_f on kylin-rk3036, but the usb failed connect to my PC
>> when back to bootrom, after a long time checking whit the bootrom code author, we found the interrupts related configurations are changed.
>> Then I try to save and restore the VBAR, then the bootrom download function works. But when I tested this function on rk3288 based board, it failed
>> again, and I found rk3288 bootrom require a different interrupt configuration with rk3036 after a long time dig, the interrupts vector base should be
>> 0xffff0000(other arm32 based boards are 0x0000), so the V bit of SCTLR should be set to 1, but the SPL startup code set it to zero.
>>    Then I have the idea back to bootrom download mode as early as possible when the download flag is set, Because no matter how many parameters 
>> I saved and restored today, no one can make sure that other parameters  will not changed by start.S in the future(maybe more properties changed about
>> the interrupt, maybe the change of mmu /caches, ), because we always have the chance to modify the startup code by the desire of new feature or the need
>> to workaround something for a new soc, what's more the start.S it's now have many #if / #else configuration, this still have risk to change the default configurations
>> which will be used in bootrom download mode. If we rely on a save and restore policy, this function may work well today, but may failed some days later just because 
>> some one changed another configuration in start.S. 
> 
> When looking at what happens (on armv7) between the save_boot_params
> and the call to _main (which in turn just sets up SP and calls into board_init_f),
> there isn’t much happening: it really is only cpu_init_cp15 and cpu_init_crit
> that will be of concern.
> I really wonder whether we could have a sufficient C runtime (i.e. SP valid)
> available before those run.
> 
> Does your BROM always call us with the SP valid (I know that that’s the case
> on the RK3399 and RK3368), so that we could run on the BROM’s stack here?

Just to explain my thinking here…
If we had a valid SP, we could mark our devices via Kconfig accordingly
by introducing a new config (e.g. $(SPL_TPL_)BROM_PERFORMS_C_CALL
for this) and then do something along these lines:

in start.S:
#if CONFIG_IS_ENABLED(BROM_PERFORMS_C_CALL)
	b brom_handoff_f
	.globl brom_handoff_f_ret
brom_handoff_f_ret:
#endif

and have a C file implementing the following (if setjmp/longjmp is not
yet implemented for AArch32 and AArch64, this will be a quick exercise):

/* The following is functionally identical to mach-rockchip/save_boot_param.S */
jmp_buf* brom_ctx = NULL;

enum {
	BROM_SETJMP_CONTINUE = 0
	BROM_RETURN_NORMAL = 1,
	BROM_RETURN_DNL = 2,
}

int brom_handoff_t(void)
{
	jmp_buf   saved_brom_ctx;
	int res ;

	res = setjmp(saved_brom_ctx);
	switch (res) {
	case BROM_SETJMP_CONTINUE:
		brom_ctx = &saved_brom_ctx;
		res = brom_handoff_f_ret();		/* needs a better name */
		break;

	case BROM_RETURN_NORMAL:
		res = 0;
		break;

	case BROM_RETURN_DNL:
		res = MAGIC_VALUE_TO_PASS_BACK;
		break;
	}

	return res;
}

void back_to_bootrom(void)
{
	longjmp(*brom_ctx, BROM_RETURN_NORMAL);
}


More information about the U-Boot mailing list