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
txgbe_calculate_checksum(u8 * buffer,u32 length)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
txgbe_hic_unlocked(struct txgbe_hw * hw,u32 * buffer,u32 length,u32 timeout)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
txgbe_host_interface_command(struct txgbe_hw * hw,u32 * buffer,u32 length,u32 timeout,bool return_data)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 **/
txgbe_hic_sr_read(struct txgbe_hw * hw,u32 addr,u8 * buf,int len)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 **/
txgbe_hic_sr_write(struct txgbe_hw * hw,u32 addr,u8 * buf,int len)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
txgbe_close_notify(struct txgbe_hw * hw)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
txgbe_open_notify(struct txgbe_hw * hw)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 **/
txgbe_hic_set_drv_ver(struct txgbe_hw * hw,u8 maj,u8 min,u8 build,u8 sub,u16 len,const char * driver_ver)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
txgbe_hic_reset(struct txgbe_hw * hw)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
txgbe_mng_present(struct txgbe_hw * hw)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
txgbe_mng_enabled(struct txgbe_hw * hw)450 txgbe_mng_enabled(struct txgbe_hw *hw)
451 {
452 UNREFERENCED_PARAMETER(hw);
453 /* firmware does not control laser */
454 return false;
455 }
456