mirror of
https://github.com/torvalds/linux.git
synced 2025-04-09 14:45:27 +00:00
bus: mhi: host: Add a policy to enable image transfer via BHIe in PBL
Currently, MHI host only performs firmware transfer via BHI in PBL and BHIe from SBL. To support BHIe transfer directly from PBL, a policy needs to be added. With this policy, BHIe will be used to transfer firmware in PBL if the MHI controller has BHIe regs, sets seg_len, and does not set fbc_download. The intention is to transfer firmware using BHIe in PBL without further BHIe transfers in SBL. Signed-off-by: Matthew Leung <quic_mattleun@quicinc.com> Reviewed-by: Youssef Samir <quic_yabdulra@quicinc.com> Reviewed-by: Jeffrey Hugo <quic_jhugo@quicinc.com> Signed-off-by: Jeffrey Hugo <quic_jhugo@quicinc.com> Reviewed-by: Jacek Lawrynowicz <jacek.lawrynowicz@linux.intel.com> Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> Link: https://patchwork.freedesktop.org/patch/msgid/20250117170943.2643280-3-quic_jhugo@quicinc.com
This commit is contained in:
parent
d07569ebcb
commit
f88f1d0998
@ -440,12 +440,59 @@ static void mhi_firmware_copy_bhie(struct mhi_controller *mhi_cntrl,
|
||||
}
|
||||
}
|
||||
|
||||
static enum mhi_fw_load_type mhi_fw_load_type_get(const struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
if (mhi_cntrl->fbc_download) {
|
||||
return MHI_FW_LOAD_FBC;
|
||||
} else {
|
||||
if (mhi_cntrl->seg_len)
|
||||
return MHI_FW_LOAD_BHIE;
|
||||
else
|
||||
return MHI_FW_LOAD_BHI;
|
||||
}
|
||||
}
|
||||
|
||||
static int mhi_load_image_bhi(struct mhi_controller *mhi_cntrl, const u8 *fw_data, size_t size)
|
||||
{
|
||||
struct image_info *image;
|
||||
int ret;
|
||||
|
||||
ret = mhi_alloc_bhi_buffer(mhi_cntrl, &image, size);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Load the firmware into BHI vec table */
|
||||
memcpy(image->mhi_buf->buf, fw_data, size);
|
||||
|
||||
ret = mhi_fw_load_bhi(mhi_cntrl, &image->mhi_buf[image->entries - 1]);
|
||||
mhi_free_bhi_buffer(mhi_cntrl, image);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mhi_load_image_bhie(struct mhi_controller *mhi_cntrl, const u8 *fw_data, size_t size)
|
||||
{
|
||||
struct image_info *image;
|
||||
int ret;
|
||||
|
||||
ret = mhi_alloc_bhie_table(mhi_cntrl, &image, size);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
mhi_firmware_copy_bhie(mhi_cntrl, fw_data, size, image);
|
||||
|
||||
ret = mhi_fw_load_bhie(mhi_cntrl, &image->mhi_buf[image->entries - 1]);
|
||||
mhi_free_bhie_table(mhi_cntrl, image);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void mhi_fw_load_handler(struct mhi_controller *mhi_cntrl)
|
||||
{
|
||||
const struct firmware *firmware = NULL;
|
||||
struct device *dev = &mhi_cntrl->mhi_dev->dev;
|
||||
enum mhi_fw_load_type fw_load_type;
|
||||
enum mhi_pm_state new_state;
|
||||
struct image_info *image;
|
||||
const char *fw_name;
|
||||
const u8 *fw_data;
|
||||
size_t size, fw_sz;
|
||||
@ -506,21 +553,17 @@ void mhi_fw_load_handler(struct mhi_controller *mhi_cntrl)
|
||||
fw_sz = firmware->size;
|
||||
|
||||
skip_req_fw:
|
||||
ret = mhi_alloc_bhi_buffer(mhi_cntrl, &image, size);
|
||||
if (ret) {
|
||||
release_firmware(firmware);
|
||||
goto error_fw_load;
|
||||
}
|
||||
/* Load the firmware into BHI vec table */
|
||||
memcpy(image->mhi_buf->buf, fw_data, size);
|
||||
|
||||
/* Download image using BHI */
|
||||
ret = mhi_fw_load_bhi(mhi_cntrl, image->mhi_buf);
|
||||
mhi_free_bhi_buffer(mhi_cntrl, image);
|
||||
fw_load_type = mhi_fw_load_type_get(mhi_cntrl);
|
||||
if (fw_load_type == MHI_FW_LOAD_BHIE)
|
||||
ret = mhi_load_image_bhie(mhi_cntrl, fw_data, size);
|
||||
else
|
||||
ret = mhi_load_image_bhi(mhi_cntrl, fw_data, size);
|
||||
|
||||
/* Error or in EDL mode, we're done */
|
||||
if (ret) {
|
||||
dev_err(dev, "MHI did not load image over BHI, ret: %d\n", ret);
|
||||
dev_err(dev, "MHI did not load image over BHI%s, ret: %d\n",
|
||||
fw_load_type == MHI_FW_LOAD_BHIE ? "e" : "",
|
||||
ret);
|
||||
release_firmware(firmware);
|
||||
goto error_fw_load;
|
||||
}
|
||||
@ -539,7 +582,7 @@ skip_req_fw:
|
||||
* If we're doing fbc, populate vector tables while
|
||||
* device transitioning into MHI READY state
|
||||
*/
|
||||
if (mhi_cntrl->fbc_download) {
|
||||
if (fw_load_type == MHI_FW_LOAD_FBC) {
|
||||
ret = mhi_alloc_bhie_table(mhi_cntrl, &mhi_cntrl->fbc_image, fw_sz);
|
||||
if (ret) {
|
||||
release_firmware(firmware);
|
||||
@ -564,7 +607,7 @@ fw_load_ready_state:
|
||||
return;
|
||||
|
||||
error_ready_state:
|
||||
if (mhi_cntrl->fbc_download) {
|
||||
if (fw_load_type == MHI_FW_LOAD_FBC) {
|
||||
mhi_free_bhie_table(mhi_cntrl, mhi_cntrl->fbc_image);
|
||||
mhi_cntrl->fbc_image = NULL;
|
||||
}
|
||||
|
@ -1144,7 +1144,7 @@ int mhi_prepare_for_power_up(struct mhi_controller *mhi_cntrl)
|
||||
}
|
||||
mhi_cntrl->bhi = mhi_cntrl->regs + bhi_off;
|
||||
|
||||
if (mhi_cntrl->fbc_download || mhi_cntrl->rddm_size) {
|
||||
if (mhi_cntrl->fbc_download || mhi_cntrl->rddm_size || mhi_cntrl->seg_len) {
|
||||
ret = mhi_read_reg(mhi_cntrl, mhi_cntrl->regs, BHIEOFF,
|
||||
&bhie_off);
|
||||
if (ret) {
|
||||
|
@ -29,6 +29,13 @@ struct bhi_vec_entry {
|
||||
u64 size;
|
||||
};
|
||||
|
||||
enum mhi_fw_load_type {
|
||||
MHI_FW_LOAD_BHI, /* BHI only in PBL */
|
||||
MHI_FW_LOAD_BHIE, /* BHIe only in PBL */
|
||||
MHI_FW_LOAD_FBC, /* BHI in PBL followed by BHIe in SBL */
|
||||
MHI_FW_LOAD_MAX,
|
||||
};
|
||||
|
||||
enum mhi_ch_state_type {
|
||||
MHI_CH_STATE_TYPE_RESET,
|
||||
MHI_CH_STATE_TYPE_STOP,
|
||||
|
Loading…
x
Reference in New Issue
Block a user