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

Commit 408666b7 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "scsi: ufs: remove code duplication from ufs specific phy"

parents f94eb0d5 faff8cbf
Loading
Loading
Loading
Loading
+26 −51
Original line number Diff line number Diff line
@@ -30,36 +30,27 @@

#define UFS_PHY_NAME "ufs_msm_phy_qmp_20nm"

static void ufs_msm_phy_qmp_20nm_phy_calibrate(struct ufs_msm_phy *phy)
static int ufs_msm_phy_qmp_20nm_phy_calibrate(struct ufs_msm_phy *ufs_msm_phy)
{
	struct ufs_msm_phy_calibration *tbl;
	int tbl_size;
	int i;
	struct ufs_msm_phy_calibration *tbl_A, *tbl_B;
	int tbl_size_A, tbl_size_B;
	int rate = UFS_MSM_LIMIT_HS_RATE;
	int err;

	tbl_size = ARRAY_SIZE(phy_cal_table_rate_A);
	tbl = phy_cal_table_rate_A;
	tbl_size_A = ARRAY_SIZE(phy_cal_table_rate_A);
	tbl_A = phy_cal_table_rate_A;

	/*
	 * calibration according phy_cal_table_rate_A happens
	 * regardless of the rate we intend to work with.
	 * Only in case we would like to work in rate B, we need
	 * to override a subset of registers of phy_cal_table_rate_A
	 * table, with phy_cal_table_rate_B table.
	 */
	for (i = 0; i < tbl_size; i++)
		writel_relaxed(tbl[i].cfg_value, phy->mmio + tbl[i].reg_offset);
	tbl_size_B = ARRAY_SIZE(phy_cal_table_rate_B);
	tbl_B = phy_cal_table_rate_B;

	if (UFS_MSM_LIMIT_HS_RATE == PA_HS_MODE_B) {
		tbl = phy_cal_table_rate_B;
		tbl_size = ARRAY_SIZE(phy_cal_table_rate_B);
	err = ufs_msm_phy_calibrate(ufs_msm_phy, tbl_A, tbl_size_A,
						tbl_B, tbl_size_B, rate);

		for (i = 0; i < tbl_size; i++)
			writel_relaxed(tbl[i].cfg_value,
					phy->mmio + tbl[i].reg_offset);
	}
	if (err)
		dev_err(ufs_msm_phy->dev, "%s: ufs_msm_phy_calibrate() failed %d\n",
			__func__, err);

	/* flush buffered writes */
	mb();
	return err;
}

static int ufs_msm_phy_qmp_20nm_init(struct phy *generic_phy)
@@ -192,7 +183,6 @@ static int ufs_msm_phy_qmp_20nm_probe(struct platform_device *pdev)
	struct device *dev = &pdev->dev;
	struct phy *generic_phy;
	struct ufs_msm_phy_qmp_20nm *phy;
	struct phy_provider *phy_provider;
	int err = 0;

	phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
@@ -202,31 +192,16 @@ static int ufs_msm_phy_qmp_20nm_probe(struct platform_device *pdev)
		goto out;
	}

	err = ufs_msm_phy_base_init(pdev, &phy->common_cfg);
	if (err) {
		dev_err(dev, "%s: phy base init failed %d\n", __func__, err);
		goto out;
	}

	phy->common_cfg.phy_spec_ops = &phy_20nm_ops;
	phy->common_cfg.cached_regs = NULL;

	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
	if (IS_ERR(phy_provider)) {
		err = PTR_ERR(phy_provider);
		dev_err(dev, "%s: failed to register phy %d\n", __func__, err);
		goto out;
	}
	generic_phy = ufs_msm_phy_generic_probe(pdev, &phy->common_cfg,
				&ufs_msm_phy_qmp_20nm_phy_ops, &phy_20nm_ops);

	generic_phy = devm_phy_create(dev, &ufs_msm_phy_qmp_20nm_phy_ops, NULL);
	if (IS_ERR(generic_phy)) {
		devm_of_phy_provider_unregister(dev, phy_provider);
		err =  PTR_ERR(generic_phy);
		dev_err(dev, "%s: failed to create phy %d\n", __func__, err);
	if (!generic_phy) {
		dev_err(dev, "%s: ufs_msm_phy_generic_probe() failed\n",
			__func__);
		err = -EIO;
		goto out;
	}

	phy->common_cfg.dev = dev;
	phy_set_drvdata(generic_phy, phy);

	strlcpy(phy->common_cfg.name, UFS_PHY_NAME,
+26 −50
Original line number Diff line number Diff line
@@ -97,46 +97,34 @@ out:
	return err;
}

static void ufs_msm_phy_qmp_28nm_calibrate(struct ufs_msm_phy *ufs_msm_phy)
static int ufs_msm_phy_qmp_28nm_calibrate(struct ufs_msm_phy *ufs_msm_phy)
{
	struct ufs_msm_phy_calibration *tbl;
	int tbl_size;
	int i;
	struct ufs_msm_phy_calibration *tbl_A, *tbl_B;
	int tbl_size_A, tbl_size_B;
	int rate = UFS_MSM_LIMIT_HS_RATE;
	u8 major = ufs_msm_phy->host_ctrl_rev_major;
	u16 minor = ufs_msm_phy->host_ctrl_rev_minor;
	u16 step = ufs_msm_phy->host_ctrl_rev_step;
	int err;

	if ((major == 0x1) && (minor == 0x001) && (step == 0x0000)) {
		tbl_size = ARRAY_SIZE(phy_cal_table_ctrl_1_1_0_rate_A);
		tbl = phy_cal_table_ctrl_1_1_0_rate_A;
		tbl_size_A = ARRAY_SIZE(phy_cal_table_ctrl_1_1_0_rate_A);
		tbl_A = phy_cal_table_ctrl_1_1_0_rate_A;
	} else if ((major == 0x1) && (minor == 0x001) && (step == 0x0001)) {
		tbl_size = ARRAY_SIZE(phy_cal_table_ctrl_1_1_1_rate_A);
		tbl = phy_cal_table_ctrl_1_1_1_rate_A;
		tbl_size_A = ARRAY_SIZE(phy_cal_table_ctrl_1_1_1_rate_A);
		tbl_A = phy_cal_table_ctrl_1_1_1_rate_A;
	}

	/*
	 * calibration according phy_cal_table_ctrl_x_x_x_rate_A
	 * happens regardless of the rate we intend to work with.
	 * Only in case we would like to work in rate B, we need
	 * to override a subset of registers of
	 * phy_cal_table_ctrl_x_x_x_rate_A table, with phy_cal_table_rate_B
	 * table.
	 */
	for (i = 0; i < tbl_size; i++)
		writel_relaxed(tbl[i].cfg_value,
				ufs_msm_phy->mmio + tbl[i].reg_offset);

	if (UFS_MSM_LIMIT_HS_RATE == PA_HS_MODE_B) {
		tbl = phy_cal_table_rate_B;
		tbl_size = ARRAY_SIZE(phy_cal_table_rate_B);
	tbl_B = phy_cal_table_rate_B;
	tbl_size_B = ARRAY_SIZE(phy_cal_table_rate_B);

		for (i = 0; i < tbl_size; i++)
			writel_relaxed(tbl[i].cfg_value,
				ufs_msm_phy->mmio + tbl[i].reg_offset);
	}
	err = ufs_msm_phy_calibrate(ufs_msm_phy, tbl_A, tbl_size_A,
			      tbl_B, tbl_size_B, rate);
	if (err)
		dev_err(ufs_msm_phy->dev, "%s: ufs_msm_phy_calibrate() failed %d\n",
			__func__, err);

	/* flush buffered writes */
	mb();
	return err;
}

static
@@ -286,7 +274,7 @@ static int ufs_msm_phy_qmp_28nm_resume(struct phy *generic_phy)
	return err;
}

struct phy_ops ufs_msm_phy_ops = {
struct phy_ops ufs_msm_phy_qmp_28nm_phy_ops = {
	.init		= ufs_msm_phy_qmp_28nm_init,
	.exit		= ufs_msm_phy_exit,
	.power_on	= ufs_msm_phy_power_on,
@@ -312,7 +300,6 @@ static int ufs_msm_phy_qmp_28nm_probe(struct platform_device *pdev)
	struct device *dev = &pdev->dev;
	int err = 0;
	struct phy *generic_phy;
	struct phy_provider *phy_provider;

	phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
	if (!phy) {
@@ -321,37 +308,26 @@ static int ufs_msm_phy_qmp_28nm_probe(struct platform_device *pdev)
		goto out;
	}

	err = ufs_msm_phy_base_init(pdev, &phy->common_cfg);
	if (err) {
		dev_err(dev, "%s: phy base init failed %d\n", __func__, err);
		goto out;
	}

	phy->common_cfg.phy_spec_ops = &phy_28nm_ops;
	phy->common_cfg.cached_regs =
			(struct ufs_msm_phy_calibration *)cached_phy_regs;
	phy->common_cfg.cached_regs_table_size =
				ARRAY_SIZE(cached_phy_regs);

	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
	if (IS_ERR(phy_provider)) {
		err = PTR_ERR(phy_provider);
		dev_err(dev, "%s: failed to register phy %d\n", __func__, err);
		goto out;
	}
	generic_phy = ufs_msm_phy_generic_probe(pdev, &phy->common_cfg,
				&ufs_msm_phy_qmp_28nm_phy_ops, &phy_28nm_ops);

	generic_phy = devm_phy_create(dev, &ufs_msm_phy_ops, NULL);
	if (IS_ERR(generic_phy)) {
		err =  PTR_ERR(generic_phy);
		dev_err(dev, "%s: failed to create phy %d\n", __func__, err);
	if (!generic_phy) {
		dev_err(dev, "%s: ufs_msm_phy_generic_probe() failed\n",
			__func__);
		err = -EIO;
		goto out;
	}

	phy->common_cfg.dev = dev;
	phy_set_drvdata(generic_phy, phy);

	strlcpy(phy->common_cfg.name, UFS_PHY_NAME,
			sizeof(phy->common_cfg.name));

out:
	return err;
}
+85 −2
Original line number Diff line number Diff line
@@ -27,6 +27,87 @@
#include "ufs-msm.h"
#include "ufs-msm-phy.h"

int ufs_msm_phy_calibrate(struct ufs_msm_phy *ufs_msm_phy,
			struct ufs_msm_phy_calibration *tbl_A, int tbl_size_A,
			struct ufs_msm_phy_calibration *tbl_B, int tbl_size_B,
			int rate)
{
	int i;
	int ret = 0;

	if (!tbl_A) {
		dev_err(ufs_msm_phy->dev, "%s: tbl_A is NULL", __func__);
		ret = EINVAL;
		goto out;
	}

	for (i = 0; i < tbl_size_A; i++)
		writel_relaxed(tbl_A[i].cfg_value,
				ufs_msm_phy->mmio + tbl_A[i].reg_offset);

	/*
	 * In case we would like to work in rate B, we need
	 * to override a registers that were configured in rate A table
	 * with registers of rate B table.
	 * table.
	 */
	if (rate == PA_HS_MODE_B) {
		if (!tbl_B) {
			dev_err(ufs_msm_phy->dev, "%s: tbl_B is NULL",
				__func__);
			ret = EINVAL;
			goto out;
		}

		for (i = 0; i < tbl_size_B; i++)
			writel_relaxed(tbl_B[i].cfg_value,
				ufs_msm_phy->mmio + tbl_B[i].reg_offset);
	}

	/* flush buffered writes */
	mb();

out:
	return ret;
}

struct phy *ufs_msm_phy_generic_probe(struct platform_device *pdev,
			  struct ufs_msm_phy *common_cfg,
			  struct phy_ops *ufs_msm_phy_gen_ops,
			  struct ufs_msm_phy_specific_ops *phy_spec_ops)
{
	int err;
	struct device *dev = &pdev->dev;
	struct phy *generic_phy = NULL;
	struct phy_provider *phy_provider;

	err = ufs_msm_phy_base_init(pdev, common_cfg);
	if (err) {
		dev_err(dev, "%s: phy base init failed %d\n", __func__, err);
		goto out;
	}

	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
	if (IS_ERR(phy_provider)) {
		err = PTR_ERR(phy_provider);
		dev_err(dev, "%s: failed to register phy %d\n", __func__, err);
		goto out;
	}

	generic_phy = devm_phy_create(dev, ufs_msm_phy_gen_ops, NULL);
	if (IS_ERR(generic_phy)) {
		err =  PTR_ERR(generic_phy);
		dev_err(dev, "%s: failed to create phy %d\n", __func__, err);
		goto out;
	}

	common_cfg->phy_spec_ops = phy_spec_ops;
	common_cfg->dev = dev;

out:
	return generic_phy;
}

/*
 * This assumes the embedded phy structure inside generic_phy is of type
 * struct ufs_msm_phy. In order to function properly it's crucial
@@ -447,8 +528,10 @@ int ufs_msm_phy_calibrate_phy(struct phy *generic_phy)
			__func__);
		ret = -ENOTSUPP;
	} else {
		ufs_msm_phy->phy_spec_ops->
		ret = ufs_msm_phy->phy_spec_ops->
				calibrate_phy(ufs_msm_phy);
		dev_err(ufs_msm_phy->dev, "%s: calibrate_phy() failed %d\n",
			__func__, ret);
	}

	return ret;
+9 −1
Original line number Diff line number Diff line
@@ -130,7 +130,7 @@ struct ufs_msm_phy {
 * and writes to QSERDES_RX_SIGDET_CNTRL attribute
 */
struct ufs_msm_phy_specific_ops {
	void (*calibrate_phy) (struct ufs_msm_phy *phy);
	int (*calibrate_phy) (struct ufs_msm_phy *phy);
	void (*start_serdes) (struct ufs_msm_phy *phy);
	void (*save_configuration)(struct ufs_msm_phy *phy);
	int (*is_physical_coding_sublayer_ready) (struct ufs_msm_phy *phy);
@@ -173,4 +173,12 @@ int ufs_msm_phy_init_vregulators(struct phy *generic_phy,
			struct ufs_msm_phy *phy_common);
int ufs_msm_phy_remove(struct phy *generic_phy,
		       struct ufs_msm_phy *ufs_msm_phy);
struct phy *ufs_msm_phy_generic_probe(struct platform_device *pdev,
			struct ufs_msm_phy *common_cfg,
			struct phy_ops *ufs_msm_phy_gen_ops,
			struct ufs_msm_phy_specific_ops *phy_spec_ops);
int ufs_msm_phy_calibrate(struct ufs_msm_phy *ufs_msm_phy,
			struct ufs_msm_phy_calibration *tbl_A, int tbl_size_A,
			struct ufs_msm_phy_calibration *tbl_B, int tbl_size_B,
			int rate);
#endif