net/bnxt: fix RSS action
[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         if (eeprom->type != ngbe_eeprom_unknown)
24                 return 0;
25
26         eeprom->type = ngbe_eeprom_none;
27         /* Set default semaphore delay to 10ms which is a well
28          * tested value
29          */
30         eeprom->semaphore_delay = 10; /*ms*/
31         /* Clear EEPROM page size, it will be initialized as needed */
32         eeprom->word_page_size = 0;
33
34         /*
35          * Check for EEPROM present first.
36          * If not present leave as none
37          */
38         eec = rd32(hw, NGBE_SPISTAT);
39         if (!(eec & NGBE_SPISTAT_BPFLASH)) {
40                 eeprom->type = ngbe_eeprom_flash;
41
42                 /*
43                  * SPI EEPROM is assumed here.  This code would need to
44                  * change if a future EEPROM is not SPI.
45                  */
46                 eeprom_size = 4096;
47                 eeprom->word_size = eeprom_size >> 1;
48         }
49
50         eeprom->address_bits = 16;
51         eeprom->sw_addr = 0x80;
52
53         DEBUGOUT("eeprom params: type = %d, size = %d, address bits: %d %d",
54                   eeprom->type, eeprom->word_size,
55                   eeprom->address_bits, eeprom->sw_addr);
56
57         return 0;
58 }
59
60 /**
61  *  ngbe_get_eeprom_semaphore - Get hardware semaphore
62  *  @hw: pointer to hardware structure
63  *
64  *  Sets the hardware semaphores so EEPROM access can occur for bit-bang method
65  **/
66 s32 ngbe_get_eeprom_semaphore(struct ngbe_hw *hw)
67 {
68         s32 status = NGBE_ERR_EEPROM;
69         u32 timeout = 2000;
70         u32 i;
71         u32 swsm;
72
73         /* Get SMBI software semaphore between device drivers first */
74         for (i = 0; i < timeout; i++) {
75                 /*
76                  * If the SMBI bit is 0 when we read it, then the bit will be
77                  * set and we have the semaphore
78                  */
79                 swsm = rd32(hw, NGBE_SWSEM);
80                 if (!(swsm & NGBE_SWSEM_PF)) {
81                         status = 0;
82                         break;
83                 }
84                 usec_delay(50);
85         }
86
87         if (i == timeout) {
88                 DEBUGOUT("Driver can't access the eeprom - SMBI Semaphore not granted.");
89                 /*
90                  * this release is particularly important because our attempts
91                  * above to get the semaphore may have succeeded, and if there
92                  * was a timeout, we should unconditionally clear the semaphore
93                  * bits to free the driver to make progress
94                  */
95                 ngbe_release_eeprom_semaphore(hw);
96
97                 usec_delay(50);
98                 /*
99                  * one last try
100                  * If the SMBI bit is 0 when we read it, then the bit will be
101                  * set and we have the semaphore
102                  */
103                 swsm = rd32(hw, NGBE_SWSEM);
104                 if (!(swsm & NGBE_SWSEM_PF))
105                         status = 0;
106         }
107
108         /* Now get the semaphore between SW/FW through the SWESMBI bit */
109         if (status == 0) {
110                 for (i = 0; i < timeout; i++) {
111                         /* Set the SW EEPROM semaphore bit to request access */
112                         wr32m(hw, NGBE_MNGSWSYNC,
113                                 NGBE_MNGSWSYNC_REQ, NGBE_MNGSWSYNC_REQ);
114
115                         /*
116                          * If we set the bit successfully then we got the
117                          * semaphore.
118                          */
119                         swsm = rd32(hw, NGBE_MNGSWSYNC);
120                         if (swsm & NGBE_MNGSWSYNC_REQ)
121                                 break;
122
123                         usec_delay(50);
124                 }
125
126                 /*
127                  * Release semaphores and return error if SW EEPROM semaphore
128                  * was not granted because we don't have access to the EEPROM
129                  */
130                 if (i >= timeout) {
131                         DEBUGOUT("SWESMBI Software EEPROM semaphore not granted.");
132                         ngbe_release_eeprom_semaphore(hw);
133                         status = NGBE_ERR_EEPROM;
134                 }
135         } else {
136                 DEBUGOUT("Software semaphore SMBI between device drivers not granted.");
137         }
138
139         return status;
140 }
141
142 /**
143  *  ngbe_release_eeprom_semaphore - Release hardware semaphore
144  *  @hw: pointer to hardware structure
145  *
146  *  This function clears hardware semaphore bits.
147  **/
148 void ngbe_release_eeprom_semaphore(struct ngbe_hw *hw)
149 {
150         wr32m(hw, NGBE_MNGSWSYNC, NGBE_MNGSWSYNC_REQ, 0);
151         wr32m(hw, NGBE_SWSEM, NGBE_SWSEM_PF, 0);
152         ngbe_flush(hw);
153 }
154
155 /**
156  *  ngbe_ee_read_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 s32 ngbe_ee_readw_buffer(struct ngbe_hw *hw,
165                                      u32 offset, u32 words, void *data)
166 {
167         const u32 mask = NGBE_MNGSEM_SWMBX | NGBE_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 <= NGBE_PMMBX_DATA_SIZE
179                                 ? len : NGBE_PMMBX_DATA_SIZE);
180
181                 err = ngbe_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 /**
195  *  ngbe_ee_read32 - Read EEPROM word using a host interface cmd
196  *  @hw: pointer to hardware structure
197  *  @offset: offset of  word in the EEPROM to read
198  *  @data: word read from the EEPROM
199  *
200  *  Reads a 32 bit word from the EEPROM using the hostif.
201  **/
202 s32 ngbe_ee_read32(struct ngbe_hw *hw, u32 addr, u32 *data)
203 {
204         const u32 mask = NGBE_MNGSEM_SWMBX | NGBE_MNGSEM_SWFLASH;
205         int err;
206
207         err = hw->mac.acquire_swfw_sync(hw, mask);
208         if (err)
209                 return err;
210
211         err = ngbe_hic_sr_read(hw, addr, (u8 *)data, 4);
212
213         hw->mac.release_swfw_sync(hw, mask);
214
215         return err;
216 }
217
218 /**
219  *  ngbe_ee_write_buffer - Write EEPROM word(s) using hostif
220  *  @hw: pointer to hardware structure
221  *  @offset: offset of  word in the EEPROM to write
222  *  @words: number of words
223  *  @data: word(s) write to the EEPROM
224  *
225  *  Write a 16 bit word(s) to the EEPROM using the hostif.
226  **/
227 s32 ngbe_ee_writew_buffer(struct ngbe_hw *hw,
228                                       u32 offset, u32 words, void *data)
229 {
230         const u32 mask = NGBE_MNGSEM_SWMBX | NGBE_MNGSEM_SWFLASH;
231         u32 addr = (offset << 1);
232         u32 len = (words << 1);
233         u8 *buf = (u8 *)data;
234         int err;
235
236         err = hw->mac.acquire_swfw_sync(hw, mask);
237         if (err)
238                 return err;
239
240         while (len) {
241                 u32 seg = (len <= NGBE_PMMBX_DATA_SIZE
242                                 ? len : NGBE_PMMBX_DATA_SIZE);
243
244                 err = ngbe_hic_sr_write(hw, addr, buf, seg);
245                 if (err)
246                         break;
247
248                 len -= seg;
249                 buf += seg;
250         }
251
252         hw->mac.release_swfw_sync(hw, mask);
253         return err;
254 }
255
256 /**
257  *  ngbe_validate_eeprom_checksum_em - Validate EEPROM checksum
258  *  @hw: pointer to hardware structure
259  *  @checksum_val: calculated checksum
260  *
261  *  Performs checksum calculation and validates the EEPROM checksum.  If the
262  *  caller does not need checksum_val, the value can be NULL.
263  **/
264 s32 ngbe_validate_eeprom_checksum_em(struct ngbe_hw *hw,
265                                            u16 *checksum_val)
266 {
267         u32 eeprom_cksum_devcap = 0;
268         int err = 0;
269
270         UNREFERENCED_PARAMETER(checksum_val);
271
272         /* Check EEPROM only once */
273         if (hw->bus.lan_id == 0) {
274                 wr32(hw, NGBE_CALSUM_CAP_STATUS, 0x0);
275                 wr32(hw, NGBE_EEPROM_VERSION_STORE_REG, 0x0);
276         } else {
277                 eeprom_cksum_devcap = rd32(hw, NGBE_CALSUM_CAP_STATUS);
278                 hw->rom.saved_version = rd32(hw, NGBE_EEPROM_VERSION_STORE_REG);
279         }
280
281         if (hw->bus.lan_id == 0 || eeprom_cksum_devcap == 0) {
282                 err = ngbe_hic_check_cap(hw);
283                 if (err != 0) {
284                         PMD_INIT_LOG(ERR,
285                                 "The EEPROM checksum is not valid: %d", err);
286                         return -EIO;
287                 }
288         }
289
290         hw->rom.cksum_devcap = eeprom_cksum_devcap & 0xffff;
291
292         return err;
293 }
294
295 /**
296  * ngbe_save_eeprom_version
297  * @hw: pointer to hardware structure
298  *
299  * Save off EEPROM version number and Option Rom version which
300  * together make a unique identify for the eeprom
301  */
302 s32 ngbe_save_eeprom_version(struct ngbe_hw *hw)
303 {
304         u32 eeprom_verl = 0;
305         u32 etrack_id = 0;
306         u32 offset = (hw->rom.sw_addr + NGBE_EEPROM_VERSION_L) << 1;
307
308         if (hw->bus.lan_id == 0) {
309                 hw->rom.read32(hw, offset, &eeprom_verl);
310                 etrack_id = eeprom_verl;
311                 wr32(hw, NGBE_EEPROM_VERSION_STORE_REG, etrack_id);
312                 wr32(hw, NGBE_CALSUM_CAP_STATUS,
313                         hw->rom.cksum_devcap | 0x10000);
314         } else if (hw->rom.cksum_devcap) {
315                 etrack_id = hw->rom.saved_version;
316         } else {
317                 hw->rom.read32(hw, offset, &eeprom_verl);
318                 etrack_id = eeprom_verl;
319         }
320
321         hw->eeprom_id = etrack_id;
322
323         return 0;
324 }