| .. | .. |
|---|
| 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; |
|---|