aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorMichal Simek <monstr@monstr.eu>2010-01-18 09:27:11 -0500
committerMichal Simek <monstr@monstr.eu>2010-03-11 08:05:18 -0500
commit733cc2183116b216abb52e709709bb0e626c9a75 (patch)
tree8764b775948622c493f70f136d25b359af90e04c /arch
parenta6475c132278c1be158a13872c233aeab8a00176 (diff)
microblaze: Add support for Xilinx PCI host bridge
This patch is based on powerpc patch 64f16502475ddf663169369fffff6da9b10ea9fb We did some cleanups and removed powerpc parts. There is one new debug early listing function too. Exclude function is only in Debug options. We tested in on custom board. Signed-off-by: Michal Simek <monstr@monstr.eu>
Diffstat (limited to 'arch')
-rw-r--r--arch/microblaze/Kconfig4
-rw-r--r--arch/microblaze/include/asm/pci.h7
-rw-r--r--arch/microblaze/kernel/setup.c3
-rw-r--r--arch/microblaze/pci/Makefile1
-rw-r--r--arch/microblaze/pci/xilinx_pci.c168
5 files changed, 183 insertions, 0 deletions
diff --git a/arch/microblaze/Kconfig b/arch/microblaze/Kconfig
index e1fa0844ba4e..c1e731bb3301 100644
--- a/arch/microblaze/Kconfig
+++ b/arch/microblaze/Kconfig
@@ -267,6 +267,10 @@ config PCI_DOMAINS
267config PCI_SYSCALL 267config PCI_SYSCALL
268 def_bool PCI 268 def_bool PCI
269 269
270config PCI_XILINX
271 bool "Xilinx PCI host bridge support"
272 depends on PCI
273
270source "drivers/pci/Kconfig" 274source "drivers/pci/Kconfig"
271 275
272endmenu 276endmenu
diff --git a/arch/microblaze/include/asm/pci.h b/arch/microblaze/include/asm/pci.h
index fecc04481101..bdd65aaee30d 100644
--- a/arch/microblaze/include/asm/pci.h
+++ b/arch/microblaze/include/asm/pci.h
@@ -166,5 +166,12 @@ extern void pci_resource_to_user(const struct pci_dev *dev, int bar,
166extern void pcibios_setup_bus_devices(struct pci_bus *bus); 166extern void pcibios_setup_bus_devices(struct pci_bus *bus);
167extern void pcibios_setup_bus_self(struct pci_bus *bus); 167extern void pcibios_setup_bus_self(struct pci_bus *bus);
168 168
169/* This part of code was originaly in xilinx-pci.h */
170#ifdef CONFIG_PCI_XILINX
171extern void __init xilinx_pci_init(void);
172#else
173static inline void __init xilinx_pci_init(void) { return; }
174#endif
175
169#endif /* __KERNEL__ */ 176#endif /* __KERNEL__ */
170#endif /* __ASM_MICROBLAZE_PCI_H */ 177#endif /* __ASM_MICROBLAZE_PCI_H */
diff --git a/arch/microblaze/kernel/setup.c b/arch/microblaze/kernel/setup.c
index bc325ac4efd3..cd68e988b48c 100644
--- a/arch/microblaze/kernel/setup.c
+++ b/arch/microblaze/kernel/setup.c
@@ -22,6 +22,7 @@
22#include <linux/io.h> 22#include <linux/io.h>
23#include <linux/bug.h> 23#include <linux/bug.h>
24#include <linux/param.h> 24#include <linux/param.h>
25#include <linux/pci.h>
25#include <linux/cache.h> 26#include <linux/cache.h>
26#include <linux/of_platform.h> 27#include <linux/of_platform.h>
27#include <linux/dma-mapping.h> 28#include <linux/dma-mapping.h>
@@ -64,6 +65,8 @@ void __init setup_arch(char **cmdline_p)
64 65
65 setup_memory(); 66 setup_memory();
66 67
68 xilinx_pci_init();
69
67#if defined(CONFIG_SELFMOD_INTC) || defined(CONFIG_SELFMOD_TIMER) 70#if defined(CONFIG_SELFMOD_INTC) || defined(CONFIG_SELFMOD_TIMER)
68 printk(KERN_NOTICE "Self modified code enable\n"); 71 printk(KERN_NOTICE "Self modified code enable\n");
69#endif 72#endif
diff --git a/arch/microblaze/pci/Makefile b/arch/microblaze/pci/Makefile
index 2b8901864b23..9889cc2e1294 100644
--- a/arch/microblaze/pci/Makefile
+++ b/arch/microblaze/pci/Makefile
@@ -3,3 +3,4 @@
3# 3#
4 4
5obj-$(CONFIG_PCI) += pci_32.o pci-common.o indirect_pci.o iomap.o 5obj-$(CONFIG_PCI) += pci_32.o pci-common.o indirect_pci.o iomap.o
6obj-$(CONFIG_PCI_XILINX) += xilinx_pci.o
diff --git a/arch/microblaze/pci/xilinx_pci.c b/arch/microblaze/pci/xilinx_pci.c
new file mode 100644
index 000000000000..7869a41b0f94
--- /dev/null
+++ b/arch/microblaze/pci/xilinx_pci.c
@@ -0,0 +1,168 @@
1/*
2 * PCI support for Xilinx plbv46_pci soft-core which can be used on
3 * Xilinx Virtex ML410 / ML510 boards.
4 *
5 * Copyright 2009 Roderick Colenbrander
6 * Copyright 2009 Secret Lab Technologies Ltd.
7 *
8 * The pci bridge fixup code was copied from ppc4xx_pci.c and was written
9 * by Benjamin Herrenschmidt.
10 * Copyright 2007 Ben. Herrenschmidt <benh@kernel.crashing.org>, IBM Corp.
11 *
12 * This file is licensed under the terms of the GNU General Public License
13 * version 2. This program is licensed "as is" without any warranty of any
14 * kind, whether express or implied.
15 */
16
17#include <linux/ioport.h>
18#include <linux/of.h>
19#include <linux/pci.h>
20#include <asm/io.h>
21
22#define XPLB_PCI_ADDR 0x10c
23#define XPLB_PCI_DATA 0x110
24#define XPLB_PCI_BUS 0x114
25
26#define PCI_HOST_ENABLE_CMD (PCI_COMMAND_SERR | PCI_COMMAND_PARITY | \
27 PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY)
28
29static struct of_device_id xilinx_pci_match[] = {
30 { .compatible = "xlnx,plbv46-pci-1.03.a", },
31 {}
32};
33
34/**
35 * xilinx_pci_fixup_bridge - Block Xilinx PHB configuration.
36 */
37static void xilinx_pci_fixup_bridge(struct pci_dev *dev)
38{
39 struct pci_controller *hose;
40 int i;
41
42 if (dev->devfn || dev->bus->self)
43 return;
44
45 hose = pci_bus_to_host(dev->bus);
46 if (!hose)
47 return;
48
49 if (!of_match_node(xilinx_pci_match, hose->dn))
50 return;
51
52 /* Hide the PCI host BARs from the kernel as their content doesn't
53 * fit well in the resource management
54 */
55 for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
56 dev->resource[i].start = 0;
57 dev->resource[i].end = 0;
58 dev->resource[i].flags = 0;
59 }
60
61 dev_info(&dev->dev, "Hiding Xilinx plb-pci host bridge resources %s\n",
62 pci_name(dev));
63}
64DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, xilinx_pci_fixup_bridge);
65
66#ifdef DEBUG
67/**
68 * xilinx_pci_exclude_device - Don't do config access for non-root bus
69 *
70 * This is a hack. Config access to any bus other than bus 0 does not
71 * currently work on the ML510 so we prevent it here.
72 */
73static int
74xilinx_pci_exclude_device(struct pci_controller *hose, u_char bus, u8 devfn)
75{
76 return (bus != 0);
77}
78
79/**
80 * xilinx_early_pci_scan - List pci config space for available devices
81 *
82 * List pci devices in very early phase.
83 */
84void __init xilinx_early_pci_scan(struct pci_controller *hose)
85{
86 u32 bus = 0;
87 u32 val, dev, func, offset;
88
89 /* Currently we have only 2 device connected - up-to 32 devices */
90 for (dev = 0; dev < 2; dev++) {
91 /* List only first function number - up-to 8 functions */
92 for (func = 0; func < 1; func++) {
93 printk(KERN_INFO "%02x:%02x:%02x", bus, dev, func);
94 /* read the first 64 standardized bytes */
95 /* Up-to 192 bytes can be list of capabilities */
96 for (offset = 0; offset < 64; offset += 4) {
97 early_read_config_dword(hose, bus,
98 PCI_DEVFN(dev, func), offset, &val);
99 if (offset == 0 && val == 0xFFFFFFFF) {
100 printk(KERN_CONT "\nABSENT");
101 break;
102 }
103 if (!(offset % 0x10))
104 printk(KERN_CONT "\n%04x: ", offset);
105
106 printk(KERN_CONT "%08x ", val);
107 }
108 printk(KERN_INFO "\n");
109 }
110 }
111}
112#else
113void __init xilinx_early_pci_scan(struct pci_controller *hose)
114{
115}
116#endif
117
118/**
119 * xilinx_pci_init - Find and register a Xilinx PCI host bridge
120 */
121void __init xilinx_pci_init(void)
122{
123 struct pci_controller *hose;
124 struct resource r;
125 void __iomem *pci_reg;
126 struct device_node *pci_node;
127
128 pci_node = of_find_matching_node(NULL, xilinx_pci_match);
129 if (!pci_node)
130 return;
131
132 if (of_address_to_resource(pci_node, 0, &r)) {
133 pr_err("xilinx-pci: cannot resolve base address\n");
134 return;
135 }
136
137 hose = pcibios_alloc_controller(pci_node);
138 if (!hose) {
139 pr_err("xilinx-pci: pcibios_alloc_controller() failed\n");
140 return;
141 }
142
143 /* Setup config space */
144 setup_indirect_pci(hose, r.start + XPLB_PCI_ADDR,
145 r.start + XPLB_PCI_DATA,
146 INDIRECT_TYPE_SET_CFG_TYPE);
147
148 /* According to the xilinx plbv46_pci documentation the soft-core starts
149 * a self-init when the bus master enable bit is set. Without this bit
150 * set the pci bus can't be scanned.
151 */
152 early_write_config_word(hose, 0, 0, PCI_COMMAND, PCI_HOST_ENABLE_CMD);
153
154 /* Set the max latency timer to 255 */
155 early_write_config_byte(hose, 0, 0, PCI_LATENCY_TIMER, 0xff);
156
157 /* Set the max bus number to 255, and bus/subbus no's to 0 */
158 pci_reg = of_iomap(pci_node, 0);
159 out_be32(pci_reg + XPLB_PCI_BUS, 0x000000ff);
160 iounmap(pci_reg);
161
162 /* Register the host bridge with the linux kernel! */
163 pci_process_bridge_OF_ranges(hose, pci_node,
164 INDIRECT_TYPE_SET_CFG_TYPE);
165
166 pr_info("xilinx-pci: Registered PCI host bridge\n");
167 xilinx_early_pci_scan(hose);
168}