xaptum / xaptum-buildroot

External Buildroot tree for Xaptum hardware
GNU General Public License v2.0
0 stars 0 forks source link

Safe re-initialization of SDRAM in at91bootstrap #87

Closed drbild closed 5 years ago

drbild commented 5 years ago

The TPM provisioning firmware fails to boot on roughly half of the router cards tested so far. at91bootstrap and uboot usually succeed, but the Linux kernel boot fails at seemingly random spots for various reasons (invalid op codes, invalid memory accesses, etc.). Memory corruption is the likely culprit, given the random nature of the failures.

This corruption is caused by at91bootstrap re-initializing system clocks and SDRAM after we've already loaded the kernel image into RAM. That reinitialization briefly pauses or changes the SDRAM refresh clock generated by the CPU, so some cells lose their value.

The pause is short enough that only some cells are affected --- those at a bad corner PVT (process-voltage-temperature variation) corner in the CMOS. On some router cards, none of the affected cells are used, so the boot succeeds.

The Fix

The fix is to place the SDRAM into "self-refresh" mode while at91bootstrap is doing its clock and sdram reconfigurations. In this mode, the SDRAM provides its own internal refresh clock. It is intended for low power modes --- the CPU can go to sleep, the external clocks stopped, and the SDRAM will use an internal low power clock to refresh its contents. But we can (ab)use it here.

Add the following lines to the start of the hw_init function in contrib/board/xaptum/xaprc001/xaprc001.c.

»       /* set self-refresh DDR3 */
»       writel(AT91C_DDRC2_LPCB_SELFREFRESH, AT91C_BASE_MPDDRC + HDDRSDRC2_LPR);

And the following lines to the end of the same function

»       /* disable self-refresh DDR3 */
»       writel(AT91C_DDRC2_LPCB_DISABLED, AT91C_BASE_MPDDRC + HDDRSDRC2_LPR);

TODO

This means that at91bootstrap will be different for the provisioning and normal firmwares. I'm not sure the best to handle that.

1) Separate board files 2) Add our own config option to enable/disable these lines and use separate def_configs

dberliner commented 5 years ago

Closed by #89