xref: /dpdk/drivers/net/ngbe/base/ngbe_eeprom.c (revision b53d106d34b5c638f5a2cbdfee0da5bd42d4383f)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2018-2021 Beijing WangXun Technology Co., Ltd.
3  * Copyright(c) 2010-2017 Intel Corporation
4  */
5 
6 #include "ngbe_hw.h"
7 #include "ngbe_mng.h"
8 #include "ngbe_eeprom.h"
9 
10 /**
11  *  ngbe_init_eeprom_params - Initialize EEPROM params
12  *  @hw: pointer to hardware structure
13  *
14  *  Initializes the EEPROM parameters ngbe_rom_info within the
15  *  ngbe_hw struct in order to set up EEPROM access.
16  **/
17 s32 ngbe_init_eeprom_params(struct ngbe_hw *hw)
18 {
19 	struct ngbe_rom_info *eeprom = &hw->rom;
20 	u32 eec;
21 	u16 eeprom_size;
22 
23 	DEBUGFUNC("ngbe_init_eeprom_params");
24 
25 	if (eeprom->type != ngbe_eeprom_unknown)
26 		return 0;
27 
28 	eeprom->type = ngbe_eeprom_none;
29 	/* Set default semaphore delay to 10ms which is a well
30 	 * tested value
31 	 */
32 	eeprom->semaphore_delay = 10; /*ms*/
33 	/* Clear EEPROM page size, it will be initialized as needed */
34 	eeprom->word_page_size = 0;
35 
36 	/*
37 	 * Check for EEPROM present first.
38 	 * If not present leave as none
39 	 */
40 	eec = rd32(hw, NGBE_SPISTAT);
41 	if (!(eec & NGBE_SPISTAT_BPFLASH)) {
42 		eeprom->type = ngbe_eeprom_flash;
43 
44 		/*
45 		 * SPI EEPROM is assumed here.  This code would need to
46 		 * change if a future EEPROM is not SPI.
47 		 */
48 		eeprom_size = 4096;
49 		eeprom->word_size = eeprom_size >> 1;
50 	}
51 
52 	eeprom->address_bits = 16;
53 	eeprom->sw_addr = 0x80;
54 
55 	DEBUGOUT("eeprom params: type = %d, size = %d, address bits: "
56 		  "%d %d\n", eeprom->type, eeprom->word_size,
57 		  eeprom->address_bits, eeprom->sw_addr);
58 
59 	return 0;
60 }
61 
62 /**
63  *  ngbe_get_eeprom_semaphore - Get hardware semaphore
64  *  @hw: pointer to hardware structure
65  *
66  *  Sets the hardware semaphores so EEPROM access can occur for bit-bang method
67  **/
68 s32 ngbe_get_eeprom_semaphore(struct ngbe_hw *hw)
69 {
70 	s32 status = NGBE_ERR_EEPROM;
71 	u32 timeout = 2000;
72 	u32 i;
73 	u32 swsm;
74 
75 	DEBUGFUNC("ngbe_get_eeprom_semaphore");
76 
77 
78 	/* Get SMBI software semaphore between device drivers first */
79 	for (i = 0; i < timeout; i++) {
80 		/*
81 		 * If the SMBI bit is 0 when we read it, then the bit will be
82 		 * set and we have the semaphore
83 		 */
84 		swsm = rd32(hw, NGBE_SWSEM);
85 		if (!(swsm & NGBE_SWSEM_PF)) {
86 			status = 0;
87 			break;
88 		}
89 		usec_delay(50);
90 	}
91 
92 	if (i == timeout) {
93 		DEBUGOUT("Driver can't access the eeprom - SMBI Semaphore "
94 			 "not granted.\n");
95 		/*
96 		 * this release is particularly important because our attempts
97 		 * above to get the semaphore may have succeeded, and if there
98 		 * was a timeout, we should unconditionally clear the semaphore
99 		 * bits to free the driver to make progress
100 		 */
101 		ngbe_release_eeprom_semaphore(hw);
102 
103 		usec_delay(50);
104 		/*
105 		 * one last try
106 		 * If the SMBI bit is 0 when we read it, then the bit will be
107 		 * set and we have the semaphore
108 		 */
109 		swsm = rd32(hw, NGBE_SWSEM);
110 		if (!(swsm & NGBE_SWSEM_PF))
111 			status = 0;
112 	}
113 
114 	/* Now get the semaphore between SW/FW through the SWESMBI bit */
115 	if (status == 0) {
116 		for (i = 0; i < timeout; i++) {
117 			/* Set the SW EEPROM semaphore bit to request access */
118 			wr32m(hw, NGBE_MNGSWSYNC,
119 				NGBE_MNGSWSYNC_REQ, NGBE_MNGSWSYNC_REQ);
120 
121 			/*
122 			 * If we set the bit successfully then we got the
123 			 * semaphore.
124 			 */
125 			swsm = rd32(hw, NGBE_MNGSWSYNC);
126 			if (swsm & NGBE_MNGSWSYNC_REQ)
127 				break;
128 
129 			usec_delay(50);
130 		}
131 
132 		/*
133 		 * Release semaphores and return error if SW EEPROM semaphore
134 		 * was not granted because we don't have access to the EEPROM
135 		 */
136 		if (i >= timeout) {
137 			DEBUGOUT("SWESMBI Software EEPROM semaphore not granted.\n");
138 			ngbe_release_eeprom_semaphore(hw);
139 			status = NGBE_ERR_EEPROM;
140 		}
141 	} else {
142 		DEBUGOUT("Software semaphore SMBI between device drivers "
143 			 "not granted.\n");
144 	}
145 
146 	return status;
147 }
148 
149 /**
150  *  ngbe_release_eeprom_semaphore - Release hardware semaphore
151  *  @hw: pointer to hardware structure
152  *
153  *  This function clears hardware semaphore bits.
154  **/
155 void ngbe_release_eeprom_semaphore(struct ngbe_hw *hw)
156 {
157 	DEBUGFUNC("ngbe_release_eeprom_semaphore");
158 
159 	wr32m(hw, NGBE_MNGSWSYNC, NGBE_MNGSWSYNC_REQ, 0);
160 	wr32m(hw, NGBE_SWSEM, NGBE_SWSEM_PF, 0);
161 	ngbe_flush(hw);
162 }
163 
164 /**
165  *  ngbe_ee_read_buffer- Read EEPROM word(s) using hostif
166  *  @hw: pointer to hardware structure
167  *  @offset: offset of  word in the EEPROM to read
168  *  @words: number of words
169  *  @data: word(s) read from the EEPROM
170  *
171  *  Reads a 16 bit word(s) from the EEPROM using the hostif.
172  **/
173 s32 ngbe_ee_readw_buffer(struct ngbe_hw *hw,
174 				     u32 offset, u32 words, void *data)
175 {
176 	const u32 mask = NGBE_MNGSEM_SWMBX | NGBE_MNGSEM_SWFLASH;
177 	u32 addr = (offset << 1);
178 	u32 len = (words << 1);
179 	u8 *buf = (u8 *)data;
180 	int err;
181 
182 	err = hw->mac.acquire_swfw_sync(hw, mask);
183 	if (err)
184 		return err;
185 
186 	while (len) {
187 		u32 seg = (len <= NGBE_PMMBX_DATA_SIZE
188 				? len : NGBE_PMMBX_DATA_SIZE);
189 
190 		err = ngbe_hic_sr_read(hw, addr, buf, seg);
191 		if (err)
192 			break;
193 
194 		len -= seg;
195 		addr += seg;
196 		buf += seg;
197 	}
198 
199 	hw->mac.release_swfw_sync(hw, mask);
200 	return err;
201 }
202 
203 /**
204  *  ngbe_ee_read32 - Read EEPROM word using a host interface cmd
205  *  @hw: pointer to hardware structure
206  *  @offset: offset of  word in the EEPROM to read
207  *  @data: word read from the EEPROM
208  *
209  *  Reads a 32 bit word from the EEPROM using the hostif.
210  **/
211 s32 ngbe_ee_read32(struct ngbe_hw *hw, u32 addr, u32 *data)
212 {
213 	const u32 mask = NGBE_MNGSEM_SWMBX | NGBE_MNGSEM_SWFLASH;
214 	int err;
215 
216 	err = hw->mac.acquire_swfw_sync(hw, mask);
217 	if (err)
218 		return err;
219 
220 	err = ngbe_hic_sr_read(hw, addr, (u8 *)data, 4);
221 
222 	hw->mac.release_swfw_sync(hw, mask);
223 
224 	return err;
225 }
226 
227 /**
228  *  ngbe_ee_write_buffer - Write EEPROM word(s) using hostif
229  *  @hw: pointer to hardware structure
230  *  @offset: offset of  word in the EEPROM to write
231  *  @words: number of words
232  *  @data: word(s) write to the EEPROM
233  *
234  *  Write a 16 bit word(s) to the EEPROM using the hostif.
235  **/
236 s32 ngbe_ee_writew_buffer(struct ngbe_hw *hw,
237 				      u32 offset, u32 words, void *data)
238 {
239 	const u32 mask = NGBE_MNGSEM_SWMBX | NGBE_MNGSEM_SWFLASH;
240 	u32 addr = (offset << 1);
241 	u32 len = (words << 1);
242 	u8 *buf = (u8 *)data;
243 	int err;
244 
245 	err = hw->mac.acquire_swfw_sync(hw, mask);
246 	if (err)
247 		return err;
248 
249 	while (len) {
250 		u32 seg = (len <= NGBE_PMMBX_DATA_SIZE
251 				? len : NGBE_PMMBX_DATA_SIZE);
252 
253 		err = ngbe_hic_sr_write(hw, addr, buf, seg);
254 		if (err)
255 			break;
256 
257 		len -= seg;
258 		buf += seg;
259 	}
260 
261 	hw->mac.release_swfw_sync(hw, mask);
262 	return err;
263 }
264 
265 /**
266  *  ngbe_validate_eeprom_checksum_em - Validate EEPROM checksum
267  *  @hw: pointer to hardware structure
268  *  @checksum_val: calculated checksum
269  *
270  *  Performs checksum calculation and validates the EEPROM checksum.  If the
271  *  caller does not need checksum_val, the value can be NULL.
272  **/
273 s32 ngbe_validate_eeprom_checksum_em(struct ngbe_hw *hw,
274 					   u16 *checksum_val)
275 {
276 	u32 eeprom_cksum_devcap = 0;
277 	int err = 0;
278 
279 	DEBUGFUNC("ngbe_validate_eeprom_checksum_em");
280 	UNREFERENCED_PARAMETER(checksum_val);
281 
282 	/* Check EEPROM only once */
283 	if (hw->bus.lan_id == 0) {
284 		wr32(hw, NGBE_CALSUM_CAP_STATUS, 0x0);
285 		wr32(hw, NGBE_EEPROM_VERSION_STORE_REG, 0x0);
286 	} else {
287 		eeprom_cksum_devcap = rd32(hw, NGBE_CALSUM_CAP_STATUS);
288 		hw->rom.saved_version = rd32(hw, NGBE_EEPROM_VERSION_STORE_REG);
289 	}
290 
291 	if (hw->bus.lan_id == 0 || eeprom_cksum_devcap == 0) {
292 		err = ngbe_hic_check_cap(hw);
293 		if (err != 0) {
294 			PMD_INIT_LOG(ERR,
295 				"The EEPROM checksum is not valid: %d", err);
296 			return -EIO;
297 		}
298 	}
299 
300 	hw->rom.cksum_devcap = eeprom_cksum_devcap & 0xffff;
301 
302 	return err;
303 }
304 
305 /**
306  * ngbe_save_eeprom_version
307  * @hw: pointer to hardware structure
308  *
309  * Save off EEPROM version number and Option Rom version which
310  * together make a unique identify for the eeprom
311  */
312 s32 ngbe_save_eeprom_version(struct ngbe_hw *hw)
313 {
314 	u32 eeprom_verl = 0;
315 	u32 etrack_id = 0;
316 	u32 offset = (hw->rom.sw_addr + NGBE_EEPROM_VERSION_L) << 1;
317 
318 	DEBUGFUNC("ngbe_save_eeprom_version");
319 
320 	if (hw->bus.lan_id == 0) {
321 		hw->rom.read32(hw, offset, &eeprom_verl);
322 		etrack_id = eeprom_verl;
323 		wr32(hw, NGBE_EEPROM_VERSION_STORE_REG, etrack_id);
324 		wr32(hw, NGBE_CALSUM_CAP_STATUS,
325 			hw->rom.cksum_devcap | 0x10000);
326 	} else if (hw->rom.cksum_devcap) {
327 		etrack_id = hw->rom.saved_version;
328 	} else {
329 		hw->rom.read32(hw, offset, &eeprom_verl);
330 		etrack_id = eeprom_verl;
331 	}
332 
333 	hw->eeprom_id = etrack_id;
334 
335 	return 0;
336 }
337