Branch data Line data Source code
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 : 0 : 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 [ # # ]: 0 : if (!status)
28 : : return IXGBE_ERR_PARAM;
29 : :
30 : 0 : *status = 0;
31 : :
32 : : /* SDP vary by MAC type */
33 [ # # # # ]: 0 : 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 : 0 : 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 : 0 : break;
50 : 0 : 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 : 0 : break;
60 : : default:
61 : : return IXGBE_ERR_DEVICE_NOT_SUPPORTED;
62 : : }
63 : :
64 : : /* Set SDP pins direction */
65 : 0 : esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
66 : 0 : esdp |= dir_sck; /* SCK as output */
67 : 0 : esdp |= dir_sdi; /* SDI as output */
68 : 0 : esdp &= ~dir_sdo; /* SDO as input */
69 : 0 : esdp |= sck;
70 : 0 : esdp |= sdi;
71 : 0 : IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
72 : 0 : IXGBE_WRITE_FLUSH(hw);
73 : : // TODO:
74 : 0 : msleep(IXGBE_BYPASS_BB_WAIT);
75 : :
76 : : /* Generate start condition */
77 : : esdp &= ~sdi;
78 : 0 : IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
79 : 0 : IXGBE_WRITE_FLUSH(hw);
80 : 0 : msleep(IXGBE_BYPASS_BB_WAIT);
81 : :
82 : 0 : esdp &= ~sck;
83 : 0 : IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
84 : 0 : IXGBE_WRITE_FLUSH(hw);
85 : 0 : msleep(IXGBE_BYPASS_BB_WAIT);
86 : :
87 : : /* Clock out the new control word and clock in the status */
88 [ # # ]: 0 : for (i = 0; i < 32; i++) {
89 [ # # ]: 0 : if ((cmd >> (31 - i)) & 0x01) {
90 : 0 : esdp |= sdi;
91 : 0 : IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
92 : : } else {
93 : 0 : esdp &= ~sdi;
94 : 0 : IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
95 : : }
96 : 0 : IXGBE_WRITE_FLUSH(hw);
97 : 0 : msleep(IXGBE_BYPASS_BB_WAIT);
98 : :
99 : 0 : esdp |= sck;
100 : 0 : IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
101 : 0 : IXGBE_WRITE_FLUSH(hw);
102 : 0 : msleep(IXGBE_BYPASS_BB_WAIT);
103 : :
104 : 0 : esdp &= ~sck;
105 : 0 : IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
106 : 0 : IXGBE_WRITE_FLUSH(hw);
107 : 0 : msleep(IXGBE_BYPASS_BB_WAIT);
108 : :
109 : 0 : esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
110 [ # # ]: 0 : if (esdp & sdo)
111 : 0 : *status = (*status << 1) | 0x01;
112 : : else
113 : 0 : *status = (*status << 1) | 0x00;
114 : 0 : msleep(IXGBE_BYPASS_BB_WAIT);
115 : : }
116 : :
117 : : /* stop condition */
118 : 0 : esdp |= sck;
119 : 0 : esdp &= ~sdi;
120 : 0 : IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
121 : 0 : IXGBE_WRITE_FLUSH(hw);
122 : 0 : msleep(IXGBE_BYPASS_BB_WAIT);
123 : :
124 : 0 : esdp |= sdi;
125 : 0 : IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
126 : 0 : IXGBE_WRITE_FLUSH(hw);
127 : :
128 : : /* set the page bits to match the cmd that the status it belongs to */
129 : 0 : *status = (*status & 0x3fffffff) | (cmd & 0xc0000000);
130 : :
131 : 0 : 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 fields 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 : 0 : 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 [ # # ]: 0 : if ((in_reg & BYPASS_PAGE_M) != (out_reg & BYPASS_PAGE_M))
152 : : return false;
153 : :
154 [ # # # ]: 0 : switch (in_reg & BYPASS_PAGE_M) {
155 : 0 : 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 [ # # ]: 0 : if ((out_reg & mask) != (in_reg & mask))
165 : : return false;
166 : :
167 : : /* 0x0 is never a valid value for bypass status */
168 [ # # ]: 0 : if (!(out_reg & BYPASS_STATUS_OFF_M))
169 : 0 : return false;
170 : : break;
171 : 0 : 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 [ # # ]: 0 : if ((out_reg & mask) != (in_reg & mask))
178 : 0 : 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 Register.
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 : 0 : static s32 ixgbe_bypass_set_generic(struct ixgbe_hw *hw, u32 ctrl, u32 event,
203 : : u32 action)
204 : : {
205 : 0 : 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 [ # # ]: 0 : if (ixgbe_bypass_rw_generic(hw, cmd, &by_ctl))
212 : : return IXGBE_ERR_INVALID_ARGUMENT;
213 : :
214 : : /* Set to new action */
215 : 0 : cmd = (by_ctl & ~event) | BYPASS_WE | action;
216 [ # # ]: 0 : 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 [ # # ]: 0 : if ((cmd & BYPASS_PAGE_M) == BYPASS_PAGE_CTL0) {
221 : : verify = BYPASS_PAGE_CTL0;
222 : : do {
223 [ # # ]: 0 : if (count++ > 5)
224 : : return IXGBE_BYPASS_FW_WRITE_FAILURE;
225 : :
226 [ # # ]: 0 : if (ixgbe_bypass_rw_generic(hw, verify, &by_ctl))
227 : : return IXGBE_ERR_INVALID_ARGUMENT;
228 [ # # ]: 0 : } while (!ixgbe_bypass_valid_rd_generic(cmd, by_ctl));
229 : : } else {
230 : : /* We have give the FW time for the write to stick */
231 : 0 : 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 : 0 : 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 : 0 : cmd |= (addr << BYPASS_CTL2_OFFSET_SHIFT) & BYPASS_CTL2_OFFSET_M;
253 [ # # ]: 0 : 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 : 0 : msleep(100);
258 : :
259 : : /* now read the results */
260 : 0 : cmd &= ~BYPASS_WE;
261 [ # # ]: 0 : if (ixgbe_bypass_rw_generic(hw, cmd, &status))
262 : : return IXGBE_ERR_INVALID_ARGUMENT;
263 : :
264 : 0 : *value = status & BYPASS_CTL2_DATA_M;
265 : :
266 : 0 : return 0;
267 : : }
268 : :
269 : : #endif /* RTE_LIBRTE_IXGBE_BYPASS */
270 : :
271 : : #endif /* _IXGBE_BYPASS_API_H_ */
|