Platform: Rockchip
OS: Android 6.0
Kernel: 3.10.92
系統重新開機過程可參考 [RK3399][Android6.0] 系統重新開機調用過程小結
而重新開機時android系統是支援帶參數重新開機的.
rk平台上定義的boot mode如下:
enum {
BOOT_NORMAL = , /* normal boot */
BOOT_LOADER, /* enter loader rockusb mode */
BOOT_MASKROM, /* enter maskrom rockusb mode (not support now) */
BOOT_RECOVER, /* enter recover */
BOOT_NORECOVER, /* do not enter recover */
BOOT_SECONDOS, /* boot second OS (not support now)*/
BOOT_WIPEDATA, /* enter recover and wipe data. */
BOOT_WIPEALL, /* enter recover and wipe all data. */
BOOT_CHECKIMG, /* check firmware img with backup part(in loader mode)*/
BOOT_FASTBOOT, /* enter fast boot mode */
BOOT_SECUREBOOT_DISABLE,
BOOT_CHARGING, /* enter charge mode */
BOOT_MAX /* MAX VALID BOOT TYPE.*/
};
而真正實作的隻有幾個常用的功能,通過rockchip_restart_get_boot_mode()來判斷是否支援.
void rockchip_restart_get_boot_mode(const char *cmd, u32 *flag, u32 *mode)
{
*flag = SYS_LOADER_REBOOT_FLAG + BOOT_NORMAL;
*mode = BOOT_MODE_REBOOT;
if (cmd) {
if (!strcmp(cmd, "loader") || !strcmp(cmd, "bootloader"))
*flag = SYS_LOADER_REBOOT_FLAG + BOOT_LOADER;
else if(!strcmp(cmd, "recovery"))
*flag = SYS_LOADER_REBOOT_FLAG + BOOT_RECOVER;
else if (!strcmp(cmd, "fastboot"))
*flag = SYS_LOADER_REBOOT_FLAG + BOOT_FASTBOOT;
else if (!strcmp(cmd, "charge")) {
*flag = SYS_LOADER_REBOOT_FLAG + BOOT_CHARGING;
*mode = BOOT_MODE_CHARGE;
}
} else {
if (is_panic)
*mode = BOOT_MODE_PANIC;
}
}
支援的boot flag被儲存在固定位置
#define SYS_LOADER_REBOOT_FLAG 0x5242C300 //high 24 bits is tag, low 8 bits is type
reboot之前通過rk3288_restart()寫到寄存器RK3288_PMU_SYS_REG0中.
static void rk3288_restart(char mode, const char *cmd)
{
u32 boot_flag, boot_mode;
rockchip_restart_get_boot_mode(cmd, &boot_flag, &boot_mode);
writel_relaxed(boot_flag, RK_PMU_VIRT + RK3288_PMU_SYS_REG0); // for loader
writel_relaxed(boot_mode, RK_PMU_VIRT + RK3288_PMU_SYS_REG1); // for linux
dsb();
/* pll enter slow mode */
writel_relaxed(xf3030000, RK_CRU_VIRT + RK3288_CRU_MODE_CON);
dsb();
writel_relaxed(xeca8, RK_CRU_VIRT + RK3288_CRU_GLB_SRST_SND_VALUE);
dsb();
}
reboot的時候在uboot中判斷boot flag
enum fbt_reboot_type board_fbt_get_reboot_type(void)
{
enum fbt_reboot_type frt = FASTBOOT_REBOOT_UNKNOWN;
uint32_t loader_flag = IReadLoaderFlag();
int reboot_mode = loader_flag ? (loader_flag & ) : BOOT_NORMAL;
/* Feedback reboot mode to the kernel. */
ISetLoaderFlag(SYS_KERNRL_REBOOT_FLAG | reboot_mode);
if (SYS_LOADER_ERR_FLAG == loader_flag) {
loader_flag = SYS_LOADER_REBOOT_FLAG | BOOT_LOADER;
reboot_mode = BOOT_LOADER;
}
if ((loader_flag & ) == SYS_LOADER_REBOOT_FLAG) {
switch (reboot_mode) {
case BOOT_NORMAL:
printf("reboot normal.\n");
frt = FASTBOOT_REBOOT_NORMAL;
break;
case BOOT_LOADER:
#ifdef CONFIG_CMD_ROCKUSB
printf("reboot rockusb.\n");
do_rockusb(NULL, , , NULL);
#endif
break;
#ifdef CONFIG_CMD_FASTBOOT
case BOOT_FASTBOOT:
printf("reboot fastboot.\n");
frt = FASTBOOT_REBOOT_FASTBOOT;
break;
#endif
case BOOT_NORECOVER:
printf("reboot no recover.\n");
frt = FASTBOOT_REBOOT_NORECOVER;
break;
case BOOT_RECOVER:
printf("reboot recover.\n");
frt = FASTBOOT_REBOOT_RECOVERY;
break;
case BOOT_WIPEDATA:
case BOOT_WIPEALL:
printf("reboot wipe data.\n");
frt = FASTBOOT_REBOOT_RECOVERY_WIPE_DATA;
break;
case BOOT_CHARGING:
printf("reboot charge.\n");
frt = FASTBOOT_REBOOT_CHARGE;
break;
default:
printf("unsupport reboot type %d\n", reboot_mode);
break;
}
} else {
printf("normal boot.\n");
}
......
return frt;
}