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

Commit 47bdb5f1 authored by Can Guo's avatar Can Guo
Browse files

phy: qcom-ufs: add UFS HS-G4 support



New generation (3.0) UFS devices are capable of running at HS-G4
(High Speed Gear 4) mode which is 2x faster than previous generation
UFS devices. However, if the connected UFS device is only capable of HS-G3
at maximum, putting the UFS PHY to its HS-G4 settings would cause power
penalty. This change adds a boolean variable to the PHY calibration API to
allow the callers tell the calibration API whether HS-G3 or HS-G4 settings
should be configured. The value of this boolean variable is decided by the
UFS PHY's submode.

Change-Id: Id2e5fc2285e71ae07ab3b9a19c2aa3937ad465c8
Signed-off-by: default avatarCan Guo <cang@codeaurora.org>
parent 3ad271f0
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
/*
 * Copyright (c) 2013-2015, Linux Foundation. All rights reserved.
 * Copyright (c) 2013-2015, 2019, Linux Foundation. All rights reserved.
 */

#ifndef UFS_QCOM_PHY_I_H_
@@ -97,6 +97,7 @@ struct ufs_qcom_phy {
	struct ufs_qcom_phy_specific_ops *phy_spec_ops;

	enum phy_mode mode;
	int submode;
	struct reset_control *ufs_reset;
};

@@ -114,7 +115,8 @@ struct ufs_qcom_phy {
 * Rx line config
 */
struct ufs_qcom_phy_specific_ops {
	int (*calibrate)(struct ufs_qcom_phy *ufs_qcom_phy, bool is_rate_B);
	int (*calibrate)(struct ufs_qcom_phy *ufs_qcom_phy, bool is_rate_B,
			 bool is_g4);
	void (*start_serdes)(struct ufs_qcom_phy *phy);
	int (*is_physical_coding_sublayer_ready)(struct ufs_qcom_phy *phy);
	void (*set_tx_lane_enable)(struct ufs_qcom_phy *phy, u32 val);
+4 −2
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2013-2015, Linux Foundation. All rights reserved.
 * Copyright (c) 2013-2015, 2019, Linux Foundation. All rights reserved.
 */

#include "phy-qcom-ufs-qmp-14nm.h"
@@ -10,7 +10,7 @@

static
int ufs_qcom_phy_qmp_14nm_phy_calibrate(struct ufs_qcom_phy *ufs_qcom_phy,
					bool is_rate_B)
					bool is_rate_B, bool is_g4)
{
	int tbl_size_A = ARRAY_SIZE(phy_cal_table_rate_A);
	int tbl_size_B = ARRAY_SIZE(phy_cal_table_rate_B);
@@ -44,6 +44,8 @@ int ufs_qcom_phy_qmp_14nm_set_mode(struct phy *generic_phy,
	if (mode > 0)
		phy_common->mode = mode;

	phy_common->submode = submode;

	return 0;
}

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

#include "phy-qcom-ufs-qmp-20nm.h"
@@ -9,7 +9,7 @@

static
int ufs_qcom_phy_qmp_20nm_phy_calibrate(struct ufs_qcom_phy *ufs_qcom_phy,
					bool is_rate_B)
					bool is_rate_B, bool is_g4)
{
	struct ufs_qcom_phy_calibration *tbl_A, *tbl_B;
	int tbl_size_A, tbl_size_B;
@@ -63,6 +63,8 @@ int ufs_qcom_phy_qmp_20nm_set_mode(struct phy *generic_phy,
	if (mode > 0)
		phy_common->mode = mode;

	phy_common->submode = submode;

	return 0;
}

+2 −2
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2016, Linux Foundation. All rights reserved.
 * Copyright (c) 2016, 2019, Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -19,7 +19,7 @@

static
int ufs_qcom_phy_qrbtc_sdm845_phy_calibrate(struct ufs_qcom_phy *ufs_qcom_phy,
					bool is_rate_B)
					bool is_rate_B, bool is_g4)
{
	int err;
	int tbl_size_A, tbl_size_B;
+5 −1
Original line number Diff line number Diff line
@@ -599,6 +599,7 @@ int ufs_qcom_phy_power_on(struct phy *generic_phy)
	struct ufs_qcom_phy *phy_common = get_ufs_qcom_phy(generic_phy);
	struct device *dev = phy_common->dev;
	bool is_rate_B = false;
	bool is_gear4 = false;
	int err;

	err = ufs_qcom_phy_enable_vreg(dev, &phy_common->vdda_phy);
@@ -656,7 +657,10 @@ int ufs_qcom_phy_power_on(struct phy *generic_phy)
	if (phy_common->mode == PHY_MODE_UFS_HS_B)
		is_rate_B = true;

	err = phy_common->phy_spec_ops->calibrate(phy_common, is_rate_B);
	is_gear4 = !!phy_common->submode;

	err = phy_common->phy_spec_ops->calibrate(phy_common, is_rate_B,
						  is_gear4);
	if (err)
		goto out_disable_ref_clk;