1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2015-2020 Beijing WangXun Technology Co., Ltd. 3 * Copyright(c) 2010-2017 Intel Corporation 4 */ 5 6 #include "txgbe_type.h" 7 #include "txgbe_mng.h" 8 9 /** 10 * txgbe_calculate_checksum - Calculate checksum for buffer 11 * @buffer: pointer to EEPROM 12 * @length: size of EEPROM to calculate a checksum for 13 * Calculates the checksum for some buffer on a specified length. The 14 * checksum calculated is returned. 15 **/ 16 static u8 17 txgbe_calculate_checksum(u8 *buffer, u32 length) 18 { 19 u32 i; 20 u8 sum = 0; 21 22 for (i = 0; i < length; i++) 23 sum += buffer[i]; 24 25 return (u8)(0 - sum); 26 } 27 28 /** 29 * txgbe_hic_unlocked - Issue command to manageability block unlocked 30 * @hw: pointer to the HW structure 31 * @buffer: command to write and where the return status will be placed 32 * @length: length of buffer, must be multiple of 4 bytes 33 * @timeout: time in ms to wait for command completion 34 * 35 * Communicates with the manageability block. On success return 0 36 * else returns semaphore error when encountering an error acquiring 37 * semaphore or TXGBE_ERR_HOST_INTERFACE_COMMAND when command fails. 38 * 39 * This function assumes that the TXGBE_MNGSEM_SWMBX semaphore is held 40 * by the caller. 41 **/ 42 static s32 43 txgbe_hic_unlocked(struct txgbe_hw *hw, u32 *buffer, u32 length, u32 timeout) 44 { 45 u32 value, loop; 46 u16 i, dword_len; 47 48 if (!length || length > TXGBE_PMMBX_BSIZE) { 49 DEBUGOUT("Buffer length failure buffersize=%d.", length); 50 return TXGBE_ERR_HOST_INTERFACE_COMMAND; 51 } 52 53 /* Calculate length in DWORDs. We must be DWORD aligned */ 54 if (length % sizeof(u32)) { 55 DEBUGOUT("Buffer length failure, not aligned to dword"); 56 return TXGBE_ERR_INVALID_ARGUMENT; 57 } 58 59 dword_len = length >> 2; 60 61 /* The device driver writes the relevant command block 62 * into the ram area. 63 */ 64 for (i = 0; i < dword_len; i++) { 65 wr32a(hw, TXGBE_MNGMBX, i, cpu_to_le32(buffer[i])); 66 buffer[i] = rd32a(hw, TXGBE_MNGMBX, i); 67 } 68 txgbe_flush(hw); 69 70 /* Setting this bit tells the ARC that a new command is pending. */ 71 wr32m(hw, TXGBE_MNGMBXCTL, 72 TXGBE_MNGMBXCTL_SWRDY, TXGBE_MNGMBXCTL_SWRDY); 73 74 /* Check command completion */ 75 loop = po32m(hw, TXGBE_MNGMBXCTL, 76 TXGBE_MNGMBXCTL_FWRDY, TXGBE_MNGMBXCTL_FWRDY, 77 &value, timeout, 1000); 78 if (!loop || !(value & TXGBE_MNGMBXCTL_FWACK)) { 79 DEBUGOUT("Command has failed with no status valid."); 80 return TXGBE_ERR_HOST_INTERFACE_COMMAND; 81 } 82 83 if ((rd32(hw, TXGBE_MNGMBX) & 0xff0000) >> 16 == 0x80) { 84 DEBUGOUT("It's unknown command."); 85 return TXGBE_ERR_MNG_ACCESS_FAILED; 86 } 87 88 return 0; 89 } 90 91 /** 92 * txgbe_host_interface_command - Issue command to manageability block 93 * @hw: pointer to the HW structure 94 * @buffer: contains the command to write and where the return status will 95 * be placed 96 * @length: length of buffer, must be multiple of 4 bytes 97 * @timeout: time in ms to wait for command completion 98 * @return_data: read and return data from the buffer (true) or not (false) 99 * Needed because FW structures are big endian and decoding of 100 * these fields can be 8 bit or 16 bit based on command. Decoding 101 * is not easily understood without making a table of commands. 102 * So we will leave this up to the caller to read back the data 103 * in these cases. 104 * 105 * Communicates with the manageability block. On success return 0 106 * else returns semaphore error when encountering an error acquiring 107 * semaphore or TXGBE_ERR_HOST_INTERFACE_COMMAND when command fails. 108 **/ 109 static s32 110 txgbe_host_interface_command(struct txgbe_hw *hw, u32 *buffer, 111 u32 length, u32 timeout, bool return_data) 112 { 113 u32 hdr_size = sizeof(struct txgbe_hic_hdr); 114 struct txgbe_hic_hdr *resp = (struct txgbe_hic_hdr *)buffer; 115 u16 buf_len; 116 s32 err; 117 u32 bi; 118 u32 dword_len; 119 120 if (length == 0 || length > TXGBE_PMMBX_BSIZE) { 121 DEBUGOUT("Buffer length failure buffersize=%d.", length); 122 return TXGBE_ERR_HOST_INTERFACE_COMMAND; 123 } 124 125 /* Take management host interface semaphore */ 126 err = hw->mac.acquire_swfw_sync(hw, TXGBE_MNGSEM_SWMBX); 127 if (err) 128 return err; 129 130 err = txgbe_hic_unlocked(hw, buffer, length, timeout); 131 if (err) 132 goto rel_out; 133 134 if (!return_data) 135 goto rel_out; 136 137 /* Calculate length in DWORDs */ 138 dword_len = hdr_size >> 2; 139 140 /* first pull in the header so we know the buffer length */ 141 for (bi = 0; bi < dword_len; bi++) 142 buffer[bi] = rd32a(hw, TXGBE_MNGMBX, bi); 143 144 /* 145 * If there is any thing in data position pull it in 146 * Read Flash command requires reading buffer length from 147 * two byes instead of one byte 148 */ 149 if (resp->cmd == 0x30) { 150 for (; bi < dword_len + 2; bi++) 151 buffer[bi] = rd32a(hw, TXGBE_MNGMBX, bi); 152 153 buf_len = (((u16)(resp->cmd_or_resp.ret_status) << 3) 154 & 0xF00) | resp->buf_len; 155 hdr_size += (2 << 2); 156 } else { 157 buf_len = resp->buf_len; 158 } 159 if (!buf_len) 160 goto rel_out; 161 162 if (length < buf_len + hdr_size) { 163 DEBUGOUT("Buffer not large enough for reply message."); 164 err = TXGBE_ERR_HOST_INTERFACE_COMMAND; 165 goto rel_out; 166 } 167 168 /* Calculate length in DWORDs, add 3 for odd lengths */ 169 dword_len = (buf_len + 3) >> 2; 170 171 /* Pull in the rest of the buffer (bi is where we left off) */ 172 for (; bi <= dword_len; bi++) 173 buffer[bi] = rd32a(hw, TXGBE_MNGMBX, bi); 174 175 rel_out: 176 hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWMBX); 177 178 return err; 179 } 180 181 /** 182 * txgbe_hic_sr_read - Read EEPROM word using a host interface cmd 183 * assuming that the semaphore is already obtained. 184 * @hw: pointer to hardware structure 185 * @offset: offset of word in the EEPROM to read 186 * @data: word read from the EEPROM 187 * 188 * Reads a 16 bit word from the EEPROM using the hostif. 189 **/ 190 s32 txgbe_hic_sr_read(struct txgbe_hw *hw, u32 addr, u8 *buf, int len) 191 { 192 struct txgbe_hic_read_shadow_ram command; 193 u32 value; 194 int err, i = 0, j = 0; 195 196 if (len > TXGBE_PMMBX_DATA_SIZE) 197 return TXGBE_ERR_HOST_INTERFACE_COMMAND; 198 199 memset(&command, 0, sizeof(command)); 200 command.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD; 201 command.hdr.req.buf_lenh = 0; 202 command.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN; 203 command.hdr.req.checksum = FW_DEFAULT_CHECKSUM; 204 command.address = cpu_to_be32(addr); 205 command.length = cpu_to_be16(len); 206 207 err = txgbe_hic_unlocked(hw, (u32 *)&command, 208 sizeof(command), TXGBE_HI_COMMAND_TIMEOUT); 209 if (err) 210 return err; 211 212 while (i < (len >> 2)) { 213 value = rd32a(hw, TXGBE_MNGMBX, FW_NVM_DATA_OFFSET + i); 214 ((u32 *)buf)[i] = value; 215 i++; 216 } 217 218 value = rd32a(hw, TXGBE_MNGMBX, FW_NVM_DATA_OFFSET + i); 219 for (i <<= 2; i < len; i++) 220 ((u8 *)buf)[i] = ((u8 *)&value)[j++]; 221 222 return 0; 223 } 224 225 /** 226 * txgbe_hic_sr_write - Write EEPROM word using hostif 227 * @hw: pointer to hardware structure 228 * @offset: offset of word in the EEPROM to write 229 * @data: word write to the EEPROM 230 * 231 * Write a 16 bit word to the EEPROM using the hostif. 232 **/ 233 s32 txgbe_hic_sr_write(struct txgbe_hw *hw, u32 addr, u8 *buf, int len) 234 { 235 struct txgbe_hic_write_shadow_ram command; 236 u32 value; 237 int err = 0, i = 0, j = 0; 238 239 if (len > TXGBE_PMMBX_DATA_SIZE) 240 return TXGBE_ERR_HOST_INTERFACE_COMMAND; 241 242 memset(&command, 0, sizeof(command)); 243 command.hdr.req.cmd = FW_WRITE_SHADOW_RAM_CMD; 244 command.hdr.req.buf_lenh = 0; 245 command.hdr.req.buf_lenl = FW_WRITE_SHADOW_RAM_LEN; 246 command.hdr.req.checksum = FW_DEFAULT_CHECKSUM; 247 command.address = cpu_to_be32(addr); 248 command.length = cpu_to_be16(len); 249 250 while (i < (len >> 2)) { 251 value = ((u32 *)buf)[i]; 252 wr32a(hw, TXGBE_MNGMBX, FW_NVM_DATA_OFFSET + i, value); 253 i++; 254 } 255 256 for (i <<= 2; i < len; i++) 257 ((u8 *)&value)[j++] = ((u8 *)buf)[i]; 258 259 wr32a(hw, TXGBE_MNGMBX, FW_NVM_DATA_OFFSET + (i >> 2), value); 260 261 UNREFERENCED_PARAMETER(&command); 262 263 return err; 264 } 265 266 s32 txgbe_close_notify(struct txgbe_hw *hw) 267 { 268 u32 tmp; 269 s32 status; 270 struct txgbe_hic_write_shadow_ram buffer; 271 272 buffer.hdr.req.cmd = FW_DW_CLOSE_NOTIFY; 273 buffer.hdr.req.buf_lenh = 0; 274 buffer.hdr.req.buf_lenl = 0; 275 buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM; 276 277 /* one word */ 278 buffer.length = 0; 279 buffer.address = 0; 280 281 status = txgbe_host_interface_command(hw, (u32 *)&buffer, 282 sizeof(buffer), 283 TXGBE_HI_COMMAND_TIMEOUT, false); 284 if (status) 285 return status; 286 287 tmp = rd32(hw, TXGBE_MNGSWSYNC); 288 if (tmp == TXGBE_CHECKSUM_CAP_ST_PASS) 289 status = 0; 290 else 291 status = TXGBE_ERR_EEPROM_CHECKSUM; 292 293 return status; 294 } 295 296 s32 txgbe_open_notify(struct txgbe_hw *hw) 297 { 298 u32 tmp; 299 s32 status; 300 struct txgbe_hic_write_shadow_ram buffer; 301 302 buffer.hdr.req.cmd = FW_DW_OPEN_NOTIFY; 303 buffer.hdr.req.buf_lenh = 0; 304 buffer.hdr.req.buf_lenl = 0; 305 buffer.hdr.req.checksum = FW_DEFAULT_CHECKSUM; 306 307 /* one word */ 308 buffer.length = 0; 309 buffer.address = 0; 310 311 status = txgbe_host_interface_command(hw, (u32 *)&buffer, 312 sizeof(buffer), 313 TXGBE_HI_COMMAND_TIMEOUT, false); 314 if (status) 315 return status; 316 317 tmp = rd32(hw, TXGBE_MNGSWSYNC); 318 if (tmp == TXGBE_CHECKSUM_CAP_ST_PASS) 319 status = 0; 320 else 321 status = TXGBE_ERR_EEPROM_CHECKSUM; 322 323 return status; 324 } 325 326 /** 327 * txgbe_hic_set_drv_ver - Sends driver version to firmware 328 * @hw: pointer to the HW structure 329 * @maj: driver version major number 330 * @min: driver version minor number 331 * @build: driver version build number 332 * @sub: driver version sub build number 333 * @len: unused 334 * @driver_ver: unused 335 * 336 * Sends driver version number to firmware through the manageability 337 * block. On success return 0 338 * else returns TXGBE_ERR_SWFW_SYNC when encountering an error acquiring 339 * semaphore or TXGBE_ERR_HOST_INTERFACE_COMMAND when command fails. 340 **/ 341 s32 txgbe_hic_set_drv_ver(struct txgbe_hw *hw, u8 maj, u8 min, 342 u8 build, u8 sub, u16 len, 343 const char *driver_ver) 344 { 345 struct txgbe_hic_drv_info fw_cmd; 346 int i; 347 s32 ret_val = 0; 348 349 UNREFERENCED_PARAMETER(len, driver_ver); 350 351 fw_cmd.hdr.cmd = FW_CEM_CMD_DRIVER_INFO; 352 fw_cmd.hdr.buf_len = FW_CEM_CMD_DRIVER_INFO_LEN; 353 fw_cmd.hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED; 354 fw_cmd.port_num = (u8)hw->bus.func; 355 fw_cmd.ver_maj = maj; 356 fw_cmd.ver_min = min; 357 fw_cmd.ver_build = build; 358 fw_cmd.ver_sub = sub; 359 fw_cmd.hdr.checksum = 0; 360 fw_cmd.pad = 0; 361 fw_cmd.pad2 = 0; 362 fw_cmd.hdr.checksum = txgbe_calculate_checksum((u8 *)&fw_cmd, 363 (FW_CEM_HDR_LEN + fw_cmd.hdr.buf_len)); 364 365 for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) { 366 ret_val = txgbe_host_interface_command(hw, (u32 *)&fw_cmd, 367 sizeof(fw_cmd), 368 TXGBE_HI_COMMAND_TIMEOUT, 369 true); 370 if (ret_val != 0) 371 continue; 372 373 if (fw_cmd.hdr.cmd_or_resp.ret_status == 374 FW_CEM_RESP_STATUS_SUCCESS) 375 ret_val = 0; 376 else 377 ret_val = TXGBE_ERR_HOST_INTERFACE_COMMAND; 378 379 break; 380 } 381 382 return ret_val; 383 } 384 385 /** 386 * txgbe_hic_reset - send reset cmd to fw 387 * @hw: pointer to hardware structure 388 * 389 * Sends reset cmd to firmware through the manageability 390 * block. On success return 0 391 * else returns TXGBE_ERR_SWFW_SYNC when encountering an error acquiring 392 * semaphore or TXGBE_ERR_HOST_INTERFACE_COMMAND when command fails. 393 **/ 394 s32 395 txgbe_hic_reset(struct txgbe_hw *hw) 396 { 397 struct txgbe_hic_reset reset_cmd; 398 int i; 399 s32 err = 0; 400 401 reset_cmd.hdr.cmd = FW_RESET_CMD; 402 reset_cmd.hdr.buf_len = FW_RESET_LEN; 403 reset_cmd.hdr.cmd_or_resp.cmd_resv = FW_CEM_CMD_RESERVED; 404 reset_cmd.lan_id = hw->bus.lan_id; 405 reset_cmd.reset_type = (u16)hw->reset_type; 406 reset_cmd.hdr.checksum = 0; 407 reset_cmd.hdr.checksum = txgbe_calculate_checksum((u8 *)&reset_cmd, 408 (FW_CEM_HDR_LEN + reset_cmd.hdr.buf_len)); 409 410 for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) { 411 err = txgbe_host_interface_command(hw, (u32 *)&reset_cmd, 412 sizeof(reset_cmd), 413 TXGBE_HI_COMMAND_TIMEOUT, 414 true); 415 if (err != 0) 416 continue; 417 418 if (reset_cmd.hdr.cmd_or_resp.ret_status == 419 FW_CEM_RESP_STATUS_SUCCESS) 420 err = 0; 421 else 422 err = TXGBE_ERR_HOST_INTERFACE_COMMAND; 423 424 break; 425 } 426 427 return err; 428 } 429 430 /** 431 * txgbe_mng_present - returns true when management capability is present 432 * @hw: pointer to hardware structure 433 */ 434 bool 435 txgbe_mng_present(struct txgbe_hw *hw) 436 { 437 if (hw->mac.type == txgbe_mac_unknown) 438 return false; 439 440 return !!rd32m(hw, TXGBE_STAT, TXGBE_STAT_MNGINIT); 441 } 442 443 /** 444 * txgbe_mng_enabled - Is the manageability engine enabled? 445 * @hw: pointer to hardware structure 446 * 447 * Returns true if the manageability engine is enabled. 448 **/ 449 bool 450 txgbe_mng_enabled(struct txgbe_hw *hw) 451 { 452 UNREFERENCED_PARAMETER(hw); 453 /* firmware does not control laser */ 454 return false; 455 } 456