diff options
Diffstat (limited to 'drivers/mtd/nand/denali.c')
-rw-r--r-- | drivers/mtd/nand/denali.c | 162 |
1 files changed, 30 insertions, 132 deletions
diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c index e706a237170f..0c8bb6bf8424 100644 --- a/drivers/mtd/nand/denali.c +++ b/drivers/mtd/nand/denali.c | |||
@@ -16,14 +16,12 @@ | |||
16 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | 16 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. |
17 | * | 17 | * |
18 | */ | 18 | */ |
19 | |||
20 | #include <linux/interrupt.h> | 19 | #include <linux/interrupt.h> |
21 | #include <linux/delay.h> | 20 | #include <linux/delay.h> |
22 | #include <linux/dma-mapping.h> | 21 | #include <linux/dma-mapping.h> |
23 | #include <linux/wait.h> | 22 | #include <linux/wait.h> |
24 | #include <linux/mutex.h> | 23 | #include <linux/mutex.h> |
25 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
26 | #include <linux/pci.h> | ||
27 | #include <linux/mtd/mtd.h> | 25 | #include <linux/mtd/mtd.h> |
28 | #include <linux/module.h> | 26 | #include <linux/module.h> |
29 | 27 | ||
@@ -89,13 +87,6 @@ MODULE_PARM_DESC(onfi_timing_mode, "Overrides default ONFI setting." | |||
89 | * format the bank into the proper bits for the controller */ | 87 | * format the bank into the proper bits for the controller */ |
90 | #define BANK(x) ((x) << 24) | 88 | #define BANK(x) ((x) << 24) |
91 | 89 | ||
92 | /* List of platforms this NAND controller has be integrated into */ | ||
93 | static const struct pci_device_id denali_pci_ids[] = { | ||
94 | { PCI_VDEVICE(INTEL, 0x0701), INTEL_CE4100 }, | ||
95 | { PCI_VDEVICE(INTEL, 0x0809), INTEL_MRST }, | ||
96 | { /* end: all zeroes */ } | ||
97 | }; | ||
98 | |||
99 | /* forward declarations */ | 90 | /* forward declarations */ |
100 | static void clear_interrupts(struct denali_nand_info *denali); | 91 | static void clear_interrupts(struct denali_nand_info *denali); |
101 | static uint32_t wait_for_irq(struct denali_nand_info *denali, | 92 | static uint32_t wait_for_irq(struct denali_nand_info *denali, |
@@ -699,7 +690,7 @@ static uint32_t wait_for_irq(struct denali_nand_info *denali, uint32_t irq_mask) | |||
699 | 690 | ||
700 | if (comp_res == 0) { | 691 | if (comp_res == 0) { |
701 | /* timeout */ | 692 | /* timeout */ |
702 | printk(KERN_ERR "timeout occurred, status = 0x%x, mask = 0x%x\n", | 693 | pr_err("timeout occurred, status = 0x%x, mask = 0x%x\n", |
703 | intr_status, irq_mask); | 694 | intr_status, irq_mask); |
704 | 695 | ||
705 | intr_status = 0; | 696 | intr_status = 0; |
@@ -1305,8 +1296,7 @@ static void denali_cmdfunc(struct mtd_info *mtd, unsigned int cmd, int col, | |||
1305 | /* TODO: Read OOB data */ | 1296 | /* TODO: Read OOB data */ |
1306 | break; | 1297 | break; |
1307 | default: | 1298 | default: |
1308 | printk(KERN_ERR ": unsupported command" | 1299 | pr_err(": unsupported command received 0x%x\n", cmd); |
1309 | " received 0x%x\n", cmd); | ||
1310 | break; | 1300 | break; |
1311 | } | 1301 | } |
1312 | } | 1302 | } |
@@ -1425,107 +1415,48 @@ void denali_drv_init(struct denali_nand_info *denali) | |||
1425 | denali->irq_status = 0; | 1415 | denali->irq_status = 0; |
1426 | } | 1416 | } |
1427 | 1417 | ||
1428 | /* driver entry point */ | 1418 | int denali_init(struct denali_nand_info *denali) |
1429 | static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | ||
1430 | { | 1419 | { |
1431 | int ret = -ENODEV; | 1420 | int ret; |
1432 | resource_size_t csr_base, mem_base; | ||
1433 | unsigned long csr_len, mem_len; | ||
1434 | struct denali_nand_info *denali; | ||
1435 | |||
1436 | denali = kzalloc(sizeof(*denali), GFP_KERNEL); | ||
1437 | if (!denali) | ||
1438 | return -ENOMEM; | ||
1439 | 1421 | ||
1440 | ret = pci_enable_device(dev); | 1422 | if (denali->platform == INTEL_CE4100) { |
1441 | if (ret) { | ||
1442 | printk(KERN_ERR "Spectra: pci_enable_device failed.\n"); | ||
1443 | goto failed_alloc_memery; | ||
1444 | } | ||
1445 | |||
1446 | if (id->driver_data == INTEL_CE4100) { | ||
1447 | /* Due to a silicon limitation, we can only support | 1423 | /* Due to a silicon limitation, we can only support |
1448 | * ONFI timing mode 1 and below. | 1424 | * ONFI timing mode 1 and below. |
1449 | */ | 1425 | */ |
1450 | if (onfi_timing_mode < -1 || onfi_timing_mode > 1) { | 1426 | if (onfi_timing_mode < -1 || onfi_timing_mode > 1) { |
1451 | printk(KERN_ERR "Intel CE4100 only supports" | 1427 | pr_err("Intel CE4100 only supports ONFI timing mode 1 or below\n"); |
1452 | " ONFI timing mode 1 or below\n"); | 1428 | return -EINVAL; |
1453 | ret = -EINVAL; | ||
1454 | goto failed_enable_dev; | ||
1455 | } | ||
1456 | denali->platform = INTEL_CE4100; | ||
1457 | mem_base = pci_resource_start(dev, 0); | ||
1458 | mem_len = pci_resource_len(dev, 1); | ||
1459 | csr_base = pci_resource_start(dev, 1); | ||
1460 | csr_len = pci_resource_len(dev, 1); | ||
1461 | } else { | ||
1462 | denali->platform = INTEL_MRST; | ||
1463 | csr_base = pci_resource_start(dev, 0); | ||
1464 | csr_len = pci_resource_len(dev, 0); | ||
1465 | mem_base = pci_resource_start(dev, 1); | ||
1466 | mem_len = pci_resource_len(dev, 1); | ||
1467 | if (!mem_len) { | ||
1468 | mem_base = csr_base + csr_len; | ||
1469 | mem_len = csr_len; | ||
1470 | } | 1429 | } |
1471 | } | 1430 | } |
1472 | 1431 | ||
1473 | /* Is 32-bit DMA supported? */ | 1432 | /* Is 32-bit DMA supported? */ |
1474 | ret = dma_set_mask(&dev->dev, DMA_BIT_MASK(32)); | 1433 | ret = dma_set_mask(denali->dev, DMA_BIT_MASK(32)); |
1475 | if (ret) { | 1434 | if (ret) { |
1476 | printk(KERN_ERR "Spectra: no usable DMA configuration\n"); | 1435 | pr_err("Spectra: no usable DMA configuration\n"); |
1477 | goto failed_enable_dev; | 1436 | return ret; |
1478 | } | 1437 | } |
1479 | denali->buf.dma_buf = dma_map_single(&dev->dev, denali->buf.buf, | 1438 | denali->buf.dma_buf = dma_map_single(denali->dev, denali->buf.buf, |
1480 | DENALI_BUF_SIZE, | 1439 | DENALI_BUF_SIZE, |
1481 | DMA_BIDIRECTIONAL); | 1440 | DMA_BIDIRECTIONAL); |
1482 | 1441 | ||
1483 | if (dma_mapping_error(&dev->dev, denali->buf.dma_buf)) { | 1442 | if (dma_mapping_error(denali->dev, denali->buf.dma_buf)) { |
1484 | dev_err(&dev->dev, "Spectra: failed to map DMA buffer\n"); | 1443 | dev_err(denali->dev, "Spectra: failed to map DMA buffer\n"); |
1485 | goto failed_enable_dev; | 1444 | return -EIO; |
1486 | } | ||
1487 | |||
1488 | pci_set_master(dev); | ||
1489 | denali->dev = &dev->dev; | ||
1490 | denali->mtd.dev.parent = &dev->dev; | ||
1491 | |||
1492 | ret = pci_request_regions(dev, DENALI_NAND_NAME); | ||
1493 | if (ret) { | ||
1494 | printk(KERN_ERR "Spectra: Unable to request memory regions\n"); | ||
1495 | goto failed_dma_map; | ||
1496 | } | ||
1497 | |||
1498 | denali->flash_reg = ioremap_nocache(csr_base, csr_len); | ||
1499 | if (!denali->flash_reg) { | ||
1500 | printk(KERN_ERR "Spectra: Unable to remap memory region\n"); | ||
1501 | ret = -ENOMEM; | ||
1502 | goto failed_req_regions; | ||
1503 | } | ||
1504 | |||
1505 | denali->flash_mem = ioremap_nocache(mem_base, mem_len); | ||
1506 | if (!denali->flash_mem) { | ||
1507 | printk(KERN_ERR "Spectra: ioremap_nocache failed!"); | ||
1508 | ret = -ENOMEM; | ||
1509 | goto failed_remap_reg; | ||
1510 | } | 1445 | } |
1511 | 1446 | denali->mtd.dev.parent = denali->dev; | |
1512 | denali_hw_init(denali); | 1447 | denali_hw_init(denali); |
1513 | denali_drv_init(denali); | 1448 | denali_drv_init(denali); |
1514 | 1449 | ||
1515 | /* denali_isr register is done after all the hardware | 1450 | /* denali_isr register is done after all the hardware |
1516 | * initilization is finished*/ | 1451 | * initilization is finished*/ |
1517 | if (request_irq(dev->irq, denali_isr, IRQF_SHARED, | 1452 | if (request_irq(denali->irq, denali_isr, IRQF_SHARED, |
1518 | DENALI_NAND_NAME, denali)) { | 1453 | DENALI_NAND_NAME, denali)) { |
1519 | printk(KERN_ERR "Spectra: Unable to allocate IRQ\n"); | 1454 | pr_err("Spectra: Unable to allocate IRQ\n"); |
1520 | ret = -ENODEV; | 1455 | return -ENODEV; |
1521 | goto failed_remap_mem; | ||
1522 | } | 1456 | } |
1523 | 1457 | ||
1524 | /* now that our ISR is registered, we can enable interrupts */ | 1458 | /* now that our ISR is registered, we can enable interrupts */ |
1525 | denali_set_intr_modes(denali, true); | 1459 | denali_set_intr_modes(denali, true); |
1526 | |||
1527 | pci_set_drvdata(dev, denali); | ||
1528 | |||
1529 | denali->mtd.name = "denali-nand"; | 1460 | denali->mtd.name = "denali-nand"; |
1530 | denali->mtd.owner = THIS_MODULE; | 1461 | denali->mtd.owner = THIS_MODULE; |
1531 | denali->mtd.priv = &denali->nand; | 1462 | denali->mtd.priv = &denali->nand; |
@@ -1549,8 +1480,7 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
1549 | */ | 1480 | */ |
1550 | if (denali->mtd.writesize > NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE) { | 1481 | if (denali->mtd.writesize > NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE) { |
1551 | ret = -ENODEV; | 1482 | ret = -ENODEV; |
1552 | printk(KERN_ERR "Spectra: device size not supported by this " | 1483 | pr_err("Spectra: device size not supported by this version of MTD."); |
1553 | "version of MTD."); | ||
1554 | goto failed_req_irq; | 1484 | goto failed_req_irq; |
1555 | } | 1485 | } |
1556 | 1486 | ||
@@ -1602,8 +1532,8 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
1602 | } else if (denali->mtd.oobsize < (denali->bbtskipbytes + | 1532 | } else if (denali->mtd.oobsize < (denali->bbtskipbytes + |
1603 | ECC_8BITS * (denali->mtd.writesize / | 1533 | ECC_8BITS * (denali->mtd.writesize / |
1604 | ECC_SECTOR_SIZE))) { | 1534 | ECC_SECTOR_SIZE))) { |
1605 | printk(KERN_ERR "Your NAND chip OOB is not large enough to" | 1535 | pr_err("Your NAND chip OOB is not large enough to \ |
1606 | " contain 8bit ECC correction codes"); | 1536 | contain 8bit ECC correction codes"); |
1607 | goto failed_req_irq; | 1537 | goto failed_req_irq; |
1608 | } else { | 1538 | } else { |
1609 | denali->nand.ecc.strength = 8; | 1539 | denali->nand.ecc.strength = 8; |
@@ -1655,56 +1585,24 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
1655 | 1585 | ||
1656 | ret = mtd_device_register(&denali->mtd, NULL, 0); | 1586 | ret = mtd_device_register(&denali->mtd, NULL, 0); |
1657 | if (ret) { | 1587 | if (ret) { |
1658 | dev_err(&dev->dev, "Spectra: Failed to register MTD: %d\n", | 1588 | dev_err(denali->dev, "Spectra: Failed to register MTD: %d\n", |
1659 | ret); | 1589 | ret); |
1660 | goto failed_req_irq; | 1590 | goto failed_req_irq; |
1661 | } | 1591 | } |
1662 | return 0; | 1592 | return 0; |
1663 | 1593 | ||
1664 | failed_req_irq: | 1594 | failed_req_irq: |
1665 | denali_irq_cleanup(dev->irq, denali); | 1595 | denali_irq_cleanup(denali->irq, denali); |
1666 | failed_remap_mem: | 1596 | |
1667 | iounmap(denali->flash_mem); | ||
1668 | failed_remap_reg: | ||
1669 | iounmap(denali->flash_reg); | ||
1670 | failed_req_regions: | ||
1671 | pci_release_regions(dev); | ||
1672 | failed_dma_map: | ||
1673 | dma_unmap_single(&dev->dev, denali->buf.dma_buf, DENALI_BUF_SIZE, | ||
1674 | DMA_BIDIRECTIONAL); | ||
1675 | failed_enable_dev: | ||
1676 | pci_disable_device(dev); | ||
1677 | failed_alloc_memery: | ||
1678 | kfree(denali); | ||
1679 | return ret; | 1597 | return ret; |
1680 | } | 1598 | } |
1599 | EXPORT_SYMBOL(denali_init); | ||
1681 | 1600 | ||
1682 | /* driver exit point */ | 1601 | /* driver exit point */ |
1683 | static void denali_pci_remove(struct pci_dev *dev) | 1602 | void denali_remove(struct denali_nand_info *denali) |
1684 | { | 1603 | { |
1685 | struct denali_nand_info *denali = pci_get_drvdata(dev); | 1604 | denali_irq_cleanup(denali->irq, denali); |
1686 | 1605 | dma_unmap_single(denali->dev, denali->buf.dma_buf, DENALI_BUF_SIZE, | |
1687 | nand_release(&denali->mtd); | 1606 | DMA_BIDIRECTIONAL); |
1688 | |||
1689 | denali_irq_cleanup(dev->irq, denali); | ||
1690 | |||
1691 | iounmap(denali->flash_reg); | ||
1692 | iounmap(denali->flash_mem); | ||
1693 | pci_release_regions(dev); | ||
1694 | pci_disable_device(dev); | ||
1695 | dma_unmap_single(&dev->dev, denali->buf.dma_buf, DENALI_BUF_SIZE, | ||
1696 | DMA_BIDIRECTIONAL); | ||
1697 | pci_set_drvdata(dev, NULL); | ||
1698 | kfree(denali); | ||
1699 | } | 1607 | } |
1700 | 1608 | EXPORT_SYMBOL(denali_remove); | |
1701 | MODULE_DEVICE_TABLE(pci, denali_pci_ids); | ||
1702 | |||
1703 | static struct pci_driver denali_pci_driver = { | ||
1704 | .name = DENALI_NAND_NAME, | ||
1705 | .id_table = denali_pci_ids, | ||
1706 | .probe = denali_pci_probe, | ||
1707 | .remove = denali_pci_remove, | ||
1708 | }; | ||
1709 | |||
1710 | module_pci_driver(denali_pci_driver); | ||