xref: /openbmc/linux/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
15b497af4SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2599119f6SJes Sorensen /*
3599119f6SJes Sorensen  * RTL8XXXU mac80211 USB driver - 8192e specific subdriver
4599119f6SJes Sorensen  *
51ee83789SJes Sorensen  * Copyright (c) 2014 - 2017 Jes Sorensen <Jes.Sorensen@gmail.com>
6599119f6SJes Sorensen  *
7599119f6SJes Sorensen  * Portions, notably calibration code:
8599119f6SJes Sorensen  * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
9599119f6SJes Sorensen  *
10599119f6SJes Sorensen  * This driver was written as a replacement for the vendor provided
11599119f6SJes Sorensen  * rtl8723au driver. As the Realtek 8xxx chips are very similar in
12599119f6SJes Sorensen  * their programming interface, I have started adding support for
13599119f6SJes Sorensen  * additional 8xxx chips like the 8192cu, 8188cus, etc.
14599119f6SJes Sorensen  */
15599119f6SJes Sorensen 
16599119f6SJes Sorensen #include <linux/init.h>
17599119f6SJes Sorensen #include <linux/kernel.h>
18599119f6SJes Sorensen #include <linux/sched.h>
19599119f6SJes Sorensen #include <linux/errno.h>
20599119f6SJes Sorensen #include <linux/slab.h>
21599119f6SJes Sorensen #include <linux/module.h>
22599119f6SJes Sorensen #include <linux/spinlock.h>
23599119f6SJes Sorensen #include <linux/list.h>
24599119f6SJes Sorensen #include <linux/usb.h>
25599119f6SJes Sorensen #include <linux/netdevice.h>
26599119f6SJes Sorensen #include <linux/etherdevice.h>
27599119f6SJes Sorensen #include <linux/ethtool.h>
28599119f6SJes Sorensen #include <linux/wireless.h>
29599119f6SJes Sorensen #include <linux/firmware.h>
30599119f6SJes Sorensen #include <linux/moduleparam.h>
31599119f6SJes Sorensen #include <net/mac80211.h>
32599119f6SJes Sorensen #include "rtl8xxxu.h"
33599119f6SJes Sorensen #include "rtl8xxxu_regs.h"
34599119f6SJes Sorensen 
3579cac25eSBitterblue Smith static const struct rtl8xxxu_reg8val rtl8192e_mac_init_table[] = {
36599119f6SJes Sorensen 	{0x011, 0xeb}, {0x012, 0x07}, {0x014, 0x75}, {0x303, 0xa7},
37599119f6SJes Sorensen 	{0x428, 0x0a}, {0x429, 0x10}, {0x430, 0x00}, {0x431, 0x00},
38599119f6SJes Sorensen 	{0x432, 0x00}, {0x433, 0x01}, {0x434, 0x04}, {0x435, 0x05},
39599119f6SJes Sorensen 	{0x436, 0x07}, {0x437, 0x08}, {0x43c, 0x04}, {0x43d, 0x05},
40599119f6SJes Sorensen 	{0x43e, 0x07}, {0x43f, 0x08}, {0x440, 0x5d}, {0x441, 0x01},
41599119f6SJes Sorensen 	{0x442, 0x00}, {0x444, 0x10}, {0x445, 0x00}, {0x446, 0x00},
42599119f6SJes Sorensen 	{0x447, 0x00}, {0x448, 0x00}, {0x449, 0xf0}, {0x44a, 0x0f},
43599119f6SJes Sorensen 	{0x44b, 0x3e}, {0x44c, 0x10}, {0x44d, 0x00}, {0x44e, 0x00},
44599119f6SJes Sorensen 	{0x44f, 0x00}, {0x450, 0x00}, {0x451, 0xf0}, {0x452, 0x0f},
45599119f6SJes Sorensen 	{0x453, 0x00}, {0x456, 0x5e}, {0x460, 0x66}, {0x461, 0x66},
46599119f6SJes Sorensen 	{0x4c8, 0xff}, {0x4c9, 0x08}, {0x4cc, 0xff}, {0x4cd, 0xff},
47599119f6SJes Sorensen 	{0x4ce, 0x01}, {0x500, 0x26}, {0x501, 0xa2}, {0x502, 0x2f},
48599119f6SJes Sorensen 	{0x503, 0x00}, {0x504, 0x28}, {0x505, 0xa3}, {0x506, 0x5e},
49599119f6SJes Sorensen 	{0x507, 0x00}, {0x508, 0x2b}, {0x509, 0xa4}, {0x50a, 0x5e},
50599119f6SJes Sorensen 	{0x50b, 0x00}, {0x50c, 0x4f}, {0x50d, 0xa4}, {0x50e, 0x00},
51599119f6SJes Sorensen 	{0x50f, 0x00}, {0x512, 0x1c}, {0x514, 0x0a}, {0x516, 0x0a},
52599119f6SJes Sorensen 	{0x525, 0x4f}, {0x540, 0x12}, {0x541, 0x64}, {0x550, 0x10},
53599119f6SJes Sorensen 	{0x551, 0x10}, {0x559, 0x02}, {0x55c, 0x50}, {0x55d, 0xff},
54599119f6SJes Sorensen 	{0x605, 0x30}, {0x608, 0x0e}, {0x609, 0x2a}, {0x620, 0xff},
55599119f6SJes Sorensen 	{0x621, 0xff}, {0x622, 0xff}, {0x623, 0xff}, {0x624, 0xff},
56599119f6SJes Sorensen 	{0x625, 0xff}, {0x626, 0xff}, {0x627, 0xff}, {0x638, 0x50},
57599119f6SJes Sorensen 	{0x63c, 0x0a}, {0x63d, 0x0a}, {0x63e, 0x0e}, {0x63f, 0x0e},
58599119f6SJes Sorensen 	{0x640, 0x40}, {0x642, 0x40}, {0x643, 0x00}, {0x652, 0xc8},
59599119f6SJes Sorensen 	{0x66e, 0x05}, {0x700, 0x21}, {0x701, 0x43}, {0x702, 0x65},
60599119f6SJes Sorensen 	{0x703, 0x87}, {0x708, 0x21}, {0x709, 0x43}, {0x70a, 0x65},
61599119f6SJes Sorensen 	{0x70b, 0x87},
62599119f6SJes Sorensen 	{0xffff, 0xff},
63599119f6SJes Sorensen };
64599119f6SJes Sorensen 
6579cac25eSBitterblue Smith static const struct rtl8xxxu_reg32val rtl8192eu_phy_init_table[] = {
66599119f6SJes Sorensen 	{0x800, 0x80040000}, {0x804, 0x00000003},
67599119f6SJes Sorensen 	{0x808, 0x0000fc00}, {0x80c, 0x0000000a},
68599119f6SJes Sorensen 	{0x810, 0x10001331}, {0x814, 0x020c3d10},
69599119f6SJes Sorensen 	{0x818, 0x02220385}, {0x81c, 0x00000000},
70599119f6SJes Sorensen 	{0x820, 0x01000100}, {0x824, 0x00390204},
71599119f6SJes Sorensen 	{0x828, 0x01000100}, {0x82c, 0x00390204},
72599119f6SJes Sorensen 	{0x830, 0x32323232}, {0x834, 0x30303030},
73599119f6SJes Sorensen 	{0x838, 0x30303030}, {0x83c, 0x30303030},
74599119f6SJes Sorensen 	{0x840, 0x00010000}, {0x844, 0x00010000},
75599119f6SJes Sorensen 	{0x848, 0x28282828}, {0x84c, 0x28282828},
76599119f6SJes Sorensen 	{0x850, 0x00000000}, {0x854, 0x00000000},
77599119f6SJes Sorensen 	{0x858, 0x009a009a}, {0x85c, 0x01000014},
78599119f6SJes Sorensen 	{0x860, 0x66f60000}, {0x864, 0x061f0000},
79599119f6SJes Sorensen 	{0x868, 0x30303030}, {0x86c, 0x30303030},
80599119f6SJes Sorensen 	{0x870, 0x00000000}, {0x874, 0x55004200},
81599119f6SJes Sorensen 	{0x878, 0x08080808}, {0x87c, 0x00000000},
82599119f6SJes Sorensen 	{0x880, 0xb0000c1c}, {0x884, 0x00000001},
83599119f6SJes Sorensen 	{0x888, 0x00000000}, {0x88c, 0xcc0000c0},
84599119f6SJes Sorensen 	{0x890, 0x00000800}, {0x894, 0xfffffffe},
85599119f6SJes Sorensen 	{0x898, 0x40302010}, {0x900, 0x00000000},
86599119f6SJes Sorensen 	{0x904, 0x00000023}, {0x908, 0x00000000},
87599119f6SJes Sorensen 	{0x90c, 0x81121313}, {0x910, 0x806c0001},
88599119f6SJes Sorensen 	{0x914, 0x00000001}, {0x918, 0x00000000},
89599119f6SJes Sorensen 	{0x91c, 0x00010000}, {0x924, 0x00000001},
90599119f6SJes Sorensen 	{0x928, 0x00000000}, {0x92c, 0x00000000},
91599119f6SJes Sorensen 	{0x930, 0x00000000}, {0x934, 0x00000000},
92599119f6SJes Sorensen 	{0x938, 0x00000000}, {0x93c, 0x00000000},
93599119f6SJes Sorensen 	{0x940, 0x00000000}, {0x944, 0x00000000},
94599119f6SJes Sorensen 	{0x94c, 0x00000008}, {0xa00, 0x00d0c7c8},
95599119f6SJes Sorensen 	{0xa04, 0x81ff000c}, {0xa08, 0x8c838300},
96599119f6SJes Sorensen 	{0xa0c, 0x2e68120f}, {0xa10, 0x95009b78},
97599119f6SJes Sorensen 	{0xa14, 0x1114d028}, {0xa18, 0x00881117},
98599119f6SJes Sorensen 	{0xa1c, 0x89140f00}, {0xa20, 0x1a1b0000},
99599119f6SJes Sorensen 	{0xa24, 0x090e1317}, {0xa28, 0x00000204},
100599119f6SJes Sorensen 	{0xa2c, 0x00d30000}, {0xa70, 0x101fff00},
101599119f6SJes Sorensen 	{0xa74, 0x00000007}, {0xa78, 0x00000900},
102599119f6SJes Sorensen 	{0xa7c, 0x225b0606}, {0xa80, 0x218075b1},
103599119f6SJes Sorensen 	{0xb38, 0x00000000}, {0xc00, 0x48071d40},
104599119f6SJes Sorensen 	{0xc04, 0x03a05633}, {0xc08, 0x000000e4},
105599119f6SJes Sorensen 	{0xc0c, 0x6c6c6c6c}, {0xc10, 0x08800000},
106599119f6SJes Sorensen 	{0xc14, 0x40000100}, {0xc18, 0x08800000},
107599119f6SJes Sorensen 	{0xc1c, 0x40000100}, {0xc20, 0x00000000},
108599119f6SJes Sorensen 	{0xc24, 0x00000000}, {0xc28, 0x00000000},
109599119f6SJes Sorensen 	{0xc2c, 0x00000000}, {0xc30, 0x69e9ac47},
110599119f6SJes Sorensen 	{0xc34, 0x469652af}, {0xc38, 0x49795994},
111599119f6SJes Sorensen 	{0xc3c, 0x0a97971c}, {0xc40, 0x1f7c403f},
112599119f6SJes Sorensen 	{0xc44, 0x000100b7}, {0xc48, 0xec020107},
113599119f6SJes Sorensen 	{0xc4c, 0x007f037f},
114599119f6SJes Sorensen #ifdef EXT_PA_8192EU
115599119f6SJes Sorensen 	/* External PA or external LNA */
116599119f6SJes Sorensen 	{0xc50, 0x00340220},
117599119f6SJes Sorensen #else
118599119f6SJes Sorensen 	{0xc50, 0x00340020},
119599119f6SJes Sorensen #endif
120599119f6SJes Sorensen 	{0xc54, 0x0080801f},
121599119f6SJes Sorensen #ifdef EXT_PA_8192EU
122599119f6SJes Sorensen 	/* External PA or external LNA */
123599119f6SJes Sorensen 	{0xc58, 0x00000220},
124599119f6SJes Sorensen #else
125599119f6SJes Sorensen 	{0xc58, 0x00000020},
126599119f6SJes Sorensen #endif
127599119f6SJes Sorensen 	{0xc5c, 0x00248492}, {0xc60, 0x00000000},
128599119f6SJes Sorensen 	{0xc64, 0x7112848b}, {0xc68, 0x47c00bff},
129599119f6SJes Sorensen 	{0xc6c, 0x00000036}, {0xc70, 0x00000600},
130599119f6SJes Sorensen 	{0xc74, 0x02013169}, {0xc78, 0x0000001f},
131599119f6SJes Sorensen 	{0xc7c, 0x00b91612},
132599119f6SJes Sorensen #ifdef EXT_PA_8192EU
133599119f6SJes Sorensen 	/* External PA or external LNA */
134599119f6SJes Sorensen 	{0xc80, 0x2d4000b5},
135599119f6SJes Sorensen #else
136599119f6SJes Sorensen 	{0xc80, 0x40000100},
137599119f6SJes Sorensen #endif
138599119f6SJes Sorensen 	{0xc84, 0x21f60000},
139599119f6SJes Sorensen #ifdef EXT_PA_8192EU
140599119f6SJes Sorensen 	/* External PA or external LNA */
141599119f6SJes Sorensen 	{0xc88, 0x2d4000b5},
142599119f6SJes Sorensen #else
143599119f6SJes Sorensen 	{0xc88, 0x40000100},
144599119f6SJes Sorensen #endif
145599119f6SJes Sorensen 	{0xc8c, 0xa0e40000}, {0xc90, 0x00121820},
146599119f6SJes Sorensen 	{0xc94, 0x00000000}, {0xc98, 0x00121820},
147599119f6SJes Sorensen 	{0xc9c, 0x00007f7f}, {0xca0, 0x00000000},
148599119f6SJes Sorensen 	{0xca4, 0x000300a0}, {0xca8, 0x00000000},
149599119f6SJes Sorensen 	{0xcac, 0x00000000}, {0xcb0, 0x00000000},
150599119f6SJes Sorensen 	{0xcb4, 0x00000000}, {0xcb8, 0x00000000},
151599119f6SJes Sorensen 	{0xcbc, 0x28000000}, {0xcc0, 0x00000000},
152599119f6SJes Sorensen 	{0xcc4, 0x00000000}, {0xcc8, 0x00000000},
153599119f6SJes Sorensen 	{0xccc, 0x00000000}, {0xcd0, 0x00000000},
154599119f6SJes Sorensen 	{0xcd4, 0x00000000}, {0xcd8, 0x64b22427},
155599119f6SJes Sorensen 	{0xcdc, 0x00766932}, {0xce0, 0x00222222},
156599119f6SJes Sorensen 	{0xce4, 0x00040000}, {0xce8, 0x77644302},
157599119f6SJes Sorensen 	{0xcec, 0x2f97d40c}, {0xd00, 0x00080740},
158599119f6SJes Sorensen 	{0xd04, 0x00020403}, {0xd08, 0x0000907f},
159599119f6SJes Sorensen 	{0xd0c, 0x20010201}, {0xd10, 0xa0633333},
160599119f6SJes Sorensen 	{0xd14, 0x3333bc43}, {0xd18, 0x7a8f5b6b},
161599119f6SJes Sorensen 	{0xd1c, 0x0000007f}, {0xd2c, 0xcc979975},
162599119f6SJes Sorensen 	{0xd30, 0x00000000}, {0xd34, 0x80608000},
163599119f6SJes Sorensen 	{0xd38, 0x00000000}, {0xd3c, 0x00127353},
164599119f6SJes Sorensen 	{0xd40, 0x00000000}, {0xd44, 0x00000000},
165599119f6SJes Sorensen 	{0xd48, 0x00000000}, {0xd4c, 0x00000000},
166599119f6SJes Sorensen 	{0xd50, 0x6437140a}, {0xd54, 0x00000000},
167599119f6SJes Sorensen 	{0xd58, 0x00000282}, {0xd5c, 0x30032064},
168599119f6SJes Sorensen 	{0xd60, 0x4653de68}, {0xd64, 0x04518a3c},
169599119f6SJes Sorensen 	{0xd68, 0x00002101}, {0xd6c, 0x2a201c16},
170599119f6SJes Sorensen 	{0xd70, 0x1812362e}, {0xd74, 0x322c2220},
171599119f6SJes Sorensen 	{0xd78, 0x000e3c24}, {0xd80, 0x01081008},
172599119f6SJes Sorensen 	{0xd84, 0x00000800}, {0xd88, 0xf0b50000},
173599119f6SJes Sorensen 	{0xe00, 0x30303030}, {0xe04, 0x30303030},
174599119f6SJes Sorensen 	{0xe08, 0x03903030}, {0xe10, 0x30303030},
175599119f6SJes Sorensen 	{0xe14, 0x30303030}, {0xe18, 0x30303030},
176599119f6SJes Sorensen 	{0xe1c, 0x30303030}, {0xe28, 0x00000000},
177599119f6SJes Sorensen 	{0xe30, 0x1000dc1f}, {0xe34, 0x10008c1f},
178599119f6SJes Sorensen 	{0xe38, 0x02140102}, {0xe3c, 0x681604c2},
179599119f6SJes Sorensen 	{0xe40, 0x01007c00}, {0xe44, 0x01004800},
180599119f6SJes Sorensen 	{0xe48, 0xfb000000}, {0xe4c, 0x000028d1},
181599119f6SJes Sorensen 	{0xe50, 0x1000dc1f}, {0xe54, 0x10008c1f},
182599119f6SJes Sorensen 	{0xe58, 0x02140102}, {0xe5c, 0x28160d05},
183599119f6SJes Sorensen 	{0xe60, 0x00000008}, {0xe68, 0x0fc05656},
184599119f6SJes Sorensen 	{0xe6c, 0x03c09696}, {0xe70, 0x03c09696},
185599119f6SJes Sorensen 	{0xe74, 0x0c005656}, {0xe78, 0x0c005656},
186599119f6SJes Sorensen 	{0xe7c, 0x0c005656}, {0xe80, 0x0c005656},
187599119f6SJes Sorensen 	{0xe84, 0x03c09696}, {0xe88, 0x0c005656},
188599119f6SJes Sorensen 	{0xe8c, 0x03c09696}, {0xed0, 0x03c09696},
189599119f6SJes Sorensen 	{0xed4, 0x03c09696}, {0xed8, 0x03c09696},
190599119f6SJes Sorensen 	{0xedc, 0x0000d6d6}, {0xee0, 0x0000d6d6},
191599119f6SJes Sorensen 	{0xeec, 0x0fc01616}, {0xee4, 0xb0000c1c},
192599119f6SJes Sorensen 	{0xee8, 0x00000001}, {0xf14, 0x00000003},
193599119f6SJes Sorensen 	{0xf4c, 0x00000000}, {0xf00, 0x00000300},
194599119f6SJes Sorensen 	{0xffff, 0xffffffff},
195599119f6SJes Sorensen };
196599119f6SJes Sorensen 
19779cac25eSBitterblue Smith static const struct rtl8xxxu_reg32val rtl8xxx_agc_8192eu_std_table[] = {
198599119f6SJes Sorensen 	{0xc78, 0xfb000001}, {0xc78, 0xfb010001},
199599119f6SJes Sorensen 	{0xc78, 0xfb020001}, {0xc78, 0xfb030001},
200599119f6SJes Sorensen 	{0xc78, 0xfb040001}, {0xc78, 0xfb050001},
201599119f6SJes Sorensen 	{0xc78, 0xfa060001}, {0xc78, 0xf9070001},
202599119f6SJes Sorensen 	{0xc78, 0xf8080001}, {0xc78, 0xf7090001},
203599119f6SJes Sorensen 	{0xc78, 0xf60a0001}, {0xc78, 0xf50b0001},
204599119f6SJes Sorensen 	{0xc78, 0xf40c0001}, {0xc78, 0xf30d0001},
205599119f6SJes Sorensen 	{0xc78, 0xf20e0001}, {0xc78, 0xf10f0001},
206599119f6SJes Sorensen 	{0xc78, 0xf0100001}, {0xc78, 0xef110001},
207599119f6SJes Sorensen 	{0xc78, 0xee120001}, {0xc78, 0xed130001},
208599119f6SJes Sorensen 	{0xc78, 0xec140001}, {0xc78, 0xeb150001},
209599119f6SJes Sorensen 	{0xc78, 0xea160001}, {0xc78, 0xe9170001},
210599119f6SJes Sorensen 	{0xc78, 0xe8180001}, {0xc78, 0xe7190001},
211599119f6SJes Sorensen 	{0xc78, 0xc81a0001}, {0xc78, 0xc71b0001},
212599119f6SJes Sorensen 	{0xc78, 0xc61c0001}, {0xc78, 0x071d0001},
213599119f6SJes Sorensen 	{0xc78, 0x061e0001}, {0xc78, 0x051f0001},
214599119f6SJes Sorensen 	{0xc78, 0x04200001}, {0xc78, 0x03210001},
215599119f6SJes Sorensen 	{0xc78, 0xaa220001}, {0xc78, 0xa9230001},
216599119f6SJes Sorensen 	{0xc78, 0xa8240001}, {0xc78, 0xa7250001},
217599119f6SJes Sorensen 	{0xc78, 0xa6260001}, {0xc78, 0x85270001},
218599119f6SJes Sorensen 	{0xc78, 0x84280001}, {0xc78, 0x83290001},
219599119f6SJes Sorensen 	{0xc78, 0x252a0001}, {0xc78, 0x242b0001},
220599119f6SJes Sorensen 	{0xc78, 0x232c0001}, {0xc78, 0x222d0001},
221599119f6SJes Sorensen 	{0xc78, 0x672e0001}, {0xc78, 0x662f0001},
222599119f6SJes Sorensen 	{0xc78, 0x65300001}, {0xc78, 0x64310001},
223599119f6SJes Sorensen 	{0xc78, 0x63320001}, {0xc78, 0x62330001},
224599119f6SJes Sorensen 	{0xc78, 0x61340001}, {0xc78, 0x45350001},
225599119f6SJes Sorensen 	{0xc78, 0x44360001}, {0xc78, 0x43370001},
226599119f6SJes Sorensen 	{0xc78, 0x42380001}, {0xc78, 0x41390001},
227599119f6SJes Sorensen 	{0xc78, 0x403a0001}, {0xc78, 0x403b0001},
228599119f6SJes Sorensen 	{0xc78, 0x403c0001}, {0xc78, 0x403d0001},
229599119f6SJes Sorensen 	{0xc78, 0x403e0001}, {0xc78, 0x403f0001},
230599119f6SJes Sorensen 	{0xc78, 0xfb400001}, {0xc78, 0xfb410001},
231599119f6SJes Sorensen 	{0xc78, 0xfb420001}, {0xc78, 0xfb430001},
232599119f6SJes Sorensen 	{0xc78, 0xfb440001}, {0xc78, 0xfb450001},
233599119f6SJes Sorensen 	{0xc78, 0xfa460001}, {0xc78, 0xf9470001},
234599119f6SJes Sorensen 	{0xc78, 0xf8480001}, {0xc78, 0xf7490001},
235599119f6SJes Sorensen 	{0xc78, 0xf64a0001}, {0xc78, 0xf54b0001},
236599119f6SJes Sorensen 	{0xc78, 0xf44c0001}, {0xc78, 0xf34d0001},
237599119f6SJes Sorensen 	{0xc78, 0xf24e0001}, {0xc78, 0xf14f0001},
238599119f6SJes Sorensen 	{0xc78, 0xf0500001}, {0xc78, 0xef510001},
239599119f6SJes Sorensen 	{0xc78, 0xee520001}, {0xc78, 0xed530001},
240599119f6SJes Sorensen 	{0xc78, 0xec540001}, {0xc78, 0xeb550001},
241599119f6SJes Sorensen 	{0xc78, 0xea560001}, {0xc78, 0xe9570001},
242599119f6SJes Sorensen 	{0xc78, 0xe8580001}, {0xc78, 0xe7590001},
243599119f6SJes Sorensen 	{0xc78, 0xe65a0001}, {0xc78, 0xe55b0001},
244599119f6SJes Sorensen 	{0xc78, 0xe45c0001}, {0xc78, 0xe35d0001},
245599119f6SJes Sorensen 	{0xc78, 0xe25e0001}, {0xc78, 0xe15f0001},
246599119f6SJes Sorensen 	{0xc78, 0x8a600001}, {0xc78, 0x89610001},
247599119f6SJes Sorensen 	{0xc78, 0x88620001}, {0xc78, 0x87630001},
248599119f6SJes Sorensen 	{0xc78, 0x86640001}, {0xc78, 0x85650001},
249599119f6SJes Sorensen 	{0xc78, 0x84660001}, {0xc78, 0x83670001},
250599119f6SJes Sorensen 	{0xc78, 0x82680001}, {0xc78, 0x6b690001},
251599119f6SJes Sorensen 	{0xc78, 0x6a6a0001}, {0xc78, 0x696b0001},
252599119f6SJes Sorensen 	{0xc78, 0x686c0001}, {0xc78, 0x676d0001},
253599119f6SJes Sorensen 	{0xc78, 0x666e0001}, {0xc78, 0x656f0001},
254599119f6SJes Sorensen 	{0xc78, 0x64700001}, {0xc78, 0x63710001},
255599119f6SJes Sorensen 	{0xc78, 0x62720001}, {0xc78, 0x61730001},
256599119f6SJes Sorensen 	{0xc78, 0x49740001}, {0xc78, 0x48750001},
257599119f6SJes Sorensen 	{0xc78, 0x47760001}, {0xc78, 0x46770001},
258599119f6SJes Sorensen 	{0xc78, 0x45780001}, {0xc78, 0x44790001},
259599119f6SJes Sorensen 	{0xc78, 0x437a0001}, {0xc78, 0x427b0001},
260599119f6SJes Sorensen 	{0xc78, 0x417c0001}, {0xc78, 0x407d0001},
261599119f6SJes Sorensen 	{0xc78, 0x407e0001}, {0xc78, 0x407f0001},
262599119f6SJes Sorensen 	{0xc50, 0x00040022}, {0xc50, 0x00040020},
263599119f6SJes Sorensen 	{0xffff, 0xffffffff}
264599119f6SJes Sorensen };
265599119f6SJes Sorensen 
26679cac25eSBitterblue Smith static const struct rtl8xxxu_reg32val rtl8xxx_agc_8192eu_highpa_table[] = {
267599119f6SJes Sorensen 	{0xc78, 0xfa000001}, {0xc78, 0xf9010001},
268599119f6SJes Sorensen 	{0xc78, 0xf8020001}, {0xc78, 0xf7030001},
269599119f6SJes Sorensen 	{0xc78, 0xf6040001}, {0xc78, 0xf5050001},
270599119f6SJes Sorensen 	{0xc78, 0xf4060001}, {0xc78, 0xf3070001},
271599119f6SJes Sorensen 	{0xc78, 0xf2080001}, {0xc78, 0xf1090001},
272599119f6SJes Sorensen 	{0xc78, 0xf00a0001}, {0xc78, 0xef0b0001},
273599119f6SJes Sorensen 	{0xc78, 0xee0c0001}, {0xc78, 0xed0d0001},
274599119f6SJes Sorensen 	{0xc78, 0xec0e0001}, {0xc78, 0xeb0f0001},
275599119f6SJes Sorensen 	{0xc78, 0xea100001}, {0xc78, 0xe9110001},
276599119f6SJes Sorensen 	{0xc78, 0xe8120001}, {0xc78, 0xe7130001},
277599119f6SJes Sorensen 	{0xc78, 0xe6140001}, {0xc78, 0xe5150001},
278599119f6SJes Sorensen 	{0xc78, 0xe4160001}, {0xc78, 0xe3170001},
279599119f6SJes Sorensen 	{0xc78, 0xe2180001}, {0xc78, 0xe1190001},
280599119f6SJes Sorensen 	{0xc78, 0x8a1a0001}, {0xc78, 0x891b0001},
281599119f6SJes Sorensen 	{0xc78, 0x881c0001}, {0xc78, 0x871d0001},
282599119f6SJes Sorensen 	{0xc78, 0x861e0001}, {0xc78, 0x851f0001},
283599119f6SJes Sorensen 	{0xc78, 0x84200001}, {0xc78, 0x83210001},
284599119f6SJes Sorensen 	{0xc78, 0x82220001}, {0xc78, 0x6a230001},
285599119f6SJes Sorensen 	{0xc78, 0x69240001}, {0xc78, 0x68250001},
286599119f6SJes Sorensen 	{0xc78, 0x67260001}, {0xc78, 0x66270001},
287599119f6SJes Sorensen 	{0xc78, 0x65280001}, {0xc78, 0x64290001},
288599119f6SJes Sorensen 	{0xc78, 0x632a0001}, {0xc78, 0x622b0001},
289599119f6SJes Sorensen 	{0xc78, 0x612c0001}, {0xc78, 0x602d0001},
290599119f6SJes Sorensen 	{0xc78, 0x472e0001}, {0xc78, 0x462f0001},
291599119f6SJes Sorensen 	{0xc78, 0x45300001}, {0xc78, 0x44310001},
292599119f6SJes Sorensen 	{0xc78, 0x43320001}, {0xc78, 0x42330001},
293599119f6SJes Sorensen 	{0xc78, 0x41340001}, {0xc78, 0x40350001},
294599119f6SJes Sorensen 	{0xc78, 0x40360001}, {0xc78, 0x40370001},
295599119f6SJes Sorensen 	{0xc78, 0x40380001}, {0xc78, 0x40390001},
296599119f6SJes Sorensen 	{0xc78, 0x403a0001}, {0xc78, 0x403b0001},
297599119f6SJes Sorensen 	{0xc78, 0x403c0001}, {0xc78, 0x403d0001},
298599119f6SJes Sorensen 	{0xc78, 0x403e0001}, {0xc78, 0x403f0001},
299599119f6SJes Sorensen 	{0xc78, 0xfa400001}, {0xc78, 0xf9410001},
300599119f6SJes Sorensen 	{0xc78, 0xf8420001}, {0xc78, 0xf7430001},
301599119f6SJes Sorensen 	{0xc78, 0xf6440001}, {0xc78, 0xf5450001},
302599119f6SJes Sorensen 	{0xc78, 0xf4460001}, {0xc78, 0xf3470001},
303599119f6SJes Sorensen 	{0xc78, 0xf2480001}, {0xc78, 0xf1490001},
304599119f6SJes Sorensen 	{0xc78, 0xf04a0001}, {0xc78, 0xef4b0001},
305599119f6SJes Sorensen 	{0xc78, 0xee4c0001}, {0xc78, 0xed4d0001},
306599119f6SJes Sorensen 	{0xc78, 0xec4e0001}, {0xc78, 0xeb4f0001},
307599119f6SJes Sorensen 	{0xc78, 0xea500001}, {0xc78, 0xe9510001},
308599119f6SJes Sorensen 	{0xc78, 0xe8520001}, {0xc78, 0xe7530001},
309599119f6SJes Sorensen 	{0xc78, 0xe6540001}, {0xc78, 0xe5550001},
310599119f6SJes Sorensen 	{0xc78, 0xe4560001}, {0xc78, 0xe3570001},
311599119f6SJes Sorensen 	{0xc78, 0xe2580001}, {0xc78, 0xe1590001},
312599119f6SJes Sorensen 	{0xc78, 0x8a5a0001}, {0xc78, 0x895b0001},
313599119f6SJes Sorensen 	{0xc78, 0x885c0001}, {0xc78, 0x875d0001},
314599119f6SJes Sorensen 	{0xc78, 0x865e0001}, {0xc78, 0x855f0001},
315599119f6SJes Sorensen 	{0xc78, 0x84600001}, {0xc78, 0x83610001},
316599119f6SJes Sorensen 	{0xc78, 0x82620001}, {0xc78, 0x6a630001},
317599119f6SJes Sorensen 	{0xc78, 0x69640001}, {0xc78, 0x68650001},
318599119f6SJes Sorensen 	{0xc78, 0x67660001}, {0xc78, 0x66670001},
319599119f6SJes Sorensen 	{0xc78, 0x65680001}, {0xc78, 0x64690001},
320599119f6SJes Sorensen 	{0xc78, 0x636a0001}, {0xc78, 0x626b0001},
321599119f6SJes Sorensen 	{0xc78, 0x616c0001}, {0xc78, 0x606d0001},
322599119f6SJes Sorensen 	{0xc78, 0x476e0001}, {0xc78, 0x466f0001},
323599119f6SJes Sorensen 	{0xc78, 0x45700001}, {0xc78, 0x44710001},
324599119f6SJes Sorensen 	{0xc78, 0x43720001}, {0xc78, 0x42730001},
325599119f6SJes Sorensen 	{0xc78, 0x41740001}, {0xc78, 0x40750001},
326599119f6SJes Sorensen 	{0xc78, 0x40760001}, {0xc78, 0x40770001},
327599119f6SJes Sorensen 	{0xc78, 0x40780001}, {0xc78, 0x40790001},
328599119f6SJes Sorensen 	{0xc78, 0x407a0001}, {0xc78, 0x407b0001},
329599119f6SJes Sorensen 	{0xc78, 0x407c0001}, {0xc78, 0x407d0001},
330599119f6SJes Sorensen 	{0xc78, 0x407e0001}, {0xc78, 0x407f0001},
331599119f6SJes Sorensen 	{0xc50, 0x00040222}, {0xc50, 0x00040220},
332599119f6SJes Sorensen 	{0xffff, 0xffffffff}
333599119f6SJes Sorensen };
334599119f6SJes Sorensen 
33579cac25eSBitterblue Smith static const struct rtl8xxxu_rfregval rtl8192eu_radioa_init_table[] = {
336599119f6SJes Sorensen 	{0x7f, 0x00000082}, {0x81, 0x0003fc00},
337599119f6SJes Sorensen 	{0x00, 0x00030000}, {0x08, 0x00008400},
338599119f6SJes Sorensen 	{0x18, 0x00000407}, {0x19, 0x00000012},
339599119f6SJes Sorensen 	{0x1b, 0x00000064}, {0x1e, 0x00080009},
340599119f6SJes Sorensen 	{0x1f, 0x00000880}, {0x2f, 0x0001a060},
341599119f6SJes Sorensen 	{0x3f, 0x00000000}, {0x42, 0x000060c0},
342599119f6SJes Sorensen 	{0x57, 0x000d0000}, {0x58, 0x000be180},
343599119f6SJes Sorensen 	{0x67, 0x00001552}, {0x83, 0x00000000},
344599119f6SJes Sorensen 	{0xb0, 0x000ff9f1}, {0xb1, 0x00055418},
345599119f6SJes Sorensen 	{0xb2, 0x0008cc00}, {0xb4, 0x00043083},
346599119f6SJes Sorensen 	{0xb5, 0x00008166}, {0xb6, 0x0000803e},
347599119f6SJes Sorensen 	{0xb7, 0x0001c69f}, {0xb8, 0x0000407f},
348599119f6SJes Sorensen 	{0xb9, 0x00080001}, {0xba, 0x00040001},
349599119f6SJes Sorensen 	{0xbb, 0x00000400}, {0xbf, 0x000c0000},
350599119f6SJes Sorensen 	{0xc2, 0x00002400}, {0xc3, 0x00000009},
351599119f6SJes Sorensen 	{0xc4, 0x00040c91}, {0xc5, 0x00099999},
352599119f6SJes Sorensen 	{0xc6, 0x000000a3}, {0xc7, 0x00088820},
353599119f6SJes Sorensen 	{0xc8, 0x00076c06}, {0xc9, 0x00000000},
354599119f6SJes Sorensen 	{0xca, 0x00080000}, {0xdf, 0x00000180},
355599119f6SJes Sorensen 	{0xef, 0x000001a0}, {0x51, 0x00069545},
356599119f6SJes Sorensen 	{0x52, 0x0007e45e}, {0x53, 0x00000071},
357599119f6SJes Sorensen 	{0x56, 0x00051ff3}, {0x35, 0x000000a8},
358599119f6SJes Sorensen 	{0x35, 0x000001e2}, {0x35, 0x000002a8},
359599119f6SJes Sorensen 	{0x36, 0x00001c24}, {0x36, 0x00009c24},
360599119f6SJes Sorensen 	{0x36, 0x00011c24}, {0x36, 0x00019c24},
361599119f6SJes Sorensen 	{0x18, 0x00000c07}, {0x5a, 0x00048000},
362599119f6SJes Sorensen 	{0x19, 0x000739d0},
363599119f6SJes Sorensen #ifdef EXT_PA_8192EU
364599119f6SJes Sorensen 	/* External PA or external LNA */
365599119f6SJes Sorensen 	{0x34, 0x0000a093}, {0x34, 0x0000908f},
366599119f6SJes Sorensen 	{0x34, 0x0000808c}, {0x34, 0x0000704d},
367599119f6SJes Sorensen 	{0x34, 0x0000604a}, {0x34, 0x00005047},
368599119f6SJes Sorensen 	{0x34, 0x0000400a}, {0x34, 0x00003007},
369599119f6SJes Sorensen 	{0x34, 0x00002004}, {0x34, 0x00001001},
370599119f6SJes Sorensen 	{0x34, 0x00000000},
371599119f6SJes Sorensen #else
372599119f6SJes Sorensen 	/* Regular */
373599119f6SJes Sorensen 	{0x34, 0x0000add7}, {0x34, 0x00009dd4},
374599119f6SJes Sorensen 	{0x34, 0x00008dd1}, {0x34, 0x00007dce},
375599119f6SJes Sorensen 	{0x34, 0x00006dcb}, {0x34, 0x00005dc8},
376599119f6SJes Sorensen 	{0x34, 0x00004dc5}, {0x34, 0x000034cc},
377599119f6SJes Sorensen 	{0x34, 0x0000244f}, {0x34, 0x0000144c},
378599119f6SJes Sorensen 	{0x34, 0x00000014},
379599119f6SJes Sorensen #endif
380599119f6SJes Sorensen 	{0x00, 0x00030159},
381599119f6SJes Sorensen 	{0x84, 0x00068180},
382599119f6SJes Sorensen 	{0x86, 0x0000014e},
383599119f6SJes Sorensen 	{0x87, 0x00048e00},
384599119f6SJes Sorensen 	{0x8e, 0x00065540},
385599119f6SJes Sorensen 	{0x8f, 0x00088000},
386599119f6SJes Sorensen 	{0xef, 0x000020a0},
387599119f6SJes Sorensen #ifdef EXT_PA_8192EU
388599119f6SJes Sorensen 	/* External PA or external LNA */
389599119f6SJes Sorensen 	{0x3b, 0x000f07b0},
390599119f6SJes Sorensen #else
391599119f6SJes Sorensen 	{0x3b, 0x000f02b0},
392599119f6SJes Sorensen #endif
393599119f6SJes Sorensen 	{0x3b, 0x000ef7b0}, {0x3b, 0x000d4fb0},
394599119f6SJes Sorensen 	{0x3b, 0x000cf060}, {0x3b, 0x000b0090},
395599119f6SJes Sorensen 	{0x3b, 0x000a0080}, {0x3b, 0x00090080},
396599119f6SJes Sorensen 	{0x3b, 0x0008f780},
397599119f6SJes Sorensen #ifdef EXT_PA_8192EU
398599119f6SJes Sorensen 	/* External PA or external LNA */
399599119f6SJes Sorensen 	{0x3b, 0x000787b0},
400599119f6SJes Sorensen #else
401599119f6SJes Sorensen 	{0x3b, 0x00078730},
402599119f6SJes Sorensen #endif
403599119f6SJes Sorensen 	{0x3b, 0x00060fb0}, {0x3b, 0x0005ffa0},
404599119f6SJes Sorensen 	{0x3b, 0x00040620}, {0x3b, 0x00037090},
405599119f6SJes Sorensen 	{0x3b, 0x00020080}, {0x3b, 0x0001f060},
406599119f6SJes Sorensen 	{0x3b, 0x0000ffb0}, {0xef, 0x000000a0},
407599119f6SJes Sorensen 	{0xfe, 0x00000000}, {0x18, 0x0000fc07},
408599119f6SJes Sorensen 	{0xfe, 0x00000000}, {0xfe, 0x00000000},
409599119f6SJes Sorensen 	{0xfe, 0x00000000}, {0xfe, 0x00000000},
410599119f6SJes Sorensen 	{0x1e, 0x00000001}, {0x1f, 0x00080000},
411599119f6SJes Sorensen 	{0x00, 0x00033e70},
412599119f6SJes Sorensen 	{0xff, 0xffffffff}
413599119f6SJes Sorensen };
414599119f6SJes Sorensen 
41579cac25eSBitterblue Smith static const struct rtl8xxxu_rfregval rtl8192eu_radiob_init_table[] = {
416599119f6SJes Sorensen 	{0x7f, 0x00000082}, {0x81, 0x0003fc00},
417599119f6SJes Sorensen 	{0x00, 0x00030000}, {0x08, 0x00008400},
418599119f6SJes Sorensen 	{0x18, 0x00000407}, {0x19, 0x00000012},
419599119f6SJes Sorensen 	{0x1b, 0x00000064}, {0x1e, 0x00080009},
420599119f6SJes Sorensen 	{0x1f, 0x00000880}, {0x2f, 0x0001a060},
421599119f6SJes Sorensen 	{0x3f, 0x00000000}, {0x42, 0x000060c0},
422599119f6SJes Sorensen 	{0x57, 0x000d0000}, {0x58, 0x000be180},
423599119f6SJes Sorensen 	{0x67, 0x00001552}, {0x7f, 0x00000082},
424599119f6SJes Sorensen 	{0x81, 0x0003f000}, {0x83, 0x00000000},
425599119f6SJes Sorensen 	{0xdf, 0x00000180}, {0xef, 0x000001a0},
426599119f6SJes Sorensen 	{0x51, 0x00069545}, {0x52, 0x0007e42e},
427599119f6SJes Sorensen 	{0x53, 0x00000071}, {0x56, 0x00051ff3},
428599119f6SJes Sorensen 	{0x35, 0x000000a8}, {0x35, 0x000001e0},
429599119f6SJes Sorensen 	{0x35, 0x000002a8}, {0x36, 0x00001ca8},
430599119f6SJes Sorensen 	{0x36, 0x00009c24}, {0x36, 0x00011c24},
431599119f6SJes Sorensen 	{0x36, 0x00019c24}, {0x18, 0x00000c07},
432599119f6SJes Sorensen 	{0x5a, 0x00048000}, {0x19, 0x000739d0},
433599119f6SJes Sorensen #ifdef EXT_PA_8192EU
434599119f6SJes Sorensen 	/* External PA or external LNA */
435599119f6SJes Sorensen 	{0x34, 0x0000a093}, {0x34, 0x0000908f},
436599119f6SJes Sorensen 	{0x34, 0x0000808c}, {0x34, 0x0000704d},
437599119f6SJes Sorensen 	{0x34, 0x0000604a}, {0x34, 0x00005047},
438599119f6SJes Sorensen 	{0x34, 0x0000400a}, {0x34, 0x00003007},
439599119f6SJes Sorensen 	{0x34, 0x00002004}, {0x34, 0x00001001},
440599119f6SJes Sorensen 	{0x34, 0x00000000},
441599119f6SJes Sorensen #else
442599119f6SJes Sorensen 	{0x34, 0x0000add7}, {0x34, 0x00009dd4},
443599119f6SJes Sorensen 	{0x34, 0x00008dd1}, {0x34, 0x00007dce},
444599119f6SJes Sorensen 	{0x34, 0x00006dcb}, {0x34, 0x00005dc8},
445599119f6SJes Sorensen 	{0x34, 0x00004dc5}, {0x34, 0x000034cc},
446599119f6SJes Sorensen 	{0x34, 0x0000244f}, {0x34, 0x0000144c},
447599119f6SJes Sorensen 	{0x34, 0x00000014},
448599119f6SJes Sorensen #endif
449599119f6SJes Sorensen 	{0x00, 0x00030159}, {0x84, 0x00068180},
450599119f6SJes Sorensen 	{0x86, 0x000000ce}, {0x87, 0x00048a00},
451599119f6SJes Sorensen 	{0x8e, 0x00065540}, {0x8f, 0x00088000},
452599119f6SJes Sorensen 	{0xef, 0x000020a0},
453599119f6SJes Sorensen #ifdef EXT_PA_8192EU
454599119f6SJes Sorensen 	/* External PA or external LNA */
455599119f6SJes Sorensen 	{0x3b, 0x000f07b0},
456599119f6SJes Sorensen #else
457599119f6SJes Sorensen 	{0x3b, 0x000f02b0},
458599119f6SJes Sorensen #endif
459599119f6SJes Sorensen 
460599119f6SJes Sorensen 	{0x3b, 0x000ef7b0}, {0x3b, 0x000d4fb0},
461599119f6SJes Sorensen 	{0x3b, 0x000cf060}, {0x3b, 0x000b0090},
462599119f6SJes Sorensen 	{0x3b, 0x000a0080}, {0x3b, 0x00090080},
463599119f6SJes Sorensen 	{0x3b, 0x0008f780},
464599119f6SJes Sorensen #ifdef EXT_PA_8192EU
465599119f6SJes Sorensen 	/* External PA or external LNA */
466599119f6SJes Sorensen 	{0x3b, 0x000787b0},
467599119f6SJes Sorensen #else
468599119f6SJes Sorensen 	{0x3b, 0x00078730},
469599119f6SJes Sorensen #endif
470599119f6SJes Sorensen 	{0x3b, 0x00060fb0}, {0x3b, 0x0005ffa0},
471599119f6SJes Sorensen 	{0x3b, 0x00040620}, {0x3b, 0x00037090},
472599119f6SJes Sorensen 	{0x3b, 0x00020080}, {0x3b, 0x0001f060},
473599119f6SJes Sorensen 	{0x3b, 0x0000ffb0}, {0xef, 0x000000a0},
474599119f6SJes Sorensen 	{0x00, 0x00010159}, {0xfe, 0x00000000},
475599119f6SJes Sorensen 	{0xfe, 0x00000000}, {0xfe, 0x00000000},
476599119f6SJes Sorensen 	{0xfe, 0x00000000}, {0x1e, 0x00000001},
477599119f6SJes Sorensen 	{0x1f, 0x00080000}, {0x00, 0x00033e70},
478599119f6SJes Sorensen 	{0xff, 0xffffffff}
479599119f6SJes Sorensen };
480599119f6SJes Sorensen 
rtl8192eu_identify_chip(struct rtl8xxxu_priv * priv)48114566bbfSBitterblue Smith static int rtl8192eu_identify_chip(struct rtl8xxxu_priv *priv)
48214566bbfSBitterblue Smith {
48314566bbfSBitterblue Smith 	struct device *dev = &priv->udev->dev;
48414566bbfSBitterblue Smith 	u32 val32, bonding, sys_cfg, vendor;
48514566bbfSBitterblue Smith 	int ret = 0;
48614566bbfSBitterblue Smith 
48714566bbfSBitterblue Smith 	sys_cfg = rtl8xxxu_read32(priv, REG_SYS_CFG);
48860d18ddbSBitterblue Smith 	priv->chip_cut = u32_get_bits(sys_cfg, SYS_CFG_CHIP_VERSION_MASK);
48914566bbfSBitterblue Smith 	if (sys_cfg & SYS_CFG_TRP_VAUX_EN) {
49014566bbfSBitterblue Smith 		dev_info(dev, "Unsupported test chip\n");
49114566bbfSBitterblue Smith 		ret = -ENOTSUPP;
49214566bbfSBitterblue Smith 		goto out;
49314566bbfSBitterblue Smith 	}
49414566bbfSBitterblue Smith 
49514566bbfSBitterblue Smith 	bonding = rtl8xxxu_read32(priv, REG_HPON_FSM);
49614566bbfSBitterblue Smith 	bonding &= HPON_FSM_BONDING_MASK;
49714566bbfSBitterblue Smith 	if (bonding == HPON_FSM_BONDING_1T2R) {
4989b00565aSBitterblue Smith 		strscpy(priv->chip_name, "8191EU", sizeof(priv->chip_name));
49914566bbfSBitterblue Smith 		priv->tx_paths = 1;
50014566bbfSBitterblue Smith 		priv->rtl_chip = RTL8191E;
50114566bbfSBitterblue Smith 	} else {
5029b00565aSBitterblue Smith 		strscpy(priv->chip_name, "8192EU", sizeof(priv->chip_name));
50314566bbfSBitterblue Smith 		priv->tx_paths = 2;
50414566bbfSBitterblue Smith 		priv->rtl_chip = RTL8192E;
50514566bbfSBitterblue Smith 	}
50614566bbfSBitterblue Smith 	priv->rf_paths = 2;
50714566bbfSBitterblue Smith 	priv->rx_paths = 2;
50814566bbfSBitterblue Smith 	priv->has_wifi = 1;
50914566bbfSBitterblue Smith 
51014566bbfSBitterblue Smith 	vendor = sys_cfg & SYS_CFG_VENDOR_EXT_MASK;
51114566bbfSBitterblue Smith 	rtl8xxxu_identify_vendor_2bits(priv, vendor);
51214566bbfSBitterblue Smith 
51314566bbfSBitterblue Smith 	val32 = rtl8xxxu_read32(priv, REG_GPIO_OUTSTS);
51460d18ddbSBitterblue Smith 	priv->rom_rev = u32_get_bits(val32, GPIO_RF_RL_ID);
51514566bbfSBitterblue Smith 
51614566bbfSBitterblue Smith 	rtl8xxxu_config_endpoints_sie(priv);
51714566bbfSBitterblue Smith 
51814566bbfSBitterblue Smith 	/*
51914566bbfSBitterblue Smith 	 * Fallback for devices that do not provide REG_NORMAL_SIE_EP_TX
52014566bbfSBitterblue Smith 	 */
52114566bbfSBitterblue Smith 	if (!priv->ep_tx_count)
52214566bbfSBitterblue Smith 		ret = rtl8xxxu_config_endpoints_no_sie(priv);
52314566bbfSBitterblue Smith 
52414566bbfSBitterblue Smith out:
52514566bbfSBitterblue Smith 	return ret;
52614566bbfSBitterblue Smith }
52714566bbfSBitterblue Smith 
528599119f6SJes Sorensen static void
rtl8192e_set_tx_power(struct rtl8xxxu_priv * priv,int channel,bool ht40)529599119f6SJes Sorensen rtl8192e_set_tx_power(struct rtl8xxxu_priv *priv, int channel, bool ht40)
530599119f6SJes Sorensen {
531599119f6SJes Sorensen 	u32 val32, ofdm, mcs;
532599119f6SJes Sorensen 	u8 cck, ofdmbase, mcsbase;
533599119f6SJes Sorensen 	int group, tx_idx;
534599119f6SJes Sorensen 
535599119f6SJes Sorensen 	tx_idx = 0;
536599119f6SJes Sorensen 	group = rtl8xxxu_gen2_channel_to_group(channel);
537599119f6SJes Sorensen 
538599119f6SJes Sorensen 	cck = priv->cck_tx_power_index_A[group];
539599119f6SJes Sorensen 
540599119f6SJes Sorensen 	val32 = rtl8xxxu_read32(priv, REG_TX_AGC_A_CCK1_MCS32);
541599119f6SJes Sorensen 	val32 &= 0xffff00ff;
542599119f6SJes Sorensen 	val32 |= (cck << 8);
543599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_TX_AGC_A_CCK1_MCS32, val32);
544599119f6SJes Sorensen 
545599119f6SJes Sorensen 	val32 = rtl8xxxu_read32(priv, REG_TX_AGC_B_CCK11_A_CCK2_11);
546599119f6SJes Sorensen 	val32 &= 0xff;
547599119f6SJes Sorensen 	val32 |= ((cck << 8) | (cck << 16) | (cck << 24));
548599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_TX_AGC_B_CCK11_A_CCK2_11, val32);
549599119f6SJes Sorensen 
550599119f6SJes Sorensen 	ofdmbase = priv->ht40_1s_tx_power_index_A[group];
551599119f6SJes Sorensen 	ofdmbase += priv->ofdm_tx_power_diff[tx_idx].a;
552599119f6SJes Sorensen 	ofdm = ofdmbase | ofdmbase << 8 | ofdmbase << 16 | ofdmbase << 24;
553599119f6SJes Sorensen 
554599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_TX_AGC_A_RATE18_06, ofdm);
555599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_TX_AGC_A_RATE54_24, ofdm);
556599119f6SJes Sorensen 
557599119f6SJes Sorensen 	mcsbase = priv->ht40_1s_tx_power_index_A[group];
558599119f6SJes Sorensen 	if (ht40)
559599119f6SJes Sorensen 		mcsbase += priv->ht40_tx_power_diff[tx_idx++].a;
560599119f6SJes Sorensen 	else
561599119f6SJes Sorensen 		mcsbase += priv->ht20_tx_power_diff[tx_idx++].a;
562599119f6SJes Sorensen 	mcs = mcsbase | mcsbase << 8 | mcsbase << 16 | mcsbase << 24;
563599119f6SJes Sorensen 
564599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_TX_AGC_A_MCS03_MCS00, mcs);
565599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_TX_AGC_A_MCS07_MCS04, mcs);
566599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_TX_AGC_A_MCS11_MCS08, mcs);
567599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_TX_AGC_A_MCS15_MCS12, mcs);
568599119f6SJes Sorensen 
569599119f6SJes Sorensen 	if (priv->tx_paths > 1) {
570599119f6SJes Sorensen 		cck = priv->cck_tx_power_index_B[group];
571599119f6SJes Sorensen 
572599119f6SJes Sorensen 		val32 = rtl8xxxu_read32(priv, REG_TX_AGC_B_CCK1_55_MCS32);
573599119f6SJes Sorensen 		val32 &= 0xff;
574599119f6SJes Sorensen 		val32 |= ((cck << 8) | (cck << 16) | (cck << 24));
575599119f6SJes Sorensen 		rtl8xxxu_write32(priv, REG_TX_AGC_B_CCK1_55_MCS32, val32);
576599119f6SJes Sorensen 
577599119f6SJes Sorensen 		val32 = rtl8xxxu_read32(priv, REG_TX_AGC_B_CCK11_A_CCK2_11);
578599119f6SJes Sorensen 		val32 &= 0xffffff00;
579599119f6SJes Sorensen 		val32 |= cck;
580599119f6SJes Sorensen 		rtl8xxxu_write32(priv, REG_TX_AGC_B_CCK11_A_CCK2_11, val32);
581599119f6SJes Sorensen 
582599119f6SJes Sorensen 		ofdmbase = priv->ht40_1s_tx_power_index_B[group];
583599119f6SJes Sorensen 		ofdmbase += priv->ofdm_tx_power_diff[tx_idx].b;
584599119f6SJes Sorensen 		ofdm = ofdmbase | ofdmbase << 8 |
585599119f6SJes Sorensen 			ofdmbase << 16 | ofdmbase << 24;
586599119f6SJes Sorensen 
587599119f6SJes Sorensen 		rtl8xxxu_write32(priv, REG_TX_AGC_B_RATE18_06, ofdm);
588599119f6SJes Sorensen 		rtl8xxxu_write32(priv, REG_TX_AGC_B_RATE54_24, ofdm);
589599119f6SJes Sorensen 
590599119f6SJes Sorensen 		mcsbase = priv->ht40_1s_tx_power_index_B[group];
591599119f6SJes Sorensen 		if (ht40)
592599119f6SJes Sorensen 			mcsbase += priv->ht40_tx_power_diff[tx_idx++].b;
593599119f6SJes Sorensen 		else
594599119f6SJes Sorensen 			mcsbase += priv->ht20_tx_power_diff[tx_idx++].b;
595599119f6SJes Sorensen 		mcs = mcsbase | mcsbase << 8 | mcsbase << 16 | mcsbase << 24;
596599119f6SJes Sorensen 
597599119f6SJes Sorensen 		rtl8xxxu_write32(priv, REG_TX_AGC_B_MCS03_MCS00, mcs);
598599119f6SJes Sorensen 		rtl8xxxu_write32(priv, REG_TX_AGC_B_MCS07_MCS04, mcs);
599599119f6SJes Sorensen 		rtl8xxxu_write32(priv, REG_TX_AGC_B_MCS11_MCS08, mcs);
600599119f6SJes Sorensen 		rtl8xxxu_write32(priv, REG_TX_AGC_B_MCS15_MCS12, mcs);
601599119f6SJes Sorensen 	}
602599119f6SJes Sorensen }
603599119f6SJes Sorensen 
rtl8192eu_parse_efuse(struct rtl8xxxu_priv * priv)604599119f6SJes Sorensen static int rtl8192eu_parse_efuse(struct rtl8xxxu_priv *priv)
605599119f6SJes Sorensen {
606599119f6SJes Sorensen 	struct rtl8192eu_efuse *efuse = &priv->efuse_wifi.efuse8192eu;
607599119f6SJes Sorensen 	int i;
608599119f6SJes Sorensen 
609599119f6SJes Sorensen 	if (efuse->rtl_id != cpu_to_le16(0x8129))
610599119f6SJes Sorensen 		return -EINVAL;
611599119f6SJes Sorensen 
612599119f6SJes Sorensen 	ether_addr_copy(priv->mac_addr, efuse->mac_addr);
613599119f6SJes Sorensen 
614599119f6SJes Sorensen 	memcpy(priv->cck_tx_power_index_A, efuse->tx_power_index_A.cck_base,
615599119f6SJes Sorensen 	       sizeof(efuse->tx_power_index_A.cck_base));
616599119f6SJes Sorensen 	memcpy(priv->cck_tx_power_index_B, efuse->tx_power_index_B.cck_base,
617599119f6SJes Sorensen 	       sizeof(efuse->tx_power_index_B.cck_base));
618599119f6SJes Sorensen 
619599119f6SJes Sorensen 	memcpy(priv->ht40_1s_tx_power_index_A,
620599119f6SJes Sorensen 	       efuse->tx_power_index_A.ht40_base,
621599119f6SJes Sorensen 	       sizeof(efuse->tx_power_index_A.ht40_base));
622599119f6SJes Sorensen 	memcpy(priv->ht40_1s_tx_power_index_B,
623599119f6SJes Sorensen 	       efuse->tx_power_index_B.ht40_base,
624599119f6SJes Sorensen 	       sizeof(efuse->tx_power_index_B.ht40_base));
625599119f6SJes Sorensen 
626599119f6SJes Sorensen 	priv->ht20_tx_power_diff[0].a =
627599119f6SJes Sorensen 		efuse->tx_power_index_A.ht20_ofdm_1s_diff.b;
628599119f6SJes Sorensen 	priv->ht20_tx_power_diff[0].b =
629599119f6SJes Sorensen 		efuse->tx_power_index_B.ht20_ofdm_1s_diff.b;
630599119f6SJes Sorensen 
631599119f6SJes Sorensen 	priv->ht40_tx_power_diff[0].a = 0;
632599119f6SJes Sorensen 	priv->ht40_tx_power_diff[0].b = 0;
633599119f6SJes Sorensen 
634599119f6SJes Sorensen 	for (i = 1; i < RTL8723B_TX_COUNT; i++) {
635599119f6SJes Sorensen 		priv->ofdm_tx_power_diff[i].a =
636599119f6SJes Sorensen 			efuse->tx_power_index_A.pwr_diff[i - 1].ofdm;
637599119f6SJes Sorensen 		priv->ofdm_tx_power_diff[i].b =
638599119f6SJes Sorensen 			efuse->tx_power_index_B.pwr_diff[i - 1].ofdm;
639599119f6SJes Sorensen 
640599119f6SJes Sorensen 		priv->ht20_tx_power_diff[i].a =
641599119f6SJes Sorensen 			efuse->tx_power_index_A.pwr_diff[i - 1].ht20;
642599119f6SJes Sorensen 		priv->ht20_tx_power_diff[i].b =
643599119f6SJes Sorensen 			efuse->tx_power_index_B.pwr_diff[i - 1].ht20;
644599119f6SJes Sorensen 
645599119f6SJes Sorensen 		priv->ht40_tx_power_diff[i].a =
646599119f6SJes Sorensen 			efuse->tx_power_index_A.pwr_diff[i - 1].ht40;
647599119f6SJes Sorensen 		priv->ht40_tx_power_diff[i].b =
648599119f6SJes Sorensen 			efuse->tx_power_index_B.pwr_diff[i - 1].ht40;
649599119f6SJes Sorensen 	}
650599119f6SJes Sorensen 
65157b328bcSBitterblue Smith 	priv->default_crystal_cap = priv->efuse_wifi.efuse8192eu.xtal_k & 0x3f;
652599119f6SJes Sorensen 
653599119f6SJes Sorensen 	return 0;
654599119f6SJes Sorensen }
655599119f6SJes Sorensen 
rtl8192eu_load_firmware(struct rtl8xxxu_priv * priv)656599119f6SJes Sorensen static int rtl8192eu_load_firmware(struct rtl8xxxu_priv *priv)
657599119f6SJes Sorensen {
658d7a3705cSBitterblue Smith 	const char *fw_name;
659599119f6SJes Sorensen 	int ret;
660599119f6SJes Sorensen 
661599119f6SJes Sorensen 	fw_name = "rtlwifi/rtl8192eu_nic.bin";
662599119f6SJes Sorensen 
663599119f6SJes Sorensen 	ret = rtl8xxxu_load_firmware(priv, fw_name);
664599119f6SJes Sorensen 
665599119f6SJes Sorensen 	return ret;
666599119f6SJes Sorensen }
667599119f6SJes Sorensen 
rtl8192eu_init_phy_bb(struct rtl8xxxu_priv * priv)668599119f6SJes Sorensen static void rtl8192eu_init_phy_bb(struct rtl8xxxu_priv *priv)
669599119f6SJes Sorensen {
670599119f6SJes Sorensen 	u8 val8;
671599119f6SJes Sorensen 	u16 val16;
672599119f6SJes Sorensen 
673599119f6SJes Sorensen 	val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC);
674599119f6SJes Sorensen 	val16 |= SYS_FUNC_BB_GLB_RSTN | SYS_FUNC_BBRSTB | SYS_FUNC_DIO_RF;
675599119f6SJes Sorensen 	rtl8xxxu_write16(priv, REG_SYS_FUNC, val16);
676599119f6SJes Sorensen 
677599119f6SJes Sorensen 	/* 6. 0x1f[7:0] = 0x07 */
678599119f6SJes Sorensen 	val8 = RF_ENABLE | RF_RSTB | RF_SDMRSTB;
679599119f6SJes Sorensen 	rtl8xxxu_write8(priv, REG_RF_CTRL, val8);
680599119f6SJes Sorensen 
681599119f6SJes Sorensen 	val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC);
682599119f6SJes Sorensen 	val16 |= (SYS_FUNC_USBA | SYS_FUNC_USBD | SYS_FUNC_DIO_RF |
683599119f6SJes Sorensen 		  SYS_FUNC_BB_GLB_RSTN | SYS_FUNC_BBRSTB);
684599119f6SJes Sorensen 	rtl8xxxu_write16(priv, REG_SYS_FUNC, val16);
685599119f6SJes Sorensen 	val8 = RF_ENABLE | RF_RSTB | RF_SDMRSTB;
686599119f6SJes Sorensen 	rtl8xxxu_write8(priv, REG_RF_CTRL, val8);
687599119f6SJes Sorensen 	rtl8xxxu_init_phy_regs(priv, rtl8192eu_phy_init_table);
688599119f6SJes Sorensen 
689599119f6SJes Sorensen 	if (priv->hi_pa)
690599119f6SJes Sorensen 		rtl8xxxu_init_phy_regs(priv, rtl8xxx_agc_8192eu_highpa_table);
691599119f6SJes Sorensen 	else
692599119f6SJes Sorensen 		rtl8xxxu_init_phy_regs(priv, rtl8xxx_agc_8192eu_std_table);
693599119f6SJes Sorensen }
694599119f6SJes Sorensen 
rtl8192eu_init_phy_rf(struct rtl8xxxu_priv * priv)695599119f6SJes Sorensen static int rtl8192eu_init_phy_rf(struct rtl8xxxu_priv *priv)
696599119f6SJes Sorensen {
697599119f6SJes Sorensen 	int ret;
698599119f6SJes Sorensen 
699599119f6SJes Sorensen 	ret = rtl8xxxu_init_phy_rf(priv, rtl8192eu_radioa_init_table, RF_A);
700599119f6SJes Sorensen 	if (ret)
701599119f6SJes Sorensen 		goto exit;
702599119f6SJes Sorensen 
703599119f6SJes Sorensen 	ret = rtl8xxxu_init_phy_rf(priv, rtl8192eu_radiob_init_table, RF_B);
704599119f6SJes Sorensen 
705599119f6SJes Sorensen exit:
706599119f6SJes Sorensen 	return ret;
707599119f6SJes Sorensen }
708599119f6SJes Sorensen 
rtl8192eu_iqk_path_a(struct rtl8xxxu_priv * priv)709599119f6SJes Sorensen static int rtl8192eu_iqk_path_a(struct rtl8xxxu_priv *priv)
710599119f6SJes Sorensen {
711599119f6SJes Sorensen 	u32 reg_eac, reg_e94, reg_e9c;
712599119f6SJes Sorensen 	int result = 0;
713599119f6SJes Sorensen 
714599119f6SJes Sorensen 	/*
715599119f6SJes Sorensen 	 * TX IQK
716599119f6SJes Sorensen 	 * PA/PAD controlled by 0x0
717599119f6SJes Sorensen 	 */
718599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000);
719103d6e9dSBitterblue Smith 	rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x00180);
720695c5d3aSJun ASAKA 
721695c5d3aSJun ASAKA 	rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_WE_LUT, 0x800a0);
722695c5d3aSJun ASAKA 	rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_RCK_OS, 0x20000);
723695c5d3aSJun ASAKA 	rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G1, 0x0000f);
724695c5d3aSJun ASAKA 	rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G2, 0x07f77);
725695c5d3aSJun ASAKA 
726599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x80800000);
727599119f6SJes Sorensen 
728599119f6SJes Sorensen 	/* Path A IQK setting */
729599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x18008c1c);
730599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x38008c1c);
731599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_TX_IQK_TONE_B, 0x38008c1c);
732599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_RX_IQK_TONE_B, 0x38008c1c);
733599119f6SJes Sorensen 
734599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_TX_IQK_PI_A, 0x82140303);
735599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_RX_IQK_PI_A, 0x68160000);
736599119f6SJes Sorensen 
737599119f6SJes Sorensen 	/* LO calibration setting */
738599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x00462911);
739599119f6SJes Sorensen 
740599119f6SJes Sorensen 	/* One shot, path A LOK & IQK */
741599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf9000000);
742599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf8000000);
743599119f6SJes Sorensen 
744599119f6SJes Sorensen 	mdelay(10);
745599119f6SJes Sorensen 
746599119f6SJes Sorensen 	/* Check failed */
747599119f6SJes Sorensen 	reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2);
748599119f6SJes Sorensen 	reg_e94 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_A);
749599119f6SJes Sorensen 	reg_e9c = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_A);
750599119f6SJes Sorensen 
751599119f6SJes Sorensen 	if (!(reg_eac & BIT(28)) &&
752599119f6SJes Sorensen 	    ((reg_e94 & 0x03ff0000) != 0x01420000) &&
753599119f6SJes Sorensen 	    ((reg_e9c & 0x03ff0000) != 0x00420000))
754599119f6SJes Sorensen 		result |= 0x01;
755599119f6SJes Sorensen 
756599119f6SJes Sorensen 	return result;
757599119f6SJes Sorensen }
758599119f6SJes Sorensen 
rtl8192eu_rx_iqk_path_a(struct rtl8xxxu_priv * priv)759599119f6SJes Sorensen static int rtl8192eu_rx_iqk_path_a(struct rtl8xxxu_priv *priv)
760599119f6SJes Sorensen {
761599119f6SJes Sorensen 	u32 reg_ea4, reg_eac, reg_e94, reg_e9c, val32;
762599119f6SJes Sorensen 	int result = 0;
763599119f6SJes Sorensen 
764599119f6SJes Sorensen 	/* Leave IQK mode */
765599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00);
766599119f6SJes Sorensen 
767599119f6SJes Sorensen 	/* Enable path A PA in TX IQK mode */
768599119f6SJes Sorensen 	rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_WE_LUT, 0x800a0);
769599119f6SJes Sorensen 	rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_RCK_OS, 0x30000);
770599119f6SJes Sorensen 	rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G1, 0x0000f);
771695c5d3aSJun ASAKA 	rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G2, 0xf1173);
772695c5d3aSJun ASAKA 
773695c5d3aSJun ASAKA 	rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_WE_LUT, 0x800a0);
774695c5d3aSJun ASAKA 	rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_RCK_OS, 0x30000);
775695c5d3aSJun ASAKA 	rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_TXPA_G1, 0x0000f);
776695c5d3aSJun ASAKA 	rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_TXPA_G2, 0xf1173);
777599119f6SJes Sorensen 
778599119f6SJes Sorensen 	/* PA/PAD control by 0x56, and set = 0x0 */
779103d6e9dSBitterblue Smith 	rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x00980);
780103d6e9dSBitterblue Smith 	rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_PAD_TXG, 0x511e0);
781599119f6SJes Sorensen 
782599119f6SJes Sorensen 	/* Enter IQK mode */
783599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x80800000);
784599119f6SJes Sorensen 
785599119f6SJes Sorensen 	/* TX IQK setting */
786599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_TX_IQK, 0x01007c00);
787599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_RX_IQK, 0x01004800);
788599119f6SJes Sorensen 
789599119f6SJes Sorensen 	/* path-A IQK setting */
790599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x18008c1c);
791599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x38008c1c);
792599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_TX_IQK_TONE_B, 0x38008c1c);
793599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_RX_IQK_TONE_B, 0x38008c1c);
794599119f6SJes Sorensen 
795695c5d3aSJun ASAKA 	rtl8xxxu_write32(priv, REG_TX_IQK_PI_A, 0x8216031f);
796695c5d3aSJun ASAKA 	rtl8xxxu_write32(priv, REG_RX_IQK_PI_A, 0x6816031f);
797599119f6SJes Sorensen 
798599119f6SJes Sorensen 	/* LO calibration setting */
799599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x0046a911);
800599119f6SJes Sorensen 
801599119f6SJes Sorensen 	/* One shot, path A LOK & IQK */
802695c5d3aSJun ASAKA 	rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf9000000);
803599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf8000000);
804599119f6SJes Sorensen 
805599119f6SJes Sorensen 	mdelay(10);
806599119f6SJes Sorensen 
807599119f6SJes Sorensen 	/* Check failed */
808599119f6SJes Sorensen 	reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2);
809599119f6SJes Sorensen 	reg_e94 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_A);
810599119f6SJes Sorensen 	reg_e9c = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_A);
811599119f6SJes Sorensen 
812599119f6SJes Sorensen 	if (!(reg_eac & BIT(28)) &&
813599119f6SJes Sorensen 	    ((reg_e94 & 0x03ff0000) != 0x01420000) &&
814599119f6SJes Sorensen 	    ((reg_e9c & 0x03ff0000) != 0x00420000)) {
815599119f6SJes Sorensen 		result |= 0x01;
816599119f6SJes Sorensen 	} else {
817599119f6SJes Sorensen 		/* PA/PAD controlled by 0x0 */
818599119f6SJes Sorensen 		rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000);
819103d6e9dSBitterblue Smith 		rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x180);
820599119f6SJes Sorensen 		goto out;
821599119f6SJes Sorensen 	}
822599119f6SJes Sorensen 
823599119f6SJes Sorensen 	val32 = 0x80007c00 |
824599119f6SJes Sorensen 		(reg_e94 & 0x03ff0000) | ((reg_e9c >> 16) & 0x03ff);
825599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_TX_IQK, val32);
826599119f6SJes Sorensen 
827599119f6SJes Sorensen 	/* Modify RX IQK mode table */
828599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000);
829599119f6SJes Sorensen 
830599119f6SJes Sorensen 	rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_WE_LUT, 0x800a0);
831599119f6SJes Sorensen 	rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_RCK_OS, 0x30000);
832599119f6SJes Sorensen 	rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G1, 0x0000f);
833695c5d3aSJun ASAKA 	rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G2, 0xf7ff2);
834695c5d3aSJun ASAKA 
835695c5d3aSJun ASAKA 	rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_WE_LUT, 0x800a0);
836695c5d3aSJun ASAKA 	rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_RCK_OS, 0x30000);
837695c5d3aSJun ASAKA 	rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_TXPA_G1, 0x0000f);
838695c5d3aSJun ASAKA 	rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_TXPA_G2, 0xf7ff2);
839599119f6SJes Sorensen 
840599119f6SJes Sorensen 	/* PA/PAD control by 0x56, and set = 0x0 */
841103d6e9dSBitterblue Smith 	rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x00980);
842103d6e9dSBitterblue Smith 	rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_PAD_TXG, 0x510e0);
843599119f6SJes Sorensen 
844599119f6SJes Sorensen 	/* Enter IQK mode */
845599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x80800000);
846599119f6SJes Sorensen 
847599119f6SJes Sorensen 	/* IQK setting */
848599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_RX_IQK, 0x01004800);
849599119f6SJes Sorensen 
850599119f6SJes Sorensen 	/* Path A IQK setting */
851599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x38008c1c);
852599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x18008c1c);
853599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_TX_IQK_TONE_B, 0x38008c1c);
854599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_RX_IQK_TONE_B, 0x38008c1c);
855599119f6SJes Sorensen 
856695c5d3aSJun ASAKA 	rtl8xxxu_write32(priv, REG_TX_IQK_PI_A, 0x821608ff);
857695c5d3aSJun ASAKA 	rtl8xxxu_write32(priv, REG_RX_IQK_PI_A, 0x281608ff);
858599119f6SJes Sorensen 
859599119f6SJes Sorensen 	/* LO calibration setting */
860599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x0046a891);
861599119f6SJes Sorensen 
862599119f6SJes Sorensen 	/* One shot, path A LOK & IQK */
863695c5d3aSJun ASAKA 	rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf9000000);
864599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf8000000);
865599119f6SJes Sorensen 
866599119f6SJes Sorensen 	mdelay(10);
867599119f6SJes Sorensen 
868599119f6SJes Sorensen 	reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2);
869599119f6SJes Sorensen 	reg_ea4 = rtl8xxxu_read32(priv, REG_RX_POWER_BEFORE_IQK_A_2);
870599119f6SJes Sorensen 
871599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000);
872103d6e9dSBitterblue Smith 	rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_GAIN_CCA, 0x180);
873599119f6SJes Sorensen 
874599119f6SJes Sorensen 	if (!(reg_eac & BIT(27)) &&
875599119f6SJes Sorensen 	    ((reg_ea4 & 0x03ff0000) != 0x01320000) &&
876599119f6SJes Sorensen 	    ((reg_eac & 0x03ff0000) != 0x00360000))
877599119f6SJes Sorensen 		result |= 0x02;
878599119f6SJes Sorensen 	else
879599119f6SJes Sorensen 		dev_warn(&priv->udev->dev, "%s: Path A RX IQK failed!\n",
880599119f6SJes Sorensen 			 __func__);
881599119f6SJes Sorensen 
882599119f6SJes Sorensen out:
883599119f6SJes Sorensen 	return result;
884599119f6SJes Sorensen }
885599119f6SJes Sorensen 
rtl8192eu_iqk_path_b(struct rtl8xxxu_priv * priv)886599119f6SJes Sorensen static int rtl8192eu_iqk_path_b(struct rtl8xxxu_priv *priv)
887599119f6SJes Sorensen {
888599119f6SJes Sorensen 	u32 reg_eac, reg_eb4, reg_ebc;
889599119f6SJes Sorensen 	int result = 0;
890599119f6SJes Sorensen 
891599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000);
892103d6e9dSBitterblue Smith 	rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_GAIN_CCA, 0x00180);
893599119f6SJes Sorensen 
894695c5d3aSJun ASAKA 	rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_WE_LUT, 0x800a0);
895695c5d3aSJun ASAKA 	rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_RCK_OS, 0x20000);
896695c5d3aSJun ASAKA 	rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_TXPA_G1, 0x0000f);
897695c5d3aSJun ASAKA 	rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_TXPA_G2, 0x07f77);
898695c5d3aSJun ASAKA 
899599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x80800000);
900599119f6SJes Sorensen 
901599119f6SJes Sorensen 	/* Path B IQK setting */
902599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x38008c1c);
903599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x38008c1c);
904599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_TX_IQK_TONE_B, 0x18008c1c);
905599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_RX_IQK_TONE_B, 0x38008c1c);
906599119f6SJes Sorensen 
907695c5d3aSJun ASAKA 	rtl8xxxu_write32(priv, REG_TX_IQK_PI_B, 0x82140303);
908599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_RX_IQK_PI_B, 0x68160000);
909599119f6SJes Sorensen 
910599119f6SJes Sorensen 	/* LO calibration setting */
911695c5d3aSJun ASAKA 	rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x00462911);
912599119f6SJes Sorensen 
913599119f6SJes Sorensen 	/* One shot, path A LOK & IQK */
914599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xfa000000);
915599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf8000000);
916599119f6SJes Sorensen 
917599119f6SJes Sorensen 	mdelay(1);
918599119f6SJes Sorensen 
919599119f6SJes Sorensen 	/* Check failed */
920599119f6SJes Sorensen 	reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2);
921599119f6SJes Sorensen 	reg_eb4 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_B);
922599119f6SJes Sorensen 	reg_ebc = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_B);
923599119f6SJes Sorensen 
924599119f6SJes Sorensen 	if (!(reg_eac & BIT(31)) &&
925599119f6SJes Sorensen 	    ((reg_eb4 & 0x03ff0000) != 0x01420000) &&
926599119f6SJes Sorensen 	    ((reg_ebc & 0x03ff0000) != 0x00420000))
927599119f6SJes Sorensen 		result |= 0x01;
928599119f6SJes Sorensen 	else
929599119f6SJes Sorensen 		dev_warn(&priv->udev->dev, "%s: Path B IQK failed!\n",
930599119f6SJes Sorensen 			 __func__);
931599119f6SJes Sorensen 
932599119f6SJes Sorensen 	return result;
933599119f6SJes Sorensen }
934599119f6SJes Sorensen 
rtl8192eu_rx_iqk_path_b(struct rtl8xxxu_priv * priv)935599119f6SJes Sorensen static int rtl8192eu_rx_iqk_path_b(struct rtl8xxxu_priv *priv)
936599119f6SJes Sorensen {
937599119f6SJes Sorensen 	u32 reg_eac, reg_eb4, reg_ebc, reg_ec4, reg_ecc, val32;
938599119f6SJes Sorensen 	int result = 0;
939599119f6SJes Sorensen 
940599119f6SJes Sorensen 	/* Leave IQK mode */
941599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000);
942599119f6SJes Sorensen 
943599119f6SJes Sorensen 	/* Enable path A PA in TX IQK mode */
944599119f6SJes Sorensen 	rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_WE_LUT, 0x800a0);
945599119f6SJes Sorensen 	rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_RCK_OS, 0x30000);
946599119f6SJes Sorensen 	rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_TXPA_G1, 0x0000f);
947695c5d3aSJun ASAKA 	rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_TXPA_G2, 0xf1173);
948695c5d3aSJun ASAKA 
949695c5d3aSJun ASAKA 	rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_WE_LUT, 0x800a0);
950695c5d3aSJun ASAKA 	rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_RCK_OS, 0x30000);
951695c5d3aSJun ASAKA 	rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G1, 0x0000f);
952695c5d3aSJun ASAKA 	rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G2, 0xf1173);
953599119f6SJes Sorensen 
954599119f6SJes Sorensen 	/* PA/PAD control by 0x56, and set = 0x0 */
955103d6e9dSBitterblue Smith 	rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_GAIN_CCA, 0x00980);
956103d6e9dSBitterblue Smith 	rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_PAD_TXG, 0x511e0);
957599119f6SJes Sorensen 
958599119f6SJes Sorensen 	/* Enter IQK mode */
959599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x80800000);
960599119f6SJes Sorensen 
961599119f6SJes Sorensen 	/* TX IQK setting */
962599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_TX_IQK, 0x01007c00);
963599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_RX_IQK, 0x01004800);
964599119f6SJes Sorensen 
965599119f6SJes Sorensen 	/* path-A IQK setting */
966599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x38008c1c);
967599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x38008c1c);
968599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_TX_IQK_TONE_B, 0x18008c1c);
969599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_RX_IQK_TONE_B, 0x38008c1c);
970599119f6SJes Sorensen 
971695c5d3aSJun ASAKA 	rtl8xxxu_write32(priv, REG_TX_IQK_PI_B, 0x8216031f);
972695c5d3aSJun ASAKA 	rtl8xxxu_write32(priv, REG_RX_IQK_PI_B, 0x6816031f);
973599119f6SJes Sorensen 
974599119f6SJes Sorensen 	/* LO calibration setting */
975599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x0046a911);
976599119f6SJes Sorensen 
977599119f6SJes Sorensen 	/* One shot, path A LOK & IQK */
978599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xfa000000);
979599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf8000000);
980599119f6SJes Sorensen 
981599119f6SJes Sorensen 	mdelay(10);
982599119f6SJes Sorensen 
983599119f6SJes Sorensen 	/* Check failed */
984599119f6SJes Sorensen 	reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2);
985599119f6SJes Sorensen 	reg_eb4 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_B);
986599119f6SJes Sorensen 	reg_ebc = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_B);
987599119f6SJes Sorensen 
988599119f6SJes Sorensen 	if (!(reg_eac & BIT(31)) &&
989599119f6SJes Sorensen 	    ((reg_eb4 & 0x03ff0000) != 0x01420000) &&
990599119f6SJes Sorensen 	    ((reg_ebc & 0x03ff0000) != 0x00420000)) {
991599119f6SJes Sorensen 		result |= 0x01;
992599119f6SJes Sorensen 	} else {
993599119f6SJes Sorensen 		/*
994599119f6SJes Sorensen 		 * PA/PAD controlled by 0x0
995599119f6SJes Sorensen 		 * Vendor driver restores RF_A here which I believe is a bug
996599119f6SJes Sorensen 		 */
997599119f6SJes Sorensen 		rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000);
998103d6e9dSBitterblue Smith 		rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_GAIN_CCA, 0x180);
999599119f6SJes Sorensen 		goto out;
1000599119f6SJes Sorensen 	}
1001599119f6SJes Sorensen 
1002599119f6SJes Sorensen 	val32 = 0x80007c00 |
1003599119f6SJes Sorensen 		(reg_eb4 & 0x03ff0000) | ((reg_ebc >> 16) & 0x03ff);
1004599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_TX_IQK, val32);
1005599119f6SJes Sorensen 
1006599119f6SJes Sorensen 	/* Modify RX IQK mode table */
1007599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000);
1008599119f6SJes Sorensen 
1009599119f6SJes Sorensen 	rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_WE_LUT, 0x800a0);
1010599119f6SJes Sorensen 	rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_RCK_OS, 0x30000);
1011599119f6SJes Sorensen 	rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_TXPA_G1, 0x0000f);
1012695c5d3aSJun ASAKA 	rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_TXPA_G2, 0xf7ff2);
1013695c5d3aSJun ASAKA 
1014695c5d3aSJun ASAKA 	rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_WE_LUT, 0x800a0);
1015695c5d3aSJun ASAKA 	rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_RCK_OS, 0x30000);
1016695c5d3aSJun ASAKA 	rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G1, 0x0000f);
1017695c5d3aSJun ASAKA 	rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G2, 0xf7ff2);
1018599119f6SJes Sorensen 
1019599119f6SJes Sorensen 	/* PA/PAD control by 0x56, and set = 0x0 */
1020103d6e9dSBitterblue Smith 	rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_GAIN_CCA, 0x00980);
1021103d6e9dSBitterblue Smith 	rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_PAD_TXG, 0x510e0);
1022599119f6SJes Sorensen 
1023599119f6SJes Sorensen 	/* Enter IQK mode */
1024599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x80800000);
1025599119f6SJes Sorensen 
1026599119f6SJes Sorensen 	/* IQK setting */
1027599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_RX_IQK, 0x01004800);
1028599119f6SJes Sorensen 
1029599119f6SJes Sorensen 	/* Path A IQK setting */
1030599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x38008c1c);
1031599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x38008c1c);
1032599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_TX_IQK_TONE_B, 0x38008c1c);
1033599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_RX_IQK_TONE_B, 0x18008c1c);
1034599119f6SJes Sorensen 
1035695c5d3aSJun ASAKA 	rtl8xxxu_write32(priv, REG_TX_IQK_PI_A, 0x821608ff);
1036695c5d3aSJun ASAKA 	rtl8xxxu_write32(priv, REG_RX_IQK_PI_A, 0x281608ff);
1037599119f6SJes Sorensen 
1038599119f6SJes Sorensen 	/* LO calibration setting */
1039599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x0046a891);
1040599119f6SJes Sorensen 
1041599119f6SJes Sorensen 	/* One shot, path A LOK & IQK */
1042599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xfa000000);
1043599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf8000000);
1044599119f6SJes Sorensen 
1045599119f6SJes Sorensen 	mdelay(10);
1046599119f6SJes Sorensen 
1047599119f6SJes Sorensen 	reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2);
1048599119f6SJes Sorensen 	reg_ec4 = rtl8xxxu_read32(priv, REG_RX_POWER_BEFORE_IQK_B_2);
1049599119f6SJes Sorensen 	reg_ecc = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_B_2);
1050599119f6SJes Sorensen 
1051599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000);
1052103d6e9dSBitterblue Smith 	rtl8xxxu_write_rfreg(priv, RF_B, RF6052_REG_GAIN_CCA, 0x180);
1053599119f6SJes Sorensen 
1054599119f6SJes Sorensen 	if (!(reg_eac & BIT(30)) &&
1055599119f6SJes Sorensen 	    ((reg_ec4 & 0x03ff0000) != 0x01320000) &&
1056599119f6SJes Sorensen 	    ((reg_ecc & 0x03ff0000) != 0x00360000))
1057599119f6SJes Sorensen 		result |= 0x02;
1058599119f6SJes Sorensen 	else
1059599119f6SJes Sorensen 		dev_warn(&priv->udev->dev, "%s: Path B RX IQK failed!\n",
1060599119f6SJes Sorensen 			 __func__);
1061599119f6SJes Sorensen 
1062599119f6SJes Sorensen out:
1063599119f6SJes Sorensen 	return result;
1064599119f6SJes Sorensen }
1065599119f6SJes Sorensen 
rtl8192eu_phy_iqcalibrate(struct rtl8xxxu_priv * priv,int result[][8],int t)1066599119f6SJes Sorensen static void rtl8192eu_phy_iqcalibrate(struct rtl8xxxu_priv *priv,
1067599119f6SJes Sorensen 				      int result[][8], int t)
1068599119f6SJes Sorensen {
1069599119f6SJes Sorensen 	struct device *dev = &priv->udev->dev;
1070599119f6SJes Sorensen 	u32 i, val32;
1071599119f6SJes Sorensen 	int path_a_ok, path_b_ok;
1072599119f6SJes Sorensen 	int retry = 2;
1073314bf64dSColin Ian King 	static const u32 adda_regs[RTL8XXXU_ADDA_REGS] = {
1074599119f6SJes Sorensen 		REG_FPGA0_XCD_SWITCH_CTRL, REG_BLUETOOTH,
1075599119f6SJes Sorensen 		REG_RX_WAIT_CCA, REG_TX_CCK_RFON,
1076599119f6SJes Sorensen 		REG_TX_CCK_BBON, REG_TX_OFDM_RFON,
1077599119f6SJes Sorensen 		REG_TX_OFDM_BBON, REG_TX_TO_RX,
1078599119f6SJes Sorensen 		REG_TX_TO_TX, REG_RX_CCK,
1079599119f6SJes Sorensen 		REG_RX_OFDM, REG_RX_WAIT_RIFS,
1080599119f6SJes Sorensen 		REG_RX_TO_RX, REG_STANDBY,
1081599119f6SJes Sorensen 		REG_SLEEP, REG_PMPD_ANAEN
1082599119f6SJes Sorensen 	};
1083314bf64dSColin Ian King 	static const u32 iqk_mac_regs[RTL8XXXU_MAC_REGS] = {
1084599119f6SJes Sorensen 		REG_TXPAUSE, REG_BEACON_CTRL,
1085599119f6SJes Sorensen 		REG_BEACON_CTRL_1, REG_GPIO_MUXCFG
1086599119f6SJes Sorensen 	};
1087314bf64dSColin Ian King 	static const u32 iqk_bb_regs[RTL8XXXU_BB_REGS] = {
1088599119f6SJes Sorensen 		REG_OFDM0_TRX_PATH_ENABLE, REG_OFDM0_TR_MUX_PAR,
1089599119f6SJes Sorensen 		REG_FPGA0_XCD_RF_SW_CTRL, REG_CONFIG_ANT_A, REG_CONFIG_ANT_B,
1090599119f6SJes Sorensen 		REG_FPGA0_XAB_RF_SW_CTRL, REG_FPGA0_XA_RF_INT_OE,
1091599119f6SJes Sorensen 		REG_FPGA0_XB_RF_INT_OE, REG_CCK0_AFE_SETTING
1092599119f6SJes Sorensen 	};
1093599119f6SJes Sorensen 	u8 xa_agc = rtl8xxxu_read32(priv, REG_OFDM0_XA_AGC_CORE1) & 0xff;
1094599119f6SJes Sorensen 	u8 xb_agc = rtl8xxxu_read32(priv, REG_OFDM0_XB_AGC_CORE1) & 0xff;
1095599119f6SJes Sorensen 
1096599119f6SJes Sorensen 	/*
1097599119f6SJes Sorensen 	 * Note: IQ calibration must be performed after loading
1098599119f6SJes Sorensen 	 *       PHY_REG.txt , and radio_a, radio_b.txt
1099599119f6SJes Sorensen 	 */
1100599119f6SJes Sorensen 
1101599119f6SJes Sorensen 	if (t == 0) {
1102599119f6SJes Sorensen 		/* Save ADDA parameters, turn Path A ADDA on */
1103599119f6SJes Sorensen 		rtl8xxxu_save_regs(priv, adda_regs, priv->adda_backup,
1104599119f6SJes Sorensen 				   RTL8XXXU_ADDA_REGS);
1105599119f6SJes Sorensen 		rtl8xxxu_save_mac_regs(priv, iqk_mac_regs, priv->mac_backup);
1106599119f6SJes Sorensen 		rtl8xxxu_save_regs(priv, iqk_bb_regs,
1107599119f6SJes Sorensen 				   priv->bb_backup, RTL8XXXU_BB_REGS);
1108599119f6SJes Sorensen 	}
1109599119f6SJes Sorensen 
1110599119f6SJes Sorensen 	rtl8xxxu_path_adda_on(priv, adda_regs, true);
1111599119f6SJes Sorensen 
1112599119f6SJes Sorensen 	/* MAC settings */
1113599119f6SJes Sorensen 	rtl8xxxu_mac_calibration(priv, iqk_mac_regs, priv->mac_backup);
1114599119f6SJes Sorensen 
1115599119f6SJes Sorensen 	val32 = rtl8xxxu_read32(priv, REG_CCK0_AFE_SETTING);
1116599119f6SJes Sorensen 	val32 |= 0x0f000000;
1117599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_CCK0_AFE_SETTING, val32);
1118599119f6SJes Sorensen 
1119599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, 0x03a05600);
1120599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_OFDM0_TR_MUX_PAR, 0x000800e4);
1121599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_FPGA0_XCD_RF_SW_CTRL, 0x22208200);
1122599119f6SJes Sorensen 
1123599119f6SJes Sorensen 	val32 = rtl8xxxu_read32(priv, REG_FPGA0_XAB_RF_SW_CTRL);
1124599119f6SJes Sorensen 	val32 |= (FPGA0_RF_PAPE | (FPGA0_RF_PAPE << FPGA0_RF_BD_CTRL_SHIFT));
1125599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_FPGA0_XAB_RF_SW_CTRL, val32);
1126599119f6SJes Sorensen 
1127599119f6SJes Sorensen 	val32 = rtl8xxxu_read32(priv, REG_FPGA0_XA_RF_INT_OE);
1128599119f6SJes Sorensen 	val32 |= BIT(10);
1129599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_FPGA0_XA_RF_INT_OE, val32);
1130599119f6SJes Sorensen 	val32 = rtl8xxxu_read32(priv, REG_FPGA0_XB_RF_INT_OE);
1131599119f6SJes Sorensen 	val32 |= BIT(10);
1132599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_FPGA0_XB_RF_INT_OE, val32);
1133599119f6SJes Sorensen 
1134599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x80800000);
1135599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_TX_IQK, 0x01007c00);
1136599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_RX_IQK, 0x01004800);
1137599119f6SJes Sorensen 
1138599119f6SJes Sorensen 	for (i = 0; i < retry; i++) {
1139599119f6SJes Sorensen 		path_a_ok = rtl8192eu_iqk_path_a(priv);
1140599119f6SJes Sorensen 		if (path_a_ok == 0x01) {
1141599119f6SJes Sorensen 			val32 = rtl8xxxu_read32(priv,
1142599119f6SJes Sorensen 						REG_TX_POWER_BEFORE_IQK_A);
1143599119f6SJes Sorensen 			result[t][0] = (val32 >> 16) & 0x3ff;
1144599119f6SJes Sorensen 			val32 = rtl8xxxu_read32(priv,
1145599119f6SJes Sorensen 						REG_TX_POWER_AFTER_IQK_A);
1146599119f6SJes Sorensen 			result[t][1] = (val32 >> 16) & 0x3ff;
1147599119f6SJes Sorensen 
1148599119f6SJes Sorensen 			break;
1149599119f6SJes Sorensen 		}
1150599119f6SJes Sorensen 	}
1151599119f6SJes Sorensen 
1152599119f6SJes Sorensen 	if (!path_a_ok)
1153599119f6SJes Sorensen 		dev_dbg(dev, "%s: Path A TX IQK failed!\n", __func__);
1154599119f6SJes Sorensen 
1155599119f6SJes Sorensen 	for (i = 0; i < retry; i++) {
1156599119f6SJes Sorensen 		path_a_ok = rtl8192eu_rx_iqk_path_a(priv);
1157599119f6SJes Sorensen 		if (path_a_ok == 0x03) {
1158599119f6SJes Sorensen 			val32 = rtl8xxxu_read32(priv,
1159599119f6SJes Sorensen 						REG_RX_POWER_BEFORE_IQK_A_2);
1160599119f6SJes Sorensen 			result[t][2] = (val32 >> 16) & 0x3ff;
1161599119f6SJes Sorensen 			val32 = rtl8xxxu_read32(priv,
1162599119f6SJes Sorensen 						REG_RX_POWER_AFTER_IQK_A_2);
1163599119f6SJes Sorensen 			result[t][3] = (val32 >> 16) & 0x3ff;
1164599119f6SJes Sorensen 
1165599119f6SJes Sorensen 			break;
1166599119f6SJes Sorensen 		}
1167599119f6SJes Sorensen 	}
1168599119f6SJes Sorensen 
1169599119f6SJes Sorensen 	if (!path_a_ok)
1170599119f6SJes Sorensen 		dev_dbg(dev, "%s: Path A RX IQK failed!\n", __func__);
1171599119f6SJes Sorensen 
1172599119f6SJes Sorensen 	if (priv->rf_paths > 1) {
1173599119f6SJes Sorensen 		/* Path A into standby */
1174599119f6SJes Sorensen 		rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000);
1175599119f6SJes Sorensen 		rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_AC, 0x10000);
1176599119f6SJes Sorensen 		rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x80800000);
1177599119f6SJes Sorensen 
1178599119f6SJes Sorensen 		/* Turn Path B ADDA on */
1179599119f6SJes Sorensen 		rtl8xxxu_path_adda_on(priv, adda_regs, false);
1180599119f6SJes Sorensen 
1181599119f6SJes Sorensen 		rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x80800000);
1182599119f6SJes Sorensen 		rtl8xxxu_write32(priv, REG_TX_IQK, 0x01007c00);
1183599119f6SJes Sorensen 		rtl8xxxu_write32(priv, REG_RX_IQK, 0x01004800);
1184599119f6SJes Sorensen 
1185599119f6SJes Sorensen 		for (i = 0; i < retry; i++) {
1186599119f6SJes Sorensen 			path_b_ok = rtl8192eu_iqk_path_b(priv);
1187599119f6SJes Sorensen 			if (path_b_ok == 0x01) {
1188599119f6SJes Sorensen 				val32 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_B);
1189599119f6SJes Sorensen 				result[t][4] = (val32 >> 16) & 0x3ff;
1190599119f6SJes Sorensen 				val32 = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_B);
1191599119f6SJes Sorensen 				result[t][5] = (val32 >> 16) & 0x3ff;
1192599119f6SJes Sorensen 				break;
1193599119f6SJes Sorensen 			}
1194599119f6SJes Sorensen 		}
1195599119f6SJes Sorensen 
1196599119f6SJes Sorensen 		if (!path_b_ok)
1197599119f6SJes Sorensen 			dev_dbg(dev, "%s: Path B IQK failed!\n", __func__);
1198599119f6SJes Sorensen 
1199599119f6SJes Sorensen 		for (i = 0; i < retry; i++) {
1200599119f6SJes Sorensen 			path_b_ok = rtl8192eu_rx_iqk_path_b(priv);
1201c70410cbSColin Ian King 			if (path_b_ok == 0x03) {
1202599119f6SJes Sorensen 				val32 = rtl8xxxu_read32(priv,
1203599119f6SJes Sorensen 							REG_RX_POWER_BEFORE_IQK_B_2);
1204599119f6SJes Sorensen 				result[t][6] = (val32 >> 16) & 0x3ff;
1205599119f6SJes Sorensen 				val32 = rtl8xxxu_read32(priv,
1206599119f6SJes Sorensen 							REG_RX_POWER_AFTER_IQK_B_2);
1207599119f6SJes Sorensen 				result[t][7] = (val32 >> 16) & 0x3ff;
1208599119f6SJes Sorensen 				break;
1209599119f6SJes Sorensen 			}
1210599119f6SJes Sorensen 		}
1211599119f6SJes Sorensen 
1212599119f6SJes Sorensen 		if (!path_b_ok)
1213599119f6SJes Sorensen 			dev_dbg(dev, "%s: Path B RX IQK failed!\n", __func__);
1214599119f6SJes Sorensen 	}
1215599119f6SJes Sorensen 
1216599119f6SJes Sorensen 	/* Back to BB mode, load original value */
1217599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_FPGA0_IQK, 0x00000000);
1218599119f6SJes Sorensen 
1219599119f6SJes Sorensen 	if (t) {
1220599119f6SJes Sorensen 		/* Reload ADDA power saving parameters */
1221599119f6SJes Sorensen 		rtl8xxxu_restore_regs(priv, adda_regs, priv->adda_backup,
1222599119f6SJes Sorensen 				      RTL8XXXU_ADDA_REGS);
1223599119f6SJes Sorensen 
1224599119f6SJes Sorensen 		/* Reload MAC parameters */
1225599119f6SJes Sorensen 		rtl8xxxu_restore_mac_regs(priv, iqk_mac_regs, priv->mac_backup);
1226599119f6SJes Sorensen 
1227599119f6SJes Sorensen 		/* Reload BB parameters */
1228599119f6SJes Sorensen 		rtl8xxxu_restore_regs(priv, iqk_bb_regs,
1229599119f6SJes Sorensen 				      priv->bb_backup, RTL8XXXU_BB_REGS);
1230599119f6SJes Sorensen 
1231599119f6SJes Sorensen 		/* Restore RX initial gain */
1232599119f6SJes Sorensen 		val32 = rtl8xxxu_read32(priv, REG_OFDM0_XA_AGC_CORE1);
1233599119f6SJes Sorensen 		val32 &= 0xffffff00;
1234599119f6SJes Sorensen 		rtl8xxxu_write32(priv, REG_OFDM0_XA_AGC_CORE1, val32 | 0x50);
1235599119f6SJes Sorensen 		rtl8xxxu_write32(priv, REG_OFDM0_XA_AGC_CORE1, val32 | xa_agc);
1236599119f6SJes Sorensen 
1237599119f6SJes Sorensen 		if (priv->rf_paths > 1) {
1238599119f6SJes Sorensen 			val32 = rtl8xxxu_read32(priv, REG_OFDM0_XB_AGC_CORE1);
1239599119f6SJes Sorensen 			val32 &= 0xffffff00;
1240599119f6SJes Sorensen 			rtl8xxxu_write32(priv, REG_OFDM0_XB_AGC_CORE1,
1241599119f6SJes Sorensen 					 val32 | 0x50);
1242599119f6SJes Sorensen 			rtl8xxxu_write32(priv, REG_OFDM0_XB_AGC_CORE1,
1243599119f6SJes Sorensen 					 val32 | xb_agc);
1244599119f6SJes Sorensen 		}
1245599119f6SJes Sorensen 
1246599119f6SJes Sorensen 		/* Load 0xe30 IQC default value */
1247599119f6SJes Sorensen 		rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x01008c00);
1248599119f6SJes Sorensen 		rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x01008c00);
1249599119f6SJes Sorensen 	}
1250599119f6SJes Sorensen }
1251599119f6SJes Sorensen 
rtl8192eu_phy_iq_calibrate(struct rtl8xxxu_priv * priv)1252599119f6SJes Sorensen static void rtl8192eu_phy_iq_calibrate(struct rtl8xxxu_priv *priv)
1253599119f6SJes Sorensen {
1254599119f6SJes Sorensen 	struct device *dev = &priv->udev->dev;
1255599119f6SJes Sorensen 	int result[4][8];	/* last is final result */
1256599119f6SJes Sorensen 	int i, candidate;
1257599119f6SJes Sorensen 	bool path_a_ok, path_b_ok;
1258599119f6SJes Sorensen 	u32 reg_e94, reg_e9c, reg_ea4, reg_eac;
1259599119f6SJes Sorensen 	u32 reg_eb4, reg_ebc, reg_ec4, reg_ecc;
1260599119f6SJes Sorensen 	bool simu;
1261599119f6SJes Sorensen 
1262599119f6SJes Sorensen 	memset(result, 0, sizeof(result));
1263599119f6SJes Sorensen 	candidate = -1;
1264599119f6SJes Sorensen 
1265599119f6SJes Sorensen 	path_a_ok = false;
1266599119f6SJes Sorensen 	path_b_ok = false;
1267599119f6SJes Sorensen 
1268599119f6SJes Sorensen 	for (i = 0; i < 3; i++) {
1269599119f6SJes Sorensen 		rtl8192eu_phy_iqcalibrate(priv, result, i);
1270599119f6SJes Sorensen 
1271599119f6SJes Sorensen 		if (i == 1) {
1272599119f6SJes Sorensen 			simu = rtl8xxxu_gen2_simularity_compare(priv,
1273599119f6SJes Sorensen 								result, 0, 1);
1274599119f6SJes Sorensen 			if (simu) {
1275599119f6SJes Sorensen 				candidate = 0;
1276599119f6SJes Sorensen 				break;
1277599119f6SJes Sorensen 			}
1278599119f6SJes Sorensen 		}
1279599119f6SJes Sorensen 
1280599119f6SJes Sorensen 		if (i == 2) {
1281599119f6SJes Sorensen 			simu = rtl8xxxu_gen2_simularity_compare(priv,
1282599119f6SJes Sorensen 								result, 0, 2);
1283599119f6SJes Sorensen 			if (simu) {
1284599119f6SJes Sorensen 				candidate = 0;
1285599119f6SJes Sorensen 				break;
1286599119f6SJes Sorensen 			}
1287599119f6SJes Sorensen 
1288599119f6SJes Sorensen 			simu = rtl8xxxu_gen2_simularity_compare(priv,
1289599119f6SJes Sorensen 								result, 1, 2);
1290599119f6SJes Sorensen 			if (simu)
1291599119f6SJes Sorensen 				candidate = 1;
1292599119f6SJes Sorensen 			else
1293599119f6SJes Sorensen 				candidate = 3;
1294599119f6SJes Sorensen 		}
1295599119f6SJes Sorensen 	}
1296599119f6SJes Sorensen 
1297599119f6SJes Sorensen 	for (i = 0; i < 4; i++) {
1298599119f6SJes Sorensen 		reg_e94 = result[i][0];
1299599119f6SJes Sorensen 		reg_e9c = result[i][1];
1300599119f6SJes Sorensen 		reg_ea4 = result[i][2];
1301599119f6SJes Sorensen 		reg_eb4 = result[i][4];
1302599119f6SJes Sorensen 		reg_ebc = result[i][5];
1303599119f6SJes Sorensen 		reg_ec4 = result[i][6];
1304599119f6SJes Sorensen 	}
1305599119f6SJes Sorensen 
1306599119f6SJes Sorensen 	if (candidate >= 0) {
1307599119f6SJes Sorensen 		reg_e94 = result[candidate][0];
1308599119f6SJes Sorensen 		priv->rege94 =  reg_e94;
1309599119f6SJes Sorensen 		reg_e9c = result[candidate][1];
1310599119f6SJes Sorensen 		priv->rege9c = reg_e9c;
1311599119f6SJes Sorensen 		reg_ea4 = result[candidate][2];
1312599119f6SJes Sorensen 		reg_eac = result[candidate][3];
1313599119f6SJes Sorensen 		reg_eb4 = result[candidate][4];
1314599119f6SJes Sorensen 		priv->regeb4 = reg_eb4;
1315599119f6SJes Sorensen 		reg_ebc = result[candidate][5];
1316599119f6SJes Sorensen 		priv->regebc = reg_ebc;
1317599119f6SJes Sorensen 		reg_ec4 = result[candidate][6];
1318599119f6SJes Sorensen 		reg_ecc = result[candidate][7];
1319599119f6SJes Sorensen 		dev_dbg(dev, "%s: candidate is %x\n", __func__, candidate);
1320599119f6SJes Sorensen 		dev_dbg(dev,
1321d602de8eSJoe Perches 			"%s: e94 =%x e9c=%x ea4=%x eac=%x eb4=%x ebc=%x ec4=%x ecc=%x\n",
1322d602de8eSJoe Perches 			__func__, reg_e94, reg_e9c,
1323599119f6SJes Sorensen 			reg_ea4, reg_eac, reg_eb4, reg_ebc, reg_ec4, reg_ecc);
1324599119f6SJes Sorensen 		path_a_ok = true;
1325599119f6SJes Sorensen 		path_b_ok = true;
1326599119f6SJes Sorensen 	} else {
1327599119f6SJes Sorensen 		reg_e94 = reg_eb4 = priv->rege94 = priv->regeb4 = 0x100;
1328599119f6SJes Sorensen 		reg_e9c = reg_ebc = priv->rege9c = priv->regebc = 0x0;
1329599119f6SJes Sorensen 	}
1330599119f6SJes Sorensen 
1331599119f6SJes Sorensen 	if (reg_e94 && candidate >= 0)
1332599119f6SJes Sorensen 		rtl8xxxu_fill_iqk_matrix_a(priv, path_a_ok, result,
1333599119f6SJes Sorensen 					   candidate, (reg_ea4 == 0));
1334599119f6SJes Sorensen 
1335599119f6SJes Sorensen 	if (priv->rf_paths > 1)
1336599119f6SJes Sorensen 		rtl8xxxu_fill_iqk_matrix_b(priv, path_b_ok, result,
1337599119f6SJes Sorensen 					   candidate, (reg_ec4 == 0));
1338599119f6SJes Sorensen 
1339599119f6SJes Sorensen 	rtl8xxxu_save_regs(priv, rtl8xxxu_iqk_phy_iq_bb_reg,
1340599119f6SJes Sorensen 			   priv->bb_recovery_backup, RTL8XXXU_BB_REGS);
1341599119f6SJes Sorensen }
1342599119f6SJes Sorensen 
1343599119f6SJes Sorensen /*
1344599119f6SJes Sorensen  * This is needed for 8723bu as well, presumable
1345599119f6SJes Sorensen  */
rtl8192e_crystal_afe_adjust(struct rtl8xxxu_priv * priv)1346599119f6SJes Sorensen static void rtl8192e_crystal_afe_adjust(struct rtl8xxxu_priv *priv)
1347599119f6SJes Sorensen {
1348599119f6SJes Sorensen 	u8 val8;
1349599119f6SJes Sorensen 	u32 val32;
1350599119f6SJes Sorensen 
1351599119f6SJes Sorensen 	/*
1352599119f6SJes Sorensen 	 * 40Mhz crystal source, MAC 0x28[2]=0
1353599119f6SJes Sorensen 	 */
1354599119f6SJes Sorensen 	val8 = rtl8xxxu_read8(priv, REG_AFE_PLL_CTRL);
1355599119f6SJes Sorensen 	val8 &= 0xfb;
1356599119f6SJes Sorensen 	rtl8xxxu_write8(priv, REG_AFE_PLL_CTRL, val8);
1357599119f6SJes Sorensen 
1358599119f6SJes Sorensen 	val32 = rtl8xxxu_read32(priv, REG_AFE_CTRL4);
1359599119f6SJes Sorensen 	val32 &= 0xfffffc7f;
1360599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_AFE_CTRL4, val32);
1361599119f6SJes Sorensen 
1362599119f6SJes Sorensen 	/*
1363599119f6SJes Sorensen 	 * 92e AFE parameter
1364599119f6SJes Sorensen 	 * AFE PLL KVCO selection, MAC 0x28[6]=1
1365599119f6SJes Sorensen 	 */
1366599119f6SJes Sorensen 	val8 = rtl8xxxu_read8(priv, REG_AFE_PLL_CTRL);
1367599119f6SJes Sorensen 	val8 &= 0xbf;
1368599119f6SJes Sorensen 	rtl8xxxu_write8(priv, REG_AFE_PLL_CTRL, val8);
1369599119f6SJes Sorensen 
1370599119f6SJes Sorensen 	/*
1371599119f6SJes Sorensen 	 * AFE PLL KVCO selection, MAC 0x78[21]=0
1372599119f6SJes Sorensen 	 */
1373599119f6SJes Sorensen 	val32 = rtl8xxxu_read32(priv, REG_AFE_CTRL4);
1374599119f6SJes Sorensen 	val32 &= 0xffdfffff;
1375599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_AFE_CTRL4, val32);
1376599119f6SJes Sorensen }
1377599119f6SJes Sorensen 
rtl8192e_disabled_to_emu(struct rtl8xxxu_priv * priv)1378599119f6SJes Sorensen static void rtl8192e_disabled_to_emu(struct rtl8xxxu_priv *priv)
1379599119f6SJes Sorensen {
1380599119f6SJes Sorensen 	u8 val8;
1381599119f6SJes Sorensen 
1382599119f6SJes Sorensen 	/* Clear suspend enable and power down enable*/
1383599119f6SJes Sorensen 	val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1);
1384599119f6SJes Sorensen 	val8 &= ~(BIT(3) | BIT(4));
1385599119f6SJes Sorensen 	rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val8);
1386599119f6SJes Sorensen }
1387599119f6SJes Sorensen 
rtl8192e_emu_to_active(struct rtl8xxxu_priv * priv)1388599119f6SJes Sorensen static int rtl8192e_emu_to_active(struct rtl8xxxu_priv *priv)
1389599119f6SJes Sorensen {
1390599119f6SJes Sorensen 	u8 val8;
1391599119f6SJes Sorensen 	u32 val32;
1392599119f6SJes Sorensen 	int count, ret = 0;
1393599119f6SJes Sorensen 
1394599119f6SJes Sorensen 	/* disable HWPDN 0x04[15]=0*/
1395599119f6SJes Sorensen 	val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1);
1396599119f6SJes Sorensen 	val8 &= ~BIT(7);
1397599119f6SJes Sorensen 	rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val8);
1398599119f6SJes Sorensen 
1399599119f6SJes Sorensen 	/* disable SW LPS 0x04[10]= 0 */
1400599119f6SJes Sorensen 	val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1);
1401599119f6SJes Sorensen 	val8 &= ~BIT(2);
1402599119f6SJes Sorensen 	rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val8);
1403599119f6SJes Sorensen 
1404599119f6SJes Sorensen 	/* disable WL suspend*/
1405599119f6SJes Sorensen 	val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1);
1406599119f6SJes Sorensen 	val8 &= ~(BIT(3) | BIT(4));
1407599119f6SJes Sorensen 	rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val8);
1408599119f6SJes Sorensen 
1409599119f6SJes Sorensen 	/* wait till 0x04[17] = 1 power ready*/
1410599119f6SJes Sorensen 	for (count = RTL8XXXU_MAX_REG_POLL; count; count--) {
1411599119f6SJes Sorensen 		val32 = rtl8xxxu_read32(priv, REG_APS_FSMCO);
1412599119f6SJes Sorensen 		if (val32 & BIT(17))
1413599119f6SJes Sorensen 			break;
1414599119f6SJes Sorensen 
1415599119f6SJes Sorensen 		udelay(10);
1416599119f6SJes Sorensen 	}
1417599119f6SJes Sorensen 
1418599119f6SJes Sorensen 	if (!count) {
1419599119f6SJes Sorensen 		ret = -EBUSY;
1420599119f6SJes Sorensen 		goto exit;
1421599119f6SJes Sorensen 	}
1422599119f6SJes Sorensen 
1423599119f6SJes Sorensen 	/* We should be able to optimize the following three entries into one */
1424599119f6SJes Sorensen 
1425599119f6SJes Sorensen 	/* release WLON reset 0x04[16]= 1*/
1426599119f6SJes Sorensen 	val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 2);
1427599119f6SJes Sorensen 	val8 |= BIT(0);
1428599119f6SJes Sorensen 	rtl8xxxu_write8(priv, REG_APS_FSMCO + 2, val8);
1429599119f6SJes Sorensen 
1430599119f6SJes Sorensen 	/* set, then poll until 0 */
1431599119f6SJes Sorensen 	val32 = rtl8xxxu_read32(priv, REG_APS_FSMCO);
1432599119f6SJes Sorensen 	val32 |= APS_FSMCO_MAC_ENABLE;
1433599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_APS_FSMCO, val32);
1434599119f6SJes Sorensen 
1435599119f6SJes Sorensen 	for (count = RTL8XXXU_MAX_REG_POLL; count; count--) {
1436599119f6SJes Sorensen 		val32 = rtl8xxxu_read32(priv, REG_APS_FSMCO);
1437599119f6SJes Sorensen 		if ((val32 & APS_FSMCO_MAC_ENABLE) == 0) {
1438599119f6SJes Sorensen 			ret = 0;
1439599119f6SJes Sorensen 			break;
1440599119f6SJes Sorensen 		}
1441599119f6SJes Sorensen 		udelay(10);
1442599119f6SJes Sorensen 	}
1443599119f6SJes Sorensen 
1444599119f6SJes Sorensen 	if (!count) {
1445599119f6SJes Sorensen 		ret = -EBUSY;
1446599119f6SJes Sorensen 		goto exit;
1447599119f6SJes Sorensen 	}
1448599119f6SJes Sorensen 
1449599119f6SJes Sorensen exit:
1450599119f6SJes Sorensen 	return ret;
1451599119f6SJes Sorensen }
1452599119f6SJes Sorensen 
rtl8192eu_active_to_lps(struct rtl8xxxu_priv * priv)1453f1785fbfSJes Sorensen static int rtl8192eu_active_to_lps(struct rtl8xxxu_priv *priv)
1454f1785fbfSJes Sorensen {
1455f1785fbfSJes Sorensen 	struct device *dev = &priv->udev->dev;
1456f1785fbfSJes Sorensen 	u8 val8;
1457f1785fbfSJes Sorensen 	u16 val16;
1458f1785fbfSJes Sorensen 	u32 val32;
1459f1785fbfSJes Sorensen 	int retry, retval;
1460f1785fbfSJes Sorensen 
1461f1785fbfSJes Sorensen 	rtl8xxxu_write8(priv, REG_TXPAUSE, 0xff);
1462f1785fbfSJes Sorensen 
1463f1785fbfSJes Sorensen 	retry = 100;
1464f1785fbfSJes Sorensen 	retval = -EBUSY;
1465f1785fbfSJes Sorensen 	/*
1466f1785fbfSJes Sorensen 	 * Poll 32 bit wide 0x05f8 for 0x00000000 to ensure no TX is pending.
1467f1785fbfSJes Sorensen 	 */
1468f1785fbfSJes Sorensen 	do {
1469f1785fbfSJes Sorensen 		val32 = rtl8xxxu_read32(priv, REG_SCH_TX_CMD);
1470f1785fbfSJes Sorensen 		if (!val32) {
1471f1785fbfSJes Sorensen 			retval = 0;
1472f1785fbfSJes Sorensen 			break;
1473f1785fbfSJes Sorensen 		}
1474f1785fbfSJes Sorensen 	} while (retry--);
1475f1785fbfSJes Sorensen 
1476f1785fbfSJes Sorensen 	if (!retry) {
1477f1785fbfSJes Sorensen 		dev_warn(dev, "Failed to flush TX queue\n");
1478f1785fbfSJes Sorensen 		retval = -EBUSY;
1479f1785fbfSJes Sorensen 		goto out;
1480f1785fbfSJes Sorensen 	}
1481f1785fbfSJes Sorensen 
1482f1785fbfSJes Sorensen 	/* Disable CCK and OFDM, clock gated */
1483f1785fbfSJes Sorensen 	val8 = rtl8xxxu_read8(priv, REG_SYS_FUNC);
1484f1785fbfSJes Sorensen 	val8 &= ~SYS_FUNC_BBRSTB;
1485f1785fbfSJes Sorensen 	rtl8xxxu_write8(priv, REG_SYS_FUNC, val8);
1486f1785fbfSJes Sorensen 
1487f1785fbfSJes Sorensen 	udelay(2);
1488f1785fbfSJes Sorensen 
1489f1785fbfSJes Sorensen 	/* Reset whole BB */
1490f1785fbfSJes Sorensen 	val8 = rtl8xxxu_read8(priv, REG_SYS_FUNC);
1491f1785fbfSJes Sorensen 	val8 &= ~SYS_FUNC_BB_GLB_RSTN;
1492f1785fbfSJes Sorensen 	rtl8xxxu_write8(priv, REG_SYS_FUNC, val8);
1493f1785fbfSJes Sorensen 
1494f1785fbfSJes Sorensen 	/* Reset MAC TRX */
1495f1785fbfSJes Sorensen 	val16 = rtl8xxxu_read16(priv, REG_CR);
1496f1785fbfSJes Sorensen 	val16 &= 0xff00;
1497f1785fbfSJes Sorensen 	val16 |= (CR_HCI_TXDMA_ENABLE | CR_HCI_RXDMA_ENABLE);
1498f1785fbfSJes Sorensen 	rtl8xxxu_write16(priv, REG_CR, val16);
1499f1785fbfSJes Sorensen 
1500f1785fbfSJes Sorensen 	val16 = rtl8xxxu_read16(priv, REG_CR);
1501f1785fbfSJes Sorensen 	val16 &= ~CR_SECURITY_ENABLE;
1502f1785fbfSJes Sorensen 	rtl8xxxu_write16(priv, REG_CR, val16);
1503f1785fbfSJes Sorensen 
1504f1785fbfSJes Sorensen 	val8 = rtl8xxxu_read8(priv, REG_DUAL_TSF_RST);
1505f1785fbfSJes Sorensen 	val8 |= DUAL_TSF_TX_OK;
1506f1785fbfSJes Sorensen 	rtl8xxxu_write8(priv, REG_DUAL_TSF_RST, val8);
1507f1785fbfSJes Sorensen 
1508f1785fbfSJes Sorensen out:
1509f1785fbfSJes Sorensen 	return retval;
1510f1785fbfSJes Sorensen }
1511f1785fbfSJes Sorensen 
rtl8192eu_active_to_emu(struct rtl8xxxu_priv * priv)1512f1785fbfSJes Sorensen static int rtl8192eu_active_to_emu(struct rtl8xxxu_priv *priv)
1513f1785fbfSJes Sorensen {
1514f1785fbfSJes Sorensen 	u8 val8;
1515f1785fbfSJes Sorensen 	int count, ret = 0;
1516f1785fbfSJes Sorensen 
1517f1785fbfSJes Sorensen 	/* Turn off RF */
15185d03f882SJes Sorensen 	val8 = rtl8xxxu_read8(priv, REG_RF_CTRL);
15195d03f882SJes Sorensen 	val8 &= ~RF_ENABLE;
15205d03f882SJes Sorensen 	rtl8xxxu_write8(priv, REG_RF_CTRL, val8);
1521f1785fbfSJes Sorensen 
1522f1785fbfSJes Sorensen 	/* Switch DPDT_SEL_P output from register 0x65[2] */
1523f1785fbfSJes Sorensen 	val8 = rtl8xxxu_read8(priv, REG_LEDCFG2);
1524f1785fbfSJes Sorensen 	val8 &= ~LEDCFG2_DPDT_SELECT;
1525f1785fbfSJes Sorensen 	rtl8xxxu_write8(priv, REG_LEDCFG2, val8);
1526f1785fbfSJes Sorensen 
1527f1785fbfSJes Sorensen 	/* 0x0005[1] = 1 turn off MAC by HW state machine*/
1528f1785fbfSJes Sorensen 	val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1);
1529f1785fbfSJes Sorensen 	val8 |= BIT(1);
1530f1785fbfSJes Sorensen 	rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val8);
1531f1785fbfSJes Sorensen 
1532f1785fbfSJes Sorensen 	for (count = RTL8XXXU_MAX_REG_POLL; count; count--) {
1533f1785fbfSJes Sorensen 		val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1);
1534f1785fbfSJes Sorensen 		if ((val8 & BIT(1)) == 0)
1535f1785fbfSJes Sorensen 			break;
1536f1785fbfSJes Sorensen 		udelay(10);
1537f1785fbfSJes Sorensen 	}
1538f1785fbfSJes Sorensen 
1539f1785fbfSJes Sorensen 	if (!count) {
1540f1785fbfSJes Sorensen 		dev_warn(&priv->udev->dev, "%s: Disabling MAC timed out\n",
1541f1785fbfSJes Sorensen 			 __func__);
1542f1785fbfSJes Sorensen 		ret = -EBUSY;
1543f1785fbfSJes Sorensen 		goto exit;
1544f1785fbfSJes Sorensen 	}
1545f1785fbfSJes Sorensen 
1546f1785fbfSJes Sorensen exit:
1547f1785fbfSJes Sorensen 	return ret;
1548f1785fbfSJes Sorensen }
1549f1785fbfSJes Sorensen 
rtl8192eu_emu_to_disabled(struct rtl8xxxu_priv * priv)1550f1785fbfSJes Sorensen static int rtl8192eu_emu_to_disabled(struct rtl8xxxu_priv *priv)
1551f1785fbfSJes Sorensen {
1552f1785fbfSJes Sorensen 	u8 val8;
1553f1785fbfSJes Sorensen 
1554f1785fbfSJes Sorensen 	/* 0x04[12:11] = 01 enable WL suspend */
1555f1785fbfSJes Sorensen 	val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1);
1556f1785fbfSJes Sorensen 	val8 &= ~(BIT(3) | BIT(4));
1557f1785fbfSJes Sorensen 	val8 |= BIT(3);
1558f1785fbfSJes Sorensen 	rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val8);
1559f1785fbfSJes Sorensen 
1560f1785fbfSJes Sorensen 	return 0;
1561f1785fbfSJes Sorensen }
1562f1785fbfSJes Sorensen 
rtl8192eu_power_on(struct rtl8xxxu_priv * priv)1563599119f6SJes Sorensen static int rtl8192eu_power_on(struct rtl8xxxu_priv *priv)
1564599119f6SJes Sorensen {
1565599119f6SJes Sorensen 	u16 val16;
1566599119f6SJes Sorensen 	u32 val32;
1567599119f6SJes Sorensen 	int ret;
1568599119f6SJes Sorensen 
1569599119f6SJes Sorensen 	val32 = rtl8xxxu_read32(priv, REG_SYS_CFG);
1570599119f6SJes Sorensen 	if (val32 & SYS_CFG_SPS_LDO_SEL) {
1571599119f6SJes Sorensen 		rtl8xxxu_write8(priv, REG_LDO_SW_CTRL, 0xc3);
1572599119f6SJes Sorensen 	} else {
1573599119f6SJes Sorensen 		/*
1574599119f6SJes Sorensen 		 * Raise 1.2V voltage
1575599119f6SJes Sorensen 		 */
1576599119f6SJes Sorensen 		val32 = rtl8xxxu_read32(priv, REG_8192E_LDOV12_CTRL);
1577599119f6SJes Sorensen 		val32 &= 0xff0fffff;
1578599119f6SJes Sorensen 		val32 |= 0x00500000;
1579599119f6SJes Sorensen 		rtl8xxxu_write32(priv, REG_8192E_LDOV12_CTRL, val32);
1580599119f6SJes Sorensen 		rtl8xxxu_write8(priv, REG_LDO_SW_CTRL, 0x83);
1581599119f6SJes Sorensen 	}
1582599119f6SJes Sorensen 
1583599119f6SJes Sorensen 	/*
1584599119f6SJes Sorensen 	 * Adjust AFE before enabling PLL
1585599119f6SJes Sorensen 	 */
1586599119f6SJes Sorensen 	rtl8192e_crystal_afe_adjust(priv);
1587599119f6SJes Sorensen 	rtl8192e_disabled_to_emu(priv);
1588599119f6SJes Sorensen 
1589599119f6SJes Sorensen 	ret = rtl8192e_emu_to_active(priv);
1590599119f6SJes Sorensen 	if (ret)
1591599119f6SJes Sorensen 		goto exit;
1592599119f6SJes Sorensen 
1593599119f6SJes Sorensen 	rtl8xxxu_write16(priv, REG_CR, 0x0000);
1594599119f6SJes Sorensen 
1595599119f6SJes Sorensen 	/*
1596599119f6SJes Sorensen 	 * Enable MAC DMA/WMAC/SCHEDULE/SEC block
1597599119f6SJes Sorensen 	 * Set CR bit10 to enable 32k calibration.
1598599119f6SJes Sorensen 	 */
1599599119f6SJes Sorensen 	val16 = rtl8xxxu_read16(priv, REG_CR);
1600599119f6SJes Sorensen 	val16 |= (CR_HCI_TXDMA_ENABLE | CR_HCI_RXDMA_ENABLE |
1601599119f6SJes Sorensen 		  CR_TXDMA_ENABLE | CR_RXDMA_ENABLE |
1602599119f6SJes Sorensen 		  CR_PROTOCOL_ENABLE | CR_SCHEDULE_ENABLE |
1603599119f6SJes Sorensen 		  CR_MAC_TX_ENABLE | CR_MAC_RX_ENABLE |
1604599119f6SJes Sorensen 		  CR_SECURITY_ENABLE | CR_CALTIMER_ENABLE);
1605599119f6SJes Sorensen 	rtl8xxxu_write16(priv, REG_CR, val16);
1606599119f6SJes Sorensen 
1607599119f6SJes Sorensen exit:
1608599119f6SJes Sorensen 	return ret;
1609599119f6SJes Sorensen }
1610599119f6SJes Sorensen 
rtl8192eu_power_off(struct rtl8xxxu_priv * priv)161113e1349aSWei Yongjun static void rtl8192eu_power_off(struct rtl8xxxu_priv *priv)
1612f1785fbfSJes Sorensen {
1613f1785fbfSJes Sorensen 	u8 val8;
1614f1785fbfSJes Sorensen 	u16 val16;
1615f1785fbfSJes Sorensen 
1616f1785fbfSJes Sorensen 	rtl8xxxu_flush_fifo(priv);
1617f1785fbfSJes Sorensen 
1618f1785fbfSJes Sorensen 	val8 = rtl8xxxu_read8(priv, REG_TX_REPORT_CTRL);
1619f1785fbfSJes Sorensen 	val8 &= ~TX_REPORT_CTRL_TIMER_ENABLE;
1620f1785fbfSJes Sorensen 	rtl8xxxu_write8(priv, REG_TX_REPORT_CTRL, val8);
1621f1785fbfSJes Sorensen 
1622f1785fbfSJes Sorensen 	/* Turn off RF */
1623f1785fbfSJes Sorensen 	rtl8xxxu_write8(priv, REG_RF_CTRL, 0x00);
1624f1785fbfSJes Sorensen 
1625f1785fbfSJes Sorensen 	rtl8192eu_active_to_lps(priv);
1626f1785fbfSJes Sorensen 
1627f1785fbfSJes Sorensen 	/* Reset Firmware if running in RAM */
1628f1785fbfSJes Sorensen 	if (rtl8xxxu_read8(priv, REG_MCU_FW_DL) & MCU_FW_RAM_SEL)
1629f1785fbfSJes Sorensen 		rtl8xxxu_firmware_self_reset(priv);
1630f1785fbfSJes Sorensen 
1631f1785fbfSJes Sorensen 	/* Reset MCU */
1632f1785fbfSJes Sorensen 	val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC);
1633f1785fbfSJes Sorensen 	val16 &= ~SYS_FUNC_CPU_ENABLE;
1634f1785fbfSJes Sorensen 	rtl8xxxu_write16(priv, REG_SYS_FUNC, val16);
1635f1785fbfSJes Sorensen 
1636f1785fbfSJes Sorensen 	/* Reset MCU ready status */
1637f1785fbfSJes Sorensen 	rtl8xxxu_write8(priv, REG_MCU_FW_DL, 0x00);
1638f1785fbfSJes Sorensen 
1639f1785fbfSJes Sorensen 	rtl8xxxu_reset_8051(priv);
1640f1785fbfSJes Sorensen 
1641f1785fbfSJes Sorensen 	rtl8192eu_active_to_emu(priv);
1642f1785fbfSJes Sorensen 	rtl8192eu_emu_to_disabled(priv);
1643f1785fbfSJes Sorensen }
1644f1785fbfSJes Sorensen 
rtl8192e_enable_rf(struct rtl8xxxu_priv * priv)1645599119f6SJes Sorensen static void rtl8192e_enable_rf(struct rtl8xxxu_priv *priv)
1646599119f6SJes Sorensen {
1647599119f6SJes Sorensen 	u32 val32;
1648599119f6SJes Sorensen 	u8 val8;
1649599119f6SJes Sorensen 
16505d03f882SJes Sorensen 	val32 = rtl8xxxu_read32(priv, REG_RX_WAIT_CCA);
16515d03f882SJes Sorensen 	val32 |= (BIT(22) | BIT(23));
16525d03f882SJes Sorensen 	rtl8xxxu_write32(priv, REG_RX_WAIT_CCA, val32);
16535d03f882SJes Sorensen 
1654599119f6SJes Sorensen 	val8 = rtl8xxxu_read8(priv, REG_GPIO_MUXCFG);
1655599119f6SJes Sorensen 	val8 |= BIT(5);
1656599119f6SJes Sorensen 	rtl8xxxu_write8(priv, REG_GPIO_MUXCFG, val8);
1657599119f6SJes Sorensen 
1658599119f6SJes Sorensen 	/*
1659599119f6SJes Sorensen 	 * WLAN action by PTA
1660599119f6SJes Sorensen 	 */
1661599119f6SJes Sorensen 	rtl8xxxu_write8(priv, REG_WLAN_ACT_CONTROL_8723B, 0x04);
1662599119f6SJes Sorensen 
1663599119f6SJes Sorensen 	val32 = rtl8xxxu_read32(priv, REG_PWR_DATA);
1664599119f6SJes Sorensen 	val32 |= PWR_DATA_EEPRPAD_RFE_CTRL_EN;
1665599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_PWR_DATA, val32);
1666599119f6SJes Sorensen 
1667599119f6SJes Sorensen 	val32 = rtl8xxxu_read32(priv, REG_RFE_BUFFER);
1668599119f6SJes Sorensen 	val32 |= (BIT(0) | BIT(1));
1669599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_RFE_BUFFER, val32);
1670599119f6SJes Sorensen 
1671599119f6SJes Sorensen 	rtl8xxxu_write8(priv, REG_RFE_CTRL_ANTA_SRC, 0x77);
1672599119f6SJes Sorensen 
1673599119f6SJes Sorensen 	val32 = rtl8xxxu_read32(priv, REG_LEDCFG0);
1674599119f6SJes Sorensen 	val32 &= ~BIT(24);
1675599119f6SJes Sorensen 	val32 |= BIT(23);
1676599119f6SJes Sorensen 	rtl8xxxu_write32(priv, REG_LEDCFG0, val32);
1677599119f6SJes Sorensen 
1678599119f6SJes Sorensen 	/*
1679599119f6SJes Sorensen 	 * Fix external switch Main->S1, Aux->S0
1680599119f6SJes Sorensen 	 */
1681599119f6SJes Sorensen 	val8 = rtl8xxxu_read8(priv, REG_PAD_CTRL1);
1682599119f6SJes Sorensen 	val8 &= ~BIT(0);
1683599119f6SJes Sorensen 	rtl8xxxu_write8(priv, REG_PAD_CTRL1, val8);
1684c6015bf3SJun ASAKA 
1685c6015bf3SJun ASAKA 	/*
1686c6015bf3SJun ASAKA 	 * Fix transmission failure of rtl8192e.
1687c6015bf3SJun ASAKA 	 */
1688c6015bf3SJun ASAKA 	rtl8xxxu_write8(priv, REG_TXPAUSE, 0x00);
1689599119f6SJes Sorensen }
1690599119f6SJes Sorensen 
rtl8192e_cck_rssi(struct rtl8xxxu_priv * priv,struct rtl8723au_phy_stats * phy_stats)169170664495SBitterblue Smith static s8 rtl8192e_cck_rssi(struct rtl8xxxu_priv *priv, struct rtl8723au_phy_stats *phy_stats)
16922ad2a813SBitterblue Smith {
16932ad2a813SBitterblue Smith 	static const s8 lna_gain_table_0[8] = {15, 9, -10, -21, -23, -27, -43, -44};
16942ad2a813SBitterblue Smith 	static const s8 lna_gain_table_1[8] = {24, 18, 13, -4, -11, -18, -31, -36};
16952ad2a813SBitterblue Smith 
169670664495SBitterblue Smith 	u8 cck_agc_rpt = phy_stats->cck_agc_rpt_ofdm_cfosho_a;
16972ad2a813SBitterblue Smith 	s8 rx_pwr_all = 0x00;
16982ad2a813SBitterblue Smith 	u8 vga_idx, lna_idx;
16992ad2a813SBitterblue Smith 	s8 lna_gain = 0;
17002ad2a813SBitterblue Smith 
1701b75289e8SBitterblue Smith 	lna_idx = u8_get_bits(cck_agc_rpt, CCK_AGC_RPT_LNA_IDX_MASK);
1702b75289e8SBitterblue Smith 	vga_idx = u8_get_bits(cck_agc_rpt, CCK_AGC_RPT_VGA_IDX_MASK);
17032ad2a813SBitterblue Smith 
17042ad2a813SBitterblue Smith 	if (priv->cck_agc_report_type == 0)
17052ad2a813SBitterblue Smith 		lna_gain = lna_gain_table_0[lna_idx];
17062ad2a813SBitterblue Smith 	else
17072ad2a813SBitterblue Smith 		lna_gain = lna_gain_table_1[lna_idx];
17082ad2a813SBitterblue Smith 
17092ad2a813SBitterblue Smith 	rx_pwr_all = lna_gain - (2 * vga_idx);
17102ad2a813SBitterblue Smith 
17112ad2a813SBitterblue Smith 	return rx_pwr_all;
17122ad2a813SBitterblue Smith }
17132ad2a813SBitterblue Smith 
rtl8192eu_led_brightness_set(struct led_classdev * led_cdev,enum led_brightness brightness)1714ae0a6df6SBitterblue Smith static int rtl8192eu_led_brightness_set(struct led_classdev *led_cdev,
1715ae0a6df6SBitterblue Smith 					enum led_brightness brightness)
1716ae0a6df6SBitterblue Smith {
1717ae0a6df6SBitterblue Smith 	struct rtl8xxxu_priv *priv = container_of(led_cdev,
1718ae0a6df6SBitterblue Smith 						  struct rtl8xxxu_priv,
1719ae0a6df6SBitterblue Smith 						  led_cdev);
1720ae0a6df6SBitterblue Smith 	u8 ledcfg = rtl8xxxu_read8(priv, REG_LEDCFG1);
1721ae0a6df6SBitterblue Smith 
1722ae0a6df6SBitterblue Smith 	if (brightness == LED_OFF) {
1723ae0a6df6SBitterblue Smith 		ledcfg &= ~LEDCFG1_HW_LED_CONTROL;
1724ae0a6df6SBitterblue Smith 		ledcfg |= LEDCFG1_LED_DISABLE;
1725ae0a6df6SBitterblue Smith 	} else if (brightness == LED_ON) {
1726ae0a6df6SBitterblue Smith 		ledcfg &= ~(LEDCFG1_HW_LED_CONTROL | LEDCFG1_LED_DISABLE);
1727ae0a6df6SBitterblue Smith 	} else if (brightness == RTL8XXXU_HW_LED_CONTROL) {
1728ae0a6df6SBitterblue Smith 		ledcfg &= ~LEDCFG1_LED_DISABLE;
1729ae0a6df6SBitterblue Smith 		ledcfg |= LEDCFG1_HW_LED_CONTROL;
1730ae0a6df6SBitterblue Smith 	}
1731ae0a6df6SBitterblue Smith 
1732ae0a6df6SBitterblue Smith 	rtl8xxxu_write8(priv, REG_LEDCFG1, ledcfg);
1733ae0a6df6SBitterblue Smith 
1734ae0a6df6SBitterblue Smith 	return 0;
1735ae0a6df6SBitterblue Smith }
1736ae0a6df6SBitterblue Smith 
1737599119f6SJes Sorensen struct rtl8xxxu_fileops rtl8192eu_fops = {
173814566bbfSBitterblue Smith 	.identify_chip = rtl8192eu_identify_chip,
1739599119f6SJes Sorensen 	.parse_efuse = rtl8192eu_parse_efuse,
1740599119f6SJes Sorensen 	.load_firmware = rtl8192eu_load_firmware,
1741599119f6SJes Sorensen 	.power_on = rtl8192eu_power_on,
1742f1785fbfSJes Sorensen 	.power_off = rtl8192eu_power_off,
174370664495SBitterblue Smith 	.read_efuse = rtl8xxxu_read_efuse,
1744599119f6SJes Sorensen 	.reset_8051 = rtl8xxxu_reset_8051,
1745599119f6SJes Sorensen 	.llt_init = rtl8xxxu_auto_llt_table,
1746599119f6SJes Sorensen 	.init_phy_bb = rtl8192eu_init_phy_bb,
1747599119f6SJes Sorensen 	.init_phy_rf = rtl8192eu_init_phy_rf,
1748c888183bSBitterblue Smith 	.phy_lc_calibrate = rtl8723a_phy_lc_calibrate,
1749599119f6SJes Sorensen 	.phy_iq_calibrate = rtl8192eu_phy_iq_calibrate,
1750599119f6SJes Sorensen 	.config_channel = rtl8xxxu_gen2_config_channel,
1751599119f6SJes Sorensen 	.parse_rx_desc = rtl8xxxu_parse_rxdesc24,
175270664495SBitterblue Smith 	.parse_phystats = rtl8723au_rx_parse_phystats,
1753599119f6SJes Sorensen 	.enable_rf = rtl8192e_enable_rf,
1754599119f6SJes Sorensen 	.disable_rf = rtl8xxxu_gen2_disable_rf,
1755599119f6SJes Sorensen 	.usb_quirks = rtl8xxxu_gen2_usb_quirks,
1756599119f6SJes Sorensen 	.set_tx_power = rtl8192e_set_tx_power,
1757599119f6SJes Sorensen 	.update_rate_mask = rtl8xxxu_gen2_update_rate_mask,
1758599119f6SJes Sorensen 	.report_connect = rtl8xxxu_gen2_report_connect,
17593922dc9fSBitterblue Smith 	.report_rssi = rtl8xxxu_gen2_report_rssi,
1760b59415c2SJes Sorensen 	.fill_txdesc = rtl8xxxu_fill_txdesc_v2,
176157b328bcSBitterblue Smith 	.set_crystal_cap = rtl8723a_set_crystal_cap,
17622ad2a813SBitterblue Smith 	.cck_rssi = rtl8192e_cck_rssi,
1763ae0a6df6SBitterblue Smith 	.led_classdev_brightness_set = rtl8192eu_led_brightness_set,
1764599119f6SJes Sorensen 	.writeN_block_size = 128,
1765599119f6SJes Sorensen 	.tx_desc_size = sizeof(struct rtl8xxxu_txdesc40),
1766599119f6SJes Sorensen 	.rx_desc_size = sizeof(struct rtl8xxxu_rxdesc24),
1767599119f6SJes Sorensen 	.has_s0s1 = 0,
1768eed145abSJes Sorensen 	.gen2_thermal_meter = 1,
1769d46e04ccSBitterblue Smith 	.needs_full_init = 1,
1770*8c34b621SBitterblue Smith 	.supports_ap = 1,
1771*8c34b621SBitterblue Smith 	.max_macid_num = 128,
1772599119f6SJes Sorensen 	.adda_1t_init = 0x0fc01616,
1773599119f6SJes Sorensen 	.adda_1t_path_on = 0x0fc01616,
1774599119f6SJes Sorensen 	.adda_2t_path_on_a = 0x0fc01616,
1775599119f6SJes Sorensen 	.adda_2t_path_on_b = 0x0fc01616,
1776599119f6SJes Sorensen 	.trxff_boundary = 0x3cff,
1777599119f6SJes Sorensen 	.mactable = rtl8192e_mac_init_table,
1778599119f6SJes Sorensen 	.total_page_num = TX_TOTAL_PAGE_NUM_8192E,
1779599119f6SJes Sorensen 	.page_num_hi = TX_PAGE_NUM_HI_PQ_8192E,
1780599119f6SJes Sorensen 	.page_num_lo = TX_PAGE_NUM_LO_PQ_8192E,
1781599119f6SJes Sorensen 	.page_num_norm = TX_PAGE_NUM_NORM_PQ_8192E,
1782599119f6SJes Sorensen };
1783