summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJared McArthur <[email protected]>2025-10-10 14:55:55 -0500
committerNeil Armstrong <[email protected]>2025-10-28 17:12:10 +0100
commitae0872e9c38394be8fcdb38ef391e635d4cf7a22 (patch)
tree9a3234826037546abe4a7dcc4b40aa8bf3c1084b
parentd0dfb8c635ab4ff60090878879c9f75f9a7193da (diff)
ufs: Add support for sending UFS attribute requests
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 <[email protected]> Reviewed-by: Bryan Brattlof <[email protected]> Reviewed-by: Neil Armstrong <[email protected]> Reviewed-by: Udit Kumar <[email protected]> Reviewed-by: Neha Malcom Francis <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Neil Armstrong <[email protected]>
-rw-r--r--drivers/ufs/ufs.c95
1 files changed, 95 insertions, 0 deletions
diff --git a/drivers/ufs/ufs.c b/drivers/ufs/ufs.c
index 1d52ff64a4a..b64556a06d1 100644
--- a/drivers/ufs/ufs.c
+++ b/drivers/ufs/ufs.c
@@ -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,