cfi_core.c (188087) | cfi_core.c (188156) |
---|---|
1/*- 2 * Copyright (c) 2007, Juniper Networks, Inc. 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 * 1. Redistributions of source code must retain the above copyright --- 14 unchanged lines hidden (view full) --- 23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 24 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 25 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30#include <sys/cdefs.h> | 1/*- 2 * Copyright (c) 2007, Juniper Networks, Inc. 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 * 1. Redistributions of source code must retain the above copyright --- 14 unchanged lines hidden (view full) --- 23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 24 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 25 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30#include <sys/cdefs.h> |
31__FBSDID("$FreeBSD: head/sys/dev/cfi/cfi_core.c 188087 2009-02-03 19:09:16Z sam $"); | 31__FBSDID("$FreeBSD: head/sys/dev/cfi/cfi_core.c 188156 2009-02-05 18:12:07Z sam $"); |
32 | 32 |
33#include "opt_cfi.h" 34 |
|
33#include <sys/param.h> 34#include <sys/systm.h> 35#include <sys/bus.h> 36#include <sys/conf.h> 37#include <sys/kernel.h> 38#include <sys/malloc.h> 39#include <sys/module.h> 40#include <sys/rman.h> --- 24 unchanged lines hidden (view full) --- 65 break; 66 case 4: 67 val = bus_space_read_4(sc->sc_tag, sc->sc_handle, ofs); 68 break; 69 default: 70 val = ~0; 71 break; 72 } | 35#include <sys/param.h> 36#include <sys/systm.h> 37#include <sys/bus.h> 38#include <sys/conf.h> 39#include <sys/kernel.h> 40#include <sys/malloc.h> 41#include <sys/module.h> 42#include <sys/rman.h> --- 24 unchanged lines hidden (view full) --- 67 break; 68 case 4: 69 val = bus_space_read_4(sc->sc_tag, sc->sc_handle, ofs); 70 break; 71 default: 72 val = ~0; 73 break; 74 } |
73 | |
74 return (val); 75} 76 77static void 78cfi_write(struct cfi_softc *sc, u_int ofs, u_int val) 79{ 80 81 ofs &= ~(sc->sc_width - 1); --- 213 unchanged lines hidden (view full) --- 295 296 destroy_dev(sc->sc_nod); 297 free(sc->sc_region, M_TEMP); 298 bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_rid, sc->sc_res); 299 return (0); 300} 301 302static int | 75 return (val); 76} 77 78static void 79cfi_write(struct cfi_softc *sc, u_int ofs, u_int val) 80{ 81 82 ofs &= ~(sc->sc_width - 1); --- 213 unchanged lines hidden (view full) --- 296 297 destroy_dev(sc->sc_nod); 298 free(sc->sc_region, M_TEMP); 299 bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_rid, sc->sc_res); 300 return (0); 301} 302 303static int |
303cfi_wait_ready(struct cfi_softc *sc, u_int timeout) | 304cfi_wait_ready(struct cfi_softc *sc, u_int ofs, u_int timeout) |
304{ 305 int done, error; | 305{ 306 int done, error; |
306 uint32_t st0, st; | 307 uint32_t st0 = 0, st = 0; |
307 308 done = 0; 309 error = 0; 310 timeout *= 10; 311 while (!done && !error && timeout) { 312 DELAY(100); 313 timeout--; 314 315 switch (sc->sc_cmdset) { 316 case CFI_VEND_INTEL_ECS: 317 case CFI_VEND_INTEL_SCS: | 308 309 done = 0; 310 error = 0; 311 timeout *= 10; 312 while (!done && !error && timeout) { 313 DELAY(100); 314 timeout--; 315 316 switch (sc->sc_cmdset) { 317 case CFI_VEND_INTEL_ECS: 318 case CFI_VEND_INTEL_SCS: |
318 st = cfi_read(sc, sc->sc_wrofs); 319 done = (st & 0x80); | 319 st = cfi_read(sc, ofs); 320 done = (st & CFI_INTEL_STATUS_WSMS); |
320 if (done) { | 321 if (done) { |
321 if (st & 0x02) | 322 /* NB: bit 0 is reserved */ 323 st &= ~(CFI_INTEL_XSTATUS_RSVD | 324 CFI_INTEL_STATUS_WSMS | 325 CFI_INTEL_STATUS_RSVD); 326 if (st & CFI_INTEL_STATUS_DPS) |
322 error = EPERM; | 327 error = EPERM; |
323 else if (st & 0x10) | 328 else if (st & CFI_INTEL_STATUS_PSLBS) |
324 error = EIO; | 329 error = EIO; |
325 else if (st & 0x20) | 330 else if (st & CFI_INTEL_STATUS_ECLBS) |
326 error = ENXIO; | 331 error = ENXIO; |
332 else if (st) 333 error = EACCES; |
|
327 } 328 break; 329 case CFI_VEND_AMD_SCS: 330 case CFI_VEND_AMD_ECS: | 334 } 335 break; 336 case CFI_VEND_AMD_SCS: 337 case CFI_VEND_AMD_ECS: |
331 st0 = cfi_read(sc, sc->sc_wrofs); 332 st = cfi_read(sc, sc->sc_wrofs); | 338 st0 = cfi_read(sc, ofs); 339 st = cfi_read(sc, ofs); |
333 done = ((st & 0x40) == (st0 & 0x40)) ? 1 : 0; 334 break; 335 } 336 } 337 if (!done && !error) 338 error = ETIMEDOUT; 339 if (error) | 340 done = ((st & 0x40) == (st0 & 0x40)) ? 1 : 0; 341 break; 342 } 343 } 344 if (!done && !error) 345 error = ETIMEDOUT; 346 if (error) |
340 printf("\nerror=%d\n", error); | 347 printf("\nerror=%d (st 0x%x st0 0x%x)\n", error, st, st0); |
341 return (error); 342} 343 344int 345cfi_write_block(struct cfi_softc *sc) 346{ 347 union { 348 uint8_t *x8; --- 15 unchanged lines hidden (view full) --- 364 cfi_amd_write(sc, sc->sc_wrofs, AMD_ADDR_START, 365 CFI_AMD_ERASE_SECTOR); 366 cfi_amd_write(sc, sc->sc_wrofs, 0, CFI_AMD_BLOCK_ERASE); 367 break; 368 default: 369 /* Better safe than sorry... */ 370 return (ENODEV); 371 } | 348 return (error); 349} 350 351int 352cfi_write_block(struct cfi_softc *sc) 353{ 354 union { 355 uint8_t *x8; --- 15 unchanged lines hidden (view full) --- 371 cfi_amd_write(sc, sc->sc_wrofs, AMD_ADDR_START, 372 CFI_AMD_ERASE_SECTOR); 373 cfi_amd_write(sc, sc->sc_wrofs, 0, CFI_AMD_BLOCK_ERASE); 374 break; 375 default: 376 /* Better safe than sorry... */ 377 return (ENODEV); 378 } |
372 error = cfi_wait_ready(sc, sc->sc_erase_timeout); | 379 error = cfi_wait_ready(sc, sc->sc_wrofs, sc->sc_erase_timeout); |
373 if (error) 374 goto out; 375 376 /* Write the block. */ 377 ptr.x8 = sc->sc_wrbuf; 378 for (i = 0; i < sc->sc_wrbufsz; i += sc->sc_width) { 379 380 /* --- 25 unchanged lines hidden (view full) --- 406 case 4: 407 bus_space_write_4(sc->sc_tag, sc->sc_handle, 408 sc->sc_wrofs + i, *(ptr.x32)++); 409 break; 410 } 411 412 intr_restore(intr); 413 | 380 if (error) 381 goto out; 382 383 /* Write the block. */ 384 ptr.x8 = sc->sc_wrbuf; 385 for (i = 0; i < sc->sc_wrbufsz; i += sc->sc_width) { 386 387 /* --- 25 unchanged lines hidden (view full) --- 413 case 4: 414 bus_space_write_4(sc->sc_tag, sc->sc_handle, 415 sc->sc_wrofs + i, *(ptr.x32)++); 416 break; 417 } 418 419 intr_restore(intr); 420 |
414 error = cfi_wait_ready(sc, sc->sc_write_timeout); | 421 error = cfi_wait_ready(sc, sc->sc_wrofs, sc->sc_write_timeout); |
415 if (error) 416 goto out; 417 } 418 419 /* error is 0. */ 420 421 out: 422 cfi_write(sc, 0, CFI_BCS_READ_ARRAY); 423 return (error); 424} | 422 if (error) 423 goto out; 424 } 425 426 /* error is 0. */ 427 428 out: 429 cfi_write(sc, 0, CFI_BCS_READ_ARRAY); 430 return (error); 431} |
432 433#ifdef CFI_SUPPORT_STRATAFLASH 434/* 435 * Intel StrataFlash Protection Register Support. 436 * 437 * The memory includes a 128-bit Protection Register that can be 438 * used for security. There are two 64-bit segments; one is programmed 439 * at the factory with a unique 64-bit number which is immutable. 440 * The other segment is left blank for User (OEM) programming. 441 * Once the User/OEM segment is programmed it can be locked 442 * to prevent future programming by writing bit 0 of the Protection 443 * Lock Register (PLR). The PLR can written only once. 444 */ 445 446static uint16_t 447cfi_get16(struct cfi_softc *sc, int off) 448{ 449 uint16_t v = bus_space_read_2(sc->sc_tag, sc->sc_handle, off<<1); 450 return v; 451} 452 453static void 454cfi_put16(struct cfi_softc *sc, int off, uint16_t v) 455{ 456 bus_space_write_2(sc->sc_tag, sc->sc_handle, off<<1, v); 457} 458 459/* 460 * Read the factory-defined 64-bit segment of the PR. 461 */ 462int 463cfi_intel_get_factory_pr(struct cfi_softc *sc, uint64_t *id) 464{ 465 if (sc->sc_cmdset != CFI_VEND_INTEL_ECS) 466 return EOPNOTSUPP; 467 KASSERT(sc->sc_width == 2, ("sc_width %d", sc->sc_width)); 468 469 cfi_write(sc, 0, CFI_INTEL_READ_ID); 470 *id = ((uint64_t)cfi_get16(sc, CFI_INTEL_PR(0)))<<48 | 471 ((uint64_t)cfi_get16(sc, CFI_INTEL_PR(1)))<<32 | 472 ((uint64_t)cfi_get16(sc, CFI_INTEL_PR(2)))<<16 | 473 ((uint64_t)cfi_get16(sc, CFI_INTEL_PR(3))); 474 cfi_write(sc, 0, CFI_BCS_READ_ARRAY); 475 return 0; 476} 477 478/* 479 * Read the User/OEM 64-bit segment of the PR. 480 */ 481int 482cfi_intel_get_oem_pr(struct cfi_softc *sc, uint64_t *id) 483{ 484 if (sc->sc_cmdset != CFI_VEND_INTEL_ECS) 485 return EOPNOTSUPP; 486 KASSERT(sc->sc_width == 2, ("sc_width %d", sc->sc_width)); 487 488 cfi_write(sc, 0, CFI_INTEL_READ_ID); 489 *id = ((uint64_t)cfi_get16(sc, CFI_INTEL_PR(4)))<<48 | 490 ((uint64_t)cfi_get16(sc, CFI_INTEL_PR(5)))<<32 | 491 ((uint64_t)cfi_get16(sc, CFI_INTEL_PR(6)))<<16 | 492 ((uint64_t)cfi_get16(sc, CFI_INTEL_PR(7))); 493 cfi_write(sc, 0, CFI_BCS_READ_ARRAY); 494 return 0; 495} 496 497/* 498 * Write the User/OEM 64-bit segment of the PR. 499 */ 500int 501cfi_intel_set_oem_pr(struct cfi_softc *sc, uint64_t id) 502{ 503 register_t intr; 504 int i, error; 505 506 if (sc->sc_cmdset != CFI_VEND_INTEL_ECS) 507 return EOPNOTSUPP; 508 KASSERT(sc->sc_width == 2, ("sc_width %d", sc->sc_width)); 509 510 for (i = 7; i >= 4; i--, id >>= 16) { 511 intr = intr_disable(); 512 cfi_write(sc, 0, CFI_INTEL_PP_SETUP); 513 cfi_put16(sc, CFI_INTEL_PR(i), id&0xffff); 514 intr_restore(intr); 515 error = cfi_wait_ready(sc, CFI_BCS_READ_STATUS, 516 sc->sc_write_timeout); 517 if (error) 518 break; 519 } 520 cfi_write(sc, 0, CFI_BCS_READ_ARRAY); 521 return error; 522} 523 524/* 525 * Read the contents of the Protection Lock Register. 526 */ 527int 528cfi_intel_get_plr(struct cfi_softc *sc, uint32_t *plr) 529{ 530 if (sc->sc_cmdset != CFI_VEND_INTEL_ECS) 531 return EOPNOTSUPP; 532 KASSERT(sc->sc_width == 2, ("sc_width %d", sc->sc_width)); 533 534 cfi_write(sc, 0, CFI_INTEL_READ_ID); 535 *plr = cfi_get16(sc, CFI_INTEL_PLR); 536 cfi_write(sc, 0, CFI_BCS_READ_ARRAY); 537 return 0; 538} 539 540/* 541 * Write the Protection Lock Register to lock down the 542 * user-settable segment of the Protection Register. 543 * NOTE: this operation is not reversible. 544 */ 545int 546cfi_intel_set_plr(struct cfi_softc *sc) 547{ 548#ifdef CFI_ARMEDANDDANGEROUS 549 register_t intr; 550#endif 551 int error; 552 553 if (sc->sc_cmdset != CFI_VEND_INTEL_ECS) 554 return EOPNOTSUPP; 555 KASSERT(sc->sc_width == 2, ("sc_width %d", sc->sc_width)); 556 557#ifdef CFI_ARMEDANDDANGEROUS 558 /* worthy of console msg */ 559 device_printf(sc->sc_dev, "set PLR\n"); 560 intr = intr_disable(); 561 cfi_write(sc, 0, CFI_INTEL_PP_SETUP); 562 cfi_put16(sc, CFI_INTEL_PLR, 0xFFFD); 563 intr_restore(intr); 564 error = cfi_wait_ready(sc, CFI_BCS_READ_STATUS, sc->sc_write_timeout); 565 cfi_write(sc, 0, CFI_BCS_READ_ARRAY); 566#else 567 device_printf(sc->sc_dev, "%s: PLR not set, " 568 "CFI_ARMEDANDDANGEROUS not configured\n", __func__); 569 error = ENXIO; 570#endif 571 return error; 572} 573#endif /* CFI_SUPPORT_STRATAFLASH */ |
|