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
20 static struct dentry *ucsi_debugfs_root;
21
ucsi_cmd(void * data,u64 val)22 static 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_CCOM:
32 case UCSI_SET_UOR:
33 case UCSI_SET_PDR:
34 case UCSI_CONNECTOR_RESET:
35 case UCSI_SET_SINK_PATH:
36 case UCSI_SET_NEW_CAM:
37 case UCSI_SET_USB:
38 ret = ucsi_send_command(ucsi, val, NULL, 0);
39 break;
40 case UCSI_GET_CAPABILITY:
41 case UCSI_GET_CONNECTOR_CAPABILITY:
42 case UCSI_GET_ALTERNATE_MODES:
43 case UCSI_GET_CAM_SUPPORTED:
44 case UCSI_GET_CURRENT_CAM:
45 case UCSI_GET_PDOS:
46 case UCSI_GET_CABLE_PROPERTY:
47 case UCSI_GET_CONNECTOR_STATUS:
48 case UCSI_GET_ERROR_STATUS:
49 case UCSI_GET_PD_MESSAGE:
50 case UCSI_GET_ATTENTION_VDO:
51 case UCSI_GET_CAM_CS:
52 case UCSI_GET_LPM_PPM_INFO:
53 ret = ucsi_send_command(ucsi, val,
54 &ucsi->debugfs->response,
55 sizeof(ucsi->debugfs->response));
56 break;
57 default:
58 ret = -EOPNOTSUPP;
59 }
60
61 if (ret < 0) {
62 ucsi->debugfs->status = ret;
63 return ret;
64 }
65
66 return 0;
67 }
68 DEFINE_DEBUGFS_ATTRIBUTE(ucsi_cmd_fops, NULL, ucsi_cmd, "0x%llx\n");
69
ucsi_resp_show(struct seq_file * s,void * not_used)70 static int ucsi_resp_show(struct seq_file *s, void *not_used)
71 {
72 struct ucsi *ucsi = s->private;
73
74 if (ucsi->debugfs->status)
75 return ucsi->debugfs->status;
76
77 seq_printf(s, "0x%016llx%016llx\n", ucsi->debugfs->response.high,
78 ucsi->debugfs->response.low);
79 return 0;
80 }
81 DEFINE_SHOW_ATTRIBUTE(ucsi_resp);
82
ucsi_debugfs_register(struct ucsi * ucsi)83 void ucsi_debugfs_register(struct ucsi *ucsi)
84 {
85 ucsi->debugfs = kzalloc(sizeof(*ucsi->debugfs), GFP_KERNEL);
86 if (!ucsi->debugfs)
87 return;
88
89 ucsi->debugfs->dentry = debugfs_create_dir(dev_name(ucsi->dev), ucsi_debugfs_root);
90 debugfs_create_file("command", 0200, ucsi->debugfs->dentry, ucsi, &ucsi_cmd_fops);
91 debugfs_create_file("response", 0400, ucsi->debugfs->dentry, ucsi, &ucsi_resp_fops);
92 }
93
ucsi_debugfs_unregister(struct ucsi * ucsi)94 void ucsi_debugfs_unregister(struct ucsi *ucsi)
95 {
96 if (IS_ERR_OR_NULL(ucsi) || !ucsi->debugfs)
97 return;
98
99 debugfs_remove_recursive(ucsi->debugfs->dentry);
100 kfree(ucsi->debugfs);
101 }
102
ucsi_debugfs_init(void)103 void ucsi_debugfs_init(void)
104 {
105 ucsi_debugfs_root = debugfs_create_dir("ucsi", usb_debug_root);
106 }
107
ucsi_debugfs_exit(void)108 void ucsi_debugfs_exit(void)
109 {
110 debugfs_remove(ucsi_debugfs_root);
111 }
112