Linux-libre 5.3.12-gnu
[librecmc/linux-libre.git] / drivers / net / wireless / mediatek / mt76 / mt76x0 / pci_mcu.c
1 /*
2  * Copyright (C) 2018 Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>
3  *
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.
7  *
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.
15  */
16 #include <linux/kernel.h>
17 #include <linux/firmware.h>
18
19 #include "mt76x0.h"
20 #include "mcu.h"
21
22 #define MT_MCU_IVB_ADDR         (MT_MCU_ILM_ADDR + 0x54000 - MT_MCU_IVB_SIZE)
23
24 static int mt76x0e_load_firmware(struct mt76x02_dev *dev)
25 {
26         bool is_combo_chip = mt76_chip(&dev->mt76) != 0x7610;
27         u32 val, ilm_len, dlm_len, offset = 0;
28         const struct mt76x02_fw_header *hdr;
29         const struct firmware *fw;
30         const char *firmware;
31         const u8 *fw_payload;
32         int len, err;
33
34         if (is_combo_chip)
35                 firmware = MT7650E_FIRMWARE;
36         else
37                 firmware = MT7610E_FIRMWARE;
38
39         err = reject_firmware(&fw, firmware, dev->mt76.dev);
40         if (err)
41                 return err;
42
43         if (!fw || !fw->data || fw->size < sizeof(*hdr)) {
44                 err = -EIO;
45                 goto out;
46         }
47
48         hdr = (const struct mt76x02_fw_header *)fw->data;
49
50         len = sizeof(*hdr);
51         len += le32_to_cpu(hdr->ilm_len);
52         len += le32_to_cpu(hdr->dlm_len);
53
54         if (fw->size != len) {
55                 err = -EIO;
56                 goto out;
57         }
58
59         fw_payload = fw->data + sizeof(*hdr);
60
61         val = le16_to_cpu(hdr->fw_ver);
62         dev_info(dev->mt76.dev, "Firmware Version: %d.%d.%02d\n",
63                  (val >> 12) & 0xf, (val >> 8) & 0xf, val & 0xf);
64
65         val = le16_to_cpu(hdr->fw_ver);
66         dev_dbg(dev->mt76.dev,
67                 "Firmware Version: %d.%d.%02d Build: %x Build time: %.16s\n",
68                 (val >> 12) & 0xf, (val >> 8) & 0xf, val & 0xf,
69                 le16_to_cpu(hdr->build_ver), hdr->build_time);
70
71         if (is_combo_chip && !mt76_poll(dev, MT_MCU_SEMAPHORE_00, 1, 1, 600)) {
72                 dev_err(dev->mt76.dev,
73                         "Could not get hardware semaphore for loading fw\n");
74                 err = -ETIMEDOUT;
75                 goto out;
76         }
77
78         /* upload ILM. */
79         mt76_wr(dev, MT_MCU_PCIE_REMAP_BASE4, 0);
80         ilm_len = le32_to_cpu(hdr->ilm_len);
81         if (is_combo_chip) {
82                 ilm_len -= MT_MCU_IVB_SIZE;
83                 offset = MT_MCU_IVB_SIZE;
84         }
85         dev_dbg(dev->mt76.dev, "loading FW - ILM %u\n", ilm_len);
86         mt76_wr_copy(dev, MT_MCU_ILM_ADDR + offset, fw_payload + offset,
87                      ilm_len);
88
89         /* upload IVB. */
90         if (is_combo_chip) {
91                 dev_dbg(dev->mt76.dev, "loading FW - IVB %u\n",
92                         MT_MCU_IVB_SIZE);
93                 mt76_wr_copy(dev, MT_MCU_IVB_ADDR, fw_payload, MT_MCU_IVB_SIZE);
94         }
95
96         /* upload DLM. */
97         mt76_wr(dev, MT_MCU_PCIE_REMAP_BASE4, MT_MCU_DLM_OFFSET);
98         dlm_len = le32_to_cpu(hdr->dlm_len);
99         dev_dbg(dev->mt76.dev, "loading FW - DLM %u\n", dlm_len);
100         mt76_wr_copy(dev, MT_MCU_ILM_ADDR,
101                      fw_payload + le32_to_cpu(hdr->ilm_len), dlm_len);
102
103         /* trigger firmware */
104         mt76_wr(dev, MT_MCU_PCIE_REMAP_BASE4, 0);
105         if (is_combo_chip)
106                 mt76_wr(dev, MT_MCU_INT_LEVEL, 0x3);
107         else
108                 mt76_wr(dev, MT_MCU_RESET_CTL, 0x300);
109
110         if (!mt76_poll_msec(dev, MT_MCU_COM_REG0, 1, 1, 1000)) {
111                 dev_err(dev->mt76.dev, "Firmware failed to start\n");
112                 err = -ETIMEDOUT;
113                 goto out;
114         }
115
116         mt76x02_set_ethtool_fwver(dev, hdr);
117         dev_dbg(dev->mt76.dev, "Firmware running!\n");
118
119 out:
120         if (is_combo_chip)
121                 mt76_wr(dev, MT_MCU_SEMAPHORE_00, 0x1);
122         release_firmware(fw);
123
124         return err;
125 }
126
127 int mt76x0e_mcu_init(struct mt76x02_dev *dev)
128 {
129         static const struct mt76_mcu_ops mt76x0e_mcu_ops = {
130                 .mcu_send_msg = mt76x02_mcu_msg_send,
131         };
132         int err;
133
134         dev->mt76.mcu_ops = &mt76x0e_mcu_ops;
135
136         err = mt76x0e_load_firmware(dev);
137         if (err < 0)
138                 return err;
139
140         set_bit(MT76_STATE_MCU_RUNNING, &dev->mt76.state);
141
142         return 0;
143 }