[PATCH 10/11] drivers: bus: mhi: host: Add support for MHI MAX TRB capability
Sivareddy Surasani <[email protected]>
| Newsgroups | dev.linux.lists.mhi,org.kernel.vger.linux-arm-msm,org.kernel.vger.linux-doc,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
From: Vivek Pernamitta <[email protected]> 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 <[email protected]> Signed-off-by: Sivareddy Surasani <[email protected]> --- 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