1f31e4b6fSAnirudh Venkataramanan // SPDX-License-Identifier: GPL-2.0
2f31e4b6fSAnirudh Venkataramanan /* Copyright (c) 2018, Intel Corporation. */
3f31e4b6fSAnirudh Venkataramanan 
4f31e4b6fSAnirudh Venkataramanan #include "ice_common.h"
5f31e4b6fSAnirudh Venkataramanan 
6f31e4b6fSAnirudh Venkataramanan /**
7f31e4b6fSAnirudh Venkataramanan  * ice_aq_read_nvm
8f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
9f31e4b6fSAnirudh Venkataramanan  * @module_typeid: module pointer location in words from the NVM beginning
10f31e4b6fSAnirudh Venkataramanan  * @offset: byte offset from the module beginning
11f31e4b6fSAnirudh Venkataramanan  * @length: length of the section to be read (in bytes from the offset)
12f31e4b6fSAnirudh Venkataramanan  * @data: command buffer (size [bytes] = length)
13f31e4b6fSAnirudh Venkataramanan  * @last_command: tells if this is the last command in a series
14e9450990SJacob Keller  * @read_shadow_ram: tell if this is a shadow RAM read
15f31e4b6fSAnirudh Venkataramanan  * @cd: pointer to command details structure or NULL
16f31e4b6fSAnirudh Venkataramanan  *
17f31e4b6fSAnirudh Venkataramanan  * Read the NVM using the admin queue commands (0x0701)
18f31e4b6fSAnirudh Venkataramanan  */
19f31e4b6fSAnirudh Venkataramanan static enum ice_status
2043c89b16SAnirudh Venkataramanan ice_aq_read_nvm(struct ice_hw *hw, u16 module_typeid, u32 offset, u16 length,
21e9450990SJacob Keller 		void *data, bool last_command, bool read_shadow_ram,
22e9450990SJacob Keller 		struct ice_sq_cd *cd)
23f31e4b6fSAnirudh Venkataramanan {
24f31e4b6fSAnirudh Venkataramanan 	struct ice_aq_desc desc;
25f31e4b6fSAnirudh Venkataramanan 	struct ice_aqc_nvm *cmd;
26f31e4b6fSAnirudh Venkataramanan 
27f31e4b6fSAnirudh Venkataramanan 	cmd = &desc.params.nvm;
28f31e4b6fSAnirudh Venkataramanan 
2981f07491SJacob Keller 	if (offset > ICE_AQC_NVM_MAX_OFFSET)
30f31e4b6fSAnirudh Venkataramanan 		return ICE_ERR_PARAM;
31f31e4b6fSAnirudh Venkataramanan 
32f31e4b6fSAnirudh Venkataramanan 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_nvm_read);
33f31e4b6fSAnirudh Venkataramanan 
34e9450990SJacob Keller 	if (!read_shadow_ram && module_typeid == ICE_AQC_NVM_START_POINT)
35e9450990SJacob Keller 		cmd->cmd_flags |= ICE_AQC_NVM_FLASH_ONLY;
36e9450990SJacob Keller 
37f31e4b6fSAnirudh Venkataramanan 	/* If this is the last command in a series, set the proper flag. */
38f31e4b6fSAnirudh Venkataramanan 	if (last_command)
39f31e4b6fSAnirudh Venkataramanan 		cmd->cmd_flags |= ICE_AQC_NVM_LAST_CMD;
4043c89b16SAnirudh Venkataramanan 	cmd->module_typeid = cpu_to_le16(module_typeid);
4143c89b16SAnirudh Venkataramanan 	cmd->offset_low = cpu_to_le16(offset & 0xFFFF);
4243c89b16SAnirudh Venkataramanan 	cmd->offset_high = (offset >> 16) & 0xFF;
43f31e4b6fSAnirudh Venkataramanan 	cmd->length = cpu_to_le16(length);
44f31e4b6fSAnirudh Venkataramanan 
45f31e4b6fSAnirudh Venkataramanan 	return ice_aq_send_cmd(hw, &desc, data, length, cd);
46f31e4b6fSAnirudh Venkataramanan }
47f31e4b6fSAnirudh Venkataramanan 
48f31e4b6fSAnirudh Venkataramanan /**
49e9450990SJacob Keller  * ice_read_flat_nvm - Read portion of NVM by flat offset
50e9450990SJacob Keller  * @hw: pointer to the HW struct
51e9450990SJacob Keller  * @offset: offset from beginning of NVM
52e9450990SJacob Keller  * @length: (in) number of bytes to read; (out) number of bytes actually read
53e9450990SJacob Keller  * @data: buffer to return data in (sized to fit the specified length)
54e9450990SJacob Keller  * @read_shadow_ram: if true, read from shadow RAM instead of NVM
55e9450990SJacob Keller  *
56e9450990SJacob Keller  * Reads a portion of the NVM, as a flat memory space. This function correctly
57e9450990SJacob Keller  * breaks read requests across Shadow RAM sectors and ensures that no single
58e9450990SJacob Keller  * read request exceeds the maximum 4Kb read for a single AdminQ command.
59e9450990SJacob Keller  *
60e9450990SJacob Keller  * Returns a status code on failure. Note that the data pointer may be
61e9450990SJacob Keller  * partially updated if some reads succeed before a failure.
62e9450990SJacob Keller  */
63e9450990SJacob Keller enum ice_status
64e9450990SJacob Keller ice_read_flat_nvm(struct ice_hw *hw, u32 offset, u32 *length, u8 *data,
65e9450990SJacob Keller 		  bool read_shadow_ram)
66e9450990SJacob Keller {
67e9450990SJacob Keller 	enum ice_status status;
68e9450990SJacob Keller 	u32 inlen = *length;
69e9450990SJacob Keller 	u32 bytes_read = 0;
70e9450990SJacob Keller 	bool last_cmd;
71e9450990SJacob Keller 
72e9450990SJacob Keller 	*length = 0;
73e9450990SJacob Keller 
74e9450990SJacob Keller 	/* Verify the length of the read if this is for the Shadow RAM */
75e9450990SJacob Keller 	if (read_shadow_ram && ((offset + inlen) > (hw->nvm.sr_words * 2u))) {
76e9450990SJacob Keller 		ice_debug(hw, ICE_DBG_NVM,
77e9450990SJacob Keller 			  "NVM error: requested offset is beyond Shadow RAM limit\n");
78e9450990SJacob Keller 		return ICE_ERR_PARAM;
79e9450990SJacob Keller 	}
80e9450990SJacob Keller 
81e9450990SJacob Keller 	do {
82e9450990SJacob Keller 		u32 read_size, sector_offset;
83e9450990SJacob Keller 
84e9450990SJacob Keller 		/* ice_aq_read_nvm cannot read more than 4Kb at a time.
85e9450990SJacob Keller 		 * Additionally, a read from the Shadow RAM may not cross over
86e9450990SJacob Keller 		 * a sector boundary. Conveniently, the sector size is also
87e9450990SJacob Keller 		 * 4Kb.
88e9450990SJacob Keller 		 */
89e9450990SJacob Keller 		sector_offset = offset % ICE_AQ_MAX_BUF_LEN;
90e9450990SJacob Keller 		read_size = min_t(u32, ICE_AQ_MAX_BUF_LEN - sector_offset,
91e9450990SJacob Keller 				  inlen - bytes_read);
92e9450990SJacob Keller 
93e9450990SJacob Keller 		last_cmd = !(bytes_read + read_size < inlen);
94e9450990SJacob Keller 
95e9450990SJacob Keller 		status = ice_aq_read_nvm(hw, ICE_AQC_NVM_START_POINT,
96e9450990SJacob Keller 					 offset, read_size,
97e9450990SJacob Keller 					 data + bytes_read, last_cmd,
98e9450990SJacob Keller 					 read_shadow_ram, NULL);
99e9450990SJacob Keller 		if (status)
100e9450990SJacob Keller 			break;
101e9450990SJacob Keller 
102e9450990SJacob Keller 		bytes_read += read_size;
103e9450990SJacob Keller 		offset += read_size;
104e9450990SJacob Keller 	} while (!last_cmd);
105e9450990SJacob Keller 
106e9450990SJacob Keller 	*length = bytes_read;
107e9450990SJacob Keller 	return status;
108e9450990SJacob Keller }
109e9450990SJacob Keller 
110e9450990SJacob Keller /**
111544cd2acSCudzilo, Szymon T  * ice_aq_update_nvm
112544cd2acSCudzilo, Szymon T  * @hw: pointer to the HW struct
113544cd2acSCudzilo, Szymon T  * @module_typeid: module pointer location in words from the NVM beginning
114544cd2acSCudzilo, Szymon T  * @offset: byte offset from the module beginning
115544cd2acSCudzilo, Szymon T  * @length: length of the section to be written (in bytes from the offset)
116544cd2acSCudzilo, Szymon T  * @data: command buffer (size [bytes] = length)
117544cd2acSCudzilo, Szymon T  * @last_command: tells if this is the last command in a series
118544cd2acSCudzilo, Szymon T  * @command_flags: command parameters
119544cd2acSCudzilo, Szymon T  * @cd: pointer to command details structure or NULL
120544cd2acSCudzilo, Szymon T  *
121544cd2acSCudzilo, Szymon T  * Update the NVM using the admin queue commands (0x0703)
122544cd2acSCudzilo, Szymon T  */
123544cd2acSCudzilo, Szymon T enum ice_status
124544cd2acSCudzilo, Szymon T ice_aq_update_nvm(struct ice_hw *hw, u16 module_typeid, u32 offset,
125544cd2acSCudzilo, Szymon T 		  u16 length, void *data, bool last_command, u8 command_flags,
126544cd2acSCudzilo, Szymon T 		  struct ice_sq_cd *cd)
127544cd2acSCudzilo, Szymon T {
128544cd2acSCudzilo, Szymon T 	struct ice_aq_desc desc;
129544cd2acSCudzilo, Szymon T 	struct ice_aqc_nvm *cmd;
130544cd2acSCudzilo, Szymon T 
131544cd2acSCudzilo, Szymon T 	cmd = &desc.params.nvm;
132544cd2acSCudzilo, Szymon T 
133544cd2acSCudzilo, Szymon T 	/* In offset the highest byte must be zeroed. */
134544cd2acSCudzilo, Szymon T 	if (offset & 0xFF000000)
135544cd2acSCudzilo, Szymon T 		return ICE_ERR_PARAM;
136544cd2acSCudzilo, Szymon T 
137544cd2acSCudzilo, Szymon T 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_nvm_write);
138544cd2acSCudzilo, Szymon T 
139544cd2acSCudzilo, Szymon T 	cmd->cmd_flags |= command_flags;
140544cd2acSCudzilo, Szymon T 
141544cd2acSCudzilo, Szymon T 	/* If this is the last command in a series, set the proper flag. */
142544cd2acSCudzilo, Szymon T 	if (last_command)
143544cd2acSCudzilo, Szymon T 		cmd->cmd_flags |= ICE_AQC_NVM_LAST_CMD;
144544cd2acSCudzilo, Szymon T 	cmd->module_typeid = cpu_to_le16(module_typeid);
145544cd2acSCudzilo, Szymon T 	cmd->offset_low = cpu_to_le16(offset & 0xFFFF);
146544cd2acSCudzilo, Szymon T 	cmd->offset_high = (offset >> 16) & 0xFF;
147544cd2acSCudzilo, Szymon T 	cmd->length = cpu_to_le16(length);
148544cd2acSCudzilo, Szymon T 
149544cd2acSCudzilo, Szymon T 	desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
150544cd2acSCudzilo, Szymon T 
151544cd2acSCudzilo, Szymon T 	return ice_aq_send_cmd(hw, &desc, data, length, cd);
152544cd2acSCudzilo, Szymon T }
153544cd2acSCudzilo, Szymon T 
154544cd2acSCudzilo, Szymon T /**
155544cd2acSCudzilo, Szymon T  * ice_aq_erase_nvm
156544cd2acSCudzilo, Szymon T  * @hw: pointer to the HW struct
157544cd2acSCudzilo, Szymon T  * @module_typeid: module pointer location in words from the NVM beginning
158544cd2acSCudzilo, Szymon T  * @cd: pointer to command details structure or NULL
159544cd2acSCudzilo, Szymon T  *
160544cd2acSCudzilo, Szymon T  * Erase the NVM sector using the admin queue commands (0x0702)
161544cd2acSCudzilo, Szymon T  */
162544cd2acSCudzilo, Szymon T enum ice_status
163544cd2acSCudzilo, Szymon T ice_aq_erase_nvm(struct ice_hw *hw, u16 module_typeid, struct ice_sq_cd *cd)
164544cd2acSCudzilo, Szymon T {
165544cd2acSCudzilo, Szymon T 	struct ice_aq_desc desc;
166544cd2acSCudzilo, Szymon T 	struct ice_aqc_nvm *cmd;
167544cd2acSCudzilo, Szymon T 
168544cd2acSCudzilo, Szymon T 	cmd = &desc.params.nvm;
169544cd2acSCudzilo, Szymon T 
170544cd2acSCudzilo, Szymon T 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_nvm_erase);
171544cd2acSCudzilo, Szymon T 
172544cd2acSCudzilo, Szymon T 	cmd->module_typeid = cpu_to_le16(module_typeid);
173544cd2acSCudzilo, Szymon T 	cmd->length = cpu_to_le16(ICE_AQC_NVM_ERASE_LEN);
174544cd2acSCudzilo, Szymon T 	cmd->offset_low = 0;
175544cd2acSCudzilo, Szymon T 	cmd->offset_high = 0;
176544cd2acSCudzilo, Szymon T 
177544cd2acSCudzilo, Szymon T 	return ice_aq_send_cmd(hw, &desc, NULL, 0, cd);
178544cd2acSCudzilo, Szymon T }
179544cd2acSCudzilo, Szymon T 
180544cd2acSCudzilo, Szymon T /**
181f31e4b6fSAnirudh Venkataramanan  * ice_read_sr_word_aq - Reads Shadow RAM via AQ
182f31e4b6fSAnirudh Venkataramanan  * @hw: pointer to the HW structure
183f31e4b6fSAnirudh Venkataramanan  * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF)
184f31e4b6fSAnirudh Venkataramanan  * @data: word read from the Shadow RAM
185f31e4b6fSAnirudh Venkataramanan  *
186e9450990SJacob Keller  * Reads one 16 bit word from the Shadow RAM using ice_read_flat_nvm.
187f31e4b6fSAnirudh Venkataramanan  */
188f31e4b6fSAnirudh Venkataramanan static enum ice_status
189f31e4b6fSAnirudh Venkataramanan ice_read_sr_word_aq(struct ice_hw *hw, u16 offset, u16 *data)
190f31e4b6fSAnirudh Venkataramanan {
191e9450990SJacob Keller 	u32 bytes = sizeof(u16);
192f31e4b6fSAnirudh Venkataramanan 	enum ice_status status;
1932efefb56SJacob Keller 	__le16 data_local;
194f31e4b6fSAnirudh Venkataramanan 
195e9450990SJacob Keller 	/* Note that ice_read_flat_nvm takes into account the 4Kb AdminQ and
196e9450990SJacob Keller 	 * Shadow RAM sector restrictions necessary when reading from the NVM.
197e9450990SJacob Keller 	 */
198e9450990SJacob Keller 	status = ice_read_flat_nvm(hw, offset * sizeof(u16), &bytes,
199e9450990SJacob Keller 				   (u8 *)&data_local, true);
200e9450990SJacob Keller 	if (status)
201f31e4b6fSAnirudh Venkataramanan 		return status;
202e9450990SJacob Keller 
203e9450990SJacob Keller 	*data = le16_to_cpu(data_local);
204e9450990SJacob Keller 	return 0;
205f31e4b6fSAnirudh Venkataramanan }
206f31e4b6fSAnirudh Venkataramanan 
207f31e4b6fSAnirudh Venkataramanan /**
208f31e4b6fSAnirudh Venkataramanan  * ice_acquire_nvm - Generic request for acquiring the NVM ownership
209f31e4b6fSAnirudh Venkataramanan  * @hw: pointer to the HW structure
210f31e4b6fSAnirudh Venkataramanan  * @access: NVM access type (read or write)
211f31e4b6fSAnirudh Venkataramanan  *
212f31e4b6fSAnirudh Venkataramanan  * This function will request NVM ownership.
213f31e4b6fSAnirudh Venkataramanan  */
21484a24798SJesse Brandeburg enum ice_status
2153968540bSAnirudh Venkataramanan ice_acquire_nvm(struct ice_hw *hw, enum ice_aq_res_access_type access)
216f31e4b6fSAnirudh Venkataramanan {
217f31e4b6fSAnirudh Venkataramanan 	if (hw->nvm.blank_nvm_mode)
218f31e4b6fSAnirudh Venkataramanan 		return 0;
219f31e4b6fSAnirudh Venkataramanan 
220ff2b1321SDan Nowlin 	return ice_acquire_res(hw, ICE_NVM_RES_ID, access, ICE_NVM_TIMEOUT);
221f31e4b6fSAnirudh Venkataramanan }
222f31e4b6fSAnirudh Venkataramanan 
223f31e4b6fSAnirudh Venkataramanan /**
224f31e4b6fSAnirudh Venkataramanan  * ice_release_nvm - Generic request for releasing the NVM ownership
225f31e4b6fSAnirudh Venkataramanan  * @hw: pointer to the HW structure
226f31e4b6fSAnirudh Venkataramanan  *
227f31e4b6fSAnirudh Venkataramanan  * This function will release NVM ownership.
228f31e4b6fSAnirudh Venkataramanan  */
22984a24798SJesse Brandeburg void ice_release_nvm(struct ice_hw *hw)
230f31e4b6fSAnirudh Venkataramanan {
231f31e4b6fSAnirudh Venkataramanan 	if (hw->nvm.blank_nvm_mode)
232f31e4b6fSAnirudh Venkataramanan 		return;
233f31e4b6fSAnirudh Venkataramanan 
234f31e4b6fSAnirudh Venkataramanan 	ice_release_res(hw, ICE_NVM_RES_ID);
235f31e4b6fSAnirudh Venkataramanan }
236f31e4b6fSAnirudh Venkataramanan 
237f31e4b6fSAnirudh Venkataramanan /**
238f31e4b6fSAnirudh Venkataramanan  * ice_read_sr_word - Reads Shadow RAM word and acquire NVM if necessary
239f31e4b6fSAnirudh Venkataramanan  * @hw: pointer to the HW structure
240f31e4b6fSAnirudh Venkataramanan  * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF)
241f31e4b6fSAnirudh Venkataramanan  * @data: word read from the Shadow RAM
242f31e4b6fSAnirudh Venkataramanan  *
243f31e4b6fSAnirudh Venkataramanan  * Reads one 16 bit word from the Shadow RAM using the ice_read_sr_word_aq.
244f31e4b6fSAnirudh Venkataramanan  */
245769c500dSAkeem G Abodunrin enum ice_status ice_read_sr_word(struct ice_hw *hw, u16 offset, u16 *data)
246f31e4b6fSAnirudh Venkataramanan {
247f31e4b6fSAnirudh Venkataramanan 	enum ice_status status;
248f31e4b6fSAnirudh Venkataramanan 
249f31e4b6fSAnirudh Venkataramanan 	status = ice_acquire_nvm(hw, ICE_RES_READ);
250f31e4b6fSAnirudh Venkataramanan 	if (!status) {
251f31e4b6fSAnirudh Venkataramanan 		status = ice_read_sr_word_aq(hw, offset, data);
252f31e4b6fSAnirudh Venkataramanan 		ice_release_nvm(hw);
253f31e4b6fSAnirudh Venkataramanan 	}
254f31e4b6fSAnirudh Venkataramanan 
255f31e4b6fSAnirudh Venkataramanan 	return status;
256f31e4b6fSAnirudh Venkataramanan }
257f31e4b6fSAnirudh Venkataramanan 
258f31e4b6fSAnirudh Venkataramanan /**
259e961b679SJacob Keller  * ice_get_pfa_module_tlv - Reads sub module TLV from NVM PFA
260e961b679SJacob Keller  * @hw: pointer to hardware structure
261e961b679SJacob Keller  * @module_tlv: pointer to module TLV to return
262e961b679SJacob Keller  * @module_tlv_len: pointer to module TLV length to return
263e961b679SJacob Keller  * @module_type: module type requested
264e961b679SJacob Keller  *
265e961b679SJacob Keller  * Finds the requested sub module TLV type from the Preserved Field
266e961b679SJacob Keller  * Area (PFA) and returns the TLV pointer and length. The caller can
267e961b679SJacob Keller  * use these to read the variable length TLV value.
268e961b679SJacob Keller  */
269ea78ce4dSPaul Greenwalt enum ice_status
270e961b679SJacob Keller ice_get_pfa_module_tlv(struct ice_hw *hw, u16 *module_tlv, u16 *module_tlv_len,
271e961b679SJacob Keller 		       u16 module_type)
272e961b679SJacob Keller {
273e961b679SJacob Keller 	enum ice_status status;
274e961b679SJacob Keller 	u16 pfa_len, pfa_ptr;
275e961b679SJacob Keller 	u16 next_tlv;
276e961b679SJacob Keller 
277e961b679SJacob Keller 	status = ice_read_sr_word(hw, ICE_SR_PFA_PTR, &pfa_ptr);
278e961b679SJacob Keller 	if (status) {
279e961b679SJacob Keller 		ice_debug(hw, ICE_DBG_INIT, "Preserved Field Array pointer.\n");
280e961b679SJacob Keller 		return status;
281e961b679SJacob Keller 	}
282e961b679SJacob Keller 	status = ice_read_sr_word(hw, pfa_ptr, &pfa_len);
283e961b679SJacob Keller 	if (status) {
284e961b679SJacob Keller 		ice_debug(hw, ICE_DBG_INIT, "Failed to read PFA length.\n");
285e961b679SJacob Keller 		return status;
286e961b679SJacob Keller 	}
287e961b679SJacob Keller 	/* Starting with first TLV after PFA length, iterate through the list
288e961b679SJacob Keller 	 * of TLVs to find the requested one.
289e961b679SJacob Keller 	 */
290e961b679SJacob Keller 	next_tlv = pfa_ptr + 1;
291e961b679SJacob Keller 	while (next_tlv < pfa_ptr + pfa_len) {
292e961b679SJacob Keller 		u16 tlv_sub_module_type;
293e961b679SJacob Keller 		u16 tlv_len;
294e961b679SJacob Keller 
295e961b679SJacob Keller 		/* Read TLV type */
296e961b679SJacob Keller 		status = ice_read_sr_word(hw, next_tlv, &tlv_sub_module_type);
297e961b679SJacob Keller 		if (status) {
298e961b679SJacob Keller 			ice_debug(hw, ICE_DBG_INIT, "Failed to read TLV type.\n");
299e961b679SJacob Keller 			break;
300e961b679SJacob Keller 		}
301e961b679SJacob Keller 		/* Read TLV length */
302e961b679SJacob Keller 		status = ice_read_sr_word(hw, next_tlv + 1, &tlv_len);
303e961b679SJacob Keller 		if (status) {
304e961b679SJacob Keller 			ice_debug(hw, ICE_DBG_INIT, "Failed to read TLV length.\n");
305e961b679SJacob Keller 			break;
306e961b679SJacob Keller 		}
307e961b679SJacob Keller 		if (tlv_sub_module_type == module_type) {
308e961b679SJacob Keller 			if (tlv_len) {
309e961b679SJacob Keller 				*module_tlv = next_tlv;
310e961b679SJacob Keller 				*module_tlv_len = tlv_len;
311e961b679SJacob Keller 				return 0;
312e961b679SJacob Keller 			}
313e961b679SJacob Keller 			return ICE_ERR_INVAL_SIZE;
314e961b679SJacob Keller 		}
315e961b679SJacob Keller 		/* Check next TLV, i.e. current TLV pointer + length + 2 words
316e961b679SJacob Keller 		 * (for current TLV's type and length)
317e961b679SJacob Keller 		 */
318e961b679SJacob Keller 		next_tlv = next_tlv + tlv_len + 2;
319e961b679SJacob Keller 	}
320e961b679SJacob Keller 	/* Module does not exist */
321e961b679SJacob Keller 	return ICE_ERR_DOES_NOT_EXIST;
322e961b679SJacob Keller }
323e961b679SJacob Keller 
324e961b679SJacob Keller /**
325e961b679SJacob Keller  * ice_read_pba_string - Reads part number string from NVM
326e961b679SJacob Keller  * @hw: pointer to hardware structure
327e961b679SJacob Keller  * @pba_num: stores the part number string from the NVM
328e961b679SJacob Keller  * @pba_num_size: part number string buffer length
329e961b679SJacob Keller  *
330e961b679SJacob Keller  * Reads the part number string from the NVM.
331e961b679SJacob Keller  */
332e961b679SJacob Keller enum ice_status
333e961b679SJacob Keller ice_read_pba_string(struct ice_hw *hw, u8 *pba_num, u32 pba_num_size)
334e961b679SJacob Keller {
335e961b679SJacob Keller 	u16 pba_tlv, pba_tlv_len;
336e961b679SJacob Keller 	enum ice_status status;
337e961b679SJacob Keller 	u16 pba_word, pba_size;
338e961b679SJacob Keller 	u16 i;
339e961b679SJacob Keller 
340e961b679SJacob Keller 	status = ice_get_pfa_module_tlv(hw, &pba_tlv, &pba_tlv_len,
341e961b679SJacob Keller 					ICE_SR_PBA_BLOCK_PTR);
342e961b679SJacob Keller 	if (status) {
343e961b679SJacob Keller 		ice_debug(hw, ICE_DBG_INIT, "Failed to read PBA Block TLV.\n");
344e961b679SJacob Keller 		return status;
345e961b679SJacob Keller 	}
346e961b679SJacob Keller 
347e961b679SJacob Keller 	/* pba_size is the next word */
348e961b679SJacob Keller 	status = ice_read_sr_word(hw, (pba_tlv + 2), &pba_size);
349e961b679SJacob Keller 	if (status) {
350e961b679SJacob Keller 		ice_debug(hw, ICE_DBG_INIT, "Failed to read PBA Section size.\n");
351e961b679SJacob Keller 		return status;
352e961b679SJacob Keller 	}
353e961b679SJacob Keller 
354e961b679SJacob Keller 	if (pba_tlv_len < pba_size) {
355e961b679SJacob Keller 		ice_debug(hw, ICE_DBG_INIT, "Invalid PBA Block TLV size.\n");
356e961b679SJacob Keller 		return ICE_ERR_INVAL_SIZE;
357e961b679SJacob Keller 	}
358e961b679SJacob Keller 
359e961b679SJacob Keller 	/* Subtract one to get PBA word count (PBA Size word is included in
360e961b679SJacob Keller 	 * total size)
361e961b679SJacob Keller 	 */
362e961b679SJacob Keller 	pba_size--;
363e961b679SJacob Keller 	if (pba_num_size < (((u32)pba_size * 2) + 1)) {
364e961b679SJacob Keller 		ice_debug(hw, ICE_DBG_INIT, "Buffer too small for PBA data.\n");
365e961b679SJacob Keller 		return ICE_ERR_PARAM;
366e961b679SJacob Keller 	}
367e961b679SJacob Keller 
368e961b679SJacob Keller 	for (i = 0; i < pba_size; i++) {
369e961b679SJacob Keller 		status = ice_read_sr_word(hw, (pba_tlv + 2 + 1) + i, &pba_word);
370e961b679SJacob Keller 		if (status) {
371e961b679SJacob Keller 			ice_debug(hw, ICE_DBG_INIT, "Failed to read PBA Block word %d.\n", i);
372e961b679SJacob Keller 			return status;
373e961b679SJacob Keller 		}
374e961b679SJacob Keller 
375e961b679SJacob Keller 		pba_num[(i * 2)] = (pba_word >> 8) & 0xFF;
376e961b679SJacob Keller 		pba_num[(i * 2) + 1] = pba_word & 0xFF;
377e961b679SJacob Keller 	}
378e961b679SJacob Keller 	pba_num[(pba_size * 2)] = '\0';
379e961b679SJacob Keller 
380e961b679SJacob Keller 	return status;
381e961b679SJacob Keller }
382e961b679SJacob Keller 
383e961b679SJacob Keller /**
384d4e87444SJacob Keller  * ice_get_orom_ver_info - Read Option ROM version information
385d4e87444SJacob Keller  * @hw: pointer to the HW struct
386d4e87444SJacob Keller  *
387d4e87444SJacob Keller  * Read the Combo Image version data from the Boot Configuration TLV and fill
388d4e87444SJacob Keller  * in the option ROM version data.
389d4e87444SJacob Keller  */
390d4e87444SJacob Keller static enum ice_status ice_get_orom_ver_info(struct ice_hw *hw)
391d4e87444SJacob Keller {
392d4e87444SJacob Keller 	u16 combo_hi, combo_lo, boot_cfg_tlv, boot_cfg_tlv_len;
393d4e87444SJacob Keller 	struct ice_orom_info *orom = &hw->nvm.orom;
394d4e87444SJacob Keller 	enum ice_status status;
395d4e87444SJacob Keller 	u32 combo_ver;
396d4e87444SJacob Keller 
397d4e87444SJacob Keller 	status = ice_get_pfa_module_tlv(hw, &boot_cfg_tlv, &boot_cfg_tlv_len,
398d4e87444SJacob Keller 					ICE_SR_BOOT_CFG_PTR);
399d4e87444SJacob Keller 	if (status) {
400d4e87444SJacob Keller 		ice_debug(hw, ICE_DBG_INIT,
401d4e87444SJacob Keller 			  "Failed to read Boot Configuration Block TLV.\n");
402d4e87444SJacob Keller 		return status;
403d4e87444SJacob Keller 	}
404d4e87444SJacob Keller 
405d4e87444SJacob Keller 	/* Boot Configuration Block must have length at least 2 words
406d4e87444SJacob Keller 	 * (Combo Image Version High and Combo Image Version Low)
407d4e87444SJacob Keller 	 */
408d4e87444SJacob Keller 	if (boot_cfg_tlv_len < 2) {
409d4e87444SJacob Keller 		ice_debug(hw, ICE_DBG_INIT,
410d4e87444SJacob Keller 			  "Invalid Boot Configuration Block TLV size.\n");
411d4e87444SJacob Keller 		return ICE_ERR_INVAL_SIZE;
412d4e87444SJacob Keller 	}
413d4e87444SJacob Keller 
414d4e87444SJacob Keller 	status = ice_read_sr_word(hw, (boot_cfg_tlv + ICE_NVM_OROM_VER_OFF),
415d4e87444SJacob Keller 				  &combo_hi);
416d4e87444SJacob Keller 	if (status) {
417d4e87444SJacob Keller 		ice_debug(hw, ICE_DBG_INIT, "Failed to read OROM_VER hi.\n");
418d4e87444SJacob Keller 		return status;
419d4e87444SJacob Keller 	}
420d4e87444SJacob Keller 
421d4e87444SJacob Keller 	status = ice_read_sr_word(hw, (boot_cfg_tlv + ICE_NVM_OROM_VER_OFF + 1),
422d4e87444SJacob Keller 				  &combo_lo);
423d4e87444SJacob Keller 	if (status) {
424d4e87444SJacob Keller 		ice_debug(hw, ICE_DBG_INIT, "Failed to read OROM_VER lo.\n");
425d4e87444SJacob Keller 		return status;
426d4e87444SJacob Keller 	}
427d4e87444SJacob Keller 
428d4e87444SJacob Keller 	combo_ver = ((u32)combo_hi << 16) | combo_lo;
429d4e87444SJacob Keller 
430d4e87444SJacob Keller 	orom->major = (u8)((combo_ver & ICE_OROM_VER_MASK) >>
431d4e87444SJacob Keller 			   ICE_OROM_VER_SHIFT);
432d4e87444SJacob Keller 	orom->patch = (u8)(combo_ver & ICE_OROM_VER_PATCH_MASK);
433d4e87444SJacob Keller 	orom->build = (u16)((combo_ver & ICE_OROM_VER_BUILD_MASK) >>
434d4e87444SJacob Keller 			    ICE_OROM_VER_BUILD_SHIFT);
435d4e87444SJacob Keller 
436d4e87444SJacob Keller 	return 0;
437d4e87444SJacob Keller }
438d4e87444SJacob Keller 
439d4e87444SJacob Keller /**
440f45a645fSJacob Keller  * ice_get_netlist_ver_info
441f45a645fSJacob Keller  * @hw: pointer to the HW struct
442f45a645fSJacob Keller  *
443f45a645fSJacob Keller  * Get the netlist version information
444f45a645fSJacob Keller  */
445f45a645fSJacob Keller static enum ice_status ice_get_netlist_ver_info(struct ice_hw *hw)
446f45a645fSJacob Keller {
447f45a645fSJacob Keller 	struct ice_netlist_ver_info *ver = &hw->netlist_ver;
448f45a645fSJacob Keller 	enum ice_status ret;
449f45a645fSJacob Keller 	u32 id_blk_start;
450f45a645fSJacob Keller 	__le16 raw_data;
451f45a645fSJacob Keller 	u16 data, i;
452f45a645fSJacob Keller 	u16 *buff;
453f45a645fSJacob Keller 
454f45a645fSJacob Keller 	ret = ice_acquire_nvm(hw, ICE_RES_READ);
455f45a645fSJacob Keller 	if (ret)
456f45a645fSJacob Keller 		return ret;
457f45a645fSJacob Keller 	buff = kcalloc(ICE_AQC_NVM_NETLIST_ID_BLK_LEN, sizeof(*buff),
458f45a645fSJacob Keller 		       GFP_KERNEL);
459f45a645fSJacob Keller 	if (!buff) {
460f45a645fSJacob Keller 		ret = ICE_ERR_NO_MEMORY;
461f45a645fSJacob Keller 		goto exit_no_mem;
462f45a645fSJacob Keller 	}
463f45a645fSJacob Keller 
464f45a645fSJacob Keller 	/* read module length */
465f45a645fSJacob Keller 	ret = ice_aq_read_nvm(hw, ICE_AQC_NVM_LINK_TOPO_NETLIST_MOD_ID,
466f45a645fSJacob Keller 			      ICE_AQC_NVM_LINK_TOPO_NETLIST_LEN_OFFSET * 2,
467f45a645fSJacob Keller 			      ICE_AQC_NVM_LINK_TOPO_NETLIST_LEN, &raw_data,
468f45a645fSJacob Keller 			      false, false, NULL);
469f45a645fSJacob Keller 	if (ret)
470f45a645fSJacob Keller 		goto exit_error;
471f45a645fSJacob Keller 
472f45a645fSJacob Keller 	data = le16_to_cpu(raw_data);
473f45a645fSJacob Keller 	/* exit if length is = 0 */
474f45a645fSJacob Keller 	if (!data)
475f45a645fSJacob Keller 		goto exit_error;
476f45a645fSJacob Keller 
477f45a645fSJacob Keller 	/* read node count */
478f45a645fSJacob Keller 	ret = ice_aq_read_nvm(hw, ICE_AQC_NVM_LINK_TOPO_NETLIST_MOD_ID,
479f45a645fSJacob Keller 			      ICE_AQC_NVM_NETLIST_NODE_COUNT_OFFSET * 2,
480f45a645fSJacob Keller 			      ICE_AQC_NVM_NETLIST_NODE_COUNT_LEN, &raw_data,
481f45a645fSJacob Keller 			      false, false, NULL);
482f45a645fSJacob Keller 	if (ret)
483f45a645fSJacob Keller 		goto exit_error;
484f45a645fSJacob Keller 	data = le16_to_cpu(raw_data) & ICE_AQC_NVM_NETLIST_NODE_COUNT_M;
485f45a645fSJacob Keller 
486f45a645fSJacob Keller 	/* netlist ID block starts from offset 4 + node count * 2 */
487f45a645fSJacob Keller 	id_blk_start = ICE_AQC_NVM_NETLIST_ID_BLK_START_OFFSET + data * 2;
488f45a645fSJacob Keller 
489f45a645fSJacob Keller 	/* read the entire netlist ID block */
490f45a645fSJacob Keller 	ret = ice_aq_read_nvm(hw, ICE_AQC_NVM_LINK_TOPO_NETLIST_MOD_ID,
491f45a645fSJacob Keller 			      id_blk_start * 2,
492f45a645fSJacob Keller 			      ICE_AQC_NVM_NETLIST_ID_BLK_LEN * 2, buff, false,
493f45a645fSJacob Keller 			      false, NULL);
494f45a645fSJacob Keller 	if (ret)
495f45a645fSJacob Keller 		goto exit_error;
496f45a645fSJacob Keller 
497f45a645fSJacob Keller 	for (i = 0; i < ICE_AQC_NVM_NETLIST_ID_BLK_LEN; i++)
498f45a645fSJacob Keller 		buff[i] = le16_to_cpu(((__force __le16 *)buff)[i]);
499f45a645fSJacob Keller 
500f45a645fSJacob Keller 	ver->major = (buff[ICE_AQC_NVM_NETLIST_ID_BLK_MAJOR_VER_HIGH] << 16) |
501f45a645fSJacob Keller 		buff[ICE_AQC_NVM_NETLIST_ID_BLK_MAJOR_VER_LOW];
502f45a645fSJacob Keller 	ver->minor = (buff[ICE_AQC_NVM_NETLIST_ID_BLK_MINOR_VER_HIGH] << 16) |
503f45a645fSJacob Keller 		buff[ICE_AQC_NVM_NETLIST_ID_BLK_MINOR_VER_LOW];
504f45a645fSJacob Keller 	ver->type = (buff[ICE_AQC_NVM_NETLIST_ID_BLK_TYPE_HIGH] << 16) |
505f45a645fSJacob Keller 		buff[ICE_AQC_NVM_NETLIST_ID_BLK_TYPE_LOW];
506f45a645fSJacob Keller 	ver->rev = (buff[ICE_AQC_NVM_NETLIST_ID_BLK_REV_HIGH] << 16) |
507f45a645fSJacob Keller 		buff[ICE_AQC_NVM_NETLIST_ID_BLK_REV_LOW];
508f45a645fSJacob Keller 	ver->cust_ver = buff[ICE_AQC_NVM_NETLIST_ID_BLK_CUST_VER];
509f45a645fSJacob Keller 	/* Read the left most 4 bytes of SHA */
510f45a645fSJacob Keller 	ver->hash = buff[ICE_AQC_NVM_NETLIST_ID_BLK_SHA_HASH + 15] << 16 |
511f45a645fSJacob Keller 		buff[ICE_AQC_NVM_NETLIST_ID_BLK_SHA_HASH + 14];
512f45a645fSJacob Keller 
513f45a645fSJacob Keller exit_error:
514f45a645fSJacob Keller 	kfree(buff);
515f45a645fSJacob Keller exit_no_mem:
516f45a645fSJacob Keller 	ice_release_nvm(hw);
517f45a645fSJacob Keller 	return ret;
518f45a645fSJacob Keller }
519f45a645fSJacob Keller 
520f45a645fSJacob Keller /**
52181f07491SJacob Keller  * ice_discover_flash_size - Discover the available flash size.
52281f07491SJacob Keller  * @hw: pointer to the HW struct
52381f07491SJacob Keller  *
52481f07491SJacob Keller  * The device flash could be up to 16MB in size. However, it is possible that
52581f07491SJacob Keller  * the actual size is smaller. Use bisection to determine the accessible size
52681f07491SJacob Keller  * of flash memory.
52781f07491SJacob Keller  */
52881f07491SJacob Keller static enum ice_status ice_discover_flash_size(struct ice_hw *hw)
52981f07491SJacob Keller {
53081f07491SJacob Keller 	u32 min_size = 0, max_size = ICE_AQC_NVM_MAX_OFFSET + 1;
53181f07491SJacob Keller 	enum ice_status status;
53281f07491SJacob Keller 
53381f07491SJacob Keller 	status = ice_acquire_nvm(hw, ICE_RES_READ);
53481f07491SJacob Keller 	if (status)
53581f07491SJacob Keller 		return status;
53681f07491SJacob Keller 
53781f07491SJacob Keller 	while ((max_size - min_size) > 1) {
53881f07491SJacob Keller 		u32 offset = (max_size + min_size) / 2;
53981f07491SJacob Keller 		u32 len = 1;
54081f07491SJacob Keller 		u8 data;
54181f07491SJacob Keller 
54281f07491SJacob Keller 		status = ice_read_flat_nvm(hw, offset, &len, &data, false);
54381f07491SJacob Keller 		if (status == ICE_ERR_AQ_ERROR &&
54481f07491SJacob Keller 		    hw->adminq.sq_last_status == ICE_AQ_RC_EINVAL) {
54581f07491SJacob Keller 			ice_debug(hw, ICE_DBG_NVM,
54681f07491SJacob Keller 				  "%s: New upper bound of %u bytes\n",
54781f07491SJacob Keller 				  __func__, offset);
54881f07491SJacob Keller 			status = 0;
54981f07491SJacob Keller 			max_size = offset;
55081f07491SJacob Keller 		} else if (!status) {
55181f07491SJacob Keller 			ice_debug(hw, ICE_DBG_NVM,
55281f07491SJacob Keller 				  "%s: New lower bound of %u bytes\n",
55381f07491SJacob Keller 				  __func__, offset);
55481f07491SJacob Keller 			min_size = offset;
55581f07491SJacob Keller 		} else {
55681f07491SJacob Keller 			/* an unexpected error occurred */
55781f07491SJacob Keller 			goto err_read_flat_nvm;
55881f07491SJacob Keller 		}
55981f07491SJacob Keller 	}
56081f07491SJacob Keller 
56181f07491SJacob Keller 	ice_debug(hw, ICE_DBG_NVM,
56281f07491SJacob Keller 		  "Predicted flash size is %u bytes\n", max_size);
56381f07491SJacob Keller 
56481f07491SJacob Keller 	hw->nvm.flash_size = max_size;
56581f07491SJacob Keller 
56681f07491SJacob Keller err_read_flat_nvm:
56781f07491SJacob Keller 	ice_release_nvm(hw);
56881f07491SJacob Keller 
56981f07491SJacob Keller 	return status;
57081f07491SJacob Keller }
57181f07491SJacob Keller 
57281f07491SJacob Keller /**
573f31e4b6fSAnirudh Venkataramanan  * ice_init_nvm - initializes NVM setting
574f9867df6SAnirudh Venkataramanan  * @hw: pointer to the HW struct
575f31e4b6fSAnirudh Venkataramanan  *
576f31e4b6fSAnirudh Venkataramanan  * This function reads and populates NVM settings such as Shadow RAM size,
577f31e4b6fSAnirudh Venkataramanan  * max_timeout, and blank_nvm_mode
578f31e4b6fSAnirudh Venkataramanan  */
579f31e4b6fSAnirudh Venkataramanan enum ice_status ice_init_nvm(struct ice_hw *hw)
580f31e4b6fSAnirudh Venkataramanan {
581f31e4b6fSAnirudh Venkataramanan 	struct ice_nvm_info *nvm = &hw->nvm;
582d4e87444SJacob Keller 	u16 eetrack_lo, eetrack_hi, ver;
583031f2147SMd Fahad Iqbal Polash 	enum ice_status status;
584f31e4b6fSAnirudh Venkataramanan 	u32 fla, gens_stat;
585f31e4b6fSAnirudh Venkataramanan 	u8 sr_size;
586f31e4b6fSAnirudh Venkataramanan 
587f9867df6SAnirudh Venkataramanan 	/* The SR size is stored regardless of the NVM programming mode
588f31e4b6fSAnirudh Venkataramanan 	 * as the blank mode may be used in the factory line.
589f31e4b6fSAnirudh Venkataramanan 	 */
590f31e4b6fSAnirudh Venkataramanan 	gens_stat = rd32(hw, GLNVM_GENS);
591f31e4b6fSAnirudh Venkataramanan 	sr_size = (gens_stat & GLNVM_GENS_SR_SIZE_M) >> GLNVM_GENS_SR_SIZE_S;
592f31e4b6fSAnirudh Venkataramanan 
593f31e4b6fSAnirudh Venkataramanan 	/* Switching to words (sr_size contains power of 2) */
594f31e4b6fSAnirudh Venkataramanan 	nvm->sr_words = BIT(sr_size) * ICE_SR_WORDS_IN_1KB;
595f31e4b6fSAnirudh Venkataramanan 
596f31e4b6fSAnirudh Venkataramanan 	/* Check if we are in the normal or blank NVM programming mode */
597f31e4b6fSAnirudh Venkataramanan 	fla = rd32(hw, GLNVM_FLA);
598f31e4b6fSAnirudh Venkataramanan 	if (fla & GLNVM_FLA_LOCKED_M) { /* Normal programming mode */
599f31e4b6fSAnirudh Venkataramanan 		nvm->blank_nvm_mode = false;
600031f2147SMd Fahad Iqbal Polash 	} else {
601031f2147SMd Fahad Iqbal Polash 		/* Blank programming mode */
602f31e4b6fSAnirudh Venkataramanan 		nvm->blank_nvm_mode = true;
603f31e4b6fSAnirudh Venkataramanan 		ice_debug(hw, ICE_DBG_NVM,
604f31e4b6fSAnirudh Venkataramanan 			  "NVM init error: unsupported blank mode.\n");
605031f2147SMd Fahad Iqbal Polash 		return ICE_ERR_NVM_BLANK_MODE;
606f31e4b6fSAnirudh Venkataramanan 	}
607f31e4b6fSAnirudh Venkataramanan 
608d4e87444SJacob Keller 	status = ice_read_sr_word(hw, ICE_SR_NVM_DEV_STARTER_VER, &ver);
609f31e4b6fSAnirudh Venkataramanan 	if (status) {
610f31e4b6fSAnirudh Venkataramanan 		ice_debug(hw, ICE_DBG_INIT,
611f31e4b6fSAnirudh Venkataramanan 			  "Failed to read DEV starter version.\n");
612f31e4b6fSAnirudh Venkataramanan 		return status;
613f31e4b6fSAnirudh Venkataramanan 	}
614d4e87444SJacob Keller 	nvm->major_ver = (ver & ICE_NVM_VER_HI_MASK) >> ICE_NVM_VER_HI_SHIFT;
615d4e87444SJacob Keller 	nvm->minor_ver = (ver & ICE_NVM_VER_LO_MASK) >> ICE_NVM_VER_LO_SHIFT;
616f31e4b6fSAnirudh Venkataramanan 
617f31e4b6fSAnirudh Venkataramanan 	status = ice_read_sr_word(hw, ICE_SR_NVM_EETRACK_LO, &eetrack_lo);
618f31e4b6fSAnirudh Venkataramanan 	if (status) {
619f31e4b6fSAnirudh Venkataramanan 		ice_debug(hw, ICE_DBG_INIT, "Failed to read EETRACK lo.\n");
620f31e4b6fSAnirudh Venkataramanan 		return status;
621f31e4b6fSAnirudh Venkataramanan 	}
622f31e4b6fSAnirudh Venkataramanan 	status = ice_read_sr_word(hw, ICE_SR_NVM_EETRACK_HI, &eetrack_hi);
623f31e4b6fSAnirudh Venkataramanan 	if (status) {
624f31e4b6fSAnirudh Venkataramanan 		ice_debug(hw, ICE_DBG_INIT, "Failed to read EETRACK hi.\n");
625f31e4b6fSAnirudh Venkataramanan 		return status;
626f31e4b6fSAnirudh Venkataramanan 	}
627f31e4b6fSAnirudh Venkataramanan 
628031f2147SMd Fahad Iqbal Polash 	nvm->eetrack = (eetrack_hi << 16) | eetrack_lo;
629f31e4b6fSAnirudh Venkataramanan 
63081f07491SJacob Keller 	status = ice_discover_flash_size(hw);
63181f07491SJacob Keller 	if (status) {
63281f07491SJacob Keller 		ice_debug(hw, ICE_DBG_NVM,
63381f07491SJacob Keller 			  "NVM init error: failed to discover flash size.\n");
63481f07491SJacob Keller 		return status;
63581f07491SJacob Keller 	}
63681f07491SJacob Keller 
637e36aeec0SBruce Allan 	switch (hw->device_id) {
6385d9e618cSJacob Keller 	/* the following devices do not have boot_cfg_tlv yet */
639e36aeec0SBruce Allan 	case ICE_DEV_ID_E823C_BACKPLANE:
640e36aeec0SBruce Allan 	case ICE_DEV_ID_E823C_QSFP:
641e36aeec0SBruce Allan 	case ICE_DEV_ID_E823C_SFP:
642e36aeec0SBruce Allan 	case ICE_DEV_ID_E823C_10G_BASE_T:
643e36aeec0SBruce Allan 	case ICE_DEV_ID_E823C_SGMII:
644e36aeec0SBruce Allan 	case ICE_DEV_ID_E822C_BACKPLANE:
645e36aeec0SBruce Allan 	case ICE_DEV_ID_E822C_QSFP:
646e36aeec0SBruce Allan 	case ICE_DEV_ID_E822C_10G_BASE_T:
647e36aeec0SBruce Allan 	case ICE_DEV_ID_E822C_SGMII:
648e36aeec0SBruce Allan 	case ICE_DEV_ID_E822C_SFP:
6492fbfa966SBruce Allan 	case ICE_DEV_ID_E822L_BACKPLANE:
650e36aeec0SBruce Allan 	case ICE_DEV_ID_E822L_SFP:
651e36aeec0SBruce Allan 	case ICE_DEV_ID_E822L_10G_BASE_T:
652e36aeec0SBruce Allan 	case ICE_DEV_ID_E822L_SGMII:
653e36aeec0SBruce Allan 	case ICE_DEV_ID_E823L_BACKPLANE:
654e36aeec0SBruce Allan 	case ICE_DEV_ID_E823L_SFP:
655e36aeec0SBruce Allan 	case ICE_DEV_ID_E823L_10G_BASE_T:
656e36aeec0SBruce Allan 	case ICE_DEV_ID_E823L_1GBE:
657e36aeec0SBruce Allan 	case ICE_DEV_ID_E823L_QSFP:
6585d9e618cSJacob Keller 		return status;
659e36aeec0SBruce Allan 	default:
660e36aeec0SBruce Allan 		break;
661e36aeec0SBruce Allan 	}
6625d9e618cSJacob Keller 
663d4e87444SJacob Keller 	status = ice_get_orom_ver_info(hw);
664031f2147SMd Fahad Iqbal Polash 	if (status) {
665d4e87444SJacob Keller 		ice_debug(hw, ICE_DBG_INIT, "Failed to read Option ROM info.\n");
666f31e4b6fSAnirudh Venkataramanan 		return status;
667f31e4b6fSAnirudh Venkataramanan 	}
6684c98ab55SBruce Allan 
669f45a645fSJacob Keller 	/* read the netlist version information */
670f45a645fSJacob Keller 	status = ice_get_netlist_ver_info(hw);
671f45a645fSJacob Keller 	if (status)
672f45a645fSJacob Keller 		ice_debug(hw, ICE_DBG_INIT, "Failed to read netlist info.\n");
673f45a645fSJacob Keller 
674031f2147SMd Fahad Iqbal Polash 	return 0;
675031f2147SMd Fahad Iqbal Polash }
676031f2147SMd Fahad Iqbal Polash 
6774c98ab55SBruce Allan /**
6780e674aebSAnirudh Venkataramanan  * ice_nvm_validate_checksum
6790e674aebSAnirudh Venkataramanan  * @hw: pointer to the HW struct
6800e674aebSAnirudh Venkataramanan  *
6810e674aebSAnirudh Venkataramanan  * Verify NVM PFA checksum validity (0x0706)
6820e674aebSAnirudh Venkataramanan  */
6830e674aebSAnirudh Venkataramanan enum ice_status ice_nvm_validate_checksum(struct ice_hw *hw)
6840e674aebSAnirudh Venkataramanan {
6850e674aebSAnirudh Venkataramanan 	struct ice_aqc_nvm_checksum *cmd;
6860e674aebSAnirudh Venkataramanan 	struct ice_aq_desc desc;
6870e674aebSAnirudh Venkataramanan 	enum ice_status status;
6880e674aebSAnirudh Venkataramanan 
6890e674aebSAnirudh Venkataramanan 	status = ice_acquire_nvm(hw, ICE_RES_READ);
6900e674aebSAnirudh Venkataramanan 	if (status)
6910e674aebSAnirudh Venkataramanan 		return status;
6920e674aebSAnirudh Venkataramanan 
6930e674aebSAnirudh Venkataramanan 	cmd = &desc.params.nvm_checksum;
6940e674aebSAnirudh Venkataramanan 
6950e674aebSAnirudh Venkataramanan 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_nvm_checksum);
6960e674aebSAnirudh Venkataramanan 	cmd->flags = ICE_AQC_NVM_CHECKSUM_VERIFY;
6970e674aebSAnirudh Venkataramanan 
6980e674aebSAnirudh Venkataramanan 	status = ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
6990e674aebSAnirudh Venkataramanan 	ice_release_nvm(hw);
7000e674aebSAnirudh Venkataramanan 
7010e674aebSAnirudh Venkataramanan 	if (!status)
7020e674aebSAnirudh Venkataramanan 		if (le16_to_cpu(cmd->checksum) != ICE_AQC_NVM_CHECKSUM_CORRECT)
7030e674aebSAnirudh Venkataramanan 			status = ICE_ERR_NVM_CHECKSUM;
7040e674aebSAnirudh Venkataramanan 
7050e674aebSAnirudh Venkataramanan 	return status;
7060e674aebSAnirudh Venkataramanan }
707544cd2acSCudzilo, Szymon T 
708544cd2acSCudzilo, Szymon T /**
709544cd2acSCudzilo, Szymon T  * ice_nvm_write_activate
710544cd2acSCudzilo, Szymon T  * @hw: pointer to the HW struct
711544cd2acSCudzilo, Szymon T  * @cmd_flags: NVM activate admin command bits (banks to be validated)
712544cd2acSCudzilo, Szymon T  *
713544cd2acSCudzilo, Szymon T  * Update the control word with the required banks' validity bits
714544cd2acSCudzilo, Szymon T  * and dumps the Shadow RAM to flash (0x0707)
715544cd2acSCudzilo, Szymon T  */
716544cd2acSCudzilo, Szymon T enum ice_status ice_nvm_write_activate(struct ice_hw *hw, u8 cmd_flags)
717544cd2acSCudzilo, Szymon T {
718544cd2acSCudzilo, Szymon T 	struct ice_aqc_nvm *cmd;
719544cd2acSCudzilo, Szymon T 	struct ice_aq_desc desc;
720544cd2acSCudzilo, Szymon T 
721544cd2acSCudzilo, Szymon T 	cmd = &desc.params.nvm;
722544cd2acSCudzilo, Szymon T 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_nvm_write_activate);
723544cd2acSCudzilo, Szymon T 
724544cd2acSCudzilo, Szymon T 	cmd->cmd_flags = cmd_flags;
725544cd2acSCudzilo, Szymon T 
726544cd2acSCudzilo, Szymon T 	return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
727544cd2acSCudzilo, Szymon T }
728544cd2acSCudzilo, Szymon T 
729544cd2acSCudzilo, Szymon T /**
730544cd2acSCudzilo, Szymon T  * ice_aq_nvm_update_empr
731544cd2acSCudzilo, Szymon T  * @hw: pointer to the HW struct
732544cd2acSCudzilo, Szymon T  *
733544cd2acSCudzilo, Szymon T  * Update empr (0x0709). This command allows SW to
734544cd2acSCudzilo, Szymon T  * request an EMPR to activate new FW.
735544cd2acSCudzilo, Szymon T  */
736544cd2acSCudzilo, Szymon T enum ice_status ice_aq_nvm_update_empr(struct ice_hw *hw)
737544cd2acSCudzilo, Szymon T {
738544cd2acSCudzilo, Szymon T 	struct ice_aq_desc desc;
739544cd2acSCudzilo, Szymon T 
740544cd2acSCudzilo, Szymon T 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_nvm_update_empr);
741544cd2acSCudzilo, Szymon T 
742544cd2acSCudzilo, Szymon T 	return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
743544cd2acSCudzilo, Szymon T }
744544cd2acSCudzilo, Szymon T 
745544cd2acSCudzilo, Szymon T /* ice_nvm_set_pkg_data
746544cd2acSCudzilo, Szymon T  * @hw: pointer to the HW struct
747544cd2acSCudzilo, Szymon T  * @del_pkg_data_flag: If is set then the current pkg_data store by FW
748544cd2acSCudzilo, Szymon T  *		       is deleted.
749544cd2acSCudzilo, Szymon T  *		       If bit is set to 1, then buffer should be size 0.
750544cd2acSCudzilo, Szymon T  * @data: pointer to buffer
751544cd2acSCudzilo, Szymon T  * @length: length of the buffer
752544cd2acSCudzilo, Szymon T  * @cd: pointer to command details structure or NULL
753544cd2acSCudzilo, Szymon T  *
754544cd2acSCudzilo, Szymon T  * Set package data (0x070A). This command is equivalent to the reception
755544cd2acSCudzilo, Szymon T  * of a PLDM FW Update GetPackageData cmd. This command should be sent
756544cd2acSCudzilo, Szymon T  * as part of the NVM update as the first cmd in the flow.
757544cd2acSCudzilo, Szymon T  */
758544cd2acSCudzilo, Szymon T 
759544cd2acSCudzilo, Szymon T enum ice_status
760544cd2acSCudzilo, Szymon T ice_nvm_set_pkg_data(struct ice_hw *hw, bool del_pkg_data_flag, u8 *data,
761544cd2acSCudzilo, Szymon T 		     u16 length, struct ice_sq_cd *cd)
762544cd2acSCudzilo, Szymon T {
763544cd2acSCudzilo, Szymon T 	struct ice_aqc_nvm_pkg_data *cmd;
764544cd2acSCudzilo, Szymon T 	struct ice_aq_desc desc;
765544cd2acSCudzilo, Szymon T 
766544cd2acSCudzilo, Szymon T 	if (length != 0 && !data)
767544cd2acSCudzilo, Szymon T 		return ICE_ERR_PARAM;
768544cd2acSCudzilo, Szymon T 
769544cd2acSCudzilo, Szymon T 	cmd = &desc.params.pkg_data;
770544cd2acSCudzilo, Szymon T 
771544cd2acSCudzilo, Szymon T 	ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_nvm_pkg_data);
772544cd2acSCudzilo, Szymon T 	desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
773544cd2acSCudzilo, Szymon T 
774544cd2acSCudzilo, Szymon T 	if (del_pkg_data_flag)
775544cd2acSCudzilo, Szymon T 		cmd->cmd_flags |= ICE_AQC_NVM_PKG_DELETE;
776544cd2acSCudzilo, Szymon T 
777544cd2acSCudzilo, Szymon T 	return ice_aq_send_cmd(hw, &desc, data, length, cd);
778544cd2acSCudzilo, Szymon T }
779544cd2acSCudzilo, Szymon T 
780544cd2acSCudzilo, Szymon T /* ice_nvm_pass_component_tbl
781544cd2acSCudzilo, Szymon T  * @hw: pointer to the HW struct
782544cd2acSCudzilo, Szymon T  * @data: pointer to buffer
783544cd2acSCudzilo, Szymon T  * @length: length of the buffer
784544cd2acSCudzilo, Szymon T  * @transfer_flag: parameter for determining stage of the update
785544cd2acSCudzilo, Szymon T  * @comp_response: a pointer to the response from the 0x070B AQC.
786544cd2acSCudzilo, Szymon T  * @comp_response_code: a pointer to the response code from the 0x070B AQC.
787544cd2acSCudzilo, Szymon T  * @cd: pointer to command details structure or NULL
788544cd2acSCudzilo, Szymon T  *
789544cd2acSCudzilo, Szymon T  * Pass component table (0x070B). This command is equivalent to the reception
790544cd2acSCudzilo, Szymon T  * of a PLDM FW Update PassComponentTable cmd. This command should be sent once
791544cd2acSCudzilo, Szymon T  * per component. It can be only sent after Set Package Data cmd and before
792544cd2acSCudzilo, Szymon T  * actual update. FW will assume these commands are going to be sent until
793544cd2acSCudzilo, Szymon T  * the TransferFlag is set to End or StartAndEnd.
794544cd2acSCudzilo, Szymon T  */
795544cd2acSCudzilo, Szymon T 
796544cd2acSCudzilo, Szymon T enum ice_status
797544cd2acSCudzilo, Szymon T ice_nvm_pass_component_tbl(struct ice_hw *hw, u8 *data, u16 length,
798544cd2acSCudzilo, Szymon T 			   u8 transfer_flag, u8 *comp_response,
799544cd2acSCudzilo, Szymon T 			   u8 *comp_response_code, struct ice_sq_cd *cd)
800544cd2acSCudzilo, Szymon T {
801544cd2acSCudzilo, Szymon T 	struct ice_aqc_nvm_pass_comp_tbl *cmd;
802544cd2acSCudzilo, Szymon T 	struct ice_aq_desc desc;
803544cd2acSCudzilo, Szymon T 	enum ice_status status;
804544cd2acSCudzilo, Szymon T 
805544cd2acSCudzilo, Szymon T 	if (!data || !comp_response || !comp_response_code)
806544cd2acSCudzilo, Szymon T 		return ICE_ERR_PARAM;
807544cd2acSCudzilo, Szymon T 
808544cd2acSCudzilo, Szymon T 	cmd = &desc.params.pass_comp_tbl;
809544cd2acSCudzilo, Szymon T 
810544cd2acSCudzilo, Szymon T 	ice_fill_dflt_direct_cmd_desc(&desc,
811544cd2acSCudzilo, Szymon T 				      ice_aqc_opc_nvm_pass_component_tbl);
812544cd2acSCudzilo, Szymon T 	desc.flags |= cpu_to_le16(ICE_AQ_FLAG_RD);
813544cd2acSCudzilo, Szymon T 
814544cd2acSCudzilo, Szymon T 	cmd->transfer_flag = transfer_flag;
815544cd2acSCudzilo, Szymon T 	status = ice_aq_send_cmd(hw, &desc, data, length, cd);
816544cd2acSCudzilo, Szymon T 
817544cd2acSCudzilo, Szymon T 	if (!status) {
818544cd2acSCudzilo, Szymon T 		*comp_response = cmd->component_response;
819544cd2acSCudzilo, Szymon T 		*comp_response_code = cmd->component_response_code;
820544cd2acSCudzilo, Szymon T 	}
821544cd2acSCudzilo, Szymon T 	return status;
822544cd2acSCudzilo, Szymon T }
823