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