blob: fc764a674e6f2807b745f1498186dca0670374dd [file] [log] [blame]
developer765b1982021-06-24 09:18:15 +08001/*
2 * Copyright (c) 2015 MediaTek Inc.
3 * Author:
4 * Shaocheng.Wang <shaocheng.wang@mediatek.com>
5 * Chunfeng.Yun <chunfeng.yun@mediatek.com>
6 *
7 * This software is licensed under the terms of the GNU General Public
8 * License version 2, as published by the Free Software Foundation, and
9 * may be copied, distributed, and modified under those terms.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 */
17
18#include <linux/platform_device.h>
19#include <linux/module.h>
20#include <linux/slab.h>
21#include <linux/usb.h>
22#include <linux/kobject.h>
23
24#include "../core/usb.h"
25#include "xhci-mtk.h"
26
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);
37static int t_power_u1u2(struct xhci_hcd_mtk *mtk, int argc, char **argv);
38
39#define PORT_PLS_VALUE(p) ((p >> 5) & 0xf)
40
41#define MAX_NAME_SIZE 32
42#define MAX_ARG_SIZE 4
43
44struct hqa_test_cmd {
45 char name[MAX_NAME_SIZE];
46 int (*cb_func)(struct xhci_hcd_mtk *mtk, int argc, char **argv);
47 char *discription;
48};
49
50
51struct hqa_test_cmd xhci_mtk_hqa_cmds[] = {
52 {"test.j", &t_test_j, "Test_J"},
53 {"test.k", &t_test_k, "Test_K"},
54 {"test.se0", &t_test_se0, "Test_SE0_NAK"},
55 {"test.packet", &t_test_packet, "Test_PACKET"},
56 {"test.suspend", &t_test_suspend, "Port Suspend"},
57 {"test.resume", &t_test_resume, "Port Resume"},
58 {"test.enumbus", &t_test_enumerate_bus, "Enumerate Bus"},
59 {"test.getdesc", &t_test_get_device_descriptor,
60 "Get Device Discriptor"},
61 {"pm.u1u2", &t_power_u1u2, "Port U1,U2"},
62 {"", NULL, ""},
63};
64
65
66int call_hqa_func(struct xhci_hcd_mtk *mtk, char *buf)
67{
68 struct hqa_test_cmd *hqa;
69 struct usb_hcd *hcd = mtk->hcd;
70 char *argv[MAX_ARG_SIZE];
71 int argc;
72 int i;
73
74 argc = 0;
75 do {
76 argv[argc] = strsep(&buf, " ");
77 xhci_err(hcd_to_xhci(hcd), "[%d] %s\r\n", argc, argv[argc]);
78 argc++;
79 } while (buf);
80
81 for (i = 0; i < ARRAY_SIZE(xhci_mtk_hqa_cmds); i++) {
82 hqa = &xhci_mtk_hqa_cmds[i];
83 if ((!strcmp(hqa->name, argv[0])) && (hqa->cb_func != NULL))
84 return hqa->cb_func(mtk, argc, argv);
85 }
86
87 return -1;
88}
89
90static int test_mode_enter(struct xhci_hcd_mtk *mtk,
91 u32 port_id, u32 test_value)
92{
93 struct usb_hcd *hcd = mtk->hcd;
94 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
95 u32 __iomem *addr;
96 u32 temp;
97
98 if (mtk->test_mode == 0) {
99 xhci_stop(hcd);
100 xhci_halt(xhci);
101 }
102
103 addr = &xhci->op_regs->port_power_base +
104 NUM_PORT_REGS * ((port_id - 1) & 0xff);
105 temp = readl(addr);
106 temp &= ~(0xf << 28);
107 temp |= (test_value << 28);
108 writel(temp, addr);
109 mtk->test_mode = 1;
110
111 return 0;
112}
113
114static int test_mode_exit(struct xhci_hcd_mtk *mtk)
115{
116 /* struct usb_hcd *hcd = mtk->hcd; */
117 /* struct xhci_hcd *xhci = hcd_to_xhci(hcd); */
118
119 if (mtk->test_mode == 1) {
120#if 0
121 xhci_reset(xhci);
122 /*reinitIP(&pdev->dev);*/
123
124 if (!usb_hcd_is_primary_hcd(test_hcd))
125 secondary_hcd = test_hcd;
126 else
127 secondary_hcd = xhci->shared_hcd;
128
129 retval = xhci_init(test_hcd->primary_hcd);
130 if (retval)
131 return retval;
132
133 retval = xhci_run(test_hcd->primary_hcd);
134 if (!retval)
135 retval = xhci_run(secondary_hcd);
136
137 /*enableXhciAllPortPower(xhci);*/
138#endif
139 mtk->test_mode = 0;
140 }
141 return 0;
142}
143
144static int t_test_j(struct xhci_hcd_mtk *mtk, int argc, char **argv)
145{
146 struct usb_hcd *hcd = mtk->hcd;
147 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
148 long port_id;
149 u32 test_value;
150
151 port_id = 2;
152 test_value = 1;
153
154 if (argc > 1 && kstrtol(argv[1], 10, &port_id))
155 xhci_err(xhci, "mu3h %s get port-id failed\n", __func__);
156
157 xhci_err(xhci, "mu3h %s test port%d\n", __func__, (int)port_id);
158 test_mode_enter(mtk, port_id, test_value);
159
160 return 0;
161}
162
163static int t_test_k(struct xhci_hcd_mtk *mtk, int argc, char **argv)
164{
165 struct usb_hcd *hcd = mtk->hcd;
166 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
167 long port_id;
168 u32 test_value;
169
170 port_id = 2;
171 test_value = 2;
172
173 if (argc > 1 && kstrtol(argv[1], 10, &port_id))
174 xhci_err(xhci, "mu3h %s get port-id failed\n", __func__);
175
176 xhci_err(xhci, "mu3h %s test port%d\n", __func__, (int)port_id);
177 test_mode_enter(mtk, port_id, test_value);
178
179 return 0;
180}
181
182static int t_test_se0(struct xhci_hcd_mtk *mtk, int argc, char **argv)
183{
184 struct usb_hcd *hcd = mtk->hcd;
185 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
186 long port_id;
187 u32 test_value;
188
189 port_id = 2;
190 test_value = 3;
191
192 if (argc > 1 && kstrtol(argv[1], 10, &port_id))
193 xhci_err(xhci, "mu3h %s get port-id failed\n", __func__);
194
195 xhci_err(xhci, "mu3h %s test port%ld\n", __func__, port_id);
196 test_mode_enter(mtk, port_id, test_value);
197
198 return 0;
199}
200
201static int t_test_packet(struct xhci_hcd_mtk *mtk, int argc, char **argv)
202{
203 struct usb_hcd *hcd = mtk->hcd;
204 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
205 long port_id;
206 u32 test_value;
207
208 port_id = 2;
209 test_value = 4;
210
211 if (argc > 1 && kstrtol(argv[1], 10, &port_id))
212 xhci_err(xhci, "mu3h %s get port-id failed\n", __func__);
213
214 xhci_err(xhci, "mu3h %s test port%ld\n", __func__, port_id);
215 test_mode_enter(mtk, port_id, test_value);
216
217 return 0;
218}
219
220/* only for u3 ports, valid values are 1, 2, ...*/
221static int t_power_u1u2(struct xhci_hcd_mtk *mtk, int argc, char **argv)
222{
223 struct usb_hcd *hcd = mtk->hcd;
224 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
225 u32 __iomem *addr;
226 u32 temp;
227 int port_id;
228 int retval = 0;
229 int u_num = 1;
230 int u1_val = 1;
231 int u2_val = 0;
232
233 port_id = 1; /* first u3port by default */
234
235 if (argc > 1 && kstrtoint(argv[1], 10, &port_id))
236 xhci_err(xhci, "mu3h %s get port-id failed\n", __func__);
237
238 if (argc > 2 && kstrtoint(argv[2], 10, &u_num))
239 xhci_err(xhci, "mu3h %s get u_num failed\n", __func__);
240
241 if (argc > 3 && kstrtoint(argv[3], 10, &u1_val))
242 xhci_err(xhci, "mu3h %s get u1_val failed\n", __func__);
243
244 if (argc > 4 && kstrtoint(argv[4], 10, &u2_val))
245 xhci_err(xhci, "mu3h %s get u2_val failed\n", __func__);
246
247 xhci_err(xhci, "mu3h %s test port%d, u_num%d, u1_val%d, u2_val%d\n",
248 __func__, (int)port_id, u_num, u1_val, u2_val);
249
250 if (mtk->test_mode == 1) {
251 xhci_err(xhci, "please suspend port first\n");
252 return -1;
253 }
254
255 xhci_err(xhci, "%s: stop port polling\n", __func__);
256 clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
257 del_timer_sync(&hcd->rh_timer);
258 clear_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags);
259 del_timer_sync(&xhci->shared_hcd->rh_timer);
260 clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
261 clear_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags);
262
263 addr = &xhci->op_regs->port_power_base +
264 NUM_PORT_REGS * ((port_id - 1) & 0xff);
265
266 temp = readl(addr);
267 if (u_num == 1) {
268 temp &= ~PORT_U1_TIMEOUT_MASK;
269 temp |= PORT_U1_TIMEOUT(u1_val);
270 } else if (u_num == 2) {
271 temp &= ~PORT_U2_TIMEOUT_MASK;
272 temp |= PORT_U2_TIMEOUT(u2_val);
273 } else if (u_num == 3) {
274 temp &= ~(PORT_U1_TIMEOUT_MASK | PORT_U2_TIMEOUT_MASK);
275 temp |= PORT_U1_TIMEOUT(u1_val) | PORT_U2_TIMEOUT(u2_val);
276 }
277
278 writel(temp, addr);
279
280 return retval;
281}
282
283
284static int t_test_suspend(struct xhci_hcd_mtk *mtk, int argc, char **argv)
285{
286 struct usb_hcd *hcd = mtk->hcd;
287 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
288 u32 __iomem *addr;
289 u32 temp;
290 long port_id;
291
292 port_id = 2;
293
294 if (argc > 1 && kstrtol(argv[1], 10, &port_id))
295 xhci_err(xhci, "mu3h %s get port-id failed\n", __func__);
296
297 xhci_err(xhci, "mu3h %s test port%d\n", __func__, (int)port_id);
298
299 xhci_err(xhci, "%s: stop port polling\n", __func__);
300 clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
301 del_timer_sync(&hcd->rh_timer);
302 clear_bit(HCD_FLAG_POLL_RH, &xhci->shared_hcd->flags);
303 del_timer_sync(&xhci->shared_hcd->rh_timer);
304 clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
305 clear_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags);
306
307 temp = readl(&xhci->ir_set->irq_pending);
308 writel(ER_IRQ_DISABLE(temp), &xhci->ir_set->irq_pending);
309
310 if (mtk->test_mode == 1)
311 test_mode_exit(mtk);
312
313 /* set PLS = 3 */
314 addr = &xhci->op_regs->port_status_base +
315 NUM_PORT_REGS*((port_id - 1) & 0xff);
316
317 temp = readl(addr);
318 temp = xhci_port_state_to_neutral(temp);
319 temp = (temp & ~(0xf << 5));
320 temp = (temp | (3 << 5) | PORT_LINK_STROBE);
321 writel(temp, addr);
322 xhci_handshake(addr, (0xf << 5), (3 << 5), 30*1000);
323
324 temp = readl(addr);
325 if (PORT_PLS_VALUE(temp) != 3)
326 xhci_err(xhci, "port not enter suspend state\n");
327 else
328 xhci_err(xhci, "port enter suspend state\n");
329
330 return 0;
331}
332
333static int t_test_resume(struct xhci_hcd_mtk *mtk, int argc, char **argv)
334{
335 struct usb_hcd *hcd = mtk->hcd;
336 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
337 u32 __iomem *addr;
338 u32 temp;
339 long port_id;
340 int retval = 0;
341
342 port_id = 2;
343
344 if (argc > 1 && kstrtol(argv[1], 10, &port_id))
345 xhci_err(xhci, "mu3h %s get port-id failed\n", __func__);
346
347 xhci_err(xhci, "mu3h %s test port%d\n", __func__, (int)port_id);
348
349 if (mtk->test_mode == 1) {
350 xhci_err(xhci, "please suspend port first\n");
351 return -1;
352 }
353 addr = &xhci->op_regs->port_status_base +
354 NUM_PORT_REGS * ((port_id - 1) & 0xff);
355
356 temp = readl(addr);
357 if (PORT_PLS_VALUE(temp) != 3) {
358 xhci_err(xhci, "port not in suspend state, please suspend port first\n");
359 retval = -1;
360 } else {
361 temp = xhci_port_state_to_neutral(temp);
362 temp = (temp & ~(0xf << 5));
363 temp = (temp | (15 << 5) | PORT_LINK_STROBE);
364 writel(temp, addr);
365 mdelay(20);
366
367 temp = readl(addr);
368 temp = xhci_port_state_to_neutral(temp);
369 temp = (temp & ~(0xf << 5));
370 temp = (temp | PORT_LINK_STROBE);
371 writel(temp, addr);
372
373 xhci_handshake(addr, (0xf << 5), (0 << 5), 100*1000);
374 temp = readl(addr);
375 if (PORT_PLS_VALUE(temp) != 0) {
376 xhci_err(xhci, "rusume fail,%x\n",
377 PORT_PLS_VALUE(temp));
378 retval = -1;
379 } else {
380 xhci_err(xhci, "port resume ok\n");
381 }
382 }
383
384 return retval;
385}
386
387static int t_test_enumerate_bus(struct xhci_hcd_mtk *mtk, int argc, char **argv)
388{
389 struct usb_hcd *hcd = mtk->hcd;
390 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
391 struct usb_device *usb2_rh;
392 struct usb_device *udev;
393 long port_id;
394 u32 retval;
395
396 port_id = 2;
397
398 if (argc > 1 && kstrtol(argv[1], 10, &port_id))
399 xhci_err(xhci, "mu3h %s get port-id failed\n", __func__);
400
401 xhci_err(xhci, "mu3h %s test port%d\n", __func__, (int)port_id);
402
403 if (mtk->test_mode == 1) {
404 test_mode_exit(mtk);
405 return 0;
406 }
407
408 usb2_rh = hcd->self.root_hub;
409 udev = usb_hub_find_child(usb2_rh, port_id - 1);
410
411 if (udev != NULL) {
412 retval = usb_reset_device(udev);
413 if (retval) {
414 xhci_err(xhci, "ERROR: enumerate bus fail!\n");
415 return -1;
416 }
417 } else {
418 xhci_err(xhci, "ERROR: Device does not exist!\n");
419 return -1;
420 }
421
422 return 0;
423}
424static int t_test_get_device_descriptor(struct xhci_hcd_mtk *mtk,
425 int argc, char **argv)
426{
427 struct usb_hcd *hcd = mtk->hcd;
428 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
429 struct usb_device *usb2_rh;
430 struct usb_device *udev;
431 long port_id;
432 u32 retval = 0;
433
434 port_id = 2;
435
436 if (argc > 1 && kstrtol(argv[1], 10, &port_id))
437 xhci_err(xhci, "mu3h %s get port-id failed\n", __func__);
438
439 xhci_err(xhci, "mu3h %s test port%d\n", __func__, (int)port_id);
440
441 if (mtk->test_mode == 1) {
442 test_mode_exit(mtk);
443 msleep(2000);
444 }
445
446 usb2_rh = hcd->self.root_hub;
447
448 udev = usb_hub_find_child(usb2_rh, port_id - 1);
449
450 if (udev != NULL) {
451 retval = usb_get_device_descriptor(udev, USB_DT_DEVICE_SIZE);
452 if (retval != sizeof(udev->descriptor)) {
453 xhci_err(xhci, "ERROR: get device descriptor fail!\n");
454 return -1;
455 }
456 } else {
457 xhci_err(xhci, "ERROR: Device does not exist!\n");
458 return -1;
459 }
460
461 return 0;
462}
463
464static ssize_t mu3h_hqa_show(struct device *dev,
465 struct device_attribute *attr, char *buf)
466{
467 int len = 0;
468 int bufLen = PAGE_SIZE;
469 struct hqa_test_cmd *hqa;
470 int i;
471
472 len += snprintf(buf+len, bufLen-len, "info:\n");
473 len += snprintf(buf+len, bufLen-len,
474 "\techo -n item port-id > hqa\n");
475 len += snprintf(buf+len, bufLen-len,
476 "\tport-id : based on number of usb3-port, e.g.\n");
477 len += snprintf(buf+len, bufLen-len,
478 "\t\txHCI with 1 u3p, 2 u2p: 1st u2p-id is 2(1+1), 2nd is 3\n");
479 len += snprintf(buf+len, bufLen-len, "items:\n");
480
481 for (i = 0; i < ARRAY_SIZE(xhci_mtk_hqa_cmds); i++) {
482 hqa = &xhci_mtk_hqa_cmds[i];
483 len += snprintf(buf+len, bufLen-len,
484 "\t%s: %s\n", hqa->name, hqa->discription);
485 }
486
487 return len;
488}
489
490static ssize_t mu3h_hqa_store(struct device *dev,
491 struct device_attribute *attr, const char *buf, size_t count)
492{
493 struct xhci_hcd_mtk *mtk = dev_get_drvdata(dev);
494 struct usb_hcd *hcd = mtk->hcd;
495 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
496 int retval;
497
498 retval = call_hqa_func(mtk, (char *)buf);
499 if (retval < 0) {
500 xhci_err(xhci, "mu3h cli fail\n");
501 return -1;
502 }
503
504 return count;
505}
506
507static DEVICE_ATTR(hqa, 0664, mu3h_hqa_show, mu3h_hqa_store);
508
509#define REGS_LIMIT_XHCI 0x1000
510#define REGS_LIMIT_MU3D 0x3000
511#define REGS_LIMIT_IPPC 0x100
512#define REGS_LIMIT_PHYS 0x4000
513
514#define REGS_XHCI_OFFSET 0x0000
515#define REGS_MU3D_OFFSET 0x1000
516#define REGS_IPPC_OFFSET 0x3e00
517#define REGS_PHY_OFFSET 0xA20000
518
519static ssize_t ssusb_reg_show(struct device *dev,
520 struct device_attribute *attr, char *buf)
521{
522 int ret = -EINVAL;
523
524 ret = sprintf(buf, "SSUSB register operation interface help info.\n"
525 " rx - read xhci reg: offset [len]\n"
526 " rm - read mu3d reg: offset [len]\n"
527 " ri - read ippc reg: offset [len]\n"
528 " rp - read phy reg: offset [len]\n"
529 " wx - write xhci reg: offset value\n"
530 " wm - write mu3d reg: offset value\n"
531 " wi - write ippc reg: offset value\n"
532 " wp - write phy reg: offset value\n"
533 " sx - set xhci mac reg bits: offset bit_start mask value\n"
534 " sm - set mu3d mac reg bits: offset bit_start mask value\n"
535 " si - set ippc reg bits: offset bit_start mask value\n"
536 " sp - set phy reg bits: offset bit_start mask value\n"
537 " px - print xhci mac reg bits: offset bit_start mask\n"
538 " pm - print mu3d mac reg bits: offset bit_start mask\n"
539 " pi - print ippc reg bits: offset bit_start mask\n"
540 " pp - print phy reg bits: offset bit_start mask\n"
541 " NOTE: numbers should be HEX, except bit_star(DEC)\n");
542
543 return ret;
544}
545
546/* base address: return value; limit is put into @limit */
547static void __iomem *get_reg_base_limit(struct xhci_hcd_mtk *mtk,
548 const char *buf, u32 *limit)
549{
550 struct usb_hcd *hcd = mtk->hcd;
551 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
552 void __iomem *base;
553 u32 len = 0;
554
555 switch (buf[1]) {
556 case 'x':
557 base = mtk->ip_base + REGS_XHCI_OFFSET;
558 len = REGS_LIMIT_XHCI;
559 xhci_info(xhci, "xhci's reg:\n");
560 break;
561 case 'm':
562 base = mtk->ip_base + REGS_MU3D_OFFSET;
563 len = REGS_LIMIT_MU3D;
564 xhci_info(xhci, "mu3d's reg:\n");
565 break;
566 case 'i':
567 base = mtk->ip_base + REGS_IPPC_OFFSET;
568 len = REGS_LIMIT_IPPC;
569 xhci_info(xhci, "ippc's reg:\n");
570 break;
571 case 'p':
572 base = mtk->ip_base + REGS_PHY_OFFSET;
573 len = REGS_LIMIT_PHYS;
574 xhci_info(xhci, "phy's reg:\n");
575 break;
576 default:
577 base = NULL;
578 }
579
580 *limit = len;
581
582 return base;
583}
584
585static void ssusb_write_reg(struct xhci_hcd_mtk *mtk, const char *buf)
586{
587 struct usb_hcd *hcd = mtk->hcd;
588 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
589 void __iomem *base;
590 u32 offset = 0;
591 u32 value = 0;
592 u32 old_val = 0;
593 u32 limit = 0;
594 u32 param;
595
596 param = sscanf(buf, "%*s 0x%x 0x%x", &offset, &value);
597 xhci_info(xhci, "params-%d (offset: %#x, value: %#x)\n",
598 param, offset, value);
599
600 base = get_reg_base_limit(mtk, buf, &limit);
601 if (!base || (param != 2)) {
602 xhci_err(xhci, "params are invalid!\n");
603 return;
604 }
605
606 offset &= ~0x3; /* 4-bytes align */
607 if (offset >= limit) {
608 xhci_err(xhci, "reg's offset overrun!\n");
609 return;
610 }
611 old_val = readl(base + offset);
612 writel(value, base + offset);
613 xhci_info(xhci, "0x%8.8x : 0x%8.8x --> 0x%8.8x\n", offset, old_val,
614 readl(base + offset));
615}
616
617static void read_single_reg(struct xhci_hcd_mtk *mtk,
618 void __iomem *base, u32 offset, u32 limit)
619{
620 struct usb_hcd *hcd = mtk->hcd;
621 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
622 u32 value;
623
624 offset &= ~0x3; /* 4-bytes align */
625 if (offset >= limit) {
626 xhci_err(xhci, "reg's offset overrun!\n");
627 return;
628 }
629 value = readl(base + offset);
630 xhci_err(xhci, "0x%8.8x : 0x%8.8x\n", offset, value);
631}
632
633static void read_multi_regs(struct xhci_hcd_mtk *mtk,
634 void __iomem *base, u32 offset, u32 len, u32 limit)
635{
636 struct usb_hcd *hcd = mtk->hcd;
637 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
638 int i;
639
640 /* at least 4 ints */
641 offset &= ~0xF;
642 len = (len + 0x3) & ~0x3;
643
644 if (offset + len > limit) {
645 xhci_err(xhci, "reg's offset overrun!\n");
646 return;
647 }
648
649 len >>= 2;
650 xhci_info(xhci, "read regs [%#x, %#x)\n", offset, offset + (len << 4));
651 for (i = 0; i < len; i++) {
652 xhci_err(xhci, "0x%8.8x : 0x%8.8x 0x%8.8x 0x%8.8x 0x%8.8x\n",
653 offset, readl(base + offset),
654 readl(base + offset + 0x4),
655 readl(base + offset + 0x8),
656 readl(base + offset + 0xc));
657 offset += 0x10;
658 }
659}
660
661static void ssusb_read_regs(struct xhci_hcd_mtk *mtk, const char *buf)
662{
663 struct usb_hcd *hcd = mtk->hcd;
664 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
665 void __iomem *base;
666 u32 offset = 0;
667 u32 len = 0;
668 u32 limit = 0;
669 u32 param;
670
671 param = sscanf(buf, "%*s 0x%x 0x%x", &offset, &len);
672 xhci_info(xhci, "params-%d (offset: %#x, len: %#x)\n",
673 param, offset, len);
674
675 base = get_reg_base_limit(mtk, buf, &limit);
676 if (!base || !param) {
677 xhci_err(xhci, "params are invalid!\n");
678 return;
679 }
680
681 if (param == 1)
682 read_single_reg(mtk, base, offset, limit);
683 else
684 read_multi_regs(mtk, base, offset, len, limit);
685}
686
687static void ssusb_set_reg_bits(struct xhci_hcd_mtk *mtk, const char *buf)
688{
689 struct usb_hcd *hcd = mtk->hcd;
690 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
691 void __iomem *base;
692 u32 offset = 0;
693 u32 bit_start = 0;
694 u32 mask = 0;
695 u32 value = 0;
696 u32 old_val = 0;
697 u32 new_val = 0;
698 u32 limit = 0;
699 u32 param;
700
701 param = sscanf(buf, "%*s 0x%x %d 0x%x 0x%x",
702 &offset, &bit_start, &mask, &value);
703 xhci_info(xhci, "params-%d (offset:%#x,bit_start:%d,mask:%#x,value:%#x)\n",
704 param, offset, bit_start, mask, value);
705
706 base = get_reg_base_limit(mtk, buf, &limit);
707 if (!base || (param != 4) || (bit_start > 32)) {
708 xhci_err(xhci, "params are invalid!\n");
709 return;
710 }
711
712 offset &= ~0x3; /* 4-bytes align */
713 if (offset >= limit) {
714 xhci_err(xhci, "reg's offset overrun!\n");
715 return;
716 }
717 old_val = readl(base + offset);
718 new_val = old_val;
719 new_val &= ~(mask << bit_start);
720 new_val |= (value << bit_start);
721 writel(new_val, base + offset);
722 xhci_info(xhci, "0x%8.8x : 0x%8.8x --> 0x%8.8x\n", offset, old_val,
723 readl(base + offset));
724}
725
726
727static void ssusb_print_reg_bits(struct xhci_hcd_mtk *mtk, const char *buf)
728{
729 struct usb_hcd *hcd = mtk->hcd;
730 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
731 void __iomem *base;
732 u32 offset = 0;
733 u32 bit_start = 0;
734 u32 mask = 0;
735 u32 old_val = 0;
736 u32 new_val = 0;
737 u32 limit = 0;
738 u32 param;
739
740 param = sscanf(buf, "%*s 0x%x %d 0x%x", &offset, &bit_start, &mask);
741 xhci_info(xhci, "params-%d (offset: %#x, bit_start: %d, mask: %#x)\n",
742 param, offset, bit_start, mask);
743
744 base = get_reg_base_limit(mtk, buf, &limit);
745 if (!base || (param != 3) || (bit_start > 32)) {
746 xhci_err(xhci, "params are invalid!\n");
747 return;
748 }
749
750 offset &= ~0x3; /* 4-bytes align */
751 if (offset >= limit) {
752 xhci_err(xhci, "reg's offset overrun!\n");
753 return;
754 }
755
756 old_val = readl(base + offset);
757 new_val = old_val;
758 new_val >>= bit_start;
759 new_val &= mask;
760 xhci_info(xhci, "0x%8.8x : 0x%8.8x (0x%x)\n", offset, old_val, new_val);
761}
762
763
764static ssize_t
765ssusb_reg_store(struct device *dev, struct device_attribute *attr,
766 const char *buf, size_t n)
767{
768 struct xhci_hcd_mtk *mtk = dev_get_drvdata(dev);
769 struct usb_hcd *hcd = mtk->hcd;
770 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
771
772 xhci_info(xhci, " cmd: %s\n", buf);
773
774 switch (buf[0]) {
775 case 'w':
776 ssusb_write_reg(mtk, buf);
777 break;
778 case 'r':
779 ssusb_read_regs(mtk, buf);
780 break;
781 case 's':
782 ssusb_set_reg_bits(mtk, buf);
783 break;
784 case 'p':
785 ssusb_print_reg_bits(mtk, buf);
786 break;
787 default:
788 xhci_err(xhci, "No such cmd\n");
789 }
790
791 return n;
792}
793
794static DEVICE_ATTR(reg, 0664, ssusb_reg_show, ssusb_reg_store);
795
796static struct device_attribute *mu3h_hqa_attr_list[] = {
797 &dev_attr_hqa,
798 &dev_attr_reg,
799};
800
801static void ssusb_remap_ip_regs(struct device *dev)
802{
803 struct xhci_hcd_mtk *mtk = dev_get_drvdata(dev);
804 struct usb_hcd *hcd = mtk->hcd;
805 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
806
807 mtk->ip_base = ioremap(hcd->rsrc_start, 0xb00000);//0xa30000
808 if (!mtk->ip_base)
809 xhci_err(xhci, "could not ioremap regs\n");
810}
811
812int mu3h_hqa_create_attr(struct device *dev)
813{
814 int idx, err = 0;
815 int num = ARRAY_SIZE(mu3h_hqa_attr_list);
816
817 if (dev == NULL)
818 return -EINVAL;
819
820 ssusb_remap_ip_regs(dev);
821
822 for (idx = 0; idx < num; idx++) {
823 err = device_create_file(dev, mu3h_hqa_attr_list[idx]);
824 if (err)
825 break;
826 }
827
828 return err;
829}
830
831void mu3h_hqa_remove_attr(struct device *dev)
832{
833 int idx;
834 int num = ARRAY_SIZE(mu3h_hqa_attr_list);
835
836 for (idx = 0; idx < num; idx++)
837 device_remove_file(dev, mu3h_hqa_attr_list[idx]);
838}