Loading drivers/platform/msm/mhi_dev/mhi.c +87 −18 Original line number Original line Diff line number Diff line Loading @@ -46,7 +46,7 @@ #define MHI_RING_PRIMARY_EVT_ID 1 #define MHI_RING_PRIMARY_EVT_ID 1 #define MHI_1K_SIZE 0x1000 #define MHI_1K_SIZE 0x1000 /* Updated Specification for event start is NER - 2 and end - NER -1 */ /* Updated Specification for event start is NER - 2 and end - NER -1 */ #define MHI_HW_ACC_EVT_RING_START 2 #define MHI_HW_ACC_EVT_RING_START 3 #define MHI_HW_ACC_EVT_RING_END 1 #define MHI_HW_ACC_EVT_RING_END 1 #define MHI_HOST_REGION_NUM 2 #define MHI_HOST_REGION_NUM 2 Loading Loading @@ -843,7 +843,9 @@ static int mhi_hwc_chcmd(struct mhi_dev *mhi, uint chid, case MHI_DEV_RING_EL_START: case MHI_DEV_RING_EL_START: connect_params.channel_id = chid; connect_params.channel_id = chid; connect_params.sys.skip_ep_cfg = true; connect_params.sys.skip_ep_cfg = true; if ((chid % 2) == 0x0) if (chid == MHI_CLIENT_ADPL_IN) connect_params.sys.client = IPA_CLIENT_MHI_DPL_CONS; else if ((chid % 2) == 0x0) connect_params.sys.client = IPA_CLIENT_MHI_PROD; connect_params.sys.client = IPA_CLIENT_MHI_PROD; else else connect_params.sys.client = IPA_CLIENT_MHI_CONS; connect_params.sys.client = IPA_CLIENT_MHI_CONS; Loading Loading @@ -2290,6 +2292,8 @@ int mhi_dev_channel_isempty(struct mhi_dev_client *handle) int rc; int rc; ch = handle->channel; ch = handle->channel; if (!ch) return -EINVAL; rc = ch->ring->rd_offset == ch->ring->wr_offset; rc = ch->ring->rd_offset == ch->ring->wr_offset; Loading Loading @@ -2669,6 +2673,64 @@ int mhi_dev_write_channel(struct mhi_req *wreq) } } EXPORT_SYMBOL(mhi_dev_write_channel); EXPORT_SYMBOL(mhi_dev_write_channel); static int mhi_dev_recover(struct mhi_dev *mhi) { int rc = 0; uint32_t syserr, max_cnt = 0, bhi_intvec = 0; bool mhi_reset; enum mhi_dev_state state; /* Check if MHI is in syserr */ mhi_dev_mmio_masked_read(mhi, MHISTATUS, MHISTATUS_SYSERR_MASK, MHISTATUS_SYSERR_SHIFT, &syserr); mhi_log(MHI_MSG_VERBOSE, "mhi_syserr = 0x%X\n", syserr); if (syserr) { rc = mhi_dev_mmio_read(mhi, BHI_INTVEC, &bhi_intvec); if (rc) return rc; if (bhi_intvec != 0xffffffff) { /* Indicate the host that the device is ready */ rc = ep_pcie_trigger_msi(mhi->phandle, bhi_intvec); if (rc) { pr_err("%s: error sending msi\n", __func__); return rc; } } /* Poll for the host to set the reset bit */ rc = mhi_dev_mmio_get_mhi_state(mhi, &state, &mhi_reset); if (rc) { pr_err("%s: get mhi state failed\n", __func__); return rc; } while (mhi_reset != true && max_cnt < MHI_SUSPEND_TIMEOUT) { /* Wait for Host to set the reset */ msleep(MHI_SUSPEND_MIN); rc = mhi_dev_mmio_get_mhi_state(mhi, &state, &mhi_reset); if (rc) { pr_err("%s: get mhi state failed\n", __func__); return rc; } max_cnt++; } if (!mhi_reset) { mhi_log(MHI_MSG_VERBOSE, "Host failed to set reset\n"); return -EINVAL; } } /* * Now mask the interrupts so that the state machine moves * only after IPA is ready */ mhi_dev_mmio_mask_interrupts(mhi); return 0; } static void mhi_dev_enable(struct work_struct *work) static void mhi_dev_enable(struct work_struct *work) { { int rc = 0; int rc = 0; Loading Loading @@ -3000,11 +3062,7 @@ static int mhi_deinit(struct mhi_dev *mhi) ring->ring_cache_dma_handle); ring->ring_cache_dma_handle); } } for (i = 0; i < mhi->cfg.channels; i++) mutex_destroy(&mhi->ch[i].ch_lock); devm_kfree(&pdev->dev, mhi->mmio_backup); devm_kfree(&pdev->dev, mhi->mmio_backup); devm_kfree(&pdev->dev, mhi->ch); devm_kfree(&pdev->dev, mhi->ring); devm_kfree(&pdev->dev, mhi->ring); mhi_dev_sm_exit(mhi); mhi_dev_sm_exit(mhi); Loading Loading @@ -3032,6 +3090,11 @@ static int mhi_init(struct mhi_dev *mhi) if (!mhi->ring) if (!mhi->ring) return -ENOMEM; return -ENOMEM; /* * mhi_init is also called during device reset, in * which case channel mem will already be allocated. */ if (!mhi->ch) { mhi->ch = devm_kzalloc(&pdev->dev, mhi->ch = devm_kzalloc(&pdev->dev, (sizeof(struct mhi_dev_channel) * (sizeof(struct mhi_dev_channel) * (mhi->cfg.channels)), GFP_KERNEL); (mhi->cfg.channels)), GFP_KERNEL); Loading @@ -3040,6 +3103,7 @@ static int mhi_init(struct mhi_dev *mhi) for (i = 0; i < mhi->cfg.channels; i++) for (i = 0; i < mhi->cfg.channels; i++) mutex_init(&mhi->ch[i].ch_lock); mutex_init(&mhi->ch[i].ch_lock); } spin_lock_init(&mhi->lock); spin_lock_init(&mhi->lock); mhi->mmio_backup = devm_kzalloc(&pdev->dev, mhi->mmio_backup = devm_kzalloc(&pdev->dev, Loading Loading @@ -3180,6 +3244,18 @@ static int mhi_dev_resume_mmio_mhi_init(struct mhi_dev *mhi_ctx) mutex_init(&mhi_ctx->mhi_event_lock); mutex_init(&mhi_ctx->mhi_event_lock); mutex_init(&mhi_ctx->mhi_write_test); mutex_init(&mhi_ctx->mhi_write_test); mhi_ctx->phandle = ep_pcie_get_phandle(mhi_ctx->ifc_id); if (!mhi_ctx->phandle) { pr_err("PCIe driver get handle failed.\n"); return -EINVAL; } rc = mhi_dev_recover(mhi_ctx); if (rc) { pr_err("%s: get mhi state failed\n", __func__); return rc; } rc = mhi_init(mhi_ctx); rc = mhi_init(mhi_ctx); if (rc) if (rc) return rc; return rc; Loading Loading @@ -3209,13 +3285,6 @@ static int mhi_dev_resume_mmio_mhi_init(struct mhi_dev *mhi_ctx) pr_err("Failed to update the MHI version\n"); pr_err("Failed to update the MHI version\n"); return rc; return rc; } } mhi_ctx->phandle = ep_pcie_get_phandle(mhi_ctx->ifc_id); if (!mhi_ctx->phandle) { pr_err("PCIe driver get handle failed.\n"); return -EINVAL; } mhi_ctx->event_reg.events = EP_PCIE_EVENT_PM_D3_HOT | mhi_ctx->event_reg.events = EP_PCIE_EVENT_PM_D3_HOT | EP_PCIE_EVENT_PM_D3_COLD | EP_PCIE_EVENT_PM_D3_COLD | EP_PCIE_EVENT_PM_D0 | EP_PCIE_EVENT_PM_D0 | Loading drivers/platform/msm/mhi_dev/mhi.h +6 −0 Original line number Original line Diff line number Diff line Loading @@ -882,6 +882,12 @@ int mhi_dev_mmio_mask_erdb_interrupts(struct mhi_dev *dev); */ */ int mhi_dev_mmio_read_erdb_status_interrupts(struct mhi_dev *dev); int mhi_dev_mmio_read_erdb_status_interrupts(struct mhi_dev *dev); /** * mhi_dev_mmio_mask_interrupts() - Mask all MHI interrupts. * @dev: MHI device structure. */ void mhi_dev_mmio_mask_interrupts(struct mhi_dev *dev); /** /** * mhi_dev_mmio_clear_interrupts() - Clear all doorbell interrupts. * mhi_dev_mmio_clear_interrupts() - Clear all doorbell interrupts. * @dev: MHI device structure. * @dev: MHI device structure. Loading drivers/platform/msm/mhi_dev/mhi_mmio.c +2 −1 Original line number Original line Diff line number Diff line Loading @@ -389,7 +389,7 @@ int mhi_dev_mmio_disable_cmdb_interrupt(struct mhi_dev *dev) } } EXPORT_SYMBOL(mhi_dev_mmio_disable_cmdb_interrupt); EXPORT_SYMBOL(mhi_dev_mmio_disable_cmdb_interrupt); static void mhi_dev_mmio_mask_interrupts(struct mhi_dev *dev) void mhi_dev_mmio_mask_interrupts(struct mhi_dev *dev) { { mhi_dev_mmio_disable_ctrl_interrupt(dev); mhi_dev_mmio_disable_ctrl_interrupt(dev); Loading @@ -399,6 +399,7 @@ static void mhi_dev_mmio_mask_interrupts(struct mhi_dev *dev) mhi_dev_mmio_mask_erdb_interrupts(dev); mhi_dev_mmio_mask_erdb_interrupts(dev); } } EXPORT_SYMBOL(mhi_dev_mmio_mask_interrupts); int mhi_dev_mmio_clear_interrupts(struct mhi_dev *dev) int mhi_dev_mmio_clear_interrupts(struct mhi_dev *dev) { { Loading Loading
drivers/platform/msm/mhi_dev/mhi.c +87 −18 Original line number Original line Diff line number Diff line Loading @@ -46,7 +46,7 @@ #define MHI_RING_PRIMARY_EVT_ID 1 #define MHI_RING_PRIMARY_EVT_ID 1 #define MHI_1K_SIZE 0x1000 #define MHI_1K_SIZE 0x1000 /* Updated Specification for event start is NER - 2 and end - NER -1 */ /* Updated Specification for event start is NER - 2 and end - NER -1 */ #define MHI_HW_ACC_EVT_RING_START 2 #define MHI_HW_ACC_EVT_RING_START 3 #define MHI_HW_ACC_EVT_RING_END 1 #define MHI_HW_ACC_EVT_RING_END 1 #define MHI_HOST_REGION_NUM 2 #define MHI_HOST_REGION_NUM 2 Loading Loading @@ -843,7 +843,9 @@ static int mhi_hwc_chcmd(struct mhi_dev *mhi, uint chid, case MHI_DEV_RING_EL_START: case MHI_DEV_RING_EL_START: connect_params.channel_id = chid; connect_params.channel_id = chid; connect_params.sys.skip_ep_cfg = true; connect_params.sys.skip_ep_cfg = true; if ((chid % 2) == 0x0) if (chid == MHI_CLIENT_ADPL_IN) connect_params.sys.client = IPA_CLIENT_MHI_DPL_CONS; else if ((chid % 2) == 0x0) connect_params.sys.client = IPA_CLIENT_MHI_PROD; connect_params.sys.client = IPA_CLIENT_MHI_PROD; else else connect_params.sys.client = IPA_CLIENT_MHI_CONS; connect_params.sys.client = IPA_CLIENT_MHI_CONS; Loading Loading @@ -2290,6 +2292,8 @@ int mhi_dev_channel_isempty(struct mhi_dev_client *handle) int rc; int rc; ch = handle->channel; ch = handle->channel; if (!ch) return -EINVAL; rc = ch->ring->rd_offset == ch->ring->wr_offset; rc = ch->ring->rd_offset == ch->ring->wr_offset; Loading Loading @@ -2669,6 +2673,64 @@ int mhi_dev_write_channel(struct mhi_req *wreq) } } EXPORT_SYMBOL(mhi_dev_write_channel); EXPORT_SYMBOL(mhi_dev_write_channel); static int mhi_dev_recover(struct mhi_dev *mhi) { int rc = 0; uint32_t syserr, max_cnt = 0, bhi_intvec = 0; bool mhi_reset; enum mhi_dev_state state; /* Check if MHI is in syserr */ mhi_dev_mmio_masked_read(mhi, MHISTATUS, MHISTATUS_SYSERR_MASK, MHISTATUS_SYSERR_SHIFT, &syserr); mhi_log(MHI_MSG_VERBOSE, "mhi_syserr = 0x%X\n", syserr); if (syserr) { rc = mhi_dev_mmio_read(mhi, BHI_INTVEC, &bhi_intvec); if (rc) return rc; if (bhi_intvec != 0xffffffff) { /* Indicate the host that the device is ready */ rc = ep_pcie_trigger_msi(mhi->phandle, bhi_intvec); if (rc) { pr_err("%s: error sending msi\n", __func__); return rc; } } /* Poll for the host to set the reset bit */ rc = mhi_dev_mmio_get_mhi_state(mhi, &state, &mhi_reset); if (rc) { pr_err("%s: get mhi state failed\n", __func__); return rc; } while (mhi_reset != true && max_cnt < MHI_SUSPEND_TIMEOUT) { /* Wait for Host to set the reset */ msleep(MHI_SUSPEND_MIN); rc = mhi_dev_mmio_get_mhi_state(mhi, &state, &mhi_reset); if (rc) { pr_err("%s: get mhi state failed\n", __func__); return rc; } max_cnt++; } if (!mhi_reset) { mhi_log(MHI_MSG_VERBOSE, "Host failed to set reset\n"); return -EINVAL; } } /* * Now mask the interrupts so that the state machine moves * only after IPA is ready */ mhi_dev_mmio_mask_interrupts(mhi); return 0; } static void mhi_dev_enable(struct work_struct *work) static void mhi_dev_enable(struct work_struct *work) { { int rc = 0; int rc = 0; Loading Loading @@ -3000,11 +3062,7 @@ static int mhi_deinit(struct mhi_dev *mhi) ring->ring_cache_dma_handle); ring->ring_cache_dma_handle); } } for (i = 0; i < mhi->cfg.channels; i++) mutex_destroy(&mhi->ch[i].ch_lock); devm_kfree(&pdev->dev, mhi->mmio_backup); devm_kfree(&pdev->dev, mhi->mmio_backup); devm_kfree(&pdev->dev, mhi->ch); devm_kfree(&pdev->dev, mhi->ring); devm_kfree(&pdev->dev, mhi->ring); mhi_dev_sm_exit(mhi); mhi_dev_sm_exit(mhi); Loading Loading @@ -3032,6 +3090,11 @@ static int mhi_init(struct mhi_dev *mhi) if (!mhi->ring) if (!mhi->ring) return -ENOMEM; return -ENOMEM; /* * mhi_init is also called during device reset, in * which case channel mem will already be allocated. */ if (!mhi->ch) { mhi->ch = devm_kzalloc(&pdev->dev, mhi->ch = devm_kzalloc(&pdev->dev, (sizeof(struct mhi_dev_channel) * (sizeof(struct mhi_dev_channel) * (mhi->cfg.channels)), GFP_KERNEL); (mhi->cfg.channels)), GFP_KERNEL); Loading @@ -3040,6 +3103,7 @@ static int mhi_init(struct mhi_dev *mhi) for (i = 0; i < mhi->cfg.channels; i++) for (i = 0; i < mhi->cfg.channels; i++) mutex_init(&mhi->ch[i].ch_lock); mutex_init(&mhi->ch[i].ch_lock); } spin_lock_init(&mhi->lock); spin_lock_init(&mhi->lock); mhi->mmio_backup = devm_kzalloc(&pdev->dev, mhi->mmio_backup = devm_kzalloc(&pdev->dev, Loading Loading @@ -3180,6 +3244,18 @@ static int mhi_dev_resume_mmio_mhi_init(struct mhi_dev *mhi_ctx) mutex_init(&mhi_ctx->mhi_event_lock); mutex_init(&mhi_ctx->mhi_event_lock); mutex_init(&mhi_ctx->mhi_write_test); mutex_init(&mhi_ctx->mhi_write_test); mhi_ctx->phandle = ep_pcie_get_phandle(mhi_ctx->ifc_id); if (!mhi_ctx->phandle) { pr_err("PCIe driver get handle failed.\n"); return -EINVAL; } rc = mhi_dev_recover(mhi_ctx); if (rc) { pr_err("%s: get mhi state failed\n", __func__); return rc; } rc = mhi_init(mhi_ctx); rc = mhi_init(mhi_ctx); if (rc) if (rc) return rc; return rc; Loading Loading @@ -3209,13 +3285,6 @@ static int mhi_dev_resume_mmio_mhi_init(struct mhi_dev *mhi_ctx) pr_err("Failed to update the MHI version\n"); pr_err("Failed to update the MHI version\n"); return rc; return rc; } } mhi_ctx->phandle = ep_pcie_get_phandle(mhi_ctx->ifc_id); if (!mhi_ctx->phandle) { pr_err("PCIe driver get handle failed.\n"); return -EINVAL; } mhi_ctx->event_reg.events = EP_PCIE_EVENT_PM_D3_HOT | mhi_ctx->event_reg.events = EP_PCIE_EVENT_PM_D3_HOT | EP_PCIE_EVENT_PM_D3_COLD | EP_PCIE_EVENT_PM_D3_COLD | EP_PCIE_EVENT_PM_D0 | EP_PCIE_EVENT_PM_D0 | Loading
drivers/platform/msm/mhi_dev/mhi.h +6 −0 Original line number Original line Diff line number Diff line Loading @@ -882,6 +882,12 @@ int mhi_dev_mmio_mask_erdb_interrupts(struct mhi_dev *dev); */ */ int mhi_dev_mmio_read_erdb_status_interrupts(struct mhi_dev *dev); int mhi_dev_mmio_read_erdb_status_interrupts(struct mhi_dev *dev); /** * mhi_dev_mmio_mask_interrupts() - Mask all MHI interrupts. * @dev: MHI device structure. */ void mhi_dev_mmio_mask_interrupts(struct mhi_dev *dev); /** /** * mhi_dev_mmio_clear_interrupts() - Clear all doorbell interrupts. * mhi_dev_mmio_clear_interrupts() - Clear all doorbell interrupts. * @dev: MHI device structure. * @dev: MHI device structure. Loading
drivers/platform/msm/mhi_dev/mhi_mmio.c +2 −1 Original line number Original line Diff line number Diff line Loading @@ -389,7 +389,7 @@ int mhi_dev_mmio_disable_cmdb_interrupt(struct mhi_dev *dev) } } EXPORT_SYMBOL(mhi_dev_mmio_disable_cmdb_interrupt); EXPORT_SYMBOL(mhi_dev_mmio_disable_cmdb_interrupt); static void mhi_dev_mmio_mask_interrupts(struct mhi_dev *dev) void mhi_dev_mmio_mask_interrupts(struct mhi_dev *dev) { { mhi_dev_mmio_disable_ctrl_interrupt(dev); mhi_dev_mmio_disable_ctrl_interrupt(dev); Loading @@ -399,6 +399,7 @@ static void mhi_dev_mmio_mask_interrupts(struct mhi_dev *dev) mhi_dev_mmio_mask_erdb_interrupts(dev); mhi_dev_mmio_mask_erdb_interrupts(dev); } } EXPORT_SYMBOL(mhi_dev_mmio_mask_interrupts); int mhi_dev_mmio_clear_interrupts(struct mhi_dev *dev) int mhi_dev_mmio_clear_interrupts(struct mhi_dev *dev) { { Loading