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 */
43void ecore_init_cmng(const struct cmng_init_input *input_data,
44                              struct cmng_init *ram_data);
45
46void 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
59void 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 */
194static 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 */
215static 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 */
241static 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
261lm_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 */
305lm_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
337void 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 */
410lm_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 */
516lm_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 */
602lm_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
665lm_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 */
732lm_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 */
805lm_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 */
861lm_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 */
891lm_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 */
922lm_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 */
1021lm_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 */
1092lm_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*/
1165void
1166lm_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
1181static 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 */
1234void 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 ******************************************************************************/
1248lm_status_t
1249lm_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 ******************************************************************************/
1279lm_status_t
1280lm_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
1391lm_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
1462static 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 ******************************************************************************/
1488lm_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 ******************************************************************************/
1547lm_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 ******************************************************************************/
1596lm_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 */
1610void 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
1636u32_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 ******************************************************************************/
1665void 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 ******************************************************************************/
1708void 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 ******************************************************************************/
1737void 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)
1749void
1750lm_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 */
1759void
1760lm_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 ******************************************************************************/
1781void
1782lm_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 ******************************************************************************/
1801void
1802lm_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 ******************************************************************************/
1816void
1817lm_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 ******************************************************************************/
1838void
1839lm_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 ******************************************************************************/
1869void
1870lm_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 ******************************************************************************/
1892void
1893lm_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
1912void 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
1920void 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