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 encapsulates all the functions required to support error
35*d14abf15SRobert Mustacchi  *      recovery in E2. It is an isolated module that can be compiled in/out
36*d14abf15SRobert Mustacchi  *      according to error recovery support in upper layer
37*d14abf15SRobert Mustacchi  *
38*d14abf15SRobert Mustacchi  *
39*d14abf15SRobert Mustacchi  ******************************************************************************/
40*d14abf15SRobert Mustacchi 
41*d14abf15SRobert Mustacchi #include "lm5710.h"
42*d14abf15SRobert Mustacchi #include "aeu_inputs.h"
43*d14abf15SRobert Mustacchi #include "lm_defs.h"
44*d14abf15SRobert Mustacchi #include "general_atten_bits.h"
45*d14abf15SRobert Mustacchi /**
46*d14abf15SRobert Mustacchi  * @Description
47*d14abf15SRobert Mustacchi  *      This function should be called to acquire the leader lock. the leader
48*d14abf15SRobert Mustacchi  *      lock should not be released until recovery process id done.
49*d14abf15SRobert Mustacchi  *      The leader lock is not waited for, its a non-blockinf function
50*d14abf15SRobert Mustacchi  *
51*d14abf15SRobert Mustacchi  * @param pdev
52*d14abf15SRobert Mustacchi  *
53*d14abf15SRobert Mustacchi  * @return lm_status_t SUCCESS or FAILURE
54*d14abf15SRobert Mustacchi  */
lm_er_acquire_leader_lock(lm_device_t * pdev)55*d14abf15SRobert Mustacchi lm_status_t lm_er_acquire_leader_lock(lm_device_t * pdev)
56*d14abf15SRobert Mustacchi {
57*d14abf15SRobert Mustacchi     return lm_hw_lock(pdev, HW_LOCK_RESOURCE_RECOVERY_LEADER_0, FALSE);
58*d14abf15SRobert Mustacchi }
59*d14abf15SRobert Mustacchi 
60*d14abf15SRobert Mustacchi /**
61*d14abf15SRobert Mustacchi  * @Description
62*d14abf15SRobert Mustacchi  *      release the lock acquired in the previous function
63*d14abf15SRobert Mustacchi  * @param pdev
64*d14abf15SRobert Mustacchi  *
65*d14abf15SRobert Mustacchi  * @return lm_status_t SUCCESS, INVALID_PARAM: if invalid input
66*d14abf15SRobert Mustacchi  *         is provided, LM_STATUS_OBJECT_NOT_FOUND if the lock
67*d14abf15SRobert Mustacchi  *         isn't taken.
68*d14abf15SRobert Mustacchi  */
lm_er_release_leader_lock(lm_device_t * pdev)69*d14abf15SRobert Mustacchi lm_status_t lm_er_release_leader_lock(lm_device_t * pdev)
70*d14abf15SRobert Mustacchi {
71*d14abf15SRobert Mustacchi     return lm_hw_unlock(pdev, HW_LOCK_RESOURCE_RECOVERY_LEADER_0);
72*d14abf15SRobert Mustacchi }
73*d14abf15SRobert Mustacchi 
74*d14abf15SRobert Mustacchi 
75*d14abf15SRobert Mustacchi /**
76*d14abf15SRobert Mustacchi  * @Description
77*d14abf15SRobert Mustacchi  *      This function disables close the gate functionality
78*d14abf15SRobert Mustacchi  *      should be called from the last driver that unloads
79*d14abf15SRobert Mustacchi  *      (unless recovery is in progress)
80*d14abf15SRobert Mustacchi  *
81*d14abf15SRobert Mustacchi  * @param pdev
82*d14abf15SRobert Mustacchi  */
lm_er_disable_close_the_gate(lm_device_t * pdev)83*d14abf15SRobert Mustacchi void lm_er_disable_close_the_gate(lm_device_t *pdev)
84*d14abf15SRobert Mustacchi {
85*d14abf15SRobert Mustacchi     u32_t val;
86*d14abf15SRobert Mustacchi 
87*d14abf15SRobert Mustacchi     DbgMessage(pdev, INFORMer, "Disabling \"close the gates\"\n");
88*d14abf15SRobert Mustacchi 
89*d14abf15SRobert Mustacchi     if (CHIP_IS_E2(pdev) || CHIP_IS_E3(pdev))
90*d14abf15SRobert Mustacchi     {
91*d14abf15SRobert Mustacchi         val = REG_RD(pdev, MISC_REG_AEU_GENERAL_MASK);
92*d14abf15SRobert Mustacchi         val &= ~(MISC_AEU_GENERAL_MASK_REG_AEU_PXP_CLOSE_MASK |
93*d14abf15SRobert Mustacchi              MISC_AEU_GENERAL_MASK_REG_AEU_NIG_CLOSE_MASK);
94*d14abf15SRobert Mustacchi         REG_WR(pdev, MISC_REG_AEU_GENERAL_MASK, val);
95*d14abf15SRobert Mustacchi     }
96*d14abf15SRobert Mustacchi }
97*d14abf15SRobert Mustacchi 
98*d14abf15SRobert Mustacchi /* Close gates #2, #3 and #4: */
lm_er_set_234_gates(lm_device_t * pdev,u8_t close_g8)99*d14abf15SRobert Mustacchi static void lm_er_set_234_gates(lm_device_t *pdev, u8_t close_g8)
100*d14abf15SRobert Mustacchi {
101*d14abf15SRobert Mustacchi     u32_t val, enable_bit;
102*d14abf15SRobert Mustacchi 
103*d14abf15SRobert Mustacchi     enable_bit = close_g8? 1 : 0;
104*d14abf15SRobert Mustacchi 
105*d14abf15SRobert Mustacchi     /* close gate #4 */
106*d14abf15SRobert Mustacchi     REG_WR(pdev, PXP_REG_HST_DISCARD_DOORBELLS, enable_bit);
107*d14abf15SRobert Mustacchi 
108*d14abf15SRobert Mustacchi     /* close gate #2 */
109*d14abf15SRobert Mustacchi     REG_WR(pdev, PXP_REG_HST_DISCARD_INTERNAL_WRITES, enable_bit);
110*d14abf15SRobert Mustacchi 
111*d14abf15SRobert Mustacchi     /* close gate #3 (this will disable new interrupts */
112*d14abf15SRobert Mustacchi     val = REG_RD(pdev, IGU_REG_BLOCK_CONFIGURATION);
113*d14abf15SRobert Mustacchi     close_g8? RESET_FLAGS(val, IGU_BLOCK_CONFIGURATION_REG_BLOCK_ENABLE) :
114*d14abf15SRobert Mustacchi         SET_FLAGS(val, IGU_BLOCK_CONFIGURATION_REG_BLOCK_ENABLE);
115*d14abf15SRobert Mustacchi 
116*d14abf15SRobert Mustacchi     REG_WR(pdev, IGU_REG_BLOCK_CONFIGURATION, val);
117*d14abf15SRobert Mustacchi 
118*d14abf15SRobert Mustacchi 
119*d14abf15SRobert Mustacchi     DbgMessage(pdev, FATAL, "%s gates #2, #3 and #4\n",
120*d14abf15SRobert Mustacchi         close_g8 ? "closing" : "opening");
121*d14abf15SRobert Mustacchi 
122*d14abf15SRobert Mustacchi }
123*d14abf15SRobert Mustacchi 
124*d14abf15SRobert Mustacchi 
lm_er_pxp_prep(lm_device_t * pdev)125*d14abf15SRobert Mustacchi static void lm_er_pxp_prep(lm_device_t *pdev)
126*d14abf15SRobert Mustacchi {
127*d14abf15SRobert Mustacchi     if (!CHIP_IS_E1(pdev))
128*d14abf15SRobert Mustacchi     {
129*d14abf15SRobert Mustacchi         REG_WR(pdev, PXP2_REG_RD_START_INIT, 0);
130*d14abf15SRobert Mustacchi         REG_WR(pdev, PXP2_REG_RQ_RBC_DONE, 0);
131*d14abf15SRobert Mustacchi     }
132*d14abf15SRobert Mustacchi }
133*d14abf15SRobert Mustacchi 
134*d14abf15SRobert Mustacchi /*
135*d14abf15SRobert Mustacchi  * Reset the whole chip except for:
136*d14abf15SRobert Mustacchi  *      - PCIE core
137*d14abf15SRobert Mustacchi  *      - PCI Glue, PSWHST, PXP/PXP2 RF (all controlled by
138*d14abf15SRobert Mustacchi  *              one reset bit)
139*d14abf15SRobert Mustacchi  *      - IGU
140*d14abf15SRobert Mustacchi  *      - MISC (including AEU)
141*d14abf15SRobert Mustacchi  *      - GRC
142*d14abf15SRobert Mustacchi  *      - RBCN, RBCP
143*d14abf15SRobert Mustacchi  * Reset MCP ONLY if reset_mcp is TRUE
144*d14abf15SRobert Mustacchi  */
lm_er_process_kill_chip_reset(lm_device_t * pdev,u8_t reset_mcp)145*d14abf15SRobert Mustacchi static void lm_er_process_kill_chip_reset(lm_device_t *pdev, u8_t reset_mcp)
146*d14abf15SRobert Mustacchi {
147*d14abf15SRobert Mustacchi     u32_t not_reset_mask1, reset_mask1, not_reset_mask2, reset_mask2;
148*d14abf15SRobert Mustacchi 
149*d14abf15SRobert Mustacchi     not_reset_mask1 =
150*d14abf15SRobert Mustacchi         MISC_REGISTERS_RESET_REG_1_RST_HC |
151*d14abf15SRobert Mustacchi         MISC_REGISTERS_RESET_REG_1_RST_PXPV |
152*d14abf15SRobert Mustacchi         MISC_REGISTERS_RESET_REG_1_RST_PXP;
153*d14abf15SRobert Mustacchi 
154*d14abf15SRobert Mustacchi     not_reset_mask2 =
155*d14abf15SRobert Mustacchi         MISC_REGISTERS_RESET_REG_2_RST_PCI_MDIO |
156*d14abf15SRobert Mustacchi         MISC_REGISTERS_RESET_REG_2_RST_EMAC0_HARD_CORE |
157*d14abf15SRobert Mustacchi         MISC_REGISTERS_RESET_REG_2_RST_EMAC1_HARD_CORE |
158*d14abf15SRobert Mustacchi         MISC_REGISTERS_RESET_REG_2_RST_MISC_CORE |
159*d14abf15SRobert Mustacchi         MISC_REGISTERS_RESET_REG_2_RST_RBCN |
160*d14abf15SRobert Mustacchi         MISC_REGISTERS_RESET_REG_2_RST_GRC  |
161*d14abf15SRobert Mustacchi         MISC_REGISTERS_RESET_REG_2_RST_MCP_N_RESET_REG_HARD_CORE |
162*d14abf15SRobert Mustacchi         MISC_REGISTERS_RESET_REG_2_RST_MCP_N_HARD_CORE_RST_B;
163*d14abf15SRobert Mustacchi 
164*d14abf15SRobert Mustacchi 
165*d14abf15SRobert Mustacchi     reset_mask1 = 0xffffffff;
166*d14abf15SRobert Mustacchi     reset_mask2 = 0x1ffff;
167*d14abf15SRobert Mustacchi 
168*d14abf15SRobert Mustacchi     if (!reset_mcp)
169*d14abf15SRobert Mustacchi     {
170*d14abf15SRobert Mustacchi         RESET_FLAGS(reset_mask2, MISC_REGISTERS_RESET_REG_2_RST_MCP_N_RESET_CMN_CPU);
171*d14abf15SRobert Mustacchi         RESET_FLAGS(reset_mask2, MISC_REGISTERS_RESET_REG_2_RST_MCP_N_RESET_CMN_CORE);
172*d14abf15SRobert Mustacchi     }
173*d14abf15SRobert Mustacchi 
174*d14abf15SRobert Mustacchi     if (CHIP_IS_E3(pdev)) /* Maybe some day... */
175*d14abf15SRobert Mustacchi     {
176*d14abf15SRobert Mustacchi         reset_mask2 |= MISC_REGISTERS_RESET_REG_2_MSTAT0;
177*d14abf15SRobert Mustacchi         reset_mask2 |= MISC_REGISTERS_RESET_REG_2_MSTAT1;
178*d14abf15SRobert Mustacchi     }
179*d14abf15SRobert Mustacchi 
180*d14abf15SRobert Mustacchi     /* CQ54250, CQ54294, CQ54298, CQ54396
181*d14abf15SRobert Mustacchi      * Error Recovery: break at evbda!lm_dmae_command+960 during error recovery,
182*d14abf15SRobert Mustacchi      * REG_1 must be called after reg_2 so that QM is reset AFTER PXP, this is because
183*d14abf15SRobert Mustacchi      * resetting QM cancels close the gates, initiates request to PXP
184*d14abf15SRobert Mustacchi      * <Ofer Zipin>: theory when QM is reset before PXP: 'close the gates' is de-activated shortly before resetting PXP.
185*d14abf15SRobert Mustacchi      * PSWRQ sends a write request to PGLUE. Then PXP is reset (PGLUE is not reset).
186*d14abf15SRobert Mustacchi      * PGLUE tries to read the payload data from PSWWR, but PSWWR does not respond. The write queue in PGLUE will be stuck.
187*d14abf15SRobert Mustacchi      */
188*d14abf15SRobert Mustacchi 
189*d14abf15SRobert Mustacchi     REG_WR(pdev, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
190*d14abf15SRobert Mustacchi            reset_mask2 & (~not_reset_mask2));
191*d14abf15SRobert Mustacchi 
192*d14abf15SRobert Mustacchi     REG_WR(pdev, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_CLEAR,
193*d14abf15SRobert Mustacchi            reset_mask1 & (~not_reset_mask1));
194*d14abf15SRobert Mustacchi     /* Take blocks out of reset */
195*d14abf15SRobert Mustacchi     REG_WR(pdev, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET, reset_mask2);
196*d14abf15SRobert Mustacchi 
197*d14abf15SRobert Mustacchi     REG_WR(pdev, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_1_SET, reset_mask1);
198*d14abf15SRobert Mustacchi 
199*d14abf15SRobert Mustacchi 
200*d14abf15SRobert Mustacchi 
201*d14abf15SRobert Mustacchi }
202*d14abf15SRobert Mustacchi 
203*d14abf15SRobert Mustacchi /**
204*d14abf15SRobert Mustacchi  * @Description
205*d14abf15SRobert Mustacchi  *      13.2 Poll for Tetris buffer to empty. PSWWR FIFOs are
206*d14abf15SRobert Mustacchi  *      not guaraneteed to empty. wait for all Glue tags to
207*d14abf15SRobert Mustacchi  *      become unused (all read completions have returned).
208*d14abf15SRobert Mustacchi  *
209*d14abf15SRobert Mustacchi  * @param pdev
210*d14abf15SRobert Mustacchi  *
211*d14abf15SRobert Mustacchi  * @return lm_status_t
212*d14abf15SRobert Mustacchi  */
lm_er_empty_tetris_buffer(lm_device_t * pdev)213*d14abf15SRobert Mustacchi static lm_status_t lm_er_empty_tetris_buffer(lm_device_t * pdev)
214*d14abf15SRobert Mustacchi {
215*d14abf15SRobert Mustacchi     u32_t cnt            = 1000;
216*d14abf15SRobert Mustacchi     u32_t sr_cnt         = 0;
217*d14abf15SRobert Mustacchi     u32_t blk_cnt        = 0;
218*d14abf15SRobert Mustacchi     u32_t port_is_idle_0 = 0;
219*d14abf15SRobert Mustacchi     u32_t port_is_idle_1 = 0;
220*d14abf15SRobert Mustacchi     u32_t pgl_exp_rom2   = 0;
221*d14abf15SRobert Mustacchi     u32_t pgl_b_reg_tags = 0;
222*d14abf15SRobert Mustacchi 
223*d14abf15SRobert Mustacchi     do {
224*d14abf15SRobert Mustacchi         sr_cnt  = REG_RD(pdev, PXP2_REG_RD_SR_CNT);
225*d14abf15SRobert Mustacchi         blk_cnt = REG_RD(pdev, PXP2_REG_RD_BLK_CNT);
226*d14abf15SRobert Mustacchi         port_is_idle_0 = REG_RD(pdev, PXP2_REG_RD_PORT_IS_IDLE_0);
227*d14abf15SRobert Mustacchi         port_is_idle_1 = REG_RD(pdev, PXP2_REG_RD_PORT_IS_IDLE_1);
228*d14abf15SRobert Mustacchi         pgl_exp_rom2 = REG_RD(pdev, PXP2_REG_PGL_EXP_ROM2);
229*d14abf15SRobert Mustacchi         pgl_b_reg_tags = REG_RD(pdev, PGLUE_B_REG_TAGS_63_32);
230*d14abf15SRobert Mustacchi 
231*d14abf15SRobert Mustacchi         if (TRUE
232*d14abf15SRobert Mustacchi             && (sr_cnt >= 0x7e)
233*d14abf15SRobert Mustacchi             && (blk_cnt == 0xa0)
234*d14abf15SRobert Mustacchi             && ((port_is_idle_0 & 0x1) == 0x1)
235*d14abf15SRobert Mustacchi             && ((port_is_idle_1 & 0x1) == 0x1)
236*d14abf15SRobert Mustacchi             && (pgl_exp_rom2 == 0xffffffff)
237*d14abf15SRobert Mustacchi             && (!CHIP_IS_E3(pdev) || (pgl_b_reg_tags == 0xffffffff)))
238*d14abf15SRobert Mustacchi         {
239*d14abf15SRobert Mustacchi             break;
240*d14abf15SRobert Mustacchi         }
241*d14abf15SRobert Mustacchi         mm_wait(pdev, 1000);
242*d14abf15SRobert Mustacchi     } while (cnt-- > 0);
243*d14abf15SRobert Mustacchi 
244*d14abf15SRobert Mustacchi     if (cnt == 0) {
245*d14abf15SRobert Mustacchi         DbgMessage(pdev, FATAL, "Tetris buffer didn't get empty or there are still outstanding read requests after 1s!\n");
246*d14abf15SRobert Mustacchi         DbgMessage(pdev, FATAL, "sr_cnt=0x%08x, blk_cnt=0x%08x, port_is_idle_0=0x%08x, port_is_idle_1=0x%08x, pgl_exp_rom2=0x%08x\n",
247*d14abf15SRobert Mustacchi               sr_cnt, blk_cnt, port_is_idle_0, port_is_idle_1, pgl_exp_rom2);
248*d14abf15SRobert Mustacchi         return LM_STATUS_BUSY;
249*d14abf15SRobert Mustacchi     }
250*d14abf15SRobert Mustacchi 
251*d14abf15SRobert Mustacchi     return LM_STATUS_SUCCESS;
252*d14abf15SRobert Mustacchi }
253*d14abf15SRobert Mustacchi 
254*d14abf15SRobert Mustacchi 
255*d14abf15SRobert Mustacchi /**
256*d14abf15SRobert Mustacchi  * @Description
257*d14abf15SRobert Mustacchi  *      13.5.   Poll for IGU VQ to become empty
258*d14abf15SRobert Mustacchi  *
259*d14abf15SRobert Mustacchi  * @param pdev
260*d14abf15SRobert Mustacchi  *
261*d14abf15SRobert Mustacchi  * @return lm_status_t
262*d14abf15SRobert Mustacchi  */
lm_er_poll_igu_vq(lm_device_t * pdev)263*d14abf15SRobert Mustacchi static lm_status_t lm_er_poll_igu_vq(lm_device_t * pdev)
264*d14abf15SRobert Mustacchi {
265*d14abf15SRobert Mustacchi     u32_t cnt       = 1000;
266*d14abf15SRobert Mustacchi     u32_t pend_bits = 0;
267*d14abf15SRobert Mustacchi 
268*d14abf15SRobert Mustacchi     do {
269*d14abf15SRobert Mustacchi         pend_bits  = REG_RD(pdev, IGU_REG_PENDING_BITS_STATUS);
270*d14abf15SRobert Mustacchi 
271*d14abf15SRobert Mustacchi         if (pend_bits == 0)
272*d14abf15SRobert Mustacchi         {
273*d14abf15SRobert Mustacchi             break;
274*d14abf15SRobert Mustacchi         }
275*d14abf15SRobert Mustacchi         mm_wait(pdev, 1000);
276*d14abf15SRobert Mustacchi     } while (cnt-- > 0);
277*d14abf15SRobert Mustacchi 
278*d14abf15SRobert Mustacchi     if (cnt == 0) {
279*d14abf15SRobert Mustacchi         DbgMessage(pdev, FATAL, "Still pending IGU requests pend_bits=%x!\n", pend_bits);
280*d14abf15SRobert Mustacchi 
281*d14abf15SRobert Mustacchi         return LM_STATUS_BUSY;
282*d14abf15SRobert Mustacchi     }
283*d14abf15SRobert Mustacchi 
284*d14abf15SRobert Mustacchi     return LM_STATUS_SUCCESS;
285*d14abf15SRobert Mustacchi }
286*d14abf15SRobert Mustacchi 
287*d14abf15SRobert Mustacchi /**
288*d14abf15SRobert Mustacchi  * @Description
289*d14abf15SRobert Mustacchi  *      This section is based on E2 Recovery Flows Design
290*d14abf15SRobert Mustacchi  *      document by Yuval Eliyahu. Section 12.2 (process kill)
291*d14abf15SRobert Mustacchi  *      item #13. Number below refer to items inside item #13.
292*d14abf15SRobert Mustacchi  *      Some modifications were made to accomidate to E2.
293*d14abf15SRobert Mustacchi  *
294*d14abf15SRobert Mustacchi  * @param pdev
295*d14abf15SRobert Mustacchi  *
296*d14abf15SRobert Mustacchi  * @return lm_status_t
297*d14abf15SRobert Mustacchi  */
lm_er_process_kill(lm_device_t * pdev,u8_t reset_mcp)298*d14abf15SRobert Mustacchi static lm_status_t lm_er_process_kill(lm_device_t *pdev, u8_t reset_mcp)
299*d14abf15SRobert Mustacchi {
300*d14abf15SRobert Mustacchi     lm_status_t lm_status = LM_STATUS_FAILURE;
301*d14abf15SRobert Mustacchi     u32_t magic_val = 0;
302*d14abf15SRobert Mustacchi 
303*d14abf15SRobert Mustacchi     /* 13.2 Empty the Tetris buffer, wait for 1s TODO_ER: is this needed for E2? */
304*d14abf15SRobert Mustacchi     lm_status = lm_er_empty_tetris_buffer(pdev);
305*d14abf15SRobert Mustacchi     if (lm_status != LM_STATUS_SUCCESS)
306*d14abf15SRobert Mustacchi     {
307*d14abf15SRobert Mustacchi         return lm_status;
308*d14abf15SRobert Mustacchi     }
309*d14abf15SRobert Mustacchi 
310*d14abf15SRobert Mustacchi     /* 13.3, 13.4 Close gates #2, #3 and #4 */
311*d14abf15SRobert Mustacchi     lm_er_set_234_gates(pdev, TRUE);
312*d14abf15SRobert Mustacchi 
313*d14abf15SRobert Mustacchi     /* 13.5 Poll for IGU VQ to become empty */
314*d14abf15SRobert Mustacchi     lm_status = lm_er_poll_igu_vq(pdev);
315*d14abf15SRobert Mustacchi     if (lm_status != LM_STATUS_SUCCESS)
316*d14abf15SRobert Mustacchi     {
317*d14abf15SRobert Mustacchi         return lm_status;
318*d14abf15SRobert Mustacchi     }
319*d14abf15SRobert Mustacchi 
320*d14abf15SRobert Mustacchi     /* 13.6 Indicate that "process kill" is in progress to MCP TODO_ER: how/why?  */
321*d14abf15SRobert Mustacchi 
322*d14abf15SRobert Mustacchi     /* 13.7 Clear "unprepared" bit */
323*d14abf15SRobert Mustacchi     REG_WR(pdev, MISC_REG_UNPREPARED, 0);
324*d14abf15SRobert Mustacchi 
325*d14abf15SRobert Mustacchi     /* 13.8 Wait for 1ms to empty GLUE and PCI-E core queues,
326*d14abf15SRobert Mustacchi      * PSWHST, GRC and PSWRD Tetris buffer.
327*d14abf15SRobert Mustacchi      */
328*d14abf15SRobert Mustacchi     mm_wait(pdev, 1000);
329*d14abf15SRobert Mustacchi 
330*d14abf15SRobert Mustacchi     /* Prepare to chip reset: */
331*d14abf15SRobert Mustacchi     /* MCP */
332*d14abf15SRobert Mustacchi     if (reset_mcp)
333*d14abf15SRobert Mustacchi     {
334*d14abf15SRobert Mustacchi         lm_reset_mcp_prep(pdev, &magic_val);
335*d14abf15SRobert Mustacchi     }
336*d14abf15SRobert Mustacchi 
337*d14abf15SRobert Mustacchi     /* 13.11.1 PXP preparations TODO_ER: should this really be called before or only after
338*d14abf15SRobert Mustacchi      * spec says after, bnx2x implementation does this before as well.  */
339*d14abf15SRobert Mustacchi     lm_er_pxp_prep(pdev);
340*d14abf15SRobert Mustacchi 
341*d14abf15SRobert Mustacchi     /* 13.9 reset the chip */
342*d14abf15SRobert Mustacchi     /* 13.10 check that PSWRD, PSWRQ, PSWWR are reset : handled in function  */
343*d14abf15SRobert Mustacchi     lm_er_process_kill_chip_reset(pdev, reset_mcp);
344*d14abf15SRobert Mustacchi 
345*d14abf15SRobert Mustacchi 
346*d14abf15SRobert Mustacchi     /* 13.11 Recover after reset: */
347*d14abf15SRobert Mustacchi     /* MCP */
348*d14abf15SRobert Mustacchi     if (reset_mcp)
349*d14abf15SRobert Mustacchi     {
350*d14abf15SRobert Mustacchi         lm_status = lm_reset_mcp_comp(pdev, magic_val);
351*d14abf15SRobert Mustacchi         if (lm_status != LM_STATUS_SUCCESS)
352*d14abf15SRobert Mustacchi         {
353*d14abf15SRobert Mustacchi             return lm_status;
354*d14abf15SRobert Mustacchi         }
355*d14abf15SRobert Mustacchi     }
356*d14abf15SRobert Mustacchi 
357*d14abf15SRobert Mustacchi     /* Reset the loader for no-mcp mode, mcp has been reset!! */
358*d14abf15SRobert Mustacchi     lm_loader_reset(pdev);
359*d14abf15SRobert Mustacchi 
360*d14abf15SRobert Mustacchi     /* 13.11.1.2 PXP */
361*d14abf15SRobert Mustacchi 
362*d14abf15SRobert Mustacchi     // PXP2 initialization skipped here to address CQ61863:
363*d14abf15SRobert Mustacchi     //  - PXP2 must not be re-initialized.
364*d14abf15SRobert Mustacchi     //  - Starting MCP 7.0.45, PXP2 is initialized by MCP.
365*d14abf15SRobert Mustacchi 
366*d14abf15SRobert Mustacchi     //lm_er_pxp_prep(pdev);
367*d14abf15SRobert Mustacchi 
368*d14abf15SRobert Mustacchi     /* 13.11.2 Open the gates #2, #3 and #4 */
369*d14abf15SRobert Mustacchi     lm_er_set_234_gates(pdev, FALSE);
370*d14abf15SRobert Mustacchi 
371*d14abf15SRobert Mustacchi     /* 13.11.3 TODO_ER:  IGU/AEU preparation bring back the AEU/IGU to a
372*d14abf15SRobert Mustacchi      * reset state, re-enable attentions. This is done in "init" */
373*d14abf15SRobert Mustacchi 
374*d14abf15SRobert Mustacchi     /* Clear the general attention used to notify second engine */
375*d14abf15SRobert Mustacchi     REG_WR(pdev, MISC_REG_AEU_GENERAL_ATTN_20 , 0);
376*d14abf15SRobert Mustacchi     /* Some Notes:
377*d14abf15SRobert Mustacchi      * 1. parity bits will be cleard for blocks that are being reset, so no need to take care of it...
378*d14abf15SRobert Mustacchi      * 2. MCP notification isn't handled yet, when it is leader will need to nofity mcp reset is done.
379*d14abf15SRobert Mustacchi      */
380*d14abf15SRobert Mustacchi     return 0;
381*d14abf15SRobert Mustacchi }
382*d14abf15SRobert Mustacchi 
383*d14abf15SRobert Mustacchi 
384*d14abf15SRobert Mustacchi /**
385*d14abf15SRobert Mustacchi  * @Description
386*d14abf15SRobert Mustacchi  *     Perform the error recovery leader process kill flow.
387*d14abf15SRobert Mustacchi  *
388*d14abf15SRobert Mustacchi  * @param pdev
389*d14abf15SRobert Mustacchi  *
390*d14abf15SRobert Mustacchi  * @return lm_status_t SUCCESS or FAILURE
391*d14abf15SRobert Mustacchi  */
lm_er_leader_reset(lm_device_t * pdev)392*d14abf15SRobert Mustacchi lm_status_t lm_er_leader_reset(lm_device_t *pdev)
393*d14abf15SRobert Mustacchi {
394*d14abf15SRobert Mustacchi     lm_status_t lm_status = LM_STATUS_SUCCESS;
395*d14abf15SRobert Mustacchi     u32_t       cnt       = 1;
396*d14abf15SRobert Mustacchi     u8_t        reset_mcp = FALSE;
397*d14abf15SRobert Mustacchi     u8_t        function_of_opposite_path = 0;
398*d14abf15SRobert Mustacchi 
399*d14abf15SRobert Mustacchi     /* Try to recover after the failure */
400*d14abf15SRobert Mustacchi     /* need to recover on both paths using pretend */
401*d14abf15SRobert Mustacchi     function_of_opposite_path = !PATH_ID(pdev);
402*d14abf15SRobert Mustacchi     do
403*d14abf15SRobert Mustacchi     {
404*d14abf15SRobert Mustacchi         lm_status = lm_er_process_kill(pdev, reset_mcp);
405*d14abf15SRobert Mustacchi         if (lm_status != LM_STATUS_SUCCESS)
406*d14abf15SRobert Mustacchi         {
407*d14abf15SRobert Mustacchi             break;
408*d14abf15SRobert Mustacchi         }
409*d14abf15SRobert Mustacchi 
410*d14abf15SRobert Mustacchi         /* Pretend to the other path... */
411*d14abf15SRobert Mustacchi         if (!reset_mcp)
412*d14abf15SRobert Mustacchi         {
413*d14abf15SRobert Mustacchi             lm_pretend_func(pdev, function_of_opposite_path);
414*d14abf15SRobert Mustacchi             /* Only second go should reset MCP, so that the second engine doesn't get out of close-dg8 before the process is done */
415*d14abf15SRobert Mustacchi             reset_mcp = TRUE;
416*d14abf15SRobert Mustacchi         }
417*d14abf15SRobert Mustacchi     } while (cnt--);
418*d14abf15SRobert Mustacchi 
419*d14abf15SRobert Mustacchi     /* in anycase pretend back... */
420*d14abf15SRobert Mustacchi     lm_pretend_func(pdev, ABS_FUNC_ID(pdev));
421*d14abf15SRobert Mustacchi 
422*d14abf15SRobert Mustacchi     return lm_status;
423*d14abf15SRobert Mustacchi }
424*d14abf15SRobert Mustacchi 
425*d14abf15SRobert Mustacchi /**
426*d14abf15SRobert Mustacchi  * @Description
427*d14abf15SRobert Mustacchi  *      This function notifies the second engine that a
428*d14abf15SRobert Mustacchi  *      attention occured and error recovery will initiate on
429*d14abf15SRobert Mustacchi  *      second engine as well. Only the leader does this meaning
430*d14abf15SRobert Mustacchi  *      that the second engine either hasn't seen that there was
431*d14abf15SRobert Mustacchi  *      an error, or seen it and is waiting (won't initiate
432*d14abf15SRobert Mustacchi  *      leader reset) which means it won't see it anyway...
433*d14abf15SRobert Mustacchi  * @param pdev
434*d14abf15SRobert Mustacchi  *
435*d14abf15SRobert Mustacchi  * @return lm_status_t
436*d14abf15SRobert Mustacchi  */
lm_er_notify_other_path(lm_device_t * pdev)437*d14abf15SRobert Mustacchi lm_status_t lm_er_notify_other_path(lm_device_t *pdev)
438*d14abf15SRobert Mustacchi {
439*d14abf15SRobert Mustacchi     u8_t function_of_opposite_path = 0;
440*d14abf15SRobert Mustacchi 
441*d14abf15SRobert Mustacchi     DbgMessage(pdev, FATAL, "lm_er_notify_other_path\n");
442*d14abf15SRobert Mustacchi     /* Pretend to the other path... */
443*d14abf15SRobert Mustacchi     function_of_opposite_path = lm_er_get_first_func_of_opp_path(pdev);
444*d14abf15SRobert Mustacchi     if (function_of_opposite_path != 0xFF)
445*d14abf15SRobert Mustacchi     {
446*d14abf15SRobert Mustacchi         lm_pretend_func(pdev, function_of_opposite_path);
447*d14abf15SRobert Mustacchi 
448*d14abf15SRobert Mustacchi         REG_WR(pdev, MISC_REG_AEU_GENERAL_ATTN_20 , 1);
449*d14abf15SRobert Mustacchi 
450*d14abf15SRobert Mustacchi         /* in anycase pretend back... */
451*d14abf15SRobert Mustacchi         lm_pretend_func(pdev, ABS_FUNC_ID(pdev));
452*d14abf15SRobert Mustacchi     }
453*d14abf15SRobert Mustacchi     else
454*d14abf15SRobert Mustacchi     {
455*d14abf15SRobert Mustacchi         DbgMessage(pdev, FATAL, "No ebnabled functions on path%d, the pah is not notfied about ER\n",!PATH_ID(pdev));
456*d14abf15SRobert Mustacchi     }
457*d14abf15SRobert Mustacchi 
458*d14abf15SRobert Mustacchi     return LM_STATUS_SUCCESS;
459*d14abf15SRobert Mustacchi }
460*d14abf15SRobert Mustacchi 
461*d14abf15SRobert Mustacchi /**
462*d14abf15SRobert Mustacchi  * @Description
463*d14abf15SRobert Mustacchi  *      This function attaches attentions to NIG / PXP
464*d14abf15SRobert Mustacchi  *      close-the-g8, any attention that is added here should
465*d14abf15SRobert Mustacchi  *      also be added to the lm_recoverable_error function.
466*d14abf15SRobert Mustacchi  * @param pdev
467*d14abf15SRobert Mustacchi  */
lm_er_config_close_the_g8(lm_device_t * pdev)468*d14abf15SRobert Mustacchi void lm_er_config_close_the_g8(lm_device_t *pdev)
469*d14abf15SRobert Mustacchi {
470*d14abf15SRobert Mustacchi     u32_t val;
471*d14abf15SRobert Mustacchi 
472*d14abf15SRobert Mustacchi     if (!pdev->params.enable_error_recovery || CHIP_IS_E1x(pdev))
473*d14abf15SRobert Mustacchi     {
474*d14abf15SRobert Mustacchi         return;
475*d14abf15SRobert Mustacchi     }
476*d14abf15SRobert Mustacchi 
477*d14abf15SRobert Mustacchi     /* HW Attentions (Except Parity which is configured by init-tool / reset-values ) */
478*d14abf15SRobert Mustacchi 
479*d14abf15SRobert Mustacchi     /* QM Block */
480*d14abf15SRobert Mustacchi     val = REG_RD(pdev, MISC_REG_AEU_ENABLE2_NIG_0);
481*d14abf15SRobert Mustacchi     SET_FLAGS(val, AEU_INPUTS_ATTN_BITS_QM_HW_INTERRUPT); /* QM HW Interrupt */
482*d14abf15SRobert Mustacchi     REG_WR(pdev, MISC_REG_AEU_ENABLE2_NIG_0, val);
483*d14abf15SRobert Mustacchi 
484*d14abf15SRobert Mustacchi     val = REG_RD(pdev, MISC_REG_AEU_ENABLE2_PXP_0);
485*d14abf15SRobert Mustacchi     SET_FLAGS(val, AEU_INPUTS_ATTN_BITS_QM_HW_INTERRUPT); /* QM HW Interrupt */
486*d14abf15SRobert Mustacchi     REG_WR(pdev, MISC_REG_AEU_ENABLE2_PXP_0, val);
487*d14abf15SRobert Mustacchi 
488*d14abf15SRobert Mustacchi     /* General Attention 20 (error recovery attention) */
489*d14abf15SRobert Mustacchi     val = REG_RD(pdev, MISC_REG_AEU_ENABLE4_NIG_0);
490*d14abf15SRobert Mustacchi     SET_FLAGS(val, AEU_INPUTS_ATTN_BITS_GRC_MAPPED_GENERAL_ATTN20); /* general attention 20 */
491*d14abf15SRobert Mustacchi     REG_WR(pdev, MISC_REG_AEU_ENABLE4_NIG_0, val);
492*d14abf15SRobert Mustacchi 
493*d14abf15SRobert Mustacchi     val = REG_RD(pdev, MISC_REG_AEU_ENABLE4_PXP_0);
494*d14abf15SRobert Mustacchi     SET_FLAGS(val, AEU_INPUTS_ATTN_BITS_GRC_MAPPED_GENERAL_ATTN20); /* general attention 20 */
495*d14abf15SRobert Mustacchi     REG_WR(pdev, MISC_REG_AEU_ENABLE4_PXP_0, val);
496*d14abf15SRobert Mustacchi 
497*d14abf15SRobert Mustacchi }
498*d14abf15SRobert Mustacchi 
lm_er_get_func_bit(struct _lm_device_t * pdev)499*d14abf15SRobert Mustacchi u32_t lm_er_get_func_bit(struct _lm_device_t *pdev)
500*d14abf15SRobert Mustacchi {
501*d14abf15SRobert Mustacchi     u32_t func_bit = 1 << ABS_FUNC_ID(pdev);
502*d14abf15SRobert Mustacchi     return func_bit;
503*d14abf15SRobert Mustacchi }
504*d14abf15SRobert Mustacchi 
lm_er_get_number_of_functions(u32_t er_register)505*d14abf15SRobert Mustacchi u32_t lm_er_get_number_of_functions(u32_t er_register)
506*d14abf15SRobert Mustacchi {
507*d14abf15SRobert Mustacchi     u8_t i = 0;
508*d14abf15SRobert Mustacchi     u32_t func_num = 0;
509*d14abf15SRobert Mustacchi     for (i = 0; i < MAX_FUNC_NUM; i++)
510*d14abf15SRobert Mustacchi     {
511*d14abf15SRobert Mustacchi         if (er_register & (1 << i))
512*d14abf15SRobert Mustacchi         {
513*d14abf15SRobert Mustacchi             func_num++;
514*d14abf15SRobert Mustacchi         }
515*d14abf15SRobert Mustacchi     }
516*d14abf15SRobert Mustacchi     return func_num;
517*d14abf15SRobert Mustacchi }
518*d14abf15SRobert Mustacchi 
lm_er_get_first_func_of_opp_path(struct _lm_device_t * pdev)519*d14abf15SRobert Mustacchi u8_t lm_er_get_first_func_of_opp_path(struct _lm_device_t *pdev)
520*d14abf15SRobert Mustacchi {
521*d14abf15SRobert Mustacchi     lm_status_t lm_status           = LM_STATUS_SUCCESS;
522*d14abf15SRobert Mustacchi     u32_t       por_aux_register    = 0;
523*d14abf15SRobert Mustacchi     u8_t        opposite_path       = 0;
524*d14abf15SRobert Mustacchi     u8_t        i                   = 0;
525*d14abf15SRobert Mustacchi     u8_t        func_of_opp_path    = 0xFF;
526*d14abf15SRobert Mustacchi 
527*d14abf15SRobert Mustacchi     if (IS_ASSIGNED_TO_VM_PFDEV(pdev))
528*d14abf15SRobert Mustacchi     {
529*d14abf15SRobert Mustacchi         lm_status = lm_hw_lock(pdev, HW_LOCK_RESOURCE_RECOVERY_REG, TRUE);
530*d14abf15SRobert Mustacchi         if (LM_STATUS_SUCCESS == lm_status)
531*d14abf15SRobert Mustacchi         {
532*d14abf15SRobert Mustacchi             por_aux_register = REG_RD(pdev, LM_ERROR_RECOVERY_COUNTER_HW_REGISTER);
533*d14abf15SRobert Mustacchi             lm_status = lm_hw_unlock(pdev, HW_LOCK_RESOURCE_RECOVERY_REG);
534*d14abf15SRobert Mustacchi             if (LM_STATUS_SUCCESS != lm_status)
535*d14abf15SRobert Mustacchi             {
536*d14abf15SRobert Mustacchi                 DbgBreakMsg("Failed to release HW Recovery Counter lock.\n");
537*d14abf15SRobert Mustacchi             }
538*d14abf15SRobert Mustacchi             opposite_path = !PATH_ID(pdev);
539*d14abf15SRobert Mustacchi             for (i = 0; i < MAX_FUNC_NUM/2; i++)
540*d14abf15SRobert Mustacchi             {
541*d14abf15SRobert Mustacchi                 if (por_aux_register & (1 << (i*2 + opposite_path)))
542*d14abf15SRobert Mustacchi                 {
543*d14abf15SRobert Mustacchi                     func_of_opp_path = i*2 + opposite_path;
544*d14abf15SRobert Mustacchi                     break;
545*d14abf15SRobert Mustacchi                 }
546*d14abf15SRobert Mustacchi             }
547*d14abf15SRobert Mustacchi         }
548*d14abf15SRobert Mustacchi         else
549*d14abf15SRobert Mustacchi         {
550*d14abf15SRobert Mustacchi             DbgBreakMsg("Failed to acquire HW Recovery Counter lock.\n");
551*d14abf15SRobert Mustacchi         }
552*d14abf15SRobert Mustacchi     }
553*d14abf15SRobert Mustacchi     else
554*d14abf15SRobert Mustacchi     {
555*d14abf15SRobert Mustacchi         func_of_opp_path = !PATH_ID(pdev);
556*d14abf15SRobert Mustacchi     }
557*d14abf15SRobert Mustacchi     return func_of_opp_path;
558*d14abf15SRobert Mustacchi }
559*d14abf15SRobert Mustacchi 
lm_er_inc_load_cnt(lm_device_t * pdev,u8_t sync_it)560*d14abf15SRobert Mustacchi u32_t lm_er_inc_load_cnt(lm_device_t *pdev, u8_t sync_it)
561*d14abf15SRobert Mustacchi {
562*d14abf15SRobert Mustacchi     lm_status_t             lm_status = LM_STATUS_SUCCESS;
563*d14abf15SRobert Mustacchi     u32_t                   counter = 0;
564*d14abf15SRobert Mustacchi     u32_t                   por_aux_register = 0;
565*d14abf15SRobert Mustacchi     u32_t                   func_er_bit = 0;
566*d14abf15SRobert Mustacchi 
567*d14abf15SRobert Mustacchi     if (sync_it)
568*d14abf15SRobert Mustacchi     {
569*d14abf15SRobert Mustacchi         lm_status = lm_hw_lock(pdev, HW_LOCK_RESOURCE_RECOVERY_REG, TRUE);
570*d14abf15SRobert Mustacchi     }
571*d14abf15SRobert Mustacchi 
572*d14abf15SRobert Mustacchi     if (LM_STATUS_SUCCESS == lm_status)
573*d14abf15SRobert Mustacchi     {
574*d14abf15SRobert Mustacchi         por_aux_register = REG_RD(pdev, LM_ERROR_RECOVERY_COUNTER_HW_REGISTER);
575*d14abf15SRobert Mustacchi         func_er_bit = lm_er_get_func_bit(pdev);
576*d14abf15SRobert Mustacchi         if ((por_aux_register & func_er_bit))
577*d14abf15SRobert Mustacchi         {
578*d14abf15SRobert Mustacchi             if (sync_it)
579*d14abf15SRobert Mustacchi             {
580*d14abf15SRobert Mustacchi                 lm_status = lm_hw_unlock(pdev, HW_LOCK_RESOURCE_RECOVERY_REG);
581*d14abf15SRobert Mustacchi             }
582*d14abf15SRobert Mustacchi             DbgMessage(pdev, FATAL, "HW Recovery bit was not cleared in previous session.\n");
583*d14abf15SRobert Mustacchi             pdev->debug_info.er_bit_is_set_already = TRUE;
584*d14abf15SRobert Mustacchi             pdev->debug_info.er_bit_from_previous_sessions++;
585*d14abf15SRobert Mustacchi         }
586*d14abf15SRobert Mustacchi         else
587*d14abf15SRobert Mustacchi         {
588*d14abf15SRobert Mustacchi             por_aux_register |= func_er_bit;
589*d14abf15SRobert Mustacchi             REG_WR(pdev, LM_ERROR_RECOVERY_COUNTER_HW_REGISTER, por_aux_register);
590*d14abf15SRobert Mustacchi             pdev->debug_info.er_bit_is_set_already = FALSE;
591*d14abf15SRobert Mustacchi             if (sync_it)
592*d14abf15SRobert Mustacchi             {
593*d14abf15SRobert Mustacchi                 lm_status = lm_hw_unlock(pdev, HW_LOCK_RESOURCE_RECOVERY_REG);
594*d14abf15SRobert Mustacchi             }
595*d14abf15SRobert Mustacchi         }
596*d14abf15SRobert Mustacchi         if (LM_STATUS_SUCCESS != lm_status)
597*d14abf15SRobert Mustacchi         {
598*d14abf15SRobert Mustacchi             DbgBreakMsg("Failed to release HW Recovery Counter lock.\n");
599*d14abf15SRobert Mustacchi         }
600*d14abf15SRobert Mustacchi         counter = lm_er_get_number_of_functions(por_aux_register);
601*d14abf15SRobert Mustacchi     }
602*d14abf15SRobert Mustacchi     else
603*d14abf15SRobert Mustacchi     {
604*d14abf15SRobert Mustacchi         DbgBreakMsg("Failed to acquire HW Recovery Counter lock.\n");
605*d14abf15SRobert Mustacchi     }
606*d14abf15SRobert Mustacchi     return counter;
607*d14abf15SRobert Mustacchi }
608*d14abf15SRobert Mustacchi 
lm_er_dec_load_cnt(lm_device_t * pdev,u8_t sync_it)609*d14abf15SRobert Mustacchi u32_t lm_er_dec_load_cnt(lm_device_t *pdev, u8_t sync_it)
610*d14abf15SRobert Mustacchi {
611*d14abf15SRobert Mustacchi     lm_status_t             lm_status = LM_STATUS_SUCCESS;
612*d14abf15SRobert Mustacchi     u32_t                   counter = 0;
613*d14abf15SRobert Mustacchi     u32_t                   por_aux_register = 0;
614*d14abf15SRobert Mustacchi     u32_t                   func_er_bit = 0;
615*d14abf15SRobert Mustacchi 
616*d14abf15SRobert Mustacchi     if (sync_it)
617*d14abf15SRobert Mustacchi     {
618*d14abf15SRobert Mustacchi         lm_status = lm_hw_lock(pdev, HW_LOCK_RESOURCE_RECOVERY_REG, TRUE);
619*d14abf15SRobert Mustacchi     }
620*d14abf15SRobert Mustacchi 
621*d14abf15SRobert Mustacchi     if (LM_STATUS_SUCCESS == lm_status)
622*d14abf15SRobert Mustacchi     {
623*d14abf15SRobert Mustacchi         por_aux_register = REG_RD(pdev, LM_ERROR_RECOVERY_COUNTER_HW_REGISTER);
624*d14abf15SRobert Mustacchi         func_er_bit = lm_er_get_func_bit(pdev);
625*d14abf15SRobert Mustacchi         if (!(por_aux_register & func_er_bit))
626*d14abf15SRobert Mustacchi         {
627*d14abf15SRobert Mustacchi             if (sync_it)
628*d14abf15SRobert Mustacchi             {
629*d14abf15SRobert Mustacchi                 lm_status = lm_hw_unlock(pdev, HW_LOCK_RESOURCE_RECOVERY_REG);
630*d14abf15SRobert Mustacchi             }
631*d14abf15SRobert Mustacchi             DbgMessage(pdev, FATAL, "HW Recovery bit is clear already.\n");
632*d14abf15SRobert Mustacchi         }
633*d14abf15SRobert Mustacchi         else
634*d14abf15SRobert Mustacchi         {
635*d14abf15SRobert Mustacchi             por_aux_register &= ~func_er_bit;
636*d14abf15SRobert Mustacchi             REG_WR(pdev, LM_ERROR_RECOVERY_COUNTER_HW_REGISTER, por_aux_register);
637*d14abf15SRobert Mustacchi             if (sync_it)
638*d14abf15SRobert Mustacchi             {
639*d14abf15SRobert Mustacchi                 lm_status = lm_hw_unlock(pdev, HW_LOCK_RESOURCE_RECOVERY_REG);
640*d14abf15SRobert Mustacchi             }
641*d14abf15SRobert Mustacchi         }
642*d14abf15SRobert Mustacchi         if (LM_STATUS_SUCCESS != lm_status)
643*d14abf15SRobert Mustacchi         {
644*d14abf15SRobert Mustacchi             DbgBreakMsg("Failed to release HW Recovery Counter lock.\n");
645*d14abf15SRobert Mustacchi         }
646*d14abf15SRobert Mustacchi         counter = lm_er_get_number_of_functions(por_aux_register);
647*d14abf15SRobert Mustacchi     }
648*d14abf15SRobert Mustacchi     else
649*d14abf15SRobert Mustacchi     {
650*d14abf15SRobert Mustacchi         DbgBreakMsg("Failed to acquire HW Recovery Counter lock.\n");
651*d14abf15SRobert Mustacchi     }
652*d14abf15SRobert Mustacchi     return counter;
653*d14abf15SRobert Mustacchi }
654*d14abf15SRobert Mustacchi 
lm_er_get_load_cnt(lm_device_t * pdev,u8_t sync_it)655*d14abf15SRobert Mustacchi u32_t lm_er_get_load_cnt(lm_device_t *pdev, u8_t sync_it)
656*d14abf15SRobert Mustacchi {
657*d14abf15SRobert Mustacchi     lm_status_t             lm_status = LM_STATUS_SUCCESS;
658*d14abf15SRobert Mustacchi     u32_t                   counter = 0;
659*d14abf15SRobert Mustacchi     u32_t                   por_aux_register = 0;
660*d14abf15SRobert Mustacchi 
661*d14abf15SRobert Mustacchi     if (sync_it)
662*d14abf15SRobert Mustacchi     {
663*d14abf15SRobert Mustacchi         lm_status = lm_hw_lock(pdev, HW_LOCK_RESOURCE_RECOVERY_REG, TRUE);
664*d14abf15SRobert Mustacchi     }
665*d14abf15SRobert Mustacchi 
666*d14abf15SRobert Mustacchi     if (LM_STATUS_SUCCESS == lm_status)
667*d14abf15SRobert Mustacchi     {
668*d14abf15SRobert Mustacchi         por_aux_register = REG_RD(pdev, LM_ERROR_RECOVERY_COUNTER_HW_REGISTER);
669*d14abf15SRobert Mustacchi         if (sync_it)
670*d14abf15SRobert Mustacchi         {
671*d14abf15SRobert Mustacchi             lm_status = lm_hw_unlock(pdev, HW_LOCK_RESOURCE_RECOVERY_REG);
672*d14abf15SRobert Mustacchi             if (LM_STATUS_SUCCESS != lm_status)
673*d14abf15SRobert Mustacchi             {
674*d14abf15SRobert Mustacchi                 DbgBreakMsg("Failed to release HW Recovery Counter lock.\n");
675*d14abf15SRobert Mustacchi             }
676*d14abf15SRobert Mustacchi         }
677*d14abf15SRobert Mustacchi         counter = lm_er_get_number_of_functions(por_aux_register);
678*d14abf15SRobert Mustacchi     }
679*d14abf15SRobert Mustacchi     else
680*d14abf15SRobert Mustacchi     {
681*d14abf15SRobert Mustacchi         DbgBreakMsg("Failed to acquire HW Recovery Counter lock.\n");
682*d14abf15SRobert Mustacchi     }
683*d14abf15SRobert Mustacchi     return counter;
684*d14abf15SRobert Mustacchi }
685*d14abf15SRobert Mustacchi 
lm_er_clear_load_cnt(lm_device_t * pdev,u8_t sync_it)686*d14abf15SRobert Mustacchi void lm_er_clear_load_cnt(lm_device_t *pdev, u8_t sync_it)
687*d14abf15SRobert Mustacchi {
688*d14abf15SRobert Mustacchi     lm_status_t             lm_status = LM_STATUS_SUCCESS;
689*d14abf15SRobert Mustacchi 
690*d14abf15SRobert Mustacchi     if (sync_it)
691*d14abf15SRobert Mustacchi     {
692*d14abf15SRobert Mustacchi         lm_status = lm_hw_lock(pdev, HW_LOCK_RESOURCE_RECOVERY_REG, TRUE);
693*d14abf15SRobert Mustacchi     }
694*d14abf15SRobert Mustacchi     if (LM_STATUS_SUCCESS == lm_status)
695*d14abf15SRobert Mustacchi     {
696*d14abf15SRobert Mustacchi         REG_WR(pdev, LM_ERROR_RECOVERY_COUNTER_HW_REGISTER, 0);
697*d14abf15SRobert Mustacchi         if (sync_it)
698*d14abf15SRobert Mustacchi         {
699*d14abf15SRobert Mustacchi             lm_status = lm_hw_unlock(pdev, HW_LOCK_RESOURCE_RECOVERY_REG);
700*d14abf15SRobert Mustacchi             if (LM_STATUS_SUCCESS != lm_status)
701*d14abf15SRobert Mustacchi             {
702*d14abf15SRobert Mustacchi                 DbgBreakMsg("Failed to release HW Recovery Counter lock.\n");
703*d14abf15SRobert Mustacchi             }
704*d14abf15SRobert Mustacchi         }
705*d14abf15SRobert Mustacchi     }
706*d14abf15SRobert Mustacchi     else
707*d14abf15SRobert Mustacchi     {
708*d14abf15SRobert Mustacchi         DbgBreakMsg("Failed to acquire HW Recovery Counter lock.\n");
709*d14abf15SRobert Mustacchi     }
710*d14abf15SRobert Mustacchi }
711*d14abf15SRobert Mustacchi 
lm_er_set_recover_done(lm_device_t * pdev,u8_t sync_it)712*d14abf15SRobert Mustacchi void lm_er_set_recover_done(lm_device_t *pdev, u8_t sync_it)
713*d14abf15SRobert Mustacchi {
714*d14abf15SRobert Mustacchi     lm_status_t             lm_status = LM_STATUS_SUCCESS;
715*d14abf15SRobert Mustacchi     u32_t                   por_aux_register = 0;
716*d14abf15SRobert Mustacchi 
717*d14abf15SRobert Mustacchi 
718*d14abf15SRobert Mustacchi     DbgMessage(pdev, FATAL, "Setting recovery in progress = 0\n");
719*d14abf15SRobert Mustacchi     if (sync_it)
720*d14abf15SRobert Mustacchi     {
721*d14abf15SRobert Mustacchi         lm_status = lm_hw_lock(pdev, HW_LOCK_RESOURCE_RECOVERY_REG, TRUE);
722*d14abf15SRobert Mustacchi     }
723*d14abf15SRobert Mustacchi     if (LM_STATUS_SUCCESS == lm_status)
724*d14abf15SRobert Mustacchi     {
725*d14abf15SRobert Mustacchi         por_aux_register = REG_RD(pdev, LM_ERROR_RECOVERY_COUNTER_HW_REGISTER);
726*d14abf15SRobert Mustacchi         por_aux_register &= ~LM_ERROR_RECOVERY_IN_PROGRESS_FLAG;
727*d14abf15SRobert Mustacchi         REG_WR(pdev, LM_ERROR_RECOVERY_COUNTER_HW_REGISTER, por_aux_register);
728*d14abf15SRobert Mustacchi         if (sync_it)
729*d14abf15SRobert Mustacchi         {
730*d14abf15SRobert Mustacchi             lm_status = lm_hw_unlock(pdev, HW_LOCK_RESOURCE_RECOVERY_REG);
731*d14abf15SRobert Mustacchi             if (LM_STATUS_SUCCESS != lm_status)
732*d14abf15SRobert Mustacchi             {
733*d14abf15SRobert Mustacchi                 DbgBreakMsg("Failed to release HW Recovery Counter lock.\n");
734*d14abf15SRobert Mustacchi             }
735*d14abf15SRobert Mustacchi         }
736*d14abf15SRobert Mustacchi     }
737*d14abf15SRobert Mustacchi     else
738*d14abf15SRobert Mustacchi     {
739*d14abf15SRobert Mustacchi         DbgBreakMsg("Failed to acquire HW Recovery Counter lock.\n");
740*d14abf15SRobert Mustacchi     }
741*d14abf15SRobert Mustacchi }
742*d14abf15SRobert Mustacchi 
lm_er_set_recover_in_progress(lm_device_t * pdev,u8_t sync_it)743*d14abf15SRobert Mustacchi void lm_er_set_recover_in_progress(lm_device_t *pdev, u8_t sync_it)
744*d14abf15SRobert Mustacchi {
745*d14abf15SRobert Mustacchi     lm_status_t             lm_status = LM_STATUS_SUCCESS;
746*d14abf15SRobert Mustacchi     u32_t                   por_aux_register = 0;
747*d14abf15SRobert Mustacchi 
748*d14abf15SRobert Mustacchi     DbgMessage(pdev, FATAL, "Setting recovery in progress = 1\n");
749*d14abf15SRobert Mustacchi     if (sync_it)
750*d14abf15SRobert Mustacchi     {
751*d14abf15SRobert Mustacchi         lm_status = lm_hw_lock(pdev, HW_LOCK_RESOURCE_RECOVERY_REG, TRUE);
752*d14abf15SRobert Mustacchi     }
753*d14abf15SRobert Mustacchi     if (LM_STATUS_SUCCESS == lm_status)
754*d14abf15SRobert Mustacchi     {
755*d14abf15SRobert Mustacchi         por_aux_register = REG_RD(pdev, LM_ERROR_RECOVERY_COUNTER_HW_REGISTER);
756*d14abf15SRobert Mustacchi         por_aux_register |= LM_ERROR_RECOVERY_IN_PROGRESS_FLAG;
757*d14abf15SRobert Mustacchi         REG_WR(pdev, LM_ERROR_RECOVERY_COUNTER_HW_REGISTER, por_aux_register);
758*d14abf15SRobert Mustacchi         if (sync_it)
759*d14abf15SRobert Mustacchi         {
760*d14abf15SRobert Mustacchi             lm_status = lm_hw_unlock(pdev, HW_LOCK_RESOURCE_RECOVERY_REG);
761*d14abf15SRobert Mustacchi             if (LM_STATUS_SUCCESS != lm_status)
762*d14abf15SRobert Mustacchi             {
763*d14abf15SRobert Mustacchi                 DbgBreakMsg("Failed to release HW Recovery Counter lock.\n");
764*d14abf15SRobert Mustacchi             }
765*d14abf15SRobert Mustacchi         }
766*d14abf15SRobert Mustacchi     }
767*d14abf15SRobert Mustacchi     else
768*d14abf15SRobert Mustacchi     {
769*d14abf15SRobert Mustacchi         DbgBreakMsg("Failed to acquire HW Recovery Counter lock.\n");
770*d14abf15SRobert Mustacchi     }
771*d14abf15SRobert Mustacchi }
772*d14abf15SRobert Mustacchi 
773*d14abf15SRobert Mustacchi 
lm_er_recovery_in_progress(lm_device_t * pdev,u8_t sync_it)774*d14abf15SRobert Mustacchi u8_t lm_er_recovery_in_progress(lm_device_t *pdev, u8_t sync_it)
775*d14abf15SRobert Mustacchi {
776*d14abf15SRobert Mustacchi     lm_status_t             lm_status = LM_STATUS_SUCCESS;
777*d14abf15SRobert Mustacchi     u32_t                   por_aux_register = 0;
778*d14abf15SRobert Mustacchi     u8_t                    is_progress = FALSE;
779*d14abf15SRobert Mustacchi 
780*d14abf15SRobert Mustacchi     if (sync_it)
781*d14abf15SRobert Mustacchi     {
782*d14abf15SRobert Mustacchi         lm_status = lm_hw_lock(pdev, HW_LOCK_RESOURCE_RECOVERY_REG, TRUE);
783*d14abf15SRobert Mustacchi     }
784*d14abf15SRobert Mustacchi     if (LM_STATUS_SUCCESS == lm_status)
785*d14abf15SRobert Mustacchi     {
786*d14abf15SRobert Mustacchi         por_aux_register = REG_RD(pdev, LM_ERROR_RECOVERY_COUNTER_HW_REGISTER);
787*d14abf15SRobert Mustacchi         if (sync_it)
788*d14abf15SRobert Mustacchi         {
789*d14abf15SRobert Mustacchi             lm_status = lm_hw_unlock(pdev, HW_LOCK_RESOURCE_RECOVERY_REG);
790*d14abf15SRobert Mustacchi             if (LM_STATUS_SUCCESS != lm_status)
791*d14abf15SRobert Mustacchi             {
792*d14abf15SRobert Mustacchi                 DbgBreakMsg("Failed to release HW Recovery Counter lock.\n");
793*d14abf15SRobert Mustacchi             }
794*d14abf15SRobert Mustacchi         }
795*d14abf15SRobert Mustacchi         if (por_aux_register & LM_ERROR_RECOVERY_IN_PROGRESS_FLAG)
796*d14abf15SRobert Mustacchi         {
797*d14abf15SRobert Mustacchi             is_progress = TRUE;
798*d14abf15SRobert Mustacchi         }
799*d14abf15SRobert Mustacchi     }
800*d14abf15SRobert Mustacchi     else
801*d14abf15SRobert Mustacchi     {
802*d14abf15SRobert Mustacchi         DbgBreakMsg("Failed to acquire HW Recovery Counter lock.\n");
803*d14abf15SRobert Mustacchi     }
804*d14abf15SRobert Mustacchi     return is_progress;
805*d14abf15SRobert Mustacchi }
806*d14abf15SRobert Mustacchi 
807