sst.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. /*
  2. * Driver for SST serial flashes
  3. *
  4. * (C) Copyright 2000-2002
  5. * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
  6. * Copyright 2008, Network Appliance Inc.
  7. * Jason McMullan <mcmullan@netapp.com>
  8. * Copyright (C) 2004-2007 Freescale Semiconductor, Inc.
  9. * TsiChung Liew (Tsi-Chung.Liew@freescale.com)
  10. * Copyright (c) 2008-2009 Analog Devices Inc.
  11. *
  12. * Licensed under the GPL-2 or later.
  13. */
  14. #include <common.h>
  15. #include <malloc.h>
  16. #include <spi_flash.h>
  17. #include "spi_flash_internal.h"
  18. #define CMD_SST_WREN 0x06 /* Write Enable */
  19. #define CMD_SST_WRDI 0x04 /* Write Disable */
  20. #define CMD_SST_RDSR 0x05 /* Read Status Register */
  21. #define CMD_SST_WRSR 0x01 /* Write Status Register */
  22. #define CMD_SST_READ 0x03 /* Read Data Bytes */
  23. #define CMD_SST_FAST_READ 0x0b /* Read Data Bytes at Higher Speed */
  24. #define CMD_SST_BP 0x02 /* Byte Program */
  25. #define CMD_SST_AAI_WP 0xAD /* Auto Address Increment Word Program */
  26. #define CMD_SST_SE 0x20 /* Sector Erase */
  27. #define SST_SR_WIP (1 << 0) /* Write-in-Progress */
  28. #define SST_SR_WEL (1 << 1) /* Write enable */
  29. #define SST_SR_BP0 (1 << 2) /* Block Protection 0 */
  30. #define SST_SR_BP1 (1 << 3) /* Block Protection 1 */
  31. #define SST_SR_BP2 (1 << 4) /* Block Protection 2 */
  32. #define SST_SR_AAI (1 << 6) /* Addressing mode */
  33. #define SST_SR_BPL (1 << 7) /* BP bits lock */
  34. struct sst_spi_flash_params {
  35. u8 idcode1;
  36. u16 nr_sectors;
  37. const char *name;
  38. };
  39. struct sst_spi_flash {
  40. struct spi_flash flash;
  41. const struct sst_spi_flash_params *params;
  42. };
  43. static inline struct sst_spi_flash *to_sst_spi_flash(struct spi_flash *flash)
  44. {
  45. return container_of(flash, struct sst_spi_flash, flash);
  46. }
  47. #define SST_SECTOR_SIZE (4 * 1024)
  48. static const struct sst_spi_flash_params sst_spi_flash_table[] = {
  49. {
  50. .idcode1 = 0x8d,
  51. .nr_sectors = 128,
  52. .name = "SST25VF040B",
  53. },{
  54. .idcode1 = 0x8e,
  55. .nr_sectors = 256,
  56. .name = "SST25VF080B",
  57. },{
  58. .idcode1 = 0x41,
  59. .nr_sectors = 512,
  60. .name = "SST25VF016B",
  61. },{
  62. .idcode1 = 0x4a,
  63. .nr_sectors = 1024,
  64. .name = "SST25VF032B",
  65. },{
  66. .idcode1 = 0x01,
  67. .nr_sectors = 16,
  68. .name = "SST25WF512",
  69. },{
  70. .idcode1 = 0x02,
  71. .nr_sectors = 32,
  72. .name = "SST25WF010",
  73. },{
  74. .idcode1 = 0x03,
  75. .nr_sectors = 64,
  76. .name = "SST25WF020",
  77. },{
  78. .idcode1 = 0x04,
  79. .nr_sectors = 128,
  80. .name = "SST25WF040",
  81. },
  82. };
  83. static int
  84. sst_wait_ready(struct spi_flash *flash, unsigned long timeout)
  85. {
  86. struct spi_slave *spi = flash->spi;
  87. unsigned long timebase;
  88. int ret;
  89. u8 byte = CMD_SST_RDSR;
  90. ret = spi_xfer(spi, sizeof(byte) * 8, &byte, NULL, SPI_XFER_BEGIN);
  91. if (ret) {
  92. debug("SF: Failed to send command %02x: %d\n", byte, ret);
  93. return ret;
  94. }
  95. timebase = get_timer(0);
  96. do {
  97. ret = spi_xfer(spi, sizeof(byte) * 8, NULL, &byte, 0);
  98. if (ret)
  99. break;
  100. if ((byte & SST_SR_WIP) == 0)
  101. break;
  102. } while (get_timer(timebase) < timeout);
  103. spi_xfer(spi, 0, NULL, NULL, SPI_XFER_END);
  104. if (!ret && (byte & SST_SR_WIP) != 0)
  105. ret = -1;
  106. if (ret)
  107. debug("SF: sst wait for ready timed out\n");
  108. return ret;
  109. }
  110. static int
  111. sst_enable_writing(struct spi_flash *flash)
  112. {
  113. int ret = spi_flash_cmd(flash->spi, CMD_SST_WREN, NULL, 0);
  114. if (ret)
  115. debug("SF: Enabling Write failed\n");
  116. return ret;
  117. }
  118. static int
  119. sst_disable_writing(struct spi_flash *flash)
  120. {
  121. int ret = spi_flash_cmd(flash->spi, CMD_SST_WRDI, NULL, 0);
  122. if (ret)
  123. debug("SF: Disabling Write failed\n");
  124. return ret;
  125. }
  126. static int
  127. sst_read_fast(struct spi_flash *flash, u32 offset, size_t len, void *buf)
  128. {
  129. u8 cmd[5] = {
  130. CMD_READ_ARRAY_FAST,
  131. offset >> 16,
  132. offset >> 8,
  133. offset,
  134. 0x00,
  135. };
  136. return spi_flash_read_common(flash, cmd, sizeof(cmd), buf, len);
  137. }
  138. static int
  139. sst_byte_write(struct spi_flash *flash, u32 offset, const void *buf)
  140. {
  141. int ret;
  142. u8 cmd[4] = {
  143. CMD_SST_BP,
  144. offset >> 16,
  145. offset >> 8,
  146. offset,
  147. };
  148. debug("BP[%02x]: 0x%p => cmd = { 0x%02x 0x%06x }\n",
  149. spi_w8r8(flash->spi, CMD_SST_RDSR), buf, cmd[0], offset);
  150. ret = sst_enable_writing(flash);
  151. if (ret)
  152. return ret;
  153. ret = spi_flash_cmd_write(flash->spi, cmd, sizeof(cmd), buf, 1);
  154. if (ret)
  155. return ret;
  156. return sst_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
  157. }
  158. static int
  159. sst_write(struct spi_flash *flash, u32 offset, size_t len, const void *buf)
  160. {
  161. size_t actual, cmd_len;
  162. int ret;
  163. u8 cmd[4];
  164. ret = spi_claim_bus(flash->spi);
  165. if (ret) {
  166. debug("SF: Unable to claim SPI bus\n");
  167. return ret;
  168. }
  169. /* If the data is not word aligned, write out leading single byte */
  170. actual = offset % 2;
  171. if (actual) {
  172. ret = sst_byte_write(flash, offset, buf);
  173. if (ret)
  174. goto done;
  175. }
  176. offset += actual;
  177. ret = sst_enable_writing(flash);
  178. if (ret)
  179. goto done;
  180. cmd_len = 4;
  181. cmd[0] = CMD_SST_AAI_WP;
  182. cmd[1] = offset >> 16;
  183. cmd[2] = offset >> 8;
  184. cmd[3] = offset;
  185. for (; actual < len - 1; actual += 2) {
  186. debug("WP[%02x]: 0x%p => cmd = { 0x%02x 0x%06x }\n",
  187. spi_w8r8(flash->spi, CMD_SST_RDSR), buf + actual, cmd[0],
  188. offset);
  189. ret = spi_flash_cmd_write(flash->spi, cmd, cmd_len,
  190. buf + actual, 2);
  191. if (ret) {
  192. debug("SF: sst word program failed\n");
  193. break;
  194. }
  195. ret = sst_wait_ready(flash, SPI_FLASH_PROG_TIMEOUT);
  196. if (ret)
  197. break;
  198. cmd_len = 1;
  199. offset += 2;
  200. }
  201. if (!ret)
  202. ret = sst_disable_writing(flash);
  203. /* If there is a single trailing byte, write it out */
  204. if (!ret && actual != len)
  205. ret = sst_byte_write(flash, offset, buf + actual);
  206. done:
  207. debug("SF: sst: program %s %zu bytes @ 0x%zx\n",
  208. ret ? "failure" : "success", len, offset - actual);
  209. spi_release_bus(flash->spi);
  210. return ret;
  211. }
  212. int
  213. sst_erase(struct spi_flash *flash, u32 offset, size_t len)
  214. {
  215. unsigned long sector_size;
  216. u32 start, end;
  217. int ret;
  218. u8 cmd[4];
  219. /*
  220. * This function currently uses sector erase only.
  221. * Probably speed things up by using bulk erase
  222. * when possible.
  223. */
  224. sector_size = SST_SECTOR_SIZE;
  225. if (offset % sector_size) {
  226. debug("SF: Erase offset not multiple of sector size\n");
  227. return -1;
  228. }
  229. ret = spi_claim_bus(flash->spi);
  230. if (ret) {
  231. debug("SF: Unable to claim SPI bus\n");
  232. return ret;
  233. }
  234. cmd[0] = CMD_SST_SE;
  235. cmd[3] = 0;
  236. start = offset;
  237. end = start + len;
  238. ret = 0;
  239. while (offset < end) {
  240. cmd[1] = offset >> 16;
  241. cmd[2] = offset >> 8;
  242. offset += sector_size;
  243. debug("SF: erase %2x %2x %2x %2x (%x)\n", cmd[0], cmd[1],
  244. cmd[2], cmd[3], offset);
  245. ret = sst_enable_writing(flash);
  246. if (ret)
  247. break;
  248. ret = spi_flash_cmd_write(flash->spi, cmd, sizeof(cmd), NULL, 0);
  249. if (ret) {
  250. debug("SF: sst page erase failed\n");
  251. break;
  252. }
  253. ret = sst_wait_ready(flash, SPI_FLASH_PAGE_ERASE_TIMEOUT);
  254. if (ret)
  255. break;
  256. }
  257. debug("SF: sst: Successfully erased %lu bytes @ 0x%x\n",
  258. len * sector_size, start);
  259. spi_release_bus(flash->spi);
  260. return ret;
  261. }
  262. static int
  263. sst_unlock(struct spi_flash *flash)
  264. {
  265. int ret;
  266. u8 cmd, status;
  267. ret = sst_enable_writing(flash);
  268. if (ret)
  269. return ret;
  270. cmd = CMD_SST_WRSR;
  271. status = 0;
  272. ret = spi_flash_cmd_write(flash->spi, &cmd, 1, &status, 1);
  273. if (ret)
  274. debug("SF: Unable to set status byte\n");
  275. debug("SF: sst: status = %x\n", spi_w8r8(flash->spi, CMD_SST_RDSR));
  276. return ret;
  277. }
  278. struct spi_flash *
  279. spi_flash_probe_sst(struct spi_slave *spi, u8 *idcode)
  280. {
  281. const struct sst_spi_flash_params *params;
  282. struct sst_spi_flash *stm;
  283. size_t i;
  284. for (i = 0; i < ARRAY_SIZE(sst_spi_flash_table); ++i) {
  285. params = &sst_spi_flash_table[i];
  286. if (params->idcode1 == idcode[2])
  287. break;
  288. }
  289. if (i == ARRAY_SIZE(sst_spi_flash_table)) {
  290. debug("SF: Unsupported SST ID %02x\n", idcode[1]);
  291. return NULL;
  292. }
  293. stm = malloc(sizeof(*stm));
  294. if (!stm) {
  295. debug("SF: Failed to allocate memory\n");
  296. return NULL;
  297. }
  298. stm->params = params;
  299. stm->flash.spi = spi;
  300. stm->flash.name = params->name;
  301. stm->flash.write = sst_write;
  302. stm->flash.erase = sst_erase;
  303. stm->flash.read = sst_read_fast;
  304. stm->flash.size = SST_SECTOR_SIZE * params->nr_sectors;
  305. debug("SF: Detected %s with page size %u, total %u bytes\n",
  306. params->name, SST_SECTOR_SIZE, stm->flash.size);
  307. /* Flash powers up read-only, so clear BP# bits */
  308. sst_unlock(&stm->flash);
  309. return &stm->flash;
  310. }