blob: 36564d2c2757248fc79f7c72ff9b9f87a123b700 [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>
developerabd06d72022-03-03 16:13:41 +080019#include <linux/usb.h>
20#include <linux/usb/hcd.h>
developerba28e032021-12-07 10:40:00 +080021#include <dt-bindings/phy/phy.h>
developer765b1982021-06-24 09:18:15 +080022#include "../core/usb.h"
23#include "xhci-mtk.h"
developerba28e032021-12-07 10:40:00 +080024#include "xhci-mtk-test.h"
25#include "xhci-mtk-unusual.h"
developer765b1982021-06-24 09:18:15 +080026
27static int t_test_j(struct xhci_hcd_mtk *mtk, int argc, char **argv);
28static int t_test_k(struct xhci_hcd_mtk *mtk, int argc, char **argv);
29static int t_test_se0(struct xhci_hcd_mtk *mtk, int argc, char **argv);
30static int t_test_packet(struct xhci_hcd_mtk *mtk, int argc, char **argv);
31static int t_test_suspend(struct xhci_hcd_mtk *mtk, int argc, char **argv);
32static int t_test_resume(struct xhci_hcd_mtk *mtk, int argc, char **argv);
33static int t_test_get_device_descriptor(struct xhci_hcd_mtk *mtk,
34 int argc, char **argv);
35static int t_test_enumerate_bus(struct xhci_hcd_mtk *mtk,
36 int argc, char **argv);
developerabd06d72022-03-03 16:13:41 +080037static int t_debug_port(struct xhci_hcd_mtk *mtk, int argc, char **argv);
developer765b1982021-06-24 09:18:15 +080038static int t_power_u1u2(struct xhci_hcd_mtk *mtk, int argc, char **argv);
39
40#define PORT_PLS_VALUE(p) ((p >> 5) & 0xf)
developerabd06d72022-03-03 16:13:41 +080041/* ip_xhci_cap register */
42#define CAP_U3_PORT_NUM(p) ((p) & 0xff)
43#define CAP_U2_PORT_NUM(p) (((p) >> 8) & 0xff)
developer765b1982021-06-24 09:18:15 +080044
45#define MAX_NAME_SIZE 32
46#define MAX_ARG_SIZE 4
47
developerabd06d72022-03-03 16:13:41 +080048struct class_info {
49 int class;
50 char *class_name;
51};
52
53static const struct class_info clas_info[] = {
54 /* max. 5 chars. per name string */
55 {USB_CLASS_PER_INTERFACE, ">ifc"},
56 {USB_CLASS_AUDIO, "audio"},
57 {USB_CLASS_COMM, "comm."},
58 {USB_CLASS_HID, "HID"},
59 {USB_CLASS_PHYSICAL, "PID"},
60 {USB_CLASS_STILL_IMAGE, "still"},
61 {USB_CLASS_PRINTER, "print"},
62 {USB_CLASS_MASS_STORAGE, "stor."},
63 {USB_CLASS_HUB, "hub"},
64 {USB_CLASS_CDC_DATA, "data"},
65 {USB_CLASS_CSCID, "scard"},
66 {USB_CLASS_CONTENT_SEC, "c-sec"},
67 {USB_CLASS_VIDEO, "video"},
68 {USB_CLASS_WIRELESS_CONTROLLER, "wlcon"},
69 {USB_CLASS_MISC, "misc"},
70 {USB_CLASS_APP_SPEC, "app."},
71 {USB_CLASS_VENDOR_SPEC, "vend."},
72 {-1, "unk."} /* leave as last */
73};
74
developer765b1982021-06-24 09:18:15 +080075struct hqa_test_cmd {
76 char name[MAX_NAME_SIZE];
77 int (*cb_func)(struct xhci_hcd_mtk *mtk, int argc, char **argv);
78 char *discription;
79};
80
developer765b1982021-06-24 09:18:15 +080081struct hqa_test_cmd xhci_mtk_hqa_cmds[] = {
82 {"test.j", &t_test_j, "Test_J"},
83 {"test.k", &t_test_k, "Test_K"},
84 {"test.se0", &t_test_se0, "Test_SE0_NAK"},
85 {"test.packet", &t_test_packet, "Test_PACKET"},
86 {"test.suspend", &t_test_suspend, "Port Suspend"},
87 {"test.resume", &t_test_resume, "Port Resume"},
88 {"test.enumbus", &t_test_enumerate_bus, "Enumerate Bus"},
89 {"test.getdesc", &t_test_get_device_descriptor,
90 "Get Device Discriptor"},
developerabd06d72022-03-03 16:13:41 +080091 {"test.debug", &t_debug_port, "debug Port infor"},
developer765b1982021-06-24 09:18:15 +080092 {"pm.u1u2", &t_power_u1u2, "Port U1,U2"},
93 {"", NULL, ""},
94};
95
developerabd06d72022-03-03 16:13:41 +080096static const char *class_decode(const int class)
97{
98 int i;
99
100 for (i = 0; clas_info[i].class != -1; i++)
101 if (clas_info[i].class == class)
102 break;
103 return clas_info[i].class_name;
104}
developer765b1982021-06-24 09:18:15 +0800105
106int call_hqa_func(struct xhci_hcd_mtk *mtk, char *buf)
107{
108 struct hqa_test_cmd *hqa;
109 struct usb_hcd *hcd = mtk->hcd;
110 char *argv[MAX_ARG_SIZE];
111 int argc;
112 int i;
113
114 argc = 0;
115 do {
116 argv[argc] = strsep(&buf, " ");
117 xhci_err(hcd_to_xhci(hcd), "[%d] %s\r\n", argc, argv[argc]);
118 argc++;
119 } while (buf);
120
121 for (i = 0; i < ARRAY_SIZE(xhci_mtk_hqa_cmds); i++) {
122 hqa = &xhci_mtk_hqa_cmds[i];
123 if ((!strcmp(hqa->name, argv[0])) && (hqa->cb_func != NULL))
124 return hqa->cb_func(mtk, argc, argv);
125 }
126
127 return -1;
128}
129
130static int test_mode_enter(struct xhci_hcd_mtk *mtk,
131 u32 port_id, u32 test_value)
132{
133 struct usb_hcd *hcd = mtk->hcd;
134 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
135 u32 __iomem *addr;
136 u32 temp;
137
138 if (mtk->test_mode == 0) {
139 xhci_stop(hcd);
140 xhci_halt(xhci);
141 }
142
143 addr = &xhci->op_regs->port_power_base +
144 NUM_PORT_REGS * ((port_id - 1) & 0xff);
145 temp = readl(addr);
146 temp &= ~(0xf << 28);
147 temp |= (test_value << 28);
148 writel(temp, addr);
149 mtk->test_mode = 1;
150
151 return 0;
152}
153
154static int test_mode_exit(struct xhci_hcd_mtk *mtk)
155{
developerba28e032021-12-07 10:40:00 +0800156 if (mtk->test_mode == 1)
developer765b1982021-06-24 09:18:15 +0800157 mtk->test_mode = 0;
developerba28e032021-12-07 10:40:00 +0800158
developer765b1982021-06-24 09:18:15 +0800159 return 0;
160}
161
162static int t_test_j(struct xhci_hcd_mtk *mtk, int argc, char **argv)
163{
164 struct usb_hcd *hcd = mtk->hcd;
165 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
166 long port_id;
167 u32 test_value;
168
169 port_id = 2;
170 test_value = 1;
171
172 if (argc > 1 && kstrtol(argv[1], 10, &port_id))
173 xhci_err(xhci, "mu3h %s get port-id failed\n", __func__);
174
175 xhci_err(xhci, "mu3h %s test port%d\n", __func__, (int)port_id);
176 test_mode_enter(mtk, port_id, test_value);
177
178 return 0;
179}
180
181static int t_test_k(struct xhci_hcd_mtk *mtk, int argc, char **argv)
182{
183 struct usb_hcd *hcd = mtk->hcd;
184 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
185 long port_id;
186 u32 test_value;
187
188 port_id = 2;
189 test_value = 2;
190
191 if (argc > 1 && kstrtol(argv[1], 10, &port_id))
192 xhci_err(xhci, "mu3h %s get port-id failed\n", __func__);
193
194 xhci_err(xhci, "mu3h %s test port%d\n", __func__, (int)port_id);
195 test_mode_enter(mtk, port_id, test_value);
196
197 return 0;
198}
199
200static int t_test_se0(struct xhci_hcd_mtk *mtk, int argc, char **argv)
201{
202 struct usb_hcd *hcd = mtk->hcd;
203 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
204 long port_id;
205 u32 test_value;
206
207 port_id = 2;
208 test_value = 3;
209
210 if (argc > 1 && kstrtol(argv[1], 10, &port_id))
211 xhci_err(xhci, "mu3h %s get port-id failed\n", __func__);
212
213 xhci_err(xhci, "mu3h %s test port%ld\n", __func__, port_id);
214 test_mode_enter(mtk, port_id, test_value);
215
216 return 0;
217}
218
219static int t_test_packet(struct xhci_hcd_mtk *mtk, int argc, char **argv)
220{
221 struct usb_hcd *hcd = mtk->hcd;
222 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
223 long port_id;
224 u32 test_value;
225
226 port_id = 2;
227 test_value = 4;
228
229 if (argc > 1 && kstrtol(argv[1], 10, &port_id))
230 xhci_err(xhci, "mu3h %s get port-id failed\n", __func__);
231
232 xhci_err(xhci, "mu3h %s test port%ld\n", __func__, port_id);
233 test_mode_enter(mtk, port_id, test_value);
234
235 return 0;
236}
237
238/* only for u3 ports, valid values are 1, 2, ...*/
239static int t_power_u1u2(struct xhci_hcd_mtk *mtk, int argc, char **argv)
240{
241 struct usb_hcd *hcd = mtk->hcd;
242 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
243 u32 __iomem *addr;
244 u32 temp;
245 int port_id;
246 int retval = 0;
247 int u_num = 1;
248 int u1_val = 1;
249 int u2_val = 0;
250
251 port_id = 1; /* first u3port by default */
252
253 if (argc > 1 && kstrtoint(argv[1], 10, &port_id))
254 xhci_err(xhci, "mu3h %s get port-id failed\n", __func__);
255
256 if (argc > 2 && kstrtoint(argv[2], 10, &u_num))
257 xhci_err(xhci, "mu3h %s get u_num failed\n", __func__);
258
259 if (argc > 3 && kstrtoint(argv[3], 10, &u1_val))
260 xhci_err(xhci, "mu3h %s get u1_val failed\n", __func__);
261
262 if (argc > 4 && kstrtoint(argv[4], 10, &u2_val))
263 xhci_err(xhci, "mu3h %s get u2_val failed\n", __func__);
264
265 xhci_err(xhci, "mu3h %s test port%d, u_num%d, u1_val%d, u2_val%d\n",
266 __func__, (int)port_id, u_num, u1_val, u2_val);
267
268 if (mtk->test_mode == 1) {
269 xhci_err(xhci, "please suspend port first\n");
270 return -1;
271 }
272
273 xhci_err(xhci, "%s: stop port polling\n", __func__);
274 clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
275 del_timer_sync(&hcd->rh_timer);
276 clear_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags);
277 del_timer_sync(&xhci->shared_hcd->rh_timer);
278 clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
279 clear_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags);
280
281 addr = &xhci->op_regs->port_power_base +
282 NUM_PORT_REGS * ((port_id - 1) & 0xff);
283
284 temp = readl(addr);
285 if (u_num == 1) {
286 temp &= ~PORT_U1_TIMEOUT_MASK;
287 temp |= PORT_U1_TIMEOUT(u1_val);
288 } else if (u_num == 2) {
289 temp &= ~PORT_U2_TIMEOUT_MASK;
290 temp |= PORT_U2_TIMEOUT(u2_val);
291 } else if (u_num == 3) {
292 temp &= ~(PORT_U1_TIMEOUT_MASK | PORT_U2_TIMEOUT_MASK);
293 temp |= PORT_U1_TIMEOUT(u1_val) | PORT_U2_TIMEOUT(u2_val);
294 }
295
296 writel(temp, addr);
297
298 return retval;
299}
300
developerabd06d72022-03-03 16:13:41 +0800301static void show_string(struct usb_device *udev, char *id, char *string)
302{
303 if (!string)
304 return;
305 dev_info(&udev->dev, "%s: %s\n", id, string);
306}
307
308static void announce_device(struct usb_device *udev)
309{
310 u16 bcdDevice = le16_to_cpu(udev->descriptor.bcdDevice);
311
312 dev_info(&udev->dev,
313 "New USB device found, idVendor=%04x, idProduct=%04x, bcdDevice=%2x.%02x\n",
314 le16_to_cpu(udev->descriptor.idVendor),
315 le16_to_cpu(udev->descriptor.idProduct),
316 bcdDevice >> 8, bcdDevice & 0xff);
317 dev_info(&udev->dev,
318 "New USB device strings: Mfr=%d, Product=%d, SerialNumber=%d\n",
319 udev->descriptor.iManufacturer,
320 udev->descriptor.iProduct,
321 udev->descriptor.iSerialNumber);
322 show_string(udev, "Product", udev->product);
323 show_string(udev, "Manufacturer", udev->manufacturer);
324 show_string(udev, "SerialNumber", udev->serial);
325}
326
327static int t_debug_port(struct xhci_hcd_mtk *mtk, int argc, char **argv)
328{
329 struct usb_hcd *hcd = mtk->hcd;
330 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
331 struct usb_device *usb2_rh;
332 struct usb_device *udev;
333 long port_id;
334 const struct usb_device_descriptor *desc;
335 u16 bcdUSB;
336 u16 bcdDevice;
337
338 port_id = 2;
339
340 if (argc > 1 && kstrtol(argv[1], 10, &port_id))
341 xhci_err(xhci, "mu3h %s get port-id failed\n", __func__);
342
343 xhci_err(xhci, "mu3h %s test port%d\n", __func__, (int)port_id);
344
345
346 usb2_rh = hcd->self.root_hub;
347 udev = usb_hub_find_child(usb2_rh, port_id - 1);
348 if (udev == NULL) {
349 xhci_err(xhci, "mu3h %s usb_hub_find_child(..., %i) failed\n", __func__, (int)port_id);
350 return -EPERM;
351 }
352
353 dev_info(&udev->dev, "%s\n", usb_state_string(udev->state));
354 if (udev && udev->state == USB_STATE_CONFIGURED) {
355 announce_device(udev);
356 desc = (const struct usb_device_descriptor *)&udev->descriptor;
357 bcdUSB = le16_to_cpu(desc->bcdUSB);
358 bcdDevice = le16_to_cpu(desc->bcdDevice);
359
360 dev_info(&udev->dev, "D: Ver=%2x.%02x Cls=%02x(%-5s) Sub=%02x Prot=%02x MxPS=%2d #Cfgs=%3d\n",
361 bcdUSB >> 8, bcdUSB & 0xff,
362 desc->bDeviceClass,
363 class_decode(desc->bDeviceClass),
364 desc->bDeviceSubClass,
365 desc->bDeviceProtocol,
366 desc->bMaxPacketSize0,
367 desc->bNumConfigurations);
368
369 dev_info(&udev->dev, "P: Vendor=%04x ProdID=%04x Rev=%2x.%02x\n",
370 le16_to_cpu(desc->idVendor),
371 le16_to_cpu(desc->idProduct),
372 bcdDevice >> 8, bcdDevice & 0xff);
373 }
374
375 return 0;
376}
developer765b1982021-06-24 09:18:15 +0800377
378static int t_test_suspend(struct xhci_hcd_mtk *mtk, int argc, char **argv)
379{
380 struct usb_hcd *hcd = mtk->hcd;
381 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
382 u32 __iomem *addr;
383 u32 temp;
384 long port_id;
385
386 port_id = 2;
387
388 if (argc > 1 && kstrtol(argv[1], 10, &port_id))
389 xhci_err(xhci, "mu3h %s get port-id failed\n", __func__);
390
391 xhci_err(xhci, "mu3h %s test port%d\n", __func__, (int)port_id);
392
393 xhci_err(xhci, "%s: stop port polling\n", __func__);
394 clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
395 del_timer_sync(&hcd->rh_timer);
396 clear_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags);
397 del_timer_sync(&xhci->shared_hcd->rh_timer);
398 clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
399 clear_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags);
400
401 temp = readl(&xhci->ir_set->irq_pending);
402 writel(ER_IRQ_DISABLE(temp), &xhci->ir_set->irq_pending);
403
404 if (mtk->test_mode == 1)
405 test_mode_exit(mtk);
406
407 /* set PLS = 3 */
408 addr = &xhci->op_regs->port_status_base +
409 NUM_PORT_REGS*((port_id - 1) & 0xff);
410
411 temp = readl(addr);
412 temp = xhci_port_state_to_neutral(temp);
413 temp = (temp & ~(0xf << 5));
414 temp = (temp | (3 << 5) | PORT_LINK_STROBE);
415 writel(temp, addr);
416 xhci_handshake(addr, (0xf << 5), (3 << 5), 30*1000);
417
418 temp = readl(addr);
419 if (PORT_PLS_VALUE(temp) != 3)
420 xhci_err(xhci, "port not enter suspend state\n");
421 else
422 xhci_err(xhci, "port enter suspend state\n");
423
424 return 0;
425}
426
427static int t_test_resume(struct xhci_hcd_mtk *mtk, int argc, char **argv)
428{
429 struct usb_hcd *hcd = mtk->hcd;
430 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
431 u32 __iomem *addr;
432 u32 temp;
433 long port_id;
434 int retval = 0;
435
436 port_id = 2;
437
438 if (argc > 1 && kstrtol(argv[1], 10, &port_id))
439 xhci_err(xhci, "mu3h %s get port-id failed\n", __func__);
440
441 xhci_err(xhci, "mu3h %s test port%d\n", __func__, (int)port_id);
442
443 if (mtk->test_mode == 1) {
444 xhci_err(xhci, "please suspend port first\n");
445 return -1;
446 }
447 addr = &xhci->op_regs->port_status_base +
448 NUM_PORT_REGS * ((port_id - 1) & 0xff);
449
450 temp = readl(addr);
451 if (PORT_PLS_VALUE(temp) != 3) {
452 xhci_err(xhci, "port not in suspend state, please suspend port first\n");
453 retval = -1;
454 } else {
455 temp = xhci_port_state_to_neutral(temp);
456 temp = (temp & ~(0xf << 5));
457 temp = (temp | (15 << 5) | PORT_LINK_STROBE);
458 writel(temp, addr);
459 mdelay(20);
460
461 temp = readl(addr);
462 temp = xhci_port_state_to_neutral(temp);
463 temp = (temp & ~(0xf << 5));
464 temp = (temp | PORT_LINK_STROBE);
465 writel(temp, addr);
466
467 xhci_handshake(addr, (0xf << 5), (0 << 5), 100*1000);
468 temp = readl(addr);
469 if (PORT_PLS_VALUE(temp) != 0) {
470 xhci_err(xhci, "rusume fail,%x\n",
471 PORT_PLS_VALUE(temp));
472 retval = -1;
473 } else {
474 xhci_err(xhci, "port resume ok\n");
475 }
476 }
477
478 return retval;
479}
480
481static int t_test_enumerate_bus(struct xhci_hcd_mtk *mtk, int argc, char **argv)
482{
483 struct usb_hcd *hcd = mtk->hcd;
484 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
485 struct usb_device *usb2_rh;
486 struct usb_device *udev;
487 long port_id;
488 u32 retval;
489
490 port_id = 2;
491
492 if (argc > 1 && kstrtol(argv[1], 10, &port_id))
493 xhci_err(xhci, "mu3h %s get port-id failed\n", __func__);
494
495 xhci_err(xhci, "mu3h %s test port%d\n", __func__, (int)port_id);
496
497 if (mtk->test_mode == 1) {
498 test_mode_exit(mtk);
499 return 0;
500 }
501
502 usb2_rh = hcd->self.root_hub;
503 udev = usb_hub_find_child(usb2_rh, port_id - 1);
504
505 if (udev != NULL) {
506 retval = usb_reset_device(udev);
507 if (retval) {
508 xhci_err(xhci, "ERROR: enumerate bus fail!\n");
509 return -1;
510 }
511 } else {
512 xhci_err(xhci, "ERROR: Device does not exist!\n");
513 return -1;
514 }
515
516 return 0;
517}
518static int t_test_get_device_descriptor(struct xhci_hcd_mtk *mtk,
519 int argc, char **argv)
520{
521 struct usb_hcd *hcd = mtk->hcd;
522 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
523 struct usb_device *usb2_rh;
524 struct usb_device *udev;
525 long port_id;
526 u32 retval = 0;
527
528 port_id = 2;
529
530 if (argc > 1 && kstrtol(argv[1], 10, &port_id))
531 xhci_err(xhci, "mu3h %s get port-id failed\n", __func__);
532
533 xhci_err(xhci, "mu3h %s test port%d\n", __func__, (int)port_id);
534
535 if (mtk->test_mode == 1) {
536 test_mode_exit(mtk);
537 msleep(2000);
538 }
539
540 usb2_rh = hcd->self.root_hub;
541
542 udev = usb_hub_find_child(usb2_rh, port_id - 1);
543
544 if (udev != NULL) {
545 retval = usb_get_device_descriptor(udev, USB_DT_DEVICE_SIZE);
546 if (retval != sizeof(udev->descriptor)) {
547 xhci_err(xhci, "ERROR: get device descriptor fail!\n");
548 return -1;
549 }
550 } else {
551 xhci_err(xhci, "ERROR: Device does not exist!\n");
552 return -1;
553 }
554
555 return 0;
556}
557
developerba28e032021-12-07 10:40:00 +0800558static ssize_t hqa_show(struct device *dev,
developer765b1982021-06-24 09:18:15 +0800559 struct device_attribute *attr, char *buf)
560{
developerba28e032021-12-07 10:40:00 +0800561 struct xhci_hcd_mtk *mtk = dev_get_drvdata(dev);
562 struct usb_hcd *hcd = mtk->hcd;
563 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
564 u32 __iomem *addr;
565 u32 val;
566 u32 ports;
developer765b1982021-06-24 09:18:15 +0800567 int len = 0;
developer765b1982021-06-24 09:18:15 +0800568 struct hqa_test_cmd *hqa;
569 int i;
570
developerabd06d72022-03-03 16:13:41 +0800571 len += sprintf(buf+len, "info:\n");
572 len += sprintf(buf+len,
developer765b1982021-06-24 09:18:15 +0800573 "\techo -n item port-id > hqa\n");
developerabd06d72022-03-03 16:13:41 +0800574 len += sprintf(buf+len,
developer765b1982021-06-24 09:18:15 +0800575 "\tport-id : based on number of usb3-port, e.g.\n");
developerabd06d72022-03-03 16:13:41 +0800576 len += sprintf(buf+len,
developer765b1982021-06-24 09:18:15 +0800577 "\t\txHCI with 1 u3p, 2 u2p: 1st u2p-id is 2(1+1), 2nd is 3\n");
developerabd06d72022-03-03 16:13:41 +0800578 len += sprintf(buf+len, "items:\n");
developer765b1982021-06-24 09:18:15 +0800579
580 for (i = 0; i < ARRAY_SIZE(xhci_mtk_hqa_cmds); i++) {
581 hqa = &xhci_mtk_hqa_cmds[i];
developerabd06d72022-03-03 16:13:41 +0800582 len += sprintf(buf+len,
developer765b1982021-06-24 09:18:15 +0800583 "\t%s: %s\n", hqa->name, hqa->discription);
584 }
585
developerba28e032021-12-07 10:40:00 +0800586 ports = mtk->num_u3_ports + mtk->num_u2_ports;
developerabd06d72022-03-03 16:13:41 +0800587 for (i = 1; i <= ports; i++) {
588 addr = &xhci->op_regs->port_status_base +
developerba28e032021-12-07 10:40:00 +0800589 NUM_PORT_REGS * ((i - 1) & 0xff);
590 val = readl(addr);
developerabd06d72022-03-03 16:13:41 +0800591 if (i <= mtk->num_u3_ports)
592 len += sprintf(buf + len,
593 "USB30 Port%i: 0x%08X\n", i, val);
594 else {
595 len += sprintf(buf + len,
596 "USB20 Port%i: 0x%08X\n", i, val);
597
598 addr = &xhci->op_regs->port_power_base +
599 NUM_PORT_REGS * ((i - 1) & 0xff);
600 val = readl(addr);
601 len += sprintf(buf+len,
602 "USB20 Port%i PORTMSC[31,28] 4b'0000: 0x%08X\n",
603 i, val);
604 }
developerba28e032021-12-07 10:40:00 +0800605 }
606
developer765b1982021-06-24 09:18:15 +0800607 return len;
608}
609
developerba28e032021-12-07 10:40:00 +0800610static ssize_t hqa_store(struct device *dev,
developer765b1982021-06-24 09:18:15 +0800611 struct device_attribute *attr, const char *buf, size_t count)
612{
613 struct xhci_hcd_mtk *mtk = dev_get_drvdata(dev);
614 struct usb_hcd *hcd = mtk->hcd;
615 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
616 int retval;
617
618 retval = call_hqa_func(mtk, (char *)buf);
619 if (retval < 0) {
620 xhci_err(xhci, "mu3h cli fail\n");
621 return -1;
622 }
623
624 return count;
625}
626
developerba28e032021-12-07 10:40:00 +0800627static DEVICE_ATTR_RW(hqa);
developer765b1982021-06-24 09:18:15 +0800628
developerba28e032021-12-07 10:40:00 +0800629static ssize_t usb3hqa_show(struct device *dev,
developer765b1982021-06-24 09:18:15 +0800630 struct device_attribute *attr, char *buf)
631{
developerba28e032021-12-07 10:40:00 +0800632 struct xhci_hcd_mtk *mtk = dev_get_drvdata(dev);
developer765b1982021-06-24 09:18:15 +0800633 struct usb_hcd *hcd = mtk->hcd;
634 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
developerba28e032021-12-07 10:40:00 +0800635 ssize_t cnt = 0;
636 u32 __iomem *addr;
637 u32 val;
638 u32 i;
639 int ports;
developer765b1982021-06-24 09:18:15 +0800640
developerba28e032021-12-07 10:40:00 +0800641 cnt += sprintf(buf + cnt, "usb3hqa usage:\n");
developerabd06d72022-03-03 16:13:41 +0800642 cnt += sprintf(buf + cnt, " echo [u3port] >usb3hqa\n");
developer765b1982021-06-24 09:18:15 +0800643
developerba28e032021-12-07 10:40:00 +0800644 ports = mtk->num_u3_ports + mtk->num_u2_ports;
645 for (i = 1; i <= ports; i++) {
646 addr = &xhci->op_regs->port_status_base +
647 NUM_PORT_REGS * ((i - 1) & 0xff);
648 val = readl(addr);
developerabd06d72022-03-03 16:13:41 +0800649 if (i <= mtk->num_u3_ports)
developerba28e032021-12-07 10:40:00 +0800650 cnt += sprintf(buf + cnt,
651 "USB30 Port%i: 0x%08X\n", i, val);
developerabd06d72022-03-03 16:13:41 +0800652 else
developerba28e032021-12-07 10:40:00 +0800653 cnt += sprintf(buf + cnt,
654 "USB20 Port%i: 0x%08X\n", i, val);
developer765b1982021-06-24 09:18:15 +0800655 }
656
developerba28e032021-12-07 10:40:00 +0800657 if (mtk->hqa_pos) {
658 cnt += sprintf(buf + cnt, "%s", mtk->hqa_buf);
659 mtk->hqa_pos = 0;
developer765b1982021-06-24 09:18:15 +0800660 }
661
developerba28e032021-12-07 10:40:00 +0800662 return cnt;
developer765b1982021-06-24 09:18:15 +0800663}
664
developer765b1982021-06-24 09:18:15 +0800665static ssize_t
developerba28e032021-12-07 10:40:00 +0800666usb3hqa_store(struct device *dev, struct device_attribute *attr,
developer765b1982021-06-24 09:18:15 +0800667 const char *buf, size_t n)
668{
669 struct xhci_hcd_mtk *mtk = dev_get_drvdata(dev);
670 struct usb_hcd *hcd = mtk->hcd;
671 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
developerba28e032021-12-07 10:40:00 +0800672 u32 __iomem *addr;
673 u32 val;
674 int port;
675 int words;
developer765b1982021-06-24 09:18:15 +0800676
developerba28e032021-12-07 10:40:00 +0800677 mtk->hqa_pos = 0;
678 memset(mtk->hqa_buf, 0, mtk->hqa_size);
developer765b1982021-06-24 09:18:15 +0800679
developerba28e032021-12-07 10:40:00 +0800680 hqa_info(mtk, "usb3hqa: %s\n", buf);
681
682 words = sscanf(buf, "%d", &port);
683 if ((words != 1) ||
684 (port < 1 || port > mtk->num_u3_ports)) {
developerabd06d72022-03-03 16:13:41 +0800685 hqa_info(mtk, "usb3hqa: param number:%i, port:%i (%i) failure\n",
686 words, port, mtk->num_u3_ports);
developerba28e032021-12-07 10:40:00 +0800687 return -EINVAL;
developer765b1982021-06-24 09:18:15 +0800688 }
689
developerba28e032021-12-07 10:40:00 +0800690 addr = &xhci->op_regs->port_status_base +
691 NUM_PORT_REGS * ((port - 1) & 0xff);
692 val = readl(addr);
693 val &= ~(PORT_PLS_MASK);
694 val |= (PORT_LINK_STROBE | XDEV_COMP_MODE);
695 writel(val, addr);
696 hqa_info(mtk, "usb3hqa: port%i: 0x%08X but 0x%08X\n",
697 port, val, readl(addr));
698
developer765b1982021-06-24 09:18:15 +0800699 return n;
700}
developerba28e032021-12-07 10:40:00 +0800701static DEVICE_ATTR_RW(usb3hqa);
developer765b1982021-06-24 09:18:15 +0800702
703static struct device_attribute *mu3h_hqa_attr_list[] = {
704 &dev_attr_hqa,
developerba28e032021-12-07 10:40:00 +0800705 &dev_attr_usb3hqa,
706#include "unusual-statement.h"
developer765b1982021-06-24 09:18:15 +0800707};
708
developerba28e032021-12-07 10:40:00 +0800709int hqa_create_attr(struct device *dev)
developer765b1982021-06-24 09:18:15 +0800710{
developerba28e032021-12-07 10:40:00 +0800711 struct xhci_hcd_mtk *mtk = dev_get_drvdata(dev);
developerabd06d72022-03-03 16:13:41 +0800712 struct usb_hcd *hcd = mtk->hcd;
713 struct mu3c_ippc_regs __iomem *ippc = mtk->ippc_regs;
714 struct platform_device *device = to_platform_device(dev);
715 int num = ARRAY_SIZE(mu3h_hqa_attr_list);
716 int idx;
717 int err = 0;
718 u32 value;
719 u32 addr = hcd->rsrc_start;
720 u32 length;
developer765b1982021-06-24 09:18:15 +0800721
developerba28e032021-12-07 10:40:00 +0800722 if (dev == NULL || mtk == NULL)
developer765b1982021-06-24 09:18:15 +0800723 return -EINVAL;
724
developerba28e032021-12-07 10:40:00 +0800725 mtk->hqa_size = HQA_PREFIX_SIZE;
726 mtk->hqa_pos = 0;
727 mtk->hqa_buf = kzalloc(mtk->hqa_size, GFP_KERNEL);
728 if (!mtk->hqa_buf)
729 return -ENOMEM;
developer765b1982021-06-24 09:18:15 +0800730
developerabd06d72022-03-03 16:13:41 +0800731 if (!mtk->has_ippc) {
732 err = query_reg_addr(device, &addr, &length, "ippc");
733 if (err)
734 return -EINVAL;
735
736 mtk->ippc_regs = ioremap(addr, length);
737 }
738
739 ippc = mtk->ippc_regs;
740 value = readl(&ippc->ip_xhci_cap);
741 mtk->num_u3_ports = CAP_U3_PORT_NUM(value);
742 mtk->num_u2_ports = CAP_U2_PORT_NUM(value);
743
developer765b1982021-06-24 09:18:15 +0800744 for (idx = 0; idx < num; idx++) {
745 err = device_create_file(dev, mu3h_hqa_attr_list[idx]);
746 if (err)
747 break;
748 }
749
750 return err;
751}
752
developerba28e032021-12-07 10:40:00 +0800753void hqa_remove_attr(struct device *dev)
developer765b1982021-06-24 09:18:15 +0800754{
755 int idx;
756 int num = ARRAY_SIZE(mu3h_hqa_attr_list);
developerba28e032021-12-07 10:40:00 +0800757 struct xhci_hcd_mtk *mtk = dev_get_drvdata(dev);
developer765b1982021-06-24 09:18:15 +0800758
759 for (idx = 0; idx < num; idx++)
760 device_remove_file(dev, mu3h_hqa_attr_list[idx]);
developerba28e032021-12-07 10:40:00 +0800761
762 kfree(mtk->hqa_buf);
763 mtk->hqa_size = 0;
764 mtk->hqa_pos = 0;
developerabd06d72022-03-03 16:13:41 +0800765 if (!mtk->has_ippc) {
766 iounmap(mtk->ippc_regs);
767 mtk->ippc_regs = NULL;
768 }
developer765b1982021-06-24 09:18:15 +0800769}