234 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/* 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