1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
|
/* $OpenBSD: igc_nvm.c,v 1.1 2021/10/31 14:52:57 patrick Exp $ */
/*-
* Copyright 2021 Intel Corp
* Copyright 2021 Rubicon Communications, LLC (Netgate)
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <dev/pci/igc_api.h>
/**
* igc_init_nvm_ops_generic - Initialize NVM function pointers
* @hw: pointer to the HW structure
*
* Setups up the function pointers to no-op functions
**/
void
igc_init_nvm_ops_generic(struct igc_hw *hw)
{
struct igc_nvm_info *nvm = &hw->nvm;
DEBUGFUNC("igc_init_nvm_ops_generic");
/* Initialize function pointers */
nvm->ops.init_params = igc_null_ops_generic;
nvm->ops.acquire = igc_null_ops_generic;
nvm->ops.read = igc_null_read_nvm;
nvm->ops.release = igc_null_nvm_generic;
nvm->ops.reload = igc_reload_nvm_generic;
nvm->ops.update = igc_null_ops_generic;
nvm->ops.validate = igc_null_ops_generic;
nvm->ops.write = igc_null_write_nvm;
}
/**
* igc_null_nvm_read - No-op function, return 0
* @hw: pointer to the HW structure
* @a: dummy variable
* @b: dummy variable
* @c: dummy variable
**/
int
igc_null_read_nvm(struct igc_hw IGC_UNUSEDARG *hw, uint16_t IGC_UNUSEDARG a,
uint16_t IGC_UNUSEDARG b, uint16_t IGC_UNUSEDARG *c)
{
DEBUGFUNC("igc_null_read_nvm");
return IGC_SUCCESS;
}
/**
* igc_null_nvm_generic - No-op function, return void
* @hw: pointer to the HW structure
**/
void
igc_null_nvm_generic(struct igc_hw IGC_UNUSEDARG *hw)
{
DEBUGFUNC("igc_null_nvm_generic");
return;
}
/**
* igc_reload_nvm_generic - Reloads EEPROM
* @hw: pointer to the HW structure
*
* Reloads the EEPROM by setting the "Reinitialize from EEPROM" bit in the
* extended control register.
**/
void
igc_reload_nvm_generic(struct igc_hw *hw)
{
uint32_t ctrl_ext;
DEBUGFUNC("igc_reload_nvm_generic");
DELAY(10);
ctrl_ext = IGC_READ_REG(hw, IGC_CTRL_EXT);
ctrl_ext |= IGC_CTRL_EXT_EE_RST;
IGC_WRITE_REG(hw, IGC_CTRL_EXT, ctrl_ext);
IGC_WRITE_FLUSH(hw);
}
/**
* igc_null_write_nvm - No-op function, return 0
* @hw: pointer to the HW structure
* @a: dummy variable
* @b: dummy variable
* @c: dummy variable
**/
int
igc_null_write_nvm(struct igc_hw IGC_UNUSEDARG *hw, uint16_t IGC_UNUSEDARG a,
uint16_t IGC_UNUSEDARG b, uint16_t IGC_UNUSEDARG *c)
{
DEBUGFUNC("igc_null_write_nvm");
return IGC_SUCCESS;
}
/**
* igc_poll_eerd_eewr_done - Poll for EEPROM read/write completion
* @hw: pointer to the HW structure
* @ee_reg: EEPROM flag for polling
*
* Polls the EEPROM status bit for either read or write completion based
* upon the value of 'ee_reg'.
**/
int
igc_poll_eerd_eewr_done(struct igc_hw *hw, int ee_reg)
{
uint32_t attempts = 100000;
uint32_t i, reg = 0;
DEBUGFUNC("igc_poll_eerd_eewr_done");
for (i = 0; i < attempts; i++) {
if (ee_reg == IGC_NVM_POLL_READ)
reg = IGC_READ_REG(hw, IGC_EERD);
else
reg = IGC_READ_REG(hw, IGC_EEWR);
if (reg & IGC_NVM_RW_REG_DONE)
return IGC_SUCCESS;
DELAY(5);
}
return -IGC_ERR_NVM;
}
/**
* igc_read_nvm_eerd - Reads EEPROM using EERD register
* @hw: pointer to the HW structure
* @offset: offset of word in the EEPROM to read
* @words: number of words to read
* @data: word read from the EEPROM
*
* Reads a 16 bit word from the EEPROM using the EERD register.
**/
int
igc_read_nvm_eerd(struct igc_hw *hw, uint16_t offset, uint16_t words,
uint16_t *data)
{
struct igc_nvm_info *nvm = &hw->nvm;
uint32_t i, eerd = 0;
int ret_val = IGC_SUCCESS;
DEBUGFUNC("igc_read_nvm_eerd");
/* A check for invalid values: offset too large, too many words,
* too many words for the offset, and not enough words.
*/
if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
(words == 0)) {
DEBUGOUT("nvm parameter(s) out of bounds\n");
return -IGC_ERR_NVM;
}
for (i = 0; i < words; i++) {
eerd = ((offset + i) << IGC_NVM_RW_ADDR_SHIFT) +
IGC_NVM_RW_REG_START;
IGC_WRITE_REG(hw, IGC_EERD, eerd);
ret_val = igc_poll_eerd_eewr_done(hw, IGC_NVM_POLL_READ);
if (ret_val)
break;
data[i] = (IGC_READ_REG(hw, IGC_EERD) >> IGC_NVM_RW_REG_DATA);
}
if (ret_val)
DEBUGOUT1("NVM read error: %d\n", ret_val);
return ret_val;
}
/**
* igc_read_mac_addr_generic - Read device MAC address
* @hw: pointer to the HW structure
*
* Reads the device MAC address from the EEPROM and stores the value.
* Since devices with two ports use the same EEPROM, we increment the
* last bit in the MAC address for the second port.
**/
int
igc_read_mac_addr_generic(struct igc_hw *hw)
{
uint32_t rar_high, rar_low;
uint16_t i;
rar_high = IGC_READ_REG(hw, IGC_RAH(0));
rar_low = IGC_READ_REG(hw, IGC_RAL(0));
for (i = 0; i < IGC_RAL_MAC_ADDR_LEN; i++)
hw->mac.perm_addr[i] = (uint8_t)(rar_low >> (i * 8));
for (i = 0; i < IGC_RAH_MAC_ADDR_LEN; i++)
hw->mac.perm_addr[i+4] = (uint8_t)(rar_high >> (i * 8));
for (i = 0; i < ETHER_ADDR_LEN; i++)
hw->mac.addr[i] = hw->mac.perm_addr[i];
return IGC_SUCCESS;
}
/**
* igc_validate_nvm_checksum_generic - Validate EEPROM checksum
* @hw: pointer to the HW structure
*
* Calculates the EEPROM checksum by reading/adding each word of the EEPROM
* and then verifies that the sum of the EEPROM is equal to 0xBABA.
**/
int
igc_validate_nvm_checksum_generic(struct igc_hw *hw)
{
uint16_t checksum = 0;
uint16_t i, nvm_data;
int ret_val;
DEBUGFUNC("igc_validate_nvm_checksum_generic");
for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) {
ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data);
if (ret_val) {
DEBUGOUT("NVM Read Error\n");
return ret_val;
}
checksum += nvm_data;
}
if (checksum != (uint16_t) NVM_SUM) {
DEBUGOUT("NVM Checksum Invalid\n");
return -IGC_ERR_NVM;
}
return IGC_SUCCESS;
}
|