diff --git a/drivers/scsi/ufs/ufs-msm-phy-qmp-20nm.c b/drivers/scsi/ufs/ufs-msm-phy-qmp-20nm.c index 2b48bac117a0..0bfbcd1bd174 100644 --- a/drivers/scsi/ufs/ufs-msm-phy-qmp-20nm.c +++ b/drivers/scsi/ufs/ufs-msm-phy-qmp-20nm.c @@ -53,6 +53,13 @@ static int ufs_msm_phy_qmp_20nm_phy_calibrate(struct ufs_msm_phy *ufs_msm_phy) return err; } +static +void ufs_msm_phy_qmp_20nm_advertise_quirks(struct ufs_msm_phy *phy_common) +{ + phy_common->quirks = + MSM_UFS_PHY_QUIRK_HIBERN8_EXIT_AFTER_PHY_PWR_COLLAPSE; +} + static int ufs_msm_phy_qmp_20nm_init(struct phy *generic_phy) { struct ufs_msm_phy_qmp_20nm *phy = phy_get_drvdata(generic_phy); @@ -67,9 +74,13 @@ static int ufs_msm_phy_qmp_20nm_init(struct phy *generic_phy) } err = ufs_msm_phy_init_vregulators(generic_phy, phy_common); - if (err) + if (err) { dev_err(phy_common->dev, "%s: ufs_msm_phy_init_vregulators() failed %d\n", __func__, err); + goto out; + } + + ufs_msm_phy_qmp_20nm_advertise_quirks(phy_common); out: return err; @@ -158,21 +169,11 @@ static int ufs_msm_phy_qmp_20nm_is_pcs_ready(struct ufs_msm_phy *phy_common) return err; } -static void ufs_msm_phy_qmp_20nm_advertise_quirks(struct phy *generic_phy) -{ - struct ufs_msm_phy_qmp_20nm *phy = phy_get_drvdata(generic_phy); - struct ufs_msm_phy *phy_common = &(phy->common_cfg); - - phy_common->quirks = - MSM_UFS_PHY_QUIRK_HIBERN8_EXIT_AFTER_PHY_PWR_COLLAPSE; -} - struct phy_ops ufs_msm_phy_qmp_20nm_phy_ops = { .init = ufs_msm_phy_qmp_20nm_init, .exit = ufs_msm_phy_exit, .power_on = ufs_msm_phy_power_on, .power_off = ufs_msm_phy_power_off, - .advertise_quirks = ufs_msm_phy_qmp_20nm_advertise_quirks, .owner = THIS_MODULE, }; diff --git a/drivers/scsi/ufs/ufs-msm-phy-qmp-28nm.c b/drivers/scsi/ufs/ufs-msm-phy-qmp-28nm.c index 6c82a59c4c9a..fb50cfaff034 100644 --- a/drivers/scsi/ufs/ufs-msm-phy-qmp-28nm.c +++ b/drivers/scsi/ufs/ufs-msm-phy-qmp-28nm.c @@ -75,6 +75,13 @@ void ufs_msm_phy_qmp_28nm_power_control(struct ufs_msm_phy *phy, bool val) } } +static +void ufs_msm_phy_qmp_28nm_advertise_quirks(struct ufs_msm_phy *phy_common) +{ + phy_common->quirks = MSM_UFS_PHY_QUIRK_CFG_RESTORE + | MSM_UFS_PHY_DIS_SIGDET_BEFORE_PWR_COLLAPSE; +} + static int ufs_msm_phy_qmp_28nm_init(struct phy *generic_phy) { struct ufs_msm_phy_qmp_28nm *phy = phy_get_drvdata(generic_phy); @@ -89,9 +96,13 @@ static int ufs_msm_phy_qmp_28nm_init(struct phy *generic_phy) } err = ufs_msm_phy_init_vregulators(generic_phy, phy_common); - if (err) + if (err) { dev_err(phy_common->dev, "%s: ufs_msm_phy_init_vregulators() failed %d\n", __func__, err); + goto out; + } + + ufs_msm_phy_qmp_28nm_advertise_quirks(phy_common); out: return err; @@ -151,6 +162,27 @@ u32 ufs_msm_phy_qmp_28nm_read_attr(struct ufs_msm_phy *phy_common, u32 attr) return l0; } +static void +ufs_msm_phy_qmp_28nm_write_attr(struct ufs_msm_phy *phy_common, + u32 attr, u32 val) +{ + writel_relaxed(attr, phy_common->mmio + UFS_PHY_RMMI_ATTRID); + writel_relaxed(val, phy_common->mmio + UFS_PHY_RMMI_ATTRWRVAL); + /* update attribute for both lanes */ + writel_relaxed((UFS_PHY_RMMI_CFGWR_L0 | UFS_PHY_RMMI_CFGWR_L1), + phy_common->mmio + UFS_PHY_RMMI_ATTR_CTRL); + if (is_mphy_tx_attr(attr)) + writel_relaxed((UFS_PHY_RMMI_TX_CFGUPDT_L0 | + UFS_PHY_RMMI_TX_CFGUPDT_L1), + phy_common->mmio + UFS_PHY_RMMI_ATTR_CTRL); + else + writel_relaxed((UFS_PHY_RMMI_RX_CFGUPDT_L0 | + UFS_PHY_RMMI_RX_CFGUPDT_L1), + phy_common->mmio + UFS_PHY_RMMI_ATTR_CTRL); + + writel_relaxed(0x00, phy_common->mmio + UFS_PHY_RMMI_ATTR_CTRL); +} + static void ufs_msm_phy_qmp_28nm_save_configuration(struct ufs_msm_phy *phy_common) { @@ -167,6 +199,16 @@ void ufs_msm_phy_qmp_28nm_save_configuration(struct ufs_msm_phy *phy_common) cached_phy_attr[i].att); } +static +void ufs_msm_phy_qmp_28nm_restore_configuration(struct ufs_msm_phy *phy_common) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(cached_phy_attr); i++) + ufs_msm_phy_qmp_28nm_write_attr(phy_common, + cached_phy_attr[i].att, cached_phy_attr[i].value); +} + static void ufs_msm_phy_qmp_28nm_set_tx_lane_enable(struct ufs_msm_phy *phy, u32 val) { @@ -186,38 +228,6 @@ static inline void ufs_msm_phy_qmp_28nm_start_serdes(struct ufs_msm_phy *phy) mb(); } -static void -ufs_msm_phy_qmp_28nm_write_attr(struct phy *generic_phy, u32 attr, u32 val) -{ - struct ufs_msm_phy_qmp_28nm *phy = phy_get_drvdata(generic_phy); - struct ufs_msm_phy *phy_common = &(phy->common_cfg); - - writel_relaxed(attr, phy_common->mmio + UFS_PHY_RMMI_ATTRID); - writel_relaxed(val, phy_common->mmio + UFS_PHY_RMMI_ATTRWRVAL); - /* update attribute for both lanes */ - writel_relaxed((UFS_PHY_RMMI_CFGWR_L0 | UFS_PHY_RMMI_CFGWR_L1), - phy_common->mmio + UFS_PHY_RMMI_ATTR_CTRL); - if (is_mphy_tx_attr(attr)) - writel_relaxed((UFS_PHY_RMMI_TX_CFGUPDT_L0 | - UFS_PHY_RMMI_TX_CFGUPDT_L1), - phy_common->mmio + UFS_PHY_RMMI_ATTR_CTRL); - else - writel_relaxed((UFS_PHY_RMMI_RX_CFGUPDT_L0 | - UFS_PHY_RMMI_RX_CFGUPDT_L1), - phy_common->mmio + UFS_PHY_RMMI_ATTR_CTRL); - - writel_relaxed(0x00, phy_common->mmio + UFS_PHY_RMMI_ATTR_CTRL); -} - -static void ufs_msm_phy_qmp_28nm_restore_attrs(struct phy *generic_phy) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(cached_phy_attr); i++) - ufs_msm_phy_qmp_28nm_write_attr(generic_phy, - cached_phy_attr[i].att, cached_phy_attr[i].value); -} - static int ufs_msm_phy_qmp_28nm_is_pcs_ready(struct ufs_msm_phy *phy_common) { int err = 0; @@ -232,55 +242,11 @@ static int ufs_msm_phy_qmp_28nm_is_pcs_ready(struct ufs_msm_phy *phy_common) return err; } -static void ufs_msm_phy_qmp_28nm_advertise_quirks(struct phy *generic_phy) -{ - struct ufs_msm_phy_qmp_28nm *phy = phy_get_drvdata(generic_phy); - struct ufs_msm_phy *phy_common = &(phy->common_cfg); - - phy_common->quirks = MSM_UFS_PHY_QUIRK_CFG_RESTORE - | MSM_UFS_PHY_DIS_SIGDET_BEFORE_PWR_COLLAPSE; -} - -static int ufs_msm_phy_qmp_28nm_suspend(struct phy *generic_phy) -{ - struct ufs_msm_phy_qmp_28nm *phy = phy_get_drvdata(generic_phy); - struct ufs_msm_phy *phy_common = &(phy->common_cfg); - - ufs_msm_phy_disable_ref_clk(generic_phy); - ufs_msm_phy_qmp_28nm_power_control(phy_common, false); - - ufs_msm_phy_disable_vreg(generic_phy, &phy_common->vdda_phy); - ufs_msm_phy_disable_vreg(generic_phy, &phy_common->vdda_pll); - - return 0; -} - -static int ufs_msm_phy_qmp_28nm_resume(struct phy *generic_phy) -{ - struct ufs_msm_phy_qmp_28nm *phy = phy_get_drvdata(generic_phy); - struct ufs_msm_phy *phy_common = &phy->common_cfg; - int err = 0; - - ufs_msm_phy_qmp_28nm_start_serdes(phy_common); - - ufs_msm_phy_qmp_28nm_restore_attrs(generic_phy); - - err = ufs_msm_phy_qmp_28nm_is_pcs_ready(phy_common); - if (err) - dev_err(phy_common->dev, "%s: failed to init phy = %d\n", - __func__, err); - - return err; -} - 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, .power_off = ufs_msm_phy_power_off, - .advertise_quirks = ufs_msm_phy_qmp_28nm_advertise_quirks, - .suspend = ufs_msm_phy_qmp_28nm_suspend, - .resume = ufs_msm_phy_qmp_28nm_resume, .owner = THIS_MODULE, }; @@ -288,6 +254,7 @@ struct ufs_msm_phy_specific_ops phy_28nm_ops = { .calibrate_phy = ufs_msm_phy_qmp_28nm_calibrate, .start_serdes = ufs_msm_phy_qmp_28nm_start_serdes, .save_configuration = ufs_msm_phy_qmp_28nm_save_configuration, + .restore_configuration = ufs_msm_phy_qmp_28nm_restore_configuration, .is_physical_coding_sublayer_ready = ufs_msm_phy_qmp_28nm_is_pcs_ready, .set_tx_lane_enable = ufs_msm_phy_qmp_28nm_set_tx_lane_enable, .power_control = ufs_msm_phy_qmp_28nm_power_control, diff --git a/drivers/scsi/ufs/ufs-msm-phy.c b/drivers/scsi/ufs/ufs-msm-phy.c index 045d87f7a16e..4d18f79c17ee 100644 --- a/drivers/scsi/ufs/ufs-msm-phy.c +++ b/drivers/scsi/ufs/ufs-msm-phy.c @@ -589,6 +589,22 @@ int ufs_msm_phy_save_configuration(struct phy *generic_phy) return ret; } +int ufs_msm_phy_restore_configuration(struct phy *generic_phy) +{ + struct ufs_msm_phy *ufs_msm_phy = get_ufs_msm_phy(generic_phy); + int ret = 0; + + if (!ufs_msm_phy->phy_spec_ops->restore_configuration) { + dev_err(ufs_msm_phy->dev, "%s: restore_configuration() callback is not supported\n", + __func__); + ret = -ENOTSUPP; + } else { + ufs_msm_phy->phy_spec_ops->restore_configuration(ufs_msm_phy); + } + + return ret; +} + int ufs_msm_phy_power_on(struct phy *generic_phy) { struct ufs_msm_phy *phy_common = get_ufs_msm_phy(generic_phy); diff --git a/drivers/scsi/ufs/ufs-msm-phy.h b/drivers/scsi/ufs/ufs-msm-phy.h index e6f2b92539f6..c6f556ebe81d 100644 --- a/drivers/scsi/ufs/ufs-msm-phy.h +++ b/drivers/scsi/ufs/ufs-msm-phy.h @@ -142,6 +142,7 @@ struct ufs_msm_phy_specific_ops { int (*calibrate_phy) (struct ufs_msm_phy *phy); void (*start_serdes) (struct ufs_msm_phy *phy); void (*save_configuration)(struct ufs_msm_phy *phy); + void (*restore_configuration)(struct ufs_msm_phy *phy); int (*is_physical_coding_sublayer_ready) (struct ufs_msm_phy *phy); void (*set_tx_lane_enable) (struct ufs_msm_phy *phy, u32 val); void (*power_control) (struct ufs_msm_phy *phy, bool val); @@ -171,6 +172,7 @@ int ufs_msm_phy_set_tx_lane_enable(struct phy *generic_phy, u32 tx_lanes); int ufs_msm_phy_calibrate_phy(struct phy *generic_phy); int ufs_msm_phy_is_pcs_ready(struct phy *generic_phy); int ufs_msm_phy_save_configuration(struct phy *generic_phy); +int ufs_msm_phy_restore_configuration(struct phy *generic_phy); void ufs_msm_phy_save_controller_version(struct phy *generic_phy, u8 major, u16 minor, u16 step); int ufs_msm_phy_power_on(struct phy *generic_phy); diff --git a/drivers/scsi/ufs/ufs-msm.c b/drivers/scsi/ufs/ufs-msm.c index 425b002b07a0..1ce763e6867d 100644 --- a/drivers/scsi/ufs/ufs-msm.c +++ b/drivers/scsi/ufs/ufs-msm.c @@ -242,7 +242,8 @@ static int ufs_msm_power_up_sequence(struct ufs_hba *hba) * voltage, current to settle down before starting serdes. */ usleep_range(1000, 1100); - if (ufs_msm_phy_start_serdes(phy)) { + ret = ufs_msm_phy_start_serdes(phy); + if (ret) { dev_err(hba->dev, "%s: ufs_msm_phy_start_serdes() failed, ret = %d\n", __func__, ret); goto out; @@ -497,7 +498,26 @@ static int ufs_msm_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op) */ usleep_range(1000, 1100); - err = phy_resume(host->generic_phy); + err = ufs_msm_phy_start_serdes(phy); + if (err) { + dev_err(hba->dev, "%s: ufs_msm_phy_start_serdes() failed, err = %d\n", + __func__, err); + goto out; + } + + err = ufs_msm_phy_restore_configuration(phy); + if (err) { + dev_err(hba->dev, "%s: ufs_msm_phy_restore_configuration() failed, err = %d\n", + __func__, err); + goto out; + } + + err = ufs_msm_phy_is_pcs_ready(phy); + if (err) { + dev_err(hba->dev, "%s: is_physical_coding_sublayer_ready() failed, err = %d\n", + __func__, err); + goto out; + } } hba->is_sys_suspended = false; @@ -787,7 +807,6 @@ out: */ static void ufs_msm_advertise_quirks(struct ufs_hba *hba) { - struct ufs_msm_host *host = hba->priv; u8 major; u16 minor, step; @@ -802,8 +821,6 @@ static void ufs_msm_advertise_quirks(struct ufs_hba *hba) hba->quirks |= (UFSHCD_QUIRK_DELAY_BEFORE_DME_CMDS | UFSHCD_QUIRK_BROKEN_PA_RXHSUNTERMCAP | UFSHCD_QUIRK_BROKEN_LCC); - - phy_advertise_quirks(host->generic_phy); } static int ufs_msm_get_bus_vote(struct ufs_msm_host *host,