LCOV - code coverage report
Current view: top level - drivers/net/wireless/realtek/rtw88 - mac.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 296 552 53.6 %
Date: 2022-03-28 16:04:14 Functions: 21 31 67.7 %
Branches: 69 206 33.5 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
       2                 :            : /* Copyright(c) 2018-2019  Realtek Corporation
       3                 :            :  */
       4                 :            : 
       5                 :            : #include "main.h"
       6                 :            : #include "mac.h"
       7                 :            : #include "reg.h"
       8                 :            : #include "fw.h"
       9                 :            : #include "debug.h"
      10                 :            : 
      11                 :          0 : void rtw_set_channel_mac(struct rtw_dev *rtwdev, u8 channel, u8 bw,
      12                 :            :                          u8 primary_ch_idx)
      13                 :            : {
      14                 :          0 :         u8 txsc40 = 0, txsc20 = 0;
      15                 :          0 :         u32 value32;
      16                 :          0 :         u8 value8;
      17                 :            : 
      18                 :          0 :         txsc20 = primary_ch_idx;
      19         [ #  # ]:          0 :         if (bw == RTW_CHANNEL_WIDTH_80) {
      20   [ #  #  #  # ]:          0 :                 if (txsc20 == 1 || txsc20 == 3)
      21                 :            :                         txsc40 = 9;
      22                 :            :                 else
      23                 :          0 :                         txsc40 = 10;
      24                 :            :         }
      25                 :          0 :         rtw_write8(rtwdev, REG_DATA_SC,
      26                 :          0 :                    BIT_TXSC_20M(txsc20) | BIT_TXSC_40M(txsc40));
      27                 :            : 
      28                 :          0 :         value32 = rtw_read32(rtwdev, REG_WMAC_TRXPTCL_CTL);
      29                 :          0 :         value32 &= ~BIT_RFMOD;
      30      [ #  #  # ]:          0 :         switch (bw) {
      31                 :          0 :         case RTW_CHANNEL_WIDTH_80:
      32                 :          0 :                 value32 |= BIT_RFMOD_80M;
      33                 :          0 :                 break;
      34                 :          0 :         case RTW_CHANNEL_WIDTH_40:
      35                 :          0 :                 value32 |= BIT_RFMOD_40M;
      36                 :          0 :                 break;
      37                 :            :         case RTW_CHANNEL_WIDTH_20:
      38                 :            :         default:
      39                 :            :                 break;
      40                 :            :         }
      41                 :          0 :         rtw_write32(rtwdev, REG_WMAC_TRXPTCL_CTL, value32);
      42                 :            : 
      43                 :          0 :         value32 = rtw_read32(rtwdev, REG_AFE_CTRL1) & ~(BIT_MAC_CLK_SEL);
      44                 :          0 :         value32 |= (MAC_CLK_HW_DEF_80M << BIT_SHIFT_MAC_CLK_SEL);
      45                 :          0 :         rtw_write32(rtwdev, REG_AFE_CTRL1, value32);
      46                 :            : 
      47                 :          0 :         rtw_write8(rtwdev, REG_USTIME_TSF, MAC_CLK_SPEED);
      48                 :          0 :         rtw_write8(rtwdev, REG_USTIME_EDCA, MAC_CLK_SPEED);
      49                 :            : 
      50                 :          0 :         value8 = rtw_read8(rtwdev, REG_CCK_CHECK);
      51                 :          0 :         value8 = value8 & ~BIT_CHECK_CCK_EN;
      52   [ #  #  #  #  :          0 :         if (IS_CH_5G_BAND(channel))
             #  #  #  # ]
      53                 :          0 :                 value8 |= BIT_CHECK_CCK_EN;
      54                 :          0 :         rtw_write8(rtwdev, REG_CCK_CHECK, value8);
      55                 :          0 : }
      56                 :            : 
      57                 :         13 : static int rtw_mac_pre_system_cfg(struct rtw_dev *rtwdev)
      58                 :            : {
      59                 :         13 :         u32 value32;
      60                 :         13 :         u8 value8;
      61                 :            : 
      62                 :         13 :         rtw_write8(rtwdev, REG_RSV_CTRL, 0);
      63                 :            : 
      64      [ +  -  - ]:         13 :         switch (rtw_hci_type(rtwdev)) {
      65                 :            :         case RTW_HCI_TYPE_PCIE:
      66                 :         13 :                 rtw_write32_set(rtwdev, REG_HCI_OPT_CTRL, BIT_BT_DIG_CLK_EN);
      67                 :            :                 break;
      68                 :            :         case RTW_HCI_TYPE_USB:
      69                 :            :                 break;
      70                 :            :         default:
      71                 :            :                 return -EINVAL;
      72                 :            :         }
      73                 :            : 
      74                 :            :         /* config PIN Mux */
      75                 :         13 :         value32 = rtw_read32(rtwdev, REG_PAD_CTRL1);
      76                 :         13 :         value32 |= BIT_PAPE_WLBT_SEL | BIT_LNAON_WLBT_SEL;
      77                 :         13 :         rtw_write32(rtwdev, REG_PAD_CTRL1, value32);
      78                 :            : 
      79                 :         13 :         value32 = rtw_read32(rtwdev, REG_LED_CFG);
      80                 :         13 :         value32 &= ~(BIT_PAPE_SEL_EN | BIT_LNAON_SEL_EN);
      81                 :         13 :         rtw_write32(rtwdev, REG_LED_CFG, value32);
      82                 :            : 
      83                 :         13 :         value32 = rtw_read32(rtwdev, REG_GPIO_MUXCFG);
      84                 :         13 :         value32 |= BIT_WLRFE_4_5_EN;
      85                 :         13 :         rtw_write32(rtwdev, REG_GPIO_MUXCFG, value32);
      86                 :            : 
      87                 :            :         /* disable BB/RF */
      88                 :         13 :         value8 = rtw_read8(rtwdev, REG_SYS_FUNC_EN);
      89                 :         13 :         value8 &= ~(BIT_FEN_BB_RSTB | BIT_FEN_BB_GLB_RST);
      90                 :         13 :         rtw_write8(rtwdev, REG_SYS_FUNC_EN, value8);
      91                 :            : 
      92                 :         13 :         value8 = rtw_read8(rtwdev, REG_RF_CTRL);
      93                 :         13 :         value8 &= ~(BIT_RF_SDM_RSTB | BIT_RF_RSTB | BIT_RF_EN);
      94                 :         13 :         rtw_write8(rtwdev, REG_RF_CTRL, value8);
      95                 :            : 
      96                 :         13 :         value32 = rtw_read32(rtwdev, REG_WLRF1);
      97                 :         13 :         value32 &= ~BIT_WLRF1_BBRF_EN;
      98                 :         13 :         rtw_write32(rtwdev, REG_WLRF1, value32);
      99                 :            : 
     100                 :         13 :         return 0;
     101                 :            : }
     102                 :            : 
     103                 :         34 : static int rtw_pwr_cmd_polling(struct rtw_dev *rtwdev,
     104                 :            :                                struct rtw_pwr_seq_cmd *cmd)
     105                 :            : {
     106                 :         34 :         u8 value;
     107                 :         34 :         u8 flag = 0;
     108                 :         34 :         u32 offset;
     109                 :         34 :         u32 cnt = RTW_PWR_POLLING_CNT;
     110                 :            : 
     111         [ -  + ]:         34 :         if (cmd->base == RTW_PWR_ADDR_SDIO)
     112                 :          0 :                 offset = cmd->offset | SDIO_LOCAL_OFFSET;
     113                 :            :         else
     114                 :         34 :                 offset = cmd->offset;
     115                 :            : 
     116                 :         62 :         do {
     117                 :         62 :                 cnt--;
     118                 :         62 :                 value = rtw_read8(rtwdev, offset);
     119                 :         62 :                 value &= cmd->mask;
     120         [ +  + ]:         62 :                 if (value == (cmd->value & cmd->mask))
     121                 :            :                         return 0;
     122         [ -  + ]:         28 :                 if (cnt == 0) {
     123   [ #  #  #  # ]:          0 :                         if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_PCIE &&
     124                 :            :                             flag == 0) {
     125                 :          0 :                                 value = rtw_read8(rtwdev, REG_SYS_PW_CTRL);
     126                 :          0 :                                 value |= BIT(3);
     127                 :          0 :                                 rtw_write8(rtwdev, REG_SYS_PW_CTRL, value);
     128                 :          0 :                                 value &= ~BIT(3);
     129                 :          0 :                                 rtw_write8(rtwdev, REG_SYS_PW_CTRL, value);
     130                 :          0 :                                 cnt = RTW_PWR_POLLING_CNT;
     131                 :          0 :                                 flag = 1;
     132                 :            :                         } else {
     133                 :            :                                 return -EBUSY;
     134                 :            :                         }
     135                 :            :                 } else {
     136                 :         28 :                         udelay(50);
     137                 :            :                 }
     138                 :            :         } while (1);
     139                 :            : }
     140                 :            : 
     141                 :         48 : static int rtw_sub_pwr_seq_parser(struct rtw_dev *rtwdev, u8 intf_mask,
     142                 :            :                                   u8 cut_mask, struct rtw_pwr_seq_cmd *cmd)
     143                 :            : {
     144                 :         48 :         struct rtw_pwr_seq_cmd *cur_cmd;
     145                 :         48 :         u32 offset;
     146                 :         48 :         u8 value;
     147                 :            : 
     148         [ +  + ]:        848 :         for (cur_cmd = cmd; cur_cmd->cmd != RTW_PWR_CMD_END; cur_cmd++) {
     149         [ +  + ]:        800 :                 if (!(cur_cmd->intf_mask & intf_mask) ||
     150         [ -  + ]:        402 :                     !(cur_cmd->cut_mask & cut_mask))
     151                 :        398 :                         continue;
     152                 :            : 
     153   [ +  +  -  -  :        402 :                 switch (cur_cmd->cmd) {
                      - ]
     154                 :        368 :                 case RTW_PWR_CMD_WRITE:
     155                 :        368 :                         offset = cur_cmd->offset;
     156                 :            : 
     157         [ -  + ]:        368 :                         if (cur_cmd->base == RTW_PWR_ADDR_SDIO)
     158                 :          0 :                                 offset |= SDIO_LOCAL_OFFSET;
     159                 :            : 
     160                 :        368 :                         value = rtw_read8(rtwdev, offset);
     161                 :        368 :                         value &= ~cur_cmd->mask;
     162                 :        368 :                         value |= (cur_cmd->value & cur_cmd->mask);
     163                 :        368 :                         rtw_write8(rtwdev, offset, value);
     164                 :            :                         break;
     165                 :         34 :                 case RTW_PWR_CMD_POLLING:
     166         [ +  - ]:         34 :                         if (rtw_pwr_cmd_polling(rtwdev, cur_cmd))
     167                 :            :                                 return -EBUSY;
     168                 :            :                         break;
     169                 :          0 :                 case RTW_PWR_CMD_DELAY:
     170         [ #  # ]:          0 :                         if (cur_cmd->value == RTW_PWR_DELAY_US)
     171   [ #  #  #  # ]:          0 :                                 udelay(cur_cmd->offset);
     172                 :            :                         else
     173   [ #  #  #  #  :          0 :                                 mdelay(cur_cmd->offset);
          #  #  #  #  #  
                      # ]
     174                 :            :                         break;
     175                 :            :                 case RTW_PWR_CMD_READ:
     176                 :            :                         break;
     177                 :            :                 default:
     178                 :            :                         return -EINVAL;
     179                 :            :                 }
     180                 :            :         }
     181                 :            : 
     182                 :            :         return 0;
     183                 :            : }
     184                 :            : 
     185                 :         24 : static int rtw_pwr_seq_parser(struct rtw_dev *rtwdev,
     186                 :            :                               struct rtw_pwr_seq_cmd **cmd_seq)
     187                 :            : {
     188                 :         24 :         u8 cut_mask;
     189                 :         24 :         u8 intf_mask;
     190                 :         24 :         u8 cut;
     191                 :         24 :         u32 idx = 0;
     192                 :         24 :         struct rtw_pwr_seq_cmd *cmd;
     193                 :         24 :         int ret;
     194                 :            : 
     195                 :         24 :         cut = rtwdev->hal.cut_version;
     196                 :         24 :         cut_mask = cut_version_to_mask(cut);
     197      [ -  +  - ]:         24 :         switch (rtw_hci_type(rtwdev)) {
     198                 :            :         case RTW_HCI_TYPE_PCIE:
     199                 :            :                 intf_mask = BIT(2);
     200                 :            :                 break;
     201                 :          0 :         case RTW_HCI_TYPE_USB:
     202                 :          0 :                 intf_mask = BIT(1);
     203                 :          0 :                 break;
     204                 :            :         default:
     205                 :            :                 return -EINVAL;
     206                 :            :         }
     207                 :            : 
     208                 :         72 :         do {
     209                 :         72 :                 cmd = cmd_seq[idx];
     210         [ +  + ]:         72 :                 if (!cmd)
     211                 :            :                         break;
     212                 :            : 
     213                 :         48 :                 ret = rtw_sub_pwr_seq_parser(rtwdev, intf_mask, cut_mask, cmd);
     214         [ +  - ]:         48 :                 if (ret)
     215                 :            :                         return -EBUSY;
     216                 :            : 
     217                 :         48 :                 idx++;
     218                 :         48 :         } while (1);
     219                 :            : 
     220                 :            :         return 0;
     221                 :            : }
     222                 :            : 
     223                 :         31 : static int rtw_mac_power_switch(struct rtw_dev *rtwdev, bool pwr_on)
     224                 :            : {
     225                 :         31 :         struct rtw_chip_info *chip = rtwdev->chip;
     226                 :         31 :         struct rtw_pwr_seq_cmd **pwr_seq;
     227                 :         31 :         u8 rpwm;
     228                 :         31 :         bool cur_pwr;
     229                 :            : 
     230                 :         31 :         rpwm = rtw_read8(rtwdev, rtwdev->hci.rpwm_addr);
     231                 :            : 
     232                 :            :         /* Check FW still exist or not */
     233         [ +  + ]:         31 :         if (rtw_read16(rtwdev, REG_MCUFW_CTRL) == 0xC078) {
     234                 :          1 :                 rpwm = (rpwm ^ BIT_RPWM_TOGGLE) & BIT_RPWM_TOGGLE;
     235                 :          1 :                 rtw_write8(rtwdev, rtwdev->hci.rpwm_addr, rpwm);
     236                 :            :         }
     237                 :            : 
     238         [ +  + ]:         31 :         if (rtw_read8(rtwdev, REG_CR) == 0xea)
     239                 :            :                 cur_pwr = false;
     240         [ -  + ]:         12 :         else if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_USB &&
     241                 :            :                  (rtw_read8(rtwdev, REG_SYS_STATUS1 + 1) & BIT(0)))
     242                 :            :                 cur_pwr = false;
     243                 :            :         else
     244                 :            :                 cur_pwr = true;
     245                 :            : 
     246   [ +  +  +  + ]:         31 :         if (pwr_on && cur_pwr)
     247                 :            :                 return -EALREADY;
     248                 :            : 
     249         [ +  + ]:         24 :         pwr_seq = pwr_on ? chip->pwr_on_seq : chip->pwr_off_seq;
     250         [ -  + ]:         24 :         if (rtw_pwr_seq_parser(rtwdev, pwr_seq))
     251                 :          0 :                 return -EINVAL;
     252                 :            : 
     253                 :            :         return 0;
     254                 :            : }
     255                 :            : 
     256                 :         10 : static int rtw_mac_init_system_cfg(struct rtw_dev *rtwdev)
     257                 :            : {
     258                 :         10 :         u8 sys_func_en = rtwdev->chip->sys_func_en;
     259                 :         10 :         u8 value8;
     260                 :         10 :         u32 value, tmp;
     261                 :            : 
     262                 :         10 :         value = rtw_read32(rtwdev, REG_CPU_DMEM_CON);
     263                 :         10 :         value |= BIT_WL_PLATFORM_RST | BIT_DDMA_EN;
     264                 :         10 :         rtw_write32(rtwdev, REG_CPU_DMEM_CON, value);
     265                 :            : 
     266                 :         10 :         rtw_write8_set(rtwdev, REG_SYS_FUNC_EN + 1, sys_func_en);
     267                 :         10 :         value8 = (rtw_read8(rtwdev, REG_CR_EXT + 3) & 0xF0) | 0x0C;
     268                 :         10 :         rtw_write8(rtwdev, REG_CR_EXT + 3, value8);
     269                 :            : 
     270                 :            :         /* disable boot-from-flash for driver's DL FW */
     271                 :         10 :         tmp = rtw_read32(rtwdev, REG_MCUFW_CTRL);
     272         [ +  - ]:         10 :         if (tmp & BIT_BOOT_FSPI_EN) {
     273                 :         10 :                 rtw_write32(rtwdev, REG_MCUFW_CTRL, tmp & (~BIT_BOOT_FSPI_EN));
     274                 :         10 :                 value = rtw_read32(rtwdev, REG_GPIO_MUXCFG) & (~BIT_FSPI_EN);
     275                 :         10 :                 rtw_write32(rtwdev, REG_GPIO_MUXCFG, value);
     276                 :            :         }
     277                 :            : 
     278                 :         10 :         return 0;
     279                 :            : }
     280                 :            : 
     281                 :         13 : int rtw_mac_power_on(struct rtw_dev *rtwdev)
     282                 :            : {
     283                 :         13 :         int ret = 0;
     284                 :            : 
     285                 :         13 :         ret = rtw_mac_pre_system_cfg(rtwdev);
     286         [ -  + ]:         13 :         if (ret)
     287                 :          0 :                 goto err;
     288                 :            : 
     289                 :         13 :         ret = rtw_mac_power_switch(rtwdev, true);
     290         [ +  + ]:         13 :         if (ret == -EALREADY) {
     291                 :          4 :                 rtw_mac_power_switch(rtwdev, false);
     292                 :          4 :                 ret = rtw_mac_power_switch(rtwdev, true);
     293         [ +  + ]:          4 :                 if (ret)
     294                 :          3 :                         goto err;
     295         [ -  + ]:          9 :         } else if (ret) {
     296                 :          0 :                 goto err;
     297                 :            :         }
     298                 :            : 
     299                 :         10 :         ret = rtw_mac_init_system_cfg(rtwdev);
     300         [ -  + ]:         10 :         if (ret)
     301                 :          0 :                 goto err;
     302                 :            : 
     303                 :            :         return 0;
     304                 :            : 
     305                 :          3 : err:
     306                 :          3 :         rtw_err(rtwdev, "mac power on failed");
     307                 :          3 :         return ret;
     308                 :            : }
     309                 :            : 
     310                 :         10 : void rtw_mac_power_off(struct rtw_dev *rtwdev)
     311                 :            : {
     312                 :         10 :         rtw_mac_power_switch(rtwdev, false);
     313                 :         10 : }
     314                 :            : 
     315                 :         10 : static bool check_firmware_size(const u8 *data, u32 size)
     316                 :            : {
     317                 :         10 :         const struct rtw_fw_hdr *fw_hdr = (const struct rtw_fw_hdr *)data;
     318                 :         10 :         u32 dmem_size;
     319                 :         10 :         u32 imem_size;
     320                 :         10 :         u32 emem_size;
     321                 :         10 :         u32 real_size;
     322                 :            : 
     323                 :         10 :         dmem_size = le32_to_cpu(fw_hdr->dmem_size);
     324                 :         10 :         imem_size = le32_to_cpu(fw_hdr->imem_size);
     325                 :         10 :         emem_size = (fw_hdr->mem_usage & BIT(4)) ?
     326         [ -  + ]:         10 :                     le32_to_cpu(fw_hdr->emem_size) : 0;
     327                 :            : 
     328                 :         10 :         printk(KERN_INFO "dmem_size: %x, imem_size: %x, emem_size: %x\n",
     329                 :            :                         dmem_size, imem_size, emem_size);
     330                 :            : 
     331                 :         10 :         dmem_size += FW_HDR_CHKSUM_SIZE;
     332                 :         10 :         imem_size += FW_HDR_CHKSUM_SIZE;
     333         [ +  - ]:         10 :         emem_size += emem_size ? FW_HDR_CHKSUM_SIZE : 0;
     334                 :         10 :         real_size = FW_HDR_SIZE + dmem_size + imem_size + emem_size;
     335                 :            : 
     336                 :         10 :         printk(KERN_INFO "real_size: %x, size: %x\n", real_size, size);
     337         [ -  + ]:         10 :         if (real_size != size)
     338                 :          0 :                 return false;
     339                 :            : 
     340                 :            :         return true;
     341                 :            : }
     342                 :            : 
     343                 :         20 : static void wlan_cpu_enable(struct rtw_dev *rtwdev, bool enable)
     344                 :            : {
     345         [ +  + ]:         20 :         if (enable) {
     346                 :            :                 /* cpu io interface enable */
     347                 :         10 :                 rtw_write8_set(rtwdev, REG_RSV_CTRL + 1, BIT_WLMCU_IOIF);
     348                 :            : 
     349                 :            :                 /* cpu enable */
     350                 :         10 :                 rtw_write8_set(rtwdev, REG_SYS_FUNC_EN + 1, BIT_FEN_CPUEN);
     351                 :            :         } else {
     352                 :            :                 /* cpu io interface disable */
     353                 :         10 :                 rtw_write8_clr(rtwdev, REG_SYS_FUNC_EN + 1, BIT_FEN_CPUEN);
     354                 :            : 
     355                 :            :                 /* cpu disable */
     356                 :         10 :                 rtw_write8_clr(rtwdev, REG_RSV_CTRL + 1, BIT_WLMCU_IOIF);
     357                 :            :         }
     358                 :         20 : }
     359                 :            : 
     360                 :            : #define DLFW_RESTORE_REG_NUM 6
     361                 :            : 
     362                 :         10 : static void download_firmware_reg_backup(struct rtw_dev *rtwdev,
     363                 :            :                                          struct rtw_backup_info *bckp)
     364                 :            : {
     365                 :         10 :         u8 tmp;
     366                 :         10 :         u8 bckp_idx = 0;
     367                 :            : 
     368                 :            :         /* set HIQ to hi priority */
     369                 :         10 :         bckp[bckp_idx].len = 1;
     370                 :         10 :         bckp[bckp_idx].reg = REG_TXDMA_PQ_MAP + 1;
     371                 :         10 :         bckp[bckp_idx].val = rtw_read8(rtwdev, REG_TXDMA_PQ_MAP + 1);
     372                 :         10 :         bckp_idx++;
     373                 :         10 :         tmp = RTW_DMA_MAPPING_HIGH << 6;
     374                 :         10 :         rtw_write8(rtwdev, REG_TXDMA_PQ_MAP + 1, tmp);
     375                 :            : 
     376                 :            :         /* DLFW only use HIQ, map HIQ to hi priority */
     377                 :         10 :         bckp[bckp_idx].len = 1;
     378                 :         10 :         bckp[bckp_idx].reg = REG_CR;
     379                 :         10 :         bckp[bckp_idx].val = rtw_read8(rtwdev, REG_CR);
     380                 :         10 :         bckp_idx++;
     381                 :         10 :         bckp[bckp_idx].len = 4;
     382                 :         10 :         bckp[bckp_idx].reg = REG_H2CQ_CSR;
     383                 :         10 :         bckp[bckp_idx].val = BIT_H2CQ_FULL;
     384                 :         10 :         bckp_idx++;
     385                 :         10 :         tmp = BIT_HCI_TXDMA_EN | BIT_TXDMA_EN;
     386                 :         10 :         rtw_write8(rtwdev, REG_CR, tmp);
     387                 :         10 :         rtw_write32(rtwdev, REG_H2CQ_CSR, BIT_H2CQ_FULL);
     388                 :            : 
     389                 :            :         /* Config hi priority queue and public priority queue page number */
     390                 :         10 :         bckp[bckp_idx].len = 2;
     391                 :         10 :         bckp[bckp_idx].reg = REG_FIFOPAGE_INFO_1;
     392                 :         10 :         bckp[bckp_idx].val = rtw_read16(rtwdev, REG_FIFOPAGE_INFO_1);
     393                 :         10 :         bckp_idx++;
     394                 :         10 :         bckp[bckp_idx].len = 4;
     395                 :         10 :         bckp[bckp_idx].reg = REG_RQPN_CTRL_2;
     396                 :         10 :         bckp[bckp_idx].val = rtw_read32(rtwdev, REG_RQPN_CTRL_2) | BIT_LD_RQPN;
     397                 :         10 :         bckp_idx++;
     398                 :         10 :         rtw_write16(rtwdev, REG_FIFOPAGE_INFO_1, 0x200);
     399                 :         10 :         rtw_write32(rtwdev, REG_RQPN_CTRL_2, bckp[bckp_idx - 1].val);
     400                 :            : 
     401                 :            :         /* Disable beacon related functions */
     402                 :         10 :         tmp = rtw_read8(rtwdev, REG_BCN_CTRL);
     403                 :         10 :         bckp[bckp_idx].len = 1;
     404                 :         10 :         bckp[bckp_idx].reg = REG_BCN_CTRL;
     405                 :         10 :         bckp[bckp_idx].val = tmp;
     406                 :         10 :         bckp_idx++;
     407                 :         10 :         tmp = (u8)((tmp & (~BIT_EN_BCN_FUNCTION)) | BIT_DIS_TSF_UDT);
     408                 :         10 :         rtw_write8(rtwdev, REG_BCN_CTRL, tmp);
     409                 :            : 
     410                 :         10 :         WARN(bckp_idx != DLFW_RESTORE_REG_NUM, "wrong backup number\n");
     411                 :         10 : }
     412                 :            : 
     413                 :         10 : static void download_firmware_reset_platform(struct rtw_dev *rtwdev)
     414                 :            : {
     415                 :         10 :         rtw_write8_clr(rtwdev, REG_CPU_DMEM_CON + 2, BIT_WL_PLATFORM_RST >> 16);
     416                 :         10 :         rtw_write8_clr(rtwdev, REG_SYS_CLK_CTRL + 1, BIT_CPU_CLK_EN >> 8);
     417                 :         10 :         rtw_write8_set(rtwdev, REG_CPU_DMEM_CON + 2, BIT_WL_PLATFORM_RST >> 16);
     418                 :         10 :         rtw_write8_set(rtwdev, REG_SYS_CLK_CTRL + 1, BIT_CPU_CLK_EN >> 8);
     419                 :         10 : }
     420                 :            : 
     421                 :         10 : static void download_firmware_reg_restore(struct rtw_dev *rtwdev,
     422                 :            :                                           struct rtw_backup_info *bckp,
     423                 :            :                                           u8 bckp_num)
     424                 :            : {
     425                 :         10 :         rtw_restore_reg(rtwdev, bckp, bckp_num);
     426                 :            : }
     427                 :            : 
     428                 :            : #define TX_DESC_SIZE 48
     429                 :            : 
     430                 :        380 : static int send_firmware_pkt_rsvd_page(struct rtw_dev *rtwdev, u16 pg_addr,
     431                 :            :                                        const u8 *data, u32 size)
     432                 :            : {
     433                 :        380 :         u8 *buf;
     434                 :        380 :         int ret;
     435                 :            : 
     436                 :        380 :         buf = kmemdup(data, size, GFP_KERNEL);
     437         [ +  - ]:        380 :         if (!buf)
     438                 :            :                 return -ENOMEM;
     439                 :            : 
     440                 :        380 :         ret = rtw_fw_write_data_rsvd_page(rtwdev, pg_addr, buf, size);
     441                 :        380 :         kfree(buf);
     442                 :        380 :         return ret;
     443                 :            : }
     444                 :            : 
     445                 :            : static int
     446                 :        380 : send_firmware_pkt(struct rtw_dev *rtwdev, u16 pg_addr, const u8 *data, u32 size)
     447                 :            : {
     448                 :        380 :         int ret;
     449                 :            : 
     450         [ -  + ]:        380 :         if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_USB &&
     451         [ #  # ]:          0 :             !((size + TX_DESC_SIZE) & (512 - 1)))
     452                 :          0 :                 size += 1;
     453                 :            : 
     454                 :        380 :         ret = send_firmware_pkt_rsvd_page(rtwdev, pg_addr, data, size);
     455         [ -  + ]:        380 :         if (ret)
     456                 :          0 :                 rtw_err(rtwdev, "failed to download rsvd page\n");
     457                 :            : 
     458                 :        380 :         return ret;
     459                 :            : }
     460                 :            : 
     461                 :            : static int
     462                 :        380 : iddma_enable(struct rtw_dev *rtwdev, u32 src, u32 dst, u32 ctrl)
     463                 :            : {
     464                 :        380 :         rtw_write32(rtwdev, REG_DDMA_CH0SA, src);
     465                 :        380 :         rtw_write32(rtwdev, REG_DDMA_CH0DA, dst);
     466                 :        380 :         rtw_write32(rtwdev, REG_DDMA_CH0CTRL, ctrl);
     467                 :            : 
     468         [ -  + ]:        380 :         if (!check_hw_ready(rtwdev, REG_DDMA_CH0CTRL, BIT_DDMACH0_OWN, 0))
     469                 :          0 :                 return -EBUSY;
     470                 :            : 
     471                 :            :         return 0;
     472                 :            : }
     473                 :            : 
     474                 :        380 : static int iddma_download_firmware(struct rtw_dev *rtwdev, u32 src, u32 dst,
     475                 :            :                                    u32 len, u8 first)
     476                 :            : {
     477                 :        380 :         u32 ch0_ctrl = BIT_DDMACH0_CHKSUM_EN | BIT_DDMACH0_OWN;
     478                 :            : 
     479         [ +  - ]:        380 :         if (!check_hw_ready(rtwdev, REG_DDMA_CH0CTRL, BIT_DDMACH0_OWN, 0))
     480                 :            :                 return -EBUSY;
     481                 :            : 
     482                 :        380 :         ch0_ctrl |= len & BIT_MASK_DDMACH0_DLEN;
     483         [ +  + ]:        380 :         if (!first)
     484                 :        360 :                 ch0_ctrl |= BIT_DDMACH0_CHKSUM_CONT;
     485                 :            : 
     486         [ -  + ]:        380 :         if (iddma_enable(rtwdev, src, dst, ch0_ctrl))
     487                 :          0 :                 return -EBUSY;
     488                 :            : 
     489                 :            :         return 0;
     490                 :            : }
     491                 :            : 
     492                 :            : static bool
     493                 :         20 : check_fw_checksum(struct rtw_dev *rtwdev, u32 addr)
     494                 :            : {
     495                 :         20 :         u8 fw_ctrl;
     496                 :            : 
     497                 :         20 :         fw_ctrl = rtw_read8(rtwdev, REG_MCUFW_CTRL);
     498                 :            : 
     499         [ -  + ]:         20 :         if (rtw_read32(rtwdev, REG_DDMA_CH0CTRL) & BIT_DDMACH0_CHKSUM_STS) {
     500         [ #  # ]:          0 :                 if (addr < OCPBASE_DMEM_88XX) {
     501                 :          0 :                         fw_ctrl |= BIT_IMEM_DW_OK;
     502                 :          0 :                         fw_ctrl &= ~BIT_IMEM_CHKSUM_OK;
     503                 :          0 :                         rtw_write8(rtwdev, REG_MCUFW_CTRL, fw_ctrl);
     504                 :            :                 } else {
     505                 :          0 :                         fw_ctrl |= BIT_DMEM_DW_OK;
     506                 :          0 :                         fw_ctrl &= ~BIT_DMEM_CHKSUM_OK;
     507                 :          0 :                         rtw_write8(rtwdev, REG_MCUFW_CTRL, fw_ctrl);
     508                 :            :                 }
     509                 :            : 
     510                 :          0 :                 rtw_err(rtwdev, "invalid fw checksum\n");
     511                 :            : 
     512                 :          0 :                 return false;
     513                 :            :         }
     514                 :            : 
     515         [ +  + ]:         20 :         if (addr < OCPBASE_DMEM_88XX) {
     516                 :         10 :                 fw_ctrl |= (BIT_IMEM_DW_OK | BIT_IMEM_CHKSUM_OK);
     517                 :         10 :                 rtw_write8(rtwdev, REG_MCUFW_CTRL, fw_ctrl);
     518                 :            :         } else {
     519                 :         10 :                 fw_ctrl |= (BIT_DMEM_DW_OK | BIT_DMEM_CHKSUM_OK);
     520                 :         10 :                 rtw_write8(rtwdev, REG_MCUFW_CTRL, fw_ctrl);
     521                 :            :         }
     522                 :            : 
     523                 :            :         return true;
     524                 :            : }
     525                 :            : 
     526                 :            : static int
     527                 :         20 : download_firmware_to_mem(struct rtw_dev *rtwdev, const u8 *data,
     528                 :            :                          u32 src, u32 dst, u32 size)
     529                 :            : {
     530                 :         20 :         struct rtw_chip_info *chip = rtwdev->chip;
     531                 :         20 :         u32 desc_size = chip->tx_pkt_desc_sz;
     532                 :         20 :         u8 first_part;
     533                 :         20 :         u32 mem_offset;
     534                 :         20 :         u32 residue_size;
     535                 :         20 :         u32 pkt_size;
     536                 :         20 :         u32 max_size = 0x1000;
     537                 :         20 :         u32 val;
     538                 :         20 :         int ret;
     539                 :            : 
     540                 :         20 :         mem_offset = 0;
     541                 :         20 :         first_part = 1;
     542                 :         20 :         residue_size = size;
     543                 :            : 
     544                 :         20 :         val = rtw_read32(rtwdev, REG_DDMA_CH0CTRL);
     545                 :         20 :         val |= BIT_DDMACH0_RESET_CHKSUM_STS;
     546                 :         20 :         rtw_write32(rtwdev, REG_DDMA_CH0CTRL, val);
     547                 :            : 
     548         [ +  + ]:        400 :         while (residue_size) {
     549                 :        380 :                 if (residue_size >= max_size)
     550                 :            :                         pkt_size = max_size;
     551                 :            :                 else
     552                 :            :                         pkt_size = residue_size;
     553                 :            : 
     554                 :        380 :                 ret = send_firmware_pkt(rtwdev, (u16)(src >> 7),
     555                 :            :                                         data + mem_offset, pkt_size);
     556         [ -  + ]:        380 :                 if (ret)
     557                 :          0 :                         return ret;
     558                 :            : 
     559                 :        380 :                 ret = iddma_download_firmware(rtwdev, OCPBASE_TXBUF_88XX +
     560                 :        380 :                                               src + desc_size,
     561                 :            :                                               dst + mem_offset, pkt_size,
     562                 :            :                                               first_part);
     563         [ -  + ]:        380 :                 if (ret)
     564                 :          0 :                         return ret;
     565                 :            : 
     566                 :        380 :                 first_part = 0;
     567                 :        380 :                 mem_offset += pkt_size;
     568                 :        380 :                 residue_size -= pkt_size;
     569                 :            :         }
     570                 :            : 
     571         [ -  + ]:         20 :         if (!check_fw_checksum(rtwdev, dst))
     572                 :          0 :                 return -EINVAL;
     573                 :            : 
     574                 :            :         return 0;
     575                 :            : }
     576                 :            : 
     577                 :            : static int
     578                 :            : start_download_firmware(struct rtw_dev *rtwdev, const u8 *data, u32 size)
     579                 :            : {
     580                 :            :         const struct rtw_fw_hdr *fw_hdr = (const struct rtw_fw_hdr *)data;
     581                 :            :         const u8 *cur_fw;
     582                 :            :         u16 val;
     583                 :            :         u32 imem_size;
     584                 :            :         u32 dmem_size;
     585                 :            :         u32 emem_size;
     586                 :            :         u32 addr;
     587                 :            :         int ret;
     588                 :            : 
     589                 :            :         dmem_size = le32_to_cpu(fw_hdr->dmem_size);
     590                 :            :         imem_size = le32_to_cpu(fw_hdr->imem_size);
     591                 :            :         emem_size = (fw_hdr->mem_usage & BIT(4)) ?
     592                 :            :                     le32_to_cpu(fw_hdr->emem_size) : 0;
     593                 :            :         dmem_size += FW_HDR_CHKSUM_SIZE;
     594                 :            :         imem_size += FW_HDR_CHKSUM_SIZE;
     595                 :            :         emem_size += emem_size ? FW_HDR_CHKSUM_SIZE : 0;
     596                 :            : 
     597                 :            :         val = (u16)(rtw_read16(rtwdev, REG_MCUFW_CTRL) & 0x3800);
     598                 :            :         val |= BIT_MCUFWDL_EN;
     599                 :            :         rtw_write16(rtwdev, REG_MCUFW_CTRL, val);
     600                 :            : 
     601                 :            :         cur_fw = data + FW_HDR_SIZE;
     602                 :            :         addr = le32_to_cpu(fw_hdr->dmem_addr);
     603                 :            :         addr &= ~BIT(31);
     604                 :            :         ret = download_firmware_to_mem(rtwdev, cur_fw, 0, addr, dmem_size);
     605                 :            :         if (ret)
     606                 :            :                 return ret;
     607                 :            : 
     608                 :            :         cur_fw = data + FW_HDR_SIZE + dmem_size;
     609                 :            :         addr = le32_to_cpu(fw_hdr->imem_addr);
     610                 :            :         addr &= ~BIT(31);
     611                 :            :         ret = download_firmware_to_mem(rtwdev, cur_fw, 0, addr, imem_size);
     612                 :            :         if (ret)
     613                 :            :                 return ret;
     614                 :            : 
     615                 :            :         if (emem_size) {
     616                 :            :                 cur_fw = data + FW_HDR_SIZE + dmem_size + imem_size;
     617                 :            :                 addr = le32_to_cpu(fw_hdr->emem_addr);
     618                 :            :                 addr &= ~BIT(31);
     619                 :            :                 ret = download_firmware_to_mem(rtwdev, cur_fw, 0, addr,
     620                 :            :                                                emem_size);
     621                 :            :                 if (ret)
     622                 :            :                         return ret;
     623                 :            :         }
     624                 :            : 
     625                 :            :         return 0;
     626                 :            : }
     627                 :            : 
     628                 :         10 : static int download_firmware_validate(struct rtw_dev *rtwdev)
     629                 :            : {
     630                 :         10 :         u32 fw_key;
     631                 :            : 
     632         [ +  + ]:         10 :         if (!check_hw_ready(rtwdev, REG_MCUFW_CTRL, FW_READY_MASK, FW_READY)) {
     633                 :          1 :                 fw_key = rtw_read32(rtwdev, REG_FW_DBG7) & FW_KEY_MASK;
     634         [ -  + ]:          1 :                 if (fw_key == ILLEGAL_KEY_GROUP)
     635                 :          0 :                         rtw_err(rtwdev, "invalid fw key\n");
     636                 :          1 :                 return -EINVAL;
     637                 :            :         }
     638                 :            : 
     639                 :            :         return 0;
     640                 :            : }
     641                 :            : 
     642                 :         10 : static void download_firmware_end_flow(struct rtw_dev *rtwdev)
     643                 :            : {
     644                 :         10 :         u16 fw_ctrl;
     645                 :            : 
     646                 :         10 :         rtw_write32(rtwdev, REG_TXDMA_STATUS, BTI_PAGE_OVF);
     647                 :            : 
     648                 :            :         /* Check IMEM & DMEM checksum is OK or not */
     649                 :         10 :         fw_ctrl = rtw_read16(rtwdev, REG_MCUFW_CTRL);
     650         [ -  + ]:         10 :         if ((fw_ctrl & BIT_CHECK_SUM_OK) != BIT_CHECK_SUM_OK)
     651                 :            :                 return;
     652                 :            : 
     653                 :          0 :         fw_ctrl = (fw_ctrl | BIT_FW_DW_RDY) & ~BIT_MCUFWDL_EN;
     654                 :          0 :         rtw_write16(rtwdev, REG_MCUFW_CTRL, fw_ctrl);
     655                 :            : }
     656                 :            : 
     657                 :         10 : int rtw_download_firmware(struct rtw_dev *rtwdev, struct rtw_fw_state *fw)
     658                 :            : {
     659                 :         10 :         struct rtw_backup_info bckp[DLFW_RESTORE_REG_NUM];
     660                 :         10 :         const u8 *data = fw->firmware->data;
     661                 :         10 :         u32 size = fw->firmware->size;
     662                 :         10 :         u32 ltecoex_bckp;
     663                 :         10 :         int ret;
     664                 :            : 
     665         [ +  - ]:         10 :         if (!check_firmware_size(data, size))
     666                 :            :                 return -EINVAL;
     667                 :            : 
     668         [ +  - ]:         10 :         if (!ltecoex_read_reg(rtwdev, 0x38, &ltecoex_bckp))
     669                 :            :                 return -EBUSY;
     670                 :            : 
     671                 :         10 :         wlan_cpu_enable(rtwdev, false);
     672                 :            : 
     673                 :         10 :         download_firmware_reg_backup(rtwdev, bckp);
     674                 :         10 :         download_firmware_reset_platform(rtwdev);
     675                 :            : 
     676                 :         10 :         ret = start_download_firmware(rtwdev, data, size);
     677         [ -  + ]:         10 :         if (ret)
     678                 :          0 :                 goto dlfw_fail;
     679                 :            : 
     680                 :         10 :         download_firmware_reg_restore(rtwdev, bckp, DLFW_RESTORE_REG_NUM);
     681                 :            : 
     682                 :         10 :         download_firmware_end_flow(rtwdev);
     683                 :            : 
     684                 :         10 :         wlan_cpu_enable(rtwdev, true);
     685                 :            : 
     686         [ +  - ]:         10 :         if (!ltecoex_reg_write(rtwdev, 0x38, ltecoex_bckp))
     687                 :            :                 return -EBUSY;
     688                 :            : 
     689                 :         10 :         ret = download_firmware_validate(rtwdev);
     690         [ +  + ]:         10 :         if (ret)
     691                 :          1 :                 goto dlfw_fail;
     692                 :            : 
     693                 :            :         /* reset desc and index */
     694                 :          9 :         rtw_hci_setup(rtwdev);
     695                 :            : 
     696                 :          9 :         rtwdev->h2c.last_box_num = 0;
     697                 :          9 :         rtwdev->h2c.seq = 0;
     698                 :            : 
     699                 :          9 :         set_bit(RTW_FLAG_FW_RUNNING, rtwdev->flags);
     700                 :            : 
     701                 :          9 :         return 0;
     702                 :            : 
     703                 :          1 : dlfw_fail:
     704                 :            :         /* Disable FWDL_EN */
     705                 :          1 :         rtw_write8_clr(rtwdev, REG_MCUFW_CTRL, BIT_MCUFWDL_EN);
     706                 :          1 :         rtw_write8_set(rtwdev, REG_SYS_FUNC_EN + 1, BIT_FEN_CPUEN);
     707                 :            : 
     708                 :          1 :         return ret;
     709                 :            : }
     710                 :            : 
     711                 :            : static u32 get_priority_queues(struct rtw_dev *rtwdev, u32 queues)
     712                 :            : {
     713                 :            :         struct rtw_rqpn *rqpn = rtwdev->fifo.rqpn;
     714                 :            :         u32 prio_queues = 0;
     715                 :            : 
     716                 :            :         if (queues & BIT(IEEE80211_AC_VO))
     717                 :            :                 prio_queues |= BIT(rqpn->dma_map_vo);
     718                 :            :         if (queues & BIT(IEEE80211_AC_VI))
     719                 :            :                 prio_queues |= BIT(rqpn->dma_map_vi);
     720                 :            :         if (queues & BIT(IEEE80211_AC_BE))
     721                 :            :                 prio_queues |= BIT(rqpn->dma_map_be);
     722                 :            :         if (queues & BIT(IEEE80211_AC_BK))
     723                 :            :                 prio_queues |= BIT(rqpn->dma_map_bk);
     724                 :            : 
     725                 :            :         return prio_queues;
     726                 :            : }
     727                 :            : 
     728                 :          0 : static void __rtw_mac_flush_prio_queue(struct rtw_dev *rtwdev,
     729                 :            :                                        u32 prio_queue, bool drop)
     730                 :            : {
     731                 :          0 :         u32 addr;
     732                 :          0 :         u16 avail_page, rsvd_page;
     733                 :          0 :         int i;
     734                 :            : 
     735         [ #  # ]:          0 :         switch (prio_queue) {
     736                 :            :         case RTW_DMA_MAPPING_EXTRA:
     737                 :            :                 addr = REG_FIFOPAGE_INFO_4;
     738                 :            :                 break;
     739                 :            :         case RTW_DMA_MAPPING_LOW:
     740                 :            :                 addr = REG_FIFOPAGE_INFO_2;
     741                 :            :                 break;
     742                 :            :         case RTW_DMA_MAPPING_NORMAL:
     743                 :            :                 addr = REG_FIFOPAGE_INFO_3;
     744                 :            :                 break;
     745                 :            :         case RTW_DMA_MAPPING_HIGH:
     746                 :            :                 addr = REG_FIFOPAGE_INFO_1;
     747                 :            :                 break;
     748                 :            :         default:
     749                 :            :                 return;
     750                 :            :         }
     751                 :            : 
     752                 :            :         /* check if all of the reserved pages are available for 100 msecs */
     753         [ #  # ]:          0 :         for (i = 0; i < 5; i++) {
     754                 :          0 :                 rsvd_page = rtw_read16(rtwdev, addr);
     755                 :          0 :                 avail_page = rtw_read16(rtwdev, addr + 2);
     756         [ #  # ]:          0 :                 if (rsvd_page == avail_page)
     757                 :            :                         return;
     758                 :            : 
     759                 :          0 :                 msleep(20);
     760                 :            :         }
     761                 :            : 
     762                 :            :         /* priority queue is still not empty, throw a warning,
     763                 :            :          *
     764                 :            :          * Note that if we want to flush the tx queue when having a lot of
     765                 :            :          * traffic (ex, 100Mbps up), some of the packets could be dropped.
     766                 :            :          * And it requires like ~2secs to flush the full priority queue.
     767                 :            :          */
     768         [ #  # ]:          0 :         if (!drop)
     769                 :          0 :                 rtw_warn(rtwdev, "timed out to flush queue %d\n", prio_queue);
     770                 :            : }
     771                 :            : 
     772                 :          0 : static void rtw_mac_flush_prio_queues(struct rtw_dev *rtwdev,
     773                 :            :                                       u32 prio_queues, bool drop)
     774                 :            : {
     775                 :          0 :         u32 q;
     776                 :            : 
     777         [ #  # ]:          0 :         for (q = 0; q < RTW_DMA_MAPPING_MAX; q++)
     778         [ #  # ]:          0 :                 if (prio_queues & BIT(q))
     779                 :          0 :                         __rtw_mac_flush_prio_queue(rtwdev, q, drop);
     780                 :            : }
     781                 :            : 
     782                 :          0 : void rtw_mac_flush_queues(struct rtw_dev *rtwdev, u32 queues, bool drop)
     783                 :            : {
     784                 :          0 :         u32 prio_queues = 0;
     785                 :            : 
     786                 :            :         /* If all of the hardware queues are requested to flush,
     787                 :            :          * or the priority queues are not mapped yet,
     788                 :            :          * flush all of the priority queues
     789                 :            :          */
     790   [ #  #  #  # ]:          0 :         if (queues == BIT(rtwdev->hw->queues) - 1 || !rtwdev->fifo.rqpn)
     791                 :            :                 prio_queues = BIT(RTW_DMA_MAPPING_MAX) - 1;
     792                 :            :         else
     793                 :          0 :                 prio_queues = get_priority_queues(rtwdev, queues);
     794                 :            : 
     795                 :          0 :         rtw_mac_flush_prio_queues(rtwdev, prio_queues, drop);
     796                 :          0 : }
     797                 :            : 
     798                 :          0 : static int txdma_queue_mapping(struct rtw_dev *rtwdev)
     799                 :            : {
     800                 :          0 :         struct rtw_chip_info *chip = rtwdev->chip;
     801                 :          0 :         struct rtw_rqpn *rqpn = NULL;
     802                 :          0 :         u16 txdma_pq_map = 0;
     803                 :            : 
     804      [ #  #  # ]:          0 :         switch (rtw_hci_type(rtwdev)) {
     805                 :          0 :         case RTW_HCI_TYPE_PCIE:
     806                 :          0 :                 rqpn = &chip->rqpn_table[1];
     807                 :          0 :                 break;
     808                 :          0 :         case RTW_HCI_TYPE_USB:
     809         [ #  # ]:          0 :                 if (rtwdev->hci.bulkout_num == 2)
     810                 :          0 :                         rqpn = &chip->rqpn_table[2];
     811         [ #  # ]:          0 :                 else if (rtwdev->hci.bulkout_num == 3)
     812                 :          0 :                         rqpn = &chip->rqpn_table[3];
     813         [ #  # ]:          0 :                 else if (rtwdev->hci.bulkout_num == 4)
     814                 :          0 :                         rqpn = &chip->rqpn_table[4];
     815                 :            :                 else
     816                 :            :                         return -EINVAL;
     817                 :            :                 break;
     818                 :            :         default:
     819                 :            :                 return -EINVAL;
     820                 :            :         }
     821                 :            : 
     822                 :          0 :         rtwdev->fifo.rqpn = rqpn;
     823                 :          0 :         txdma_pq_map |= BIT_TXDMA_HIQ_MAP(rqpn->dma_map_hi);
     824                 :          0 :         txdma_pq_map |= BIT_TXDMA_MGQ_MAP(rqpn->dma_map_mg);
     825                 :          0 :         txdma_pq_map |= BIT_TXDMA_BKQ_MAP(rqpn->dma_map_bk);
     826                 :          0 :         txdma_pq_map |= BIT_TXDMA_BEQ_MAP(rqpn->dma_map_be);
     827                 :          0 :         txdma_pq_map |= BIT_TXDMA_VIQ_MAP(rqpn->dma_map_vi);
     828                 :          0 :         txdma_pq_map |= BIT_TXDMA_VOQ_MAP(rqpn->dma_map_vo);
     829                 :          0 :         rtw_write16(rtwdev, REG_TXDMA_PQ_MAP, txdma_pq_map);
     830                 :            : 
     831                 :          0 :         rtw_write8(rtwdev, REG_CR, 0);
     832                 :          0 :         rtw_write8(rtwdev, REG_CR, MAC_TRX_ENABLE);
     833                 :          0 :         rtw_write32(rtwdev, REG_H2CQ_CSR, BIT_H2CQ_FULL);
     834                 :            : 
     835                 :          0 :         return 0;
     836                 :            : }
     837                 :            : 
     838                 :          0 : static int set_trx_fifo_info(struct rtw_dev *rtwdev)
     839                 :            : {
     840                 :          0 :         struct rtw_fifo_conf *fifo = &rtwdev->fifo;
     841                 :          0 :         struct rtw_chip_info *chip = rtwdev->chip;
     842                 :          0 :         u16 cur_pg_addr;
     843                 :          0 :         u8 csi_buf_pg_num = chip->csi_buf_pg_num;
     844                 :            : 
     845                 :            :         /* config rsvd page num */
     846                 :          0 :         fifo->rsvd_drv_pg_num = 8;
     847                 :          0 :         fifo->txff_pg_num = chip->txff_size >> 7;
     848                 :          0 :         fifo->rsvd_pg_num = fifo->rsvd_drv_pg_num +
     849                 :            :                            RSVD_PG_H2C_EXTRAINFO_NUM +
     850                 :            :                            RSVD_PG_H2C_STATICINFO_NUM +
     851                 :            :                            RSVD_PG_H2CQ_NUM +
     852                 :            :                            RSVD_PG_CPU_INSTRUCTION_NUM +
     853                 :          0 :                            RSVD_PG_FW_TXBUF_NUM +
     854                 :            :                            csi_buf_pg_num;
     855                 :            : 
     856         [ #  # ]:          0 :         if (fifo->rsvd_pg_num > fifo->txff_pg_num)
     857                 :            :                 return -ENOMEM;
     858                 :            : 
     859                 :          0 :         fifo->acq_pg_num = fifo->txff_pg_num - fifo->rsvd_pg_num;
     860                 :          0 :         fifo->rsvd_boundary = fifo->txff_pg_num - fifo->rsvd_pg_num;
     861                 :            : 
     862                 :          0 :         cur_pg_addr = fifo->txff_pg_num;
     863                 :          0 :         cur_pg_addr -= csi_buf_pg_num;
     864                 :          0 :         fifo->rsvd_csibuf_addr = cur_pg_addr;
     865                 :          0 :         cur_pg_addr -= RSVD_PG_FW_TXBUF_NUM;
     866                 :          0 :         fifo->rsvd_fw_txbuf_addr = cur_pg_addr;
     867                 :          0 :         cur_pg_addr -= RSVD_PG_CPU_INSTRUCTION_NUM;
     868                 :          0 :         fifo->rsvd_cpu_instr_addr = cur_pg_addr;
     869                 :          0 :         cur_pg_addr -= RSVD_PG_H2CQ_NUM;
     870                 :          0 :         fifo->rsvd_h2cq_addr = cur_pg_addr;
     871                 :          0 :         cur_pg_addr -= RSVD_PG_H2C_STATICINFO_NUM;
     872                 :          0 :         fifo->rsvd_h2c_sta_info_addr = cur_pg_addr;
     873                 :          0 :         cur_pg_addr -= RSVD_PG_H2C_EXTRAINFO_NUM;
     874                 :          0 :         fifo->rsvd_h2c_info_addr = cur_pg_addr;
     875                 :          0 :         cur_pg_addr -= fifo->rsvd_drv_pg_num;
     876                 :          0 :         fifo->rsvd_drv_addr = cur_pg_addr;
     877                 :            : 
     878         [ #  # ]:          0 :         if (fifo->rsvd_boundary != fifo->rsvd_drv_addr) {
     879                 :          0 :                 rtw_err(rtwdev, "wrong rsvd driver address\n");
     880                 :          0 :                 return -EINVAL;
     881                 :            :         }
     882                 :            : 
     883                 :            :         return 0;
     884                 :            : }
     885                 :            : 
     886                 :          0 : static int priority_queue_cfg(struct rtw_dev *rtwdev)
     887                 :            : {
     888                 :          0 :         struct rtw_fifo_conf *fifo = &rtwdev->fifo;
     889                 :          0 :         struct rtw_chip_info *chip = rtwdev->chip;
     890                 :          0 :         struct rtw_page_table *pg_tbl = NULL;
     891                 :          0 :         u16 pubq_num;
     892                 :          0 :         int ret;
     893                 :            : 
     894                 :          0 :         ret = set_trx_fifo_info(rtwdev);
     895         [ #  # ]:          0 :         if (ret)
     896                 :            :                 return ret;
     897                 :            : 
     898      [ #  #  # ]:          0 :         switch (rtw_hci_type(rtwdev)) {
     899                 :          0 :         case RTW_HCI_TYPE_PCIE:
     900                 :          0 :                 pg_tbl = &chip->page_table[1];
     901                 :          0 :                 break;
     902                 :          0 :         case RTW_HCI_TYPE_USB:
     903         [ #  # ]:          0 :                 if (rtwdev->hci.bulkout_num == 2)
     904                 :          0 :                         pg_tbl = &chip->page_table[2];
     905         [ #  # ]:          0 :                 else if (rtwdev->hci.bulkout_num == 3)
     906                 :          0 :                         pg_tbl = &chip->page_table[3];
     907         [ #  # ]:          0 :                 else if (rtwdev->hci.bulkout_num == 4)
     908                 :          0 :                         pg_tbl = &chip->page_table[4];
     909                 :            :                 else
     910                 :            :                         return -EINVAL;
     911                 :            :                 break;
     912                 :            :         default:
     913                 :            :                 return -EINVAL;
     914                 :            :         }
     915                 :            : 
     916                 :          0 :         pubq_num = fifo->acq_pg_num - pg_tbl->hq_num - pg_tbl->lq_num -
     917                 :          0 :                    pg_tbl->nq_num - pg_tbl->exq_num - pg_tbl->gapq_num;
     918                 :          0 :         rtw_write16(rtwdev, REG_FIFOPAGE_INFO_1, pg_tbl->hq_num);
     919                 :          0 :         rtw_write16(rtwdev, REG_FIFOPAGE_INFO_2, pg_tbl->lq_num);
     920                 :          0 :         rtw_write16(rtwdev, REG_FIFOPAGE_INFO_3, pg_tbl->nq_num);
     921                 :          0 :         rtw_write16(rtwdev, REG_FIFOPAGE_INFO_4, pg_tbl->exq_num);
     922                 :          0 :         rtw_write16(rtwdev, REG_FIFOPAGE_INFO_5, pubq_num);
     923                 :          0 :         rtw_write32_set(rtwdev, REG_RQPN_CTRL_2, BIT_LD_RQPN);
     924                 :            : 
     925                 :          0 :         rtw_write16(rtwdev, REG_FIFOPAGE_CTRL_2, fifo->rsvd_boundary);
     926                 :          0 :         rtw_write8_set(rtwdev, REG_FWHW_TXQ_CTRL + 2, BIT_EN_WR_FREE_TAIL >> 16);
     927                 :            : 
     928                 :          0 :         rtw_write16(rtwdev, REG_BCNQ_BDNY_V1, fifo->rsvd_boundary);
     929                 :          0 :         rtw_write16(rtwdev, REG_FIFOPAGE_CTRL_2 + 2, fifo->rsvd_boundary);
     930                 :          0 :         rtw_write16(rtwdev, REG_BCNQ1_BDNY_V1, fifo->rsvd_boundary);
     931                 :          0 :         rtw_write32(rtwdev, REG_RXFF_BNDY, chip->rxff_size - C2H_PKT_BUF - 1);
     932                 :          0 :         rtw_write8_set(rtwdev, REG_AUTO_LLT_V1, BIT_AUTO_INIT_LLT_V1);
     933                 :            : 
     934         [ #  # ]:          0 :         if (!check_hw_ready(rtwdev, REG_AUTO_LLT_V1, BIT_AUTO_INIT_LLT_V1, 0))
     935                 :            :                 return -EBUSY;
     936                 :            : 
     937                 :          0 :         rtw_write8(rtwdev, REG_CR + 3, 0);
     938                 :            : 
     939                 :          0 :         return 0;
     940                 :            : }
     941                 :            : 
     942                 :          0 : static int init_h2c(struct rtw_dev *rtwdev)
     943                 :            : {
     944                 :          0 :         struct rtw_fifo_conf *fifo = &rtwdev->fifo;
     945                 :          0 :         u8 value8;
     946                 :          0 :         u32 value32;
     947                 :          0 :         u32 h2cq_addr;
     948                 :          0 :         u32 h2cq_size;
     949                 :          0 :         u32 h2cq_free;
     950                 :          0 :         u32 wp, rp;
     951                 :            : 
     952                 :          0 :         h2cq_addr = fifo->rsvd_h2cq_addr << TX_PAGE_SIZE_SHIFT;
     953                 :          0 :         h2cq_size = RSVD_PG_H2CQ_NUM << TX_PAGE_SIZE_SHIFT;
     954                 :            : 
     955                 :          0 :         value32 = rtw_read32(rtwdev, REG_H2C_HEAD);
     956                 :          0 :         value32 = (value32 & 0xFFFC0000) | h2cq_addr;
     957                 :          0 :         rtw_write32(rtwdev, REG_H2C_HEAD, value32);
     958                 :            : 
     959                 :          0 :         value32 = rtw_read32(rtwdev, REG_H2C_READ_ADDR);
     960                 :          0 :         value32 = (value32 & 0xFFFC0000) | h2cq_addr;
     961                 :          0 :         rtw_write32(rtwdev, REG_H2C_READ_ADDR, value32);
     962                 :            : 
     963                 :          0 :         value32 = rtw_read32(rtwdev, REG_H2C_TAIL);
     964                 :          0 :         value32 &= 0xFFFC0000;
     965                 :          0 :         value32 |= (h2cq_addr + h2cq_size);
     966                 :          0 :         rtw_write32(rtwdev, REG_H2C_TAIL, value32);
     967                 :            : 
     968                 :          0 :         value8 = rtw_read8(rtwdev, REG_H2C_INFO);
     969                 :          0 :         value8 = (u8)((value8 & 0xFC) | 0x01);
     970                 :          0 :         rtw_write8(rtwdev, REG_H2C_INFO, value8);
     971                 :            : 
     972                 :          0 :         value8 = rtw_read8(rtwdev, REG_H2C_INFO);
     973                 :          0 :         value8 = (u8)((value8 & 0xFB) | 0x04);
     974                 :          0 :         rtw_write8(rtwdev, REG_H2C_INFO, value8);
     975                 :            : 
     976                 :          0 :         value8 = rtw_read8(rtwdev, REG_TXDMA_OFFSET_CHK + 1);
     977                 :          0 :         value8 = (u8)((value8 & 0x7f) | 0x80);
     978                 :          0 :         rtw_write8(rtwdev, REG_TXDMA_OFFSET_CHK + 1, value8);
     979                 :            : 
     980                 :          0 :         wp = rtw_read32(rtwdev, REG_H2C_PKT_WRITEADDR) & 0x3FFFF;
     981                 :          0 :         rp = rtw_read32(rtwdev, REG_H2C_PKT_READADDR) & 0x3FFFF;
     982         [ #  # ]:          0 :         h2cq_free = wp >= rp ? h2cq_size - (wp - rp) : rp - wp;
     983                 :            : 
     984         [ #  # ]:          0 :         if (h2cq_size != h2cq_free) {
     985                 :          0 :                 rtw_err(rtwdev, "H2C queue mismatch\n");
     986                 :          0 :                 return -EINVAL;
     987                 :            :         }
     988                 :            : 
     989                 :            :         return 0;
     990                 :            : }
     991                 :            : 
     992                 :          0 : static int rtw_init_trx_cfg(struct rtw_dev *rtwdev)
     993                 :            : {
     994                 :          0 :         int ret;
     995                 :            : 
     996                 :          0 :         ret = txdma_queue_mapping(rtwdev);
     997         [ #  # ]:          0 :         if (ret)
     998                 :            :                 return ret;
     999                 :            : 
    1000                 :          0 :         ret = priority_queue_cfg(rtwdev);
    1001         [ #  # ]:          0 :         if (ret)
    1002                 :            :                 return ret;
    1003                 :            : 
    1004                 :          0 :         ret = init_h2c(rtwdev);
    1005         [ #  # ]:          0 :         if (ret)
    1006                 :          0 :                 return ret;
    1007                 :            : 
    1008                 :            :         return 0;
    1009                 :            : }
    1010                 :            : 
    1011                 :          0 : static int rtw_drv_info_cfg(struct rtw_dev *rtwdev)
    1012                 :            : {
    1013                 :          0 :         u8 value8;
    1014                 :            : 
    1015                 :          0 :         rtw_write8(rtwdev, REG_RX_DRVINFO_SZ, PHY_STATUS_SIZE);
    1016                 :          0 :         value8 = rtw_read8(rtwdev, REG_TRXFF_BNDY + 1);
    1017                 :          0 :         value8 &= 0xF0;
    1018                 :            :         /* For rxdesc len = 0 issue */
    1019                 :          0 :         value8 |= 0xF;
    1020                 :          0 :         rtw_write8(rtwdev, REG_TRXFF_BNDY + 1, value8);
    1021                 :          0 :         rtw_write32_set(rtwdev, REG_RCR, BIT_APP_PHYSTS);
    1022                 :          0 :         rtw_write32_clr(rtwdev, REG_WMAC_OPTION_FUNCTION + 4, BIT(8) | BIT(9));
    1023                 :            : 
    1024                 :          0 :         return 0;
    1025                 :            : }
    1026                 :            : 
    1027                 :          0 : int rtw_mac_init(struct rtw_dev *rtwdev)
    1028                 :            : {
    1029                 :          0 :         struct rtw_chip_info *chip = rtwdev->chip;
    1030                 :          0 :         int ret;
    1031                 :            : 
    1032                 :          0 :         ret = rtw_init_trx_cfg(rtwdev);
    1033         [ #  # ]:          0 :         if (ret)
    1034                 :            :                 return ret;
    1035                 :            : 
    1036                 :          0 :         ret = chip->ops->mac_init(rtwdev);
    1037         [ #  # ]:          0 :         if (ret)
    1038                 :            :                 return ret;
    1039                 :            : 
    1040                 :          0 :         ret = rtw_drv_info_cfg(rtwdev);
    1041         [ #  # ]:          0 :         if (ret)
    1042                 :            :                 return ret;
    1043                 :            : 
    1044                 :          0 :         rtw_hci_interface_cfg(rtwdev);
    1045                 :            : 
    1046                 :          0 :         return 0;
    1047                 :            : }

Generated by: LCOV version 1.14