blob: 01029fb22ed89cdd6d844d5ae7b66f8a9284bfb5 [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
38u32 binary_write_width3(u32 __iomem *addr, u32 shift, const char *buf)
39{
40 u32 val = 0;
41
42 if (!strncmp(buf, STRNG_0_WIDTH_3, BIT_WIDTH_3))
43 val = 0;
44 else if (!strncmp(buf, STRNG_1_WIDTH_3, BIT_WIDTH_3))
45 val = 1;
46 else if (!strncmp(buf, STRNG_2_WIDTH_3, BIT_WIDTH_3))
47 val = 2;
48 else if (!strncmp(buf, STRNG_3_WIDTH_3, BIT_WIDTH_3))
49 val = 3;
50 else if (!strncmp(buf, STRNG_4_WIDTH_3, BIT_WIDTH_3))
51 val = 4;
52 else if (!strncmp(buf, STRNG_5_WIDTH_3, BIT_WIDTH_3))
53 val = 5;
54 else if (!strncmp(buf, STRNG_6_WIDTH_3, BIT_WIDTH_3))
55 val = 6;
56 else if (!strncmp(buf, STRNG_7_WIDTH_3, BIT_WIDTH_3))
57 val = 7;
58 else
59 val = 0xFFFFFFFF;
60
61 if (val <= 7)
62 val = usb20hqa_write(addr, shift, MSK_WIDTH_3, val);
63
64 return val;
65}
66
67u32 binary_write_width4(u32 __iomem *addr, u32 shift, const char *buf)
68{
69 u32 val = 0;
70
71 if (!strncmp(buf, STRNG_0_WIDTH_4, BIT_WIDTH_4))
72 val = 0;
73 else if (!strncmp(buf, STRNG_1_WIDTH_4, BIT_WIDTH_4))
74 val = 1;
75 else if (!strncmp(buf, STRNG_2_WIDTH_4, BIT_WIDTH_4))
76 val = 2;
77 else if (!strncmp(buf, STRNG_3_WIDTH_4, BIT_WIDTH_4))
78 val = 3;
79 else if (!strncmp(buf, STRNG_4_WIDTH_4, BIT_WIDTH_4))
80 val = 4;
81 else if (!strncmp(buf, STRNG_5_WIDTH_4, BIT_WIDTH_4))
82 val = 5;
83 else if (!strncmp(buf, STRNG_6_WIDTH_4, BIT_WIDTH_4))
84 val = 6;
85 else if (!strncmp(buf, STRNG_7_WIDTH_4, BIT_WIDTH_4))
86 val = 7;
87 else if (!strncmp(buf, STRNG_8_WIDTH_4, BIT_WIDTH_4))
88 val = 8;
89 else if (!strncmp(buf, STRNG_9_WIDTH_4, BIT_WIDTH_4))
90 val = 9;
91 else if (!strncmp(buf, STRNG_A_WIDTH_4, BIT_WIDTH_4))
92 val = 10;
93 else if (!strncmp(buf, STRNG_B_WIDTH_4, BIT_WIDTH_4))
94 val = 11;
95 else if (!strncmp(buf, STRNG_C_WIDTH_4, BIT_WIDTH_4))
96 val = 12;
97 else if (!strncmp(buf, STRNG_D_WIDTH_4, BIT_WIDTH_4))
98 val = 13;
99 else if (!strncmp(buf, STRNG_E_WIDTH_4, BIT_WIDTH_4))
100 val = 14;
101 else if (!strncmp(buf, STRNG_F_WIDTH_4, BIT_WIDTH_4))
102 val = 15;
103 else
104 val = 0xFFFFFFFF;
105
106 if (val <= 15)
107 val = usb20hqa_write(addr, shift, MSK_WIDTH_4, val);
108
109 return val;
110}
111
112u32 bin2str(u32 value, u32 width, char *buffer)
113{
114 int i, temp;
115
116 temp = value;
117 buffer[width] = '\0';
118 for (i = (width - 1); i >= 0; i--) {
119 buffer[i] = '0';
120 if (value % 2)
121 buffer[i] = '1';
122
123 value /= 2;
124 }
125
126 return value;
127}
128
developerabd06d72022-03-03 16:13:41 +0800129int query_phy_addr(struct device_node *np, int *start, u32 *addr, u32 *length, int type)
developerba28e032021-12-07 10:40:00 +0800130{
131 int ret = -EPERM;
132 struct of_phandle_args args;
133 struct resource res;
developerabd06d72022-03-03 16:13:41 +0800134 struct device_node *node = np;
developerba28e032021-12-07 10:40:00 +0800135 int numphys = 0;
136 int index;
137
developerabd06d72022-03-03 16:13:41 +0800138 if (np == NULL || start == NULL || addr == NULL || length == NULL)
developerba28e032021-12-07 10:40:00 +0800139 return -EINVAL;
140
developerabd06d72022-03-03 16:13:41 +0800141 while (node) {
142 numphys = of_count_phandle_with_args(node,
143 "phys", "#phy-cells");
144 for (index = *start;
145 (numphys > 0) && index < numphys; index++) {
146 ret = of_parse_phandle_with_args(node,
147 "phys", "#phy-cells",
developerba28e032021-12-07 10:40:00 +0800148 index, &args);
developerabd06d72022-03-03 16:13:41 +0800149 if (ret < 0)
150 break;
151
152 if (args.args[0] == type) {
153 ret = of_address_to_resource(args.np,
154 0, &res);
155 if (ret < 0) {
156 of_node_put(args.np);
157 break;
158 }
developerba28e032021-12-07 10:40:00 +0800159
developerabd06d72022-03-03 16:13:41 +0800160 *addr = res.start;
161 *length = (u32)resource_size(&res);
162 *start = index;
163 if (!of_device_is_available(args.np))
164 ret = -EACCES;
165
developerba28e032021-12-07 10:40:00 +0800166 of_node_put(args.np);
167 break;
168 }
developerabd06d72022-03-03 16:13:41 +0800169 }
170 if (index < numphys)
171 break;
developerba28e032021-12-07 10:40:00 +0800172
developerabd06d72022-03-03 16:13:41 +0800173 node = node->parent;
174 }
175
176 ret = index < numphys ? ret : -EPERM;
177 return ret;
178}
developerba28e032021-12-07 10:40:00 +0800179
developerabd06d72022-03-03 16:13:41 +0800180int query_reg_addr(struct platform_device *pdev, u32 *addr, u32 *length, const char* name)
181{
182 int ret = -EPERM;
183 struct resource *pres;
184 struct platform_device *device = pdev;
185
186 if (pdev == NULL || addr == NULL || length == NULL)
187 return -EINVAL;
188
189 while (device) {
190 pres = platform_get_resource_byname(device, IORESOURCE_MEM, name);
191 if (pres != NULL) {
192 *addr = pres->start;
193 *length = (u32)resource_size(pres);
194 ret = 0;
developerba28e032021-12-07 10:40:00 +0800195 break;
196 }
developerabd06d72022-03-03 16:13:41 +0800197
198 if (device->dev.parent == NULL)
199 break;
200
201 device = to_platform_device(device->dev.parent);
developerba28e032021-12-07 10:40:00 +0800202 }
203
developerba28e032021-12-07 10:40:00 +0800204 return ret;
205}
developerabd06d72022-03-03 16:13:41 +0800206