aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wwan/t7xx/t7xx_state_monitor.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wwan/t7xx/t7xx_state_monitor.c')
-rw-r--r--drivers/net/wwan/t7xx/t7xx_state_monitor.c109
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)