[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