linux/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192c.c
<<
>>
Prefs
   1/*
   2 * RTL8XXXU mac80211 USB driver - 8188c/8188r/8192c specific subdriver
   3 *
   4 * Copyright (c) 2014 - 2016 Jes Sorensen <Jes.Sorensen@redhat.com>
   5 *
   6 * Portions, notably calibration code:
   7 * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
   8 *
   9 * This driver was written as a replacement for the vendor provided
  10 * rtl8723au driver. As the Realtek 8xxx chips are very similar in
  11 * their programming interface, I have started adding support for
  12 * additional 8xxx chips like the 8192cu, 8188cus, etc.
  13 *
  14 * This program is free software; you can redistribute it and/or modify it
  15 * under the terms of version 2 of the GNU General Public License as
  16 * published by the Free Software Foundation.
  17 *
  18 * This program is distributed in the hope that it will be useful, but WITHOUT
  19 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  20 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  21 * more details.
  22 */
  23
  24#include <linux/init.h>
  25#include <linux/kernel.h>
  26#include <linux/sched.h>
  27#include <linux/errno.h>
  28#include <linux/slab.h>
  29#include <linux/module.h>
  30#include <linux/spinlock.h>
  31#include <linux/list.h>
  32#include <linux/usb.h>
  33#include <linux/netdevice.h>
  34#include <linux/etherdevice.h>
  35#include <linux/ethtool.h>
  36#include <linux/wireless.h>
  37#include <linux/firmware.h>
  38#include <linux/moduleparam.h>
  39#include <net/mac80211.h>
  40#include "rtl8xxxu.h"
  41#include "rtl8xxxu_regs.h"
  42
  43#ifdef CONFIG_RTL8XXXU_UNTESTED
  44static struct rtl8xxxu_power_base rtl8192c_power_base = {
  45        .reg_0e00 = 0x07090c0c,
  46        .reg_0e04 = 0x01020405,
  47        .reg_0e08 = 0x00000000,
  48        .reg_086c = 0x00000000,
  49
  50        .reg_0e10 = 0x0b0c0c0e,
  51        .reg_0e14 = 0x01030506,
  52        .reg_0e18 = 0x0b0c0d0e,
  53        .reg_0e1c = 0x01030509,
  54
  55        .reg_0830 = 0x07090c0c,
  56        .reg_0834 = 0x01020405,
  57        .reg_0838 = 0x00000000,
  58        .reg_086c_2 = 0x00000000,
  59
  60        .reg_083c = 0x0b0c0d0e,
  61        .reg_0848 = 0x01030509,
  62        .reg_084c = 0x0b0c0d0e,
  63        .reg_0868 = 0x01030509,
  64};
  65
  66static struct rtl8xxxu_power_base rtl8188r_power_base = {
  67        .reg_0e00 = 0x06080808,
  68        .reg_0e04 = 0x00040406,
  69        .reg_0e08 = 0x00000000,
  70        .reg_086c = 0x00000000,
  71
  72        .reg_0e10 = 0x04060608,
  73        .reg_0e14 = 0x00020204,
  74        .reg_0e18 = 0x04060608,
  75        .reg_0e1c = 0x00020204,
  76
  77        .reg_0830 = 0x06080808,
  78        .reg_0834 = 0x00040406,
  79        .reg_0838 = 0x00000000,
  80        .reg_086c_2 = 0x00000000,
  81
  82        .reg_083c = 0x04060608,
  83        .reg_0848 = 0x00020204,
  84        .reg_084c = 0x04060608,
  85        .reg_0868 = 0x00020204,
  86};
  87
  88static struct rtl8xxxu_rfregval rtl8192cu_radioa_2t_init_table[] = {
  89        {0x00, 0x00030159}, {0x01, 0x00031284},
  90        {0x02, 0x00098000}, {0x03, 0x00018c63},
  91        {0x04, 0x000210e7}, {0x09, 0x0002044f},
  92        {0x0a, 0x0001adb1}, {0x0b, 0x00054867},
  93        {0x0c, 0x0008992e}, {0x0d, 0x0000e52c},
  94        {0x0e, 0x00039ce7}, {0x0f, 0x00000451},
  95        {0x19, 0x00000000}, {0x1a, 0x00010255},
  96        {0x1b, 0x00060a00}, {0x1c, 0x000fc378},
  97        {0x1d, 0x000a1250}, {0x1e, 0x0004445f},
  98        {0x1f, 0x00080001}, {0x20, 0x0000b614},
  99        {0x21, 0x0006c000}, {0x22, 0x00000000},
 100        {0x23, 0x00001558}, {0x24, 0x00000060},
 101        {0x25, 0x00000483}, {0x26, 0x0004f000},
 102        {0x27, 0x000ec7d9}, {0x28, 0x000577c0},
 103        {0x29, 0x00004783}, {0x2a, 0x00000001},
 104        {0x2b, 0x00021334}, {0x2a, 0x00000000},
 105        {0x2b, 0x00000054}, {0x2a, 0x00000001},
 106        {0x2b, 0x00000808}, {0x2b, 0x00053333},
 107        {0x2c, 0x0000000c}, {0x2a, 0x00000002},
 108        {0x2b, 0x00000808}, {0x2b, 0x0005b333},
 109        {0x2c, 0x0000000d}, {0x2a, 0x00000003},
 110        {0x2b, 0x00000808}, {0x2b, 0x00063333},
 111        {0x2c, 0x0000000d}, {0x2a, 0x00000004},
 112        {0x2b, 0x00000808}, {0x2b, 0x0006b333},
 113        {0x2c, 0x0000000d}, {0x2a, 0x00000005},
 114        {0x2b, 0x00000808}, {0x2b, 0x00073333},
 115        {0x2c, 0x0000000d}, {0x2a, 0x00000006},
 116        {0x2b, 0x00000709}, {0x2b, 0x0005b333},
 117        {0x2c, 0x0000000d}, {0x2a, 0x00000007},
 118        {0x2b, 0x00000709}, {0x2b, 0x00063333},
 119        {0x2c, 0x0000000d}, {0x2a, 0x00000008},
 120        {0x2b, 0x0000060a}, {0x2b, 0x0004b333},
 121        {0x2c, 0x0000000d}, {0x2a, 0x00000009},
 122        {0x2b, 0x0000060a}, {0x2b, 0x00053333},
 123        {0x2c, 0x0000000d}, {0x2a, 0x0000000a},
 124        {0x2b, 0x0000060a}, {0x2b, 0x0005b333},
 125        {0x2c, 0x0000000d}, {0x2a, 0x0000000b},
 126        {0x2b, 0x0000060a}, {0x2b, 0x00063333},
 127        {0x2c, 0x0000000d}, {0x2a, 0x0000000c},
 128        {0x2b, 0x0000060a}, {0x2b, 0x0006b333},
 129        {0x2c, 0x0000000d}, {0x2a, 0x0000000d},
 130        {0x2b, 0x0000060a}, {0x2b, 0x00073333},
 131        {0x2c, 0x0000000d}, {0x2a, 0x0000000e},
 132        {0x2b, 0x0000050b}, {0x2b, 0x00066666},
 133        {0x2c, 0x0000001a}, {0x2a, 0x000e0000},
 134        {0x10, 0x0004000f}, {0x11, 0x000e31fc},
 135        {0x10, 0x0006000f}, {0x11, 0x000ff9f8},
 136        {0x10, 0x0002000f}, {0x11, 0x000203f9},
 137        {0x10, 0x0003000f}, {0x11, 0x000ff500},
 138        {0x10, 0x00000000}, {0x11, 0x00000000},
 139        {0x10, 0x0008000f}, {0x11, 0x0003f100},
 140        {0x10, 0x0009000f}, {0x11, 0x00023100},
 141        {0x12, 0x00032000}, {0x12, 0x00071000},
 142        {0x12, 0x000b0000}, {0x12, 0x000fc000},
 143        {0x13, 0x000287b3}, {0x13, 0x000244b7},
 144        {0x13, 0x000204ab}, {0x13, 0x0001c49f},
 145        {0x13, 0x00018493}, {0x13, 0x0001429b},
 146        {0x13, 0x00010299}, {0x13, 0x0000c29c},
 147        {0x13, 0x000081a0}, {0x13, 0x000040ac},
 148        {0x13, 0x00000020}, {0x14, 0x0001944c},
 149        {0x14, 0x00059444}, {0x14, 0x0009944c},
 150        {0x14, 0x000d9444}, {0x15, 0x0000f424},
 151        {0x15, 0x0004f424}, {0x15, 0x0008f424},
 152        {0x15, 0x000cf424}, {0x16, 0x000e0330},
 153        {0x16, 0x000a0330}, {0x16, 0x00060330},
 154        {0x16, 0x00020330}, {0x00, 0x00010159},
 155        {0x18, 0x0000f401}, {0xfe, 0x00000000},
 156        {0xfe, 0x00000000}, {0x1f, 0x00080003},
 157        {0xfe, 0x00000000}, {0xfe, 0x00000000},
 158        {0x1e, 0x00044457}, {0x1f, 0x00080000},
 159        {0x00, 0x00030159},
 160        {0xff, 0xffffffff}
 161};
 162
 163static struct rtl8xxxu_rfregval rtl8192cu_radiob_2t_init_table[] = {
 164        {0x00, 0x00030159}, {0x01, 0x00031284},
 165        {0x02, 0x00098000}, {0x03, 0x00018c63},
 166        {0x04, 0x000210e7}, {0x09, 0x0002044f},
 167        {0x0a, 0x0001adb1}, {0x0b, 0x00054867},
 168        {0x0c, 0x0008992e}, {0x0d, 0x0000e52c},
 169        {0x0e, 0x00039ce7}, {0x0f, 0x00000451},
 170        {0x12, 0x00032000}, {0x12, 0x00071000},
 171        {0x12, 0x000b0000}, {0x12, 0x000fc000},
 172        {0x13, 0x000287af}, {0x13, 0x000244b7},
 173        {0x13, 0x000204ab}, {0x13, 0x0001c49f},
 174        {0x13, 0x00018493}, {0x13, 0x00014297},
 175        {0x13, 0x00010295}, {0x13, 0x0000c298},
 176        {0x13, 0x0000819c}, {0x13, 0x000040a8},
 177        {0x13, 0x0000001c}, {0x14, 0x0001944c},
 178        {0x14, 0x00059444}, {0x14, 0x0009944c},
 179        {0x14, 0x000d9444}, {0x15, 0x0000f424},
 180        {0x15, 0x0004f424}, {0x15, 0x0008f424},
 181        {0x15, 0x000cf424}, {0x16, 0x000e0330},
 182        {0x16, 0x000a0330}, {0x16, 0x00060330},
 183        {0x16, 0x00020330},
 184        {0xff, 0xffffffff}
 185};
 186
 187static struct rtl8xxxu_rfregval rtl8192cu_radioa_1t_init_table[] = {
 188        {0x00, 0x00030159}, {0x01, 0x00031284},
 189        {0x02, 0x00098000}, {0x03, 0x00018c63},
 190        {0x04, 0x000210e7}, {0x09, 0x0002044f},
 191        {0x0a, 0x0001adb1}, {0x0b, 0x00054867},
 192        {0x0c, 0x0008992e}, {0x0d, 0x0000e52c},
 193        {0x0e, 0x00039ce7}, {0x0f, 0x00000451},
 194        {0x19, 0x00000000}, {0x1a, 0x00010255},
 195        {0x1b, 0x00060a00}, {0x1c, 0x000fc378},
 196        {0x1d, 0x000a1250}, {0x1e, 0x0004445f},
 197        {0x1f, 0x00080001}, {0x20, 0x0000b614},
 198        {0x21, 0x0006c000}, {0x22, 0x00000000},
 199        {0x23, 0x00001558}, {0x24, 0x00000060},
 200        {0x25, 0x00000483}, {0x26, 0x0004f000},
 201        {0x27, 0x000ec7d9}, {0x28, 0x000577c0},
 202        {0x29, 0x00004783}, {0x2a, 0x00000001},
 203        {0x2b, 0x00021334}, {0x2a, 0x00000000},
 204        {0x2b, 0x00000054}, {0x2a, 0x00000001},
 205        {0x2b, 0x00000808}, {0x2b, 0x00053333},
 206        {0x2c, 0x0000000c}, {0x2a, 0x00000002},
 207        {0x2b, 0x00000808}, {0x2b, 0x0005b333},
 208        {0x2c, 0x0000000d}, {0x2a, 0x00000003},
 209        {0x2b, 0x00000808}, {0x2b, 0x00063333},
 210        {0x2c, 0x0000000d}, {0x2a, 0x00000004},
 211        {0x2b, 0x00000808}, {0x2b, 0x0006b333},
 212        {0x2c, 0x0000000d}, {0x2a, 0x00000005},
 213        {0x2b, 0x00000808}, {0x2b, 0x00073333},
 214        {0x2c, 0x0000000d}, {0x2a, 0x00000006},
 215        {0x2b, 0x00000709}, {0x2b, 0x0005b333},
 216        {0x2c, 0x0000000d}, {0x2a, 0x00000007},
 217        {0x2b, 0x00000709}, {0x2b, 0x00063333},
 218        {0x2c, 0x0000000d}, {0x2a, 0x00000008},
 219        {0x2b, 0x0000060a}, {0x2b, 0x0004b333},
 220        {0x2c, 0x0000000d}, {0x2a, 0x00000009},
 221        {0x2b, 0x0000060a}, {0x2b, 0x00053333},
 222        {0x2c, 0x0000000d}, {0x2a, 0x0000000a},
 223        {0x2b, 0x0000060a}, {0x2b, 0x0005b333},
 224        {0x2c, 0x0000000d}, {0x2a, 0x0000000b},
 225        {0x2b, 0x0000060a}, {0x2b, 0x00063333},
 226        {0x2c, 0x0000000d}, {0x2a, 0x0000000c},
 227        {0x2b, 0x0000060a}, {0x2b, 0x0006b333},
 228        {0x2c, 0x0000000d}, {0x2a, 0x0000000d},
 229        {0x2b, 0x0000060a}, {0x2b, 0x00073333},
 230        {0x2c, 0x0000000d}, {0x2a, 0x0000000e},
 231        {0x2b, 0x0000050b}, {0x2b, 0x00066666},
 232        {0x2c, 0x0000001a}, {0x2a, 0x000e0000},
 233        {0x10, 0x0004000f}, {0x11, 0x000e31fc},
 234        {0x10, 0x0006000f}, {0x11, 0x000ff9f8},
 235        {0x10, 0x0002000f}, {0x11, 0x000203f9},
 236        {0x10, 0x0003000f}, {0x11, 0x000ff500},
 237        {0x10, 0x00000000}, {0x11, 0x00000000},
 238        {0x10, 0x0008000f}, {0x11, 0x0003f100},
 239        {0x10, 0x0009000f}, {0x11, 0x00023100},
 240        {0x12, 0x00032000}, {0x12, 0x00071000},
 241        {0x12, 0x000b0000}, {0x12, 0x000fc000},
 242        {0x13, 0x000287b3}, {0x13, 0x000244b7},
 243        {0x13, 0x000204ab}, {0x13, 0x0001c49f},
 244        {0x13, 0x00018493}, {0x13, 0x0001429b},
 245        {0x13, 0x00010299}, {0x13, 0x0000c29c},
 246        {0x13, 0x000081a0}, {0x13, 0x000040ac},
 247        {0x13, 0x00000020}, {0x14, 0x0001944c},
 248        {0x14, 0x00059444}, {0x14, 0x0009944c},
 249        {0x14, 0x000d9444}, {0x15, 0x0000f405},
 250        {0x15, 0x0004f405}, {0x15, 0x0008f405},
 251        {0x15, 0x000cf405}, {0x16, 0x000e0330},
 252        {0x16, 0x000a0330}, {0x16, 0x00060330},
 253        {0x16, 0x00020330}, {0x00, 0x00010159},
 254        {0x18, 0x0000f401}, {0xfe, 0x00000000},
 255        {0xfe, 0x00000000}, {0x1f, 0x00080003},
 256        {0xfe, 0x00000000}, {0xfe, 0x00000000},
 257        {0x1e, 0x00044457}, {0x1f, 0x00080000},
 258        {0x00, 0x00030159},
 259        {0xff, 0xffffffff}
 260};
 261
 262static struct rtl8xxxu_rfregval rtl8188ru_radioa_1t_highpa_table[] = {
 263        {0x00, 0x00030159}, {0x01, 0x00031284},
 264        {0x02, 0x00098000}, {0x03, 0x00018c63},
 265        {0x04, 0x000210e7}, {0x09, 0x0002044f},
 266        {0x0a, 0x0001adb0}, {0x0b, 0x00054867},
 267        {0x0c, 0x0008992e}, {0x0d, 0x0000e529},
 268        {0x0e, 0x00039ce7}, {0x0f, 0x00000451},
 269        {0x19, 0x00000000}, {0x1a, 0x00000255},
 270        {0x1b, 0x00060a00}, {0x1c, 0x000fc378},
 271        {0x1d, 0x000a1250}, {0x1e, 0x0004445f},
 272        {0x1f, 0x00080001}, {0x20, 0x0000b614},
 273        {0x21, 0x0006c000}, {0x22, 0x0000083c},
 274        {0x23, 0x00001558}, {0x24, 0x00000060},
 275        {0x25, 0x00000483}, {0x26, 0x0004f000},
 276        {0x27, 0x000ec7d9}, {0x28, 0x000977c0},
 277        {0x29, 0x00004783}, {0x2a, 0x00000001},
 278        {0x2b, 0x00021334}, {0x2a, 0x00000000},
 279        {0x2b, 0x00000054}, {0x2a, 0x00000001},
 280        {0x2b, 0x00000808}, {0x2b, 0x00053333},
 281        {0x2c, 0x0000000c}, {0x2a, 0x00000002},
 282        {0x2b, 0x00000808}, {0x2b, 0x0005b333},
 283        {0x2c, 0x0000000d}, {0x2a, 0x00000003},
 284        {0x2b, 0x00000808}, {0x2b, 0x00063333},
 285        {0x2c, 0x0000000d}, {0x2a, 0x00000004},
 286        {0x2b, 0x00000808}, {0x2b, 0x0006b333},
 287        {0x2c, 0x0000000d}, {0x2a, 0x00000005},
 288        {0x2b, 0x00000808}, {0x2b, 0x00073333},
 289        {0x2c, 0x0000000d}, {0x2a, 0x00000006},
 290        {0x2b, 0x00000709}, {0x2b, 0x0005b333},
 291        {0x2c, 0x0000000d}, {0x2a, 0x00000007},
 292        {0x2b, 0x00000709}, {0x2b, 0x00063333},
 293        {0x2c, 0x0000000d}, {0x2a, 0x00000008},
 294        {0x2b, 0x0000060a}, {0x2b, 0x0004b333},
 295        {0x2c, 0x0000000d}, {0x2a, 0x00000009},
 296        {0x2b, 0x0000060a}, {0x2b, 0x00053333},
 297        {0x2c, 0x0000000d}, {0x2a, 0x0000000a},
 298        {0x2b, 0x0000060a}, {0x2b, 0x0005b333},
 299        {0x2c, 0x0000000d}, {0x2a, 0x0000000b},
 300        {0x2b, 0x0000060a}, {0x2b, 0x00063333},
 301        {0x2c, 0x0000000d}, {0x2a, 0x0000000c},
 302        {0x2b, 0x0000060a}, {0x2b, 0x0006b333},
 303        {0x2c, 0x0000000d}, {0x2a, 0x0000000d},
 304        {0x2b, 0x0000060a}, {0x2b, 0x00073333},
 305        {0x2c, 0x0000000d}, {0x2a, 0x0000000e},
 306        {0x2b, 0x0000050b}, {0x2b, 0x00066666},
 307        {0x2c, 0x0000001a}, {0x2a, 0x000e0000},
 308        {0x10, 0x0004000f}, {0x11, 0x000e31fc},
 309        {0x10, 0x0006000f}, {0x11, 0x000ff9f8},
 310        {0x10, 0x0002000f}, {0x11, 0x000203f9},
 311        {0x10, 0x0003000f}, {0x11, 0x000ff500},
 312        {0x10, 0x00000000}, {0x11, 0x00000000},
 313        {0x10, 0x0008000f}, {0x11, 0x0003f100},
 314        {0x10, 0x0009000f}, {0x11, 0x00023100},
 315        {0x12, 0x000d8000}, {0x12, 0x00090000},
 316        {0x12, 0x00051000}, {0x12, 0x00012000},
 317        {0x13, 0x00028fb4}, {0x13, 0x00024fa8},
 318        {0x13, 0x000207a4}, {0x13, 0x0001c3b0},
 319        {0x13, 0x000183a4}, {0x13, 0x00014398},
 320        {0x13, 0x000101a4}, {0x13, 0x0000c198},
 321        {0x13, 0x000080a4}, {0x13, 0x00004098},
 322        {0x13, 0x00000000}, {0x14, 0x0001944c},
 323        {0x14, 0x00059444}, {0x14, 0x0009944c},
 324        {0x14, 0x000d9444}, {0x15, 0x0000f405},
 325        {0x15, 0x0004f405}, {0x15, 0x0008f405},
 326        {0x15, 0x000cf405}, {0x16, 0x000e0330},
 327        {0x16, 0x000a0330}, {0x16, 0x00060330},
 328        {0x16, 0x00020330}, {0x00, 0x00010159},
 329        {0x18, 0x0000f401}, {0xfe, 0x00000000},
 330        {0xfe, 0x00000000}, {0x1f, 0x00080003},
 331        {0xfe, 0x00000000}, {0xfe, 0x00000000},
 332        {0x1e, 0x00044457}, {0x1f, 0x00080000},
 333        {0x00, 0x00030159},
 334        {0xff, 0xffffffff}
 335};
 336
 337static int rtl8192cu_load_firmware(struct rtl8xxxu_priv *priv)
 338{
 339        char *fw_name;
 340        int ret;
 341
 342        if (!priv->vendor_umc)
 343                fw_name = "rtlwifi/rtl8192cufw_TMSC.bin";
 344        else if (priv->chip_cut || priv->rtl_chip == RTL8192C)
 345                fw_name = "rtlwifi/rtl8192cufw_B.bin";
 346        else
 347                fw_name = "rtlwifi/rtl8192cufw_A.bin";
 348
 349        ret = rtl8xxxu_load_firmware(priv, fw_name);
 350
 351        return ret;
 352}
 353
 354static int rtl8192cu_parse_efuse(struct rtl8xxxu_priv *priv)
 355{
 356        struct rtl8192cu_efuse *efuse = &priv->efuse_wifi.efuse8192;
 357        int i;
 358
 359        if (efuse->rtl_id != cpu_to_le16(0x8129))
 360                return -EINVAL;
 361
 362        ether_addr_copy(priv->mac_addr, efuse->mac_addr);
 363
 364        memcpy(priv->cck_tx_power_index_A,
 365               efuse->cck_tx_power_index_A,
 366               sizeof(efuse->cck_tx_power_index_A));
 367        memcpy(priv->cck_tx_power_index_B,
 368               efuse->cck_tx_power_index_B,
 369               sizeof(efuse->cck_tx_power_index_B));
 370
 371        memcpy(priv->ht40_1s_tx_power_index_A,
 372               efuse->ht40_1s_tx_power_index_A,
 373               sizeof(efuse->ht40_1s_tx_power_index_A));
 374        memcpy(priv->ht40_1s_tx_power_index_B,
 375               efuse->ht40_1s_tx_power_index_B,
 376               sizeof(efuse->ht40_1s_tx_power_index_B));
 377        memcpy(priv->ht40_2s_tx_power_index_diff,
 378               efuse->ht40_2s_tx_power_index_diff,
 379               sizeof(efuse->ht40_2s_tx_power_index_diff));
 380
 381        memcpy(priv->ht20_tx_power_index_diff,
 382               efuse->ht20_tx_power_index_diff,
 383               sizeof(efuse->ht20_tx_power_index_diff));
 384        memcpy(priv->ofdm_tx_power_index_diff,
 385               efuse->ofdm_tx_power_index_diff,
 386               sizeof(efuse->ofdm_tx_power_index_diff));
 387
 388        memcpy(priv->ht40_max_power_offset,
 389               efuse->ht40_max_power_offset,
 390               sizeof(efuse->ht40_max_power_offset));
 391        memcpy(priv->ht20_max_power_offset,
 392               efuse->ht20_max_power_offset,
 393               sizeof(efuse->ht20_max_power_offset));
 394
 395        dev_info(&priv->udev->dev, "Vendor: %.7s\n",
 396                 efuse->vendor_name);
 397        dev_info(&priv->udev->dev, "Product: %.20s\n",
 398                 efuse->device_name);
 399
 400        priv->power_base = &rtl8192c_power_base;
 401
 402        if (efuse->rf_regulatory & 0x20) {
 403                sprintf(priv->chip_name, "8188RU");
 404                priv->rtl_chip = RTL8188R;
 405                priv->hi_pa = 1;
 406                priv->no_pape = 1;
 407                priv->power_base = &rtl8188r_power_base;
 408        }
 409
 410        if (rtl8xxxu_debug & RTL8XXXU_DEBUG_EFUSE) {
 411                unsigned char *raw = priv->efuse_wifi.raw;
 412
 413                dev_info(&priv->udev->dev,
 414                         "%s: dumping efuse (0x%02zx bytes):\n",
 415                         __func__, sizeof(struct rtl8192cu_efuse));
 416                for (i = 0; i < sizeof(struct rtl8192cu_efuse); i += 8)
 417                        dev_info(&priv->udev->dev, "%02x: %8ph\n", i, &raw[i]);
 418        }
 419        return 0;
 420}
 421
 422static int rtl8192cu_init_phy_rf(struct rtl8xxxu_priv *priv)
 423{
 424        struct rtl8xxxu_rfregval *rftable;
 425        int ret;
 426
 427        if (priv->rtl_chip == RTL8188R) {
 428                rftable = rtl8188ru_radioa_1t_highpa_table;
 429                ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_A);
 430        } else if (priv->rf_paths == 1) {
 431                rftable = rtl8192cu_radioa_1t_init_table;
 432                ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_A);
 433        } else {
 434                rftable = rtl8192cu_radioa_2t_init_table;
 435                ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_A);
 436                if (ret)
 437                        goto exit;
 438                rftable = rtl8192cu_radiob_2t_init_table;
 439                ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_B);
 440        }
 441
 442exit:
 443        return ret;
 444}
 445
 446static int rtl8192cu_power_on(struct rtl8xxxu_priv *priv)
 447{
 448        u8 val8;
 449        u16 val16;
 450        u32 val32;
 451        int i;
 452
 453        for (i = 100; i; i--) {
 454                val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO);
 455                if (val8 & APS_FSMCO_PFM_ALDN)
 456                        break;
 457        }
 458
 459        if (!i) {
 460                pr_info("%s: Poll failed\n", __func__);
 461                return -ENODEV;
 462        }
 463
 464        /*
 465         * RSV_CTRL 0x001C[7:0] = 0x00, unlock ISO/CLK/Power control register
 466         */
 467        rtl8xxxu_write8(priv, REG_RSV_CTRL, 0x0);
 468        rtl8xxxu_write8(priv, REG_SPS0_CTRL, 0x2b);
 469        udelay(100);
 470
 471        val8 = rtl8xxxu_read8(priv, REG_LDOV12D_CTRL);
 472        if (!(val8 & LDOV12D_ENABLE)) {
 473                pr_info("%s: Enabling LDOV12D (%02x)\n", __func__, val8);
 474                val8 |= LDOV12D_ENABLE;
 475                rtl8xxxu_write8(priv, REG_LDOV12D_CTRL, val8);
 476
 477                udelay(100);
 478
 479                val8 = rtl8xxxu_read8(priv, REG_SYS_ISO_CTRL);
 480                val8 &= ~SYS_ISO_MD2PP;
 481                rtl8xxxu_write8(priv, REG_SYS_ISO_CTRL, val8);
 482        }
 483
 484        /*
 485         * Auto enable WLAN
 486         */
 487        val16 = rtl8xxxu_read16(priv, REG_APS_FSMCO);
 488        val16 |= APS_FSMCO_MAC_ENABLE;
 489        rtl8xxxu_write16(priv, REG_APS_FSMCO, val16);
 490
 491        for (i = 1000; i; i--) {
 492                val16 = rtl8xxxu_read16(priv, REG_APS_FSMCO);
 493                if (!(val16 & APS_FSMCO_MAC_ENABLE))
 494                        break;
 495        }
 496        if (!i) {
 497                pr_info("%s: FSMCO_MAC_ENABLE poll failed\n", __func__);
 498                return -EBUSY;
 499        }
 500
 501        /*
 502         * Enable radio, GPIO, LED
 503         */
 504        val16 = APS_FSMCO_HW_SUSPEND | APS_FSMCO_ENABLE_POWERDOWN |
 505                APS_FSMCO_PFM_ALDN;
 506        rtl8xxxu_write16(priv, REG_APS_FSMCO, val16);
 507
 508        /*
 509         * Release RF digital isolation
 510         */
 511        val16 = rtl8xxxu_read16(priv, REG_SYS_ISO_CTRL);
 512        val16 &= ~SYS_ISO_DIOR;
 513        rtl8xxxu_write16(priv, REG_SYS_ISO_CTRL, val16);
 514
 515        val8 = rtl8xxxu_read8(priv, REG_APSD_CTRL);
 516        val8 &= ~APSD_CTRL_OFF;
 517        rtl8xxxu_write8(priv, REG_APSD_CTRL, val8);
 518        for (i = 200; i; i--) {
 519                val8 = rtl8xxxu_read8(priv, REG_APSD_CTRL);
 520                if (!(val8 & APSD_CTRL_OFF_STATUS))
 521                        break;
 522        }
 523
 524        if (!i) {
 525                pr_info("%s: APSD_CTRL poll failed\n", __func__);
 526                return -EBUSY;
 527        }
 528
 529        /*
 530         * Enable MAC DMA/WMAC/SCHEDULE/SEC block
 531         */
 532        val16 = rtl8xxxu_read16(priv, REG_CR);
 533        val16 |= CR_HCI_TXDMA_ENABLE | CR_HCI_RXDMA_ENABLE |
 534                CR_TXDMA_ENABLE | CR_RXDMA_ENABLE | CR_PROTOCOL_ENABLE |
 535                CR_SCHEDULE_ENABLE | CR_MAC_TX_ENABLE | CR_MAC_RX_ENABLE;
 536        rtl8xxxu_write16(priv, REG_CR, val16);
 537
 538        rtl8xxxu_write8(priv, 0xfe10, 0x19);
 539
 540        /*
 541         * Workaround for 8188RU LNA power leakage problem.
 542         */
 543        if (priv->rtl_chip == RTL8188R) {
 544                val32 = rtl8xxxu_read32(priv, REG_FPGA0_XCD_RF_PARM);
 545                val32 &= ~BIT(1);
 546                rtl8xxxu_write32(priv, REG_FPGA0_XCD_RF_PARM, val32);
 547        }
 548        return 0;
 549}
 550
 551struct rtl8xxxu_fileops rtl8192cu_fops = {
 552        .parse_efuse = rtl8192cu_parse_efuse,
 553        .load_firmware = rtl8192cu_load_firmware,
 554        .power_on = rtl8192cu_power_on,
 555        .power_off = rtl8xxxu_power_off,
 556        .reset_8051 = rtl8xxxu_reset_8051,
 557        .llt_init = rtl8xxxu_init_llt_table,
 558        .init_phy_bb = rtl8xxxu_gen1_init_phy_bb,
 559        .init_phy_rf = rtl8192cu_init_phy_rf,
 560        .phy_iq_calibrate = rtl8xxxu_gen1_phy_iq_calibrate,
 561        .config_channel = rtl8xxxu_gen1_config_channel,
 562        .parse_rx_desc = rtl8xxxu_parse_rxdesc16,
 563        .init_aggregation = rtl8xxxu_gen1_init_aggregation,
 564        .enable_rf = rtl8xxxu_gen1_enable_rf,
 565        .disable_rf = rtl8xxxu_gen1_disable_rf,
 566        .usb_quirks = rtl8xxxu_gen1_usb_quirks,
 567        .set_tx_power = rtl8xxxu_gen1_set_tx_power,
 568        .update_rate_mask = rtl8xxxu_update_rate_mask,
 569        .report_connect = rtl8xxxu_gen1_report_connect,
 570        .fill_txdesc = rtl8xxxu_fill_txdesc_v1,
 571        .writeN_block_size = 128,
 572        .rx_agg_buf_size = 16000,
 573        .tx_desc_size = sizeof(struct rtl8xxxu_txdesc32),
 574        .rx_desc_size = sizeof(struct rtl8xxxu_rxdesc16),
 575        .adda_1t_init = 0x0b1b25a0,
 576        .adda_1t_path_on = 0x0bdb25a0,
 577        .adda_2t_path_on_a = 0x04db25a4,
 578        .adda_2t_path_on_b = 0x0b1b25a4,
 579        .trxff_boundary = 0x27ff,
 580        .pbp_rx = PBP_PAGE_SIZE_128,
 581        .pbp_tx = PBP_PAGE_SIZE_128,
 582        .mactable = rtl8xxxu_gen1_mac_init_table,
 583        .total_page_num = TX_TOTAL_PAGE_NUM,
 584        .page_num_hi = TX_PAGE_NUM_HI_PQ,
 585        .page_num_lo = TX_PAGE_NUM_LO_PQ,
 586        .page_num_norm = TX_PAGE_NUM_NORM_PQ,
 587};
 588#endif
 589