13dfb8e84SJes Sorensen // SPDX-License-Identifier: GPL-2.0-only
23dfb8e84SJes Sorensen /*
33dfb8e84SJes Sorensen * RTL8XXXU mac80211 USB driver - 8188e specific subdriver
43dfb8e84SJes Sorensen *
53dfb8e84SJes Sorensen * Copyright (c) 2014 - 2016 Jes Sorensen <Jes.Sorensen@gmail.com>
63dfb8e84SJes Sorensen *
73dfb8e84SJes Sorensen * Portions, notably calibration code:
83dfb8e84SJes Sorensen * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
93dfb8e84SJes Sorensen *
103dfb8e84SJes Sorensen * This driver was written as a replacement for the vendor provided
113dfb8e84SJes Sorensen * rtl8723au driver. As the Realtek 8xxx chips are very similar in
123dfb8e84SJes Sorensen * their programming interface, I have started adding support for
133dfb8e84SJes Sorensen * additional 8xxx chips like the 8192cu, 8188cus, etc.
143dfb8e84SJes Sorensen */
153dfb8e84SJes Sorensen
16028fa281SKalle Valo #include "regs.h"
17949f6f3aSPing-Ke Shih #include "rtl8xxxu.h"
183dfb8e84SJes Sorensen
193dfb8e84SJes Sorensen static const struct rtl8xxxu_reg8val rtl8188e_mac_init_table[] = {
203dfb8e84SJes Sorensen {0x026, 0x41}, {0x027, 0x35}, {0x040, 0x00}, {0x421, 0x0f},
213dfb8e84SJes Sorensen {0x428, 0x0a}, {0x429, 0x10}, {0x430, 0x00}, {0x431, 0x01},
223dfb8e84SJes Sorensen {0x432, 0x02}, {0x433, 0x04}, {0x434, 0x05}, {0x435, 0x06},
233dfb8e84SJes Sorensen {0x436, 0x07}, {0x437, 0x08}, {0x438, 0x00}, {0x439, 0x00},
243dfb8e84SJes Sorensen {0x43a, 0x01}, {0x43b, 0x02}, {0x43c, 0x04}, {0x43d, 0x05},
253dfb8e84SJes Sorensen {0x43e, 0x06}, {0x43f, 0x07}, {0x440, 0x5d}, {0x441, 0x01},
263dfb8e84SJes Sorensen {0x442, 0x00}, {0x444, 0x15}, {0x445, 0xf0}, {0x446, 0x0f},
273dfb8e84SJes Sorensen {0x447, 0x00}, {0x458, 0x41}, {0x459, 0xa8}, {0x45a, 0x72},
283dfb8e84SJes Sorensen {0x45b, 0xb9}, {0x460, 0x66}, {0x461, 0x66}, {0x480, 0x08},
293dfb8e84SJes Sorensen {0x4c8, 0xff}, {0x4c9, 0x08}, {0x4cc, 0xff}, {0x4cd, 0xff},
303dfb8e84SJes Sorensen {0x4ce, 0x01}, {0x4d3, 0x01}, {0x500, 0x26}, {0x501, 0xa2},
313dfb8e84SJes Sorensen {0x502, 0x2f}, {0x503, 0x00}, {0x504, 0x28}, {0x505, 0xa3},
323dfb8e84SJes Sorensen {0x506, 0x5e}, {0x507, 0x00}, {0x508, 0x2b}, {0x509, 0xa4},
333dfb8e84SJes Sorensen {0x50a, 0x5e}, {0x50b, 0x00}, {0x50c, 0x4f}, {0x50d, 0xa4},
343dfb8e84SJes Sorensen {0x50e, 0x00}, {0x50f, 0x00}, {0x512, 0x1c}, {0x514, 0x0a},
353dfb8e84SJes Sorensen {0x516, 0x0a}, {0x525, 0x4f}, {0x550, 0x10}, {0x551, 0x10},
363dfb8e84SJes Sorensen {0x559, 0x02}, {0x55d, 0xff}, {0x605, 0x30}, {0x608, 0x0e},
373dfb8e84SJes Sorensen {0x609, 0x2a}, {0x620, 0xff}, {0x621, 0xff}, {0x622, 0xff},
383dfb8e84SJes Sorensen {0x623, 0xff}, {0x624, 0xff}, {0x625, 0xff}, {0x626, 0xff},
393dfb8e84SJes Sorensen {0x627, 0xff}, {0x63c, 0x08}, {0x63d, 0x08}, {0x63e, 0x0c},
403dfb8e84SJes Sorensen {0x63f, 0x0c}, {0x640, 0x40}, {0x652, 0x20}, {0x66e, 0x05},
413dfb8e84SJes Sorensen {0x700, 0x21}, {0x701, 0x43}, {0x702, 0x65}, {0x703, 0x87},
423dfb8e84SJes Sorensen {0x708, 0x21}, {0x709, 0x43}, {0x70a, 0x65}, {0x70b, 0x87},
433dfb8e84SJes Sorensen {0xffff, 0xff},
443dfb8e84SJes Sorensen };
453dfb8e84SJes Sorensen
463dfb8e84SJes Sorensen static const struct rtl8xxxu_reg32val rtl8188eu_phy_init_table[] = {
473dfb8e84SJes Sorensen {0x800, 0x80040000}, {0x804, 0x00000003},
483dfb8e84SJes Sorensen {0x808, 0x0000fc00}, {0x80c, 0x0000000a},
493dfb8e84SJes Sorensen {0x810, 0x10001331}, {0x814, 0x020c3d10},
503dfb8e84SJes Sorensen {0x818, 0x02200385}, {0x81c, 0x00000000},
513dfb8e84SJes Sorensen {0x820, 0x01000100}, {0x824, 0x00390204},
523dfb8e84SJes Sorensen {0x828, 0x00000000}, {0x82c, 0x00000000},
533dfb8e84SJes Sorensen {0x830, 0x00000000}, {0x834, 0x00000000},
543dfb8e84SJes Sorensen {0x838, 0x00000000}, {0x83c, 0x00000000},
553dfb8e84SJes Sorensen {0x840, 0x00010000}, {0x844, 0x00000000},
563dfb8e84SJes Sorensen {0x848, 0x00000000}, {0x84c, 0x00000000},
573dfb8e84SJes Sorensen {0x850, 0x00000000}, {0x854, 0x00000000},
583dfb8e84SJes Sorensen {0x858, 0x569a11a9}, {0x85c, 0x01000014},
593dfb8e84SJes Sorensen {0x860, 0x66f60110}, {0x864, 0x061f0649},
603dfb8e84SJes Sorensen {0x868, 0x00000000}, {0x86c, 0x27272700},
613dfb8e84SJes Sorensen {0x870, 0x07000760}, {0x874, 0x25004000},
623dfb8e84SJes Sorensen {0x878, 0x00000808}, {0x87c, 0x00000000},
633dfb8e84SJes Sorensen {0x880, 0xb0000c1c}, {0x884, 0x00000001},
643dfb8e84SJes Sorensen {0x888, 0x00000000}, {0x88c, 0xccc000c0},
653dfb8e84SJes Sorensen {0x890, 0x00000800}, {0x894, 0xfffffffe},
663dfb8e84SJes Sorensen {0x898, 0x40302010}, {0x89c, 0x00706050},
673dfb8e84SJes Sorensen {0x900, 0x00000000}, {0x904, 0x00000023},
683dfb8e84SJes Sorensen {0x908, 0x00000000}, {0x90c, 0x81121111},
693dfb8e84SJes Sorensen {0x910, 0x00000002}, {0x914, 0x00000201},
703dfb8e84SJes Sorensen {0xa00, 0x00d047c8}, {0xa04, 0x80ff800c},
713dfb8e84SJes Sorensen {0xa08, 0x8c838300}, {0xa0c, 0x2e7f120f},
723dfb8e84SJes Sorensen {0xa10, 0x9500bb7e}, {0xa14, 0x1114d028},
733dfb8e84SJes Sorensen {0xa18, 0x00881117}, {0xa1c, 0x89140f00},
743dfb8e84SJes Sorensen {0xa20, 0x1a1b0000}, {0xa24, 0x090e1317},
753dfb8e84SJes Sorensen {0xa28, 0x00000204}, {0xa2c, 0x00d30000},
763dfb8e84SJes Sorensen {0xa70, 0x101fbf00}, {0xa74, 0x00000007},
773dfb8e84SJes Sorensen {0xa78, 0x00000900}, {0xa7c, 0x225b0606},
783dfb8e84SJes Sorensen {0xa80, 0x218075b1}, {0xb2c, 0x80000000},
793dfb8e84SJes Sorensen {0xc00, 0x48071d40}, {0xc04, 0x03a05611},
803dfb8e84SJes Sorensen {0xc08, 0x000000e4}, {0xc0c, 0x6c6c6c6c},
813dfb8e84SJes Sorensen {0xc10, 0x08800000}, {0xc14, 0x40000100},
823dfb8e84SJes Sorensen {0xc18, 0x08800000}, {0xc1c, 0x40000100},
833dfb8e84SJes Sorensen {0xc20, 0x00000000}, {0xc24, 0x00000000},
843dfb8e84SJes Sorensen {0xc28, 0x00000000}, {0xc2c, 0x00000000},
853dfb8e84SJes Sorensen {0xc30, 0x69e9ac47}, {0xc34, 0x469652af},
863dfb8e84SJes Sorensen {0xc38, 0x49795994}, {0xc3c, 0x0a97971c},
873dfb8e84SJes Sorensen {0xc40, 0x1f7c403f}, {0xc44, 0x000100b7},
883dfb8e84SJes Sorensen {0xc48, 0xec020107}, {0xc4c, 0x007f037f},
893dfb8e84SJes Sorensen {0xc50, 0x69553420}, {0xc54, 0x43bc0094},
903dfb8e84SJes Sorensen {0xc58, 0x00013169}, {0xc5c, 0x00250492},
913dfb8e84SJes Sorensen {0xc60, 0x00000000}, {0xc64, 0x7112848b},
923dfb8e84SJes Sorensen {0xc68, 0x47c00bff}, {0xc6c, 0x00000036},
933dfb8e84SJes Sorensen {0xc70, 0x2c7f000d}, {0xc74, 0x020610db},
943dfb8e84SJes Sorensen {0xc78, 0x0000001f}, {0xc7c, 0x00b91612},
953dfb8e84SJes Sorensen {0xc80, 0x390000e4}, {0xc84, 0x21f60000},
963dfb8e84SJes Sorensen {0xc88, 0x40000100}, {0xc8c, 0x20200000},
973dfb8e84SJes Sorensen {0xc90, 0x00091521}, {0xc94, 0x00000000},
983dfb8e84SJes Sorensen {0xc98, 0x00121820}, {0xc9c, 0x00007f7f},
993dfb8e84SJes Sorensen {0xca0, 0x00000000}, {0xca4, 0x000300a0},
1003dfb8e84SJes Sorensen {0xca8, 0x00000000}, {0xcac, 0x00000000},
1013dfb8e84SJes Sorensen {0xcb0, 0x00000000}, {0xcb4, 0x00000000},
1023dfb8e84SJes Sorensen {0xcb8, 0x00000000}, {0xcbc, 0x28000000},
1033dfb8e84SJes Sorensen {0xcc0, 0x00000000}, {0xcc4, 0x00000000},
1043dfb8e84SJes Sorensen {0xcc8, 0x00000000}, {0xccc, 0x00000000},
1053dfb8e84SJes Sorensen {0xcd0, 0x00000000}, {0xcd4, 0x00000000},
1063dfb8e84SJes Sorensen {0xcd8, 0x64b22427}, {0xcdc, 0x00766932},
1073dfb8e84SJes Sorensen {0xce0, 0x00222222}, {0xce4, 0x00000000},
1083dfb8e84SJes Sorensen {0xce8, 0x37644302}, {0xcec, 0x2f97d40c},
1093dfb8e84SJes Sorensen {0xd00, 0x00000740}, {0xd04, 0x00020401},
1103dfb8e84SJes Sorensen {0xd08, 0x0000907f}, {0xd0c, 0x20010201},
1113dfb8e84SJes Sorensen {0xd10, 0xa0633333}, {0xd14, 0x3333bc43},
1123dfb8e84SJes Sorensen {0xd18, 0x7a8f5b6f}, {0xd2c, 0xcc979975},
1133dfb8e84SJes Sorensen {0xd30, 0x00000000}, {0xd34, 0x80608000},
1143dfb8e84SJes Sorensen {0xd38, 0x00000000}, {0xd3c, 0x00127353},
1153dfb8e84SJes Sorensen {0xd40, 0x00000000}, {0xd44, 0x00000000},
1163dfb8e84SJes Sorensen {0xd48, 0x00000000}, {0xd4c, 0x00000000},
1173dfb8e84SJes Sorensen {0xd50, 0x6437140a}, {0xd54, 0x00000000},
1183dfb8e84SJes Sorensen {0xd58, 0x00000282}, {0xd5c, 0x30032064},
1193dfb8e84SJes Sorensen {0xd60, 0x4653de68}, {0xd64, 0x04518a3c},
1203dfb8e84SJes Sorensen {0xd68, 0x00002101}, {0xd6c, 0x2a201c16},
1213dfb8e84SJes Sorensen {0xd70, 0x1812362e}, {0xd74, 0x322c2220},
1223dfb8e84SJes Sorensen {0xd78, 0x000e3c24}, {0xe00, 0x2d2d2d2d},
1233dfb8e84SJes Sorensen {0xe04, 0x2d2d2d2d}, {0xe08, 0x0390272d},
1243dfb8e84SJes Sorensen {0xe10, 0x2d2d2d2d}, {0xe14, 0x2d2d2d2d},
1253dfb8e84SJes Sorensen {0xe18, 0x2d2d2d2d}, {0xe1c, 0x2d2d2d2d},
1263dfb8e84SJes Sorensen {0xe28, 0x00000000}, {0xe30, 0x1000dc1f},
1273dfb8e84SJes Sorensen {0xe34, 0x10008c1f}, {0xe38, 0x02140102},
1283dfb8e84SJes Sorensen {0xe3c, 0x681604c2}, {0xe40, 0x01007c00},
1293dfb8e84SJes Sorensen {0xe44, 0x01004800}, {0xe48, 0xfb000000},
1303dfb8e84SJes Sorensen {0xe4c, 0x000028d1}, {0xe50, 0x1000dc1f},
1313dfb8e84SJes Sorensen {0xe54, 0x10008c1f}, {0xe58, 0x02140102},
1323dfb8e84SJes Sorensen {0xe5c, 0x28160d05}, {0xe60, 0x00000048},
1333dfb8e84SJes Sorensen {0xe68, 0x001b25a4}, {0xe6c, 0x00c00014},
1343dfb8e84SJes Sorensen {0xe70, 0x00c00014}, {0xe74, 0x01000014},
1353dfb8e84SJes Sorensen {0xe78, 0x01000014}, {0xe7c, 0x01000014},
1363dfb8e84SJes Sorensen {0xe80, 0x01000014}, {0xe84, 0x00c00014},
1373dfb8e84SJes Sorensen {0xe88, 0x01000014}, {0xe8c, 0x00c00014},
1383dfb8e84SJes Sorensen {0xed0, 0x00c00014}, {0xed4, 0x00c00014},
1393dfb8e84SJes Sorensen {0xed8, 0x00c00014}, {0xedc, 0x00000014},
1403dfb8e84SJes Sorensen {0xee0, 0x00000014}, {0xee8, 0x21555448},
1413dfb8e84SJes Sorensen {0xeec, 0x01c00014}, {0xf14, 0x00000003},
1423dfb8e84SJes Sorensen {0xf4c, 0x00000000}, {0xf00, 0x00000300},
1433dfb8e84SJes Sorensen {0xffff, 0xffffffff},
1443dfb8e84SJes Sorensen };
1453dfb8e84SJes Sorensen
1463dfb8e84SJes Sorensen static const struct rtl8xxxu_reg32val rtl8188e_agc_table[] = {
1473dfb8e84SJes Sorensen {0xc78, 0xfb000001}, {0xc78, 0xfb010001},
1483dfb8e84SJes Sorensen {0xc78, 0xfb020001}, {0xc78, 0xfb030001},
1493dfb8e84SJes Sorensen {0xc78, 0xfb040001}, {0xc78, 0xfb050001},
1503dfb8e84SJes Sorensen {0xc78, 0xfa060001}, {0xc78, 0xf9070001},
1513dfb8e84SJes Sorensen {0xc78, 0xf8080001}, {0xc78, 0xf7090001},
1523dfb8e84SJes Sorensen {0xc78, 0xf60a0001}, {0xc78, 0xf50b0001},
1533dfb8e84SJes Sorensen {0xc78, 0xf40c0001}, {0xc78, 0xf30d0001},
1543dfb8e84SJes Sorensen {0xc78, 0xf20e0001}, {0xc78, 0xf10f0001},
1553dfb8e84SJes Sorensen {0xc78, 0xf0100001}, {0xc78, 0xef110001},
1563dfb8e84SJes Sorensen {0xc78, 0xee120001}, {0xc78, 0xed130001},
1573dfb8e84SJes Sorensen {0xc78, 0xec140001}, {0xc78, 0xeb150001},
1583dfb8e84SJes Sorensen {0xc78, 0xea160001}, {0xc78, 0xe9170001},
1593dfb8e84SJes Sorensen {0xc78, 0xe8180001}, {0xc78, 0xe7190001},
1603dfb8e84SJes Sorensen {0xc78, 0xe61a0001}, {0xc78, 0xe51b0001},
1613dfb8e84SJes Sorensen {0xc78, 0xe41c0001}, {0xc78, 0xe31d0001},
1623dfb8e84SJes Sorensen {0xc78, 0xe21e0001}, {0xc78, 0xe11f0001},
1633dfb8e84SJes Sorensen {0xc78, 0x8a200001}, {0xc78, 0x89210001},
1643dfb8e84SJes Sorensen {0xc78, 0x88220001}, {0xc78, 0x87230001},
1653dfb8e84SJes Sorensen {0xc78, 0x86240001}, {0xc78, 0x85250001},
1663dfb8e84SJes Sorensen {0xc78, 0x84260001}, {0xc78, 0x83270001},
1673dfb8e84SJes Sorensen {0xc78, 0x82280001}, {0xc78, 0x6b290001},
1683dfb8e84SJes Sorensen {0xc78, 0x6a2a0001}, {0xc78, 0x692b0001},
1693dfb8e84SJes Sorensen {0xc78, 0x682c0001}, {0xc78, 0x672d0001},
1703dfb8e84SJes Sorensen {0xc78, 0x662e0001}, {0xc78, 0x652f0001},
1713dfb8e84SJes Sorensen {0xc78, 0x64300001}, {0xc78, 0x63310001},
1723dfb8e84SJes Sorensen {0xc78, 0x62320001}, {0xc78, 0x61330001},
1733dfb8e84SJes Sorensen {0xc78, 0x46340001}, {0xc78, 0x45350001},
1743dfb8e84SJes Sorensen {0xc78, 0x44360001}, {0xc78, 0x43370001},
1753dfb8e84SJes Sorensen {0xc78, 0x42380001}, {0xc78, 0x41390001},
1763dfb8e84SJes Sorensen {0xc78, 0x403a0001}, {0xc78, 0x403b0001},
1773dfb8e84SJes Sorensen {0xc78, 0x403c0001}, {0xc78, 0x403d0001},
1783dfb8e84SJes Sorensen {0xc78, 0x403e0001}, {0xc78, 0x403f0001},
1793dfb8e84SJes Sorensen {0xc78, 0xfb400001}, {0xc78, 0xfb410001},
1803dfb8e84SJes Sorensen {0xc78, 0xfb420001}, {0xc78, 0xfb430001},
1813dfb8e84SJes Sorensen {0xc78, 0xfb440001}, {0xc78, 0xfb450001},
1823dfb8e84SJes Sorensen {0xc78, 0xfb460001}, {0xc78, 0xfb470001},
1833dfb8e84SJes Sorensen {0xc78, 0xfb480001}, {0xc78, 0xfa490001},
1843dfb8e84SJes Sorensen {0xc78, 0xf94a0001}, {0xc78, 0xf84b0001},
1853dfb8e84SJes Sorensen {0xc78, 0xf74c0001}, {0xc78, 0xf64d0001},
1863dfb8e84SJes Sorensen {0xc78, 0xf54e0001}, {0xc78, 0xf44f0001},
1873dfb8e84SJes Sorensen {0xc78, 0xf3500001}, {0xc78, 0xf2510001},
1883dfb8e84SJes Sorensen {0xc78, 0xf1520001}, {0xc78, 0xf0530001},
1893dfb8e84SJes Sorensen {0xc78, 0xef540001}, {0xc78, 0xee550001},
1903dfb8e84SJes Sorensen {0xc78, 0xed560001}, {0xc78, 0xec570001},
1913dfb8e84SJes Sorensen {0xc78, 0xeb580001}, {0xc78, 0xea590001},
1923dfb8e84SJes Sorensen {0xc78, 0xe95a0001}, {0xc78, 0xe85b0001},
1933dfb8e84SJes Sorensen {0xc78, 0xe75c0001}, {0xc78, 0xe65d0001},
1943dfb8e84SJes Sorensen {0xc78, 0xe55e0001}, {0xc78, 0xe45f0001},
1953dfb8e84SJes Sorensen {0xc78, 0xe3600001}, {0xc78, 0xe2610001},
1963dfb8e84SJes Sorensen {0xc78, 0xc3620001}, {0xc78, 0xc2630001},
1973dfb8e84SJes Sorensen {0xc78, 0xc1640001}, {0xc78, 0x8b650001},
1983dfb8e84SJes Sorensen {0xc78, 0x8a660001}, {0xc78, 0x89670001},
1993dfb8e84SJes Sorensen {0xc78, 0x88680001}, {0xc78, 0x87690001},
2003dfb8e84SJes Sorensen {0xc78, 0x866a0001}, {0xc78, 0x856b0001},
2013dfb8e84SJes Sorensen {0xc78, 0x846c0001}, {0xc78, 0x676d0001},
2023dfb8e84SJes Sorensen {0xc78, 0x666e0001}, {0xc78, 0x656f0001},
2033dfb8e84SJes Sorensen {0xc78, 0x64700001}, {0xc78, 0x63710001},
2043dfb8e84SJes Sorensen {0xc78, 0x62720001}, {0xc78, 0x61730001},
2053dfb8e84SJes Sorensen {0xc78, 0x60740001}, {0xc78, 0x46750001},
2063dfb8e84SJes Sorensen {0xc78, 0x45760001}, {0xc78, 0x44770001},
2073dfb8e84SJes Sorensen {0xc78, 0x43780001}, {0xc78, 0x42790001},
2083dfb8e84SJes Sorensen {0xc78, 0x417a0001}, {0xc78, 0x407b0001},
2093dfb8e84SJes Sorensen {0xc78, 0x407c0001}, {0xc78, 0x407d0001},
2103dfb8e84SJes Sorensen {0xc78, 0x407e0001}, {0xc78, 0x407f0001},
2113dfb8e84SJes Sorensen {0xc50, 0x69553422}, {0xc50, 0x69553420},
2123dfb8e84SJes Sorensen {0xffff, 0xffffffff}
2133dfb8e84SJes Sorensen };
2143dfb8e84SJes Sorensen
2153dfb8e84SJes Sorensen static const struct rtl8xxxu_rfregval rtl8188eu_radioa_init_table[] = {
2163dfb8e84SJes Sorensen {0x00, 0x00030000}, {0x08, 0x00084000},
2173dfb8e84SJes Sorensen {0x18, 0x00000407}, {0x19, 0x00000012},
2183dfb8e84SJes Sorensen {0x1e, 0x00080009}, {0x1f, 0x00000880},
2193dfb8e84SJes Sorensen {0x2f, 0x0001a060}, {0x3f, 0x00000000},
2203dfb8e84SJes Sorensen {0x42, 0x000060c0}, {0x57, 0x000d0000},
2213dfb8e84SJes Sorensen {0x58, 0x000be180}, {0x67, 0x00001552},
2223dfb8e84SJes Sorensen {0x83, 0x00000000}, {0xb0, 0x000ff8fc},
2233dfb8e84SJes Sorensen {0xb1, 0x00054400}, {0xb2, 0x000ccc19},
2243dfb8e84SJes Sorensen {0xb4, 0x00043003}, {0xb6, 0x0004953e},
2253dfb8e84SJes Sorensen {0xb7, 0x0001c718}, {0xb8, 0x000060ff},
2263dfb8e84SJes Sorensen {0xb9, 0x00080001}, {0xba, 0x00040000},
2273dfb8e84SJes Sorensen {0xbb, 0x00000400}, {0xbf, 0x000c0000},
2283dfb8e84SJes Sorensen {0xc2, 0x00002400}, {0xc3, 0x00000009},
2293dfb8e84SJes Sorensen {0xc4, 0x00040c91}, {0xc5, 0x00099999},
2303dfb8e84SJes Sorensen {0xc6, 0x000000a3}, {0xc7, 0x00088820},
2313dfb8e84SJes Sorensen {0xc8, 0x00076c06}, {0xc9, 0x00000000},
2323dfb8e84SJes Sorensen {0xca, 0x00080000}, {0xdf, 0x00000180},
2333dfb8e84SJes Sorensen {0xef, 0x000001a0}, {0x51, 0x0006b27d},
2343dfb8e84SJes Sorensen {0x52, 0x0007e49d}, /* Set to 0x0007e4dd for SDIO */
2353dfb8e84SJes Sorensen {0x53, 0x00000073}, {0x56, 0x00051ff3},
2363dfb8e84SJes Sorensen {0x35, 0x00000086}, {0x35, 0x00000186},
2373dfb8e84SJes Sorensen {0x35, 0x00000286}, {0x36, 0x00001c25},
2383dfb8e84SJes Sorensen {0x36, 0x00009c25}, {0x36, 0x00011c25},
2393dfb8e84SJes Sorensen {0x36, 0x00019c25}, {0xb6, 0x00048538},
2403dfb8e84SJes Sorensen {0x18, 0x00000c07}, {0x5a, 0x0004bd00},
2413dfb8e84SJes Sorensen {0x19, 0x000739d0}, {0x34, 0x0000adf3},
2423dfb8e84SJes Sorensen {0x34, 0x00009df0}, {0x34, 0x00008ded},
2433dfb8e84SJes Sorensen {0x34, 0x00007dea}, {0x34, 0x00006de7},
2443dfb8e84SJes Sorensen {0x34, 0x000054ee}, {0x34, 0x000044eb},
2453dfb8e84SJes Sorensen {0x34, 0x000034e8}, {0x34, 0x0000246b},
2463dfb8e84SJes Sorensen {0x34, 0x00001468}, {0x34, 0x0000006d},
2473dfb8e84SJes Sorensen {0x00, 0x00030159}, {0x84, 0x00068200},
2483dfb8e84SJes Sorensen {0x86, 0x000000ce}, {0x87, 0x00048a00},
2493dfb8e84SJes Sorensen {0x8e, 0x00065540}, {0x8f, 0x00088000},
2503dfb8e84SJes Sorensen {0xef, 0x000020a0}, {0x3b, 0x000f02b0},
2513dfb8e84SJes Sorensen {0x3b, 0x000ef7b0}, {0x3b, 0x000d4fb0},
2523dfb8e84SJes Sorensen {0x3b, 0x000cf060}, {0x3b, 0x000b0090},
2533dfb8e84SJes Sorensen {0x3b, 0x000a0080}, {0x3b, 0x00090080},
2543dfb8e84SJes Sorensen {0x3b, 0x0008f780}, {0x3b, 0x000722b0},
2553dfb8e84SJes Sorensen {0x3b, 0x0006f7b0}, {0x3b, 0x00054fb0},
2563dfb8e84SJes Sorensen {0x3b, 0x0004f060}, {0x3b, 0x00030090},
2573dfb8e84SJes Sorensen {0x3b, 0x00020080}, {0x3b, 0x00010080},
2583dfb8e84SJes Sorensen {0x3b, 0x0000f780}, {0xef, 0x000000a0},
2593dfb8e84SJes Sorensen {0x00, 0x00010159}, {0x18, 0x0000f407},
2603dfb8e84SJes Sorensen {0xFE, 0x00000000}, {0xFE, 0x00000000},
2613dfb8e84SJes Sorensen {0x1F, 0x00080003}, {0xFE, 0x00000000},
2623dfb8e84SJes Sorensen {0xFE, 0x00000000}, {0x1E, 0x00000001},
2633dfb8e84SJes Sorensen {0x1F, 0x00080000}, {0x00, 0x00033e60},
2643dfb8e84SJes Sorensen {0xff, 0xffffffff}
2653dfb8e84SJes Sorensen };
2663dfb8e84SJes Sorensen
2678b9754b2SBitterblue Smith #define PERENTRY 23
2688b9754b2SBitterblue Smith #define RETRYSIZE 5
2698b9754b2SBitterblue Smith #define RATESIZE 28
2708b9754b2SBitterblue Smith #define TX_RPT2_ITEM_SIZE 8
2718b9754b2SBitterblue Smith
2728b9754b2SBitterblue Smith static const u8 retry_penalty[PERENTRY][RETRYSIZE + 1] = {
2738b9754b2SBitterblue Smith {5, 4, 3, 2, 0, 3}, /* 92 , idx=0 */
2748b9754b2SBitterblue Smith {6, 5, 4, 3, 0, 4}, /* 86 , idx=1 */
2758b9754b2SBitterblue Smith {6, 5, 4, 2, 0, 4}, /* 81 , idx=2 */
2768b9754b2SBitterblue Smith {8, 7, 6, 4, 0, 6}, /* 75 , idx=3 */
2778b9754b2SBitterblue Smith {10, 9, 8, 6, 0, 8}, /* 71 , idx=4 */
2788b9754b2SBitterblue Smith {10, 9, 8, 4, 0, 8}, /* 66 , idx=5 */
2798b9754b2SBitterblue Smith {10, 9, 8, 2, 0, 8}, /* 62 , idx=6 */
2808b9754b2SBitterblue Smith {10, 9, 8, 0, 0, 8}, /* 59 , idx=7 */
2818b9754b2SBitterblue Smith {18, 17, 16, 8, 0, 16}, /* 53 , idx=8 */
2828b9754b2SBitterblue Smith {26, 25, 24, 16, 0, 24}, /* 50 , idx=9 */
2838b9754b2SBitterblue Smith {34, 33, 32, 24, 0, 32}, /* 47 , idx=0x0a */
2848b9754b2SBitterblue Smith {34, 31, 28, 20, 0, 32}, /* 43 , idx=0x0b */
2858b9754b2SBitterblue Smith {34, 31, 27, 18, 0, 32}, /* 40 , idx=0x0c */
2868b9754b2SBitterblue Smith {34, 31, 26, 16, 0, 32}, /* 37 , idx=0x0d */
2878b9754b2SBitterblue Smith {34, 30, 22, 16, 0, 32}, /* 32 , idx=0x0e */
2888b9754b2SBitterblue Smith {34, 30, 24, 16, 0, 32}, /* 26 , idx=0x0f */
2898b9754b2SBitterblue Smith {49, 46, 40, 16, 0, 48}, /* 20 , idx=0x10 */
2908b9754b2SBitterblue Smith {49, 45, 32, 0, 0, 48}, /* 17 , idx=0x11 */
2918b9754b2SBitterblue Smith {49, 45, 22, 18, 0, 48}, /* 15 , idx=0x12 */
2928b9754b2SBitterblue Smith {49, 40, 24, 16, 0, 48}, /* 12 , idx=0x13 */
2938b9754b2SBitterblue Smith {49, 32, 18, 12, 0, 48}, /* 9 , idx=0x14 */
2948b9754b2SBitterblue Smith {49, 22, 18, 14, 0, 48}, /* 6 , idx=0x15 */
2958b9754b2SBitterblue Smith {49, 16, 16, 0, 0, 48} /* 3, idx=0x16 */
2968b9754b2SBitterblue Smith };
2978b9754b2SBitterblue Smith
2988b9754b2SBitterblue Smith static const u8 pt_penalty[RETRYSIZE + 1] = {34, 31, 30, 24, 0, 32};
2998b9754b2SBitterblue Smith
3008b9754b2SBitterblue Smith static const u8 retry_penalty_idx_normal[2][RATESIZE] = {
3018b9754b2SBitterblue Smith { /* RSSI>TH */
3028b9754b2SBitterblue Smith 4, 4, 4, 5,
3038b9754b2SBitterblue Smith 4, 4, 5, 7, 7, 7, 8, 0x0a,
3048b9754b2SBitterblue Smith 4, 4, 4, 4, 6, 0x0a, 0x0b, 0x0d,
3058b9754b2SBitterblue Smith 5, 5, 7, 7, 8, 0x0b, 0x0d, 0x0f
3068b9754b2SBitterblue Smith },
3078b9754b2SBitterblue Smith { /* RSSI<TH */
3088b9754b2SBitterblue Smith 0x0a, 0x0a, 0x0b, 0x0c,
3098b9754b2SBitterblue Smith 0x0a, 0x0a, 0x0b, 0x0c, 0x0d, 0x10, 0x13, 0x13,
3108b9754b2SBitterblue Smith 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x11, 0x13, 0x13,
3118b9754b2SBitterblue Smith 9, 9, 9, 9, 0x0c, 0x0e, 0x11, 0x13
3128b9754b2SBitterblue Smith }
3138b9754b2SBitterblue Smith };
3148b9754b2SBitterblue Smith
3158b9754b2SBitterblue Smith static const u8 retry_penalty_idx_cut_i[2][RATESIZE] = {
3168b9754b2SBitterblue Smith { /* RSSI>TH */
3178b9754b2SBitterblue Smith 4, 4, 4, 5,
3188b9754b2SBitterblue Smith 4, 4, 5, 7, 7, 7, 8, 0x0a,
3198b9754b2SBitterblue Smith 4, 4, 4, 4, 6, 0x0a, 0x0b, 0x0d,
3208b9754b2SBitterblue Smith 5, 5, 7, 7, 8, 0x0b, 0x0d, 0x0f
3218b9754b2SBitterblue Smith },
3228b9754b2SBitterblue Smith { /* RSSI<TH */
3238b9754b2SBitterblue Smith 0x0a, 0x0a, 0x0b, 0x0c,
3248b9754b2SBitterblue Smith 0x0a, 0x0a, 0x0b, 0x0c, 0x0d, 0x10, 0x13, 0x13,
3258b9754b2SBitterblue Smith 0x06, 0x07, 0x08, 0x0d, 0x0e, 0x11, 0x11, 0x11,
3268b9754b2SBitterblue Smith 9, 9, 9, 9, 0x0c, 0x0e, 0x11, 0x13
3278b9754b2SBitterblue Smith }
3288b9754b2SBitterblue Smith };
3298b9754b2SBitterblue Smith
3308b9754b2SBitterblue Smith static const u8 retry_penalty_up_idx_normal[RATESIZE] = {
3318b9754b2SBitterblue Smith 0x0c, 0x0d, 0x0d, 0x0f,
3328b9754b2SBitterblue Smith 0x0d, 0x0e, 0x0f, 0x0f, 0x10, 0x12, 0x13, 0x14,
3338b9754b2SBitterblue Smith 0x0f, 0x10, 0x10, 0x12, 0x12, 0x13, 0x14, 0x15,
3348b9754b2SBitterblue Smith 0x11, 0x11, 0x12, 0x13, 0x13, 0x13, 0x14, 0x15
3358b9754b2SBitterblue Smith };
3368b9754b2SBitterblue Smith
3378b9754b2SBitterblue Smith static const u8 retry_penalty_up_idx_cut_i[RATESIZE] = {
3388b9754b2SBitterblue Smith 0x0c, 0x0d, 0x0d, 0x0f,
3398b9754b2SBitterblue Smith 0x0d, 0x0e, 0x0f, 0x0f, 0x10, 0x12, 0x13, 0x14,
3408b9754b2SBitterblue Smith 0x0b, 0x0b, 0x11, 0x11, 0x12, 0x12, 0x12, 0x12,
3418b9754b2SBitterblue Smith 0x11, 0x11, 0x12, 0x13, 0x13, 0x13, 0x14, 0x15
3428b9754b2SBitterblue Smith };
3438b9754b2SBitterblue Smith
3448b9754b2SBitterblue Smith static const u8 rssi_threshold[RATESIZE] = {
3458b9754b2SBitterblue Smith 0, 0, 0, 0,
3468b9754b2SBitterblue Smith 0, 0, 0, 0, 0, 0x24, 0x26, 0x2a,
3478b9754b2SBitterblue Smith 0x18, 0x1a, 0x1d, 0x1f, 0x21, 0x27, 0x29, 0x2a,
3488b9754b2SBitterblue Smith 0, 0, 0, 0x1f, 0x23, 0x28, 0x2a, 0x2c
3498b9754b2SBitterblue Smith };
3508b9754b2SBitterblue Smith
3518b9754b2SBitterblue Smith static const u16 n_threshold_high[RATESIZE] = {
3528b9754b2SBitterblue Smith 4, 4, 8, 16,
3538b9754b2SBitterblue Smith 24, 36, 48, 72, 96, 144, 192, 216,
3548b9754b2SBitterblue Smith 60, 80, 100, 160, 240, 400, 600, 800,
3558b9754b2SBitterblue Smith 300, 320, 480, 720, 1000, 1200, 1600, 2000
3568b9754b2SBitterblue Smith };
3578b9754b2SBitterblue Smith
3588b9754b2SBitterblue Smith static const u16 n_threshold_low[RATESIZE] = {
3598b9754b2SBitterblue Smith 2, 2, 4, 8,
3608b9754b2SBitterblue Smith 12, 18, 24, 36, 48, 72, 96, 108,
3618b9754b2SBitterblue Smith 30, 40, 50, 80, 120, 200, 300, 400,
3628b9754b2SBitterblue Smith 150, 160, 240, 360, 500, 600, 800, 1000
3638b9754b2SBitterblue Smith };
3648b9754b2SBitterblue Smith
3658b9754b2SBitterblue Smith static const u8 dropping_necessary[RATESIZE] = {
3668b9754b2SBitterblue Smith 1, 1, 1, 1,
3678b9754b2SBitterblue Smith 1, 2, 3, 4, 5, 6, 7, 8,
3688b9754b2SBitterblue Smith 1, 2, 3, 4, 5, 6, 7, 8,
3698b9754b2SBitterblue Smith 5, 6, 7, 8, 9, 10, 11, 12
3708b9754b2SBitterblue Smith };
3718b9754b2SBitterblue Smith
3728b9754b2SBitterblue Smith static const u8 pending_for_rate_up_fail[5] = {2, 10, 24, 40, 60};
3738b9754b2SBitterblue Smith
3748b9754b2SBitterblue Smith static const u16 dynamic_tx_rpt_timing[6] = {
3758b9754b2SBitterblue Smith 0x186a, 0x30d4, 0x493e, 0x61a8, 0x7a12, 0x927c /* 200ms-1200ms */
3768b9754b2SBitterblue Smith };
3778b9754b2SBitterblue Smith
3788b9754b2SBitterblue Smith enum rtl8188e_tx_rpt_timing {
3798b9754b2SBitterblue Smith DEFAULT_TIMING = 0,
3808b9754b2SBitterblue Smith INCREASE_TIMING,
3818b9754b2SBitterblue Smith DECREASE_TIMING
3828b9754b2SBitterblue Smith };
3838b9754b2SBitterblue Smith
rtl8188eu_identify_chip(struct rtl8xxxu_priv * priv)3843dfb8e84SJes Sorensen static int rtl8188eu_identify_chip(struct rtl8xxxu_priv *priv)
3853dfb8e84SJes Sorensen {
3863dfb8e84SJes Sorensen struct device *dev = &priv->udev->dev;
3873dfb8e84SJes Sorensen u32 sys_cfg, vendor;
3883dfb8e84SJes Sorensen int ret = 0;
3893dfb8e84SJes Sorensen
3903dfb8e84SJes Sorensen strscpy(priv->chip_name, "8188EU", sizeof(priv->chip_name));
3913dfb8e84SJes Sorensen priv->rtl_chip = RTL8188E;
3923dfb8e84SJes Sorensen priv->rf_paths = 1;
3933dfb8e84SJes Sorensen priv->rx_paths = 1;
3943dfb8e84SJes Sorensen priv->tx_paths = 1;
3953dfb8e84SJes Sorensen priv->has_wifi = 1;
3963dfb8e84SJes Sorensen
3973dfb8e84SJes Sorensen sys_cfg = rtl8xxxu_read32(priv, REG_SYS_CFG);
3983dfb8e84SJes Sorensen priv->chip_cut = u32_get_bits(sys_cfg, SYS_CFG_CHIP_VERSION_MASK);
3993dfb8e84SJes Sorensen if (sys_cfg & SYS_CFG_TRP_VAUX_EN) {
4003dfb8e84SJes Sorensen dev_info(dev, "Unsupported test chip\n");
4013dfb8e84SJes Sorensen return -EOPNOTSUPP;
4023dfb8e84SJes Sorensen }
4033dfb8e84SJes Sorensen
4043dfb8e84SJes Sorensen /*
4053dfb8e84SJes Sorensen * TODO: At a glance, I cut requires a different firmware,
4063dfb8e84SJes Sorensen * different initialisation tables, and no software rate
4073dfb8e84SJes Sorensen * control. The vendor driver is not configured to handle
4083dfb8e84SJes Sorensen * I cut chips by default. Are there any in the wild?
4093dfb8e84SJes Sorensen */
4103dfb8e84SJes Sorensen if (priv->chip_cut == 8) {
4113dfb8e84SJes Sorensen dev_info(dev, "RTL8188EU cut I is not supported. Please complain about it at linux-wireless@vger.kernel.org.\n");
4123dfb8e84SJes Sorensen return -EOPNOTSUPP;
4133dfb8e84SJes Sorensen }
4143dfb8e84SJes Sorensen
4153dfb8e84SJes Sorensen vendor = sys_cfg & SYS_CFG_VENDOR_ID;
4163dfb8e84SJes Sorensen rtl8xxxu_identify_vendor_1bit(priv, vendor);
4173dfb8e84SJes Sorensen
4183dfb8e84SJes Sorensen ret = rtl8xxxu_config_endpoints_no_sie(priv);
4193dfb8e84SJes Sorensen
4203dfb8e84SJes Sorensen return ret;
4213dfb8e84SJes Sorensen }
4223dfb8e84SJes Sorensen
rtl8188eu_config_channel(struct ieee80211_hw * hw)4233dfb8e84SJes Sorensen static void rtl8188eu_config_channel(struct ieee80211_hw *hw)
4243dfb8e84SJes Sorensen {
4253dfb8e84SJes Sorensen struct rtl8xxxu_priv *priv = hw->priv;
4263dfb8e84SJes Sorensen u32 val32, rsr;
4273dfb8e84SJes Sorensen u8 opmode;
4283dfb8e84SJes Sorensen int sec_ch_above, channel;
4293dfb8e84SJes Sorensen int i;
4303dfb8e84SJes Sorensen
4313dfb8e84SJes Sorensen opmode = rtl8xxxu_read8(priv, REG_BW_OPMODE);
4323dfb8e84SJes Sorensen rsr = rtl8xxxu_read32(priv, REG_RESPONSE_RATE_SET);
4333dfb8e84SJes Sorensen channel = hw->conf.chandef.chan->hw_value;
4343dfb8e84SJes Sorensen
4353dfb8e84SJes Sorensen switch (hw->conf.chandef.width) {
4363dfb8e84SJes Sorensen case NL80211_CHAN_WIDTH_20_NOHT:
4373dfb8e84SJes Sorensen case NL80211_CHAN_WIDTH_20:
4383dfb8e84SJes Sorensen opmode |= BW_OPMODE_20MHZ;
4393dfb8e84SJes Sorensen rtl8xxxu_write8(priv, REG_BW_OPMODE, opmode);
4403dfb8e84SJes Sorensen
4413dfb8e84SJes Sorensen val32 = rtl8xxxu_read32(priv, REG_FPGA0_RF_MODE);
4423dfb8e84SJes Sorensen val32 &= ~FPGA_RF_MODE;
4433dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_FPGA0_RF_MODE, val32);
4443dfb8e84SJes Sorensen
4453dfb8e84SJes Sorensen val32 = rtl8xxxu_read32(priv, REG_FPGA1_RF_MODE);
4463dfb8e84SJes Sorensen val32 &= ~FPGA_RF_MODE;
4473dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_FPGA1_RF_MODE, val32);
4483dfb8e84SJes Sorensen break;
4493dfb8e84SJes Sorensen case NL80211_CHAN_WIDTH_40:
4503dfb8e84SJes Sorensen if (hw->conf.chandef.center_freq1 >
4513dfb8e84SJes Sorensen hw->conf.chandef.chan->center_freq) {
4523dfb8e84SJes Sorensen sec_ch_above = 1;
4533dfb8e84SJes Sorensen channel += 2;
4543dfb8e84SJes Sorensen } else {
4553dfb8e84SJes Sorensen sec_ch_above = 0;
4563dfb8e84SJes Sorensen channel -= 2;
4573dfb8e84SJes Sorensen }
4583dfb8e84SJes Sorensen
4593dfb8e84SJes Sorensen opmode &= ~BW_OPMODE_20MHZ;
4603dfb8e84SJes Sorensen rtl8xxxu_write8(priv, REG_BW_OPMODE, opmode);
4613dfb8e84SJes Sorensen rsr &= ~RSR_RSC_BANDWIDTH_40M;
4623dfb8e84SJes Sorensen if (sec_ch_above)
4633dfb8e84SJes Sorensen rsr |= RSR_RSC_LOWER_SUB_CHANNEL;
4643dfb8e84SJes Sorensen else
4653dfb8e84SJes Sorensen rsr |= RSR_RSC_UPPER_SUB_CHANNEL;
4663dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_RESPONSE_RATE_SET, rsr);
4673dfb8e84SJes Sorensen
4683dfb8e84SJes Sorensen val32 = rtl8xxxu_read32(priv, REG_FPGA0_RF_MODE);
4693dfb8e84SJes Sorensen val32 |= FPGA_RF_MODE;
4703dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_FPGA0_RF_MODE, val32);
4713dfb8e84SJes Sorensen
4723dfb8e84SJes Sorensen val32 = rtl8xxxu_read32(priv, REG_FPGA1_RF_MODE);
4733dfb8e84SJes Sorensen val32 |= FPGA_RF_MODE;
4743dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_FPGA1_RF_MODE, val32);
4753dfb8e84SJes Sorensen
4763dfb8e84SJes Sorensen /*
4773dfb8e84SJes Sorensen * Set Control channel to upper or lower. These settings
4783dfb8e84SJes Sorensen * are required only for 40MHz
4793dfb8e84SJes Sorensen */
4803dfb8e84SJes Sorensen val32 = rtl8xxxu_read32(priv, REG_CCK0_SYSTEM);
4813dfb8e84SJes Sorensen val32 &= ~CCK0_SIDEBAND;
4823dfb8e84SJes Sorensen if (!sec_ch_above)
4833dfb8e84SJes Sorensen val32 |= CCK0_SIDEBAND;
4843dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_CCK0_SYSTEM, val32);
4853dfb8e84SJes Sorensen
4863dfb8e84SJes Sorensen val32 = rtl8xxxu_read32(priv, REG_OFDM1_LSTF);
4873dfb8e84SJes Sorensen val32 &= ~OFDM_LSTF_PRIME_CH_MASK; /* 0xc00 */
4883dfb8e84SJes Sorensen if (sec_ch_above)
4893dfb8e84SJes Sorensen val32 |= OFDM_LSTF_PRIME_CH_LOW;
4903dfb8e84SJes Sorensen else
4913dfb8e84SJes Sorensen val32 |= OFDM_LSTF_PRIME_CH_HIGH;
4923dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_OFDM1_LSTF, val32);
4933dfb8e84SJes Sorensen
4943dfb8e84SJes Sorensen val32 = rtl8xxxu_read32(priv, REG_FPGA0_POWER_SAVE);
4953dfb8e84SJes Sorensen val32 &= ~(FPGA0_PS_LOWER_CHANNEL | FPGA0_PS_UPPER_CHANNEL);
4963dfb8e84SJes Sorensen if (sec_ch_above)
4973dfb8e84SJes Sorensen val32 |= FPGA0_PS_UPPER_CHANNEL;
4983dfb8e84SJes Sorensen else
4993dfb8e84SJes Sorensen val32 |= FPGA0_PS_LOWER_CHANNEL;
5003dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_FPGA0_POWER_SAVE, val32);
5013dfb8e84SJes Sorensen break;
5023dfb8e84SJes Sorensen
5033dfb8e84SJes Sorensen default:
5043dfb8e84SJes Sorensen break;
5053dfb8e84SJes Sorensen }
5063dfb8e84SJes Sorensen
5073dfb8e84SJes Sorensen for (i = RF_A; i < priv->rf_paths; i++) {
5083dfb8e84SJes Sorensen val32 = rtl8xxxu_read_rfreg(priv, i, RF6052_REG_MODE_AG);
5093dfb8e84SJes Sorensen u32p_replace_bits(&val32, channel, MODE_AG_CHANNEL_MASK);
5103dfb8e84SJes Sorensen rtl8xxxu_write_rfreg(priv, i, RF6052_REG_MODE_AG, val32);
5113dfb8e84SJes Sorensen }
5123dfb8e84SJes Sorensen
5133dfb8e84SJes Sorensen for (i = RF_A; i < priv->rf_paths; i++) {
5143dfb8e84SJes Sorensen val32 = rtl8xxxu_read_rfreg(priv, i, RF6052_REG_MODE_AG);
5153dfb8e84SJes Sorensen val32 &= ~MODE_AG_BW_MASK;
5163dfb8e84SJes Sorensen if (hw->conf.chandef.width == NL80211_CHAN_WIDTH_40)
5173dfb8e84SJes Sorensen val32 |= MODE_AG_BW_40MHZ_8723B;
5183dfb8e84SJes Sorensen else
5193dfb8e84SJes Sorensen val32 |= MODE_AG_BW_20MHZ_8723B;
5203dfb8e84SJes Sorensen rtl8xxxu_write_rfreg(priv, i, RF6052_REG_MODE_AG, val32);
5213dfb8e84SJes Sorensen }
5223dfb8e84SJes Sorensen }
5233dfb8e84SJes Sorensen
rtl8188eu_init_aggregation(struct rtl8xxxu_priv * priv)5243dfb8e84SJes Sorensen static void rtl8188eu_init_aggregation(struct rtl8xxxu_priv *priv)
5253dfb8e84SJes Sorensen {
5263dfb8e84SJes Sorensen u8 agg_ctrl, usb_spec;
5273dfb8e84SJes Sorensen
5283dfb8e84SJes Sorensen usb_spec = rtl8xxxu_read8(priv, REG_USB_SPECIAL_OPTION);
5293dfb8e84SJes Sorensen usb_spec &= ~USB_SPEC_USB_AGG_ENABLE;
5303dfb8e84SJes Sorensen rtl8xxxu_write8(priv, REG_USB_SPECIAL_OPTION, usb_spec);
5313dfb8e84SJes Sorensen
5323dfb8e84SJes Sorensen agg_ctrl = rtl8xxxu_read8(priv, REG_TRXDMA_CTRL);
5333dfb8e84SJes Sorensen agg_ctrl &= ~TRXDMA_CTRL_RXDMA_AGG_EN;
5343dfb8e84SJes Sorensen rtl8xxxu_write8(priv, REG_TRXDMA_CTRL, agg_ctrl);
5353dfb8e84SJes Sorensen }
5363dfb8e84SJes Sorensen
rtl8188eu_parse_efuse(struct rtl8xxxu_priv * priv)5373dfb8e84SJes Sorensen static int rtl8188eu_parse_efuse(struct rtl8xxxu_priv *priv)
5383dfb8e84SJes Sorensen {
5393dfb8e84SJes Sorensen struct rtl8188eu_efuse *efuse = &priv->efuse_wifi.efuse8188eu;
5403dfb8e84SJes Sorensen
5413dfb8e84SJes Sorensen if (efuse->rtl_id != cpu_to_le16(0x8129))
5423dfb8e84SJes Sorensen return -EINVAL;
5433dfb8e84SJes Sorensen
5443dfb8e84SJes Sorensen ether_addr_copy(priv->mac_addr, efuse->mac_addr);
5453dfb8e84SJes Sorensen
5463dfb8e84SJes Sorensen memcpy(priv->cck_tx_power_index_A, efuse->tx_power_index_A.cck_base,
5473dfb8e84SJes Sorensen sizeof(efuse->tx_power_index_A.cck_base));
5483dfb8e84SJes Sorensen
5493dfb8e84SJes Sorensen memcpy(priv->ht40_1s_tx_power_index_A,
5503dfb8e84SJes Sorensen efuse->tx_power_index_A.ht40_base,
5513dfb8e84SJes Sorensen sizeof(efuse->tx_power_index_A.ht40_base));
5523dfb8e84SJes Sorensen
5533dfb8e84SJes Sorensen priv->default_crystal_cap = efuse->xtal_k & 0x3f;
5543dfb8e84SJes Sorensen
5553dfb8e84SJes Sorensen return 0;
5563dfb8e84SJes Sorensen }
5573dfb8e84SJes Sorensen
rtl8188eu_reset_8051(struct rtl8xxxu_priv * priv)5583dfb8e84SJes Sorensen static void rtl8188eu_reset_8051(struct rtl8xxxu_priv *priv)
5593dfb8e84SJes Sorensen {
5603dfb8e84SJes Sorensen u16 sys_func;
5613dfb8e84SJes Sorensen
5623dfb8e84SJes Sorensen sys_func = rtl8xxxu_read16(priv, REG_SYS_FUNC);
5633dfb8e84SJes Sorensen sys_func &= ~SYS_FUNC_CPU_ENABLE;
5643dfb8e84SJes Sorensen rtl8xxxu_write16(priv, REG_SYS_FUNC, sys_func);
5653dfb8e84SJes Sorensen
5663dfb8e84SJes Sorensen sys_func |= SYS_FUNC_CPU_ENABLE;
5673dfb8e84SJes Sorensen rtl8xxxu_write16(priv, REG_SYS_FUNC, sys_func);
5683dfb8e84SJes Sorensen }
5693dfb8e84SJes Sorensen
rtl8188eu_load_firmware(struct rtl8xxxu_priv * priv)5703dfb8e84SJes Sorensen static int rtl8188eu_load_firmware(struct rtl8xxxu_priv *priv)
5713dfb8e84SJes Sorensen {
5723dfb8e84SJes Sorensen const char *fw_name;
5733dfb8e84SJes Sorensen int ret;
5743dfb8e84SJes Sorensen
5753dfb8e84SJes Sorensen fw_name = "rtlwifi/rtl8188eufw.bin";
5763dfb8e84SJes Sorensen
5773dfb8e84SJes Sorensen ret = rtl8xxxu_load_firmware(priv, fw_name);
5783dfb8e84SJes Sorensen
5793dfb8e84SJes Sorensen return ret;
5803dfb8e84SJes Sorensen }
5813dfb8e84SJes Sorensen
rtl8188eu_init_phy_bb(struct rtl8xxxu_priv * priv)5823dfb8e84SJes Sorensen static void rtl8188eu_init_phy_bb(struct rtl8xxxu_priv *priv)
5833dfb8e84SJes Sorensen {
5843dfb8e84SJes Sorensen u8 val8;
5853dfb8e84SJes Sorensen u16 val16;
5863dfb8e84SJes Sorensen
5873dfb8e84SJes Sorensen val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC);
5883dfb8e84SJes Sorensen val16 |= SYS_FUNC_BB_GLB_RSTN | SYS_FUNC_BBRSTB | SYS_FUNC_DIO_RF;
5893dfb8e84SJes Sorensen rtl8xxxu_write16(priv, REG_SYS_FUNC, val16);
5903dfb8e84SJes Sorensen
5913dfb8e84SJes Sorensen /*
5923dfb8e84SJes Sorensen * Per vendor driver, run power sequence before init of RF
5933dfb8e84SJes Sorensen */
5943dfb8e84SJes Sorensen val8 = RF_ENABLE | RF_RSTB | RF_SDMRSTB;
5953dfb8e84SJes Sorensen rtl8xxxu_write8(priv, REG_RF_CTRL, val8);
5963dfb8e84SJes Sorensen
5973dfb8e84SJes Sorensen val8 = SYS_FUNC_USBA | SYS_FUNC_USBD |
5983dfb8e84SJes Sorensen SYS_FUNC_BB_GLB_RSTN | SYS_FUNC_BBRSTB;
5993dfb8e84SJes Sorensen rtl8xxxu_write8(priv, REG_SYS_FUNC, val8);
6003dfb8e84SJes Sorensen
6013dfb8e84SJes Sorensen rtl8xxxu_init_phy_regs(priv, rtl8188eu_phy_init_table);
6023dfb8e84SJes Sorensen rtl8xxxu_init_phy_regs(priv, rtl8188e_agc_table);
6033dfb8e84SJes Sorensen }
6043dfb8e84SJes Sorensen
rtl8188eu_init_phy_rf(struct rtl8xxxu_priv * priv)6053dfb8e84SJes Sorensen static int rtl8188eu_init_phy_rf(struct rtl8xxxu_priv *priv)
6063dfb8e84SJes Sorensen {
6073dfb8e84SJes Sorensen return rtl8xxxu_init_phy_rf(priv, rtl8188eu_radioa_init_table, RF_A);
6083dfb8e84SJes Sorensen }
6093dfb8e84SJes Sorensen
rtl8188eu_iqk_path_a(struct rtl8xxxu_priv * priv)6103dfb8e84SJes Sorensen static int rtl8188eu_iqk_path_a(struct rtl8xxxu_priv *priv)
6113dfb8e84SJes Sorensen {
6123dfb8e84SJes Sorensen u32 reg_eac, reg_e94, reg_e9c;
6133dfb8e84SJes Sorensen int result = 0;
6143dfb8e84SJes Sorensen
6153dfb8e84SJes Sorensen /* Path A IQK setting */
6163dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x10008c1c);
6173dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x30008c1c);
6183dfb8e84SJes Sorensen
6193dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_TX_IQK_PI_A, 0x8214032a);
6203dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_RX_IQK_PI_A, 0x28160000);
6213dfb8e84SJes Sorensen
6223dfb8e84SJes Sorensen /* LO calibration setting */
6233dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x00462911);
6243dfb8e84SJes Sorensen
6253dfb8e84SJes Sorensen /* One shot, path A LOK & IQK */
6263dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf9000000);
6273dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf8000000);
6283dfb8e84SJes Sorensen
6293dfb8e84SJes Sorensen mdelay(10);
6303dfb8e84SJes Sorensen
6313dfb8e84SJes Sorensen /* Check failed */
6323dfb8e84SJes Sorensen reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2);
6333dfb8e84SJes Sorensen reg_e94 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_A);
6343dfb8e84SJes Sorensen reg_e9c = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_A);
6353dfb8e84SJes Sorensen
6363dfb8e84SJes Sorensen if (!(reg_eac & BIT(28)) &&
6373dfb8e84SJes Sorensen ((reg_e94 & 0x03ff0000) != 0x01420000) &&
6383dfb8e84SJes Sorensen ((reg_e9c & 0x03ff0000) != 0x00420000))
6393dfb8e84SJes Sorensen result |= 0x01;
6403dfb8e84SJes Sorensen
6413dfb8e84SJes Sorensen return result;
6423dfb8e84SJes Sorensen }
6433dfb8e84SJes Sorensen
rtl8188eu_rx_iqk_path_a(struct rtl8xxxu_priv * priv)6443dfb8e84SJes Sorensen static int rtl8188eu_rx_iqk_path_a(struct rtl8xxxu_priv *priv)
6453dfb8e84SJes Sorensen {
6463dfb8e84SJes Sorensen u32 reg_ea4, reg_eac, reg_e94, reg_e9c, val32;
6473dfb8e84SJes Sorensen int result = 0;
6483dfb8e84SJes Sorensen
6493dfb8e84SJes Sorensen /* Leave IQK mode */
6503dfb8e84SJes Sorensen val32 = rtl8xxxu_read32(priv, REG_FPGA0_IQK);
6513dfb8e84SJes Sorensen u32p_replace_bits(&val32, 0, 0xffffff00);
6523dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_FPGA0_IQK, val32);
6533dfb8e84SJes Sorensen
6543dfb8e84SJes Sorensen /* Enable path A PA in TX IQK mode */
6553dfb8e84SJes Sorensen rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_WE_LUT, 0x800a0);
6563dfb8e84SJes Sorensen rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_RCK_OS, 0x30000);
6573dfb8e84SJes Sorensen rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G1, 0x0000f);
6583dfb8e84SJes Sorensen rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G2, 0xf117b);
6593dfb8e84SJes Sorensen
6603dfb8e84SJes Sorensen /* Enter IQK mode */
6613dfb8e84SJes Sorensen val32 = rtl8xxxu_read32(priv, REG_FPGA0_IQK);
6623dfb8e84SJes Sorensen u32p_replace_bits(&val32, 0x808000, 0xffffff00);
6633dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_FPGA0_IQK, val32);
6643dfb8e84SJes Sorensen
6653dfb8e84SJes Sorensen /* TX IQK setting */
6663dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_TX_IQK, 0x01007c00);
6673dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_RX_IQK, 0x81004800);
6683dfb8e84SJes Sorensen
6693dfb8e84SJes Sorensen /* path-A IQK setting */
6703dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x10008c1c);
6713dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x30008c1c);
6723dfb8e84SJes Sorensen
6733dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_TX_IQK_PI_A, 0x82160804);
6743dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_RX_IQK_PI_A, 0x28160000);
6753dfb8e84SJes Sorensen
6763dfb8e84SJes Sorensen /* LO calibration setting */
6773dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x0046a911);
6783dfb8e84SJes Sorensen
6793dfb8e84SJes Sorensen /* One shot, path A LOK & IQK */
6803dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf9000000);
6813dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf8000000);
6823dfb8e84SJes Sorensen
6833dfb8e84SJes Sorensen mdelay(10);
6843dfb8e84SJes Sorensen
6853dfb8e84SJes Sorensen /* Check failed */
6863dfb8e84SJes Sorensen reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2);
6873dfb8e84SJes Sorensen reg_e94 = rtl8xxxu_read32(priv, REG_TX_POWER_BEFORE_IQK_A);
6883dfb8e84SJes Sorensen reg_e9c = rtl8xxxu_read32(priv, REG_TX_POWER_AFTER_IQK_A);
6893dfb8e84SJes Sorensen
6903dfb8e84SJes Sorensen if (!(reg_eac & BIT(28)) &&
6913dfb8e84SJes Sorensen ((reg_e94 & 0x03ff0000) != 0x01420000) &&
6923dfb8e84SJes Sorensen ((reg_e9c & 0x03ff0000) != 0x00420000))
6933dfb8e84SJes Sorensen result |= 0x01;
6943dfb8e84SJes Sorensen else
6953dfb8e84SJes Sorensen goto out;
6963dfb8e84SJes Sorensen
6973dfb8e84SJes Sorensen val32 = 0x80007c00 |
6983dfb8e84SJes Sorensen (reg_e94 & 0x03ff0000) | ((reg_e9c >> 16) & 0x03ff);
6993dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_TX_IQK, val32);
7003dfb8e84SJes Sorensen
7013dfb8e84SJes Sorensen /* Modify RX IQK mode table */
7023dfb8e84SJes Sorensen val32 = rtl8xxxu_read32(priv, REG_FPGA0_IQK);
7033dfb8e84SJes Sorensen u32p_replace_bits(&val32, 0, 0xffffff00);
7043dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_FPGA0_IQK, val32);
7053dfb8e84SJes Sorensen
7063dfb8e84SJes Sorensen rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_WE_LUT, 0x800a0);
7073dfb8e84SJes Sorensen rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_RCK_OS, 0x30000);
7083dfb8e84SJes Sorensen rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G1, 0x0000f);
7093dfb8e84SJes Sorensen rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_TXPA_G2, 0xf7ffa);
7103dfb8e84SJes Sorensen
7113dfb8e84SJes Sorensen /* Enter IQK mode */
7123dfb8e84SJes Sorensen val32 = rtl8xxxu_read32(priv, REG_FPGA0_IQK);
7133dfb8e84SJes Sorensen u32p_replace_bits(&val32, 0x808000, 0xffffff00);
7143dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_FPGA0_IQK, val32);
7153dfb8e84SJes Sorensen
7163dfb8e84SJes Sorensen /* IQK setting */
7173dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_RX_IQK, 0x01004800);
7183dfb8e84SJes Sorensen
7193dfb8e84SJes Sorensen /* Path A IQK setting */
7203dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x30008c1c);
7213dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x10008c1c);
7223dfb8e84SJes Sorensen
7233dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_TX_IQK_PI_A, 0x82160c05);
7243dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_RX_IQK_PI_A, 0x28160c05);
7253dfb8e84SJes Sorensen
7263dfb8e84SJes Sorensen /* LO calibration setting */
7273dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_IQK_AGC_RSP, 0x0046a911);
7283dfb8e84SJes Sorensen
7293dfb8e84SJes Sorensen /* One shot, path A LOK & IQK */
7303dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf9000000);
7313dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_IQK_AGC_PTS, 0xf8000000);
7323dfb8e84SJes Sorensen
7333dfb8e84SJes Sorensen mdelay(10);
7343dfb8e84SJes Sorensen
7353dfb8e84SJes Sorensen reg_eac = rtl8xxxu_read32(priv, REG_RX_POWER_AFTER_IQK_A_2);
7363dfb8e84SJes Sorensen reg_ea4 = rtl8xxxu_read32(priv, REG_RX_POWER_BEFORE_IQK_A_2);
7373dfb8e84SJes Sorensen
7383dfb8e84SJes Sorensen if (!(reg_eac & BIT(27)) &&
7393dfb8e84SJes Sorensen ((reg_ea4 & 0x03ff0000) != 0x01320000) &&
7403dfb8e84SJes Sorensen ((reg_eac & 0x03ff0000) != 0x00360000))
7413dfb8e84SJes Sorensen result |= 0x02;
7423dfb8e84SJes Sorensen else
7433dfb8e84SJes Sorensen dev_warn(&priv->udev->dev, "%s: Path A RX IQK failed!\n",
7443dfb8e84SJes Sorensen __func__);
7453dfb8e84SJes Sorensen
7463dfb8e84SJes Sorensen out:
7473dfb8e84SJes Sorensen return result;
7483dfb8e84SJes Sorensen }
7493dfb8e84SJes Sorensen
rtl8188eu_phy_iqcalibrate(struct rtl8xxxu_priv * priv,int result[][8],int t)7503dfb8e84SJes Sorensen static void rtl8188eu_phy_iqcalibrate(struct rtl8xxxu_priv *priv,
7513dfb8e84SJes Sorensen int result[][8], int t)
7523dfb8e84SJes Sorensen {
7533dfb8e84SJes Sorensen struct device *dev = &priv->udev->dev;
7543dfb8e84SJes Sorensen u32 i, val32;
7553dfb8e84SJes Sorensen int path_a_ok;
7563dfb8e84SJes Sorensen int retry = 2;
7573dfb8e84SJes Sorensen static const u32 adda_regs[RTL8XXXU_ADDA_REGS] = {
7583dfb8e84SJes Sorensen REG_FPGA0_XCD_SWITCH_CTRL, REG_BLUETOOTH,
7593dfb8e84SJes Sorensen REG_RX_WAIT_CCA, REG_TX_CCK_RFON,
7603dfb8e84SJes Sorensen REG_TX_CCK_BBON, REG_TX_OFDM_RFON,
7613dfb8e84SJes Sorensen REG_TX_OFDM_BBON, REG_TX_TO_RX,
7623dfb8e84SJes Sorensen REG_TX_TO_TX, REG_RX_CCK,
7633dfb8e84SJes Sorensen REG_RX_OFDM, REG_RX_WAIT_RIFS,
7643dfb8e84SJes Sorensen REG_RX_TO_RX, REG_STANDBY,
7653dfb8e84SJes Sorensen REG_SLEEP, REG_PMPD_ANAEN
7663dfb8e84SJes Sorensen };
7673dfb8e84SJes Sorensen static const u32 iqk_mac_regs[RTL8XXXU_MAC_REGS] = {
7683dfb8e84SJes Sorensen REG_TXPAUSE, REG_BEACON_CTRL,
7693dfb8e84SJes Sorensen REG_BEACON_CTRL_1, REG_GPIO_MUXCFG
7703dfb8e84SJes Sorensen };
7713dfb8e84SJes Sorensen static const u32 iqk_bb_regs[RTL8XXXU_BB_REGS] = {
7723dfb8e84SJes Sorensen REG_OFDM0_TRX_PATH_ENABLE, REG_OFDM0_TR_MUX_PAR,
7733dfb8e84SJes Sorensen REG_FPGA0_XCD_RF_SW_CTRL, REG_CONFIG_ANT_A, REG_CONFIG_ANT_B,
7743dfb8e84SJes Sorensen REG_FPGA0_XAB_RF_SW_CTRL, REG_FPGA0_XA_RF_INT_OE,
7753dfb8e84SJes Sorensen REG_FPGA0_XB_RF_INT_OE, REG_CCK0_AFE_SETTING
7763dfb8e84SJes Sorensen };
7773dfb8e84SJes Sorensen
7783dfb8e84SJes Sorensen /*
7793dfb8e84SJes Sorensen * Note: IQ calibration must be performed after loading
7803dfb8e84SJes Sorensen * PHY_REG.txt , and radio_a, radio_b.txt
7813dfb8e84SJes Sorensen */
7823dfb8e84SJes Sorensen
7833dfb8e84SJes Sorensen if (t == 0) {
7843dfb8e84SJes Sorensen /* Save ADDA parameters, turn Path A ADDA on */
7853dfb8e84SJes Sorensen rtl8xxxu_save_regs(priv, adda_regs, priv->adda_backup,
7863dfb8e84SJes Sorensen RTL8XXXU_ADDA_REGS);
7873dfb8e84SJes Sorensen rtl8xxxu_save_mac_regs(priv, iqk_mac_regs, priv->mac_backup);
7883dfb8e84SJes Sorensen rtl8xxxu_save_regs(priv, iqk_bb_regs,
7893dfb8e84SJes Sorensen priv->bb_backup, RTL8XXXU_BB_REGS);
7903dfb8e84SJes Sorensen }
7913dfb8e84SJes Sorensen
7923dfb8e84SJes Sorensen rtl8xxxu_path_adda_on(priv, adda_regs, true);
7933dfb8e84SJes Sorensen
7943dfb8e84SJes Sorensen if (t == 0) {
7953dfb8e84SJes Sorensen val32 = rtl8xxxu_read32(priv, REG_FPGA0_XA_HSSI_PARM1);
7963dfb8e84SJes Sorensen priv->pi_enabled = u32_get_bits(val32, FPGA0_HSSI_PARM1_PI);
7973dfb8e84SJes Sorensen }
7983dfb8e84SJes Sorensen
7993dfb8e84SJes Sorensen if (!priv->pi_enabled) {
8003dfb8e84SJes Sorensen /* Switch BB to PI mode to do IQ Calibration. */
8013dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_FPGA0_XA_HSSI_PARM1, 0x01000100);
8023dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_FPGA0_XB_HSSI_PARM1, 0x01000100);
8033dfb8e84SJes Sorensen }
8043dfb8e84SJes Sorensen
8053dfb8e84SJes Sorensen /* MAC settings */
8063dfb8e84SJes Sorensen rtl8xxxu_mac_calibration(priv, iqk_mac_regs, priv->mac_backup);
8073dfb8e84SJes Sorensen
8083dfb8e84SJes Sorensen val32 = rtl8xxxu_read32(priv, REG_CCK0_AFE_SETTING);
8093dfb8e84SJes Sorensen u32p_replace_bits(&val32, 0xf, 0x0f000000);
8103dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_CCK0_AFE_SETTING, val32);
8113dfb8e84SJes Sorensen
8123dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, 0x03a05600);
8133dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_OFDM0_TR_MUX_PAR, 0x000800e4);
8143dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_FPGA0_XCD_RF_SW_CTRL, 0x22204000);
8153dfb8e84SJes Sorensen
8163dfb8e84SJes Sorensen if (!priv->no_pape) {
8173dfb8e84SJes Sorensen val32 = rtl8xxxu_read32(priv, REG_FPGA0_XAB_RF_SW_CTRL);
8183dfb8e84SJes Sorensen val32 |= (FPGA0_RF_PAPE |
8193dfb8e84SJes Sorensen (FPGA0_RF_PAPE << FPGA0_RF_BD_CTRL_SHIFT));
8203dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_FPGA0_XAB_RF_SW_CTRL, val32);
8213dfb8e84SJes Sorensen }
8223dfb8e84SJes Sorensen
8233dfb8e84SJes Sorensen val32 = rtl8xxxu_read32(priv, REG_FPGA0_XA_RF_INT_OE);
8243dfb8e84SJes Sorensen val32 &= ~BIT(10);
8253dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_FPGA0_XA_RF_INT_OE, val32);
8263dfb8e84SJes Sorensen val32 = rtl8xxxu_read32(priv, REG_FPGA0_XB_RF_INT_OE);
8273dfb8e84SJes Sorensen val32 &= ~BIT(10);
8283dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_FPGA0_XB_RF_INT_OE, val32);
8293dfb8e84SJes Sorensen
8303dfb8e84SJes Sorensen /* Page B init */
8313dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_CONFIG_ANT_A, 0x0f600000);
8323dfb8e84SJes Sorensen
8333dfb8e84SJes Sorensen /* IQ calibration setting */
8343dfb8e84SJes Sorensen val32 = rtl8xxxu_read32(priv, REG_FPGA0_IQK);
8353dfb8e84SJes Sorensen u32p_replace_bits(&val32, 0x808000, 0xffffff00);
8363dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_FPGA0_IQK, val32);
8373dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_TX_IQK, 0x01007c00);
8383dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_RX_IQK, 0x81004800);
8393dfb8e84SJes Sorensen
8403dfb8e84SJes Sorensen for (i = 0; i < retry; i++) {
8413dfb8e84SJes Sorensen path_a_ok = rtl8188eu_iqk_path_a(priv);
8423dfb8e84SJes Sorensen if (path_a_ok == 0x01) {
8433dfb8e84SJes Sorensen val32 = rtl8xxxu_read32(priv,
8443dfb8e84SJes Sorensen REG_TX_POWER_BEFORE_IQK_A);
8453dfb8e84SJes Sorensen result[t][0] = (val32 >> 16) & 0x3ff;
8463dfb8e84SJes Sorensen val32 = rtl8xxxu_read32(priv,
8473dfb8e84SJes Sorensen REG_TX_POWER_AFTER_IQK_A);
8483dfb8e84SJes Sorensen result[t][1] = (val32 >> 16) & 0x3ff;
8493dfb8e84SJes Sorensen break;
8503dfb8e84SJes Sorensen }
8513dfb8e84SJes Sorensen }
8523dfb8e84SJes Sorensen
8533dfb8e84SJes Sorensen if (!path_a_ok)
8543dfb8e84SJes Sorensen dev_dbg(dev, "%s: Path A TX IQK failed!\n", __func__);
8553dfb8e84SJes Sorensen
8563dfb8e84SJes Sorensen for (i = 0; i < retry; i++) {
8573dfb8e84SJes Sorensen path_a_ok = rtl8188eu_rx_iqk_path_a(priv);
8583dfb8e84SJes Sorensen if (path_a_ok == 0x03) {
8593dfb8e84SJes Sorensen val32 = rtl8xxxu_read32(priv,
8603dfb8e84SJes Sorensen REG_RX_POWER_BEFORE_IQK_A_2);
8613dfb8e84SJes Sorensen result[t][2] = (val32 >> 16) & 0x3ff;
8623dfb8e84SJes Sorensen val32 = rtl8xxxu_read32(priv,
8633dfb8e84SJes Sorensen REG_RX_POWER_AFTER_IQK_A_2);
8643dfb8e84SJes Sorensen result[t][3] = (val32 >> 16) & 0x3ff;
8653dfb8e84SJes Sorensen
8663dfb8e84SJes Sorensen break;
8673dfb8e84SJes Sorensen }
8683dfb8e84SJes Sorensen }
8693dfb8e84SJes Sorensen
8703dfb8e84SJes Sorensen if (!path_a_ok)
8713dfb8e84SJes Sorensen dev_dbg(dev, "%s: Path A RX IQK failed!\n", __func__);
8723dfb8e84SJes Sorensen
8733dfb8e84SJes Sorensen /* Back to BB mode, load original value */
8743dfb8e84SJes Sorensen val32 = rtl8xxxu_read32(priv, REG_FPGA0_IQK);
8753dfb8e84SJes Sorensen u32p_replace_bits(&val32, 0, 0xffffff00);
8763dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_FPGA0_IQK, val32);
8773dfb8e84SJes Sorensen
8783dfb8e84SJes Sorensen if (t == 0)
8793dfb8e84SJes Sorensen return;
8803dfb8e84SJes Sorensen
8813dfb8e84SJes Sorensen if (!priv->pi_enabled) {
8823dfb8e84SJes Sorensen /* Switch back BB to SI mode after finishing IQ Calibration */
8833dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_FPGA0_XA_HSSI_PARM1, 0x01000000);
8843dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_FPGA0_XB_HSSI_PARM1, 0x01000000);
8853dfb8e84SJes Sorensen }
8863dfb8e84SJes Sorensen
8873dfb8e84SJes Sorensen /* Reload ADDA power saving parameters */
8883dfb8e84SJes Sorensen rtl8xxxu_restore_regs(priv, adda_regs, priv->adda_backup,
8893dfb8e84SJes Sorensen RTL8XXXU_ADDA_REGS);
8903dfb8e84SJes Sorensen
8913dfb8e84SJes Sorensen /* Reload MAC parameters */
8923dfb8e84SJes Sorensen rtl8xxxu_restore_mac_regs(priv, iqk_mac_regs, priv->mac_backup);
8933dfb8e84SJes Sorensen
8943dfb8e84SJes Sorensen /* Reload BB parameters */
8953dfb8e84SJes Sorensen rtl8xxxu_restore_regs(priv, iqk_bb_regs,
8963dfb8e84SJes Sorensen priv->bb_backup, RTL8XXXU_BB_REGS);
8973dfb8e84SJes Sorensen
8983dfb8e84SJes Sorensen /* Restore RX initial gain */
8993dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_FPGA0_XA_LSSI_PARM, 0x00032ed3);
9003dfb8e84SJes Sorensen
9013dfb8e84SJes Sorensen /* Load 0xe30 IQC default value */
9023dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_TX_IQK_TONE_A, 0x01008c00);
9033dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_RX_IQK_TONE_A, 0x01008c00);
9043dfb8e84SJes Sorensen }
9053dfb8e84SJes Sorensen
rtl8188eu_phy_iq_calibrate(struct rtl8xxxu_priv * priv)9063dfb8e84SJes Sorensen static void rtl8188eu_phy_iq_calibrate(struct rtl8xxxu_priv *priv)
9073dfb8e84SJes Sorensen {
9083dfb8e84SJes Sorensen struct device *dev = &priv->udev->dev;
9093dfb8e84SJes Sorensen int result[4][8]; /* last is final result */
9103dfb8e84SJes Sorensen int i, candidate;
9113dfb8e84SJes Sorensen bool path_a_ok;
9123dfb8e84SJes Sorensen u32 reg_e94, reg_e9c, reg_ea4, reg_eac;
9133dfb8e84SJes Sorensen u32 reg_eb4, reg_ebc, reg_ec4, reg_ecc;
9143dfb8e84SJes Sorensen bool simu;
9153dfb8e84SJes Sorensen
9163dfb8e84SJes Sorensen memset(result, 0, sizeof(result));
9173dfb8e84SJes Sorensen result[3][0] = 0x100;
9183dfb8e84SJes Sorensen result[3][2] = 0x100;
9193dfb8e84SJes Sorensen result[3][4] = 0x100;
9203dfb8e84SJes Sorensen result[3][6] = 0x100;
9213dfb8e84SJes Sorensen
9223dfb8e84SJes Sorensen candidate = -1;
9233dfb8e84SJes Sorensen
9243dfb8e84SJes Sorensen path_a_ok = false;
9253dfb8e84SJes Sorensen
9263dfb8e84SJes Sorensen for (i = 0; i < 3; i++) {
9273dfb8e84SJes Sorensen rtl8188eu_phy_iqcalibrate(priv, result, i);
9283dfb8e84SJes Sorensen
9293dfb8e84SJes Sorensen if (i == 1) {
9303dfb8e84SJes Sorensen simu = rtl8xxxu_simularity_compare(priv,
9313dfb8e84SJes Sorensen result, 0, 1);
9323dfb8e84SJes Sorensen if (simu) {
9333dfb8e84SJes Sorensen candidate = 0;
9343dfb8e84SJes Sorensen break;
9353dfb8e84SJes Sorensen }
9363dfb8e84SJes Sorensen }
9373dfb8e84SJes Sorensen
9383dfb8e84SJes Sorensen if (i == 2) {
9393dfb8e84SJes Sorensen simu = rtl8xxxu_simularity_compare(priv,
9403dfb8e84SJes Sorensen result, 0, 2);
9413dfb8e84SJes Sorensen if (simu) {
9423dfb8e84SJes Sorensen candidate = 0;
9433dfb8e84SJes Sorensen break;
9443dfb8e84SJes Sorensen }
9453dfb8e84SJes Sorensen
9463dfb8e84SJes Sorensen simu = rtl8xxxu_simularity_compare(priv,
9473dfb8e84SJes Sorensen result, 1, 2);
9483dfb8e84SJes Sorensen if (simu)
9493dfb8e84SJes Sorensen candidate = 1;
9503dfb8e84SJes Sorensen else
9513dfb8e84SJes Sorensen candidate = 3;
9523dfb8e84SJes Sorensen }
9533dfb8e84SJes Sorensen }
9543dfb8e84SJes Sorensen
9553dfb8e84SJes Sorensen if (candidate >= 0) {
9563dfb8e84SJes Sorensen reg_e94 = result[candidate][0];
9573dfb8e84SJes Sorensen priv->rege94 = reg_e94;
9583dfb8e84SJes Sorensen reg_e9c = result[candidate][1];
9593dfb8e84SJes Sorensen priv->rege9c = reg_e9c;
9603dfb8e84SJes Sorensen reg_ea4 = result[candidate][2];
9613dfb8e84SJes Sorensen reg_eac = result[candidate][3];
9623dfb8e84SJes Sorensen reg_eb4 = result[candidate][4];
9633dfb8e84SJes Sorensen priv->regeb4 = reg_eb4;
9643dfb8e84SJes Sorensen reg_ebc = result[candidate][5];
9653dfb8e84SJes Sorensen priv->regebc = reg_ebc;
9663dfb8e84SJes Sorensen reg_ec4 = result[candidate][6];
9673dfb8e84SJes Sorensen reg_ecc = result[candidate][7];
9683dfb8e84SJes Sorensen dev_dbg(dev, "%s: candidate is %x\n", __func__, candidate);
9693dfb8e84SJes Sorensen dev_dbg(dev,
9703dfb8e84SJes Sorensen "%s: e94=%x e9c=%x ea4=%x eac=%x eb4=%x ebc=%x ec4=%x ecc=%x\n",
9713dfb8e84SJes Sorensen __func__, reg_e94, reg_e9c, reg_ea4, reg_eac,
9723dfb8e84SJes Sorensen reg_eb4, reg_ebc, reg_ec4, reg_ecc);
9733dfb8e84SJes Sorensen path_a_ok = true;
9743dfb8e84SJes Sorensen } else {
9753dfb8e84SJes Sorensen reg_e94 = 0x100;
9763dfb8e84SJes Sorensen reg_eb4 = 0x100;
9773dfb8e84SJes Sorensen priv->rege94 = 0x100;
9783dfb8e84SJes Sorensen priv->regeb4 = 0x100;
9793dfb8e84SJes Sorensen reg_e9c = 0x0;
9803dfb8e84SJes Sorensen reg_ebc = 0x0;
9813dfb8e84SJes Sorensen priv->rege9c = 0x0;
9823dfb8e84SJes Sorensen priv->regebc = 0x0;
9833dfb8e84SJes Sorensen }
9843dfb8e84SJes Sorensen
9853dfb8e84SJes Sorensen if (reg_e94 && candidate >= 0)
9863dfb8e84SJes Sorensen rtl8xxxu_fill_iqk_matrix_a(priv, path_a_ok, result,
9873dfb8e84SJes Sorensen candidate, (reg_ea4 == 0));
9883dfb8e84SJes Sorensen
9893dfb8e84SJes Sorensen rtl8xxxu_save_regs(priv, rtl8xxxu_iqk_phy_iq_bb_reg,
9903dfb8e84SJes Sorensen priv->bb_recovery_backup, RTL8XXXU_BB_REGS);
9913dfb8e84SJes Sorensen }
9923dfb8e84SJes Sorensen
rtl8188e_disabled_to_emu(struct rtl8xxxu_priv * priv)9933dfb8e84SJes Sorensen static void rtl8188e_disabled_to_emu(struct rtl8xxxu_priv *priv)
9943dfb8e84SJes Sorensen {
9953dfb8e84SJes Sorensen u16 val16;
9963dfb8e84SJes Sorensen
9973dfb8e84SJes Sorensen val16 = rtl8xxxu_read16(priv, REG_APS_FSMCO);
9983dfb8e84SJes Sorensen val16 &= ~(APS_FSMCO_HW_SUSPEND | APS_FSMCO_PCIE);
9993dfb8e84SJes Sorensen rtl8xxxu_write16(priv, REG_APS_FSMCO, val16);
10003dfb8e84SJes Sorensen }
10013dfb8e84SJes Sorensen
rtl8188e_emu_to_active(struct rtl8xxxu_priv * priv)10023dfb8e84SJes Sorensen static int rtl8188e_emu_to_active(struct rtl8xxxu_priv *priv)
10033dfb8e84SJes Sorensen {
10043dfb8e84SJes Sorensen u8 val8;
10053dfb8e84SJes Sorensen u32 val32;
10063dfb8e84SJes Sorensen u16 val16;
10073dfb8e84SJes Sorensen int count, ret = 0;
10083dfb8e84SJes Sorensen
10093dfb8e84SJes Sorensen /* wait till 0x04[17] = 1 power ready*/
10103dfb8e84SJes Sorensen for (count = RTL8XXXU_MAX_REG_POLL; count; count--) {
10113dfb8e84SJes Sorensen val32 = rtl8xxxu_read32(priv, REG_APS_FSMCO);
10123dfb8e84SJes Sorensen if (val32 & BIT(17))
10133dfb8e84SJes Sorensen break;
10143dfb8e84SJes Sorensen
10153dfb8e84SJes Sorensen udelay(10);
10163dfb8e84SJes Sorensen }
10173dfb8e84SJes Sorensen
10183dfb8e84SJes Sorensen if (!count) {
10193dfb8e84SJes Sorensen ret = -EBUSY;
10203dfb8e84SJes Sorensen goto exit;
10213dfb8e84SJes Sorensen }
10223dfb8e84SJes Sorensen
10233dfb8e84SJes Sorensen /* reset baseband */
10243dfb8e84SJes Sorensen val8 = rtl8xxxu_read8(priv, REG_SYS_FUNC);
10253dfb8e84SJes Sorensen val8 &= ~(SYS_FUNC_BBRSTB | SYS_FUNC_BB_GLB_RSTN);
10263dfb8e84SJes Sorensen rtl8xxxu_write8(priv, REG_SYS_FUNC, val8);
10273dfb8e84SJes Sorensen
10283dfb8e84SJes Sorensen /*0x24[23] = 2b'01 schmit trigger */
10293dfb8e84SJes Sorensen val32 = rtl8xxxu_read32(priv, REG_AFE_XTAL_CTRL);
10303dfb8e84SJes Sorensen val32 |= BIT(23);
10313dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_AFE_XTAL_CTRL, val32);
10323dfb8e84SJes Sorensen
10333dfb8e84SJes Sorensen /* 0x04[15] = 0 disable HWPDN (control by DRV)*/
10343dfb8e84SJes Sorensen val16 = rtl8xxxu_read16(priv, REG_APS_FSMCO);
10353dfb8e84SJes Sorensen val16 &= ~APS_FSMCO_HW_POWERDOWN;
10363dfb8e84SJes Sorensen rtl8xxxu_write16(priv, REG_APS_FSMCO, val16);
10373dfb8e84SJes Sorensen
10383dfb8e84SJes Sorensen /*0x04[12:11] = 2b'00 disable WL suspend*/
10393dfb8e84SJes Sorensen val16 = rtl8xxxu_read16(priv, REG_APS_FSMCO);
10403dfb8e84SJes Sorensen val16 &= ~(APS_FSMCO_HW_SUSPEND | APS_FSMCO_PCIE);
10413dfb8e84SJes Sorensen rtl8xxxu_write16(priv, REG_APS_FSMCO, val16);
10423dfb8e84SJes Sorensen
10433dfb8e84SJes Sorensen /* set, then poll until 0 */
10443dfb8e84SJes Sorensen val32 = rtl8xxxu_read32(priv, REG_APS_FSMCO);
10453dfb8e84SJes Sorensen val32 |= APS_FSMCO_MAC_ENABLE;
10463dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_APS_FSMCO, val32);
10473dfb8e84SJes Sorensen
10483dfb8e84SJes Sorensen for (count = RTL8XXXU_MAX_REG_POLL; count; count--) {
10493dfb8e84SJes Sorensen val32 = rtl8xxxu_read32(priv, REG_APS_FSMCO);
10503dfb8e84SJes Sorensen if ((val32 & APS_FSMCO_MAC_ENABLE) == 0) {
10513dfb8e84SJes Sorensen ret = 0;
10523dfb8e84SJes Sorensen break;
10533dfb8e84SJes Sorensen }
10543dfb8e84SJes Sorensen udelay(10);
10553dfb8e84SJes Sorensen }
10563dfb8e84SJes Sorensen
10573dfb8e84SJes Sorensen if (!count) {
10583dfb8e84SJes Sorensen ret = -EBUSY;
10593dfb8e84SJes Sorensen goto exit;
10603dfb8e84SJes Sorensen }
10613dfb8e84SJes Sorensen
10623dfb8e84SJes Sorensen /* LDO normal mode*/
10633dfb8e84SJes Sorensen val8 = rtl8xxxu_read8(priv, REG_LPLDO_CTRL);
10643dfb8e84SJes Sorensen val8 &= ~BIT(4);
10653dfb8e84SJes Sorensen rtl8xxxu_write8(priv, REG_LPLDO_CTRL, val8);
10663dfb8e84SJes Sorensen
10673dfb8e84SJes Sorensen exit:
10683dfb8e84SJes Sorensen return ret;
10693dfb8e84SJes Sorensen }
10703dfb8e84SJes Sorensen
rtl8188eu_active_to_emu(struct rtl8xxxu_priv * priv)10713dfb8e84SJes Sorensen static int rtl8188eu_active_to_emu(struct rtl8xxxu_priv *priv)
10723dfb8e84SJes Sorensen {
10733dfb8e84SJes Sorensen u8 val8;
10743dfb8e84SJes Sorensen
10753dfb8e84SJes Sorensen /* Turn off RF */
10763dfb8e84SJes Sorensen val8 = rtl8xxxu_read8(priv, REG_RF_CTRL);
10773dfb8e84SJes Sorensen val8 &= ~RF_ENABLE;
10783dfb8e84SJes Sorensen rtl8xxxu_write8(priv, REG_RF_CTRL, val8);
10793dfb8e84SJes Sorensen
10803dfb8e84SJes Sorensen /* LDO Sleep mode */
10813dfb8e84SJes Sorensen val8 = rtl8xxxu_read8(priv, REG_LPLDO_CTRL);
10823dfb8e84SJes Sorensen val8 |= BIT(4);
10833dfb8e84SJes Sorensen rtl8xxxu_write8(priv, REG_LPLDO_CTRL, val8);
10843dfb8e84SJes Sorensen
10853dfb8e84SJes Sorensen return 0;
10863dfb8e84SJes Sorensen }
10873dfb8e84SJes Sorensen
rtl8188eu_emu_to_disabled(struct rtl8xxxu_priv * priv)10883dfb8e84SJes Sorensen static int rtl8188eu_emu_to_disabled(struct rtl8xxxu_priv *priv)
10893dfb8e84SJes Sorensen {
10903dfb8e84SJes Sorensen u32 val32;
10913dfb8e84SJes Sorensen u16 val16;
10923dfb8e84SJes Sorensen u8 val8;
10933dfb8e84SJes Sorensen
10943dfb8e84SJes Sorensen val32 = rtl8xxxu_read32(priv, REG_AFE_XTAL_CTRL);
10953dfb8e84SJes Sorensen val32 |= BIT(23);
10963dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_AFE_XTAL_CTRL, val32);
10973dfb8e84SJes Sorensen
10983dfb8e84SJes Sorensen val16 = rtl8xxxu_read16(priv, REG_APS_FSMCO);
10993dfb8e84SJes Sorensen val16 &= ~APS_FSMCO_PCIE;
11003dfb8e84SJes Sorensen val16 |= APS_FSMCO_HW_SUSPEND;
11013dfb8e84SJes Sorensen rtl8xxxu_write16(priv, REG_APS_FSMCO, val16);
11023dfb8e84SJes Sorensen
11033dfb8e84SJes Sorensen rtl8xxxu_write8(priv, REG_APS_FSMCO + 3, 0x00);
11043dfb8e84SJes Sorensen
11053dfb8e84SJes Sorensen val8 = rtl8xxxu_read8(priv, REG_GPIO_MUXCFG + 1);
11063dfb8e84SJes Sorensen val8 &= ~BIT(4);
11073dfb8e84SJes Sorensen rtl8xxxu_write8(priv, REG_GPIO_MUXCFG + 1, val8);
11083dfb8e84SJes Sorensen
11093dfb8e84SJes Sorensen /* Set USB suspend enable local register 0xfe10[4]=1 */
11103dfb8e84SJes Sorensen val8 = rtl8xxxu_read8(priv, 0xfe10);
11113dfb8e84SJes Sorensen val8 |= BIT(4);
11123dfb8e84SJes Sorensen rtl8xxxu_write8(priv, 0xfe10, val8);
11133dfb8e84SJes Sorensen
11143dfb8e84SJes Sorensen return 0;
11153dfb8e84SJes Sorensen }
11163dfb8e84SJes Sorensen
rtl8188eu_active_to_lps(struct rtl8xxxu_priv * priv)11173dfb8e84SJes Sorensen static int rtl8188eu_active_to_lps(struct rtl8xxxu_priv *priv)
11183dfb8e84SJes Sorensen {
11193dfb8e84SJes Sorensen struct device *dev = &priv->udev->dev;
11203dfb8e84SJes Sorensen u8 val8;
11213dfb8e84SJes Sorensen u16 val16;
11223dfb8e84SJes Sorensen u32 val32;
11233dfb8e84SJes Sorensen int retry, retval;
11243dfb8e84SJes Sorensen
11253dfb8e84SJes Sorensen rtl8xxxu_write8(priv, REG_TXPAUSE, 0x7f);
11263dfb8e84SJes Sorensen
11273dfb8e84SJes Sorensen retry = 100;
11283dfb8e84SJes Sorensen retval = -EBUSY;
11293dfb8e84SJes Sorensen /* Poll 32 bit wide REG_SCH_TX_CMD for 0 to ensure no TX is pending. */
11303dfb8e84SJes Sorensen do {
11313dfb8e84SJes Sorensen val32 = rtl8xxxu_read32(priv, REG_SCH_TX_CMD);
11323dfb8e84SJes Sorensen if (!val32) {
11333dfb8e84SJes Sorensen retval = 0;
11343dfb8e84SJes Sorensen break;
11353dfb8e84SJes Sorensen }
11363dfb8e84SJes Sorensen } while (retry--);
11373dfb8e84SJes Sorensen
11383dfb8e84SJes Sorensen if (!retry) {
11393dfb8e84SJes Sorensen dev_warn(dev, "Failed to flush TX queue\n");
11403dfb8e84SJes Sorensen retval = -EBUSY;
11413dfb8e84SJes Sorensen goto out;
11423dfb8e84SJes Sorensen }
11433dfb8e84SJes Sorensen
11443dfb8e84SJes Sorensen /* Disable CCK and OFDM, clock gated */
11453dfb8e84SJes Sorensen val8 = rtl8xxxu_read8(priv, REG_SYS_FUNC);
11463dfb8e84SJes Sorensen val8 &= ~SYS_FUNC_BBRSTB;
11473dfb8e84SJes Sorensen rtl8xxxu_write8(priv, REG_SYS_FUNC, val8);
11483dfb8e84SJes Sorensen
11493dfb8e84SJes Sorensen udelay(2);
11503dfb8e84SJes Sorensen
11513dfb8e84SJes Sorensen /* Reset MAC TRX */
11523dfb8e84SJes Sorensen val16 = rtl8xxxu_read16(priv, REG_CR);
11533dfb8e84SJes Sorensen val16 |= 0xff;
11543dfb8e84SJes Sorensen val16 &= ~(CR_MAC_TX_ENABLE | CR_MAC_RX_ENABLE | CR_SECURITY_ENABLE);
11553dfb8e84SJes Sorensen rtl8xxxu_write16(priv, REG_CR, val16);
11563dfb8e84SJes Sorensen
11573dfb8e84SJes Sorensen val8 = rtl8xxxu_read8(priv, REG_DUAL_TSF_RST);
11583dfb8e84SJes Sorensen val8 |= DUAL_TSF_TX_OK;
11593dfb8e84SJes Sorensen rtl8xxxu_write8(priv, REG_DUAL_TSF_RST, val8);
11603dfb8e84SJes Sorensen
11613dfb8e84SJes Sorensen out:
11623dfb8e84SJes Sorensen return retval;
11633dfb8e84SJes Sorensen }
11643dfb8e84SJes Sorensen
rtl8188eu_power_on(struct rtl8xxxu_priv * priv)11653dfb8e84SJes Sorensen static int rtl8188eu_power_on(struct rtl8xxxu_priv *priv)
11663dfb8e84SJes Sorensen {
11673dfb8e84SJes Sorensen u16 val16;
11683dfb8e84SJes Sorensen int ret;
11693dfb8e84SJes Sorensen
11703dfb8e84SJes Sorensen rtl8188e_disabled_to_emu(priv);
11713dfb8e84SJes Sorensen
11723dfb8e84SJes Sorensen ret = rtl8188e_emu_to_active(priv);
11733dfb8e84SJes Sorensen if (ret)
11743dfb8e84SJes Sorensen goto exit;
11753dfb8e84SJes Sorensen
11763dfb8e84SJes Sorensen /*
11773dfb8e84SJes Sorensen * Enable MAC DMA/WMAC/SCHEDULE/SEC block
11783dfb8e84SJes Sorensen * Set CR bit10 to enable 32k calibration.
11793dfb8e84SJes Sorensen * We do not set CR_MAC_TX_ENABLE | CR_MAC_RX_ENABLE here
11803dfb8e84SJes Sorensen * due to a hardware bug in the 88E, requiring those to be
11813dfb8e84SJes Sorensen * set after REG_TRXFF_BNDY is set. If not the RXFF bundary
11823dfb8e84SJes Sorensen * will get set to a larger buffer size than the real buffer
11833dfb8e84SJes Sorensen * size.
11843dfb8e84SJes Sorensen */
11853dfb8e84SJes Sorensen val16 = (CR_HCI_TXDMA_ENABLE | CR_HCI_RXDMA_ENABLE |
11863dfb8e84SJes Sorensen CR_TXDMA_ENABLE | CR_RXDMA_ENABLE |
11873dfb8e84SJes Sorensen CR_PROTOCOL_ENABLE | CR_SCHEDULE_ENABLE |
11883dfb8e84SJes Sorensen CR_SECURITY_ENABLE | CR_CALTIMER_ENABLE);
11893dfb8e84SJes Sorensen rtl8xxxu_write16(priv, REG_CR, val16);
11903dfb8e84SJes Sorensen
11913dfb8e84SJes Sorensen exit:
11923dfb8e84SJes Sorensen return ret;
11933dfb8e84SJes Sorensen }
11943dfb8e84SJes Sorensen
rtl8188eu_power_off(struct rtl8xxxu_priv * priv)11953dfb8e84SJes Sorensen static void rtl8188eu_power_off(struct rtl8xxxu_priv *priv)
11963dfb8e84SJes Sorensen {
11973dfb8e84SJes Sorensen u8 val8;
11983dfb8e84SJes Sorensen u16 val16;
11993dfb8e84SJes Sorensen
12003dfb8e84SJes Sorensen rtl8xxxu_flush_fifo(priv);
12013dfb8e84SJes Sorensen
12023dfb8e84SJes Sorensen val8 = rtl8xxxu_read8(priv, REG_TX_REPORT_CTRL);
12033dfb8e84SJes Sorensen val8 &= ~TX_REPORT_CTRL_TIMER_ENABLE;
12043dfb8e84SJes Sorensen rtl8xxxu_write8(priv, REG_TX_REPORT_CTRL, val8);
12053dfb8e84SJes Sorensen
12063dfb8e84SJes Sorensen /* Turn off RF */
12073dfb8e84SJes Sorensen rtl8xxxu_write8(priv, REG_RF_CTRL, 0x00);
12083dfb8e84SJes Sorensen
12093dfb8e84SJes Sorensen rtl8188eu_active_to_lps(priv);
12103dfb8e84SJes Sorensen
12113dfb8e84SJes Sorensen /* Reset Firmware if running in RAM */
12123dfb8e84SJes Sorensen if (rtl8xxxu_read8(priv, REG_MCU_FW_DL) & MCU_FW_RAM_SEL)
12133dfb8e84SJes Sorensen rtl8xxxu_firmware_self_reset(priv);
12143dfb8e84SJes Sorensen
12153dfb8e84SJes Sorensen /* Reset MCU */
12163dfb8e84SJes Sorensen val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC);
12173dfb8e84SJes Sorensen val16 &= ~SYS_FUNC_CPU_ENABLE;
12183dfb8e84SJes Sorensen rtl8xxxu_write16(priv, REG_SYS_FUNC, val16);
12193dfb8e84SJes Sorensen
12203dfb8e84SJes Sorensen /* Reset MCU ready status */
12213dfb8e84SJes Sorensen rtl8xxxu_write8(priv, REG_MCU_FW_DL, 0x00);
12223dfb8e84SJes Sorensen
12233dfb8e84SJes Sorensen /* 32K_CTRL looks to be very 8188e specific */
12243dfb8e84SJes Sorensen val8 = rtl8xxxu_read8(priv, REG_32K_CTRL);
12253dfb8e84SJes Sorensen val8 &= ~BIT(0);
12263dfb8e84SJes Sorensen rtl8xxxu_write8(priv, REG_32K_CTRL, val8);
12273dfb8e84SJes Sorensen
12283dfb8e84SJes Sorensen rtl8188eu_active_to_emu(priv);
12293dfb8e84SJes Sorensen rtl8188eu_emu_to_disabled(priv);
12303dfb8e84SJes Sorensen
12313dfb8e84SJes Sorensen /* Reset MCU IO Wrapper */
12323dfb8e84SJes Sorensen val8 = rtl8xxxu_read8(priv, REG_RSV_CTRL + 1);
12333dfb8e84SJes Sorensen val8 &= ~BIT(3);
12343dfb8e84SJes Sorensen rtl8xxxu_write8(priv, REG_RSV_CTRL + 1, val8);
12353dfb8e84SJes Sorensen
12363dfb8e84SJes Sorensen val8 = rtl8xxxu_read8(priv, REG_RSV_CTRL + 1);
12373dfb8e84SJes Sorensen val8 |= BIT(3);
12383dfb8e84SJes Sorensen rtl8xxxu_write8(priv, REG_RSV_CTRL + 1, val8);
12393dfb8e84SJes Sorensen
12403dfb8e84SJes Sorensen /* Vendor driver refers to GPIO_IN */
12413dfb8e84SJes Sorensen val8 = rtl8xxxu_read8(priv, REG_GPIO_PIN_CTRL);
12423dfb8e84SJes Sorensen /* Vendor driver refers to GPIO_OUT */
12433dfb8e84SJes Sorensen rtl8xxxu_write8(priv, REG_GPIO_PIN_CTRL + 1, val8);
12443dfb8e84SJes Sorensen rtl8xxxu_write8(priv, REG_GPIO_PIN_CTRL + 2, 0xff);
12453dfb8e84SJes Sorensen
12463dfb8e84SJes Sorensen val8 = rtl8xxxu_read8(priv, REG_GPIO_IO_SEL);
12473dfb8e84SJes Sorensen rtl8xxxu_write8(priv, REG_GPIO_IO_SEL, val8 << 4);
12483dfb8e84SJes Sorensen val8 = rtl8xxxu_read8(priv, REG_GPIO_IO_SEL + 1);
12493dfb8e84SJes Sorensen rtl8xxxu_write8(priv, REG_GPIO_IO_SEL + 1, val8 | 0x0f);
12503dfb8e84SJes Sorensen
12513dfb8e84SJes Sorensen /*
12523dfb8e84SJes Sorensen * Set LNA, TRSW, EX_PA Pin to output mode
12533dfb8e84SJes Sorensen * Referred to as REG_BB_PAD_CTRL in 8188eu vendor driver
12543dfb8e84SJes Sorensen */
12553dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_PAD_CTRL1, 0x00080808);
12563dfb8e84SJes Sorensen
12573dfb8e84SJes Sorensen rtl8xxxu_write8(priv, REG_RSV_CTRL, 0x00);
12583dfb8e84SJes Sorensen
12593dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_GPIO_MUXCFG, 0x00000000);
12603dfb8e84SJes Sorensen }
12613dfb8e84SJes Sorensen
rtl8188e_enable_rf(struct rtl8xxxu_priv * priv)12623dfb8e84SJes Sorensen static void rtl8188e_enable_rf(struct rtl8xxxu_priv *priv)
12633dfb8e84SJes Sorensen {
12643dfb8e84SJes Sorensen u32 val32;
12653dfb8e84SJes Sorensen
12663dfb8e84SJes Sorensen rtl8xxxu_write8(priv, REG_RF_CTRL, RF_ENABLE | RF_RSTB | RF_SDMRSTB);
12673dfb8e84SJes Sorensen
12683dfb8e84SJes Sorensen val32 = rtl8xxxu_read32(priv, REG_OFDM0_TRX_PATH_ENABLE);
12693dfb8e84SJes Sorensen val32 &= ~(OFDM_RF_PATH_RX_MASK | OFDM_RF_PATH_TX_MASK);
12703dfb8e84SJes Sorensen val32 |= OFDM_RF_PATH_RX_A | OFDM_RF_PATH_TX_A;
12713dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, val32);
12723dfb8e84SJes Sorensen
12733dfb8e84SJes Sorensen rtl8xxxu_write8(priv, REG_TXPAUSE, 0x00);
12743dfb8e84SJes Sorensen }
12753dfb8e84SJes Sorensen
rtl8188e_disable_rf(struct rtl8xxxu_priv * priv)12763dfb8e84SJes Sorensen static void rtl8188e_disable_rf(struct rtl8xxxu_priv *priv)
12773dfb8e84SJes Sorensen {
12783dfb8e84SJes Sorensen u32 val32;
12793dfb8e84SJes Sorensen
12803dfb8e84SJes Sorensen val32 = rtl8xxxu_read32(priv, REG_OFDM0_TRX_PATH_ENABLE);
12813dfb8e84SJes Sorensen val32 &= ~OFDM_RF_PATH_TX_MASK;
12823dfb8e84SJes Sorensen rtl8xxxu_write32(priv, REG_OFDM0_TRX_PATH_ENABLE, val32);
12833dfb8e84SJes Sorensen
12843dfb8e84SJes Sorensen /* Power down RF module */
12853dfb8e84SJes Sorensen rtl8xxxu_write_rfreg(priv, RF_A, RF6052_REG_AC, 0);
12863dfb8e84SJes Sorensen
12873dfb8e84SJes Sorensen rtl8188eu_active_to_emu(priv);
12883dfb8e84SJes Sorensen }
12893dfb8e84SJes Sorensen
rtl8188e_usb_quirks(struct rtl8xxxu_priv * priv)12903dfb8e84SJes Sorensen static void rtl8188e_usb_quirks(struct rtl8xxxu_priv *priv)
12913dfb8e84SJes Sorensen {
12923dfb8e84SJes Sorensen u16 val16;
12933dfb8e84SJes Sorensen
12943dfb8e84SJes Sorensen /*
12953dfb8e84SJes Sorensen * Technically this is not a USB quirk, but a chip quirk.
12963dfb8e84SJes Sorensen * This has to be done after REG_TRXFF_BNDY is set, see
12973dfb8e84SJes Sorensen * rtl8188eu_power_on() for details.
12983dfb8e84SJes Sorensen */
12993dfb8e84SJes Sorensen val16 = rtl8xxxu_read16(priv, REG_CR);
13003dfb8e84SJes Sorensen val16 |= (CR_MAC_TX_ENABLE | CR_MAC_RX_ENABLE);
13013dfb8e84SJes Sorensen rtl8xxxu_write16(priv, REG_CR, val16);
13023dfb8e84SJes Sorensen
13033dfb8e84SJes Sorensen rtl8xxxu_gen2_usb_quirks(priv);
13043dfb8e84SJes Sorensen
13053dfb8e84SJes Sorensen /* Pre-TX enable WEP/TKIP security */
13063dfb8e84SJes Sorensen rtl8xxxu_write8(priv, REG_EARLY_MODE_CONTROL_8188E + 3, 0x01);
13073dfb8e84SJes Sorensen }
13083dfb8e84SJes Sorensen
rtl8188e_cck_rssi(struct rtl8xxxu_priv * priv,struct rtl8723au_phy_stats * phy_stats)130970664495SBitterblue Smith static s8 rtl8188e_cck_rssi(struct rtl8xxxu_priv *priv, struct rtl8723au_phy_stats *phy_stats)
13103dfb8e84SJes Sorensen {
13113dfb8e84SJes Sorensen /* only use lna 0/1/2/3/7 */
13123dfb8e84SJes Sorensen static const s8 lna_gain_table_0[8] = {17, -1, -13, -29, -32, -35, -38, -41};
13133dfb8e84SJes Sorensen /* only use lna 3/7 */
13143dfb8e84SJes Sorensen static const s8 lna_gain_table_1[8] = {29, 20, 12, 3, -6, -15, -24, -33};
13153dfb8e84SJes Sorensen
131670664495SBitterblue Smith u8 cck_agc_rpt = phy_stats->cck_agc_rpt_ofdm_cfosho_a;
13173dfb8e84SJes Sorensen s8 rx_pwr_all = 0x00;
13183dfb8e84SJes Sorensen u8 vga_idx, lna_idx;
13193dfb8e84SJes Sorensen s8 lna_gain = 0;
13203dfb8e84SJes Sorensen
13213dfb8e84SJes Sorensen lna_idx = u8_get_bits(cck_agc_rpt, CCK_AGC_RPT_LNA_IDX_MASK);
13223dfb8e84SJes Sorensen vga_idx = u8_get_bits(cck_agc_rpt, CCK_AGC_RPT_VGA_IDX_MASK);
13233dfb8e84SJes Sorensen
13243dfb8e84SJes Sorensen if (priv->chip_cut >= 8) /* cut I */ /* SMIC */
13253dfb8e84SJes Sorensen lna_gain = lna_gain_table_0[lna_idx];
13263dfb8e84SJes Sorensen else /* TSMC */
13273dfb8e84SJes Sorensen lna_gain = lna_gain_table_1[lna_idx];
13283dfb8e84SJes Sorensen
13293dfb8e84SJes Sorensen rx_pwr_all = lna_gain - (2 * vga_idx);
13303dfb8e84SJes Sorensen
13313dfb8e84SJes Sorensen return rx_pwr_all;
13323dfb8e84SJes Sorensen }
13333dfb8e84SJes Sorensen
rtl8188eu_led_brightness_set(struct led_classdev * led_cdev,enum led_brightness brightness)1334873b3811SBitterblue Smith static int rtl8188eu_led_brightness_set(struct led_classdev *led_cdev,
1335873b3811SBitterblue Smith enum led_brightness brightness)
1336873b3811SBitterblue Smith {
1337873b3811SBitterblue Smith struct rtl8xxxu_priv *priv = container_of(led_cdev,
1338873b3811SBitterblue Smith struct rtl8xxxu_priv,
1339873b3811SBitterblue Smith led_cdev);
1340873b3811SBitterblue Smith u8 ledcfg = rtl8xxxu_read8(priv, REG_LEDCFG2);
1341873b3811SBitterblue Smith
1342873b3811SBitterblue Smith if (brightness == LED_OFF) {
1343873b3811SBitterblue Smith ledcfg &= ~LEDCFG2_HW_LED_CONTROL;
1344873b3811SBitterblue Smith ledcfg |= LEDCFG2_SW_LED_CONTROL | LEDCFG2_SW_LED_DISABLE;
1345873b3811SBitterblue Smith } else if (brightness == LED_ON) {
1346873b3811SBitterblue Smith ledcfg &= ~(LEDCFG2_HW_LED_CONTROL | LEDCFG2_SW_LED_DISABLE);
1347873b3811SBitterblue Smith ledcfg |= LEDCFG2_SW_LED_CONTROL;
1348873b3811SBitterblue Smith } else if (brightness == RTL8XXXU_HW_LED_CONTROL) {
1349873b3811SBitterblue Smith ledcfg &= ~LEDCFG2_SW_LED_DISABLE;
1350873b3811SBitterblue Smith ledcfg |= LEDCFG2_HW_LED_CONTROL | LEDCFG2_HW_LED_ENABLE;
1351873b3811SBitterblue Smith }
1352873b3811SBitterblue Smith
1353873b3811SBitterblue Smith rtl8xxxu_write8(priv, REG_LEDCFG2, ledcfg);
1354873b3811SBitterblue Smith
1355873b3811SBitterblue Smith return 0;
1356873b3811SBitterblue Smith }
1357873b3811SBitterblue Smith
rtl8188e_set_tx_rpt_timing(struct rtl8xxxu_ra_info * ra,u8 timing)13588b9754b2SBitterblue Smith static void rtl8188e_set_tx_rpt_timing(struct rtl8xxxu_ra_info *ra, u8 timing)
13598b9754b2SBitterblue Smith {
13608b9754b2SBitterblue Smith u8 idx;
13618b9754b2SBitterblue Smith
13628b9754b2SBitterblue Smith for (idx = 0; idx < 5; idx++)
13638b9754b2SBitterblue Smith if (dynamic_tx_rpt_timing[idx] == ra->rpt_time)
13648b9754b2SBitterblue Smith break;
13658b9754b2SBitterblue Smith
13668b9754b2SBitterblue Smith if (timing == DEFAULT_TIMING) {
13678b9754b2SBitterblue Smith idx = 0; /* 200ms */
13688b9754b2SBitterblue Smith } else if (timing == INCREASE_TIMING) {
13698b9754b2SBitterblue Smith if (idx < 5)
13708b9754b2SBitterblue Smith idx++;
13718b9754b2SBitterblue Smith } else if (timing == DECREASE_TIMING) {
13728b9754b2SBitterblue Smith if (idx > 0)
13738b9754b2SBitterblue Smith idx--;
13748b9754b2SBitterblue Smith }
13758b9754b2SBitterblue Smith
13768b9754b2SBitterblue Smith ra->rpt_time = dynamic_tx_rpt_timing[idx];
13778b9754b2SBitterblue Smith }
13788b9754b2SBitterblue Smith
rtl8188e_rate_down(struct rtl8xxxu_ra_info * ra)13798b9754b2SBitterblue Smith static void rtl8188e_rate_down(struct rtl8xxxu_ra_info *ra)
13808b9754b2SBitterblue Smith {
13818b9754b2SBitterblue Smith u8 rate_id = ra->pre_rate;
13828b9754b2SBitterblue Smith u8 lowest_rate = ra->lowest_rate;
13838b9754b2SBitterblue Smith u8 highest_rate = ra->highest_rate;
13848b9754b2SBitterblue Smith s8 i;
13858b9754b2SBitterblue Smith
13868b9754b2SBitterblue Smith if (rate_id > highest_rate) {
13878b9754b2SBitterblue Smith rate_id = highest_rate;
13888b9754b2SBitterblue Smith } else if (ra->rate_sgi) {
13898b9754b2SBitterblue Smith ra->rate_sgi = 0;
13908b9754b2SBitterblue Smith } else if (rate_id > lowest_rate) {
13918b9754b2SBitterblue Smith if (rate_id > 0) {
13928b9754b2SBitterblue Smith for (i = rate_id - 1; i >= lowest_rate; i--) {
13938b9754b2SBitterblue Smith if (ra->ra_use_rate & BIT(i)) {
13948b9754b2SBitterblue Smith rate_id = i;
13958b9754b2SBitterblue Smith goto rate_down_finish;
13968b9754b2SBitterblue Smith }
13978b9754b2SBitterblue Smith }
13988b9754b2SBitterblue Smith }
13998b9754b2SBitterblue Smith } else if (rate_id <= lowest_rate) {
14008b9754b2SBitterblue Smith rate_id = lowest_rate;
14018b9754b2SBitterblue Smith }
14028b9754b2SBitterblue Smith
14038b9754b2SBitterblue Smith rate_down_finish:
14048b9754b2SBitterblue Smith if (ra->ra_waiting_counter == 1) {
14058b9754b2SBitterblue Smith ra->ra_waiting_counter++;
14068b9754b2SBitterblue Smith ra->ra_pending_counter++;
14078b9754b2SBitterblue Smith } else if (ra->ra_waiting_counter > 1) {
14088b9754b2SBitterblue Smith ra->ra_waiting_counter = 0;
14098b9754b2SBitterblue Smith ra->ra_pending_counter = 0;
14108b9754b2SBitterblue Smith }
14118b9754b2SBitterblue Smith
14128b9754b2SBitterblue Smith if (ra->ra_pending_counter >= 4)
14138b9754b2SBitterblue Smith ra->ra_pending_counter = 4;
14148b9754b2SBitterblue Smith
14158b9754b2SBitterblue Smith ra->ra_drop_after_down = 1;
14168b9754b2SBitterblue Smith
14178b9754b2SBitterblue Smith ra->decision_rate = rate_id;
14188b9754b2SBitterblue Smith
14198b9754b2SBitterblue Smith rtl8188e_set_tx_rpt_timing(ra, DECREASE_TIMING);
14208b9754b2SBitterblue Smith }
14218b9754b2SBitterblue Smith
rtl8188e_rate_up(struct rtl8xxxu_ra_info * ra)14228b9754b2SBitterblue Smith static void rtl8188e_rate_up(struct rtl8xxxu_ra_info *ra)
14238b9754b2SBitterblue Smith {
14248b9754b2SBitterblue Smith u8 rate_id = ra->pre_rate;
14258b9754b2SBitterblue Smith u8 highest_rate = ra->highest_rate;
14268b9754b2SBitterblue Smith u8 i;
14278b9754b2SBitterblue Smith
14288b9754b2SBitterblue Smith if (ra->ra_waiting_counter == 1) {
14298b9754b2SBitterblue Smith ra->ra_waiting_counter = 0;
14308b9754b2SBitterblue Smith ra->ra_pending_counter = 0;
14318b9754b2SBitterblue Smith } else if (ra->ra_waiting_counter > 1) {
14328b9754b2SBitterblue Smith ra->pre_rssi_sta_ra = ra->rssi_sta_ra;
14338b9754b2SBitterblue Smith goto rate_up_finish;
14348b9754b2SBitterblue Smith }
14358b9754b2SBitterblue Smith
14368b9754b2SBitterblue Smith rtl8188e_set_tx_rpt_timing(ra, DEFAULT_TIMING);
14378b9754b2SBitterblue Smith
14388b9754b2SBitterblue Smith if (rate_id < highest_rate) {
14398b9754b2SBitterblue Smith for (i = rate_id + 1; i <= highest_rate; i++) {
14408b9754b2SBitterblue Smith if (ra->ra_use_rate & BIT(i)) {
14418b9754b2SBitterblue Smith rate_id = i;
14428b9754b2SBitterblue Smith goto rate_up_finish;
14438b9754b2SBitterblue Smith }
14448b9754b2SBitterblue Smith }
14458b9754b2SBitterblue Smith } else if (rate_id == highest_rate) {
14468b9754b2SBitterblue Smith if (ra->sgi_enable && !ra->rate_sgi)
14478b9754b2SBitterblue Smith ra->rate_sgi = 1;
14488b9754b2SBitterblue Smith else if (!ra->sgi_enable)
14498b9754b2SBitterblue Smith ra->rate_sgi = 0;
14508b9754b2SBitterblue Smith } else { /* rate_id > ra->highest_rate */
14518b9754b2SBitterblue Smith rate_id = highest_rate;
14528b9754b2SBitterblue Smith }
14538b9754b2SBitterblue Smith
14548b9754b2SBitterblue Smith rate_up_finish:
14558b9754b2SBitterblue Smith if (ra->ra_waiting_counter == (4 + pending_for_rate_up_fail[ra->ra_pending_counter]))
14568b9754b2SBitterblue Smith ra->ra_waiting_counter = 0;
14578b9754b2SBitterblue Smith else
14588b9754b2SBitterblue Smith ra->ra_waiting_counter++;
14598b9754b2SBitterblue Smith
14608b9754b2SBitterblue Smith ra->decision_rate = rate_id;
14618b9754b2SBitterblue Smith }
14628b9754b2SBitterblue Smith
rtl8188e_reset_ra_counter(struct rtl8xxxu_ra_info * ra)14638b9754b2SBitterblue Smith static void rtl8188e_reset_ra_counter(struct rtl8xxxu_ra_info *ra)
14648b9754b2SBitterblue Smith {
14658b9754b2SBitterblue Smith u8 rate_id = ra->decision_rate;
14668b9754b2SBitterblue Smith
14678b9754b2SBitterblue Smith ra->nsc_up = (n_threshold_high[rate_id] + n_threshold_low[rate_id]) >> 1;
14688b9754b2SBitterblue Smith ra->nsc_down = (n_threshold_high[rate_id] + n_threshold_low[rate_id]) >> 1;
14698b9754b2SBitterblue Smith }
14708b9754b2SBitterblue Smith
rtl8188e_rate_decision(struct rtl8xxxu_ra_info * ra)14718b9754b2SBitterblue Smith static void rtl8188e_rate_decision(struct rtl8xxxu_ra_info *ra)
14728b9754b2SBitterblue Smith {
14738b9754b2SBitterblue Smith struct rtl8xxxu_priv *priv = container_of(ra, struct rtl8xxxu_priv, ra_info);
14748b9754b2SBitterblue Smith const u8 *retry_penalty_idx_0;
14758b9754b2SBitterblue Smith const u8 *retry_penalty_idx_1;
14768b9754b2SBitterblue Smith const u8 *retry_penalty_up_idx;
14778b9754b2SBitterblue Smith u8 rate_id, penalty_id1, penalty_id2;
14788b9754b2SBitterblue Smith int i;
14798b9754b2SBitterblue Smith
14808b9754b2SBitterblue Smith if (ra->total == 0)
14818b9754b2SBitterblue Smith return;
14828b9754b2SBitterblue Smith
14838b9754b2SBitterblue Smith if (ra->ra_drop_after_down) {
14848b9754b2SBitterblue Smith ra->ra_drop_after_down--;
14858b9754b2SBitterblue Smith
14868b9754b2SBitterblue Smith rtl8188e_reset_ra_counter(ra);
14878b9754b2SBitterblue Smith
14888b9754b2SBitterblue Smith return;
14898b9754b2SBitterblue Smith }
14908b9754b2SBitterblue Smith
14918b9754b2SBitterblue Smith if (priv->chip_cut == 8) { /* cut I */
14928b9754b2SBitterblue Smith retry_penalty_idx_0 = retry_penalty_idx_cut_i[0];
14938b9754b2SBitterblue Smith retry_penalty_idx_1 = retry_penalty_idx_cut_i[1];
14948b9754b2SBitterblue Smith retry_penalty_up_idx = retry_penalty_up_idx_cut_i;
14958b9754b2SBitterblue Smith } else {
14968b9754b2SBitterblue Smith retry_penalty_idx_0 = retry_penalty_idx_normal[0];
14978b9754b2SBitterblue Smith retry_penalty_idx_1 = retry_penalty_idx_normal[1];
14988b9754b2SBitterblue Smith retry_penalty_up_idx = retry_penalty_up_idx_normal;
14998b9754b2SBitterblue Smith }
15008b9754b2SBitterblue Smith
15018b9754b2SBitterblue Smith if (ra->rssi_sta_ra < (ra->pre_rssi_sta_ra - 3) ||
15028b9754b2SBitterblue Smith ra->rssi_sta_ra > (ra->pre_rssi_sta_ra + 3)) {
15038b9754b2SBitterblue Smith ra->pre_rssi_sta_ra = ra->rssi_sta_ra;
15048b9754b2SBitterblue Smith ra->ra_waiting_counter = 0;
15058b9754b2SBitterblue Smith ra->ra_pending_counter = 0;
15068b9754b2SBitterblue Smith }
15078b9754b2SBitterblue Smith
15088b9754b2SBitterblue Smith /* Start RA decision */
15098b9754b2SBitterblue Smith if (ra->pre_rate > ra->highest_rate)
15108b9754b2SBitterblue Smith rate_id = ra->highest_rate;
15118b9754b2SBitterblue Smith else
15128b9754b2SBitterblue Smith rate_id = ra->pre_rate;
15138b9754b2SBitterblue Smith
15148b9754b2SBitterblue Smith /* rate down */
15158b9754b2SBitterblue Smith if (ra->rssi_sta_ra > rssi_threshold[rate_id])
15168b9754b2SBitterblue Smith penalty_id1 = retry_penalty_idx_0[rate_id];
15178b9754b2SBitterblue Smith else
15188b9754b2SBitterblue Smith penalty_id1 = retry_penalty_idx_1[rate_id];
15198b9754b2SBitterblue Smith
15208b9754b2SBitterblue Smith for (i = 0; i < 5; i++)
15218b9754b2SBitterblue Smith ra->nsc_down += ra->retry[i] * retry_penalty[penalty_id1][i];
15228b9754b2SBitterblue Smith
15238b9754b2SBitterblue Smith if (ra->nsc_down > (ra->total * retry_penalty[penalty_id1][5]))
15248b9754b2SBitterblue Smith ra->nsc_down -= ra->total * retry_penalty[penalty_id1][5];
15258b9754b2SBitterblue Smith else
15268b9754b2SBitterblue Smith ra->nsc_down = 0;
15278b9754b2SBitterblue Smith
15288b9754b2SBitterblue Smith /* rate up */
15298b9754b2SBitterblue Smith penalty_id2 = retry_penalty_up_idx[rate_id];
15308b9754b2SBitterblue Smith
15318b9754b2SBitterblue Smith for (i = 0; i < 5; i++)
15328b9754b2SBitterblue Smith ra->nsc_up += ra->retry[i] * retry_penalty[penalty_id2][i];
15338b9754b2SBitterblue Smith
15348b9754b2SBitterblue Smith if (ra->nsc_up > (ra->total * retry_penalty[penalty_id2][5]))
15358b9754b2SBitterblue Smith ra->nsc_up -= ra->total * retry_penalty[penalty_id2][5];
15368b9754b2SBitterblue Smith else
15378b9754b2SBitterblue Smith ra->nsc_up = 0;
15388b9754b2SBitterblue Smith
15398b9754b2SBitterblue Smith if (ra->nsc_down < n_threshold_low[rate_id] ||
15408b9754b2SBitterblue Smith ra->drop > dropping_necessary[rate_id]) {
15418b9754b2SBitterblue Smith rtl8188e_rate_down(ra);
15428b9754b2SBitterblue Smith
15438b9754b2SBitterblue Smith rtl8xxxu_update_ra_report(&priv->ra_report, ra->decision_rate,
15448b9754b2SBitterblue Smith ra->rate_sgi, priv->ra_report.txrate.bw);
15458b9754b2SBitterblue Smith } else if (ra->nsc_up > n_threshold_high[rate_id]) {
15468b9754b2SBitterblue Smith rtl8188e_rate_up(ra);
15478b9754b2SBitterblue Smith
15488b9754b2SBitterblue Smith rtl8xxxu_update_ra_report(&priv->ra_report, ra->decision_rate,
15498b9754b2SBitterblue Smith ra->rate_sgi, priv->ra_report.txrate.bw);
15508b9754b2SBitterblue Smith }
15518b9754b2SBitterblue Smith
15528b9754b2SBitterblue Smith if (ra->decision_rate == ra->pre_rate)
15538b9754b2SBitterblue Smith ra->dynamic_tx_rpt_timing_counter++;
15548b9754b2SBitterblue Smith else
15558b9754b2SBitterblue Smith ra->dynamic_tx_rpt_timing_counter = 0;
15568b9754b2SBitterblue Smith
15578b9754b2SBitterblue Smith if (ra->dynamic_tx_rpt_timing_counter >= 4) {
15588b9754b2SBitterblue Smith /* Rate didn't change 4 times, extend RPT timing */
15598b9754b2SBitterblue Smith rtl8188e_set_tx_rpt_timing(ra, INCREASE_TIMING);
15608b9754b2SBitterblue Smith ra->dynamic_tx_rpt_timing_counter = 0;
15618b9754b2SBitterblue Smith }
15628b9754b2SBitterblue Smith
15638b9754b2SBitterblue Smith ra->pre_rate = ra->decision_rate;
15648b9754b2SBitterblue Smith
15658b9754b2SBitterblue Smith rtl8188e_reset_ra_counter(ra);
15668b9754b2SBitterblue Smith }
15678b9754b2SBitterblue Smith
rtl8188e_power_training_try_state(struct rtl8xxxu_ra_info * ra)15688b9754b2SBitterblue Smith static void rtl8188e_power_training_try_state(struct rtl8xxxu_ra_info *ra)
15698b9754b2SBitterblue Smith {
15708b9754b2SBitterblue Smith ra->pt_try_state = 0;
15718b9754b2SBitterblue Smith switch (ra->pt_mode_ss) {
15728b9754b2SBitterblue Smith case 3:
15738b9754b2SBitterblue Smith if (ra->decision_rate >= DESC_RATE_MCS13)
15748b9754b2SBitterblue Smith ra->pt_try_state = 1;
15758b9754b2SBitterblue Smith break;
15768b9754b2SBitterblue Smith case 2:
15778b9754b2SBitterblue Smith if (ra->decision_rate >= DESC_RATE_MCS5)
15788b9754b2SBitterblue Smith ra->pt_try_state = 1;
15798b9754b2SBitterblue Smith break;
15808b9754b2SBitterblue Smith case 1:
15818b9754b2SBitterblue Smith if (ra->decision_rate >= DESC_RATE_48M)
15828b9754b2SBitterblue Smith ra->pt_try_state = 1;
15838b9754b2SBitterblue Smith break;
15848b9754b2SBitterblue Smith case 0:
15858b9754b2SBitterblue Smith if (ra->decision_rate >= DESC_RATE_11M)
15868b9754b2SBitterblue Smith ra->pt_try_state = 1;
15878b9754b2SBitterblue Smith break;
15888b9754b2SBitterblue Smith default:
15898b9754b2SBitterblue Smith break;
15908b9754b2SBitterblue Smith }
15918b9754b2SBitterblue Smith
15928b9754b2SBitterblue Smith if (ra->rssi_sta_ra < 48) {
15938b9754b2SBitterblue Smith ra->pt_stage = 0;
15948b9754b2SBitterblue Smith } else if (ra->pt_try_state == 1) {
15958b9754b2SBitterblue Smith if ((ra->pt_stop_count >= 10) ||
15968b9754b2SBitterblue Smith (ra->pt_pre_rssi > ra->rssi_sta_ra + 5) ||
15978b9754b2SBitterblue Smith (ra->pt_pre_rssi < ra->rssi_sta_ra - 5) ||
15988b9754b2SBitterblue Smith (ra->decision_rate != ra->pt_pre_rate)) {
15998b9754b2SBitterblue Smith if (ra->pt_stage == 0)
16008b9754b2SBitterblue Smith ra->pt_stage = 1;
16018b9754b2SBitterblue Smith else if (ra->pt_stage == 1)
16028b9754b2SBitterblue Smith ra->pt_stage = 3;
16038b9754b2SBitterblue Smith else
16048b9754b2SBitterblue Smith ra->pt_stage = 5;
16058b9754b2SBitterblue Smith
16068b9754b2SBitterblue Smith ra->pt_pre_rssi = ra->rssi_sta_ra;
16078b9754b2SBitterblue Smith ra->pt_stop_count = 0;
16088b9754b2SBitterblue Smith } else {
16098b9754b2SBitterblue Smith ra->ra_stage = 0;
16108b9754b2SBitterblue Smith ra->pt_stop_count++;
16118b9754b2SBitterblue Smith }
16128b9754b2SBitterblue Smith } else {
16138b9754b2SBitterblue Smith ra->pt_stage = 0;
16148b9754b2SBitterblue Smith ra->ra_stage = 0;
16158b9754b2SBitterblue Smith }
16168b9754b2SBitterblue Smith
16178b9754b2SBitterblue Smith ra->pt_pre_rate = ra->decision_rate;
16188b9754b2SBitterblue Smith
16198b9754b2SBitterblue Smith /* TODO: implement the "false alarm" statistics for this */
16208b9754b2SBitterblue Smith /* Disable power training when noisy environment */
16218b9754b2SBitterblue Smith /* if (p_dm_odm->is_disable_power_training) { */
16228b9754b2SBitterblue Smith if (1) {
16238b9754b2SBitterblue Smith ra->pt_stage = 0;
16248b9754b2SBitterblue Smith ra->ra_stage = 0;
16258b9754b2SBitterblue Smith ra->pt_stop_count = 0;
16268b9754b2SBitterblue Smith }
16278b9754b2SBitterblue Smith }
16288b9754b2SBitterblue Smith
rtl8188e_power_training_decision(struct rtl8xxxu_ra_info * ra)16298b9754b2SBitterblue Smith static void rtl8188e_power_training_decision(struct rtl8xxxu_ra_info *ra)
16308b9754b2SBitterblue Smith {
16318b9754b2SBitterblue Smith u8 temp_stage;
16328b9754b2SBitterblue Smith u32 numsc;
16338b9754b2SBitterblue Smith u32 num_total;
16348b9754b2SBitterblue Smith u8 stage_id;
16358b9754b2SBitterblue Smith u8 j;
16368b9754b2SBitterblue Smith
16378b9754b2SBitterblue Smith numsc = 0;
16388b9754b2SBitterblue Smith num_total = ra->total * pt_penalty[5];
16398b9754b2SBitterblue Smith for (j = 0; j <= 4; j++) {
16408b9754b2SBitterblue Smith numsc += ra->retry[j] * pt_penalty[j];
16418b9754b2SBitterblue Smith
16428b9754b2SBitterblue Smith if (numsc > num_total)
16438b9754b2SBitterblue Smith break;
16448b9754b2SBitterblue Smith }
16458b9754b2SBitterblue Smith
16468b9754b2SBitterblue Smith j >>= 1;
16478b9754b2SBitterblue Smith temp_stage = (ra->pt_stage + 1) >> 1;
16488b9754b2SBitterblue Smith if (temp_stage > j)
16498b9754b2SBitterblue Smith stage_id = temp_stage - j;
16508b9754b2SBitterblue Smith else
16518b9754b2SBitterblue Smith stage_id = 0;
16528b9754b2SBitterblue Smith
16538b9754b2SBitterblue Smith ra->pt_smooth_factor = (ra->pt_smooth_factor >> 1) +
16548b9754b2SBitterblue Smith (ra->pt_smooth_factor >> 2) +
16558b9754b2SBitterblue Smith stage_id * 16 + 2;
16568b9754b2SBitterblue Smith if (ra->pt_smooth_factor > 192)
16578b9754b2SBitterblue Smith ra->pt_smooth_factor = 192;
16588b9754b2SBitterblue Smith stage_id = ra->pt_smooth_factor >> 6;
16598b9754b2SBitterblue Smith temp_stage = stage_id * 2;
16608b9754b2SBitterblue Smith if (temp_stage != 0)
16618b9754b2SBitterblue Smith temp_stage--;
16628b9754b2SBitterblue Smith if (ra->drop > 3)
16638b9754b2SBitterblue Smith temp_stage = 0;
16648b9754b2SBitterblue Smith ra->pt_stage = temp_stage;
16658b9754b2SBitterblue Smith }
16668b9754b2SBitterblue Smith
rtl8188e_handle_ra_tx_report2(struct rtl8xxxu_priv * priv,struct sk_buff * skb)16678b9754b2SBitterblue Smith void rtl8188e_handle_ra_tx_report2(struct rtl8xxxu_priv *priv, struct sk_buff *skb)
16688b9754b2SBitterblue Smith {
16698b9754b2SBitterblue Smith u32 *_rx_desc = (u32 *)(skb->data - sizeof(struct rtl8xxxu_rxdesc16));
16708b9754b2SBitterblue Smith struct rtl8xxxu_rxdesc16 *rx_desc = (struct rtl8xxxu_rxdesc16 *)_rx_desc;
16718b9754b2SBitterblue Smith struct device *dev = &priv->udev->dev;
16728b9754b2SBitterblue Smith struct rtl8xxxu_ra_info *ra = &priv->ra_info;
16738b9754b2SBitterblue Smith u32 tx_rpt_len = rx_desc->pktlen & 0x3ff;
16748b9754b2SBitterblue Smith u32 items = tx_rpt_len / TX_RPT2_ITEM_SIZE;
16758b9754b2SBitterblue Smith u64 macid_valid = ((u64)_rx_desc[5] << 32) | _rx_desc[4];
16768b9754b2SBitterblue Smith u32 macid;
16778b9754b2SBitterblue Smith u8 *rpt = skb->data;
16788b9754b2SBitterblue Smith bool valid;
16798b9754b2SBitterblue Smith u16 min_rpt_time = 0x927c;
16808b9754b2SBitterblue Smith
16818b9754b2SBitterblue Smith dev_dbg(dev, "%s: len: %d items: %d\n", __func__, tx_rpt_len, items);
16828b9754b2SBitterblue Smith
1683398eb194SPing-Ke Shih /* We only use macid 0, so only the first item is relevant.
1684398eb194SPing-Ke Shih * AP mode will use more of them if it's ever implemented.
1685398eb194SPing-Ke Shih */
1686a047e46aSMartin Kaistra if (!priv->vifs[0] || priv->vifs[0]->type == NL80211_IFTYPE_STATION)
1687398eb194SPing-Ke Shih items = 1;
1688398eb194SPing-Ke Shih
16898b9754b2SBitterblue Smith for (macid = 0; macid < items; macid++) {
16908b9754b2SBitterblue Smith valid = false;
16918b9754b2SBitterblue Smith
16928b9754b2SBitterblue Smith if (macid < 64)
16938b9754b2SBitterblue Smith valid = macid_valid & BIT(macid);
16948b9754b2SBitterblue Smith
16958b9754b2SBitterblue Smith if (valid) {
16968b9754b2SBitterblue Smith ra->retry[0] = le16_to_cpu(*(__le16 *)rpt);
16978b9754b2SBitterblue Smith ra->retry[1] = rpt[2];
16988b9754b2SBitterblue Smith ra->retry[2] = rpt[3];
16998b9754b2SBitterblue Smith ra->retry[3] = rpt[4];
17008b9754b2SBitterblue Smith ra->retry[4] = rpt[5];
17018b9754b2SBitterblue Smith ra->drop = rpt[6];
17028b9754b2SBitterblue Smith ra->total = ra->retry[0] + ra->retry[1] + ra->retry[2] +
17038b9754b2SBitterblue Smith ra->retry[3] + ra->retry[4] + ra->drop;
17048b9754b2SBitterblue Smith
17058b9754b2SBitterblue Smith if (ra->total > 0) {
17068b9754b2SBitterblue Smith if (ra->ra_stage < 5)
17078b9754b2SBitterblue Smith rtl8188e_rate_decision(ra);
17088b9754b2SBitterblue Smith else if (ra->ra_stage == 5)
17098b9754b2SBitterblue Smith rtl8188e_power_training_try_state(ra);
17108b9754b2SBitterblue Smith else /* ra->ra_stage == 6 */
17118b9754b2SBitterblue Smith rtl8188e_power_training_decision(ra);
17128b9754b2SBitterblue Smith
17138b9754b2SBitterblue Smith if (ra->ra_stage <= 5)
17148b9754b2SBitterblue Smith ra->ra_stage++;
17158b9754b2SBitterblue Smith else
17168b9754b2SBitterblue Smith ra->ra_stage = 0;
17178b9754b2SBitterblue Smith }
17188b9754b2SBitterblue Smith } else if (macid == 0) {
17198b9754b2SBitterblue Smith dev_warn(dev, "%s: TX report item 0 not valid\n", __func__);
17208b9754b2SBitterblue Smith }
17218b9754b2SBitterblue Smith
17228b9754b2SBitterblue Smith dev_dbg(dev, "%s: valid: %d retry: %d %d %d %d %d drop: %d\n",
17238b9754b2SBitterblue Smith __func__, valid,
17248b9754b2SBitterblue Smith ra->retry[0], ra->retry[1], ra->retry[2],
17258b9754b2SBitterblue Smith ra->retry[3], ra->retry[4], ra->drop);
17268b9754b2SBitterblue Smith
17278b9754b2SBitterblue Smith if (min_rpt_time > ra->rpt_time)
17288b9754b2SBitterblue Smith min_rpt_time = ra->rpt_time;
17298b9754b2SBitterblue Smith
17308b9754b2SBitterblue Smith rpt += TX_RPT2_ITEM_SIZE;
17318b9754b2SBitterblue Smith }
17328b9754b2SBitterblue Smith
17338b9754b2SBitterblue Smith if (min_rpt_time != ra->pre_min_rpt_time) {
17348b9754b2SBitterblue Smith rtl8xxxu_write16(priv, REG_TX_REPORT_TIME, min_rpt_time);
17358b9754b2SBitterblue Smith ra->pre_min_rpt_time = min_rpt_time;
17368b9754b2SBitterblue Smith }
17378b9754b2SBitterblue Smith }
17388b9754b2SBitterblue Smith
rtl8188e_arfb_refresh(struct rtl8xxxu_ra_info * ra)17398b9754b2SBitterblue Smith static void rtl8188e_arfb_refresh(struct rtl8xxxu_ra_info *ra)
17408b9754b2SBitterblue Smith {
17418b9754b2SBitterblue Smith s8 i;
17428b9754b2SBitterblue Smith
17438b9754b2SBitterblue Smith ra->ra_use_rate = ra->rate_mask;
17448b9754b2SBitterblue Smith
17458b9754b2SBitterblue Smith /* Highest rate */
17468b9754b2SBitterblue Smith if (ra->ra_use_rate) {
17478b9754b2SBitterblue Smith for (i = RATESIZE; i >= 0; i--) {
17488b9754b2SBitterblue Smith if (ra->ra_use_rate & BIT(i)) {
17498b9754b2SBitterblue Smith ra->highest_rate = i;
17508b9754b2SBitterblue Smith break;
17518b9754b2SBitterblue Smith }
17528b9754b2SBitterblue Smith }
17538b9754b2SBitterblue Smith } else {
17548b9754b2SBitterblue Smith ra->highest_rate = 0;
17558b9754b2SBitterblue Smith }
17568b9754b2SBitterblue Smith
17578b9754b2SBitterblue Smith /* Lowest rate */
17588b9754b2SBitterblue Smith if (ra->ra_use_rate) {
17598b9754b2SBitterblue Smith for (i = 0; i < RATESIZE; i++) {
17608b9754b2SBitterblue Smith if (ra->ra_use_rate & BIT(i)) {
17618b9754b2SBitterblue Smith ra->lowest_rate = i;
17628b9754b2SBitterblue Smith break;
17638b9754b2SBitterblue Smith }
17648b9754b2SBitterblue Smith }
17658b9754b2SBitterblue Smith } else {
17668b9754b2SBitterblue Smith ra->lowest_rate = 0;
17678b9754b2SBitterblue Smith }
17688b9754b2SBitterblue Smith
17698b9754b2SBitterblue Smith if (ra->highest_rate > DESC_RATE_MCS7)
17708b9754b2SBitterblue Smith ra->pt_mode_ss = 3;
17718b9754b2SBitterblue Smith else if (ra->highest_rate > DESC_RATE_54M)
17728b9754b2SBitterblue Smith ra->pt_mode_ss = 2;
17738b9754b2SBitterblue Smith else if (ra->highest_rate > DESC_RATE_11M)
17748b9754b2SBitterblue Smith ra->pt_mode_ss = 1;
17758b9754b2SBitterblue Smith else
17768b9754b2SBitterblue Smith ra->pt_mode_ss = 0;
17778b9754b2SBitterblue Smith }
17788b9754b2SBitterblue Smith
17798b9754b2SBitterblue Smith static void
rtl8188e_update_rate_mask(struct rtl8xxxu_priv * priv,u32 ramask,u8 rateid,int sgi,int txbw_40mhz,u8 macid)17808b9754b2SBitterblue Smith rtl8188e_update_rate_mask(struct rtl8xxxu_priv *priv,
1781769f3263SMartin Kaistra u32 ramask, u8 rateid, int sgi, int txbw_40mhz,
1782769f3263SMartin Kaistra u8 macid)
17838b9754b2SBitterblue Smith {
17848b9754b2SBitterblue Smith struct rtl8xxxu_ra_info *ra = &priv->ra_info;
17858b9754b2SBitterblue Smith
17868b9754b2SBitterblue Smith ra->rate_id = rateid;
17878b9754b2SBitterblue Smith ra->rate_mask = ramask;
17888b9754b2SBitterblue Smith ra->sgi_enable = sgi;
17898b9754b2SBitterblue Smith
17908b9754b2SBitterblue Smith rtl8188e_arfb_refresh(ra);
17918b9754b2SBitterblue Smith }
17928b9754b2SBitterblue Smith
rtl8188e_ra_set_rssi(struct rtl8xxxu_priv * priv,u8 macid,u8 rssi)17933922dc9fSBitterblue Smith static void rtl8188e_ra_set_rssi(struct rtl8xxxu_priv *priv, u8 macid, u8 rssi)
17943922dc9fSBitterblue Smith {
17953922dc9fSBitterblue Smith priv->ra_info.rssi_sta_ra = rssi;
17963922dc9fSBitterblue Smith }
17973922dc9fSBitterblue Smith
rtl8188e_ra_info_init_all(struct rtl8xxxu_ra_info * ra)17988b9754b2SBitterblue Smith void rtl8188e_ra_info_init_all(struct rtl8xxxu_ra_info *ra)
17998b9754b2SBitterblue Smith {
18008b9754b2SBitterblue Smith ra->decision_rate = DESC_RATE_MCS7;
18018b9754b2SBitterblue Smith ra->pre_rate = DESC_RATE_MCS7;
18028b9754b2SBitterblue Smith ra->highest_rate = DESC_RATE_MCS7;
18038b9754b2SBitterblue Smith ra->lowest_rate = 0;
18048b9754b2SBitterblue Smith ra->rate_id = 0;
18058b9754b2SBitterblue Smith ra->rate_mask = 0xfffff;
18068b9754b2SBitterblue Smith ra->rssi_sta_ra = 0;
18078b9754b2SBitterblue Smith ra->pre_rssi_sta_ra = 0;
18088b9754b2SBitterblue Smith ra->sgi_enable = 0;
18098b9754b2SBitterblue Smith ra->ra_use_rate = 0xfffff;
18108b9754b2SBitterblue Smith ra->nsc_down = (n_threshold_high[DESC_RATE_MCS7] + n_threshold_low[DESC_RATE_MCS7]) / 2;
18118b9754b2SBitterblue Smith ra->nsc_up = (n_threshold_high[DESC_RATE_MCS7] + n_threshold_low[DESC_RATE_MCS7]) / 2;
18128b9754b2SBitterblue Smith ra->rate_sgi = 0;
18138b9754b2SBitterblue Smith ra->rpt_time = 0x927c;
18148b9754b2SBitterblue Smith ra->drop = 0;
18158b9754b2SBitterblue Smith ra->retry[0] = 0;
18168b9754b2SBitterblue Smith ra->retry[1] = 0;
18178b9754b2SBitterblue Smith ra->retry[2] = 0;
18188b9754b2SBitterblue Smith ra->retry[3] = 0;
18198b9754b2SBitterblue Smith ra->retry[4] = 0;
18208b9754b2SBitterblue Smith ra->total = 0;
18218b9754b2SBitterblue Smith ra->ra_waiting_counter = 0;
18228b9754b2SBitterblue Smith ra->ra_pending_counter = 0;
18238b9754b2SBitterblue Smith ra->ra_drop_after_down = 0;
18248b9754b2SBitterblue Smith
18258b9754b2SBitterblue Smith ra->pt_try_state = 0;
18268b9754b2SBitterblue Smith ra->pt_stage = 5;
18278b9754b2SBitterblue Smith ra->pt_smooth_factor = 192;
18288b9754b2SBitterblue Smith ra->pt_stop_count = 0;
18298b9754b2SBitterblue Smith ra->pt_pre_rate = 0;
18308b9754b2SBitterblue Smith ra->pt_pre_rssi = 0;
18318b9754b2SBitterblue Smith ra->pt_mode_ss = 0;
18328b9754b2SBitterblue Smith ra->ra_stage = 0;
18338b9754b2SBitterblue Smith }
18348b9754b2SBitterblue Smith
18353dfb8e84SJes Sorensen struct rtl8xxxu_fileops rtl8188eu_fops = {
18363dfb8e84SJes Sorensen .identify_chip = rtl8188eu_identify_chip,
18373dfb8e84SJes Sorensen .parse_efuse = rtl8188eu_parse_efuse,
18383dfb8e84SJes Sorensen .load_firmware = rtl8188eu_load_firmware,
18393dfb8e84SJes Sorensen .power_on = rtl8188eu_power_on,
18403dfb8e84SJes Sorensen .power_off = rtl8188eu_power_off,
184170664495SBitterblue Smith .read_efuse = rtl8xxxu_read_efuse,
18423dfb8e84SJes Sorensen .reset_8051 = rtl8188eu_reset_8051,
18433dfb8e84SJes Sorensen .llt_init = rtl8xxxu_init_llt_table,
18443dfb8e84SJes Sorensen .init_phy_bb = rtl8188eu_init_phy_bb,
18453dfb8e84SJes Sorensen .init_phy_rf = rtl8188eu_init_phy_rf,
18463dfb8e84SJes Sorensen .phy_lc_calibrate = rtl8723a_phy_lc_calibrate,
18473dfb8e84SJes Sorensen .phy_iq_calibrate = rtl8188eu_phy_iq_calibrate,
18483dfb8e84SJes Sorensen .config_channel = rtl8188eu_config_channel,
18493dfb8e84SJes Sorensen .parse_rx_desc = rtl8xxxu_parse_rxdesc16,
185070664495SBitterblue Smith .parse_phystats = rtl8723au_rx_parse_phystats,
18513dfb8e84SJes Sorensen .init_aggregation = rtl8188eu_init_aggregation,
18523dfb8e84SJes Sorensen .enable_rf = rtl8188e_enable_rf,
18533dfb8e84SJes Sorensen .disable_rf = rtl8188e_disable_rf,
18543dfb8e84SJes Sorensen .usb_quirks = rtl8188e_usb_quirks,
18553dfb8e84SJes Sorensen .set_tx_power = rtl8188f_set_tx_power,
18568b9754b2SBitterblue Smith .update_rate_mask = rtl8188e_update_rate_mask,
18573dfb8e84SJes Sorensen .report_connect = rtl8xxxu_gen2_report_connect,
18583922dc9fSBitterblue Smith .report_rssi = rtl8188e_ra_set_rssi,
18593dfb8e84SJes Sorensen .fill_txdesc = rtl8xxxu_fill_txdesc_v3,
18603dfb8e84SJes Sorensen .set_crystal_cap = rtl8188f_set_crystal_cap,
18613dfb8e84SJes Sorensen .cck_rssi = rtl8188e_cck_rssi,
1862873b3811SBitterblue Smith .led_classdev_brightness_set = rtl8188eu_led_brightness_set,
1863*93b3a456SBitterblue Smith .writeN_block_size = 196,
18643dfb8e84SJes Sorensen .rx_desc_size = sizeof(struct rtl8xxxu_rxdesc16),
18653dfb8e84SJes Sorensen .tx_desc_size = sizeof(struct rtl8xxxu_txdesc32),
18663dfb8e84SJes Sorensen .has_tx_report = 1,
1867a5be45eaSBitterblue Smith .init_reg_pkt_life_time = 1,
18683dfb8e84SJes Sorensen .gen2_thermal_meter = 1,
1869563d5025SMartin Kaistra .max_sec_cam_num = 32,
18703dfb8e84SJes Sorensen .adda_1t_init = 0x0b1b25a0,
18713dfb8e84SJes Sorensen .adda_1t_path_on = 0x0bdb25a0,
18723dfb8e84SJes Sorensen /*
18733dfb8e84SJes Sorensen * Use 9K for 8188e normal chip
18743dfb8e84SJes Sorensen * Max RX buffer = 10K - max(TxReportSize(64*8), WOLPattern(16*24))
18753dfb8e84SJes Sorensen */
18763dfb8e84SJes Sorensen .trxff_boundary = 0x25ff,
18773dfb8e84SJes Sorensen .pbp_rx = PBP_PAGE_SIZE_128,
18783dfb8e84SJes Sorensen .pbp_tx = PBP_PAGE_SIZE_128,
18793dfb8e84SJes Sorensen .mactable = rtl8188e_mac_init_table,
18803dfb8e84SJes Sorensen .total_page_num = TX_TOTAL_PAGE_NUM_8188E,
18813dfb8e84SJes Sorensen .page_num_hi = TX_PAGE_NUM_HI_PQ_8188E,
18823dfb8e84SJes Sorensen .page_num_lo = TX_PAGE_NUM_LO_PQ_8188E,
18833dfb8e84SJes Sorensen .page_num_norm = TX_PAGE_NUM_NORM_PQ_8188E,
18843dfb8e84SJes Sorensen .last_llt_entry = 175,
18853dfb8e84SJes Sorensen };
1886