1*fb38d839Srin /* $NetBSD: igc_api.c,v 1.2 2023/10/04 07:35:27 rin Exp $ */
2d0d8f2a5Srin /* $OpenBSD: igc_api.c,v 1.1 2021/10/31 14:52:57 patrick Exp $ */
3d0d8f2a5Srin /*-
4d0d8f2a5Srin * Copyright 2021 Intel Corp
5d0d8f2a5Srin * Copyright 2021 Rubicon Communications, LLC (Netgate)
6d0d8f2a5Srin * SPDX-License-Identifier: BSD-3-Clause
7d0d8f2a5Srin */
8d0d8f2a5Srin
9*fb38d839Srin #include <sys/cdefs.h>
10*fb38d839Srin __KERNEL_RCSID(0, "$NetBSD: igc_api.c,v 1.2 2023/10/04 07:35:27 rin Exp $");
11*fb38d839Srin
12*fb38d839Srin #include <dev/pci/igc/igc_api.h>
13*fb38d839Srin #include <dev/pci/igc/igc_hw.h>
14d0d8f2a5Srin
15d0d8f2a5Srin /**
16d0d8f2a5Srin * igc_init_mac_params - Initialize MAC function pointers
17d0d8f2a5Srin * @hw: pointer to the HW structure
18d0d8f2a5Srin *
19d0d8f2a5Srin * This function initializes the function pointers for the MAC
20d0d8f2a5Srin * set of functions. Called by drivers or by igc_setup_init_funcs.
21d0d8f2a5Srin **/
22d0d8f2a5Srin int
igc_init_mac_params(struct igc_hw * hw)23d0d8f2a5Srin igc_init_mac_params(struct igc_hw *hw)
24d0d8f2a5Srin {
25d0d8f2a5Srin int ret_val = IGC_SUCCESS;
26d0d8f2a5Srin
27d0d8f2a5Srin if (hw->mac.ops.init_params) {
28d0d8f2a5Srin ret_val = hw->mac.ops.init_params(hw);
29d0d8f2a5Srin if (ret_val) {
30d0d8f2a5Srin DEBUGOUT("MAC Initialization Error\n");
31d0d8f2a5Srin goto out;
32d0d8f2a5Srin }
33d0d8f2a5Srin } else {
34d0d8f2a5Srin DEBUGOUT("mac.init_mac_params was NULL\n");
35d0d8f2a5Srin ret_val = -IGC_ERR_CONFIG;
36d0d8f2a5Srin }
37d0d8f2a5Srin out:
38d0d8f2a5Srin return ret_val;
39d0d8f2a5Srin }
40d0d8f2a5Srin
41d0d8f2a5Srin /**
42d0d8f2a5Srin * igc_init_nvm_params - Initialize NVM function pointers
43d0d8f2a5Srin * @hw: pointer to the HW structure
44d0d8f2a5Srin *
45d0d8f2a5Srin * This function initializes the function pointers for the NVM
46d0d8f2a5Srin * set of functions. Called by drivers or by igc_setup_init_funcs.
47d0d8f2a5Srin **/
48d0d8f2a5Srin int
igc_init_nvm_params(struct igc_hw * hw)49d0d8f2a5Srin igc_init_nvm_params(struct igc_hw *hw)
50d0d8f2a5Srin {
51d0d8f2a5Srin int ret_val = IGC_SUCCESS;
52d0d8f2a5Srin
53d0d8f2a5Srin if (hw->nvm.ops.init_params) {
54d0d8f2a5Srin ret_val = hw->nvm.ops.init_params(hw);
55d0d8f2a5Srin if (ret_val) {
56d0d8f2a5Srin DEBUGOUT("NVM Initialization Error\n");
57d0d8f2a5Srin goto out;
58d0d8f2a5Srin }
59d0d8f2a5Srin } else {
60d0d8f2a5Srin DEBUGOUT("nvm.init_nvm_params was NULL\n");
61d0d8f2a5Srin ret_val = -IGC_ERR_CONFIG;
62d0d8f2a5Srin }
63d0d8f2a5Srin out:
64d0d8f2a5Srin return ret_val;
65d0d8f2a5Srin }
66d0d8f2a5Srin
67d0d8f2a5Srin /**
68d0d8f2a5Srin * igc_init_phy_params - Initialize PHY function pointers
69d0d8f2a5Srin * @hw: pointer to the HW structure
70d0d8f2a5Srin *
71d0d8f2a5Srin * This function initializes the function pointers for the PHY
72d0d8f2a5Srin * set of functions. Called by drivers or by igc_setup_init_funcs.
73d0d8f2a5Srin **/
74d0d8f2a5Srin int
igc_init_phy_params(struct igc_hw * hw)75d0d8f2a5Srin igc_init_phy_params(struct igc_hw *hw)
76d0d8f2a5Srin {
77d0d8f2a5Srin int ret_val = IGC_SUCCESS;
78d0d8f2a5Srin
79d0d8f2a5Srin if (hw->phy.ops.init_params) {
80d0d8f2a5Srin ret_val = hw->phy.ops.init_params(hw);
81d0d8f2a5Srin if (ret_val) {
82d0d8f2a5Srin DEBUGOUT("PHY Initialization Error\n");
83d0d8f2a5Srin goto out;
84d0d8f2a5Srin }
85d0d8f2a5Srin } else {
86d0d8f2a5Srin DEBUGOUT("phy.init_phy_params was NULL\n");
87d0d8f2a5Srin ret_val = -IGC_ERR_CONFIG;
88d0d8f2a5Srin }
89d0d8f2a5Srin out:
90d0d8f2a5Srin return ret_val;
91d0d8f2a5Srin }
92d0d8f2a5Srin
93d0d8f2a5Srin /**
94d0d8f2a5Srin * igc_set_mac_type - Sets MAC type
95d0d8f2a5Srin * @hw: pointer to the HW structure
96d0d8f2a5Srin *
97d0d8f2a5Srin * This function sets the mac type of the adapter based on the
98d0d8f2a5Srin * device ID stored in the hw structure.
99d0d8f2a5Srin * MUST BE FIRST FUNCTION CALLED (explicitly or through
100d0d8f2a5Srin * igc_setup_init_funcs()).
101d0d8f2a5Srin **/
102d0d8f2a5Srin int
igc_set_mac_type(struct igc_hw * hw)103d0d8f2a5Srin igc_set_mac_type(struct igc_hw *hw)
104d0d8f2a5Srin {
105d0d8f2a5Srin struct igc_mac_info *mac = &hw->mac;
106d0d8f2a5Srin int ret_val = IGC_SUCCESS;
107d0d8f2a5Srin
108d0d8f2a5Srin DEBUGFUNC("igc_set_mac_type");
109d0d8f2a5Srin
110d0d8f2a5Srin switch (hw->device_id) {
111d0d8f2a5Srin case PCI_PRODUCT_INTEL_I220_V:
112d0d8f2a5Srin case PCI_PRODUCT_INTEL_I221_V:
113d0d8f2a5Srin case PCI_PRODUCT_INTEL_I225_BLANK_NVM:
114d0d8f2a5Srin case PCI_PRODUCT_INTEL_I225_I:
115d0d8f2a5Srin case PCI_PRODUCT_INTEL_I225_IT:
116d0d8f2a5Srin case PCI_PRODUCT_INTEL_I225_K:
117d0d8f2a5Srin case PCI_PRODUCT_INTEL_I225_K2:
118d0d8f2a5Srin case PCI_PRODUCT_INTEL_I225_LM:
119d0d8f2a5Srin case PCI_PRODUCT_INTEL_I225_LMVP:
120d0d8f2a5Srin case PCI_PRODUCT_INTEL_I225_V:
121d0d8f2a5Srin case PCI_PRODUCT_INTEL_I226_BLANK_NVM:
122d0d8f2a5Srin case PCI_PRODUCT_INTEL_I226_IT:
123d0d8f2a5Srin case PCI_PRODUCT_INTEL_I226_LM:
124*fb38d839Srin case PCI_PRODUCT_INTEL_I226_LMVP:
125d0d8f2a5Srin case PCI_PRODUCT_INTEL_I226_K:
126d0d8f2a5Srin case PCI_PRODUCT_INTEL_I226_V:
127d0d8f2a5Srin mac->type = igc_i225;
128d0d8f2a5Srin break;
129d0d8f2a5Srin default:
130d0d8f2a5Srin /* Should never have loaded on this device */
131d0d8f2a5Srin ret_val = -IGC_ERR_MAC_INIT;
132d0d8f2a5Srin break;
133d0d8f2a5Srin }
134d0d8f2a5Srin
135d0d8f2a5Srin return ret_val;
136d0d8f2a5Srin }
137d0d8f2a5Srin
138d0d8f2a5Srin /**
139d0d8f2a5Srin * igc_setup_init_funcs - Initializes function pointers
140d0d8f2a5Srin * @hw: pointer to the HW structure
141d0d8f2a5Srin * @init_device: true will initialize the rest of the function pointers
142d0d8f2a5Srin * getting the device ready for use. FALSE will only set
143d0d8f2a5Srin * MAC type and the function pointers for the other init
144d0d8f2a5Srin * functions. Passing FALSE will not generate any hardware
145d0d8f2a5Srin * reads or writes.
146d0d8f2a5Srin *
147d0d8f2a5Srin * This function must be called by a driver in order to use the rest
148d0d8f2a5Srin * of the 'shared' code files. Called by drivers only.
149d0d8f2a5Srin **/
150d0d8f2a5Srin int
igc_setup_init_funcs(struct igc_hw * hw,bool init_device)151d0d8f2a5Srin igc_setup_init_funcs(struct igc_hw *hw, bool init_device)
152d0d8f2a5Srin {
153d0d8f2a5Srin int ret_val;
154d0d8f2a5Srin
155d0d8f2a5Srin /* Can't do much good without knowing the MAC type. */
156d0d8f2a5Srin ret_val = igc_set_mac_type(hw);
157d0d8f2a5Srin if (ret_val) {
158d0d8f2a5Srin DEBUGOUT("ERROR: MAC type could not be set properly.\n");
159d0d8f2a5Srin goto out;
160d0d8f2a5Srin }
161d0d8f2a5Srin
162d0d8f2a5Srin if (!hw->hw_addr) {
163d0d8f2a5Srin DEBUGOUT("ERROR: Registers not mapped\n");
164d0d8f2a5Srin ret_val = -IGC_ERR_CONFIG;
165d0d8f2a5Srin goto out;
166d0d8f2a5Srin }
167d0d8f2a5Srin
168d0d8f2a5Srin /*
169d0d8f2a5Srin * Init function pointers to generic implementations. We do this first
170d0d8f2a5Srin * allowing a driver module to override it afterward.
171d0d8f2a5Srin */
172d0d8f2a5Srin igc_init_mac_ops_generic(hw);
173d0d8f2a5Srin igc_init_phy_ops_generic(hw);
174d0d8f2a5Srin igc_init_nvm_ops_generic(hw);
175d0d8f2a5Srin
176d0d8f2a5Srin /*
177d0d8f2a5Srin * Set up the init function pointers. These are functions within the
178d0d8f2a5Srin * adapter family file that sets up function pointers for the rest of
179d0d8f2a5Srin * the functions in that family.
180d0d8f2a5Srin */
181d0d8f2a5Srin switch (hw->mac.type) {
182d0d8f2a5Srin case igc_i225:
183d0d8f2a5Srin igc_init_function_pointers_i225(hw);
184d0d8f2a5Srin break;
185d0d8f2a5Srin default:
186d0d8f2a5Srin DEBUGOUT("Hardware not supported\n");
187d0d8f2a5Srin ret_val = -IGC_ERR_CONFIG;
188d0d8f2a5Srin break;
189d0d8f2a5Srin }
190d0d8f2a5Srin
191d0d8f2a5Srin /*
192d0d8f2a5Srin * Initialize the rest of the function pointers. These require some
193d0d8f2a5Srin * register reads/writes in some cases.
194d0d8f2a5Srin */
195d0d8f2a5Srin if (!(ret_val) && init_device) {
196d0d8f2a5Srin ret_val = igc_init_mac_params(hw);
197d0d8f2a5Srin if (ret_val)
198d0d8f2a5Srin goto out;
199d0d8f2a5Srin
200d0d8f2a5Srin ret_val = igc_init_nvm_params(hw);
201d0d8f2a5Srin if (ret_val)
202d0d8f2a5Srin goto out;
203d0d8f2a5Srin
204d0d8f2a5Srin ret_val = igc_init_phy_params(hw);
205d0d8f2a5Srin if (ret_val)
206d0d8f2a5Srin goto out;
207d0d8f2a5Srin }
208d0d8f2a5Srin out:
209d0d8f2a5Srin return ret_val;
210d0d8f2a5Srin }
211d0d8f2a5Srin
212d0d8f2a5Srin /**
213d0d8f2a5Srin * igc_update_mc_addr_list - Update Multicast addresses
214d0d8f2a5Srin * @hw: pointer to the HW structure
215d0d8f2a5Srin * @mc_addr_list: array of multicast addresses to program
216d0d8f2a5Srin * @mc_addr_count: number of multicast addresses to program
217d0d8f2a5Srin *
218d0d8f2a5Srin * Updates the Multicast Table Array.
219d0d8f2a5Srin * The caller must have a packed mc_addr_list of multicast addresses.
220d0d8f2a5Srin **/
221d0d8f2a5Srin void
igc_update_mc_addr_list(struct igc_hw * hw,uint8_t * mc_addr_list,uint32_t mc_addr_count)222d0d8f2a5Srin igc_update_mc_addr_list(struct igc_hw *hw, uint8_t *mc_addr_list,
223d0d8f2a5Srin uint32_t mc_addr_count)
224d0d8f2a5Srin {
225d0d8f2a5Srin if (hw->mac.ops.update_mc_addr_list)
226d0d8f2a5Srin hw->mac.ops.update_mc_addr_list(hw, mc_addr_list,
227d0d8f2a5Srin mc_addr_count);
228d0d8f2a5Srin }
229d0d8f2a5Srin
230d0d8f2a5Srin /**
231d0d8f2a5Srin * igc_check_for_link - Check/Store link connection
232d0d8f2a5Srin * @hw: pointer to the HW structure
233d0d8f2a5Srin *
234d0d8f2a5Srin * This checks the link condition of the adapter and stores the
235d0d8f2a5Srin * results in the hw->mac structure. This is a function pointer entry
236d0d8f2a5Srin * point called by drivers.
237d0d8f2a5Srin **/
238d0d8f2a5Srin int
igc_check_for_link(struct igc_hw * hw)239d0d8f2a5Srin igc_check_for_link(struct igc_hw *hw)
240d0d8f2a5Srin {
241d0d8f2a5Srin if (hw->mac.ops.check_for_link)
242d0d8f2a5Srin return hw->mac.ops.check_for_link(hw);
243d0d8f2a5Srin
244d0d8f2a5Srin return -IGC_ERR_CONFIG;
245d0d8f2a5Srin }
246d0d8f2a5Srin
247d0d8f2a5Srin /**
248d0d8f2a5Srin * igc_reset_hw - Reset hardware
249d0d8f2a5Srin * @hw: pointer to the HW structure
250d0d8f2a5Srin *
251d0d8f2a5Srin * This resets the hardware into a known state. This is a function pointer
252d0d8f2a5Srin * entry point called by drivers.
253d0d8f2a5Srin **/
254d0d8f2a5Srin int
igc_reset_hw(struct igc_hw * hw)255d0d8f2a5Srin igc_reset_hw(struct igc_hw *hw)
256d0d8f2a5Srin {
257d0d8f2a5Srin if (hw->mac.ops.reset_hw)
258d0d8f2a5Srin return hw->mac.ops.reset_hw(hw);
259d0d8f2a5Srin
260d0d8f2a5Srin return -IGC_ERR_CONFIG;
261d0d8f2a5Srin }
262d0d8f2a5Srin
263d0d8f2a5Srin /**
264d0d8f2a5Srin * igc_init_hw - Initialize hardware
265d0d8f2a5Srin * @hw: pointer to the HW structure
266d0d8f2a5Srin *
267d0d8f2a5Srin * This inits the hardware readying it for operation. This is a function
268d0d8f2a5Srin * pointer entry point called by drivers.
269d0d8f2a5Srin **/
270d0d8f2a5Srin int
igc_init_hw(struct igc_hw * hw)271d0d8f2a5Srin igc_init_hw(struct igc_hw *hw)
272d0d8f2a5Srin {
273d0d8f2a5Srin if (hw->mac.ops.init_hw)
274d0d8f2a5Srin return hw->mac.ops.init_hw(hw);
275d0d8f2a5Srin
276d0d8f2a5Srin return -IGC_ERR_CONFIG;
277d0d8f2a5Srin }
278d0d8f2a5Srin
279d0d8f2a5Srin /**
280d0d8f2a5Srin * igc_get_speed_and_duplex - Returns current speed and duplex
281d0d8f2a5Srin * @hw: pointer to the HW structure
282d0d8f2a5Srin * @speed: pointer to a 16-bit value to store the speed
283d0d8f2a5Srin * @duplex: pointer to a 16-bit value to store the duplex.
284d0d8f2a5Srin *
285d0d8f2a5Srin * This returns the speed and duplex of the adapter in the two 'out'
286d0d8f2a5Srin * variables passed in. This is a function pointer entry point called
287d0d8f2a5Srin * by drivers.
288d0d8f2a5Srin **/
289d0d8f2a5Srin int
igc_get_speed_and_duplex(struct igc_hw * hw,uint16_t * speed,uint16_t * duplex)290d0d8f2a5Srin igc_get_speed_and_duplex(struct igc_hw *hw, uint16_t *speed, uint16_t *duplex)
291d0d8f2a5Srin {
292d0d8f2a5Srin if (hw->mac.ops.get_link_up_info)
293d0d8f2a5Srin return hw->mac.ops.get_link_up_info(hw, speed, duplex);
294d0d8f2a5Srin
295d0d8f2a5Srin return -IGC_ERR_CONFIG;
296d0d8f2a5Srin }
297d0d8f2a5Srin
298d0d8f2a5Srin /**
299d0d8f2a5Srin * igc_rar_set - Sets a receive address register
300d0d8f2a5Srin * @hw: pointer to the HW structure
301d0d8f2a5Srin * @addr: address to set the RAR to
302d0d8f2a5Srin * @index: the RAR to set
303d0d8f2a5Srin *
304d0d8f2a5Srin * Sets a Receive Address Register (RAR) to the specified address.
305d0d8f2a5Srin **/
306d0d8f2a5Srin int
igc_rar_set(struct igc_hw * hw,uint8_t * addr,uint32_t index)307d0d8f2a5Srin igc_rar_set(struct igc_hw *hw, uint8_t *addr, uint32_t index)
308d0d8f2a5Srin {
309d0d8f2a5Srin if (hw->mac.ops.rar_set)
310d0d8f2a5Srin return hw->mac.ops.rar_set(hw, addr, index);
311d0d8f2a5Srin
312d0d8f2a5Srin return IGC_SUCCESS;
313d0d8f2a5Srin }
314d0d8f2a5Srin
315d0d8f2a5Srin /**
316d0d8f2a5Srin * igc_check_reset_block - Verifies PHY can be reset
317d0d8f2a5Srin * @hw: pointer to the HW structure
318d0d8f2a5Srin *
319d0d8f2a5Srin * Checks if the PHY is in a state that can be reset or if manageability
320d0d8f2a5Srin * has it tied up. This is a function pointer entry point called by drivers.
321d0d8f2a5Srin **/
322d0d8f2a5Srin int
igc_check_reset_block(struct igc_hw * hw)323d0d8f2a5Srin igc_check_reset_block(struct igc_hw *hw)
324d0d8f2a5Srin {
325d0d8f2a5Srin if (hw->phy.ops.check_reset_block)
326d0d8f2a5Srin return hw->phy.ops.check_reset_block(hw);
327d0d8f2a5Srin
328d0d8f2a5Srin return IGC_SUCCESS;
329d0d8f2a5Srin }
330d0d8f2a5Srin
331d0d8f2a5Srin /**
332d0d8f2a5Srin * igc_get_phy_info - Retrieves PHY information from registers
333d0d8f2a5Srin * @hw: pointer to the HW structure
334d0d8f2a5Srin *
335d0d8f2a5Srin * This function gets some information from various PHY registers and
336d0d8f2a5Srin * populates hw->phy values with it. This is a function pointer entry
337d0d8f2a5Srin * point called by drivers.
338d0d8f2a5Srin **/
339d0d8f2a5Srin int
igc_get_phy_info(struct igc_hw * hw)340d0d8f2a5Srin igc_get_phy_info(struct igc_hw *hw)
341d0d8f2a5Srin {
342d0d8f2a5Srin if (hw->phy.ops.get_info)
343d0d8f2a5Srin return hw->phy.ops.get_info(hw);
344d0d8f2a5Srin
345d0d8f2a5Srin return IGC_SUCCESS;
346d0d8f2a5Srin }
347d0d8f2a5Srin
348d0d8f2a5Srin /**
349d0d8f2a5Srin * igc_phy_hw_reset - Hard PHY reset
350d0d8f2a5Srin * @hw: pointer to the HW structure
351d0d8f2a5Srin *
352d0d8f2a5Srin * Performs a hard PHY reset. This is a function pointer entry point called
353d0d8f2a5Srin * by drivers.
354d0d8f2a5Srin **/
355d0d8f2a5Srin int
igc_phy_hw_reset(struct igc_hw * hw)356d0d8f2a5Srin igc_phy_hw_reset(struct igc_hw *hw)
357d0d8f2a5Srin {
358d0d8f2a5Srin if (hw->phy.ops.reset)
359d0d8f2a5Srin return hw->phy.ops.reset(hw);
360d0d8f2a5Srin
361d0d8f2a5Srin return IGC_SUCCESS;
362d0d8f2a5Srin }
363d0d8f2a5Srin
364d0d8f2a5Srin /**
365d0d8f2a5Srin * igc_read_mac_addr - Reads MAC address
366d0d8f2a5Srin * @hw: pointer to the HW structure
367d0d8f2a5Srin *
368d0d8f2a5Srin * Reads the MAC address out of the adapter and stores it in the HW structure.
369d0d8f2a5Srin * Currently no func pointer exists and all implementations are handled in the
370d0d8f2a5Srin * generic version of this function.
371d0d8f2a5Srin **/
372d0d8f2a5Srin int
igc_read_mac_addr(struct igc_hw * hw)373d0d8f2a5Srin igc_read_mac_addr(struct igc_hw *hw)
374d0d8f2a5Srin {
375d0d8f2a5Srin if (hw->mac.ops.read_mac_addr)
376d0d8f2a5Srin return hw->mac.ops.read_mac_addr(hw);
377d0d8f2a5Srin
378d0d8f2a5Srin return igc_read_mac_addr_generic(hw);
379d0d8f2a5Srin }
380d0d8f2a5Srin
381d0d8f2a5Srin /**
382d0d8f2a5Srin * igc_validate_nvm_checksum - Verifies NVM (EEPROM) checksum
383d0d8f2a5Srin * @hw: pointer to the HW structure
384d0d8f2a5Srin *
385d0d8f2a5Srin * Validates the NVM checksum is correct. This is a function pointer entry
386d0d8f2a5Srin * point called by drivers.
387d0d8f2a5Srin **/
388d0d8f2a5Srin int
igc_validate_nvm_checksum(struct igc_hw * hw)389d0d8f2a5Srin igc_validate_nvm_checksum(struct igc_hw *hw)
390d0d8f2a5Srin {
391d0d8f2a5Srin if (hw->nvm.ops.validate)
392d0d8f2a5Srin return hw->nvm.ops.validate(hw);
393d0d8f2a5Srin
394d0d8f2a5Srin return -IGC_ERR_CONFIG;
395d0d8f2a5Srin }
396