void __cpuinit platform_secondary_init(unsigned int cpu) { printk(KERN_CRIT "Slave cpu init\n"); mt_gic_secondary_init(); HOTPLUG_INFO("platform_secondary_init, cpu: %d\n", cpu); pen_release = -1; smp_wmb(); #ifdef CONFIG_LOCAL_WDT printk("[WDK]cpu %d plug on platform_secondary_init++++++\n", cpu); wk_start_kick_cpu_hotplug(cpu); mtk_wdt_restart(WK_WDT_LOC_TYPE); mtk_wdt_restart(WK_WDT_EXT_TYPE); printk("[WDK]cpu %d plug on platform_secondary_init------\n", cpu); #endif fiq_glue_resume(); /* * Synchronise with the boot thread. */ spin_lock(&boot_lock); spin_unlock(&boot_lock); }
void mtk_wdt_init(void) { unsigned int tmp; unsigned int nonrst; unsigned int interval_val = DRV_Reg32(MTK_WDT_INTERVAL); mtk_wdt_mode_config(FALSE, FALSE, FALSE, FALSE, FALSE); WDTLOG("UB wdt init\n"); /* Update interval register value and check reboot flag */ if( (interval_val & RGU_TRIGGER_RESET_MASK) == IS_POWER_ON_RESET ) is_rgu_trigger_rst = 0; // Power off and power on reset else is_rgu_trigger_rst = 1; // RGU trigger reset interval_val &= ~(RGU_TRIGGER_RESET_MASK|MAGIC_NUM_MASK); interval_val |= (U_BOOT_MAGIC|IS_POWER_ON_RESET); /* Write back INTERVAL REG */ DRV_WriteReg32(MTK_WDT_INTERVAL, interval_val); /* Setting timeout 10s */ mtk_wdt_set_time_out_value(10); #if (!LK_WDT_DISABLE) mtk_wdt_mode_config(TRUE, TRUE, TRUE, FALSE, TRUE); mtk_wdt_restart(); #endif /* * E3 ECO * reset will delay 2ms after set SW_WDT in register */ nonrst = DRV_Reg32(MTK_WDT_NONRST_REG); nonrst = (nonrst | (1<<29)); DRV_WriteReg32(MTK_WDT_NONRST_REG, nonrst); dprintf(CRITICAL,"WDT NONRST=0x%x \n\r", DRV_Reg32(MTK_WDT_NONRST_REG)); #if 0 int i=0; //lk wdt test while(1) { i++; mdelay(1000); WDTLOG("UB wdt test %d\n" ,i); /* Dump RGU regisers */ WDTLOG("==== fwq Dump RGU Reg ========\n"); WDTLOG("RGU MODE: %x\n", DRV_Reg32(MTK_WDT_MODE)); WDTLOG("RGU LENGTH: %x\n", DRV_Reg32(MTK_WDT_LENGTH)); WDTLOG("RGU STA: %x\n", DRV_Reg32(MTK_WDT_STATUS)); WDTLOG("RGU INTERVAL: %x\n", DRV_Reg32(MTK_WDT_INTERVAL)); WDTLOG("RGU SWSYSRST: %x\n", DRV_Reg32(MTK_WDT_SWSYSRST)); WDTLOG("==== Dump RGU Reg End ====\n"); if(i<60) { WDTLOG("kick lk ext\n" ); mtk_wdt_restart(); } } #endif }
static void ipanic_kick_wdt(void) { #ifdef CONFIG_LOCAL_WDT mtk_wdt_restart(WK_WDT_LOC_TYPE); mtk_wdt_restart(WK_WDT_EXT_TYPE); #else mtk_wdt_restart(); #endif }
void mtk_wdt_init(void) { unsigned int tmp; unsigned int interval_val = DRV_Reg32(MTK_WDT_INTERVAL); mtk_wdt_mode_config(FALSE, FALSE, FALSE, FALSE, FALSE); printf("UB wdt init\n"); /* Update interval register value and check reboot flag */ if( (interval_val & RGU_TRIGGER_RESET_MASK) == IS_POWER_ON_RESET ) is_rgu_trigger_rst = 0; // Power off and power on reset else is_rgu_trigger_rst = 1; // RGU trigger reset interval_val &= ~(RGU_TRIGGER_RESET_MASK|MAGIC_NUM_MASK); interval_val |= (U_BOOT_MAGIC|IS_POWER_ON_RESET); /* Write back INTERVAL REG */ DRV_WriteReg32(MTK_WDT_INTERVAL, interval_val); /* Setting timeout 10s */ mtk_wdt_set_time_out_value(10); /*set spm_sysrst & pcm_wdt_rst to be reset mode*/ tmp = DRV_Reg32(MTK_WDT_REQ_IRQ_EN); tmp |= MTK_WDT_REQ_IRQ_EN_KEY; tmp &= ~(MTK_WDT_REQ_IRQ_EN_SPM | MTK_WDT_REQ_IRQ_EN_PCM); DRV_WriteReg32(MTK_WDT_REQ_IRQ_EN, tmp); mtk_wdt_mode_config(TRUE, TRUE, FALSE, FALSE, TRUE); mtk_wdt_restart(); }
int mtk_wdt_confirm_hwreboot(void) { //aee need confirm wd can hw reboot //printk("mtk_wdt_probe : Initialize to dual mode \n"); unsigned int tmp=0; aee_sram_fiq_log("mt6582 only hw reboot mode ++\n"); mtk_wdt_restart(WD_TYPE_NOLOCK);//restart spm wdt //set rgu 20s time out tmp = (unsigned int)(20 * ( 1 << 6) ); tmp = tmp << 5; *(volatile u32 *)(MTK_WDT_LENGTH)= (tmp | MTK_WDT_LENGTH_KEY); //restart rgu wdt *(volatile u32 *)( MTK_WDT_RESTART) =MTK_WDT_RESTART_KEY ; //use only hw reboot mode and enable rgu wdt tmp = DRV_Reg32(MTK_WDT_MODE); tmp |=MTK_WDT_MODE_KEY ; tmp &=(~(MTK_WDT_MODE_IRQ | MTK_WDT_MODE_DUAL_MODE)); tmp |=MTK_WDT_MODE_ENABLE ; *(volatile u32 *)(MTK_WDT_MODE)=tmp; aee_sram_fiq_log("mt6582 only hw reboot mode --\n"); return 0; }
static void kdump_ui(struct mrdump_control_block *mrdump_cblock) { video_clean_screen(); video_set_cursor(0, 0); mrdump_status_error("Unknown error\n"); voprintf_info("Kdump triggerd by '%s'\n", mrdump_mode2string(mrdump_cblock->crash_record.reboot_mode)); struct aee_timer elapse_time; aee_timer_init(&elapse_time); uint32_t total_dump_size = memory_size(); aee_timer_start(&elapse_time); switch (mrdump_cblock->machdesc.output_device) { case MRDUMP_DEV_NULL: kdump_null_output(mrdump_cblock, total_dump_size); break; #if 0 case MRDUMP_DEV_SDCARD: kdump_sdcard_output(mrdump_cblock, total_dump_size); break; #endif case MRDUMP_DEV_EMMC: kdump_emmc_output(mrdump_cblock, total_dump_size); break; default: voprintf_error("Unknown device id %d\n", mrdump_cblock->machdesc.output_device); } aee_timer_stop(&elapse_time); voprintf_info("Reset count down %d ...\n", MRDUMP_DELAY_TIME); mtk_wdt_restart(); int timeout = MRDUMP_DELAY_TIME; while(timeout-- >= 0) { mdelay(1000); mtk_wdt_restart(); voprintf_info("\rsec %d", timeout); } aee_mrdump_flush_cblock(); video_clean_screen(); video_set_cursor(0, 0); }
static int wd_cpu_hot_plug_on_notify(int cpu) { int res=0; wk_cpu_update_bit_flag(cpu,1); mtk_wdt_restart(WD_TYPE_NOLOCK);// for KICK external wdt printk("WD wd_cpu_hot_plug_on_notify kick ext wd\n"); return res; }
void platform_wdt_all_kick(void) { /* kick watchdog to avoid cpu reset */ mtk_wdt_restart(); #if !CFG_FPGA_PLATFORM /* kick PMIC watchdog to keep charging */ pl_kick_chr_wdt(); #endif }
void mtk_wd_suspend(void) { //mtk_wdt_ModeSelection(KAL_FALSE, KAL_FALSE, KAL_FALSE); // en debug, dis irq, dis ext, low pol, dis wdt mtk_wdt_mode_config(TRUE, TRUE, TRUE, FALSE, FALSE); mtk_wdt_restart(WD_TYPE_NORMAL); aee_sram_printk("[WDT] suspend\n"); printk("[WDT] suspend\n"); }
static void mtk_wdt_shutdown(struct platform_device *dev) { printk("******** MTK WDT driver shutdown!! ********\n" ); //mtk_wdt_ModeSelection(KAL_FALSE, KAL_FALSE, KAL_FALSE); //kick external wdt //mtk_wdt_mode_config(TRUE, FALSE, FALSE, FALSE, FALSE); mtk_wdt_restart(WD_TYPE_NORMAL); printk("******** MTK WDT driver shutdown done ********\n" ); }
static int wd_restart(enum wd_restart_type type) { #ifdef CONFIG_LOCAL_WDT #ifdef CONFIG_SMP on_each_cpu((smp_call_func_t)mpcore_wdt_restart, WK_WDT_LOC_TYPE, 0); #else mpcore_wdt_restart(type); #endif #endif mtk_wdt_restart(type); return 0; }
void mtk_wd_resume(void) { if ( g_wdt_enable == 1 ) { mtk_wdt_set_time_out_value(g_last_time_time_out_value); mtk_wdt_mode_config(TRUE, TRUE, TRUE, FALSE, TRUE); mtk_wdt_restart(WD_TYPE_NORMAL); } aee_sram_printk("[WDT] resume(%d)\n", g_wdt_enable); printk("[WDT] resume(%d)\n", g_wdt_enable); }
int kdump_null_output(const struct mrdump_control_block *mrdump_cb, uint32_t total_dump_size) { const struct mrdump_machdesc *kparams = &mrdump_cb->machdesc; voprintf_info("null dumping(address %x, size:%dM)\n", kparams->phys_offset, total_dump_size / 0x100000UL); mtk_wdt_restart(); bool ok = true; void *bufp = kdump_core_header_init(mrdump_cb, (uint32_t)kparams->phys_offset, total_dump_size); if (bufp != NULL) { mtk_wdt_restart(); struct kzip_file *zf = kzip_open(NULL, null_write_cb); if (zf != NULL) { struct kzip_memlist memlist[3]; memlist[0].address = bufp; memlist[0].size = KDUMP_CORE_SIZE; memlist[1].address = kparams->phys_offset; memlist[1].size = total_dump_size; memlist[2].address = NULL; memlist[2].size = 0; kzip_add_file(zf, memlist, "SYS_COREDUMP"); kzip_close(zf); zf = NULL; } else { ok = false; } free(bufp); } mtk_wdt_restart(); if (ok) { voprintf_info("%s: dump finished, dumped.\n", __func__); mrdump_status_ok("NULL-OUTPUT\n"); } return 0; }
static int kzip_write_current(struct kzip_file *zfile, void *buf, int len) { KZIP_DEBUG("%s: write_cb %p len %d\n", __func__, zfile->write_cb, len); int retval = zfile->write_cb(zfile->handle, buf, len); if (retval > 0) { zfile->current_size += retval; } if ((zfile->current_size - zfile->reported_size) >= KDUMP_SIZE_REPORT) { voprintf_info(".. Written %dM\n", zfile->current_size / 0x100000); zfile->reported_size = zfile->current_size; } if ((zfile->current_size - zfile->wdk_kick_size) >= KDUMP_TICK_WDT) { mtk_wdt_restart(); zfile->wdk_kick_size = zfile->current_size; } return retval; }
static void mtk_wdt_hw_reset(void) { printf("UB WDT_HW_Reset\n"); // 1. set WDT timeout 1 secs, 1*64*512/32768 = 1sec mtk_wdt_set_time_out_value(1); // 2. enable WDT debug reset enable, generating irq disable, ext reset disable // ext reset signal low, wdt enalbe mtk_wdt_mode_config(TRUE, FALSE, FALSE, FALSE, TRUE); // 3. reset the watch dog timer to the value set in WDT_LENGTH register mtk_wdt_restart(); // 4. system will reset while(1); }
//enter this function when low battery with charger void check_bat_protect_status() { kal_int32 bat_val = 0; #if defined(SWCHR_POWER_PATH) bat_val = get_i_sense_volt(5); #else bat_val = get_bat_sense_volt(5); #endif dprintf(CRITICAL, "[%s]: check VBAT=%d mV with %d mV, start charging... \n", __FUNCTION__, bat_val, BATTERY_LOWVOL_THRESOLD); if (bat_val < BATTERY_LOWVOL_THRESOLD) mt65xx_leds_brightness_set(MT65XX_LED_TYPE_RED, LED_FULL); while (bat_val < BATTERY_LOWVOL_THRESOLD) { mtk_wdt_restart(); if(upmu_is_chr_det() == KAL_FALSE) { dprintf(CRITICAL, "[BATTERY] No Charger, Power OFF !\n"); mt6575_power_off(); while(1); } pchr_turn_on_charging(KAL_TRUE); mdelay(5000); #if defined(SWCHR_POWER_PATH) pchr_turn_on_charging(KAL_FALSE); mdelay(100); bat_val = get_i_sense_volt(5); #else bat_val = get_bat_sense_volt(5); #endif } dprintf(CRITICAL, "[%s]: check VBAT=%d mV with %d mV, stop charging... \n", __FUNCTION__, bat_val, BATTERY_LOWVOL_THRESOLD); }
void mtk_wdt_init(void) { unsigned short interval_val = DRV_Reg16(MTK_WDT_INTERVAL); mtk_wdt_mode_config(FALSE, FALSE, FALSE, FALSE, FALSE); printf("UB wdt init\n"); /* Update interval register value and check reboot flag */ if( (interval_val & RGU_TRIGGER_RESET_MASK) == IS_POWER_ON_RESET ) is_rgu_trigger_rst = 0; // Power off and power on reset else is_rgu_trigger_rst = 1; // RGU trigger reset interval_val &= ~(RGU_TRIGGER_RESET_MASK|MAGIC_NUM_MASK); interval_val |= (U_BOOT_MAGIC|IS_POWER_ON_RESET); /* Write back INTERVAL REG */ DRV_WriteReg(MTK_WDT_INTERVAL, interval_val); /* Setting timeout 10s */ mtk_wdt_set_time_out_value(10); mtk_wdt_mode_config(TRUE, FALSE, FALSE, FALSE, TRUE); mtk_wdt_restart(); }
int mtk_wdt_boot_check(void) { unsigned int wdt_sta = mtk_wdt_check_status(); #if 0 if (wdt_sta == MTK_WDT_STATUS_HWWDT_RST) { /* For E1 bug, that SW reset value is 0xC000, we using "==" to check */ /* Time out reboot always by pass power key */ print ("TO reset, need bypass power key\n"); return WDT_BY_PASS_PWK_REBOOT; } else if (wdt_sta & MTK_WDT_STATUS_SWWDT_RST) { #endif /* * For DA download hope to timeout reboot, and boot to u-boot/kernel configurable reason, * we set both timeout reboot and software reboot can check whether bypass power key. */ if (wdt_sta & (MTK_WDT_STATUS_HWWDT_RST|MTK_WDT_STATUS_SWWDT_RST| MTK_WDT_STATUS_SPM_THERMAL_RST|MTK_WDT_STATUS_SPMWDT_RST| MTK_WDT_STATUS_THERMAL_DIRECT_RST|MTK_WDT_STATUS_SECURITY_RST |MTK_WDT_STATUS_DEBUGWDT_RST)) { if (rgu_mode & MTK_WDT_MODE_AUTO_RESTART) { /* HW/SW reboot, and auto restart is set, means bypass power key */ print ("SW reset with bypass power key flag\n"); return WDT_BY_PASS_PWK_REBOOT; } else { print ("SW reset without bypass power key flag\n"); return WDT_NORMAL_REBOOT; } } return WDT_NOT_WDT_REBOOT; } void mtk_wdt_init(void) { unsigned wdt_sta; unsigned int wdt_dbg_ctrl; unsigned int nonrst; /* Dump RGU regisers */ print("==== Dump RGU Reg ========\n"); print("RGU MODE: %x\n", DRV_Reg32(MTK_WDT_MODE)); print("RGU LENGTH: %x\n", DRV_Reg32(MTK_WDT_LENGTH)); print("RGU STA: %x\n", DRV_Reg32(MTK_WDT_STATUS)); print("RGU INTERVAL: %x\n", DRV_Reg32(MTK_WDT_INTERVAL)); print("RGU SWSYSRST: %x\n", DRV_Reg32(MTK_WDT_SWSYSRST)); print("==== Dump RGU Reg End ====\n"); rgu_mode = DRV_Reg32(MTK_WDT_MODE); wdt_sta = mtk_wdt_check_status(); // This function will store the reset reason: Time out/ SW trigger if ((wdt_sta & MTK_WDT_STATUS_HWWDT_RST)&&(rgu_mode&MTK_WDT_MODE_AUTO_RESTART)) { /* For E1 bug, that SW reset value is 0xC000, we using "==" to check */ /* Time out reboot always by pass power key */ g_rgu_status = RE_BOOT_BY_WDT_HW; } else if (wdt_sta & MTK_WDT_STATUS_SWWDT_RST) { g_rgu_status = RE_BOOT_BY_WDT_SW; } else { g_rgu_status = RE_BOOT_REASON_UNKNOW; } if(wdt_sta & MTK_WDT_STATUS_IRQWDT_RST) { g_rgu_status |= RE_BOOT_WITH_INTTERUPT; } if(wdt_sta & MTK_WDT_STATUS_SPM_THERMAL_RST) { g_rgu_status |= RE_BOOT_BY_SPM_THERMAL; } if(wdt_sta & MTK_WDT_STATUS_SPMWDT_RST) { g_rgu_status |= RE_BOOT_BY_SPM; } if(wdt_sta & MTK_WDT_STATUS_THERMAL_DIRECT_RST) { g_rgu_status |= RE_BOOT_BY_THERMAL_DIRECT; } if(wdt_sta & MTK_WDT_STATUS_DEBUGWDT_RST) { g_rgu_status |= RE_BOOT_BY_DEBUG; } if(wdt_sta & MTK_WDT_STATUS_SECURITY_RST) { g_rgu_status |= RE_BOOT_BY_SECURITY; } print ("RGU: g_rgu_satus:%d\n", g_rgu_status); mtk_wdt_mode_config(FALSE, FALSE, FALSE, FALSE, FALSE); // Wirte Mode register will clear status register mtk_wdt_check_trig_reboot_reason(); /* Setting timeout 10s */ mtk_wdt_set_time_out_value(16); #if (!CFG_APWDT_DISABLE) /* Config HW reboot mode */ mtk_wdt_mode_config(TRUE, TRUE, TRUE, FALSE, TRUE); mtk_wdt_restart(); #endif /* * E3 ECO * reset will delay 2ms after set SW_WDT in register */ nonrst = READ_REG(MTK_WDT_NONRST_REG); nonrst = (nonrst | (1<<29)); WRITE_REG(nonrst, MTK_WDT_NONRST_REG); print("WDT NONRST=0x%x\n", READ_REG(MTK_WDT_NONRST_REG)); // set mcu_lath_en requir by pl owner confirmed by RGU DE /*SW workaround close DEBUG IRQ for C2K*/ nonrst = READ_REG(MTK_WDT_REQ_IRQ_EN); nonrst &= (~(1<<19)); nonrst |= MTK_WDT_REQ_IRQ_KEY; WRITE_REG(nonrst, MTK_WDT_REQ_IRQ_EN); /*disable spm_thermal bit, becaue spm_thermal had been remove from HW*/ nonrst = READ_REG(MTK_WDT_REQ_IRQ_EN); nonrst &= (~(1<<0)); /*disale spm_thermal irq*/ nonrst |= MTK_WDT_REQ_IRQ_KEY; WRITE_REG(nonrst, MTK_WDT_REQ_IRQ_EN); print("WDT IRQ_EN=0x%x\n", READ_REG(MTK_WDT_REQ_IRQ_EN)); nonrst = READ_REG(MTK_WDT_REQ_MODE); nonrst &= (~(1<<0)); /*disale spm_thermal reset*/ nonrst |= 0x33000000; WRITE_REG(nonrst, MTK_WDT_REQ_MODE); print("WDT REQ_EN=0x%x\n", READ_REG(MTK_WDT_REQ_MODE)); wdt_dbg_ctrl = READ_REG(MTK_WDT_DEBUG_CTL); wdt_dbg_ctrl |= MTK_RG_MCU_LATH_EN; wdt_dbg_ctrl |= MTK_DEBUG_CTL_KEY; WRITE_REG(wdt_dbg_ctrl, MTK_WDT_DEBUG_CTL); print("RGU %s:MTK_WDT_DEBUG_CTL(%x)\n", __func__,wdt_dbg_ctrl); }
static void ipanic_kick_wdt(void) { mtk_wdt_restart(WK_WDT_LOC_TYPE); mtk_wdt_restart(WK_WDT_EXT_TYPE); }
// check the boot mode : (1) meta mode or (2) recovery mode ... void boot_mode_select(void) { //Ivan ulong begin; if (meta_detection()) { return; } #if defined (HAVE_LK_TEXT_MENU) if(Check_RTC_PDN1_bit13()) { printf("[FASTBOOT] reboot to boot loader\n"); g_boot_mode = FASTBOOT; Set_Clr_RTC_PDN1_bit13(false); return; } //Ivan #ifdef MENU_BOOT_ENABLE boot_mode_dkey_check(); if (g_boot_mode == MENU_BOOT) { /* clean console screen */ video_clean_screen(); // mt65xx_disp_fill_rect(0, 0, CFG_DISPLAY_WIDTH, CFG_DISPLAY_HEIGHT, 0x0); video_set_cursor(2,0); video_printf("Recovery Mode: Volume Up\r\n"); video_set_cursor(4,0); video_printf("Factory Mode: Volume Down\r\n"); // mt65xx_disp_update(0, 0, CFG_DISPLAY_WIDTH, CFG_DISPLAY_HEIGHT); mt65xx_backlight_on(); video_set_cursor(49,0); while (mt65XX_get_key() != 0xFFFF); printf(" > Key release!!!\n"); mdelay(500); //Ivan added mtk_wdt_restart(); begin = get_timer(0); while (g_boot_mode == MENU_BOOT) { if (factory_detection()) { video_clean_screen(); return; } if(boot_menu_detection())//recovery, fastboot, normal boot. { video_clean_screen(); return; } //Ivan add 20s time limit if (get_timer(begin) < 20000) mtk_wdt_restart(); } // video_clean_screen(); // mt65xx_disp_fill_rect(0, 0, CFG_DISPLAY_WIDTH, CFG_DISPLAY_HEIGHT, 0x0); // mt65xx_disp_update(0, 0, CFG_DISPLAY_WIDTH, CFG_DISPLAY_HEIGHT); // video_set_cursor(49,0); // mt65xx_disp_wait_idle(); } if(Check_RTC_Recovery_Mode()) { g_boot_mode = RECOVERY_BOOT; } recovery_check_command_trigger(); #else //MENU_BOOT_ENABLE if (factory_detection()) { return; } if(boot_menu_detection())//recovery, fastboot, normal boot. { return; } recovery_detection(); #endif //MENU_BOOT_ENABLE #else //HAVE_LK_TEXT_MENU #ifdef MTK_FASTBOOT_SUPPORT if(fastboot_trigger()) { return; } #endif //MTK_FASTBOOT_SUPPORT if (factory_detection()) { return; } if(recovery_detection()) { //************************************** //* CHECK IMAGE //************************************** if(DRV_Reg32(0x40002300)==0xE92D4800) { printf(" > do recovery_check\n"); //jump(0x40002300); } else { printf(" > bypass recovery_check\n"); } return; } #endif #ifdef MTK_KERNEL_POWER_OFF_CHARGING if(kernel_power_off_charging_detection()) { printf(" < Kernel Power Off Charging Detection Ok> \n"); return; } else { printf("< Kernel Enter Normal Boot > \n"); } #endif }
void platform_wdt_kick(void) { /* kick hardware watchdog */ mtk_wdt_restart(); }
int mtk_wdt_boot_check(void) { unsigned int wdt_sta = mtk_wdt_check_status(); #if 0 if (wdt_sta == MTK_WDT_STATUS_HWWDT_RST) { /* For E1 bug, that SW reset value is 0xC000, we using "==" to check */ /* Time out reboot always by pass power key */ print ("TO reset, need bypass power key\n"); return WDT_BY_PASS_PWK_REBOOT; } else if (wdt_sta & MTK_WDT_STATUS_SWWDT_RST) { #endif /* * For DA download hope to timeout reboot, and boot to u-boot/kernel configurable reason, * we set both timeout reboot and software reboot can check whether bypass power key. */ if (wdt_sta & (MTK_WDT_STATUS_HWWDT_RST|MTK_WDT_STATUS_SWWDT_RST|MTK_WDT_STATUS_PCMWDT_RST|MTK_WDT_STATUS_SPMWDT_RST)) { if (rgu_mode & MTK_WDT_MODE_AUTO_RESTART) { /* HW/SW reboot, and auto restart is set, means bypass power key */ print ("SW RST with bypass power key\n"); return WDT_BY_PASS_PWK_REBOOT; } else { print ("SW RST without bypass power key\n"); return WDT_NORMAL_REBOOT; } } return WDT_NOT_WDT_REBOOT; } void mtk_wdt_init(void) { #if defined(CONFIG_EMULATION_EARLY_PORTING) print("==== Dump RGU Reg ========\n"); print("RGU MODE: %x\n", DRV_Reg32(MTK_WDT_MODE)); print("RGU LENGTH: %x\n", DRV_Reg32(MTK_WDT_LENGTH)); print("RGU STA: %x\n", DRV_Reg32(MTK_WDT_STATUS)); print("RGU INTERVAL: %x\n", DRV_Reg32(MTK_WDT_INTERVAL)); print("==== Dump RGU Reg End ====\n"); DRV_WriteReg32(0x10007000, 0x22000000); //mt6572 emulation #else unsigned wdt_sta; /* Dump RGU regisers */ print("==== Dump RGU Reg ========\n"); print("RGU MODE: %x\n", DRV_Reg32(MTK_WDT_MODE)); print("RGU EN_FAST: %x\n", DRV_Reg32(MTK_WDT_EN_FAST)); print("RGU LENGTH: %x\n", DRV_Reg32(MTK_WDT_LENGTH)); print("RGU STA: %x\n", DRV_Reg32(MTK_WDT_STATUS)); print("RGU DRAM_CTL: %x\n", DRV_Reg32(MTK_WDT_DRAMC_CTL)); print("RGU INTERVAL: %x\n", DRV_Reg32(MTK_WDT_INTERVAL)); print("RGU FAST_SWSYSRST: %x\n", DRV_Reg32(MTK_WDT_FAST_SWSYSRST)); print("==== Dump RGU Reg End ====\n"); rgu_mode = DRV_Reg32(MTK_WDT_MODE); wdt_sta = mtk_wdt_check_status(); // This function will store the reset reason: Time out/ SW trigger if (((wdt_sta & MTK_WDT_STATUS_HWWDT_RST) || (wdt_sta & MTK_WDT_STATUS_PCMWDT_RST)) && (rgu_mode&MTK_WDT_MODE_AUTO_RESTART)) { /* For E1 bug, that SW reset value is 0xC000, we using "==" to check */ /* Time out reboot always by pass power key */ g_rgu_status = RE_BOOT_BY_WDT_HW; } else if (wdt_sta & MTK_WDT_STATUS_SWWDT_RST) { g_rgu_status = RE_BOOT_BY_WDT_SW; } else { g_rgu_status = RE_BOOT_REASON_UNKNOW; } if(wdt_sta & MTK_WDT_STATUS_IRQWDT_RST) { g_rgu_status |= RE_BOOT_WITH_INTTERUPT; } if(wdt_sta & MTK_WDT_STATUS_SPMWDT_RST) { g_rgu_status |= RE_BOOT_WITH_THERMAL; } if(wdt_sta & MTK_WDT_STATUS_PCMWDT_RST) { g_rgu_status |= RE_BOOT_BY_SPM; } print ("g_rgu_satus:%d\n", g_rgu_status); mtk_wdt_mode_config(FALSE, FALSE, FALSE, FALSE, FALSE); // Wirte Mode register will clear status register mtk_wdt_check_trig_reboot_reason(); /* Setting timeout 10s */ mtk_wdt_set_time_out_value(16); #ifdef CFG_APWDT_DISABLE /* Config HW reboot mode */ mtk_wdt_mode_config(TRUE, FALSE, TRUE, FALSE, TRUE); mtk_wdt_restart(); #endif mtk_wdt_reset_deglitch_enable(); #endif }
/* * Device interface */ static int mtk_wdt_probe(struct platform_device *dev) { int ret=0; unsigned int interval_val; printk("******** MTK WDT driver probe!! ********\n" ); #ifndef __USING_DUMMY_WDT_DRV__ /* FPGA will set this flag */ #ifndef CONFIG_FIQ_GLUE printk("******** MTK WDT register irq ********\n" ); #ifdef CONFIG_KICK_SPM_WDT ret = spm_wdt_register_irq((irq_handler_t)mtk_wdt_isr); #else ret = request_irq(AP_RGU_WDT_IRQ_ID, (irq_handler_t)mtk_wdt_isr, IRQF_TRIGGER_FALLING, "mtk_watchdog", NULL); #endif //CONFIG_KICK_SPM_WDT #else printk("******** MTK WDT register fiq ********\n" ); #ifdef CONFIG_KICK_SPM_WDT ret = spm_wdt_register_fiq(wdt_fiq); #else ret = request_fiq(AP_RGU_WDT_IRQ_ID, wdt_fiq, IRQF_TRIGGER_FALLING, NULL); #endif //CONFIG_KICK_SPM_WDT #endif if(ret != 0) { printk( "mtk_wdt_probe : failed to request irq (%d)\n", ret); return ret; } printk("mtk_wdt_probe : Success to request irq\n"); #ifdef CONFIG_KICK_SPM_WDT spm_wdt_init(); #endif /* Set timeout vale and restart counter */ g_last_time_time_out_value=30; mtk_wdt_set_time_out_value(g_last_time_time_out_value); mtk_wdt_restart(WD_TYPE_NORMAL); /** * Set the reset lenght: we will set a special magic key. * For Power off and power on reset, the INTERVAL default value is 0x7FF. * We set Interval[1:0] to different value to distinguish different stage. * Enter pre-loader, we will set it to 0x0 * Enter u-boot, we will set it to 0x1 * Enter kernel, we will set it to 0x2 * And the default value is 0x3 which means reset from a power off and power on reset */ #define POWER_OFF_ON_MAGIC (0x3) #define PRE_LOADER_MAGIC (0x0) #define U_BOOT_MAGIC (0x1) #define KERNEL_MAGIC (0x2) #define MAGIC_NUM_MASK (0x3) #ifdef CONFIG_MTK_WD_KICKER // Initialize to dual mode printk("mtk_wdt_probe : Initialize to dual mode \n"); mtk_wdt_mode_config(TRUE, TRUE, TRUE, FALSE, TRUE); #else // Initialize to disable wdt printk("mtk_wdt_probe : Initialize to disable wdt \n"); mtk_wdt_mode_config(FALSE, FALSE, TRUE, FALSE, FALSE); g_wdt_enable =0; #endif /* Update interval register value and check reboot flag */ interval_val = DRV_Reg32(MTK_WDT_INTERVAL); interval_val &= ~(MAGIC_NUM_MASK); interval_val |= (KERNEL_MAGIC); /* Write back INTERVAL REG */ DRV_WriteReg32(MTK_WDT_INTERVAL, interval_val); #endif mtk_wdt_deglitch_en(); udelay(100); printk("mtk_wdt_probe : done WDT_MODE(%x), MTK_WDT_DEGLITCH_EN(%x)\n",DRV_Reg32(MTK_WDT_MODE),DRV_Reg32(MTK_WDT_DEGLITCH_EN)); printk("mtk_wdt_probe : done MTK_WDT_REQ_MODE(%x)\n",DRV_Reg32(MTK_WDT_REQ_MODE)); printk("mtk_wdt_probe : done MTK_WDT_REQ_IRQ_EN(%x)\n",DRV_Reg32(MTK_WDT_REQ_IRQ_EN)); return ret; }
static int kwdt_thread(void *arg) { struct sched_param param = { .sched_priority = RTPM_PRIO_WDT}; struct rtc_time tm; struct timeval tv = {0}; /* android time */ struct rtc_time tm_android; struct timeval tv_android = {0}; int cpu = 0; int local_bit = 0, loc_need_config = 0, loc_timeout = 0; struct wd_api *loc_wk_wdt = NULL; sched_setscheduler(current, SCHED_FIFO, ¶m); set_current_state(TASK_INTERRUPTIBLE); for(;;) { if (kthread_should_stop()) break; spin_lock(&lock); cpu = smp_processor_id(); loc_wk_wdt = g_wd_api; loc_need_config = g_need_config; loc_timeout = g_timeout; spin_unlock(&lock); //printk("fwq loc_wk_wdt(%x),loc_wk_wdt->ready(%d)\n",loc_wk_wdt ,loc_wk_wdt->ready); if (loc_wk_wdt && loc_wk_wdt->ready && g_enable) { if (loc_need_config) { // daul mode loc_wk_wdt->wd_config(WDT_DUAL_MODE, loc_timeout); spin_lock(&lock); g_need_config = 0; spin_unlock(&lock); } //printk("[WDK] cpu-task=%d, current_pid=%d\n", wk_tsk[cpu]->pid, current->pid); if(wk_tsk[cpu]->pid == current->pid) { //only process WDT info if thread-x is on cpu-x spin_lock(&lock); local_bit = kick_bit; //printk_sched("[WDK], local_bit:0x%x, cpu:%d,RT[%lld]\n", local_bit, cpu,sched_clock()); if((local_bit&(1<<cpu)) == 0) { //printk("[WDK]: set WDT kick_bit\n"); local_bit |= (1<<cpu); //aee_rr_rec_wdk_kick_jiffies(jiffies); } //printk_sched("[WDK], local_bit:0x%x, cpu:%d, check bit0x:%x,RT[%lld]\n", local_bit, cpu, wk_check_kick_bit(),sched_clock()); if(local_bit == wk_check_kick_bit()) { //printk_sched("[WDK]: kick Ex WDT,RT[%lld]\n",sched_clock()); mtk_wdt_restart(WD_TYPE_NORMAL);// for KICK external wdt local_bit = 0; } kick_bit = local_bit; spin_unlock(&lock); #ifdef CONFIG_LOCAL_WDT //printk_sched("[WDK]: cpu:%d, kick local wdt,RT[%lld]\n", cpu,sched_clock()); // kick local wdt mpcore_wdt_restart(WD_TYPE_NORMAL); #endif } } else if(0 == g_enable) { printk("WDK stop to kick \n"); } else { errmsg("No watch dog driver is hooked\n"); BUG(); } if(wk_tsk[cpu]->pid == current->pid) { #if (DEBUG_WDK==1) msleep_interruptible(debug_sleep * 1000); dbgmsg("WD kicker woke up %d\n", debug_sleep); #endif do_gettimeofday(&tv); tv_android = tv; rtc_time_to_tm(tv.tv_sec, &tm); tv_android.tv_sec -= sys_tz.tz_minuteswest*60; rtc_time_to_tm(tv_android.tv_sec, &tm_android); /* printk_sched("[thread:%d][RT:%lld] %d-%02d-%02d %02d:%02d:%02d.%u UTC; android time %d-%02d-%02d %02d:%02d:%02d.%03d\n", current->pid,sched_clock(), tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, (unsigned int) tv.tv_usec, tm_android.tm_year + 1900, tm_android.tm_mon + 1, tm_android.tm_mday, tm_android.tm_hour, tm_android.tm_min, tm_android.tm_sec, (unsigned int) tv_android.tv_usec ); */ } msleep_interruptible((g_kinterval) * 1000); #ifdef CONFIG_MTK_AEE_POWERKEY_HANG_DETECT if( (cpu==0)&&(wk_tsk[cpu]->pid == current->pid))//only effect at cpu0 { if(aee_kernel_wdt_kick_api(g_kinterval)==WDT_PWK_HANG_FORCE_HWT) { //printk_sched("power key trigger HWT\n"); cpus_kick_bit=0xFFFF; //Try to force to HWT } } #endif } printk("[WDK] WDT kicker thread stop, cpu:%d, pid:%d\n", cpu, current->pid); return 0; }
void aee_stop_nested_panic(struct pt_regs *regs) { struct thread_info *thread = current_thread_info(); int i = 0; int len = 0; int timeout = 1000000; local_irq_disable(); preempt_disable(); /*Data abort handler data abort again on many cpu. Since ram console api is lockless, this should be prevented*/ if(atomic_xchg(&nested_panic_time, 1) != 0) { aee_nested_printf("multicore enters nested panic\n"); goto out; } mtk_wdt_restart(WK_WDT_LOC_TYPE_NOLOCK); hw_reboot_mode(); /*must guarantee Only one cpu can run here*/ aee_nested_printf("Nested panic\n"); aee_nested_printf("Log for the previous panic:\n"); aee_nested_printf("pc: %08lx lr: %08lx psr: %08lx\n", ((struct pt_regs *)thread->regs_on_excp)->ARM_pc, ((struct pt_regs *)thread->regs_on_excp)->ARM_lr, ((struct pt_regs *)thread->regs_on_excp)->ARM_cpsr); aee_nested_printf("sp: %08lx ip: %08lx fp: %08lx\n", ((struct pt_regs *)thread->regs_on_excp)->ARM_sp, ((struct pt_regs *)thread->regs_on_excp)->ARM_ip, ((struct pt_regs *)thread->regs_on_excp)->ARM_fp); aee_nested_printf("r10: %08lx r9: %08lx r8: %08lx\n", ((struct pt_regs *)thread->regs_on_excp)->ARM_r10, ((struct pt_regs *)thread->regs_on_excp)->ARM_r9, ((struct pt_regs *)thread->regs_on_excp)->ARM_r8); aee_nested_printf("r7: %08lx r6: %08lx r5: %08lx r4: %08lx\n", ((struct pt_regs *)thread->regs_on_excp)->ARM_r7, ((struct pt_regs *)thread->regs_on_excp)->ARM_r6, ((struct pt_regs *)thread->regs_on_excp)->ARM_r5, ((struct pt_regs *)thread->regs_on_excp)->ARM_r4); aee_nested_printf("r3: %08lx r2: %08lx r1: %08lx r0: %08lx\n", ((struct pt_regs *)thread->regs_on_excp)->ARM_r3, ((struct pt_regs *)thread->regs_on_excp)->ARM_r2, ((struct pt_regs *)thread->regs_on_excp)->ARM_r1, ((struct pt_regs *)thread->regs_on_excp)->ARM_r0); aee_nested_printf("Log for the current panic:\n"); aee_nested_printf("pc: %08lx lr: %08lx psr: %08lx\n", regs->ARM_pc, regs->ARM_lr, regs->ARM_cpsr); aee_nested_printf("sp: %08lx ip: %08lx fp: %08lx\n", regs->ARM_sp, regs->ARM_ip, regs->ARM_fp); aee_nested_printf("r10: %08lx r9: %08lx r8: %08lx\n", regs->ARM_r10, regs->ARM_r9, regs->ARM_r8); aee_nested_printf("r7: %08lx r6: %08lx r5: %08lx r4: %08lx\n", regs->ARM_r7, regs->ARM_r6, regs->ARM_r5, regs->ARM_r4); len = aee_nested_printf("r3: %08lx r2: %08lx r1: %08lx r0: %08lx\n", regs->ARM_r3, regs->ARM_r2, regs->ARM_r1, regs->ARM_r0); /*should not print stack info. this may overwhelms ram console used by fiq*/ if(0!= in_fiq_handler()) { goto out; } aee_nested_printf("stack [%08lx %08lx]", ((struct pt_regs *)thread->regs_on_excp)->ARM_sp, ((struct pt_regs *)thread->regs_on_excp)->ARM_sp + 512); /*Dump first panic stack*/ len = aee_dump_stack_top_binary(nested_panic_buf, sizeof(nested_panic_buf), ((struct pt_regs *)thread->regs_on_excp)->ARM_sp, ((struct pt_regs *)thread->regs_on_excp)->ARM_sp + 512 ); if(len > 0) { aee_sram_fiq_save_bin(nested_panic_buf, len); }else{ print_error_msg(len); } aee_nested_printf("stack [%08lx %08lx]", regs->ARM_sp, regs->ARM_sp + 256); /*Dump second panic stack*/ len = aee_dump_stack_top_binary(nested_panic_buf, sizeof(nested_panic_buf), regs->ARM_sp, regs->ARM_sp + 256); if(len > 0) { aee_sram_fiq_save_bin(nested_panic_buf, len); }else { print_error_msg(len); } out: /* waiting for the WDT timeout */ while (1) { printk("%s hang here%d\t", __func__, i++); while(timeout--) { udelay(1); } timeout = 1000000; } }