]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
wifi: rtw89: 8922d: add power on/off functions
authorPing-Ke Shih <pkshih@realtek.com>
Tue, 24 Mar 2026 06:20:44 +0000 (14:20 +0800)
committerPing-Ke Shih <pkshih@realtek.com>
Mon, 30 Mar 2026 02:03:57 +0000 (10:03 +0800)
The power on function is the first entry to power on hardware including
all MAC/BB/RF circuits, and then it becomes possible to do high level
operations, such as WiFi scan, connection.

If connection becomes unavailable, device stays into idle mode, calling
power off function to cut power.

Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
Link: https://patch.msgid.link/20260324062049.52266-3-pkshih@realtek.com
drivers/net/wireless/realtek/rtw89/reg.h
drivers/net/wireless/realtek/rtw89/rtw8922d.c

index 2cb35458a8222ddcfa0898dad9f2ef00dbd06f9e..b6fd7b434de97b96fafb958a51b41fc787ea28a6 100644 (file)
 #define B_BE_FS_GPIO17_INT_EN BIT(1)
 #define B_BE_FS_GPIO16_INT_EN BIT(0)
 
+#define R_BE_FWS1ISR 0x019C
+#define B_BE_FS_WL_HW_RADIO_OFF_INT BIT(28)
+#define B_BE_SWRD_BOD_INT BIT(27)
+#define B_BE_HCIDBG_INT BIT(25)
+#define B_BE_FS_RPWM_INT_V1 BIT(24)
+#define B_BE_PCIE_HOTRST BIT(22)
+#define B_BE_PCIE_SER_TIMEOUT_INDIC BIT(21)
+#define B_BE_PCIE_RXI300_SLVTOUT_INDIC BIT(20)
+#define B_BE_AON_PCIE_FLR_INT BIT(19)
+#define B_BE_PCIE_ERR_INDIC BIT(18)
+#define B_BE_SDIO_ERR_INDIC BIT(17)
+#define B_BE_USB_ERR_INDIC BIT(16)
+#define B_BE_FS_GPIO27_INT BIT(11)
+#define B_BE_FS_GPIO26_INT BIT(10)
+#define B_BE_FS_GPIO25_INT BIT(9)
+#define B_BE_FS_GPIO24_INT BIT(8)
+#define B_BE_FS_GPIO23_INT BIT(7)
+#define B_BE_FS_GPIO22_INT BIT(6)
+#define B_BE_FS_GPIO21_INT BIT(5)
+#define B_BE_FS_GPIO20_INT BIT(4)
+#define B_BE_FS_GPIO19_INT BIT(3)
+#define B_BE_FS_GPIO18_INT BIT(2)
+#define B_BE_FS_GPIO17_INT BIT(1)
+#define B_BE_FS_GPIO16_INT BIT(0)
+
 #define R_BE_HIMR0 0x01A0
 #define B_BE_WDT_DATACPU_TIMEOUT_INT_EN BIT(25)
 #define B_BE_HALT_D2H_INT_EN BIT(24)
 #define R_BE_UDM2 0x01F8
 #define B_BE_UDM2_EPC_RA_MASK GENMASK(31, 0)
 
+#define R_BE_SPS_DIG_ON_CTRL1 0x0204
+#define B_BE_SN_N_L_MASK GENMASK(31, 28)
+#define B_BE_SP_N_L_MASK GENMASK(27, 24)
+#define B_BE_SN_P_L_MASK GENMASK(23, 20)
+#define B_BE_SP_P_L_MASK GENMASK(19, 16)
+#define B_BE_VO_DISCHG_PWM_H BIT(15)
+#define B_BE_REG_MODE_PREDRIVER BIT(14)
+#define B_BE_VREFOCP_MASK GENMASK(13, 10)
+#define B_BE_POWOCP_L1 BIT(9)
+#define B_BE_PWM_FORCE BIT(8)
+#define B_BE_PFM_PD_RST BIT(7)
+#define B_BE_VC_PFM_RSTB BIT(6)
+#define B_BE_PFM_IN_SEL BIT(5)
+#define B_BE_VC_RSTB BIT(4)
+#define B_BE_FPWMDELAY BIT(3)
+#define B_BE_ENFPWMDELAY_H BIT(2)
+#define B_BE_REG_MOS_HALF_L BIT(1)
+#define B_BE_CURRENT_SENSE_MOS BIT(0)
+
+#define R_BE_SPS_ANA_ON_CTRL1 0x0224
+#define B_BE_SN_N_L_ANA_MASK GENMASK(31, 28)
+#define B_BE_SP_N_L_ANA_MASK GENMASK(27, 24)
+#define B_BE_SN_P_L_ANA_MASK GENMASK(23, 20)
+#define B_BE_SP_P_L_ANA_MASK GENMASK(19, 16)
+#define B_BE_VO_DISCHG_PWM_H_ANA BIT(15)
+#define B_BE_REG_MODE_PREDRIVER_ANA BIT(14)
+#define B_BE_VREFOCP_ANA_MASK GENMASK(13, 10)
+#define B_BE_POWOCP_L1_ANA BIT(9)
+#define B_BE_PWM_FORCE_ANA BIT(8)
+#define B_BE_PFM_PD_RST_ANA BIT(7)
+#define B_BE_VC_PFM_RSTB_ANA BIT(6)
+#define B_BE_PFM_IN_SEL_ANA BIT(5)
+#define B_BE_VC_RSTB_ANA BIT(4)
+#define B_BE_FPWMDELAY_ANA BIT(3)
+#define B_BE_ENFPWMDELAY_H_ANA BIT(2)
+#define B_BE_REG_MOS_HALF_L_ANA BIT(1)
+#define B_BE_CURRENT_SENSE_MOS_ANA BIT(0)
+
 #define R_BE_AFE_ON_CTRL0 0x0240
 #define B_BE_REG_LPF_R3_3_0_MASK GENMASK(31, 29)
 #define B_BE_REG_LPF_R2_MASK GENMASK(28, 24)
index 6a90ded1b33edf4d1472d4872524e026a5ff86f9..194e2901232b01eb17ebebcd4475b58c602c8f41 100644 (file)
@@ -231,6 +231,243 @@ static const struct rtw89_efuse_block_cfg rtw8922d_efuse_blocks[] = {
        [RTW89_EFUSE_BLOCK_ADIE]                = {.offset = 0x70000, .size = 0x10},
 };
 
+static int rtw8922d_pwr_on_func(struct rtw89_dev *rtwdev)
+{
+       struct rtw89_hal *hal = &rtwdev->hal;
+       u32 val32;
+       int ret;
+
+       if (hal->cid != RTL8922D_CID7025)
+               goto begin;
+
+       switch (hal->cv) {
+       case CHIP_CAV:
+       case CHIP_CBV:
+               rtw89_write32_set(rtwdev, R_BE_SPS_DIG_ON_CTRL1, B_BE_PWM_FORCE);
+               rtw89_write32_set(rtwdev, R_BE_SPS_ANA_ON_CTRL1, B_BE_PWM_FORCE_ANA);
+               break;
+       default:
+               break;
+       }
+
+begin:
+       rtw89_write32_clr(rtwdev, R_BE_SYS_PW_CTRL, B_BE_AFSM_WLSUS_EN |
+                                                   B_BE_AFSM_PCIE_SUS_EN);
+       rtw89_write32_set(rtwdev, R_BE_SYS_PW_CTRL, B_BE_DIS_WLBT_PDNSUSEN_SOPC);
+       rtw89_write32_set(rtwdev, R_BE_WLLPS_CTRL, B_BE_DIS_WLBT_LPSEN_LOPC);
+       if (hal->cid != RTL8922D_CID7090)
+               rtw89_write32_clr(rtwdev, R_BE_SYS_PW_CTRL, B_BE_APDM_HPDN);
+       rtw89_write32_clr(rtwdev, R_BE_FWS1ISR, B_BE_FS_WL_HW_RADIO_OFF_INT);
+       rtw89_write32_clr(rtwdev, R_BE_SYS_PW_CTRL, B_BE_APFM_SWLPS);
+
+       ret = read_poll_timeout(rtw89_read32, val32, val32 & B_BE_RDY_SYSPWR,
+                               1000, 3000000, false, rtwdev, R_BE_SYS_PW_CTRL);
+       if (ret)
+               return ret;
+
+       rtw89_write32_set(rtwdev, R_BE_SYS_PW_CTRL, B_BE_EN_WLON);
+       rtw89_write32_set(rtwdev, R_BE_WLRESUME_CTRL, B_BE_LPSROP_CMAC0 |
+                                                     B_BE_LPSROP_CMAC1);
+       rtw89_write32_set(rtwdev, R_BE_SYS_PW_CTRL, B_BE_APFN_ONMAC);
+
+       ret = read_poll_timeout(rtw89_read32, val32, !(val32 & B_BE_APFN_ONMAC),
+                               1000, 3000000, false, rtwdev, R_BE_SYS_PW_CTRL);
+       if (ret)
+               return ret;
+
+       rtw89_write8_set(rtwdev, R_BE_PLATFORM_ENABLE, B_BE_PLATFORM_EN);
+       rtw89_write32_set(rtwdev, R_BE_HCI_OPT_CTRL, B_BE_HAXIDMA_IO_EN);
+
+       ret = read_poll_timeout(rtw89_read32, val32, val32 & B_BE_HAXIDMA_IO_ST,
+                               1000, 3000000, false, rtwdev, R_BE_HCI_OPT_CTRL);
+       if (ret)
+               return ret;
+
+       ret = read_poll_timeout(rtw89_read32, val32, !(val32 & B_BE_HAXIDMA_BACKUP_RESTORE_ST),
+                               1000, 3000000, false, rtwdev, R_BE_HCI_OPT_CTRL);
+       if (ret)
+               return ret;
+
+       rtw89_write32_set(rtwdev, R_BE_HCI_OPT_CTRL, B_BE_HCI_WLAN_IO_EN);
+
+       ret = read_poll_timeout(rtw89_read32, val32, val32 & B_BE_HCI_WLAN_IO_ST,
+                               1000, 3000000, false, rtwdev, R_BE_HCI_OPT_CTRL);
+       if (ret)
+               return ret;
+
+       rtw89_write32_clr(rtwdev, R_BE_SYS_SDIO_CTRL, B_BE_PCIE_FORCE_IBX_EN);
+
+       ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_NORMAL_WRITE, 0x10, 0x10);
+       if (ret)
+               return ret;
+
+       rtw89_write32_set(rtwdev, R_BE_SYS_ADIE_PAD_PWR_CTRL, B_BE_SYM_PADPDN_WL_RFC1_1P3);
+
+       ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, 0x40, 0x40);
+       if (ret)
+               return ret;
+
+       rtw89_write32_set(rtwdev, R_BE_SYS_ADIE_PAD_PWR_CTRL, B_BE_SYM_PADPDN_WL_RFC0_1P3);
+
+       ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, 0x20, 0x20);
+       if (ret)
+               return ret;
+       ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, 0x04, 0x04);
+       if (ret)
+               return ret;
+       ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, 0x08, 0x08);
+       if (ret)
+               return ret;
+       ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, 0, 0x10);
+       if (ret)
+               return ret;
+       ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_WL_RFC_S0, 0xEB, 0xFF);
+       if (ret)
+               return ret;
+       ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_WL_RFC_S1, 0xEB, 0xFF);
+       if (ret)
+               return ret;
+       ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, 0x01, 0x01);
+       if (ret)
+               return ret;
+       ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, 0x02, 0x02);
+       if (ret)
+               return ret;
+       ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, 0, 0x80);
+       if (ret)
+               return ret;
+       ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_XTAL_XMD_2, 0, 0x70);
+       if (ret)
+               return ret;
+       ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_SRAM_CTRL, 0, 0x02);
+       if (ret)
+               return ret;
+
+       rtw89_write32_set(rtwdev, R_BE_PMC_DBG_CTRL2, B_BE_SYSON_DIS_PMCR_BE_WRMSK);
+       rtw89_write32_set(rtwdev, R_BE_SYS_ISO_CTRL, B_BE_ISO_EB2CORE);
+       rtw89_write32_clr(rtwdev, R_BE_SYS_ISO_CTRL, B_BE_PWC_EV2EF_B);
+
+       mdelay(1);
+
+       rtw89_write32_clr(rtwdev, R_BE_SYS_ISO_CTRL, B_BE_PWC_EV2EF_S);
+       rtw89_write32_clr(rtwdev, R_BE_PMC_DBG_CTRL2, B_BE_SYSON_DIS_PMCR_BE_WRMSK);
+
+       rtw89_write32_set(rtwdev, R_BE_DMAC_FUNC_EN,
+                         B_BE_MAC_FUNC_EN | B_BE_DMAC_FUNC_EN |
+                         B_BE_MPDU_PROC_EN | B_BE_WD_RLS_EN |
+                         B_BE_DLE_WDE_EN | B_BE_TXPKT_CTRL_EN |
+                         B_BE_STA_SCH_EN | B_BE_DLE_PLE_EN |
+                         B_BE_PKT_BUF_EN | B_BE_DMAC_TBL_EN |
+                         B_BE_PKT_IN_EN | B_BE_DLE_CPUIO_EN |
+                         B_BE_DISPATCHER_EN | B_BE_BBRPT_EN |
+                         B_BE_MAC_SEC_EN | B_BE_H_AXIDMA_EN |
+                         B_BE_DMAC_MLO_EN | B_BE_PLRLS_EN |
+                         B_BE_P_AXIDMA_EN | B_BE_DLE_DATACPUIO_EN |
+                         B_BE_LTR_CTL_EN);
+
+       set_bit(RTW89_FLAG_DMAC_FUNC, rtwdev->flags);
+
+       rtw89_write32_set(rtwdev, R_BE_CMAC_SHARE_FUNC_EN,
+                         B_BE_CMAC_SHARE_EN | B_BE_RESPBA_EN |
+                         B_BE_ADDRSRCH_EN | B_BE_BTCOEX_EN);
+
+       rtw89_write32_set(rtwdev, R_BE_CMAC_FUNC_EN,
+                         B_BE_CMAC_EN | B_BE_CMAC_TXEN |
+                         B_BE_CMAC_RXEN | B_BE_SIGB_EN |
+                         B_BE_PHYINTF_EN | B_BE_CMAC_DMA_EN |
+                         B_BE_PTCLTOP_EN | B_BE_SCHEDULER_EN |
+                         B_BE_TMAC_EN | B_BE_RMAC_EN |
+                         B_BE_TXTIME_EN | B_BE_RESP_PKTCTL_EN);
+
+       set_bit(RTW89_FLAG_CMAC0_FUNC, rtwdev->flags);
+
+       rtw89_write32_set(rtwdev, R_BE_FEN_RST_ENABLE,
+                         B_BE_FEN_BB_IP_RSTN | B_BE_FEN_BBPLAT_RSTB);
+
+       return 0;
+}
+
+static int rtw8922d_pwr_off_func(struct rtw89_dev *rtwdev)
+{
+       u32 val32;
+       int ret;
+
+       ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, 0x10, 0x10);
+       if (ret)
+               return ret;
+       ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, 0, 0x08);
+       if (ret)
+               return ret;
+       ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, 0, 0x04);
+       if (ret)
+               return ret;
+       ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_WL_RFC_S0, 0, 0x01);
+       if (ret)
+               return ret;
+       ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_WL_RFC_S1, 0, 0x01);
+       if (ret)
+               return ret;
+       ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, 0x80, 0x80);
+       if (ret)
+               return ret;
+       ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, 0, 0x02);
+       if (ret)
+               return ret;
+       ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, 0, 0x01);
+       if (ret)
+               return ret;
+
+       rtw89_write32_set(rtwdev, R_BE_SYS_PW_CTRL, B_BE_EN_WLON);
+       rtw89_write8_clr(rtwdev, R_BE_FEN_RST_ENABLE, B_BE_FEN_BB_IP_RSTN |
+                                                     B_BE_FEN_BBPLAT_RSTB);
+       rtw89_write32_clr(rtwdev, R_BE_SYS_ADIE_PAD_PWR_CTRL,
+                         B_BE_SYM_PADPDN_WL_RFC0_1P3);
+
+       ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, 0, 0x20);
+       if (ret)
+               return ret;
+
+       rtw89_write32_clr(rtwdev, R_BE_SYS_ADIE_PAD_PWR_CTRL,
+                         B_BE_SYM_PADPDN_WL_RFC1_1P3);
+
+       ret = rtw89_mac_write_xtal_si(rtwdev, XTAL_SI_ANAPAR_WL, 0, 0x40);
+       if (ret)
+               return ret;
+
+       rtw89_write32_clr(rtwdev, R_BE_HCI_OPT_CTRL, B_BE_HAXIDMA_IO_EN);
+
+       ret = read_poll_timeout(rtw89_read32, val32, !(val32 & B_BE_HAXIDMA_IO_ST),
+                               1000, 3000000, false, rtwdev, R_BE_HCI_OPT_CTRL);
+       if (ret)
+               return ret;
+       ret = read_poll_timeout(rtw89_read32, val32,
+                               !(val32 & B_BE_HAXIDMA_BACKUP_RESTORE_ST),
+                               1000, 3000000, false, rtwdev, R_BE_HCI_OPT_CTRL);
+       if (ret)
+               return ret;
+
+       rtw89_write32_clr(rtwdev, R_BE_HCI_OPT_CTRL, B_BE_HCI_WLAN_IO_EN);
+
+       ret = read_poll_timeout(rtw89_read32, val32, !(val32 & B_BE_HCI_WLAN_IO_ST),
+                               1000, 3000000, false, rtwdev, R_BE_HCI_OPT_CTRL);
+       if (ret)
+               return ret;
+
+       rtw89_write32_set(rtwdev, R_BE_SYS_PW_CTRL, B_BE_APFM_OFFMAC);
+
+       ret = read_poll_timeout(rtw89_read32, val32, !(val32 & B_BE_APFM_OFFMAC),
+                               1000, 3000000, false, rtwdev, R_BE_SYS_PW_CTRL);
+       if (ret)
+               return ret;
+
+       rtw89_write32(rtwdev, R_BE_WLLPS_CTRL, 0x00015002);
+       rtw89_write32_clr(rtwdev, R_BE_SYS_PW_CTRL, B_BE_XTAL_OFF_A_DIE);
+       rtw89_write32_set(rtwdev, R_BE_SYS_PW_CTRL, B_BE_APFM_SWLPS);
+       rtw89_write32(rtwdev, R_BE_UDM1, 0);
+
+       return 0;
+}
+
 MODULE_FIRMWARE(RTW8922D_MODULE_FIRMWARE);
 MODULE_FIRMWARE(RTW8922DS_MODULE_FIRMWARE);
 MODULE_AUTHOR("Realtek Corporation");