All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH V2 1/6] powerpc/fsl-pci: Unify pci/pcie initialization code
@ 2012-07-25  9:26 Jia Hongtao
  2012-07-25  9:26 ` [PATCH V2 2/6] powerpc/fsl-pci: Check swiotlb enable at board setup_arch stage Jia Hongtao
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: Jia Hongtao @ 2012-07-25  9:26 UTC (permalink / raw)
  To: linuxppc-dev, galak, B07421; +Cc: b38951

We unified the Freescale pci/pcie initialization by changing the fsl_pci
to a platform driver. In previous PCI code architecture the initialization
is called at board_setup_arch stage. Now the initialization is done in
probe function which is architectural better. Also It's convenient for
adding PM support for PCI controller in later patch.

Signed-off-by: Jia Hongtao <B38951@freescale.com>
Signed-off-by: Li Yang <leoli@freescale.com>
---
Changed for V2:
- Rebase the patch set on the latest tree
- Add missing pci compatible "fsl,mpc8610-pci"

 arch/powerpc/sysdev/fsl_pci.c |   80 ++++++++++++++++++----------------------
 arch/powerpc/sysdev/fsl_pci.h |    9 +----
 2 files changed, 37 insertions(+), 52 deletions(-)

diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index a7b2a60..3ebbcec 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -823,56 +823,48 @@ static const struct of_device_id pci_ids[] = {
 	{},
 };
 
-struct device_node *fsl_pci_primary;
-
-void __devinit fsl_pci_init(void)
+int primary_phb_addr;
+static int __devinit fsl_pci_probe(struct platform_device *pdev)
 {
-	struct device_node *node;
 	struct pci_controller *hose;
-	dma_addr_t max = 0xffffffff;
-
-	/* Callers can specify the primary bus using other means. */
-	if (!fsl_pci_primary) {
-		/* If a PCI host bridge contains an ISA node, it's primary. */
-		node = of_find_node_by_type(NULL, "isa");
-		while ((fsl_pci_primary = of_get_parent(node))) {
-			of_node_put(node);
-			node = fsl_pci_primary;
-
-			if (of_match_node(pci_ids, node))
-				break;
-		}
-	}
+	bool is_primary;
 
-	node = NULL;
-	for_each_node_by_type(node, "pci") {
-		if (of_match_node(pci_ids, node)) {
-			/*
-			 * If there's no PCI host bridge with ISA, arbitrarily
-			 * designate one as primary.  This can go away once
-			 * various bugs with primary-less systems are fixed.
-			 */
-			if (!fsl_pci_primary)
-				fsl_pci_primary = node;
+	if (of_match_node(pci_ids, pdev->dev.of_node)) {
+		struct resource rsrc;
+		of_address_to_resource(pdev->dev.of_node, 0, &rsrc);
+		is_primary = ((rsrc.start & 0xfffff) == primary_phb_addr);
+		fsl_add_bridge(pdev->dev.of_node, is_primary);
 
-			fsl_add_bridge(node, fsl_pci_primary == node);
-			hose = pci_find_hose_for_OF_device(node);
-			max = min(max, hose->dma_window_base_cur +
-					hose->dma_window_size);
+#ifdef CONFIG_SWIOTLB
+		hose = pci_find_hose_for_OF_device(pdev->dev.of_node);
+		/*
+		 * if we couldn't map all of DRAM via the dma windows
+		 * we need SWIOTLB to handle buffers located outside of
+		 * dma capable memory region
+		 */
+		if (memblock_end_of_DRAM() > hose->dma_window_base_cur
+				+ hose->dma_window_size) {
+			ppc_swiotlb_enable = 1;
+			set_pci_dma_ops(&swiotlb_dma_ops);
+			ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
 		}
+#endif
 	}
 
-#ifdef CONFIG_SWIOTLB
-	/*
-	 * if we couldn't map all of DRAM via the dma windows
-	 * we need SWIOTLB to handle buffers located outside of
-	 * dma capable memory region
-	 */
-	if (memblock_end_of_DRAM() - 1 > max) {
-		ppc_swiotlb_enable = 1;
-		set_pci_dma_ops(&swiotlb_dma_ops);
-		ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
-	}
-#endif
+	return 0;
+}
+
+static struct platform_driver fsl_pci_driver = {
+	.driver = {
+		.name = "fsl-pci",
+		.of_match_table = pci_ids,
+	},
+	.probe = fsl_pci_probe,
+};
+
+static int __init fsl_pci_init(void)
+{
+	return platform_driver_register(&fsl_pci_driver);
 }
+arch_initcall(fsl_pci_init);
 #endif
diff --git a/arch/powerpc/sysdev/fsl_pci.h b/arch/powerpc/sysdev/fsl_pci.h
index baa0fd1..df9fc44 100644
--- a/arch/powerpc/sysdev/fsl_pci.h
+++ b/arch/powerpc/sysdev/fsl_pci.h
@@ -88,18 +88,11 @@ struct ccsr_pci {
 	__be32	pex_err_cap_r3;		/* 0x.e34 - PCIE error capture register 0 */
 };
 
+extern int primary_phb_addr;
 extern int fsl_add_bridge(struct device_node *dev, int is_primary);
 extern void fsl_pcibios_fixup_bus(struct pci_bus *bus);
 extern int mpc83xx_add_bridge(struct device_node *dev);
 u64 fsl_pci_immrbar_base(struct pci_controller *hose);
 
-extern struct device_node *fsl_pci_primary;
-
-#ifdef CONFIG_FSL_PCI
-void fsl_pci_init(void);
-#else
-static inline void fsl_pci_init(void) {}
-#endif
-
 #endif /* __POWERPC_FSL_PCI_H */
 #endif /* __KERNEL__ */
-- 
1.7.5.1

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

* [PATCH V2 2/6] powerpc/fsl-pci: Check swiotlb enable at board setup_arch stage
  2012-07-25  9:26 [PATCH V2 1/6] powerpc/fsl-pci: Unify pci/pcie initialization code Jia Hongtao
@ 2012-07-25  9:26 ` Jia Hongtao
  2012-07-25  9:26 ` [PATCH V2 3/6] powerpc/fsl-pci: Determine primary bus by looking for ISA node Jia Hongtao
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Jia Hongtao @ 2012-07-25  9:26 UTC (permalink / raw)
  To: linuxppc-dev, galak, B07421; +Cc: b38951

PCI initialization is called later than swiotlb_init() due to PCI controller is
a platform driver now. So we provide a function which called at board setup_arch
stage to address swiotlb enable by parsing pci ranges.

This patch depends on the following patch:
powerpc/fsl-pci: Unify pci/pcie initialization code

Signed-off-by: Jia Hongtao <B38951@freescale.com>
Signed-off-by: Li Yang <leoli@freescale.com>
---
 arch/powerpc/sysdev/fsl_pci.c |  125 ++++++++++++++++++++++++++++++++++++-----
 arch/powerpc/sysdev/fsl_pci.h |    6 ++
 2 files changed, 116 insertions(+), 15 deletions(-)

diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index 3ebbcec..c473206 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -823,6 +823,116 @@ static const struct of_device_id pci_ids[] = {
 	{},
 };
 
+#ifdef CONFIG_SWIOTLB
+void pci_check_swiotlb(void)
+{
+	const u32 *ranges;
+	int rlen;
+	int pna;
+	int np;
+	struct device_node *node;
+	int memno;
+	u32 pci_space;
+	unsigned long long pci_addr, cpu_addr, pci_next, cpu_next, size;
+	unsigned long long pci_addr_lo = ULLONG_MAX;
+	unsigned long long pci_addr_hi = 0x0;
+	dma_addr_t pci_dma_sz;
+
+	for_each_node_by_type(node, "pci") {
+		if (of_match_node(pci_ids, node)) {
+			memno = 0;
+			pna = of_n_addr_cells(node);
+			np = pna + 5;
+			/* Get ranges property */
+			ranges = of_get_property(node, "ranges", &rlen);
+			if (ranges == NULL)
+				return;
+
+			/* Parse outbound MEM window range */
+			while ((rlen -= np * 4) >= 0) {
+				/* Read next ranges element */
+				pci_space = ranges[0];
+				if (!((pci_space >> 24) & 0x2)) {
+					ranges += np;
+					break;
+				}
+				pci_addr = of_read_number(ranges + 1, 2);
+				cpu_addr = of_translate_address(
+						node, ranges + 3);
+				size = of_read_number(ranges + pna + 3, 2);
+				ranges += np;
+
+				/*
+				 * If we failed translation or got a zero-sized
+				 * region (some FW try to feed us with non
+				 * sensical zero sized regions such as power3
+				 * which look like some kind of attempt at
+				 * exposing the VGA memory hole)
+				 */
+				if (cpu_addr == OF_BAD_ADDR || size == 0)
+					continue;
+
+				/*
+				 * Now consume following elements while they
+				 * are contiguous
+				 */
+				for (; rlen >= np * sizeof(u32);
+						ranges += np, rlen -= np * 4) {
+					if (ranges[0] != pci_space)
+						break;
+					pci_next = of_read_number(ranges + 1,
+							2);
+					cpu_next = of_translate_address(node,
+							ranges + 3);
+					if (pci_next != pci_addr + size ||
+						cpu_next != cpu_addr + size)
+						break;
+					size += of_read_number(
+							ranges + pna + 3, 2);
+				}
+
+				/* We support only 3 memory ranges */
+				if (memno >= 3) {
+					printk(KERN_INFO
+							" \\--> Skipped (too many) !\n");
+					continue;
+				}
+
+				pci_addr_lo = min(pci_addr, pci_addr_lo);
+				pci_addr_hi = max(pci_addr + size, pci_addr_hi);
+				memno++;
+			}
+		}
+	}
+
+	/* Get PEXCSRBAR size (equal to CCSR size) */
+	node = of_find_node_by_type(NULL, "soc");
+	ranges = of_get_property(node, "ranges", &rlen);
+	if (ranges == NULL)
+		return;
+
+	size = of_read_number(ranges + 3, 1);
+	of_node_put(node);
+
+	if (pci_addr_hi < (0x100000000ull - size))
+		pci_dma_sz = pci_addr_lo;
+	else
+		pci_dma_sz = pci_addr_lo - size;
+
+	/*
+	 * if we couldn't map all of DRAM via the dma windows
+	 * we need SWIOTLB to handle buffers located outside of
+	 * dma capable memory region
+	 */
+	if (memblock_end_of_DRAM() > pci_dma_sz) {
+		ppc_swiotlb_enable = 1;
+		set_pci_dma_ops(&swiotlb_dma_ops);
+		ppc_md.pci_dma_dev_setup =
+			pci_dma_dev_setup_swiotlb;
+	}
+}
+#endif
+
 int primary_phb_addr;
 static int __devinit fsl_pci_probe(struct platform_device *pdev)
 {
@@ -834,21 +944,6 @@ static int __devinit fsl_pci_probe(struct platform_device *pdev)
 		of_address_to_resource(pdev->dev.of_node, 0, &rsrc);
 		is_primary = ((rsrc.start & 0xfffff) == primary_phb_addr);
 		fsl_add_bridge(pdev->dev.of_node, is_primary);
-
-#ifdef CONFIG_SWIOTLB
-		hose = pci_find_hose_for_OF_device(pdev->dev.of_node);
-		/*
-		 * if we couldn't map all of DRAM via the dma windows
-		 * we need SWIOTLB to handle buffers located outside of
-		 * dma capable memory region
-		 */
-		if (memblock_end_of_DRAM() > hose->dma_window_base_cur
-				+ hose->dma_window_size) {
-			ppc_swiotlb_enable = 1;
-			set_pci_dma_ops(&swiotlb_dma_ops);
-			ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
-		}
-#endif
 	}
 
 	return 0;
diff --git a/arch/powerpc/sysdev/fsl_pci.h b/arch/powerpc/sysdev/fsl_pci.h
index df9fc44..c2c1de5 100644
--- a/arch/powerpc/sysdev/fsl_pci.h
+++ b/arch/powerpc/sysdev/fsl_pci.h
@@ -94,5 +94,11 @@ extern void fsl_pcibios_fixup_bus(struct pci_bus *bus);
 extern int mpc83xx_add_bridge(struct device_node *dev);
 u64 fsl_pci_immrbar_base(struct pci_controller *hose);
 
+#ifdef CONFIG_SWIOTLB
+extern void pci_check_swiotlb(void);
+#else
+static inline void pci_check_swiotlb(void) {}
+#endif
+
 #endif /* __POWERPC_FSL_PCI_H */
 #endif /* __KERNEL__ */
-- 
1.7.5.1

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

* [PATCH V2 3/6] powerpc/fsl-pci: Determine primary bus by looking for ISA node
  2012-07-25  9:26 [PATCH V2 1/6] powerpc/fsl-pci: Unify pci/pcie initialization code Jia Hongtao
  2012-07-25  9:26 ` [PATCH V2 2/6] powerpc/fsl-pci: Check swiotlb enable at board setup_arch stage Jia Hongtao
@ 2012-07-25  9:26 ` Jia Hongtao
  2012-07-25  9:26 ` [PATCH V2 4/6] powerpc/mpc85xx: convert to unified PCI init Jia Hongtao
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: Jia Hongtao @ 2012-07-25  9:26 UTC (permalink / raw)
  To: linuxppc-dev, galak, B07421; +Cc: b38951

PCI host bridge is primary bus if it contains an ISA node. But not all boards
fit this rule. Device tree should be updated for all these boards.

Signed-off-by: Jia Hongtao <B38951@freescale.com>
Signed-off-by: Li Yang <leoli@freescale.com>
---
 arch/powerpc/include/asm/pci-bridge.h |    1 +
 arch/powerpc/sysdev/fsl_pci.c         |   31 ++++++++++++++++++++++++-------
 arch/powerpc/sysdev/fsl_pci.h         |   12 +++++++++++-
 3 files changed, 36 insertions(+), 8 deletions(-)

diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h
index ac39e6a..b48fa7f 100644
--- a/arch/powerpc/include/asm/pci-bridge.h
+++ b/arch/powerpc/include/asm/pci-bridge.h
@@ -20,6 +20,7 @@ struct device_node;
 struct pci_controller {
 	struct pci_bus *bus;
 	char is_dynamic;
+	int is_primary;
 #ifdef CONFIG_PPC64
 	int node;
 #endif
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index c473206..babeec6 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -453,6 +453,7 @@ int __init fsl_add_bridge(struct device_node *dev, int is_primary)
 
 	hose->first_busno = bus_range ? bus_range[0] : 0x0;
 	hose->last_busno = bus_range ? bus_range[1] : 0xff;
+	hose->is_primary = is_primary;
 
 	setup_indirect_pci(hose, rsrc.start, rsrc.start + 0x4,
 		PPC_INDIRECT_TYPE_BIG_ENDIAN);
@@ -933,18 +934,34 @@ void pci_check_swiotlb(void)
 }
 #endif
 
-int primary_phb_addr;
+/*
+ * Recursively scan all the children nodes of parent and find out if there
+ * is "isa" node. Return 1 if parent has isa node otherwise return 0.
+ */
+int has_isa_node(struct device_node *parent)
+{
+	static int result;
+	struct device_node *cur_child;
+
+	cur_child = NULL;
+	result = 0;
+	while (!result && (cur_child = of_get_next_child(parent, cur_child))) {
+		/* Get "isa" node and return 1 */
+		if (of_node_cmp(cur_child->type, "isa") == 0)
+			return result = 1;
+		has_isa_node(cur_child);
+	}
+
+	return result;
+}
+
 static int __devinit fsl_pci_probe(struct platform_device *pdev)
 {
-	struct pci_controller *hose;
 	bool is_primary;
+	is_primary = has_isa_node(pdev->dev.of_node);
 
-	if (of_match_node(pci_ids, pdev->dev.of_node)) {
-		struct resource rsrc;
-		of_address_to_resource(pdev->dev.of_node, 0, &rsrc);
-		is_primary = ((rsrc.start & 0xfffff) == primary_phb_addr);
+	if (of_match_node(pci_ids, pdev->dev.of_node))
 		fsl_add_bridge(pdev->dev.of_node, is_primary);
-	}
 
 	return 0;
 }
diff --git a/arch/powerpc/sysdev/fsl_pci.h b/arch/powerpc/sysdev/fsl_pci.h
index c2c1de5..abbc09d 100644
--- a/arch/powerpc/sysdev/fsl_pci.h
+++ b/arch/powerpc/sysdev/fsl_pci.h
@@ -88,7 +88,17 @@ struct ccsr_pci {
 	__be32	pex_err_cap_r3;		/* 0x.e34 - PCIE error capture register 0 */
 };
 
-extern int primary_phb_addr;
+
+#ifdef CONFIG_SUSPEND
+struct fsl_pci_private_data {
+	int inbound_num;
+	struct pci_outbound_window_regs __iomem *pci_pow;
+	struct pci_inbound_window_regs __iomem *pci_piw;
+	void *saved_regs;
+};
+#endif
+
+extern int is_has_isa_node(struct device_node *parent);
 extern int fsl_add_bridge(struct device_node *dev, int is_primary);
 extern void fsl_pcibios_fixup_bus(struct pci_bus *bus);
 extern int mpc83xx_add_bridge(struct device_node *dev);
-- 
1.7.5.1

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

* [PATCH V2 4/6] powerpc/mpc85xx: convert to unified PCI init
  2012-07-25  9:26 [PATCH V2 1/6] powerpc/fsl-pci: Unify pci/pcie initialization code Jia Hongtao
  2012-07-25  9:26 ` [PATCH V2 2/6] powerpc/fsl-pci: Check swiotlb enable at board setup_arch stage Jia Hongtao
  2012-07-25  9:26 ` [PATCH V2 3/6] powerpc/fsl-pci: Determine primary bus by looking for ISA node Jia Hongtao
@ 2012-07-25  9:26 ` Jia Hongtao
  2012-07-25  9:27 ` [PATCH V2 5/6] powerpc/fsl-pci: Add pci inbound/outbound PM support Jia Hongtao
  2012-07-25  9:27 ` [PATCH V2 6/6] Edac/85xx: Register mpc85xx_pci_err_driver by fsl_pci_driver Jia Hongtao
  4 siblings, 0 replies; 6+ messages in thread
From: Jia Hongtao @ 2012-07-25  9:26 UTC (permalink / raw)
  To: linuxppc-dev, galak, B07421; +Cc: b38951

PCI initialization is now done by PCI controller driver. In board setup_arch
stage we don't need PCI init any more but swiotlb should be determined at this
stage.

Signed-off-by: Jia Hongtao <B38951@freescale.com>
Signed-off-by: Li Yang <leoli@freescale.com>
---
We now just apply this for mpc85xx_ds and qemu

 arch/powerpc/platforms/85xx/mpc85xx_ds.c |   38 +++++++----------------------
 arch/powerpc/platforms/85xx/qemu_e500.c  |    5 +++-
 2 files changed, 13 insertions(+), 30 deletions(-)

diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ds.c b/arch/powerpc/platforms/85xx/mpc85xx_ds.c
index 6d3265f..3082ee8 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_ds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_ds.c
@@ -117,40 +117,16 @@ void __init mpc85xx_ds_pic_init(void)
 extern int uli_exclude_device(struct pci_controller *hose,
 				u_char bus, u_char devfn);
 
-static struct device_node *pci_with_uli;
-
 static int mpc85xx_exclude_device(struct pci_controller *hose,
 				   u_char bus, u_char devfn)
 {
-	if (hose->dn == pci_with_uli)
+	if (hose->is_primary)
 		return uli_exclude_device(hose, bus, devfn);
 
 	return PCIBIOS_SUCCESSFUL;
 }
 #endif	/* CONFIG_PCI */
 
-static void __init mpc85xx_ds_pci_init(void)
-{
-#ifdef CONFIG_PCI
-	struct device_node *node;
-
-	fsl_pci_init();
-
-	/* See if we have a ULI under the primary */
-
-	node = of_find_node_by_name(NULL, "uli1575");
-	while ((pci_with_uli = of_get_parent(node))) {
-		of_node_put(node);
-		node = pci_with_uli;
-
-		if (pci_with_uli == fsl_pci_primary) {
-			ppc_md.pci_exclude_device = mpc85xx_exclude_device;
-			break;
-		}
-	}
-#endif
-}
-
 /*
  * Setup the architecture
  */
@@ -159,7 +135,11 @@ static void __init mpc85xx_ds_setup_arch(void)
 	if (ppc_md.progress)
 		ppc_md.progress("mpc85xx_ds_setup_arch()", 0);
 
-	mpc85xx_ds_pci_init();
+#ifdef CONFIG_PCI
+	pci_check_swiotlb();
+	ppc_md.pci_exclude_device = mpc85xx_exclude_device;
+#endif
+
 	mpc85xx_smp_init();
 
 	printk("MPC85xx DS board from Freescale Semiconductor\n");
@@ -175,9 +155,9 @@ static int __init mpc8544_ds_probe(void)
 	return !!of_flat_dt_is_compatible(root, "MPC8544DS");
 }
 
-machine_device_initcall(mpc8544_ds, mpc85xx_common_publish_devices);
-machine_device_initcall(mpc8572_ds, mpc85xx_common_publish_devices);
-machine_device_initcall(p2020_ds, mpc85xx_common_publish_devices);
+machine_arch_initcall(mpc8544_ds, mpc85xx_common_publish_devices);
+machine_arch_initcall(mpc8572_ds, mpc85xx_common_publish_devices);
+machine_arch_initcall(p2020_ds, mpc85xx_common_publish_devices);
 
 machine_arch_initcall(mpc8544_ds, swiotlb_setup_bus_notifier);
 machine_arch_initcall(mpc8572_ds, swiotlb_setup_bus_notifier);
diff --git a/arch/powerpc/platforms/85xx/qemu_e500.c b/arch/powerpc/platforms/85xx/qemu_e500.c
index 95a2e53..025c9c2 100644
--- a/arch/powerpc/platforms/85xx/qemu_e500.c
+++ b/arch/powerpc/platforms/85xx/qemu_e500.c
@@ -41,7 +41,10 @@ static void __init qemu_e500_setup_arch(void)
 {
 	ppc_md.progress("qemu_e500_setup_arch()", 0);
 
-	fsl_pci_init();
+#ifdef CONFIG_PCI
+	pci_check_swiotlb();
+#endif
+
 	mpc85xx_smp_init();
 }
 
-- 
1.7.5.1

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

* [PATCH V2 5/6] powerpc/fsl-pci: Add pci inbound/outbound PM support
  2012-07-25  9:26 [PATCH V2 1/6] powerpc/fsl-pci: Unify pci/pcie initialization code Jia Hongtao
                   ` (2 preceding siblings ...)
  2012-07-25  9:26 ` [PATCH V2 4/6] powerpc/mpc85xx: convert to unified PCI init Jia Hongtao
@ 2012-07-25  9:27 ` Jia Hongtao
  2012-07-25  9:27 ` [PATCH V2 6/6] Edac/85xx: Register mpc85xx_pci_err_driver by fsl_pci_driver Jia Hongtao
  4 siblings, 0 replies; 6+ messages in thread
From: Jia Hongtao @ 2012-07-25  9:27 UTC (permalink / raw)
  To: linuxppc-dev, galak, B07421; +Cc: b38951

Power supply for PCI inbound/outbound window registers is off when system
go to deep-sleep state. We save the values of registers before suspend
and restore to registers after resume.

Signed-off-by: Jiang Yutang <b14898@freescale.com>
Signed-off-by: Jia Hongtao <B38951@freescale.com>
Signed-off-by: Li Yang <leoli@freescale.com>
---
 arch/powerpc/include/asm/pci-bridge.h |    2 +-
 arch/powerpc/sysdev/fsl_pci.c         |  121 +++++++++++++++++++++++++++++++++
 2 files changed, 122 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/include/asm/pci-bridge.h b/arch/powerpc/include/asm/pci-bridge.h
index b48fa7f..f0f00a7 100644
--- a/arch/powerpc/include/asm/pci-bridge.h
+++ b/arch/powerpc/include/asm/pci-bridge.h
@@ -90,9 +90,9 @@ struct pci_controller {
 
 #ifdef CONFIG_PPC64
 	unsigned long buid;
+#endif	/* CONFIG_PPC64 */
 
 	void *private_data;
-#endif	/* CONFIG_PPC64 */
 };
 
 /* These are used for config access before all the PCI probing
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index babeec6..f67e609 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -966,12 +966,133 @@ static int __devinit fsl_pci_probe(struct platform_device *pdev)
 	return 0;
 }
 
+#ifdef CONFIG_SUSPEND
+
+#define PCI_POW_PIW_OFFSET	0xc00
+#define PCI_POW_PIW_SIZE	0x200
+#define PCI_POW_NUMBER		5
+
+static int fsl_pci_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct pci_controller *hose;
+	struct pci_outbound_window_regs *pci_saved_pow;
+	struct pci_inbound_window_regs *pci_saved_piw, *temp_piw;
+	struct resource pci_rsrc;
+	unsigned int i;
+	struct fsl_pci_private_data *sus_info;
+
+	hose = pci_find_hose_for_OF_device(pdev->dev.of_node);
+	of_address_to_resource(pdev->dev.of_node, 0, &pci_rsrc);
+
+	sus_info = kmalloc(
+			sizeof(struct fsl_pci_private_data), GFP_KERNEL);
+	if (!sus_info)
+		return -ENOMEM;
+
+	hose->private_data = sus_info;
+
+	sus_info->pci_pow = ioremap(pci_rsrc.start + PCI_POW_PIW_OFFSET,
+			PCI_POW_PIW_SIZE);
+	if (!sus_info->pci_pow) {
+		dev_err(&pdev->dev, "pci outbound/inbound windows ioremap error!\n");
+		goto err1;
+	}
+
+	sus_info->pci_piw = (struct pci_inbound_window_regs *)
+		((void *)sus_info->pci_pow + PCI_POW_PIW_SIZE) - 1;
+
+	if (of_device_is_compatible(pdev->dev.of_node, "fsl,qoriq-pcie-v2.2"))
+		sus_info->inbound_num = 4;
+	else
+		sus_info->inbound_num = 3;
+
+	sus_info->saved_regs = kmalloc(
+		sizeof(struct pci_outbound_window_regs) * PCI_POW_NUMBER +
+		sizeof(struct pci_inbound_window_regs) * sus_info->inbound_num,
+		GFP_KERNEL);
+	if (!sus_info->saved_regs)
+		goto err2;
+
+	pci_saved_pow = sus_info->saved_regs;
+	for (i = 0; i < PCI_POW_NUMBER; i++) {
+		pci_saved_pow[i].potar = in_be32(&sus_info->pci_pow[i].potar);
+		pci_saved_pow[i].potear = in_be32(&sus_info->pci_pow[i].potear);
+		pci_saved_pow[i].powbar = in_be32(&sus_info->pci_pow[i].powbar);
+		pci_saved_pow[i].powar = in_be32(&sus_info->pci_pow[i].powar);
+	}
+
+	pci_saved_piw = (struct pci_inbound_window_regs *)
+		(pci_saved_pow + PCI_POW_NUMBER);
+	temp_piw = sus_info->pci_piw;
+	for (i = 0; i < sus_info->inbound_num; i++, temp_piw--) {
+		pci_saved_piw[i].pitar = in_be32(&temp_piw->pitar);
+		pci_saved_piw[i].piwbar = in_be32(&temp_piw->piwbar);
+		pci_saved_piw[i].piwbear = in_be32(&temp_piw->piwbear);
+		pci_saved_piw[i].piwar = in_be32(&temp_piw->piwar);
+	}
+
+	return 0;
+
+err2:
+	iounmap(sus_info->pci_pow);
+
+err1:
+	kfree(sus_info);
+	return -ENOMEM;
+}
+
+static int fsl_pci_resume(struct platform_device *pdev)
+{
+	struct pci_controller *hose;
+	struct pci_outbound_window_regs *pci_saved_pow;
+	struct pci_inbound_window_regs *pci_saved_piw, *temp_piw;
+	unsigned int i;
+	struct fsl_pci_private_data *sus_info;
+
+	hose = pci_find_hose_for_OF_device(pdev->dev.of_node);
+	sus_info = (struct fsl_pci_private_data *)hose->private_data;
+
+	if (!sus_info->pci_pow || !sus_info->pci_piw || !sus_info->saved_regs)
+		return 0;
+
+	pci_saved_pow = sus_info->saved_regs;
+	for (i = 0; i < PCI_POW_NUMBER; i++) {
+		out_be32(&sus_info->pci_pow[i].potar, pci_saved_pow[i].potar);
+		out_be32(&sus_info->pci_pow[i].potear, pci_saved_pow[i].potear);
+		out_be32(&sus_info->pci_pow[i].powbar, pci_saved_pow[i].powbar);
+		out_be32(&sus_info->pci_pow[i].powar, pci_saved_pow[i].powar);
+	}
+
+	pci_saved_piw = (struct pci_inbound_window_regs *)
+		(pci_saved_pow + PCI_POW_NUMBER);
+	temp_piw = sus_info->pci_piw;
+	for (i = 0; i < sus_info->inbound_num; i++, temp_piw--) {
+		out_be32(&temp_piw->pitar, pci_saved_piw[i].pitar);
+		out_be32(&temp_piw->piwbar, pci_saved_piw[i].piwbar);
+		out_be32(&temp_piw->piwbear, pci_saved_piw[i].piwbear);
+		out_be32(&temp_piw->piwar, pci_saved_piw[i].piwar);
+	}
+	iounmap(sus_info->pci_pow);
+	kfree(sus_info->saved_regs);
+	sus_info->saved_regs = NULL;
+	kfree(sus_info);
+	sus_info = NULL;
+	hose->private_data = NULL;
+
+	return 0;
+}
+#endif
+
 static struct platform_driver fsl_pci_driver = {
 	.driver = {
 		.name = "fsl-pci",
 		.of_match_table = pci_ids,
 	},
 	.probe = fsl_pci_probe,
+#ifdef CONFIG_SUSPEND
+	.suspend	= fsl_pci_suspend,
+	.resume		= fsl_pci_resume,
+#endif
 };
 
 static int __init fsl_pci_init(void)
-- 
1.7.5.1

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

* [PATCH V2 6/6] Edac/85xx: Register mpc85xx_pci_err_driver by fsl_pci_driver
  2012-07-25  9:26 [PATCH V2 1/6] powerpc/fsl-pci: Unify pci/pcie initialization code Jia Hongtao
                   ` (3 preceding siblings ...)
  2012-07-25  9:27 ` [PATCH V2 5/6] powerpc/fsl-pci: Add pci inbound/outbound PM support Jia Hongtao
@ 2012-07-25  9:27 ` Jia Hongtao
  4 siblings, 0 replies; 6+ messages in thread
From: Jia Hongtao @ 2012-07-25  9:27 UTC (permalink / raw)
  To: linuxppc-dev, galak, B07421; +Cc: b38951

From: Chunhe Lan <Chunhe.Lan@freescale.com>

Now we registered pci controllers as platform devices. It will make edac
driver failed to register pci nodes as platform devices too. So we combine
two initialization code as one platform driver.

Signed-off-by: Chunhe Lan <Chunhe.Lan@freescale.com>
Signed-off-by: Li Yang <leoli@freescale.com>
Signed-off-by: Jia Hongtao <B38951@freescale.com>
---
 arch/powerpc/sysdev/fsl_pci.c |    4 +++
 arch/powerpc/sysdev/fsl_pci.h |    4 +++
 drivers/edac/mpc85xx_edac.c   |   43 +++++++++++-----------------------------
 3 files changed, 20 insertions(+), 31 deletions(-)

diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index f67e609..e84e230 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -963,6 +963,10 @@ static int __devinit fsl_pci_probe(struct platform_device *pdev)
 	if (of_match_node(pci_ids, pdev->dev.of_node))
 		fsl_add_bridge(pdev->dev.of_node, is_primary);
 
+#ifdef CONFIG_EDAC_MPC85XX
+	mpc85xx_pci_err_probe(pdev);
+#endif
+
 	return 0;
 }
 
diff --git a/arch/powerpc/sysdev/fsl_pci.h b/arch/powerpc/sysdev/fsl_pci.h
index abbc09d..1dfe85d 100644
--- a/arch/powerpc/sysdev/fsl_pci.h
+++ b/arch/powerpc/sysdev/fsl_pci.h
@@ -110,5 +110,9 @@ extern void pci_check_swiotlb(void);
 static inline void pci_check_swiotlb(void) {}
 #endif
 
+#ifdef CONFIG_EDAC_MPC85XX
+extern int mpc85xx_pci_err_probe(struct platform_device *op);
+#endif
+
 #endif /* __POWERPC_FSL_PCI_H */
 #endif /* __KERNEL__ */
diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c
index 0e37462..e4b6113 100644
--- a/drivers/edac/mpc85xx_edac.c
+++ b/drivers/edac/mpc85xx_edac.c
@@ -200,7 +200,7 @@ static irqreturn_t mpc85xx_pci_isr(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
-static int __devinit mpc85xx_pci_err_probe(struct platform_device *op)
+int __devinit mpc85xx_pci_err_probe(struct platform_device *op)
 {
 	struct edac_pci_ctl_info *pci;
 	struct mpc85xx_pci_pdata *pdata;
@@ -214,6 +214,16 @@ static int __devinit mpc85xx_pci_err_probe(struct platform_device *op)
 	if (!pci)
 		return -ENOMEM;
 
+	/* make sure error reporting method is sane */
+	switch (edac_op_state) {
+	case EDAC_OPSTATE_POLL:
+	case EDAC_OPSTATE_INT:
+		break;
+	default:
+		edac_op_state = EDAC_OPSTATE_INT;
+		break;
+	}
+
 	pdata = pci->pvt_info;
 	pdata->name = "mpc85xx_pci_err";
 	pdata->irq = NO_IRQ;
@@ -303,6 +313,7 @@ err:
 	devres_release_group(&op->dev, mpc85xx_pci_err_probe);
 	return res;
 }
+EXPORT_SYMBOL(mpc85xx_pci_err_probe);
 
 static int mpc85xx_pci_err_remove(struct platform_device *op)
 {
@@ -326,27 +337,6 @@ static int mpc85xx_pci_err_remove(struct platform_device *op)
 	return 0;
 }
 
-static struct of_device_id mpc85xx_pci_err_of_match[] = {
-	{
-	 .compatible = "fsl,mpc8540-pcix",
-	 },
-	{
-	 .compatible = "fsl,mpc8540-pci",
-	},
-	{},
-};
-MODULE_DEVICE_TABLE(of, mpc85xx_pci_err_of_match);
-
-static struct platform_driver mpc85xx_pci_err_driver = {
-	.probe = mpc85xx_pci_err_probe,
-	.remove = __devexit_p(mpc85xx_pci_err_remove),
-	.driver = {
-		.name = "mpc85xx_pci_err",
-		.owner = THIS_MODULE,
-		.of_match_table = mpc85xx_pci_err_of_match,
-	},
-};
-
 #endif				/* CONFIG_PCI */
 
 /**************************** L2 Err device ***************************/
@@ -1193,12 +1183,6 @@ static int __init mpc85xx_mc_init(void)
 	if (res)
 		printk(KERN_WARNING EDAC_MOD_STR "L2 fails to register\n");
 
-#ifdef CONFIG_PCI
-	res = platform_driver_register(&mpc85xx_pci_err_driver);
-	if (res)
-		printk(KERN_WARNING EDAC_MOD_STR "PCI fails to register\n");
-#endif
-
 #ifdef CONFIG_FSL_SOC_BOOKE
 	pvr = mfspr(SPRN_PVR);
 
@@ -1235,9 +1219,6 @@ static void __exit mpc85xx_mc_exit(void)
 		on_each_cpu(mpc85xx_mc_restore_hid1, NULL, 0);
 	}
 #endif
-#ifdef CONFIG_PCI
-	platform_driver_unregister(&mpc85xx_pci_err_driver);
-#endif
 	platform_driver_unregister(&mpc85xx_l2_err_driver);
 	platform_driver_unregister(&mpc85xx_mc_err_driver);
 }
-- 
1.7.5.1

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

end of thread, other threads:[~2012-07-25  9:50 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-07-25  9:26 [PATCH V2 1/6] powerpc/fsl-pci: Unify pci/pcie initialization code Jia Hongtao
2012-07-25  9:26 ` [PATCH V2 2/6] powerpc/fsl-pci: Check swiotlb enable at board setup_arch stage Jia Hongtao
2012-07-25  9:26 ` [PATCH V2 3/6] powerpc/fsl-pci: Determine primary bus by looking for ISA node Jia Hongtao
2012-07-25  9:26 ` [PATCH V2 4/6] powerpc/mpc85xx: convert to unified PCI init Jia Hongtao
2012-07-25  9:27 ` [PATCH V2 5/6] powerpc/fsl-pci: Add pci inbound/outbound PM support Jia Hongtao
2012-07-25  9:27 ` [PATCH V2 6/6] Edac/85xx: Register mpc85xx_pci_err_driver by fsl_pci_driver Jia Hongtao

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.