[U-Boot] [PATCH 10/13] mtd/nand/tegra: alignment workaround

Marcel Ziswiler marcel at ziswiler.com
Mon Jul 6 10:20:36 CEST 2015


From: Marcel Ziswiler <marcel.ziswiler at toradex.com>

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

Signed-off-by: Marcel Ziswiler <marcel.ziswiler at toradex.com>
---
 drivers/mtd/nand/tegra_nand.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/drivers/mtd/nand/tegra_nand.c b/drivers/mtd/nand/tegra_nand.c
index 9c90634..a7ab415 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, &reg_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;
 
@@ -638,6 +646,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);
@@ -999,6 +1012,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;
-- 
1.9.3



More information about the U-Boot mailing list