1// SPDX-License-Identifier: GPL-2.0-only
2/* r8169_firmware.c: RealTek 8169/8168/8101 ethernet driver.
3 *
4 * Copyright (c) 2002 ShuChen <shuchen@realtek.com.tw>
5 * Copyright (c) 2003 - 2007 Francois Romieu <romieu@fr.zoreil.com>
6 * Copyright (c) a lot of people too. Please respect their work.
7 *
8 * See MAINTAINERS file for support contact information.
9 */
10
11#include <linux/delay.h>
12#include <linux/firmware.h>
13
14#include "r8169_firmware.h"
15
16enum rtl_fw_opcode {
17	PHY_READ		= 0x0,
18	PHY_DATA_OR		= 0x1,
19	PHY_DATA_AND		= 0x2,
20	PHY_BJMPN		= 0x3,
21	PHY_MDIO_CHG		= 0x4,
22	PHY_CLEAR_READCOUNT	= 0x7,
23	PHY_WRITE		= 0x8,
24	PHY_READCOUNT_EQ_SKIP	= 0x9,
25	PHY_COMP_EQ_SKIPN	= 0xa,
26	PHY_COMP_NEQ_SKIPN	= 0xb,
27	PHY_WRITE_PREVIOUS	= 0xc,
28	PHY_SKIPN		= 0xd,
29	PHY_DELAY_MS		= 0xe,
30};
31
32struct fw_info {
33	u32	magic;
34	char	version[RTL_VER_SIZE];
35	__le32	fw_start;
36	__le32	fw_len;
37	u8	chksum;
38} __packed;
39
40#define FW_OPCODE_SIZE sizeof_field(struct rtl_fw_phy_action, code[0])
41
42static bool rtl_fw_format_ok(struct rtl_fw *rtl_fw)
43{
44	const struct firmware *fw = rtl_fw->fw;
45	struct fw_info *fw_info = (struct fw_info *)fw->data;
46	struct rtl_fw_phy_action *pa = &rtl_fw->phy_action;
47
48	if (fw->size < FW_OPCODE_SIZE)
49		return false;
50
51	if (!fw_info->magic) {
52		size_t i, size, start;
53		u8 checksum = 0;
54
55		if (fw->size < sizeof(*fw_info))
56			return false;
57
58		for (i = 0; i < fw->size; i++)
59			checksum += fw->data[i];
60		if (checksum != 0)
61			return false;
62
63		start = le32_to_cpu(fw_info->fw_start);
64		if (start > fw->size)
65			return false;
66
67		size = le32_to_cpu(fw_info->fw_len);
68		if (size > (fw->size - start) / FW_OPCODE_SIZE)
69			return false;
70
71		strscpy(rtl_fw->version, fw_info->version, RTL_VER_SIZE);
72
73		pa->code = (__le32 *)(fw->data + start);
74		pa->size = size;
75	} else {
76		if (fw->size % FW_OPCODE_SIZE)
77			return false;
78
79		strscpy(rtl_fw->version, rtl_fw->fw_name, RTL_VER_SIZE);
80
81		pa->code = (__le32 *)fw->data;
82		pa->size = fw->size / FW_OPCODE_SIZE;
83	}
84
85	return true;
86}
87
88static bool rtl_fw_data_ok(struct rtl_fw *rtl_fw)
89{
90	struct rtl_fw_phy_action *pa = &rtl_fw->phy_action;
91	size_t index;
92
93	for (index = 0; index < pa->size; index++) {
94		u32 action = le32_to_cpu(pa->code[index]);
95		u32 val = action & 0x0000ffff;
96		u32 regno = (action & 0x0fff0000) >> 16;
97
98		switch (action >> 28) {
99		case PHY_READ:
100		case PHY_DATA_OR:
101		case PHY_DATA_AND:
102		case PHY_CLEAR_READCOUNT:
103		case PHY_WRITE:
104		case PHY_WRITE_PREVIOUS:
105		case PHY_DELAY_MS:
106			break;
107
108		case PHY_MDIO_CHG:
109			if (val > 1)
110				goto out;
111			break;
112
113		case PHY_BJMPN:
114			if (regno > index)
115				goto out;
116			break;
117		case PHY_READCOUNT_EQ_SKIP:
118			if (index + 2 >= pa->size)
119				goto out;
120			break;
121		case PHY_COMP_EQ_SKIPN:
122		case PHY_COMP_NEQ_SKIPN:
123		case PHY_SKIPN:
124			if (index + 1 + regno >= pa->size)
125				goto out;
126			break;
127
128		default:
129			dev_err(rtl_fw->dev, "Invalid action 0x%08x\n", action);
130			return false;
131		}
132	}
133
134	return true;
135out:
136	dev_err(rtl_fw->dev, "Out of range of firmware\n");
137	return false;
138}
139
140void rtl_fw_write_firmware(struct rtl8169_private *tp, struct rtl_fw *rtl_fw)
141{
142	struct rtl_fw_phy_action *pa = &rtl_fw->phy_action;
143	rtl_fw_write_t fw_write = rtl_fw->phy_write;
144	rtl_fw_read_t fw_read = rtl_fw->phy_read;
145	int predata = 0, count = 0;
146	size_t index;
147
148	for (index = 0; index < pa->size; index++) {
149		u32 action = le32_to_cpu(pa->code[index]);
150		u32 data = action & 0x0000ffff;
151		u32 regno = (action & 0x0fff0000) >> 16;
152		enum rtl_fw_opcode opcode = action >> 28;
153
154		switch (opcode) {
155		case PHY_READ:
156			predata = fw_read(tp, regno);
157			count++;
158			break;
159		case PHY_DATA_OR:
160			predata |= data;
161			break;
162		case PHY_DATA_AND:
163			predata &= data;
164			break;
165		case PHY_BJMPN:
166			index -= (regno + 1);
167			break;
168		case PHY_MDIO_CHG:
169			if (data) {
170				fw_write = rtl_fw->mac_mcu_write;
171				fw_read = rtl_fw->mac_mcu_read;
172			} else {
173				fw_write = rtl_fw->phy_write;
174				fw_read = rtl_fw->phy_read;
175			}
176
177			break;
178		case PHY_CLEAR_READCOUNT:
179			count = 0;
180			break;
181		case PHY_WRITE:
182			fw_write(tp, regno, data);
183			break;
184		case PHY_READCOUNT_EQ_SKIP:
185			if (count == data)
186				index++;
187			break;
188		case PHY_COMP_EQ_SKIPN:
189			if (predata == data)
190				index += regno;
191			break;
192		case PHY_COMP_NEQ_SKIPN:
193			if (predata != data)
194				index += regno;
195			break;
196		case PHY_WRITE_PREVIOUS:
197			fw_write(tp, regno, predata);
198			break;
199		case PHY_SKIPN:
200			index += regno;
201			break;
202		case PHY_DELAY_MS:
203			msleep(data);
204			break;
205		}
206	}
207}
208
209void rtl_fw_release_firmware(struct rtl_fw *rtl_fw)
210{
211	release_firmware(rtl_fw->fw);
212}
213
214int rtl_fw_request_firmware(struct rtl_fw *rtl_fw)
215{
216	int rc;
217
218	rc = request_firmware(&rtl_fw->fw, rtl_fw->fw_name, rtl_fw->dev);
219	if (rc < 0)
220		goto out;
221
222	if (!rtl_fw_format_ok(rtl_fw) || !rtl_fw_data_ok(rtl_fw)) {
223		release_firmware(rtl_fw->fw);
224		rc = -EINVAL;
225		goto out;
226	}
227
228	return 0;
229out:
230	dev_err(rtl_fw->dev, "Unable to load firmware %s (%d)\n",
231		rtl_fw->fw_name, rc);
232	return rc;
233}
234