1// SPDX-License-Identifier: GPL-2.0
2/*
3 * UCSI debugfs interface
4 *
5 * Copyright (C) 2023 Intel Corporation
6 *
7 * Authors: Rajaram Regupathy <rajaram.regupathy@intel.com>
8 * Gopal Saranya <saranya.gopal@intel.com>
9 */
10#include <linux/debugfs.h>
11#include <linux/slab.h>
12#include <linux/string.h>
13#include <linux/types.h>
14#include <linux/usb.h>
15
16#include <asm/errno.h>
17
18#include "ucsi.h"
19
20static struct dentry *ucsi_debugfs_root;
21
22static int ucsi_cmd(void *data, u64 val)
23{
24 struct ucsi *ucsi = data;
25 int ret;
26
27 memset(&ucsi->debugfs->response, 0, sizeof(ucsi->debugfs->response));
28 ucsi->debugfs->status = 0;
29
30 switch (UCSI_COMMAND(val)) {
31 case UCSI_SET_UOM:
32 case UCSI_SET_UOR:
33 case UCSI_SET_PDR:
34 case UCSI_CONNECTOR_RESET:
35 ret = ucsi_send_command(ucsi, command: val, NULL, size: 0);
36 break;
37 case UCSI_GET_CAPABILITY:
38 case UCSI_GET_CONNECTOR_CAPABILITY:
39 case UCSI_GET_ALTERNATE_MODES:
40 case UCSI_GET_CURRENT_CAM:
41 case UCSI_GET_PDOS:
42 case UCSI_GET_CABLE_PROPERTY:
43 case UCSI_GET_CONNECTOR_STATUS:
44 ret = ucsi_send_command(ucsi, command: val,
45 retval: &ucsi->debugfs->response,
46 size: sizeof(ucsi->debugfs->response));
47 break;
48 default:
49 ret = -EOPNOTSUPP;
50 }
51
52 if (ret < 0) {
53 ucsi->debugfs->status = ret;
54 return ret;
55 }
56
57 return 0;
58}
59DEFINE_DEBUGFS_ATTRIBUTE(ucsi_cmd_fops, NULL, ucsi_cmd, "0x%llx\n");
60
61static int ucsi_resp_show(struct seq_file *s, void *not_used)
62{
63 struct ucsi *ucsi = s->private;
64
65 if (ucsi->debugfs->status)
66 return ucsi->debugfs->status;
67
68 seq_printf(m: s, fmt: "0x%016llx%016llx\n", ucsi->debugfs->response.high,
69 ucsi->debugfs->response.low);
70 return 0;
71}
72DEFINE_SHOW_ATTRIBUTE(ucsi_resp);
73
74void ucsi_debugfs_register(struct ucsi *ucsi)
75{
76 ucsi->debugfs = kzalloc(size: sizeof(*ucsi->debugfs), GFP_KERNEL);
77 if (!ucsi->debugfs)
78 return;
79
80 ucsi->debugfs->dentry = debugfs_create_dir(name: dev_name(dev: ucsi->dev), parent: ucsi_debugfs_root);
81 debugfs_create_file(name: "command", mode: 0200, parent: ucsi->debugfs->dentry, data: ucsi, fops: &ucsi_cmd_fops);
82 debugfs_create_file(name: "response", mode: 0400, parent: ucsi->debugfs->dentry, data: ucsi, fops: &ucsi_resp_fops);
83}
84
85void ucsi_debugfs_unregister(struct ucsi *ucsi)
86{
87 if (IS_ERR_OR_NULL(ptr: ucsi) || !ucsi->debugfs)
88 return;
89
90 debugfs_remove_recursive(dentry: ucsi->debugfs->dentry);
91 kfree(objp: ucsi->debugfs);
92}
93
94void ucsi_debugfs_init(void)
95{
96 ucsi_debugfs_root = debugfs_create_dir(name: "ucsi", parent: usb_debug_root);
97}
98
99void ucsi_debugfs_exit(void)
100{
101 debugfs_remove(dentry: ucsi_debugfs_root);
102}
103

source code of linux/drivers/usb/typec/ucsi/debugfs.c