Loading drivers/bus/mhi/core/mhi_boot.c +6 −12 Original line number Diff line number Diff line Loading @@ -268,15 +268,13 @@ static int mhi_fw_load_amss(struct mhi_controller *mhi_cntrl, } static int mhi_fw_load_sbl(struct mhi_controller *mhi_cntrl, void *buf, dma_addr_t dma_addr, size_t size) { u32 tx_status, val; int i, ret; void __iomem *base = mhi_cntrl->bhi; rwlock_t *pm_lock = &mhi_cntrl->pm_lock; dma_addr_t dma_addr = dma_map_single(mhi_cntrl->dev, buf, size, DMA_TO_DEVICE); struct { char *name; u32 offset; Loading @@ -288,9 +286,6 @@ static int mhi_fw_load_sbl(struct mhi_controller *mhi_cntrl, { NULL }, }; if (dma_mapping_error(mhi_cntrl->dev, dma_addr)) return -ENOMEM; MHI_LOG("Starting BHI programming\n"); /* program start sbl download via bhi protocol */ Loading Loading @@ -339,12 +334,9 @@ static int mhi_fw_load_sbl(struct mhi_controller *mhi_cntrl, goto invalid_pm_state; } dma_unmap_single(mhi_cntrl->dev, dma_addr, size, DMA_TO_DEVICE); return (tx_status == BHI_STATUS_SUCCESS) ? 0 : -ETIMEDOUT; invalid_pm_state: dma_unmap_single(mhi_cntrl->dev, dma_addr, size, DMA_TO_DEVICE); return -EIO; } Loading Loading @@ -462,6 +454,7 @@ void mhi_fw_load_worker(struct work_struct *work) const struct firmware *firmware; struct image_info *image_info; void *buf; dma_addr_t dma_addr; size_t size; mhi_cntrl = container_of(work, struct mhi_controller, fw_worker); Loading Loading @@ -506,7 +499,7 @@ void mhi_fw_load_worker(struct work_struct *work) if (size > firmware->size) size = firmware->size; buf = kmemdup(firmware->data, size, GFP_KERNEL); buf = mhi_alloc_coherent(mhi_cntrl, size, &dma_addr, GFP_KERNEL); if (!buf) { MHI_ERR("Could not allocate memory for image\n"); release_firmware(firmware); Loading @@ -514,8 +507,9 @@ void mhi_fw_load_worker(struct work_struct *work) } /* load sbl image */ ret = mhi_fw_load_sbl(mhi_cntrl, buf, size); kfree(buf); memcpy(buf, firmware->data, size); ret = mhi_fw_load_sbl(mhi_cntrl, dma_addr, size); mhi_free_coherent(mhi_cntrl, size, buf, dma_addr); if (!mhi_cntrl->fbc_download || ret || mhi_cntrl->ee == MHI_EE_EDL) release_firmware(firmware); Loading drivers/bus/mhi/core/mhi_init.c +12 −15 Original line number Diff line number Diff line Loading @@ -54,20 +54,18 @@ const char * const mhi_state_str[MHI_STATE_MAX] = { }; static const char * const mhi_pm_state_str[] = { "DISABLE", "POR", "M0", "M1", "M1->M2", "M2", "M?->M3", "M3", "M3->M0", "FW DL Error", "SYS_ERR Detect", "SYS_ERR Process", "SHUTDOWN Process", "LD or Error Fatal Detect", [MHI_PM_BIT_DISABLE] = "DISABLE", [MHI_PM_BIT_POR] = "POR", [MHI_PM_BIT_M0] = "M0", [MHI_PM_BIT_M2] = "M2", [MHI_PM_BIT_M3_ENTER] = "M?->M3", [MHI_PM_BIT_M3] = "M3", [MHI_PM_BIT_M3_EXIT] = "M3->M0", [MHI_PM_BIT_FW_DL_ERR] = "FW DL Error", [MHI_PM_BIT_SYS_ERR_DETECT] = "SYS_ERR Detect", [MHI_PM_BIT_SYS_ERR_PROCESS] = "SYS_ERR Process", [MHI_PM_BIT_SHUTDOWN_PROCESS] = "SHUTDOWN Process", [MHI_PM_BIT_LD_ERR_FATAL_DETECT] = "LD or Error Fatal Detect", }; struct mhi_bus mhi_bus; Loading Loading @@ -1087,7 +1085,6 @@ int of_register_mhi_controller(struct mhi_controller *mhi_cntrl) spin_lock_init(&mhi_cntrl->wlock); INIT_WORK(&mhi_cntrl->st_worker, mhi_pm_st_worker); INIT_WORK(&mhi_cntrl->fw_worker, mhi_fw_load_worker); INIT_WORK(&mhi_cntrl->m1_worker, mhi_pm_m1_worker); INIT_WORK(&mhi_cntrl->syserr_worker, mhi_pm_sys_err_worker); init_waitqueue_head(&mhi_cntrl->state_event); Loading drivers/bus/mhi/core/mhi_internal.h +33 −19 Original line number Diff line number Diff line Loading @@ -425,33 +425,49 @@ extern const char * const mhi_state_str[MHI_STATE_MAX]; !mhi_state_str[state]) ? \ "INVALID_STATE" : mhi_state_str[state]) enum { MHI_PM_BIT_DISABLE, MHI_PM_BIT_POR, MHI_PM_BIT_M0, MHI_PM_BIT_M2, MHI_PM_BIT_M3_ENTER, MHI_PM_BIT_M3, MHI_PM_BIT_M3_EXIT, MHI_PM_BIT_FW_DL_ERR, MHI_PM_BIT_SYS_ERR_DETECT, MHI_PM_BIT_SYS_ERR_PROCESS, MHI_PM_BIT_SHUTDOWN_PROCESS, MHI_PM_BIT_LD_ERR_FATAL_DETECT, MHI_PM_BIT_MAX }; /* internal power states */ enum MHI_PM_STATE { MHI_PM_DISABLE = BIT(0), /* MHI is not enabled */ MHI_PM_POR = BIT(1), /* reset state */ MHI_PM_M0 = BIT(2), MHI_PM_M1 = BIT(3), MHI_PM_M1_M2_TRANSITION = BIT(4), /* register access not allowed */ MHI_PM_M2 = BIT(5), MHI_PM_M3_ENTER = BIT(6), MHI_PM_M3 = BIT(7), MHI_PM_M3_EXIT = BIT(8), MHI_PM_FW_DL_ERR = BIT(9), /* firmware download failure state */ MHI_PM_SYS_ERR_DETECT = BIT(10), MHI_PM_SYS_ERR_PROCESS = BIT(11), MHI_PM_SHUTDOWN_PROCESS = BIT(12), MHI_PM_LD_ERR_FATAL_DETECT = BIT(13), /* link not accessible */ MHI_PM_DISABLE = BIT(MHI_PM_BIT_DISABLE), /* MHI is not enabled */ MHI_PM_POR = BIT(MHI_PM_BIT_POR), /* reset state */ MHI_PM_M0 = BIT(MHI_PM_BIT_M0), MHI_PM_M2 = BIT(MHI_PM_BIT_M2), MHI_PM_M3_ENTER = BIT(MHI_PM_BIT_M3_ENTER), MHI_PM_M3 = BIT(MHI_PM_BIT_M3), MHI_PM_M3_EXIT = BIT(MHI_PM_BIT_M3_EXIT), /* firmware download failure state */ MHI_PM_FW_DL_ERR = BIT(MHI_PM_BIT_FW_DL_ERR), MHI_PM_SYS_ERR_DETECT = BIT(MHI_PM_BIT_SYS_ERR_DETECT), MHI_PM_SYS_ERR_PROCESS = BIT(MHI_PM_BIT_SYS_ERR_PROCESS), MHI_PM_SHUTDOWN_PROCESS = BIT(MHI_PM_BIT_SHUTDOWN_PROCESS), /* link not accessible */ MHI_PM_LD_ERR_FATAL_DETECT = BIT(MHI_PM_BIT_LD_ERR_FATAL_DETECT), }; #define MHI_REG_ACCESS_VALID(pm_state) ((pm_state & (MHI_PM_POR | MHI_PM_M0 | \ MHI_PM_M1 | MHI_PM_M2 | MHI_PM_M3_ENTER | MHI_PM_M3_EXIT | \ MHI_PM_M2 | MHI_PM_M3_ENTER | MHI_PM_M3_EXIT | \ MHI_PM_SYS_ERR_DETECT | MHI_PM_SYS_ERR_PROCESS | \ MHI_PM_SHUTDOWN_PROCESS | MHI_PM_FW_DL_ERR))) #define MHI_PM_IN_ERROR_STATE(pm_state) (pm_state >= MHI_PM_FW_DL_ERR) #define MHI_PM_IN_FATAL_STATE(pm_state) (pm_state == MHI_PM_LD_ERR_FATAL_DETECT) #define MHI_DB_ACCESS_VALID(pm_state) (pm_state & (MHI_PM_M0 | MHI_PM_M1)) #define MHI_DB_ACCESS_VALID(pm_state) (pm_state & MHI_PM_M0) #define MHI_WAKE_DB_CLEAR_VALID(pm_state) (pm_state & (MHI_PM_M0 | \ MHI_PM_M1 | MHI_PM_M2)) MHI_PM_M2)) #define MHI_WAKE_DB_SET_VALID(pm_state) (pm_state & MHI_PM_M2) #define MHI_WAKE_DB_FORCE_SET_VALID(pm_state) MHI_WAKE_DB_CLEAR_VALID(pm_state) #define MHI_EVENT_ACCESS_INVALID(pm_state) (pm_state == MHI_PM_DISABLE || \ Loading @@ -471,7 +487,6 @@ enum MHI_XFER_TYPE { #define CMD_EL_PER_RING (128) #define PRIMARY_CMD_RING (0) #define MHI_DEV_WAKE_DB (127) #define MHI_M2_DEBOUNCE_TMR_US (10000) #define MHI_MAX_MTU (0xffff) enum MHI_ER_TYPE { Loading Loading @@ -654,7 +669,6 @@ int mhi_queue_state_transition(struct mhi_controller *mhi_cntrl, enum MHI_ST_TRANSITION state); void mhi_pm_st_worker(struct work_struct *work); void mhi_fw_load_worker(struct work_struct *work); void mhi_pm_m1_worker(struct work_struct *work); void mhi_pm_sys_err_worker(struct work_struct *work); int mhi_ready_state_transition(struct mhi_controller *mhi_cntrl); void mhi_ctrl_ev_task(unsigned long data); Loading drivers/bus/mhi/core/mhi_main.c +2 −2 Original line number Diff line number Diff line Loading @@ -1582,11 +1582,11 @@ int mhi_debugfs_mhi_states_show(struct seq_file *m, void *d) struct mhi_controller *mhi_cntrl = m->private; seq_printf(m, "pm_state:%s dev_state:%s EE:%s M0:%u M1:%u M2:%u M3:%u wake:%d dev_wake:%u alloc_size:%u\n", "pm_state:%s dev_state:%s EE:%s M0:%u M2:%u M3:%u wake:%d dev_wake:%u alloc_size:%u\n", to_mhi_pm_state_str(mhi_cntrl->pm_state), TO_MHI_STATE_STR(mhi_cntrl->dev_state), TO_MHI_EXEC_STR(mhi_cntrl->ee), mhi_cntrl->M0, mhi_cntrl->M1, mhi_cntrl->M2, mhi_cntrl->M3, mhi_cntrl->M0, mhi_cntrl->M2, mhi_cntrl->M3, mhi_cntrl->wake_set, atomic_read(&mhi_cntrl->dev_wake), atomic_read(&mhi_cntrl->alloc_size)); Loading drivers/bus/mhi/core/mhi_pm.c +25 −94 Original line number Diff line number Diff line Loading @@ -36,13 +36,11 @@ * Valid transitions: * L0: DISABLE <--> POR * POR <--> POR * POR -> M0 -> M1 -> M1_M2 -> M2 --> M0 * POR -> M0 -> M2 --> M0 * POR -> FW_DL_ERR * FW_DL_ERR <--> FW_DL_ERR * M0 -> FW_DL_ERR * M1_M2 -> M0 (Device can trigger it) * M0 -> M3_ENTER -> M3 -> M3_EXIT --> M0 * M1 -> M3_ENTER --> M3 * L1: SYS_ERR_DETECT -> SYS_ERR_PROCESS --> POR * L2: SHUTDOWN_PROCESS -> DISABLE * L3: LD_ERR_FATAL_DETECT <--> LD_ERR_FATAL_DETECT Loading @@ -62,21 +60,10 @@ static struct mhi_pm_transitions const mhi_state_transitions[] = { }, { MHI_PM_M0, MHI_PM_M1 | MHI_PM_M3_ENTER | MHI_PM_SYS_ERR_DETECT | MHI_PM_M2 | MHI_PM_M3_ENTER | MHI_PM_SYS_ERR_DETECT | MHI_PM_SHUTDOWN_PROCESS | MHI_PM_LD_ERR_FATAL_DETECT | MHI_PM_FW_DL_ERR }, { MHI_PM_M1, MHI_PM_M1_M2_TRANSITION | MHI_PM_M3_ENTER | MHI_PM_SYS_ERR_DETECT | MHI_PM_SHUTDOWN_PROCESS | MHI_PM_LD_ERR_FATAL_DETECT }, { MHI_PM_M1_M2_TRANSITION, MHI_PM_M2 | MHI_PM_M0 | MHI_PM_SYS_ERR_DETECT | MHI_PM_SHUTDOWN_PROCESS | MHI_PM_LD_ERR_FATAL_DETECT }, { MHI_PM_M2, MHI_PM_M0 | MHI_PM_SYS_ERR_DETECT | MHI_PM_SHUTDOWN_PROCESS | Loading Loading @@ -376,56 +363,22 @@ int mhi_pm_m0_transition(struct mhi_controller *mhi_cntrl) return 0; } void mhi_pm_m1_worker(struct work_struct *work) void mhi_pm_m1_transition(struct mhi_controller *mhi_cntrl) { enum MHI_PM_STATE cur_state; struct mhi_controller *mhi_cntrl; mhi_cntrl = container_of(work, struct mhi_controller, m1_worker); MHI_LOG("M1 state transition from dev_state:%s pm_state:%s\n", TO_MHI_STATE_STR(mhi_cntrl->dev_state), to_mhi_pm_state_str(mhi_cntrl->pm_state)); enum MHI_PM_STATE state; mutex_lock(&mhi_cntrl->pm_mutex); write_lock_irq(&mhi_cntrl->pm_lock); /* we either Entered M3 or we did M3->M0 Exit */ if (mhi_cntrl->pm_state != MHI_PM_M1) goto invalid_pm_state; MHI_LOG("Transitioning to M2 Transition\n"); cur_state = mhi_tryset_pm_state(mhi_cntrl, MHI_PM_M1_M2_TRANSITION); if (unlikely(cur_state != MHI_PM_M1_M2_TRANSITION)) { MHI_ERR("Failed to transition to state %s from %s\n", to_mhi_pm_state_str(MHI_PM_M1_M2_TRANSITION), to_mhi_pm_state_str(cur_state)); goto invalid_pm_state; } mhi_cntrl->dev_state = MHI_STATE_M2; /* if it fails, means we transition to M3 */ state = mhi_tryset_pm_state(mhi_cntrl, MHI_PM_M2); if (state == MHI_PM_M2) { MHI_VERB("Entered M2 State\n"); mhi_set_mhi_state(mhi_cntrl, MHI_STATE_M2); write_unlock_irq(&mhi_cntrl->pm_lock); mhi_cntrl->dev_state = MHI_STATE_M2; mhi_cntrl->M2++; /* during M2 transition we cannot access DB registers must sleep */ usleep_range(MHI_M2_DEBOUNCE_TMR_US, MHI_M2_DEBOUNCE_TMR_US + 50); write_lock_irq(&mhi_cntrl->pm_lock); /* during de-bounce time could be receiving M0 Event */ if (mhi_cntrl->pm_state == MHI_PM_M1_M2_TRANSITION) { MHI_LOG("Entered M2 State\n"); cur_state = mhi_tryset_pm_state(mhi_cntrl, MHI_PM_M2); if (unlikely(cur_state != MHI_PM_M2)) { MHI_ERR("Failed to transition to state %s from %s\n", to_mhi_pm_state_str(MHI_PM_M2), to_mhi_pm_state_str(cur_state)); goto invalid_pm_state; } } write_unlock_irq(&mhi_cntrl->pm_lock); /* transfer pending, exit M2 */ /* transfer pending, exit M2 immediately */ if (unlikely(atomic_read(&mhi_cntrl->dev_wake))) { MHI_VERB("Exiting M2 Immediately, count:%d\n", atomic_read(&mhi_cntrl->dev_wake)); Loading @@ -433,35 +386,14 @@ void mhi_pm_m1_worker(struct work_struct *work) mhi_cntrl->wake_get(mhi_cntrl, true); mhi_cntrl->wake_put(mhi_cntrl, false); read_unlock_bh(&mhi_cntrl->pm_lock); } else } else { mhi_cntrl->status_cb(mhi_cntrl, mhi_cntrl->priv_data, MHI_CB_IDLE); mutex_unlock(&mhi_cntrl->pm_mutex); return; invalid_pm_state: write_unlock_irq(&mhi_cntrl->pm_lock); mutex_unlock(&mhi_cntrl->pm_mutex); } void mhi_pm_m1_transition(struct mhi_controller *mhi_cntrl) { enum MHI_PM_STATE state; write_lock_irq(&mhi_cntrl->pm_lock); mhi_cntrl->dev_state = mhi_get_m_state(mhi_cntrl); if (mhi_cntrl->dev_state == MHI_STATE_M1) { state = mhi_tryset_pm_state(mhi_cntrl, MHI_PM_M1); /* schedule M1->M2 transition */ if (state == MHI_PM_M1) { schedule_work(&mhi_cntrl->m1_worker); mhi_cntrl->M1++; } } } else { write_unlock_irq(&mhi_cntrl->pm_lock); } } int mhi_pm_m3_transition(struct mhi_controller *mhi_cntrl) { Loading Loading @@ -619,7 +551,6 @@ static void mhi_pm_disable_transition(struct mhi_controller *mhi_cntrl, mutex_unlock(&mhi_cntrl->pm_mutex); MHI_LOG("Waiting for all pending threads to complete\n"); wake_up(&mhi_cntrl->state_event); flush_work(&mhi_cntrl->m1_worker); flush_work(&mhi_cntrl->st_worker); flush_work(&mhi_cntrl->fw_worker); Loading Loading
drivers/bus/mhi/core/mhi_boot.c +6 −12 Original line number Diff line number Diff line Loading @@ -268,15 +268,13 @@ static int mhi_fw_load_amss(struct mhi_controller *mhi_cntrl, } static int mhi_fw_load_sbl(struct mhi_controller *mhi_cntrl, void *buf, dma_addr_t dma_addr, size_t size) { u32 tx_status, val; int i, ret; void __iomem *base = mhi_cntrl->bhi; rwlock_t *pm_lock = &mhi_cntrl->pm_lock; dma_addr_t dma_addr = dma_map_single(mhi_cntrl->dev, buf, size, DMA_TO_DEVICE); struct { char *name; u32 offset; Loading @@ -288,9 +286,6 @@ static int mhi_fw_load_sbl(struct mhi_controller *mhi_cntrl, { NULL }, }; if (dma_mapping_error(mhi_cntrl->dev, dma_addr)) return -ENOMEM; MHI_LOG("Starting BHI programming\n"); /* program start sbl download via bhi protocol */ Loading Loading @@ -339,12 +334,9 @@ static int mhi_fw_load_sbl(struct mhi_controller *mhi_cntrl, goto invalid_pm_state; } dma_unmap_single(mhi_cntrl->dev, dma_addr, size, DMA_TO_DEVICE); return (tx_status == BHI_STATUS_SUCCESS) ? 0 : -ETIMEDOUT; invalid_pm_state: dma_unmap_single(mhi_cntrl->dev, dma_addr, size, DMA_TO_DEVICE); return -EIO; } Loading Loading @@ -462,6 +454,7 @@ void mhi_fw_load_worker(struct work_struct *work) const struct firmware *firmware; struct image_info *image_info; void *buf; dma_addr_t dma_addr; size_t size; mhi_cntrl = container_of(work, struct mhi_controller, fw_worker); Loading Loading @@ -506,7 +499,7 @@ void mhi_fw_load_worker(struct work_struct *work) if (size > firmware->size) size = firmware->size; buf = kmemdup(firmware->data, size, GFP_KERNEL); buf = mhi_alloc_coherent(mhi_cntrl, size, &dma_addr, GFP_KERNEL); if (!buf) { MHI_ERR("Could not allocate memory for image\n"); release_firmware(firmware); Loading @@ -514,8 +507,9 @@ void mhi_fw_load_worker(struct work_struct *work) } /* load sbl image */ ret = mhi_fw_load_sbl(mhi_cntrl, buf, size); kfree(buf); memcpy(buf, firmware->data, size); ret = mhi_fw_load_sbl(mhi_cntrl, dma_addr, size); mhi_free_coherent(mhi_cntrl, size, buf, dma_addr); if (!mhi_cntrl->fbc_download || ret || mhi_cntrl->ee == MHI_EE_EDL) release_firmware(firmware); Loading
drivers/bus/mhi/core/mhi_init.c +12 −15 Original line number Diff line number Diff line Loading @@ -54,20 +54,18 @@ const char * const mhi_state_str[MHI_STATE_MAX] = { }; static const char * const mhi_pm_state_str[] = { "DISABLE", "POR", "M0", "M1", "M1->M2", "M2", "M?->M3", "M3", "M3->M0", "FW DL Error", "SYS_ERR Detect", "SYS_ERR Process", "SHUTDOWN Process", "LD or Error Fatal Detect", [MHI_PM_BIT_DISABLE] = "DISABLE", [MHI_PM_BIT_POR] = "POR", [MHI_PM_BIT_M0] = "M0", [MHI_PM_BIT_M2] = "M2", [MHI_PM_BIT_M3_ENTER] = "M?->M3", [MHI_PM_BIT_M3] = "M3", [MHI_PM_BIT_M3_EXIT] = "M3->M0", [MHI_PM_BIT_FW_DL_ERR] = "FW DL Error", [MHI_PM_BIT_SYS_ERR_DETECT] = "SYS_ERR Detect", [MHI_PM_BIT_SYS_ERR_PROCESS] = "SYS_ERR Process", [MHI_PM_BIT_SHUTDOWN_PROCESS] = "SHUTDOWN Process", [MHI_PM_BIT_LD_ERR_FATAL_DETECT] = "LD or Error Fatal Detect", }; struct mhi_bus mhi_bus; Loading Loading @@ -1087,7 +1085,6 @@ int of_register_mhi_controller(struct mhi_controller *mhi_cntrl) spin_lock_init(&mhi_cntrl->wlock); INIT_WORK(&mhi_cntrl->st_worker, mhi_pm_st_worker); INIT_WORK(&mhi_cntrl->fw_worker, mhi_fw_load_worker); INIT_WORK(&mhi_cntrl->m1_worker, mhi_pm_m1_worker); INIT_WORK(&mhi_cntrl->syserr_worker, mhi_pm_sys_err_worker); init_waitqueue_head(&mhi_cntrl->state_event); Loading
drivers/bus/mhi/core/mhi_internal.h +33 −19 Original line number Diff line number Diff line Loading @@ -425,33 +425,49 @@ extern const char * const mhi_state_str[MHI_STATE_MAX]; !mhi_state_str[state]) ? \ "INVALID_STATE" : mhi_state_str[state]) enum { MHI_PM_BIT_DISABLE, MHI_PM_BIT_POR, MHI_PM_BIT_M0, MHI_PM_BIT_M2, MHI_PM_BIT_M3_ENTER, MHI_PM_BIT_M3, MHI_PM_BIT_M3_EXIT, MHI_PM_BIT_FW_DL_ERR, MHI_PM_BIT_SYS_ERR_DETECT, MHI_PM_BIT_SYS_ERR_PROCESS, MHI_PM_BIT_SHUTDOWN_PROCESS, MHI_PM_BIT_LD_ERR_FATAL_DETECT, MHI_PM_BIT_MAX }; /* internal power states */ enum MHI_PM_STATE { MHI_PM_DISABLE = BIT(0), /* MHI is not enabled */ MHI_PM_POR = BIT(1), /* reset state */ MHI_PM_M0 = BIT(2), MHI_PM_M1 = BIT(3), MHI_PM_M1_M2_TRANSITION = BIT(4), /* register access not allowed */ MHI_PM_M2 = BIT(5), MHI_PM_M3_ENTER = BIT(6), MHI_PM_M3 = BIT(7), MHI_PM_M3_EXIT = BIT(8), MHI_PM_FW_DL_ERR = BIT(9), /* firmware download failure state */ MHI_PM_SYS_ERR_DETECT = BIT(10), MHI_PM_SYS_ERR_PROCESS = BIT(11), MHI_PM_SHUTDOWN_PROCESS = BIT(12), MHI_PM_LD_ERR_FATAL_DETECT = BIT(13), /* link not accessible */ MHI_PM_DISABLE = BIT(MHI_PM_BIT_DISABLE), /* MHI is not enabled */ MHI_PM_POR = BIT(MHI_PM_BIT_POR), /* reset state */ MHI_PM_M0 = BIT(MHI_PM_BIT_M0), MHI_PM_M2 = BIT(MHI_PM_BIT_M2), MHI_PM_M3_ENTER = BIT(MHI_PM_BIT_M3_ENTER), MHI_PM_M3 = BIT(MHI_PM_BIT_M3), MHI_PM_M3_EXIT = BIT(MHI_PM_BIT_M3_EXIT), /* firmware download failure state */ MHI_PM_FW_DL_ERR = BIT(MHI_PM_BIT_FW_DL_ERR), MHI_PM_SYS_ERR_DETECT = BIT(MHI_PM_BIT_SYS_ERR_DETECT), MHI_PM_SYS_ERR_PROCESS = BIT(MHI_PM_BIT_SYS_ERR_PROCESS), MHI_PM_SHUTDOWN_PROCESS = BIT(MHI_PM_BIT_SHUTDOWN_PROCESS), /* link not accessible */ MHI_PM_LD_ERR_FATAL_DETECT = BIT(MHI_PM_BIT_LD_ERR_FATAL_DETECT), }; #define MHI_REG_ACCESS_VALID(pm_state) ((pm_state & (MHI_PM_POR | MHI_PM_M0 | \ MHI_PM_M1 | MHI_PM_M2 | MHI_PM_M3_ENTER | MHI_PM_M3_EXIT | \ MHI_PM_M2 | MHI_PM_M3_ENTER | MHI_PM_M3_EXIT | \ MHI_PM_SYS_ERR_DETECT | MHI_PM_SYS_ERR_PROCESS | \ MHI_PM_SHUTDOWN_PROCESS | MHI_PM_FW_DL_ERR))) #define MHI_PM_IN_ERROR_STATE(pm_state) (pm_state >= MHI_PM_FW_DL_ERR) #define MHI_PM_IN_FATAL_STATE(pm_state) (pm_state == MHI_PM_LD_ERR_FATAL_DETECT) #define MHI_DB_ACCESS_VALID(pm_state) (pm_state & (MHI_PM_M0 | MHI_PM_M1)) #define MHI_DB_ACCESS_VALID(pm_state) (pm_state & MHI_PM_M0) #define MHI_WAKE_DB_CLEAR_VALID(pm_state) (pm_state & (MHI_PM_M0 | \ MHI_PM_M1 | MHI_PM_M2)) MHI_PM_M2)) #define MHI_WAKE_DB_SET_VALID(pm_state) (pm_state & MHI_PM_M2) #define MHI_WAKE_DB_FORCE_SET_VALID(pm_state) MHI_WAKE_DB_CLEAR_VALID(pm_state) #define MHI_EVENT_ACCESS_INVALID(pm_state) (pm_state == MHI_PM_DISABLE || \ Loading @@ -471,7 +487,6 @@ enum MHI_XFER_TYPE { #define CMD_EL_PER_RING (128) #define PRIMARY_CMD_RING (0) #define MHI_DEV_WAKE_DB (127) #define MHI_M2_DEBOUNCE_TMR_US (10000) #define MHI_MAX_MTU (0xffff) enum MHI_ER_TYPE { Loading Loading @@ -654,7 +669,6 @@ int mhi_queue_state_transition(struct mhi_controller *mhi_cntrl, enum MHI_ST_TRANSITION state); void mhi_pm_st_worker(struct work_struct *work); void mhi_fw_load_worker(struct work_struct *work); void mhi_pm_m1_worker(struct work_struct *work); void mhi_pm_sys_err_worker(struct work_struct *work); int mhi_ready_state_transition(struct mhi_controller *mhi_cntrl); void mhi_ctrl_ev_task(unsigned long data); Loading
drivers/bus/mhi/core/mhi_main.c +2 −2 Original line number Diff line number Diff line Loading @@ -1582,11 +1582,11 @@ int mhi_debugfs_mhi_states_show(struct seq_file *m, void *d) struct mhi_controller *mhi_cntrl = m->private; seq_printf(m, "pm_state:%s dev_state:%s EE:%s M0:%u M1:%u M2:%u M3:%u wake:%d dev_wake:%u alloc_size:%u\n", "pm_state:%s dev_state:%s EE:%s M0:%u M2:%u M3:%u wake:%d dev_wake:%u alloc_size:%u\n", to_mhi_pm_state_str(mhi_cntrl->pm_state), TO_MHI_STATE_STR(mhi_cntrl->dev_state), TO_MHI_EXEC_STR(mhi_cntrl->ee), mhi_cntrl->M0, mhi_cntrl->M1, mhi_cntrl->M2, mhi_cntrl->M3, mhi_cntrl->M0, mhi_cntrl->M2, mhi_cntrl->M3, mhi_cntrl->wake_set, atomic_read(&mhi_cntrl->dev_wake), atomic_read(&mhi_cntrl->alloc_size)); Loading
drivers/bus/mhi/core/mhi_pm.c +25 −94 Original line number Diff line number Diff line Loading @@ -36,13 +36,11 @@ * Valid transitions: * L0: DISABLE <--> POR * POR <--> POR * POR -> M0 -> M1 -> M1_M2 -> M2 --> M0 * POR -> M0 -> M2 --> M0 * POR -> FW_DL_ERR * FW_DL_ERR <--> FW_DL_ERR * M0 -> FW_DL_ERR * M1_M2 -> M0 (Device can trigger it) * M0 -> M3_ENTER -> M3 -> M3_EXIT --> M0 * M1 -> M3_ENTER --> M3 * L1: SYS_ERR_DETECT -> SYS_ERR_PROCESS --> POR * L2: SHUTDOWN_PROCESS -> DISABLE * L3: LD_ERR_FATAL_DETECT <--> LD_ERR_FATAL_DETECT Loading @@ -62,21 +60,10 @@ static struct mhi_pm_transitions const mhi_state_transitions[] = { }, { MHI_PM_M0, MHI_PM_M1 | MHI_PM_M3_ENTER | MHI_PM_SYS_ERR_DETECT | MHI_PM_M2 | MHI_PM_M3_ENTER | MHI_PM_SYS_ERR_DETECT | MHI_PM_SHUTDOWN_PROCESS | MHI_PM_LD_ERR_FATAL_DETECT | MHI_PM_FW_DL_ERR }, { MHI_PM_M1, MHI_PM_M1_M2_TRANSITION | MHI_PM_M3_ENTER | MHI_PM_SYS_ERR_DETECT | MHI_PM_SHUTDOWN_PROCESS | MHI_PM_LD_ERR_FATAL_DETECT }, { MHI_PM_M1_M2_TRANSITION, MHI_PM_M2 | MHI_PM_M0 | MHI_PM_SYS_ERR_DETECT | MHI_PM_SHUTDOWN_PROCESS | MHI_PM_LD_ERR_FATAL_DETECT }, { MHI_PM_M2, MHI_PM_M0 | MHI_PM_SYS_ERR_DETECT | MHI_PM_SHUTDOWN_PROCESS | Loading Loading @@ -376,56 +363,22 @@ int mhi_pm_m0_transition(struct mhi_controller *mhi_cntrl) return 0; } void mhi_pm_m1_worker(struct work_struct *work) void mhi_pm_m1_transition(struct mhi_controller *mhi_cntrl) { enum MHI_PM_STATE cur_state; struct mhi_controller *mhi_cntrl; mhi_cntrl = container_of(work, struct mhi_controller, m1_worker); MHI_LOG("M1 state transition from dev_state:%s pm_state:%s\n", TO_MHI_STATE_STR(mhi_cntrl->dev_state), to_mhi_pm_state_str(mhi_cntrl->pm_state)); enum MHI_PM_STATE state; mutex_lock(&mhi_cntrl->pm_mutex); write_lock_irq(&mhi_cntrl->pm_lock); /* we either Entered M3 or we did M3->M0 Exit */ if (mhi_cntrl->pm_state != MHI_PM_M1) goto invalid_pm_state; MHI_LOG("Transitioning to M2 Transition\n"); cur_state = mhi_tryset_pm_state(mhi_cntrl, MHI_PM_M1_M2_TRANSITION); if (unlikely(cur_state != MHI_PM_M1_M2_TRANSITION)) { MHI_ERR("Failed to transition to state %s from %s\n", to_mhi_pm_state_str(MHI_PM_M1_M2_TRANSITION), to_mhi_pm_state_str(cur_state)); goto invalid_pm_state; } mhi_cntrl->dev_state = MHI_STATE_M2; /* if it fails, means we transition to M3 */ state = mhi_tryset_pm_state(mhi_cntrl, MHI_PM_M2); if (state == MHI_PM_M2) { MHI_VERB("Entered M2 State\n"); mhi_set_mhi_state(mhi_cntrl, MHI_STATE_M2); write_unlock_irq(&mhi_cntrl->pm_lock); mhi_cntrl->dev_state = MHI_STATE_M2; mhi_cntrl->M2++; /* during M2 transition we cannot access DB registers must sleep */ usleep_range(MHI_M2_DEBOUNCE_TMR_US, MHI_M2_DEBOUNCE_TMR_US + 50); write_lock_irq(&mhi_cntrl->pm_lock); /* during de-bounce time could be receiving M0 Event */ if (mhi_cntrl->pm_state == MHI_PM_M1_M2_TRANSITION) { MHI_LOG("Entered M2 State\n"); cur_state = mhi_tryset_pm_state(mhi_cntrl, MHI_PM_M2); if (unlikely(cur_state != MHI_PM_M2)) { MHI_ERR("Failed to transition to state %s from %s\n", to_mhi_pm_state_str(MHI_PM_M2), to_mhi_pm_state_str(cur_state)); goto invalid_pm_state; } } write_unlock_irq(&mhi_cntrl->pm_lock); /* transfer pending, exit M2 */ /* transfer pending, exit M2 immediately */ if (unlikely(atomic_read(&mhi_cntrl->dev_wake))) { MHI_VERB("Exiting M2 Immediately, count:%d\n", atomic_read(&mhi_cntrl->dev_wake)); Loading @@ -433,35 +386,14 @@ void mhi_pm_m1_worker(struct work_struct *work) mhi_cntrl->wake_get(mhi_cntrl, true); mhi_cntrl->wake_put(mhi_cntrl, false); read_unlock_bh(&mhi_cntrl->pm_lock); } else } else { mhi_cntrl->status_cb(mhi_cntrl, mhi_cntrl->priv_data, MHI_CB_IDLE); mutex_unlock(&mhi_cntrl->pm_mutex); return; invalid_pm_state: write_unlock_irq(&mhi_cntrl->pm_lock); mutex_unlock(&mhi_cntrl->pm_mutex); } void mhi_pm_m1_transition(struct mhi_controller *mhi_cntrl) { enum MHI_PM_STATE state; write_lock_irq(&mhi_cntrl->pm_lock); mhi_cntrl->dev_state = mhi_get_m_state(mhi_cntrl); if (mhi_cntrl->dev_state == MHI_STATE_M1) { state = mhi_tryset_pm_state(mhi_cntrl, MHI_PM_M1); /* schedule M1->M2 transition */ if (state == MHI_PM_M1) { schedule_work(&mhi_cntrl->m1_worker); mhi_cntrl->M1++; } } } else { write_unlock_irq(&mhi_cntrl->pm_lock); } } int mhi_pm_m3_transition(struct mhi_controller *mhi_cntrl) { Loading Loading @@ -619,7 +551,6 @@ static void mhi_pm_disable_transition(struct mhi_controller *mhi_cntrl, mutex_unlock(&mhi_cntrl->pm_mutex); MHI_LOG("Waiting for all pending threads to complete\n"); wake_up(&mhi_cntrl->state_event); flush_work(&mhi_cntrl->m1_worker); flush_work(&mhi_cntrl->st_worker); flush_work(&mhi_cntrl->fw_worker); Loading