The two most important fixes in this list are probably the SST write
failure and the Qcom raw NAND controller probe failure which are due to some refactoring, otherwise there has been a series of misc fixes on the Cadence raw NAND controller driver and especially on the DMA side. -----BEGIN PGP SIGNATURE----- iQEzBAABCAAdFiEE9HuaYnbmDhq/XIDIJWrqGEe9VoQFAme4omgACgkQJWrqGEe9 VoS6nQf+MJuHmlOeAInMmoKA6gJ358GIxStkiT88db4NuOtXrWkf9BVcI/LNlHDv dV1xW0uHbrjnf2teuBk4mD11PbH5lKz738ElBphQWkDbsEq7+l0OiN7ixZ8dF7UK 6qKvP8CLRgz/41elD8Kg0c2x4Tfoxym6G1lrNqt9igkv6/jDgKrP93ScDwmVpS76 DZ3toKGqo2fHuG8sN+qGh1KQIf6DWUUx6E7SJin4cF/dHamYBT60KnVHtftabo60 1HEJcIXc6dIxXWz4Zqcjzogje3ynKhKuFW50qmJJKxE4VzcZIVkS0UpiLNZcJtP4 oulojoBQStASD5ztBP2zq4kGaXo6pQ== =fjkV -----END PGP SIGNATURE----- Merge tag 'mtd/fixes-for-6.14-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux Pull mtd fixes from Miquel Raynal: "The two most important fixes in this list are probably the SST write failure and the Qcom raw NAND controller probe failure which are due to some refactoring, otherwise there has been a series of misc fixes on the Cadence raw NAND controller driver and especially on the DMA side" * tag 'mtd/fixes-for-6.14-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux: mtd: rawnand: cadence: fix unchecked dereference mtd: spi-nor: sst: Fix SST write failure dt-bindings: mtd: cadence: document required clock-names mtd: rawnand: qcom: fix broken config in qcom_param_page_type_exec mtd: rawnand: cadence: fix incorrect device in dma_unmap_single mtd: rawnand: cadence: use dma_map_resource for sdma address mtd: rawnand: cadence: fix error code in cadence_nand_init()
This commit is contained in:
commit
a3daad8215
4 changed files with 52 additions and 24 deletions
|
@ -33,6 +33,10 @@ properties:
|
|||
clocks:
|
||||
maxItems: 1
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: nf_clk
|
||||
|
||||
dmas:
|
||||
maxItems: 1
|
||||
|
||||
|
@ -51,6 +55,7 @@ required:
|
|||
- reg-names
|
||||
- interrupts
|
||||
- clocks
|
||||
- clock-names
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
|
@ -66,7 +71,8 @@ examples:
|
|||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&nf_clk>;
|
||||
clocks = <&clk>;
|
||||
clock-names = "nf_clk";
|
||||
cdns,board-delay-ps = <4830>;
|
||||
|
||||
nand@0 {
|
||||
|
|
|
@ -471,6 +471,8 @@ struct cdns_nand_ctrl {
|
|||
struct {
|
||||
void __iomem *virt;
|
||||
dma_addr_t dma;
|
||||
dma_addr_t iova_dma;
|
||||
u32 size;
|
||||
} io;
|
||||
|
||||
int irq;
|
||||
|
@ -1835,11 +1837,11 @@ static int cadence_nand_slave_dma_transfer(struct cdns_nand_ctrl *cdns_ctrl,
|
|||
}
|
||||
|
||||
if (dir == DMA_FROM_DEVICE) {
|
||||
src_dma = cdns_ctrl->io.dma;
|
||||
src_dma = cdns_ctrl->io.iova_dma;
|
||||
dst_dma = buf_dma;
|
||||
} else {
|
||||
src_dma = buf_dma;
|
||||
dst_dma = cdns_ctrl->io.dma;
|
||||
dst_dma = cdns_ctrl->io.iova_dma;
|
||||
}
|
||||
|
||||
tx = dmaengine_prep_dma_memcpy(cdns_ctrl->dmac, dst_dma, src_dma, len,
|
||||
|
@ -1861,12 +1863,12 @@ static int cadence_nand_slave_dma_transfer(struct cdns_nand_ctrl *cdns_ctrl,
|
|||
dma_async_issue_pending(cdns_ctrl->dmac);
|
||||
wait_for_completion(&finished);
|
||||
|
||||
dma_unmap_single(cdns_ctrl->dev, buf_dma, len, dir);
|
||||
dma_unmap_single(dma_dev->dev, buf_dma, len, dir);
|
||||
|
||||
return 0;
|
||||
|
||||
err_unmap:
|
||||
dma_unmap_single(cdns_ctrl->dev, buf_dma, len, dir);
|
||||
dma_unmap_single(dma_dev->dev, buf_dma, len, dir);
|
||||
|
||||
err:
|
||||
dev_dbg(cdns_ctrl->dev, "Fall back to CPU I/O\n");
|
||||
|
@ -2869,6 +2871,7 @@ cadence_nand_irq_cleanup(int irqnum, struct cdns_nand_ctrl *cdns_ctrl)
|
|||
static int cadence_nand_init(struct cdns_nand_ctrl *cdns_ctrl)
|
||||
{
|
||||
dma_cap_mask_t mask;
|
||||
struct dma_device *dma_dev = cdns_ctrl->dmac->device;
|
||||
int ret;
|
||||
|
||||
cdns_ctrl->cdma_desc = dma_alloc_coherent(cdns_ctrl->dev,
|
||||
|
@ -2904,15 +2907,24 @@ static int cadence_nand_init(struct cdns_nand_ctrl *cdns_ctrl)
|
|||
dma_cap_set(DMA_MEMCPY, mask);
|
||||
|
||||
if (cdns_ctrl->caps1->has_dma) {
|
||||
cdns_ctrl->dmac = dma_request_channel(mask, NULL, NULL);
|
||||
if (!cdns_ctrl->dmac) {
|
||||
dev_err(cdns_ctrl->dev,
|
||||
"Unable to get a DMA channel\n");
|
||||
ret = -EBUSY;
|
||||
cdns_ctrl->dmac = dma_request_chan_by_mask(&mask);
|
||||
if (IS_ERR(cdns_ctrl->dmac)) {
|
||||
ret = dev_err_probe(cdns_ctrl->dev, PTR_ERR(cdns_ctrl->dmac),
|
||||
"%d: Failed to get a DMA channel\n", ret);
|
||||
goto disable_irq;
|
||||
}
|
||||
}
|
||||
|
||||
cdns_ctrl->io.iova_dma = dma_map_resource(dma_dev->dev, cdns_ctrl->io.dma,
|
||||
cdns_ctrl->io.size,
|
||||
DMA_BIDIRECTIONAL, 0);
|
||||
|
||||
ret = dma_mapping_error(dma_dev->dev, cdns_ctrl->io.iova_dma);
|
||||
if (ret) {
|
||||
dev_err(cdns_ctrl->dev, "Failed to map I/O resource to DMA\n");
|
||||
goto dma_release_chnl;
|
||||
}
|
||||
|
||||
nand_controller_init(&cdns_ctrl->controller);
|
||||
INIT_LIST_HEAD(&cdns_ctrl->chips);
|
||||
|
||||
|
@ -2923,18 +2935,22 @@ static int cadence_nand_init(struct cdns_nand_ctrl *cdns_ctrl)
|
|||
if (ret) {
|
||||
dev_err(cdns_ctrl->dev, "Failed to register MTD: %d\n",
|
||||
ret);
|
||||
goto dma_release_chnl;
|
||||
goto unmap_dma_resource;
|
||||
}
|
||||
|
||||
kfree(cdns_ctrl->buf);
|
||||
cdns_ctrl->buf = kzalloc(cdns_ctrl->buf_size, GFP_KERNEL);
|
||||
if (!cdns_ctrl->buf) {
|
||||
ret = -ENOMEM;
|
||||
goto dma_release_chnl;
|
||||
goto unmap_dma_resource;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
unmap_dma_resource:
|
||||
dma_unmap_resource(dma_dev->dev, cdns_ctrl->io.iova_dma,
|
||||
cdns_ctrl->io.size, DMA_BIDIRECTIONAL, 0);
|
||||
|
||||
dma_release_chnl:
|
||||
if (cdns_ctrl->dmac)
|
||||
dma_release_channel(cdns_ctrl->dmac);
|
||||
|
@ -2956,6 +2972,10 @@ free_buf_desc:
|
|||
static void cadence_nand_remove(struct cdns_nand_ctrl *cdns_ctrl)
|
||||
{
|
||||
cadence_nand_chips_cleanup(cdns_ctrl);
|
||||
if (cdns_ctrl->dmac)
|
||||
dma_unmap_resource(cdns_ctrl->dmac->device->dev,
|
||||
cdns_ctrl->io.iova_dma, cdns_ctrl->io.size,
|
||||
DMA_BIDIRECTIONAL, 0);
|
||||
cadence_nand_irq_cleanup(cdns_ctrl->irq, cdns_ctrl);
|
||||
kfree(cdns_ctrl->buf);
|
||||
dma_free_coherent(cdns_ctrl->dev, sizeof(struct cadence_nand_cdma_desc),
|
||||
|
@ -3020,7 +3040,9 @@ static int cadence_nand_dt_probe(struct platform_device *ofdev)
|
|||
cdns_ctrl->io.virt = devm_platform_get_and_ioremap_resource(ofdev, 1, &res);
|
||||
if (IS_ERR(cdns_ctrl->io.virt))
|
||||
return PTR_ERR(cdns_ctrl->io.virt);
|
||||
|
||||
cdns_ctrl->io.dma = res->start;
|
||||
cdns_ctrl->io.size = resource_size(res);
|
||||
|
||||
dt->clk = devm_clk_get(cdns_ctrl->dev, "nf_clk");
|
||||
if (IS_ERR(dt->clk))
|
||||
|
|
|
@ -1881,18 +1881,18 @@ static int qcom_param_page_type_exec(struct nand_chip *chip, const struct nand_
|
|||
nandc->regs->addr0 = 0;
|
||||
nandc->regs->addr1 = 0;
|
||||
|
||||
host->cfg0 = FIELD_PREP(CW_PER_PAGE_MASK, 0) |
|
||||
FIELD_PREP(UD_SIZE_BYTES_MASK, 512) |
|
||||
FIELD_PREP(NUM_ADDR_CYCLES_MASK, 5) |
|
||||
FIELD_PREP(SPARE_SIZE_BYTES_MASK, 0);
|
||||
nandc->regs->cfg0 = cpu_to_le32(FIELD_PREP(CW_PER_PAGE_MASK, 0) |
|
||||
FIELD_PREP(UD_SIZE_BYTES_MASK, 512) |
|
||||
FIELD_PREP(NUM_ADDR_CYCLES_MASK, 5) |
|
||||
FIELD_PREP(SPARE_SIZE_BYTES_MASK, 0));
|
||||
|
||||
host->cfg1 = FIELD_PREP(NAND_RECOVERY_CYCLES_MASK, 7) |
|
||||
FIELD_PREP(BAD_BLOCK_BYTE_NUM_MASK, 17) |
|
||||
FIELD_PREP(CS_ACTIVE_BSY, 0) |
|
||||
FIELD_PREP(BAD_BLOCK_IN_SPARE_AREA, 1) |
|
||||
FIELD_PREP(WR_RD_BSY_GAP_MASK, 2) |
|
||||
FIELD_PREP(WIDE_FLASH, 0) |
|
||||
FIELD_PREP(DEV0_CFG1_ECC_DISABLE, 1);
|
||||
nandc->regs->cfg1 = cpu_to_le32(FIELD_PREP(NAND_RECOVERY_CYCLES_MASK, 7) |
|
||||
FIELD_PREP(BAD_BLOCK_BYTE_NUM_MASK, 17) |
|
||||
FIELD_PREP(CS_ACTIVE_BSY, 0) |
|
||||
FIELD_PREP(BAD_BLOCK_IN_SPARE_AREA, 1) |
|
||||
FIELD_PREP(WR_RD_BSY_GAP_MASK, 2) |
|
||||
FIELD_PREP(WIDE_FLASH, 0) |
|
||||
FIELD_PREP(DEV0_CFG1_ECC_DISABLE, 1));
|
||||
|
||||
if (!nandc->props->qpic_version2)
|
||||
nandc->regs->ecc_buf_cfg = cpu_to_le32(ECC_CFG_ECC_DISABLE);
|
||||
|
|
|
@ -174,7 +174,7 @@ static int sst_nor_write_data(struct spi_nor *nor, loff_t to, size_t len,
|
|||
int ret;
|
||||
|
||||
nor->program_opcode = op;
|
||||
ret = spi_nor_write_data(nor, to, 1, buf);
|
||||
ret = spi_nor_write_data(nor, to, len, buf);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
WARN(ret != len, "While writing %zu byte written %i bytes\n", len, ret);
|
||||
|
|
Loading…
Add table
Reference in a new issue