root/drivers/net/wireless/mediatek/mt76/mt76x0/usb_mcu.c

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

DEFINITIONS

This source file includes following definitions.
  1. mt76x0u_upload_firmware
  2. mt76x0_get_firmware
  3. mt76x0u_load_firmware
  4. mt76x0u_mcu_init

   1 // SPDX-License-Identifier: ISC
   2 /*
   3  * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
   4  */
   5 #include <linux/kernel.h>
   6 #include <linux/firmware.h>
   7 #include <linux/module.h>
   8 
   9 #include "mt76x0.h"
  10 #include "mcu.h"
  11 #include "../mt76x02_usb.h"
  12 
  13 #define MCU_FW_URB_MAX_PAYLOAD          0x38f8
  14 #define MCU_FW_URB_SIZE                 (MCU_FW_URB_MAX_PAYLOAD + 12)
  15 
  16 static int
  17 mt76x0u_upload_firmware(struct mt76x02_dev *dev,
  18                         const struct mt76x02_fw_header *hdr)
  19 {
  20         u8 *fw_payload = (u8 *)(hdr + 1);
  21         u32 ilm_len, dlm_len;
  22         void *ivb;
  23         int err;
  24 
  25         ivb = kmemdup(fw_payload, MT_MCU_IVB_SIZE, GFP_KERNEL);
  26         if (!ivb)
  27                 return -ENOMEM;
  28 
  29         ilm_len = le32_to_cpu(hdr->ilm_len) - MT_MCU_IVB_SIZE;
  30         dev_dbg(dev->mt76.dev, "loading FW - ILM %u + IVB %u\n",
  31                 ilm_len, MT_MCU_IVB_SIZE);
  32         err = mt76x02u_mcu_fw_send_data(dev, fw_payload + MT_MCU_IVB_SIZE,
  33                                         ilm_len, MCU_FW_URB_MAX_PAYLOAD,
  34                                         MT_MCU_IVB_SIZE);
  35         if (err)
  36                 goto out;
  37 
  38         dlm_len = le32_to_cpu(hdr->dlm_len);
  39         dev_dbg(dev->mt76.dev, "loading FW - DLM %u\n", dlm_len);
  40         err = mt76x02u_mcu_fw_send_data(dev,
  41                                         fw_payload + le32_to_cpu(hdr->ilm_len),
  42                                         dlm_len, MCU_FW_URB_MAX_PAYLOAD,
  43                                         MT_MCU_DLM_OFFSET);
  44         if (err)
  45                 goto out;
  46 
  47         err = mt76u_vendor_request(&dev->mt76, MT_VEND_DEV_MODE,
  48                                    USB_DIR_OUT | USB_TYPE_VENDOR,
  49                                    0x12, 0, ivb, MT_MCU_IVB_SIZE);
  50         if (err < 0)
  51                 goto out;
  52 
  53         if (!mt76_poll_msec(dev, MT_MCU_COM_REG0, 1, 1, 1000)) {
  54                 dev_err(dev->mt76.dev, "Firmware failed to start\n");
  55                 err = -ETIMEDOUT;
  56                 goto out;
  57         }
  58 
  59         dev_dbg(dev->mt76.dev, "Firmware running!\n");
  60 
  61 out:
  62         kfree(ivb);
  63 
  64         return err;
  65 }
  66 
  67 static int mt76x0_get_firmware(struct mt76x02_dev *dev,
  68                                const struct firmware **fw)
  69 {
  70         int err;
  71 
  72         /* try to load mt7610e fw if available
  73          * otherwise fall back to mt7610u one
  74          */
  75         err = firmware_request_nowarn(fw, MT7610E_FIRMWARE, dev->mt76.dev);
  76         if (err) {
  77                 dev_info(dev->mt76.dev, "%s not found, switching to %s",
  78                          MT7610E_FIRMWARE, MT7610U_FIRMWARE);
  79                 return request_firmware(fw, MT7610U_FIRMWARE,
  80                                         dev->mt76.dev);
  81         }
  82         return 0;
  83 }
  84 
  85 static int mt76x0u_load_firmware(struct mt76x02_dev *dev)
  86 {
  87         const struct firmware *fw;
  88         const struct mt76x02_fw_header *hdr;
  89         int len, ret;
  90         u32 val;
  91 
  92         mt76_wr(dev, MT_USB_DMA_CFG, (MT_USB_DMA_CFG_RX_BULK_EN |
  93                                       MT_USB_DMA_CFG_TX_BULK_EN));
  94 
  95         if (mt76x0_firmware_running(dev))
  96                 return 0;
  97 
  98         ret = mt76x0_get_firmware(dev, &fw);
  99         if (ret)
 100                 return ret;
 101 
 102         if (!fw || !fw->data || fw->size < sizeof(*hdr))
 103                 goto err_inv_fw;
 104 
 105         hdr = (const struct mt76x02_fw_header *)fw->data;
 106 
 107         if (le32_to_cpu(hdr->ilm_len) <= MT_MCU_IVB_SIZE)
 108                 goto err_inv_fw;
 109 
 110         len = sizeof(*hdr);
 111         len += le32_to_cpu(hdr->ilm_len);
 112         len += le32_to_cpu(hdr->dlm_len);
 113 
 114         if (fw->size != len)
 115                 goto err_inv_fw;
 116 
 117         val = le16_to_cpu(hdr->fw_ver);
 118         dev_dbg(dev->mt76.dev,
 119                 "Firmware Version: %d.%d.%02d Build: %x Build time: %.16s\n",
 120                 (val >> 12) & 0xf, (val >> 8) & 0xf, val & 0xf,
 121                 le16_to_cpu(hdr->build_ver), hdr->build_time);
 122 
 123         len = le32_to_cpu(hdr->ilm_len);
 124 
 125         mt76_wr(dev, 0x1004, 0x2c);
 126 
 127         mt76_set(dev, MT_USB_DMA_CFG,
 128                  (MT_USB_DMA_CFG_RX_BULK_EN | MT_USB_DMA_CFG_TX_BULK_EN) |
 129                  FIELD_PREP(MT_USB_DMA_CFG_RX_BULK_AGG_TOUT, 0x20));
 130         mt76x02u_mcu_fw_reset(dev);
 131         usleep_range(5000, 6000);
 132 
 133         mt76_wr(dev, MT_FCE_PSE_CTRL, 1);
 134 
 135         /* FCE tx_fs_base_ptr */
 136         mt76_wr(dev, MT_TX_CPU_FROM_FCE_BASE_PTR, 0x400230);
 137         /* FCE tx_fs_max_cnt */
 138         mt76_wr(dev, MT_TX_CPU_FROM_FCE_MAX_COUNT, 1);
 139         /* FCE pdma enable */
 140         mt76_wr(dev, MT_FCE_PDMA_GLOBAL_CONF, 0x44);
 141         /* FCE skip_fs_en */
 142         mt76_wr(dev, MT_FCE_SKIP_FS, 3);
 143 
 144         val = mt76_rr(dev, MT_USB_DMA_CFG);
 145         val |= MT_USB_DMA_CFG_UDMA_TX_WL_DROP;
 146         mt76_wr(dev, MT_USB_DMA_CFG, val);
 147         val &= ~MT_USB_DMA_CFG_UDMA_TX_WL_DROP;
 148         mt76_wr(dev, MT_USB_DMA_CFG, val);
 149 
 150         ret = mt76x0u_upload_firmware(dev, hdr);
 151         release_firmware(fw);
 152 
 153         mt76_wr(dev, MT_FCE_PSE_CTRL, 1);
 154 
 155         return ret;
 156 
 157 err_inv_fw:
 158         dev_err(dev->mt76.dev, "Invalid firmware image\n");
 159         release_firmware(fw);
 160         return -ENOENT;
 161 }
 162 
 163 int mt76x0u_mcu_init(struct mt76x02_dev *dev)
 164 {
 165         int ret;
 166 
 167         ret = mt76x0u_load_firmware(dev);
 168         if (ret < 0)
 169                 return ret;
 170 
 171         set_bit(MT76_STATE_MCU_RUNNING, &dev->mt76.state);
 172 
 173         return 0;
 174 }

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