[PATCH 1/6] ufs: Add UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS

Add UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS for host controllers which do not support 64-bit addressing.
Ported from Linux kernel commit 6554400d6f66 ("scsi: ufs: core: Add UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS") with ufs_scsi_buffer_aligned() based on U-Boot generic bounce buffer.
Signed-off-by: Marek Vasut marek.vasut+renesas@mailbox.org --- Cc: Faiz Abbas faiz_abbas@ti.com --- drivers/ufs/ufs.c | 26 ++++++++++++++++++++++++++ drivers/ufs/ufs.h | 6 ++++++ 2 files changed, 32 insertions(+)
diff --git a/drivers/ufs/ufs.c b/drivers/ufs/ufs.c index 3bf1a95e7f2..da0550d98c6 100644 --- a/drivers/ufs/ufs.c +++ b/drivers/ufs/ufs.c @@ -8,6 +8,7 @@ * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com */
+#include <bouncebuf.h> #include <charset.h> #include <common.h> #include <dm.h> @@ -1889,6 +1890,8 @@ int ufshcd_probe(struct udevice *ufs_dev, struct ufs_hba_ops *hba_ops)
/* Read capabilties registers */ hba->capabilities = ufshcd_readl(hba, REG_CONTROLLER_CAPABILITIES); + if (hba->quirks & UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS) + hba->capabilities &= ~MASK_64_ADDRESSING_SUPPORT;
/* Get UFS version supported by the controller */ hba->version = ufshcd_get_ufs_version(hba); @@ -1942,8 +1945,31 @@ int ufs_scsi_bind(struct udevice *ufs_dev, struct udevice **scsi_devp) return ret; }
+#if IS_ENABLED(CONFIG_BOUNCE_BUFFER) +static int ufs_scsi_buffer_aligned(struct udevice *scsi_dev, struct bounce_buffer *state) +{ +#ifdef CONFIG_PHYS_64BIT + struct ufs_hba *hba = dev_get_uclass_priv(scsi_dev->parent); + uintptr_t ubuf = (uintptr_t)state->user_buffer; + size_t len = state->len_aligned; + + /* Check if below 32bit boundary */ + if ((hba->quirks & UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS) && + ((ubuf >> 32) || (ubuf + len) >> 32)) { + dev_dbg(scsi_dev, "Buffer above 32bit boundary %lx-%lx\n", + ubuf, ubuf + len); + return 0; + } +#endif + return 1; +} +#endif /* CONFIG_BOUNCE_BUFFER */ + static struct scsi_ops ufs_ops = { .exec = ufs_scsi_exec, +#if IS_ENABLED(CONFIG_BOUNCE_BUFFER) + .buffer_aligned = ufs_scsi_buffer_aligned, +#endif /* CONFIG_BOUNCE_BUFFER */ };
int ufs_probe_dev(int index) diff --git a/drivers/ufs/ufs.h b/drivers/ufs/ufs.h index 8a38832b05f..070db0dce68 100644 --- a/drivers/ufs/ufs.h +++ b/drivers/ufs/ufs.h @@ -719,6 +719,12 @@ struct ufs_hba { */ #define UFSHCD_QUIRK_BROKEN_LCC 0x1
+/* + * This quirk needs to be enabled if the host controller has + * 64-bit addressing supported capability but it doesn't work. + */ +#define UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS 0x2 + /* Virtual memory reference */ struct utp_transfer_cmd_desc *ucdl; struct utp_transfer_req_desc *utrdl;

Add UFSHCD_QUIRK_HIBERN_FASTAUTO quirk for host controllers which supports auto-hibernate the capability but only FASTAUTO mode.
Ported from Linux kernel commit 2f11bbc2c7f3 ("scsi: ufs: core: Add UFSHCD_QUIRK_HIBERN_FASTAUTO")
Signed-off-by: Marek Vasut marek.vasut+renesas@mailbox.org --- Cc: Faiz Abbas faiz_abbas@ti.com --- drivers/ufs/ufs.c | 9 +++++++-- drivers/ufs/ufs.h | 6 ++++++ 2 files changed, 13 insertions(+), 2 deletions(-)
diff --git a/drivers/ufs/ufs.c b/drivers/ufs/ufs.c index da0550d98c6..261ae2843c2 100644 --- a/drivers/ufs/ufs.c +++ b/drivers/ufs/ufs.c @@ -1631,8 +1631,13 @@ static int ufshcd_get_max_pwr_mode(struct ufs_hba *hba) if (hba->max_pwr_info.is_valid) return 0;
- pwr_info->pwr_tx = FAST_MODE; - pwr_info->pwr_rx = FAST_MODE; + if (hba->quirks & UFSHCD_QUIRK_HIBERN_FASTAUTO) { + pwr_info->pwr_tx = FASTAUTO_MODE; + pwr_info->pwr_rx = FASTAUTO_MODE; + } else { + pwr_info->pwr_tx = FAST_MODE; + pwr_info->pwr_rx = FAST_MODE; + } pwr_info->hs_rate = PA_HS_MODE_B;
/* Get the connected lane count */ diff --git a/drivers/ufs/ufs.h b/drivers/ufs/ufs.h index 070db0dce68..33ca5f29812 100644 --- a/drivers/ufs/ufs.h +++ b/drivers/ufs/ufs.h @@ -725,6 +725,12 @@ struct ufs_hba { */ #define UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS 0x2
+/* + * This quirk needs to be enabled if the host controller has + * auto-hibernate capability but it's FASTAUTO only. + */ +#define UFSHCD_QUIRK_HIBERN_FASTAUTO 0x4 + /* Virtual memory reference */ struct utp_transfer_cmd_desc *ucdl; struct utp_transfer_req_desc *utrdl;

Extend the version check to handle UFS 3.0 controllers as well. Tested on R-Car S4 UFS 3.0 controller.
Signed-off-by: Marek Vasut marek.vasut+renesas@mailbox.org --- Cc: Faiz Abbas faiz_abbas@ti.com --- drivers/ufs/ufs.c | 3 ++- drivers/ufs/ufs.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/ufs/ufs.c b/drivers/ufs/ufs.c index 261ae2843c2..58830c8ddca 100644 --- a/drivers/ufs/ufs.c +++ b/drivers/ufs/ufs.c @@ -1903,7 +1903,8 @@ int ufshcd_probe(struct udevice *ufs_dev, struct ufs_hba_ops *hba_ops) if (hba->version != UFSHCI_VERSION_10 && hba->version != UFSHCI_VERSION_11 && hba->version != UFSHCI_VERSION_20 && - hba->version != UFSHCI_VERSION_21) + hba->version != UFSHCI_VERSION_21 && + hba->version != UFSHCI_VERSION_30) dev_err(hba->dev, "invalid UFS version 0x%x\n", hba->version);
diff --git a/drivers/ufs/ufs.h b/drivers/ufs/ufs.h index 33ca5f29812..ef7728fc39e 100644 --- a/drivers/ufs/ufs.h +++ b/drivers/ufs/ufs.h @@ -781,6 +781,7 @@ enum { UFSHCI_VERSION_11 = 0x00010100, /* 1.1 */ UFSHCI_VERSION_20 = 0x00000200, /* 2.0 */ UFSHCI_VERSION_21 = 0x00000210, /* 2.1 */ + UFSHCI_VERSION_30 = 0x00000300, /* 3.0 */ };
/* Interrupt disable masks */

On Mon, 14 Aug 2023 at 05:23, Marek Vasut marek.vasut+renesas@mailbox.org wrote:
Extend the version check to handle UFS 3.0 controllers as well. Tested on R-Car S4 UFS 3.0 controller.
Signed-off-by: Marek Vasut marek.vasut+renesas@mailbox.org
Cc: Faiz Abbas faiz_abbas@ti.com
drivers/ufs/ufs.c | 3 ++- drivers/ufs/ufs.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/ufs/ufs.c b/drivers/ufs/ufs.c index 261ae2843c2..58830c8ddca 100644 --- a/drivers/ufs/ufs.c +++ b/drivers/ufs/ufs.c @@ -1903,7 +1903,8 @@ int ufshcd_probe(struct udevice *ufs_dev, struct ufs_hba_ops *hba_ops) if (hba->version != UFSHCI_VERSION_10 && hba->version != UFSHCI_VERSION_11 && hba->version != UFSHCI_VERSION_20 &&
hba->version != UFSHCI_VERSION_21)
hba->version != UFSHCI_VERSION_21 &&
hba->version != UFSHCI_VERSION_30) dev_err(hba->dev, "invalid UFS version 0x%x\n", hba->version);
diff --git a/drivers/ufs/ufs.h b/drivers/ufs/ufs.h index 33ca5f29812..ef7728fc39e 100644 --- a/drivers/ufs/ufs.h +++ b/drivers/ufs/ufs.h @@ -781,6 +781,7 @@ enum { UFSHCI_VERSION_11 = 0x00010100, /* 1.1 */ UFSHCI_VERSION_20 = 0x00000200, /* 2.0 */ UFSHCI_VERSION_21 = 0x00000210, /* 2.1 */
UFSHCI_VERSION_30 = 0x00000300, /* 3.0 */
};
/* Interrupt disable masks */
2.40.1
SInce the Qualcomm UFS HC controllers are even newer / greater version values, we can drop this patch in favour of my UFS patch here: https://lists.denx.de/pipermail/u-boot/2023-August/527215.html
Thanks, Bhupesh

On 8/15/23 19:14, Bhupesh Sharma wrote:
On Mon, 14 Aug 2023 at 05:23, Marek Vasut marek.vasut+renesas@mailbox.org wrote:
Extend the version check to handle UFS 3.0 controllers as well. Tested on R-Car S4 UFS 3.0 controller.
Signed-off-by: Marek Vasut marek.vasut+renesas@mailbox.org
Cc: Faiz Abbas faiz_abbas@ti.com
drivers/ufs/ufs.c | 3 ++- drivers/ufs/ufs.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/ufs/ufs.c b/drivers/ufs/ufs.c index 261ae2843c2..58830c8ddca 100644 --- a/drivers/ufs/ufs.c +++ b/drivers/ufs/ufs.c @@ -1903,7 +1903,8 @@ int ufshcd_probe(struct udevice *ufs_dev, struct ufs_hba_ops *hba_ops) if (hba->version != UFSHCI_VERSION_10 && hba->version != UFSHCI_VERSION_11 && hba->version != UFSHCI_VERSION_20 &&
hba->version != UFSHCI_VERSION_21)
hba->version != UFSHCI_VERSION_21 &&
hba->version != UFSHCI_VERSION_30) dev_err(hba->dev, "invalid UFS version 0x%x\n", hba->version);
diff --git a/drivers/ufs/ufs.h b/drivers/ufs/ufs.h index 33ca5f29812..ef7728fc39e 100644 --- a/drivers/ufs/ufs.h +++ b/drivers/ufs/ufs.h @@ -781,6 +781,7 @@ enum { UFSHCI_VERSION_11 = 0x00010100, /* 1.1 */ UFSHCI_VERSION_20 = 0x00000200, /* 2.0 */ UFSHCI_VERSION_21 = 0x00000210, /* 2.1 */
UFSHCI_VERSION_30 = 0x00000300, /* 3.0 */
};
/* Interrupt disable masks */
-- 2.40.1
SInce the Qualcomm UFS HC controllers are even newer / greater version values, we can drop this patch in favour of my UFS patch here: https://lists.denx.de/pipermail/u-boot/2023-August/527215.html
Why not keep validating the version ?

On Wed, 16 Aug 2023 at 02:31, Marek Vasut marek.vasut@mailbox.org wrote:
On 8/15/23 19:14, Bhupesh Sharma wrote:
On Mon, 14 Aug 2023 at 05:23, Marek Vasut marek.vasut+renesas@mailbox.org wrote:
Extend the version check to handle UFS 3.0 controllers as well. Tested on R-Car S4 UFS 3.0 controller.
Signed-off-by: Marek Vasut marek.vasut+renesas@mailbox.org
Cc: Faiz Abbas faiz_abbas@ti.com
drivers/ufs/ufs.c | 3 ++- drivers/ufs/ufs.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/ufs/ufs.c b/drivers/ufs/ufs.c index 261ae2843c2..58830c8ddca 100644 --- a/drivers/ufs/ufs.c +++ b/drivers/ufs/ufs.c @@ -1903,7 +1903,8 @@ int ufshcd_probe(struct udevice *ufs_dev, struct ufs_hba_ops *hba_ops) if (hba->version != UFSHCI_VERSION_10 && hba->version != UFSHCI_VERSION_11 && hba->version != UFSHCI_VERSION_20 &&
hba->version != UFSHCI_VERSION_21)
hba->version != UFSHCI_VERSION_21 &&
hba->version != UFSHCI_VERSION_30) dev_err(hba->dev, "invalid UFS version 0x%x\n", hba->version);
diff --git a/drivers/ufs/ufs.h b/drivers/ufs/ufs.h index 33ca5f29812..ef7728fc39e 100644 --- a/drivers/ufs/ufs.h +++ b/drivers/ufs/ufs.h @@ -781,6 +781,7 @@ enum { UFSHCI_VERSION_11 = 0x00010100, /* 1.1 */ UFSHCI_VERSION_20 = 0x00000200, /* 2.0 */ UFSHCI_VERSION_21 = 0x00000210, /* 2.1 */
UFSHCI_VERSION_30 = 0x00000300, /* 3.0 */
};
/* Interrupt disable masks */
-- 2.40.1
SInce the Qualcomm UFS HC controllers are even newer / greater version values, we can drop this patch in favour of my UFS patch here: https://lists.denx.de/pipermail/u-boot/2023-August/527215.html
Why not keep validating the version ?
How many versions would one want to validate when the newer versions are 4.1 or greater?

On 8/15/23 23:05, Bhupesh Sharma wrote:
On Wed, 16 Aug 2023 at 02:31, Marek Vasut marek.vasut@mailbox.org wrote:
On 8/15/23 19:14, Bhupesh Sharma wrote:
On Mon, 14 Aug 2023 at 05:23, Marek Vasut marek.vasut+renesas@mailbox.org wrote:
Extend the version check to handle UFS 3.0 controllers as well. Tested on R-Car S4 UFS 3.0 controller.
Signed-off-by: Marek Vasut marek.vasut+renesas@mailbox.org
Cc: Faiz Abbas faiz_abbas@ti.com
drivers/ufs/ufs.c | 3 ++- drivers/ufs/ufs.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/ufs/ufs.c b/drivers/ufs/ufs.c index 261ae2843c2..58830c8ddca 100644 --- a/drivers/ufs/ufs.c +++ b/drivers/ufs/ufs.c @@ -1903,7 +1903,8 @@ int ufshcd_probe(struct udevice *ufs_dev, struct ufs_hba_ops *hba_ops) if (hba->version != UFSHCI_VERSION_10 && hba->version != UFSHCI_VERSION_11 && hba->version != UFSHCI_VERSION_20 &&
hba->version != UFSHCI_VERSION_21)
hba->version != UFSHCI_VERSION_21 &&
hba->version != UFSHCI_VERSION_30) dev_err(hba->dev, "invalid UFS version 0x%x\n", hba->version);
diff --git a/drivers/ufs/ufs.h b/drivers/ufs/ufs.h index 33ca5f29812..ef7728fc39e 100644 --- a/drivers/ufs/ufs.h +++ b/drivers/ufs/ufs.h @@ -781,6 +781,7 @@ enum { UFSHCI_VERSION_11 = 0x00010100, /* 1.1 */ UFSHCI_VERSION_20 = 0x00000200, /* 2.0 */ UFSHCI_VERSION_21 = 0x00000210, /* 2.1 */
UFSHCI_VERSION_30 = 0x00000300, /* 3.0 */
};
/* Interrupt disable masks */
-- 2.40.1
SInce the Qualcomm UFS HC controllers are even newer / greater version values, we can drop this patch in favour of my UFS patch here: https://lists.denx.de/pipermail/u-boot/2023-August/527215.html
Why not keep validating the version ?
How many versions would one want to validate when the newer versions are 4.1 or greater?
I'd say the ones which are known and tested.

Pass the hba pointer itself to ufshcd_prepare_req_desc_hdr() instead of duplicating utp_transfer_req_desc access at each call site. No functional change.
Signed-off-by: Marek Vasut marek.vasut+renesas@mailbox.org --- Cc: Faiz Abbas faiz_abbas@ti.com --- drivers/ufs/ufs.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/drivers/ufs/ufs.c b/drivers/ufs/ufs.c index 58830c8ddca..da1009e2c14 100644 --- a/drivers/ufs/ufs.c +++ b/drivers/ufs/ufs.c @@ -696,10 +696,11 @@ static inline u8 ufshcd_get_upmcrs(struct ufs_hba *hba) * ufshcd_prepare_req_desc_hdr() - Fills the requests header * descriptor according to request */ -static void ufshcd_prepare_req_desc_hdr(struct utp_transfer_req_desc *req_desc, +static void ufshcd_prepare_req_desc_hdr(struct ufs_hba *hba, u32 *upiu_flags, enum dma_data_direction cmd_dir) { + struct utp_transfer_req_desc *req_desc = hba->utrdl; u32 data_direction; u32 dword_0;
@@ -793,11 +794,10 @@ static int ufshcd_comp_devman_upiu(struct ufs_hba *hba, { u32 upiu_flags; int ret = 0; - struct utp_transfer_req_desc *req_desc = hba->utrdl;
hba->dev_cmd.type = cmd_type;
- ufshcd_prepare_req_desc_hdr(req_desc, &upiu_flags, DMA_NONE); + ufshcd_prepare_req_desc_hdr(hba, &upiu_flags, DMA_NONE); switch (cmd_type) { case DEV_CMD_TYPE_QUERY: ufshcd_prepare_utp_query_req_upiu(hba, upiu_flags); @@ -1449,12 +1449,11 @@ static void prepare_prdt_table(struct ufs_hba *hba, struct scsi_cmd *pccb) static int ufs_scsi_exec(struct udevice *scsi_dev, struct scsi_cmd *pccb) { struct ufs_hba *hba = dev_get_uclass_priv(scsi_dev->parent); - struct utp_transfer_req_desc *req_desc = hba->utrdl; u32 upiu_flags; int ocs, result = 0; u8 scsi_status;
- ufshcd_prepare_req_desc_hdr(req_desc, &upiu_flags, pccb->dma_dir); + ufshcd_prepare_req_desc_hdr(hba, &upiu_flags, pccb->dma_dir); ufshcd_prepare_utp_scsi_cmd_upiu(hba, pccb, upiu_flags); prepare_prdt_table(hba, pccb);

On 8/14/23 5:22 AM, Marek Vasut wrote:
Pass the hba pointer itself to ufshcd_prepare_req_desc_hdr() instead of duplicating utp_transfer_req_desc access at each call site. No functional change.
Signed-off-by: Marek Vasut marek.vasut+renesas@mailbox.org
Cc: Faiz Abbas faiz_abbas@ti.com
drivers/ufs/ufs.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/drivers/ufs/ufs.c b/drivers/ufs/ufs.c index 58830c8ddca..da1009e2c14 100644 --- a/drivers/ufs/ufs.c +++ b/drivers/ufs/ufs.c @@ -696,10 +696,11 @@ static inline u8 ufshcd_get_upmcrs(struct ufs_hba *hba)
- ufshcd_prepare_req_desc_hdr() - Fills the requests header
- descriptor according to request
*/ -static void ufshcd_prepare_req_desc_hdr(struct utp_transfer_req_desc *req_desc, +static void ufshcd_prepare_req_desc_hdr(struct ufs_hba *hba, u32 *upiu_flags, enum dma_data_direction cmd_dir) {
- struct utp_transfer_req_desc *req_desc = hba->utrdl; u32 data_direction; u32 dword_0;
@@ -793,11 +794,10 @@ static int ufshcd_comp_devman_upiu(struct ufs_hba *hba, { u32 upiu_flags; int ret = 0;
struct utp_transfer_req_desc *req_desc = hba->utrdl;
hba->dev_cmd.type = cmd_type;
ufshcd_prepare_req_desc_hdr(req_desc, &upiu_flags, DMA_NONE);
- ufshcd_prepare_req_desc_hdr(hba, &upiu_flags, DMA_NONE); switch (cmd_type) { case DEV_CMD_TYPE_QUERY: ufshcd_prepare_utp_query_req_upiu(hba, upiu_flags);
@@ -1449,12 +1449,11 @@ static void prepare_prdt_table(struct ufs_hba *hba, struct scsi_cmd *pccb) static int ufs_scsi_exec(struct udevice *scsi_dev, struct scsi_cmd *pccb) { struct ufs_hba *hba = dev_get_uclass_priv(scsi_dev->parent);
struct utp_transfer_req_desc *req_desc = hba->utrdl; u32 upiu_flags; int ocs, result = 0; u8 scsi_status;
ufshcd_prepare_req_desc_hdr(req_desc, &upiu_flags, pccb->dma_dir);
- ufshcd_prepare_req_desc_hdr(hba, &upiu_flags, pccb->dma_dir); ufshcd_prepare_utp_scsi_cmd_upiu(hba, pccb, upiu_flags); prepare_prdt_table(hba, pccb);
Reviewed-and-Tested-by: Bhupesh Sharma bhupesh.sharma@linaro.org
Thanks.

On 8/15/23 21:57, Bhupesh Sharma wrote:
On 8/14/23 5:22 AM, Marek Vasut wrote:
Pass the hba pointer itself to ufshcd_prepare_req_desc_hdr() instead of duplicating utp_transfer_req_desc access at each call site. No functional change.
Signed-off-by: Marek Vasut marek.vasut+renesas@mailbox.org
Cc: Faiz Abbas faiz_abbas@ti.com
drivers/ufs/ufs.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/drivers/ufs/ufs.c b/drivers/ufs/ufs.c index 58830c8ddca..da1009e2c14 100644 --- a/drivers/ufs/ufs.c +++ b/drivers/ufs/ufs.c @@ -696,10 +696,11 @@ static inline u8 ufshcd_get_upmcrs(struct ufs_hba *hba) * ufshcd_prepare_req_desc_hdr() - Fills the requests header * descriptor according to request */ -static void ufshcd_prepare_req_desc_hdr(struct utp_transfer_req_desc *req_desc, +static void ufshcd_prepare_req_desc_hdr(struct ufs_hba *hba, u32 *upiu_flags, enum dma_data_direction cmd_dir) { + struct utp_transfer_req_desc *req_desc = hba->utrdl; u32 data_direction; u32 dword_0; @@ -793,11 +794,10 @@ static int ufshcd_comp_devman_upiu(struct ufs_hba *hba, { u32 upiu_flags; int ret = 0; - struct utp_transfer_req_desc *req_desc = hba->utrdl; hba->dev_cmd.type = cmd_type; - ufshcd_prepare_req_desc_hdr(req_desc, &upiu_flags, DMA_NONE); + ufshcd_prepare_req_desc_hdr(hba, &upiu_flags, DMA_NONE); switch (cmd_type) { case DEV_CMD_TYPE_QUERY: ufshcd_prepare_utp_query_req_upiu(hba, upiu_flags); @@ -1449,12 +1449,11 @@ static void prepare_prdt_table(struct ufs_hba *hba, struct scsi_cmd *pccb) static int ufs_scsi_exec(struct udevice *scsi_dev, struct scsi_cmd *pccb) { struct ufs_hba *hba = dev_get_uclass_priv(scsi_dev->parent); - struct utp_transfer_req_desc *req_desc = hba->utrdl; u32 upiu_flags; int ocs, result = 0; u8 scsi_status; - ufshcd_prepare_req_desc_hdr(req_desc, &upiu_flags, pccb->dma_dir); + ufshcd_prepare_req_desc_hdr(hba, &upiu_flags, pccb->dma_dir); ufshcd_prepare_utp_scsi_cmd_upiu(hba, pccb, upiu_flags); prepare_prdt_table(hba, pccb);
Reviewed-and-Tested-by: Bhupesh Sharma bhupesh.sharma@linaro.org
Please use Reviewed-by: and Tested-by: tags separately, else patchwork won't pick those tags up.

Use utp_transfer_req_desc pointer to reference to utrdl queue instead of referencing the queue directly. This makes the code more consistent. No functional change.
Signed-off-by: Marek Vasut marek.vasut+renesas@mailbox.org --- Cc: Faiz Abbas faiz_abbas@ti.com --- drivers/ufs/ufs.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/ufs/ufs.c b/drivers/ufs/ufs.c index da1009e2c14..041caee714f 100644 --- a/drivers/ufs/ufs.c +++ b/drivers/ufs/ufs.c @@ -858,7 +858,9 @@ static inline int ufshcd_get_req_rsp(struct utp_upiu_rsp *ucd_rsp_ptr) */ static inline int ufshcd_get_tr_ocs(struct ufs_hba *hba) { - return le32_to_cpu(hba->utrdl->header.dword_2) & MASK_OCS; + struct utp_transfer_req_desc *req_desc = hba->utrdl; + + return le32_to_cpu(req_desc->header.dword_2) & MASK_OCS; }
static inline int ufshcd_get_rsp_upiu_result(struct utp_upiu_rsp *ucd_rsp_ptr)

On 8/14/23 5:22 AM, Marek Vasut wrote:
Use utp_transfer_req_desc pointer to reference to utrdl queue instead of referencing the queue directly. This makes the code more consistent. No functional change.
Signed-off-by: Marek Vasut marek.vasut+renesas@mailbox.org
Cc: Faiz Abbas faiz_abbas@ti.com
drivers/ufs/ufs.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/ufs/ufs.c b/drivers/ufs/ufs.c index da1009e2c14..041caee714f 100644 --- a/drivers/ufs/ufs.c +++ b/drivers/ufs/ufs.c @@ -858,7 +858,9 @@ static inline int ufshcd_get_req_rsp(struct utp_upiu_rsp *ucd_rsp_ptr) */ static inline int ufshcd_get_tr_ocs(struct ufs_hba *hba) {
- return le32_to_cpu(hba->utrdl->header.dword_2) & MASK_OCS;
struct utp_transfer_req_desc *req_desc = hba->utrdl;
return le32_to_cpu(req_desc->header.dword_2) & MASK_OCS; }
static inline int ufshcd_get_rsp_upiu_result(struct utp_upiu_rsp *ucd_rsp_ptr)
LGTM, so: Reviewed-and-Tested-by: Bhupesh Sharma bhupesh.sharma@linaro.org
Thanks.

Add function to flush and invalidate cache over request and response queue entries, and perform flush and optional invalidate over block layer data that are passed into the UFS layer. This makes it possible to use UFS with caches enabled.
Signed-off-by: Marek Vasut marek.vasut+renesas@mailbox.org --- Cc: Faiz Abbas faiz_abbas@ti.com --- drivers/ufs/ufs.c | 42 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-)
diff --git a/drivers/ufs/ufs.c b/drivers/ufs/ufs.c index 041caee714f..7c48d57f99d 100644 --- a/drivers/ufs/ufs.c +++ b/drivers/ufs/ufs.c @@ -692,6 +692,21 @@ static inline u8 ufshcd_get_upmcrs(struct ufs_hba *hba) return (ufshcd_readl(hba, REG_CONTROLLER_STATUS) >> 8) & 0x7; }
+/** + * ufshcd_cache_flush_and_invalidate - Flush and invalidate cache + * + * Flush and invalidate cache in aligned address..address+size range. + * The invalidation is in place to avoid stale data in cache. + */ +static void ufshcd_cache_flush_and_invalidate(void *addr, unsigned long size) +{ + uintptr_t aaddr = (uintptr_t)addr & ~(ARCH_DMA_MINALIGN - 1); + unsigned long asize = ALIGN(size, ARCH_DMA_MINALIGN); + + flush_dcache_range(aaddr, aaddr + asize); + invalidate_dcache_range(aaddr, aaddr + asize); +} + /** * ufshcd_prepare_req_desc_hdr() - Fills the requests header * descriptor according to request @@ -735,6 +750,8 @@ static void ufshcd_prepare_req_desc_hdr(struct ufs_hba *hba, req_desc->header.dword_3 = 0;
req_desc->prd_table_length = 0; + + ufshcd_cache_flush_and_invalidate(req_desc, sizeof(*req_desc)); }
static void ufshcd_prepare_utp_query_req_upiu(struct ufs_hba *hba, @@ -763,10 +780,15 @@ static void ufshcd_prepare_utp_query_req_upiu(struct ufs_hba *hba, memcpy(&ucd_req_ptr->qr, &query->request.upiu_req, QUERY_OSF_SIZE);
/* Copy the Descriptor */ - if (query->request.upiu_req.opcode == UPIU_QUERY_OPCODE_WRITE_DESC) + if (query->request.upiu_req.opcode == UPIU_QUERY_OPCODE_WRITE_DESC) { memcpy(ucd_req_ptr + 1, query->descriptor, len); + ufshcd_cache_flush_and_invalidate(ucd_req_ptr, 2 * sizeof(*ucd_req_ptr)); + } else { + ufshcd_cache_flush_and_invalidate(ucd_req_ptr, sizeof(*ucd_req_ptr)); + }
memset(hba->ucd_rsp_ptr, 0, sizeof(struct utp_upiu_rsp)); + ufshcd_cache_flush_and_invalidate(hba->ucd_rsp_ptr, sizeof(*hba->ucd_rsp_ptr)); }
static inline void ufshcd_prepare_utp_nop_upiu(struct ufs_hba *hba) @@ -783,6 +805,9 @@ static inline void ufshcd_prepare_utp_nop_upiu(struct ufs_hba *hba) ucd_req_ptr->header.dword_2 = 0;
memset(hba->ucd_rsp_ptr, 0, sizeof(struct utp_upiu_rsp)); + + ufshcd_cache_flush_and_invalidate(ucd_req_ptr, sizeof(*ucd_req_ptr)); + ufshcd_cache_flush_and_invalidate(hba->ucd_rsp_ptr, sizeof(*hba->ucd_rsp_ptr)); }
/** @@ -1409,6 +1434,8 @@ void ufshcd_prepare_utp_scsi_cmd_upiu(struct ufs_hba *hba, memcpy(ucd_req_ptr->sc.cdb, pccb->cmd, cdb_len);
memset(hba->ucd_rsp_ptr, 0, sizeof(struct utp_upiu_rsp)); + ufshcd_cache_flush_and_invalidate(ucd_req_ptr, sizeof(*ucd_req_ptr)); + ufshcd_cache_flush_and_invalidate(hba->ucd_rsp_ptr, sizeof(*hba->ucd_rsp_ptr)); }
static inline void prepare_prdt_desc(struct ufshcd_sg_entry *entry, @@ -1423,6 +1450,7 @@ static void prepare_prdt_table(struct ufs_hba *hba, struct scsi_cmd *pccb) { struct utp_transfer_req_desc *req_desc = hba->utrdl; struct ufshcd_sg_entry *prd_table = hba->ucd_prdt_ptr; + uintptr_t aaddr = (uintptr_t)(pccb->pdata) & ~(ARCH_DMA_MINALIGN - 1); ulong datalen = pccb->datalen; int table_length; u8 *buf; @@ -1430,9 +1458,19 @@ static void prepare_prdt_table(struct ufs_hba *hba, struct scsi_cmd *pccb)
if (!datalen) { req_desc->prd_table_length = 0; + ufshcd_cache_flush_and_invalidate(req_desc, sizeof(*req_desc)); return; }
+ if (pccb->dma_dir == DMA_TO_DEVICE) { /* Write to device */ + flush_dcache_range(aaddr, aaddr + + ALIGN(datalen, ARCH_DMA_MINALIGN)); + } + + /* In any case, invalidate cache to avoid stale data in it. */ + invalidate_dcache_range(aaddr, aaddr + + ALIGN(datalen, ARCH_DMA_MINALIGN)); + table_length = DIV_ROUND_UP(pccb->datalen, MAX_PRDT_ENTRY); buf = pccb->pdata; i = table_length; @@ -1446,6 +1484,8 @@ static void prepare_prdt_table(struct ufs_hba *hba, struct scsi_cmd *pccb) prepare_prdt_desc(&prd_table[table_length - i - 1], buf, datalen - 1);
req_desc->prd_table_length = table_length; + ufshcd_cache_flush_and_invalidate(prd_table, sizeof(*prd_table) * table_length); + ufshcd_cache_flush_and_invalidate(req_desc, sizeof(*req_desc)); }
static int ufs_scsi_exec(struct udevice *scsi_dev, struct scsi_cmd *pccb)

On 8/14/23 5:22 AM, Marek Vasut wrote:
Add function to flush and invalidate cache over request and response queue entries, and perform flush and optional invalidate over block layer data that are passed into the UFS layer. This makes it possible to use UFS with caches enabled.
Signed-off-by: Marek Vasut marek.vasut+renesas@mailbox.org
Cc: Faiz Abbas faiz_abbas@ti.com
drivers/ufs/ufs.c | 42 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-)
diff --git a/drivers/ufs/ufs.c b/drivers/ufs/ufs.c index 041caee714f..7c48d57f99d 100644 --- a/drivers/ufs/ufs.c +++ b/drivers/ufs/ufs.c @@ -692,6 +692,21 @@ static inline u8 ufshcd_get_upmcrs(struct ufs_hba *hba) return (ufshcd_readl(hba, REG_CONTROLLER_STATUS) >> 8) & 0x7; }
+/**
- ufshcd_cache_flush_and_invalidate - Flush and invalidate cache
- Flush and invalidate cache in aligned address..address+size range.
- The invalidation is in place to avoid stale data in cache.
- */
+static void ufshcd_cache_flush_and_invalidate(void *addr, unsigned long size) +{
- uintptr_t aaddr = (uintptr_t)addr & ~(ARCH_DMA_MINALIGN - 1);
- unsigned long asize = ALIGN(size, ARCH_DMA_MINALIGN);
- flush_dcache_range(aaddr, aaddr + asize);
- invalidate_dcache_range(aaddr, aaddr + asize);
+}
- /**
- ufshcd_prepare_req_desc_hdr() - Fills the requests header
- descriptor according to request
@@ -735,6 +750,8 @@ static void ufshcd_prepare_req_desc_hdr(struct ufs_hba *hba, req_desc->header.dword_3 = 0;
req_desc->prd_table_length = 0;
ufshcd_cache_flush_and_invalidate(req_desc, sizeof(*req_desc)); }
static void ufshcd_prepare_utp_query_req_upiu(struct ufs_hba *hba,
@@ -763,10 +780,15 @@ static void ufshcd_prepare_utp_query_req_upiu(struct ufs_hba *hba, memcpy(&ucd_req_ptr->qr, &query->request.upiu_req, QUERY_OSF_SIZE);
/* Copy the Descriptor */
- if (query->request.upiu_req.opcode == UPIU_QUERY_OPCODE_WRITE_DESC)
if (query->request.upiu_req.opcode == UPIU_QUERY_OPCODE_WRITE_DESC) { memcpy(ucd_req_ptr + 1, query->descriptor, len);
ufshcd_cache_flush_and_invalidate(ucd_req_ptr, 2 * sizeof(*ucd_req_ptr));
} else {
ufshcd_cache_flush_and_invalidate(ucd_req_ptr, sizeof(*ucd_req_ptr));
}
memset(hba->ucd_rsp_ptr, 0, sizeof(struct utp_upiu_rsp));
ufshcd_cache_flush_and_invalidate(hba->ucd_rsp_ptr, sizeof(*hba->ucd_rsp_ptr)); }
static inline void ufshcd_prepare_utp_nop_upiu(struct ufs_hba *hba)
@@ -783,6 +805,9 @@ static inline void ufshcd_prepare_utp_nop_upiu(struct ufs_hba *hba) ucd_req_ptr->header.dword_2 = 0;
memset(hba->ucd_rsp_ptr, 0, sizeof(struct utp_upiu_rsp));
ufshcd_cache_flush_and_invalidate(ucd_req_ptr, sizeof(*ucd_req_ptr));
ufshcd_cache_flush_and_invalidate(hba->ucd_rsp_ptr, sizeof(*hba->ucd_rsp_ptr)); }
/**
@@ -1409,6 +1434,8 @@ void ufshcd_prepare_utp_scsi_cmd_upiu(struct ufs_hba *hba, memcpy(ucd_req_ptr->sc.cdb, pccb->cmd, cdb_len);
memset(hba->ucd_rsp_ptr, 0, sizeof(struct utp_upiu_rsp));
ufshcd_cache_flush_and_invalidate(ucd_req_ptr, sizeof(*ucd_req_ptr));
ufshcd_cache_flush_and_invalidate(hba->ucd_rsp_ptr, sizeof(*hba->ucd_rsp_ptr)); }
static inline void prepare_prdt_desc(struct ufshcd_sg_entry *entry,
@@ -1423,6 +1450,7 @@ static void prepare_prdt_table(struct ufs_hba *hba, struct scsi_cmd *pccb) { struct utp_transfer_req_desc *req_desc = hba->utrdl; struct ufshcd_sg_entry *prd_table = hba->ucd_prdt_ptr;
- uintptr_t aaddr = (uintptr_t)(pccb->pdata) & ~(ARCH_DMA_MINALIGN - 1); ulong datalen = pccb->datalen; int table_length; u8 *buf;
@@ -1430,9 +1458,19 @@ static void prepare_prdt_table(struct ufs_hba *hba, struct scsi_cmd *pccb)
if (!datalen) { req_desc->prd_table_length = 0;
ufshcd_cache_flush_and_invalidate(req_desc, sizeof(*req_desc));
return; }
if (pccb->dma_dir == DMA_TO_DEVICE) { /* Write to device */
flush_dcache_range(aaddr, aaddr +
ALIGN(datalen, ARCH_DMA_MINALIGN));
}
/* In any case, invalidate cache to avoid stale data in it. */
invalidate_dcache_range(aaddr, aaddr +
ALIGN(datalen, ARCH_DMA_MINALIGN));
table_length = DIV_ROUND_UP(pccb->datalen, MAX_PRDT_ENTRY); buf = pccb->pdata; i = table_length;
@@ -1446,6 +1484,8 @@ static void prepare_prdt_table(struct ufs_hba *hba, struct scsi_cmd *pccb) prepare_prdt_desc(&prd_table[table_length - i - 1], buf, datalen - 1);
req_desc->prd_table_length = table_length;
ufshcd_cache_flush_and_invalidate(prd_table, sizeof(*prd_table) * table_length);
ufshcd_cache_flush_and_invalidate(req_desc, sizeof(*req_desc)); }
static int ufs_scsi_exec(struct udevice *scsi_dev, struct scsi_cmd *pccb)
LGTM, so: Reviewed-and-Tested-by: Bhupesh Sharma bhupesh.sharma@linaro.org
Thanks.

Hi Marek,
On 8/14/23 5:22 AM, Marek Vasut wrote:
Add UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS for host controllers which do not support 64-bit addressing.
Ported from Linux kernel commit 6554400d6f66 ("scsi: ufs: core: Add UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS") with ufs_scsi_buffer_aligned() based on U-Boot generic bounce buffer.
Signed-off-by: Marek Vasut marek.vasut+renesas@mailbox.org
Cc: Faiz Abbas faiz_abbas@ti.com
drivers/ufs/ufs.c | 26 ++++++++++++++++++++++++++ drivers/ufs/ufs.h | 6 ++++++ 2 files changed, 32 insertions(+)
diff --git a/drivers/ufs/ufs.c b/drivers/ufs/ufs.c index 3bf1a95e7f2..da0550d98c6 100644 --- a/drivers/ufs/ufs.c +++ b/drivers/ufs/ufs.c @@ -8,6 +8,7 @@
- Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com
*/
+#include <bouncebuf.h> #include <charset.h> #include <common.h> #include <dm.h> @@ -1889,6 +1890,8 @@ int ufshcd_probe(struct udevice *ufs_dev, struct ufs_hba_ops *hba_ops)
/* Read capabilties registers */ hba->capabilities = ufshcd_readl(hba, REG_CONTROLLER_CAPABILITIES);
if (hba->quirks & UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS)
hba->capabilities &= ~MASK_64_ADDRESSING_SUPPORT;
/* Get UFS version supported by the controller */ hba->version = ufshcd_get_ufs_version(hba);
@@ -1942,8 +1945,31 @@ int ufs_scsi_bind(struct udevice *ufs_dev, struct udevice **scsi_devp) return ret; }
+#if IS_ENABLED(CONFIG_BOUNCE_BUFFER) +static int ufs_scsi_buffer_aligned(struct udevice *scsi_dev, struct bounce_buffer *state) +{ +#ifdef CONFIG_PHYS_64BIT
- struct ufs_hba *hba = dev_get_uclass_priv(scsi_dev->parent);
- uintptr_t ubuf = (uintptr_t)state->user_buffer;
- size_t len = state->len_aligned;
- /* Check if below 32bit boundary */
- if ((hba->quirks & UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS) &&
((ubuf >> 32) || (ubuf + len) >> 32)) {
dev_dbg(scsi_dev, "Buffer above 32bit boundary %lx-%lx\n",
ubuf, ubuf + len);
return 0;
- }
+#endif
- return 1;
+} +#endif /* CONFIG_BOUNCE_BUFFER */
- static struct scsi_ops ufs_ops = { .exec = ufs_scsi_exec,
+#if IS_ENABLED(CONFIG_BOUNCE_BUFFER)
- .buffer_aligned = ufs_scsi_buffer_aligned,
+#endif /* CONFIG_BOUNCE_BUFFER */ };
int ufs_probe_dev(int index) diff --git a/drivers/ufs/ufs.h b/drivers/ufs/ufs.h index 8a38832b05f..070db0dce68 100644 --- a/drivers/ufs/ufs.h +++ b/drivers/ufs/ufs.h @@ -719,6 +719,12 @@ struct ufs_hba { */ #define UFSHCD_QUIRK_BROKEN_LCC 0x1
+/*
- This quirk needs to be enabled if the host controller has
- 64-bit addressing supported capability but it doesn't work.
- */
+#define UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS 0x2
- /* Virtual memory reference */ struct utp_transfer_cmd_desc *ucdl; struct utp_transfer_req_desc *utrdl;
For this and the follow-up patch, I think implementing or at least supporting all the quirks currently supported by the Linux UFS driver makes sense as newer controllers do support these quirks.
Accordingly I had sent: https://lists.denx.de/pipermail/u-boot/2023-August/527217.html
So, I would suggest that we pick these two patches and then I can send my patches rebased on the same, but change the .h to support all the possible UFS quirks currently supported in Linux so that subsequent patches can utilize them in u-boot - which I plan to post next.
Thanks, Bhupesh

On 8/15/23 22:04, Bhupesh Sharma wrote:
Hi Marek,
On 8/14/23 5:22 AM, Marek Vasut wrote:
Add UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS for host controllers which do not support 64-bit addressing.
Ported from Linux kernel commit 6554400d6f66 ("scsi: ufs: core: Add UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS") with ufs_scsi_buffer_aligned() based on U-Boot generic bounce buffer.
Signed-off-by: Marek Vasut marek.vasut+renesas@mailbox.org
Cc: Faiz Abbas faiz_abbas@ti.com
drivers/ufs/ufs.c | 26 ++++++++++++++++++++++++++ drivers/ufs/ufs.h | 6 ++++++ 2 files changed, 32 insertions(+)
diff --git a/drivers/ufs/ufs.c b/drivers/ufs/ufs.c index 3bf1a95e7f2..da0550d98c6 100644 --- a/drivers/ufs/ufs.c +++ b/drivers/ufs/ufs.c @@ -8,6 +8,7 @@ * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com */ +#include <bouncebuf.h> #include <charset.h> #include <common.h> #include <dm.h> @@ -1889,6 +1890,8 @@ int ufshcd_probe(struct udevice *ufs_dev, struct ufs_hba_ops *hba_ops) /* Read capabilties registers */ hba->capabilities = ufshcd_readl(hba, REG_CONTROLLER_CAPABILITIES); + if (hba->quirks & UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS) + hba->capabilities &= ~MASK_64_ADDRESSING_SUPPORT; /* Get UFS version supported by the controller */ hba->version = ufshcd_get_ufs_version(hba); @@ -1942,8 +1945,31 @@ int ufs_scsi_bind(struct udevice *ufs_dev, struct udevice **scsi_devp) return ret; } +#if IS_ENABLED(CONFIG_BOUNCE_BUFFER) +static int ufs_scsi_buffer_aligned(struct udevice *scsi_dev, struct bounce_buffer *state) +{ +#ifdef CONFIG_PHYS_64BIT + struct ufs_hba *hba = dev_get_uclass_priv(scsi_dev->parent); + uintptr_t ubuf = (uintptr_t)state->user_buffer; + size_t len = state->len_aligned;
+ /* Check if below 32bit boundary */ + if ((hba->quirks & UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS) && + ((ubuf >> 32) || (ubuf + len) >> 32)) { + dev_dbg(scsi_dev, "Buffer above 32bit boundary %lx-%lx\n", + ubuf, ubuf + len); + return 0; + } +#endif + return 1; +} +#endif /* CONFIG_BOUNCE_BUFFER */
static struct scsi_ops ufs_ops = { .exec = ufs_scsi_exec, +#if IS_ENABLED(CONFIG_BOUNCE_BUFFER) + .buffer_aligned = ufs_scsi_buffer_aligned, +#endif /* CONFIG_BOUNCE_BUFFER */ }; int ufs_probe_dev(int index) diff --git a/drivers/ufs/ufs.h b/drivers/ufs/ufs.h index 8a38832b05f..070db0dce68 100644 --- a/drivers/ufs/ufs.h +++ b/drivers/ufs/ufs.h @@ -719,6 +719,12 @@ struct ufs_hba { */ #define UFSHCD_QUIRK_BROKEN_LCC 0x1 +/*
- This quirk needs to be enabled if the host controller has
- 64-bit addressing supported capability but it doesn't work.
- */
+#define UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS 0x2
/* Virtual memory reference */ struct utp_transfer_cmd_desc *ucdl; struct utp_transfer_req_desc *utrdl;
For this and the follow-up patch, I think implementing or at least supporting all the quirks currently supported by the Linux UFS driver makes sense as newer controllers do support these quirks.
I disagree. There is no point in implementing quirks which cannot be tested or may not even be relevant to U-Boot. Quirks which are needed should be added one by one.
Accordingly I had sent: https://lists.denx.de/pipermail/u-boot/2023-August/527217.html
So, I would suggest that we pick these two patches and then I can send my patches rebased on the same, but change the .h to support all the possible UFS quirks currently supported in Linux so that subsequent patches can utilize them in u-boot - which I plan to post next.
See above.

On Wed, 16 Aug 2023 at 02:31, Marek Vasut marek.vasut@mailbox.org wrote:
On 8/15/23 22:04, Bhupesh Sharma wrote:
Hi Marek,
On 8/14/23 5:22 AM, Marek Vasut wrote:
Add UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS for host controllers which do not support 64-bit addressing.
Ported from Linux kernel commit 6554400d6f66 ("scsi: ufs: core: Add UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS") with ufs_scsi_buffer_aligned() based on U-Boot generic bounce buffer.
Signed-off-by: Marek Vasut marek.vasut+renesas@mailbox.org
Cc: Faiz Abbas faiz_abbas@ti.com
drivers/ufs/ufs.c | 26 ++++++++++++++++++++++++++ drivers/ufs/ufs.h | 6 ++++++ 2 files changed, 32 insertions(+)
diff --git a/drivers/ufs/ufs.c b/drivers/ufs/ufs.c index 3bf1a95e7f2..da0550d98c6 100644 --- a/drivers/ufs/ufs.c +++ b/drivers/ufs/ufs.c @@ -8,6 +8,7 @@
- Copyright (C) 2019 Texas Instruments Incorporated -
http://www.ti.com */ +#include <bouncebuf.h> #include <charset.h> #include <common.h> #include <dm.h> @@ -1889,6 +1890,8 @@ int ufshcd_probe(struct udevice *ufs_dev, struct ufs_hba_ops *hba_ops) /* Read capabilties registers */ hba->capabilities = ufshcd_readl(hba, REG_CONTROLLER_CAPABILITIES);
- if (hba->quirks & UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS)
hba->capabilities &= ~MASK_64_ADDRESSING_SUPPORT; /* Get UFS version supported by the controller */ hba->version = ufshcd_get_ufs_version(hba);
@@ -1942,8 +1945,31 @@ int ufs_scsi_bind(struct udevice *ufs_dev, struct udevice **scsi_devp) return ret; } +#if IS_ENABLED(CONFIG_BOUNCE_BUFFER) +static int ufs_scsi_buffer_aligned(struct udevice *scsi_dev, struct bounce_buffer *state) +{ +#ifdef CONFIG_PHYS_64BIT
- struct ufs_hba *hba = dev_get_uclass_priv(scsi_dev->parent);
- uintptr_t ubuf = (uintptr_t)state->user_buffer;
- size_t len = state->len_aligned;
- /* Check if below 32bit boundary */
- if ((hba->quirks & UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS) &&
((ubuf >> 32) || (ubuf + len) >> 32)) {
dev_dbg(scsi_dev, "Buffer above 32bit boundary %lx-%lx\n",
ubuf, ubuf + len);
return 0;
- }
+#endif
- return 1;
+} +#endif /* CONFIG_BOUNCE_BUFFER */
- static struct scsi_ops ufs_ops = { .exec = ufs_scsi_exec,
+#if IS_ENABLED(CONFIG_BOUNCE_BUFFER)
- .buffer_aligned = ufs_scsi_buffer_aligned,
+#endif /* CONFIG_BOUNCE_BUFFER */ }; int ufs_probe_dev(int index) diff --git a/drivers/ufs/ufs.h b/drivers/ufs/ufs.h index 8a38832b05f..070db0dce68 100644 --- a/drivers/ufs/ufs.h +++ b/drivers/ufs/ufs.h @@ -719,6 +719,12 @@ struct ufs_hba { */ #define UFSHCD_QUIRK_BROKEN_LCC 0x1 +/*
- This quirk needs to be enabled if the host controller has
- 64-bit addressing supported capability but it doesn't work.
- */
+#define UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS 0x2
/* Virtual memory reference */ struct utp_transfer_cmd_desc *ucdl; struct utp_transfer_req_desc *utrdl;
For this and the follow-up patch, I think implementing or at least supporting all the quirks currently supported by the Linux UFS driver makes sense as newer controllers do support these quirks.
I disagree. There is no point in implementing quirks which cannot be tested or may not even be relevant to U-Boot. Quirks which are needed should be added one by one.
But the format you use for adding new quiks in u-boot is still in sync with Linux version 3.10. Can we atleast use the newer ( 1<< 7) kind of format for consistency.
Thanks.
Accordingly I had sent: https://lists.denx.de/pipermail/u-boot/2023-August/527217.html
So, I would suggest that we pick these two patches and then I can send my patches rebased on the same, but change the .h to support all the possible UFS quirks currently supported in Linux so that subsequent patches can utilize them in u-boot - which I plan to post next.
See above.

On 8/15/23 23:08, Bhupesh Sharma wrote:
On Wed, 16 Aug 2023 at 02:31, Marek Vasut marek.vasut@mailbox.org wrote:
On 8/15/23 22:04, Bhupesh Sharma wrote:
Hi Marek,
On 8/14/23 5:22 AM, Marek Vasut wrote:
Add UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS for host controllers which do not support 64-bit addressing.
Ported from Linux kernel commit 6554400d6f66 ("scsi: ufs: core: Add UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS") with ufs_scsi_buffer_aligned() based on U-Boot generic bounce buffer.
Signed-off-by: Marek Vasut marek.vasut+renesas@mailbox.org
Cc: Faiz Abbas faiz_abbas@ti.com
drivers/ufs/ufs.c | 26 ++++++++++++++++++++++++++ drivers/ufs/ufs.h | 6 ++++++ 2 files changed, 32 insertions(+)
diff --git a/drivers/ufs/ufs.c b/drivers/ufs/ufs.c index 3bf1a95e7f2..da0550d98c6 100644 --- a/drivers/ufs/ufs.c +++ b/drivers/ufs/ufs.c @@ -8,6 +8,7 @@ * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com */ +#include <bouncebuf.h> #include <charset.h> #include <common.h> #include <dm.h> @@ -1889,6 +1890,8 @@ int ufshcd_probe(struct udevice *ufs_dev, struct ufs_hba_ops *hba_ops) /* Read capabilties registers */ hba->capabilities = ufshcd_readl(hba, REG_CONTROLLER_CAPABILITIES);
- if (hba->quirks & UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS)
hba->capabilities &= ~MASK_64_ADDRESSING_SUPPORT; /* Get UFS version supported by the controller */ hba->version = ufshcd_get_ufs_version(hba);
@@ -1942,8 +1945,31 @@ int ufs_scsi_bind(struct udevice *ufs_dev, struct udevice **scsi_devp) return ret; } +#if IS_ENABLED(CONFIG_BOUNCE_BUFFER) +static int ufs_scsi_buffer_aligned(struct udevice *scsi_dev, struct bounce_buffer *state) +{ +#ifdef CONFIG_PHYS_64BIT
- struct ufs_hba *hba = dev_get_uclass_priv(scsi_dev->parent);
- uintptr_t ubuf = (uintptr_t)state->user_buffer;
- size_t len = state->len_aligned;
- /* Check if below 32bit boundary */
- if ((hba->quirks & UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS) &&
((ubuf >> 32) || (ubuf + len) >> 32)) {
dev_dbg(scsi_dev, "Buffer above 32bit boundary %lx-%lx\n",
ubuf, ubuf + len);
return 0;
- }
+#endif
- return 1;
+} +#endif /* CONFIG_BOUNCE_BUFFER */
- static struct scsi_ops ufs_ops = { .exec = ufs_scsi_exec,
+#if IS_ENABLED(CONFIG_BOUNCE_BUFFER)
- .buffer_aligned = ufs_scsi_buffer_aligned,
+#endif /* CONFIG_BOUNCE_BUFFER */ }; int ufs_probe_dev(int index) diff --git a/drivers/ufs/ufs.h b/drivers/ufs/ufs.h index 8a38832b05f..070db0dce68 100644 --- a/drivers/ufs/ufs.h +++ b/drivers/ufs/ufs.h @@ -719,6 +719,12 @@ struct ufs_hba { */ #define UFSHCD_QUIRK_BROKEN_LCC 0x1 +/*
- This quirk needs to be enabled if the host controller has
- 64-bit addressing supported capability but it doesn't work.
- */
+#define UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS 0x2
/* Virtual memory reference */ struct utp_transfer_cmd_desc *ucdl; struct utp_transfer_req_desc *utrdl;
For this and the follow-up patch, I think implementing or at least supporting all the quirks currently supported by the Linux UFS driver makes sense as newer controllers do support these quirks.
I disagree. There is no point in implementing quirks which cannot be tested or may not even be relevant to U-Boot. Quirks which are needed should be added one by one.
I assume you agree we should not add all quirks at once ?
But the format you use for adding new quiks in u-boot is still in sync with Linux version 3.10. Can we atleast use the newer ( 1<< 7) kind of format for consistency.
Feel free to update quirks to BIT() macro.
We should enumerate the quirks in order instead of starting with BIT(7) however.

On Wed, 16 Aug 2023 at 03:10, Marek Vasut marek.vasut@mailbox.org wrote:
On 8/15/23 23:08, Bhupesh Sharma wrote:
On Wed, 16 Aug 2023 at 02:31, Marek Vasut marek.vasut@mailbox.org wrote:
On 8/15/23 22:04, Bhupesh Sharma wrote:
Hi Marek,
On 8/14/23 5:22 AM, Marek Vasut wrote:
Add UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS for host controllers which do not support 64-bit addressing.
Ported from Linux kernel commit 6554400d6f66 ("scsi: ufs: core: Add UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS") with ufs_scsi_buffer_aligned() based on U-Boot generic bounce buffer.
Signed-off-by: Marek Vasut marek.vasut+renesas@mailbox.org
Cc: Faiz Abbas faiz_abbas@ti.com
drivers/ufs/ufs.c | 26 ++++++++++++++++++++++++++ drivers/ufs/ufs.h | 6 ++++++ 2 files changed, 32 insertions(+)
diff --git a/drivers/ufs/ufs.c b/drivers/ufs/ufs.c index 3bf1a95e7f2..da0550d98c6 100644 --- a/drivers/ufs/ufs.c +++ b/drivers/ufs/ufs.c @@ -8,6 +8,7 @@ * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com */ +#include <bouncebuf.h> #include <charset.h> #include <common.h> #include <dm.h> @@ -1889,6 +1890,8 @@ int ufshcd_probe(struct udevice *ufs_dev, struct ufs_hba_ops *hba_ops) /* Read capabilties registers */ hba->capabilities = ufshcd_readl(hba, REG_CONTROLLER_CAPABILITIES);
- if (hba->quirks & UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS)
hba->capabilities &= ~MASK_64_ADDRESSING_SUPPORT; /* Get UFS version supported by the controller */ hba->version = ufshcd_get_ufs_version(hba);
@@ -1942,8 +1945,31 @@ int ufs_scsi_bind(struct udevice *ufs_dev, struct udevice **scsi_devp) return ret; } +#if IS_ENABLED(CONFIG_BOUNCE_BUFFER) +static int ufs_scsi_buffer_aligned(struct udevice *scsi_dev, struct bounce_buffer *state) +{ +#ifdef CONFIG_PHYS_64BIT
- struct ufs_hba *hba = dev_get_uclass_priv(scsi_dev->parent);
- uintptr_t ubuf = (uintptr_t)state->user_buffer;
- size_t len = state->len_aligned;
- /* Check if below 32bit boundary */
- if ((hba->quirks & UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS) &&
((ubuf >> 32) || (ubuf + len) >> 32)) {
dev_dbg(scsi_dev, "Buffer above 32bit boundary %lx-%lx\n",
ubuf, ubuf + len);
return 0;
- }
+#endif
- return 1;
+} +#endif /* CONFIG_BOUNCE_BUFFER */
- static struct scsi_ops ufs_ops = { .exec = ufs_scsi_exec,
+#if IS_ENABLED(CONFIG_BOUNCE_BUFFER)
- .buffer_aligned = ufs_scsi_buffer_aligned,
+#endif /* CONFIG_BOUNCE_BUFFER */ }; int ufs_probe_dev(int index) diff --git a/drivers/ufs/ufs.h b/drivers/ufs/ufs.h index 8a38832b05f..070db0dce68 100644 --- a/drivers/ufs/ufs.h +++ b/drivers/ufs/ufs.h @@ -719,6 +719,12 @@ struct ufs_hba { */ #define UFSHCD_QUIRK_BROKEN_LCC 0x1 +/*
- This quirk needs to be enabled if the host controller has
- 64-bit addressing supported capability but it doesn't work.
- */
+#define UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS 0x2
/* Virtual memory reference */ struct utp_transfer_cmd_desc *ucdl; struct utp_transfer_req_desc *utrdl;
For this and the follow-up patch, I think implementing or at least supporting all the quirks currently supported by the Linux UFS driver makes sense as newer controllers do support these quirks.
I disagree. There is no point in implementing quirks which cannot be tested or may not even be relevant to U-Boot. Quirks which are needed should be added one by one.
I assume you agree we should not add all quirks at once ?
But the format you use for adding new quiks in u-boot is still in sync with Linux version 3.10. Can we atleast use the newer ( 1<< 7) kind of format for consistency.
Feel free to update quirks to BIT() macro.
We should enumerate the quirks in order instead of starting with BIT(7) however.
Qualcomm UFS controllers support a few quirks from the list so the numbering can be taken care of in my patch.
But since 'include/ufs/ufs_quirks.h' in Linux already uses the (1 <<7) kind of format we can use the same as it would make future backporting from Linux easier.
Thanks.

On 8/16/23 00:05, Bhupesh Sharma wrote:
On Wed, 16 Aug 2023 at 03:10, Marek Vasut marek.vasut@mailbox.org wrote:
On 8/15/23 23:08, Bhupesh Sharma wrote:
On Wed, 16 Aug 2023 at 02:31, Marek Vasut marek.vasut@mailbox.org wrote:
On 8/15/23 22:04, Bhupesh Sharma wrote:
Hi Marek,
On 8/14/23 5:22 AM, Marek Vasut wrote:
Add UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS for host controllers which do not support 64-bit addressing.
Ported from Linux kernel commit 6554400d6f66 ("scsi: ufs: core: Add UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS") with ufs_scsi_buffer_aligned() based on U-Boot generic bounce buffer.
Signed-off-by: Marek Vasut marek.vasut+renesas@mailbox.org
Cc: Faiz Abbas faiz_abbas@ti.com
drivers/ufs/ufs.c | 26 ++++++++++++++++++++++++++ drivers/ufs/ufs.h | 6 ++++++ 2 files changed, 32 insertions(+)
diff --git a/drivers/ufs/ufs.c b/drivers/ufs/ufs.c index 3bf1a95e7f2..da0550d98c6 100644 --- a/drivers/ufs/ufs.c +++ b/drivers/ufs/ufs.c @@ -8,6 +8,7 @@ * Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com */ +#include <bouncebuf.h> #include <charset.h> #include <common.h> #include <dm.h> @@ -1889,6 +1890,8 @@ int ufshcd_probe(struct udevice *ufs_dev, struct ufs_hba_ops *hba_ops) /* Read capabilties registers */ hba->capabilities = ufshcd_readl(hba, REG_CONTROLLER_CAPABILITIES);
- if (hba->quirks & UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS)
hba->capabilities &= ~MASK_64_ADDRESSING_SUPPORT; /* Get UFS version supported by the controller */ hba->version = ufshcd_get_ufs_version(hba);
@@ -1942,8 +1945,31 @@ int ufs_scsi_bind(struct udevice *ufs_dev, struct udevice **scsi_devp) return ret; } +#if IS_ENABLED(CONFIG_BOUNCE_BUFFER) +static int ufs_scsi_buffer_aligned(struct udevice *scsi_dev, struct bounce_buffer *state) +{ +#ifdef CONFIG_PHYS_64BIT
- struct ufs_hba *hba = dev_get_uclass_priv(scsi_dev->parent);
- uintptr_t ubuf = (uintptr_t)state->user_buffer;
- size_t len = state->len_aligned;
- /* Check if below 32bit boundary */
- if ((hba->quirks & UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS) &&
((ubuf >> 32) || (ubuf + len) >> 32)) {
dev_dbg(scsi_dev, "Buffer above 32bit boundary %lx-%lx\n",
ubuf, ubuf + len);
return 0;
- }
+#endif
- return 1;
+} +#endif /* CONFIG_BOUNCE_BUFFER */
- static struct scsi_ops ufs_ops = { .exec = ufs_scsi_exec,
+#if IS_ENABLED(CONFIG_BOUNCE_BUFFER)
- .buffer_aligned = ufs_scsi_buffer_aligned,
+#endif /* CONFIG_BOUNCE_BUFFER */ }; int ufs_probe_dev(int index) diff --git a/drivers/ufs/ufs.h b/drivers/ufs/ufs.h index 8a38832b05f..070db0dce68 100644 --- a/drivers/ufs/ufs.h +++ b/drivers/ufs/ufs.h @@ -719,6 +719,12 @@ struct ufs_hba { */ #define UFSHCD_QUIRK_BROKEN_LCC 0x1 +/*
- This quirk needs to be enabled if the host controller has
- 64-bit addressing supported capability but it doesn't work.
- */
+#define UFSHCD_QUIRK_BROKEN_64BIT_ADDRESS 0x2
/* Virtual memory reference */ struct utp_transfer_cmd_desc *ucdl; struct utp_transfer_req_desc *utrdl;
For this and the follow-up patch, I think implementing or at least supporting all the quirks currently supported by the Linux UFS driver makes sense as newer controllers do support these quirks.
I disagree. There is no point in implementing quirks which cannot be tested or may not even be relevant to U-Boot. Quirks which are needed should be added one by one.
I assume you agree we should not add all quirks at once ?
But the format you use for adding new quiks in u-boot is still in sync with Linux version 3.10. Can we atleast use the newer ( 1<< 7) kind of format for consistency.
Feel free to update quirks to BIT() macro.
We should enumerate the quirks in order instead of starting with BIT(7) however.
Qualcomm UFS controllers support a few quirks from the list so the numbering can be taken care of in my patch.
But since 'include/ufs/ufs_quirks.h' in Linux already uses the (1 <<7) kind of format we can use the same as it would make future backporting from Linux easier.
Better use BIT() macro , can you fix that in Linux ? I'll fix it in V2 here.
participants (3)
-
Bhupesh Sharma
-
Marek Vasut
-
Marek Vasut