1/*
2 * Copyright (C) 1999 - 2010 Intel Corporation.
3 * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
4 *
5 * This code was derived from the Intel e1000e Linux driver.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
18 */
19#include "pch_gbe.h"
20#include "pch_gbe_phy.h"
21#include "pch_gbe_api.h"
22
23/* bus type values */
24#define pch_gbe_bus_type_unknown	0
25#define pch_gbe_bus_type_pci		1
26#define pch_gbe_bus_type_pcix		2
27#define pch_gbe_bus_type_pci_express	3
28#define pch_gbe_bus_type_reserved	4
29
30/* bus speed values */
31#define pch_gbe_bus_speed_unknown	0
32#define pch_gbe_bus_speed_33		1
33#define pch_gbe_bus_speed_66		2
34#define pch_gbe_bus_speed_100		3
35#define pch_gbe_bus_speed_120		4
36#define pch_gbe_bus_speed_133		5
37#define pch_gbe_bus_speed_2500		6
38#define pch_gbe_bus_speed_reserved	7
39
40/* bus width values */
41#define pch_gbe_bus_width_unknown	0
42#define pch_gbe_bus_width_pcie_x1	1
43#define pch_gbe_bus_width_pcie_x2	2
44#define pch_gbe_bus_width_pcie_x4	4
45#define pch_gbe_bus_width_32		5
46#define pch_gbe_bus_width_64		6
47#define pch_gbe_bus_width_reserved	7
48
49/**
50 * pch_gbe_plat_get_bus_info - Obtain bus information for adapter
51 * @hw:	Pointer to the HW structure
52 */
53static void pch_gbe_plat_get_bus_info(struct pch_gbe_hw *hw)
54{
55	hw->bus.type  = pch_gbe_bus_type_pci_express;
56	hw->bus.speed = pch_gbe_bus_speed_2500;
57	hw->bus.width = pch_gbe_bus_width_pcie_x1;
58}
59
60/**
61 * pch_gbe_plat_init_hw - Initialize hardware
62 * @hw:	Pointer to the HW structure
63 * Returns:
64 *	0:		Successfully
65 *	Negative value:	Failed-EBUSY
66 */
67static s32 pch_gbe_plat_init_hw(struct pch_gbe_hw *hw)
68{
69	s32 ret_val;
70
71	ret_val = pch_gbe_phy_get_id(hw);
72	if (ret_val) {
73		struct pch_gbe_adapter *adapter = pch_gbe_hw_to_adapter(hw);
74
75		netdev_err(adapter->netdev, "pch_gbe_phy_get_id error\n");
76		return ret_val;
77	}
78	pch_gbe_phy_init_setting(hw);
79	/* Setup Mac interface option RGMII */
80#ifdef PCH_GBE_MAC_IFOP_RGMII
81	pch_gbe_phy_set_rgmii(hw);
82#endif
83	return ret_val;
84}
85
86static const struct pch_gbe_functions pch_gbe_ops = {
87	.get_bus_info      = pch_gbe_plat_get_bus_info,
88	.init_hw           = pch_gbe_plat_init_hw,
89	.read_phy_reg      = pch_gbe_phy_read_reg_miic,
90	.write_phy_reg     = pch_gbe_phy_write_reg_miic,
91	.reset_phy         = pch_gbe_phy_hw_reset,
92	.sw_reset_phy      = pch_gbe_phy_sw_reset,
93	.power_up_phy      = pch_gbe_phy_power_up,
94	.power_down_phy    = pch_gbe_phy_power_down,
95	.read_mac_addr     = pch_gbe_mac_read_mac_addr
96};
97
98/**
99 * pch_gbe_plat_init_function_pointers - Init func ptrs
100 * @hw:	Pointer to the HW structure
101 */
102static void pch_gbe_plat_init_function_pointers(struct pch_gbe_hw *hw)
103{
104	/* Set PHY parameter */
105	hw->phy.reset_delay_us     = PCH_GBE_PHY_RESET_DELAY_US;
106	/* Set function pointers */
107	hw->func = &pch_gbe_ops;
108}
109
110/**
111 * pch_gbe_hal_setup_init_funcs - Initializes function pointers
112 * @hw:	Pointer to the HW structure
113 * Returns:
114 *	0:	Successfully
115 *	ENOSYS:	Function is not registered
116 */
117s32 pch_gbe_hal_setup_init_funcs(struct pch_gbe_hw *hw)
118{
119	if (!hw->reg) {
120		struct pch_gbe_adapter *adapter = pch_gbe_hw_to_adapter(hw);
121
122		netdev_err(adapter->netdev, "ERROR: Registers not mapped\n");
123		return -ENOSYS;
124	}
125	pch_gbe_plat_init_function_pointers(hw);
126	return 0;
127}
128
129/**
130 * pch_gbe_hal_get_bus_info - Obtain bus information for adapter
131 * @hw:	Pointer to the HW structure
132 */
133void pch_gbe_hal_get_bus_info(struct pch_gbe_hw *hw)
134{
135	if (!hw->func->get_bus_info) {
136		struct pch_gbe_adapter *adapter = pch_gbe_hw_to_adapter(hw);
137
138		netdev_err(adapter->netdev, "ERROR: configuration\n");
139		return;
140	}
141	hw->func->get_bus_info(hw);
142}
143
144/**
145 * pch_gbe_hal_init_hw - Initialize hardware
146 * @hw:	Pointer to the HW structure
147 * Returns:
148 *	0:	Successfully
149 *	ENOSYS:	Function is not registered
150 */
151s32 pch_gbe_hal_init_hw(struct pch_gbe_hw *hw)
152{
153	if (!hw->func->init_hw) {
154		struct pch_gbe_adapter *adapter = pch_gbe_hw_to_adapter(hw);
155
156		netdev_err(adapter->netdev, "ERROR: configuration\n");
157		return -ENOSYS;
158	}
159	return hw->func->init_hw(hw);
160}
161
162/**
163 * pch_gbe_hal_read_phy_reg - Reads PHY register
164 * @hw:	    Pointer to the HW structure
165 * @offset: The register to read
166 * @data:   The buffer to store the 16-bit read.
167 * Returns:
168 *	0:	Successfully
169 *	Negative value:	Failed
170 */
171s32 pch_gbe_hal_read_phy_reg(struct pch_gbe_hw *hw, u32 offset,
172					u16 *data)
173{
174	if (!hw->func->read_phy_reg)
175		return 0;
176	return hw->func->read_phy_reg(hw, offset, data);
177}
178
179/**
180 * pch_gbe_hal_write_phy_reg - Writes PHY register
181 * @hw:	    Pointer to the HW structure
182 * @offset: The register to read
183 * @data:   The value to write.
184 * Returns:
185 *	0:	Successfully
186 *	Negative value:	Failed
187 */
188s32 pch_gbe_hal_write_phy_reg(struct pch_gbe_hw *hw, u32 offset,
189					u16 data)
190{
191	if (!hw->func->write_phy_reg)
192		return 0;
193	return hw->func->write_phy_reg(hw, offset, data);
194}
195
196/**
197 * pch_gbe_hal_phy_hw_reset - Hard PHY reset
198 * @hw:	    Pointer to the HW structure
199 */
200void pch_gbe_hal_phy_hw_reset(struct pch_gbe_hw *hw)
201{
202	if (!hw->func->reset_phy) {
203		struct pch_gbe_adapter *adapter = pch_gbe_hw_to_adapter(hw);
204
205		netdev_err(adapter->netdev, "ERROR: configuration\n");
206		return;
207	}
208	hw->func->reset_phy(hw);
209}
210
211/**
212 * pch_gbe_hal_phy_sw_reset - Soft PHY reset
213 * @hw:	    Pointer to the HW structure
214 */
215void pch_gbe_hal_phy_sw_reset(struct pch_gbe_hw *hw)
216{
217	if (!hw->func->sw_reset_phy) {
218		struct pch_gbe_adapter *adapter = pch_gbe_hw_to_adapter(hw);
219
220		netdev_err(adapter->netdev, "ERROR: configuration\n");
221		return;
222	}
223	hw->func->sw_reset_phy(hw);
224}
225
226/**
227 * pch_gbe_hal_read_mac_addr - Reads MAC address
228 * @hw:	Pointer to the HW structure
229 * Returns:
230 *	0:	Successfully
231 *	ENOSYS:	Function is not registered
232 */
233s32 pch_gbe_hal_read_mac_addr(struct pch_gbe_hw *hw)
234{
235	if (!hw->func->read_mac_addr) {
236		struct pch_gbe_adapter *adapter = pch_gbe_hw_to_adapter(hw);
237
238		netdev_err(adapter->netdev, "ERROR: configuration\n");
239		return -ENOSYS;
240	}
241	return hw->func->read_mac_addr(hw);
242}
243
244/**
245 * pch_gbe_hal_power_up_phy - Power up PHY
246 * @hw:	Pointer to the HW structure
247 */
248void pch_gbe_hal_power_up_phy(struct pch_gbe_hw *hw)
249{
250	if (hw->func->power_up_phy)
251		hw->func->power_up_phy(hw);
252}
253
254/**
255 * pch_gbe_hal_power_down_phy - Power down PHY
256 * @hw:	Pointer to the HW structure
257 */
258void pch_gbe_hal_power_down_phy(struct pch_gbe_hw *hw)
259{
260	if (hw->func->power_down_phy)
261		hw->func->power_down_phy(hw);
262}
263