1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 ################################################################################
4 #
5 # r8168 is the Linux device driver released for Realtek Gigabit Ethernet
6 # controllers with PCI-Express interface.
7 #
8 # Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved.
9 #
10 # This program is free software; you can redistribute it and/or modify it
11 # under the terms of the GNU General Public License as published by the Free
12 # Software Foundation; either version 2 of the License, or (at your option)
13 # any later version.
14 #
15 # This program is distributed in the hope that it will be useful, but WITHOUT
16 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
18 # more details.
19 #
20 # You should have received a copy of the GNU General Public License along with
21 # this program; if not, see <http://www.gnu.org/licenses/>.
22 #
23 # Author:
24 # Realtek NIC software team <nicfae@realtek.com>
25 # No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan
26 #
27 ################################################################################
28 */
29
30 /************************************************************************************
31 * This product is covered by one or more of the following patents:
32 * US6,570,884, US6,115,776, and US6,327,625.
33 ***********************************************************************************/
34
35 #include <linux/version.h>
36 #include <linux/delay.h>
37 #include <linux/firmware.h>
38
39 #include "r8168_firmware.h"
40
41 enum rtl_fw_opcode {
42 PHY_READ = 0x0,
43 PHY_DATA_OR = 0x1,
44 PHY_DATA_AND = 0x2,
45 PHY_BJMPN = 0x3,
46 PHY_MDIO_CHG = 0x4,
47 PHY_CLEAR_READCOUNT = 0x7,
48 PHY_WRITE = 0x8,
49 PHY_READCOUNT_EQ_SKIP = 0x9,
50 PHY_COMP_EQ_SKIPN = 0xa,
51 PHY_COMP_NEQ_SKIPN = 0xb,
52 PHY_WRITE_PREVIOUS = 0xc,
53 PHY_SKIPN = 0xd,
54 PHY_DELAY_MS = 0xe,
55 };
56
57 struct fw_info {
58 u32 magic;
59 char version[RTL8168_VER_SIZE];
60 __le32 fw_start;
61 __le32 fw_len;
62 u8 chksum;
63 } __packed;
64
65 #if LINUX_VERSION_CODE < KERNEL_VERSION(4,16,0)
66 #define sizeof_field(TYPE, MEMBER) sizeof((((TYPE *)0)->MEMBER))
67 #endif
68 #define FW_OPCODE_SIZE sizeof_field(struct rtl8168_fw_phy_action, code[0])
69
rtl8168_fw_format_ok(struct rtl8168_fw * rtl_fw)70 static bool rtl8168_fw_format_ok(struct rtl8168_fw *rtl_fw)
71 {
72 const struct firmware *fw = rtl_fw->fw;
73 struct fw_info *fw_info = (struct fw_info *)fw->data;
74 struct rtl8168_fw_phy_action *pa = &rtl_fw->phy_action;
75
76 if (fw->size < FW_OPCODE_SIZE)
77 return false;
78
79 if (!fw_info->magic) {
80 size_t i, size, start;
81 u8 checksum = 0;
82
83 if (fw->size < sizeof(*fw_info))
84 return false;
85
86 for (i = 0; i < fw->size; i++)
87 checksum += fw->data[i];
88 if (checksum != 0)
89 return false;
90
91 start = le32_to_cpu(fw_info->fw_start);
92 if (start > fw->size)
93 return false;
94
95 size = le32_to_cpu(fw_info->fw_len);
96 if (size > (fw->size - start) / FW_OPCODE_SIZE)
97 return false;
98
99 strscpy(rtl_fw->version, fw_info->version, RTL8168_VER_SIZE);
100
101 pa->code = (__le32 *)(fw->data + start);
102 pa->size = size;
103 } else {
104 if (fw->size % FW_OPCODE_SIZE)
105 return false;
106
107 strscpy(rtl_fw->version, rtl_fw->fw_name, RTL8168_VER_SIZE);
108
109 pa->code = (__le32 *)fw->data;
110 pa->size = fw->size / FW_OPCODE_SIZE;
111 }
112
113 return true;
114 }
115
rtl8168_fw_data_ok(struct rtl8168_fw * rtl_fw)116 static bool rtl8168_fw_data_ok(struct rtl8168_fw *rtl_fw)
117 {
118 struct rtl8168_fw_phy_action *pa = &rtl_fw->phy_action;
119 size_t index;
120
121 for (index = 0; index < pa->size; index++) {
122 u32 action = le32_to_cpu(pa->code[index]);
123 u32 val = action & 0x0000ffff;
124 u32 regno = (action & 0x0fff0000) >> 16;
125
126 switch (action >> 28) {
127 case PHY_READ:
128 case PHY_DATA_OR:
129 case PHY_DATA_AND:
130 case PHY_CLEAR_READCOUNT:
131 case PHY_WRITE:
132 case PHY_WRITE_PREVIOUS:
133 case PHY_DELAY_MS:
134 break;
135
136 case PHY_MDIO_CHG:
137 if (val > 1)
138 goto out;
139 break;
140
141 case PHY_BJMPN:
142 if (regno > index)
143 goto out;
144 break;
145 case PHY_READCOUNT_EQ_SKIP:
146 if (index + 2 >= pa->size)
147 goto out;
148 break;
149 case PHY_COMP_EQ_SKIPN:
150 case PHY_COMP_NEQ_SKIPN:
151 case PHY_SKIPN:
152 if (index + 1 + regno >= pa->size)
153 goto out;
154 break;
155
156 default:
157 dev_err(rtl_fw->dev, "Invalid action 0x%08x\n", action);
158 return false;
159 }
160 }
161
162 return true;
163 out:
164 dev_err(rtl_fw->dev, "Out of range of firmware\n");
165 return false;
166 }
167
rtl8168_fw_write_firmware(struct rtl8168_private * tp,struct rtl8168_fw * rtl_fw)168 void rtl8168_fw_write_firmware(struct rtl8168_private *tp, struct rtl8168_fw *rtl_fw)
169 {
170 struct rtl8168_fw_phy_action *pa = &rtl_fw->phy_action;
171 rtl8168_fw_write_t fw_write = rtl_fw->phy_write;
172 rtl8168_fw_read_t fw_read = rtl_fw->phy_read;
173 int predata = 0, count = 0;
174 size_t index;
175
176 for (index = 0; index < pa->size; index++) {
177 u32 action = le32_to_cpu(pa->code[index]);
178 u32 data = action & 0x0000ffff;
179 u32 regno = (action & 0x0fff0000) >> 16;
180 enum rtl_fw_opcode opcode = action >> 28;
181
182 if (!action)
183 break;
184
185 switch (opcode) {
186 case PHY_READ:
187 predata = fw_read(tp, regno);
188 count++;
189 break;
190 case PHY_DATA_OR:
191 predata |= data;
192 break;
193 case PHY_DATA_AND:
194 predata &= data;
195 break;
196 case PHY_BJMPN:
197 index -= (regno + 1);
198 break;
199 case PHY_MDIO_CHG:
200 if (data) {
201 fw_write = rtl_fw->mac_mcu_write;
202 fw_read = rtl_fw->mac_mcu_read;
203 } else {
204 fw_write = rtl_fw->phy_write;
205 fw_read = rtl_fw->phy_read;
206 }
207
208 break;
209 case PHY_CLEAR_READCOUNT:
210 count = 0;
211 break;
212 case PHY_WRITE:
213 fw_write(tp, regno, data);
214 break;
215 case PHY_READCOUNT_EQ_SKIP:
216 if (count == data)
217 index++;
218 break;
219 case PHY_COMP_EQ_SKIPN:
220 if (predata == data)
221 index += regno;
222 break;
223 case PHY_COMP_NEQ_SKIPN:
224 if (predata != data)
225 index += regno;
226 break;
227 case PHY_WRITE_PREVIOUS:
228 fw_write(tp, regno, predata);
229 break;
230 case PHY_SKIPN:
231 index += regno;
232 break;
233 case PHY_DELAY_MS:
234 mdelay(data);
235 break;
236 }
237 }
238 }
239
rtl8168_fw_release_firmware(struct rtl8168_fw * rtl_fw)240 void rtl8168_fw_release_firmware(struct rtl8168_fw *rtl_fw)
241 {
242 release_firmware(rtl_fw->fw);
243 }
244
rtl8168_fw_request_firmware(struct rtl8168_fw * rtl_fw)245 int rtl8168_fw_request_firmware(struct rtl8168_fw *rtl_fw)
246 {
247 int rc;
248
249 rc = request_firmware(&rtl_fw->fw, rtl_fw->fw_name, rtl_fw->dev);
250 if (rc < 0)
251 goto out;
252
253 if (!rtl8168_fw_format_ok(rtl_fw) || !rtl8168_fw_data_ok(rtl_fw)) {
254 release_firmware(rtl_fw->fw);
255 rc = -EINVAL;
256 goto out;
257 }
258
259 return 0;
260 out:
261 dev_err(rtl_fw->dev, "Unable to load firmware %s (%d)\n",
262 rtl_fw->fw_name, rc);
263 return rc;
264 }
265