diff options
Diffstat (limited to 'drivers/mtd/nand/raw/arasan-nand-controller.c')
| -rw-r--r-- | drivers/mtd/nand/raw/arasan-nand-controller.c | 65 |
1 files changed, 32 insertions, 33 deletions
diff --git a/drivers/mtd/nand/raw/arasan-nand-controller.c b/drivers/mtd/nand/raw/arasan-nand-controller.c index 906eef70cb6d..865754737f5f 100644 --- a/drivers/mtd/nand/raw/arasan-nand-controller.c +++ b/drivers/mtd/nand/raw/arasan-nand-controller.c @@ -481,7 +481,7 @@ static int anfc_read_page_hw_ecc(struct nand_chip *chip, u8 *buf, } bf = nand_check_erased_ecc_chunk(raw_buf, chip->ecc.size, - NULL, 0, NULL, 0, + anand->hw_ecc, chip->ecc.bytes, NULL, 0, chip->ecc.strength); if (bf > 0) { mtd->ecc_stats.corrected += bf; @@ -515,6 +515,7 @@ static int anfc_write_page_hw_ecc(struct nand_chip *chip, const u8 *buf, struct mtd_info *mtd = nand_to_mtd(chip); unsigned int len = mtd->writesize + (oob_required ? mtd->oobsize : 0); dma_addr_t dma_addr; + u8 status; int ret; struct anfc_op nfc_op = { .pkt_reg = @@ -561,10 +562,21 @@ static int anfc_write_page_hw_ecc(struct nand_chip *chip, const u8 *buf, } /* Spare data is not protected */ - if (oob_required) + if (oob_required) { ret = nand_write_oob_std(chip, page); + if (ret) + return ret; + } - return ret; + /* Check write status on the chip side */ + ret = nand_status_op(chip, &status); + if (ret) + return ret; + + if (status & NAND_STATUS_FAIL) + return -EIO; + + return 0; } static int anfc_sel_write_page_hw_ecc(struct nand_chip *chip, const u8 *buf, @@ -1348,7 +1360,7 @@ static void anfc_chips_cleanup(struct arasan_nfc *nfc) static int anfc_chips_init(struct arasan_nfc *nfc) { - struct device_node *np = nfc->dev->of_node, *nand_np; + struct device_node *np = nfc->dev->of_node; int nchips = of_get_child_count(np); int ret; @@ -1358,10 +1370,9 @@ static int anfc_chips_init(struct arasan_nfc *nfc) return -EINVAL; } - for_each_child_of_node(np, nand_np) { + for_each_child_of_node_scoped(np, nand_np) { ret = anfc_chip_init(nfc, nand_np); if (ret) { - of_node_put(nand_np); anfc_chips_cleanup(nfc); break; } @@ -1398,8 +1409,8 @@ static int anfc_parse_cs(struct arasan_nfc *nfc) * case, the "not" chosen CS is assigned to nfc->spare_cs and selected * whenever a GPIO CS must be asserted. */ - if (nfc->cs_array && nfc->ncs > 2) { - if (!nfc->cs_array[0] && !nfc->cs_array[1]) { + if (nfc->cs_array) { + if (nfc->ncs > 2 && !nfc->cs_array[0] && !nfc->cs_array[1]) { dev_err(nfc->dev, "Assign a single native CS when using GPIOs\n"); return -EINVAL; @@ -1440,55 +1451,43 @@ static int anfc_probe(struct platform_device *pdev) anfc_reset(nfc); - nfc->controller_clk = devm_clk_get(&pdev->dev, "controller"); + nfc->controller_clk = devm_clk_get_enabled(&pdev->dev, "controller"); if (IS_ERR(nfc->controller_clk)) return PTR_ERR(nfc->controller_clk); - nfc->bus_clk = devm_clk_get(&pdev->dev, "bus"); + nfc->bus_clk = devm_clk_get_enabled(&pdev->dev, "bus"); if (IS_ERR(nfc->bus_clk)) return PTR_ERR(nfc->bus_clk); - ret = clk_prepare_enable(nfc->controller_clk); - if (ret) - return ret; - - ret = clk_prepare_enable(nfc->bus_clk); - if (ret) - goto disable_controller_clk; - ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(64)); if (ret) - goto disable_bus_clk; + return ret; ret = anfc_parse_cs(nfc); if (ret) - goto disable_bus_clk; + return ret; ret = anfc_chips_init(nfc); if (ret) - goto disable_bus_clk; + return ret; platform_set_drvdata(pdev, nfc); return 0; - -disable_bus_clk: - clk_disable_unprepare(nfc->bus_clk); - -disable_controller_clk: - clk_disable_unprepare(nfc->controller_clk); - - return ret; } static void anfc_remove(struct platform_device *pdev) { + int i; struct arasan_nfc *nfc = platform_get_drvdata(pdev); - anfc_chips_cleanup(nfc); + for (i = 0; i < nfc->ncs; i++) { + if (nfc->cs_array[i]) { + gpiod_put(nfc->cs_array[i]); + } + } - clk_disable_unprepare(nfc->bus_clk); - clk_disable_unprepare(nfc->controller_clk); + anfc_chips_cleanup(nfc); } static const struct of_device_id anfc_ids[] = { @@ -1508,7 +1507,7 @@ static struct platform_driver anfc_driver = { .of_match_table = anfc_ids, }, .probe = anfc_probe, - .remove_new = anfc_remove, + .remove = anfc_remove, }; module_platform_driver(anfc_driver); |
