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

Commit 54098687 authored by Can Guo's avatar Can Guo
Browse files

phy: ufs: Refactor phy_power_on and phy_calibrate callbacks



Move UFS PHY calibration, starting serdes and PCS ready status polling
from phy_power_on callback to phy_calibrate callback.

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

#ifndef UFS_QCOM_PHY_I_H_
@@ -137,6 +137,7 @@ struct phy *ufs_qcom_phy_generic_probe(struct platform_device *pdev,
			struct ufs_qcom_phy *common_cfg,
			const struct phy_ops *ufs_qcom_phy_gen_ops,
			struct ufs_qcom_phy_specific_ops *phy_spec_ops);
int ufs_qcom_phy_get_reset(struct ufs_qcom_phy *phy_common);
int ufs_qcom_phy_calibrate(struct ufs_qcom_phy *ufs_qcom_phy,
			struct ufs_qcom_phy_calibration *tbl_A, int tbl_size_A,
			struct ufs_qcom_phy_calibration *tbl_B, int tbl_size_B,
+7 −4
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2013-2015, 2019, Linux Foundation. All rights reserved.
 * Copyright (c) 2013-2015, 2019-2020, Linux Foundation. All rights reserved.
 */

#include "phy-qcom-ufs-qmp-14nm.h"
@@ -9,13 +9,16 @@
#define UFS_PHY_VDDA_PHY_UV	(925000)

static
int ufs_qcom_phy_qmp_14nm_phy_calibrate(struct ufs_qcom_phy *ufs_qcom_phy,
					bool is_rate_B, bool is_g4)
int ufs_qcom_phy_qmp_14nm_phy_calibrate(struct phy *generic_phy)
{
	struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(generic_phy);
	int tbl_size_A = ARRAY_SIZE(phy_cal_table_rate_A);
	int tbl_size_B = ARRAY_SIZE(phy_cal_table_rate_B);
	bool is_rate_B;
	int err;

	is_rate_B = (ufs_qcom_phy->mode == PHY_MODE_UFS_HS_B) ? true : false;

	err = ufs_qcom_phy_calibrate(ufs_qcom_phy, phy_cal_table_rate_A,
		tbl_size_A, phy_cal_table_rate_B, tbl_size_B, is_rate_B);

@@ -98,11 +101,11 @@ static const struct phy_ops ufs_qcom_phy_qmp_14nm_phy_ops = {
	.power_on	= ufs_qcom_phy_power_on,
	.power_off	= ufs_qcom_phy_power_off,
	.set_mode	= ufs_qcom_phy_qmp_14nm_set_mode,
	.calibrate	= ufs_qcom_phy_qmp_14nm_phy_calibrate,
	.owner		= THIS_MODULE,
};

static struct ufs_qcom_phy_specific_ops phy_14nm_ops = {
	.calibrate		= ufs_qcom_phy_qmp_14nm_phy_calibrate,
	.start_serdes		= ufs_qcom_phy_qmp_14nm_start_serdes,
	.is_physical_coding_sublayer_ready = ufs_qcom_phy_qmp_14nm_is_pcs_ready,
	.set_tx_lane_enable	= ufs_qcom_phy_qmp_14nm_set_tx_lane_enable,
+6 −4
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2013-2015, 2019, Linux Foundation. All rights reserved.
 * Copyright (c) 2013-2015, 2019-2020, Linux Foundation. All rights reserved.
 */

#include "phy-qcom-ufs-qmp-20nm.h"
@@ -8,11 +8,12 @@
#define UFS_PHY_NAME "ufs_phy_qmp_20nm"

static
int ufs_qcom_phy_qmp_20nm_phy_calibrate(struct ufs_qcom_phy *ufs_qcom_phy,
					bool is_rate_B, bool is_g4)
int ufs_qcom_phy_qmp_20nm_phy_calibrate(struct phy *generic_phy)
{
	struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(generic_phy);
	struct ufs_qcom_phy_calibration *tbl_A, *tbl_B;
	int tbl_size_A, tbl_size_B;
	bool is_rate_B;
	u8 major = ufs_qcom_phy->host_ctrl_rev_major;
	u16 minor = ufs_qcom_phy->host_ctrl_rev_minor;
	u16 step = ufs_qcom_phy->host_ctrl_rev_step;
@@ -33,6 +34,7 @@ int ufs_qcom_phy_qmp_20nm_phy_calibrate(struct ufs_qcom_phy *ufs_qcom_phy,

	tbl_size_B = ARRAY_SIZE(phy_cal_table_rate_B);
	tbl_B = phy_cal_table_rate_B;
	is_rate_B = (ufs_qcom_phy->mode == PHY_MODE_UFS_HS_B) ? true : false;

	err = ufs_qcom_phy_calibrate(ufs_qcom_phy, tbl_A, tbl_size_A,
						tbl_B, tbl_size_B, is_rate_B);
@@ -156,11 +158,11 @@ static const struct phy_ops ufs_qcom_phy_qmp_20nm_phy_ops = {
	.power_on	= ufs_qcom_phy_power_on,
	.power_off	= ufs_qcom_phy_power_off,
	.set_mode	= ufs_qcom_phy_qmp_20nm_set_mode,
	.calibrate	= ufs_qcom_phy_qmp_20nm_phy_calibrate,
	.owner		= THIS_MODULE,
};

static struct ufs_qcom_phy_specific_ops phy_20nm_ops = {
	.calibrate		= ufs_qcom_phy_qmp_20nm_phy_calibrate,
	.start_serdes		= ufs_qcom_phy_qmp_20nm_start_serdes,
	.is_physical_coding_sublayer_ready = ufs_qcom_phy_qmp_20nm_is_pcs_ready,
	.set_tx_lane_enable	= ufs_qcom_phy_qmp_20nm_set_tx_lane_enable,
+37 −6
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2019, Linux Foundation. All rights reserved.
 * Copyright (c) 2019-2020, Linux Foundation. All rights reserved.
 */

#include "phy-qcom-ufs-qmp-v4-lahaina.h"

#define UFS_PHY_NAME "ufs_phy_qmp_v4_lahaina"

static
int ufs_qcom_phy_qmp_v4_phy_calibrate(struct ufs_qcom_phy *ufs_qcom_phy,
					bool is_rate_B, bool is_g4)
static inline void ufs_qcom_phy_qmp_v4_start_serdes(struct ufs_qcom_phy *phy);
static int ufs_qcom_phy_qmp_v4_is_pcs_ready(struct ufs_qcom_phy *phy_common);

static int ufs_qcom_phy_qmp_v4_phy_calibrate(struct phy *generic_phy)
{
	struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(generic_phy);
	struct device *dev = ufs_qcom_phy->dev;
	bool is_g4, is_rate_B;
	int err;

	err = reset_control_assert(ufs_qcom_phy->ufs_reset);
	if (err) {
		dev_err(dev, "Failed to assert UFS PHY reset %d\n", err);
		goto out;
	}

	/* For UFS PHY's submode, 1 = G4, 0 = non-G4 */
	is_g4 = !!ufs_qcom_phy->submode;
	is_rate_B = (ufs_qcom_phy->mode == PHY_MODE_UFS_HS_B) ? true : false;

	writel_relaxed(0x01, ufs_qcom_phy->mmio + UFS_PHY_SW_RESET);
	/* Ensure PHY is in reset before writing PHY calibration data */
	wmb();
@@ -43,7 +59,18 @@ int ufs_qcom_phy_qmp_v4_phy_calibrate(struct ufs_qcom_phy *ufs_qcom_phy,
	/* flush buffered writes */
	wmb();

	return 0;
	err = reset_control_deassert(ufs_qcom_phy->ufs_reset);
	if (err) {
		dev_err(dev, "Failed to deassert UFS PHY reset %d\n", err);
		goto out;
	}

	ufs_qcom_phy_qmp_v4_start_serdes(ufs_qcom_phy);

	err = ufs_qcom_phy_qmp_v4_is_pcs_ready(ufs_qcom_phy);

out:
	return err;
}

static int ufs_qcom_phy_qmp_v4_init(struct phy *generic_phy)
@@ -66,6 +93,9 @@ static int ufs_qcom_phy_qmp_v4_init(struct phy *generic_phy)
		goto out;
	}

	/* Optional */
	ufs_qcom_phy_get_reset(phy_common);

out:
	return err;
}
@@ -200,6 +230,7 @@ static int ufs_qcom_phy_qmp_v4_is_pcs_ready(struct ufs_qcom_phy *phy_common)
	return err;
}


static void ufs_qcom_phy_qmp_v4_dbg_register_dump(struct ufs_qcom_phy *phy)
{
	ufs_qcom_phy_dump_regs(phy, COM_BASE, COM_SIZE,
@@ -222,11 +253,11 @@ static const struct phy_ops ufs_qcom_phy_qmp_v4_phy_ops = {
	.power_on	= ufs_qcom_phy_power_on,
	.power_off	= ufs_qcom_phy_power_off,
	.set_mode	= ufs_qcom_phy_qmp_v4_set_mode,
	.calibrate	= ufs_qcom_phy_qmp_v4_phy_calibrate,
	.owner		= THIS_MODULE,
};

static struct ufs_qcom_phy_specific_ops phy_v4_ops = {
	.calibrate		= ufs_qcom_phy_qmp_v4_phy_calibrate,
	.start_serdes		= ufs_qcom_phy_qmp_v4_start_serdes,
	.is_physical_coding_sublayer_ready = ufs_qcom_phy_qmp_v4_is_pcs_ready,
	.set_tx_lane_enable	= ufs_qcom_phy_qmp_v4_set_tx_lane_enable,
+14 −4
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2016, 2019, Linux Foundation. All rights reserved.
 * Copyright (c) 2016, 2019-2020, 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
@@ -18,12 +18,13 @@
#define UFS_PHY_NAME "ufs_phy_qrbtc_sdm845"

static
int ufs_qcom_phy_qrbtc_sdm845_phy_calibrate(struct ufs_qcom_phy *ufs_qcom_phy,
					bool is_rate_B, bool is_g4)
int ufs_qcom_phy_qrbtc_sdm845_phy_calibrate(struct phy *generic_phy)
{
	int err;
	int tbl_size_A, tbl_size_B;
	struct ufs_qcom_phy_calibration *tbl_A, *tbl_B;
	struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(generic_phy);
	bool is_rate_B;

	tbl_A = phy_cal_table_rate_A;
	tbl_size_A = ARRAY_SIZE(phy_cal_table_rate_A);
@@ -31,6 +32,8 @@ int ufs_qcom_phy_qrbtc_sdm845_phy_calibrate(struct ufs_qcom_phy *ufs_qcom_phy,
	tbl_size_B = ARRAY_SIZE(phy_cal_table_rate_B);
	tbl_B = phy_cal_table_rate_B;

	is_rate_B = (ufs_qcom_phy->mode == PHY_MODE_UFS_HS_B) ? true : false;

	err = ufs_qcom_phy_calibrate(ufs_qcom_phy,
				     tbl_A, tbl_size_A,
				     tbl_B, tbl_size_B,
@@ -85,6 +88,13 @@ static void ufs_qcom_phy_qrbtc_sdm845_start_serdes(struct ufs_qcom_phy *phy)

static int ufs_qcom_phy_qrbtc_sdm845_init(struct phy *generic_phy)
{
	struct ufs_qcom_phy *phy_common = get_ufs_qcom_phy(generic_phy);
	int ret;

	ret = ufs_qcom_phy_get_reset(phy_common);
	if (ret)
		dev_err(phy_common->dev, "Failed to get reset control\n", ret);

	return 0;
}

@@ -96,11 +106,11 @@ static int ufs_qcom_phy_qrbtc_sdm845_exit(struct phy *generic_phy)
static struct phy_ops ufs_qcom_phy_qrbtc_sdm845_phy_ops = {
	.init		= ufs_qcom_phy_qrbtc_sdm845_init,
	.exit		= ufs_qcom_phy_qrbtc_sdm845_exit,
	.calibrate	= ufs_qcom_phy_qrbtc_sdm845_phy_calibrate,
	.owner		= THIS_MODULE,
};

static struct ufs_qcom_phy_specific_ops phy_qrbtc_sdm845_ops = {
	.calibrate		= ufs_qcom_phy_qrbtc_sdm845_phy_calibrate,
	.start_serdes		= ufs_qcom_phy_qrbtc_sdm845_start_serdes,
	.is_physical_coding_sublayer_ready =
				ufs_qcom_phy_qrbtc_sdm845_is_pcs_ready,
Loading