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 return status;
115 }
116
117 /**
118 * txgbe_release_eeprom_semaphore - Release hardware semaphore
119 * @hw: pointer to hardware structure
120 *
121 * This function clears hardware semaphore bits.
122 **/
txgbe_release_eeprom_semaphore(struct txgbe_hw * hw)123 void txgbe_release_eeprom_semaphore(struct txgbe_hw *hw)
124 {
125 wr32m(hw, TXGBE_SWSEM, TXGBE_SWSEM_PF, 0);
126 txgbe_flush(hw);
127 }
128
129 /**
130 * txgbe_ee_read - Read EEPROM word using a host interface cmd
131 * @hw: pointer to hardware structure
132 * @offset: offset of word in the EEPROM to read
133 * @data: word read from the EEPROM
134 *
135 * Reads a 16 bit word from the EEPROM using the hostif.
136 **/
txgbe_ee_read16(struct txgbe_hw * hw,u32 offset,u16 * data)137 s32 txgbe_ee_read16(struct txgbe_hw *hw, u32 offset,
138 u16 *data)
139 {
140 const u32 mask = TXGBE_MNGSEM_SWMBX | TXGBE_MNGSEM_SWFLASH;
141 u32 addr = (offset << 1);
142 int err;
143
144 err = hw->mac.acquire_swfw_sync(hw, mask);
145 if (err)
146 return err;
147
148 err = txgbe_hic_sr_read(hw, addr, (u8 *)data, 2);
149
150 hw->mac.release_swfw_sync(hw, mask);
151
152 return err;
153 }
154
155 /**
156 * txgbe_ee_readw_buffer- Read EEPROM word(s) using hostif
157 * @hw: pointer to hardware structure
158 * @offset: offset of word in the EEPROM to read
159 * @words: number of words
160 * @data: word(s) read from the EEPROM
161 *
162 * Reads a 16 bit word(s) from the EEPROM using the hostif.
163 **/
txgbe_ee_readw_buffer(struct txgbe_hw * hw,u32 offset,u32 words,void * data)164 s32 txgbe_ee_readw_buffer(struct txgbe_hw *hw,
165 u32 offset, u32 words, void *data)
166 {
167 const u32 mask = TXGBE_MNGSEM_SWMBX | TXGBE_MNGSEM_SWFLASH;
168 u32 addr = (offset << 1);
169 u32 len = (words << 1);
170 u8 *buf = (u8 *)data;
171 int err;
172
173 err = hw->mac.acquire_swfw_sync(hw, mask);
174 if (err)
175 return err;
176
177 while (len) {
178 u32 seg = (len <= TXGBE_PMMBX_DATA_SIZE
179 ? len : TXGBE_PMMBX_DATA_SIZE);
180
181 err = txgbe_hic_sr_read(hw, addr, buf, seg);
182 if (err)
183 break;
184
185 len -= seg;
186 addr += seg;
187 buf += seg;
188 }
189
190 hw->mac.release_swfw_sync(hw, mask);
191 return err;
192 }
193
194
txgbe_ee_readw_sw(struct txgbe_hw * hw,u32 offset,u16 * data)195 s32 txgbe_ee_readw_sw(struct txgbe_hw *hw, u32 offset,
196 u16 *data)
197 {
198 const u32 mask = TXGBE_MNGSEM_SWMBX | TXGBE_MNGSEM_SWFLASH;
199 u32 addr = hw->rom.sw_addr + (offset << 1);
200 int err;
201
202 err = hw->mac.acquire_swfw_sync(hw, mask);
203 if (err)
204 return err;
205
206 err = txgbe_hic_sr_read(hw, addr, (u8 *)data, 2);
207
208 hw->mac.release_swfw_sync(hw, mask);
209
210 return err;
211 }
212
213 /**
214 * txgbe_ee_read32 - Read EEPROM word using a host interface cmd
215 * @hw: pointer to hardware structure
216 * @offset: offset of word in the EEPROM to read
217 * @data: word read from the EEPROM
218 *
219 * Reads a 32 bit word from the EEPROM using the hostif.
220 **/
txgbe_ee_read32(struct txgbe_hw * hw,u32 addr,u32 * data)221 s32 txgbe_ee_read32(struct txgbe_hw *hw, u32 addr, u32 *data)
222 {
223 const u32 mask = TXGBE_MNGSEM_SWMBX | TXGBE_MNGSEM_SWFLASH;
224 int err;
225
226 err = hw->mac.acquire_swfw_sync(hw, mask);
227 if (err)
228 return err;
229
230 err = txgbe_hic_sr_read(hw, addr, (u8 *)data, 4);
231
232 hw->mac.release_swfw_sync(hw, mask);
233
234 return err;
235 }
236
237 /**
238 * txgbe_ee_write - Write EEPROM word using hostif
239 * @hw: pointer to hardware structure
240 * @offset: offset of word in the EEPROM to write
241 * @data: word write to the EEPROM
242 *
243 * Write a 16 bit word to the EEPROM using the hostif.
244 **/
txgbe_ee_write16(struct txgbe_hw * hw,u32 offset,u16 data)245 s32 txgbe_ee_write16(struct txgbe_hw *hw, u32 offset,
246 u16 data)
247 {
248 const u32 mask = TXGBE_MNGSEM_SWMBX | TXGBE_MNGSEM_SWFLASH;
249 u32 addr = (offset << 1);
250 int err;
251
252 err = hw->mac.acquire_swfw_sync(hw, mask);
253 if (err)
254 return err;
255
256 err = txgbe_hic_sr_write(hw, addr, (u8 *)&data, 2);
257
258 hw->mac.release_swfw_sync(hw, mask);
259
260 return err;
261 }
262
263 /**
264 * txgbe_ee_writew_buffer - Write EEPROM word(s) using hostif
265 * @hw: pointer to hardware structure
266 * @offset: offset of word in the EEPROM to write
267 * @words: number of words
268 * @data: word(s) write to the EEPROM
269 *
270 * Write a 16 bit word(s) to the EEPROM using the hostif.
271 **/
txgbe_ee_writew_buffer(struct txgbe_hw * hw,u32 offset,u32 words,void * data)272 s32 txgbe_ee_writew_buffer(struct txgbe_hw *hw,
273 u32 offset, u32 words, void *data)
274 {
275 const u32 mask = TXGBE_MNGSEM_SWMBX | TXGBE_MNGSEM_SWFLASH;
276 u32 addr = (offset << 1);
277 u32 len = (words << 1);
278 u8 *buf = (u8 *)data;
279 int err;
280
281 err = hw->mac.acquire_swfw_sync(hw, mask);
282 if (err)
283 return err;
284
285 while (len) {
286 u32 seg = (len <= TXGBE_PMMBX_DATA_SIZE
287 ? len : TXGBE_PMMBX_DATA_SIZE);
288
289 err = txgbe_hic_sr_write(hw, addr, buf, seg);
290 if (err)
291 break;
292
293 len -= seg;
294 buf += seg;
295 }
296
297 hw->mac.release_swfw_sync(hw, mask);
298 return err;
299 }
300
txgbe_ee_writew_sw(struct txgbe_hw * hw,u32 offset,u16 data)301 s32 txgbe_ee_writew_sw(struct txgbe_hw *hw, u32 offset,
302 u16 data)
303 {
304 const u32 mask = TXGBE_MNGSEM_SWMBX | TXGBE_MNGSEM_SWFLASH;
305 u32 addr = hw->rom.sw_addr + (offset << 1);
306 int err;
307
308 err = hw->mac.acquire_swfw_sync(hw, mask);
309 if (err)
310 return err;
311
312 err = txgbe_hic_sr_write(hw, addr, (u8 *)&data, 2);
313
314 hw->mac.release_swfw_sync(hw, mask);
315
316 return err;
317 }
318
319 /**
320 * txgbe_ee_write32 - Read EEPROM word using a host interface cmd
321 * @hw: pointer to hardware structure
322 * @offset: offset of word in the EEPROM to read
323 * @data: word read from the EEPROM
324 *
325 * Reads a 32 bit word from the EEPROM using the hostif.
326 **/
txgbe_ee_write32(struct txgbe_hw * hw,u32 addr,u32 data)327 s32 txgbe_ee_write32(struct txgbe_hw *hw, u32 addr, u32 data)
328 {
329 const u32 mask = TXGBE_MNGSEM_SWMBX | TXGBE_MNGSEM_SWFLASH;
330 int err;
331
332 err = hw->mac.acquire_swfw_sync(hw, mask);
333 if (err)
334 return err;
335
336 err = txgbe_hic_sr_write(hw, addr, (u8 *)&data, 4);
337
338 hw->mac.release_swfw_sync(hw, mask);
339
340 return err;
341 }
342
343 /**
344 * txgbe_calc_eeprom_checksum - Calculates and returns the checksum
345 * @hw: pointer to hardware structure
346 *
347 * Returns a negative error code on error, or the 16-bit checksum
348 **/
349 #define BUFF_SIZE 64
txgbe_calc_eeprom_checksum(struct txgbe_hw * hw)350 s32 txgbe_calc_eeprom_checksum(struct txgbe_hw *hw)
351 {
352 u16 checksum = 0, read_checksum = 0;
353 int i, j, seg;
354 int err;
355 u16 buffer[BUFF_SIZE];
356
357 err = hw->rom.readw_sw(hw, TXGBE_EEPROM_CHECKSUM, &read_checksum);
358 if (err) {
359 DEBUGOUT("EEPROM read failed");
360 return err;
361 }
362
363 for (i = 0; i < TXGBE_EE_CSUM_MAX; i += seg) {
364 seg = (i + BUFF_SIZE < TXGBE_EE_CSUM_MAX
365 ? BUFF_SIZE : TXGBE_EE_CSUM_MAX - i);
366 err = hw->rom.readw_buffer(hw, i, seg, buffer);
367 if (err)
368 return err;
369 for (j = 0; j < seg; j++)
370 checksum += buffer[j];
371 }
372
373 checksum = (u16)TXGBE_EEPROM_SUM - checksum + read_checksum;
374
375 return (s32)checksum;
376 }
377
378 /**
379 * txgbe_validate_eeprom_checksum - Validate EEPROM checksum
380 * @hw: pointer to hardware structure
381 * @checksum_val: calculated checksum
382 *
383 * Performs checksum calculation and validates the EEPROM checksum. If the
384 * caller does not need checksum_val, the value can be NULL.
385 **/
txgbe_validate_eeprom_checksum(struct txgbe_hw * hw,u16 * checksum_val)386 s32 txgbe_validate_eeprom_checksum(struct txgbe_hw *hw,
387 u16 *checksum_val)
388 {
389 u16 checksum;
390 u16 read_checksum = 0;
391 int err;
392
393 /* Read the first word from the EEPROM. If this times out or fails, do
394 * not continue or we could be in for a very long wait while every
395 * EEPROM read fails
396 */
397 err = hw->rom.read16(hw, 0, &checksum);
398 if (err) {
399 DEBUGOUT("EEPROM read failed");
400 return err;
401 }
402
403 err = hw->rom.calc_checksum(hw);
404 if (err < 0)
405 return err;
406
407 checksum = (u16)(err & 0xffff);
408
409 err = hw->rom.readw_sw(hw, TXGBE_EEPROM_CHECKSUM, &read_checksum);
410 if (err) {
411 DEBUGOUT("EEPROM read failed");
412 return err;
413 }
414
415 /* Verify read checksum from EEPROM is the same as
416 * calculated checksum
417 */
418 if (read_checksum != checksum) {
419 err = TXGBE_ERR_EEPROM_CHECKSUM;
420 DEBUGOUT("EEPROM checksum error");
421 }
422
423 /* If the user cares, return the calculated checksum */
424 if (checksum_val)
425 *checksum_val = checksum;
426
427 return err;
428 }
429
430 /**
431 * txgbe_update_eeprom_checksum - Updates the EEPROM checksum
432 * @hw: pointer to hardware structure
433 **/
txgbe_update_eeprom_checksum(struct txgbe_hw * hw)434 s32 txgbe_update_eeprom_checksum(struct txgbe_hw *hw)
435 {
436 s32 status;
437 u16 checksum;
438
439 /* Read the first word from the EEPROM. If this times out or fails, do
440 * not continue or we could be in for a very long wait while every
441 * EEPROM read fails
442 */
443 status = hw->rom.read16(hw, 0, &checksum);
444 if (status) {
445 DEBUGOUT("EEPROM read failed");
446 return status;
447 }
448
449 status = hw->rom.calc_checksum(hw);
450 if (status < 0)
451 return status;
452
453 checksum = (u16)(status & 0xffff);
454
455 status = hw->rom.writew_sw(hw, TXGBE_EEPROM_CHECKSUM, checksum);
456
457 return status;
458 }
459
460