net/i40e: fix RSS flow action parser
[dpdk.git] / drivers / net / ixgbe / ixgbe_bypass_api.h
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2014 Intel Corporation
3  */
4
5 #ifndef _IXGBE_BYPASS_API_H_
6 #define _IXGBE_BYPASS_API_H_
7
8 #ifdef RTE_LIBRTE_IXGBE_BYPASS
9
10 #include "ixgbe_bypass_defines.h"
11 /**
12  *  ixgbe_bypass_rw_generic - Bit bang data into by_pass FW
13  *
14  *  @hw: pointer to hardware structure
15  *  @cmd: Command we send to the FW
16  *  @status: The reply from the FW
17  *
18  *  Bit-bangs the cmd to the by_pass FW status points to what is returned.
19  **/
20 #define IXGBE_BYPASS_BB_WAIT 1
21 static s32 ixgbe_bypass_rw_generic(struct ixgbe_hw *hw, u32 cmd, u32 *status)
22 {
23         int i;
24         u32 sck, sdi, sdo, dir_sck, dir_sdi, dir_sdo;
25         u32 esdp;
26
27         if (!status)
28                 return IXGBE_ERR_PARAM;
29
30         *status = 0;
31
32         /* SDP vary by MAC type */
33         switch (hw->mac.type) {
34         case ixgbe_mac_82599EB:
35                 sck = IXGBE_ESDP_SDP7;
36                 sdi = IXGBE_ESDP_SDP0;
37                 sdo = IXGBE_ESDP_SDP6;
38                 dir_sck = IXGBE_ESDP_SDP7_DIR;
39                 dir_sdi = IXGBE_ESDP_SDP0_DIR;
40                 dir_sdo = IXGBE_ESDP_SDP6_DIR;
41                 break;
42         case ixgbe_mac_X540:
43                 sck = IXGBE_ESDP_SDP2;
44                 sdi = IXGBE_ESDP_SDP0;
45                 sdo = IXGBE_ESDP_SDP1;
46                 dir_sck = IXGBE_ESDP_SDP2_DIR;
47                 dir_sdi = IXGBE_ESDP_SDP0_DIR;
48                 dir_sdo = IXGBE_ESDP_SDP1_DIR;
49                 break;
50         case ixgbe_mac_X550:
51         case ixgbe_mac_X550EM_x:
52         case ixgbe_mac_X550EM_a:
53                 sck = IXGBE_ESDP_SDP2;
54                 sdi = IXGBE_ESDP_SDP0;
55                 sdo = IXGBE_ESDP_SDP1;
56                 dir_sck = IXGBE_ESDP_SDP2_DIR;
57                 dir_sdi = IXGBE_ESDP_SDP0_DIR;
58                 dir_sdo = IXGBE_ESDP_SDP1_DIR;
59                 break;
60         default:
61                 return IXGBE_ERR_DEVICE_NOT_SUPPORTED;
62         }
63
64         /* Set SDP pins direction */
65         esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
66         esdp |= dir_sck;        /* SCK as output */
67         esdp |= dir_sdi;        /* SDI as output */
68         esdp &= ~dir_sdo;       /* SDO as input */
69         esdp |= sck;
70         esdp |= sdi;
71         IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
72         IXGBE_WRITE_FLUSH(hw);
73   //  TODO:
74         msleep(IXGBE_BYPASS_BB_WAIT);
75
76         /* Generate start condition */
77         esdp &= ~sdi;
78         IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
79         IXGBE_WRITE_FLUSH(hw);
80         msleep(IXGBE_BYPASS_BB_WAIT);
81
82         esdp &= ~sck;
83         IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
84         IXGBE_WRITE_FLUSH(hw);
85         msleep(IXGBE_BYPASS_BB_WAIT);
86
87         /* Clock out the new control word and clock in the status */
88         for (i = 0; i < 32; i++) {
89                 if ((cmd >> (31 - i)) & 0x01) {
90                         esdp |= sdi;
91                         IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
92                 } else {
93                         esdp &= ~sdi;
94                         IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
95                 }
96                 IXGBE_WRITE_FLUSH(hw);
97                 msleep(IXGBE_BYPASS_BB_WAIT);
98
99                 esdp |= sck;
100                 IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
101                 IXGBE_WRITE_FLUSH(hw);
102                 msleep(IXGBE_BYPASS_BB_WAIT);
103
104                 esdp &= ~sck;
105                 IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
106                 IXGBE_WRITE_FLUSH(hw);
107                 msleep(IXGBE_BYPASS_BB_WAIT);
108
109                 esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
110                 if (esdp & sdo)
111                         *status = (*status << 1) | 0x01;
112                 else
113                         *status = (*status << 1) | 0x00;
114                 msleep(IXGBE_BYPASS_BB_WAIT);
115         }
116
117         /* stop condition */
118         esdp |= sck;
119         esdp &= ~sdi;
120         IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
121         IXGBE_WRITE_FLUSH(hw);
122         msleep(IXGBE_BYPASS_BB_WAIT);
123
124         esdp |= sdi;
125         IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
126         IXGBE_WRITE_FLUSH(hw);
127
128         /* set the page bits to match the cmd that the status it belongs to */
129         *status = (*status & 0x3fffffff) | (cmd & 0xc0000000);
130
131         return 0;
132 }
133
134 /**
135  * ixgbe_bypass_valid_rd_generic - Verify valid return from bit-bang.
136  *
137  * If we send a write we can't be sure it took until we can read back
138  * that same register.  It can be a problem as some of the feilds may
139  * for valid reasons change between the time wrote the register and
140  * we read it again to verify.  So this function check everything we
141  * can check and then assumes it worked.
142  *
143  * @u32 in_reg - The register cmd for the bit-bang read.
144  * @u32 out_reg - The register returned from a bit-bang read.
145  **/
146 static bool ixgbe_bypass_valid_rd_generic(u32 in_reg, u32 out_reg)
147 {
148         u32 mask;
149
150         /* Page must match for all control pages */
151         if ((in_reg & BYPASS_PAGE_M) != (out_reg & BYPASS_PAGE_M))
152                 return false;
153
154         switch (in_reg & BYPASS_PAGE_M) {
155         case BYPASS_PAGE_CTL0:
156                 /* All the following can't change since the last write
157                  *  - All the event actions
158                  *  - The timeout value
159                  */
160                 mask = BYPASS_AUX_ON_M | BYPASS_MAIN_ON_M |
161                        BYPASS_MAIN_OFF_M | BYPASS_AUX_OFF_M |
162                        BYPASS_WDTIMEOUT_M |
163                        BYPASS_WDT_VALUE_M;
164                 if ((out_reg & mask) != (in_reg & mask))
165                         return false;
166
167                 /* 0x0 is never a valid value for bypass status */
168                 if (!(out_reg & BYPASS_STATUS_OFF_M))
169                         return false;
170                 break;
171         case BYPASS_PAGE_CTL1:
172                 /* All the following can't change since the last write
173                  *  - time valid bit
174                  *  - time we last sent
175                  */
176                 mask = BYPASS_CTL1_VALID_M | BYPASS_CTL1_TIME_M;
177                 if ((out_reg & mask) != (in_reg & mask))
178                         return false;
179                 break;
180         case BYPASS_PAGE_CTL2:
181                 /* All we can check in this page is control number
182                  * which is already done above.
183                  */
184                 break;
185         }
186
187         /* We are as sure as we can be return true */
188         return true;
189 }
190
191 /**
192  *  ixgbe_bypass_set_generic - Set a bypass field in the FW CTRL Regiter.
193  *
194  *  @hw: pointer to hardware structure
195  *  @cmd: The control word we are setting.
196  *  @event: The event we are setting in the FW.  This also happens to
197  *          be the mask for the event we are setting (handy)
198  *  @action: The action we set the event to in the FW. This is in a
199  *           bit field that happens to be what we want to put in
200  *           the event spot (also handy)
201  **/
202 static s32 ixgbe_bypass_set_generic(struct ixgbe_hw *hw, u32 ctrl, u32 event,
203                              u32 action)
204 {
205         u32 by_ctl = 0;
206         u32 cmd, verify;
207         u32 count = 0;
208
209         /* Get current values */
210         cmd = ctrl;     /* just reading only need control number */
211         if (ixgbe_bypass_rw_generic(hw, cmd, &by_ctl))
212                 return IXGBE_ERR_INVALID_ARGUMENT;
213
214         /* Set to new action */
215         cmd = (by_ctl & ~event) | BYPASS_WE | action;
216         if (ixgbe_bypass_rw_generic(hw, cmd, &by_ctl))
217                 return IXGBE_ERR_INVALID_ARGUMENT;
218
219         /* Page 0 force a FW eeprom write which is slow so verify */
220         if ((cmd & BYPASS_PAGE_M) == BYPASS_PAGE_CTL0) {
221                 verify = BYPASS_PAGE_CTL0;
222                 do {
223                         if (count++ > 5)
224                                 return IXGBE_BYPASS_FW_WRITE_FAILURE;
225
226                         if (ixgbe_bypass_rw_generic(hw, verify, &by_ctl))
227                                 return IXGBE_ERR_INVALID_ARGUMENT;
228                 } while (!ixgbe_bypass_valid_rd_generic(cmd, by_ctl));
229         } else {
230                 /* We have give the FW time for the write to stick */
231                 msleep(100);
232         }
233
234         return 0;
235 }
236
237 /**
238  *  ixgbe_bypass_rd_eep_generic - Read the bypass FW eeprom address.
239  *
240  *  @hw: pointer to hardware structure
241  *  @addr: The bypass eeprom address to read.
242  *  @value: The 8b of data at the address above.
243  **/
244 static s32 ixgbe_bypass_rd_eep_generic(struct ixgbe_hw *hw, u32 addr, u8 *value)
245 {
246         u32 cmd;
247         u32 status;
248
249
250         /* send the request */
251         cmd = BYPASS_PAGE_CTL2 | BYPASS_WE;
252         cmd |= (addr << BYPASS_CTL2_OFFSET_SHIFT) & BYPASS_CTL2_OFFSET_M;
253         if (ixgbe_bypass_rw_generic(hw, cmd, &status))
254                 return IXGBE_ERR_INVALID_ARGUMENT;
255
256         /* We have give the FW time for the write to stick */
257         msleep(100);
258
259         /* now read the results */
260         cmd &= ~BYPASS_WE;
261         if (ixgbe_bypass_rw_generic(hw, cmd, &status))
262                 return IXGBE_ERR_INVALID_ARGUMENT;
263
264         *value = status & BYPASS_CTL2_DATA_M;
265
266         return 0;
267 }
268
269 #endif /* RTE_LIBRTE_IXGBE_BYPASS */
270
271 #endif /* _IXGBE_BYPASS_API_H_ */