2 * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 #include <linux/firmware.h>
21 #include "../mt76x02_usb.h"
23 #define MT_CMD_HDR_LEN 4
25 #define MCU_FW_URB_MAX_PAYLOAD 0x3900
26 #define MCU_ROM_PATCH_MAX_PAYLOAD 2048
28 #define MT76U_MCU_ILM_OFFSET 0x80000
29 #define MT76U_MCU_DLM_OFFSET 0x110000
30 #define MT76U_MCU_ROM_PATCH_OFFSET 0x90000
32 static void mt76x2u_mcu_load_ivb(struct mt76x02_dev
*dev
)
34 mt76u_vendor_request(&dev
->mt76
, MT_VEND_DEV_MODE
,
35 USB_DIR_OUT
| USB_TYPE_VENDOR
,
39 static void mt76x2u_mcu_enable_patch(struct mt76x02_dev
*dev
)
41 struct mt76_usb
*usb
= &dev
->mt76
.usb
;
42 static const u8 data
[] = {
43 0x6f, 0xfc, 0x08, 0x01,
44 0x20, 0x04, 0x00, 0x00,
48 memcpy(usb
->data
, data
, sizeof(data
));
49 mt76u_vendor_request(&dev
->mt76
, MT_VEND_DEV_MODE
,
50 USB_DIR_OUT
| USB_TYPE_CLASS
,
51 0x12, 0, usb
->data
, sizeof(data
));
54 static void mt76x2u_mcu_reset_wmt(struct mt76x02_dev
*dev
)
56 struct mt76_usb
*usb
= &dev
->mt76
.usb
;
58 0x6f, 0xfc, 0x05, 0x01,
59 0x07, 0x01, 0x00, 0x04
62 memcpy(usb
->data
, data
, sizeof(data
));
63 mt76u_vendor_request(&dev
->mt76
, MT_VEND_DEV_MODE
,
64 USB_DIR_OUT
| USB_TYPE_CLASS
,
65 0x12, 0, usb
->data
, sizeof(data
));
68 static int mt76x2u_mcu_load_rom_patch(struct mt76x02_dev
*dev
)
70 bool rom_protect
= !is_mt7612(dev
);
71 struct mt76x02_patch_header
*hdr
;
72 u32 val
, patch_mask
, patch_reg
;
73 const struct firmware
*fw
;
77 !mt76_poll_msec(dev
, MT_MCU_SEMAPHORE_03
, 1, 1, 600)) {
78 dev_err(dev
->mt76
.dev
,
79 "could not get hardware semaphore for ROM PATCH\n");
83 if (mt76xx_rev(dev
) >= MT76XX_REV_E3
) {
85 patch_reg
= MT_MCU_CLOCK_CTL
;
88 patch_reg
= MT_MCU_COM_REG0
;
91 if (rom_protect
&& (mt76_rr(dev
, patch_reg
) & patch_mask
)) {
92 dev_info(dev
->mt76
.dev
, "ROM patch already applied\n");
96 err
= request_firmware(&fw
, MT7662_ROM_PATCH
, dev
->mt76
.dev
);
100 if (!fw
|| !fw
->data
|| fw
->size
<= sizeof(*hdr
)) {
101 dev_err(dev
->mt76
.dev
, "failed to load firmware\n");
106 hdr
= (struct mt76x02_patch_header
*)fw
->data
;
107 dev_info(dev
->mt76
.dev
, "ROM patch build: %.15s\n", hdr
->build_time
);
109 /* enable USB_DMA_CFG */
110 val
= MT_USB_DMA_CFG_RX_BULK_EN
|
111 MT_USB_DMA_CFG_TX_BULK_EN
|
112 FIELD_PREP(MT_USB_DMA_CFG_RX_BULK_AGG_TOUT
, 0x20);
113 mt76_wr(dev
, MT_VEND_ADDR(CFG
, MT_USB_U3DMA_CFG
), val
);
116 mt76x02u_mcu_fw_reset(dev
);
117 usleep_range(5000, 10000);
119 /* enable FCE to send in-band cmd */
120 mt76_wr(dev
, MT_FCE_PSE_CTRL
, 0x1);
121 /* FCE tx_fs_base_ptr */
122 mt76_wr(dev
, MT_TX_CPU_FROM_FCE_BASE_PTR
, 0x400230);
123 /* FCE tx_fs_max_cnt */
124 mt76_wr(dev
, MT_TX_CPU_FROM_FCE_MAX_COUNT
, 0x1);
125 /* FCE pdma enable */
126 mt76_wr(dev
, MT_FCE_PDMA_GLOBAL_CONF
, 0x44);
128 mt76_wr(dev
, MT_FCE_SKIP_FS
, 0x3);
130 err
= mt76x02u_mcu_fw_send_data(dev
, fw
->data
+ sizeof(*hdr
),
131 fw
->size
- sizeof(*hdr
),
132 MCU_ROM_PATCH_MAX_PAYLOAD
,
133 MT76U_MCU_ROM_PATCH_OFFSET
);
139 mt76x2u_mcu_enable_patch(dev
);
140 mt76x2u_mcu_reset_wmt(dev
);
143 if (!mt76_poll_msec(dev
, patch_reg
, patch_mask
, patch_mask
, 100)) {
144 dev_err(dev
->mt76
.dev
, "failed to load ROM patch\n");
150 mt76_wr(dev
, MT_MCU_SEMAPHORE_03
, 1);
151 release_firmware(fw
);
155 static int mt76x2u_mcu_load_firmware(struct mt76x02_dev
*dev
)
157 u32 val
, dlm_offset
= MT76U_MCU_DLM_OFFSET
;
158 const struct mt76x02_fw_header
*hdr
;
159 int err
, len
, ilm_len
, dlm_len
;
160 const struct firmware
*fw
;
162 err
= request_firmware(&fw
, MT7662_FIRMWARE
, dev
->mt76
.dev
);
166 if (!fw
|| !fw
->data
|| fw
->size
< sizeof(*hdr
)) {
171 hdr
= (const struct mt76x02_fw_header
*)fw
->data
;
172 ilm_len
= le32_to_cpu(hdr
->ilm_len
);
173 dlm_len
= le32_to_cpu(hdr
->dlm_len
);
174 len
= sizeof(*hdr
) + ilm_len
+ dlm_len
;
175 if (fw
->size
!= len
) {
180 val
= le16_to_cpu(hdr
->fw_ver
);
181 dev_info(dev
->mt76
.dev
, "Firmware Version: %d.%d.%02d\n",
182 (val
>> 12) & 0xf, (val
>> 8) & 0xf, val
& 0xf);
184 val
= le16_to_cpu(hdr
->build_ver
);
185 dev_info(dev
->mt76
.dev
, "Build: %x\n", val
);
186 dev_info(dev
->mt76
.dev
, "Build Time: %.16s\n", hdr
->build_time
);
189 mt76x02u_mcu_fw_reset(dev
);
190 usleep_range(5000, 10000);
192 /* enable USB_DMA_CFG */
193 val
= MT_USB_DMA_CFG_RX_BULK_EN
|
194 MT_USB_DMA_CFG_TX_BULK_EN
|
195 FIELD_PREP(MT_USB_DMA_CFG_RX_BULK_AGG_TOUT
, 0x20);
196 mt76_wr(dev
, MT_VEND_ADDR(CFG
, MT_USB_U3DMA_CFG
), val
);
197 /* enable FCE to send in-band cmd */
198 mt76_wr(dev
, MT_FCE_PSE_CTRL
, 0x1);
199 /* FCE tx_fs_base_ptr */
200 mt76_wr(dev
, MT_TX_CPU_FROM_FCE_BASE_PTR
, 0x400230);
201 /* FCE tx_fs_max_cnt */
202 mt76_wr(dev
, MT_TX_CPU_FROM_FCE_MAX_COUNT
, 0x1);
203 /* FCE pdma enable */
204 mt76_wr(dev
, MT_FCE_PDMA_GLOBAL_CONF
, 0x44);
206 mt76_wr(dev
, MT_FCE_SKIP_FS
, 0x3);
209 err
= mt76x02u_mcu_fw_send_data(dev
, fw
->data
+ sizeof(*hdr
),
210 ilm_len
, MCU_FW_URB_MAX_PAYLOAD
,
211 MT76U_MCU_ILM_OFFSET
);
218 if (mt76xx_rev(dev
) >= MT76XX_REV_E3
)
220 err
= mt76x02u_mcu_fw_send_data(dev
, fw
->data
+ sizeof(*hdr
) + ilm_len
,
221 dlm_len
, MCU_FW_URB_MAX_PAYLOAD
,
228 mt76x2u_mcu_load_ivb(dev
);
229 if (!mt76_poll_msec(dev
, MT_MCU_COM_REG0
, 1, 1, 100)) {
230 dev_err(dev
->mt76
.dev
, "firmware failed to start\n");
235 mt76_set(dev
, MT_MCU_COM_REG0
, BIT(1));
236 /* enable FCE to send in-band cmd */
237 mt76_wr(dev
, MT_FCE_PSE_CTRL
, 0x1);
238 mt76x02_set_ethtool_fwver(dev
, hdr
);
239 dev_dbg(dev
->mt76
.dev
, "firmware running\n");
242 release_firmware(fw
);
246 int mt76x2u_mcu_fw_init(struct mt76x02_dev
*dev
)
250 err
= mt76x2u_mcu_load_rom_patch(dev
);
254 return mt76x2u_mcu_load_firmware(dev
);
257 int mt76x2u_mcu_init(struct mt76x02_dev
*dev
)
261 err
= mt76x02_mcu_function_select(dev
, Q_SELECT
, 1);
265 return mt76x02_mcu_set_radio_state(dev
, true);