aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/mtd/nand/omap2.c78
1 files changed, 50 insertions, 28 deletions
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index 3578c633e97e..27293e328517 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -137,7 +137,8 @@ struct omap_nand_info {
137 unsigned long mem_size; 137 unsigned long mem_size;
138 struct completion comp; 138 struct completion comp;
139 struct dma_chan *dma; 139 struct dma_chan *dma;
140 int gpmc_irq; 140 int gpmc_irq_fifo;
141 int gpmc_irq_count;
141 enum { 142 enum {
142 OMAP_NAND_IO_READ = 0, /* read */ 143 OMAP_NAND_IO_READ = 0, /* read */
143 OMAP_NAND_IO_WRITE, /* write */ 144 OMAP_NAND_IO_WRITE, /* write */
@@ -553,14 +554,12 @@ static irqreturn_t omap_nand_irq(int this_irq, void *dev)
553{ 554{
554 struct omap_nand_info *info = (struct omap_nand_info *) dev; 555 struct omap_nand_info *info = (struct omap_nand_info *) dev;
555 u32 bytes; 556 u32 bytes;
556 u32 irq_stat;
557 557
558 irq_stat = gpmc_read_status(GPMC_GET_IRQ_STATUS);
559 bytes = readl(info->reg.gpmc_prefetch_status); 558 bytes = readl(info->reg.gpmc_prefetch_status);
560 bytes = GPMC_PREFETCH_STATUS_FIFO_CNT(bytes); 559 bytes = GPMC_PREFETCH_STATUS_FIFO_CNT(bytes);
561 bytes = bytes & 0xFFFC; /* io in multiple of 4 bytes */ 560 bytes = bytes & 0xFFFC; /* io in multiple of 4 bytes */
562 if (info->iomode == OMAP_NAND_IO_WRITE) { /* checks for write io */ 561 if (info->iomode == OMAP_NAND_IO_WRITE) { /* checks for write io */
563 if (irq_stat & 0x2) 562 if (this_irq == info->gpmc_irq_count)
564 goto done; 563 goto done;
565 564
566 if (info->buf_len && (info->buf_len < bytes)) 565 if (info->buf_len && (info->buf_len < bytes))
@@ -577,20 +576,17 @@ static irqreturn_t omap_nand_irq(int this_irq, void *dev)
577 (u32 *)info->buf, bytes >> 2); 576 (u32 *)info->buf, bytes >> 2);
578 info->buf = info->buf + bytes; 577 info->buf = info->buf + bytes;
579 578
580 if (irq_stat & 0x2) 579 if (this_irq == info->gpmc_irq_count)
581 goto done; 580 goto done;
582 } 581 }
583 gpmc_cs_configure(info->gpmc_cs, GPMC_SET_IRQ_STATUS, irq_stat);
584 582
585 return IRQ_HANDLED; 583 return IRQ_HANDLED;
586 584
587done: 585done:
588 complete(&info->comp); 586 complete(&info->comp);
589 /* disable irq */
590 gpmc_cs_configure(info->gpmc_cs, GPMC_ENABLE_IRQ, 0);
591 587
592 /* clear status */ 588 disable_irq_nosync(info->gpmc_irq_fifo);
593 gpmc_cs_configure(info->gpmc_cs, GPMC_SET_IRQ_STATUS, irq_stat); 589 disable_irq_nosync(info->gpmc_irq_count);
594 590
595 return IRQ_HANDLED; 591 return IRQ_HANDLED;
596} 592}
@@ -624,9 +620,9 @@ static void omap_read_buf_irq_pref(struct mtd_info *mtd, u_char *buf, int len)
624 goto out_copy; 620 goto out_copy;
625 621
626 info->buf_len = len; 622 info->buf_len = len;
627 /* enable irq */ 623
628 gpmc_cs_configure(info->gpmc_cs, GPMC_ENABLE_IRQ, 624 enable_irq(info->gpmc_irq_count);
629 (GPMC_IRQ_FIFOEVENTENABLE | GPMC_IRQ_COUNT_EVENT)); 625 enable_irq(info->gpmc_irq_fifo);
630 626
631 /* waiting for read to complete */ 627 /* waiting for read to complete */
632 wait_for_completion(&info->comp); 628 wait_for_completion(&info->comp);
@@ -674,12 +670,13 @@ static void omap_write_buf_irq_pref(struct mtd_info *mtd,
674 goto out_copy; 670 goto out_copy;
675 671
676 info->buf_len = len; 672 info->buf_len = len;
677 /* enable irq */ 673
678 gpmc_cs_configure(info->gpmc_cs, GPMC_ENABLE_IRQ, 674 enable_irq(info->gpmc_irq_count);
679 (GPMC_IRQ_FIFOEVENTENABLE | GPMC_IRQ_COUNT_EVENT)); 675 enable_irq(info->gpmc_irq_fifo);
680 676
681 /* waiting for write to complete */ 677 /* waiting for write to complete */
682 wait_for_completion(&info->comp); 678 wait_for_completion(&info->comp);
679
683 /* wait for data to flushed-out before reset the prefetch */ 680 /* wait for data to flushed-out before reset the prefetch */
684 tim = 0; 681 tim = 0;
685 limit = (loops_per_jiffy * msecs_to_jiffies(OMAP_NAND_TIMEOUT_MS)); 682 limit = (loops_per_jiffy * msecs_to_jiffies(OMAP_NAND_TIMEOUT_MS));
@@ -1300,9 +1297,6 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
1300 info->nand.options = pdata->devsize; 1297 info->nand.options = pdata->devsize;
1301 info->nand.options |= NAND_SKIP_BBTSCAN; 1298 info->nand.options |= NAND_SKIP_BBTSCAN;
1302 1299
1303 /* NAND write protect off */
1304 gpmc_cs_configure(info->gpmc_cs, GPMC_CONFIG_WP, 0);
1305
1306 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1300 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1307 if (res == NULL) { 1301 if (res == NULL) {
1308 err = -EINVAL; 1302 err = -EINVAL;
@@ -1392,17 +1386,39 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
1392 break; 1386 break;
1393 1387
1394 case NAND_OMAP_PREFETCH_IRQ: 1388 case NAND_OMAP_PREFETCH_IRQ:
1395 err = request_irq(pdata->gpmc_irq, 1389 info->gpmc_irq_fifo = platform_get_irq(pdev, 0);
1396 omap_nand_irq, IRQF_SHARED, "gpmc-nand", info); 1390 if (info->gpmc_irq_fifo <= 0) {
1391 dev_err(&pdev->dev, "error getting fifo irq\n");
1392 err = -ENODEV;
1393 goto out_release_mem_region;
1394 }
1395 err = request_irq(info->gpmc_irq_fifo, omap_nand_irq,
1396 IRQF_SHARED, "gpmc-nand-fifo", info);
1397 if (err) { 1397 if (err) {
1398 dev_err(&pdev->dev, "requesting irq(%d) error:%d", 1398 dev_err(&pdev->dev, "requesting irq(%d) error:%d",
1399 pdata->gpmc_irq, err); 1399 info->gpmc_irq_fifo, err);
1400 info->gpmc_irq_fifo = 0;
1401 goto out_release_mem_region;
1402 }
1403
1404 info->gpmc_irq_count = platform_get_irq(pdev, 1);
1405 if (info->gpmc_irq_count <= 0) {
1406 dev_err(&pdev->dev, "error getting count irq\n");
1407 err = -ENODEV;
1408 goto out_release_mem_region;
1409 }
1410 err = request_irq(info->gpmc_irq_count, omap_nand_irq,
1411 IRQF_SHARED, "gpmc-nand-count", info);
1412 if (err) {
1413 dev_err(&pdev->dev, "requesting irq(%d) error:%d",
1414 info->gpmc_irq_count, err);
1415 info->gpmc_irq_count = 0;
1400 goto out_release_mem_region; 1416 goto out_release_mem_region;
1401 } else {
1402 info->gpmc_irq = pdata->gpmc_irq;
1403 info->nand.read_buf = omap_read_buf_irq_pref;
1404 info->nand.write_buf = omap_write_buf_irq_pref;
1405 } 1417 }
1418
1419 info->nand.read_buf = omap_read_buf_irq_pref;
1420 info->nand.write_buf = omap_write_buf_irq_pref;
1421
1406 break; 1422 break;
1407 1423
1408 default: 1424 default:
@@ -1490,6 +1506,10 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
1490out_release_mem_region: 1506out_release_mem_region:
1491 if (info->dma) 1507 if (info->dma)
1492 dma_release_channel(info->dma); 1508 dma_release_channel(info->dma);
1509 if (info->gpmc_irq_count > 0)
1510 free_irq(info->gpmc_irq_count, info);
1511 if (info->gpmc_irq_fifo > 0)
1512 free_irq(info->gpmc_irq_fifo, info);
1493 release_mem_region(info->phys_base, info->mem_size); 1513 release_mem_region(info->phys_base, info->mem_size);
1494out_free_info: 1514out_free_info:
1495 kfree(info); 1515 kfree(info);
@@ -1508,8 +1528,10 @@ static int omap_nand_remove(struct platform_device *pdev)
1508 if (info->dma) 1528 if (info->dma)
1509 dma_release_channel(info->dma); 1529 dma_release_channel(info->dma);
1510 1530
1511 if (info->gpmc_irq) 1531 if (info->gpmc_irq_count > 0)
1512 free_irq(info->gpmc_irq, info); 1532 free_irq(info->gpmc_irq_count, info);
1533 if (info->gpmc_irq_fifo > 0)
1534 free_irq(info->gpmc_irq_fifo, info);
1513 1535
1514 /* Release NAND device, its internal structures and partitions */ 1536 /* Release NAND device, its internal structures and partitions */
1515 nand_release(&info->mtd); 1537 nand_release(&info->mtd);