Deleted Added
full compact
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 */