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