summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/realtek/rtl8xxxu/8192c.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/realtek/rtl8xxxu/8192c.c')
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/8192c.c80
1 files changed, 79 insertions, 1 deletions
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/8192c.c b/drivers/net/wireless/realtek/rtl8xxxu/8192c.c
index 73034e7e41d1..444872131c66 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/8192c.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/8192c.c
@@ -593,6 +593,84 @@ static int rtl8192cu_power_on(struct rtl8xxxu_priv *priv)
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)
{
@@ -618,7 +696,7 @@ struct rtl8xxxu_fileops rtl8192cu_fops = {
.parse_efuse = rtl8192cu_parse_efuse,
.load_firmware = rtl8192cu_load_firmware,
.power_on = rtl8192cu_power_on,
- .power_off = rtl8xxxu_power_off,
+ .power_off = rtl8192cu_power_off,
.read_efuse = rtl8xxxu_read_efuse,
.reset_8051 = rtl8xxxu_reset_8051,
.llt_init = rtl8xxxu_init_llt_table,