1087-mtd-spi-nor-fsl-quadspi-add-big-endian-support.patch 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  1. From c58b398221d88ac0db29c3bb7522a4f48dfa102c Mon Sep 17 00:00:00 2001
  2. From: Yuan Yao <yao.yuan@freescale.com>
  3. Date: Tue, 17 Nov 2015 16:13:47 +0800
  4. Subject: [PATCH 087/113] mtd: spi-nor: fsl-quadspi: add big-endian support
  5. Add R/W functions for big- or little-endian registers:
  6. The qSPI controller's endian is independent of the CPU core's endian.
  7. So far, the qSPI have two versions for big-endian and little-endian.
  8. Signed-off-by: Yuan Yao <yao.yuan@nxp.com>
  9. Acked-by: Han xu <han.xu@freescale.com>
  10. ---
  11. drivers/mtd/spi-nor/fsl-quadspi.c | 157 +++++++++++++++++++++++--------------
  12. 1 file changed, 97 insertions(+), 60 deletions(-)
  13. --- a/drivers/mtd/spi-nor/fsl-quadspi.c
  14. +++ b/drivers/mtd/spi-nor/fsl-quadspi.c
  15. @@ -275,6 +275,7 @@ struct fsl_qspi {
  16. u32 clk_rate;
  17. unsigned int chip_base_addr; /* We may support two chips. */
  18. bool has_second_chip;
  19. + bool big_endian;
  20. struct mutex lock;
  21. struct pm_qos_request pm_qos_req;
  22. };
  23. @@ -300,6 +301,28 @@ static inline int needs_wakeup_wait_mode
  24. }
  25. /*
  26. + * R/W functions for big- or little-endian registers:
  27. + * The qSPI controller's endian is independent of the CPU core's endian.
  28. + * So far, although the CPU core is little-endian but the qSPI have two
  29. + * versions for big-endian and little-endian.
  30. + */
  31. +static void qspi_writel(struct fsl_qspi *q, u32 val, void __iomem *addr)
  32. +{
  33. + if (q->big_endian)
  34. + iowrite32be(val, addr);
  35. + else
  36. + iowrite32(val, addr);
  37. +}
  38. +
  39. +static u32 qspi_readl(struct fsl_qspi *q, void __iomem *addr)
  40. +{
  41. + if (q->big_endian)
  42. + return ioread32be(addr);
  43. + else
  44. + return ioread32(addr);
  45. +}
  46. +
  47. +/*
  48. * An IC bug makes us to re-arrange the 32-bit data.
  49. * The following chips, such as IMX6SLX, have fixed this bug.
  50. */
  51. @@ -310,14 +333,14 @@ static inline u32 fsl_qspi_endian_xchg(s
  52. static inline void fsl_qspi_unlock_lut(struct fsl_qspi *q)
  53. {
  54. - writel(QUADSPI_LUTKEY_VALUE, q->iobase + QUADSPI_LUTKEY);
  55. - writel(QUADSPI_LCKER_UNLOCK, q->iobase + QUADSPI_LCKCR);
  56. + qspi_writel(q, QUADSPI_LUTKEY_VALUE, q->iobase + QUADSPI_LUTKEY);
  57. + qspi_writel(q, QUADSPI_LCKER_UNLOCK, q->iobase + QUADSPI_LCKCR);
  58. }
  59. static inline void fsl_qspi_lock_lut(struct fsl_qspi *q)
  60. {
  61. - writel(QUADSPI_LUTKEY_VALUE, q->iobase + QUADSPI_LUTKEY);
  62. - writel(QUADSPI_LCKER_LOCK, q->iobase + QUADSPI_LCKCR);
  63. + qspi_writel(q, QUADSPI_LUTKEY_VALUE, q->iobase + QUADSPI_LUTKEY);
  64. + qspi_writel(q, QUADSPI_LCKER_LOCK, q->iobase + QUADSPI_LCKCR);
  65. }
  66. static irqreturn_t fsl_qspi_irq_handler(int irq, void *dev_id)
  67. @@ -326,8 +349,8 @@ static irqreturn_t fsl_qspi_irq_handler(
  68. u32 reg;
  69. /* clear interrupt */
  70. - reg = readl(q->iobase + QUADSPI_FR);
  71. - writel(reg, q->iobase + QUADSPI_FR);
  72. + reg = qspi_readl(q, q->iobase + QUADSPI_FR);
  73. + qspi_writel(q, reg, q->iobase + QUADSPI_FR);
  74. if (reg & QUADSPI_FR_TFF_MASK)
  75. complete(&q->c);
  76. @@ -348,7 +371,7 @@ static void fsl_qspi_init_lut(struct fsl
  77. /* Clear all the LUT table */
  78. for (i = 0; i < QUADSPI_LUT_NUM; i++)
  79. - writel(0, base + QUADSPI_LUT_BASE + i * 4);
  80. + qspi_writel(q, 0, base + QUADSPI_LUT_BASE + i * 4);
  81. /* Quad Read */
  82. lut_base = SEQID_QUAD_READ * 4;
  83. @@ -364,14 +387,15 @@ static void fsl_qspi_init_lut(struct fsl
  84. dummy = 8;
  85. }
  86. - writel(LUT0(CMD, PAD1, cmd) | LUT1(ADDR, PAD1, addrlen),
  87. + qspi_writel(q, LUT0(CMD, PAD1, cmd) | LUT1(ADDR, PAD1, addrlen),
  88. base + QUADSPI_LUT(lut_base));
  89. - writel(LUT0(DUMMY, PAD1, dummy) | LUT1(FSL_READ, PAD4, rxfifo),
  90. + qspi_writel(q, LUT0(DUMMY, PAD1, dummy) | LUT1(FSL_READ, PAD4, rxfifo),
  91. base + QUADSPI_LUT(lut_base + 1));
  92. /* Write enable */
  93. lut_base = SEQID_WREN * 4;
  94. - writel(LUT0(CMD, PAD1, SPINOR_OP_WREN), base + QUADSPI_LUT(lut_base));
  95. + qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_WREN),
  96. + base + QUADSPI_LUT(lut_base));
  97. /* Page Program */
  98. lut_base = SEQID_PP * 4;
  99. @@ -385,13 +409,15 @@ static void fsl_qspi_init_lut(struct fsl
  100. addrlen = ADDR32BIT;
  101. }
  102. - writel(LUT0(CMD, PAD1, cmd) | LUT1(ADDR, PAD1, addrlen),
  103. + qspi_writel(q, LUT0(CMD, PAD1, cmd) | LUT1(ADDR, PAD1, addrlen),
  104. base + QUADSPI_LUT(lut_base));
  105. - writel(LUT0(FSL_WRITE, PAD1, 0), base + QUADSPI_LUT(lut_base + 1));
  106. + qspi_writel(q, LUT0(FSL_WRITE, PAD1, 0),
  107. + base + QUADSPI_LUT(lut_base + 1));
  108. /* Read Status */
  109. lut_base = SEQID_RDSR * 4;
  110. - writel(LUT0(CMD, PAD1, SPINOR_OP_RDSR) | LUT1(FSL_READ, PAD1, 0x1),
  111. + qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_RDSR) |
  112. + LUT1(FSL_READ, PAD1, 0x1),
  113. base + QUADSPI_LUT(lut_base));
  114. /* Erase a sector */
  115. @@ -400,40 +426,46 @@ static void fsl_qspi_init_lut(struct fsl
  116. cmd = q->nor[0].erase_opcode;
  117. addrlen = q->nor_size <= SZ_16M ? ADDR24BIT : ADDR32BIT;
  118. - writel(LUT0(CMD, PAD1, cmd) | LUT1(ADDR, PAD1, addrlen),
  119. + qspi_writel(q, LUT0(CMD, PAD1, cmd) | LUT1(ADDR, PAD1, addrlen),
  120. base + QUADSPI_LUT(lut_base));
  121. /* Erase the whole chip */
  122. lut_base = SEQID_CHIP_ERASE * 4;
  123. - writel(LUT0(CMD, PAD1, SPINOR_OP_CHIP_ERASE),
  124. + qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_CHIP_ERASE),
  125. base + QUADSPI_LUT(lut_base));
  126. /* READ ID */
  127. lut_base = SEQID_RDID * 4;
  128. - writel(LUT0(CMD, PAD1, SPINOR_OP_RDID) | LUT1(FSL_READ, PAD1, 0x8),
  129. + qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_RDID) |
  130. + LUT1(FSL_READ, PAD1, 0x8),
  131. base + QUADSPI_LUT(lut_base));
  132. /* Write Register */
  133. lut_base = SEQID_WRSR * 4;
  134. - writel(LUT0(CMD, PAD1, SPINOR_OP_WRSR) | LUT1(FSL_WRITE, PAD1, 0x2),
  135. + qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_WRSR) |
  136. + LUT1(FSL_WRITE, PAD1, 0x2),
  137. base + QUADSPI_LUT(lut_base));
  138. /* Read Configuration Register */
  139. lut_base = SEQID_RDCR * 4;
  140. - writel(LUT0(CMD, PAD1, SPINOR_OP_RDCR) | LUT1(FSL_READ, PAD1, 0x1),
  141. + qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_RDCR) |
  142. + LUT1(FSL_READ, PAD1, 0x1),
  143. base + QUADSPI_LUT(lut_base));
  144. /* Write disable */
  145. lut_base = SEQID_WRDI * 4;
  146. - writel(LUT0(CMD, PAD1, SPINOR_OP_WRDI), base + QUADSPI_LUT(lut_base));
  147. + qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_WRDI),
  148. + base + QUADSPI_LUT(lut_base));
  149. /* Enter 4 Byte Mode (Micron) */
  150. lut_base = SEQID_EN4B * 4;
  151. - writel(LUT0(CMD, PAD1, SPINOR_OP_EN4B), base + QUADSPI_LUT(lut_base));
  152. + qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_EN4B),
  153. + base + QUADSPI_LUT(lut_base));
  154. /* Enter 4 Byte Mode (Spansion) */
  155. lut_base = SEQID_BRWR * 4;
  156. - writel(LUT0(CMD, PAD1, SPINOR_OP_BRWR), base + QUADSPI_LUT(lut_base));
  157. + qspi_writel(q, LUT0(CMD, PAD1, SPINOR_OP_BRWR),
  158. + base + QUADSPI_LUT(lut_base));
  159. fsl_qspi_lock_lut(q);
  160. }
  161. @@ -488,15 +520,16 @@ fsl_qspi_runcmd(struct fsl_qspi *q, u8 c
  162. q->chip_base_addr, addr, len, cmd);
  163. /* save the reg */
  164. - reg = readl(base + QUADSPI_MCR);
  165. + reg = qspi_readl(q, base + QUADSPI_MCR);
  166. - writel(q->memmap_phy + q->chip_base_addr + addr, base + QUADSPI_SFAR);
  167. - writel(QUADSPI_RBCT_WMRK_MASK | QUADSPI_RBCT_RXBRD_USEIPS,
  168. + qspi_writel(q, q->memmap_phy + q->chip_base_addr + addr,
  169. + base + QUADSPI_SFAR);
  170. + qspi_writel(q, QUADSPI_RBCT_WMRK_MASK | QUADSPI_RBCT_RXBRD_USEIPS,
  171. base + QUADSPI_RBCT);
  172. - writel(reg | QUADSPI_MCR_CLR_RXF_MASK, base + QUADSPI_MCR);
  173. + qspi_writel(q, reg | QUADSPI_MCR_CLR_RXF_MASK, base + QUADSPI_MCR);
  174. do {
  175. - reg2 = readl(base + QUADSPI_SR);
  176. + reg2 = qspi_readl(q, base + QUADSPI_SR);
  177. if (reg2 & (QUADSPI_SR_IP_ACC_MASK | QUADSPI_SR_AHB_ACC_MASK)) {
  178. udelay(1);
  179. dev_dbg(q->dev, "The controller is busy, 0x%x\n", reg2);
  180. @@ -507,21 +540,22 @@ fsl_qspi_runcmd(struct fsl_qspi *q, u8 c
  181. /* trigger the LUT now */
  182. seqid = fsl_qspi_get_seqid(q, cmd);
  183. - writel((seqid << QUADSPI_IPCR_SEQID_SHIFT) | len, base + QUADSPI_IPCR);
  184. + qspi_writel(q, (seqid << QUADSPI_IPCR_SEQID_SHIFT) | len,
  185. + base + QUADSPI_IPCR);
  186. /* Wait for the interrupt. */
  187. if (!wait_for_completion_timeout(&q->c, msecs_to_jiffies(1000))) {
  188. dev_err(q->dev,
  189. "cmd 0x%.2x timeout, addr@%.8x, FR:0x%.8x, SR:0x%.8x\n",
  190. - cmd, addr, readl(base + QUADSPI_FR),
  191. - readl(base + QUADSPI_SR));
  192. + cmd, addr, qspi_readl(q, base + QUADSPI_FR),
  193. + qspi_readl(q, base + QUADSPI_SR));
  194. err = -ETIMEDOUT;
  195. } else {
  196. err = 0;
  197. }
  198. /* restore the MCR */
  199. - writel(reg, base + QUADSPI_MCR);
  200. + qspi_writel(q, reg, base + QUADSPI_MCR);
  201. return err;
  202. }
  203. @@ -533,7 +567,7 @@ static void fsl_qspi_read_data(struct fs
  204. int i = 0;
  205. while (len > 0) {
  206. - tmp = readl(q->iobase + QUADSPI_RBDR + i * 4);
  207. + tmp = qspi_readl(q, q->iobase + QUADSPI_RBDR + i * 4);
  208. tmp = fsl_qspi_endian_xchg(q, tmp);
  209. dev_dbg(q->dev, "chip addr:0x%.8x, rcv:0x%.8x\n",
  210. q->chip_base_addr, tmp);
  211. @@ -561,9 +595,9 @@ static inline void fsl_qspi_invalid(stru
  212. {
  213. u32 reg;
  214. - reg = readl(q->iobase + QUADSPI_MCR);
  215. + reg = qspi_readl(q, q->iobase + QUADSPI_MCR);
  216. reg |= QUADSPI_MCR_SWRSTHD_MASK | QUADSPI_MCR_SWRSTSD_MASK;
  217. - writel(reg, q->iobase + QUADSPI_MCR);
  218. + qspi_writel(q, reg, q->iobase + QUADSPI_MCR);
  219. /*
  220. * The minimum delay : 1 AHB + 2 SFCK clocks.
  221. @@ -572,7 +606,7 @@ static inline void fsl_qspi_invalid(stru
  222. udelay(1);
  223. reg &= ~(QUADSPI_MCR_SWRSTHD_MASK | QUADSPI_MCR_SWRSTSD_MASK);
  224. - writel(reg, q->iobase + QUADSPI_MCR);
  225. + qspi_writel(q, reg, q->iobase + QUADSPI_MCR);
  226. }
  227. static int fsl_qspi_nor_write(struct fsl_qspi *q, struct spi_nor *nor,
  228. @@ -586,20 +620,20 @@ static int fsl_qspi_nor_write(struct fsl
  229. q->chip_base_addr, to, count);
  230. /* clear the TX FIFO. */
  231. - tmp = readl(q->iobase + QUADSPI_MCR);
  232. - writel(tmp | QUADSPI_MCR_CLR_TXF_MASK, q->iobase + QUADSPI_MCR);
  233. + tmp = qspi_readl(q, q->iobase + QUADSPI_MCR);
  234. + qspi_writel(q, tmp | QUADSPI_MCR_CLR_TXF_MASK, q->iobase + QUADSPI_MCR);
  235. /* fill the TX data to the FIFO */
  236. for (j = 0, i = ((count + 3) / 4); j < i; j++) {
  237. tmp = fsl_qspi_endian_xchg(q, *txbuf);
  238. - writel(tmp, q->iobase + QUADSPI_TBDR);
  239. + qspi_writel(q, tmp, q->iobase + QUADSPI_TBDR);
  240. txbuf++;
  241. }
  242. /* fill the TXFIFO upto 16 bytes for i.MX7d */
  243. if (needs_fill_txfifo(q))
  244. for (; i < 4; i++)
  245. - writel(tmp, q->iobase + QUADSPI_TBDR);
  246. + qspi_writel(q, tmp, q->iobase + QUADSPI_TBDR);
  247. /* Trigger it */
  248. ret = fsl_qspi_runcmd(q, opcode, to, count);
  249. @@ -615,10 +649,10 @@ static void fsl_qspi_set_map_addr(struct
  250. int nor_size = q->nor_size;
  251. void __iomem *base = q->iobase;
  252. - writel(nor_size + q->memmap_phy, base + QUADSPI_SFA1AD);
  253. - writel(nor_size * 2 + q->memmap_phy, base + QUADSPI_SFA2AD);
  254. - writel(nor_size * 3 + q->memmap_phy, base + QUADSPI_SFB1AD);
  255. - writel(nor_size * 4 + q->memmap_phy, base + QUADSPI_SFB2AD);
  256. + qspi_writel(q, nor_size + q->memmap_phy, base + QUADSPI_SFA1AD);
  257. + qspi_writel(q, nor_size * 2 + q->memmap_phy, base + QUADSPI_SFA2AD);
  258. + qspi_writel(q, nor_size * 3 + q->memmap_phy, base + QUADSPI_SFB1AD);
  259. + qspi_writel(q, nor_size * 4 + q->memmap_phy, base + QUADSPI_SFB2AD);
  260. }
  261. /*
  262. @@ -640,24 +674,26 @@ static void fsl_qspi_init_abh_read(struc
  263. int seqid;
  264. /* AHB configuration for access buffer 0/1/2 .*/
  265. - writel(QUADSPI_BUFXCR_INVALID_MSTRID, base + QUADSPI_BUF0CR);
  266. - writel(QUADSPI_BUFXCR_INVALID_MSTRID, base + QUADSPI_BUF1CR);
  267. - writel(QUADSPI_BUFXCR_INVALID_MSTRID, base + QUADSPI_BUF2CR);
  268. + qspi_writel(q, QUADSPI_BUFXCR_INVALID_MSTRID, base + QUADSPI_BUF0CR);
  269. + qspi_writel(q, QUADSPI_BUFXCR_INVALID_MSTRID, base + QUADSPI_BUF1CR);
  270. + qspi_writel(q, QUADSPI_BUFXCR_INVALID_MSTRID, base + QUADSPI_BUF2CR);
  271. /*
  272. * Set ADATSZ with the maximum AHB buffer size to improve the
  273. * read performance.
  274. */
  275. - writel(QUADSPI_BUF3CR_ALLMST_MASK | ((q->devtype_data->ahb_buf_size / 8)
  276. - << QUADSPI_BUF3CR_ADATSZ_SHIFT), base + QUADSPI_BUF3CR);
  277. + qspi_writel(q, QUADSPI_BUF3CR_ALLMST_MASK |
  278. + ((q->devtype_data->ahb_buf_size / 8)
  279. + << QUADSPI_BUF3CR_ADATSZ_SHIFT),
  280. + base + QUADSPI_BUF3CR);
  281. /* We only use the buffer3 */
  282. - writel(0, base + QUADSPI_BUF0IND);
  283. - writel(0, base + QUADSPI_BUF1IND);
  284. - writel(0, base + QUADSPI_BUF2IND);
  285. + qspi_writel(q, 0, base + QUADSPI_BUF0IND);
  286. + qspi_writel(q, 0, base + QUADSPI_BUF1IND);
  287. + qspi_writel(q, 0, base + QUADSPI_BUF2IND);
  288. /* Set the default lut sequence for AHB Read. */
  289. seqid = fsl_qspi_get_seqid(q, q->nor[0].read_opcode);
  290. - writel(seqid << QUADSPI_BFGENCR_SEQID_SHIFT,
  291. + qspi_writel(q, seqid << QUADSPI_BFGENCR_SEQID_SHIFT,
  292. q->iobase + QUADSPI_BFGENCR);
  293. }
  294. @@ -713,7 +749,7 @@ static int fsl_qspi_nor_setup(struct fsl
  295. return ret;
  296. /* Reset the module */
  297. - writel(QUADSPI_MCR_SWRSTSD_MASK | QUADSPI_MCR_SWRSTHD_MASK,
  298. + qspi_writel(q, QUADSPI_MCR_SWRSTSD_MASK | QUADSPI_MCR_SWRSTHD_MASK,
  299. base + QUADSPI_MCR);
  300. udelay(1);
  301. @@ -721,24 +757,24 @@ static int fsl_qspi_nor_setup(struct fsl
  302. fsl_qspi_init_lut(q);
  303. /* Disable the module */
  304. - writel(QUADSPI_MCR_MDIS_MASK | QUADSPI_MCR_RESERVED_MASK,
  305. + qspi_writel(q, QUADSPI_MCR_MDIS_MASK | QUADSPI_MCR_RESERVED_MASK,
  306. base + QUADSPI_MCR);
  307. - reg = readl(base + QUADSPI_SMPR);
  308. - writel(reg & ~(QUADSPI_SMPR_FSDLY_MASK
  309. + reg = qspi_readl(q, base + QUADSPI_SMPR);
  310. + qspi_writel(q, reg & ~(QUADSPI_SMPR_FSDLY_MASK
  311. | QUADSPI_SMPR_FSPHS_MASK
  312. | QUADSPI_SMPR_HSENA_MASK
  313. | QUADSPI_SMPR_DDRSMP_MASK), base + QUADSPI_SMPR);
  314. /* Enable the module */
  315. - writel(QUADSPI_MCR_RESERVED_MASK | QUADSPI_MCR_END_CFG_MASK,
  316. + qspi_writel(q, QUADSPI_MCR_RESERVED_MASK | QUADSPI_MCR_END_CFG_MASK,
  317. base + QUADSPI_MCR);
  318. /* clear all interrupt status */
  319. - writel(0xffffffff, q->iobase + QUADSPI_FR);
  320. + qspi_writel(q, 0xffffffff, q->iobase + QUADSPI_FR);
  321. /* enable the interrupt */
  322. - writel(QUADSPI_RSER_TFIE, q->iobase + QUADSPI_RSER);
  323. + qspi_writel(q, QUADSPI_RSER_TFIE, q->iobase + QUADSPI_RSER);
  324. return 0;
  325. }
  326. @@ -954,6 +990,7 @@ static int fsl_qspi_probe(struct platfor
  327. if (IS_ERR(q->iobase))
  328. return PTR_ERR(q->iobase);
  329. + q->big_endian = of_property_read_bool(np, "big-endian");
  330. res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
  331. "QuadSPI-memory");
  332. if (!devm_request_mem_region(dev, res->start, resource_size(res),
  333. @@ -1101,8 +1138,8 @@ static int fsl_qspi_remove(struct platfo
  334. }
  335. /* disable the hardware */
  336. - writel(QUADSPI_MCR_MDIS_MASK, q->iobase + QUADSPI_MCR);
  337. - writel(0x0, q->iobase + QUADSPI_RSER);
  338. + qspi_writel(q, QUADSPI_MCR_MDIS_MASK, q->iobase + QUADSPI_MCR);
  339. + qspi_writel(q, 0x0, q->iobase + QUADSPI_RSER);
  340. mutex_destroy(&q->lock);