blob: b02720d1e4fdd008c32ad36cc84c0905ff3460ff [file] [log] [blame]
developerba28e032021-12-07 10:40:00 +08001// SPDX-License-Identifier: GPL-2.0
2/*
3 * xHCI host controller toolkit driver
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 <linux/of.h>
15#include <linux/of_address.h>
developerba28e032021-12-07 10:40:00 +080016#include "xhci-mtk.h"
17#include "xhci-mtk-test.h"
18#include "xhci-mtk-unusual.h"
19
20
21u32 binary_write_width1(u32 __iomem *addr, u32 shift, const char *buf)
22{
23 u32 val = 0;
24
25 if (!strncmp(buf, STRNG_0_WIDTH_1, BIT_WIDTH_1))
26 val = 0;
27 else if (!strncmp(buf, STRNG_1_WIDTH_1, BIT_WIDTH_1))
28 val = 1;
29 else
30 val = 0xFFFFFFFF;
31
32 if (val <= 1)
33 val = usb20hqa_write(addr, shift, MSK_WIDTH_1, val);
34
35 return val;
36}
37
developerd9f9d252022-08-15 17:11:38 +080038u32 binary_write_width2(u32 __iomem *addr, u32 shift, const char *buf)
39{
40 u32 val = 0;
41
42 if (!strncmp(buf, STRNG_0_WIDTH_2, BIT_WIDTH_2))
43 val = 0;
44 else if (!strncmp(buf, STRNG_1_WIDTH_2, BIT_WIDTH_2))
45 val = 1;
46 else if (!strncmp(buf, STRNG_2_WIDTH_2, BIT_WIDTH_2))
47 val = 2;
48 else if (!strncmp(buf, STRNG_3_WIDTH_2, BIT_WIDTH_2))
49 val = 3;
50 else
51 val = 0xFFFFFFFF;
52
53 if (val <= 3)
54 val = usb20hqa_write(addr, shift, MSK_WIDTH_2, val);
55
56 return val;
57}
58
developerba28e032021-12-07 10:40:00 +080059u32 binary_write_width3(u32 __iomem *addr, u32 shift, const char *buf)
60{
61 u32 val = 0;
62
63 if (!strncmp(buf, STRNG_0_WIDTH_3, BIT_WIDTH_3))
64 val = 0;
65 else if (!strncmp(buf, STRNG_1_WIDTH_3, BIT_WIDTH_3))
66 val = 1;
67 else if (!strncmp(buf, STRNG_2_WIDTH_3, BIT_WIDTH_3))
68 val = 2;
69 else if (!strncmp(buf, STRNG_3_WIDTH_3, BIT_WIDTH_3))
70 val = 3;
71 else if (!strncmp(buf, STRNG_4_WIDTH_3, BIT_WIDTH_3))
72 val = 4;
73 else if (!strncmp(buf, STRNG_5_WIDTH_3, BIT_WIDTH_3))
74 val = 5;
75 else if (!strncmp(buf, STRNG_6_WIDTH_3, BIT_WIDTH_3))
76 val = 6;
77 else if (!strncmp(buf, STRNG_7_WIDTH_3, BIT_WIDTH_3))
78 val = 7;
79 else
80 val = 0xFFFFFFFF;
81
82 if (val <= 7)
83 val = usb20hqa_write(addr, shift, MSK_WIDTH_3, val);
84
85 return val;
86}
87
88u32 binary_write_width4(u32 __iomem *addr, u32 shift, const char *buf)
89{
90 u32 val = 0;
91
92 if (!strncmp(buf, STRNG_0_WIDTH_4, BIT_WIDTH_4))
93 val = 0;
94 else if (!strncmp(buf, STRNG_1_WIDTH_4, BIT_WIDTH_4))
95 val = 1;
96 else if (!strncmp(buf, STRNG_2_WIDTH_4, BIT_WIDTH_4))
97 val = 2;
98 else if (!strncmp(buf, STRNG_3_WIDTH_4, BIT_WIDTH_4))
99 val = 3;
100 else if (!strncmp(buf, STRNG_4_WIDTH_4, BIT_WIDTH_4))
101 val = 4;
102 else if (!strncmp(buf, STRNG_5_WIDTH_4, BIT_WIDTH_4))
103 val = 5;
104 else if (!strncmp(buf, STRNG_6_WIDTH_4, BIT_WIDTH_4))
105 val = 6;
106 else if (!strncmp(buf, STRNG_7_WIDTH_4, BIT_WIDTH_4))
107 val = 7;
108 else if (!strncmp(buf, STRNG_8_WIDTH_4, BIT_WIDTH_4))
109 val = 8;
110 else if (!strncmp(buf, STRNG_9_WIDTH_4, BIT_WIDTH_4))
111 val = 9;
112 else if (!strncmp(buf, STRNG_A_WIDTH_4, BIT_WIDTH_4))
113 val = 10;
114 else if (!strncmp(buf, STRNG_B_WIDTH_4, BIT_WIDTH_4))
115 val = 11;
116 else if (!strncmp(buf, STRNG_C_WIDTH_4, BIT_WIDTH_4))
117 val = 12;
118 else if (!strncmp(buf, STRNG_D_WIDTH_4, BIT_WIDTH_4))
119 val = 13;
120 else if (!strncmp(buf, STRNG_E_WIDTH_4, BIT_WIDTH_4))
121 val = 14;
122 else if (!strncmp(buf, STRNG_F_WIDTH_4, BIT_WIDTH_4))
123 val = 15;
124 else
125 val = 0xFFFFFFFF;
126
127 if (val <= 15)
128 val = usb20hqa_write(addr, shift, MSK_WIDTH_4, val);
129
130 return val;
131}
132
133u32 bin2str(u32 value, u32 width, char *buffer)
134{
135 int i, temp;
136
137 temp = value;
138 buffer[width] = '\0';
139 for (i = (width - 1); i >= 0; i--) {
140 buffer[i] = '0';
141 if (value % 2)
142 buffer[i] = '1';
143
144 value /= 2;
145 }
146
147 return value;
148}
149
developerabd06d72022-03-03 16:13:41 +0800150int query_phy_addr(struct device_node *np, int *start, u32 *addr, u32 *length, int type)
developerba28e032021-12-07 10:40:00 +0800151{
152 int ret = -EPERM;
153 struct of_phandle_args args;
154 struct resource res;
developerabd06d72022-03-03 16:13:41 +0800155 struct device_node *node = np;
developerba28e032021-12-07 10:40:00 +0800156 int numphys = 0;
157 int index;
158
developerabd06d72022-03-03 16:13:41 +0800159 if (np == NULL || start == NULL || addr == NULL || length == NULL)
developerba28e032021-12-07 10:40:00 +0800160 return -EINVAL;
161
developerabd06d72022-03-03 16:13:41 +0800162 while (node) {
163 numphys = of_count_phandle_with_args(node,
164 "phys", "#phy-cells");
165 for (index = *start;
166 (numphys > 0) && index < numphys; index++) {
167 ret = of_parse_phandle_with_args(node,
168 "phys", "#phy-cells",
developerba28e032021-12-07 10:40:00 +0800169 index, &args);
developerabd06d72022-03-03 16:13:41 +0800170 if (ret < 0)
171 break;
172
173 if (args.args[0] == type) {
174 ret = of_address_to_resource(args.np,
175 0, &res);
176 if (ret < 0) {
177 of_node_put(args.np);
178 break;
179 }
developerba28e032021-12-07 10:40:00 +0800180
developerabd06d72022-03-03 16:13:41 +0800181 *addr = res.start;
182 *length = (u32)resource_size(&res);
183 *start = index;
184 if (!of_device_is_available(args.np))
185 ret = -EACCES;
186
developerba28e032021-12-07 10:40:00 +0800187 of_node_put(args.np);
188 break;
189 }
developerabd06d72022-03-03 16:13:41 +0800190 }
191 if (index < numphys)
192 break;
developerba28e032021-12-07 10:40:00 +0800193
developerabd06d72022-03-03 16:13:41 +0800194 node = node->parent;
195 }
196
197 ret = index < numphys ? ret : -EPERM;
198 return ret;
199}
developerba28e032021-12-07 10:40:00 +0800200
developerabd06d72022-03-03 16:13:41 +0800201int query_reg_addr(struct platform_device *pdev, u32 *addr, u32 *length, const char* name)
202{
203 int ret = -EPERM;
204 struct resource *pres;
205 struct platform_device *device = pdev;
206
207 if (pdev == NULL || addr == NULL || length == NULL)
208 return -EINVAL;
209
210 while (device) {
211 pres = platform_get_resource_byname(device, IORESOURCE_MEM, name);
212 if (pres != NULL) {
213 *addr = pres->start;
214 *length = (u32)resource_size(pres);
215 ret = 0;
developerba28e032021-12-07 10:40:00 +0800216 break;
217 }
developerabd06d72022-03-03 16:13:41 +0800218
219 if (device->dev.parent == NULL)
220 break;
221
222 device = to_platform_device(device->dev.parent);
developerba28e032021-12-07 10:40:00 +0800223 }
224
developerba28e032021-12-07 10:40:00 +0800225 return ret;
226}
developerabd06d72022-03-03 16:13:41 +0800227