xref: /freebsd/sys/dev/ixl/ixl_pf_i2c.c (revision 1031d839aa127290f6ef6e11d16472bf268616d4)
1cb6b8299SEric Joyner /******************************************************************************
2cb6b8299SEric Joyner 
3ceebc2f3SEric Joyner   Copyright (c) 2013-2017, 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 /*$FreeBSD$*/
34cb6b8299SEric Joyner 
35cb6b8299SEric Joyner #include "ixl_pf.h"
36cb6b8299SEric Joyner 
37cb6b8299SEric Joyner #define IXL_I2C_T_RISE		1
38cb6b8299SEric Joyner #define IXL_I2C_T_FALL		1
39cb6b8299SEric Joyner #define IXL_I2C_T_SU_DATA	1
40cb6b8299SEric Joyner #define IXL_I2C_T_SU_STA	5
41cb6b8299SEric Joyner #define IXL_I2C_T_SU_STO	4
42cb6b8299SEric Joyner #define IXL_I2C_T_HD_STA	4
43cb6b8299SEric Joyner #define IXL_I2C_T_LOW		5
44cb6b8299SEric Joyner #define IXL_I2C_T_HIGH		4
45cb6b8299SEric Joyner #define IXL_I2C_T_BUF		5
46cb6b8299SEric Joyner #define IXL_I2C_CLOCK_STRETCHING_TIMEOUT 500
47cb6b8299SEric Joyner 
48cb6b8299SEric Joyner #define IXL_I2C_REG(_hw)	\
49*1031d839SEric Joyner     I40E_GLGEN_I2CPARAMS(_hw->func_caps.mdio_port_num)
50cb6b8299SEric Joyner 
51*1031d839SEric Joyner /* I2C bit-banging functions */
52cb6b8299SEric Joyner static s32	ixl_set_i2c_data(struct ixl_pf *pf, u32 *i2cctl, bool data);
53cb6b8299SEric Joyner static bool	ixl_get_i2c_data(struct ixl_pf *pf, u32 *i2cctl);
54cb6b8299SEric Joyner static void	ixl_raise_i2c_clk(struct ixl_pf *pf, u32 *i2cctl);
55cb6b8299SEric Joyner static void	ixl_lower_i2c_clk(struct ixl_pf *pf, u32 *i2cctl);
56cb6b8299SEric Joyner static s32	ixl_clock_out_i2c_bit(struct ixl_pf *pf, bool data);
57cb6b8299SEric Joyner static s32	ixl_get_i2c_ack(struct ixl_pf *pf);
58cb6b8299SEric Joyner static s32	ixl_clock_out_i2c_byte(struct ixl_pf *pf, u8 data);
59cb6b8299SEric Joyner static s32	ixl_clock_in_i2c_bit(struct ixl_pf *pf, bool *data);
60cb6b8299SEric Joyner static s32	ixl_clock_in_i2c_byte(struct ixl_pf *pf, u8 *data);
61cb6b8299SEric Joyner static void 	ixl_i2c_bus_clear(struct ixl_pf *pf);
62cb6b8299SEric Joyner static void	ixl_i2c_start(struct ixl_pf *pf);
63cb6b8299SEric Joyner static void	ixl_i2c_stop(struct ixl_pf *pf);
64cb6b8299SEric Joyner 
65*1031d839SEric Joyner static s32	ixl_wait_for_i2c_completion(struct i40e_hw *hw, u8 portnum);
66*1031d839SEric Joyner 
67cb6b8299SEric Joyner /**
68cb6b8299SEric Joyner  *  ixl_i2c_bus_clear - Clears the I2C bus
69cb6b8299SEric Joyner  *  @hw: pointer to hardware structure
70cb6b8299SEric Joyner  *
71cb6b8299SEric Joyner  *  Clears the I2C bus by sending nine clock pulses.
72cb6b8299SEric Joyner  *  Used when data line is stuck low.
73cb6b8299SEric Joyner  **/
74cb6b8299SEric Joyner static void
75cb6b8299SEric Joyner ixl_i2c_bus_clear(struct ixl_pf *pf)
76cb6b8299SEric Joyner {
77cb6b8299SEric Joyner 	struct i40e_hw *hw = &pf->hw;
78cb6b8299SEric Joyner 	u32 i2cctl = rd32(hw, IXL_I2C_REG(hw));
79cb6b8299SEric Joyner 	u32 i;
80cb6b8299SEric Joyner 
81cb6b8299SEric Joyner 	DEBUGFUNC("ixl_i2c_bus_clear");
82cb6b8299SEric Joyner 
83cb6b8299SEric Joyner 	ixl_i2c_start(pf);
84cb6b8299SEric Joyner 
85cb6b8299SEric Joyner 	ixl_set_i2c_data(pf, &i2cctl, 1);
86cb6b8299SEric Joyner 
87cb6b8299SEric Joyner 	for (i = 0; i < 9; i++) {
88cb6b8299SEric Joyner 		ixl_raise_i2c_clk(pf, &i2cctl);
89cb6b8299SEric Joyner 
90cb6b8299SEric Joyner 		/* Min high period of clock is 4us */
91cb6b8299SEric Joyner 		i40e_usec_delay(IXL_I2C_T_HIGH);
92cb6b8299SEric Joyner 
93cb6b8299SEric Joyner 		ixl_lower_i2c_clk(pf, &i2cctl);
94cb6b8299SEric Joyner 
95cb6b8299SEric Joyner 		/* Min low period of clock is 4.7us*/
96cb6b8299SEric Joyner 		i40e_usec_delay(IXL_I2C_T_LOW);
97cb6b8299SEric Joyner 	}
98cb6b8299SEric Joyner 
99cb6b8299SEric Joyner 	ixl_i2c_start(pf);
100cb6b8299SEric Joyner 
101cb6b8299SEric Joyner 	/* Put the i2c bus back to default state */
102cb6b8299SEric Joyner 	ixl_i2c_stop(pf);
103cb6b8299SEric Joyner }
104cb6b8299SEric Joyner 
105cb6b8299SEric Joyner /**
106cb6b8299SEric Joyner  *  ixl_i2c_stop - Sets I2C stop condition
107cb6b8299SEric Joyner  *  @hw: pointer to hardware structure
108cb6b8299SEric Joyner  *
109cb6b8299SEric Joyner  *  Sets I2C stop condition (Low -> High on SDA while SCL is High)
110cb6b8299SEric Joyner  **/
111cb6b8299SEric Joyner static void
112cb6b8299SEric Joyner ixl_i2c_stop(struct ixl_pf *pf)
113cb6b8299SEric Joyner {
114cb6b8299SEric Joyner 	struct i40e_hw *hw = &pf->hw;
115cb6b8299SEric Joyner 	u32 i2cctl = rd32(hw, IXL_I2C_REG(hw));
116cb6b8299SEric Joyner 
117cb6b8299SEric Joyner 	DEBUGFUNC("ixl_i2c_stop");
118cb6b8299SEric Joyner 
119cb6b8299SEric Joyner 	/* Stop condition must begin with data low and clock high */
120cb6b8299SEric Joyner 	ixl_set_i2c_data(pf, &i2cctl, 0);
121cb6b8299SEric Joyner 	ixl_raise_i2c_clk(pf, &i2cctl);
122cb6b8299SEric Joyner 
123cb6b8299SEric Joyner 	/* Setup time for stop condition (4us) */
124cb6b8299SEric Joyner 	i40e_usec_delay(IXL_I2C_T_SU_STO);
125cb6b8299SEric Joyner 
126cb6b8299SEric Joyner 	ixl_set_i2c_data(pf, &i2cctl, 1);
127cb6b8299SEric Joyner 
128cb6b8299SEric Joyner 	/* bus free time between stop and start (4.7us)*/
129cb6b8299SEric Joyner 	i40e_usec_delay(IXL_I2C_T_BUF);
130cb6b8299SEric Joyner }
131cb6b8299SEric Joyner 
132cb6b8299SEric Joyner /**
133cb6b8299SEric Joyner  *  ixl_clock_in_i2c_byte - Clocks in one byte via I2C
134cb6b8299SEric Joyner  *  @hw: pointer to hardware structure
135cb6b8299SEric Joyner  *  @data: data byte to clock in
136cb6b8299SEric Joyner  *
137cb6b8299SEric Joyner  *  Clocks in one byte data via I2C data/clock
138cb6b8299SEric Joyner  **/
139cb6b8299SEric Joyner static s32
140cb6b8299SEric Joyner ixl_clock_in_i2c_byte(struct ixl_pf *pf, u8 *data)
141cb6b8299SEric Joyner {
142cb6b8299SEric Joyner 	s32 i;
143cb6b8299SEric Joyner 	bool bit = 0;
144cb6b8299SEric Joyner 
145cb6b8299SEric Joyner 	DEBUGFUNC("ixl_clock_in_i2c_byte");
146cb6b8299SEric Joyner 
147cb6b8299SEric Joyner 	for (i = 7; i >= 0; i--) {
148cb6b8299SEric Joyner 		ixl_clock_in_i2c_bit(pf, &bit);
149cb6b8299SEric Joyner 		*data |= bit << i;
150cb6b8299SEric Joyner 	}
151cb6b8299SEric Joyner 
152cb6b8299SEric Joyner 	return I40E_SUCCESS;
153cb6b8299SEric Joyner }
154cb6b8299SEric Joyner 
155cb6b8299SEric Joyner /**
156cb6b8299SEric Joyner  *  ixl_clock_in_i2c_bit - Clocks in one bit via I2C data/clock
157cb6b8299SEric Joyner  *  @hw: pointer to hardware structure
158cb6b8299SEric Joyner  *  @data: read data value
159cb6b8299SEric Joyner  *
160cb6b8299SEric Joyner  *  Clocks in one bit via I2C data/clock
161cb6b8299SEric Joyner  **/
162cb6b8299SEric Joyner static s32
163cb6b8299SEric Joyner ixl_clock_in_i2c_bit(struct ixl_pf *pf, bool *data)
164cb6b8299SEric Joyner {
165cb6b8299SEric Joyner 	struct i40e_hw *hw = &pf->hw;
166cb6b8299SEric Joyner 	u32 i2cctl = rd32(hw, IXL_I2C_REG(hw));
167cb6b8299SEric Joyner 
168cb6b8299SEric Joyner 	DEBUGFUNC("ixl_clock_in_i2c_bit");
169cb6b8299SEric Joyner 
170cb6b8299SEric Joyner 	ixl_raise_i2c_clk(pf, &i2cctl);
171cb6b8299SEric Joyner 
172cb6b8299SEric Joyner 	/* Minimum high period of clock is 4us */
173cb6b8299SEric Joyner 	i40e_usec_delay(IXL_I2C_T_HIGH);
174cb6b8299SEric Joyner 
175cb6b8299SEric Joyner 	i2cctl = rd32(hw, IXL_I2C_REG(hw));
176cb6b8299SEric Joyner 	i2cctl |= I40E_GLGEN_I2CPARAMS_DATA_OE_N_MASK;
177cb6b8299SEric Joyner 	wr32(hw, IXL_I2C_REG(hw), i2cctl);
178cb6b8299SEric Joyner 	ixl_flush(hw);
179cb6b8299SEric Joyner 
180cb6b8299SEric Joyner 	i2cctl = rd32(hw, IXL_I2C_REG(hw));
181cb6b8299SEric Joyner 	*data = ixl_get_i2c_data(pf, &i2cctl);
182cb6b8299SEric Joyner 
183cb6b8299SEric Joyner 	ixl_lower_i2c_clk(pf, &i2cctl);
184cb6b8299SEric Joyner 
185cb6b8299SEric Joyner 	/* Minimum low period of clock is 4.7 us */
186cb6b8299SEric Joyner 	i40e_usec_delay(IXL_I2C_T_LOW);
187cb6b8299SEric Joyner 
188cb6b8299SEric Joyner 	return I40E_SUCCESS;
189cb6b8299SEric Joyner }
190cb6b8299SEric Joyner 
191cb6b8299SEric Joyner /**
192cb6b8299SEric Joyner  *  ixl_get_i2c_ack - Polls for I2C ACK
193cb6b8299SEric Joyner  *  @hw: pointer to hardware structure
194cb6b8299SEric Joyner  *
195cb6b8299SEric Joyner  *  Clocks in/out one bit via I2C data/clock
196cb6b8299SEric Joyner  **/
197cb6b8299SEric Joyner static s32
198cb6b8299SEric Joyner ixl_get_i2c_ack(struct ixl_pf *pf)
199cb6b8299SEric Joyner {
200cb6b8299SEric Joyner 	struct i40e_hw *hw = &pf->hw;
201cb6b8299SEric Joyner 	s32 status = I40E_SUCCESS;
202cb6b8299SEric Joyner 	u32 i = 0;
203cb6b8299SEric Joyner 	u32 i2cctl = rd32(hw, IXL_I2C_REG(hw));
204cb6b8299SEric Joyner 	u32 timeout = 10;
205cb6b8299SEric Joyner 	bool ack = 1;
206cb6b8299SEric Joyner 
207cb6b8299SEric Joyner 	ixl_raise_i2c_clk(pf, &i2cctl);
208cb6b8299SEric Joyner 
209cb6b8299SEric Joyner 	/* Minimum high period of clock is 4us */
210cb6b8299SEric Joyner 	i40e_usec_delay(IXL_I2C_T_HIGH);
211cb6b8299SEric Joyner 
212cb6b8299SEric Joyner 	i2cctl = rd32(hw, IXL_I2C_REG(hw));
213cb6b8299SEric Joyner 	i2cctl |= I40E_GLGEN_I2CPARAMS_DATA_OE_N_MASK;
214cb6b8299SEric Joyner 	wr32(hw, IXL_I2C_REG(hw), i2cctl);
215cb6b8299SEric Joyner 	ixl_flush(hw);
216cb6b8299SEric Joyner 
217cb6b8299SEric Joyner 	/* Poll for ACK.  Note that ACK in I2C spec is
218cb6b8299SEric Joyner 	 * transition from 1 to 0 */
219cb6b8299SEric Joyner 	for (i = 0; i < timeout; i++) {
220cb6b8299SEric Joyner 		i2cctl = rd32(hw, IXL_I2C_REG(hw));
221cb6b8299SEric Joyner 		ack = ixl_get_i2c_data(pf, &i2cctl);
222cb6b8299SEric Joyner 
223cb6b8299SEric Joyner 		i40e_usec_delay(1);
224cb6b8299SEric Joyner 		if (!ack)
225cb6b8299SEric Joyner 			break;
226cb6b8299SEric Joyner 	}
227cb6b8299SEric Joyner 
228cb6b8299SEric Joyner 	if (ack) {
229cb6b8299SEric Joyner 		ixl_dbg(pf, IXL_DBG_I2C, "I2C ack was not received.\n");
230cb6b8299SEric Joyner 		status = I40E_ERR_PHY;
231cb6b8299SEric Joyner 	}
232cb6b8299SEric Joyner 
233cb6b8299SEric Joyner 	ixl_lower_i2c_clk(pf, &i2cctl);
234cb6b8299SEric Joyner 
235cb6b8299SEric Joyner 	/* Minimum low period of clock is 4.7 us */
236cb6b8299SEric Joyner 	i40e_usec_delay(IXL_I2C_T_LOW);
237cb6b8299SEric Joyner 
238cb6b8299SEric Joyner 	return status;
239cb6b8299SEric Joyner }
240cb6b8299SEric Joyner 
241cb6b8299SEric Joyner /**
242cb6b8299SEric Joyner  *  ixl_clock_out_i2c_bit - Clocks in/out one bit via I2C data/clock
243cb6b8299SEric Joyner  *  @hw: pointer to hardware structure
244cb6b8299SEric Joyner  *  @data: data value to write
245cb6b8299SEric Joyner  *
246cb6b8299SEric Joyner  *  Clocks out one bit via I2C data/clock
247cb6b8299SEric Joyner  **/
248cb6b8299SEric Joyner static s32
249cb6b8299SEric Joyner ixl_clock_out_i2c_bit(struct ixl_pf *pf, bool data)
250cb6b8299SEric Joyner {
251cb6b8299SEric Joyner 	struct i40e_hw *hw = &pf->hw;
252cb6b8299SEric Joyner 	s32 status;
253cb6b8299SEric Joyner 	u32 i2cctl = rd32(hw, IXL_I2C_REG(hw));
254cb6b8299SEric Joyner 
255cb6b8299SEric Joyner 	status = ixl_set_i2c_data(pf, &i2cctl, data);
256cb6b8299SEric Joyner 	if (status == I40E_SUCCESS) {
257cb6b8299SEric Joyner 		ixl_raise_i2c_clk(pf, &i2cctl);
258cb6b8299SEric Joyner 
259cb6b8299SEric Joyner 		/* Minimum high period of clock is 4us */
260cb6b8299SEric Joyner 		i40e_usec_delay(IXL_I2C_T_HIGH);
261cb6b8299SEric Joyner 
262cb6b8299SEric Joyner 		ixl_lower_i2c_clk(pf, &i2cctl);
263cb6b8299SEric Joyner 
264cb6b8299SEric Joyner 		/* Minimum low period of clock is 4.7 us.
265cb6b8299SEric Joyner 		 * This also takes care of the data hold time.
266cb6b8299SEric Joyner 		 */
267cb6b8299SEric Joyner 		i40e_usec_delay(IXL_I2C_T_LOW);
268cb6b8299SEric Joyner 	} else {
269cb6b8299SEric Joyner 		status = I40E_ERR_PHY;
270cb6b8299SEric Joyner 		ixl_dbg(pf, IXL_DBG_I2C, "I2C data was not set to %#x\n", data);
271cb6b8299SEric Joyner 	}
272cb6b8299SEric Joyner 
273cb6b8299SEric Joyner 	return status;
274cb6b8299SEric Joyner }
275cb6b8299SEric Joyner 
276cb6b8299SEric Joyner /**
277cb6b8299SEric Joyner  *  ixl_clock_out_i2c_byte - Clocks out one byte via I2C
278cb6b8299SEric Joyner  *  @hw: pointer to hardware structure
279cb6b8299SEric Joyner  *  @data: data byte clocked out
280cb6b8299SEric Joyner  *
281cb6b8299SEric Joyner  *  Clocks out one byte data via I2C data/clock
282cb6b8299SEric Joyner  **/
283cb6b8299SEric Joyner static s32
284cb6b8299SEric Joyner ixl_clock_out_i2c_byte(struct ixl_pf *pf, u8 data)
285cb6b8299SEric Joyner {
286cb6b8299SEric Joyner 	struct i40e_hw *hw = &pf->hw;
287cb6b8299SEric Joyner 	s32 status = I40E_SUCCESS;
288cb6b8299SEric Joyner 	s32 i;
289cb6b8299SEric Joyner 	u32 i2cctl;
290cb6b8299SEric Joyner 	bool bit;
291cb6b8299SEric Joyner 
292cb6b8299SEric Joyner 	DEBUGFUNC("ixl_clock_out_i2c_byte");
293cb6b8299SEric Joyner 
294cb6b8299SEric Joyner 	for (i = 7; i >= 0; i--) {
295cb6b8299SEric Joyner 		bit = (data >> i) & 0x1;
296cb6b8299SEric Joyner 		status = ixl_clock_out_i2c_bit(pf, bit);
297cb6b8299SEric Joyner 
298cb6b8299SEric Joyner 		if (status != I40E_SUCCESS)
299cb6b8299SEric Joyner 			break;
300cb6b8299SEric Joyner 	}
301cb6b8299SEric Joyner 
302cb6b8299SEric Joyner 	/* Release SDA line (set high) */
303cb6b8299SEric Joyner 	i2cctl = rd32(hw, IXL_I2C_REG(hw));
304cb6b8299SEric Joyner 	i2cctl |= I40E_GLGEN_I2CPARAMS_DATA_OUT_MASK;
305cb6b8299SEric Joyner 	i2cctl &= ~(I40E_GLGEN_I2CPARAMS_DATA_OE_N_MASK);
306cb6b8299SEric Joyner 	wr32(hw, IXL_I2C_REG(hw), i2cctl);
307cb6b8299SEric Joyner 	ixl_flush(hw);
308cb6b8299SEric Joyner 
309cb6b8299SEric Joyner 	return status;
310cb6b8299SEric Joyner }
311cb6b8299SEric Joyner 
312cb6b8299SEric Joyner /**
313cb6b8299SEric Joyner  *  ixl_lower_i2c_clk - Lowers the I2C SCL clock
314cb6b8299SEric Joyner  *  @hw: pointer to hardware structure
315cb6b8299SEric Joyner  *  @i2cctl: Current value of I2CCTL register
316cb6b8299SEric Joyner  *
317cb6b8299SEric Joyner  *  Lowers the I2C clock line '1'->'0'
318cb6b8299SEric Joyner  **/
319cb6b8299SEric Joyner static void
320cb6b8299SEric Joyner ixl_lower_i2c_clk(struct ixl_pf *pf, u32 *i2cctl)
321cb6b8299SEric Joyner {
322cb6b8299SEric Joyner 	struct i40e_hw *hw = &pf->hw;
323cb6b8299SEric Joyner 
324cb6b8299SEric Joyner 	*i2cctl &= ~(I40E_GLGEN_I2CPARAMS_CLK_MASK);
325cb6b8299SEric Joyner 	*i2cctl &= ~(I40E_GLGEN_I2CPARAMS_CLK_OE_N_MASK);
326cb6b8299SEric Joyner 
327cb6b8299SEric Joyner 	wr32(hw, IXL_I2C_REG(hw), *i2cctl);
328cb6b8299SEric Joyner 	ixl_flush(hw);
329cb6b8299SEric Joyner 
330cb6b8299SEric Joyner 	/* SCL fall time (300ns) */
331cb6b8299SEric Joyner 	i40e_usec_delay(IXL_I2C_T_FALL);
332cb6b8299SEric Joyner }
333cb6b8299SEric Joyner 
334cb6b8299SEric Joyner /**
335cb6b8299SEric Joyner  *  ixl_raise_i2c_clk - Raises the I2C SCL clock
336cb6b8299SEric Joyner  *  @hw: pointer to hardware structure
337cb6b8299SEric Joyner  *  @i2cctl: Current value of I2CCTL register
338cb6b8299SEric Joyner  *
339cb6b8299SEric Joyner  *  Raises the I2C clock line '0'->'1'
340cb6b8299SEric Joyner  **/
341cb6b8299SEric Joyner static void
342cb6b8299SEric Joyner ixl_raise_i2c_clk(struct ixl_pf *pf, u32 *i2cctl)
343cb6b8299SEric Joyner {
344cb6b8299SEric Joyner 	struct i40e_hw *hw = &pf->hw;
345cb6b8299SEric Joyner 	u32 i = 0;
346cb6b8299SEric Joyner 	u32 timeout = IXL_I2C_CLOCK_STRETCHING_TIMEOUT;
347cb6b8299SEric Joyner 	u32 i2cctl_r = 0;
348cb6b8299SEric Joyner 
349cb6b8299SEric Joyner 	for (i = 0; i < timeout; i++) {
350cb6b8299SEric Joyner 		*i2cctl |= I40E_GLGEN_I2CPARAMS_CLK_MASK;
351cb6b8299SEric Joyner 		*i2cctl &= ~(I40E_GLGEN_I2CPARAMS_CLK_OE_N_MASK);
352cb6b8299SEric Joyner 
353cb6b8299SEric Joyner 		wr32(hw, IXL_I2C_REG(hw), *i2cctl);
354cb6b8299SEric Joyner 		ixl_flush(hw);
355cb6b8299SEric Joyner 		/* SCL rise time (1000ns) */
356cb6b8299SEric Joyner 		i40e_usec_delay(IXL_I2C_T_RISE);
357cb6b8299SEric Joyner 
358cb6b8299SEric Joyner 		i2cctl_r = rd32(hw, IXL_I2C_REG(hw));
359cb6b8299SEric Joyner 		if (i2cctl_r & I40E_GLGEN_I2CPARAMS_CLK_IN_MASK)
360cb6b8299SEric Joyner 			break;
361cb6b8299SEric Joyner 	}
362cb6b8299SEric Joyner }
363cb6b8299SEric Joyner 
364cb6b8299SEric Joyner /**
365cb6b8299SEric Joyner  *  ixl_get_i2c_data - Reads the I2C SDA data bit
366cb6b8299SEric Joyner  *  @hw: pointer to hardware structure
367cb6b8299SEric Joyner  *  @i2cctl: Current value of I2CCTL register
368cb6b8299SEric Joyner  *
369cb6b8299SEric Joyner  *  Returns the I2C data bit value
370cb6b8299SEric Joyner  **/
371cb6b8299SEric Joyner static bool
372cb6b8299SEric Joyner ixl_get_i2c_data(struct ixl_pf *pf, u32 *i2cctl)
373cb6b8299SEric Joyner {
374cb6b8299SEric Joyner 	bool data;
375cb6b8299SEric Joyner 
376cb6b8299SEric Joyner 	if (*i2cctl & I40E_GLGEN_I2CPARAMS_DATA_IN_MASK)
377cb6b8299SEric Joyner 		data = 1;
378cb6b8299SEric Joyner 	else
379cb6b8299SEric Joyner 		data = 0;
380cb6b8299SEric Joyner 
381cb6b8299SEric Joyner 	return data;
382cb6b8299SEric Joyner }
383cb6b8299SEric Joyner 
384cb6b8299SEric Joyner /**
385cb6b8299SEric Joyner  *  ixl_set_i2c_data - Sets the I2C data bit
386cb6b8299SEric Joyner  *  @hw: pointer to hardware structure
387cb6b8299SEric Joyner  *  @i2cctl: Current value of I2CCTL register
388cb6b8299SEric Joyner  *  @data: I2C data value (0 or 1) to set
389cb6b8299SEric Joyner  *
390cb6b8299SEric Joyner  *  Sets the I2C data bit
391cb6b8299SEric Joyner  **/
392cb6b8299SEric Joyner static s32
393cb6b8299SEric Joyner ixl_set_i2c_data(struct ixl_pf *pf, u32 *i2cctl, bool data)
394cb6b8299SEric Joyner {
395cb6b8299SEric Joyner 	struct i40e_hw *hw = &pf->hw;
396cb6b8299SEric Joyner 	s32 status = I40E_SUCCESS;
397cb6b8299SEric Joyner 
398cb6b8299SEric Joyner 	DEBUGFUNC("ixl_set_i2c_data");
399cb6b8299SEric Joyner 
400cb6b8299SEric Joyner 	if (data)
401cb6b8299SEric Joyner 		*i2cctl |= I40E_GLGEN_I2CPARAMS_DATA_OUT_MASK;
402cb6b8299SEric Joyner 	else
403cb6b8299SEric Joyner 		*i2cctl &= ~(I40E_GLGEN_I2CPARAMS_DATA_OUT_MASK);
404cb6b8299SEric Joyner 	*i2cctl &= ~(I40E_GLGEN_I2CPARAMS_DATA_OE_N_MASK);
405cb6b8299SEric Joyner 
406cb6b8299SEric Joyner 	wr32(hw, IXL_I2C_REG(hw), *i2cctl);
407cb6b8299SEric Joyner 	ixl_flush(hw);
408cb6b8299SEric Joyner 
409cb6b8299SEric Joyner 	/* Data rise/fall (1000ns/300ns) and set-up time (250ns) */
410cb6b8299SEric Joyner 	i40e_usec_delay(IXL_I2C_T_RISE + IXL_I2C_T_FALL + IXL_I2C_T_SU_DATA);
411cb6b8299SEric Joyner 
412cb6b8299SEric Joyner 	/* Verify data was set correctly */
413cb6b8299SEric Joyner 	*i2cctl = rd32(hw, IXL_I2C_REG(hw));
414cb6b8299SEric Joyner 	if (data != ixl_get_i2c_data(pf, i2cctl)) {
415cb6b8299SEric Joyner 		status = I40E_ERR_PHY;
416cb6b8299SEric Joyner 		ixl_dbg(pf, IXL_DBG_I2C, "Error - I2C data was not set to %X.\n", data);
417cb6b8299SEric Joyner 	}
418cb6b8299SEric Joyner 
419cb6b8299SEric Joyner 	return status;
420cb6b8299SEric Joyner }
421cb6b8299SEric Joyner 
422cb6b8299SEric Joyner /**
423cb6b8299SEric Joyner  *  ixl_i2c_start - Sets I2C start condition
424cb6b8299SEric Joyner  *  Sets I2C start condition (High -> Low on SDA while SCL is High)
425cb6b8299SEric Joyner  **/
426cb6b8299SEric Joyner static void
427cb6b8299SEric Joyner ixl_i2c_start(struct ixl_pf *pf)
428cb6b8299SEric Joyner {
429cb6b8299SEric Joyner 	struct i40e_hw *hw = &pf->hw;
430cb6b8299SEric Joyner 	u32 i2cctl = rd32(hw, IXL_I2C_REG(hw));
431cb6b8299SEric Joyner 
432cb6b8299SEric Joyner 	DEBUGFUNC("ixl_i2c_start");
433cb6b8299SEric Joyner 
434cb6b8299SEric Joyner 	/* Start condition must begin with data and clock high */
435cb6b8299SEric Joyner 	ixl_set_i2c_data(pf, &i2cctl, 1);
436cb6b8299SEric Joyner 	ixl_raise_i2c_clk(pf, &i2cctl);
437cb6b8299SEric Joyner 
438cb6b8299SEric Joyner 	/* Setup time for start condition (4.7us) */
439cb6b8299SEric Joyner 	i40e_usec_delay(IXL_I2C_T_SU_STA);
440cb6b8299SEric Joyner 
441cb6b8299SEric Joyner 	ixl_set_i2c_data(pf, &i2cctl, 0);
442cb6b8299SEric Joyner 
443cb6b8299SEric Joyner 	/* Hold time for start condition (4us) */
444cb6b8299SEric Joyner 	i40e_usec_delay(IXL_I2C_T_HD_STA);
445cb6b8299SEric Joyner 
446cb6b8299SEric Joyner 	ixl_lower_i2c_clk(pf, &i2cctl);
447cb6b8299SEric Joyner 
448cb6b8299SEric Joyner 	/* Minimum low period of clock is 4.7 us */
449cb6b8299SEric Joyner 	i40e_usec_delay(IXL_I2C_T_LOW);
450cb6b8299SEric Joyner 
451cb6b8299SEric Joyner }
452cb6b8299SEric Joyner 
453cb6b8299SEric Joyner /**
454*1031d839SEric Joyner  *  ixl_read_i2c_byte_bb - Reads 8 bit word over I2C
455cb6b8299SEric Joyner  **/
456cb6b8299SEric Joyner s32
457*1031d839SEric Joyner ixl_read_i2c_byte_bb(struct ixl_pf *pf, u8 byte_offset,
458cb6b8299SEric Joyner 		  u8 dev_addr, u8 *data)
459cb6b8299SEric Joyner {
460cb6b8299SEric Joyner 	struct i40e_hw *hw = &pf->hw;
461cb6b8299SEric Joyner 	u32 max_retry = 10;
462cb6b8299SEric Joyner 	u32 retry = 0;
463cb6b8299SEric Joyner 	bool nack = 1;
464cb6b8299SEric Joyner 	s32 status;
465cb6b8299SEric Joyner 	*data = 0;
466cb6b8299SEric Joyner 
467cb6b8299SEric Joyner 	u32 i2cctl = rd32(hw, IXL_I2C_REG(hw));
468cb6b8299SEric Joyner 	i2cctl |= I40E_GLGEN_I2CPARAMS_I2CBB_EN_MASK;
469cb6b8299SEric Joyner 	wr32(hw, IXL_I2C_REG(hw), i2cctl);
470cb6b8299SEric Joyner 	ixl_flush(hw);
471cb6b8299SEric Joyner 
472cb6b8299SEric Joyner 	do {
473cb6b8299SEric Joyner 		ixl_i2c_start(pf);
474cb6b8299SEric Joyner 
475cb6b8299SEric Joyner 		/* Device Address and write indication */
476cb6b8299SEric Joyner 		status = ixl_clock_out_i2c_byte(pf, dev_addr);
477cb6b8299SEric Joyner 		if (status != I40E_SUCCESS) {
478cb6b8299SEric Joyner 			ixl_dbg(pf, IXL_DBG_I2C, "dev_addr clock out error\n");
479cb6b8299SEric Joyner 			goto fail;
480cb6b8299SEric Joyner 		}
481cb6b8299SEric Joyner 
482cb6b8299SEric Joyner 		status = ixl_get_i2c_ack(pf);
483cb6b8299SEric Joyner 		if (status != I40E_SUCCESS) {
484cb6b8299SEric Joyner 			ixl_dbg(pf, IXL_DBG_I2C, "dev_addr i2c ack error\n");
485cb6b8299SEric Joyner 			goto fail;
486cb6b8299SEric Joyner 		}
487cb6b8299SEric Joyner 
488cb6b8299SEric Joyner 		status = ixl_clock_out_i2c_byte(pf, byte_offset);
489cb6b8299SEric Joyner 		if (status != I40E_SUCCESS) {
490cb6b8299SEric Joyner 			ixl_dbg(pf, IXL_DBG_I2C, "byte_offset clock out error\n");
491cb6b8299SEric Joyner 			goto fail;
492cb6b8299SEric Joyner 		}
493cb6b8299SEric Joyner 
494cb6b8299SEric Joyner 		status = ixl_get_i2c_ack(pf);
495cb6b8299SEric Joyner 		if (status != I40E_SUCCESS) {
496cb6b8299SEric Joyner 			ixl_dbg(pf, IXL_DBG_I2C, "byte_offset i2c ack error\n");
497cb6b8299SEric Joyner 			goto fail;
498cb6b8299SEric Joyner 		}
499cb6b8299SEric Joyner 
500cb6b8299SEric Joyner 		ixl_i2c_start(pf);
501cb6b8299SEric Joyner 
502cb6b8299SEric Joyner 		/* Device Address and read indication */
503cb6b8299SEric Joyner 		status = ixl_clock_out_i2c_byte(pf, (dev_addr | 0x1));
504cb6b8299SEric Joyner 		if (status != I40E_SUCCESS)
505cb6b8299SEric Joyner 			goto fail;
506cb6b8299SEric Joyner 
507cb6b8299SEric Joyner 		status = ixl_get_i2c_ack(pf);
508cb6b8299SEric Joyner 		if (status != I40E_SUCCESS)
509cb6b8299SEric Joyner 			goto fail;
510cb6b8299SEric Joyner 
511cb6b8299SEric Joyner 		status = ixl_clock_in_i2c_byte(pf, data);
512cb6b8299SEric Joyner 		if (status != I40E_SUCCESS)
513cb6b8299SEric Joyner 			goto fail;
514cb6b8299SEric Joyner 
515cb6b8299SEric Joyner 		status = ixl_clock_out_i2c_bit(pf, nack);
516cb6b8299SEric Joyner 		if (status != I40E_SUCCESS)
517cb6b8299SEric Joyner 			goto fail;
518cb6b8299SEric Joyner 
519cb6b8299SEric Joyner 		ixl_i2c_stop(pf);
520cb6b8299SEric Joyner 		status = I40E_SUCCESS;
521cb6b8299SEric Joyner 		goto done;
522cb6b8299SEric Joyner 
523cb6b8299SEric Joyner fail:
524cb6b8299SEric Joyner 		ixl_i2c_bus_clear(pf);
525cb6b8299SEric Joyner 		i40e_msec_delay(100);
526cb6b8299SEric Joyner 		retry++;
527cb6b8299SEric Joyner 		if (retry < max_retry)
528*1031d839SEric Joyner 			ixl_dbg(pf, IXL_DBG_I2C, "I2C byte read error - Retrying\n");
529cb6b8299SEric Joyner 		else
530*1031d839SEric Joyner 			ixl_dbg(pf, IXL_DBG_I2C, "I2C byte read error\n");
531cb6b8299SEric Joyner 
532cb6b8299SEric Joyner 	} while (retry < max_retry);
533cb6b8299SEric Joyner done:
534cb6b8299SEric Joyner 	i2cctl = rd32(hw, IXL_I2C_REG(hw));
535cb6b8299SEric Joyner 	i2cctl &= ~I40E_GLGEN_I2CPARAMS_I2CBB_EN_MASK;
536cb6b8299SEric Joyner 	wr32(hw, IXL_I2C_REG(hw), i2cctl);
537cb6b8299SEric Joyner 	ixl_flush(hw);
538cb6b8299SEric Joyner 
539cb6b8299SEric Joyner 	return status;
540cb6b8299SEric Joyner }
541cb6b8299SEric Joyner 
542cb6b8299SEric Joyner /**
543*1031d839SEric Joyner  *  ixl_write_i2c_byte_bb - Writes 8 bit word over I2C
544cb6b8299SEric Joyner  **/
545cb6b8299SEric Joyner s32
546*1031d839SEric Joyner ixl_write_i2c_byte_bb(struct ixl_pf *pf, u8 byte_offset,
547cb6b8299SEric Joyner 		       u8 dev_addr, u8 data)
548cb6b8299SEric Joyner {
549cb6b8299SEric Joyner 	struct i40e_hw *hw = &pf->hw;
550cb6b8299SEric Joyner 	s32 status = I40E_SUCCESS;
551cb6b8299SEric Joyner 	u32 max_retry = 1;
552cb6b8299SEric Joyner 	u32 retry = 0;
553cb6b8299SEric Joyner 
554cb6b8299SEric Joyner 	u32 i2cctl = rd32(hw, IXL_I2C_REG(hw));
555cb6b8299SEric Joyner 	i2cctl |= I40E_GLGEN_I2CPARAMS_I2CBB_EN_MASK;
556cb6b8299SEric Joyner 	wr32(hw, IXL_I2C_REG(hw), i2cctl);
557cb6b8299SEric Joyner 	ixl_flush(hw);
558cb6b8299SEric Joyner 
559cb6b8299SEric Joyner 	do {
560cb6b8299SEric Joyner 		ixl_i2c_start(pf);
561cb6b8299SEric Joyner 
562cb6b8299SEric Joyner 		status = ixl_clock_out_i2c_byte(pf, dev_addr);
563cb6b8299SEric Joyner 		if (status != I40E_SUCCESS)
564cb6b8299SEric Joyner 			goto fail;
565cb6b8299SEric Joyner 
566cb6b8299SEric Joyner 		status = ixl_get_i2c_ack(pf);
567cb6b8299SEric Joyner 		if (status != I40E_SUCCESS)
568cb6b8299SEric Joyner 			goto fail;
569cb6b8299SEric Joyner 
570cb6b8299SEric Joyner 		status = ixl_clock_out_i2c_byte(pf, byte_offset);
571cb6b8299SEric Joyner 		if (status != I40E_SUCCESS)
572cb6b8299SEric Joyner 			goto fail;
573cb6b8299SEric Joyner 
574cb6b8299SEric Joyner 		status = ixl_get_i2c_ack(pf);
575cb6b8299SEric Joyner 		if (status != I40E_SUCCESS)
576cb6b8299SEric Joyner 			goto fail;
577cb6b8299SEric Joyner 
578cb6b8299SEric Joyner 		status = ixl_clock_out_i2c_byte(pf, data);
579cb6b8299SEric Joyner 		if (status != I40E_SUCCESS)
580cb6b8299SEric Joyner 			goto fail;
581cb6b8299SEric Joyner 
582cb6b8299SEric Joyner 		status = ixl_get_i2c_ack(pf);
583cb6b8299SEric Joyner 		if (status != I40E_SUCCESS)
584cb6b8299SEric Joyner 			goto fail;
585cb6b8299SEric Joyner 
586cb6b8299SEric Joyner 		ixl_i2c_stop(pf);
587cb6b8299SEric Joyner 		goto write_byte_out;
588cb6b8299SEric Joyner 
589cb6b8299SEric Joyner fail:
590cb6b8299SEric Joyner 		ixl_i2c_bus_clear(pf);
591cb6b8299SEric Joyner 		i40e_msec_delay(100);
592cb6b8299SEric Joyner 		retry++;
593cb6b8299SEric Joyner 		if (retry < max_retry)
594*1031d839SEric Joyner 			ixl_dbg(pf, IXL_DBG_I2C, "I2C byte write error - Retrying\n");
595cb6b8299SEric Joyner 		else
596*1031d839SEric Joyner 			ixl_dbg(pf, IXL_DBG_I2C, "I2C byte write error\n");
597cb6b8299SEric Joyner 	} while (retry < max_retry);
598cb6b8299SEric Joyner 
599cb6b8299SEric Joyner write_byte_out:
600cb6b8299SEric Joyner 	i2cctl = rd32(hw, IXL_I2C_REG(hw));
601cb6b8299SEric Joyner 	i2cctl &= ~I40E_GLGEN_I2CPARAMS_I2CBB_EN_MASK;
602cb6b8299SEric Joyner 	wr32(hw, IXL_I2C_REG(hw), i2cctl);
603cb6b8299SEric Joyner 	ixl_flush(hw);
604cb6b8299SEric Joyner 
605cb6b8299SEric Joyner 	return status;
606cb6b8299SEric Joyner }
607cb6b8299SEric Joyner 
608*1031d839SEric Joyner /**
609*1031d839SEric Joyner  *  ixl_read_i2c_byte - Reads 8 bit word over I2C using a hardware register
610*1031d839SEric Joyner  **/
611*1031d839SEric Joyner s32
612*1031d839SEric Joyner ixl_read_i2c_byte_reg(struct ixl_pf *pf, u8 byte_offset,
613*1031d839SEric Joyner 		  u8 dev_addr, u8 *data)
614*1031d839SEric Joyner {
615*1031d839SEric Joyner 	struct i40e_hw *hw = &pf->hw;
616*1031d839SEric Joyner 	u32 reg = 0;
617*1031d839SEric Joyner 	s32 status;
618*1031d839SEric Joyner 	*data = 0;
619*1031d839SEric Joyner 
620*1031d839SEric Joyner 	reg |= (byte_offset << I40E_GLGEN_I2CCMD_REGADD_SHIFT);
621*1031d839SEric Joyner 	reg |= (((dev_addr >> 1) & 0x7) << I40E_GLGEN_I2CCMD_PHYADD_SHIFT);
622*1031d839SEric Joyner 	reg |= I40E_GLGEN_I2CCMD_OP_MASK;
623*1031d839SEric Joyner 	wr32(hw, I40E_GLGEN_I2CCMD(hw->func_caps.mdio_port_num), reg);
624*1031d839SEric Joyner 
625*1031d839SEric Joyner 	status = ixl_wait_for_i2c_completion(hw, hw->func_caps.mdio_port_num);
626*1031d839SEric Joyner 
627*1031d839SEric Joyner 	/* Get data from I2C register */
628*1031d839SEric Joyner 	reg = rd32(hw, I40E_GLGEN_I2CCMD(hw->func_caps.mdio_port_num));
629*1031d839SEric Joyner 
630*1031d839SEric Joyner 	/* Retrieve data readed from EEPROM */
631*1031d839SEric Joyner 	*data = (u8)(reg & 0xff);
632*1031d839SEric Joyner 
633*1031d839SEric Joyner 	if (status)
634*1031d839SEric Joyner 		ixl_dbg(pf, IXL_DBG_I2C, "I2C byte read error\n");
635*1031d839SEric Joyner 	return status;
636*1031d839SEric Joyner }
637*1031d839SEric Joyner 
638*1031d839SEric Joyner /**
639*1031d839SEric Joyner  *  ixl_write_i2c_byte - Writes 8 bit word over I2C using a hardware register
640*1031d839SEric Joyner  **/
641*1031d839SEric Joyner s32
642*1031d839SEric Joyner ixl_write_i2c_byte_reg(struct ixl_pf *pf, u8 byte_offset,
643*1031d839SEric Joyner 		       u8 dev_addr, u8 data)
644*1031d839SEric Joyner {
645*1031d839SEric Joyner 	struct i40e_hw *hw = &pf->hw;
646*1031d839SEric Joyner 	s32 status = I40E_SUCCESS;
647*1031d839SEric Joyner 	u32 reg = 0;
648*1031d839SEric Joyner 	u8 upperbyte = 0;
649*1031d839SEric Joyner 	u16 datai2c = 0;
650*1031d839SEric Joyner 
651*1031d839SEric Joyner 	status = ixl_read_i2c_byte_reg(pf, byte_offset + 1, dev_addr, &upperbyte);
652*1031d839SEric Joyner 	datai2c = ((u16)upperbyte << 8) | (u16)data;
653*1031d839SEric Joyner 	reg = rd32(hw, I40E_GLGEN_I2CCMD(hw->func_caps.mdio_port_num));
654*1031d839SEric Joyner 
655*1031d839SEric Joyner 	/* Form write command */
656*1031d839SEric Joyner 	reg &= ~I40E_GLGEN_I2CCMD_PHYADD_MASK;
657*1031d839SEric Joyner 	reg |= (((dev_addr >> 1) & 0x7) << I40E_GLGEN_I2CCMD_PHYADD_SHIFT);
658*1031d839SEric Joyner 	reg &= ~I40E_GLGEN_I2CCMD_REGADD_MASK;
659*1031d839SEric Joyner 	reg |= (byte_offset << I40E_GLGEN_I2CCMD_REGADD_SHIFT);
660*1031d839SEric Joyner 	reg &= ~I40E_GLGEN_I2CCMD_DATA_MASK;
661*1031d839SEric Joyner 	reg |= (datai2c << I40E_GLGEN_I2CCMD_DATA_SHIFT);
662*1031d839SEric Joyner 	reg &= ~I40E_GLGEN_I2CCMD_OP_MASK;
663*1031d839SEric Joyner 
664*1031d839SEric Joyner 	/* Write command to registers controling I2C - data and address. */
665*1031d839SEric Joyner 	wr32(hw, I40E_GLGEN_I2CCMD(hw->func_caps.mdio_port_num), reg);
666*1031d839SEric Joyner 
667*1031d839SEric Joyner 	status = ixl_wait_for_i2c_completion(hw, hw->func_caps.mdio_port_num);
668*1031d839SEric Joyner 
669*1031d839SEric Joyner 	if (status)
670*1031d839SEric Joyner 		ixl_dbg(pf, IXL_DBG_I2C, "I2C byte write error\n");
671*1031d839SEric Joyner 	return status;
672*1031d839SEric Joyner }
673*1031d839SEric Joyner 
674*1031d839SEric Joyner /**
675*1031d839SEric Joyner  *  ixl_wait_for_i2c_completion
676*1031d839SEric Joyner  **/
677*1031d839SEric Joyner static s32
678*1031d839SEric Joyner ixl_wait_for_i2c_completion(struct i40e_hw *hw, u8 portnum)
679*1031d839SEric Joyner {
680*1031d839SEric Joyner 	s32 status = 0;
681*1031d839SEric Joyner 	u32 timeout = 100;
682*1031d839SEric Joyner 	u32 reg;
683*1031d839SEric Joyner 	do {
684*1031d839SEric Joyner 		reg = rd32(hw, I40E_GLGEN_I2CCMD(portnum));
685*1031d839SEric Joyner 		if ((reg & I40E_GLGEN_I2CCMD_R_MASK) != 0)
686*1031d839SEric Joyner 			break;
687*1031d839SEric Joyner 		i40e_usec_delay(10);
688*1031d839SEric Joyner 	} while (timeout-- > 0);
689*1031d839SEric Joyner 
690*1031d839SEric Joyner 	if (timeout == 0)
691*1031d839SEric Joyner 		return I40E_ERR_TIMEOUT;
692*1031d839SEric Joyner 	else
693*1031d839SEric Joyner 		return status;
694*1031d839SEric Joyner }
695*1031d839SEric Joyner 
696*1031d839SEric Joyner /**
697*1031d839SEric Joyner  *  ixl_read_i2c_byte - Reads 8 bit word over I2C using a hardware register
698*1031d839SEric Joyner  **/
699*1031d839SEric Joyner s32
700*1031d839SEric Joyner ixl_read_i2c_byte_aq(struct ixl_pf *pf, u8 byte_offset,
701*1031d839SEric Joyner 		  u8 dev_addr, u8 *data)
702*1031d839SEric Joyner {
703*1031d839SEric Joyner 	struct i40e_hw *hw = &pf->hw;
704*1031d839SEric Joyner 	s32 status = I40E_SUCCESS;
705*1031d839SEric Joyner 	u32 reg;
706*1031d839SEric Joyner 
707*1031d839SEric Joyner 	status = i40e_aq_get_phy_register(hw,
708*1031d839SEric Joyner 					I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE,
709*1031d839SEric Joyner 					dev_addr,
710*1031d839SEric Joyner 					byte_offset,
711*1031d839SEric Joyner 					&reg, NULL);
712*1031d839SEric Joyner 
713*1031d839SEric Joyner 	if (status)
714*1031d839SEric Joyner 		ixl_dbg(pf, IXL_DBG_I2C, "I2C byte read status %s, error %s\n",
715*1031d839SEric Joyner 		    i40e_stat_str(hw, status), i40e_aq_str(hw, hw->aq.asq_last_status));
716*1031d839SEric Joyner 	else
717*1031d839SEric Joyner 		*data = (u8)reg;
718*1031d839SEric Joyner 
719*1031d839SEric Joyner 	return status;
720*1031d839SEric Joyner }
721*1031d839SEric Joyner 
722*1031d839SEric Joyner /**
723*1031d839SEric Joyner  *  ixl_write_i2c_byte - Writes 8 bit word over I2C using a hardware register
724*1031d839SEric Joyner  **/
725*1031d839SEric Joyner s32
726*1031d839SEric Joyner ixl_write_i2c_byte_aq(struct ixl_pf *pf, u8 byte_offset,
727*1031d839SEric Joyner 		       u8 dev_addr, u8 data)
728*1031d839SEric Joyner {
729*1031d839SEric Joyner 	struct i40e_hw *hw = &pf->hw;
730*1031d839SEric Joyner 	s32 status = I40E_SUCCESS;
731*1031d839SEric Joyner 
732*1031d839SEric Joyner 	status = i40e_aq_set_phy_register(hw,
733*1031d839SEric Joyner 					I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE,
734*1031d839SEric Joyner 					dev_addr,
735*1031d839SEric Joyner 					byte_offset,
736*1031d839SEric Joyner 					data, NULL);
737*1031d839SEric Joyner 
738*1031d839SEric Joyner 	if (status)
739*1031d839SEric Joyner 		ixl_dbg(pf, IXL_DBG_I2C, "I2C byte write status %s, error %s\n",
740*1031d839SEric Joyner 		    i40e_stat_str(hw, status), i40e_aq_str(hw, hw->aq.asq_last_status));
741*1031d839SEric Joyner 
742*1031d839SEric Joyner 	return status;
743*1031d839SEric Joyner }
744