Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 278cc639 authored by Can Guo's avatar Can Guo
Browse files

ufs: ufs-qcom: Clean up UFS PHY mode and submode selection



In hba power up sequence, phy_set_mode_ext() is used to pass UFS PHY mode
and HS gear as the submode to UFS PHY driver. UFS PHY mode is decided by
limit_rate, which is Rate-B by default. While, UFS PHY submode is dediced
by limit_phy_submode, 1 stands for G4, 0 stands for non-G4.

Change-Id: I54fc377abd42290e76094125b446d24ef1478124
Signed-off-by: default avatarCan Guo <cang@codeaurora.org>
parent 9f8c6436
Loading
Loading
Loading
Loading
+22 −48
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2013-2019, Linux Foundation. All rights reserved.
 * Copyright (c) 2013-2020, Linux Foundation. All rights reserved.
 */

#include <linux/acpi.h>
@@ -69,7 +69,7 @@ static void ufs_qcom_get_default_testbus_cfg(struct ufs_qcom_host *host);
static int ufs_qcom_set_dme_vs_core_clk_ctrl_clear_div(struct ufs_hba *hba,
						       u32 clk_1us_cycles,
						       u32 clk_40ns_cycles);
static void ufs_qcom_parse_gear_limits(struct ufs_qcom_host *host);
static void ufs_qcom_parse_limits(struct ufs_qcom_host *host);
static void ufs_qcom_parse_lpm(struct ufs_qcom_host *host);
static int ufs_qcom_set_dme_vs_core_clk_ctrl_max_freq_mode(struct ufs_hba *hba);

@@ -456,8 +456,9 @@ static int ufs_qcom_power_up_sequence(struct ufs_hba *hba)
	struct ufs_qcom_host *host = ufshcd_get_variant(hba);
	struct phy *phy = host->generic_phy;
	int ret = 0;
	bool is_rate_B = (UFS_QCOM_LIMIT_HS_RATE == PA_HS_MODE_B)
							? true : false;
	enum phy_mode mode = (host->limit_rate == PA_HS_MODE_B) ?
					PHY_MODE_UFS_HS_B : PHY_MODE_UFS_HS_A;
	int submode = host->limit_phy_submode;

	/* Reset UFS Host Controller and PHY */
	ret = ufs_qcom_host_reset(hba);
@@ -465,23 +466,10 @@ static int ufs_qcom_power_up_sequence(struct ufs_hba *hba)
		dev_warn(hba->dev, "%s: host reset returned %d\n",
				  __func__, ret);

#ifdef CONFIG_SCSI_UFSHCD_QTI
	/* Use Rate-A for Gear4 on non-simulation platforms */
	if (hba->phy_init_g4) {
		if (!host->limit_rate)
			is_rate_B = false;
		else
			is_rate_B = true;
	}
	if (host->hw_ver.major < 0x4)
		submode = UFS_QCOM_PHY_SUBMODE_NON_G4;
	phy_set_mode_ext(phy, mode, submode);

	phy_set_mode_ext(phy,
			 is_rate_B ? PHY_MODE_UFS_HS_B : PHY_MODE_UFS_HS_A,
			 hba->phy_init_g4);
#else
	if (is_rate_B)
		phy_set_mode(phy, PHY_MODE_UFS_HS_B);

#endif
	/* phy initialization - calibrate the phy */
	ret = phy_init(phy);
	if (ret) {
@@ -1329,25 +1317,6 @@ static void ufs_qcom_dev_ref_clk_ctrl(struct ufs_qcom_host *host, bool enable)
	}
}

#ifdef CONFIG_SCSI_UFSHCD_QTI
static inline void ufs_qcom_set_hs_rate(struct ufs_hba *hba,
					struct ufs_qcom_dev_params *params)
{
	struct ufs_qcom_host *host = ufshcd_get_variant(hba);

	params->hs_rate = PA_HS_MODE_B;
	if (hba->phy_init_g4) {
		if (!host->limit_rate)
			params->hs_rate = PA_HS_MODE_A;
	}
}
#else
static inline void ufs_qcom_set_hs_rate(struct ufs_hba *hba,
					struct ufs_qcom_dev_params *params)
{

}
#endif
static int ufs_qcom_pwr_change_notify(struct ufs_hba *hba,
				enum ufs_notify_change_status status,
				struct ufs_pa_layer_attr *dev_max_params,
@@ -1380,8 +1349,8 @@ static int ufs_qcom_pwr_change_notify(struct ufs_hba *hba,
		ufs_qcom_cap.rx_pwr_hs = UFS_QCOM_LIMIT_RX_PWR_HS;
		ufs_qcom_cap.tx_pwr_hs = UFS_QCOM_LIMIT_TX_PWR_HS;

		ufs_qcom_cap.hs_rate = UFS_QCOM_LIMIT_HS_RATE;
		ufs_qcom_set_hs_rate(hba, &ufs_qcom_cap);
		ufs_qcom_cap.hs_rate = host->limit_rate;

		ufs_qcom_cap.desired_working_mode =
					UFS_QCOM_LIMIT_DESIRED_MODE;

@@ -1397,6 +1366,11 @@ static int ufs_qcom_pwr_change_notify(struct ufs_hba *hba,
				ufs_qcom_cap.hs_tx_gear = UFS_HS_G2;
			if (ufs_qcom_cap.hs_rx_gear > UFS_HS_G2)
				ufs_qcom_cap.hs_rx_gear = UFS_HS_G2;
		} else if (host->hw_ver.major < 0x4) {
			if (ufs_qcom_cap.hs_tx_gear > UFS_HS_G3)
				ufs_qcom_cap.hs_tx_gear = UFS_HS_G3;
			if (ufs_qcom_cap.hs_rx_gear > UFS_HS_G3)
				ufs_qcom_cap.hs_rx_gear = UFS_HS_G3;
		}

		ret = ufs_qcom_get_pwr_dev_param(&ufs_qcom_cap,
@@ -2166,7 +2140,7 @@ static int ufs_qcom_init(struct ufs_hba *hba)
	if (err)
		goto out_set_load_vccq_parent;

	ufs_qcom_parse_gear_limits(host);
	ufs_qcom_parse_limits(host);
	ufs_qcom_parse_lpm(host);
	if (host->disable_lpm)
		pm_runtime_forbid(host->hba->dev);
@@ -2674,12 +2648,11 @@ static void ufs_qcom_dump_dbg_regs(struct ufs_hba *hba)
}

/*
 * ufs_qcom_parse_gear_limits - read from DTS if gears should be limited
 * ufs_qcom_parse_limits - read limits from DTS
 */
static void ufs_qcom_parse_gear_limits(struct ufs_qcom_host *host)
static void ufs_qcom_parse_limits(struct ufs_qcom_host *host)
{
	struct device_node *np = host->hba->dev->of_node;
	int ret;

	if (!np)
		return;
@@ -2688,14 +2661,15 @@ static void ufs_qcom_parse_gear_limits(struct ufs_qcom_host *host)
	host->limit_rx_hs_gear = UFS_QCOM_LIMIT_HSGEAR_RX;
	host->limit_tx_pwm_gear = UFS_QCOM_LIMIT_PWMGEAR_TX;
	host->limit_rx_pwm_gear = UFS_QCOM_LIMIT_PWMGEAR_RX;
	host->limit_rate = UFS_QCOM_LIMIT_HS_RATE;
	host->limit_phy_submode = UFS_QCOM_LIMIT_PHY_SUBMODE;

	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);
	of_property_read_u32(np, "limit-rx-pwm-gear", &host->limit_rx_pwm_gear);
	ret = of_property_read_u32(np, "limit-rate", &host->limit_rate);
	if (ret)
		host->limit_rate = 0;
	of_property_read_u32(np, "limit-rate", &host->limit_rate);
	of_property_read_u32(np, "limit-phy-submode", &host->limit_phy_submode);
}

/*
+8 −8
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
/* Copyright (c) 2013-2019, The Linux Foundation. All rights reserved.
/* Copyright (c) 2013-2020, The Linux Foundation. All rights reserved.
 */

#ifndef UFS_QCOM_H_
@@ -30,28 +30,27 @@
#define UFS_HW_VER_STEP_MASK	(0xFFFF << UFS_HW_VER_STEP_SHFT)

/* vendor specific pre-defined parameters */
#define UFS_HS_G4	4		/* HS Gear 4 */

#define SLOW 1
#define FAST 2

#define UFS_QCOM_PHY_SUBMODE_NON_G4	0
#define UFS_QCOM_PHY_SUBMODE_G4		1

#define UFS_QCOM_LIMIT_NUM_LANES_RX	2
#define UFS_QCOM_LIMIT_NUM_LANES_TX	2
#ifdef CONFIG_SCSI_UFSHCD_QTI
#define UFS_QCOM_LIMIT_HSGEAR_RX	UFS_HS_G4
#define UFS_QCOM_LIMIT_HSGEAR_TX	UFS_HS_G4
#define UFS_QCOM_LIMIT_PWMGEAR_RX	UFS_PWM_G4
#define UFS_QCOM_LIMIT_PWMGEAR_TX	UFS_PWM_G4
#else
#define UFS_QCOM_LIMIT_HSGEAR_RX	UFS_HS_G3
#define UFS_QCOM_LIMIT_HSGEAR_TX	UFS_HS_G3
#define UFS_QCOM_LIMIT_PWMGEAR_RX	UFS_PWM_G3
#define UFS_QCOM_LIMIT_PWMGEAR_TX	UFS_PWM_G3
#endif
#define UFS_QCOM_LIMIT_RX_PWR_PWM	SLOW_MODE
#define UFS_QCOM_LIMIT_TX_PWR_PWM	SLOW_MODE
#define UFS_QCOM_LIMIT_RX_PWR_HS	FAST_MODE
#define UFS_QCOM_LIMIT_TX_PWR_HS	FAST_MODE
#define UFS_QCOM_LIMIT_HS_RATE		PA_HS_MODE_B
#define UFS_QCOM_LIMIT_DESIRED_MODE	FAST
#define UFS_QCOM_LIMIT_PHY_SUBMODE	UFS_QCOM_PHY_SUBMODE_G4

/* QCOM UFS host controller vendor specific registers */
enum {
@@ -324,6 +323,7 @@ struct ufs_qcom_host {
	int limit_tx_pwm_gear;
	int limit_rx_pwm_gear;
	int limit_rate;
	int limit_phy_submode;

	bool disable_lpm;
	struct qcom_bus_scale_data *qbsd;