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