ixgbe: move to drivers/net/
[dpdk.git] / drivers / net / ixgbe / ixgbe_bypass_api.h
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33
34 #ifndef _IXGBE_BYPASS_API_H_
35 #define _IXGBE_BYPASS_API_H_
36
37 #ifdef RTE_NIC_BYPASS
38
39 #include "ixgbe_bypass_defines.h"
40 /**
41  *  ixgbe_bypass_rw_generic - Bit bang data into by_pass FW
42  *
43  *  @hw: pointer to hardware structure
44  *  @cmd: Command we send to the FW
45  *  @status: The reply from the FW
46  *
47  *  Bit-bangs the cmd to the by_pass FW status points to what is returned.
48  **/
49 #define IXGBE_BYPASS_BB_WAIT 1
50 static s32 ixgbe_bypass_rw_generic(struct ixgbe_hw *hw, u32 cmd, u32 *status)
51 {
52         int i;
53         u32 sck, sdi, sdo, dir_sck, dir_sdi, dir_sdo;
54         u32 esdp;
55
56         if (!status)
57                 return IXGBE_ERR_PARAM;
58
59         *status = 0;
60
61         /* SDP vary by MAC type */
62         switch (hw->mac.type) {
63         case ixgbe_mac_82599EB:
64                 sck = IXGBE_ESDP_SDP7;
65                 sdi = IXGBE_ESDP_SDP0;
66                 sdo = IXGBE_ESDP_SDP6;
67                 dir_sck = IXGBE_ESDP_SDP7_DIR;
68                 dir_sdi = IXGBE_ESDP_SDP0_DIR;
69                 dir_sdo = IXGBE_ESDP_SDP6_DIR;
70                 break;
71         case ixgbe_mac_X540:
72                 sck = IXGBE_ESDP_SDP2;
73                 sdi = IXGBE_ESDP_SDP0;
74                 sdo = IXGBE_ESDP_SDP1;
75                 dir_sck = IXGBE_ESDP_SDP2_DIR;
76                 dir_sdi = IXGBE_ESDP_SDP0_DIR;
77                 dir_sdo = IXGBE_ESDP_SDP1_DIR;
78                 break;
79         case ixgbe_mac_X550:
80         case ixgbe_mac_X550EM_x:
81                 sck = IXGBE_ESDP_SDP2;
82                 sdi = IXGBE_ESDP_SDP0;
83                 sdo = IXGBE_ESDP_SDP1;
84                 dir_sck = IXGBE_ESDP_SDP2_DIR;
85                 dir_sdi = IXGBE_ESDP_SDP0_DIR;
86                 dir_sdo = IXGBE_ESDP_SDP1_DIR;
87                 break;
88         default:
89                 return IXGBE_ERR_DEVICE_NOT_SUPPORTED;
90         }
91
92         /* Set SDP pins direction */
93         esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
94         esdp |= dir_sck;        /* SCK as output */
95         esdp |= dir_sdi;        /* SDI as output */
96         esdp &= ~dir_sdo;       /* SDO as input */
97         esdp |= sck;
98         esdp |= sdi;
99         IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
100         IXGBE_WRITE_FLUSH(hw);
101   //  TODO:
102         msleep(IXGBE_BYPASS_BB_WAIT);
103
104         /* Generate start condition */
105         esdp &= ~sdi;
106         IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
107         IXGBE_WRITE_FLUSH(hw);
108         msleep(IXGBE_BYPASS_BB_WAIT);
109
110         esdp &= ~sck;
111         IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
112         IXGBE_WRITE_FLUSH(hw);
113         msleep(IXGBE_BYPASS_BB_WAIT);
114
115         /* Clock out the new control word and clock in the status */
116         for (i = 0; i < 32; i++) {
117                 if ((cmd >> (31 - i)) & 0x01) {
118                         esdp |= sdi;
119                         IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
120                 } else {
121                         esdp &= ~sdi;
122                         IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
123                 }
124                 IXGBE_WRITE_FLUSH(hw);
125                 msleep(IXGBE_BYPASS_BB_WAIT);
126
127                 esdp |= sck;
128                 IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
129                 IXGBE_WRITE_FLUSH(hw);
130                 msleep(IXGBE_BYPASS_BB_WAIT);
131
132                 esdp &= ~sck;
133                 IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
134                 IXGBE_WRITE_FLUSH(hw);
135                 msleep(IXGBE_BYPASS_BB_WAIT);
136
137                 esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
138                 if (esdp & sdo)
139                         *status = (*status << 1) | 0x01;
140                 else
141                         *status = (*status << 1) | 0x00;
142                 msleep(IXGBE_BYPASS_BB_WAIT);
143         }
144
145         /* stop condition */
146         esdp |= sck;
147         esdp &= ~sdi;
148         IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
149         IXGBE_WRITE_FLUSH(hw);
150         msleep(IXGBE_BYPASS_BB_WAIT);
151
152         esdp |= sdi;
153         IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
154         IXGBE_WRITE_FLUSH(hw);
155
156         /* set the page bits to match the cmd that the status it belongs to */
157         *status = (*status & 0x3fffffff) | (cmd & 0xc0000000);
158
159         return 0;
160 }
161
162 /**
163  * ixgbe_bypass_valid_rd_generic - Verify valid return from bit-bang.
164  *
165  * If we send a write we can't be sure it took until we can read back
166  * that same register.  It can be a problem as some of the feilds may
167  * for valid reasons change between the time wrote the register and
168  * we read it again to verify.  So this function check everything we
169  * can check and then assumes it worked.
170  *
171  * @u32 in_reg - The register cmd for the bit-bang read.
172  * @u32 out_reg - The register returned from a bit-bang read.
173  **/
174 static bool ixgbe_bypass_valid_rd_generic(u32 in_reg, u32 out_reg)
175 {
176         u32 mask;
177
178         /* Page must match for all control pages */
179         if ((in_reg & BYPASS_PAGE_M) != (out_reg & BYPASS_PAGE_M))
180                 return false;
181
182         switch (in_reg & BYPASS_PAGE_M) {
183         case BYPASS_PAGE_CTL0:
184                 /* All the following can't change since the last write
185                  *  - All the event actions
186                  *  - The timeout value
187                  */
188                 mask = BYPASS_AUX_ON_M | BYPASS_MAIN_ON_M |
189                        BYPASS_MAIN_OFF_M | BYPASS_AUX_OFF_M |
190                        BYPASS_WDTIMEOUT_M |
191                        BYPASS_WDT_VALUE_M;
192                 if ((out_reg & mask) != (in_reg & mask))
193                         return false;
194
195                 /* 0x0 is never a valid value for bypass status */
196                 if (!(out_reg & BYPASS_STATUS_OFF_M))
197                         return false;
198                 break;
199         case BYPASS_PAGE_CTL1:
200                 /* All the following can't change since the last write
201                  *  - time valid bit
202                  *  - time we last sent
203                  */
204                 mask = BYPASS_CTL1_VALID_M | BYPASS_CTL1_TIME_M;
205                 if ((out_reg & mask) != (in_reg & mask))
206                         return false;
207                 break;
208         case BYPASS_PAGE_CTL2:
209                 /* All we can check in this page is control number
210                  * which is already done above.
211                  */
212                 break;
213         }
214
215         /* We are as sure as we can be return true */
216         return true;
217 }
218
219 /**
220  *  ixgbe_bypass_set_generic - Set a bypass field in the FW CTRL Regiter.
221  *
222  *  @hw: pointer to hardware structure
223  *  @cmd: The control word we are setting.
224  *  @event: The event we are setting in the FW.  This also happens to
225  *          be the mask for the event we are setting (handy)
226  *  @action: The action we set the event to in the FW. This is in a
227  *           bit field that happens to be what we want to put in
228  *           the event spot (also handy)
229  **/
230 static s32 ixgbe_bypass_set_generic(struct ixgbe_hw *hw, u32 ctrl, u32 event,
231                              u32 action)
232 {
233         u32 by_ctl = 0;
234         u32 cmd, verify;
235         u32 count = 0;
236
237         /* Get current values */
238         cmd = ctrl;     /* just reading only need control number */
239         if (ixgbe_bypass_rw_generic(hw, cmd, &by_ctl))
240                 return IXGBE_ERR_INVALID_ARGUMENT;
241
242         /* Set to new action */
243         cmd = (by_ctl & ~event) | BYPASS_WE | action;
244         if (ixgbe_bypass_rw_generic(hw, cmd, &by_ctl))
245                 return IXGBE_ERR_INVALID_ARGUMENT;
246
247         /* Page 0 force a FW eeprom write which is slow so verify */
248         if ((cmd & BYPASS_PAGE_M) == BYPASS_PAGE_CTL0) {
249                 verify = BYPASS_PAGE_CTL0;
250                 do {
251                         if (count++ > 5)
252                                 return IXGBE_BYPASS_FW_WRITE_FAILURE;
253
254                         if (ixgbe_bypass_rw_generic(hw, verify, &by_ctl))
255                                 return IXGBE_ERR_INVALID_ARGUMENT;
256                 } while (!ixgbe_bypass_valid_rd_generic(cmd, by_ctl));
257         } else {
258                 /* We have give the FW time for the write to stick */
259                 msleep(100);
260         }
261
262         return 0;
263 }
264
265 /**
266  *  ixgbe_bypass_rd_eep_generic - Read the bypass FW eeprom address.
267  *
268  *  @hw: pointer to hardware structure
269  *  @addr: The bypass eeprom address to read.
270  *  @value: The 8b of data at the address above.
271  **/
272 static s32 ixgbe_bypass_rd_eep_generic(struct ixgbe_hw *hw, u32 addr, u8 *value)
273 {
274         u32 cmd;
275         u32 status;
276
277
278         /* send the request */
279         cmd = BYPASS_PAGE_CTL2 | BYPASS_WE;
280         cmd |= (addr << BYPASS_CTL2_OFFSET_SHIFT) & BYPASS_CTL2_OFFSET_M;
281         if (ixgbe_bypass_rw_generic(hw, cmd, &status))
282                 return IXGBE_ERR_INVALID_ARGUMENT;
283
284         /* We have give the FW time for the write to stick */
285         msleep(100);
286
287         /* now read the results */
288         cmd &= ~BYPASS_WE;
289         if (ixgbe_bypass_rw_generic(hw, cmd, &status))
290                 return IXGBE_ERR_INVALID_ARGUMENT;
291
292         *value = status & BYPASS_CTL2_DATA_M;
293
294         return 0;
295 }
296
297 #endif /* RTE_NIC_BYPASS */
298
299 #endif /* _IXGBE_BYPASS_API_H_ */