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 Original line Diff line number Diff line
@@ -30,36 +30,27 @@


#define UFS_PHY_NAME "ufs_msm_phy_qmp_20nm"
#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;
	struct ufs_msm_phy_calibration *tbl_A, *tbl_B;
	int tbl_size;
	int tbl_size_A, tbl_size_B;
	int i;
	int rate = UFS_MSM_LIMIT_HS_RATE;
	int err;


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


	/*
	tbl_size_B = ARRAY_SIZE(phy_cal_table_rate_B);
	 * calibration according phy_cal_table_rate_A happens
	tbl_B = phy_cal_table_rate_B;
	 * 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);


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


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


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


static int ufs_msm_phy_qmp_20nm_init(struct phy *generic_phy)
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 device *dev = &pdev->dev;
	struct phy *generic_phy;
	struct phy *generic_phy;
	struct ufs_msm_phy_qmp_20nm *phy;
	struct ufs_msm_phy_qmp_20nm *phy;
	struct phy_provider *phy_provider;
	int err = 0;
	int err = 0;


	phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
	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;
		goto out;
	}
	}


	err = ufs_msm_phy_base_init(pdev, &phy->common_cfg);
	generic_phy = ufs_msm_phy_generic_probe(pdev, &phy->common_cfg,
	if (err) {
				&ufs_msm_phy_qmp_20nm_phy_ops, &phy_20nm_ops);
		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 = devm_phy_create(dev, &ufs_msm_phy_qmp_20nm_phy_ops, NULL);
	if (!generic_phy) {
	if (IS_ERR(generic_phy)) {
		dev_err(dev, "%s: ufs_msm_phy_generic_probe() failed\n",
		devm_of_phy_provider_unregister(dev, phy_provider);
			__func__);
		err =  PTR_ERR(generic_phy);
		err = -EIO;
		dev_err(dev, "%s: failed to create phy %d\n", __func__, err);
		goto out;
		goto out;
	}
	}


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


	strlcpy(phy->common_cfg.name, UFS_PHY_NAME,
	strlcpy(phy->common_cfg.name, UFS_PHY_NAME,
+26 −50
Original line number Original line Diff line number Diff line
@@ -97,46 +97,34 @@ out:
	return err;
	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;
	struct ufs_msm_phy_calibration *tbl_A, *tbl_B;
	int tbl_size;
	int tbl_size_A, tbl_size_B;
	int i;
	int rate = UFS_MSM_LIMIT_HS_RATE;
	u8 major = ufs_msm_phy->host_ctrl_rev_major;
	u8 major = ufs_msm_phy->host_ctrl_rev_major;
	u16 minor = ufs_msm_phy->host_ctrl_rev_minor;
	u16 minor = ufs_msm_phy->host_ctrl_rev_minor;
	u16 step = ufs_msm_phy->host_ctrl_rev_step;
	u16 step = ufs_msm_phy->host_ctrl_rev_step;
	int err;


	if ((major == 0x1) && (minor == 0x001) && (step == 0x0000)) {
	if ((major == 0x1) && (minor == 0x001) && (step == 0x0000)) {
		tbl_size = ARRAY_SIZE(phy_cal_table_ctrl_1_1_0_rate_A);
		tbl_size_A = ARRAY_SIZE(phy_cal_table_ctrl_1_1_0_rate_A);
		tbl = 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)) {
	} else if ((major == 0x1) && (minor == 0x001) && (step == 0x0001)) {
		tbl_size = ARRAY_SIZE(phy_cal_table_ctrl_1_1_1_rate_A);
		tbl_size_A = ARRAY_SIZE(phy_cal_table_ctrl_1_1_1_rate_A);
		tbl = phy_cal_table_ctrl_1_1_1_rate_A;
		tbl_A = phy_cal_table_ctrl_1_1_1_rate_A;
	}
	}


	/*
	tbl_B = phy_cal_table_rate_B;
	 * calibration according phy_cal_table_ctrl_x_x_x_rate_A
	tbl_size_B = ARRAY_SIZE(phy_cal_table_rate_B);
	 * 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);


		for (i = 0; i < tbl_size; i++)
	err = ufs_msm_phy_calibrate(ufs_msm_phy, tbl_A, tbl_size_A,
			writel_relaxed(tbl[i].cfg_value,
			      tbl_B, tbl_size_B, rate);
				ufs_msm_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 */
	return err;
	mb();
}
}


static
static
@@ -286,7 +274,7 @@ static int ufs_msm_phy_qmp_28nm_resume(struct phy *generic_phy)
	return err;
	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,
	.init		= ufs_msm_phy_qmp_28nm_init,
	.exit		= ufs_msm_phy_exit,
	.exit		= ufs_msm_phy_exit,
	.power_on	= ufs_msm_phy_power_on,
	.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;
	struct device *dev = &pdev->dev;
	int err = 0;
	int err = 0;
	struct phy *generic_phy;
	struct phy *generic_phy;
	struct phy_provider *phy_provider;


	phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
	phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL);
	if (!phy) {
	if (!phy) {
@@ -321,37 +308,26 @@ static int ufs_msm_phy_qmp_28nm_probe(struct platform_device *pdev)
		goto out;
		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 =
	phy->common_cfg.cached_regs =
			(struct ufs_msm_phy_calibration *)cached_phy_regs;
			(struct ufs_msm_phy_calibration *)cached_phy_regs;
	phy->common_cfg.cached_regs_table_size =
	phy->common_cfg.cached_regs_table_size =
				ARRAY_SIZE(cached_phy_regs);
				ARRAY_SIZE(cached_phy_regs);


	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
	generic_phy = ufs_msm_phy_generic_probe(pdev, &phy->common_cfg,
	if (IS_ERR(phy_provider)) {
				&ufs_msm_phy_qmp_28nm_phy_ops, &phy_28nm_ops);
		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_ops, NULL);
	if (!generic_phy) {
	if (IS_ERR(generic_phy)) {
		dev_err(dev, "%s: ufs_msm_phy_generic_probe() failed\n",
		err =  PTR_ERR(generic_phy);
			__func__);
		dev_err(dev, "%s: failed to create phy %d\n", __func__, err);
		err = -EIO;
		goto out;
		goto out;
	}
	}


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


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

out:
out:
	return err;
	return err;
}
}
+85 −2
Original line number Original line Diff line number Diff line
@@ -27,6 +27,87 @@
#include "ufs-msm.h"
#include "ufs-msm.h"
#include "ufs-msm-phy.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
 * This assumes the embedded phy structure inside generic_phy is of type
 * struct ufs_msm_phy. In order to function properly it's crucial
 * 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__);
			__func__);
		ret = -ENOTSUPP;
		ret = -ENOTSUPP;
	} else {
	} else {
		ufs_msm_phy->phy_spec_ops->
		ret = ufs_msm_phy->phy_spec_ops->
				calibrate_phy(ufs_msm_phy);
				calibrate_phy(ufs_msm_phy);
		dev_err(ufs_msm_phy->dev, "%s: calibrate_phy() failed %d\n",
			__func__, ret);
	}
	}


	return ret;
	return ret;
+9 −1
Original line number Original line Diff line number Diff line
@@ -130,7 +130,7 @@ struct ufs_msm_phy {
 * and writes to QSERDES_RX_SIGDET_CNTRL attribute
 * and writes to QSERDES_RX_SIGDET_CNTRL attribute
 */
 */
struct ufs_msm_phy_specific_ops {
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 (*start_serdes) (struct ufs_msm_phy *phy);
	void (*save_configuration)(struct ufs_msm_phy *phy);
	void (*save_configuration)(struct ufs_msm_phy *phy);
	int (*is_physical_coding_sublayer_ready) (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);
			struct ufs_msm_phy *phy_common);
int ufs_msm_phy_remove(struct phy *generic_phy,
int ufs_msm_phy_remove(struct phy *generic_phy,
		       struct ufs_msm_phy *ufs_msm_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
#endif