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 /* 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 */
539 static int
540 qla_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 */
592 int
593 qla_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
641 qla_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
650 static int
651 qla_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
668 static int
669 qla_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
687 static int
688 qla_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
725 static int
726 qla_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
747 static uint32_t
748 qla_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
773 static int
774 qla_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
788 static int
789 qla_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
803 static int
804 qla_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
829 int
830 qla_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
856 qla_erase_flash_unlock_exit:
857 qla_sem_unlock(ha, Q8_SEM2_UNLOCK);
858
859 qla_erase_flash_exit:
860 return (rval);
861 }
862
863 static int
864 qla_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
889 static int
890 qla_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
916 static int
917 qla_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
931 static int
932 qla_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
959 qla_wr_pattern_unlock_exit:
960 qla_sem_unlock(ha, Q8_SEM2_UNLOCK);
961
962 qla_wr_pattern_exit:
963 return (rval);
964 }
965
966 static int
967 qla_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
999 qla_wr_pattern_unlock_exit:
1000 qla_sem_unlock(ha, Q8_SEM2_UNLOCK);
1001
1002 qla_wr_pattern_exit:
1003 return (rval);
1004 }
1005
1006 int
1007 qla_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
1036 qla_wr_flash_buffer_free_exit:
1037 free(data, M_QLA8XXXBUF);
1038
1039 qla_wr_flash_buffer_exit:
1040 return (rval);
1041 }
Cache object: 63d2ad565e1c05f86128e80d8cc82770
|