diff --git a/drivers/platform/msm/ep_pcie/ep_pcie_com.h b/drivers/platform/msm/ep_pcie/ep_pcie_com.h index 2dc2dd0d5d49..7776b6bae902 100644 --- a/drivers/platform/msm/ep_pcie/ep_pcie_com.h +++ b/drivers/platform/msm/ep_pcie/ep_pcie_com.h @@ -176,7 +176,7 @@ #define MAX_IATU_ENTRY_NUM 2 #define EP_PCIE_LOG_PAGES 50 -#define EP_PCIE_MAX_VREG 3 +#define EP_PCIE_MAX_VREG 4 #define EP_PCIE_MAX_CLK 10 #define EP_PCIE_MAX_PIPE_CLK 1 #define EP_PCIE_MAX_RESET 2 diff --git a/drivers/platform/msm/ep_pcie/ep_pcie_core.c b/drivers/platform/msm/ep_pcie/ep_pcie_core.c index daa0abc5f5e2..59068faa1b77 100644 --- a/drivers/platform/msm/ep_pcie/ep_pcie_core.c +++ b/drivers/platform/msm/ep_pcie/ep_pcie_core.c @@ -5,6 +5,7 @@ * MSM PCIe endpoint core driver. */ +#include #include #include #include @@ -52,9 +53,10 @@ static u32 clkreq_irq; struct ep_pcie_dev_t ep_pcie_dev = {0}; static struct ep_pcie_vreg_info_t ep_pcie_vreg_info[EP_PCIE_MAX_VREG] = { - {NULL, "vreg-1p8", 1200000, 1200000, 3000, true}, + {NULL, "vreg-1p8", 1200000, 1200000, 30000, true}, {NULL, "vreg-0p9", 912000, 912000, 132000, true}, - {NULL, "vreg-cx", 0, 0, 0, false} + {NULL, "vreg-cx", 0, 0, 0, false}, + {NULL, "vreg-mx", 0, 0, 0, false} }; static struct ep_pcie_gpio_info_t ep_pcie_gpio_info[EP_PCIE_MAX_GPIO] = { @@ -311,8 +313,15 @@ static int ep_pcie_vreg_init(struct ep_pcie_dev_t *dev) while (i--) { struct regulator *hdl = dev->vreg[i].hdl; - if (hdl) + if (hdl) { regulator_disable(hdl); + if (!strcmp(dev->vreg[i].name, "vreg-mx")) { + EP_PCIE_DBG(dev, "PCIe V%d: Removing vote for %s.\n", + dev->rev, dev->vreg[i].name); + regulator_set_voltage(hdl, RPMH_REGULATOR_LEVEL_RETENTION, + RPMH_REGULATOR_LEVEL_MAX); + } + } } return rc; @@ -329,6 +338,12 @@ static void ep_pcie_vreg_deinit(struct ep_pcie_dev_t *dev) EP_PCIE_DBG(dev, "Vreg %s is being disabled\n", dev->vreg[i].name); regulator_disable(dev->vreg[i].hdl); + if (!strcmp(dev->vreg[i].name, "vreg-mx")) { + EP_PCIE_DBG(dev, "PCIe V%d: Removing vote for %s.\n", + dev->rev, dev->vreg[i].name); + regulator_set_voltage(dev->vreg[i].hdl, + RPMH_REGULATOR_LEVEL_RETENTION, RPMH_REGULATOR_LEVEL_MAX); + } } } } diff --git a/drivers/platform/msm/mhi_dev/mhi.c b/drivers/platform/msm/mhi_dev/mhi.c index f93ed5a83761..fab33e09d435 100644 --- a/drivers/platform/msm/mhi_dev/mhi.c +++ b/drivers/platform/msm/mhi_dev/mhi.c @@ -1803,8 +1803,10 @@ static void mhi_dev_process_cmd_ring(struct mhi_dev *mhi, return; } } + mutex_lock(&mhi->ch[ch_id].ch_lock); mhi_dev_alloc_evt_buf_evt_req(mhi, &mhi->ch[ch_id], evt_ring); + mutex_unlock(&mhi->ch[ch_id].ch_lock); } if (MHI_USE_DMA(mhi)) @@ -3429,8 +3431,14 @@ static void mhi_dev_enable(struct work_struct *work) pr_err("%s: get mhi state failed\n", __func__); return; } + if (mhi_reset) { + mhi_dev_mmio_clear_reset(mhi); + mhi_log(MHI_MSG_VERBOSE, + "Cleared reset before waiting for M0\n"); + } - while (state != MHI_DEV_M0_STATE && max_cnt < MHI_SUSPEND_TIMEOUT) { + while (state != MHI_DEV_M0_STATE && + ((max_cnt < MHI_SUSPEND_TIMEOUT) || mhi->no_m0_timeout)) { /* Wait for Host to set the M0 state */ msleep(MHI_SUSPEND_MIN); rc = mhi_dev_mmio_get_mhi_state(mhi, &state, &mhi_reset); @@ -3438,6 +3446,11 @@ static void mhi_dev_enable(struct work_struct *work) pr_err("%s: get mhi state failed\n", __func__); return; } + if (mhi_reset) { + mhi_dev_mmio_clear_reset(mhi); + mhi_log(MHI_MSG_VERBOSE, + "Cleared reset while waiting for M0\n"); + } max_cnt++; } @@ -3694,6 +3707,9 @@ static int get_device_tree_data(struct platform_device *pdev) mhi->enable_m2 = of_property_read_bool((&pdev->dev)->of_node, "qcom,enable-m2"); + mhi->no_m0_timeout = of_property_read_bool((&pdev->dev)->of_node, + "qcom,no-m0-timeout"); + mhi_log(MHI_MSG_VERBOSE, "acquiring wakelock\n"); return 0; diff --git a/drivers/platform/msm/mhi_dev/mhi.h b/drivers/platform/msm/mhi_dev/mhi.h index e73692205307..10e9ca3145dc 100644 --- a/drivers/platform/msm/mhi_dev/mhi.h +++ b/drivers/platform/msm/mhi_dev/mhi.h @@ -610,9 +610,13 @@ struct mhi_dev { /*Register for interrupt*/ bool mhi_int; bool mhi_int_en; + /* Enable M2 autonomous mode from MHI */ bool enable_m2; + /* Dont timeout waiting for M0 */ + bool no_m0_timeout; + /* Registered client callback list */ struct list_head client_cb_list; /* Tx, Rx DMA channels */ @@ -981,6 +985,12 @@ int mhi_dev_mmio_get_cmd_db(struct mhi_dev_ring *ring, uint64_t *wr_offset); */ int mhi_dev_mmio_set_env(struct mhi_dev *dev, uint32_t value); +/** + * mhi_dev_mmio_clear_reset() - Clear the reset bit + * @dev: MHI device structure. + */ +int mhi_dev_mmio_clear_reset(struct mhi_dev *dev); + /** * mhi_dev_mmio_reset() - Reset the MMIO done as part of initialization. * @dev: MHI device structure. diff --git a/drivers/platform/msm/mhi_dev/mhi_mmio.c b/drivers/platform/msm/mhi_dev/mhi_mmio.c index b0cc8673fe03..71fa971dc8eb 100644 --- a/drivers/platform/msm/mhi_dev/mhi_mmio.c +++ b/drivers/platform/msm/mhi_dev/mhi_mmio.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2015,2017-2020, The Linux Foundation. All rights reserved.*/ +/* Copyright (c) 2015,2017-2021, The Linux Foundation. All rights reserved.*/ #include #include @@ -574,6 +574,18 @@ int mhi_dev_mmio_set_env(struct mhi_dev *dev, uint32_t value) } EXPORT_SYMBOL(mhi_dev_mmio_set_env); +int mhi_dev_mmio_clear_reset(struct mhi_dev *dev) +{ + if (WARN_ON(!dev)) + return -EINVAL; + + mhi_dev_mmio_masked_write(dev, MHICTRL, + MHICTRL_RESET_MASK, MHICTRL_RESET_SHIFT, 0); + + return 0; +} +EXPORT_SYMBOL(mhi_dev_mmio_clear_reset); + int mhi_dev_mmio_reset(struct mhi_dev *dev) { if (WARN_ON(!dev)) diff --git a/drivers/platform/msm/mhi_dev/mhi_sm.c b/drivers/platform/msm/mhi_dev/mhi_sm.c index 3c53ea89403d..7e3be7654729 100644 --- a/drivers/platform/msm/mhi_dev/mhi_sm.c +++ b/drivers/platform/msm/mhi_dev/mhi_sm.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -/* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.*/ +/* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.*/ #include #include @@ -1429,7 +1429,7 @@ void mhi_dev_sm_pcie_handler(struct ep_pcie_notify *notify) dstate_change_evt->event = event; INIT_WORK(&dstate_change_evt->work, mhi_sm_pcie_event_manager); - queue_work(mhi_sm_ctx->mhi_sm_wq, &dstate_change_evt->work); + queue_work(system_highpri_wq, &dstate_change_evt->work); atomic_inc(&mhi_sm_ctx->pending_pcie_events); exit: diff --git a/drivers/platform/msm/mhi_dev/mhi_uci.c b/drivers/platform/msm/mhi_dev/mhi_uci.c index e4edf6f97730..e694f086bac8 100644 --- a/drivers/platform/msm/mhi_dev/mhi_uci.c +++ b/drivers/platform/msm/mhi_dev/mhi_uci.c @@ -1941,7 +1941,7 @@ static void mhi_uci_at_ctrl_tre_cb(struct mhi_dev_client_cb_reason *reason) static void mhi_uci_at_ctrl_client_cb(struct mhi_dev_client_cb_data *cb_data) { struct uci_client *client = cb_data->user_data; - int rc; + int rc, i; struct mhi_req *ureq; uci_log(UCI_DBG_VERBOSE, " Rcvd MHI cb for channel %d, state %d\n", @@ -1980,6 +1980,12 @@ static void mhi_uci_at_ctrl_client_cb(struct mhi_dev_client_cb_data *cb_data) /* Add to in-use list */ list_add_tail(&ureq->list, &client->req_list); } + + for (i = 0; i < (client->in_chan_attr->nr_trbs); i++) { + kfree(client->in_buf_list[i].addr); + client->in_buf_list[i].addr = NULL; + client->in_buf_list[i].buf_size = 0; + } } }