summaryrefslogtreecommitdiff
path: root/drivers/phy
diff options
context:
space:
mode:
authorVenkat Gopalakrishnan <venkatg@codeaurora.org>2016-08-26 18:33:11 -0700
committerVenkat Gopalakrishnan <venkatg@codeaurora.org>2016-09-12 11:19:39 -0700
commitfc8a047e3117ac9335c5ef579c27ae5b1833735c (patch)
tree5b88b4e2daf6a4f34538ea24b6322b1a4649b37c /drivers/phy
parent3dc7ca5e82cc56abc0463e35f1851cd8e2eed97a (diff)
phy: qcom-ufs-qmp-v3: add ops to dump phy regs
It's useful to dump phy registers on failure to debug link issues. Export a new ops for the ufs driver to invoke during link failures. Change-Id: Id3a9c9085375b783d97e7f2ffd3e11ec469aedb9 Signed-off-by: Venkat Gopalakrishnan <venkatg@codeaurora.org>
Diffstat (limited to 'drivers/phy')
-rw-r--r--drivers/phy/phy-qcom-ufs-i.h5
-rw-r--r--drivers/phy/phy-qcom-ufs-qmp-v3.c17
-rw-r--r--drivers/phy/phy-qcom-ufs-qmp-v3.h16
-rw-r--r--drivers/phy/phy-qcom-ufs.c18
4 files changed, 51 insertions, 5 deletions
diff --git a/drivers/phy/phy-qcom-ufs-i.h b/drivers/phy/phy-qcom-ufs-i.h
index 35179c8be471..7acef104d5b7 100644
--- a/drivers/phy/phy-qcom-ufs-i.h
+++ b/drivers/phy/phy-qcom-ufs-i.h
@@ -152,6 +152,7 @@ struct ufs_qcom_phy {
* and writes to QSERDES_RX_SIGDET_CNTRL attribute
* @configure_lpm: pointer to a function that configures the phy
* for low power mode.
+ * @dbg_register_dump: pointer to a function that dumps phy registers for debug.
*/
struct ufs_qcom_phy_specific_ops {
int (*calibrate_phy)(struct ufs_qcom_phy *phy, bool is_rate_B);
@@ -161,6 +162,7 @@ struct ufs_qcom_phy_specific_ops {
void (*ctrl_rx_linecfg)(struct ufs_qcom_phy *phy, bool ctrl);
void (*power_control)(struct ufs_qcom_phy *phy, bool val);
int (*configure_lpm)(struct ufs_qcom_phy *phy, bool enable);
+ void (*dbg_register_dump)(struct ufs_qcom_phy *phy);
};
struct ufs_qcom_phy *get_ufs_qcom_phy(struct phy *generic_phy);
@@ -184,5 +186,6 @@ int ufs_qcom_phy_calibrate(struct ufs_qcom_phy *ufs_qcom_phy,
void ufs_qcom_phy_write_tbl(struct ufs_qcom_phy *ufs_qcom_phy,
struct ufs_qcom_phy_calibration *tbl,
int tbl_size);
-
+void ufs_qcom_phy_dump_regs(struct ufs_qcom_phy *phy,
+ int offset, int len, char *prefix);
#endif
diff --git a/drivers/phy/phy-qcom-ufs-qmp-v3.c b/drivers/phy/phy-qcom-ufs-qmp-v3.c
index 57c23f70eb63..a9ad3a6f87cc 100644
--- a/drivers/phy/phy-qcom-ufs-qmp-v3.c
+++ b/drivers/phy/phy-qcom-ufs-qmp-v3.c
@@ -194,6 +194,22 @@ out:
return err;
}
+static void ufs_qcom_phy_qmp_v3_dbg_register_dump(struct ufs_qcom_phy *phy)
+{
+ ufs_qcom_phy_dump_regs(phy, COM_BASE, COM_SIZE,
+ "PHY QSERDES COM Registers ");
+ ufs_qcom_phy_dump_regs(phy, PHY_BASE, PHY_SIZE,
+ "PHY Registers ");
+ ufs_qcom_phy_dump_regs(phy, RX_BASE(0), RX_SIZE,
+ "PHY RX0 Registers ");
+ ufs_qcom_phy_dump_regs(phy, TX_BASE(0), TX_SIZE,
+ "PHY TX0 Registers ");
+ ufs_qcom_phy_dump_regs(phy, RX_BASE(1), RX_SIZE,
+ "PHY RX1 Registers ");
+ ufs_qcom_phy_dump_regs(phy, TX_BASE(1), TX_SIZE,
+ "PHY TX1 Registers ");
+}
+
struct phy_ops ufs_qcom_phy_qmp_v3_phy_ops = {
.init = ufs_qcom_phy_qmp_v3_init,
.exit = ufs_qcom_phy_exit,
@@ -210,6 +226,7 @@ struct ufs_qcom_phy_specific_ops phy_v3_ops = {
.ctrl_rx_linecfg = ufs_qcom_phy_qmp_v3_ctrl_rx_linecfg,
.power_control = ufs_qcom_phy_qmp_v3_power_control,
.configure_lpm = ufs_qcom_phy_qmp_v3_configure_lpm,
+ .dbg_register_dump = ufs_qcom_phy_qmp_v3_dbg_register_dump,
};
static int ufs_qcom_phy_qmp_v3_probe(struct platform_device *pdev)
diff --git a/drivers/phy/phy-qcom-ufs-qmp-v3.h b/drivers/phy/phy-qcom-ufs-qmp-v3.h
index cda57855acb5..8b1e03eab639 100644
--- a/drivers/phy/phy-qcom-ufs-qmp-v3.h
+++ b/drivers/phy/phy-qcom-ufs-qmp-v3.h
@@ -18,10 +18,18 @@
#include "phy-qcom-ufs-i.h"
/* QCOM UFS PHY control registers */
-#define COM_OFF(x) (0x000 + x)
-#define PHY_OFF(x) (0xC00 + x)
-#define TX_OFF(n, x) (0x400 + (0x400 * n) + x)
-#define RX_OFF(n, x) (0x600 + (0x400 * n) + x)
+#define COM_BASE 0x000
+#define COM_SIZE 0x18C
+#define PHY_BASE 0xC00
+#define PHY_SIZE 0x1DC
+#define TX_BASE(n) (0x400 + (0x400 * n))
+#define TX_SIZE 0x128
+#define RX_BASE(n) (0x600 + (0x400 * n))
+#define RX_SIZE 0x1FC
+#define COM_OFF(x) (COM_BASE + x)
+#define PHY_OFF(x) (PHY_BASE + x)
+#define TX_OFF(n, x) (TX_BASE(n) + x)
+#define RX_OFF(n, x) (RX_BASE(n) + x)
/* UFS PHY QSERDES COM registers */
#define QSERDES_COM_ATB_SEL1 COM_OFF(0x00)
diff --git a/drivers/phy/phy-qcom-ufs.c b/drivers/phy/phy-qcom-ufs.c
index de32b75f4f57..b2c58430785a 100644
--- a/drivers/phy/phy-qcom-ufs.c
+++ b/drivers/phy/phy-qcom-ufs.c
@@ -788,3 +788,21 @@ int ufs_qcom_phy_configure_lpm(struct phy *generic_phy, bool enable)
return ret;
}
EXPORT_SYMBOL(ufs_qcom_phy_configure_lpm);
+
+void ufs_qcom_phy_dump_regs(struct ufs_qcom_phy *phy, int offset,
+ int len, char *prefix)
+{
+ print_hex_dump(KERN_ERR, prefix,
+ len > 4 ? DUMP_PREFIX_OFFSET : DUMP_PREFIX_NONE,
+ 16, 4, phy->mmio + offset, len, false);
+}
+EXPORT_SYMBOL(ufs_qcom_phy_dump_regs);
+
+void ufs_qcom_phy_dbg_register_dump(struct phy *generic_phy)
+{
+ struct ufs_qcom_phy *ufs_qcom_phy = get_ufs_qcom_phy(generic_phy);
+
+ if (ufs_qcom_phy->phy_spec_ops->dbg_register_dump)
+ ufs_qcom_phy->phy_spec_ops->dbg_register_dump(ufs_qcom_phy);
+}
+EXPORT_SYMBOL(ufs_qcom_phy_dbg_register_dump);