xref: /freebsd/sys/dev/ixl/ixl_pf_i2c.c (revision 71625ec9ad2a9bc8c09784fbd23b759830e0ee5f)
1cb6b8299SEric Joyner /******************************************************************************
2cb6b8299SEric Joyner 
3f4cc2d17SEric Joyner   Copyright (c) 2013-2018, Intel Corporation
4cb6b8299SEric Joyner   All rights reserved.
5cb6b8299SEric Joyner 
6cb6b8299SEric Joyner   Redistribution and use in source and binary forms, with or without
7cb6b8299SEric Joyner   modification, are permitted provided that the following conditions are met:
8cb6b8299SEric Joyner 
9cb6b8299SEric Joyner    1. Redistributions of source code must retain the above copyright notice,
10cb6b8299SEric Joyner       this list of conditions and the following disclaimer.
11cb6b8299SEric Joyner 
12cb6b8299SEric Joyner    2. Redistributions in binary form must reproduce the above copyright
13cb6b8299SEric Joyner       notice, this list of conditions and the following disclaimer in the
14cb6b8299SEric Joyner       documentation and/or other materials provided with the distribution.
15cb6b8299SEric Joyner 
16cb6b8299SEric Joyner    3. Neither the name of the Intel Corporation nor the names of its
17cb6b8299SEric Joyner       contributors may be used to endorse or promote products derived from
18cb6b8299SEric Joyner       this software without specific prior written permission.
19cb6b8299SEric Joyner 
20cb6b8299SEric Joyner   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21cb6b8299SEric Joyner   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22cb6b8299SEric Joyner   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23cb6b8299SEric Joyner   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24cb6b8299SEric Joyner   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25cb6b8299SEric Joyner   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26cb6b8299SEric Joyner   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27cb6b8299SEric Joyner   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28cb6b8299SEric Joyner   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29cb6b8299SEric Joyner   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30cb6b8299SEric Joyner   POSSIBILITY OF SUCH DAMAGE.
31cb6b8299SEric Joyner 
32cb6b8299SEric Joyner ******************************************************************************/
33cb6b8299SEric Joyner 
34cb6b8299SEric Joyner #include "ixl_pf.h"
35cb6b8299SEric Joyner 
36cb6b8299SEric Joyner #define IXL_I2C_T_RISE		1
37cb6b8299SEric Joyner #define IXL_I2C_T_FALL		1
38cb6b8299SEric Joyner #define IXL_I2C_T_SU_DATA	1
39cb6b8299SEric Joyner #define IXL_I2C_T_SU_STA	5
40cb6b8299SEric Joyner #define IXL_I2C_T_SU_STO	4
41cb6b8299SEric Joyner #define IXL_I2C_T_HD_STA	4
42cb6b8299SEric Joyner #define IXL_I2C_T_LOW		5
43cb6b8299SEric Joyner #define IXL_I2C_T_HIGH		4
44cb6b8299SEric Joyner #define IXL_I2C_T_BUF		5
45cb6b8299SEric Joyner #define IXL_I2C_CLOCK_STRETCHING_TIMEOUT 500
46cb6b8299SEric Joyner 
47cb6b8299SEric Joyner #define IXL_I2C_REG(_hw)	\
481031d839SEric Joyner     I40E_GLGEN_I2CPARAMS(_hw->func_caps.mdio_port_num)
49cb6b8299SEric Joyner 
501031d839SEric Joyner /* I2C bit-banging functions */
51cb6b8299SEric Joyner static s32	ixl_set_i2c_data(struct ixl_pf *pf, u32 *i2cctl, bool data);
52cb6b8299SEric Joyner static bool	ixl_get_i2c_data(struct ixl_pf *pf, u32 *i2cctl);
53cb6b8299SEric Joyner static void	ixl_raise_i2c_clk(struct ixl_pf *pf, u32 *i2cctl);
54cb6b8299SEric Joyner static void	ixl_lower_i2c_clk(struct ixl_pf *pf, u32 *i2cctl);
55cb6b8299SEric Joyner static s32	ixl_clock_out_i2c_bit(struct ixl_pf *pf, bool data);
56cb6b8299SEric Joyner static s32	ixl_get_i2c_ack(struct ixl_pf *pf);
57cb6b8299SEric Joyner static s32	ixl_clock_out_i2c_byte(struct ixl_pf *pf, u8 data);
58cb6b8299SEric Joyner static s32	ixl_clock_in_i2c_bit(struct ixl_pf *pf, bool *data);
59cb6b8299SEric Joyner static s32	ixl_clock_in_i2c_byte(struct ixl_pf *pf, u8 *data);
60cb6b8299SEric Joyner static void 	ixl_i2c_bus_clear(struct ixl_pf *pf);
61cb6b8299SEric Joyner static void	ixl_i2c_start(struct ixl_pf *pf);
62cb6b8299SEric Joyner static void	ixl_i2c_stop(struct ixl_pf *pf);
63cb6b8299SEric Joyner 
641031d839SEric Joyner static s32	ixl_wait_for_i2c_completion(struct i40e_hw *hw, u8 portnum);
651031d839SEric Joyner 
66cb6b8299SEric Joyner /**
67cb6b8299SEric Joyner  *  ixl_i2c_bus_clear - Clears the I2C bus
68cb6b8299SEric Joyner  *  @hw: pointer to hardware structure
69cb6b8299SEric Joyner  *
70cb6b8299SEric Joyner  *  Clears the I2C bus by sending nine clock pulses.
71cb6b8299SEric Joyner  *  Used when data line is stuck low.
72cb6b8299SEric Joyner  **/
73cb6b8299SEric Joyner static void
ixl_i2c_bus_clear(struct ixl_pf * pf)74cb6b8299SEric Joyner ixl_i2c_bus_clear(struct ixl_pf *pf)
75cb6b8299SEric Joyner {
76cb6b8299SEric Joyner 	struct i40e_hw *hw = &pf->hw;
77cb6b8299SEric Joyner 	u32 i2cctl = rd32(hw, IXL_I2C_REG(hw));
78cb6b8299SEric Joyner 	u32 i;
79cb6b8299SEric Joyner 
80cb6b8299SEric Joyner 	DEBUGFUNC("ixl_i2c_bus_clear");
81cb6b8299SEric Joyner 
82cb6b8299SEric Joyner 	ixl_i2c_start(pf);
83cb6b8299SEric Joyner 
84cb6b8299SEric Joyner 	ixl_set_i2c_data(pf, &i2cctl, 1);
85cb6b8299SEric Joyner 
86cb6b8299SEric Joyner 	for (i = 0; i < 9; i++) {
87cb6b8299SEric Joyner 		ixl_raise_i2c_clk(pf, &i2cctl);
88cb6b8299SEric Joyner 
89cb6b8299SEric Joyner 		/* Min high period of clock is 4us */
90cb6b8299SEric Joyner 		i40e_usec_delay(IXL_I2C_T_HIGH);
91cb6b8299SEric Joyner 
92cb6b8299SEric Joyner 		ixl_lower_i2c_clk(pf, &i2cctl);
93cb6b8299SEric Joyner 
94cb6b8299SEric Joyner 		/* Min low period of clock is 4.7us*/
95cb6b8299SEric Joyner 		i40e_usec_delay(IXL_I2C_T_LOW);
96cb6b8299SEric Joyner 	}
97cb6b8299SEric Joyner 
98cb6b8299SEric Joyner 	ixl_i2c_start(pf);
99cb6b8299SEric Joyner 
100cb6b8299SEric Joyner 	/* Put the i2c bus back to default state */
101cb6b8299SEric Joyner 	ixl_i2c_stop(pf);
102cb6b8299SEric Joyner }
103cb6b8299SEric Joyner 
104cb6b8299SEric Joyner /**
105cb6b8299SEric Joyner  *  ixl_i2c_stop - Sets I2C stop condition
106cb6b8299SEric Joyner  *  @hw: pointer to hardware structure
107cb6b8299SEric Joyner  *
108cb6b8299SEric Joyner  *  Sets I2C stop condition (Low -> High on SDA while SCL is High)
109cb6b8299SEric Joyner  **/
110cb6b8299SEric Joyner static void
ixl_i2c_stop(struct ixl_pf * pf)111cb6b8299SEric Joyner ixl_i2c_stop(struct ixl_pf *pf)
112cb6b8299SEric Joyner {
113cb6b8299SEric Joyner 	struct i40e_hw *hw = &pf->hw;
114cb6b8299SEric Joyner 	u32 i2cctl = rd32(hw, IXL_I2C_REG(hw));
115cb6b8299SEric Joyner 
116cb6b8299SEric Joyner 	DEBUGFUNC("ixl_i2c_stop");
117cb6b8299SEric Joyner 
118cb6b8299SEric Joyner 	/* Stop condition must begin with data low and clock high */
119cb6b8299SEric Joyner 	ixl_set_i2c_data(pf, &i2cctl, 0);
120cb6b8299SEric Joyner 	ixl_raise_i2c_clk(pf, &i2cctl);
121cb6b8299SEric Joyner 
122cb6b8299SEric Joyner 	/* Setup time for stop condition (4us) */
123cb6b8299SEric Joyner 	i40e_usec_delay(IXL_I2C_T_SU_STO);
124cb6b8299SEric Joyner 
125cb6b8299SEric Joyner 	ixl_set_i2c_data(pf, &i2cctl, 1);
126cb6b8299SEric Joyner 
127cb6b8299SEric Joyner 	/* bus free time between stop and start (4.7us)*/
128cb6b8299SEric Joyner 	i40e_usec_delay(IXL_I2C_T_BUF);
129cb6b8299SEric Joyner }
130cb6b8299SEric Joyner 
131cb6b8299SEric Joyner /**
132cb6b8299SEric Joyner  *  ixl_clock_in_i2c_byte - Clocks in one byte via I2C
133cb6b8299SEric Joyner  *  @hw: pointer to hardware structure
134cb6b8299SEric Joyner  *  @data: data byte to clock in
135cb6b8299SEric Joyner  *
136cb6b8299SEric Joyner  *  Clocks in one byte data via I2C data/clock
137cb6b8299SEric Joyner  **/
138cb6b8299SEric Joyner static s32
ixl_clock_in_i2c_byte(struct ixl_pf * pf,u8 * data)139cb6b8299SEric Joyner ixl_clock_in_i2c_byte(struct ixl_pf *pf, u8 *data)
140cb6b8299SEric Joyner {
141cb6b8299SEric Joyner 	s32 i;
142cb6b8299SEric Joyner 	bool bit = 0;
143cb6b8299SEric Joyner 
144cb6b8299SEric Joyner 	DEBUGFUNC("ixl_clock_in_i2c_byte");
145cb6b8299SEric Joyner 
146cb6b8299SEric Joyner 	for (i = 7; i >= 0; i--) {
147cb6b8299SEric Joyner 		ixl_clock_in_i2c_bit(pf, &bit);
148cb6b8299SEric Joyner 		*data |= bit << i;
149cb6b8299SEric Joyner 	}
150cb6b8299SEric Joyner 
151cb6b8299SEric Joyner 	return I40E_SUCCESS;
152cb6b8299SEric Joyner }
153cb6b8299SEric Joyner 
154cb6b8299SEric Joyner /**
155cb6b8299SEric Joyner  *  ixl_clock_in_i2c_bit - Clocks in one bit via I2C data/clock
156cb6b8299SEric Joyner  *  @hw: pointer to hardware structure
157cb6b8299SEric Joyner  *  @data: read data value
158cb6b8299SEric Joyner  *
159cb6b8299SEric Joyner  *  Clocks in one bit via I2C data/clock
160cb6b8299SEric Joyner  **/
161cb6b8299SEric Joyner static s32
ixl_clock_in_i2c_bit(struct ixl_pf * pf,bool * data)162cb6b8299SEric Joyner ixl_clock_in_i2c_bit(struct ixl_pf *pf, bool *data)
163cb6b8299SEric Joyner {
164cb6b8299SEric Joyner 	struct i40e_hw *hw = &pf->hw;
165cb6b8299SEric Joyner 	u32 i2cctl = rd32(hw, IXL_I2C_REG(hw));
166cb6b8299SEric Joyner 
167cb6b8299SEric Joyner 	DEBUGFUNC("ixl_clock_in_i2c_bit");
168cb6b8299SEric Joyner 
169cb6b8299SEric Joyner 	ixl_raise_i2c_clk(pf, &i2cctl);
170cb6b8299SEric Joyner 
171cb6b8299SEric Joyner 	/* Minimum high period of clock is 4us */
172cb6b8299SEric Joyner 	i40e_usec_delay(IXL_I2C_T_HIGH);
173cb6b8299SEric Joyner 
174cb6b8299SEric Joyner 	i2cctl = rd32(hw, IXL_I2C_REG(hw));
175cb6b8299SEric Joyner 	i2cctl |= I40E_GLGEN_I2CPARAMS_DATA_OE_N_MASK;
176cb6b8299SEric Joyner 	wr32(hw, IXL_I2C_REG(hw), i2cctl);
177cb6b8299SEric Joyner 	ixl_flush(hw);
178cb6b8299SEric Joyner 
179cb6b8299SEric Joyner 	i2cctl = rd32(hw, IXL_I2C_REG(hw));
180cb6b8299SEric Joyner 	*data = ixl_get_i2c_data(pf, &i2cctl);
181cb6b8299SEric Joyner 
182cb6b8299SEric Joyner 	ixl_lower_i2c_clk(pf, &i2cctl);
183cb6b8299SEric Joyner 
184cb6b8299SEric Joyner 	/* Minimum low period of clock is 4.7 us */
185cb6b8299SEric Joyner 	i40e_usec_delay(IXL_I2C_T_LOW);
186cb6b8299SEric Joyner 
187cb6b8299SEric Joyner 	return I40E_SUCCESS;
188cb6b8299SEric Joyner }
189cb6b8299SEric Joyner 
190cb6b8299SEric Joyner /**
191cb6b8299SEric Joyner  *  ixl_get_i2c_ack - Polls for I2C ACK
192cb6b8299SEric Joyner  *  @hw: pointer to hardware structure
193cb6b8299SEric Joyner  *
194cb6b8299SEric Joyner  *  Clocks in/out one bit via I2C data/clock
195cb6b8299SEric Joyner  **/
196cb6b8299SEric Joyner static s32
ixl_get_i2c_ack(struct ixl_pf * pf)197cb6b8299SEric Joyner ixl_get_i2c_ack(struct ixl_pf *pf)
198cb6b8299SEric Joyner {
199cb6b8299SEric Joyner 	struct i40e_hw *hw = &pf->hw;
200cb6b8299SEric Joyner 	s32 status = I40E_SUCCESS;
201cb6b8299SEric Joyner 	u32 i = 0;
202cb6b8299SEric Joyner 	u32 i2cctl = rd32(hw, IXL_I2C_REG(hw));
203cb6b8299SEric Joyner 	u32 timeout = 10;
204cb6b8299SEric Joyner 	bool ack = 1;
205cb6b8299SEric Joyner 
206cb6b8299SEric Joyner 	ixl_raise_i2c_clk(pf, &i2cctl);
207cb6b8299SEric Joyner 
208cb6b8299SEric Joyner 	/* Minimum high period of clock is 4us */
209cb6b8299SEric Joyner 	i40e_usec_delay(IXL_I2C_T_HIGH);
210cb6b8299SEric Joyner 
211cb6b8299SEric Joyner 	i2cctl = rd32(hw, IXL_I2C_REG(hw));
212cb6b8299SEric Joyner 	i2cctl |= I40E_GLGEN_I2CPARAMS_DATA_OE_N_MASK;
213cb6b8299SEric Joyner 	wr32(hw, IXL_I2C_REG(hw), i2cctl);
214cb6b8299SEric Joyner 	ixl_flush(hw);
215cb6b8299SEric Joyner 
216cb6b8299SEric Joyner 	/* Poll for ACK.  Note that ACK in I2C spec is
217cb6b8299SEric Joyner 	 * transition from 1 to 0 */
218cb6b8299SEric Joyner 	for (i = 0; i < timeout; i++) {
219cb6b8299SEric Joyner 		i2cctl = rd32(hw, IXL_I2C_REG(hw));
220cb6b8299SEric Joyner 		ack = ixl_get_i2c_data(pf, &i2cctl);
221cb6b8299SEric Joyner 
222cb6b8299SEric Joyner 		i40e_usec_delay(1);
223cb6b8299SEric Joyner 		if (!ack)
224cb6b8299SEric Joyner 			break;
225cb6b8299SEric Joyner 	}
226cb6b8299SEric Joyner 
227cb6b8299SEric Joyner 	if (ack) {
228cb6b8299SEric Joyner 		ixl_dbg(pf, IXL_DBG_I2C, "I2C ack was not received.\n");
229cb6b8299SEric Joyner 		status = I40E_ERR_PHY;
230cb6b8299SEric Joyner 	}
231cb6b8299SEric Joyner 
232cb6b8299SEric Joyner 	ixl_lower_i2c_clk(pf, &i2cctl);
233cb6b8299SEric Joyner 
234cb6b8299SEric Joyner 	/* Minimum low period of clock is 4.7 us */
235cb6b8299SEric Joyner 	i40e_usec_delay(IXL_I2C_T_LOW);
236cb6b8299SEric Joyner 
237cb6b8299SEric Joyner 	return status;
238cb6b8299SEric Joyner }
239cb6b8299SEric Joyner 
240cb6b8299SEric Joyner /**
241cb6b8299SEric Joyner  *  ixl_clock_out_i2c_bit - Clocks in/out one bit via I2C data/clock
242cb6b8299SEric Joyner  *  @hw: pointer to hardware structure
243cb6b8299SEric Joyner  *  @data: data value to write
244cb6b8299SEric Joyner  *
245cb6b8299SEric Joyner  *  Clocks out one bit via I2C data/clock
246cb6b8299SEric Joyner  **/
247cb6b8299SEric Joyner static s32
ixl_clock_out_i2c_bit(struct ixl_pf * pf,bool data)248cb6b8299SEric Joyner ixl_clock_out_i2c_bit(struct ixl_pf *pf, bool data)
249cb6b8299SEric Joyner {
250cb6b8299SEric Joyner 	struct i40e_hw *hw = &pf->hw;
251cb6b8299SEric Joyner 	s32 status;
252cb6b8299SEric Joyner 	u32 i2cctl = rd32(hw, IXL_I2C_REG(hw));
253cb6b8299SEric Joyner 
254cb6b8299SEric Joyner 	status = ixl_set_i2c_data(pf, &i2cctl, data);
255cb6b8299SEric Joyner 	if (status == I40E_SUCCESS) {
256cb6b8299SEric Joyner 		ixl_raise_i2c_clk(pf, &i2cctl);
257cb6b8299SEric Joyner 
258cb6b8299SEric Joyner 		/* Minimum high period of clock is 4us */
259cb6b8299SEric Joyner 		i40e_usec_delay(IXL_I2C_T_HIGH);
260cb6b8299SEric Joyner 
261cb6b8299SEric Joyner 		ixl_lower_i2c_clk(pf, &i2cctl);
262cb6b8299SEric Joyner 
263cb6b8299SEric Joyner 		/* Minimum low period of clock is 4.7 us.
264cb6b8299SEric Joyner 		 * This also takes care of the data hold time.
265cb6b8299SEric Joyner 		 */
266cb6b8299SEric Joyner 		i40e_usec_delay(IXL_I2C_T_LOW);
267cb6b8299SEric Joyner 	} else {
268cb6b8299SEric Joyner 		status = I40E_ERR_PHY;
269cb6b8299SEric Joyner 		ixl_dbg(pf, IXL_DBG_I2C, "I2C data was not set to %#x\n", data);
270cb6b8299SEric Joyner 	}
271cb6b8299SEric Joyner 
272cb6b8299SEric Joyner 	return status;
273cb6b8299SEric Joyner }
274cb6b8299SEric Joyner 
275cb6b8299SEric Joyner /**
276cb6b8299SEric Joyner  *  ixl_clock_out_i2c_byte - Clocks out one byte via I2C
277cb6b8299SEric Joyner  *  @hw: pointer to hardware structure
278cb6b8299SEric Joyner  *  @data: data byte clocked out
279cb6b8299SEric Joyner  *
280cb6b8299SEric Joyner  *  Clocks out one byte data via I2C data/clock
281cb6b8299SEric Joyner  **/
282cb6b8299SEric Joyner static s32
ixl_clock_out_i2c_byte(struct ixl_pf * pf,u8 data)283cb6b8299SEric Joyner ixl_clock_out_i2c_byte(struct ixl_pf *pf, u8 data)
284cb6b8299SEric Joyner {
285cb6b8299SEric Joyner 	struct i40e_hw *hw = &pf->hw;
286cb6b8299SEric Joyner 	s32 status = I40E_SUCCESS;
287cb6b8299SEric Joyner 	s32 i;
288cb6b8299SEric Joyner 	u32 i2cctl;
289cb6b8299SEric Joyner 	bool bit;
290cb6b8299SEric Joyner 
291cb6b8299SEric Joyner 	DEBUGFUNC("ixl_clock_out_i2c_byte");
292cb6b8299SEric Joyner 
293cb6b8299SEric Joyner 	for (i = 7; i >= 0; i--) {
294cb6b8299SEric Joyner 		bit = (data >> i) & 0x1;
295cb6b8299SEric Joyner 		status = ixl_clock_out_i2c_bit(pf, bit);
296cb6b8299SEric Joyner 
297cb6b8299SEric Joyner 		if (status != I40E_SUCCESS)
298cb6b8299SEric Joyner 			break;
299cb6b8299SEric Joyner 	}
300cb6b8299SEric Joyner 
301cb6b8299SEric Joyner 	/* Release SDA line (set high) */
302cb6b8299SEric Joyner 	i2cctl = rd32(hw, IXL_I2C_REG(hw));
303cb6b8299SEric Joyner 	i2cctl |= I40E_GLGEN_I2CPARAMS_DATA_OUT_MASK;
304cb6b8299SEric Joyner 	i2cctl &= ~(I40E_GLGEN_I2CPARAMS_DATA_OE_N_MASK);
305cb6b8299SEric Joyner 	wr32(hw, IXL_I2C_REG(hw), i2cctl);
306cb6b8299SEric Joyner 	ixl_flush(hw);
307cb6b8299SEric Joyner 
308cb6b8299SEric Joyner 	return status;
309cb6b8299SEric Joyner }
310cb6b8299SEric Joyner 
311cb6b8299SEric Joyner /**
312cb6b8299SEric Joyner  *  ixl_lower_i2c_clk - Lowers the I2C SCL clock
313cb6b8299SEric Joyner  *  @hw: pointer to hardware structure
314cb6b8299SEric Joyner  *  @i2cctl: Current value of I2CCTL register
315cb6b8299SEric Joyner  *
316cb6b8299SEric Joyner  *  Lowers the I2C clock line '1'->'0'
317cb6b8299SEric Joyner  **/
318cb6b8299SEric Joyner static void
ixl_lower_i2c_clk(struct ixl_pf * pf,u32 * i2cctl)319cb6b8299SEric Joyner ixl_lower_i2c_clk(struct ixl_pf *pf, u32 *i2cctl)
320cb6b8299SEric Joyner {
321cb6b8299SEric Joyner 	struct i40e_hw *hw = &pf->hw;
322cb6b8299SEric Joyner 
323cb6b8299SEric Joyner 	*i2cctl &= ~(I40E_GLGEN_I2CPARAMS_CLK_MASK);
324cb6b8299SEric Joyner 	*i2cctl &= ~(I40E_GLGEN_I2CPARAMS_CLK_OE_N_MASK);
325cb6b8299SEric Joyner 
326cb6b8299SEric Joyner 	wr32(hw, IXL_I2C_REG(hw), *i2cctl);
327cb6b8299SEric Joyner 	ixl_flush(hw);
328cb6b8299SEric Joyner 
329cb6b8299SEric Joyner 	/* SCL fall time (300ns) */
330cb6b8299SEric Joyner 	i40e_usec_delay(IXL_I2C_T_FALL);
331cb6b8299SEric Joyner }
332cb6b8299SEric Joyner 
333cb6b8299SEric Joyner /**
334cb6b8299SEric Joyner  *  ixl_raise_i2c_clk - Raises the I2C SCL clock
335cb6b8299SEric Joyner  *  @hw: pointer to hardware structure
336cb6b8299SEric Joyner  *  @i2cctl: Current value of I2CCTL register
337cb6b8299SEric Joyner  *
338cb6b8299SEric Joyner  *  Raises the I2C clock line '0'->'1'
339cb6b8299SEric Joyner  **/
340cb6b8299SEric Joyner static void
ixl_raise_i2c_clk(struct ixl_pf * pf,u32 * i2cctl)341cb6b8299SEric Joyner ixl_raise_i2c_clk(struct ixl_pf *pf, u32 *i2cctl)
342cb6b8299SEric Joyner {
343cb6b8299SEric Joyner 	struct i40e_hw *hw = &pf->hw;
344cb6b8299SEric Joyner 	u32 i = 0;
345cb6b8299SEric Joyner 	u32 timeout = IXL_I2C_CLOCK_STRETCHING_TIMEOUT;
346cb6b8299SEric Joyner 	u32 i2cctl_r = 0;
347cb6b8299SEric Joyner 
348cb6b8299SEric Joyner 	for (i = 0; i < timeout; i++) {
349cb6b8299SEric Joyner 		*i2cctl |= I40E_GLGEN_I2CPARAMS_CLK_MASK;
350cb6b8299SEric Joyner 		*i2cctl &= ~(I40E_GLGEN_I2CPARAMS_CLK_OE_N_MASK);
351cb6b8299SEric Joyner 
352cb6b8299SEric Joyner 		wr32(hw, IXL_I2C_REG(hw), *i2cctl);
353cb6b8299SEric Joyner 		ixl_flush(hw);
354cb6b8299SEric Joyner 		/* SCL rise time (1000ns) */
355cb6b8299SEric Joyner 		i40e_usec_delay(IXL_I2C_T_RISE);
356cb6b8299SEric Joyner 
357cb6b8299SEric Joyner 		i2cctl_r = rd32(hw, IXL_I2C_REG(hw));
358cb6b8299SEric Joyner 		if (i2cctl_r & I40E_GLGEN_I2CPARAMS_CLK_IN_MASK)
359cb6b8299SEric Joyner 			break;
360cb6b8299SEric Joyner 	}
361cb6b8299SEric Joyner }
362cb6b8299SEric Joyner 
363cb6b8299SEric Joyner /**
364cb6b8299SEric Joyner  *  ixl_get_i2c_data - Reads the I2C SDA data bit
365cb6b8299SEric Joyner  *  @hw: pointer to hardware structure
366cb6b8299SEric Joyner  *  @i2cctl: Current value of I2CCTL register
367cb6b8299SEric Joyner  *
368cb6b8299SEric Joyner  *  Returns the I2C data bit value
369cb6b8299SEric Joyner  **/
370cb6b8299SEric Joyner static bool
ixl_get_i2c_data(struct ixl_pf * pf,u32 * i2cctl)371cb6b8299SEric Joyner ixl_get_i2c_data(struct ixl_pf *pf, u32 *i2cctl)
372cb6b8299SEric Joyner {
373cb6b8299SEric Joyner 	bool data;
374cb6b8299SEric Joyner 
375cb6b8299SEric Joyner 	if (*i2cctl & I40E_GLGEN_I2CPARAMS_DATA_IN_MASK)
376cb6b8299SEric Joyner 		data = 1;
377cb6b8299SEric Joyner 	else
378cb6b8299SEric Joyner 		data = 0;
379cb6b8299SEric Joyner 
380cb6b8299SEric Joyner 	return data;
381cb6b8299SEric Joyner }
382cb6b8299SEric Joyner 
383cb6b8299SEric Joyner /**
384cb6b8299SEric Joyner  *  ixl_set_i2c_data - Sets the I2C data bit
385cb6b8299SEric Joyner  *  @hw: pointer to hardware structure
386cb6b8299SEric Joyner  *  @i2cctl: Current value of I2CCTL register
387cb6b8299SEric Joyner  *  @data: I2C data value (0 or 1) to set
388cb6b8299SEric Joyner  *
389cb6b8299SEric Joyner  *  Sets the I2C data bit
390cb6b8299SEric Joyner  **/
391cb6b8299SEric Joyner static s32
ixl_set_i2c_data(struct ixl_pf * pf,u32 * i2cctl,bool data)392cb6b8299SEric Joyner ixl_set_i2c_data(struct ixl_pf *pf, u32 *i2cctl, bool data)
393cb6b8299SEric Joyner {
394cb6b8299SEric Joyner 	struct i40e_hw *hw = &pf->hw;
395cb6b8299SEric Joyner 	s32 status = I40E_SUCCESS;
396cb6b8299SEric Joyner 
397cb6b8299SEric Joyner 	DEBUGFUNC("ixl_set_i2c_data");
398cb6b8299SEric Joyner 
399cb6b8299SEric Joyner 	if (data)
400cb6b8299SEric Joyner 		*i2cctl |= I40E_GLGEN_I2CPARAMS_DATA_OUT_MASK;
401cb6b8299SEric Joyner 	else
402cb6b8299SEric Joyner 		*i2cctl &= ~(I40E_GLGEN_I2CPARAMS_DATA_OUT_MASK);
403cb6b8299SEric Joyner 	*i2cctl &= ~(I40E_GLGEN_I2CPARAMS_DATA_OE_N_MASK);
404cb6b8299SEric Joyner 
405cb6b8299SEric Joyner 	wr32(hw, IXL_I2C_REG(hw), *i2cctl);
406cb6b8299SEric Joyner 	ixl_flush(hw);
407cb6b8299SEric Joyner 
408cb6b8299SEric Joyner 	/* Data rise/fall (1000ns/300ns) and set-up time (250ns) */
409cb6b8299SEric Joyner 	i40e_usec_delay(IXL_I2C_T_RISE + IXL_I2C_T_FALL + IXL_I2C_T_SU_DATA);
410cb6b8299SEric Joyner 
411cb6b8299SEric Joyner 	/* Verify data was set correctly */
412cb6b8299SEric Joyner 	*i2cctl = rd32(hw, IXL_I2C_REG(hw));
413cb6b8299SEric Joyner 	if (data != ixl_get_i2c_data(pf, i2cctl)) {
414cb6b8299SEric Joyner 		status = I40E_ERR_PHY;
415cb6b8299SEric Joyner 		ixl_dbg(pf, IXL_DBG_I2C, "Error - I2C data was not set to %X.\n", data);
416cb6b8299SEric Joyner 	}
417cb6b8299SEric Joyner 
418cb6b8299SEric Joyner 	return status;
419cb6b8299SEric Joyner }
420cb6b8299SEric Joyner 
421cb6b8299SEric Joyner /**
422cb6b8299SEric Joyner  *  ixl_i2c_start - Sets I2C start condition
423cb6b8299SEric Joyner  *  Sets I2C start condition (High -> Low on SDA while SCL is High)
424cb6b8299SEric Joyner  **/
425cb6b8299SEric Joyner static void
ixl_i2c_start(struct ixl_pf * pf)426cb6b8299SEric Joyner ixl_i2c_start(struct ixl_pf *pf)
427cb6b8299SEric Joyner {
428cb6b8299SEric Joyner 	struct i40e_hw *hw = &pf->hw;
429cb6b8299SEric Joyner 	u32 i2cctl = rd32(hw, IXL_I2C_REG(hw));
430cb6b8299SEric Joyner 
431cb6b8299SEric Joyner 	DEBUGFUNC("ixl_i2c_start");
432cb6b8299SEric Joyner 
433cb6b8299SEric Joyner 	/* Start condition must begin with data and clock high */
434cb6b8299SEric Joyner 	ixl_set_i2c_data(pf, &i2cctl, 1);
435cb6b8299SEric Joyner 	ixl_raise_i2c_clk(pf, &i2cctl);
436cb6b8299SEric Joyner 
437cb6b8299SEric Joyner 	/* Setup time for start condition (4.7us) */
438cb6b8299SEric Joyner 	i40e_usec_delay(IXL_I2C_T_SU_STA);
439cb6b8299SEric Joyner 
440cb6b8299SEric Joyner 	ixl_set_i2c_data(pf, &i2cctl, 0);
441cb6b8299SEric Joyner 
442cb6b8299SEric Joyner 	/* Hold time for start condition (4us) */
443cb6b8299SEric Joyner 	i40e_usec_delay(IXL_I2C_T_HD_STA);
444cb6b8299SEric Joyner 
445cb6b8299SEric Joyner 	ixl_lower_i2c_clk(pf, &i2cctl);
446cb6b8299SEric Joyner 
447cb6b8299SEric Joyner 	/* Minimum low period of clock is 4.7 us */
448cb6b8299SEric Joyner 	i40e_usec_delay(IXL_I2C_T_LOW);
449cb6b8299SEric Joyner 
450cb6b8299SEric Joyner }
451cb6b8299SEric Joyner 
452cb6b8299SEric Joyner /**
4531031d839SEric Joyner  *  ixl_read_i2c_byte_bb - Reads 8 bit word over I2C
454cb6b8299SEric Joyner  **/
455cb6b8299SEric Joyner s32
ixl_read_i2c_byte_bb(struct ixl_pf * pf,u8 byte_offset,u8 dev_addr,u8 * data)4561031d839SEric Joyner ixl_read_i2c_byte_bb(struct ixl_pf *pf, u8 byte_offset,
457cb6b8299SEric Joyner 		  u8 dev_addr, u8 *data)
458cb6b8299SEric Joyner {
459cb6b8299SEric Joyner 	struct i40e_hw *hw = &pf->hw;
460cb6b8299SEric Joyner 	u32 max_retry = 10;
461cb6b8299SEric Joyner 	u32 retry = 0;
462cb6b8299SEric Joyner 	bool nack = 1;
463cb6b8299SEric Joyner 	s32 status;
464cb6b8299SEric Joyner 	*data = 0;
465cb6b8299SEric Joyner 
466cb6b8299SEric Joyner 	u32 i2cctl = rd32(hw, IXL_I2C_REG(hw));
467cb6b8299SEric Joyner 	i2cctl |= I40E_GLGEN_I2CPARAMS_I2CBB_EN_MASK;
468cb6b8299SEric Joyner 	wr32(hw, IXL_I2C_REG(hw), i2cctl);
469cb6b8299SEric Joyner 	ixl_flush(hw);
470cb6b8299SEric Joyner 
471cb6b8299SEric Joyner 	do {
472cb6b8299SEric Joyner 		ixl_i2c_start(pf);
473cb6b8299SEric Joyner 
474cb6b8299SEric Joyner 		/* Device Address and write indication */
475cb6b8299SEric Joyner 		status = ixl_clock_out_i2c_byte(pf, dev_addr);
476cb6b8299SEric Joyner 		if (status != I40E_SUCCESS) {
477cb6b8299SEric Joyner 			ixl_dbg(pf, IXL_DBG_I2C, "dev_addr clock out error\n");
478cb6b8299SEric Joyner 			goto fail;
479cb6b8299SEric Joyner 		}
480cb6b8299SEric Joyner 
481cb6b8299SEric Joyner 		status = ixl_get_i2c_ack(pf);
482cb6b8299SEric Joyner 		if (status != I40E_SUCCESS) {
483cb6b8299SEric Joyner 			ixl_dbg(pf, IXL_DBG_I2C, "dev_addr i2c ack error\n");
484cb6b8299SEric Joyner 			goto fail;
485cb6b8299SEric Joyner 		}
486cb6b8299SEric Joyner 
487cb6b8299SEric Joyner 		status = ixl_clock_out_i2c_byte(pf, byte_offset);
488cb6b8299SEric Joyner 		if (status != I40E_SUCCESS) {
489cb6b8299SEric Joyner 			ixl_dbg(pf, IXL_DBG_I2C, "byte_offset clock out error\n");
490cb6b8299SEric Joyner 			goto fail;
491cb6b8299SEric Joyner 		}
492cb6b8299SEric Joyner 
493cb6b8299SEric Joyner 		status = ixl_get_i2c_ack(pf);
494cb6b8299SEric Joyner 		if (status != I40E_SUCCESS) {
495cb6b8299SEric Joyner 			ixl_dbg(pf, IXL_DBG_I2C, "byte_offset i2c ack error\n");
496cb6b8299SEric Joyner 			goto fail;
497cb6b8299SEric Joyner 		}
498cb6b8299SEric Joyner 
499cb6b8299SEric Joyner 		ixl_i2c_start(pf);
500cb6b8299SEric Joyner 
501cb6b8299SEric Joyner 		/* Device Address and read indication */
502cb6b8299SEric Joyner 		status = ixl_clock_out_i2c_byte(pf, (dev_addr | 0x1));
503cb6b8299SEric Joyner 		if (status != I40E_SUCCESS)
504cb6b8299SEric Joyner 			goto fail;
505cb6b8299SEric Joyner 
506cb6b8299SEric Joyner 		status = ixl_get_i2c_ack(pf);
507cb6b8299SEric Joyner 		if (status != I40E_SUCCESS)
508cb6b8299SEric Joyner 			goto fail;
509cb6b8299SEric Joyner 
510cb6b8299SEric Joyner 		status = ixl_clock_in_i2c_byte(pf, data);
511cb6b8299SEric Joyner 		if (status != I40E_SUCCESS)
512cb6b8299SEric Joyner 			goto fail;
513cb6b8299SEric Joyner 
514cb6b8299SEric Joyner 		status = ixl_clock_out_i2c_bit(pf, nack);
515cb6b8299SEric Joyner 		if (status != I40E_SUCCESS)
516cb6b8299SEric Joyner 			goto fail;
517cb6b8299SEric Joyner 
518cb6b8299SEric Joyner 		ixl_i2c_stop(pf);
519cb6b8299SEric Joyner 		status = I40E_SUCCESS;
520cb6b8299SEric Joyner 		goto done;
521cb6b8299SEric Joyner 
522cb6b8299SEric Joyner fail:
523cb6b8299SEric Joyner 		ixl_i2c_bus_clear(pf);
524cb6b8299SEric Joyner 		i40e_msec_delay(100);
525cb6b8299SEric Joyner 		retry++;
526cb6b8299SEric Joyner 		if (retry < max_retry)
5271031d839SEric Joyner 			ixl_dbg(pf, IXL_DBG_I2C, "I2C byte read error - Retrying\n");
528cb6b8299SEric Joyner 		else
5291031d839SEric Joyner 			ixl_dbg(pf, IXL_DBG_I2C, "I2C byte read error\n");
530cb6b8299SEric Joyner 
531cb6b8299SEric Joyner 	} while (retry < max_retry);
532cb6b8299SEric Joyner done:
533cb6b8299SEric Joyner 	i2cctl = rd32(hw, IXL_I2C_REG(hw));
534cb6b8299SEric Joyner 	i2cctl &= ~I40E_GLGEN_I2CPARAMS_I2CBB_EN_MASK;
535cb6b8299SEric Joyner 	wr32(hw, IXL_I2C_REG(hw), i2cctl);
536cb6b8299SEric Joyner 	ixl_flush(hw);
537cb6b8299SEric Joyner 
538cb6b8299SEric Joyner 	return status;
539cb6b8299SEric Joyner }
540cb6b8299SEric Joyner 
541cb6b8299SEric Joyner /**
5421031d839SEric Joyner  *  ixl_write_i2c_byte_bb - Writes 8 bit word over I2C
543cb6b8299SEric Joyner  **/
544cb6b8299SEric Joyner s32
ixl_write_i2c_byte_bb(struct ixl_pf * pf,u8 byte_offset,u8 dev_addr,u8 data)5451031d839SEric Joyner ixl_write_i2c_byte_bb(struct ixl_pf *pf, u8 byte_offset,
546cb6b8299SEric Joyner 		       u8 dev_addr, u8 data)
547cb6b8299SEric Joyner {
548cb6b8299SEric Joyner 	struct i40e_hw *hw = &pf->hw;
549cb6b8299SEric Joyner 	s32 status = I40E_SUCCESS;
550cb6b8299SEric Joyner 	u32 max_retry = 1;
551cb6b8299SEric Joyner 	u32 retry = 0;
552cb6b8299SEric Joyner 
553cb6b8299SEric Joyner 	u32 i2cctl = rd32(hw, IXL_I2C_REG(hw));
554cb6b8299SEric Joyner 	i2cctl |= I40E_GLGEN_I2CPARAMS_I2CBB_EN_MASK;
555cb6b8299SEric Joyner 	wr32(hw, IXL_I2C_REG(hw), i2cctl);
556cb6b8299SEric Joyner 	ixl_flush(hw);
557cb6b8299SEric Joyner 
558cb6b8299SEric Joyner 	do {
559cb6b8299SEric Joyner 		ixl_i2c_start(pf);
560cb6b8299SEric Joyner 
561cb6b8299SEric Joyner 		status = ixl_clock_out_i2c_byte(pf, dev_addr);
562cb6b8299SEric Joyner 		if (status != I40E_SUCCESS)
563cb6b8299SEric Joyner 			goto fail;
564cb6b8299SEric Joyner 
565cb6b8299SEric Joyner 		status = ixl_get_i2c_ack(pf);
566cb6b8299SEric Joyner 		if (status != I40E_SUCCESS)
567cb6b8299SEric Joyner 			goto fail;
568cb6b8299SEric Joyner 
569cb6b8299SEric Joyner 		status = ixl_clock_out_i2c_byte(pf, byte_offset);
570cb6b8299SEric Joyner 		if (status != I40E_SUCCESS)
571cb6b8299SEric Joyner 			goto fail;
572cb6b8299SEric Joyner 
573cb6b8299SEric Joyner 		status = ixl_get_i2c_ack(pf);
574cb6b8299SEric Joyner 		if (status != I40E_SUCCESS)
575cb6b8299SEric Joyner 			goto fail;
576cb6b8299SEric Joyner 
577cb6b8299SEric Joyner 		status = ixl_clock_out_i2c_byte(pf, data);
578cb6b8299SEric Joyner 		if (status != I40E_SUCCESS)
579cb6b8299SEric Joyner 			goto fail;
580cb6b8299SEric Joyner 
581cb6b8299SEric Joyner 		status = ixl_get_i2c_ack(pf);
582cb6b8299SEric Joyner 		if (status != I40E_SUCCESS)
583cb6b8299SEric Joyner 			goto fail;
584cb6b8299SEric Joyner 
585cb6b8299SEric Joyner 		ixl_i2c_stop(pf);
586cb6b8299SEric Joyner 		goto write_byte_out;
587cb6b8299SEric Joyner 
588cb6b8299SEric Joyner fail:
589cb6b8299SEric Joyner 		ixl_i2c_bus_clear(pf);
590cb6b8299SEric Joyner 		i40e_msec_delay(100);
591cb6b8299SEric Joyner 		retry++;
592cb6b8299SEric Joyner 		if (retry < max_retry)
5931031d839SEric Joyner 			ixl_dbg(pf, IXL_DBG_I2C, "I2C byte write error - Retrying\n");
594cb6b8299SEric Joyner 		else
5951031d839SEric Joyner 			ixl_dbg(pf, IXL_DBG_I2C, "I2C byte write error\n");
596cb6b8299SEric Joyner 	} while (retry < max_retry);
597cb6b8299SEric Joyner 
598cb6b8299SEric Joyner write_byte_out:
599cb6b8299SEric Joyner 	i2cctl = rd32(hw, IXL_I2C_REG(hw));
600cb6b8299SEric Joyner 	i2cctl &= ~I40E_GLGEN_I2CPARAMS_I2CBB_EN_MASK;
601cb6b8299SEric Joyner 	wr32(hw, IXL_I2C_REG(hw), i2cctl);
602cb6b8299SEric Joyner 	ixl_flush(hw);
603cb6b8299SEric Joyner 
604cb6b8299SEric Joyner 	return status;
605cb6b8299SEric Joyner }
606cb6b8299SEric Joyner 
6071031d839SEric Joyner /**
608b4a7ce06SEric Joyner  *  ixl_read_i2c_byte_reg - Reads 8 bit word over I2C using a hardware register
6091031d839SEric Joyner  **/
6101031d839SEric Joyner s32
ixl_read_i2c_byte_reg(struct ixl_pf * pf,u8 byte_offset,u8 dev_addr,u8 * data)6111031d839SEric Joyner ixl_read_i2c_byte_reg(struct ixl_pf *pf, u8 byte_offset,
6121031d839SEric Joyner 		  u8 dev_addr, u8 *data)
6131031d839SEric Joyner {
6141031d839SEric Joyner 	struct i40e_hw *hw = &pf->hw;
6151031d839SEric Joyner 	u32 reg = 0;
6161031d839SEric Joyner 	s32 status;
6171031d839SEric Joyner 	*data = 0;
6181031d839SEric Joyner 
6191031d839SEric Joyner 	reg |= (byte_offset << I40E_GLGEN_I2CCMD_REGADD_SHIFT);
6201031d839SEric Joyner 	reg |= (((dev_addr >> 1) & 0x7) << I40E_GLGEN_I2CCMD_PHYADD_SHIFT);
6211031d839SEric Joyner 	reg |= I40E_GLGEN_I2CCMD_OP_MASK;
6221031d839SEric Joyner 	wr32(hw, I40E_GLGEN_I2CCMD(hw->func_caps.mdio_port_num), reg);
6231031d839SEric Joyner 
6241031d839SEric Joyner 	status = ixl_wait_for_i2c_completion(hw, hw->func_caps.mdio_port_num);
6251031d839SEric Joyner 
6261031d839SEric Joyner 	/* Get data from I2C register */
6271031d839SEric Joyner 	reg = rd32(hw, I40E_GLGEN_I2CCMD(hw->func_caps.mdio_port_num));
6281031d839SEric Joyner 
629b4a7ce06SEric Joyner 	/* Retrieve data read from EEPROM */
6301031d839SEric Joyner 	*data = (u8)(reg & 0xff);
6311031d839SEric Joyner 
6321031d839SEric Joyner 	if (status)
6331031d839SEric Joyner 		ixl_dbg(pf, IXL_DBG_I2C, "I2C byte read error\n");
6341031d839SEric Joyner 	return status;
6351031d839SEric Joyner }
6361031d839SEric Joyner 
6371031d839SEric Joyner /**
638b4a7ce06SEric Joyner  *  ixl_write_i2c_byte_reg - Writes 8 bit word over I2C using a hardware register
6391031d839SEric Joyner  **/
6401031d839SEric Joyner s32
ixl_write_i2c_byte_reg(struct ixl_pf * pf,u8 byte_offset,u8 dev_addr,u8 data)6411031d839SEric Joyner ixl_write_i2c_byte_reg(struct ixl_pf *pf, u8 byte_offset,
6421031d839SEric Joyner 		       u8 dev_addr, u8 data)
6431031d839SEric Joyner {
6441031d839SEric Joyner 	struct i40e_hw *hw = &pf->hw;
6451031d839SEric Joyner 	s32 status = I40E_SUCCESS;
6461031d839SEric Joyner 	u32 reg = 0;
6471031d839SEric Joyner 	u8 upperbyte = 0;
6481031d839SEric Joyner 	u16 datai2c = 0;
6491031d839SEric Joyner 
6501031d839SEric Joyner 	status = ixl_read_i2c_byte_reg(pf, byte_offset + 1, dev_addr, &upperbyte);
6511031d839SEric Joyner 	datai2c = ((u16)upperbyte << 8) | (u16)data;
6521031d839SEric Joyner 	reg = rd32(hw, I40E_GLGEN_I2CCMD(hw->func_caps.mdio_port_num));
6531031d839SEric Joyner 
6541031d839SEric Joyner 	/* Form write command */
6551031d839SEric Joyner 	reg &= ~I40E_GLGEN_I2CCMD_PHYADD_MASK;
6561031d839SEric Joyner 	reg |= (((dev_addr >> 1) & 0x7) << I40E_GLGEN_I2CCMD_PHYADD_SHIFT);
6571031d839SEric Joyner 	reg &= ~I40E_GLGEN_I2CCMD_REGADD_MASK;
6581031d839SEric Joyner 	reg |= (byte_offset << I40E_GLGEN_I2CCMD_REGADD_SHIFT);
6591031d839SEric Joyner 	reg &= ~I40E_GLGEN_I2CCMD_DATA_MASK;
6601031d839SEric Joyner 	reg |= (datai2c << I40E_GLGEN_I2CCMD_DATA_SHIFT);
6611031d839SEric Joyner 	reg &= ~I40E_GLGEN_I2CCMD_OP_MASK;
6621031d839SEric Joyner 
663*5666643aSGordon Bergling 	/* Write command to registers controlling I2C - data and address. */
6641031d839SEric Joyner 	wr32(hw, I40E_GLGEN_I2CCMD(hw->func_caps.mdio_port_num), reg);
6651031d839SEric Joyner 
6661031d839SEric Joyner 	status = ixl_wait_for_i2c_completion(hw, hw->func_caps.mdio_port_num);
6671031d839SEric Joyner 
6681031d839SEric Joyner 	if (status)
6691031d839SEric Joyner 		ixl_dbg(pf, IXL_DBG_I2C, "I2C byte write error\n");
6701031d839SEric Joyner 	return status;
6711031d839SEric Joyner }
6721031d839SEric Joyner 
6731031d839SEric Joyner /**
6741031d839SEric Joyner  *  ixl_wait_for_i2c_completion
6751031d839SEric Joyner  **/
6761031d839SEric Joyner static s32
ixl_wait_for_i2c_completion(struct i40e_hw * hw,u8 portnum)6771031d839SEric Joyner ixl_wait_for_i2c_completion(struct i40e_hw *hw, u8 portnum)
6781031d839SEric Joyner {
6791031d839SEric Joyner 	s32 status = 0;
6801031d839SEric Joyner 	u32 timeout = 100;
6811031d839SEric Joyner 	u32 reg;
6821031d839SEric Joyner 	do {
6831031d839SEric Joyner 		reg = rd32(hw, I40E_GLGEN_I2CCMD(portnum));
6841031d839SEric Joyner 		if ((reg & I40E_GLGEN_I2CCMD_R_MASK) != 0)
6851031d839SEric Joyner 			break;
6861031d839SEric Joyner 		i40e_usec_delay(10);
6871031d839SEric Joyner 	} while (timeout-- > 0);
6881031d839SEric Joyner 
6891031d839SEric Joyner 	if (timeout == 0)
6901031d839SEric Joyner 		return I40E_ERR_TIMEOUT;
6911031d839SEric Joyner 	else
6921031d839SEric Joyner 		return status;
6931031d839SEric Joyner }
6941031d839SEric Joyner 
6951031d839SEric Joyner /**
696b4a7ce06SEric Joyner  *  ixl_read_i2c_byte_aq - Reads 8 bit word over I2C using an AQ command
6971031d839SEric Joyner  **/
6981031d839SEric Joyner s32
ixl_read_i2c_byte_aq(struct ixl_pf * pf,u8 byte_offset,u8 dev_addr,u8 * data)6991031d839SEric Joyner ixl_read_i2c_byte_aq(struct ixl_pf *pf, u8 byte_offset,
7001031d839SEric Joyner 		  u8 dev_addr, u8 *data)
7011031d839SEric Joyner {
7021031d839SEric Joyner 	struct i40e_hw *hw = &pf->hw;
7031031d839SEric Joyner 	s32 status = I40E_SUCCESS;
7041031d839SEric Joyner 	u32 reg;
7051031d839SEric Joyner 
7061031d839SEric Joyner 	status = i40e_aq_get_phy_register(hw,
7071031d839SEric Joyner 					I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE,
708b4a7ce06SEric Joyner 					dev_addr, false,
7091031d839SEric Joyner 					byte_offset,
7101031d839SEric Joyner 					&reg, NULL);
7111031d839SEric Joyner 
7121031d839SEric Joyner 	if (status)
7131031d839SEric Joyner 		ixl_dbg(pf, IXL_DBG_I2C, "I2C byte read status %s, error %s\n",
7141031d839SEric Joyner 		    i40e_stat_str(hw, status), i40e_aq_str(hw, hw->aq.asq_last_status));
7151031d839SEric Joyner 	else
7161031d839SEric Joyner 		*data = (u8)reg;
7171031d839SEric Joyner 
7181031d839SEric Joyner 	return status;
7191031d839SEric Joyner }
7201031d839SEric Joyner 
7211031d839SEric Joyner /**
722b4a7ce06SEric Joyner  *  ixl_write_i2c_byte_aq - Writes 8 bit word over I2C using an AQ command
7231031d839SEric Joyner  **/
7241031d839SEric Joyner s32
ixl_write_i2c_byte_aq(struct ixl_pf * pf,u8 byte_offset,u8 dev_addr,u8 data)7251031d839SEric Joyner ixl_write_i2c_byte_aq(struct ixl_pf *pf, u8 byte_offset,
7261031d839SEric Joyner 		       u8 dev_addr, u8 data)
7271031d839SEric Joyner {
7281031d839SEric Joyner 	struct i40e_hw *hw = &pf->hw;
7291031d839SEric Joyner 	s32 status = I40E_SUCCESS;
7301031d839SEric Joyner 
7311031d839SEric Joyner 	status = i40e_aq_set_phy_register(hw,
7321031d839SEric Joyner 					I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE,
733b4a7ce06SEric Joyner 					dev_addr, false,
7341031d839SEric Joyner 					byte_offset,
7351031d839SEric Joyner 					data, NULL);
7361031d839SEric Joyner 
7371031d839SEric Joyner 	if (status)
7381031d839SEric Joyner 		ixl_dbg(pf, IXL_DBG_I2C, "I2C byte write status %s, error %s\n",
7391031d839SEric Joyner 		    i40e_stat_str(hw, status), i40e_aq_str(hw, hw->aq.asq_last_status));
7401031d839SEric Joyner 
7411031d839SEric Joyner 	return status;
7421031d839SEric Joyner }
743