nand_samsung.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Copyright (C) 2017 Free Electrons
  4. * Copyright (C) 2017 NextThing Co
  5. *
  6. * Author: Boris Brezillon <[email protected]>
  7. */
  8. #include "internals.h"
  9. static void samsung_nand_decode_id(struct nand_chip *chip)
  10. {
  11. struct nand_device *base = &chip->base;
  12. struct nand_ecc_props requirements = {};
  13. struct mtd_info *mtd = nand_to_mtd(chip);
  14. struct nand_memory_organization *memorg;
  15. memorg = nanddev_get_memorg(&chip->base);
  16. /* New Samsung (6 byte ID): Samsung K9GAG08U0F (p.44) */
  17. if (chip->id.len == 6 && !nand_is_slc(chip) &&
  18. chip->id.data[5] != 0x00) {
  19. u8 extid = chip->id.data[3];
  20. /* Get pagesize */
  21. memorg->pagesize = 2048 << (extid & 0x03);
  22. mtd->writesize = memorg->pagesize;
  23. extid >>= 2;
  24. /* Get oobsize */
  25. switch (((extid >> 2) & 0x4) | (extid & 0x3)) {
  26. case 1:
  27. memorg->oobsize = 128;
  28. break;
  29. case 2:
  30. memorg->oobsize = 218;
  31. break;
  32. case 3:
  33. memorg->oobsize = 400;
  34. break;
  35. case 4:
  36. memorg->oobsize = 436;
  37. break;
  38. case 5:
  39. memorg->oobsize = 512;
  40. break;
  41. case 6:
  42. memorg->oobsize = 640;
  43. break;
  44. default:
  45. /*
  46. * We should never reach this case, but if that
  47. * happens, this probably means Samsung decided to use
  48. * a different extended ID format, and we should find
  49. * a way to support it.
  50. */
  51. WARN(1, "Invalid OOB size value");
  52. break;
  53. }
  54. mtd->oobsize = memorg->oobsize;
  55. /* Get blocksize */
  56. extid >>= 2;
  57. memorg->pages_per_eraseblock = (128 * 1024) <<
  58. (((extid >> 1) & 0x04) |
  59. (extid & 0x03)) /
  60. memorg->pagesize;
  61. mtd->erasesize = (128 * 1024) <<
  62. (((extid >> 1) & 0x04) | (extid & 0x03));
  63. /* Extract ECC requirements from 5th id byte*/
  64. extid = (chip->id.data[4] >> 4) & 0x07;
  65. if (extid < 5) {
  66. requirements.step_size = 512;
  67. requirements.strength = 1 << extid;
  68. } else {
  69. requirements.step_size = 1024;
  70. switch (extid) {
  71. case 5:
  72. requirements.strength = 24;
  73. break;
  74. case 6:
  75. requirements.strength = 40;
  76. break;
  77. case 7:
  78. requirements.strength = 60;
  79. break;
  80. default:
  81. WARN(1, "Could not decode ECC info");
  82. requirements.step_size = 0;
  83. }
  84. }
  85. } else {
  86. nand_decode_ext_id(chip);
  87. if (nand_is_slc(chip)) {
  88. switch (chip->id.data[1]) {
  89. /* K9F4G08U0D-S[I|C]B0(T00) */
  90. case 0xDC:
  91. requirements.step_size = 512;
  92. requirements.strength = 1;
  93. break;
  94. /* K9F1G08U0E 21nm chips do not support subpage write */
  95. case 0xF1:
  96. if (chip->id.len > 4 &&
  97. (chip->id.data[4] & GENMASK(1, 0)) == 0x1)
  98. chip->options |= NAND_NO_SUBPAGE_WRITE;
  99. break;
  100. default:
  101. break;
  102. }
  103. }
  104. }
  105. nanddev_set_ecc_requirements(base, &requirements);
  106. }
  107. static int samsung_nand_init(struct nand_chip *chip)
  108. {
  109. struct mtd_info *mtd = nand_to_mtd(chip);
  110. if (mtd->writesize > 512)
  111. chip->options |= NAND_SAMSUNG_LP_OPTIONS;
  112. if (!nand_is_slc(chip))
  113. chip->options |= NAND_BBM_LASTPAGE;
  114. else
  115. chip->options |= NAND_BBM_FIRSTPAGE | NAND_BBM_SECONDPAGE;
  116. return 0;
  117. }
  118. const struct nand_manufacturer_ops samsung_nand_manuf_ops = {
  119. .detect = samsung_nand_decode_id,
  120. .init = samsung_nand_init,
  121. };