Commit 7c3fc998 authored by Valentin Korenblit's avatar Valentin Korenblit Committed by Miquel Raynal

mtd: rawnand: cadence: support 64-bit slave dma interface

32-bit accesses on 64-bit sdma trigger sdma_err in intr_status register.

Check dma capabilities before reading/writing from/to sdma interface.

Link: https://lore.kernel.org/all/b7e5ebb4-0de8-4958-9bc4-fe06ec4c3635@www.fastmail.com/t/Signed-off-by: default avatarValentin Korenblit <vkorenblit@sequans.com>
Reviewed-by: default avatarArnd Bergmann <arnd@arndb.de>
Signed-off-by: default avatarMiquel Raynal <miquel.raynal@bootlin.com>
Link: https://lore.kernel.org/linux-mtd/20221018093000.12072-1-vkorenblit@sequans.com
parent 6154c7a5
...@@ -1184,6 +1184,14 @@ static int cadence_nand_hw_init(struct cdns_nand_ctrl *cdns_ctrl) ...@@ -1184,6 +1184,14 @@ static int cadence_nand_hw_init(struct cdns_nand_ctrl *cdns_ctrl)
if (cadence_nand_read_bch_caps(cdns_ctrl)) if (cadence_nand_read_bch_caps(cdns_ctrl))
return -EIO; return -EIO;
#ifndef CONFIG_64BIT
if (cdns_ctrl->caps2.data_dma_width == 8) {
dev_err(cdns_ctrl->dev,
"cannot access 64-bit dma on !64-bit architectures");
return -EIO;
}
#endif
/* /*
* Set IO width access to 8. * Set IO width access to 8.
* It is because during SW device discovering width access * It is because during SW device discovering width access
...@@ -1882,17 +1890,36 @@ static int cadence_nand_read_buf(struct cdns_nand_ctrl *cdns_ctrl, ...@@ -1882,17 +1890,36 @@ static int cadence_nand_read_buf(struct cdns_nand_ctrl *cdns_ctrl,
return status; return status;
if (!cdns_ctrl->caps1->has_dma) { if (!cdns_ctrl->caps1->has_dma) {
int len_in_words = len >> 2; u8 data_dma_width = cdns_ctrl->caps2.data_dma_width;
int len_in_words = (data_dma_width == 4) ? len >> 2 : len >> 3;
/* read alingment data */ /* read alingment data */
ioread32_rep(cdns_ctrl->io.virt, buf, len_in_words); if (data_dma_width == 4)
ioread32_rep(cdns_ctrl->io.virt, buf, len_in_words);
#ifdef CONFIG_64BIT
else
readsq(cdns_ctrl->io.virt, buf, len_in_words);
#endif
if (sdma_size > len) { if (sdma_size > len) {
int read_bytes = (data_dma_width == 4) ?
len_in_words << 2 : len_in_words << 3;
/* read rest data from slave DMA interface if any */ /* read rest data from slave DMA interface if any */
ioread32_rep(cdns_ctrl->io.virt, cdns_ctrl->buf, if (data_dma_width == 4)
sdma_size / 4 - len_in_words); ioread32_rep(cdns_ctrl->io.virt,
cdns_ctrl->buf,
sdma_size / 4 - len_in_words);
#ifdef CONFIG_64BIT
else
readsq(cdns_ctrl->io.virt, cdns_ctrl->buf,
sdma_size / 8 - len_in_words);
#endif
/* copy rest of data */ /* copy rest of data */
memcpy(buf + (len_in_words << 2), cdns_ctrl->buf, memcpy(buf + read_bytes, cdns_ctrl->buf,
len - (len_in_words << 2)); len - read_bytes);
} }
return 0; return 0;
} }
...@@ -1936,16 +1963,35 @@ static int cadence_nand_write_buf(struct cdns_nand_ctrl *cdns_ctrl, ...@@ -1936,16 +1963,35 @@ static int cadence_nand_write_buf(struct cdns_nand_ctrl *cdns_ctrl,
return status; return status;
if (!cdns_ctrl->caps1->has_dma) { if (!cdns_ctrl->caps1->has_dma) {
int len_in_words = len >> 2; u8 data_dma_width = cdns_ctrl->caps2.data_dma_width;
int len_in_words = (data_dma_width == 4) ? len >> 2 : len >> 3;
if (data_dma_width == 4)
iowrite32_rep(cdns_ctrl->io.virt, buf, len_in_words);
#ifdef CONFIG_64BIT
else
writesq(cdns_ctrl->io.virt, buf, len_in_words);
#endif
iowrite32_rep(cdns_ctrl->io.virt, buf, len_in_words);
if (sdma_size > len) { if (sdma_size > len) {
int written_bytes = (data_dma_width == 4) ?
len_in_words << 2 : len_in_words << 3;
/* copy rest of data */ /* copy rest of data */
memcpy(cdns_ctrl->buf, buf + (len_in_words << 2), memcpy(cdns_ctrl->buf, buf + written_bytes,
len - (len_in_words << 2)); len - written_bytes);
/* write all expected by nand controller data */ /* write all expected by nand controller data */
iowrite32_rep(cdns_ctrl->io.virt, cdns_ctrl->buf, if (data_dma_width == 4)
sdma_size / 4 - len_in_words); iowrite32_rep(cdns_ctrl->io.virt,
cdns_ctrl->buf,
sdma_size / 4 - len_in_words);
#ifdef CONFIG_64BIT
else
writesq(cdns_ctrl->io.virt, cdns_ctrl->buf,
sdma_size / 8 - len_in_words);
#endif
} }
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment