summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYaniv Gardi <ygardi@codeaurora.org>2014-07-16 23:46:05 +0300
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-22 10:57:04 -0700
commitf6ffbc88ef91064ee86f742a5bebc42d2ed8e6f8 (patch)
treec37ca30e88a35a2caec8a7aa0bd7ae8c45b95cce
parentb06e5004fbe1edf5393f72fc8826465c0078c7ef (diff)
scsi: ufs: remove code duplication from ufs specific phy
In this change, code that is duplicated in specific ufs msm PHYs modules is removed, and helper functions that contain the common code are added to ufs-msm-phy.c. Change-Id: I30ca8b4d4b452450a155671da94f03d7b965160a Signed-off-by: Yaniv Gardi <ygardi@codeaurora.org> [subhashj@codeaurora.org: fixed compilation errors] Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org>
-rw-r--r--drivers/scsi/ufs/ufs-msm-phy-qmp-20nm.c77
-rw-r--r--drivers/scsi/ufs/ufs-msm-phy-qmp-28nm.c76
-rw-r--r--drivers/scsi/ufs/ufs-msm-phy.c87
-rw-r--r--drivers/scsi/ufs/ufs-msm-phy.h10
4 files changed, 146 insertions, 104 deletions
diff --git a/drivers/scsi/ufs/ufs-msm-phy-qmp-20nm.c b/drivers/scsi/ufs/ufs-msm-phy-qmp-20nm.c
index beb75d350e52..1e72dcc61ac9 100644
--- a/drivers/scsi/ufs/ufs-msm-phy-qmp-20nm.c
+++ b/drivers/scsi/ufs/ufs-msm-phy-qmp-20nm.c
@@ -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;
-
- tbl_size = ARRAY_SIZE(phy_cal_table_rate_A);
- tbl = 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);
-
- 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++)
- writel_relaxed(tbl[i].cfg_value,
- phy->mmio + tbl[i].reg_offset);
- }
+ 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;
- /* flush buffered writes */
- mb();
+ tbl_size_A = ARRAY_SIZE(phy_cal_table_rate_A);
+ tbl_A = phy_cal_table_rate_A;
+
+ tbl_size_B = ARRAY_SIZE(phy_cal_table_rate_B);
+ tbl_B = phy_cal_table_rate_B;
+
+ 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);
+
+ 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,35 +192,20 @@ 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, NULL, &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,
- sizeof(phy->common_cfg.name));
+ sizeof(phy->common_cfg.name));
out:
return err;
diff --git a/drivers/scsi/ufs/ufs-msm-phy-qmp-28nm.c b/drivers/scsi/ufs/ufs-msm-phy-qmp-28nm.c
index 0612e5523f1b..a75a6ca8fc2a 100644
--- a/drivers/scsi/ufs/ufs-msm-phy-qmp-28nm.c
+++ b/drivers/scsi/ufs/ufs-msm-phy-qmp-28nm.c
@@ -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);
-
- for (i = 0; i < tbl_size; i++)
- writel_relaxed(tbl[i].cfg_value,
- ufs_msm_phy->mmio + tbl[i].reg_offset);
- }
+ tbl_B = phy_cal_table_rate_B;
+ tbl_size_B = ARRAY_SIZE(phy_cal_table_rate_B);
- /* flush buffered writes */
- mb();
+ 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);
+
+ 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, NULL, &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;
}
diff --git a/drivers/scsi/ufs/ufs-msm-phy.c b/drivers/scsi/ufs/ufs-msm-phy.c
index f04b2621e68f..e7c0c7d9fcc1 100644
--- a/drivers/scsi/ufs/ufs-msm-phy.c
+++ b/drivers/scsi/ufs/ufs-msm-phy.c
@@ -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, NULL, 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->
- calibrate_phy(ufs_msm_phy);
+ 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;
diff --git a/drivers/scsi/ufs/ufs-msm-phy.h b/drivers/scsi/ufs/ufs-msm-phy.h
index 5edd9d2260a3..90eac935c161 100644
--- a/drivers/scsi/ufs/ufs-msm-phy.h
+++ b/drivers/scsi/ufs/ufs-msm-phy.h
@@ -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