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