1 // SPDX-License-Identifier: GPL-2.0 2 3 #include <linux/bitfield.h> 4 #include <linux/of.h> 5 #include <linux/firmware.h> 6 #include <linux/crc-itu-t.h> 7 #include <linux/nvmem-consumer.h> 8 9 #include <asm/unaligned.h> 10 11 #include "aquantia.h" 12 13 #define UP_RESET_SLEEP 100 14 15 /* addresses of memory segments in the phy */ 16 #define DRAM_BASE_ADDR 0x3FFE0000 17 #define IRAM_BASE_ADDR 0x40000000 18 19 /* firmware image format constants */ 20 #define VERSION_STRING_SIZE 0x40 21 #define VERSION_STRING_OFFSET 0x0200 22 /* primary offset is written at an offset from the start of the fw blob */ 23 #define PRIMARY_OFFSET_OFFSET 0x8 24 /* primary offset needs to be then added to a base offset */ 25 #define PRIMARY_OFFSET_SHIFT 12 26 #define PRIMARY_OFFSET(x) ((x) << PRIMARY_OFFSET_SHIFT) 27 #define HEADER_OFFSET 0x300 28 29 struct aqr_fw_header { 30 u32 padding; 31 u8 iram_offset[3]; 32 u8 iram_size[3]; 33 u8 dram_offset[3]; 34 u8 dram_size[3]; 35 } __packed; 36 37 enum aqr_fw_src { 38 AQR_FW_SRC_NVMEM = 0, 39 AQR_FW_SRC_FS, 40 }; 41 42 static const char * const aqr_fw_src_string[] = { 43 [AQR_FW_SRC_NVMEM] = "NVMEM", 44 [AQR_FW_SRC_FS] = "FS", 45 }; 46 47 /* AQR firmware doesn't have fixed offsets for iram and dram section 48 * but instead provide an header with the offset to use on reading 49 * and parsing the firmware. 50 * 51 * AQR firmware can't be trusted and each offset is validated to be 52 * not negative and be in the size of the firmware itself. 53 */ 54 static bool aqr_fw_validate_get(size_t size, size_t offset, size_t get_size) 55 { 56 return offset + get_size <= size; 57 } 58 59 static int aqr_fw_get_be16(const u8 *data, size_t offset, size_t size, u16 *value) 60 { 61 if (!aqr_fw_validate_get(size, offset, sizeof(u16))) 62 return -EINVAL; 63 64 *value = get_unaligned_be16(data + offset); 65 66 return 0; 67 } 68 69 static int aqr_fw_get_le16(const u8 *data, size_t offset, size_t size, u16 *value) 70 { 71 if (!aqr_fw_validate_get(size, offset, sizeof(u16))) 72 return -EINVAL; 73 74 *value = get_unaligned_le16(data + offset); 75 76 return 0; 77 } 78 79 static int aqr_fw_get_le24(const u8 *data, size_t offset, size_t size, u32 *value) 80 { 81 if (!aqr_fw_validate_get(size, offset, sizeof(u8) * 3)) 82 return -EINVAL; 83 84 *value = get_unaligned_le24(data + offset); 85 86 return 0; 87 } 88 89 /* load data into the phy's memory */ 90 static int aqr_fw_load_memory(struct phy_device *phydev, u32 addr, 91 const u8 *data, size_t len) 92 { 93 u16 crc = 0, up_crc; 94 size_t pos; 95 96 phy_write_mmd(phydev, MDIO_MMD_VEND1, 97 VEND1_GLOBAL_MAILBOX_INTERFACE1, 98 VEND1_GLOBAL_MAILBOX_INTERFACE1_CRC_RESET); 99 phy_write_mmd(phydev, MDIO_MMD_VEND1, 100 VEND1_GLOBAL_MAILBOX_INTERFACE3, 101 VEND1_GLOBAL_MAILBOX_INTERFACE3_MSW_ADDR(addr)); 102 phy_write_mmd(phydev, MDIO_MMD_VEND1, 103 VEND1_GLOBAL_MAILBOX_INTERFACE4, 104 VEND1_GLOBAL_MAILBOX_INTERFACE4_LSW_ADDR(addr)); 105 106 /* We assume and enforce the size to be word aligned. 107 * If a firmware that is not word aligned is found, please report upstream. 108 */ 109 for (pos = 0; pos < len; pos += sizeof(u32)) { 110 u8 crc_data[4]; 111 u32 word; 112 113 /* FW data is always stored in little-endian */ 114 word = get_unaligned_le32((const u32 *)(data + pos)); 115 116 phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_MAILBOX_INTERFACE5, 117 VEND1_GLOBAL_MAILBOX_INTERFACE5_MSW_DATA(word)); 118 phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_MAILBOX_INTERFACE6, 119 VEND1_GLOBAL_MAILBOX_INTERFACE6_LSW_DATA(word)); 120 121 phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_MAILBOX_INTERFACE1, 122 VEND1_GLOBAL_MAILBOX_INTERFACE1_EXECUTE | 123 VEND1_GLOBAL_MAILBOX_INTERFACE1_WRITE); 124 125 /* Word is swapped internally and MAILBOX CRC is calculated 126 * using big-endian order. Mimic what the PHY does to have a 127 * matching CRC... 128 */ 129 crc_data[0] = word >> 24; 130 crc_data[1] = word >> 16; 131 crc_data[2] = word >> 8; 132 crc_data[3] = word; 133 134 /* ...calculate CRC as we load data... */ 135 crc = crc_itu_t(crc, crc_data, sizeof(crc_data)); 136 } 137 /* ...gets CRC from MAILBOX after we have loaded the entire section... */ 138 up_crc = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_MAILBOX_INTERFACE2); 139 /* ...and make sure it does match our calculated CRC */ 140 if (crc != up_crc) { 141 phydev_err(phydev, "CRC mismatch: calculated 0x%04x PHY 0x%04x\n", 142 crc, up_crc); 143 return -EINVAL; 144 } 145 146 return 0; 147 } 148 149 static int aqr_fw_boot(struct phy_device *phydev, const u8 *data, size_t size, 150 enum aqr_fw_src fw_src) 151 { 152 u16 calculated_crc, read_crc, read_primary_offset; 153 u32 iram_offset = 0, iram_size = 0; 154 u32 dram_offset = 0, dram_size = 0; 155 char version[VERSION_STRING_SIZE]; 156 u32 primary_offset = 0; 157 int ret; 158 159 /* extract saved CRC at the end of the fw 160 * CRC is saved in big-endian as PHY is BE 161 */ 162 ret = aqr_fw_get_be16(data, size - sizeof(u16), size, &read_crc); 163 if (ret) { 164 phydev_err(phydev, "bad firmware CRC in firmware\n"); 165 return ret; 166 } 167 calculated_crc = crc_itu_t(0, data, size - sizeof(u16)); 168 if (read_crc != calculated_crc) { 169 phydev_err(phydev, "bad firmware CRC: file 0x%04x calculated 0x%04x\n", 170 read_crc, calculated_crc); 171 return -EINVAL; 172 } 173 174 /* Get the primary offset to extract DRAM and IRAM sections. */ 175 ret = aqr_fw_get_le16(data, PRIMARY_OFFSET_OFFSET, size, &read_primary_offset); 176 if (ret) { 177 phydev_err(phydev, "bad primary offset in firmware\n"); 178 return ret; 179 } 180 primary_offset = PRIMARY_OFFSET(read_primary_offset); 181 182 /* Find the DRAM and IRAM sections within the firmware file. 183 * Make sure the fw_header is correctly in the firmware. 184 */ 185 if (!aqr_fw_validate_get(size, primary_offset + HEADER_OFFSET, 186 sizeof(struct aqr_fw_header))) { 187 phydev_err(phydev, "bad fw_header in firmware\n"); 188 return -EINVAL; 189 } 190 191 /* offset are in LE and values needs to be converted to cpu endian */ 192 ret = aqr_fw_get_le24(data, primary_offset + HEADER_OFFSET + 193 offsetof(struct aqr_fw_header, iram_offset), 194 size, &iram_offset); 195 if (ret) { 196 phydev_err(phydev, "bad iram offset in firmware\n"); 197 return ret; 198 } 199 ret = aqr_fw_get_le24(data, primary_offset + HEADER_OFFSET + 200 offsetof(struct aqr_fw_header, iram_size), 201 size, &iram_size); 202 if (ret) { 203 phydev_err(phydev, "invalid iram size in firmware\n"); 204 return ret; 205 } 206 ret = aqr_fw_get_le24(data, primary_offset + HEADER_OFFSET + 207 offsetof(struct aqr_fw_header, dram_offset), 208 size, &dram_offset); 209 if (ret) { 210 phydev_err(phydev, "bad dram offset in firmware\n"); 211 return ret; 212 } 213 ret = aqr_fw_get_le24(data, primary_offset + HEADER_OFFSET + 214 offsetof(struct aqr_fw_header, dram_size), 215 size, &dram_size); 216 if (ret) { 217 phydev_err(phydev, "invalid dram size in firmware\n"); 218 return ret; 219 } 220 221 /* Increment the offset with the primary offset. 222 * Validate iram/dram offset and size. 223 */ 224 iram_offset += primary_offset; 225 if (iram_size % sizeof(u32)) { 226 phydev_err(phydev, "iram size if not aligned to word size. Please report this upstream!\n"); 227 return -EINVAL; 228 } 229 if (!aqr_fw_validate_get(size, iram_offset, iram_size)) { 230 phydev_err(phydev, "invalid iram offset for iram size\n"); 231 return -EINVAL; 232 } 233 234 dram_offset += primary_offset; 235 if (dram_size % sizeof(u32)) { 236 phydev_err(phydev, "dram size if not aligned to word size. Please report this upstream!\n"); 237 return -EINVAL; 238 } 239 if (!aqr_fw_validate_get(size, dram_offset, dram_size)) { 240 phydev_err(phydev, "invalid iram offset for iram size\n"); 241 return -EINVAL; 242 } 243 244 phydev_dbg(phydev, "primary %d IRAM offset=%d size=%d DRAM offset=%d size=%d\n", 245 primary_offset, iram_offset, iram_size, dram_offset, dram_size); 246 247 if (!aqr_fw_validate_get(size, dram_offset + VERSION_STRING_OFFSET, 248 VERSION_STRING_SIZE)) { 249 phydev_err(phydev, "invalid version in firmware\n"); 250 return -EINVAL; 251 } 252 strscpy(version, (char *)data + dram_offset + VERSION_STRING_OFFSET, 253 VERSION_STRING_SIZE); 254 if (version[0] == '\0') { 255 phydev_err(phydev, "invalid version in firmware\n"); 256 return -EINVAL; 257 } 258 phydev_info(phydev, "loading firmware version '%s' from '%s'\n", version, 259 aqr_fw_src_string[fw_src]); 260 261 /* stall the microcprocessor */ 262 phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_CONTROL2, 263 VEND1_GLOBAL_CONTROL2_UP_RUN_STALL | VEND1_GLOBAL_CONTROL2_UP_RUN_STALL_OVD); 264 265 phydev_dbg(phydev, "loading DRAM 0x%08x from offset=%d size=%d\n", 266 DRAM_BASE_ADDR, dram_offset, dram_size); 267 ret = aqr_fw_load_memory(phydev, DRAM_BASE_ADDR, data + dram_offset, 268 dram_size); 269 if (ret) 270 return ret; 271 272 phydev_dbg(phydev, "loading IRAM 0x%08x from offset=%d size=%d\n", 273 IRAM_BASE_ADDR, iram_offset, iram_size); 274 ret = aqr_fw_load_memory(phydev, IRAM_BASE_ADDR, data + iram_offset, 275 iram_size); 276 if (ret) 277 return ret; 278 279 /* make sure soft reset and low power mode are clear */ 280 phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_SC, 281 VEND1_GLOBAL_SC_SOFT_RESET | VEND1_GLOBAL_SC_LOW_POWER); 282 283 /* Release the microprocessor. UP_RESET must be held for 100 usec. */ 284 phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_CONTROL2, 285 VEND1_GLOBAL_CONTROL2_UP_RUN_STALL | 286 VEND1_GLOBAL_CONTROL2_UP_RUN_STALL_OVD | 287 VEND1_GLOBAL_CONTROL2_UP_RUN_STALL_RST); 288 usleep_range(UP_RESET_SLEEP, UP_RESET_SLEEP * 2); 289 290 phy_write_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_CONTROL2, 291 VEND1_GLOBAL_CONTROL2_UP_RUN_STALL_OVD); 292 293 return 0; 294 } 295 296 static int aqr_firmware_load_nvmem(struct phy_device *phydev) 297 { 298 struct nvmem_cell *cell; 299 size_t size; 300 u8 *buf; 301 int ret; 302 303 cell = nvmem_cell_get(&phydev->mdio.dev, "firmware"); 304 if (IS_ERR(cell)) 305 return PTR_ERR(cell); 306 307 buf = nvmem_cell_read(cell, &size); 308 if (IS_ERR(buf)) { 309 ret = PTR_ERR(buf); 310 goto exit; 311 } 312 313 ret = aqr_fw_boot(phydev, buf, size, AQR_FW_SRC_NVMEM); 314 if (ret) 315 phydev_err(phydev, "firmware loading failed: %d\n", ret); 316 317 kfree(buf); 318 exit: 319 nvmem_cell_put(cell); 320 321 return ret; 322 } 323 324 static int aqr_firmware_load_fs(struct phy_device *phydev) 325 { 326 struct device *dev = &phydev->mdio.dev; 327 const struct firmware *fw; 328 const char *fw_name; 329 int ret; 330 331 ret = of_property_read_string(dev->of_node, "firmware-name", 332 &fw_name); 333 if (ret) 334 return ret; 335 336 ret = request_firmware(&fw, fw_name, dev); 337 if (ret) { 338 phydev_err(phydev, "failed to find FW file %s (%d)\n", 339 fw_name, ret); 340 return ret; 341 } 342 343 ret = aqr_fw_boot(phydev, fw->data, fw->size, AQR_FW_SRC_FS); 344 if (ret) 345 phydev_err(phydev, "firmware loading failed: %d\n", ret); 346 347 release_firmware(fw); 348 349 return ret; 350 } 351 352 int aqr_firmware_load(struct phy_device *phydev) 353 { 354 int ret; 355 356 /* Check if the firmware is not already loaded by pooling 357 * the current version returned by the PHY. If 0 is returned, 358 * no firmware is loaded. 359 */ 360 ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, VEND1_GLOBAL_FW_ID); 361 if (ret > 0) 362 goto exit; 363 364 ret = aqr_firmware_load_nvmem(phydev); 365 if (!ret) 366 goto exit; 367 368 ret = aqr_firmware_load_fs(phydev); 369 if (ret) 370 return ret; 371 372 exit: 373 return 0; 374 } 375