refactor(ufs): reuse ufshc_send_uic_cmd
This change aims to make the UFS code more robust by removing asserts
and adding retry logic. We also reduce repetition by reusing
ufshc_send_uic_cmd for DME_GET and DME_SET commands.
Signed-off-by: Jorge Troncoso <jatron@google.com>
Change-Id: Id70aa1687d5ca78dc7d47234372255ac5a04a612
diff --git a/drivers/ufs/ufs.c b/drivers/ufs/ufs.c
index 6dbf372..97a9d5e 100644
--- a/drivers/ufs/ufs.c
+++ b/drivers/ufs/ufs.c
@@ -34,6 +34,9 @@
{
unsigned int data;
+ if (base == 0 || cmd == NULL)
+ return -EINVAL;
+
data = mmio_read_32(base + HCS);
if ((data & HCS_UCRDY) == 0)
return -EBUSY;
@@ -54,9 +57,13 @@
{
uintptr_t base;
unsigned int data;
- int retries;
+ int result, retries;
+ uic_cmd_t cmd;
- assert((ufs_params.reg_base != 0) && (val != NULL));
+ assert(ufs_params.reg_base != 0);
+
+ if (val == NULL)
+ return -EINVAL;
base = ufs_params.reg_base;
for (retries = 0; retries < 100; retries++) {
@@ -68,19 +75,20 @@
if (retries >= 100)
return -EBUSY;
- mmio_write_32(base + IS, ~0);
- mmio_write_32(base + UCMDARG1, (attr << 16) | GEN_SELECTOR_IDX(idx));
- mmio_write_32(base + UCMDARG2, 0);
- mmio_write_32(base + UCMDARG3, 0);
- mmio_write_32(base + UICCMD, DME_GET);
- do {
+ cmd.arg1 = (attr << 16) | GEN_SELECTOR_IDX(idx);
+ cmd.arg2 = 0;
+ cmd.arg3 = 0;
+ cmd.op = DME_GET;
+ for (retries = 0; retries < UFS_UIC_COMMAND_RETRIES; ++retries) {
+ result = ufshc_send_uic_cmd(base, &cmd);
+ if (result == 0)
+ break;
data = mmio_read_32(base + IS);
if (data & UFS_INT_UE)
return -EINVAL;
- } while ((data & UFS_INT_UCCS) == 0);
- mmio_write_32(base + IS, UFS_INT_UCCS);
- data = mmio_read_32(base + UCMDARG2) & CONFIG_RESULT_CODE_MASK;
- assert(data == 0);
+ }
+ if (retries >= UFS_UIC_COMMAND_RETRIES)
+ return -EIO;
*val = mmio_read_32(base + UCMDARG3);
return 0;
@@ -90,26 +98,28 @@
{
uintptr_t base;
unsigned int data;
+ int result, retries;
+ uic_cmd_t cmd;
assert((ufs_params.reg_base != 0));
base = ufs_params.reg_base;
- data = mmio_read_32(base + HCS);
- if ((data & HCS_UCRDY) == 0)
- return -EBUSY;
- mmio_write_32(base + IS, ~0);
- mmio_write_32(base + UCMDARG1, (attr << 16) | GEN_SELECTOR_IDX(idx));
- mmio_write_32(base + UCMDARG2, 0);
- mmio_write_32(base + UCMDARG3, val);
- mmio_write_32(base + UICCMD, DME_SET);
- do {
+ cmd.arg1 = (attr << 16) | GEN_SELECTOR_IDX(idx);
+ cmd.arg2 = 0;
+ cmd.arg3 = val;
+ cmd.op = DME_SET;
+
+ for (retries = 0; retries < UFS_UIC_COMMAND_RETRIES; ++retries) {
+ result = ufshc_send_uic_cmd(base, &cmd);
+ if (result == 0)
+ break;
data = mmio_read_32(base + IS);
if (data & UFS_INT_UE)
return -EINVAL;
- } while ((data & UFS_INT_UCCS) == 0);
- mmio_write_32(base + IS, UFS_INT_UCCS);
- data = mmio_read_32(base + UCMDARG2) & CONFIG_RESULT_CODE_MASK;
- assert(data == 0);
+ }
+ if (retries >= UFS_UIC_COMMAND_RETRIES)
+ return -EIO;
+
return 0;
}
diff --git a/include/drivers/ufs.h b/include/drivers/ufs.h
index 574c4ea..3f8f360 100644
--- a/include/drivers/ufs.h
+++ b/include/drivers/ufs.h
@@ -254,6 +254,10 @@
#define UFS_VENDOR_SKHYNIX U(0x1AD)
#define MAX_MODEL_LEN 16
+
+/* maximum number of retries for a general UIC command */
+#define UFS_UIC_COMMAND_RETRIES 3
+
/**
* ufs_dev_desc - ufs device details from the device descriptor
* @wmanufacturerid: card details