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