100-14-mtd-spi-nor-add-support-to-read-flash-unique-ID.patch 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. From c4172a95df8a57a66c70a8b9948b9600a01c4cb7 Mon Sep 17 00:00:00 2001
  2. From: Weijie Gao <[email protected]>
  3. Date: Mon, 25 Jul 2022 11:32:08 +0800
  4. Subject: [PATCH 49/71] mtd: spi-nor: add support to read flash unique ID
  5. This patch adds support to read unique ID from spi-nor flashes.
  6. Signed-off-by: Weijie Gao <[email protected]>
  7. ---
  8. drivers/mtd/spi/spi-nor-core.c | 95 ++++++++++++++++++++++++++++++++++
  9. include/linux/mtd/spi-nor.h | 2 +
  10. 2 files changed, 97 insertions(+)
  11. --- a/drivers/mtd/spi/spi-nor-core.c
  12. +++ b/drivers/mtd/spi/spi-nor-core.c
  13. @@ -2854,6 +2854,100 @@ static int spi_nor_init_params(struct sp
  14. return 0;
  15. }
  16. +static int spi_nor_read_uuid(struct spi_nor *nor)
  17. +{
  18. + u8 read_opcode, addr_width, read_dummy;
  19. + loff_t addr;
  20. + u8 *uuid;
  21. + u8 uuid_len;
  22. + int shift = 0;
  23. + int ret;
  24. + int i;
  25. + struct spi_mem_op op;
  26. +
  27. + read_opcode = nor->read_opcode;
  28. + addr_width = nor->addr_width;
  29. + read_dummy = nor->read_dummy;
  30. +
  31. + switch (JEDEC_MFR(nor->info)) {
  32. + case SNOR_MFR_WINBOND:
  33. + uuid_len = 8;
  34. + nor->read_opcode = 0x4b;
  35. + nor->addr_width = 0;
  36. + addr = 0x0;
  37. + nor->read_dummy = 4;
  38. + break;
  39. + case SNOR_MFR_GIGADEVICE:
  40. + uuid_len = 16;
  41. + nor->read_opcode = 0x4b;
  42. + nor->addr_width = 3;
  43. + addr = 0x0;
  44. + nor->read_dummy = 1;
  45. + break;
  46. + case CFI_MFR_ST:
  47. + case SNOR_MFR_MICRON:
  48. + uuid_len = 17;
  49. + shift = 3;
  50. + nor->read_opcode = 0x9f;
  51. + nor->addr_width = 0;
  52. + addr = 0x0;
  53. + nor->read_dummy = 0;
  54. + break;
  55. + case SNOR_MFR_EON:
  56. + uuid_len = 12;
  57. + nor->read_opcode = 0x5a;
  58. + nor->addr_width = 3;
  59. + addr = 0x80;
  60. + nor->read_dummy = 1;
  61. + break;
  62. + /* Automotive only in SPANSION's NOR devices */
  63. + case SNOR_MFR_SPANSION:
  64. + uuid_len = 11;
  65. + shift = 386;
  66. + nor->read_opcode = 0x9f;
  67. + nor->addr_width = 0;
  68. + addr = 0x0;
  69. + nor->read_dummy = 0;
  70. + break;
  71. + default:
  72. + printf("UUID not supported on this device.\n");
  73. + return -ENOTSUPP;
  74. + }
  75. +
  76. + uuid = kmalloc((uuid_len + shift) * sizeof(*uuid), GFP_KERNEL);
  77. + if (!uuid) {
  78. + ret = -ENOMEM;
  79. + goto read_err;
  80. + }
  81. + memset(uuid, 0x0, (uuid_len + shift) * sizeof(*uuid));
  82. +
  83. + op = (struct spi_mem_op)SPI_MEM_OP(SPI_MEM_OP_CMD(nor->read_opcode, 0),
  84. + SPI_MEM_OP_ADDR(nor->addr_width, addr, 0),
  85. + SPI_MEM_OP_DUMMY(nor->read_dummy, 0),
  86. + SPI_MEM_OP_DATA_IN(uuid_len+shift, NULL, 0));
  87. +
  88. + spi_nor_setup_op(nor, &op, nor->reg_proto);
  89. +
  90. + ret = spi_nor_read_write_reg(nor, &op, uuid);
  91. + if (ret < 0) {
  92. + dev_dbg(nor->dev, "error %d reading %x\n", ret, nor->read_opcode);
  93. + goto read_err;
  94. + }
  95. +
  96. + printf("UUID: 0x");
  97. + for(i = 0; i<uuid_len; i++)
  98. + printf("%02x", uuid[i+shift]);
  99. + puts("\n");
  100. +
  101. +read_err:
  102. + nor->read_opcode = read_opcode;
  103. + nor->addr_width = addr_width;
  104. + nor->read_dummy = read_dummy;
  105. + kfree(uuid);
  106. +
  107. + return ret;
  108. +}
  109. +
  110. static int spi_nor_hwcaps2cmd(u32 hwcaps, const int table[][2], size_t size)
  111. {
  112. size_t i;
  113. @@ -4051,6 +4145,7 @@ int spi_nor_scan(struct spi_nor *nor)
  114. nor->write = spi_nor_write_data;
  115. nor->read_reg = spi_nor_read_reg;
  116. nor->write_reg = spi_nor_write_reg;
  117. + nor->read_uuid = spi_nor_read_uuid;
  118. nor->setup = spi_nor_default_setup;
  119. --- a/include/linux/mtd/spi-nor.h
  120. +++ b/include/linux/mtd/spi-nor.h
  121. @@ -29,6 +29,7 @@
  122. #define SNOR_MFR_SPANSION CFI_MFR_AMD
  123. #define SNOR_MFR_SST CFI_MFR_SST
  124. #define SNOR_MFR_WINBOND 0xef /* Also used by some Spansion */
  125. +#define SNOR_MFR_EON CFI_MFR_EON
  126. #define SNOR_MFR_CYPRESS 0x34
  127. /*
  128. @@ -571,6 +572,7 @@ struct spi_nor {
  129. void (*unprepare)(struct spi_nor *nor, enum spi_nor_ops ops);
  130. int (*read_reg)(struct spi_nor *nor, u8 opcode, u8 *buf, int len);
  131. int (*write_reg)(struct spi_nor *nor, u8 opcode, u8 *buf, int len);
  132. + int (*read_uuid)(struct spi_nor *nor);
  133. ssize_t (*read)(struct spi_nor *nor, loff_t from,
  134. size_t len, u_char *read_buf);