ufs: qcom: add dts property to disable LPM modes

Since msmcobalt RUMI uses QRBTC-V2 UFS PHY, there are a few limitations
that must be applied in order to be able to initialize UFS:
1. UFS should remain in PWM-G1 1-Lane and never change its gear, as other
gears are not stable
2. hibern8 enter/exit should be bypassed
3. we should avoid any power change (as in runtime suspend/resume)

Add "qcom,disable-lpm" property to facilitate disabling of these.

Change-Id: I3f1801da1e2bf1ce8ce98f5ab08211683106ae8c
Signed-off-by: Yaniv Gardi <ygardi@codeaurora.org>
Signed-off-by: Gilad Broner <gbroner@codeaurora.org>
This commit is contained in:
Gilad Broner 2016-02-28 15:24:56 +02:00 committed by David Keitel
parent 3564520a5e
commit 9fbeb1c910
5 changed files with 50 additions and 7 deletions

View file

@ -28,6 +28,8 @@ Optional properties:
- vddp-ref-clk-supply : phandle to UFS device ref_clk pad power supply
- vddp-ref-clk-max-microamp : specifies max. load that can be drawn from this supply
- vddp-ref-clk-always-on : specifies if this supply needs to be kept always on
- 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)
Example:

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2015, Linux Foundation. All rights reserved.
* Copyright (c) 2013-2016, Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@ -612,6 +612,14 @@ int ufs_qcom_phy_calibrate_phy(struct phy *generic_phy, bool is_rate_B)
}
EXPORT_SYMBOL_GPL(ufs_qcom_phy_calibrate_phy);
const char *ufs_qcom_phy_name(struct phy *phy)
{
struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(phy);
return ufs_qcom_phy->name;
}
EXPORT_SYMBOL(ufs_qcom_phy_name);
int ufs_qcom_phy_remove(struct phy *generic_phy,
struct ufs_qcom_phy *ufs_qcom_phy)
{

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2015, Linux Foundation. All rights reserved.
* Copyright (c) 2013-2016, Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@ -1122,6 +1122,18 @@ static int ufs_qcom_pwr_change_notify(struct ufs_hba *hba,
ufs_qcom_cap.hs_rx_gear = UFS_HS_G2;
}
/*
* Platforms using QRBTCv2 phy must limit link to PWM Gear-1
* and SLOW mode to successfully bring up the link.
*/
if (!strcmp(ufs_qcom_phy_name(phy), "ufs_phy_qrbtc_v2")) {
ufs_qcom_cap.tx_lanes = 1;
ufs_qcom_cap.rx_lanes = 1;
ufs_qcom_cap.pwm_rx_gear = UFS_PWM_G1;
ufs_qcom_cap.pwm_tx_gear = UFS_PWM_G1;
ufs_qcom_cap.desired_working_mode = SLOW;
}
ret = ufs_qcom_get_pwr_dev_param(&ufs_qcom_cap,
dev_max_params,
dev_req_params);
@ -1253,12 +1265,16 @@ static void ufs_qcom_set_caps(struct ufs_hba *hba)
{
struct ufs_qcom_host *host = ufshcd_get_variant(hba);
hba->caps |= UFSHCD_CAP_CLK_GATING | UFSHCD_CAP_HIBERN8_WITH_CLK_GATING;
hba->caps |= UFSHCD_CAP_CLK_SCALING;
if (!host->disable_lpm) {
hba->caps |= UFSHCD_CAP_CLK_GATING;
hba->caps |= UFSHCD_CAP_HIBERN8_WITH_CLK_GATING;
hba->caps |= UFSHCD_CAP_CLK_SCALING;
}
hba->caps |= UFSHCD_CAP_AUTO_BKOPS_SUSPEND;
if (host->hw_ver.major >= 0x2) {
hba->caps |= UFSHCD_CAP_POWER_COLLAPSE_DURING_HIBERN8;
if (!host->disable_lpm)
hba->caps |= UFSHCD_CAP_POWER_COLLAPSE_DURING_HIBERN8;
host->caps = UFS_QCOM_CAP_QUNIPRO |
UFS_QCOM_CAP_RETAIN_SEC_CFG_AFTER_PWR_COLLAPSE;
}
@ -1735,6 +1751,18 @@ static int __init get_android_boot_dev(char *str)
__setup("androidboot.bootdevice=", get_android_boot_dev);
#endif
/*
* ufs_qcom_parse_lpm - read from DTS whether LPM modes should be disabled.
*/
static void ufs_qcom_parse_lpm(struct ufs_qcom_host *host)
{
struct device_node *node = host->hba->dev->of_node;
host->disable_lpm = of_property_read_bool(node, "qcom,disable-lpm");
if (host->disable_lpm)
pr_info("%s: will disable all LPM modes\n", __func__);
}
/**
* ufs_qcom_init - bind phy with controller
* @hba: host controller instance
@ -1866,6 +1894,9 @@ static int ufs_qcom_init(struct ufs_hba *hba)
if (err)
goto out_disable_phy;
ufs_qcom_parse_lpm(host);
if (host->disable_lpm)
pm_runtime_forbid(host->hba->dev);
ufs_qcom_set_caps(hba);
ufs_qcom_advertise_quirks(hba);

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@ -323,6 +323,7 @@ struct ufs_qcom_host {
/* PM Quality-of-Service (QoS) data */
struct ufs_qcom_pm_qos pm_qos;
bool disable_lpm;
bool is_lane_clks_enabled;
bool sec_cfg_updated;
struct ufs_qcom_ice_data ice;

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013-2015, Linux Foundation. All rights reserved.
* Copyright (c) 2013-2016, Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@ -56,5 +56,6 @@ int ufs_qcom_phy_calibrate_phy(struct phy *phy, bool is_rate_B);
int ufs_qcom_phy_is_pcs_ready(struct phy *phy);
void ufs_qcom_phy_save_controller_version(struct phy *phy,
u8 major, u16 minor, u16 step);
const char *ufs_qcom_phy_name(struct phy *phy);
#endif /* PHY_QCOM_UFS_H_ */