xref: /illumos-gate/usr/src/uts/common/io/bnxe/577xx/drivers/common/lm/device/lm_util.c (revision d14abf155341d55053c76eeec58b787a456b753b)
1 /*******************************************************************************
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  *
21  * Copyright 2014 QLogic Corporation
22  * The contents of this file are subject to the terms of the
23  * QLogic End User License (the "License").
24  * You may not use this file except in compliance with the License.
25  *
26  * You can obtain a copy of the License at
27  * http://www.qlogic.com/Resources/Documents/DriverDownloadHelp/
28  * QLogic_End_User_Software_License.txt
29  * See the License for the specific language governing permissions
30  * and limitations under the License.
31  *
32  *
33  * Module Description:
34  *      This file contains general LM utility functions
35  *
36  ******************************************************************************/
37 
38 #include "lm5710.h"
39 
40 #ifdef _VBD_CMD_
41 #include "everest_sim.h"
42 #endif
43 
44 #define MASK_01010101 (((unsigned int)(-1))/3)
45 #define MASK_00110011 (((unsigned int)(-1))/5)
46 #define MASK_00001111 (((unsigned int)(-1))/17)
47 
count_bits(u32_t n)48 u32_t count_bits(u32_t n)
49 {
50     n = (n & MASK_01010101) + ((n >> 1) & MASK_01010101) ;
51     n = (n & MASK_00110011) + ((n >> 2) & MASK_00110011) ;
52     n = (n & MASK_00001111) + ((n >> 4) & MASK_00001111) ;
53 
54     return n % 255 ;
55 }
56 
log2_align(unsigned long n)57 unsigned long log2_align(unsigned long n)
58 {
59     unsigned long ret = n ? 1 : 0;
60     unsigned long _n  = n >> 1;
61 
62     while (_n)
63     {
64         _n >>= 1;
65         ret <<= 1;
66     }
67 
68     if (ret < n)
69         ret <<= 1;
70 
71     return ret;
72 }
73 /**
74  * @description
75  * Should be moved to a common file.
76  * Calculates the lower align of power 2.
77  * Values lower than 0 are returned directly.
78  * @param n
79  *
80  * @return unsigned long
81  * lower align of power 2.
82  */
power2_lower_align(unsigned long n)83 unsigned long power2_lower_align(unsigned long n)
84 {
85     unsigned long ret = 0;
86     if(0 == n)
87     {
88         return 0;
89     }
90 
91     if(TRUE == POWER_OF_2(n))
92     {
93         // The number is already a power of 2.
94         return n;
95     }
96 
97     //Calculates the lower align of power 2.
98     ret = log2_align(n);
99     DbgBreakIf(FALSE == POWER_OF_2(ret));
100     ret >>= 1;
101 
102     return ret;
103 }
104 /*
105 Log2
106 this function calculates rounded LOG2 of a certain number
107 e.g.: LOG2(1080) = 10 (2^10=1024)
108 */
LOG2(u32_t v)109 u32_t LOG2(u32_t v){
110     u32_t r=0;
111     while (v >>= 1) {
112         r++;
113     }
114     return r;
115 }
116 
117 /**
118  * @description
119  *  Should be moved to a common place.
120  *  Find the next power of 2 that is larger than "num".
121  * @param num - The variable to find a power of 2 that is
122  *            larger.
123  * @param num_bits_supported - The largest number of bits
124  *                           supported
125  *
126  * @return u32_t - The next power of 2 that is larger than
127  *         "num".
128  */
129 u32_t
upper_align_power_of_2(IN const u16_t num,IN const u8_t num_bits_supported)130 upper_align_power_of_2(IN const u16_t num,
131                        IN const u8_t num_bits_supported)
132 {
133     u32_t const largest_power_of_2 = 1 << (num_bits_supported - 1);
134     u32_t prev_power_of_2 = largest_power_of_2;
135     u32_t cur_power_of_2 = 0;
136     u8_t  i = 0;
137 
138     //This is not realy needed (the for also handles this case) but to avoide confusing
139     if(num >= largest_power_of_2)
140     {
141         DbgBreakMsg("num is larger than num_bits_supported");
142         return largest_power_of_2;
143     }
144     // Exception case
145     if(0 == num)
146     {
147         return 1;
148     }
149 
150     // Look for a value that is smaller than prev_power_of_2 and bigger than cur_power_of_2
151     for (i = (num_bits_supported - 1) ; i != 0 ;i--)
152     {
153         cur_power_of_2 = 1 << (i);
154         if(num > cur_power_of_2)
155         {
156             break;
157         }
158         prev_power_of_2 = cur_power_of_2;
159     }
160     return prev_power_of_2;
161 }
162 
163 /**
164  * General function that waits for a certain state to change,
165  * not protocol specific. It takes into account vbd-commander
166  * and reset-is-in-progress
167  *
168  * @param pdev
169  * @param curr_state -> what to poll on
170  * @param new_state -> what we're waiting for
171  *
172  * @return lm_status_t TIMEOUT if state didn't change, SUCCESS
173  *         otherwise
174  */
175 
176 
177 /**
178  * @param pdev
179  *
180  * @return 0 if device is ASIC.
181  */
lm_chip_is_slow(struct _lm_device_t * pdev)182 int lm_chip_is_slow(struct _lm_device_t *pdev)
183 {
184     u32_t val = 0;
185 
186     lm_reg_rd_ind(pdev, MISC_REG_CHIP_REV, &val);
187 
188     val = (val & 0xf) << 12;
189 
190     if (val > CHIP_REV_Cx) {
191         DbgMessage(pdev, VERBOSEi, "Chip is slow\n");
192         return 1;
193     } else {
194         return 0;
195     }
196 }
197 
lm_wait_state_change(struct _lm_device_t * pdev,volatile u32_t * curr_state,u32_t new_state)198 lm_status_t lm_wait_state_change(struct _lm_device_t *pdev, volatile u32_t * curr_state, u32_t new_state)
199 {
200     u32_t delay_us = 0;
201     u32_t to_cnt   = 10000 + 2360; // We'll wait 10,000 times 100us (1 second) + 2360 times 25000us (59sec) = total 60 sec
202                                                                     // (Winodws only note) the 25000 wait will cause wait to be without CPU stall (look in win_util.c)
203     lm_status_t lm_status = LM_STATUS_SUCCESS;
204 
205 
206 #ifdef _VBD_CMD_
207     if (!GET_FLAGS(*g_everest_sim_flags_ptr, EVEREST_SIM_RAMROD))
208     {
209         *curr_state = new_state;
210         return lm_status;
211     }
212 #endif
213 
214 
215     /* wait for state change */
216     while ((*curr_state != new_state) && to_cnt--)
217     {
218         delay_us = (to_cnt >= 2360) ? 100 : 25000 ;
219         mm_wait(pdev, delay_us);
220 
221         #ifdef DOS
222             sleep(0); // rescheduling threads, since we don't have a memory barrier.
223         #elif defined(__LINUX)
224             mm_read_barrier(); // synchronize on eth_con->con_state
225         #endif
226 
227         // in case reset in progress
228         // we won't get completion so no need to wait
229         if( lm_reset_is_inprogress(pdev) )
230         {
231             lm_status = LM_STATUS_ABORTED;
232             break;
233         }
234     }
235 
236     if ( *curr_state != new_state)
237     {
238         DbgMessage(pdev, FATAL,
239                     "lm_wait_state_change: state change timeout, curr state=%d, expected new state=%d!\n",
240                     *curr_state, new_state);
241         if (!lm_reset_is_inprogress(pdev)) {
242             #if defined(_VBD_)
243             DbgBreak();
244             #endif
245             lm_status = LM_STATUS_TIMEOUT;
246         }
247     }
248 
249     return lm_status;
250 }
251 
252 /*******************************************************************************
253  * Description:
254  *         Calculates crc 32 on a buffer
255  *         Note: crc32_length MUST be aligned to 8
256  * Return:
257  ******************************************************************************/
calc_crc32(u8_t * crc32_packet,u32_t crc32_length,u32_t crc32_seed,u8_t complement)258 u32_t calc_crc32( u8_t* crc32_packet, u32_t crc32_length, u32_t crc32_seed, u8_t complement)
259 {
260    u32_t byte             = 0 ;
261    u32_t bit              = 0 ;
262    u8_t  msb              = 0 ; // 1
263    u32_t temp             = 0 ;
264    u32_t shft             = 0 ;
265    u8_t  current_byte     = 0 ;
266    u32_t crc32_result     = crc32_seed;
267    const u32_t CRC32_POLY = 0x1edc6f41;
268     if( CHK_NULL( crc32_packet) || ERR_IF( 0 == crc32_length ) || ERR_IF( 0 != ( crc32_length % 8 ) ) )
269     {
270         return crc32_result ;
271     }
272     for (byte = 0; byte < crc32_length; byte = byte + 1)
273     {
274         current_byte = crc32_packet[byte];
275         for (bit = 0; bit < 8; bit = bit + 1)
276         {
277             msb = (u8_t)(crc32_result >> 31) ; // msb = crc32_result[31];
278             crc32_result = crc32_result << 1;
279             if ( msb != ( 0x1 & (current_byte>>bit)) ) // (msb != current_byte[bit])
280             {
281                crc32_result = crc32_result ^ CRC32_POLY;
282                crc32_result |= 1 ;//crc32_result[0] = 1;
283             }
284          }
285       }
286       // Last step is to "mirror" every bit, swap the 4 bytes, and then complement each bit.
287       //
288       // Mirror:
289       temp = crc32_result ;
290       shft = sizeof(crc32_result) * 8 -1 ;
291       for( crc32_result>>= 1; crc32_result; crc32_result>>= 1 )
292       {
293         temp <<= 1;
294         temp  |= crc32_result & 1;
295         shft-- ;
296       }
297       temp <<= shft ;
298       //temp[31-bit] = crc32_result[bit];
299       // Swap:
300       // crc32_result = {temp[7:0], temp[15:8], temp[23:16], temp[31:24]};
301       {
302           u32_t t0, t1, t2, t3 ;
303           t0 = ( ( 0x000000ff ) & ( temp >> 24 ) ) ; // temp >> 24 ;
304           t1 = ( ( 0x0000ff00 ) & ( temp >> 8 ) ) ;
305           t2 = ( ( 0x00ff0000 ) & ( temp << 8 ) ) ;
306           t3 = ( ( 0xff000000 ) & ( temp << 24 ) ) ;
307           crc32_result = t0 | t1 | t2 | t3 ;
308       }
309       // Complement:
310       if (complement)
311       {
312           crc32_result = ~crc32_result ;
313       }
314       return crc32_result  ;
315 }
316 
317 /**
318  *  @brief: convert 4 bytes version into 32 bit BCD formatted version
319  *
320  *  1. Format the product_version string:
321  *     a. The "Major, "Minor, "Build and "Sub build" bytes are BCD-encoded, and each byte holds two BCD digits.
322  *     b. The semantics of these fields follow the semantics specified in DSP4004.
323  *     c. The value 0xF in the most-significant nibble of a BCD-encoded value indicates that the most significant nibble should be ignored and the overall field treated as a single digit value.
324  *     d. A value of 0xFF indicates that the entire field is not present. 0xFF is not allowed as a value for the fields.
325  *     Example: Version 3.7.10.FF --> 0xF3F710FF
326  *
327 
328  * @param[in] CONST u8_t IN ver_arr[4]
329  *
330  * @return u32_t value
331  */
332 u32_t
convert_to_bcd(const u8_t IN ver_arr[4])333 convert_to_bcd( const u8_t IN ver_arr[4] )
334 {
335     u32_t                 ver_32             = 0xffffffff;
336     u8_t                  idx                = 0;
337     u8_t                  ver_current        = 0;
338 
339     if ( ver_arr )
340     {
341         ver_32 = 0;
342 
343         // convert to BCD format
344         // We have for sure 4 digits only
345         // ARRSIZE(ver_arr) won't work here since in non x86 compile it is NOT 4....
346         for( idx = 0; idx < 4; idx++ )
347         {
348             ver_current = ver_arr[idx];
349             if ( 0 == ( ver_current & 0xf0 ) )
350             {
351                 ver_current |= 0xf0 ;
352             }
353             ver_32 =  ( ver_32<<8 ) | ver_current ;
354         }
355     }
356 
357     return ver_32;
358 }
359