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