s32 invoke_reset_cb(DRV_RESET_CALLCBFUN_MOMENT stage) { struct reset_cb_list *p = g_modem_reset_ctrl.list_head; s32 ret = RESET_ERROR; reset_print_debug("(%d) @reset %d\n", ++g_reset_debug.main_stage, (u32)stage); /*根据回调函数优先级,调用回调函数*/ while (NULL != p) { if (NULL != p->cb_info.cbfun) { reset_print_debug("%s callback invoked\n", p->cb_info.name); ret = p->cb_info.cbfun(stage, p->cb_info.userdata); if (RESET_OK != ret) { reset_print_err("fail to run cbfunc of %s, at stage%d return %d\n", p->cb_info.name, stage, ret); return RESET_ERROR; } } p = p->next; } return RESET_OK; }
s32 wait_for_ccore_reset_done(u32 timeout) { reset_print_debug("(%d) waiting the reply from modem A9\n", ++g_reset_debug.main_stage); if (osl_sem_downtimeout(&(g_modem_reset_ctrl.wait_ccore_reset_ok_sem), msecs_to_jiffies(timeout)))/*lint !e713 */ { reset_print_err("Get response from ccore reset timeout within %d\n", timeout); return RESET_ERROR; } reset_print_debug("(%d) has received the reply from modem A9\n", ++g_reset_debug.main_stage); return RESET_OK; }
void let_modem_master_in_idle(void) { u32 regval = 0; /* nmi开关 */ regval = readl((volatile const void *)(g_modem_reset_ctrl.crg_base + 0x12c)); reset_print_debug("org ccore nmi regval[%p]=0x%x\n", (g_modem_reset_ctrl.crg_base + 0x12c), regval); regval &= (~((u32)1 << 12)); writel(regval,(volatile void *)(g_modem_reset_ctrl.crg_base + 0x12c)); regval = readl((volatile const void *)(g_modem_reset_ctrl.crg_base + 0x12c)); reset_print_debug("(%d) ccore nmi regval: 0x%x\n", ++g_reset_debug.main_stage, regval); return; }
s32 reset_prepare(enum MODEM_ACTION action) { unsigned long flags = 0; u32 current_action = (u32)action; u32 global_action = g_modem_reset_ctrl.modem_action; if (current_action == global_action) { return RESET_OK; } else if ((u32)MODEM_NORMAL != global_action) { reset_print_err("action(%d) is doing, abundon action(%d)\n", global_action, action); return RESET_ERROR; } g_reset_debug.main_stage = 0; wake_lock(&(g_modem_reset_ctrl.wake_lock)); reset_print_debug("(%d) wake_lock\n", ++g_reset_debug.main_stage); spin_lock_irqsave(&g_modem_reset_ctrl.action_lock, flags); g_modem_reset_ctrl.modem_action = action; spin_unlock_irqrestore(&g_modem_reset_ctrl.action_lock, flags); if ((MODEM_POWER_OFF == current_action) || (MODEM_RESET == current_action)) { ccore_ipc_disable(); } osl_sem_up(&(g_modem_reset_ctrl.task_sem)); return RESET_OK; }
void bsp_modem_power_on(void) { reset_print_debug("\n");; if (g_modem_reset_ctrl.nv_config.is_feature_on) { queue_work(g_modem_reset_ctrl.reset_wq, &(g_modem_reset_ctrl.work_power_on)); } else { reset_print_err("reset fearute is off\n"); } }
void modem_power_on_do_work(struct work_struct *work) { reset_print_debug("\n"); if (1 == g_modem_reset_ctrl.in_suspend_state) { if (!wait_for_completion_timeout(&(g_modem_reset_ctrl.suspend_completion), HZ*10)) { machine_restart("system halt"); return; } } reset_prepare(MODEM_POWER_ON); }
int bsp_modem_reset(void) { reset_print_debug("\n"); if (g_modem_reset_ctrl.nv_config.is_feature_on) { queue_work(g_modem_reset_ctrl.reset_wq, &(g_modem_reset_ctrl.work_reset)); return 0; } else { reset_print_err("reset fearute is off\n"); return -1; } }
void modem_reset_do_work(struct work_struct *work) { reset_print_debug("\n"); g_modem_reset_ctrl.exec_time = bsp_get_slice_value(); if (1 == g_modem_reset_ctrl.in_suspend_state) { if (!wait_for_completion_timeout(&(g_modem_reset_ctrl.suspend_completion), HZ*10)) { machine_restart("system halt"); /* 调systemError */ return; } } reset_prepare(MODEM_RESET); }
int modem_reset_task(void *arg) { u16 action = 0; unsigned long flags = 0; for( ; ;) { osl_sem_down(&(g_modem_reset_ctrl.task_sem)); action = (u16)g_modem_reset_ctrl.modem_action; reset_print_debug("(%d)has taken task_sem, action=%d\n", ++g_reset_debug.main_stage, action); if (MODEM_POWER_OFF == action) { (void)do_power_off(action); } else if (MODEM_POWER_ON == action) { (void)do_power_on(action); } else if (MODEM_RESET == action) { (void)do_reset(action); reset_print_err("reset count: %d\n", ++g_modem_reset_ctrl.reset_cnt); } if (action == g_modem_reset_ctrl.modem_action) { spin_lock_irqsave(&g_modem_reset_ctrl.action_lock, flags); g_modem_reset_ctrl.modem_action = MODEM_NORMAL; spin_unlock_irqrestore(&g_modem_reset_ctrl.action_lock, flags); } wake_unlock(&(g_modem_reset_ctrl.wake_lock)); g_modem_reset_ctrl.exec_time = get_timer_slice_delta(g_modem_reset_ctrl.exec_time, bsp_get_slice_value()); reset_print_debug("execute done, elapse time %d\n", g_modem_reset_ctrl.exec_time); } }
void from_hifi_mailbox_readcb(void *usr_handle, void *mail_handle, unsigned int mail_len)/*lint !e438 */ { unsigned long ret = 0; unsigned int msg_len = (unsigned int)sizeof(HIFI_AP_CCPU_RESET_CNF_STRU); HIFI_AP_CCPU_RESET_CNF_STRU msg_hifi = {0}; ret = DRV_MAILBOX_READMAILDATA(mail_handle, (unsigned char *)(&msg_hifi), &msg_len); reset_print_debug("ret=%lu, uhwMsgId=%d, uhwResult=%d\n", ret, msg_hifi.uhwMsgId, msg_hifi.uhwResult); if (ID_HIFI_AP_CCPU_RESET_CNF == msg_hifi.uhwMsgId && 0 == msg_hifi.uhwResult) { up(&(g_modem_reset_ctrl.wait_hifi_reply_sem)); } else { up(&(g_modem_reset_ctrl.wait_hifi_reply_sem)); reset_print_err("unkown msg from hifi\n"); reset_reboot_system(RESET_TYPE_RECV_HIFI_MSG_FAIL); } }
s32 send_msg_to_hifi(DRV_RESET_CALLCBFUN_MOMENT stage) { s32 ret = RESET_ERROR; AP_HIFI_CCPU_RESET_REQ_STRU hifi_mailbox = {0}; reset_print_debug("(%d) stage%d,ID_AP_HIFI_CCPU_RESET_REQ=%d\n", ++g_reset_debug.main_stage, (s32)stage, (s32)ID_AP_HIFI_CCPU_RESET_REQ); if (DRV_RESET_CALLCBFUN_RESET_BEFORE == stage) { /*消息ID*/ hifi_mailbox.uhwMsgId = ID_AP_HIFI_CCPU_RESET_REQ; ret = DRV_MAILBOX_SENDMAIL(MAILBOX_MAILCODE_ACPU_TO_HIFI_CCORE_RESET_ID, (void *)(&hifi_mailbox), sizeof(hifi_mailbox)); /*lint !e713 */ if(MAILBOX_OK != ret) { reset_print_err("fail to send msg to hifi\n"); return RESET_ERROR; } } /* 如果有必要,其他阶段也通知hifi */ return RESET_OK; }
s32 load_modem_image(void) { s32 ret = SEC_ERROR; reset_print_debug("(%d) vxworks & dsp image is loading...\n", ++g_reset_debug.main_stage); ret = bsp_load_modem(); if(ret) { sec_print_err("vxworks fail\n"); return SEC_ERROR; } ret = bsp_load_modem_dsp(); if(ret) { sec_print_err("dsp fail\n"); return SEC_ERROR; } return SEC_OK; }
void reset_ipc_isr_reboot(u32 data) { reset_print_debug("\n"); osl_sem_up(&(g_modem_reset_ctrl.wait_ccore_reset_ok_sem)); }
void reset_ipc_isr_idle(u32 data) { reset_print_debug("\n"); osl_sem_up(&(g_modem_reset_ctrl.wait_modem_master_in_idle_sem)); }
s32 do_power_on(u16 action) { u32 msg = 0; s32 ret = RESET_ERROR; u32 ack_val = 0xff; u32 i; /* C核和dsp镜像加载 */ /* 如出现错误,重试3次,直至每次都错误,则复位系统 */ for (i=0; i<RESET_RETRY_TIMES; i++) { ret = load_modem_image(); if (ret == 0) break; else reset_print_err("Retry %d times to load modem image also failed\n", i); } if(ret < 0) { reset_reboot_system(RESET_TYPE_LOAD_MODEM_IMG_FAIL); return RESET_ERROR; } /* 清除C核dump区域 */ rdr_modem_reset_dumpmem(); /* 通知m3进行A9解复位及相关处理 */ msg = RESET_INFO_MAKEUP(action, (u32)DRV_RESET_CALLCBFUN_RESETING); /*lint !e701 */ ret = RESET_ERROR; ret = send_sync_msg_to_mcore(msg, &ack_val); if(ret) { reset_print_err("send_sync_msg_to_mcore(0x%x) at resting stage fail!\n", ret); reset_reboot_system(RESET_TYPE_SEND_MSG2_M3_FAIL_RESTING); return RESET_ERROR; } else if(RESET_MCORE_RESETING_OK != ack_val) { reset_print_err("modem unreset fail on m3, ack_val=0x%x, %s\n", ack_val, lpm3_err[ack_val-RESET_MCORE_BEFORE_AP_TO_MDM_BUS_ERR]); reset_reboot_system(RESET_TYPE_RECV_WRONG_MSG_FROM_M3_RESTING); return RESET_ERROR; } reset_print_debug("(%d) at reseting stage has communicated with lpm3 succeed\n", ++g_reset_debug.main_stage); /* 复位中相关处理:与C核需要交互的模块在此阶段准备好 */ if ((MODEM_POWER_ON == action) || (MODEM_RESET == action)) { ccore_ipc_enable(); } ret = drv_reset_cb(DRV_RESET_CALLCBFUN_RESETING, 0); if(ret < 0) { reset_reboot_system(RESET_TYPE_CB_INVOKE_RESTING); return RESET_ERROR; } ret = wait_for_ccore_reset_done(RESET_WAIT_CCPU_STARTUP_TIMEOUT); if(ret < 0) { reset_reboot_system(RESET_TYPE_WAIT_CCORE_RELAY_TIMEOUT); return RESET_ERROR; } /* 复位后相关处理 */ ret = invoke_reset_cb(DRV_RESET_CALLCBFUN_RESET_AFTER); if(ret < 0) { reset_reboot_system(RESET_TYPE_CB_INVOKE_AFTER); return RESET_ERROR; } /* 复位后通知M3进行相关处理 */ msg = RESET_INFO_MAKEUP(action, DRV_RESET_CALLCBFUN_RESET_AFTER); /*lint !e701 */ ret = RESET_ERROR; ret = send_sync_msg_to_mcore(msg, &ack_val); if(ret) { reset_print_err("send_sync_msg_to_mcore(0x%x) after reset stage fail!\n", ret); reset_reboot_system(RESET_TYPE_SEND_MSG2_M3_FAIL_AFTER); return RESET_ERROR; } else if(RESET_MCORE_AFTER_RESET_OK != ack_val) { reset_print_err("after reset handle failed on m3, ack_val=0x%x, fail!\n", ack_val); reset_reboot_system(RESET_TYPE_RECV_WRONG_MSG_FROM_M3_AFTER); return RESET_ERROR; } reset_print_debug("(%d) after reset stage has communicated with lpm3 succeed\n", ++g_reset_debug.main_stage); /* 将启动模式置回普通模式 */ bsp_reset_bootflag_set(CCORE_BOOT_NORMAL); return RESET_OK; }
s32 do_power_off(u16 action) { u32 msg = 0; s32 ret = RESET_ERROR; u32 ack_val = 0xff; /* 设置启动模式为C核单独复位 */ bsp_reset_bootflag_set(CCORE_IS_REBOOT); g_modem_reset_ctrl.boot_mode = readl((volatile const void *)SCBAKDATA13); reset_print_debug("(%d) set boot mode:0x%x\n", ++g_reset_debug.main_stage, g_modem_reset_ctrl.boot_mode); /* 唤醒ccore */ ret = bsp_ipc_int_send(IPC_CORE_CCORE, g_modem_reset_ctrl.ipc_send_irq_wakeup_ccore); if(ret != 0) { reset_print_err("wakeup ccore failt\n"); } /* 复位前各组件回调 */ ret = invoke_reset_cb(DRV_RESET_CALLCBFUN_RESET_BEFORE); if(ret < 0) { reset_reboot_system(RESET_TYPE_CB_INVOKE_BEFORE); return RESET_ERROR; } /* 阻止核间通信 */ ccore_msg_switch_off(g_modem_reset_ctrl.multicore_msg_switch, CCORE_STATUS); reset_print_debug("(%d) switch off msg connect:%d\n", ++g_reset_debug.main_stage, g_modem_reset_ctrl.multicore_msg_switch); /* 通知hifi,停止与modem交互 */ ret = send_msg_to_hifi(DRV_RESET_CALLCBFUN_RESET_BEFORE); if(ret < 0) { reset_print_err("send_msg_to_hifi=0x%x fail\n", ret); reset_reboot_system(RESET_TYPE_SEND_MSG2_M3_FAIL_BEFORE); return RESET_ERROR; } /* 等待hifi处理完成 */ if (osl_sem_downtimeout(&(g_modem_reset_ctrl.wait_hifi_reply_sem), msecs_to_jiffies((u32)RESET_WAIT_RESP_TIMEOUT)))/*lint !e713 */ { reset_print_err("waiting the reply from hifi timeout(%d), but not reboot system!\n", RESET_WAIT_RESP_TIMEOUT); } reset_print_debug("(%d) has received the reply from hifi\n", ++g_reset_debug.main_stage); /* 通知modem master进idle态,并等待ccore回复 */ let_modem_master_in_idle(); ret = osl_sem_downtimeout(&(g_modem_reset_ctrl.wait_modem_master_in_idle_sem), msecs_to_jiffies(RESET_WAIT_MODEM_IN_IDLE_TIMEOUT));/*lint !e713 */ if (ret) { reset_print_debug("(%d) let modem master in idle timeout\n", ++g_reset_debug.main_stage); master_in_idle_timestamp_dump(); } else { reset_print_debug("(%d) let modem master in idle successfully\n", ++g_reset_debug.main_stage); } /* 通知m3进行复位前辅助处理 */ msg = RESET_INFO_MAKEUP(action, DRV_RESET_CALLCBFUN_RESET_BEFORE); /*lint !e701 */ ret = RESET_ERROR; /* 复位解复位modem子系统期间不接收ipc消息 */ disable_ipc_irq(); ret = send_sync_msg_to_mcore(msg, &ack_val); if(ret) { reset_print_err("send_sync_msg_to_mcore(0x%x) before reset fail!\n", ret); reset_reboot_system(RESET_TYPE_SEND_MSG2_M3_FAIL_BEFORE); return RESET_ERROR; } else if(RESET_MCORE_BEFORE_RESET_OK != ack_val) { reset_print_err("bus error probed on m3, ack_val=0x%x, %s\n!\n", ack_val, lpm3_err[ack_val-RESET_MCORE_BEFORE_AP_TO_MDM_BUS_ERR]); reset_reboot_system(RESET_TYPE_SEND_MSG2_M3_FAIL_BEFORE); return RESET_ERROR; } enable_ipc_irq(); reset_print_debug("(%d) before reset stage has communicated with lpm3 succeed\n", ++g_reset_debug.main_stage); return RESET_OK; }