linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v4 1/3] phy: mediatek: fix build warning caused by clang for powerpc
@ 2022-11-10 13:27 Chunfeng Yun
  2022-11-10 13:27 ` [PATCH v4 2/3] phy: core: add debugfs root Chunfeng Yun
  2022-11-10 13:27 ` [PATCH v4 3/3] phy: mediatek: tphy: add debugfs files Chunfeng Yun
  0 siblings, 2 replies; 10+ messages in thread
From: Chunfeng Yun @ 2022-11-10 13:27 UTC (permalink / raw)
  To: Vinod Koul
  Cc: Chunfeng Yun, Kishon Vijay Abraham I, Matthias Brugger,
	Nathan Chancellor, Nick Desaulniers, Tom Rix,
	AngeloGioacchino Del Regno, linux-arm-kernel, linux-mediatek,
	linux-phy, linux-kernel, llvm, Eddie Hung, Tianping Fang,
	kernel test robot

Remove the temporary @mask_, this may cause build warning when use clang
compiler for powerpc, but can't reproduce it when compile for arm64.
the build warning is -Wtautological-constant-out-of-range-compare, and
caused by
"BUILD_BUG_ON_MSG(__bf_cast_unsigned(_mask, _mask)"

After removing @mask_, there is a "CHECK:MACRO_ARG_REUSE" when run
checkpatch.pl, due to @mask is constant, no reuse problem will happen.

Fixes: 84513eccd678 ("phy: mediatek: fix build warning of FIELD_PREP()")
Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
---
v4 new patch, I'm not sure it can fix build warning, due to I don't cross compile
    it for powerpc using clang in office.
---
 drivers/phy/mediatek/phy-mtk-io.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/phy/mediatek/phy-mtk-io.h b/drivers/phy/mediatek/phy-mtk-io.h
index d20ad5e5be81..58f06db822cb 100644
--- a/drivers/phy/mediatek/phy-mtk-io.h
+++ b/drivers/phy/mediatek/phy-mtk-io.h
@@ -39,8 +39,8 @@ static inline void mtk_phy_update_bits(void __iomem *reg, u32 mask, u32 val)
 /* field @mask shall be constant and continuous */
 #define mtk_phy_update_field(reg, mask, val) \
 ({ \
-	typeof(mask) mask_ = (mask);	\
-	mtk_phy_update_bits(reg, mask_, FIELD_PREP(mask_, val)); \
+	BUILD_BUG_ON_MSG(!__builtin_constant_p(mask), "mask is not constant"); \
+	mtk_phy_update_bits(reg, mask, FIELD_PREP(mask, val)); \
 })
 
 #endif
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v4 2/3] phy: core: add debugfs root
  2022-11-10 13:27 [PATCH v4 1/3] phy: mediatek: fix build warning caused by clang for powerpc Chunfeng Yun
@ 2022-11-10 13:27 ` Chunfeng Yun
  2022-11-24 17:39   ` Vinod Koul
  2022-11-10 13:27 ` [PATCH v4 3/3] phy: mediatek: tphy: add debugfs files Chunfeng Yun
  1 sibling, 1 reply; 10+ messages in thread
From: Chunfeng Yun @ 2022-11-10 13:27 UTC (permalink / raw)
  To: Vinod Koul
  Cc: Chunfeng Yun, Kishon Vijay Abraham I, Matthias Brugger,
	Nathan Chancellor, Nick Desaulniers, Tom Rix,
	AngeloGioacchino Del Regno, linux-arm-kernel, linux-mediatek,
	linux-phy, linux-kernel, llvm, Eddie Hung, Tianping Fang

Add a debugfs root for phy class, then phy drivers can add debugfs files
under this folder.

Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
---
v2~v4: no changes
---
 drivers/phy/phy-core.c  | 6 ++++++
 include/linux/phy/phy.h | 2 ++
 2 files changed, 8 insertions(+)

diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c
index d93ddf1262c5..2f9f69190519 100644
--- a/drivers/phy/phy-core.c
+++ b/drivers/phy/phy-core.c
@@ -11,6 +11,7 @@
 #include <linux/export.h>
 #include <linux/module.h>
 #include <linux/err.h>
+#include <linux/debugfs.h>
 #include <linux/device.h>
 #include <linux/slab.h>
 #include <linux/of.h>
@@ -1204,6 +1205,9 @@ void devm_of_phy_provider_unregister(struct device *dev,
 }
 EXPORT_SYMBOL_GPL(devm_of_phy_provider_unregister);
 
+struct dentry *phy_debug_root;
+EXPORT_SYMBOL_GPL(phy_debug_root);
+
 /**
  * phy_release() - release the phy
  * @dev: the dev member within phy
@@ -1233,6 +1237,8 @@ static int __init phy_core_init(void)
 
 	phy_class->dev_release = phy_release;
 
+	phy_debug_root = debugfs_create_dir("phy", NULL);
+
 	return 0;
 }
 device_initcall(phy_core_init);
diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h
index b1413757fcc3..c398749d49b9 100644
--- a/include/linux/phy/phy.h
+++ b/include/linux/phy/phy.h
@@ -205,6 +205,8 @@ struct phy_lookup {
 #define devm_of_phy_provider_register_full(dev, children, xlate) \
 	__devm_of_phy_provider_register(dev, children, THIS_MODULE, xlate)
 
+extern struct dentry *phy_debug_root;
+
 static inline void phy_set_drvdata(struct phy *phy, void *data)
 {
 	dev_set_drvdata(&phy->dev, data);
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v4 3/3] phy: mediatek: tphy: add debugfs files
  2022-11-10 13:27 [PATCH v4 1/3] phy: mediatek: fix build warning caused by clang for powerpc Chunfeng Yun
  2022-11-10 13:27 ` [PATCH v4 2/3] phy: core: add debugfs root Chunfeng Yun
@ 2022-11-10 13:27 ` Chunfeng Yun
  2022-11-24 17:47   ` Vinod Koul
  1 sibling, 1 reply; 10+ messages in thread
From: Chunfeng Yun @ 2022-11-10 13:27 UTC (permalink / raw)
  To: Vinod Koul
  Cc: Chunfeng Yun, Kishon Vijay Abraham I, Matthias Brugger,
	Nathan Chancellor, Nick Desaulniers, Tom Rix,
	AngeloGioacchino Del Regno, linux-arm-kernel, linux-mediatek,
	linux-phy, linux-kernel, llvm, Eddie Hung, Tianping Fang

These debugfs files are mainly used to make eye diagram test easier,
especially helpful to do HQA test for a new IC without efuse enabled.

Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
---
v4: fix build warning of sometimes uninitialized variable

v3: fix typo of "debugfs" suggested by AngeloGioacchino

v2: add CONFIG_PHY_MTK_TPHY_DEBUGFS suggested by AngeloGioacchino
---
 drivers/phy/mediatek/Kconfig        |   5 +
 drivers/phy/mediatek/phy-mtk-tphy.c | 405 +++++++++++++++++++++++++++-
 2 files changed, 409 insertions(+), 1 deletion(-)

diff --git a/drivers/phy/mediatek/Kconfig b/drivers/phy/mediatek/Kconfig
index 3125ecb5d119..e9fdfe9f519f 100644
--- a/drivers/phy/mediatek/Kconfig
+++ b/drivers/phy/mediatek/Kconfig
@@ -27,6 +27,11 @@ config PHY_MTK_TPHY
 	  multi-ports is first version, otherwise is second version,
 	  so you can easily distinguish them by banks layout.
 
+config PHY_MTK_TPHY_DEBUGFS
+	bool "Add T-PHY Debugfs Files"
+	help
+	  Say Y here to add debugfs files mainly for T-PHY HQA test.
+
 config PHY_MTK_UFS
 	tristate "MediaTek UFS M-PHY driver"
 	depends on ARCH_MEDIATEK || COMPILE_TEST
diff --git a/drivers/phy/mediatek/phy-mtk-tphy.c b/drivers/phy/mediatek/phy-mtk-tphy.c
index e906a82791bd..f220a9a409bf 100644
--- a/drivers/phy/mediatek/phy-mtk-tphy.c
+++ b/drivers/phy/mediatek/phy-mtk-tphy.c
@@ -7,6 +7,7 @@
 
 #include <dt-bindings/phy/phy.h>
 #include <linux/clk.h>
+#include <linux/debugfs.h>
 #include <linux/delay.h>
 #include <linux/iopoll.h>
 #include <linux/mfd/syscon.h>
@@ -264,6 +265,8 @@
 
 #define TPHY_CLKS_CNT	2
 
+#define USER_BUF_LEN(count) min_t(size_t, 8, (count))
+
 enum mtk_phy_version {
 	MTK_PHY_V1 = 1,
 	MTK_PHY_V2,
@@ -310,6 +313,7 @@ struct mtk_phy_instance {
 	struct clk_bulk_data clks[TPHY_CLKS_CNT];
 	u32 index;
 	u32 type;
+	struct dentry *dbgfs;
 	struct regmap *type_sw;
 	u32 type_sw_reg;
 	u32 type_sw_index;
@@ -332,10 +336,391 @@ struct mtk_tphy {
 	const struct mtk_phy_pdata *pdata;
 	struct mtk_phy_instance **phys;
 	int nphys;
+	struct dentry *dbgfs_root;
 	int src_ref_clk; /* MHZ, reference clock for slew rate calibrate */
 	int src_coef; /* coefficient for slew rate calibrate */
 };
 
+#if IS_ENABLED(CONFIG_PHY_MTK_TPHY_DEBUGFS)
+
+enum u2_phy_params {
+	U2P_EYE_VRT = 0,
+	U2P_EYE_TERM,
+	U2P_EFUSE_EN,
+	U2P_EFUSE_INTR,
+	U2P_DISCTH,
+	U2P_PRE_EMPHASIS,
+};
+
+enum u3_phy_params {
+	U3P_EFUSE_EN = 0,
+	U3P_EFUSE_INTR,
+	U3P_EFUSE_TX_IMP,
+	U3P_EFUSE_RX_IMP,
+};
+
+static const char *const u2_phy_files[] = {
+	[U2P_EYE_VRT] = "vrt",
+	[U2P_EYE_TERM] = "term",
+	[U2P_EFUSE_EN] = "efuse",
+	[U2P_EFUSE_INTR] = "intr",
+	[U2P_DISCTH] = "discth",
+	[U2P_PRE_EMPHASIS] = "preemph",
+};
+
+static const char *const u3_phy_files[] = {
+	[U3P_EFUSE_EN] = "efuse",
+	[U3P_EFUSE_INTR] = "intr",
+	[U3P_EFUSE_TX_IMP] = "tx-imp",
+	[U3P_EFUSE_RX_IMP] = "rx-imp",
+};
+
+static int u2_phy_params_show(struct seq_file *sf, void *unused)
+{
+	struct mtk_phy_instance *inst = sf->private;
+	const char *fname = file_dentry(sf->file)->d_iname;
+	struct u2phy_banks *u2_banks = &inst->u2_banks;
+	void __iomem *com = u2_banks->com;
+	u32 max = 0;
+	u32 tmp = 0;
+	u32 val = 0;
+	int ret;
+
+	ret = match_string(u2_phy_files, ARRAY_SIZE(u2_phy_files), fname);
+	if (ret < 0)
+		return ret;
+
+	switch (ret) {
+	case U2P_EYE_VRT:
+		tmp = readl(com + U3P_USBPHYACR1);
+		val = FIELD_GET(PA1_RG_VRT_SEL, tmp);
+		max = FIELD_MAX(PA1_RG_VRT_SEL);
+		break;
+
+	case U2P_EYE_TERM:
+		tmp = readl(com + U3P_USBPHYACR1);
+		val = FIELD_GET(PA1_RG_TERM_SEL, tmp);
+		max = FIELD_MAX(PA1_RG_TERM_SEL);
+		break;
+
+	case U2P_EFUSE_EN:
+		if (u2_banks->misc) {
+			tmp = readl(u2_banks->misc + U3P_MISC_REG1);
+			max = 1;
+		}
+
+		val = !!(tmp & MR1_EFUSE_AUTO_LOAD_DIS);
+		break;
+
+	case U2P_EFUSE_INTR:
+		tmp = readl(com + U3P_USBPHYACR1);
+		val = FIELD_GET(PA1_RG_INTR_CAL, tmp);
+		max = FIELD_MAX(PA1_RG_INTR_CAL);
+		break;
+
+	case U2P_DISCTH:
+		tmp = readl(com + U3P_USBPHYACR6);
+		val = FIELD_GET(PA6_RG_U2_DISCTH, tmp);
+		max = FIELD_MAX(PA6_RG_U2_DISCTH);
+		break;
+
+	case U2P_PRE_EMPHASIS:
+		tmp = readl(com + U3P_USBPHYACR6);
+		val = FIELD_GET(PA6_RG_U2_PRE_EMP, tmp);
+		max = FIELD_MAX(PA6_RG_U2_PRE_EMP);
+		break;
+
+	default:
+		seq_printf(sf, "invalid, %d\n", ret);
+		break;
+	}
+
+	seq_printf(sf, "%s : %d [0, %d]\n", fname, val, max);
+
+	return 0;
+}
+
+static int u2_phy_params_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, u2_phy_params_show, inode->i_private);
+}
+
+static ssize_t u2_phy_params_write(struct file *file, const char __user *ubuf,
+				   size_t count, loff_t *ppos)
+{
+	const char *fname = file_dentry(file)->d_iname;
+	struct seq_file *sf = file->private_data;
+	struct mtk_phy_instance *inst = sf->private;
+	struct u2phy_banks *u2_banks = &inst->u2_banks;
+	void __iomem *com = u2_banks->com;
+	ssize_t rc;
+	u32 val;
+	int ret;
+
+	rc = kstrtouint_from_user(ubuf, USER_BUF_LEN(count), 0, &val);
+	if (rc)
+		return rc;
+
+	ret = match_string(u2_phy_files, ARRAY_SIZE(u2_phy_files), fname);
+	if (ret < 0)
+		return (ssize_t)ret;
+
+	switch (ret) {
+	case U2P_EYE_VRT:
+		mtk_phy_update_field(com + U3P_USBPHYACR1, PA1_RG_VRT_SEL, val);
+		break;
+
+	case U2P_EYE_TERM:
+		mtk_phy_update_field(com + U3P_USBPHYACR1, PA1_RG_TERM_SEL, val);
+		break;
+
+	case U2P_EFUSE_EN:
+		if (u2_banks->misc)
+			mtk_phy_update_field(u2_banks->misc + U3P_MISC_REG1,
+					     MR1_EFUSE_AUTO_LOAD_DIS, !!val);
+		break;
+
+	case U2P_EFUSE_INTR:
+		mtk_phy_update_field(com + U3P_USBPHYACR1, PA1_RG_INTR_CAL, val);
+		break;
+
+	case U2P_DISCTH:
+		mtk_phy_update_field(com + U3P_USBPHYACR6, PA6_RG_U2_DISCTH, val);
+		break;
+
+	case U2P_PRE_EMPHASIS:
+		mtk_phy_update_field(com + U3P_USBPHYACR6, PA6_RG_U2_PRE_EMP, val);
+		break;
+
+	default:
+		break;
+	}
+
+	return count;
+}
+
+static const struct file_operations u2_phy_fops = {
+	.open = u2_phy_params_open,
+	.write = u2_phy_params_write,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+
+static void u2_phy_dbgfs_files_create(struct mtk_phy_instance *inst)
+{
+	u32 count = ARRAY_SIZE(u2_phy_files);
+	int i;
+
+	for (i = 0; i < count; i++)
+		debugfs_create_file(u2_phy_files[i], 0644, inst->dbgfs, inst, &u2_phy_fops);
+}
+
+static int u3_phy_params_show(struct seq_file *sf, void *unused)
+{
+	struct mtk_phy_instance *inst = sf->private;
+	const char *fname = file_dentry(sf->file)->d_iname;
+	struct u3phy_banks *u3_banks = &inst->u3_banks;
+	u32 val = 0;
+	u32 max = 0;
+	u32 tmp;
+	int ret;
+
+	ret = match_string(u3_phy_files, ARRAY_SIZE(u3_phy_files), fname);
+	if (ret < 0)
+		return ret;
+
+	switch (ret) {
+	case U3P_EFUSE_EN:
+		tmp = readl(u3_banks->phyd + U3P_U3_PHYD_RSV);
+		val = !!(tmp & P3D_RG_EFUSE_AUTO_LOAD_DIS);
+		max = 1;
+		break;
+
+	case U3P_EFUSE_INTR:
+		tmp = readl(u3_banks->phya + U3P_U3_PHYA_REG0);
+		val = FIELD_GET(P3A_RG_IEXT_INTR, tmp);
+		max = FIELD_MAX(P3A_RG_IEXT_INTR);
+		break;
+
+	case U3P_EFUSE_TX_IMP:
+		tmp = readl(u3_banks->phyd + U3P_U3_PHYD_IMPCAL0);
+		val = FIELD_GET(P3D_RG_TX_IMPEL, tmp);
+		max = FIELD_MAX(P3D_RG_TX_IMPEL);
+		break;
+
+	case U3P_EFUSE_RX_IMP:
+		tmp = readl(u3_banks->phyd + U3P_U3_PHYD_IMPCAL1);
+		val = FIELD_GET(P3D_RG_RX_IMPEL, tmp);
+		max = FIELD_MAX(P3D_RG_RX_IMPEL);
+		break;
+
+	default:
+		seq_printf(sf, "invalid, %d\n", ret);
+		break;
+	}
+
+	seq_printf(sf, "%s : %d [0, %d]\n", fname, val, max);
+
+	return 0;
+}
+
+static int u3_phy_params_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, u3_phy_params_show, inode->i_private);
+}
+
+static ssize_t u3_phy_params_write(struct file *file, const char __user *ubuf,
+				   size_t count, loff_t *ppos)
+{
+	const char *fname = file_dentry(file)->d_iname;
+	struct seq_file *sf = file->private_data;
+	struct mtk_phy_instance *inst = sf->private;
+	struct u3phy_banks *u3_banks = &inst->u3_banks;
+	void __iomem *phyd = u3_banks->phyd;
+	ssize_t rc;
+	u32 val;
+	int ret;
+
+	rc = kstrtouint_from_user(ubuf, USER_BUF_LEN(count), 0, &val);
+	if (rc)
+		return rc;
+
+	ret = match_string(u3_phy_files, ARRAY_SIZE(u3_phy_files), fname);
+	if (ret < 0)
+		return (ssize_t)ret;
+
+	switch (ret) {
+	case U3P_EFUSE_EN:
+		mtk_phy_update_field(phyd + U3P_U3_PHYD_RSV,
+				     P3D_RG_EFUSE_AUTO_LOAD_DIS, !!val);
+		break;
+
+	case U3P_EFUSE_INTR:
+		mtk_phy_update_field(u3_banks->phya + U3P_U3_PHYA_REG0, P3A_RG_IEXT_INTR, val);
+		break;
+
+	case U3P_EFUSE_TX_IMP:
+		mtk_phy_update_field(phyd + U3P_U3_PHYD_IMPCAL0, P3D_RG_TX_IMPEL, val);
+		mtk_phy_set_bits(phyd + U3P_U3_PHYD_IMPCAL0, P3D_RG_FORCE_TX_IMPEL);
+		break;
+
+	case U3P_EFUSE_RX_IMP:
+		mtk_phy_update_field(phyd + U3P_U3_PHYD_IMPCAL1, P3D_RG_RX_IMPEL, val);
+		mtk_phy_set_bits(phyd + U3P_U3_PHYD_IMPCAL1, P3D_RG_FORCE_RX_IMPEL);
+		break;
+
+	default:
+		break;
+	}
+
+	return count;
+}
+
+static const struct file_operations u3_phy_fops = {
+	.open = u3_phy_params_open,
+	.write = u3_phy_params_write,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+
+static void u3_phy_dbgfs_files_create(struct mtk_phy_instance *inst)
+{
+	u32 count = ARRAY_SIZE(u3_phy_files);
+	int i;
+
+	for (i = 0; i < count; i++)
+		debugfs_create_file(u3_phy_files[i], 0644, inst->dbgfs, inst, &u3_phy_fops);
+}
+
+static int tphy_type_show(struct seq_file *sf, void *unused)
+{
+	struct mtk_phy_instance *inst = sf->private;
+	const char *type;
+
+	switch (inst->type) {
+	case PHY_TYPE_USB2:
+		type = "USB2";
+		break;
+	case PHY_TYPE_USB3:
+		type = "USB3";
+		break;
+	case PHY_TYPE_PCIE:
+		type = "PCIe";
+		break;
+	case PHY_TYPE_SGMII:
+		type = "SGMII";
+		break;
+	case PHY_TYPE_SATA:
+		type = "SATA";
+		break;
+	default:
+		type = "";
+	}
+
+	seq_printf(sf, "%s\n", type);
+
+	return 0;
+}
+
+DEFINE_SHOW_ATTRIBUTE(tphy_type);
+
+static void tphy_debugfs_init(struct mtk_tphy *tphy, struct mtk_phy_instance *inst)
+{
+	char name[16];
+
+	snprintf(name, sizeof(name) - 1, "phy.%d", inst->index);
+	inst->dbgfs = debugfs_create_dir(name, tphy->dbgfs_root);
+
+	debugfs_create_file("type", 0444, inst->dbgfs, inst, &tphy_type_fops);
+
+	switch (inst->type) {
+	case PHY_TYPE_USB2:
+		u2_phy_dbgfs_files_create(inst);
+		break;
+	case PHY_TYPE_USB3:
+	case PHY_TYPE_PCIE:
+		u3_phy_dbgfs_files_create(inst);
+		break;
+	default:
+		break;
+	}
+}
+
+static void tphy_debugfs_exit(struct mtk_phy_instance *inst)
+{
+	debugfs_remove_recursive(inst->dbgfs);
+	inst->dbgfs = NULL;
+}
+
+static void tphy_debugfs_root_create(struct mtk_tphy *tphy)
+{
+	tphy->dbgfs_root = debugfs_create_dir(dev_name(tphy->dev), phy_debug_root);
+}
+
+static void tphy_debugfs_root_remove(struct mtk_tphy *tphy)
+{
+	debugfs_remove_recursive(tphy->dbgfs_root);
+	tphy->dbgfs_root = NULL;
+}
+
+#else
+
+static void tphy_debugfs_init(struct mtk_tphy *tphy, struct mtk_phy_instance *inst)
+{}
+
+static void tphy_debugfs_exit(struct mtk_phy_instance *inst)
+{}
+
+static void tphy_debugfs_root_create(struct mtk_tphy *tphy)
+{}
+
+static void tphy_debugfs_root_remove(struct mtk_tphy *tphy)
+{}
+
+#endif
+
 static void hs_slew_rate_calibrate(struct mtk_tphy *tphy,
 	struct mtk_phy_instance *instance)
 {
@@ -1032,6 +1417,8 @@ static int mtk_phy_init(struct phy *phy)
 		return -EINVAL;
 	}
 
+	tphy_debugfs_init(tphy, instance);
+
 	return 0;
 }
 
@@ -1068,6 +1455,8 @@ static int mtk_phy_exit(struct phy *phy)
 	struct mtk_phy_instance *instance = phy_get_drvdata(phy);
 	struct mtk_tphy *tphy = dev_get_drvdata(phy->dev.parent);
 
+	tphy_debugfs_exit(instance);
+
 	if (instance->type == PHY_TYPE_USB2)
 		u2_phy_instance_exit(tphy, instance);
 
@@ -1295,15 +1684,29 @@ static int mtk_tphy_probe(struct platform_device *pdev)
 	}
 
 	provider = devm_of_phy_provider_register(dev, mtk_phy_xlate);
+	if (IS_ERR(provider))
+		return dev_err_probe(dev, PTR_ERR(provider), "probe failed\n");
+
+	tphy_debugfs_root_create(tphy);
+	return 0;
 
-	return PTR_ERR_OR_ZERO(provider);
 put_child:
 	of_node_put(child_np);
 	return retval;
 }
 
+static int mtk_tphy_remove(struct platform_device *pdev)
+{
+	struct mtk_tphy *tphy;
+
+	tphy = platform_get_drvdata(pdev);
+	tphy_debugfs_root_remove(tphy);
+	return 0;
+}
+
 static struct platform_driver mtk_tphy_driver = {
 	.probe		= mtk_tphy_probe,
+	.remove		= mtk_tphy_remove,
 	.driver		= {
 		.name	= "mtk-tphy",
 		.of_match_table = mtk_tphy_id_table,
-- 
2.18.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH v4 2/3] phy: core: add debugfs root
  2022-11-10 13:27 ` [PATCH v4 2/3] phy: core: add debugfs root Chunfeng Yun
@ 2022-11-24 17:39   ` Vinod Koul
  2022-11-28  7:00     ` Chunfeng Yun (云春峰)
  0 siblings, 1 reply; 10+ messages in thread
From: Vinod Koul @ 2022-11-24 17:39 UTC (permalink / raw)
  To: Chunfeng Yun
  Cc: Kishon Vijay Abraham I, Matthias Brugger, Nathan Chancellor,
	Nick Desaulniers, Tom Rix, AngeloGioacchino Del Regno,
	linux-arm-kernel, linux-mediatek, linux-phy, linux-kernel, llvm,
	Eddie Hung, Tianping Fang

On 10-11-22, 21:27, Chunfeng Yun wrote:
> Add a debugfs root for phy class, then phy drivers can add debugfs files
> under this folder.
> 
> Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
> ---
> v2~v4: no changes
> ---
>  drivers/phy/phy-core.c  | 6 ++++++
>  include/linux/phy/phy.h | 2 ++
>  2 files changed, 8 insertions(+)
> 
> diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c
> index d93ddf1262c5..2f9f69190519 100644
> --- a/drivers/phy/phy-core.c
> +++ b/drivers/phy/phy-core.c
> @@ -11,6 +11,7 @@
>  #include <linux/export.h>
>  #include <linux/module.h>
>  #include <linux/err.h>
> +#include <linux/debugfs.h>
>  #include <linux/device.h>
>  #include <linux/slab.h>
>  #include <linux/of.h>
> @@ -1204,6 +1205,9 @@ void devm_of_phy_provider_unregister(struct device *dev,
>  }
>  EXPORT_SYMBOL_GPL(devm_of_phy_provider_unregister);
>  
> +struct dentry *phy_debug_root;
> +EXPORT_SYMBOL_GPL(phy_debug_root);

Why expose this to whole world? Alternate approach would be to add this
in struct phy

> +
>  /**
>   * phy_release() - release the phy
>   * @dev: the dev member within phy
> @@ -1233,6 +1237,8 @@ static int __init phy_core_init(void)
>  
>  	phy_class->dev_release = phy_release;
>  
> +	phy_debug_root = debugfs_create_dir("phy", NULL);
> +
>  	return 0;
>  }
>  device_initcall(phy_core_init);
> diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h
> index b1413757fcc3..c398749d49b9 100644
> --- a/include/linux/phy/phy.h
> +++ b/include/linux/phy/phy.h
> @@ -205,6 +205,8 @@ struct phy_lookup {
>  #define devm_of_phy_provider_register_full(dev, children, xlate) \
>  	__devm_of_phy_provider_register(dev, children, THIS_MODULE, xlate)
>  
> +extern struct dentry *phy_debug_root;
> +
>  static inline void phy_set_drvdata(struct phy *phy, void *data)
>  {
>  	dev_set_drvdata(&phy->dev, data);
> -- 
> 2.18.0

-- 
~Vinod

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v4 3/3] phy: mediatek: tphy: add debugfs files
  2022-11-10 13:27 ` [PATCH v4 3/3] phy: mediatek: tphy: add debugfs files Chunfeng Yun
@ 2022-11-24 17:47   ` Vinod Koul
  2022-11-28  7:26     ` Chunfeng Yun (云春峰)
  0 siblings, 1 reply; 10+ messages in thread
From: Vinod Koul @ 2022-11-24 17:47 UTC (permalink / raw)
  To: Chunfeng Yun
  Cc: Kishon Vijay Abraham I, Matthias Brugger, Nathan Chancellor,
	Nick Desaulniers, Tom Rix, AngeloGioacchino Del Regno,
	linux-arm-kernel, linux-mediatek, linux-phy, linux-kernel, llvm,
	Eddie Hung, Tianping Fang

On 10-11-22, 21:27, Chunfeng Yun wrote:
> These debugfs files are mainly used to make eye diagram test easier,
> especially helpful to do HQA test for a new IC without efuse enabled.
> 
> Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
> ---
> v4: fix build warning of sometimes uninitialized variable
> 
> v3: fix typo of "debugfs" suggested by AngeloGioacchino
> 
> v2: add CONFIG_PHY_MTK_TPHY_DEBUGFS suggested by AngeloGioacchino
> ---
>  drivers/phy/mediatek/Kconfig        |   5 +
>  drivers/phy/mediatek/phy-mtk-tphy.c | 405 +++++++++++++++++++++++++++-
>  2 files changed, 409 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/phy/mediatek/Kconfig b/drivers/phy/mediatek/Kconfig
> index 3125ecb5d119..e9fdfe9f519f 100644
> --- a/drivers/phy/mediatek/Kconfig
> +++ b/drivers/phy/mediatek/Kconfig
> @@ -27,6 +27,11 @@ config PHY_MTK_TPHY
>  	  multi-ports is first version, otherwise is second version,
>  	  so you can easily distinguish them by banks layout.
>  
> +config PHY_MTK_TPHY_DEBUGFS
> +	bool "Add T-PHY Debugfs Files"
> +	help
> +	  Say Y here to add debugfs files mainly for T-PHY HQA test.

Why do we need a config option for this, is debugfs config option not
sufficient?

> +
>  config PHY_MTK_UFS
>  	tristate "MediaTek UFS M-PHY driver"
>  	depends on ARCH_MEDIATEK || COMPILE_TEST
> diff --git a/drivers/phy/mediatek/phy-mtk-tphy.c b/drivers/phy/mediatek/phy-mtk-tphy.c
> index e906a82791bd..f220a9a409bf 100644
> --- a/drivers/phy/mediatek/phy-mtk-tphy.c
> +++ b/drivers/phy/mediatek/phy-mtk-tphy.c
> @@ -7,6 +7,7 @@
>  
>  #include <dt-bindings/phy/phy.h>
>  #include <linux/clk.h>
> +#include <linux/debugfs.h>
>  #include <linux/delay.h>
>  #include <linux/iopoll.h>
>  #include <linux/mfd/syscon.h>
> @@ -264,6 +265,8 @@
>  
>  #define TPHY_CLKS_CNT	2
>  
> +#define USER_BUF_LEN(count) min_t(size_t, 8, (count))
> +
>  enum mtk_phy_version {
>  	MTK_PHY_V1 = 1,
>  	MTK_PHY_V2,
> @@ -310,6 +313,7 @@ struct mtk_phy_instance {
>  	struct clk_bulk_data clks[TPHY_CLKS_CNT];
>  	u32 index;
>  	u32 type;
> +	struct dentry *dbgfs;
>  	struct regmap *type_sw;
>  	u32 type_sw_reg;
>  	u32 type_sw_index;
> @@ -332,10 +336,391 @@ struct mtk_tphy {
>  	const struct mtk_phy_pdata *pdata;
>  	struct mtk_phy_instance **phys;
>  	int nphys;
> +	struct dentry *dbgfs_root;
>  	int src_ref_clk; /* MHZ, reference clock for slew rate calibrate */
>  	int src_coef; /* coefficient for slew rate calibrate */
>  };
>  
> +#if IS_ENABLED(CONFIG_PHY_MTK_TPHY_DEBUGFS)
> +
> +enum u2_phy_params {
> +	U2P_EYE_VRT = 0,
> +	U2P_EYE_TERM,
> +	U2P_EFUSE_EN,
> +	U2P_EFUSE_INTR,
> +	U2P_DISCTH,
> +	U2P_PRE_EMPHASIS,
> +};
> +
> +enum u3_phy_params {
> +	U3P_EFUSE_EN = 0,
> +	U3P_EFUSE_INTR,
> +	U3P_EFUSE_TX_IMP,
> +	U3P_EFUSE_RX_IMP,
> +};
> +
> +static const char *const u2_phy_files[] = {
> +	[U2P_EYE_VRT] = "vrt",
> +	[U2P_EYE_TERM] = "term",
> +	[U2P_EFUSE_EN] = "efuse",
> +	[U2P_EFUSE_INTR] = "intr",
> +	[U2P_DISCTH] = "discth",
> +	[U2P_PRE_EMPHASIS] = "preemph",
> +};
> +
> +static const char *const u3_phy_files[] = {
> +	[U3P_EFUSE_EN] = "efuse",
> +	[U3P_EFUSE_INTR] = "intr",
> +	[U3P_EFUSE_TX_IMP] = "tx-imp",
> +	[U3P_EFUSE_RX_IMP] = "rx-imp",
> +};
> +
> +static int u2_phy_params_show(struct seq_file *sf, void *unused)
> +{
> +	struct mtk_phy_instance *inst = sf->private;
> +	const char *fname = file_dentry(sf->file)->d_iname;
> +	struct u2phy_banks *u2_banks = &inst->u2_banks;
> +	void __iomem *com = u2_banks->com;
> +	u32 max = 0;
> +	u32 tmp = 0;
> +	u32 val = 0;
> +	int ret;
> +
> +	ret = match_string(u2_phy_files, ARRAY_SIZE(u2_phy_files), fname);
> +	if (ret < 0)
> +		return ret;
> +
> +	switch (ret) {
> +	case U2P_EYE_VRT:
> +		tmp = readl(com + U3P_USBPHYACR1);
> +		val = FIELD_GET(PA1_RG_VRT_SEL, tmp);
> +		max = FIELD_MAX(PA1_RG_VRT_SEL);
> +		break;
> +
> +	case U2P_EYE_TERM:
> +		tmp = readl(com + U3P_USBPHYACR1);
> +		val = FIELD_GET(PA1_RG_TERM_SEL, tmp);
> +		max = FIELD_MAX(PA1_RG_TERM_SEL);
> +		break;
> +
> +	case U2P_EFUSE_EN:
> +		if (u2_banks->misc) {
> +			tmp = readl(u2_banks->misc + U3P_MISC_REG1);
> +			max = 1;
> +		}
> +
> +		val = !!(tmp & MR1_EFUSE_AUTO_LOAD_DIS);
> +		break;
> +
> +	case U2P_EFUSE_INTR:
> +		tmp = readl(com + U3P_USBPHYACR1);
> +		val = FIELD_GET(PA1_RG_INTR_CAL, tmp);
> +		max = FIELD_MAX(PA1_RG_INTR_CAL);
> +		break;
> +
> +	case U2P_DISCTH:
> +		tmp = readl(com + U3P_USBPHYACR6);
> +		val = FIELD_GET(PA6_RG_U2_DISCTH, tmp);
> +		max = FIELD_MAX(PA6_RG_U2_DISCTH);
> +		break;
> +
> +	case U2P_PRE_EMPHASIS:
> +		tmp = readl(com + U3P_USBPHYACR6);
> +		val = FIELD_GET(PA6_RG_U2_PRE_EMP, tmp);
> +		max = FIELD_MAX(PA6_RG_U2_PRE_EMP);
> +		break;
> +
> +	default:
> +		seq_printf(sf, "invalid, %d\n", ret);
> +		break;
> +	}
> +
> +	seq_printf(sf, "%s : %d [0, %d]\n", fname, val, max);
> +
> +	return 0;
> +}
> +
> +static int u2_phy_params_open(struct inode *inode, struct file *file)
> +{
> +	return single_open(file, u2_phy_params_show, inode->i_private);
> +}
> +
> +static ssize_t u2_phy_params_write(struct file *file, const char __user *ubuf,
> +				   size_t count, loff_t *ppos)

so are we writing to phy registers from userspace, why?

> +{
> +	const char *fname = file_dentry(file)->d_iname;
> +	struct seq_file *sf = file->private_data;
> +	struct mtk_phy_instance *inst = sf->private;
> +	struct u2phy_banks *u2_banks = &inst->u2_banks;
> +	void __iomem *com = u2_banks->com;
> +	ssize_t rc;
> +	u32 val;
> +	int ret;
> +
> +	rc = kstrtouint_from_user(ubuf, USER_BUF_LEN(count), 0, &val);
> +	if (rc)
> +		return rc;
> +
> +	ret = match_string(u2_phy_files, ARRAY_SIZE(u2_phy_files), fname);
> +	if (ret < 0)
> +		return (ssize_t)ret;
> +
> +	switch (ret) {
> +	case U2P_EYE_VRT:
> +		mtk_phy_update_field(com + U3P_USBPHYACR1, PA1_RG_VRT_SEL, val);
> +		break;
> +
> +	case U2P_EYE_TERM:
> +		mtk_phy_update_field(com + U3P_USBPHYACR1, PA1_RG_TERM_SEL, val);
> +		break;
> +
> +	case U2P_EFUSE_EN:
> +		if (u2_banks->misc)
> +			mtk_phy_update_field(u2_banks->misc + U3P_MISC_REG1,
> +					     MR1_EFUSE_AUTO_LOAD_DIS, !!val);
> +		break;
> +
> +	case U2P_EFUSE_INTR:
> +		mtk_phy_update_field(com + U3P_USBPHYACR1, PA1_RG_INTR_CAL, val);
> +		break;
> +
> +	case U2P_DISCTH:
> +		mtk_phy_update_field(com + U3P_USBPHYACR6, PA6_RG_U2_DISCTH, val);
> +		break;
> +
> +	case U2P_PRE_EMPHASIS:
> +		mtk_phy_update_field(com + U3P_USBPHYACR6, PA6_RG_U2_PRE_EMP, val);
> +		break;
> +
> +	default:
> +		break;
> +	}
> +
> +	return count;
> +}
> +
> +static const struct file_operations u2_phy_fops = {
> +	.open = u2_phy_params_open,
> +	.write = u2_phy_params_write,
> +	.read = seq_read,
> +	.llseek = seq_lseek,
> +	.release = single_release,
> +};
> +
> +static void u2_phy_dbgfs_files_create(struct mtk_phy_instance *inst)
> +{
> +	u32 count = ARRAY_SIZE(u2_phy_files);
> +	int i;
> +
> +	for (i = 0; i < count; i++)
> +		debugfs_create_file(u2_phy_files[i], 0644, inst->dbgfs, inst, &u2_phy_fops);

pls use 
> +}
> +
> +static int u3_phy_params_show(struct seq_file *sf, void *unused)
> +{
> +	struct mtk_phy_instance *inst = sf->private;
> +	const char *fname = file_dentry(sf->file)->d_iname;
> +	struct u3phy_banks *u3_banks = &inst->u3_banks;
> +	u32 val = 0;
> +	u32 max = 0;
> +	u32 tmp;
> +	int ret;
> +
> +	ret = match_string(u3_phy_files, ARRAY_SIZE(u3_phy_files), fname);
> +	if (ret < 0)
> +		return ret;
> +
> +	switch (ret) {
> +	case U3P_EFUSE_EN:
> +		tmp = readl(u3_banks->phyd + U3P_U3_PHYD_RSV);
> +		val = !!(tmp & P3D_RG_EFUSE_AUTO_LOAD_DIS);
> +		max = 1;
> +		break;
> +
> +	case U3P_EFUSE_INTR:
> +		tmp = readl(u3_banks->phya + U3P_U3_PHYA_REG0);
> +		val = FIELD_GET(P3A_RG_IEXT_INTR, tmp);
> +		max = FIELD_MAX(P3A_RG_IEXT_INTR);
> +		break;
> +
> +	case U3P_EFUSE_TX_IMP:
> +		tmp = readl(u3_banks->phyd + U3P_U3_PHYD_IMPCAL0);
> +		val = FIELD_GET(P3D_RG_TX_IMPEL, tmp);
> +		max = FIELD_MAX(P3D_RG_TX_IMPEL);
> +		break;
> +
> +	case U3P_EFUSE_RX_IMP:
> +		tmp = readl(u3_banks->phyd + U3P_U3_PHYD_IMPCAL1);
> +		val = FIELD_GET(P3D_RG_RX_IMPEL, tmp);
> +		max = FIELD_MAX(P3D_RG_RX_IMPEL);
> +		break;
> +
> +	default:
> +		seq_printf(sf, "invalid, %d\n", ret);
> +		break;
> +	}
> +
> +	seq_printf(sf, "%s : %d [0, %d]\n", fname, val, max);
> +
> +	return 0;
> +}
> +
> +static int u3_phy_params_open(struct inode *inode, struct file *file)
> +{
> +	return single_open(file, u3_phy_params_show, inode->i_private);
> +}
> +
> +static ssize_t u3_phy_params_write(struct file *file, const char __user *ubuf,
> +				   size_t count, loff_t *ppos)
> +{
> +	const char *fname = file_dentry(file)->d_iname;
> +	struct seq_file *sf = file->private_data;
> +	struct mtk_phy_instance *inst = sf->private;
> +	struct u3phy_banks *u3_banks = &inst->u3_banks;
> +	void __iomem *phyd = u3_banks->phyd;
> +	ssize_t rc;
> +	u32 val;
> +	int ret;
> +
> +	rc = kstrtouint_from_user(ubuf, USER_BUF_LEN(count), 0, &val);
> +	if (rc)
> +		return rc;
> +
> +	ret = match_string(u3_phy_files, ARRAY_SIZE(u3_phy_files), fname);
> +	if (ret < 0)
> +		return (ssize_t)ret;
> +
> +	switch (ret) {
> +	case U3P_EFUSE_EN:
> +		mtk_phy_update_field(phyd + U3P_U3_PHYD_RSV,
> +				     P3D_RG_EFUSE_AUTO_LOAD_DIS, !!val);
> +		break;
> +
> +	case U3P_EFUSE_INTR:
> +		mtk_phy_update_field(u3_banks->phya + U3P_U3_PHYA_REG0, P3A_RG_IEXT_INTR, val);
> +		break;
> +
> +	case U3P_EFUSE_TX_IMP:
> +		mtk_phy_update_field(phyd + U3P_U3_PHYD_IMPCAL0, P3D_RG_TX_IMPEL, val);
> +		mtk_phy_set_bits(phyd + U3P_U3_PHYD_IMPCAL0, P3D_RG_FORCE_TX_IMPEL);
> +		break;
> +
> +	case U3P_EFUSE_RX_IMP:
> +		mtk_phy_update_field(phyd + U3P_U3_PHYD_IMPCAL1, P3D_RG_RX_IMPEL, val);
> +		mtk_phy_set_bits(phyd + U3P_U3_PHYD_IMPCAL1, P3D_RG_FORCE_RX_IMPEL);
> +		break;
> +
> +	default:
> +		break;
> +	}
> +
> +	return count;
> +}
> +
> +static const struct file_operations u3_phy_fops = {
> +	.open = u3_phy_params_open,
> +	.write = u3_phy_params_write,
> +	.read = seq_read,
> +	.llseek = seq_lseek,
> +	.release = single_release,
> +};
> +
> +static void u3_phy_dbgfs_files_create(struct mtk_phy_instance *inst)
> +{
> +	u32 count = ARRAY_SIZE(u3_phy_files);
> +	int i;
> +
> +	for (i = 0; i < count; i++)
> +		debugfs_create_file(u3_phy_files[i], 0644, inst->dbgfs, inst, &u3_phy_fops);
> +}
> +
> +static int tphy_type_show(struct seq_file *sf, void *unused)
> +{
> +	struct mtk_phy_instance *inst = sf->private;
> +	const char *type;
> +
> +	switch (inst->type) {
> +	case PHY_TYPE_USB2:
> +		type = "USB2";
> +		break;
> +	case PHY_TYPE_USB3:
> +		type = "USB3";
> +		break;
> +	case PHY_TYPE_PCIE:
> +		type = "PCIe";
> +		break;
> +	case PHY_TYPE_SGMII:
> +		type = "SGMII";
> +		break;
> +	case PHY_TYPE_SATA:
> +		type = "SATA";
> +		break;
> +	default:
> +		type = "";
> +	}
> +
> +	seq_printf(sf, "%s\n", type);
> +
> +	return 0;
> +}
> +
> +DEFINE_SHOW_ATTRIBUTE(tphy_type);
> +
> +static void tphy_debugfs_init(struct mtk_tphy *tphy, struct mtk_phy_instance *inst)
> +{
> +	char name[16];
> +
> +	snprintf(name, sizeof(name) - 1, "phy.%d", inst->index);
> +	inst->dbgfs = debugfs_create_dir(name, tphy->dbgfs_root);
> +
> +	debugfs_create_file("type", 0444, inst->dbgfs, inst, &tphy_type_fops);
> +
> +	switch (inst->type) {
> +	case PHY_TYPE_USB2:
> +		u2_phy_dbgfs_files_create(inst);
> +		break;
> +	case PHY_TYPE_USB3:
> +	case PHY_TYPE_PCIE:
> +		u3_phy_dbgfs_files_create(inst);
> +		break;
> +	default:
> +		break;
> +	}
> +}
> +
> +static void tphy_debugfs_exit(struct mtk_phy_instance *inst)
> +{
> +	debugfs_remove_recursive(inst->dbgfs);
> +	inst->dbgfs = NULL;
> +}
> +
> +static void tphy_debugfs_root_create(struct mtk_tphy *tphy)
> +{
> +	tphy->dbgfs_root = debugfs_create_dir(dev_name(tphy->dev), phy_debug_root);
> +}
> +
> +static void tphy_debugfs_root_remove(struct mtk_tphy *tphy)
> +{
> +	debugfs_remove_recursive(tphy->dbgfs_root);
> +	tphy->dbgfs_root = NULL;
> +}
> +
> +#else
> +
> +static void tphy_debugfs_init(struct mtk_tphy *tphy, struct mtk_phy_instance *inst)
> +{}
> +
> +static void tphy_debugfs_exit(struct mtk_phy_instance *inst)
> +{}
> +
> +static void tphy_debugfs_root_create(struct mtk_tphy *tphy)
> +{}
> +
> +static void tphy_debugfs_root_remove(struct mtk_tphy *tphy)
> +{}
> +
> +#endif
> +
>  static void hs_slew_rate_calibrate(struct mtk_tphy *tphy,
>  	struct mtk_phy_instance *instance)
>  {
> @@ -1032,6 +1417,8 @@ static int mtk_phy_init(struct phy *phy)
>  		return -EINVAL;
>  	}
>  
> +	tphy_debugfs_init(tphy, instance);
> +
>  	return 0;
>  }
>  
> @@ -1068,6 +1455,8 @@ static int mtk_phy_exit(struct phy *phy)
>  	struct mtk_phy_instance *instance = phy_get_drvdata(phy);
>  	struct mtk_tphy *tphy = dev_get_drvdata(phy->dev.parent);
>  
> +	tphy_debugfs_exit(instance);
> +
>  	if (instance->type == PHY_TYPE_USB2)
>  		u2_phy_instance_exit(tphy, instance);
>  
> @@ -1295,15 +1684,29 @@ static int mtk_tphy_probe(struct platform_device *pdev)
>  	}
>  
>  	provider = devm_of_phy_provider_register(dev, mtk_phy_xlate);
> +	if (IS_ERR(provider))
> +		return dev_err_probe(dev, PTR_ERR(provider), "probe failed\n");
> +
> +	tphy_debugfs_root_create(tphy);
> +	return 0;
>  
> -	return PTR_ERR_OR_ZERO(provider);
>  put_child:
>  	of_node_put(child_np);
>  	return retval;
>  }
>  
> +static int mtk_tphy_remove(struct platform_device *pdev)
> +{
> +	struct mtk_tphy *tphy;
> +
> +	tphy = platform_get_drvdata(pdev);
> +	tphy_debugfs_root_remove(tphy);
> +	return 0;
> +}
> +
>  static struct platform_driver mtk_tphy_driver = {
>  	.probe		= mtk_tphy_probe,
> +	.remove		= mtk_tphy_remove,
>  	.driver		= {
>  		.name	= "mtk-tphy",
>  		.of_match_table = mtk_tphy_id_table,
> -- 
> 2.18.0

-- 
~Vinod

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v4 2/3] phy: core: add debugfs root
  2022-11-24 17:39   ` Vinod Koul
@ 2022-11-28  7:00     ` Chunfeng Yun (云春峰)
  0 siblings, 0 replies; 10+ messages in thread
From: Chunfeng Yun (云春峰) @ 2022-11-28  7:00 UTC (permalink / raw)
  To: vkoul
  Cc: llvm, linux-mediatek, linux-kernel, nathan, kishon,
	Eddie Hung (洪正鑫),
	Tianping Fang (方天平),
	linux-arm-kernel, matthias.bgg, linux-phy, trix,
	angelogioacchino.delregno, ndesaulniers

On Thu, 2022-11-24 at 23:09 +0530, Vinod Koul wrote:
> On 10-11-22, 21:27, Chunfeng Yun wrote:
> > Add a debugfs root for phy class, then phy drivers can add debugfs
> > files
> > under this folder.
> > 
> > Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
> > ---
> > v2~v4: no changes
> > ---
> >  drivers/phy/phy-core.c  | 6 ++++++
> >  include/linux/phy/phy.h | 2 ++
> >  2 files changed, 8 insertions(+)
> > 
> > diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c
> > index d93ddf1262c5..2f9f69190519 100644
> > --- a/drivers/phy/phy-core.c
> > +++ b/drivers/phy/phy-core.c
> > @@ -11,6 +11,7 @@
> >  #include <linux/export.h>
> >  #include <linux/module.h>
> >  #include <linux/err.h>
> > +#include <linux/debugfs.h>
> >  #include <linux/device.h>
> >  #include <linux/slab.h>
> >  #include <linux/of.h>
> > @@ -1204,6 +1205,9 @@ void devm_of_phy_provider_unregister(struct
> > device *dev,
> >  }
> >  EXPORT_SYMBOL_GPL(devm_of_phy_provider_unregister);
> >  
> > +struct dentry *phy_debug_root;
> > +EXPORT_SYMBOL_GPL(phy_debug_root);
> 
> Why expose this to whole world? Alternate approach would be to add
> this
> in struct phy
If only add it in struct phy, many phy folders will be created under
/sys/kernel/debug/, and create them under /sys/kernel/debug/phy seems
more clearer, this also follows other class, such as usb

> 
> > +
> >  /**
> >   * phy_release() - release the phy
> >   * @dev: the dev member within phy
> > @@ -1233,6 +1237,8 @@ static int __init phy_core_init(void)
> >  
> >  	phy_class->dev_release = phy_release;
> >  
> > +	phy_debug_root = debugfs_create_dir("phy", NULL);
> > +
> >  	return 0;
> >  }
> >  device_initcall(phy_core_init);
> > diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h
> > index b1413757fcc3..c398749d49b9 100644
> > --- a/include/linux/phy/phy.h
> > +++ b/include/linux/phy/phy.h
> > @@ -205,6 +205,8 @@ struct phy_lookup {
> >  #define devm_of_phy_provider_register_full(dev, children, xlate) \
> >  	__devm_of_phy_provider_register(dev, children, THIS_MODULE,
> > xlate)
> >  
> > +extern struct dentry *phy_debug_root;
> > +
> >  static inline void phy_set_drvdata(struct phy *phy, void *data)
> >  {
> >  	dev_set_drvdata(&phy->dev, data);
> > -- 
> > 2.18.0
> 
> 

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v4 3/3] phy: mediatek: tphy: add debugfs files
  2022-11-24 17:47   ` Vinod Koul
@ 2022-11-28  7:26     ` Chunfeng Yun (云春峰)
  2022-11-28 14:00       ` Andrew Lunn
  0 siblings, 1 reply; 10+ messages in thread
From: Chunfeng Yun (云春峰) @ 2022-11-28  7:26 UTC (permalink / raw)
  To: vkoul
  Cc: llvm, linux-mediatek, linux-kernel, nathan, kishon,
	Eddie Hung (洪正鑫),
	Tianping Fang (方天平),
	linux-arm-kernel, matthias.bgg, linux-phy, trix,
	angelogioacchino.delregno, ndesaulniers

On Thu, 2022-11-24 at 23:17 +0530, Vinod Koul wrote:
> On 10-11-22, 21:27, Chunfeng Yun wrote:
> > These debugfs files are mainly used to make eye diagram test
> > easier,
> > especially helpful to do HQA test for a new IC without efuse
> > enabled.
> > 
> > Signed-off-by: Chunfeng Yun <chunfeng.yun@mediatek.com>
> > ---
> > v4: fix build warning of sometimes uninitialized variable
> > 
> > v3: fix typo of "debugfs" suggested by AngeloGioacchino
> > 
> > v2: add CONFIG_PHY_MTK_TPHY_DEBUGFS suggested by AngeloGioacchino
> > ---
> >  drivers/phy/mediatek/Kconfig        |   5 +
> >  drivers/phy/mediatek/phy-mtk-tphy.c | 405
> > +++++++++++++++++++++++++++-
> >  2 files changed, 409 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/phy/mediatek/Kconfig
> > b/drivers/phy/mediatek/Kconfig
> > index 3125ecb5d119..e9fdfe9f519f 100644
> > --- a/drivers/phy/mediatek/Kconfig
> > +++ b/drivers/phy/mediatek/Kconfig
> > @@ -27,6 +27,11 @@ config PHY_MTK_TPHY
> >  	  multi-ports is first version, otherwise is second version,
> >  	  so you can easily distinguish them by banks layout.
> >  
> > +config PHY_MTK_TPHY_DEBUGFS
> > +	bool "Add T-PHY Debugfs Files"
> > +	help
> > +	  Say Y here to add debugfs files mainly for T-PHY HQA test.
> 
> Why do we need a config option for this, is debugfs config option not
> sufficient?
We may want to disable these files even debugfs config is enabled in
release image, and prefer to use them only when bring up new IC. 

> 
> > +
> >  config PHY_MTK_UFS
> >  	tristate "MediaTek UFS M-PHY driver"
> >  	depends on ARCH_MEDIATEK || COMPILE_TEST
> > diff --git a/drivers/phy/mediatek/phy-mtk-tphy.c
> > b/drivers/phy/mediatek/phy-mtk-tphy.c
> > index e906a82791bd..f220a9a409bf 100644
> > --- a/drivers/phy/mediatek/phy-mtk-tphy.c
> > +++ b/drivers/phy/mediatek/phy-mtk-tphy.c
> > @@ -7,6 +7,7 @@
> >  
> >  #include <dt-bindings/phy/phy.h>
> >  #include <linux/clk.h>
> > +#include <linux/debugfs.h>
> >  #include <linux/delay.h>
> >  #include <linux/iopoll.h>
> >  #include <linux/mfd/syscon.h>
> > @@ -264,6 +265,8 @@
> >  
> >  #define TPHY_CLKS_CNT	2
> >  
> > +#define USER_BUF_LEN(count) min_t(size_t, 8, (count))
> > +
> >  enum mtk_phy_version {
> >  	MTK_PHY_V1 = 1,
> >  	MTK_PHY_V2,
> > @@ -310,6 +313,7 @@ struct mtk_phy_instance {
> >  	struct clk_bulk_data clks[TPHY_CLKS_CNT];
> >  	u32 index;
> >  	u32 type;
> > +	struct dentry *dbgfs;
> >  	struct regmap *type_sw;
> >  	u32 type_sw_reg;
> >  	u32 type_sw_index;
> > @@ -332,10 +336,391 @@ struct mtk_tphy {
> >  	const struct mtk_phy_pdata *pdata;
> >  	struct mtk_phy_instance **phys;
> >  	int nphys;
> > +	struct dentry *dbgfs_root;
> >  	int src_ref_clk; /* MHZ, reference clock for slew rate
> > calibrate */
> >  	int src_coef; /* coefficient for slew rate calibrate */
> >  };
> >  
> > +#if IS_ENABLED(CONFIG_PHY_MTK_TPHY_DEBUGFS)
> > +
> > +enum u2_phy_params {
> > +	U2P_EYE_VRT = 0,
> > +	U2P_EYE_TERM,
> > +	U2P_EFUSE_EN,
> > +	U2P_EFUSE_INTR,
> > +	U2P_DISCTH,
> > +	U2P_PRE_EMPHASIS,
> > +};
> > +
> > +enum u3_phy_params {
> > +	U3P_EFUSE_EN = 0,
> > +	U3P_EFUSE_INTR,
> > +	U3P_EFUSE_TX_IMP,
> > +	U3P_EFUSE_RX_IMP,
> > +};
> > +
> > +static const char *const u2_phy_files[] = {
> > +	[U2P_EYE_VRT] = "vrt",
> > +	[U2P_EYE_TERM] = "term",
> > +	[U2P_EFUSE_EN] = "efuse",
> > +	[U2P_EFUSE_INTR] = "intr",
> > +	[U2P_DISCTH] = "discth",
> > +	[U2P_PRE_EMPHASIS] = "preemph",
> > +};
> > +
> > +static const char *const u3_phy_files[] = {
> > +	[U3P_EFUSE_EN] = "efuse",
> > +	[U3P_EFUSE_INTR] = "intr",
> > +	[U3P_EFUSE_TX_IMP] = "tx-imp",
> > +	[U3P_EFUSE_RX_IMP] = "rx-imp",
> > +};
> > +
> > +static int u2_phy_params_show(struct seq_file *sf, void *unused)
> > +{
> > +	struct mtk_phy_instance *inst = sf->private;
> > +	const char *fname = file_dentry(sf->file)->d_iname;
> > +	struct u2phy_banks *u2_banks = &inst->u2_banks;
> > +	void __iomem *com = u2_banks->com;
> > +	u32 max = 0;
> > +	u32 tmp = 0;
> > +	u32 val = 0;
> > +	int ret;
> > +
> > +	ret = match_string(u2_phy_files, ARRAY_SIZE(u2_phy_files),
> > fname);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	switch (ret) {
> > +	case U2P_EYE_VRT:
> > +		tmp = readl(com + U3P_USBPHYACR1);
> > +		val = FIELD_GET(PA1_RG_VRT_SEL, tmp);
> > +		max = FIELD_MAX(PA1_RG_VRT_SEL);
> > +		break;
> > +
> > +	case U2P_EYE_TERM:
> > +		tmp = readl(com + U3P_USBPHYACR1);
> > +		val = FIELD_GET(PA1_RG_TERM_SEL, tmp);
> > +		max = FIELD_MAX(PA1_RG_TERM_SEL);
> > +		break;
> > +
> > +	case U2P_EFUSE_EN:
> > +		if (u2_banks->misc) {
> > +			tmp = readl(u2_banks->misc + U3P_MISC_REG1);
> > +			max = 1;
> > +		}
> > +
> > +		val = !!(tmp & MR1_EFUSE_AUTO_LOAD_DIS);
> > +		break;
> > +
> > +	case U2P_EFUSE_INTR:
> > +		tmp = readl(com + U3P_USBPHYACR1);
> > +		val = FIELD_GET(PA1_RG_INTR_CAL, tmp);
> > +		max = FIELD_MAX(PA1_RG_INTR_CAL);
> > +		break;
> > +
> > +	case U2P_DISCTH:
> > +		tmp = readl(com + U3P_USBPHYACR6);
> > +		val = FIELD_GET(PA6_RG_U2_DISCTH, tmp);
> > +		max = FIELD_MAX(PA6_RG_U2_DISCTH);
> > +		break;
> > +
> > +	case U2P_PRE_EMPHASIS:
> > +		tmp = readl(com + U3P_USBPHYACR6);
> > +		val = FIELD_GET(PA6_RG_U2_PRE_EMP, tmp);
> > +		max = FIELD_MAX(PA6_RG_U2_PRE_EMP);
> > +		break;
> > +
> > +	default:
> > +		seq_printf(sf, "invalid, %d\n", ret);
> > +		break;
> > +	}
> > +
> > +	seq_printf(sf, "%s : %d [0, %d]\n", fname, val, max);
> > +
> > +	return 0;
> > +}
> > +
> > +static int u2_phy_params_open(struct inode *inode, struct file
> > *file)
> > +{
> > +	return single_open(file, u2_phy_params_show, inode->i_private);
> > +}
> > +
> > +static ssize_t u2_phy_params_write(struct file *file, const char
> > __user *ubuf,
> > +				   size_t count, loff_t *ppos)
> 
> so are we writing to phy registers from userspace, why?
Mainly because when bring up a new ic which efuse is not set, we need
to tune some parameters many times for eye diagram test, using debugfs
files will make it easier at runtime.

Thanks a lot

> 
> > +{
> > +	const char *fname = file_dentry(file)->d_iname;
> > +	struct seq_file *sf = file->private_data;
> > +	struct mtk_phy_instance *inst = sf->private;
> > +	struct u2phy_banks *u2_banks = &inst->u2_banks;
> > +	void __iomem *com = u2_banks->com;
> > +	ssize_t rc;
> > +	u32 val;
> > +	int ret;
> > +
> > +	rc = kstrtouint_from_user(ubuf, USER_BUF_LEN(count), 0, &val);
> > +	if (rc)
> > +		return rc;
> > +
> > +	ret = match_string(u2_phy_files, ARRAY_SIZE(u2_phy_files),
> > fname);
> > +	if (ret < 0)
> > +		return (ssize_t)ret;
> > +
> > +	switch (ret) {
> > +	case U2P_EYE_VRT:
> > +		mtk_phy_update_field(com + U3P_USBPHYACR1,
> > PA1_RG_VRT_SEL, val);
> > +		break;
> > +
> > +	case U2P_EYE_TERM:
> > +		mtk_phy_update_field(com + U3P_USBPHYACR1,
> > PA1_RG_TERM_SEL, val);
> > +		break;
> > +
> > +	case U2P_EFUSE_EN:
> > +		if (u2_banks->misc)
> > +			mtk_phy_update_field(u2_banks->misc +
> > U3P_MISC_REG1,
> > +					     MR1_EFUSE_AUTO_LOAD_DIS,
> > !!val);
> > +		break;
> > +
> > +	case U2P_EFUSE_INTR:
> > +		mtk_phy_update_field(com + U3P_USBPHYACR1,
> > PA1_RG_INTR_CAL, val);
> > +		break;
> > +
> > +	case U2P_DISCTH:
> > +		mtk_phy_update_field(com + U3P_USBPHYACR6,
> > PA6_RG_U2_DISCTH, val);
> > +		break;
> > +
> > +	case U2P_PRE_EMPHASIS:
> > +		mtk_phy_update_field(com + U3P_USBPHYACR6,
> > PA6_RG_U2_PRE_EMP, val);
> > +		break;
> > +
> > +	default:
> > +		break;
> > +	}
> > +
> > +	return count;
> > +}
> > +
> > +static const struct file_operations u2_phy_fops = {
> > +	.open = u2_phy_params_open,
> > +	.write = u2_phy_params_write,
> > +	.read = seq_read,
> > +	.llseek = seq_lseek,
> > +	.release = single_release,
> > +};
> > +
> > +static void u2_phy_dbgfs_files_create(struct mtk_phy_instance
> > *inst)
> > +{
> > +	u32 count = ARRAY_SIZE(u2_phy_files);
> > +	int i;
> > +
> > +	for (i = 0; i < count; i++)
> > +		debugfs_create_file(u2_phy_files[i], 0644, inst->dbgfs, 
> > inst, &u2_phy_fops);
> 
> pls use 
> > +}
> > +
> > +static int u3_phy_params_show(struct seq_file *sf, void *unused)
> > +{
> > +	struct mtk_phy_instance *inst = sf->private;
> > +	const char *fname = file_dentry(sf->file)->d_iname;
> > +	struct u3phy_banks *u3_banks = &inst->u3_banks;
> > +	u32 val = 0;
> > +	u32 max = 0;
> > +	u32 tmp;
> > +	int ret;
> > +
> > +	ret = match_string(u3_phy_files, ARRAY_SIZE(u3_phy_files),
> > fname);
> > +	if (ret < 0)
> > +		return ret;
> > +
> > +	switch (ret) {
> > +	case U3P_EFUSE_EN:
> > +		tmp = readl(u3_banks->phyd + U3P_U3_PHYD_RSV);
> > +		val = !!(tmp & P3D_RG_EFUSE_AUTO_LOAD_DIS);
> > +		max = 1;
> > +		break;
> > +
> > +	case U3P_EFUSE_INTR:
> > +		tmp = readl(u3_banks->phya + U3P_U3_PHYA_REG0);
> > +		val = FIELD_GET(P3A_RG_IEXT_INTR, tmp);
> > +		max = FIELD_MAX(P3A_RG_IEXT_INTR);
> > +		break;
> > +
> > +	case U3P_EFUSE_TX_IMP:
> > +		tmp = readl(u3_banks->phyd + U3P_U3_PHYD_IMPCAL0);
> > +		val = FIELD_GET(P3D_RG_TX_IMPEL, tmp);
> > +		max = FIELD_MAX(P3D_RG_TX_IMPEL);
> > +		break;
> > +
> > +	case U3P_EFUSE_RX_IMP:
> > +		tmp = readl(u3_banks->phyd + U3P_U3_PHYD_IMPCAL1);
> > +		val = FIELD_GET(P3D_RG_RX_IMPEL, tmp);
> > +		max = FIELD_MAX(P3D_RG_RX_IMPEL);
> > +		break;
> > +
> > +	default:
> > +		seq_printf(sf, "invalid, %d\n", ret);
> > +		break;
> > +	}
> > +
> > +	seq_printf(sf, "%s : %d [0, %d]\n", fname, val, max);
> > +
> > +	return 0;
> > +}
> > +
> > +static int u3_phy_params_open(struct inode *inode, struct file
> > *file)
> > +{
> > +	return single_open(file, u3_phy_params_show, inode->i_private);
> > +}
> > +
> > +static ssize_t u3_phy_params_write(struct file *file, const char
> > __user *ubuf,
> > +				   size_t count, loff_t *ppos)
> > +{
> > +	const char *fname = file_dentry(file)->d_iname;
> > +	struct seq_file *sf = file->private_data;
> > +	struct mtk_phy_instance *inst = sf->private;
> > +	struct u3phy_banks *u3_banks = &inst->u3_banks;
> > +	void __iomem *phyd = u3_banks->phyd;
> > +	ssize_t rc;
> > +	u32 val;
> > +	int ret;
> > +
> > +	rc = kstrtouint_from_user(ubuf, USER_BUF_LEN(count), 0, &val);
> > +	if (rc)
> > +		return rc;
> > +
> > +	ret = match_string(u3_phy_files, ARRAY_SIZE(u3_phy_files),
> > fname);
> > +	if (ret < 0)
> > +		return (ssize_t)ret;
> > +
> > +	switch (ret) {
> > +	case U3P_EFUSE_EN:
> > +		mtk_phy_update_field(phyd + U3P_U3_PHYD_RSV,
> > +				     P3D_RG_EFUSE_AUTO_LOAD_DIS,
> > !!val);
> > +		break;
> > +
> > +	case U3P_EFUSE_INTR:
> > +		mtk_phy_update_field(u3_banks->phya + U3P_U3_PHYA_REG0,
> > P3A_RG_IEXT_INTR, val);
> > +		break;
> > +
> > +	case U3P_EFUSE_TX_IMP:
> > +		mtk_phy_update_field(phyd + U3P_U3_PHYD_IMPCAL0,
> > P3D_RG_TX_IMPEL, val);
> > +		mtk_phy_set_bits(phyd + U3P_U3_PHYD_IMPCAL0,
> > P3D_RG_FORCE_TX_IMPEL);
> > +		break;
> > +
> > +	case U3P_EFUSE_RX_IMP:
> > +		mtk_phy_update_field(phyd + U3P_U3_PHYD_IMPCAL1,
> > P3D_RG_RX_IMPEL, val);
> > +		mtk_phy_set_bits(phyd + U3P_U3_PHYD_IMPCAL1,
> > P3D_RG_FORCE_RX_IMPEL);
> > +		break;
> > +
> > +	default:
> > +		break;
> > +	}
> > +
> > +	return count;
> > +}
> > +
> > +static const struct file_operations u3_phy_fops = {
> > +	.open = u3_phy_params_open,
> > +	.write = u3_phy_params_write,
> > +	.read = seq_read,
> > +	.llseek = seq_lseek,
> > +	.release = single_release,
> > +};
> > +
> > +static void u3_phy_dbgfs_files_create(struct mtk_phy_instance
> > *inst)
> > +{
> > +	u32 count = ARRAY_SIZE(u3_phy_files);
> > +	int i;
> > +
> > +	for (i = 0; i < count; i++)
> > +		debugfs_create_file(u3_phy_files[i], 0644, inst->dbgfs, 
> > inst, &u3_phy_fops);
> > +}
> > +
> > +static int tphy_type_show(struct seq_file *sf, void *unused)
> > +{
> > +	struct mtk_phy_instance *inst = sf->private;
> > +	const char *type;
> > +
> > +	switch (inst->type) {
> > +	case PHY_TYPE_USB2:
> > +		type = "USB2";
> > +		break;
> > +	case PHY_TYPE_USB3:
> > +		type = "USB3";
> > +		break;
> > +	case PHY_TYPE_PCIE:
> > +		type = "PCIe";
> > +		break;
> > +	case PHY_TYPE_SGMII:
> > +		type = "SGMII";
> > +		break;
> > +	case PHY_TYPE_SATA:
> > +		type = "SATA";
> > +		break;
> > +	default:
> > +		type = "";
> > +	}
> > +
> > +	seq_printf(sf, "%s\n", type);
> > +
> > +	return 0;
> > +}
> > +
> > +DEFINE_SHOW_ATTRIBUTE(tphy_type);
> > +
> > +static void tphy_debugfs_init(struct mtk_tphy *tphy, struct
> > mtk_phy_instance *inst)
> > +{
> > +	char name[16];
> > +
> > +	snprintf(name, sizeof(name) - 1, "phy.%d", inst->index);
> > +	inst->dbgfs = debugfs_create_dir(name, tphy->dbgfs_root);
> > +
> > +	debugfs_create_file("type", 0444, inst->dbgfs, inst,
> > &tphy_type_fops);
> > +
> > +	switch (inst->type) {
> > +	case PHY_TYPE_USB2:
> > +		u2_phy_dbgfs_files_create(inst);
> > +		break;
> > +	case PHY_TYPE_USB3:
> > +	case PHY_TYPE_PCIE:
> > +		u3_phy_dbgfs_files_create(inst);
> > +		break;
> > +	default:
> > +		break;
> > +	}
> > +}
> > +
> > +static void tphy_debugfs_exit(struct mtk_phy_instance *inst)
> > +{
> > +	debugfs_remove_recursive(inst->dbgfs);
> > +	inst->dbgfs = NULL;
> > +}
> > +
> > +static void tphy_debugfs_root_create(struct mtk_tphy *tphy)
> > +{
> > +	tphy->dbgfs_root = debugfs_create_dir(dev_name(tphy->dev),
> > phy_debug_root);
> > +}
> > +
> > +static void tphy_debugfs_root_remove(struct mtk_tphy *tphy)
> > +{
> > +	debugfs_remove_recursive(tphy->dbgfs_root);
> > +	tphy->dbgfs_root = NULL;
> > +}
> > +
> > +#else
> > +
> > +static void tphy_debugfs_init(struct mtk_tphy *tphy, struct
> > mtk_phy_instance *inst)
> > +{}
> > +
> > +static void tphy_debugfs_exit(struct mtk_phy_instance *inst)
> > +{}
> > +
> > +static void tphy_debugfs_root_create(struct mtk_tphy *tphy)
> > +{}
> > +
> > +static void tphy_debugfs_root_remove(struct mtk_tphy *tphy)
> > +{}
> > +
> > +#endif
> > +
> >  static void hs_slew_rate_calibrate(struct mtk_tphy *tphy,
> >  	struct mtk_phy_instance *instance)
> >  {
> > @@ -1032,6 +1417,8 @@ static int mtk_phy_init(struct phy *phy)
> >  		return -EINVAL;
> >  	}
> >  
> > +	tphy_debugfs_init(tphy, instance);
> > +
> >  	return 0;
> >  }
> >  
> > @@ -1068,6 +1455,8 @@ static int mtk_phy_exit(struct phy *phy)
> >  	struct mtk_phy_instance *instance = phy_get_drvdata(phy);
> >  	struct mtk_tphy *tphy = dev_get_drvdata(phy->dev.parent);
> >  
> > +	tphy_debugfs_exit(instance);
> > +
> >  	if (instance->type == PHY_TYPE_USB2)
> >  		u2_phy_instance_exit(tphy, instance);
> >  
> > @@ -1295,15 +1684,29 @@ static int mtk_tphy_probe(struct
> > platform_device *pdev)
> >  	}
> >  
> >  	provider = devm_of_phy_provider_register(dev, mtk_phy_xlate);
> > +	if (IS_ERR(provider))
> > +		return dev_err_probe(dev, PTR_ERR(provider), "probe
> > failed\n");
> > +
> > +	tphy_debugfs_root_create(tphy);
> > +	return 0;
> >  
> > -	return PTR_ERR_OR_ZERO(provider);
> >  put_child:
> >  	of_node_put(child_np);
> >  	return retval;
> >  }
> >  
> > +static int mtk_tphy_remove(struct platform_device *pdev)
> > +{
> > +	struct mtk_tphy *tphy;
> > +
> > +	tphy = platform_get_drvdata(pdev);
> > +	tphy_debugfs_root_remove(tphy);
> > +	return 0;
> > +}
> > +
> >  static struct platform_driver mtk_tphy_driver = {
> >  	.probe		= mtk_tphy_probe,
> > +	.remove		= mtk_tphy_remove,
> >  	.driver		= {
> >  		.name	= "mtk-tphy",
> >  		.of_match_table = mtk_tphy_id_table,
> > -- 
> > 2.18.0
> 
> 

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v4 3/3] phy: mediatek: tphy: add debugfs files
  2022-11-28  7:26     ` Chunfeng Yun (云春峰)
@ 2022-11-28 14:00       ` Andrew Lunn
  2022-12-03 14:53         ` Chunfeng Yun (云春峰)
  0 siblings, 1 reply; 10+ messages in thread
From: Andrew Lunn @ 2022-11-28 14:00 UTC (permalink / raw)
  To: Chunfeng Yun (云春峰)
  Cc: vkoul, llvm, linux-mediatek, linux-kernel, nathan, kishon,
	Eddie Hung (洪正鑫),
	Tianping Fang (方天平),
	linux-arm-kernel, matthias.bgg, linux-phy, trix,
	angelogioacchino.delregno, ndesaulniers

On Mon, Nov 28, 2022 at 07:26:02AM +0000, Chunfeng Yun (云春峰) wrote:
> On Thu, 2022-11-24 at 23:17 +0530, Vinod Koul wrote:
> > On 10-11-22, 21:27, Chunfeng Yun wrote:
> > > These debugfs files are mainly used to make eye diagram test
> > > easier,
> > > especially helpful to do HQA test for a new IC without efuse
> > > enabled.

Exporting data for eye diagrams seems like something many PHYs could
use. Please consider adding an official uniform API which any PHY
could use, so we don't end up with lots of incompatible formats in
debugfs.

	Andrew

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v4 3/3] phy: mediatek: tphy: add debugfs files
  2022-11-28 14:00       ` Andrew Lunn
@ 2022-12-03 14:53         ` Chunfeng Yun (云春峰)
  2022-12-03 15:38           ` Andrew Lunn
  0 siblings, 1 reply; 10+ messages in thread
From: Chunfeng Yun (云春峰) @ 2022-12-03 14:53 UTC (permalink / raw)
  To: andrew
  Cc: angelogioacchino.delregno, linux-kernel, linux-mediatek, nathan,
	kishon, Eddie Hung (洪正鑫),
	Tianping Fang (方天平),
	linux-arm-kernel, vkoul, matthias.bgg, linux-phy, llvm, trix,
	ndesaulniers

On Mon, 2022-11-28 at 15:00 +0100, Andrew Lunn wrote:
> On Mon, Nov 28, 2022 at 07:26:02AM +0000, Chunfeng Yun (云春峰) wrote:
> > On Thu, 2022-11-24 at 23:17 +0530, Vinod Koul wrote:
> > > On 10-11-22, 21:27, Chunfeng Yun wrote:
> > > > These debugfs files are mainly used to make eye diagram test
> > > > easier,
> > > > especially helpful to do HQA test for a new IC without efuse
> > > > enabled.
> 
> Exporting data for eye diagrams seems like something many PHYs could
> use. Please consider adding an official uniform API which any PHY
> could use, so we don't end up with lots of incompatible formats in
> debugfs.
Good idea, but it seems difficult to do it due to the settings of phy
controllers are not common.

> 
> 	Andrew

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v4 3/3] phy: mediatek: tphy: add debugfs files
  2022-12-03 14:53         ` Chunfeng Yun (云春峰)
@ 2022-12-03 15:38           ` Andrew Lunn
  0 siblings, 0 replies; 10+ messages in thread
From: Andrew Lunn @ 2022-12-03 15:38 UTC (permalink / raw)
  To: Chunfeng Yun (云春峰)
  Cc: angelogioacchino.delregno, linux-kernel, linux-mediatek, nathan,
	kishon, Eddie Hung (洪正鑫),
	Tianping Fang (方天平),
	linux-arm-kernel, vkoul, matthias.bgg, linux-phy, llvm, trix,
	ndesaulniers

On Sat, Dec 03, 2022 at 02:53:19PM +0000, Chunfeng Yun (云春峰) wrote:
> On Mon, 2022-11-28 at 15:00 +0100, Andrew Lunn wrote:
> > On Mon, Nov 28, 2022 at 07:26:02AM +0000, Chunfeng Yun (云春峰) wrote:
> > > On Thu, 2022-11-24 at 23:17 +0530, Vinod Koul wrote:
> > > > On 10-11-22, 21:27, Chunfeng Yun wrote:
> > > > > These debugfs files are mainly used to make eye diagram test
> > > > > easier,
> > > > > especially helpful to do HQA test for a new IC without efuse
> > > > > enabled.
> > 
> > Exporting data for eye diagrams seems like something many PHYs could
> > use. Please consider adding an official uniform API which any PHY
> > could use, so we don't end up with lots of incompatible formats in
> > debugfs.
> Good idea, but it seems difficult to do it due to the settings of phy
> controllers are not common.

Do you have clear documentation about the values are exporting? Do you
have a documented procedure for the tests?

We need to collect together documentation from multiple vendors and
see what is common. Maybe nothing is common, maybe a lot is in common.
We won't know until we actually compare them.

I implemented cable testing for Ethernet PHYs. They are all different,
but actual give very similar results, so can have one common
description. How many different ways is there to make eye diagram
tests?

	Andrew

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2022-12-03 15:39 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-11-10 13:27 [PATCH v4 1/3] phy: mediatek: fix build warning caused by clang for powerpc Chunfeng Yun
2022-11-10 13:27 ` [PATCH v4 2/3] phy: core: add debugfs root Chunfeng Yun
2022-11-24 17:39   ` Vinod Koul
2022-11-28  7:00     ` Chunfeng Yun (云春峰)
2022-11-10 13:27 ` [PATCH v4 3/3] phy: mediatek: tphy: add debugfs files Chunfeng Yun
2022-11-24 17:47   ` Vinod Koul
2022-11-28  7:26     ` Chunfeng Yun (云春峰)
2022-11-28 14:00       ` Andrew Lunn
2022-12-03 14:53         ` Chunfeng Yun (云春峰)
2022-12-03 15:38           ` Andrew Lunn

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).