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