1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2018-2021 Beijing WangXun Technology Co., Ltd.
3 * Copyright(c) 2010-2017 Intel Corporation
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
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.
20 * This function assumes that the NGBE_MNGSEM_SWMBX semaphore is held
24 ngbe_hic_unlocked(struct ngbe_hw *hw, u32 *buffer, u32 length, u32 timeout)
29 DEBUGFUNC("ngbe_hic_unlocked");
31 if (!length || length > NGBE_PMMBX_BSIZE) {
32 DEBUGOUT("Buffer length failure buffersize=%d.\n", length);
33 return NGBE_ERR_HOST_INTERFACE_COMMAND;
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;
42 dword_len = length >> 2;
44 /* The device driver writes the relevant command block
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);
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);
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;
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
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
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.
88 ngbe_host_interface_command(struct ngbe_hw *hw, u32 *buffer,
89 u32 length, u32 timeout, bool return_data)
91 u32 hdr_size = sizeof(struct ngbe_hic_hdr);
92 struct ngbe_hic_hdr *resp = (struct ngbe_hic_hdr *)buffer;
98 DEBUGFUNC("ngbe_host_interface_command");
100 if (length == 0 || length > NGBE_PMMBX_BSIZE) {
101 DEBUGOUT("Buffer length failure buffersize=%d.\n", length);
102 return NGBE_ERR_HOST_INTERFACE_COMMAND;
105 /* Take management host interface semaphore */
106 err = hw->mac.acquire_swfw_sync(hw, NGBE_MNGSEM_SWMBX);
110 err = ngbe_hic_unlocked(hw, buffer, length, timeout);
117 /* Calculate length in DWORDs */
118 dword_len = hdr_size >> 2;
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);
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
129 if (resp->cmd == 0x30) {
130 for (; bi < dword_len + 2; bi++)
131 buffer[bi] = rd32a(hw, NGBE_MNGMBX, bi);
133 buf_len = (((u16)(resp->cmd_or_resp.ret_status) << 3)
134 & 0xF00) | resp->buf_len;
135 hdr_size += (2 << 2);
137 buf_len = resp->buf_len;
142 if (length < buf_len + hdr_size) {
143 DEBUGOUT("Buffer not large enough for reply message.\n");
144 err = NGBE_ERR_HOST_INTERFACE_COMMAND;
148 /* Calculate length in DWORDs, add 3 for odd lengths */
149 dword_len = (buf_len + 3) >> 2;
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);
156 hw->mac.release_swfw_sync(hw, NGBE_MNGSEM_SWMBX);
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
168 * Reads a 16 bit word from the EEPROM using the hostif.
170 s32 ngbe_hic_sr_read(struct ngbe_hw *hw, u32 addr, u8 *buf, int len)
172 struct ngbe_hic_read_shadow_ram command;
174 int err, i = 0, j = 0;
176 if (len > NGBE_PMMBX_DATA_SIZE)
177 return NGBE_ERR_HOST_INTERFACE_COMMAND;
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);
187 err = ngbe_hic_unlocked(hw, (u32 *)&command,
188 sizeof(command), NGBE_HI_COMMAND_TIMEOUT);
192 while (i < (len >> 2)) {
193 value = rd32a(hw, NGBE_MNGMBX, FW_NVM_DATA_OFFSET + i);
194 ((u32 *)buf)[i] = value;
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++];
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
211 * Write a 16 bit word to the EEPROM using the hostif.
213 s32 ngbe_hic_sr_write(struct ngbe_hw *hw, u32 addr, u8 *buf, int len)
215 struct ngbe_hic_write_shadow_ram command;
217 int err = 0, i = 0, j = 0;
219 if (len > NGBE_PMMBX_DATA_SIZE)
220 return NGBE_ERR_HOST_INTERFACE_COMMAND;
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);
230 while (i < (len >> 2)) {
231 value = ((u32 *)buf)[i];
232 wr32a(hw, NGBE_MNGMBX, FW_NVM_DATA_OFFSET + i, value);
236 for (i <<= 2; i < len; i++)
237 ((u8 *)&value)[j++] = ((u8 *)buf)[i];
239 wr32a(hw, NGBE_MNGMBX, FW_NVM_DATA_OFFSET + (i >> 2), value);
241 UNREFERENCED_PARAMETER(&command);
246 s32 ngbe_hic_pcie_read(struct ngbe_hw *hw, u16 addr, u32 *buf, int len)
248 struct ngbe_hic_read_pcie command;
252 if (len > NGBE_PMMBX_DATA_SIZE)
253 return NGBE_ERR_HOST_INTERFACE_COMMAND;
255 memset(&command, 0, sizeof(command));
256 command.hdr.cmd = FW_PCIE_READ_CMD;
257 command.hdr.buf_len = sizeof(command) - sizeof(command.hdr);
258 command.hdr.checksum = FW_DEFAULT_CHECKSUM;
259 command.lan_id = hw->bus.lan_id;
262 err = ngbe_host_interface_command(hw, (u32 *)&command,
263 sizeof(command), NGBE_HI_COMMAND_TIMEOUT, false);
267 while (i < (len >> 2)) {
268 value = rd32a(hw, NGBE_MNGMBX, FW_PCIE_BUSMASTER_OFFSET + i);
269 ((u32 *)buf)[i] = value;
276 s32 ngbe_hic_pcie_write(struct ngbe_hw *hw, u16 addr, u32 *buf, int len)
278 struct ngbe_hic_write_pcie command;
282 while (i < (len >> 2)) {
283 value = ((u32 *)buf)[i];
287 memset(&command, 0, sizeof(command));
288 command.hdr.cmd = FW_PCIE_WRITE_CMD;
289 command.hdr.buf_len = sizeof(command) - sizeof(command.hdr);
290 command.hdr.checksum = FW_DEFAULT_CHECKSUM;
291 command.lan_id = hw->bus.lan_id;
293 command.data = value;
295 err = ngbe_host_interface_command(hw, (u32 *)&command,
296 sizeof(command), NGBE_HI_COMMAND_TIMEOUT, false);
303 s32 ngbe_hic_check_cap(struct ngbe_hw *hw)
305 struct ngbe_hic_read_shadow_ram command;
311 command.hdr.req.cmd = FW_EEPROM_CHECK_STATUS;
312 command.hdr.req.buf_lenh = 0;
313 command.hdr.req.buf_lenl = 0;
314 command.hdr.req.checksum = FW_DEFAULT_CHECKSUM;
316 /* convert offset from words to bytes */
321 for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) {
322 err = ngbe_host_interface_command(hw, (u32 *)&command,
324 NGBE_HI_COMMAND_TIMEOUT, true);
328 command.hdr.rsp.ret_status &= 0x1F;
329 if (command.hdr.rsp.ret_status !=
330 FW_CEM_RESP_STATUS_SUCCESS)
331 err = NGBE_ERR_HOST_INTERFACE_COMMAND;
336 if (!err && command.address != FW_CHECKSUM_CAP_ST_PASS)
337 err = NGBE_ERR_EEPROM_CHECKSUM;
342 s32 ngbe_phy_led_oem_chk(struct ngbe_hw *hw, u32 *data)
344 struct ngbe_hic_read_shadow_ram command;
350 command.hdr.req.cmd = FW_PHY_LED_CONF;
351 command.hdr.req.buf_lenh = 0;
352 command.hdr.req.buf_lenl = 0;
353 command.hdr.req.checksum = FW_DEFAULT_CHECKSUM;
355 /* convert offset from words to bytes */
360 for (i = 0; i <= FW_CEM_MAX_RETRIES; i++) {
361 err = ngbe_host_interface_command(hw, (u32 *)&command,
363 NGBE_HI_COMMAND_TIMEOUT, true);
367 command.hdr.rsp.ret_status &= 0x1F;
368 if (command.hdr.rsp.ret_status !=
369 FW_CEM_RESP_STATUS_SUCCESS)
370 err = NGBE_ERR_HOST_INTERFACE_COMMAND;
378 if (command.address == FW_CHECKSUM_CAP_ST_PASS) {
379 *data = ((u32 *)&command)[2];
381 } else if (command.address == FW_CHECKSUM_CAP_ST_FAIL) {
382 *data = FW_CHECKSUM_CAP_ST_FAIL;
385 err = NGBE_ERR_EEPROM_CHECKSUM;