1103-mtd-spi-nor-Support-R-W-for-S25FS-S-family-flash.patch 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. From 0878404f549021e7fe0a49ae0454cf53fd452add Mon Sep 17 00:00:00 2001
  2. From: Yunhui Cui <yunhui.cui@nxp.com>
  3. Date: Tue, 2 Feb 2016 12:00:27 +0800
  4. Subject: [PATCH 103/113] mtd: spi-nor: Support R/W for S25FS-S family flash
  5. With the physical sectors combination, S25FS-S family flash
  6. requires some special operations for read/write functions.
  7. Signed-off-by: Yunhui Cui <yunhui.cui@nxp.com>
  8. ---
  9. drivers/mtd/spi-nor/spi-nor.c | 60 +++++++++++++++++++++++++++++++++++++++++
  10. 1 file changed, 60 insertions(+)
  11. --- a/drivers/mtd/spi-nor/spi-nor.c
  12. +++ b/drivers/mtd/spi-nor/spi-nor.c
  13. @@ -40,6 +40,10 @@
  14. #define SPI_NOR_MAX_ID_LEN 6
  15. #define SPI_NOR_MAX_ADDR_WIDTH 4
  16. #define SPI_NOR_MICRON_WRITE_ENABLE 0x7f
  17. +/* Added for S25FS-S family flash */
  18. +#define SPINOR_CONFIG_REG3_OFFSET 0x800004
  19. +#define CR3V_4KB_ERASE_UNABLE 0x8
  20. +#define SPINOR_S25FS_FAMILY_ID 0x81
  21. struct flash_info {
  22. char *name;
  23. @@ -74,6 +78,8 @@ struct flash_info {
  24. };
  25. #define JEDEC_MFR(info) ((info)->id[0])
  26. +#define EXT_ID(info) ((info)->id[5])
  27. +
  28. static const struct flash_info *spi_nor_match_id(const char *name);
  29. @@ -792,6 +798,7 @@ static const struct flash_info spi_nor_i
  30. */
  31. { "s25sl032p", INFO(0x010215, 0x4d00, 64 * 1024, 64, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
  32. { "s25sl064p", INFO(0x010216, 0x4d00, 64 * 1024, 128, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
  33. + { "s25fs256s1", INFO6(0x010219, 0x4d0181, 64 * 1024, 512, 0)},
  34. { "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, 0) },
  35. { "s25fl256s1", INFO(0x010219, 0x4d01, 64 * 1024, 512, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
  36. { "s25fl512s", INFO(0x010220, 0x4d00, 256 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
  37. @@ -916,6 +923,53 @@ static const struct flash_info *spi_nor_
  38. return ERR_PTR(-ENODEV);
  39. }
  40. +/*
  41. + * The S25FS-S family physical sectors may be configured as a
  42. + * hybrid combination of eight 4-kB parameter sectors
  43. + * at the top or bottom of the address space with all
  44. + * but one of the remaining sectors being uniform size.
  45. + * The Parameter Sector Erase commands (20h or 21h) must
  46. + * be used to erase the 4-kB parameter sectors individually.
  47. + * The Sector (uniform sector) Erase commands (D8h or DCh)
  48. + * must be used to erase any of the remaining
  49. + * sectors, including the portion of highest or lowest address
  50. + * sector that is not overlaid by the parameter sectors.
  51. + * The uniform sector erase command has no effect on parameter sectors.
  52. + */
  53. +static int spansion_s25fs_disable_4kb_erase(struct spi_nor *nor)
  54. +{
  55. + struct fsl_qspi *q;
  56. + u32 cr3v_addr = SPINOR_CONFIG_REG3_OFFSET;
  57. + u8 cr3v = 0x0;
  58. + int ret = 0x0;
  59. +
  60. + q = nor->priv;
  61. +
  62. + nor->cmd_buf[2] = cr3v_addr >> 16;
  63. + nor->cmd_buf[1] = cr3v_addr >> 8;
  64. + nor->cmd_buf[0] = cr3v_addr >> 0;
  65. +
  66. + ret = nor->read_reg(nor, SPINOR_OP_SPANSION_RDAR, &cr3v, 1);
  67. + if (ret)
  68. + return ret;
  69. + if (cr3v & CR3V_4KB_ERASE_UNABLE)
  70. + return 0;
  71. + ret = nor->write_reg(nor, SPINOR_OP_WREN, NULL, 0);
  72. + if (ret)
  73. + return ret;
  74. + cr3v = CR3V_4KB_ERASE_UNABLE;
  75. + nor->program_opcode = SPINOR_OP_SPANSION_WRAR;
  76. + nor->write(nor, cr3v_addr, 1, &cr3v);
  77. +
  78. + ret = nor->read_reg(nor, SPINOR_OP_SPANSION_RDAR, &cr3v, 1);
  79. + if (ret)
  80. + return ret;
  81. + if (!(cr3v & CR3V_4KB_ERASE_UNABLE))
  82. + return -EPERM;
  83. +
  84. + return 0;
  85. +}
  86. +
  87. static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len,
  88. size_t *retlen, u_char *buf)
  89. {
  90. @@ -1261,6 +1315,12 @@ int spi_nor_scan(struct spi_nor *nor, co
  91. write_sr(nor, ret);
  92. }
  93. + if (EXT_ID(info) == SPINOR_S25FS_FAMILY_ID) {
  94. + ret = spansion_s25fs_disable_4kb_erase(nor);
  95. + if (ret)
  96. + return ret;
  97. + }
  98. +
  99. if (!mtd->name)
  100. mtd->name = dev_name(dev);
  101. mtd->priv = nor;