Merge "phy: qcom-ufs-qmp-v3: separate out 2 lanes configuration" into msm-4.9
diff --git a/Documentation/devicetree/bindings/ufs/ufs-qcom.txt b/Documentation/devicetree/bindings/ufs/ufs-qcom.txt
index b097889..af754fe 100644
--- a/Documentation/devicetree/bindings/ufs/ufs-qcom.txt
+++ b/Documentation/devicetree/bindings/ufs/ufs-qcom.txt
@@ -30,6 +30,10 @@
- vdda-pll-max-microamp : specifies max. load that can be drawn from pll supply
- qcom,disable-lpm : disable various LPM mechanisms in UFS for platform compatibility
(limit link to PWM Gear-1, 1-lane slow mode; disable hibernate, and avoid suspend/resume)
+- lanes-per-direction: number of lanes available per direction - either 1 or 2.
+ Note that it is assumed that same number of lanes is
+ used both directions at once.
+ If not specified, default is 2 lanes per direction.
Example:
@@ -38,6 +42,7 @@
reg = <0xfc597000 0x800>;
reg-names = "phy_mem";
#phy-cells = <0>;
+ lanes-per-direction = <1>;
vdda-phy-supply = <&pma8084_l4>;
vdda-pll-supply = <&pma8084_l12>;
vdda-phy-max-microamp = <50000>;
diff --git a/drivers/phy/phy-qcom-ufs-i.h b/drivers/phy/phy-qcom-ufs-i.h
index 7acef10..b92bc89 100644
--- a/drivers/phy/phy-qcom-ufs-i.h
+++ b/drivers/phy/phy-qcom-ufs-i.h
@@ -97,6 +97,10 @@ struct ufs_qcom_phy {
struct ufs_qcom_phy_vreg vdda_pll;
struct ufs_qcom_phy_vreg vdda_phy;
struct ufs_qcom_phy_vreg vddp_ref_clk;
+
+ /* Number of lanes available (1 or 2) for Rx/Tx */
+ u32 lanes_per_direction;
+
unsigned int quirks;
/*
diff --git a/drivers/phy/phy-qcom-ufs-qmp-v3.c b/drivers/phy/phy-qcom-ufs-qmp-v3.c
index 46c3ed6..0bfde0c7 100644
--- a/drivers/phy/phy-qcom-ufs-qmp-v3.c
+++ b/drivers/phy/phy-qcom-ufs-qmp-v3.c
@@ -20,27 +20,24 @@ static
int ufs_qcom_phy_qmp_v3_phy_calibrate(struct ufs_qcom_phy *ufs_qcom_phy,
bool is_rate_B)
{
- int err;
- int tbl_size_A, tbl_size_B;
- struct ufs_qcom_phy_calibration *tbl_A, *tbl_B;
+ /*
+ * Writing PHY calibration in this order:
+ * 1. Write Rate-A calibration first (1-lane mode).
+ * 2. Write 2nd lane configuration if needed.
+ * 3. Write Rate-B calibration overrides
+ */
+ ufs_qcom_phy_write_tbl(ufs_qcom_phy, phy_cal_table_rate_A,
+ ARRAY_SIZE(phy_cal_table_rate_A));
+ if (ufs_qcom_phy->lanes_per_direction == 2)
+ ufs_qcom_phy_write_tbl(ufs_qcom_phy, phy_cal_table_2nd_lane,
+ ARRAY_SIZE(phy_cal_table_2nd_lane));
+ if (is_rate_B)
+ ufs_qcom_phy_write_tbl(ufs_qcom_phy, phy_cal_table_rate_B,
+ ARRAY_SIZE(phy_cal_table_rate_B));
+ /* flush buffered writes */
+ mb();
- tbl_size_B = ARRAY_SIZE(phy_cal_table_rate_B);
- tbl_B = phy_cal_table_rate_B;
-
- tbl_A = phy_cal_table_rate_A;
- tbl_size_A = ARRAY_SIZE(phy_cal_table_rate_A);
-
- err = ufs_qcom_phy_calibrate(ufs_qcom_phy,
- tbl_A, tbl_size_A,
- tbl_B, tbl_size_B,
- is_rate_B);
-
- if (err)
- dev_err(ufs_qcom_phy->dev,
- "%s: ufs_qcom_phy_calibrate() failed %d\n",
- __func__, err);
-
- return err;
+ return 0;
}
static int ufs_qcom_phy_qmp_v3_init(struct phy *generic_phy)
diff --git a/drivers/phy/phy-qcom-ufs-qmp-v3.h b/drivers/phy/phy-qcom-ufs-qmp-v3.h
index 7ca9f9b..4851aac 100644
--- a/drivers/phy/phy-qcom-ufs-qmp-v3.h
+++ b/drivers/phy/phy-qcom-ufs-qmp-v3.h
@@ -262,6 +262,16 @@ static struct ufs_qcom_phy_calibration phy_cal_table_rate_A[] = {
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX0_UCDR_SO_SATURATION_AND_ENABLE, 0x4B),
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX0_UCDR_PI_CONTROLS, 0xF1),
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX0_UCDR_FASTLOCK_COUNT_LOW, 0x80),
+ UFS_QCOM_PHY_CAL_ENTRY(UFS_PHY_RX_SIGDET_CTRL2, 0x6C),
+ UFS_QCOM_PHY_CAL_ENTRY(UFS_PHY_TX_LARGE_AMP_DRV_LVL, 0x0A),
+ UFS_QCOM_PHY_CAL_ENTRY(UFS_PHY_TX_SMALL_AMP_DRV_LVL, 0x02),
+ UFS_QCOM_PHY_CAL_ENTRY(UFS_PHY_RX_SYM_RESYNC_CTRL, 0x03),
+ UFS_QCOM_PHY_CAL_ENTRY(UFS_PHY_TX_MID_TERM_CTRL1, 0x43),
+ UFS_QCOM_PHY_CAL_ENTRY(UFS_PHY_RX_SIGDET_CTRL1, 0x0F),
+ UFS_QCOM_PHY_CAL_ENTRY(UFS_PHY_RX_MIN_HIBERN8_TIME, 0x9A), /* 8 us */
+};
+
+static struct ufs_qcom_phy_calibration phy_cal_table_2nd_lane[] = {
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_TX1_LANE_MODE_1, 0x06),
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX1_SIGDET_LVL, 0x24),
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX1_SIGDET_CNTRL, 0x0F),
@@ -279,13 +289,6 @@ static struct ufs_qcom_phy_calibration phy_cal_table_rate_A[] = {
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX1_UCDR_PI_CONTROLS, 0xF1),
UFS_QCOM_PHY_CAL_ENTRY(QSERDES_RX1_UCDR_FASTLOCK_COUNT_LOW, 0x80),
UFS_QCOM_PHY_CAL_ENTRY(UFS_PHY_MULTI_LANE_CTRL1, 0x02),
- UFS_QCOM_PHY_CAL_ENTRY(UFS_PHY_RX_SIGDET_CTRL2, 0x6C),
- UFS_QCOM_PHY_CAL_ENTRY(UFS_PHY_TX_LARGE_AMP_DRV_LVL, 0x0A),
- UFS_QCOM_PHY_CAL_ENTRY(UFS_PHY_TX_SMALL_AMP_DRV_LVL, 0x02),
- UFS_QCOM_PHY_CAL_ENTRY(UFS_PHY_RX_SYM_RESYNC_CTRL, 0x03),
- UFS_QCOM_PHY_CAL_ENTRY(UFS_PHY_TX_MID_TERM_CTRL1, 0x43),
- UFS_QCOM_PHY_CAL_ENTRY(UFS_PHY_RX_SIGDET_CTRL1, 0x0F),
- UFS_QCOM_PHY_CAL_ENTRY(UFS_PHY_RX_MIN_HIBERN8_TIME, 0x9A), /* 8 us */
};
static struct ufs_qcom_phy_calibration phy_cal_table_rate_B[] = {
diff --git a/drivers/phy/phy-qcom-ufs.c b/drivers/phy/phy-qcom-ufs.c
index 95d2ec7..d18929f 100644
--- a/drivers/phy/phy-qcom-ufs.c
+++ b/drivers/phy/phy-qcom-ufs.c
@@ -22,6 +22,8 @@
#define VDDP_REF_CLK_MIN_UV 1200000
#define VDDP_REF_CLK_MAX_UV 1200000
+#define UFS_PHY_DEFAULT_LANES_PER_DIRECTION 1
+
static int __ufs_qcom_phy_init_vreg(struct phy *, struct ufs_qcom_phy_vreg *,
const char *, bool);
static int ufs_qcom_phy_init_vreg(struct phy *, struct ufs_qcom_phy_vreg *,
@@ -113,6 +115,11 @@ struct phy *ufs_qcom_phy_generic_probe(struct platform_device *pdev,
goto out;
}
+ if (of_property_read_u32(dev->of_node, "lanes-per-direction",
+ &common_cfg->lanes_per_direction))
+ common_cfg->lanes_per_direction =
+ UFS_PHY_DEFAULT_LANES_PER_DIRECTION;
+
/*
* UFS PHY power management is managed by its parent (UFS host
* controller) hence set the no the no runtime PM callbacks flag