1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2014 Intel Corporation
5 #ifndef _IXGBE_BYPASS_API_H_
6 #define _IXGBE_BYPASS_API_H_
8 #ifdef RTE_LIBRTE_IXGBE_BYPASS
10 #include "ixgbe_bypass_defines.h"
12 * ixgbe_bypass_rw_generic - Bit bang data into by_pass FW
14 * @hw: pointer to hardware structure
15 * @cmd: Command we send to the FW
16 * @status: The reply from the FW
18 * Bit-bangs the cmd to the by_pass FW status points to what is returned.
20 #define IXGBE_BYPASS_BB_WAIT 1
21 static s32 ixgbe_bypass_rw_generic(struct ixgbe_hw *hw, u32 cmd, u32 *status)
24 u32 sck, sdi, sdo, dir_sck, dir_sdi, dir_sdo;
28 return IXGBE_ERR_PARAM;
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;
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;
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;
61 return IXGBE_ERR_DEVICE_NOT_SUPPORTED;
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 */
71 IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
72 IXGBE_WRITE_FLUSH(hw);
74 msleep(IXGBE_BYPASS_BB_WAIT);
76 /* Generate start condition */
78 IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
79 IXGBE_WRITE_FLUSH(hw);
80 msleep(IXGBE_BYPASS_BB_WAIT);
83 IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
84 IXGBE_WRITE_FLUSH(hw);
85 msleep(IXGBE_BYPASS_BB_WAIT);
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) {
91 IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
94 IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
96 IXGBE_WRITE_FLUSH(hw);
97 msleep(IXGBE_BYPASS_BB_WAIT);
100 IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
101 IXGBE_WRITE_FLUSH(hw);
102 msleep(IXGBE_BYPASS_BB_WAIT);
105 IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
106 IXGBE_WRITE_FLUSH(hw);
107 msleep(IXGBE_BYPASS_BB_WAIT);
109 esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
111 *status = (*status << 1) | 0x01;
113 *status = (*status << 1) | 0x00;
114 msleep(IXGBE_BYPASS_BB_WAIT);
120 IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
121 IXGBE_WRITE_FLUSH(hw);
122 msleep(IXGBE_BYPASS_BB_WAIT);
125 IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
126 IXGBE_WRITE_FLUSH(hw);
128 /* set the page bits to match the cmd that the status it belongs to */
129 *status = (*status & 0x3fffffff) | (cmd & 0xc0000000);
135 * ixgbe_bypass_valid_rd_generic - Verify valid return from bit-bang.
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.
143 * @u32 in_reg - The register cmd for the bit-bang read.
144 * @u32 out_reg - The register returned from a bit-bang read.
146 static bool ixgbe_bypass_valid_rd_generic(u32 in_reg, u32 out_reg)
150 /* Page must match for all control pages */
151 if ((in_reg & BYPASS_PAGE_M) != (out_reg & BYPASS_PAGE_M))
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
160 mask = BYPASS_AUX_ON_M | BYPASS_MAIN_ON_M |
161 BYPASS_MAIN_OFF_M | BYPASS_AUX_OFF_M |
164 if ((out_reg & mask) != (in_reg & mask))
167 /* 0x0 is never a valid value for bypass status */
168 if (!(out_reg & BYPASS_STATUS_OFF_M))
171 case BYPASS_PAGE_CTL1:
172 /* All the following can't change since the last write
174 * - time we last sent
176 mask = BYPASS_CTL1_VALID_M | BYPASS_CTL1_TIME_M;
177 if ((out_reg & mask) != (in_reg & mask))
180 case BYPASS_PAGE_CTL2:
181 /* All we can check in this page is control number
182 * which is already done above.
187 /* We are as sure as we can be return true */
192 * ixgbe_bypass_set_generic - Set a bypass field in the FW CTRL Regiter.
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)
202 static s32 ixgbe_bypass_set_generic(struct ixgbe_hw *hw, u32 ctrl, u32 event,
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;
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;
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;
224 return IXGBE_BYPASS_FW_WRITE_FAILURE;
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));
230 /* We have give the FW time for the write to stick */
238 * ixgbe_bypass_rd_eep_generic - Read the bypass FW eeprom address.
240 * @hw: pointer to hardware structure
241 * @addr: The bypass eeprom address to read.
242 * @value: The 8b of data at the address above.
244 static s32 ixgbe_bypass_rd_eep_generic(struct ixgbe_hw *hw, u32 addr, u8 *value)
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;
256 /* We have give the FW time for the write to stick */
259 /* now read the results */
261 if (ixgbe_bypass_rw_generic(hw, cmd, &status))
262 return IXGBE_ERR_INVALID_ARGUMENT;
264 *value = status & BYPASS_CTL2_DATA_M;
269 #endif /* RTE_LIBRTE_IXGBE_BYPASS */
271 #endif /* _IXGBE_BYPASS_API_H_ */