blob: 4939e551897d829f05dd7735b9f310d2cebfc328 [file] [log] [blame]
developerba28e032021-12-07 10:40:00 +08001// SPDX-License-Identifier: GPL-2.0
developer765b1982021-06-24 09:18:15 +08002/*
developerba28e032021-12-07 10:40:00 +08003 * xHCI host controller toolkit driver
developer765b1982021-06-24 09:18:15 +08004 *
developerba28e032021-12-07 10:40:00 +08005 * Copyright (C) 2021 MediaTek Inc.
developer765b1982021-06-24 09:18:15 +08006 *
developerba28e032021-12-07 10:40:00 +08007 * Author: Zhanyong Wang <zhanyong.wang@mediatek.com>
8 * Shaocheng.Wang <shaocheng.wang@mediatek.com>
9 * Chunfeng.Yun <chunfeng.yun@mediatek.com>
developer765b1982021-06-24 09:18:15 +080010 */
11
12#include <linux/platform_device.h>
13#include <linux/module.h>
14#include <linux/slab.h>
15#include <linux/usb.h>
16#include <linux/kobject.h>
developerba28e032021-12-07 10:40:00 +080017#include <linux/of.h>
18#include <linux/of_address.h>
19#include <dt-bindings/phy/phy.h>
developer765b1982021-06-24 09:18:15 +080020#include "../core/usb.h"
21#include "xhci-mtk.h"
developerba28e032021-12-07 10:40:00 +080022#include "xhci-mtk-test.h"
23#include "xhci-mtk-unusual.h"
developer765b1982021-06-24 09:18:15 +080024
25static int t_test_j(struct xhci_hcd_mtk *mtk, int argc, char **argv);
26static int t_test_k(struct xhci_hcd_mtk *mtk, int argc, char **argv);
27static int t_test_se0(struct xhci_hcd_mtk *mtk, int argc, char **argv);
28static int t_test_packet(struct xhci_hcd_mtk *mtk, int argc, char **argv);
29static int t_test_suspend(struct xhci_hcd_mtk *mtk, int argc, char **argv);
30static int t_test_resume(struct xhci_hcd_mtk *mtk, int argc, char **argv);
31static int t_test_get_device_descriptor(struct xhci_hcd_mtk *mtk,
32 int argc, char **argv);
33static int t_test_enumerate_bus(struct xhci_hcd_mtk *mtk,
34 int argc, char **argv);
35static int t_power_u1u2(struct xhci_hcd_mtk *mtk, int argc, char **argv);
36
37#define PORT_PLS_VALUE(p) ((p >> 5) & 0xf)
38
39#define MAX_NAME_SIZE 32
40#define MAX_ARG_SIZE 4
41
42struct hqa_test_cmd {
43 char name[MAX_NAME_SIZE];
44 int (*cb_func)(struct xhci_hcd_mtk *mtk, int argc, char **argv);
45 char *discription;
46};
47
48
49struct hqa_test_cmd xhci_mtk_hqa_cmds[] = {
50 {"test.j", &t_test_j, "Test_J"},
51 {"test.k", &t_test_k, "Test_K"},
52 {"test.se0", &t_test_se0, "Test_SE0_NAK"},
53 {"test.packet", &t_test_packet, "Test_PACKET"},
54 {"test.suspend", &t_test_suspend, "Port Suspend"},
55 {"test.resume", &t_test_resume, "Port Resume"},
56 {"test.enumbus", &t_test_enumerate_bus, "Enumerate Bus"},
57 {"test.getdesc", &t_test_get_device_descriptor,
58 "Get Device Discriptor"},
59 {"pm.u1u2", &t_power_u1u2, "Port U1,U2"},
60 {"", NULL, ""},
61};
62
63
64int call_hqa_func(struct xhci_hcd_mtk *mtk, char *buf)
65{
66 struct hqa_test_cmd *hqa;
67 struct usb_hcd *hcd = mtk->hcd;
68 char *argv[MAX_ARG_SIZE];
69 int argc;
70 int i;
71
72 argc = 0;
73 do {
74 argv[argc] = strsep(&buf, " ");
75 xhci_err(hcd_to_xhci(hcd), "[%d] %s\r\n", argc, argv[argc]);
76 argc++;
77 } while (buf);
78
79 for (i = 0; i < ARRAY_SIZE(xhci_mtk_hqa_cmds); i++) {
80 hqa = &xhci_mtk_hqa_cmds[i];
81 if ((!strcmp(hqa->name, argv[0])) && (hqa->cb_func != NULL))
82 return hqa->cb_func(mtk, argc, argv);
83 }
84
85 return -1;
86}
87
88static int test_mode_enter(struct xhci_hcd_mtk *mtk,
89 u32 port_id, u32 test_value)
90{
91 struct usb_hcd *hcd = mtk->hcd;
92 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
93 u32 __iomem *addr;
94 u32 temp;
95
96 if (mtk->test_mode == 0) {
97 xhci_stop(hcd);
98 xhci_halt(xhci);
99 }
100
101 addr = &xhci->op_regs->port_power_base +
102 NUM_PORT_REGS * ((port_id - 1) & 0xff);
103 temp = readl(addr);
104 temp &= ~(0xf << 28);
105 temp |= (test_value << 28);
106 writel(temp, addr);
107 mtk->test_mode = 1;
108
109 return 0;
110}
111
112static int test_mode_exit(struct xhci_hcd_mtk *mtk)
113{
developerba28e032021-12-07 10:40:00 +0800114 if (mtk->test_mode == 1)
developer765b1982021-06-24 09:18:15 +0800115 mtk->test_mode = 0;
developerba28e032021-12-07 10:40:00 +0800116
developer765b1982021-06-24 09:18:15 +0800117 return 0;
118}
119
120static int t_test_j(struct xhci_hcd_mtk *mtk, int argc, char **argv)
121{
122 struct usb_hcd *hcd = mtk->hcd;
123 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
124 long port_id;
125 u32 test_value;
126
127 port_id = 2;
128 test_value = 1;
129
130 if (argc > 1 && kstrtol(argv[1], 10, &port_id))
131 xhci_err(xhci, "mu3h %s get port-id failed\n", __func__);
132
133 xhci_err(xhci, "mu3h %s test port%d\n", __func__, (int)port_id);
134 test_mode_enter(mtk, port_id, test_value);
135
136 return 0;
137}
138
139static int t_test_k(struct xhci_hcd_mtk *mtk, int argc, char **argv)
140{
141 struct usb_hcd *hcd = mtk->hcd;
142 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
143 long port_id;
144 u32 test_value;
145
146 port_id = 2;
147 test_value = 2;
148
149 if (argc > 1 && kstrtol(argv[1], 10, &port_id))
150 xhci_err(xhci, "mu3h %s get port-id failed\n", __func__);
151
152 xhci_err(xhci, "mu3h %s test port%d\n", __func__, (int)port_id);
153 test_mode_enter(mtk, port_id, test_value);
154
155 return 0;
156}
157
158static int t_test_se0(struct xhci_hcd_mtk *mtk, int argc, char **argv)
159{
160 struct usb_hcd *hcd = mtk->hcd;
161 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
162 long port_id;
163 u32 test_value;
164
165 port_id = 2;
166 test_value = 3;
167
168 if (argc > 1 && kstrtol(argv[1], 10, &port_id))
169 xhci_err(xhci, "mu3h %s get port-id failed\n", __func__);
170
171 xhci_err(xhci, "mu3h %s test port%ld\n", __func__, port_id);
172 test_mode_enter(mtk, port_id, test_value);
173
174 return 0;
175}
176
177static int t_test_packet(struct xhci_hcd_mtk *mtk, int argc, char **argv)
178{
179 struct usb_hcd *hcd = mtk->hcd;
180 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
181 long port_id;
182 u32 test_value;
183
184 port_id = 2;
185 test_value = 4;
186
187 if (argc > 1 && kstrtol(argv[1], 10, &port_id))
188 xhci_err(xhci, "mu3h %s get port-id failed\n", __func__);
189
190 xhci_err(xhci, "mu3h %s test port%ld\n", __func__, port_id);
191 test_mode_enter(mtk, port_id, test_value);
192
193 return 0;
194}
195
196/* only for u3 ports, valid values are 1, 2, ...*/
197static int t_power_u1u2(struct xhci_hcd_mtk *mtk, int argc, char **argv)
198{
199 struct usb_hcd *hcd = mtk->hcd;
200 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
201 u32 __iomem *addr;
202 u32 temp;
203 int port_id;
204 int retval = 0;
205 int u_num = 1;
206 int u1_val = 1;
207 int u2_val = 0;
208
209 port_id = 1; /* first u3port by default */
210
211 if (argc > 1 && kstrtoint(argv[1], 10, &port_id))
212 xhci_err(xhci, "mu3h %s get port-id failed\n", __func__);
213
214 if (argc > 2 && kstrtoint(argv[2], 10, &u_num))
215 xhci_err(xhci, "mu3h %s get u_num failed\n", __func__);
216
217 if (argc > 3 && kstrtoint(argv[3], 10, &u1_val))
218 xhci_err(xhci, "mu3h %s get u1_val failed\n", __func__);
219
220 if (argc > 4 && kstrtoint(argv[4], 10, &u2_val))
221 xhci_err(xhci, "mu3h %s get u2_val failed\n", __func__);
222
223 xhci_err(xhci, "mu3h %s test port%d, u_num%d, u1_val%d, u2_val%d\n",
224 __func__, (int)port_id, u_num, u1_val, u2_val);
225
226 if (mtk->test_mode == 1) {
227 xhci_err(xhci, "please suspend port first\n");
228 return -1;
229 }
230
231 xhci_err(xhci, "%s: stop port polling\n", __func__);
232 clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
233 del_timer_sync(&hcd->rh_timer);
234 clear_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags);
235 del_timer_sync(&xhci->shared_hcd->rh_timer);
236 clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
237 clear_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags);
238
239 addr = &xhci->op_regs->port_power_base +
240 NUM_PORT_REGS * ((port_id - 1) & 0xff);
241
242 temp = readl(addr);
243 if (u_num == 1) {
244 temp &= ~PORT_U1_TIMEOUT_MASK;
245 temp |= PORT_U1_TIMEOUT(u1_val);
246 } else if (u_num == 2) {
247 temp &= ~PORT_U2_TIMEOUT_MASK;
248 temp |= PORT_U2_TIMEOUT(u2_val);
249 } else if (u_num == 3) {
250 temp &= ~(PORT_U1_TIMEOUT_MASK | PORT_U2_TIMEOUT_MASK);
251 temp |= PORT_U1_TIMEOUT(u1_val) | PORT_U2_TIMEOUT(u2_val);
252 }
253
254 writel(temp, addr);
255
256 return retval;
257}
258
259
260static int t_test_suspend(struct xhci_hcd_mtk *mtk, int argc, char **argv)
261{
262 struct usb_hcd *hcd = mtk->hcd;
263 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
264 u32 __iomem *addr;
265 u32 temp;
266 long port_id;
267
268 port_id = 2;
269
270 if (argc > 1 && kstrtol(argv[1], 10, &port_id))
271 xhci_err(xhci, "mu3h %s get port-id failed\n", __func__);
272
273 xhci_err(xhci, "mu3h %s test port%d\n", __func__, (int)port_id);
274
275 xhci_err(xhci, "%s: stop port polling\n", __func__);
276 clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
277 del_timer_sync(&hcd->rh_timer);
278 clear_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags);
279 del_timer_sync(&xhci->shared_hcd->rh_timer);
280 clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
281 clear_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags);
282
283 temp = readl(&xhci->ir_set->irq_pending);
284 writel(ER_IRQ_DISABLE(temp), &xhci->ir_set->irq_pending);
285
286 if (mtk->test_mode == 1)
287 test_mode_exit(mtk);
288
289 /* set PLS = 3 */
290 addr = &xhci->op_regs->port_status_base +
291 NUM_PORT_REGS*((port_id - 1) & 0xff);
292
293 temp = readl(addr);
294 temp = xhci_port_state_to_neutral(temp);
295 temp = (temp & ~(0xf << 5));
296 temp = (temp | (3 << 5) | PORT_LINK_STROBE);
297 writel(temp, addr);
298 xhci_handshake(addr, (0xf << 5), (3 << 5), 30*1000);
299
300 temp = readl(addr);
301 if (PORT_PLS_VALUE(temp) != 3)
302 xhci_err(xhci, "port not enter suspend state\n");
303 else
304 xhci_err(xhci, "port enter suspend state\n");
305
306 return 0;
307}
308
309static int t_test_resume(struct xhci_hcd_mtk *mtk, int argc, char **argv)
310{
311 struct usb_hcd *hcd = mtk->hcd;
312 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
313 u32 __iomem *addr;
314 u32 temp;
315 long port_id;
316 int retval = 0;
317
318 port_id = 2;
319
320 if (argc > 1 && kstrtol(argv[1], 10, &port_id))
321 xhci_err(xhci, "mu3h %s get port-id failed\n", __func__);
322
323 xhci_err(xhci, "mu3h %s test port%d\n", __func__, (int)port_id);
324
325 if (mtk->test_mode == 1) {
326 xhci_err(xhci, "please suspend port first\n");
327 return -1;
328 }
329 addr = &xhci->op_regs->port_status_base +
330 NUM_PORT_REGS * ((port_id - 1) & 0xff);
331
332 temp = readl(addr);
333 if (PORT_PLS_VALUE(temp) != 3) {
334 xhci_err(xhci, "port not in suspend state, please suspend port first\n");
335 retval = -1;
336 } else {
337 temp = xhci_port_state_to_neutral(temp);
338 temp = (temp & ~(0xf << 5));
339 temp = (temp | (15 << 5) | PORT_LINK_STROBE);
340 writel(temp, addr);
341 mdelay(20);
342
343 temp = readl(addr);
344 temp = xhci_port_state_to_neutral(temp);
345 temp = (temp & ~(0xf << 5));
346 temp = (temp | PORT_LINK_STROBE);
347 writel(temp, addr);
348
349 xhci_handshake(addr, (0xf << 5), (0 << 5), 100*1000);
350 temp = readl(addr);
351 if (PORT_PLS_VALUE(temp) != 0) {
352 xhci_err(xhci, "rusume fail,%x\n",
353 PORT_PLS_VALUE(temp));
354 retval = -1;
355 } else {
356 xhci_err(xhci, "port resume ok\n");
357 }
358 }
359
360 return retval;
361}
362
363static int t_test_enumerate_bus(struct xhci_hcd_mtk *mtk, int argc, char **argv)
364{
365 struct usb_hcd *hcd = mtk->hcd;
366 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
367 struct usb_device *usb2_rh;
368 struct usb_device *udev;
369 long port_id;
370 u32 retval;
371
372 port_id = 2;
373
374 if (argc > 1 && kstrtol(argv[1], 10, &port_id))
375 xhci_err(xhci, "mu3h %s get port-id failed\n", __func__);
376
377 xhci_err(xhci, "mu3h %s test port%d\n", __func__, (int)port_id);
378
379 if (mtk->test_mode == 1) {
380 test_mode_exit(mtk);
381 return 0;
382 }
383
384 usb2_rh = hcd->self.root_hub;
385 udev = usb_hub_find_child(usb2_rh, port_id - 1);
386
387 if (udev != NULL) {
388 retval = usb_reset_device(udev);
389 if (retval) {
390 xhci_err(xhci, "ERROR: enumerate bus fail!\n");
391 return -1;
392 }
393 } else {
394 xhci_err(xhci, "ERROR: Device does not exist!\n");
395 return -1;
396 }
397
398 return 0;
399}
400static int t_test_get_device_descriptor(struct xhci_hcd_mtk *mtk,
401 int argc, char **argv)
402{
403 struct usb_hcd *hcd = mtk->hcd;
404 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
405 struct usb_device *usb2_rh;
406 struct usb_device *udev;
407 long port_id;
408 u32 retval = 0;
409
410 port_id = 2;
411
412 if (argc > 1 && kstrtol(argv[1], 10, &port_id))
413 xhci_err(xhci, "mu3h %s get port-id failed\n", __func__);
414
415 xhci_err(xhci, "mu3h %s test port%d\n", __func__, (int)port_id);
416
417 if (mtk->test_mode == 1) {
418 test_mode_exit(mtk);
419 msleep(2000);
420 }
421
422 usb2_rh = hcd->self.root_hub;
423
424 udev = usb_hub_find_child(usb2_rh, port_id - 1);
425
426 if (udev != NULL) {
427 retval = usb_get_device_descriptor(udev, USB_DT_DEVICE_SIZE);
428 if (retval != sizeof(udev->descriptor)) {
429 xhci_err(xhci, "ERROR: get device descriptor fail!\n");
430 return -1;
431 }
432 } else {
433 xhci_err(xhci, "ERROR: Device does not exist!\n");
434 return -1;
435 }
436
437 return 0;
438}
439
developerba28e032021-12-07 10:40:00 +0800440static ssize_t hqa_show(struct device *dev,
developer765b1982021-06-24 09:18:15 +0800441 struct device_attribute *attr, char *buf)
442{
developerba28e032021-12-07 10:40:00 +0800443 struct xhci_hcd_mtk *mtk = dev_get_drvdata(dev);
444 struct usb_hcd *hcd = mtk->hcd;
445 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
446 u32 __iomem *addr;
447 u32 val;
448 u32 ports;
developer765b1982021-06-24 09:18:15 +0800449 int len = 0;
450 int bufLen = PAGE_SIZE;
451 struct hqa_test_cmd *hqa;
452 int i;
453
454 len += snprintf(buf+len, bufLen-len, "info:\n");
455 len += snprintf(buf+len, bufLen-len,
456 "\techo -n item port-id > hqa\n");
457 len += snprintf(buf+len, bufLen-len,
458 "\tport-id : based on number of usb3-port, e.g.\n");
459 len += snprintf(buf+len, bufLen-len,
460 "\t\txHCI with 1 u3p, 2 u2p: 1st u2p-id is 2(1+1), 2nd is 3\n");
461 len += snprintf(buf+len, bufLen-len, "items:\n");
462
463 for (i = 0; i < ARRAY_SIZE(xhci_mtk_hqa_cmds); i++) {
464 hqa = &xhci_mtk_hqa_cmds[i];
465 len += snprintf(buf+len, bufLen-len,
466 "\t%s: %s\n", hqa->name, hqa->discription);
467 }
468
developerba28e032021-12-07 10:40:00 +0800469 ports = mtk->num_u3_ports + mtk->num_u2_ports;
470 for (i = mtk->num_u3_ports + 1; i <= ports; i++) {
471 addr = &xhci->op_regs->port_power_base +
472 NUM_PORT_REGS * ((i - 1) & 0xff);
473 val = readl(addr);
474 len += snprintf(buf+len, bufLen-len,
475 "USB20 Port%i PORTMSC[31,28] 4b'0000: 0x%08X\n",
476 i, val);
477 }
478
developer765b1982021-06-24 09:18:15 +0800479 return len;
480}
481
developerba28e032021-12-07 10:40:00 +0800482static ssize_t hqa_store(struct device *dev,
developer765b1982021-06-24 09:18:15 +0800483 struct device_attribute *attr, const char *buf, size_t count)
484{
485 struct xhci_hcd_mtk *mtk = dev_get_drvdata(dev);
486 struct usb_hcd *hcd = mtk->hcd;
487 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
488 int retval;
489
490 retval = call_hqa_func(mtk, (char *)buf);
491 if (retval < 0) {
492 xhci_err(xhci, "mu3h cli fail\n");
493 return -1;
494 }
495
496 return count;
497}
498
developerba28e032021-12-07 10:40:00 +0800499static DEVICE_ATTR_RW(hqa);
developer765b1982021-06-24 09:18:15 +0800500
developerba28e032021-12-07 10:40:00 +0800501static ssize_t usb3hqa_show(struct device *dev,
developer765b1982021-06-24 09:18:15 +0800502 struct device_attribute *attr, char *buf)
503{
developerba28e032021-12-07 10:40:00 +0800504 struct xhci_hcd_mtk *mtk = dev_get_drvdata(dev);
developer765b1982021-06-24 09:18:15 +0800505 struct usb_hcd *hcd = mtk->hcd;
506 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
developerba28e032021-12-07 10:40:00 +0800507 ssize_t cnt = 0;
508 u32 __iomem *addr;
509 u32 val;
510 u32 i;
511 int ports;
developer765b1982021-06-24 09:18:15 +0800512
developerba28e032021-12-07 10:40:00 +0800513 cnt += sprintf(buf + cnt, "usb3hqa usage:\n");
514 cnt += sprintf(buf + cnt, " echo u3port >usb3hqa\n");
developer765b1982021-06-24 09:18:15 +0800515
developerba28e032021-12-07 10:40:00 +0800516 ports = mtk->num_u3_ports + mtk->num_u2_ports;
517 for (i = 1; i <= ports; i++) {
518 addr = &xhci->op_regs->port_status_base +
519 NUM_PORT_REGS * ((i - 1) & 0xff);
520 val = readl(addr);
521 if (i < mtk->num_u3_ports)
522 cnt += sprintf(buf + cnt,
523 "USB30 Port%i: 0x%08X\n", i, val);
524 else
525 cnt += sprintf(buf + cnt,
526 "USB20 Port%i: 0x%08X\n", i, val);
developer765b1982021-06-24 09:18:15 +0800527 }
528
developerba28e032021-12-07 10:40:00 +0800529 if (mtk->hqa_pos) {
530 cnt += sprintf(buf + cnt, "%s", mtk->hqa_buf);
531 mtk->hqa_pos = 0;
developer765b1982021-06-24 09:18:15 +0800532 }
533
developerba28e032021-12-07 10:40:00 +0800534 return cnt;
developer765b1982021-06-24 09:18:15 +0800535}
536
developer765b1982021-06-24 09:18:15 +0800537static ssize_t
developerba28e032021-12-07 10:40:00 +0800538usb3hqa_store(struct device *dev, struct device_attribute *attr,
developer765b1982021-06-24 09:18:15 +0800539 const char *buf, size_t n)
540{
541 struct xhci_hcd_mtk *mtk = dev_get_drvdata(dev);
542 struct usb_hcd *hcd = mtk->hcd;
543 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
developerba28e032021-12-07 10:40:00 +0800544 u32 __iomem *addr;
545 u32 val;
546 int port;
547 int words;
developer765b1982021-06-24 09:18:15 +0800548
developerba28e032021-12-07 10:40:00 +0800549 mtk->hqa_pos = 0;
550 memset(mtk->hqa_buf, 0, mtk->hqa_size);
developer765b1982021-06-24 09:18:15 +0800551
developerba28e032021-12-07 10:40:00 +0800552 hqa_info(mtk, "usb3hqa: %s\n", buf);
553
554 words = sscanf(buf, "%d", &port);
555 if ((words != 1) ||
556 (port < 1 || port > mtk->num_u3_ports)) {
557 hqa_info(mtk, "usb3hqa: param number:%i, port:%i failure\n",
558 words, port);
559 return -EINVAL;
developer765b1982021-06-24 09:18:15 +0800560 }
561
developerba28e032021-12-07 10:40:00 +0800562 addr = &xhci->op_regs->port_status_base +
563 NUM_PORT_REGS * ((port - 1) & 0xff);
564 val = readl(addr);
565 val &= ~(PORT_PLS_MASK);
566 val |= (PORT_LINK_STROBE | XDEV_COMP_MODE);
567 writel(val, addr);
568 hqa_info(mtk, "usb3hqa: port%i: 0x%08X but 0x%08X\n",
569 port, val, readl(addr));
570
developer765b1982021-06-24 09:18:15 +0800571 return n;
572}
developerba28e032021-12-07 10:40:00 +0800573static DEVICE_ATTR_RW(usb3hqa);
developer765b1982021-06-24 09:18:15 +0800574
575static struct device_attribute *mu3h_hqa_attr_list[] = {
576 &dev_attr_hqa,
developerba28e032021-12-07 10:40:00 +0800577 &dev_attr_usb3hqa,
578#include "unusual-statement.h"
developer765b1982021-06-24 09:18:15 +0800579};
580
developerba28e032021-12-07 10:40:00 +0800581int hqa_create_attr(struct device *dev)
developer765b1982021-06-24 09:18:15 +0800582{
583 int idx, err = 0;
584 int num = ARRAY_SIZE(mu3h_hqa_attr_list);
developerba28e032021-12-07 10:40:00 +0800585 struct xhci_hcd_mtk *mtk = dev_get_drvdata(dev);
developer765b1982021-06-24 09:18:15 +0800586
developerba28e032021-12-07 10:40:00 +0800587 if (dev == NULL || mtk == NULL)
developer765b1982021-06-24 09:18:15 +0800588 return -EINVAL;
589
developerba28e032021-12-07 10:40:00 +0800590 mtk->hqa_size = HQA_PREFIX_SIZE;
591 mtk->hqa_pos = 0;
592 mtk->hqa_buf = kzalloc(mtk->hqa_size, GFP_KERNEL);
593 if (!mtk->hqa_buf)
594 return -ENOMEM;
developer765b1982021-06-24 09:18:15 +0800595
596 for (idx = 0; idx < num; idx++) {
597 err = device_create_file(dev, mu3h_hqa_attr_list[idx]);
598 if (err)
599 break;
600 }
601
602 return err;
603}
604
developerba28e032021-12-07 10:40:00 +0800605void hqa_remove_attr(struct device *dev)
developer765b1982021-06-24 09:18:15 +0800606{
607 int idx;
608 int num = ARRAY_SIZE(mu3h_hqa_attr_list);
developerba28e032021-12-07 10:40:00 +0800609 struct xhci_hcd_mtk *mtk = dev_get_drvdata(dev);
developer765b1982021-06-24 09:18:15 +0800610
611 for (idx = 0; idx < num; idx++)
612 device_remove_file(dev, mu3h_hqa_attr_list[idx]);
developerba28e032021-12-07 10:40:00 +0800613
614 kfree(mtk->hqa_buf);
615 mtk->hqa_size = 0;
616 mtk->hqa_pos = 0;
developer765b1982021-06-24 09:18:15 +0800617}