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>
This commit is contained in:
parent
3dc7ca5e82
commit
fc8a047e31
5 changed files with 52 additions and 5 deletions
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -58,5 +58,6 @@ 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);
|
||||
int ufs_qcom_phy_configure_lpm(struct phy *generic_phy, bool enable);
|
||||
void ufs_qcom_phy_dbg_register_dump(struct phy *generic_phy);
|
||||
|
||||
#endif /* PHY_QCOM_UFS_H_ */
|
||||
|
|
Loading…
Add table
Reference in a new issue