Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2bc58696 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "scsi: ufs-qcom: expose debug registers by debugfs"

parents d9c0d608 0aa5c4c0
Loading
Loading
Loading
Loading
+20 −12
Original line number Diff line number Diff line
@@ -181,7 +181,7 @@ static void ufsdbg_setup_fault_injection(struct ufs_hba *hba)
}
#endif /* CONFIG_UFS_FAULT_INJECTION */

#define BUFF_LINE_CAPACITY 16
#define BUFF_LINE_SIZE 16 /* Must be a multiplication of sizeof(u32) */
#define TAB_CHARS 8

static int ufsdbg_tag_stats_show(struct seq_file *file, void *data)
@@ -436,20 +436,28 @@ exit:
	return ret;
}

static void
ufsdbg_pr_buf_to_std(struct seq_file *file, void *buff, int size, char *str)
void ufsdbg_pr_buf_to_std(struct ufs_hba *hba, int offset, int num_regs,
				char *str, void *priv)
{
	int i;
	char linebuf[38];
	int lines = size/BUFF_LINE_CAPACITY +
			(size % BUFF_LINE_CAPACITY ? 1 : 0);
	int size = num_regs * sizeof(u32);
	int lines = size / BUFF_LINE_SIZE +
			(size % BUFF_LINE_SIZE ? 1 : 0);
	struct seq_file *file = priv;

	if (!hba || !file) {
		pr_err("%s called with NULL pointer\n", __func__);
		return;
	}

	for (i = 0; i < lines; i++) {
		hex_dump_to_buffer(buff + i * BUFF_LINE_CAPACITY,
				BUFF_LINE_CAPACITY, BUFF_LINE_CAPACITY, 4,
		hex_dump_to_buffer(hba->mmio_base + offset + i * BUFF_LINE_SIZE,
				min(BUFF_LINE_SIZE, size), BUFF_LINE_SIZE, 4,
				linebuf, sizeof(linebuf), false);
		seq_printf(file, "%s [%x]: %s\n", str, i * BUFF_LINE_CAPACITY,
		seq_printf(file, "%s [%x]: %s\n", str, i * BUFF_LINE_SIZE,
				linebuf);
		size -= BUFF_LINE_SIZE/sizeof(u32);
	}
}

@@ -459,8 +467,8 @@ static int ufsdbg_host_regs_show(struct seq_file *file, void *data)

	ufshcd_hold(hba, false);
	pm_runtime_get_sync(hba->dev);
	ufsdbg_pr_buf_to_std(file, hba->mmio_base, UFSHCI_REG_SPACE_SIZE,
				"host regs");
	ufsdbg_pr_buf_to_std(hba, 0, UFSHCI_REG_SPACE_SIZE / sizeof(u32),
				"host regs", file);
	pm_runtime_put_sync(hba->dev);
	ufshcd_release(hba, false);
	return 0;
@@ -778,12 +786,12 @@ static ssize_t ufsdbg_power_mode_write(struct file *file,
	struct ufs_hba *hba = file->f_mapping->host->i_private;
	struct ufs_pa_layer_attr pwr_mode;
	struct ufs_pa_layer_attr final_pwr_mode;
	char pwr_mode_str[BUFF_LINE_CAPACITY] = {0};
	char pwr_mode_str[BUFF_LINE_SIZE] = {0};
	loff_t buff_pos = 0;
	int ret;
	int idx = 0;

	ret = simple_write_to_buffer(pwr_mode_str, BUFF_LINE_CAPACITY,
	ret = simple_write_to_buffer(pwr_mode_str, BUFF_LINE_SIZE,
		&buff_pos, ubuf, cnt);

	pwr_mode.gear_rx = pwr_mode_str[idx++] - '0';
+7 −1
Original line number Diff line number Diff line
/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
/* Copyright (c) 2013-2015, 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
@@ -28,6 +28,8 @@ void ufsdbg_add_debugfs(struct ufs_hba *hba);

void ufsdbg_remove_debugfs(struct ufs_hba *hba);
void ufsdbg_fail_request(struct ufs_hba *hba, u32 *intr_status);
void ufsdbg_pr_buf_to_std(struct ufs_hba *hba, int offset, int num_regs,
				char *str, void *priv);
#else
void ufsdbg_add_debugfs(struct ufs_hba *hba)
{
@@ -38,5 +40,9 @@ void ufsdbg_remove_debugfs(struct ufs_hba *hba)
void ufsdbg_fail_request(struct ufs_hba *hba, u32 *intr_status)
{
}
void ufsdbg_pr_buf_to_std(struct ufs_hba *hba, int offset, int num_regs,
				char *str, void *priv)
{
}
#endif
#endif /* End of Header */
+45 −0
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
#include <linux/debugfs.h>
#include <linux/scsi/ufs/ufs-qcom.h>
#include "qcom-debugfs.h"
#include "debugfs.h"

#define TESTBUS_CFG_BUFF_LINE_SIZE	sizeof("0xXY, 0xXY")

@@ -184,6 +185,39 @@ DEFINE_SIMPLE_ATTRIBUTE(ufs_qcom_dbg_testbus_bus_ops,
			NULL,
			"%llu\n");

static int ufs_qcom_dbg_dbg_regs_show(struct seq_file *file, void *data)
{
	struct ufs_qcom_host *host = (struct ufs_qcom_host *)file->private;
	bool dbg_print_reg = !!(host->dbg_print_en &
				UFS_QCOM_DBG_PRINT_REGS_EN);

	ufshcd_hold(host->hba, false);
	pm_runtime_get_sync(host->hba->dev);

	/* Temporarily override the debug print enable */
	host->dbg_print_en |= UFS_QCOM_DBG_PRINT_REGS_EN;
	ufs_qcom_print_hw_debug_reg_all(host->hba, file, ufsdbg_pr_buf_to_std);
	/* Restore previous debug print enable value */
	if (!dbg_print_reg)
		host->dbg_print_en &= ~UFS_QCOM_DBG_PRINT_REGS_EN;

	pm_runtime_put_sync(host->hba->dev);
	ufshcd_release(host->hba, false);

	return 0;
}

static int ufs_qcom_dbg_dbg_regs_open(struct inode *inode,
					      struct file *file)
{
	return single_open(file, ufs_qcom_dbg_dbg_regs_show,
				inode->i_private);
}

static const struct file_operations ufs_qcom_dbg_dbg_regs_desc = {
	.open		= ufs_qcom_dbg_dbg_regs_open,
	.read		= seq_read,
};

void ufs_qcom_dbg_add_debugfs(struct ufs_hba *hba, struct dentry *root)
{
@@ -262,6 +296,17 @@ void ufs_qcom_dbg_add_debugfs(struct ufs_hba *hba, struct dentry *root)
		goto err;
	}

	host->debugfs_files.dbg_regs =
		debugfs_create_file("debug-regs", S_IRUSR,
				    host->debugfs_files.debugfs_root, host,
				    &ufs_qcom_dbg_dbg_regs_desc);
	if (!host->debugfs_files.dbg_regs) {
		dev_err(host->hba->dev,
			"%s: failed create dbg_regs debugfs entry\n",
			__func__);
		goto err;
	}

	return;

err:
+43 −25
Original line number Diff line number Diff line
@@ -68,6 +68,12 @@ static void ufs_qcom_dump_regs(struct ufs_hba *hba, int offset, int len,
			16, 4, hba->mmio_base + offset, 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;
@@ -1389,44 +1395,56 @@ out:
	return ret;
}

static void ufs_qcom_print_hw_debug_reg_all(struct ufs_hba *hba)
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 = hba->priv;
	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 = hba->priv;
	if (!(host->dbg_print_en & UFS_QCOM_DBG_PRINT_REGS_EN))
		return;

	ufs_qcom_dump_regs(hba, UFS_UFS_DBG_RD_REG_OCSC, 44,
			"UFS_UFS_DBG_RD_REG_OCSC ");
	print_fn(hba, UFS_UFS_DBG_RD_REG_OCSC, 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);

	ufs_qcom_dump_regs(hba, UFS_UFS_DBG_RD_EDTL_RAM, 32,
			"UFS_UFS_DBG_RD_EDTL_RAM ");
	ufs_qcom_dump_regs(hba, UFS_UFS_DBG_RD_DESC_RAM, 128,
			"UFS_UFS_DBG_RD_DESC_RAM ");
	ufs_qcom_dump_regs(hba, UFS_UFS_DBG_RD_PRDT_RAM, 64,
			"UFS_UFS_DBG_RD_PRDT_RAM ");
	print_fn(hba, UFS_UFS_DBG_RD_EDTL_RAM, 32,
			"UFS_UFS_DBG_RD_EDTL_RAM ", priv);
	print_fn(hba, UFS_UFS_DBG_RD_DESC_RAM, 128,
			"UFS_UFS_DBG_RD_DESC_RAM ", priv);
	print_fn(hba, UFS_UFS_DBG_RD_PRDT_RAM, 64,
			"UFS_UFS_DBG_RD_PRDT_RAM ", priv);

	ufshcd_writel(hba, (reg & ~UFS_BIT(17)), REG_UFS_CFG1);

	ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_UAWM, 4,
			"UFS_DBG_RD_REG_UAWM ");
	ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_UARM, 4,
			"UFS_DBG_RD_REG_UARM ");
	ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_TXUC, 48,
			"UFS_DBG_RD_REG_TXUC ");
	ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_RXUC, 27,
			"UFS_DBG_RD_REG_RXUC ");
	ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_DFC, 19,
			"UFS_DBG_RD_REG_DFC ");
	ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_TRLUT, 34,
			"UFS_DBG_RD_REG_TRLUT ");
	ufs_qcom_dump_regs(hba, UFS_DBG_RD_REG_TMRLUT, 9,
			"UFS_DBG_RD_REG_TMRLUT ");
	print_fn(hba, UFS_DBG_RD_REG_UAWM, 4,
			"UFS_DBG_RD_REG_UAWM ", priv);
	print_fn(hba, UFS_DBG_RD_REG_UARM, 4,
			"UFS_DBG_RD_REG_UARM ", priv);
	print_fn(hba, UFS_DBG_RD_REG_TXUC, 48,
			"UFS_DBG_RD_REG_TXUC ", priv);
	print_fn(hba, UFS_DBG_RD_REG_RXUC, 27,
			"UFS_DBG_RD_REG_RXUC ", priv);
	print_fn(hba, UFS_DBG_RD_REG_DFC, 19,
			"UFS_DBG_RD_REG_DFC ", priv);
	print_fn(hba, UFS_DBG_RD_REG_TRLUT, 34,
			"UFS_DBG_RD_REG_TRLUT ", priv);
	print_fn(hba, UFS_DBG_RD_REG_TMRLUT, 9,
			"UFS_DBG_RD_REG_TMRLUT ", priv);
}

static void ufs_qcom_enable_test_bus(struct ufs_qcom_host *host)
@@ -1565,7 +1583,7 @@ 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);
	ufs_qcom_print_hw_debug_reg_all(hba, NULL, ufs_qcom_dump_regs_wrapper);
	ufs_qcom_testbus_read(hba);
	ufs_qcom_ice_print_regs(host);
}
+4 −0
Original line number Diff line number Diff line
@@ -218,6 +218,7 @@ struct qcom_debugfs_files {
	struct dentry *testbus_en;
	struct dentry *testbus_cfg;
	struct dentry *testbus_bus;
	struct dentry *dbg_regs;
};
#endif

@@ -254,6 +255,9 @@ struct ufs_qcom_host {
#define ufs_qcom_is_link_hibern8(hba) ufshcd_is_link_hibern8(hba)

int ufs_qcom_testbus_config(struct ufs_qcom_host *host);
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));

#define MAX_PROP_NAME              32
#define VDDA_PHY_MIN_UV            1000000