Loading drivers/bus/mhi/core/mhi_boot.c +51 −25 Original line number Diff line number Diff line Loading @@ -204,17 +204,47 @@ void mhi_rddm_prepare(struct mhi_controller *mhi_cntrl, &mhi_buf->dma_addr, mhi_buf->len, sequence_id); } /* check RDDM image is downloaded */ static int mhi_rddm_download_status(struct mhi_controller *mhi_cntrl) { u32 rx_status; enum mhi_ee ee; const u32 delayms = 5; void __iomem *base = mhi_cntrl->bhie; u32 retry = (mhi_cntrl->timeout_ms) / delayms; int ret = 0; while (retry--) { ret = mhi_read_reg_field(mhi_cntrl, base, BHIE_RXVECSTATUS_OFFS, BHIE_RXVECSTATUS_STATUS_BMSK, BHIE_RXVECSTATUS_STATUS_SHFT, &rx_status); if (ret) return -EIO; if (rx_status == BHIE_RXVECSTATUS_STATUS_XFER_COMPL) { MHI_CNTRL_LOG("RDDM dumps collected successfully"); return 0; } mdelay(delayms); } ee = mhi_get_exec_env(mhi_cntrl); ret = mhi_read_reg(mhi_cntrl, base, BHIE_RXVECSTATUS_OFFS, &rx_status); MHI_ERR("RXVEC_STATUS: 0x%x\n", rx_status); MHI_CNTRL_ERR("Current EE:%s\n", TO_MHI_EXEC_STR(ee)); return -EIO; } /* collect rddm during kernel panic */ static int __mhi_download_rddm_in_panic(struct mhi_controller *mhi_cntrl) { int ret; u32 rx_status; enum mhi_ee ee; const u32 delayms = 5; u32 retry = (mhi_cntrl->timeout_ms) / delayms; const u32 rddm_timeout_ms = 250; int rddm_retry = rddm_timeout_ms / delayms; /* time to enter rddm */ void __iomem *base = mhi_cntrl->bhie; MHI_CNTRL_LOG("Entered with pm_state:%s dev_state:%s ee:%s\n", to_mhi_pm_state_str(mhi_cntrl->pm_state), Loading Loading @@ -269,9 +299,7 @@ static int __mhi_download_rddm_in_panic(struct mhi_controller *mhi_cntrl) /* Hardware reset; force device to enter rddm */ MHI_CNTRL_LOG( "Did not enter RDDM, do a host req. reset\n"); mhi_cntrl->write_reg(mhi_cntrl, mhi_cntrl->regs, MHI_SOC_RESET_REQ_OFFSET, MHI_SOC_RESET_REQ); mhi_soc_reset(mhi_cntrl); mdelay(delayms); } Loading @@ -280,29 +308,14 @@ static int __mhi_download_rddm_in_panic(struct mhi_controller *mhi_cntrl) MHI_CNTRL_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, BHIE_RXVECSTATUS_STATUS_SHFT, &rx_status); if (ret) return -EIO; if (rx_status == BHIE_RXVECSTATUS_STATUS_XFER_COMPL) { MHI_CNTRL_LOG("RDDM successfully collected\n"); ret = mhi_rddm_download_status(mhi_cntrl); if (!ret) { MHI_CNTRL_LOG("RDDM dumps collected successfully"); return 0; } mdelay(delayms); } ee = mhi_get_exec_env(mhi_cntrl); ret = mhi_read_reg(mhi_cntrl, base, BHIE_RXVECSTATUS_OFFS, &rx_status); MHI_CNTRL_ERR("RXVEC_STATUS:0x%x, ret:%d\n", rx_status, ret); err_no_rddm: MHI_CNTRL_ERR("Current EE:%s\n", TO_MHI_EXEC_STR(ee)); MHI_CNTRL_ERR("Did not complete RDDM transfer\n"); return -EIO; Loading Loading @@ -336,6 +349,19 @@ int mhi_download_rddm_img(struct mhi_controller *mhi_cntrl, bool in_panic) } EXPORT_SYMBOL(mhi_download_rddm_img); /* MHI host reset request*/ int mhi_force_reset(struct mhi_controller *mhi_cntrl) { MHI_VERB("Entered with pm_state:%s dev_state:%s ee:%s\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_soc_reset(mhi_cntrl); return mhi_rddm_download_status(mhi_cntrl); } EXPORT_SYMBOL(mhi_force_reset); static int mhi_fw_load_bhie(struct mhi_controller *mhi_cntrl, const struct mhi_buf *mhi_buf) { Loading drivers/bus/mhi/core/mhi_main.c +14 −1 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. */ /* Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. */ #include <linux/debugfs.h> #include <linux/device.h> Loading Loading @@ -266,6 +266,19 @@ enum mhi_dev_state mhi_get_mhi_state(struct mhi_controller *mhi_cntrl) } EXPORT_SYMBOL(mhi_get_mhi_state); void mhi_soc_reset(struct mhi_controller *mhi_cntrl) { if (mhi_cntrl->reset) { mhi_cntrl->reset(mhi_cntrl); return; } /* Generic MHI SoC reset */ mhi_write_reg(mhi_cntrl, mhi_cntrl->regs, MHI_SOC_RESET_REQ_OFFSET, MHI_SOC_RESET_REQ); } EXPORT_SYMBOL(mhi_soc_reset); int mhi_queue_sclist(struct mhi_device *mhi_dev, struct mhi_chan *mhi_chan, void *buf, Loading include/linux/mhi.h +16 −0 Original line number Diff line number Diff line Loading @@ -258,6 +258,7 @@ struct reg_write_info { * @time_get: Return host time in us * @lpm_disable: Request controller to disable link level low power modes * @lpm_enable: Controller may enable link level low power modes again * @reset: Controller specific reset function (optional) * @priv_data: Points to bus master's private data */ struct mhi_controller { Loading Loading @@ -390,6 +391,7 @@ struct mhi_controller { struct mhi_link_info *link_info); void (*write_reg)(struct mhi_controller *mhi_cntrl, void __iomem *base, u32 offset, u32 val); void (*reset)(struct mhi_controller *mhi_cntrl); /* channel to control DTR messaging */ struct mhi_device *dtr_dev; Loading Loading @@ -808,6 +810,13 @@ int mhi_pm_fast_resume(struct mhi_controller *mhi_cntrl, bool notify_client); */ int mhi_download_rddm_img(struct mhi_controller *mhi_cntrl, bool in_panic); /** * mhi_force_reset - does host reset request to collect device side dumps * for debugging purpose * @mhi_cntrl: MHI controller */ int mhi_force_reset(struct mhi_controller *mhi_cntrl); /** * mhi_scan_rddm_cookie - Look for supplied cookie value in the BHI debug * registers set by device to indicate rddm readiness for debugging purposes. Loading Loading @@ -887,6 +896,13 @@ enum mhi_ee mhi_get_exec_env(struct mhi_controller *mhi_cntrl); */ enum mhi_dev_state mhi_get_mhi_state(struct mhi_controller *mhi_cntrl); /** * mhi_soc_reset - Trigger a device reset. This can be used as a last resort * to reset and recover a device. * @mhi_cntrl: MHI controller */ void mhi_soc_reset(struct mhi_controller *mhi_cntrl); /** * mhi_set_mhi_state - Set device state * @mhi_cntrl: MHI controller Loading Loading
drivers/bus/mhi/core/mhi_boot.c +51 −25 Original line number Diff line number Diff line Loading @@ -204,17 +204,47 @@ void mhi_rddm_prepare(struct mhi_controller *mhi_cntrl, &mhi_buf->dma_addr, mhi_buf->len, sequence_id); } /* check RDDM image is downloaded */ static int mhi_rddm_download_status(struct mhi_controller *mhi_cntrl) { u32 rx_status; enum mhi_ee ee; const u32 delayms = 5; void __iomem *base = mhi_cntrl->bhie; u32 retry = (mhi_cntrl->timeout_ms) / delayms; int ret = 0; while (retry--) { ret = mhi_read_reg_field(mhi_cntrl, base, BHIE_RXVECSTATUS_OFFS, BHIE_RXVECSTATUS_STATUS_BMSK, BHIE_RXVECSTATUS_STATUS_SHFT, &rx_status); if (ret) return -EIO; if (rx_status == BHIE_RXVECSTATUS_STATUS_XFER_COMPL) { MHI_CNTRL_LOG("RDDM dumps collected successfully"); return 0; } mdelay(delayms); } ee = mhi_get_exec_env(mhi_cntrl); ret = mhi_read_reg(mhi_cntrl, base, BHIE_RXVECSTATUS_OFFS, &rx_status); MHI_ERR("RXVEC_STATUS: 0x%x\n", rx_status); MHI_CNTRL_ERR("Current EE:%s\n", TO_MHI_EXEC_STR(ee)); return -EIO; } /* collect rddm during kernel panic */ static int __mhi_download_rddm_in_panic(struct mhi_controller *mhi_cntrl) { int ret; u32 rx_status; enum mhi_ee ee; const u32 delayms = 5; u32 retry = (mhi_cntrl->timeout_ms) / delayms; const u32 rddm_timeout_ms = 250; int rddm_retry = rddm_timeout_ms / delayms; /* time to enter rddm */ void __iomem *base = mhi_cntrl->bhie; MHI_CNTRL_LOG("Entered with pm_state:%s dev_state:%s ee:%s\n", to_mhi_pm_state_str(mhi_cntrl->pm_state), Loading Loading @@ -269,9 +299,7 @@ static int __mhi_download_rddm_in_panic(struct mhi_controller *mhi_cntrl) /* Hardware reset; force device to enter rddm */ MHI_CNTRL_LOG( "Did not enter RDDM, do a host req. reset\n"); mhi_cntrl->write_reg(mhi_cntrl, mhi_cntrl->regs, MHI_SOC_RESET_REQ_OFFSET, MHI_SOC_RESET_REQ); mhi_soc_reset(mhi_cntrl); mdelay(delayms); } Loading @@ -280,29 +308,14 @@ static int __mhi_download_rddm_in_panic(struct mhi_controller *mhi_cntrl) MHI_CNTRL_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, BHIE_RXVECSTATUS_STATUS_SHFT, &rx_status); if (ret) return -EIO; if (rx_status == BHIE_RXVECSTATUS_STATUS_XFER_COMPL) { MHI_CNTRL_LOG("RDDM successfully collected\n"); ret = mhi_rddm_download_status(mhi_cntrl); if (!ret) { MHI_CNTRL_LOG("RDDM dumps collected successfully"); return 0; } mdelay(delayms); } ee = mhi_get_exec_env(mhi_cntrl); ret = mhi_read_reg(mhi_cntrl, base, BHIE_RXVECSTATUS_OFFS, &rx_status); MHI_CNTRL_ERR("RXVEC_STATUS:0x%x, ret:%d\n", rx_status, ret); err_no_rddm: MHI_CNTRL_ERR("Current EE:%s\n", TO_MHI_EXEC_STR(ee)); MHI_CNTRL_ERR("Did not complete RDDM transfer\n"); return -EIO; Loading Loading @@ -336,6 +349,19 @@ int mhi_download_rddm_img(struct mhi_controller *mhi_cntrl, bool in_panic) } EXPORT_SYMBOL(mhi_download_rddm_img); /* MHI host reset request*/ int mhi_force_reset(struct mhi_controller *mhi_cntrl) { MHI_VERB("Entered with pm_state:%s dev_state:%s ee:%s\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_soc_reset(mhi_cntrl); return mhi_rddm_download_status(mhi_cntrl); } EXPORT_SYMBOL(mhi_force_reset); static int mhi_fw_load_bhie(struct mhi_controller *mhi_cntrl, const struct mhi_buf *mhi_buf) { Loading
drivers/bus/mhi/core/mhi_main.c +14 −1 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. */ /* Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. */ #include <linux/debugfs.h> #include <linux/device.h> Loading Loading @@ -266,6 +266,19 @@ enum mhi_dev_state mhi_get_mhi_state(struct mhi_controller *mhi_cntrl) } EXPORT_SYMBOL(mhi_get_mhi_state); void mhi_soc_reset(struct mhi_controller *mhi_cntrl) { if (mhi_cntrl->reset) { mhi_cntrl->reset(mhi_cntrl); return; } /* Generic MHI SoC reset */ mhi_write_reg(mhi_cntrl, mhi_cntrl->regs, MHI_SOC_RESET_REQ_OFFSET, MHI_SOC_RESET_REQ); } EXPORT_SYMBOL(mhi_soc_reset); int mhi_queue_sclist(struct mhi_device *mhi_dev, struct mhi_chan *mhi_chan, void *buf, Loading
include/linux/mhi.h +16 −0 Original line number Diff line number Diff line Loading @@ -258,6 +258,7 @@ struct reg_write_info { * @time_get: Return host time in us * @lpm_disable: Request controller to disable link level low power modes * @lpm_enable: Controller may enable link level low power modes again * @reset: Controller specific reset function (optional) * @priv_data: Points to bus master's private data */ struct mhi_controller { Loading Loading @@ -390,6 +391,7 @@ struct mhi_controller { struct mhi_link_info *link_info); void (*write_reg)(struct mhi_controller *mhi_cntrl, void __iomem *base, u32 offset, u32 val); void (*reset)(struct mhi_controller *mhi_cntrl); /* channel to control DTR messaging */ struct mhi_device *dtr_dev; Loading Loading @@ -808,6 +810,13 @@ int mhi_pm_fast_resume(struct mhi_controller *mhi_cntrl, bool notify_client); */ int mhi_download_rddm_img(struct mhi_controller *mhi_cntrl, bool in_panic); /** * mhi_force_reset - does host reset request to collect device side dumps * for debugging purpose * @mhi_cntrl: MHI controller */ int mhi_force_reset(struct mhi_controller *mhi_cntrl); /** * mhi_scan_rddm_cookie - Look for supplied cookie value in the BHI debug * registers set by device to indicate rddm readiness for debugging purposes. Loading Loading @@ -887,6 +896,13 @@ enum mhi_ee mhi_get_exec_env(struct mhi_controller *mhi_cntrl); */ enum mhi_dev_state mhi_get_mhi_state(struct mhi_controller *mhi_cntrl); /** * mhi_soc_reset - Trigger a device reset. This can be used as a last resort * to reset and recover a device. * @mhi_cntrl: MHI controller */ void mhi_soc_reset(struct mhi_controller *mhi_cntrl); /** * mhi_set_mhi_state - Set device state * @mhi_cntrl: MHI controller Loading