Re: [PATCH v9 8/8] scsi: ufs-qcom: add QUniPro hardware support and power optimizations

2015-10-30 Thread Hannes Reinecke
On 10/28/2015 12:15 PM, Yaniv Gardi wrote:
> New revisions of UFS host controller supports the new UniPro
> hardware controller (referred as QUniPro). This patch adds
> the support to enable this new UniPro controller hardware.
> 
> This change also adds power optimization for bus scaling feature,
> as well as support for HS-G3 power mode.
> 
> Reviewed-by: Subhash Jadavani 
> Reviewed-by: Gilad Broner 
> Signed-off-by: Yaniv Gardi 
> 
Reviewed-by: Hannes Reinecke 

Cheers,

Hannes
-- 
Dr. Hannes Reinecke   zSeries & Storage
h...@suse.de  +49 911 74053 688
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: J. Hawn, J. Guild, F. Imendörffer, HRB 16746 (AG Nürnberg)
--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v9 8/8] scsi: ufs-qcom: add QUniPro hardware support and power optimizations

2015-10-28 Thread Yaniv Gardi
New revisions of UFS host controller supports the new UniPro
hardware controller (referred as QUniPro). This patch adds
the support to enable this new UniPro controller hardware.

This change also adds power optimization for bus scaling feature,
as well as support for HS-G3 power mode.

Reviewed-by: Subhash Jadavani 
Reviewed-by: Gilad Broner 
Signed-off-by: Yaniv Gardi 

---
 drivers/scsi/ufs/ufs-qcom.c | 640 
 drivers/scsi/ufs/ufs-qcom.h |  31 ++-
 drivers/scsi/ufs/ufshcd.c   |   8 +-
 drivers/scsi/ufs/ufshcd.h   |  27 +-
 4 files changed, 525 insertions(+), 181 deletions(-)

diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
index 1633808..4f38d00 100644
--- a/drivers/scsi/ufs/ufs-qcom.c
+++ b/drivers/scsi/ufs/ufs-qcom.c
@@ -44,11 +44,11 @@ enum {
 
 static struct ufs_qcom_host *ufs_qcom_hosts[MAX_UFS_QCOM_HOSTS];
 
-static void ufs_qcom_get_speed_mode(struct ufs_pa_layer_attr *p, char *result);
-static int ufs_qcom_get_bus_vote(struct ufs_qcom_host *host,
-   const char *speed_mode);
 static int ufs_qcom_set_bus_vote(struct ufs_qcom_host *host, int vote);
 static void ufs_qcom_get_default_testbus_cfg(struct ufs_qcom_host *host);
+static int ufs_qcom_set_dme_vs_core_clk_ctrl_clear_div(struct ufs_hba *hba,
+  u32 clk_cycles);
+
 static void ufs_qcom_dump_regs(struct ufs_hba *hba, int offset, int len,
char *prefix)
 {
@@ -177,6 +177,7 @@ static int ufs_qcom_init_lane_clks(struct ufs_qcom_host 
*host)
 
err = ufs_qcom_host_clk_get(dev, "tx_lane1_sync_clk",
>tx_l1_sync_clk);
+
 out:
return err;
 }
@@ -209,7 +210,9 @@ static int ufs_qcom_check_hibern8(struct ufs_hba *hba)
 
do {
err = ufshcd_dme_get(hba,
-   UIC_ARG_MIB(MPHY_TX_FSM_STATE), _fsm_val);
+   UIC_ARG_MIB_SEL(MPHY_TX_FSM_STATE,
+   UIC_ARG_MPHY_TX_GEN_SEL_INDEX(0)),
+   _fsm_val);
if (err || tx_fsm_val == TX_FSM_HIBERN8)
break;
 
@@ -223,7 +226,9 @@ static int ufs_qcom_check_hibern8(struct ufs_hba *hba)
 */
if (time_after(jiffies, timeout))
err = ufshcd_dme_get(hba,
-   UIC_ARG_MIB(MPHY_TX_FSM_STATE), _fsm_val);
+   UIC_ARG_MIB_SEL(MPHY_TX_FSM_STATE,
+   UIC_ARG_MPHY_TX_GEN_SEL_INDEX(0)),
+   _fsm_val);
 
if (err) {
dev_err(hba->dev, "%s: unable to get TX_FSM_STATE, err %d\n",
@@ -237,6 +242,15 @@ static int ufs_qcom_check_hibern8(struct ufs_hba *hba)
return err;
 }
 
+static void ufs_qcom_select_unipro_mode(struct ufs_qcom_host *host)
+{
+   ufshcd_rmwl(host->hba, QUNIPRO_SEL,
+  ufs_qcom_cap_qunipro(host) ? QUNIPRO_SEL : 0,
+  REG_UFS_CFG1);
+   /* make sure above configuration is applied before we return */
+   mb();
+}
+
 static int ufs_qcom_power_up_sequence(struct ufs_hba *hba)
 {
struct ufs_qcom_host *host = ufshcd_get_variant(hba);
@@ -251,9 +265,11 @@ static int ufs_qcom_power_up_sequence(struct ufs_hba *hba)
usleep_range(1000, 1100);
 
ret = ufs_qcom_phy_calibrate_phy(phy, is_rate_B);
+
if (ret) {
-   dev_err(hba->dev, "%s: ufs_qcom_phy_calibrate_phy() failed, ret 
= %d\n",
-   __func__, ret);
+   dev_err(hba->dev,
+   "%s: ufs_qcom_phy_calibrate_phy()failed, ret = %d\n",
+   __func__, ret);
goto out;
}
 
@@ -274,9 +290,12 @@ static int ufs_qcom_power_up_sequence(struct ufs_hba *hba)
 
ret = ufs_qcom_phy_is_pcs_ready(phy);
if (ret)
-   dev_err(hba->dev, "%s: is_physical_coding_sublayer_ready() 
failed, ret = %d\n",
+   dev_err(hba->dev,
+   "%s: is_physical_coding_sublayer_ready() failed, ret = 
%d\n",
__func__, ret);
 
+   ufs_qcom_select_unipro_mode(host);
+
 out:
return ret;
 }
@@ -299,7 +318,8 @@ static void ufs_qcom_enable_hw_clk_gating(struct ufs_hba 
*hba)
mb();
 }
 
-static int ufs_qcom_hce_enable_notify(struct ufs_hba *hba, bool status)
+static int ufs_qcom_hce_enable_notify(struct ufs_hba *hba,
+ enum ufs_notify_change_status status)
 {
struct ufs_qcom_host *host = ufshcd_get_variant(hba);
int err = 0;
@@ -329,12 +349,12 @@ static int ufs_qcom_hce_enable_notify(struct ufs_hba 
*hba, bool status)
 }
 
 /**
- * Returns non-zero for success (which rate of core_clk) and 0
- * in case of a failure
+ * Returns zero for success and non-zero in case of a failure
  */
-static unsigned long
-ufs_qcom_cfg_timers(struct