All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/15] SPEAr13xx PCIe patches
@ 2012-10-29  7:01 ` Pratyush Anand
  0 siblings, 0 replies; 56+ messages in thread
From: Pratyush Anand @ 2012-10-29  7:01 UTC (permalink / raw)
  To: arnd, shiraz.hashim, viresh.linux
  Cc: spear-devel, linux-pci, devicetree-discuss, olof, Pratyush Anand

-- First two patches are common for all platforms on ARM architecture.
-- Remaining patches belongs to SPEAr13xx architecture.
-- SPEAr13xx supports both RC and EP mode of PCIe interface. This patchset
	supports only RC mode.


Pratyush Anand (15):
  arm: source drivers/pci/pcie/kconfig
  arm: Call pcie_bus_configure_settings for pcie devices
  SPEAr13xx: Add mach/io.h
  SPEAr13xx: Add PCIe Root Complex driver support
  clk: SPEAr1340: Fix pcie0 clock name
  clk: SPEAr1310: Fix pcie clock name
  SPEAr1340: Add PCIe auxdata for miphy clock initialization
  SPEAr1310: Add PCIe auxdata for miphy clock initialization
  SPEAr13xx: dts: Fix PCIe core address ranges
  SPEAr13xx: DTS: Add auxiliary data for PCIe host
  SPEAr1340-evb: dts: Enable PCIe0
  SPEAr1310-EVB: DTS: Fix PCIe1 enable
  SPEAr13xx: update kconfig for PCIe selection
  SPEAR13xx: Update makefile for PCIe inclusion
  SPEAR13xx: update defconfig for PCIe compilation

 arch/arm/Kconfig                            |    1 +
 arch/arm/boot/dts/spear1310-evb.dts         |    4 -
 arch/arm/boot/dts/spear1340-evb.dts         |    4 +
 arch/arm/boot/dts/spear13xx.dtsi            |   33 +-
 arch/arm/configs/spear13xx_defconfig        |    1 +
 arch/arm/kernel/bios32.c                    |   12 +
 arch/arm/mach-spear13xx/Kconfig             |   12 +
 arch/arm/mach-spear13xx/Makefile            |    1 +
 arch/arm/mach-spear13xx/include/mach/io.h   |   35 +
 arch/arm/mach-spear13xx/include/mach/pcie.h |  233 ++++++
 arch/arm/mach-spear13xx/pcie.c              | 1145 +++++++++++++++++++++++++++
 arch/arm/mach-spear13xx/spear1310.c         |  148 ++++
 arch/arm/mach-spear13xx/spear1340.c         |   26 +
 drivers/clk/spear/spear1310_clock.c         |    6 +-
 drivers/clk/spear/spear1340_clock.c         |    2 +-
 15 files changed, 1651 insertions(+), 12 deletions(-)
 create mode 100644 arch/arm/mach-spear13xx/include/mach/io.h
 create mode 100644 arch/arm/mach-spear13xx/include/mach/pcie.h
 create mode 100644 arch/arm/mach-spear13xx/pcie.c

-- 
1.7.5.4

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

* [PATCH 00/15] SPEAr13xx PCIe patches
@ 2012-10-29  7:01 ` Pratyush Anand
  0 siblings, 0 replies; 56+ messages in thread
From: Pratyush Anand @ 2012-10-29  7:01 UTC (permalink / raw)
  To: arnd, shiraz.hashim, viresh.linux
  Cc: spear-devel, linux-pci, devicetree-discuss, olof, Pratyush Anand

-- First two patches are common for all platforms on ARM architecture.
-- Remaining patches belongs to SPEAr13xx architecture.
-- SPEAr13xx supports both RC and EP mode of PCIe interface. This patchset
	supports only RC mode.


Pratyush Anand (15):
  arm: source drivers/pci/pcie/kconfig
  arm: Call pcie_bus_configure_settings for pcie devices
  SPEAr13xx: Add mach/io.h
  SPEAr13xx: Add PCIe Root Complex driver support
  clk: SPEAr1340: Fix pcie0 clock name
  clk: SPEAr1310: Fix pcie clock name
  SPEAr1340: Add PCIe auxdata for miphy clock initialization
  SPEAr1310: Add PCIe auxdata for miphy clock initialization
  SPEAr13xx: dts: Fix PCIe core address ranges
  SPEAr13xx: DTS: Add auxiliary data for PCIe host
  SPEAr1340-evb: dts: Enable PCIe0
  SPEAr1310-EVB: DTS: Fix PCIe1 enable
  SPEAr13xx: update kconfig for PCIe selection
  SPEAR13xx: Update makefile for PCIe inclusion
  SPEAR13xx: update defconfig for PCIe compilation

 arch/arm/Kconfig                            |    1 +
 arch/arm/boot/dts/spear1310-evb.dts         |    4 -
 arch/arm/boot/dts/spear1340-evb.dts         |    4 +
 arch/arm/boot/dts/spear13xx.dtsi            |   33 +-
 arch/arm/configs/spear13xx_defconfig        |    1 +
 arch/arm/kernel/bios32.c                    |   12 +
 arch/arm/mach-spear13xx/Kconfig             |   12 +
 arch/arm/mach-spear13xx/Makefile            |    1 +
 arch/arm/mach-spear13xx/include/mach/io.h   |   35 +
 arch/arm/mach-spear13xx/include/mach/pcie.h |  233 ++++++
 arch/arm/mach-spear13xx/pcie.c              | 1145 +++++++++++++++++++++++++++
 arch/arm/mach-spear13xx/spear1310.c         |  148 ++++
 arch/arm/mach-spear13xx/spear1340.c         |   26 +
 drivers/clk/spear/spear1310_clock.c         |    6 +-
 drivers/clk/spear/spear1340_clock.c         |    2 +-
 15 files changed, 1651 insertions(+), 12 deletions(-)
 create mode 100644 arch/arm/mach-spear13xx/include/mach/io.h
 create mode 100644 arch/arm/mach-spear13xx/include/mach/pcie.h
 create mode 100644 arch/arm/mach-spear13xx/pcie.c

-- 
1.7.5.4


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

* [PATCH 01/15] arm: source drivers/pci/pcie/kconfig
  2012-10-29  7:01 ` Pratyush Anand
@ 2012-10-29  7:01   ` Pratyush Anand
  -1 siblings, 0 replies; 56+ messages in thread
From: Pratyush Anand @ 2012-10-29  7:01 UTC (permalink / raw)
  To: arnd, shiraz.hashim, viresh.linux
  Cc: spear-devel, linux-pci, devicetree-discuss, olof, Pratyush Anand

Signed-off-by: Pratyush Anand <pratyush.anand@st.com>
---
 arch/arm/Kconfig |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 170e215..a644454 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1434,6 +1434,7 @@ config PCI_HOST_ITE8152
 	select DMABOUNCE
 
 source "drivers/pci/Kconfig"
+source "drivers/pci/pcie/Kconfig"
 
 source "drivers/pcmcia/Kconfig"
 
-- 
1.7.5.4

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

* [PATCH 01/15] arm: source drivers/pci/pcie/kconfig
@ 2012-10-29  7:01   ` Pratyush Anand
  0 siblings, 0 replies; 56+ messages in thread
From: Pratyush Anand @ 2012-10-29  7:01 UTC (permalink / raw)
  To: arnd, shiraz.hashim, viresh.linux
  Cc: spear-devel, linux-pci, devicetree-discuss, olof, Pratyush Anand

Signed-off-by: Pratyush Anand <pratyush.anand@st.com>
---
 arch/arm/Kconfig |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 170e215..a644454 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1434,6 +1434,7 @@ config PCI_HOST_ITE8152
 	select DMABOUNCE
 
 source "drivers/pci/Kconfig"
+source "drivers/pci/pcie/Kconfig"
 
 source "drivers/pcmcia/Kconfig"
 
-- 
1.7.5.4


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

* [PATCH 02/15] arm: Call pcie_bus_configure_settings for pcie devices
  2012-10-29  7:01 ` Pratyush Anand
@ 2012-10-29  7:01   ` Pratyush Anand
  -1 siblings, 0 replies; 56+ messages in thread
From: Pratyush Anand @ 2012-10-29  7:01 UTC (permalink / raw)
  To: arnd, shiraz.hashim, viresh.linux
  Cc: spear-devel, linux-pci, devicetree-discuss, olof, Pratyush Anand

There could be some device which will work only after adjusting their
"Max Packet Size" and/or "Max Read Request Size".

This modification will only  be effective if proper 'pci=' bootargs is
passed.

Signed-off-by: Pratyush Anand <pratyush.anand@st.com>
---
 arch/arm/kernel/bios32.c |   12 ++++++++++++
 1 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
index 2555250..62d603f 100644
--- a/arch/arm/kernel/bios32.c
+++ b/arch/arm/kernel/bios32.c
@@ -490,6 +490,18 @@ void __init pci_common_init(struct hw_pci *hw)
 		struct pci_bus *bus = sys->bus;
 
 		if (!pci_has_flag(PCI_PROBE_ONLY)) {
+			struct pci_bus *child;
+
+			/*
+			 * Set MPS and readrq size
+			 */
+			list_for_each_entry(child, &bus->children, node) {
+				struct pci_dev *self = child->self;
+				if (!self)
+					continue;
+				pcie_bus_configure_settings(child,
+						self->pcie_mpss);
+			}
 			/*
 			 * Size the bridge windows.
 			 */
-- 
1.7.5.4

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

* [PATCH 02/15] arm: Call pcie_bus_configure_settings for pcie devices
@ 2012-10-29  7:01   ` Pratyush Anand
  0 siblings, 0 replies; 56+ messages in thread
From: Pratyush Anand @ 2012-10-29  7:01 UTC (permalink / raw)
  To: arnd, shiraz.hashim, viresh.linux
  Cc: spear-devel, linux-pci, devicetree-discuss, olof, Pratyush Anand

There could be some device which will work only after adjusting their
"Max Packet Size" and/or "Max Read Request Size".

This modification will only  be effective if proper 'pci=' bootargs is
passed.

Signed-off-by: Pratyush Anand <pratyush.anand@st.com>
---
 arch/arm/kernel/bios32.c |   12 ++++++++++++
 1 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
index 2555250..62d603f 100644
--- a/arch/arm/kernel/bios32.c
+++ b/arch/arm/kernel/bios32.c
@@ -490,6 +490,18 @@ void __init pci_common_init(struct hw_pci *hw)
 		struct pci_bus *bus = sys->bus;
 
 		if (!pci_has_flag(PCI_PROBE_ONLY)) {
+			struct pci_bus *child;
+
+			/*
+			 * Set MPS and readrq size
+			 */
+			list_for_each_entry(child, &bus->children, node) {
+				struct pci_dev *self = child->self;
+				if (!self)
+					continue;
+				pcie_bus_configure_settings(child,
+						self->pcie_mpss);
+			}
 			/*
 			 * Size the bridge windows.
 			 */
-- 
1.7.5.4


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

* [PATCH 03/15] SPEAr13xx: Add mach/io.h
  2012-10-29  7:01 ` Pratyush Anand
@ 2012-10-29  7:01   ` Pratyush Anand
  -1 siblings, 0 replies; 56+ messages in thread
From: Pratyush Anand @ 2012-10-29  7:01 UTC (permalink / raw)
  To: arnd, shiraz.hashim, viresh.linux
  Cc: spear-devel, linux-pci, devicetree-discuss, olof, Pratyush Anand

In case of PCIe we need to have a different __io macro, which can write
into PCIe address space.

Signed-off-by: Pratyush Anand <pratyush.anand@st.com>
---
 arch/arm/mach-spear13xx/include/mach/io.h |   35 +++++++++++++++++++++++++++++
 1 files changed, 35 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-spear13xx/include/mach/io.h

diff --git a/arch/arm/mach-spear13xx/include/mach/io.h b/arch/arm/mach-spear13xx/include/mach/io.h
new file mode 100644
index 0000000..a0d93ca
--- /dev/null
+++ b/arch/arm/mach-spear13xx/include/mach/io.h
@@ -0,0 +1,35 @@
+/*
+ * arch/arm/mach-spear13xx/include/mach/io.h
+ *
+ * spear13xx machine family generic header file
+ *
+ * Copyright (C) 2012 ST Microelectronics
+ * Pratyush Anand <pratyush.anand@st.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __MACH_IO_H
+#define __MACH_IO_H
+
+#define IO_SPACE_LIMIT	0xFFFF
+
+#ifdef CONFIG_SPEAR13XX_PCI
+extern void __iomem *spear13xx_pcie_io_base(unsigned long addr);
+
+static inline void __iomem *__io(unsigned long addr)
+{
+	return spear13xx_pcie_io_base(addr) + (addr & IO_SPACE_LIMIT);
+}
+#else
+static inline void __iomem *__io(unsigned long addr)
+{
+	return (void __iomem *)addr;
+}
+#endif
+
+#define __io(a)		__io(a)
+
+#endif /* __MACH_IO_H */
-- 
1.7.5.4

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

* [PATCH 03/15] SPEAr13xx: Add mach/io.h
@ 2012-10-29  7:01   ` Pratyush Anand
  0 siblings, 0 replies; 56+ messages in thread
From: Pratyush Anand @ 2012-10-29  7:01 UTC (permalink / raw)
  To: arnd, shiraz.hashim, viresh.linux
  Cc: spear-devel, linux-pci, devicetree-discuss, olof, Pratyush Anand

In case of PCIe we need to have a different __io macro, which can write
into PCIe address space.

Signed-off-by: Pratyush Anand <pratyush.anand@st.com>
---
 arch/arm/mach-spear13xx/include/mach/io.h |   35 +++++++++++++++++++++++++++++
 1 files changed, 35 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-spear13xx/include/mach/io.h

diff --git a/arch/arm/mach-spear13xx/include/mach/io.h b/arch/arm/mach-spear13xx/include/mach/io.h
new file mode 100644
index 0000000..a0d93ca
--- /dev/null
+++ b/arch/arm/mach-spear13xx/include/mach/io.h
@@ -0,0 +1,35 @@
+/*
+ * arch/arm/mach-spear13xx/include/mach/io.h
+ *
+ * spear13xx machine family generic header file
+ *
+ * Copyright (C) 2012 ST Microelectronics
+ * Pratyush Anand <pratyush.anand@st.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __MACH_IO_H
+#define __MACH_IO_H
+
+#define IO_SPACE_LIMIT	0xFFFF
+
+#ifdef CONFIG_SPEAR13XX_PCI
+extern void __iomem *spear13xx_pcie_io_base(unsigned long addr);
+
+static inline void __iomem *__io(unsigned long addr)
+{
+	return spear13xx_pcie_io_base(addr) + (addr & IO_SPACE_LIMIT);
+}
+#else
+static inline void __iomem *__io(unsigned long addr)
+{
+	return (void __iomem *)addr;
+}
+#endif
+
+#define __io(a)		__io(a)
+
+#endif /* __MACH_IO_H */
-- 
1.7.5.4


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

* [PATCH 04/15] SPEAr13xx: Add PCIe Root Complex driver support
  2012-10-29  7:01 ` Pratyush Anand
@ 2012-10-29  7:01   ` Pratyush Anand
  -1 siblings, 0 replies; 56+ messages in thread
From: Pratyush Anand @ 2012-10-29  7:01 UTC (permalink / raw)
  To: arnd, shiraz.hashim, viresh.linux
  Cc: spear-devel, linux-pci, devicetree-discuss, olof, Pratyush Anand

SPEAr13xx has dual mode PCIe controller which can be used as Root
Complex as well as Endpoint. This driver supports RC mode of the
controller.

If CONFIG_PCI_MSI is defined then support of MSI interrupt for
downstream  PCIe devices will be enabled.

If CONFIG_PM is defined then it supports suspend/resume functionality.

Signed-off-by: Pratyush Anand <pratyush.anand@st.com>
---
 arch/arm/mach-spear13xx/include/mach/pcie.h |  233 ++++++
 arch/arm/mach-spear13xx/pcie.c              | 1145 +++++++++++++++++++++++++++
 2 files changed, 1378 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-spear13xx/include/mach/pcie.h
 create mode 100644 arch/arm/mach-spear13xx/pcie.c

diff --git a/arch/arm/mach-spear13xx/include/mach/pcie.h b/arch/arm/mach-spear13xx/include/mach/pcie.h
new file mode 100644
index 0000000..39bff4f
--- /dev/null
+++ b/arch/arm/mach-spear13xx/include/mach/pcie.h
@@ -0,0 +1,233 @@
+/*
+ * arch/arm/mach-spear13xx/include/mach/pcie.h
+ *
+ * Copyright (C) 2010-2012 ST Microelectronics
+ * Pratyush Anand <pratyush.anand@st.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+#ifndef __MACH_PCIE_H
+#define __MACH_PCIE_H
+
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+#include <linux/types.h>
+#include <linux/clk.h>
+
+#define MAX_LINK_UP_WAIT_MS	2
+/* Max port defined can be changed if required */
+#define MAX_PCIE_PORT_SUPPORTED	3
+struct pcie_port;
+
+struct pcie_port_info {
+	u32	is_host;
+	u32	is_gen1;
+	u32	cfg0_size;
+	u32	cfg1_size;
+	u32	mem_size;
+	u32	msg_size;
+	u32	in_mem_size;
+	u32	io_size;
+	int (*clk_init)(struct pcie_port *pp);
+	int (*clk_exit)(struct pcie_port *pp);
+};
+
+struct pcie_port {
+	u8			controller;
+	u8			root_bus_nr;
+	void __iomem		*dbi_base;
+	void __iomem		*va_dbi_base;
+	void __iomem		*app_base;
+	void __iomem		*va_app_base;
+	void __iomem		*base;
+	void __iomem		*phy_base;
+	void __iomem		*va_phy_base;
+	void __iomem		*cfg0_base;
+	void __iomem		*va_cfg0_base;
+	void __iomem		*cfg1_base;
+	void __iomem		*va_cfg1_base;
+	void __iomem		*mem_base;
+	void __iomem		*io_base;
+	spinlock_t		conf_lock;
+	char			mem_space_name[16];
+	char			io_space_name[16];
+	struct resource		res[2];
+	struct pcie_port_info	config;
+	struct list_head	next;
+	struct clk		*clk;
+	int			irq;
+	int			virt_irq_base;
+	int			susp_state;
+};
+
+/* synopsis specific PCIE configuration registers*/
+#define PCIE_PORT_LOGIC			0x80C
+#define PORT_LOGIC_SPD_CHANGE_ID	17
+
+#define PCIE_MSI_ADDR_LO		0x820
+#define PCIE_MSI_ADDR_HI		0x824
+#define PCIE_MSI_INTR0_ENABLE		0x828
+#define PCIE_MSI_INTR0_MASK		0x82C
+#define PCIE_MSI_INTR0_STATUS		0x830
+
+#define PCIE_ATU_VIEWPORT		0x900
+#define PCIE_ATU_REGION_INBOUND		(1 << 31)
+#define PCIE_ATU_REGION_OUTBOUND	(0 << 31)
+#define PCIE_ATU_CR1			0x904
+#define PCIE_ATU_TYPE_MEM		0
+#define PCIE_ATU_TYPE_IO		2
+#define PCIE_ATU_TYPE_CFG0		4
+#define PCIE_ATU_TYPE_CFG1		5
+#define PCIE_ATU_CR2			0x908
+#define PCIE_ATU_ENABLE			(1 << 31)
+#define PCIE_ATU_BAR_MODE_ENABLE	(1 << 30)
+#define PCIE_ATU_LOWER_BASE		0x90C
+#define PCIE_ATU_UPPER_BASE		0x910
+#define PCIE_ATU_LIMIT			0x914
+#define PCIE_ATU_LOWER_TARGET		0x918
+#define PCIE_ATU_UPPER_TARGET		0x91C
+
+/*BAR MASK registers*/
+#define PCIE_BAR0_MASK_REG		0x1010
+
+struct pcie_app_reg {
+	u32	app_ctrl_0;		/*cr0*/
+	u32	app_ctrl_1;		/*cr1*/
+	u32	app_status_0;		/*cr2*/
+	u32	app_status_1;		/*cr3*/
+	u32	msg_status;		/*cr4*/
+	u32	msg_payload;		/*cr5*/
+	u32	int_sts;		/*cr6*/
+	u32	int_clr;		/*cr7*/
+	u32	int_mask;		/*cr8*/
+	u32	mst_bmisc;		/*cr9*/
+	u32	phy_ctrl;		/*cr10*/
+	u32	phy_status;		/*cr11*/
+	u32	cxpl_debug_info_0;	/*cr12*/
+	u32	cxpl_debug_info_1;	/*cr13*/
+	u32	ven_msg_ctrl_0;		/*cr14*/
+	u32	ven_msg_ctrl_1;		/*cr15*/
+	u32	ven_msg_data_0;		/*cr16*/
+	u32	ven_msg_data_1;		/*cr17*/
+	u32	ven_msi_0;		/*cr18*/
+	u32	ven_msi_1;		/*cr19*/
+	u32	mst_rmisc;		/*cr 20*/
+	u32	slv_awmisc;		/*cr 21*/
+	u32	slv_armisc;		/*cr 22*/
+	u32	pom0_mem_addr_start;	/*cr23*/
+	u32	pom1_mem_addr_start;	/*cr24*/
+	u32	pom_io_addr_start;	/*cr25*/
+	u32	pom_cfg0_addr_start;	/*cr26*/
+	u32	pom_cfg1_addr_start;	/*cr27*/
+	u32	in0_mem_addr_start;	/*cr28*/
+	u32	in1_mem_addr_start;	/*cr29*/
+	u32	in_io_addr_start;	/*cr30*/
+	u32	in_cfg0_addr_start;	/*cr31*/
+	u32	in_cfg1_addr_start;	/*cr32*/
+	u32	in_msg_addr_start;	/*cr33*/
+	u32	in0_mem_addr_limit;	/*cr34*/
+	u32	in1_mem_addr_limit;	/*cr35*/
+	u32	in_io_addr_limit;	/*cr36*/
+	u32	in_cfg0_addr_limit;	/*cr37*/
+	u32	in_cfg1_addr_limit;	/*cr38*/
+	u32	in_msg_addr_limit;	/*cr39*/
+	u32	mem0_addr_offset_limit;	/*cr40*/
+	u32	pim0_mem_addr_start;	/*cr41*/
+	u32	pim1_mem_addr_start;	/*cr42*/
+	u32	pim_io_addr_start;	/*cr43*/
+	u32	pim_rom_addr_start;	/*cr44*/
+};
+
+/*CR0 ID*/
+#define RX_LANE_FLIP_EN_ID			0
+#define TX_LANE_FLIP_EN_ID			1
+#define SYS_AUX_PWR_DET_ID			2
+#define APP_LTSSM_ENABLE_ID			3
+#define SYS_ATTEN_BUTTON_PRESSED_ID		4
+#define SYS_MRL_SENSOR_STATE_ID			5
+#define SYS_PWR_FAULT_DET_ID			6
+#define SYS_MRL_SENSOR_CHGED_ID			7
+#define SYS_PRE_DET_CHGED_ID			8
+#define SYS_CMD_CPLED_INT_ID			9
+#define APP_INIT_RST_0_ID			11
+#define APP_REQ_ENTR_L1_ID			12
+#define APP_READY_ENTR_L23_ID			13
+#define APP_REQ_EXIT_L1_ID			14
+#define DEVICE_TYPE_EP				(0 << 25)
+#define DEVICE_TYPE_LEP				(1 << 25)
+#define DEVICE_TYPE_RC				(4 << 25)
+#define SYS_INT_ID				29
+#define MISCTRL_EN_ID				30
+#define REG_TRANSLATION_ENABLE			31
+
+/*CR1 ID*/
+#define APPS_PM_XMT_TURNOFF_ID			2
+#define APPS_PM_XMT_PME_ID			5
+
+/*CR3 ID*/
+#define XMLH_LTSSM_STATE_ID			0
+#define XMLH_LTSSM_STATE_L0	((u32)0x11 << XMLH_LTSSM_STATE_ID)
+#define XMLH_LTSSM_STATE_MASK	((u32)0x3F << XMLH_LTSSM_STATE_ID)
+#define XMLH_LINK_UP_ID				6
+
+/*CR4 ID*/
+#define CFG_MSI_EN_ID				18
+
+/*CR6*/
+#define INTA_CTRL_INT				(1 << 7)
+#define INTB_CTRL_INT				(1 << 8)
+#define INTC_CTRL_INT				(1 << 9)
+#define INTD_CTRL_INT				(1 << 10)
+#define MSI_CTRL_INT				(1 << 26)
+
+/*CR19 ID*/
+#define VEN_MSI_REQ_ID				11
+#define VEN_MSI_FUN_NUM_ID			8
+#define VEN_MSI_TC_ID				5
+#define VEN_MSI_VECTOR_ID			0
+#define VEN_MSI_REQ_EN		((u32)0x1 << VEN_MSI_REQ_ID)
+#define VEN_MSI_FUN_NUM_MASK	((u32)0x7 << VEN_MSI_FUN_NUM_ID)
+#define VEN_MSI_TC_MASK		((u32)0x7 << VEN_MSI_TC_ID)
+#define VEN_MSI_VECTOR_MASK	((u32)0x1F << VEN_MSI_VECTOR_ID)
+
+/*CE21-22 ID*/
+/*ID definition of ARMISC*/
+#define AXI_OP_TYPE_ID				0
+#define AXI_OP_BCM_ID				5
+#define AXI_OP_EP_ID				6
+#define AXI_OP_TD_ID				7
+#define AXI_OP_ATTRIBUTE_ID			8
+#define AXI_OP_TC_ID				10
+#define AXI_OP_MSG_CODE_ID			13
+#define AXI_OP_DBI_ACCESS_ID			21
+#define AXI_OP_TYPE_MASK			0x1F
+#define AXI_OP_TYPE_MEM_RDRW			0
+#define AXI_OP_TYPE_MEM_RDRW_LOCKED		1
+#define AXI_OP_TYPE_IO_RDRW			2
+#define AXI_OP_TYPE_CONFIG_RDRW_TYPE0		4
+#define AXI_OP_TYPE_CONFIG_RDRW_TYPE1		5
+#define AXI_OP_TYPE_MSG_REQ			16
+#define AXI_OP_TYPE_COMPLETION			10
+#define AXI_OP_TYPE_COMPLETION_LOCKED		11
+#define AXI_OP_TYPE_DBI_ELBI_ENABLE		1
+
+#define PCI_CAP_ID_EXP_OFFSET			0x70
+
+#define PCIE_IS_HOST		1
+#define PCIE_IS_DEVICE		0
+
+#define PCIE_IS_GEN1		1
+#define PCIE_IS_GEN2		0
+
+#define NUM_INTX_IRQS		4
+/*
+ * Maximum number of MSI IRQs can be 256 per controller. But keep it 64
+ * as of now. Probably we will never need more than 64. If needed, then
+ * Increment it in multiple of 32.
+ */
+#define NUM_MSI_IRQS		64
+
+#define	IO_SIZE_PER_PORT	SZ_16K
+#endif
diff --git a/arch/arm/mach-spear13xx/pcie.c b/arch/arm/mach-spear13xx/pcie.c
new file mode 100644
index 0000000..bfed3b7
--- /dev/null
+++ b/arch/arm/mach-spear13xx/pcie.c
@@ -0,0 +1,1145 @@
+/*
+ * arch/arm/mach-spear13xx/pcie.c
+ *
+ * PCIe functions for SPEAr13XX PCIe Host controllers
+ *
+ * Copyright (C) 2010-2012 ST Microelectronics
+ * Pratyush Anand <pratyush.anand@st.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/msi.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/pci.h>
+#include <linux/pci_regs.h>
+#include <linux/platform_device.h>
+#include <linux/resource.h>
+#include <linux/slab.h>
+#include <asm/mach/irq.h>
+#include <asm/signal.h>
+#include <mach/pcie.h>
+
+static struct list_head	pcie_port_list;
+static struct hw_pci pci;
+
+static inline int cfg_read(void *addr, int where, int size, u32 *val)
+{
+	*val = readl(addr);
+
+	if (size == 1)
+		*val = (*val >> (8 * (where & 3))) & 0xff;
+	else if (size == 2)
+		*val = (*val >> (8 * (where & 3))) & 0xffff;
+	else if (size != 4)
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static inline int cfg_write(void *addr, int where, int size, u32 val)
+{
+	if (size == 4)
+		writel(val, addr);
+	else if (size == 2)
+		writew(val, addr + (where & 2));
+	else if (size == 1)
+		writeb(val, addr + (where & 3));
+	else
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int pcie_rd_own_conf(struct pcie_port *pp, int where, int size,
+		u32 *val)
+{
+	return cfg_read(pp->va_dbi_base + (where & ~0x3), where, size, val);
+}
+
+static int pcie_wr_own_conf(struct pcie_port *pp, int where, int size,
+		u32 val)
+{
+	return cfg_write(pp->va_dbi_base + (where & ~0x3), where, size, val);
+}
+
+static void spear_pcie_prog_viewport_cfg0(struct pcie_port *pp, u32 busdev)
+{
+	u32 val;
+	void __iomem *dbi_base = pp->va_dbi_base;
+
+	/* Program viewport 0 : OUTBOUND : CFG0 */
+	val = PCIE_ATU_REGION_OUTBOUND | (0 & 0xF);
+	writel(val, dbi_base + PCIE_ATU_VIEWPORT);
+	writel(PCIE_ATU_TYPE_CFG0, dbi_base + PCIE_ATU_CR1);
+	val = PCIE_ATU_ENABLE;
+	writel(val, dbi_base + PCIE_ATU_CR2);
+	writel(pp->cfg0_base, dbi_base + PCIE_ATU_LOWER_BASE);
+	writel(0, dbi_base + PCIE_ATU_UPPER_BASE);
+	writel(pp->cfg0_base + pp->config.cfg0_size - 1,
+			dbi_base + PCIE_ATU_LIMIT);
+	writel(busdev, dbi_base + PCIE_ATU_LOWER_TARGET);
+	writel(0, dbi_base + PCIE_ATU_UPPER_TARGET);
+}
+
+static void spear_pcie_prog_viewport_cfg1(struct pcie_port *pp, u32 busdev)
+{
+	u32 val;
+	void __iomem *dbi_base = pp->va_dbi_base;
+
+	/* Program viewport 1 : OUTBOUND : CFG1 */
+	val = PCIE_ATU_REGION_OUTBOUND | (1 & 0xF);
+	writel(val, dbi_base + PCIE_ATU_VIEWPORT);
+	writel(PCIE_ATU_TYPE_CFG1, dbi_base + PCIE_ATU_CR1);
+	val = PCIE_ATU_ENABLE;
+	writel(val, dbi_base + PCIE_ATU_CR2);
+	writel(pp->cfg1_base, dbi_base + PCIE_ATU_LOWER_BASE);
+	writel(0, dbi_base + PCIE_ATU_UPPER_BASE);
+	writel(pp->cfg1_base + pp->config.cfg1_size - 1,
+			dbi_base + PCIE_ATU_LIMIT);
+	writel(busdev, dbi_base + PCIE_ATU_LOWER_TARGET);
+	writel(0, dbi_base + PCIE_ATU_UPPER_TARGET);
+}
+
+static void spear_pcie_prog_viewport_mem(struct pcie_port *pp)
+{
+	u32 val;
+	void __iomem *dbi_base = pp->va_dbi_base;
+
+	/* Program viewport 0 : OUTBOUND : MEM */
+	val = PCIE_ATU_REGION_OUTBOUND | (0 & 0xF);
+	writel(val, dbi_base + PCIE_ATU_VIEWPORT);
+	writel(PCIE_ATU_TYPE_MEM, dbi_base + PCIE_ATU_CR1);
+	val = PCIE_ATU_ENABLE;
+	writel(val, dbi_base + PCIE_ATU_CR2);
+	writel(pp->mem_base, dbi_base + PCIE_ATU_LOWER_BASE);
+	writel(0, dbi_base + PCIE_ATU_UPPER_BASE);
+	writel(pp->mem_base + pp->config.mem_size - 1,
+			dbi_base + PCIE_ATU_LIMIT);
+	writel(pp->mem_base, dbi_base + PCIE_ATU_LOWER_TARGET);
+	writel(0, dbi_base + PCIE_ATU_UPPER_TARGET);
+}
+
+static void spear_pcie_prog_viewport_io(struct pcie_port *pp)
+{
+	u32 val;
+	void __iomem *dbi_base = pp->va_dbi_base;
+
+	/* Program viewport 1 : OUTBOUND : IO */
+	val = PCIE_ATU_REGION_OUTBOUND | (1 & 0xF);
+	writel(val, dbi_base + PCIE_ATU_VIEWPORT);
+	writel(PCIE_ATU_TYPE_IO, dbi_base + PCIE_ATU_CR1);
+	val = PCIE_ATU_ENABLE;
+	writel(val, dbi_base + PCIE_ATU_CR2);
+	writel(pp->io_base, dbi_base + PCIE_ATU_LOWER_BASE);
+	writel(0, dbi_base + PCIE_ATU_UPPER_BASE);
+	writel(pp->io_base + pp->config.io_size - 1,
+			dbi_base + PCIE_ATU_LIMIT);
+	writel(pp->io_base, dbi_base + PCIE_ATU_LOWER_TARGET);
+	writel(0, dbi_base + PCIE_ATU_UPPER_TARGET);
+}
+
+static int pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
+		u32 devfn, int where, int size, u32 *val)
+{
+	int ret = PCIBIOS_SUCCESSFUL;
+	u32 address, busdev;
+
+	busdev = (bus->number << 24) | (PCI_SLOT(devfn) << 19);
+	address = (PCI_FUNC(devfn) << 16) | (where & 0xFFFC);
+
+	if (bus->parent->number == pp->root_bus_nr) {
+		spear_pcie_prog_viewport_cfg0(pp, busdev);
+		ret = cfg_read(pp->va_cfg0_base + address, where, size, val);
+		spear_pcie_prog_viewport_mem(pp);
+	} else {
+		spear_pcie_prog_viewport_cfg1(pp, busdev);
+		ret = cfg_read(pp->va_cfg1_base + address, where, size, val);
+		spear_pcie_prog_viewport_io(pp);
+	}
+
+	return ret;
+}
+
+static int pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus,
+		u32 devfn, int where, int size, u32 val)
+{
+	int ret = PCIBIOS_SUCCESSFUL;
+	u32 address, busdev;
+
+	busdev = (bus->number << 24) | (PCI_SLOT(devfn) << 19);
+	address = (PCI_FUNC(devfn) << 16) | (where & 0xFFFC);
+
+	if (bus->parent->number == pp->root_bus_nr) {
+		spear_pcie_prog_viewport_cfg0(pp, busdev);
+		ret = cfg_write(pp->va_cfg0_base + address, where, size, val);
+		spear_pcie_prog_viewport_mem(pp);
+	} else {
+		spear_pcie_prog_viewport_cfg1(pp, busdev);
+		ret = cfg_write(pp->va_cfg1_base + address, where, size, val);
+		spear_pcie_prog_viewport_io(pp);
+	}
+
+	return ret;
+}
+
+static struct pcie_port *controller_to_port(int controller)
+{
+	struct pcie_port *pp;
+
+	if (controller >= pci.nr_controllers)
+		return NULL;
+
+	list_for_each_entry(pp, &pcie_port_list, next) {
+		if (pp->controller == controller)
+			return pp;
+	}
+	return NULL;
+}
+
+static struct pcie_port *bus_to_port(int bus)
+{
+	int i;
+	int rbus;
+	struct pcie_port *pp;
+
+	for (i = pci.nr_controllers - 1 ; i >= 0; i--) {
+		pp = controller_to_port(i);
+		rbus = pp->root_bus_nr;
+		if (rbus != -1 && rbus <= bus)
+			break;
+	}
+
+	return i >= 0 ? pp : NULL;
+}
+
+#ifdef CONFIG_PCI_MSI
+static DECLARE_BITMAP(msi_irq_in_use[MAX_PCIE_PORT_SUPPORTED],
+		NUM_MSI_IRQS);
+static unsigned int msi_data[MAX_PCIE_PORT_SUPPORTED];
+
+/* MSI int handler */
+static void handle_msi(struct pcie_port *pp)
+{
+	unsigned long val;
+	int i, pos;
+
+	for (i = 0; i < NUM_MSI_IRQS / 32; i++) {
+		pcie_rd_own_conf(pp, PCIE_MSI_INTR0_STATUS + i * 12, 4,
+				(u32 *)&val);
+		if (val) {
+			pos = 0;
+			while ((pos = find_next_bit(&val, 32, pos)) != 32) {
+				generic_handle_irq(pp->virt_irq_base +
+						NUM_INTX_IRQS + (i * 32) + pos);
+				pos++;
+			}
+		}
+		pcie_wr_own_conf(pp, PCIE_MSI_INTR0_STATUS + i * 12, 4, val);
+	}
+}
+
+static void msi_nop(struct irq_data *d)
+{
+	return;
+}
+
+static struct irq_chip msi_chip = {
+	.name = "PCI-MSI",
+	.irq_ack = msi_nop,
+	.irq_enable = unmask_msi_irq,
+	.irq_disable = mask_msi_irq,
+	.irq_mask = mask_msi_irq,
+	.irq_unmask = unmask_msi_irq,
+};
+
+/* Dynamic irq allocate and deallocation */
+static int get_irq(struct msi_desc *desc, int *pos)
+{
+	int res, bit, irq, pos0;
+	u32 val;
+	struct pcie_port *pp = bus_to_port(desc->dev->bus->number);
+
+	if (!pp) {
+		BUG();
+		return -EINVAL;
+	}
+
+	pos0 = find_first_zero_bit(msi_irq_in_use[pp->controller],
+			NUM_MSI_IRQS);
+
+	irq = pp->virt_irq_base + NUM_INTX_IRQS + pos0;
+
+	if (pos0 > NUM_MSI_IRQS)
+		goto no_valid_irq;
+
+	set_bit(pos0, msi_irq_in_use[pp->controller]);
+
+	dynamic_irq_init(irq);
+	irq_set_msi_desc(irq, desc);
+	irq_set_chip_and_handler(irq, &msi_chip, handle_simple_irq);
+	set_irq_flags(irq, IRQF_VALID);
+	irq_set_chip_data(irq, pp);
+
+	/*
+	 * Enable corresponding interrupt on MSI interrupt
+	 * controller.
+	 */
+	res = (pos0 / 32) * 12;
+	bit = pos0 % 32;
+	pcie_rd_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, &val);
+	val |= 1 << bit;
+	pcie_wr_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, val);
+
+	*pos = pos0;
+	return irq;
+
+no_valid_irq:
+	*pos = pos0;
+
+	return -ENOSPC;
+}
+
+static void clean_irq(unsigned int irq)
+{
+	int res, bit, val, pos;
+	struct irq_desc *desc = irq_to_desc(irq);
+	struct msi_desc *msi_desc = irq_desc_get_msi_desc(desc);
+	struct pcie_port *pp = bus_to_port(msi_desc->dev->bus->number);
+
+	if (!pp) {
+		BUG();
+		return;
+	}
+
+	pos = irq - pp->virt_irq_base - NUM_INTX_IRQS;
+
+	dynamic_irq_cleanup(irq);
+
+	clear_bit(pos, msi_irq_in_use[pp->controller]);
+
+	/*
+	 * Disable corresponding interrupt on MSI interrupt
+	 * controller.
+	 */
+	res = (pos / 32) * 12;
+	bit = pos % 32;
+	pcie_rd_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, &val);
+	val &= ~(1 << bit);
+	pcie_wr_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, val);
+}
+
+int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
+{
+	int irq, pos;
+	struct msi_msg msg;
+	struct pcie_port *pp = bus_to_port(pdev->bus->number);
+
+	if (!pp) {
+		BUG();
+		return -EINVAL;
+	}
+
+	irq = get_irq(desc, &pos);
+
+	if (irq < 0)
+		return irq;
+	/*
+	 * An EP will modify lower 8 bits(max) of msi data while
+	 * sending any msi interrupt
+	 */
+	msg.address_hi = 0x0;
+	msg.address_lo = __virt_to_phys((u32)(&msi_data[pp->controller]));
+	msg.data = pos;
+	write_msi_msg(irq, &msg);
+
+	return 0;
+}
+
+void arch_teardown_msi_irq(unsigned int irq)
+{
+	clean_irq(irq);
+}
+
+static void msi_init(struct pcie_port *pp)
+{
+	struct pcie_app_reg *app_reg = pp->va_app_base;
+
+	pcie_wr_own_conf(pp, PCIE_MSI_ADDR_LO, 4,
+			__virt_to_phys((u32)(&msi_data[pp->controller])));
+	pcie_wr_own_conf(pp, PCIE_MSI_ADDR_HI, 4, 0);
+
+	/* Enable MSI interrupt */
+	writel(readl(&app_reg->int_mask) | MSI_CTRL_INT,
+			&app_reg->int_mask);
+}
+#endif
+
+static int __init pcie_setup(int nr, struct pci_sys_data *sys)
+{
+	struct pcie_port *pp;
+
+	pp = controller_to_port(nr);
+
+	if (!pp)
+		return 0;
+
+	pp->root_bus_nr = sys->busnr;
+
+	snprintf(pp->mem_space_name, sizeof(pp->mem_space_name),
+			"PCIe %d MEM", nr);
+	pp->mem_space_name[sizeof(pp->mem_space_name) - 1] = 0;
+	pp->res[0].name = pp->mem_space_name;
+	pp->res[0].start = (resource_size_t)pp->mem_base;
+	pp->res[0].end = pp->res[0].start + pp->config.mem_size - 1;
+	pp->res[0].flags = IORESOURCE_MEM;
+	if (request_resource(&iomem_resource, &pp->res[0]))
+		panic("can't allocate PCIe Mem space");
+	pci_add_resource_offset(&sys->resources, &pp->res[0], sys->mem_offset);
+
+	snprintf(pp->io_space_name, sizeof(pp->io_space_name),
+			"PCIe %d I/O", nr);
+	pp->io_space_name[sizeof(pp->io_space_name) - 1] = 0;
+	pp->res[1].name = pp->io_space_name;
+	pp->res[1].start = PCIBIOS_MIN_IO + nr * pp->config.io_size;
+	pp->res[1].end = pp->res[1].start + (pp->config.io_size - 1);
+	pp->res[1].flags = IORESOURCE_IO;
+	if (request_resource(&ioport_resource, &pp->res[1]))
+		panic("can't allocate PCIe IO space");
+	pci_add_resource_offset(&sys->resources, &pp->res[1], sys->io_offset);
+
+	return 1;
+}
+
+static int pcie_link_up(struct pcie_app_reg *app_reg)
+{
+	int ucount = 0;
+
+	do {
+		if (readl(&app_reg->app_status_1) &
+			((u32)1 << XMLH_LINK_UP_ID))
+			return 1;
+		ucount++;
+		udelay(1);
+	} while (ucount <= MAX_LINK_UP_WAIT_MS * 1000);
+
+	return 0;
+}
+
+static int pcie_valid_config(struct pcie_port *pp, struct pci_bus *bus, int dev)
+{
+	/* If there is no link, then there is no device */
+	if (bus->number != pp->root_bus_nr) {
+		if (!pcie_link_up(pp->va_app_base))
+			return 0;
+	}
+
+	/*
+	 * Don't go out when trying to access non-existing devices
+	 * on the local bus.
+	 * we have only one slot on each root port.
+	 */
+	if (bus->number == pp->root_bus_nr && dev > 0)
+		return 0;
+
+	/*
+	 * do not read more than one device on the bus directly attached
+	 * to RC's (Virtual Bridge's) DS side.
+	 */
+	if (bus->primary == pp->root_bus_nr && dev > 0)
+		return 0;
+
+	return 1;
+}
+
+static int pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
+			int size, u32 *val)
+{
+	struct pcie_port *pp = bus_to_port(bus->number);
+	unsigned long flags;
+	int ret;
+
+	if (!pp) {
+		BUG();
+		return -EINVAL;
+	}
+
+	if (pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) {
+		*val = 0xffffffff;
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	}
+
+	spin_lock_irqsave(&pp->conf_lock, flags);
+	if (bus->number != pp->root_bus_nr)
+		ret = pcie_rd_other_conf(pp, bus, devfn, where, size, val);
+	else
+		ret = pcie_rd_own_conf(pp, where, size, val);
+	spin_unlock_irqrestore(&pp->conf_lock, flags);
+
+	return ret;
+}
+
+static int pcie_wr_conf(struct pci_bus *bus, u32 devfn,
+			int where, int size, u32 val)
+{
+	struct pcie_port *pp = bus_to_port(bus->number);
+	unsigned long flags;
+	int ret;
+
+	if (!pp) {
+		BUG();
+		return -EINVAL;
+	}
+
+	if (pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	spin_lock_irqsave(&pp->conf_lock, flags);
+	if (bus->number != pp->root_bus_nr)
+		ret = pcie_wr_other_conf(pp, bus, devfn, where, size, val);
+	else
+		ret = pcie_wr_own_conf(pp, where, size, val);
+	spin_unlock_irqrestore(&pp->conf_lock, flags);
+
+	return ret;
+}
+
+static struct pci_ops pcie_ops = {
+	.read = pcie_rd_conf,
+	.write = pcie_wr_conf,
+};
+
+static struct pci_bus __init *pcie_scan_bus(int nr, struct pci_sys_data *sys)
+{
+	struct pci_bus *bus;
+	struct pcie_port *pp = controller_to_port(nr);
+
+	if (pp) {
+		pp->root_bus_nr = sys->busnr;
+
+		return bus = pci_scan_root_bus(NULL, sys->busnr, &pcie_ops, sys,
+				&sys->resources);
+	} else {
+		bus = NULL;
+		BUG();
+	}
+
+	return bus;
+}
+
+static int pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+	struct pcie_port *pp = bus_to_port(dev->bus->number);
+	int irq;
+
+	if (!pp) {
+		BUG();
+		return -EINVAL;
+	}
+
+	irq = (pp->virt_irq_base + pin - 1);
+
+	return irq;
+}
+
+static struct hw_pci pci = {
+	.setup		= pcie_setup,
+	.scan		= pcie_scan_bus,
+	.map_irq	= pcie_map_irq,
+};
+
+static void mask_intx_irq(struct irq_data *data)
+{
+	struct pcie_port *pp = irq_data_get_irq_chip_data(data);
+	struct pcie_app_reg *app_reg = pp->va_app_base;
+	int irq_offset = data->irq - pp->virt_irq_base;
+	u32 mask;
+
+	switch (irq_offset) {
+	case 0:
+		mask = ~INTA_CTRL_INT;
+		break;
+	case 1:
+		mask = ~INTB_CTRL_INT;
+		break;
+	case 2:
+		mask = ~INTC_CTRL_INT;
+		break;
+	case 3:
+		mask = ~INTD_CTRL_INT;
+		break;
+	default:
+		BUG();
+		return;
+	}
+
+	writel(readl(&app_reg->int_mask) & mask, &app_reg->int_mask);
+}
+
+static void unmask_intx_irq(struct irq_data *data)
+{
+	struct pcie_port *pp = irq_data_get_irq_chip_data(data);
+	struct pcie_app_reg *app_reg = pp->va_app_base;
+	int irq_offset = data->irq - pp->virt_irq_base;
+	u32 mask;
+
+	switch (irq_offset) {
+	case 0:
+		mask = INTA_CTRL_INT;
+		break;
+	case 1:
+		mask = INTB_CTRL_INT;
+		break;
+	case 2:
+		mask = INTC_CTRL_INT;
+		break;
+	case 3:
+		mask = INTD_CTRL_INT;
+		break;
+	default:
+		BUG();
+		return;
+	}
+
+	writel(readl(&app_reg->int_mask) | mask, &app_reg->int_mask);
+}
+
+static struct irq_chip intx_chip = {
+	.name = "PCI-INTX",
+	.irq_mask = mask_intx_irq,
+	.irq_unmask = unmask_intx_irq,
+};
+
+static void pcie_int_handler(unsigned int irq, struct irq_desc *desc)
+{
+	struct pcie_port *pp = irq_get_handler_data(irq);
+	struct pcie_app_reg *app_reg = pp->va_app_base;
+	struct irq_chip *irqchip = irq_desc_get_chip(desc);
+	unsigned int status;
+
+	chained_irq_enter(irqchip, desc);
+
+	status = readl(&app_reg->int_sts);
+
+	if (status & MSI_CTRL_INT) {
+#ifdef CONFIG_PCI_MSI
+		handle_msi(pp);
+#endif
+		writel(MSI_CTRL_INT, &app_reg->int_clr);
+	} else if (status & INTA_CTRL_INT)
+		generic_handle_irq(pp->virt_irq_base);
+	else if (status & INTB_CTRL_INT)
+		generic_handle_irq(pp->virt_irq_base + 1);
+	else if (status & INTC_CTRL_INT)
+		generic_handle_irq(pp->virt_irq_base + 2);
+	else if (status & INTD_CTRL_INT)
+		generic_handle_irq(pp->virt_irq_base + 3);
+	else
+		writel(status, &app_reg->int_clr);
+
+	chained_irq_exit(irqchip, desc);
+}
+
+static void pcie_irq_init(struct pcie_port *pp)
+{
+	struct pcie_app_reg *app_reg = pp->va_app_base;
+	int i;
+
+	irq_set_chained_handler(pp->irq, pcie_int_handler);
+	irq_set_handler_data(pp->irq, pp);
+
+#ifdef CONFIG_PCI_MSI
+	msi_init(pp);
+#endif
+	/*
+	 * initialize INTX chip here only. MSI chip will be
+	 * initialized dynamically.
+	 */
+	for (i = 0; i < NUM_INTX_IRQS; i++) {
+		irq_set_chip_and_handler(pp->virt_irq_base + i, &intx_chip,
+				handle_simple_irq);
+		set_irq_flags(pp->virt_irq_base + i, IRQF_VALID);
+		irq_set_chip_data(pp->virt_irq_base + i, pp);
+	}
+
+	/* Enable INTX interrupt */
+	writel(readl(&app_reg->int_mask) | INTA_CTRL_INT
+			| INTB_CTRL_INT	| INTC_CTRL_INT
+			| INTD_CTRL_INT, &app_reg->int_mask);
+}
+
+static int patch_txdetectrx_spear1340(struct pcie_port *pp)
+{
+	void __iomem *miphy = pp->va_phy_base;
+	struct pcie_app_reg *app_reg = pp->va_app_base;
+	int ucount = 0;
+	u32 tempa;
+	u8 tempm;
+
+	tempa = readl(&app_reg->app_status_1);
+	/* till ltsmm state is not L0 */
+	while ((tempa & 0x3F) != 0x11) {
+		while (((tempa & 0x3F) == 0) || ((tempa & 0x3F) == 1)) {
+			tempm = readb(miphy + 0x20);
+			tempm &= ~0x3;
+			writeb(tempm, miphy + 0x20);
+
+			writeb(0, miphy + 0x21);
+
+			tempm = readb(miphy + 0x16);
+			tempm &= ~(1 << 3);
+			writeb(tempm, miphy + 0x16);
+
+			tempm = readb(miphy + 0x12);
+			tempm &= ~0x3;
+			writeb(tempm, miphy + 0x12);
+
+			tempm = readb(miphy + 0x10);
+			tempm |= 0x1;
+			writeb(tempm, miphy + 0x10);
+
+			tempa = readl(&app_reg->app_status_1);
+
+			ucount++;
+			udelay(1);
+			if (ucount > MAX_LINK_UP_WAIT_MS * 100000)
+				return -ECONNRESET;
+		}
+		tempm = readb(miphy + 0x10);
+		tempm &= ~0x1;
+		writeb(tempm, miphy + 0x10);
+
+		tempa = readl(&app_reg->app_status_1);
+	}
+
+	return 0;
+}
+
+void __iomem *spear13xx_pcie_io_base(unsigned long addr)
+{
+	int controller = (addr - PCIBIOS_MIN_IO) / IO_SIZE_PER_PORT;
+	struct pcie_port *pp;
+
+	pp = controller_to_port(controller);
+
+	return pp->io_base;
+}
+
+static void pcie_host_init(struct pcie_port *pp)
+{
+	struct pcie_port_info *config = &pp->config;
+	void __iomem *dbi_base = pp->va_dbi_base;
+	struct pcie_app_reg *app_reg = pp->va_app_base;
+	u32 exp_cap_off = PCI_CAP_ID_EXP_OFFSET;
+	u32 val;
+
+	/* Keep first 64K for IO */
+	pp->io_base = pp->base;
+	pp->mem_base = pp->io_base + config->io_size;
+	pp->cfg0_base = pp->mem_base + config->mem_size;
+	pp->cfg1_base = pp->cfg0_base + config->cfg0_size;
+
+	/*
+	 * setup registers for inbound translation. Fix viewport 0 for
+	 * Memory and viewport 1 for IO transaction
+	 */
+
+	/* Program viewport 0 : INBOUND : MEMORY */
+	val = PCIE_ATU_REGION_INBOUND | (0 & 0xF);
+	writel(val, dbi_base + PCIE_ATU_VIEWPORT);
+	writel(PCIE_ATU_TYPE_MEM, dbi_base + PCIE_ATU_CR1);
+	val = PCIE_ATU_ENABLE | PCIE_ATU_BAR_MODE_ENABLE;
+	writel(val, dbi_base + PCIE_ATU_CR2);
+
+	/* program first 256 MB as inbound address */
+	writel(0, dbi_base + PCIE_ATU_LOWER_BASE);
+	writel(0, dbi_base + PCIE_ATU_UPPER_BASE);
+	writel(config->in_mem_size - 1, dbi_base + PCIE_ATU_LIMIT);
+	writel(0, dbi_base + PCIE_ATU_LOWER_TARGET);
+	writel(0, dbi_base + PCIE_ATU_UPPER_TARGET);
+
+	/* Program viewport 1 : INBOUND : IO */
+	val = PCIE_ATU_REGION_INBOUND | (1 & 0xF);
+	writel(val, dbi_base + PCIE_ATU_VIEWPORT);
+	writel(PCIE_ATU_TYPE_IO, dbi_base + PCIE_ATU_CR1);
+	val = PCIE_ATU_ENABLE | PCIE_ATU_BAR_MODE_ENABLE;
+	writel(val, dbi_base + PCIE_ATU_CR2);
+
+	/* program first 256 MB as inbound address */
+	writel(0, dbi_base + PCIE_ATU_LOWER_BASE);
+	writel(0, dbi_base + PCIE_ATU_UPPER_BASE);
+	writel(config->in_mem_size - 1, dbi_base + PCIE_ATU_LIMIT);
+	writel(0, dbi_base + PCIE_ATU_LOWER_TARGET);
+	writel(0, dbi_base + PCIE_ATU_UPPER_TARGET);
+
+	pcie_wr_own_conf(pp, PCIE_BAR0_MASK_REG, 4,
+			(config->in_mem_size - 1));
+	pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0);
+
+	/*
+	 * this controller support only 128 bytes read size, however its
+	 * default value in capability register is 512 bytes. So force
+	 * it to 128 here.
+	 */
+
+	pcie_rd_own_conf(pp, exp_cap_off + PCI_EXP_DEVCTL, 4, &val);
+	val &= ~PCI_EXP_DEVCTL_READRQ;
+	pcie_wr_own_conf(pp, exp_cap_off + PCI_EXP_DEVCTL, 4, val);
+
+	/* program correct class for RC */
+	pcie_rd_own_conf(pp, PCI_CLASS_REVISION, 4, &val);
+	val &= 0xFFFF;
+	val |= (PCI_CLASS_BRIDGE_PCI << 16);
+	pcie_wr_own_conf(pp, PCI_CLASS_REVISION, 4, val);
+
+	/* program vid and did for RC */
+	pcie_wr_own_conf(pp, PCI_VENDOR_ID, 2, 0x104A);
+	pcie_wr_own_conf(pp, PCI_DEVICE_ID, 2, 0xCD80);
+
+	/* if is_gen1 is set then handle it */
+	if (pp->config.is_gen1) {
+		pcie_rd_own_conf(pp, exp_cap_off + PCI_EXP_LNKCAP, 4, &val);
+		if ((val & 0xF) != 1) {
+			val &= ~((u32)0xF);
+			val |= 1;
+			pcie_wr_own_conf(pp, exp_cap_off + PCI_EXP_LNKCAP, 4,
+					val);
+		}
+
+		pcie_rd_own_conf(pp, exp_cap_off + PCI_EXP_LNKCTL2, 4, &val);
+		if ((val & 0xF) != 1) {
+			val &= ~((u32)0xF);
+			val |= 1;
+			pcie_wr_own_conf(pp, exp_cap_off + PCI_EXP_LNKCTL2, 4,
+					val);
+		}
+	} else {
+		pcie_rd_own_conf(pp, PCIE_PORT_LOGIC, 4, &val);
+		val |= (1 << PORT_LOGIC_SPD_CHANGE_ID);
+		pcie_wr_own_conf(pp, PCIE_PORT_LOGIC, 4, val);
+	}
+
+	/* set max trial before lock failure */
+	writeb(0xC0, pp->va_phy_base + 0x85);
+	/* set max trial before lock failure */
+	writeb(0x01, pp->va_phy_base + 0x86);
+
+	/* txdetect RX settings for SPEAr1310 */
+	if (of_machine_is_compatible("st,spear1310"))
+		writeb(0x00, pp->va_phy_base + 0x16);
+
+	writel(DEVICE_TYPE_RC | (1 << MISCTRL_EN_ID)
+			| (1 << APP_LTSSM_ENABLE_ID)
+			| ((u32)1 << REG_TRANSLATION_ENABLE),
+			&app_reg->app_ctrl_0);
+
+	/* txdetect RX settings for SPEAr1340 */
+	if (of_machine_is_compatible("st,spear1340"))
+		patch_txdetectrx_spear1340(pp);
+
+	pcie_irq_init(pp);
+}
+
+static void pcie_host_exit(struct pcie_port *pp)
+{
+	struct pcie_app_reg *app_reg = pp->va_app_base;
+
+	writel(0, &app_reg->app_ctrl_0);
+
+}
+
+static int add_pcie_port(struct pcie_port *pp, struct platform_device *pdev)
+{
+	struct resource *base;
+	struct resource *dbi_base;
+	struct resource *phy_base;
+	int virt_irq_base;
+	struct device_node *np = pdev->dev.of_node;
+	struct irq_domain *irq_domain;
+	int num_virt_irqs = NUM_INTX_IRQS;
+
+	dbi_base = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!dbi_base) {
+		dev_err(&pdev->dev, "couldn't get dbi base resource\n");
+		return -EINVAL;
+	}
+	if (!devm_request_mem_region(&pdev->dev, dbi_base->start,
+				resource_size(dbi_base), pdev->name)) {
+		dev_err(&pdev->dev, "dbi base resource is busy\n");
+		return -EBUSY;
+	}
+
+	pp->dbi_base = (void __iomem *)dbi_base->start;
+	pp->va_dbi_base = devm_ioremap(&pdev->dev, dbi_base->start,
+			resource_size(dbi_base));
+	if (!pp->va_dbi_base) {
+		dev_err(&pdev->dev, "error with ioremap\n");
+		return -ENOMEM;
+	}
+
+	/* App base starts from offset 0x2000 of dbi base */
+	pp->app_base = pp->dbi_base + 0x2000;
+	pp->va_app_base = pp->va_dbi_base + 0x2000;
+
+	phy_base = platform_get_resource(pdev, IORESOURCE_MEM, 2);
+	if (!phy_base) {
+		dev_err(&pdev->dev, "couldn't get phy base resource\n");
+		return -EINVAL;
+	}
+	if (!devm_request_mem_region(&pdev->dev, phy_base->start,
+				resource_size(phy_base), pdev->name)) {
+		dev_err(&pdev->dev, "phy base resource is busy\n");
+		return -EBUSY;
+	}
+
+	pp->phy_base = (void __iomem *)phy_base->start;
+	pp->va_phy_base = devm_ioremap(&pdev->dev, phy_base->start,
+			resource_size(phy_base));
+	if (!pp->va_phy_base) {
+		dev_err(&pdev->dev, "error with ioremap\n");
+		return -ENOMEM;
+	}
+
+	base = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!base) {
+		dev_err(&pdev->dev, "couldn't get base resource\n");
+		return -EINVAL;
+	}
+
+	pp->base = (void __iomem *)base->start;
+
+	pp->root_bus_nr = -1;
+
+#ifdef CONFIG_PCI_MSI
+	num_virt_irqs += NUM_MSI_IRQS;
+#endif
+
+	virt_irq_base = irq_alloc_descs(-1, 0, num_virt_irqs, 0);
+	if (IS_ERR_VALUE(virt_irq_base)) {
+		dev_err(&pdev->dev, "irq desc alloc failed\n");
+		return -ENXIO;
+	}
+
+	irq_domain = irq_domain_add_legacy(np, num_virt_irqs, virt_irq_base,
+			0, &irq_domain_simple_ops, NULL);
+	if (!irq_domain) {
+		dev_err(&pdev->dev, "irq domain init failed\n");
+		irq_free_descs(virt_irq_base, 32);
+		return -ENXIO;
+	}
+
+	pp->virt_irq_base = irq_find_mapping(irq_domain, 0);
+
+	spin_lock_init(&pp->conf_lock);
+	if (pcie_link_up(pp->va_app_base)) {
+		dev_info(&pdev->dev, "link up\n");
+	} else {
+		dev_info(&pdev->dev, "link down\n");
+		pcie_host_init(pp);
+		pp->va_cfg0_base = devm_ioremap(&pdev->dev,
+				(resource_size_t)pp->cfg0_base,
+					pp->config.cfg0_size);
+		if (!pp->va_cfg0_base) {
+			dev_err(&pdev->dev, "error with ioremap in function\n");
+			return -ENOMEM;
+		}
+		pp->va_cfg1_base = devm_ioremap(&pdev->dev,
+				(resource_size_t)pp->cfg1_base,
+					pp->config.cfg1_size);
+		if (!pp->va_cfg1_base) {
+			dev_err(&pdev->dev, "error with ioremap\n");
+			return -ENOMEM;
+		}
+
+	}
+
+	return 0;
+}
+
+static int __devinit pcie_probe(struct platform_device *pdev)
+{
+	int err;
+	struct clk *clk;
+	struct pcie_port *pp;
+	struct device_node *np = pdev->dev.of_node;
+
+	if (!pdev->dev.platform_data)
+		return -EINVAL;
+
+	pp = devm_kzalloc(&pdev->dev, sizeof(*pp), GFP_KERNEL);
+	if (!pp) {
+		dev_err(&pdev->dev, "no memory for pcie port\n");
+		return -ENOMEM;
+	}
+
+	memcpy(&pp->config, pdev->dev.platform_data, (sizeof(pp->config)));
+	pp->config.io_size = IO_SIZE_PER_PORT;
+	of_property_read_u32(np, "pcie-host,is_host", &pp->config.is_host);
+	of_property_read_u32(np, "pcie-host,is_gen1", &pp->config.is_gen1);
+	of_property_read_u32(np, "pcie-host,cfg0_size", &pp->config.cfg0_size);
+	of_property_read_u32(np, "pcie-host,cfg1_size", &pp->config.cfg1_size);
+	of_property_read_u32(np, "pcie-host,mem_size", &pp->config.mem_size);
+	of_property_read_u32(np, "pcie-host,msg_size", &pp->config.msg_size);
+	of_property_read_u32(np, "pcie-host,in_mem_size",
+			&pp->config.in_mem_size);
+
+	if (!pp->config.is_host)
+		return -EINVAL;
+
+	err = pp->config.clk_init(pp);
+	if (err)
+		goto free_mem;
+
+	clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(clk)) {
+		dev_err(&pdev->dev, "couldn't get clk for pcie\n");
+		err = PTR_ERR(clk);
+		goto free_mem;
+	}
+
+	if (clk_prepare_enable(clk)) {
+		dev_err(&pdev->dev, "couldn't enable clk for pcie\n");
+		err = -EINVAL;
+		goto clk_put;
+	}
+
+	pp->irq = platform_get_irq(pdev, 0);
+	if (pp->irq < 0) {
+		err = -EINVAL;
+		goto clk_put;
+	}
+
+	if (!add_pcie_port(pp, pdev)) {
+		pp->controller = pci.nr_controllers;
+		pci.nr_controllers++;
+		list_add_tail(&pp->next, &pcie_port_list);
+		return 0;
+	}
+
+clk_put:
+	clk_put(clk);
+free_mem:
+	kfree(pp);
+
+	return err;
+}
+
+static int __devinit pcie_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+#ifdef CONFIG_PM
+int spear_pcie_suspend(void)
+{
+	struct pcie_port *pp;
+	int i;
+
+	for (i = 0; i < pci.nr_controllers; i++) {
+		pp = controller_to_port(i);
+		if (pcie_link_up(pp->va_app_base)) {
+			pcie_host_exit(pp);
+			pp->config.clk_exit(pp);
+			pp->susp_state = 1;
+		}
+	}
+
+	return 0;
+}
+
+int spear_pcie_resume(void)
+{
+	struct pcie_port *pp;
+	int i;
+
+	for (i = 0; i < pci.nr_controllers; i++) {
+		pp = controller_to_port(i);
+		if (pp->susp_state) {
+			pp->config.clk_init(pp);
+			pp->susp_state = 0;
+			if (!pcie_link_up(pp->va_app_base))
+				pcie_host_init(pp);
+		}
+	}
+
+	return 0;
+}
+#endif
+
+static const struct of_device_id pcie_of_match[] = {
+	{ .compatible = "st,pcie-host", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, pcie_of_match);
+
+static struct platform_driver pcie_driver = {
+	.driver = {
+		.name	= "pcie",
+		.owner = THIS_MODULE,
+		.of_match_table = pcie_of_match,
+	},
+	.probe = pcie_probe,
+	.remove = __devexit_p(pcie_remove),
+
+};
+
+static int
+pcie_abort(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
+{
+	unsigned long pc = instruction_pointer(regs);
+	unsigned long instr = *(unsigned long *)(pc - 8);
+
+	WARN_ONCE(1, "pcie abort\n");
+	/*
+	 * If the instruction being executed was a read,
+	 * make it look like it read all-ones.
+	 */
+	if ((instr & 0x0c100000) == 0x04100000) {
+		int reg = (instr >> 12) & 15;
+		unsigned long val;
+
+		if (instr & 0x00400000)
+			val = 255;
+		else
+			val = -1;
+
+		regs->uregs[reg] = val;
+		regs->ARM_pc += 4;
+
+		return 0;
+	}
+
+	return 1;
+}
+
+static int __init pcie_init(void)
+{
+	hook_fault_code(16+6, pcie_abort, SIGBUS, 0,
+			"imprecise external abort");
+
+	INIT_LIST_HEAD(&pcie_port_list);
+	platform_driver_probe(&pcie_driver, pcie_probe);
+
+	if (pci.nr_controllers) {
+		pci_common_init(&pci);
+		pci_assign_unassigned_resources();
+		pr_info("pcie init successful\n");
+	}
+
+	return 0;
+}
+subsys_initcall(pcie_init);
+
+static void __exit pcie_exit(void)
+{
+	platform_driver_unregister(&pcie_driver);
+}
+module_exit(pcie_exit);
-- 
1.7.5.4

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

* [PATCH 04/15] SPEAr13xx: Add PCIe Root Complex driver support
@ 2012-10-29  7:01   ` Pratyush Anand
  0 siblings, 0 replies; 56+ messages in thread
From: Pratyush Anand @ 2012-10-29  7:01 UTC (permalink / raw)
  To: arnd, shiraz.hashim, viresh.linux
  Cc: spear-devel, linux-pci, devicetree-discuss, olof, Pratyush Anand

SPEAr13xx has dual mode PCIe controller which can be used as Root
Complex as well as Endpoint. This driver supports RC mode of the
controller.

If CONFIG_PCI_MSI is defined then support of MSI interrupt for
downstream  PCIe devices will be enabled.

If CONFIG_PM is defined then it supports suspend/resume functionality.

Signed-off-by: Pratyush Anand <pratyush.anand@st.com>
---
 arch/arm/mach-spear13xx/include/mach/pcie.h |  233 ++++++
 arch/arm/mach-spear13xx/pcie.c              | 1145 +++++++++++++++++++++++++++
 2 files changed, 1378 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-spear13xx/include/mach/pcie.h
 create mode 100644 arch/arm/mach-spear13xx/pcie.c

diff --git a/arch/arm/mach-spear13xx/include/mach/pcie.h b/arch/arm/mach-spear13xx/include/mach/pcie.h
new file mode 100644
index 0000000..39bff4f
--- /dev/null
+++ b/arch/arm/mach-spear13xx/include/mach/pcie.h
@@ -0,0 +1,233 @@
+/*
+ * arch/arm/mach-spear13xx/include/mach/pcie.h
+ *
+ * Copyright (C) 2010-2012 ST Microelectronics
+ * Pratyush Anand <pratyush.anand@st.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+#ifndef __MACH_PCIE_H
+#define __MACH_PCIE_H
+
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+#include <linux/types.h>
+#include <linux/clk.h>
+
+#define MAX_LINK_UP_WAIT_MS	2
+/* Max port defined can be changed if required */
+#define MAX_PCIE_PORT_SUPPORTED	3
+struct pcie_port;
+
+struct pcie_port_info {
+	u32	is_host;
+	u32	is_gen1;
+	u32	cfg0_size;
+	u32	cfg1_size;
+	u32	mem_size;
+	u32	msg_size;
+	u32	in_mem_size;
+	u32	io_size;
+	int (*clk_init)(struct pcie_port *pp);
+	int (*clk_exit)(struct pcie_port *pp);
+};
+
+struct pcie_port {
+	u8			controller;
+	u8			root_bus_nr;
+	void __iomem		*dbi_base;
+	void __iomem		*va_dbi_base;
+	void __iomem		*app_base;
+	void __iomem		*va_app_base;
+	void __iomem		*base;
+	void __iomem		*phy_base;
+	void __iomem		*va_phy_base;
+	void __iomem		*cfg0_base;
+	void __iomem		*va_cfg0_base;
+	void __iomem		*cfg1_base;
+	void __iomem		*va_cfg1_base;
+	void __iomem		*mem_base;
+	void __iomem		*io_base;
+	spinlock_t		conf_lock;
+	char			mem_space_name[16];
+	char			io_space_name[16];
+	struct resource		res[2];
+	struct pcie_port_info	config;
+	struct list_head	next;
+	struct clk		*clk;
+	int			irq;
+	int			virt_irq_base;
+	int			susp_state;
+};
+
+/* synopsis specific PCIE configuration registers*/
+#define PCIE_PORT_LOGIC			0x80C
+#define PORT_LOGIC_SPD_CHANGE_ID	17
+
+#define PCIE_MSI_ADDR_LO		0x820
+#define PCIE_MSI_ADDR_HI		0x824
+#define PCIE_MSI_INTR0_ENABLE		0x828
+#define PCIE_MSI_INTR0_MASK		0x82C
+#define PCIE_MSI_INTR0_STATUS		0x830
+
+#define PCIE_ATU_VIEWPORT		0x900
+#define PCIE_ATU_REGION_INBOUND		(1 << 31)
+#define PCIE_ATU_REGION_OUTBOUND	(0 << 31)
+#define PCIE_ATU_CR1			0x904
+#define PCIE_ATU_TYPE_MEM		0
+#define PCIE_ATU_TYPE_IO		2
+#define PCIE_ATU_TYPE_CFG0		4
+#define PCIE_ATU_TYPE_CFG1		5
+#define PCIE_ATU_CR2			0x908
+#define PCIE_ATU_ENABLE			(1 << 31)
+#define PCIE_ATU_BAR_MODE_ENABLE	(1 << 30)
+#define PCIE_ATU_LOWER_BASE		0x90C
+#define PCIE_ATU_UPPER_BASE		0x910
+#define PCIE_ATU_LIMIT			0x914
+#define PCIE_ATU_LOWER_TARGET		0x918
+#define PCIE_ATU_UPPER_TARGET		0x91C
+
+/*BAR MASK registers*/
+#define PCIE_BAR0_MASK_REG		0x1010
+
+struct pcie_app_reg {
+	u32	app_ctrl_0;		/*cr0*/
+	u32	app_ctrl_1;		/*cr1*/
+	u32	app_status_0;		/*cr2*/
+	u32	app_status_1;		/*cr3*/
+	u32	msg_status;		/*cr4*/
+	u32	msg_payload;		/*cr5*/
+	u32	int_sts;		/*cr6*/
+	u32	int_clr;		/*cr7*/
+	u32	int_mask;		/*cr8*/
+	u32	mst_bmisc;		/*cr9*/
+	u32	phy_ctrl;		/*cr10*/
+	u32	phy_status;		/*cr11*/
+	u32	cxpl_debug_info_0;	/*cr12*/
+	u32	cxpl_debug_info_1;	/*cr13*/
+	u32	ven_msg_ctrl_0;		/*cr14*/
+	u32	ven_msg_ctrl_1;		/*cr15*/
+	u32	ven_msg_data_0;		/*cr16*/
+	u32	ven_msg_data_1;		/*cr17*/
+	u32	ven_msi_0;		/*cr18*/
+	u32	ven_msi_1;		/*cr19*/
+	u32	mst_rmisc;		/*cr 20*/
+	u32	slv_awmisc;		/*cr 21*/
+	u32	slv_armisc;		/*cr 22*/
+	u32	pom0_mem_addr_start;	/*cr23*/
+	u32	pom1_mem_addr_start;	/*cr24*/
+	u32	pom_io_addr_start;	/*cr25*/
+	u32	pom_cfg0_addr_start;	/*cr26*/
+	u32	pom_cfg1_addr_start;	/*cr27*/
+	u32	in0_mem_addr_start;	/*cr28*/
+	u32	in1_mem_addr_start;	/*cr29*/
+	u32	in_io_addr_start;	/*cr30*/
+	u32	in_cfg0_addr_start;	/*cr31*/
+	u32	in_cfg1_addr_start;	/*cr32*/
+	u32	in_msg_addr_start;	/*cr33*/
+	u32	in0_mem_addr_limit;	/*cr34*/
+	u32	in1_mem_addr_limit;	/*cr35*/
+	u32	in_io_addr_limit;	/*cr36*/
+	u32	in_cfg0_addr_limit;	/*cr37*/
+	u32	in_cfg1_addr_limit;	/*cr38*/
+	u32	in_msg_addr_limit;	/*cr39*/
+	u32	mem0_addr_offset_limit;	/*cr40*/
+	u32	pim0_mem_addr_start;	/*cr41*/
+	u32	pim1_mem_addr_start;	/*cr42*/
+	u32	pim_io_addr_start;	/*cr43*/
+	u32	pim_rom_addr_start;	/*cr44*/
+};
+
+/*CR0 ID*/
+#define RX_LANE_FLIP_EN_ID			0
+#define TX_LANE_FLIP_EN_ID			1
+#define SYS_AUX_PWR_DET_ID			2
+#define APP_LTSSM_ENABLE_ID			3
+#define SYS_ATTEN_BUTTON_PRESSED_ID		4
+#define SYS_MRL_SENSOR_STATE_ID			5
+#define SYS_PWR_FAULT_DET_ID			6
+#define SYS_MRL_SENSOR_CHGED_ID			7
+#define SYS_PRE_DET_CHGED_ID			8
+#define SYS_CMD_CPLED_INT_ID			9
+#define APP_INIT_RST_0_ID			11
+#define APP_REQ_ENTR_L1_ID			12
+#define APP_READY_ENTR_L23_ID			13
+#define APP_REQ_EXIT_L1_ID			14
+#define DEVICE_TYPE_EP				(0 << 25)
+#define DEVICE_TYPE_LEP				(1 << 25)
+#define DEVICE_TYPE_RC				(4 << 25)
+#define SYS_INT_ID				29
+#define MISCTRL_EN_ID				30
+#define REG_TRANSLATION_ENABLE			31
+
+/*CR1 ID*/
+#define APPS_PM_XMT_TURNOFF_ID			2
+#define APPS_PM_XMT_PME_ID			5
+
+/*CR3 ID*/
+#define XMLH_LTSSM_STATE_ID			0
+#define XMLH_LTSSM_STATE_L0	((u32)0x11 << XMLH_LTSSM_STATE_ID)
+#define XMLH_LTSSM_STATE_MASK	((u32)0x3F << XMLH_LTSSM_STATE_ID)
+#define XMLH_LINK_UP_ID				6
+
+/*CR4 ID*/
+#define CFG_MSI_EN_ID				18
+
+/*CR6*/
+#define INTA_CTRL_INT				(1 << 7)
+#define INTB_CTRL_INT				(1 << 8)
+#define INTC_CTRL_INT				(1 << 9)
+#define INTD_CTRL_INT				(1 << 10)
+#define MSI_CTRL_INT				(1 << 26)
+
+/*CR19 ID*/
+#define VEN_MSI_REQ_ID				11
+#define VEN_MSI_FUN_NUM_ID			8
+#define VEN_MSI_TC_ID				5
+#define VEN_MSI_VECTOR_ID			0
+#define VEN_MSI_REQ_EN		((u32)0x1 << VEN_MSI_REQ_ID)
+#define VEN_MSI_FUN_NUM_MASK	((u32)0x7 << VEN_MSI_FUN_NUM_ID)
+#define VEN_MSI_TC_MASK		((u32)0x7 << VEN_MSI_TC_ID)
+#define VEN_MSI_VECTOR_MASK	((u32)0x1F << VEN_MSI_VECTOR_ID)
+
+/*CE21-22 ID*/
+/*ID definition of ARMISC*/
+#define AXI_OP_TYPE_ID				0
+#define AXI_OP_BCM_ID				5
+#define AXI_OP_EP_ID				6
+#define AXI_OP_TD_ID				7
+#define AXI_OP_ATTRIBUTE_ID			8
+#define AXI_OP_TC_ID				10
+#define AXI_OP_MSG_CODE_ID			13
+#define AXI_OP_DBI_ACCESS_ID			21
+#define AXI_OP_TYPE_MASK			0x1F
+#define AXI_OP_TYPE_MEM_RDRW			0
+#define AXI_OP_TYPE_MEM_RDRW_LOCKED		1
+#define AXI_OP_TYPE_IO_RDRW			2
+#define AXI_OP_TYPE_CONFIG_RDRW_TYPE0		4
+#define AXI_OP_TYPE_CONFIG_RDRW_TYPE1		5
+#define AXI_OP_TYPE_MSG_REQ			16
+#define AXI_OP_TYPE_COMPLETION			10
+#define AXI_OP_TYPE_COMPLETION_LOCKED		11
+#define AXI_OP_TYPE_DBI_ELBI_ENABLE		1
+
+#define PCI_CAP_ID_EXP_OFFSET			0x70
+
+#define PCIE_IS_HOST		1
+#define PCIE_IS_DEVICE		0
+
+#define PCIE_IS_GEN1		1
+#define PCIE_IS_GEN2		0
+
+#define NUM_INTX_IRQS		4
+/*
+ * Maximum number of MSI IRQs can be 256 per controller. But keep it 64
+ * as of now. Probably we will never need more than 64. If needed, then
+ * Increment it in multiple of 32.
+ */
+#define NUM_MSI_IRQS		64
+
+#define	IO_SIZE_PER_PORT	SZ_16K
+#endif
diff --git a/arch/arm/mach-spear13xx/pcie.c b/arch/arm/mach-spear13xx/pcie.c
new file mode 100644
index 0000000..bfed3b7
--- /dev/null
+++ b/arch/arm/mach-spear13xx/pcie.c
@@ -0,0 +1,1145 @@
+/*
+ * arch/arm/mach-spear13xx/pcie.c
+ *
+ * PCIe functions for SPEAr13XX PCIe Host controllers
+ *
+ * Copyright (C) 2010-2012 ST Microelectronics
+ * Pratyush Anand <pratyush.anand@st.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/msi.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/pci.h>
+#include <linux/pci_regs.h>
+#include <linux/platform_device.h>
+#include <linux/resource.h>
+#include <linux/slab.h>
+#include <asm/mach/irq.h>
+#include <asm/signal.h>
+#include <mach/pcie.h>
+
+static struct list_head	pcie_port_list;
+static struct hw_pci pci;
+
+static inline int cfg_read(void *addr, int where, int size, u32 *val)
+{
+	*val = readl(addr);
+
+	if (size == 1)
+		*val = (*val >> (8 * (where & 3))) & 0xff;
+	else if (size == 2)
+		*val = (*val >> (8 * (where & 3))) & 0xffff;
+	else if (size != 4)
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static inline int cfg_write(void *addr, int where, int size, u32 val)
+{
+	if (size == 4)
+		writel(val, addr);
+	else if (size == 2)
+		writew(val, addr + (where & 2));
+	else if (size == 1)
+		writeb(val, addr + (where & 3));
+	else
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int pcie_rd_own_conf(struct pcie_port *pp, int where, int size,
+		u32 *val)
+{
+	return cfg_read(pp->va_dbi_base + (where & ~0x3), where, size, val);
+}
+
+static int pcie_wr_own_conf(struct pcie_port *pp, int where, int size,
+		u32 val)
+{
+	return cfg_write(pp->va_dbi_base + (where & ~0x3), where, size, val);
+}
+
+static void spear_pcie_prog_viewport_cfg0(struct pcie_port *pp, u32 busdev)
+{
+	u32 val;
+	void __iomem *dbi_base = pp->va_dbi_base;
+
+	/* Program viewport 0 : OUTBOUND : CFG0 */
+	val = PCIE_ATU_REGION_OUTBOUND | (0 & 0xF);
+	writel(val, dbi_base + PCIE_ATU_VIEWPORT);
+	writel(PCIE_ATU_TYPE_CFG0, dbi_base + PCIE_ATU_CR1);
+	val = PCIE_ATU_ENABLE;
+	writel(val, dbi_base + PCIE_ATU_CR2);
+	writel(pp->cfg0_base, dbi_base + PCIE_ATU_LOWER_BASE);
+	writel(0, dbi_base + PCIE_ATU_UPPER_BASE);
+	writel(pp->cfg0_base + pp->config.cfg0_size - 1,
+			dbi_base + PCIE_ATU_LIMIT);
+	writel(busdev, dbi_base + PCIE_ATU_LOWER_TARGET);
+	writel(0, dbi_base + PCIE_ATU_UPPER_TARGET);
+}
+
+static void spear_pcie_prog_viewport_cfg1(struct pcie_port *pp, u32 busdev)
+{
+	u32 val;
+	void __iomem *dbi_base = pp->va_dbi_base;
+
+	/* Program viewport 1 : OUTBOUND : CFG1 */
+	val = PCIE_ATU_REGION_OUTBOUND | (1 & 0xF);
+	writel(val, dbi_base + PCIE_ATU_VIEWPORT);
+	writel(PCIE_ATU_TYPE_CFG1, dbi_base + PCIE_ATU_CR1);
+	val = PCIE_ATU_ENABLE;
+	writel(val, dbi_base + PCIE_ATU_CR2);
+	writel(pp->cfg1_base, dbi_base + PCIE_ATU_LOWER_BASE);
+	writel(0, dbi_base + PCIE_ATU_UPPER_BASE);
+	writel(pp->cfg1_base + pp->config.cfg1_size - 1,
+			dbi_base + PCIE_ATU_LIMIT);
+	writel(busdev, dbi_base + PCIE_ATU_LOWER_TARGET);
+	writel(0, dbi_base + PCIE_ATU_UPPER_TARGET);
+}
+
+static void spear_pcie_prog_viewport_mem(struct pcie_port *pp)
+{
+	u32 val;
+	void __iomem *dbi_base = pp->va_dbi_base;
+
+	/* Program viewport 0 : OUTBOUND : MEM */
+	val = PCIE_ATU_REGION_OUTBOUND | (0 & 0xF);
+	writel(val, dbi_base + PCIE_ATU_VIEWPORT);
+	writel(PCIE_ATU_TYPE_MEM, dbi_base + PCIE_ATU_CR1);
+	val = PCIE_ATU_ENABLE;
+	writel(val, dbi_base + PCIE_ATU_CR2);
+	writel(pp->mem_base, dbi_base + PCIE_ATU_LOWER_BASE);
+	writel(0, dbi_base + PCIE_ATU_UPPER_BASE);
+	writel(pp->mem_base + pp->config.mem_size - 1,
+			dbi_base + PCIE_ATU_LIMIT);
+	writel(pp->mem_base, dbi_base + PCIE_ATU_LOWER_TARGET);
+	writel(0, dbi_base + PCIE_ATU_UPPER_TARGET);
+}
+
+static void spear_pcie_prog_viewport_io(struct pcie_port *pp)
+{
+	u32 val;
+	void __iomem *dbi_base = pp->va_dbi_base;
+
+	/* Program viewport 1 : OUTBOUND : IO */
+	val = PCIE_ATU_REGION_OUTBOUND | (1 & 0xF);
+	writel(val, dbi_base + PCIE_ATU_VIEWPORT);
+	writel(PCIE_ATU_TYPE_IO, dbi_base + PCIE_ATU_CR1);
+	val = PCIE_ATU_ENABLE;
+	writel(val, dbi_base + PCIE_ATU_CR2);
+	writel(pp->io_base, dbi_base + PCIE_ATU_LOWER_BASE);
+	writel(0, dbi_base + PCIE_ATU_UPPER_BASE);
+	writel(pp->io_base + pp->config.io_size - 1,
+			dbi_base + PCIE_ATU_LIMIT);
+	writel(pp->io_base, dbi_base + PCIE_ATU_LOWER_TARGET);
+	writel(0, dbi_base + PCIE_ATU_UPPER_TARGET);
+}
+
+static int pcie_rd_other_conf(struct pcie_port *pp, struct pci_bus *bus,
+		u32 devfn, int where, int size, u32 *val)
+{
+	int ret = PCIBIOS_SUCCESSFUL;
+	u32 address, busdev;
+
+	busdev = (bus->number << 24) | (PCI_SLOT(devfn) << 19);
+	address = (PCI_FUNC(devfn) << 16) | (where & 0xFFFC);
+
+	if (bus->parent->number == pp->root_bus_nr) {
+		spear_pcie_prog_viewport_cfg0(pp, busdev);
+		ret = cfg_read(pp->va_cfg0_base + address, where, size, val);
+		spear_pcie_prog_viewport_mem(pp);
+	} else {
+		spear_pcie_prog_viewport_cfg1(pp, busdev);
+		ret = cfg_read(pp->va_cfg1_base + address, where, size, val);
+		spear_pcie_prog_viewport_io(pp);
+	}
+
+	return ret;
+}
+
+static int pcie_wr_other_conf(struct pcie_port *pp, struct pci_bus *bus,
+		u32 devfn, int where, int size, u32 val)
+{
+	int ret = PCIBIOS_SUCCESSFUL;
+	u32 address, busdev;
+
+	busdev = (bus->number << 24) | (PCI_SLOT(devfn) << 19);
+	address = (PCI_FUNC(devfn) << 16) | (where & 0xFFFC);
+
+	if (bus->parent->number == pp->root_bus_nr) {
+		spear_pcie_prog_viewport_cfg0(pp, busdev);
+		ret = cfg_write(pp->va_cfg0_base + address, where, size, val);
+		spear_pcie_prog_viewport_mem(pp);
+	} else {
+		spear_pcie_prog_viewport_cfg1(pp, busdev);
+		ret = cfg_write(pp->va_cfg1_base + address, where, size, val);
+		spear_pcie_prog_viewport_io(pp);
+	}
+
+	return ret;
+}
+
+static struct pcie_port *controller_to_port(int controller)
+{
+	struct pcie_port *pp;
+
+	if (controller >= pci.nr_controllers)
+		return NULL;
+
+	list_for_each_entry(pp, &pcie_port_list, next) {
+		if (pp->controller == controller)
+			return pp;
+	}
+	return NULL;
+}
+
+static struct pcie_port *bus_to_port(int bus)
+{
+	int i;
+	int rbus;
+	struct pcie_port *pp;
+
+	for (i = pci.nr_controllers - 1 ; i >= 0; i--) {
+		pp = controller_to_port(i);
+		rbus = pp->root_bus_nr;
+		if (rbus != -1 && rbus <= bus)
+			break;
+	}
+
+	return i >= 0 ? pp : NULL;
+}
+
+#ifdef CONFIG_PCI_MSI
+static DECLARE_BITMAP(msi_irq_in_use[MAX_PCIE_PORT_SUPPORTED],
+		NUM_MSI_IRQS);
+static unsigned int msi_data[MAX_PCIE_PORT_SUPPORTED];
+
+/* MSI int handler */
+static void handle_msi(struct pcie_port *pp)
+{
+	unsigned long val;
+	int i, pos;
+
+	for (i = 0; i < NUM_MSI_IRQS / 32; i++) {
+		pcie_rd_own_conf(pp, PCIE_MSI_INTR0_STATUS + i * 12, 4,
+				(u32 *)&val);
+		if (val) {
+			pos = 0;
+			while ((pos = find_next_bit(&val, 32, pos)) != 32) {
+				generic_handle_irq(pp->virt_irq_base +
+						NUM_INTX_IRQS + (i * 32) + pos);
+				pos++;
+			}
+		}
+		pcie_wr_own_conf(pp, PCIE_MSI_INTR0_STATUS + i * 12, 4, val);
+	}
+}
+
+static void msi_nop(struct irq_data *d)
+{
+	return;
+}
+
+static struct irq_chip msi_chip = {
+	.name = "PCI-MSI",
+	.irq_ack = msi_nop,
+	.irq_enable = unmask_msi_irq,
+	.irq_disable = mask_msi_irq,
+	.irq_mask = mask_msi_irq,
+	.irq_unmask = unmask_msi_irq,
+};
+
+/* Dynamic irq allocate and deallocation */
+static int get_irq(struct msi_desc *desc, int *pos)
+{
+	int res, bit, irq, pos0;
+	u32 val;
+	struct pcie_port *pp = bus_to_port(desc->dev->bus->number);
+
+	if (!pp) {
+		BUG();
+		return -EINVAL;
+	}
+
+	pos0 = find_first_zero_bit(msi_irq_in_use[pp->controller],
+			NUM_MSI_IRQS);
+
+	irq = pp->virt_irq_base + NUM_INTX_IRQS + pos0;
+
+	if (pos0 > NUM_MSI_IRQS)
+		goto no_valid_irq;
+
+	set_bit(pos0, msi_irq_in_use[pp->controller]);
+
+	dynamic_irq_init(irq);
+	irq_set_msi_desc(irq, desc);
+	irq_set_chip_and_handler(irq, &msi_chip, handle_simple_irq);
+	set_irq_flags(irq, IRQF_VALID);
+	irq_set_chip_data(irq, pp);
+
+	/*
+	 * Enable corresponding interrupt on MSI interrupt
+	 * controller.
+	 */
+	res = (pos0 / 32) * 12;
+	bit = pos0 % 32;
+	pcie_rd_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, &val);
+	val |= 1 << bit;
+	pcie_wr_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, val);
+
+	*pos = pos0;
+	return irq;
+
+no_valid_irq:
+	*pos = pos0;
+
+	return -ENOSPC;
+}
+
+static void clean_irq(unsigned int irq)
+{
+	int res, bit, val, pos;
+	struct irq_desc *desc = irq_to_desc(irq);
+	struct msi_desc *msi_desc = irq_desc_get_msi_desc(desc);
+	struct pcie_port *pp = bus_to_port(msi_desc->dev->bus->number);
+
+	if (!pp) {
+		BUG();
+		return;
+	}
+
+	pos = irq - pp->virt_irq_base - NUM_INTX_IRQS;
+
+	dynamic_irq_cleanup(irq);
+
+	clear_bit(pos, msi_irq_in_use[pp->controller]);
+
+	/*
+	 * Disable corresponding interrupt on MSI interrupt
+	 * controller.
+	 */
+	res = (pos / 32) * 12;
+	bit = pos % 32;
+	pcie_rd_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, &val);
+	val &= ~(1 << bit);
+	pcie_wr_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, val);
+}
+
+int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
+{
+	int irq, pos;
+	struct msi_msg msg;
+	struct pcie_port *pp = bus_to_port(pdev->bus->number);
+
+	if (!pp) {
+		BUG();
+		return -EINVAL;
+	}
+
+	irq = get_irq(desc, &pos);
+
+	if (irq < 0)
+		return irq;
+	/*
+	 * An EP will modify lower 8 bits(max) of msi data while
+	 * sending any msi interrupt
+	 */
+	msg.address_hi = 0x0;
+	msg.address_lo = __virt_to_phys((u32)(&msi_data[pp->controller]));
+	msg.data = pos;
+	write_msi_msg(irq, &msg);
+
+	return 0;
+}
+
+void arch_teardown_msi_irq(unsigned int irq)
+{
+	clean_irq(irq);
+}
+
+static void msi_init(struct pcie_port *pp)
+{
+	struct pcie_app_reg *app_reg = pp->va_app_base;
+
+	pcie_wr_own_conf(pp, PCIE_MSI_ADDR_LO, 4,
+			__virt_to_phys((u32)(&msi_data[pp->controller])));
+	pcie_wr_own_conf(pp, PCIE_MSI_ADDR_HI, 4, 0);
+
+	/* Enable MSI interrupt */
+	writel(readl(&app_reg->int_mask) | MSI_CTRL_INT,
+			&app_reg->int_mask);
+}
+#endif
+
+static int __init pcie_setup(int nr, struct pci_sys_data *sys)
+{
+	struct pcie_port *pp;
+
+	pp = controller_to_port(nr);
+
+	if (!pp)
+		return 0;
+
+	pp->root_bus_nr = sys->busnr;
+
+	snprintf(pp->mem_space_name, sizeof(pp->mem_space_name),
+			"PCIe %d MEM", nr);
+	pp->mem_space_name[sizeof(pp->mem_space_name) - 1] = 0;
+	pp->res[0].name = pp->mem_space_name;
+	pp->res[0].start = (resource_size_t)pp->mem_base;
+	pp->res[0].end = pp->res[0].start + pp->config.mem_size - 1;
+	pp->res[0].flags = IORESOURCE_MEM;
+	if (request_resource(&iomem_resource, &pp->res[0]))
+		panic("can't allocate PCIe Mem space");
+	pci_add_resource_offset(&sys->resources, &pp->res[0], sys->mem_offset);
+
+	snprintf(pp->io_space_name, sizeof(pp->io_space_name),
+			"PCIe %d I/O", nr);
+	pp->io_space_name[sizeof(pp->io_space_name) - 1] = 0;
+	pp->res[1].name = pp->io_space_name;
+	pp->res[1].start = PCIBIOS_MIN_IO + nr * pp->config.io_size;
+	pp->res[1].end = pp->res[1].start + (pp->config.io_size - 1);
+	pp->res[1].flags = IORESOURCE_IO;
+	if (request_resource(&ioport_resource, &pp->res[1]))
+		panic("can't allocate PCIe IO space");
+	pci_add_resource_offset(&sys->resources, &pp->res[1], sys->io_offset);
+
+	return 1;
+}
+
+static int pcie_link_up(struct pcie_app_reg *app_reg)
+{
+	int ucount = 0;
+
+	do {
+		if (readl(&app_reg->app_status_1) &
+			((u32)1 << XMLH_LINK_UP_ID))
+			return 1;
+		ucount++;
+		udelay(1);
+	} while (ucount <= MAX_LINK_UP_WAIT_MS * 1000);
+
+	return 0;
+}
+
+static int pcie_valid_config(struct pcie_port *pp, struct pci_bus *bus, int dev)
+{
+	/* If there is no link, then there is no device */
+	if (bus->number != pp->root_bus_nr) {
+		if (!pcie_link_up(pp->va_app_base))
+			return 0;
+	}
+
+	/*
+	 * Don't go out when trying to access non-existing devices
+	 * on the local bus.
+	 * we have only one slot on each root port.
+	 */
+	if (bus->number == pp->root_bus_nr && dev > 0)
+		return 0;
+
+	/*
+	 * do not read more than one device on the bus directly attached
+	 * to RC's (Virtual Bridge's) DS side.
+	 */
+	if (bus->primary == pp->root_bus_nr && dev > 0)
+		return 0;
+
+	return 1;
+}
+
+static int pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
+			int size, u32 *val)
+{
+	struct pcie_port *pp = bus_to_port(bus->number);
+	unsigned long flags;
+	int ret;
+
+	if (!pp) {
+		BUG();
+		return -EINVAL;
+	}
+
+	if (pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0) {
+		*val = 0xffffffff;
+		return PCIBIOS_DEVICE_NOT_FOUND;
+	}
+
+	spin_lock_irqsave(&pp->conf_lock, flags);
+	if (bus->number != pp->root_bus_nr)
+		ret = pcie_rd_other_conf(pp, bus, devfn, where, size, val);
+	else
+		ret = pcie_rd_own_conf(pp, where, size, val);
+	spin_unlock_irqrestore(&pp->conf_lock, flags);
+
+	return ret;
+}
+
+static int pcie_wr_conf(struct pci_bus *bus, u32 devfn,
+			int where, int size, u32 val)
+{
+	struct pcie_port *pp = bus_to_port(bus->number);
+	unsigned long flags;
+	int ret;
+
+	if (!pp) {
+		BUG();
+		return -EINVAL;
+	}
+
+	if (pcie_valid_config(pp, bus, PCI_SLOT(devfn)) == 0)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	spin_lock_irqsave(&pp->conf_lock, flags);
+	if (bus->number != pp->root_bus_nr)
+		ret = pcie_wr_other_conf(pp, bus, devfn, where, size, val);
+	else
+		ret = pcie_wr_own_conf(pp, where, size, val);
+	spin_unlock_irqrestore(&pp->conf_lock, flags);
+
+	return ret;
+}
+
+static struct pci_ops pcie_ops = {
+	.read = pcie_rd_conf,
+	.write = pcie_wr_conf,
+};
+
+static struct pci_bus __init *pcie_scan_bus(int nr, struct pci_sys_data *sys)
+{
+	struct pci_bus *bus;
+	struct pcie_port *pp = controller_to_port(nr);
+
+	if (pp) {
+		pp->root_bus_nr = sys->busnr;
+
+		return bus = pci_scan_root_bus(NULL, sys->busnr, &pcie_ops, sys,
+				&sys->resources);
+	} else {
+		bus = NULL;
+		BUG();
+	}
+
+	return bus;
+}
+
+static int pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+	struct pcie_port *pp = bus_to_port(dev->bus->number);
+	int irq;
+
+	if (!pp) {
+		BUG();
+		return -EINVAL;
+	}
+
+	irq = (pp->virt_irq_base + pin - 1);
+
+	return irq;
+}
+
+static struct hw_pci pci = {
+	.setup		= pcie_setup,
+	.scan		= pcie_scan_bus,
+	.map_irq	= pcie_map_irq,
+};
+
+static void mask_intx_irq(struct irq_data *data)
+{
+	struct pcie_port *pp = irq_data_get_irq_chip_data(data);
+	struct pcie_app_reg *app_reg = pp->va_app_base;
+	int irq_offset = data->irq - pp->virt_irq_base;
+	u32 mask;
+
+	switch (irq_offset) {
+	case 0:
+		mask = ~INTA_CTRL_INT;
+		break;
+	case 1:
+		mask = ~INTB_CTRL_INT;
+		break;
+	case 2:
+		mask = ~INTC_CTRL_INT;
+		break;
+	case 3:
+		mask = ~INTD_CTRL_INT;
+		break;
+	default:
+		BUG();
+		return;
+	}
+
+	writel(readl(&app_reg->int_mask) & mask, &app_reg->int_mask);
+}
+
+static void unmask_intx_irq(struct irq_data *data)
+{
+	struct pcie_port *pp = irq_data_get_irq_chip_data(data);
+	struct pcie_app_reg *app_reg = pp->va_app_base;
+	int irq_offset = data->irq - pp->virt_irq_base;
+	u32 mask;
+
+	switch (irq_offset) {
+	case 0:
+		mask = INTA_CTRL_INT;
+		break;
+	case 1:
+		mask = INTB_CTRL_INT;
+		break;
+	case 2:
+		mask = INTC_CTRL_INT;
+		break;
+	case 3:
+		mask = INTD_CTRL_INT;
+		break;
+	default:
+		BUG();
+		return;
+	}
+
+	writel(readl(&app_reg->int_mask) | mask, &app_reg->int_mask);
+}
+
+static struct irq_chip intx_chip = {
+	.name = "PCI-INTX",
+	.irq_mask = mask_intx_irq,
+	.irq_unmask = unmask_intx_irq,
+};
+
+static void pcie_int_handler(unsigned int irq, struct irq_desc *desc)
+{
+	struct pcie_port *pp = irq_get_handler_data(irq);
+	struct pcie_app_reg *app_reg = pp->va_app_base;
+	struct irq_chip *irqchip = irq_desc_get_chip(desc);
+	unsigned int status;
+
+	chained_irq_enter(irqchip, desc);
+
+	status = readl(&app_reg->int_sts);
+
+	if (status & MSI_CTRL_INT) {
+#ifdef CONFIG_PCI_MSI
+		handle_msi(pp);
+#endif
+		writel(MSI_CTRL_INT, &app_reg->int_clr);
+	} else if (status & INTA_CTRL_INT)
+		generic_handle_irq(pp->virt_irq_base);
+	else if (status & INTB_CTRL_INT)
+		generic_handle_irq(pp->virt_irq_base + 1);
+	else if (status & INTC_CTRL_INT)
+		generic_handle_irq(pp->virt_irq_base + 2);
+	else if (status & INTD_CTRL_INT)
+		generic_handle_irq(pp->virt_irq_base + 3);
+	else
+		writel(status, &app_reg->int_clr);
+
+	chained_irq_exit(irqchip, desc);
+}
+
+static void pcie_irq_init(struct pcie_port *pp)
+{
+	struct pcie_app_reg *app_reg = pp->va_app_base;
+	int i;
+
+	irq_set_chained_handler(pp->irq, pcie_int_handler);
+	irq_set_handler_data(pp->irq, pp);
+
+#ifdef CONFIG_PCI_MSI
+	msi_init(pp);
+#endif
+	/*
+	 * initialize INTX chip here only. MSI chip will be
+	 * initialized dynamically.
+	 */
+	for (i = 0; i < NUM_INTX_IRQS; i++) {
+		irq_set_chip_and_handler(pp->virt_irq_base + i, &intx_chip,
+				handle_simple_irq);
+		set_irq_flags(pp->virt_irq_base + i, IRQF_VALID);
+		irq_set_chip_data(pp->virt_irq_base + i, pp);
+	}
+
+	/* Enable INTX interrupt */
+	writel(readl(&app_reg->int_mask) | INTA_CTRL_INT
+			| INTB_CTRL_INT	| INTC_CTRL_INT
+			| INTD_CTRL_INT, &app_reg->int_mask);
+}
+
+static int patch_txdetectrx_spear1340(struct pcie_port *pp)
+{
+	void __iomem *miphy = pp->va_phy_base;
+	struct pcie_app_reg *app_reg = pp->va_app_base;
+	int ucount = 0;
+	u32 tempa;
+	u8 tempm;
+
+	tempa = readl(&app_reg->app_status_1);
+	/* till ltsmm state is not L0 */
+	while ((tempa & 0x3F) != 0x11) {
+		while (((tempa & 0x3F) == 0) || ((tempa & 0x3F) == 1)) {
+			tempm = readb(miphy + 0x20);
+			tempm &= ~0x3;
+			writeb(tempm, miphy + 0x20);
+
+			writeb(0, miphy + 0x21);
+
+			tempm = readb(miphy + 0x16);
+			tempm &= ~(1 << 3);
+			writeb(tempm, miphy + 0x16);
+
+			tempm = readb(miphy + 0x12);
+			tempm &= ~0x3;
+			writeb(tempm, miphy + 0x12);
+
+			tempm = readb(miphy + 0x10);
+			tempm |= 0x1;
+			writeb(tempm, miphy + 0x10);
+
+			tempa = readl(&app_reg->app_status_1);
+
+			ucount++;
+			udelay(1);
+			if (ucount > MAX_LINK_UP_WAIT_MS * 100000)
+				return -ECONNRESET;
+		}
+		tempm = readb(miphy + 0x10);
+		tempm &= ~0x1;
+		writeb(tempm, miphy + 0x10);
+
+		tempa = readl(&app_reg->app_status_1);
+	}
+
+	return 0;
+}
+
+void __iomem *spear13xx_pcie_io_base(unsigned long addr)
+{
+	int controller = (addr - PCIBIOS_MIN_IO) / IO_SIZE_PER_PORT;
+	struct pcie_port *pp;
+
+	pp = controller_to_port(controller);
+
+	return pp->io_base;
+}
+
+static void pcie_host_init(struct pcie_port *pp)
+{
+	struct pcie_port_info *config = &pp->config;
+	void __iomem *dbi_base = pp->va_dbi_base;
+	struct pcie_app_reg *app_reg = pp->va_app_base;
+	u32 exp_cap_off = PCI_CAP_ID_EXP_OFFSET;
+	u32 val;
+
+	/* Keep first 64K for IO */
+	pp->io_base = pp->base;
+	pp->mem_base = pp->io_base + config->io_size;
+	pp->cfg0_base = pp->mem_base + config->mem_size;
+	pp->cfg1_base = pp->cfg0_base + config->cfg0_size;
+
+	/*
+	 * setup registers for inbound translation. Fix viewport 0 for
+	 * Memory and viewport 1 for IO transaction
+	 */
+
+	/* Program viewport 0 : INBOUND : MEMORY */
+	val = PCIE_ATU_REGION_INBOUND | (0 & 0xF);
+	writel(val, dbi_base + PCIE_ATU_VIEWPORT);
+	writel(PCIE_ATU_TYPE_MEM, dbi_base + PCIE_ATU_CR1);
+	val = PCIE_ATU_ENABLE | PCIE_ATU_BAR_MODE_ENABLE;
+	writel(val, dbi_base + PCIE_ATU_CR2);
+
+	/* program first 256 MB as inbound address */
+	writel(0, dbi_base + PCIE_ATU_LOWER_BASE);
+	writel(0, dbi_base + PCIE_ATU_UPPER_BASE);
+	writel(config->in_mem_size - 1, dbi_base + PCIE_ATU_LIMIT);
+	writel(0, dbi_base + PCIE_ATU_LOWER_TARGET);
+	writel(0, dbi_base + PCIE_ATU_UPPER_TARGET);
+
+	/* Program viewport 1 : INBOUND : IO */
+	val = PCIE_ATU_REGION_INBOUND | (1 & 0xF);
+	writel(val, dbi_base + PCIE_ATU_VIEWPORT);
+	writel(PCIE_ATU_TYPE_IO, dbi_base + PCIE_ATU_CR1);
+	val = PCIE_ATU_ENABLE | PCIE_ATU_BAR_MODE_ENABLE;
+	writel(val, dbi_base + PCIE_ATU_CR2);
+
+	/* program first 256 MB as inbound address */
+	writel(0, dbi_base + PCIE_ATU_LOWER_BASE);
+	writel(0, dbi_base + PCIE_ATU_UPPER_BASE);
+	writel(config->in_mem_size - 1, dbi_base + PCIE_ATU_LIMIT);
+	writel(0, dbi_base + PCIE_ATU_LOWER_TARGET);
+	writel(0, dbi_base + PCIE_ATU_UPPER_TARGET);
+
+	pcie_wr_own_conf(pp, PCIE_BAR0_MASK_REG, 4,
+			(config->in_mem_size - 1));
+	pcie_wr_own_conf(pp, PCI_BASE_ADDRESS_0, 4, 0);
+
+	/*
+	 * this controller support only 128 bytes read size, however its
+	 * default value in capability register is 512 bytes. So force
+	 * it to 128 here.
+	 */
+
+	pcie_rd_own_conf(pp, exp_cap_off + PCI_EXP_DEVCTL, 4, &val);
+	val &= ~PCI_EXP_DEVCTL_READRQ;
+	pcie_wr_own_conf(pp, exp_cap_off + PCI_EXP_DEVCTL, 4, val);
+
+	/* program correct class for RC */
+	pcie_rd_own_conf(pp, PCI_CLASS_REVISION, 4, &val);
+	val &= 0xFFFF;
+	val |= (PCI_CLASS_BRIDGE_PCI << 16);
+	pcie_wr_own_conf(pp, PCI_CLASS_REVISION, 4, val);
+
+	/* program vid and did for RC */
+	pcie_wr_own_conf(pp, PCI_VENDOR_ID, 2, 0x104A);
+	pcie_wr_own_conf(pp, PCI_DEVICE_ID, 2, 0xCD80);
+
+	/* if is_gen1 is set then handle it */
+	if (pp->config.is_gen1) {
+		pcie_rd_own_conf(pp, exp_cap_off + PCI_EXP_LNKCAP, 4, &val);
+		if ((val & 0xF) != 1) {
+			val &= ~((u32)0xF);
+			val |= 1;
+			pcie_wr_own_conf(pp, exp_cap_off + PCI_EXP_LNKCAP, 4,
+					val);
+		}
+
+		pcie_rd_own_conf(pp, exp_cap_off + PCI_EXP_LNKCTL2, 4, &val);
+		if ((val & 0xF) != 1) {
+			val &= ~((u32)0xF);
+			val |= 1;
+			pcie_wr_own_conf(pp, exp_cap_off + PCI_EXP_LNKCTL2, 4,
+					val);
+		}
+	} else {
+		pcie_rd_own_conf(pp, PCIE_PORT_LOGIC, 4, &val);
+		val |= (1 << PORT_LOGIC_SPD_CHANGE_ID);
+		pcie_wr_own_conf(pp, PCIE_PORT_LOGIC, 4, val);
+	}
+
+	/* set max trial before lock failure */
+	writeb(0xC0, pp->va_phy_base + 0x85);
+	/* set max trial before lock failure */
+	writeb(0x01, pp->va_phy_base + 0x86);
+
+	/* txdetect RX settings for SPEAr1310 */
+	if (of_machine_is_compatible("st,spear1310"))
+		writeb(0x00, pp->va_phy_base + 0x16);
+
+	writel(DEVICE_TYPE_RC | (1 << MISCTRL_EN_ID)
+			| (1 << APP_LTSSM_ENABLE_ID)
+			| ((u32)1 << REG_TRANSLATION_ENABLE),
+			&app_reg->app_ctrl_0);
+
+	/* txdetect RX settings for SPEAr1340 */
+	if (of_machine_is_compatible("st,spear1340"))
+		patch_txdetectrx_spear1340(pp);
+
+	pcie_irq_init(pp);
+}
+
+static void pcie_host_exit(struct pcie_port *pp)
+{
+	struct pcie_app_reg *app_reg = pp->va_app_base;
+
+	writel(0, &app_reg->app_ctrl_0);
+
+}
+
+static int add_pcie_port(struct pcie_port *pp, struct platform_device *pdev)
+{
+	struct resource *base;
+	struct resource *dbi_base;
+	struct resource *phy_base;
+	int virt_irq_base;
+	struct device_node *np = pdev->dev.of_node;
+	struct irq_domain *irq_domain;
+	int num_virt_irqs = NUM_INTX_IRQS;
+
+	dbi_base = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!dbi_base) {
+		dev_err(&pdev->dev, "couldn't get dbi base resource\n");
+		return -EINVAL;
+	}
+	if (!devm_request_mem_region(&pdev->dev, dbi_base->start,
+				resource_size(dbi_base), pdev->name)) {
+		dev_err(&pdev->dev, "dbi base resource is busy\n");
+		return -EBUSY;
+	}
+
+	pp->dbi_base = (void __iomem *)dbi_base->start;
+	pp->va_dbi_base = devm_ioremap(&pdev->dev, dbi_base->start,
+			resource_size(dbi_base));
+	if (!pp->va_dbi_base) {
+		dev_err(&pdev->dev, "error with ioremap\n");
+		return -ENOMEM;
+	}
+
+	/* App base starts from offset 0x2000 of dbi base */
+	pp->app_base = pp->dbi_base + 0x2000;
+	pp->va_app_base = pp->va_dbi_base + 0x2000;
+
+	phy_base = platform_get_resource(pdev, IORESOURCE_MEM, 2);
+	if (!phy_base) {
+		dev_err(&pdev->dev, "couldn't get phy base resource\n");
+		return -EINVAL;
+	}
+	if (!devm_request_mem_region(&pdev->dev, phy_base->start,
+				resource_size(phy_base), pdev->name)) {
+		dev_err(&pdev->dev, "phy base resource is busy\n");
+		return -EBUSY;
+	}
+
+	pp->phy_base = (void __iomem *)phy_base->start;
+	pp->va_phy_base = devm_ioremap(&pdev->dev, phy_base->start,
+			resource_size(phy_base));
+	if (!pp->va_phy_base) {
+		dev_err(&pdev->dev, "error with ioremap\n");
+		return -ENOMEM;
+	}
+
+	base = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!base) {
+		dev_err(&pdev->dev, "couldn't get base resource\n");
+		return -EINVAL;
+	}
+
+	pp->base = (void __iomem *)base->start;
+
+	pp->root_bus_nr = -1;
+
+#ifdef CONFIG_PCI_MSI
+	num_virt_irqs += NUM_MSI_IRQS;
+#endif
+
+	virt_irq_base = irq_alloc_descs(-1, 0, num_virt_irqs, 0);
+	if (IS_ERR_VALUE(virt_irq_base)) {
+		dev_err(&pdev->dev, "irq desc alloc failed\n");
+		return -ENXIO;
+	}
+
+	irq_domain = irq_domain_add_legacy(np, num_virt_irqs, virt_irq_base,
+			0, &irq_domain_simple_ops, NULL);
+	if (!irq_domain) {
+		dev_err(&pdev->dev, "irq domain init failed\n");
+		irq_free_descs(virt_irq_base, 32);
+		return -ENXIO;
+	}
+
+	pp->virt_irq_base = irq_find_mapping(irq_domain, 0);
+
+	spin_lock_init(&pp->conf_lock);
+	if (pcie_link_up(pp->va_app_base)) {
+		dev_info(&pdev->dev, "link up\n");
+	} else {
+		dev_info(&pdev->dev, "link down\n");
+		pcie_host_init(pp);
+		pp->va_cfg0_base = devm_ioremap(&pdev->dev,
+				(resource_size_t)pp->cfg0_base,
+					pp->config.cfg0_size);
+		if (!pp->va_cfg0_base) {
+			dev_err(&pdev->dev, "error with ioremap in function\n");
+			return -ENOMEM;
+		}
+		pp->va_cfg1_base = devm_ioremap(&pdev->dev,
+				(resource_size_t)pp->cfg1_base,
+					pp->config.cfg1_size);
+		if (!pp->va_cfg1_base) {
+			dev_err(&pdev->dev, "error with ioremap\n");
+			return -ENOMEM;
+		}
+
+	}
+
+	return 0;
+}
+
+static int __devinit pcie_probe(struct platform_device *pdev)
+{
+	int err;
+	struct clk *clk;
+	struct pcie_port *pp;
+	struct device_node *np = pdev->dev.of_node;
+
+	if (!pdev->dev.platform_data)
+		return -EINVAL;
+
+	pp = devm_kzalloc(&pdev->dev, sizeof(*pp), GFP_KERNEL);
+	if (!pp) {
+		dev_err(&pdev->dev, "no memory for pcie port\n");
+		return -ENOMEM;
+	}
+
+	memcpy(&pp->config, pdev->dev.platform_data, (sizeof(pp->config)));
+	pp->config.io_size = IO_SIZE_PER_PORT;
+	of_property_read_u32(np, "pcie-host,is_host", &pp->config.is_host);
+	of_property_read_u32(np, "pcie-host,is_gen1", &pp->config.is_gen1);
+	of_property_read_u32(np, "pcie-host,cfg0_size", &pp->config.cfg0_size);
+	of_property_read_u32(np, "pcie-host,cfg1_size", &pp->config.cfg1_size);
+	of_property_read_u32(np, "pcie-host,mem_size", &pp->config.mem_size);
+	of_property_read_u32(np, "pcie-host,msg_size", &pp->config.msg_size);
+	of_property_read_u32(np, "pcie-host,in_mem_size",
+			&pp->config.in_mem_size);
+
+	if (!pp->config.is_host)
+		return -EINVAL;
+
+	err = pp->config.clk_init(pp);
+	if (err)
+		goto free_mem;
+
+	clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(clk)) {
+		dev_err(&pdev->dev, "couldn't get clk for pcie\n");
+		err = PTR_ERR(clk);
+		goto free_mem;
+	}
+
+	if (clk_prepare_enable(clk)) {
+		dev_err(&pdev->dev, "couldn't enable clk for pcie\n");
+		err = -EINVAL;
+		goto clk_put;
+	}
+
+	pp->irq = platform_get_irq(pdev, 0);
+	if (pp->irq < 0) {
+		err = -EINVAL;
+		goto clk_put;
+	}
+
+	if (!add_pcie_port(pp, pdev)) {
+		pp->controller = pci.nr_controllers;
+		pci.nr_controllers++;
+		list_add_tail(&pp->next, &pcie_port_list);
+		return 0;
+	}
+
+clk_put:
+	clk_put(clk);
+free_mem:
+	kfree(pp);
+
+	return err;
+}
+
+static int __devinit pcie_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+#ifdef CONFIG_PM
+int spear_pcie_suspend(void)
+{
+	struct pcie_port *pp;
+	int i;
+
+	for (i = 0; i < pci.nr_controllers; i++) {
+		pp = controller_to_port(i);
+		if (pcie_link_up(pp->va_app_base)) {
+			pcie_host_exit(pp);
+			pp->config.clk_exit(pp);
+			pp->susp_state = 1;
+		}
+	}
+
+	return 0;
+}
+
+int spear_pcie_resume(void)
+{
+	struct pcie_port *pp;
+	int i;
+
+	for (i = 0; i < pci.nr_controllers; i++) {
+		pp = controller_to_port(i);
+		if (pp->susp_state) {
+			pp->config.clk_init(pp);
+			pp->susp_state = 0;
+			if (!pcie_link_up(pp->va_app_base))
+				pcie_host_init(pp);
+		}
+	}
+
+	return 0;
+}
+#endif
+
+static const struct of_device_id pcie_of_match[] = {
+	{ .compatible = "st,pcie-host", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, pcie_of_match);
+
+static struct platform_driver pcie_driver = {
+	.driver = {
+		.name	= "pcie",
+		.owner = THIS_MODULE,
+		.of_match_table = pcie_of_match,
+	},
+	.probe = pcie_probe,
+	.remove = __devexit_p(pcie_remove),
+
+};
+
+static int
+pcie_abort(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
+{
+	unsigned long pc = instruction_pointer(regs);
+	unsigned long instr = *(unsigned long *)(pc - 8);
+
+	WARN_ONCE(1, "pcie abort\n");
+	/*
+	 * If the instruction being executed was a read,
+	 * make it look like it read all-ones.
+	 */
+	if ((instr & 0x0c100000) == 0x04100000) {
+		int reg = (instr >> 12) & 15;
+		unsigned long val;
+
+		if (instr & 0x00400000)
+			val = 255;
+		else
+			val = -1;
+
+		regs->uregs[reg] = val;
+		regs->ARM_pc += 4;
+
+		return 0;
+	}
+
+	return 1;
+}
+
+static int __init pcie_init(void)
+{
+	hook_fault_code(16+6, pcie_abort, SIGBUS, 0,
+			"imprecise external abort");
+
+	INIT_LIST_HEAD(&pcie_port_list);
+	platform_driver_probe(&pcie_driver, pcie_probe);
+
+	if (pci.nr_controllers) {
+		pci_common_init(&pci);
+		pci_assign_unassigned_resources();
+		pr_info("pcie init successful\n");
+	}
+
+	return 0;
+}
+subsys_initcall(pcie_init);
+
+static void __exit pcie_exit(void)
+{
+	platform_driver_unregister(&pcie_driver);
+}
+module_exit(pcie_exit);
-- 
1.7.5.4


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

* [PATCH 05/15] clk: SPEAr1340: Fix pcie0 clock name
  2012-10-29  7:01 ` Pratyush Anand
@ 2012-10-29  7:01   ` Pratyush Anand
  -1 siblings, 0 replies; 56+ messages in thread
From: Pratyush Anand @ 2012-10-29  7:01 UTC (permalink / raw)
  To: arnd, shiraz.hashim, viresh.linux
  Cc: spear-devel, linux-pci, devicetree-discuss, olof, Pratyush Anand

Signed-off-by: Pratyush Anand <pratyush.anand@st.com>
---
 drivers/clk/spear/spear1340_clock.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/clk/spear/spear1340_clock.c b/drivers/clk/spear/spear1340_clock.c
index 364c947..9f69a61 100644
--- a/drivers/clk/spear/spear1340_clock.c
+++ b/drivers/clk/spear/spear1340_clock.c
@@ -844,7 +844,7 @@ void __init spear1340_clk_init(void)
 	clk = clk_register_gate(NULL, "pcie_sata_clk", "ahb_clk", 0,
 			SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_PCIE_SATA_CLK_ENB,
 			0, &_lock);
-	clk_register_clkdev(clk, NULL, "dw_pcie");
+	clk_register_clkdev(clk, NULL, "b1000000.pcie0");
 	clk_register_clkdev(clk, NULL, "b1000000.ahci");
 
 	clk = clk_register_gate(NULL, "sysram0_clk", "ahb_clk", 0,
-- 
1.7.5.4

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

* [PATCH 05/15] clk: SPEAr1340: Fix pcie0 clock name
@ 2012-10-29  7:01   ` Pratyush Anand
  0 siblings, 0 replies; 56+ messages in thread
From: Pratyush Anand @ 2012-10-29  7:01 UTC (permalink / raw)
  To: arnd, shiraz.hashim, viresh.linux
  Cc: spear-devel, linux-pci, devicetree-discuss, olof, Pratyush Anand

Signed-off-by: Pratyush Anand <pratyush.anand@st.com>
---
 drivers/clk/spear/spear1340_clock.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/clk/spear/spear1340_clock.c b/drivers/clk/spear/spear1340_clock.c
index 364c947..9f69a61 100644
--- a/drivers/clk/spear/spear1340_clock.c
+++ b/drivers/clk/spear/spear1340_clock.c
@@ -844,7 +844,7 @@ void __init spear1340_clk_init(void)
 	clk = clk_register_gate(NULL, "pcie_sata_clk", "ahb_clk", 0,
 			SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_PCIE_SATA_CLK_ENB,
 			0, &_lock);
-	clk_register_clkdev(clk, NULL, "dw_pcie");
+	clk_register_clkdev(clk, NULL, "b1000000.pcie0");
 	clk_register_clkdev(clk, NULL, "b1000000.ahci");
 
 	clk = clk_register_gate(NULL, "sysram0_clk", "ahb_clk", 0,
-- 
1.7.5.4


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

* [PATCH 06/15] clk: SPEAr1310: Fix pcie clock name
  2012-10-29  7:01 ` Pratyush Anand
@ 2012-10-29  7:01   ` Pratyush Anand
  -1 siblings, 0 replies; 56+ messages in thread
From: Pratyush Anand @ 2012-10-29  7:01 UTC (permalink / raw)
  To: arnd, shiraz.hashim, viresh.linux
  Cc: spear-devel, linux-pci, devicetree-discuss, olof, Pratyush Anand

Signed-off-by: Pratyush Anand <pratyush.anand@st.com>
---
 drivers/clk/spear/spear1310_clock.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/clk/spear/spear1310_clock.c b/drivers/clk/spear/spear1310_clock.c
index 52e418f..97c3981 100644
--- a/drivers/clk/spear/spear1310_clock.c
+++ b/drivers/clk/spear/spear1310_clock.c
@@ -733,19 +733,19 @@ void __init spear1310_clk_init(void)
 	clk = clk_register_gate(NULL, "pcie_sata_0_clk", "ahb_clk", 0,
 			SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_PCIE_SATA_0_CLK_ENB,
 			0, &_lock);
-	clk_register_clkdev(clk, NULL, "dw_pcie.0");
+	clk_register_clkdev(clk, NULL, "b1000000.pcie0");
 	clk_register_clkdev(clk, NULL, "b1000000.ahci");
 
 	clk = clk_register_gate(NULL, "pcie_sata_1_clk", "ahb_clk", 0,
 			SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_PCIE_SATA_1_CLK_ENB,
 			0, &_lock);
-	clk_register_clkdev(clk, NULL, "dw_pcie.1");
+	clk_register_clkdev(clk, NULL, "b1800000.pcie1");
 	clk_register_clkdev(clk, NULL, "b1800000.ahci");
 
 	clk = clk_register_gate(NULL, "pcie_sata_2_clk", "ahb_clk", 0,
 			SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_PCIE_SATA_2_CLK_ENB,
 			0, &_lock);
-	clk_register_clkdev(clk, NULL, "dw_pcie.2");
+	clk_register_clkdev(clk, NULL, "b4000000.pcie2");
 	clk_register_clkdev(clk, NULL, "b4000000.ahci");
 
 	clk = clk_register_gate(NULL, "sysram0_clk", "ahb_clk", 0,
-- 
1.7.5.4

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

* [PATCH 06/15] clk: SPEAr1310: Fix pcie clock name
@ 2012-10-29  7:01   ` Pratyush Anand
  0 siblings, 0 replies; 56+ messages in thread
From: Pratyush Anand @ 2012-10-29  7:01 UTC (permalink / raw)
  To: arnd, shiraz.hashim, viresh.linux
  Cc: spear-devel, linux-pci, devicetree-discuss, olof, Pratyush Anand

Signed-off-by: Pratyush Anand <pratyush.anand@st.com>
---
 drivers/clk/spear/spear1310_clock.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/clk/spear/spear1310_clock.c b/drivers/clk/spear/spear1310_clock.c
index 52e418f..97c3981 100644
--- a/drivers/clk/spear/spear1310_clock.c
+++ b/drivers/clk/spear/spear1310_clock.c
@@ -733,19 +733,19 @@ void __init spear1310_clk_init(void)
 	clk = clk_register_gate(NULL, "pcie_sata_0_clk", "ahb_clk", 0,
 			SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_PCIE_SATA_0_CLK_ENB,
 			0, &_lock);
-	clk_register_clkdev(clk, NULL, "dw_pcie.0");
+	clk_register_clkdev(clk, NULL, "b1000000.pcie0");
 	clk_register_clkdev(clk, NULL, "b1000000.ahci");
 
 	clk = clk_register_gate(NULL, "pcie_sata_1_clk", "ahb_clk", 0,
 			SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_PCIE_SATA_1_CLK_ENB,
 			0, &_lock);
-	clk_register_clkdev(clk, NULL, "dw_pcie.1");
+	clk_register_clkdev(clk, NULL, "b1800000.pcie1");
 	clk_register_clkdev(clk, NULL, "b1800000.ahci");
 
 	clk = clk_register_gate(NULL, "pcie_sata_2_clk", "ahb_clk", 0,
 			SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_PCIE_SATA_2_CLK_ENB,
 			0, &_lock);
-	clk_register_clkdev(clk, NULL, "dw_pcie.2");
+	clk_register_clkdev(clk, NULL, "b4000000.pcie2");
 	clk_register_clkdev(clk, NULL, "b4000000.ahci");
 
 	clk = clk_register_gate(NULL, "sysram0_clk", "ahb_clk", 0,
-- 
1.7.5.4


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

* [PATCH 07/15] SPEAr1340: Add PCIe auxdata for miphy clock initialization
  2012-10-29  7:01 ` Pratyush Anand
@ 2012-10-29  7:01   ` Pratyush Anand
  -1 siblings, 0 replies; 56+ messages in thread
From: Pratyush Anand @ 2012-10-29  7:01 UTC (permalink / raw)
  To: arnd, shiraz.hashim, viresh.linux
  Cc: spear-devel, linux-pci, devicetree-discuss, olof, Pratyush Anand

Miphy Clock initialization is very specific to controller and its
instances. Pass this custom function using auxdata.

Signed-off-by: Pratyush Anand <pratyush.anand@st.com>
---
 arch/arm/mach-spear13xx/spear1340.c |   26 ++++++++++++++++++++++++++
 1 files changed, 26 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-spear13xx/spear1340.c b/arch/arm/mach-spear13xx/spear1340.c
index 223d9ef..194c3ac 100644
--- a/arch/arm/mach-spear13xx/spear1340.c
+++ b/arch/arm/mach-spear13xx/spear1340.c
@@ -29,6 +29,7 @@
 #include <asm/mach/arch.h>
 #include <mach/dma.h>
 #include <mach/generic.h>
+#include <mach/pcie.h>
 #include <mach/spdif.h>
 #include <mach/spear.h>
 #include <sound/designware_i2s.h>
@@ -42,6 +43,7 @@
 #define SPEAR1340_CAM2_BASE			UL(0xD0400000)
 #define SPEAR1340_CAM3_BASE			UL(0xD0500000)
 #define SPEAR1340_SATA_BASE			UL(0xB1000000)
+#define SPEAR1340_PCIE_BASE			UL(0xB1000000)
 #define SPEAR1340_UART1_BASE			UL(0xB4100000)
 #define SPEAR1340_I2S_PLAY_BASE			UL(0xB2400000)
 #define SPEAR1340_I2S_REC_BASE			UL(0xB2000000)
@@ -358,6 +360,28 @@ static struct ahci_platform_data sata_pdata = {
 	.resume = sata_resume,
 };
 
+static int spear1340_pcie_clk_init(struct pcie_port *pp)
+{
+	writel(SPEAR1340_PCIE_SATA_MIPHY_CFG_PCIE,
+			SPEAR1340_PCIE_MIPHY_CFG);
+	writel(SPEAR1340_PCIE_CFG_VAL, SPEAR1340_PCIE_SATA_CFG);
+
+	return 0;
+}
+
+static int spear1340_pcie_clk_exit(struct pcie_port *pp)
+{
+	writel(0, SPEAR1340_PCIE_SATA_CFG);
+	writel(0, SPEAR1340_PCIE_MIPHY_CFG);
+
+	return 0;
+}
+
+static struct pcie_port_info pcie_pdata = {
+	.clk_init = spear1340_pcie_clk_init,
+	.clk_exit = spear1340_pcie_clk_exit,
+};
+
 /* camera sensor registeration */
 static struct i2c_board_info vs6725_camera_sensor_info = {
 	I2C_BOARD_INFO("vs6725", 0x10),
@@ -609,6 +633,8 @@ static struct of_dev_auxdata spear1340_auxdata_lookup[] __initdata = {
 
 	OF_DEV_AUXDATA("snps,spear-ahci", SPEAR1340_SATA_BASE, NULL,
 			&sata_pdata),
+	OF_DEV_AUXDATA("st,pcie-host", SPEAR1340_PCIE_BASE, NULL,
+			&pcie_pdata),
 	OF_DEV_AUXDATA("arm,pl011", SPEAR1340_UART1_BASE, NULL, &uart1_data),
 	OF_DEV_AUXDATA("st,spear600-gmac", SPEAR13XX_GETH_BASE, NULL,
 			&eth_data),
-- 
1.7.5.4

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

* [PATCH 07/15] SPEAr1340: Add PCIe auxdata for miphy clock initialization
@ 2012-10-29  7:01   ` Pratyush Anand
  0 siblings, 0 replies; 56+ messages in thread
From: Pratyush Anand @ 2012-10-29  7:01 UTC (permalink / raw)
  To: arnd, shiraz.hashim, viresh.linux
  Cc: spear-devel, linux-pci, devicetree-discuss, olof, Pratyush Anand

Miphy Clock initialization is very specific to controller and its
instances. Pass this custom function using auxdata.

Signed-off-by: Pratyush Anand <pratyush.anand@st.com>
---
 arch/arm/mach-spear13xx/spear1340.c |   26 ++++++++++++++++++++++++++
 1 files changed, 26 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-spear13xx/spear1340.c b/arch/arm/mach-spear13xx/spear1340.c
index 223d9ef..194c3ac 100644
--- a/arch/arm/mach-spear13xx/spear1340.c
+++ b/arch/arm/mach-spear13xx/spear1340.c
@@ -29,6 +29,7 @@
 #include <asm/mach/arch.h>
 #include <mach/dma.h>
 #include <mach/generic.h>
+#include <mach/pcie.h>
 #include <mach/spdif.h>
 #include <mach/spear.h>
 #include <sound/designware_i2s.h>
@@ -42,6 +43,7 @@
 #define SPEAR1340_CAM2_BASE			UL(0xD0400000)
 #define SPEAR1340_CAM3_BASE			UL(0xD0500000)
 #define SPEAR1340_SATA_BASE			UL(0xB1000000)
+#define SPEAR1340_PCIE_BASE			UL(0xB1000000)
 #define SPEAR1340_UART1_BASE			UL(0xB4100000)
 #define SPEAR1340_I2S_PLAY_BASE			UL(0xB2400000)
 #define SPEAR1340_I2S_REC_BASE			UL(0xB2000000)
@@ -358,6 +360,28 @@ static struct ahci_platform_data sata_pdata = {
 	.resume = sata_resume,
 };
 
+static int spear1340_pcie_clk_init(struct pcie_port *pp)
+{
+	writel(SPEAR1340_PCIE_SATA_MIPHY_CFG_PCIE,
+			SPEAR1340_PCIE_MIPHY_CFG);
+	writel(SPEAR1340_PCIE_CFG_VAL, SPEAR1340_PCIE_SATA_CFG);
+
+	return 0;
+}
+
+static int spear1340_pcie_clk_exit(struct pcie_port *pp)
+{
+	writel(0, SPEAR1340_PCIE_SATA_CFG);
+	writel(0, SPEAR1340_PCIE_MIPHY_CFG);
+
+	return 0;
+}
+
+static struct pcie_port_info pcie_pdata = {
+	.clk_init = spear1340_pcie_clk_init,
+	.clk_exit = spear1340_pcie_clk_exit,
+};
+
 /* camera sensor registeration */
 static struct i2c_board_info vs6725_camera_sensor_info = {
 	I2C_BOARD_INFO("vs6725", 0x10),
@@ -609,6 +633,8 @@ static struct of_dev_auxdata spear1340_auxdata_lookup[] __initdata = {
 
 	OF_DEV_AUXDATA("snps,spear-ahci", SPEAR1340_SATA_BASE, NULL,
 			&sata_pdata),
+	OF_DEV_AUXDATA("st,pcie-host", SPEAR1340_PCIE_BASE, NULL,
+			&pcie_pdata),
 	OF_DEV_AUXDATA("arm,pl011", SPEAR1340_UART1_BASE, NULL, &uart1_data),
 	OF_DEV_AUXDATA("st,spear600-gmac", SPEAR13XX_GETH_BASE, NULL,
 			&eth_data),
-- 
1.7.5.4


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

* [PATCH 08/15] SPEAr1310: Add PCIe auxdata for miphy clock initialization
  2012-10-29  7:01 ` Pratyush Anand
@ 2012-10-29  7:01   ` Pratyush Anand
  -1 siblings, 0 replies; 56+ messages in thread
From: Pratyush Anand @ 2012-10-29  7:01 UTC (permalink / raw)
  To: arnd, shiraz.hashim, viresh.linux
  Cc: spear-devel, linux-pci, devicetree-discuss, olof, Pratyush Anand

Miphy Clock initialization is very specific to controller and its
instances. Pass this custom function using auxdata.

Signed-off-by: Pratyush Anand <pratyush.anand@st.com>
---
 arch/arm/mach-spear13xx/spear1310.c |  148 +++++++++++++++++++++++++++++++++++
 1 files changed, 148 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-spear13xx/spear1310.c b/arch/arm/mach-spear13xx/spear1310.c
index 25e0fbb..3c673a1 100644
--- a/arch/arm/mach-spear13xx/spear1310.c
+++ b/arch/arm/mach-spear13xx/spear1310.c
@@ -24,6 +24,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <mach/generic.h>
+#include <mach/pcie.h>
 #include <mach/spear.h>
 
 /* Base addresses */
@@ -35,6 +36,9 @@
 #define SPEAR1310_SATA0_BASE			UL(0xB1000000)
 #define SPEAR1310_SATA1_BASE			UL(0xB1800000)
 #define SPEAR1310_SATA2_BASE			UL(0xB4000000)
+#define SPEAR1310_PCIE0_BASE			UL(0xB1000000)
+#define SPEAR1310_PCIE1_BASE			UL(0xB1800000)
+#define SPEAR1310_PCIE2_BASE			UL(0xB4000000)
 
 /* RAS Area Control Register */
 #define VA_SPEAR1310_RAS_CTRL_REG1	(VA_SPEAR1310_RAS_BASE + 0x4)
@@ -57,6 +61,81 @@
 #define SPEAR1310_PERIP1_SW_RST			(VA_MISC_BASE + 0x308)
 #define SPEAR1310_UOC_RST_ENB			11
 
+#define VA_SPEAR1310_PCIE_SATA_CFG		(VA_MISC_BASE + 0x3A4)
+	/* PCIE CFG MASks */
+	#define SPEAR1310_PCIE_SATA2_SEL_PCIE		(0 << 31)
+	#define SPEAR1310_PCIE_SATA1_SEL_PCIE		(0 << 30)
+	#define SPEAR1310_PCIE_SATA0_SEL_PCIE		(0 << 29)
+	#define SPEAR1310_PCIE_SATA2_SEL_SATA		(1 << 31)
+	#define SPEAR1310_PCIE_SATA1_SEL_SATA		(1 << 30)
+	#define SPEAR1310_PCIE_SATA0_SEL_SATA		(1 << 29)
+	#define SPEAR1310_SATA2_CFG_TX_CLK_EN		(1 << 27)
+	#define SPEAR1310_SATA2_CFG_RX_CLK_EN		(1 << 26)
+	#define SPEAR1310_SATA2_CFG_POWERUP_RESET	(1 << 25)
+	#define SPEAR1310_SATA2_CFG_PM_CLK_EN		(1 << 24)
+	#define SPEAR1310_SATA1_CFG_TX_CLK_EN		(1 << 23)
+	#define SPEAR1310_SATA1_CFG_RX_CLK_EN		(1 << 22)
+	#define SPEAR1310_SATA1_CFG_POWERUP_RESET	(1 << 21)
+	#define SPEAR1310_SATA1_CFG_PM_CLK_EN		(1 << 20)
+	#define SPEAR1310_SATA0_CFG_TX_CLK_EN		(1 << 19)
+	#define SPEAR1310_SATA0_CFG_RX_CLK_EN		(1 << 18)
+	#define SPEAR1310_SATA0_CFG_POWERUP_RESET	(1 << 17)
+	#define SPEAR1310_SATA0_CFG_PM_CLK_EN		(1 << 16)
+	#define SPEAR1310_PCIE2_CFG_DEVICE_PRESENT	(1 << 11)
+	#define SPEAR1310_PCIE2_CFG_POWERUP_RESET	(1 << 10)
+	#define SPEAR1310_PCIE2_CFG_CORE_CLK_EN		(1 << 9)
+	#define SPEAR1310_PCIE2_CFG_AUX_CLK_EN		(1 << 8)
+	#define SPEAR1310_PCIE1_CFG_DEVICE_PRESENT	(1 << 7)
+	#define SPEAR1310_PCIE1_CFG_POWERUP_RESET	(1 << 6)
+	#define SPEAR1310_PCIE1_CFG_CORE_CLK_EN		(1 << 5)
+	#define SPEAR1310_PCIE1_CFG_AUX_CLK_EN		(1 << 4)
+	#define SPEAR1310_PCIE0_CFG_DEVICE_PRESENT	(1 << 3)
+	#define SPEAR1310_PCIE0_CFG_POWERUP_RESET	(1 << 2)
+	#define SPEAR1310_PCIE0_CFG_CORE_CLK_EN		(1 << 1)
+	#define SPEAR1310_PCIE0_CFG_AUX_CLK_EN		(1 << 0)
+
+	#define SPEAR1310_PCIE_CFG_MASK(x) ((0xF << (x * 4)) | (1 << (x + 29)))
+	#define SPEAR1310_SATA_CFG_MASK(x) ((0xF << (x * 4 + 16)) | \
+			(1 << (x + 29)))
+	#define SPEAR1310_PCIE_CFG_VAL(x) \
+			(SPEAR1310_PCIE_SATA##x##_SEL_PCIE | \
+			SPEAR1310_PCIE##x##_CFG_AUX_CLK_EN | \
+			SPEAR1310_PCIE##x##_CFG_CORE_CLK_EN | \
+			SPEAR1310_PCIE##x##_CFG_POWERUP_RESET | \
+			SPEAR1310_PCIE##x##_CFG_DEVICE_PRESENT)
+	#define SPEAR1310_SATA_CFG_VAL(x) \
+			(SPEAR1310_PCIE_SATA##x##_SEL_SATA | \
+			SPEAR1310_SATA##x##_CFG_PM_CLK_EN | \
+			SPEAR1310_SATA##x##_CFG_POWERUP_RESET | \
+			SPEAR1310_SATA##x##_CFG_RX_CLK_EN | \
+			SPEAR1310_SATA##x##_CFG_TX_CLK_EN)
+
+#define VA_SPEAR1310_PCIE_MIPHY_CFG_1		(VA_MISC_BASE + 0x3A8)
+	#define SPEAR1310_MIPHY_DUAL_OSC_BYPASS_EXT	(1 << 31)
+	#define SPEAR1310_MIPHY_DUAL_CLK_REF_DIV2	(1 << 28)
+	#define SPEAR1310_MIPHY_DUAL_PLL_RATIO_TOP(x)	(x << 16)
+	#define SPEAR1310_MIPHY_SINGLE_OSC_BYPASS_EXT	(1 << 15)
+	#define SPEAR1310_MIPHY_SINGLE_CLK_REF_DIV2	(1 << 12)
+	#define SPEAR1310_MIPHY_SINGLE_PLL_RATIO_TOP(x)	(x << 0)
+	#define SPEAR1310_PCIE_SATA_MIPHY_CFG_SATA_MASK (0xFFFF)
+	#define SPEAR1310_PCIE_SATA_MIPHY_CFG_PCIE_MASK (0xFFFF << 16)
+	#define SPEAR1310_PCIE_SATA_MIPHY_CFG_SATA \
+			(SPEAR1310_MIPHY_DUAL_OSC_BYPASS_EXT | \
+			SPEAR1310_MIPHY_DUAL_CLK_REF_DIV2 | \
+			SPEAR1310_MIPHY_DUAL_PLL_RATIO_TOP(60) | \
+			SPEAR1310_MIPHY_SINGLE_OSC_BYPASS_EXT | \
+			SPEAR1310_MIPHY_SINGLE_CLK_REF_DIV2 | \
+			SPEAR1310_MIPHY_SINGLE_PLL_RATIO_TOP(60))
+	#define SPEAR1310_PCIE_SATA_MIPHY_CFG_SATA_25M_CRYSTAL_CLK \
+			(SPEAR1310_MIPHY_SINGLE_PLL_RATIO_TOP(120))
+	#define SPEAR1310_PCIE_SATA_MIPHY_CFG_PCIE \
+			(SPEAR1310_MIPHY_DUAL_OSC_BYPASS_EXT | \
+			SPEAR1310_MIPHY_DUAL_PLL_RATIO_TOP(25) | \
+			SPEAR1310_MIPHY_SINGLE_OSC_BYPASS_EXT | \
+			SPEAR1310_MIPHY_SINGLE_PLL_RATIO_TOP(25))
+
+#define VA_SPEAR1310_PCIE_MIPHY_CFG_2		(VA_MISC_BASE + 0x3AC)
+
 static int spear1310_eth_phy_clk_cfg(struct platform_device *pdev)
 {
 	struct plat_stmmacenet_data *pdata = dev_get_platdata(&pdev->dev);
@@ -342,6 +421,69 @@ static struct dwc_otg_plat_data spear1310_otg_plat_data = {
 	.phy_init = spear1310_otg_phy_init,
 };
 
+static int spear1310_pcie_clk_init(struct pcie_port *pp)
+{
+	u32 temp;
+
+	temp = readl(VA_SPEAR1310_PCIE_MIPHY_CFG_1);
+	temp &= ~SPEAR1310_PCIE_SATA_MIPHY_CFG_PCIE_MASK;
+	temp |= SPEAR1310_PCIE_SATA_MIPHY_CFG_PCIE;
+
+	writel(temp, VA_SPEAR1310_PCIE_MIPHY_CFG_1);
+
+	temp = readl(VA_SPEAR1310_PCIE_SATA_CFG);
+
+	switch (pp->controller) {
+	case 0:
+		temp &= ~SPEAR1310_PCIE_CFG_MASK(0);
+		temp |= SPEAR1310_PCIE_CFG_VAL(0);
+		break;
+	case 1:
+		temp &= ~SPEAR1310_PCIE_CFG_MASK(1);
+		temp |= SPEAR1310_PCIE_CFG_VAL(1);
+		break;
+	case 2:
+		temp &= ~SPEAR1310_PCIE_CFG_MASK(2);
+		temp |= SPEAR1310_PCIE_CFG_VAL(2);
+		break;
+	default:
+		return -EINVAL;
+	}
+	writel(temp, VA_SPEAR1310_PCIE_SATA_CFG);
+
+	return 0;
+}
+
+static int spear1310_pcie_clk_exit(struct pcie_port *pp)
+{
+	u32 temp;
+
+	temp = readl(VA_SPEAR1310_PCIE_SATA_CFG);
+
+	switch (pp->controller) {
+	case 0:
+		temp &= ~SPEAR1310_PCIE_CFG_MASK(0);
+		break;
+	case 1:
+		temp &= ~SPEAR1310_PCIE_CFG_MASK(1);
+		break;
+	case 2:
+		temp &= ~SPEAR1310_PCIE_CFG_MASK(2);
+		break;
+	}
+
+	writel(temp, VA_SPEAR1310_PCIE_SATA_CFG);
+	writel(~SPEAR1310_PCIE_SATA_MIPHY_CFG_PCIE_MASK,
+			VA_SPEAR1310_PCIE_MIPHY_CFG_1);
+
+	return 0;
+}
+
+static struct pcie_port_info pcie_pdata = {
+	.clk_init = spear1310_pcie_clk_init,
+	.clk_exit = spear1310_pcie_clk_exit,
+};
+
 /* Add SPEAr1310 auxdata to pass platform data */
 static struct of_dev_auxdata spear1310_auxdata_lookup[] __initdata = {
 	OF_DEV_AUXDATA("st,spear-adc", SPEAR13XX_ADC_BASE, NULL, &adc_pdata),
@@ -363,6 +505,12 @@ static struct of_dev_auxdata spear1310_auxdata_lookup[] __initdata = {
 			&eth4_data),
 	OF_DEV_AUXDATA("snps,usb-otg", SPEAR_UOC_BASE, NULL,
 			&spear1310_otg_plat_data),
+	OF_DEV_AUXDATA("st,pcie-host", SPEAR1310_PCIE0_BASE, NULL,
+			&pcie_pdata),
+	OF_DEV_AUXDATA("st,pcie-host", SPEAR1310_PCIE1_BASE, NULL,
+			&pcie_pdata),
+	OF_DEV_AUXDATA("st,pcie-host", SPEAR1310_PCIE2_BASE, NULL,
+			&pcie_pdata),
 	OF_DEV_AUXDATA("st,db9000-clcd", SPEAR13XX_CLCD_BASE, NULL,
 			&clcd_plat_info),
 	{}
-- 
1.7.5.4

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

* [PATCH 08/15] SPEAr1310: Add PCIe auxdata for miphy clock initialization
@ 2012-10-29  7:01   ` Pratyush Anand
  0 siblings, 0 replies; 56+ messages in thread
From: Pratyush Anand @ 2012-10-29  7:01 UTC (permalink / raw)
  To: arnd, shiraz.hashim, viresh.linux
  Cc: spear-devel, linux-pci, devicetree-discuss, olof, Pratyush Anand

Miphy Clock initialization is very specific to controller and its
instances. Pass this custom function using auxdata.

Signed-off-by: Pratyush Anand <pratyush.anand@st.com>
---
 arch/arm/mach-spear13xx/spear1310.c |  148 +++++++++++++++++++++++++++++++++++
 1 files changed, 148 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-spear13xx/spear1310.c b/arch/arm/mach-spear13xx/spear1310.c
index 25e0fbb..3c673a1 100644
--- a/arch/arm/mach-spear13xx/spear1310.c
+++ b/arch/arm/mach-spear13xx/spear1310.c
@@ -24,6 +24,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <mach/generic.h>
+#include <mach/pcie.h>
 #include <mach/spear.h>
 
 /* Base addresses */
@@ -35,6 +36,9 @@
 #define SPEAR1310_SATA0_BASE			UL(0xB1000000)
 #define SPEAR1310_SATA1_BASE			UL(0xB1800000)
 #define SPEAR1310_SATA2_BASE			UL(0xB4000000)
+#define SPEAR1310_PCIE0_BASE			UL(0xB1000000)
+#define SPEAR1310_PCIE1_BASE			UL(0xB1800000)
+#define SPEAR1310_PCIE2_BASE			UL(0xB4000000)
 
 /* RAS Area Control Register */
 #define VA_SPEAR1310_RAS_CTRL_REG1	(VA_SPEAR1310_RAS_BASE + 0x4)
@@ -57,6 +61,81 @@
 #define SPEAR1310_PERIP1_SW_RST			(VA_MISC_BASE + 0x308)
 #define SPEAR1310_UOC_RST_ENB			11
 
+#define VA_SPEAR1310_PCIE_SATA_CFG		(VA_MISC_BASE + 0x3A4)
+	/* PCIE CFG MASks */
+	#define SPEAR1310_PCIE_SATA2_SEL_PCIE		(0 << 31)
+	#define SPEAR1310_PCIE_SATA1_SEL_PCIE		(0 << 30)
+	#define SPEAR1310_PCIE_SATA0_SEL_PCIE		(0 << 29)
+	#define SPEAR1310_PCIE_SATA2_SEL_SATA		(1 << 31)
+	#define SPEAR1310_PCIE_SATA1_SEL_SATA		(1 << 30)
+	#define SPEAR1310_PCIE_SATA0_SEL_SATA		(1 << 29)
+	#define SPEAR1310_SATA2_CFG_TX_CLK_EN		(1 << 27)
+	#define SPEAR1310_SATA2_CFG_RX_CLK_EN		(1 << 26)
+	#define SPEAR1310_SATA2_CFG_POWERUP_RESET	(1 << 25)
+	#define SPEAR1310_SATA2_CFG_PM_CLK_EN		(1 << 24)
+	#define SPEAR1310_SATA1_CFG_TX_CLK_EN		(1 << 23)
+	#define SPEAR1310_SATA1_CFG_RX_CLK_EN		(1 << 22)
+	#define SPEAR1310_SATA1_CFG_POWERUP_RESET	(1 << 21)
+	#define SPEAR1310_SATA1_CFG_PM_CLK_EN		(1 << 20)
+	#define SPEAR1310_SATA0_CFG_TX_CLK_EN		(1 << 19)
+	#define SPEAR1310_SATA0_CFG_RX_CLK_EN		(1 << 18)
+	#define SPEAR1310_SATA0_CFG_POWERUP_RESET	(1 << 17)
+	#define SPEAR1310_SATA0_CFG_PM_CLK_EN		(1 << 16)
+	#define SPEAR1310_PCIE2_CFG_DEVICE_PRESENT	(1 << 11)
+	#define SPEAR1310_PCIE2_CFG_POWERUP_RESET	(1 << 10)
+	#define SPEAR1310_PCIE2_CFG_CORE_CLK_EN		(1 << 9)
+	#define SPEAR1310_PCIE2_CFG_AUX_CLK_EN		(1 << 8)
+	#define SPEAR1310_PCIE1_CFG_DEVICE_PRESENT	(1 << 7)
+	#define SPEAR1310_PCIE1_CFG_POWERUP_RESET	(1 << 6)
+	#define SPEAR1310_PCIE1_CFG_CORE_CLK_EN		(1 << 5)
+	#define SPEAR1310_PCIE1_CFG_AUX_CLK_EN		(1 << 4)
+	#define SPEAR1310_PCIE0_CFG_DEVICE_PRESENT	(1 << 3)
+	#define SPEAR1310_PCIE0_CFG_POWERUP_RESET	(1 << 2)
+	#define SPEAR1310_PCIE0_CFG_CORE_CLK_EN		(1 << 1)
+	#define SPEAR1310_PCIE0_CFG_AUX_CLK_EN		(1 << 0)
+
+	#define SPEAR1310_PCIE_CFG_MASK(x) ((0xF << (x * 4)) | (1 << (x + 29)))
+	#define SPEAR1310_SATA_CFG_MASK(x) ((0xF << (x * 4 + 16)) | \
+			(1 << (x + 29)))
+	#define SPEAR1310_PCIE_CFG_VAL(x) \
+			(SPEAR1310_PCIE_SATA##x##_SEL_PCIE | \
+			SPEAR1310_PCIE##x##_CFG_AUX_CLK_EN | \
+			SPEAR1310_PCIE##x##_CFG_CORE_CLK_EN | \
+			SPEAR1310_PCIE##x##_CFG_POWERUP_RESET | \
+			SPEAR1310_PCIE##x##_CFG_DEVICE_PRESENT)
+	#define SPEAR1310_SATA_CFG_VAL(x) \
+			(SPEAR1310_PCIE_SATA##x##_SEL_SATA | \
+			SPEAR1310_SATA##x##_CFG_PM_CLK_EN | \
+			SPEAR1310_SATA##x##_CFG_POWERUP_RESET | \
+			SPEAR1310_SATA##x##_CFG_RX_CLK_EN | \
+			SPEAR1310_SATA##x##_CFG_TX_CLK_EN)
+
+#define VA_SPEAR1310_PCIE_MIPHY_CFG_1		(VA_MISC_BASE + 0x3A8)
+	#define SPEAR1310_MIPHY_DUAL_OSC_BYPASS_EXT	(1 << 31)
+	#define SPEAR1310_MIPHY_DUAL_CLK_REF_DIV2	(1 << 28)
+	#define SPEAR1310_MIPHY_DUAL_PLL_RATIO_TOP(x)	(x << 16)
+	#define SPEAR1310_MIPHY_SINGLE_OSC_BYPASS_EXT	(1 << 15)
+	#define SPEAR1310_MIPHY_SINGLE_CLK_REF_DIV2	(1 << 12)
+	#define SPEAR1310_MIPHY_SINGLE_PLL_RATIO_TOP(x)	(x << 0)
+	#define SPEAR1310_PCIE_SATA_MIPHY_CFG_SATA_MASK (0xFFFF)
+	#define SPEAR1310_PCIE_SATA_MIPHY_CFG_PCIE_MASK (0xFFFF << 16)
+	#define SPEAR1310_PCIE_SATA_MIPHY_CFG_SATA \
+			(SPEAR1310_MIPHY_DUAL_OSC_BYPASS_EXT | \
+			SPEAR1310_MIPHY_DUAL_CLK_REF_DIV2 | \
+			SPEAR1310_MIPHY_DUAL_PLL_RATIO_TOP(60) | \
+			SPEAR1310_MIPHY_SINGLE_OSC_BYPASS_EXT | \
+			SPEAR1310_MIPHY_SINGLE_CLK_REF_DIV2 | \
+			SPEAR1310_MIPHY_SINGLE_PLL_RATIO_TOP(60))
+	#define SPEAR1310_PCIE_SATA_MIPHY_CFG_SATA_25M_CRYSTAL_CLK \
+			(SPEAR1310_MIPHY_SINGLE_PLL_RATIO_TOP(120))
+	#define SPEAR1310_PCIE_SATA_MIPHY_CFG_PCIE \
+			(SPEAR1310_MIPHY_DUAL_OSC_BYPASS_EXT | \
+			SPEAR1310_MIPHY_DUAL_PLL_RATIO_TOP(25) | \
+			SPEAR1310_MIPHY_SINGLE_OSC_BYPASS_EXT | \
+			SPEAR1310_MIPHY_SINGLE_PLL_RATIO_TOP(25))
+
+#define VA_SPEAR1310_PCIE_MIPHY_CFG_2		(VA_MISC_BASE + 0x3AC)
+
 static int spear1310_eth_phy_clk_cfg(struct platform_device *pdev)
 {
 	struct plat_stmmacenet_data *pdata = dev_get_platdata(&pdev->dev);
@@ -342,6 +421,69 @@ static struct dwc_otg_plat_data spear1310_otg_plat_data = {
 	.phy_init = spear1310_otg_phy_init,
 };
 
+static int spear1310_pcie_clk_init(struct pcie_port *pp)
+{
+	u32 temp;
+
+	temp = readl(VA_SPEAR1310_PCIE_MIPHY_CFG_1);
+	temp &= ~SPEAR1310_PCIE_SATA_MIPHY_CFG_PCIE_MASK;
+	temp |= SPEAR1310_PCIE_SATA_MIPHY_CFG_PCIE;
+
+	writel(temp, VA_SPEAR1310_PCIE_MIPHY_CFG_1);
+
+	temp = readl(VA_SPEAR1310_PCIE_SATA_CFG);
+
+	switch (pp->controller) {
+	case 0:
+		temp &= ~SPEAR1310_PCIE_CFG_MASK(0);
+		temp |= SPEAR1310_PCIE_CFG_VAL(0);
+		break;
+	case 1:
+		temp &= ~SPEAR1310_PCIE_CFG_MASK(1);
+		temp |= SPEAR1310_PCIE_CFG_VAL(1);
+		break;
+	case 2:
+		temp &= ~SPEAR1310_PCIE_CFG_MASK(2);
+		temp |= SPEAR1310_PCIE_CFG_VAL(2);
+		break;
+	default:
+		return -EINVAL;
+	}
+	writel(temp, VA_SPEAR1310_PCIE_SATA_CFG);
+
+	return 0;
+}
+
+static int spear1310_pcie_clk_exit(struct pcie_port *pp)
+{
+	u32 temp;
+
+	temp = readl(VA_SPEAR1310_PCIE_SATA_CFG);
+
+	switch (pp->controller) {
+	case 0:
+		temp &= ~SPEAR1310_PCIE_CFG_MASK(0);
+		break;
+	case 1:
+		temp &= ~SPEAR1310_PCIE_CFG_MASK(1);
+		break;
+	case 2:
+		temp &= ~SPEAR1310_PCIE_CFG_MASK(2);
+		break;
+	}
+
+	writel(temp, VA_SPEAR1310_PCIE_SATA_CFG);
+	writel(~SPEAR1310_PCIE_SATA_MIPHY_CFG_PCIE_MASK,
+			VA_SPEAR1310_PCIE_MIPHY_CFG_1);
+
+	return 0;
+}
+
+static struct pcie_port_info pcie_pdata = {
+	.clk_init = spear1310_pcie_clk_init,
+	.clk_exit = spear1310_pcie_clk_exit,
+};
+
 /* Add SPEAr1310 auxdata to pass platform data */
 static struct of_dev_auxdata spear1310_auxdata_lookup[] __initdata = {
 	OF_DEV_AUXDATA("st,spear-adc", SPEAR13XX_ADC_BASE, NULL, &adc_pdata),
@@ -363,6 +505,12 @@ static struct of_dev_auxdata spear1310_auxdata_lookup[] __initdata = {
 			&eth4_data),
 	OF_DEV_AUXDATA("snps,usb-otg", SPEAR_UOC_BASE, NULL,
 			&spear1310_otg_plat_data),
+	OF_DEV_AUXDATA("st,pcie-host", SPEAR1310_PCIE0_BASE, NULL,
+			&pcie_pdata),
+	OF_DEV_AUXDATA("st,pcie-host", SPEAR1310_PCIE1_BASE, NULL,
+			&pcie_pdata),
+	OF_DEV_AUXDATA("st,pcie-host", SPEAR1310_PCIE2_BASE, NULL,
+			&pcie_pdata),
 	OF_DEV_AUXDATA("st,db9000-clcd", SPEAR13XX_CLCD_BASE, NULL,
 			&clcd_plat_info),
 	{}
-- 
1.7.5.4


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

* [PATCH 09/15] SPEAr13xx: dts: Fix PCIe core address ranges
  2012-10-29  7:01 ` Pratyush Anand
@ 2012-10-29  7:01   ` Pratyush Anand
  -1 siblings, 0 replies; 56+ messages in thread
From: Pratyush Anand @ 2012-10-29  7:01 UTC (permalink / raw)
  To: arnd, shiraz.hashim, viresh.linux
  Cc: spear-devel, linux-pci, devicetree-discuss, olof, Pratyush Anand

Each PCIe controller has 256 MB of address space whcih is accessible by
AHB and used to communicate with PCIe devices connected with the host
controller.

Signed-off-by: Pratyush Anand <pratyush.anand@st.com>
---
 arch/arm/boot/dts/spear13xx.dtsi |    9 +++++----
 1 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/arch/arm/boot/dts/spear13xx.dtsi b/arch/arm/boot/dts/spear13xx.dtsi
index 9ff4f5f..b7990754 100644
--- a/arch/arm/boot/dts/spear13xx.dtsi
+++ b/arch/arm/boot/dts/spear13xx.dtsi
@@ -76,7 +76,8 @@
 		#size-cells = <1>;
 		compatible = "simple-bus";
 		ranges = <0x50000000 0x50000000 0x10000000
-			  0xb0000000 0xb0000000 0x10000000
+			  0x80000000 0x80000000 0x20000000
+			  0xb0000000 0xb0000000 0x20000000
 			  0xd0000000 0xd0000000 0x02000000
 			  0xd8000000 0xd8000000 0x01000000
 			  0xe0000000 0xe0000000 0x10000000>;
@@ -194,7 +195,7 @@
 		pcie0@b1000000 {
 			compatible = "st,pcie-gadget", "st,pcie-host" ;
 			reg = < 0xb1000000 0x4000
-				0x80000000 0x2000
+				0x80000000 0x10000000
 				0xeb800000 0x1000 >;
 			interrupts = <0 68 0x4>;
 			status = "disabled";
@@ -203,7 +204,7 @@
 		pcie1@b1800000 {
 			compatible = "st,pcie-gadget", "st,pcie-host" ;
 			reg = < 0xb1800000 0x4000
-				0x90000000 0x2000
+				0x90000000 0x10000000
 				0xeb804000 0x1000 >;
 			interrupts = <0 69 0x4>;
 			status = "disabled";
@@ -212,7 +213,7 @@
 		pcie2@b4000000 {
 			compatible = "st,pcie-gadget", "st,pcie-host" ;
 			reg = < 0xb4000000 0x4000
-				0xc0000000 0x2000
+				0xc0000000 0x10000000
 				0xeb808000 0x1000 >;
 			interrupts = <0 70 0x4>;
 			status = "disabled";
-- 
1.7.5.4

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

* [PATCH 09/15] SPEAr13xx: dts: Fix PCIe core address ranges
@ 2012-10-29  7:01   ` Pratyush Anand
  0 siblings, 0 replies; 56+ messages in thread
From: Pratyush Anand @ 2012-10-29  7:01 UTC (permalink / raw)
  To: arnd, shiraz.hashim, viresh.linux
  Cc: spear-devel, linux-pci, devicetree-discuss, olof, Pratyush Anand

Each PCIe controller has 256 MB of address space whcih is accessible by
AHB and used to communicate with PCIe devices connected with the host
controller.

Signed-off-by: Pratyush Anand <pratyush.anand@st.com>
---
 arch/arm/boot/dts/spear13xx.dtsi |    9 +++++----
 1 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/arch/arm/boot/dts/spear13xx.dtsi b/arch/arm/boot/dts/spear13xx.dtsi
index 9ff4f5f..b7990754 100644
--- a/arch/arm/boot/dts/spear13xx.dtsi
+++ b/arch/arm/boot/dts/spear13xx.dtsi
@@ -76,7 +76,8 @@
 		#size-cells = <1>;
 		compatible = "simple-bus";
 		ranges = <0x50000000 0x50000000 0x10000000
-			  0xb0000000 0xb0000000 0x10000000
+			  0x80000000 0x80000000 0x20000000
+			  0xb0000000 0xb0000000 0x20000000
 			  0xd0000000 0xd0000000 0x02000000
 			  0xd8000000 0xd8000000 0x01000000
 			  0xe0000000 0xe0000000 0x10000000>;
@@ -194,7 +195,7 @@
 		pcie0@b1000000 {
 			compatible = "st,pcie-gadget", "st,pcie-host" ;
 			reg = < 0xb1000000 0x4000
-				0x80000000 0x2000
+				0x80000000 0x10000000
 				0xeb800000 0x1000 >;
 			interrupts = <0 68 0x4>;
 			status = "disabled";
@@ -203,7 +204,7 @@
 		pcie1@b1800000 {
 			compatible = "st,pcie-gadget", "st,pcie-host" ;
 			reg = < 0xb1800000 0x4000
-				0x90000000 0x2000
+				0x90000000 0x10000000
 				0xeb804000 0x1000 >;
 			interrupts = <0 69 0x4>;
 			status = "disabled";
@@ -212,7 +213,7 @@
 		pcie2@b4000000 {
 			compatible = "st,pcie-gadget", "st,pcie-host" ;
 			reg = < 0xb4000000 0x4000
-				0xc0000000 0x2000
+				0xc0000000 0x10000000
 				0xeb808000 0x1000 >;
 			interrupts = <0 70 0x4>;
 			status = "disabled";
-- 
1.7.5.4


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

* [PATCH 10/15] SPEAr13xx: DTS: Add auxiliary data for PCIe host
  2012-10-29  7:01 ` Pratyush Anand
@ 2012-10-29  7:01   ` Pratyush Anand
  -1 siblings, 0 replies; 56+ messages in thread
From: Pratyush Anand @ 2012-10-29  7:01 UTC (permalink / raw)
  To: arnd, shiraz.hashim, viresh.linux
  Cc: spear-devel, linux-pci, devicetree-discuss, olof, Pratyush Anand

Signed-off-by: Pratyush Anand <pratyush.anand@st.com>
---
 arch/arm/boot/dts/spear13xx.dtsi |   24 ++++++++++++++++++++++++
 1 files changed, 24 insertions(+), 0 deletions(-)

diff --git a/arch/arm/boot/dts/spear13xx.dtsi b/arch/arm/boot/dts/spear13xx.dtsi
index b7990754..fe55d21 100644
--- a/arch/arm/boot/dts/spear13xx.dtsi
+++ b/arch/arm/boot/dts/spear13xx.dtsi
@@ -199,6 +199,14 @@
 				0xeb800000 0x1000 >;
 			interrupts = <0 68 0x4>;
 			status = "disabled";
+			pcie-host,is_host = <1>;
+			pcie-host,is_gen1 = <0>;
+			pcie-host,cfg0_size = <0x100000>;
+			pcie-host,cfg1_size = <0x100000>;
+			pcie-host,mem_size = <0xFC00000>;
+			pcie-host,msg_size = <0x100000>;
+			/* Entire DDR Area */
+			pcie-host,in_mem_size = <0x80000000>;
 		};
 
 		pcie1@b1800000 {
@@ -208,6 +216,14 @@
 				0xeb804000 0x1000 >;
 			interrupts = <0 69 0x4>;
 			status = "disabled";
+			pcie-host,is_host = <1>;
+			pcie-host,is_gen1 = <0>;
+			pcie-host,cfg0_size = <0x100000>;
+			pcie-host,cfg1_size = <0x100000>;
+			pcie-host,mem_size = <0xFC00000>;
+			pcie-host,msg_size = <0x100000>;
+			/* Entire DDR Area */
+			pcie-host,in_mem_size = <0x80000000>;
 		};
 
 		pcie2@b4000000 {
@@ -217,6 +233,14 @@
 				0xeb808000 0x1000 >;
 			interrupts = <0 70 0x4>;
 			status = "disabled";
+			pcie-host,is_host = <1>;
+			pcie-host,is_gen1 = <0>;
+			pcie-host,cfg0_size = <0x100000>;
+			pcie-host,cfg1_size = <0x100000>;
+			pcie-host,mem_size = <0xFC00000>;
+			pcie-host,msg_size = <0x100000>;
+			/* Entire DDR Area */
+			pcie-host,in_mem_size = <0x80000000>;
 		};
 
 		c3@e1800000 {
-- 
1.7.5.4

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

* [PATCH 10/15] SPEAr13xx: DTS: Add auxiliary data for PCIe host
@ 2012-10-29  7:01   ` Pratyush Anand
  0 siblings, 0 replies; 56+ messages in thread
From: Pratyush Anand @ 2012-10-29  7:01 UTC (permalink / raw)
  To: arnd, shiraz.hashim, viresh.linux
  Cc: spear-devel, linux-pci, devicetree-discuss, olof, Pratyush Anand

Signed-off-by: Pratyush Anand <pratyush.anand@st.com>
---
 arch/arm/boot/dts/spear13xx.dtsi |   24 ++++++++++++++++++++++++
 1 files changed, 24 insertions(+), 0 deletions(-)

diff --git a/arch/arm/boot/dts/spear13xx.dtsi b/arch/arm/boot/dts/spear13xx.dtsi
index b7990754..fe55d21 100644
--- a/arch/arm/boot/dts/spear13xx.dtsi
+++ b/arch/arm/boot/dts/spear13xx.dtsi
@@ -199,6 +199,14 @@
 				0xeb800000 0x1000 >;
 			interrupts = <0 68 0x4>;
 			status = "disabled";
+			pcie-host,is_host = <1>;
+			pcie-host,is_gen1 = <0>;
+			pcie-host,cfg0_size = <0x100000>;
+			pcie-host,cfg1_size = <0x100000>;
+			pcie-host,mem_size = <0xFC00000>;
+			pcie-host,msg_size = <0x100000>;
+			/* Entire DDR Area */
+			pcie-host,in_mem_size = <0x80000000>;
 		};
 
 		pcie1@b1800000 {
@@ -208,6 +216,14 @@
 				0xeb804000 0x1000 >;
 			interrupts = <0 69 0x4>;
 			status = "disabled";
+			pcie-host,is_host = <1>;
+			pcie-host,is_gen1 = <0>;
+			pcie-host,cfg0_size = <0x100000>;
+			pcie-host,cfg1_size = <0x100000>;
+			pcie-host,mem_size = <0xFC00000>;
+			pcie-host,msg_size = <0x100000>;
+			/* Entire DDR Area */
+			pcie-host,in_mem_size = <0x80000000>;
 		};
 
 		pcie2@b4000000 {
@@ -217,6 +233,14 @@
 				0xeb808000 0x1000 >;
 			interrupts = <0 70 0x4>;
 			status = "disabled";
+			pcie-host,is_host = <1>;
+			pcie-host,is_gen1 = <0>;
+			pcie-host,cfg0_size = <0x100000>;
+			pcie-host,cfg1_size = <0x100000>;
+			pcie-host,mem_size = <0xFC00000>;
+			pcie-host,msg_size = <0x100000>;
+			/* Entire DDR Area */
+			pcie-host,in_mem_size = <0x80000000>;
 		};
 
 		c3@e1800000 {
-- 
1.7.5.4


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

* [PATCH 11/15] SPEAr1340-evb: dts: Enable PCIe0
  2012-10-29  7:01 ` Pratyush Anand
@ 2012-10-29  7:01   ` Pratyush Anand
  -1 siblings, 0 replies; 56+ messages in thread
From: Pratyush Anand @ 2012-10-29  7:01 UTC (permalink / raw)
  To: arnd, shiraz.hashim, viresh.linux
  Cc: spear-devel, linux-pci, devicetree-discuss, olof, Pratyush Anand

Signed-off-by: Pratyush Anand <pratyush.anand@st.com>
---
 arch/arm/boot/dts/spear1340-evb.dts |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/arch/arm/boot/dts/spear1340-evb.dts b/arch/arm/boot/dts/spear1340-evb.dts
index fb5ae40..926781c 100644
--- a/arch/arm/boot/dts/spear1340-evb.dts
+++ b/arch/arm/boot/dts/spear1340-evb.dts
@@ -228,6 +228,10 @@
 			};
 		};
 
+		pcie0@b1000000 {
+			status = "okay";
+		};
+
 		ehci@e4800000 {
 			status = "okay";
 		};
-- 
1.7.5.4

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

* [PATCH 11/15] SPEAr1340-evb: dts: Enable PCIe0
@ 2012-10-29  7:01   ` Pratyush Anand
  0 siblings, 0 replies; 56+ messages in thread
From: Pratyush Anand @ 2012-10-29  7:01 UTC (permalink / raw)
  To: arnd, shiraz.hashim, viresh.linux
  Cc: spear-devel, linux-pci, devicetree-discuss, olof, Pratyush Anand

Signed-off-by: Pratyush Anand <pratyush.anand@st.com>
---
 arch/arm/boot/dts/spear1340-evb.dts |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/arch/arm/boot/dts/spear1340-evb.dts b/arch/arm/boot/dts/spear1340-evb.dts
index fb5ae40..926781c 100644
--- a/arch/arm/boot/dts/spear1340-evb.dts
+++ b/arch/arm/boot/dts/spear1340-evb.dts
@@ -228,6 +228,10 @@
 			};
 		};
 
+		pcie0@b1000000 {
+			status = "okay";
+		};
+
 		ehci@e4800000 {
 			status = "okay";
 		};
-- 
1.7.5.4


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

* [PATCH 12/15] SPEAr1310-EVB: DTS: Fix PCIe1 enable
  2012-10-29  7:01 ` Pratyush Anand
@ 2012-10-29  7:01   ` Pratyush Anand
  -1 siblings, 0 replies; 56+ messages in thread
From: Pratyush Anand @ 2012-10-29  7:01 UTC (permalink / raw)
  To: arnd, shiraz.hashim, viresh.linux
  Cc: spear-devel, linux-pci, devicetree-discuss, olof, Pratyush Anand

On SPEAr1310 EVB only PCIe2 can be used as PCIe host. Currently we do not
have driver for PCIe EP. So keep PCIe1 disabled.

Signed-off-by: Pratyush Anand <pratyush.anand@st.com>
---
 arch/arm/boot/dts/spear1310-evb.dts |    4 ----
 1 files changed, 0 insertions(+), 4 deletions(-)

diff --git a/arch/arm/boot/dts/spear1310-evb.dts b/arch/arm/boot/dts/spear1310-evb.dts
index 2c8da65..1bb5332 100644
--- a/arch/arm/boot/dts/spear1310-evb.dts
+++ b/arch/arm/boot/dts/spear1310-evb.dts
@@ -237,10 +237,6 @@
 			ignore_cpufreq_notification = <0>;
 		};
 
-		pcie1@b1800000 {
-			status = "okay";
-		};
-
 		pcie2@b4000000 {
 			status = "okay";
 		};
-- 
1.7.5.4

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

* [PATCH 12/15] SPEAr1310-EVB: DTS: Fix PCIe1 enable
@ 2012-10-29  7:01   ` Pratyush Anand
  0 siblings, 0 replies; 56+ messages in thread
From: Pratyush Anand @ 2012-10-29  7:01 UTC (permalink / raw)
  To: arnd, shiraz.hashim, viresh.linux
  Cc: spear-devel, linux-pci, devicetree-discuss, olof, Pratyush Anand

On SPEAr1310 EVB only PCIe2 can be used as PCIe host. Currently we do not
have driver for PCIe EP. So keep PCIe1 disabled.

Signed-off-by: Pratyush Anand <pratyush.anand@st.com>
---
 arch/arm/boot/dts/spear1310-evb.dts |    4 ----
 1 files changed, 0 insertions(+), 4 deletions(-)

diff --git a/arch/arm/boot/dts/spear1310-evb.dts b/arch/arm/boot/dts/spear1310-evb.dts
index 2c8da65..1bb5332 100644
--- a/arch/arm/boot/dts/spear1310-evb.dts
+++ b/arch/arm/boot/dts/spear1310-evb.dts
@@ -237,10 +237,6 @@
 			ignore_cpufreq_notification = <0>;
 		};
 
-		pcie1@b1800000 {
-			status = "okay";
-		};
-
 		pcie2@b4000000 {
 			status = "okay";
 		};
-- 
1.7.5.4


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

* [PATCH 13/15] SPEAr13xx: update kconfig for PCIe selection
  2012-10-29  7:01 ` Pratyush Anand
@ 2012-10-29  7:01   ` Pratyush Anand
  -1 siblings, 0 replies; 56+ messages in thread
From: Pratyush Anand @ 2012-10-29  7:01 UTC (permalink / raw)
  To: arnd, shiraz.hashim, viresh.linux
  Cc: spear-devel, linux-pci, devicetree-discuss, olof, Pratyush Anand

Signed-off-by: Pratyush Anand <pratyush.anand@st.com>
---
 arch/arm/mach-spear13xx/Kconfig |   12 ++++++++++++
 1 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-spear13xx/Kconfig b/arch/arm/mach-spear13xx/Kconfig
index eaadc66..4817314 100644
--- a/arch/arm/mach-spear13xx/Kconfig
+++ b/arch/arm/mach-spear13xx/Kconfig
@@ -16,5 +16,17 @@ config MACH_SPEAR1340
 	select PINCTRL_SPEAR1340
 	help
 	  Supports ST SPEAr1340 machine configured via the device-tree
+
 endmenu
+
+config SPEAR13XX_PCI
+	bool "PCI Express support"
+	select PCI
+	select PCIEPORTBUS
+	select ARCH_SUPPORTS_MSI
+	select PCI_MSI
+	select NEED_MACH_IO_H
+	help
+	  Support SPEAr13xx PCIe Dual controler as a host
+
 endif #ARCH_SPEAR13XX
-- 
1.7.5.4

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

* [PATCH 13/15] SPEAr13xx: update kconfig for PCIe selection
@ 2012-10-29  7:01   ` Pratyush Anand
  0 siblings, 0 replies; 56+ messages in thread
From: Pratyush Anand @ 2012-10-29  7:01 UTC (permalink / raw)
  To: arnd, shiraz.hashim, viresh.linux
  Cc: spear-devel, linux-pci, devicetree-discuss, olof, Pratyush Anand

Signed-off-by: Pratyush Anand <pratyush.anand@st.com>
---
 arch/arm/mach-spear13xx/Kconfig |   12 ++++++++++++
 1 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-spear13xx/Kconfig b/arch/arm/mach-spear13xx/Kconfig
index eaadc66..4817314 100644
--- a/arch/arm/mach-spear13xx/Kconfig
+++ b/arch/arm/mach-spear13xx/Kconfig
@@ -16,5 +16,17 @@ config MACH_SPEAR1340
 	select PINCTRL_SPEAR1340
 	help
 	  Supports ST SPEAr1340 machine configured via the device-tree
+
 endmenu
+
+config SPEAR13XX_PCI
+	bool "PCI Express support"
+	select PCI
+	select PCIEPORTBUS
+	select ARCH_SUPPORTS_MSI
+	select PCI_MSI
+	select NEED_MACH_IO_H
+	help
+	  Support SPEAr13xx PCIe Dual controler as a host
+
 endif #ARCH_SPEAR13XX
-- 
1.7.5.4


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

* [PATCH 14/15] SPEAR13xx: Update makefile for PCIe inclusion
  2012-10-29  7:01 ` Pratyush Anand
@ 2012-10-29  7:01   ` Pratyush Anand
  -1 siblings, 0 replies; 56+ messages in thread
From: Pratyush Anand @ 2012-10-29  7:01 UTC (permalink / raw)
  To: arnd, shiraz.hashim, viresh.linux
  Cc: spear-devel, linux-pci, devicetree-discuss, olof, Pratyush Anand

Signed-off-by: Pratyush Anand <pratyush.anand@st.com>
---
 arch/arm/mach-spear13xx/Makefile |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-spear13xx/Makefile b/arch/arm/mach-spear13xx/Makefile
index b721566..f7a42fb 100644
--- a/arch/arm/mach-spear13xx/Makefile
+++ b/arch/arm/mach-spear13xx/Makefile
@@ -9,3 +9,4 @@ obj-$(CONFIG_ARCH_SPEAR13XX)	+= spear13xx.o
 obj-$(CONFIG_SUSPEND)		+= pm.o wakeup.o sleep_1340.o sleep_1310.o
 obj-$(CONFIG_MACH_SPEAR1310)	+= spear1310.o
 obj-$(CONFIG_MACH_SPEAR1340)	+= spear1340.o
+obj-$(CONFIG_SPEAR13XX_PCI)	+= pcie.o
-- 
1.7.5.4

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

* [PATCH 14/15] SPEAR13xx: Update makefile for PCIe inclusion
@ 2012-10-29  7:01   ` Pratyush Anand
  0 siblings, 0 replies; 56+ messages in thread
From: Pratyush Anand @ 2012-10-29  7:01 UTC (permalink / raw)
  To: arnd, shiraz.hashim, viresh.linux
  Cc: spear-devel, linux-pci, devicetree-discuss, olof, Pratyush Anand

Signed-off-by: Pratyush Anand <pratyush.anand@st.com>
---
 arch/arm/mach-spear13xx/Makefile |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-spear13xx/Makefile b/arch/arm/mach-spear13xx/Makefile
index b721566..f7a42fb 100644
--- a/arch/arm/mach-spear13xx/Makefile
+++ b/arch/arm/mach-spear13xx/Makefile
@@ -9,3 +9,4 @@ obj-$(CONFIG_ARCH_SPEAR13XX)	+= spear13xx.o
 obj-$(CONFIG_SUSPEND)		+= pm.o wakeup.o sleep_1340.o sleep_1310.o
 obj-$(CONFIG_MACH_SPEAR1310)	+= spear1310.o
 obj-$(CONFIG_MACH_SPEAR1340)	+= spear1340.o
+obj-$(CONFIG_SPEAR13XX_PCI)	+= pcie.o
-- 
1.7.5.4


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

* [PATCH 15/15] SPEAR13xx: update defconfig for PCIe compilation
  2012-10-29  7:01 ` Pratyush Anand
@ 2012-10-29  7:01   ` Pratyush Anand
  -1 siblings, 0 replies; 56+ messages in thread
From: Pratyush Anand @ 2012-10-29  7:01 UTC (permalink / raw)
  To: arnd, shiraz.hashim, viresh.linux
  Cc: spear-devel, linux-pci, devicetree-discuss, olof, Pratyush Anand

Signed-off-by: Pratyush Anand <pratyush.anand@st.com>
---
 arch/arm/configs/spear13xx_defconfig |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/arch/arm/configs/spear13xx_defconfig b/arch/arm/configs/spear13xx_defconfig
index 3b559b8..cd9a150 100644
--- a/arch/arm/configs/spear13xx_defconfig
+++ b/arch/arm/configs/spear13xx_defconfig
@@ -14,6 +14,7 @@ CONFIG_PLAT_SPEAR=y
 CONFIG_ARCH_SPEAR13XX=y
 CONFIG_MACH_SPEAR1310=y
 CONFIG_MACH_SPEAR1340=y
+CONFIG_SPEAR13XX_PCI=y
 # CONFIG_SWP_EMULATE is not set
 CONFIG_SMP=y
 # CONFIG_ARM_CPU_TOPOLOGY is not set
-- 
1.7.5.4

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

* [PATCH 15/15] SPEAR13xx: update defconfig for PCIe compilation
@ 2012-10-29  7:01   ` Pratyush Anand
  0 siblings, 0 replies; 56+ messages in thread
From: Pratyush Anand @ 2012-10-29  7:01 UTC (permalink / raw)
  To: arnd, shiraz.hashim, viresh.linux
  Cc: spear-devel, linux-pci, devicetree-discuss, olof, Pratyush Anand

Signed-off-by: Pratyush Anand <pratyush.anand@st.com>
---
 arch/arm/configs/spear13xx_defconfig |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/arch/arm/configs/spear13xx_defconfig b/arch/arm/configs/spear13xx_defconfig
index 3b559b8..cd9a150 100644
--- a/arch/arm/configs/spear13xx_defconfig
+++ b/arch/arm/configs/spear13xx_defconfig
@@ -14,6 +14,7 @@ CONFIG_PLAT_SPEAR=y
 CONFIG_ARCH_SPEAR13XX=y
 CONFIG_MACH_SPEAR1310=y
 CONFIG_MACH_SPEAR1340=y
+CONFIG_SPEAR13XX_PCI=y
 # CONFIG_SWP_EMULATE is not set
 CONFIG_SMP=y
 # CONFIG_ARM_CPU_TOPOLOGY is not set
-- 
1.7.5.4


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

* Re: [PATCH 00/15] SPEAr13xx PCIe patches
  2012-10-29  7:01 ` Pratyush Anand
                   ` (15 preceding siblings ...)
  (?)
@ 2012-10-29  7:16 ` viresh kumar
  2012-10-29  7:22   ` Pratyush Anand
  -1 siblings, 1 reply; 56+ messages in thread
From: viresh kumar @ 2012-10-29  7:16 UTC (permalink / raw)
  To: Pratyush Anand, arm
  Cc: arnd, shiraz.hashim, spear-devel, linux-pci, devicetree-discuss, olof

On Mon, Oct 29, 2012 at 12:31 PM, Pratyush Anand <pratyush.anand@st.com> wrote:
> -- First two patches are common for all platforms on ARM architecture.
> -- Remaining patches belongs to SPEAr13xx architecture.
> -- SPEAr13xx supports both RC and EP mode of PCIe interface. This patchset
>         supports only RC mode.

Hi Pratyush,

For ARM SoC specific patches, that you want Arnd or Olof to apply, please send
them to arm@kernel.org. Arnd and Olof push ARM SoC trees in turns and they
pick them from arm@kernel.org.

--
viresh

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

* Re: [PATCH 00/15] SPEAr13xx PCIe patches
  2012-10-29  7:16 ` [PATCH 00/15] SPEAr13xx PCIe patches viresh kumar
@ 2012-10-29  7:22   ` Pratyush Anand
  0 siblings, 0 replies; 56+ messages in thread
From: Pratyush Anand @ 2012-10-29  7:22 UTC (permalink / raw)
  To: viresh kumar
  Cc: arm, arnd, Shiraz HASHIM, spear-devel, linux-pci,
	devicetree-discuss, olof

Hi Viresh,

On 10/29/2012 12:46 PM, viresh kumar wrote:
> On Mon, Oct 29, 2012 at 12:31 PM, Pratyush Anand <pratyush.anand@st.com> wrote:
>> -- First two patches are common for all platforms on ARM architecture.
>> -- Remaining patches belongs to SPEAr13xx architecture.
>> -- SPEAr13xx supports both RC and EP mode of PCIe interface. This patchset
>>          supports only RC mode.
>
> Hi Pratyush,
>
> For ARM SoC specific patches, that you want Arnd or Olof to apply, please send
> them to arm@kernel.org. Arnd and Olof push ARM SoC trees in turns and they
> pick them from arm@kernel.org.

Ok, I will wait for few days if any more comment is received, and V2 is 
needed then will take care during v2, else I will resend V1 to this id 
after few days.


>
> --
> viresh
> .
>

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

* Re: [PATCH 03/15] SPEAr13xx: Add mach/io.h
  2012-10-29  7:01   ` Pratyush Anand
  (?)
@ 2012-10-29  7:29   ` viresh kumar
  2012-10-29  8:11     ` Pratyush Anand
  -1 siblings, 1 reply; 56+ messages in thread
From: viresh kumar @ 2012-10-29  7:29 UTC (permalink / raw)
  To: Pratyush Anand
  Cc: arnd, shiraz.hashim, spear-devel, linux-pci, devicetree-discuss, olof

On Mon, Oct 29, 2012 at 12:31 PM, Pratyush Anand <pratyush.anand@st.com> wrote:
> In case of PCIe we need to have a different __io macro, which can write
> into PCIe address space.

You may find this interesting:

Do, git log --stat -p dd9bf78040fa0da4cecc228e1682b9682b8cb180

There is a series of commits like:

commit dd9bf78040fa0da4cecc228e1682b9682b8cb180
Author: Rob Herring <rob.herring@calxeda.com>
Date:   Wed Jul 4 11:18:40 2012 -0500

    ARM: iop3xx: use fixed PCI i/o mapping

    Move iop33x and iop32x PCI to fixed i/o mapping and remove io.h. This
    changes the PCI bus addresses from the cpu address to 0 based. It appears
    that there is translation h/w for this, but its untested.

    Not sure what to do with io_offset. I think it should always be 0.
    AFAICT, PCI setup is skipped if the ATU is already setup.

    Signed-off-by: Rob Herring <rob.herring@calxeda.com>
    Reviewed-by: Arnd Bergmann <arnd@arndb.de>

All mach/io.h are removed and you are adding one of those. :)

>
> Signed-off-by: Pratyush Anand <pratyush.anand@st.com>
> ---
>  arch/arm/mach-spear13xx/include/mach/io.h |   35 +++++++++++++++++++++++++++++
>  1 files changed, 35 insertions(+), 0 deletions(-)
>  create mode 100644 arch/arm/mach-spear13xx/include/mach/io.h
>
> diff --git a/arch/arm/mach-spear13xx/include/mach/io.h b/arch/arm/mach-spear13xx/include/mach/io.h
> new file mode 100644
> index 0000000..a0d93ca
> --- /dev/null
> +++ b/arch/arm/mach-spear13xx/include/mach/io.h
> @@ -0,0 +1,35 @@
> +/*
> + * arch/arm/mach-spear13xx/include/mach/io.h
> + *
> + * spear13xx machine family generic header file

SPEAr

> + *
> + * Copyright (C) 2012 ST Microelectronics
> + * Pratyush Anand <pratyush.anand@st.com>
> + *
> + * This file is licensed under the terms of the GNU General Public
> + * License version 2. This program is licensed "as is" without any
> + * warranty of any kind, whether express or implied.
> + */
> +
> +#ifndef __MACH_IO_H
> +#define __MACH_IO_H
> +
> +#define IO_SPACE_LIMIT 0xFFFF
> +
> +#ifdef CONFIG_SPEAR13XX_PCI
> +extern void __iomem *spear13xx_pcie_io_base(unsigned long addr);
> +
> +static inline void __iomem *__io(unsigned long addr)
> +{
> +       return spear13xx_pcie_io_base(addr) + (addr & IO_SPACE_LIMIT);
> +}
> +#else
> +static inline void __iomem *__io(unsigned long addr)
> +{
> +       return (void __iomem *)addr;
> +}
> +#endif
> +
> +#define __io(a)                __io(a)
> +
> +#endif /* __MACH_IO_H */
> --
> 1.7.5.4
>

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

* Re: [PATCH 03/15] SPEAr13xx: Add mach/io.h
  2012-10-29  7:29   ` viresh kumar
@ 2012-10-29  8:11     ` Pratyush Anand
       [not found]       ` <508E3A2E.3000204-qxv4g6HH51o@public.gmane.org>
  0 siblings, 1 reply; 56+ messages in thread
From: Pratyush Anand @ 2012-10-29  8:11 UTC (permalink / raw)
  To: viresh kumar
  Cc: arnd, Shiraz HASHIM, spear-devel, linux-pci, devicetree-discuss, olof

On 10/29/2012 12:59 PM, viresh kumar wrote:
> On Mon, Oct 29, 2012 at 12:31 PM, Pratyush Anand <pratyush.anand@st.com> wrote:
>> In case of PCIe we need to have a different __io macro, which can write
>> into PCIe address space.
>
> You may find this interesting:
>
> Do, git log --stat -p dd9bf78040fa0da4cecc228e1682b9682b8cb180
>
> There is a series of commits like:
>
> commit dd9bf78040fa0da4cecc228e1682b9682b8cb180
> Author: Rob Herring <rob.herring@calxeda.com>
> Date:   Wed Jul 4 11:18:40 2012 -0500
>
>      ARM: iop3xx: use fixed PCI i/o mapping
>
>      Move iop33x and iop32x PCI to fixed i/o mapping and remove io.h. This
>      changes the PCI bus addresses from the cpu address to 0 based. It appears
>      that there is translation h/w for this, but its untested.

In case of SPEAr we can not translate a CPU address 0 to PCIe space. To 
explain it better, lets say we allocate 0x0000 - 0xFFFF for PCIe IO 
transaction. Now if CPU writes on these addressed, there is no way we 
can route those transactions to PCIe bus.

Any transaction between 0x80000000 to 0x8FFFFFFF can only be used for 
any type(IO/MEM/CFG0/CFG1) of PCIe transaction. Therefore , we need to 
have this mapping in io.h.

Regards
Pratyush

>
>      Not sure what to do with io_offset. I think it should always be 0.
>      AFAICT, PCI setup is skipped if the ATU is already setup.
>
>      Signed-off-by: Rob Herring <rob.herring@calxeda.com>
>      Reviewed-by: Arnd Bergmann <arnd@arndb.de>
>
> All mach/io.h are removed and you are adding one of those. :)
>
>>
>> Signed-off-by: Pratyush Anand <pratyush.anand@st.com>
>> ---
>>   arch/arm/mach-spear13xx/include/mach/io.h |   35 +++++++++++++++++++++++++++++
>>   1 files changed, 35 insertions(+), 0 deletions(-)
>>   create mode 100644 arch/arm/mach-spear13xx/include/mach/io.h
>>
>> diff --git a/arch/arm/mach-spear13xx/include/mach/io.h b/arch/arm/mach-spear13xx/include/mach/io.h
>> new file mode 100644
>> index 0000000..a0d93ca
>> --- /dev/null
>> +++ b/arch/arm/mach-spear13xx/include/mach/io.h
>> @@ -0,0 +1,35 @@
>> +/*
>> + * arch/arm/mach-spear13xx/include/mach/io.h
>> + *
>> + * spear13xx machine family generic header file
>
> SPEAr
>
>> + *
>> + * Copyright (C) 2012 ST Microelectronics
>> + * Pratyush Anand <pratyush.anand@st.com>
>> + *
>> + * This file is licensed under the terms of the GNU General Public
>> + * License version 2. This program is licensed "as is" without any
>> + * warranty of any kind, whether express or implied.
>> + */
>> +
>> +#ifndef __MACH_IO_H
>> +#define __MACH_IO_H
>> +
>> +#define IO_SPACE_LIMIT 0xFFFF
>> +
>> +#ifdef CONFIG_SPEAR13XX_PCI
>> +extern void __iomem *spear13xx_pcie_io_base(unsigned long addr);
>> +
>> +static inline void __iomem *__io(unsigned long addr)
>> +{
>> +       return spear13xx_pcie_io_base(addr) + (addr & IO_SPACE_LIMIT);
>> +}
>> +#else
>> +static inline void __iomem *__io(unsigned long addr)
>> +{
>> +       return (void __iomem *)addr;
>> +}
>> +#endif
>> +
>> +#define __io(a)                __io(a)
>> +
>> +#endif /* __MACH_IO_H */
>> --
>> 1.7.5.4
>>
> .
>

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

* Re: [PATCH 06/15] clk: SPEAr1310: Fix pcie clock name
  2012-10-29  7:01   ` Pratyush Anand
  (?)
@ 2012-10-29 13:11   ` viresh kumar
  -1 siblings, 0 replies; 56+ messages in thread
From: viresh kumar @ 2012-10-29 13:11 UTC (permalink / raw)
  To: Pratyush Anand
  Cc: arnd, shiraz.hashim, spear-devel, linux-pci, devicetree-discuss, olof

On Mon, Oct 29, 2012 at 12:31 PM, Pratyush Anand <pratyush.anand@st.com> wrote:
> Signed-off-by: Pratyush Anand <pratyush.anand@st.com>
> ---
>  drivers/clk/spear/spear1310_clock.c |    6 +++---
>  1 files changed, 3 insertions(+), 3 deletions(-)

It is not required, that you send one patch per file. If two changes to two
files are having the same purpose, then merge them.

Merge this with 5/15.

Acked-by: Viresh Kumar <viresh.kumar@linaro.org>

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

* Re: [PATCH 09/15] SPEAr13xx: dts: Fix PCIe core address ranges
  2012-10-29  7:01   ` Pratyush Anand
  (?)
@ 2012-10-29 13:23   ` viresh kumar
  2012-10-30  3:23     ` Pratyush Anand
  -1 siblings, 1 reply; 56+ messages in thread
From: viresh kumar @ 2012-10-29 13:23 UTC (permalink / raw)
  To: Pratyush Anand
  Cc: arnd, shiraz.hashim, spear-devel, linux-pci, devicetree-discuss, olof

On Mon, Oct 29, 2012 at 12:31 PM, Pratyush Anand <pratyush.anand@st.com> wrote:
> Each PCIe controller has 256 MB of address space whcih is accessible by
> AHB and used to communicate with PCIe devices connected with the host
> controller.

you haven't said what you have done here in this patch. i.e. extend AHB range
to include pcie space.

> Signed-off-by: Pratyush Anand <pratyush.anand@st.com>
> ---
>  arch/arm/boot/dts/spear13xx.dtsi |    9 +++++----
>  1 files changed, 5 insertions(+), 4 deletions(-)
>
> diff --git a/arch/arm/boot/dts/spear13xx.dtsi b/arch/arm/boot/dts/spear13xx.dtsi
> index 9ff4f5f..b7990754 100644
> --- a/arch/arm/boot/dts/spear13xx.dtsi
> +++ b/arch/arm/boot/dts/spear13xx.dtsi
> @@ -76,7 +76,8 @@
>                 #size-cells = <1>;
>                 compatible = "simple-bus";
>                 ranges = <0x50000000 0x50000000 0x10000000
> -                         0xb0000000 0xb0000000 0x10000000
> +                         0x80000000 0x80000000 0x20000000
> +                         0xb0000000 0xb0000000 0x20000000
>                           0xd0000000 0xd0000000 0x02000000
>                           0xd8000000 0xd8000000 0x01000000
>                           0xe0000000 0xe0000000 0x10000000>;
> @@ -194,7 +195,7 @@
>                 pcie0@b1000000 {
>                         compatible = "st,pcie-gadget", "st,pcie-host" ;
>                         reg = < 0xb1000000 0x4000
> -                               0x80000000 0x2000
> +                               0x80000000 0x10000000
>                                 0xeb800000 0x1000 >;
>                         interrupts = <0 68 0x4>;
>                         status = "disabled";

That's a blunder. I am damn sure, you haven't rebased it
on any rc. And you have rebased it on your local next.

There is no pci support in upstream kernel.

--
viresh

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

* Re: [PATCH 10/15] SPEAr13xx: DTS: Add auxiliary data for PCIe host
  2012-10-29  7:01   ` Pratyush Anand
  (?)
@ 2012-10-29 13:24   ` viresh kumar
  2012-10-30  3:24     ` Pratyush Anand
  -1 siblings, 1 reply; 56+ messages in thread
From: viresh kumar @ 2012-10-29 13:24 UTC (permalink / raw)
  To: Pratyush Anand
  Cc: arnd, shiraz.hashim, spear-devel, linux-pci, devicetree-discuss, olof

On Mon, Oct 29, 2012 at 12:31 PM, Pratyush Anand <pratyush.anand@st.com> wrote:
> Signed-off-by: Pratyush Anand <pratyush.anand@st.com>
> ---

Please add commit log in each and every message.

What do you mean by auxiliary data in subject?

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

* Re: [PATCH 13/15] SPEAr13xx: update kconfig for PCIe selection
  2012-10-29  7:01   ` Pratyush Anand
  (?)
@ 2012-10-29 13:33   ` viresh kumar
  2012-10-30  3:25     ` Pratyush Anand
  -1 siblings, 1 reply; 56+ messages in thread
From: viresh kumar @ 2012-10-29 13:33 UTC (permalink / raw)
  To: Pratyush Anand
  Cc: arnd, shiraz.hashim, spear-devel, linux-pci, devicetree-discuss, olof

On Mon, Oct 29, 2012 at 12:31 PM, Pratyush Anand <pratyush.anand@st.com> wrote:
> Signed-off-by: Pratyush Anand <pratyush.anand@st.com>
> ---
>  arch/arm/mach-spear13xx/Kconfig |   12 ++++++++++++
>  1 files changed, 12 insertions(+), 0 deletions(-)
>
> diff --git a/arch/arm/mach-spear13xx/Kconfig b/arch/arm/mach-spear13xx/Kconfig
> index eaadc66..4817314 100644
> --- a/arch/arm/mach-spear13xx/Kconfig
> +++ b/arch/arm/mach-spear13xx/Kconfig
> @@ -16,5 +16,17 @@ config MACH_SPEAR1340
>         select PINCTRL_SPEAR1340
>         help
>           Supports ST SPEAr1340 machine configured via the device-tree
> +

change irrelevant to your patch

>  endmenu
> +
> +config SPEAR13XX_PCI
> +       bool "PCI Express support"

cant this be module

> +       select PCI
> +       select PCIEPORTBUS
> +       select ARCH_SUPPORTS_MSI
> +       select PCI_MSI
> +       select NEED_MACH_IO_H
> +       help
> +         Support SPEAr13xx PCIe Dual controler as a host

s/controler/controller

> +
>  endif #ARCH_SPEAR13XX
> --
> 1.7.5.4
>

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

* Re: [PATCH 14/15] SPEAR13xx: Update makefile for PCIe inclusion
  2012-10-29  7:01   ` Pratyush Anand
  (?)
@ 2012-10-29 13:34   ` viresh kumar
  -1 siblings, 0 replies; 56+ messages in thread
From: viresh kumar @ 2012-10-29 13:34 UTC (permalink / raw)
  To: Pratyush Anand
  Cc: arnd, shiraz.hashim, spear-devel, linux-pci, devicetree-discuss, olof

On Mon, Oct 29, 2012 at 12:31 PM, Pratyush Anand <pratyush.anand@st.com> wrote:
> Signed-off-by: Pratyush Anand <pratyush.anand@st.com>
> ---
>  arch/arm/mach-spear13xx/Makefile |    1 +
>  1 files changed, 1 insertions(+), 0 deletions(-)
>
> diff --git a/arch/arm/mach-spear13xx/Makefile b/arch/arm/mach-spear13xx/Makefile
> index b721566..f7a42fb 100644
> --- a/arch/arm/mach-spear13xx/Makefile
> +++ b/arch/arm/mach-spear13xx/Makefile
> @@ -9,3 +9,4 @@ obj-$(CONFIG_ARCH_SPEAR13XX)    += spear13xx.o
>  obj-$(CONFIG_SUSPEND)          += pm.o wakeup.o sleep_1340.o sleep_1310.o
>  obj-$(CONFIG_MACH_SPEAR1310)   += spear1310.o
>  obj-$(CONFIG_MACH_SPEAR1340)   += spear1340.o
> +obj-$(CONFIG_SPEAR13XX_PCI)    += pcie.o

Add this before Machines. Also, you can add Kconfig and Makefile changes
with drivers patch only.

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

* Re: [PATCH 09/15] SPEAr13xx: dts: Fix PCIe core address ranges
  2012-10-29 13:23   ` viresh kumar
@ 2012-10-30  3:23     ` Pratyush Anand
  0 siblings, 0 replies; 56+ messages in thread
From: Pratyush Anand @ 2012-10-30  3:23 UTC (permalink / raw)
  To: viresh kumar
  Cc: arnd, Shiraz HASHIM, spear-devel, linux-pci, devicetree-discuss, olof

On 10/29/2012 6:53 PM, viresh kumar wrote:
> On Mon, Oct 29, 2012 at 12:31 PM, Pratyush Anand <pratyush.anand@st.com> wrote:
>> Each PCIe controller has 256 MB of address space whcih is accessible by
>> AHB and used to communicate with PCIe devices connected with the host
>> controller.
>
> you haven't said what you have done here in this patch. i.e. extend AHB range
> to include pcie space.
>
>> Signed-off-by: Pratyush Anand <pratyush.anand@st.com>
>> ---
>>   arch/arm/boot/dts/spear13xx.dtsi |    9 +++++----
>>   1 files changed, 5 insertions(+), 4 deletions(-)
>>
>> diff --git a/arch/arm/boot/dts/spear13xx.dtsi b/arch/arm/boot/dts/spear13xx.dtsi
>> index 9ff4f5f..b7990754 100644
>> --- a/arch/arm/boot/dts/spear13xx.dtsi
>> +++ b/arch/arm/boot/dts/spear13xx.dtsi
>> @@ -76,7 +76,8 @@
>>                  #size-cells = <1>;
>>                  compatible = "simple-bus";
>>                  ranges = <0x50000000 0x50000000 0x10000000
>> -                         0xb0000000 0xb0000000 0x10000000
>> +                         0x80000000 0x80000000 0x20000000
>> +                         0xb0000000 0xb0000000 0x20000000
>>                            0xd0000000 0xd0000000 0x02000000
>>                            0xd8000000 0xd8000000 0x01000000
>>                            0xe0000000 0xe0000000 0x10000000>;
>> @@ -194,7 +195,7 @@
>>                  pcie0@b1000000 {
>>                          compatible = "st,pcie-gadget", "st,pcie-host" ;
>>                          reg = < 0xb1000000 0x4000
>> -                               0x80000000 0x2000
>> +                               0x80000000 0x10000000
>>                                  0xeb800000 0x1000 >;
>>                          interrupts = <0 68 0x4>;
>>                          status = "disabled";
>
> That's a blunder. I am damn sure, you haven't rebased it
> on any rc. And you have rebased it on your local next.
>

Yes, I re-based it with next of ST's repo.  :(

> There is no pci support in upstream kernel.

I will send a v2 after rebasing with mainline content.

>
> --
> viresh
> .
>

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

* Re: [PATCH 10/15] SPEAr13xx: DTS: Add auxiliary data for PCIe host
  2012-10-29 13:24   ` viresh kumar
@ 2012-10-30  3:24     ` Pratyush Anand
  2012-10-30  5:47       ` Viresh Kumar
  0 siblings, 1 reply; 56+ messages in thread
From: Pratyush Anand @ 2012-10-30  3:24 UTC (permalink / raw)
  To: viresh kumar
  Cc: arnd, Shiraz HASHIM, spear-devel, linux-pci, devicetree-discuss, olof

On 10/29/2012 6:54 PM, viresh kumar wrote:
> On Mon, Oct 29, 2012 at 12:31 PM, Pratyush Anand <pratyush.anand@st.com> wrote:
>> Signed-off-by: Pratyush Anand <pratyush.anand@st.com>
>> ---
>
> Please add commit log in each and every message.
>
> What do you mean by auxiliary data in subject?

It used to be plat data earlier, which is being passed from DT now.

> .
>

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

* Re: [PATCH 13/15] SPEAr13xx: update kconfig for PCIe selection
  2012-10-29 13:33   ` viresh kumar
@ 2012-10-30  3:25     ` Pratyush Anand
  0 siblings, 0 replies; 56+ messages in thread
From: Pratyush Anand @ 2012-10-30  3:25 UTC (permalink / raw)
  To: viresh kumar
  Cc: arnd, Shiraz HASHIM, spear-devel, linux-pci, devicetree-discuss, olof

On 10/29/2012 7:03 PM, viresh kumar wrote:
>> >  endmenu
>> >+
>> >+config SPEAR13XX_PCI
>> >+       bool "PCI Express support"
> cant this be module
>

No.

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

* Re: [PATCH 10/15] SPEAr13xx: DTS: Add auxiliary data for PCIe host
  2012-10-30  3:24     ` Pratyush Anand
@ 2012-10-30  5:47       ` Viresh Kumar
  0 siblings, 0 replies; 56+ messages in thread
From: Viresh Kumar @ 2012-10-30  5:47 UTC (permalink / raw)
  To: Pratyush Anand
  Cc: arnd, Shiraz HASHIM, spear-devel, linux-pci, devicetree-discuss, olof

On 30 October 2012 08:54, Pratyush Anand <pratyush.anand@st.com> wrote:
>> What do you mean by auxiliary data in subject?
>
> It used to be plat data earlier, which is being passed from DT now.

Yes. But how did you conclude that it should be called auxiliary data?

I would change subject of this patch to:
ARM: SPEAr13xx: Pass configuration information of PCIe via DT

But i believe you wouldn't need any of above messages and the new message
will also add basic DT support for PCIe.

--
viresh

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

* Re: [PATCH 03/15] SPEAr13xx: Add mach/io.h
  2012-10-29  8:11     ` Pratyush Anand
@ 2012-10-30 21:45           ` Arnd Bergmann
  0 siblings, 0 replies; 56+ messages in thread
From: Arnd Bergmann @ 2012-10-30 21:45 UTC (permalink / raw)
  To: Pratyush Anand
  Cc: viresh kumar, devicetree-discuss-uLR06cmDAlY/bJ5BZ2RsiQ,
	spear-devel, Shiraz HASHIM, linux-pci-u79uwXL29TY76Z2rM5mHXA

On Monday 29 October 2012, Pratyush Anand wrote:
> Any transaction between 0x80000000 to 0x8FFFFFFF can only be used for 
> any type(IO/MEM/CFG0/CFG1) of PCIe transaction. Therefore , we need to 
> have this mapping in io.h.

No you don't.

The I/O space window will only be in one place on a given system, so you
should register that window using pci_ioremap_io() as all the other
modern platforms. There is no excuse for having a per-platform mach/io.h
any more and that would prevent you from enabling spear in a multiplatform
configuration.

	Arnd

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

* Re: [PATCH 03/15] SPEAr13xx: Add mach/io.h
@ 2012-10-30 21:45           ` Arnd Bergmann
  0 siblings, 0 replies; 56+ messages in thread
From: Arnd Bergmann @ 2012-10-30 21:45 UTC (permalink / raw)
  To: Pratyush Anand
  Cc: viresh kumar, Shiraz HASHIM, spear-devel, linux-pci,
	devicetree-discuss, olof

On Monday 29 October 2012, Pratyush Anand wrote:
> Any transaction between 0x80000000 to 0x8FFFFFFF can only be used for 
> any type(IO/MEM/CFG0/CFG1) of PCIe transaction. Therefore , we need to 
> have this mapping in io.h.

No you don't.

The I/O space window will only be in one place on a given system, so you
should register that window using pci_ioremap_io() as all the other
modern platforms. There is no excuse for having a per-platform mach/io.h
any more and that would prevent you from enabling spear in a multiplatform
configuration.

	Arnd

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

* Re: [PATCH 09/15] SPEAr13xx: dts: Fix PCIe core address ranges
  2012-10-29  7:01   ` Pratyush Anand
  (?)
  (?)
@ 2012-10-30 21:55   ` Arnd Bergmann
  2012-10-31 11:24     ` Pratyush Anand
  -1 siblings, 1 reply; 56+ messages in thread
From: Arnd Bergmann @ 2012-10-30 21:55 UTC (permalink / raw)
  To: Pratyush Anand
  Cc: shiraz.hashim, viresh.linux, spear-devel, linux-pci,
	devicetree-discuss, olof

On Monday 29 October 2012, Pratyush Anand wrote:
> sible by
> AHB and used to communicate with PCIe devices connected with the host
> controller.
> 
> Signed-off-by: Pratyush Anand <pratyush.anand@st.com>
> ---
>  arch/arm/boot/dts/spear13xx.dtsi |    9 +++++----
>  1 files changed, 5 insertions(+), 4 deletions(-)
> 
> diff --git a/arch/arm/boot/dts/spear13xx.dtsi b/arch/arm/boot/dts/spear13xx.dtsi
> index 9ff4f5f..b7990754 100644
> --- a/arch/arm/boot/dts/spear13xx.dtsi
> +++ b/arch/arm/boot/dts/spear13xx.dtsi
> @@ -76,7 +76,8 @@
>                 #size-cells = <1>;
>                 compatible = "simple-bus";
>                 ranges = <0x50000000 0x50000000 0x10000000
> -                         0xb0000000 0xb0000000 0x10000000
> +                         0x80000000 0x80000000 0x20000000
> +                         0xb0000000 0xb0000000 0x20000000
>                           0xd0000000 0xd0000000 0x02000000
>                           0xd8000000 0xd8000000 0x01000000
>                           0xe0000000 0xe0000000 0x10000000>;
> @@ -194,7 +195,7 @@
>                 pcie0@b1000000 {
>                         compatible = "st,pcie-gadget", "st,pcie-host" ;
>                         reg = < 0xb1000000 0x4000
> -                               0x80000000 0x2000
> +                               0x80000000 0x10000000
>                                 0xeb800000 0x1000 >;
>                         interrupts = <0 68 0x4>;
>                         status = "disabled";

The code that I'm looking at in the upstream kernel looks very different, so I don't
see how this patch would apply. Also, the version that you are patching as well
as the changes you do don't actually follow the generic PCI bindings at all
and should be done quite differently.

Please have a look at how to configure the PCI ranges in the IEEE1275 PCI
bindings and in examples you find in arch/powerpc/.

Most importantly, the compatible string used here can't really refer to both
the host and the endpoint mode, you really need separate bindings for those
and have only one of the two used in a particular system. What you can do is
to put both into the dtsi file and mark them as "disabled" and then enable
just one of the two on a given board file.

	Arnd

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

* Re: [PATCH 08/15] SPEAr1310: Add PCIe auxdata for miphy clock initialization
  2012-10-29  7:01   ` Pratyush Anand
  (?)
@ 2012-10-30 21:57   ` Arnd Bergmann
  -1 siblings, 0 replies; 56+ messages in thread
From: Arnd Bergmann @ 2012-10-30 21:57 UTC (permalink / raw)
  To: Pratyush Anand
  Cc: shiraz.hashim, viresh.linux, spear-devel, linux-pci,
	devicetree-discuss, olof

On Monday 29 October 2012, Pratyush Anand wrote:
> Miphy Clock initialization is very specific to controller and its
> instances. Pass this custom function using auxdata.
> 
> Signed-off-by: Pratyush Anand <pratyush.anand@st.com>
> ---
>  arch/arm/mach-spear13xx/spear1310.c |  148 +++++++++++++++++++++++++++++++++++
>  1 files changed, 148 insertions(+), 0 deletions(-)

I think you shouldn't have this in platform code. I don't have the full picture here
but it looks like it could be a separate clock driver so you can use the regular clock
functions. Platform data with callbacks is not acceptable here.

	Arnd

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

* Re: [PATCH 04/15] SPEAr13xx: Add PCIe Root Complex driver support
  2012-10-29  7:01   ` Pratyush Anand
  (?)
@ 2012-10-30 22:20   ` Arnd Bergmann
  2012-10-31 11:24     ` Pratyush Anand
  -1 siblings, 1 reply; 56+ messages in thread
From: Arnd Bergmann @ 2012-10-30 22:20 UTC (permalink / raw)
  To: Pratyush Anand
  Cc: shiraz.hashim, viresh.linux, spear-devel, linux-pci,
	devicetree-discuss, olof

On Monday 29 October 2012, Pratyush Anand wrote:
> SPEAr13xx has dual mode PCIe controller which can be used as Root
> Complex as well as Endpoint. This driver supports RC mode of the
> controller.
> 
> If CONFIG_PCI_MSI is defined then support of MSI interrupt for
> downstream  PCIe devices will be enabled.
> 
> If CONFIG_PM is defined then it supports suspend/resume functionality.

I think I've seen the same hardware before used with another driver.
IMHO we should really make sure this does not get duplicated again and
move this stuff to a new subdirectory drivers/pci/host. We don't yet have
a completely architecture independent way of defining a PCIe root complex,
but we're getting there and given of how many ARM implementations we have,
we can just as well start with this one and adapt it to another arch if
necesary.

> +struct pcie_port {
> +	u8			controller;
> +	u8			root_bus_nr;
> +	void __iomem		*dbi_base;
> +	void __iomem		*va_dbi_base;
> +	void __iomem		*app_base;
> +	void __iomem		*va_app_base;
> +	void __iomem		*base;
> +	void __iomem		*phy_base;
> +	void __iomem		*va_phy_base;
> +	void __iomem		*cfg0_base;
> +	void __iomem		*va_cfg0_base;
> +	void __iomem		*cfg1_base;
> +	void __iomem		*va_cfg1_base;
> +	void __iomem		*mem_base;
> +	void __iomem		*io_base;
> +	spinlock_t		conf_lock;
> +	char			mem_space_name[16];
> +	char			io_space_name[16];
> +	struct resource		res[2];
> +	struct pcie_port_info	config;
> +	struct list_head	next;
> +	struct clk		*clk;
> +	int			irq;
> +	int			virt_irq_base;
> +	int			susp_state;
> +};

Can you explain why you need a total of 13 virtual memory areas?

> +
> +static struct list_head	pcie_port_list;

I'm pretty sure you don't need your own list of ports, since we already enumerate the
ports in the PCI code.

> +static struct hw_pci pci;

Why is this not statically initialized?

> +	snprintf(pp->io_space_name, sizeof(pp->io_space_name),
> +			"PCIe %d I/O", nr);
> +	pp->io_space_name[sizeof(pp->io_space_name) - 1] = 0;
> +	pp->res[1].name = pp->io_space_name;
> +	pp->res[1].start = PCIBIOS_MIN_IO + nr * pp->config.io_size;
> +	pp->res[1].end = pp->res[1].start + (pp->config.io_size - 1);
> +	pp->res[1].flags = IORESOURCE_IO;
> +	if (request_resource(&ioport_resource, &pp->res[1]))
> +		panic("can't allocate PCIe IO space");
> +	pci_add_resource_offset(&sys->resources, &pp->res[1], sys->io_offset);

Is the io_offset ever nonzero?

> +void __iomem *spear13xx_pcie_io_base(unsigned long addr)
> +{
> +	int controller = (addr - PCIBIOS_MIN_IO) / IO_SIZE_PER_PORT;
> +	struct pcie_port *pp;
> +
> +	pp = controller_to_port(controller);
> +
> +	return pp->io_base;
> +}

This function looks completely bogus. Subtracting PCIBIOS_MIN_IO means that
everything is shifted by 0x1000 ports, since secondary bridges don't
have this offset. The I/O spaces are just mapped linearly into the virtual
address space anyway, so looking up the I/O base like this is pointless.

> +static void pcie_host_init(struct pcie_port *pp)
> +{
> +	struct pcie_port_info *config = &pp->config;
> +	void __iomem *dbi_base = pp->va_dbi_base;
> +	struct pcie_app_reg *app_reg = pp->va_app_base;
> +	u32 exp_cap_off = PCI_CAP_ID_EXP_OFFSET;
> +	u32 val;
> +
> +	/* Keep first 64K for IO */
> +	pp->io_base = pp->base;
> +	pp->mem_base = pp->io_base + config->io_size;
> +	pp->cfg0_base = pp->mem_base + config->mem_size;
> +	pp->cfg1_base = pp->cfg0_base + config->cfg0_size;

Why is the memory space part of the virtual bus address range here?


> +static int add_pcie_port(struct pcie_port *pp, struct platform_device *pdev)
> +{
> +	struct resource *base;
> +	struct resource *dbi_base;
> +	struct resource *phy_base;
> +	int virt_irq_base;
> +	struct device_node *np = pdev->dev.of_node;
> +	struct irq_domain *irq_domain;
> +	int num_virt_irqs = NUM_INTX_IRQS;
> +
> +	dbi_base = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +	if (!dbi_base) {
> +		dev_err(&pdev->dev, "couldn't get dbi base resource\n");
> +		return -EINVAL;
> +	}
> +	if (!devm_request_mem_region(&pdev->dev, dbi_base->start,
> +				resource_size(dbi_base), pdev->name)) {
> +		dev_err(&pdev->dev, "dbi base resource is busy\n");
> +		return -EBUSY;
> +	}
> +
> +	pp->dbi_base = (void __iomem *)dbi_base->start;

dbi_base is a resource here, which refers to a physical address. You cannot cast
that to an __iomem token.

> +	pp->va_dbi_base = devm_ioremap(&pdev->dev, dbi_base->start,
> +			resource_size(dbi_base));

Here you even pass that address into ioremap, so it certainly isn't a virtual address

> +	pp->phy_base = (void __iomem *)phy_base->start;

same here.

> +	pp->va_phy_base = devm_ioremap(&pdev->dev, phy_base->start,
> +			resource_size(phy_base));
> +	if (!pp->va_phy_base) {
> +		dev_err(&pdev->dev, "error with ioremap\n");
> +		return -ENOMEM;
> +	}
> +
> +	base = platform_get_resource(pdev, IORESOURCE_MEM, 1);
> +	if (!base) {
> +		dev_err(&pdev->dev, "couldn't get base resource\n");
> +		return -EINVAL;
> +	}
> +
> +	pp->base = (void __iomem *)base->start;

and here.

> +	virt_irq_base = irq_alloc_descs(-1, 0, num_virt_irqs, 0);
> +	if (IS_ERR_VALUE(virt_irq_base)) {
> +		dev_err(&pdev->dev, "irq desc alloc failed\n");
> +		return -ENXIO;
> +	}
> +
> +	irq_domain = irq_domain_add_legacy(np, num_virt_irqs, virt_irq_base,
> +			0, &irq_domain_simple_ops, NULL);

Why not use a linear domain?

> +	pp->virt_irq_base = irq_find_mapping(irq_domain, 0);

Then you can get rid of virt_irq_base and use CONFIG_SPARSE_IRQ.

> +	spin_lock_init(&pp->conf_lock);
> +	if (pcie_link_up(pp->va_app_base)) {
> +		dev_info(&pdev->dev, "link up\n");
> +	} else {
> +		dev_info(&pdev->dev, "link down\n");
> +		pcie_host_init(pp);
> +		pp->va_cfg0_base = devm_ioremap(&pdev->dev,
> +				(resource_size_t)pp->cfg0_base,

cfg0_base is an __iomem token, you cannot pass that into ioremap,
which expects a physical address.

> +	pp->config.io_size = IO_SIZE_PER_PORT;
> +	of_property_read_u32(np, "pcie-host,is_host", &pp->config.is_host);
> +	of_property_read_u32(np, "pcie-host,is_gen1", &pp->config.is_gen1);

These should probably be derived from the "compatible" value.

> +	of_property_read_u32(np, "pcie-host,cfg0_size", &pp->config.cfg0_size);
> +	of_property_read_u32(np, "pcie-host,cfg1_size", &pp->config.cfg1_size);
> +	of_property_read_u32(np, "pcie-host,mem_size", &pp->config.mem_size);
> +	of_property_read_u32(np, "pcie-host,msg_size", &pp->config.msg_size);
> +	of_property_read_u32(np, "pcie-host,in_mem_size",
> +			&pp->config.in_mem_size);

And these should come from the "ranges" property I suppose.

	Arnd

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

* Re: [PATCH 04/15] SPEAr13xx: Add PCIe Root Complex driver support
  2012-10-30 22:20   ` Arnd Bergmann
@ 2012-10-31 11:24     ` Pratyush Anand
  2012-10-31 22:00       ` Arnd Bergmann
  0 siblings, 1 reply; 56+ messages in thread
From: Pratyush Anand @ 2012-10-31 11:24 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Shiraz HASHIM, viresh.linux, spear-devel, linux-pci,
	devicetree-discuss, olof

On 10/31/2012 3:50 AM, Arnd Bergmann wrote:
> On Monday 29 October 2012, Pratyush Anand wrote:
>> SPEAr13xx has dual mode PCIe controller which can be used as Root
>> Complex as well as Endpoint. This driver supports RC mode of the
>> controller.
>>
>> If CONFIG_PCI_MSI is defined then support of MSI interrupt for
>> downstream  PCIe devices will be enabled.
>>
>> If CONFIG_PM is defined then it supports suspend/resume functionality.
>
> I think I've seen the same hardware before used with another driver.
> IMHO we should really make sure this does not get duplicated again and
> move this stuff to a new subdirectory drivers/pci/host. We don't yet have
> a completely architecture independent way of defining a PCIe root complex,
> but we're getting there and given of how many ARM implementations we have,
> we can just as well start with this one and adapt it to another arch if
> necesary.
>

Yes, I too wanted to put it into drivers/pci/host. But, still it would 
be ARCH (arm) dependent, until we have a common solution for all 
architecture. Let me know, if I can put it into drivers/pci/host even if 
it works initially for ARM only.

>> +struct pcie_port {
>> +	u8			controller;
>> +	u8			root_bus_nr;
>> +	void __iomem		*dbi_base;
>> +	void __iomem		*va_dbi_base;
>> +	void __iomem		*app_base;
>> +	void __iomem		*va_app_base;
>> +	void __iomem		*base;
>> +	void __iomem		*phy_base;
>> +	void __iomem		*va_phy_base;
>> +	void __iomem		*cfg0_base;
>> +	void __iomem		*va_cfg0_base;
>> +	void __iomem		*cfg1_base;
>> +	void __iomem		*va_cfg1_base;
>> +	void __iomem		*mem_base;
>> +	void __iomem		*io_base;
>> +	spinlock_t		conf_lock;
>> +	char			mem_space_name[16];
>> +	char			io_space_name[16];
>> +	struct resource		res[2];
>> +	struct pcie_port_info	config;
>> +	struct list_head	next;
>> +	struct clk		*clk;
>> +	int			irq;
>> +	int			virt_irq_base;
>> +	int			susp_state;
>> +};
>
> Can you explain why you need a total of 13 virtual memory areas?
>

Ah, its not 13, Its just 5 all va_xxxx.
Probably, I have wrongly put __iomem annotation  with physical addresses 
too. I will correct. Will keep physical address as normal void *.

>> +
>> +static struct list_head	pcie_port_list;
>
> I'm pretty sure you don't need your own list of ports, since we already enumerate the
> ports in the PCI code.
>

This pcie_port_list is list of private data (struct pcie_port). 
Callbacks defined in struct hw_pci such as setup, scan etc are called 
with first argument as controller number. Now other option could have 
been to use a simple array of struct pcie_port[MAX_PORT_NUM], as other 
platforms has used. But I thought to keep list as better option, so that 
we are not dependent on MAX_PORT_NUM.

>> +static struct hw_pci pci;
>
> Why is this not statically initialized?

Ok, ll take care in next version.

>
>> +	snprintf(pp->io_space_name, sizeof(pp->io_space_name),
>> +			"PCIe %d I/O", nr);
>> +	pp->io_space_name[sizeof(pp->io_space_name) - 1] = 0;
>> +	pp->res[1].name = pp->io_space_name;
>> +	pp->res[1].start = PCIBIOS_MIN_IO + nr * pp->config.io_size;
>> +	pp->res[1].end = pp->res[1].start + (pp->config.io_size - 1);
>> +	pp->res[1].flags = IORESOURCE_IO;
>> +	if (request_resource(&ioport_resource, &pp->res[1]))
>> +		panic("can't allocate PCIe IO space");
>> +	pci_add_resource_offset(&sys->resources, &pp->res[1], sys->io_offset);
>
> Is the io_offset ever nonzero?
>
>> +void __iomem *spear13xx_pcie_io_base(unsigned long addr)
>> +{
>> +	int controller = (addr - PCIBIOS_MIN_IO) / IO_SIZE_PER_PORT;
>> +	struct pcie_port *pp;
>> +
>> +	pp = controller_to_port(controller);
>> +
>> +	return pp->io_base;
>> +}
>
> This function looks completely bogus. Subtracting PCIBIOS_MIN_IO means that
> everything is shifted by 0x1000 ports, since secondary bridges don't
> have this offset. The I/O spaces are just mapped linearly into the virtual
> address space anyway, so looking up the I/O base like this is pointless.
>

Frankly speaking, I do not have clear understanding of PCIe IO 
transaction. I did not test any PCIe device with my host which might 
need IO resource. Since , my host controller does support IO 
transaction, I want to support it in driver. Let me explain my 
requirement, please correct my understanding where I am wrong.

-- I can program one my viewport to generate IO transaction on PCIe bus, 
if CPU writes between AHB address 0x80000000-0x80007FFF.

-- Now, lets say a PCIe device needs 100 io ports, then address range 
0x80000000-0x80000064 will be allocated to this device by pci stack. It 
will also write 0x80000000 to IO_BAR register of its configuration 
address space. Now, if my CPU writes at ahb address 0x80000010 then 16th 
IO port of this device will be written.

-- Probably, I need something like following and it will remove 
mach/io.h , hence spear13xx_pcie_io_base too.

--- a/arch/arm/mach-spear13xx/pcie.c
+++ b/arch/arm/mach-spear13xx/pcie.c
@@ -414,7 +414,7 @@ static int __init pcie_setup(int nr, struct 
pci_sys_data *sys)
         pp->res[1].flags = IORESOURCE_IO;
         if (request_resource(&ioport_resource, &pp->res[1]))
                 panic("can't allocate PCIe IO space");
-       pci_add_resource_offset(&sys->resources, &pp->res[1], 
sys->io_offset);
+       pci_add_resource_offset(&sys->resources, &pp->res[1], 0x80000000);


>> +static void pcie_host_init(struct pcie_port *pp)
>> +{
>> +	struct pcie_port_info *config = &pp->config;
>> +	void __iomem *dbi_base = pp->va_dbi_base;
>> +	struct pcie_app_reg *app_reg = pp->va_app_base;
>> +	u32 exp_cap_off = PCI_CAP_ID_EXP_OFFSET;
>> +	u32 val;
>> +
>> +	/* Keep first 64K for IO */
>> +	pp->io_base = pp->base;
>> +	pp->mem_base = pp->io_base + config->io_size;
>> +	pp->cfg0_base = pp->mem_base + config->mem_size;
>> +	pp->cfg1_base = pp->cfg0_base + config->cfg0_size;
>
> Why is the memory space part of the virtual bus address range here?

Sorry, its not virtual address. I will remove __iomem from all physical 
address pointer.

>
>
>> +static int add_pcie_port(struct pcie_port *pp, struct platform_device *pdev)
>> +{
>> +	struct resource *base;
>> +	struct resource *dbi_base;
>> +	struct resource *phy_base;
>> +	int virt_irq_base;
>> +	struct device_node *np = pdev->dev.of_node;
>> +	struct irq_domain *irq_domain;
>> +	int num_virt_irqs = NUM_INTX_IRQS;
>> +
>> +	dbi_base = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>> +	if (!dbi_base) {
>> +		dev_err(&pdev->dev, "couldn't get dbi base resource\n");
>> +		return -EINVAL;
>> +	}
>> +	if (!devm_request_mem_region(&pdev->dev, dbi_base->start,
>> +				resource_size(dbi_base), pdev->name)) {
>> +		dev_err(&pdev->dev, "dbi base resource is busy\n");
>> +		return -EBUSY;
>> +	}
>> +
>> +	pp->dbi_base = (void __iomem *)dbi_base->start;
>
> dbi_base is a resource here, which refers to a physical address. You cannot cast
> that to an __iomem token.

ok.

>
>> +	pp->va_dbi_base = devm_ioremap(&pdev->dev, dbi_base->start,
>> +			resource_size(dbi_base));
>
> Here you even pass that address into ioremap, so it certainly isn't a virtual address

Yes, I understand it :(

>
>> +	pp->phy_base = (void __iomem *)phy_base->start;
>
> same here.
>
>> +	pp->va_phy_base = devm_ioremap(&pdev->dev, phy_base->start,
>> +			resource_size(phy_base));
>> +	if (!pp->va_phy_base) {
>> +		dev_err(&pdev->dev, "error with ioremap\n");
>> +		return -ENOMEM;
>> +	}
>> +
>> +	base = platform_get_resource(pdev, IORESOURCE_MEM, 1);
>> +	if (!base) {
>> +		dev_err(&pdev->dev, "couldn't get base resource\n");
>> +		return -EINVAL;
>> +	}
>> +
>> +	pp->base = (void __iomem *)base->start;
>
> and here.
>
>> +	virt_irq_base = irq_alloc_descs(-1, 0, num_virt_irqs, 0);
>> +	if (IS_ERR_VALUE(virt_irq_base)) {
>> +		dev_err(&pdev->dev, "irq desc alloc failed\n");
>> +		return -ENXIO;
>> +	}
>> +
>> +	irq_domain = irq_domain_add_legacy(np, num_virt_irqs, virt_irq_base,
>> +			0, &irq_domain_simple_ops, NULL);
>
> Why not use a linear domain?
>
>> +	pp->virt_irq_base = irq_find_mapping(irq_domain, 0);
>
> Then you can get rid of virt_irq_base and use CONFIG_SPARSE_IRQ.

I do not know about. Will explore and implement.

>
>> +	spin_lock_init(&pp->conf_lock);
>> +	if (pcie_link_up(pp->va_app_base)) {
>> +		dev_info(&pdev->dev, "link up\n");
>> +	} else {
>> +		dev_info(&pdev->dev, "link down\n");
>> +		pcie_host_init(pp);
>> +		pp->va_cfg0_base = devm_ioremap(&pdev->dev,
>> +				(resource_size_t)pp->cfg0_base,
>
> cfg0_base is an __iomem token, you cannot pass that into ioremap,
> which expects a physical address.

Again cfg0_base is physical and va_cfg0_base is virtual.

>
>> +	pp->config.io_size = IO_SIZE_PER_PORT;
>> +	of_property_read_u32(np, "pcie-host,is_host", &pp->config.is_host);
>> +	of_property_read_u32(np, "pcie-host,is_gen1", &pp->config.is_gen1);
>
> These should probably be derived from the "compatible" value.

Yes, about is_host I think, I will go with "compatible".

Let me explain why I have provided is_gen1: There are few buggy PCIe 
cards which links up only if host is gen1. My host is by default gen2. 
It does work with gen1 as well as gen2 devices except some buggy gen1 
devices. I provided this flag, to force controller to linkup at gen1 
only so that it can work with those buggy cards too.

>
>> +	of_property_read_u32(np, "pcie-host,cfg0_size", &pp->config.cfg0_size);
>> +	of_property_read_u32(np, "pcie-host,cfg1_size", &pp->config.cfg1_size);
>> +	of_property_read_u32(np, "pcie-host,mem_size", &pp->config.mem_size);
>> +	of_property_read_u32(np, "pcie-host,msg_size", &pp->config.msg_size);
>> +	of_property_read_u32(np, "pcie-host,in_mem_size",
>> +			&pp->config.in_mem_size);
>
> And these should come from the "ranges" property I suppose.

Ok..

Regards
Pratyush

PS: Thanks for your valuable inputs :)

>
> 	Arnd
> .
>

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

* Re: [PATCH 03/15] SPEAr13xx: Add mach/io.h
  2012-10-30 21:45           ` Arnd Bergmann
  (?)
@ 2012-10-31 11:24           ` Pratyush Anand
  2012-10-31 22:05             ` Arnd Bergmann
  -1 siblings, 1 reply; 56+ messages in thread
From: Pratyush Anand @ 2012-10-31 11:24 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: viresh kumar, Shiraz HASHIM, spear-devel, linux-pci,
	devicetree-discuss, olof

On 10/31/2012 3:15 AM, Arnd Bergmann wrote:
> On Monday 29 October 2012, Pratyush Anand wrote:
>> Any transaction between 0x80000000 to 0x8FFFFFFF can only be used for
>> any type(IO/MEM/CFG0/CFG1) of PCIe transaction. Therefore , we need to
>> have this mapping in io.h.
>
> No you don't.
>
> The I/O space window will only be in one place on a given system, so you
> should register that window using pci_ioremap_io() as all the other

Sorry, I could not find pci_ioremap_io function. May be you wanted to 
refer something else.

In case of SPEAr too , we can reserve first 32Kb per controller as PCIe 
IO space. So, lets say I fixed address 0x80000000--0x80007FFF for IO 
transaction. I need to register address range of this window somehow.

But, issue which faced was that I was not able to successfully 
request_resource(&ioport_resource, &res]) with res.start = 0x80000000 
and res.end = 0x80007fff.

So, I though first to change IO_SPACE_LIMIT. But I found it not a 
correct way.

May be I am missing something and not able to get how can I use 
pci_ioremap_io or something else to register 0x80000000--0x80007FFF 
window. A reference will help.


Regards
Pratyush
> modern platforms. There is no excuse for having a per-platform mach/io.h
> any more and that would prevent you from enabling spear in a multiplatform
> configuration.
>
> 	Arnd
> .
>

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

* Re: [PATCH 09/15] SPEAr13xx: dts: Fix PCIe core address ranges
  2012-10-30 21:55   ` Arnd Bergmann
@ 2012-10-31 11:24     ` Pratyush Anand
  0 siblings, 0 replies; 56+ messages in thread
From: Pratyush Anand @ 2012-10-31 11:24 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Shiraz HASHIM, viresh.linux, spear-devel, linux-pci,
	devicetree-discuss, olof

On 10/31/2012 3:25 AM, Arnd Bergmann wrote:
> On Monday 29 October 2012, Pratyush Anand wrote:
>> sible by
>> AHB and used to communicate with PCIe devices connected with the host
>> controller.
>>
>> Signed-off-by: Pratyush Anand <pratyush.anand@st.com>
>> ---
>>   arch/arm/boot/dts/spear13xx.dtsi |    9 +++++----
>>   1 files changed, 5 insertions(+), 4 deletions(-)
>>
>> diff --git a/arch/arm/boot/dts/spear13xx.dtsi b/arch/arm/boot/dts/spear13xx.dtsi
>> index 9ff4f5f..b7990754 100644
>> --- a/arch/arm/boot/dts/spear13xx.dtsi
>> +++ b/arch/arm/boot/dts/spear13xx.dtsi
>> @@ -76,7 +76,8 @@
>>                  #size-cells = <1>;
>>                  compatible = "simple-bus";
>>                  ranges = <0x50000000 0x50000000 0x10000000
>> -                         0xb0000000 0xb0000000 0x10000000
>> +                         0x80000000 0x80000000 0x20000000
>> +                         0xb0000000 0xb0000000 0x20000000
>>                            0xd0000000 0xd0000000 0x02000000
>>                            0xd8000000 0xd8000000 0x01000000
>>                            0xe0000000 0xe0000000 0x10000000>;
>> @@ -194,7 +195,7 @@
>>                  pcie0@b1000000 {
>>                          compatible = "st,pcie-gadget", "st,pcie-host" ;
>>                          reg = < 0xb1000000 0x4000
>> -                               0x80000000 0x2000
>> +                               0x80000000 0x10000000
>>                                  0xeb800000 0x1000 >;
>>                          interrupts = <0 68 0x4>;
>>                          status = "disabled";
>
> The code that I'm looking at in the upstream kernel looks very different, so I don't
> see how this patch would apply. Also, the version that you are patching as well
> as the changes you do don't actually follow the generic PCI bindings at all
> and should be done quite differently.
>

Yes, this was my mistake. I rebased with ST repo. Will send V2 with 
correct rebase.


> Please have a look at how to configure the PCI ranges in the IEEE1275 PCI
> bindings and in examples you find in arch/powerpc/.
>

Will look into.

> Most importantly, the compatible string used here can't really refer to both
> the host and the endpoint mode, you really need separate bindings for those
> and have only one of the two used in a particular system. What you can do is
> to put both into the dtsi file and mark them as "disabled" and then enable
> just one of the two on a given board file.

Yes, we had though of this limitation and had decided to do exactly the 
same way you have suggested.

thanks for your review comments.
Regards
Pratyush

>
> 	Arnd
> .
>

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

* Re: [PATCH 04/15] SPEAr13xx: Add PCIe Root Complex driver support
  2012-10-31 11:24     ` Pratyush Anand
@ 2012-10-31 22:00       ` Arnd Bergmann
  2012-11-01  7:25         ` Pratyush Anand
  0 siblings, 1 reply; 56+ messages in thread
From: Arnd Bergmann @ 2012-10-31 22:00 UTC (permalink / raw)
  To: Pratyush Anand
  Cc: Shiraz HASHIM, viresh.linux, spear-devel, linux-pci,
	devicetree-discuss, olof, Bjorn Helgaas

On Wednesday 31 October 2012, Pratyush Anand wrote:
> On 10/31/2012 3:50 AM, Arnd Bergmann wrote:
> > On Monday 29 October 2012, Pratyush Anand wrote:
> >> SPEAr13xx has dual mode PCIe controller which can be used as Root
> >> Complex as well as Endpoint. This driver supports RC mode of the
> >> controller.
> >>
> >> If CONFIG_PCI_MSI is defined then support of MSI interrupt for
> >> downstream  PCIe devices will be enabled.
> >>
> >> If CONFIG_PM is defined then it supports suspend/resume functionality.
> >
> > I think I've seen the same hardware before used with another driver.
> > IMHO we should really make sure this does not get duplicated again and
> > move this stuff to a new subdirectory drivers/pci/host. We don't yet have
> > a completely architecture independent way of defining a PCIe root complex,
> > but we're getting there and given of how many ARM implementations we have,
> > we can just as well start with this one and adapt it to another arch if
> > necesary.
> >
> 
> Yes, I too wanted to put it into drivers/pci/host. But, still it would 
> be ARCH (arm) dependent, until we have a common solution for all 
> architecture. Let me know, if I can put it into drivers/pci/host even if 
> it works initially for ARM only.


This is ultimately up to Bjorn Helgaas as the PCI maintainer. I think
everybody would prefer to have an architecture independent interface between
PCI hosts and platform specific code, and we are progressing towards that
goal. I think it would be worthwhile to have this code already in
drivers/pci while it's still ARM specific, and then remove the ARM bits
over time by replacing them with generic interfaces as we get there.

> 
> >> +struct pcie_port {
> >> +	u8			controller;
> >> +	u8			root_bus_nr;
> >> +	void __iomem		*dbi_base;
> >> +	void __iomem		*va_dbi_base;
> >> +	void __iomem		*app_base;
> >> +	void __iomem		*va_app_base;
> >> +	void __iomem		*base;
> >> +	void __iomem		*phy_base;
> >> +	void __iomem		*va_phy_base;
> >> +	void __iomem		*cfg0_base;
> >> +	void __iomem		*va_cfg0_base;
> >> +	void __iomem		*cfg1_base;
> >> +	void __iomem		*va_cfg1_base;
> >> +	void __iomem		*mem_base;
> >> +	void __iomem		*io_base;
> >> +	spinlock_t		conf_lock;
> >> +	char			mem_space_name[16];
> >> +	char			io_space_name[16];
> >> +	struct resource		res[2];
> >> +	struct pcie_port_info	config;
> >> +	struct list_head	next;
> >> +	struct clk		*clk;
> >> +	int			irq;
> >> +	int			virt_irq_base;
> >> +	int			susp_state;
> >> +};
> >
> > Can you explain why you need a total of 13 virtual memory areas?
> >
> 
> Ah, its not 13, Its just 5 all va_xxxx.
> Probably, I have wrongly put __iomem annotation  with physical addresses 
> too. I will correct. Will keep physical address as normal void *.

Physical addresses should not be pointers at all, but they should be
phys_addr_t. If you have a system with LPAE enabled, the physical
address space may be 64 bit long, so pointers don't work on that.

> >> +static struct list_head	pcie_port_list;
> >
> > I'm pretty sure you don't need your own list of ports, since we already enumerate the
> > ports in the PCI code.
> >
> 
> This pcie_port_list is list of private data (struct pcie_port). 
> Callbacks defined in struct hw_pci such as setup, scan etc are called 
> with first argument as controller number. Now other option could have 
> been to use a simple array of struct pcie_port[MAX_PORT_NUM], as other 
> platforms has used. But I thought to keep list as better option, so that 
> we are not dependent on MAX_PORT_NUM.

A list is indeed better than a static array. However, the preferred way to
do kernel code is to not have any such global lists in a device driver at
all, but keep it inside of the subsystems. I don't remember how this is
done for PCIe ports, but I would assume that you can iterate over them
already. If not, it would be nice to add this feature to the PCI subsystem
so that nobody has to keep arrays or lists like this.

> >> +static struct hw_pci pci;
> >
> > Why is this not statically initialized?
> 
> Ok, ll take care in next version.

I noticed later that it does get statically initialized below, so my comment wasn't
actually correct. However, you should try to order the symbols so that you don't
need forward declarations.

> > This function looks completely bogus. Subtracting PCIBIOS_MIN_IO means that
> > everything is shifted by 0x1000 ports, since secondary bridges don't
> > have this offset. The I/O spaces are just mapped linearly into the virtual
> > address space anyway, so looking up the I/O base like this is pointless.
> >
> 
> Frankly speaking, I do not have clear understanding of PCIe IO 
> transaction. I did not test any PCIe device with my host which might 
> need IO resource. Since , my host controller does support IO 
> transaction, I want to support it in driver. Let me explain my 
> requirement, please correct my understanding where I am wrong.
> 
> -- I can program one my viewport to generate IO transaction on PCIe bus, 
> if CPU writes between AHB address 0x80000000-0x80007FFF.
> 
> -- Now, lets say a PCIe device needs 100 io ports, then address range 
> 0x80000000-0x80000064 will be allocated to this device by pci stack. It 
> will also write 0x80000000 to IO_BAR register of its configuration 
> address space. Now, if my CPU writes at ahb address 0x80000010 then 16th 
> IO port of this device will be written.

The number space for I/O ports is usually 16 bits, which is a hardware
limitation on x86. Practically all PCI implementations on non-x86
architecture have the I/O access directly mapped into the physical
address space, like you have at phys address 0x80000000. However, the
port number for the first port in there is still "0", not "0x80000000",
and the I/O window in you PCI host registers should be set up so that
an access to address 0x80000000 gets translated into a I/O transfer
at address 0 on the PCI bus. This is different from the memory window,
which is typically set up so that the physical addresses are the
same as the bus address in PCI memory space accesses.

> -- Probably, I need something like following and it will remove 
> mach/io.h , hence spear13xx_pcie_io_base too.
> 
> --- a/arch/arm/mach-spear13xx/pcie.c
> +++ b/arch/arm/mach-spear13xx/pcie.c
> @@ -414,7 +414,7 @@ static int __init pcie_setup(int nr, struct 
> pci_sys_data *sys)
>          pp->res[1].flags = IORESOURCE_IO;
>          if (request_resource(&ioport_resource, &pp->res[1]))
>                  panic("can't allocate PCIe IO space");
> -       pci_add_resource_offset(&sys->resources, &pp->res[1], 
> sys->io_offset);
> +       pci_add_resource_offset(&sys->resources, &pp->res[1], 0x80000000);

The io_offset should be zero on all modern implementations, we just have a few
legacy cases that we carry around mostly because of interactions with older
PCMCIA drivers that can get fixed over time.

If you have multiple root buses, you can choose to make the offset for the
second bus 0x10000.

> >> +static void pcie_host_init(struct pcie_port *pp)
> >> +{
> >> +	struct pcie_port_info *config = &pp->config;
> >> +	void __iomem *dbi_base = pp->va_dbi_base;
> >> +	struct pcie_app_reg *app_reg = pp->va_app_base;
> >> +	u32 exp_cap_off = PCI_CAP_ID_EXP_OFFSET;
> >> +	u32 val;
> >> +
> >> +	/* Keep first 64K for IO */
> >> +	pp->io_base = pp->base;
> >> +	pp->mem_base = pp->io_base + config->io_size;
> >> +	pp->cfg0_base = pp->mem_base + config->mem_size;
> >> +	pp->cfg1_base = pp->cfg0_base + config->cfg0_size;
> >
> > Why is the memory space part of the virtual bus address range here?
> 
> Sorry, its not virtual address. I will remove __iomem from all physical 
> address pointer.

Ok. I suspect that you don't actually need to store the physicall address
then, because it's not needed after setting up the devices, and you can easily
retrieve it from the resources.

> >> +	pp->config.io_size = IO_SIZE_PER_PORT;
> >> +	of_property_read_u32(np, "pcie-host,is_host", &pp->config.is_host);
> >> +	of_property_read_u32(np, "pcie-host,is_gen1", &pp->config.is_gen1);
> >
> > These should probably be derived from the "compatible" value.
> 
> Yes, about is_host I think, I will go with "compatible".
> 
> Let me explain why I have provided is_gen1: There are few buggy PCIe 
> cards which links up only if host is gen1. My host is by default gen2. 
> It does work with gen1 as well as gen2 devices except some buggy gen1 
> devices. I provided this flag, to force controller to linkup at gen1 
> only so that it can work with those buggy cards too.

Ok, makes sense.

Thanks for the quick replies. I hope I managed to explain the I/O space accesses
now.

	Arnd

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

* Re: [PATCH 03/15] SPEAr13xx: Add mach/io.h
  2012-10-31 11:24           ` Pratyush Anand
@ 2012-10-31 22:05             ` Arnd Bergmann
  0 siblings, 0 replies; 56+ messages in thread
From: Arnd Bergmann @ 2012-10-31 22:05 UTC (permalink / raw)
  To: Pratyush Anand
  Cc: viresh kumar, Shiraz HASHIM, spear-devel, linux-pci,
	devicetree-discuss, olof

On Wednesday 31 October 2012, Pratyush Anand wrote:
> Sorry, I could not find pci_ioremap_io function. May be you wanted to 
> refer something else.

$ git grep pci_ioremap_io
arch/arm/include/asm/io.h:extern int pci_ioremap_io(unsigned int offset, phys_addr_t phys_addr);
arch/arm/mach-dove/pcie.c:              pci_ioremap_io(sys->busnr * SZ_64K, DOVE_PCIE0_IO_PHYS_BASE);
...
arch/arm/mach-versatile/pci.c:  ret = pci_ioremap_io(0, VERSATILE_PCI_MEM_BASE0);
arch/arm/mm/ioremap.c:int pci_ioremap_io(unsigned int offset, phys_addr_t phys_addr)
arch/arm/mm/ioremap.c:EXPORT_SYMBOL_GPL(pci_ioremap_io);


> In case of SPEAr too , we can reserve first 32Kb per controller as PCIe 
> IO space. So, lets say I fixed address 0x80000000--0x80007FFF for IO 
> transaction. I need to register address range of this window somehow.
> 
> But, issue which faced was that I was not able to successfully 
> request_resource(&ioport_resource, &res]) with res.start = 0x80000000 
> and res.end = 0x80007fff.

That cannot work properly, because the ioport_resource lists ports between
0 and 0x10000 normally, or possibly a little bit higher. You certainly
don't want to waste 2 GB of virtual address space for having a PCI I/O window
that you don't use.

> So, I though first to change IO_SPACE_LIMIT. But I found it not a 
> correct way.
> 
> May be I am missing something and not able to get how can I use 
> pci_ioremap_io or something else to register 0x80000000--0x80007FFF 
> window. A reference will help.

Calling pci_ioremap_io will do the right thing, you just have to decide
how you partition the I/O space between the root complexes you have.

	Arnd

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

* Re: [PATCH 04/15] SPEAr13xx: Add PCIe Root Complex driver support
  2012-10-31 22:00       ` Arnd Bergmann
@ 2012-11-01  7:25         ` Pratyush Anand
  0 siblings, 0 replies; 56+ messages in thread
From: Pratyush Anand @ 2012-11-01  7:25 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Shiraz HASHIM, viresh.linux, spear-devel, linux-pci,
	devicetree-discuss, olof, Bjorn Helgaas

On 11/1/2012 3:30 AM, Arnd Bergmann wrote:
> Thanks for the quick replies. I hope I managed to explain the I/O space accesses
> now.

Yes, I understood now :)

Also looked into pci_ioremap_io. Things are clear now.

Will send V2 after incorporating all comments.

Regards
Pratyush

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

end of thread, other threads:[~2012-11-01  7:25 UTC | newest]

Thread overview: 56+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-10-29  7:01 [PATCH 00/15] SPEAr13xx PCIe patches Pratyush Anand
2012-10-29  7:01 ` Pratyush Anand
2012-10-29  7:01 ` [PATCH 01/15] arm: source drivers/pci/pcie/kconfig Pratyush Anand
2012-10-29  7:01   ` Pratyush Anand
2012-10-29  7:01 ` [PATCH 02/15] arm: Call pcie_bus_configure_settings for pcie devices Pratyush Anand
2012-10-29  7:01   ` Pratyush Anand
2012-10-29  7:01 ` [PATCH 03/15] SPEAr13xx: Add mach/io.h Pratyush Anand
2012-10-29  7:01   ` Pratyush Anand
2012-10-29  7:29   ` viresh kumar
2012-10-29  8:11     ` Pratyush Anand
     [not found]       ` <508E3A2E.3000204-qxv4g6HH51o@public.gmane.org>
2012-10-30 21:45         ` Arnd Bergmann
2012-10-30 21:45           ` Arnd Bergmann
2012-10-31 11:24           ` Pratyush Anand
2012-10-31 22:05             ` Arnd Bergmann
2012-10-29  7:01 ` [PATCH 04/15] SPEAr13xx: Add PCIe Root Complex driver support Pratyush Anand
2012-10-29  7:01   ` Pratyush Anand
2012-10-30 22:20   ` Arnd Bergmann
2012-10-31 11:24     ` Pratyush Anand
2012-10-31 22:00       ` Arnd Bergmann
2012-11-01  7:25         ` Pratyush Anand
2012-10-29  7:01 ` [PATCH 05/15] clk: SPEAr1340: Fix pcie0 clock name Pratyush Anand
2012-10-29  7:01   ` Pratyush Anand
2012-10-29  7:01 ` [PATCH 06/15] clk: SPEAr1310: Fix pcie " Pratyush Anand
2012-10-29  7:01   ` Pratyush Anand
2012-10-29 13:11   ` viresh kumar
2012-10-29  7:01 ` [PATCH 07/15] SPEAr1340: Add PCIe auxdata for miphy clock initialization Pratyush Anand
2012-10-29  7:01   ` Pratyush Anand
2012-10-29  7:01 ` [PATCH 08/15] SPEAr1310: " Pratyush Anand
2012-10-29  7:01   ` Pratyush Anand
2012-10-30 21:57   ` Arnd Bergmann
2012-10-29  7:01 ` [PATCH 09/15] SPEAr13xx: dts: Fix PCIe core address ranges Pratyush Anand
2012-10-29  7:01   ` Pratyush Anand
2012-10-29 13:23   ` viresh kumar
2012-10-30  3:23     ` Pratyush Anand
2012-10-30 21:55   ` Arnd Bergmann
2012-10-31 11:24     ` Pratyush Anand
2012-10-29  7:01 ` [PATCH 10/15] SPEAr13xx: DTS: Add auxiliary data for PCIe host Pratyush Anand
2012-10-29  7:01   ` Pratyush Anand
2012-10-29 13:24   ` viresh kumar
2012-10-30  3:24     ` Pratyush Anand
2012-10-30  5:47       ` Viresh Kumar
2012-10-29  7:01 ` [PATCH 11/15] SPEAr1340-evb: dts: Enable PCIe0 Pratyush Anand
2012-10-29  7:01   ` Pratyush Anand
2012-10-29  7:01 ` [PATCH 12/15] SPEAr1310-EVB: DTS: Fix PCIe1 enable Pratyush Anand
2012-10-29  7:01   ` Pratyush Anand
2012-10-29  7:01 ` [PATCH 13/15] SPEAr13xx: update kconfig for PCIe selection Pratyush Anand
2012-10-29  7:01   ` Pratyush Anand
2012-10-29 13:33   ` viresh kumar
2012-10-30  3:25     ` Pratyush Anand
2012-10-29  7:01 ` [PATCH 14/15] SPEAR13xx: Update makefile for PCIe inclusion Pratyush Anand
2012-10-29  7:01   ` Pratyush Anand
2012-10-29 13:34   ` viresh kumar
2012-10-29  7:01 ` [PATCH 15/15] SPEAR13xx: update defconfig for PCIe compilation Pratyush Anand
2012-10-29  7:01   ` Pratyush Anand
2012-10-29  7:16 ` [PATCH 00/15] SPEAr13xx PCIe patches viresh kumar
2012-10-29  7:22   ` Pratyush Anand

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.