ufs: Add missing memory barriers
Add missing wmb() and mb() barriers in the u-boot UFS core
framework driver to allow registers updates to happen before
follow-up read operations.
This makes the barrier placement similar to the Linux UFS driver,
synced from the Linux v6.9 release.
Starting from the v6.10 release, the barriers were replaced with a register
read-back in [1], this will ported to u-boot in a second time.
[1] https://lore.kernel.org/all/20240329-ufs-reset-ensure-effect-before-delay-v5-0-181252004586@redhat.com/
Signed-off-by: Bhupesh Sharma <bhupesh.sharma@linaro.org>
Tested-by: Venkatesh Yadav Abbarapu <venkatesh.abbarapu@amd.com>
Tested-by: Julius Lehmann <lehmanju@devpi.de>
Link: https://lore.kernel.org/r/20240930-topic-ufs-enhancements-v3-10-58234f84ab89@linaro.org
Signed-off-by: Neil Armstrong <neil.armstrong@linaro.org>
diff --git a/drivers/ufs/ufs.c b/drivers/ufs/ufs.c
index 565a6af..5d4e542 100644
--- a/drivers/ufs/ufs.c
+++ b/drivers/ufs/ufs.c
@@ -433,6 +433,12 @@
REG_UTP_TASK_REQ_LIST_BASE_H);
/*
+ * Make sure base address and interrupt setup are updated before
+ * enabling the run/stop registers below.
+ */
+ wmb();
+
+ /*
* UCRDY, UTMRLDY and UTRLRDY bits must be 1
*/
reg = ufshcd_readl(hba, REG_CONTROLLER_STATUS);
@@ -861,6 +867,9 @@
ufshcd_writel(hba, 1 << task_tag, REG_UTP_TRANSFER_REQ_DOOR_BELL);
+ /* Make sure doorbell reg is updated before reading interrupt status */
+ wmb();
+
start = get_timer(0);
do {
intr_status = ufshcd_readl(hba, REG_INTERRUPT_STATUS);
@@ -1994,6 +2003,8 @@
REG_INTERRUPT_STATUS);
ufshcd_writel(hba, 0, REG_INTERRUPT_ENABLE);
+ mb();
+
err = ufshcd_hba_enable(hba);
if (err) {
dev_err(hba->dev, "Host controller enable failed\n");