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