This adds support for MMIO IDE device like CompactFlash
in TrueIDE mode.
Signed-off-by: Anton Vorontsov <[email protected]>
Signed-off-by: Vitaly Bordug <[email protected]>
---
drivers/ide/Kconfig | 6 +
drivers/ide/legacy/Makefile | 2
drivers/ide/legacy/mmio-ide.c | 211 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 219 insertions(+), 0 deletions(-)
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig
index b1a9b81..0dab799 100644
--- a/drivers/ide/Kconfig
+++ b/drivers/ide/Kconfig
@@ -946,6 +946,12 @@ config BLK_DEV_MPC8xx_IDE
If unsure, say N.
+config BLK_DEV_MMIOIDE
+ tristate "Memory Mapped IDE support"
+ help
+ This is the IDE driver for Memory Mapped IDE devices. Like
+ Compact Flash running in True IDE mode.
+
choice
prompt "Type of MPC8xx IDE interface"
depends on BLK_DEV_MPC8xx_IDE
diff --git a/drivers/ide/legacy/Makefile b/drivers/ide/legacy/Makefile
index c797106..61bd21e 100644
--- a/drivers/ide/legacy/Makefile
+++ b/drivers/ide/legacy/Makefile
@@ -7,6 +7,8 @@ obj-$(CONFIG_BLK_DEV_UMC8672) += umc8672.o
obj-$(CONFIG_BLK_DEV_IDECS) += ide-cs.o
+obj-$(CONFIG_BLK_DEV_MMIOIDE) += mmio-ide.o
+
# Last of all
obj-$(CONFIG_BLK_DEV_HD) += hd.o
diff --git a/drivers/ide/legacy/mmio-ide.c b/drivers/ide/legacy/mmio-ide.c
new file mode 100644
index 0000000..77fb7dd
--- /dev/null
+++ b/drivers/ide/legacy/mmio-ide.c
@@ -0,0 +1,211 @@
+/*
+ * Memory Mapped IDE driver
+ *
+ * Author: Kumar Gala <[email protected]>
+ *
+ * 2007 (c) MontaVista Software, Inc.
+ * Vitaly Bordug <[email protected]>
+ * Anton Vorontsov <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/ide.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+#include <linux/mmio-ide.h>
+#include <asm/io.h>
+
+static struct {
+ void __iomem *mmio_ide_mapbase;
+ void __iomem *mmio_ide_alt_mapbase;
+ ide_hwif_t *hwif;
+ int index;
+} hwif_prop;
+
+static ide_hwif_t * __devinit mmio_ide_locate_hwif(void __iomem * base,
+ void __iomem * ctrl, struct mmio_ide_platform_data *pdata, int irq)
+{
+ unsigned long port = (unsigned long)base;
+ ide_hwif_t *hwif;
+ int index, i;
+
+ for (index = 0; index < MAX_HWIFS; ++index) {
+ hwif = ide_hwifs + index;
+ if (hwif->io_ports[IDE_DATA_OFFSET] == port)
+ goto found;
+ }
+
+ for (index = 0; index < MAX_HWIFS; ++index) {
+ hwif = ide_hwifs + index;
+ if (hwif->io_ports[IDE_DATA_OFFSET] == 0)
+ goto found;
+ }
+
+ return NULL;
+
+found:
+
+ hwif->hw.io_ports[IDE_DATA_OFFSET] = port;
+
+ port += pdata->regaddr_step + pdata->byte_lanes_swapping;
+ for (i = IDE_ERROR_OFFSET; i <= IDE_STATUS_OFFSET;
+ i++, port += pdata->regaddr_step)
+ hwif->hw.io_ports[i] = port;
+
+ hwif->hw.io_ports[IDE_CONTROL_OFFSET] = (unsigned long)ctrl +
+ 6 * pdata->regaddr_step + pdata->byte_lanes_swapping;
+
+ memcpy(hwif->io_ports, hwif->hw.io_ports, sizeof(hwif->hw.io_ports));
+ hwif->hw.irq = hwif->irq = irq;
+ hwif->selectproc = pdata->selectproc;
+
+ hwif->hw.dma = NO_DMA;
+ hwif->hw.chipset = ide_generic;
+
+ hwif->mmio = 2;
+ pdata->mmiops(hwif);
+ hwif_prop.hwif = hwif;
+ hwif_prop.index = index;
+
+ return hwif;
+}
+
+static int __devinit mmio_ide_probe(struct platform_device *pdev)
+{
+ struct resource *res_base, *res_alt, *res_irq;
+ ide_hwif_t *hwif;
+ struct mmio_ide_platform_data *pdata;
+ int ret = 0;
+
+ pdata = (struct mmio_ide_platform_data*)pdev->dev.platform_data;
+
+ /* get a pointer to the register memory */
+ res_base = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ res_alt = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+
+ if ((!res_base) || (!res_alt) || (!res_irq)) {
+ ret = -ENODEV;
+ goto out;
+ }
+
+ if (!request_mem_region(res_base->start, res_base->end -
+ res_base->start + 1, pdev->name)) {
+ dev_dbg(&pdev->dev, "%s: request_mem_region of base failed\n",
+ pdev->name);
+ ret = -EBUSY;
+ goto out;
+ }
+
+ if (!request_mem_region(res_alt->start, res_alt->end -
+ res_alt->start + 1, pdev->name)) {
+ dev_dbg(&pdev->dev, "%s: request_mem_region of alt failed\n",
+ pdev->name);
+ ret = -EBUSY;
+ goto release_base;
+ }
+
+ hwif_prop.mmio_ide_mapbase = ioremap(res_base->start, res_base->end -
+ res_base->start + 1);
+ if (!hwif_prop.mmio_ide_mapbase) {
+ ret = -ENOMEM;
+ goto release_alt;
+ }
+
+ hwif_prop.mmio_ide_alt_mapbase = ioremap(res_alt->start, res_alt->end -
+ res_alt->start + 1);
+ if (!hwif_prop.mmio_ide_alt_mapbase) {
+ ret = -ENOMEM;
+ goto unmap_base;
+ }
+
+ hwif = mmio_ide_locate_hwif(hwif_prop.mmio_ide_mapbase,
+ hwif_prop.mmio_ide_alt_mapbase, pdata, res_irq->start);
+
+ if (!hwif) {
+ ret = -ENODEV;
+ goto unmap_alt;
+ }
+ hwif->gendev.parent = &pdev->dev;
+ hwif->noprobe = 0;
+
+ probe_hwif_init(hwif);
+
+ platform_set_drvdata(pdev, hwif);
+ create_proc_ide_interfaces();
+
+ return 0;
+
+unmap_alt:
+ iounmap(hwif_prop.mmio_ide_alt_mapbase);
+unmap_base:
+ iounmap(hwif_prop.mmio_ide_mapbase);
+release_alt:
+ release_mem_region(res_alt->start, res_alt->end - res_alt->start + 1);
+release_base:
+ release_mem_region(res_base->start,
+ res_base->end - res_base->start + 1);
+out:
+ return ret;
+}
+
+static int __devexit mmio_ide_remove(struct platform_device *pdev)
+{
+ ide_hwif_t *hwif = pdev->dev.driver_data;
+ struct resource *res_base, *res_alt;
+
+ /* get a pointer to the register memory */
+ res_base = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ res_alt = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+
+ release_mem_region(res_base->start,
+ res_base->end - res_base->start + 1);
+ release_mem_region(res_alt->start, res_alt->end - res_alt->start + 1);
+
+ platform_set_drvdata(pdev, NULL);
+
+ if (hwif != hwif_prop.hwif)
+ dev_printk(KERN_DEBUG, &pdev->dev, "%s: hwif value error",
+ pdev->name);
+ else {
+ ide_unregister (hwif_prop.index);
+ hwif_prop.index = 0;
+ hwif_prop.hwif = NULL;
+ }
+
+ iounmap(hwif_prop.mmio_ide_mapbase);
+ iounmap(hwif_prop.mmio_ide_alt_mapbase);
+
+ return 0;
+}
+
+static struct platform_driver mmio_ide_driver = {
+ .driver {
+ .name = "mmio-ide",
+ },
+ .probe = mmio_ide_probe,
+ .remove = __devexit_p(mmio_ide_remove),
+};
+
+static int __init mmio_ide_init(void)
+{
+ return platform_driver_register(&mmio_ide_driver);
+}
+
+static void __exit mmio_ide_exit(void)
+{
+ platform_driver_unregister(&mmio_ide_driver);
+}
+
+MODULE_DESCRIPTION("Memory Mapped IDE driver");
+MODULE_LICENSE("GPL");
+
+module_init(mmio_ide_init);
+module_exit(mmio_ide_exit);
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[Index of Archives]
[Kernel Newbies]
[Netfilter]
[Bugtraq]
[Photo]
[Stuff]
[Gimp]
[Yosemite News]
[MIPS Linux]
[ARM Linux]
[Linux Security]
[Linux RAID]
[Video 4 Linux]
[Linux for the blind]
[Linux Resources]