diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-07-07 04:53:18 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-07-07 04:53:18 +0000 |
commit | 4bbd0cd0119622be8e5f8fae058774b1650f6a44 (patch) | |
tree | 2ce8a4e341ac9f98fb265347777487eda74eba48 /drivers/ufs/ufs.c | |
parent | f95ca314c488ae4fc69f08379e5cbb3c12adb9a5 (diff) | |
parent | 138668cae2394deb5d695c70fe4aa9760c4458ee (diff) | |
download | arm-trusted-firmware-4bbd0cd0119622be8e5f8fae058774b1650f6a44.tar.gz |
Snap for 10453563 from 138668cae2394deb5d695c70fe4aa9760c4458ee to mainline-mediaprovider-releaseaml_mpr_341713020aml_mpr_341614010aml_mpr_341511070aml_mpr_341411070aml_mpr_341313030aml_mpr_341111030aml_mpr_341111020aml_mpr_341015090aml_mpr_341015030aml_mpr_340919000android14-mainline-mediaprovider-release
Change-Id: I889bd88f18521a36153944279cb56cb397c7ce03
Diffstat (limited to 'drivers/ufs/ufs.c')
-rw-r--r-- | drivers/ufs/ufs.c | 122 |
1 files changed, 87 insertions, 35 deletions
diff --git a/drivers/ufs/ufs.c b/drivers/ufs/ufs.c index 6dbf37236..ae42e326f 100644 --- a/drivers/ufs/ufs.c +++ b/drivers/ufs/ufs.c @@ -34,6 +34,9 @@ int ufshc_send_uic_cmd(uintptr_t base, uic_cmd_t *cmd) { 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 @@ int ufshc_dme_get(unsigned int attr, unsigned int idx, unsigned int *val) { uintptr_t base; unsigned int data; - int retries; + int result, retries; + uic_cmd_t cmd; + + assert(ufs_params.reg_base != 0); - assert((ufs_params.reg_base != 0) && (val != NULL)); + if (val == NULL) + return -EINVAL; base = ufs_params.reg_base; for (retries = 0; retries < 100; retries++) { @@ -68,19 +75,20 @@ int ufshc_dme_get(unsigned int attr, unsigned int idx, unsigned int *val) 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,58 +98,101 @@ int ufshc_dme_set(unsigned int attr, unsigned int idx, unsigned int val) { 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; } -static void ufshc_reset(uintptr_t base) +static int ufshc_hce_enable(uintptr_t base) { unsigned int data; + int retries; /* Enable Host Controller */ mmio_write_32(base + HCE, HCE_ENABLE); + /* Wait until basic initialization sequence completed */ - do { + for (retries = 0; retries < HCE_ENABLE_INNER_RETRIES; ++retries) { data = mmio_read_32(base + HCE); - } while ((data & HCE_ENABLE) == 0); + if (data & HCE_ENABLE) { + break; + } + udelay(HCE_ENABLE_TIMEOUT_US); + } + if (retries >= HCE_ENABLE_INNER_RETRIES) { + return -ETIMEDOUT; + } + + return 0; +} + +static int ufshc_reset(uintptr_t base) +{ + unsigned int data; + int retries, result; + + for (retries = 0; retries < HCE_ENABLE_OUTER_RETRIES; ++retries) { + result = ufshc_hce_enable(base); + if (result == 0) { + break; + } + } + if (retries >= HCE_ENABLE_OUTER_RETRIES) { + return -EIO; + } /* Enable Interrupts */ data = UFS_INT_UCCS | UFS_INT_ULSS | UFS_INT_UE | UFS_INT_UTPES | UFS_INT_DFES | UFS_INT_HCFES | UFS_INT_SBFES; mmio_write_32(base + IE, data); + + return 0; } -static int ufshc_link_startup(uintptr_t base) +static int ufshc_dme_link_startup(uintptr_t base) { uic_cmd_t cmd; + + memset(&cmd, 0, sizeof(cmd)); + cmd.op = DME_LINKSTARTUP; + return ufshc_send_uic_cmd(base, &cmd); +} + +static int ufshc_link_startup(uintptr_t base) +{ int data, result; int retries; - for (retries = 10; retries > 0; retries--) { - memset(&cmd, 0, sizeof(cmd)); - cmd.op = DME_LINKSTARTUP; - result = ufshc_send_uic_cmd(base, &cmd); - if (result != 0) + for (retries = DME_LINKSTARTUP_RETRIES; retries > 0; retries--) { + result = ufshc_dme_link_startup(base); + if (result != 0) { + /* Reset controller before trying again */ + result = ufshc_reset(base); + if (result != 0) { + return result; + } continue; + } while ((mmio_read_32(base + HCS) & HCS_DP) == 0) ; data = mmio_read_32(base + IS); @@ -772,7 +823,8 @@ int ufs_init(const ufs_ops_t *ops, ufs_params_t *params) assert((ops != NULL) && (ops->phy_init != NULL) && (ops->phy_set_pwr_mode != NULL)); - ufshc_reset(ufs_params.reg_base); + result = ufshc_reset(ufs_params.reg_base); + assert(result == 0); ops->phy_init(&ufs_params); result = ufshc_link_startup(ufs_params.reg_base); assert(result == 0); |