diff options
Diffstat (limited to 'drivers/net/wireless/realtek/rtw88/mac.c')
| -rw-r--r-- | drivers/net/wireless/realtek/rtw88/mac.c | 211 |
1 files changed, 167 insertions, 44 deletions
diff --git a/drivers/net/wireless/realtek/rtw88/mac.c b/drivers/net/wireless/realtek/rtw88/mac.c index d1678aed9d9c..eaa928bab240 100644 --- a/drivers/net/wireless/realtek/rtw88/mac.c +++ b/drivers/net/wireless/realtek/rtw88/mac.c @@ -7,6 +7,7 @@ #include "reg.h" #include "fw.h" #include "debug.h" +#include "sdio.h" void rtw_set_channel_mac(struct rtw_dev *rtwdev, u8 channel, u8 bw, u8 primary_ch_idx) @@ -40,7 +41,7 @@ void rtw_set_channel_mac(struct rtw_dev *rtwdev, u8 channel, u8 bw, } rtw_write32(rtwdev, REG_WMAC_TRXPTCL_CTL, value32); - if (rtw_chip_wcpu_11n(rtwdev)) + if (rtw_chip_wcpu_8051(rtwdev)) return; value32 = rtw_read32(rtwdev, REG_AFE_CTRL1) & ~(BIT_MAC_CLK_SEL); @@ -60,12 +61,13 @@ EXPORT_SYMBOL(rtw_set_channel_mac); static int rtw_mac_pre_system_cfg(struct rtw_dev *rtwdev) { + unsigned int retry; u32 value32; u8 value8; rtw_write8(rtwdev, REG_RSV_CTRL, 0); - if (rtw_chip_wcpu_11n(rtwdev)) { + if (rtw_chip_wcpu_8051(rtwdev)) { if (rtw_read32(rtwdev, REG_SYS_CFG1) & BIT_LDO) rtw_write8(rtwdev, REG_LDO_SWR_CTRL, LDO_SEL); else @@ -75,7 +77,29 @@ static int rtw_mac_pre_system_cfg(struct rtw_dev *rtwdev) switch (rtw_hci_type(rtwdev)) { case RTW_HCI_TYPE_PCIE: - rtw_write32_set(rtwdev, REG_HCI_OPT_CTRL, BIT_BT_DIG_CLK_EN); + rtw_write32_set(rtwdev, REG_HCI_OPT_CTRL, BIT_USB_SUS_DIS); + break; + case RTW_HCI_TYPE_SDIO: + rtw_write8_clr(rtwdev, REG_SDIO_HSUS_CTRL, BIT_HCI_SUS_REQ); + + for (retry = 0; retry < RTW_PWR_POLLING_CNT; retry++) { + if (rtw_read8(rtwdev, REG_SDIO_HSUS_CTRL) & BIT_HCI_RESUME_RDY) + break; + + usleep_range(10, 50); + } + + if (retry == RTW_PWR_POLLING_CNT) { + rtw_err(rtwdev, "failed to poll REG_SDIO_HSUS_CTRL[1]"); + return -ETIMEDOUT; + } + + if (rtw_sdio_is_sdio30_supported(rtwdev)) + rtw_write8_set(rtwdev, REG_HCI_OPT_CTRL + 2, + BIT_SDIO_PAD_E5 >> 16); + else + rtw_write8_clr(rtwdev, REG_HCI_OPT_CTRL + 2, + BIT_SDIO_PAD_E5 >> 16); break; case RTW_HCI_TYPE_USB: break; @@ -203,8 +227,8 @@ static int rtw_sub_pwr_seq_parser(struct rtw_dev *rtwdev, u8 intf_mask, return 0; } -static int rtw_pwr_seq_parser(struct rtw_dev *rtwdev, - const struct rtw_pwr_seq_cmd **cmd_seq) +int rtw_pwr_seq_parser(struct rtw_dev *rtwdev, + const struct rtw_pwr_seq_cmd * const *cmd_seq) { u8 cut_mask; u8 intf_mask; @@ -217,10 +241,13 @@ static int rtw_pwr_seq_parser(struct rtw_dev *rtwdev, cut_mask = cut_version_to_mask(cut); switch (rtw_hci_type(rtwdev)) { case RTW_HCI_TYPE_PCIE: - intf_mask = BIT(2); + intf_mask = RTW_PWR_INTF_PCI_MSK; break; case RTW_HCI_TYPE_USB: - intf_mask = BIT(1); + intf_mask = RTW_PWR_INTF_USB_MSK; + break; + case RTW_HCI_TYPE_SDIO: + intf_mask = RTW_PWR_INTF_SDIO_MSK; break; default: return -EINVAL; @@ -233,22 +260,25 @@ static int rtw_pwr_seq_parser(struct rtw_dev *rtwdev, ret = rtw_sub_pwr_seq_parser(rtwdev, intf_mask, cut_mask, cmd); if (ret) - return -EBUSY; + return ret; idx++; } while (1); return 0; } +EXPORT_SYMBOL(rtw_pwr_seq_parser); static int rtw_mac_power_switch(struct rtw_dev *rtwdev, bool pwr_on) { - struct rtw_chip_info *chip = rtwdev->chip; - const struct rtw_pwr_seq_cmd **pwr_seq; + const struct rtw_chip_info *chip = rtwdev->chip; + const struct rtw_pwr_seq_cmd * const *pwr_seq; + u32 imr = 0; u8 rpwm; bool cur_pwr; + int ret; - if (rtw_chip_wcpu_11ac(rtwdev)) { + if (rtw_chip_wcpu_3081(rtwdev)) { rpwm = rtw_read8(rtwdev, rtwdev->hci.rpwm_addr); /* Check FW still exist or not */ @@ -261,6 +291,7 @@ static int rtw_mac_power_switch(struct rtw_dev *rtwdev, bool pwr_on) if (rtw_read8(rtwdev, REG_CR) == 0xea) cur_pwr = false; else if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_USB && + chip->id != RTW_CHIP_TYPE_8814A && (rtw_read8(rtwdev, REG_SYS_STATUS1 + 1) & BIT(0))) cur_pwr = false; else @@ -269,11 +300,31 @@ static int rtw_mac_power_switch(struct rtw_dev *rtwdev, bool pwr_on) if (pwr_on == cur_pwr) return -EALREADY; + if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_SDIO) { + imr = rtw_read32(rtwdev, REG_SDIO_HIMR); + rtw_write32(rtwdev, REG_SDIO_HIMR, 0); + } + + if (!pwr_on) + clear_bit(RTW_FLAG_POWERON, rtwdev->flags); + pwr_seq = pwr_on ? chip->pwr_on_seq : chip->pwr_off_seq; - if (rtw_pwr_seq_parser(rtwdev, pwr_seq)) - return -EINVAL; + ret = rtw_pwr_seq_parser(rtwdev, pwr_seq); - return 0; + if (pwr_on && rtw_hci_type(rtwdev) == RTW_HCI_TYPE_USB) { + if (chip->id == RTW_CHIP_TYPE_8822C || + chip->id == RTW_CHIP_TYPE_8822B || + chip->id == RTW_CHIP_TYPE_8821C) + rtw_write8_clr(rtwdev, REG_SYS_STATUS1 + 1, BIT(0)); + } + + if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_SDIO) + rtw_write32(rtwdev, REG_SDIO_HIMR, imr); + + if (!ret && pwr_on) + set_bit(RTW_FLAG_POWERON, rtwdev->flags); + + return ret; } static int __rtw_mac_init_system_cfg(struct rtw_dev *rtwdev) @@ -318,7 +369,7 @@ static int __rtw_mac_init_system_cfg_legacy(struct rtw_dev *rtwdev) static int rtw_mac_init_system_cfg(struct rtw_dev *rtwdev) { - if (rtw_chip_wcpu_11n(rtwdev)) + if (rtw_chip_wcpu_8051(rtwdev)) return __rtw_mac_init_system_cfg_legacy(rtwdev); return __rtw_mac_init_system_cfg(rtwdev); @@ -335,6 +386,11 @@ int rtw_mac_power_on(struct rtw_dev *rtwdev) ret = rtw_mac_power_switch(rtwdev, true); if (ret == -EALREADY) { rtw_mac_power_switch(rtwdev, false); + + ret = rtw_mac_pre_system_cfg(rtwdev); + if (ret) + goto err; + ret = rtw_mac_power_switch(rtwdev, true); if (ret) goto err; @@ -439,6 +495,9 @@ static void download_firmware_reg_backup(struct rtw_dev *rtwdev, rtw_write16(rtwdev, REG_FIFOPAGE_INFO_1, 0x200); rtw_write32(rtwdev, REG_RQPN_CTRL_2, bckp[bckp_idx - 1].val); + if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_SDIO) + rtw_read32(rtwdev, REG_SDIO_FREE_TXPG); + /* Disable beacon related functions */ tmp = rtw_read8(rtwdev, REG_BCN_CTRL); bckp[bckp_idx].len = 1; @@ -587,7 +646,7 @@ static int download_firmware_to_mem(struct rtw_dev *rtwdev, const u8 *data, u32 src, u32 dst, u32 size) { - struct rtw_chip_info *chip = rtwdev->chip; + const struct rtw_chip_info *chip = rtwdev->chip; u32 desc_size = chip->tx_pkt_desc_sz; u8 first_part; u32 mem_offset; @@ -726,7 +785,8 @@ static int __rtw_download_firmware(struct rtw_dev *rtwdev, if (!check_firmware_size(data, size)) return -EINVAL; - if (!ltecoex_read_reg(rtwdev, 0x38, <ecoex_bckp)) + if (rtwdev->chip->ltecoex_addr && + !ltecoex_read_reg(rtwdev, 0x38, <ecoex_bckp)) return -EBUSY; wlan_cpu_enable(rtwdev, false); @@ -744,8 +804,11 @@ static int __rtw_download_firmware(struct rtw_dev *rtwdev, wlan_cpu_enable(rtwdev, true); - if (!ltecoex_reg_write(rtwdev, 0x38, ltecoex_bckp)) - return -EBUSY; + if (rtwdev->chip->ltecoex_addr && + !ltecoex_reg_write(rtwdev, 0x38, ltecoex_bckp)) { + ret = -EBUSY; + goto dlfw_fail; + } ret = download_firmware_validate(rtwdev); if (ret) @@ -793,8 +856,8 @@ fwdl_ready: } } -static void -write_firmware_page(struct rtw_dev *rtwdev, u32 page, const u8 *data, u32 size) +void rtw_write_firmware_page(struct rtw_dev *rtwdev, u32 page, + const u8 *data, u32 size) { u32 val32; u32 block_nr; @@ -824,6 +887,7 @@ write_firmware_page(struct rtw_dev *rtwdev, u32 page, const u8 *data, u32 size) rtw_write32(rtwdev, write_addr, le32_to_cpu(remain_data)); } } +EXPORT_SYMBOL(rtw_write_firmware_page); static int download_firmware_legacy(struct rtw_dev *rtwdev, const u8 *data, u32 size) @@ -841,11 +905,13 @@ download_firmware_legacy(struct rtw_dev *rtwdev, const u8 *data, u32 size) rtw_write8_set(rtwdev, REG_MCUFW_CTRL, BIT_FWDL_CHK_RPT); for (page = 0; page < total_page; page++) { - write_firmware_page(rtwdev, page, data, DLFW_PAGE_SIZE_LEGACY); + rtw_hci_write_firmware_page(rtwdev, page, data, + DLFW_PAGE_SIZE_LEGACY); data += DLFW_PAGE_SIZE_LEGACY; } if (last_page_size) - write_firmware_page(rtwdev, page, data, last_page_size); + rtw_hci_write_firmware_page(rtwdev, page, data, + last_page_size); if (!check_hw_ready(rtwdev, REG_MCUFW_CTRL, BIT_FWDL_CHK_RPT, 1)) { rtw_err(rtwdev, "failed to check download firmware report\n"); @@ -884,6 +950,12 @@ static int __rtw_download_firmware_legacy(struct rtw_dev *rtwdev, { int ret = 0; + /* reset firmware if still present */ + if (rtwdev->chip->id == RTW_CHIP_TYPE_8703B && + rtw_read8_mask(rtwdev, REG_MCUFW_CTRL, BIT_RAM_DL_SEL)) { + rtw_write8(rtwdev, REG_MCUFW_CTRL, 0x00); + } + en_download_firmware_legacy(rtwdev, true); ret = download_firmware_legacy(rtwdev, fw->firmware->data, fw->firmware->size); en_download_firmware_legacy(rtwdev, false); @@ -906,14 +978,31 @@ out: return ret; } -int rtw_download_firmware(struct rtw_dev *rtwdev, struct rtw_fw_state *fw) +static +int _rtw_download_firmware(struct rtw_dev *rtwdev, struct rtw_fw_state *fw) { - if (rtw_chip_wcpu_11n(rtwdev)) + if (rtw_chip_wcpu_8051(rtwdev)) return __rtw_download_firmware_legacy(rtwdev, fw); return __rtw_download_firmware(rtwdev, fw); } +int rtw_download_firmware(struct rtw_dev *rtwdev, struct rtw_fw_state *fw) +{ + int ret; + + ret = _rtw_download_firmware(rtwdev, fw); + if (ret) + return ret; + + if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_PCIE && + rtwdev->chip->id == RTW_CHIP_TYPE_8821C) + rtw_fw_set_recover_bt_device(rtwdev); + + return 0; +} +EXPORT_SYMBOL(rtw_download_firmware); + static u32 get_priority_queues(struct rtw_dev *rtwdev, u32 queues) { const struct rtw_rqpn *rqpn = rtwdev->fifo.rqpn; @@ -934,7 +1023,7 @@ static u32 get_priority_queues(struct rtw_dev *rtwdev, u32 queues) static void __rtw_mac_flush_prio_queue(struct rtw_dev *rtwdev, u32 prio_queue, bool drop) { - struct rtw_chip_info *chip = rtwdev->chip; + const struct rtw_chip_info *chip = rtwdev->chip; const struct rtw_prioq_addr *addr; bool wsize; u16 avail_page, rsvd_page; @@ -958,14 +1047,15 @@ static void __rtw_mac_flush_prio_queue(struct rtw_dev *rtwdev, msleep(20); } - /* priority queue is still not empty, throw a warning, + /* priority queue is still not empty, throw a debug message * * Note that if we want to flush the tx queue when having a lot of * traffic (ex, 100Mbps up), some of the packets could be dropped. * And it requires like ~2secs to flush the full priority queue. */ if (!drop) - rtw_warn(rtwdev, "timed out to flush queue %d\n", prio_queue); + rtw_dbg(rtwdev, RTW_DBG_UNEXP, + "timed out to flush queue %d\n", prio_queue); } static void rtw_mac_flush_prio_queues(struct rtw_dev *rtwdev, @@ -996,7 +1086,7 @@ void rtw_mac_flush_queues(struct rtw_dev *rtwdev, u32 queues, bool drop) static int txdma_queue_mapping(struct rtw_dev *rtwdev) { - struct rtw_chip_info *chip = rtwdev->chip; + const struct rtw_chip_info *chip = rtwdev->chip; const struct rtw_rqpn *rqpn = NULL; u16 txdma_pq_map = 0; @@ -1014,6 +1104,9 @@ static int txdma_queue_mapping(struct rtw_dev *rtwdev) else return -EINVAL; break; + case RTW_HCI_TYPE_SDIO: + rqpn = &chip->rqpn_table[0]; + break; default: return -EINVAL; } @@ -1029,23 +1122,30 @@ static int txdma_queue_mapping(struct rtw_dev *rtwdev) rtw_write8(rtwdev, REG_CR, 0); rtw_write8(rtwdev, REG_CR, MAC_TRX_ENABLE); - if (rtw_chip_wcpu_11ac(rtwdev)) + if (rtw_chip_wcpu_3081(rtwdev)) rtw_write32(rtwdev, REG_H2CQ_CSR, BIT_H2CQ_FULL); + if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_SDIO) { + rtw_read32(rtwdev, REG_SDIO_FREE_TXPG); + rtw_write32(rtwdev, REG_SDIO_TX_CTRL, 0); + } else if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_USB) { + rtw_write8_set(rtwdev, REG_TXDMA_PQ_MAP, BIT_RXDMA_ARBBW_EN); + } + return 0; } -static int set_trx_fifo_info(struct rtw_dev *rtwdev) +int rtw_set_trx_fifo_info(struct rtw_dev *rtwdev) { + const struct rtw_chip_info *chip = rtwdev->chip; struct rtw_fifo_conf *fifo = &rtwdev->fifo; - struct rtw_chip_info *chip = rtwdev->chip; u16 cur_pg_addr; u8 csi_buf_pg_num = chip->csi_buf_pg_num; /* config rsvd page num */ - fifo->rsvd_drv_pg_num = 8; - fifo->txff_pg_num = chip->txff_size >> 7; - if (rtw_chip_wcpu_11n(rtwdev)) + fifo->rsvd_drv_pg_num = chip->rsvd_drv_pg_num; + fifo->txff_pg_num = chip->txff_size / chip->page_size; + if (rtw_chip_wcpu_8051(rtwdev)) fifo->rsvd_pg_num = fifo->rsvd_drv_pg_num; else fifo->rsvd_pg_num = fifo->rsvd_drv_pg_num + @@ -1063,7 +1163,7 @@ static int set_trx_fifo_info(struct rtw_dev *rtwdev) fifo->rsvd_boundary = fifo->txff_pg_num - fifo->rsvd_pg_num; cur_pg_addr = fifo->txff_pg_num; - if (rtw_chip_wcpu_11ac(rtwdev)) { + if (rtw_chip_wcpu_3081(rtwdev)) { cur_pg_addr -= csi_buf_pg_num; fifo->rsvd_csibuf_addr = cur_pg_addr; cur_pg_addr -= RSVD_PG_FW_TXBUF_NUM; @@ -1087,13 +1187,14 @@ static int set_trx_fifo_info(struct rtw_dev *rtwdev) return 0; } +EXPORT_SYMBOL(rtw_set_trx_fifo_info); static int __priority_queue_cfg(struct rtw_dev *rtwdev, const struct rtw_page_table *pg_tbl, u16 pubq_num) { + const struct rtw_chip_info *chip = rtwdev->chip; struct rtw_fifo_conf *fifo = &rtwdev->fifo; - struct rtw_chip_info *chip = rtwdev->chip; rtw_write16(rtwdev, REG_FIFOPAGE_INFO_1, pg_tbl->hq_num); rtw_write16(rtwdev, REG_FIFOPAGE_INFO_2, pg_tbl->lq_num); @@ -1109,6 +1210,15 @@ static int __priority_queue_cfg(struct rtw_dev *rtwdev, rtw_write16(rtwdev, REG_FIFOPAGE_CTRL_2 + 2, fifo->rsvd_boundary); rtw_write16(rtwdev, REG_BCNQ1_BDNY_V1, fifo->rsvd_boundary); rtw_write32(rtwdev, REG_RXFF_BNDY, chip->rxff_size - C2H_PKT_BUF - 1); + + if (rtwdev->hci.type == RTW_HCI_TYPE_USB) { + rtw_write8_mask(rtwdev, REG_AUTO_LLT_V1, BIT_MASK_BLK_DESC_NUM, + chip->usb_tx_agg_desc_num); + + rtw_write8(rtwdev, REG_AUTO_LLT_V1 + 3, chip->usb_tx_agg_desc_num); + rtw_write8_set(rtwdev, REG_TXDMA_OFFSET_CHK + 1, BIT(1)); + } + rtw_write8_set(rtwdev, REG_AUTO_LLT_V1, BIT_AUTO_INIT_LLT_V1); if (!check_hw_ready(rtwdev, REG_AUTO_LLT_V1, BIT_AUTO_INIT_LLT_V1, 0)) @@ -1123,8 +1233,8 @@ static int __priority_queue_cfg_legacy(struct rtw_dev *rtwdev, const struct rtw_page_table *pg_tbl, u16 pubq_num) { + const struct rtw_chip_info *chip = rtwdev->chip; struct rtw_fifo_conf *fifo = &rtwdev->fifo; - struct rtw_chip_info *chip = rtwdev->chip; u32 val32; val32 = BIT_RQPN_NE(pg_tbl->nq_num, pg_tbl->exq_num); @@ -1149,13 +1259,13 @@ static int __priority_queue_cfg_legacy(struct rtw_dev *rtwdev, static int priority_queue_cfg(struct rtw_dev *rtwdev) { + const struct rtw_chip_info *chip = rtwdev->chip; struct rtw_fifo_conf *fifo = &rtwdev->fifo; - struct rtw_chip_info *chip = rtwdev->chip; const struct rtw_page_table *pg_tbl = NULL; u16 pubq_num; int ret; - ret = set_trx_fifo_info(rtwdev); + ret = rtw_set_trx_fifo_info(rtwdev); if (ret) return ret; @@ -1173,13 +1283,16 @@ static int priority_queue_cfg(struct rtw_dev *rtwdev) else return -EINVAL; break; + case RTW_HCI_TYPE_SDIO: + pg_tbl = &chip->page_table[0]; + break; default: return -EINVAL; } pubq_num = fifo->acq_pg_num - pg_tbl->hq_num - pg_tbl->lq_num - pg_tbl->nq_num - pg_tbl->exq_num - pg_tbl->gapq_num; - if (rtw_chip_wcpu_11n(rtwdev)) + if (rtw_chip_wcpu_8051(rtwdev)) return __priority_queue_cfg_legacy(rtwdev, pg_tbl, pubq_num); else return __priority_queue_cfg(rtwdev, pg_tbl, pubq_num); @@ -1195,7 +1308,7 @@ static int init_h2c(struct rtw_dev *rtwdev) u32 h2cq_free; u32 wp, rp; - if (rtw_chip_wcpu_11n(rtwdev)) + if (rtw_chip_wcpu_8051(rtwdev)) return 0; h2cq_addr = fifo->rsvd_h2cq_addr << TX_PAGE_SIZE_SHIFT; @@ -1262,7 +1375,7 @@ static int rtw_drv_info_cfg(struct rtw_dev *rtwdev) u8 value8; rtw_write8(rtwdev, REG_RX_DRVINFO_SZ, PHY_STATUS_SIZE); - if (rtw_chip_wcpu_11ac(rtwdev)) { + if (rtw_chip_wcpu_3081(rtwdev)) { value8 = rtw_read8(rtwdev, REG_TRXFF_BNDY + 1); value8 &= 0xF0; /* For rxdesc len = 0 issue */ @@ -1277,7 +1390,7 @@ static int rtw_drv_info_cfg(struct rtw_dev *rtwdev) int rtw_mac_init(struct rtw_dev *rtwdev) { - struct rtw_chip_info *chip = rtwdev->chip; + const struct rtw_chip_info *chip = rtwdev->chip; int ret; ret = rtw_init_trx_cfg(rtwdev); @@ -1296,3 +1409,13 @@ int rtw_mac_init(struct rtw_dev *rtwdev) return 0; } + +int rtw_mac_postinit(struct rtw_dev *rtwdev) +{ + const struct rtw_chip_info *chip = rtwdev->chip; + + if (!chip->ops->mac_postinit) + return 0; + + return chip->ops->mac_postinit(rtwdev); +} |
