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