From 50593e696edee7c296d1bc3ef346888c200b1c02 Mon Sep 17 00:00:00 2001 From: anans Date: Mon, 21 Mar 2022 09:43:11 +0530 Subject: [PATCH 1/3] refactor(ufs): adds a function for fdeviceinit time taken for device init varies based on different devices, instead of waiting for 200ms - we can poll on fdevice init until it gets cleared, similar to what linux does Change-Id: I571649231732fde0cd6d5be89b6f14fe905fcaff Signed-off-by: anans --- drivers/ufs/ufs.c | 33 ++++++++++++++++++++++++++++++--- include/drivers/ufs.h | 2 ++ 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/drivers/ufs/ufs.c b/drivers/ufs/ufs.c index 3c27afff2..f4e54b3d3 100644 --- a/drivers/ufs/ufs.c +++ b/drivers/ufs/ufs.c @@ -734,16 +734,41 @@ size_t ufs_write_blocks(int lun, int lba, const uintptr_t buf, size_t size) return size - resp->res_trans_cnt; } +static int ufs_set_fdevice_init(void) +{ + unsigned int result; + int timeout; + + ufs_set_flag(FLAG_DEVICE_INIT); + + timeout = FDEVICEINIT_TIMEOUT_MS; + do { + result = ufs_read_flag(FLAG_DEVICE_INIT); + if (!result) { + break; + } + mdelay(5); + timeout -= 5; + } while (timeout > 0); + + if (result != 0U) { + return -ETIMEDOUT; + } + + return 0; +} + static void ufs_enum(void) { unsigned int blk_num, blk_size; - int i; + int i, result; ufs_verify_init(); ufs_verify_ready(); - ufs_set_flag(FLAG_DEVICE_INIT); - mdelay(200); + result = ufs_set_fdevice_init(); + assert(result == 0); + /* dump available LUNs */ for (i = 0; i < UFS_MAX_LUNS; i++) { ufs_read_capacity(i, &blk_num, &blk_size); @@ -752,6 +777,8 @@ static void ufs_enum(void) i, blk_num, blk_size); } } + + (void)result; } static void ufs_get_device_info(struct ufs_dev_desc *card_data) diff --git a/include/drivers/ufs.h b/include/drivers/ufs.h index c074e85d1..8930474a9 100644 --- a/include/drivers/ufs.h +++ b/include/drivers/ufs.h @@ -265,6 +265,8 @@ #define HCE_ENABLE_INNER_RETRIES 50 #define HCE_ENABLE_TIMEOUT_US 100 +#define FDEVICEINIT_TIMEOUT_MS 1500 + /** * ufs_dev_desc - ufs device details from the device descriptor * @wmanufacturerid: card details From b3f03b20135fc5fcd5e6ec7e5ca49f1e59b5602e Mon Sep 17 00:00:00 2001 From: anans Date: Mon, 21 Mar 2022 09:59:18 +0530 Subject: [PATCH 2/3] fix(ufs): disables controller if enabled ufs controller needs to be disabled if already enabled, without this we noticed a crash at linkstartup during reinit Signed-off-by: anans Change-Id: I523c5d57c1d34f6404a6368ee3f364fbffd2e542 --- drivers/ufs/ufs.c | 32 ++++++++++++++++++++++++++++++++ include/drivers/ufs.h | 2 ++ 2 files changed, 34 insertions(+) diff --git a/drivers/ufs/ufs.c b/drivers/ufs/ufs.c index f4e54b3d3..720b73235 100644 --- a/drivers/ufs/ufs.c +++ b/drivers/ufs/ufs.c @@ -146,11 +146,43 @@ static int ufshc_hce_enable(uintptr_t base) return 0; } +static int ufshc_hce_disable(uintptr_t base) +{ + unsigned int data; + int timeout; + + /* Disable Host Controller */ + mmio_write_32(base + HCE, HCE_DISABLE); + timeout = HCE_DISABLE_TIMEOUT_US; + do { + data = mmio_read_32(base + HCE); + if ((data & HCE_ENABLE) == HCE_DISABLE) { + break; + } + udelay(1); + } while (--timeout > 0); + + if (timeout <= 0) { + return -ETIMEDOUT; + } + + return 0; +} + + static int ufshc_reset(uintptr_t base) { unsigned int data; int retries, result; + /* disable controller if enabled */ + if (mmio_read_32(base + HCE) & HCE_ENABLE) { + result = ufshc_hce_disable(base); + if (result != 0) { + return -EIO; + } + } + for (retries = 0; retries < HCE_ENABLE_OUTER_RETRIES; ++retries) { result = ufshc_hce_enable(base); if (result == 0) { diff --git a/include/drivers/ufs.h b/include/drivers/ufs.h index 8930474a9..4a5e46495 100644 --- a/include/drivers/ufs.h +++ b/include/drivers/ufs.h @@ -69,6 +69,7 @@ /* Host Controller Enable */ #define HCE 0x34 #define HCE_ENABLE 1 +#define HCE_DISABLE 0 /* Host UIC Error Code PHY Adapter Layer */ #define UECPA 0x38 @@ -264,6 +265,7 @@ #define HCE_ENABLE_OUTER_RETRIES 3 #define HCE_ENABLE_INNER_RETRIES 50 #define HCE_ENABLE_TIMEOUT_US 100 +#define HCE_DISABLE_TIMEOUT_US 1000 #define FDEVICEINIT_TIMEOUT_MS 1500 From a475518337e15935469543b1cce353e5b337ef52 Mon Sep 17 00:00:00 2001 From: anans Date: Mon, 18 Apr 2022 12:21:43 +0530 Subject: [PATCH 3/3] fix(ufs): read and write attribute based on spec according to the spec, the response to read attr comes in the ts.attr.value field and not in the data segment. Signed-off-by: anans Change-Id: Iaf21883bb7e364fd7c7e4bccb33359367a0cf99d --- drivers/ufs/ufs.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/ufs/ufs.c b/drivers/ufs/ufs.c index 720b73235..c71ff5a76 100644 --- a/drivers/ufs/ufs.c +++ b/drivers/ufs/ufs.c @@ -441,7 +441,7 @@ static int ufs_prepare_query(utp_utrd_t *utrd, uint8_t op, uint8_t idn, break; case QUERY_WRITE_ATTR: query_upiu->query_func = QUERY_FUNC_STD_WRITE; - memcpy((void *)&query_upiu->ts.attr.value, (void *)buf, length); + query_upiu->ts.attr.value = htobe32(*((uint32_t *)buf)); break; default: assert(0); @@ -624,12 +624,14 @@ static void ufs_query(uint8_t op, uint8_t idn, uint8_t index, uint8_t sel, case QUERY_READ_FLAG: *(uint32_t *)buf = (uint32_t)resp->ts.flag.value; break; - case QUERY_READ_ATTR: case QUERY_READ_DESC: memcpy((void *)buf, (void *)(utrd.resp_upiu + sizeof(query_resp_upiu_t)), size); break; + case QUERY_READ_ATTR: + *(uint32_t *)buf = htobe32(resp->ts.attr.value); + break; default: /* Do nothing in default case */ break;