[PATCH v2 6/9] bus: mhi: Load DDR training data using per-device serial number

From: Kishore Batta

Date: Sat Mar 07 2026 - 06:45:33 EST


Devices may provide device-specific DDR training data that can be reused
across boot to avoid retraining and reduce boot time. The Sahara driver
currently always falls back to the default DDR training image, even when
per-device training data is available.

Extend the firmware loading logic to first attempt loading a per-device
DDR training image using the device serial number. If the serial-specific
image is not present, fallback to the existing default image, preserving
current behavior.

This change enables DDR training data reuse when available while keeping
the existing training flow unchanged for devices without saved data.

Signed-off-by: Kishore Batta <kishore.batta@xxxxxxxxxxxxxxxx>
---
drivers/bus/mhi/sahara/sahara.c | 56 ++++++++++++++++++++++++++++++++---------
1 file changed, 44 insertions(+), 12 deletions(-)

diff --git a/drivers/bus/mhi/sahara/sahara.c b/drivers/bus/mhi/sahara/sahara.c
index 73ae722122a35b77760a4816bc60e6607aa53455..19fb9cb78fbecee047ba27674043c0940e749195 100644
--- a/drivers/bus/mhi/sahara/sahara.c
+++ b/drivers/bus/mhi/sahara/sahara.c
@@ -61,6 +61,8 @@
#define SAHARA_MEM_DEBUG64_LENGTH 0x18
#define SAHARA_MEM_READ64_LENGTH 0x18

+#define SAHARA_DDR_TRAINING_IMG_ID 34
+
struct sahara_packet {
__le32 cmd;
__le32 length;
@@ -319,6 +321,7 @@ static const struct sahara_variant *sahara_select_variant(struct mhi_device *mhi

static int sahara_find_image(struct sahara_context *context, u32 image_id)
{
+ char *fw_path;
int ret;

if (image_id == context->active_image_id)
@@ -335,18 +338,47 @@ static int sahara_find_image(struct sahara_context *context, u32 image_id)
return -EINVAL;
}

- /*
- * This image might be optional. The device may continue without it.
- * Only the device knows. Suppress error messages that could suggest an
- * a problem when we were actually able to continue.
- */
- ret = firmware_request_nowarn(&context->firmware,
- context->image_table[image_id],
- &context->mhi_dev->dev);
- if (ret) {
- dev_dbg(&context->mhi_dev->dev, "request for image id %d / file %s failed %d\n",
- image_id, context->image_table[image_id], ret);
- return ret;
+ /* DDR training special case: Try per-serial number file first */
+ if (image_id == SAHARA_DDR_TRAINING_IMG_ID && context->fw_folder) {
+ u32 serial_num = context->mhi_dev->mhi_cntrl->serial_number;
+
+ fw_path = kasprintf(GFP_KERNEL,
+ "qcom/%s/mdmddr_0x%x.mbn",
+ context->fw_folder, serial_num);
+ if (!fw_path)
+ return -ENOMEM;
+
+ ret = firmware_request_nowarn(&context->firmware,
+ fw_path,
+ &context->mhi_dev->dev);
+ kfree(fw_path);
+
+ if (ret) {
+ ret = firmware_request_nowarn(&context->firmware,
+ context->image_table[image_id],
+ &context->mhi_dev->dev);
+ if (ret) {
+ dev_dbg(&context->mhi_dev->dev,
+ "request for image id %d / file %s failed %d\n",
+ image_id, context->image_table[image_id], ret);
+ }
+ return ret;
+ }
+ } else {
+ /*
+ * This image might be optional. The device may continue without it.
+ * Only the device knows. Suppress error messages that could suggest an
+ * a problem when we were actually able to continue.
+ */
+ ret = firmware_request_nowarn(&context->firmware,
+ context->image_table[image_id],
+ &context->mhi_dev->dev);
+ if (ret) {
+ dev_dbg(&context->mhi_dev->dev,
+ "request for image id %d / file %s failed %d\n",
+ image_id, context->image_table[image_id], ret);
+ return ret;
+ }
}

context->active_image_id = image_id;

--
2.34.1