Skip to content

Commit e450760

Browse files
Chunfeng Yunvinodkoul
authored andcommitted
phy: mediatek: tphy: add debugfs files
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> Link: https://lore.kernel.org/r/20230513092218.21139-2-chunfeng.yun@mediatek.com Signed-off-by: Vinod Koul <vkoul@kernel.org>
1 parent 9169477 commit e450760

1 file changed

Lines changed: 356 additions & 0 deletions

File tree

drivers/phy/mediatek/phy-mtk-tphy.c

Lines changed: 356 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#include <dt-bindings/phy/phy.h>
99
#include <linux/clk.h>
10+
#include <linux/debugfs.h>
1011
#include <linux/delay.h>
1112
#include <linux/iopoll.h>
1213
#include <linux/mfd/syscon.h>
@@ -264,6 +265,8 @@
264265

265266
#define TPHY_CLKS_CNT 2
266267

268+
#define USER_BUF_LEN(count) min_t(size_t, 8, (count))
269+
267270
enum mtk_phy_version {
268271
MTK_PHY_V1 = 1,
269272
MTK_PHY_V2,
@@ -336,6 +339,358 @@ struct mtk_tphy {
336339
int src_coef; /* coefficient for slew rate calibrate */
337340
};
338341

342+
#if IS_ENABLED(CONFIG_DEBUG_FS)
343+
344+
enum u2_phy_params {
345+
U2P_EYE_VRT = 0,
346+
U2P_EYE_TERM,
347+
U2P_EFUSE_EN,
348+
U2P_EFUSE_INTR,
349+
U2P_DISCTH,
350+
U2P_PRE_EMPHASIS,
351+
};
352+
353+
enum u3_phy_params {
354+
U3P_EFUSE_EN = 0,
355+
U3P_EFUSE_INTR,
356+
U3P_EFUSE_TX_IMP,
357+
U3P_EFUSE_RX_IMP,
358+
};
359+
360+
static const char *const u2_phy_files[] = {
361+
[U2P_EYE_VRT] = "vrt",
362+
[U2P_EYE_TERM] = "term",
363+
[U2P_EFUSE_EN] = "efuse",
364+
[U2P_EFUSE_INTR] = "intr",
365+
[U2P_DISCTH] = "discth",
366+
[U2P_PRE_EMPHASIS] = "preemph",
367+
};
368+
369+
static const char *const u3_phy_files[] = {
370+
[U3P_EFUSE_EN] = "efuse",
371+
[U3P_EFUSE_INTR] = "intr",
372+
[U3P_EFUSE_TX_IMP] = "tx-imp",
373+
[U3P_EFUSE_RX_IMP] = "rx-imp",
374+
};
375+
376+
static int u2_phy_params_show(struct seq_file *sf, void *unused)
377+
{
378+
struct mtk_phy_instance *inst = sf->private;
379+
const char *fname = file_dentry(sf->file)->d_iname;
380+
struct u2phy_banks *u2_banks = &inst->u2_banks;
381+
void __iomem *com = u2_banks->com;
382+
u32 max = 0;
383+
u32 tmp = 0;
384+
u32 val = 0;
385+
int ret;
386+
387+
ret = match_string(u2_phy_files, ARRAY_SIZE(u2_phy_files), fname);
388+
if (ret < 0)
389+
return ret;
390+
391+
switch (ret) {
392+
case U2P_EYE_VRT:
393+
tmp = readl(com + U3P_USBPHYACR1);
394+
val = FIELD_GET(PA1_RG_VRT_SEL, tmp);
395+
max = FIELD_MAX(PA1_RG_VRT_SEL);
396+
break;
397+
398+
case U2P_EYE_TERM:
399+
tmp = readl(com + U3P_USBPHYACR1);
400+
val = FIELD_GET(PA1_RG_TERM_SEL, tmp);
401+
max = FIELD_MAX(PA1_RG_TERM_SEL);
402+
break;
403+
404+
case U2P_EFUSE_EN:
405+
if (u2_banks->misc) {
406+
tmp = readl(u2_banks->misc + U3P_MISC_REG1);
407+
max = 1;
408+
}
409+
410+
val = !!(tmp & MR1_EFUSE_AUTO_LOAD_DIS);
411+
break;
412+
413+
case U2P_EFUSE_INTR:
414+
tmp = readl(com + U3P_USBPHYACR1);
415+
val = FIELD_GET(PA1_RG_INTR_CAL, tmp);
416+
max = FIELD_MAX(PA1_RG_INTR_CAL);
417+
break;
418+
419+
case U2P_DISCTH:
420+
tmp = readl(com + U3P_USBPHYACR6);
421+
val = FIELD_GET(PA6_RG_U2_DISCTH, tmp);
422+
max = FIELD_MAX(PA6_RG_U2_DISCTH);
423+
break;
424+
425+
case U2P_PRE_EMPHASIS:
426+
tmp = readl(com + U3P_USBPHYACR6);
427+
val = FIELD_GET(PA6_RG_U2_PRE_EMP, tmp);
428+
max = FIELD_MAX(PA6_RG_U2_PRE_EMP);
429+
break;
430+
431+
default:
432+
seq_printf(sf, "invalid, %d\n", ret);
433+
break;
434+
}
435+
436+
seq_printf(sf, "%s : %d [0, %d]\n", fname, val, max);
437+
438+
return 0;
439+
}
440+
441+
static int u2_phy_params_open(struct inode *inode, struct file *file)
442+
{
443+
return single_open(file, u2_phy_params_show, inode->i_private);
444+
}
445+
446+
static ssize_t u2_phy_params_write(struct file *file, const char __user *ubuf,
447+
size_t count, loff_t *ppos)
448+
{
449+
const char *fname = file_dentry(file)->d_iname;
450+
struct seq_file *sf = file->private_data;
451+
struct mtk_phy_instance *inst = sf->private;
452+
struct u2phy_banks *u2_banks = &inst->u2_banks;
453+
void __iomem *com = u2_banks->com;
454+
ssize_t rc;
455+
u32 val;
456+
int ret;
457+
458+
rc = kstrtouint_from_user(ubuf, USER_BUF_LEN(count), 0, &val);
459+
if (rc)
460+
return rc;
461+
462+
ret = match_string(u2_phy_files, ARRAY_SIZE(u2_phy_files), fname);
463+
if (ret < 0)
464+
return (ssize_t)ret;
465+
466+
switch (ret) {
467+
case U2P_EYE_VRT:
468+
mtk_phy_update_field(com + U3P_USBPHYACR1, PA1_RG_VRT_SEL, val);
469+
break;
470+
471+
case U2P_EYE_TERM:
472+
mtk_phy_update_field(com + U3P_USBPHYACR1, PA1_RG_TERM_SEL, val);
473+
break;
474+
475+
case U2P_EFUSE_EN:
476+
if (u2_banks->misc)
477+
mtk_phy_update_field(u2_banks->misc + U3P_MISC_REG1,
478+
MR1_EFUSE_AUTO_LOAD_DIS, !!val);
479+
break;
480+
481+
case U2P_EFUSE_INTR:
482+
mtk_phy_update_field(com + U3P_USBPHYACR1, PA1_RG_INTR_CAL, val);
483+
break;
484+
485+
case U2P_DISCTH:
486+
mtk_phy_update_field(com + U3P_USBPHYACR6, PA6_RG_U2_DISCTH, val);
487+
break;
488+
489+
case U2P_PRE_EMPHASIS:
490+
mtk_phy_update_field(com + U3P_USBPHYACR6, PA6_RG_U2_PRE_EMP, val);
491+
break;
492+
493+
default:
494+
break;
495+
}
496+
497+
return count;
498+
}
499+
500+
static const struct file_operations u2_phy_fops = {
501+
.open = u2_phy_params_open,
502+
.write = u2_phy_params_write,
503+
.read = seq_read,
504+
.llseek = seq_lseek,
505+
.release = single_release,
506+
};
507+
508+
static void u2_phy_dbgfs_files_create(struct mtk_phy_instance *inst)
509+
{
510+
u32 count = ARRAY_SIZE(u2_phy_files);
511+
int i;
512+
513+
for (i = 0; i < count; i++)
514+
debugfs_create_file(u2_phy_files[i], 0644, inst->phy->debugfs,
515+
inst, &u2_phy_fops);
516+
}
517+
518+
static int u3_phy_params_show(struct seq_file *sf, void *unused)
519+
{
520+
struct mtk_phy_instance *inst = sf->private;
521+
const char *fname = file_dentry(sf->file)->d_iname;
522+
struct u3phy_banks *u3_banks = &inst->u3_banks;
523+
u32 val = 0;
524+
u32 max = 0;
525+
u32 tmp;
526+
int ret;
527+
528+
ret = match_string(u3_phy_files, ARRAY_SIZE(u3_phy_files), fname);
529+
if (ret < 0)
530+
return ret;
531+
532+
switch (ret) {
533+
case U3P_EFUSE_EN:
534+
tmp = readl(u3_banks->phyd + U3P_U3_PHYD_RSV);
535+
val = !!(tmp & P3D_RG_EFUSE_AUTO_LOAD_DIS);
536+
max = 1;
537+
break;
538+
539+
case U3P_EFUSE_INTR:
540+
tmp = readl(u3_banks->phya + U3P_U3_PHYA_REG0);
541+
val = FIELD_GET(P3A_RG_IEXT_INTR, tmp);
542+
max = FIELD_MAX(P3A_RG_IEXT_INTR);
543+
break;
544+
545+
case U3P_EFUSE_TX_IMP:
546+
tmp = readl(u3_banks->phyd + U3P_U3_PHYD_IMPCAL0);
547+
val = FIELD_GET(P3D_RG_TX_IMPEL, tmp);
548+
max = FIELD_MAX(P3D_RG_TX_IMPEL);
549+
break;
550+
551+
case U3P_EFUSE_RX_IMP:
552+
tmp = readl(u3_banks->phyd + U3P_U3_PHYD_IMPCAL1);
553+
val = FIELD_GET(P3D_RG_RX_IMPEL, tmp);
554+
max = FIELD_MAX(P3D_RG_RX_IMPEL);
555+
break;
556+
557+
default:
558+
seq_printf(sf, "invalid, %d\n", ret);
559+
break;
560+
}
561+
562+
seq_printf(sf, "%s : %d [0, %d]\n", fname, val, max);
563+
564+
return 0;
565+
}
566+
567+
static int u3_phy_params_open(struct inode *inode, struct file *file)
568+
{
569+
return single_open(file, u3_phy_params_show, inode->i_private);
570+
}
571+
572+
static ssize_t u3_phy_params_write(struct file *file, const char __user *ubuf,
573+
size_t count, loff_t *ppos)
574+
{
575+
const char *fname = file_dentry(file)->d_iname;
576+
struct seq_file *sf = file->private_data;
577+
struct mtk_phy_instance *inst = sf->private;
578+
struct u3phy_banks *u3_banks = &inst->u3_banks;
579+
void __iomem *phyd = u3_banks->phyd;
580+
ssize_t rc;
581+
u32 val;
582+
int ret;
583+
584+
rc = kstrtouint_from_user(ubuf, USER_BUF_LEN(count), 0, &val);
585+
if (rc)
586+
return rc;
587+
588+
ret = match_string(u3_phy_files, ARRAY_SIZE(u3_phy_files), fname);
589+
if (ret < 0)
590+
return (ssize_t)ret;
591+
592+
switch (ret) {
593+
case U3P_EFUSE_EN:
594+
mtk_phy_update_field(phyd + U3P_U3_PHYD_RSV,
595+
P3D_RG_EFUSE_AUTO_LOAD_DIS, !!val);
596+
break;
597+
598+
case U3P_EFUSE_INTR:
599+
mtk_phy_update_field(u3_banks->phya + U3P_U3_PHYA_REG0,
600+
P3A_RG_IEXT_INTR, val);
601+
break;
602+
603+
case U3P_EFUSE_TX_IMP:
604+
mtk_phy_update_field(phyd + U3P_U3_PHYD_IMPCAL0, P3D_RG_TX_IMPEL, val);
605+
mtk_phy_set_bits(phyd + U3P_U3_PHYD_IMPCAL0, P3D_RG_FORCE_TX_IMPEL);
606+
break;
607+
608+
case U3P_EFUSE_RX_IMP:
609+
mtk_phy_update_field(phyd + U3P_U3_PHYD_IMPCAL1, P3D_RG_RX_IMPEL, val);
610+
mtk_phy_set_bits(phyd + U3P_U3_PHYD_IMPCAL1, P3D_RG_FORCE_RX_IMPEL);
611+
break;
612+
613+
default:
614+
break;
615+
}
616+
617+
return count;
618+
}
619+
620+
static const struct file_operations u3_phy_fops = {
621+
.open = u3_phy_params_open,
622+
.write = u3_phy_params_write,
623+
.read = seq_read,
624+
.llseek = seq_lseek,
625+
.release = single_release,
626+
};
627+
628+
static void u3_phy_dbgfs_files_create(struct mtk_phy_instance *inst)
629+
{
630+
u32 count = ARRAY_SIZE(u3_phy_files);
631+
int i;
632+
633+
for (i = 0; i < count; i++)
634+
debugfs_create_file(u3_phy_files[i], 0644, inst->phy->debugfs,
635+
inst, &u3_phy_fops);
636+
}
637+
638+
static int phy_type_show(struct seq_file *sf, void *unused)
639+
{
640+
struct mtk_phy_instance *inst = sf->private;
641+
const char *type;
642+
643+
switch (inst->type) {
644+
case PHY_TYPE_USB2:
645+
type = "USB2";
646+
break;
647+
case PHY_TYPE_USB3:
648+
type = "USB3";
649+
break;
650+
case PHY_TYPE_PCIE:
651+
type = "PCIe";
652+
break;
653+
case PHY_TYPE_SGMII:
654+
type = "SGMII";
655+
break;
656+
case PHY_TYPE_SATA:
657+
type = "SATA";
658+
break;
659+
default:
660+
type = "";
661+
}
662+
663+
seq_printf(sf, "%s\n", type);
664+
665+
return 0;
666+
}
667+
DEFINE_SHOW_ATTRIBUTE(phy_type);
668+
669+
/* these files will be removed when phy is released by phy core */
670+
static void phy_debugfs_init(struct mtk_phy_instance *inst)
671+
{
672+
debugfs_create_file("type", 0444, inst->phy->debugfs, inst, &phy_type_fops);
673+
674+
switch (inst->type) {
675+
case PHY_TYPE_USB2:
676+
u2_phy_dbgfs_files_create(inst);
677+
break;
678+
case PHY_TYPE_USB3:
679+
case PHY_TYPE_PCIE:
680+
u3_phy_dbgfs_files_create(inst);
681+
break;
682+
default:
683+
break;
684+
}
685+
}
686+
687+
#else
688+
689+
static void phy_debugfs_init(struct mtk_phy_instance *inst)
690+
{}
691+
692+
#endif
693+
339694
static void hs_slew_rate_calibrate(struct mtk_tphy *tphy,
340695
struct mtk_phy_instance *instance)
341696
{
@@ -1140,6 +1495,7 @@ static struct phy *mtk_phy_xlate(struct device *dev,
11401495

11411496
phy_parse_property(tphy, instance);
11421497
phy_type_set(instance);
1498+
phy_debugfs_init(instance);
11431499

11441500
return instance->phy;
11451501
}

0 commit comments

Comments
 (0)