diff options
Diffstat (limited to 'drivers/net/wwan/t7xx/t7xx_state_monitor.c')
-rw-r--r-- | drivers/net/wwan/t7xx/t7xx_state_monitor.c | 109 |
1 files changed, 97 insertions, 12 deletions
diff --git a/drivers/net/wwan/t7xx/t7xx_state_monitor.c b/drivers/net/wwan/t7xx/t7xx_state_monitor.c index 80edb8e75a6a..c1789a558c9d 100644 --- a/drivers/net/wwan/t7xx/t7xx_state_monitor.c +++ b/drivers/net/wwan/t7xx/t7xx_state_monitor.c @@ -47,6 +47,10 @@ #define FSM_MD_EX_PASS_TIMEOUT_MS 45000 #define FSM_CMD_TIMEOUT_MS 2000 +/* As per MTK, AP to MD Handshake time is ~15s*/ +#define DEVICE_STAGE_POLL_INTERVAL_MS 100 +#define DEVICE_STAGE_POLL_COUNT 150 + void t7xx_fsm_notifier_register(struct t7xx_modem *md, struct t7xx_fsm_notifier *notifier) { struct t7xx_fsm_ctl *ctl = md->fsm_ctl; @@ -206,6 +210,46 @@ static void fsm_routine_exception(struct t7xx_fsm_ctl *ctl, struct t7xx_fsm_comm fsm_finish_command(ctl, cmd, 0); } +static void t7xx_lk_stage_event_handling(struct t7xx_fsm_ctl *ctl, unsigned int dev_status) +{ + struct t7xx_modem *md = ctl->md; + struct cldma_ctrl *md_ctrl; + enum lk_event_id lk_event; + struct t7xx_port *port; + struct device *dev; + + dev = &md->t7xx_dev->pdev->dev; + lk_event = FIELD_GET(LK_EVENT_MASK, dev_status); + dev_info(dev, "Device enter next stage from LK stage/n"); + switch (lk_event) { + case LK_EVENT_NORMAL: + break; + + case LK_EVENT_CREATE_PD_PORT: + md_ctrl = md->md_ctrl[CLDMA_ID_AP]; + t7xx_cldma_hif_hw_init(md_ctrl); + t7xx_cldma_stop(md_ctrl); + t7xx_cldma_switch_cfg(md_ctrl, CLDMA_DEDICATED_Q_CFG); + dev_info(dev, "creating the ttyDUMP port\n"); + port = t7xx_port_proxy_get_port_by_name(md->port_prox, "ttyDUMP"); + if (!port) { + dev_err(dev, "ttyDUMP port not found\n"); + return; + } + + port->port_conf->ops->enable_chl(port); + t7xx_cldma_start(md_ctrl); + break; + + case LK_EVENT_RESET: + break; + + default: + dev_err(dev, "Invalid BROM event\n"); + break; + } +} + static int fsm_stopped_handler(struct t7xx_fsm_ctl *ctl) { ctl->curr_state = FSM_STATE_STOPPED; @@ -317,8 +361,10 @@ static int fsm_routine_starting(struct t7xx_fsm_ctl *ctl) static void fsm_routine_start(struct t7xx_fsm_ctl *ctl, struct t7xx_fsm_command *cmd) { struct t7xx_modem *md = ctl->md; + unsigned int device_stage; + struct device *dev; u32 dev_status; - int ret; + int ret = 0; if (!md) return; @@ -329,23 +375,60 @@ static void fsm_routine_start(struct t7xx_fsm_ctl *ctl, struct t7xx_fsm_command return; } + dev = &md->t7xx_dev->pdev->dev; + dev_status = ioread32(IREG_BASE(md->t7xx_dev) + T7XX_PCIE_MISC_DEV_STATUS); + dev_status &= MISC_DEV_STATUS_MASK; + dev_dbg(dev, "dev_status = %x modem state = %d\n", dev_status, ctl->md_state); + + if (dev_status == MISC_DEV_STATUS_MASK) { + dev_err(dev, "invalid device status\n"); + ret = -EINVAL; + goto finish_command; + } + ctl->curr_state = FSM_STATE_PRE_START; t7xx_md_event_notify(md, FSM_PRE_START); - ret = read_poll_timeout(ioread32, dev_status, - (dev_status & MISC_STAGE_MASK) == LINUX_STAGE, 20000, 2000000, - false, IREG_BASE(md->t7xx_dev) + T7XX_PCIE_MISC_DEV_STATUS); - if (ret) { - struct device *dev = &md->t7xx_dev->pdev->dev; + device_stage = FIELD_GET(MISC_STAGE_MASK, dev_status); + if (dev_status == ctl->prev_dev_status) { + if (ctl->device_stage_check_cnt++ >= DEVICE_STAGE_POLL_COUNT) { + dev_err(dev, "Timeout at device stage 0x%x\n", device_stage); + ctl->device_stage_check_cnt = 0; + ret = -ETIMEDOUT; + } else { + msleep(DEVICE_STAGE_POLL_INTERVAL_MS); + ret = t7xx_fsm_append_cmd(ctl, FSM_CMD_START, 0); + } - fsm_finish_command(ctl, cmd, -ETIMEDOUT); - dev_err(dev, "Invalid device status 0x%lx\n", dev_status & MISC_STAGE_MASK); - return; + goto finish_command; + } + + switch (device_stage) { + case INIT_STAGE: + case PRE_BROM_STAGE: + case POST_BROM_STAGE: + ret = t7xx_fsm_append_cmd(ctl, FSM_CMD_START, 0); + break; + + case LK_STAGE: + dev_info(dev, "LK_STAGE Entered"); + t7xx_lk_stage_event_handling(ctl, dev_status); + break; + + case LINUX_STAGE: + t7xx_cldma_hif_hw_init(md->md_ctrl[CLDMA_ID_AP]); + t7xx_cldma_hif_hw_init(md->md_ctrl[CLDMA_ID_MD]); + t7xx_port_proxy_set_cfg(md, PORT_CFG_ID_NORMAL); + ret = fsm_routine_starting(ctl); + break; + + default: + break; } - t7xx_cldma_hif_hw_init(md->md_ctrl[CLDMA_ID_AP]); - t7xx_cldma_hif_hw_init(md->md_ctrl[CLDMA_ID_MD]); - fsm_finish_command(ctl, cmd, fsm_routine_starting(ctl)); +finish_command: + ctl->prev_dev_status = dev_status; + fsm_finish_command(ctl, cmd, ret); } static int fsm_main_thread(void *data) @@ -516,6 +599,8 @@ void t7xx_fsm_reset(struct t7xx_modem *md) fsm_flush_event_cmd_qs(ctl); ctl->curr_state = FSM_STATE_STOPPED; ctl->exp_flg = false; + ctl->prev_dev_status = 0; + ctl->device_stage_check_cnt = 0; } int t7xx_fsm_init(struct t7xx_modem *md) |