xref: /freebsd/sys/dev/qlxgb/qla_misc.c (revision 0957b409)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2011-2013 Qlogic Corporation
5  * All rights reserved.
6  *
7  *  Redistribution and use in source and binary forms, with or without
8  *  modification, are permitted provided that the following conditions
9  *  are met:
10  *
11  *  1. Redistributions of source code must retain the above copyright
12  *     notice, this list of conditions and the following disclaimer.
13  *  2. Redistributions in binary form must reproduce the above copyright
14  *     notice, this list of conditions and the following disclaimer in the
15  *     documentation and/or other materials provided with the distribution.
16  *
17  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  *  POSSIBILITY OF SUCH DAMAGE.
28  */
29 /*
30  * File : qla_misc.c
31  * Author : David C Somayajulu, Qlogic Corporation, Aliso Viejo, CA 92656.
32  */
33 
34 #include <sys/cdefs.h>
35 __FBSDID("$FreeBSD$");
36 
37 #include "qla_os.h"
38 #include "qla_reg.h"
39 #include "qla_hw.h"
40 #include "qla_def.h"
41 #include "qla_reg.h"
42 #include "qla_inline.h"
43 #include "qla_glbl.h"
44 #include "qla_dbg.h"
45 
46 /*
47  * structure encapsulating the value to read/write to offchip memory
48  */
49 typedef struct _offchip_mem_val {
50         uint32_t data_lo;
51         uint32_t data_hi;
52         uint32_t data_ulo;
53         uint32_t data_uhi;
54 } offchip_mem_val_t;
55 
56 #define Q8_ADDR_UNDEFINED		0xFFFFFFFF
57 
58 /*
59  * The index to this table is Bits 20-27 of the indirect register address
60  */
61 static uint32_t indirect_to_base_map[] =
62 	{
63 		Q8_ADDR_UNDEFINED,	/* 0x00 */
64 		0x77300000,		/* 0x01 */
65 		0x29500000,		/* 0x02 */
66 		0x2A500000,		/* 0x03 */
67 		Q8_ADDR_UNDEFINED,	/* 0x04 */
68 		0x0D000000,		/* 0x05 */
69 		0x1B100000,		/* 0x06 */
70 		0x0E600000,		/* 0x07 */
71 		0x0E000000,		/* 0x08 */
72 		0x0E100000,		/* 0x09 */
73 		0x0E200000,		/* 0x0A */
74 		0x0E300000,		/* 0x0B */
75 		0x42000000,		/* 0x0C */
76 		0x41700000,		/* 0x0D */
77 		0x42100000,		/* 0x0E */
78 		0x34B00000,		/* 0x0F */
79 		0x40500000,		/* 0x10 */
80 		0x34000000,		/* 0x11 */
81 		0x34100000,		/* 0x12 */
82 		0x34200000,		/* 0x13 */
83 		0x34300000,		/* 0x14 */
84 		0x34500000,		/* 0x15 */
85 		0x34400000,		/* 0x16 */
86 		0x3C000000,		/* 0x17 */
87 		0x3C100000,		/* 0x18 */
88 		0x3C200000,		/* 0x19 */
89 		0x3C300000,		/* 0x1A */
90 		Q8_ADDR_UNDEFINED,	/* 0x1B */
91 		0x3C400000,		/* 0x1C */
92 		0x41000000,		/* 0x1D */
93 		Q8_ADDR_UNDEFINED,	/* 0x1E */
94 		0x0D100000,		/* 0x1F */
95 		Q8_ADDR_UNDEFINED,	/* 0x20 */
96 		0x77300000,		/* 0x21 */
97 		0x41600000,		/* 0x22 */
98 		Q8_ADDR_UNDEFINED,	/* 0x23 */
99 		Q8_ADDR_UNDEFINED,	/* 0x24 */
100 		Q8_ADDR_UNDEFINED,	/* 0x25 */
101 		Q8_ADDR_UNDEFINED,	/* 0x26 */
102 		Q8_ADDR_UNDEFINED,	/* 0x27 */
103 		0x41700000,		/* 0x28 */
104 		Q8_ADDR_UNDEFINED,	/* 0x29 */
105 		0x08900000,		/* 0x2A */
106 		0x70A00000,		/* 0x2B */
107 		0x70B00000,		/* 0x2C */
108 		0x70C00000,		/* 0x2D */
109 		0x08D00000,		/* 0x2E */
110 		0x08E00000,		/* 0x2F */
111 		0x70F00000,		/* 0x30 */
112 		0x40500000,		/* 0x31 */
113 		0x42000000,		/* 0x32 */
114 		0x42100000,		/* 0x33 */
115 		Q8_ADDR_UNDEFINED,	/* 0x34 */
116 		0x08800000,		/* 0x35 */
117 		0x09100000,		/* 0x36 */
118 		0x71200000,		/* 0x37 */
119 		0x40600000,		/* 0x38 */
120 		Q8_ADDR_UNDEFINED,	/* 0x39 */
121 		0x71800000,		/* 0x3A */
122 		0x19900000,		/* 0x3B */
123 		0x1A900000,		/* 0x3C */
124 		Q8_ADDR_UNDEFINED,	/* 0x3D */
125 		0x34600000,		/* 0x3E */
126 		Q8_ADDR_UNDEFINED,	/* 0x3F */
127 	};
128 
129 /*
130  * Address Translation Table for CRB to offsets from PCI BAR0
131  */
132 typedef struct _crb_to_pci {
133 	uint32_t crb_addr;
134 	uint32_t pci_addr;
135 } crb_to_pci_t;
136 
137 static crb_to_pci_t crbinit_to_pciaddr[] = {
138 	{(0x088 << 20), (0x035 << 20)},
139 	{(0x089 << 20), (0x02A << 20)},
140 	{(0x08D << 20), (0x02E << 20)},
141 	{(0x08E << 20), (0x02F << 20)},
142 	{(0x0C6 << 20), (0x023 << 20)},
143 	{(0x0C7 << 20), (0x024 << 20)},
144 	{(0x0C8 << 20), (0x025 << 20)},
145 	{(0x0D0 << 20), (0x005 << 20)},
146 	{(0x0D1 << 20), (0x01F << 20)},
147 	{(0x0E0 << 20), (0x008 << 20)},
148 	{(0x0E1 << 20), (0x009 << 20)},
149 	{(0x0E2 << 20), (0x00A << 20)},
150 	{(0x0E3 << 20), (0x00B << 20)},
151 	{(0x0E6 << 20), (0x007 << 20)},
152 	{(0x199 << 20), (0x03B << 20)},
153 	{(0x1B1 << 20), (0x006 << 20)},
154 	{(0x295 << 20), (0x002 << 20)},
155 	{(0x29A << 20), (0x000 << 20)},
156 	{(0x2A5 << 20), (0x003 << 20)},
157 	{(0x340 << 20), (0x011 << 20)},
158 	{(0x341 << 20), (0x012 << 20)},
159 	{(0x342 << 20), (0x013 << 20)},
160 	{(0x343 << 20), (0x014 << 20)},
161 	{(0x344 << 20), (0x016 << 20)},
162 	{(0x345 << 20), (0x015 << 20)},
163 	{(0x3C0 << 20), (0x017 << 20)},
164 	{(0x3C1 << 20), (0x018 << 20)},
165 	{(0x3C2 << 20), (0x019 << 20)},
166 	{(0x3C3 << 20), (0x01A << 20)},
167 	{(0x3C4 << 20), (0x01C << 20)},
168 	{(0x3C5 << 20), (0x01B << 20)},
169 	{(0x405 << 20), (0x031 << 20)},
170 	{(0x406 << 20), (0x038 << 20)},
171 	{(0x410 << 20), (0x01D << 20)},
172 	{(0x416 << 20), (0x022 << 20)},
173 	{(0x417 << 20), (0x028 << 20)},
174 	{(0x420 << 20), (0x032 << 20)},
175 	{(0x421 << 20), (0x033 << 20)},
176 	{(0x700 << 20), (0x00C << 20)},
177 	{(0x701 << 20), (0x00D << 20)},
178 	{(0x702 << 20), (0x00E << 20)},
179 	{(0x703 << 20), (0x00F << 20)},
180 	{(0x704 << 20), (0x010 << 20)},
181 	{(0x70A << 20), (0x02B << 20)},
182 	{(0x70B << 20), (0x02C << 20)},
183 	{(0x70C << 20), (0x02D << 20)},
184 	{(0x70F << 20), (0x030 << 20)},
185 	{(0x718 << 20), (0x03A << 20)},
186 	{(0x758 << 20), (0x026 << 20)},
187 	{(0x759 << 20), (0x027 << 20)},
188 	{(0x773 << 20), (0x001 << 20)}
189 };
190 
191 #define Q8_INVALID_ADDRESS	(-1)
192 #define Q8_ADDR_MASK		(0xFFF << 20)
193 
194 typedef struct _addr_val {
195 	uint32_t addr;
196 	uint32_t value;
197 	uint32_t pci_addr;
198 	uint32_t ind_addr;
199 } addr_val_t;
200 
201 /*
202  * Name: qla_rdwr_indreg32
203  * Function: Read/Write an Indirect Register
204  */
205 int
206 qla_rdwr_indreg32(qla_host_t *ha, uint32_t addr, uint32_t *val, uint32_t rd)
207 {
208 	uint32_t offset;
209 	int count = 100;
210 
211 	offset = (addr & 0xFFF00000) >> 20;
212 
213 	if (offset > 0x3F) {
214 		device_printf(ha->pci_dev, "%s: invalid addr 0x%08x\n",
215 			__func__, addr);
216 		return -1;
217 	}
218 
219 	offset = indirect_to_base_map[offset];
220 	if (offset == Q8_ADDR_UNDEFINED) {
221 		device_printf(ha->pci_dev, "%s: undefined map 0x%08x\n",
222 			__func__, addr);
223 		return -1;
224 	}
225 
226 	offset = offset | (addr & 0x000F0000);
227 
228 	if (qla_sem_lock(ha, Q8_SEM7_LOCK, 0, 0)) {
229 		device_printf(ha->pci_dev, "%s: SEM7_LOCK failed\n", __func__);
230 		return (-1);
231 	}
232 
233 	WRITE_OFFSET32(ha, Q8_CRB_WINDOW_2M, offset);
234 
235 	while (offset != (READ_OFFSET32(ha, Q8_CRB_WINDOW_2M))) {
236 		count--;
237 		if (!count) {
238 			qla_sem_unlock(ha, Q8_SEM7_UNLOCK);
239 			return -1;
240 		}
241 
242 		qla_mdelay(__func__, 1);
243 	}
244 
245 	if (rd) {
246 		*val = READ_OFFSET32(ha, ((addr & 0xFFFF) | 0x1E0000));
247 	} else {
248 		WRITE_OFFSET32(ha, ((addr & 0xFFFF) | 0x1E0000), *val);
249 	}
250 
251 	qla_sem_unlock(ha, Q8_SEM7_UNLOCK);
252 	return 0;
253 }
254 
255 /*
256  * Name: qla_rdwr_offchip_mem
257  * Function: Read/Write OffChip Memory
258  */
259 static int
260 qla_rdwr_offchip_mem(qla_host_t *ha, uint64_t addr, offchip_mem_val_t *val,
261 	uint32_t rd)
262 {
263 	uint32_t count = 100;
264 	uint32_t data;
265 
266 	WRITE_OFFSET32(ha, Q8_MIU_TEST_AGT_ADDR_LO, (uint32_t)addr);
267 	WRITE_OFFSET32(ha, Q8_MIU_TEST_AGT_ADDR_HI, (uint32_t)(addr >> 32));
268 
269 	if (!rd) {
270 		WRITE_OFFSET32(ha, Q8_MIU_TEST_AGT_WRDATA_LO, val->data_lo);
271 		WRITE_OFFSET32(ha, Q8_MIU_TEST_AGT_WRDATA_HI, val->data_hi);
272 		WRITE_OFFSET32(ha, Q8_MIU_TEST_AGT_WRDATA_ULO, val->data_ulo);
273 		WRITE_OFFSET32(ha, Q8_MIU_TEST_AGT_WRDATA_UHI, val->data_uhi);
274 		WRITE_OFFSET32(ha, Q8_MIU_TEST_AGT_CTRL, 0x07); /* Write */
275 	} else {
276 		WRITE_OFFSET32(ha, Q8_MIU_TEST_AGT_CTRL, 0x03); /* Read */
277 	}
278 
279 	while (count--) {
280 		data = READ_OFFSET32(ha, Q8_MIU_TEST_AGT_CTRL);
281 		if (!(data & BIT_3)) {
282 			if (rd) {
283 				val->data_lo = READ_OFFSET32(ha, \
284 						Q8_MIU_TEST_AGT_RDDATA_LO);
285 				val->data_hi = READ_OFFSET32(ha, \
286 						Q8_MIU_TEST_AGT_RDDATA_HI);
287 				val->data_ulo = READ_OFFSET32(ha, \
288 						Q8_MIU_TEST_AGT_RDDATA_ULO);
289 				val->data_uhi = READ_OFFSET32(ha, \
290 						Q8_MIU_TEST_AGT_RDDATA_UHI);
291 			}
292 			return 0;
293 		} else
294 			qla_mdelay(__func__, 1);
295 	}
296 
297 	device_printf(ha->pci_dev, "%s: failed[0x%08x]\n", __func__, data);
298 	return (-1);
299 }
300 
301 /*
302  * Name: qla_rd_flash32
303  * Function: Read Flash Memory
304  */
305 int
306 qla_rd_flash32(qla_host_t *ha, uint32_t addr, uint32_t *data)
307 {
308 	uint32_t val;
309 	uint32_t count = 100;
310 
311 	if (qla_sem_lock(ha, Q8_SEM2_LOCK, 0, 0)) {
312 		device_printf(ha->pci_dev, "%s: SEM2_LOCK failed\n", __func__);
313 		return (-1);
314 	}
315 	WRITE_OFFSET32(ha, Q8_ROM_LOCKID, 0xa5a5a5a5);
316 
317 	val = addr;
318 	qla_rdwr_indreg32(ha, Q8_ROM_ADDRESS, &val, 0);
319 	val = 0;
320 	qla_rdwr_indreg32(ha, Q8_ROM_DUMMY_BYTE_COUNT, &val, 0);
321 	val = 3;
322 	qla_rdwr_indreg32(ha, Q8_ROM_ADDR_BYTE_COUNT, &val, 0);
323 
324 	QLA_USEC_DELAY(100);
325 
326 	val = ROM_OPCODE_FAST_RD;
327 	qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0);
328 
329 	while (!((val = READ_OFFSET32(ha, Q8_ROM_STATUS)) & BIT_1)) {
330 		count--;
331 		if (!count) {
332 			qla_sem_unlock(ha, Q8_SEM7_UNLOCK);
333 			return -1;
334 		}
335 	}
336 
337 	val = 0;
338 	qla_rdwr_indreg32(ha, Q8_ROM_DUMMY_BYTE_COUNT, &val, 0);
339 	qla_rdwr_indreg32(ha, Q8_ROM_ADDR_BYTE_COUNT, &val, 0);
340 
341 	QLA_USEC_DELAY(100);
342 
343 	qla_rdwr_indreg32(ha, Q8_ROM_RD_DATA, data, 1);
344 
345 	qla_sem_unlock(ha, Q8_SEM2_UNLOCK);
346 	return 0;
347 }
348 
349 static int
350 qla_p3p_sem_lock2(qla_host_t *ha)
351 {
352         if (qla_sem_lock(ha, Q8_SEM2_LOCK, 0, 0)) {
353                 device_printf(ha->pci_dev, "%s: SEM2_LOCK failed\n", __func__);
354                 return (-1);
355         }
356         WRITE_OFFSET32(ha, Q8_ROM_LOCKID, 0xa5a5a5a5);
357         return (0);
358 }
359 
360 /*
361  * Name: qla_int_to_pci_addr_map
362  * Function: Convert's Internal(CRB) Address to Indirect Address
363  */
364 static uint32_t
365 qla_int_to_pci_addr_map(qla_host_t *ha, uint32_t int_addr)
366 {
367 	uint32_t crb_to_pci_table_size, i;
368 	uint32_t addr;
369 
370 	crb_to_pci_table_size = sizeof(crbinit_to_pciaddr)/sizeof(crb_to_pci_t);
371 	addr = int_addr & Q8_ADDR_MASK;
372 
373 	for (i = 0; i < crb_to_pci_table_size; i++) {
374 		if (crbinit_to_pciaddr[i].crb_addr == addr) {
375 			addr = (int_addr & ~Q8_ADDR_MASK) |
376 					crbinit_to_pciaddr[i].pci_addr;
377 			return (addr);
378 		}
379 	}
380 	return (Q8_INVALID_ADDRESS);
381 }
382 
383 /*
384  * Name: qla_filter_pci_addr
385  * Function: Filter's out Indirect Addresses which are not writeable
386  */
387 static uint32_t
388 qla_filter_pci_addr(qla_host_t *ha, uint32_t addr)
389 {
390 	if ((addr == Q8_INVALID_ADDRESS) ||
391 		(addr == 0x00112040) ||
392 		(addr == 0x00112048) ||
393 		((addr & 0xFFFF0FFF) == 0x001100C4) ||
394 		((addr & 0xFFFF0FFF) == 0x001100C8) ||
395 		((addr & 0x0FF00000) == 0x00200000) ||
396 		(addr == 0x022021FC) ||
397 		(addr == 0x0330001C) ||
398 		(addr == 0x03300024) ||
399 		(addr == 0x033000A8) ||
400 		(addr == 0x033000C8) ||
401 		(addr == 0x033000BC) ||
402 		((addr & 0x0FF00000) == 0x03A00000) ||
403 		(addr == 0x03B0001C))
404 		return (Q8_INVALID_ADDRESS);
405 	else
406 		return (addr);
407 }
408 
409 /*
410  * Name: qla_crb_init
411  * Function: CRB Initialization - first step in the initialization after reset
412  *	Essentially reads the address/value pairs from address = 0x00 and
413  *	writes the value into address in the addr/value pair.
414  */
415 static int
416 qla_crb_init(qla_host_t *ha)
417 {
418 	uint32_t val = 0, sig = 0;
419 	uint32_t offset, count, i;
420 	addr_val_t *addr_val_map, *avmap;
421 
422 	qla_rd_flash32(ha, 0, &sig);
423 	QL_DPRINT2((ha->pci_dev, "%s: val[0] = 0x%08x\n", __func__, sig));
424 
425 	qla_rd_flash32(ha, 4, &val);
426 	QL_DPRINT2((ha->pci_dev, "%s: val[4] = 0x%08x\n", __func__, val));
427 
428 	count = val >> 16;
429 	offset = val & 0xFFFF;
430 	offset = offset << 2;
431 
432 	QL_DPRINT2((ha->pci_dev, "%s: [sig,val]=[0x%08x, 0x%08x] %d pairs\n",
433 		__func__, sig, val, count));
434 
435 	addr_val_map = avmap = malloc((sizeof(addr_val_t) * count),
436 					M_QLA8XXXBUF, M_NOWAIT);
437 
438 	if (addr_val_map == NULL) {
439 		device_printf(ha->pci_dev, "%s: malloc failed\n", __func__);
440 		return (-1);
441 	}
442 	memset(avmap, 0, (sizeof(addr_val_t) * count));
443 
444 	count = count << 1;
445 	for (i = 0; i < count; ) {
446 		qla_rd_flash32(ha, (offset + (i * 4)), &avmap->value);
447 		i++;
448 		qla_rd_flash32(ha, (offset + (i * 4)), &avmap->addr);
449 		i++;
450 
451 		avmap->pci_addr = qla_int_to_pci_addr_map(ha, avmap->addr);
452 		avmap->ind_addr = qla_filter_pci_addr(ha, avmap->pci_addr);
453 
454 		QL_DPRINT2((ha->pci_dev,
455 			"%s: [0x%02x][0x%08x:0x%08x:0x%08x] 0x%08x\n",
456 			__func__, (i >> 1), avmap->addr, avmap->pci_addr,
457 			avmap->ind_addr, avmap->value));
458 
459 		if (avmap->ind_addr != Q8_INVALID_ADDRESS) {
460 			qla_rdwr_indreg32(ha, avmap->ind_addr, &avmap->value,0);
461 			qla_mdelay(__func__, 1);
462 		}
463 		avmap++;
464 	}
465 
466 	free (addr_val_map, M_QLA8XXXBUF);
467 	return (0);
468 }
469 
470 /*
471  * Name: qla_init_peg_regs
472  * Function: Protocol Engine Register Initialization
473  */
474 static void
475 qla_init_peg_regs(qla_host_t *ha)
476 {
477 	WRITE_OFFSET32(ha, Q8_PEG_D_RESET1, 0x001E);
478 	WRITE_OFFSET32(ha, Q8_PEG_D_RESET2, 0x0008);
479 	WRITE_OFFSET32(ha, Q8_PEG_I_RESET, 0x0008);
480 	WRITE_OFFSET32(ha, Q8_PEG_0_CLR1, 0x0000);
481 	WRITE_OFFSET32(ha, Q8_PEG_0_CLR2, 0x0000);
482 	WRITE_OFFSET32(ha, Q8_PEG_1_CLR1, 0x0000);
483 	WRITE_OFFSET32(ha, Q8_PEG_1_CLR2, 0x0000);
484 	WRITE_OFFSET32(ha, Q8_PEG_2_CLR1, 0x0000);
485 	WRITE_OFFSET32(ha, Q8_PEG_2_CLR2, 0x0000);
486 	WRITE_OFFSET32(ha, Q8_PEG_3_CLR1, 0x0000);
487 	WRITE_OFFSET32(ha, Q8_PEG_3_CLR2, 0x0000);
488 	WRITE_OFFSET32(ha, Q8_PEG_4_CLR1, 0x0000);
489 	WRITE_OFFSET32(ha, Q8_PEG_4_CLR2, 0x0000);
490 }
491 
492 /*
493  * Name: qla_load_fw_from_flash
494  * Function: Reads the Bootloader from Flash and Loads into Offchip Memory
495  */
496 static void
497 qla_load_fw_from_flash(qla_host_t *ha)
498 {
499 	uint64_t mem_off	= 0x10000;
500 	uint32_t flash_off	= 0x10000;
501 	uint32_t count;
502 	offchip_mem_val_t val;
503 
504 
505 	/* only bootloader needs to be loaded into memory */
506 	for (count = 0; count < 0x20000 ; ) {
507 		qla_rd_flash32(ha, flash_off, &val.data_lo);
508 		count = count + 4;
509 		flash_off = flash_off + 4;
510 
511 		qla_rd_flash32(ha, flash_off, &val.data_hi);
512 		count = count + 4;
513 		flash_off = flash_off + 4;
514 
515 		qla_rd_flash32(ha, flash_off, &val.data_ulo);
516 		count = count + 4;
517 		flash_off = flash_off + 4;
518 
519 		qla_rd_flash32(ha, flash_off, &val.data_uhi);
520 		count = count + 4;
521 		flash_off = flash_off + 4;
522 
523 		qla_rdwr_offchip_mem(ha, mem_off, &val, 0);
524 
525 		mem_off = mem_off + 16;
526 	}
527 	return;
528 }
529 
530 /*
531  * Name: qla_init_from_flash
532  * Function: Performs Initialization which consists of the following sequence
533  *	- reset
534  *	- CRB Init
535  *	- Peg Init
536  *	- Read the Bootloader from Flash and Load into Offchip Memory
537  *	- Kick start the bootloader which loads the rest of the firmware
538  *		and performs the remaining steps in the initialization process.
539  */
540 static int
541 qla_init_from_flash(qla_host_t *ha)
542 {
543 	uint32_t delay = 300;
544 	uint32_t data;
545 
546 	qla_hw_reset(ha);
547 	qla_mdelay(__func__, 100);
548 
549 	qla_crb_init(ha);
550 	qla_mdelay(__func__, 10);
551 
552 	qla_init_peg_regs(ha);
553 	qla_mdelay(__func__, 10);
554 
555 	qla_load_fw_from_flash(ha);
556 
557 	WRITE_OFFSET32(ha, Q8_CMDPEG_STATE, 0x00000000);
558 	WRITE_OFFSET32(ha, Q8_PEG_0_RESET, 0x00001020);
559 	WRITE_OFFSET32(ha, Q8_ASIC_RESET, 0x0080001E);
560 	qla_mdelay(__func__, 100);
561 
562 	do {
563 		data = READ_OFFSET32(ha, Q8_CMDPEG_STATE);
564 
565 		QL_DPRINT2((ha->pci_dev, "%s: func[%d] cmdpegstate 0x%08x\n",
566 				__func__, ha->pci_func, data));
567 		if (data == CMDPEG_PHAN_INIT_COMPLETE) {
568 			QL_DPRINT2((ha->pci_dev,
569 				"%s: func[%d] init complete\n",
570 				__func__, ha->pci_func));
571 			return(0);
572 		}
573 		qla_mdelay(__func__, 100);
574 	} while (delay--);
575 
576 	device_printf(ha->pci_dev,
577 		"%s: func[%d] Q8_PEG_HALT_STATUS1[0x%08x] STATUS2[0x%08x]"
578 		" HEARTBEAT[0x%08x] RCVPEG_STATE[0x%08x]"
579 		" CMDPEG_STATE[0x%08x]\n",
580 		__func__, ha->pci_func,
581 		(READ_OFFSET32(ha, Q8_PEG_HALT_STATUS1)),
582 		(READ_OFFSET32(ha, Q8_PEG_HALT_STATUS2)),
583 		(READ_OFFSET32(ha, Q8_FIRMWARE_HEARTBEAT)),
584 		(READ_OFFSET32(ha, Q8_RCVPEG_STATE)), data);
585 
586 	return (-1);
587 }
588 
589 /*
590  * Name: qla_init_hw
591  * Function: Initializes P3+ hardware.
592  */
593 int
594 qla_init_hw(qla_host_t *ha)
595 {
596         device_t dev;
597         int ret = 0;
598         uint32_t val, delay = 300;
599 
600         dev = ha->pci_dev;
601 
602         QL_DPRINT1((dev, "%s: enter\n", __func__));
603 
604 	qla_mdelay(__func__, 100);
605 
606 	if (ha->pci_func & 0x1) {
607         	while ((ha->pci_func & 0x1) && delay--) {
608 			val = READ_OFFSET32(ha, Q8_CMDPEG_STATE);
609 
610 			if (val == CMDPEG_PHAN_INIT_COMPLETE) {
611 				QL_DPRINT2((dev,
612 					"%s: func = %d init complete\n",
613 					__func__, ha->pci_func));
614 				qla_mdelay(__func__, 100);
615 				goto qla_init_exit;
616 			}
617 			qla_mdelay(__func__, 100);
618 		}
619 		return (-1);
620 	}
621 
622 	val = READ_OFFSET32(ha, Q8_CMDPEG_STATE);
623 
624 	if (val != CMDPEG_PHAN_INIT_COMPLETE) {
625         	ret = qla_init_from_flash(ha);
626 		qla_mdelay(__func__, 100);
627 	} else {
628         	ha->fw_ver_major = READ_OFFSET32(ha, Q8_FW_VER_MAJOR);
629         	ha->fw_ver_minor = READ_OFFSET32(ha, Q8_FW_VER_MINOR);
630 		ha->fw_ver_sub = READ_OFFSET32(ha, Q8_FW_VER_SUB);
631 
632 		if (qla_rd_flash32(ha, 0x100004, &val) == 0) {
633 
634 			if (((val & 0xFF) != ha->fw_ver_major) ||
635 				(((val >> 8) & 0xFF) != ha->fw_ver_minor) ||
636 				(((val >> 16) & 0xFF) != ha->fw_ver_sub)) {
637 
638         			ret = qla_init_from_flash(ha);
639 				qla_mdelay(__func__, 100);
640 			}
641 		}
642 	}
643 
644 qla_init_exit:
645         ha->fw_ver_major = READ_OFFSET32(ha, Q8_FW_VER_MAJOR);
646         ha->fw_ver_minor = READ_OFFSET32(ha, Q8_FW_VER_MINOR);
647         ha->fw_ver_sub = READ_OFFSET32(ha, Q8_FW_VER_SUB);
648         ha->fw_ver_build = READ_OFFSET32(ha, Q8_FW_VER_BUILD);
649 
650         return (ret);
651 }
652 
653 static int
654 qla_wait_for_flash_busy(qla_host_t *ha)
655 {
656 	uint32_t count = 100;
657 	uint32_t val;
658 
659 	QLA_USEC_DELAY(100);
660 
661 	while (count--) {
662 		val = READ_OFFSET32(ha, Q8_ROM_STATUS);
663 
664 		if (val & BIT_1)
665 			return 0;
666 		qla_mdelay(__func__, 1);
667 	}
668 	return -1;
669 }
670 
671 static int
672 qla_flash_write_enable(qla_host_t *ha)
673 {
674 	uint32_t val, rval;
675 
676 	val = 0;
677 	qla_rdwr_indreg32(ha, Q8_ROM_ADDR_BYTE_COUNT, &val, 0);
678 
679 	val = ROM_OPCODE_WR_ENABLE;
680 	qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0);
681 
682 	rval = qla_wait_for_flash_busy(ha);
683 
684 	if (rval)
685 		device_printf(ha->pci_dev, "%s: failed \n", __func__);
686 
687 	return (rval);
688 }
689 
690 static int
691 qla_flash_unprotect(qla_host_t *ha)
692 {
693 	uint32_t val, rval;
694 
695 	if (qla_flash_write_enable(ha) != 0)
696 		return(-1);
697 
698 	val = 0;
699 	qla_rdwr_indreg32(ha, Q8_ROM_WR_DATA, &val, 0);
700 
701 	val = ROM_OPCODE_WR_STATUS_REG;
702 	qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0);
703 
704 	rval = qla_wait_for_flash_busy(ha);
705 
706 	if (rval) {
707 		device_printf(ha->pci_dev, "%s: failed \n", __func__);
708 		return rval;
709 	}
710 
711 	if (qla_flash_write_enable(ha) != 0)
712 		return(-1);
713 
714 	val = 0;
715 	qla_rdwr_indreg32(ha, Q8_ROM_WR_DATA, &val, 0);
716 
717 	val = ROM_OPCODE_WR_STATUS_REG;
718 	qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0);
719 
720 	rval = qla_wait_for_flash_busy(ha);
721 
722 	if (rval)
723 		device_printf(ha->pci_dev, "%s: failed \n", __func__);
724 
725 	return rval;
726 }
727 
728 static int
729 qla_flash_protect(qla_host_t *ha)
730 {
731 	uint32_t val, rval;
732 
733 	if (qla_flash_write_enable(ha) != 0)
734 		return(-1);
735 
736 	val = 0x9C;
737 	qla_rdwr_indreg32(ha, Q8_ROM_WR_DATA, &val, 0);
738 
739 	val = ROM_OPCODE_WR_STATUS_REG;
740 	qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0);
741 
742 	rval = qla_wait_for_flash_busy(ha);
743 
744 	if (rval)
745 		device_printf(ha->pci_dev, "%s: failed \n", __func__);
746 
747 	return rval;
748 }
749 
750 static uint32_t
751 qla_flash_get_status(qla_host_t *ha)
752 {
753 	uint32_t count = 1000;
754 	uint32_t val, rval;
755 
756 	while (count--) {
757 		val = 0;
758 		qla_rdwr_indreg32(ha, Q8_ROM_ADDR_BYTE_COUNT, &val, 0);
759 
760 		val = ROM_OPCODE_RD_STATUS_REG;
761 		qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0);
762 
763 		rval = qla_wait_for_flash_busy(ha);
764 
765 		if (rval == 0) {
766 			qla_rdwr_indreg32(ha, Q8_ROM_RD_DATA, &val, 1);
767 
768 			if ((val & BIT_0) == 0)
769 				return (val);
770 		}
771 		qla_mdelay(__func__, 1);
772 	}
773 	return -1;
774 }
775 
776 static int
777 qla_wait_for_flash_unprotect(qla_host_t *ha)
778 {
779 	uint32_t delay = 1000;
780 
781 	while (delay--) {
782 
783 		if (qla_flash_get_status(ha) == 0)
784 			return 0;
785 
786 		qla_mdelay(__func__, 1);
787 	}
788 
789 	return -1;
790 }
791 
792 static int
793 qla_wait_for_flash_protect(qla_host_t *ha)
794 {
795 	uint32_t delay = 1000;
796 
797 	while (delay--) {
798 
799 		if (qla_flash_get_status(ha) == 0x9C)
800 			return 0;
801 
802 		qla_mdelay(__func__, 1);
803 	}
804 
805 	return -1;
806 }
807 
808 static int
809 qla_erase_flash_sector(qla_host_t *ha, uint32_t start)
810 {
811 	uint32_t val;
812 	int rval;
813 
814 	if (qla_flash_write_enable(ha) != 0)
815 		return(-1);
816 
817         val = start;
818         qla_rdwr_indreg32(ha, Q8_ROM_ADDRESS, &val, 0);
819 
820         val = 3;
821         qla_rdwr_indreg32(ha, Q8_ROM_ADDR_BYTE_COUNT, &val, 0);
822 
823         val = ROM_OPCODE_SECTOR_ERASE;
824         qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0);
825 
826 	rval = qla_wait_for_flash_busy(ha);
827 
828 	if (rval)
829 		device_printf(ha->pci_dev, "%s: failed \n", __func__);
830 	return rval;
831 }
832 
833 #define Q8_FLASH_SECTOR_SIZE 0x10000
834 int
835 qla_erase_flash(qla_host_t *ha, uint32_t off, uint32_t size)
836 {
837 	int rval = 0;
838 	uint32_t start;
839 
840 	if (off & (Q8_FLASH_SECTOR_SIZE -1))
841 		return -1;
842 
843 	if ((rval = qla_p3p_sem_lock2(ha)))
844 		goto qla_erase_flash_exit;
845 
846 	if ((rval = qla_flash_unprotect(ha)))
847 		goto qla_erase_flash_unlock_exit;
848 
849 	if ((rval = qla_wait_for_flash_unprotect(ha)))
850 		goto qla_erase_flash_unlock_exit;
851 
852 	for (start = off; start < (off + size); start = start + 0x10000) {
853 		if (qla_erase_flash_sector(ha, start)) {
854 			rval = -1;
855 			break;
856 		}
857 	}
858 
859 	rval = qla_flash_protect(ha);
860 
861 qla_erase_flash_unlock_exit:
862 	qla_sem_unlock(ha, Q8_SEM2_UNLOCK);
863 
864 qla_erase_flash_exit:
865 	return (rval);
866 }
867 
868 static int
869 qla_flash_write32(qla_host_t *ha, uint32_t off, uint32_t data)
870 {
871 	uint32_t val;
872 	int rval = 0;
873 
874         val = data;
875         qla_rdwr_indreg32(ha, Q8_ROM_WR_DATA, &val, 0);
876 
877         val = off;
878         qla_rdwr_indreg32(ha, Q8_ROM_ADDRESS, &val, 0);
879 
880         val = 3;
881         qla_rdwr_indreg32(ha, Q8_ROM_ADDR_BYTE_COUNT, &val, 0);
882 
883         val = ROM_OPCODE_PROG_PAGE;
884         qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0);
885 
886 	rval = qla_wait_for_flash_busy(ha);
887 
888 	if (rval)
889 		device_printf(ha->pci_dev, "%s: failed \n", __func__);
890 
891 	return rval;
892 }
893 
894 static int
895 qla_flash_wait_for_write_complete(qla_host_t *ha)
896 {
897 	uint32_t val, count = 1000;
898 	int rval = 0;
899 
900 	while (count--) {
901 
902 		val = 0;
903 		qla_rdwr_indreg32(ha, Q8_ROM_ADDR_BYTE_COUNT, &val, 0);
904 
905 		val = ROM_OPCODE_RD_STATUS_REG;
906 		qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0);
907 
908 
909 		rval = qla_wait_for_flash_busy(ha);
910 
911 		if (rval == 0) {
912 			qla_rdwr_indreg32(ha, Q8_ROM_RD_DATA, &val, 1);
913 
914 			if ((val & BIT_0) == 0)
915 				return (0);
916 		}
917 		qla_mdelay(__func__, 1);
918 	}
919 	return -1;
920 }
921 
922 static int
923 qla_flash_write(qla_host_t *ha, uint32_t off, uint32_t data)
924 {
925 	if (qla_flash_write_enable(ha) != 0)
926 		return(-1);
927 
928 	if (qla_flash_write32(ha, off, data) != 0)
929 		return -1;
930 
931 	if (qla_flash_wait_for_write_complete(ha))
932 		return -1;
933 
934 	return 0;
935 }
936 
937 
938 static int
939 qla_flash_write_pattern(qla_host_t *ha, uint32_t off, uint32_t size,
940 	uint32_t pattern)
941 {
942 	int rval = 0;
943 	uint32_t start;
944 
945 
946 	if ((rval = qla_p3p_sem_lock2(ha)))
947 		goto qla_wr_pattern_exit;
948 
949 	if ((rval = qla_flash_unprotect(ha)))
950 		goto qla_wr_pattern_unlock_exit;
951 
952 	if ((rval = qla_wait_for_flash_unprotect(ha)))
953 		goto qla_wr_pattern_unlock_exit;
954 
955 	for (start = off; start < (off + size); start = start + 4) {
956 		if (qla_flash_write(ha, start, pattern)) {
957 			rval = -1;
958 			break;
959 		}
960 	}
961 
962 	rval = qla_flash_protect(ha);
963 
964 	if (rval == 0)
965 		rval = qla_wait_for_flash_protect(ha);
966 
967 qla_wr_pattern_unlock_exit:
968 	qla_sem_unlock(ha, Q8_SEM2_UNLOCK);
969 
970 qla_wr_pattern_exit:
971 	return (rval);
972 }
973 
974 static int
975 qla_flash_write_data(qla_host_t *ha, uint32_t off, uint32_t size,
976 	void *data)
977 {
978 	int rval = 0;
979 	uint32_t start;
980 	uint32_t *data32 = data;
981 
982 
983 	if ((rval = qla_p3p_sem_lock2(ha)))
984 		goto qla_wr_pattern_exit;
985 
986 	if ((rval = qla_flash_unprotect(ha)))
987 		goto qla_wr_pattern_unlock_exit;
988 
989 	if ((rval = qla_wait_for_flash_unprotect(ha)))
990 		goto qla_wr_pattern_unlock_exit;
991 
992 	for (start = off; start < (off + size); start = start + 4) {
993 
994 		if (*data32 != 0xFFFFFFFF) {
995 			if (qla_flash_write(ha, start, *data32)) {
996 				rval = -1;
997 				break;
998 			}
999 		}
1000 		data32++;
1001 	}
1002 
1003 	rval = qla_flash_protect(ha);
1004 
1005 	if (rval == 0)
1006 		rval = qla_wait_for_flash_protect(ha);
1007 
1008 qla_wr_pattern_unlock_exit:
1009 	qla_sem_unlock(ha, Q8_SEM2_UNLOCK);
1010 
1011 qla_wr_pattern_exit:
1012 	return (rval);
1013 }
1014 
1015 int
1016 qla_wr_flash_buffer(qla_host_t *ha, uint32_t off, uint32_t size, void *buf,
1017 	uint32_t pattern)
1018 {
1019 	int rval = 0;
1020 	void *data;
1021 
1022 
1023 	if (size == 0)
1024 		return 0;
1025 
1026 	size = size << 2;
1027 
1028 	if (buf == NULL) {
1029 		rval = qla_flash_write_pattern(ha, off, size, pattern);
1030 		return (rval);
1031 	}
1032 
1033 	if ((data = malloc(size, M_QLA8XXXBUF, M_NOWAIT)) == NULL) {
1034 		device_printf(ha->pci_dev, "%s: malloc failed \n", __func__);
1035 		rval = -1;
1036 		goto qla_wr_flash_buffer_exit;
1037 	}
1038 
1039 	if ((rval = copyin(buf, data, size))) {
1040 		device_printf(ha->pci_dev, "%s copyin failed\n", __func__);
1041 		goto qla_wr_flash_buffer_free_exit;
1042 	}
1043 
1044 	rval = qla_flash_write_data(ha, off, size, data);
1045 
1046 qla_wr_flash_buffer_free_exit:
1047 	free(data, M_QLA8XXXBUF);
1048 
1049 qla_wr_flash_buffer_exit:
1050 	return (rval);
1051 }
1052 
1053