xref: /freebsd/sys/dev/qlxgbe/ql_misc.c (revision 685dc743dc3b5645e34836464128e1c0558b404b)
1718cf2ccSPedro F. Giffuni /*-
2*4d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
3718cf2ccSPedro F. Giffuni  *
435291c22SDavid C Somayajulu  * Copyright (c) 2013-2016 Qlogic Corporation
5f10a77bbSDavid C Somayajulu  * All rights reserved.
6f10a77bbSDavid C Somayajulu  *
7f10a77bbSDavid C Somayajulu  *  Redistribution and use in source and binary forms, with or without
8f10a77bbSDavid C Somayajulu  *  modification, are permitted provided that the following conditions
9f10a77bbSDavid C Somayajulu  *  are met:
10f10a77bbSDavid C Somayajulu  *
11f10a77bbSDavid C Somayajulu  *  1. Redistributions of source code must retain the above copyright
12f10a77bbSDavid C Somayajulu  *     notice, this list of conditions and the following disclaimer.
13f10a77bbSDavid C Somayajulu  *  2. Redistributions in binary form must reproduce the above copyright
14f10a77bbSDavid C Somayajulu  *     notice, this list of conditions and the following disclaimer in the
15f10a77bbSDavid C Somayajulu  *     documentation and/or other materials provided with the distribution.
16f10a77bbSDavid C Somayajulu  *
17f10a77bbSDavid C Somayajulu  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18f10a77bbSDavid C Somayajulu  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19f10a77bbSDavid C Somayajulu  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20f10a77bbSDavid C Somayajulu  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21f10a77bbSDavid C Somayajulu  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22f10a77bbSDavid C Somayajulu  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23f10a77bbSDavid C Somayajulu  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24f10a77bbSDavid C Somayajulu  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25f10a77bbSDavid C Somayajulu  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26f10a77bbSDavid C Somayajulu  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27f10a77bbSDavid C Somayajulu  *  POSSIBILITY OF SUCH DAMAGE.
28f10a77bbSDavid C Somayajulu  */
29f10a77bbSDavid C Somayajulu /*
30f10a77bbSDavid C Somayajulu  * File : ql_misc.c
31f10a77bbSDavid C Somayajulu  * Author : David C Somayajulu, Qlogic Corporation, Aliso Viejo, CA 92656.
32f10a77bbSDavid C Somayajulu  */
33f10a77bbSDavid C Somayajulu 
34f10a77bbSDavid C Somayajulu #include <sys/cdefs.h>
35f10a77bbSDavid C Somayajulu #include "ql_os.h"
36f10a77bbSDavid C Somayajulu #include "ql_hw.h"
37f10a77bbSDavid C Somayajulu #include "ql_def.h"
38f10a77bbSDavid C Somayajulu #include "ql_inline.h"
39f10a77bbSDavid C Somayajulu #include "ql_glbl.h"
40f10a77bbSDavid C Somayajulu #include "ql_dbg.h"
41f10a77bbSDavid C Somayajulu #include "ql_tmplt.h"
42f10a77bbSDavid C Somayajulu 
43f10a77bbSDavid C Somayajulu #define	QL_FDT_OFFSET		0x3F0000
44f10a77bbSDavid C Somayajulu #define Q8_FLASH_SECTOR_SIZE	0x10000
45f10a77bbSDavid C Somayajulu 
46f10a77bbSDavid C Somayajulu static int qla_ld_fw_init(qla_host_t *ha);
47f10a77bbSDavid C Somayajulu 
48f10a77bbSDavid C Somayajulu /*
49f10a77bbSDavid C Somayajulu  * structure encapsulating the value to read/write to offchip memory
50f10a77bbSDavid C Somayajulu  */
51f10a77bbSDavid C Somayajulu typedef struct _offchip_mem_val {
52f10a77bbSDavid C Somayajulu         uint32_t data_lo;
53f10a77bbSDavid C Somayajulu         uint32_t data_hi;
54f10a77bbSDavid C Somayajulu         uint32_t data_ulo;
55f10a77bbSDavid C Somayajulu         uint32_t data_uhi;
56f10a77bbSDavid C Somayajulu } offchip_mem_val_t;
57f10a77bbSDavid C Somayajulu 
58f10a77bbSDavid C Somayajulu /*
59f10a77bbSDavid C Somayajulu  * Name: ql_rdwr_indreg32
60f10a77bbSDavid C Somayajulu  * Function: Read/Write an Indirect Register
61f10a77bbSDavid C Somayajulu  */
62f10a77bbSDavid C Somayajulu int
ql_rdwr_indreg32(qla_host_t * ha,uint32_t addr,uint32_t * val,uint32_t rd)63f10a77bbSDavid C Somayajulu ql_rdwr_indreg32(qla_host_t *ha, uint32_t addr, uint32_t *val, uint32_t rd)
64f10a77bbSDavid C Somayajulu {
65f10a77bbSDavid C Somayajulu 	uint32_t wnd_reg;
66f10a77bbSDavid C Somayajulu 	uint32_t count = 100;
67f10a77bbSDavid C Somayajulu 
68f10a77bbSDavid C Somayajulu 	wnd_reg = (Q8_CRB_WINDOW_PF0 | (ha->pci_func << 2));
69f10a77bbSDavid C Somayajulu 
70f10a77bbSDavid C Somayajulu 	WRITE_REG32(ha, wnd_reg, addr);
71f10a77bbSDavid C Somayajulu 
72f10a77bbSDavid C Somayajulu 	while (count--) {
73f10a77bbSDavid C Somayajulu 		if (READ_REG32(ha, wnd_reg) == addr)
74f10a77bbSDavid C Somayajulu 			break;
75f10a77bbSDavid C Somayajulu 		qla_mdelay(__func__, 1);
76f10a77bbSDavid C Somayajulu 	}
77f10a77bbSDavid C Somayajulu 	if (!count || QL_ERR_INJECT(ha, INJCT_RDWR_INDREG_FAILURE)) {
78f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "%s: [0x%08x, 0x%08x, %d] failed\n",
79f10a77bbSDavid C Somayajulu 			__func__, addr, *val, rd);
80b65c0c07SDavid C Somayajulu 		QL_INITIATE_RECOVERY(ha);
81f10a77bbSDavid C Somayajulu 		return -1;
82f10a77bbSDavid C Somayajulu 	}
83f10a77bbSDavid C Somayajulu 
84f10a77bbSDavid C Somayajulu 	if (rd) {
85f10a77bbSDavid C Somayajulu 		*val = READ_REG32(ha, Q8_WILD_CARD);
86f10a77bbSDavid C Somayajulu 	} else {
87f10a77bbSDavid C Somayajulu 		WRITE_REG32(ha, Q8_WILD_CARD, *val);
88f10a77bbSDavid C Somayajulu 	}
89f10a77bbSDavid C Somayajulu 
90f10a77bbSDavid C Somayajulu 	return 0;
91f10a77bbSDavid C Somayajulu }
92f10a77bbSDavid C Somayajulu 
93f10a77bbSDavid C Somayajulu /*
94f10a77bbSDavid C Somayajulu  * Name: ql_rdwr_offchip_mem
95f10a77bbSDavid C Somayajulu  * Function: Read/Write OffChip Memory
96f10a77bbSDavid C Somayajulu  */
97f10a77bbSDavid C Somayajulu int
ql_rdwr_offchip_mem(qla_host_t * ha,uint64_t addr,q80_offchip_mem_val_t * val,uint32_t rd)98f10a77bbSDavid C Somayajulu ql_rdwr_offchip_mem(qla_host_t *ha, uint64_t addr, q80_offchip_mem_val_t *val,
99f10a77bbSDavid C Somayajulu 	uint32_t rd)
100f10a77bbSDavid C Somayajulu {
101f10a77bbSDavid C Somayajulu 	uint32_t count = 100;
102f10a77bbSDavid C Somayajulu 	uint32_t data, step = 0;
103f10a77bbSDavid C Somayajulu 
104f10a77bbSDavid C Somayajulu 	if (QL_ERR_INJECT(ha, INJCT_RDWR_OFFCHIPMEM_FAILURE))
105f10a77bbSDavid C Somayajulu 		goto exit_ql_rdwr_offchip_mem;
106f10a77bbSDavid C Somayajulu 
107f10a77bbSDavid C Somayajulu 	data = (uint32_t)addr;
108f10a77bbSDavid C Somayajulu 	if (ql_rdwr_indreg32(ha, Q8_MS_ADDR_LO, &data, 0)) {
109f10a77bbSDavid C Somayajulu 		step = 1;
110f10a77bbSDavid C Somayajulu 		goto exit_ql_rdwr_offchip_mem;
111f10a77bbSDavid C Somayajulu 	}
112f10a77bbSDavid C Somayajulu 
113f10a77bbSDavid C Somayajulu 	data = (uint32_t)(addr >> 32);
114f10a77bbSDavid C Somayajulu 	if (ql_rdwr_indreg32(ha, Q8_MS_ADDR_HI, &data, 0)) {
115f10a77bbSDavid C Somayajulu 		step = 2;
116f10a77bbSDavid C Somayajulu 		goto exit_ql_rdwr_offchip_mem;
117f10a77bbSDavid C Somayajulu 	}
118f10a77bbSDavid C Somayajulu 
119f10a77bbSDavid C Somayajulu 	data = BIT_1;
120f10a77bbSDavid C Somayajulu 	if (ql_rdwr_indreg32(ha, Q8_MS_CNTRL, &data, 0)) {
121f10a77bbSDavid C Somayajulu 		step = 3;
122f10a77bbSDavid C Somayajulu 		goto exit_ql_rdwr_offchip_mem;
123f10a77bbSDavid C Somayajulu 	}
124f10a77bbSDavid C Somayajulu 
125f10a77bbSDavid C Somayajulu 	if (!rd) {
126f10a77bbSDavid C Somayajulu 		data = val->data_lo;
127f10a77bbSDavid C Somayajulu 		if (ql_rdwr_indreg32(ha, Q8_MS_WR_DATA_0_31, &data, 0)) {
128f10a77bbSDavid C Somayajulu 			step = 4;
129f10a77bbSDavid C Somayajulu 			goto exit_ql_rdwr_offchip_mem;
130f10a77bbSDavid C Somayajulu 		}
131f10a77bbSDavid C Somayajulu 
132f10a77bbSDavid C Somayajulu 		data = val->data_hi;
133f10a77bbSDavid C Somayajulu 		if (ql_rdwr_indreg32(ha, Q8_MS_WR_DATA_32_63, &data, 0)) {
134f10a77bbSDavid C Somayajulu 			step = 5;
135f10a77bbSDavid C Somayajulu 			goto exit_ql_rdwr_offchip_mem;
136f10a77bbSDavid C Somayajulu 		}
137f10a77bbSDavid C Somayajulu 
138f10a77bbSDavid C Somayajulu 		data = val->data_ulo;
139f10a77bbSDavid C Somayajulu 		if (ql_rdwr_indreg32(ha, Q8_MS_WR_DATA_64_95, &data, 0)) {
140f10a77bbSDavid C Somayajulu 			step = 6;
141f10a77bbSDavid C Somayajulu 			goto exit_ql_rdwr_offchip_mem;
142f10a77bbSDavid C Somayajulu 		}
143f10a77bbSDavid C Somayajulu 
144f10a77bbSDavid C Somayajulu 		data = val->data_uhi;
145f10a77bbSDavid C Somayajulu 		if (ql_rdwr_indreg32(ha, Q8_MS_WR_DATA_96_127, &data, 0)) {
146f10a77bbSDavid C Somayajulu 			step = 7;
147f10a77bbSDavid C Somayajulu 			goto exit_ql_rdwr_offchip_mem;
148f10a77bbSDavid C Somayajulu 		}
149f10a77bbSDavid C Somayajulu 
150f10a77bbSDavid C Somayajulu 		data = (BIT_2|BIT_1|BIT_0);
151f10a77bbSDavid C Somayajulu 		if (ql_rdwr_indreg32(ha, Q8_MS_CNTRL, &data, 0)) {
152f10a77bbSDavid C Somayajulu 			step = 7;
153f10a77bbSDavid C Somayajulu 			goto exit_ql_rdwr_offchip_mem;
154f10a77bbSDavid C Somayajulu 		}
155f10a77bbSDavid C Somayajulu 	} else {
156f10a77bbSDavid C Somayajulu 		data = (BIT_1|BIT_0);
157f10a77bbSDavid C Somayajulu 		if (ql_rdwr_indreg32(ha, Q8_MS_CNTRL, &data, 0)) {
158f10a77bbSDavid C Somayajulu 			step = 8;
159f10a77bbSDavid C Somayajulu 			goto exit_ql_rdwr_offchip_mem;
160f10a77bbSDavid C Somayajulu 		}
161f10a77bbSDavid C Somayajulu 	}
162f10a77bbSDavid C Somayajulu 
163f10a77bbSDavid C Somayajulu 	while (count--) {
164f10a77bbSDavid C Somayajulu 		if (ql_rdwr_indreg32(ha, Q8_MS_CNTRL, &data, 1)) {
165f10a77bbSDavid C Somayajulu 			step = 9;
166f10a77bbSDavid C Somayajulu 			goto exit_ql_rdwr_offchip_mem;
167f10a77bbSDavid C Somayajulu 		}
168f10a77bbSDavid C Somayajulu 
169f10a77bbSDavid C Somayajulu 		if (!(data & BIT_3)) {
170f10a77bbSDavid C Somayajulu 			if (rd) {
171f10a77bbSDavid C Somayajulu 				if (ql_rdwr_indreg32(ha, Q8_MS_RD_DATA_0_31,
172f10a77bbSDavid C Somayajulu 					&data, 1)) {
173f10a77bbSDavid C Somayajulu 					step = 10;
174f10a77bbSDavid C Somayajulu 					goto exit_ql_rdwr_offchip_mem;
175f10a77bbSDavid C Somayajulu 				}
176f10a77bbSDavid C Somayajulu 				val->data_lo = data;
177f10a77bbSDavid C Somayajulu 
178f10a77bbSDavid C Somayajulu 				if (ql_rdwr_indreg32(ha, Q8_MS_RD_DATA_32_63,
179f10a77bbSDavid C Somayajulu 					&data, 1)) {
180f10a77bbSDavid C Somayajulu 					step = 11;
181f10a77bbSDavid C Somayajulu 					goto exit_ql_rdwr_offchip_mem;
182f10a77bbSDavid C Somayajulu 				}
183f10a77bbSDavid C Somayajulu 				val->data_hi = data;
184f10a77bbSDavid C Somayajulu 
185f10a77bbSDavid C Somayajulu 				if (ql_rdwr_indreg32(ha, Q8_MS_RD_DATA_64_95,
186f10a77bbSDavid C Somayajulu 					&data, 1)) {
187f10a77bbSDavid C Somayajulu 					step = 12;
188f10a77bbSDavid C Somayajulu 					goto exit_ql_rdwr_offchip_mem;
189f10a77bbSDavid C Somayajulu 				}
190f10a77bbSDavid C Somayajulu 				val->data_ulo = data;
191f10a77bbSDavid C Somayajulu 
192f10a77bbSDavid C Somayajulu 				if (ql_rdwr_indreg32(ha, Q8_MS_RD_DATA_96_127,
193f10a77bbSDavid C Somayajulu 					&data, 1)) {
194f10a77bbSDavid C Somayajulu 					step = 13;
195f10a77bbSDavid C Somayajulu 					goto exit_ql_rdwr_offchip_mem;
196f10a77bbSDavid C Somayajulu 				}
197f10a77bbSDavid C Somayajulu 				val->data_uhi = data;
198f10a77bbSDavid C Somayajulu 			}
199f10a77bbSDavid C Somayajulu 			return 0;
200f10a77bbSDavid C Somayajulu 		} else
201f10a77bbSDavid C Somayajulu 			qla_mdelay(__func__, 1);
202f10a77bbSDavid C Somayajulu 	}
203f10a77bbSDavid C Somayajulu 
204f10a77bbSDavid C Somayajulu exit_ql_rdwr_offchip_mem:
205f10a77bbSDavid C Somayajulu 
206f10a77bbSDavid C Somayajulu 	device_printf(ha->pci_dev,
207f10a77bbSDavid C Somayajulu 		"%s: [0x%08x 0x%08x : 0x%08x 0x%08x 0x%08x 0x%08x]"
208f10a77bbSDavid C Somayajulu 		" [%d] [%d] failed\n", __func__, (uint32_t)(addr >> 32),
209f10a77bbSDavid C Somayajulu 		(uint32_t)(addr), val->data_lo, val->data_hi, val->data_ulo,
210f10a77bbSDavid C Somayajulu 		val->data_uhi, rd, step);
211f10a77bbSDavid C Somayajulu 
212b65c0c07SDavid C Somayajulu 	QL_INITIATE_RECOVERY(ha);
213f10a77bbSDavid C Somayajulu 
214f10a77bbSDavid C Somayajulu 	return (-1);
215f10a77bbSDavid C Somayajulu }
216f10a77bbSDavid C Somayajulu 
217f10a77bbSDavid C Somayajulu /*
218f10a77bbSDavid C Somayajulu  * Name: ql_rd_flash32
219f10a77bbSDavid C Somayajulu  * Function: Read Flash Memory
220f10a77bbSDavid C Somayajulu  */
221f10a77bbSDavid C Somayajulu int
ql_rd_flash32(qla_host_t * ha,uint32_t addr,uint32_t * data)222f10a77bbSDavid C Somayajulu ql_rd_flash32(qla_host_t *ha, uint32_t addr, uint32_t *data)
223f10a77bbSDavid C Somayajulu {
224f10a77bbSDavid C Somayajulu 	uint32_t data32;
225f10a77bbSDavid C Somayajulu 
226f10a77bbSDavid C Somayajulu 	if (qla_sem_lock(ha, Q8_FLASH_LOCK, Q8_FLASH_LOCK_ID, 0xABCDABCD)) {
227f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "%s: Q8_FLASH_LOCK failed\n",
228f10a77bbSDavid C Somayajulu 			__func__);
229f10a77bbSDavid C Somayajulu 		return (-1);
230f10a77bbSDavid C Somayajulu 	}
231f10a77bbSDavid C Somayajulu 
232f10a77bbSDavid C Somayajulu 	data32 = addr;
233f10a77bbSDavid C Somayajulu 	if (ql_rdwr_indreg32(ha, Q8_FLASH_DIRECT_WINDOW, &data32, 0)) {
234f10a77bbSDavid C Somayajulu 		qla_sem_unlock(ha, Q8_FLASH_UNLOCK);
235f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev,
236f10a77bbSDavid C Somayajulu 			"%s: Q8_FLASH_DIRECT_WINDOW[0x%08x] failed\n",
237f10a77bbSDavid C Somayajulu 			__func__, data32);
238f10a77bbSDavid C Somayajulu 		return (-1);
239f10a77bbSDavid C Somayajulu 	}
240f10a77bbSDavid C Somayajulu 
241f10a77bbSDavid C Somayajulu 	data32 = Q8_FLASH_DIRECT_DATA | (addr & 0xFFFF);
242f10a77bbSDavid C Somayajulu 	if (ql_rdwr_indreg32(ha, data32, data, 1)) {
243f10a77bbSDavid C Somayajulu 		qla_sem_unlock(ha, Q8_FLASH_UNLOCK);
244f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev,
245f10a77bbSDavid C Somayajulu 			"%s: data32:data [0x%08x] failed\n",
246f10a77bbSDavid C Somayajulu 			__func__, data32);
247f10a77bbSDavid C Somayajulu 		return (-1);
248f10a77bbSDavid C Somayajulu 	}
249f10a77bbSDavid C Somayajulu 
250f10a77bbSDavid C Somayajulu 	qla_sem_unlock(ha, Q8_FLASH_UNLOCK);
251f10a77bbSDavid C Somayajulu 	return 0;
252f10a77bbSDavid C Somayajulu }
253f10a77bbSDavid C Somayajulu 
254f10a77bbSDavid C Somayajulu static int
qla_get_fdt(qla_host_t * ha)255f10a77bbSDavid C Somayajulu qla_get_fdt(qla_host_t *ha)
256f10a77bbSDavid C Somayajulu {
257f10a77bbSDavid C Somayajulu 	uint32_t data32;
258f10a77bbSDavid C Somayajulu 	int count;
259f10a77bbSDavid C Somayajulu 	qla_hw_t *hw;
260f10a77bbSDavid C Somayajulu 
261f10a77bbSDavid C Somayajulu 	hw = &ha->hw;
262f10a77bbSDavid C Somayajulu 
263f10a77bbSDavid C Somayajulu 	for (count = 0; count < sizeof(qla_flash_desc_table_t); count+=4) {
264f10a77bbSDavid C Somayajulu 		if (ql_rd_flash32(ha, QL_FDT_OFFSET + count,
265f10a77bbSDavid C Somayajulu 			(uint32_t *)&hw->fdt + (count >> 2))) {
266f10a77bbSDavid C Somayajulu 				device_printf(ha->pci_dev,
267f10a77bbSDavid C Somayajulu 					"%s: Read QL_FDT_OFFSET + %d failed\n",
268f10a77bbSDavid C Somayajulu 					__func__, count);
269f10a77bbSDavid C Somayajulu 				return (-1);
270f10a77bbSDavid C Somayajulu 		}
271f10a77bbSDavid C Somayajulu 	}
272f10a77bbSDavid C Somayajulu 
273f10a77bbSDavid C Somayajulu 	if (qla_sem_lock(ha, Q8_FLASH_LOCK, Q8_FLASH_LOCK_ID,
274f10a77bbSDavid C Somayajulu 		Q8_FDT_LOCK_MAGIC_ID)) {
275f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "%s: Q8_FLASH_LOCK failed\n",
276f10a77bbSDavid C Somayajulu 			__func__);
277f10a77bbSDavid C Somayajulu 		return (-1);
278f10a77bbSDavid C Somayajulu 	}
279f10a77bbSDavid C Somayajulu 
280f10a77bbSDavid C Somayajulu 	data32 = Q8_FDT_FLASH_ADDR_VAL;
281f10a77bbSDavid C Somayajulu 	if (ql_rdwr_indreg32(ha, Q8_FLASH_ADDRESS, &data32, 0)) {
282f10a77bbSDavid C Somayajulu 		qla_sem_unlock(ha, Q8_FLASH_UNLOCK);
283f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev,
284f10a77bbSDavid C Somayajulu 			"%s: Write to Q8_FLASH_ADDRESS failed\n",
285f10a77bbSDavid C Somayajulu 			__func__);
286f10a77bbSDavid C Somayajulu 		return (-1);
287f10a77bbSDavid C Somayajulu 	}
288f10a77bbSDavid C Somayajulu 
289f10a77bbSDavid C Somayajulu 	data32 = Q8_FDT_FLASH_CTRL_VAL;
290f10a77bbSDavid C Somayajulu 	if (ql_rdwr_indreg32(ha, Q8_FLASH_CONTROL, &data32, 0)) {
291f10a77bbSDavid C Somayajulu 		qla_sem_unlock(ha, Q8_FLASH_UNLOCK);
292f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev,
293f10a77bbSDavid C Somayajulu 			"%s: Write to Q8_FLASH_CONTROL failed\n",
294f10a77bbSDavid C Somayajulu 			__func__);
295f10a77bbSDavid C Somayajulu 		return (-1);
296f10a77bbSDavid C Somayajulu 	}
297f10a77bbSDavid C Somayajulu 
298f10a77bbSDavid C Somayajulu 	count = 0;
299f10a77bbSDavid C Somayajulu 
300f10a77bbSDavid C Somayajulu 	do {
301f10a77bbSDavid C Somayajulu 		if (count < 1000) {
302f10a77bbSDavid C Somayajulu 			QLA_USEC_DELAY(10);
303f10a77bbSDavid C Somayajulu 			count += 10;
304f10a77bbSDavid C Somayajulu 		} else {
305f10a77bbSDavid C Somayajulu 			qla_mdelay(__func__, 1);
306f10a77bbSDavid C Somayajulu 			count += 1000;
307f10a77bbSDavid C Somayajulu 		}
308f10a77bbSDavid C Somayajulu 
309f10a77bbSDavid C Somayajulu 		data32 = 0;
310f10a77bbSDavid C Somayajulu 
311f10a77bbSDavid C Somayajulu 		if (ql_rdwr_indreg32(ha, Q8_FLASH_STATUS, &data32, 1)) {
312f10a77bbSDavid C Somayajulu 			qla_sem_unlock(ha, Q8_FLASH_UNLOCK);
313f10a77bbSDavid C Somayajulu 			device_printf(ha->pci_dev,
314f10a77bbSDavid C Somayajulu 				"%s: Read Q8_FLASH_STATUS failed\n",
315f10a77bbSDavid C Somayajulu 				__func__);
316f10a77bbSDavid C Somayajulu 			return (-1);
317f10a77bbSDavid C Somayajulu 		}
318f10a77bbSDavid C Somayajulu 
319f10a77bbSDavid C Somayajulu 		data32 &= 0x6;
320f10a77bbSDavid C Somayajulu 
321f10a77bbSDavid C Somayajulu 	} while ((count < 10000) && (data32 != 0x6));
322f10a77bbSDavid C Somayajulu 
323e43ab9b9SDavid C Somayajulu 	if (data32 != 0x6) {
324f10a77bbSDavid C Somayajulu 		qla_sem_unlock(ha, Q8_FLASH_UNLOCK);
325f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev,
326f10a77bbSDavid C Somayajulu 			"%s: Poll Q8_FLASH_STATUS failed\n",
327f10a77bbSDavid C Somayajulu 			__func__);
328f10a77bbSDavid C Somayajulu 		return (-1);
329f10a77bbSDavid C Somayajulu 	}
330f10a77bbSDavid C Somayajulu 
331f10a77bbSDavid C Somayajulu 	if (ql_rdwr_indreg32(ha, Q8_FLASH_RD_DATA, &data32, 1)) {
332f10a77bbSDavid C Somayajulu 		qla_sem_unlock(ha, Q8_FLASH_UNLOCK);
333f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev,
334f10a77bbSDavid C Somayajulu 			"%s: Read Q8_FLASH_RD_DATA failed\n",
335f10a77bbSDavid C Somayajulu 			__func__);
336f10a77bbSDavid C Somayajulu 		return (-1);
337f10a77bbSDavid C Somayajulu 	}
338f10a77bbSDavid C Somayajulu 
339f10a77bbSDavid C Somayajulu 	qla_sem_unlock(ha, Q8_FLASH_UNLOCK);
340f10a77bbSDavid C Somayajulu 
341f10a77bbSDavid C Somayajulu 	data32 &= Q8_FDT_MASK_VAL;
342f10a77bbSDavid C Somayajulu 	if (hw->fdt.flash_manuf == data32)
343f10a77bbSDavid C Somayajulu 		return (0);
344f10a77bbSDavid C Somayajulu 	else
345f10a77bbSDavid C Somayajulu 		return (-1);
346f10a77bbSDavid C Somayajulu }
347f10a77bbSDavid C Somayajulu 
348f10a77bbSDavid C Somayajulu static int
qla_flash_write_enable(qla_host_t * ha,int enable)349f10a77bbSDavid C Somayajulu qla_flash_write_enable(qla_host_t *ha, int enable)
350f10a77bbSDavid C Somayajulu {
351f10a77bbSDavid C Somayajulu 	uint32_t data32;
352f10a77bbSDavid C Somayajulu 	int count = 0;
353f10a77bbSDavid C Somayajulu 
354f10a77bbSDavid C Somayajulu 	data32 = Q8_WR_ENABLE_FL_ADDR | ha->hw.fdt.write_statusreg_cmd;
355f10a77bbSDavid C Somayajulu 	if (ql_rdwr_indreg32(ha, Q8_FLASH_ADDRESS, &data32, 0)) {
356f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev,
357f10a77bbSDavid C Somayajulu 			"%s: Write to Q8_FLASH_ADDRESS failed\n",
358f10a77bbSDavid C Somayajulu 			__func__);
359f10a77bbSDavid C Somayajulu 		return (-1);
360f10a77bbSDavid C Somayajulu 	}
361f10a77bbSDavid C Somayajulu 
362f10a77bbSDavid C Somayajulu 	if (enable)
363f10a77bbSDavid C Somayajulu 		data32 = ha->hw.fdt.write_enable_bits;
364f10a77bbSDavid C Somayajulu 	else
365f10a77bbSDavid C Somayajulu 		data32 = ha->hw.fdt.write_disable_bits;
366f10a77bbSDavid C Somayajulu 
367f10a77bbSDavid C Somayajulu 	if (ql_rdwr_indreg32(ha, Q8_FLASH_WR_DATA, &data32, 0)) {
368f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev,
369f10a77bbSDavid C Somayajulu 			"%s: Write to Q8_FLASH_WR_DATA failed\n",
370f10a77bbSDavid C Somayajulu 			__func__);
371f10a77bbSDavid C Somayajulu 		return (-1);
372f10a77bbSDavid C Somayajulu 	}
373f10a77bbSDavid C Somayajulu 
374f10a77bbSDavid C Somayajulu 	data32 = Q8_WR_ENABLE_FL_CTRL;
375f10a77bbSDavid C Somayajulu 	if (ql_rdwr_indreg32(ha, Q8_FLASH_CONTROL, &data32, 0)) {
376f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev,
377f10a77bbSDavid C Somayajulu 			"%s: Write to Q8_FLASH_CONTROL failed\n",
378f10a77bbSDavid C Somayajulu 			__func__);
379f10a77bbSDavid C Somayajulu 		return (-1);
380f10a77bbSDavid C Somayajulu 	}
381f10a77bbSDavid C Somayajulu 
382f10a77bbSDavid C Somayajulu 	do {
383f10a77bbSDavid C Somayajulu 		if (count < 1000) {
384f10a77bbSDavid C Somayajulu 			QLA_USEC_DELAY(10);
385f10a77bbSDavid C Somayajulu 			count += 10;
386f10a77bbSDavid C Somayajulu 		} else {
387f10a77bbSDavid C Somayajulu 			qla_mdelay(__func__, 1);
388f10a77bbSDavid C Somayajulu 			count += 1000;
389f10a77bbSDavid C Somayajulu 		}
390f10a77bbSDavid C Somayajulu 
391f10a77bbSDavid C Somayajulu 		data32 = 0;
392f10a77bbSDavid C Somayajulu 		if (ql_rdwr_indreg32(ha, Q8_FLASH_STATUS, &data32, 1)) {
393f10a77bbSDavid C Somayajulu 			device_printf(ha->pci_dev,
394f10a77bbSDavid C Somayajulu 				"%s: Read Q8_FLASH_STATUS failed\n",
395f10a77bbSDavid C Somayajulu 				__func__);
396f10a77bbSDavid C Somayajulu 			return (-1);
397f10a77bbSDavid C Somayajulu 		}
398f10a77bbSDavid C Somayajulu 
399f10a77bbSDavid C Somayajulu 		data32 &= 0x6;
400f10a77bbSDavid C Somayajulu 
401f10a77bbSDavid C Somayajulu 	} while ((count < 10000) && (data32 != 0x6));
402f10a77bbSDavid C Somayajulu 
403e43ab9b9SDavid C Somayajulu 	if (data32 != 0x6) {
404f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev,
405f10a77bbSDavid C Somayajulu 			"%s: Poll Q8_FLASH_STATUS failed\n",
406f10a77bbSDavid C Somayajulu 			__func__);
407f10a77bbSDavid C Somayajulu 		return (-1);
408f10a77bbSDavid C Somayajulu 	}
409f10a77bbSDavid C Somayajulu 
410f10a77bbSDavid C Somayajulu 	return 0;
411f10a77bbSDavid C Somayajulu }
412f10a77bbSDavid C Somayajulu 
413f10a77bbSDavid C Somayajulu static int
qla_erase_flash_sector(qla_host_t * ha,uint32_t start)414f10a77bbSDavid C Somayajulu qla_erase_flash_sector(qla_host_t *ha, uint32_t start)
415f10a77bbSDavid C Somayajulu {
416f10a77bbSDavid C Somayajulu 	uint32_t data32;
417f10a77bbSDavid C Somayajulu 	int count = 0;
418f10a77bbSDavid C Somayajulu 
419f10a77bbSDavid C Somayajulu 	do {
420f10a77bbSDavid C Somayajulu 		qla_mdelay(__func__, 1);
421f10a77bbSDavid C Somayajulu 
422f10a77bbSDavid C Somayajulu 		data32 = 0;
423f10a77bbSDavid C Somayajulu 		if (ql_rdwr_indreg32(ha, Q8_FLASH_STATUS, &data32, 1)) {
424f10a77bbSDavid C Somayajulu 			device_printf(ha->pci_dev,
425f10a77bbSDavid C Somayajulu 				"%s: Read Q8_FLASH_STATUS failed\n",
426f10a77bbSDavid C Somayajulu 				__func__);
427f10a77bbSDavid C Somayajulu 			return (-1);
428f10a77bbSDavid C Somayajulu 		}
429f10a77bbSDavid C Somayajulu 
430f10a77bbSDavid C Somayajulu 		data32 &= 0x6;
431f10a77bbSDavid C Somayajulu 
432f10a77bbSDavid C Somayajulu 	} while (((count++) < 1000) && (data32 != 0x6));
433f10a77bbSDavid C Somayajulu 
434e43ab9b9SDavid C Somayajulu 	if (data32 != 0x6) {
435f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev,
436f10a77bbSDavid C Somayajulu 			"%s: Poll Q8_FLASH_STATUS failed\n",
437f10a77bbSDavid C Somayajulu 			__func__);
438f10a77bbSDavid C Somayajulu 		return (-1);
439f10a77bbSDavid C Somayajulu 	}
440f10a77bbSDavid C Somayajulu 
441f10a77bbSDavid C Somayajulu 	data32 = (start >> 16) & 0xFF;
442f10a77bbSDavid C Somayajulu 	if (ql_rdwr_indreg32(ha, Q8_FLASH_WR_DATA, &data32, 0)) {
443f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev,
444f10a77bbSDavid C Somayajulu 			"%s: Write to Q8_FLASH_WR_DATA failed\n",
445f10a77bbSDavid C Somayajulu 			__func__);
446f10a77bbSDavid C Somayajulu 		return (-1);
447f10a77bbSDavid C Somayajulu 	}
448f10a77bbSDavid C Somayajulu 
449f10a77bbSDavid C Somayajulu 	data32 = Q8_ERASE_FL_ADDR_MASK | ha->hw.fdt.erase_cmd;
450f10a77bbSDavid C Somayajulu 	if (ql_rdwr_indreg32(ha, Q8_FLASH_ADDRESS, &data32, 0)) {
451f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev,
452f10a77bbSDavid C Somayajulu 			"%s: Write to Q8_FLASH_ADDRESS failed\n",
453f10a77bbSDavid C Somayajulu 			__func__);
454f10a77bbSDavid C Somayajulu 		return (-1);
455f10a77bbSDavid C Somayajulu 	}
456f10a77bbSDavid C Somayajulu 
457f10a77bbSDavid C Somayajulu 	data32 = Q8_ERASE_FL_CTRL_MASK;
458f10a77bbSDavid C Somayajulu 	if (ql_rdwr_indreg32(ha, Q8_FLASH_CONTROL, &data32, 0)) {
459f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev,
460f10a77bbSDavid C Somayajulu 			"%s: Write to Q8_FLASH_CONTROL failed\n",
461f10a77bbSDavid C Somayajulu 			__func__);
462f10a77bbSDavid C Somayajulu 		return (-1);
463f10a77bbSDavid C Somayajulu 	}
464f10a77bbSDavid C Somayajulu 
465f10a77bbSDavid C Somayajulu 	count = 0;
466f10a77bbSDavid C Somayajulu 	do {
467f10a77bbSDavid C Somayajulu 		qla_mdelay(__func__, 1);
468f10a77bbSDavid C Somayajulu 
469f10a77bbSDavid C Somayajulu 		data32 = 0;
470f10a77bbSDavid C Somayajulu 		if (ql_rdwr_indreg32(ha, Q8_FLASH_STATUS, &data32, 1)) {
471f10a77bbSDavid C Somayajulu 			device_printf(ha->pci_dev,
472f10a77bbSDavid C Somayajulu 				"%s: Read Q8_FLASH_STATUS failed\n",
473f10a77bbSDavid C Somayajulu 				__func__);
474f10a77bbSDavid C Somayajulu 			return (-1);
475f10a77bbSDavid C Somayajulu 		}
476f10a77bbSDavid C Somayajulu 
477f10a77bbSDavid C Somayajulu 		data32 &= 0x6;
478f10a77bbSDavid C Somayajulu 
479f10a77bbSDavid C Somayajulu 	} while (((count++) < 1000) && (data32 != 0x6));
480f10a77bbSDavid C Somayajulu 
481e43ab9b9SDavid C Somayajulu 	if (data32 != 0x6) {
482f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev,
483f10a77bbSDavid C Somayajulu 			"%s: Poll Q8_FLASH_STATUS failed\n",
484f10a77bbSDavid C Somayajulu 			__func__);
485f10a77bbSDavid C Somayajulu 		return (-1);
486f10a77bbSDavid C Somayajulu 	}
487f10a77bbSDavid C Somayajulu 
488f10a77bbSDavid C Somayajulu 	return 0;
489f10a77bbSDavid C Somayajulu }
490f10a77bbSDavid C Somayajulu 
491f10a77bbSDavid C Somayajulu int
ql_erase_flash(qla_host_t * ha,uint32_t off,uint32_t size)492f10a77bbSDavid C Somayajulu ql_erase_flash(qla_host_t *ha, uint32_t off, uint32_t size)
493f10a77bbSDavid C Somayajulu {
494f10a77bbSDavid C Somayajulu 	int rval = 0;
495f10a77bbSDavid C Somayajulu 	uint32_t start;
496f10a77bbSDavid C Somayajulu 
497f10a77bbSDavid C Somayajulu 	if (off & (Q8_FLASH_SECTOR_SIZE -1))
498f10a77bbSDavid C Somayajulu 		return (-1);
499f10a77bbSDavid C Somayajulu 
500f10a77bbSDavid C Somayajulu 	if (qla_sem_lock(ha, Q8_FLASH_LOCK, Q8_FLASH_LOCK_ID,
501f10a77bbSDavid C Somayajulu 		Q8_ERASE_LOCK_MAGIC_ID)) {
502f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "%s: Q8_FLASH_LOCK failed\n",
503f10a77bbSDavid C Somayajulu 			__func__);
504f10a77bbSDavid C Somayajulu 		return (-1);
505f10a77bbSDavid C Somayajulu 	}
506f10a77bbSDavid C Somayajulu 
507f10a77bbSDavid C Somayajulu 	if (qla_flash_write_enable(ha, 1) != 0) {
508f10a77bbSDavid C Somayajulu 		rval = -1;
509f10a77bbSDavid C Somayajulu 		goto ql_erase_flash_exit;
510f10a77bbSDavid C Somayajulu 	}
511f10a77bbSDavid C Somayajulu 
512f10a77bbSDavid C Somayajulu 	for (start = off; start < (off + size); start = start +
513f10a77bbSDavid C Somayajulu 		Q8_FLASH_SECTOR_SIZE) {
514f10a77bbSDavid C Somayajulu 			if (qla_erase_flash_sector(ha, start)) {
515f10a77bbSDavid C Somayajulu 				rval = -1;
516f10a77bbSDavid C Somayajulu 				break;
517f10a77bbSDavid C Somayajulu 			}
518f10a77bbSDavid C Somayajulu 	}
519f10a77bbSDavid C Somayajulu 
520f10a77bbSDavid C Somayajulu 	rval = qla_flash_write_enable(ha, 0);
521f10a77bbSDavid C Somayajulu 
522f10a77bbSDavid C Somayajulu ql_erase_flash_exit:
523f10a77bbSDavid C Somayajulu 	qla_sem_unlock(ha, Q8_FLASH_UNLOCK);
524f10a77bbSDavid C Somayajulu 	return (rval);
525f10a77bbSDavid C Somayajulu }
526f10a77bbSDavid C Somayajulu 
527f10a77bbSDavid C Somayajulu static int
qla_wr_flash32(qla_host_t * ha,uint32_t off,uint32_t * data)528f10a77bbSDavid C Somayajulu qla_wr_flash32(qla_host_t *ha, uint32_t off, uint32_t *data)
529f10a77bbSDavid C Somayajulu {
530f10a77bbSDavid C Somayajulu 	uint32_t data32;
531f10a77bbSDavid C Somayajulu 	int count = 0;
532f10a77bbSDavid C Somayajulu 
533f10a77bbSDavid C Somayajulu 	data32 = Q8_WR_FL_ADDR_MASK | (off >> 2);
534f10a77bbSDavid C Somayajulu 	if (ql_rdwr_indreg32(ha, Q8_FLASH_ADDRESS, &data32, 0)) {
535f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev,
536f10a77bbSDavid C Somayajulu 			"%s: Write to Q8_FLASH_ADDRESS failed\n",
537f10a77bbSDavid C Somayajulu 			__func__);
538f10a77bbSDavid C Somayajulu 		return (-1);
539f10a77bbSDavid C Somayajulu 	}
540f10a77bbSDavid C Somayajulu 
541f10a77bbSDavid C Somayajulu 	if (ql_rdwr_indreg32(ha, Q8_FLASH_WR_DATA, data, 0)) {
542f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev,
543f10a77bbSDavid C Somayajulu 			"%s: Write to Q8_FLASH_WR_DATA failed\n",
544f10a77bbSDavid C Somayajulu 			__func__);
545f10a77bbSDavid C Somayajulu 		return (-1);
546f10a77bbSDavid C Somayajulu 	}
547f10a77bbSDavid C Somayajulu 
548f10a77bbSDavid C Somayajulu 	data32 = Q8_WR_FL_CTRL_MASK;
549f10a77bbSDavid C Somayajulu 	if (ql_rdwr_indreg32(ha, Q8_FLASH_CONTROL, &data32, 0)) {
550f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev,
551f10a77bbSDavid C Somayajulu 			"%s: Write to Q8_FLASH_CONTROL failed\n",
552f10a77bbSDavid C Somayajulu 			__func__);
553f10a77bbSDavid C Somayajulu 		return (-1);
554f10a77bbSDavid C Somayajulu 	}
555f10a77bbSDavid C Somayajulu 
556f10a77bbSDavid C Somayajulu 	do {
557f10a77bbSDavid C Somayajulu 		if (count < 1000) {
558f10a77bbSDavid C Somayajulu 			QLA_USEC_DELAY(10);
559f10a77bbSDavid C Somayajulu 			count += 10;
560f10a77bbSDavid C Somayajulu 		} else {
561f10a77bbSDavid C Somayajulu 			qla_mdelay(__func__, 1);
562f10a77bbSDavid C Somayajulu 			count += 1000;
563f10a77bbSDavid C Somayajulu 		}
564f10a77bbSDavid C Somayajulu 
565f10a77bbSDavid C Somayajulu 		data32 = 0;
566f10a77bbSDavid C Somayajulu 		if (ql_rdwr_indreg32(ha, Q8_FLASH_STATUS, &data32, 1)) {
567f10a77bbSDavid C Somayajulu 			device_printf(ha->pci_dev,
568f10a77bbSDavid C Somayajulu 				"%s: Read Q8_FLASH_STATUS failed\n",
569f10a77bbSDavid C Somayajulu 				__func__);
570f10a77bbSDavid C Somayajulu 			return (-1);
571f10a77bbSDavid C Somayajulu 		}
572f10a77bbSDavid C Somayajulu 
573f10a77bbSDavid C Somayajulu 		data32 &= 0x6;
574f10a77bbSDavid C Somayajulu 
575f10a77bbSDavid C Somayajulu 	} while ((count < 10000) && (data32 != 0x6));
576f10a77bbSDavid C Somayajulu 
577e43ab9b9SDavid C Somayajulu 	if (data32 != 0x6) {
578f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev,
579f10a77bbSDavid C Somayajulu 			"%s: Poll Q8_FLASH_STATUS failed\n",
580f10a77bbSDavid C Somayajulu 			__func__);
581f10a77bbSDavid C Somayajulu 		return (-1);
582f10a77bbSDavid C Somayajulu 	}
583f10a77bbSDavid C Somayajulu 
584f10a77bbSDavid C Somayajulu 	return 0;
585f10a77bbSDavid C Somayajulu }
586f10a77bbSDavid C Somayajulu 
587f10a77bbSDavid C Somayajulu static int
qla_flash_write_data(qla_host_t * ha,uint32_t off,uint32_t size,void * data)588f10a77bbSDavid C Somayajulu qla_flash_write_data(qla_host_t *ha, uint32_t off, uint32_t size,
589f10a77bbSDavid C Somayajulu         void *data)
590f10a77bbSDavid C Somayajulu {
591f10a77bbSDavid C Somayajulu 	int rval = 0;
592f10a77bbSDavid C Somayajulu 	uint32_t start;
593f10a77bbSDavid C Somayajulu 	uint32_t *data32 = data;
594f10a77bbSDavid C Somayajulu 
595f10a77bbSDavid C Somayajulu 	if (qla_sem_lock(ha, Q8_FLASH_LOCK, Q8_FLASH_LOCK_ID,
596f10a77bbSDavid C Somayajulu 		Q8_WR_FL_LOCK_MAGIC_ID)) {
597f10a77bbSDavid C Somayajulu 			device_printf(ha->pci_dev, "%s: Q8_FLASH_LOCK failed\n",
598f10a77bbSDavid C Somayajulu 				__func__);
599f10a77bbSDavid C Somayajulu 			rval = -1;
600f10a77bbSDavid C Somayajulu 			goto qla_flash_write_data_exit;
601f10a77bbSDavid C Somayajulu 	}
602f10a77bbSDavid C Somayajulu 
603f10a77bbSDavid C Somayajulu 	if ((qla_flash_write_enable(ha, 1) != 0)) {
604f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "%s: failed\n",
605f10a77bbSDavid C Somayajulu 			__func__);
606f10a77bbSDavid C Somayajulu 		rval = -1;
607f10a77bbSDavid C Somayajulu 		goto qla_flash_write_data_unlock_exit;
608f10a77bbSDavid C Somayajulu 	}
609f10a77bbSDavid C Somayajulu 
610f10a77bbSDavid C Somayajulu 	for (start = off; start < (off + size); start = start + 4) {
611f10a77bbSDavid C Somayajulu 		if (*data32 != 0xFFFFFFFF) {
612f10a77bbSDavid C Somayajulu 			if (qla_wr_flash32(ha, start, data32)) {
613f10a77bbSDavid C Somayajulu 				rval = -1;
614f10a77bbSDavid C Somayajulu 				break;
615f10a77bbSDavid C Somayajulu 			}
616f10a77bbSDavid C Somayajulu 		}
617f10a77bbSDavid C Somayajulu 		data32++;
618f10a77bbSDavid C Somayajulu 	}
619f10a77bbSDavid C Somayajulu 
620f10a77bbSDavid C Somayajulu 	rval = qla_flash_write_enable(ha, 0);
621f10a77bbSDavid C Somayajulu 
622f10a77bbSDavid C Somayajulu qla_flash_write_data_unlock_exit:
623f10a77bbSDavid C Somayajulu 	qla_sem_unlock(ha, Q8_FLASH_UNLOCK);
624f10a77bbSDavid C Somayajulu 
625f10a77bbSDavid C Somayajulu qla_flash_write_data_exit:
626f10a77bbSDavid C Somayajulu 	return (rval);
627f10a77bbSDavid C Somayajulu }
628f10a77bbSDavid C Somayajulu 
629f10a77bbSDavid C Somayajulu int
ql_wr_flash_buffer(qla_host_t * ha,uint32_t off,uint32_t size,void * buf)630f10a77bbSDavid C Somayajulu ql_wr_flash_buffer(qla_host_t *ha, uint32_t off, uint32_t size, void *buf)
631f10a77bbSDavid C Somayajulu {
632f10a77bbSDavid C Somayajulu 	int rval = 0;
633f10a77bbSDavid C Somayajulu 	void *data;
634f10a77bbSDavid C Somayajulu 
635f10a77bbSDavid C Somayajulu 	if (size == 0)
636f10a77bbSDavid C Somayajulu 		return 0;
637f10a77bbSDavid C Somayajulu 
638f10a77bbSDavid C Somayajulu 	size = size << 2;
639f10a77bbSDavid C Somayajulu 
640f10a77bbSDavid C Somayajulu 	if (buf == NULL)
641f10a77bbSDavid C Somayajulu 		return -1;
642f10a77bbSDavid C Somayajulu 
643f10a77bbSDavid C Somayajulu 	if ((data = malloc(size, M_QLA83XXBUF, M_NOWAIT)) == NULL) {
644f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "%s: malloc failed \n", __func__);
645f10a77bbSDavid C Somayajulu 		rval = -1;
646f10a77bbSDavid C Somayajulu 		goto ql_wr_flash_buffer_exit;
647f10a77bbSDavid C Somayajulu 	}
648f10a77bbSDavid C Somayajulu 
649f10a77bbSDavid C Somayajulu 	if ((rval = copyin(buf, data, size))) {
650f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "%s copyin failed\n", __func__);
651f10a77bbSDavid C Somayajulu 		goto ql_wr_flash_buffer_free_exit;
652f10a77bbSDavid C Somayajulu 	}
653f10a77bbSDavid C Somayajulu 
654f10a77bbSDavid C Somayajulu 	rval = qla_flash_write_data(ha, off, size, data);
655f10a77bbSDavid C Somayajulu 
656f10a77bbSDavid C Somayajulu ql_wr_flash_buffer_free_exit:
657f10a77bbSDavid C Somayajulu 	free(data, M_QLA83XXBUF);
658f10a77bbSDavid C Somayajulu 
659f10a77bbSDavid C Somayajulu ql_wr_flash_buffer_exit:
660f10a77bbSDavid C Somayajulu 	return (rval);
661f10a77bbSDavid C Somayajulu }
662f10a77bbSDavid C Somayajulu 
66335291c22SDavid C Somayajulu #ifdef QL_LDFLASH_FW
664f10a77bbSDavid C Somayajulu /*
665f10a77bbSDavid C Somayajulu  * Name: qla_load_fw_from_flash
666f10a77bbSDavid C Somayajulu  * Function: Reads the Bootloader from Flash and Loads into Offchip Memory
667f10a77bbSDavid C Somayajulu  */
668f10a77bbSDavid C Somayajulu static void
qla_load_fw_from_flash(qla_host_t * ha)669f10a77bbSDavid C Somayajulu qla_load_fw_from_flash(qla_host_t *ha)
670f10a77bbSDavid C Somayajulu {
671f10a77bbSDavid C Somayajulu 	uint32_t flash_off	= 0x10000;
672f10a77bbSDavid C Somayajulu 	uint64_t mem_off;
673f10a77bbSDavid C Somayajulu 	uint32_t count, mem_size;
674f10a77bbSDavid C Somayajulu 	q80_offchip_mem_val_t val;
675f10a77bbSDavid C Somayajulu 
676f10a77bbSDavid C Somayajulu 	mem_off = (uint64_t)(READ_REG32(ha, Q8_BOOTLD_ADDR));
677f10a77bbSDavid C Somayajulu 	mem_size = READ_REG32(ha, Q8_BOOTLD_SIZE);
678f10a77bbSDavid C Somayajulu 
679f10a77bbSDavid C Somayajulu 	device_printf(ha->pci_dev, "%s: [0x%08x][0x%08x]\n",
680f10a77bbSDavid C Somayajulu 		__func__, (uint32_t)mem_off, mem_size);
681f10a77bbSDavid C Somayajulu 
682f10a77bbSDavid C Somayajulu 	/* only bootloader needs to be loaded into memory */
683f10a77bbSDavid C Somayajulu 	for (count = 0; count < mem_size ; ) {
684f10a77bbSDavid C Somayajulu 		ql_rd_flash32(ha, flash_off, &val.data_lo);
685f10a77bbSDavid C Somayajulu 		count = count + 4;
686f10a77bbSDavid C Somayajulu 		flash_off = flash_off + 4;
687f10a77bbSDavid C Somayajulu 
688f10a77bbSDavid C Somayajulu 		ql_rd_flash32(ha, flash_off, &val.data_hi);
689f10a77bbSDavid C Somayajulu 		count = count + 4;
690f10a77bbSDavid C Somayajulu 		flash_off = flash_off + 4;
691f10a77bbSDavid C Somayajulu 
692f10a77bbSDavid C Somayajulu 		ql_rd_flash32(ha, flash_off, &val.data_ulo);
693f10a77bbSDavid C Somayajulu 		count = count + 4;
694f10a77bbSDavid C Somayajulu 		flash_off = flash_off + 4;
695f10a77bbSDavid C Somayajulu 
696f10a77bbSDavid C Somayajulu 		ql_rd_flash32(ha, flash_off, &val.data_uhi);
697f10a77bbSDavid C Somayajulu 		count = count + 4;
698f10a77bbSDavid C Somayajulu 		flash_off = flash_off + 4;
699f10a77bbSDavid C Somayajulu 
700f10a77bbSDavid C Somayajulu 		ql_rdwr_offchip_mem(ha, mem_off, &val, 0);
701f10a77bbSDavid C Somayajulu 
702f10a77bbSDavid C Somayajulu 		mem_off = mem_off + 16;
703f10a77bbSDavid C Somayajulu 	}
704f10a77bbSDavid C Somayajulu 
705f10a77bbSDavid C Somayajulu 	return;
706f10a77bbSDavid C Somayajulu }
70735291c22SDavid C Somayajulu #endif /* #ifdef QL_LDFLASH_FW */
708f10a77bbSDavid C Somayajulu 
709f10a77bbSDavid C Somayajulu /*
710f10a77bbSDavid C Somayajulu  * Name: qla_init_from_flash
711f10a77bbSDavid C Somayajulu  * Function: Performs Initialization which consists of the following sequence
712f10a77bbSDavid C Somayajulu  *	- reset
713f10a77bbSDavid C Somayajulu  *	- CRB Init
714f10a77bbSDavid C Somayajulu  *	- Peg Init
715f10a77bbSDavid C Somayajulu  *	- Read the Bootloader from Flash and Load into Offchip Memory
716f10a77bbSDavid C Somayajulu  *	- Kick start the bootloader which loads the rest of the firmware
717f10a77bbSDavid C Somayajulu  *		and performs the remaining steps in the initialization process.
718f10a77bbSDavid C Somayajulu  */
719f10a77bbSDavid C Somayajulu static int
qla_init_from_flash(qla_host_t * ha)720f10a77bbSDavid C Somayajulu qla_init_from_flash(qla_host_t *ha)
721f10a77bbSDavid C Somayajulu {
722f10a77bbSDavid C Somayajulu 	uint32_t delay = 300;
723f10a77bbSDavid C Somayajulu 	uint32_t data;
724f10a77bbSDavid C Somayajulu 
725f10a77bbSDavid C Somayajulu 	qla_ld_fw_init(ha);
726f10a77bbSDavid C Somayajulu 
727f10a77bbSDavid C Somayajulu 	do {
728f10a77bbSDavid C Somayajulu 		data = READ_REG32(ha, Q8_CMDPEG_STATE);
729f10a77bbSDavid C Somayajulu 
730f10a77bbSDavid C Somayajulu 		QL_DPRINT2(ha,
731f10a77bbSDavid C Somayajulu 			(ha->pci_dev, "%s: func[%d] cmdpegstate 0x%08x\n",
732f10a77bbSDavid C Somayajulu 				__func__, ha->pci_func, data));
733f10a77bbSDavid C Somayajulu 		if (data == 0xFF01) {
734f10a77bbSDavid C Somayajulu 			QL_DPRINT2(ha, (ha->pci_dev,
735f10a77bbSDavid C Somayajulu 				"%s: func[%d] init complete\n",
736f10a77bbSDavid C Somayajulu 				__func__, ha->pci_func));
737f10a77bbSDavid C Somayajulu 			return(0);
738f10a77bbSDavid C Somayajulu 		}
739f10a77bbSDavid C Somayajulu 		qla_mdelay(__func__, 100);
740f10a77bbSDavid C Somayajulu 	} while (delay--);
741f10a77bbSDavid C Somayajulu 
742f10a77bbSDavid C Somayajulu 	return (-1);
743f10a77bbSDavid C Somayajulu }
744f10a77bbSDavid C Somayajulu 
745f10a77bbSDavid C Somayajulu /*
746f10a77bbSDavid C Somayajulu  * Name: ql_init_hw
747f10a77bbSDavid C Somayajulu  * Function: Initializes P3+ hardware.
748f10a77bbSDavid C Somayajulu  */
749f10a77bbSDavid C Somayajulu int
ql_init_hw(qla_host_t * ha)750f10a77bbSDavid C Somayajulu ql_init_hw(qla_host_t *ha)
751f10a77bbSDavid C Somayajulu {
752f10a77bbSDavid C Somayajulu         device_t dev;
753f10a77bbSDavid C Somayajulu         int ret = 0;
754f10a77bbSDavid C Somayajulu         uint32_t val, delay = 300;
755f10a77bbSDavid C Somayajulu 
756f10a77bbSDavid C Somayajulu         dev = ha->pci_dev;
757f10a77bbSDavid C Somayajulu 
758f10a77bbSDavid C Somayajulu         QL_DPRINT1(ha, (dev, "%s: enter\n", __func__));
759f10a77bbSDavid C Somayajulu 
760f10a77bbSDavid C Somayajulu 	if (ha->pci_func & 0x1) {
761f10a77bbSDavid C Somayajulu         	while ((ha->pci_func & 0x1) && delay--) {
762f10a77bbSDavid C Somayajulu 			val = READ_REG32(ha, Q8_CMDPEG_STATE);
763f10a77bbSDavid C Somayajulu 
764f10a77bbSDavid C Somayajulu 			if (val == 0xFF01) {
765f10a77bbSDavid C Somayajulu 				QL_DPRINT2(ha, (dev,
766f10a77bbSDavid C Somayajulu 					"%s: func = %d init complete\n",
767f10a77bbSDavid C Somayajulu 					__func__, ha->pci_func));
768f10a77bbSDavid C Somayajulu 				qla_mdelay(__func__, 100);
769f10a77bbSDavid C Somayajulu 				goto qla_init_exit;
770f10a77bbSDavid C Somayajulu 			}
771f10a77bbSDavid C Somayajulu 			qla_mdelay(__func__, 100);
772f10a77bbSDavid C Somayajulu 		}
773b65c0c07SDavid C Somayajulu 		ret = -1;
774b65c0c07SDavid C Somayajulu 		goto ql_init_hw_exit;
775f10a77bbSDavid C Somayajulu 	}
776f10a77bbSDavid C Somayajulu 
777f10a77bbSDavid C Somayajulu 	val = READ_REG32(ha, Q8_CMDPEG_STATE);
778b65c0c07SDavid C Somayajulu 	if (!cold || (val != 0xFF01) || ha->qla_initiate_recovery) {
779f10a77bbSDavid C Somayajulu         	ret = qla_init_from_flash(ha);
780f10a77bbSDavid C Somayajulu 		qla_mdelay(__func__, 100);
781f10a77bbSDavid C Somayajulu 	}
782f10a77bbSDavid C Somayajulu 
783f10a77bbSDavid C Somayajulu qla_init_exit:
784f10a77bbSDavid C Somayajulu         ha->fw_ver_major = READ_REG32(ha, Q8_FW_VER_MAJOR);
785f10a77bbSDavid C Somayajulu         ha->fw_ver_minor = READ_REG32(ha, Q8_FW_VER_MINOR);
786f10a77bbSDavid C Somayajulu         ha->fw_ver_sub = READ_REG32(ha, Q8_FW_VER_SUB);
787f10a77bbSDavid C Somayajulu 
788f10a77bbSDavid C Somayajulu 	if (qla_get_fdt(ha) != 0) {
789f10a77bbSDavid C Somayajulu 		device_printf(dev, "%s: qla_get_fdt failed\n", __func__);
790f10a77bbSDavid C Somayajulu 	} else {
791f10a77bbSDavid C Somayajulu 		ha->hw.flags.fdt_valid = 1;
792f10a77bbSDavid C Somayajulu 	}
793f10a77bbSDavid C Somayajulu 
794b65c0c07SDavid C Somayajulu ql_init_hw_exit:
795b65c0c07SDavid C Somayajulu 
796b65c0c07SDavid C Somayajulu 	if (ret) {
797b65c0c07SDavid C Somayajulu 		if (ha->hw.sp_log_stop_events & Q8_SP_LOG_STOP_HW_INIT_FAILURE)
798b65c0c07SDavid C Somayajulu 			ha->hw.sp_log_stop = -1;
799b65c0c07SDavid C Somayajulu 	}
800b65c0c07SDavid C Somayajulu 
801f10a77bbSDavid C Somayajulu         return (ret);
802f10a77bbSDavid C Somayajulu }
803f10a77bbSDavid C Somayajulu 
804f10a77bbSDavid C Somayajulu void
ql_read_mac_addr(qla_host_t * ha)805f10a77bbSDavid C Somayajulu ql_read_mac_addr(qla_host_t *ha)
806f10a77bbSDavid C Somayajulu {
807f10a77bbSDavid C Somayajulu 	uint8_t *macp;
808f10a77bbSDavid C Somayajulu 	uint32_t mac_lo;
809f10a77bbSDavid C Somayajulu 	uint32_t mac_hi;
810f10a77bbSDavid C Somayajulu 	uint32_t flash_off;
811f10a77bbSDavid C Somayajulu 
812f10a77bbSDavid C Somayajulu 	flash_off = Q8_BOARD_CONFIG_OFFSET + Q8_BOARD_CONFIG_MAC0_LO +
813f10a77bbSDavid C Somayajulu 			(ha->pci_func << 3);
814f10a77bbSDavid C Somayajulu 	ql_rd_flash32(ha, flash_off, &mac_lo);
815f10a77bbSDavid C Somayajulu 
816f10a77bbSDavid C Somayajulu 	flash_off += 4;
817f10a77bbSDavid C Somayajulu 	ql_rd_flash32(ha, flash_off, &mac_hi);
818f10a77bbSDavid C Somayajulu 
819f10a77bbSDavid C Somayajulu 	macp = (uint8_t *)&mac_lo;
820f10a77bbSDavid C Somayajulu 	ha->hw.mac_addr[5] = macp[0];
821f10a77bbSDavid C Somayajulu 	ha->hw.mac_addr[4] = macp[1];
822f10a77bbSDavid C Somayajulu 	ha->hw.mac_addr[3] = macp[2];
823f10a77bbSDavid C Somayajulu 	ha->hw.mac_addr[2] = macp[3];
824f10a77bbSDavid C Somayajulu 
825f10a77bbSDavid C Somayajulu 	macp = (uint8_t *)&mac_hi;
826f10a77bbSDavid C Somayajulu 	ha->hw.mac_addr[1] = macp[0];
827f10a77bbSDavid C Somayajulu 	ha->hw.mac_addr[0] = macp[1];
828f10a77bbSDavid C Somayajulu 
829f10a77bbSDavid C Somayajulu 	//device_printf(ha->pci_dev, "%s: %02x:%02x:%02x:%02x:%02x:%02x\n",
830f10a77bbSDavid C Somayajulu 	//	__func__, ha->hw.mac_addr[0], ha->hw.mac_addr[1],
831f10a77bbSDavid C Somayajulu 	//	ha->hw.mac_addr[2], ha->hw.mac_addr[3],
832f10a77bbSDavid C Somayajulu 	//	ha->hw.mac_addr[4], ha->hw.mac_addr[5]);
833f10a77bbSDavid C Somayajulu 
834f10a77bbSDavid C Somayajulu         return;
835f10a77bbSDavid C Somayajulu }
836f10a77bbSDavid C Somayajulu 
837f10a77bbSDavid C Somayajulu /*
838f10a77bbSDavid C Somayajulu  * Stop/Start/Initialization Handling
839f10a77bbSDavid C Somayajulu  */
840f10a77bbSDavid C Somayajulu 
841f10a77bbSDavid C Somayajulu static uint16_t
qla_tmplt_16bit_checksum(qla_host_t * ha,uint16_t * buf,uint32_t size)842f10a77bbSDavid C Somayajulu qla_tmplt_16bit_checksum(qla_host_t *ha, uint16_t *buf, uint32_t size)
843f10a77bbSDavid C Somayajulu {
844f10a77bbSDavid C Somayajulu 	uint32_t sum = 0;
845f10a77bbSDavid C Somayajulu 	uint32_t count = size >> 1; /* size in 16 bit words */
846f10a77bbSDavid C Somayajulu 
847f10a77bbSDavid C Somayajulu 	while (count-- > 0)
848f10a77bbSDavid C Somayajulu 		sum += *buf++;
849f10a77bbSDavid C Somayajulu 
850f10a77bbSDavid C Somayajulu 	while (sum >> 16)
851f10a77bbSDavid C Somayajulu 		sum = (sum & 0xFFFF) + (sum >> 16);
852f10a77bbSDavid C Somayajulu 
853f10a77bbSDavid C Somayajulu 	return (~sum);
854f10a77bbSDavid C Somayajulu }
855f10a77bbSDavid C Somayajulu 
856f10a77bbSDavid C Somayajulu static int
qla_wr_list(qla_host_t * ha,q8_ce_hdr_t * ce_hdr)857f10a77bbSDavid C Somayajulu qla_wr_list(qla_host_t *ha, q8_ce_hdr_t *ce_hdr)
858f10a77bbSDavid C Somayajulu {
859f10a77bbSDavid C Somayajulu 	q8_wrl_e_t *wr_l;
860f10a77bbSDavid C Somayajulu 	int i;
861f10a77bbSDavid C Somayajulu 
862f10a77bbSDavid C Somayajulu 	wr_l = (q8_wrl_e_t *)((uint8_t *)ce_hdr + sizeof (q8_ce_hdr_t));
863f10a77bbSDavid C Somayajulu 
864f10a77bbSDavid C Somayajulu 	for (i = 0; i < ce_hdr->opcount; i++, wr_l++) {
865f10a77bbSDavid C Somayajulu 		if (ql_rdwr_indreg32(ha, wr_l->addr, &wr_l->value, 0)) {
866f10a77bbSDavid C Somayajulu 			device_printf(ha->pci_dev,
867f10a77bbSDavid C Somayajulu 				"%s: [0x%08x 0x%08x] error\n", __func__,
868f10a77bbSDavid C Somayajulu 				wr_l->addr, wr_l->value);
869f10a77bbSDavid C Somayajulu 			return -1;
870f10a77bbSDavid C Somayajulu 		}
871f10a77bbSDavid C Somayajulu 		if (ce_hdr->delay_to) {
872f10a77bbSDavid C Somayajulu 			DELAY(ce_hdr->delay_to);
873f10a77bbSDavid C Somayajulu 		}
874f10a77bbSDavid C Somayajulu 	}
875f10a77bbSDavid C Somayajulu 	return 0;
876f10a77bbSDavid C Somayajulu }
877f10a77bbSDavid C Somayajulu 
878f10a77bbSDavid C Somayajulu static int
qla_rd_wr_list(qla_host_t * ha,q8_ce_hdr_t * ce_hdr)879f10a77bbSDavid C Somayajulu qla_rd_wr_list(qla_host_t *ha, q8_ce_hdr_t *ce_hdr)
880f10a77bbSDavid C Somayajulu {
881f10a77bbSDavid C Somayajulu 	q8_rdwrl_e_t *rd_wr_l;
882f10a77bbSDavid C Somayajulu 	uint32_t data;
883f10a77bbSDavid C Somayajulu 	int i;
884f10a77bbSDavid C Somayajulu 
885f10a77bbSDavid C Somayajulu 	rd_wr_l = (q8_rdwrl_e_t *)((uint8_t *)ce_hdr + sizeof (q8_ce_hdr_t));
886f10a77bbSDavid C Somayajulu 
887f10a77bbSDavid C Somayajulu 	for (i = 0; i < ce_hdr->opcount; i++, rd_wr_l++) {
888f10a77bbSDavid C Somayajulu 		if (ql_rdwr_indreg32(ha, rd_wr_l->rd_addr, &data, 1)) {
889f10a77bbSDavid C Somayajulu 			device_printf(ha->pci_dev, "%s: [0x%08x] error\n",
890f10a77bbSDavid C Somayajulu 				__func__, rd_wr_l->rd_addr);
891f10a77bbSDavid C Somayajulu 
892f10a77bbSDavid C Somayajulu 			return -1;
893f10a77bbSDavid C Somayajulu 		}
894f10a77bbSDavid C Somayajulu 
895f10a77bbSDavid C Somayajulu 		if (ql_rdwr_indreg32(ha, rd_wr_l->wr_addr, &data, 0)) {
896f10a77bbSDavid C Somayajulu 			device_printf(ha->pci_dev,
897f10a77bbSDavid C Somayajulu 				"%s: [0x%08x 0x%08x] error\n", __func__,
898f10a77bbSDavid C Somayajulu 				rd_wr_l->wr_addr, data);
899f10a77bbSDavid C Somayajulu 			return -1;
900f10a77bbSDavid C Somayajulu 		}
901f10a77bbSDavid C Somayajulu 		if (ce_hdr->delay_to) {
902f10a77bbSDavid C Somayajulu 			DELAY(ce_hdr->delay_to);
903f10a77bbSDavid C Somayajulu 		}
904f10a77bbSDavid C Somayajulu 	}
905f10a77bbSDavid C Somayajulu 	return 0;
906f10a77bbSDavid C Somayajulu }
907f10a77bbSDavid C Somayajulu 
908f10a77bbSDavid C Somayajulu static int
qla_poll_reg(qla_host_t * ha,uint32_t addr,uint32_t ms_to,uint32_t tmask,uint32_t tvalue)909f10a77bbSDavid C Somayajulu qla_poll_reg(qla_host_t *ha, uint32_t addr, uint32_t ms_to, uint32_t tmask,
910f10a77bbSDavid C Somayajulu 	uint32_t tvalue)
911f10a77bbSDavid C Somayajulu {
912f10a77bbSDavid C Somayajulu 	uint32_t data;
913f10a77bbSDavid C Somayajulu 
914f10a77bbSDavid C Somayajulu 	while (ms_to) {
915f10a77bbSDavid C Somayajulu 		if (ql_rdwr_indreg32(ha, addr, &data, 1)) {
916f10a77bbSDavid C Somayajulu 			device_printf(ha->pci_dev, "%s: [0x%08x] error\n",
917f10a77bbSDavid C Somayajulu 				__func__, addr);
918f10a77bbSDavid C Somayajulu 			return -1;
919f10a77bbSDavid C Somayajulu 		}
920f10a77bbSDavid C Somayajulu 
921f10a77bbSDavid C Somayajulu 		if ((data & tmask) != tvalue) {
922f10a77bbSDavid C Somayajulu 			ms_to--;
923f10a77bbSDavid C Somayajulu 		} else
924f10a77bbSDavid C Somayajulu 			break;
925f10a77bbSDavid C Somayajulu 
926f10a77bbSDavid C Somayajulu 		qla_mdelay(__func__, 1);
927f10a77bbSDavid C Somayajulu 	}
928f10a77bbSDavid C Somayajulu 	return ((ms_to ? 0: -1));
929f10a77bbSDavid C Somayajulu }
930f10a77bbSDavid C Somayajulu 
931f10a77bbSDavid C Somayajulu static int
qla_poll_list(qla_host_t * ha,q8_ce_hdr_t * ce_hdr)932f10a77bbSDavid C Somayajulu qla_poll_list(qla_host_t *ha, q8_ce_hdr_t *ce_hdr)
933f10a77bbSDavid C Somayajulu {
934f10a77bbSDavid C Somayajulu 	int		i;
935f10a77bbSDavid C Somayajulu 	q8_poll_hdr_t	*phdr;
936f10a77bbSDavid C Somayajulu 	q8_poll_e_t	*pe;
937f10a77bbSDavid C Somayajulu 	uint32_t	data;
938f10a77bbSDavid C Somayajulu 
939f10a77bbSDavid C Somayajulu 	phdr = (q8_poll_hdr_t *)((uint8_t *)ce_hdr + sizeof (q8_ce_hdr_t));
940f10a77bbSDavid C Somayajulu 	pe = (q8_poll_e_t *)((uint8_t *)phdr + sizeof(q8_poll_hdr_t));
941f10a77bbSDavid C Somayajulu 
942f10a77bbSDavid C Somayajulu 	for (i = 0; i < ce_hdr->opcount; i++, pe++) {
943f10a77bbSDavid C Somayajulu 		if (ql_rdwr_indreg32(ha, pe->addr, &data, 1)) {
944f10a77bbSDavid C Somayajulu 			device_printf(ha->pci_dev, "%s: [0x%08x] error\n",
945f10a77bbSDavid C Somayajulu 				__func__, pe->addr);
946f10a77bbSDavid C Somayajulu 			return -1;
947f10a77bbSDavid C Somayajulu 		}
948f10a77bbSDavid C Somayajulu 
949f10a77bbSDavid C Somayajulu 		if (ce_hdr->delay_to)  {
950f10a77bbSDavid C Somayajulu 			if ((data & phdr->tmask) == phdr->tvalue)
951f10a77bbSDavid C Somayajulu 				break;
952f10a77bbSDavid C Somayajulu 			if (qla_poll_reg(ha, pe->addr, ce_hdr->delay_to,
953f10a77bbSDavid C Somayajulu 				phdr->tmask, phdr->tvalue)) {
954f10a77bbSDavid C Somayajulu 				if (ql_rdwr_indreg32(ha, pe->to_addr, &data,
955f10a77bbSDavid C Somayajulu 					1)) {
956f10a77bbSDavid C Somayajulu 					device_printf(ha->pci_dev,
957f10a77bbSDavid C Somayajulu 						"%s: [0x%08x] error\n",
958f10a77bbSDavid C Somayajulu 						__func__, pe->to_addr);
959f10a77bbSDavid C Somayajulu 					return -1;
960f10a77bbSDavid C Somayajulu 				}
961f10a77bbSDavid C Somayajulu 
962f10a77bbSDavid C Somayajulu 				if (ql_rdwr_indreg32(ha, pe->addr, &data, 1)) {
963f10a77bbSDavid C Somayajulu 					device_printf(ha->pci_dev,
964f10a77bbSDavid C Somayajulu 						"%s: [0x%08x] error\n",
965f10a77bbSDavid C Somayajulu 						__func__, pe->addr);
966f10a77bbSDavid C Somayajulu 					return -1;
967f10a77bbSDavid C Somayajulu 				}
968f10a77bbSDavid C Somayajulu 			}
969f10a77bbSDavid C Somayajulu 		}
970f10a77bbSDavid C Somayajulu 	}
971f10a77bbSDavid C Somayajulu 	return 0;
972f10a77bbSDavid C Somayajulu }
973f10a77bbSDavid C Somayajulu 
974f10a77bbSDavid C Somayajulu static int
qla_poll_write_list(qla_host_t * ha,q8_ce_hdr_t * ce_hdr)975f10a77bbSDavid C Somayajulu qla_poll_write_list(qla_host_t *ha, q8_ce_hdr_t *ce_hdr)
976f10a77bbSDavid C Somayajulu {
977f10a77bbSDavid C Somayajulu 	int		i;
978f10a77bbSDavid C Somayajulu 	q8_poll_hdr_t	*phdr;
979f10a77bbSDavid C Somayajulu 	q8_poll_wr_e_t	*wr_e;
980f10a77bbSDavid C Somayajulu 
981f10a77bbSDavid C Somayajulu 	phdr = (q8_poll_hdr_t *)((uint8_t *)ce_hdr + sizeof (q8_ce_hdr_t));
982f10a77bbSDavid C Somayajulu 	wr_e = (q8_poll_wr_e_t *)((uint8_t *)phdr + sizeof(q8_poll_hdr_t));
983f10a77bbSDavid C Somayajulu 
984f10a77bbSDavid C Somayajulu 	for (i = 0; i < ce_hdr->opcount; i++, wr_e++) {
985f10a77bbSDavid C Somayajulu 		if (ql_rdwr_indreg32(ha, wr_e->dr_addr, &wr_e->dr_value, 0)) {
986f10a77bbSDavid C Somayajulu 			device_printf(ha->pci_dev,
987f10a77bbSDavid C Somayajulu 				"%s: [0x%08x 0x%08x] error\n", __func__,
988f10a77bbSDavid C Somayajulu 				wr_e->dr_addr, wr_e->dr_value);
989f10a77bbSDavid C Somayajulu 			return -1;
990f10a77bbSDavid C Somayajulu 		}
991f10a77bbSDavid C Somayajulu 		if (ql_rdwr_indreg32(ha, wr_e->ar_addr, &wr_e->ar_value, 0)) {
992f10a77bbSDavid C Somayajulu 			device_printf(ha->pci_dev,
993f10a77bbSDavid C Somayajulu 				"%s: [0x%08x 0x%08x] error\n", __func__,
994f10a77bbSDavid C Somayajulu 				wr_e->ar_addr, wr_e->ar_value);
995f10a77bbSDavid C Somayajulu 			return -1;
996f10a77bbSDavid C Somayajulu 		}
997f10a77bbSDavid C Somayajulu 		if (ce_hdr->delay_to)  {
998f10a77bbSDavid C Somayajulu 			if (qla_poll_reg(ha, wr_e->ar_addr, ce_hdr->delay_to,
999f10a77bbSDavid C Somayajulu 				phdr->tmask, phdr->tvalue))
1000f10a77bbSDavid C Somayajulu 				device_printf(ha->pci_dev, "%s: "
1001f10a77bbSDavid C Somayajulu 					"[ar_addr, ar_value, delay, tmask,"
1002f10a77bbSDavid C Somayajulu 					"tvalue] [0x%08x 0x%08x 0x%08x 0x%08x"
1003f10a77bbSDavid C Somayajulu 					" 0x%08x]\n",
1004f10a77bbSDavid C Somayajulu 					__func__, wr_e->ar_addr, wr_e->ar_value,
1005f10a77bbSDavid C Somayajulu 					ce_hdr->delay_to, phdr->tmask,
1006f10a77bbSDavid C Somayajulu 					phdr->tvalue);
1007f10a77bbSDavid C Somayajulu 		}
1008f10a77bbSDavid C Somayajulu 	}
1009f10a77bbSDavid C Somayajulu 	return 0;
1010f10a77bbSDavid C Somayajulu }
1011f10a77bbSDavid C Somayajulu 
1012f10a77bbSDavid C Somayajulu static int
qla_poll_read_list(qla_host_t * ha,q8_ce_hdr_t * ce_hdr)1013f10a77bbSDavid C Somayajulu qla_poll_read_list(qla_host_t *ha, q8_ce_hdr_t *ce_hdr)
1014f10a77bbSDavid C Somayajulu {
1015f10a77bbSDavid C Somayajulu 	int		i;
1016f10a77bbSDavid C Somayajulu 	q8_poll_hdr_t	*phdr;
1017f10a77bbSDavid C Somayajulu 	q8_poll_rd_e_t	*rd_e;
1018f10a77bbSDavid C Somayajulu 	uint32_t	value;
1019f10a77bbSDavid C Somayajulu 
1020f10a77bbSDavid C Somayajulu 	phdr = (q8_poll_hdr_t *)((uint8_t *)ce_hdr + sizeof (q8_ce_hdr_t));
1021f10a77bbSDavid C Somayajulu 	rd_e = (q8_poll_rd_e_t *)((uint8_t *)phdr + sizeof(q8_poll_hdr_t));
1022f10a77bbSDavid C Somayajulu 
1023f10a77bbSDavid C Somayajulu 	for (i = 0; i < ce_hdr->opcount; i++, rd_e++) {
1024f10a77bbSDavid C Somayajulu 		if (ql_rdwr_indreg32(ha, rd_e->ar_addr, &rd_e->ar_value, 0)) {
1025f10a77bbSDavid C Somayajulu 			device_printf(ha->pci_dev,
1026f10a77bbSDavid C Somayajulu 				"%s: [0x%08x 0x%08x] error\n", __func__,
1027f10a77bbSDavid C Somayajulu 				rd_e->ar_addr, rd_e->ar_value);
1028f10a77bbSDavid C Somayajulu 			return -1;
1029f10a77bbSDavid C Somayajulu 		}
1030f10a77bbSDavid C Somayajulu 
1031f10a77bbSDavid C Somayajulu 		if (ce_hdr->delay_to)  {
1032f10a77bbSDavid C Somayajulu 			if (qla_poll_reg(ha, rd_e->ar_addr, ce_hdr->delay_to,
1033f10a77bbSDavid C Somayajulu 				phdr->tmask, phdr->tvalue)) {
1034f10a77bbSDavid C Somayajulu 				return (-1);
1035f10a77bbSDavid C Somayajulu 			} else {
1036f10a77bbSDavid C Somayajulu 				if (ql_rdwr_indreg32(ha, rd_e->dr_addr,
1037f10a77bbSDavid C Somayajulu 					&value, 1)) {
1038f10a77bbSDavid C Somayajulu 					device_printf(ha->pci_dev,
1039f10a77bbSDavid C Somayajulu 						"%s: [0x%08x] error\n",
1040f10a77bbSDavid C Somayajulu 						__func__, rd_e->ar_addr);
1041f10a77bbSDavid C Somayajulu 					return -1;
1042f10a77bbSDavid C Somayajulu 				}
1043f10a77bbSDavid C Somayajulu 
1044f10a77bbSDavid C Somayajulu 				ha->hw.rst_seq[ha->hw.rst_seq_idx++] = value;
1045f10a77bbSDavid C Somayajulu 				if (ha->hw.rst_seq_idx == Q8_MAX_RESET_SEQ_IDX)
1046f10a77bbSDavid C Somayajulu 					ha->hw.rst_seq_idx = 1;
1047f10a77bbSDavid C Somayajulu 			}
1048f10a77bbSDavid C Somayajulu 		}
1049f10a77bbSDavid C Somayajulu 	}
1050f10a77bbSDavid C Somayajulu 	return 0;
1051f10a77bbSDavid C Somayajulu }
1052f10a77bbSDavid C Somayajulu 
1053f10a77bbSDavid C Somayajulu static int
qla_rdmwr(qla_host_t * ha,uint32_t raddr,uint32_t waddr,q8_rdmwr_hdr_t * hdr)1054f10a77bbSDavid C Somayajulu qla_rdmwr(qla_host_t *ha, uint32_t raddr, uint32_t waddr, q8_rdmwr_hdr_t *hdr)
1055f10a77bbSDavid C Somayajulu {
1056f10a77bbSDavid C Somayajulu 	uint32_t value;
1057f10a77bbSDavid C Somayajulu 
1058f10a77bbSDavid C Somayajulu 	if (hdr->index_a >= Q8_MAX_RESET_SEQ_IDX) {
1059f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "%s: [0x%08x] error\n", __func__,
1060f10a77bbSDavid C Somayajulu 			hdr->index_a);
1061f10a77bbSDavid C Somayajulu 		return -1;
1062f10a77bbSDavid C Somayajulu 	}
1063f10a77bbSDavid C Somayajulu 
1064f10a77bbSDavid C Somayajulu 	if (hdr->index_a) {
1065f10a77bbSDavid C Somayajulu 		value = ha->hw.rst_seq[hdr->index_a];
1066f10a77bbSDavid C Somayajulu 	} else {
1067f10a77bbSDavid C Somayajulu 		if (ql_rdwr_indreg32(ha, raddr, &value, 1)) {
1068f10a77bbSDavid C Somayajulu 			device_printf(ha->pci_dev, "%s: [0x%08x] error\n",
1069f10a77bbSDavid C Somayajulu 						__func__, raddr);
1070f10a77bbSDavid C Somayajulu 			return -1;
1071f10a77bbSDavid C Somayajulu 		}
1072f10a77bbSDavid C Somayajulu 	}
1073f10a77bbSDavid C Somayajulu 
1074f10a77bbSDavid C Somayajulu 	value &= hdr->and_value;
1075f10a77bbSDavid C Somayajulu 	value <<= hdr->shl;
1076f10a77bbSDavid C Somayajulu 	value >>= hdr->shr;
1077f10a77bbSDavid C Somayajulu 	value |= hdr->or_value;
1078f10a77bbSDavid C Somayajulu 	value ^= hdr->xor_value;
1079f10a77bbSDavid C Somayajulu 
1080f10a77bbSDavid C Somayajulu 	if (ql_rdwr_indreg32(ha, waddr, &value, 0)) {
1081f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "%s: [0x%08x] error\n", __func__,
1082f10a77bbSDavid C Somayajulu 			raddr);
1083f10a77bbSDavid C Somayajulu 		return -1;
1084f10a77bbSDavid C Somayajulu 	}
1085f10a77bbSDavid C Somayajulu 	return 0;
1086f10a77bbSDavid C Somayajulu }
1087f10a77bbSDavid C Somayajulu 
1088f10a77bbSDavid C Somayajulu static int
qla_read_modify_write_list(qla_host_t * ha,q8_ce_hdr_t * ce_hdr)1089f10a77bbSDavid C Somayajulu qla_read_modify_write_list(qla_host_t *ha, q8_ce_hdr_t *ce_hdr)
1090f10a77bbSDavid C Somayajulu {
1091f10a77bbSDavid C Somayajulu 	int		i;
1092f10a77bbSDavid C Somayajulu 	q8_rdmwr_hdr_t	*rdmwr_hdr;
1093f10a77bbSDavid C Somayajulu 	q8_rdmwr_e_t	*rdmwr_e;
1094f10a77bbSDavid C Somayajulu 
1095f10a77bbSDavid C Somayajulu 	rdmwr_hdr = (q8_rdmwr_hdr_t *)((uint8_t *)ce_hdr +
1096f10a77bbSDavid C Somayajulu 						sizeof (q8_ce_hdr_t));
1097f10a77bbSDavid C Somayajulu 	rdmwr_e = (q8_rdmwr_e_t *)((uint8_t *)rdmwr_hdr +
1098f10a77bbSDavid C Somayajulu 					sizeof(q8_rdmwr_hdr_t));
1099f10a77bbSDavid C Somayajulu 
1100f10a77bbSDavid C Somayajulu 	for (i = 0; i < ce_hdr->opcount; i++, rdmwr_e++) {
1101f10a77bbSDavid C Somayajulu 		if (qla_rdmwr(ha, rdmwr_e->rd_addr, rdmwr_e->wr_addr,
1102f10a77bbSDavid C Somayajulu 			rdmwr_hdr)) {
1103f10a77bbSDavid C Somayajulu 			return -1;
1104f10a77bbSDavid C Somayajulu 		}
1105f10a77bbSDavid C Somayajulu 		if (ce_hdr->delay_to) {
1106f10a77bbSDavid C Somayajulu 			DELAY(ce_hdr->delay_to);
1107f10a77bbSDavid C Somayajulu 		}
1108f10a77bbSDavid C Somayajulu 	}
1109f10a77bbSDavid C Somayajulu 	return 0;
1110f10a77bbSDavid C Somayajulu }
1111f10a77bbSDavid C Somayajulu 
1112f10a77bbSDavid C Somayajulu static int
qla_tmplt_execute(qla_host_t * ha,uint8_t * buf,int start_idx,int * end_idx,uint32_t nentries)1113f10a77bbSDavid C Somayajulu qla_tmplt_execute(qla_host_t *ha, uint8_t *buf, int start_idx, int *end_idx,
1114f10a77bbSDavid C Somayajulu 	uint32_t nentries)
1115f10a77bbSDavid C Somayajulu {
1116f10a77bbSDavid C Somayajulu 	int i, ret = 0, proc_end = 0;
1117f10a77bbSDavid C Somayajulu 	q8_ce_hdr_t	*ce_hdr;
1118f10a77bbSDavid C Somayajulu 
1119f10a77bbSDavid C Somayajulu 	for (i = start_idx; ((i < nentries) && (!proc_end)); i++) {
1120f10a77bbSDavid C Somayajulu 		ce_hdr = (q8_ce_hdr_t *)buf;
1121f10a77bbSDavid C Somayajulu 		ret = 0;
1122f10a77bbSDavid C Somayajulu 
1123f10a77bbSDavid C Somayajulu 		switch (ce_hdr->opcode) {
1124f10a77bbSDavid C Somayajulu 		case Q8_CE_OPCODE_NOP:
1125f10a77bbSDavid C Somayajulu 			break;
1126f10a77bbSDavid C Somayajulu 
1127f10a77bbSDavid C Somayajulu 		case Q8_CE_OPCODE_WRITE_LIST:
1128f10a77bbSDavid C Somayajulu 			ret = qla_wr_list(ha, ce_hdr);
1129f10a77bbSDavid C Somayajulu 			//printf("qla_wr_list %d\n", ret);
1130f10a77bbSDavid C Somayajulu 			break;
1131f10a77bbSDavid C Somayajulu 
1132f10a77bbSDavid C Somayajulu 		case Q8_CE_OPCODE_READ_WRITE_LIST:
1133f10a77bbSDavid C Somayajulu 			ret = qla_rd_wr_list(ha, ce_hdr);
1134f10a77bbSDavid C Somayajulu 			//printf("qla_rd_wr_list %d\n", ret);
1135f10a77bbSDavid C Somayajulu 			break;
1136f10a77bbSDavid C Somayajulu 
1137f10a77bbSDavid C Somayajulu 		case Q8_CE_OPCODE_POLL_LIST:
1138f10a77bbSDavid C Somayajulu 			ret = qla_poll_list(ha, ce_hdr);
1139f10a77bbSDavid C Somayajulu 			//printf("qla_poll_list %d\n", ret);
1140f10a77bbSDavid C Somayajulu 			break;
1141f10a77bbSDavid C Somayajulu 
1142f10a77bbSDavid C Somayajulu 		case Q8_CE_OPCODE_POLL_WRITE_LIST:
1143f10a77bbSDavid C Somayajulu 			ret = qla_poll_write_list(ha, ce_hdr);
1144f10a77bbSDavid C Somayajulu 			//printf("qla_poll_write_list %d\n", ret);
1145f10a77bbSDavid C Somayajulu 			break;
1146f10a77bbSDavid C Somayajulu 
1147f10a77bbSDavid C Somayajulu 		case Q8_CE_OPCODE_POLL_RD_LIST:
1148f10a77bbSDavid C Somayajulu 			ret = qla_poll_read_list(ha, ce_hdr);
1149f10a77bbSDavid C Somayajulu 			//printf("qla_poll_read_list %d\n", ret);
1150f10a77bbSDavid C Somayajulu 			break;
1151f10a77bbSDavid C Somayajulu 
1152f10a77bbSDavid C Somayajulu 		case Q8_CE_OPCODE_READ_MODIFY_WRITE:
1153f10a77bbSDavid C Somayajulu 			ret = qla_read_modify_write_list(ha, ce_hdr);
1154f10a77bbSDavid C Somayajulu 			//printf("qla_read_modify_write_list %d\n", ret);
1155f10a77bbSDavid C Somayajulu 			break;
1156f10a77bbSDavid C Somayajulu 
1157f10a77bbSDavid C Somayajulu 		case Q8_CE_OPCODE_SEQ_PAUSE:
1158f10a77bbSDavid C Somayajulu 			if (ce_hdr->delay_to) {
1159f10a77bbSDavid C Somayajulu 				qla_mdelay(__func__, ce_hdr->delay_to);
1160f10a77bbSDavid C Somayajulu 			}
1161f10a77bbSDavid C Somayajulu 			break;
1162f10a77bbSDavid C Somayajulu 
1163f10a77bbSDavid C Somayajulu 		case Q8_CE_OPCODE_SEQ_END:
1164f10a77bbSDavid C Somayajulu 			proc_end = 1;
1165f10a77bbSDavid C Somayajulu 			break;
1166f10a77bbSDavid C Somayajulu 
1167f10a77bbSDavid C Somayajulu 		case Q8_CE_OPCODE_TMPLT_END:
1168f10a77bbSDavid C Somayajulu 			*end_idx = i;
1169f10a77bbSDavid C Somayajulu 			return 0;
1170f10a77bbSDavid C Somayajulu 		}
1171f10a77bbSDavid C Somayajulu 
1172f10a77bbSDavid C Somayajulu 		if (ret)
1173f10a77bbSDavid C Somayajulu 			break;
1174f10a77bbSDavid C Somayajulu 
1175f10a77bbSDavid C Somayajulu 		buf += ce_hdr->size;
1176f10a77bbSDavid C Somayajulu 	}
1177f10a77bbSDavid C Somayajulu 	*end_idx = i;
1178f10a77bbSDavid C Somayajulu 
1179f10a77bbSDavid C Somayajulu 	return (ret);
1180f10a77bbSDavid C Somayajulu }
1181f10a77bbSDavid C Somayajulu 
118235291c22SDavid C Somayajulu #ifndef QL_LDFLASH_FW
118335291c22SDavid C Somayajulu static int
qla_load_offchip_mem(qla_host_t * ha,uint64_t addr,uint32_t * data32,uint32_t len32)118435291c22SDavid C Somayajulu qla_load_offchip_mem(qla_host_t *ha, uint64_t addr, uint32_t *data32,
118535291c22SDavid C Somayajulu         uint32_t len32)
118635291c22SDavid C Somayajulu {
118735291c22SDavid C Somayajulu         q80_offchip_mem_val_t val;
118835291c22SDavid C Somayajulu         int             ret = 0;
118935291c22SDavid C Somayajulu 
119035291c22SDavid C Somayajulu         while (len32) {
119135291c22SDavid C Somayajulu                 if (len32 > 4) {
119235291c22SDavid C Somayajulu                         val.data_lo = *data32++;
119335291c22SDavid C Somayajulu                         val.data_hi = *data32++;
119435291c22SDavid C Somayajulu                         val.data_ulo = *data32++;
119535291c22SDavid C Somayajulu                         val.data_uhi = *data32++;
119635291c22SDavid C Somayajulu                         len32 -= 4;
119735291c22SDavid C Somayajulu                         if (ql_rdwr_offchip_mem(ha, addr, &val, 0))
119835291c22SDavid C Somayajulu                                 return -1;
119935291c22SDavid C Somayajulu 
120035291c22SDavid C Somayajulu                         addr += (uint64_t)16;
120135291c22SDavid C Somayajulu                 } else {
120235291c22SDavid C Somayajulu                         break;
120335291c22SDavid C Somayajulu                 }
120435291c22SDavid C Somayajulu         }
120535291c22SDavid C Somayajulu 
120635291c22SDavid C Somayajulu         bzero(&val, sizeof(q80_offchip_mem_val_t));
120735291c22SDavid C Somayajulu 
120835291c22SDavid C Somayajulu         switch (len32) {
120935291c22SDavid C Somayajulu         case 3:
121035291c22SDavid C Somayajulu                 val.data_lo = *data32++;
121135291c22SDavid C Somayajulu                 val.data_hi = *data32++;
121235291c22SDavid C Somayajulu                 val.data_ulo = *data32++;
121335291c22SDavid C Somayajulu                  ret = ql_rdwr_offchip_mem(ha, addr, &val, 0);
121435291c22SDavid C Somayajulu                 break;
121535291c22SDavid C Somayajulu 
121635291c22SDavid C Somayajulu         case 2:
121735291c22SDavid C Somayajulu                 val.data_lo = *data32++;
121835291c22SDavid C Somayajulu                 val.data_hi = *data32++;
121935291c22SDavid C Somayajulu                  ret = ql_rdwr_offchip_mem(ha, addr, &val, 0);
122035291c22SDavid C Somayajulu                 break;
122135291c22SDavid C Somayajulu 
122235291c22SDavid C Somayajulu         case 1:
122335291c22SDavid C Somayajulu                 val.data_lo = *data32++;
122435291c22SDavid C Somayajulu                 ret = ql_rdwr_offchip_mem(ha, addr, &val, 0);
122535291c22SDavid C Somayajulu                 break;
122635291c22SDavid C Somayajulu 
122735291c22SDavid C Somayajulu         default:
122835291c22SDavid C Somayajulu                 break;
122935291c22SDavid C Somayajulu         }
123035291c22SDavid C Somayajulu         return ret;
123135291c22SDavid C Somayajulu }
123235291c22SDavid C Somayajulu 
123335291c22SDavid C Somayajulu static int
qla_load_bootldr(qla_host_t * ha)123435291c22SDavid C Somayajulu qla_load_bootldr(qla_host_t *ha)
123535291c22SDavid C Somayajulu {
123635291c22SDavid C Somayajulu         uint64_t        addr;
123735291c22SDavid C Somayajulu         uint32_t        *data32;
123835291c22SDavid C Somayajulu         uint32_t        len32;
123935291c22SDavid C Somayajulu         int             ret;
124035291c22SDavid C Somayajulu 
124135291c22SDavid C Somayajulu         addr = (uint64_t)(READ_REG32(ha, Q8_BOOTLD_ADDR));
124235291c22SDavid C Somayajulu         data32 = (uint32_t *)ql83xx_bootloader;
124335291c22SDavid C Somayajulu         len32 = ql83xx_bootloader_len >> 2;
124435291c22SDavid C Somayajulu 
124535291c22SDavid C Somayajulu         ret = qla_load_offchip_mem(ha, addr, data32, len32);
124635291c22SDavid C Somayajulu 
124735291c22SDavid C Somayajulu         return (ret);
124835291c22SDavid C Somayajulu }
124935291c22SDavid C Somayajulu 
125035291c22SDavid C Somayajulu static int
qla_load_fwimage(qla_host_t * ha)125135291c22SDavid C Somayajulu qla_load_fwimage(qla_host_t *ha)
125235291c22SDavid C Somayajulu {
125335291c22SDavid C Somayajulu         uint64_t        addr;
125435291c22SDavid C Somayajulu         uint32_t        *data32;
125535291c22SDavid C Somayajulu         uint32_t        len32;
125635291c22SDavid C Somayajulu         int             ret;
125735291c22SDavid C Somayajulu 
125835291c22SDavid C Somayajulu         addr = (uint64_t)(READ_REG32(ha, Q8_FW_IMAGE_ADDR));
125935291c22SDavid C Somayajulu         data32 = (uint32_t *)ql83xx_firmware;
126035291c22SDavid C Somayajulu         len32 = ql83xx_firmware_len >> 2;
126135291c22SDavid C Somayajulu 
126235291c22SDavid C Somayajulu         ret = qla_load_offchip_mem(ha, addr, data32, len32);
126335291c22SDavid C Somayajulu 
126435291c22SDavid C Somayajulu         return (ret);
126535291c22SDavid C Somayajulu }
126635291c22SDavid C Somayajulu #endif /* #ifndef QL_LDFLASH_FW */
1267f10a77bbSDavid C Somayajulu 
1268f10a77bbSDavid C Somayajulu static int
qla_ld_fw_init(qla_host_t * ha)1269f10a77bbSDavid C Somayajulu qla_ld_fw_init(qla_host_t *ha)
1270f10a77bbSDavid C Somayajulu {
1271f10a77bbSDavid C Somayajulu 	uint8_t *buf;
1272f10a77bbSDavid C Somayajulu 	uint32_t index = 0, end_idx;
1273f10a77bbSDavid C Somayajulu 	q8_tmplt_hdr_t *hdr;
1274f10a77bbSDavid C Somayajulu 
1275f10a77bbSDavid C Somayajulu 	bzero(ha->hw.rst_seq, sizeof (ha->hw.rst_seq));
1276f10a77bbSDavid C Somayajulu 
1277f10a77bbSDavid C Somayajulu 	hdr = (q8_tmplt_hdr_t *)ql83xx_resetseq;
1278f10a77bbSDavid C Somayajulu 
1279b65c0c07SDavid C Somayajulu 	device_printf(ha->pci_dev, "%s: reset sequence\n", __func__);
1280f10a77bbSDavid C Somayajulu 	if (qla_tmplt_16bit_checksum(ha, (uint16_t *)ql83xx_resetseq,
1281f10a77bbSDavid C Somayajulu 		(uint32_t)hdr->size)) {
1282f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "%s: reset seq checksum failed\n",
1283f10a77bbSDavid C Somayajulu 			__func__);
1284f10a77bbSDavid C Somayajulu 		return -1;
1285f10a77bbSDavid C Somayajulu 	}
1286f10a77bbSDavid C Somayajulu 
1287f10a77bbSDavid C Somayajulu 	buf = ql83xx_resetseq + hdr->stop_seq_off;
1288f10a77bbSDavid C Somayajulu 
1289b65c0c07SDavid C Somayajulu 	device_printf(ha->pci_dev, "%s: stop sequence\n", __func__);
1290f10a77bbSDavid C Somayajulu 	if (qla_tmplt_execute(ha, buf, index , &end_idx, hdr->nentries)) {
1291f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "%s: stop seq failed\n", __func__);
1292f10a77bbSDavid C Somayajulu 		return -1;
1293f10a77bbSDavid C Somayajulu 	}
1294f10a77bbSDavid C Somayajulu 
1295f10a77bbSDavid C Somayajulu 	index = end_idx;
1296f10a77bbSDavid C Somayajulu 
1297f10a77bbSDavid C Somayajulu 	buf = ql83xx_resetseq + hdr->init_seq_off;
1298f10a77bbSDavid C Somayajulu 
1299b65c0c07SDavid C Somayajulu 	device_printf(ha->pci_dev, "%s: init sequence\n", __func__);
1300f10a77bbSDavid C Somayajulu 	if (qla_tmplt_execute(ha, buf, index , &end_idx, hdr->nentries)) {
1301f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "%s: init seq failed\n", __func__);
1302f10a77bbSDavid C Somayajulu 		return -1;
1303f10a77bbSDavid C Somayajulu 	}
1304f10a77bbSDavid C Somayajulu 
130535291c22SDavid C Somayajulu #ifdef QL_LDFLASH_FW
1306f10a77bbSDavid C Somayajulu 	qla_load_fw_from_flash(ha);
1307f10a77bbSDavid C Somayajulu 	WRITE_REG32(ha, Q8_FW_IMAGE_VALID, 0);
130835291c22SDavid C Somayajulu #else
130935291c22SDavid C Somayajulu         if (qla_load_bootldr(ha))
131035291c22SDavid C Somayajulu                 return -1;
131135291c22SDavid C Somayajulu 
131235291c22SDavid C Somayajulu         if (qla_load_fwimage(ha))
131335291c22SDavid C Somayajulu                 return -1;
131435291c22SDavid C Somayajulu 
131535291c22SDavid C Somayajulu         WRITE_REG32(ha, Q8_FW_IMAGE_VALID, 0x12345678);
131635291c22SDavid C Somayajulu #endif /* #ifdef QL_LDFLASH_FW */
1317f10a77bbSDavid C Somayajulu 
1318f10a77bbSDavid C Somayajulu 	index = end_idx;
1319f10a77bbSDavid C Somayajulu 	buf = ql83xx_resetseq + hdr->start_seq_off;
1320f10a77bbSDavid C Somayajulu 
1321b65c0c07SDavid C Somayajulu 	device_printf(ha->pci_dev, "%s: start sequence\n", __func__);
1322f10a77bbSDavid C Somayajulu 	if (qla_tmplt_execute(ha, buf, index , &end_idx, hdr->nentries)) {
1323f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "%s: init seq failed\n", __func__);
1324f10a77bbSDavid C Somayajulu 		return -1;
1325f10a77bbSDavid C Somayajulu 	}
1326f10a77bbSDavid C Somayajulu 
1327f10a77bbSDavid C Somayajulu 	return 0;
1328f10a77bbSDavid C Somayajulu }
1329f10a77bbSDavid C Somayajulu 
1330f10a77bbSDavid C Somayajulu int
ql_stop_sequence(qla_host_t * ha)1331f10a77bbSDavid C Somayajulu ql_stop_sequence(qla_host_t *ha)
1332f10a77bbSDavid C Somayajulu {
1333f10a77bbSDavid C Somayajulu 	uint8_t *buf;
1334f10a77bbSDavid C Somayajulu 	uint32_t index = 0, end_idx;
1335f10a77bbSDavid C Somayajulu 	q8_tmplt_hdr_t *hdr;
1336f10a77bbSDavid C Somayajulu 
1337f10a77bbSDavid C Somayajulu 	bzero(ha->hw.rst_seq, sizeof (ha->hw.rst_seq));
1338f10a77bbSDavid C Somayajulu 
1339f10a77bbSDavid C Somayajulu 	hdr = (q8_tmplt_hdr_t *)ql83xx_resetseq;
1340f10a77bbSDavid C Somayajulu 
1341f10a77bbSDavid C Somayajulu 	if (qla_tmplt_16bit_checksum(ha, (uint16_t *)ql83xx_resetseq,
1342f10a77bbSDavid C Somayajulu 		(uint32_t)hdr->size)) {
1343f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "%s: reset seq checksum failed\n",
1344f10a77bbSDavid C Somayajulu 		__func__);
1345f10a77bbSDavid C Somayajulu 		return (-1);
1346f10a77bbSDavid C Somayajulu 	}
1347f10a77bbSDavid C Somayajulu 
1348f10a77bbSDavid C Somayajulu 	buf = ql83xx_resetseq + hdr->stop_seq_off;
1349f10a77bbSDavid C Somayajulu 
1350f10a77bbSDavid C Somayajulu 	device_printf(ha->pci_dev, "%s: stop sequence\n", __func__);
1351f10a77bbSDavid C Somayajulu 	if (qla_tmplt_execute(ha, buf, index , &end_idx, hdr->nentries)) {
1352f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "%s: stop seq failed\n", __func__);
1353f10a77bbSDavid C Somayajulu 		return (-1);
1354f10a77bbSDavid C Somayajulu 	}
1355f10a77bbSDavid C Somayajulu 
1356f10a77bbSDavid C Somayajulu 	return end_idx;
1357f10a77bbSDavid C Somayajulu }
1358f10a77bbSDavid C Somayajulu 
1359f10a77bbSDavid C Somayajulu int
ql_start_sequence(qla_host_t * ha,uint16_t index)1360f10a77bbSDavid C Somayajulu ql_start_sequence(qla_host_t *ha, uint16_t index)
1361f10a77bbSDavid C Somayajulu {
1362f10a77bbSDavid C Somayajulu 	uint8_t *buf;
1363f10a77bbSDavid C Somayajulu 	uint32_t end_idx;
1364f10a77bbSDavid C Somayajulu 	q8_tmplt_hdr_t *hdr;
1365f10a77bbSDavid C Somayajulu 
1366f10a77bbSDavid C Somayajulu 	bzero(ha->hw.rst_seq, sizeof (ha->hw.rst_seq));
1367f10a77bbSDavid C Somayajulu 
1368f10a77bbSDavid C Somayajulu 	hdr = (q8_tmplt_hdr_t *)ql83xx_resetseq;
1369f10a77bbSDavid C Somayajulu 
1370f10a77bbSDavid C Somayajulu 	if (qla_tmplt_16bit_checksum(ha, (uint16_t *)ql83xx_resetseq,
1371f10a77bbSDavid C Somayajulu 		(uint32_t)hdr->size)) {
1372f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "%s: reset seq checksum failed\n",
1373f10a77bbSDavid C Somayajulu 		__func__);
1374f10a77bbSDavid C Somayajulu 		return (-1);
1375f10a77bbSDavid C Somayajulu 	}
1376f10a77bbSDavid C Somayajulu 
1377f10a77bbSDavid C Somayajulu 	buf = ql83xx_resetseq + hdr->init_seq_off;
1378f10a77bbSDavid C Somayajulu 
1379f10a77bbSDavid C Somayajulu 	device_printf(ha->pci_dev, "%s: init sequence\n", __func__);
1380f10a77bbSDavid C Somayajulu 	if (qla_tmplt_execute(ha, buf, index , &end_idx, hdr->nentries)) {
1381f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "%s: init seq failed\n", __func__);
1382f10a77bbSDavid C Somayajulu 		return (-1);
1383f10a77bbSDavid C Somayajulu 	}
1384f10a77bbSDavid C Somayajulu 
138535291c22SDavid C Somayajulu #ifdef QL_LDFLASH_FW
1386f10a77bbSDavid C Somayajulu 	qla_load_fw_from_flash(ha);
1387f10a77bbSDavid C Somayajulu 	WRITE_REG32(ha, Q8_FW_IMAGE_VALID, 0);
138835291c22SDavid C Somayajulu #else
138935291c22SDavid C Somayajulu         if (qla_load_bootldr(ha))
139035291c22SDavid C Somayajulu                 return -1;
139135291c22SDavid C Somayajulu 
139235291c22SDavid C Somayajulu         if (qla_load_fwimage(ha))
139335291c22SDavid C Somayajulu                 return -1;
139435291c22SDavid C Somayajulu 
139535291c22SDavid C Somayajulu         WRITE_REG32(ha, Q8_FW_IMAGE_VALID, 0x12345678);
139635291c22SDavid C Somayajulu #endif /* #ifdef QL_LDFLASH_FW */
139735291c22SDavid C Somayajulu 
1398f10a77bbSDavid C Somayajulu 	index = end_idx;
1399f10a77bbSDavid C Somayajulu 	buf = ql83xx_resetseq + hdr->start_seq_off;
1400f10a77bbSDavid C Somayajulu 
1401f10a77bbSDavid C Somayajulu 	device_printf(ha->pci_dev, "%s: start sequence\n", __func__);
1402f10a77bbSDavid C Somayajulu 	if (qla_tmplt_execute(ha, buf, index , &end_idx, hdr->nentries)) {
1403f10a77bbSDavid C Somayajulu 		device_printf(ha->pci_dev, "%s: init seq failed\n", __func__);
1404f10a77bbSDavid C Somayajulu 		return -1;
1405f10a77bbSDavid C Somayajulu 	}
1406f10a77bbSDavid C Somayajulu 
1407f10a77bbSDavid C Somayajulu 	return (0);
1408f10a77bbSDavid C Somayajulu }
1409