]> git.ipfire.org Git - thirdparty/u-boot.git/commitdiff
ufs: Add support for sending UFS attribute requests
authorJared McArthur <j-mcarthur@ti.com>
Fri, 10 Oct 2025 19:55:55 +0000 (14:55 -0500)
committerNeil Armstrong <neil.armstrong@linaro.org>
Tue, 28 Oct 2025 16:12:10 +0000 (17:12 +0100)
Some UFS attributes must be set before a UFS device is initialized.
Add ufshcd_query_attr and ufshcd_query_attr_retry to send UFS
attribute requests.

Taken from Linux Kernel v6.17 (drivers/ufs/core/ufshcd.c) and ported
to U-Boot.

Signed-off-by: Jared McArthur <j-mcarthur@ti.com>
Reviewed-by: Bryan Brattlof <bb@ti.com>
Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
Reviewed-by: Udit Kumar <u-kumar1@ti.com>
Reviewed-by: Neha Malcom Francis <n-francis@ti.com>
Link: https://patch.msgid.link/20251010195556.1772611-2-j-mcarthur@ti.com
Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
drivers/ufs/ufs.c

index 1d52ff64a4a3169cd8bd1e449bcfde2a8cb39c55..b64556a06d1ff36bacd6c9019435a3d80af710a5 100644 (file)
@@ -1123,6 +1123,101 @@ static int ufshcd_query_flag_retry(struct ufs_hba *hba,
        return ret;
 }
 
+/**
+ * ufshcd_query_attr - API function for sending attribute requests
+ * @hba: per-adapter instance
+ * @opcode: attribute opcode
+ * @idn: attribute idn to access
+ * @index: index field
+ * @selector: selector field
+ * @attr_val: the attribute value after the query request completes
+ *
+ * Return: 0 for success, non-zero in case of failure.
+ */
+int ufshcd_query_attr(struct ufs_hba *hba, enum query_opcode opcode,
+                     enum attr_idn idn, u8 index, u8 selector, u32 *attr_val)
+{
+       struct ufs_query_req *request = NULL;
+       struct ufs_query_res *response = NULL;
+       int err;
+
+       if (!attr_val) {
+               dev_err(hba->dev,
+                       "%s: attribute value required for opcode 0x%x\n",
+                       __func__, opcode);
+               return -EINVAL;
+       }
+
+       ufshcd_init_query(hba, &request, &response, opcode, idn, index, selector);
+
+       switch (opcode) {
+       case UPIU_QUERY_OPCODE_WRITE_ATTR:
+               request->query_func = UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST;
+               request->upiu_req.value = cpu_to_be32(*attr_val);
+               break;
+       case UPIU_QUERY_OPCODE_READ_ATTR:
+               request->query_func = UPIU_QUERY_FUNC_STANDARD_READ_REQUEST;
+               break;
+       default:
+               dev_err(hba->dev,
+                       "%s: Expected query attr opcode but got = 0x%.2x\n",
+                       __func__, opcode);
+               err = -EINVAL;
+               goto out;
+       }
+
+       err = ufshcd_exec_dev_cmd(hba, DEV_CMD_TYPE_QUERY, QUERY_REQ_TIMEOUT);
+
+       if (err) {
+               dev_err(hba->dev,
+                       "%s: opcode 0x%.2x for idn %d failed, index %d, err = %d\n",
+                       __func__, opcode, idn, index, err);
+               goto out;
+       }
+
+       *attr_val = be32_to_cpu(response->upiu_res.value);
+
+out:
+       return err;
+}
+
+/**
+ * ufshcd_query_attr_retry() - API function for sending query
+ * attribute with retries
+ * @hba: per-adapter instance
+ * @opcode: attribute opcode
+ * @idn: attribute idn to access
+ * @index: index field
+ * @selector: selector field
+ * @attr_val: the attribute value after the query request
+ * completes
+ *
+ * Return: 0 for success, non-zero in case of failure.
+ */
+int ufshcd_query_attr_retry(struct ufs_hba *hba, enum query_opcode opcode,
+                           enum attr_idn idn, u8 index, u8 selector,
+                           u32 *attr_val)
+{
+       int ret = 0;
+       u32 retries;
+
+       for (retries = QUERY_REQ_RETRIES; retries > 0; retries--) {
+               ret = ufshcd_query_attr(hba, opcode, idn, index, selector, attr_val);
+               if (ret)
+                       dev_dbg(hba->dev,
+                               "%s: failed with error %d, retries %d\n",
+                               __func__, ret, retries);
+               else
+                       break;
+       }
+
+       if (ret)
+               dev_err(hba->dev,
+                       "%s: query attribute, idn %d, failed with error %d after %d retries\n",
+                       __func__, idn, ret, QUERY_REQ_RETRIES);
+       return ret;
+}
+
 static int __ufshcd_query_descriptor(struct ufs_hba *hba,
                                     enum query_opcode opcode,
                                     enum desc_idn idn, u8 index, u8 selector,