net/hns3: fix typos on comments
[dpdk.git] / drivers / net / txgbe / base / txgbe_eeprom.c
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  **/
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  **/
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  **/
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  **/
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_readw_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  **/
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
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  **/
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_write - Write EEPROM word using hostif
279  *  @hw: pointer to hardware structure
280  *  @offset: offset of  word in the EEPROM to write
281  *  @data: word write to the EEPROM
282  *
283  *  Write a 16 bit word to the EEPROM using the hostif.
284  **/
285 s32 txgbe_ee_write16(struct txgbe_hw *hw, u32 offset,
286                                u16 data)
287 {
288         const u32 mask = TXGBE_MNGSEM_SWMBX | TXGBE_MNGSEM_SWFLASH;
289         u32 addr = (offset << 1);
290         int err;
291
292         DEBUGFUNC("\n");
293
294         err = hw->mac.acquire_swfw_sync(hw, mask);
295         if (err)
296                 return err;
297
298         err = txgbe_hic_sr_write(hw, addr, (u8 *)&data, 2);
299
300         hw->mac.release_swfw_sync(hw, mask);
301
302         return err;
303 }
304
305 /**
306  *  txgbe_ee_writew_buffer - Write EEPROM word(s) using hostif
307  *  @hw: pointer to hardware structure
308  *  @offset: offset of  word in the EEPROM to write
309  *  @words: number of words
310  *  @data: word(s) write to the EEPROM
311  *
312  *  Write a 16 bit word(s) to the EEPROM using the hostif.
313  **/
314 s32 txgbe_ee_writew_buffer(struct txgbe_hw *hw,
315                                       u32 offset, u32 words, void *data)
316 {
317         const u32 mask = TXGBE_MNGSEM_SWMBX | TXGBE_MNGSEM_SWFLASH;
318         u32 addr = (offset << 1);
319         u32 len = (words << 1);
320         u8 *buf = (u8 *)data;
321         int err;
322
323         err = hw->mac.acquire_swfw_sync(hw, mask);
324         if (err)
325                 return err;
326
327         while (len) {
328                 u32 seg = (len <= TXGBE_PMMBX_DATA_SIZE
329                                 ? len : TXGBE_PMMBX_DATA_SIZE);
330
331                 err = txgbe_hic_sr_write(hw, addr, buf, seg);
332                 if (err)
333                         break;
334
335                 len -= seg;
336                 buf += seg;
337         }
338
339         hw->mac.release_swfw_sync(hw, mask);
340         return err;
341 }
342
343 s32 txgbe_ee_writew_sw(struct txgbe_hw *hw, u32 offset,
344                                u16 data)
345 {
346         const u32 mask = TXGBE_MNGSEM_SWMBX | TXGBE_MNGSEM_SWFLASH;
347         u32 addr = hw->rom.sw_addr + (offset << 1);
348         int err;
349
350         DEBUGFUNC("\n");
351
352         err = hw->mac.acquire_swfw_sync(hw, mask);
353         if (err)
354                 return err;
355
356         err = txgbe_hic_sr_write(hw, addr, (u8 *)&data, 2);
357
358         hw->mac.release_swfw_sync(hw, mask);
359
360         return err;
361 }
362
363 /**
364  *  txgbe_ee_write32 - Read EEPROM word using a host interface cmd
365  *  @hw: pointer to hardware structure
366  *  @offset: offset of  word in the EEPROM to read
367  *  @data: word read from the EEPROM
368  *
369  *  Reads a 32 bit word from the EEPROM using the hostif.
370  **/
371 s32 txgbe_ee_write32(struct txgbe_hw *hw, u32 addr, u32 data)
372 {
373         const u32 mask = TXGBE_MNGSEM_SWMBX | TXGBE_MNGSEM_SWFLASH;
374         int err;
375
376         err = hw->mac.acquire_swfw_sync(hw, mask);
377         if (err)
378                 return err;
379
380         err = txgbe_hic_sr_write(hw, addr, (u8 *)&data, 4);
381
382         hw->mac.release_swfw_sync(hw, mask);
383
384         return err;
385 }
386
387 /**
388  *  txgbe_calc_eeprom_checksum - Calculates and returns the checksum
389  *  @hw: pointer to hardware structure
390  *
391  *  Returns a negative error code on error, or the 16-bit checksum
392  **/
393 #define BUFF_SIZE  64
394 s32 txgbe_calc_eeprom_checksum(struct txgbe_hw *hw)
395 {
396         u16 checksum = 0, read_checksum = 0;
397         int i, j, seg;
398         int err;
399         u16 buffer[BUFF_SIZE];
400
401         DEBUGFUNC("txgbe_calc_eeprom_checksum");
402
403         err = hw->rom.readw_sw(hw, TXGBE_EEPROM_CHECKSUM, &read_checksum);
404         if (err) {
405                 DEBUGOUT("EEPROM read failed\n");
406                 return err;
407         }
408
409         for (i = 0; i < TXGBE_EE_CSUM_MAX; i += seg) {
410                 seg = (i + BUFF_SIZE < TXGBE_EE_CSUM_MAX
411                        ? BUFF_SIZE : TXGBE_EE_CSUM_MAX - i);
412                 err = hw->rom.readw_buffer(hw, i, seg, buffer);
413                 if (err)
414                         return err;
415                 for (j = 0; j < seg; j++)
416                         checksum += buffer[j];
417         }
418
419         checksum = (u16)TXGBE_EEPROM_SUM - checksum + read_checksum;
420
421         return (s32)checksum;
422 }
423
424 /**
425  *  txgbe_validate_eeprom_checksum - Validate EEPROM checksum
426  *  @hw: pointer to hardware structure
427  *  @checksum_val: calculated checksum
428  *
429  *  Performs checksum calculation and validates the EEPROM checksum.  If the
430  *  caller does not need checksum_val, the value can be NULL.
431  **/
432 s32 txgbe_validate_eeprom_checksum(struct txgbe_hw *hw,
433                                            u16 *checksum_val)
434 {
435         u16 checksum;
436         u16 read_checksum = 0;
437         int err;
438
439         DEBUGFUNC("txgbe_validate_eeprom_checksum");
440
441         /* Read the first word from the EEPROM. If this times out or fails, do
442          * not continue or we could be in for a very long wait while every
443          * EEPROM read fails
444          */
445         err = hw->rom.read16(hw, 0, &checksum);
446         if (err) {
447                 DEBUGOUT("EEPROM read failed\n");
448                 return err;
449         }
450
451         err = hw->rom.calc_checksum(hw);
452         if (err < 0)
453                 return err;
454
455         checksum = (u16)(err & 0xffff);
456
457         err = hw->rom.readw_sw(hw, TXGBE_EEPROM_CHECKSUM, &read_checksum);
458         if (err) {
459                 DEBUGOUT("EEPROM read failed\n");
460                 return err;
461         }
462
463         /* Verify read checksum from EEPROM is the same as
464          * calculated checksum
465          */
466         if (read_checksum != checksum) {
467                 err = TXGBE_ERR_EEPROM_CHECKSUM;
468                 DEBUGOUT("EEPROM checksum error\n");
469         }
470
471         /* If the user cares, return the calculated checksum */
472         if (checksum_val)
473                 *checksum_val = checksum;
474
475         return err;
476 }
477
478 /**
479  *  txgbe_update_eeprom_checksum - Updates the EEPROM checksum
480  *  @hw: pointer to hardware structure
481  **/
482 s32 txgbe_update_eeprom_checksum(struct txgbe_hw *hw)
483 {
484         s32 status;
485         u16 checksum;
486
487         DEBUGFUNC("txgbe_update_eeprom_checksum");
488
489         /* Read the first word from the EEPROM. If this times out or fails, do
490          * not continue or we could be in for a very long wait while every
491          * EEPROM read fails
492          */
493         status = hw->rom.read16(hw, 0, &checksum);
494         if (status) {
495                 DEBUGOUT("EEPROM read failed\n");
496                 return status;
497         }
498
499         status = hw->rom.calc_checksum(hw);
500         if (status < 0)
501                 return status;
502
503         checksum = (u16)(status & 0xffff);
504
505         status = hw->rom.writew_sw(hw, TXGBE_EEPROM_CHECKSUM, checksum);
506
507         return status;
508 }
509