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