diff options
Diffstat (limited to 'drivers/net/ethernet/intel/igc')
-rw-r--r-- | drivers/net/ethernet/intel/igc/Makefile | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/igc/igc.h | 6 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/igc/igc_base.c | 109 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/igc/igc_defines.h | 52 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/igc/igc_hw.h | 3 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/igc/igc_i225.c | 349 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/igc/igc_i225.h | 3 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/igc/igc_mac.c | 170 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/igc/igc_mac.h | 6 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/igc/igc_main.c | 20 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/igc/igc_nvm.c | 215 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/igc/igc_nvm.h | 14 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/igc/igc_regs.h | 3 |
13 files changed, 949 insertions, 3 deletions
diff --git a/drivers/net/ethernet/intel/igc/Makefile b/drivers/net/ethernet/intel/igc/Makefile index 8b8022ea590a..2b5378d96c7b 100644 --- a/drivers/net/ethernet/intel/igc/Makefile +++ b/drivers/net/ethernet/intel/igc/Makefile | |||
@@ -7,4 +7,4 @@ | |||
7 | 7 | ||
8 | obj-$(CONFIG_IGC) += igc.o | 8 | obj-$(CONFIG_IGC) += igc.o |
9 | 9 | ||
10 | igc-objs := igc_main.o igc_mac.o igc_i225.o igc_base.o | 10 | igc-objs := igc_main.o igc_mac.o igc_i225.o igc_base.o igc_nvm.o |
diff --git a/drivers/net/ethernet/intel/igc/igc.h b/drivers/net/ethernet/intel/igc/igc.h index 88ee451e36fd..6dcf51c112f4 100644 --- a/drivers/net/ethernet/intel/igc/igc.h +++ b/drivers/net/ethernet/intel/igc/igc.h | |||
@@ -131,6 +131,10 @@ enum igc_tx_flags { | |||
131 | IGC_TX_FLAGS_CSUM = 0x20, | 131 | IGC_TX_FLAGS_CSUM = 0x20, |
132 | }; | 132 | }; |
133 | 133 | ||
134 | enum igc_boards { | ||
135 | board_base, | ||
136 | }; | ||
137 | |||
134 | /* The largest size we can write to the descriptor is 65535. In order to | 138 | /* The largest size we can write to the descriptor is 65535. In order to |
135 | * maintain a power of two alignment we have to limit ourselves to 32K. | 139 | * maintain a power of two alignment we have to limit ourselves to 32K. |
136 | */ | 140 | */ |
@@ -342,6 +346,8 @@ struct igc_adapter { | |||
342 | spinlock_t nfc_lock; | 346 | spinlock_t nfc_lock; |
343 | 347 | ||
344 | struct igc_mac_addr *mac_table; | 348 | struct igc_mac_addr *mac_table; |
349 | |||
350 | struct igc_info ei; | ||
345 | }; | 351 | }; |
346 | 352 | ||
347 | /* igc_desc_unused - calculate if we have unused descriptors */ | 353 | /* igc_desc_unused - calculate if we have unused descriptors */ |
diff --git a/drivers/net/ethernet/intel/igc/igc_base.c b/drivers/net/ethernet/intel/igc/igc_base.c index 4efb47497e6b..2d49814966d3 100644 --- a/drivers/net/ethernet/intel/igc/igc_base.c +++ b/drivers/net/ethernet/intel/igc/igc_base.c | |||
@@ -54,6 +54,22 @@ out: | |||
54 | } | 54 | } |
55 | 55 | ||
56 | /** | 56 | /** |
57 | * igc_check_for_link_base - Check for link | ||
58 | * @hw: pointer to the HW structure | ||
59 | * | ||
60 | * If sgmii is enabled, then use the pcs register to determine link, otherwise | ||
61 | * use the generic interface for determining link. | ||
62 | */ | ||
63 | static s32 igc_check_for_link_base(struct igc_hw *hw) | ||
64 | { | ||
65 | s32 ret_val = 0; | ||
66 | |||
67 | ret_val = igc_check_for_copper_link(hw); | ||
68 | |||
69 | return ret_val; | ||
70 | } | ||
71 | |||
72 | /** | ||
57 | * igc_reset_hw_base - Reset hardware | 73 | * igc_reset_hw_base - Reset hardware |
58 | * @hw: pointer to the HW structure | 74 | * @hw: pointer to the HW structure |
59 | * | 75 | * |
@@ -108,11 +124,50 @@ static s32 igc_reset_hw_base(struct igc_hw *hw) | |||
108 | } | 124 | } |
109 | 125 | ||
110 | /** | 126 | /** |
127 | * igc_init_nvm_params_base - Init NVM func ptrs. | ||
128 | * @hw: pointer to the HW structure | ||
129 | */ | ||
130 | static s32 igc_init_nvm_params_base(struct igc_hw *hw) | ||
131 | { | ||
132 | struct igc_nvm_info *nvm = &hw->nvm; | ||
133 | u32 eecd = rd32(IGC_EECD); | ||
134 | u16 size; | ||
135 | |||
136 | size = (u16)((eecd & IGC_EECD_SIZE_EX_MASK) >> | ||
137 | IGC_EECD_SIZE_EX_SHIFT); | ||
138 | |||
139 | /* Added to a constant, "size" becomes the left-shift value | ||
140 | * for setting word_size. | ||
141 | */ | ||
142 | size += NVM_WORD_SIZE_BASE_SHIFT; | ||
143 | |||
144 | /* Just in case size is out of range, cap it to the largest | ||
145 | * EEPROM size supported | ||
146 | */ | ||
147 | if (size > 15) | ||
148 | size = 15; | ||
149 | |||
150 | nvm->word_size = BIT(size); | ||
151 | nvm->opcode_bits = 8; | ||
152 | nvm->delay_usec = 1; | ||
153 | |||
154 | nvm->page_size = eecd & IGC_EECD_ADDR_BITS ? 32 : 8; | ||
155 | nvm->address_bits = eecd & IGC_EECD_ADDR_BITS ? | ||
156 | 16 : 8; | ||
157 | |||
158 | if (nvm->word_size == BIT(15)) | ||
159 | nvm->page_size = 128; | ||
160 | |||
161 | return 0; | ||
162 | } | ||
163 | |||
164 | /** | ||
111 | * igc_init_mac_params_base - Init MAC func ptrs. | 165 | * igc_init_mac_params_base - Init MAC func ptrs. |
112 | * @hw: pointer to the HW structure | 166 | * @hw: pointer to the HW structure |
113 | */ | 167 | */ |
114 | static s32 igc_init_mac_params_base(struct igc_hw *hw) | 168 | static s32 igc_init_mac_params_base(struct igc_hw *hw) |
115 | { | 169 | { |
170 | struct igc_dev_spec_base *dev_spec = &hw->dev_spec._base; | ||
116 | struct igc_mac_info *mac = &hw->mac; | 171 | struct igc_mac_info *mac = &hw->mac; |
117 | 172 | ||
118 | /* Set mta register count */ | 173 | /* Set mta register count */ |
@@ -125,6 +180,10 @@ static s32 igc_init_mac_params_base(struct igc_hw *hw) | |||
125 | mac->ops.acquire_swfw_sync = igc_acquire_swfw_sync_i225; | 180 | mac->ops.acquire_swfw_sync = igc_acquire_swfw_sync_i225; |
126 | mac->ops.release_swfw_sync = igc_release_swfw_sync_i225; | 181 | mac->ops.release_swfw_sync = igc_release_swfw_sync_i225; |
127 | 182 | ||
183 | /* Allow a single clear of the SW semaphore on I225 */ | ||
184 | if (mac->type == igc_i225) | ||
185 | dev_spec->clear_semaphore_once = true; | ||
186 | |||
128 | return 0; | 187 | return 0; |
129 | } | 188 | } |
130 | 189 | ||
@@ -142,11 +201,44 @@ static s32 igc_get_invariants_base(struct igc_hw *hw) | |||
142 | if (ret_val) | 201 | if (ret_val) |
143 | goto out; | 202 | goto out; |
144 | 203 | ||
204 | /* NVM initialization */ | ||
205 | ret_val = igc_init_nvm_params_base(hw); | ||
206 | switch (hw->mac.type) { | ||
207 | case igc_i225: | ||
208 | ret_val = igc_init_nvm_params_i225(hw); | ||
209 | break; | ||
210 | default: | ||
211 | break; | ||
212 | } | ||
213 | |||
214 | if (ret_val) | ||
215 | goto out; | ||
216 | |||
145 | out: | 217 | out: |
146 | return ret_val; | 218 | return ret_val; |
147 | } | 219 | } |
148 | 220 | ||
149 | /** | 221 | /** |
222 | * igc_get_link_up_info_base - Get link speed/duplex info | ||
223 | * @hw: pointer to the HW structure | ||
224 | * @speed: stores the current speed | ||
225 | * @duplex: stores the current duplex | ||
226 | * | ||
227 | * This is a wrapper function, if using the serial gigabit media independent | ||
228 | * interface, use PCS to retrieve the link speed and duplex information. | ||
229 | * Otherwise, use the generic function to get the link speed and duplex info. | ||
230 | */ | ||
231 | static s32 igc_get_link_up_info_base(struct igc_hw *hw, u16 *speed, | ||
232 | u16 *duplex) | ||
233 | { | ||
234 | s32 ret_val; | ||
235 | |||
236 | ret_val = igc_get_speed_and_duplex_copper(hw, speed, duplex); | ||
237 | |||
238 | return ret_val; | ||
239 | } | ||
240 | |||
241 | /** | ||
150 | * igc_init_hw_base - Initialize hardware | 242 | * igc_init_hw_base - Initialize hardware |
151 | * @hw: pointer to the HW structure | 243 | * @hw: pointer to the HW structure |
152 | * | 244 | * |
@@ -185,6 +277,19 @@ static s32 igc_init_hw_base(struct igc_hw *hw) | |||
185 | } | 277 | } |
186 | 278 | ||
187 | /** | 279 | /** |
280 | * igc_read_mac_addr_base - Read device MAC address | ||
281 | * @hw: pointer to the HW structure | ||
282 | */ | ||
283 | static s32 igc_read_mac_addr_base(struct igc_hw *hw) | ||
284 | { | ||
285 | s32 ret_val = 0; | ||
286 | |||
287 | ret_val = igc_read_mac_addr(hw); | ||
288 | |||
289 | return ret_val; | ||
290 | } | ||
291 | |||
292 | /** | ||
188 | * igc_rx_fifo_flush_base - Clean rx fifo after Rx enable | 293 | * igc_rx_fifo_flush_base - Clean rx fifo after Rx enable |
189 | * @hw: pointer to the HW structure | 294 | * @hw: pointer to the HW structure |
190 | * | 295 | * |
@@ -262,6 +367,10 @@ void igc_rx_fifo_flush_base(struct igc_hw *hw) | |||
262 | 367 | ||
263 | static struct igc_mac_operations igc_mac_ops_base = { | 368 | static struct igc_mac_operations igc_mac_ops_base = { |
264 | .init_hw = igc_init_hw_base, | 369 | .init_hw = igc_init_hw_base, |
370 | .check_for_link = igc_check_for_link_base, | ||
371 | .rar_set = igc_rar_set, | ||
372 | .read_mac_addr = igc_read_mac_addr_base, | ||
373 | .get_speed_and_duplex = igc_get_link_up_info_base, | ||
265 | }; | 374 | }; |
266 | 375 | ||
267 | const struct igc_info igc_base_info = { | 376 | const struct igc_info igc_base_info = { |
diff --git a/drivers/net/ethernet/intel/igc/igc_defines.h b/drivers/net/ethernet/intel/igc/igc_defines.h index 3d6c2cee0ad3..e5736577009a 100644 --- a/drivers/net/ethernet/intel/igc/igc_defines.h +++ b/drivers/net/ethernet/intel/igc/igc_defines.h | |||
@@ -35,6 +35,8 @@ | |||
35 | */ | 35 | */ |
36 | #define IGC_RAH_AV 0x80000000 /* Receive descriptor valid */ | 36 | #define IGC_RAH_AV 0x80000000 /* Receive descriptor valid */ |
37 | #define IGC_RAH_POOL_1 0x00040000 | 37 | #define IGC_RAH_POOL_1 0x00040000 |
38 | #define IGC_RAL_MAC_ADDR_LEN 4 | ||
39 | #define IGC_RAH_MAC_ADDR_LEN 2 | ||
38 | 40 | ||
39 | /* Error Codes */ | 41 | /* Error Codes */ |
40 | #define IGC_SUCCESS 0 | 42 | #define IGC_SUCCESS 0 |
@@ -57,9 +59,51 @@ | |||
57 | #define IGC_SWSM_SMBI 0x00000001 /* Driver Semaphore bit */ | 59 | #define IGC_SWSM_SMBI 0x00000001 /* Driver Semaphore bit */ |
58 | #define IGC_SWSM_SWESMBI 0x00000002 /* FW Semaphore bit */ | 60 | #define IGC_SWSM_SWESMBI 0x00000002 /* FW Semaphore bit */ |
59 | 61 | ||
62 | /* SWFW_SYNC Definitions */ | ||
63 | #define IGC_SWFW_EEP_SM 0x1 | ||
64 | #define IGC_SWFW_PHY0_SM 0x2 | ||
65 | |||
66 | /* NVM Control */ | ||
60 | /* Number of milliseconds for NVM auto read done after MAC reset. */ | 67 | /* Number of milliseconds for NVM auto read done after MAC reset. */ |
61 | #define AUTO_READ_DONE_TIMEOUT 10 | 68 | #define AUTO_READ_DONE_TIMEOUT 10 |
62 | #define IGC_EECD_AUTO_RD 0x00000200 /* NVM Auto Read done */ | 69 | #define IGC_EECD_AUTO_RD 0x00000200 /* NVM Auto Read done */ |
70 | #define IGC_EECD_REQ 0x00000040 /* NVM Access Request */ | ||
71 | #define IGC_EECD_GNT 0x00000080 /* NVM Access Grant */ | ||
72 | /* NVM Addressing bits based on type 0=small, 1=large */ | ||
73 | #define IGC_EECD_ADDR_BITS 0x00000400 | ||
74 | #define IGC_NVM_GRANT_ATTEMPTS 1000 /* NVM # attempts to gain grant */ | ||
75 | #define IGC_EECD_SIZE_EX_MASK 0x00007800 /* NVM Size */ | ||
76 | #define IGC_EECD_SIZE_EX_SHIFT 11 | ||
77 | #define IGC_EECD_FLUPD_I225 0x00800000 /* Update FLASH */ | ||
78 | #define IGC_EECD_FLUDONE_I225 0x04000000 /* Update FLASH done*/ | ||
79 | #define IGC_EECD_FLASH_DETECTED_I225 0x00080000 /* FLASH detected */ | ||
80 | #define IGC_FLUDONE_ATTEMPTS 20000 | ||
81 | #define IGC_EERD_EEWR_MAX_COUNT 512 /* buffered EEPROM words rw */ | ||
82 | |||
83 | /* Offset to data in NVM read/write registers */ | ||
84 | #define IGC_NVM_RW_REG_DATA 16 | ||
85 | #define IGC_NVM_RW_REG_DONE 2 /* Offset to READ/WRITE done bit */ | ||
86 | #define IGC_NVM_RW_REG_START 1 /* Start operation */ | ||
87 | #define IGC_NVM_RW_ADDR_SHIFT 2 /* Shift to the address bits */ | ||
88 | #define IGC_NVM_POLL_READ 0 /* Flag for polling for read complete */ | ||
89 | |||
90 | /* NVM Word Offsets */ | ||
91 | #define NVM_CHECKSUM_REG 0x003F | ||
92 | |||
93 | /* For checksumming, the sum of all words in the NVM should equal 0xBABA. */ | ||
94 | #define NVM_SUM 0xBABA | ||
95 | |||
96 | #define NVM_PBA_OFFSET_0 8 | ||
97 | #define NVM_PBA_OFFSET_1 9 | ||
98 | #define NVM_RESERVED_WORD 0xFFFF | ||
99 | #define NVM_PBA_PTR_GUARD 0xFAFA | ||
100 | #define NVM_WORD_SIZE_BASE_SHIFT 6 | ||
101 | |||
102 | /* Collision related configuration parameters */ | ||
103 | #define IGC_COLLISION_THRESHOLD 15 | ||
104 | #define IGC_CT_SHIFT 4 | ||
105 | #define IGC_COLLISION_DISTANCE 63 | ||
106 | #define IGC_COLD_SHIFT 12 | ||
63 | 107 | ||
64 | /* Device Status */ | 108 | /* Device Status */ |
65 | #define IGC_STATUS_FD 0x00000001 /* Full duplex.0=half,1=full */ | 109 | #define IGC_STATUS_FD 0x00000001 /* Full duplex.0=half,1=full */ |
@@ -70,6 +114,14 @@ | |||
70 | #define IGC_STATUS_TXOFF 0x00000010 /* transmission paused */ | 114 | #define IGC_STATUS_TXOFF 0x00000010 /* transmission paused */ |
71 | #define IGC_STATUS_SPEED_100 0x00000040 /* Speed 100Mb/s */ | 115 | #define IGC_STATUS_SPEED_100 0x00000040 /* Speed 100Mb/s */ |
72 | #define IGC_STATUS_SPEED_1000 0x00000080 /* Speed 1000Mb/s */ | 116 | #define IGC_STATUS_SPEED_1000 0x00000080 /* Speed 1000Mb/s */ |
117 | #define IGC_STATUS_SPEED_2500 0x00400000 /* Speed 2.5Gb/s */ | ||
118 | |||
119 | #define SPEED_10 10 | ||
120 | #define SPEED_100 100 | ||
121 | #define SPEED_1000 1000 | ||
122 | #define SPEED_2500 2500 | ||
123 | #define HALF_DUPLEX 1 | ||
124 | #define FULL_DUPLEX 2 | ||
73 | 125 | ||
74 | /* Interrupt Cause Read */ | 126 | /* Interrupt Cause Read */ |
75 | #define IGC_ICR_TXDW BIT(0) /* Transmit desc written back */ | 127 | #define IGC_ICR_TXDW BIT(0) /* Transmit desc written back */ |
diff --git a/drivers/net/ethernet/intel/igc/igc_hw.h b/drivers/net/ethernet/intel/igc/igc_hw.h index e31d85f1ee12..107d6461924b 100644 --- a/drivers/net/ethernet/intel/igc/igc_hw.h +++ b/drivers/net/ethernet/intel/igc/igc_hw.h | |||
@@ -11,6 +11,7 @@ | |||
11 | #include "igc_regs.h" | 11 | #include "igc_regs.h" |
12 | #include "igc_defines.h" | 12 | #include "igc_defines.h" |
13 | #include "igc_mac.h" | 13 | #include "igc_mac.h" |
14 | #include "igc_nvm.h" | ||
14 | #include "igc_i225.h" | 15 | #include "igc_i225.h" |
15 | #include "igc_base.h" | 16 | #include "igc_base.h" |
16 | 17 | ||
@@ -56,6 +57,8 @@ struct igc_info { | |||
56 | struct igc_nvm_operations *nvm_ops; | 57 | struct igc_nvm_operations *nvm_ops; |
57 | }; | 58 | }; |
58 | 59 | ||
60 | extern const struct igc_info igc_base_info; | ||
61 | |||
59 | struct igc_mac_info { | 62 | struct igc_mac_info { |
60 | struct igc_mac_operations ops; | 63 | struct igc_mac_operations ops; |
61 | 64 | ||
diff --git a/drivers/net/ethernet/intel/igc/igc_i225.c b/drivers/net/ethernet/intel/igc/igc_i225.c index fb1487727d79..c25f555aaf82 100644 --- a/drivers/net/ethernet/intel/igc/igc_i225.c +++ b/drivers/net/ethernet/intel/igc/igc_i225.c | |||
@@ -9,6 +9,32 @@ | |||
9 | * igc_get_hw_semaphore_i225 - Acquire hardware semaphore | 9 | * igc_get_hw_semaphore_i225 - Acquire hardware semaphore |
10 | * @hw: pointer to the HW structure | 10 | * @hw: pointer to the HW structure |
11 | * | 11 | * |
12 | * Acquire the necessary semaphores for exclusive access to the EEPROM. | ||
13 | * Set the EEPROM access request bit and wait for EEPROM access grant bit. | ||
14 | * Return successful if access grant bit set, else clear the request for | ||
15 | * EEPROM access and return -IGC_ERR_NVM (-1). | ||
16 | */ | ||
17 | static s32 igc_acquire_nvm_i225(struct igc_hw *hw) | ||
18 | { | ||
19 | return igc_acquire_swfw_sync_i225(hw, IGC_SWFW_EEP_SM); | ||
20 | } | ||
21 | |||
22 | /** | ||
23 | * igc_release_nvm_i225 - Release exclusive access to EEPROM | ||
24 | * @hw: pointer to the HW structure | ||
25 | * | ||
26 | * Stop any current commands to the EEPROM and clear the EEPROM request bit, | ||
27 | * then release the semaphores acquired. | ||
28 | */ | ||
29 | static void igc_release_nvm_i225(struct igc_hw *hw) | ||
30 | { | ||
31 | igc_release_swfw_sync_i225(hw, IGC_SWFW_EEP_SM); | ||
32 | } | ||
33 | |||
34 | /** | ||
35 | * igc_get_hw_semaphore_i225 - Acquire hardware semaphore | ||
36 | * @hw: pointer to the HW structure | ||
37 | * | ||
12 | * Acquire the HW semaphore to access the PHY or NVM | 38 | * Acquire the HW semaphore to access the PHY or NVM |
13 | */ | 39 | */ |
14 | static s32 igc_get_hw_semaphore_i225(struct igc_hw *hw) | 40 | static s32 igc_get_hw_semaphore_i225(struct igc_hw *hw) |
@@ -139,3 +165,326 @@ void igc_release_swfw_sync_i225(struct igc_hw *hw, u16 mask) | |||
139 | 165 | ||
140 | igc_put_hw_semaphore(hw); | 166 | igc_put_hw_semaphore(hw); |
141 | } | 167 | } |
168 | |||
169 | /** | ||
170 | * igc_read_nvm_srrd_i225 - Reads Shadow Ram using EERD register | ||
171 | * @hw: pointer to the HW structure | ||
172 | * @offset: offset of word in the Shadow Ram to read | ||
173 | * @words: number of words to read | ||
174 | * @data: word read from the Shadow Ram | ||
175 | * | ||
176 | * Reads a 16 bit word from the Shadow Ram using the EERD register. | ||
177 | * Uses necessary synchronization semaphores. | ||
178 | */ | ||
179 | static s32 igc_read_nvm_srrd_i225(struct igc_hw *hw, u16 offset, u16 words, | ||
180 | u16 *data) | ||
181 | { | ||
182 | s32 status = 0; | ||
183 | u16 i, count; | ||
184 | |||
185 | /* We cannot hold synchronization semaphores for too long, | ||
186 | * because of forceful takeover procedure. However it is more efficient | ||
187 | * to read in bursts than synchronizing access for each word. | ||
188 | */ | ||
189 | for (i = 0; i < words; i += IGC_EERD_EEWR_MAX_COUNT) { | ||
190 | count = (words - i) / IGC_EERD_EEWR_MAX_COUNT > 0 ? | ||
191 | IGC_EERD_EEWR_MAX_COUNT : (words - i); | ||
192 | |||
193 | status = hw->nvm.ops.acquire(hw); | ||
194 | if (status) | ||
195 | break; | ||
196 | |||
197 | status = igc_read_nvm_eerd(hw, offset, count, data + i); | ||
198 | hw->nvm.ops.release(hw); | ||
199 | if (status) | ||
200 | break; | ||
201 | } | ||
202 | |||
203 | return status; | ||
204 | } | ||
205 | |||
206 | /** | ||
207 | * igc_write_nvm_srwr - Write to Shadow Ram using EEWR | ||
208 | * @hw: pointer to the HW structure | ||
209 | * @offset: offset within the Shadow Ram to be written to | ||
210 | * @words: number of words to write | ||
211 | * @data: 16 bit word(s) to be written to the Shadow Ram | ||
212 | * | ||
213 | * Writes data to Shadow Ram at offset using EEWR register. | ||
214 | * | ||
215 | * If igc_update_nvm_checksum is not called after this function , the | ||
216 | * Shadow Ram will most likely contain an invalid checksum. | ||
217 | */ | ||
218 | static s32 igc_write_nvm_srwr(struct igc_hw *hw, u16 offset, u16 words, | ||
219 | u16 *data) | ||
220 | { | ||
221 | struct igc_nvm_info *nvm = &hw->nvm; | ||
222 | u32 attempts = 100000; | ||
223 | u32 i, k, eewr = 0; | ||
224 | s32 ret_val = 0; | ||
225 | |||
226 | /* A check for invalid values: offset too large, too many words, | ||
227 | * too many words for the offset, and not enough words. | ||
228 | */ | ||
229 | if (offset >= nvm->word_size || (words > (nvm->word_size - offset)) || | ||
230 | words == 0) { | ||
231 | hw_dbg("nvm parameter(s) out of bounds\n"); | ||
232 | ret_val = -IGC_ERR_NVM; | ||
233 | goto out; | ||
234 | } | ||
235 | |||
236 | for (i = 0; i < words; i++) { | ||
237 | eewr = ((offset + i) << IGC_NVM_RW_ADDR_SHIFT) | | ||
238 | (data[i] << IGC_NVM_RW_REG_DATA) | | ||
239 | IGC_NVM_RW_REG_START; | ||
240 | |||
241 | wr32(IGC_SRWR, eewr); | ||
242 | |||
243 | for (k = 0; k < attempts; k++) { | ||
244 | if (IGC_NVM_RW_REG_DONE & | ||
245 | rd32(IGC_SRWR)) { | ||
246 | ret_val = 0; | ||
247 | break; | ||
248 | } | ||
249 | udelay(5); | ||
250 | } | ||
251 | |||
252 | if (ret_val) { | ||
253 | hw_dbg("Shadow RAM write EEWR timed out\n"); | ||
254 | break; | ||
255 | } | ||
256 | } | ||
257 | |||
258 | out: | ||
259 | return ret_val; | ||
260 | } | ||
261 | |||
262 | /** | ||
263 | * igc_write_nvm_srwr_i225 - Write to Shadow RAM using EEWR | ||
264 | * @hw: pointer to the HW structure | ||
265 | * @offset: offset within the Shadow RAM to be written to | ||
266 | * @words: number of words to write | ||
267 | * @data: 16 bit word(s) to be written to the Shadow RAM | ||
268 | * | ||
269 | * Writes data to Shadow RAM at offset using EEWR register. | ||
270 | * | ||
271 | * If igc_update_nvm_checksum is not called after this function , the | ||
272 | * data will not be committed to FLASH and also Shadow RAM will most likely | ||
273 | * contain an invalid checksum. | ||
274 | * | ||
275 | * If error code is returned, data and Shadow RAM may be inconsistent - buffer | ||
276 | * partially written. | ||
277 | */ | ||
278 | static s32 igc_write_nvm_srwr_i225(struct igc_hw *hw, u16 offset, u16 words, | ||
279 | u16 *data) | ||
280 | { | ||
281 | s32 status = 0; | ||
282 | u16 i, count; | ||
283 | |||
284 | /* We cannot hold synchronization semaphores for too long, | ||
285 | * because of forceful takeover procedure. However it is more efficient | ||
286 | * to write in bursts than synchronizing access for each word. | ||
287 | */ | ||
288 | for (i = 0; i < words; i += IGC_EERD_EEWR_MAX_COUNT) { | ||
289 | count = (words - i) / IGC_EERD_EEWR_MAX_COUNT > 0 ? | ||
290 | IGC_EERD_EEWR_MAX_COUNT : (words - i); | ||
291 | |||
292 | status = hw->nvm.ops.acquire(hw); | ||
293 | if (status) | ||
294 | break; | ||
295 | |||
296 | status = igc_write_nvm_srwr(hw, offset, count, data + i); | ||
297 | hw->nvm.ops.release(hw); | ||
298 | if (status) | ||
299 | break; | ||
300 | } | ||
301 | |||
302 | return status; | ||
303 | } | ||
304 | |||
305 | /** | ||
306 | * igc_validate_nvm_checksum_i225 - Validate EEPROM checksum | ||
307 | * @hw: pointer to the HW structure | ||
308 | * | ||
309 | * Calculates the EEPROM checksum by reading/adding each word of the EEPROM | ||
310 | * and then verifies that the sum of the EEPROM is equal to 0xBABA. | ||
311 | */ | ||
312 | static s32 igc_validate_nvm_checksum_i225(struct igc_hw *hw) | ||
313 | { | ||
314 | s32 (*read_op_ptr)(struct igc_hw *hw, u16 offset, u16 count, | ||
315 | u16 *data); | ||
316 | s32 status = 0; | ||
317 | |||
318 | status = hw->nvm.ops.acquire(hw); | ||
319 | if (status) | ||
320 | goto out; | ||
321 | |||
322 | /* Replace the read function with semaphore grabbing with | ||
323 | * the one that skips this for a while. | ||
324 | * We have semaphore taken already here. | ||
325 | */ | ||
326 | read_op_ptr = hw->nvm.ops.read; | ||
327 | hw->nvm.ops.read = igc_read_nvm_eerd; | ||
328 | |||
329 | status = igc_validate_nvm_checksum(hw); | ||
330 | |||
331 | /* Revert original read operation. */ | ||
332 | hw->nvm.ops.read = read_op_ptr; | ||
333 | |||
334 | hw->nvm.ops.release(hw); | ||
335 | |||
336 | out: | ||
337 | return status; | ||
338 | } | ||
339 | |||
340 | /** | ||
341 | * igc_pool_flash_update_done_i225 - Pool FLUDONE status | ||
342 | * @hw: pointer to the HW structure | ||
343 | */ | ||
344 | static s32 igc_pool_flash_update_done_i225(struct igc_hw *hw) | ||
345 | { | ||
346 | s32 ret_val = -IGC_ERR_NVM; | ||
347 | u32 i, reg; | ||
348 | |||
349 | for (i = 0; i < IGC_FLUDONE_ATTEMPTS; i++) { | ||
350 | reg = rd32(IGC_EECD); | ||
351 | if (reg & IGC_EECD_FLUDONE_I225) { | ||
352 | ret_val = 0; | ||
353 | break; | ||
354 | } | ||
355 | udelay(5); | ||
356 | } | ||
357 | |||
358 | return ret_val; | ||
359 | } | ||
360 | |||
361 | /** | ||
362 | * igc_update_flash_i225 - Commit EEPROM to the flash | ||
363 | * @hw: pointer to the HW structure | ||
364 | */ | ||
365 | static s32 igc_update_flash_i225(struct igc_hw *hw) | ||
366 | { | ||
367 | s32 ret_val = 0; | ||
368 | u32 flup; | ||
369 | |||
370 | ret_val = igc_pool_flash_update_done_i225(hw); | ||
371 | if (ret_val == -IGC_ERR_NVM) { | ||
372 | hw_dbg("Flash update time out\n"); | ||
373 | goto out; | ||
374 | } | ||
375 | |||
376 | flup = rd32(IGC_EECD) | IGC_EECD_FLUPD_I225; | ||
377 | wr32(IGC_EECD, flup); | ||
378 | |||
379 | ret_val = igc_pool_flash_update_done_i225(hw); | ||
380 | if (ret_val) | ||
381 | hw_dbg("Flash update time out\n"); | ||
382 | else | ||
383 | hw_dbg("Flash update complete\n"); | ||
384 | |||
385 | out: | ||
386 | return ret_val; | ||
387 | } | ||
388 | |||
389 | /** | ||
390 | * igc_update_nvm_checksum_i225 - Update EEPROM checksum | ||
391 | * @hw: pointer to the HW structure | ||
392 | * | ||
393 | * Updates the EEPROM checksum by reading/adding each word of the EEPROM | ||
394 | * up to the checksum. Then calculates the EEPROM checksum and writes the | ||
395 | * value to the EEPROM. Next commit EEPROM data onto the Flash. | ||
396 | */ | ||
397 | static s32 igc_update_nvm_checksum_i225(struct igc_hw *hw) | ||
398 | { | ||
399 | u16 checksum = 0; | ||
400 | s32 ret_val = 0; | ||
401 | u16 i, nvm_data; | ||
402 | |||
403 | /* Read the first word from the EEPROM. If this times out or fails, do | ||
404 | * not continue or we could be in for a very long wait while every | ||
405 | * EEPROM read fails | ||
406 | */ | ||
407 | ret_val = igc_read_nvm_eerd(hw, 0, 1, &nvm_data); | ||
408 | if (ret_val) { | ||
409 | hw_dbg("EEPROM read failed\n"); | ||
410 | goto out; | ||
411 | } | ||
412 | |||
413 | ret_val = hw->nvm.ops.acquire(hw); | ||
414 | if (ret_val) | ||
415 | goto out; | ||
416 | |||
417 | /* Do not use hw->nvm.ops.write, hw->nvm.ops.read | ||
418 | * because we do not want to take the synchronization | ||
419 | * semaphores twice here. | ||
420 | */ | ||
421 | |||
422 | for (i = 0; i < NVM_CHECKSUM_REG; i++) { | ||
423 | ret_val = igc_read_nvm_eerd(hw, i, 1, &nvm_data); | ||
424 | if (ret_val) { | ||
425 | hw->nvm.ops.release(hw); | ||
426 | hw_dbg("NVM Read Error while updating checksum.\n"); | ||
427 | goto out; | ||
428 | } | ||
429 | checksum += nvm_data; | ||
430 | } | ||
431 | checksum = (u16)NVM_SUM - checksum; | ||
432 | ret_val = igc_write_nvm_srwr(hw, NVM_CHECKSUM_REG, 1, | ||
433 | &checksum); | ||
434 | if (ret_val) { | ||
435 | hw->nvm.ops.release(hw); | ||
436 | hw_dbg("NVM Write Error while updating checksum.\n"); | ||
437 | goto out; | ||
438 | } | ||
439 | |||
440 | hw->nvm.ops.release(hw); | ||
441 | |||
442 | ret_val = igc_update_flash_i225(hw); | ||
443 | |||
444 | out: | ||
445 | return ret_val; | ||
446 | } | ||
447 | |||
448 | /** | ||
449 | * igc_get_flash_presence_i225 - Check if flash device is detected | ||
450 | * @hw: pointer to the HW structure | ||
451 | */ | ||
452 | bool igc_get_flash_presence_i225(struct igc_hw *hw) | ||
453 | { | ||
454 | bool ret_val = false; | ||
455 | u32 eec = 0; | ||
456 | |||
457 | eec = rd32(IGC_EECD); | ||
458 | if (eec & IGC_EECD_FLASH_DETECTED_I225) | ||
459 | ret_val = true; | ||
460 | |||
461 | return ret_val; | ||
462 | } | ||
463 | |||
464 | /** | ||
465 | * igc_init_nvm_params_i225 - Init NVM func ptrs. | ||
466 | * @hw: pointer to the HW structure | ||
467 | */ | ||
468 | s32 igc_init_nvm_params_i225(struct igc_hw *hw) | ||
469 | { | ||
470 | struct igc_nvm_info *nvm = &hw->nvm; | ||
471 | |||
472 | nvm->ops.acquire = igc_acquire_nvm_i225; | ||
473 | nvm->ops.release = igc_release_nvm_i225; | ||
474 | |||
475 | /* NVM Function Pointers */ | ||
476 | if (igc_get_flash_presence_i225(hw)) { | ||
477 | hw->nvm.type = igc_nvm_flash_hw; | ||
478 | nvm->ops.read = igc_read_nvm_srrd_i225; | ||
479 | nvm->ops.write = igc_write_nvm_srwr_i225; | ||
480 | nvm->ops.validate = igc_validate_nvm_checksum_i225; | ||
481 | nvm->ops.update = igc_update_nvm_checksum_i225; | ||
482 | } else { | ||
483 | hw->nvm.type = igc_nvm_invm; | ||
484 | nvm->ops.read = igc_read_nvm_eerd; | ||
485 | nvm->ops.write = NULL; | ||
486 | nvm->ops.validate = NULL; | ||
487 | nvm->ops.update = NULL; | ||
488 | } | ||
489 | return 0; | ||
490 | } | ||
diff --git a/drivers/net/ethernet/intel/igc/igc_i225.h b/drivers/net/ethernet/intel/igc/igc_i225.h index 461cd8c7e352..7b66e1f9c0e6 100644 --- a/drivers/net/ethernet/intel/igc/igc_i225.h +++ b/drivers/net/ethernet/intel/igc/igc_i225.h | |||
@@ -7,4 +7,7 @@ | |||
7 | s32 igc_acquire_swfw_sync_i225(struct igc_hw *hw, u16 mask); | 7 | s32 igc_acquire_swfw_sync_i225(struct igc_hw *hw, u16 mask); |
8 | void igc_release_swfw_sync_i225(struct igc_hw *hw, u16 mask); | 8 | void igc_release_swfw_sync_i225(struct igc_hw *hw, u16 mask); |
9 | 9 | ||
10 | s32 igc_init_nvm_params_i225(struct igc_hw *hw); | ||
11 | bool igc_get_flash_presence_i225(struct igc_hw *hw); | ||
12 | |||
10 | #endif | 13 | #endif |
diff --git a/drivers/net/ethernet/intel/igc/igc_mac.c b/drivers/net/ethernet/intel/igc/igc_mac.c index 90a98ee14550..249ac03b05d8 100644 --- a/drivers/net/ethernet/intel/igc/igc_mac.c +++ b/drivers/net/ethernet/intel/igc/igc_mac.c | |||
@@ -275,6 +275,129 @@ void igc_clear_hw_cntrs_base(struct igc_hw *hw) | |||
275 | } | 275 | } |
276 | 276 | ||
277 | /** | 277 | /** |
278 | * igc_rar_set - Set receive address register | ||
279 | * @hw: pointer to the HW structure | ||
280 | * @addr: pointer to the receive address | ||
281 | * @index: receive address array register | ||
282 | * | ||
283 | * Sets the receive address array register at index to the address passed | ||
284 | * in by addr. | ||
285 | */ | ||
286 | void igc_rar_set(struct igc_hw *hw, u8 *addr, u32 index) | ||
287 | { | ||
288 | u32 rar_low, rar_high; | ||
289 | |||
290 | /* HW expects these in little endian so we reverse the byte order | ||
291 | * from network order (big endian) to little endian | ||
292 | */ | ||
293 | rar_low = ((u32)addr[0] | | ||
294 | ((u32)addr[1] << 8) | | ||
295 | ((u32)addr[2] << 16) | ((u32)addr[3] << 24)); | ||
296 | |||
297 | rar_high = ((u32)addr[4] | ((u32)addr[5] << 8)); | ||
298 | |||
299 | /* If MAC address zero, no need to set the AV bit */ | ||
300 | if (rar_low || rar_high) | ||
301 | rar_high |= IGC_RAH_AV; | ||
302 | |||
303 | /* Some bridges will combine consecutive 32-bit writes into | ||
304 | * a single burst write, which will malfunction on some parts. | ||
305 | * The flushes avoid this. | ||
306 | */ | ||
307 | wr32(IGC_RAL(index), rar_low); | ||
308 | wrfl(); | ||
309 | wr32(IGC_RAH(index), rar_high); | ||
310 | wrfl(); | ||
311 | } | ||
312 | |||
313 | /** | ||
314 | * igc_check_for_copper_link - Check for link (Copper) | ||
315 | * @hw: pointer to the HW structure | ||
316 | * | ||
317 | * Checks to see of the link status of the hardware has changed. If a | ||
318 | * change in link status has been detected, then we read the PHY registers | ||
319 | * to get the current speed/duplex if link exists. | ||
320 | */ | ||
321 | s32 igc_check_for_copper_link(struct igc_hw *hw) | ||
322 | { | ||
323 | struct igc_mac_info *mac = &hw->mac; | ||
324 | s32 ret_val; | ||
325 | bool link; | ||
326 | |||
327 | /* We only want to go out to the PHY registers to see if Auto-Neg | ||
328 | * has completed and/or if our link status has changed. The | ||
329 | * get_link_status flag is set upon receiving a Link Status | ||
330 | * Change or Rx Sequence Error interrupt. | ||
331 | */ | ||
332 | if (!mac->get_link_status) { | ||
333 | ret_val = 0; | ||
334 | goto out; | ||
335 | } | ||
336 | |||
337 | /* First we want to see if the MII Status Register reports | ||
338 | * link. If so, then we want to get the current speed/duplex | ||
339 | * of the PHY. | ||
340 | */ | ||
341 | if (ret_val) | ||
342 | goto out; | ||
343 | |||
344 | if (!link) | ||
345 | goto out; /* No link detected */ | ||
346 | |||
347 | mac->get_link_status = false; | ||
348 | |||
349 | /* Check if there was DownShift, must be checked | ||
350 | * immediately after link-up | ||
351 | */ | ||
352 | |||
353 | /* If we are forcing speed/duplex, then we simply return since | ||
354 | * we have already determined whether we have link or not. | ||
355 | */ | ||
356 | if (!mac->autoneg) { | ||
357 | ret_val = -IGC_ERR_CONFIG; | ||
358 | goto out; | ||
359 | } | ||
360 | |||
361 | /* Auto-Neg is enabled. Auto Speed Detection takes care | ||
362 | * of MAC speed/duplex configuration. So we only need to | ||
363 | * configure Collision Distance in the MAC. | ||
364 | */ | ||
365 | igc_config_collision_dist(hw); | ||
366 | |||
367 | /* Configure Flow Control now that Auto-Neg has completed. | ||
368 | * First, we need to restore the desired flow control | ||
369 | * settings because we may have had to re-autoneg with a | ||
370 | * different link partner. | ||
371 | */ | ||
372 | if (ret_val) | ||
373 | hw_dbg("Error configuring flow control\n"); | ||
374 | |||
375 | out: | ||
376 | return ret_val; | ||
377 | } | ||
378 | |||
379 | /** | ||
380 | * igc_config_collision_dist - Configure collision distance | ||
381 | * @hw: pointer to the HW structure | ||
382 | * | ||
383 | * Configures the collision distance to the default value and is used | ||
384 | * during link setup. Currently no func pointer exists and all | ||
385 | * implementations are handled in the generic version of this function. | ||
386 | */ | ||
387 | void igc_config_collision_dist(struct igc_hw *hw) | ||
388 | { | ||
389 | u32 tctl; | ||
390 | |||
391 | tctl = rd32(IGC_TCTL); | ||
392 | |||
393 | tctl &= ~IGC_TCTL_COLD; | ||
394 | tctl |= IGC_COLLISION_DISTANCE << IGC_COLD_SHIFT; | ||
395 | |||
396 | wr32(IGC_TCTL, tctl); | ||
397 | wrfl(); | ||
398 | } | ||
399 | |||
400 | /** | ||
278 | * igc_get_auto_rd_done - Check for auto read completion | 401 | * igc_get_auto_rd_done - Check for auto read completion |
279 | * @hw: pointer to the HW structure | 402 | * @hw: pointer to the HW structure |
280 | * | 403 | * |
@@ -303,6 +426,53 @@ out: | |||
303 | } | 426 | } |
304 | 427 | ||
305 | /** | 428 | /** |
429 | * igc_get_speed_and_duplex_copper - Retrieve current speed/duplex | ||
430 | * @hw: pointer to the HW structure | ||
431 | * @speed: stores the current speed | ||
432 | * @duplex: stores the current duplex | ||
433 | * | ||
434 | * Read the status register for the current speed/duplex and store the current | ||
435 | * speed and duplex for copper connections. | ||
436 | */ | ||
437 | s32 igc_get_speed_and_duplex_copper(struct igc_hw *hw, u16 *speed, | ||
438 | u16 *duplex) | ||
439 | { | ||
440 | u32 status; | ||
441 | |||
442 | status = rd32(IGC_STATUS); | ||
443 | if (status & IGC_STATUS_SPEED_1000) { | ||
444 | /* For I225, STATUS will indicate 1G speed in both 1 Gbps | ||
445 | * and 2.5 Gbps link modes. An additional bit is used | ||
446 | * to differentiate between 1 Gbps and 2.5 Gbps. | ||
447 | */ | ||
448 | if (hw->mac.type == igc_i225 && | ||
449 | (status & IGC_STATUS_SPEED_2500)) { | ||
450 | *speed = SPEED_2500; | ||
451 | hw_dbg("2500 Mbs, "); | ||
452 | } else { | ||
453 | *speed = SPEED_1000; | ||
454 | hw_dbg("1000 Mbs, "); | ||
455 | } | ||
456 | } else if (status & IGC_STATUS_SPEED_100) { | ||
457 | *speed = SPEED_100; | ||
458 | hw_dbg("100 Mbs, "); | ||
459 | } else { | ||
460 | *speed = SPEED_10; | ||
461 | hw_dbg("10 Mbs, "); | ||
462 | } | ||
463 | |||
464 | if (status & IGC_STATUS_FD) { | ||
465 | *duplex = FULL_DUPLEX; | ||
466 | hw_dbg("Full Duplex\n"); | ||
467 | } else { | ||
468 | *duplex = HALF_DUPLEX; | ||
469 | hw_dbg("Half Duplex\n"); | ||
470 | } | ||
471 | |||
472 | return 0; | ||
473 | } | ||
474 | |||
475 | /** | ||
306 | * igc_put_hw_semaphore - Release hardware semaphore | 476 | * igc_put_hw_semaphore - Release hardware semaphore |
307 | * @hw: pointer to the HW structure | 477 | * @hw: pointer to the HW structure |
308 | * | 478 | * |
diff --git a/drivers/net/ethernet/intel/igc/igc_mac.h b/drivers/net/ethernet/intel/igc/igc_mac.h index 88bdb8dd6f3f..88599661d017 100644 --- a/drivers/net/ethernet/intel/igc/igc_mac.h +++ b/drivers/net/ethernet/intel/igc/igc_mac.h | |||
@@ -13,10 +13,16 @@ | |||
13 | 13 | ||
14 | /* forward declaration */ | 14 | /* forward declaration */ |
15 | s32 igc_disable_pcie_master(struct igc_hw *hw); | 15 | s32 igc_disable_pcie_master(struct igc_hw *hw); |
16 | s32 igc_check_for_copper_link(struct igc_hw *hw); | ||
16 | void igc_init_rx_addrs(struct igc_hw *hw, u16 rar_count); | 17 | void igc_init_rx_addrs(struct igc_hw *hw, u16 rar_count); |
17 | s32 igc_setup_link(struct igc_hw *hw); | 18 | s32 igc_setup_link(struct igc_hw *hw); |
18 | void igc_clear_hw_cntrs_base(struct igc_hw *hw); | 19 | void igc_clear_hw_cntrs_base(struct igc_hw *hw); |
19 | s32 igc_get_auto_rd_done(struct igc_hw *hw); | 20 | s32 igc_get_auto_rd_done(struct igc_hw *hw); |
20 | void igc_put_hw_semaphore(struct igc_hw *hw); | 21 | void igc_put_hw_semaphore(struct igc_hw *hw); |
22 | void igc_rar_set(struct igc_hw *hw, u8 *addr, u32 index); | ||
23 | void igc_config_collision_dist(struct igc_hw *hw); | ||
24 | |||
25 | s32 igc_get_speed_and_duplex_copper(struct igc_hw *hw, u16 *speed, | ||
26 | u16 *duplex); | ||
21 | 27 | ||
22 | #endif | 28 | #endif |
diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c index f2ad49fcd39b..115fc2a544d7 100644 --- a/drivers/net/ethernet/intel/igc/igc_main.c +++ b/drivers/net/ethernet/intel/igc/igc_main.c | |||
@@ -27,9 +27,13 @@ static const char igc_driver_string[] = DRV_SUMMARY; | |||
27 | static const char igc_copyright[] = | 27 | static const char igc_copyright[] = |
28 | "Copyright(c) 2018 Intel Corporation."; | 28 | "Copyright(c) 2018 Intel Corporation."; |
29 | 29 | ||
30 | static const struct igc_info *igc_info_tbl[] = { | ||
31 | [board_base] = &igc_base_info, | ||
32 | }; | ||
33 | |||
30 | static const struct pci_device_id igc_pci_tbl[] = { | 34 | static const struct pci_device_id igc_pci_tbl[] = { |
31 | { PCI_VDEVICE(INTEL, IGC_DEV_ID_I225_LM) }, | 35 | { PCI_VDEVICE(INTEL, IGC_DEV_ID_I225_LM), board_base }, |
32 | { PCI_VDEVICE(INTEL, IGC_DEV_ID_I225_V) }, | 36 | { PCI_VDEVICE(INTEL, IGC_DEV_ID_I225_V), board_base }, |
33 | /* required last entry */ | 37 | /* required last entry */ |
34 | {0, } | 38 | {0, } |
35 | }; | 39 | }; |
@@ -3289,6 +3293,7 @@ static int igc_probe(struct pci_dev *pdev, | |||
3289 | struct igc_adapter *adapter; | 3293 | struct igc_adapter *adapter; |
3290 | struct net_device *netdev; | 3294 | struct net_device *netdev; |
3291 | struct igc_hw *hw; | 3295 | struct igc_hw *hw; |
3296 | const struct igc_info *ei = igc_info_tbl[ent->driver_data]; | ||
3292 | int err, pci_using_dac; | 3297 | int err, pci_using_dac; |
3293 | 3298 | ||
3294 | err = pci_enable_device_mem(pdev); | 3299 | err = pci_enable_device_mem(pdev); |
@@ -3370,6 +3375,14 @@ static int igc_probe(struct pci_dev *pdev, | |||
3370 | hw->subsystem_vendor_id = pdev->subsystem_vendor; | 3375 | hw->subsystem_vendor_id = pdev->subsystem_vendor; |
3371 | hw->subsystem_device_id = pdev->subsystem_device; | 3376 | hw->subsystem_device_id = pdev->subsystem_device; |
3372 | 3377 | ||
3378 | /* Copy the default MAC and PHY function pointers */ | ||
3379 | memcpy(&hw->mac.ops, ei->mac_ops, sizeof(hw->mac.ops)); | ||
3380 | |||
3381 | /* Initialize skew-specific constants */ | ||
3382 | err = ei->get_invariants(hw); | ||
3383 | if (err) | ||
3384 | goto err_sw_init; | ||
3385 | |||
3373 | /* setup the private structure */ | 3386 | /* setup the private structure */ |
3374 | err = igc_sw_init(adapter); | 3387 | err = igc_sw_init(adapter); |
3375 | if (err) | 3388 | if (err) |
@@ -3403,6 +3416,9 @@ static int igc_probe(struct pci_dev *pdev, | |||
3403 | /* carrier off reporting is important to ethtool even BEFORE open */ | 3416 | /* carrier off reporting is important to ethtool even BEFORE open */ |
3404 | netif_carrier_off(netdev); | 3417 | netif_carrier_off(netdev); |
3405 | 3418 | ||
3419 | /* Check if Media Autosense is enabled */ | ||
3420 | adapter->ei = *ei; | ||
3421 | |||
3406 | /* print pcie link status and MAC address */ | 3422 | /* print pcie link status and MAC address */ |
3407 | pcie_print_link_status(pdev); | 3423 | pcie_print_link_status(pdev); |
3408 | netdev_info(netdev, "MAC: %pM\n", netdev->dev_addr); | 3424 | netdev_info(netdev, "MAC: %pM\n", netdev->dev_addr); |
diff --git a/drivers/net/ethernet/intel/igc/igc_nvm.c b/drivers/net/ethernet/intel/igc/igc_nvm.c new file mode 100644 index 000000000000..58f81aba0144 --- /dev/null +++ b/drivers/net/ethernet/intel/igc/igc_nvm.c | |||
@@ -0,0 +1,215 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | /* Copyright (c) 2018 Intel Corporation */ | ||
3 | |||
4 | #include "igc_mac.h" | ||
5 | #include "igc_nvm.h" | ||
6 | |||
7 | /** | ||
8 | * igc_poll_eerd_eewr_done - Poll for EEPROM read/write completion | ||
9 | * @hw: pointer to the HW structure | ||
10 | * @ee_reg: EEPROM flag for polling | ||
11 | * | ||
12 | * Polls the EEPROM status bit for either read or write completion based | ||
13 | * upon the value of 'ee_reg'. | ||
14 | */ | ||
15 | static s32 igc_poll_eerd_eewr_done(struct igc_hw *hw, int ee_reg) | ||
16 | { | ||
17 | s32 ret_val = -IGC_ERR_NVM; | ||
18 | u32 attempts = 100000; | ||
19 | u32 i, reg = 0; | ||
20 | |||
21 | for (i = 0; i < attempts; i++) { | ||
22 | if (ee_reg == IGC_NVM_POLL_READ) | ||
23 | reg = rd32(IGC_EERD); | ||
24 | else | ||
25 | reg = rd32(IGC_EEWR); | ||
26 | |||
27 | if (reg & IGC_NVM_RW_REG_DONE) { | ||
28 | ret_val = 0; | ||
29 | break; | ||
30 | } | ||
31 | |||
32 | udelay(5); | ||
33 | } | ||
34 | |||
35 | return ret_val; | ||
36 | } | ||
37 | |||
38 | /** | ||
39 | * igc_acquire_nvm - Generic request for access to EEPROM | ||
40 | * @hw: pointer to the HW structure | ||
41 | * | ||
42 | * Set the EEPROM access request bit and wait for EEPROM access grant bit. | ||
43 | * Return successful if access grant bit set, else clear the request for | ||
44 | * EEPROM access and return -IGC_ERR_NVM (-1). | ||
45 | */ | ||
46 | s32 igc_acquire_nvm(struct igc_hw *hw) | ||
47 | { | ||
48 | s32 timeout = IGC_NVM_GRANT_ATTEMPTS; | ||
49 | u32 eecd = rd32(IGC_EECD); | ||
50 | s32 ret_val = 0; | ||
51 | |||
52 | wr32(IGC_EECD, eecd | IGC_EECD_REQ); | ||
53 | eecd = rd32(IGC_EECD); | ||
54 | |||
55 | while (timeout) { | ||
56 | if (eecd & IGC_EECD_GNT) | ||
57 | break; | ||
58 | udelay(5); | ||
59 | eecd = rd32(IGC_EECD); | ||
60 | timeout--; | ||
61 | } | ||
62 | |||
63 | if (!timeout) { | ||
64 | eecd &= ~IGC_EECD_REQ; | ||
65 | wr32(IGC_EECD, eecd); | ||
66 | hw_dbg("Could not acquire NVM grant\n"); | ||
67 | ret_val = -IGC_ERR_NVM; | ||
68 | } | ||
69 | |||
70 | return ret_val; | ||
71 | } | ||
72 | |||
73 | /** | ||
74 | * igc_release_nvm - Release exclusive access to EEPROM | ||
75 | * @hw: pointer to the HW structure | ||
76 | * | ||
77 | * Stop any current commands to the EEPROM and clear the EEPROM request bit. | ||
78 | */ | ||
79 | void igc_release_nvm(struct igc_hw *hw) | ||
80 | { | ||
81 | u32 eecd; | ||
82 | |||
83 | eecd = rd32(IGC_EECD); | ||
84 | eecd &= ~IGC_EECD_REQ; | ||
85 | wr32(IGC_EECD, eecd); | ||
86 | } | ||
87 | |||
88 | /** | ||
89 | * igc_read_nvm_eerd - Reads EEPROM using EERD register | ||
90 | * @hw: pointer to the HW structure | ||
91 | * @offset: offset of word in the EEPROM to read | ||
92 | * @words: number of words to read | ||
93 | * @data: word read from the EEPROM | ||
94 | * | ||
95 | * Reads a 16 bit word from the EEPROM using the EERD register. | ||
96 | */ | ||
97 | s32 igc_read_nvm_eerd(struct igc_hw *hw, u16 offset, u16 words, u16 *data) | ||
98 | { | ||
99 | struct igc_nvm_info *nvm = &hw->nvm; | ||
100 | u32 i, eerd = 0; | ||
101 | s32 ret_val = 0; | ||
102 | |||
103 | /* A check for invalid values: offset too large, too many words, | ||
104 | * and not enough words. | ||
105 | */ | ||
106 | if (offset >= nvm->word_size || (words > (nvm->word_size - offset)) || | ||
107 | words == 0) { | ||
108 | hw_dbg("nvm parameter(s) out of bounds\n"); | ||
109 | ret_val = -IGC_ERR_NVM; | ||
110 | goto out; | ||
111 | } | ||
112 | |||
113 | for (i = 0; i < words; i++) { | ||
114 | eerd = ((offset + i) << IGC_NVM_RW_ADDR_SHIFT) + | ||
115 | IGC_NVM_RW_REG_START; | ||
116 | |||
117 | wr32(IGC_EERD, eerd); | ||
118 | ret_val = igc_poll_eerd_eewr_done(hw, IGC_NVM_POLL_READ); | ||
119 | if (ret_val) | ||
120 | break; | ||
121 | |||
122 | data[i] = (rd32(IGC_EERD) >> IGC_NVM_RW_REG_DATA); | ||
123 | } | ||
124 | |||
125 | out: | ||
126 | return ret_val; | ||
127 | } | ||
128 | |||
129 | /** | ||
130 | * igc_read_mac_addr - Read device MAC address | ||
131 | * @hw: pointer to the HW structure | ||
132 | */ | ||
133 | s32 igc_read_mac_addr(struct igc_hw *hw) | ||
134 | { | ||
135 | u32 rar_high; | ||
136 | u32 rar_low; | ||
137 | u16 i; | ||
138 | |||
139 | rar_high = rd32(IGC_RAH(0)); | ||
140 | rar_low = rd32(IGC_RAL(0)); | ||
141 | |||
142 | for (i = 0; i < IGC_RAL_MAC_ADDR_LEN; i++) | ||
143 | hw->mac.perm_addr[i] = (u8)(rar_low >> (i * 8)); | ||
144 | |||
145 | for (i = 0; i < IGC_RAH_MAC_ADDR_LEN; i++) | ||
146 | hw->mac.perm_addr[i + 4] = (u8)(rar_high >> (i * 8)); | ||
147 | |||
148 | for (i = 0; i < ETH_ALEN; i++) | ||
149 | hw->mac.addr[i] = hw->mac.perm_addr[i]; | ||
150 | |||
151 | return 0; | ||
152 | } | ||
153 | |||
154 | /** | ||
155 | * igc_validate_nvm_checksum - Validate EEPROM checksum | ||
156 | * @hw: pointer to the HW structure | ||
157 | * | ||
158 | * Calculates the EEPROM checksum by reading/adding each word of the EEPROM | ||
159 | * and then verifies that the sum of the EEPROM is equal to 0xBABA. | ||
160 | */ | ||
161 | s32 igc_validate_nvm_checksum(struct igc_hw *hw) | ||
162 | { | ||
163 | u16 checksum = 0; | ||
164 | u16 i, nvm_data; | ||
165 | s32 ret_val = 0; | ||
166 | |||
167 | for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) { | ||
168 | ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data); | ||
169 | if (ret_val) { | ||
170 | hw_dbg("NVM Read Error\n"); | ||
171 | goto out; | ||
172 | } | ||
173 | checksum += nvm_data; | ||
174 | } | ||
175 | |||
176 | if (checksum != (u16)NVM_SUM) { | ||
177 | hw_dbg("NVM Checksum Invalid\n"); | ||
178 | ret_val = -IGC_ERR_NVM; | ||
179 | goto out; | ||
180 | } | ||
181 | |||
182 | out: | ||
183 | return ret_val; | ||
184 | } | ||
185 | |||
186 | /** | ||
187 | * igc_update_nvm_checksum - Update EEPROM checksum | ||
188 | * @hw: pointer to the HW structure | ||
189 | * | ||
190 | * Updates the EEPROM checksum by reading/adding each word of the EEPROM | ||
191 | * up to the checksum. Then calculates the EEPROM checksum and writes the | ||
192 | * value to the EEPROM. | ||
193 | */ | ||
194 | s32 igc_update_nvm_checksum(struct igc_hw *hw) | ||
195 | { | ||
196 | u16 checksum = 0; | ||
197 | u16 i, nvm_data; | ||
198 | s32 ret_val; | ||
199 | |||
200 | for (i = 0; i < NVM_CHECKSUM_REG; i++) { | ||
201 | ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data); | ||
202 | if (ret_val) { | ||
203 | hw_dbg("NVM Read Error while updating checksum.\n"); | ||
204 | goto out; | ||
205 | } | ||
206 | checksum += nvm_data; | ||
207 | } | ||
208 | checksum = (u16)NVM_SUM - checksum; | ||
209 | ret_val = hw->nvm.ops.write(hw, NVM_CHECKSUM_REG, 1, &checksum); | ||
210 | if (ret_val) | ||
211 | hw_dbg("NVM Write Error while updating checksum.\n"); | ||
212 | |||
213 | out: | ||
214 | return ret_val; | ||
215 | } | ||
diff --git a/drivers/net/ethernet/intel/igc/igc_nvm.h b/drivers/net/ethernet/intel/igc/igc_nvm.h new file mode 100644 index 000000000000..f9fc2e9cfb03 --- /dev/null +++ b/drivers/net/ethernet/intel/igc/igc_nvm.h | |||
@@ -0,0 +1,14 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
2 | /* Copyright (c) 2018 Intel Corporation */ | ||
3 | |||
4 | #ifndef _IGC_NVM_H_ | ||
5 | #define _IGC_NVM_H_ | ||
6 | |||
7 | s32 igc_acquire_nvm(struct igc_hw *hw); | ||
8 | void igc_release_nvm(struct igc_hw *hw); | ||
9 | s32 igc_read_mac_addr(struct igc_hw *hw); | ||
10 | s32 igc_read_nvm_eerd(struct igc_hw *hw, u16 offset, u16 words, u16 *data); | ||
11 | s32 igc_validate_nvm_checksum(struct igc_hw *hw); | ||
12 | s32 igc_update_nvm_checksum(struct igc_hw *hw); | ||
13 | |||
14 | #endif | ||
diff --git a/drivers/net/ethernet/intel/igc/igc_regs.h b/drivers/net/ethernet/intel/igc/igc_regs.h index c57f573fb864..b5996e474c3c 100644 --- a/drivers/net/ethernet/intel/igc/igc_regs.h +++ b/drivers/net/ethernet/intel/igc/igc_regs.h | |||
@@ -191,6 +191,9 @@ | |||
191 | /* Management registers */ | 191 | /* Management registers */ |
192 | #define IGC_MANC 0x05820 /* Management Control - RW */ | 192 | #define IGC_MANC 0x05820 /* Management Control - RW */ |
193 | 193 | ||
194 | /* Shadow Ram Write Register - RW */ | ||
195 | #define IGC_SRWR 0x12018 | ||
196 | |||
194 | /* forward declaration */ | 197 | /* forward declaration */ |
195 | struct igc_hw; | 198 | struct igc_hw; |
196 | u32 igc_rd32(struct igc_hw *hw, u32 reg); | 199 | u32 igc_rd32(struct igc_hw *hw, u32 reg); |