root/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. _rtl92e_wait_for_fw
  2. _rtl92e_fw_boot_cpu
  3. _rtl92e_fw_check_ready
  4. _rtl92e_fw_prepare
  5. rtl92e_init_fw

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
   4  *
   5  * Contact Information: wlanfae <wlanfae@realtek.com>
   6  */
   7 #include "rtl_core.h"
   8 #include "r8192E_hw.h"
   9 #include "r8192E_hwimg.h"
  10 #include "r8192E_firmware.h"
  11 #include "r8192E_cmdpkt.h"
  12 #include <linux/firmware.h>
  13 
  14 static bool _rtl92e_wait_for_fw(struct net_device *dev, u32 mask, u32 timeout)
  15 {
  16         unsigned long deadline = jiffies + msecs_to_jiffies(timeout);
  17 
  18         while (time_before(jiffies, deadline)) {
  19                 if (rtl92e_readl(dev, CPU_GEN) & mask)
  20                         return true;
  21                 mdelay(2);
  22         }
  23         return false;
  24 }
  25 
  26 static bool _rtl92e_fw_boot_cpu(struct net_device *dev)
  27 {
  28         u32             CPU_status = 0;
  29 
  30         if (!_rtl92e_wait_for_fw(dev, CPU_GEN_PUT_CODE_OK, 200)) {
  31                 netdev_err(dev, "Firmware download failed.\n");
  32                 return false;
  33         }
  34         netdev_dbg(dev, "Download Firmware: Put code ok!\n");
  35 
  36         CPU_status = rtl92e_readl(dev, CPU_GEN);
  37         rtl92e_writeb(dev, CPU_GEN,
  38                       (u8)((CPU_status|CPU_GEN_PWR_STB_CPU)&0xff));
  39         mdelay(1);
  40 
  41         if (!_rtl92e_wait_for_fw(dev, CPU_GEN_BOOT_RDY, 200)) {
  42                 netdev_err(dev, "Firmware boot failed.\n");
  43                 return false;
  44         }
  45 
  46         netdev_dbg(dev, "Download Firmware: Boot ready!\n");
  47 
  48         return true;
  49 }
  50 
  51 static bool _rtl92e_fw_check_ready(struct net_device *dev,
  52                                    u8 load_fw_status)
  53 {
  54         struct r8192_priv *priv = rtllib_priv(dev);
  55         struct rt_firmware *pfirmware = priv->pFirmware;
  56         bool rt_status  = true;
  57 
  58         switch (load_fw_status) {
  59         case FW_INIT_STEP0_BOOT:
  60                 pfirmware->status = FW_STATUS_1_MOVE_BOOT_CODE;
  61                 break;
  62 
  63         case FW_INIT_STEP1_MAIN:
  64                 pfirmware->status = FW_STATUS_2_MOVE_MAIN_CODE;
  65 
  66                 rt_status = _rtl92e_fw_boot_cpu(dev);
  67                 if (rt_status)
  68                         pfirmware->status = FW_STATUS_3_TURNON_CPU;
  69                 else
  70                         netdev_dbg(dev, "_rtl92e_fw_boot_cpu fail!\n");
  71 
  72                 break;
  73 
  74         case FW_INIT_STEP2_DATA:
  75                 pfirmware->status = FW_STATUS_4_MOVE_DATA_CODE;
  76                 mdelay(1);
  77 
  78                 rt_status = _rtl92e_wait_for_fw(dev, CPU_GEN_FIRM_RDY, 20);
  79                 if (rt_status)
  80                         pfirmware->status = FW_STATUS_5_READY;
  81                 else
  82                         RT_TRACE(COMP_FIRMWARE,
  83                                  "_rtl92e_is_fw_ready fail(%d)!\n",
  84                                  rt_status);
  85                 break;
  86         default:
  87                 rt_status = false;
  88                 netdev_dbg(dev, "Unknown firmware status");
  89                 break;
  90         }
  91 
  92         return rt_status;
  93 }
  94 
  95 static bool _rtl92e_fw_prepare(struct net_device *dev, struct rt_fw_blob *blob,
  96                                const char *name, u8 padding)
  97 {
  98         const struct firmware *fw;
  99         int rc, i;
 100         bool ret = true;
 101 
 102         rc = request_firmware(&fw, name, &dev->dev);
 103         if (rc < 0)
 104                 return false;
 105 
 106         if (round_up(fw->size, 4) > MAX_FW_SIZE - padding) {
 107                 netdev_err(dev, "Firmware image %s too big for the device.\n",
 108                            name);
 109                 ret = false;
 110                 goto out;
 111         }
 112 
 113         if (padding)
 114                 memset(blob->data, 0, padding);
 115         if (fw->size % 4)
 116                 memset(blob->data + padding + fw->size, 0, 4);
 117         memcpy(blob->data + padding, fw->data, fw->size);
 118 
 119         blob->size = round_up(fw->size, 4) + padding;
 120 
 121         /* Swap endian - firmware is packaged in invalid endiannes*/
 122         for (i = padding; i < blob->size; i += 4) {
 123                 u32 *data = (u32 *)(blob->data + i);
 124                 *data = swab32p(data);
 125         }
 126 out:
 127         release_firmware(fw);
 128         return ret;
 129 }
 130 
 131 bool rtl92e_init_fw(struct net_device *dev)
 132 {
 133         struct r8192_priv *priv = rtllib_priv(dev);
 134         bool                    rt_status = true;
 135 
 136         u32     file_length = 0;
 137         u8      *mapped_file = NULL;
 138         u8      i = 0;
 139         enum opt_rst_type rst_opt = OPT_SYSTEM_RESET;
 140         enum firmware_init_step starting_state = FW_INIT_STEP0_BOOT;
 141 
 142         struct rt_firmware *pfirmware = priv->pFirmware;
 143 
 144         netdev_dbg(dev, " PlatformInitFirmware()==>\n");
 145 
 146         if (pfirmware->status == FW_STATUS_0_INIT) {
 147                 rst_opt = OPT_SYSTEM_RESET;
 148                 starting_state = FW_INIT_STEP0_BOOT;
 149 
 150         } else if (pfirmware->status == FW_STATUS_5_READY) {
 151                 rst_opt = OPT_FIRMWARE_RESET;
 152                 starting_state = FW_INIT_STEP2_DATA;
 153         } else {
 154                 RT_TRACE(COMP_FIRMWARE,
 155                          "PlatformInitFirmware: undefined firmware state\n");
 156         }
 157 
 158         for (i = starting_state; i <= FW_INIT_STEP2_DATA; i++) {
 159                 if (rst_opt == OPT_SYSTEM_RESET) {
 160                         if (pfirmware->blobs[i].size == 0) {
 161                                 const char *fw_name[3] = {
 162                                         RTL8192E_BOOT_IMG_FW,
 163                                         RTL8192E_MAIN_IMG_FW,
 164                                         RTL8192E_DATA_IMG_FW
 165                                 };
 166                                 int pad = 0;
 167 
 168                                 if (i == FW_INIT_STEP1_MAIN)
 169                                         pad = 128;
 170 
 171                                 if (!_rtl92e_fw_prepare(dev,
 172                                                         &pfirmware->blobs[i],
 173                                                         fw_name[i],
 174                                                         pad))
 175                                         goto download_firmware_fail;
 176                         }
 177                 }
 178 
 179                 mapped_file = pfirmware->blobs[i].data;
 180                 file_length = pfirmware->blobs[i].size;
 181 
 182                 rt_status = rtl92e_send_cmd_pkt(dev, DESC_PACKET_TYPE_INIT,
 183                                                 mapped_file, file_length);
 184                 if (!rt_status)
 185                         goto download_firmware_fail;
 186 
 187                 if (!_rtl92e_fw_check_ready(dev, i))
 188                         goto download_firmware_fail;
 189         }
 190 
 191         netdev_dbg(dev, "Firmware Download Success\n");
 192         return rt_status;
 193 
 194 download_firmware_fail:
 195         netdev_err(dev, "%s: Failed to initialize firmware.\n", __func__);
 196         return false;
 197 }

/* [<][>][^][v][top][bottom][index][help] */