linux/drivers/staging/rtl8192e/rtl8192e/r8192E_firmware.c
<<
>>
Prefs
   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
  14static 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
  26static 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
  51static 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
  95static 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        }
 126out:
 127        release_firmware(fw);
 128        return ret;
 129}
 130
 131bool 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
 194download_firmware_fail:
 195        netdev_err(dev, "%s: Failed to initialize firmware.\n", __func__);
 196        return false;
 197}
 198