.. | .. |
---|
72 | 72 | #define GENCMDIADDRH(aih, addr) ((aih) | (((addr) >> 16) & 0xffff)) |
---|
73 | 73 | |
---|
74 | 74 | #define DMA_DIR(dir) ((dir) ? NFC_CMD_N2M : NFC_CMD_M2N) |
---|
| 75 | +#define DMA_ADDR_ALIGN 8 |
---|
75 | 76 | |
---|
76 | 77 | #define ECC_CHECK_RETURN_FF (-1) |
---|
77 | 78 | |
---|
.. | .. |
---|
172 | 173 | |
---|
173 | 174 | dma_addr_t daddr; |
---|
174 | 175 | dma_addr_t iaddr; |
---|
| 176 | + u32 info_bytes; |
---|
175 | 177 | |
---|
176 | 178 | unsigned long assigned_cs; |
---|
177 | 179 | }; |
---|
.. | .. |
---|
275 | 277 | |
---|
276 | 278 | if (raw) { |
---|
277 | 279 | len = mtd->writesize + mtd->oobsize; |
---|
278 | | - cmd = (len & GENMASK(5, 0)) | scrambler | DMA_DIR(dir); |
---|
| 280 | + cmd = (len & GENMASK(13, 0)) | scrambler | DMA_DIR(dir); |
---|
279 | 281 | writel(cmd, nfc->reg_base + NFC_REG_CMD); |
---|
280 | 282 | return; |
---|
281 | 283 | } |
---|
.. | .. |
---|
499 | 501 | nfc->daddr, datalen, dir); |
---|
500 | 502 | return ret; |
---|
501 | 503 | } |
---|
| 504 | + nfc->info_bytes = infolen; |
---|
502 | 505 | cmd = GENCMDIADDRL(NFC_CMD_AIL, nfc->iaddr); |
---|
503 | 506 | writel(cmd, nfc->reg_base + NFC_REG_CMD); |
---|
504 | 507 | |
---|
.. | .. |
---|
516 | 519 | struct meson_nfc *nfc = nand_get_controller_data(nand); |
---|
517 | 520 | |
---|
518 | 521 | dma_unmap_single(nfc->dev, nfc->daddr, datalen, dir); |
---|
519 | | - if (infolen) |
---|
| 522 | + if (infolen) { |
---|
520 | 523 | dma_unmap_single(nfc->dev, nfc->iaddr, infolen, dir); |
---|
| 524 | + nfc->info_bytes = 0; |
---|
| 525 | + } |
---|
521 | 526 | } |
---|
522 | 527 | |
---|
523 | 528 | static int meson_nfc_read_buf(struct nand_chip *nand, u8 *buf, int len) |
---|
.. | .. |
---|
536 | 541 | if (ret) |
---|
537 | 542 | goto out; |
---|
538 | 543 | |
---|
539 | | - cmd = NFC_CMD_N2M | (len & GENMASK(5, 0)); |
---|
| 544 | + cmd = NFC_CMD_N2M | (len & GENMASK(13, 0)); |
---|
540 | 545 | writel(cmd, nfc->reg_base + NFC_REG_CMD); |
---|
541 | 546 | |
---|
542 | 547 | meson_nfc_drain_cmd(nfc); |
---|
.. | .. |
---|
560 | 565 | if (ret) |
---|
561 | 566 | return ret; |
---|
562 | 567 | |
---|
563 | | - cmd = NFC_CMD_M2N | (len & GENMASK(5, 0)); |
---|
| 568 | + cmd = NFC_CMD_M2N | (len & GENMASK(13, 0)); |
---|
564 | 569 | writel(cmd, nfc->reg_base + NFC_REG_CMD); |
---|
565 | 570 | |
---|
566 | 571 | meson_nfc_drain_cmd(nfc); |
---|
.. | .. |
---|
706 | 711 | usleep_range(10, 15); |
---|
707 | 712 | /* info is updated by nfc dma engine*/ |
---|
708 | 713 | smp_rmb(); |
---|
| 714 | + dma_sync_single_for_cpu(nfc->dev, nfc->iaddr, nfc->info_bytes, |
---|
| 715 | + DMA_FROM_DEVICE); |
---|
709 | 716 | ret = *info & ECC_COMPLETE; |
---|
710 | 717 | } while (!ret); |
---|
711 | 718 | } |
---|
.. | .. |
---|
832 | 839 | |
---|
833 | 840 | static bool meson_nfc_is_buffer_dma_safe(const void *buffer) |
---|
834 | 841 | { |
---|
| 842 | + if ((uintptr_t)buffer % DMA_ADDR_ALIGN) |
---|
| 843 | + return false; |
---|
| 844 | + |
---|
835 | 845 | if (virt_addr_valid(buffer) && (!object_is_on_stack(buffer))) |
---|
836 | 846 | return true; |
---|
837 | 847 | return false; |
---|
.. | .. |
---|
1170 | 1180 | struct meson_nfc *nfc = nand_get_controller_data(nand); |
---|
1171 | 1181 | struct meson_nfc_nand_chip *meson_chip = to_meson_nand(nand); |
---|
1172 | 1182 | struct mtd_info *mtd = nand_to_mtd(nand); |
---|
1173 | | - int nsectors = mtd->writesize / 1024; |
---|
1174 | 1183 | int ret; |
---|
1175 | 1184 | |
---|
1176 | 1185 | if (!mtd->name) { |
---|
.. | .. |
---|
1188 | 1197 | nand->options |= NAND_NO_SUBPAGE_WRITE; |
---|
1189 | 1198 | |
---|
1190 | 1199 | ret = nand_ecc_choose_conf(nand, nfc->data->ecc_caps, |
---|
1191 | | - mtd->oobsize - 2 * nsectors); |
---|
| 1200 | + mtd->oobsize - 2); |
---|
1192 | 1201 | if (ret) { |
---|
1193 | 1202 | dev_err(nfc->dev, "failed to ECC init\n"); |
---|
1194 | 1203 | return -EINVAL; |
---|