diff options
-rw-r--r-- | drivers/mtd/spi-nor/spi-nor.c | 39 |
1 files changed, 25 insertions, 14 deletions
diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 3f2a3ccb37d5..786344f08675 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c | |||
@@ -418,6 +418,8 @@ err: | |||
418 | return ret; | 418 | return ret; |
419 | } | 419 | } |
420 | 420 | ||
421 | #define SPI_NOR_MAX_ID_LEN 6 | ||
422 | |||
421 | struct flash_info { | 423 | struct flash_info { |
422 | /* JEDEC id zero means "no ID" (most older chips); otherwise it has | 424 | /* JEDEC id zero means "no ID" (most older chips); otherwise it has |
423 | * a high byte of zero plus three data bytes: the manufacturer id, | 425 | * a high byte of zero plus three data bytes: the manufacturer id, |
@@ -426,6 +428,14 @@ struct flash_info { | |||
426 | u32 jedec_id; | 428 | u32 jedec_id; |
427 | u16 ext_id; | 429 | u16 ext_id; |
428 | 430 | ||
431 | /* | ||
432 | * This array stores the ID bytes. | ||
433 | * The first three bytes are the JEDIC ID. | ||
434 | * JEDEC ID zero means "no ID" (mostly older chips). | ||
435 | */ | ||
436 | u8 id[SPI_NOR_MAX_ID_LEN]; | ||
437 | u8 id_len; | ||
438 | |||
429 | /* The size listed here is what works with SPINOR_OP_SE, which isn't | 439 | /* The size listed here is what works with SPINOR_OP_SE, which isn't |
430 | * necessarily called a "sector" by the vendor. | 440 | * necessarily called a "sector" by the vendor. |
431 | */ | 441 | */ |
@@ -446,10 +456,19 @@ struct flash_info { | |||
446 | #define USE_FSR 0x80 /* use flag status register */ | 456 | #define USE_FSR 0x80 /* use flag status register */ |
447 | }; | 457 | }; |
448 | 458 | ||
459 | /* Used when the "_ext_id" is two bytes at most */ | ||
449 | #define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \ | 460 | #define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \ |
450 | ((kernel_ulong_t)&(struct flash_info) { \ | 461 | ((kernel_ulong_t)&(struct flash_info) { \ |
451 | .jedec_id = (_jedec_id), \ | 462 | .jedec_id = (_jedec_id), \ |
452 | .ext_id = (_ext_id), \ | 463 | .ext_id = (_ext_id), \ |
464 | .id = { \ | ||
465 | ((_jedec_id) >> 16) & 0xff, \ | ||
466 | ((_jedec_id) >> 8) & 0xff, \ | ||
467 | (_jedec_id) & 0xff, \ | ||
468 | ((_ext_id) >> 8) & 0xff, \ | ||
469 | (_ext_id) & 0xff, \ | ||
470 | }, \ | ||
471 | .id_len = (!(_jedec_id) ? 0 : (3 + ((_ext_id) ? 2 : 0))), \ | ||
453 | .sector_size = (_sector_size), \ | 472 | .sector_size = (_sector_size), \ |
454 | .n_sectors = (_n_sectors), \ | 473 | .n_sectors = (_n_sectors), \ |
455 | .page_size = 256, \ | 474 | .page_size = 256, \ |
@@ -642,32 +661,24 @@ static const struct spi_device_id spi_nor_ids[] = { | |||
642 | static const struct spi_device_id *spi_nor_read_id(struct spi_nor *nor) | 661 | static const struct spi_device_id *spi_nor_read_id(struct spi_nor *nor) |
643 | { | 662 | { |
644 | int tmp; | 663 | int tmp; |
645 | u8 id[5]; | 664 | u8 id[SPI_NOR_MAX_ID_LEN]; |
646 | u32 jedec; | ||
647 | u16 ext_jedec; | ||
648 | struct flash_info *info; | 665 | struct flash_info *info; |
649 | 666 | ||
650 | tmp = nor->read_reg(nor, SPINOR_OP_RDID, id, 5); | 667 | tmp = nor->read_reg(nor, SPINOR_OP_RDID, id, SPI_NOR_MAX_ID_LEN); |
651 | if (tmp < 0) { | 668 | if (tmp < 0) { |
652 | dev_dbg(nor->dev, " error %d reading JEDEC ID\n", tmp); | 669 | dev_dbg(nor->dev, " error %d reading JEDEC ID\n", tmp); |
653 | return ERR_PTR(tmp); | 670 | return ERR_PTR(tmp); |
654 | } | 671 | } |
655 | jedec = id[0]; | ||
656 | jedec = jedec << 8; | ||
657 | jedec |= id[1]; | ||
658 | jedec = jedec << 8; | ||
659 | jedec |= id[2]; | ||
660 | |||
661 | ext_jedec = id[3] << 8 | id[4]; | ||
662 | 672 | ||
663 | for (tmp = 0; tmp < ARRAY_SIZE(spi_nor_ids) - 1; tmp++) { | 673 | for (tmp = 0; tmp < ARRAY_SIZE(spi_nor_ids) - 1; tmp++) { |
664 | info = (void *)spi_nor_ids[tmp].driver_data; | 674 | info = (void *)spi_nor_ids[tmp].driver_data; |
665 | if (info->jedec_id == jedec) { | 675 | if (info->id_len) { |
666 | if (info->ext_id == 0 || info->ext_id == ext_jedec) | 676 | if (!memcmp(info->id, id, info->id_len)) |
667 | return &spi_nor_ids[tmp]; | 677 | return &spi_nor_ids[tmp]; |
668 | } | 678 | } |
669 | } | 679 | } |
670 | dev_err(nor->dev, "unrecognized JEDEC id %06x\n", jedec); | 680 | dev_err(nor->dev, "unrecognized JEDEC id bytes: %02x, %2x, %2x\n", |
681 | id[0], id[1], id[2]); | ||
671 | return ERR_PTR(-ENODEV); | 682 | return ERR_PTR(-ENODEV); |
672 | } | 683 | } |
673 | 684 | ||