| /* |
| * Copyright (C) 2015 MediaTek Inc. |
| * |
| * This program is free software: you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License version 2 as |
| * published by the Free Software Foundation. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| */ |
| |
| #include <linux/kernel.h> |
| #include <ext_wd_drv.h> |
| #include <linux/smp.h> |
| /*add by debug for register restart notify*/ |
| #include <linux/notifier.h> |
| #include <linux/reboot.h> |
| #include <mt-plat/mtk_reboot.h> |
| #include <mt-plat/mtk_rtc.h> |
| #include <asm/system_misc.h> |
| #include <linux/console.h> |
| #ifdef CONFIG_MTK_SECURITY_SW_SUPPORT |
| #include <sec_hal.h> |
| #endif |
| |
| static int wd_cpu_hot_plug_on_notify(int cpu); |
| static int wd_cpu_hot_plug_off_notify(int cpu); |
| static int spmwdt_mode_config(enum wk_req_en en, enum wk_req_mode mode); |
| static int thermal_mode_config(enum wk_req_en en, enum wk_req_mode mode); |
| static int confirm_hwreboot(void); |
| static void resume_notify(void); |
| static void suspend_notify(void); |
| static int mtk_wk_wdt_config(enum ext_wdt_mode mode, int timeout_val); |
| static unsigned int wd_get_check_bit(void); |
| static unsigned int wd_get_kick_bit(void); |
| static int disable_all_wd(void); |
| static int disable_ext(void); |
| static int disable_local(void); |
| static int wd_sw_reset(int type); |
| static int wd_restart(enum wd_restart_type type); |
| static int set_mode(enum ext_wdt_mode mode); |
| static int wd_dram_reserved_mode(bool enabled); |
| static int wd_mcu_cache_preserve(bool enabled); |
| static int thermal_direct_mode_config(enum wk_req_en en, |
| enum wk_req_mode mode); |
| static int debug_key_eint_config(enum wk_req_en en, enum wk_req_mode mode); |
| static int debug_key_sysrst_config(enum wk_req_en en, enum wk_req_mode mode); |
| static int dfd_count_en(int value); |
| static int dfd_thermal1_dis(int value); |
| static int dfd_thermal2_dis(int value); |
| static int dfd_timeout(int value); |
| |
| static struct wd_api g_wd_api_obj = { |
| .ready = 1, |
| .wd_cpu_hot_plug_on_notify = wd_cpu_hot_plug_on_notify, |
| .wd_cpu_hot_plug_off_notify = wd_cpu_hot_plug_off_notify, |
| .wd_spmwdt_mode_config = spmwdt_mode_config, |
| .wd_thermal_mode_config = thermal_mode_config, |
| .wd_sw_reset = wd_sw_reset, |
| .wd_restart = wd_restart, |
| .wd_config = mtk_wk_wdt_config, |
| .wd_set_mode = set_mode, |
| .wd_aee_confirm_hwreboot = confirm_hwreboot, |
| .wd_disable_ext = disable_ext, |
| .wd_disable_local = disable_local, |
| .wd_suspend_notify = suspend_notify, |
| .wd_resume_notify = resume_notify, |
| .wd_disable_all = disable_all_wd, |
| .wd_get_check_bit = wd_get_check_bit, |
| .wd_get_kick_bit = wd_get_kick_bit, |
| .wd_dram_reserved_mode = wd_dram_reserved_mode, |
| .wd_mcu_cache_preserve = wd_mcu_cache_preserve, |
| .wd_thermal_direct_mode_config = thermal_direct_mode_config, |
| .wd_debug_key_eint_config = debug_key_eint_config, |
| .wd_debug_key_sysrst_config = debug_key_sysrst_config, |
| .wd_dfd_count_en = dfd_count_en, |
| .wd_dfd_thermal1_dis = dfd_thermal1_dis, |
| .wd_dfd_thermal2_dis = dfd_thermal2_dis, |
| .wd_dfd_timeout = dfd_timeout, |
| }; |
| |
| /* struct wd_private_api *g_wd_private_api_obj; */ |
| |
| |
| |
| /* apiimplimentation */ |
| #ifdef CONFIG_MTK_WD_KICKER |
| |
| static unsigned int wd_get_check_bit(void) |
| { |
| return get_check_bit(); |
| } |
| |
| static unsigned int wd_get_kick_bit(void) |
| { |
| return get_kick_bit(); |
| } |
| |
| |
| 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, WD_TYPE_NORMAL, 0); |
| #else |
| mpcore_wdt_restart(type); |
| #endif |
| #endif |
| mtk_wdt_restart(type); |
| return 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 */ |
| pr_notice("WD %s kick ext wd\n", __func__); |
| |
| return res; |
| } |
| |
| static int wd_cpu_hot_plug_off_notify(int cpu) |
| { |
| int res = 0; |
| |
| wk_cpu_update_bit_flag(cpu, 0); |
| return res; |
| } |
| |
| static int wd_sw_reset(int type) |
| { |
| wdt_arch_reset(type); |
| return 0; |
| } |
| |
| static int mtk_wk_wdt_config(enum ext_wdt_mode mode, int timeout_val) |
| { |
| |
| mtk_wdt_mode_config(TRUE, TRUE, TRUE, FALSE, TRUE); |
| mtk_wdt_set_time_out_value(timeout_val); |
| #ifdef CONFIG_LOCAL_WDT |
| mpcore_wk_wdt_config(0, 0, timeout_val - 5); |
| /* local 25s time out */ |
| /* mpcore_wdt_set_heartbeat(timeout_val - 5);*/ |
| /* local 25s time out */ |
| #endif |
| |
| return 0; |
| } |
| |
| static int disable_ext(void) |
| { |
| mtk_wdt_enable(WK_WDT_DIS); |
| return 0; |
| } |
| |
| |
| static int disable_local(void) |
| { |
| #ifdef CONFIG_LOCAL_WDT |
| #ifdef CONFIG_SMP |
| on_each_cpu((smp_call_func_t) local_wdt_enable, WK_WDT_DIS, 0); |
| #else |
| local_wdt_enable(WK_WDT_DIS); |
| #endif |
| #endif |
| pr_debug(" wd_api %s not support now\n", __func__); |
| return 0; |
| } |
| |
| static int set_mode(enum ext_wdt_mode mode) |
| { |
| pr_debug(" support only irq mode-20140522"); |
| switch (mode) { |
| case WDT_DUAL_MODE: |
| break; |
| |
| case WDT_HW_REBOOT_ONLY_MODE: |
| break; |
| |
| case WDT_IRQ_ONLY_MODE: |
| pr_debug("wd set only irq mode for debug\n"); |
| mtk_wdt_mode_config(FALSE, TRUE, TRUE, FALSE, TRUE); |
| break; |
| } |
| |
| return 0; |
| |
| } |
| |
| static int confirm_hwreboot(void) |
| { |
| mtk_wdt_confirm_hwreboot(); |
| return 0; |
| } |
| |
| static void suspend_notify(void) |
| { |
| mtk_wd_suspend(); |
| } |
| |
| static void resume_notify(void) |
| { |
| mtk_wd_resume(); |
| } |
| |
| static int disable_all_wd(void) |
| { |
| disable_ext(); |
| #ifdef CONFIG_LOCAL_WDT |
| disable_local(); |
| #endif |
| return 0; |
| } |
| |
| static int spmwdt_mode_config(enum wk_req_en en, enum wk_req_mode mode) |
| { |
| int res = 0; |
| |
| if (en == WD_REQ_EN) { |
| res = mtk_wdt_request_en_set(MTK_WDT_REQ_SPM_SCPSYS_MARK, |
| WD_REQ_EN); |
| } else if (en == WD_REQ_DIS) { |
| res = mtk_wdt_request_en_set(MTK_WDT_REQ_SPM_SCPSYS_MARK, |
| WD_REQ_DIS); |
| } else { |
| res = -2; |
| } |
| |
| if (mode == WD_REQ_IRQ_MODE) { |
| res = mtk_wdt_request_mode_set(MTK_WDT_REQ_SPM_SCPSYS_MARK, |
| WD_REQ_IRQ_MODE); |
| } else if (mode == WD_REQ_RST_MODE) { |
| res = mtk_wdt_request_mode_set(MTK_WDT_REQ_SPM_SCPSYS_MARK, |
| WD_REQ_RST_MODE); |
| } else { |
| res = -3; |
| } |
| return res; |
| } |
| |
| static int thermal_mode_config(enum wk_req_en en, enum wk_req_mode mode) |
| { |
| int res = 0; |
| |
| if (en == WD_REQ_EN) { |
| res = mtk_wdt_request_en_set(MTK_WDT_REQ_SPM_THERMAL_MARK, |
| WD_REQ_EN); |
| } else if (en == WD_REQ_DIS) { |
| res = mtk_wdt_request_en_set(MTK_WDT_REQ_SPM_THERMAL_MARK, |
| WD_REQ_DIS); |
| } else { |
| res = -2; |
| } |
| |
| if (mode == WD_REQ_IRQ_MODE) { |
| res = mtk_wdt_request_mode_set(MTK_WDT_REQ_SPM_THERMAL_MARK, |
| WD_REQ_IRQ_MODE); |
| } else if (mode == WD_REQ_RST_MODE) { |
| res = mtk_wdt_request_mode_set(MTK_WDT_REQ_SPM_THERMAL_MARK, |
| WD_REQ_RST_MODE); |
| } else { |
| res = -3; |
| } |
| return res; |
| } |
| |
| static int thermal_direct_mode_config(enum wk_req_en en, enum wk_req_mode mode) |
| { |
| int res = 0; |
| |
| pr_debug("%s(en:0x%x,mode:0x%x)\n", __func__, en, mode); |
| if (en == WD_REQ_EN) { |
| res = mtk_wdt_request_en_set(MTK_WDT_REQ_THERMAL_MARK, |
| WD_REQ_EN); |
| } else if (en == WD_REQ_DIS) { |
| res = mtk_wdt_request_en_set(MTK_WDT_REQ_THERMAL_MARK, |
| WD_REQ_DIS); |
| } else { |
| res = -2; |
| } |
| |
| if (mode == WD_REQ_IRQ_MODE) { |
| res = mtk_wdt_request_mode_set(MTK_WDT_REQ_THERMAL_MARK, |
| WD_REQ_IRQ_MODE); |
| } else if (mode == WD_REQ_RST_MODE) { |
| res = mtk_wdt_request_mode_set(MTK_WDT_REQ_THERMAL_MARK, |
| WD_REQ_RST_MODE); |
| } else { |
| res = -3; |
| } |
| return res; |
| } |
| |
| |
| static int wd_dram_reserved_mode(bool enabled) |
| { |
| int ret = 0; |
| |
| if (true == enabled) { |
| mtk_wdt_swsysret_config(0x10000000, 1); |
| mtk_rgu_dram_reserved(1); |
| } else { |
| mtk_wdt_swsysret_config(0x10000000, 0); |
| mtk_rgu_dram_reserved(0); |
| } |
| return ret; |
| } |
| |
| static int wd_mcu_cache_preserve(bool enabled) |
| { |
| int ret = 0; |
| |
| if (true == enabled) |
| mtk_rgu_mcu_cache_preserve(1); |
| else |
| mtk_rgu_mcu_cache_preserve(0); |
| |
| return ret; |
| } |
| |
| static int debug_key_eint_config(enum wk_req_en en, enum wk_req_mode mode) |
| { |
| int res = 0; |
| |
| pr_debug("%s(en:0x%x,mode:0x%x)\n", __func__, en, mode); |
| if (en == WD_REQ_EN) |
| res = mtk_wdt_request_en_set(MTK_WDT_REQ_EINT_MARK, |
| WD_REQ_EN); |
| else if (en == WD_REQ_DIS) |
| res = mtk_wdt_request_en_set(MTK_WDT_REQ_EINT_MARK, |
| WD_REQ_DIS); |
| else |
| res = -2; |
| |
| if (mode == WD_REQ_IRQ_MODE) |
| res = mtk_wdt_request_mode_set(MTK_WDT_REQ_EINT_MARK, |
| WD_REQ_IRQ_MODE); |
| else if (mode == WD_REQ_RST_MODE) |
| res = mtk_wdt_request_mode_set(MTK_WDT_REQ_EINT_MARK, |
| WD_REQ_RST_MODE); |
| else |
| res = -3; |
| return res; |
| } |
| |
| static int debug_key_sysrst_config(enum wk_req_en en, enum wk_req_mode mode) |
| { |
| int res = 0; |
| |
| pr_debug("%s(en:0x%x,mode:0x%x)\n", __func__, en, mode); |
| if (en == WD_REQ_EN) |
| res = mtk_wdt_request_en_set(MTK_WDT_REQ_SYSRST_MARK, |
| WD_REQ_EN); |
| else if (en == WD_REQ_DIS) |
| res = mtk_wdt_request_en_set(MTK_WDT_REQ_SYSRST_MARK, |
| WD_REQ_DIS); |
| else |
| res = -2; |
| |
| if (mode == WD_REQ_IRQ_MODE) |
| res = mtk_wdt_request_mode_set(MTK_WDT_REQ_SYSRST_MARK, |
| WD_REQ_IRQ_MODE); |
| else if (mode == WD_REQ_RST_MODE) |
| res = mtk_wdt_request_mode_set(MTK_WDT_REQ_SYSRST_MARK, |
| WD_REQ_RST_MODE); |
| else |
| res = -3; |
| return res; |
| } |
| |
| #else |
| /* dummy api */ |
| |
| static unsigned int wd_get_check_bit(void) |
| { |
| pr_debug("dummy %s", __func__); |
| return 0; |
| } |
| |
| static unsigned int wd_get_kick_bit(void) |
| { |
| pr_debug("dummy %s", __func__); |
| return 0; |
| } |
| |
| static int wd_restart(enum wd_restart_type type) |
| { |
| pr_debug("dummy %s", __func__); |
| return 0; |
| } |
| |
| |
| static int wd_cpu_hot_plug_on_notify(int cpu) |
| { |
| int res = 0; |
| |
| pr_debug("dummy %s", __func__); |
| return res; |
| } |
| |
| static int wd_cpu_hot_plug_off_notify(int cpu) |
| { |
| int res = 0; |
| |
| pr_debug("dummy %s", __func__); |
| return res; |
| } |
| |
| static int wd_sw_reset(int type) |
| { |
| pr_debug("dummy %s", __func__); |
| #ifndef CONFIG_MEDIATEK_WATCHDOG |
| wdt_arch_reset(type); |
| #endif |
| return 0; |
| } |
| |
| static int mtk_wk_wdt_config(enum ext_wdt_mode mode, int timeout_val) |
| { |
| |
| pr_debug("dummy %s", __func__); |
| return 0; |
| } |
| |
| static int disable_ext(void) |
| { |
| pr_debug("dummy %s", __func__); |
| return 0; |
| } |
| |
| static int disable_local(void) |
| { |
| pr_debug("dummy %s", __func__); |
| return 0; |
| } |
| |
| static int set_mode(enum ext_wdt_mode mode) |
| { |
| pr_debug("dummy %s", __func__); |
| return 0; |
| |
| } |
| |
| static int confirm_hwreboot(void) |
| { |
| pr_debug("dummy %s", __func__); |
| return 0; |
| } |
| |
| static void suspend_notify(void) |
| { |
| pr_debug("dummy %s", __func__); |
| } |
| |
| static void resume_notify(void) |
| { |
| |
| pr_debug("dummy %s", __func__); |
| |
| } |
| |
| static int disable_all_wd(void) |
| { |
| pr_debug("dummy %s", __func__); |
| return 0; |
| } |
| |
| static int spmwdt_mode_config(enum wk_req_en en, enum wk_req_mode mode) |
| { |
| int res = 0; |
| |
| pr_debug("dummy %s", __func__); |
| return res; |
| } |
| |
| static int thermal_mode_config(enum wk_req_en en, enum wk_req_mode mode) |
| { |
| int res = 0; |
| |
| pr_debug("dummy %s", __func__); |
| return res; |
| } |
| |
| static int wd_dram_reserved_mode(bool enabled) |
| { |
| int res = 0; |
| |
| pr_debug("dummy %s", __func__); |
| return res; |
| } |
| |
| static int wd_mcu_cache_preserve(bool enabled) |
| { |
| int res = 0; |
| |
| pr_debug("dummy %s", __func__); |
| return res; |
| } |
| |
| static int thermal_direct_mode_config(enum wk_req_en en, enum wk_req_mode mode) |
| { |
| int res = 0; |
| |
| pr_debug("thermal_direct_mode in dummy driver (en:0x%x,mode:0x%x)\n", |
| en, mode); |
| if (en == WD_REQ_EN) { |
| /* g_ext_wd_drv.reques_en_set(MTK_WDT_REQ_SPM_THERMAL_MARK, |
| * WD_REQ_EN); |
| */ |
| res = mtk_wdt_request_en_set(MTK_WDT_REQ_THERMAL_MARK, |
| WD_REQ_EN); |
| } else if (en == WD_REQ_DIS) { |
| /* g_ext_wd_drv.reques_en_set(MTK_WDT_REQ_SPM_THERMAL_MARK, |
| * WD_REQ_DIS); |
| */ |
| res = mtk_wdt_request_en_set(MTK_WDT_REQ_THERMAL_MARK, |
| WD_REQ_DIS); |
| } else { |
| res = -2; |
| } |
| |
| if (mode == WD_REQ_IRQ_MODE) { |
| /* g_ext_wd_drv.reques_mode_set(MTK_WDT_REQ_SPM_THERMAL_MARK, |
| * WD_REQ_IRQ_MODE); |
| */ |
| res = mtk_wdt_request_mode_set(MTK_WDT_REQ_THERMAL_MARK, |
| WD_REQ_IRQ_MODE); |
| } else if (mode == WD_REQ_RST_MODE) { |
| /* g_ext_wd_drv.reques_mode_set(MTK_WDT_REQ_SPM_THERMAL_MARK, |
| * WD_REQ_RST_MODE); |
| */ |
| res = mtk_wdt_request_mode_set(MTK_WDT_REQ_THERMAL_MARK, |
| WD_REQ_RST_MODE); |
| } else { |
| res = -3; |
| } |
| return res; |
| } |
| |
| static int debug_key_eint_config(enum wk_req_en en, enum wk_req_mode mode) |
| { |
| int res = 0; |
| |
| pr_debug("%s(en:0x%x,mode:0x%x)\n", __func__, en, mode); |
| if (en == WD_REQ_EN) |
| res = mtk_wdt_request_en_set(MTK_WDT_REQ_EINT_MARK, |
| WD_REQ_EN); |
| else if (en == WD_REQ_DIS) |
| res = mtk_wdt_request_en_set(MTK_WDT_REQ_EINT_MARK, |
| WD_REQ_DIS); |
| else |
| res = -2; |
| |
| if (mode == WD_REQ_IRQ_MODE) |
| res = mtk_wdt_request_mode_set(MTK_WDT_REQ_EINT_MARK, |
| WD_REQ_IRQ_MODE); |
| else if (mode == WD_REQ_RST_MODE) |
| res = mtk_wdt_request_mode_set(MTK_WDT_REQ_EINT_MARK, |
| WD_REQ_RST_MODE); |
| else |
| res = -3; |
| return res; |
| } |
| |
| static int debug_key_sysrst_config(enum wk_req_en en, enum wk_req_mode mode) |
| { |
| int res = 0; |
| |
| pr_debug("%s(en:0x%x,mode:0x%x)\n", __func__, en, mode); |
| if (en == WD_REQ_EN) |
| res = mtk_wdt_request_en_set(MTK_WDT_REQ_SYSRST_MARK, |
| WD_REQ_EN); |
| else if (en == WD_REQ_DIS) |
| res = mtk_wdt_request_en_set(MTK_WDT_REQ_SYSRST_MARK, |
| WD_REQ_DIS); |
| else |
| res = -2; |
| |
| if (mode == WD_REQ_IRQ_MODE) |
| res = mtk_wdt_request_mode_set(MTK_WDT_REQ_SYSRST_MARK, |
| WD_REQ_IRQ_MODE); |
| else if (mode == WD_REQ_RST_MODE) |
| res = mtk_wdt_request_mode_set(MTK_WDT_REQ_SYSRST_MARK, |
| WD_REQ_RST_MODE); |
| else |
| res = -3; |
| return res; |
| } |
| |
| #endif |
| |
| static int dfd_count_en(int value) |
| { |
| return mtk_wdt_dfd_count_en(value); |
| } |
| |
| static int dfd_thermal1_dis(int value) |
| { |
| return mtk_wdt_dfd_thermal1_dis(value); |
| } |
| |
| static int dfd_thermal2_dis(int value) |
| { |
| return mtk_wdt_dfd_thermal2_dis(value); |
| } |
| |
| static int dfd_timeout(int value) |
| { |
| return mtk_wdt_dfd_timeout(value); |
| } |
| |
| /* public interface implimentation end */ |
| |
| int wd_api_init(void) |
| { |
| |
| int i = 0; |
| long *check_p = NULL; |
| int api_size = 0; |
| |
| api_size = (sizeof(g_wd_api_obj) / sizeof(long)); |
| pr_debug("wd api_size=%d\n", api_size); |
| /* check wd api */ |
| check_p = (long *)&g_wd_api_obj; |
| for (i = 1; i < api_size; i++) { |
| pr_debug("p[%d]=%lx\n", i, *(check_p + i)); |
| if (check_p[i] == 0) { |
| pr_debug("wd_api init fail the %d api not init\n", i); |
| g_wd_api_obj.ready = 0; |
| return -1; |
| } |
| |
| } |
| pr_debug("wd_api init ok\n"); |
| return 0; |
| } |
| |
| int get_wd_api(struct wd_api **obj) |
| { |
| int res = 0; |
| *obj = &g_wd_api_obj; |
| if (*obj == NULL) |
| res = -1; |
| |
| if ((*obj)->ready == 0) |
| res = -2; |
| |
| return res; |
| } |
| |
| #ifndef CONFIG_MEDIATEK_WATCHDOG |
| /*register restart notify and own by debug start*/ |
| void arch_reset(char mode, const char *cmd) |
| { |
| #ifdef CONFIG_FPGA_EARLY_PORTING |
| return; |
| #else |
| char reboot = 0; |
| int res = 0; |
| struct wd_api *wd_api = NULL; |
| |
| res = get_wd_api(&wd_api); |
| pr_info("%s: cmd = %s\n", __func__, cmd ? : "NULL"); |
| dump_stack(); |
| if (console_trylock()) { |
| pr_notice("we can get console_sem\n"); |
| console_unlock(); |
| } else { |
| pr_notice("we cannot get console_sem\n"); |
| } |
| |
| if (cmd && !strcmp(cmd, "charger")) { |
| /* do nothing */ |
| } else if (cmd && !strcmp(cmd, "recovery")) { |
| rtc_mark_recovery(); |
| } else if (cmd && !strcmp(cmd, "bootloader")) { |
| rtc_mark_fast(); |
| } else if (cmd && !strcmp(cmd, "dm-verity device corrupted")) { |
| #ifdef CONFIG_MTK_SECURITY_SW_SUPPORT |
| res = masp_hal_set_dm_verity_error(); |
| #endif |
| reboot = WD_SW_RESET_BYPASS_PWR_KEY; |
| } else if (cmd && !strcmp(cmd, "kpoc")) { |
| rtc_mark_kpoc(); |
| #ifdef VENDOR_EDIT |
| /* Bin.Li@EXP.BSP.bootloader.bootflow, 2017/05/24,, Add for reboot kernel panic mode */ |
| }else if (cmd && !strcmp(cmd, "silence")) { |
| oppo_rtc_mark_silence(); |
| reboot = 1; |
| }else if (cmd && !strcmp(cmd, "sau")) { |
| oppo_rtc_mark_sau(); |
| }else if (cmd && !strcmp(cmd, "meta")) { |
| oppo_rtc_mark_meta(); |
| } else if (cmd && !strcmp(cmd, "ftm")) { |
| oppo_rtc_mark_factory(); |
| } else if (cmd && !strcmp(cmd, "safe")) { |
| oppo_rtc_mark_safe(); |
| //xiaofan.yang@PSW.TECH.AgingTest, 2019/09/09,Add for factory agingtest |
| #ifdef OPLUS_FEATURE_AGINGTEST |
| } else if (cmd && (!strcmp(cmd, "sblmemtest") || !strcmp(cmd, "usermemaging"))) { |
| oppo_rtc_mark_agingtest(); |
| #endif /*OPLUS_FEATURE_AGINGTEST */ |
| #endif |
| } else { |
| reboot = WD_SW_RESET_BYPASS_PWR_KEY; |
| } |
| |
| if (cmd && !strcmp(cmd, "ddr-reserve")) |
| reboot |= WD_SW_RESET_KEEP_DDR_RESERVE; |
| |
| if (res) { |
| pr_notice("%s, get wd api error %d\n", __func__, res); |
| } else { |
| /* disable dfd count in normal reboot */ |
| if (!(reboot & WD_SW_RESET_KEEP_DDR_RESERVE)) |
| wd_api->wd_dfd_count_en(0); |
| wd_api->wd_sw_reset(reboot); |
| } |
| #endif |
| } |
| static struct notifier_block mtk_restart_handler; |
| static int mtk_arch_reset_handle(struct notifier_block *this, |
| unsigned long mode, void *cmd) |
| { |
| pr_info("ARCH_RESET happen!!!\n"); |
| arch_reset(mode, cmd); |
| pr_info("ARCH_RESET end!!!!\n"); |
| return NOTIFY_DONE; |
| } |
| |
| static int __init mtk_arch_reset_init(void) |
| { |
| int ret; |
| |
| arm_pm_restart = NULL; |
| mtk_restart_handler.notifier_call = mtk_arch_reset_handle; |
| mtk_restart_handler.priority = 128; |
| pr_info("\n register_restart_handler- 0x%p, Notify call: - 0x%p\n", |
| &mtk_restart_handler, mtk_restart_handler.notifier_call); |
| ret = register_restart_handler(&mtk_restart_handler); |
| if (ret) |
| pr_notice("ARCH_RESET cannot register mtk_restart_handler!!!!\n"); |
| pr_info("ARCH_RESET register mtk_restart_handler ok!!!!\n"); |
| return ret; |
| } |
| |
| pure_initcall(mtk_arch_reset_init); |
| /*register restart notify and own by debug end*/ |
| #endif |