129-nand-sunxi-fix-write-to-USER_DATA-a13.patch 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. From b1488f1a55da6a297ac4e8e9140922f35b7583c5 Mon Sep 17 00:00:00 2001
  2. From: Boris Brezillon <boris.brezillon@free-electrons.com>
  3. Date: Mon, 15 Jun 2015 11:09:58 +0200
  4. Subject: [PATCH] nand: sunxi: fix write to USER_DATA reg
  5. The USER_DATA register cannot be updated with readb on A13 SoCs, thus
  6. triggering a bug when using memcpy_toio on this register.
  7. Use writel (plus a temporary variable to old the USER_DATA value) to
  8. address that problem.
  9. Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
  10. ---
  11. drivers/mtd/nand/sunxi_nand.c | 38 +++++++++++++++++++++-----------------
  12. 1 file changed, 21 insertions(+), 17 deletions(-)
  13. --- a/drivers/mtd/nand/sunxi_nand.c
  14. +++ b/drivers/mtd/nand/sunxi_nand.c
  15. @@ -908,7 +908,7 @@ static int sunxi_nfc_hw_ecc_write_page(s
  16. for (i = 0; i < ecc->steps; i++) {
  17. bool rndactiv = false;
  18. - u8 oob_buf[4];
  19. + u32 user_data;
  20. if (i)
  21. chip->cmdfunc(mtd, NAND_CMD_RNDIN, i * ecc->size, -1);
  22. @@ -919,15 +919,13 @@ static int sunxi_nfc_hw_ecc_write_page(s
  23. offset = layout->eccpos[i * ecc->bytes] - 4 + mtd->writesize;
  24. /* Fill OOB data in */
  25. - if (!oob_required)
  26. - memset(oob_buf, 0xff, 4);
  27. - else
  28. - memcpy(oob_buf,
  29. - chip->oob_poi + layout->oobfree[i].offset,
  30. - 4);
  31. -
  32. -
  33. - memcpy_toio(nfc->regs + NFC_REG_USER_DATA_BASE, oob_buf, 4);
  34. + if (!oob_required) {
  35. + user_data = 0xffffffff;
  36. + } else {
  37. + memcpy(&user_data,
  38. + chip->oob_poi + layout->oobfree[i].offset, 4);
  39. + user_data = le32_to_cpu(user_data);
  40. + }
  41. if (i) {
  42. cnt = ecc->bytes + 4;
  43. @@ -946,12 +944,16 @@ static int sunxi_nfc_hw_ecc_write_page(s
  44. if (rndactiv) {
  45. /* pre randomize to generate FF patterns on the NAND */
  46. if (!i) {
  47. + u8 oob_tmp[2];
  48. u16 state = rnd->subseeds[rnd->page % rnd->nseeds];
  49. + oob_tmp[0] = user_data;
  50. + oob_tmp[1] = user_data >> 8;
  51. state = sunxi_nfc_hwrnd_single_step(state, 15);
  52. - oob_buf[0] ^= state;
  53. + oob_tmp[0] ^= state;
  54. state = sunxi_nfc_hwrnd_step(rnd, state, 1);
  55. - oob_buf[1] ^= state;
  56. - memcpy_toio(nfc->regs + NFC_REG_USER_DATA_BASE, oob_buf, 4);
  57. + oob_tmp[1] ^= state;
  58. + user_data &= ~0xffff;
  59. + user_data |= oob_tmp[0] | (oob_tmp[1] << 8);
  60. }
  61. tmp = readl(nfc->regs + NFC_REG_ECC_CTL);
  62. tmp &= ~(NFC_RANDOM_DIRECTION | NFC_ECC_EXCEPTION);
  63. @@ -959,6 +961,8 @@ static int sunxi_nfc_hw_ecc_write_page(s
  64. writel(tmp, nfc->regs + NFC_REG_ECC_CTL);
  65. }
  66. + writel(user_data, nfc->regs + NFC_REG_USER_DATA_BASE);
  67. +
  68. chip->cmdfunc(mtd, NAND_CMD_RNDIN, offset, -1);
  69. ret = sunxi_nfc_wait_cmd_fifo_empty(nfc);