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