[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20251211-siva_mhi_dp2-v1-10-d2895c4ec73a@oss.qualcomm.com>
Date: Thu, 11 Dec 2025 13:37:42 +0530
From: Sivareddy Surasani <sivareddy.surasani@....qualcomm.com>
To: Manivannan Sadhasivam <mani@...nel.org>, Jonathan Corbet <corbet@....net>,
Arnd Bergmann <arnd@...db.de>,
Greg Kroah-Hartman <gregkh@...uxfoundation.org>
Cc: mhi@...ts.linux.dev, linux-arm-msm@...r.kernel.org,
linux-kernel@...r.kernel.org, linux-doc@...r.kernel.org,
Upal Kumar Saha <upal.saha@....qualcomm.com>,
Himanshu Shukla <quic_himashuk@...cinc.com>,
Sivareddy Surasani <sivareddy.surasani@....qualcomm.com>,
Vivek Pernamitta <vivek.pernamitta@....qualcomm.com>
Subject: [PATCH 10/11] drivers: bus: mhi: host: Add support for MHI MAX TRB
capability
From: Vivek Pernamitta <vivek.pernamitta@....qualcomm.com>
Read the MHI capability for MAX TRB length if device is supporting.
Use this information to send MHI data with a higher TRB length, as
supported by the device.
Signed-off-by: Vivek Pernamitta <vivek.pernamitta@....qualcomm.com>
Signed-off-by: Sivareddy Surasani <sivareddy.surasani@....qualcomm.com>
---
drivers/bus/mhi/common.h | 9 ++++++++-
drivers/bus/mhi/host/init.c | 21 +++++++++++++++++++++
drivers/bus/mhi/host/main.c | 17 ++++++++++++++---
include/linux/mhi.h | 2 ++
4 files changed, 45 insertions(+), 4 deletions(-)
diff --git a/drivers/bus/mhi/common.h b/drivers/bus/mhi/common.h
index 3b3ecbc6169f..4962035f4693 100644
--- a/drivers/bus/mhi/common.h
+++ b/drivers/bus/mhi/common.h
@@ -158,6 +158,8 @@
#define MHI_TRE_GET_EV_PTR(tre) le64_to_cpu((tre)->ptr)
#define MHI_TRE_GET_EV_CODE(tre) FIELD_GET(GENMASK(31, 24), (MHI_TRE_GET_DWORD(tre, 0)))
#define MHI_TRE_GET_EV_LEN(tre) FIELD_GET(GENMASK(15, 0), (MHI_TRE_GET_DWORD(tre, 0)))
+#define MHI_TRE_GET_EV_LEN_MAX_TRB(max_trb, tre) (GENMASK(__fls(max_trb), 0) & \
+ (MHI_TRE_GET_DWORD(tre, 0)))
#define MHI_TRE_GET_EV_CHID(tre) FIELD_GET(GENMASK(31, 24), (MHI_TRE_GET_DWORD(tre, 1)))
#define MHI_TRE_GET_EV_TYPE(tre) FIELD_GET(GENMASK(23, 16), (MHI_TRE_GET_DWORD(tre, 1)))
#define MHI_TRE_GET_EV_STATE(tre) FIELD_GET(GENMASK(31, 24), (MHI_TRE_GET_DWORD(tre, 0)))
@@ -188,6 +190,7 @@
/* Transfer descriptor macros */
#define MHI_TRE_DATA_PTR(ptr) cpu_to_le64(ptr)
#define MHI_TRE_DATA_DWORD0(len) cpu_to_le32(FIELD_PREP(GENMASK(15, 0), len))
+#define MHI_TRE_DATA_DWORD0_MAX_TREB_CAP(max_len, len) ((GENMASK(__fls(max_len), 0)) & (len))
#define MHI_TRE_TYPE_TRANSFER 2
#define MHI_TRE_DATA_DWORD1(bei, ieot, ieob, chain) cpu_to_le32(FIELD_PREP(GENMASK(23, 16), \
MHI_TRE_TYPE_TRANSFER) | \
@@ -206,7 +209,11 @@
#define MHI_RSCTRE_DATA_PTR(ptr, len) cpu_to_le64(FIELD_PREP(GENMASK(64, 48), len) | ptr)
#define MHI_RSCTRE_DATA_DWORD0(cookie) cpu_to_le32(cookie)
#define MHI_RSCTRE_DATA_DWORD1 cpu_to_le32(FIELD_PREP(GENMASK(23, 16), \
- MHI_PKT_TYPE_COALESCING))
+ MHI_PKT_TYPE_COALESCING))
+
+/* MHI Max TRB Length CAP ID */
+#define MAX_TRB_LEN_CAP_ID 0x5
+#define MAX_TRB_LEN_CFG 0x4
enum mhi_capability_type {
MHI_CAP_ID_INTX = 0x1,
diff --git a/drivers/bus/mhi/host/init.c b/drivers/bus/mhi/host/init.c
index 50f96f2c823f..b0982cb24fb9 100644
--- a/drivers/bus/mhi/host/init.c
+++ b/drivers/bus/mhi/host/init.c
@@ -500,6 +500,25 @@ static int mhi_find_capability(struct mhi_controller *mhi_cntrl, u32 capability,
return -ENXIO;
}
+static int mhi_init_ext_trb_len(struct mhi_controller *mhi_cntrl)
+{
+ struct device *dev = &mhi_cntrl->mhi_dev->dev;
+ u32 trb_offset;
+ int ret;
+
+ ret = mhi_find_capability(mhi_cntrl, MAX_TRB_LEN_CAP_ID, &trb_offset);
+ if (ret)
+ return ret;
+
+ /* Get max TRB length */
+ ret = mhi_read_reg(mhi_cntrl, mhi_cntrl->regs,
+ trb_offset + MAX_TRB_LEN_CFG, &mhi_cntrl->ext_trb_len);
+
+ dev_dbg(dev, "Max TRB length supported is : 0x%x\n", mhi_cntrl->ext_trb_len);
+
+ return 0;
+}
+
int mhi_init_mmio(struct mhi_controller *mhi_cntrl)
{
u32 val;
@@ -637,6 +656,8 @@ int mhi_init_mmio(struct mhi_controller *mhi_cntrl)
return ret;
}
+ ret = mhi_init_ext_trb_len(mhi_cntrl);
+
return 0;
}
diff --git a/drivers/bus/mhi/host/main.c b/drivers/bus/mhi/host/main.c
index 6be15297829d..a11bddce2182 100644
--- a/drivers/bus/mhi/host/main.c
+++ b/drivers/bus/mhi/host/main.c
@@ -648,7 +648,12 @@ static int parse_xfer_event(struct mhi_controller *mhi_cntrl,
buf_info = buf_ring->rp;
/* If it's the last TRE, get length from the event */
if (local_rp == ev_tre) {
- xfer_len = MHI_TRE_GET_EV_LEN(event);
+ if (mhi_cntrl->ext_trb_len)
+ xfer_len = MHI_TRE_GET_EV_LEN_MAX_TRB(
+ mhi_cntrl->ext_trb_len,
+ event);
+ else
+ xfer_len = MHI_TRE_GET_EV_LEN(event);
send_cb = true;
} else {
xfer_len = buf_info->len;
@@ -664,7 +669,7 @@ static int parse_xfer_event(struct mhi_controller *mhi_cntrl,
/* truncate to buf len if xfer_len is larger */
result.bytes_xferd =
- min_t(u16, xfer_len, buf_info->len);
+ min_t(u32, xfer_len, buf_info->len);
mhi_del_ring_element(mhi_cntrl, buf_ring);
mhi_del_ring_element(mhi_cntrl, tre_ring);
local_rp = tre_ring->rp;
@@ -1288,7 +1293,13 @@ int __mhi_gen_tre(struct mhi_controller *mhi_cntrl, struct mhi_chan *mhi_chan,
mhi_tre = tre_ring->wp;
mhi_tre->ptr = MHI_TRE_DATA_PTR(buf_info->p_addr);
- mhi_tre->dword[0] = MHI_TRE_DATA_DWORD0(info->len);
+
+ if (mhi_cntrl->ext_trb_len)
+ mhi_tre->dword[0] = MHI_TRE_DATA_DWORD0_MAX_TREB_CAP(mhi_cntrl->ext_trb_len,
+ info->len);
+ else
+ mhi_tre->dword[0] = MHI_TRE_DATA_DWORD0(info->len);
+
mhi_tre->dword[1] = MHI_TRE_DATA_DWORD1(bei, eot, eob, chain);
if (mhi_chan->dir == DMA_TO_DEVICE)
diff --git a/include/linux/mhi.h b/include/linux/mhi.h
index 013bc2d82196..0d78a95c2fa2 100644
--- a/include/linux/mhi.h
+++ b/include/linux/mhi.h
@@ -370,6 +370,7 @@ struct mhi_controller_config {
* @wake_set: Device wakeup set flag
* @irq_flags: irq flags passed to request_irq (optional)
* @mru: the default MRU for the MHI device
+ * @ext_trb_len: Extended TRB length if device supports (optional)
*
* Fields marked as (required) need to be populated by the controller driver
* before calling mhi_register_controller(). For the fields marked as (optional)
@@ -455,6 +456,7 @@ struct mhi_controller {
bool wake_set;
unsigned long irq_flags;
u32 mru;
+ u32 ext_trb_len;
};
/**
--
2.34.1
Powered by blists - more mailing lists