aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c')
-rw-r--r--drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c76
1 files changed, 38 insertions, 38 deletions
diff --git a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
index dc8104e67506..5cdf05bcbf8f 100644
--- a/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
+++ b/drivers/mtd/nand/raw/gpmi-nand/gpmi-nand.c
@@ -149,8 +149,10 @@ static int gpmi_init(struct gpmi_nand_data *this)
int ret;
ret = pm_runtime_get_sync(this->dev);
- if (ret < 0)
+ if (ret < 0) {
+ pm_runtime_put_noidle(this->dev);
return ret;
+ }
ret = gpmi_reset_block(r->gpmi_regs, false);
if (ret)
@@ -179,9 +181,11 @@ static int gpmi_init(struct gpmi_nand_data *this)
/*
* Decouple the chip select from dma channel. We use dma0 for all
- * the chips.
+ * the chips, force all NAND RDY_BUSY inputs to be sourced from
+ * RDY_BUSY0.
*/
- writel(BM_GPMI_CTRL1_DECOUPLE_CS, r->gpmi_regs + HW_GPMI_CTRL1_SET);
+ writel(BM_GPMI_CTRL1_DECOUPLE_CS | BM_GPMI_CTRL1_GANGED_RDYBUSY,
+ r->gpmi_regs + HW_GPMI_CTRL1_SET);
err_out:
pm_runtime_mark_last_busy(this->dev);
@@ -2252,7 +2256,7 @@ static int gpmi_nfc_exec_op(struct nand_chip *chip,
void *buf_read = NULL;
const void *buf_write = NULL;
bool direct = false;
- struct completion *completion;
+ struct completion *dma_completion, *bch_completion;
unsigned long to;
if (check_only)
@@ -2263,8 +2267,10 @@ static int gpmi_nfc_exec_op(struct nand_chip *chip,
this->transfers[i].direction = DMA_NONE;
ret = pm_runtime_get_sync(this->dev);
- if (ret < 0)
+ if (ret < 0) {
+ pm_runtime_put_noidle(this->dev);
return ret;
+ }
/*
* This driver currently supports only one NAND chip. Plus, dies share
@@ -2347,22 +2353,24 @@ static int gpmi_nfc_exec_op(struct nand_chip *chip,
this->resources.bch_regs + HW_BCH_FLASH0LAYOUT1);
}
+ desc->callback = dma_irq_callback;
+ desc->callback_param = this;
+ dma_completion = &this->dma_done;
+ bch_completion = NULL;
+
+ init_completion(dma_completion);
+
if (this->bch && buf_read) {
writel(BM_BCH_CTRL_COMPLETE_IRQ_EN,
this->resources.bch_regs + HW_BCH_CTRL_SET);
- completion = &this->bch_done;
- } else {
- desc->callback = dma_irq_callback;
- desc->callback_param = this;
- completion = &this->dma_done;
+ bch_completion = &this->bch_done;
+ init_completion(bch_completion);
}
- init_completion(completion);
-
dmaengine_submit(desc);
dma_async_issue_pending(get_dma_chan(this));
- to = wait_for_completion_timeout(completion, msecs_to_jiffies(1000));
+ to = wait_for_completion_timeout(dma_completion, msecs_to_jiffies(1000));
if (!to) {
dev_err(this->dev, "DMA timeout, last DMA\n");
gpmi_dump_info(this);
@@ -2370,6 +2378,16 @@ static int gpmi_nfc_exec_op(struct nand_chip *chip,
goto unmap;
}
+ if (this->bch && buf_read) {
+ to = wait_for_completion_timeout(bch_completion, msecs_to_jiffies(1000));
+ if (!to) {
+ dev_err(this->dev, "BCH timeout, last DMA\n");
+ gpmi_dump_info(this);
+ ret = -ETIMEDOUT;
+ goto unmap;
+ }
+ }
+
writel(BM_BCH_CTRL_COMPLETE_IRQ_EN,
this->resources.bch_regs + HW_BCH_CTRL_CLR);
gpmi_clear_bch(this);
@@ -2461,43 +2479,25 @@ err_out:
}
static const struct of_device_id gpmi_nand_id_table[] = {
- {
- .compatible = "fsl,imx23-gpmi-nand",
- .data = &gpmi_devdata_imx23,
- }, {
- .compatible = "fsl,imx28-gpmi-nand",
- .data = &gpmi_devdata_imx28,
- }, {
- .compatible = "fsl,imx6q-gpmi-nand",
- .data = &gpmi_devdata_imx6q,
- }, {
- .compatible = "fsl,imx6sx-gpmi-nand",
- .data = &gpmi_devdata_imx6sx,
- }, {
- .compatible = "fsl,imx7d-gpmi-nand",
- .data = &gpmi_devdata_imx7d,
- }, {}
+ { .compatible = "fsl,imx23-gpmi-nand", .data = &gpmi_devdata_imx23, },
+ { .compatible = "fsl,imx28-gpmi-nand", .data = &gpmi_devdata_imx28, },
+ { .compatible = "fsl,imx6q-gpmi-nand", .data = &gpmi_devdata_imx6q, },
+ { .compatible = "fsl,imx6sx-gpmi-nand", .data = &gpmi_devdata_imx6sx, },
+ { .compatible = "fsl,imx7d-gpmi-nand", .data = &gpmi_devdata_imx7d,},
+ {}
};
MODULE_DEVICE_TABLE(of, gpmi_nand_id_table);
static int gpmi_nand_probe(struct platform_device *pdev)
{
struct gpmi_nand_data *this;
- const struct of_device_id *of_id;
int ret;
this = devm_kzalloc(&pdev->dev, sizeof(*this), GFP_KERNEL);
if (!this)
return -ENOMEM;
- of_id = of_match_device(gpmi_nand_id_table, &pdev->dev);
- if (of_id) {
- this->devdata = of_id->data;
- } else {
- dev_err(&pdev->dev, "Failed to find the right device id.\n");
- return -ENODEV;
- }
-
+ this->devdata = of_device_get_match_data(&pdev->dev);
platform_set_drvdata(pdev, this);
this->pdev = pdev;
this->dev = &pdev->dev;