0064-ramips-mtd-spi-nor-add-support-for-switching-between-3-byte-and-4-byte-addressing-on-w25q256-flash.patch 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456
  1. From: Vincent Wiemann <me@bibbl.com>
  2. Date: Sat, 6 Jan 2018 04:33:09 +0100
  3. Subject: ramips: mtd: spi-nor: add support for switching between 3-byte and 4-byte addressing on w25q256 flash
  4. CAUTION! NEEDS TESTING!
  5. Tries to backport switching between 3-byte and 4-byte addressing on w25q256 flash from Lede master (62ede4f78389c313a8004e79330a7d055eda2f7d) by Felix Fietkau.
  6. Applied patches:
  7. mtd: spi-nor: rename SPINOR_OP_* macros of the 4-byte address op codes
  8. mtd: spi-nor: add a stateless method to support memory size above 128Mib
  9. mtd: spi-nor: add w25q256 3b-mode-switch
  10. mtd: add chunked read-io to m25p80
  11. On some devices the flash chip needs to be in 3-byte addressing mode during
  12. reboot, otherwise the boot loader will fail to start.
  13. This mode however does not allow regular reads/writes onto the upper 16M
  14. half. W25Q256 has separate read commands for reading from >16M, however
  15. it does not have any separate write commands.
  16. This patch changes the code to leave the chip in 3-byte mode most of the
  17. time and only switch during erase/write cycles that go to >16M
  18. addresses.
  19. Signed-off-by: Vincent Wiemann (me@bibbl.com)
  20. diff --git a/target/linux/ramips/patches-4.4/400-mtd-spi-nor-add-w25q256-3b-mode-switch.patch b/target/linux/ramips/patches-4.4/400-mtd-spi-nor-add-w25q256-3b-mode-switch.patch
  21. new file mode 100644
  22. index 0000000000000000000000000000000000000000..5399f547e4edd0eb1cfee8c1ec5b35e69c692ee9
  23. --- /dev/null
  24. +++ b/target/linux/ramips/patches-4.4/400-mtd-spi-nor-add-w25q256-3b-mode-switch.patch
  25. @@ -0,0 +1,399 @@
  26. +--- a/drivers/mtd/devices/serial_flash_cmds.h
  27. ++++ b/drivers/mtd/devices/serial_flash_cmds.h
  28. +@@ -18,19 +18,12 @@
  29. + #define SPINOR_OP_RDVCR 0x85
  30. +
  31. + /* JEDEC Standard - Serial Flash Discoverable Parmeters (SFDP) Commands */
  32. +-#define SPINOR_OP_READ_1_2_2 0xbb /* DUAL I/O READ */
  33. +-#define SPINOR_OP_READ_1_4_4 0xeb /* QUAD I/O READ */
  34. +-
  35. + #define SPINOR_OP_WRITE 0x02 /* PAGE PROGRAM */
  36. + #define SPINOR_OP_WRITE_1_1_2 0xa2 /* DUAL INPUT PROGRAM */
  37. + #define SPINOR_OP_WRITE_1_2_2 0xd2 /* DUAL INPUT EXT PROGRAM */
  38. + #define SPINOR_OP_WRITE_1_1_4 0x32 /* QUAD INPUT PROGRAM */
  39. + #define SPINOR_OP_WRITE_1_4_4 0x12 /* QUAD INPUT EXT PROGRAM */
  40. +
  41. +-/* READ commands with 32-bit addressing */
  42. +-#define SPINOR_OP_READ4_1_2_2 0xbc
  43. +-#define SPINOR_OP_READ4_1_4_4 0xec
  44. +-
  45. + /* Configuration flags */
  46. + #define FLASH_FLAG_SINGLE 0x000000ff
  47. + #define FLASH_FLAG_READ_WRITE 0x00000001
  48. +--- a/drivers/mtd/devices/st_spi_fsm.c
  49. ++++ b/drivers/mtd/devices/st_spi_fsm.c
  50. +@@ -507,13 +507,13 @@ static struct seq_rw_config n25q_read3_c
  51. + * - 'FAST' variants configured for 8 dummy cycles (see note above.)
  52. + */
  53. + static struct seq_rw_config n25q_read4_configs[] = {
  54. +- {FLASH_FLAG_READ_1_4_4, SPINOR_OP_READ4_1_4_4, 0, 4, 4, 0x00, 0, 8},
  55. +- {FLASH_FLAG_READ_1_1_4, SPINOR_OP_READ4_1_1_4, 0, 1, 4, 0x00, 0, 8},
  56. +- {FLASH_FLAG_READ_1_2_2, SPINOR_OP_READ4_1_2_2, 0, 2, 2, 0x00, 0, 8},
  57. +- {FLASH_FLAG_READ_1_1_2, SPINOR_OP_READ4_1_1_2, 0, 1, 2, 0x00, 0, 8},
  58. +- {FLASH_FLAG_READ_FAST, SPINOR_OP_READ4_FAST, 0, 1, 1, 0x00, 0, 8},
  59. +- {FLASH_FLAG_READ_WRITE, SPINOR_OP_READ4, 0, 1, 1, 0x00, 0, 0},
  60. +- {0x00, 0, 0, 0, 0, 0x00, 0, 0},
  61. ++ {FLASH_FLAG_READ_1_4_4, SPINOR_OP_READ_1_4_4_4B, 0, 4, 4, 0x00, 0, 8},
  62. ++ {FLASH_FLAG_READ_1_1_4, SPINOR_OP_READ_1_1_4_4B, 0, 1, 4, 0x00, 0, 8},
  63. ++ {FLASH_FLAG_READ_1_2_2, SPINOR_OP_READ_1_2_2_4B, 0, 2, 2, 0x00, 0, 8},
  64. ++ {FLASH_FLAG_READ_1_1_2, SPINOR_OP_READ_1_1_2_4B, 0, 1, 2, 0x00, 0, 8},
  65. ++ {FLASH_FLAG_READ_FAST, SPINOR_OP_READ_FAST_4B, 0, 1, 1, 0x00, 0, 8},
  66. ++ {FLASH_FLAG_READ_WRITE, SPINOR_OP_READ_4B, 0, 1, 1, 0x00, 0, 0},
  67. ++ {0x00, 0, 0, 0, 0, 0x00, 0, 0},
  68. + };
  69. +
  70. + /*
  71. +@@ -553,13 +553,13 @@ static int stfsm_mx25_en_32bit_addr_seq(
  72. + * entering a state that is incompatible with the SPIBoot Controller.
  73. + */
  74. + static struct seq_rw_config stfsm_s25fl_read4_configs[] = {
  75. +- {FLASH_FLAG_READ_1_4_4, SPINOR_OP_READ4_1_4_4, 0, 4, 4, 0x00, 2, 4},
  76. +- {FLASH_FLAG_READ_1_1_4, SPINOR_OP_READ4_1_1_4, 0, 1, 4, 0x00, 0, 8},
  77. +- {FLASH_FLAG_READ_1_2_2, SPINOR_OP_READ4_1_2_2, 0, 2, 2, 0x00, 4, 0},
  78. +- {FLASH_FLAG_READ_1_1_2, SPINOR_OP_READ4_1_1_2, 0, 1, 2, 0x00, 0, 8},
  79. +- {FLASH_FLAG_READ_FAST, SPINOR_OP_READ4_FAST, 0, 1, 1, 0x00, 0, 8},
  80. +- {FLASH_FLAG_READ_WRITE, SPINOR_OP_READ4, 0, 1, 1, 0x00, 0, 0},
  81. +- {0x00, 0, 0, 0, 0, 0x00, 0, 0},
  82. ++ {FLASH_FLAG_READ_1_4_4, SPINOR_OP_READ_1_4_4_4B, 0, 4, 4, 0x00, 2, 4},
  83. ++ {FLASH_FLAG_READ_1_1_4, SPINOR_OP_READ_1_1_4_4B, 0, 1, 4, 0x00, 0, 8},
  84. ++ {FLASH_FLAG_READ_1_2_2, SPINOR_OP_READ_1_2_2_4B, 0, 2, 2, 0x00, 4, 0},
  85. ++ {FLASH_FLAG_READ_1_1_2, SPINOR_OP_READ_1_1_2_4B, 0, 1, 2, 0x00, 0, 8},
  86. ++ {FLASH_FLAG_READ_FAST, SPINOR_OP_READ_FAST_4B, 0, 1, 1, 0x00, 0, 8},
  87. ++ {FLASH_FLAG_READ_WRITE, SPINOR_OP_READ_4B, 0, 1, 1, 0x00, 0, 0},
  88. ++ {0x00, 0, 0, 0, 0, 0x00, 0, 0},
  89. + };
  90. +
  91. + static struct seq_rw_config stfsm_s25fl_write4_configs[] = {
  92. +--- a/drivers/mtd/spi-nor/spi-nor.c
  93. ++++ b/drivers/mtd/spi-nor/spi-nor.c
  94. +@@ -69,6 +69,14 @@ struct flash_info {
  95. + #define SPI_NOR_QUAD_READ 0x40 /* Flash supports Quad Read */
  96. + #define USE_FSR 0x80 /* use flag status register */
  97. + #define SPI_NOR_HAS_LOCK 0x100 /* Flash supports lock/unlock via SR */
  98. ++#define SPI_NOR_4B_OPCODES 0x200 /*
  99. ++ * Use dedicated 4byte address op codes
  100. ++ * to support memory size above 128Mib.
  101. ++ */
  102. ++#define SPI_NOR_4B_READ_OP 0x400 /*
  103. ++ * Like SPI_NOR_4B_OPCODES, but for read
  104. ++ * op code only.
  105. ++ */
  106. + };
  107. +
  108. + #define JEDEC_MFR(info) ((info)->id[0])
  109. +@@ -182,6 +190,89 @@ static inline struct spi_nor *mtd_to_spi
  110. + return mtd->priv;
  111. + }
  112. +
  113. ++
  114. ++static u8 spi_nor_convert_opcode(u8 opcode, const u8 table[][2], size_t size)
  115. ++{
  116. ++ size_t i;
  117. ++
  118. ++ for (i = 0; i < size; i++)
  119. ++ if (table[i][0] == opcode)
  120. ++ return table[i][1];
  121. ++
  122. ++ /* No conversion found, keep input op code. */
  123. ++ return opcode;
  124. ++}
  125. ++
  126. ++static inline u8 spi_nor_convert_3to4_read(u8 opcode)
  127. ++{
  128. ++ static const u8 spi_nor_3to4_read[][2] = {
  129. ++ { SPINOR_OP_READ, SPINOR_OP_READ_4B },
  130. ++ { SPINOR_OP_READ_FAST, SPINOR_OP_READ_FAST_4B },
  131. ++ { SPINOR_OP_READ_1_1_2, SPINOR_OP_READ_1_1_2_4B },
  132. ++ { SPINOR_OP_READ_1_2_2, SPINOR_OP_READ_1_2_2_4B },
  133. ++ { SPINOR_OP_READ_1_1_4, SPINOR_OP_READ_1_1_4_4B },
  134. ++ { SPINOR_OP_READ_1_4_4, SPINOR_OP_READ_1_4_4_4B },
  135. ++ };
  136. ++
  137. ++ return spi_nor_convert_opcode(opcode, spi_nor_3to4_read,
  138. ++ ARRAY_SIZE(spi_nor_3to4_read));
  139. ++}
  140. ++
  141. ++static inline u8 spi_nor_convert_3to4_program(u8 opcode)
  142. ++{
  143. ++ static const u8 spi_nor_3to4_program[][2] = {
  144. ++ { SPINOR_OP_PP, SPINOR_OP_PP_4B },
  145. ++ { SPINOR_OP_PP_1_1_4, SPINOR_OP_PP_1_1_4_4B },
  146. ++ { SPINOR_OP_PP_1_4_4, SPINOR_OP_PP_1_4_4_4B },
  147. ++ };
  148. ++
  149. ++ return spi_nor_convert_opcode(opcode, spi_nor_3to4_program,
  150. ++ ARRAY_SIZE(spi_nor_3to4_program));
  151. ++}
  152. ++
  153. ++static inline u8 spi_nor_convert_3to4_erase(u8 opcode)
  154. ++{
  155. ++ static const u8 spi_nor_3to4_erase[][2] = {
  156. ++ { SPINOR_OP_BE_4K, SPINOR_OP_BE_4K_4B },
  157. ++ { SPINOR_OP_BE_32K, SPINOR_OP_BE_32K_4B },
  158. ++ { SPINOR_OP_SE, SPINOR_OP_SE_4B },
  159. ++ };
  160. ++
  161. ++ return spi_nor_convert_opcode(opcode, spi_nor_3to4_erase,
  162. ++ ARRAY_SIZE(spi_nor_3to4_erase));
  163. ++}
  164. ++
  165. ++static void spi_nor_set_4byte_read(struct spi_nor *nor,
  166. ++ const struct flash_info *info)
  167. ++{
  168. ++ nor->addr_width = 3;
  169. ++ nor->ext_addr = 0;
  170. ++ nor->read_opcode = spi_nor_convert_3to4_read(nor->read_opcode);
  171. ++ nor->flags |= SNOR_F_4B_EXT_ADDR;
  172. ++}
  173. ++
  174. ++
  175. ++
  176. ++static void spi_nor_set_4byte_opcodes(struct spi_nor *nor,
  177. ++ const struct flash_info *info)
  178. ++{
  179. ++ /* Do some manufacturer fixups first */
  180. ++ switch (JEDEC_MFR(info)) {
  181. ++ case SNOR_MFR_SPANSION:
  182. ++ /* No small sector erase for 4-byte command set */
  183. ++ nor->erase_opcode = SPINOR_OP_SE;
  184. ++ nor->mtd.erasesize = info->sector_size;
  185. ++ break;
  186. ++
  187. ++ default:
  188. ++ break;
  189. ++ }
  190. ++
  191. ++ nor->read_opcode = spi_nor_convert_3to4_read(nor->read_opcode);
  192. ++ nor->program_opcode = spi_nor_convert_3to4_program(nor->program_opcode);
  193. ++ nor->erase_opcode = spi_nor_convert_3to4_erase(nor->erase_opcode);
  194. ++}
  195. ++
  196. + /* Enable/disable 4-byte addressing mode. */
  197. + static inline int set_4byte(struct spi_nor *nor, const struct flash_info *info,
  198. + int enable)
  199. +@@ -313,6 +404,36 @@ static void spi_nor_unlock_and_unprep(st
  200. + mutex_unlock(&nor->lock);
  201. + }
  202. +
  203. ++static int spi_nor_check_ext_addr(struct spi_nor *nor, u32 addr)
  204. ++{
  205. ++ bool ext_addr;
  206. ++ int ret;
  207. ++ u8 cmd;
  208. ++
  209. ++ if (!(nor->flags & SNOR_F_4B_EXT_ADDR))
  210. ++ return 0;
  211. ++
  212. ++ ext_addr = !!(addr & 0xff000000);
  213. ++ if (nor->ext_addr == ext_addr)
  214. ++ return 0;
  215. ++
  216. ++ cmd = ext_addr ? SPINOR_OP_EN4B : SPINOR_OP_EX4B;
  217. ++ write_enable(nor);
  218. ++ ret = nor->write_reg(nor, cmd, NULL, 0);
  219. ++ if (ret)
  220. ++ return ret;
  221. ++
  222. ++ cmd = 0;
  223. ++ ret = nor->write_reg(nor, SPINOR_OP_WREAR, &cmd, 1);
  224. ++ if (ret)
  225. ++ return ret;
  226. ++
  227. ++ nor->addr_width = 3 + ext_addr;
  228. ++ nor->ext_addr = ext_addr;
  229. ++ write_disable(nor);
  230. ++ return 0;
  231. ++}
  232. ++
  233. + /*
  234. + * Erase an address range on the nor chip. The address range may extend
  235. + * one or more erase sectors. Return an error is there is a problem erasing.
  236. +@@ -338,6 +459,10 @@ static int spi_nor_erase(struct mtd_info
  237. + if (ret)
  238. + return ret;
  239. +
  240. ++ ret = spi_nor_check_ext_addr(nor, addr + len);
  241. ++ if (ret)
  242. ++ return ret;
  243. ++
  244. + /* whole-chip erase? */
  245. + if (len == mtd->size) {
  246. + unsigned long timeout;
  247. +@@ -396,6 +521,7 @@ static int spi_nor_erase(struct mtd_info
  248. + return ret;
  249. +
  250. + erase_err:
  251. ++ spi_nor_check_ext_addr(nor, 0);
  252. + spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_ERASE);
  253. + instr->state = MTD_ERASE_FAILED;
  254. + return ret;
  255. +@@ -585,7 +711,9 @@ static int spi_nor_lock(struct mtd_info
  256. + if (ret)
  257. + return ret;
  258. +
  259. ++ spi_nor_check_ext_addr(nor, ofs + len);
  260. + ret = nor->flash_lock(nor, ofs, len);
  261. ++ spi_nor_check_ext_addr(nor, 0);
  262. +
  263. + spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_UNLOCK);
  264. + return ret;
  265. +@@ -600,7 +728,9 @@ static int spi_nor_unlock(struct mtd_inf
  266. + if (ret)
  267. + return ret;
  268. +
  269. ++ spi_nor_check_ext_addr(nor, ofs + len);
  270. + ret = nor->flash_unlock(nor, ofs, len);
  271. ++ spi_nor_check_ext_addr(nor, 0);
  272. +
  273. + spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_LOCK);
  274. + return ret;
  275. +@@ -851,7 +981,7 @@ static const struct flash_info spi_nor_i
  276. + { "w25q80", INFO(0xef5014, 0, 64 * 1024, 16, SECT_4K) },
  277. + { "w25q80bl", INFO(0xef4014, 0, 64 * 1024, 16, SECT_4K) },
  278. + { "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, SECT_4K) },
  279. +- { "w25q256", INFO(0xef4019, 0, 64 * 1024, 512, SECT_4K) },
  280. ++ { "w25q256", INFO(0xef4019, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_4B_READ_OP) },
  281. +
  282. + /* Catalyst / On Semiconductor -- non-JEDEC */
  283. + { "cat25c11", CAT25_INFO( 16, 8, 16, 1, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
  284. +@@ -898,8 +1028,23 @@ static int spi_nor_read(struct mtd_info
  285. + if (ret)
  286. + return ret;
  287. +
  288. ++ if (nor->flags & SNOR_F_4B_EXT_ADDR)
  289. ++ nor->addr_width = 4;
  290. ++
  291. + ret = nor->read(nor, from, len, retlen, buf);
  292. +
  293. ++ if (nor->flags & SNOR_F_4B_EXT_ADDR) {
  294. ++ u8 val = 0;
  295. ++
  296. ++ if ((from + len) & 0xff000000) {
  297. ++ write_enable(nor);
  298. ++ nor->write_reg(nor, SPINOR_OP_WREAR, &val, 1);
  299. ++ write_disable(nor);
  300. ++ }
  301. ++
  302. ++ nor->addr_width = 3;
  303. ++ }
  304. ++
  305. + spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_READ);
  306. + return ret;
  307. + }
  308. +@@ -988,6 +1133,10 @@ static int spi_nor_write(struct mtd_info
  309. + if (ret)
  310. + return ret;
  311. +
  312. ++ ret = spi_nor_check_ext_addr(nor, to + len);
  313. ++ if (ret < 0)
  314. ++ return ret;
  315. ++
  316. + write_enable(nor);
  317. +
  318. + page_offset = to & (nor->page_size - 1);
  319. +@@ -1018,6 +1167,7 @@ static int spi_nor_write(struct mtd_info
  320. +
  321. + ret = spi_nor_wait_till_ready(nor);
  322. + write_err:
  323. ++ spi_nor_check_ext_addr(nor, 0);
  324. + spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_WRITE);
  325. + return ret;
  326. + }
  327. +@@ -1366,27 +1516,12 @@ int spi_nor_scan(struct spi_nor *nor, co
  328. + else if (mtd->size > 0x1000000) {
  329. + /* enable 4-byte addressing if the device exceeds 16MiB */
  330. + nor->addr_width = 4;
  331. +- if (JEDEC_MFR(info) == SNOR_MFR_SPANSION) {
  332. +- /* Dedicated 4-byte command set */
  333. +- switch (nor->flash_read) {
  334. +- case SPI_NOR_QUAD:
  335. +- nor->read_opcode = SPINOR_OP_READ4_1_1_4;
  336. +- break;
  337. +- case SPI_NOR_DUAL:
  338. +- nor->read_opcode = SPINOR_OP_READ4_1_1_2;
  339. +- break;
  340. +- case SPI_NOR_FAST:
  341. +- nor->read_opcode = SPINOR_OP_READ4_FAST;
  342. +- break;
  343. +- case SPI_NOR_NORMAL:
  344. +- nor->read_opcode = SPINOR_OP_READ4;
  345. +- break;
  346. +- }
  347. +- nor->program_opcode = SPINOR_OP_PP_4B;
  348. +- /* No small sector erase for 4-byte command set */
  349. +- nor->erase_opcode = SPINOR_OP_SE_4B;
  350. +- mtd->erasesize = info->sector_size;
  351. +- } else
  352. ++ if (info->flags & SPI_NOR_4B_READ_OP)
  353. ++ spi_nor_set_4byte_read(nor, info);
  354. ++ else if (JEDEC_MFR(info) == SNOR_MFR_SPANSION ||
  355. ++ info->flags & SPI_NOR_4B_OPCODES)
  356. ++ spi_nor_set_4byte_opcodes(nor, info);
  357. ++ else
  358. + set_4byte(nor, info, 1);
  359. + } else {
  360. + nor->addr_width = 3;
  361. +--- a/include/linux/mtd/spi-nor.h
  362. ++++ b/include/linux/mtd/spi-nor.h
  363. +@@ -42,9 +42,13 @@
  364. + #define SPINOR_OP_WRSR 0x01 /* Write status register 1 byte */
  365. + #define SPINOR_OP_READ 0x03 /* Read data bytes (low frequency) */
  366. + #define SPINOR_OP_READ_FAST 0x0b /* Read data bytes (high frequency) */
  367. +-#define SPINOR_OP_READ_1_1_2 0x3b /* Read data bytes (Dual SPI) */
  368. +-#define SPINOR_OP_READ_1_1_4 0x6b /* Read data bytes (Quad SPI) */
  369. ++#define SPINOR_OP_READ_1_1_2 0x3b /* Read data bytes (Dual Output SPI) */
  370. ++#define SPINOR_OP_READ_1_2_2 0xbb /* Read data bytes (Dual I/O SPI) */
  371. ++#define SPINOR_OP_READ_1_1_4 0x6b /* Read data bytes (Quad Output SPI) */
  372. ++#define SPINOR_OP_READ_1_4_4 0xeb /* Read data bytes (Quad I/O SPI) */
  373. + #define SPINOR_OP_PP 0x02 /* Page program (up to 256 bytes) */
  374. ++#define SPINOR_OP_PP_1_1_4 0x32 /* Quad page program */
  375. ++#define SPINOR_OP_PP_1_4_4 0x38 /* Quad page program */
  376. + #define SPINOR_OP_BE_4K 0x20 /* Erase 4KiB block */
  377. + #define SPINOR_OP_BE_4K_PMC 0xd7 /* Erase 4KiB block on PMC chips */
  378. + #define SPINOR_OP_BE_32K 0x52 /* Erase 32KiB block */
  379. +@@ -55,11 +59,17 @@
  380. + #define SPINOR_OP_RDFSR 0x70 /* Read flag status register */
  381. +
  382. + /* 4-byte address opcodes - used on Spansion and some Macronix flashes. */
  383. +-#define SPINOR_OP_READ4 0x13 /* Read data bytes (low frequency) */
  384. +-#define SPINOR_OP_READ4_FAST 0x0c /* Read data bytes (high frequency) */
  385. +-#define SPINOR_OP_READ4_1_1_2 0x3c /* Read data bytes (Dual SPI) */
  386. +-#define SPINOR_OP_READ4_1_1_4 0x6c /* Read data bytes (Quad SPI) */
  387. ++#define SPINOR_OP_READ_4B 0x13 /* Read data bytes (low frequency) */
  388. ++#define SPINOR_OP_READ_FAST_4B 0x0c /* Read data bytes (high frequency) */
  389. ++#define SPINOR_OP_READ_1_1_2_4B 0x3c /* Read data bytes (Dual Output SPI) */
  390. ++#define SPINOR_OP_READ_1_2_2_4B 0xbc /* Read data bytes (Dual I/O SPI) */
  391. ++#define SPINOR_OP_READ_1_1_4_4B 0x6c /* Read data bytes (Quad Output SPI) */
  392. ++#define SPINOR_OP_READ_1_4_4_4B 0xec /* Read data bytes (Quad I/O SPI) */
  393. + #define SPINOR_OP_PP_4B 0x12 /* Page program (up to 256 bytes) */
  394. ++#define SPINOR_OP_PP_1_1_4_4B 0x34 /* Quad page program */
  395. ++#define SPINOR_OP_PP_1_4_4_4B 0x3e /* Quad page program */
  396. ++#define SPINOR_OP_BE_4K_4B 0x21 /* Erase 4KiB block */
  397. ++#define SPINOR_OP_BE_32K_4B 0x5c /* Erase 32KiB block */
  398. + #define SPINOR_OP_SE_4B 0xdc /* Sector erase (usually 64KiB) */
  399. +
  400. + /* Used for SST flashes only. */
  401. +@@ -70,6 +80,7 @@
  402. + /* Used for Macronix and Winbond flashes. */
  403. + #define SPINOR_OP_EN4B 0xb7 /* Enter 4-byte mode */
  404. + #define SPINOR_OP_EX4B 0xe9 /* Exit 4-byte mode */
  405. ++#define SPINOR_OP_WREAR 0xc5 /* Write extended address register */
  406. +
  407. + /* Used for Spansion flashes only. */
  408. + #define SPINOR_OP_BRWR 0x17 /* Bank register write */
  409. +@@ -117,6 +128,7 @@ enum spi_nor_ops {
  410. + enum spi_nor_option_flags {
  411. + SNOR_F_USE_FSR = BIT(0),
  412. + SNOR_F_SST = BIT(1),
  413. ++ SNOR_F_4B_EXT_ADDR = BIT(5),
  414. + };
  415. +
  416. + /**
  417. +@@ -166,6 +178,7 @@ struct spi_nor {
  418. + enum read_mode flash_read;
  419. + bool sst_write_second;
  420. + u32 flags;
  421. ++ u8 ext_addr;
  422. + u8 cmd_buf[SPI_NOR_MAX_CMD_SIZE];
  423. +
  424. + int (*prepare)(struct spi_nor *nor, enum spi_nor_ops ops);
  425. diff --git a/target/linux/ramips/patches-4.4/401-mtd-add-chunked-read-io-to-m25p80.patch b/target/linux/ramips/patches-4.4/401-mtd-add-chunked-read-io-to-m25p80.patch
  426. new file mode 100644
  427. index 0000000000000000000000000000000000000000..b6111abad7063951c07688c66854fa743daeb6c6
  428. --- /dev/null
  429. +++ b/target/linux/ramips/patches-4.4/401-mtd-add-chunked-read-io-to-m25p80.patch
  430. @@ -0,0 +1,21 @@
  431. +--- a/drivers/mtd/spi-nor/spi-nor.c
  432. ++++ b/drivers/mtd/spi-nor/spi-nor.c
  433. +@@ -1176,6 +1176,7 @@ static int spi_nor_chunked_write(struct
  434. + size_t *_retlen, const u_char *_buf)
  435. + {
  436. + struct spi_nor *nor = mtd_to_spi_nor(mtd);
  437. ++ u32 addr_width = nor->addr_width + !!(nor->flags & SNOR_F_4B_EXT_ADDR);
  438. + int chunk_size;
  439. + int retlen = 0;
  440. + int ret;
  441. +@@ -1184,8 +1185,8 @@ static int spi_nor_chunked_write(struct
  442. + if (!chunk_size)
  443. + chunk_size = _len;
  444. +
  445. +- if (nor->addr_width > 3)
  446. +- chunk_size -= nor->addr_width - 3;
  447. ++ if (addr_width > 3)
  448. ++ chunk_size -= addr_width - 3;
  449. +
  450. + while (retlen < _len) {
  451. + size_t len = min_t(int, chunk_size, _len - retlen);