at25.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. /*
  2. * This file is part of the flashrom project.
  3. *
  4. * Copyright (C) 2010 Carl-Daniel Hailfinger
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; version 2 of the License.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  18. */
  19. #include "flash.h"
  20. #include "chipdrivers.h"
  21. #include "spi.h"
  22. /* Prettyprint the status register. Works for Atmel A25/A26 series. */
  23. static void spi_prettyprint_status_register_atmel_at25_srpl(uint8_t status)
  24. {
  25. msg_cdbg("Chip status register: Sector Protection Register Lock (SRPL) "
  26. "is %sset\n", (status & (1 << 7)) ? "" : "not ");
  27. }
  28. static void spi_prettyprint_status_register_atmel_at25_epewpp(uint8_t status)
  29. {
  30. msg_cdbg("Chip status register: Erase/Program Error (EPE) "
  31. "is %sset\n", (status & (1 << 5)) ? "" : "not ");
  32. msg_cdbg("Chip status register: WP# pin (WPP) "
  33. "is %sasserted\n", (status & (1 << 4)) ? "not " : "");
  34. }
  35. static void spi_prettyprint_status_register_atmel_at25_swp(uint8_t status)
  36. {
  37. msg_cdbg("Chip status register: Software Protection Status (SWP): ");
  38. switch (status & (3 << 2)) {
  39. case 0x0 << 2:
  40. msg_cdbg("no sectors are protected\n");
  41. break;
  42. case 0x1 << 2:
  43. msg_cdbg("some sectors are protected\n");
  44. /* FIXME: Read individual Sector Protection Registers. */
  45. break;
  46. case 0x3 << 2:
  47. msg_cdbg("all sectors are protected\n");
  48. break;
  49. default:
  50. msg_cdbg("reserved for future use\n");
  51. break;
  52. }
  53. }
  54. int spi_prettyprint_status_register_at25df(struct flashctx *flash)
  55. {
  56. uint8_t status;
  57. status = spi_read_status_register(flash);
  58. msg_cdbg("Chip status register is %02x\n", status);
  59. spi_prettyprint_status_register_atmel_at25_srpl(status);
  60. spi_prettyprint_status_register_bit(status, 6);
  61. spi_prettyprint_status_register_atmel_at25_epewpp(status);
  62. spi_prettyprint_status_register_atmel_at25_swp(status);
  63. spi_prettyprint_status_register_welwip(status);
  64. return 0;
  65. }
  66. int spi_prettyprint_status_register_at25df_sec(struct flashctx *flash)
  67. {
  68. /* FIXME: We should check the security lockdown. */
  69. msg_cdbg("Ignoring security lockdown (if present)\n");
  70. msg_cdbg("Ignoring status register byte 2\n");
  71. return spi_prettyprint_status_register_at25df(flash);
  72. }
  73. int spi_prettyprint_status_register_at25f(struct flashctx *flash)
  74. {
  75. uint8_t status;
  76. status = spi_read_status_register(flash);
  77. msg_cdbg("Chip status register is %02x\n", status);
  78. spi_prettyprint_status_register_atmel_at25_srpl(status);
  79. spi_prettyprint_status_register_bit(status, 6);
  80. spi_prettyprint_status_register_atmel_at25_epewpp(status);
  81. spi_prettyprint_status_register_bit(status, 3);
  82. msg_cdbg("Chip status register: Block Protect 0 (BP0) is "
  83. "%sset, %s sectors are protected\n",
  84. (status & (1 << 2)) ? "" : "not ",
  85. (status & (1 << 2)) ? "all" : "no");
  86. spi_prettyprint_status_register_welwip(status);
  87. return 0;
  88. }
  89. int spi_prettyprint_status_register_at25fs010(struct flashctx *flash)
  90. {
  91. uint8_t status;
  92. status = spi_read_status_register(flash);
  93. msg_cdbg("Chip status register is %02x\n", status);
  94. msg_cdbg("Chip status register: Status Register Write Protect (WPEN) "
  95. "is %sset\n", (status & (1 << 7)) ? "" : "not ");
  96. msg_cdbg("Chip status register: Bit 6 / Block Protect 4 (BP4) is "
  97. "%sset\n", (status & (1 << 6)) ? "" : "not ");
  98. msg_cdbg("Chip status register: Bit 5 / Block Protect 3 (BP3) is "
  99. "%sset\n", (status & (1 << 5)) ? "" : "not ");
  100. msg_cdbg("Chip status register: Bit 4 is "
  101. "%sset\n", (status & (1 << 4)) ? "" : "not ");
  102. msg_cdbg("Chip status register: Bit 3 / Block Protect 1 (BP1) is "
  103. "%sset\n", (status & (1 << 3)) ? "" : "not ");
  104. msg_cdbg("Chip status register: Bit 2 / Block Protect 0 (BP0) is "
  105. "%sset\n", (status & (1 << 2)) ? "" : "not ");
  106. /* FIXME: Pretty-print detailed sector protection status. */
  107. spi_prettyprint_status_register_welwip(status);
  108. return 0;
  109. }
  110. int spi_prettyprint_status_register_at25fs040(struct flashctx *flash)
  111. {
  112. uint8_t status;
  113. status = spi_read_status_register(flash);
  114. msg_cdbg("Chip status register is %02x\n", status);
  115. msg_cdbg("Chip status register: Status Register Write Protect (WPEN) "
  116. "is %sset\n", (status & (1 << 7)) ? "" : "not ");
  117. msg_cdbg("Chip status register: Bit 6 / Block Protect 4 (BP4) is "
  118. "%sset\n", (status & (1 << 6)) ? "" : "not ");
  119. msg_cdbg("Chip status register: Bit 5 / Block Protect 3 (BP3) is "
  120. "%sset\n", (status & (1 << 5)) ? "" : "not ");
  121. msg_cdbg("Chip status register: Bit 4 / Block Protect 2 (BP2) is "
  122. "%sset\n", (status & (1 << 4)) ? "" : "not ");
  123. msg_cdbg("Chip status register: Bit 3 / Block Protect 1 (BP1) is "
  124. "%sset\n", (status & (1 << 3)) ? "" : "not ");
  125. msg_cdbg("Chip status register: Bit 2 / Block Protect 0 (BP0) is "
  126. "%sset\n", (status & (1 << 2)) ? "" : "not ");
  127. /* FIXME: Pretty-print detailed sector protection status. */
  128. spi_prettyprint_status_register_welwip(status);
  129. return 0;
  130. }
  131. int spi_prettyprint_status_register_atmel_at26df081a(struct flashctx *flash)
  132. {
  133. uint8_t status;
  134. status = spi_read_status_register(flash);
  135. msg_cdbg("Chip status register is %02x\n", status);
  136. spi_prettyprint_status_register_atmel_at25_srpl(status);
  137. msg_cdbg("Chip status register: Sequential Program Mode Status (SPM) "
  138. "is %sset\n", (status & (1 << 6)) ? "" : "not ");
  139. spi_prettyprint_status_register_atmel_at25_epewpp(status);
  140. spi_prettyprint_status_register_atmel_at25_swp(status);
  141. spi_prettyprint_status_register_welwip(status);
  142. return 0;
  143. }
  144. int spi_disable_blockprotect_at25df(struct flashctx *flash)
  145. {
  146. uint8_t status;
  147. int result;
  148. status = spi_read_status_register(flash);
  149. /* If block protection is disabled, stop here. */
  150. if ((status & (3 << 2)) == 0)
  151. return 0;
  152. msg_cdbg("Some block protection in effect, disabling\n");
  153. if (status & (1 << 7)) {
  154. msg_cdbg("Need to disable Sector Protection Register Lock\n");
  155. if ((status & (1 << 4)) == 0) {
  156. msg_cerr("WP# pin is active, disabling "
  157. "write protection is impossible.\n");
  158. return 1;
  159. }
  160. /* All bits except bit 7 (SPRL) are readonly. */
  161. result = spi_write_status_register(flash, status & ~(1 << 7));
  162. if (result) {
  163. msg_cerr("spi_write_status_register failed\n");
  164. return result;
  165. }
  166. }
  167. /* Global unprotect. Make sure to mask SPRL as well. */
  168. result = spi_write_status_register(flash, status & ~0xbc);
  169. if (result) {
  170. msg_cerr("spi_write_status_register failed\n");
  171. return result;
  172. }
  173. status = spi_read_status_register(flash);
  174. if ((status & (3 << 2)) != 0) {
  175. msg_cerr("Block protection could not be disabled!\n");
  176. return 1;
  177. }
  178. return 0;
  179. }
  180. int spi_disable_blockprotect_at25df_sec(struct flashctx *flash)
  181. {
  182. /* FIXME: We should check the security lockdown. */
  183. msg_cinfo("Ignoring security lockdown (if present)\n");
  184. return spi_disable_blockprotect_at25df(flash);
  185. }
  186. int spi_disable_blockprotect_at25f(struct flashctx *flash)
  187. {
  188. /* spi_disable_blockprotect_at25df is not really the right way to do
  189. * this, but the side effects of said function work here as well.
  190. */
  191. return spi_disable_blockprotect_at25df(flash);
  192. }
  193. int spi_disable_blockprotect_at25fs010(struct flashctx *flash)
  194. {
  195. uint8_t status;
  196. int result;
  197. status = spi_read_status_register(flash);
  198. /* If block protection is disabled, stop here. */
  199. if ((status & 0x6c) == 0)
  200. return 0;
  201. msg_cdbg("Some block protection in effect, disabling\n");
  202. if (status & (1 << 7)) {
  203. msg_cdbg("Need to disable Status Register Write Protect\n");
  204. /* Clear bit 7 (WPEN). */
  205. result = spi_write_status_register(flash, status & ~(1 << 7));
  206. if (result) {
  207. msg_cerr("spi_write_status_register failed\n");
  208. return result;
  209. }
  210. }
  211. /* Global unprotect. Make sure to mask WPEN as well. */
  212. result = spi_write_status_register(flash, status & ~0xec);
  213. if (result) {
  214. msg_cerr("spi_write_status_register failed\n");
  215. return result;
  216. }
  217. status = spi_read_status_register(flash);
  218. if ((status & 0x6c) != 0) {
  219. msg_cerr("Block protection could not be disabled!\n");
  220. return 1;
  221. }
  222. return 0;
  223. }
  224. int spi_disable_blockprotect_at25fs040(struct flashctx *flash)
  225. {
  226. uint8_t status;
  227. int result;
  228. status = spi_read_status_register(flash);
  229. /* If block protection is disabled, stop here. */
  230. if ((status & 0x7c) == 0)
  231. return 0;
  232. msg_cdbg("Some block protection in effect, disabling\n");
  233. if (status & (1 << 7)) {
  234. msg_cdbg("Need to disable Status Register Write Protect\n");
  235. /* Clear bit 7 (WPEN). */
  236. result = spi_write_status_register(flash, status & ~(1 << 7));
  237. if (result) {
  238. msg_cerr("spi_write_status_register failed\n");
  239. return result;
  240. }
  241. }
  242. /* Global unprotect. Make sure to mask WPEN as well. */
  243. result = spi_write_status_register(flash, status & ~0xfc);
  244. if (result) {
  245. msg_cerr("spi_write_status_register failed\n");
  246. return result;
  247. }
  248. status = spi_read_status_register(flash);
  249. if ((status & 0x7c) != 0) {
  250. msg_cerr("Block protection could not be disabled!\n");
  251. return 1;
  252. }
  253. return 0;
  254. }