net/bnxt: add Tx TruFlow table config for P4 device
[dpdk.git] / drivers / net / ngbe / base / ngbe_eeprom.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2018-2021 Beijing WangXun Technology Co., Ltd.
3  * Copyright(c) 2010-2017 Intel Corporation
4  */
5
6 #include "ngbe_hw.h"
7 #include "ngbe_mng.h"
8 #include "ngbe_eeprom.h"
9
10 /**
11  *  ngbe_init_eeprom_params - Initialize EEPROM params
12  *  @hw: pointer to hardware structure
13  *
14  *  Initializes the EEPROM parameters ngbe_rom_info within the
15  *  ngbe_hw struct in order to set up EEPROM access.
16  **/
17 s32 ngbe_init_eeprom_params(struct ngbe_hw *hw)
18 {
19         struct ngbe_rom_info *eeprom = &hw->rom;
20         u32 eec;
21         u16 eeprom_size;
22
23         DEBUGFUNC("ngbe_init_eeprom_params");
24
25         if (eeprom->type != ngbe_eeprom_unknown)
26                 return 0;
27
28         eeprom->type = ngbe_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, NGBE_SPISTAT);
41         if (!(eec & NGBE_SPISTAT_BPFLASH)) {
42                 eeprom->type = ngbe_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         eeprom->sw_addr = 0x80;
54
55         DEBUGOUT("eeprom params: type = %d, size = %d, address bits: "
56                   "%d %d\n", eeprom->type, eeprom->word_size,
57                   eeprom->address_bits, eeprom->sw_addr);
58
59         return 0;
60 }
61
62 /**
63  *  ngbe_get_eeprom_semaphore - Get hardware semaphore
64  *  @hw: pointer to hardware structure
65  *
66  *  Sets the hardware semaphores so EEPROM access can occur for bit-bang method
67  **/
68 s32 ngbe_get_eeprom_semaphore(struct ngbe_hw *hw)
69 {
70         s32 status = NGBE_ERR_EEPROM;
71         u32 timeout = 2000;
72         u32 i;
73         u32 swsm;
74
75         DEBUGFUNC("ngbe_get_eeprom_semaphore");
76
77
78         /* Get SMBI software semaphore between device drivers first */
79         for (i = 0; i < timeout; i++) {
80                 /*
81                  * If the SMBI bit is 0 when we read it, then the bit will be
82                  * set and we have the semaphore
83                  */
84                 swsm = rd32(hw, NGBE_SWSEM);
85                 if (!(swsm & NGBE_SWSEM_PF)) {
86                         status = 0;
87                         break;
88                 }
89                 usec_delay(50);
90         }
91
92         if (i == timeout) {
93                 DEBUGOUT("Driver can't access the eeprom - SMBI Semaphore "
94                          "not granted.\n");
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                 ngbe_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, NGBE_SWSEM);
110                 if (!(swsm & NGBE_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, NGBE_MNGSWSYNC,
119                                 NGBE_MNGSWSYNC_REQ, NGBE_MNGSWSYNC_REQ);
120
121                         /*
122                          * If we set the bit successfully then we got the
123                          * semaphore.
124                          */
125                         swsm = rd32(hw, NGBE_MNGSWSYNC);
126                         if (swsm & NGBE_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.\n");
138                         ngbe_release_eeprom_semaphore(hw);
139                         status = NGBE_ERR_EEPROM;
140                 }
141         } else {
142                 DEBUGOUT("Software semaphore SMBI between device drivers "
143                          "not granted.\n");
144         }
145
146         return status;
147 }
148
149 /**
150  *  ngbe_release_eeprom_semaphore - Release hardware semaphore
151  *  @hw: pointer to hardware structure
152  *
153  *  This function clears hardware semaphore bits.
154  **/
155 void ngbe_release_eeprom_semaphore(struct ngbe_hw *hw)
156 {
157         DEBUGFUNC("ngbe_release_eeprom_semaphore");
158
159         wr32m(hw, NGBE_MNGSWSYNC, NGBE_MNGSWSYNC_REQ, 0);
160         wr32m(hw, NGBE_SWSEM, NGBE_SWSEM_PF, 0);
161         ngbe_flush(hw);
162 }
163
164 /**
165  *  ngbe_ee_read_buffer- Read EEPROM word(s) using hostif
166  *  @hw: pointer to hardware structure
167  *  @offset: offset of  word in the EEPROM to read
168  *  @words: number of words
169  *  @data: word(s) read from the EEPROM
170  *
171  *  Reads a 16 bit word(s) from the EEPROM using the hostif.
172  **/
173 s32 ngbe_ee_readw_buffer(struct ngbe_hw *hw,
174                                      u32 offset, u32 words, void *data)
175 {
176         const u32 mask = NGBE_MNGSEM_SWMBX | NGBE_MNGSEM_SWFLASH;
177         u32 addr = (offset << 1);
178         u32 len = (words << 1);
179         u8 *buf = (u8 *)data;
180         int err;
181
182         err = hw->mac.acquire_swfw_sync(hw, mask);
183         if (err)
184                 return err;
185
186         while (len) {
187                 u32 seg = (len <= NGBE_PMMBX_DATA_SIZE
188                                 ? len : NGBE_PMMBX_DATA_SIZE);
189
190                 err = ngbe_hic_sr_read(hw, addr, buf, seg);
191                 if (err)
192                         break;
193
194                 len -= seg;
195                 addr += seg;
196                 buf += seg;
197         }
198
199         hw->mac.release_swfw_sync(hw, mask);
200         return err;
201 }
202
203 /**
204  *  ngbe_ee_read32 - Read EEPROM word using a host interface cmd
205  *  @hw: pointer to hardware structure
206  *  @offset: offset of  word in the EEPROM to read
207  *  @data: word read from the EEPROM
208  *
209  *  Reads a 32 bit word from the EEPROM using the hostif.
210  **/
211 s32 ngbe_ee_read32(struct ngbe_hw *hw, u32 addr, u32 *data)
212 {
213         const u32 mask = NGBE_MNGSEM_SWMBX | NGBE_MNGSEM_SWFLASH;
214         int err;
215
216         err = hw->mac.acquire_swfw_sync(hw, mask);
217         if (err)
218                 return err;
219
220         err = ngbe_hic_sr_read(hw, addr, (u8 *)data, 4);
221
222         hw->mac.release_swfw_sync(hw, mask);
223
224         return err;
225 }
226
227 /**
228  *  ngbe_ee_write_buffer - Write EEPROM word(s) using hostif
229  *  @hw: pointer to hardware structure
230  *  @offset: offset of  word in the EEPROM to write
231  *  @words: number of words
232  *  @data: word(s) write to the EEPROM
233  *
234  *  Write a 16 bit word(s) to the EEPROM using the hostif.
235  **/
236 s32 ngbe_ee_writew_buffer(struct ngbe_hw *hw,
237                                       u32 offset, u32 words, void *data)
238 {
239         const u32 mask = NGBE_MNGSEM_SWMBX | NGBE_MNGSEM_SWFLASH;
240         u32 addr = (offset << 1);
241         u32 len = (words << 1);
242         u8 *buf = (u8 *)data;
243         int err;
244
245         err = hw->mac.acquire_swfw_sync(hw, mask);
246         if (err)
247                 return err;
248
249         while (len) {
250                 u32 seg = (len <= NGBE_PMMBX_DATA_SIZE
251                                 ? len : NGBE_PMMBX_DATA_SIZE);
252
253                 err = ngbe_hic_sr_write(hw, addr, buf, seg);
254                 if (err)
255                         break;
256
257                 len -= seg;
258                 buf += seg;
259         }
260
261         hw->mac.release_swfw_sync(hw, mask);
262         return err;
263 }
264
265 /**
266  *  ngbe_validate_eeprom_checksum_em - Validate EEPROM checksum
267  *  @hw: pointer to hardware structure
268  *  @checksum_val: calculated checksum
269  *
270  *  Performs checksum calculation and validates the EEPROM checksum.  If the
271  *  caller does not need checksum_val, the value can be NULL.
272  **/
273 s32 ngbe_validate_eeprom_checksum_em(struct ngbe_hw *hw,
274                                            u16 *checksum_val)
275 {
276         u32 eeprom_cksum_devcap = 0;
277         int err = 0;
278
279         DEBUGFUNC("ngbe_validate_eeprom_checksum_em");
280         UNREFERENCED_PARAMETER(checksum_val);
281
282         /* Check EEPROM only once */
283         if (hw->bus.lan_id == 0) {
284                 wr32(hw, NGBE_CALSUM_CAP_STATUS, 0x0);
285                 wr32(hw, NGBE_EEPROM_VERSION_STORE_REG, 0x0);
286         } else {
287                 eeprom_cksum_devcap = rd32(hw, NGBE_CALSUM_CAP_STATUS);
288                 hw->rom.saved_version = rd32(hw, NGBE_EEPROM_VERSION_STORE_REG);
289         }
290
291         if (hw->bus.lan_id == 0 || eeprom_cksum_devcap == 0) {
292                 err = ngbe_hic_check_cap(hw);
293                 if (err != 0) {
294                         PMD_INIT_LOG(ERR,
295                                 "The EEPROM checksum is not valid: %d", err);
296                         return -EIO;
297                 }
298         }
299
300         hw->rom.cksum_devcap = eeprom_cksum_devcap & 0xffff;
301
302         return err;
303 }
304
305 /**
306  * ngbe_save_eeprom_version
307  * @hw: pointer to hardware structure
308  *
309  * Save off EEPROM version number and Option Rom version which
310  * together make a unique identify for the eeprom
311  */
312 s32 ngbe_save_eeprom_version(struct ngbe_hw *hw)
313 {
314         u32 eeprom_verl = 0;
315         u32 etrack_id = 0;
316         u32 offset = (hw->rom.sw_addr + NGBE_EEPROM_VERSION_L) << 1;
317
318         DEBUGFUNC("ngbe_save_eeprom_version");
319
320         if (hw->bus.lan_id == 0) {
321                 hw->rom.read32(hw, offset, &eeprom_verl);
322                 etrack_id = eeprom_verl;
323                 wr32(hw, NGBE_EEPROM_VERSION_STORE_REG, etrack_id);
324                 wr32(hw, NGBE_CALSUM_CAP_STATUS,
325                         hw->rom.cksum_devcap | 0x10000);
326         } else if (hw->rom.cksum_devcap) {
327                 etrack_id = hw->rom.saved_version;
328         } else {
329                 hw->rom.read32(hw, offset, &eeprom_verl);
330                 etrack_id = eeprom_verl;
331         }
332
333         hw->eeprom_id = etrack_id;
334
335         return 0;
336 }