| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618 |
- #include <linux/kernel.h>
- #include <ext_wd_drv.h>
- #include <mach/wd_api.h>
- #include <linux/smp.h>
- /*add by debug for register restart notify*/
- #include <linux/notifier.h>
- #include <linux/reboot.h>
- #include <mt-plat/mt_reboot.h>
- #include <mt-plat/mtk_rtc.h>
- 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(WD_REQ_CTL en, WD_REQ_MODE mode);
- static int thermal_mode_config(WD_REQ_CTL en, WD_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 thermal_direct_mode_config(WD_REQ_CTL en, WD_REQ_MODE mode);
- static int debug_key_eint_config(WD_REQ_CTL en, WD_REQ_MODE mode);
- static int debug_key_sysrst_config(WD_REQ_CTL en, WD_REQ_MODE mode);
- static struct wd_api g_wd_api_obj = {
- .ready = 1,
- .wd_cpu_hot_plug_on_notify = wd_cpu_hot_plug_on_notify, /* for cpu hot plug */
- .wd_cpu_hot_plug_off_notify = wd_cpu_hot_plug_off_notify, /* for cpu hot plug */
- .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_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,
- };
- /* 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_alert("WD wd_cpu_hot_plug_on_notify kick ext wd\n");
- 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 disable_local not support now\n");
- 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(WD_REQ_CTL en, WD_REQ_MODE mode)
- {
- int res = 0;
- if (WD_REQ_EN == en) {
- /* g_ext_wd_drv.reques_en_set(MTK_WDT_REQ_SPM_SCPSYS_MARK,WD_REQ_EN); */
- res = mtk_wdt_request_en_set(MTK_WDT_REQ_SPM_SCPSYS_MARK, WD_REQ_EN);
- } else if (WD_REQ_DIS == en) {
- /* g_ext_wd_drv.reques_en_set(MTK_WDT_REQ_SPM_SCPSYS_MARK,WD_REQ_DIS); */
- res = mtk_wdt_request_en_set(MTK_WDT_REQ_SPM_SCPSYS_MARK, WD_REQ_DIS);
- } else {
- res = -2;
- }
- if (WD_REQ_IRQ_MODE == mode) {
- res = mtk_wdt_request_mode_set(MTK_WDT_REQ_SPM_SCPSYS_MARK, WD_REQ_IRQ_MODE);
- /* g_ext_wd_drv.reques_mode_set(MTK_WDT_REQ_SPM_SCPSYS_MARK,WD_REQ_IRQ_MODE); */
- } else if (WD_REQ_RST_MODE == mode) {
- res = mtk_wdt_request_mode_set(MTK_WDT_REQ_SPM_SCPSYS_MARK, WD_REQ_RST_MODE);
- /* g_ext_wd_drv.reques_mode_set(MTK_WDT_REQ_SPM_SCPSYS_MARK,WD_REQ_RST_MODE); */
- } else {
- res = -3;
- }
- return res;
- }
- static int thermal_mode_config(WD_REQ_CTL en, WD_REQ_MODE mode)
- {
- int res = 0;
- if (WD_REQ_EN == 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_SPM_THERMAL_MARK, WD_REQ_EN);
- } else if (WD_REQ_DIS == en) {
- /* 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_SPM_THERMAL_MARK, WD_REQ_DIS);
- } else {
- res = -2;
- }
- if (WD_REQ_IRQ_MODE == 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_SPM_THERMAL_MARK, WD_REQ_IRQ_MODE);
- } else if (WD_REQ_RST_MODE == 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_SPM_THERMAL_MARK, WD_REQ_RST_MODE);
- } else {
- res = -3;
- }
- return res;
- }
- static int thermal_direct_mode_config(WD_REQ_CTL en, WD_REQ_MODE mode)
- {
- int res = 0;
- pr_debug("thermal_direct_mode_config(en:0x%x,mode:0x%x)\n", en, mode);
- if (WD_REQ_EN == 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 (WD_REQ_DIS == en) {
- /* 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 (WD_REQ_IRQ_MODE == 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 (WD_REQ_RST_MODE == 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 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 debug_key_eint_config(WD_REQ_CTL en, WD_REQ_MODE mode)
- {
- int res = 0;
- pr_debug("debug_key_eint_config(en:0x%x,mode:0x%x)\n", en, mode);
- if (WD_REQ_EN == en)
- res = mtk_wdt_request_en_set(MTK_WDT_REQ_EINT_MARK, WD_REQ_EN);
- else if (WD_REQ_DIS == en)
- res = mtk_wdt_request_en_set(MTK_WDT_REQ_EINT_MARK, WD_REQ_DIS);
- else
- res = -2;
- if (WD_REQ_IRQ_MODE == mode)
- res = mtk_wdt_request_mode_set(MTK_WDT_REQ_EINT_MARK, WD_REQ_IRQ_MODE);
- else if (WD_REQ_RST_MODE == 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(WD_REQ_CTL en, WD_REQ_MODE mode)
- {
- int res = 0;
- pr_debug("debug_key_sysrst_config(en:0x%x,mode:0x%x)\n", en, mode);
- if (WD_REQ_EN == en)
- res = mtk_wdt_request_en_set(MTK_WDT_REQ_SYSRST_MARK, WD_REQ_EN);
- else if (WD_REQ_DIS == en)
- res = mtk_wdt_request_en_set(MTK_WDT_REQ_SYSRST_MARK, WD_REQ_DIS);
- else
- res = -2;
- if (WD_REQ_IRQ_MODE == mode)
- res = mtk_wdt_request_mode_set(MTK_WDT_REQ_SYSRST_MARK, WD_REQ_IRQ_MODE);
- else if (WD_REQ_RST_MODE == 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 wd_get_check_bit");
- return 0;
- }
- static unsigned int wd_get_kick_bit(void)
- {
- pr_debug("dummy wd_get_kick_bit");
- return 0;
- }
- static int wd_restart(enum wd_restart_type type)
- {
- pr_debug("dummy wd_restart");
- return 0;
- }
- static int wd_cpu_hot_plug_on_notify(int cpu)
- {
- int res = 0;
- pr_debug("dummy wd_cpu_hot_plug_on_notify");
- return res;
- }
- static int wd_cpu_hot_plug_off_notify(int cpu)
- {
- int res = 0;
- pr_debug("dummy wd_cpu_hot_plug_off_notify");
- return res;
- }
- static int wd_sw_reset(int type)
- {
- pr_debug("dummy wd_sw_reset");
- wdt_arch_reset(type);
- return 0;
- }
- static int mtk_wk_wdt_config(enum ext_wdt_mode mode, int timeout_val)
- {
- pr_debug("dummy mtk_wk_wdt_config");
- return 0;
- }
- static int disable_ext(void)
- {
- pr_debug("dummy disable_ext");
- return 0;
- }
- static int disable_local(void)
- {
- pr_debug("dummy disable_local");
- return 0;
- }
- static int set_mode(enum ext_wdt_mode mode)
- {
- pr_debug("dummy set_mode");
- return 0;
- }
- static int confirm_hwreboot(void)
- {
- pr_debug("dummy confirm_hwreboot");
- return 0;
- }
- static void suspend_notify(void)
- {
- pr_debug("dummy suspend_notify\n");
- }
- static void resume_notify(void)
- {
- pr_debug("dummy resume_notify\n");
- }
- static int disable_all_wd(void)
- {
- pr_debug("dummy disable_all_wd\n");
- return 0;
- }
- static int spmwdt_mode_config(WD_REQ_CTL en, WD_REQ_MODE mode)
- {
- int res = 0;
- pr_debug("dummy spmwdt_mode_config\n");
- return res;
- }
- static int thermal_mode_config(WD_REQ_CTL en, WD_REQ_MODE mode)
- {
- int res = 0;
- pr_debug("dummy thermal_mode_config\n");
- return res;
- }
- static int wd_dram_reserved_mode(bool enabled)
- {
- int res = 0;
- pr_debug("dummy wd_dram_reserved_mode\n");
- return res;
- }
- static int thermal_direct_mode_config(WD_REQ_CTL en, WD_REQ_MODE mode)
- {
- int res = 0;
- pr_debug("thermal_direct_mode_config in dummy driver (en:0x%x,mode:0x%x)\n", en, mode);
- if (WD_REQ_EN == 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 (WD_REQ_DIS == en) {
- /* 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 (WD_REQ_IRQ_MODE == 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 (WD_REQ_RST_MODE == 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(WD_REQ_CTL en, WD_REQ_MODE mode)
- {
- int res = 0;
- pr_debug("debug_key_eint_config(en:0x%x,mode:0x%x)\n", en, mode);
- if (WD_REQ_EN == en)
- res = mtk_wdt_request_en_set(MTK_WDT_REQ_EINT_MARK, WD_REQ_EN);
- else if (WD_REQ_DIS == en)
- res = mtk_wdt_request_en_set(MTK_WDT_REQ_EINT_MARK, WD_REQ_DIS);
- else
- res = -2;
- if (WD_REQ_IRQ_MODE == mode)
- res = mtk_wdt_request_mode_set(MTK_WDT_REQ_EINT_MARK, WD_REQ_IRQ_MODE);
- else if (WD_REQ_RST_MODE == 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(WD_REQ_CTL en, WD_REQ_MODE mode)
- {
- int res = 0;
- pr_debug("debug_key_sysrst_config(en:0x%x,mode:0x%x)\n", en, mode);
- if (WD_REQ_EN == en)
- res = mtk_wdt_request_en_set(MTK_WDT_REQ_SYSRST_MARK, WD_REQ_EN);
- else if (WD_REQ_DIS == en)
- res = mtk_wdt_request_en_set(MTK_WDT_REQ_SYSRST_MARK, WD_REQ_DIS);
- else
- res = -2;
- if (WD_REQ_IRQ_MODE == mode)
- res = mtk_wdt_request_mode_set(MTK_WDT_REQ_SYSRST_MARK, WD_REQ_IRQ_MODE);
- else if (WD_REQ_RST_MODE == mode)
- res = mtk_wdt_request_mode_set(MTK_WDT_REQ_SYSRST_MARK, WD_REQ_RST_MODE);
- else
- res = -3;
- return res;
- }
- #endif
- /* 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 (0 == check_p[i]) {
- 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 (NULL == *obj) {
- res = -1;
- }
- if ((*obj)->ready == 0) {
- res = -2;
- }
- return res;
- }
- /*register restart notify and own by debug start-------
- *
- */
- void arch_reset(char mode, const char *cmd)
- {
- char reboot = 1;
- int res = 0;
- struct wd_api *wd_api = NULL;
- #ifdef CONFIG_FPGA_EARLY_PORTING
- return;
- #else
- res = get_wd_api(&wd_api);
- pr_alert("arch_reset: cmd = %s\n", cmd ? : "NULL");
- dump_stack();
- 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, "kpoc")) {
- #ifdef CONFIG_MTK_KERNEL_POWER_OFF_CHARGING
- rtc_mark_kpoc();
- #endif
- } else {
- reboot = 1;
- }
- if (res)
- pr_err("arch_reset, get wd api error %d\n", res);
- else
- 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_alert("ARCH_RESET happen!!!\n");
- arch_reset(mode, cmd);
- pr_alert("ARCH_RESET end!!!!\n");
- return NOTIFY_DONE;
- }
- static int __init mtk_arch_reset_init(void)
- {
- int ret;
- mtk_restart_handler.notifier_call = mtk_arch_reset_handle;
- mtk_restart_handler.priority = 128;
- pr_alert("\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_err("ARCH_RESET cannot register mtk_restart_handler!!!!\n");
- pr_alert("ARCH_RESET register mtk_restart_handler ok!!!!\n");
- return ret;
- }
- pure_initcall(mtk_arch_reset_init);
- /*register restart notify and own by debug end+++++
- *
- */
|