xref: /netbsd-src/sys/dev/pci/igc/igc_base.c (revision fb38d839b48b9b6204dbbee1672454d6e719ba01)
1*fb38d839Srin /*	$NetBSD: igc_base.c,v 1.2 2023/10/04 07:35:27 rin Exp $	*/
2d0d8f2a5Srin /*	$OpenBSD: igc_base.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_base.c,v 1.2 2023/10/04 07:35:27 rin Exp $");
11*fb38d839Srin 
12*fb38d839Srin #include <dev/pci/igc/igc_hw.h>
13*fb38d839Srin #include <dev/pci/igc/igc_i225.h>
14*fb38d839Srin #include <dev/pci/igc/if_igc.h>
15*fb38d839Srin #include <dev/pci/igc/igc_mac.h>
16*fb38d839Srin #include <dev/pci/igc/igc_base.h>
17d0d8f2a5Srin 
18d0d8f2a5Srin /**
19d0d8f2a5Srin  *  igc_acquire_phy_base - Acquire rights to access PHY
20d0d8f2a5Srin  *  @hw: pointer to the HW structure
21d0d8f2a5Srin  *
22d0d8f2a5Srin  *  Acquire access rights to the correct PHY.
23d0d8f2a5Srin  **/
24d0d8f2a5Srin int
igc_acquire_phy_base(struct igc_hw * hw)25d0d8f2a5Srin igc_acquire_phy_base(struct igc_hw *hw)
26d0d8f2a5Srin {
27d0d8f2a5Srin 	uint16_t mask = IGC_SWFW_PHY0_SM;
28d0d8f2a5Srin 
29d0d8f2a5Srin 	DEBUGFUNC("igc_acquire_phy_base");
30d0d8f2a5Srin 
31d0d8f2a5Srin 	if (hw->bus.func == IGC_FUNC_1)
32d0d8f2a5Srin 		mask = IGC_SWFW_PHY1_SM;
33d0d8f2a5Srin 
34d0d8f2a5Srin 	return hw->mac.ops.acquire_swfw_sync(hw, mask);
35d0d8f2a5Srin }
36d0d8f2a5Srin 
37d0d8f2a5Srin /**
38d0d8f2a5Srin  *  igc_release_phy_base - Release rights to access PHY
39d0d8f2a5Srin  *  @hw: pointer to the HW structure
40d0d8f2a5Srin  *
41d0d8f2a5Srin  *  A wrapper to release access rights to the correct PHY.
42d0d8f2a5Srin  **/
43d0d8f2a5Srin void
igc_release_phy_base(struct igc_hw * hw)44d0d8f2a5Srin igc_release_phy_base(struct igc_hw *hw)
45d0d8f2a5Srin {
46d0d8f2a5Srin 	uint16_t mask = IGC_SWFW_PHY0_SM;
47d0d8f2a5Srin 
48d0d8f2a5Srin 	DEBUGFUNC("igc_release_phy_base");
49d0d8f2a5Srin 
50d0d8f2a5Srin 	if (hw->bus.func == IGC_FUNC_1)
51d0d8f2a5Srin 		mask = IGC_SWFW_PHY1_SM;
52d0d8f2a5Srin 
53d0d8f2a5Srin 	hw->mac.ops.release_swfw_sync(hw, mask);
54d0d8f2a5Srin }
55d0d8f2a5Srin 
56d0d8f2a5Srin /**
57d0d8f2a5Srin  *  igc_init_hw_base - Initialize hardware
58d0d8f2a5Srin  *  @hw: pointer to the HW structure
59d0d8f2a5Srin  *
60d0d8f2a5Srin  *  This inits the hardware readying it for operation.
61d0d8f2a5Srin  **/
62d0d8f2a5Srin int
igc_init_hw_base(struct igc_hw * hw)63d0d8f2a5Srin igc_init_hw_base(struct igc_hw *hw)
64d0d8f2a5Srin {
65d0d8f2a5Srin 	struct igc_mac_info *mac = &hw->mac;
66d0d8f2a5Srin 	uint16_t i, rar_count = mac->rar_entry_count;
67d0d8f2a5Srin 	int ret_val;
68d0d8f2a5Srin 
69d0d8f2a5Srin 	DEBUGFUNC("igc_init_hw_base");
70d0d8f2a5Srin 
71d0d8f2a5Srin 	/* Setup the receive address */
72d0d8f2a5Srin 	igc_init_rx_addrs_generic(hw, rar_count);
73d0d8f2a5Srin 
74d0d8f2a5Srin 	/* Zero out the Multicast HASH table */
75d0d8f2a5Srin 	DEBUGOUT("Zeroing the MTA\n");
76d0d8f2a5Srin 	for (i = 0; i < mac->mta_reg_count; i++)
77d0d8f2a5Srin 		IGC_WRITE_REG_ARRAY(hw, IGC_MTA, i, 0);
78d0d8f2a5Srin 
79d0d8f2a5Srin 	/* Zero out the Unicast HASH table */
80d0d8f2a5Srin 	DEBUGOUT("Zeroing the UTA\n");
81d0d8f2a5Srin 	for (i = 0; i < mac->uta_reg_count; i++)
82d0d8f2a5Srin 		IGC_WRITE_REG_ARRAY(hw, IGC_UTA, i, 0);
83d0d8f2a5Srin 
84d0d8f2a5Srin 	/* Setup link and flow control */
85d0d8f2a5Srin 	ret_val = mac->ops.setup_link(hw);
86d0d8f2a5Srin 	/*
87d0d8f2a5Srin 	 * Clear all of the statistics registers (clear on read).  It is
88d0d8f2a5Srin 	 * important that we do this after we have tried to establish link
89d0d8f2a5Srin 	 * because the symbol error count will increment wildly if there
90d0d8f2a5Srin 	 * is no link.
91d0d8f2a5Srin 	 */
92d0d8f2a5Srin 	igc_clear_hw_cntrs_base_generic(hw);
93d0d8f2a5Srin 
94d0d8f2a5Srin 	return ret_val;
95d0d8f2a5Srin }
96d0d8f2a5Srin 
97d0d8f2a5Srin /**
98d0d8f2a5Srin  * igc_power_down_phy_copper_base - Remove link during PHY power down
99d0d8f2a5Srin  * @hw: pointer to the HW structure
100d0d8f2a5Srin  *
101d0d8f2a5Srin  * In the case of a PHY power down to save power, or to turn off link during a
102d0d8f2a5Srin  * driver unload, or wake on lan is not enabled, remove the link.
103d0d8f2a5Srin  **/
104d0d8f2a5Srin void
igc_power_down_phy_copper_base(struct igc_hw * hw)105d0d8f2a5Srin igc_power_down_phy_copper_base(struct igc_hw *hw)
106d0d8f2a5Srin {
107d0d8f2a5Srin 	struct igc_phy_info *phy = &hw->phy;
108d0d8f2a5Srin 
109d0d8f2a5Srin 	if (!(phy->ops.check_reset_block))
110d0d8f2a5Srin 		return;
111d0d8f2a5Srin 
112d0d8f2a5Srin 	/* If the management interface is not enabled, then power down */
113d0d8f2a5Srin 	if (phy->ops.check_reset_block(hw))
114d0d8f2a5Srin 		igc_power_down_phy_copper(hw);
115d0d8f2a5Srin 
116d0d8f2a5Srin 	return;
117d0d8f2a5Srin }
118