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