1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2015-2020 Beijing WangXun Technology Co., Ltd.
3 * Copyright(c) 2010-2017 Intel Corporation
6 #include "txgbe_type.h"
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.
17 txgbe_calculate_checksum(u8 *buffer, u32 length)
22 for (i = 0; i < length; i++)
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
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.
39 * This function assumes that the TXGBE_MNGSEM_SWMBX semaphore is held
43 txgbe_hic_unlocked(struct txgbe_hw *hw, u32 *buffer, u32 length, u32 timeout)
48 if (!length || length > TXGBE_PMMBX_BSIZE) {
49 DEBUGOUT("Buffer length failure buffersize=%d.", length);
50 return TXGBE_ERR_HOST_INTERFACE_COMMAND;
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;
59 dword_len = length >> 2;
61 /* The device driver writes the relevant command block
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);
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);
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;
83 if ((rd32(hw, TXGBE_MNGMBX) & 0xff0000) >> 16 == 0x80) {
84 DEBUGOUT("It's unknown command.");
85 return TXGBE_ERR_MNG_ACCESS_FAILED;
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
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
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.
110 txgbe_host_interface_command(struct txgbe_hw *hw, u32 *buffer,
111 u32 length, u32 timeout, bool return_data)
113 u32 hdr_size = sizeof(struct txgbe_hic_hdr);
114 struct txgbe_hic_hdr *resp = (struct txgbe_hic_hdr *)buffer;
120 if (length == 0 || length > TXGBE_PMMBX_BSIZE) {
121 DEBUGOUT("Buffer length failure buffersize=%d.", length);
122 return TXGBE_ERR_HOST_INTERFACE_COMMAND;
125 /* Take management host interface semaphore */
126 err = hw->mac.acquire_swfw_sync(hw, TXGBE_MNGSEM_SWMBX);
130 err = txgbe_hic_unlocked(hw, buffer, length, timeout);
137 /* Calculate length in DWORDs */
138 dword_len = hdr_size >> 2;
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);
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
149 if (resp->cmd == 0x30) {
150 for (; bi < dword_len + 2; bi++)
151 buffer[bi] = rd32a(hw, TXGBE_MNGMBX, bi);
153 buf_len = (((u16)(resp->cmd_or_resp.ret_status) << 3)
154 & 0xF00) | resp->buf_len;
155 hdr_size += (2 << 2);
157 buf_len = resp->buf_len;
162 if (length < buf_len + hdr_size) {
163 DEBUGOUT("Buffer not large enough for reply message.");
164 err = TXGBE_ERR_HOST_INTERFACE_COMMAND;
168 /* Calculate length in DWORDs, add 3 for odd lengths */
169 dword_len = (buf_len + 3) >> 2;
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);
176 hw->mac.release_swfw_sync(hw, TXGBE_MNGSEM_SWMBX);
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
188 * Reads a 16 bit word from the EEPROM using the hostif.
190 s32 txgbe_hic_sr_read(struct txgbe_hw *hw, u32 addr, u8 *buf, int len)
192 struct txgbe_hic_read_shadow_ram command;
194 int err, i = 0, j = 0;
196 if (len > TXGBE_PMMBX_DATA_SIZE)
197 return TXGBE_ERR_HOST_INTERFACE_COMMAND;
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);
207 err = txgbe_hic_unlocked(hw, (u32 *)&command,
208 sizeof(command), TXGBE_HI_COMMAND_TIMEOUT);
212 while (i < (len >> 2)) {
213 value = rd32a(hw, TXGBE_MNGMBX, FW_NVM_DATA_OFFSET + i);
214 ((u32 *)buf)[i] = value;
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++];
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
231 * Write a 16 bit word to the EEPROM using the hostif.
233 s32 txgbe_hic_sr_write(struct txgbe_hw *hw, u32 addr, u8 *buf, int len)
235 struct txgbe_hic_write_shadow_ram command;
237 int err = 0, i = 0, j = 0;
239 if (len > TXGBE_PMMBX_DATA_SIZE)
240 return TXGBE_ERR_HOST_INTERFACE_COMMAND;
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);
250 while (i < (len >> 2)) {
251 value = ((u32 *)buf)[i];
252 wr32a(hw, TXGBE_MNGMBX, FW_NVM_DATA_OFFSET + i, value);
256 for (i <<= 2; i < len; i++)
257 ((u8 *)&value)[j++] = ((u8 *)buf)[i];
259 wr32a(hw, TXGBE_MNGMBX, FW_NVM_DATA_OFFSET + (i >> 2), value);
261 UNREFERENCED_PARAMETER(&command);
266 s32 txgbe_close_notify(struct txgbe_hw *hw)
270 struct txgbe_hic_write_shadow_ram buffer;
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;
281 status = txgbe_host_interface_command(hw, (u32 *)&buffer,
283 TXGBE_HI_COMMAND_TIMEOUT, false);
287 tmp = rd32(hw, TXGBE_MNGSWSYNC);
288 if (tmp == TXGBE_CHECKSUM_CAP_ST_PASS)
291 status = TXGBE_ERR_EEPROM_CHECKSUM;
296 s32 txgbe_open_notify(struct txgbe_hw *hw)
300 struct txgbe_hic_write_shadow_ram buffer;
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;
311 status = txgbe_host_interface_command(hw, (u32 *)&buffer,
313 TXGBE_HI_COMMAND_TIMEOUT, false);
317 tmp = rd32(hw, TXGBE_MNGSWSYNC);
318 if (tmp == TXGBE_CHECKSUM_CAP_ST_PASS)
321 status = TXGBE_ERR_EEPROM_CHECKSUM;
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
334 * @driver_ver: unused
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.
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)
345 struct txgbe_hic_drv_info fw_cmd;
349 UNREFERENCED_PARAMETER(len, driver_ver);
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;
362 fw_cmd.hdr.checksum = txgbe_calculate_checksum((u8 *)&fw_cmd,
363 (FW_CEM_HDR_LEN + fw_cmd.hdr.buf_len));
365 for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) {
366 ret_val = txgbe_host_interface_command(hw, (u32 *)&fw_cmd,
368 TXGBE_HI_COMMAND_TIMEOUT,
373 if (fw_cmd.hdr.cmd_or_resp.ret_status ==
374 FW_CEM_RESP_STATUS_SUCCESS)
377 ret_val = TXGBE_ERR_HOST_INTERFACE_COMMAND;
386 * txgbe_hic_reset - send reset cmd to fw
387 * @hw: pointer to hardware structure
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.
395 txgbe_hic_reset(struct txgbe_hw *hw)
397 struct txgbe_hic_reset reset_cmd;
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));
410 for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) {
411 err = txgbe_host_interface_command(hw, (u32 *)&reset_cmd,
413 TXGBE_HI_COMMAND_TIMEOUT,
418 if (reset_cmd.hdr.cmd_or_resp.ret_status ==
419 FW_CEM_RESP_STATUS_SUCCESS)
422 err = TXGBE_ERR_HOST_INTERFACE_COMMAND;
431 * txgbe_mng_present - returns true when management capability is present
432 * @hw: pointer to hardware structure
435 txgbe_mng_present(struct txgbe_hw *hw)
437 if (hw->mac.type == txgbe_mac_unknown)
440 return !!rd32m(hw, TXGBE_STAT, TXGBE_STAT_MNGINIT);
444 * txgbe_mng_enabled - Is the manageability engine enabled?
445 * @hw: pointer to hardware structure
447 * Returns true if the manageability engine is enabled.
450 txgbe_mng_enabled(struct txgbe_hw *hw)
452 UNREFERENCED_PARAMETER(hw);
453 /* firmware does not control laser */