diff options
author | Marcel Ziswiler <marcel.ziswiler@toradex.com> | 2015-05-13 13:00:24 +0200 |
---|---|---|
committer | Marcel Ziswiler <marcel.ziswiler@toradex.com> | 2015-05-13 13:00:24 +0200 |
commit | 7c91ed0ad13111b2c693c90f7c835449ad450970 (patch) | |
tree | 112c877fa5e28e191eed15f0ac3fdf59a5e9dfa5 | |
parent | 5c2752a59cde6424709ca20c00fb19f1b9d58bf3 (diff) |
mtd/nand/tegra: alignment workaround
Introduce cache alignment bounce buffer to workaround issues as follows:
Loading file '/boot/zImage' to addr 0x01000000 with size 4499152 (0x0044a6d0)...
ERROR: v7_dcache_inval_range - start address is not aligned - 0x1f7f0108
ERROR: v7_dcache_inval_range - stop address is not aligned - 0x1f7f1108
Done
Kernel image @ 0x1000000 [ 0x000000 - 0x44a6d0 ]
Starting kernel ...
undefined instruction
pc : [<005ff03c>] lr : [<0000800c>]
sp : 0144b6e8 ip : 01000188 fp : 0144a6c8
r10: 00000000 r9 : 411fc090 r8 : 00000100
r7 : 00000cfb r6 : 0144a6d0 r5 : 00000000 r4 : 00008000
r3 : 0000000c r2 : 00000100 r1 : 00000cfb r0 : 00000000
Flags: nZCv IRQs off FIQs off Mode SVC_32
Resetting CPU ...
-rw-r--r-- | drivers/mtd/nand/tegra_nand.c | 18 |
1 files changed, 18 insertions, 0 deletions
diff --git a/drivers/mtd/nand/tegra_nand.c b/drivers/mtd/nand/tegra_nand.c index b02d27abc35..b51910bf4fc 100644 --- a/drivers/mtd/nand/tegra_nand.c +++ b/drivers/mtd/nand/tegra_nand.c @@ -87,6 +87,7 @@ struct fdt_nand { struct nand_drv { struct nand_ctlr *reg; struct fdt_nand config; + uint8_t *data_buf; /* cache alignment bounce buffer */ }; static struct nand_drv nand_ctrl; @@ -534,6 +535,7 @@ static int nand_rw_page(struct mtd_info *mtd, struct nand_chip *chip, char *tag_ptr; struct nand_drv *info; struct fdt_nand *config; + uint8_t *temp_buf = NULL; if ((uintptr_t)buf & 0x03) { printf("buf %p has to be 4-byte aligned\n", buf); @@ -545,6 +547,12 @@ static int nand_rw_page(struct mtd_info *mtd, struct nand_chip *chip, if (set_bus_width_page_size(config, ®_val)) return -EINVAL; + /* cache alignment */ + if ((!is_writing) && ((uintptr_t)buf & (ARCH_DMA_MINALIGN - 1))) { + temp_buf = buf; + buf = info->data_buf; + } + /* Need to be 4-byte aligned */ tag_ptr = (char *)tag_buf; @@ -633,6 +641,11 @@ static int nand_rw_page(struct mtd_info *mtd, struct nand_chip *chip, return -EIO; } + /* cache alignment */ + if (temp_buf) { + memcpy(temp_buf, buf, 1 << chip->page_shift); + } + if (with_ecc && !is_writing) { memcpy(chip->oob_poi, tag_ptr, SKIPPED_SPARE_BYTES); @@ -994,6 +1007,11 @@ int tegra_nand_init(struct nand_chip *nand, int devnum) nand->ecc.size = our_mtd->writesize; nand->ecc.bytes = our_mtd->oobsize; + /* cache alignment */ + info->data_buf = memalign(ARCH_DMA_MINALIGN, our_mtd->writesize); + if (!info->data_buf) + return -ENOMEM; + ret = nand_scan_tail(our_mtd); if (ret) return ret; |