mtd: rawnand: meson: invalidate cache on polling ECC bit
[ Upstream commit e732e39ed9929c05fd219035bc9653ba4100d4fa ]
'info_buf' memory is cached and driver polls ECC bit in it. This bit
is set by the NAND controller. If 'usleep_range()' returns before device
sets this bit, 'info_buf' will be cached and driver won't see update of
this bit and will loop forever.
Fixes: 8fae856c53
("mtd: rawnand: meson: add support for Amlogic NAND flash controller")
Signed-off-by: Arseniy Krasnov <AVKrasnov@sberdevices.ru>
Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Link: https://lore.kernel.org/linux-mtd/d4ef0bd6-816e-f6fa-9385-f05f775f0ae2@sberdevices.ru
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
53dc0b69fb
commit
43b70c9c4c
@ -176,6 +176,7 @@ struct meson_nfc {
|
|||||||
|
|
||||||
dma_addr_t daddr;
|
dma_addr_t daddr;
|
||||||
dma_addr_t iaddr;
|
dma_addr_t iaddr;
|
||||||
|
u32 info_bytes;
|
||||||
|
|
||||||
unsigned long assigned_cs;
|
unsigned long assigned_cs;
|
||||||
};
|
};
|
||||||
@ -503,6 +504,7 @@ static int meson_nfc_dma_buffer_setup(struct nand_chip *nand, void *databuf,
|
|||||||
nfc->daddr, datalen, dir);
|
nfc->daddr, datalen, dir);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
nfc->info_bytes = infolen;
|
||||||
cmd = GENCMDIADDRL(NFC_CMD_AIL, nfc->iaddr);
|
cmd = GENCMDIADDRL(NFC_CMD_AIL, nfc->iaddr);
|
||||||
writel(cmd, nfc->reg_base + NFC_REG_CMD);
|
writel(cmd, nfc->reg_base + NFC_REG_CMD);
|
||||||
|
|
||||||
@ -520,8 +522,10 @@ static void meson_nfc_dma_buffer_release(struct nand_chip *nand,
|
|||||||
struct meson_nfc *nfc = nand_get_controller_data(nand);
|
struct meson_nfc *nfc = nand_get_controller_data(nand);
|
||||||
|
|
||||||
dma_unmap_single(nfc->dev, nfc->daddr, datalen, dir);
|
dma_unmap_single(nfc->dev, nfc->daddr, datalen, dir);
|
||||||
if (infolen)
|
if (infolen) {
|
||||||
dma_unmap_single(nfc->dev, nfc->iaddr, infolen, dir);
|
dma_unmap_single(nfc->dev, nfc->iaddr, infolen, dir);
|
||||||
|
nfc->info_bytes = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int meson_nfc_read_buf(struct nand_chip *nand, u8 *buf, int len)
|
static int meson_nfc_read_buf(struct nand_chip *nand, u8 *buf, int len)
|
||||||
@ -710,6 +714,8 @@ static void meson_nfc_check_ecc_pages_valid(struct meson_nfc *nfc,
|
|||||||
usleep_range(10, 15);
|
usleep_range(10, 15);
|
||||||
/* info is updated by nfc dma engine*/
|
/* info is updated by nfc dma engine*/
|
||||||
smp_rmb();
|
smp_rmb();
|
||||||
|
dma_sync_single_for_cpu(nfc->dev, nfc->iaddr, nfc->info_bytes,
|
||||||
|
DMA_FROM_DEVICE);
|
||||||
ret = *info & ECC_COMPLETE;
|
ret = *info & ECC_COMPLETE;
|
||||||
} while (!ret);
|
} while (!ret);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user