spi_probe.c 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. /* SPDX-License-Identifier: GPL-2.0-or-later */
  2. /**
  3. ******************************************************************************
  4. * @file spi_probe.c
  5. * @author StarFive Technology
  6. * @version V1.0
  7. * @date 06/25/2020
  8. * @brief
  9. ******************************************************************************
  10. * @copy
  11. *
  12. * THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
  13. * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
  14. * TIME. AS A RESULT, STARFIVE SHALL NOT BE HELD LIABLE FOR ANY
  15. * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
  16. * FROM THE CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
  17. * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
  18. *
  19. * COPYRIGHT 2020 Shanghai StarFive Technology Co., Ltd.
  20. */
  21. #include <comdef.h>
  22. #include <spi_flash.h>
  23. #include <spi_flash_internal.h>
  24. #include <spi.h>
  25. #include <uart.h>
  26. #define IDCODE_CONT_LEN 0
  27. #define IDCODE_PART_LEN 3
  28. #define IDCODE_LEN (IDCODE_CONT_LEN + IDCODE_PART_LEN)
  29. #define CMD_READ_ID 0x9f
  30. #define NOR 0
  31. #define GIGANAND 1
  32. //#define CONFIG_SPI_FLASH_ATMEL
  33. //#define CONFIG_SPI_FLASH_GIGADEVICE
  34. //#define CONFIG_SPI_FLASH_EON
  35. //#define CONFIG_SPI_FLASH_MACRONIX
  36. //#define CONFIG_SPI_FLASH_SPANSION
  37. //#define CONFIG_SPI_FLASH_STMICRO
  38. //#define CONFIG_SPI_FLASH_SST
  39. //#define CONFIG_SPI_FLASH_WINBOND
  40. //#define TEST_GD25Q64B
  41. //#define TEST_GD25Q64C
  42. //#define TEST_GD25LB64C
  43. static struct spi_flash g_spi_flash[1];
  44. static const struct spi_flash_params spi_flash_table[] =
  45. {
  46. #ifdef CONFIG_SPI_FLASH_ATMEL /* ATMEL */
  47. {"AT45DB011D", 0x00221f,8,16,16,4,NOR},
  48. {"AT45DB021D", 0x00231f,8,16,16,8,NOR},
  49. {"AT45DB041D", 0x00241f,8,16,16,8,NOR},
  50. {"AT45DB081D", 0x00251f,8,16,16,16,NOR},
  51. {"AT45DB161D", 0x00261f,8,16,16,32,NOR},
  52. {"AT45DB321D", 0x00271f,8,16,16,64,NOR},
  53. {"AT45DB641D", 0x00281f,8,16,16,128,NOR},
  54. {"AT25DF161", 0x01461f,8,16,16,32,NOR},
  55. {"AT25DF321", 0x01471f,8,16,16,64,NOR},
  56. #endif
  57. #ifdef CONFIG_SPI_FLASH_EON /* EON */
  58. {"EN25Q64", 0x17301c,8,16,16,128,NOR},
  59. #endif
  60. #ifdef CONFIG_SPI_FLASH_GIGADEVICE /* GIGADEVICE */
  61. #ifdef TEST_GD25Q64B
  62. {"GD25Q64B", 0x1740c8,8,16,16,128,NOR},
  63. #endif
  64. #ifdef TEST_GD25Q64C
  65. {"GD25Q64C", 0x1740c8,8,16,16,128,NOR},
  66. {"GD25Q64C---", 0x1740D8,8,16,16,128,NOR},
  67. #endif
  68. {"GD25LQ32", 0x1660c8,8,16,16,64,NOR},
  69. {"GD5F1GQ4UAYIG", 0xc8f1c8,11,64,0,1024,GIGANAND},
  70. #endif
  71. #ifdef CONFIG_SPI_FLASH_MACRONIX /* MACRONIX */
  72. {"MX25L2006E", 0x1220c2,8,16,16,4,NOR},
  73. {"MX25L4005", 0x1320c2,8,16,16,8,NOR},
  74. {"MX25L8005", 0x1420c2,8,16,16,16,NOR},
  75. {"MX25L1605D", 0x1520c2,8,16,16,32,NOR},
  76. {"MX25L3205D", 0x1620c2,8,16,16,64,NOR},
  77. {"MX25L6405D", 0x1720c2,8,16,16,128,NOR},
  78. {"MX25L12805", 0x1820c2,8,16,16,256,NOR},
  79. {"MX25L25635F", 0x1920c2,8,16,16,512,NOR},
  80. {"MX25L51235F", 0x1a20c2,8,16,16,1024,NOR},
  81. {"MX25L12855E", 0x1826c2,8,16,16,256,NOR},
  82. #endif
  83. #ifdef CONFIG_SPI_FLASH_SPANSION /* SPANSION */
  84. {"S25FL008A", 0x130201, 8,16,16, 16,NOR},
  85. {"S25FL016A", 0x140201, 8,16,16, 32,NOR},
  86. {"S25FL032A", 0x150201, 8,16,16, 64,NOR},
  87. {"S25FL064A", 0x160201, 8,16,16, 128,NOR},
  88. #endif
  89. #ifdef CONFIG_SPI_FLASH_STMICRO /* STMICRO */
  90. {"M25P10", 0x112020, 8,16,8, 4,NOR},
  91. {"M25P20", 0x122020, 8,16,16, 4,NOR},
  92. {"M25P40", 0x132020, 8,16,16, 8,NOR},
  93. {"M25P80", 0x142020, 8,16,16, 16,NOR},
  94. {"M25P16", 0x152020, 8,16,16, 32,NOR},
  95. {"M25P32", 0x162020, 8,16,16, 64,NOR},
  96. {"M25P64", 0x172020, 8,16,16, 128,NOR},
  97. {"M25P128", 0x182020, 8,16,32, 64,NOR},
  98. {"N25Q32", 0x16ba20, 8,16,16, 64,NOR},
  99. {"N25Q32A", 0x16bb20, 8,16,16, 64,NOR},
  100. {"N25Q64", 0x17ba20, 8,16,16, 128,NOR},
  101. {"N25Q64A", 0x17bb20, 8,16,16, 128,NOR},
  102. {"N25Q128", 0x18ba20, 8,16,16, 256,NOR},
  103. {"N25Q128A", 0x18bb20, 8,16,16, 256,NOR},
  104. {"N25Q256", 0x19ba20, 8,16,16, 512,NOR},
  105. {"N25Q256A", 0x19bb20, 8,16,16, 512,NOR},
  106. {"N25Q512", 0x20ba20, 8,16,16, 1024,NOR},
  107. {"N25Q512A", 0x20bb20, 8,16,16, 1024,NOR},
  108. {"N25Q1024", 0x21ba20, 8,16,16, 2048,NOR},
  109. {"N25Q1024A", 0x21bb20, 8,16,16,2048,NOR},
  110. #endif
  111. #ifdef CONFIG_SPI_FLASH_SST /* SST */
  112. {"SST25VF040B", 0x8d25bf, 8,16,16, 8,NOR},
  113. {"SST25VF080B", 0x8e25bf, 8,16,16, 16,NOR},
  114. {"SST25VF016B", 0x4125bf, 8,16,16, 32,NOR},
  115. {"SST25VF032B", 0x4a25bf, 8,16,16, 64,NOR},
  116. {"SST25VF064C", 0x4b25bf, 8,16,16, 128,NOR},
  117. {"SST25WF512", 0x0125bf, 8,16,16, 1,NOR},
  118. {"SST25WF010", 0x0225bf, 8,16,16, 2,NOR},
  119. {"SST25WF020", 0x0325bf, 8,16,16, 4,NOR},
  120. {"SST25WF040", 0x0425bf, 8,16,16, 8,NOR},
  121. {"SST25WF080", 0x0525bf, 8,16,16, 16,NOR},
  122. #endif
  123. #ifdef CONFIG_SPI_FLASH_WINBOND /* WINBOND */
  124. {"W25P80", 0x1420ef, 8,16,16, 16,NOR},
  125. {"W25P16", 0x1520ef, 8,16,16, 32,NOR},
  126. {"W25P32", 0x1620ef, 8,16,16, 64,NOR},
  127. {"W25X40", 0x1330ef, 8,16,16, 8,NOR},
  128. {"W25X16", 0x1530ef, 8,16,16, 32,NOR},
  129. {"W25X32", 0x1630ef, 8,16,16, 64,NOR},
  130. {"W25X64", 0x1730ef, 8,16,16, 128,NOR},
  131. {"W25Q80BL", 0x1440ef, 8,16,16, 16,NOR},
  132. {"W25Q16CL", 0x1540ef, 8,16,16, 32,NOR},
  133. {"W25Q32BV", 0x1640ef, 8,16,16, 64,NOR},
  134. {"W25Q64CV", 0x1740ef, 8,16,16, 128,NOR},
  135. {"W25Q128BV", 0x1840ef, 8,16,16, 256,NOR},
  136. {"W25Q256", 0x1940ef, 8,16,16, 512,NOR},
  137. {"W25Q80BW", 0x1450ef, 8,16,16, 16,NOR},
  138. {"W25Q16DW", 0x1560ef, 8,16,16, 32,NOR},
  139. {"W25Q32DW", 0x1660ef, 8,16,16, 64,NOR},
  140. {"W25Q64DW", 0x1760ef, 8,16,16, 128,NOR},
  141. {"W25Q128FW", 0x1860ef, 8,16,16, 256,NOR},
  142. {"W25Q256FW", 0x1940ef, 8,16,16, 256,NOR},
  143. #endif
  144. //{"EN25QH16", 0x15701c, 8,16,16,32, NOR},
  145. //{"IS25WP256D", 0x19609d, 8,16,16,256, NOR},
  146. //{"MT25QL256ABA", 0x19ba20, 8,16,16,256, NOR},
  147. //{"GD25LB64C", 0x1760C8, 8,16,16,256, NOR},
  148. {"S25FL512S_512K", 0x200201, 8,16,64,256, NOR},
  149. {"GD25LQ256D", 0x1960C8, 8,16,16,512, NOR},
  150. {"GD25LQ128", 0x1960C8, 8,16,16,256, NOR}
  151. //{"GD25LB64B", 0xC86017, 8,16,16,256, NOR},
  152. //{"NORMAL", 0x000000, 8,16,16, 1, NOR},
  153. };
  154. struct spi_flash *spi_flash_probe_nor(struct spi_slave *spi, u8 *idcode)
  155. {
  156. struct spi_flash_params *params;
  157. struct spi_flash *flash;
  158. u32 id = 0;
  159. static int i = 0;
  160. id = ((idcode[2] << 16) | (idcode[1] << 8) | idcode[0]);
  161. if(id == 0x0)
  162. {
  163. return NULL;
  164. }
  165. params = spi_flash_table;
  166. for (i = 0; spi_flash_table[i].name != NULL; i++)
  167. {
  168. if ((spi_flash_table[i].id & 0xFFFFFF) == id)
  169. {
  170. break;
  171. }
  172. }
  173. flash = &g_spi_flash[spi->bus];
  174. if (!flash)
  175. {
  176. //uart_printf("SF: Failed to allocate memory\r\n");
  177. return NULL;
  178. }
  179. flash->name = spi_flash_table[i].name;
  180. if(spi_flash_table[i].flags == NOR)
  181. {
  182. /* Assuming power-of-two page size initially. */
  183. flash->write = spi_flash_cmd_write_mode;
  184. flash->erase = spi_flash_erase_mode;
  185. flash->read = spi_flash_read_mode;
  186. flash->page_size = 1 << spi_flash_table[i].l2_page_size;
  187. flash->sector_size = flash->page_size * spi_flash_table[i].pages_per_sector;
  188. flash->block_size = flash->sector_size * spi_flash_table[i].sectors_per_block;
  189. flash->size = flash->page_size * spi_flash_table[i].pages_per_sector
  190. * spi_flash_table[i].sectors_per_block
  191. * spi_flash_table[i].nr_blocks;
  192. }
  193. //uart_printf("spi probe complete\r\n");
  194. return flash;
  195. }
  196. #if 0
  197. static int print_id(u8 *idcode, int len)
  198. {
  199. int i;
  200. uart_printf("idcode:0x");
  201. for (i=len-1; i>=0; i--)
  202. print_ubyte_hex(idcode[i]);
  203. uart_printf("\r\n");
  204. return 0;
  205. }
  206. #endif
  207. static int spi_read_id(struct spi_slave *spi, unsigned char cmd, void *response, u32 len)
  208. {
  209. int ret1 = -1,ret2 = -1;
  210. unsigned char buf[4] = {0};// = {(u8)cmd, 0x00, 0x00, 0x00};
  211. buf[0] = cmd;
  212. buf[1] = 0;
  213. buf[2] = 0;
  214. buf[3] = 0;
  215. ret1 = spi_xfer(spi, 1*8, &buf[0], NULL, SPI_XFER_BEGIN, 8);
  216. ret2 = spi_xfer(spi, len*8, NULL, response, SPI_XFER_END, 8);
  217. return 0;
  218. }
  219. static struct spi_flash aic_flash;
  220. struct spi_flash *spi_flash_probe(unsigned int bus, unsigned int cs,
  221. unsigned int max_hz, unsigned int mode, unsigned int bus_width)
  222. {
  223. struct spi_slave *spi;
  224. struct spi_flash *flash = &aic_flash;
  225. int ret = 0;
  226. u8 idcode[IDCODE_LEN];
  227. spi = spi_setup_slave(bus, cs, max_hz, mode, bus_width);
  228. if (!spi) {
  229. //uart_printf("SF: Failed to set up slave\n");
  230. return NULL;
  231. }
  232. /* Read the ID codes */
  233. ret = spi_read_id(spi, CMD_READ_ID, idcode, sizeof(idcode));
  234. if (ret)
  235. {
  236. //uart_printf("SF: Failed to read ID : %d\n", ret);
  237. goto err_read_id;
  238. }
  239. //print_id(idcode, sizeof(idcode));
  240. flash = spi_flash_probe_nor(spi,idcode);
  241. if (!flash)
  242. {
  243. goto err_manufacturer_probe;
  244. }
  245. flash->spi = spi;
  246. return flash;
  247. err_manufacturer_probe:
  248. err_read_id:
  249. return NULL;
  250. }