summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorRichard Zhu <r65037@freescale.com>2014-02-08 15:27:50 +0800
committerNitin Garg <nitin.garg@freescale.com>2014-06-03 23:01:57 -0500
commit78201dcb85255cef14af409618eafe2375372100 (patch)
treea73246341a9854ac5959e97e68e37e61bc4d119a /arch
parent4a0e6ad225c6f01c1fe1f2905e729d28abd2071e (diff)
ENGR00298394 pcie: enable imx pcie ep msi demo
- add one imx pcie ep simple skeleton driver to demo the msi trigger capability in imx6 pcie rc/ep validation system Test howto: - Enable CONFIG_PCI_MSI=y, when rebuild the rc/ep images - EP side(console command and kernel message): root@sabresd_6dq:/ # memtool 0x1ff8000=0 Writing 32-bit value 0x0 to address 0x01FF8000 root@sabresd_6dq:/ # - RC side(console command and kernel message): root@sabresd_6dq:/ # cat /proc/interrupts | grep MSI 496: 1 0 0 0 PCIe-MSI - EP side(console command and kernel message): root@sabresd_6dq:/ # memtool 0x1ff8000=0 Writing 32-bit value 0x0 to address 0x01FF8000 - RC side(console command and kernel message): root@sabresd_6dq:/ # cat /proc/interrupts | grep MSI 496: 2 0 0 0 PCIe-MSI Signed-off-by: Richard Zhu <r65037@freescale.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-mx6/Kconfig5
-rw-r--r--arch/arm/mach-mx6/Makefile1
-rw-r--r--arch/arm/mach-mx6/pcie_imx_ep_driver.c152
3 files changed, 158 insertions, 0 deletions
diff --git a/arch/arm/mach-mx6/Kconfig b/arch/arm/mach-mx6/Kconfig
index 64ce4d4ac71d..1a319b82ba70 100644
--- a/arch/arm/mach-mx6/Kconfig
+++ b/arch/arm/mach-mx6/Kconfig
@@ -296,6 +296,11 @@ config IMX_PCIE_RC_MODE_IN_EP_RC_SYS
bool "PCI Express RC mode in the IMX6 RC/EP interconnection system"
depends on IMX_PCIE
+config PCIE_IMX_EP
+ bool "i.MX6 PCI Express EP skeleton driver"
+ depends on IMX_PCIE_RC_MODE_IN_EP_RC_SYS
+ default y
+
config USB_EHCI_ARC_H1
tristate "USB Host 1 support"
depends on USB_EHCI_ARC
diff --git a/arch/arm/mach-mx6/Makefile b/arch/arm/mach-mx6/Makefile
index 8c1d754f02a2..9356a07bda18 100644
--- a/arch/arm/mach-mx6/Makefile
+++ b/arch/arm/mach-mx6/Makefile
@@ -22,3 +22,4 @@ obj-$(CONFIG_USB_FSL_ARC_OTG) += usb_dr.o
obj-$(CONFIG_USB_EHCI_ARC_H1) += usb_h1.o
obj-$(CONFIG_MACH_IMX_BLUETOOTH_RFKILL) += mx6_bt_rfkill.o
obj-$(CONFIG_PCI_MSI) += msi.o
+obj-$(CONFIG_PCIE_IMX_EP) += pcie_imx_ep_driver.o
diff --git a/arch/arm/mach-mx6/pcie_imx_ep_driver.c b/arch/arm/mach-mx6/pcie_imx_ep_driver.c
new file mode 100644
index 000000000000..7f703e41ae93
--- /dev/null
+++ b/arch/arm/mach-mx6/pcie_imx_ep_driver.c
@@ -0,0 +1,152 @@
+/*
+ * PCIe endpoint skeleton driver for IMX6 SOCs
+ *
+ * Copyright (C) 2014 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/pci-aspm.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+
+#define DRV_DESCRIPTION "i.MX PCIE endpoint device driver"
+#define DRV_VERSION "version 0.1"
+#define DRV_NAME "imx_pcie_ep"
+
+struct imx_pcie_ep_priv {
+ struct pci_dev *pci_dev;
+ void __iomem *hw_base;
+};
+
+/**
+ * imx_pcie_ep_probe - Device Initialization Routine
+ * @pdev: PCI device information struct
+ * @id: entry in id_tbl
+ *
+ * Returns 0 on success, negative on failure
+ **/
+static int imx_pcie_ep_probe(struct pci_dev *pdev,
+ const struct pci_device_id *id)
+{
+ int ret = 0;
+ struct device *dev = &pdev->dev;
+ struct imx_pcie_ep_priv *priv;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv) {
+ dev_err(dev, "can't alloc imx pcie priv\n");
+ return -ENOMEM;
+ }
+
+ priv->pci_dev = pdev;
+
+ if (pci_enable_device(pdev)) {
+ ret = -ENODEV;
+ goto out;
+ }
+ pci_set_master(pdev);
+
+ pci_set_drvdata(pdev, priv);
+
+ priv->hw_base = pci_iomap(pdev, 0, 0);
+ if (!priv->hw_base) {
+ ret = -ENODEV;
+ goto out;
+ }
+
+ pr_info("pci_resource_len = 0x%08llx\n",
+ (unsigned long long) pci_resource_len(pdev, 0));
+ pr_info("pci_resource_base = %p\n", priv->hw_base);
+
+ ret = pci_enable_msi(priv->pci_dev);
+ if (ret < 0) {
+ dev_err(dev, "can't enable msi\n");
+ return ret;
+ }
+
+ /* configure rc's msi cap */
+ pci_bus_read_config_dword(pdev->bus->parent, 0, 0x50, &ret);
+ ret |= (PCI_MSI_FLAGS_ENABLE << 16);
+ pci_bus_write_config_dword(pdev->bus->parent, 0, 0x50, ret);
+ pci_bus_write_config_dword(pdev->bus->parent, 0, 0x828, 0x1);
+ pci_bus_write_config_dword(pdev->bus->parent, 0, 0x82C, 0xFFFFFFFE);
+
+ return 0;
+
+out:
+ return ret;
+}
+
+static void __devexit imx_pcie_ep_remove(struct pci_dev *pdev)
+{
+ struct imx_pcie_ep_priv *priv = pci_get_drvdata(pdev);
+
+ if (!priv)
+ return;
+ pr_info("***imx pcie ep driver unload***\n");
+}
+
+static struct pci_device_id imx_pcie_ep_ids[] = {
+ {
+ .class = PCI_CLASS_MEMORY_RAM << 8,
+ .class_mask = ~0,
+ .vendor = 0xbeaf,
+ .device = 0xdead,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+ },
+ { } /* terminate list */
+};
+MODULE_DEVICE_TABLE(pci, imx_pcie_ep_ids);
+
+static struct pci_driver imx_pcie_ep_driver = {
+ .name = DRV_NAME,
+ .id_table = imx_pcie_ep_ids,
+ .probe = imx_pcie_ep_probe,
+ .remove = __devexit_p(imx_pcie_ep_remove),
+};
+
+static int __init imx_pcie_ep_init(void)
+{
+ int ret;
+ pr_info(DRV_DESCRIPTION ", " DRV_VERSION "\n");
+
+ ret = pci_register_driver(&imx_pcie_ep_driver);
+ if (ret)
+ pr_err("Unable to initialize PCI module\n");
+
+ return ret;
+}
+
+static void __exit imx_pcie_ep_exit(void)
+{
+ pci_unregister_driver(&imx_pcie_ep_driver);
+}
+
+module_exit(imx_pcie_ep_exit);
+module_init(imx_pcie_ep_init);
+
+MODULE_DESCRIPTION(DRV_DESCRIPTION);
+MODULE_VERSION(DRV_VERSION);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("imx_pcie_ep");