Merge tag 'for-linus-2023101101' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-block.git] / drivers / usb / typec / ucsi / debugfs.c
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
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_UOM:
32         case UCSI_SET_UOR:
33         case UCSI_SET_PDR:
34         case UCSI_CONNECTOR_RESET:
35                 ret = ucsi_send_command(ucsi, val, NULL, 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, val,
45                                         &ucsi->debugfs->response,
46                                         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 }
59 DEFINE_DEBUGFS_ATTRIBUTE(ucsi_cmd_fops, NULL, ucsi_cmd, "0x%llx\n");
60
61 static 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(s, "0x%016llx%016llx\n", ucsi->debugfs->response.high,
69                    ucsi->debugfs->response.low);
70         return 0;
71 }
72 DEFINE_SHOW_ATTRIBUTE(ucsi_resp);
73
74 void ucsi_debugfs_register(struct ucsi *ucsi)
75 {
76         ucsi->debugfs = kzalloc(sizeof(*ucsi->debugfs), GFP_KERNEL);
77         if (!ucsi->debugfs)
78                 return;
79
80         ucsi->debugfs->dentry = debugfs_create_dir(dev_name(ucsi->dev), ucsi_debugfs_root);
81         debugfs_create_file("command", 0200, ucsi->debugfs->dentry, ucsi, &ucsi_cmd_fops);
82         debugfs_create_file("response", 0400, ucsi->debugfs->dentry, ucsi, &ucsi_resp_fops);
83 }
84
85 void ucsi_debugfs_unregister(struct ucsi *ucsi)
86 {
87         if (IS_ERR_OR_NULL(ucsi) || !ucsi->debugfs)
88                 return;
89
90         debugfs_remove_recursive(ucsi->debugfs->dentry);
91         kfree(ucsi->debugfs);
92 }
93
94 void ucsi_debugfs_init(void)
95 {
96         ucsi_debugfs_root = debugfs_create_dir("ucsi", usb_debug_root);
97 }
98
99 void ucsi_debugfs_exit(void)
100 {
101         debugfs_remove(ucsi_debugfs_root);
102 }