Branch data Line data Source code
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 : 0 : 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 [ # # ]: 0 : if (eeprom->type != txgbe_eeprom_unknown)
25 : : return 0;
26 : :
27 : 0 : eeprom->type = txgbe_eeprom_none;
28 : : /* Set default semaphore delay to 10ms which is a well
29 : : * tested value
30 : : */
31 : 0 : eeprom->semaphore_delay = 10; /*ms*/
32 : : /* Clear EEPROM page size, it will be initialized as needed */
33 : 0 : 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 [ # # ]: 0 : if (!(eec & TXGBE_SPISTAT_BPFLASH)) {
41 : 0 : 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 : 0 : eeprom->word_size = eeprom_size >> 1;
49 : : }
50 : :
51 : 0 : eeprom->address_bits = 16;
52 : :
53 : 0 : err = eeprom->read32(hw, TXGBE_SW_REGION_PTR << 1, &eeprom->sw_addr);
54 [ # # ]: 0 : if (err) {
55 : 0 : DEBUGOUT("EEPROM read failed.");
56 : 0 : return err;
57 : : }
58 : :
59 : 0 : 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 : 0 : 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 : : **/
72 : 0 : 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 [ # # ]: 0 : 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 [ # # ]: 0 : if (!(swsm & TXGBE_SWSEM_PF)) {
87 : : status = 0;
88 : : break;
89 : : }
90 : 0 : usec_delay(50);
91 : : }
92 : :
93 [ # # ]: 0 : if (i == timeout) {
94 : 0 : 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 : 0 : txgbe_release_eeprom_semaphore(hw);
102 : :
103 : 0 : 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 [ # # ]: 0 : if (!(swsm & TXGBE_SWSEM_PF))
111 : : status = 0;
112 : : }
113 : :
114 : 0 : 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 : : **/
123 : 0 : void txgbe_release_eeprom_semaphore(struct txgbe_hw *hw)
124 : : {
125 : : wr32m(hw, TXGBE_SWSEM, TXGBE_SWSEM_PF, 0);
126 : : txgbe_flush(hw);
127 : 0 : }
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 : : **/
137 : 0 : 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 : 0 : u32 addr = (offset << 1);
142 : : int err;
143 : :
144 : 0 : err = hw->mac.acquire_swfw_sync(hw, mask);
145 [ # # ]: 0 : if (err)
146 : : return err;
147 : :
148 : 0 : err = txgbe_hic_sr_read(hw, addr, (u8 *)data, 2);
149 : :
150 : 0 : hw->mac.release_swfw_sync(hw, mask);
151 : :
152 : 0 : 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 : : **/
164 : 0 : 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 : 0 : u32 addr = (offset << 1);
169 : 0 : u32 len = (words << 1);
170 : : u8 *buf = (u8 *)data;
171 : : int err;
172 : :
173 : 0 : err = hw->mac.acquire_swfw_sync(hw, mask);
174 [ # # ]: 0 : if (err)
175 : : return err;
176 : :
177 [ # # ]: 0 : while (len) {
178 : 0 : u32 seg = (len <= TXGBE_PMMBX_DATA_SIZE
179 : : ? len : TXGBE_PMMBX_DATA_SIZE);
180 : :
181 : 0 : err = txgbe_hic_sr_read(hw, addr, buf, seg);
182 [ # # ]: 0 : if (err)
183 : : break;
184 : :
185 : 0 : len -= seg;
186 : 0 : addr += seg;
187 : 0 : buf += seg;
188 : : }
189 : :
190 : 0 : hw->mac.release_swfw_sync(hw, mask);
191 : 0 : return err;
192 : : }
193 : :
194 : :
195 : 0 : 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 : 0 : u32 addr = hw->rom.sw_addr + (offset << 1);
200 : : int err;
201 : :
202 : 0 : err = hw->mac.acquire_swfw_sync(hw, mask);
203 [ # # ]: 0 : if (err)
204 : : return err;
205 : :
206 : 0 : err = txgbe_hic_sr_read(hw, addr, (u8 *)data, 2);
207 : :
208 : 0 : hw->mac.release_swfw_sync(hw, mask);
209 : :
210 : 0 : 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 : : **/
221 : 0 : 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 : 0 : err = hw->mac.acquire_swfw_sync(hw, mask);
227 [ # # ]: 0 : if (err)
228 : : return err;
229 : :
230 : 0 : err = txgbe_hic_sr_read(hw, addr, (u8 *)data, 4);
231 : :
232 : 0 : hw->mac.release_swfw_sync(hw, mask);
233 : :
234 : 0 : 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 : : **/
245 : 0 : 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 : 0 : u32 addr = (offset << 1);
250 : : int err;
251 : :
252 : 0 : err = hw->mac.acquire_swfw_sync(hw, mask);
253 [ # # ]: 0 : if (err)
254 : : return err;
255 : :
256 : 0 : err = txgbe_hic_sr_write(hw, addr, (u8 *)&data, 2);
257 : :
258 : 0 : hw->mac.release_swfw_sync(hw, mask);
259 : :
260 : 0 : 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 : : **/
272 : 0 : 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 : 0 : u32 addr = (offset << 1);
277 : 0 : u32 len = (words << 1);
278 : : u8 *buf = (u8 *)data;
279 : : int err;
280 : :
281 : 0 : err = hw->mac.acquire_swfw_sync(hw, mask);
282 [ # # ]: 0 : if (err)
283 : : return err;
284 : :
285 [ # # ]: 0 : while (len) {
286 : 0 : u32 seg = (len <= TXGBE_PMMBX_DATA_SIZE
287 : : ? len : TXGBE_PMMBX_DATA_SIZE);
288 : :
289 : 0 : err = txgbe_hic_sr_write(hw, addr, buf, seg);
290 [ # # ]: 0 : if (err)
291 : : break;
292 : :
293 : 0 : len -= seg;
294 : 0 : buf += seg;
295 : : }
296 : :
297 : 0 : hw->mac.release_swfw_sync(hw, mask);
298 : 0 : return err;
299 : : }
300 : :
301 : 0 : 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 : 0 : u32 addr = hw->rom.sw_addr + (offset << 1);
306 : : int err;
307 : :
308 : 0 : err = hw->mac.acquire_swfw_sync(hw, mask);
309 [ # # ]: 0 : if (err)
310 : : return err;
311 : :
312 : 0 : err = txgbe_hic_sr_write(hw, addr, (u8 *)&data, 2);
313 : :
314 : 0 : hw->mac.release_swfw_sync(hw, mask);
315 : :
316 : 0 : 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 : : **/
327 : 0 : 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 : 0 : err = hw->mac.acquire_swfw_sync(hw, mask);
333 [ # # ]: 0 : if (err)
334 : : return err;
335 : :
336 : 0 : err = txgbe_hic_sr_write(hw, addr, (u8 *)&data, 4);
337 : :
338 : 0 : hw->mac.release_swfw_sync(hw, mask);
339 : :
340 : 0 : 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
350 : 0 : s32 txgbe_calc_eeprom_checksum(struct txgbe_hw *hw)
351 : : {
352 : 0 : u16 checksum = 0, read_checksum = 0;
353 : : int i, j, seg;
354 : : int err;
355 : : u16 buffer[BUFF_SIZE];
356 : :
357 : 0 : err = hw->rom.readw_sw(hw, TXGBE_EEPROM_CHECKSUM, &read_checksum);
358 [ # # ]: 0 : if (err) {
359 : 0 : DEBUGOUT("EEPROM read failed");
360 : 0 : return err;
361 : : }
362 : :
363 [ # # ]: 0 : for (i = 0; i < TXGBE_EE_CSUM_MAX; i += seg) {
364 : : seg = (i + BUFF_SIZE < TXGBE_EE_CSUM_MAX
365 [ # # ]: 0 : ? BUFF_SIZE : TXGBE_EE_CSUM_MAX - i);
366 : 0 : err = hw->rom.readw_buffer(hw, i, seg, buffer);
367 [ # # ]: 0 : if (err)
368 : 0 : return err;
369 [ # # ]: 0 : for (j = 0; j < seg; j++)
370 : 0 : checksum += buffer[j];
371 : : }
372 : :
373 : 0 : checksum = (u16)TXGBE_EEPROM_SUM - checksum + read_checksum;
374 : :
375 : 0 : 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 : : **/
386 : 0 : s32 txgbe_validate_eeprom_checksum(struct txgbe_hw *hw,
387 : : u16 *checksum_val)
388 : : {
389 : : u16 checksum;
390 : 0 : 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 : 0 : err = hw->rom.read16(hw, 0, &checksum);
398 [ # # ]: 0 : if (err) {
399 : 0 : DEBUGOUT("EEPROM read failed");
400 : 0 : return err;
401 : : }
402 : :
403 : 0 : err = hw->rom.calc_checksum(hw);
404 [ # # ]: 0 : if (err < 0)
405 : : return err;
406 : :
407 : 0 : checksum = (u16)(err & 0xffff);
408 : :
409 : 0 : err = hw->rom.readw_sw(hw, TXGBE_EEPROM_CHECKSUM, &read_checksum);
410 [ # # ]: 0 : if (err) {
411 : 0 : DEBUGOUT("EEPROM read failed");
412 : 0 : return err;
413 : : }
414 : :
415 : : /* Verify read checksum from EEPROM is the same as
416 : : * calculated checksum
417 : : */
418 [ # # ]: 0 : if (read_checksum != checksum) {
419 : : err = TXGBE_ERR_EEPROM_CHECKSUM;
420 : 0 : DEBUGOUT("EEPROM checksum error");
421 : : }
422 : :
423 : : /* If the user cares, return the calculated checksum */
424 [ # # ]: 0 : if (checksum_val)
425 : 0 : *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 : : **/
434 : 0 : 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 : 0 : status = hw->rom.read16(hw, 0, &checksum);
444 [ # # ]: 0 : if (status) {
445 : 0 : DEBUGOUT("EEPROM read failed");
446 : 0 : return status;
447 : : }
448 : :
449 : 0 : status = hw->rom.calc_checksum(hw);
450 [ # # ]: 0 : if (status < 0)
451 : : return status;
452 : :
453 : 0 : checksum = (u16)(status & 0xffff);
454 : :
455 : 0 : status = hw->rom.writew_sw(hw, TXGBE_EEPROM_CHECKSUM, checksum);
456 : :
457 : 0 : return status;
458 : : }
459 : :
|