blob: a7791cfa0e5d4e3654412d16d3cde72463855832 [file] [log] [blame]
developerba28e032021-12-07 10:40:00 +08001// SPDX-License-Identifier: GPL-2.0
2/*
3 * xHCI host controller toolkit driver for hstx-srctrl
4 *
5 * Copyright (C) 2021 MediaTek Inc.
6 *
7 * Author: Zhanyong Wang <zhanyong.wang@mediatek.com>
8 */
9
10#include <linux/platform_device.h>
11#include <linux/module.h>
12#include <linux/slab.h>
13#include <linux/usb.h>
14#include "xhci-mtk.h"
15#include "xhci-mtk-test.h"
16#include "xhci-mtk-unusual.h"
17
18static ssize_t RG_USB20_HSTX_SRCTRL_show(struct device *dev,
19 struct device_attribute *attr, char *buf)
20{
21 struct xhci_hcd_mtk *mtk = dev_get_drvdata(dev);
22 struct usb_hcd *hcd = mtk->hcd;
23 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
24 ssize_t cnt = 0;
25 void __iomem *addr;
26 u32 val;
27 u32 i;
28 int ports;
29 char str[32];
30 int index = 0;
31 u32 io, length;
32 int ret;
33
34 ports = mtk->num_u3_ports + mtk->num_u2_ports;
35 cnt += sprintf(buf + cnt, " RG_USB20_HSTX_SRCTRL usage:\n");
36 cnt += sprintf(buf + cnt,
37 " echo u2p index 3b011 > RG_USB20_HSTX_SRCTRL\n");
38 if (mtk->num_u3_ports + 1 != ports)
39 cnt += sprintf(buf + cnt, " parameter: u2p: %i ~ %i\n",
40 mtk->num_u3_ports + 1, ports);
41 else
42 cnt += sprintf(buf + cnt, " parameter: u2p: %i\n",
43 mtk->num_u3_ports + 1);
44
45 if (mtk->num_u2_ports > 1)
46 cnt += sprintf(buf + cnt, " parameter: index: 0 ~ %i\n",
47 mtk->num_u2_ports);
48 else
49 cnt += sprintf(buf + cnt, " parameter: index: 0\n");
50
51 cnt += sprintf(buf + cnt,
52 " e.g.: echo 2 0 3b010 > RG_USB20_HSTX_SRCTRL\n");
53 cnt += sprintf(buf + cnt,
54 " port2 binding phy 0, tune 3b'010 as HSTX_SRCTRL value\n");
55
56 cnt += sprintf(buf + cnt,
57 "\n=========current HQA setting check=========\n");
58 for (i = 1; i <= ports; i++) {
59 addr = &xhci->op_regs->port_status_base +
60 NUM_PORT_REGS * ((i - 1) & 0xff);
61 val = readl(addr);
62 if (i <= mtk->num_u3_ports) {
63 cnt += sprintf(buf + cnt,
64 "USB30 Port%i: 0x%08X\n", i, val);
65 } else {
66 cnt += sprintf(buf + cnt,
67 "USB20 Port%i: 0x%08X\n", i, val);
68
69 ret = query_phy_addr(dev->of_node,
70 &index, &io, &length);
71 if (ret && ret != -EACCES) {
72 if (ret == -EPERM)
73 cnt += sprintf(buf + cnt,
74 "USB20 Port%i (Phy%i: absent)\n",
75 i, index);
76 else
77 cnt += sprintf(buf + cnt,
78 "USB20 Port%i (Phy%i) failure %i\n",
79 i, index, ret);
80 continue;
81 }
82
83 cnt += sprintf(buf + cnt,
84 "USB20 Port%i (Phy%i:%sable): 0x%08X 0x%08X\n",
85 i, index, ret ? " dis" : " en", io, length);
86
87 addr = ioremap_nocache(io, length);
88 addr += (length != 0x100) ? 0x300 : 0;
89
90 HQA_INFORMACTION_COLLECTS();
91
92 iounmap(addr);
93 index ++;
94 }
95 }
96
97 if (mtk->hqa_pos) {
98 cnt += sprintf(buf + cnt, "%s", mtk->hqa_buf);
99 mtk->hqa_pos = 0;
100 }
101
102 return cnt;
103}
104
105static ssize_t RG_USB20_HSTX_SRCTRL_store(struct device *dev,
106 struct device_attribute *attr,
107 const char *buf, size_t n)
108{
109 u32 val;
110 u32 io;
111 u32 length;
112 int ports;
113 int words;
114 int port;
115 int index;
116 int ret;
117 char *str = NULL;
118 void __iomem *addr;
119 struct xhci_hcd_mtk *mtk = dev_get_drvdata(dev);
120 struct device_node *node = dev->of_node;
121
122 ports = mtk->num_u3_ports + mtk->num_u2_ports;
123 mtk->hqa_pos = 0;
124
125 memset(mtk->hqa_buf, 0, mtk->hqa_size);
126
127 str = kzalloc(n, GFP_ATOMIC);
128
129 hqa_info(mtk, "RG_USB20_HSTX_SRCTRL(%lu): %s\n", n, buf);
130
131 words = sscanf(buf, "%i %i 3b%3[0,1]", &port, &index, str);
132 if ((words != 3) ||
133 (port < mtk->num_u3_ports || port > ports)) {
134 hqa_info(mtk, "Check params(%i):\" %i %i %s\", Please!\n",
135 words, port, index, str);
136
137 ret = -EINVAL;
138 goto error;
139 }
140
141 hqa_info(mtk, " params: %i %i %s\n",
142 port, index, str);
143
144 ret = query_phy_addr(node, &index, &io, &length);
145 if (ret && ret != -EACCES)
146 goto error;
147
148 io += (length != 0x100) ? 0x300 : 0;
149 io += USB20_PHY_USBPHYACR5;
150
151 addr = ioremap_nocache(io, 4);
152 val = binary_write_width3(addr, SHFT_RG_USB20_HSTX_SRCTRL, str);
153 hqa_info(mtk, "Port%i(Phy%i)[0x%08X]: 0x%08X but 0x%08X\n",
154 port, index, io, val, readl(addr));
155
156 iounmap(addr);
157 ret = n;
158
159error:
160 kfree(str);
161 return ret;
162}
163DEVICE_ATTR_RW(RG_USB20_HSTX_SRCTRL);