usb: typec: ucsi: Add debugfs for ucsi commands
Add support for UCSI commands through the following debugfs: # /sys/kernel/debug/usb/ucsi/$UCSI_DEVICE/command # /sys/kernel/debug/usb/ucsi/$UCSI_DEVICE/response Eg: To execute UCSI GetCapabilities: # echo 0x6 > /sys/kernel/debug/usb/ucsi/<ucsi device>/command Then read the result, # cat /sys/kernel/debug/usb/ucsi/<ucsi device>/response 0x02000320000000020000ff0400000445 UCSI command will be written into the command file and the response for the command can be viewed under the response file. Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Signed-off-by: Saranya Gopal <saranya.gopal@intel.com> Co-developed-by: Rajaram Regupathy <rajaram.regupathy@intel.com> Signed-off-by: Rajaram Regupathy <rajaram.regupathy@intel.com> Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com> Link: https://lore.kernel.org/r/20230807105205.742819-1-saranya.gopal@intel.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
3b563b901e
commit
df0383ffad
@ -4,6 +4,7 @@ config TYPEC_UCSI
|
||||
tristate "USB Type-C Connector System Software Interface driver"
|
||||
depends on !CPU_BIG_ENDIAN
|
||||
depends on USB_ROLE_SWITCH || !USB_ROLE_SWITCH
|
||||
select USB_COMMON if DEBUG_FS
|
||||
help
|
||||
USB Type-C Connector System Software Interface (UCSI) is a
|
||||
specification for an interface that allows the operating system to
|
||||
|
@ -5,6 +5,8 @@ obj-$(CONFIG_TYPEC_UCSI) += typec_ucsi.o
|
||||
|
||||
typec_ucsi-y := ucsi.o
|
||||
|
||||
typec_ucsi-$(CONFIG_DEBUG_FS) += debugfs.o
|
||||
|
||||
typec_ucsi-$(CONFIG_TRACING) += trace.o
|
||||
|
||||
ifneq ($(CONFIG_POWER_SUPPLY),)
|
||||
|
99
drivers/usb/typec/ucsi/debugfs.c
Normal file
99
drivers/usb/typec/ucsi/debugfs.c
Normal file
@ -0,0 +1,99 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* UCSI debugfs interface
|
||||
*
|
||||
* Copyright (C) 2023 Intel Corporation
|
||||
*
|
||||
* Authors: Rajaram Regupathy <rajaram.regupathy@intel.com>
|
||||
* Gopal Saranya <saranya.gopal@intel.com>
|
||||
*/
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/usb.h>
|
||||
|
||||
#include <asm/errno.h>
|
||||
|
||||
#include "ucsi.h"
|
||||
|
||||
static struct dentry *ucsi_debugfs_root;
|
||||
|
||||
static int ucsi_cmd(void *data, u64 val)
|
||||
{
|
||||
struct ucsi *ucsi = data;
|
||||
int ret;
|
||||
|
||||
memset(&ucsi->debugfs->response, 0, sizeof(ucsi->debugfs->response));
|
||||
ucsi->debugfs->status = 0;
|
||||
|
||||
switch (UCSI_COMMAND(val)) {
|
||||
case UCSI_SET_UOM:
|
||||
case UCSI_SET_UOR:
|
||||
case UCSI_SET_PDR:
|
||||
case UCSI_CONNECTOR_RESET:
|
||||
ret = ucsi_send_command(ucsi, val, NULL, 0);
|
||||
break;
|
||||
case UCSI_GET_CAPABILITY:
|
||||
case UCSI_GET_CONNECTOR_CAPABILITY:
|
||||
case UCSI_GET_ALTERNATE_MODES:
|
||||
case UCSI_GET_CURRENT_CAM:
|
||||
case UCSI_GET_PDOS:
|
||||
case UCSI_GET_CABLE_PROPERTY:
|
||||
case UCSI_GET_CONNECTOR_STATUS:
|
||||
ret = ucsi_send_command(ucsi, val,
|
||||
&ucsi->debugfs->response,
|
||||
sizeof(ucsi->debugfs->response));
|
||||
break;
|
||||
default:
|
||||
ret = -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
ucsi->debugfs->status = ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
DEFINE_DEBUGFS_ATTRIBUTE(ucsi_cmd_fops, NULL, ucsi_cmd, "0x%llx\n");
|
||||
|
||||
static int ucsi_resp_show(struct seq_file *s, void *not_used)
|
||||
{
|
||||
struct ucsi *ucsi = s->private;
|
||||
|
||||
if (ucsi->debugfs->status)
|
||||
return ucsi->debugfs->status;
|
||||
|
||||
seq_printf(s, "0x%016llx%016llx\n", ucsi->debugfs->response.high,
|
||||
ucsi->debugfs->response.low);
|
||||
return 0;
|
||||
}
|
||||
DEFINE_SHOW_ATTRIBUTE(ucsi_resp);
|
||||
|
||||
void ucsi_debugfs_register(struct ucsi *ucsi)
|
||||
{
|
||||
ucsi->debugfs = kzalloc(sizeof(*ucsi->debugfs), GFP_KERNEL);
|
||||
if (!ucsi->debugfs)
|
||||
return;
|
||||
|
||||
ucsi->debugfs->dentry = debugfs_create_dir(dev_name(ucsi->dev), ucsi_debugfs_root);
|
||||
debugfs_create_file("command", 0200, ucsi->debugfs->dentry, ucsi, &ucsi_cmd_fops);
|
||||
debugfs_create_file("response", 0400, ucsi->debugfs->dentry, ucsi, &ucsi_resp_fops);
|
||||
}
|
||||
|
||||
void ucsi_debugfs_unregister(struct ucsi *ucsi)
|
||||
{
|
||||
debugfs_remove_recursive(ucsi->debugfs->dentry);
|
||||
kfree(ucsi->debugfs);
|
||||
}
|
||||
|
||||
void ucsi_debugfs_init(void)
|
||||
{
|
||||
ucsi_debugfs_root = debugfs_create_dir("ucsi", usb_debug_root);
|
||||
}
|
||||
|
||||
void ucsi_debugfs_exit(void)
|
||||
{
|
||||
debugfs_remove(ucsi_debugfs_root);
|
||||
}
|
@ -1530,6 +1530,7 @@ EXPORT_SYMBOL_GPL(ucsi_create);
|
||||
*/
|
||||
void ucsi_destroy(struct ucsi *ucsi)
|
||||
{
|
||||
ucsi_debugfs_unregister(ucsi);
|
||||
kfree(ucsi);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ucsi_destroy);
|
||||
@ -1552,6 +1553,7 @@ int ucsi_register(struct ucsi *ucsi)
|
||||
|
||||
queue_delayed_work(system_long_wq, &ucsi->work, 0);
|
||||
|
||||
ucsi_debugfs_register(ucsi);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ucsi_register);
|
||||
@ -1611,6 +1613,19 @@ void ucsi_unregister(struct ucsi *ucsi)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(ucsi_unregister);
|
||||
|
||||
static int __init ucsi_module_init(void)
|
||||
{
|
||||
ucsi_debugfs_init();
|
||||
return 0;
|
||||
}
|
||||
module_init(ucsi_module_init);
|
||||
|
||||
static void __exit ucsi_module_exit(void)
|
||||
{
|
||||
ucsi_debugfs_exit();
|
||||
}
|
||||
module_exit(ucsi_module_exit);
|
||||
|
||||
MODULE_AUTHOR("Heikki Krogerus <heikki.krogerus@linux.intel.com>");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_DESCRIPTION("USB Type-C Connector System Software Interface driver");
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
struct ucsi;
|
||||
struct ucsi_altmode;
|
||||
struct dentry;
|
||||
|
||||
/* UCSI offsets (Bytes) */
|
||||
#define UCSI_VERSION 0
|
||||
@ -277,6 +278,16 @@ struct ucsi_connector_status {
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
struct ucsi_debugfs_entry {
|
||||
u64 command;
|
||||
struct ucsi_data {
|
||||
u64 low;
|
||||
u64 high;
|
||||
} response;
|
||||
u32 status;
|
||||
struct dentry *dentry;
|
||||
};
|
||||
|
||||
struct ucsi {
|
||||
u16 version;
|
||||
struct device *dev;
|
||||
@ -286,6 +297,7 @@ struct ucsi {
|
||||
|
||||
struct ucsi_capability cap;
|
||||
struct ucsi_connector *connector;
|
||||
struct ucsi_debugfs_entry *debugfs;
|
||||
|
||||
struct work_struct resume_work;
|
||||
struct delayed_work work;
|
||||
@ -388,6 +400,18 @@ static inline void
|
||||
ucsi_displayport_remove_partner(struct typec_altmode *adev) { }
|
||||
#endif /* CONFIG_TYPEC_DP_ALTMODE */
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
void ucsi_debugfs_init(void);
|
||||
void ucsi_debugfs_exit(void);
|
||||
void ucsi_debugfs_register(struct ucsi *ucsi);
|
||||
void ucsi_debugfs_unregister(struct ucsi *ucsi);
|
||||
#else
|
||||
static inline void ucsi_debugfs_init(void) { }
|
||||
static inline void ucsi_debugfs_exit(void) { }
|
||||
static inline void ucsi_debugfs_register(struct ucsi *ucsi) { }
|
||||
static inline void ucsi_debugfs_unregister(struct ucsi *ucsi) { }
|
||||
#endif /* CONFIG_DEBUG_FS */
|
||||
|
||||
/*
|
||||
* NVIDIA VirtualLink (svid 0x955) has two altmode. VirtualLink
|
||||
* DP mode with vdo=0x1 and NVIDIA test mode with vdo=0x3
|
||||
|
Loading…
x
Reference in New Issue
Block a user