一、boot_mode boot_reason 枚举定义 preloader、LK相同
typedef enum {
NORMAL_BOOT = 0,
META_BOOT = 1,
RECOVERY_BOOT = 2,
SW_REBOOT = 3,
FACTORY_BOOT = 4,
ADVMETA_BOOT = 5,
ATE_FACTORY_BOOT = 6,
ALARM_BOOT = 7,
FASTBOOT = 99,
DOWNLOAD_BOOT = 100,
UNKNOWN_BOOT
} boot_mode_t;
typedef enum {
BR_POWER_KEY = 0,
BR_USB,
BR_RTC,
BR_WDT,
BR_WDT_BY_PASS_PWK,
BR_TOOL_BY_PASS_PWK,
BR_2SEC_REBOOT,
BR_UNKNOWN,
BR_KERNEL_PANIC,
BR_WDT_SW,
BR_WDT_HW,
BR_POWER_EXC = 30,
BR_LONG_POWKEY,
BR_POWER_LOSS,
BR_REBOOT_EXCEPTION
} boot_reason_t;
二、preloader usb 转串口功能,charger BC12功能,meta功能
mt6768 preloader 从main.c 入口
void main(u32 *arg)
bldr_pre_process();
//重要功能初始化 gpio rtc 内存,总线,uart 等
platform_pre_init();
/*GPIO init*/
mt_gpio_init();
//print rtc time
rtc_get_time(&tm);
pal_log_info("Current RTC time:[%d/%d/%d %d:%d:%d]\n", tm.tm_year, tm.tm_mon, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
//i2c hw init
i2c_hw_init();
BOOTING_TIME_PROFILING_LOG("I2C");
//connsys init
connsys_init();
BOOTING_TIME_PROFILING_LOG("Connsys");
//enable_devinfo_dcm
enable_devinfo_dcm();
//show ic debug information
show_devinfo_debug_info();
BOOTING_TIME_PROFILING_LOG("DEVINFO");
ret = boot_device_init();
BOOTING_TIME_PROFILING_LOG("Boot dev init");
pal_log_err("%s Init Boot Device: %s(%d)\n", MOD, ret ? "FAIL" : "OK", ret);
pal_log_info("%s Init PMIC: %s(%d)\n", MOD, pmic_ret ? "FAIL" : "OK", pmic_ret);
pal_log_info("%s chip_ver[%x]\n", MOD, mt_get_chip_sw_ver());
pal_log_info("\n%s Build Time: %s\n", MOD, BUILD_TIME);
//其他功能,逻辑判断及处理相关
platform_init();
g_boot_reason = reason = platform_boot_status();
u32 pmic_reboot = get_pmic_boot_status();
if (pmic_reboot == 1) {
pal_log_err("%s pmic: power exception(OC/PG)!\n", MOD);
rtc_mark_bypass_pwrkey();
return BR_POWER_EXC;
} else if (pmic_reboot == 2) { //长按power键开机
pal_log_err("%s pmic: long power key press reboot!\n", MOD);
rtc_mark_bypass_pwrkey();
return BR_LONG_POWKEY;
BOOTING_TIME_PROFILING_LOG("check Boot status");
if(drdi_get_hw_ver() == HW_VER_V1) {
if (usb_accessory_in()) {
pal_log_err("%s USB/charger boot!\n", MOD);
BOOTING_TIME_PROFILING_LOG("check Boot status-usb_accessory_in");
return BR_USB;
}
//check after rtc_boot_check() initial finish.
if (rtc_2sec_reboot_check()) {
pal_log_err("%s 2sec reboot!\n", MOD);
BOOTING_TIME_PROFILING_LOG("check Boot status-rtc_2sec_reboot_check");
return BR_2SEC_REBOOT;
}
handler.priv = NULL;
handler.attr = 0;
handler.cb = bldr_cmd_handler;
BOOTING_TIME_PROFILING_LOG("before bldr_handshake");
bldr_handshake(&handler);
switch (mode) {
case NORMAL_BOOT:
if (TRUE == usb_handshake(handler))
if (TRUE == force_download) {
enum_tmo = 0;
handshake_tmo = 0;
usb_cable_in();
// 判断
} else if (!usb_cable_in()) {
usb_cable_in
1、先PMIC 检测USB 线是否在位
pal_log_info("\n[USB] MDCIRQ 0x10000280 before: %x\n", DRV_Reg32(0x10000280));
DRV_WriteReg32(0x10000280, (DRV_Reg32(0x10000280) & ~0x3) | 0x1);
pal_log_info("[USB] MDCIRQ 0x10000280 after: %x\n\n", DRV_Reg32(0x10000280));
2、做BC12 检测,判断是否链接的什么端口
if ((g_boot_reason == BR_USB) || usb_accessory_in()) {
ret = mt_charger_type_detection(); //BC12 检测,类型检测对才会有usb口
if(upmu_is_chr_det() == KAL_FALSE)
upmu_is_chr_det
ret = pmic_read_interface((U32)(PMIC_RGS_CHRDET_ADDR), (&val),
(U32)(PMIC_RGS_CHRDET_MASK),
(U32)(PMIC_RGS_CHRDET_SHIFT));
pal_log_info("[PMIC]IsUsbCableIn %d\n", val); //log打印 usb 在位
mtk_ext_chgdet(&g_ret);
#ifdef MTK_SYSTEM_USB_UART_SWITCH
if(mtk_uart_plug == 1){
pal_log_info("keeping uart mode and mtk_uart_plug = %d \n",mtk_uart_plug);
goto out;
}
#endif
for(i = 0; i < VG_DET_COUNT_MAX; i++) {
sc8950_i2c_read_byte(SC8950_REG_STATUS, &pg_stat);
pal_log_err("mtk_ext_chgdet pg_stat:0x%x\n", pg_stat);
for (i = 0; i < max_retry_cnt; i++) {
ret = sc8950_i2c_read_byte(SC8950_REG_STATUS, &stat);
pal_log_info("%s ic_stat = 0x%x\n", __func__, stat);
switch (stat) {
case SC8950_PORTSTAT_SDP:
*chg_type = STANDARD_HOST;
case SC8950_PORTSTAT_CDP:
*chg_type = CHARGING_HOST;
pal_log_err("%s chg type = %d\n", __func__, *chg_type);
Charger_Detect_Release();
/*init input/ichg current to 500mA*/
sc8950_set_indpm(500000);
sc8950_set_ichg(500000);
sc8950_en_charge(true);
sc8950_dump_registers();
if (ret == STANDARD_HOST || ret == CHARGING_HOST) { //根据上面BC12 判断是否接的是 PC host,来决定usb是否枚举
pal_log_info("\n%s USB cable in\n", MOD);
pal_log_warn("%s PMIC not dectect usb cable!\n", MOD);
pal_log_info("%s USB enum timeout (%s), handshake timeout(%s)\n", MOD, enum_tmo ? "Yes" : "No", handshake_tmo ? "Yes" : "No");
3、做usb 枚举
usbdl_init();
//先配置描述符,然后enable
udc_enable
ep = &udc_device->endpoint_array[0];
ep0_urb = usb_alloc_urb (udc_device, ep);
/* reset USB hardware */
mt_udc_reset();
if (__raw_readb (POWER) & PWR_HS_MODE)
{
print ("[USBD] USB High Speed\n");
enable_highspeed ();
}
udelay(1000);
usb_disconnect();
if (usb_connect(enum_tmo) == FALSE) {
pal_log_info("%s Enumeration(Start)\n", MOD);
pal_log_info("%s Enumeration(End): %s %dms \n", MOD, result == TRUE ? "OK" : "TMO", get_timer(start_time));
4、上面做usb 端口枚举,下面和meta工具交互,
if (FALSE == usb_handshake_handler(handler, handshake_tmo)) {
return handler->cb(handler, &cmd, &comport); //调用 bldr_cmd_handler 回调函数
} else if (CMD_MATCH(cmd, META_STR_REQ)) {
pal_log_info("meta_com_id = %d\n", param.v0001.usb_type);
if (0 == comm->recv((u8*)¶m.v0001, sizeof(param.v0001), 5000)) {
g_meta_com_id = param.v0001.usb_type;
pal_log_info("meta_com_id = %d\n", param.v0001.usb_type);
pal_log_info("md_type[0] = %d \n", param.v0001.md0_type);
pal_log_info("md_type[1] = %d \n", param.v0001.md1_type);
/* V2 param extension */
comm->send((u8*)META_ARG_VER_STR_V2, strlen(META_ARG_VER_STR_V2));
if (0 == comm->recv((u8*)¶m_v2.v0002, sizeof(param_v2.v0002), 5000)) {
pal_log_info("meta_com_id = %d\n", param_v2.v0002.usb_type);
pal_log_info("meta_log_disable = %d\n", param_v2.v0002.meta_log_disable);
g_boot_mode = META_BOOT;
pal_log_info("%s '%s' received!\n", MOD, cmd->data); //[BLDR] 'METAMETA' received!
g_meta_com_type = META_USB_COM;
BOOTING_TIME_PROFILING_LOG("USB handshake");
//除了usb 也可以用 uart 进行meta交互
if (TRUE == uart_handshake(handler))
g_meta_com_type = META_UART_COM;
BOOTING_TIME_PROFILING_LOG("UART handshake");
BOOTING_TIME_PROFILING_LOG("bldr_handshake");
bldr_post_process();
platform_post_init();
platform_set_boot_args
pal_log_info("\n%s boot to LK by ATAG reason=%d addr=%x\n", MOD, g_boot_reason,&g_dram_buf->boottag);
platform_set_boot_args_by_atag((unsigned int *)&(g_dram_buf->boottag)); // set jump addr
//做一些打印,关于 BOOT_REASON BOOT_MODE META_COM
platform_dump_boot_atag();
for (tags = (boot_tag *)&(g_dram_buf->boottag); tags->hdr.size; tags = (boot_tag *)boot_tag_next(tags))
switch(tags->hdr.tag)
case BOOT_TAG_BOOT_REASON:
pal_log_err("BOOT_REASON: %d\n", tags->u.boot_reason.boot_reason);
break;
case BOOT_TAG_BOOT_MODE:
pal_log_err("BOOT_MODE: %d\n", tags->u.boot_mode.boot_mode);
break;
case BOOT_TAG_META_COM:
pal_log_info("META_COM TYPE: %d\n", tags->u.meta_com.meta_com_type);
pal_log_info("META_COM ID: %d\n", tags->u.meta_com.meta_com_id);
pal_log_info("META_COM PORT: %d\n", tags->u.meta_com.meta_uart_port);
pal_log_info("META LOG DISABLE: %d\n", tags->u.meta_com.meta_log_disable);
pal_log_info("FAST META GPIO: %d\n", tags->u.meta_com.fast_meta_gpio);
preloader 重要打印
[PMIC]IsUsbCableIn 1
mtk_ext_chgdet chg type = 1
[PLFM] USB cable in
[TOOL] USB enum timeout (Yes), handshake timeout(Yes)
[USBD] USB Full Speed
[TOOL] Enumeration(Start)
[USBD] USB High Speed
[TOOL] Enumeration(End): OK 294ms
BOOT_REASON: 1
BOOT_MODE: 1
META_COM TYPE: 2
[BLDR] 'METAMETA' received!
[TOOL] USB port down timeout!
[TOOL] aleady detected meta tool!
三、LK: 多功能按键定制,马达功能,recovery 模式 FTM模式
kernel/main.c
kmain(void)
// get us into some sort of thread context
thread_init_early();
// early arch stuff
arch_early_init();
// do any super early platform initialization
platform_early_init();
PROFILING_START("platform_early_init");
/* initialize the uart */
uart_init_early();
PROFILING_START("Devinfo Init");
init_devinfo_data();
PROFILING_END();
platform_init_interrupts();
platform_early_init_timer();
dprintf(SPEW, "bootarg_addr: 0x%x, bootarg_size: 0x%x\n", platform_get_bootarg_addr(), platform_get_bootarg_size());
//i2c_v1_init();
PROFILING_START("WDT Init");
mtk_wdt_init();
PROFILING_END();
//i2c init
i2c_hw_init();
boot_time = get_timer(0);
// do any super early target initialization
target_early_init();
dprintf(INFO, "welcome to lk\n\n");
dprintf(INFO, "LK_VER_TAG = %s\n", LK_VER_TAG);
// deal with any static constructors
dprintf(SPEW, "calling constructors\n");
call_constructors();
// bring up the kernel heap
dprintf(SPEW, "initializing heap\n");
heap_init();
// initialize the threading system
dprintf(SPEW, "initializing threads\n");
thread_init();
// initialize the dpc system
dprintf(SPEW, "initializing dpc\n");
dpc_init();
// initialize kernel timers
dprintf(SPEW, "initializing timers\n");
timer_init();
#if (!ENABLE_NANDWRITE)
// create a thread to complete system initialization
dprintf(SPEW, "creating bootstrap completion thread\n");
thread_t *thread_bs2 = thread_create("bootstrap2", &bootstrap2, NULL,
DEFAULT_PRIORITY, DEFAULT_STACK_SIZE);
if (thread_bs2)
thread_resume(thread_bs2);
else {
dprintf(CRITICAL, "Error: Cannot create bootstrap2 thread!\n");
assert(0);
}
thread_t *thread_io = thread_create("iothread", &iothread, NULL,
IO_THREAD_PRIORITY, DEFAULT_STACK_SIZE);
if (thread_io)
thread_resume(thread_io);
else {
dprintf(CRITICAL, "Error: Cannot create I/O thread!\n");
assert(0);
}
// enable interrupts
exit_critical_section();
// become the idle thread
thread_become_idle();
#else
bootstrap_nandwrite();
#endif
bootstrap2
dprintf(SPEW, "top of bootstrap2()\n");
print_stack_of_current_thread();
// initialize the rest of the platform
dprintf(SPEW, "initializing platform\n");
platform_init();
PROFILING_START("platform_init");
dprintf(CRITICAL, "platform_init()\n");
/* The device tree should be loaded as early as possible. */
load_device_tree();
PROFILING_START("led init");
leds_init();
PROFILING_END();
/*这里会读取DTS 信息,DWS配置信息也在这里,DWS 配置错的话会读取错误,导致后面的流程异常。可以根据这些打印信息,判断配置是否正常
如果按键功能有问题的话厅,可以此案对比排查这里配置是否正常,检查键值定义*/
get_kpd_dts_info();
offset = fdt_path_offset(lk_drv_fdt, "/kp@10010000");
if (offset >= 0) {
kpd_dts_data.kpd_sw_pwrkey = kpd_fdt_getprop_u32(lk_drv_fdt, offset, "mediatek,kpd-sw-pwrkey");
kpd_dts_data.kpd_hw_pwrkey = kpd_fdt_getprop_u32(lk_drv_fdt, offset, "mediatek,kpd-hw-pwrkey");
kpd_dts_data.kpd_sw_rstkey = kpd_fdt_getprop_u32(lk_drv_fdt, offset, "mediatek,kpd-sw-rstkey");
if(!kpd_dts_data.kpd_sw_rstkey) {
kpd_dts_data.kpd_sw_rstkey = 17;
}
kpd_dts_data.kpd_hw_rstkey = kpd_fdt_getprop_u32(lk_drv_fdt, offset, "mediatek,kpd-hw-rstkey");
if(!kpd_dts_data.kpd_hw_rstkey) {
kpd_dts_data.kpd_hw_rstkey = 17;
}
kpd_dts_data.kpd_use_extend_type = kpd_fdt_getprop_u32(lk_drv_fdt, offset, "mediatek,kpd-use-extend-type");
kpd_dts_data.kpd_hw_recovery_key = kpd_fdt_getprop_u32(lk_drv_fdt, offset, "mediatek,kpd-hw-recovery-key");
kpd_dts_data.kpd_hw_factory_key = kpd_fdt_getprop_u32(lk_drv_fdt, offset, "mediatek,kpd-hw-factory-key");
dprintf(INFO, "kpd_sw_pwrkey = %d, kpd_hw_pwrkey = %d, kpd_sw_rstkey = %d, kpd_hw_rstkey = %d\n",
kpd_dts_data.kpd_sw_pwrkey, kpd_dts_data.kpd_hw_pwrkey, kpd_dts_data.kpd_sw_rstkey, kpd_dts_data.kpd_hw_rstkey);
dprintf(INFO, "kpd_use_extend_type = %d, kpd_hw_recovery_key = %d, kpd_hw_factory_key = %d\n",
kpd_dts_data.kpd_use_extend_type, kpd_dts_data.kpd_hw_recovery_key, kpd_dts_data.kpd_hw_factory_key);
kpd_dts_data.kpd_hw_map_num = kpd_fdt_getprop_u32(lk_drv_fdt, offset, "mediatek,kpd-hw-map-num");
kpd_fdt_getprop_u32_array(lk_drv_fdt, offset, "mediatek,kpd-hw-init-map", kpd_dts_data.kpd_hw_init_map, KPD_NUM_KEYS);
kpd_dts_init_done = 1;
} else {
#ifdef MT65XX_FACTORY_KEY
dprintf(CRITICAL, "MT65XX_FACTORY_KEY 0x%x\n",MT65XX_FACTORY_KEY);
#endif
#ifdef MT65XX_BOOT_MENU_KEY
dprintf(CRITICAL, "MT65XX_BOOT_MENU_KEY 0x%x\n",MT65XX_BOOT_MENU_KEY);
#endif
#ifdef MT65XX_RECOVERY_KEY
dprintf(CRITICAL, "MT65XX_RECOVERY_KEY 0x%x\n",MT65XX_RECOVERY_KEY);
#endif
mt_disp_init((void *)g_fb_base);
PROFILING_END();
PROFILING_START("vedio init");
drv_video_init();
PROFILING_END();
PROFIKING_START(boot mode select); //会计算并打印 boot_mode 判断的时间
// 启动模式选择,meta模式检测,还有这里会有很多按键检测,比如FTM 关机工模组合键,recovery 组合键
boot_mode_select
// meta mode是从 preloader 中传递过来的,可以查看上面preloader流程
if (meta_detection()) {
dprintf(INFO,"[META] Check meta info from pre-loader: %x, %x, %d\n", g_boot_arg->boot_mode, g_boot_arg->maggic_number, mode);
if (g_boot_arg->maggic_number == BOOT_ARGUMENT_MAGIC) {
if (mode == META_BOOT) {
g_boot_mode = META_BOOT;
return TRUE;
} else if (mode == ADVMETA_BOOT) {
g_boot_mode = ADVMETA_BOOT;
return TRUE;
} else if (mode == ATE_FACTORY_BOOT) {
g_boot_mode = ATE_FACTORY_BOOT;
return TRUE;
} else if (mode == ALARM_BOOT) {
g_boot_mode = ALARM_BOOT;
return TRUE;
} else if (mode == FASTBOOT) {
g_boot_mode = FASTBOOT;
return TRUE;
} else if (mode == FACTORY_BOOT) {
g_boot_mode = FACTORY_BOOT;
return TRUE;
} else if (mode == RECOVERY_BOOT) {
g_boot_mode = RECOVERY_BOOT;
return TRUE;
} else {
return FALSE;
}
}
return;
}
//正常MTK是音量上键加power键进 recovery,如果三键齐按进了recovery的话,需要排查按键的配置是否有问题
if (mtk_detect_key(MT65XX_RECOVERY_KEY)) {
dprintf(CRITICAL, "%s Detect cal key\n",MODULE_NAME);
dprintf(CRITICAL, "%s Enable recovery mode\n",MODULE_NAME);
g_boot_mode = RECOVERY_BOOT;
PROFILING_START("wdt_check_exception");
wdt_check_exception();
PROFILING_END();
PROFIKING_START(boot mode select); //会计算并打印 boot_mode 判断的时间
lk_vb_vfy_logo();
PROFILING_START("battery init");
PROFILING_START("charger init");
mtk_charger_init();
PROFILING_END(); /* charger init */
PROFILING_START("charger start");
mtk_charger_start();
PROFILING_END(); /* charger start */
//这里是开机马达震动一下的地方,马达放到charger 之后,防止低电时马达耗电大于充电速度,导致不能开机
timer_initialize(&timer);
if(g_boot_mode == NORMAL_BOOT || g_boot_mode == KERNEL_POWER_OFF_CHARGING_BOOT) {
dprintf(CRITICAL, "vibrator enable disable HW\n");
vibr_Enable_HW();
timer_set_oneshot(&timer, 200, vibr_disable_callback, NULL);
}
// initialize the target
dprintf(SPEW, "initializing target\n");
target_init();
dprintf(SPEW, "calling apps_init()\n");
apps_init();
先整理这么多,后续遇到问题再继续补充