From: Yaniv Gardi <ygardi@codeaurora.org>
To: James.Bottomley@HansenPartnership.com, pebolle@tiscali.nl,
hch@infradead.org
Cc: linux-kernel@vger.kernel.org, linux-scsi@vger.kernel.org,
linux-arm-msm@vger.kernel.org, santoshsy@gmail.com,
linux-scsi-owner@vger.kernel.org, subhashj@codeaurora.org,
ygardi@codeaurora.org, gbroner@codeaurora.org,
draviv@codeaurora.org, Vinayak Holikatti <vinholikatti@gmail.com>,
"James E.J. Bottomley" <JBottomley@odin.com>
Subject: [PATCH v1 17/17] scsi: ufs-qcom: set PA_Local_TX_LCC_Enable before link startup
Date: Sun, 13 Sep 2015 17:52:57 +0300 [thread overview]
Message-ID: <1442155977-7686-18-git-send-email-ygardi@codeaurora.org> (raw)
In-Reply-To: <1442155977-7686-1-git-send-email-ygardi@codeaurora.org>
Some UFS devices (and may be host) have issues if LCC is
enabled. So we are setting PA_Local_TX_LCC_Enable to 0
before link startup which will make sure that both host
and device TX LCC are disabled once link startup is
completed.
This change also:
- enables the device ref clock before changing to HS mode
and disables it if entered to PWM mode
- adds printouts of testbus debug registers
Signed-off-by: Yaniv Gardi <ygardi@codeaurora.org>
---
drivers/scsi/ufs/ufs-qcom.c | 116 +++++++++++++++++++++++++++++++++++++++++---
drivers/scsi/ufs/ufs-qcom.h | 9 ++++
drivers/scsi/ufs/ufshcd.h | 9 ++++
drivers/scsi/ufs/unipro.h | 1 +
4 files changed, 128 insertions(+), 7 deletions(-)
diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
index 1d26e49..f70b581 100644
--- a/drivers/scsi/ufs/ufs-qcom.c
+++ b/drivers/scsi/ufs/ufs-qcom.c
@@ -16,8 +16,8 @@
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/phy/phy.h>
-
#include <linux/phy/phy-qcom-ufs.h>
+
#include "ufshcd.h"
#include "ufshcd-pltfrm.h"
#include "unipro.h"
@@ -58,6 +58,12 @@ static void ufs_qcom_dump_regs(struct ufs_hba *hba, int offset, int len,
len * 4, false);
}
+static void ufs_qcom_dump_regs_wrapper(struct ufs_hba *hba, int offset, int len,
+ char *prefix, void *priv)
+{
+ ufs_qcom_dump_regs(hba, offset, len, prefix);
+}
+
static int ufs_qcom_get_connected_tx_lanes(struct ufs_hba *hba, u32 *tx_lanes)
{
int err = 0;
@@ -106,9 +112,11 @@ static void ufs_qcom_disable_lane_clks(struct ufs_qcom_host *host)
if (!host->is_lane_clks_enabled)
return;
- clk_disable_unprepare(host->tx_l1_sync_clk);
+ if (host->hba->lanes_per_direction > 1)
+ clk_disable_unprepare(host->tx_l1_sync_clk);
clk_disable_unprepare(host->tx_l0_sync_clk);
- clk_disable_unprepare(host->rx_l1_sync_clk);
+ if (host->hba->lanes_per_direction > 1)
+ clk_disable_unprepare(host->rx_l1_sync_clk);
clk_disable_unprepare(host->rx_l0_sync_clk);
host->is_lane_clks_enabled = false;
@@ -271,9 +279,8 @@ static int ufs_qcom_power_up_sequence(struct ufs_hba *hba)
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;
}
@@ -523,6 +530,18 @@ static int ufs_qcom_link_startup_notify(struct ufs_hba *hba,
err = ufs_qcom_set_dme_vs_core_clk_ctrl_clear_div(hba,
150);
+ /*
+ * Some UFS devices (and may be host) have issues if LCC is
+ * enabled. So we are setting PA_Local_TX_LCC_Enable to 0
+ * before link startup which will make sure that both host
+ * and device TX LCC are disabled once link startup is
+ * completed.
+ */
+ if (ufshcd_get_local_unipro_ver(hba) != UFS_UNIPRO_VER_1_41)
+ err = ufshcd_dme_set(hba,
+ UIC_ARG_MIB(PA_LOCAL_TX_LCC_ENABLE),
+ 0);
+
break;
case POST_CHANGE:
ufs_qcom_link_startup_post_change(hba);
@@ -966,6 +985,10 @@ static int ufs_qcom_pwr_change_notify(struct ufs_hba *hba,
goto out;
}
+ /* enable the device ref clock before changing to HS mode */
+ if (!ufshcd_is_hs_mode(&hba->pwr_info) &&
+ ufshcd_is_hs_mode(dev_req_params))
+ ufs_qcom_dev_ref_clk_ctrl(host, true);
break;
case POST_CHANGE:
if (ufs_qcom_cfg_timers(hba, dev_req_params->gear_rx,
@@ -993,6 +1016,11 @@ static int ufs_qcom_pwr_change_notify(struct ufs_hba *hba,
memcpy(&host->dev_req_params,
dev_req_params, sizeof(*dev_req_params));
ufs_qcom_update_bus_bw_vote(host);
+
+ /* disable the device ref clock if entered PWM mode */
+ if (ufshcd_is_hs_mode(&hba->pwr_info) &&
+ !ufshcd_is_hs_mode(dev_req_params))
+ ufs_qcom_dev_ref_clk_ctrl(host, false);
break;
default:
ret = -EINVAL;
@@ -1094,6 +1122,9 @@ static int ufs_qcom_setup_clocks(struct ufs_hba *hba, bool on)
ufs_qcom_phy_disable_iface_clk(host->generic_phy);
goto out;
}
+ /* enable the device ref clock for HS mode*/
+ if (ufshcd_is_hs_mode(&hba->pwr_info))
+ ufs_qcom_dev_ref_clk_ctrl(host, true);
vote = host->bus_vote.saved_vote;
if (vote == host->bus_vote.min_bw_vote)
ufs_qcom_update_bus_bw_vote(host);
@@ -1372,6 +1403,74 @@ out:
return err;
}
+static void ufs_qcom_print_hw_debug_reg_all(struct ufs_hba *hba,
+ void *priv, void (*print_fn)(struct ufs_hba *hba,
+ int offset, int num_regs, char *str, void *priv))
+{
+ u32 reg;
+ struct ufs_qcom_host *host;
+
+ if (unlikely(!hba)) {
+ pr_err("%s: hba is NULL\n", __func__);
+ return;
+ }
+ if (unlikely(!print_fn)) {
+ dev_err(hba->dev, "%s: print_fn is NULL\n", __func__);
+ return;
+ }
+
+ host = ufshcd_get_variant(hba);
+ if (!(host->dbg_print_en & UFS_QCOM_DBG_PRINT_REGS_EN))
+ return;
+
+ reg = ufs_qcom_get_debug_reg_offset(host, UFS_UFS_DBG_RD_REG_OCSC);
+ print_fn(hba, reg, 44, "UFS_UFS_DBG_RD_REG_OCSC ", priv);
+
+ reg = ufshcd_readl(hba, REG_UFS_CFG1);
+ reg |= UFS_BIT(17);
+ ufshcd_writel(hba, reg, REG_UFS_CFG1);
+
+ reg = ufs_qcom_get_debug_reg_offset(host, UFS_UFS_DBG_RD_EDTL_RAM);
+ print_fn(hba, reg, 32, "UFS_UFS_DBG_RD_EDTL_RAM ", priv);
+
+ reg = ufs_qcom_get_debug_reg_offset(host, UFS_UFS_DBG_RD_DESC_RAM);
+ print_fn(hba, reg, 128, "UFS_UFS_DBG_RD_DESC_RAM ", priv);
+
+ reg = ufs_qcom_get_debug_reg_offset(host, UFS_UFS_DBG_RD_PRDT_RAM);
+ print_fn(hba, reg, 64, "UFS_UFS_DBG_RD_PRDT_RAM ", priv);
+
+ ufshcd_writel(hba, (reg & ~UFS_BIT(17)), REG_UFS_CFG1);
+
+ reg = ufs_qcom_get_debug_reg_offset(host, UFS_DBG_RD_REG_UAWM);
+ print_fn(hba, reg, 4, "UFS_DBG_RD_REG_UAWM ", priv);
+
+ reg = ufs_qcom_get_debug_reg_offset(host, UFS_DBG_RD_REG_UARM);
+ print_fn(hba, reg, 4, "UFS_DBG_RD_REG_UARM ", priv);
+
+ reg = ufs_qcom_get_debug_reg_offset(host, UFS_DBG_RD_REG_TXUC);
+ print_fn(hba, reg, 48, "UFS_DBG_RD_REG_TXUC ", priv);
+
+ reg = ufs_qcom_get_debug_reg_offset(host, UFS_DBG_RD_REG_RXUC);
+ print_fn(hba, reg, 27, "UFS_DBG_RD_REG_RXUC ", priv);
+
+ reg = ufs_qcom_get_debug_reg_offset(host, UFS_DBG_RD_REG_DFC);
+ print_fn(hba, reg, 19, "UFS_DBG_RD_REG_DFC ", priv);
+
+ reg = ufs_qcom_get_debug_reg_offset(host, UFS_DBG_RD_REG_TRLUT);
+ print_fn(hba, reg, 34, "UFS_DBG_RD_REG_TRLUT ", priv);
+
+ reg = ufs_qcom_get_debug_reg_offset(host, UFS_DBG_RD_REG_TMRLUT);
+ print_fn(hba, reg, 9, "UFS_DBG_RD_REG_TMRLUT ", priv);
+}
+
+static void ufs_qcom_enable_test_bus(struct ufs_qcom_host *host)
+{
+ if (host->dbg_print_en & UFS_QCOM_DBG_PRINT_TEST_BUS_EN)
+ ufshcd_rmwl(host->hba, TEST_BUS_EN, TEST_BUS_EN, REG_UFS_CFG1);
+ else
+ ufshcd_rmwl(host->hba, TEST_BUS_EN, 0, REG_UFS_CFG1);
+}
+
static void ufs_qcom_get_default_testbus_cfg(struct ufs_qcom_host *host)
{
/* provide a legal default configuration */
@@ -1480,6 +1579,7 @@ int ufs_qcom_testbus_config(struct ufs_qcom_host *host)
ufshcd_rmwl(host->hba, mask,
(u32)host->testbus.select_minor << offset,
reg);
+ ufs_qcom_enable_test_bus(host);
ufshcd_release(host->hba);
pm_runtime_put_sync(host->hba->dev);
@@ -1496,8 +1596,10 @@ static void ufs_qcom_dump_dbg_regs(struct ufs_hba *hba)
ufs_qcom_dump_regs(hba, REG_UFS_SYS1CLK_1US, 16,
"HCI Vendor Specific Registers ");
+ ufs_qcom_print_hw_debug_reg_all(hba, NULL, ufs_qcom_dump_regs_wrapper);
ufs_qcom_testbus_read(hba);
}
+
/**
* struct ufs_hba_qcom_vops - UFS QCOM specific variant operations
*
@@ -1558,7 +1660,7 @@ out:
* ufs_qcom_remove - set driver_data of the device to NULL
* @pdev: pointer to platform device handle
*
- * Always return 0
+ * Always returns 0
*/
static int ufs_qcom_remove(struct platform_device *pdev)
{
diff --git a/drivers/scsi/ufs/ufs-qcom.h b/drivers/scsi/ufs/ufs-qcom.h
index 36249b3..a19307a 100644
--- a/drivers/scsi/ufs/ufs-qcom.h
+++ b/drivers/scsi/ufs/ufs-qcom.h
@@ -241,6 +241,15 @@ struct ufs_qcom_host {
struct ufs_qcom_testbus testbus;
};
+static inline u32
+ufs_qcom_get_debug_reg_offset(struct ufs_qcom_host *host, u32 reg)
+{
+ if (host->hw_ver.major <= 0x02)
+ return UFS_CNTLR_2_x_x_VEN_REGS_OFFSET(reg);
+
+ return UFS_CNTLR_3_x_x_VEN_REGS_OFFSET(reg);
+};
+
#define ufs_qcom_is_link_off(hba) ufshcd_is_link_off(hba)
#define ufs_qcom_is_link_active(hba) ufshcd_is_link_active(hba)
#define ufs_qcom_is_link_hibern8(hba) ufshcd_is_link_hibern8(hba)
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h
index aa1f3e5..cba580c 100644
--- a/drivers/scsi/ufs/ufshcd.h
+++ b/drivers/scsi/ufs/ufshcd.h
@@ -54,6 +54,7 @@
#include <linux/clk.h>
#include <linux/completion.h>
#include <linux/regulator/consumer.h>
+#include "unipro.h"
#include <asm/irq.h>
#include <asm/byteorder.h>
@@ -689,6 +690,14 @@ static inline int ufshcd_dme_peer_get(struct ufs_hba *hba,
int ufshcd_read_device_desc(struct ufs_hba *hba, u8 *buf, u32 size);
+static inline bool ufshcd_is_hs_mode(struct ufs_pa_layer_attr *pwr_info)
+{
+ return (pwr_info->pwr_rx == FAST_MODE ||
+ pwr_info->pwr_rx == FASTAUTO_MODE) &&
+ (pwr_info->pwr_tx == FAST_MODE ||
+ pwr_info->pwr_tx == FASTAUTO_MODE);
+}
+
#define ASCII_STD true
int ufshcd_read_string_desc(struct ufs_hba *hba, int desc_index, u8 *buf,
diff --git a/drivers/scsi/ufs/unipro.h b/drivers/scsi/ufs/unipro.h
index 8082020..e2854e4 100644
--- a/drivers/scsi/ufs/unipro.h
+++ b/drivers/scsi/ufs/unipro.h
@@ -75,6 +75,7 @@
#define PA_MAXRXSPEEDFAST 0x1541
#define PA_MAXRXSPEEDSLOW 0x1542
#define PA_TXLINKSTARTUPHS 0x1544
+#define PA_LOCAL_TX_LCC_ENABLE 0x155E
#define PA_TXSPEEDFAST 0x1565
#define PA_TXSPEEDSLOW 0x1566
#define PA_REMOTEVERINFO 0x15A0
--
1.8.5.2
--
QUALCOMM ISRAEL, on behalf of Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
prev parent reply other threads:[~2015-09-13 14:52 UTC|newest]
Thread overview: 38+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-09-13 14:52 [PATCH v1 00/17] add fixes, device quirks, error recovery, Yaniv Gardi
[not found] ` <1442155977-7686-1-git-send-email-ygardi-sgV2jX0FEOL9JmXXK+q4OQ@public.gmane.org>
2015-09-13 14:52 ` [PATCH v1 01/17] scsi: ufs-qcom: add number of lanes per direction Yaniv Gardi
2015-09-13 14:52 ` Yaniv Gardi
2015-10-21 15:47 ` Akinobu Mita
2015-10-21 15:47 ` Akinobu Mita
2015-09-13 14:52 ` [PATCH v1 02/17] scsi: ufs: add option to change default UFS power management level Yaniv Gardi
2015-09-13 14:52 ` Yaniv Gardi
2015-10-21 15:51 ` Akinobu Mita
2015-10-21 15:51 ` Akinobu Mita
2015-10-26 13:04 ` ygardi
2015-10-26 13:04 ` ygardi
2015-09-13 14:52 ` [PATCH v1 03/17] scsi: ufs: optimize system suspend handling Yaniv Gardi
2015-09-13 14:52 ` [PATCH v1 04/17] scsi: ufs: avoid spurious UFS host controller interrupts Yaniv Gardi
2015-09-13 14:52 ` [PATCH v1 05/17] scsi: ufs: implement scsi host timeout handler Yaniv Gardi
2015-09-13 14:52 ` [PATCH v1 06/17] scsi :ufs: verify hba controller hce reg value Yaniv Gardi
2015-10-21 15:53 ` Akinobu Mita
2015-10-26 13:11 ` ygardi
2015-09-13 14:52 ` [PATCH v1 07/17] scsi: ufs: separate device and host quirks Yaniv Gardi
2015-10-21 15:59 ` Akinobu Mita
2015-10-26 13:30 ` ygardi
2015-09-13 14:52 ` [PATCH v1 08/17] scsi: ufs: split broken LCC quirk Yaniv Gardi
2015-10-21 16:00 ` Akinobu Mita
2015-10-26 13:58 ` ygardi
2015-09-13 14:52 ` [PATCH v1 09/17] scsi: ufs: disable vccq if it's not needed by UFS device Yaniv Gardi
2015-09-13 14:52 ` [PATCH v1 10/17] scsi: ufs: make error handling bit faster Yaniv Gardi
2015-09-13 14:52 ` [PATCH v1 11/17] scsi: ufs: add error recovery after DL NAC error Yaniv Gardi
2015-09-13 14:52 ` [PATCH v1 12/17] scsi: ufs: add retry for query descriptors Yaniv Gardi
2015-10-21 16:05 ` Akinobu Mita
2015-10-26 14:03 ` ygardi
2015-09-13 14:52 ` [PATCH v1 13/17] scsi: ufs: handle non spec compliant bkops behaviour by device Yaniv Gardi
2015-09-13 14:52 ` [PATCH v1 14/17] scsi: ufs: tune UniPro parameters to optimize hibern8 exit time Yaniv Gardi
2015-10-21 16:10 ` Akinobu Mita
2015-10-26 14:32 ` ygardi
2015-09-13 14:52 ` [PATCH v1 15/17] scsi: ufs: fix leakage during link off state Yaniv Gardi
2015-09-13 14:52 ` [PATCH v1 16/17] scsi: ufs: add delay before putting UFS rails in low power modes Yaniv Gardi
2015-10-21 16:11 ` Akinobu Mita
2015-10-26 15:08 ` ygardi
2015-09-13 14:52 ` Yaniv Gardi [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1442155977-7686-18-git-send-email-ygardi@codeaurora.org \
--to=ygardi@codeaurora.org \
--cc=JBottomley@odin.com \
--cc=James.Bottomley@HansenPartnership.com \
--cc=draviv@codeaurora.org \
--cc=gbroner@codeaurora.org \
--cc=hch@infradead.org \
--cc=linux-arm-msm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-scsi-owner@vger.kernel.org \
--cc=linux-scsi@vger.kernel.org \
--cc=pebolle@tiscali.nl \
--cc=santoshsy@gmail.com \
--cc=subhashj@codeaurora.org \
--cc=vinholikatti@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.