summaryrefslogtreecommitdiff
path: root/drivers/mtd
diff options
context:
space:
mode:
authorHan Xu <han.xu@nxp.com>2017-07-21 16:17:59 -0500
committerLeonard Crestez <leonard.crestez@nxp.com>2018-08-24 12:41:33 +0300
commit120587fee2bbd3ca9e1f56913e73558fd42a94a0 (patch)
treea38e59b0f2f2ddf5b7a442f23ed09e353d6e8f4b /drivers/mtd
parent888f445fc4f8d0e02139ee5f65cef2f28f6c28b5 (diff)
MLK-16060: mtd: fsl-quadspi: fix the unalignment issue for qspi
ARM64 platforms may access QSPI from non-64-bit-aligned address which causes unalignment fault. Fixed the issue for AHB reading. Signed-off-by: Han Xu <han.xu@nxp.com>
Diffstat (limited to 'drivers/mtd')
-rw-r--r--drivers/mtd/spi-nor/fsl-quadspi.c21
1 files changed, 18 insertions, 3 deletions
diff --git a/drivers/mtd/spi-nor/fsl-quadspi.c b/drivers/mtd/spi-nor/fsl-quadspi.c
index 47f675098d63..dd0d817047fa 100644
--- a/drivers/mtd/spi-nor/fsl-quadspi.c
+++ b/drivers/mtd/spi-nor/fsl-quadspi.c
@@ -2,6 +2,7 @@
* Freescale QuadSPI driver.
*
* Copyright (C) 2013-2016 Freescale Semiconductor, Inc.
+ * Copyright 2017 NXP
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -1090,6 +1091,8 @@ static ssize_t fsl_qspi_read(struct spi_nor *nor, loff_t from,
{
struct fsl_qspi *q = nor->priv;
u8 cmd = nor->read_opcode;
+ u8 tmp[8] = {0};
+ int i, j;
/* if necessary,ioremap buffer before AHB read, */
if (!q->ahb_addr) {
@@ -1124,9 +1127,21 @@ static ssize_t fsl_qspi_read(struct spi_nor *nor, loff_t from,
cmd, q->ahb_addr + q->chip_base_addr + from - q->memmap_offs,
len);
- /* Read out the data directly from the AHB buffer.*/
- memcpy(buf, q->ahb_addr + q->chip_base_addr + from - q->memmap_offs,
- len);
+ /* For non-8-byte alignment cases */
+ if (from % 8) {
+ j = 8 - (from & 0x7);
+ for (i = 0; i < j; ++i) {
+ memcpy(tmp + i, q->ahb_addr + q->chip_base_addr + from
+ - q->memmap_offs + i, 1);
+ }
+ memcpy(buf, tmp, j);
+ memcpy(buf + j, q->ahb_addr + q->chip_base_addr + from
+ - q->memmap_offs + j, len - j);
+ } else {
+ /* Read out the data directly from the AHB buffer.*/
+ memcpy(buf, q->ahb_addr + q->chip_base_addr + from
+ - q->memmap_offs, len);
+ }
return len;
}