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: Valentin Korenblit <vkorenblit@sequans.com> Reviewed-by: Arnd Bergmann <arnd@arndb.de> Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com> Link: https://lore.kernel.org/linux-mtd/20221018093000.12072-1-vkorenblit@sequans.com
This commit is contained in:
parent
6154c7a583
commit
7c3fc99819
|
@ -1184,6 +1184,14 @@ static int cadence_nand_hw_init(struct cdns_nand_ctrl *cdns_ctrl)
|
|||
if (cadence_nand_read_bch_caps(cdns_ctrl))
|
||||
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.
|
||||
* 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,
|
|||
return status;
|
||||
|
||||
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 */
|
||||
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) {
|
||||
int read_bytes = (data_dma_width == 4) ?
|
||||
len_in_words << 2 : len_in_words << 3;
|
||||
|
||||
/* read rest data from slave DMA interface if any */
|
||||
ioread32_rep(cdns_ctrl->io.virt, cdns_ctrl->buf,
|
||||
sdma_size / 4 - len_in_words);
|
||||
if (data_dma_width == 4)
|
||||
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 */
|
||||
memcpy(buf + (len_in_words << 2), cdns_ctrl->buf,
|
||||
len - (len_in_words << 2));
|
||||
memcpy(buf + read_bytes, cdns_ctrl->buf,
|
||||
len - read_bytes);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -1936,16 +1963,35 @@ static int cadence_nand_write_buf(struct cdns_nand_ctrl *cdns_ctrl,
|
|||
return status;
|
||||
|
||||
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) {
|
||||
int written_bytes = (data_dma_width == 4) ?
|
||||
len_in_words << 2 : len_in_words << 3;
|
||||
|
||||
/* copy rest of data */
|
||||
memcpy(cdns_ctrl->buf, buf + (len_in_words << 2),
|
||||
len - (len_in_words << 2));
|
||||
memcpy(cdns_ctrl->buf, buf + written_bytes,
|
||||
len - written_bytes);
|
||||
|
||||
/* write all expected by nand controller data */
|
||||
iowrite32_rep(cdns_ctrl->io.virt, cdns_ctrl->buf,
|
||||
sdma_size / 4 - len_in_words);
|
||||
if (data_dma_width == 4)
|
||||
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;
|
||||
|
|
Loading…
Reference in New Issue