xref: /dpdk/drivers/net/txgbe/base/txgbe_mng.c (revision b19f366c)
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