blob: 14d7d0b14173f5f4371e8108c1f9de1b3d208cd9 [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>
16#include <dt-bindings/phy/phy.h>
17#include "xhci-mtk.h"
18#include "xhci-mtk-test.h"
19#include "xhci-mtk-unusual.h"
20
21
22u32 binary_write_width1(u32 __iomem *addr, u32 shift, const char *buf)
23{
24 u32 val = 0;
25
26 if (!strncmp(buf, STRNG_0_WIDTH_1, BIT_WIDTH_1))
27 val = 0;
28 else if (!strncmp(buf, STRNG_1_WIDTH_1, BIT_WIDTH_1))
29 val = 1;
30 else
31 val = 0xFFFFFFFF;
32
33 if (val <= 1)
34 val = usb20hqa_write(addr, shift, MSK_WIDTH_1, val);
35
36 return val;
37}
38
39u32 binary_write_width3(u32 __iomem *addr, u32 shift, const char *buf)
40{
41 u32 val = 0;
42
43 if (!strncmp(buf, STRNG_0_WIDTH_3, BIT_WIDTH_3))
44 val = 0;
45 else if (!strncmp(buf, STRNG_1_WIDTH_3, BIT_WIDTH_3))
46 val = 1;
47 else if (!strncmp(buf, STRNG_2_WIDTH_3, BIT_WIDTH_3))
48 val = 2;
49 else if (!strncmp(buf, STRNG_3_WIDTH_3, BIT_WIDTH_3))
50 val = 3;
51 else if (!strncmp(buf, STRNG_4_WIDTH_3, BIT_WIDTH_3))
52 val = 4;
53 else if (!strncmp(buf, STRNG_5_WIDTH_3, BIT_WIDTH_3))
54 val = 5;
55 else if (!strncmp(buf, STRNG_6_WIDTH_3, BIT_WIDTH_3))
56 val = 6;
57 else if (!strncmp(buf, STRNG_7_WIDTH_3, BIT_WIDTH_3))
58 val = 7;
59 else
60 val = 0xFFFFFFFF;
61
62 if (val <= 7)
63 val = usb20hqa_write(addr, shift, MSK_WIDTH_3, val);
64
65 return val;
66}
67
68u32 binary_write_width4(u32 __iomem *addr, u32 shift, const char *buf)
69{
70 u32 val = 0;
71
72 if (!strncmp(buf, STRNG_0_WIDTH_4, BIT_WIDTH_4))
73 val = 0;
74 else if (!strncmp(buf, STRNG_1_WIDTH_4, BIT_WIDTH_4))
75 val = 1;
76 else if (!strncmp(buf, STRNG_2_WIDTH_4, BIT_WIDTH_4))
77 val = 2;
78 else if (!strncmp(buf, STRNG_3_WIDTH_4, BIT_WIDTH_4))
79 val = 3;
80 else if (!strncmp(buf, STRNG_4_WIDTH_4, BIT_WIDTH_4))
81 val = 4;
82 else if (!strncmp(buf, STRNG_5_WIDTH_4, BIT_WIDTH_4))
83 val = 5;
84 else if (!strncmp(buf, STRNG_6_WIDTH_4, BIT_WIDTH_4))
85 val = 6;
86 else if (!strncmp(buf, STRNG_7_WIDTH_4, BIT_WIDTH_4))
87 val = 7;
88 else if (!strncmp(buf, STRNG_8_WIDTH_4, BIT_WIDTH_4))
89 val = 8;
90 else if (!strncmp(buf, STRNG_9_WIDTH_4, BIT_WIDTH_4))
91 val = 9;
92 else if (!strncmp(buf, STRNG_A_WIDTH_4, BIT_WIDTH_4))
93 val = 10;
94 else if (!strncmp(buf, STRNG_B_WIDTH_4, BIT_WIDTH_4))
95 val = 11;
96 else if (!strncmp(buf, STRNG_C_WIDTH_4, BIT_WIDTH_4))
97 val = 12;
98 else if (!strncmp(buf, STRNG_D_WIDTH_4, BIT_WIDTH_4))
99 val = 13;
100 else if (!strncmp(buf, STRNG_E_WIDTH_4, BIT_WIDTH_4))
101 val = 14;
102 else if (!strncmp(buf, STRNG_F_WIDTH_4, BIT_WIDTH_4))
103 val = 15;
104 else
105 val = 0xFFFFFFFF;
106
107 if (val <= 15)
108 val = usb20hqa_write(addr, shift, MSK_WIDTH_4, val);
109
110 return val;
111}
112
113u32 bin2str(u32 value, u32 width, char *buffer)
114{
115 int i, temp;
116
117 temp = value;
118 buffer[width] = '\0';
119 for (i = (width - 1); i >= 0; i--) {
120 buffer[i] = '0';
121 if (value % 2)
122 buffer[i] = '1';
123
124 value /= 2;
125 }
126
127 return value;
128}
129
130int query_phy_addr(struct device_node *np, int *start, u32 *addr, u32 *length)
131{
132 int ret = -EPERM;
133 struct of_phandle_args args;
134 struct resource res;
135 int numphys = 0;
136 int index;
137
138 if (start == NULL || addr == NULL || length == NULL)
139 return -EINVAL;
140
141 numphys = of_count_phandle_with_args(np, "phys", "#phy-cells");
142 for ( index = *start; (numphys > 0) && index < numphys; index++) {
143 ret = of_parse_phandle_with_args(np, "phys", "#phy-cells",
144 index, &args);
145 if (ret < 0)
146 break;
147
148 if (args.args[0] == PHY_TYPE_USB2) {
149 ret = of_address_to_resource(args.np, 0, &res);
150 if (ret < 0) {
151 of_node_put(args.np);
152 break;
153 }
154
155 *addr = res.start;
156 *length = (u32)resource_size(&res);
157 *start = index;
158 if (!of_device_is_available(args.np))
159 ret = -EACCES;
160
161 of_node_put(args.np);
162 break;
163 }
164 }
165
166 ret = index < numphys ? ret : -EPERM;
167 return ret;
168}