cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

usb_mcu.c (6360B)


      1// SPDX-License-Identifier: ISC
      2/*
      3 * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
      4 */
      5
      6#include <linux/firmware.h>
      7
      8#include "mt76x2u.h"
      9#include "eeprom.h"
     10#include "../mt76x02_usb.h"
     11
     12#define MT_CMD_HDR_LEN			4
     13
     14#define MCU_FW_URB_MAX_PAYLOAD		0x3900
     15#define MCU_ROM_PATCH_MAX_PAYLOAD	2048
     16
     17#define MT76U_MCU_ILM_OFFSET		0x80000
     18#define MT76U_MCU_DLM_OFFSET		0x110000
     19#define MT76U_MCU_ROM_PATCH_OFFSET	0x90000
     20
     21static void mt76x2u_mcu_load_ivb(struct mt76x02_dev *dev)
     22{
     23	mt76u_vendor_request(&dev->mt76, MT_VEND_DEV_MODE,
     24			     USB_DIR_OUT | USB_TYPE_VENDOR,
     25			     0x12, 0, NULL, 0);
     26}
     27
     28static void mt76x2u_mcu_enable_patch(struct mt76x02_dev *dev)
     29{
     30	struct mt76_usb *usb = &dev->mt76.usb;
     31	static const u8 data[] = {
     32		0x6f, 0xfc, 0x08, 0x01,
     33		0x20, 0x04, 0x00, 0x00,
     34		0x00, 0x09, 0x00,
     35	};
     36
     37	memcpy(usb->data, data, sizeof(data));
     38	mt76u_vendor_request(&dev->mt76, MT_VEND_DEV_MODE,
     39			     USB_DIR_OUT | USB_TYPE_CLASS,
     40			     0x12, 0, usb->data, sizeof(data));
     41}
     42
     43static void mt76x2u_mcu_reset_wmt(struct mt76x02_dev *dev)
     44{
     45	struct mt76_usb *usb = &dev->mt76.usb;
     46	u8 data[] = {
     47		0x6f, 0xfc, 0x05, 0x01,
     48		0x07, 0x01, 0x00, 0x04
     49	};
     50
     51	memcpy(usb->data, data, sizeof(data));
     52	mt76u_vendor_request(&dev->mt76, MT_VEND_DEV_MODE,
     53			     USB_DIR_OUT | USB_TYPE_CLASS,
     54			     0x12, 0, usb->data, sizeof(data));
     55}
     56
     57static int mt76x2u_mcu_load_rom_patch(struct mt76x02_dev *dev)
     58{
     59	bool rom_protect = !is_mt7612(dev);
     60	struct mt76x02_patch_header *hdr;
     61	u32 val, patch_mask, patch_reg;
     62	const struct firmware *fw;
     63	int err;
     64
     65	if (rom_protect &&
     66	    !mt76_poll_msec(dev, MT_MCU_SEMAPHORE_03, 1, 1, 600)) {
     67		dev_err(dev->mt76.dev,
     68			"could not get hardware semaphore for ROM PATCH\n");
     69		return -ETIMEDOUT;
     70	}
     71
     72	if (mt76xx_rev(dev) >= MT76XX_REV_E3) {
     73		patch_mask = BIT(0);
     74		patch_reg = MT_MCU_CLOCK_CTL;
     75	} else {
     76		patch_mask = BIT(1);
     77		patch_reg = MT_MCU_COM_REG0;
     78	}
     79
     80	if (rom_protect && (mt76_rr(dev, patch_reg) & patch_mask)) {
     81		dev_info(dev->mt76.dev, "ROM patch already applied\n");
     82		return 0;
     83	}
     84
     85	err = request_firmware(&fw, MT7662_ROM_PATCH, dev->mt76.dev);
     86	if (err < 0)
     87		return err;
     88
     89	if (!fw || !fw->data || fw->size <= sizeof(*hdr)) {
     90		dev_err(dev->mt76.dev, "failed to load firmware\n");
     91		err = -EIO;
     92		goto out;
     93	}
     94
     95	hdr = (struct mt76x02_patch_header *)fw->data;
     96	dev_info(dev->mt76.dev, "ROM patch build: %.15s\n", hdr->build_time);
     97
     98	/* enable USB_DMA_CFG */
     99	val = MT_USB_DMA_CFG_RX_BULK_EN |
    100	      MT_USB_DMA_CFG_TX_BULK_EN |
    101	      FIELD_PREP(MT_USB_DMA_CFG_RX_BULK_AGG_TOUT, 0x20);
    102	mt76_wr(dev, MT_VEND_ADDR(CFG, MT_USB_U3DMA_CFG), val);
    103
    104	/* vendor reset */
    105	mt76x02u_mcu_fw_reset(dev);
    106	usleep_range(5000, 10000);
    107
    108	/* enable FCE to send in-band cmd */
    109	mt76_wr(dev, MT_FCE_PSE_CTRL, 0x1);
    110	/* FCE tx_fs_base_ptr */
    111	mt76_wr(dev, MT_TX_CPU_FROM_FCE_BASE_PTR, 0x400230);
    112	/* FCE tx_fs_max_cnt */
    113	mt76_wr(dev, MT_TX_CPU_FROM_FCE_MAX_COUNT, 0x1);
    114	/* FCE pdma enable */
    115	mt76_wr(dev, MT_FCE_PDMA_GLOBAL_CONF, 0x44);
    116	/* FCE skip_fs_en */
    117	mt76_wr(dev, MT_FCE_SKIP_FS, 0x3);
    118
    119	err = mt76x02u_mcu_fw_send_data(dev, fw->data + sizeof(*hdr),
    120					fw->size - sizeof(*hdr),
    121					MCU_ROM_PATCH_MAX_PAYLOAD,
    122					MT76U_MCU_ROM_PATCH_OFFSET);
    123	if (err < 0) {
    124		err = -EIO;
    125		goto out;
    126	}
    127
    128	mt76x2u_mcu_enable_patch(dev);
    129	mt76x2u_mcu_reset_wmt(dev);
    130	mdelay(20);
    131
    132	if (!mt76_poll_msec(dev, patch_reg, patch_mask, patch_mask, 100)) {
    133		dev_err(dev->mt76.dev, "failed to load ROM patch\n");
    134		err = -ETIMEDOUT;
    135	}
    136
    137out:
    138	if (rom_protect)
    139		mt76_wr(dev, MT_MCU_SEMAPHORE_03, 1);
    140	release_firmware(fw);
    141	return err;
    142}
    143
    144static int mt76x2u_mcu_load_firmware(struct mt76x02_dev *dev)
    145{
    146	u32 val, dlm_offset = MT76U_MCU_DLM_OFFSET;
    147	const struct mt76x02_fw_header *hdr;
    148	int err, len, ilm_len, dlm_len;
    149	const struct firmware *fw;
    150
    151	err = request_firmware(&fw, MT7662_FIRMWARE, dev->mt76.dev);
    152	if (err < 0)
    153		return err;
    154
    155	if (!fw || !fw->data || fw->size < sizeof(*hdr)) {
    156		err = -EINVAL;
    157		goto out;
    158	}
    159
    160	hdr = (const struct mt76x02_fw_header *)fw->data;
    161	ilm_len = le32_to_cpu(hdr->ilm_len);
    162	dlm_len = le32_to_cpu(hdr->dlm_len);
    163	len = sizeof(*hdr) + ilm_len + dlm_len;
    164	if (fw->size != len) {
    165		err = -EINVAL;
    166		goto out;
    167	}
    168
    169	val = le16_to_cpu(hdr->fw_ver);
    170	dev_info(dev->mt76.dev, "Firmware Version: %d.%d.%02d\n",
    171		 (val >> 12) & 0xf, (val >> 8) & 0xf, val & 0xf);
    172
    173	val = le16_to_cpu(hdr->build_ver);
    174	dev_info(dev->mt76.dev, "Build: %x\n", val);
    175	dev_info(dev->mt76.dev, "Build Time: %.16s\n", hdr->build_time);
    176
    177	/* vendor reset */
    178	mt76x02u_mcu_fw_reset(dev);
    179	usleep_range(5000, 10000);
    180
    181	/* enable USB_DMA_CFG */
    182	val = MT_USB_DMA_CFG_RX_BULK_EN |
    183	      MT_USB_DMA_CFG_TX_BULK_EN |
    184	      FIELD_PREP(MT_USB_DMA_CFG_RX_BULK_AGG_TOUT, 0x20);
    185	mt76_wr(dev, MT_VEND_ADDR(CFG, MT_USB_U3DMA_CFG), val);
    186	/* enable FCE to send in-band cmd */
    187	mt76_wr(dev, MT_FCE_PSE_CTRL, 0x1);
    188	/* FCE tx_fs_base_ptr */
    189	mt76_wr(dev, MT_TX_CPU_FROM_FCE_BASE_PTR, 0x400230);
    190	/* FCE tx_fs_max_cnt */
    191	mt76_wr(dev, MT_TX_CPU_FROM_FCE_MAX_COUNT, 0x1);
    192	/* FCE pdma enable */
    193	mt76_wr(dev, MT_FCE_PDMA_GLOBAL_CONF, 0x44);
    194	/* FCE skip_fs_en */
    195	mt76_wr(dev, MT_FCE_SKIP_FS, 0x3);
    196
    197	/* load ILM */
    198	err = mt76x02u_mcu_fw_send_data(dev, fw->data + sizeof(*hdr),
    199					ilm_len, MCU_FW_URB_MAX_PAYLOAD,
    200					MT76U_MCU_ILM_OFFSET);
    201	if (err < 0) {
    202		err = -EIO;
    203		goto out;
    204	}
    205
    206	/* load DLM */
    207	if (mt76xx_rev(dev) >= MT76XX_REV_E3)
    208		dlm_offset += 0x800;
    209	err = mt76x02u_mcu_fw_send_data(dev, fw->data + sizeof(*hdr) + ilm_len,
    210					dlm_len, MCU_FW_URB_MAX_PAYLOAD,
    211					dlm_offset);
    212	if (err < 0) {
    213		err = -EIO;
    214		goto out;
    215	}
    216
    217	mt76x2u_mcu_load_ivb(dev);
    218	if (!mt76_poll_msec(dev, MT_MCU_COM_REG0, 1, 1, 100)) {
    219		dev_err(dev->mt76.dev, "firmware failed to start\n");
    220		err = -ETIMEDOUT;
    221		goto out;
    222	}
    223
    224	mt76_set(dev, MT_MCU_COM_REG0, BIT(1));
    225	/* enable FCE to send in-band cmd */
    226	mt76_wr(dev, MT_FCE_PSE_CTRL, 0x1);
    227	mt76x02_set_ethtool_fwver(dev, hdr);
    228	dev_dbg(dev->mt76.dev, "firmware running\n");
    229
    230out:
    231	release_firmware(fw);
    232	return err;
    233}
    234
    235int mt76x2u_mcu_fw_init(struct mt76x02_dev *dev)
    236{
    237	int err;
    238
    239	err = mt76x2u_mcu_load_rom_patch(dev);
    240	if (err < 0)
    241		return err;
    242
    243	return mt76x2u_mcu_load_firmware(dev);
    244}
    245
    246int mt76x2u_mcu_init(struct mt76x02_dev *dev)
    247{
    248	int err;
    249
    250	err = mt76x02_mcu_function_select(dev, Q_SELECT, 1);
    251	if (err < 0)
    252		return err;
    253
    254	return mt76x02_mcu_set_radio_state(dev, true);
    255}