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  *
35*d14abf15SRobert Mustacchi  *
36*d14abf15SRobert Mustacchi  * History:
37*d14abf15SRobert Mustacchi  *    03/21/03 Hav Khauv        Inception.
38*d14abf15SRobert Mustacchi  ******************************************************************************/
39*d14abf15SRobert Mustacchi 
40*d14abf15SRobert Mustacchi #include "lm5710.h"
41*d14abf15SRobert Mustacchi 
42*d14abf15SRobert Mustacchi #define NVRAM_TIMEOUT_COUNT                     100000
43*d14abf15SRobert Mustacchi 
44*d14abf15SRobert Mustacchi 
45*d14abf15SRobert Mustacchi /*******************************************************************************
46*d14abf15SRobert Mustacchi  * Description:
47*d14abf15SRobert Mustacchi  *
48*d14abf15SRobert Mustacchi  * Return:
49*d14abf15SRobert Mustacchi  ******************************************************************************/
50*d14abf15SRobert Mustacchi static lm_status_t
acquire_nvram_lock(lm_device_t * pdev)51*d14abf15SRobert Mustacchi acquire_nvram_lock(
52*d14abf15SRobert Mustacchi     lm_device_t *pdev)
53*d14abf15SRobert Mustacchi {
54*d14abf15SRobert Mustacchi     lm_status_t lm_status;
55*d14abf15SRobert Mustacchi     u32_t j, cnt;
56*d14abf15SRobert Mustacchi     u32_t val;
57*d14abf15SRobert Mustacchi     u8_t port_num = PORT_ID(pdev); /* TBD - E1H: nvram lock � DOES NOT scale to 8 functions! (only 4 clients)
58*d14abf15SRobert Mustacchi                                     * 1. Can we assume no concurrent access by control applications?
59*d14abf15SRobert Mustacchi                                     * 2. If not, the MISC lock is our backup */
60*d14abf15SRobert Mustacchi 
61*d14abf15SRobert Mustacchi     DbgMessage(pdev, VERBOSEnv, "### acquire_nvram_lock\n");
62*d14abf15SRobert Mustacchi     /* Adjust timeout for emulation/FPGA */
63*d14abf15SRobert Mustacchi     cnt = NVRAM_TIMEOUT_COUNT;
64*d14abf15SRobert Mustacchi     if (CHIP_REV_IS_EMUL(pdev)) cnt *= 100;
65*d14abf15SRobert Mustacchi 
66*d14abf15SRobert Mustacchi     val = 0;
67*d14abf15SRobert Mustacchi 
68*d14abf15SRobert Mustacchi     /* Request access to the flash interface. */
69*d14abf15SRobert Mustacchi     REG_WR(pdev, MCP_REG_MCPR_NVM_SW_ARB, (MCPR_NVM_SW_ARB_ARB_REQ_SET1 << port_num ));
70*d14abf15SRobert Mustacchi     for(j = 0; j < cnt*10; j++)
71*d14abf15SRobert Mustacchi     {
72*d14abf15SRobert Mustacchi         val=REG_RD(pdev, MCP_REG_MCPR_NVM_SW_ARB);
73*d14abf15SRobert Mustacchi         if(val & (MCPR_NVM_SW_ARB_ARB_ARB1 << port_num))
74*d14abf15SRobert Mustacchi         {
75*d14abf15SRobert Mustacchi             break;
76*d14abf15SRobert Mustacchi         }
77*d14abf15SRobert Mustacchi 
78*d14abf15SRobert Mustacchi         mm_wait(pdev, 5);
79*d14abf15SRobert Mustacchi     }
80*d14abf15SRobert Mustacchi 
81*d14abf15SRobert Mustacchi     if(val & (MCPR_NVM_SW_ARB_ARB_ARB1 << port_num))
82*d14abf15SRobert Mustacchi     {
83*d14abf15SRobert Mustacchi         lm_status = LM_STATUS_SUCCESS;
84*d14abf15SRobert Mustacchi     }
85*d14abf15SRobert Mustacchi     else
86*d14abf15SRobert Mustacchi     {
87*d14abf15SRobert Mustacchi         DbgMessage(NULL, FATAL, "Value of MCP_REG_MCPR_NVM_SW_ARB is 0x%x\n", val);
88*d14abf15SRobert Mustacchi         DbgBreakMsg("Cannot get access to nvram interface.\n");
89*d14abf15SRobert Mustacchi 
90*d14abf15SRobert Mustacchi         lm_status = LM_STATUS_BUSY;
91*d14abf15SRobert Mustacchi     }
92*d14abf15SRobert Mustacchi 
93*d14abf15SRobert Mustacchi     return lm_status;
94*d14abf15SRobert Mustacchi } /* acquire_nvram_lock */
95*d14abf15SRobert Mustacchi 
96*d14abf15SRobert Mustacchi 
97*d14abf15SRobert Mustacchi 
98*d14abf15SRobert Mustacchi /*******************************************************************************
99*d14abf15SRobert Mustacchi  * Description:
100*d14abf15SRobert Mustacchi  *
101*d14abf15SRobert Mustacchi  * Return:
102*d14abf15SRobert Mustacchi  ******************************************************************************/
103*d14abf15SRobert Mustacchi static void
release_nvram_lock(lm_device_t * pdev)104*d14abf15SRobert Mustacchi release_nvram_lock(
105*d14abf15SRobert Mustacchi     lm_device_t *pdev)
106*d14abf15SRobert Mustacchi {
107*d14abf15SRobert Mustacchi     u32_t j, cnt;
108*d14abf15SRobert Mustacchi     u32_t val;
109*d14abf15SRobert Mustacchi     u8_t port_num = PORT_ID(pdev);
110*d14abf15SRobert Mustacchi 
111*d14abf15SRobert Mustacchi     DbgMessage(pdev, VERBOSEnv, "### release_nvram_lock\n");
112*d14abf15SRobert Mustacchi     /* Adjust timeout for emulation/FPGA */
113*d14abf15SRobert Mustacchi     cnt = NVRAM_TIMEOUT_COUNT;
114*d14abf15SRobert Mustacchi     if (CHIP_REV_IS_EMUL(pdev)) cnt *= 100;
115*d14abf15SRobert Mustacchi 
116*d14abf15SRobert Mustacchi     /* Relinquish nvram interface. */
117*d14abf15SRobert Mustacchi     REG_WR(pdev,  MCP_REG_MCPR_NVM_SW_ARB, (MCPR_NVM_SW_ARB_ARB_REQ_CLR1 << port_num));
118*d14abf15SRobert Mustacchi 
119*d14abf15SRobert Mustacchi     val = 0;
120*d14abf15SRobert Mustacchi 
121*d14abf15SRobert Mustacchi     for(j = 0; j < cnt; j++)
122*d14abf15SRobert Mustacchi     {
123*d14abf15SRobert Mustacchi         val=REG_RD(pdev, MCP_REG_MCPR_NVM_SW_ARB);
124*d14abf15SRobert Mustacchi         if(!(val & (MCPR_NVM_SW_ARB_ARB_ARB1 << port_num)))
125*d14abf15SRobert Mustacchi         {
126*d14abf15SRobert Mustacchi             break;
127*d14abf15SRobert Mustacchi         }
128*d14abf15SRobert Mustacchi 
129*d14abf15SRobert Mustacchi         mm_wait(pdev, 5);
130*d14abf15SRobert Mustacchi     }
131*d14abf15SRobert Mustacchi 
132*d14abf15SRobert Mustacchi     DbgBreakIf(val & (MCPR_NVM_SW_ARB_ARB_ARB1 << port_num));
133*d14abf15SRobert Mustacchi } /* release_nvram_lock */
134*d14abf15SRobert Mustacchi 
135*d14abf15SRobert Mustacchi 
136*d14abf15SRobert Mustacchi #if 0
137*d14abf15SRobert Mustacchi /*******************************************************************************
138*d14abf15SRobert Mustacchi * Description:
139*d14abf15SRobert Mustacchi *
140*d14abf15SRobert Mustacchi * Return:
141*d14abf15SRobert Mustacchi *
142*d14abf15SRobert Mustacchi ******************************************************************************/
143*d14abf15SRobert Mustacchi static lm_status_t
144*d14abf15SRobert Mustacchi enable_nvram_write(
145*d14abf15SRobert Mustacchi    lm_device_t *pdev)
146*d14abf15SRobert Mustacchi {
147*d14abf15SRobert Mustacchi     u32_t val, j, cnt;
148*d14abf15SRobert Mustacchi     lm_status_t lm_status;
149*d14abf15SRobert Mustacchi 
150*d14abf15SRobert Mustacchi     lm_status = LM_STATUS_SUCCESS;
151*d14abf15SRobert Mustacchi 
152*d14abf15SRobert Mustacchi     DbgMessage(pdev, INFORMnv, "### enable_nvram_write\n");
153*d14abf15SRobert Mustacchi 
154*d14abf15SRobert Mustacchi     /* Need to clear DONE bit separately. */
155*d14abf15SRobert Mustacchi     REG_WR(pdev, MCP_REG_MCPR_NVM_COMMAND, MCPR_NVM_COMMAND_DONE);
156*d14abf15SRobert Mustacchi 
157*d14abf15SRobert Mustacchi     /* Issue a write enable command. */
158*d14abf15SRobert Mustacchi     REG_WR(pdev, MCP_REG_MCPR_NVM_COMMAND, MCPR_NVM_COMMAND_DOIT | MCPR_NVM_COMMAND_WREN);
159*d14abf15SRobert Mustacchi 
160*d14abf15SRobert Mustacchi     /* Adjust timeout for emulation/FPGA */
161*d14abf15SRobert Mustacchi     cnt = NVRAM_TIMEOUT_COUNT;
162*d14abf15SRobert Mustacchi     if (CHIP_REV(pdev) == CHIP_REV_EMUL) cnt *= 100;
163*d14abf15SRobert Mustacchi 
164*d14abf15SRobert Mustacchi     lm_status = LM_STATUS_BUSY;
165*d14abf15SRobert Mustacchi 
166*d14abf15SRobert Mustacchi     for(j = 0; j < cnt; j++)
167*d14abf15SRobert Mustacchi     {
168*d14abf15SRobert Mustacchi         mm_wait(pdev, 5);
169*d14abf15SRobert Mustacchi 
170*d14abf15SRobert Mustacchi         val=REG_RD(pdev,  MCP_REG_MCPR_NVM_COMMAND);
171*d14abf15SRobert Mustacchi         if(val & MCPR_NVM_COMMAND_DONE)
172*d14abf15SRobert Mustacchi         {
173*d14abf15SRobert Mustacchi             lm_status = LM_STATUS_SUCCESS;
174*d14abf15SRobert Mustacchi             break;
175*d14abf15SRobert Mustacchi         }
176*d14abf15SRobert Mustacchi     }
177*d14abf15SRobert Mustacchi 
178*d14abf15SRobert Mustacchi     return lm_status;
179*d14abf15SRobert Mustacchi } /* enable_nvram_write */
180*d14abf15SRobert Mustacchi 
181*d14abf15SRobert Mustacchi 
182*d14abf15SRobert Mustacchi 
183*d14abf15SRobert Mustacchi /*******************************************************************************
184*d14abf15SRobert Mustacchi * Description:
185*d14abf15SRobert Mustacchi *
186*d14abf15SRobert Mustacchi * Return:
187*d14abf15SRobert Mustacchi *
188*d14abf15SRobert Mustacchi ******************************************************************************/
189*d14abf15SRobert Mustacchi static lm_status_t
190*d14abf15SRobert Mustacchi disable_nvram_write(
191*d14abf15SRobert Mustacchi                     lm_device_t *pdev)
192*d14abf15SRobert Mustacchi {
193*d14abf15SRobert Mustacchi     lm_status_t lm_status;
194*d14abf15SRobert Mustacchi     u32_t cnt,j,val;
195*d14abf15SRobert Mustacchi 
196*d14abf15SRobert Mustacchi     DbgMessage(pdev, INFORMnv, "### disable_nvram_write\n");
197*d14abf15SRobert Mustacchi     /* Need to clear DONE bit separately. */
198*d14abf15SRobert Mustacchi     REG_WR(pdev, MCP_REG_MCPR_NVM_COMMAND, MCPR_NVM_COMMAND_DONE);
199*d14abf15SRobert Mustacchi 
200*d14abf15SRobert Mustacchi         /* Issue a write disable command. */
201*d14abf15SRobert Mustacchi     REG_WR(pdev, MCP_REG_MCPR_NVM_COMMAND, MCPR_NVM_COMMAND_DOIT | MCPR_NVM_COMMAND_WRDI);
202*d14abf15SRobert Mustacchi 
203*d14abf15SRobert Mustacchi     /* Adjust timeout for emulation/FPGA */
204*d14abf15SRobert Mustacchi     cnt = NVRAM_TIMEOUT_COUNT;
205*d14abf15SRobert Mustacchi     if (CHIP_REV(pdev) == CHIP_REV_EMUL) cnt *= 100;
206*d14abf15SRobert Mustacchi 
207*d14abf15SRobert Mustacchi     lm_status = LM_STATUS_BUSY;
208*d14abf15SRobert Mustacchi     for(j = 0; j < cnt; j++)
209*d14abf15SRobert Mustacchi     {
210*d14abf15SRobert Mustacchi         mm_wait(pdev, 5);
211*d14abf15SRobert Mustacchi 
212*d14abf15SRobert Mustacchi         val=REG_RD(pdev,  MCP_REG_MCPR_NVM_COMMAND);
213*d14abf15SRobert Mustacchi         if(val & MCPR_NVM_COMMAND_DONE)
214*d14abf15SRobert Mustacchi         {
215*d14abf15SRobert Mustacchi             lm_status = LM_STATUS_SUCCESS;
216*d14abf15SRobert Mustacchi             break;
217*d14abf15SRobert Mustacchi         }
218*d14abf15SRobert Mustacchi     }
219*d14abf15SRobert Mustacchi 
220*d14abf15SRobert Mustacchi     return lm_status;
221*d14abf15SRobert Mustacchi } /* disable_nvram_write */
222*d14abf15SRobert Mustacchi 
223*d14abf15SRobert Mustacchi #endif /* 0 */
224*d14abf15SRobert Mustacchi 
225*d14abf15SRobert Mustacchi /*******************************************************************************
226*d14abf15SRobert Mustacchi * Description:
227*d14abf15SRobert Mustacchi *
228*d14abf15SRobert Mustacchi * Return:
229*d14abf15SRobert Mustacchi ******************************************************************************/
230*d14abf15SRobert Mustacchi static lm_status_t
enable_nvram_access(lm_device_t * pdev)231*d14abf15SRobert Mustacchi enable_nvram_access(
232*d14abf15SRobert Mustacchi     lm_device_t *pdev)
233*d14abf15SRobert Mustacchi {
234*d14abf15SRobert Mustacchi     u32_t val;
235*d14abf15SRobert Mustacchi 
236*d14abf15SRobert Mustacchi     DbgMessage(pdev, VERBOSEnv, "### enable_nvram_access\n");
237*d14abf15SRobert Mustacchi     val=REG_RD(pdev,  MCP_REG_MCPR_NVM_ACCESS_ENABLE);
238*d14abf15SRobert Mustacchi 
239*d14abf15SRobert Mustacchi     /* Enable both bits, even on read. */
240*d14abf15SRobert Mustacchi     REG_WR(pdev,  MCP_REG_MCPR_NVM_ACCESS_ENABLE, val | MCPR_NVM_ACCESS_ENABLE_EN | MCPR_NVM_ACCESS_ENABLE_WR_EN);
241*d14abf15SRobert Mustacchi 
242*d14abf15SRobert Mustacchi     return LM_STATUS_SUCCESS;
243*d14abf15SRobert Mustacchi } /* enable_nvram_access */
244*d14abf15SRobert Mustacchi 
245*d14abf15SRobert Mustacchi 
246*d14abf15SRobert Mustacchi 
247*d14abf15SRobert Mustacchi /*******************************************************************************
248*d14abf15SRobert Mustacchi * Description:
249*d14abf15SRobert Mustacchi *
250*d14abf15SRobert Mustacchi * Return:
251*d14abf15SRobert Mustacchi ******************************************************************************/
252*d14abf15SRobert Mustacchi static lm_status_t
disable_nvram_access(lm_device_t * pdev)253*d14abf15SRobert Mustacchi disable_nvram_access(
254*d14abf15SRobert Mustacchi     lm_device_t *pdev)
255*d14abf15SRobert Mustacchi {
256*d14abf15SRobert Mustacchi     u32_t val;
257*d14abf15SRobert Mustacchi 
258*d14abf15SRobert Mustacchi     DbgMessage(pdev, VERBOSEnv, "### disable_nvram_access\n");
259*d14abf15SRobert Mustacchi     val=REG_RD(pdev,  MCP_REG_MCPR_NVM_ACCESS_ENABLE);
260*d14abf15SRobert Mustacchi 
261*d14abf15SRobert Mustacchi     /* Disable both bits, even after read. */
262*d14abf15SRobert Mustacchi     REG_WR(pdev,  MCP_REG_MCPR_NVM_ACCESS_ENABLE, val & ~(MCPR_NVM_ACCESS_ENABLE_EN | MCPR_NVM_ACCESS_ENABLE_WR_EN));
263*d14abf15SRobert Mustacchi 
264*d14abf15SRobert Mustacchi     return LM_STATUS_SUCCESS;
265*d14abf15SRobert Mustacchi } /* disable_nvram_access */
266*d14abf15SRobert Mustacchi 
267*d14abf15SRobert Mustacchi 
268*d14abf15SRobert Mustacchi 
269*d14abf15SRobert Mustacchi 
270*d14abf15SRobert Mustacchi /*******************************************************************************
271*d14abf15SRobert Mustacchi  * Description:
272*d14abf15SRobert Mustacchi  *
273*d14abf15SRobert Mustacchi  * Return:
274*d14abf15SRobert Mustacchi  ******************************************************************************/
275*d14abf15SRobert Mustacchi static lm_status_t
nvram_read_dword(lm_device_t * pdev,u32_t offset,u32_t * ret_val,u32_t nvram_flags)276*d14abf15SRobert Mustacchi nvram_read_dword(
277*d14abf15SRobert Mustacchi     lm_device_t *pdev,
278*d14abf15SRobert Mustacchi     u32_t offset,
279*d14abf15SRobert Mustacchi     u32_t *ret_val,
280*d14abf15SRobert Mustacchi     u32_t nvram_flags)
281*d14abf15SRobert Mustacchi {
282*d14abf15SRobert Mustacchi     lm_status_t lm_status;
283*d14abf15SRobert Mustacchi     u32_t cmd_flags;
284*d14abf15SRobert Mustacchi     u32_t val;
285*d14abf15SRobert Mustacchi     u32_t j, cnt;
286*d14abf15SRobert Mustacchi 
287*d14abf15SRobert Mustacchi     DbgMessage(pdev, VERBOSEnv, "### nvram_read_dword\n");
288*d14abf15SRobert Mustacchi     DbgMessage(pdev, VERBOSEnv, "offset %d flags %d\n",offset,nvram_flags);
289*d14abf15SRobert Mustacchi 
290*d14abf15SRobert Mustacchi     /* Build the command word. */
291*d14abf15SRobert Mustacchi     cmd_flags = nvram_flags | MCPR_NVM_COMMAND_DOIT;
292*d14abf15SRobert Mustacchi 
293*d14abf15SRobert Mustacchi     /* Need to clear DONE bit separately. */
294*d14abf15SRobert Mustacchi     REG_WR(pdev,  MCP_REG_MCPR_NVM_COMMAND, MCPR_NVM_COMMAND_DONE);
295*d14abf15SRobert Mustacchi 
296*d14abf15SRobert Mustacchi     /* Address of the NVRAM to read from. */
297*d14abf15SRobert Mustacchi     REG_WR(pdev,  MCP_REG_MCPR_NVM_ADDR, offset & MCPR_NVM_ADDR_NVM_ADDR_VALUE);
298*d14abf15SRobert Mustacchi 
299*d14abf15SRobert Mustacchi     /* Issue a read command. */
300*d14abf15SRobert Mustacchi     REG_WR(pdev,  MCP_REG_MCPR_NVM_COMMAND, cmd_flags);
301*d14abf15SRobert Mustacchi 
302*d14abf15SRobert Mustacchi     /* Adjust timeout for emulation/FPGA */
303*d14abf15SRobert Mustacchi     cnt = NVRAM_TIMEOUT_COUNT;
304*d14abf15SRobert Mustacchi     if (CHIP_REV_IS_EMUL(pdev)) cnt *= 100;
305*d14abf15SRobert Mustacchi 
306*d14abf15SRobert Mustacchi     /* Wait for completion. */
307*d14abf15SRobert Mustacchi     lm_status = LM_STATUS_BUSY;
308*d14abf15SRobert Mustacchi     for(j = 0; j < cnt; j++)
309*d14abf15SRobert Mustacchi     {
310*d14abf15SRobert Mustacchi         mm_wait(pdev, 5);
311*d14abf15SRobert Mustacchi         val=REG_RD(pdev,  MCP_REG_MCPR_NVM_COMMAND);
312*d14abf15SRobert Mustacchi         if(val & MCPR_NVM_COMMAND_DONE)
313*d14abf15SRobert Mustacchi         {
314*d14abf15SRobert Mustacchi             val=REG_RD(pdev,  MCP_REG_MCPR_NVM_READ);
315*d14abf15SRobert Mustacchi 
316*d14abf15SRobert Mustacchi             /* Change to little endian. */
317*d14abf15SRobert Mustacchi             #if defined(LITTLE_ENDIAN)
318*d14abf15SRobert Mustacchi             val = ((val & 0xff) << 24) | ((val & 0xff00) << 8) |
319*d14abf15SRobert Mustacchi                 ((val & 0xff0000) >> 8) | ((val >> 24) & 0xff);
320*d14abf15SRobert Mustacchi             #endif
321*d14abf15SRobert Mustacchi 
322*d14abf15SRobert Mustacchi             *ret_val = val;
323*d14abf15SRobert Mustacchi 
324*d14abf15SRobert Mustacchi             lm_status = LM_STATUS_SUCCESS;
325*d14abf15SRobert Mustacchi 
326*d14abf15SRobert Mustacchi             break;
327*d14abf15SRobert Mustacchi         }
328*d14abf15SRobert Mustacchi     }
329*d14abf15SRobert Mustacchi 
330*d14abf15SRobert Mustacchi     return lm_status;
331*d14abf15SRobert Mustacchi } /* nvram_read_dword */
332*d14abf15SRobert Mustacchi 
333*d14abf15SRobert Mustacchi 
334*d14abf15SRobert Mustacchi 
335*d14abf15SRobert Mustacchi /*******************************************************************************
336*d14abf15SRobert Mustacchi  * Description:
337*d14abf15SRobert Mustacchi  *
338*d14abf15SRobert Mustacchi  * Return:
339*d14abf15SRobert Mustacchi  ******************************************************************************/
340*d14abf15SRobert Mustacchi static lm_status_t
nvram_write_dword(lm_device_t * pdev,u32_t offset,u32_t val,u32_t nvram_flags)341*d14abf15SRobert Mustacchi nvram_write_dword(
342*d14abf15SRobert Mustacchi     lm_device_t *pdev,
343*d14abf15SRobert Mustacchi     u32_t offset,
344*d14abf15SRobert Mustacchi     u32_t val,
345*d14abf15SRobert Mustacchi     u32_t nvram_flags)
346*d14abf15SRobert Mustacchi {
347*d14abf15SRobert Mustacchi     lm_status_t lm_status;
348*d14abf15SRobert Mustacchi     u32_t cmd_flags;
349*d14abf15SRobert Mustacchi     u32_t j, cnt;
350*d14abf15SRobert Mustacchi 
351*d14abf15SRobert Mustacchi     DbgMessage(pdev, VERBOSEnv, "### nvram_write_dword\n");
352*d14abf15SRobert Mustacchi     /* Build the command word. */
353*d14abf15SRobert Mustacchi     cmd_flags = nvram_flags | MCPR_NVM_COMMAND_DOIT | MCPR_NVM_COMMAND_WR;
354*d14abf15SRobert Mustacchi 
355*d14abf15SRobert Mustacchi     /* Change to little endian. */
356*d14abf15SRobert Mustacchi     #if defined(LITTLE_ENDIAN)
357*d14abf15SRobert Mustacchi     val = ((val & 0xff) << 24) | ((val & 0xff00) << 8) |
358*d14abf15SRobert Mustacchi         ((val & 0xff0000) >> 8) | ((val >> 24) & 0xff);
359*d14abf15SRobert Mustacchi     #endif
360*d14abf15SRobert Mustacchi 
361*d14abf15SRobert Mustacchi     /* Need to clear DONE bit separately. */
362*d14abf15SRobert Mustacchi     REG_WR(pdev,  MCP_REG_MCPR_NVM_COMMAND, MCPR_NVM_COMMAND_DONE);
363*d14abf15SRobert Mustacchi 
364*d14abf15SRobert Mustacchi     /* Write the data. */
365*d14abf15SRobert Mustacchi     REG_WR(pdev,  MCP_REG_MCPR_NVM_WRITE, val);
366*d14abf15SRobert Mustacchi 
367*d14abf15SRobert Mustacchi     /* Address of the NVRAM to write to. */
368*d14abf15SRobert Mustacchi     REG_WR(pdev,  MCP_REG_MCPR_NVM_ADDR, offset & MCPR_NVM_ADDR_NVM_ADDR_VALUE);
369*d14abf15SRobert Mustacchi 
370*d14abf15SRobert Mustacchi     /* Issue the write command. */
371*d14abf15SRobert Mustacchi     REG_WR(pdev,  MCP_REG_MCPR_NVM_COMMAND, cmd_flags);
372*d14abf15SRobert Mustacchi 
373*d14abf15SRobert Mustacchi     /* Adjust timeout for emulation/FPGA */
374*d14abf15SRobert Mustacchi 
375*d14abf15SRobert Mustacchi     cnt = NVRAM_TIMEOUT_COUNT;
376*d14abf15SRobert Mustacchi     if (CHIP_REV_IS_EMUL(pdev)) cnt *= 100;
377*d14abf15SRobert Mustacchi 
378*d14abf15SRobert Mustacchi     /* Wait for completion. */
379*d14abf15SRobert Mustacchi     lm_status = LM_STATUS_BUSY;
380*d14abf15SRobert Mustacchi     for(j = 0; j < cnt; j++)
381*d14abf15SRobert Mustacchi     {
382*d14abf15SRobert Mustacchi         mm_wait(pdev, 5);
383*d14abf15SRobert Mustacchi 
384*d14abf15SRobert Mustacchi         val=REG_RD(pdev,  MCP_REG_MCPR_NVM_COMMAND);
385*d14abf15SRobert Mustacchi         if(val & MCPR_NVM_COMMAND_DONE)
386*d14abf15SRobert Mustacchi         {
387*d14abf15SRobert Mustacchi             lm_status = LM_STATUS_SUCCESS;
388*d14abf15SRobert Mustacchi             break;
389*d14abf15SRobert Mustacchi         }
390*d14abf15SRobert Mustacchi     }
391*d14abf15SRobert Mustacchi 
392*d14abf15SRobert Mustacchi     return lm_status;
393*d14abf15SRobert Mustacchi } /* nvram_write_dword */
394*d14abf15SRobert Mustacchi 
395*d14abf15SRobert Mustacchi 
396*d14abf15SRobert Mustacchi 
397*d14abf15SRobert Mustacchi /*******************************************************************************
398*d14abf15SRobert Mustacchi  * Description:
399*d14abf15SRobert Mustacchi  *
400*d14abf15SRobert Mustacchi  * Return:
401*d14abf15SRobert Mustacchi  ******************************************************************************/
402*d14abf15SRobert Mustacchi lm_status_t
lm_nvram_read(lm_device_t * pdev,u32_t offset,u32_t * ret_buf,u32_t buf_size)403*d14abf15SRobert Mustacchi lm_nvram_read(
404*d14abf15SRobert Mustacchi     lm_device_t *pdev,
405*d14abf15SRobert Mustacchi     u32_t offset,
406*d14abf15SRobert Mustacchi     u32_t *ret_buf,
407*d14abf15SRobert Mustacchi     u32_t buf_size)
408*d14abf15SRobert Mustacchi {
409*d14abf15SRobert Mustacchi     lm_status_t lm_status;
410*d14abf15SRobert Mustacchi     u32_t cmd_flags;
411*d14abf15SRobert Mustacchi 
412*d14abf15SRobert Mustacchi 
413*d14abf15SRobert Mustacchi     DbgMessage(pdev, VERBOSEnv, "### lm_nvram_read\n");
414*d14abf15SRobert Mustacchi     DbgMessage(pdev, VERBOSEnv, "offset %d size %d\n",offset,buf_size);
415*d14abf15SRobert Mustacchi 
416*d14abf15SRobert Mustacchi     if((buf_size & 0x03) || (offset & 0x03))
417*d14abf15SRobert Mustacchi     {
418*d14abf15SRobert Mustacchi         DbgBreakMsg("Invalid paramter.\n");
419*d14abf15SRobert Mustacchi 
420*d14abf15SRobert Mustacchi         return LM_STATUS_FAILURE;
421*d14abf15SRobert Mustacchi     }
422*d14abf15SRobert Mustacchi 
423*d14abf15SRobert Mustacchi     // TODO what is the nvram total size
424*d14abf15SRobert Mustacchi     if(offset + buf_size > pdev->hw_info.flash_spec.total_size)
425*d14abf15SRobert Mustacchi     {
426*d14abf15SRobert Mustacchi         DbgBreakMsg("Invalid paramter.\n");
427*d14abf15SRobert Mustacchi 
428*d14abf15SRobert Mustacchi         return LM_STATUS_FAILURE;
429*d14abf15SRobert Mustacchi     }
430*d14abf15SRobert Mustacchi 
431*d14abf15SRobert Mustacchi     /* Request access to the flash interface. */
432*d14abf15SRobert Mustacchi     lm_status = acquire_nvram_lock(pdev);
433*d14abf15SRobert Mustacchi     if(lm_status != LM_STATUS_SUCCESS)
434*d14abf15SRobert Mustacchi     {
435*d14abf15SRobert Mustacchi         return lm_status;
436*d14abf15SRobert Mustacchi     }
437*d14abf15SRobert Mustacchi 
438*d14abf15SRobert Mustacchi     /* Enable access to flash interface */
439*d14abf15SRobert Mustacchi     lm_status = enable_nvram_access(pdev);
440*d14abf15SRobert Mustacchi     if(lm_status != LM_STATUS_SUCCESS)
441*d14abf15SRobert Mustacchi     {
442*d14abf15SRobert Mustacchi         release_nvram_lock(pdev);
443*d14abf15SRobert Mustacchi         return lm_status;
444*d14abf15SRobert Mustacchi     }
445*d14abf15SRobert Mustacchi 
446*d14abf15SRobert Mustacchi     /* Read the first word. */
447*d14abf15SRobert Mustacchi     cmd_flags = MCPR_NVM_COMMAND_FIRST;
448*d14abf15SRobert Mustacchi     while(buf_size > sizeof(u32_t) && lm_status == LM_STATUS_SUCCESS)
449*d14abf15SRobert Mustacchi     {
450*d14abf15SRobert Mustacchi         lm_status = nvram_read_dword(pdev, offset, ret_buf, cmd_flags);
451*d14abf15SRobert Mustacchi 
452*d14abf15SRobert Mustacchi         /* Advance to the next dword. */
453*d14abf15SRobert Mustacchi         offset += sizeof(u32_t);
454*d14abf15SRobert Mustacchi         ret_buf++;
455*d14abf15SRobert Mustacchi         buf_size -= sizeof(u32_t);
456*d14abf15SRobert Mustacchi         cmd_flags = 0;
457*d14abf15SRobert Mustacchi     }
458*d14abf15SRobert Mustacchi 
459*d14abf15SRobert Mustacchi     if(lm_status == LM_STATUS_SUCCESS)
460*d14abf15SRobert Mustacchi     {
461*d14abf15SRobert Mustacchi         cmd_flags |= MCPR_NVM_COMMAND_LAST;
462*d14abf15SRobert Mustacchi         lm_status = nvram_read_dword(pdev, offset, ret_buf, cmd_flags);
463*d14abf15SRobert Mustacchi     }
464*d14abf15SRobert Mustacchi 
465*d14abf15SRobert Mustacchi     /* Disable access to flash interface */
466*d14abf15SRobert Mustacchi     disable_nvram_access(pdev);
467*d14abf15SRobert Mustacchi 
468*d14abf15SRobert Mustacchi     release_nvram_lock(pdev);
469*d14abf15SRobert Mustacchi 
470*d14abf15SRobert Mustacchi     return lm_status;
471*d14abf15SRobert Mustacchi } /* lm_nvram_read */
472*d14abf15SRobert Mustacchi 
473*d14abf15SRobert Mustacchi 
474*d14abf15SRobert Mustacchi /*******************************************************************************
475*d14abf15SRobert Mustacchi  * Description:
476*d14abf15SRobert Mustacchi  *
477*d14abf15SRobert Mustacchi  * Return:
478*d14abf15SRobert Mustacchi  ******************************************************************************/
479*d14abf15SRobert Mustacchi lm_status_t
lm_nvram_write(lm_device_t * pdev,u32_t offset,u32_t * data_buf,u32_t buf_size)480*d14abf15SRobert Mustacchi lm_nvram_write(
481*d14abf15SRobert Mustacchi     lm_device_t *pdev,
482*d14abf15SRobert Mustacchi     u32_t offset,
483*d14abf15SRobert Mustacchi     u32_t *data_buf,
484*d14abf15SRobert Mustacchi     u32_t buf_size)
485*d14abf15SRobert Mustacchi {
486*d14abf15SRobert Mustacchi     lm_status_t lm_status;
487*d14abf15SRobert Mustacchi     u32_t written_so_far;
488*d14abf15SRobert Mustacchi     u32_t cmd_flags;
489*d14abf15SRobert Mustacchi     u32_t *ptr32, addr;
490*d14abf15SRobert Mustacchi 
491*d14abf15SRobert Mustacchi     DbgMessage(pdev, VERBOSEnv, "### lm_nvram_write\n");
492*d14abf15SRobert Mustacchi 
493*d14abf15SRobert Mustacchi     if(offset & 0x03)
494*d14abf15SRobert Mustacchi     {
495*d14abf15SRobert Mustacchi         DbgBreakMsg("Invalid paramter.\n");
496*d14abf15SRobert Mustacchi 
497*d14abf15SRobert Mustacchi         return LM_STATUS_FAILURE;
498*d14abf15SRobert Mustacchi     }
499*d14abf15SRobert Mustacchi     // TODO what is the nvram total size
500*d14abf15SRobert Mustacchi     if(offset + buf_size > pdev->hw_info.flash_spec.total_size)
501*d14abf15SRobert Mustacchi     {
502*d14abf15SRobert Mustacchi 	DbgMessage(pdev, FATAL, "lm_nvram_write failed ! buf_size %d larger than NVM total_size %d\n", buf_size, pdev->hw_info.flash_spec.total_size);
503*d14abf15SRobert Mustacchi         DbgBreakMsg("Failed to write to NVM! Attemp to write to offset larger than NVM total size !\n");
504*d14abf15SRobert Mustacchi 
505*d14abf15SRobert Mustacchi         return LM_STATUS_FAILURE;
506*d14abf15SRobert Mustacchi     }
507*d14abf15SRobert Mustacchi 
508*d14abf15SRobert Mustacchi     lm_status = LM_STATUS_SUCCESS;
509*d14abf15SRobert Mustacchi 
510*d14abf15SRobert Mustacchi     /* Request access to the flash interface. */
511*d14abf15SRobert Mustacchi     lm_status = acquire_nvram_lock(pdev);
512*d14abf15SRobert Mustacchi     if(lm_status != LM_STATUS_SUCCESS)
513*d14abf15SRobert Mustacchi         return lm_status;
514*d14abf15SRobert Mustacchi 
515*d14abf15SRobert Mustacchi     /* Enable access to flash interface */
516*d14abf15SRobert Mustacchi     lm_status = enable_nvram_access(pdev);
517*d14abf15SRobert Mustacchi     if(lm_status != LM_STATUS_SUCCESS)
518*d14abf15SRobert Mustacchi     {
519*d14abf15SRobert Mustacchi         release_nvram_lock(pdev);
520*d14abf15SRobert Mustacchi         return lm_status;
521*d14abf15SRobert Mustacchi     }
522*d14abf15SRobert Mustacchi 
523*d14abf15SRobert Mustacchi     written_so_far = 0;
524*d14abf15SRobert Mustacchi     cmd_flags = MCPR_NVM_COMMAND_FIRST;
525*d14abf15SRobert Mustacchi     addr = offset;
526*d14abf15SRobert Mustacchi     ptr32 = data_buf;
527*d14abf15SRobert Mustacchi     while (written_so_far < buf_size)
528*d14abf15SRobert Mustacchi     {
529*d14abf15SRobert Mustacchi         if (written_so_far == (buf_size - 4))
530*d14abf15SRobert Mustacchi             cmd_flags |= MCPR_NVM_COMMAND_LAST;
531*d14abf15SRobert Mustacchi         else if (((addr & 0xff) + 4) == NVRAM_PAGE_SIZE)        // else if (((addr + 4) % NVRAM_PAGE_SIZE) == 0)
532*d14abf15SRobert Mustacchi             cmd_flags |= MCPR_NVM_COMMAND_LAST;
533*d14abf15SRobert Mustacchi         else if ((addr & 0xff) == 0)                            // else if ((addr % NVRAM_PAGE_SIZE) == 0)
534*d14abf15SRobert Mustacchi             cmd_flags |= MCPR_NVM_COMMAND_FIRST;
535*d14abf15SRobert Mustacchi         nvram_write_dword(pdev, addr, *ptr32, cmd_flags);
536*d14abf15SRobert Mustacchi         ptr32++;
537*d14abf15SRobert Mustacchi         addr += 4;
538*d14abf15SRobert Mustacchi         written_so_far += 4;
539*d14abf15SRobert Mustacchi         cmd_flags = 0;
540*d14abf15SRobert Mustacchi     }
541*d14abf15SRobert Mustacchi     /* Disable access to flash interface */
542*d14abf15SRobert Mustacchi     disable_nvram_access(pdev);
543*d14abf15SRobert Mustacchi     release_nvram_lock(pdev);
544*d14abf15SRobert Mustacchi 
545*d14abf15SRobert Mustacchi 
546*d14abf15SRobert Mustacchi     return lm_status;
547*d14abf15SRobert Mustacchi 
548*d14abf15SRobert Mustacchi } /* lm_nvram_write */
549