All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/2] adding PCI support to AXS10x
@ 2015-11-24 11:44 Joao Pinto
  2015-11-24 11:44 ` [PATCH 1/2] add new platform driver for PCI RC Joao Pinto
  2015-11-24 11:44 ` [PATCH 2/2] PCI support added to ARC Joao Pinto
  0 siblings, 2 replies; 15+ messages in thread
From: Joao Pinto @ 2015-11-24 11:44 UTC (permalink / raw)
  To: linux-pci, linux-kernel
  Cc: bhelgaas, CARLOS.PALMINHA, Vineet.Gupta1, Alexey.Brodkin, Joao Pinto

This patch set has the goal to add suppport for DesignWare PCIe RC in ARC
AXS10x. It includes the necessary tweaks to the ARC architecture, necessary
tweaks to the PCI subsystem and a new driver (pcie-snpsdev).
This new driver will be used extensively in the PCIe RC Prototyping Kit.

The patches were produced against the 'next' branch of Bjorn Helgaas'
repository. It was properly tested in an IP Prototyping Kit.

Joao Pinto (2):
  add new platform driver for PCI RC
  PCI support added to ARC

 .../devicetree/bindings/pci/pcie-snpsdev.txt       |  28 ++
 MAINTAINERS                                        |   7 +
 arch/arc/Kconfig                                   |  22 ++
 arch/arc/include/asm/dma.h                         |   5 +
 arch/arc/include/asm/io.h                          |   2 +
 arch/arc/include/asm/mach/pci.h                    |  97 ++++++
 arch/arc/include/asm/pci.h                         |  34 ++
 arch/arc/kernel/Makefile                           |   1 +
 arch/arc/kernel/pcibios.c                          | 360 +++++++++++++++++++++
 arch/arc/mm/ioremap.c                              |  29 +-
 arch/arc/plat-axs10x/Kconfig                       |   1 +
 drivers/pci/Makefile                               |   1 +
 drivers/pci/host/Kconfig                           |   5 +
 drivers/pci/host/Makefile                          |   1 +
 drivers/pci/host/pcie-designware.c                 |   9 +
 drivers/pci/host/pcie-designware.h                 |   1 +
 drivers/pci/host/pcie-snpsdev.c                    | 342 ++++++++++++++++++++
 17 files changed, 944 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/devicetree/bindings/pci/pcie-snpsdev.txt
 create mode 100644 arch/arc/include/asm/mach/pci.h
 create mode 100644 arch/arc/include/asm/pci.h
 create mode 100644 arch/arc/kernel/pcibios.c
 create mode 100644 drivers/pci/host/pcie-snpsdev.c

-- 
1.8.1.5


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 1/2] add new platform driver for PCI RC
  2015-11-24 11:44 [PATCH 0/2] adding PCI support to AXS10x Joao Pinto
@ 2015-11-24 11:44 ` Joao Pinto
  2015-11-24 12:15   ` kbuild test robot
  2015-11-24 11:44 ` [PATCH 2/2] PCI support added to ARC Joao Pinto
  1 sibling, 1 reply; 15+ messages in thread
From: Joao Pinto @ 2015-11-24 11:44 UTC (permalink / raw)
  To: linux-pci, linux-kernel
  Cc: bhelgaas, CARLOS.PALMINHA, Vineet.Gupta1, Alexey.Brodkin, Joao Pinto

This patch adds a new driver that will be the reference platform driver for all
PCIe RC IP Protoyping Kits based on ARC SDP. This patch is composed by:

-Changes to pcie-designware driver adds a function that enables the feature
of starting the LTSSM (Link Train Status State) used by the new driver
-MAINTAINERS file was updated to include the new driver
-Documentation/devicetree/bindings/pci was updated to include the new driver
documentation

Signed-off-by: Joao Pinto <jpinto@synopsys.com>
---
 .../devicetree/bindings/pci/pcie-snpsdev.txt       |  28 ++
 MAINTAINERS                                        |   7 +
 drivers/pci/host/Kconfig                           |   5 +
 drivers/pci/host/Makefile                          |   1 +
 drivers/pci/host/pcie-designware.c                 |   9 +
 drivers/pci/host/pcie-designware.h                 |   1 +
 drivers/pci/host/pcie-snpsdev.c                    | 342 +++++++++++++++++++++
 7 files changed, 393 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/pci/pcie-snpsdev.txt
 create mode 100644 drivers/pci/host/pcie-snpsdev.c

diff --git a/Documentation/devicetree/bindings/pci/pcie-snpsdev.txt b/Documentation/devicetree/bindings/pci/pcie-snpsdev.txt
new file mode 100644
index 0000000..b833c8f
--- /dev/null
+++ b/Documentation/devicetree/bindings/pci/pcie-snpsdev.txt
@@ -0,0 +1,28 @@
+Synopsys PCI RC IP Prototyping Kit
+----------------------------------
+
+This is the reference platform driver to be used in the Synopsys PCI RC IP
+Prototyping Kits.
+
+Required properties:
+- compatible: "snps,pcie-snpsdev";
+- reg:	A list of physical regions to access the device.
+- interrupts: interrupt for the device.
+- #address-cells: must be 3.
+- #size-cells: must be 2.
+
+Example configuration:
+
+	pcie: pcie@0xdffff000 {
+		#interrupt-cells = <1>;
+		compatible = "snps,pcie-snpsdev";
+		reg = <0xdffff000 0x1000>;
+		interrupts = <25>, <24>;
+		#address-cells = <3>;
+		#size-cells = <2>;
+		device_type = "pci";
+		ranges = <0x00000800 0 0xd0000000 0xd0000000 0 0x00002000
+			  0x81000000 0 0x00000000 0xde000000 0 0x00010000
+			  0x82000000 0 0xd0400000 0xd0400000 0 0x0d000000>;
+		num-lanes = <1>;
+	};
diff --git a/MAINTAINERS b/MAINTAINERS
index e9caa4b..d2e4506 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -8230,6 +8230,13 @@ S:	Maintained
 F:	Documentation/devicetree/bindings/pci/hisilicon-pcie.txt
 F:	drivers/pci/host/pcie-hisi.c
 
+PCI DRIVER FOR SYNOPSYS PROTOTYPING DEVICE
+M:	Joao Pinto <jpinto@synopsys.com>
+L:	linux-pci@vger.kernel.org
+S:	Maintained
+F:	Documentation/devicetree/bindings/pci/pcie-snpsdev.txt
+F:	drivers/pci/host/pcie-snpsdev.c
+
 PCMCIA SUBSYSTEM
 P:	Linux PCMCIA Team
 L:	linux-pcmcia@lists.infradead.org
diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig
index f131ba9..a874b1e 100644
--- a/drivers/pci/host/Kconfig
+++ b/drivers/pci/host/Kconfig
@@ -172,4 +172,9 @@ config PCI_HISI
 	help
 	  Say Y here if you want PCIe controller support on HiSilicon HIP05 SoC
 
+config PCIE_SNPSDEV
+	bool "Platform Driver for Synopsys Device"
+	select PCIEPORTBUS
+	select PCIE_DW
+
 endmenu
diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile
index 9d4d3c6..e422f65 100644
--- a/drivers/pci/host/Makefile
+++ b/drivers/pci/host/Makefile
@@ -20,3 +20,4 @@ obj-$(CONFIG_PCIE_IPROC_BCMA) += pcie-iproc-bcma.o
 obj-$(CONFIG_PCIE_ALTERA) += pcie-altera.o
 obj-$(CONFIG_PCIE_ALTERA_MSI) += pcie-altera-msi.o
 obj-$(CONFIG_PCI_HISI) += pcie-hisi.o
+obj-$(CONFIG_PCIE_SNPSDEV) += pcie-snpsdev.o
diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c
index 540f077..d9a7aa6 100644
--- a/drivers/pci/host/pcie-designware.c
+++ b/drivers/pci/host/pcie-designware.c
@@ -706,6 +706,15 @@ static struct pci_ops dw_pcie_ops = {
 	.write = dw_pcie_wr_conf,
 };
 
+void dw_pcie_link_retrain(struct pcie_port *pp)
+{
+	u32 val = 0;
+
+	dw_pcie_readl_rc(pp, LINK_CONTROL_LINK_STATUS_REG, &val);
+	val = val | PCIE_RETRAIN_LINK_MASK;
+	dw_pcie_writel_rc(pp, val, LINK_CONTROL_LINK_STATUS_REG);
+}
+
 void dw_pcie_setup_rc(struct pcie_port *pp)
 {
 	u32 val;
diff --git a/drivers/pci/host/pcie-designware.h b/drivers/pci/host/pcie-designware.h
index 2356d29..249b631 100644
--- a/drivers/pci/host/pcie-designware.h
+++ b/drivers/pci/host/pcie-designware.h
@@ -79,5 +79,6 @@ void dw_pcie_msi_init(struct pcie_port *pp);
 int dw_pcie_link_up(struct pcie_port *pp);
 void dw_pcie_setup_rc(struct pcie_port *pp);
 int dw_pcie_host_init(struct pcie_port *pp);
+void dw_pcie_link_retrain(struct pcie_port *pp);
 
 #endif /* _PCIE_DESIGNWARE_H */
diff --git a/drivers/pci/host/pcie-snpsdev.c b/drivers/pci/host/pcie-snpsdev.c
new file mode 100644
index 0000000..5721da9
--- /dev/null
+++ b/drivers/pci/host/pcie-snpsdev.c
@@ -0,0 +1,342 @@
+/*
+ * PCIe RC driver for Synopsys Designware Core
+ *
+ * Copyright (C) 2015-2016 Synopsys, Inc. (www.synopsys.com)
+ *
+ * Authors: Manjunath Bettegowda <manjumb@synopsys.com>,
+ *	    Jie Deng <jiedeng@synopsys.com>
+ *	    Joao Pinto <jpinto@synopsys.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_gpio.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+#include <linux/resource.h>
+#include <linux/signal.h>
+#include <linux/types.h>
+
+#include "pcie-designware.h"
+
+#define to_snpsdev_pcie(x)	container_of(x, struct snpsdev_pcie, pp)
+
+struct snpsdev_pcie {
+	void __iomem		*mem_base; /* Memory Base to access Core's [RC]
+					    * Config Space Layout
+					    */
+	struct pcie_port	pp;        /* RC Root Port specific structure -
+					    * DWC_PCIE_RC stuff
+					    */
+};
+
+#define SIZE_1GB 0x40000000
+#define PCI_EQUAL_CONTROL_PHY 0x00000707
+
+/* PCIe Port Logic registers (memory-mapped) */
+#define PLR_OFFSET 0x700
+#define PCIE_PHY_DEBUG_R0 (PLR_OFFSET + 0x28) /* 0x728 */
+#define PCIE_PHY_DEBUG_R1 (PLR_OFFSET + 0x2c) /* 0x72c */
+
+/* PCIE PHY CONTROL REGISTER: Useful for cfg_phy_control GPIO outputs */
+#define PCIE_PHY_CTRL (PLR_OFFSET + 0x114)    /* 0x814 */
+/* PCIE PHY STATUS REGISTER: Useful for phy_cfg_status GPIO inputs */
+#define PCIE_PHY_STAT (PLR_OFFSET + 0x110)    /* 0x810 */
+
+static void snpsdev_pcie_fixup_bridge(struct pci_dev *dev)
+{
+	u32 slot_cap;
+
+	u16 caps_reg = pcie_caps_reg(dev) | PCI_EXP_FLAGS_SLOT;
+
+	pcie_capability_write_word(dev, PCI_EXP_FLAGS, caps_reg);
+	dev->pcie_flags_reg = caps_reg;
+
+	pcie_capability_read_dword(dev, PCI_EXP_SLTCAP, &slot_cap);
+
+	slot_cap = slot_cap & (~PCI_EXP_SLTCAP_SPLV);
+	slot_cap = slot_cap | (0x30 << 7);
+
+	pcie_capability_write_dword(dev, PCI_EXP_SLTCAP, slot_cap);
+
+	if (pcibios_enable_device(dev, ~0) < 0)
+		pr_err("PCI: synopsys device enable failed\n");
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, snpsdev_pcie_fixup_bridge);
+
+static void snpsdev_pcie_fixup_res(struct pci_dev *dev)
+{
+	struct resource *res;
+	resource_size_t size;
+	int bar;
+
+	for (bar = 0; bar < 6; bar++) {
+		res = dev->resource + bar;
+		size = resource_size(res);
+
+		if (size == SIZE_1GB) {
+			res->start = 0;
+			res->end   = 0;
+			res->flags = 0;
+		}
+	}
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, snpsdev_pcie_fixup_res);
+
+/* This handler was created for future work */
+static irqreturn_t snpsdev_pcie_irq_handler(int irq, void *arg)
+{
+	return IRQ_NONE;
+}
+
+static irqreturn_t snpsdev_pcie_msi_irq_handler(int irq, void *arg)
+{
+	struct pcie_port *pp = arg;
+
+	dw_handle_msi_irq(pp);
+
+	return IRQ_HANDLED;
+}
+
+static void snpsdev_pcie_init_phy(struct pcie_port *pp)
+{
+	/* write Lane 0 Equalization Control fields register */
+	writel(PCI_EQUAL_CONTROL_PHY, pp->dbi_base + 0x154);
+}
+
+static int snpsdev_pcie_deassert_core_reset(struct pcie_port *pp)
+{
+	return 0;
+}
+
+/*
+ * snpsdev_pcie_host_init()
+ * Platform specific host/RC initialization
+ *	a. Assert the core reset
+ *	b. Assert and deassert phy reset and initialize the phy
+ *	c. De-Assert the core reset
+ *	d. Initializet the Root Port (BARs/Memory Or IO/ Interrupt/ Commnad Reg)
+ *	e. Initiate Link startup procedure
+ *
+ */
+static void snpsdev_pcie_host_init(struct pcie_port *pp)
+{
+	int count = 0;
+
+	/* Initialize Phy (Reset/poweron/control-inputs ) */
+	snpsdev_pcie_init_phy(pp);
+
+	/* de-assert core reset */
+	snpsdev_pcie_deassert_core_reset(pp);
+
+	/* We expect the PCIE Link to be up by this time */
+	dw_pcie_setup_rc(pp);
+
+	/* Start LTSSM here */
+	dw_pcie_link_retrain(pp);
+
+	/* Check for Link up indication */
+	while (!dw_pcie_link_up(pp)) {
+		usleep_range(1000, 1100);
+		count++;
+		if (count == 20) {
+			dev_err(pp->dev, "phy link never came up\n");
+			dev_dbg(pp->dev,
+				"PL_DEBUG0: 0x%08x, DEBUG_R1: 0x%08x\n",
+				readl(pp->dbi_base + PCIE_PHY_DEBUG_R0),
+				readl(pp->dbi_base + PCIE_PHY_DEBUG_R1));
+			break;
+		}
+	}
+
+	if (IS_ENABLED(CONFIG_PCI_MSI))
+		dw_pcie_msi_init(pp);
+}
+/**
+ *
+ * Let all outof band signalling be handled by cfg_phy_control[31:0]
+ * which is selected through optional config attribute PHY_CONTROL_REG
+ *
+ * Monitor cxpl_debug_info as required to take necessary action
+ * This is available in the register PCIE_PHY_DEBUG_R0 & PCIE_PHY_DEBUG_R1
+ *
+ */
+static int snpsdev_pcie_link_up(struct pcie_port *pp)
+{
+	u32 status;
+
+	/* Bit number 36: reports LTSSM PHY Link UP; Available in bit 3 of
+	 * PCIE_PHY_DEBUG_R1
+	 */
+	status = readl(pp->dbi_base + PCIE_PHY_DEBUG_R1) & (0x1 << 4);
+	if (status != 0)
+		return 1;
+
+	/* TODO:Now Link is in L0;Initiate GEN2/GEN3 migration if RC Supports*/
+	return 0;
+}
+
+
+/**
+ * This is RC operation structure
+ * snpsdev_pcie_link_up: the function which initiates the phy link up procedure
+ * snpsdev_pcie_host_init: the function whihc does the host/RC Root port
+ * initialization.
+ */
+static struct pcie_host_ops snpsdev_pcie_host_ops = {
+	.link_up = snpsdev_pcie_link_up,
+	.host_init = snpsdev_pcie_host_init,
+};
+
+/**
+ * snpsdev_add_pcie_port
+ * This function
+ * a. installs the interrupt handler
+ * b. registers host operations int he pcie_port structure
+ */
+static int snpsdev_add_pcie_port(struct pcie_port *pp,
+				 struct platform_device *pdev)
+{
+	int ret;
+
+	pp->irq = platform_get_irq(pdev, 1);
+
+	if (pp->irq < 0) {
+		if (pp->irq != -EPROBE_DEFER)
+			dev_err(&pdev->dev, "cannot get irq\n");
+		return pp->irq;
+	}
+
+	ret = devm_request_irq(&pdev->dev, pp->irq, snpsdev_pcie_irq_handler,
+				IRQF_SHARED, "snpsdev-pcie", pp);
+
+	if (ret) {
+		dev_err(&pdev->dev, "failed to request irq\n");
+		return ret;
+	}
+
+	if (IS_ENABLED(CONFIG_PCI_MSI)) {
+		pp->msi_irq = platform_get_irq(pdev, 0);
+
+		if (pp->msi_irq < 0) {
+			if (pp->msi_irq != -EPROBE_DEFER)
+				dev_err(&pdev->dev, "cannot get msi irq\n");
+			return pp->msi_irq;
+		}
+
+		ret = devm_request_irq(&pdev->dev, pp->msi_irq,
+					snpsdev_pcie_msi_irq_handler,
+					IRQF_SHARED, "snpsdev-pcie-msi", pp);
+		if (ret) {
+			dev_err(&pdev->dev, "failed to request msi irq\n");
+			return ret;
+		}
+	}
+
+	pp->root_bus_nr = -1;
+	pp->ops = &snpsdev_pcie_host_ops;
+
+	/* Below function:
+	 * Checks for range property from DT
+	 * Gets the IO and MEMORY and CONFIG-Space ranges from DT
+	 * Does IOREMAPS on the physical addresses
+	 * Gets the num-lanes from DT
+	 * Gets MSI capability from DT
+	 * Calls the platform specific host initialization
+	 * Program the correct class, BAR0, Link width, in Config space
+	 * Then it calls pci common init routine
+	 * Then it calls function to assign "unassigned resources"
+	 */
+	ret = dw_pcie_host_init(pp);
+	if (ret) {
+		dev_err(&pdev->dev, "failed to initialize host\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+/**
+ * snpsdev_pcie_rc_probe()
+ * This function gets called as part of pcie registration. if the id matches
+ * the platform driver framework will call this function.
+ *
+ * @pdev: Pointer to the platform_device structure
+ *
+ * Returns zero on success; Negative errorno on failure
+ */
+static int __init snpsdev_pcie_rc_probe(struct platform_device *pdev)
+{
+	struct snpsdev_pcie *snpsdev_pcie;
+	struct pcie_port *pp;
+	struct resource *dwc_pcie_rc_res;  /* Resource from DT */
+	int ret;
+
+	snpsdev_pcie = devm_kzalloc(&pdev->dev, sizeof(*snpsdev_pcie),
+					GFP_KERNEL);
+	if (!snpsdev_pcie)
+		return -ENOMEM;
+
+	pp = &snpsdev_pcie->pp;
+	pp->dev = &pdev->dev;
+
+	dwc_pcie_rc_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	if (!dwc_pcie_rc_res)
+		return -ENODEV;
+
+	snpsdev_pcie->mem_base = devm_ioremap_resource(&pdev->dev,
+							dwc_pcie_rc_res);
+	if (IS_ERR(snpsdev_pcie->mem_base)) {
+		ret = PTR_ERR(snpsdev_pcie->mem_base);
+		return ret;
+	}
+	pp->dbi_base = snpsdev_pcie->mem_base;
+
+	ret = snpsdev_add_pcie_port(pp, pdev);
+	if (ret < 0)
+		return ret;
+
+	platform_set_drvdata(pdev, snpsdev_pcie);
+
+	return 0;
+}
+
+static int __exit snpsdev_pcie_rc_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+static const struct of_device_id snpsdev_pcie_rc_of_match[] = {
+	{ .compatible = "snps,pcie-snpsdev", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, snpsdev_pcie_rc_of_match);
+
+static struct platform_driver snpsdev_pcie_rc_driver = {
+	.remove		= __exit_p(snpsdev_pcie_rc_remove),
+	.driver = {
+		.name	= "pcie-snpsdev",
+		.owner	= THIS_MODULE,
+		.of_match_table = snpsdev_pcie_rc_of_match,
+	},
+};
+
+static int __init snpsdev_pcie_init(void)
+{
+	return platform_driver_probe(&snpsdev_pcie_rc_driver,
+					snpsdev_pcie_rc_probe);
+}
+subsys_initcall(snpsdev_pcie_init);
+
+MODULE_AUTHOR("Manjunath Bettegowda <manjumb@synopsys.com>");
+MODULE_DESCRIPTION("Platform Driver for Synopsys Device");
+MODULE_LICENSE("GPL v2");
-- 
1.8.1.5


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH 2/2] PCI support added to ARC
  2015-11-24 11:44 [PATCH 0/2] adding PCI support to AXS10x Joao Pinto
  2015-11-24 11:44 ` [PATCH 1/2] add new platform driver for PCI RC Joao Pinto
@ 2015-11-24 11:44 ` Joao Pinto
  1 sibling, 0 replies; 15+ messages in thread
From: Joao Pinto @ 2015-11-24 11:44 UTC (permalink / raw)
  To: linux-pci, linux-kernel
  Cc: bhelgaas, CARLOS.PALMINHA, Vineet.Gupta1, Alexey.Brodkin, Joao Pinto

This patch adds PCI support to ARC and updates drivers/pci Makefile enabling
the ARC arch to use the generic PCI setup functions.

Signed-off-by: Joao Pinto <jpinto@synopsys.com>
---
 arch/arc/Kconfig                |  22 +++
 arch/arc/include/asm/dma.h      |   5 +
 arch/arc/include/asm/io.h       |   2 +
 arch/arc/include/asm/mach/pci.h |  97 +++++++++++
 arch/arc/include/asm/pci.h      |  34 ++++
 arch/arc/kernel/Makefile        |   1 +
 arch/arc/kernel/pcibios.c       | 360 ++++++++++++++++++++++++++++++++++++++++
 arch/arc/mm/ioremap.c           |  29 +++-
 arch/arc/plat-axs10x/Kconfig    |   1 +
 drivers/pci/Makefile            |   1 +
 10 files changed, 551 insertions(+), 1 deletion(-)
 create mode 100644 arch/arc/include/asm/mach/pci.h
 create mode 100644 arch/arc/include/asm/pci.h
 create mode 100644 arch/arc/kernel/pcibios.c

diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
index 2c2ac3f..5b526a3 100644
--- a/arch/arc/Kconfig
+++ b/arch/arc/Kconfig
@@ -19,6 +19,7 @@ config ARC
 	select GENERIC_FIND_FIRST_BIT
 	# for now, we don't need GENERIC_IRQ_PROBE, CONFIG_GENERIC_IRQ_CHIP
 	select GENERIC_IRQ_SHOW
+	select GENERIC_PCI_IOMAP
 	select GENERIC_PENDING_IRQ if SMP
 	select GENERIC_SMP_IDLE_THREAD
 	select HAVE_ARCH_KGDB
@@ -39,6 +40,9 @@ config ARC
 	select PERF_USE_VMALLOC
 	select HAVE_DEBUG_STACKOVERFLOW
 
+config MIGHT_HAVE_PCI
+	bool
+
 config TRACE_IRQFLAGS_SUPPORT
 	def_bool y
 
@@ -110,6 +114,24 @@ config ISA_ARCV2
 
 endchoice
 
+menu "Bus Support"
+
+config PCI
+	bool "PCI support" if MIGHT_HAVE_PCI
+	help
+	  PCI is the name of a bus system, i.e. the way the CPU talks to the other stuff inside
+	  your box.Find out if your board/platform have PCI.
+	  Note: PCIE support for Synopsys Device will be available only when
+	  HAPS DX is configured with PCIE RC bitmap. If you have PCI, say Y, otherwise N.
+
+config PCI_SYSCALL
+	def_bool PCI
+
+source "drivers/pci/Kconfig"
+source "drivers/pci/pcie/Kconfig"
+
+endmenu
+
 menu "ARC CPU Configuration"
 
 choice
diff --git a/arch/arc/include/asm/dma.h b/arch/arc/include/asm/dma.h
index ca7c451..37942fa 100644
--- a/arch/arc/include/asm/dma.h
+++ b/arch/arc/include/asm/dma.h
@@ -10,5 +10,10 @@
 #define ASM_ARC_DMA_H
 
 #define MAX_DMA_ADDRESS 0xC0000000
+#ifdef CONFIG_PCI
+extern int isa_dma_bridge_buggy;
+#else
+#define isa_dma_bridge_buggy    (0)
+#endif
 
 #endif
diff --git a/arch/arc/include/asm/io.h b/arch/arc/include/asm/io.h
index 694ece8..d86c2e3 100644
--- a/arch/arc/include/asm/io.h
+++ b/arch/arc/include/asm/io.h
@@ -17,6 +17,8 @@ extern void __iomem *ioremap(unsigned long physaddr, unsigned long size);
 extern void __iomem *ioremap_prot(phys_addr_t offset, unsigned long size,
 				  unsigned long flags);
 extern void iounmap(const void __iomem *addr);
+extern void __iomem *ioport_map(unsigned long port, unsigned int size);
+extern int pci_ioremap_io(unsigned int offset, phys_addr_t phys_addr);
 
 #define ioremap_nocache(phy, sz)	ioremap(phy, sz)
 #define ioremap_wc(phy, sz)		ioremap(phy, sz)
diff --git a/arch/arc/include/asm/mach/pci.h b/arch/arc/include/asm/mach/pci.h
new file mode 100644
index 0000000..9e75277
--- /dev/null
+++ b/arch/arc/include/asm/mach/pci.h
@@ -0,0 +1,97 @@
+/*
+ *  arch/arc/include/asm/mach/pci.h
+ *
+ *  Copyright (C) 2004-2014 Synopsys, Inc. (www.synopsys.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_MACH_PCI_H
+#define __ASM_MACH_PCI_H
+
+#include <linux/ioport.h>
+
+struct pci_sys_data;
+struct pci_ops;
+struct pci_bus;
+struct device;
+
+struct hw_pci {
+#ifdef CONFIG_PCI_DOMAINS
+	int		domain;
+#endif
+	struct pci_ops	*ops;
+	int		nr_controllers;
+	void		**private_data;
+	int		(*setup)(int nr, struct pci_sys_data *);
+	struct pci_bus *(*scan)(int nr, struct pci_sys_data *);
+	void		(*preinit)(void);
+	void		(*postinit)(void);
+	u8		(*swizzle)(struct pci_dev *dev, u8 *pin);
+	int		(*map_irq)(const struct pci_dev *dev, u8 slot, u8 pin);
+	resource_size_t (*align_resource)(struct pci_dev *dev,
+					  const struct resource *res,
+					  resource_size_t start,
+					  resource_size_t size,
+					  resource_size_t align);
+	void		(*add_bus)(struct pci_bus *bus);
+	void		(*remove_bus)(struct pci_bus *bus);
+};
+
+/*
+ * Per-controller structure
+ */
+struct pci_sys_data {
+#ifdef CONFIG_PCI_DOMAINS
+	int		domain;
+#endif
+	struct list_head node;
+	int		busnr;		/* primary bus number		    */
+	u64		mem_offset;	/* bus->cpu memory mapping offset   */
+	unsigned long	io_offset;	/* bus->cpu IO mapping offset	    */
+	struct pci_bus	*bus;		/* PCI bus			    */
+	struct list_head resources;	/* root bus resources (apertures)   */
+	struct resource io_res;
+	char		io_res_name[12];
+					/* Bridge swizzling		    */
+	u8		(*swizzle)(struct pci_dev *, u8 *);
+					/* IRQ mapping			    */
+	int		(*map_irq)(const struct pci_dev *, u8, u8);
+					/* Resource alignement requirements */
+	resource_size_t (*align_resource)(struct pci_dev *dev,
+					  const struct resource *res,
+					  resource_size_t start,
+					  resource_size_t size,
+					  resource_size_t align);
+	void		(*add_bus)(struct pci_bus *bus);
+	void		(*remove_bus)(struct pci_bus *bus);
+	void		*private_data;	/* platform controller private data */
+};
+
+/*
+ * Call this with your hw_pci struct to initialise the PCI system.
+ */
+void pci_common_init_dev(struct device *, struct hw_pci *);
+
+/*
+ * Compatibility wrapper for older platforms that do not care about
+ * passing the parent device.
+ */
+static inline void pci_common_init(struct hw_pci *hw)
+{
+	pci_common_init_dev(NULL, hw);
+}
+
+/*
+ * Setup early fixed I/O mapping.
+ */
+#if defined(CONFIG_PCI)
+extern void pci_map_io_early(unsigned long pfn);
+#else
+static inline void pci_map_io_early(unsigned long pfn) {}
+#endif
+
+#endif /* __ASM_MACH_PCI_H */
+
diff --git a/arch/arc/include/asm/pci.h b/arch/arc/include/asm/pci.h
new file mode 100644
index 0000000..085b15f
--- /dev/null
+++ b/arch/arc/include/asm/pci.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2015-2016 Synopsys, Inc. (www.synopsys.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _ASM_ARC_PCI_H
+#define _ASM_ARC_PCI_H
+
+#ifdef __KERNEL__
+#include <asm-generic/pci-dma-compat.h>
+#include <asm-generic/pci-bridge.h>
+
+#include <asm/mach/pci.h> /* for pci_sys_data */
+
+extern unsigned long pcibios_min_io;
+#define PCIBIOS_MIN_IO pcibios_min_io
+extern unsigned long pcibios_min_mem;
+#define PCIBIOS_MIN_MEM pcibios_min_mem
+
+#define pcibios_assign_all_busses()	1
+/*
+ * The PCI address space does equal the physical memory address space.
+ * The networking and block device layers use this boolean for bounce
+ * buffer decisions.
+ */
+#define PCI_DMA_BUS_IS_PHYS     (1)
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_ARC_PCI_H */
+
diff --git a/arch/arc/kernel/Makefile b/arch/arc/kernel/Makefile
index e7f3625..1bc2036 100644
--- a/arch/arc/kernel/Makefile
+++ b/arch/arc/kernel/Makefile
@@ -12,6 +12,7 @@ obj-y	:= arcksyms.o setup.o irq.o time.o reset.o ptrace.o process.o devtree.o
 obj-y	+= signal.o traps.o sys.o troubleshoot.o stacktrace.o disasm.o clk.o
 obj-$(CONFIG_ISA_ARCOMPACT)		+= entry-compact.o intc-compact.o
 obj-$(CONFIG_ISA_ARCV2)			+= entry-arcv2.o intc-arcv2.o
+obj-$(CONFIG_PCI)  			+= pcibios.o
 
 obj-$(CONFIG_MODULES)			+= arcksyms.o module.o
 obj-$(CONFIG_SMP) 			+= smp.o
diff --git a/arch/arc/kernel/pcibios.c b/arch/arc/kernel/pcibios.c
new file mode 100644
index 0000000..a7bd76a
--- /dev/null
+++ b/arch/arc/kernel/pcibios.c
@@ -0,0 +1,360 @@
+/*
+ * Copyright (C) 2014-2015 Synopsys, Inc. (www.synopsys.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/bootmem.h>
+#include <linux/sizes.h>
+#include <linux/slab.h>
+
+#include <asm/pci.h>
+#include <asm/mach/pci.h>
+
+static int pcibios_init_resources(int busnr, struct pci_sys_data *sys)
+{
+	int ret;
+	struct pci_host_bridge_window *window;
+
+	if (list_empty(&sys->resources)) {
+		pci_add_resource_offset(&sys->resources,
+			 &iomem_resource, sys->mem_offset);
+	}
+
+	list_for_each_entry(window, &sys->resources, list) {
+		if (resource_type(window->res) == IORESOURCE_IO)
+			return 0;
+	}
+
+	sys->io_res.start = (busnr * SZ_64K) ?  : pcibios_min_io;
+	sys->io_res.end = (busnr + 1) * SZ_64K - 1;
+	sys->io_res.flags = IORESOURCE_IO;
+	sys->io_res.name = sys->io_res_name;
+	sprintf(sys->io_res_name, "PCI%d I/O", busnr);
+
+	ret = request_resource(&ioport_resource, &sys->io_res);
+	if (ret) {
+		pr_err("PCI: unable to allocate I/O port region (%d)\n", ret);
+		return ret;
+	}
+	pci_add_resource_offset(&sys->resources, &sys->io_res,
+				sys->io_offset);
+
+	return 0;
+}
+
+
+static void pcibios_init_hw(struct device *parent, struct hw_pci *hw,
+			    struct list_head *head)
+{
+	struct pci_sys_data *sys = NULL;
+	int ret;
+	int nr, busnr;
+
+	for (nr = busnr = 0; nr < hw->nr_controllers; nr++) {
+		sys = kzalloc(sizeof(struct pci_sys_data), GFP_KERNEL);
+		if (!sys)
+			panic("PCI: unable to allocate sys data!");
+
+#ifdef CONFIG_PCI_DOMAINS
+		sys->domain  = hw->domain;
+#endif
+		sys->busnr   = busnr;
+		sys->swizzle = hw->swizzle;
+		sys->map_irq = hw->map_irq;
+		sys->align_resource = hw->align_resource;
+		sys->add_bus = hw->add_bus;
+		sys->remove_bus = hw->remove_bus;
+		INIT_LIST_HEAD(&sys->resources);
+
+
+		if (hw->private_data)
+			sys->private_data = hw->private_data[nr];
+
+		ret = hw->setup(nr, sys);
+
+		if (ret > 0) {
+			ret = pcibios_init_resources(nr, sys);
+			if (ret)  {
+				kfree(sys);
+				break;
+			}
+
+			if (hw->scan)
+				sys->bus = hw->scan(nr, sys);
+			else
+				sys->bus = pci_scan_root_bus(parent, sys->busnr,
+						hw->ops, sys, &sys->resources);
+
+			if (!sys->bus)
+				panic("PCI: unable to scan bus!");
+
+			busnr = sys->bus->busn_res.end + 1;
+
+			list_add(&sys->node, head);
+		} else {
+			kfree(sys);
+			if (ret < 0)
+				break;
+		}
+	}
+}
+int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
+{
+	return 0;
+}
+
+void pcibios_add_bus(struct pci_bus *bus)
+{
+	struct pci_sys_data *sys = bus->sysdata;
+
+	if (sys->add_bus)
+		sys->add_bus(bus);
+}
+
+void pcibios_remove_bus(struct pci_bus *bus)
+{
+	struct pci_sys_data *sys = bus->sysdata;
+
+	if (sys->remove_bus)
+		sys->remove_bus(bus);
+}
+
+/*
+ * Swizzle the device pin each time we cross a bridge.  If a platform does
+ * not provide a swizzle function, we perform the standard PCI swizzling.
+ *
+ * The default swizzling walks up the bus tree one level at a time, applying
+ * the standard swizzle function at each step, stopping when it finds the PCI
+ * root bus.  This will return the slot number of the bridge device on the
+ * root bus and the interrupt pin on that device which should correspond
+ * with the downstream device interrupt.
+ *
+ * Platforms may override this, in which case the slot and pin returned
+ * depend entirely on the platform code.  However, please note that the
+ * PCI standard swizzle is implemented on plug-in cards and Cardbus based
+ * PCI extenders, so it can not be ignored.
+ */
+static u8 pcibios_swizzle(struct pci_dev *dev, u8 *pin)
+{
+	struct pci_sys_data *sys = dev->sysdata;
+	int slot, oldpin = *pin;
+
+	if (sys->swizzle)
+		slot = sys->swizzle(dev, pin);
+	else
+		slot = pci_common_swizzle(dev, pin);
+
+	return slot;
+}
+
+/*
+ * Map a slot/pin to an IRQ.
+ */
+static int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+	struct pci_sys_data *sys = dev->sysdata;
+	int irq = -1;
+
+	if (sys->map_irq)
+		irq = sys->map_irq(dev, slot, pin);
+
+	return irq;
+}
+
+void pci_common_init_dev(struct device *parent, struct hw_pci *hw)
+{
+	struct pci_sys_data *sys;
+	LIST_HEAD(head);
+
+	pci_add_flags(PCI_REASSIGN_ALL_RSRC);
+	if (hw->preinit)
+		hw->preinit();
+	pcibios_init_hw(parent, hw, &head);
+	if (hw->postinit)
+		hw->postinit();
+
+	pci_fixup_irqs(pcibios_swizzle, pcibios_map_irq);
+
+	list_for_each_entry(sys, &head, node) {
+		struct pci_bus *bus = sys->bus;
+
+		if (!pci_has_flag(PCI_PROBE_ONLY)) {
+			/*
+			 * Size the bridge windows.
+			 */
+			pci_bus_size_bridges(bus);
+
+			/*
+			 * Assign resources.
+			 */
+			pci_bus_assign_resources(bus);
+		}
+
+		/*
+		 * Tell drivers about devices found.
+		 */
+		pci_bus_add_devices(bus);
+	}
+}
+
+/*
+ * We don't have to worry about legacy ISA devices, so nothing to do here
+ */
+resource_size_t pcibios_align_resource(void *data, const struct resource *res,
+				resource_size_t size, resource_size_t align)
+{
+	return res->start;
+}
+
+/**
+ * pcibios_enable_device - Enable I/O and memory.
+ * @dev: PCI device to be enabled
+ */
+int pcibios_enable_device(struct pci_dev *dev, int mask)
+{
+	u16 cmd, old_cmd;
+	int idx;
+	struct resource *r;
+
+	pci_read_config_word(dev, PCI_COMMAND, &cmd);
+	old_cmd = cmd;
+	for (idx = 0; idx < 6; idx++) {
+		/* Only set up the requested stuff */
+		if (!(mask & (1 << idx)))
+			continue;
+
+		r = dev->resource + idx;
+		if (!r->start && r->end) {
+			pr_err("PCI: Device %s not available because"/
+			       " of resource collisions\n", pci_name(dev));
+			return -EINVAL;
+		}
+		if (r->flags & IORESOURCE_IO)
+			cmd |= PCI_COMMAND_IO;
+		if (r->flags & IORESOURCE_MEM)
+			cmd |= PCI_COMMAND_MEMORY;
+	}
+
+	/*
+	 * Bridges (eg, cardbus bridges) need to be fully enabled
+	 */
+	if ((dev->class >> 16) == PCI_BASE_CLASS_BRIDGE)
+		cmd |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
+
+	if (cmd != old_cmd) {
+		pr_info("PCI: enabling device %s (%04x -> %04x)\n",
+		       pci_name(dev), old_cmd, cmd);
+		pci_write_config_word(dev, PCI_COMMAND, cmd);
+	}
+	return 0;
+}
+
+/*
+ * If the bus contains any of these devices, then we must not turn on
+ * parity checking of any kind.  Currently this is CyberPro 20x0 only.
+ */
+static inline int pdev_bad_for_parity(struct pci_dev *dev)
+{
+	return ((dev->vendor == PCI_VENDOR_ID_INTERG &&
+		 (dev->device == PCI_DEVICE_ID_INTERG_2000 ||
+		  dev->device == PCI_DEVICE_ID_INTERG_2010)) ||
+		(dev->vendor == PCI_VENDOR_ID_ITE &&
+		 dev->device == PCI_DEVICE_ID_ITE_8152));
+
+}
+
+/*
+ * pcibios_fixup_bus - Called after each bus is probed,
+ * but before its children are examined.
+ */
+void pcibios_fixup_bus(struct pci_bus *bus)
+{
+	struct pci_dev *dev;
+	u16 features = PCI_COMMAND_SERR | PCI_COMMAND_PARITY
+			| PCI_COMMAND_FAST_BACK;
+
+	/*
+	 * Walk the devices on this bus, working out what we can
+	 * and can't support.
+	 */
+	list_for_each_entry(dev, &bus->devices, bus_list) {
+		u16 status;
+
+		pci_read_config_word(dev, PCI_STATUS, &status);
+
+		/*
+		 * If any device on this bus does not support fast back
+		 * to back transfers, then the bus as a whole is not able
+		 * to support them.  Having fast back to back transfers
+		 * on saves us one PCI cycle per transaction.
+		 */
+		if (!(status & PCI_STATUS_FAST_BACK))
+			features &= ~PCI_COMMAND_FAST_BACK;
+
+		if (pdev_bad_for_parity(dev))
+			features &= ~(PCI_COMMAND_SERR | PCI_COMMAND_PARITY);
+
+		switch (dev->class >> 8) {
+		case PCI_CLASS_BRIDGE_PCI:
+			pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &status);
+			status |= PCI_BRIDGE_CTL_PARITY
+					|PCI_BRIDGE_CTL_MASTER_ABORT;
+			status &= ~(PCI_BRIDGE_CTL_BUS_RESET
+					|PCI_BRIDGE_CTL_FAST_BACK);
+			pci_write_config_word(dev, PCI_BRIDGE_CONTROL, status);
+			break;
+
+		case PCI_CLASS_BRIDGE_CARDBUS:
+			pci_read_config_word(dev, PCI_CB_BRIDGE_CONTROL,
+						&status);
+			status |= PCI_CB_BRIDGE_CTL_PARITY
+					|PCI_CB_BRIDGE_CTL_MASTER_ABORT;
+			pci_write_config_word(dev, PCI_CB_BRIDGE_CONTROL,
+						status);
+			break;
+		}
+	}
+
+	/*
+	 * Now walk the devices again, this time setting them up.
+	 */
+	list_for_each_entry(dev, &bus->devices, bus_list) {
+		u16 cmd;
+
+		pci_read_config_word(dev, PCI_COMMAND, &cmd);
+		cmd |= features;
+		pci_write_config_word(dev, PCI_COMMAND, cmd);
+
+		pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE,
+				      L1_CACHE_BYTES >> 2);
+	}
+
+	/*
+	 * Propagate the flags to the PCI bridge.
+	 */
+	if (bus->self && bus->self->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
+		if (features & PCI_COMMAND_FAST_BACK)
+			bus->bridge_ctl |= PCI_BRIDGE_CTL_FAST_BACK;
+		if (features & PCI_COMMAND_PARITY)
+			bus->bridge_ctl |= PCI_BRIDGE_CTL_PARITY;
+	}
+
+	/*
+	 * Report what we did for this bus
+	 */
+	pr_info("PCI: bus%d: Fast back to back transfers %sabled\n",
+		bus->number, (features & PCI_COMMAND_FAST_BACK) ? "en" : "dis");
+}
+EXPORT_SYMBOL(pcibios_fixup_bus);
+
diff --git a/arch/arc/mm/ioremap.c b/arch/arc/mm/ioremap.c
index 739e65f..583c9fe 100644
--- a/arch/arc/mm/ioremap.c
+++ b/arch/arc/mm/ioremap.c
@@ -13,6 +13,26 @@
 #include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/cache.h>
+#include <linux/sizes.h>
+
+#ifdef CONFIG_PCI
+unsigned long pcibios_min_io = 0x100;
+EXPORT_SYMBOL(pcibios_min_io);
+
+unsigned long pcibios_min_mem = 0x100000;
+EXPORT_SYMBOL(pcibios_min_mem);
+#endif
+
+inline void __iomem *ioport_map(unsigned long port, unsigned int nr)
+{
+	return port;
+}
+EXPORT_SYMBOL(ioport_map);
+
+inline void ioport_unmap(void __iomem *addr)
+{
+}
+EXPORT_SYMBOL(ioport_unmap);
 
 void __iomem *ioremap(unsigned long paddr, unsigned long size)
 {
@@ -80,7 +100,6 @@ void __iomem *ioremap_prot(phys_addr_t paddr, unsigned long size,
 }
 EXPORT_SYMBOL(ioremap_prot);
 
-
 void iounmap(const void __iomem *addr)
 {
 	if (addr >= (void __force __iomem *)ARC_UNCACHED_ADDR_SPACE)
@@ -89,3 +108,11 @@ void iounmap(const void __iomem *addr)
 	vfree((void *)(PAGE_MASK & (unsigned long __force)addr));
 }
 EXPORT_SYMBOL(iounmap);
+
+#ifdef CONFIG_PCI
+int pci_ioremap_io(unsigned int offset, phys_addr_t phys_addr)
+{
+	return ioremap_nocache(phys_addr + offset,  SZ_64K);
+}
+EXPORT_SYMBOL_GPL(pci_ioremap_io);
+#endif
diff --git a/arch/arc/plat-axs10x/Kconfig b/arch/arc/plat-axs10x/Kconfig
index d475f9d..33b5db6 100644
--- a/arch/arc/plat-axs10x/Kconfig
+++ b/arch/arc/plat-axs10x/Kconfig
@@ -8,6 +8,7 @@
 
 menuconfig ARC_PLAT_AXS10X
 	bool "Synopsys ARC AXS10x Software Development Platforms"
+	select MIGHT_HAVE_PCI
 	select DW_APB_ICTL
 	select GPIO_DWAPB
 	select OF_GPIO
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index be3f631..2154092 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -32,6 +32,7 @@ obj-$(CONFIG_PCI_IOV) += iov.o
 # Some architectures use the generic PCI setup functions
 #
 obj-$(CONFIG_ALPHA) += setup-irq.o
+obj-$(CONFIG_ARC) += setup-irq.o
 obj-$(CONFIG_ARM) += setup-irq.o
 obj-$(CONFIG_ARM64) += setup-irq.o
 obj-$(CONFIG_UNICORE32) += setup-irq.o
-- 
1.8.1.5


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH 1/2] add new platform driver for PCI RC
  2015-11-24 11:44 ` [PATCH 1/2] add new platform driver for PCI RC Joao Pinto
@ 2015-11-24 12:15   ` kbuild test robot
  0 siblings, 0 replies; 15+ messages in thread
From: kbuild test robot @ 2015-11-24 12:15 UTC (permalink / raw)
  To: Joao Pinto
  Cc: kbuild-all, linux-pci, linux-kernel, bhelgaas, CARLOS.PALMINHA,
	Vineet.Gupta1, Alexey.Brodkin, Joao Pinto

[-- Attachment #1: Type: text/plain, Size: 7118 bytes --]

Hi Joao,

[auto build test ERROR on arc/for-next]
[also build test ERROR on v4.4-rc2 next-20151124]

url:    https://github.com/0day-ci/linux/commits/Joao-Pinto/add-new-platform-driver-for-PCI-RC/20151124-194755
base:   https://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc for-next
config: i386-allmodconfig (attached as .config)
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All errors (new ones prefixed by >>):

   drivers/pci/host/pcie-designware.c: In function 'dw_pcie_host_init':
   drivers/pci/host/pcie-designware.c:555:7: error: implicit declaration of function 'pci_has_flag' [-Werror=implicit-function-declaration]
     if (!pci_has_flag(PCI_PROBE_ONLY)) {
          ^
   drivers/pci/host/pcie-designware.c:555:20: error: 'PCI_PROBE_ONLY' undeclared (first use in this function)
     if (!pci_has_flag(PCI_PROBE_ONLY)) {
                       ^
   drivers/pci/host/pcie-designware.c:555:20: note: each undeclared identifier is reported only once for each function it appears in
   drivers/pci/host/pcie-designware.c: In function 'dw_pcie_link_retrain':
>> drivers/pci/host/pcie-designware.c:713:23: error: 'LINK_CONTROL_LINK_STATUS_REG' undeclared (first use in this function)
     dw_pcie_readl_rc(pp, LINK_CONTROL_LINK_STATUS_REG, &val);
                          ^
>> drivers/pci/host/pcie-designware.c:714:14: error: 'PCIE_RETRAIN_LINK_MASK' undeclared (first use in this function)
     val = val | PCIE_RETRAIN_LINK_MASK;
                 ^
   cc1: some warnings being treated as errors

vim +/LINK_CONTROL_LINK_STATUS_REG +713 drivers/pci/host/pcie-designware.c

   549	
   550	#ifdef CONFIG_ARM
   551		/* support old dtbs that incorrectly describe IRQs */
   552		pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
   553	#endif
   554	
 > 555		if (!pci_has_flag(PCI_PROBE_ONLY)) {
   556			pci_bus_size_bridges(bus);
   557			pci_bus_assign_resources(bus);
   558	
   559			list_for_each_entry(child, &bus->children, node)
   560				pcie_bus_configure_settings(child);
   561		}
   562	
   563		pci_bus_add_devices(bus);
   564		return 0;
   565	}
   566	
   567	static int dw_pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
   568			u32 devfn, int where, int size, u32 *val)
   569	{
   570		int ret, type;
   571		u32 busdev, cfg_size;
   572		u64 cpu_addr;
   573		void __iomem *va_cfg_base;
   574	
   575		busdev = PCIE_ATU_BUS(bus->number) | PCIE_ATU_DEV(PCI_SLOT(devfn)) |
   576			 PCIE_ATU_FUNC(PCI_FUNC(devfn));
   577	
   578		if (bus->parent->number == pp->root_bus_nr) {
   579			type = PCIE_ATU_TYPE_CFG0;
   580			cpu_addr = pp->cfg0_base;
   581			cfg_size = pp->cfg0_size;
   582			va_cfg_base = pp->va_cfg0_base;
   583		} else {
   584			type = PCIE_ATU_TYPE_CFG1;
   585			cpu_addr = pp->cfg1_base;
   586			cfg_size = pp->cfg1_size;
   587			va_cfg_base = pp->va_cfg1_base;
   588		}
   589	
   590		dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
   591					  type, cpu_addr,
   592					  busdev, cfg_size);
   593		ret = dw_pcie_cfg_read(va_cfg_base + where, size, val);
   594		dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
   595					  PCIE_ATU_TYPE_IO, pp->io_base,
   596					  pp->io_bus_addr, pp->io_size);
   597	
   598		return ret;
   599	}
   600	
   601	static int dw_pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus,
   602			u32 devfn, int where, int size, u32 val)
   603	{
   604		int ret, type;
   605		u32 busdev, cfg_size;
   606		u64 cpu_addr;
   607		void __iomem *va_cfg_base;
   608	
   609		busdev = PCIE_ATU_BUS(bus->number) | PCIE_ATU_DEV(PCI_SLOT(devfn)) |
   610			 PCIE_ATU_FUNC(PCI_FUNC(devfn));
   611	
   612		if (bus->parent->number == pp->root_bus_nr) {
   613			type = PCIE_ATU_TYPE_CFG0;
   614			cpu_addr = pp->cfg0_base;
   615			cfg_size = pp->cfg0_size;
   616			va_cfg_base = pp->va_cfg0_base;
   617		} else {
   618			type = PCIE_ATU_TYPE_CFG1;
   619			cpu_addr = pp->cfg1_base;
   620			cfg_size = pp->cfg1_size;
   621			va_cfg_base = pp->va_cfg1_base;
   622		}
   623	
   624		dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
   625					  type, cpu_addr,
   626					  busdev, cfg_size);
   627		ret = dw_pcie_cfg_write(va_cfg_base + where, size, val);
   628		dw_pcie_prog_outbound_atu(pp, PCIE_ATU_REGION_INDEX0,
   629					  PCIE_ATU_TYPE_IO, pp->io_base,
   630					  pp->io_bus_addr, pp->io_size);
   631	
   632		return ret;
   633	}
   634	
   635	static int dw_pcie_valid_config(struct pcie_port *pp,
   636					struct pci_bus *bus, int dev)
   637	{
   638		/* If there is no link, then there is no device */
   639		if (bus->number != pp->root_bus_nr) {
   640			if (!dw_pcie_link_up(pp))
   641				return 0;
   642		}
   643	
   644		/* access only one slot on each root port */
   645		if (bus->number == pp->root_bus_nr && dev > 0)
   646			return 0;
   647	
   648		/*
   649		 * do not read more than one device on the bus directly attached
   650		 * to RC's (Virtual Bridge's) DS side.
   651		 */
   652		if (bus->primary == pp->root_bus_nr && dev > 0)
   653			return 0;
   654	
   655		return 1;
   656	}
   657	
   658	static int dw_pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
   659				int size, u32 *val)
   660	{
   661		struct pcie_port *pp = bus->sysdata;
   662		int ret;
   663	
   664		if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) {
   665			*val = 0xffffffff;
   666			return PCIBIOS_DEVICE_NOT_FOUND;
   667		}
   668	
   669		if (bus->number != pp->root_bus_nr)
   670			if (pp->ops->rd_other_conf)
   671				ret = pp->ops->rd_other_conf(pp, bus, devfn,
   672							where, size, val);
   673			else
   674				ret = dw_pcie_rd_other_conf(pp, bus, devfn,
   675							where, size, val);
   676		else
   677			ret = dw_pcie_rd_own_conf(pp, where, size, val);
   678	
   679		return ret;
   680	}
   681	
   682	static int dw_pcie_wr_conf(struct pci_bus *bus, u32 devfn,
   683				int where, int size, u32 val)
   684	{
   685		struct pcie_port *pp = bus->sysdata;
   686		int ret;
   687	
   688		if (dw_pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0)
   689			return PCIBIOS_DEVICE_NOT_FOUND;
   690	
   691		if (bus->number != pp->root_bus_nr)
   692			if (pp->ops->wr_other_conf)
   693				ret = pp->ops->wr_other_conf(pp, bus, devfn,
   694							where, size, val);
   695			else
   696				ret = dw_pcie_wr_other_conf(pp, bus, devfn,
   697							where, size, val);
   698		else
   699			ret = dw_pcie_wr_own_conf(pp, where, size, val);
   700	
   701		return ret;
   702	}
   703	
   704	static struct pci_ops dw_pcie_ops = {
   705		.read = dw_pcie_rd_conf,
   706		.write = dw_pcie_wr_conf,
   707	};
   708	
   709	void dw_pcie_link_retrain(struct pcie_port *pp)
   710	{
   711		u32 val = 0;
   712	
 > 713		dw_pcie_readl_rc(pp, LINK_CONTROL_LINK_STATUS_REG, &val);
 > 714		val = val | PCIE_RETRAIN_LINK_MASK;
   715		dw_pcie_writel_rc(pp, val, LINK_CONTROL_LINK_STATUS_REG);
   716	}
   717	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 52568 bytes --]

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 2/2] PCI support added to ARC
  2015-11-30  1:00       ` Bjorn Helgaas
@ 2015-11-30  6:21         ` Vineet Gupta
  -1 siblings, 0 replies; 15+ messages in thread
From: Vineet Gupta @ 2015-11-30  6:21 UTC (permalink / raw)
  To: Bjorn Helgaas
  Cc: Joao Pinto, linux-pci, linux-kernel, bhelgaas, Carlos Palminha,
	Alexey Brodkin, arcml, Arnd Bergmann

On Monday 30 November 2015 06:30 AM, Bjorn Helgaas wrote:
> + *
> + *  Copyright (C) 2004-2014 Synopsys, Inc. (www.synopsys.com)
>> Perhaps extend this to 2016 (and other copyrights in the patch too if needed)
> What is the reasoning behind claiming a copyright date in the future?
> That doesn't sound right to me.

TBH I could be completely wrong here. That's just a convention I tend to follow
whenever introducing a new file - specially when we are close to a new year.

-Vineet

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 2/2] PCI support added to ARC
@ 2015-11-30  6:21         ` Vineet Gupta
  0 siblings, 0 replies; 15+ messages in thread
From: Vineet Gupta @ 2015-11-30  6:21 UTC (permalink / raw)
  To: linux-snps-arc

On Monday 30 November 2015 06:30 AM, Bjorn Helgaas wrote:
> + *
> + *  Copyright (C) 2004-2014 Synopsys, Inc. (www.synopsys.com)
>> Perhaps extend this to 2016 (and other copyrights in the patch too if needed)
> What is the reasoning behind claiming a copyright date in the future?
> That doesn't sound right to me.

TBH I could be completely wrong here. That's just a convention I tend to follow
whenever introducing a new file - specially when we are close to a new year.

-Vineet

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 2/2] PCI support added to ARC
  2015-11-25  5:25     ` Vineet Gupta
@ 2015-11-30  1:00       ` Bjorn Helgaas
  -1 siblings, 0 replies; 15+ messages in thread
From: Bjorn Helgaas @ 2015-11-30  1:00 UTC (permalink / raw)
  To: Vineet Gupta
  Cc: Joao Pinto, linux-pci, linux-kernel, bhelgaas, Carlos Palminha,
	Alexey Brodkin, arcml, Arnd Bergmann

On Wed, Nov 25, 2015 at 05:25:37AM +0000, Vineet Gupta wrote:
> On Tuesday 24 November 2015 08:02 PM, Joao Pinto wrote:

> > +++ b/arch/arc/include/asm/mach/pci.h
> > @@ -0,0 +1,97 @@
> > +/*
> > + *  arch/arc/include/asm/mach/pci.h
> > + *
> > + *  Copyright (C) 2004-2014 Synopsys, Inc. (www.synopsys.com)
> 
> Perhaps extend this to 2016 (and other copyrights in the patch too if needed)

What is the reasoning behind claiming a copyright date in the future?
That doesn't sound right to me.

Bjorn

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 2/2] PCI support added to ARC
@ 2015-11-30  1:00       ` Bjorn Helgaas
  0 siblings, 0 replies; 15+ messages in thread
From: Bjorn Helgaas @ 2015-11-30  1:00 UTC (permalink / raw)
  To: linux-snps-arc

On Wed, Nov 25, 2015@05:25:37AM +0000, Vineet Gupta wrote:
> On Tuesday 24 November 2015 08:02 PM, Joao Pinto wrote:

> > +++ b/arch/arc/include/asm/mach/pci.h
> > @@ -0,0 +1,97 @@
> > +/*
> > + *  arch/arc/include/asm/mach/pci.h
> > + *
> > + *  Copyright (C) 2004-2014 Synopsys, Inc. (www.synopsys.com)
> 
> Perhaps extend this to 2016 (and other copyrights in the patch too if needed)

What is the reasoning behind claiming a copyright date in the future?
That doesn't sound right to me.

Bjorn

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 2/2] PCI support added to ARC
  2015-11-25 16:46       ` Bjorn Helgaas
@ 2015-11-26 15:41         ` Joao Pinto
  -1 siblings, 0 replies; 15+ messages in thread
From: Joao Pinto @ 2015-11-26 15:41 UTC (permalink / raw)
  To: Bjorn Helgaas, Vineet Gupta
  Cc: Joao Pinto, linux-pci, linux-kernel, bhelgaas, Carlos Palminha,
	Alexey Brodkin, arcml, Arnd Bergmann

Hi Bjorn,

On 11/25/2015 4:46 PM, Bjorn Helgaas wrote:
> On Wed, Nov 25, 2015 at 05:25:37AM +0000, Vineet Gupta wrote:
>> On Tuesday 24 November 2015 08:02 PM, Joao Pinto wrote:
> 
>>> +			pr_err("PCI: Device %s not available because"/
>>> +			       " of resource collisions\n", pci_name(dev));
>>
>> Better not to break strings - even if they sometime exceed line sz limit of 80.
>> You could anyways reduce the string content herer.
> 
> Also use dev_err() instead of pr_err().
> 

Thanks for the review. Could you please check PATCH 1/2 regarding the new
platform driver? This way I would produce a v2 of the patch set.

Thanks,
Joao


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 2/2] PCI support added to ARC
@ 2015-11-26 15:41         ` Joao Pinto
  0 siblings, 0 replies; 15+ messages in thread
From: Joao Pinto @ 2015-11-26 15:41 UTC (permalink / raw)
  To: linux-snps-arc

Hi Bjorn,

On 11/25/2015 4:46 PM, Bjorn Helgaas wrote:
> On Wed, Nov 25, 2015@05:25:37AM +0000, Vineet Gupta wrote:
>> On Tuesday 24 November 2015 08:02 PM, Joao Pinto wrote:
> 
>>> +			pr_err("PCI: Device %s not available because"/
>>> +			       " of resource collisions\n", pci_name(dev));
>>
>> Better not to break strings - even if they sometime exceed line sz limit of 80.
>> You could anyways reduce the string content herer.
> 
> Also use dev_err() instead of pr_err().
> 

Thanks for the review. Could you please check PATCH 1/2 regarding the new
platform driver? This way I would produce a v2 of the patch set.

Thanks,
Joao

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 2/2] PCI support added to ARC
  2015-11-25  5:25     ` Vineet Gupta
@ 2015-11-25 16:46       ` Bjorn Helgaas
  -1 siblings, 0 replies; 15+ messages in thread
From: Bjorn Helgaas @ 2015-11-25 16:46 UTC (permalink / raw)
  To: Vineet Gupta
  Cc: Joao Pinto, linux-pci, linux-kernel, bhelgaas, Carlos Palminha,
	Alexey Brodkin, arcml, Arnd Bergmann

On Wed, Nov 25, 2015 at 05:25:37AM +0000, Vineet Gupta wrote:
> On Tuesday 24 November 2015 08:02 PM, Joao Pinto wrote:

> > +			pr_err("PCI: Device %s not available because"/
> > +			       " of resource collisions\n", pci_name(dev));
> 
> Better not to break strings - even if they sometime exceed line sz limit of 80.
> You could anyways reduce the string content herer.

Also use dev_err() instead of pr_err().

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 2/2] PCI support added to ARC
@ 2015-11-25 16:46       ` Bjorn Helgaas
  0 siblings, 0 replies; 15+ messages in thread
From: Bjorn Helgaas @ 2015-11-25 16:46 UTC (permalink / raw)
  To: linux-snps-arc

On Wed, Nov 25, 2015@05:25:37AM +0000, Vineet Gupta wrote:
> On Tuesday 24 November 2015 08:02 PM, Joao Pinto wrote:

> > +			pr_err("PCI: Device %s not available because"/
> > +			       " of resource collisions\n", pci_name(dev));
> 
> Better not to break strings - even if they sometime exceed line sz limit of 80.
> You could anyways reduce the string content herer.

Also use dev_err() instead of pr_err().

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH 2/2] PCI support added to ARC
  2015-11-24 14:32 ` [PATCH 2/2] PCI support added to ARC Joao Pinto
@ 2015-11-25  5:25     ` Vineet Gupta
  0 siblings, 0 replies; 15+ messages in thread
From: Vineet Gupta @ 2015-11-25  5:25 UTC (permalink / raw)
  To: Joao Pinto, linux-pci, linux-kernel
  Cc: bhelgaas, Carlos Palminha, Alexey Brodkin, arcml, Arnd Bergmann

On Tuesday 24 November 2015 08:02 PM, Joao Pinto wrote:
> This patch adds PCI support to ARC and updates drivers/pci Makefile enabling
> the ARC arch to use the generic PCI setup functions.
>
> Signed-off-by: Joao Pinto <jpinto@synopsys.com>
> ---
>  arch/arc/Kconfig                |  22 +++
>  arch/arc/include/asm/dma.h      |   5 +
>  arch/arc/include/asm/io.h       |   2 +
>  arch/arc/include/asm/mach/pci.h |  97 +++++++++++
>  arch/arc/include/asm/pci.h      |  34 ++++
>  arch/arc/kernel/Makefile        |   1 +
>  arch/arc/kernel/pcibios.c       | 360 ++++++++++++++++++++++++++++++++++++++++
>  arch/arc/mm/ioremap.c           |  29 +++-
>  arch/arc/plat-axs10x/Kconfig    |   1 +
>  drivers/pci/Makefile            |   1 +
>  10 files changed, 551 insertions(+), 1 deletion(-)
>  create mode 100644 arch/arc/include/asm/mach/pci.h
>  create mode 100644 arch/arc/include/asm/pci.h
>  create mode 100644 arch/arc/kernel/pcibios.c
>
> diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
> index 2c2ac3f..5b526a3 100644
> --- a/arch/arc/Kconfig
> +++ b/arch/arc/Kconfig
> @@ -19,6 +19,7 @@ config ARC
>  	select GENERIC_FIND_FIRST_BIT
>  	# for now, we don't need GENERIC_IRQ_PROBE, CONFIG_GENERIC_IRQ_CHIP
>  	select GENERIC_IRQ_SHOW
> +	select GENERIC_PCI_IOMAP
>  	select GENERIC_PENDING_IRQ if SMP
>  	select GENERIC_SMP_IDLE_THREAD
>  	select HAVE_ARCH_KGDB
> @@ -39,6 +40,9 @@ config ARC
>  	select PERF_USE_VMALLOC
>  	select HAVE_DEBUG_STACKOVERFLOW
>  
> +config MIGHT_HAVE_PCI
> +	bool
> +
>  config TRACE_IRQFLAGS_SUPPORT
>  	def_bool y
>  
> @@ -110,6 +114,24 @@ config ISA_ARCV2
>  
>  endchoice
>  
> +menu "Bus Support"
> +
> +config PCI
> +	bool "PCI support" if MIGHT_HAVE_PCI
> +	help
> +	  PCI is the name of a bus system, i.e. the way the CPU talks to the other stuff inside
> +	  your box.Find out if your board/platform have PCI.
> +	  Note: PCIE support for Synopsys Device will be available only when
> +	  HAPS DX is configured with PCIE RC bitmap. If you have PCI, say Y, otherwise N.
> +
> +config PCI_SYSCALL
> +	def_bool PCI
> +
> +source "drivers/pci/Kconfig"
> +source "drivers/pci/pcie/Kconfig"
> +
> +endmenu
> +

Could you please move these towards end of file - preferably between sourcing of
drivers/Kconfig and fs/Kconfig to keep hardware related stuff together.

>  menu "ARC CPU Configuration"
>  
>  choice
> diff --git a/arch/arc/include/asm/dma.h b/arch/arc/include/asm/dma.h
> index ca7c451..37942fa 100644
> --- a/arch/arc/include/asm/dma.h
> +++ b/arch/arc/include/asm/dma.h
> @@ -10,5 +10,10 @@
>  #define ASM_ARC_DMA_H
>  
>  #define MAX_DMA_ADDRESS 0xC0000000
> +#ifdef CONFIG_PCI
> +extern int isa_dma_bridge_buggy;
> +#else
> +#define isa_dma_bridge_buggy    (0)
> +#endif
>  
>  #endif
> diff --git a/arch/arc/include/asm/io.h b/arch/arc/include/asm/io.h
> index 694ece8..d86c2e3 100644
> --- a/arch/arc/include/asm/io.h
> +++ b/arch/arc/include/asm/io.h
> @@ -17,6 +17,8 @@ extern void __iomem *ioremap(unsigned long physaddr, unsigned long size);
>  extern void __iomem *ioremap_prot(phys_addr_t offset, unsigned long size,
>  				  unsigned long flags);
>  extern void iounmap(const void __iomem *addr);
> +extern void __iomem *ioport_map(unsigned long port, unsigned int size);
> +extern int pci_ioremap_io(unsigned int offset, phys_addr_t phys_addr);

ioport_unmap is missing. Anyhow you can define the empty ioport_{map,unmap} as
static inline here (see below)

>  #define ioremap_nocache(phy, sz)	ioremap(phy, sz)
>  #define ioremap_wc(phy, sz)		ioremap(phy, sz)
> diff --git a/arch/arc/include/asm/mach/pci.h b/arch/arc/include/asm/mach/pci.h
> new file mode 100644
> index 0000000..9e75277
> --- /dev/null
> +++ b/arch/arc/include/asm/mach/pci.h
> @@ -0,0 +1,97 @@
> +/*
> + *  arch/arc/include/asm/mach/pci.h
> + *
> + *  Copyright (C) 2004-2014 Synopsys, Inc. (www.synopsys.com)

Perhaps extend this to 2016 (and other copyrights in the patch too if needed)

> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#ifndef __ASM_MACH_PCI_H
> +#define __ASM_MACH_PCI_H
> +
> +#include <linux/ioport.h>
> +
> +struct pci_sys_data;
> +struct pci_ops;
> +struct pci_bus;
> +struct device;
> +
> +struct hw_pci {
> +#ifdef CONFIG_PCI_DOMAINS
> +	int		domain;
> +#endif
> +	struct pci_ops	*ops;
> +	int		nr_controllers;
> +	void		**private_data;
> +	int		(*setup)(int nr, struct pci_sys_data *);
> +	struct pci_bus *(*scan)(int nr, struct pci_sys_data *);
> +	void		(*preinit)(void);
> +	void		(*postinit)(void);
> +	u8		(*swizzle)(struct pci_dev *dev, u8 *pin);
> +	int		(*map_irq)(const struct pci_dev *dev, u8 slot, u8 pin);
> +	resource_size_t (*align_resource)(struct pci_dev *dev,
> +					  const struct resource *res,
> +					  resource_size_t start,
> +					  resource_size_t size,
> +					  resource_size_t align);
> +	void		(*add_bus)(struct pci_bus *bus);
> +	void		(*remove_bus)(struct pci_bus *bus);
> +};
> +
> +/*
> + * Per-controller structure
> + */
> +struct pci_sys_data {
> +#ifdef CONFIG_PCI_DOMAINS
> +	int		domain;
> +#endif
> +	struct list_head node;
> +	int		busnr;		/* primary bus number		    */
> +	u64		mem_offset;	/* bus->cpu memory mapping offset   */
> +	unsigned long	io_offset;	/* bus->cpu IO mapping offset	    */
> +	struct pci_bus	*bus;		/* PCI bus			    */
> +	struct list_head resources;	/* root bus resources (apertures)   */
> +	struct resource io_res;
> +	char		io_res_name[12];
> +					/* Bridge swizzling		    */
> +	u8		(*swizzle)(struct pci_dev *, u8 *);
> +					/* IRQ mapping			    */
> +	int		(*map_irq)(const struct pci_dev *, u8, u8);
> +					/* Resource alignement requirements */
> +	resource_size_t (*align_resource)(struct pci_dev *dev,
> +					  const struct resource *res,
> +					  resource_size_t start,
> +					  resource_size_t size,
> +					  resource_size_t align);
> +	void		(*add_bus)(struct pci_bus *bus);
> +	void		(*remove_bus)(struct pci_bus *bus);
> +	void		*private_data;	/* platform controller private data */
> +};
> +
> +/*
> + * Call this with your hw_pci struct to initialise the PCI system.
> + */
> +void pci_common_init_dev(struct device *, struct hw_pci *);
> +
> +/*
> + * Compatibility wrapper for older platforms that do not care about
> + * passing the parent device.
> + */
> +static inline void pci_common_init(struct hw_pci *hw)
> +{
> +	pci_common_init_dev(NULL, hw);
> +}
> +
> +/*
> + * Setup early fixed I/O mapping.
> + */
> +#if defined(CONFIG_PCI)
> +extern void pci_map_io_early(unsigned long pfn);
> +#else
> +static inline void pci_map_io_early(unsigned long pfn) {}
> +#endif
> +
> +#endif /* __ASM_MACH_PCI_H */
> +
> diff --git a/arch/arc/include/asm/pci.h b/arch/arc/include/asm/pci.h
> new file mode 100644
> index 0000000..085b15f
> --- /dev/null
> +++ b/arch/arc/include/asm/pci.h
> @@ -0,0 +1,34 @@
> +/*
> + * Copyright (C) 2015-2016 Synopsys, Inc. (www.synopsys.com)
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#ifndef _ASM_ARC_PCI_H
> +#define _ASM_ARC_PCI_H
> +
> +#ifdef __KERNEL__
> +#include <asm-generic/pci-dma-compat.h>
> +#include <asm-generic/pci-bridge.h>
> +
> +#include <asm/mach/pci.h> /* for pci_sys_data */
> +
> +extern unsigned long pcibios_min_io;
> +#define PCIBIOS_MIN_IO pcibios_min_io
> +extern unsigned long pcibios_min_mem;
> +#define PCIBIOS_MIN_MEM pcibios_min_mem
> +
> +#define pcibios_assign_all_busses()	1
> +/*
> + * The PCI address space does equal the physical memory address space.
> + * The networking and block device layers use this boolean for bounce
> + * buffer decisions.
> + */
> +#define PCI_DMA_BUS_IS_PHYS     (1)
> +
> +#endif /* __KERNEL__ */
> +
> +#endif /* _ASM_ARC_PCI_H */
> +
> diff --git a/arch/arc/kernel/Makefile b/arch/arc/kernel/Makefile
> index e7f3625..1bc2036 100644
> --- a/arch/arc/kernel/Makefile
> +++ b/arch/arc/kernel/Makefile
> @@ -12,6 +12,7 @@ obj-y	:= arcksyms.o setup.o irq.o time.o reset.o ptrace.o process.o devtree.o
>  obj-y	+= signal.o traps.o sys.o troubleshoot.o stacktrace.o disasm.o clk.o
>  obj-$(CONFIG_ISA_ARCOMPACT)		+= entry-compact.o intc-compact.o
>  obj-$(CONFIG_ISA_ARCV2)			+= entry-arcv2.o intc-arcv2.o
> +obj-$(CONFIG_PCI)  			+= pcibios.o
>  
>  obj-$(CONFIG_MODULES)			+= arcksyms.o module.o
>  obj-$(CONFIG_SMP) 			+= smp.o
> diff --git a/arch/arc/kernel/pcibios.c b/arch/arc/kernel/pcibios.c
> new file mode 100644
> index 0000000..a7bd76a
> --- /dev/null
> +++ b/arch/arc/kernel/pcibios.c
> @@ -0,0 +1,360 @@
> +/*
> + * Copyright (C) 2014-2015 Synopsys, Inc. (www.synopsys.com)
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/pci.h>
> +#include <linux/delay.h>
> +#include <linux/string.h>
> +#include <linux/init.h>
> +#include <linux/sched.h>
> +#include <linux/errno.h>
> +#include <linux/bootmem.h>
> +#include <linux/sizes.h>
> +#include <linux/slab.h>
> +
> +#include <asm/pci.h>
> +#include <asm/mach/pci.h>
> +
> +static int pcibios_init_resources(int busnr, struct pci_sys_data *sys)
> +{
> +	int ret;
> +	struct pci_host_bridge_window *window;
> +
> +	if (list_empty(&sys->resources)) {
> +		pci_add_resource_offset(&sys->resources,
> +			 &iomem_resource, sys->mem_offset);
> +	}
> +
> +	list_for_each_entry(window, &sys->resources, list) {
> +		if (resource_type(window->res) == IORESOURCE_IO)
> +			return 0;
> +	}
> +
> +	sys->io_res.start = (busnr * SZ_64K) ?  : pcibios_min_io;
> +	sys->io_res.end = (busnr + 1) * SZ_64K - 1;
> +	sys->io_res.flags = IORESOURCE_IO;
> +	sys->io_res.name = sys->io_res_name;
> +	sprintf(sys->io_res_name, "PCI%d I/O", busnr);
> +
> +	ret = request_resource(&ioport_resource, &sys->io_res);
> +	if (ret) {
> +		pr_err("PCI: unable to allocate I/O port region (%d)\n", ret);
> +		return ret;
> +	}
> +	pci_add_resource_offset(&sys->resources, &sys->io_res,
> +				sys->io_offset);
> +
> +	return 0;
> +}
> +
> +
> +static void pcibios_init_hw(struct device *parent, struct hw_pci *hw,
> +			    struct list_head *head)
> +{
> +	struct pci_sys_data *sys = NULL;
> +	int ret;
> +	int nr, busnr;
> +
> +	for (nr = busnr = 0; nr < hw->nr_controllers; nr++) {
> +		sys = kzalloc(sizeof(struct pci_sys_data), GFP_KERNEL);
> +		if (!sys)
> +			panic("PCI: unable to allocate sys data!");
> +
> +#ifdef CONFIG_PCI_DOMAINS
> +		sys->domain  = hw->domain;
> +#endif
> +		sys->busnr   = busnr;
> +		sys->swizzle = hw->swizzle;
> +		sys->map_irq = hw->map_irq;
> +		sys->align_resource = hw->align_resource;
> +		sys->add_bus = hw->add_bus;
> +		sys->remove_bus = hw->remove_bus;
> +		INIT_LIST_HEAD(&sys->resources);
> +
> +
> +		if (hw->private_data)
> +			sys->private_data = hw->private_data[nr];
> +
> +		ret = hw->setup(nr, sys);
> +
> +		if (ret > 0) {
> +			ret = pcibios_init_resources(nr, sys);
> +			if (ret)  {
> +				kfree(sys);
> +				break;
> +			}
> +
> +			if (hw->scan)
> +				sys->bus = hw->scan(nr, sys);
> +			else
> +				sys->bus = pci_scan_root_bus(parent, sys->busnr,
> +						hw->ops, sys, &sys->resources);
> +
> +			if (!sys->bus)
> +				panic("PCI: unable to scan bus!");
> +
> +			busnr = sys->bus->busn_res.end + 1;
> +
> +			list_add(&sys->node, head);
> +		} else {
> +			kfree(sys);
> +			if (ret < 0)
> +				break;
> +		}
> +	}
> +}
> +int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
> +{
> +	return 0;
> +}
> +
> +void pcibios_add_bus(struct pci_bus *bus)
> +{
> +	struct pci_sys_data *sys = bus->sysdata;
> +
> +	if (sys->add_bus)
> +		sys->add_bus(bus);
> +}
> +
> +void pcibios_remove_bus(struct pci_bus *bus)
> +{
> +	struct pci_sys_data *sys = bus->sysdata;
> +
> +	if (sys->remove_bus)
> +		sys->remove_bus(bus);
> +}
> +
> +/*
> + * Swizzle the device pin each time we cross a bridge.  If a platform does
> + * not provide a swizzle function, we perform the standard PCI swizzling.
> + *
> + * The default swizzling walks up the bus tree one level at a time, applying
> + * the standard swizzle function at each step, stopping when it finds the PCI
> + * root bus.  This will return the slot number of the bridge device on the
> + * root bus and the interrupt pin on that device which should correspond
> + * with the downstream device interrupt.
> + *
> + * Platforms may override this, in which case the slot and pin returned
> + * depend entirely on the platform code.  However, please note that the
> + * PCI standard swizzle is implemented on plug-in cards and Cardbus based
> + * PCI extenders, so it can not be ignored.
> + */
> +static u8 pcibios_swizzle(struct pci_dev *dev, u8 *pin)
> +{
> +	struct pci_sys_data *sys = dev->sysdata;
> +	int slot, oldpin = *pin;
> +
> +	if (sys->swizzle)
> +		slot = sys->swizzle(dev, pin);
> +	else
> +		slot = pci_common_swizzle(dev, pin);
> +
> +	return slot;
> +}
> +
> +/*
> + * Map a slot/pin to an IRQ.
> + */
> +static int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
> +{
> +	struct pci_sys_data *sys = dev->sysdata;
> +	int irq = -1;
> +
> +	if (sys->map_irq)
> +		irq = sys->map_irq(dev, slot, pin);
> +
> +	return irq;
> +}
> +
> +void pci_common_init_dev(struct device *parent, struct hw_pci *hw)
> +{
> +	struct pci_sys_data *sys;
> +	LIST_HEAD(head);
> +
> +	pci_add_flags(PCI_REASSIGN_ALL_RSRC);
> +	if (hw->preinit)
> +		hw->preinit();
> +	pcibios_init_hw(parent, hw, &head);
> +	if (hw->postinit)
> +		hw->postinit();
> +
> +	pci_fixup_irqs(pcibios_swizzle, pcibios_map_irq);
> +
> +	list_for_each_entry(sys, &head, node) {
> +		struct pci_bus *bus = sys->bus;
> +
> +		if (!pci_has_flag(PCI_PROBE_ONLY)) {
> +			/*
> +			 * Size the bridge windows.
> +			 */
> +			pci_bus_size_bridges(bus);
> +
> +			/*
> +			 * Assign resources.
> +			 */
> +			pci_bus_assign_resources(bus);
> +		}
> +
> +		/*
> +		 * Tell drivers about devices found.
> +		 */
> +		pci_bus_add_devices(bus);
> +	}
> +}
> +
> +/*
> + * We don't have to worry about legacy ISA devices, so nothing to do here
> + */
> +resource_size_t pcibios_align_resource(void *data, const struct resource *res,
> +				resource_size_t size, resource_size_t align)
> +{
> +	return res->start;
> +}
> +
> +/**
> + * pcibios_enable_device - Enable I/O and memory.
> + * @dev: PCI device to be enabled
> + */
> +int pcibios_enable_device(struct pci_dev *dev, int mask)
> +{
> +	u16 cmd, old_cmd;
> +	int idx;
> +	struct resource *r;
> +
> +	pci_read_config_word(dev, PCI_COMMAND, &cmd);
> +	old_cmd = cmd;
> +	for (idx = 0; idx < 6; idx++) {
> +		/* Only set up the requested stuff */
> +		if (!(mask & (1 << idx)))
> +			continue;
> +
> +		r = dev->resource + idx;
> +		if (!r->start && r->end) {
> +			pr_err("PCI: Device %s not available because"/
> +			       " of resource collisions\n", pci_name(dev));

Better not to break strings - even if they sometime exceed line sz limit of 80.
You could anyways reduce the string content herer.

> +			return -EINVAL;
> +		}
> +		if (r->flags & IORESOURCE_IO)
> +			cmd |= PCI_COMMAND_IO;
> +		if (r->flags & IORESOURCE_MEM)
> +			cmd |= PCI_COMMAND_MEMORY;
> +	}
> +
> +	/*
> +	 * Bridges (eg, cardbus bridges) need to be fully enabled
> +	 */
> +	if ((dev->class >> 16) == PCI_BASE_CLASS_BRIDGE)
> +		cmd |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
> +
> +	if (cmd != old_cmd) {
> +		pr_info("PCI: enabling device %s (%04x -> %04x)\n",
> +		       pci_name(dev), old_cmd, cmd);
> +		pci_write_config_word(dev, PCI_COMMAND, cmd);
> +	}
> +	return 0;
> +}
> +
> +/*
> + * If the bus contains any of these devices, then we must not turn on
> + * parity checking of any kind.  Currently this is CyberPro 20x0 only.
> + */
> +static inline int pdev_bad_for_parity(struct pci_dev *dev)
> +{
> +	return ((dev->vendor == PCI_VENDOR_ID_INTERG &&
> +		 (dev->device == PCI_DEVICE_ID_INTERG_2000 ||
> +		  dev->device == PCI_DEVICE_ID_INTERG_2010)) ||
> +		(dev->vendor == PCI_VENDOR_ID_ITE &&
> +		 dev->device == PCI_DEVICE_ID_ITE_8152));
> +
> +}
> +
> +/*
> + * pcibios_fixup_bus - Called after each bus is probed,
> + * but before its children are examined.
> + */
> +void pcibios_fixup_bus(struct pci_bus *bus)
> +{
> +	struct pci_dev *dev;
> +	u16 features = PCI_COMMAND_SERR | PCI_COMMAND_PARITY
> +			| PCI_COMMAND_FAST_BACK;
> +
> +	/*
> +	 * Walk the devices on this bus, working out what we can
> +	 * and can't support.
> +	 */
> +	list_for_each_entry(dev, &bus->devices, bus_list) {
> +		u16 status;
> +
> +		pci_read_config_word(dev, PCI_STATUS, &status);
> +
> +		/*
> +		 * If any device on this bus does not support fast back
> +		 * to back transfers, then the bus as a whole is not able
> +		 * to support them.  Having fast back to back transfers
> +		 * on saves us one PCI cycle per transaction.
> +		 */
> +		if (!(status & PCI_STATUS_FAST_BACK))
> +			features &= ~PCI_COMMAND_FAST_BACK;
> +
> +		if (pdev_bad_for_parity(dev))
> +			features &= ~(PCI_COMMAND_SERR | PCI_COMMAND_PARITY);
> +
> +		switch (dev->class >> 8) {
> +		case PCI_CLASS_BRIDGE_PCI:
> +			pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &status);
> +			status |= PCI_BRIDGE_CTL_PARITY
> +					|PCI_BRIDGE_CTL_MASTER_ABORT;
> +			status &= ~(PCI_BRIDGE_CTL_BUS_RESET
> +					|PCI_BRIDGE_CTL_FAST_BACK);
> +			pci_write_config_word(dev, PCI_BRIDGE_CONTROL, status);
> +			break;
> +
> +		case PCI_CLASS_BRIDGE_CARDBUS:
> +			pci_read_config_word(dev, PCI_CB_BRIDGE_CONTROL,
> +						&status);
> +			status |= PCI_CB_BRIDGE_CTL_PARITY
> +					|PCI_CB_BRIDGE_CTL_MASTER_ABORT;
> +			pci_write_config_word(dev, PCI_CB_BRIDGE_CONTROL,
> +						status);
> +			break;
> +		}
> +	}
> +
> +	/*
> +	 * Now walk the devices again, this time setting them up.
> +	 */
> +	list_for_each_entry(dev, &bus->devices, bus_list) {
> +		u16 cmd;
> +
> +		pci_read_config_word(dev, PCI_COMMAND, &cmd);
> +		cmd |= features;
> +		pci_write_config_word(dev, PCI_COMMAND, cmd);
> +
> +		pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE,
> +				      L1_CACHE_BYTES >> 2);
> +	}
> +
> +	/*
> +	 * Propagate the flags to the PCI bridge.
> +	 */
> +	if (bus->self && bus->self->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
> +		if (features & PCI_COMMAND_FAST_BACK)
> +			bus->bridge_ctl |= PCI_BRIDGE_CTL_FAST_BACK;
> +		if (features & PCI_COMMAND_PARITY)
> +			bus->bridge_ctl |= PCI_BRIDGE_CTL_PARITY;
> +	}
> +
> +	/*
> +	 * Report what we did for this bus
> +	 */
> +	pr_info("PCI: bus%d: Fast back to back transfers %sabled\n",
> +		bus->number, (features & PCI_COMMAND_FAST_BACK) ? "en" : "dis");
> +}
> +EXPORT_SYMBOL(pcibios_fixup_bus);
> +
> diff --git a/arch/arc/mm/ioremap.c b/arch/arc/mm/ioremap.c
> index 739e65f..583c9fe 100644
> --- a/arch/arc/mm/ioremap.c
> +++ b/arch/arc/mm/ioremap.c
> @@ -13,6 +13,26 @@
>  #include <linux/mm.h>
>  #include <linux/slab.h>
>  #include <linux/cache.h>
> +#include <linux/sizes.h>

You really need this #include.

> +
> +#ifdef CONFIG_PCI
> +unsigned long pcibios_min_io = 0x100;
> +EXPORT_SYMBOL(pcibios_min_io);
> +
> +unsigned long pcibios_min_mem = 0x100000;
> +EXPORT_SYMBOL(pcibios_min_mem);
> +#endif

Can these be moved into one the newer pci files you've introduced ?

> +
> +inline void __iomem *ioport_map(unsigned long port, unsigned int nr)
> +{
> +	return port;
> +}
> +EXPORT_SYMBOL(ioport_map);
> +
> +inline void ioport_unmap(void __iomem *addr)
> +{
> +}
> +EXPORT_SYMBOL(ioport_unmap);

So you are inlining and EXPORT the function which doesn't make sense. EXPORTs are
generally _GPL.
Anyhow since these are empty, please move them into  io.h

>  
>  void __iomem *ioremap(unsigned long paddr, unsigned long size)
>  {
> @@ -80,7 +100,6 @@ void __iomem *ioremap_prot(phys_addr_t paddr, unsigned long size,
>  }
>  EXPORT_SYMBOL(ioremap_prot);
>  
> -
>  void iounmap(const void __iomem *addr)
>  {
>  	if (addr >= (void __force __iomem *)ARC_UNCACHED_ADDR_SPACE)
> @@ -89,3 +108,11 @@ void iounmap(const void __iomem *addr)
>  	vfree((void *)(PAGE_MASK & (unsigned long __force)addr));
>  }
>  EXPORT_SYMBOL(iounmap);
> +
> +#ifdef CONFIG_PCI
> +int pci_ioremap_io(unsigned int offset, phys_addr_t phys_addr)
> +{
> +	return ioremap_nocache(phys_addr + offset,  SZ_64K);
> +}
> +EXPORT_SYMBOL_GPL(pci_ioremap_io);
> +#endif
> diff --git a/arch/arc/plat-axs10x/Kconfig b/arch/arc/plat-axs10x/Kconfig
> index d475f9d..33b5db6 100644
> --- a/arch/arc/plat-axs10x/Kconfig
> +++ b/arch/arc/plat-axs10x/Kconfig
> @@ -8,6 +8,7 @@
>  
>  menuconfig ARC_PLAT_AXS10X
>  	bool "Synopsys ARC AXS10x Software Development Platforms"
> +	select MIGHT_HAVE_PCI

We tend to keep select lists sorted.

>  	select DW_APB_ICTL
>  	select GPIO_DWAPB
>  	select OF_GPIO
> diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
> index be3f631..2154092 100644
> --- a/drivers/pci/Makefile
> +++ b/drivers/pci/Makefile
> @@ -32,6 +32,7 @@ obj-$(CONFIG_PCI_IOV) += iov.o
>  # Some architectures use the generic PCI setup functions
>  #
>  obj-$(CONFIG_ALPHA) += setup-irq.o
> +obj-$(CONFIG_ARC) += setup-irq.o
>  obj-$(CONFIG_ARM) += setup-irq.o
>  obj-$(CONFIG_ARM64) += setup-irq.o
>  obj-$(CONFIG_UNICORE32) += setup-irq.o


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 2/2] PCI support added to ARC
@ 2015-11-25  5:25     ` Vineet Gupta
  0 siblings, 0 replies; 15+ messages in thread
From: Vineet Gupta @ 2015-11-25  5:25 UTC (permalink / raw)
  To: linux-snps-arc

On Tuesday 24 November 2015 08:02 PM, Joao Pinto wrote:
> This patch adds PCI support to ARC and updates drivers/pci Makefile enabling
> the ARC arch to use the generic PCI setup functions.
>
> Signed-off-by: Joao Pinto <jpinto at synopsys.com>
> ---
>  arch/arc/Kconfig                |  22 +++
>  arch/arc/include/asm/dma.h      |   5 +
>  arch/arc/include/asm/io.h       |   2 +
>  arch/arc/include/asm/mach/pci.h |  97 +++++++++++
>  arch/arc/include/asm/pci.h      |  34 ++++
>  arch/arc/kernel/Makefile        |   1 +
>  arch/arc/kernel/pcibios.c       | 360 ++++++++++++++++++++++++++++++++++++++++
>  arch/arc/mm/ioremap.c           |  29 +++-
>  arch/arc/plat-axs10x/Kconfig    |   1 +
>  drivers/pci/Makefile            |   1 +
>  10 files changed, 551 insertions(+), 1 deletion(-)
>  create mode 100644 arch/arc/include/asm/mach/pci.h
>  create mode 100644 arch/arc/include/asm/pci.h
>  create mode 100644 arch/arc/kernel/pcibios.c
>
> diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
> index 2c2ac3f..5b526a3 100644
> --- a/arch/arc/Kconfig
> +++ b/arch/arc/Kconfig
> @@ -19,6 +19,7 @@ config ARC
>  	select GENERIC_FIND_FIRST_BIT
>  	# for now, we don't need GENERIC_IRQ_PROBE, CONFIG_GENERIC_IRQ_CHIP
>  	select GENERIC_IRQ_SHOW
> +	select GENERIC_PCI_IOMAP
>  	select GENERIC_PENDING_IRQ if SMP
>  	select GENERIC_SMP_IDLE_THREAD
>  	select HAVE_ARCH_KGDB
> @@ -39,6 +40,9 @@ config ARC
>  	select PERF_USE_VMALLOC
>  	select HAVE_DEBUG_STACKOVERFLOW
>  
> +config MIGHT_HAVE_PCI
> +	bool
> +
>  config TRACE_IRQFLAGS_SUPPORT
>  	def_bool y
>  
> @@ -110,6 +114,24 @@ config ISA_ARCV2
>  
>  endchoice
>  
> +menu "Bus Support"
> +
> +config PCI
> +	bool "PCI support" if MIGHT_HAVE_PCI
> +	help
> +	  PCI is the name of a bus system, i.e. the way the CPU talks to the other stuff inside
> +	  your box.Find out if your board/platform have PCI.
> +	  Note: PCIE support for Synopsys Device will be available only when
> +	  HAPS DX is configured with PCIE RC bitmap. If you have PCI, say Y, otherwise N.
> +
> +config PCI_SYSCALL
> +	def_bool PCI
> +
> +source "drivers/pci/Kconfig"
> +source "drivers/pci/pcie/Kconfig"
> +
> +endmenu
> +

Could you please move these towards end of file - preferably between sourcing of
drivers/Kconfig and fs/Kconfig to keep hardware related stuff together.

>  menu "ARC CPU Configuration"
>  
>  choice
> diff --git a/arch/arc/include/asm/dma.h b/arch/arc/include/asm/dma.h
> index ca7c451..37942fa 100644
> --- a/arch/arc/include/asm/dma.h
> +++ b/arch/arc/include/asm/dma.h
> @@ -10,5 +10,10 @@
>  #define ASM_ARC_DMA_H
>  
>  #define MAX_DMA_ADDRESS 0xC0000000
> +#ifdef CONFIG_PCI
> +extern int isa_dma_bridge_buggy;
> +#else
> +#define isa_dma_bridge_buggy    (0)
> +#endif
>  
>  #endif
> diff --git a/arch/arc/include/asm/io.h b/arch/arc/include/asm/io.h
> index 694ece8..d86c2e3 100644
> --- a/arch/arc/include/asm/io.h
> +++ b/arch/arc/include/asm/io.h
> @@ -17,6 +17,8 @@ extern void __iomem *ioremap(unsigned long physaddr, unsigned long size);
>  extern void __iomem *ioremap_prot(phys_addr_t offset, unsigned long size,
>  				  unsigned long flags);
>  extern void iounmap(const void __iomem *addr);
> +extern void __iomem *ioport_map(unsigned long port, unsigned int size);
> +extern int pci_ioremap_io(unsigned int offset, phys_addr_t phys_addr);

ioport_unmap is missing. Anyhow you can define the empty ioport_{map,unmap} as
static inline here (see below)

>  #define ioremap_nocache(phy, sz)	ioremap(phy, sz)
>  #define ioremap_wc(phy, sz)		ioremap(phy, sz)
> diff --git a/arch/arc/include/asm/mach/pci.h b/arch/arc/include/asm/mach/pci.h
> new file mode 100644
> index 0000000..9e75277
> --- /dev/null
> +++ b/arch/arc/include/asm/mach/pci.h
> @@ -0,0 +1,97 @@
> +/*
> + *  arch/arc/include/asm/mach/pci.h
> + *
> + *  Copyright (C) 2004-2014 Synopsys, Inc. (www.synopsys.com)

Perhaps extend this to 2016 (and other copyrights in the patch too if needed)

> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#ifndef __ASM_MACH_PCI_H
> +#define __ASM_MACH_PCI_H
> +
> +#include <linux/ioport.h>
> +
> +struct pci_sys_data;
> +struct pci_ops;
> +struct pci_bus;
> +struct device;
> +
> +struct hw_pci {
> +#ifdef CONFIG_PCI_DOMAINS
> +	int		domain;
> +#endif
> +	struct pci_ops	*ops;
> +	int		nr_controllers;
> +	void		**private_data;
> +	int		(*setup)(int nr, struct pci_sys_data *);
> +	struct pci_bus *(*scan)(int nr, struct pci_sys_data *);
> +	void		(*preinit)(void);
> +	void		(*postinit)(void);
> +	u8		(*swizzle)(struct pci_dev *dev, u8 *pin);
> +	int		(*map_irq)(const struct pci_dev *dev, u8 slot, u8 pin);
> +	resource_size_t (*align_resource)(struct pci_dev *dev,
> +					  const struct resource *res,
> +					  resource_size_t start,
> +					  resource_size_t size,
> +					  resource_size_t align);
> +	void		(*add_bus)(struct pci_bus *bus);
> +	void		(*remove_bus)(struct pci_bus *bus);
> +};
> +
> +/*
> + * Per-controller structure
> + */
> +struct pci_sys_data {
> +#ifdef CONFIG_PCI_DOMAINS
> +	int		domain;
> +#endif
> +	struct list_head node;
> +	int		busnr;		/* primary bus number		    */
> +	u64		mem_offset;	/* bus->cpu memory mapping offset   */
> +	unsigned long	io_offset;	/* bus->cpu IO mapping offset	    */
> +	struct pci_bus	*bus;		/* PCI bus			    */
> +	struct list_head resources;	/* root bus resources (apertures)   */
> +	struct resource io_res;
> +	char		io_res_name[12];
> +					/* Bridge swizzling		    */
> +	u8		(*swizzle)(struct pci_dev *, u8 *);
> +					/* IRQ mapping			    */
> +	int		(*map_irq)(const struct pci_dev *, u8, u8);
> +					/* Resource alignement requirements */
> +	resource_size_t (*align_resource)(struct pci_dev *dev,
> +					  const struct resource *res,
> +					  resource_size_t start,
> +					  resource_size_t size,
> +					  resource_size_t align);
> +	void		(*add_bus)(struct pci_bus *bus);
> +	void		(*remove_bus)(struct pci_bus *bus);
> +	void		*private_data;	/* platform controller private data */
> +};
> +
> +/*
> + * Call this with your hw_pci struct to initialise the PCI system.
> + */
> +void pci_common_init_dev(struct device *, struct hw_pci *);
> +
> +/*
> + * Compatibility wrapper for older platforms that do not care about
> + * passing the parent device.
> + */
> +static inline void pci_common_init(struct hw_pci *hw)
> +{
> +	pci_common_init_dev(NULL, hw);
> +}
> +
> +/*
> + * Setup early fixed I/O mapping.
> + */
> +#if defined(CONFIG_PCI)
> +extern void pci_map_io_early(unsigned long pfn);
> +#else
> +static inline void pci_map_io_early(unsigned long pfn) {}
> +#endif
> +
> +#endif /* __ASM_MACH_PCI_H */
> +
> diff --git a/arch/arc/include/asm/pci.h b/arch/arc/include/asm/pci.h
> new file mode 100644
> index 0000000..085b15f
> --- /dev/null
> +++ b/arch/arc/include/asm/pci.h
> @@ -0,0 +1,34 @@
> +/*
> + * Copyright (C) 2015-2016 Synopsys, Inc. (www.synopsys.com)
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#ifndef _ASM_ARC_PCI_H
> +#define _ASM_ARC_PCI_H
> +
> +#ifdef __KERNEL__
> +#include <asm-generic/pci-dma-compat.h>
> +#include <asm-generic/pci-bridge.h>
> +
> +#include <asm/mach/pci.h> /* for pci_sys_data */
> +
> +extern unsigned long pcibios_min_io;
> +#define PCIBIOS_MIN_IO pcibios_min_io
> +extern unsigned long pcibios_min_mem;
> +#define PCIBIOS_MIN_MEM pcibios_min_mem
> +
> +#define pcibios_assign_all_busses()	1
> +/*
> + * The PCI address space does equal the physical memory address space.
> + * The networking and block device layers use this boolean for bounce
> + * buffer decisions.
> + */
> +#define PCI_DMA_BUS_IS_PHYS     (1)
> +
> +#endif /* __KERNEL__ */
> +
> +#endif /* _ASM_ARC_PCI_H */
> +
> diff --git a/arch/arc/kernel/Makefile b/arch/arc/kernel/Makefile
> index e7f3625..1bc2036 100644
> --- a/arch/arc/kernel/Makefile
> +++ b/arch/arc/kernel/Makefile
> @@ -12,6 +12,7 @@ obj-y	:= arcksyms.o setup.o irq.o time.o reset.o ptrace.o process.o devtree.o
>  obj-y	+= signal.o traps.o sys.o troubleshoot.o stacktrace.o disasm.o clk.o
>  obj-$(CONFIG_ISA_ARCOMPACT)		+= entry-compact.o intc-compact.o
>  obj-$(CONFIG_ISA_ARCV2)			+= entry-arcv2.o intc-arcv2.o
> +obj-$(CONFIG_PCI)  			+= pcibios.o
>  
>  obj-$(CONFIG_MODULES)			+= arcksyms.o module.o
>  obj-$(CONFIG_SMP) 			+= smp.o
> diff --git a/arch/arc/kernel/pcibios.c b/arch/arc/kernel/pcibios.c
> new file mode 100644
> index 0000000..a7bd76a
> --- /dev/null
> +++ b/arch/arc/kernel/pcibios.c
> @@ -0,0 +1,360 @@
> +/*
> + * Copyright (C) 2014-2015 Synopsys, Inc. (www.synopsys.com)
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/pci.h>
> +#include <linux/delay.h>
> +#include <linux/string.h>
> +#include <linux/init.h>
> +#include <linux/sched.h>
> +#include <linux/errno.h>
> +#include <linux/bootmem.h>
> +#include <linux/sizes.h>
> +#include <linux/slab.h>
> +
> +#include <asm/pci.h>
> +#include <asm/mach/pci.h>
> +
> +static int pcibios_init_resources(int busnr, struct pci_sys_data *sys)
> +{
> +	int ret;
> +	struct pci_host_bridge_window *window;
> +
> +	if (list_empty(&sys->resources)) {
> +		pci_add_resource_offset(&sys->resources,
> +			 &iomem_resource, sys->mem_offset);
> +	}
> +
> +	list_for_each_entry(window, &sys->resources, list) {
> +		if (resource_type(window->res) == IORESOURCE_IO)
> +			return 0;
> +	}
> +
> +	sys->io_res.start = (busnr * SZ_64K) ?  : pcibios_min_io;
> +	sys->io_res.end = (busnr + 1) * SZ_64K - 1;
> +	sys->io_res.flags = IORESOURCE_IO;
> +	sys->io_res.name = sys->io_res_name;
> +	sprintf(sys->io_res_name, "PCI%d I/O", busnr);
> +
> +	ret = request_resource(&ioport_resource, &sys->io_res);
> +	if (ret) {
> +		pr_err("PCI: unable to allocate I/O port region (%d)\n", ret);
> +		return ret;
> +	}
> +	pci_add_resource_offset(&sys->resources, &sys->io_res,
> +				sys->io_offset);
> +
> +	return 0;
> +}
> +
> +
> +static void pcibios_init_hw(struct device *parent, struct hw_pci *hw,
> +			    struct list_head *head)
> +{
> +	struct pci_sys_data *sys = NULL;
> +	int ret;
> +	int nr, busnr;
> +
> +	for (nr = busnr = 0; nr < hw->nr_controllers; nr++) {
> +		sys = kzalloc(sizeof(struct pci_sys_data), GFP_KERNEL);
> +		if (!sys)
> +			panic("PCI: unable to allocate sys data!");
> +
> +#ifdef CONFIG_PCI_DOMAINS
> +		sys->domain  = hw->domain;
> +#endif
> +		sys->busnr   = busnr;
> +		sys->swizzle = hw->swizzle;
> +		sys->map_irq = hw->map_irq;
> +		sys->align_resource = hw->align_resource;
> +		sys->add_bus = hw->add_bus;
> +		sys->remove_bus = hw->remove_bus;
> +		INIT_LIST_HEAD(&sys->resources);
> +
> +
> +		if (hw->private_data)
> +			sys->private_data = hw->private_data[nr];
> +
> +		ret = hw->setup(nr, sys);
> +
> +		if (ret > 0) {
> +			ret = pcibios_init_resources(nr, sys);
> +			if (ret)  {
> +				kfree(sys);
> +				break;
> +			}
> +
> +			if (hw->scan)
> +				sys->bus = hw->scan(nr, sys);
> +			else
> +				sys->bus = pci_scan_root_bus(parent, sys->busnr,
> +						hw->ops, sys, &sys->resources);
> +
> +			if (!sys->bus)
> +				panic("PCI: unable to scan bus!");
> +
> +			busnr = sys->bus->busn_res.end + 1;
> +
> +			list_add(&sys->node, head);
> +		} else {
> +			kfree(sys);
> +			if (ret < 0)
> +				break;
> +		}
> +	}
> +}
> +int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
> +{
> +	return 0;
> +}
> +
> +void pcibios_add_bus(struct pci_bus *bus)
> +{
> +	struct pci_sys_data *sys = bus->sysdata;
> +
> +	if (sys->add_bus)
> +		sys->add_bus(bus);
> +}
> +
> +void pcibios_remove_bus(struct pci_bus *bus)
> +{
> +	struct pci_sys_data *sys = bus->sysdata;
> +
> +	if (sys->remove_bus)
> +		sys->remove_bus(bus);
> +}
> +
> +/*
> + * Swizzle the device pin each time we cross a bridge.  If a platform does
> + * not provide a swizzle function, we perform the standard PCI swizzling.
> + *
> + * The default swizzling walks up the bus tree one level at a time, applying
> + * the standard swizzle function at each step, stopping when it finds the PCI
> + * root bus.  This will return the slot number of the bridge device on the
> + * root bus and the interrupt pin on that device which should correspond
> + * with the downstream device interrupt.
> + *
> + * Platforms may override this, in which case the slot and pin returned
> + * depend entirely on the platform code.  However, please note that the
> + * PCI standard swizzle is implemented on plug-in cards and Cardbus based
> + * PCI extenders, so it can not be ignored.
> + */
> +static u8 pcibios_swizzle(struct pci_dev *dev, u8 *pin)
> +{
> +	struct pci_sys_data *sys = dev->sysdata;
> +	int slot, oldpin = *pin;
> +
> +	if (sys->swizzle)
> +		slot = sys->swizzle(dev, pin);
> +	else
> +		slot = pci_common_swizzle(dev, pin);
> +
> +	return slot;
> +}
> +
> +/*
> + * Map a slot/pin to an IRQ.
> + */
> +static int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
> +{
> +	struct pci_sys_data *sys = dev->sysdata;
> +	int irq = -1;
> +
> +	if (sys->map_irq)
> +		irq = sys->map_irq(dev, slot, pin);
> +
> +	return irq;
> +}
> +
> +void pci_common_init_dev(struct device *parent, struct hw_pci *hw)
> +{
> +	struct pci_sys_data *sys;
> +	LIST_HEAD(head);
> +
> +	pci_add_flags(PCI_REASSIGN_ALL_RSRC);
> +	if (hw->preinit)
> +		hw->preinit();
> +	pcibios_init_hw(parent, hw, &head);
> +	if (hw->postinit)
> +		hw->postinit();
> +
> +	pci_fixup_irqs(pcibios_swizzle, pcibios_map_irq);
> +
> +	list_for_each_entry(sys, &head, node) {
> +		struct pci_bus *bus = sys->bus;
> +
> +		if (!pci_has_flag(PCI_PROBE_ONLY)) {
> +			/*
> +			 * Size the bridge windows.
> +			 */
> +			pci_bus_size_bridges(bus);
> +
> +			/*
> +			 * Assign resources.
> +			 */
> +			pci_bus_assign_resources(bus);
> +		}
> +
> +		/*
> +		 * Tell drivers about devices found.
> +		 */
> +		pci_bus_add_devices(bus);
> +	}
> +}
> +
> +/*
> + * We don't have to worry about legacy ISA devices, so nothing to do here
> + */
> +resource_size_t pcibios_align_resource(void *data, const struct resource *res,
> +				resource_size_t size, resource_size_t align)
> +{
> +	return res->start;
> +}
> +
> +/**
> + * pcibios_enable_device - Enable I/O and memory.
> + * @dev: PCI device to be enabled
> + */
> +int pcibios_enable_device(struct pci_dev *dev, int mask)
> +{
> +	u16 cmd, old_cmd;
> +	int idx;
> +	struct resource *r;
> +
> +	pci_read_config_word(dev, PCI_COMMAND, &cmd);
> +	old_cmd = cmd;
> +	for (idx = 0; idx < 6; idx++) {
> +		/* Only set up the requested stuff */
> +		if (!(mask & (1 << idx)))
> +			continue;
> +
> +		r = dev->resource + idx;
> +		if (!r->start && r->end) {
> +			pr_err("PCI: Device %s not available because"/
> +			       " of resource collisions\n", pci_name(dev));

Better not to break strings - even if they sometime exceed line sz limit of 80.
You could anyways reduce the string content herer.

> +			return -EINVAL;
> +		}
> +		if (r->flags & IORESOURCE_IO)
> +			cmd |= PCI_COMMAND_IO;
> +		if (r->flags & IORESOURCE_MEM)
> +			cmd |= PCI_COMMAND_MEMORY;
> +	}
> +
> +	/*
> +	 * Bridges (eg, cardbus bridges) need to be fully enabled
> +	 */
> +	if ((dev->class >> 16) == PCI_BASE_CLASS_BRIDGE)
> +		cmd |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
> +
> +	if (cmd != old_cmd) {
> +		pr_info("PCI: enabling device %s (%04x -> %04x)\n",
> +		       pci_name(dev), old_cmd, cmd);
> +		pci_write_config_word(dev, PCI_COMMAND, cmd);
> +	}
> +	return 0;
> +}
> +
> +/*
> + * If the bus contains any of these devices, then we must not turn on
> + * parity checking of any kind.  Currently this is CyberPro 20x0 only.
> + */
> +static inline int pdev_bad_for_parity(struct pci_dev *dev)
> +{
> +	return ((dev->vendor == PCI_VENDOR_ID_INTERG &&
> +		 (dev->device == PCI_DEVICE_ID_INTERG_2000 ||
> +		  dev->device == PCI_DEVICE_ID_INTERG_2010)) ||
> +		(dev->vendor == PCI_VENDOR_ID_ITE &&
> +		 dev->device == PCI_DEVICE_ID_ITE_8152));
> +
> +}
> +
> +/*
> + * pcibios_fixup_bus - Called after each bus is probed,
> + * but before its children are examined.
> + */
> +void pcibios_fixup_bus(struct pci_bus *bus)
> +{
> +	struct pci_dev *dev;
> +	u16 features = PCI_COMMAND_SERR | PCI_COMMAND_PARITY
> +			| PCI_COMMAND_FAST_BACK;
> +
> +	/*
> +	 * Walk the devices on this bus, working out what we can
> +	 * and can't support.
> +	 */
> +	list_for_each_entry(dev, &bus->devices, bus_list) {
> +		u16 status;
> +
> +		pci_read_config_word(dev, PCI_STATUS, &status);
> +
> +		/*
> +		 * If any device on this bus does not support fast back
> +		 * to back transfers, then the bus as a whole is not able
> +		 * to support them.  Having fast back to back transfers
> +		 * on saves us one PCI cycle per transaction.
> +		 */
> +		if (!(status & PCI_STATUS_FAST_BACK))
> +			features &= ~PCI_COMMAND_FAST_BACK;
> +
> +		if (pdev_bad_for_parity(dev))
> +			features &= ~(PCI_COMMAND_SERR | PCI_COMMAND_PARITY);
> +
> +		switch (dev->class >> 8) {
> +		case PCI_CLASS_BRIDGE_PCI:
> +			pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &status);
> +			status |= PCI_BRIDGE_CTL_PARITY
> +					|PCI_BRIDGE_CTL_MASTER_ABORT;
> +			status &= ~(PCI_BRIDGE_CTL_BUS_RESET
> +					|PCI_BRIDGE_CTL_FAST_BACK);
> +			pci_write_config_word(dev, PCI_BRIDGE_CONTROL, status);
> +			break;
> +
> +		case PCI_CLASS_BRIDGE_CARDBUS:
> +			pci_read_config_word(dev, PCI_CB_BRIDGE_CONTROL,
> +						&status);
> +			status |= PCI_CB_BRIDGE_CTL_PARITY
> +					|PCI_CB_BRIDGE_CTL_MASTER_ABORT;
> +			pci_write_config_word(dev, PCI_CB_BRIDGE_CONTROL,
> +						status);
> +			break;
> +		}
> +	}
> +
> +	/*
> +	 * Now walk the devices again, this time setting them up.
> +	 */
> +	list_for_each_entry(dev, &bus->devices, bus_list) {
> +		u16 cmd;
> +
> +		pci_read_config_word(dev, PCI_COMMAND, &cmd);
> +		cmd |= features;
> +		pci_write_config_word(dev, PCI_COMMAND, cmd);
> +
> +		pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE,
> +				      L1_CACHE_BYTES >> 2);
> +	}
> +
> +	/*
> +	 * Propagate the flags to the PCI bridge.
> +	 */
> +	if (bus->self && bus->self->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
> +		if (features & PCI_COMMAND_FAST_BACK)
> +			bus->bridge_ctl |= PCI_BRIDGE_CTL_FAST_BACK;
> +		if (features & PCI_COMMAND_PARITY)
> +			bus->bridge_ctl |= PCI_BRIDGE_CTL_PARITY;
> +	}
> +
> +	/*
> +	 * Report what we did for this bus
> +	 */
> +	pr_info("PCI: bus%d: Fast back to back transfers %sabled\n",
> +		bus->number, (features & PCI_COMMAND_FAST_BACK) ? "en" : "dis");
> +}
> +EXPORT_SYMBOL(pcibios_fixup_bus);
> +
> diff --git a/arch/arc/mm/ioremap.c b/arch/arc/mm/ioremap.c
> index 739e65f..583c9fe 100644
> --- a/arch/arc/mm/ioremap.c
> +++ b/arch/arc/mm/ioremap.c
> @@ -13,6 +13,26 @@
>  #include <linux/mm.h>
>  #include <linux/slab.h>
>  #include <linux/cache.h>
> +#include <linux/sizes.h>

You really need this #include.

> +
> +#ifdef CONFIG_PCI
> +unsigned long pcibios_min_io = 0x100;
> +EXPORT_SYMBOL(pcibios_min_io);
> +
> +unsigned long pcibios_min_mem = 0x100000;
> +EXPORT_SYMBOL(pcibios_min_mem);
> +#endif

Can these be moved into one the newer pci files you've introduced ?

> +
> +inline void __iomem *ioport_map(unsigned long port, unsigned int nr)
> +{
> +	return port;
> +}
> +EXPORT_SYMBOL(ioport_map);
> +
> +inline void ioport_unmap(void __iomem *addr)
> +{
> +}
> +EXPORT_SYMBOL(ioport_unmap);

So you are inlining and EXPORT the function which doesn't make sense. EXPORTs are
generally _GPL.
Anyhow since these are empty, please move them into  io.h

>  
>  void __iomem *ioremap(unsigned long paddr, unsigned long size)
>  {
> @@ -80,7 +100,6 @@ void __iomem *ioremap_prot(phys_addr_t paddr, unsigned long size,
>  }
>  EXPORT_SYMBOL(ioremap_prot);
>  
> -
>  void iounmap(const void __iomem *addr)
>  {
>  	if (addr >= (void __force __iomem *)ARC_UNCACHED_ADDR_SPACE)
> @@ -89,3 +108,11 @@ void iounmap(const void __iomem *addr)
>  	vfree((void *)(PAGE_MASK & (unsigned long __force)addr));
>  }
>  EXPORT_SYMBOL(iounmap);
> +
> +#ifdef CONFIG_PCI
> +int pci_ioremap_io(unsigned int offset, phys_addr_t phys_addr)
> +{
> +	return ioremap_nocache(phys_addr + offset,  SZ_64K);
> +}
> +EXPORT_SYMBOL_GPL(pci_ioremap_io);
> +#endif
> diff --git a/arch/arc/plat-axs10x/Kconfig b/arch/arc/plat-axs10x/Kconfig
> index d475f9d..33b5db6 100644
> --- a/arch/arc/plat-axs10x/Kconfig
> +++ b/arch/arc/plat-axs10x/Kconfig
> @@ -8,6 +8,7 @@
>  
>  menuconfig ARC_PLAT_AXS10X
>  	bool "Synopsys ARC AXS10x Software Development Platforms"
> +	select MIGHT_HAVE_PCI

We tend to keep select lists sorted.

>  	select DW_APB_ICTL
>  	select GPIO_DWAPB
>  	select OF_GPIO
> diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
> index be3f631..2154092 100644
> --- a/drivers/pci/Makefile
> +++ b/drivers/pci/Makefile
> @@ -32,6 +32,7 @@ obj-$(CONFIG_PCI_IOV) += iov.o
>  # Some architectures use the generic PCI setup functions
>  #
>  obj-$(CONFIG_ALPHA) += setup-irq.o
> +obj-$(CONFIG_ARC) += setup-irq.o
>  obj-$(CONFIG_ARM) += setup-irq.o
>  obj-$(CONFIG_ARM64) += setup-irq.o
>  obj-$(CONFIG_UNICORE32) += setup-irq.o

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH 2/2] PCI support added to ARC
  2015-11-24 14:32 [PATCH 0/2] adding PCI support to AXS10x Joao Pinto
@ 2015-11-24 14:32 ` Joao Pinto
  2015-11-25  5:25     ` Vineet Gupta
  0 siblings, 1 reply; 15+ messages in thread
From: Joao Pinto @ 2015-11-24 14:32 UTC (permalink / raw)
  To: linux-pci, linux-kernel
  Cc: bhelgaas, CARLOS.PALMINHA, Vineet.Gupta1, Alexey.Brodkin, Joao Pinto

This patch adds PCI support to ARC and updates drivers/pci Makefile enabling
the ARC arch to use the generic PCI setup functions.

Signed-off-by: Joao Pinto <jpinto@synopsys.com>
---
 arch/arc/Kconfig                |  22 +++
 arch/arc/include/asm/dma.h      |   5 +
 arch/arc/include/asm/io.h       |   2 +
 arch/arc/include/asm/mach/pci.h |  97 +++++++++++
 arch/arc/include/asm/pci.h      |  34 ++++
 arch/arc/kernel/Makefile        |   1 +
 arch/arc/kernel/pcibios.c       | 360 ++++++++++++++++++++++++++++++++++++++++
 arch/arc/mm/ioremap.c           |  29 +++-
 arch/arc/plat-axs10x/Kconfig    |   1 +
 drivers/pci/Makefile            |   1 +
 10 files changed, 551 insertions(+), 1 deletion(-)
 create mode 100644 arch/arc/include/asm/mach/pci.h
 create mode 100644 arch/arc/include/asm/pci.h
 create mode 100644 arch/arc/kernel/pcibios.c

diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
index 2c2ac3f..5b526a3 100644
--- a/arch/arc/Kconfig
+++ b/arch/arc/Kconfig
@@ -19,6 +19,7 @@ config ARC
 	select GENERIC_FIND_FIRST_BIT
 	# for now, we don't need GENERIC_IRQ_PROBE, CONFIG_GENERIC_IRQ_CHIP
 	select GENERIC_IRQ_SHOW
+	select GENERIC_PCI_IOMAP
 	select GENERIC_PENDING_IRQ if SMP
 	select GENERIC_SMP_IDLE_THREAD
 	select HAVE_ARCH_KGDB
@@ -39,6 +40,9 @@ config ARC
 	select PERF_USE_VMALLOC
 	select HAVE_DEBUG_STACKOVERFLOW
 
+config MIGHT_HAVE_PCI
+	bool
+
 config TRACE_IRQFLAGS_SUPPORT
 	def_bool y
 
@@ -110,6 +114,24 @@ config ISA_ARCV2
 
 endchoice
 
+menu "Bus Support"
+
+config PCI
+	bool "PCI support" if MIGHT_HAVE_PCI
+	help
+	  PCI is the name of a bus system, i.e. the way the CPU talks to the other stuff inside
+	  your box.Find out if your board/platform have PCI.
+	  Note: PCIE support for Synopsys Device will be available only when
+	  HAPS DX is configured with PCIE RC bitmap. If you have PCI, say Y, otherwise N.
+
+config PCI_SYSCALL
+	def_bool PCI
+
+source "drivers/pci/Kconfig"
+source "drivers/pci/pcie/Kconfig"
+
+endmenu
+
 menu "ARC CPU Configuration"
 
 choice
diff --git a/arch/arc/include/asm/dma.h b/arch/arc/include/asm/dma.h
index ca7c451..37942fa 100644
--- a/arch/arc/include/asm/dma.h
+++ b/arch/arc/include/asm/dma.h
@@ -10,5 +10,10 @@
 #define ASM_ARC_DMA_H
 
 #define MAX_DMA_ADDRESS 0xC0000000
+#ifdef CONFIG_PCI
+extern int isa_dma_bridge_buggy;
+#else
+#define isa_dma_bridge_buggy    (0)
+#endif
 
 #endif
diff --git a/arch/arc/include/asm/io.h b/arch/arc/include/asm/io.h
index 694ece8..d86c2e3 100644
--- a/arch/arc/include/asm/io.h
+++ b/arch/arc/include/asm/io.h
@@ -17,6 +17,8 @@ extern void __iomem *ioremap(unsigned long physaddr, unsigned long size);
 extern void __iomem *ioremap_prot(phys_addr_t offset, unsigned long size,
 				  unsigned long flags);
 extern void iounmap(const void __iomem *addr);
+extern void __iomem *ioport_map(unsigned long port, unsigned int size);
+extern int pci_ioremap_io(unsigned int offset, phys_addr_t phys_addr);
 
 #define ioremap_nocache(phy, sz)	ioremap(phy, sz)
 #define ioremap_wc(phy, sz)		ioremap(phy, sz)
diff --git a/arch/arc/include/asm/mach/pci.h b/arch/arc/include/asm/mach/pci.h
new file mode 100644
index 0000000..9e75277
--- /dev/null
+++ b/arch/arc/include/asm/mach/pci.h
@@ -0,0 +1,97 @@
+/*
+ *  arch/arc/include/asm/mach/pci.h
+ *
+ *  Copyright (C) 2004-2014 Synopsys, Inc. (www.synopsys.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __ASM_MACH_PCI_H
+#define __ASM_MACH_PCI_H
+
+#include <linux/ioport.h>
+
+struct pci_sys_data;
+struct pci_ops;
+struct pci_bus;
+struct device;
+
+struct hw_pci {
+#ifdef CONFIG_PCI_DOMAINS
+	int		domain;
+#endif
+	struct pci_ops	*ops;
+	int		nr_controllers;
+	void		**private_data;
+	int		(*setup)(int nr, struct pci_sys_data *);
+	struct pci_bus *(*scan)(int nr, struct pci_sys_data *);
+	void		(*preinit)(void);
+	void		(*postinit)(void);
+	u8		(*swizzle)(struct pci_dev *dev, u8 *pin);
+	int		(*map_irq)(const struct pci_dev *dev, u8 slot, u8 pin);
+	resource_size_t (*align_resource)(struct pci_dev *dev,
+					  const struct resource *res,
+					  resource_size_t start,
+					  resource_size_t size,
+					  resource_size_t align);
+	void		(*add_bus)(struct pci_bus *bus);
+	void		(*remove_bus)(struct pci_bus *bus);
+};
+
+/*
+ * Per-controller structure
+ */
+struct pci_sys_data {
+#ifdef CONFIG_PCI_DOMAINS
+	int		domain;
+#endif
+	struct list_head node;
+	int		busnr;		/* primary bus number		    */
+	u64		mem_offset;	/* bus->cpu memory mapping offset   */
+	unsigned long	io_offset;	/* bus->cpu IO mapping offset	    */
+	struct pci_bus	*bus;		/* PCI bus			    */
+	struct list_head resources;	/* root bus resources (apertures)   */
+	struct resource io_res;
+	char		io_res_name[12];
+					/* Bridge swizzling		    */
+	u8		(*swizzle)(struct pci_dev *, u8 *);
+					/* IRQ mapping			    */
+	int		(*map_irq)(const struct pci_dev *, u8, u8);
+					/* Resource alignement requirements */
+	resource_size_t (*align_resource)(struct pci_dev *dev,
+					  const struct resource *res,
+					  resource_size_t start,
+					  resource_size_t size,
+					  resource_size_t align);
+	void		(*add_bus)(struct pci_bus *bus);
+	void		(*remove_bus)(struct pci_bus *bus);
+	void		*private_data;	/* platform controller private data */
+};
+
+/*
+ * Call this with your hw_pci struct to initialise the PCI system.
+ */
+void pci_common_init_dev(struct device *, struct hw_pci *);
+
+/*
+ * Compatibility wrapper for older platforms that do not care about
+ * passing the parent device.
+ */
+static inline void pci_common_init(struct hw_pci *hw)
+{
+	pci_common_init_dev(NULL, hw);
+}
+
+/*
+ * Setup early fixed I/O mapping.
+ */
+#if defined(CONFIG_PCI)
+extern void pci_map_io_early(unsigned long pfn);
+#else
+static inline void pci_map_io_early(unsigned long pfn) {}
+#endif
+
+#endif /* __ASM_MACH_PCI_H */
+
diff --git a/arch/arc/include/asm/pci.h b/arch/arc/include/asm/pci.h
new file mode 100644
index 0000000..085b15f
--- /dev/null
+++ b/arch/arc/include/asm/pci.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2015-2016 Synopsys, Inc. (www.synopsys.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _ASM_ARC_PCI_H
+#define _ASM_ARC_PCI_H
+
+#ifdef __KERNEL__
+#include <asm-generic/pci-dma-compat.h>
+#include <asm-generic/pci-bridge.h>
+
+#include <asm/mach/pci.h> /* for pci_sys_data */
+
+extern unsigned long pcibios_min_io;
+#define PCIBIOS_MIN_IO pcibios_min_io
+extern unsigned long pcibios_min_mem;
+#define PCIBIOS_MIN_MEM pcibios_min_mem
+
+#define pcibios_assign_all_busses()	1
+/*
+ * The PCI address space does equal the physical memory address space.
+ * The networking and block device layers use this boolean for bounce
+ * buffer decisions.
+ */
+#define PCI_DMA_BUS_IS_PHYS     (1)
+
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_ARC_PCI_H */
+
diff --git a/arch/arc/kernel/Makefile b/arch/arc/kernel/Makefile
index e7f3625..1bc2036 100644
--- a/arch/arc/kernel/Makefile
+++ b/arch/arc/kernel/Makefile
@@ -12,6 +12,7 @@ obj-y	:= arcksyms.o setup.o irq.o time.o reset.o ptrace.o process.o devtree.o
 obj-y	+= signal.o traps.o sys.o troubleshoot.o stacktrace.o disasm.o clk.o
 obj-$(CONFIG_ISA_ARCOMPACT)		+= entry-compact.o intc-compact.o
 obj-$(CONFIG_ISA_ARCV2)			+= entry-arcv2.o intc-arcv2.o
+obj-$(CONFIG_PCI)  			+= pcibios.o
 
 obj-$(CONFIG_MODULES)			+= arcksyms.o module.o
 obj-$(CONFIG_SMP) 			+= smp.o
diff --git a/arch/arc/kernel/pcibios.c b/arch/arc/kernel/pcibios.c
new file mode 100644
index 0000000..a7bd76a
--- /dev/null
+++ b/arch/arc/kernel/pcibios.c
@@ -0,0 +1,360 @@
+/*
+ * Copyright (C) 2014-2015 Synopsys, Inc. (www.synopsys.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/bootmem.h>
+#include <linux/sizes.h>
+#include <linux/slab.h>
+
+#include <asm/pci.h>
+#include <asm/mach/pci.h>
+
+static int pcibios_init_resources(int busnr, struct pci_sys_data *sys)
+{
+	int ret;
+	struct pci_host_bridge_window *window;
+
+	if (list_empty(&sys->resources)) {
+		pci_add_resource_offset(&sys->resources,
+			 &iomem_resource, sys->mem_offset);
+	}
+
+	list_for_each_entry(window, &sys->resources, list) {
+		if (resource_type(window->res) == IORESOURCE_IO)
+			return 0;
+	}
+
+	sys->io_res.start = (busnr * SZ_64K) ?  : pcibios_min_io;
+	sys->io_res.end = (busnr + 1) * SZ_64K - 1;
+	sys->io_res.flags = IORESOURCE_IO;
+	sys->io_res.name = sys->io_res_name;
+	sprintf(sys->io_res_name, "PCI%d I/O", busnr);
+
+	ret = request_resource(&ioport_resource, &sys->io_res);
+	if (ret) {
+		pr_err("PCI: unable to allocate I/O port region (%d)\n", ret);
+		return ret;
+	}
+	pci_add_resource_offset(&sys->resources, &sys->io_res,
+				sys->io_offset);
+
+	return 0;
+}
+
+
+static void pcibios_init_hw(struct device *parent, struct hw_pci *hw,
+			    struct list_head *head)
+{
+	struct pci_sys_data *sys = NULL;
+	int ret;
+	int nr, busnr;
+
+	for (nr = busnr = 0; nr < hw->nr_controllers; nr++) {
+		sys = kzalloc(sizeof(struct pci_sys_data), GFP_KERNEL);
+		if (!sys)
+			panic("PCI: unable to allocate sys data!");
+
+#ifdef CONFIG_PCI_DOMAINS
+		sys->domain  = hw->domain;
+#endif
+		sys->busnr   = busnr;
+		sys->swizzle = hw->swizzle;
+		sys->map_irq = hw->map_irq;
+		sys->align_resource = hw->align_resource;
+		sys->add_bus = hw->add_bus;
+		sys->remove_bus = hw->remove_bus;
+		INIT_LIST_HEAD(&sys->resources);
+
+
+		if (hw->private_data)
+			sys->private_data = hw->private_data[nr];
+
+		ret = hw->setup(nr, sys);
+
+		if (ret > 0) {
+			ret = pcibios_init_resources(nr, sys);
+			if (ret)  {
+				kfree(sys);
+				break;
+			}
+
+			if (hw->scan)
+				sys->bus = hw->scan(nr, sys);
+			else
+				sys->bus = pci_scan_root_bus(parent, sys->busnr,
+						hw->ops, sys, &sys->resources);
+
+			if (!sys->bus)
+				panic("PCI: unable to scan bus!");
+
+			busnr = sys->bus->busn_res.end + 1;
+
+			list_add(&sys->node, head);
+		} else {
+			kfree(sys);
+			if (ret < 0)
+				break;
+		}
+	}
+}
+int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
+{
+	return 0;
+}
+
+void pcibios_add_bus(struct pci_bus *bus)
+{
+	struct pci_sys_data *sys = bus->sysdata;
+
+	if (sys->add_bus)
+		sys->add_bus(bus);
+}
+
+void pcibios_remove_bus(struct pci_bus *bus)
+{
+	struct pci_sys_data *sys = bus->sysdata;
+
+	if (sys->remove_bus)
+		sys->remove_bus(bus);
+}
+
+/*
+ * Swizzle the device pin each time we cross a bridge.  If a platform does
+ * not provide a swizzle function, we perform the standard PCI swizzling.
+ *
+ * The default swizzling walks up the bus tree one level at a time, applying
+ * the standard swizzle function at each step, stopping when it finds the PCI
+ * root bus.  This will return the slot number of the bridge device on the
+ * root bus and the interrupt pin on that device which should correspond
+ * with the downstream device interrupt.
+ *
+ * Platforms may override this, in which case the slot and pin returned
+ * depend entirely on the platform code.  However, please note that the
+ * PCI standard swizzle is implemented on plug-in cards and Cardbus based
+ * PCI extenders, so it can not be ignored.
+ */
+static u8 pcibios_swizzle(struct pci_dev *dev, u8 *pin)
+{
+	struct pci_sys_data *sys = dev->sysdata;
+	int slot, oldpin = *pin;
+
+	if (sys->swizzle)
+		slot = sys->swizzle(dev, pin);
+	else
+		slot = pci_common_swizzle(dev, pin);
+
+	return slot;
+}
+
+/*
+ * Map a slot/pin to an IRQ.
+ */
+static int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+	struct pci_sys_data *sys = dev->sysdata;
+	int irq = -1;
+
+	if (sys->map_irq)
+		irq = sys->map_irq(dev, slot, pin);
+
+	return irq;
+}
+
+void pci_common_init_dev(struct device *parent, struct hw_pci *hw)
+{
+	struct pci_sys_data *sys;
+	LIST_HEAD(head);
+
+	pci_add_flags(PCI_REASSIGN_ALL_RSRC);
+	if (hw->preinit)
+		hw->preinit();
+	pcibios_init_hw(parent, hw, &head);
+	if (hw->postinit)
+		hw->postinit();
+
+	pci_fixup_irqs(pcibios_swizzle, pcibios_map_irq);
+
+	list_for_each_entry(sys, &head, node) {
+		struct pci_bus *bus = sys->bus;
+
+		if (!pci_has_flag(PCI_PROBE_ONLY)) {
+			/*
+			 * Size the bridge windows.
+			 */
+			pci_bus_size_bridges(bus);
+
+			/*
+			 * Assign resources.
+			 */
+			pci_bus_assign_resources(bus);
+		}
+
+		/*
+		 * Tell drivers about devices found.
+		 */
+		pci_bus_add_devices(bus);
+	}
+}
+
+/*
+ * We don't have to worry about legacy ISA devices, so nothing to do here
+ */
+resource_size_t pcibios_align_resource(void *data, const struct resource *res,
+				resource_size_t size, resource_size_t align)
+{
+	return res->start;
+}
+
+/**
+ * pcibios_enable_device - Enable I/O and memory.
+ * @dev: PCI device to be enabled
+ */
+int pcibios_enable_device(struct pci_dev *dev, int mask)
+{
+	u16 cmd, old_cmd;
+	int idx;
+	struct resource *r;
+
+	pci_read_config_word(dev, PCI_COMMAND, &cmd);
+	old_cmd = cmd;
+	for (idx = 0; idx < 6; idx++) {
+		/* Only set up the requested stuff */
+		if (!(mask & (1 << idx)))
+			continue;
+
+		r = dev->resource + idx;
+		if (!r->start && r->end) {
+			pr_err("PCI: Device %s not available because"/
+			       " of resource collisions\n", pci_name(dev));
+			return -EINVAL;
+		}
+		if (r->flags & IORESOURCE_IO)
+			cmd |= PCI_COMMAND_IO;
+		if (r->flags & IORESOURCE_MEM)
+			cmd |= PCI_COMMAND_MEMORY;
+	}
+
+	/*
+	 * Bridges (eg, cardbus bridges) need to be fully enabled
+	 */
+	if ((dev->class >> 16) == PCI_BASE_CLASS_BRIDGE)
+		cmd |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
+
+	if (cmd != old_cmd) {
+		pr_info("PCI: enabling device %s (%04x -> %04x)\n",
+		       pci_name(dev), old_cmd, cmd);
+		pci_write_config_word(dev, PCI_COMMAND, cmd);
+	}
+	return 0;
+}
+
+/*
+ * If the bus contains any of these devices, then we must not turn on
+ * parity checking of any kind.  Currently this is CyberPro 20x0 only.
+ */
+static inline int pdev_bad_for_parity(struct pci_dev *dev)
+{
+	return ((dev->vendor == PCI_VENDOR_ID_INTERG &&
+		 (dev->device == PCI_DEVICE_ID_INTERG_2000 ||
+		  dev->device == PCI_DEVICE_ID_INTERG_2010)) ||
+		(dev->vendor == PCI_VENDOR_ID_ITE &&
+		 dev->device == PCI_DEVICE_ID_ITE_8152));
+
+}
+
+/*
+ * pcibios_fixup_bus - Called after each bus is probed,
+ * but before its children are examined.
+ */
+void pcibios_fixup_bus(struct pci_bus *bus)
+{
+	struct pci_dev *dev;
+	u16 features = PCI_COMMAND_SERR | PCI_COMMAND_PARITY
+			| PCI_COMMAND_FAST_BACK;
+
+	/*
+	 * Walk the devices on this bus, working out what we can
+	 * and can't support.
+	 */
+	list_for_each_entry(dev, &bus->devices, bus_list) {
+		u16 status;
+
+		pci_read_config_word(dev, PCI_STATUS, &status);
+
+		/*
+		 * If any device on this bus does not support fast back
+		 * to back transfers, then the bus as a whole is not able
+		 * to support them.  Having fast back to back transfers
+		 * on saves us one PCI cycle per transaction.
+		 */
+		if (!(status & PCI_STATUS_FAST_BACK))
+			features &= ~PCI_COMMAND_FAST_BACK;
+
+		if (pdev_bad_for_parity(dev))
+			features &= ~(PCI_COMMAND_SERR | PCI_COMMAND_PARITY);
+
+		switch (dev->class >> 8) {
+		case PCI_CLASS_BRIDGE_PCI:
+			pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &status);
+			status |= PCI_BRIDGE_CTL_PARITY
+					|PCI_BRIDGE_CTL_MASTER_ABORT;
+			status &= ~(PCI_BRIDGE_CTL_BUS_RESET
+					|PCI_BRIDGE_CTL_FAST_BACK);
+			pci_write_config_word(dev, PCI_BRIDGE_CONTROL, status);
+			break;
+
+		case PCI_CLASS_BRIDGE_CARDBUS:
+			pci_read_config_word(dev, PCI_CB_BRIDGE_CONTROL,
+						&status);
+			status |= PCI_CB_BRIDGE_CTL_PARITY
+					|PCI_CB_BRIDGE_CTL_MASTER_ABORT;
+			pci_write_config_word(dev, PCI_CB_BRIDGE_CONTROL,
+						status);
+			break;
+		}
+	}
+
+	/*
+	 * Now walk the devices again, this time setting them up.
+	 */
+	list_for_each_entry(dev, &bus->devices, bus_list) {
+		u16 cmd;
+
+		pci_read_config_word(dev, PCI_COMMAND, &cmd);
+		cmd |= features;
+		pci_write_config_word(dev, PCI_COMMAND, cmd);
+
+		pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE,
+				      L1_CACHE_BYTES >> 2);
+	}
+
+	/*
+	 * Propagate the flags to the PCI bridge.
+	 */
+	if (bus->self && bus->self->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
+		if (features & PCI_COMMAND_FAST_BACK)
+			bus->bridge_ctl |= PCI_BRIDGE_CTL_FAST_BACK;
+		if (features & PCI_COMMAND_PARITY)
+			bus->bridge_ctl |= PCI_BRIDGE_CTL_PARITY;
+	}
+
+	/*
+	 * Report what we did for this bus
+	 */
+	pr_info("PCI: bus%d: Fast back to back transfers %sabled\n",
+		bus->number, (features & PCI_COMMAND_FAST_BACK) ? "en" : "dis");
+}
+EXPORT_SYMBOL(pcibios_fixup_bus);
+
diff --git a/arch/arc/mm/ioremap.c b/arch/arc/mm/ioremap.c
index 739e65f..583c9fe 100644
--- a/arch/arc/mm/ioremap.c
+++ b/arch/arc/mm/ioremap.c
@@ -13,6 +13,26 @@
 #include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/cache.h>
+#include <linux/sizes.h>
+
+#ifdef CONFIG_PCI
+unsigned long pcibios_min_io = 0x100;
+EXPORT_SYMBOL(pcibios_min_io);
+
+unsigned long pcibios_min_mem = 0x100000;
+EXPORT_SYMBOL(pcibios_min_mem);
+#endif
+
+inline void __iomem *ioport_map(unsigned long port, unsigned int nr)
+{
+	return port;
+}
+EXPORT_SYMBOL(ioport_map);
+
+inline void ioport_unmap(void __iomem *addr)
+{
+}
+EXPORT_SYMBOL(ioport_unmap);
 
 void __iomem *ioremap(unsigned long paddr, unsigned long size)
 {
@@ -80,7 +100,6 @@ void __iomem *ioremap_prot(phys_addr_t paddr, unsigned long size,
 }
 EXPORT_SYMBOL(ioremap_prot);
 
-
 void iounmap(const void __iomem *addr)
 {
 	if (addr >= (void __force __iomem *)ARC_UNCACHED_ADDR_SPACE)
@@ -89,3 +108,11 @@ void iounmap(const void __iomem *addr)
 	vfree((void *)(PAGE_MASK & (unsigned long __force)addr));
 }
 EXPORT_SYMBOL(iounmap);
+
+#ifdef CONFIG_PCI
+int pci_ioremap_io(unsigned int offset, phys_addr_t phys_addr)
+{
+	return ioremap_nocache(phys_addr + offset,  SZ_64K);
+}
+EXPORT_SYMBOL_GPL(pci_ioremap_io);
+#endif
diff --git a/arch/arc/plat-axs10x/Kconfig b/arch/arc/plat-axs10x/Kconfig
index d475f9d..33b5db6 100644
--- a/arch/arc/plat-axs10x/Kconfig
+++ b/arch/arc/plat-axs10x/Kconfig
@@ -8,6 +8,7 @@
 
 menuconfig ARC_PLAT_AXS10X
 	bool "Synopsys ARC AXS10x Software Development Platforms"
+	select MIGHT_HAVE_PCI
 	select DW_APB_ICTL
 	select GPIO_DWAPB
 	select OF_GPIO
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index be3f631..2154092 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -32,6 +32,7 @@ obj-$(CONFIG_PCI_IOV) += iov.o
 # Some architectures use the generic PCI setup functions
 #
 obj-$(CONFIG_ALPHA) += setup-irq.o
+obj-$(CONFIG_ARC) += setup-irq.o
 obj-$(CONFIG_ARM) += setup-irq.o
 obj-$(CONFIG_ARM64) += setup-irq.o
 obj-$(CONFIG_UNICORE32) += setup-irq.o
-- 
1.8.1.5


^ permalink raw reply related	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2015-11-30  6:21 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-11-24 11:44 [PATCH 0/2] adding PCI support to AXS10x Joao Pinto
2015-11-24 11:44 ` [PATCH 1/2] add new platform driver for PCI RC Joao Pinto
2015-11-24 12:15   ` kbuild test robot
2015-11-24 11:44 ` [PATCH 2/2] PCI support added to ARC Joao Pinto
2015-11-24 14:32 [PATCH 0/2] adding PCI support to AXS10x Joao Pinto
2015-11-24 14:32 ` [PATCH 2/2] PCI support added to ARC Joao Pinto
2015-11-25  5:25   ` Vineet Gupta
2015-11-25  5:25     ` Vineet Gupta
2015-11-25 16:46     ` Bjorn Helgaas
2015-11-25 16:46       ` Bjorn Helgaas
2015-11-26 15:41       ` Joao Pinto
2015-11-26 15:41         ` Joao Pinto
2015-11-30  1:00     ` Bjorn Helgaas
2015-11-30  1:00       ` Bjorn Helgaas
2015-11-30  6:21       ` Vineet Gupta
2015-11-30  6:21         ` Vineet Gupta

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.