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 <quic_nguyenb@quicinc.com>
This commit is contained in:
Bao D. Nguyen 2022-11-03 22:02:16 -07:00
parent 0be12ba8de
commit 91270dbb7a
2 changed files with 30 additions and 0 deletions

View File

@ -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 <linux/acpi.h>
@ -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);

View File

@ -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 */