Loading drivers/bus/mhi/core/mhi_boot.c +26 −10 Original line number Diff line number Diff line Loading @@ -43,8 +43,10 @@ static int __mhi_download_rddm_in_panic(struct mhi_controller *mhi_cntrl) u32 rx_status; enum mhi_ee ee; struct image_info *rddm_image = mhi_cntrl->rddm_image; const u32 delayus = 100; const u32 delayus = 5000; u32 retry = (mhi_cntrl->timeout_ms * 1000) / delayus; const u32 rddm_timeout_us = 200000; int rddm_retry = rddm_timeout_us / delayus; /* time to enter rddm */ void __iomem *base = mhi_cntrl->bhie; MHI_LOG("Entered with pm_state:%s dev_state:%s ee:%s\n", Loading @@ -58,14 +60,8 @@ static int __mhi_download_rddm_in_panic(struct mhi_controller *mhi_cntrl) * returning from this function, we expect device to reset. * * Normaly, we would read/write pm_state only after grabbing * pm_lock, since we're in a panic, skipping it. */ if (!MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) return -EIO; /* * There is no gurantee this state change would take effect since * pm_lock, since we're in a panic, skipping it. Also there is no * gurantee this state change would take effect since * we're setting it w/o grabbing pmlock, it's best effort */ mhi_cntrl->pm_state = MHI_PM_LD_ERR_FATAL_DETECT; Loading Loading @@ -98,7 +94,27 @@ static int __mhi_download_rddm_in_panic(struct mhi_controller *mhi_cntrl) MHI_LOG("Trigger device into RDDM mode\n"); mhi_set_mhi_state(mhi_cntrl, MHI_STATE_SYS_ERR); MHI_LOG("Waiting for image download completion\n"); MHI_LOG("Waiting for device to enter RDDM\n"); while (rddm_retry--) { ee = mhi_get_exec_env(mhi_cntrl); if (ee == MHI_EE_RDDM) break; udelay(delayus); } if (rddm_retry <= 0) { /* This is a hardware reset, will force device to enter rddm */ MHI_LOG( "Did not enter RDDM triggering host req. reset to force rddm\n"); mhi_write_reg(mhi_cntrl, mhi_cntrl->regs, MHI_SOC_RESET_REQ_OFFSET, MHI_SOC_RESET_REQ); udelay(delayus); } ee = mhi_get_exec_env(mhi_cntrl); MHI_LOG("Waiting for image download completion, current EE:%s\n", TO_MHI_EXEC_STR(ee)); while (retry--) { ret = mhi_read_reg_field(mhi_cntrl, base, BHIE_RXVECSTATUS_OFFS, BHIE_RXVECSTATUS_STATUS_BMSK, Loading drivers/bus/mhi/core/mhi_init.c +26 −2 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* Copyright (c) 2018, The Linux Foundation. All rights reserved. */ /* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. */ #include <linux/debugfs.h> #include <linux/device.h> Loading Loading @@ -1239,6 +1239,7 @@ EXPORT_SYMBOL(mhi_alloc_controller); int mhi_prepare_for_power_up(struct mhi_controller *mhi_cntrl) { int ret; u32 bhie_off; mutex_lock(&mhi_cntrl->pm_mutex); Loading @@ -1258,16 +1259,39 @@ int mhi_prepare_for_power_up(struct mhi_controller *mhi_cntrl) * allocate rddm table if specified, this table is for debug purpose * so we'll ignore erros */ if (mhi_cntrl->rddm_size) if (mhi_cntrl->rddm_size) { mhi_alloc_bhie_table(mhi_cntrl, &mhi_cntrl->rddm_image, mhi_cntrl->rddm_size); /* * This controller supports rddm, we need to manually clear * BHIE RX registers since por values are undefined. */ ret = mhi_read_reg(mhi_cntrl, mhi_cntrl->regs, BHIEOFF, &bhie_off); if (ret) { MHI_ERR("Error getting bhie offset\n"); goto bhie_error; } memset_io(mhi_cntrl->regs + bhie_off + BHIE_RXVECADDR_LOW_OFFS, 0, BHIE_RXVECSTATUS_OFFS - BHIE_RXVECADDR_LOW_OFFS + 4); } mhi_cntrl->pre_init = true; mutex_unlock(&mhi_cntrl->pm_mutex); return 0; bhie_error: if (mhi_cntrl->rddm_image) { mhi_free_bhie_table(mhi_cntrl, mhi_cntrl->rddm_image); mhi_cntrl->rddm_image = NULL; } mhi_deinit_free_irq(mhi_cntrl); error_setup_irq: mhi_deinit_dev_ctxt(mhi_cntrl); Loading drivers/bus/mhi/core/mhi_internal.h +4 −0 Original line number Diff line number Diff line Loading @@ -125,6 +125,10 @@ extern struct bus_type mhi_bus_type; #define MHIDATALIMIT_HIGHER_MHIDATALIMIT_HIGHER_MASK (0xFFFFFFFF) #define MHIDATALIMIT_HIGHER_MHIDATALIMIT_HIGHER_SHIFT (0) /* Host request register */ #define MHI_SOC_RESET_REQ_OFFSET (0xB0) #define MHI_SOC_RESET_REQ BIT(0) /* MHI misc capability registers */ #define MISC_OFFSET (0x24) #define MISC_CAP_MASK (0xFFFFFFFF) Loading drivers/bus/mhi/core/mhi_main.c +10 −3 Original line number Diff line number Diff line Loading @@ -1381,12 +1381,20 @@ void mhi_ctrl_ev_task(unsigned long data) { struct mhi_event *mhi_event = (struct mhi_event *)data; struct mhi_controller *mhi_cntrl = mhi_event->mhi_cntrl; enum mhi_dev_state state = MHI_STATE_MAX; enum mhi_dev_state state; enum MHI_PM_STATE pm_state = 0; int ret; MHI_VERB("Enter for ev_index:%d\n", mhi_event->er_index); /* * we can check pm_state w/o a lock here because there is no way * pm_state can change from reg access valid to no access while this * therad being executed. */ if (!MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) return; /* process ctrl events events */ ret = mhi_event->process_event(mhi_cntrl, mhi_event, U32_MAX); Loading @@ -1396,7 +1404,6 @@ void mhi_ctrl_ev_task(unsigned long data) */ if (!ret) { write_lock_irq(&mhi_cntrl->pm_lock); if (MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) state = mhi_get_mhi_state(mhi_cntrl); if (state == MHI_STATE_SYS_ERR) { MHI_ERR("MHI system error detected\n"); Loading drivers/bus/mhi/core/mhi_pm.c +6 −21 Original line number Diff line number Diff line Loading @@ -1045,6 +1045,12 @@ int mhi_pm_resume(struct mhi_controller *mhi_cntrl) MHI_ERR("Did not enter M0 state, cur_state:%s pm_state:%s\n", TO_MHI_STATE_STR(mhi_cntrl->dev_state), to_mhi_pm_state_str(mhi_cntrl->pm_state)); /* * It's possible device already in error state and we didn't * process it due to low power mode, force a check */ mhi_intvec_threaded_handlr(0, mhi_cntrl); return -EIO; } Loading Loading @@ -1124,22 +1130,8 @@ int mhi_force_rddm_mode(struct mhi_controller *mhi_cntrl) to_mhi_pm_state_str(mhi_cntrl->pm_state), TO_MHI_EXEC_STR(mhi_cntrl->ee)); /* before rddm mode, we need to enter M0 state */ ret = __mhi_device_get_sync(mhi_cntrl); if (ret) return ret; mutex_lock(&mhi_cntrl->pm_mutex); write_lock_irq(&mhi_cntrl->pm_lock); if (!MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) goto no_reg_access; MHI_LOG("Triggering SYS_ERR to force rddm state\n"); mhi_set_mhi_state(mhi_cntrl, MHI_STATE_SYS_ERR); mhi_cntrl->wake_put(mhi_cntrl, false); write_unlock_irq(&mhi_cntrl->pm_lock); mutex_unlock(&mhi_cntrl->pm_mutex); /* wait for rddm event */ MHI_LOG("Waiting for device to enter RDDM state\n"); Loading @@ -1153,12 +1145,5 @@ int mhi_force_rddm_mode(struct mhi_controller *mhi_cntrl) TO_MHI_EXEC_STR(mhi_cntrl->ee), ret); return ret; no_reg_access: mhi_cntrl->wake_put(mhi_cntrl, false); write_unlock_irq(&mhi_cntrl->pm_lock); mutex_unlock(&mhi_cntrl->pm_mutex); return -EIO; } EXPORT_SYMBOL(mhi_force_rddm_mode); Loading
drivers/bus/mhi/core/mhi_boot.c +26 −10 Original line number Diff line number Diff line Loading @@ -43,8 +43,10 @@ static int __mhi_download_rddm_in_panic(struct mhi_controller *mhi_cntrl) u32 rx_status; enum mhi_ee ee; struct image_info *rddm_image = mhi_cntrl->rddm_image; const u32 delayus = 100; const u32 delayus = 5000; u32 retry = (mhi_cntrl->timeout_ms * 1000) / delayus; const u32 rddm_timeout_us = 200000; int rddm_retry = rddm_timeout_us / delayus; /* time to enter rddm */ void __iomem *base = mhi_cntrl->bhie; MHI_LOG("Entered with pm_state:%s dev_state:%s ee:%s\n", Loading @@ -58,14 +60,8 @@ static int __mhi_download_rddm_in_panic(struct mhi_controller *mhi_cntrl) * returning from this function, we expect device to reset. * * Normaly, we would read/write pm_state only after grabbing * pm_lock, since we're in a panic, skipping it. */ if (!MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) return -EIO; /* * There is no gurantee this state change would take effect since * pm_lock, since we're in a panic, skipping it. Also there is no * gurantee this state change would take effect since * we're setting it w/o grabbing pmlock, it's best effort */ mhi_cntrl->pm_state = MHI_PM_LD_ERR_FATAL_DETECT; Loading Loading @@ -98,7 +94,27 @@ static int __mhi_download_rddm_in_panic(struct mhi_controller *mhi_cntrl) MHI_LOG("Trigger device into RDDM mode\n"); mhi_set_mhi_state(mhi_cntrl, MHI_STATE_SYS_ERR); MHI_LOG("Waiting for image download completion\n"); MHI_LOG("Waiting for device to enter RDDM\n"); while (rddm_retry--) { ee = mhi_get_exec_env(mhi_cntrl); if (ee == MHI_EE_RDDM) break; udelay(delayus); } if (rddm_retry <= 0) { /* This is a hardware reset, will force device to enter rddm */ MHI_LOG( "Did not enter RDDM triggering host req. reset to force rddm\n"); mhi_write_reg(mhi_cntrl, mhi_cntrl->regs, MHI_SOC_RESET_REQ_OFFSET, MHI_SOC_RESET_REQ); udelay(delayus); } ee = mhi_get_exec_env(mhi_cntrl); MHI_LOG("Waiting for image download completion, current EE:%s\n", TO_MHI_EXEC_STR(ee)); while (retry--) { ret = mhi_read_reg_field(mhi_cntrl, base, BHIE_RXVECSTATUS_OFFS, BHIE_RXVECSTATUS_STATUS_BMSK, Loading
drivers/bus/mhi/core/mhi_init.c +26 −2 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* Copyright (c) 2018, The Linux Foundation. All rights reserved. */ /* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. */ #include <linux/debugfs.h> #include <linux/device.h> Loading Loading @@ -1239,6 +1239,7 @@ EXPORT_SYMBOL(mhi_alloc_controller); int mhi_prepare_for_power_up(struct mhi_controller *mhi_cntrl) { int ret; u32 bhie_off; mutex_lock(&mhi_cntrl->pm_mutex); Loading @@ -1258,16 +1259,39 @@ int mhi_prepare_for_power_up(struct mhi_controller *mhi_cntrl) * allocate rddm table if specified, this table is for debug purpose * so we'll ignore erros */ if (mhi_cntrl->rddm_size) if (mhi_cntrl->rddm_size) { mhi_alloc_bhie_table(mhi_cntrl, &mhi_cntrl->rddm_image, mhi_cntrl->rddm_size); /* * This controller supports rddm, we need to manually clear * BHIE RX registers since por values are undefined. */ ret = mhi_read_reg(mhi_cntrl, mhi_cntrl->regs, BHIEOFF, &bhie_off); if (ret) { MHI_ERR("Error getting bhie offset\n"); goto bhie_error; } memset_io(mhi_cntrl->regs + bhie_off + BHIE_RXVECADDR_LOW_OFFS, 0, BHIE_RXVECSTATUS_OFFS - BHIE_RXVECADDR_LOW_OFFS + 4); } mhi_cntrl->pre_init = true; mutex_unlock(&mhi_cntrl->pm_mutex); return 0; bhie_error: if (mhi_cntrl->rddm_image) { mhi_free_bhie_table(mhi_cntrl, mhi_cntrl->rddm_image); mhi_cntrl->rddm_image = NULL; } mhi_deinit_free_irq(mhi_cntrl); error_setup_irq: mhi_deinit_dev_ctxt(mhi_cntrl); Loading
drivers/bus/mhi/core/mhi_internal.h +4 −0 Original line number Diff line number Diff line Loading @@ -125,6 +125,10 @@ extern struct bus_type mhi_bus_type; #define MHIDATALIMIT_HIGHER_MHIDATALIMIT_HIGHER_MASK (0xFFFFFFFF) #define MHIDATALIMIT_HIGHER_MHIDATALIMIT_HIGHER_SHIFT (0) /* Host request register */ #define MHI_SOC_RESET_REQ_OFFSET (0xB0) #define MHI_SOC_RESET_REQ BIT(0) /* MHI misc capability registers */ #define MISC_OFFSET (0x24) #define MISC_CAP_MASK (0xFFFFFFFF) Loading
drivers/bus/mhi/core/mhi_main.c +10 −3 Original line number Diff line number Diff line Loading @@ -1381,12 +1381,20 @@ void mhi_ctrl_ev_task(unsigned long data) { struct mhi_event *mhi_event = (struct mhi_event *)data; struct mhi_controller *mhi_cntrl = mhi_event->mhi_cntrl; enum mhi_dev_state state = MHI_STATE_MAX; enum mhi_dev_state state; enum MHI_PM_STATE pm_state = 0; int ret; MHI_VERB("Enter for ev_index:%d\n", mhi_event->er_index); /* * we can check pm_state w/o a lock here because there is no way * pm_state can change from reg access valid to no access while this * therad being executed. */ if (!MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) return; /* process ctrl events events */ ret = mhi_event->process_event(mhi_cntrl, mhi_event, U32_MAX); Loading @@ -1396,7 +1404,6 @@ void mhi_ctrl_ev_task(unsigned long data) */ if (!ret) { write_lock_irq(&mhi_cntrl->pm_lock); if (MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) state = mhi_get_mhi_state(mhi_cntrl); if (state == MHI_STATE_SYS_ERR) { MHI_ERR("MHI system error detected\n"); Loading
drivers/bus/mhi/core/mhi_pm.c +6 −21 Original line number Diff line number Diff line Loading @@ -1045,6 +1045,12 @@ int mhi_pm_resume(struct mhi_controller *mhi_cntrl) MHI_ERR("Did not enter M0 state, cur_state:%s pm_state:%s\n", TO_MHI_STATE_STR(mhi_cntrl->dev_state), to_mhi_pm_state_str(mhi_cntrl->pm_state)); /* * It's possible device already in error state and we didn't * process it due to low power mode, force a check */ mhi_intvec_threaded_handlr(0, mhi_cntrl); return -EIO; } Loading Loading @@ -1124,22 +1130,8 @@ int mhi_force_rddm_mode(struct mhi_controller *mhi_cntrl) to_mhi_pm_state_str(mhi_cntrl->pm_state), TO_MHI_EXEC_STR(mhi_cntrl->ee)); /* before rddm mode, we need to enter M0 state */ ret = __mhi_device_get_sync(mhi_cntrl); if (ret) return ret; mutex_lock(&mhi_cntrl->pm_mutex); write_lock_irq(&mhi_cntrl->pm_lock); if (!MHI_REG_ACCESS_VALID(mhi_cntrl->pm_state)) goto no_reg_access; MHI_LOG("Triggering SYS_ERR to force rddm state\n"); mhi_set_mhi_state(mhi_cntrl, MHI_STATE_SYS_ERR); mhi_cntrl->wake_put(mhi_cntrl, false); write_unlock_irq(&mhi_cntrl->pm_lock); mutex_unlock(&mhi_cntrl->pm_mutex); /* wait for rddm event */ MHI_LOG("Waiting for device to enter RDDM state\n"); Loading @@ -1153,12 +1145,5 @@ int mhi_force_rddm_mode(struct mhi_controller *mhi_cntrl) TO_MHI_EXEC_STR(mhi_cntrl->ee), ret); return ret; no_reg_access: mhi_cntrl->wake_put(mhi_cntrl, false); write_unlock_irq(&mhi_cntrl->pm_lock); mutex_unlock(&mhi_cntrl->pm_mutex); return -EIO; } EXPORT_SYMBOL(mhi_force_rddm_mode);