Platform: RK3399
OS: Android 7.1
Kernel: v4.4.83
背景:
到kernel 4.4上面,发现内核把重启参数通用驱动也实现了。
rk3288 android6.0 kernel3.10上rk是自己实现的。
文档说明:
针对通用reboot mode驱动,内核有文档解释:
Generic reboot mode core map driver
This driver get reboot mode arguments and call the write interface to stores the magic value in special register or ram . Then the bootloader can read it and take different action according the argument stored.
All mode properties are vendor specific, it is a indication to tell the bootloder what to do when the system reboot, and should be named as mode-xxx = <magic> (xxx is mode name).
- mode-normal: Normal reboot mode, system reboot with command "reboot".
- mode-recovery: Android Recovery mode, it is a mode to format the device or update a new image.
- mode-bootloader: Android fastboot mode, it's a mode to re-flash partitions on the Android based device.
- mode-loader: A bootloader mode, it's a mode used to download image on Rockchip platform, usually used in development.
大概意思就是:
1. reboot mode只提供驱动框架,具体写进去的参数和vendor对应平台相关,重启后会在uboot中判断。
2. 如果模式支持,只要在dts中加上mode-的选项就可以了。
rk3399平台驱动:
dts配置:
rk3399.dtsi:
reboot-mode {
compatible = "syscon-reboot-mode";
offset = <0x300>;
mode-bootloader = <BOOT_BL_DOWNLOAD>;
mode-charge = <BOOT_CHARGING>;
mode-fastboot = <BOOT_FASTBOOT>;
mode-loader = <BOOT_BL_DOWNLOAD>;
mode-normal = <BOOT_NORMAL>;
mode-recovery = <BOOT_RECOVERY>;
mode-ums = <BOOT_UMS>;
mode-wipedata = <BOOT_UMS>;
};
reboot mode注册:
syscon_reboot_mode_probe ->
reboot_mode_register ->
register_reboot_notifier -> //reboot_notifier的callback是reboot_mode_notify
blocking_notifier_chain_register //list是reboot_notifier_list
reboot调用:
当系统重启的时候会调用
kernel_restart ->
kernel_restart_prepare ->
blocking_notifier_call_chain ->
__blocking_notifier_call_chain ->
notifier_call_chain ->
nb->notifier_call -> //reboot_notifier_list被调用到
reboot_mode_notify -> reboot-mode.c
get_reboot_mode_magic -> //获取参数对应的magic
reboot->write ->
syscon_reboot_mode_write ->
regmap_update_bits //使用regmap mmio更新到寄存器中
重启开机判断是在uboot中完成的
static void fbt_handle_reboot(const char *cmdbuf)
{
if (!strcmp(&cmdbuf[6], "-bootloader")) {
FBTDBG("%s\n", cmdbuf);
board_fbt_set_reboot_type(FASTBOOT_REBOOT_BOOTLOADER);
}
if (!strcmp(&cmdbuf[6], "-recovery")) {
FBTDBG("%s\n", cmdbuf);
board_fbt_set_reboot_type(FASTBOOT_REBOOT_RECOVERY);
}
if (!strcmp(&cmdbuf[6], "-recovery:wipe_data")) {
FBTDBG("%s\n", cmdbuf);
board_fbt_set_reboot_type(FASTBOOT_REBOOT_RECOVERY_WIPE_DATA);
}
strcpy(priv.response, "OKAY");
priv.flag |= FASTBOOT_FLAG_RESPONSE;
fbt_handle_response();
udelay(1000000); /* 1 sec */
do_reset(NULL, 0, 0, NULL);
}