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 functions that handle direct HW access
35  *
36  ******************************************************************************/
37 
38 #include "lm5710.h"
39 #include "hw_dump.h"
40 #include "577xx_int_offsets.h"
41 
42 /* not in hsi */
43 void ecore_init_cmng(const struct cmng_init_input *input_data,
44                               struct cmng_init *ram_data);
45 
46 void ecore_init_max_per_vn(u16_t vnic_max_rate,
47                              struct rate_shaping_vars_per_vn *ram_data);
48 
49 /*The NIG mirror is only used in VMChimney in MF/SI mode.
50   In this mode, we assume that the driver in the host OS loads
51   first, and allocates offset 0 in the NIG for it's own MAC address,
52   so we don't use it. Also, iSCSI has a reserved entry in the NIG, so
53   we don't use that either.
54   */
55 #define IS_VALID_NIG_IDX(_idx) ((_idx != ECORE_LLH_CAM_ETH_LINE) && (_idx != ECORE_LLH_CAM_ISCSI_ETH_LINE))
56 #define INVALID_NIG_OFFSET ((u8_t)-1)
57 
58 // initialize congestion managmet params
lm_cmng_init(struct _lm_device_t * pdev,u32_t port_rate)59 void lm_cmng_init(struct _lm_device_t *pdev, u32_t port_rate)
60 {
61     u8_t                   vnic                       = 0;
62     u32_t                  i                          = 0;
63     u32_t*                 buf                        = NULL;
64     u8_t                   all_zero                   = 0;
65     u8_t                   num_vnics                  = pdev->params.vnics_per_port;
66     const u8_t             b_afex_and_non_pmf         = IS_MF_AFEX_MODE(pdev) && (!IS_PMF(pdev));
67     const u8_t             port_id                    = PORT_ID(pdev); // TBD: E1H - cmng params are currently per port, may change to be per function
68     const u8_t             vnic_id                    = VNIC_ID(pdev);
69     static const u8_t      DEF_MIN_RATE               = 1      ; /* default MIN rate in case VNIC min rate is configured to zero- 100Mbps */
70     struct cmng_init_input input_data                 = {0};
71     struct cmng_init       ram_data                   = {{{0}}};
72 
73     if(IS_MULTI_VNIC(pdev) && pdev->params.cmng_enable)
74     {
75         SET_FLAGS(input_data.flags.cmng_enables, CMNG_FLAGS_PER_PORT_RATE_SHAPING_VN);
76         input_data.port_rate = port_rate;
77 
78         all_zero = TRUE;
79         for (vnic = 0 ; vnic < num_vnics ; vnic++)
80         {
81             input_data.vnic_max_rate[vnic] = lm_get_max_bw(pdev,
82                                                            port_rate,
83                                                            vnic);
84 
85             if (!GET_FLAGS(pdev->hw_info.mf_info.func_mf_cfg , FUNC_MF_CFG_FUNC_HIDE))
86             {
87                 if (pdev->hw_info.mf_info.min_bw[vnic] == 0)
88                 {
89                     input_data.vnic_min_rate[vnic] = DEF_MIN_RATE;
90                 }
91                 else
92                 {
93                     input_data.vnic_min_rate[vnic] = pdev->hw_info.mf_info.min_bw[vnic];
94                     all_zero = FALSE;
95                 }
96             }
97         }
98 
99         // IS_DCB_ENABLED isn't updated when this function is called from lm_init_intmem_port
100         // but it is called each time the link is up.
101         if (!(all_zero || LM_DCBX_ETS_IS_ENABLED(pdev)))
102         {
103             SET_FLAGS(input_data.flags.cmng_enables,CMNG_FLAGS_PER_PORT_FAIRNESS_VN);
104         }
105 
106         if( b_afex_and_non_pmf )
107         {
108             ecore_init_max_per_vn( input_data.vnic_max_rate[vnic_id], &ram_data.vnic.vnic_max_rate[vnic_id] );
109         }
110         else
111         {
112             ecore_init_cmng(&input_data,&ram_data);
113         }
114     }
115 
116     // store per vnic struct to internal memory rs. we store data for all 4 vnics even if there are only 2 vnics, just to
117     // make sure there are known values.
118     for (vnic = 0; vnic < ARRSIZE(ram_data.vnic.vnic_max_rate); vnic++)
119     {
120         buf = (u32_t *)&ram_data.vnic.vnic_max_rate[vnic];
121         ASSERT_STATIC(0 == sizeof(ram_data.vnic.vnic_max_rate[vnic]) % 4);
122 
123         if( b_afex_and_non_pmf && (vnic != vnic_id) )
124         {
125             // If AFEX && non pmf we want to write only for the current VNIC
126             continue;
127         }
128 
129         for (i = 0; i < sizeof(ram_data.vnic.vnic_max_rate[vnic])/4; i++)
130         {
131             LM_INTMEM_WRITE32(pdev,XSTORM_RATE_SHAPING_PER_VN_VARS_OFFSET((port_id+2*vnic))+i*4,
132                               buf[i], BAR_XSTRORM_INTMEM);
133         }
134     }
135 
136     if( b_afex_and_non_pmf )
137     {
138         // If AFEX && non pmf we want to write only for the current VNIC
139         // All other writes below are for PMF so we exit in this case.
140         return;
141     }
142 
143     // Store per port struct to internal memory
144     buf = (u32_t *)&ram_data.port.rs_vars;
145     ASSERT_STATIC(0 == (sizeof(ram_data.port.rs_vars) % 4)) ;
146     for (i = 0; i < sizeof(ram_data.port.rs_vars)/4; i++)
147     {
148        LM_INTMEM_WRITE32(pdev,(XSTORM_CMNG_PER_PORT_VARS_OFFSET(port_id) + OFFSETOF(struct cmng_struct_per_port, rs_vars) + i*4),
149                           buf[i], BAR_XSTRORM_INTMEM);
150     }
151 
152     buf = (u32_t *)&ram_data.port.fair_vars;
153     ASSERT_STATIC(0 == (sizeof(ram_data.port.fair_vars) % 4)) ;
154     for (i = 0; i < sizeof(ram_data.port.fair_vars)/4; i++)
155     {
156        LM_INTMEM_WRITE32(pdev,(XSTORM_CMNG_PER_PORT_VARS_OFFSET(port_id) + OFFSETOF(struct cmng_struct_per_port, fair_vars) + i*4),
157                           buf[i], BAR_XSTRORM_INTMEM);
158     }
159 
160     buf = (u32_t *)&ram_data.port.flags;
161     ASSERT_STATIC(0 == (sizeof(ram_data.port.flags) % 4));
162     for (i = 0; i < sizeof(ram_data.port.flags)/4; i++)
163     {
164        LM_INTMEM_WRITE32(pdev,(XSTORM_CMNG_PER_PORT_VARS_OFFSET(port_id) + OFFSETOF(struct cmng_struct_per_port, flags) + i*4),
165                           buf[i], BAR_XSTRORM_INTMEM);
166     }
167 
168     // store per vnic struct to internal memory fair. we store data for all 4 vnics even if there are only 2 vnics, just to
169     //make sure there are known values.
170     for (vnic = 0; vnic < ARRSIZE(ram_data.vnic.vnic_min_rate); vnic++)
171     {
172         buf = (u32_t *)&ram_data.vnic.vnic_min_rate[vnic];
173         ASSERT_STATIC(0 == sizeof(ram_data.vnic.vnic_min_rate[vnic]) % 4);
174         for (i = 0; i < sizeof(ram_data.vnic.vnic_min_rate[vnic])/4; i++)
175         {
176             LM_INTMEM_WRITE32(pdev,XSTORM_FAIRNESS_PER_VN_VARS_OFFSET((port_id+2*vnic))+i*4,
177                               buf[i], BAR_XSTRORM_INTMEM);
178         }
179     }
180 
181 } /* lm_cmng_init */
182 
183 /**initialize_nig_entry
184  * Initialize a NIG mirror entry to a given MAC address. Note -
185  * the entrie's reference count remains 0.
186  *
187  * @param pdev
188  * @param offset the index of the NIG entry
189  * @param addr the MAC address to use
190  *
191  * @return lm_status_t LM_STATUS_SUCCESS on success, some other
192  *         failure code on failure.
193  */
lm_initialize_nig_entry(lm_device_t * pdev,u8_t offset,u8_t * addr)194 static lm_status_t lm_initialize_nig_entry(
195     lm_device_t *pdev,
196     u8_t         offset,
197     u8_t        *addr)
198 {
199     lm_nig_mirror_entry_t* entry = &pdev->vars.nig_mirror.entries[offset];
200     DbgBreakIf(entry->refcnt != 0);
201     mm_memcpy(entry->addr, addr, ARRSIZE(entry->addr));
202     return LM_STATUS_SUCCESS;
203 }
204 
205 /**get_available_nig_entry
206  * Find a NIG entry that's not in use. Entry 0 and 15 are never
207  * considered available, since they are used by iSCSI and by the
208  * L2 client.
209  *
210  * @param pdev
211  *
212  * @return an index to a usable NIG entry, or INVALID_NIG_OFFSET
213  *         if there aren't any available entries.
214  */
lm_get_available_nig_entry(lm_device_t * pdev)215 static u8_t lm_get_available_nig_entry(lm_device_t *pdev)
216 {
217     u8_t i;
218     lm_nig_mirror_t *nig_mirror = &pdev->vars.nig_mirror;
219 
220     for (i=0; i<ARRSIZE(nig_mirror->entries); ++i)
221     {
222         if (IS_VALID_NIG_IDX(i) &&
223             (nig_mirror->entries[i].refcnt == 0))
224         {
225             return i;
226         }
227     }
228     return INVALID_NIG_OFFSET;
229 }
230 
231 /**find_nig_entry_for_addr
232  * Find the entry for a given MAC address in the nig.
233  *
234  * @param pdev
235  * @param addr the MAC address to look for
236  *
237  * @return u8_t the index of the NIG entry that contains the
238  *         given MAC address, or INVALID_NIG_OFFSET if no such
239  *         entry exists.
240  */
lm_find_nig_entry_for_addr(lm_device_t * pdev,u8_t * addr)241 static u8_t lm_find_nig_entry_for_addr(
242     lm_device_t *pdev,
243     u8_t        *addr)
244 {
245     u8_t i;
246     lm_nig_mirror_t *nig_mirror = &pdev->vars.nig_mirror;
247     lm_nig_mirror_entry_t* cur_entry = NULL;
248 
249     for (i=0; i<ARRSIZE(nig_mirror->entries); ++i)
250     {
251         cur_entry = &nig_mirror->entries[i];
252         if ( (cur_entry->refcnt > 0) &&
253              (mm_memcmp(cur_entry->addr, addr, ARRSIZE(cur_entry->addr))) )
254         {
255             return i;
256         }
257     }
258     return INVALID_NIG_OFFSET;
259 }
260 
lm_insert_nig_entry(lm_device_t * pdev,u8_t * addr)261 lm_status_t lm_insert_nig_entry(
262     lm_device_t *pdev,
263     u8_t        *addr)
264 {
265     u8_t offset = 0;
266     lm_status_t lm_status = LM_STATUS_SUCCESS;
267 
268     offset = lm_find_nig_entry_for_addr(pdev, addr);
269 
270     if (offset == INVALID_NIG_OFFSET)
271     {
272         /*If there was no entry for this MAC, insert it to an available slot and call lm_set_mac_in_nig.*/
273         offset = lm_get_available_nig_entry(pdev);
274         if (offset == INVALID_NIG_OFFSET)
275         {
276             return LM_STATUS_RESOURCE; //no available NIG entry.
277         }
278 
279         lm_status = lm_initialize_nig_entry(pdev, offset, addr);
280         DbgBreakIf (lm_status != LM_STATUS_SUCCESS);
281 
282         lm_status = lm_set_mac_in_nig(pdev, addr, LM_CLI_IDX_NDIS, offset);
283         if (lm_status != LM_STATUS_SUCCESS)
284         {
285             return lm_status;
286         }
287     }
288 
289     NIG_ENTRY_INC_REFCNT(&pdev->vars.nig_mirror.entries[offset]);
290 
291     return lm_status;
292 }
293 
294 /**remove_nig_entry
295  * Dereference the entry for a given MAC address. If this was
296  * the last reference the MAC address is removed from the NIG.
297  *
298  * @param pdev
299  * @param addr the MAC address
300  *
301  * @return lm_status_t LM_STATUS_SUCCESS on success,
302  *         LM_STATUS_FAILURE if the given MAC is not in the NIG,
303  *         other failure codes on other errors.
304  */
lm_remove_nig_entry(lm_device_t * pdev,u8_t * addr)305 lm_status_t lm_remove_nig_entry(
306     lm_device_t *pdev,
307     u8_t        *addr)
308 {
309     u8_t offset = 0;
310     lm_status_t lm_status = LM_STATUS_SUCCESS;
311     lm_nig_mirror_entry_t* entry = NULL;
312 
313     offset = lm_find_nig_entry_for_addr(pdev, addr);
314     if (offset == INVALID_NIG_OFFSET)
315     {
316         DbgBreakIf(offset == INVALID_NIG_OFFSET); //trying to remove an address that isn't in the NIG.
317         return LM_STATUS_FAILURE;
318     }
319 
320     entry = &pdev->vars.nig_mirror.entries[offset];
321 
322     NIG_ENTRY_DEC_REFCNT(entry);
323 
324     if (entry->refcnt == 0)
325     {
326         lm_status = lm_set_mac_in_nig(pdev, NULL, LM_CLI_IDX_NDIS, offset);
327         if (lm_status != LM_STATUS_SUCCESS)
328         {
329             return lm_status;
330         }
331         mm_mem_zero(entry->addr, sizeof(entry->addr));
332     }
333 
334     return lm_status;
335 }
336 
lm_setup_fan_failure_detection(struct _lm_device_t * pdev)337 void lm_setup_fan_failure_detection(struct _lm_device_t *pdev)
338 {
339     u32_t             val = 0;
340     lm_status_t lm_status = LM_STATUS_SUCCESS;
341     u8_t             port = 0;
342     u8_t      is_required = FALSE;
343     u32            offset = 0;
344 
345     offset = OFFSETOF(shmem_region_t, dev_info.shared_hw_config.config2) ;
346 
347     LM_SHMEM_READ(pdev, offset, &val);
348 
349     val &= SHARED_HW_CFG_FAN_FAILURE_MASK;
350 
351     switch(val)
352     {
353     case SHARED_HW_CFG_FAN_FAILURE_PHY_TYPE:
354         {
355             /*
356              * The fan failure mechanism is usually related to the PHY type since
357              * the power consumption of the board is effected by the PHY. Currently,
358              * fan is required for most designs with SFX7101, BCM8727 and BCM8481.
359              */
360             for (port = PORT_0; port < PORT_MAX; port++)
361             {
362                 is_required |= elink_fan_failure_det_req(pdev, pdev->hw_info.shmem_base, pdev->hw_info.shmem_base2, port);
363             }
364         }
365         break;
366 
367     case SHARED_HW_CFG_FAN_FAILURE_ENABLED:
368         is_required = TRUE;
369         break;
370 
371     case SHARED_HW_CFG_FAN_FAILURE_DISABLED:
372     default:
373         break;
374     }
375 
376     DbgMessage(pdev, WARN, "lm_setup_fan_failure_detection: cfg=0x%x is_required=%d\n", val, is_required );
377 
378     if (!is_required)
379     {
380         return;
381     }
382 
383     // read spio5 in order to make it input collaterally - we don't care of the returned value
384     // MCP does the same
385     lm_status = lm_spio_read( pdev, 5, &val ) ;
386     if( LM_STATUS_SUCCESS != lm_status )
387     {
388         DbgBreakIf(1) ;
389     }
390 
391     // We write here since value changes from 1 to 0
392     val = REG_RD(pdev,MISC_REG_SPIO_INT) ;
393     val |= (1<<(16+5)) ;
394     REG_WR(pdev,MISC_REG_SPIO_INT, val ) ;
395 
396     // enable the SPIO_INT 5 to signal the IGU
397     val = REG_RD(pdev,MISC_REG_SPIO_EVENT_EN) ;
398     val |= (1<<5) ;
399     REG_WR(pdev,MISC_REG_SPIO_EVENT_EN, val ) ;
400 }
401 
402 /*
403  *------------------------------------------------------------------------
404  * lm_gpio_read -
405  *
406  * Read the value of the requested GPIO pin (with pin_num)
407  *
408  *------------------------------------------------------------------------
409  */
lm_gpio_read(struct _lm_device_t * pdev,u32_t pin_num,u32_t * value_ptr,u8_t port)410 lm_status_t lm_gpio_read(struct _lm_device_t *pdev, u32_t pin_num, u32_t* value_ptr, u8_t port)
411 {
412     u32_t reg_val       = 0;
413     u32_t gpio_port     = 0;
414     u32_t mask          = 0;
415     u32_t swap_val      = 0;
416     u32_t swap_override = 0;
417 
418     if ( CHK_NULL(pdev) || CHK_NULL(value_ptr) )
419     {
420         DbgBreakIf(!pdev);
421         DbgBreakIf(!value_ptr);
422         return LM_STATUS_INVALID_PARAMETER ;
423     }
424 
425     if (pin_num > MISC_REGISTERS_GPIO_3)
426     {
427         DbgMessage(pdev, FATAL , "Invalid pin_num GPIO %d\n", pin_num);
428         return LM_STATUS_INVALID_PARAMETER;
429     }
430 
431     /* The GPIO should be swapped if the swap register is set and active */
432     swap_val      = REG_RD(pdev,  NIG_REG_PORT_SWAP);
433     swap_override = REG_RD(pdev,  NIG_REG_STRAP_OVERRIDE);
434 
435 
436     // define port upon swap
437     gpio_port = (swap_val && swap_override) ^ port;
438 
439     // Get the current port number (0 or 1)
440     if (gpio_port > 1)
441     {
442         return LM_STATUS_FAILURE;
443     }
444 
445     // Calculate the value with relevent OE set to 1 (for input).
446     // Calulate the mask for the read value.
447     if (gpio_port == 0)
448     {
449         switch (pin_num)
450         {
451             case 0:
452                 mask = GRC_MISC_REGISTERS_GPIO_PORT0_VAL0;
453                 break;
454             case 1:
455                 mask = GRC_MISC_REGISTERS_GPIO_PORT0_VAL1;
456                 break;
457             case 2:
458                 mask = GRC_MISC_REGISTERS_GPIO_PORT0_VAL2;
459                 break;
460             case 3:
461                 mask = GRC_MISC_REGISTERS_GPIO_PORT0_VAL3;
462                 break;
463             default:
464                 break;
465         }
466     }
467     // Calculate the value with relevent OE set to 1 (for input).
468     // Calulate the mask for the read value.
469     if (gpio_port == 1)
470     {
471         switch (pin_num)
472         {
473             case 0:
474                 mask = GRC_MISC_REGISTERS_GPIO_PORT1_VAL0;
475                 break;
476             case 1:
477                 mask = GRC_MISC_REGISTERS_GPIO_PORT1_VAL1;
478                 break;
479             case 2:
480                 mask = GRC_MISC_REGISTERS_GPIO_PORT1_VAL2;
481                 break;
482             case 3:
483                 mask = GRC_MISC_REGISTERS_GPIO_PORT1_VAL3;
484                 break;
485             default:
486                 break;
487         }
488     }
489 
490     // Read from MISC block the GPIO register
491     reg_val = REG_RD(pdev, MISC_REG_GPIO);
492     DbgMessage(NULL, INFORM, "lm_gpio_read: MISC_REG_GPIO value 0x%x mask 0x%x\n", reg_val, mask);
493 
494     // Get the requested pin value by masking the val with mask
495     if ((reg_val & mask) == mask)
496     {
497         *value_ptr = 1;
498     }
499     else
500     {
501         *value_ptr = 0;
502     }
503     DbgMessage(NULL, INFORM, "lm_gpio_read: pin %d value is %x\n", pin_num, *value_ptr);
504 
505     return LM_STATUS_SUCCESS;
506 }
507 
508 /*
509  *------------------------------------------------------------------------
510  * lm_gpio_write -
511  *
512  * Write a value to the requested GPIO pin (with pin_num)
513  *
514  *------------------------------------------------------------------------
515  */
lm_gpio_write(struct _lm_device_t * pdev,u32_t pin_num,u32_t mode,u8_t port)516 lm_status_t lm_gpio_write(struct _lm_device_t *pdev, u32_t pin_num, u32_t mode, u8_t port)
517 {
518     u32_t gpio_port     = 0;
519     u32_t gpio_shift    = 0;
520     u32_t gpio_mask     = 0;
521     u32_t gpio_reg      = 0;
522     u32_t swap_val      = 0;
523     u32_t swap_override = 0;
524 
525     if( CHK_NULL(pdev) )
526     {
527         DbgBreakIf(!pdev);
528         return LM_STATUS_INVALID_PARAMETER ;
529     }
530     if (pin_num > MISC_REGISTERS_GPIO_3)
531     {
532     DbgMessage(pdev, FATAL , "lm_gpio_write: Invalid pin_num GPIO %d\n", pin_num);
533     return LM_STATUS_INVALID_PARAMETER;
534     }
535 
536     /* The GPIO should be swapped if the swap register is set and active */
537     swap_val      = REG_RD(pdev,  NIG_REG_PORT_SWAP);
538     swap_override = REG_RD(pdev,  NIG_REG_STRAP_OVERRIDE);
539 
540     // define port upon swap
541     gpio_port = (swap_val && swap_override) ^ port;
542 
543     // Get the current port number (0 or 1)
544     if (gpio_port > 1) {
545     return LM_STATUS_FAILURE;
546     }
547 
548     gpio_shift = pin_num +
549             (gpio_port ? MISC_REGISTERS_GPIO_PORT_SHIFT : 0);
550 
551     gpio_mask = (1 << gpio_shift);
552 
553     // lock before read
554     lm_hw_lock(pdev, HW_LOCK_RESOURCE_GPIO, TRUE);
555 
556     /* read GPIO and mask except the float bits */
557     gpio_reg = (REG_RD(pdev, MISC_REG_GPIO) & MISC_REGISTERS_GPIO_FLOAT);
558 
559     switch (mode) {
560     case MISC_REGISTERS_GPIO_OUTPUT_LOW:
561         DbgMessage(NULL, WARN, "Set GPIO %d (shift %d) -> output low\n", pin_num, gpio_shift);
562         /* clear FLOAT and set CLR */
563         gpio_reg &= ~(gpio_mask << MISC_REGISTERS_GPIO_FLOAT_POS);
564         gpio_reg |=  (gpio_mask << MISC_REGISTERS_GPIO_CLR_POS);
565         break;
566 
567     case MISC_REGISTERS_GPIO_OUTPUT_HIGH:
568         DbgMessage(NULL, WARN, "Set GPIO %d (shift %d) -> output high\n", pin_num, gpio_shift);
569         /* clear FLOAT and set SET */
570         gpio_reg &= ~(gpio_mask << MISC_REGISTERS_GPIO_FLOAT_POS);
571         gpio_reg |=  (gpio_mask << MISC_REGISTERS_GPIO_SET_POS);
572         break;
573 
574     case MISC_REGISTERS_GPIO_INPUT_HI_Z:
575         DbgMessage(NULL, WARN, "Set GPIO %d (shift %d) -> input\n", pin_num, gpio_shift);
576         /* set FLOAT */
577         gpio_reg |= (gpio_mask << MISC_REGISTERS_GPIO_FLOAT_POS);
578         break;
579 
580     default:
581         break;
582     }
583 
584     REG_WR(pdev, MISC_REG_GPIO, gpio_reg);
585     lm_hw_unlock(pdev, HW_LOCK_RESOURCE_GPIO);
586 
587     return LM_STATUS_SUCCESS;
588 
589 
590 }
591 
592 /*
593  *------------------------------------------------------------------------
594  * lm_gpio_mult_write -
595  *
596  * Write a value to the requested GPIO pins (bits defined)
597  * User is expected to handle any port swapping and know exactly
598  * which pin(s) to drive.
599  *
600  *------------------------------------------------------------------------
601  */
lm_gpio_mult_write(struct _lm_device_t * pdev,u8_t pins,u32_t mode)602 lm_status_t lm_gpio_mult_write(struct _lm_device_t *pdev, u8_t pins, u32_t mode)
603 {
604     u32_t gpio_reg      = 0;
605     lm_status_t rc      = LM_STATUS_SUCCESS;
606 
607     if( CHK_NULL(pdev) )
608     {
609         DbgBreakIf(!pdev);
610         return LM_STATUS_INVALID_PARAMETER ;
611     }
612     // lock before read
613     lm_hw_lock(pdev, HW_LOCK_RESOURCE_GPIO, TRUE);
614 
615     /* read GPIO and mask except the float bits */
616     gpio_reg = REG_RD(pdev, MISC_REG_GPIO);
617     gpio_reg &= ~(pins << MISC_REGISTERS_GPIO_FLOAT_POS);
618     gpio_reg &= ~(pins << MISC_REGISTERS_GPIO_CLR_POS);
619     gpio_reg &= ~(pins << MISC_REGISTERS_GPIO_SET_POS);
620 
621     switch (mode) {
622     case MISC_REGISTERS_GPIO_OUTPUT_LOW:
623         DbgMessage(NULL, WARN, "Set GPIO 0x%x -> output low\n", pins);
624         /* clear FLOAT and set CLR */
625         gpio_reg |=  (pins << MISC_REGISTERS_GPIO_CLR_POS);
626         break;
627 
628     case MISC_REGISTERS_GPIO_OUTPUT_HIGH:
629         DbgMessage(NULL, WARN, "Set GPIO 0x%x -> output high\n", pins);
630         /* clear FLOAT and set SET */
631         gpio_reg |=  (pins << MISC_REGISTERS_GPIO_SET_POS);
632         break;
633 
634     case MISC_REGISTERS_GPIO_INPUT_HI_Z:
635         DbgMessage(NULL, WARN, "Set GPIO 0x%x -> input\n", pins);
636         /* set FLOAT */
637         gpio_reg |= (pins << MISC_REGISTERS_GPIO_FLOAT_POS);
638         break;
639 
640     default:
641     DbgMessage(pdev, FATAL , "lm_gpio_mult_write: Invalid GPIO mode %d\n", mode);
642     rc = LM_STATUS_INVALID_PARAMETER;
643         break;
644     }
645 
646     if (rc == LM_STATUS_SUCCESS)
647     {
648         REG_WR(pdev, MISC_REG_GPIO, gpio_reg);
649     }
650 
651     lm_hw_unlock(pdev, HW_LOCK_RESOURCE_GPIO);
652 
653     return rc;
654 }
655 
656 /*
657  *------------------------------------------------------------------------
658  * lm_gpio_int_write -
659  *
660  * Set or clear the requested GPIO pin (with pin_num)
661  *
662  *------------------------------------------------------------------------
663  */
664 
lm_gpio_int_write(struct _lm_device_t * pdev,u32_t pin_num,u32_t mode,u8_t port)665 lm_status_t lm_gpio_int_write(struct _lm_device_t *pdev, u32_t pin_num, u32_t mode, u8_t port)
666 {
667     /* The GPIO should be swapped if swap register is set and active */
668     u32_t gpio_port;
669     u32_t gpio_shift ;
670     u32_t gpio_mask;
671     u32_t gpio_reg;
672     u32_t swap_val      = 0;
673     u32_t swap_override = 0;
674 
675     swap_val      = REG_RD(pdev,  NIG_REG_PORT_SWAP);
676     swap_override = REG_RD(pdev,  NIG_REG_STRAP_OVERRIDE);
677     gpio_port     = (swap_val && swap_override ) ^ port;
678     gpio_shift    = pin_num + (gpio_port ? MISC_REGISTERS_GPIO_PORT_SHIFT : 0);
679     gpio_mask     = (1 << gpio_shift);
680 
681     if (pin_num > MISC_REGISTERS_GPIO_3)
682     {
683         DbgMessage(pdev, FATAL , "lm_gpio_write: Invalid pin_num GPIO %d\n", pin_num);
684         return LM_STATUS_INVALID_PARAMETER;
685     }
686 
687     // lock before read
688     lm_hw_lock(pdev, HW_LOCK_RESOURCE_GPIO, TRUE);
689 
690     /* read GPIO int */
691     gpio_reg = REG_RD(pdev, MISC_REG_GPIO_INT);
692 
693     switch (mode)
694     {
695     case MISC_REGISTERS_GPIO_INT_OUTPUT_CLR:
696         DbgMessage(pdev, INFORM, "Clear GPIO INT %d (shift %d) -> output low\n",
697            pin_num, gpio_shift);
698         // clear SET and set CLR
699         gpio_reg &= ~(gpio_mask << MISC_REGISTERS_GPIO_INT_SET_POS);
700         gpio_reg |=  (gpio_mask << MISC_REGISTERS_GPIO_INT_CLR_POS);
701         break;
702 
703     case MISC_REGISTERS_GPIO_INT_OUTPUT_SET:
704         DbgMessage(pdev, INFORM, "Set GPIO INT %d (shift %d) -> output high\n",
705            pin_num, gpio_shift);
706         // clear CLR and set SET
707         gpio_reg &= ~(gpio_mask << MISC_REGISTERS_GPIO_INT_CLR_POS);
708         gpio_reg |=  (gpio_mask << MISC_REGISTERS_GPIO_INT_SET_POS);
709         break;
710 
711     default:
712         break;
713     }
714 
715     REG_WR(pdev, MISC_REG_GPIO_INT, gpio_reg);
716     // unlock after write
717     DbgMessage(pdev, INFORM, "lm_gpio_int_write: pin %d value is %x\n",
718        pin_num, gpio_reg);
719     lm_hw_unlock(pdev, HW_LOCK_RESOURCE_GPIO);
720 
721     return 0;
722 }
723 
724 /*
725  *------------------------------------------------------------------------
726  * lm_spio_read -
727  *
728  * Read the value of the requested SPIO pin (with pin_num)
729  *
730  *------------------------------------------------------------------------
731  */
lm_spio_read(struct _lm_device_t * pdev,u32_t pin_num,u32_t * value_ptr)732 lm_status_t lm_spio_read(struct _lm_device_t *pdev, u32_t pin_num, u32_t* value_ptr)
733 {
734     u32_t reg_val = 0, mask = 0;
735 
736     // Read from MISC block the SPIO register
737     reg_val = REG_RD(pdev, MISC_REG_SPIO);
738 
739     DbgMessage(pdev, INFORM, "lm_spio_read: MISC_REG_SPIO value is 0x%x\n", reg_val);
740 
741     // Calculate the value with relevent OE set to 1 (for input).
742     // Calulate the mask for the read value.
743     switch (pin_num) {
744         case 0:        // SPIO pins 0-2 do not have OE pins
745             mask = MISC_SPIO_EN_VAUX_L;
746             break;
747         case 1:
748             mask = MISC_SPIO_DIS_VAUX_L;
749             break;
750         case 2:
751             mask = MISC_SPIO_SEL_VAUX_L;
752             break;
753         case 3:         // SPIO pin 3 is not connected
754             return LM_STATUS_FAILURE;
755         case 4:        // SPIO pins 4-7 have OE pins
756             reg_val |= (MISC_SPIO_SPIO4 << MISC_SPIO_FLOAT_POS);
757             mask = MISC_SPIO_SPIO4;
758             break;
759         case 5:
760             reg_val |= (MISC_SPIO_SPIO5 << MISC_SPIO_FLOAT_POS);
761             mask = MISC_SPIO_SPIO5;
762             break;
763         case 6:
764             reg_val |= (MISC_SPIO_UMP_ADDR0 << MISC_SPIO_FLOAT_POS);
765             mask = MISC_SPIO_UMP_ADDR0;
766             break;
767         case 7:
768             reg_val |= (MISC_SPIO_UMP_ADDR1 << MISC_SPIO_FLOAT_POS);
769             mask = MISC_SPIO_UMP_ADDR1;
770             break;
771         default:
772             return LM_STATUS_FAILURE;
773     }
774 
775     // Write to SPIO register the value with the relevant OE set to 1
776     REG_WR(pdev, MISC_REG_SPIO, reg_val);
777     DbgMessage(NULL, INFORM, "lm_spio_read: writing MISC_REG_SPIO 0x%x\n", reg_val);
778 
779     // Read from MISC block the SPIO register
780     reg_val = REG_RD(pdev, MISC_REG_SPIO);
781     DbgMessage(NULL, INFORM, "lm_spio_read: MISC_REG_SPIO value 0x%x\n", reg_val);
782 
783     // Get the requested pin value by masking the val with mask
784     if ((reg_val & mask) == mask)
785     {
786         *value_ptr = 1;
787     }
788     else
789     {
790         *value_ptr = 0;
791     }
792     DbgMessage(NULL, INFORM, "lm_spio_read: pin %d value is 0x%x\n", pin_num, *value_ptr);
793 
794     return LM_STATUS_SUCCESS;
795 }
796 
797 /*
798  *------------------------------------------------------------------------
799  * lm_spio_write -
800  *
801  * Write a value to the requested SPIO pin (with pin_num)
802  *
803  *------------------------------------------------------------------------
804  */
lm_spio_write(struct _lm_device_t * pdev,u32_t pin_num,u32_t value)805 lm_status_t lm_spio_write(struct _lm_device_t *pdev, u32_t pin_num, u32_t value)
806 {
807     u32_t       reg_val   = 0;
808     lm_status_t lm_status = LM_STATUS_SUCCESS ;
809 
810     if CHK_NULL(pdev)
811     {
812         DbgBreakIf(!pdev);
813         return LM_STATUS_INVALID_PARAMETER ;
814     }
815 
816     // lock before read
817     lm_hw_lock(pdev, HW_LOCK_RESOURCE_GPIO, TRUE); // The GPIO lock is used for SPIO as well!
818 
819     // Read from MISC block the SPIO register
820     reg_val = REG_RD(pdev, MISC_REG_SPIO);
821     DbgMessage(NULL, INFORM, "lm_gpio_write: MISC_REG_SPIO value is 0x%x\n", reg_val);
822 
823     // Turn the requested SPIO pin to output by setting its OE bit to 0 and
824     // If value is 1 set the relevant SET bit to 1, otherwise set the CLR bit to 1.
825     if (pin_num >= 8 || pin_num == 3) {
826         // SPIO pin 3 is not connected
827         lm_status = LM_STATUS_FAILURE;
828     } else {
829         u32 pin = 1 << pin_num;
830         // Set pin as OUTPUT
831         reg_val &= ~(pin << MISC_SPIO_FLOAT_POS);
832         // Clear the pins CLR and SET bits
833         reg_val &= ~(pin << MISC_SPIO_SET_POS) & ~(pin << MISC_SPIO_CLR_POS);
834         // If value is 1 set the SET bit of this pin, otherwise set the CLR bit.
835         reg_val |= (value == 1) ? (pin << MISC_SPIO_SET_POS) : (pin << MISC_SPIO_CLR_POS);
836     }
837 
838     if( LM_STATUS_SUCCESS == lm_status )
839     {
840         // Write to SPIO register the value with the relevant OE set to 1 and
841         // If value is 1, set the relevant SET bit to 1, otherwise set the CLR bit to 1.
842         REG_WR(pdev, MISC_REG_SPIO, reg_val);
843         DbgMessage(NULL, INFORM, "lm_spio_write: writing MISC_REG_SPIO 0x%x\n", reg_val);
844     }
845 
846     // unlock
847     lm_hw_unlock(pdev, HW_LOCK_RESOURCE_GPIO);
848 
849     return lm_status ;
850 }
851 
852 
853 /*
854  *------------------------------------------------------------------------
855  * lm_set_led_mode -
856  *
857  * Set the led mode of the requested port
858  *
859  *------------------------------------------------------------------------
860  */
lm_set_led_mode(struct _lm_device_t * pdev,u32_t port_idx,u32_t mode_idx)861 lm_status_t lm_set_led_mode(struct _lm_device_t *pdev, u32_t port_idx, u32_t mode_idx)
862 {
863 
864     DbgBreakIf(!pdev);
865 
866     // Write to relevant NIG register LED_MODE (P0 or P1) the mode index (0-15)
867     switch (port_idx) {
868         case 0:
869             REG_WR(pdev,  NIG_REG_LED_MODE_P0, mode_idx);
870             break;
871         case 1:
872             REG_WR(pdev,  NIG_REG_LED_MODE_P1, mode_idx);
873             break;
874         default:
875             DbgMessage(NULL, FATAL, "lm_set_led_mode() unknown port index %d\n", port_idx);
876             return LM_STATUS_FAILURE;
877     }
878 
879     DbgMessage(NULL, INFORM, "lm_set_led_mode() wrote to NIG_REG_LED_MODE (port %d) 0x%x\n", port_idx, mode_idx);
880     return LM_STATUS_SUCCESS;
881 }
882 
883 /*
884  *------------------------------------------------------------------------
885  * lm_get_led_mode -
886  *
887  * Get the led mode of the requested port
888  *
889  *------------------------------------------------------------------------
890  */
lm_get_led_mode(struct _lm_device_t * pdev,u32_t port_idx,u32_t * mode_idx_ptr)891 lm_status_t lm_get_led_mode(struct _lm_device_t *pdev, u32_t port_idx, u32_t* mode_idx_ptr)
892 {
893 
894     DbgBreakIf(!pdev);
895 
896     // Read from the relevant NIG register LED_MODE (P0 or P1) the mode index (0-15)
897     switch (port_idx) {
898         case 0:
899             *mode_idx_ptr = REG_RD(pdev,  NIG_REG_LED_MODE_P0);
900             break;
901         case 1:
902             *mode_idx_ptr = REG_RD(pdev,  NIG_REG_LED_MODE_P1);
903             break;
904         default:
905             DbgMessage(NULL, FATAL, "lm_get_led_mode() unknown port index %d\n", port_idx);
906             return LM_STATUS_FAILURE;
907     }
908 
909     DbgMessage(NULL, INFORM, "lm_get_led_mode() read from NIG_REG_LED_MODE (port %d) 0x%x\n", port_idx, *mode_idx_ptr);
910 
911     return LM_STATUS_SUCCESS;
912 }
913 
914 /*
915  *------------------------------------------------------------------------
916  * lm_override_led_value -
917  *
918  * Override the led value of the requsted led
919  *
920  *------------------------------------------------------------------------
921  */
lm_override_led_value(struct _lm_device_t * pdev,u32_t port_idx,u32_t led_idx,u32_t value)922 lm_status_t lm_override_led_value(struct _lm_device_t *pdev, u32_t port_idx, u32_t led_idx, u32_t value)
923 {
924     u32_t reg_val   = 0;
925 
926     // If port 0 then use EMAC0, else use EMAC1
927     u32_t emac_base = (port_idx) ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
928 
929     DbgBreakIf(!pdev);
930 
931     DbgMessage(NULL, INFORM, "lm_override_led_value() port %d led_idx %d value %d\n", port_idx, led_idx, value);
932 
933     switch (led_idx) {
934         case 0: //10MB led
935             // Read the current value of the LED register in the EMAC block
936             reg_val = REG_RD(pdev, emac_base + EMAC_REG_EMAC_LED);
937             // Set the OVERRIDE bit to 1
938             reg_val |= EMAC_LED_OVERRIDE;
939             // If value is 1, set the 10M_OVERRIDE bit, otherwise reset it.
940             reg_val = (value==1) ? (reg_val | EMAC_LED_10MB_OVERRIDE) : (reg_val & ~EMAC_LED_10MB_OVERRIDE);
941             REG_WR(pdev, emac_base+ EMAC_REG_EMAC_LED, reg_val);
942             break;
943         case 1: //100MB led
944             // Read the current value of the LED register in the EMAC block
945             reg_val = REG_RD(pdev, emac_base + EMAC_REG_EMAC_LED);
946             // Set the OVERRIDE bit to 1
947             reg_val |= EMAC_LED_OVERRIDE;
948             // If value is 1, set the 100M_OVERRIDE bit, otherwise reset it.
949             reg_val = (value==1) ? (reg_val | EMAC_LED_100MB_OVERRIDE) : (reg_val & ~EMAC_LED_100MB_OVERRIDE);
950             REG_WR(pdev, emac_base+ EMAC_REG_EMAC_LED, reg_val);
951             break;
952         case 2: //1000MB led
953             // Read the current value of the LED register in the EMAC block
954             reg_val = REG_RD(pdev, emac_base + EMAC_REG_EMAC_LED);
955             // Set the OVERRIDE bit to 1
956             reg_val |= EMAC_LED_OVERRIDE;
957             // If value is 1, set the 1000M_OVERRIDE bit, otherwise reset it.
958             reg_val = (value==1) ? (reg_val | EMAC_LED_1000MB_OVERRIDE) : (reg_val & ~EMAC_LED_1000MB_OVERRIDE);
959             REG_WR(pdev, emac_base+ EMAC_REG_EMAC_LED, reg_val);
960             break;
961         case 3: //2500MB led
962             // Read the current value of the LED register in the EMAC block
963             reg_val = REG_RD(pdev, emac_base + EMAC_REG_EMAC_LED);
964             // Set the OVERRIDE bit to 1
965             reg_val |= EMAC_LED_OVERRIDE;
966             // If value is 1, set the 2500M_OVERRIDE bit, otherwise reset it.
967             reg_val = (value==1) ? (reg_val | EMAC_LED_2500MB_OVERRIDE) : (reg_val & ~EMAC_LED_2500MB_OVERRIDE);
968             REG_WR(pdev, emac_base+ EMAC_REG_EMAC_LED, reg_val);
969             break;
970         case 4: //10G led
971             if (port_idx == 0) {
972                 REG_WR(pdev,  NIG_REG_LED_10G_P0, value);
973             } else {
974                 REG_WR(pdev,  NIG_REG_LED_10G_P1, value);
975             }
976             break;
977         case 5: //TRAFFIC led
978 
979             // Find if the traffic control is via BMAC or EMAC
980             if (port_idx == 0) {
981                 reg_val = REG_RD(pdev,  NIG_REG_NIG_EMAC0_EN);
982             } else {
983                 reg_val = REG_RD(pdev,  NIG_REG_NIG_EMAC1_EN);
984             }
985 
986             // Override the traffic led in the EMAC:
987             if (reg_val == 1) {
988                 // Read the current value of the LED register in the EMAC block
989                 reg_val = REG_RD(pdev, emac_base + EMAC_REG_EMAC_LED);
990                 // Set the TRAFFIC_OVERRIDE bit to 1
991                 reg_val |= EMAC_LED_OVERRIDE;
992                 // If value is 1, set the TRAFFIC bit, otherwise reset it.
993                 reg_val = (value==1) ? (reg_val | EMAC_LED_TRAFFIC) : (reg_val & ~EMAC_LED_TRAFFIC);
994                 REG_WR(pdev, emac_base+ EMAC_REG_EMAC_LED, reg_val);
995             } else {    // Override the traffic led in the BMAC:
996                 if (port_idx == 0) {
997                     REG_WR(pdev,  NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0, 1);
998                     REG_WR(pdev,  NIG_REG_LED_CONTROL_TRAFFIC_P0, value);
999                 } else {
1000                     REG_WR(pdev,  NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P1, 1);
1001                     REG_WR(pdev,  NIG_REG_LED_CONTROL_TRAFFIC_P1, value);
1002                 }
1003             }
1004             break;
1005         default:
1006             DbgMessage(NULL, FATAL, "lm_override_led_value() unknown led index %d (should be 0-5)\n", led_idx);
1007             return LM_STATUS_FAILURE;
1008     }
1009 
1010     return LM_STATUS_SUCCESS;
1011 }
1012 
1013 /*
1014  *------------------------------------------------------------------------
1015  * lm_blink_traffic_led -
1016  *
1017  * Blink the traffic led with the requsted rate
1018  *
1019  *------------------------------------------------------------------------
1020  */
lm_blink_traffic_led(struct _lm_device_t * pdev,u32_t port_idx,u32_t rate)1021 lm_status_t lm_blink_traffic_led(struct _lm_device_t *pdev, u32_t port_idx, u32_t rate)
1022 {
1023     u32_t reg_val   = 0;
1024     // If port 0 then use EMAC0, else use EMAC1
1025     u32_t emac_base = (port_idx) ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
1026 
1027     DbgBreakIf(!pdev);
1028 
1029     // Find if the traffic control is via BMAC or EMAC
1030     if (port_idx == 0) {
1031         reg_val = REG_RD(pdev,  NIG_REG_NIG_EMAC0_EN);
1032     } else {
1033         reg_val = REG_RD(pdev,  NIG_REG_NIG_EMAC1_EN);
1034     }
1035 
1036     // Blink the traffic led using EMAC control:
1037     if (reg_val == 1) {
1038         // Read the current value of the LED register in the EMAC block
1039         reg_val = REG_RD(pdev, emac_base + EMAC_REG_EMAC_LED);
1040 
1041         // Set the TRAFFIC_OVERRIDE, TRAFFIC and BLNK_TRAFFIC to 1
1042         reg_val |= EMAC_LED_OVERRIDE;
1043         reg_val |= EMAC_LED_TRAFFIC;
1044         reg_val |= EMAC_LED_BLNK_TRAFFIC;
1045 
1046         // If rate field was entered then set the BLNK_RATE_ENA bit and the BLNK_RATE field,
1047         // Otherwise the blink rate will be about 16Hz
1048         if (rate != 0) {
1049             reg_val |= EMAC_LED_BLNK_RATE_ENA;
1050             reg_val |= (rate << EMAC_LED_BLNK_RATE_BITSHIFT);
1051         }
1052         REG_WR(pdev, emac_base+ EMAC_REG_EMAC_LED, reg_val);
1053         DbgMessage(NULL, INFORM, "lm_blink_traffic_led() port %d write to EMAC_REG_EMAC_LED the value 0x%x\n", port_idx, reg_val);
1054 
1055     } else { // Blink the traffic led in the BMAC:
1056         // Set the CONTROL_OVERRIDE_TRAFFIC and the CONTROL_BLINK_TRAFFIC to 1.
1057         if (port_idx == 0) {
1058             REG_WR(pdev,  NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0, 1);
1059             REG_WR(pdev,  NIG_REG_LED_CONTROL_TRAFFIC_P0, 1);
1060             REG_WR(pdev,  NIG_REG_LED_CONTROL_BLINK_TRAFFIC_P0, 1);
1061             DbgMessage(NULL, INFORM, "lm_blink_traffic_led() set BLINK_TRAFFIC_P0 to 1\n");
1062             // If the rate field was entered, update the BLINK_RATE register accordingly
1063             if (rate != 0) {
1064                 REG_WR(pdev,  NIG_REG_LED_CONTROL_BLINK_RATE_ENA_P0, 1);
1065                 REG_WR(pdev,  NIG_REG_LED_CONTROL_BLINK_RATE_P0, rate);
1066                 DbgMessage(NULL, INFORM, "lm_blink_traffic_led() port %d write to NIG_REG_LED_CONTROL_BLINK_RATE_P0 %x\n", port_idx, rate);
1067             }
1068         } else {
1069             REG_WR(pdev,  NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P1, 1);
1070             REG_WR(pdev,  NIG_REG_LED_CONTROL_TRAFFIC_P1, 1);
1071             REG_WR(pdev,  NIG_REG_LED_CONTROL_BLINK_TRAFFIC_P1, 1);
1072             DbgMessage(NULL, INFORM, "lm_blink_traffic_led() set BLINK_TRAFFIC_P1 to 1\n");
1073             // If the rate field was entered, update the BLINK_RATE register accordingly
1074             if (rate != 0) {
1075                 REG_WR(pdev,  NIG_REG_LED_CONTROL_BLINK_RATE_ENA_P1, 1);
1076                 REG_WR(pdev,  NIG_REG_LED_CONTROL_BLINK_RATE_P1, rate);
1077                 DbgMessage(NULL, INFORM, "lm_blink_traffic_led() port %d write to NIG_REG_LED_CONTROL_BLINK_RATE_P1 0x%x\n", port_idx, rate);
1078             }
1079         }
1080     }
1081     return LM_STATUS_SUCCESS;
1082 }
1083 
1084 /*
1085  *------------------------------------------------------------------------
1086  * lm_get_led_status -
1087  *
1088  * Get the led status of the requsted led, on the requested port
1089  *
1090  *------------------------------------------------------------------------
1091  */
lm_get_led_status(struct _lm_device_t * pdev,u32_t port_idx,u32_t led_idx,u32_t * value_ptr)1092 lm_status_t lm_get_led_status(struct _lm_device_t *pdev, u32_t port_idx, u32_t led_idx, u32_t* value_ptr)
1093 {
1094     u32_t reg_val   = 0;
1095 
1096     // If port 0 then use EMAC0, else use EMAC1
1097     u32_t emac_base = (port_idx) ? GRCBASE_EMAC1 : GRCBASE_EMAC0;
1098 
1099     DbgBreakIf(!pdev);
1100 
1101     switch (led_idx) {
1102         case 0: //10MB LED
1103             // Read the current value of the LED register in the EMAC block
1104             reg_val = REG_RD(pdev, emac_base + EMAC_REG_EMAC_LED);
1105             // Check the 10MB bit status
1106             *value_ptr = ((reg_val & EMAC_LED_10MB) == EMAC_LED_10MB) ? 1 : 0;
1107             break;
1108         case 1: //100MB LED
1109             // Read the current value of the LED register in the EMAC block
1110             reg_val = REG_RD(pdev, emac_base + EMAC_REG_EMAC_LED);
1111             // Check the 100MB bit status
1112             *value_ptr = ((reg_val & EMAC_LED_100MB) == EMAC_LED_100MB) ? 1 : 0;
1113             break;
1114         case 2: //1000MB LED
1115             // Read the current value of the LED register in the EMAC block
1116             reg_val = REG_RD(pdev, emac_base + EMAC_REG_EMAC_LED);
1117             // Check the 1000MB bit status
1118             *value_ptr = ((reg_val & EMAC_LED_1000MB) == EMAC_LED_1000MB) ? 1 : 0;
1119             break;
1120         case 3: //2500MB LED
1121             // Read the current value of the LED register in the EMAC block
1122             reg_val = REG_RD(pdev, emac_base + EMAC_REG_EMAC_LED);
1123             // Check the 2500MB bit status
1124             *value_ptr = ((reg_val & EMAC_LED_2500MB) == EMAC_LED_2500MB) ? 1 : 0;
1125             break;
1126         case 4: //10G LED
1127             if (port_idx == 0) {
1128                 *value_ptr = REG_RD(pdev,  NIG_REG_LED_10G_P0);
1129             } else {
1130                 *value_ptr = REG_RD(pdev,  NIG_REG_LED_10G_P1);
1131             }
1132             break;
1133         case 5: //TRAFFIC LED
1134             // Read the traffic led from the EMAC block
1135             reg_val = REG_RD(pdev, emac_base + EMAC_REG_EMAC_LED);
1136             // Check the TRAFFIC_STAT bit status
1137             *value_ptr = ((reg_val & EMAC_LED_TRAFFIC_STAT) == EMAC_LED_TRAFFIC_STAT) ? 1 : 0;
1138 
1139             // Read the traffic led from the BMAC block
1140             if (port_idx == 0) {
1141                 *value_ptr = REG_RD(pdev,  NIG_REG_LED_STATUS_ACTIVE_P0);
1142             } else {
1143                 *value_ptr = REG_RD(pdev,  NIG_REG_LED_STATUS_ACTIVE_P1);
1144             }
1145             break;
1146         default:
1147             DbgMessage(NULL, FATAL, "lm_get_led_status() unknown led index %d (should be 0-5)\n", led_idx);
1148             return LM_STATUS_FAILURE;
1149     }
1150 
1151     DbgMessage(NULL, INFORM, "lm_get_led_status() port %d led_idx %d value %d\n", port_idx, led_idx, *value_ptr);
1152 
1153     return LM_STATUS_SUCCESS;
1154 
1155 }
1156 
1157 /*
1158 *------------------------------------------------------------------------
1159 * lm_reset_led -
1160 *
1161 * Sets the LEDs to operational mode after establishing link
1162 *
1163 *------------------------------------------------------------------------
1164 */
1165 void
lm_reset_led(struct _lm_device_t * pdev)1166 lm_reset_led(struct _lm_device_t *pdev)
1167 {
1168     //u32_t val;
1169     u8_t port = 0;
1170 
1171     if (CHK_NULL(pdev)){
1172         DbgBreakIf(!pdev);
1173         return;
1174     }
1175     port = PORT_ID(pdev);
1176 
1177     REG_WR(pdev,  NIG_REG_LED_10G_P0 + port*4, 0);
1178     REG_WR(pdev,  NIG_REG_LED_MODE_P0 + port*4,SHARED_HW_CFG_LED_MAC1);
1179 }
1180 
lm_is_57710A0_dbg_intr(struct _lm_device_t * pdev)1181 static u8_t lm_is_57710A0_dbg_intr( struct _lm_device_t * pdev )
1182 {
1183     u32_t val = 0;
1184 
1185     /* if during MSI/MSI-X mode then take no action (different problem) */
1186     if(pdev->params.interrupt_mode != LM_INT_MODE_INTA)
1187     {
1188         DbgMessage(pdev, WARN, "MSI/MSI-X enabled - debugging INTA/B failed\n");
1189         return 0;
1190     }
1191 
1192     /* read status from PCIE core */
1193     val = REG_RD(pdev, 0x2004);
1194 
1195     /* if interrupt line value from PCIE core is not asserted then take no action (different problem) */
1196     #define PCIE_CORE_INT_PENDING_BIT 0X00080000 /* when this bit is set, interrupt is asserted (pending) */
1197     if(!GET_FLAGS(val, PCIE_CORE_INT_PENDING_BIT))
1198     {
1199         DbgMessage(pdev, WARN, "PCIE core int line not asserted - debugging INTA/B failed\n");
1200         return 0;
1201     }
1202 
1203     /* if interrupt line from PCIE core is not enabled then take no action (different problem) */
1204     #define PCIE_CORE_INT_DISABLE_BIT 0X00000400 /* when this bit is set, interrupt is disabled */
1205     if(GET_FLAGS(val, PCIE_CORE_INT_DISABLE_BIT))
1206     {
1207         DbgMessage(pdev, WARN, "PCIE core int line not enabled - debugging INTA/B failed\n");
1208         return 0;
1209     }
1210 
1211     /* read interrupt mask from IGU */
1212     val = REG_RD(pdev,  HC_REG_INT_MASK + 4*PORT_ID(pdev) );
1213 
1214     /* if not 1FFFF then write warning to log (suspected as different problem) and continue to following step */
1215     if(val != 0x0001ffff)
1216     {
1217         DbgMessage(pdev, WARN, "IGU int mask != 0x1ffff - might not be related to debugging INTA/B issue\n");
1218     }
1219 
1220     /* verify that int_line_en_0/1 is 1. If bit is clear then no action  write warning to log and return. */
1221     // We skip this check.
1222 
1223     return 1;
1224 }
1225 
1226 /** lm_57710A0_dbg_intr
1227  *
1228  * Description:
1229  * 1. some sanity checks that the case we have is indeed the
1230  * interrupt debugging mode.
1231  * 2. Apply special handling, that is to disable and enable
1232  * INTA/B in IGU
1233  */
lm_57710A0_dbg_intr(struct _lm_device_t * pdev)1234 void lm_57710A0_dbg_intr( struct _lm_device_t * pdev )
1235 {
1236     if(IS_CHIP_REV_A0(pdev) && lm_is_57710A0_dbg_intr(pdev))
1237     {
1238         lm_disable_int(pdev);
1239         lm_enable_int(pdev);
1240     }
1241 }
1242 
1243 /*******************************************************************************
1244  * Description: turn led on/off/operational mode
1245  *              Must be called under PHY_LOCK
1246  * Return:
1247  ******************************************************************************/
1248 lm_status_t
lm_set_led_wrapper(struct _lm_device_t * pdev,const u8_t led_mode)1249 lm_set_led_wrapper(struct _lm_device_t*     pdev,
1250                    const   u8_t             led_mode )
1251 {
1252     u8_t        elink_res = ELINK_STATUS_OK;
1253     lm_status_t lm_status = LM_STATUS_SUCCESS;
1254 
1255     PHY_HW_LOCK(pdev);
1256     elink_res = elink_set_led( &pdev->params.link, &pdev->vars.link, led_mode, pdev->vars.link.line_speed );
1257     PHY_HW_UNLOCK(pdev);
1258 
1259     switch(elink_res)
1260     {
1261     case ELINK_STATUS_OK:
1262         lm_status = LM_STATUS_SUCCESS;
1263         break;
1264 
1265     case ELINK_STATUS_ERROR:
1266     default:
1267         lm_status = LM_STATUS_FAILURE;
1268         break;
1269     }// switch elink_res
1270 
1271     return lm_status;
1272 } /* lm_set_led */
1273 
1274 /*******************************************************************************
1275  * Description: Reads the parametrs using elink interface
1276  *              Must be called under PHY_LOCK
1277  * Return:
1278  ******************************************************************************/
1279 lm_status_t
lm_get_transceiver_data(struct _lm_device_t * pdev,b10_transceiver_data_t * b10_transceiver_data)1280 lm_get_transceiver_data(struct _lm_device_t*     pdev,
1281                         b10_transceiver_data_t*  b10_transceiver_data )
1282 {
1283     u16_t eeprom_data[][2] = { { ELINK_SFP_EEPROM_VENDOR_NAME_ADDR, ELINK_SFP_EEPROM_VENDOR_NAME_SIZE},
1284                                { ELINK_SFP_EEPROM_PART_NO_ADDR,     ELINK_SFP_EEPROM_PART_NO_SIZE},
1285                                { ELINK_SFP_EEPROM_SERIAL_ADDR,      ELINK_SFP_EEPROM_SERIAL_SIZE},
1286                                { ELINK_SFP_EEPROM_REVISION_ADDR,    ELINK_SFP_EEPROM_REVISION_SIZE},
1287                                { ELINK_SFP_EEPROM_DATE_ADDR,        ELINK_SFP_EEPROM_DATE_SIZE} } ;
1288 
1289     u8_t        vendor_name  [ELINK_SFP_EEPROM_VENDOR_NAME_SIZE] = {0};
1290     u8_t        model_num    [ELINK_SFP_EEPROM_PART_NO_SIZE]     = {0};
1291     u8_t        serial_num   [ELINK_SFP_EEPROM_SERIAL_SIZE]      = {0};
1292     u8_t        revision_num [ELINK_SFP_EEPROM_REVISION_SIZE]    = {0};
1293     u8_t        mfg_date     [ELINK_SFP_EEPROM_DATE_SIZE]        = {0};
1294     u8_t*       ptr_arr[ARRSIZE(eeprom_data)]                    = {0}; // for convinence of coding
1295     u8_t        idx                                              = 0;
1296     u8_t        elink_res                                        = ELINK_STATUS_ERROR;
1297     u8_t        ext_phy_type                                     = 0;
1298     lm_status_t lm_status                                        = LM_STATUS_SUCCESS;
1299 
1300     // we use local variables (vendor_name, model_num etc...) to protect flows in IA64
1301     // that upper layer might send us non-aligned to u16_t pointer, in this case a BSOD might occur.
1302     // using local variables and than memcpy prevent such situation.
1303 
1304     if CHK_NULL( b10_transceiver_data )
1305     {
1306         return LM_STATUS_INVALID_PARAMETER;
1307     }
1308 
1309     ASSERT_STATIC( sizeof(b10_transceiver_data->vendor_name)  == sizeof(vendor_name) ) ;
1310     ASSERT_STATIC( sizeof(b10_transceiver_data->model_num)    == sizeof(model_num) ) ;
1311     ASSERT_STATIC( sizeof(b10_transceiver_data->serial_num)   == sizeof(serial_num) ) ;
1312     ASSERT_STATIC( sizeof(b10_transceiver_data->revision_num) == sizeof(revision_num) ) ;
1313     ASSERT_STATIC( sizeof(b10_transceiver_data->mfg_date)     == sizeof(mfg_date) ) ;
1314 
1315     mm_mem_zero( b10_transceiver_data, sizeof( b10_transceiver_data_t ) ) ;
1316 
1317     ptr_arr[0] = &vendor_name[0];
1318     ptr_arr[1] = &model_num[0];
1319     ptr_arr[2] = &serial_num[0];
1320     ptr_arr[3] = &revision_num[0];
1321     ptr_arr[4] = &mfg_date[0];
1322 
1323     if( pdev->params.link.num_phys > ELINK_MAX_PHYS )
1324     {
1325         DbgBreakIf(1);
1326         return LM_STATUS_FAILURE;
1327     }
1328 
1329     // query from elink all ext_phy types (currently 1 and 2)
1330     for( ext_phy_type = ELINK_EXT_PHY1; ext_phy_type < pdev->params.link.num_phys; ext_phy_type++ )
1331     {
1332         if( ELINK_ETH_PHY_SFPP_10G_FIBER == pdev->params.link.phy[ext_phy_type].media_type ||
1333        ELINK_ETH_PHY_SFP_1G_FIBER == pdev->params.link.phy[ext_phy_type].media_type ||
1334         ELINK_ETH_PHY_DA_TWINAX == pdev->params.link.phy[ext_phy_type].media_type)
1335         {
1336             // only in case not SFP+ - the elink query is supported
1337             for( idx = 0; idx < ARRSIZE(eeprom_data) ; idx++ )
1338             {
1339                 PHY_HW_LOCK(pdev);
1340                 elink_res = elink_read_sfp_module_eeprom( &pdev->params.link.phy[ext_phy_type], // ELINK_INT_PHY, ELINK_EXT_PHY1, ELINK_EXT_PHY2
1341                                                           &pdev->params.link,
1342 							  ELINK_I2C_DEV_ADDR_A0,
1343                                                           eeprom_data[idx][0],
1344                                                           (u8_t)eeprom_data[idx][1],
1345                                                           ptr_arr[idx] ) ;
1346                 PHY_HW_UNLOCK(pdev);
1347                 if( ELINK_STATUS_OK != elink_res )
1348                 {
1349                     // We assume that if one of the queries failed - there is an error so we break this loop
1350                     break;
1351                 }
1352 
1353             } // for "eeprom_data" size
1354 
1355             // only one sfp+ module is expected on board so we exit the ext_phy_type loop
1356             break;
1357 
1358         } // ELINK_ETH_PHY_SFP_FIBER == media_type
1359 
1360     } // for "ext_phy_type"
1361 
1362     switch(elink_res)
1363     {
1364     case ELINK_STATUS_OK:
1365         {
1366             b10_transceiver_data->ver_num = TRANSCEIVER_DATA_VER_NUM;
1367 
1368             mm_memcpy( b10_transceiver_data->vendor_name,  &vendor_name[0],  sizeof(vendor_name) );
1369             mm_memcpy( b10_transceiver_data->model_num,    &model_num[0],    sizeof(model_num) );
1370             mm_memcpy( b10_transceiver_data->serial_num,   &serial_num[0],   sizeof(serial_num) );
1371             mm_memcpy( b10_transceiver_data->revision_num, &revision_num[0], sizeof(revision_num) );
1372             mm_memcpy( b10_transceiver_data->mfg_date,     &mfg_date[0],     sizeof(mfg_date) );
1373         }
1374         lm_status = LM_STATUS_SUCCESS;
1375         break;
1376 
1377     case ELINK_STATUS_TIMEOUT:
1378         lm_status = LM_STATUS_TIMEOUT;
1379         break;
1380 
1381     case ELINK_STATUS_ERROR:
1382     default:
1383         lm_status = LM_STATUS_FAILURE;
1384         break;
1385     }// switch elink_res
1386 
1387     return lm_status;
1388 
1389 } /* lm_get_transceiver_data */
1390 
lm_set_mac_in_nig(lm_device_t * pdev,u8_t * mac_addr,lm_cli_idx_t lm_cli_idx,u8_t offset)1391 lm_status_t lm_set_mac_in_nig(lm_device_t * pdev, u8_t * mac_addr, lm_cli_idx_t lm_cli_idx, u8_t offset)
1392 {
1393     u32_t reg_offset = 0;
1394     u32_t wb_data[2] = {0};
1395     u8_t  enable_mac = 0;
1396 
1397     #define MAX_OFFSET_IN_MEM_1   8
1398 
1399     if (lm_cli_idx == LM_CLI_IDX_ISCSI)
1400     {
1401         offset = ECORE_LLH_CAM_ISCSI_ETH_LINE;
1402     }
1403     else if (offset == ECORE_LLH_CAM_ISCSI_ETH_LINE)
1404     {
1405         offset = MAX_MAC_OFFSET_IN_NIG; /* Invalidate offset if not iscsi and its in iscsi place */
1406     }
1407 
1408     /* We set the macs in the nig llh only for E2 SI/NIV mode and for NDIS only (first 16 entries) */
1409     if (CHIP_IS_E1x(pdev) || !IS_MULTI_VNIC(pdev) || IS_MF_SD_MODE(pdev) || offset >= MAX_MAC_OFFSET_IN_NIG)
1410     {
1411         return LM_STATUS_SUCCESS;
1412     }
1413 
1414     /* in switch-independt mode we need to configure the NIG LLH with the appropriate mac addresses, we use the
1415      * cam mapping 1--1 for all indices smaller than 16 */
1416     if (mac_addr)
1417     {
1418         DbgMessage(pdev, WARN, "Setting mac in nig to offset: %d mac_addr[%02x]:[%02x]:[%02x]:[%02x]:[%02x]:[%02x]\n", offset,
1419                    mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
1420         DbgMessage(pdev, WARN, "[%x]:[%x]\n",  mac_addr[6], mac_addr[7]);
1421 
1422         if (offset < MAX_OFFSET_IN_MEM_1)
1423         {
1424             reg_offset = (PORT_ID(pdev)? NIG_REG_LLH1_FUNC_MEM: NIG_REG_LLH0_FUNC_MEM) + 8*offset;
1425         }
1426         else
1427         {
1428             reg_offset = (PORT_ID(pdev)? NIG_REG_P1_LLH_FUNC_MEM2: NIG_REG_P0_LLH_FUNC_MEM2) + 8*(offset - MAX_OFFSET_IN_MEM_1);
1429         }
1430 
1431         wb_data[0] = ((mac_addr[2] << 24) | (mac_addr[3] << 16) | (mac_addr[4] << 8) | mac_addr[5]);
1432         wb_data[1] = ((mac_addr[0] << 8)  | mac_addr[1]);
1433 
1434         REG_WR_DMAE_LEN(pdev, reg_offset, wb_data, ARRSIZE(wb_data));
1435 
1436         enable_mac = 1;
1437     }
1438 
1439     DbgMessage(pdev, WARN, "Enable_mac: %d\n", enable_mac);
1440 
1441     if (offset < MAX_OFFSET_IN_MEM_1)
1442     {
1443         reg_offset = (PORT_ID(pdev)? NIG_REG_LLH1_FUNC_MEM_ENABLE : NIG_REG_LLH0_FUNC_MEM_ENABLE) + 4*offset;
1444     }
1445     else
1446     {
1447         reg_offset = (PORT_ID(pdev)? NIG_REG_P1_LLH_FUNC_MEM2_ENABLE : NIG_REG_P0_LLH_FUNC_MEM2_ENABLE) + 4*(offset - MAX_OFFSET_IN_MEM_1);
1448     }
1449     REG_WR(pdev, reg_offset, enable_mac);
1450 
1451     return LM_STATUS_SUCCESS;
1452 }
1453 
1454 /**
1455  * Table to lookup appropriate lock register for function.
1456  *
1457  * Indexed with func ID (0-7).
1458  *
1459  * Note registers are *not* consecutive, thus table.
1460  */
1461 
1462 static const u32_t lm_hw_lock_table[8] = {
1463         MISC_REG_DRIVER_CONTROL_1, /* 0 */
1464         MISC_REG_DRIVER_CONTROL_2, /* 1 */
1465         MISC_REG_DRIVER_CONTROL_3, /* 2 */
1466         MISC_REG_DRIVER_CONTROL_4, /* 3 */
1467         MISC_REG_DRIVER_CONTROL_5, /* 4 */
1468         MISC_REG_DRIVER_CONTROL_6, /* 5 */
1469         MISC_REG_DRIVER_CONTROL_7, /* 6 */
1470         MISC_REG_DRIVER_CONTROL_8, /* 7 */
1471 };
1472 
1473 /*******************************************************************************
1474  * Description:
1475  *         Acquiring the HW lock for a specific resource.
1476  *         The assumption is that only 1 bit is set in the resource parameter
1477  *         There is a HW attention in case the same function attempts to
1478  *         acquire the same lock more than once
1479  *
1480  * Params:
1481  *         resource: the HW LOCK Register name
1482  *         b_block: Try to get lock until succesful, or backout immediately on failure.
1483  * Return:
1484  *          Success - got the lock
1485  *          Fail - Invalid parameter or could not obtain the lock for our 1 sec in block mode
1486  *          or couldn't obtain lock one-shot in non block mode
1487  ******************************************************************************/
lm_hw_lock(lm_device_t * pdev,const u32_t resource,const u8_t b_block)1488 lm_status_t lm_hw_lock(      lm_device_t* pdev,
1489                        const u32_t        resource,
1490                        const u8_t         b_block)
1491 {
1492     u32_t cnt                = 0;
1493     u32_t lock_status        = 0;
1494     u32_t const resource_bit = (1 << resource);
1495     u8_t  const func         = FUNC_ID(pdev);
1496     u32_t hw_lock_cntr_reg   = 0;
1497 
1498     // Validating the resource in within range
1499     if (resource > HW_LOCK_MAX_RESOURCE_VALUE)
1500     {
1501         DbgMessage(pdev, FATAL, "lm_hw_lock: LM_STATUS_INVALID_PARAMETER resource=0x%x\n", resource);
1502         DbgBreakMsg("lm_hw_lock: LM_STATUS_INVALID_PARAMETER\n");
1503         return LM_STATUS_INVALID_PARAMETER;
1504     }
1505 
1506     DbgBreakIf(func >= ARRSIZE(lm_hw_lock_table));
1507     hw_lock_cntr_reg = lm_hw_lock_table[func];
1508 
1509     // Validating that the resource is not already taken
1510     lock_status = REG_RD(pdev, hw_lock_cntr_reg);
1511     if (lock_status & resource_bit)
1512     {
1513         DbgMessage(pdev, FATAL , "lm_hw_lock: LM_STATUS_EXISTING_OBJECT lock_status=0x%x resource_bit=0x%x\n", lock_status, resource_bit);
1514         DbgBreakMsg("lm_hw_lock: LM_STATUS_EXISTING_OBJECT\n");
1515         return LM_STATUS_EXISTING_OBJECT;
1516     }
1517     // Try for 16 second every 50us
1518     for (cnt = 0; cnt < 320000; cnt++)
1519     {
1520         // Try to acquire the lock
1521         REG_WR(pdev, hw_lock_cntr_reg + 4, resource_bit);
1522         lock_status= REG_RD(pdev, hw_lock_cntr_reg);
1523         if (lock_status & resource_bit)
1524         {
1525             return LM_STATUS_SUCCESS;
1526         }
1527         if (!b_block)
1528         {
1529             return LM_STATUS_FAILURE;
1530         }
1531         mm_wait(pdev, 50);
1532     }
1533     DbgMessage(pdev, FATAL , "lm_hw_lock: LM_STATUS_TIMEOUT\n" );
1534     DbgBreakMsg("lm_hw_lock: FAILED LM_STATUS_TIMEOUT\n");
1535     return LM_STATUS_TIMEOUT;
1536 }
1537 /*******************************************************************************
1538  * Description:
1539  *         Releasing the HW lock for a specific resource.
1540  *         There is a HW attention in case the a function attempts to release
1541  *         a lock that it did not acquire (if b_verify_locked is TRUE, default)
1542  * Return:
1543  *          Success - if the parameter is valid, the assumption is that it
1544  *                    will succeed
1545  *          Fail - Invalid parameter
1546  ******************************************************************************/
lm_hw_unlock_ex(lm_device_t * pdev,const u32_t resource,const u8_t b_verify_locked)1547 lm_status_t lm_hw_unlock_ex(lm_device_t*  pdev,
1548                             const u32_t   resource,
1549                             const u8_t    b_verify_locked )
1550 {
1551     u32_t lock_status        = 0;
1552     u32_t const resource_bit = (1 << resource);
1553     u8_t  const func         = FUNC_ID(pdev);
1554     u32_t hw_lock_cntr_reg   = 0;
1555 
1556     // Validating the resource in within range
1557     if (resource > HW_LOCK_MAX_RESOURCE_VALUE)
1558     {
1559         DbgMessage(pdev, FATAL, "lm_hw_unlock: LM_STATUS_INVALID_PARAMETER resource=0x%x\n", resource);
1560         DbgBreakMsg("lm_hw_unlock: LM_STATUS_INVALID_PARAMETER\n");
1561         return LM_STATUS_INVALID_PARAMETER;
1562     }
1563 
1564     DbgBreakIf(func >= ARRSIZE(lm_hw_lock_table));
1565     hw_lock_cntr_reg = lm_hw_lock_table[func];
1566 
1567     // Validating that the resource is currently taken
1568     lock_status = REG_RD(pdev, hw_lock_cntr_reg);
1569     if (!(lock_status & resource_bit))
1570     {
1571         // This comment is explicitly outside the IF since we still want to be aware it happened.
1572         DbgMessage(pdev, FATAL, "lm_hw_unlock: LM_STATUS_OBJECT_NOT_FOUND lock_status=0x%x resource_bit=0x%x\n", lock_status, resource_bit);
1573 
1574         if( b_verify_locked )
1575         {
1576            DbgBreakMsg("lm_hw_unlock: LM_STATUS_OBJECT_NOT_FOUND\n");
1577            return LM_STATUS_OBJECT_NOT_FOUND;
1578         }
1579     }
1580     REG_WR(pdev, hw_lock_cntr_reg, resource_bit);
1581 
1582     return LM_STATUS_SUCCESS;
1583 }
1584 
1585 /*******************************************************************************
1586  * Description:
1587  *         Releasing the HW lock for a specific resource.
1588  *         There is a HW attention in case the a function attempts to release
1589  *         a lock that it did not acquire
1590            THIS function is a wrapper function now for lm_hw_unlock_ex.
1591  * Return:
1592  *          Success - if the parameter is valid, the assumption is that it
1593  *                    will succeed
1594  *          Fail - Invalid parameter
1595  ******************************************************************************/
lm_hw_unlock(lm_device_t * pdev,const u32_t resource)1596 lm_status_t lm_hw_unlock(lm_device_t*      pdev,
1597                          const u32_t       resource)
1598 {
1599     return lm_hw_unlock_ex( pdev, resource, TRUE);
1600 }
1601 
1602 /**
1603  * @Desription
1604  *      This function is used to recover from a state where the
1605  *      locks stayed in "taken" state during a reboot. We want
1606  *      to clear all the locks before proceeding.
1607  *
1608  * @param pdev
1609  */
lm_hw_clear_all_locks(lm_device_t * pdev)1610 void lm_hw_clear_all_locks(lm_device_t *pdev)
1611 {
1612     u32_t lock_status        = 0;
1613     u32_t hw_lock_cntr_reg   = 0;
1614     u8_t  func               = 0;
1615 
1616     /* We clear locks due to error recover possible failure leaving locking traces...
1617      * we do this only for E2 and above */
1618     if (CHIP_IS_E1x(pdev))
1619     {
1620         return;
1621     }
1622 
1623     for (func = 0; func < MAX_FUNC_NUM; func++)
1624     {
1625         DbgBreakIf(func >= ARRSIZE(lm_hw_lock_table));
1626         hw_lock_cntr_reg = lm_hw_lock_table[func];
1627 
1628         lock_status = REG_RD(pdev, hw_lock_cntr_reg);
1629         if (lock_status != 0)
1630         {
1631             REG_WR(pdev, hw_lock_cntr_reg, lock_status);
1632         }
1633     }
1634 }
1635 
reg_wait_verify_val(struct _lm_device_t * pdev,u32_t reg_offset,u32_t excpected_val,u32_t total_wait_time_ms)1636 u32_t reg_wait_verify_val(struct _lm_device_t * pdev, u32_t reg_offset, u32_t excpected_val, u32_t total_wait_time_ms )
1637 {
1638     u32_t val            = 0 ;
1639     u32_t wait_cnt       = 0 ;
1640     u32_t wait_cnt_limit = total_wait_time_ms/DEFAULT_WAIT_INTERVAL_MICSEC ;
1641     if( wait_cnt_limit == 0 )
1642     {
1643         wait_cnt_limit = 1;
1644     }
1645     val=REG_RD(pdev,reg_offset);
1646     while( (val != excpected_val) && (wait_cnt++ != wait_cnt_limit) )
1647     {
1648         mm_wait(pdev, DEFAULT_WAIT_INTERVAL_MICSEC) ;
1649         val=REG_RD(pdev,reg_offset);
1650     }
1651     if (val != excpected_val) {
1652         DbgMessage(pdev, WARN, "val = 0x%x, expected val = 0x%x\n", val, excpected_val );
1653     DbgBreakIf(val != excpected_val);
1654     }
1655     return wait_cnt;
1656 }
1657 
1658 /*******************************************************************************
1659  * Description:
1660  *     stop any dma transactions to/from chip
1661  *     after this function is called, no write to chip is availalbe anymore.
1662  * Return:
1663  *     void
1664  ******************************************************************************/
lm_disable_pci_dma(struct _lm_device_t * pdev,u8_t b_wait_for_done)1665 void lm_disable_pci_dma(struct _lm_device_t *pdev, u8_t b_wait_for_done)
1666 {
1667     u32_t       val   = 0;
1668     u32_t       idx   = 0;
1669     const u32_t flags = (PCICFG_DEVICE_STATUS_NO_PEND << 16) ;
1670 
1671     if (IS_PFDEV(pdev))
1672     {
1673         if (CHIP_IS_E1x(pdev))
1674         {
1675             /* Disable bus_master. */
1676             val=REG_RD(pdev,GRCBASE_PCICONFIG+PCICFG_COMMAND_OFFSET);
1677             RESET_FLAGS( val, PCICFG_COMMAND_BUS_MASTER );
1678             REG_WR(pdev,GRCBASE_PCICONFIG+PCICFG_COMMAND_OFFSET,val);
1679         }
1680         else
1681         {
1682             /* In E2, there is a cleaner way to disable pci-dma, no need for a pci-configuration
1683              * transaction */
1684             REG_WR(pdev, PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER, 0);
1685         }
1686 
1687         /* wait until there is no pending transaction. */
1688         if (b_wait_for_done)
1689         {
1690             for(idx = 0; idx < 1000; idx++)
1691             {
1692                 val=REG_RD(pdev,GRCBASE_PCICONFIG+PCICFG_DEVICE_CONTROL);
1693                 if( (val & flags) == 0)
1694                 {
1695                     break;
1696                 }
1697                 mm_wait(pdev, 5);
1698             }
1699         }
1700     }
1701 }
1702 /*******************************************************************************
1703  * Description:
1704  *     enable Bus Master Enable
1705  * Return:
1706  *     void
1707  ******************************************************************************/
lm_enable_pci_dma(struct _lm_device_t * pdev)1708 void lm_enable_pci_dma(struct _lm_device_t *pdev)
1709 {
1710     u32_t       val   = 0;
1711     if (IS_PFDEV(pdev))
1712     {
1713         if (CHIP_IS_E1x(pdev))
1714         {
1715             /* Enable bus_master. */
1716             val=REG_RD(pdev,GRCBASE_PCICONFIG+PCICFG_COMMAND_OFFSET);
1717             if( 0 == GET_FLAGS( val, PCICFG_COMMAND_BUS_MASTER ) )
1718             {
1719                 SET_FLAGS( val, PCICFG_COMMAND_BUS_MASTER );
1720                 REG_WR(pdev,GRCBASE_PCICONFIG+PCICFG_COMMAND_OFFSET,val);
1721             }
1722         }
1723         else
1724         {
1725             /* In E2, there is a cleaner way to disable pci-dma, no need for a pci-configuration
1726              * transaction */
1727             REG_WR(pdev, PGLUE_B_REG_INTERNAL_PFID_ENABLE_MASTER, 1);
1728         }
1729     }
1730 }
1731 /*******************************************************************************
1732  * Description:
1733  *     disable non fatal error pcie reporting
1734  * Return:
1735  *     void
1736  ******************************************************************************/
lm_set_pcie_nfe_report(lm_device_t * pdev)1737 void lm_set_pcie_nfe_report(lm_device_t *pdev)
1738 {
1739     if(IS_PFDEV(pdev) && pdev->params.disable_pcie_nfr)
1740     {
1741         u32_t pci_devctl = 0 ;
1742         pci_devctl = REG_RD(pdev,GRCBASE_PCICONFIG + PCICFG_DEVICE_CONTROL);
1743         RESET_FLAGS( pci_devctl, PCICFG_DEVICE_STATUS_NON_FATAL_ERR_DET );
1744         REG_WR(pdev,GRCBASE_PCICONFIG + PCICFG_DEVICE_CONTROL,pci_devctl);
1745     }
1746 }
1747 
1748 // These lm_reg_xx_ind_imp() are for blk reading when lock is acquired only once (for the whole block reading)
1749 void
lm_reg_rd_ind_imp(lm_device_t * pdev,u32_t offset,u32_t * ret)1750 lm_reg_rd_ind_imp(
1751     lm_device_t *pdev,
1752     u32_t offset,
1753     u32_t *ret)
1754 {
1755     DbgBreakIf(offset & 0x3);
1756     mm_write_pci(pdev,PCICFG_GRC_ADDRESS,offset);
1757     mm_read_pci(pdev,PCICFG_GRC_DATA,ret);
1758 } /* lm_reg_rd_ind_imp */
1759 void
lm_reg_wr_ind_imp(lm_device_t * pdev,u32_t offset,u32_t val)1760 lm_reg_wr_ind_imp(
1761     lm_device_t *pdev,
1762     u32_t offset,
1763     u32_t val)
1764 {
1765     u32_t dummy;
1766     DbgBreakIf(offset & 0x3);
1767     mm_write_pci(pdev,PCICFG_GRC_ADDRESS,offset);
1768     mm_write_pci(pdev,PCICFG_GRC_DATA,val);
1769     lm_reg_rd_ind_imp(pdev,PCICFG_VENDOR_ID_OFFSET,&dummy);
1770 } /* lm_reg_wr_ind_imp */
1771 /*******************************************************************************
1772  * Description:
1773  *
1774  * Return:
1775  *    None.
1776  *
1777  * Note:
1778  *    The caller is responsible for synchronizing calls to lm_reg_rd_ind and
1779  *    lm_reg_wr_ind.
1780  ******************************************************************************/
1781 void
lm_reg_rd_ind(lm_device_t * pdev,u32_t offset,u32_t * ret)1782 lm_reg_rd_ind(
1783     lm_device_t *pdev,
1784     u32_t offset,
1785     u32_t *ret)
1786 {
1787     MM_ACQUIRE_IND_REG_LOCK(pdev);
1788     lm_reg_rd_ind_imp(pdev,offset,ret);
1789     MM_RELEASE_IND_REG_LOCK(pdev);
1790 } /* lm_reg_rd_ind */
1791 /*******************************************************************************
1792  * Description:
1793  *
1794  * Return:
1795  *    None.
1796  *
1797  * Note:
1798  *    The caller is responsible for synchronizing calls to lm_reg_rd_ind and
1799  *    lm_reg_wr_ind.
1800  ******************************************************************************/
1801 void
lm_reg_wr_ind(lm_device_t * pdev,u32_t offset,u32_t val)1802 lm_reg_wr_ind(
1803     lm_device_t *pdev,
1804     u32_t offset,
1805     u32_t val)
1806 {
1807     MM_ACQUIRE_IND_REG_LOCK(pdev);
1808     lm_reg_wr_ind_imp(pdev,offset,val);
1809     MM_RELEASE_IND_REG_LOCK(pdev);
1810 } /* lm_reg_wr_ind */
1811 /*******************************************************************************
1812  * Description:
1813  *
1814  * Return:
1815  ******************************************************************************/
1816 void
lm_reg_rd_blk(lm_device_t * pdev,u32_t reg_offset,u32_t * buf_ptr,u32_t u32t_cnt)1817 lm_reg_rd_blk(
1818     lm_device_t *pdev,
1819     u32_t reg_offset,
1820     u32_t *buf_ptr,
1821     u32_t u32t_cnt)
1822 {
1823     u32_t current_offset = 0;
1824     DbgBreakIf(reg_offset & 0x3);
1825     while(u32t_cnt)
1826     {
1827         *buf_ptr = REG_RD(pdev, reg_offset + current_offset);
1828         buf_ptr++;
1829         u32t_cnt--;
1830         current_offset += 4;
1831     }
1832 } /* lm_reg_rd_blk */
1833 /*******************************************************************************
1834  * Description:
1835  *
1836  * Return:
1837  ******************************************************************************/
1838 void
lm_reg_rd_blk_ind(lm_device_t * pdev,u32_t reg_offset,u32_t * buf_ptr,u32_t u32t_cnt,u8_t acquire_lock_flag)1839 lm_reg_rd_blk_ind(
1840     lm_device_t *pdev,
1841     u32_t reg_offset,
1842     u32_t *buf_ptr,
1843     u32_t u32t_cnt,
1844     u8_t acquire_lock_flag)
1845 {
1846     u32_t current_offset = 0;
1847     if(acquire_lock_flag)
1848     {
1849         MM_ACQUIRE_IND_REG_LOCK(pdev);
1850     }
1851     while(u32t_cnt)
1852     {
1853         lm_reg_rd_ind_imp(pdev, reg_offset + current_offset, buf_ptr);
1854         buf_ptr++;
1855         u32t_cnt--;
1856         current_offset += 4;
1857     }
1858     if(acquire_lock_flag)
1859     {
1860         MM_RELEASE_IND_REG_LOCK(pdev);
1861     }
1862 } /* lm_reg_rd_blk_ind */
1863 
1864 /*******************************************************************************
1865  * Description:
1866  *
1867  * Return:
1868  ******************************************************************************/
1869 void
lm_reg_wr_blk(lm_device_t * pdev,u32_t reg_offset,u32_t * data_ptr,u32_t u32t_cnt)1870 lm_reg_wr_blk(
1871     lm_device_t *pdev,
1872     u32_t reg_offset,
1873     u32_t *data_ptr,
1874     u32_t u32t_cnt)
1875 {
1876     u32_t current_offset = 0;
1877     DbgBreakIf(reg_offset & 0x3);
1878     while(u32t_cnt)
1879     {
1880         REG_WR(pdev, reg_offset + current_offset, *data_ptr);
1881         data_ptr++;
1882         u32t_cnt--;
1883         current_offset += 4;
1884     }
1885 } /* lm_reg_wr_blk */
1886 
1887 /*******************************************************************************
1888  * Description:
1889  *
1890  * Return:
1891  ******************************************************************************/
1892 void
lm_reg_wr_blk_ind(lm_device_t * pdev,u32_t reg_offset,u32_t * data_ptr,u32_t u32t_cnt)1893 lm_reg_wr_blk_ind(
1894     lm_device_t *pdev,
1895     u32_t reg_offset,
1896     u32_t *data_ptr,
1897     u32_t u32t_cnt)
1898 {
1899     u32_t current_offset = 0;
1900 
1901     MM_ACQUIRE_IND_REG_LOCK(pdev);
1902     while(u32t_cnt)
1903     {
1904         lm_reg_wr_ind_imp(pdev, reg_offset + current_offset, *data_ptr);
1905         data_ptr++;
1906         u32t_cnt--;
1907         current_offset += 4;
1908     }
1909     MM_RELEASE_IND_REG_LOCK(pdev);
1910 } /* lm_reg_wr_blk_ind */
1911 
lm_set_waitp(lm_device_t * pdev)1912 void lm_set_waitp(lm_device_t *pdev)
1913 {
1914     REG_WR(pdev,DRV_DUMP_TSTORM_WAITP_ADDRESS,1);
1915     REG_WR(pdev,DRV_DUMP_XSTORM_WAITP_ADDRESS,1);
1916     REG_WR(pdev,DRV_DUMP_CSTORM_WAITP_ADDRESS,1);
1917     REG_WR(pdev,DRV_DUMP_USTORM_WAITP_ADDRESS,1);
1918 }
1919 
lm_collect_idle_storms_dorrbell_asserts(struct _lm_device_t * pdev,const u8_t b_idle_chk,const u8_t b_storms_asserts,const u8_t b_dorrbell_info)1920 void lm_collect_idle_storms_dorrbell_asserts( struct _lm_device_t *pdev,
1921                                               const  u8_t          b_idle_chk,
1922                                               const  u8_t          b_storms_asserts,
1923                                               const  u8_t          b_dorrbell_info )
1924 {
1925 #if !(defined(UEFI) || defined(DOS) || defined(__LINUX))
1926     if( b_idle_chk )
1927     {
1928         lm_idle_chk(pdev);
1929     }
1930 
1931     if( b_dorrbell_info )
1932     {
1933         lm_get_doorbell_info(pdev);
1934     }
1935 
1936     if( b_storms_asserts )
1937     {
1938         lm_get_storms_assert(pdev);
1939     }
1940 #endif
1941 }
1942