1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun #include <linux/kernel.h>
3*4882a593Smuzhiyun #include <linux/device.h>
4*4882a593Smuzhiyun #include <linux/types.h>
5*4882a593Smuzhiyun #include <linux/spinlock.h>
6*4882a593Smuzhiyun #include <linux/debugfs.h>
7*4882a593Smuzhiyun #include <linux/seq_file.h>
8*4882a593Smuzhiyun #include <linux/uaccess.h>
9*4882a593Smuzhiyun #include <linux/usb/ch9.h>
10*4882a593Smuzhiyun #include <linux/usb/gadget.h>
11*4882a593Smuzhiyun #include <linux/usb/phy.h>
12*4882a593Smuzhiyun #include <linux/usb/otg.h>
13*4882a593Smuzhiyun #include <linux/usb/otg-fsm.h>
14*4882a593Smuzhiyun #include <linux/usb/chipidea.h>
15*4882a593Smuzhiyun
16*4882a593Smuzhiyun #include "ci.h"
17*4882a593Smuzhiyun #include "udc.h"
18*4882a593Smuzhiyun #include "bits.h"
19*4882a593Smuzhiyun #include "otg.h"
20*4882a593Smuzhiyun
21*4882a593Smuzhiyun /*
22*4882a593Smuzhiyun * ci_device_show: prints information about device capabilities and status
23*4882a593Smuzhiyun */
ci_device_show(struct seq_file * s,void * data)24*4882a593Smuzhiyun static int ci_device_show(struct seq_file *s, void *data)
25*4882a593Smuzhiyun {
26*4882a593Smuzhiyun struct ci_hdrc *ci = s->private;
27*4882a593Smuzhiyun struct usb_gadget *gadget = &ci->gadget;
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun seq_printf(s, "speed = %d\n", gadget->speed);
30*4882a593Smuzhiyun seq_printf(s, "max_speed = %d\n", gadget->max_speed);
31*4882a593Smuzhiyun seq_printf(s, "is_otg = %d\n", gadget->is_otg);
32*4882a593Smuzhiyun seq_printf(s, "is_a_peripheral = %d\n", gadget->is_a_peripheral);
33*4882a593Smuzhiyun seq_printf(s, "b_hnp_enable = %d\n", gadget->b_hnp_enable);
34*4882a593Smuzhiyun seq_printf(s, "a_hnp_support = %d\n", gadget->a_hnp_support);
35*4882a593Smuzhiyun seq_printf(s, "a_alt_hnp_support = %d\n", gadget->a_alt_hnp_support);
36*4882a593Smuzhiyun seq_printf(s, "name = %s\n",
37*4882a593Smuzhiyun (gadget->name ? gadget->name : ""));
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun if (!ci->driver)
40*4882a593Smuzhiyun return 0;
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun seq_printf(s, "gadget function = %s\n",
43*4882a593Smuzhiyun (ci->driver->function ? ci->driver->function : ""));
44*4882a593Smuzhiyun seq_printf(s, "gadget max speed = %d\n", ci->driver->max_speed);
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun return 0;
47*4882a593Smuzhiyun }
48*4882a593Smuzhiyun DEFINE_SHOW_ATTRIBUTE(ci_device);
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun /*
51*4882a593Smuzhiyun * ci_port_test_show: reads port test mode
52*4882a593Smuzhiyun */
ci_port_test_show(struct seq_file * s,void * data)53*4882a593Smuzhiyun static int ci_port_test_show(struct seq_file *s, void *data)
54*4882a593Smuzhiyun {
55*4882a593Smuzhiyun struct ci_hdrc *ci = s->private;
56*4882a593Smuzhiyun unsigned long flags;
57*4882a593Smuzhiyun unsigned mode;
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun pm_runtime_get_sync(ci->dev);
60*4882a593Smuzhiyun spin_lock_irqsave(&ci->lock, flags);
61*4882a593Smuzhiyun mode = hw_port_test_get(ci);
62*4882a593Smuzhiyun spin_unlock_irqrestore(&ci->lock, flags);
63*4882a593Smuzhiyun pm_runtime_put_sync(ci->dev);
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun seq_printf(s, "mode = %u\n", mode);
66*4882a593Smuzhiyun
67*4882a593Smuzhiyun return 0;
68*4882a593Smuzhiyun }
69*4882a593Smuzhiyun
70*4882a593Smuzhiyun /*
71*4882a593Smuzhiyun * ci_port_test_write: writes port test mode
72*4882a593Smuzhiyun */
ci_port_test_write(struct file * file,const char __user * ubuf,size_t count,loff_t * ppos)73*4882a593Smuzhiyun static ssize_t ci_port_test_write(struct file *file, const char __user *ubuf,
74*4882a593Smuzhiyun size_t count, loff_t *ppos)
75*4882a593Smuzhiyun {
76*4882a593Smuzhiyun struct seq_file *s = file->private_data;
77*4882a593Smuzhiyun struct ci_hdrc *ci = s->private;
78*4882a593Smuzhiyun unsigned long flags;
79*4882a593Smuzhiyun unsigned mode;
80*4882a593Smuzhiyun char buf[32];
81*4882a593Smuzhiyun int ret;
82*4882a593Smuzhiyun
83*4882a593Smuzhiyun count = min_t(size_t, sizeof(buf) - 1, count);
84*4882a593Smuzhiyun if (copy_from_user(buf, ubuf, count))
85*4882a593Smuzhiyun return -EFAULT;
86*4882a593Smuzhiyun
87*4882a593Smuzhiyun /* sscanf requires a zero terminated string */
88*4882a593Smuzhiyun buf[count] = '\0';
89*4882a593Smuzhiyun
90*4882a593Smuzhiyun if (sscanf(buf, "%u", &mode) != 1)
91*4882a593Smuzhiyun return -EINVAL;
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun if (mode > 255)
94*4882a593Smuzhiyun return -EBADRQC;
95*4882a593Smuzhiyun
96*4882a593Smuzhiyun pm_runtime_get_sync(ci->dev);
97*4882a593Smuzhiyun spin_lock_irqsave(&ci->lock, flags);
98*4882a593Smuzhiyun ret = hw_port_test_set(ci, mode);
99*4882a593Smuzhiyun spin_unlock_irqrestore(&ci->lock, flags);
100*4882a593Smuzhiyun pm_runtime_put_sync(ci->dev);
101*4882a593Smuzhiyun
102*4882a593Smuzhiyun return ret ? ret : count;
103*4882a593Smuzhiyun }
104*4882a593Smuzhiyun
ci_port_test_open(struct inode * inode,struct file * file)105*4882a593Smuzhiyun static int ci_port_test_open(struct inode *inode, struct file *file)
106*4882a593Smuzhiyun {
107*4882a593Smuzhiyun return single_open(file, ci_port_test_show, inode->i_private);
108*4882a593Smuzhiyun }
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun static const struct file_operations ci_port_test_fops = {
111*4882a593Smuzhiyun .open = ci_port_test_open,
112*4882a593Smuzhiyun .write = ci_port_test_write,
113*4882a593Smuzhiyun .read = seq_read,
114*4882a593Smuzhiyun .llseek = seq_lseek,
115*4882a593Smuzhiyun .release = single_release,
116*4882a593Smuzhiyun };
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun /*
119*4882a593Smuzhiyun * ci_qheads_show: DMA contents of all queue heads
120*4882a593Smuzhiyun */
ci_qheads_show(struct seq_file * s,void * data)121*4882a593Smuzhiyun static int ci_qheads_show(struct seq_file *s, void *data)
122*4882a593Smuzhiyun {
123*4882a593Smuzhiyun struct ci_hdrc *ci = s->private;
124*4882a593Smuzhiyun unsigned long flags;
125*4882a593Smuzhiyun unsigned i, j;
126*4882a593Smuzhiyun
127*4882a593Smuzhiyun if (ci->role != CI_ROLE_GADGET) {
128*4882a593Smuzhiyun seq_printf(s, "not in gadget mode\n");
129*4882a593Smuzhiyun return 0;
130*4882a593Smuzhiyun }
131*4882a593Smuzhiyun
132*4882a593Smuzhiyun spin_lock_irqsave(&ci->lock, flags);
133*4882a593Smuzhiyun for (i = 0; i < ci->hw_ep_max/2; i++) {
134*4882a593Smuzhiyun struct ci_hw_ep *hweprx = &ci->ci_hw_ep[i];
135*4882a593Smuzhiyun struct ci_hw_ep *hweptx =
136*4882a593Smuzhiyun &ci->ci_hw_ep[i + ci->hw_ep_max/2];
137*4882a593Smuzhiyun seq_printf(s, "EP=%02i: RX=%08X TX=%08X\n",
138*4882a593Smuzhiyun i, (u32)hweprx->qh.dma, (u32)hweptx->qh.dma);
139*4882a593Smuzhiyun for (j = 0; j < (sizeof(struct ci_hw_qh)/sizeof(u32)); j++)
140*4882a593Smuzhiyun seq_printf(s, " %04X: %08X %08X\n", j,
141*4882a593Smuzhiyun *((u32 *)hweprx->qh.ptr + j),
142*4882a593Smuzhiyun *((u32 *)hweptx->qh.ptr + j));
143*4882a593Smuzhiyun }
144*4882a593Smuzhiyun spin_unlock_irqrestore(&ci->lock, flags);
145*4882a593Smuzhiyun
146*4882a593Smuzhiyun return 0;
147*4882a593Smuzhiyun }
148*4882a593Smuzhiyun DEFINE_SHOW_ATTRIBUTE(ci_qheads);
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun /*
151*4882a593Smuzhiyun * ci_requests_show: DMA contents of all requests currently queued (all endpts)
152*4882a593Smuzhiyun */
ci_requests_show(struct seq_file * s,void * data)153*4882a593Smuzhiyun static int ci_requests_show(struct seq_file *s, void *data)
154*4882a593Smuzhiyun {
155*4882a593Smuzhiyun struct ci_hdrc *ci = s->private;
156*4882a593Smuzhiyun unsigned long flags;
157*4882a593Smuzhiyun struct ci_hw_req *req = NULL;
158*4882a593Smuzhiyun struct td_node *node, *tmpnode;
159*4882a593Smuzhiyun unsigned i, j, qsize = sizeof(struct ci_hw_td)/sizeof(u32);
160*4882a593Smuzhiyun
161*4882a593Smuzhiyun if (ci->role != CI_ROLE_GADGET) {
162*4882a593Smuzhiyun seq_printf(s, "not in gadget mode\n");
163*4882a593Smuzhiyun return 0;
164*4882a593Smuzhiyun }
165*4882a593Smuzhiyun
166*4882a593Smuzhiyun spin_lock_irqsave(&ci->lock, flags);
167*4882a593Smuzhiyun for (i = 0; i < ci->hw_ep_max; i++)
168*4882a593Smuzhiyun list_for_each_entry(req, &ci->ci_hw_ep[i].qh.queue, queue) {
169*4882a593Smuzhiyun list_for_each_entry_safe(node, tmpnode, &req->tds, td) {
170*4882a593Smuzhiyun seq_printf(s, "EP=%02i: TD=%08X %s\n",
171*4882a593Smuzhiyun i % (ci->hw_ep_max / 2),
172*4882a593Smuzhiyun (u32)node->dma,
173*4882a593Smuzhiyun ((i < ci->hw_ep_max/2) ?
174*4882a593Smuzhiyun "RX" : "TX"));
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun for (j = 0; j < qsize; j++)
177*4882a593Smuzhiyun seq_printf(s, " %04X: %08X\n", j,
178*4882a593Smuzhiyun *((u32 *)node->ptr + j));
179*4882a593Smuzhiyun }
180*4882a593Smuzhiyun }
181*4882a593Smuzhiyun spin_unlock_irqrestore(&ci->lock, flags);
182*4882a593Smuzhiyun
183*4882a593Smuzhiyun return 0;
184*4882a593Smuzhiyun }
185*4882a593Smuzhiyun DEFINE_SHOW_ATTRIBUTE(ci_requests);
186*4882a593Smuzhiyun
ci_otg_show(struct seq_file * s,void * unused)187*4882a593Smuzhiyun static int ci_otg_show(struct seq_file *s, void *unused)
188*4882a593Smuzhiyun {
189*4882a593Smuzhiyun struct ci_hdrc *ci = s->private;
190*4882a593Smuzhiyun struct otg_fsm *fsm;
191*4882a593Smuzhiyun
192*4882a593Smuzhiyun if (!ci || !ci_otg_is_fsm_mode(ci))
193*4882a593Smuzhiyun return 0;
194*4882a593Smuzhiyun
195*4882a593Smuzhiyun fsm = &ci->fsm;
196*4882a593Smuzhiyun
197*4882a593Smuzhiyun /* ------ State ----- */
198*4882a593Smuzhiyun seq_printf(s, "OTG state: %s\n\n",
199*4882a593Smuzhiyun usb_otg_state_string(ci->otg.state));
200*4882a593Smuzhiyun
201*4882a593Smuzhiyun /* ------ State Machine Variables ----- */
202*4882a593Smuzhiyun seq_printf(s, "a_bus_drop: %d\n", fsm->a_bus_drop);
203*4882a593Smuzhiyun
204*4882a593Smuzhiyun seq_printf(s, "a_bus_req: %d\n", fsm->a_bus_req);
205*4882a593Smuzhiyun
206*4882a593Smuzhiyun seq_printf(s, "a_srp_det: %d\n", fsm->a_srp_det);
207*4882a593Smuzhiyun
208*4882a593Smuzhiyun seq_printf(s, "a_vbus_vld: %d\n", fsm->a_vbus_vld);
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun seq_printf(s, "b_conn: %d\n", fsm->b_conn);
211*4882a593Smuzhiyun
212*4882a593Smuzhiyun seq_printf(s, "adp_change: %d\n", fsm->adp_change);
213*4882a593Smuzhiyun
214*4882a593Smuzhiyun seq_printf(s, "power_up: %d\n", fsm->power_up);
215*4882a593Smuzhiyun
216*4882a593Smuzhiyun seq_printf(s, "a_bus_resume: %d\n", fsm->a_bus_resume);
217*4882a593Smuzhiyun
218*4882a593Smuzhiyun seq_printf(s, "a_bus_suspend: %d\n", fsm->a_bus_suspend);
219*4882a593Smuzhiyun
220*4882a593Smuzhiyun seq_printf(s, "a_conn: %d\n", fsm->a_conn);
221*4882a593Smuzhiyun
222*4882a593Smuzhiyun seq_printf(s, "b_bus_req: %d\n", fsm->b_bus_req);
223*4882a593Smuzhiyun
224*4882a593Smuzhiyun seq_printf(s, "b_bus_suspend: %d\n", fsm->b_bus_suspend);
225*4882a593Smuzhiyun
226*4882a593Smuzhiyun seq_printf(s, "b_se0_srp: %d\n", fsm->b_se0_srp);
227*4882a593Smuzhiyun
228*4882a593Smuzhiyun seq_printf(s, "b_ssend_srp: %d\n", fsm->b_ssend_srp);
229*4882a593Smuzhiyun
230*4882a593Smuzhiyun seq_printf(s, "b_sess_vld: %d\n", fsm->b_sess_vld);
231*4882a593Smuzhiyun
232*4882a593Smuzhiyun seq_printf(s, "b_srp_done: %d\n", fsm->b_srp_done);
233*4882a593Smuzhiyun
234*4882a593Smuzhiyun seq_printf(s, "drv_vbus: %d\n", fsm->drv_vbus);
235*4882a593Smuzhiyun
236*4882a593Smuzhiyun seq_printf(s, "loc_conn: %d\n", fsm->loc_conn);
237*4882a593Smuzhiyun
238*4882a593Smuzhiyun seq_printf(s, "loc_sof: %d\n", fsm->loc_sof);
239*4882a593Smuzhiyun
240*4882a593Smuzhiyun seq_printf(s, "adp_prb: %d\n", fsm->adp_prb);
241*4882a593Smuzhiyun
242*4882a593Smuzhiyun seq_printf(s, "id: %d\n", fsm->id);
243*4882a593Smuzhiyun
244*4882a593Smuzhiyun seq_printf(s, "protocol: %d\n", fsm->protocol);
245*4882a593Smuzhiyun
246*4882a593Smuzhiyun return 0;
247*4882a593Smuzhiyun }
248*4882a593Smuzhiyun DEFINE_SHOW_ATTRIBUTE(ci_otg);
249*4882a593Smuzhiyun
ci_role_show(struct seq_file * s,void * data)250*4882a593Smuzhiyun static int ci_role_show(struct seq_file *s, void *data)
251*4882a593Smuzhiyun {
252*4882a593Smuzhiyun struct ci_hdrc *ci = s->private;
253*4882a593Smuzhiyun
254*4882a593Smuzhiyun if (ci->role != CI_ROLE_END)
255*4882a593Smuzhiyun seq_printf(s, "%s\n", ci_role(ci)->name);
256*4882a593Smuzhiyun
257*4882a593Smuzhiyun return 0;
258*4882a593Smuzhiyun }
259*4882a593Smuzhiyun
ci_role_write(struct file * file,const char __user * ubuf,size_t count,loff_t * ppos)260*4882a593Smuzhiyun static ssize_t ci_role_write(struct file *file, const char __user *ubuf,
261*4882a593Smuzhiyun size_t count, loff_t *ppos)
262*4882a593Smuzhiyun {
263*4882a593Smuzhiyun struct seq_file *s = file->private_data;
264*4882a593Smuzhiyun struct ci_hdrc *ci = s->private;
265*4882a593Smuzhiyun enum ci_role role;
266*4882a593Smuzhiyun char buf[8];
267*4882a593Smuzhiyun int ret;
268*4882a593Smuzhiyun
269*4882a593Smuzhiyun if (copy_from_user(buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
270*4882a593Smuzhiyun return -EFAULT;
271*4882a593Smuzhiyun
272*4882a593Smuzhiyun for (role = CI_ROLE_HOST; role < CI_ROLE_END; role++)
273*4882a593Smuzhiyun if (ci->roles[role] &&
274*4882a593Smuzhiyun !strncmp(buf, ci->roles[role]->name,
275*4882a593Smuzhiyun strlen(ci->roles[role]->name)))
276*4882a593Smuzhiyun break;
277*4882a593Smuzhiyun
278*4882a593Smuzhiyun if (role == CI_ROLE_END || role == ci->role)
279*4882a593Smuzhiyun return -EINVAL;
280*4882a593Smuzhiyun
281*4882a593Smuzhiyun pm_runtime_get_sync(ci->dev);
282*4882a593Smuzhiyun disable_irq(ci->irq);
283*4882a593Smuzhiyun ci_role_stop(ci);
284*4882a593Smuzhiyun ret = ci_role_start(ci, role);
285*4882a593Smuzhiyun enable_irq(ci->irq);
286*4882a593Smuzhiyun pm_runtime_put_sync(ci->dev);
287*4882a593Smuzhiyun
288*4882a593Smuzhiyun return ret ? ret : count;
289*4882a593Smuzhiyun }
290*4882a593Smuzhiyun
ci_role_open(struct inode * inode,struct file * file)291*4882a593Smuzhiyun static int ci_role_open(struct inode *inode, struct file *file)
292*4882a593Smuzhiyun {
293*4882a593Smuzhiyun return single_open(file, ci_role_show, inode->i_private);
294*4882a593Smuzhiyun }
295*4882a593Smuzhiyun
296*4882a593Smuzhiyun static const struct file_operations ci_role_fops = {
297*4882a593Smuzhiyun .open = ci_role_open,
298*4882a593Smuzhiyun .write = ci_role_write,
299*4882a593Smuzhiyun .read = seq_read,
300*4882a593Smuzhiyun .llseek = seq_lseek,
301*4882a593Smuzhiyun .release = single_release,
302*4882a593Smuzhiyun };
303*4882a593Smuzhiyun
ci_registers_show(struct seq_file * s,void * unused)304*4882a593Smuzhiyun static int ci_registers_show(struct seq_file *s, void *unused)
305*4882a593Smuzhiyun {
306*4882a593Smuzhiyun struct ci_hdrc *ci = s->private;
307*4882a593Smuzhiyun u32 tmp_reg;
308*4882a593Smuzhiyun
309*4882a593Smuzhiyun if (!ci || ci->in_lpm)
310*4882a593Smuzhiyun return -EPERM;
311*4882a593Smuzhiyun
312*4882a593Smuzhiyun /* ------ Registers ----- */
313*4882a593Smuzhiyun tmp_reg = hw_read_intr_enable(ci);
314*4882a593Smuzhiyun seq_printf(s, "USBINTR reg: %08x\n", tmp_reg);
315*4882a593Smuzhiyun
316*4882a593Smuzhiyun tmp_reg = hw_read_intr_status(ci);
317*4882a593Smuzhiyun seq_printf(s, "USBSTS reg: %08x\n", tmp_reg);
318*4882a593Smuzhiyun
319*4882a593Smuzhiyun tmp_reg = hw_read(ci, OP_USBMODE, ~0);
320*4882a593Smuzhiyun seq_printf(s, "USBMODE reg: %08x\n", tmp_reg);
321*4882a593Smuzhiyun
322*4882a593Smuzhiyun tmp_reg = hw_read(ci, OP_USBCMD, ~0);
323*4882a593Smuzhiyun seq_printf(s, "USBCMD reg: %08x\n", tmp_reg);
324*4882a593Smuzhiyun
325*4882a593Smuzhiyun tmp_reg = hw_read(ci, OP_PORTSC, ~0);
326*4882a593Smuzhiyun seq_printf(s, "PORTSC reg: %08x\n", tmp_reg);
327*4882a593Smuzhiyun
328*4882a593Smuzhiyun if (ci->is_otg) {
329*4882a593Smuzhiyun tmp_reg = hw_read_otgsc(ci, ~0);
330*4882a593Smuzhiyun seq_printf(s, "OTGSC reg: %08x\n", tmp_reg);
331*4882a593Smuzhiyun }
332*4882a593Smuzhiyun
333*4882a593Smuzhiyun return 0;
334*4882a593Smuzhiyun }
335*4882a593Smuzhiyun DEFINE_SHOW_ATTRIBUTE(ci_registers);
336*4882a593Smuzhiyun
337*4882a593Smuzhiyun /**
338*4882a593Smuzhiyun * dbg_create_files: initializes the attribute interface
339*4882a593Smuzhiyun * @ci: device
340*4882a593Smuzhiyun *
341*4882a593Smuzhiyun * This function returns an error code
342*4882a593Smuzhiyun */
dbg_create_files(struct ci_hdrc * ci)343*4882a593Smuzhiyun void dbg_create_files(struct ci_hdrc *ci)
344*4882a593Smuzhiyun {
345*4882a593Smuzhiyun ci->debugfs = debugfs_create_dir(dev_name(ci->dev), usb_debug_root);
346*4882a593Smuzhiyun
347*4882a593Smuzhiyun debugfs_create_file("device", S_IRUGO, ci->debugfs, ci,
348*4882a593Smuzhiyun &ci_device_fops);
349*4882a593Smuzhiyun debugfs_create_file("port_test", S_IRUGO | S_IWUSR, ci->debugfs, ci,
350*4882a593Smuzhiyun &ci_port_test_fops);
351*4882a593Smuzhiyun debugfs_create_file("qheads", S_IRUGO, ci->debugfs, ci,
352*4882a593Smuzhiyun &ci_qheads_fops);
353*4882a593Smuzhiyun debugfs_create_file("requests", S_IRUGO, ci->debugfs, ci,
354*4882a593Smuzhiyun &ci_requests_fops);
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun if (ci_otg_is_fsm_mode(ci)) {
357*4882a593Smuzhiyun debugfs_create_file("otg", S_IRUGO, ci->debugfs, ci,
358*4882a593Smuzhiyun &ci_otg_fops);
359*4882a593Smuzhiyun }
360*4882a593Smuzhiyun
361*4882a593Smuzhiyun debugfs_create_file("role", S_IRUGO | S_IWUSR, ci->debugfs, ci,
362*4882a593Smuzhiyun &ci_role_fops);
363*4882a593Smuzhiyun debugfs_create_file("registers", S_IRUGO, ci->debugfs, ci,
364*4882a593Smuzhiyun &ci_registers_fops);
365*4882a593Smuzhiyun }
366*4882a593Smuzhiyun
367*4882a593Smuzhiyun /**
368*4882a593Smuzhiyun * dbg_remove_files: destroys the attribute interface
369*4882a593Smuzhiyun * @ci: device
370*4882a593Smuzhiyun */
dbg_remove_files(struct ci_hdrc * ci)371*4882a593Smuzhiyun void dbg_remove_files(struct ci_hdrc *ci)
372*4882a593Smuzhiyun {
373*4882a593Smuzhiyun debugfs_remove_recursive(ci->debugfs);
374*4882a593Smuzhiyun }
375