Resguardo inicial

This commit is contained in:
lastdragon
2026-09-06 12:53:21 -06:00
parent 662efe3c2a
commit ad2088d178
94853 changed files with 43200404 additions and 0 deletions
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,742 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* RTL8XXXU mac80211 USB driver - 8188c/8188r/8192c specific subdriver
*
* Copyright (c) 2014 - 2017 Jes Sorensen <Jes.Sorensen@gmail.com>
*
* Portions, notably calibration code:
* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
*
* This driver was written as a replacement for the vendor provided
* rtl8723au driver. As the Realtek 8xxx chips are very similar in
* their programming interface, I have started adding support for
* additional 8xxx chips like the 8192cu, 8188cus, etc.
*/
#include "regs.h"
#include "rtl8xxxu.h"
#ifdef CONFIG_RTL8XXXU_UNTESTED
static struct rtl8xxxu_power_base rtl8192c_power_base = {
.reg_0e00 = 0x07090c0c,
.reg_0e04 = 0x01020405,
.reg_0e08 = 0x00000000,
.reg_086c = 0x00000000,
.reg_0e10 = 0x0b0c0c0e,
.reg_0e14 = 0x01030506,
.reg_0e18 = 0x0b0c0d0e,
.reg_0e1c = 0x01030509,
.reg_0830 = 0x07090c0c,
.reg_0834 = 0x01020405,
.reg_0838 = 0x00000000,
.reg_086c_2 = 0x00000000,
.reg_083c = 0x0b0c0d0e,
.reg_0848 = 0x01030509,
.reg_084c = 0x0b0c0d0e,
.reg_0868 = 0x01030509,
};
static struct rtl8xxxu_power_base rtl8188r_power_base = {
.reg_0e00 = 0x06080808,
.reg_0e04 = 0x00040406,
.reg_0e08 = 0x00000000,
.reg_086c = 0x00000000,
.reg_0e10 = 0x04060608,
.reg_0e14 = 0x00020204,
.reg_0e18 = 0x04060608,
.reg_0e1c = 0x00020204,
.reg_0830 = 0x06080808,
.reg_0834 = 0x00040406,
.reg_0838 = 0x00000000,
.reg_086c_2 = 0x00000000,
.reg_083c = 0x04060608,
.reg_0848 = 0x00020204,
.reg_084c = 0x04060608,
.reg_0868 = 0x00020204,
};
static const struct rtl8xxxu_reg8val rtl8192cu_mac_init_table[] = {
{0x420, 0x80}, {0x423, 0x00}, {0x430, 0x00}, {0x431, 0x00},
{0x432, 0x00}, {0x433, 0x01}, {0x434, 0x04}, {0x435, 0x05},
{0x436, 0x06}, {0x437, 0x07}, {0x438, 0x00}, {0x439, 0x00},
{0x43a, 0x00}, {0x43b, 0x01}, {0x43c, 0x04}, {0x43d, 0x05},
{0x43e, 0x06}, {0x43f, 0x07}, {0x440, 0x5d}, {0x441, 0x01},
{0x442, 0x00}, {0x444, 0x15}, {0x445, 0xf0}, {0x446, 0x0f},
{0x447, 0x00}, {0x458, 0x41}, {0x459, 0xa8}, {0x45a, 0x72},
{0x45b, 0xb9}, {0x460, 0x66}, {0x461, 0x66}, {0x462, 0x08},
{0x463, 0x03}, {0x4c8, 0xff}, {0x4c9, 0x08}, {0x4cc, 0xff},
{0x4cd, 0xff}, {0x4ce, 0x01}, {0x500, 0x26}, {0x501, 0xa2},
{0x502, 0x2f}, {0x503, 0x00}, {0x504, 0x28}, {0x505, 0xa3},
{0x506, 0x5e}, {0x507, 0x00}, {0x508, 0x2b}, {0x509, 0xa4},
{0x50a, 0x5e}, {0x50b, 0x00}, {0x50c, 0x4f}, {0x50d, 0xa4},
{0x50e, 0x00}, {0x50f, 0x00}, {0x512, 0x1c}, {0x514, 0x0a},
{0x515, 0x10}, {0x516, 0x0a}, {0x517, 0x10}, {0x51a, 0x16},
{0x524, 0x0f}, {0x525, 0x4f}, {0x546, 0x40}, {0x547, 0x00},
{0x550, 0x10}, {0x551, 0x10}, {0x559, 0x02}, {0x55a, 0x02},
{0x55d, 0xff}, {0x605, 0x30}, {0x608, 0x0e}, {0x609, 0x2a},
{0x652, 0x20}, {0x652, 0x20}, {0x63c, 0x08}, {0x63d, 0x08},
{0x63e, 0x0c}, {0x63f, 0x0c}, {0x66e, 0x05}, {0x700, 0x21},
{0x701, 0x43}, {0x702, 0x65}, {0x703, 0x87}, {0x708, 0x21},
{0x709, 0x43}, {0x70a, 0x65}, {0x70b, 0x87},
{0xffff, 0xff},
};
static const struct rtl8xxxu_rfregval rtl8192cu_radioa_2t_init_table[] = {
{0x00, 0x00030159}, {0x01, 0x00031284},
{0x02, 0x00098000}, {0x03, 0x00018c63},
{0x04, 0x000210e7}, {0x09, 0x0002044f},
{0x0a, 0x0001adb1}, {0x0b, 0x00054867},
{0x0c, 0x0008992e}, {0x0d, 0x0000e52c},
{0x0e, 0x00039ce7}, {0x0f, 0x00000451},
{0x19, 0x00000000}, {0x1a, 0x00010255},
{0x1b, 0x00060a00}, {0x1c, 0x000fc378},
{0x1d, 0x000a1250}, {0x1e, 0x0004445f},
{0x1f, 0x00080001}, {0x20, 0x0000b614},
{0x21, 0x0006c000}, {0x22, 0x00000000},
{0x23, 0x00001558}, {0x24, 0x00000060},
{0x25, 0x00000483}, {0x26, 0x0004f000},
{0x27, 0x000ec7d9}, {0x28, 0x000577c0},
{0x29, 0x00004783}, {0x2a, 0x00000001},
{0x2b, 0x00021334}, {0x2a, 0x00000000},
{0x2b, 0x00000054}, {0x2a, 0x00000001},
{0x2b, 0x00000808}, {0x2b, 0x00053333},
{0x2c, 0x0000000c}, {0x2a, 0x00000002},
{0x2b, 0x00000808}, {0x2b, 0x0005b333},
{0x2c, 0x0000000d}, {0x2a, 0x00000003},
{0x2b, 0x00000808}, {0x2b, 0x00063333},
{0x2c, 0x0000000d}, {0x2a, 0x00000004},
{0x2b, 0x00000808}, {0x2b, 0x0006b333},
{0x2c, 0x0000000d}, {0x2a, 0x00000005},
{0x2b, 0x00000808}, {0x2b, 0x00073333},
{0x2c, 0x0000000d}, {0x2a, 0x00000006},
{0x2b, 0x00000709}, {0x2b, 0x0005b333},
{0x2c, 0x0000000d}, {0x2a, 0x00000007},
{0x2b, 0x00000709}, {0x2b, 0x00063333},
{0x2c, 0x0000000d}, {0x2a, 0x00000008},
{0x2b, 0x0000060a}, {0x2b, 0x0004b333},
{0x2c, 0x0000000d}, {0x2a, 0x00000009},
{0x2b, 0x0000060a}, {0x2b, 0x00053333},
{0x2c, 0x0000000d}, {0x2a, 0x0000000a},
{0x2b, 0x0000060a}, {0x2b, 0x0005b333},
{0x2c, 0x0000000d}, {0x2a, 0x0000000b},
{0x2b, 0x0000060a}, {0x2b, 0x00063333},
{0x2c, 0x0000000d}, {0x2a, 0x0000000c},
{0x2b, 0x0000060a}, {0x2b, 0x0006b333},
{0x2c, 0x0000000d}, {0x2a, 0x0000000d},
{0x2b, 0x0000060a}, {0x2b, 0x00073333},
{0x2c, 0x0000000d}, {0x2a, 0x0000000e},
{0x2b, 0x0000050b}, {0x2b, 0x00066666},
{0x2c, 0x0000001a}, {0x2a, 0x000e0000},
{0x10, 0x0004000f}, {0x11, 0x000e31fc},
{0x10, 0x0006000f}, {0x11, 0x000ff9f8},
{0x10, 0x0002000f}, {0x11, 0x000203f9},
{0x10, 0x0003000f}, {0x11, 0x000ff500},
{0x10, 0x00000000}, {0x11, 0x00000000},
{0x10, 0x0008000f}, {0x11, 0x0003f100},
{0x10, 0x0009000f}, {0x11, 0x00023100},
{0x12, 0x00032000}, {0x12, 0x00071000},
{0x12, 0x000b0000}, {0x12, 0x000fc000},
{0x13, 0x000287b3}, {0x13, 0x000244b7},
{0x13, 0x000204ab}, {0x13, 0x0001c49f},
{0x13, 0x00018493}, {0x13, 0x0001429b},
{0x13, 0x00010299}, {0x13, 0x0000c29c},
{0x13, 0x000081a0}, {0x13, 0x000040ac},
{0x13, 0x00000020}, {0x14, 0x0001944c},
{0x14, 0x00059444}, {0x14, 0x0009944c},
{0x14, 0x000d9444}, {0x15, 0x0000f424},
{0x15, 0x0004f424}, {0x15, 0x0008f424},
{0x15, 0x000cf424}, {0x16, 0x000e0330},
{0x16, 0x000a0330}, {0x16, 0x00060330},
{0x16, 0x00020330}, {0x00, 0x00010159},
{0x18, 0x0000f401}, {0xfe, 0x00000000},
{0xfe, 0x00000000}, {0x1f, 0x00080003},
{0xfe, 0x00000000}, {0xfe, 0x00000000},
{0x1e, 0x00044457}, {0x1f, 0x00080000},
{0x00, 0x00030159},
{0xff, 0xffffffff}
};
static const struct rtl8xxxu_rfregval rtl8192cu_radiob_2t_init_table[] = {
{0x00, 0x00030159}, {0x01, 0x00031284},
{0x02, 0x00098000}, {0x03, 0x00018c63},
{0x04, 0x000210e7}, {0x09, 0x0002044f},
{0x0a, 0x0001adb1}, {0x0b, 0x00054867},
{0x0c, 0x0008992e}, {0x0d, 0x0000e52c},
{0x0e, 0x00039ce7}, {0x0f, 0x00000451},
{0x12, 0x00032000}, {0x12, 0x00071000},
{0x12, 0x000b0000}, {0x12, 0x000fc000},
{0x13, 0x000287af}, {0x13, 0x000244b7},
{0x13, 0x000204ab}, {0x13, 0x0001c49f},
{0x13, 0x00018493}, {0x13, 0x00014297},
{0x13, 0x00010295}, {0x13, 0x0000c298},
{0x13, 0x0000819c}, {0x13, 0x000040a8},
{0x13, 0x0000001c}, {0x14, 0x0001944c},
{0x14, 0x00059444}, {0x14, 0x0009944c},
{0x14, 0x000d9444}, {0x15, 0x0000f424},
{0x15, 0x0004f424}, {0x15, 0x0008f424},
{0x15, 0x000cf424}, {0x16, 0x000e0330},
{0x16, 0x000a0330}, {0x16, 0x00060330},
{0x16, 0x00020330},
{0xff, 0xffffffff}
};
static const struct rtl8xxxu_rfregval rtl8192cu_radioa_1t_init_table[] = {
{0x00, 0x00030159}, {0x01, 0x00031284},
{0x02, 0x00098000}, {0x03, 0x00018c63},
{0x04, 0x000210e7}, {0x09, 0x0002044f},
{0x0a, 0x0001adb1}, {0x0b, 0x00054867},
{0x0c, 0x0008992e}, {0x0d, 0x0000e52c},
{0x0e, 0x00039ce7}, {0x0f, 0x00000451},
{0x19, 0x00000000}, {0x1a, 0x00010255},
{0x1b, 0x00060a00}, {0x1c, 0x000fc378},
{0x1d, 0x000a1250}, {0x1e, 0x0004445f},
{0x1f, 0x00080001}, {0x20, 0x0000b614},
{0x21, 0x0006c000}, {0x22, 0x00000000},
{0x23, 0x00001558}, {0x24, 0x00000060},
{0x25, 0x00000483}, {0x26, 0x0004f000},
{0x27, 0x000ec7d9}, {0x28, 0x000577c0},
{0x29, 0x00004783}, {0x2a, 0x00000001},
{0x2b, 0x00021334}, {0x2a, 0x00000000},
{0x2b, 0x00000054}, {0x2a, 0x00000001},
{0x2b, 0x00000808}, {0x2b, 0x00053333},
{0x2c, 0x0000000c}, {0x2a, 0x00000002},
{0x2b, 0x00000808}, {0x2b, 0x0005b333},
{0x2c, 0x0000000d}, {0x2a, 0x00000003},
{0x2b, 0x00000808}, {0x2b, 0x00063333},
{0x2c, 0x0000000d}, {0x2a, 0x00000004},
{0x2b, 0x00000808}, {0x2b, 0x0006b333},
{0x2c, 0x0000000d}, {0x2a, 0x00000005},
{0x2b, 0x00000808}, {0x2b, 0x00073333},
{0x2c, 0x0000000d}, {0x2a, 0x00000006},
{0x2b, 0x00000709}, {0x2b, 0x0005b333},
{0x2c, 0x0000000d}, {0x2a, 0x00000007},
{0x2b, 0x00000709}, {0x2b, 0x00063333},
{0x2c, 0x0000000d}, {0x2a, 0x00000008},
{0x2b, 0x0000060a}, {0x2b, 0x0004b333},
{0x2c, 0x0000000d}, {0x2a, 0x00000009},
{0x2b, 0x0000060a}, {0x2b, 0x00053333},
{0x2c, 0x0000000d}, {0x2a, 0x0000000a},
{0x2b, 0x0000060a}, {0x2b, 0x0005b333},
{0x2c, 0x0000000d}, {0x2a, 0x0000000b},
{0x2b, 0x0000060a}, {0x2b, 0x00063333},
{0x2c, 0x0000000d}, {0x2a, 0x0000000c},
{0x2b, 0x0000060a}, {0x2b, 0x0006b333},
{0x2c, 0x0000000d}, {0x2a, 0x0000000d},
{0x2b, 0x0000060a}, {0x2b, 0x00073333},
{0x2c, 0x0000000d}, {0x2a, 0x0000000e},
{0x2b, 0x0000050b}, {0x2b, 0x00066666},
{0x2c, 0x0000001a}, {0x2a, 0x000e0000},
{0x10, 0x0004000f}, {0x11, 0x000e31fc},
{0x10, 0x0006000f}, {0x11, 0x000ff9f8},
{0x10, 0x0002000f}, {0x11, 0x000203f9},
{0x10, 0x0003000f}, {0x11, 0x000ff500},
{0x10, 0x00000000}, {0x11, 0x00000000},
{0x10, 0x0008000f}, {0x11, 0x0003f100},
{0x10, 0x0009000f}, {0x11, 0x00023100},
{0x12, 0x00032000}, {0x12, 0x00071000},
{0x12, 0x000b0000}, {0x12, 0x000fc000},
{0x13, 0x000287b3}, {0x13, 0x000244b7},
{0x13, 0x000204ab}, {0x13, 0x0001c49f},
{0x13, 0x00018493}, {0x13, 0x0001429b},
{0x13, 0x00010299}, {0x13, 0x0000c29c},
{0x13, 0x000081a0}, {0x13, 0x000040ac},
{0x13, 0x00000020}, {0x14, 0x0001944c},
{0x14, 0x00059444}, {0x14, 0x0009944c},
{0x14, 0x000d9444}, {0x15, 0x0000f405},
{0x15, 0x0004f405}, {0x15, 0x0008f405},
{0x15, 0x000cf405}, {0x16, 0x000e0330},
{0x16, 0x000a0330}, {0x16, 0x00060330},
{0x16, 0x00020330}, {0x00, 0x00010159},
{0x18, 0x0000f401}, {0xfe, 0x00000000},
{0xfe, 0x00000000}, {0x1f, 0x00080003},
{0xfe, 0x00000000}, {0xfe, 0x00000000},
{0x1e, 0x00044457}, {0x1f, 0x00080000},
{0x00, 0x00030159},
{0xff, 0xffffffff}
};
static const struct rtl8xxxu_rfregval rtl8188ru_radioa_1t_highpa_table[] = {
{0x00, 0x00030159}, {0x01, 0x00031284},
{0x02, 0x00098000}, {0x03, 0x00018c63},
{0x04, 0x000210e7}, {0x09, 0x0002044f},
{0x0a, 0x0001adb0}, {0x0b, 0x00054867},
{0x0c, 0x0008992e}, {0x0d, 0x0000e529},
{0x0e, 0x00039ce7}, {0x0f, 0x00000451},
{0x19, 0x00000000}, {0x1a, 0x00000255},
{0x1b, 0x00060a00}, {0x1c, 0x000fc378},
{0x1d, 0x000a1250}, {0x1e, 0x0004445f},
{0x1f, 0x00080001}, {0x20, 0x0000b614},
{0x21, 0x0006c000}, {0x22, 0x0000083c},
{0x23, 0x00001558}, {0x24, 0x00000060},
{0x25, 0x00000483}, {0x26, 0x0004f000},
{0x27, 0x000ec7d9}, {0x28, 0x000977c0},
{0x29, 0x00004783}, {0x2a, 0x00000001},
{0x2b, 0x00021334}, {0x2a, 0x00000000},
{0x2b, 0x00000054}, {0x2a, 0x00000001},
{0x2b, 0x00000808}, {0x2b, 0x00053333},
{0x2c, 0x0000000c}, {0x2a, 0x00000002},
{0x2b, 0x00000808}, {0x2b, 0x0005b333},
{0x2c, 0x0000000d}, {0x2a, 0x00000003},
{0x2b, 0x00000808}, {0x2b, 0x00063333},
{0x2c, 0x0000000d}, {0x2a, 0x00000004},
{0x2b, 0x00000808}, {0x2b, 0x0006b333},
{0x2c, 0x0000000d}, {0x2a, 0x00000005},
{0x2b, 0x00000808}, {0x2b, 0x00073333},
{0x2c, 0x0000000d}, {0x2a, 0x00000006},
{0x2b, 0x00000709}, {0x2b, 0x0005b333},
{0x2c, 0x0000000d}, {0x2a, 0x00000007},
{0x2b, 0x00000709}, {0x2b, 0x00063333},
{0x2c, 0x0000000d}, {0x2a, 0x00000008},
{0x2b, 0x0000060a}, {0x2b, 0x0004b333},
{0x2c, 0x0000000d}, {0x2a, 0x00000009},
{0x2b, 0x0000060a}, {0x2b, 0x00053333},
{0x2c, 0x0000000d}, {0x2a, 0x0000000a},
{0x2b, 0x0000060a}, {0x2b, 0x0005b333},
{0x2c, 0x0000000d}, {0x2a, 0x0000000b},
{0x2b, 0x0000060a}, {0x2b, 0x00063333},
{0x2c, 0x0000000d}, {0x2a, 0x0000000c},
{0x2b, 0x0000060a}, {0x2b, 0x0006b333},
{0x2c, 0x0000000d}, {0x2a, 0x0000000d},
{0x2b, 0x0000060a}, {0x2b, 0x00073333},
{0x2c, 0x0000000d}, {0x2a, 0x0000000e},
{0x2b, 0x0000050b}, {0x2b, 0x00066666},
{0x2c, 0x0000001a}, {0x2a, 0x000e0000},
{0x10, 0x0004000f}, {0x11, 0x000e31fc},
{0x10, 0x0006000f}, {0x11, 0x000ff9f8},
{0x10, 0x0002000f}, {0x11, 0x000203f9},
{0x10, 0x0003000f}, {0x11, 0x000ff500},
{0x10, 0x00000000}, {0x11, 0x00000000},
{0x10, 0x0008000f}, {0x11, 0x0003f100},
{0x10, 0x0009000f}, {0x11, 0x00023100},
{0x12, 0x000d8000}, {0x12, 0x00090000},
{0x12, 0x00051000}, {0x12, 0x00012000},
{0x13, 0x00028fb4}, {0x13, 0x00024fa8},
{0x13, 0x000207a4}, {0x13, 0x0001c3b0},
{0x13, 0x000183a4}, {0x13, 0x00014398},
{0x13, 0x000101a4}, {0x13, 0x0000c198},
{0x13, 0x000080a4}, {0x13, 0x00004098},
{0x13, 0x00000000}, {0x14, 0x0001944c},
{0x14, 0x00059444}, {0x14, 0x0009944c},
{0x14, 0x000d9444}, {0x15, 0x0000f405},
{0x15, 0x0004f405}, {0x15, 0x0008f405},
{0x15, 0x000cf405}, {0x16, 0x000e0330},
{0x16, 0x000a0330}, {0x16, 0x00060330},
{0x16, 0x00020330}, {0x00, 0x00010159},
{0x18, 0x0000f401}, {0xfe, 0x00000000},
{0xfe, 0x00000000}, {0x1f, 0x00080003},
{0xfe, 0x00000000}, {0xfe, 0x00000000},
{0x1e, 0x00044457}, {0x1f, 0x00080000},
{0x00, 0x00030159},
{0xff, 0xffffffff}
};
static int rtl8192cu_identify_chip(struct rtl8xxxu_priv *priv)
{
struct device *dev = &priv->udev->dev;
u32 val32, bonding, sys_cfg, vendor;
int ret = 0;
sys_cfg = rtl8xxxu_read32(priv, REG_SYS_CFG);
priv->chip_cut = u32_get_bits(sys_cfg, SYS_CFG_CHIP_VERSION_MASK);
if (sys_cfg & SYS_CFG_TRP_VAUX_EN) {
dev_info(dev, "Unsupported test chip\n");
ret = -ENOTSUPP;
goto out;
}
if (sys_cfg & SYS_CFG_TYPE_ID) {
bonding = rtl8xxxu_read32(priv, REG_HPON_FSM);
bonding &= HPON_FSM_BONDING_MASK;
if (bonding == HPON_FSM_BONDING_1T2R) {
strscpy(priv->chip_name, "8191CU", sizeof(priv->chip_name));
priv->tx_paths = 1;
priv->usb_interrupts = 1;
priv->rtl_chip = RTL8191C;
} else {
strscpy(priv->chip_name, "8192CU", sizeof(priv->chip_name));
priv->tx_paths = 2;
priv->usb_interrupts = 0;
priv->rtl_chip = RTL8192C;
}
priv->rf_paths = 2;
priv->rx_paths = 2;
} else {
strscpy(priv->chip_name, "8188CU", sizeof(priv->chip_name));
priv->rf_paths = 1;
priv->rx_paths = 1;
priv->tx_paths = 1;
priv->rtl_chip = RTL8188C;
priv->usb_interrupts = 0;
}
priv->has_wifi = 1;
vendor = sys_cfg & SYS_CFG_VENDOR_ID;
rtl8xxxu_identify_vendor_1bit(priv, vendor);
val32 = rtl8xxxu_read32(priv, REG_GPIO_OUTSTS);
priv->rom_rev = u32_get_bits(val32, GPIO_RF_RL_ID);
rtl8xxxu_config_endpoints_sie(priv);
/*
* Fallback for devices that do not provide REG_NORMAL_SIE_EP_TX
*/
if (!priv->ep_tx_count)
ret = rtl8xxxu_config_endpoints_no_sie(priv);
out:
return ret;
}
static int rtl8192cu_load_firmware(struct rtl8xxxu_priv *priv)
{
const char *fw_name;
int ret;
if (!priv->vendor_umc)
fw_name = "rtlwifi/rtl8192cufw_TMSC.bin";
else if (priv->chip_cut || priv->rtl_chip == RTL8192C)
fw_name = "rtlwifi/rtl8192cufw_B.bin";
else
fw_name = "rtlwifi/rtl8192cufw_A.bin";
ret = rtl8xxxu_load_firmware(priv, fw_name);
return ret;
}
static int rtl8192cu_parse_efuse(struct rtl8xxxu_priv *priv)
{
struct rtl8192cu_efuse *efuse = &priv->efuse_wifi.efuse8192;
if (efuse->rtl_id != cpu_to_le16(0x8129))
return -EINVAL;
ether_addr_copy(priv->mac_addr, efuse->mac_addr);
memcpy(priv->cck_tx_power_index_A,
efuse->cck_tx_power_index_A,
sizeof(efuse->cck_tx_power_index_A));
memcpy(priv->cck_tx_power_index_B,
efuse->cck_tx_power_index_B,
sizeof(efuse->cck_tx_power_index_B));
memcpy(priv->ht40_1s_tx_power_index_A,
efuse->ht40_1s_tx_power_index_A,
sizeof(efuse->ht40_1s_tx_power_index_A));
memcpy(priv->ht40_1s_tx_power_index_B,
efuse->ht40_1s_tx_power_index_B,
sizeof(efuse->ht40_1s_tx_power_index_B));
memcpy(priv->ht40_2s_tx_power_index_diff,
efuse->ht40_2s_tx_power_index_diff,
sizeof(efuse->ht40_2s_tx_power_index_diff));
memcpy(priv->ht20_tx_power_index_diff,
efuse->ht20_tx_power_index_diff,
sizeof(efuse->ht20_tx_power_index_diff));
memcpy(priv->ofdm_tx_power_index_diff,
efuse->ofdm_tx_power_index_diff,
sizeof(efuse->ofdm_tx_power_index_diff));
memcpy(priv->ht40_max_power_offset,
efuse->ht40_max_power_offset,
sizeof(efuse->ht40_max_power_offset));
memcpy(priv->ht20_max_power_offset,
efuse->ht20_max_power_offset,
sizeof(efuse->ht20_max_power_offset));
priv->power_base = &rtl8192c_power_base;
if (efuse->rf_regulatory & 0x20) {
strscpy(priv->chip_name, "8188RU", sizeof(priv->chip_name));
priv->rtl_chip = RTL8188R;
priv->hi_pa = 1;
priv->no_pape = 1;
priv->power_base = &rtl8188r_power_base;
}
return 0;
}
static int rtl8192cu_init_phy_rf(struct rtl8xxxu_priv *priv)
{
const struct rtl8xxxu_rfregval *rftable;
int ret;
if (priv->rtl_chip == RTL8188R) {
rftable = rtl8188ru_radioa_1t_highpa_table;
ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_A);
} else if (priv->rf_paths == 1) {
rftable = rtl8192cu_radioa_1t_init_table;
ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_A);
} else {
rftable = rtl8192cu_radioa_2t_init_table;
ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_A);
if (ret)
goto exit;
rftable = rtl8192cu_radiob_2t_init_table;
ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_B);
}
exit:
return ret;
}
static int rtl8192cu_power_on(struct rtl8xxxu_priv *priv)
{
u8 val8;
u16 val16;
u32 val32;
int i;
for (i = 100; i; i--) {
val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO);
if (val8 & APS_FSMCO_PFM_ALDN)
break;
}
if (!i) {
pr_info("%s: Poll failed\n", __func__);
return -ENODEV;
}
/*
* RSV_CTRL 0x001C[7:0] = 0x00, unlock ISO/CLK/Power control register
*/
rtl8xxxu_write8(priv, REG_RSV_CTRL, 0x0);
rtl8xxxu_write8(priv, REG_SPS0_CTRL, 0x2b);
udelay(100);
val8 = rtl8xxxu_read8(priv, REG_LDOV12D_CTRL);
if (!(val8 & LDOV12D_ENABLE)) {
pr_info("%s: Enabling LDOV12D (%02x)\n", __func__, val8);
val8 |= LDOV12D_ENABLE;
rtl8xxxu_write8(priv, REG_LDOV12D_CTRL, val8);
udelay(100);
val8 = rtl8xxxu_read8(priv, REG_SYS_ISO_CTRL);
val8 &= ~SYS_ISO_MD2PP;
rtl8xxxu_write8(priv, REG_SYS_ISO_CTRL, val8);
}
/*
* Auto enable WLAN
*/
val16 = rtl8xxxu_read16(priv, REG_APS_FSMCO);
val16 |= APS_FSMCO_MAC_ENABLE;
rtl8xxxu_write16(priv, REG_APS_FSMCO, val16);
for (i = 1000; i; i--) {
val16 = rtl8xxxu_read16(priv, REG_APS_FSMCO);
if (!(val16 & APS_FSMCO_MAC_ENABLE))
break;
}
if (!i) {
pr_info("%s: FSMCO_MAC_ENABLE poll failed\n", __func__);
return -EBUSY;
}
/*
* Enable radio, GPIO, LED
*/
val16 = APS_FSMCO_HW_SUSPEND | APS_FSMCO_ENABLE_POWERDOWN |
APS_FSMCO_PFM_ALDN;
rtl8xxxu_write16(priv, REG_APS_FSMCO, val16);
/*
* Release RF digital isolation
*/
val16 = rtl8xxxu_read16(priv, REG_SYS_ISO_CTRL);
val16 &= ~SYS_ISO_DIOR;
rtl8xxxu_write16(priv, REG_SYS_ISO_CTRL, val16);
val8 = rtl8xxxu_read8(priv, REG_APSD_CTRL);
val8 &= ~APSD_CTRL_OFF;
rtl8xxxu_write8(priv, REG_APSD_CTRL, val8);
for (i = 200; i; i--) {
val8 = rtl8xxxu_read8(priv, REG_APSD_CTRL);
if (!(val8 & APSD_CTRL_OFF_STATUS))
break;
}
if (!i) {
pr_info("%s: APSD_CTRL poll failed\n", __func__);
return -EBUSY;
}
/*
* Enable MAC DMA/WMAC/SCHEDULE/SEC block
*/
val16 = rtl8xxxu_read16(priv, REG_CR);
val16 |= CR_HCI_TXDMA_ENABLE | CR_HCI_RXDMA_ENABLE |
CR_TXDMA_ENABLE | CR_RXDMA_ENABLE | CR_PROTOCOL_ENABLE |
CR_SCHEDULE_ENABLE | CR_MAC_TX_ENABLE | CR_MAC_RX_ENABLE;
rtl8xxxu_write16(priv, REG_CR, val16);
rtl8xxxu_write8(priv, 0xfe10, 0x19);
/*
* Workaround for 8188RU LNA power leakage problem.
*/
if (priv->rtl_chip == RTL8188R) {
val32 = rtl8xxxu_read32(priv, REG_FPGA0_XCD_RF_PARM);
val32 &= ~BIT(1);
rtl8xxxu_write32(priv, REG_FPGA0_XCD_RF_PARM, val32);
}
return 0;
}
static void rtl8192cu_power_off(struct rtl8xxxu_priv *priv)
{
u32 val32;
u16 val16;
u8 val8;
int i;
/*
* Workaround for 8188RU LNA power leakage problem.
*/
if (priv->rtl_chip == RTL8188R) {
val32 = rtl8xxxu_read32(priv, REG_FPGA0_XCD_RF_PARM);
val32 |= BIT(1);
rtl8xxxu_write32(priv, REG_FPGA0_XCD_RF_PARM, val32);
}
/* _DisableRFAFEAndResetBB */
rtl8xxxu_write8(priv, REG_TXPAUSE, 0xff);
rtl8xxxu_write_rfreg_mask(priv, RF_A, RF6052_REG_AC, 0xff, 0);
rtl8xxxu_write8_set(priv, REG_APSD_CTRL, APSD_CTRL_OFF);
rtl8xxxu_write32_set(priv, REG_FPGA0_XCD_RF_PARM, FPGA0_RF_PARM_CLK_GATE);
rtl8xxxu_write8(priv, REG_SYS_FUNC,
SYS_FUNC_USBA | SYS_FUNC_USBD | SYS_FUNC_BB_GLB_RSTN);
rtl8xxxu_write8(priv, REG_SYS_FUNC, SYS_FUNC_USBA | SYS_FUNC_USBD);
/* _ResetDigitalProcedure1 */
if (rtl8xxxu_read8(priv, REG_MCU_FW_DL) & MCU_FW_DL_READY) {
rtl8xxxu_write8(priv, REG_MCU_FW_DL, 0x00);
rtl8xxxu_write8(priv, REG_FWIMR, 0x20);
rtl8xxxu_write8(priv, REG_HMTFR + 3, 0x20);
for (i = 0; i < 100; i++) {
val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC);
if (!(val16 & SYS_FUNC_CPU_ENABLE))
break;
fsleep(50);
}
if (i == 100) {
rtl8xxxu_write8(priv, REG_SYS_FUNC + 1,
(SYS_FUNC_HWPDN | SYS_FUNC_ELDR) >> 8);
msleep(10);
}
}
val8 = (SYS_FUNC_HWPDN | SYS_FUNC_ELDR | SYS_FUNC_CPU_ENABLE) >> 8;
rtl8xxxu_write8(priv, REG_SYS_FUNC + 1, val8);
/* _DisableGPIO */
rtl8xxxu_write16(priv, REG_GPIO_PIN_CTRL + 2, 0);
val32 = rtl8xxxu_read32(priv, REG_GPIO_PIN_CTRL) & 0xffff00ff;
val32 |= (val32 & 0xff) << 8;
val32 |= 0x00ff0000;
rtl8xxxu_write32(priv, REG_GPIO_PIN_CTRL, val32);
rtl8xxxu_write8(priv, REG_GPIO_MUXCFG + 3, 0);
val16 = rtl8xxxu_read16(priv, REG_GPIO_MUXCFG + 2) & 0xff0f;
val16 |= (val16 & 0xf) << 4;
val16 |= 0x0780;
rtl8xxxu_write16(priv, REG_GPIO_MUXCFG + 2, val16);
/* _DisableAnalog */
val8 = 0x23;
if (priv->vendor_umc && priv->chip_cut == 1)
val8 |= BIT(3);
rtl8xxxu_write8(priv, REG_SPS0_CTRL, val8);
val16 = APS_FSMCO_HOST | APS_FSMCO_HW_SUSPEND | APS_FSMCO_PFM_ALDN;
rtl8xxxu_write16(priv, REG_APS_FSMCO, val16);
rtl8xxxu_write8(priv, REG_RSV_CTRL, 0x0e);
}
static int rtl8192cu_led_brightness_set(struct led_classdev *led_cdev,
enum led_brightness brightness)
{
struct rtl8xxxu_priv *priv = container_of(led_cdev,
struct rtl8xxxu_priv,
led_cdev);
u8 ledcfg = rtl8xxxu_read8(priv, REG_LEDCFG0);
if (brightness == LED_OFF)
ledcfg = LEDCFG2_SW_LED_CONTROL | LEDCFG2_SW_LED_DISABLE;
else if (brightness == LED_ON)
ledcfg = LEDCFG2_SW_LED_CONTROL;
else if (brightness == RTL8XXXU_HW_LED_CONTROL)
ledcfg = LEDCFG2_HW_LED_CONTROL | LEDCFG2_HW_LED_ENABLE;
rtl8xxxu_write8(priv, REG_LEDCFG0, ledcfg);
return 0;
}
struct rtl8xxxu_fileops rtl8192cu_fops = {
.identify_chip = rtl8192cu_identify_chip,
.parse_efuse = rtl8192cu_parse_efuse,
.load_firmware = rtl8192cu_load_firmware,
.power_on = rtl8192cu_power_on,
.power_off = rtl8192cu_power_off,
.read_efuse = rtl8xxxu_read_efuse,
.reset_8051 = rtl8xxxu_reset_8051,
.llt_init = rtl8xxxu_init_llt_table,
.init_phy_bb = rtl8xxxu_gen1_init_phy_bb,
.init_phy_rf = rtl8192cu_init_phy_rf,
.phy_lc_calibrate = rtl8723a_phy_lc_calibrate,
.phy_iq_calibrate = rtl8xxxu_gen1_phy_iq_calibrate,
.config_channel = rtl8xxxu_gen1_config_channel,
.parse_rx_desc = rtl8xxxu_parse_rxdesc16,
.parse_phystats = rtl8723au_rx_parse_phystats,
.init_aggregation = rtl8xxxu_gen1_init_aggregation,
.enable_rf = rtl8xxxu_gen1_enable_rf,
.disable_rf = rtl8xxxu_gen1_disable_rf,
.usb_quirks = rtl8xxxu_gen1_usb_quirks,
.set_tx_power = rtl8xxxu_gen1_set_tx_power,
.update_rate_mask = rtl8xxxu_update_rate_mask,
.report_connect = rtl8xxxu_gen1_report_connect,
.report_rssi = rtl8xxxu_gen1_report_rssi,
.fill_txdesc = rtl8xxxu_fill_txdesc_v1,
.cck_rssi = rtl8723a_cck_rssi,
.led_classdev_brightness_set = rtl8192cu_led_brightness_set,
.writeN_block_size = 128,
.rx_agg_buf_size = 16000,
.tx_desc_size = sizeof(struct rtl8xxxu_txdesc32),
.rx_desc_size = sizeof(struct rtl8xxxu_rxdesc16),
.supports_ap = 1,
.hw_feature_report = 0,
.max_macid_num = 32,
.max_sec_cam_num = 32,
.adda_1t_init = 0x0b1b25a0,
.adda_1t_path_on = 0x0bdb25a0,
.adda_2t_path_on_a = 0x04db25a4,
.adda_2t_path_on_b = 0x0b1b25a4,
.trxff_boundary = 0x27ff,
.pbp_rx = PBP_PAGE_SIZE_128,
.pbp_tx = PBP_PAGE_SIZE_128,
.mactable = rtl8192cu_mac_init_table,
.total_page_num = TX_TOTAL_PAGE_NUM,
.page_num_hi = TX_PAGE_NUM_HI_PQ,
.page_num_lo = TX_PAGE_NUM_LO_PQ,
.page_num_norm = TX_PAGE_NUM_NORM_PQ,
};
#endif
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,649 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* RTL8XXXU mac80211 USB driver - 8723a specific subdriver
*
* Copyright (c) 2014 - 2017 Jes Sorensen <Jes.Sorensen@gmail.com>
*
* Portions, notably calibration code:
* Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
*
* This driver was written as a replacement for the vendor provided
* rtl8723au driver. As the Realtek 8xxx chips are very similar in
* their programming interface, I have started adding support for
* additional 8xxx chips like the 8192cu, 8188cus, etc.
*/
#include "regs.h"
#include "rtl8xxxu.h"
static struct rtl8xxxu_power_base rtl8723a_power_base = {
.reg_0e00 = 0x0a0c0c0c,
.reg_0e04 = 0x02040608,
.reg_0e08 = 0x00000000,
.reg_086c = 0x00000000,
.reg_0e10 = 0x0a0c0d0e,
.reg_0e14 = 0x02040608,
.reg_0e18 = 0x0a0c0d0e,
.reg_0e1c = 0x02040608,
.reg_0830 = 0x0a0c0c0c,
.reg_0834 = 0x02040608,
.reg_0838 = 0x00000000,
.reg_086c_2 = 0x00000000,
.reg_083c = 0x0a0c0d0e,
.reg_0848 = 0x02040608,
.reg_084c = 0x0a0c0d0e,
.reg_0868 = 0x02040608,
};
static const struct rtl8xxxu_reg8val rtl8723au_mac_init_table[] = {
{0x420, 0x80}, {0x423, 0x00}, {0x430, 0x00}, {0x431, 0x00},
{0x432, 0x00}, {0x433, 0x01}, {0x434, 0x04}, {0x435, 0x05},
{0x436, 0x06}, {0x437, 0x07}, {0x438, 0x00}, {0x439, 0x00},
{0x43a, 0x00}, {0x43b, 0x01}, {0x43c, 0x04}, {0x43d, 0x05},
{0x43e, 0x06}, {0x43f, 0x07}, {0x440, 0x5d}, {0x441, 0x01},
{0x442, 0x00}, {0x444, 0x15}, {0x445, 0xf0}, {0x446, 0x0f},
{0x447, 0x00}, {0x458, 0x41}, {0x459, 0xa8}, {0x45a, 0x72},
{0x45b, 0xb9}, {0x460, 0x66}, {0x461, 0x66}, {0x462, 0x08},
{0x463, 0x03}, {0x4c8, 0xff}, {0x4c9, 0x08}, {0x4cc, 0xff},
{0x4cd, 0xff}, {0x4ce, 0x01}, {0x500, 0x26}, {0x501, 0xa2},
{0x502, 0x2f}, {0x503, 0x00}, {0x504, 0x28}, {0x505, 0xa3},
{0x506, 0x5e}, {0x507, 0x00}, {0x508, 0x2b}, {0x509, 0xa4},
{0x50a, 0x5e}, {0x50b, 0x00}, {0x50c, 0x4f}, {0x50d, 0xa4},
{0x50e, 0x00}, {0x50f, 0x00}, {0x512, 0x1c}, {0x514, 0x0a},
{0x515, 0x10}, {0x516, 0x0a}, {0x517, 0x10}, {0x51a, 0x16},
{0x524, 0x0f}, {0x525, 0x4f}, {0x546, 0x40}, {0x547, 0x00},
{0x550, 0x10}, {0x551, 0x10}, {0x559, 0x02}, {0x55a, 0x02},
{0x55d, 0xff}, {0x605, 0x30}, {0x608, 0x0e}, {0x609, 0x2a},
{0x652, 0x20}, {0x63c, 0x0a}, {0x63d, 0x0a}, {0x63e, 0x0e},
{0x63f, 0x0e}, {0x66e, 0x05}, {0x700, 0x21}, {0x701, 0x43},
{0x702, 0x65}, {0x703, 0x87}, {0x708, 0x21}, {0x709, 0x43},
{0x70a, 0x65}, {0x70b, 0x87}, {0xffff, 0xff},
};
static const struct rtl8xxxu_rfregval rtl8723au_radioa_1t_init_table[] = {
{0x00, 0x00030159}, {0x01, 0x00031284},
{0x02, 0x00098000}, {0x03, 0x00039c63},
{0x04, 0x000210e7}, {0x09, 0x0002044f},
{0x0a, 0x0001a3f1}, {0x0b, 0x00014787},
{0x0c, 0x000896fe}, {0x0d, 0x0000e02c},
{0x0e, 0x00039ce7}, {0x0f, 0x00000451},
{0x19, 0x00000000}, {0x1a, 0x00030355},
{0x1b, 0x00060a00}, {0x1c, 0x000fc378},
{0x1d, 0x000a1250}, {0x1e, 0x0000024f},
{0x1f, 0x00000000}, {0x20, 0x0000b614},
{0x21, 0x0006c000}, {0x22, 0x00000000},
{0x23, 0x00001558}, {0x24, 0x00000060},
{0x25, 0x00000483}, {0x26, 0x0004f000},
{0x27, 0x000ec7d9}, {0x28, 0x00057730},
{0x29, 0x00004783}, {0x2a, 0x00000001},
{0x2b, 0x00021334}, {0x2a, 0x00000000},
{0x2b, 0x00000054}, {0x2a, 0x00000001},
{0x2b, 0x00000808}, {0x2b, 0x00053333},
{0x2c, 0x0000000c}, {0x2a, 0x00000002},
{0x2b, 0x00000808}, {0x2b, 0x0005b333},
{0x2c, 0x0000000d}, {0x2a, 0x00000003},
{0x2b, 0x00000808}, {0x2b, 0x00063333},
{0x2c, 0x0000000d}, {0x2a, 0x00000004},
{0x2b, 0x00000808}, {0x2b, 0x0006b333},
{0x2c, 0x0000000d}, {0x2a, 0x00000005},
{0x2b, 0x00000808}, {0x2b, 0x00073333},
{0x2c, 0x0000000d}, {0x2a, 0x00000006},
{0x2b, 0x00000709}, {0x2b, 0x0005b333},
{0x2c, 0x0000000d}, {0x2a, 0x00000007},
{0x2b, 0x00000709}, {0x2b, 0x00063333},
{0x2c, 0x0000000d}, {0x2a, 0x00000008},
{0x2b, 0x0000060a}, {0x2b, 0x0004b333},
{0x2c, 0x0000000d}, {0x2a, 0x00000009},
{0x2b, 0x0000060a}, {0x2b, 0x00053333},
{0x2c, 0x0000000d}, {0x2a, 0x0000000a},
{0x2b, 0x0000060a}, {0x2b, 0x0005b333},
{0x2c, 0x0000000d}, {0x2a, 0x0000000b},
{0x2b, 0x0000060a}, {0x2b, 0x00063333},
{0x2c, 0x0000000d}, {0x2a, 0x0000000c},
{0x2b, 0x0000060a}, {0x2b, 0x0006b333},
{0x2c, 0x0000000d}, {0x2a, 0x0000000d},
{0x2b, 0x0000060a}, {0x2b, 0x00073333},
{0x2c, 0x0000000d}, {0x2a, 0x0000000e},
{0x2b, 0x0000050b}, {0x2b, 0x00066666},
{0x2c, 0x0000001a}, {0x2a, 0x000e0000},
{0x10, 0x0004000f}, {0x11, 0x000e31fc},
{0x10, 0x0006000f}, {0x11, 0x000ff9f8},
{0x10, 0x0002000f}, {0x11, 0x000203f9},
{0x10, 0x0003000f}, {0x11, 0x000ff500},
{0x10, 0x00000000}, {0x11, 0x00000000},
{0x10, 0x0008000f}, {0x11, 0x0003f100},
{0x10, 0x0009000f}, {0x11, 0x00023100},
{0x12, 0x00032000}, {0x12, 0x00071000},
{0x12, 0x000b0000}, {0x12, 0x000fc000},
{0x13, 0x000287b3}, {0x13, 0x000244b7},
{0x13, 0x000204ab}, {0x13, 0x0001c49f},
{0x13, 0x00018493}, {0x13, 0x0001429b},
{0x13, 0x00010299}, {0x13, 0x0000c29c},
{0x13, 0x000081a0}, {0x13, 0x000040ac},
{0x13, 0x00000020}, {0x14, 0x0001944c},
{0x14, 0x00059444}, {0x14, 0x0009944c},
{0x14, 0x000d9444}, {0x15, 0x0000f474},
{0x15, 0x0004f477}, {0x15, 0x0008f455},
{0x15, 0x000cf455}, {0x16, 0x00000339},
{0x16, 0x00040339}, {0x16, 0x00080339},
{0x16, 0x000c0366}, {0x00, 0x00010159},
{0x18, 0x0000f401}, {0xfe, 0x00000000},
{0xfe, 0x00000000}, {0x1f, 0x00000003},
{0xfe, 0x00000000}, {0xfe, 0x00000000},
{0x1e, 0x00000247}, {0x1f, 0x00000000},
{0x00, 0x00030159},
{0xff, 0xffffffff}
};
static int rtl8723au_identify_chip(struct rtl8xxxu_priv *priv)
{
struct device *dev = &priv->udev->dev;
u32 val32, sys_cfg, vendor;
int ret = 0;
sys_cfg = rtl8xxxu_read32(priv, REG_SYS_CFG);
priv->chip_cut = u32_get_bits(sys_cfg, SYS_CFG_CHIP_VERSION_MASK);
if (sys_cfg & SYS_CFG_TRP_VAUX_EN) {
dev_info(dev, "Unsupported test chip\n");
ret = -ENOTSUPP;
goto out;
}
strscpy(priv->chip_name, "8723AU", sizeof(priv->chip_name));
priv->usb_interrupts = 1;
priv->rtl_chip = RTL8723A;
priv->rf_paths = 1;
priv->rx_paths = 1;
priv->tx_paths = 1;
val32 = rtl8xxxu_read32(priv, REG_MULTI_FUNC_CTRL);
if (val32 & MULTI_WIFI_FUNC_EN)
priv->has_wifi = 1;
if (val32 & MULTI_BT_FUNC_EN)
priv->has_bluetooth = 1;
if (val32 & MULTI_GPS_FUNC_EN)
priv->has_gps = 1;
priv->is_multi_func = 1;
vendor = sys_cfg & SYS_CFG_VENDOR_ID;
rtl8xxxu_identify_vendor_1bit(priv, vendor);
val32 = rtl8xxxu_read32(priv, REG_GPIO_OUTSTS);
priv->rom_rev = u32_get_bits(val32, GPIO_RF_RL_ID);
rtl8xxxu_config_endpoints_sie(priv);
/*
* Fallback for devices that do not provide REG_NORMAL_SIE_EP_TX
*/
if (!priv->ep_tx_count)
ret = rtl8xxxu_config_endpoints_no_sie(priv);
out:
return ret;
}
static int rtl8723au_parse_efuse(struct rtl8xxxu_priv *priv)
{
struct rtl8723au_efuse *efuse = &priv->efuse_wifi.efuse8723;
if (efuse->rtl_id != cpu_to_le16(0x8129))
return -EINVAL;
ether_addr_copy(priv->mac_addr, efuse->mac_addr);
memcpy(priv->cck_tx_power_index_A,
efuse->cck_tx_power_index_A,
sizeof(efuse->cck_tx_power_index_A));
memcpy(priv->cck_tx_power_index_B,
efuse->cck_tx_power_index_B,
sizeof(efuse->cck_tx_power_index_B));
memcpy(priv->ht40_1s_tx_power_index_A,
efuse->ht40_1s_tx_power_index_A,
sizeof(efuse->ht40_1s_tx_power_index_A));
memcpy(priv->ht40_1s_tx_power_index_B,
efuse->ht40_1s_tx_power_index_B,
sizeof(efuse->ht40_1s_tx_power_index_B));
memcpy(priv->ht20_tx_power_index_diff,
efuse->ht20_tx_power_index_diff,
sizeof(efuse->ht20_tx_power_index_diff));
memcpy(priv->ofdm_tx_power_index_diff,
efuse->ofdm_tx_power_index_diff,
sizeof(efuse->ofdm_tx_power_index_diff));
memcpy(priv->ht40_max_power_offset,
efuse->ht40_max_power_offset,
sizeof(efuse->ht40_max_power_offset));
memcpy(priv->ht20_max_power_offset,
efuse->ht20_max_power_offset,
sizeof(efuse->ht20_max_power_offset));
if (priv->efuse_wifi.efuse8723.version >= 0x01)
priv->default_crystal_cap = priv->efuse_wifi.efuse8723.xtal_k & 0x3f;
else
priv->fops->set_crystal_cap = NULL;
priv->power_base = &rtl8723a_power_base;
return 0;
}
static int rtl8723au_load_firmware(struct rtl8xxxu_priv *priv)
{
const char *fw_name;
int ret;
switch (priv->chip_cut) {
case 0:
fw_name = "rtlwifi/rtl8723aufw_A.bin";
break;
case 1:
if (priv->enable_bluetooth)
fw_name = "rtlwifi/rtl8723aufw_B.bin";
else
fw_name = "rtlwifi/rtl8723aufw_B_NoBT.bin";
break;
default:
return -EINVAL;
}
ret = rtl8xxxu_load_firmware(priv, fw_name);
return ret;
}
static int rtl8723au_init_phy_rf(struct rtl8xxxu_priv *priv)
{
int ret;
ret = rtl8xxxu_init_phy_rf(priv, rtl8723au_radioa_1t_init_table, RF_A);
/* Reduce 80M spur */
rtl8xxxu_write32(priv, REG_AFE_XTAL_CTRL, 0x0381808d);
rtl8xxxu_write32(priv, REG_AFE_PLL_CTRL, 0xf0ffff83);
rtl8xxxu_write32(priv, REG_AFE_PLL_CTRL, 0xf0ffff82);
rtl8xxxu_write32(priv, REG_AFE_PLL_CTRL, 0xf0ffff83);
return ret;
}
static int rtl8723a_emu_to_active(struct rtl8xxxu_priv *priv)
{
u8 val8;
u32 val32;
int count, ret = 0;
/* 0x20[0] = 1 enable LDOA12 MACRO block for all interface*/
val8 = rtl8xxxu_read8(priv, REG_LDOA15_CTRL);
val8 |= LDOA15_ENABLE;
rtl8xxxu_write8(priv, REG_LDOA15_CTRL, val8);
/* 0x67[0] = 0 to disable BT_GPS_SEL pins*/
val8 = rtl8xxxu_read8(priv, 0x0067);
val8 &= ~BIT(4);
rtl8xxxu_write8(priv, 0x0067, val8);
mdelay(1);
/* 0x00[5] = 0 release analog Ips to digital, 1:isolation */
val8 = rtl8xxxu_read8(priv, REG_SYS_ISO_CTRL);
val8 &= ~SYS_ISO_ANALOG_IPS;
rtl8xxxu_write8(priv, REG_SYS_ISO_CTRL, val8);
/* disable SW LPS 0x04[10]= 0 */
val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1);
val8 &= ~BIT(2);
rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val8);
/* wait till 0x04[17] = 1 power ready*/
for (count = RTL8XXXU_MAX_REG_POLL; count; count--) {
val32 = rtl8xxxu_read32(priv, REG_APS_FSMCO);
if (val32 & BIT(17))
break;
udelay(10);
}
if (!count) {
ret = -EBUSY;
goto exit;
}
/* We should be able to optimize the following three entries into one */
/* release WLON reset 0x04[16]= 1*/
val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 2);
val8 |= BIT(0);
rtl8xxxu_write8(priv, REG_APS_FSMCO + 2, val8);
/* disable HWPDN 0x04[15]= 0*/
val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1);
val8 &= ~BIT(7);
rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val8);
/* disable WL suspend*/
val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1);
val8 &= ~(BIT(3) | BIT(4));
rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val8);
/* set, then poll until 0 */
val32 = rtl8xxxu_read32(priv, REG_APS_FSMCO);
val32 |= APS_FSMCO_MAC_ENABLE;
rtl8xxxu_write32(priv, REG_APS_FSMCO, val32);
for (count = RTL8XXXU_MAX_REG_POLL; count; count--) {
val32 = rtl8xxxu_read32(priv, REG_APS_FSMCO);
if ((val32 & APS_FSMCO_MAC_ENABLE) == 0) {
ret = 0;
break;
}
udelay(10);
}
if (!count) {
ret = -EBUSY;
goto exit;
}
/* 0x4C[23] = 0x4E[7] = 1, switch DPDT_SEL_P output from WL BB */
/*
* Note: Vendor driver actually clears this bit, despite the
* documentation claims it's being set!
*/
val8 = rtl8xxxu_read8(priv, REG_LEDCFG2);
val8 |= LEDCFG2_DPDT_SELECT;
val8 &= ~LEDCFG2_DPDT_SELECT;
rtl8xxxu_write8(priv, REG_LEDCFG2, val8);
exit:
return ret;
}
static int rtl8723au_power_on(struct rtl8xxxu_priv *priv)
{
u8 val8;
u16 val16;
u32 val32;
int ret;
/*
* RSV_CTRL 0x001C[7:0] = 0x00, unlock ISO/CLK/Power control register
*/
rtl8xxxu_write8(priv, REG_RSV_CTRL, 0x0);
rtl8xxxu_disabled_to_emu(priv);
ret = rtl8723a_emu_to_active(priv);
if (ret)
goto exit;
/*
* 0x0004[19] = 1, reset 8051
*/
val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 2);
val8 |= BIT(3);
rtl8xxxu_write8(priv, REG_APS_FSMCO + 2, val8);
/*
* Enable MAC DMA/WMAC/SCHEDULE/SEC block
* Set CR bit10 to enable 32k calibration.
*/
val16 = rtl8xxxu_read16(priv, REG_CR);
val16 |= (CR_HCI_TXDMA_ENABLE | CR_HCI_RXDMA_ENABLE |
CR_TXDMA_ENABLE | CR_RXDMA_ENABLE |
CR_PROTOCOL_ENABLE | CR_SCHEDULE_ENABLE |
CR_MAC_TX_ENABLE | CR_MAC_RX_ENABLE |
CR_SECURITY_ENABLE | CR_CALTIMER_ENABLE);
rtl8xxxu_write16(priv, REG_CR, val16);
/* For EFuse PG */
val32 = rtl8xxxu_read32(priv, REG_EFUSE_CTRL);
val32 &= ~(BIT(28) | BIT(29) | BIT(30));
val32 |= (0x06 << 28);
rtl8xxxu_write32(priv, REG_EFUSE_CTRL, val32);
exit:
return ret;
}
static int rtl8723au_active_to_emu(struct rtl8xxxu_priv *priv)
{
u8 val8;
int count, ret = 0;
/* Start of rtl8723AU_card_enable_flow */
/* Act to Cardemu sequence*/
/* Turn off RF */
rtl8xxxu_write8(priv, REG_RF_CTRL, 0);
/* 0x004E[7] = 0, switch DPDT_SEL_P output from register 0x0065[2] */
val8 = rtl8xxxu_read8(priv, REG_LEDCFG2);
val8 &= ~LEDCFG2_DPDT_SELECT;
rtl8xxxu_write8(priv, REG_LEDCFG2, val8);
/* 0x0005[1] = 1 turn off MAC by HW state machine*/
val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1);
val8 |= BIT(1);
rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val8);
for (count = RTL8XXXU_MAX_REG_POLL; count; count--) {
val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1);
if ((val8 & BIT(1)) == 0)
break;
udelay(10);
}
if (!count) {
dev_warn(&priv->udev->dev, "%s: Disabling MAC timed out\n",
__func__);
ret = -EBUSY;
goto exit;
}
/* 0x0000[5] = 1 analog Ips to digital, 1:isolation */
val8 = rtl8xxxu_read8(priv, REG_SYS_ISO_CTRL);
val8 |= SYS_ISO_ANALOG_IPS;
rtl8xxxu_write8(priv, REG_SYS_ISO_CTRL, val8);
/* 0x0020[0] = 0 disable LDOA12 MACRO block*/
val8 = rtl8xxxu_read8(priv, REG_LDOA15_CTRL);
val8 &= ~LDOA15_ENABLE;
rtl8xxxu_write8(priv, REG_LDOA15_CTRL, val8);
exit:
return ret;
}
static int rtl8723au_emu_to_disabled(struct rtl8xxxu_priv *priv)
{
u8 val8;
/* 0x0007[7:0] = 0x20 SOP option to disable BG/MB */
rtl8xxxu_write8(priv, REG_APS_FSMCO + 3, 0x20);
/* 0x04[12:11] = 01 enable WL suspend */
val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1);
val8 &= ~BIT(4);
val8 |= BIT(3);
rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val8);
val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1);
val8 |= BIT(7);
rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val8);
/* 0x48[16] = 1 to enable GPIO9 as EXT wakeup */
val8 = rtl8xxxu_read8(priv, REG_GPIO_INTM + 2);
val8 |= BIT(0);
rtl8xxxu_write8(priv, REG_GPIO_INTM + 2, val8);
return 0;
}
static void rtl8723au_power_off(struct rtl8xxxu_priv *priv)
{
u8 val8;
u16 val16;
rtl8xxxu_flush_fifo(priv);
rtl8xxxu_active_to_lps(priv);
/* Turn off RF */
rtl8xxxu_write8(priv, REG_RF_CTRL, 0x00);
/* Reset Firmware if running in RAM */
if (rtl8xxxu_read8(priv, REG_MCU_FW_DL) & MCU_FW_RAM_SEL)
rtl8xxxu_firmware_self_reset(priv);
/* Reset MCU */
val16 = rtl8xxxu_read16(priv, REG_SYS_FUNC);
val16 &= ~SYS_FUNC_CPU_ENABLE;
rtl8xxxu_write16(priv, REG_SYS_FUNC, val16);
/* Reset MCU ready status */
rtl8xxxu_write8(priv, REG_MCU_FW_DL, 0x00);
rtl8723au_active_to_emu(priv);
rtl8723au_emu_to_disabled(priv);
/* Reset MCU IO Wrapper */
val8 = rtl8xxxu_read8(priv, REG_RSV_CTRL + 1);
val8 &= ~BIT(0);
rtl8xxxu_write8(priv, REG_RSV_CTRL + 1, val8);
val8 = rtl8xxxu_read8(priv, REG_RSV_CTRL + 1);
val8 |= BIT(0);
rtl8xxxu_write8(priv, REG_RSV_CTRL + 1, val8);
/* RSV_CTRL 0x1C[7:0] = 0x0e lock ISO/CLK/Power control register */
rtl8xxxu_write8(priv, REG_RSV_CTRL, 0x0e);
}
#define XTAL1 GENMASK(23, 18)
#define XTAL0 GENMASK(17, 12)
void rtl8723a_set_crystal_cap(struct rtl8xxxu_priv *priv, u8 crystal_cap)
{
struct rtl8xxxu_cfo_tracking *cfo = &priv->cfo_tracking;
u32 val32;
if (crystal_cap == cfo->crystal_cap)
return;
val32 = rtl8xxxu_read32(priv, REG_MAC_PHY_CTRL);
dev_dbg(&priv->udev->dev,
"%s: Adjusting crystal cap from 0x%x (actually 0x%lx 0x%lx) to 0x%x\n",
__func__,
cfo->crystal_cap,
FIELD_GET(XTAL1, val32),
FIELD_GET(XTAL0, val32),
crystal_cap);
val32 &= ~(XTAL1 | XTAL0);
val32 |= FIELD_PREP(XTAL1, crystal_cap) |
FIELD_PREP(XTAL0, crystal_cap);
rtl8xxxu_write32(priv, REG_MAC_PHY_CTRL, val32);
cfo->crystal_cap = crystal_cap;
}
s8 rtl8723a_cck_rssi(struct rtl8xxxu_priv *priv, struct rtl8723au_phy_stats *phy_stats)
{
u8 cck_agc_rpt = phy_stats->cck_agc_rpt_ofdm_cfosho_a;
s8 rx_pwr_all = 0x00;
switch (cck_agc_rpt & 0xc0) {
case 0xc0:
rx_pwr_all = -46 - (cck_agc_rpt & 0x3e);
break;
case 0x80:
rx_pwr_all = -26 - (cck_agc_rpt & 0x3e);
break;
case 0x40:
rx_pwr_all = -12 - (cck_agc_rpt & 0x3e);
break;
case 0x00:
rx_pwr_all = 16 - (cck_agc_rpt & 0x3e);
break;
}
return rx_pwr_all;
}
static int rtl8723au_led_brightness_set(struct led_classdev *led_cdev,
enum led_brightness brightness)
{
struct rtl8xxxu_priv *priv = container_of(led_cdev,
struct rtl8xxxu_priv,
led_cdev);
u8 ledcfg = rtl8xxxu_read8(priv, REG_LEDCFG2);
if (brightness == LED_OFF) {
ledcfg &= ~LEDCFG2_HW_LED_CONTROL;
ledcfg |= LEDCFG2_SW_LED_CONTROL | LEDCFG2_SW_LED_DISABLE;
} else if (brightness == LED_ON) {
ledcfg &= ~(LEDCFG2_HW_LED_CONTROL | LEDCFG2_SW_LED_DISABLE);
ledcfg |= LEDCFG2_SW_LED_CONTROL;
} else if (brightness == RTL8XXXU_HW_LED_CONTROL) {
ledcfg &= ~LEDCFG2_SW_LED_DISABLE;
ledcfg |= LEDCFG2_HW_LED_CONTROL | LEDCFG2_HW_LED_ENABLE;
}
rtl8xxxu_write8(priv, REG_LEDCFG2, ledcfg);
return 0;
}
struct rtl8xxxu_fileops rtl8723au_fops = {
.identify_chip = rtl8723au_identify_chip,
.parse_efuse = rtl8723au_parse_efuse,
.load_firmware = rtl8723au_load_firmware,
.power_on = rtl8723au_power_on,
.power_off = rtl8723au_power_off,
.read_efuse = rtl8xxxu_read_efuse,
.reset_8051 = rtl8xxxu_reset_8051,
.llt_init = rtl8xxxu_init_llt_table,
.init_phy_bb = rtl8xxxu_gen1_init_phy_bb,
.init_phy_rf = rtl8723au_init_phy_rf,
.phy_lc_calibrate = rtl8723a_phy_lc_calibrate,
.phy_iq_calibrate = rtl8xxxu_gen1_phy_iq_calibrate,
.config_channel = rtl8xxxu_gen1_config_channel,
.parse_rx_desc = rtl8xxxu_parse_rxdesc16,
.parse_phystats = rtl8723au_rx_parse_phystats,
.init_aggregation = rtl8xxxu_gen1_init_aggregation,
.enable_rf = rtl8xxxu_gen1_enable_rf,
.disable_rf = rtl8xxxu_gen1_disable_rf,
.usb_quirks = rtl8xxxu_gen1_usb_quirks,
.set_tx_power = rtl8xxxu_gen1_set_tx_power,
.update_rate_mask = rtl8xxxu_update_rate_mask,
.report_connect = rtl8xxxu_gen1_report_connect,
.report_rssi = rtl8xxxu_gen1_report_rssi,
.fill_txdesc = rtl8xxxu_fill_txdesc_v1,
.set_crystal_cap = rtl8723a_set_crystal_cap,
.cck_rssi = rtl8723a_cck_rssi,
.led_classdev_brightness_set = rtl8723au_led_brightness_set,
.writeN_block_size = 1024,
.rx_agg_buf_size = 16000,
.tx_desc_size = sizeof(struct rtl8xxxu_txdesc32),
.rx_desc_size = sizeof(struct rtl8xxxu_rxdesc16),
.hw_feature_report = 0,
.max_sec_cam_num = 32,
.adda_1t_init = 0x0b1b25a0,
.adda_1t_path_on = 0x0bdb25a0,
.adda_2t_path_on_a = 0x04db25a4,
.adda_2t_path_on_b = 0x0b1b25a4,
.trxff_boundary = 0x27ff,
.pbp_rx = PBP_PAGE_SIZE_128,
.pbp_tx = PBP_PAGE_SIZE_128,
.mactable = rtl8723au_mac_init_table,
.total_page_num = TX_TOTAL_PAGE_NUM,
.page_num_hi = TX_PAGE_NUM_HI_PQ,
.page_num_lo = TX_PAGE_NUM_LO_PQ,
.page_num_norm = TX_PAGE_NUM_NORM_PQ,
};
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,37 @@
# SPDX-License-Identifier: GPL-2.0-only
#
# RTL8XXXU Wireless LAN device configuration
#
config RTL8XXXU
tristate "Realtek 802.11n USB wireless chips support"
depends on MAC80211 && USB
depends on LEDS_CLASS
help
This is an alternative driver for various Realtek RTL8XXX
parts written to utilize the Linux mac80211 stack.
The driver is known to work with a number of RTL8723AU,
RL8188CU, RTL8188RU, RTL8191CU, RTL8192CU, RTL8723BU, RTL8192EU,
RTL8188FU, RTL8188EU, RTL8710BU (aka RTL8188GU), and RTL8192FU
devices.
This driver is under development and has a limited feature
set. In particular it does not yet support 40MHz channels
and power management. However it should have a smaller
memory footprint than the vendor drivers and benefits
from the in kernel mac80211 stack.
It can coexist with the rtlwifi driver but you will need
to control which module you wish to load.
To compile this driver as a module, choose M here: the module will
be called rtl8xxxu. If unsure, say N.
config RTL8XXXU_UNTESTED
bool "Include support for untested Realtek 8xxx USB devices (EXPERIMENTAL)"
depends on RTL8XXXU
help
This option enables detection of Realtek 8723/8188/8191/8192 WiFi
USB devices which have not been tested directly by the driver
author or reported to be working by third parties.
Please report your results!
@@ -0,0 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_RTL8XXXU) += rtl8xxxu.o
rtl8xxxu-y := core.o 8192e.o 8723b.o \
8723a.o 8192c.o 8188f.o \
8188e.o 8710b.o 8192f.o
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff