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

pci_mcu.c (4528B)


      1// SPDX-License-Identifier: ISC
      2/*
      3 * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
      4 */
      5
      6#include <linux/kernel.h>
      7#include <linux/firmware.h>
      8#include <linux/delay.h>
      9
     10#include "mt76x2.h"
     11#include "mcu.h"
     12#include "eeprom.h"
     13
     14static int
     15mt76pci_load_rom_patch(struct mt76x02_dev *dev)
     16{
     17	const struct firmware *fw = NULL;
     18	struct mt76x02_patch_header *hdr;
     19	bool rom_protect = !is_mt7612(dev);
     20	int len, ret = 0;
     21	__le32 *cur;
     22	u32 patch_mask, patch_reg;
     23
     24	if (rom_protect && !mt76_poll(dev, MT_MCU_SEMAPHORE_03, 1, 1, 600)) {
     25		dev_err(dev->mt76.dev,
     26			"Could not get hardware semaphore for ROM PATCH\n");
     27		return -ETIMEDOUT;
     28	}
     29
     30	if (mt76xx_rev(dev) >= MT76XX_REV_E3) {
     31		patch_mask = BIT(0);
     32		patch_reg = MT_MCU_CLOCK_CTL;
     33	} else {
     34		patch_mask = BIT(1);
     35		patch_reg = MT_MCU_COM_REG0;
     36	}
     37
     38	if (rom_protect && (mt76_rr(dev, patch_reg) & patch_mask)) {
     39		dev_info(dev->mt76.dev, "ROM patch already applied\n");
     40		goto out;
     41	}
     42
     43	ret = request_firmware(&fw, MT7662_ROM_PATCH, dev->mt76.dev);
     44	if (ret)
     45		goto out;
     46
     47	if (!fw || !fw->data || fw->size <= sizeof(*hdr)) {
     48		ret = -EIO;
     49		dev_err(dev->mt76.dev, "Failed to load firmware\n");
     50		goto out;
     51	}
     52
     53	hdr = (struct mt76x02_patch_header *)fw->data;
     54	dev_info(dev->mt76.dev, "ROM patch build: %.15s\n", hdr->build_time);
     55
     56	mt76_wr(dev, MT_MCU_PCIE_REMAP_BASE4, MT_MCU_ROM_PATCH_OFFSET);
     57
     58	cur = (__le32 *)(fw->data + sizeof(*hdr));
     59	len = fw->size - sizeof(*hdr);
     60	mt76_wr_copy(dev, MT_MCU_ROM_PATCH_ADDR, cur, len);
     61
     62	mt76_wr(dev, MT_MCU_PCIE_REMAP_BASE4, 0);
     63
     64	/* Trigger ROM */
     65	mt76_wr(dev, MT_MCU_INT_LEVEL, 4);
     66
     67	if (!mt76_poll_msec(dev, patch_reg, patch_mask, patch_mask, 2000)) {
     68		dev_err(dev->mt76.dev, "Failed to load ROM patch\n");
     69		ret = -ETIMEDOUT;
     70	}
     71
     72out:
     73	/* release semaphore */
     74	if (rom_protect)
     75		mt76_wr(dev, MT_MCU_SEMAPHORE_03, 1);
     76	release_firmware(fw);
     77	return ret;
     78}
     79
     80static int
     81mt76pci_load_firmware(struct mt76x02_dev *dev)
     82{
     83	const struct firmware *fw;
     84	const struct mt76x02_fw_header *hdr;
     85	int len, ret;
     86	__le32 *cur;
     87	u32 offset, val;
     88
     89	ret = request_firmware(&fw, MT7662_FIRMWARE, dev->mt76.dev);
     90	if (ret)
     91		return ret;
     92
     93	if (!fw || !fw->data || fw->size < sizeof(*hdr))
     94		goto error;
     95
     96	hdr = (const struct mt76x02_fw_header *)fw->data;
     97
     98	len = sizeof(*hdr);
     99	len += le32_to_cpu(hdr->ilm_len);
    100	len += le32_to_cpu(hdr->dlm_len);
    101
    102	if (fw->size != len)
    103		goto error;
    104
    105	val = le16_to_cpu(hdr->fw_ver);
    106	dev_info(dev->mt76.dev, "Firmware Version: %d.%d.%02d\n",
    107		 (val >> 12) & 0xf, (val >> 8) & 0xf, val & 0xf);
    108
    109	val = le16_to_cpu(hdr->build_ver);
    110	dev_info(dev->mt76.dev, "Build: %x\n", val);
    111	dev_info(dev->mt76.dev, "Build Time: %.16s\n", hdr->build_time);
    112
    113	cur = (__le32 *)(fw->data + sizeof(*hdr));
    114	len = le32_to_cpu(hdr->ilm_len);
    115
    116	mt76_wr(dev, MT_MCU_PCIE_REMAP_BASE4, MT_MCU_ILM_OFFSET);
    117	mt76_wr_copy(dev, MT_MCU_ILM_ADDR, cur, len);
    118
    119	cur += len / sizeof(*cur);
    120	len = le32_to_cpu(hdr->dlm_len);
    121
    122	if (mt76xx_rev(dev) >= MT76XX_REV_E3)
    123		offset = MT_MCU_DLM_ADDR_E3;
    124	else
    125		offset = MT_MCU_DLM_ADDR;
    126
    127	mt76_wr(dev, MT_MCU_PCIE_REMAP_BASE4, MT_MCU_DLM_OFFSET);
    128	mt76_wr_copy(dev, offset, cur, len);
    129
    130	mt76_wr(dev, MT_MCU_PCIE_REMAP_BASE4, 0);
    131
    132	val = mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_2);
    133	if (FIELD_GET(MT_EE_NIC_CONF_2_XTAL_OPTION, val) == 1)
    134		mt76_set(dev, MT_MCU_COM_REG0, BIT(30));
    135
    136	/* trigger firmware */
    137	mt76_wr(dev, MT_MCU_INT_LEVEL, 2);
    138	if (!mt76_poll_msec(dev, MT_MCU_COM_REG0, 1, 1, 200)) {
    139		dev_err(dev->mt76.dev, "Firmware failed to start\n");
    140		release_firmware(fw);
    141		return -ETIMEDOUT;
    142	}
    143
    144	mt76x02_set_ethtool_fwver(dev, hdr);
    145	dev_info(dev->mt76.dev, "Firmware running!\n");
    146
    147	release_firmware(fw);
    148
    149	return ret;
    150
    151error:
    152	dev_err(dev->mt76.dev, "Invalid firmware\n");
    153	release_firmware(fw);
    154	return -ENOENT;
    155}
    156
    157static int
    158mt76pci_mcu_restart(struct mt76_dev *mdev)
    159{
    160	struct mt76x02_dev *dev;
    161	int ret;
    162
    163	dev = container_of(mdev, struct mt76x02_dev, mt76);
    164
    165	mt76x02_mcu_cleanup(dev);
    166	mt76x2_mac_reset(dev, true);
    167
    168	ret = mt76pci_load_firmware(dev);
    169	if (ret)
    170		return ret;
    171
    172	mt76_wr(dev, MT_WPDMA_RST_IDX, ~0);
    173
    174	return 0;
    175}
    176
    177int mt76x2_mcu_init(struct mt76x02_dev *dev)
    178{
    179	static const struct mt76_mcu_ops mt76x2_mcu_ops = {
    180		.mcu_restart = mt76pci_mcu_restart,
    181		.mcu_send_msg = mt76x02_mcu_msg_send,
    182		.mcu_parse_response = mt76x02_mcu_parse_response,
    183	};
    184	int ret;
    185
    186	dev->mt76.mcu_ops = &mt76x2_mcu_ops;
    187
    188	ret = mt76pci_load_rom_patch(dev);
    189	if (ret)
    190		return ret;
    191
    192	ret = mt76pci_load_firmware(dev);
    193	if (ret)
    194		return ret;
    195
    196	mt76x02_mcu_function_select(dev, Q_SELECT, 1);
    197	return 0;
    198}