xref: /dpdk/drivers/net/ngbe/base/ngbe_eeprom.c (revision c18385220f776855a1b2eb798d44068d8fa2bd6d)
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