xref: /dpdk/drivers/net/txgbe/base/txgbe_eeprom.c (revision d0b8a4e1)
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_hw.h"
7 #include "txgbe_mng.h"
8 #include "txgbe_eeprom.h"
9 
10 /**
11  *  txgbe_init_eeprom_params - Initialize EEPROM params
12  *  @hw: pointer to hardware structure
13  *
14  *  Initializes the EEPROM parameters txgbe_rom_info within the
15  *  txgbe_hw struct in order to set up EEPROM access.
16  **/
17 s32 txgbe_init_eeprom_params(struct txgbe_hw *hw)
18 {
19 	struct txgbe_rom_info *eeprom = &hw->rom;
20 	u32 eec;
21 	u16 eeprom_size;
22 	int err = 0;
23 
24 	DEBUGFUNC("txgbe_init_eeprom_params");
25 
26 	if (eeprom->type != txgbe_eeprom_unknown)
27 		return 0;
28 
29 	eeprom->type = txgbe_eeprom_none;
30 	/* Set default semaphore delay to 10ms which is a well
31 	 * tested value
32 	 */
33 	eeprom->semaphore_delay = 10; /*ms*/
34 	/* Clear EEPROM page size, it will be initialized as needed */
35 	eeprom->word_page_size = 0;
36 
37 	/*
38 	 * Check for EEPROM present first.
39 	 * If not present leave as none
40 	 */
41 	eec = rd32(hw, TXGBE_SPISTAT);
42 	if (!(eec & TXGBE_SPISTAT_BPFLASH)) {
43 		eeprom->type = txgbe_eeprom_flash;
44 
45 		/*
46 		 * SPI EEPROM is assumed here.  This code would need to
47 		 * change if a future EEPROM is not SPI.
48 		 */
49 		eeprom_size = 4096;
50 		eeprom->word_size = eeprom_size >> 1;
51 	}
52 
53 	eeprom->address_bits = 16;
54 
55 	err = eeprom->read32(hw, TXGBE_SW_REGION_PTR << 1, &eeprom->sw_addr);
56 	if (err) {
57 		DEBUGOUT("EEPROM read failed.\n");
58 		return err;
59 	}
60 
61 	DEBUGOUT("eeprom params: type = %d, size = %d, address bits: "
62 		  "%d %d\n", eeprom->type, eeprom->word_size,
63 		  eeprom->address_bits, eeprom->sw_addr);
64 
65 	return 0;
66 }
67 
68 /**
69  *  txgbe_get_eeprom_semaphore - Get hardware semaphore
70  *  @hw: pointer to hardware structure
71  *
72  *  Sets the hardware semaphores so EEPROM access can occur for bit-bang method
73  **/
74 s32 txgbe_get_eeprom_semaphore(struct txgbe_hw *hw)
75 {
76 	s32 status = TXGBE_ERR_EEPROM;
77 	u32 timeout = 2000;
78 	u32 i;
79 	u32 swsm;
80 
81 	DEBUGFUNC("txgbe_get_eeprom_semaphore");
82 
83 
84 	/* Get SMBI software semaphore between device drivers first */
85 	for (i = 0; i < timeout; i++) {
86 		/*
87 		 * If the SMBI bit is 0 when we read it, then the bit will be
88 		 * set and we have the semaphore
89 		 */
90 		swsm = rd32(hw, TXGBE_SWSEM);
91 		if (!(swsm & TXGBE_SWSEM_PF)) {
92 			status = 0;
93 			break;
94 		}
95 		usec_delay(50);
96 	}
97 
98 	if (i == timeout) {
99 		DEBUGOUT("Driver can't access the eeprom - SMBI Semaphore "
100 			 "not granted.\n");
101 		/*
102 		 * this release is particularly important because our attempts
103 		 * above to get the semaphore may have succeeded, and if there
104 		 * was a timeout, we should unconditionally clear the semaphore
105 		 * bits to free the driver to make progress
106 		 */
107 		txgbe_release_eeprom_semaphore(hw);
108 
109 		usec_delay(50);
110 		/*
111 		 * one last try
112 		 * If the SMBI bit is 0 when we read it, then the bit will be
113 		 * set and we have the semaphore
114 		 */
115 		swsm = rd32(hw, TXGBE_SWSEM);
116 		if (!(swsm & TXGBE_SWSEM_PF))
117 			status = 0;
118 	}
119 
120 	/* Now get the semaphore between SW/FW through the SWESMBI bit */
121 	if (status == 0) {
122 		for (i = 0; i < timeout; i++) {
123 			/* Set the SW EEPROM semaphore bit to request access */
124 			wr32m(hw, TXGBE_MNGSWSYNC,
125 				TXGBE_MNGSWSYNC_REQ, TXGBE_MNGSWSYNC_REQ);
126 
127 			/*
128 			 * If we set the bit successfully then we got the
129 			 * semaphore.
130 			 */
131 			swsm = rd32(hw, TXGBE_MNGSWSYNC);
132 			if (swsm & TXGBE_MNGSWSYNC_REQ)
133 				break;
134 
135 			usec_delay(50);
136 		}
137 
138 		/*
139 		 * Release semaphores and return error if SW EEPROM semaphore
140 		 * was not granted because we don't have access to the EEPROM
141 		 */
142 		if (i >= timeout) {
143 			DEBUGOUT("SWESMBI Software EEPROM semaphore not granted.\n");
144 			txgbe_release_eeprom_semaphore(hw);
145 			status = TXGBE_ERR_EEPROM;
146 		}
147 	} else {
148 		DEBUGOUT("Software semaphore SMBI between device drivers "
149 			 "not granted.\n");
150 	}
151 
152 	return status;
153 }
154 
155 /**
156  *  txgbe_release_eeprom_semaphore - Release hardware semaphore
157  *  @hw: pointer to hardware structure
158  *
159  *  This function clears hardware semaphore bits.
160  **/
161 void txgbe_release_eeprom_semaphore(struct txgbe_hw *hw)
162 {
163 	DEBUGFUNC("txgbe_release_eeprom_semaphore");
164 
165 	wr32m(hw, TXGBE_MNGSWSYNC, TXGBE_MNGSWSYNC_REQ, 0);
166 	wr32m(hw, TXGBE_SWSEM, TXGBE_SWSEM_PF, 0);
167 	txgbe_flush(hw);
168 }
169 
170 /**
171  *  txgbe_ee_read - Read EEPROM word using a host interface cmd
172  *  @hw: pointer to hardware structure
173  *  @offset: offset of  word in the EEPROM to read
174  *  @data: word read from the EEPROM
175  *
176  *  Reads a 16 bit word from the EEPROM using the hostif.
177  **/
178 s32 txgbe_ee_read16(struct txgbe_hw *hw, u32 offset,
179 			      u16 *data)
180 {
181 	const u32 mask = TXGBE_MNGSEM_SWMBX | TXGBE_MNGSEM_SWFLASH;
182 	u32 addr = (offset << 1);
183 	int err;
184 
185 	err = hw->mac.acquire_swfw_sync(hw, mask);
186 	if (err)
187 		return err;
188 
189 	err = txgbe_hic_sr_read(hw, addr, (u8 *)data, 2);
190 
191 	hw->mac.release_swfw_sync(hw, mask);
192 
193 	return err;
194 }
195 
196 /**
197  *  txgbe_ee_readw_buffer- Read EEPROM word(s) using hostif
198  *  @hw: pointer to hardware structure
199  *  @offset: offset of  word in the EEPROM to read
200  *  @words: number of words
201  *  @data: word(s) read from the EEPROM
202  *
203  *  Reads a 16 bit word(s) from the EEPROM using the hostif.
204  **/
205 s32 txgbe_ee_readw_buffer(struct txgbe_hw *hw,
206 				     u32 offset, u32 words, void *data)
207 {
208 	const u32 mask = TXGBE_MNGSEM_SWMBX | TXGBE_MNGSEM_SWFLASH;
209 	u32 addr = (offset << 1);
210 	u32 len = (words << 1);
211 	u8 *buf = (u8 *)data;
212 	int err;
213 
214 	err = hw->mac.acquire_swfw_sync(hw, mask);
215 	if (err)
216 		return err;
217 
218 	while (len) {
219 		u32 seg = (len <= TXGBE_PMMBX_DATA_SIZE
220 				? len : TXGBE_PMMBX_DATA_SIZE);
221 
222 		err = txgbe_hic_sr_read(hw, addr, buf, seg);
223 		if (err)
224 			break;
225 
226 		len -= seg;
227 		addr += seg;
228 		buf += seg;
229 	}
230 
231 	hw->mac.release_swfw_sync(hw, mask);
232 	return err;
233 }
234 
235 
236 s32 txgbe_ee_readw_sw(struct txgbe_hw *hw, u32 offset,
237 			      u16 *data)
238 {
239 	const u32 mask = TXGBE_MNGSEM_SWMBX | TXGBE_MNGSEM_SWFLASH;
240 	u32 addr = hw->rom.sw_addr + (offset << 1);
241 	int err;
242 
243 	err = hw->mac.acquire_swfw_sync(hw, mask);
244 	if (err)
245 		return err;
246 
247 	err = txgbe_hic_sr_read(hw, addr, (u8 *)data, 2);
248 
249 	hw->mac.release_swfw_sync(hw, mask);
250 
251 	return err;
252 }
253 
254 /**
255  *  txgbe_ee_read32 - Read EEPROM word using a host interface cmd
256  *  @hw: pointer to hardware structure
257  *  @offset: offset of  word in the EEPROM to read
258  *  @data: word read from the EEPROM
259  *
260  *  Reads a 32 bit word from the EEPROM using the hostif.
261  **/
262 s32 txgbe_ee_read32(struct txgbe_hw *hw, u32 addr, u32 *data)
263 {
264 	const u32 mask = TXGBE_MNGSEM_SWMBX | TXGBE_MNGSEM_SWFLASH;
265 	int err;
266 
267 	err = hw->mac.acquire_swfw_sync(hw, mask);
268 	if (err)
269 		return err;
270 
271 	err = txgbe_hic_sr_read(hw, addr, (u8 *)data, 4);
272 
273 	hw->mac.release_swfw_sync(hw, mask);
274 
275 	return err;
276 }
277 
278 /**
279  *  txgbe_ee_write - Write EEPROM word using hostif
280  *  @hw: pointer to hardware structure
281  *  @offset: offset of  word in the EEPROM to write
282  *  @data: word write to the EEPROM
283  *
284  *  Write a 16 bit word to the EEPROM using the hostif.
285  **/
286 s32 txgbe_ee_write16(struct txgbe_hw *hw, u32 offset,
287 			       u16 data)
288 {
289 	const u32 mask = TXGBE_MNGSEM_SWMBX | TXGBE_MNGSEM_SWFLASH;
290 	u32 addr = (offset << 1);
291 	int err;
292 
293 	DEBUGFUNC("\n");
294 
295 	err = hw->mac.acquire_swfw_sync(hw, mask);
296 	if (err)
297 		return err;
298 
299 	err = txgbe_hic_sr_write(hw, addr, (u8 *)&data, 2);
300 
301 	hw->mac.release_swfw_sync(hw, mask);
302 
303 	return err;
304 }
305 
306 /**
307  *  txgbe_ee_writew_buffer - Write EEPROM word(s) using hostif
308  *  @hw: pointer to hardware structure
309  *  @offset: offset of  word in the EEPROM to write
310  *  @words: number of words
311  *  @data: word(s) write to the EEPROM
312  *
313  *  Write a 16 bit word(s) to the EEPROM using the hostif.
314  **/
315 s32 txgbe_ee_writew_buffer(struct txgbe_hw *hw,
316 				      u32 offset, u32 words, void *data)
317 {
318 	const u32 mask = TXGBE_MNGSEM_SWMBX | TXGBE_MNGSEM_SWFLASH;
319 	u32 addr = (offset << 1);
320 	u32 len = (words << 1);
321 	u8 *buf = (u8 *)data;
322 	int err;
323 
324 	err = hw->mac.acquire_swfw_sync(hw, mask);
325 	if (err)
326 		return err;
327 
328 	while (len) {
329 		u32 seg = (len <= TXGBE_PMMBX_DATA_SIZE
330 				? len : TXGBE_PMMBX_DATA_SIZE);
331 
332 		err = txgbe_hic_sr_write(hw, addr, buf, seg);
333 		if (err)
334 			break;
335 
336 		len -= seg;
337 		buf += seg;
338 	}
339 
340 	hw->mac.release_swfw_sync(hw, mask);
341 	return err;
342 }
343 
344 s32 txgbe_ee_writew_sw(struct txgbe_hw *hw, u32 offset,
345 			       u16 data)
346 {
347 	const u32 mask = TXGBE_MNGSEM_SWMBX | TXGBE_MNGSEM_SWFLASH;
348 	u32 addr = hw->rom.sw_addr + (offset << 1);
349 	int err;
350 
351 	DEBUGFUNC("\n");
352 
353 	err = hw->mac.acquire_swfw_sync(hw, mask);
354 	if (err)
355 		return err;
356 
357 	err = txgbe_hic_sr_write(hw, addr, (u8 *)&data, 2);
358 
359 	hw->mac.release_swfw_sync(hw, mask);
360 
361 	return err;
362 }
363 
364 /**
365  *  txgbe_ee_write32 - Read EEPROM word using a host interface cmd
366  *  @hw: pointer to hardware structure
367  *  @offset: offset of  word in the EEPROM to read
368  *  @data: word read from the EEPROM
369  *
370  *  Reads a 32 bit word from the EEPROM using the hostif.
371  **/
372 s32 txgbe_ee_write32(struct txgbe_hw *hw, u32 addr, u32 data)
373 {
374 	const u32 mask = TXGBE_MNGSEM_SWMBX | TXGBE_MNGSEM_SWFLASH;
375 	int err;
376 
377 	err = hw->mac.acquire_swfw_sync(hw, mask);
378 	if (err)
379 		return err;
380 
381 	err = txgbe_hic_sr_write(hw, addr, (u8 *)&data, 4);
382 
383 	hw->mac.release_swfw_sync(hw, mask);
384 
385 	return err;
386 }
387 
388 /**
389  *  txgbe_calc_eeprom_checksum - Calculates and returns the checksum
390  *  @hw: pointer to hardware structure
391  *
392  *  Returns a negative error code on error, or the 16-bit checksum
393  **/
394 #define BUFF_SIZE  64
395 s32 txgbe_calc_eeprom_checksum(struct txgbe_hw *hw)
396 {
397 	u16 checksum = 0, read_checksum = 0;
398 	int i, j, seg;
399 	int err;
400 	u16 buffer[BUFF_SIZE];
401 
402 	DEBUGFUNC("txgbe_calc_eeprom_checksum");
403 
404 	err = hw->rom.readw_sw(hw, TXGBE_EEPROM_CHECKSUM, &read_checksum);
405 	if (err) {
406 		DEBUGOUT("EEPROM read failed\n");
407 		return err;
408 	}
409 
410 	for (i = 0; i < TXGBE_EE_CSUM_MAX; i += seg) {
411 		seg = (i + BUFF_SIZE < TXGBE_EE_CSUM_MAX
412 		       ? BUFF_SIZE : TXGBE_EE_CSUM_MAX - i);
413 		err = hw->rom.readw_buffer(hw, i, seg, buffer);
414 		if (err)
415 			return err;
416 		for (j = 0; j < seg; j++)
417 			checksum += buffer[j];
418 	}
419 
420 	checksum = (u16)TXGBE_EEPROM_SUM - checksum + read_checksum;
421 
422 	return (s32)checksum;
423 }
424 
425 /**
426  *  txgbe_validate_eeprom_checksum - Validate EEPROM checksum
427  *  @hw: pointer to hardware structure
428  *  @checksum_val: calculated checksum
429  *
430  *  Performs checksum calculation and validates the EEPROM checksum.  If the
431  *  caller does not need checksum_val, the value can be NULL.
432  **/
433 s32 txgbe_validate_eeprom_checksum(struct txgbe_hw *hw,
434 					   u16 *checksum_val)
435 {
436 	u16 checksum;
437 	u16 read_checksum = 0;
438 	int err;
439 
440 	DEBUGFUNC("txgbe_validate_eeprom_checksum");
441 
442 	/* Read the first word from the EEPROM. If this times out or fails, do
443 	 * not continue or we could be in for a very long wait while every
444 	 * EEPROM read fails
445 	 */
446 	err = hw->rom.read16(hw, 0, &checksum);
447 	if (err) {
448 		DEBUGOUT("EEPROM read failed\n");
449 		return err;
450 	}
451 
452 	err = hw->rom.calc_checksum(hw);
453 	if (err < 0)
454 		return err;
455 
456 	checksum = (u16)(err & 0xffff);
457 
458 	err = hw->rom.readw_sw(hw, TXGBE_EEPROM_CHECKSUM, &read_checksum);
459 	if (err) {
460 		DEBUGOUT("EEPROM read failed\n");
461 		return err;
462 	}
463 
464 	/* Verify read checksum from EEPROM is the same as
465 	 * calculated checksum
466 	 */
467 	if (read_checksum != checksum) {
468 		err = TXGBE_ERR_EEPROM_CHECKSUM;
469 		DEBUGOUT("EEPROM checksum error\n");
470 	}
471 
472 	/* If the user cares, return the calculated checksum */
473 	if (checksum_val)
474 		*checksum_val = checksum;
475 
476 	return err;
477 }
478 
479 /**
480  *  txgbe_update_eeprom_checksum - Updates the EEPROM checksum
481  *  @hw: pointer to hardware structure
482  **/
483 s32 txgbe_update_eeprom_checksum(struct txgbe_hw *hw)
484 {
485 	s32 status;
486 	u16 checksum;
487 
488 	DEBUGFUNC("txgbe_update_eeprom_checksum");
489 
490 	/* Read the first word from the EEPROM. If this times out or fails, do
491 	 * not continue or we could be in for a very long wait while every
492 	 * EEPROM read fails
493 	 */
494 	status = hw->rom.read16(hw, 0, &checksum);
495 	if (status) {
496 		DEBUGOUT("EEPROM read failed\n");
497 		return status;
498 	}
499 
500 	status = hw->rom.calc_checksum(hw);
501 	if (status < 0)
502 		return status;
503 
504 	checksum = (u16)(status & 0xffff);
505 
506 	status = hw->rom.writew_sw(hw, TXGBE_EEPROM_CHECKSUM, checksum);
507 
508 	return status;
509 }
510 
511