xref: /linux/drivers/net/wireless/realtek/rtl8xxxu/8188f.c (revision a1ff5a7d78a036d6c2178ee5acd6ba4946243800)
1028fa281SKalle Valo // SPDX-License-Identifier: GPL-2.0-only
2028fa281SKalle Valo /*
3028fa281SKalle Valo  * RTL8XXXU mac80211 USB driver - 8188f specific subdriver
4028fa281SKalle Valo  *
5028fa281SKalle Valo  * Copyright (c) 2022 Bitterblue Smith <rtl8821cerfe2@gmail.com>
6028fa281SKalle Valo  *
7028fa281SKalle Valo  * Portions copied from existing rtl8xxxu code:
8028fa281SKalle Valo  * Copyright (c) 2014 - 2017 Jes Sorensen <Jes.Sorensen@gmail.com>
9028fa281SKalle Valo  *
10028fa281SKalle Valo  * Portions, notably calibration code:
11028fa281SKalle Valo  * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
12028fa281SKalle Valo  */
13028fa281SKalle Valo 
14028fa281SKalle Valo #include "regs.h"
15949f6f3aSPing-Ke Shih #include "rtl8xxxu.h"
16028fa281SKalle Valo 
17028fa281SKalle Valo static const struct rtl8xxxu_reg8val rtl8188f_mac_init_table[] = {
18028fa281SKalle Valo 	{0x024, 0xDF}, {0x025, 0x07}, {0x02B, 0x1C}, {0x283, 0x20},
19028fa281SKalle Valo 	{0x421, 0x0F}, {0x428, 0x0A}, {0x429, 0x10}, {0x430, 0x00},
20028fa281SKalle Valo 	{0x431, 0x00}, {0x432, 0x00}, {0x433, 0x01}, {0x434, 0x04},
21028fa281SKalle Valo 	{0x435, 0x05}, {0x436, 0x07}, {0x437, 0x08}, {0x43C, 0x04},
22028fa281SKalle Valo 	{0x43D, 0x05}, {0x43E, 0x07}, {0x43F, 0x08}, {0x440, 0x5D},
23028fa281SKalle Valo 	{0x441, 0x01}, {0x442, 0x00}, {0x444, 0x10}, {0x445, 0x00},
24028fa281SKalle Valo 	{0x446, 0x00}, {0x447, 0x00}, {0x448, 0x00}, {0x449, 0xF0},
25028fa281SKalle Valo 	{0x44A, 0x0F}, {0x44B, 0x3E}, {0x44C, 0x10}, {0x44D, 0x00},
26028fa281SKalle Valo 	{0x44E, 0x00}, {0x44F, 0x00}, {0x450, 0x00}, {0x451, 0xF0},
27028fa281SKalle Valo 	{0x452, 0x0F}, {0x453, 0x00}, {0x456, 0x5E}, {0x460, 0x44},
28028fa281SKalle Valo 	{0x461, 0x44}, {0x4BC, 0xC0}, {0x4C8, 0xFF}, {0x4C9, 0x08},
29028fa281SKalle Valo 	{0x4CC, 0xFF}, {0x4CD, 0xFF}, {0x4CE, 0x01}, {0x500, 0x26},
30028fa281SKalle Valo 	{0x501, 0xA2}, {0x502, 0x2F}, {0x503, 0x00}, {0x504, 0x28},
31028fa281SKalle Valo 	{0x505, 0xA3}, {0x506, 0x5E}, {0x507, 0x00}, {0x508, 0x2B},
32028fa281SKalle Valo 	{0x509, 0xA4}, {0x50A, 0x5E}, {0x50B, 0x00}, {0x50C, 0x4F},
33028fa281SKalle Valo 	{0x50D, 0xA4}, {0x50E, 0x00}, {0x50F, 0x00}, {0x512, 0x1C},
34028fa281SKalle Valo 	{0x514, 0x0A}, {0x516, 0x0A}, {0x525, 0x4F}, {0x550, 0x10},
35028fa281SKalle Valo 	{0x551, 0x10}, {0x559, 0x02}, {0x55C, 0x28}, {0x55D, 0xFF},
36028fa281SKalle Valo 	{0x605, 0x30}, {0x608, 0x0E}, {0x609, 0x2A}, {0x620, 0xFF},
37028fa281SKalle Valo 	{0x621, 0xFF}, {0x622, 0xFF}, {0x623, 0xFF}, {0x624, 0xFF},
38028fa281SKalle Valo 	{0x625, 0xFF}, {0x626, 0xFF}, {0x627, 0xFF}, {0x638, 0x28},
39028fa281SKalle Valo 	{0x63C, 0x0A}, {0x63D, 0x0A}, {0x63E, 0x0E}, {0x63F, 0x0E},
40028fa281SKalle Valo 	{0x640, 0x40}, {0x642, 0x40}, {0x643, 0x00}, {0x652, 0xC8},
41028fa281SKalle Valo 	{0x66E, 0x05}, {0x700, 0x21}, {0x701, 0x43}, {0x702, 0x65},
42028fa281SKalle Valo 	{0x703, 0x87}, {0x708, 0x21}, {0x709, 0x43}, {0x70A, 0x65},
43028fa281SKalle Valo 	{0x70B, 0x87},
44028fa281SKalle Valo 	{0xffff, 0xff},
45028fa281SKalle Valo };
46028fa281SKalle Valo 
47028fa281SKalle Valo static const struct rtl8xxxu_reg32val rtl8188fu_phy_init_table[] = {
48028fa281SKalle Valo 	{0x800, 0x80045700}, {0x804, 0x00000001},
49028fa281SKalle Valo 	{0x808, 0x0000FC00}, {0x80C, 0x0000000A},
50028fa281SKalle Valo 	{0x810, 0x10001331}, {0x814, 0x020C3D10},
51028fa281SKalle Valo 	{0x818, 0x00200385}, {0x81C, 0x00000000},
52028fa281SKalle Valo 	{0x820, 0x01000100}, {0x824, 0x00390204},
53028fa281SKalle Valo 	{0x828, 0x00000000}, {0x82C, 0x00000000},
54028fa281SKalle Valo 	{0x830, 0x00000000}, {0x834, 0x00000000},
55028fa281SKalle Valo 	{0x838, 0x00000000}, {0x83C, 0x00000000},
56028fa281SKalle Valo 	{0x840, 0x00010000}, {0x844, 0x00000000},
57028fa281SKalle Valo 	{0x848, 0x00000000}, {0x84C, 0x00000000},
58028fa281SKalle Valo 	{0x850, 0x00030000}, {0x854, 0x00000000},
59028fa281SKalle Valo 	{0x858, 0x569A569A}, {0x85C, 0x569A569A},
60028fa281SKalle Valo 	{0x860, 0x00000130}, {0x864, 0x00000000},
61028fa281SKalle Valo 	{0x868, 0x00000000}, {0x86C, 0x27272700},
62028fa281SKalle Valo 	{0x870, 0x00000000}, {0x874, 0x25004000},
63028fa281SKalle Valo 	{0x878, 0x00000808}, {0x87C, 0x004F0201},
64028fa281SKalle Valo 	{0x880, 0xB0000B1E}, {0x884, 0x00000007},
65028fa281SKalle Valo 	{0x888, 0x00000000}, {0x88C, 0xCCC000C0},
66028fa281SKalle Valo 	{0x890, 0x00000800}, {0x894, 0xFFFFFFFE},
67028fa281SKalle Valo 	{0x898, 0x40302010}, {0x89C, 0x00706050},
68028fa281SKalle Valo 	{0x900, 0x00000000}, {0x904, 0x00000023},
69028fa281SKalle Valo 	{0x908, 0x00000000}, {0x90C, 0x81121111},
70028fa281SKalle Valo 	{0x910, 0x00000002}, {0x914, 0x00000201},
71028fa281SKalle Valo 	{0x948, 0x99000000}, {0x94C, 0x00000010},
72028fa281SKalle Valo 	{0x950, 0x20003000}, {0x954, 0x4A880000},
73028fa281SKalle Valo 	{0x958, 0x4BC5D87A}, {0x95C, 0x04EB9B79},
74028fa281SKalle Valo 	{0x96C, 0x00000003}, {0xA00, 0x00D047C8},
75028fa281SKalle Valo 	{0xA04, 0x80FF800C}, {0xA08, 0x8C898300},
76028fa281SKalle Valo 	{0xA0C, 0x2E7F120F}, {0xA10, 0x9500BB78},
77028fa281SKalle Valo 	{0xA14, 0x1114D028}, {0xA18, 0x00881117},
78028fa281SKalle Valo 	{0xA1C, 0x89140F00}, {0xA20, 0xD1D80000},
79028fa281SKalle Valo 	{0xA24, 0x5A7DA0BD}, {0xA28, 0x0000223B},
80028fa281SKalle Valo 	{0xA2C, 0x00D30000}, {0xA70, 0x101FBF00},
81028fa281SKalle Valo 	{0xA74, 0x00000007}, {0xA78, 0x00000900},
82028fa281SKalle Valo 	{0xA7C, 0x225B0606}, {0xA80, 0x218075B1},
83028fa281SKalle Valo 	{0xA84, 0x00120000}, {0xA88, 0x040C0000},
84028fa281SKalle Valo 	{0xA8C, 0x12345678}, {0xA90, 0xABCDEF00},
85028fa281SKalle Valo 	{0xA94, 0x001B1B89}, {0xA98, 0x05100000},
86028fa281SKalle Valo 	{0xA9C, 0x3F000000}, {0xAA0, 0x00000000},
87028fa281SKalle Valo 	{0xB2C, 0x00000000}, {0xC00, 0x48071D40},
88028fa281SKalle Valo 	{0xC04, 0x03A05611}, {0xC08, 0x000000E4},
89028fa281SKalle Valo 	{0xC0C, 0x6C6C6C6C}, {0xC10, 0x18800000},
90028fa281SKalle Valo 	{0xC14, 0x40000100}, {0xC18, 0x08800000},
91028fa281SKalle Valo 	{0xC1C, 0x40000100}, {0xC20, 0x00000000},
92028fa281SKalle Valo 	{0xC24, 0x00000000}, {0xC28, 0x00000000},
93028fa281SKalle Valo 	{0xC2C, 0x00000000}, {0xC30, 0x69E9CC4A},
94028fa281SKalle Valo 	{0xC34, 0x31000040}, {0xC38, 0x21688080},
95028fa281SKalle Valo 	{0xC3C, 0x00001714}, {0xC40, 0x1F78403F},
96028fa281SKalle Valo 	{0xC44, 0x00010036}, {0xC48, 0xEC020107},
97028fa281SKalle Valo 	{0xC4C, 0x007F037F}, {0xC50, 0x69553420},
98028fa281SKalle Valo 	{0xC54, 0x43BC0094}, {0xC58, 0x00013169},
99028fa281SKalle Valo 	{0xC5C, 0x00250492}, {0xC60, 0x00000000},
100028fa281SKalle Valo 	{0xC64, 0x7112848B}, {0xC68, 0x47C07BFF},
101028fa281SKalle Valo 	{0xC6C, 0x00000036}, {0xC70, 0x2C7F000D},
102028fa281SKalle Valo 	{0xC74, 0x020600DB}, {0xC78, 0x0000001F},
103028fa281SKalle Valo 	{0xC7C, 0x00B91612}, {0xC80, 0x390000E4},
104028fa281SKalle Valo 	{0xC84, 0x11F60000},
105028fa281SKalle Valo 	{0xC88, 0x40000100}, {0xC8C, 0x20200000},
106028fa281SKalle Valo 	{0xC90, 0x00091521}, {0xC94, 0x00000000},
107028fa281SKalle Valo 	{0xC98, 0x00121820}, {0xC9C, 0x00007F7F},
108028fa281SKalle Valo 	{0xCA0, 0x00000000}, {0xCA4, 0x000300A0},
109028fa281SKalle Valo 	{0xCA8, 0x00000000}, {0xCAC, 0x00000000},
110028fa281SKalle Valo 	{0xCB0, 0x00000000}, {0xCB4, 0x00000000},
111028fa281SKalle Valo 	{0xCB8, 0x00000000}, {0xCBC, 0x28000000},
112028fa281SKalle Valo 	{0xCC0, 0x00000000}, {0xCC4, 0x00000000},
113028fa281SKalle Valo 	{0xCC8, 0x00000000}, {0xCCC, 0x00000000},
114028fa281SKalle Valo 	{0xCD0, 0x00000000}, {0xCD4, 0x00000000},
115028fa281SKalle Valo 	{0xCD8, 0x64B22427}, {0xCDC, 0x00766932},
116028fa281SKalle Valo 	{0xCE0, 0x00222222}, {0xCE4, 0x10000000},
117028fa281SKalle Valo 	{0xCE8, 0x37644302}, {0xCEC, 0x2F97D40C},
118028fa281SKalle Valo 	{0xD00, 0x04030740}, {0xD04, 0x40020401},
119028fa281SKalle Valo 	{0xD08, 0x0000907F}, {0xD0C, 0x20010201},
120028fa281SKalle Valo 	{0xD10, 0xA0633333}, {0xD14, 0x3333BC53},
121028fa281SKalle Valo 	{0xD18, 0x7A8F5B6F}, {0xD2C, 0xCB979975},
122028fa281SKalle Valo 	{0xD30, 0x00000000}, {0xD34, 0x80608000},
123028fa281SKalle Valo 	{0xD38, 0x98000000}, {0xD3C, 0x40127353},
124028fa281SKalle Valo 	{0xD40, 0x00000000}, {0xD44, 0x00000000},
125028fa281SKalle Valo 	{0xD48, 0x00000000}, {0xD4C, 0x00000000},
126028fa281SKalle Valo 	{0xD50, 0x6437140A}, {0xD54, 0x00000000},
127028fa281SKalle Valo 	{0xD58, 0x00000282}, {0xD5C, 0x30032064},
128028fa281SKalle Valo 	{0xD60, 0x4653DE68}, {0xD64, 0x04518A3C},
129028fa281SKalle Valo 	{0xD68, 0x00002101}, {0xD6C, 0x2A201C16},
130028fa281SKalle Valo 	{0xD70, 0x1812362E}, {0xD74, 0x322C2220},
131028fa281SKalle Valo 	{0xD78, 0x000E3C24}, {0xE00, 0x2D2D2D2D},
132028fa281SKalle Valo 	{0xE04, 0x2D2D2D2D}, {0xE08, 0x0390272D},
133028fa281SKalle Valo 	{0xE10, 0x2D2D2D2D}, {0xE14, 0x2D2D2D2D},
134028fa281SKalle Valo 	{0xE18, 0x2D2D2D2D}, {0xE1C, 0x2D2D2D2D},
135028fa281SKalle Valo 	{0xE28, 0x00000000}, {0xE30, 0x1000DC1F},
136028fa281SKalle Valo 	{0xE34, 0x10008C1F}, {0xE38, 0x02140102},
137028fa281SKalle Valo 	{0xE3C, 0x681604C2}, {0xE40, 0x01007C00},
138028fa281SKalle Valo 	{0xE44, 0x01004800}, {0xE48, 0xFB000000},
139028fa281SKalle Valo 	{0xE4C, 0x000028D1}, {0xE50, 0x1000DC1F},
140028fa281SKalle Valo 	{0xE54, 0x10008C1F}, {0xE58, 0x02140102},
141028fa281SKalle Valo 	{0xE5C, 0x28160D05}, {0xE60, 0x00000008},
142028fa281SKalle Valo 	{0xE60, 0x021400A0}, {0xE64, 0x281600A0},
143028fa281SKalle Valo 	{0xE6C, 0x01C00010}, {0xE70, 0x01C00010},
144028fa281SKalle Valo 	{0xE74, 0x02000010}, {0xE78, 0x02000010},
145028fa281SKalle Valo 	{0xE7C, 0x02000010}, {0xE80, 0x02000010},
146028fa281SKalle Valo 	{0xE84, 0x01C00010}, {0xE88, 0x02000010},
147028fa281SKalle Valo 	{0xE8C, 0x01C00010}, {0xED0, 0x01C00010},
148028fa281SKalle Valo 	{0xED4, 0x01C00010}, {0xED8, 0x01C00010},
149028fa281SKalle Valo 	{0xEDC, 0x00000010}, {0xEE0, 0x00000010},
150028fa281SKalle Valo 	{0xEEC, 0x03C00010}, {0xF14, 0x00000003},
151028fa281SKalle Valo 	{0xF4C, 0x00000000}, {0xF00, 0x00000300},
152028fa281SKalle Valo 	{0xffff, 0xffffffff},
153028fa281SKalle Valo };
154028fa281SKalle Valo 
155028fa281SKalle Valo static const struct rtl8xxxu_reg32val rtl8188f_agc_table[] = {
156028fa281SKalle Valo 	{0xC78, 0xFC000001}, {0xC78, 0xFB010001},
157028fa281SKalle Valo 	{0xC78, 0xFA020001}, {0xC78, 0xF9030001},
158028fa281SKalle Valo 	{0xC78, 0xF8040001}, {0xC78, 0xF7050001},
159028fa281SKalle Valo 	{0xC78, 0xF6060001}, {0xC78, 0xF5070001},
160028fa281SKalle Valo 	{0xC78, 0xF4080001}, {0xC78, 0xF3090001},
161028fa281SKalle Valo 	{0xC78, 0xF20A0001}, {0xC78, 0xF10B0001},
162028fa281SKalle Valo 	{0xC78, 0xF00C0001}, {0xC78, 0xEF0D0001},
163028fa281SKalle Valo 	{0xC78, 0xEE0E0001}, {0xC78, 0xED0F0001},
164028fa281SKalle Valo 	{0xC78, 0xEC100001}, {0xC78, 0xEB110001},
165028fa281SKalle Valo 	{0xC78, 0xEA120001}, {0xC78, 0xE9130001},
166028fa281SKalle Valo 	{0xC78, 0xE8140001}, {0xC78, 0xE7150001},
167028fa281SKalle Valo 	{0xC78, 0xE6160001}, {0xC78, 0xE5170001},
168028fa281SKalle Valo 	{0xC78, 0xE4180001}, {0xC78, 0xE3190001},
169028fa281SKalle Valo 	{0xC78, 0xE21A0001}, {0xC78, 0xE11B0001},
170028fa281SKalle Valo 	{0xC78, 0xE01C0001}, {0xC78, 0xC21D0001},
171028fa281SKalle Valo 	{0xC78, 0xC11E0001}, {0xC78, 0xC01F0001},
172028fa281SKalle Valo 	{0xC78, 0xA5200001}, {0xC78, 0xA4210001},
173028fa281SKalle Valo 	{0xC78, 0xA3220001}, {0xC78, 0xA2230001},
174028fa281SKalle Valo 	{0xC78, 0xA1240001}, {0xC78, 0xA0250001},
175028fa281SKalle Valo 	{0xC78, 0x65260001}, {0xC78, 0x64270001},
176028fa281SKalle Valo 	{0xC78, 0x63280001}, {0xC78, 0x62290001},
177028fa281SKalle Valo 	{0xC78, 0x612A0001}, {0xC78, 0x442B0001},
178028fa281SKalle Valo 	{0xC78, 0x432C0001}, {0xC78, 0x422D0001},
179028fa281SKalle Valo 	{0xC78, 0x412E0001}, {0xC78, 0x402F0001},
180028fa281SKalle Valo 	{0xC78, 0x21300001}, {0xC78, 0x20310001},
181028fa281SKalle Valo 	{0xC78, 0x05320001}, {0xC78, 0x04330001},
182028fa281SKalle Valo 	{0xC78, 0x03340001}, {0xC78, 0x02350001},
183028fa281SKalle Valo 	{0xC78, 0x01360001}, {0xC78, 0x00370001},
184028fa281SKalle Valo 	{0xC78, 0x00380001}, {0xC78, 0x00390001},
185028fa281SKalle Valo 	{0xC78, 0x003A0001}, {0xC78, 0x003B0001},
186028fa281SKalle Valo 	{0xC78, 0x003C0001}, {0xC78, 0x003D0001},
187028fa281SKalle Valo 	{0xC78, 0x003E0001}, {0xC78, 0x003F0001},
188028fa281SKalle Valo 	{0xC50, 0x69553422}, {0xC50, 0x69553420},
189028fa281SKalle Valo 	{0xffff, 0xffffffff}
190028fa281SKalle Valo };
191028fa281SKalle Valo 
192028fa281SKalle Valo static const struct rtl8xxxu_rfregval rtl8188fu_radioa_init_table[] = {
193028fa281SKalle Valo 	{0x00, 0x00030000}, {0x08, 0x00008400},
194028fa281SKalle Valo 	{0x18, 0x00000407}, {0x19, 0x00000012},
195028fa281SKalle Valo 	{0x1B, 0x00001C6C},
196028fa281SKalle Valo 	{0x1E, 0x00080009}, {0x1F, 0x00000880},
197028fa281SKalle Valo 	{0x2F, 0x0001A060}, {0x3F, 0x00028000},
198028fa281SKalle Valo 	{0x42, 0x000060C0}, {0x57, 0x000D0000},
199028fa281SKalle Valo 	{0x58, 0x000C0160}, {0x67, 0x00001552},
200028fa281SKalle Valo 	{0x83, 0x00000000}, {0xB0, 0x000FF9F0},
201028fa281SKalle Valo 	{0xB1, 0x00022218}, {0xB2, 0x00034C00},
202028fa281SKalle Valo 	{0xB4, 0x0004484B}, {0xB5, 0x0000112A},
203028fa281SKalle Valo 	{0xB6, 0x0000053E}, {0xB7, 0x00010408},
204028fa281SKalle Valo 	{0xB8, 0x00010200}, {0xB9, 0x00080001},
205028fa281SKalle Valo 	{0xBA, 0x00040001}, {0xBB, 0x00000400},
206028fa281SKalle Valo 	{0xBF, 0x000C0000}, {0xC2, 0x00002400},
207028fa281SKalle Valo 	{0xC3, 0x00000009}, {0xC4, 0x00040C91},
208028fa281SKalle Valo 	{0xC5, 0x00099999}, {0xC6, 0x000000A3},
209028fa281SKalle Valo 	{0xC7, 0x0008F820}, {0xC8, 0x00076C06},
210028fa281SKalle Valo 	{0xC9, 0x00000000}, {0xCA, 0x00080000},
211028fa281SKalle Valo 	{0xDF, 0x00000180}, {0xEF, 0x000001A0},
212028fa281SKalle Valo 	{0x51, 0x000E8333}, {0x52, 0x000FAC2C},
213028fa281SKalle Valo 	{0x53, 0x00000103}, {0x56, 0x000517F0},
214028fa281SKalle Valo 	{0x35, 0x00000099}, {0x35, 0x00000199},
215028fa281SKalle Valo 	{0x35, 0x00000299}, {0x36, 0x00000064},
216028fa281SKalle Valo 	{0x36, 0x00008064}, {0x36, 0x00010064},
217028fa281SKalle Valo 	{0x36, 0x00018064}, {0x18, 0x00000C07},
218028fa281SKalle Valo 	{0x5A, 0x00048000}, {0x19, 0x000739D0},
219028fa281SKalle Valo 	{0x34, 0x0000ADD6}, {0x34, 0x00009DD3},
220028fa281SKalle Valo 	{0x34, 0x00008CF4}, {0x34, 0x00007CF1},
221028fa281SKalle Valo 	{0x34, 0x00006CEE}, {0x34, 0x00005CEB},
222028fa281SKalle Valo 	{0x34, 0x00004CCE}, {0x34, 0x00003CCB},
223028fa281SKalle Valo 	{0x34, 0x00002CC8}, {0x34, 0x00001C4B},
224028fa281SKalle Valo 	{0x34, 0x00000C48},
225028fa281SKalle Valo 	{0x00, 0x00030159}, {0x84, 0x00048000},
226028fa281SKalle Valo 	{0x86, 0x0000002A}, {0x87, 0x00000025},
227028fa281SKalle Valo 	{0x8E, 0x00065540}, {0x8F, 0x00088000},
228028fa281SKalle Valo 	{0xEF, 0x000020A0}, {0x3B, 0x000F0F00},
229028fa281SKalle Valo 	{0x3B, 0x000E0B00}, {0x3B, 0x000D0900},
230028fa281SKalle Valo 	{0x3B, 0x000C0700}, {0x3B, 0x000B0600},
231028fa281SKalle Valo 	{0x3B, 0x000A0400}, {0x3B, 0x00090200},
232028fa281SKalle Valo 	{0x3B, 0x00080000}, {0x3B, 0x0007BF00},
233028fa281SKalle Valo 	{0x3B, 0x00060B00}, {0x3B, 0x0005C900},
234028fa281SKalle Valo 	{0x3B, 0x00040700}, {0x3B, 0x00030600},
235028fa281SKalle Valo 	{0x3B, 0x0002D500}, {0x3B, 0x00010200},
236028fa281SKalle Valo 	{0x3B, 0x0000E000}, {0xEF, 0x000000A0},
237028fa281SKalle Valo 	{0xEF, 0x00000010}, {0x3B, 0x0000C0A8},
238028fa281SKalle Valo 	{0x3B, 0x00010400}, {0xEF, 0x00000000},
239028fa281SKalle Valo 	{0xEF, 0x00080000}, {0x30, 0x00010000},
240028fa281SKalle Valo 	{0x31, 0x0000000F}, {0x32, 0x00007EFE},
241028fa281SKalle Valo 	{0xEF, 0x00000000}, {0x00, 0x00010159},
242028fa281SKalle Valo 	{0x18, 0x0000FC07}, {0xFE, 0x00000000},
243028fa281SKalle Valo 	{0xFE, 0x00000000}, {0x1F, 0x00080003},
244028fa281SKalle Valo 	{0xFE, 0x00000000}, {0xFE, 0x00000000},
245028fa281SKalle Valo 	{0x1E, 0x00000001}, {0x1F, 0x00080000},
246028fa281SKalle Valo 	{0x00, 0x00033D95},
247028fa281SKalle Valo 	{0xff, 0xffffffff}
248028fa281SKalle Valo };
249028fa281SKalle Valo 
250028fa281SKalle Valo static const struct rtl8xxxu_rfregval rtl8188fu_cut_b_radioa_init_table[] = {
251028fa281SKalle Valo 	{0x00, 0x00030000}, {0x08, 0x00008400},
252028fa281SKalle Valo 	{0x18, 0x00000407}, {0x19, 0x00000012},
253028fa281SKalle Valo 	{0x1B, 0x00001C6C},
254028fa281SKalle Valo 	{0x1E, 0x00080009}, {0x1F, 0x00000880},
255028fa281SKalle Valo 	{0x2F, 0x0001A060}, {0x3F, 0x00028000},
256028fa281SKalle Valo 	{0x42, 0x000060C0}, {0x57, 0x000D0000},
257028fa281SKalle Valo 	{0x58, 0x000C0160}, {0x67, 0x00001552},
258028fa281SKalle Valo 	{0x83, 0x00000000}, {0xB0, 0x000FF9F0},
259028fa281SKalle Valo 	{0xB1, 0x00022218}, {0xB2, 0x00034C00},
260028fa281SKalle Valo 	{0xB4, 0x0004484B}, {0xB5, 0x0000112A},
261028fa281SKalle Valo 	{0xB6, 0x0000053E}, {0xB7, 0x00010408},
262028fa281SKalle Valo 	{0xB8, 0x00010200}, {0xB9, 0x00080001},
263028fa281SKalle Valo 	{0xBA, 0x00040001}, {0xBB, 0x00000400},
264028fa281SKalle Valo 	{0xBF, 0x000C0000}, {0xC2, 0x00002400},
265028fa281SKalle Valo 	{0xC3, 0x00000009}, {0xC4, 0x00040C91},
266028fa281SKalle Valo 	{0xC5, 0x00099999}, {0xC6, 0x000000A3},
267028fa281SKalle Valo 	{0xC7, 0x0008F820}, {0xC8, 0x00076C06},
268028fa281SKalle Valo 	{0xC9, 0x00000000}, {0xCA, 0x00080000},
269028fa281SKalle Valo 	{0xDF, 0x00000180}, {0xEF, 0x000001A0},
270028fa281SKalle Valo 	{0x51, 0x000E8231}, {0x52, 0x000FAC2C},
271028fa281SKalle Valo 	{0x53, 0x00000141}, {0x56, 0x000517F0},
272028fa281SKalle Valo 	{0x35, 0x00000090}, {0x35, 0x00000190},
273028fa281SKalle Valo 	{0x35, 0x00000290}, {0x36, 0x00001064},
274028fa281SKalle Valo 	{0x36, 0x00009064}, {0x36, 0x00011064},
275028fa281SKalle Valo 	{0x36, 0x00019064}, {0x18, 0x00000C07},
276028fa281SKalle Valo 	{0x5A, 0x00048000}, {0x19, 0x000739D0},
277028fa281SKalle Valo 	{0x34, 0x0000ADD2}, {0x34, 0x00009DD0},
278028fa281SKalle Valo 	{0x34, 0x00008CF3}, {0x34, 0x00007CF0},
279028fa281SKalle Valo 	{0x34, 0x00006CED}, {0x34, 0x00005CD2},
280028fa281SKalle Valo 	{0x34, 0x00004CCF}, {0x34, 0x00003CCC},
281028fa281SKalle Valo 	{0x34, 0x00002CC9}, {0x34, 0x00001C4C},
282028fa281SKalle Valo 	{0x34, 0x00000C49},
283028fa281SKalle Valo 	{0x00, 0x00030159}, {0x84, 0x00048000},
284028fa281SKalle Valo 	{0x86, 0x0000002A}, {0x87, 0x00000025},
285028fa281SKalle Valo 	{0x8E, 0x00065540}, {0x8F, 0x00088000},
286028fa281SKalle Valo 	{0xEF, 0x000020A0}, {0x3B, 0x000F0F00},
287028fa281SKalle Valo 	{0x3B, 0x000E0B00}, {0x3B, 0x000D0900},
288028fa281SKalle Valo 	{0x3B, 0x000C0700}, {0x3B, 0x000B0600},
289028fa281SKalle Valo 	{0x3B, 0x000A0400}, {0x3B, 0x00090200},
290028fa281SKalle Valo 	{0x3B, 0x00080000}, {0x3B, 0x0007BF00},
291028fa281SKalle Valo 	{0x3B, 0x00060B00}, {0x3B, 0x0005C900},
292028fa281SKalle Valo 	{0x3B, 0x00040700}, {0x3B, 0x00030600},
293028fa281SKalle Valo 	{0x3B, 0x0002D500}, {0x3B, 0x00010200},
294028fa281SKalle Valo 	{0x3B, 0x0000E000}, {0xEF, 0x000000A0},
295028fa281SKalle Valo 	{0xEF, 0x00000010}, {0x3B, 0x0000C0A8},
296028fa281SKalle Valo 	{0x3B, 0x00010400}, {0xEF, 0x00000000},
297028fa281SKalle Valo 	{0xEF, 0x00080000}, {0x30, 0x00010000},
298028fa281SKalle Valo 	{0x31, 0x0000000F}, {0x32, 0x00007EFE},
299028fa281SKalle Valo 	{0xEF, 0x00000000}, {0x00, 0x00010159},
300028fa281SKalle Valo 	{0x18, 0x0000FC07}, {0xFE, 0x00000000},
301028fa281SKalle Valo 	{0xFE, 0x00000000}, {0x1F, 0x00080003},
302028fa281SKalle Valo 	{0xFE, 0x00000000}, {0xFE, 0x00000000},
303028fa281SKalle Valo 	{0x1E, 0x00000001}, {0x1F, 0x00080000},
304028fa281SKalle Valo 	{0x00, 0x00033D95},
305028fa281SKalle Valo 	{0xff, 0xffffffff}
306028fa281SKalle Valo };
307028fa281SKalle Valo 
rtl8188fu_identify_chip(struct rtl8xxxu_priv * priv)308028fa281SKalle Valo static int rtl8188fu_identify_chip(struct rtl8xxxu_priv *priv)
309028fa281SKalle Valo {
310028fa281SKalle Valo 	struct device *dev = &priv->udev->dev;
311028fa281SKalle Valo 	u32 sys_cfg, vendor;
312028fa281SKalle Valo 	int ret = 0;
313028fa281SKalle Valo 
314028fa281SKalle Valo 	strscpy(priv->chip_name, "8188FU", sizeof(priv->chip_name));
315028fa281SKalle Valo 	priv->rtl_chip = RTL8188F;
316028fa281SKalle Valo 	priv->rf_paths = 1;
317028fa281SKalle Valo 	priv->rx_paths = 1;
318028fa281SKalle Valo 	priv->tx_paths = 1;
319028fa281SKalle Valo 	priv->has_wifi = 1;
320028fa281SKalle Valo 
321028fa281SKalle Valo 	sys_cfg = rtl8xxxu_read32(priv, REG_SYS_CFG);
322028fa281SKalle Valo 	priv->chip_cut = u32_get_bits(sys_cfg, SYS_CFG_CHIP_VERSION_MASK);
323028fa281SKalle Valo 	if (sys_cfg & SYS_CFG_TRP_VAUX_EN) {
324028fa281SKalle Valo 		dev_info(dev, "Unsupported test chip\n");
325028fa281SKalle Valo 		ret = -ENOTSUPP;
326028fa281SKalle Valo 		goto out;
327028fa281SKalle Valo 	}
328028fa281SKalle Valo 
329028fa281SKalle Valo 	vendor = sys_cfg & SYS_CFG_VENDOR_EXT_MASK;
330028fa281SKalle Valo 	rtl8xxxu_identify_vendor_2bits(priv, vendor);
331028fa281SKalle Valo 
332028fa281SKalle Valo 	ret = rtl8xxxu_config_endpoints_no_sie(priv);
333028fa281SKalle Valo 
334028fa281SKalle Valo out:
335028fa281SKalle Valo 	return ret;
336028fa281SKalle Valo }
337028fa281SKalle Valo 
rtl8188f_channel_to_group(int channel,int * group,int * cck_group)338028fa281SKalle Valo void rtl8188f_channel_to_group(int channel, int *group, int *cck_group)
339028fa281SKalle Valo {
340028fa281SKalle Valo 	if (channel < 3)
341028fa281SKalle Valo 		*group = 0;
342028fa281SKalle Valo 	else if (channel < 6)
343028fa281SKalle Valo 		*group = 1;
344028fa281SKalle Valo 	else if (channel < 9)
345028fa281SKalle Valo 		*group = 2;
346028fa281SKalle Valo 	else if (channel < 12)
347028fa281SKalle Valo 		*group = 3;
348028fa281SKalle Valo 	else
349028fa281SKalle Valo 		*group = 4;
350028fa281SKalle Valo 
351028fa281SKalle Valo 	if (channel == 14)
352028fa281SKalle Valo 		*cck_group = 5;
353028fa281SKalle Valo 	else
354028fa281SKalle Valo 		*cck_group = *group;
355028fa281SKalle Valo }
356028fa281SKalle Valo 
357028fa281SKalle Valo void
rtl8188f_set_tx_power(struct rtl8xxxu_priv * priv,int channel,bool ht40)358028fa281SKalle Valo rtl8188f_set_tx_power(struct rtl8xxxu_priv *priv, int channel, bool ht40)
359028fa281SKalle Valo {
360028fa281SKalle Valo 	u32 val32, ofdm, mcs;
361028fa281SKalle Valo 	u8 cck, ofdmbase, mcsbase;
362028fa281SKalle Valo 	int group, cck_group;
363028fa281SKalle Valo 
364028fa281SKalle Valo 	rtl8188f_channel_to_group(channel, &group, &cck_group);
365028fa281SKalle Valo 
366028fa281SKalle Valo 	cck = priv->cck_tx_power_index_A[cck_group];
367028fa281SKalle Valo 
368028fa281SKalle Valo 	val32 = rtl8xxxu_read32(priv, REG_TX_AGC_A_CCK1_MCS32);
369028fa281SKalle Valo 	val32 &= 0xffff00ff;
370028fa281SKalle Valo 	val32 |= (cck << 8);
371028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_TX_AGC_A_CCK1_MCS32, val32);
372028fa281SKalle Valo 
373028fa281SKalle Valo 	val32 = rtl8xxxu_read32(priv, REG_TX_AGC_B_CCK11_A_CCK2_11);
374028fa281SKalle Valo 	val32 &= 0xff;
375028fa281SKalle Valo 	val32 |= ((cck << 8) | (cck << 16) | (cck << 24));
376028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_TX_AGC_B_CCK11_A_CCK2_11, val32);
377028fa281SKalle Valo 
378028fa281SKalle Valo 	ofdmbase = priv->ht40_1s_tx_power_index_A[group];
379028fa281SKalle Valo 	ofdmbase += priv->ofdm_tx_power_diff[0].a;
380028fa281SKalle Valo 	ofdm = ofdmbase | ofdmbase << 8 | ofdmbase << 16 | ofdmbase << 24;
381028fa281SKalle Valo 
382028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_TX_AGC_A_RATE18_06, ofdm);
383028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_TX_AGC_A_RATE54_24, ofdm);
384028fa281SKalle Valo 
385028fa281SKalle Valo 	mcsbase = priv->ht40_1s_tx_power_index_A[group];
386028fa281SKalle Valo 	if (ht40)
387028fa281SKalle Valo 		/* This diff is always 0 - not used in 8188FU. */
388028fa281SKalle Valo 		mcsbase += priv->ht40_tx_power_diff[0].a;
389028fa281SKalle Valo 	else
390028fa281SKalle Valo 		mcsbase += priv->ht20_tx_power_diff[0].a;
391028fa281SKalle Valo 	mcs = mcsbase | mcsbase << 8 | mcsbase << 16 | mcsbase << 24;
392028fa281SKalle Valo 
393028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_TX_AGC_A_MCS03_MCS00, mcs);
394028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_TX_AGC_A_MCS07_MCS04, mcs);
395028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_TX_AGC_A_MCS11_MCS08, mcs);
396028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_TX_AGC_A_MCS15_MCS12, mcs);
397028fa281SKalle Valo }
398028fa281SKalle Valo 
399028fa281SKalle Valo /* A workaround to eliminate the 2400MHz, 2440MHz, 2480MHz spur of 8188F. */
rtl8188f_spur_calibration(struct rtl8xxxu_priv * priv,u8 channel)400028fa281SKalle Valo static void rtl8188f_spur_calibration(struct rtl8xxxu_priv *priv, u8 channel)
401028fa281SKalle Valo {
402028fa281SKalle Valo 	static const u32 frequencies[14 + 1] = {
403028fa281SKalle Valo 		[5] = 0xFCCD,
404028fa281SKalle Valo 		[6] = 0xFC4D,
405028fa281SKalle Valo 		[7] = 0xFFCD,
406028fa281SKalle Valo 		[8] = 0xFF4D,
407028fa281SKalle Valo 		[11] = 0xFDCD,
408028fa281SKalle Valo 		[13] = 0xFCCD,
409028fa281SKalle Valo 		[14] = 0xFF9A
410028fa281SKalle Valo 	};
411028fa281SKalle Valo 
412028fa281SKalle Valo 	static const u32 reg_d40[14 + 1] = {
413028fa281SKalle Valo 		[5] = 0x06000000,
414028fa281SKalle Valo 		[6] = 0x00000600,
415028fa281SKalle Valo 		[13] = 0x06000000
416028fa281SKalle Valo 	};
417028fa281SKalle Valo 
418028fa281SKalle Valo 	static const u32 reg_d44[14 + 1] = {
419028fa281SKalle Valo 		[11] = 0x04000000
420028fa281SKalle Valo 	};
421028fa281SKalle Valo 
422028fa281SKalle Valo 	static const u32 reg_d4c[14 + 1] = {
423028fa281SKalle Valo 		[7] = 0x06000000,
424028fa281SKalle Valo 		[8] = 0x00000380,
425028fa281SKalle Valo 		[14] = 0x00180000
426028fa281SKalle Valo 	};
427028fa281SKalle Valo 
428028fa281SKalle Valo 	const u8 threshold = 0x16;
429028fa281SKalle Valo 	bool do_notch, hw_ctrl, sw_ctrl, hw_ctrl_s1 = 0, sw_ctrl_s1 = 0;
430028fa281SKalle Valo 	u32 val32, initial_gain, reg948;
431028fa281SKalle Valo 
432028fa281SKalle Valo 	val32 = rtl8xxxu_read32(priv, REG_OFDM0_RX_D_SYNC_PATH);
433028fa281SKalle Valo 	val32 |= GENMASK(28, 24);
434028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_OFDM0_RX_D_SYNC_PATH, val32);
435028fa281SKalle Valo 
436028fa281SKalle Valo 	/* enable notch filter */
437028fa281SKalle Valo 	val32 = rtl8xxxu_read32(priv, REG_OFDM0_RX_D_SYNC_PATH);
438028fa281SKalle Valo 	val32 |= BIT(9);
439028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_OFDM0_RX_D_SYNC_PATH, val32);
440028fa281SKalle Valo 
441028fa281SKalle Valo 	if (channel <= 14 && frequencies[channel] > 0) {
442028fa281SKalle Valo 		reg948 = rtl8xxxu_read32(priv, REG_S0S1_PATH_SWITCH);
443028fa281SKalle Valo 		hw_ctrl = reg948 & BIT(6);
444028fa281SKalle Valo 		sw_ctrl = !hw_ctrl;
445028fa281SKalle Valo 
446028fa281SKalle Valo 		if (hw_ctrl) {
447028fa281SKalle Valo 			val32 = rtl8xxxu_read32(priv, REG_FPGA0_XB_RF_INT_OE);
448028fa281SKalle Valo 			val32 &= GENMASK(5, 3);
449028fa281SKalle Valo 			hw_ctrl_s1 = val32 == BIT(3);
450028fa281SKalle Valo 		} else if (sw_ctrl) {
451028fa281SKalle Valo 			sw_ctrl_s1 = !(reg948 & BIT(9));
452028fa281SKalle Valo 		}
453028fa281SKalle Valo 
454028fa281SKalle Valo 		if (hw_ctrl_s1 || sw_ctrl_s1) {
455028fa281SKalle Valo 			initial_gain = rtl8xxxu_read32(priv, REG_OFDM0_XA_AGC_CORE1);
456028fa281SKalle Valo 
457028fa281SKalle Valo 			/* Disable CCK block */
458028fa281SKalle Valo 			val32 = rtl8xxxu_read32(priv, REG_FPGA0_RF_MODE);
459028fa281SKalle Valo 			val32 &= ~FPGA_RF_MODE_CCK;
460028fa281SKalle Valo 			rtl8xxxu_write32(priv, REG_FPGA0_RF_MODE, val32);
461028fa281SKalle Valo 
462028fa281SKalle Valo 			val32 = initial_gain & ~OFDM0_X_AGC_CORE1_IGI_MASK;
463028fa281SKalle Valo 			val32 |= 0x30;
464028fa281SKalle Valo 			rtl8xxxu_write32(priv, REG_OFDM0_XA_AGC_CORE1, val32);
465028fa281SKalle Valo 
466028fa281SKalle Valo 			/* disable 3-wire */
467028fa281SKalle Valo 			rtl8xxxu_write32(priv, REG_FPGA0_ANALOG4, 0xccf000c0);
468028fa281SKalle Valo 
469028fa281SKalle Valo 			/* Setup PSD */
470028fa281SKalle Valo 			rtl8xxxu_write32(priv, REG_FPGA0_PSD_FUNC, frequencies[channel]);
471028fa281SKalle Valo 
472028fa281SKalle Valo 			/* Start PSD */
473028fa281SKalle Valo 			rtl8xxxu_write32(priv, REG_FPGA0_PSD_FUNC, 0x400000 | frequencies[channel]);
474028fa281SKalle Valo 
475028fa281SKalle Valo 			msleep(30);
476028fa281SKalle Valo 
477028fa281SKalle Valo 			do_notch = rtl8xxxu_read32(priv, REG_FPGA0_PSD_REPORT) >= threshold;
478028fa281SKalle Valo 
479028fa281SKalle Valo 			/* turn off PSD */
480028fa281SKalle Valo 			rtl8xxxu_write32(priv, REG_FPGA0_PSD_FUNC, frequencies[channel]);
481028fa281SKalle Valo 
482028fa281SKalle Valo 			/* enable 3-wire */
483028fa281SKalle Valo 			rtl8xxxu_write32(priv, REG_FPGA0_ANALOG4, 0xccc000c0);
484028fa281SKalle Valo 
485028fa281SKalle Valo 			/* Enable CCK block */
486028fa281SKalle Valo 			val32 = rtl8xxxu_read32(priv, REG_FPGA0_RF_MODE);
487028fa281SKalle Valo 			val32 |= FPGA_RF_MODE_CCK;
488028fa281SKalle Valo 			rtl8xxxu_write32(priv, REG_FPGA0_RF_MODE, val32);
489028fa281SKalle Valo 
490028fa281SKalle Valo 			rtl8xxxu_write32(priv, REG_OFDM0_XA_AGC_CORE1, initial_gain);
491028fa281SKalle Valo 
492028fa281SKalle Valo 			if (do_notch) {
493028fa281SKalle Valo 				rtl8xxxu_write32(priv, REG_OFDM1_CSI_FIX_MASK1, reg_d40[channel]);
494028fa281SKalle Valo 				rtl8xxxu_write32(priv, REG_OFDM1_CSI_FIX_MASK2, reg_d44[channel]);
495028fa281SKalle Valo 				rtl8xxxu_write32(priv, 0xd48, 0x0);
496028fa281SKalle Valo 				rtl8xxxu_write32(priv, 0xd4c, reg_d4c[channel]);
497028fa281SKalle Valo 
498028fa281SKalle Valo 				/* enable CSI mask */
499028fa281SKalle Valo 				val32 = rtl8xxxu_read32(priv, REG_OFDM1_CFO_TRACKING);
500028fa281SKalle Valo 				val32 |= BIT(28);
501028fa281SKalle Valo 				rtl8xxxu_write32(priv, REG_OFDM1_CFO_TRACKING, val32);
502028fa281SKalle Valo 
503028fa281SKalle Valo 				return;
504028fa281SKalle Valo 			}
505028fa281SKalle Valo 		}
506028fa281SKalle Valo 	}
507028fa281SKalle Valo 
508028fa281SKalle Valo 	/* disable CSI mask function */
509028fa281SKalle Valo 	val32 = rtl8xxxu_read32(priv, REG_OFDM1_CFO_TRACKING);
510028fa281SKalle Valo 	val32 &= ~BIT(28);
511028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_OFDM1_CFO_TRACKING, val32);
512028fa281SKalle Valo }
513028fa281SKalle Valo 
rtl8188fu_config_channel(struct ieee80211_hw * hw)514028fa281SKalle Valo static void rtl8188fu_config_channel(struct ieee80211_hw *hw)
515028fa281SKalle Valo {
516028fa281SKalle Valo 	struct rtl8xxxu_priv *priv = hw->priv;
517028fa281SKalle Valo 	u32 val32;
518028fa281SKalle Valo 	u8 channel, subchannel;
519028fa281SKalle Valo 	bool sec_ch_above;
520028fa281SKalle Valo 
521028fa281SKalle Valo 	channel = (u8)hw->conf.chandef.chan->hw_value;
522028fa281SKalle Valo 
523028fa281SKalle Valo 	/* Set channel */
524028fa281SKalle Valo 	val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_MODE_AG);
525028fa281SKalle Valo 	val32 &= ~MODE_AG_CHANNEL_MASK;
526028fa281SKalle Valo 	val32 |= channel;
527028fa281SKalle Valo 	rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_MODE_AG, val32);
528028fa281SKalle Valo 
529028fa281SKalle Valo 	/* Spur calibration */
530028fa281SKalle Valo 	rtl8188f_spur_calibration(priv, channel);
531028fa281SKalle Valo 
532028fa281SKalle Valo 	/* Set bandwidth mode */
533028fa281SKalle Valo 	val32 = rtl8xxxu_read32(priv, REG_FPGA0_RF_MODE);
534028fa281SKalle Valo 	val32 &= ~FPGA_RF_MODE;
535028fa281SKalle Valo 	val32 |= hw->conf.chandef.width == NL80211_CHAN_WIDTH_40;
536028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_FPGA0_RF_MODE, val32);
537028fa281SKalle Valo 
538028fa281SKalle Valo 	val32 = rtl8xxxu_read32(priv, REG_FPGA1_RF_MODE);
539028fa281SKalle Valo 	val32 &= ~FPGA_RF_MODE;
540028fa281SKalle Valo 	val32 |= hw->conf.chandef.width == NL80211_CHAN_WIDTH_40;
541028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_FPGA1_RF_MODE, val32);
542028fa281SKalle Valo 
543028fa281SKalle Valo 	/* RXADC CLK */
544028fa281SKalle Valo 	val32 = rtl8xxxu_read32(priv, REG_FPGA0_RF_MODE);
545028fa281SKalle Valo 	val32 |= GENMASK(10, 8);
546028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_FPGA0_RF_MODE, val32);
547028fa281SKalle Valo 
548028fa281SKalle Valo 	/* TXDAC CLK */
549028fa281SKalle Valo 	val32 = rtl8xxxu_read32(priv, REG_FPGA0_RF_MODE);
550028fa281SKalle Valo 	val32 |= BIT(14) | BIT(12);
551028fa281SKalle Valo 	val32 &= ~BIT(13);
552028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_FPGA0_RF_MODE, val32);
553028fa281SKalle Valo 
554028fa281SKalle Valo 	/* small BW */
555028fa281SKalle Valo 	val32 = rtl8xxxu_read32(priv, REG_OFDM0_TX_PSDO_NOISE_WEIGHT);
556028fa281SKalle Valo 	val32 &= ~GENMASK(31, 30);
557028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_OFDM0_TX_PSDO_NOISE_WEIGHT, val32);
558028fa281SKalle Valo 
559028fa281SKalle Valo 	/* adc buffer clk */
560028fa281SKalle Valo 	val32 = rtl8xxxu_read32(priv, REG_OFDM0_TX_PSDO_NOISE_WEIGHT);
561028fa281SKalle Valo 	val32 &= ~BIT(29);
562028fa281SKalle Valo 	val32 |= BIT(28);
563028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_OFDM0_TX_PSDO_NOISE_WEIGHT, val32);
564028fa281SKalle Valo 
565028fa281SKalle Valo 	/* adc buffer clk */
566028fa281SKalle Valo 	val32 = rtl8xxxu_read32(priv, REG_OFDM0_XA_RX_AFE);
567028fa281SKalle Valo 	val32 &= ~BIT(29);
568028fa281SKalle Valo 	val32 |= BIT(28);
569028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_OFDM0_XA_RX_AFE, val32);
570028fa281SKalle Valo 
571028fa281SKalle Valo 	val32 = rtl8xxxu_read32(priv, REG_OFDM_RX_DFIR);
572028fa281SKalle Valo 	val32 &= ~BIT(19);
573028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_OFDM_RX_DFIR, val32);
574028fa281SKalle Valo 
575028fa281SKalle Valo 	val32 = rtl8xxxu_read32(priv, REG_OFDM_RX_DFIR);
576028fa281SKalle Valo 	val32 &= ~GENMASK(23, 20);
577028fa281SKalle Valo 	val32 |= BIT(21);
578028fa281SKalle Valo 	if (hw->conf.chandef.width == NL80211_CHAN_WIDTH_20 ||
579028fa281SKalle Valo 	    hw->conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT)
580028fa281SKalle Valo 		val32 |= BIT(20);
581028fa281SKalle Valo 	else if (hw->conf.chandef.width == NL80211_CHAN_WIDTH_40)
582028fa281SKalle Valo 		val32 |= BIT(22);
583028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_OFDM_RX_DFIR, val32);
584028fa281SKalle Valo 
585028fa281SKalle Valo 	if (hw->conf.chandef.width == NL80211_CHAN_WIDTH_40) {
586028fa281SKalle Valo 		if (hw->conf.chandef.center_freq1 >
587028fa281SKalle Valo 		    hw->conf.chandef.chan->center_freq) {
588028fa281SKalle Valo 			sec_ch_above = 1;
589028fa281SKalle Valo 			channel += 2;
590028fa281SKalle Valo 		} else {
591028fa281SKalle Valo 			sec_ch_above = 0;
592028fa281SKalle Valo 			channel -= 2;
593028fa281SKalle Valo 		}
594028fa281SKalle Valo 
595028fa281SKalle Valo 		/* Set Control channel to upper or lower. */
596028fa281SKalle Valo 		val32 = rtl8xxxu_read32(priv, REG_CCK0_SYSTEM);
597028fa281SKalle Valo 		val32 &= ~CCK0_SIDEBAND;
598028fa281SKalle Valo 		if (!sec_ch_above)
599028fa281SKalle Valo 			val32 |= CCK0_SIDEBAND;
600028fa281SKalle Valo 		rtl8xxxu_write32(priv, REG_CCK0_SYSTEM, val32);
601028fa281SKalle Valo 
602028fa281SKalle Valo 		val32 = rtl8xxxu_read32(priv, REG_DATA_SUBCHANNEL);
603028fa281SKalle Valo 		val32 &= ~GENMASK(3, 0);
604028fa281SKalle Valo 		if (sec_ch_above)
605028fa281SKalle Valo 			subchannel = 2;
606028fa281SKalle Valo 		else
607028fa281SKalle Valo 			subchannel = 1;
608028fa281SKalle Valo 		val32 |= subchannel;
609028fa281SKalle Valo 		rtl8xxxu_write32(priv, REG_DATA_SUBCHANNEL, val32);
610028fa281SKalle Valo 
611028fa281SKalle Valo 		val32 = rtl8xxxu_read32(priv, REG_RESPONSE_RATE_SET);
612028fa281SKalle Valo 		val32 &= ~RSR_RSC_BANDWIDTH_40M;
613028fa281SKalle Valo 		rtl8xxxu_write32(priv, REG_RESPONSE_RATE_SET, val32);
614028fa281SKalle Valo 	}
615028fa281SKalle Valo 
616028fa281SKalle Valo 	/* RF TRX_BW */
617028fa281SKalle Valo 	val32 = channel;
618028fa281SKalle Valo 	if (hw->conf.chandef.width == NL80211_CHAN_WIDTH_20 ||
619028fa281SKalle Valo 	    hw->conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT)
620028fa281SKalle Valo 		val32 |= MODE_AG_BW_20MHZ_8723B;
621028fa281SKalle Valo 	else if (hw->conf.chandef.width == NL80211_CHAN_WIDTH_40)
622028fa281SKalle Valo 		val32 |= MODE_AG_BW_40MHZ_8723B;
623028fa281SKalle Valo 	rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_MODE_AG, val32);
624028fa281SKalle Valo 
625028fa281SKalle Valo 	/* FILTER BW&RC Corner (ACPR) */
626028fa281SKalle Valo 	if (hw->conf.chandef.width == NL80211_CHAN_WIDTH_20 ||
627028fa281SKalle Valo 	    hw->conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT)
628028fa281SKalle Valo 		val32 = 0x00065;
629028fa281SKalle Valo 	else if (hw->conf.chandef.width == NL80211_CHAN_WIDTH_40)
630028fa281SKalle Valo 		val32 = 0x00025;
631028fa281SKalle Valo 	rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_RXG_MIX_SWBW, val32);
632028fa281SKalle Valo 
633028fa281SKalle Valo 	if (hw->conf.chandef.width == NL80211_CHAN_WIDTH_20 ||
634028fa281SKalle Valo 	    hw->conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT)
635028fa281SKalle Valo 		val32 = 0x0;
636028fa281SKalle Valo 	else if (hw->conf.chandef.width == NL80211_CHAN_WIDTH_40)
637028fa281SKalle Valo 		val32 = 0x01000;
638028fa281SKalle Valo 	rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_RX_BB2, val32);
639028fa281SKalle Valo 
640028fa281SKalle Valo 	/* RC Corner */
641028fa281SKalle Valo 	rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x00140);
642028fa281SKalle Valo 	rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_RX_G2, 0x01c6c);
643028fa281SKalle Valo }
644028fa281SKalle Valo 
rtl8188fu_init_aggregation(struct rtl8xxxu_priv * priv)645028fa281SKalle Valo static void rtl8188fu_init_aggregation(struct rtl8xxxu_priv *priv)
646028fa281SKalle Valo {
647028fa281SKalle Valo 	u8 agg_ctrl, rxdma_mode, usb_tx_agg_desc_num = 6;
648028fa281SKalle Valo 	u32 agg_rx, val32;
649028fa281SKalle Valo 
650028fa281SKalle Valo 	/* TX aggregation */
651028fa281SKalle Valo 	val32 = rtl8xxxu_read32(priv, REG_DWBCN0_CTRL_8188F);
652028fa281SKalle Valo 	val32 &= ~(0xf << 4);
653028fa281SKalle Valo 	val32 |= usb_tx_agg_desc_num << 4;
654028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_DWBCN0_CTRL_8188F, val32);
655028fa281SKalle Valo 	rtl8xxxu_write8(priv, REG_DWBCN1_CTRL_8723B, usb_tx_agg_desc_num << 1);
656028fa281SKalle Valo 
657028fa281SKalle Valo 	/* RX aggregation */
658028fa281SKalle Valo 	agg_ctrl = rtl8xxxu_read8(priv, REG_TRXDMA_CTRL);
659028fa281SKalle Valo 	agg_ctrl &= ~TRXDMA_CTRL_RXDMA_AGG_EN;
660028fa281SKalle Valo 
661028fa281SKalle Valo 	agg_rx = rtl8xxxu_read32(priv, REG_RXDMA_AGG_PG_TH);
662028fa281SKalle Valo 	agg_rx &= ~RXDMA_USB_AGG_ENABLE;
663028fa281SKalle Valo 	agg_rx &= ~0xFF0F; /* reset agg size and timeout */
664028fa281SKalle Valo 
665028fa281SKalle Valo 	rxdma_mode = rtl8xxxu_read8(priv, REG_RXDMA_PRO_8723B);
666028fa281SKalle Valo 	rxdma_mode &= ~BIT(1);
667028fa281SKalle Valo 
668028fa281SKalle Valo 	rtl8xxxu_write8(priv, REG_TRXDMA_CTRL, agg_ctrl);
669028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_RXDMA_AGG_PG_TH, agg_rx);
670028fa281SKalle Valo 	rtl8xxxu_write8(priv, REG_RXDMA_PRO_8723B, rxdma_mode);
671028fa281SKalle Valo }
672028fa281SKalle Valo 
rtl8188fu_init_statistics(struct rtl8xxxu_priv * priv)673028fa281SKalle Valo static void rtl8188fu_init_statistics(struct rtl8xxxu_priv *priv)
674028fa281SKalle Valo {
675028fa281SKalle Valo 	u32 val32;
676028fa281SKalle Valo 
677028fa281SKalle Valo 	/* Time duration for NHM unit: 4us, 0xc350=200ms */
678028fa281SKalle Valo 	rtl8xxxu_write16(priv, REG_NHM_TIMER_8723B + 2, 0xc350);
679028fa281SKalle Valo 	rtl8xxxu_write16(priv, REG_NHM_TH9_TH10_8723B + 2, 0xffff);
680028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_NHM_TH3_TO_TH0_8723B, 0xffffff50);
681028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_NHM_TH7_TO_TH4_8723B, 0xffffffff);
682028fa281SKalle Valo 
683028fa281SKalle Valo 	/* TH8 */
684028fa281SKalle Valo 	val32 = rtl8xxxu_read32(priv, REG_FPGA0_IQK);
685028fa281SKalle Valo 	val32 |= 0xff;
686028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_FPGA0_IQK, val32);
687028fa281SKalle Valo 
688028fa281SKalle Valo 	/* Enable CCK */
689028fa281SKalle Valo 	val32 = rtl8xxxu_read32(priv, REG_NHM_TH9_TH10_8723B);
690028fa281SKalle Valo 	val32 &= ~(BIT(8) | BIT(9) | BIT(10));
691028fa281SKalle Valo 	val32 |= BIT(8);
692028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_NHM_TH9_TH10_8723B, val32);
693028fa281SKalle Valo 
694028fa281SKalle Valo 	/* Max power amongst all RX antennas */
695028fa281SKalle Valo 	val32 = rtl8xxxu_read32(priv, REG_OFDM0_FA_RSTC);
696028fa281SKalle Valo 	val32 |= BIT(7);
697028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_OFDM0_FA_RSTC, val32);
698028fa281SKalle Valo }
699028fa281SKalle Valo 
700*d0b4b8efSMartin Kaistra #define TX_POWER_INDEX_MAX 0x3F
701*d0b4b8efSMartin Kaistra #define TX_POWER_INDEX_DEFAULT_CCK 0x22
702*d0b4b8efSMartin Kaistra #define TX_POWER_INDEX_DEFAULT_HT40 0x27
703*d0b4b8efSMartin Kaistra 
rtl8188fu_parse_efuse(struct rtl8xxxu_priv * priv)704028fa281SKalle Valo static int rtl8188fu_parse_efuse(struct rtl8xxxu_priv *priv)
705028fa281SKalle Valo {
706028fa281SKalle Valo 	struct rtl8188fu_efuse *efuse = &priv->efuse_wifi.efuse8188fu;
707*d0b4b8efSMartin Kaistra 	int i;
708028fa281SKalle Valo 
709028fa281SKalle Valo 	if (efuse->rtl_id != cpu_to_le16(0x8129))
710028fa281SKalle Valo 		return -EINVAL;
711028fa281SKalle Valo 
712028fa281SKalle Valo 	ether_addr_copy(priv->mac_addr, efuse->mac_addr);
713028fa281SKalle Valo 
714028fa281SKalle Valo 	memcpy(priv->cck_tx_power_index_A, efuse->tx_power_index_A.cck_base,
715028fa281SKalle Valo 	       sizeof(efuse->tx_power_index_A.cck_base));
716028fa281SKalle Valo 
717028fa281SKalle Valo 	memcpy(priv->ht40_1s_tx_power_index_A,
718028fa281SKalle Valo 	       efuse->tx_power_index_A.ht40_base,
719028fa281SKalle Valo 	       sizeof(efuse->tx_power_index_A.ht40_base));
720028fa281SKalle Valo 
721*d0b4b8efSMartin Kaistra 	for (i = 0; i < ARRAY_SIZE(priv->cck_tx_power_index_A); i++) {
722*d0b4b8efSMartin Kaistra 		if (priv->cck_tx_power_index_A[i] > TX_POWER_INDEX_MAX)
723*d0b4b8efSMartin Kaistra 			priv->cck_tx_power_index_A[i] = TX_POWER_INDEX_DEFAULT_CCK;
724*d0b4b8efSMartin Kaistra 	}
725*d0b4b8efSMartin Kaistra 
726*d0b4b8efSMartin Kaistra 	for (i = 0; i < ARRAY_SIZE(priv->ht40_1s_tx_power_index_A); i++) {
727*d0b4b8efSMartin Kaistra 		if (priv->ht40_1s_tx_power_index_A[i] > TX_POWER_INDEX_MAX)
728*d0b4b8efSMartin Kaistra 			priv->ht40_1s_tx_power_index_A[i] = TX_POWER_INDEX_DEFAULT_HT40;
729*d0b4b8efSMartin Kaistra 	}
730*d0b4b8efSMartin Kaistra 
731028fa281SKalle Valo 	priv->ofdm_tx_power_diff[0].a = efuse->tx_power_index_A.ht20_ofdm_1s_diff.a;
732028fa281SKalle Valo 	priv->ht20_tx_power_diff[0].a = efuse->tx_power_index_A.ht20_ofdm_1s_diff.b;
733028fa281SKalle Valo 
734028fa281SKalle Valo 	priv->default_crystal_cap = efuse->xtal_k & 0x3f;
735028fa281SKalle Valo 
736028fa281SKalle Valo 	return 0;
737028fa281SKalle Valo }
738028fa281SKalle Valo 
rtl8188fu_load_firmware(struct rtl8xxxu_priv * priv)739028fa281SKalle Valo static int rtl8188fu_load_firmware(struct rtl8xxxu_priv *priv)
740028fa281SKalle Valo {
741028fa281SKalle Valo 	const char *fw_name;
742028fa281SKalle Valo 	int ret;
743028fa281SKalle Valo 
744028fa281SKalle Valo 	fw_name = "rtlwifi/rtl8188fufw.bin";
745028fa281SKalle Valo 
746028fa281SKalle Valo 	ret = rtl8xxxu_load_firmware(priv, fw_name);
747028fa281SKalle Valo 
748028fa281SKalle Valo 	return ret;
749028fa281SKalle Valo }
750028fa281SKalle Valo 
rtl8188fu_init_phy_bb(struct rtl8xxxu_priv * priv)751028fa281SKalle Valo static void rtl8188fu_init_phy_bb(struct rtl8xxxu_priv *priv)
752028fa281SKalle Valo {
753028fa281SKalle Valo 	u8 val8;
754028fa281SKalle Valo 	u16 val16;
755028fa281SKalle Valo 
756028fa281SKalle Valo 	/* Enable BB and RF */
757028fa281SKalle Valo 	val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC);
758028fa281SKalle Valo 	val16 |= SYS_FUNC_BB_GLB_RSTN | SYS_FUNC_BBRSTB | SYS_FUNC_DIO_RF;
759028fa281SKalle Valo 	rtl8xxxu_write16(priv, REG_SYS_FUNC, val16);
760028fa281SKalle Valo 
761028fa281SKalle Valo 	/*
762028fa281SKalle Valo 	 * Per vendor driver, run power sequence before init of RF
763028fa281SKalle Valo 	 */
764028fa281SKalle Valo 	val8 = RF_ENABLE | RF_RSTB | RF_SDMRSTB;
765028fa281SKalle Valo 	rtl8xxxu_write8(priv, REG_RF_CTRL, val8);
766028fa281SKalle Valo 
767028fa281SKalle Valo 	usleep_range(10, 20);
768028fa281SKalle Valo 
769028fa281SKalle Valo 	rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_IQADJ_G1, 0x780);
770028fa281SKalle Valo 
771028fa281SKalle Valo 	val8 = SYS_FUNC_BB_GLB_RSTN | SYS_FUNC_BBRSTB | SYS_FUNC_USBA | SYS_FUNC_USBD;
772028fa281SKalle Valo 	rtl8xxxu_write8(priv, REG_SYS_FUNC, val8);
773028fa281SKalle Valo 
774028fa281SKalle Valo 	rtl8xxxu_init_phy_regs(priv, rtl8188fu_phy_init_table);
775028fa281SKalle Valo 	rtl8xxxu_init_phy_regs(priv, rtl8188f_agc_table);
776028fa281SKalle Valo }
777028fa281SKalle Valo 
rtl8188fu_init_phy_rf(struct rtl8xxxu_priv * priv)778028fa281SKalle Valo static int rtl8188fu_init_phy_rf(struct rtl8xxxu_priv *priv)
779028fa281SKalle Valo {
780028fa281SKalle Valo 	int ret;
781028fa281SKalle Valo 
782028fa281SKalle Valo 	if (priv->chip_cut == 1)
783028fa281SKalle Valo 		ret = rtl8xxxu_init_phy_rf(priv, rtl8188fu_cut_b_radioa_init_table, RF_A);
784028fa281SKalle Valo 	else
785028fa281SKalle Valo 		ret = rtl8xxxu_init_phy_rf(priv, rtl8188fu_radioa_init_table, RF_A);
786028fa281SKalle Valo 
787028fa281SKalle Valo 	return ret;
788028fa281SKalle Valo }
789028fa281SKalle Valo 
rtl8188f_phy_lc_calibrate(struct rtl8xxxu_priv * priv)790028fa281SKalle Valo void rtl8188f_phy_lc_calibrate(struct rtl8xxxu_priv *priv)
791028fa281SKalle Valo {
792028fa281SKalle Valo 	u32 val32;
793028fa281SKalle Valo 	u32 rf_amode, lstf;
794028fa281SKalle Valo 	int i;
795028fa281SKalle Valo 
796028fa281SKalle Valo 	/* Check continuous TX and Packet TX */
797028fa281SKalle Valo 	lstf = rtl8xxxu_read32(priv, REG_OFDM1_LSTF);
798028fa281SKalle Valo 
799028fa281SKalle Valo 	if (lstf & OFDM_LSTF_MASK) {
800028fa281SKalle Valo 		/* Disable all continuous TX */
801028fa281SKalle Valo 		val32 = lstf & ~OFDM_LSTF_MASK;
802028fa281SKalle Valo 		rtl8xxxu_write32(priv, REG_OFDM1_LSTF, val32);
803028fa281SKalle Valo 	} else {
804028fa281SKalle Valo 		/* Deal with Packet TX case */
805028fa281SKalle Valo 		/* block all queues */
806028fa281SKalle Valo 		rtl8xxxu_write8(priv, REG_TXPAUSE, 0xff);
807028fa281SKalle Valo 	}
808028fa281SKalle Valo 
809028fa281SKalle Valo 	/* Read original RF mode Path A */
810028fa281SKalle Valo 	rf_amode = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_MODE_AG);
811028fa281SKalle Valo 
812028fa281SKalle Valo 	/* Start LC calibration */
813028fa281SKalle Valo 	rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_MODE_AG, rf_amode | 0x08000);
814028fa281SKalle Valo 
815028fa281SKalle Valo 	for (i = 0; i < 100; i++) {
816028fa281SKalle Valo 		if ((rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_MODE_AG) & 0x08000) == 0)
817028fa281SKalle Valo 			break;
818028fa281SKalle Valo 		msleep(10);
819028fa281SKalle Valo 	}
820028fa281SKalle Valo 
821028fa281SKalle Valo 	if (i == 100)
822028fa281SKalle Valo 		dev_warn(&priv->udev->dev, "LC calibration timed out.\n");
823028fa281SKalle Valo 
824028fa281SKalle Valo 	rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_MODE_AG, rf_amode);
825028fa281SKalle Valo 
826028fa281SKalle Valo 	/* Restore original parameters */
827028fa281SKalle Valo 	if (lstf & OFDM_LSTF_MASK)
828028fa281SKalle Valo 		rtl8xxxu_write32(priv, REG_OFDM1_LSTF, lstf);
829028fa281SKalle Valo 	else /*  Deal with Packet TX case */
830028fa281SKalle Valo 		rtl8xxxu_write8(priv, REG_TXPAUSE, 0x00);
831028fa281SKalle Valo }
832028fa281SKalle Valo 
rtl8188fu_iqk_path_a(struct rtl8xxxu_priv * priv,u32 * lok_result)833028fa281SKalle Valo static int rtl8188fu_iqk_path_a(struct rtl8xxxu_priv *priv, u32 *lok_result)
834028fa281SKalle Valo {
835028fa281SKalle Valo 	u32 reg_eac, reg_e94, reg_e9c, val32;
836028fa281SKalle Valo 	int result = 0;
837028fa281SKalle Valo 
838028fa281SKalle Valo 	/*
839028fa281SKalle Valo 	 * Leave IQK mode
840028fa281SKalle Valo 	 */
841028fa281SKalle Valo 	val32 = rtl8xxxu_read32(priv, REG_FPGA0_IQK);
842028fa281SKalle Valo 	val32 &= 0x000000ff;
843028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_FPGA0_IQK, val32);
844028fa281SKalle Valo 
845028fa281SKalle Valo 	/*
846028fa281SKalle Valo 	 * Enable path A PA in TX IQK mode
847028fa281SKalle Valo 	 */
848028fa281SKalle Valo 	val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_WE_LUT);
849028fa281SKalle Valo 	val32 |= 0x80000;
850028fa281SKalle Valo 	rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_WE_LUT, val32);
851028fa281SKalle Valo 	rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_RCK_OS, 0x20000);
852028fa281SKalle Valo 	rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G1, 0x0000f);
853028fa281SKalle Valo 	rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G2, 0x07ff7);
854028fa281SKalle Valo 
855028fa281SKalle Valo 	/* PA,PAD gain adjust */
856028fa281SKalle Valo 	rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x980);
857028fa281SKalle Valo 	rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_PAD_TXG, 0x5102a);
858028fa281SKalle Valo 
859028fa281SKalle Valo 	/* enter IQK mode */
860028fa281SKalle Valo 	val32 = rtl8xxxu_read32(priv, REG_FPGA0_IQK);
861028fa281SKalle Valo 	val32 &= 0x000000ff;
862028fa281SKalle Valo 	val32 |= 0x80800000;
863028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_FPGA0_IQK, val32);
864028fa281SKalle Valo 
865028fa281SKalle Valo 	/* path-A IQK setting */
866028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x18008c1c);
867028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x38008c1c);
868028fa281SKalle Valo 
869028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_TX_IQK_PI_A, 0x821403ff);
870028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_RX_IQK_PI_A, 0x28160000);
871028fa281SKalle Valo 
872028fa281SKalle Valo 	/* LO calibration setting */
873028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x00462911);
874028fa281SKalle Valo 
875028fa281SKalle Valo 	/* One shot, path A LOK & IQK */
876028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf9000000);
877028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf8000000);
878028fa281SKalle Valo 
879028fa281SKalle Valo 	mdelay(25);
880028fa281SKalle Valo 
881028fa281SKalle Valo 	/*
882028fa281SKalle Valo 	 * Leave IQK mode
883028fa281SKalle Valo 	 */
884028fa281SKalle Valo 	val32 = rtl8xxxu_read32(priv, REG_FPGA0_IQK);
885028fa281SKalle Valo 	val32 &= 0x000000ff;
886028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_FPGA0_IQK, val32);
887028fa281SKalle Valo 
888028fa281SKalle Valo 	rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x180);
889028fa281SKalle Valo 
890028fa281SKalle Valo 	/* save LOK result */
891028fa281SKalle Valo 	*lok_result = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_TXM_IDAC);
892028fa281SKalle Valo 
893028fa281SKalle Valo 	/* Check failed */
894028fa281SKalle Valo 	reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2);
895028fa281SKalle Valo 	reg_e94 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_A);
896028fa281SKalle Valo 	reg_e9c = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_A);
897028fa281SKalle Valo 
898028fa281SKalle Valo 	if (!(reg_eac & BIT(28)) &&
899028fa281SKalle Valo 	    ((reg_e94 & 0x03ff0000) != 0x01420000) &&
900028fa281SKalle Valo 	    ((reg_e9c & 0x03ff0000) != 0x00420000))
901028fa281SKalle Valo 		result |= 0x01;
902028fa281SKalle Valo 
903028fa281SKalle Valo 	return result;
904028fa281SKalle Valo }
905028fa281SKalle Valo 
rtl8188fu_rx_iqk_path_a(struct rtl8xxxu_priv * priv,u32 lok_result)906028fa281SKalle Valo static int rtl8188fu_rx_iqk_path_a(struct rtl8xxxu_priv *priv, u32 lok_result)
907028fa281SKalle Valo {
908028fa281SKalle Valo 	u32 reg_ea4, reg_eac, reg_e94, reg_e9c, val32;
909028fa281SKalle Valo 	int result = 0;
910028fa281SKalle Valo 
911028fa281SKalle Valo 	/*
912028fa281SKalle Valo 	 * Leave IQK mode
913028fa281SKalle Valo 	 */
914028fa281SKalle Valo 	val32 = rtl8xxxu_read32(priv, REG_FPGA0_IQK);
915028fa281SKalle Valo 	val32 &= 0x000000ff;
916028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_FPGA0_IQK, val32);
917028fa281SKalle Valo 
918028fa281SKalle Valo 	/*
919028fa281SKalle Valo 	 * Enable path A PA in TX IQK mode
920028fa281SKalle Valo 	 */
921028fa281SKalle Valo 	val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_WE_LUT);
922028fa281SKalle Valo 	val32 |= 0x80000;
923028fa281SKalle Valo 	rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_WE_LUT, val32);
924028fa281SKalle Valo 	rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_RCK_OS, 0x30000);
925028fa281SKalle Valo 	rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G1, 0x0000f);
926028fa281SKalle Valo 	rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G2, 0xf1173);
927028fa281SKalle Valo 
928028fa281SKalle Valo 	/* PA,PAD gain adjust */
929028fa281SKalle Valo 	rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x980);
930028fa281SKalle Valo 	rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_PAD_TXG, 0x5102a);
931028fa281SKalle Valo 
932028fa281SKalle Valo 	/*
933028fa281SKalle Valo 	 * Enter IQK mode
934028fa281SKalle Valo 	 */
935028fa281SKalle Valo 	val32 = rtl8xxxu_read32(priv, REG_FPGA0_IQK);
936028fa281SKalle Valo 	val32 &= 0x000000ff;
937028fa281SKalle Valo 	val32 |= 0x80800000;
938028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_FPGA0_IQK, val32);
939028fa281SKalle Valo 
940028fa281SKalle Valo 	/*
941028fa281SKalle Valo 	 * Tx IQK setting
942028fa281SKalle Valo 	 */
943028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_TX_IQK, 0x01007c00);
944028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_RX_IQK, 0x01004800);
945028fa281SKalle Valo 
946028fa281SKalle Valo 	/* path-A IQK setting */
947028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x10008c1c);
948028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x30008c1c);
949028fa281SKalle Valo 
950028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_TX_IQK_PI_A, 0x82160fff);
951028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_RX_IQK_PI_A, 0x28160000);
952028fa281SKalle Valo 
953028fa281SKalle Valo 	/* LO calibration setting */
954028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x00462911);
955028fa281SKalle Valo 
956028fa281SKalle Valo 	/* One shot, path A LOK & IQK */
957028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf9000000);
958028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf8000000);
959028fa281SKalle Valo 
960028fa281SKalle Valo 	mdelay(25);
961028fa281SKalle Valo 
962028fa281SKalle Valo 	/*
963028fa281SKalle Valo 	 * Leave IQK mode
964028fa281SKalle Valo 	 */
965028fa281SKalle Valo 	val32 = rtl8xxxu_read32(priv, REG_FPGA0_IQK);
966028fa281SKalle Valo 	val32 &= 0x000000ff;
967028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_FPGA0_IQK, val32);
968028fa281SKalle Valo 
969028fa281SKalle Valo 	rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x180);
970028fa281SKalle Valo 
971028fa281SKalle Valo 	/* Check failed */
972028fa281SKalle Valo 	reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2);
973028fa281SKalle Valo 	reg_e94 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_A);
974028fa281SKalle Valo 	reg_e9c = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_A);
975028fa281SKalle Valo 
976028fa281SKalle Valo 	if (!(reg_eac & BIT(28)) &&
977028fa281SKalle Valo 	    ((reg_e94 & 0x03ff0000) != 0x01420000) &&
978028fa281SKalle Valo 	    ((reg_e9c & 0x03ff0000) != 0x00420000))
979028fa281SKalle Valo 		result |= 0x01;
980028fa281SKalle Valo 	else /* If TX not OK, ignore RX */
981028fa281SKalle Valo 		goto out;
982028fa281SKalle Valo 
983028fa281SKalle Valo 	val32 = 0x80007c00 | (reg_e94 & 0x3ff0000) |
984028fa281SKalle Valo 		((reg_e9c & 0x3ff0000) >> 16);
985028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_TX_IQK, val32);
986028fa281SKalle Valo 
987028fa281SKalle Valo 	/*
988028fa281SKalle Valo 	 * Modify RX IQK mode table
989028fa281SKalle Valo 	 */
990028fa281SKalle Valo 	val32 = rtl8xxxu_read32(priv, REG_FPGA0_IQK);
991028fa281SKalle Valo 	val32 &= 0x000000ff;
992028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_FPGA0_IQK, val32);
993028fa281SKalle Valo 
994028fa281SKalle Valo 	val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_WE_LUT);
995028fa281SKalle Valo 	val32 |= 0x80000;
996028fa281SKalle Valo 	rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_WE_LUT, val32);
997028fa281SKalle Valo 	rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_RCK_OS, 0x30000);
998028fa281SKalle Valo 	rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G1, 0x0000f);
999028fa281SKalle Valo 	rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G2, 0xf7ff2);
1000028fa281SKalle Valo 
1001028fa281SKalle Valo 	/*
1002028fa281SKalle Valo 	 * PA, PAD setting
1003028fa281SKalle Valo 	 */
1004028fa281SKalle Valo 	rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x980);
1005028fa281SKalle Valo 	rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_PAD_TXG, 0x51000);
1006028fa281SKalle Valo 
1007028fa281SKalle Valo 	/*
1008028fa281SKalle Valo 	 * Enter IQK mode
1009028fa281SKalle Valo 	 */
1010028fa281SKalle Valo 	val32 = rtl8xxxu_read32(priv, REG_FPGA0_IQK);
1011028fa281SKalle Valo 	val32 &= 0x000000ff;
1012028fa281SKalle Valo 	val32 |= 0x80800000;
1013028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_FPGA0_IQK, val32);
1014028fa281SKalle Valo 
1015028fa281SKalle Valo 	/*
1016028fa281SKalle Valo 	 * RX IQK setting
1017028fa281SKalle Valo 	 */
1018028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_RX_IQK, 0x01004800);
1019028fa281SKalle Valo 
1020028fa281SKalle Valo 	/* path-A IQK setting */
1021028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x30008c1c);
1022028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x10008c1c);
1023028fa281SKalle Valo 
1024028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_TX_IQK_PI_A, 0x82160000);
1025028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_RX_IQK_PI_A, 0x281613ff);
1026028fa281SKalle Valo 
1027028fa281SKalle Valo 	/* LO calibration setting */
1028028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x0046a911);
1029028fa281SKalle Valo 
1030028fa281SKalle Valo 	/* One shot, path A LOK & IQK */
1031028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf9000000);
1032028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf8000000);
1033028fa281SKalle Valo 
1034028fa281SKalle Valo 	mdelay(25);
1035028fa281SKalle Valo 
1036028fa281SKalle Valo 	/*
1037028fa281SKalle Valo 	 * Leave IQK mode
1038028fa281SKalle Valo 	 */
1039028fa281SKalle Valo 	val32 = rtl8xxxu_read32(priv, REG_FPGA0_IQK);
1040028fa281SKalle Valo 	val32 &= 0x000000ff;
1041028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_FPGA0_IQK, val32);
1042028fa281SKalle Valo 
1043028fa281SKalle Valo 	rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x180);
1044028fa281SKalle Valo 
1045028fa281SKalle Valo 	/* reload LOK value */
1046028fa281SKalle Valo 	rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXM_IDAC, lok_result);
1047028fa281SKalle Valo 
1048028fa281SKalle Valo 	/* Check failed */
1049028fa281SKalle Valo 	reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2);
1050028fa281SKalle Valo 	reg_ea4 = rtl8xxxu_read32(priv, REG_RX_POWER_BEFORE_IQK_A_2);
1051028fa281SKalle Valo 
1052028fa281SKalle Valo 	if (!(reg_eac & BIT(27)) &&
1053028fa281SKalle Valo 	    ((reg_ea4 & 0x03ff0000) != 0x01320000) &&
1054028fa281SKalle Valo 	    ((reg_eac & 0x03ff0000) != 0x00360000))
1055028fa281SKalle Valo 		result |= 0x02;
1056028fa281SKalle Valo 
1057028fa281SKalle Valo out:
1058028fa281SKalle Valo 	return result;
1059028fa281SKalle Valo }
1060028fa281SKalle Valo 
rtl8188fu_phy_iqcalibrate(struct rtl8xxxu_priv * priv,int result[][8],int t)1061028fa281SKalle Valo static void rtl8188fu_phy_iqcalibrate(struct rtl8xxxu_priv *priv,
1062028fa281SKalle Valo 				      int result[][8], int t)
1063028fa281SKalle Valo {
1064028fa281SKalle Valo 	struct device *dev = &priv->udev->dev;
1065028fa281SKalle Valo 	u32 i, val32, rx_initial_gain, lok_result;
1066028fa281SKalle Valo 	u32 path_sel_bb, path_sel_rf;
1067028fa281SKalle Valo 	int path_a_ok;
1068028fa281SKalle Valo 	int retry = 2;
1069028fa281SKalle Valo 	static const u32 adda_regs[RTL8XXXU_ADDA_REGS] = {
1070028fa281SKalle Valo 		REG_FPGA0_XCD_SWITCH_CTRL, REG_BLUETOOTH,
1071028fa281SKalle Valo 		REG_RX_WAIT_CCA, REG_TX_CCK_RFON,
1072028fa281SKalle Valo 		REG_TX_CCK_BBON, REG_TX_OFDM_RFON,
1073028fa281SKalle Valo 		REG_TX_OFDM_BBON, REG_TX_TO_RX,
1074028fa281SKalle Valo 		REG_TX_TO_TX, REG_RX_CCK,
1075028fa281SKalle Valo 		REG_RX_OFDM, REG_RX_WAIT_RIFS,
1076028fa281SKalle Valo 		REG_RX_TO_RX, REG_STANDBY,
1077028fa281SKalle Valo 		REG_SLEEP, REG_PMPD_ANAEN
1078028fa281SKalle Valo 	};
1079028fa281SKalle Valo 	static const u32 iqk_mac_regs[RTL8XXXU_MAC_REGS] = {
1080028fa281SKalle Valo 		REG_TXPAUSE, REG_BEACON_CTRL,
1081028fa281SKalle Valo 		REG_BEACON_CTRL_1, REG_GPIO_MUXCFG
1082028fa281SKalle Valo 	};
1083028fa281SKalle Valo 	static const u32 iqk_bb_regs[RTL8XXXU_BB_REGS] = {
1084028fa281SKalle Valo 		REG_OFDM0_TRX_PATH_ENABLE, REG_OFDM0_TR_MUX_PAR,
1085028fa281SKalle Valo 		REG_FPGA0_XCD_RF_SW_CTRL, REG_CONFIG_ANT_A, REG_CONFIG_ANT_B,
1086028fa281SKalle Valo 		REG_FPGA0_XAB_RF_SW_CTRL, REG_FPGA0_XA_RF_INT_OE,
1087028fa281SKalle Valo 		REG_FPGA0_XB_RF_INT_OE, REG_FPGA0_RF_MODE
1088028fa281SKalle Valo 	};
1089028fa281SKalle Valo 
1090028fa281SKalle Valo 	/*
1091028fa281SKalle Valo 	 * Note: IQ calibration must be performed after loading
1092028fa281SKalle Valo 	 *       PHY_REG.txt , and radio_a, radio_b.txt
1093028fa281SKalle Valo 	 */
1094028fa281SKalle Valo 
1095028fa281SKalle Valo 	rx_initial_gain = rtl8xxxu_read32(priv, REG_OFDM0_XA_AGC_CORE1);
1096028fa281SKalle Valo 
1097028fa281SKalle Valo 	if (t == 0) {
1098028fa281SKalle Valo 		/* Save ADDA parameters, turn Path A ADDA on */
1099028fa281SKalle Valo 		rtl8xxxu_save_regs(priv, adda_regs, priv->adda_backup,
1100028fa281SKalle Valo 				   RTL8XXXU_ADDA_REGS);
1101028fa281SKalle Valo 		rtl8xxxu_save_mac_regs(priv, iqk_mac_regs, priv->mac_backup);
1102028fa281SKalle Valo 		rtl8xxxu_save_regs(priv, iqk_bb_regs,
1103028fa281SKalle Valo 				   priv->bb_backup, RTL8XXXU_BB_REGS);
1104028fa281SKalle Valo 	}
1105028fa281SKalle Valo 
1106028fa281SKalle Valo 	rtl8xxxu_path_adda_on(priv, adda_regs, true);
1107028fa281SKalle Valo 
1108028fa281SKalle Valo 	if (t == 0) {
1109028fa281SKalle Valo 		val32 = rtl8xxxu_read32(priv, REG_FPGA0_XA_HSSI_PARM1);
1110028fa281SKalle Valo 		priv->pi_enabled = u32_get_bits(val32, FPGA0_HSSI_PARM1_PI);
1111028fa281SKalle Valo 	}
1112028fa281SKalle Valo 
1113028fa281SKalle Valo 	/* save RF path */
1114028fa281SKalle Valo 	path_sel_bb = rtl8xxxu_read32(priv, REG_S0S1_PATH_SWITCH);
1115028fa281SKalle Valo 	path_sel_rf = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_S0S1);
1116028fa281SKalle Valo 
1117028fa281SKalle Valo 	/* BB setting */
1118028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, 0x03a05600);
1119028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_OFDM0_TR_MUX_PAR, 0x000800e4);
1120028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_FPGA0_XCD_RF_SW_CTRL, 0x25204000);
1121028fa281SKalle Valo 
1122028fa281SKalle Valo 	/* MAC settings */
1123028fa281SKalle Valo 	val32 = rtl8xxxu_read32(priv, REG_TX_PTCL_CTRL);
1124028fa281SKalle Valo 	val32 |= 0x00ff0000;
1125028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_TX_PTCL_CTRL, val32);
1126028fa281SKalle Valo 
1127028fa281SKalle Valo 	/* IQ calibration setting */
1128028fa281SKalle Valo 	val32 = rtl8xxxu_read32(priv, REG_FPGA0_IQK);
1129028fa281SKalle Valo 	val32 &= 0xff;
1130028fa281SKalle Valo 	val32 |= 0x80800000;
1131028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_FPGA0_IQK, val32);
1132028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_TX_IQK, 0x01007c00);
1133028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_RX_IQK, 0x01004800);
1134028fa281SKalle Valo 
1135028fa281SKalle Valo 	for (i = 0; i < retry; i++) {
1136028fa281SKalle Valo 		path_a_ok = rtl8188fu_iqk_path_a(priv, &lok_result);
1137028fa281SKalle Valo 		if (path_a_ok == 0x01) {
1138028fa281SKalle Valo 			val32 = rtl8xxxu_read32(priv, REG_FPGA0_IQK);
1139028fa281SKalle Valo 			val32 &= 0xff;
1140028fa281SKalle Valo 			rtl8xxxu_write32(priv, REG_FPGA0_IQK, val32);
1141028fa281SKalle Valo 
1142028fa281SKalle Valo 			val32 = rtl8xxxu_read32(priv,
1143028fa281SKalle Valo 						REG_TX_POWER_BEFORE_IQK_A);
1144028fa281SKalle Valo 			result[t][0] = (val32 >> 16) & 0x3ff;
1145028fa281SKalle Valo 
1146028fa281SKalle Valo 			val32 = rtl8xxxu_read32(priv,
1147028fa281SKalle Valo 						REG_TX_POWER_AFTER_IQK_A);
1148028fa281SKalle Valo 			result[t][1] = (val32 >> 16) & 0x3ff;
1149028fa281SKalle Valo 			break;
1150028fa281SKalle Valo 		}
1151028fa281SKalle Valo 	}
1152028fa281SKalle Valo 
1153028fa281SKalle Valo 	for (i = 0; i < retry; i++) {
1154028fa281SKalle Valo 		path_a_ok = rtl8188fu_rx_iqk_path_a(priv, lok_result);
1155028fa281SKalle Valo 		if (path_a_ok == 0x03) {
1156028fa281SKalle Valo 			val32 = rtl8xxxu_read32(priv,
1157028fa281SKalle Valo 						REG_RX_POWER_BEFORE_IQK_A_2);
1158028fa281SKalle Valo 			result[t][2] = (val32 >> 16) & 0x3ff;
1159028fa281SKalle Valo 
1160028fa281SKalle Valo 			val32 = rtl8xxxu_read32(priv,
1161028fa281SKalle Valo 						REG_RX_POWER_AFTER_IQK_A_2);
1162028fa281SKalle Valo 			result[t][3] = (val32 >> 16) & 0x3ff;
1163028fa281SKalle Valo 			break;
1164028fa281SKalle Valo 		}
1165028fa281SKalle Valo 	}
1166028fa281SKalle Valo 
1167028fa281SKalle Valo 	if (!path_a_ok)
1168028fa281SKalle Valo 		dev_dbg(dev, "%s: Path A IQK failed!\n", __func__);
1169028fa281SKalle Valo 
1170028fa281SKalle Valo 	/* Back to BB mode, load original value */
1171028fa281SKalle Valo 	val32 = rtl8xxxu_read32(priv, REG_FPGA0_IQK);
1172028fa281SKalle Valo 	val32 &= 0xff;
1173028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_FPGA0_IQK, val32);
1174028fa281SKalle Valo 
1175028fa281SKalle Valo 	if (t == 0)
1176028fa281SKalle Valo 		return;
1177028fa281SKalle Valo 
1178028fa281SKalle Valo 	if (!priv->pi_enabled) {
1179028fa281SKalle Valo 		/*
1180028fa281SKalle Valo 		 * Switch back BB to SI mode after finishing
1181028fa281SKalle Valo 		 * IQ Calibration
1182028fa281SKalle Valo 		 */
1183028fa281SKalle Valo 		val32 = 0x01000000;
1184028fa281SKalle Valo 		rtl8xxxu_write32(priv, REG_FPGA0_XA_HSSI_PARM1, val32);
1185028fa281SKalle Valo 		rtl8xxxu_write32(priv, REG_FPGA0_XB_HSSI_PARM1, val32);
1186028fa281SKalle Valo 	}
1187028fa281SKalle Valo 
1188028fa281SKalle Valo 	/* Reload ADDA power saving parameters */
1189028fa281SKalle Valo 	rtl8xxxu_restore_regs(priv, adda_regs, priv->adda_backup,
1190028fa281SKalle Valo 			      RTL8XXXU_ADDA_REGS);
1191028fa281SKalle Valo 
1192028fa281SKalle Valo 	/* Reload MAC parameters */
1193028fa281SKalle Valo 	rtl8xxxu_restore_mac_regs(priv, iqk_mac_regs, priv->mac_backup);
1194028fa281SKalle Valo 
1195028fa281SKalle Valo 	/* Reload BB parameters */
1196028fa281SKalle Valo 	rtl8xxxu_restore_regs(priv, iqk_bb_regs,
1197028fa281SKalle Valo 			      priv->bb_backup, RTL8XXXU_BB_REGS);
1198028fa281SKalle Valo 
1199028fa281SKalle Valo 	/* Reload RF path */
1200028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_S0S1_PATH_SWITCH, path_sel_bb);
1201028fa281SKalle Valo 	rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_S0S1, path_sel_rf);
1202028fa281SKalle Valo 
1203028fa281SKalle Valo 	/* Restore RX initial gain */
1204028fa281SKalle Valo 	val32 = rtl8xxxu_read32(priv, REG_OFDM0_XA_AGC_CORE1);
1205028fa281SKalle Valo 	val32 &= 0xffffff00;
1206028fa281SKalle Valo 	val32 |= 0x50;
1207028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_OFDM0_XA_AGC_CORE1, val32);
1208028fa281SKalle Valo 	val32 = rtl8xxxu_read32(priv, REG_OFDM0_XA_AGC_CORE1);
1209028fa281SKalle Valo 	val32 &= 0xffffff00;
1210028fa281SKalle Valo 	val32 |= rx_initial_gain & 0xff;
1211028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_OFDM0_XA_AGC_CORE1, val32);
1212028fa281SKalle Valo 
1213028fa281SKalle Valo 	/* Load 0xe30 IQC default value */
1214028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x01008c00);
1215028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x01008c00);
1216028fa281SKalle Valo }
1217028fa281SKalle Valo 
rtl8188fu_phy_iq_calibrate(struct rtl8xxxu_priv * priv)1218028fa281SKalle Valo static void rtl8188fu_phy_iq_calibrate(struct rtl8xxxu_priv *priv)
1219028fa281SKalle Valo {
1220028fa281SKalle Valo 	struct device *dev = &priv->udev->dev;
1221028fa281SKalle Valo 	int result[4][8]; /* last is final result */
1222028fa281SKalle Valo 	int i, candidate;
1223028fa281SKalle Valo 	bool path_a_ok;
1224028fa281SKalle Valo 	u32 reg_e94, reg_e9c, reg_ea4, reg_eac;
1225028fa281SKalle Valo 	u32 reg_eb4, reg_ebc, reg_ec4, reg_ecc;
1226028fa281SKalle Valo 	s32 reg_tmp = 0;
1227028fa281SKalle Valo 	bool simu;
1228028fa281SKalle Valo 	u32 path_sel_bb, path_sel_rf;
1229028fa281SKalle Valo 
1230028fa281SKalle Valo 	/* Save RF path */
1231028fa281SKalle Valo 	path_sel_bb = rtl8xxxu_read32(priv, REG_S0S1_PATH_SWITCH);
1232028fa281SKalle Valo 	path_sel_rf = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_S0S1);
1233028fa281SKalle Valo 
1234028fa281SKalle Valo 	memset(result, 0, sizeof(result));
1235028fa281SKalle Valo 	candidate = -1;
1236028fa281SKalle Valo 
1237028fa281SKalle Valo 	path_a_ok = false;
1238028fa281SKalle Valo 
1239028fa281SKalle Valo 	for (i = 0; i < 3; i++) {
1240028fa281SKalle Valo 		rtl8188fu_phy_iqcalibrate(priv, result, i);
1241028fa281SKalle Valo 
1242028fa281SKalle Valo 		if (i == 1) {
1243028fa281SKalle Valo 			simu = rtl8xxxu_gen2_simularity_compare(priv, result, 0, 1);
1244028fa281SKalle Valo 			if (simu) {
1245028fa281SKalle Valo 				candidate = 0;
1246028fa281SKalle Valo 				break;
1247028fa281SKalle Valo 			}
1248028fa281SKalle Valo 		}
1249028fa281SKalle Valo 
1250028fa281SKalle Valo 		if (i == 2) {
1251028fa281SKalle Valo 			simu = rtl8xxxu_gen2_simularity_compare(priv, result, 0, 2);
1252028fa281SKalle Valo 			if (simu) {
1253028fa281SKalle Valo 				candidate = 0;
1254028fa281SKalle Valo 				break;
1255028fa281SKalle Valo 			}
1256028fa281SKalle Valo 
1257028fa281SKalle Valo 			simu = rtl8xxxu_gen2_simularity_compare(priv, result, 1, 2);
1258028fa281SKalle Valo 			if (simu) {
1259028fa281SKalle Valo 				candidate = 1;
1260028fa281SKalle Valo 			} else {
1261028fa281SKalle Valo 				for (i = 0; i < 8; i++)
1262028fa281SKalle Valo 					reg_tmp += result[3][i];
1263028fa281SKalle Valo 
1264028fa281SKalle Valo 				if (reg_tmp)
1265028fa281SKalle Valo 					candidate = 3;
1266028fa281SKalle Valo 				else
1267028fa281SKalle Valo 					candidate = -1;
1268028fa281SKalle Valo 			}
1269028fa281SKalle Valo 		}
1270028fa281SKalle Valo 	}
1271028fa281SKalle Valo 
1272028fa281SKalle Valo 	for (i = 0; i < 4; i++) {
1273028fa281SKalle Valo 		reg_e94 = result[i][0];
1274028fa281SKalle Valo 		reg_e9c = result[i][1];
1275028fa281SKalle Valo 		reg_ea4 = result[i][2];
1276028fa281SKalle Valo 		reg_eac = result[i][3];
1277028fa281SKalle Valo 		reg_eb4 = result[i][4];
1278028fa281SKalle Valo 		reg_ebc = result[i][5];
1279028fa281SKalle Valo 		reg_ec4 = result[i][6];
1280028fa281SKalle Valo 		reg_ecc = result[i][7];
1281028fa281SKalle Valo 	}
1282028fa281SKalle Valo 
1283028fa281SKalle Valo 	if (candidate >= 0) {
1284028fa281SKalle Valo 		reg_e94 = result[candidate][0];
1285028fa281SKalle Valo 		priv->rege94 =  reg_e94;
1286028fa281SKalle Valo 		reg_e9c = result[candidate][1];
1287028fa281SKalle Valo 		priv->rege9c = reg_e9c;
1288028fa281SKalle Valo 		reg_ea4 = result[candidate][2];
1289028fa281SKalle Valo 		reg_eac = result[candidate][3];
1290028fa281SKalle Valo 		reg_eb4 = result[candidate][4];
1291028fa281SKalle Valo 		priv->regeb4 = reg_eb4;
1292028fa281SKalle Valo 		reg_ebc = result[candidate][5];
1293028fa281SKalle Valo 		priv->regebc = reg_ebc;
1294028fa281SKalle Valo 		reg_ec4 = result[candidate][6];
1295028fa281SKalle Valo 		reg_ecc = result[candidate][7];
1296028fa281SKalle Valo 		dev_dbg(dev, "%s: candidate is %x\n", __func__, candidate);
1297028fa281SKalle Valo 		dev_dbg(dev,
1298028fa281SKalle Valo 			"%s: e94 =%x e9c=%x ea4=%x eac=%x eb4=%x ebc=%x ec4=%x ecc=%x\n",
1299028fa281SKalle Valo 			__func__, reg_e94, reg_e9c,
1300028fa281SKalle Valo 			reg_ea4, reg_eac, reg_eb4, reg_ebc, reg_ec4, reg_ecc);
1301028fa281SKalle Valo 		path_a_ok = true;
1302028fa281SKalle Valo 	} else {
1303028fa281SKalle Valo 		reg_e94 = reg_eb4 = priv->rege94 = priv->regeb4 = 0x100;
1304028fa281SKalle Valo 		reg_e9c = reg_ebc = priv->rege9c = priv->regebc = 0x0;
1305028fa281SKalle Valo 	}
1306028fa281SKalle Valo 
1307028fa281SKalle Valo 	if (reg_e94 && candidate >= 0)
1308028fa281SKalle Valo 		rtl8xxxu_fill_iqk_matrix_a(priv, path_a_ok, result,
1309028fa281SKalle Valo 					   candidate, (reg_ea4 == 0));
1310028fa281SKalle Valo 
1311028fa281SKalle Valo 	rtl8xxxu_save_regs(priv, rtl8xxxu_iqk_phy_iq_bb_reg,
1312028fa281SKalle Valo 			   priv->bb_recovery_backup, RTL8XXXU_BB_REGS);
1313028fa281SKalle Valo 
1314028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_S0S1_PATH_SWITCH, path_sel_bb);
1315028fa281SKalle Valo 	rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_S0S1, path_sel_rf);
1316028fa281SKalle Valo }
1317028fa281SKalle Valo 
rtl8188f_disabled_to_emu(struct rtl8xxxu_priv * priv)1318028fa281SKalle Valo static void rtl8188f_disabled_to_emu(struct rtl8xxxu_priv *priv)
1319028fa281SKalle Valo {
1320028fa281SKalle Valo 	u16 val8;
1321028fa281SKalle Valo 
1322028fa281SKalle Valo 	/* 0x04[12:11] = 2b'01enable WL suspend */
1323028fa281SKalle Valo 	val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1);
1324028fa281SKalle Valo 	val8 &= ~((APS_FSMCO_PCIE | APS_FSMCO_HW_SUSPEND) >> 8);
1325028fa281SKalle Valo 	rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val8);
1326028fa281SKalle Valo 
1327028fa281SKalle Valo 	/* 0xC4[4] <= 1, turn off USB APHY LDO under suspend mode */
1328028fa281SKalle Valo 	val8 = rtl8xxxu_read8(priv, 0xc4);
1329028fa281SKalle Valo 	val8 &= ~BIT(4);
1330028fa281SKalle Valo 	rtl8xxxu_write8(priv, 0xc4, val8);
1331028fa281SKalle Valo }
1332028fa281SKalle Valo 
rtl8188f_emu_to_active(struct rtl8xxxu_priv * priv)1333028fa281SKalle Valo static int rtl8188f_emu_to_active(struct rtl8xxxu_priv *priv)
1334028fa281SKalle Valo {
1335028fa281SKalle Valo 	u8 val8;
1336028fa281SKalle Valo 	u32 val32;
1337028fa281SKalle Valo 	int count, ret = 0;
1338028fa281SKalle Valo 
1339028fa281SKalle Valo 	/* Disable SW LPS */
1340028fa281SKalle Valo 	val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1);
1341028fa281SKalle Valo 	val8 &= ~(APS_FSMCO_SW_LPS >> 8);
1342028fa281SKalle Valo 	rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val8);
1343028fa281SKalle Valo 
1344028fa281SKalle Valo 	/* wait till 0x04[17] = 1 power ready */
1345028fa281SKalle Valo 	for (count = RTL8XXXU_MAX_REG_POLL; count; count--) {
1346028fa281SKalle Valo 		val32 = rtl8xxxu_read32(priv, REG_APS_FSMCO);
1347028fa281SKalle Valo 		if (val32 & BIT(17))
1348028fa281SKalle Valo 			break;
1349028fa281SKalle Valo 
1350028fa281SKalle Valo 		udelay(10);
1351028fa281SKalle Valo 	}
1352028fa281SKalle Valo 
1353028fa281SKalle Valo 	if (!count) {
1354028fa281SKalle Valo 		ret = -EBUSY;
1355028fa281SKalle Valo 		goto exit;
1356028fa281SKalle Valo 	}
1357028fa281SKalle Valo 
1358028fa281SKalle Valo 	/* Disable HWPDN */
1359028fa281SKalle Valo 	val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1);
1360028fa281SKalle Valo 	val8 &= ~(APS_FSMCO_HW_POWERDOWN >> 8);
1361028fa281SKalle Valo 	rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val8);
1362028fa281SKalle Valo 
1363028fa281SKalle Valo 	/* Disable WL suspend */
1364028fa281SKalle Valo 	val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1);
1365028fa281SKalle Valo 	val8 &= ~(APS_FSMCO_HW_SUSPEND >> 8);
1366028fa281SKalle Valo 	rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val8);
1367028fa281SKalle Valo 
1368028fa281SKalle Valo 	/* set, then poll until 0 */
1369028fa281SKalle Valo 	val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1);
1370028fa281SKalle Valo 	val8 |= APS_FSMCO_MAC_ENABLE >> 8;
1371028fa281SKalle Valo 	rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val8);
1372028fa281SKalle Valo 
1373028fa281SKalle Valo 	for (count = RTL8XXXU_MAX_REG_POLL; count; count--) {
1374028fa281SKalle Valo 		val32 = rtl8xxxu_read32(priv, REG_APS_FSMCO);
1375028fa281SKalle Valo 		if ((val32 & APS_FSMCO_MAC_ENABLE) == 0) {
1376028fa281SKalle Valo 			ret = 0;
1377028fa281SKalle Valo 			break;
1378028fa281SKalle Valo 		}
1379028fa281SKalle Valo 		udelay(10);
1380028fa281SKalle Valo 	}
1381028fa281SKalle Valo 
1382028fa281SKalle Valo 	if (!count) {
1383028fa281SKalle Valo 		ret = -EBUSY;
1384028fa281SKalle Valo 		goto exit;
1385028fa281SKalle Valo 	}
1386028fa281SKalle Valo 
1387028fa281SKalle Valo 	/* 0x27<=35 to reduce RF noise */
1388028fa281SKalle Valo 	val8 = rtl8xxxu_write8(priv, 0x27, 0x35);
1389028fa281SKalle Valo exit:
1390028fa281SKalle Valo 	return ret;
1391028fa281SKalle Valo }
1392028fa281SKalle Valo 
rtl8188fu_active_to_emu(struct rtl8xxxu_priv * priv)1393028fa281SKalle Valo static int rtl8188fu_active_to_emu(struct rtl8xxxu_priv *priv)
1394028fa281SKalle Valo {
1395028fa281SKalle Valo 	u8 val8;
1396028fa281SKalle Valo 	u32 val32;
1397028fa281SKalle Valo 	int count, ret = 0;
1398028fa281SKalle Valo 
1399028fa281SKalle Valo 	/* Turn off RF */
1400028fa281SKalle Valo 	rtl8xxxu_write8(priv, REG_RF_CTRL, 0);
1401028fa281SKalle Valo 
1402028fa281SKalle Valo 	/* 0x4C[23] = 0x4E[7] = 0, switch DPDT_SEL_P output from register 0x65[2] */
1403028fa281SKalle Valo 	val8 = rtl8xxxu_read8(priv, 0x4e);
1404028fa281SKalle Valo 	val8 &= ~BIT(7);
1405028fa281SKalle Valo 	rtl8xxxu_write8(priv, 0x4e, val8);
1406028fa281SKalle Valo 
1407028fa281SKalle Valo 	/* 0x27 <= 34, xtal_qsel = 0 to xtal bring up */
1408028fa281SKalle Valo 	rtl8xxxu_write8(priv, 0x27, 0x34);
1409028fa281SKalle Valo 
1410028fa281SKalle Valo 	/* 0x04[9] = 1 turn off MAC by HW state machine */
1411028fa281SKalle Valo 	val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1);
1412028fa281SKalle Valo 	val8 |= APS_FSMCO_MAC_OFF >> 8;
1413028fa281SKalle Valo 	rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val8);
1414028fa281SKalle Valo 
1415028fa281SKalle Valo 	for (count = RTL8XXXU_MAX_REG_POLL; count; count--) {
1416028fa281SKalle Valo 		val32 = rtl8xxxu_read32(priv, REG_APS_FSMCO);
1417028fa281SKalle Valo 		if ((val32 & APS_FSMCO_MAC_OFF) == 0) {
1418028fa281SKalle Valo 			ret = 0;
1419028fa281SKalle Valo 			break;
1420028fa281SKalle Valo 		}
1421028fa281SKalle Valo 		udelay(10);
1422028fa281SKalle Valo 	}
1423028fa281SKalle Valo 
1424028fa281SKalle Valo 	if (!count) {
1425028fa281SKalle Valo 		ret = -EBUSY;
1426028fa281SKalle Valo 		goto exit;
1427028fa281SKalle Valo 	}
1428028fa281SKalle Valo 
1429028fa281SKalle Valo exit:
1430028fa281SKalle Valo 	return ret;
1431028fa281SKalle Valo }
1432028fa281SKalle Valo 
rtl8188fu_emu_to_disabled(struct rtl8xxxu_priv * priv)1433028fa281SKalle Valo static int rtl8188fu_emu_to_disabled(struct rtl8xxxu_priv *priv)
1434028fa281SKalle Valo {
1435028fa281SKalle Valo 	u8 val8;
1436028fa281SKalle Valo 
1437028fa281SKalle Valo 	/* 0x04[12:11] = 2b'01 enable WL suspend */
1438028fa281SKalle Valo 	val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1);
1439028fa281SKalle Valo 	val8 &= ~((APS_FSMCO_PCIE | APS_FSMCO_HW_SUSPEND) >> 8);
1440028fa281SKalle Valo 	val8 |= APS_FSMCO_HW_SUSPEND >> 8;
1441028fa281SKalle Valo 	rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val8);
1442028fa281SKalle Valo 
1443028fa281SKalle Valo 	/* 0xC4[4] <= 1, turn off USB APHY LDO under suspend mode */
1444028fa281SKalle Valo 	val8 = rtl8xxxu_read8(priv, 0xc4);
1445028fa281SKalle Valo 	val8 |= BIT(4);
1446028fa281SKalle Valo 	rtl8xxxu_write8(priv, 0xc4, val8);
1447028fa281SKalle Valo 
1448028fa281SKalle Valo 	return 0;
1449028fa281SKalle Valo }
1450028fa281SKalle Valo 
rtl8188fu_active_to_lps(struct rtl8xxxu_priv * priv)1451028fa281SKalle Valo static int rtl8188fu_active_to_lps(struct rtl8xxxu_priv *priv)
1452028fa281SKalle Valo {
1453028fa281SKalle Valo 	struct device *dev = &priv->udev->dev;
1454028fa281SKalle Valo 	u8 val8;
1455028fa281SKalle Valo 	u16 val16;
1456028fa281SKalle Valo 	u32 val32;
1457028fa281SKalle Valo 	int retry, retval;
1458028fa281SKalle Valo 
1459028fa281SKalle Valo 	/* set RPWM IMR */
1460028fa281SKalle Valo 	val8 = rtl8xxxu_read8(priv, REG_FTIMR + 1);
1461028fa281SKalle Valo 	val8 |= IMR0_CPWM >> 8;
1462028fa281SKalle Valo 	rtl8xxxu_write8(priv, REG_FTIMR + 1, val8);
1463028fa281SKalle Valo 
1464028fa281SKalle Valo 	/* Tx Pause */
1465028fa281SKalle Valo 	rtl8xxxu_write8(priv, REG_TXPAUSE, 0xff);
1466028fa281SKalle Valo 
1467028fa281SKalle Valo 	retry = 100;
1468028fa281SKalle Valo 	retval = -EBUSY;
1469028fa281SKalle Valo 
1470028fa281SKalle Valo 	/*
1471028fa281SKalle Valo 	 * Poll 32 bit wide REG_SCH_TX_CMD for 0x00000000 to ensure no TX is pending.
1472028fa281SKalle Valo 	 */
1473028fa281SKalle Valo 	do {
1474028fa281SKalle Valo 		val32 = rtl8xxxu_read32(priv, REG_SCH_TX_CMD);
1475028fa281SKalle Valo 		if (!val32) {
1476028fa281SKalle Valo 			retval = 0;
1477028fa281SKalle Valo 			break;
1478028fa281SKalle Valo 		}
1479028fa281SKalle Valo 	} while (retry--);
1480028fa281SKalle Valo 
1481028fa281SKalle Valo 	if (!retry) {
1482028fa281SKalle Valo 		dev_warn(dev, "Failed to flush TX queue\n");
1483028fa281SKalle Valo 		retval = -EBUSY;
1484028fa281SKalle Valo 		goto out;
1485028fa281SKalle Valo 	}
1486028fa281SKalle Valo 
1487028fa281SKalle Valo 	/* Disable CCK and OFDM, clock gated */
1488028fa281SKalle Valo 	val8 = rtl8xxxu_read8(priv, REG_SYS_FUNC);
1489028fa281SKalle Valo 	val8 &= ~SYS_FUNC_BBRSTB;
1490028fa281SKalle Valo 	rtl8xxxu_write8(priv, REG_SYS_FUNC, val8);
1491028fa281SKalle Valo 
1492028fa281SKalle Valo 	udelay(2);
1493028fa281SKalle Valo 
1494028fa281SKalle Valo 	/* Whole BB is reset */
1495028fa281SKalle Valo 	val8 = rtl8xxxu_read8(priv, REG_SYS_FUNC);
1496028fa281SKalle Valo 	val8 &= ~SYS_FUNC_BB_GLB_RSTN;
1497028fa281SKalle Valo 	rtl8xxxu_write8(priv, REG_SYS_FUNC, val8);
1498028fa281SKalle Valo 
1499028fa281SKalle Valo 	/* Reset MAC TRX */
1500028fa281SKalle Valo 	val16 = rtl8xxxu_read16(priv, REG_CR);
1501028fa281SKalle Valo 	val16 |= 0x3f;
1502028fa281SKalle Valo 	val16 &= ~(CR_MAC_TX_ENABLE | CR_MAC_RX_ENABLE | CR_SECURITY_ENABLE);
1503028fa281SKalle Valo 	rtl8xxxu_write16(priv, REG_CR, val16);
1504028fa281SKalle Valo 
1505028fa281SKalle Valo 	/* Respond TxOK to scheduler */
1506028fa281SKalle Valo 	val8 = rtl8xxxu_read8(priv, REG_DUAL_TSF_RST);
1507028fa281SKalle Valo 	val8 |= DUAL_TSF_TX_OK;
1508028fa281SKalle Valo 	rtl8xxxu_write8(priv, REG_DUAL_TSF_RST, val8);
1509028fa281SKalle Valo 
1510028fa281SKalle Valo out:
1511028fa281SKalle Valo 	return retval;
1512028fa281SKalle Valo }
1513028fa281SKalle Valo 
rtl8188fu_power_on(struct rtl8xxxu_priv * priv)1514028fa281SKalle Valo static int rtl8188fu_power_on(struct rtl8xxxu_priv *priv)
1515028fa281SKalle Valo {
1516028fa281SKalle Valo 	u16 val16;
1517028fa281SKalle Valo 	int ret;
1518028fa281SKalle Valo 
1519028fa281SKalle Valo 	rtl8188f_disabled_to_emu(priv);
1520028fa281SKalle Valo 
1521028fa281SKalle Valo 	ret = rtl8188f_emu_to_active(priv);
1522028fa281SKalle Valo 	if (ret)
1523028fa281SKalle Valo 		goto exit;
1524028fa281SKalle Valo 
1525028fa281SKalle Valo 	rtl8xxxu_write8(priv, REG_CR, 0);
1526028fa281SKalle Valo 
1527028fa281SKalle Valo 	val16 = rtl8xxxu_read16(priv, REG_CR);
1528028fa281SKalle Valo 
1529028fa281SKalle Valo 	val16 |= (CR_HCI_TXDMA_ENABLE | CR_HCI_RXDMA_ENABLE |
1530028fa281SKalle Valo 		 CR_TXDMA_ENABLE | CR_RXDMA_ENABLE |
1531028fa281SKalle Valo 		 CR_PROTOCOL_ENABLE | CR_SCHEDULE_ENABLE |
1532028fa281SKalle Valo 		 CR_SECURITY_ENABLE | CR_CALTIMER_ENABLE);
1533028fa281SKalle Valo 	rtl8xxxu_write16(priv, REG_CR, val16);
1534028fa281SKalle Valo 
1535028fa281SKalle Valo exit:
1536028fa281SKalle Valo 	return ret;
1537028fa281SKalle Valo }
1538028fa281SKalle Valo 
rtl8188fu_power_off(struct rtl8xxxu_priv * priv)1539028fa281SKalle Valo static void rtl8188fu_power_off(struct rtl8xxxu_priv *priv)
1540028fa281SKalle Valo {
1541028fa281SKalle Valo 	u8 val8;
1542028fa281SKalle Valo 	u16 val16;
1543028fa281SKalle Valo 
1544028fa281SKalle Valo 	rtl8xxxu_flush_fifo(priv);
1545028fa281SKalle Valo 
1546028fa281SKalle Valo 	val16 = rtl8xxxu_read16(priv, REG_GPIO_MUXCFG);
1547028fa281SKalle Valo 	val16 &= ~BIT(12);
1548028fa281SKalle Valo 	rtl8xxxu_write16(priv, REG_GPIO_MUXCFG, val16);
1549028fa281SKalle Valo 
1550028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_HISR0, 0xFFFFFFFF);
1551028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_HISR1, 0xFFFFFFFF);
1552028fa281SKalle Valo 
1553028fa281SKalle Valo 	/* Stop Tx Report Timer. 0x4EC[Bit1]=b'0 */
1554028fa281SKalle Valo 	val8 = rtl8xxxu_read8(priv, REG_TX_REPORT_CTRL);
1555028fa281SKalle Valo 	val8 &= ~TX_REPORT_CTRL_TIMER_ENABLE;
1556028fa281SKalle Valo 	rtl8xxxu_write8(priv, REG_TX_REPORT_CTRL, val8);
1557028fa281SKalle Valo 
1558028fa281SKalle Valo 	/* Turn off RF */
1559028fa281SKalle Valo 	rtl8xxxu_write8(priv, REG_RF_CTRL, 0x00);
1560028fa281SKalle Valo 
1561028fa281SKalle Valo 	/* Reset Firmware if running in RAM */
1562028fa281SKalle Valo 	if (rtl8xxxu_read8(priv, REG_MCU_FW_DL) & MCU_FW_RAM_SEL)
1563028fa281SKalle Valo 		rtl8xxxu_firmware_self_reset(priv);
1564028fa281SKalle Valo 
1565028fa281SKalle Valo 	rtl8188fu_active_to_lps(priv);
1566028fa281SKalle Valo 
1567028fa281SKalle Valo 	/* Reset MCU */
1568028fa281SKalle Valo 	val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC);
1569028fa281SKalle Valo 	val16 &= ~SYS_FUNC_CPU_ENABLE;
1570028fa281SKalle Valo 	rtl8xxxu_write16(priv, REG_SYS_FUNC, val16);
1571028fa281SKalle Valo 
1572028fa281SKalle Valo 	/* Reset MCU ready status */
1573028fa281SKalle Valo 	rtl8xxxu_write8(priv, REG_MCU_FW_DL, 0x00);
1574028fa281SKalle Valo 
1575028fa281SKalle Valo 	rtl8188fu_active_to_emu(priv);
1576028fa281SKalle Valo 	rtl8188fu_emu_to_disabled(priv);
1577028fa281SKalle Valo }
1578028fa281SKalle Valo 
1579028fa281SKalle Valo #define PPG_BB_GAIN_2G_TXA_OFFSET_8188F 0xee
1580028fa281SKalle Valo #define PPG_BB_GAIN_2G_TX_OFFSET_MASK 0x0f
1581028fa281SKalle Valo 
rtl8188f_enable_rf(struct rtl8xxxu_priv * priv)1582028fa281SKalle Valo static void rtl8188f_enable_rf(struct rtl8xxxu_priv *priv)
1583028fa281SKalle Valo {
1584028fa281SKalle Valo 	u32 val32;
1585028fa281SKalle Valo 	u8 pg_pwrtrim = 0xff, val8;
1586028fa281SKalle Valo 	s8 bb_gain;
1587028fa281SKalle Valo 
1588028fa281SKalle Valo 	/* Somehow this is not found in the efuse we read earlier. */
1589028fa281SKalle Valo 	rtl8xxxu_read_efuse8(priv, PPG_BB_GAIN_2G_TXA_OFFSET_8188F, &pg_pwrtrim);
1590028fa281SKalle Valo 
1591028fa281SKalle Valo 	if (pg_pwrtrim != 0xff) {
1592028fa281SKalle Valo 		bb_gain = pg_pwrtrim & PPG_BB_GAIN_2G_TX_OFFSET_MASK;
1593028fa281SKalle Valo 
1594028fa281SKalle Valo 		if (bb_gain == PPG_BB_GAIN_2G_TX_OFFSET_MASK)
1595028fa281SKalle Valo 			bb_gain = 0;
1596028fa281SKalle Valo 		else if (bb_gain & 1)
1597028fa281SKalle Valo 			bb_gain = bb_gain >> 1;
1598028fa281SKalle Valo 		else
1599028fa281SKalle Valo 			bb_gain = -(bb_gain >> 1);
1600028fa281SKalle Valo 
1601028fa281SKalle Valo 		val8 = abs(bb_gain);
1602028fa281SKalle Valo 		if (bb_gain > 0)
1603028fa281SKalle Valo 			val8 |= BIT(5);
1604028fa281SKalle Valo 
1605028fa281SKalle Valo 		val32 = rtl8xxxu_read_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_55);
1606028fa281SKalle Valo 		val32 &= ~0xfc000;
1607028fa281SKalle Valo 		val32 |= val8 << 14;
1608028fa281SKalle Valo 		rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_UNKNOWN_55, val32);
1609028fa281SKalle Valo 	}
1610028fa281SKalle Valo 
1611028fa281SKalle Valo 	rtl8xxxu_write8(priv, REG_RF_CTRL, RF_ENABLE | RF_RSTB | RF_SDMRSTB);
1612028fa281SKalle Valo 
1613028fa281SKalle Valo 	val32 = rtl8xxxu_read32(priv, REG_OFDM0_TRX_PATH_ENABLE);
1614028fa281SKalle Valo 	val32 &= ~(OFDM_RF_PATH_RX_MASK | OFDM_RF_PATH_TX_MASK);
1615028fa281SKalle Valo 	val32 |= OFDM_RF_PATH_RX_A | OFDM_RF_PATH_TX_A;
1616028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, val32);
1617028fa281SKalle Valo 
1618028fa281SKalle Valo 	rtl8xxxu_write8(priv, REG_TXPAUSE, 0x00);
1619028fa281SKalle Valo }
1620028fa281SKalle Valo 
rtl8188f_disable_rf(struct rtl8xxxu_priv * priv)1621028fa281SKalle Valo static void rtl8188f_disable_rf(struct rtl8xxxu_priv *priv)
1622028fa281SKalle Valo {
1623028fa281SKalle Valo 	u32 val32;
1624028fa281SKalle Valo 
1625028fa281SKalle Valo 	val32 = rtl8xxxu_read32(priv, REG_OFDM0_TRX_PATH_ENABLE);
1626028fa281SKalle Valo 	val32 &= ~OFDM_RF_PATH_TX_MASK;
1627028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, val32);
1628028fa281SKalle Valo 
1629028fa281SKalle Valo 	/* Power down RF module */
1630028fa281SKalle Valo 	rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_AC, 0);
1631028fa281SKalle Valo }
1632028fa281SKalle Valo 
rtl8188f_usb_quirks(struct rtl8xxxu_priv * priv)1633028fa281SKalle Valo static void rtl8188f_usb_quirks(struct rtl8xxxu_priv *priv)
1634028fa281SKalle Valo {
1635028fa281SKalle Valo 	u16 val16;
1636028fa281SKalle Valo 	u32 val32;
1637028fa281SKalle Valo 
1638028fa281SKalle Valo 	val16 = rtl8xxxu_read16(priv, REG_CR);
1639028fa281SKalle Valo 	val16 |= (CR_MAC_TX_ENABLE | CR_MAC_RX_ENABLE);
1640028fa281SKalle Valo 	rtl8xxxu_write16(priv, REG_CR, val16);
1641028fa281SKalle Valo 
1642028fa281SKalle Valo 	val32 = rtl8xxxu_read32(priv, REG_TXDMA_OFFSET_CHK);
1643028fa281SKalle Valo 	val32 |= TXDMA_OFFSET_DROP_DATA_EN;
1644028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_TXDMA_OFFSET_CHK, val32);
1645028fa281SKalle Valo }
1646028fa281SKalle Valo 
1647028fa281SKalle Valo #define XTAL1	GENMASK(22, 17)
1648028fa281SKalle Valo #define XTAL0	GENMASK(16, 11)
1649028fa281SKalle Valo 
rtl8188f_set_crystal_cap(struct rtl8xxxu_priv * priv,u8 crystal_cap)1650028fa281SKalle Valo void rtl8188f_set_crystal_cap(struct rtl8xxxu_priv *priv, u8 crystal_cap)
1651028fa281SKalle Valo {
1652028fa281SKalle Valo 	struct rtl8xxxu_cfo_tracking *cfo = &priv->cfo_tracking;
1653028fa281SKalle Valo 	u32 val32;
1654028fa281SKalle Valo 
1655028fa281SKalle Valo 	if (crystal_cap == cfo->crystal_cap)
1656028fa281SKalle Valo 		return;
1657028fa281SKalle Valo 
1658028fa281SKalle Valo 	val32 = rtl8xxxu_read32(priv, REG_AFE_XTAL_CTRL);
1659028fa281SKalle Valo 
1660028fa281SKalle Valo 	dev_dbg(&priv->udev->dev,
1661028fa281SKalle Valo 	        "%s: Adjusting crystal cap from 0x%x (actually 0x%lx 0x%lx) to 0x%x\n",
1662028fa281SKalle Valo 	        __func__,
1663028fa281SKalle Valo 	        cfo->crystal_cap,
1664028fa281SKalle Valo 	        FIELD_GET(XTAL1, val32),
1665028fa281SKalle Valo 	        FIELD_GET(XTAL0, val32),
1666028fa281SKalle Valo 	        crystal_cap);
1667028fa281SKalle Valo 
1668028fa281SKalle Valo 	val32 &= ~(XTAL1 | XTAL0);
1669028fa281SKalle Valo 	val32 |= FIELD_PREP(XTAL1, crystal_cap) |
1670028fa281SKalle Valo 		 FIELD_PREP(XTAL0, crystal_cap);
1671028fa281SKalle Valo 	rtl8xxxu_write32(priv, REG_AFE_XTAL_CTRL, val32);
1672028fa281SKalle Valo 
1673028fa281SKalle Valo 	cfo->crystal_cap = crystal_cap;
1674028fa281SKalle Valo }
1675028fa281SKalle Valo 
rtl8188f_cck_rssi(struct rtl8xxxu_priv * priv,struct rtl8723au_phy_stats * phy_stats)1676028fa281SKalle Valo static s8 rtl8188f_cck_rssi(struct rtl8xxxu_priv *priv, struct rtl8723au_phy_stats *phy_stats)
1677028fa281SKalle Valo {
1678028fa281SKalle Valo 	u8 cck_agc_rpt = phy_stats->cck_agc_rpt_ofdm_cfosho_a;
1679028fa281SKalle Valo 	s8 rx_pwr_all = 0x00;
1680028fa281SKalle Valo 	u8 vga_idx, lna_idx;
1681028fa281SKalle Valo 
1682028fa281SKalle Valo 	lna_idx = u8_get_bits(cck_agc_rpt, CCK_AGC_RPT_LNA_IDX_MASK);
1683028fa281SKalle Valo 	vga_idx = u8_get_bits(cck_agc_rpt, CCK_AGC_RPT_VGA_IDX_MASK);
1684028fa281SKalle Valo 
1685028fa281SKalle Valo 	switch (lna_idx) {
1686028fa281SKalle Valo 	case 7:
1687028fa281SKalle Valo 		if (vga_idx <= 27)
1688028fa281SKalle Valo 			rx_pwr_all = -100 + 2 * (27 - vga_idx);
1689028fa281SKalle Valo 		else
1690028fa281SKalle Valo 			rx_pwr_all = -100;
1691028fa281SKalle Valo 		break;
1692028fa281SKalle Valo 	case 5:
1693028fa281SKalle Valo 		rx_pwr_all = -74 + 2 * (21 - vga_idx);
1694028fa281SKalle Valo 		break;
1695028fa281SKalle Valo 	case 3:
1696028fa281SKalle Valo 		rx_pwr_all = -60 + 2 * (20 - vga_idx);
1697028fa281SKalle Valo 		break;
1698028fa281SKalle Valo 	case 1:
1699028fa281SKalle Valo 		rx_pwr_all = -44 + 2 * (19 - vga_idx);
1700028fa281SKalle Valo 		break;
1701028fa281SKalle Valo 	default:
1702028fa281SKalle Valo 		break;
1703028fa281SKalle Valo 	}
1704028fa281SKalle Valo 
1705028fa281SKalle Valo 	return rx_pwr_all;
1706028fa281SKalle Valo }
1707028fa281SKalle Valo 
1708028fa281SKalle Valo struct rtl8xxxu_fileops rtl8188fu_fops = {
1709028fa281SKalle Valo 	.identify_chip = rtl8188fu_identify_chip,
1710028fa281SKalle Valo 	.parse_efuse = rtl8188fu_parse_efuse,
1711028fa281SKalle Valo 	.load_firmware = rtl8188fu_load_firmware,
1712028fa281SKalle Valo 	.power_on = rtl8188fu_power_on,
1713028fa281SKalle Valo 	.power_off = rtl8188fu_power_off,
1714028fa281SKalle Valo 	.read_efuse = rtl8xxxu_read_efuse,
1715028fa281SKalle Valo 	.reset_8051 = rtl8xxxu_reset_8051,
1716028fa281SKalle Valo 	.llt_init = rtl8xxxu_auto_llt_table,
1717028fa281SKalle Valo 	.init_phy_bb = rtl8188fu_init_phy_bb,
1718028fa281SKalle Valo 	.init_phy_rf = rtl8188fu_init_phy_rf,
1719028fa281SKalle Valo 	.phy_init_antenna_selection = rtl8723bu_phy_init_antenna_selection,
1720028fa281SKalle Valo 	.phy_lc_calibrate = rtl8188f_phy_lc_calibrate,
1721028fa281SKalle Valo 	.phy_iq_calibrate = rtl8188fu_phy_iq_calibrate,
1722028fa281SKalle Valo 	.config_channel = rtl8188fu_config_channel,
1723028fa281SKalle Valo 	.parse_rx_desc = rtl8xxxu_parse_rxdesc24,
1724028fa281SKalle Valo 	.parse_phystats = rtl8723au_rx_parse_phystats,
1725028fa281SKalle Valo 	.init_aggregation = rtl8188fu_init_aggregation,
1726028fa281SKalle Valo 	.init_statistics = rtl8188fu_init_statistics,
1727028fa281SKalle Valo 	.init_burst = rtl8xxxu_init_burst,
1728028fa281SKalle Valo 	.enable_rf = rtl8188f_enable_rf,
1729028fa281SKalle Valo 	.disable_rf = rtl8188f_disable_rf,
1730028fa281SKalle Valo 	.usb_quirks = rtl8188f_usb_quirks,
1731028fa281SKalle Valo 	.set_tx_power = rtl8188f_set_tx_power,
1732028fa281SKalle Valo 	.update_rate_mask = rtl8xxxu_gen2_update_rate_mask,
1733028fa281SKalle Valo 	.report_connect = rtl8xxxu_gen2_report_connect,
1734028fa281SKalle Valo 	.report_rssi = rtl8xxxu_gen2_report_rssi,
1735028fa281SKalle Valo 	.fill_txdesc = rtl8xxxu_fill_txdesc_v2,
1736028fa281SKalle Valo 	.set_crystal_cap = rtl8188f_set_crystal_cap,
1737028fa281SKalle Valo 	.cck_rssi = rtl8188f_cck_rssi,
1738028fa281SKalle Valo 	.writeN_block_size = 128,
1739028fa281SKalle Valo 	.rx_desc_size = sizeof(struct rtl8xxxu_rxdesc24),
1740028fa281SKalle Valo 	.tx_desc_size = sizeof(struct rtl8xxxu_txdesc40),
1741028fa281SKalle Valo 	.has_s0s1 = 1,
1742028fa281SKalle Valo 	.has_tx_report = 1,
1743028fa281SKalle Valo 	.gen2_thermal_meter = 1,
1744028fa281SKalle Valo 	.needs_full_init = 1,
1745028fa281SKalle Valo 	.init_reg_rxfltmap = 1,
1746028fa281SKalle Valo 	.init_reg_pkt_life_time = 1,
1747028fa281SKalle Valo 	.init_reg_hmtfr = 1,
1748028fa281SKalle Valo 	.ampdu_max_time = 0x70,
1749028fa281SKalle Valo 	.ustime_tsf_edca = 0x28,
1750028fa281SKalle Valo 	.max_aggr_num = 0x0c14,
1751028fa281SKalle Valo 	.supports_ap = 1,
1752028fa281SKalle Valo 	.max_macid_num = 16,
1753028fa281SKalle Valo 	.max_sec_cam_num = 16,
1754028fa281SKalle Valo 	.supports_concurrent = 1,
1755028fa281SKalle Valo 	.adda_1t_init = 0x03c00014,
1756028fa281SKalle Valo 	.adda_1t_path_on = 0x03c00014,
1757028fa281SKalle Valo 	.trxff_boundary = 0x3f7f,
1758028fa281SKalle Valo 	.pbp_rx = PBP_PAGE_SIZE_256,
1759028fa281SKalle Valo 	.pbp_tx = PBP_PAGE_SIZE_256,
1760028fa281SKalle Valo 	.mactable = rtl8188f_mac_init_table,
1761028fa281SKalle Valo 	.total_page_num = TX_TOTAL_PAGE_NUM_8188F,
1762028fa281SKalle Valo 	.page_num_hi = TX_PAGE_NUM_HI_PQ_8188F,
1763028fa281SKalle Valo 	.page_num_lo = TX_PAGE_NUM_LO_PQ_8188F,
1764028fa281SKalle Valo 	.page_num_norm = TX_PAGE_NUM_NORM_PQ_8188F,
1765028fa281SKalle Valo };
1766