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 **/
ngbe_init_eeprom_params(struct ngbe_hw * hw)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 **/
ngbe_get_eeprom_semaphore(struct ngbe_hw * hw)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 return status;
109 }
110
111 /**
112 * ngbe_release_eeprom_semaphore - Release hardware semaphore
113 * @hw: pointer to hardware structure
114 *
115 * This function clears hardware semaphore bits.
116 **/
ngbe_release_eeprom_semaphore(struct ngbe_hw * hw)117 void ngbe_release_eeprom_semaphore(struct ngbe_hw *hw)
118 {
119 wr32m(hw, NGBE_SWSEM, NGBE_SWSEM_PF, 0);
120 ngbe_flush(hw);
121 }
122
123 /**
124 * ngbe_ee_read_buffer- Read EEPROM word(s) using hostif
125 * @hw: pointer to hardware structure
126 * @offset: offset of word in the EEPROM to read
127 * @words: number of words
128 * @data: word(s) read from the EEPROM
129 *
130 * Reads a 16 bit word(s) from the EEPROM using the hostif.
131 **/
ngbe_ee_readw_buffer(struct ngbe_hw * hw,u32 offset,u32 words,void * data)132 s32 ngbe_ee_readw_buffer(struct ngbe_hw *hw,
133 u32 offset, u32 words, void *data)
134 {
135 const u32 mask = NGBE_MNGSEM_SWMBX | NGBE_MNGSEM_SWFLASH;
136 u32 addr = (offset << 1);
137 u32 len = (words << 1);
138 u8 *buf = (u8 *)data;
139 int err;
140
141 err = hw->mac.acquire_swfw_sync(hw, mask);
142 if (err)
143 return err;
144
145 while (len) {
146 u32 seg = (len <= NGBE_PMMBX_DATA_SIZE
147 ? len : NGBE_PMMBX_DATA_SIZE);
148
149 err = ngbe_hic_sr_read(hw, addr, buf, seg);
150 if (err)
151 break;
152
153 len -= seg;
154 addr += seg;
155 buf += seg;
156 }
157
158 hw->mac.release_swfw_sync(hw, mask);
159 return err;
160 }
161
162 /**
163 * ngbe_ee_read32 - Read EEPROM word using a host interface cmd
164 * @hw: pointer to hardware structure
165 * @offset: offset of word in the EEPROM to read
166 * @data: word read from the EEPROM
167 *
168 * Reads a 32 bit word from the EEPROM using the hostif.
169 **/
ngbe_ee_read32(struct ngbe_hw * hw,u32 addr,u32 * data)170 s32 ngbe_ee_read32(struct ngbe_hw *hw, u32 addr, u32 *data)
171 {
172 const u32 mask = NGBE_MNGSEM_SWMBX | NGBE_MNGSEM_SWFLASH;
173 int err;
174
175 err = hw->mac.acquire_swfw_sync(hw, mask);
176 if (err)
177 return err;
178
179 err = ngbe_hic_sr_read(hw, addr, (u8 *)data, 4);
180
181 hw->mac.release_swfw_sync(hw, mask);
182
183 return err;
184 }
185
186 /**
187 * ngbe_ee_write_buffer - Write EEPROM word(s) using hostif
188 * @hw: pointer to hardware structure
189 * @offset: offset of word in the EEPROM to write
190 * @words: number of words
191 * @data: word(s) write to the EEPROM
192 *
193 * Write a 16 bit word(s) to the EEPROM using the hostif.
194 **/
ngbe_ee_writew_buffer(struct ngbe_hw * hw,u32 offset,u32 words,void * data)195 s32 ngbe_ee_writew_buffer(struct ngbe_hw *hw,
196 u32 offset, u32 words, void *data)
197 {
198 const u32 mask = NGBE_MNGSEM_SWMBX | NGBE_MNGSEM_SWFLASH;
199 u32 addr = (offset << 1);
200 u32 len = (words << 1);
201 u8 *buf = (u8 *)data;
202 int err;
203
204 err = hw->mac.acquire_swfw_sync(hw, mask);
205 if (err)
206 return err;
207
208 while (len) {
209 u32 seg = (len <= NGBE_PMMBX_DATA_SIZE
210 ? len : NGBE_PMMBX_DATA_SIZE);
211
212 err = ngbe_hic_sr_write(hw, addr, buf, seg);
213 if (err)
214 break;
215
216 len -= seg;
217 buf += seg;
218 }
219
220 hw->mac.release_swfw_sync(hw, mask);
221 return err;
222 }
223
224 /**
225 * ngbe_validate_eeprom_checksum_em - Validate EEPROM checksum
226 * @hw: pointer to hardware structure
227 * @checksum_val: calculated checksum
228 *
229 * Performs checksum calculation and validates the EEPROM checksum. If the
230 * caller does not need checksum_val, the value can be NULL.
231 **/
ngbe_validate_eeprom_checksum_em(struct ngbe_hw * hw,u16 * checksum_val)232 s32 ngbe_validate_eeprom_checksum_em(struct ngbe_hw *hw,
233 u16 *checksum_val)
234 {
235 u32 eeprom_cksum_devcap = 0;
236 int err = 0;
237
238 UNREFERENCED_PARAMETER(checksum_val);
239
240 /* Check EEPROM only once */
241 if (hw->bus.lan_id == 0) {
242 wr32(hw, NGBE_CALSUM_CAP_STATUS, 0x0);
243 wr32(hw, NGBE_EEPROM_VERSION_STORE_REG, 0x0);
244 } else {
245 eeprom_cksum_devcap = rd32(hw, NGBE_CALSUM_CAP_STATUS);
246 hw->rom.saved_version = rd32(hw, NGBE_EEPROM_VERSION_STORE_REG);
247 }
248
249 if (hw->bus.lan_id == 0 || eeprom_cksum_devcap == 0) {
250 err = ngbe_hic_check_cap(hw);
251 if (err != 0) {
252 PMD_INIT_LOG(ERR,
253 "The EEPROM checksum is not valid: %d", err);
254 return -EIO;
255 }
256 }
257
258 hw->rom.cksum_devcap = eeprom_cksum_devcap & 0xffff;
259
260 return err;
261 }
262
263 /**
264 * ngbe_save_eeprom_version
265 * @hw: pointer to hardware structure
266 *
267 * Save off EEPROM version number and Option Rom version which
268 * together make a unique identify for the eeprom
269 */
ngbe_save_eeprom_version(struct ngbe_hw * hw)270 s32 ngbe_save_eeprom_version(struct ngbe_hw *hw)
271 {
272 u32 eeprom_verl = 0;
273 u32 etrack_id = 0;
274 u32 offset = (hw->rom.sw_addr + NGBE_EEPROM_VERSION_L) << 1;
275
276 if (hw->bus.lan_id == 0) {
277 hw->rom.read32(hw, offset, &eeprom_verl);
278 etrack_id = eeprom_verl;
279 wr32(hw, NGBE_EEPROM_VERSION_STORE_REG, etrack_id);
280 wr32(hw, NGBE_CALSUM_CAP_STATUS,
281 hw->rom.cksum_devcap | 0x10000);
282 } else if (hw->rom.cksum_devcap) {
283 etrack_id = hw->rom.saved_version;
284 } else {
285 hw->rom.read32(hw, offset, &eeprom_verl);
286 etrack_id = eeprom_verl;
287 }
288
289 hw->eeprom_id = etrack_id;
290
291 return 0;
292 }
293