1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2018-2021 Beijing WangXun Technology Co., Ltd. 3 * Copyright(c) 2010-2017 Intel Corporation 4 */ 5 6 #include "ngbe_type.h" 7 #include "ngbe_mng.h" 8 9 /** 10 * ngbe_hic_unlocked - Issue command to manageability block unlocked 11 * @hw: pointer to the HW structure 12 * @buffer: command to write and where the return status will be placed 13 * @length: length of buffer, must be multiple of 4 bytes 14 * @timeout: time in ms to wait for command completion 15 * 16 * Communicates with the manageability block. On success return 0 17 * else returns semaphore error when encountering an error acquiring 18 * semaphore or NGBE_ERR_HOST_INTERFACE_COMMAND when command fails. 19 * 20 * This function assumes that the NGBE_MNGSEM_SWMBX semaphore is held 21 * by the caller. 22 **/ 23 static s32 24 ngbe_hic_unlocked(struct ngbe_hw *hw, u32 *buffer, u32 length, u32 timeout) 25 { 26 u32 value, loop; 27 u16 i, dword_len; 28 29 DEBUGFUNC("ngbe_hic_unlocked"); 30 31 if (!length || length > NGBE_PMMBX_BSIZE) { 32 DEBUGOUT("Buffer length failure buffersize=%d.\n", length); 33 return NGBE_ERR_HOST_INTERFACE_COMMAND; 34 } 35 36 /* Calculate length in DWORDs. We must be DWORD aligned */ 37 if (length % sizeof(u32)) { 38 DEBUGOUT("Buffer length failure, not aligned to dword"); 39 return NGBE_ERR_INVALID_ARGUMENT; 40 } 41 42 dword_len = length >> 2; 43 44 /* The device driver writes the relevant command block 45 * into the ram area. 46 */ 47 for (i = 0; i < dword_len; i++) { 48 wr32a(hw, NGBE_MNGMBX, i, cpu_to_le32(buffer[i])); 49 buffer[i] = rd32a(hw, NGBE_MNGMBX, i); 50 } 51 ngbe_flush(hw); 52 53 /* Setting this bit tells the ARC that a new command is pending. */ 54 wr32m(hw, NGBE_MNGMBXCTL, 55 NGBE_MNGMBXCTL_SWRDY, NGBE_MNGMBXCTL_SWRDY); 56 57 /* Check command completion */ 58 loop = po32m(hw, NGBE_MNGMBXCTL, 59 NGBE_MNGMBXCTL_FWRDY, NGBE_MNGMBXCTL_FWRDY, 60 &value, timeout, 1000); 61 if (!loop || !(value & NGBE_MNGMBXCTL_FWACK)) { 62 DEBUGOUT("Command has failed with no status valid.\n"); 63 return NGBE_ERR_HOST_INTERFACE_COMMAND; 64 } 65 66 return 0; 67 } 68 69 /** 70 * ngbe_host_interface_command - Issue command to manageability block 71 * @hw: pointer to the HW structure 72 * @buffer: contains the command to write and where the return status will 73 * be placed 74 * @length: length of buffer, must be multiple of 4 bytes 75 * @timeout: time in ms to wait for command completion 76 * @return_data: read and return data from the buffer (true) or not (false) 77 * Needed because FW structures are big endian and decoding of 78 * these fields can be 8 bit or 16 bit based on command. Decoding 79 * is not easily understood without making a table of commands. 80 * So we will leave this up to the caller to read back the data 81 * in these cases. 82 * 83 * Communicates with the manageability block. On success return 0 84 * else returns semaphore error when encountering an error acquiring 85 * semaphore or NGBE_ERR_HOST_INTERFACE_COMMAND when command fails. 86 **/ 87 static s32 88 ngbe_host_interface_command(struct ngbe_hw *hw, u32 *buffer, 89 u32 length, u32 timeout, bool return_data) 90 { 91 u32 hdr_size = sizeof(struct ngbe_hic_hdr); 92 struct ngbe_hic_hdr *resp = (struct ngbe_hic_hdr *)buffer; 93 u16 buf_len; 94 s32 err; 95 u32 bi; 96 u32 dword_len; 97 98 DEBUGFUNC("ngbe_host_interface_command"); 99 100 if (length == 0 || length > NGBE_PMMBX_BSIZE) { 101 DEBUGOUT("Buffer length failure buffersize=%d.\n", length); 102 return NGBE_ERR_HOST_INTERFACE_COMMAND; 103 } 104 105 /* Take management host interface semaphore */ 106 err = hw->mac.acquire_swfw_sync(hw, NGBE_MNGSEM_SWMBX); 107 if (err) 108 return err; 109 110 err = ngbe_hic_unlocked(hw, buffer, length, timeout); 111 if (err) 112 goto rel_out; 113 114 if (!return_data) 115 goto rel_out; 116 117 /* Calculate length in DWORDs */ 118 dword_len = hdr_size >> 2; 119 120 /* first pull in the header so we know the buffer length */ 121 for (bi = 0; bi < dword_len; bi++) 122 buffer[bi] = rd32a(hw, NGBE_MNGMBX, bi); 123 124 /* 125 * If there is any thing in data position pull it in 126 * Read Flash command requires reading buffer length from 127 * two byes instead of one byte 128 */ 129 if (resp->cmd == 0x30) { 130 for (; bi < dword_len + 2; bi++) 131 buffer[bi] = rd32a(hw, NGBE_MNGMBX, bi); 132 133 buf_len = (((u16)(resp->cmd_or_resp.ret_status) << 3) 134 & 0xF00) | resp->buf_len; 135 hdr_size += (2 << 2); 136 } else { 137 buf_len = resp->buf_len; 138 } 139 if (!buf_len) 140 goto rel_out; 141 142 if (length < buf_len + hdr_size) { 143 DEBUGOUT("Buffer not large enough for reply message.\n"); 144 err = NGBE_ERR_HOST_INTERFACE_COMMAND; 145 goto rel_out; 146 } 147 148 /* Calculate length in DWORDs, add 3 for odd lengths */ 149 dword_len = (buf_len + 3) >> 2; 150 151 /* Pull in the rest of the buffer (bi is where we left off) */ 152 for (; bi <= dword_len; bi++) 153 buffer[bi] = rd32a(hw, NGBE_MNGMBX, bi); 154 155 rel_out: 156 hw->mac.release_swfw_sync(hw, NGBE_MNGSEM_SWMBX); 157 158 return err; 159 } 160 161 /** 162 * ngbe_hic_sr_read - Read EEPROM word using a host interface cmd 163 * assuming that the semaphore is already obtained. 164 * @hw: pointer to hardware structure 165 * @offset: offset of word in the EEPROM to read 166 * @data: word read from the EEPROM 167 * 168 * Reads a 16 bit word from the EEPROM using the hostif. 169 **/ 170 s32 ngbe_hic_sr_read(struct ngbe_hw *hw, u32 addr, u8 *buf, int len) 171 { 172 struct ngbe_hic_read_shadow_ram command; 173 u32 value; 174 int err, i = 0, j = 0; 175 176 if (len > NGBE_PMMBX_DATA_SIZE) 177 return NGBE_ERR_HOST_INTERFACE_COMMAND; 178 179 memset(&command, 0, sizeof(command)); 180 command.hdr.req.cmd = FW_READ_SHADOW_RAM_CMD; 181 command.hdr.req.buf_lenh = 0; 182 command.hdr.req.buf_lenl = FW_READ_SHADOW_RAM_LEN; 183 command.hdr.req.checksum = FW_DEFAULT_CHECKSUM; 184 command.address = cpu_to_be32(addr); 185 command.length = cpu_to_be16(len); 186 187 err = ngbe_hic_unlocked(hw, (u32 *)&command, 188 sizeof(command), NGBE_HI_COMMAND_TIMEOUT); 189 if (err) 190 return err; 191 192 while (i < (len >> 2)) { 193 value = rd32a(hw, NGBE_MNGMBX, FW_NVM_DATA_OFFSET + i); 194 ((u32 *)buf)[i] = value; 195 i++; 196 } 197 198 value = rd32a(hw, NGBE_MNGMBX, FW_NVM_DATA_OFFSET + i); 199 for (i <<= 2; i < len; i++) 200 ((u8 *)buf)[i] = ((u8 *)&value)[j++]; 201 202 return 0; 203 } 204 205 /** 206 * ngbe_hic_sr_write - Write EEPROM word using hostif 207 * @hw: pointer to hardware structure 208 * @offset: offset of word in the EEPROM to write 209 * @data: word write to the EEPROM 210 * 211 * Write a 16 bit word to the EEPROM using the hostif. 212 **/ 213 s32 ngbe_hic_sr_write(struct ngbe_hw *hw, u32 addr, u8 *buf, int len) 214 { 215 struct ngbe_hic_write_shadow_ram command; 216 u32 value; 217 int err = 0, i = 0, j = 0; 218 219 if (len > NGBE_PMMBX_DATA_SIZE) 220 return NGBE_ERR_HOST_INTERFACE_COMMAND; 221 222 memset(&command, 0, sizeof(command)); 223 command.hdr.req.cmd = FW_WRITE_SHADOW_RAM_CMD; 224 command.hdr.req.buf_lenh = 0; 225 command.hdr.req.buf_lenl = FW_WRITE_SHADOW_RAM_LEN; 226 command.hdr.req.checksum = FW_DEFAULT_CHECKSUM; 227 command.address = cpu_to_be32(addr); 228 command.length = cpu_to_be16(len); 229 230 while (i < (len >> 2)) { 231 value = ((u32 *)buf)[i]; 232 wr32a(hw, NGBE_MNGMBX, FW_NVM_DATA_OFFSET + i, value); 233 i++; 234 } 235 236 for (i <<= 2; i < len; i++) 237 ((u8 *)&value)[j++] = ((u8 *)buf)[i]; 238 239 wr32a(hw, NGBE_MNGMBX, FW_NVM_DATA_OFFSET + (i >> 2), value); 240 241 UNREFERENCED_PARAMETER(&command); 242 243 return err; 244 } 245 246 s32 ngbe_hic_check_cap(struct ngbe_hw *hw) 247 { 248 struct ngbe_hic_read_shadow_ram command; 249 s32 err; 250 int i; 251 252 DEBUGFUNC("\n"); 253 254 command.hdr.req.cmd = FW_EEPROM_CHECK_STATUS; 255 command.hdr.req.buf_lenh = 0; 256 command.hdr.req.buf_lenl = 0; 257 command.hdr.req.checksum = FW_DEFAULT_CHECKSUM; 258 259 /* convert offset from words to bytes */ 260 command.address = 0; 261 /* one word */ 262 command.length = 0; 263 264 for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) { 265 err = ngbe_host_interface_command(hw, (u32 *)&command, 266 sizeof(command), 267 NGBE_HI_COMMAND_TIMEOUT, true); 268 if (err) 269 continue; 270 271 command.hdr.rsp.ret_status &= 0x1F; 272 if (command.hdr.rsp.ret_status != 273 FW_CEM_RESP_STATUS_SUCCESS) 274 err = NGBE_ERR_HOST_INTERFACE_COMMAND; 275 276 break; 277 } 278 279 if (!err && command.address != FW_CHECKSUM_CAP_ST_PASS) 280 err = NGBE_ERR_EEPROM_CHECKSUM; 281 282 return err; 283 } 284