1 /****************************************************************************** 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 * 21 * Copyright 2014 QLogic Corporation 22 * The contents of this file are subject to the terms of the 23 * QLogic End User License (the "License"). 24 * You may not use this file except in compliance with the License. 25 * 26 * You can obtain a copy of the License at 27 * http://www.qlogic.com/Resources/Documents/DriverDownloadHelp/ 28 * QLogic_End_User_Software_License.txt 29 * See the License for the specific language governing permissions 30 * and limitations under the License. 31 * 32 * 33 * Module Description: 34 * 35 * 36 * History: 37 * 03/21/03 Hav Khauv Inception. 38 ******************************************************************************/ 39 40 #include "lm5710.h" 41 42 #define NVRAM_TIMEOUT_COUNT 100000 43 44 45 /******************************************************************************* 46 * Description: 47 * 48 * Return: 49 ******************************************************************************/ 50 static lm_status_t 51 acquire_nvram_lock( 52 lm_device_t *pdev) 53 { 54 lm_status_t lm_status; 55 u32_t j, cnt; 56 u32_t val; 57 u8_t port_num = PORT_ID(pdev); /* TBD - E1H: nvram lock � DOES NOT scale to 8 functions! (only 4 clients) 58 * 1. Can we assume no concurrent access by control applications? 59 * 2. If not, the MISC lock is our backup */ 60 61 DbgMessage(pdev, VERBOSEnv, "### acquire_nvram_lock\n"); 62 /* Adjust timeout for emulation/FPGA */ 63 cnt = NVRAM_TIMEOUT_COUNT; 64 if (CHIP_REV_IS_EMUL(pdev)) cnt *= 100; 65 66 val = 0; 67 68 /* Request access to the flash interface. */ 69 REG_WR(pdev, MCP_REG_MCPR_NVM_SW_ARB, (MCPR_NVM_SW_ARB_ARB_REQ_SET1 << port_num )); 70 for(j = 0; j < cnt*10; j++) 71 { 72 val=REG_RD(pdev, MCP_REG_MCPR_NVM_SW_ARB); 73 if(val & (MCPR_NVM_SW_ARB_ARB_ARB1 << port_num)) 74 { 75 break; 76 } 77 78 mm_wait(pdev, 5); 79 } 80 81 if(val & (MCPR_NVM_SW_ARB_ARB_ARB1 << port_num)) 82 { 83 lm_status = LM_STATUS_SUCCESS; 84 } 85 else 86 { 87 DbgMessage(NULL, FATAL, "Value of MCP_REG_MCPR_NVM_SW_ARB is 0x%x\n", val); 88 DbgBreakMsg("Cannot get access to nvram interface.\n"); 89 90 lm_status = LM_STATUS_BUSY; 91 } 92 93 return lm_status; 94 } /* acquire_nvram_lock */ 95 96 97 98 /******************************************************************************* 99 * Description: 100 * 101 * Return: 102 ******************************************************************************/ 103 static void 104 release_nvram_lock( 105 lm_device_t *pdev) 106 { 107 u32_t j, cnt; 108 u32_t val; 109 u8_t port_num = PORT_ID(pdev); 110 111 DbgMessage(pdev, VERBOSEnv, "### release_nvram_lock\n"); 112 /* Adjust timeout for emulation/FPGA */ 113 cnt = NVRAM_TIMEOUT_COUNT; 114 if (CHIP_REV_IS_EMUL(pdev)) cnt *= 100; 115 116 /* Relinquish nvram interface. */ 117 REG_WR(pdev, MCP_REG_MCPR_NVM_SW_ARB, (MCPR_NVM_SW_ARB_ARB_REQ_CLR1 << port_num)); 118 119 val = 0; 120 121 for(j = 0; j < cnt; j++) 122 { 123 val=REG_RD(pdev, MCP_REG_MCPR_NVM_SW_ARB); 124 if(!(val & (MCPR_NVM_SW_ARB_ARB_ARB1 << port_num))) 125 { 126 break; 127 } 128 129 mm_wait(pdev, 5); 130 } 131 132 DbgBreakIf(val & (MCPR_NVM_SW_ARB_ARB_ARB1 << port_num)); 133 } /* release_nvram_lock */ 134 135 136 #if 0 137 /******************************************************************************* 138 * Description: 139 * 140 * Return: 141 * 142 ******************************************************************************/ 143 static lm_status_t 144 enable_nvram_write( 145 lm_device_t *pdev) 146 { 147 u32_t val, j, cnt; 148 lm_status_t lm_status; 149 150 lm_status = LM_STATUS_SUCCESS; 151 152 DbgMessage(pdev, INFORMnv, "### enable_nvram_write\n"); 153 154 /* Need to clear DONE bit separately. */ 155 REG_WR(pdev, MCP_REG_MCPR_NVM_COMMAND, MCPR_NVM_COMMAND_DONE); 156 157 /* Issue a write enable command. */ 158 REG_WR(pdev, MCP_REG_MCPR_NVM_COMMAND, MCPR_NVM_COMMAND_DOIT | MCPR_NVM_COMMAND_WREN); 159 160 /* Adjust timeout for emulation/FPGA */ 161 cnt = NVRAM_TIMEOUT_COUNT; 162 if (CHIP_REV(pdev) == CHIP_REV_EMUL) cnt *= 100; 163 164 lm_status = LM_STATUS_BUSY; 165 166 for(j = 0; j < cnt; j++) 167 { 168 mm_wait(pdev, 5); 169 170 val=REG_RD(pdev, MCP_REG_MCPR_NVM_COMMAND); 171 if(val & MCPR_NVM_COMMAND_DONE) 172 { 173 lm_status = LM_STATUS_SUCCESS; 174 break; 175 } 176 } 177 178 return lm_status; 179 } /* enable_nvram_write */ 180 181 182 183 /******************************************************************************* 184 * Description: 185 * 186 * Return: 187 * 188 ******************************************************************************/ 189 static lm_status_t 190 disable_nvram_write( 191 lm_device_t *pdev) 192 { 193 lm_status_t lm_status; 194 u32_t cnt,j,val; 195 196 DbgMessage(pdev, INFORMnv, "### disable_nvram_write\n"); 197 /* Need to clear DONE bit separately. */ 198 REG_WR(pdev, MCP_REG_MCPR_NVM_COMMAND, MCPR_NVM_COMMAND_DONE); 199 200 /* Issue a write disable command. */ 201 REG_WR(pdev, MCP_REG_MCPR_NVM_COMMAND, MCPR_NVM_COMMAND_DOIT | MCPR_NVM_COMMAND_WRDI); 202 203 /* Adjust timeout for emulation/FPGA */ 204 cnt = NVRAM_TIMEOUT_COUNT; 205 if (CHIP_REV(pdev) == CHIP_REV_EMUL) cnt *= 100; 206 207 lm_status = LM_STATUS_BUSY; 208 for(j = 0; j < cnt; j++) 209 { 210 mm_wait(pdev, 5); 211 212 val=REG_RD(pdev, MCP_REG_MCPR_NVM_COMMAND); 213 if(val & MCPR_NVM_COMMAND_DONE) 214 { 215 lm_status = LM_STATUS_SUCCESS; 216 break; 217 } 218 } 219 220 return lm_status; 221 } /* disable_nvram_write */ 222 223 #endif /* 0 */ 224 225 /******************************************************************************* 226 * Description: 227 * 228 * Return: 229 ******************************************************************************/ 230 static lm_status_t 231 enable_nvram_access( 232 lm_device_t *pdev) 233 { 234 u32_t val; 235 236 DbgMessage(pdev, VERBOSEnv, "### enable_nvram_access\n"); 237 val=REG_RD(pdev, MCP_REG_MCPR_NVM_ACCESS_ENABLE); 238 239 /* Enable both bits, even on read. */ 240 REG_WR(pdev, MCP_REG_MCPR_NVM_ACCESS_ENABLE, val | MCPR_NVM_ACCESS_ENABLE_EN | MCPR_NVM_ACCESS_ENABLE_WR_EN); 241 242 return LM_STATUS_SUCCESS; 243 } /* enable_nvram_access */ 244 245 246 247 /******************************************************************************* 248 * Description: 249 * 250 * Return: 251 ******************************************************************************/ 252 static lm_status_t 253 disable_nvram_access( 254 lm_device_t *pdev) 255 { 256 u32_t val; 257 258 DbgMessage(pdev, VERBOSEnv, "### disable_nvram_access\n"); 259 val=REG_RD(pdev, MCP_REG_MCPR_NVM_ACCESS_ENABLE); 260 261 /* Disable both bits, even after read. */ 262 REG_WR(pdev, MCP_REG_MCPR_NVM_ACCESS_ENABLE, val & ~(MCPR_NVM_ACCESS_ENABLE_EN | MCPR_NVM_ACCESS_ENABLE_WR_EN)); 263 264 return LM_STATUS_SUCCESS; 265 } /* disable_nvram_access */ 266 267 268 269 270 /******************************************************************************* 271 * Description: 272 * 273 * Return: 274 ******************************************************************************/ 275 static lm_status_t 276 nvram_read_dword( 277 lm_device_t *pdev, 278 u32_t offset, 279 u32_t *ret_val, 280 u32_t nvram_flags) 281 { 282 lm_status_t lm_status; 283 u32_t cmd_flags; 284 u32_t val; 285 u32_t j, cnt; 286 287 DbgMessage(pdev, VERBOSEnv, "### nvram_read_dword\n"); 288 DbgMessage(pdev, VERBOSEnv, "offset %d flags %d\n",offset,nvram_flags); 289 290 /* Build the command word. */ 291 cmd_flags = nvram_flags | MCPR_NVM_COMMAND_DOIT; 292 293 /* Need to clear DONE bit separately. */ 294 REG_WR(pdev, MCP_REG_MCPR_NVM_COMMAND, MCPR_NVM_COMMAND_DONE); 295 296 /* Address of the NVRAM to read from. */ 297 REG_WR(pdev, MCP_REG_MCPR_NVM_ADDR, offset & MCPR_NVM_ADDR_NVM_ADDR_VALUE); 298 299 /* Issue a read command. */ 300 REG_WR(pdev, MCP_REG_MCPR_NVM_COMMAND, cmd_flags); 301 302 /* Adjust timeout for emulation/FPGA */ 303 cnt = NVRAM_TIMEOUT_COUNT; 304 if (CHIP_REV_IS_EMUL(pdev)) cnt *= 100; 305 306 /* Wait for completion. */ 307 lm_status = LM_STATUS_BUSY; 308 for(j = 0; j < cnt; j++) 309 { 310 mm_wait(pdev, 5); 311 val=REG_RD(pdev, MCP_REG_MCPR_NVM_COMMAND); 312 if(val & MCPR_NVM_COMMAND_DONE) 313 { 314 val=REG_RD(pdev, MCP_REG_MCPR_NVM_READ); 315 316 /* Change to little endian. */ 317 #if defined(LITTLE_ENDIAN) 318 val = ((val & 0xff) << 24) | ((val & 0xff00) << 8) | 319 ((val & 0xff0000) >> 8) | ((val >> 24) & 0xff); 320 #endif 321 322 *ret_val = val; 323 324 lm_status = LM_STATUS_SUCCESS; 325 326 break; 327 } 328 } 329 330 return lm_status; 331 } /* nvram_read_dword */ 332 333 334 335 /******************************************************************************* 336 * Description: 337 * 338 * Return: 339 ******************************************************************************/ 340 static lm_status_t 341 nvram_write_dword( 342 lm_device_t *pdev, 343 u32_t offset, 344 u32_t val, 345 u32_t nvram_flags) 346 { 347 lm_status_t lm_status; 348 u32_t cmd_flags; 349 u32_t j, cnt; 350 351 DbgMessage(pdev, VERBOSEnv, "### nvram_write_dword\n"); 352 /* Build the command word. */ 353 cmd_flags = nvram_flags | MCPR_NVM_COMMAND_DOIT | MCPR_NVM_COMMAND_WR; 354 355 /* Change to little endian. */ 356 #if defined(LITTLE_ENDIAN) 357 val = ((val & 0xff) << 24) | ((val & 0xff00) << 8) | 358 ((val & 0xff0000) >> 8) | ((val >> 24) & 0xff); 359 #endif 360 361 /* Need to clear DONE bit separately. */ 362 REG_WR(pdev, MCP_REG_MCPR_NVM_COMMAND, MCPR_NVM_COMMAND_DONE); 363 364 /* Write the data. */ 365 REG_WR(pdev, MCP_REG_MCPR_NVM_WRITE, val); 366 367 /* Address of the NVRAM to write to. */ 368 REG_WR(pdev, MCP_REG_MCPR_NVM_ADDR, offset & MCPR_NVM_ADDR_NVM_ADDR_VALUE); 369 370 /* Issue the write command. */ 371 REG_WR(pdev, MCP_REG_MCPR_NVM_COMMAND, cmd_flags); 372 373 /* Adjust timeout for emulation/FPGA */ 374 375 cnt = NVRAM_TIMEOUT_COUNT; 376 if (CHIP_REV_IS_EMUL(pdev)) cnt *= 100; 377 378 /* Wait for completion. */ 379 lm_status = LM_STATUS_BUSY; 380 for(j = 0; j < cnt; j++) 381 { 382 mm_wait(pdev, 5); 383 384 val=REG_RD(pdev, MCP_REG_MCPR_NVM_COMMAND); 385 if(val & MCPR_NVM_COMMAND_DONE) 386 { 387 lm_status = LM_STATUS_SUCCESS; 388 break; 389 } 390 } 391 392 return lm_status; 393 } /* nvram_write_dword */ 394 395 396 397 /******************************************************************************* 398 * Description: 399 * 400 * Return: 401 ******************************************************************************/ 402 lm_status_t 403 lm_nvram_read( 404 lm_device_t *pdev, 405 u32_t offset, 406 u32_t *ret_buf, 407 u32_t buf_size) 408 { 409 lm_status_t lm_status; 410 u32_t cmd_flags; 411 412 413 DbgMessage(pdev, VERBOSEnv, "### lm_nvram_read\n"); 414 DbgMessage(pdev, VERBOSEnv, "offset %d size %d\n",offset,buf_size); 415 416 if((buf_size & 0x03) || (offset & 0x03)) 417 { 418 DbgBreakMsg("Invalid paramter.\n"); 419 420 return LM_STATUS_FAILURE; 421 } 422 423 // TODO what is the nvram total size 424 if(offset + buf_size > pdev->hw_info.flash_spec.total_size) 425 { 426 DbgBreakMsg("Invalid paramter.\n"); 427 428 return LM_STATUS_FAILURE; 429 } 430 431 /* Request access to the flash interface. */ 432 lm_status = acquire_nvram_lock(pdev); 433 if(lm_status != LM_STATUS_SUCCESS) 434 { 435 return lm_status; 436 } 437 438 /* Enable access to flash interface */ 439 lm_status = enable_nvram_access(pdev); 440 if(lm_status != LM_STATUS_SUCCESS) 441 { 442 release_nvram_lock(pdev); 443 return lm_status; 444 } 445 446 /* Read the first word. */ 447 cmd_flags = MCPR_NVM_COMMAND_FIRST; 448 while(buf_size > sizeof(u32_t) && lm_status == LM_STATUS_SUCCESS) 449 { 450 lm_status = nvram_read_dword(pdev, offset, ret_buf, cmd_flags); 451 452 /* Advance to the next dword. */ 453 offset += sizeof(u32_t); 454 ret_buf++; 455 buf_size -= sizeof(u32_t); 456 cmd_flags = 0; 457 } 458 459 if(lm_status == LM_STATUS_SUCCESS) 460 { 461 cmd_flags |= MCPR_NVM_COMMAND_LAST; 462 lm_status = nvram_read_dword(pdev, offset, ret_buf, cmd_flags); 463 } 464 465 /* Disable access to flash interface */ 466 disable_nvram_access(pdev); 467 468 release_nvram_lock(pdev); 469 470 return lm_status; 471 } /* lm_nvram_read */ 472 473 474 /******************************************************************************* 475 * Description: 476 * 477 * Return: 478 ******************************************************************************/ 479 lm_status_t 480 lm_nvram_write( 481 lm_device_t *pdev, 482 u32_t offset, 483 u32_t *data_buf, 484 u32_t buf_size) 485 { 486 lm_status_t lm_status; 487 u32_t written_so_far; 488 u32_t cmd_flags; 489 u32_t *ptr32, addr; 490 491 DbgMessage(pdev, VERBOSEnv, "### lm_nvram_write\n"); 492 493 if(offset & 0x03) 494 { 495 DbgBreakMsg("Invalid paramter.\n"); 496 497 return LM_STATUS_FAILURE; 498 } 499 // TODO what is the nvram total size 500 if(offset + buf_size > pdev->hw_info.flash_spec.total_size) 501 { 502 DbgMessage(pdev, FATAL, "lm_nvram_write failed ! buf_size %d larger than NVM total_size %d\n", buf_size, pdev->hw_info.flash_spec.total_size); 503 DbgBreakMsg("Failed to write to NVM! Attemp to write to offset larger than NVM total size !\n"); 504 505 return LM_STATUS_FAILURE; 506 } 507 508 lm_status = LM_STATUS_SUCCESS; 509 510 /* Request access to the flash interface. */ 511 lm_status = acquire_nvram_lock(pdev); 512 if(lm_status != LM_STATUS_SUCCESS) 513 return lm_status; 514 515 /* Enable access to flash interface */ 516 lm_status = enable_nvram_access(pdev); 517 if(lm_status != LM_STATUS_SUCCESS) 518 { 519 release_nvram_lock(pdev); 520 return lm_status; 521 } 522 523 written_so_far = 0; 524 cmd_flags = MCPR_NVM_COMMAND_FIRST; 525 addr = offset; 526 ptr32 = data_buf; 527 while (written_so_far < buf_size) 528 { 529 if (written_so_far == (buf_size - 4)) 530 cmd_flags |= MCPR_NVM_COMMAND_LAST; 531 else if (((addr & 0xff) + 4) == NVRAM_PAGE_SIZE) // else if (((addr + 4) % NVRAM_PAGE_SIZE) == 0) 532 cmd_flags |= MCPR_NVM_COMMAND_LAST; 533 else if ((addr & 0xff) == 0) // else if ((addr % NVRAM_PAGE_SIZE) == 0) 534 cmd_flags |= MCPR_NVM_COMMAND_FIRST; 535 nvram_write_dword(pdev, addr, *ptr32, cmd_flags); 536 ptr32++; 537 addr += 4; 538 written_so_far += 4; 539 cmd_flags = 0; 540 } 541 /* Disable access to flash interface */ 542 disable_nvram_access(pdev); 543 release_nvram_lock(pdev); 544 545 546 return lm_status; 547 548 } /* lm_nvram_write */ 549