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 */
49typedef 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 */
61static 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 */
132typedef struct _crb_to_pci {
133	uint32_t crb_addr;
134	uint32_t pci_addr;
135} crb_to_pci_t;
136
137static 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
194typedef 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 */
205int
206qla_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 */
259static int
260qla_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 */
305int
306qla_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
349static int
350qla_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 */
364static uint32_t
365qla_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 */
387static uint32_t
388qla_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 */
415static int
416qla_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 */
474static void
475qla_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 */
496static void
497qla_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	/* only bootloader needs to be loaded into memory */
505	for (count = 0; count < 0x20000 ; ) {
506		qla_rd_flash32(ha, flash_off, &val.data_lo);
507		count = count + 4;
508		flash_off = flash_off + 4;
509
510		qla_rd_flash32(ha, flash_off, &val.data_hi);
511		count = count + 4;
512		flash_off = flash_off + 4;
513
514		qla_rd_flash32(ha, flash_off, &val.data_ulo);
515		count = count + 4;
516		flash_off = flash_off + 4;
517
518		qla_rd_flash32(ha, flash_off, &val.data_uhi);
519		count = count + 4;
520		flash_off = flash_off + 4;
521
522		qla_rdwr_offchip_mem(ha, mem_off, &val, 0);
523
524		mem_off = mem_off + 16;
525	}
526	return;
527}
528
529/*
530 * Name: qla_init_from_flash
531 * Function: Performs Initialization which consists of the following sequence
532 *	- reset
533 *	- CRB Init
534 *	- Peg Init
535 *	- Read the Bootloader from Flash and Load into Offchip Memory
536 *	- Kick start the bootloader which loads the rest of the firmware
537 *		and performs the remaining steps in the initialization process.
538 */
539static int
540qla_init_from_flash(qla_host_t *ha)
541{
542	uint32_t delay = 300;
543	uint32_t data;
544
545	qla_hw_reset(ha);
546	qla_mdelay(__func__, 100);
547
548	qla_crb_init(ha);
549	qla_mdelay(__func__, 10);
550
551	qla_init_peg_regs(ha);
552	qla_mdelay(__func__, 10);
553
554	qla_load_fw_from_flash(ha);
555
556	WRITE_OFFSET32(ha, Q8_CMDPEG_STATE, 0x00000000);
557	WRITE_OFFSET32(ha, Q8_PEG_0_RESET, 0x00001020);
558	WRITE_OFFSET32(ha, Q8_ASIC_RESET, 0x0080001E);
559	qla_mdelay(__func__, 100);
560
561	do {
562		data = READ_OFFSET32(ha, Q8_CMDPEG_STATE);
563
564		QL_DPRINT2((ha->pci_dev, "%s: func[%d] cmdpegstate 0x%08x\n",
565				__func__, ha->pci_func, data));
566		if (data == CMDPEG_PHAN_INIT_COMPLETE) {
567			QL_DPRINT2((ha->pci_dev,
568				"%s: func[%d] init complete\n",
569				__func__, ha->pci_func));
570			return(0);
571		}
572		qla_mdelay(__func__, 100);
573	} while (delay--);
574
575	device_printf(ha->pci_dev,
576		"%s: func[%d] Q8_PEG_HALT_STATUS1[0x%08x] STATUS2[0x%08x]"
577		" HEARTBEAT[0x%08x] RCVPEG_STATE[0x%08x]"
578		" CMDPEG_STATE[0x%08x]\n",
579		__func__, ha->pci_func,
580		(READ_OFFSET32(ha, Q8_PEG_HALT_STATUS1)),
581		(READ_OFFSET32(ha, Q8_PEG_HALT_STATUS2)),
582		(READ_OFFSET32(ha, Q8_FIRMWARE_HEARTBEAT)),
583		(READ_OFFSET32(ha, Q8_RCVPEG_STATE)), data);
584
585	return (-1);
586}
587
588/*
589 * Name: qla_init_hw
590 * Function: Initializes P3+ hardware.
591 */
592int
593qla_init_hw(qla_host_t *ha)
594{
595        device_t dev;
596        int ret = 0;
597        uint32_t val, delay = 300;
598
599        dev = ha->pci_dev;
600
601        QL_DPRINT1((dev, "%s: enter\n", __func__));
602
603	qla_mdelay(__func__, 100);
604
605	if (ha->pci_func & 0x1) {
606        	while ((ha->pci_func & 0x1) && delay--) {
607			val = READ_OFFSET32(ha, Q8_CMDPEG_STATE);
608
609			if (val == CMDPEG_PHAN_INIT_COMPLETE) {
610				QL_DPRINT2((dev,
611					"%s: func = %d init complete\n",
612					__func__, ha->pci_func));
613				qla_mdelay(__func__, 100);
614				goto qla_init_exit;
615			}
616			qla_mdelay(__func__, 100);
617		}
618		return (-1);
619	}
620
621	val = READ_OFFSET32(ha, Q8_CMDPEG_STATE);
622
623	if (val != CMDPEG_PHAN_INIT_COMPLETE) {
624        	ret = qla_init_from_flash(ha);
625		qla_mdelay(__func__, 100);
626	} else {
627        	ha->fw_ver_major = READ_OFFSET32(ha, Q8_FW_VER_MAJOR);
628        	ha->fw_ver_minor = READ_OFFSET32(ha, Q8_FW_VER_MINOR);
629		ha->fw_ver_sub = READ_OFFSET32(ha, Q8_FW_VER_SUB);
630
631		if (qla_rd_flash32(ha, 0x100004, &val) == 0) {
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        			ret = qla_init_from_flash(ha);
636				qla_mdelay(__func__, 100);
637			}
638		}
639	}
640
641qla_init_exit:
642        ha->fw_ver_major = READ_OFFSET32(ha, Q8_FW_VER_MAJOR);
643        ha->fw_ver_minor = READ_OFFSET32(ha, Q8_FW_VER_MINOR);
644        ha->fw_ver_sub = READ_OFFSET32(ha, Q8_FW_VER_SUB);
645        ha->fw_ver_build = READ_OFFSET32(ha, Q8_FW_VER_BUILD);
646
647        return (ret);
648}
649
650static int
651qla_wait_for_flash_busy(qla_host_t *ha)
652{
653	uint32_t count = 100;
654	uint32_t val;
655
656	QLA_USEC_DELAY(100);
657
658	while (count--) {
659		val = READ_OFFSET32(ha, Q8_ROM_STATUS);
660
661		if (val & BIT_1)
662			return 0;
663		qla_mdelay(__func__, 1);
664	}
665	return -1;
666}
667
668static int
669qla_flash_write_enable(qla_host_t *ha)
670{
671	uint32_t val, rval;
672
673	val = 0;
674	qla_rdwr_indreg32(ha, Q8_ROM_ADDR_BYTE_COUNT, &val, 0);
675
676	val = ROM_OPCODE_WR_ENABLE;
677	qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0);
678
679	rval = qla_wait_for_flash_busy(ha);
680
681	if (rval)
682		device_printf(ha->pci_dev, "%s: failed \n", __func__);
683
684	return (rval);
685}
686
687static int
688qla_flash_unprotect(qla_host_t *ha)
689{
690	uint32_t val, rval;
691
692	if (qla_flash_write_enable(ha) != 0)
693		return(-1);
694
695	val = 0;
696	qla_rdwr_indreg32(ha, Q8_ROM_WR_DATA, &val, 0);
697
698	val = ROM_OPCODE_WR_STATUS_REG;
699	qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0);
700
701	rval = qla_wait_for_flash_busy(ha);
702
703	if (rval) {
704		device_printf(ha->pci_dev, "%s: failed \n", __func__);
705		return rval;
706	}
707
708	if (qla_flash_write_enable(ha) != 0)
709		return(-1);
710
711	val = 0;
712	qla_rdwr_indreg32(ha, Q8_ROM_WR_DATA, &val, 0);
713
714	val = ROM_OPCODE_WR_STATUS_REG;
715	qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0);
716
717	rval = qla_wait_for_flash_busy(ha);
718
719	if (rval)
720		device_printf(ha->pci_dev, "%s: failed \n", __func__);
721
722	return rval;
723}
724
725static int
726qla_flash_protect(qla_host_t *ha)
727{
728	uint32_t val, rval;
729
730	if (qla_flash_write_enable(ha) != 0)
731		return(-1);
732
733	val = 0x9C;
734	qla_rdwr_indreg32(ha, Q8_ROM_WR_DATA, &val, 0);
735
736	val = ROM_OPCODE_WR_STATUS_REG;
737	qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0);
738
739	rval = qla_wait_for_flash_busy(ha);
740
741	if (rval)
742		device_printf(ha->pci_dev, "%s: failed \n", __func__);
743
744	return rval;
745}
746
747static uint32_t
748qla_flash_get_status(qla_host_t *ha)
749{
750	uint32_t count = 1000;
751	uint32_t val, rval;
752
753	while (count--) {
754		val = 0;
755		qla_rdwr_indreg32(ha, Q8_ROM_ADDR_BYTE_COUNT, &val, 0);
756
757		val = ROM_OPCODE_RD_STATUS_REG;
758		qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0);
759
760		rval = qla_wait_for_flash_busy(ha);
761
762		if (rval == 0) {
763			qla_rdwr_indreg32(ha, Q8_ROM_RD_DATA, &val, 1);
764
765			if ((val & BIT_0) == 0)
766				return (val);
767		}
768		qla_mdelay(__func__, 1);
769	}
770	return -1;
771}
772
773static int
774qla_wait_for_flash_unprotect(qla_host_t *ha)
775{
776	uint32_t delay = 1000;
777
778	while (delay--) {
779		if (qla_flash_get_status(ha) == 0)
780			return 0;
781
782		qla_mdelay(__func__, 1);
783	}
784
785	return -1;
786}
787
788static int
789qla_wait_for_flash_protect(qla_host_t *ha)
790{
791	uint32_t delay = 1000;
792
793	while (delay--) {
794		if (qla_flash_get_status(ha) == 0x9C)
795			return 0;
796
797		qla_mdelay(__func__, 1);
798	}
799
800	return -1;
801}
802
803static int
804qla_erase_flash_sector(qla_host_t *ha, uint32_t start)
805{
806	uint32_t val;
807	int rval;
808
809	if (qla_flash_write_enable(ha) != 0)
810		return(-1);
811
812        val = start;
813        qla_rdwr_indreg32(ha, Q8_ROM_ADDRESS, &val, 0);
814
815        val = 3;
816        qla_rdwr_indreg32(ha, Q8_ROM_ADDR_BYTE_COUNT, &val, 0);
817
818        val = ROM_OPCODE_SECTOR_ERASE;
819        qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0);
820
821	rval = qla_wait_for_flash_busy(ha);
822
823	if (rval)
824		device_printf(ha->pci_dev, "%s: failed \n", __func__);
825	return rval;
826}
827
828#define Q8_FLASH_SECTOR_SIZE 0x10000
829int
830qla_erase_flash(qla_host_t *ha, uint32_t off, uint32_t size)
831{
832	int rval = 0;
833	uint32_t start;
834
835	if (off & (Q8_FLASH_SECTOR_SIZE -1))
836		return -1;
837
838	if ((rval = qla_p3p_sem_lock2(ha)))
839		goto qla_erase_flash_exit;
840
841	if ((rval = qla_flash_unprotect(ha)))
842		goto qla_erase_flash_unlock_exit;
843
844	if ((rval = qla_wait_for_flash_unprotect(ha)))
845		goto qla_erase_flash_unlock_exit;
846
847	for (start = off; start < (off + size); start = start + 0x10000) {
848		if (qla_erase_flash_sector(ha, start)) {
849			rval = -1;
850			break;
851		}
852	}
853
854	rval = qla_flash_protect(ha);
855
856qla_erase_flash_unlock_exit:
857	qla_sem_unlock(ha, Q8_SEM2_UNLOCK);
858
859qla_erase_flash_exit:
860	return (rval);
861}
862
863static int
864qla_flash_write32(qla_host_t *ha, uint32_t off, uint32_t data)
865{
866	uint32_t val;
867	int rval = 0;
868
869        val = data;
870        qla_rdwr_indreg32(ha, Q8_ROM_WR_DATA, &val, 0);
871
872        val = off;
873        qla_rdwr_indreg32(ha, Q8_ROM_ADDRESS, &val, 0);
874
875        val = 3;
876        qla_rdwr_indreg32(ha, Q8_ROM_ADDR_BYTE_COUNT, &val, 0);
877
878        val = ROM_OPCODE_PROG_PAGE;
879        qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0);
880
881	rval = qla_wait_for_flash_busy(ha);
882
883	if (rval)
884		device_printf(ha->pci_dev, "%s: failed \n", __func__);
885
886	return rval;
887}
888
889static int
890qla_flash_wait_for_write_complete(qla_host_t *ha)
891{
892	uint32_t val, count = 1000;
893	int rval = 0;
894
895	while (count--) {
896		val = 0;
897		qla_rdwr_indreg32(ha, Q8_ROM_ADDR_BYTE_COUNT, &val, 0);
898
899		val = ROM_OPCODE_RD_STATUS_REG;
900		qla_rdwr_indreg32(ha, Q8_ROM_INSTR_OPCODE, &val, 0);
901
902
903		rval = qla_wait_for_flash_busy(ha);
904
905		if (rval == 0) {
906			qla_rdwr_indreg32(ha, Q8_ROM_RD_DATA, &val, 1);
907
908			if ((val & BIT_0) == 0)
909				return (0);
910		}
911		qla_mdelay(__func__, 1);
912	}
913	return -1;
914}
915
916static int
917qla_flash_write(qla_host_t *ha, uint32_t off, uint32_t data)
918{
919	if (qla_flash_write_enable(ha) != 0)
920		return(-1);
921
922	if (qla_flash_write32(ha, off, data) != 0)
923		return -1;
924
925	if (qla_flash_wait_for_write_complete(ha))
926		return -1;
927
928	return 0;
929}
930
931static int
932qla_flash_write_pattern(qla_host_t *ha, uint32_t off, uint32_t size,
933	uint32_t pattern)
934{
935	int rval = 0;
936	uint32_t start;
937
938	if ((rval = qla_p3p_sem_lock2(ha)))
939		goto qla_wr_pattern_exit;
940
941	if ((rval = qla_flash_unprotect(ha)))
942		goto qla_wr_pattern_unlock_exit;
943
944	if ((rval = qla_wait_for_flash_unprotect(ha)))
945		goto qla_wr_pattern_unlock_exit;
946
947	for (start = off; start < (off + size); start = start + 4) {
948		if (qla_flash_write(ha, start, pattern)) {
949			rval = -1;
950			break;
951		}
952	}
953
954	rval = qla_flash_protect(ha);
955
956	if (rval == 0)
957		rval = qla_wait_for_flash_protect(ha);
958
959qla_wr_pattern_unlock_exit:
960	qla_sem_unlock(ha, Q8_SEM2_UNLOCK);
961
962qla_wr_pattern_exit:
963	return (rval);
964}
965
966static int
967qla_flash_write_data(qla_host_t *ha, uint32_t off, uint32_t size,
968	void *data)
969{
970	int rval = 0;
971	uint32_t start;
972	uint32_t *data32 = data;
973
974	if ((rval = qla_p3p_sem_lock2(ha)))
975		goto qla_wr_pattern_exit;
976
977	if ((rval = qla_flash_unprotect(ha)))
978		goto qla_wr_pattern_unlock_exit;
979
980	if ((rval = qla_wait_for_flash_unprotect(ha)))
981		goto qla_wr_pattern_unlock_exit;
982
983	for (start = off; start < (off + size); start = start + 4) {
984
985		if (*data32 != 0xFFFFFFFF) {
986			if (qla_flash_write(ha, start, *data32)) {
987				rval = -1;
988				break;
989			}
990		}
991		data32++;
992	}
993
994	rval = qla_flash_protect(ha);
995
996	if (rval == 0)
997		rval = qla_wait_for_flash_protect(ha);
998
999qla_wr_pattern_unlock_exit:
1000	qla_sem_unlock(ha, Q8_SEM2_UNLOCK);
1001
1002qla_wr_pattern_exit:
1003	return (rval);
1004}
1005
1006int
1007qla_wr_flash_buffer(qla_host_t *ha, uint32_t off, uint32_t size, void *buf,
1008	uint32_t pattern)
1009{
1010	int rval = 0;
1011	void *data;
1012
1013	if (size == 0)
1014		return 0;
1015
1016	size = size << 2;
1017
1018	if (buf == NULL) {
1019		rval = qla_flash_write_pattern(ha, off, size, pattern);
1020		return (rval);
1021	}
1022
1023	if ((data = malloc(size, M_QLA8XXXBUF, M_NOWAIT)) == NULL) {
1024		device_printf(ha->pci_dev, "%s: malloc failed \n", __func__);
1025		rval = -1;
1026		goto qla_wr_flash_buffer_exit;
1027	}
1028
1029	if ((rval = copyin(buf, data, size))) {
1030		device_printf(ha->pci_dev, "%s copyin failed\n", __func__);
1031		goto qla_wr_flash_buffer_free_exit;
1032	}
1033
1034	rval = qla_flash_write_data(ha, off, size, data);
1035
1036qla_wr_flash_buffer_free_exit:
1037	free(data, M_QLA8XXXBUF);
1038
1039qla_wr_flash_buffer_exit:
1040	return (rval);
1041}
1042