mcb: Add PCI carrier for MEN Chameleon Bus
authorJohannes Thumshirn <johannes.thumshirn@men.de>
Wed, 26 Feb 2014 16:29:06 +0000 (17:29 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 28 Feb 2014 23:47:12 +0000 (15:47 -0800)
Add support for MCB over PCI devices. Both PCI attached on-board Chameleon FPGAs
as well as CompactPCI based MCB carrier cards are supported with this driver.

Signed-off-by: Johannes Thumshirn <johannes.thumshirn@men.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/mcb/Kconfig
drivers/mcb/Makefile
drivers/mcb/mcb-internal.h
drivers/mcb/mcb-pci.c [new file with mode: 0644]

index 44c82d68c5632ae3ee1198a9f745e30cf3b6cc14..b8f5d469165c0421693f82db35fe1f61254fc046 100644 (file)
@@ -13,3 +13,17 @@ menuconfig MCB
           for these devices.
 
           If build as a module, the module is called mcb.ko
+
+if MCB
+config MCB_PCI
+          tristate "PCI based MCB carrier"
+          default m
+          help
+
+          This is a MCB carrier on a PCI device. Both PCI attached on-board
+          FPGAs as well as CompactPCI attached MCB FPGAs are supported with
+          this driver.
+
+          If build as a module, the module is called mcb-pci.ko
+
+endif # MCB
index 2d9a751e93bdf7c6c9588ad5a2745b57f16cef33..1ae141311defb9888e24ca404a733147ead9956e 100644 (file)
@@ -3,3 +3,5 @@ obj-$(CONFIG_MCB) += mcb.o
 
 mcb-y += mcb-core.o
 mcb-y += mcb-parse.o
+
+obj-$(CONFIG_MCB_PCI) += mcb-pci.o
index db22777d0ac8abd8d23a286db783ed3936e6df83..f956ef26c0ce2ddc1f81014b8ab5e0b658eb9977 100644 (file)
@@ -3,6 +3,8 @@
 
 #include <linux/types.h>
 
+#define PCI_VENDOR_ID_MEN              0x1a88
+#define PCI_DEVICE_ID_MEN_CHAMELEON    0x4d45
 #define CHAMELEON_FILENAME_LEN         12
 #define CHAMELEONV2_MAGIC              0xabce
 
diff --git a/drivers/mcb/mcb-pci.c b/drivers/mcb/mcb-pci.c
new file mode 100644 (file)
index 0000000..99c742c
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * MEN Chameleon Bus.
+ *
+ * Copyright (C) 2014 MEN Mikroelektronik GmbH (www.men.de)
+ * Author: Johannes Thumshirn <johannes.thumshirn@men.de>
+ *
+ * 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; version 2 of the License.
+ */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/mcb.h>
+
+#include "mcb-internal.h"
+
+struct priv {
+       struct mcb_bus *bus;
+       void __iomem *base;
+};
+
+static int mcb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+       struct priv *priv;
+       phys_addr_t mapbase;
+       int ret;
+       int num_cells;
+       unsigned long flags;
+
+       priv = devm_kzalloc(&pdev->dev, sizeof(struct priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       ret = pci_enable_device(pdev);
+       if (ret) {
+               dev_err(&pdev->dev, "Failed to enable PCI device\n");
+               return -ENODEV;
+       }
+
+       mapbase = pci_resource_start(pdev, 0);
+       if (!mapbase) {
+               dev_err(&pdev->dev, "No PCI resource\n");
+               goto err_start;
+       }
+
+       ret = pci_request_region(pdev, 0, KBUILD_MODNAME);
+       if (ret) {
+               dev_err(&pdev->dev, "Failed to request PCI BARs\n");
+               goto err_start;
+       }
+
+       priv->base = pci_iomap(pdev, 0, 0);
+       if (!priv->base) {
+               dev_err(&pdev->dev, "Cannot ioremap\n");
+               ret = -ENOMEM;
+               goto err_ioremap;
+       }
+
+       flags = pci_resource_flags(pdev, 0);
+       if (flags & IORESOURCE_IO) {
+               ret = -ENOTSUPP;
+               dev_err(&pdev->dev,
+                       "IO mapped PCI devices are not supported\n");
+               goto err_ioremap;
+       }
+
+       pci_set_drvdata(pdev, priv);
+
+       priv->bus = mcb_alloc_bus();
+
+       ret = chameleon_parse_cells(priv->bus, mapbase, priv->base);
+       if (ret < 0)
+               goto err_drvdata;
+       num_cells = ret;
+
+       dev_dbg(&pdev->dev, "Found %d cells\n", num_cells);
+
+       mcb_bus_add_devices(priv->bus);
+
+err_drvdata:
+       pci_iounmap(pdev, priv->base);
+err_ioremap:
+       pci_release_region(pdev, 0);
+err_start:
+       pci_disable_device(pdev);
+       return ret;
+}
+
+static void mcb_pci_remove(struct pci_dev *pdev)
+{
+       struct priv *priv = pci_get_drvdata(pdev);
+
+       mcb_release_bus(priv->bus);
+}
+
+static const struct pci_device_id mcb_pci_tbl[] = {
+       { PCI_DEVICE(PCI_VENDOR_ID_MEN, PCI_DEVICE_ID_MEN_CHAMELEON) },
+       { 0 },
+};
+MODULE_DEVICE_TABLE(pci, mcb_pci_tbl);
+
+static struct pci_driver mcb_pci_driver = {
+       .name = "mcb-pci",
+       .id_table = mcb_pci_tbl,
+       .probe = mcb_pci_probe,
+       .remove = mcb_pci_remove,
+};
+
+module_pci_driver(mcb_pci_driver);
+
+MODULE_AUTHOR("Johannes Thumshirn <johannes.thumshirn@men.de>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("MCB over PCI support");