From 91270dbb7a974620299fede246ff6e4897fb3129 Mon Sep 17 00:00:00 2001 From: "Bao D. Nguyen" Date: Thu, 3 Nov 2022 22:02:16 -0700 Subject: [PATCH 1/2] scsi: ufs-qcom: Add support for UFS device version detection The bootloader software is aware of the type of UFS device populated on the board. It passes this information through a UFS's controller spare register. Retrieve the UFS device type information passed from the bootloader. Together with the Device Tree settings for the UFS's rate and PHY's submode, configure the UFS PHY properly to work with different types of UFS device populated on the board. Change-Id: Ide107ef87405fb9c8c30f6ada67613bc44ef28e8 Signed-off-by: Bao D. Nguyen --- drivers/ufs/host/ufs-qcom.c | 28 ++++++++++++++++++++++++++++ drivers/ufs/host/ufs-qcom.h | 2 ++ 2 files changed, 30 insertions(+) diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c index eb7fbff7f8f2..5071ae136db5 100644 --- a/drivers/ufs/host/ufs-qcom.c +++ b/drivers/ufs/host/ufs-qcom.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2013-2022, Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -3850,6 +3851,8 @@ static void ufs_qcom_dump_dbg_regs(struct ufs_hba *hba) static void ufs_qcom_parse_limits(struct ufs_qcom_host *host) { struct device_node *np = host->hba->dev->of_node; + u32 dev_major = 0, dev_minor = 0; + u32 val; if (!np) return; @@ -3861,6 +3864,31 @@ static void ufs_qcom_parse_limits(struct ufs_qcom_host *host) host->limit_rate = UFS_QCOM_LIMIT_HS_RATE; host->limit_phy_submode = UFS_QCOM_LIMIT_PHY_SUBMODE; + /* + * The bootloader passes the on board device + * information to the HLOS using the UFS host controller register's + * UFS_MEM_DEBUG_SPARE_CFG Bit[0:3] = device's minor revision + * UFS_MEM_DEBUG_SPARE_CFG Bit[4:7] = device's major revision + * For example, UFS 3.1 devices would have a 0x31, and UFS 4.0 devices + * would have a 0x40 as the content of the mentioned register. + * If the bootloader does not support this feature, the default + * hardcoded setting would be used. The DT settings can be used to + * override any other gear's and Rate's settings. + */ + if (host->hw_ver.major >= 0x5) { + val = ufshcd_readl(host->hba, REG_UFS_DEBUG_SPARE_CFG); + dev_major = FIELD_GET(GENMASK(7, 4), val); + dev_minor = FIELD_GET(GENMASK(3, 0), val); + } + + if (host->hw_ver.major == 0x5 && dev_major >= 0x4 && dev_minor >= 0) { + host->limit_rate = PA_HS_MODE_A; + host->limit_phy_submode = UFS_QCOM_PHY_SUBMODE_G5; + } else if (host->hw_ver.major >= 0x6 && dev_major >= 0x4 && dev_minor >= 0) { + host->limit_rate = PA_HS_MODE_B; + host->limit_phy_submode = UFS_QCOM_PHY_SUBMODE_G5; + } + of_property_read_u32(np, "limit-tx-hs-gear", &host->limit_tx_hs_gear); of_property_read_u32(np, "limit-rx-hs-gear", &host->limit_rx_hs_gear); of_property_read_u32(np, "limit-tx-pwm-gear", &host->limit_tx_pwm_gear); diff --git a/drivers/ufs/host/ufs-qcom.h b/drivers/ufs/host/ufs-qcom.h index e88441ac8cc2..779802c328b6 100644 --- a/drivers/ufs/host/ufs-qcom.h +++ b/drivers/ufs/host/ufs-qcom.h @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* Copyright (c) 2013-2022, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef UFS_QCOM_H_ @@ -85,6 +86,7 @@ enum { */ UFS_AH8_CFG = 0xFC, UFS_MEM_ICE = 0x2600, + REG_UFS_DEBUG_SPARE_CFG = 0x284C, }; /* QCOM UFS host controller vendor specific debug registers */ From fcfc5902c3a6266ff747042c40c7cc431e4b3954 Mon Sep 17 00:00:00 2001 From: "Bao D. Nguyen" Date: Thu, 3 Nov 2022 22:08:59 -0700 Subject: [PATCH 2/2] scsi: ufs: ufs-qcom: Correct the REG_UFS_CFG0 setting for pineapple Correctly configure the REG_UFS_CFG0 register for supporting UFS4.0 devices on pineapple platforms. Change-Id: If2edfb4d939a15d08bcdc2150e4badd086bc7ccf Signed-off-by: Bao D. Nguyen --- drivers/ufs/host/ufs-qcom.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c index 5071ae136db5..97f1660d5e34 100644 --- a/drivers/ufs/host/ufs-qcom.c +++ b/drivers/ufs/host/ufs-qcom.c @@ -482,7 +482,7 @@ static void ufs_qcom_select_unipro_mode(struct ufs_qcom_host *host) ufs_qcom_cap_qunipro(host) ? QUNIPRO_SEL : 0, REG_UFS_CFG1); - if (host->hw_ver.major == 0x05) + if (host->hw_ver.major >= 0x05) ufshcd_rmwl(host->hba, QUNIPRO_G4_SEL, 0, REG_UFS_CFG0); /* make sure above configuration is applied before we return */ @@ -646,7 +646,7 @@ static int ufs_qcom_enable_hw_clk_gating(struct ufs_hba *hba) ufshcd_readl(hba, REG_UFS_CFG2) | REG_UFS_CFG2_CGC_EN_ALL, REG_UFS_CFG2); - if (host->hw_ver.major == 0x05) + if (host->hw_ver.major >= 0x05) /* Ensure unused Unipro block's clock is gated */ ufshcd_rmwl(host->hba, UNUSED_UNIPRO_CLK_GATED, UNUSED_UNIPRO_CLK_GATED, UFS_AH8_CFG);