2 * arch/arm/mach-mv78xx0/pcie.c
4 * PCIe functions for Marvell MV78xx0 SoCs
6 * This file is licensed under the terms of the GNU General Public
7 * License version 2. This program is licensed "as is" without any
8 * warranty of any kind, whether express or implied.
11 #include <linux/kernel.h>
12 #include <linux/pci.h>
13 #include <linux/mbus.h>
15 #include <asm/mach/pci.h>
16 #include <plat/pcie.h>
25 char io_space_name
[16];
26 char mem_space_name
[16];
27 struct resource res
[2];
30 static struct pcie_port pcie_port
[8];
31 static int num_pcie_ports
;
32 static struct resource pcie_io_space
;
33 static struct resource pcie_mem_space
;
36 void __init
mv78xx0_pcie_id(u32
*dev
, u32
*rev
)
38 *dev
= orion_pcie_dev_id((void __iomem
*)PCIE00_VIRT_BASE
);
39 *rev
= orion_pcie_rev((void __iomem
*)PCIE00_VIRT_BASE
);
42 static void __init
mv78xx0_pcie_preinit(void)
49 pcie_io_space
.name
= "PCIe I/O Space";
50 pcie_io_space
.start
= MV78XX0_PCIE_IO_PHYS_BASE(0);
52 MV78XX0_PCIE_IO_PHYS_BASE(0) + MV78XX0_PCIE_IO_SIZE
* 8 - 1;
53 pcie_io_space
.flags
= IORESOURCE_IO
;
54 if (request_resource(&iomem_resource
, &pcie_io_space
))
55 panic("can't allocate PCIe I/O space");
57 pcie_mem_space
.name
= "PCIe MEM Space";
58 pcie_mem_space
.start
= MV78XX0_PCIE_MEM_PHYS_BASE
;
60 MV78XX0_PCIE_MEM_PHYS_BASE
+ MV78XX0_PCIE_MEM_SIZE
- 1;
61 pcie_mem_space
.flags
= IORESOURCE_MEM
;
62 if (request_resource(&iomem_resource
, &pcie_mem_space
))
63 panic("can't allocate PCIe MEM space");
65 for (i
= 0; i
< num_pcie_ports
; i
++) {
66 struct pcie_port
*pp
= pcie_port
+ i
;
68 snprintf(pp
->io_space_name
, sizeof(pp
->io_space_name
),
69 "PCIe %d.%d I/O", pp
->maj
, pp
->min
);
70 pp
->io_space_name
[sizeof(pp
->io_space_name
) - 1] = 0;
71 pp
->res
[0].name
= pp
->io_space_name
;
72 pp
->res
[0].start
= MV78XX0_PCIE_IO_PHYS_BASE(i
);
73 pp
->res
[0].end
= pp
->res
[0].start
+ MV78XX0_PCIE_IO_SIZE
- 1;
74 pp
->res
[0].flags
= IORESOURCE_IO
;
76 snprintf(pp
->mem_space_name
, sizeof(pp
->mem_space_name
),
77 "PCIe %d.%d MEM", pp
->maj
, pp
->min
);
78 pp
->mem_space_name
[sizeof(pp
->mem_space_name
) - 1] = 0;
79 pp
->res
[1].name
= pp
->mem_space_name
;
80 pp
->res
[1].flags
= IORESOURCE_MEM
;
83 switch (num_pcie_ports
) {
89 size_each
= 0x30000000;
93 size_each
= 0x10000000;
97 size_each
= 0x08000000;
101 size_each
= 0x04000000;
105 panic("invalid number of PCIe ports");
108 start
= MV78XX0_PCIE_MEM_PHYS_BASE
;
109 for (i
= 0; i
< num_pcie_ports
; i
++) {
110 struct pcie_port
*pp
= pcie_port
+ i
;
112 pp
->res
[1].start
= start
;
113 pp
->res
[1].end
= start
+ size_each
- 1;
117 for (i
= 0; i
< num_pcie_ports
; i
++) {
118 struct pcie_port
*pp
= pcie_port
+ i
;
120 if (request_resource(&pcie_io_space
, &pp
->res
[0]))
121 panic("can't allocate PCIe I/O sub-space");
123 if (request_resource(&pcie_mem_space
, &pp
->res
[1]))
124 panic("can't allocate PCIe MEM sub-space");
128 for (i
= 0; i
< num_pcie_ports
; i
++) {
129 struct pcie_port
*pp
= pcie_port
+ i
;
131 mv78xx0_setup_pcie_io_win(win
++, pp
->res
[0].start
,
132 pp
->res
[0].end
- pp
->res
[0].start
+ 1,
135 mv78xx0_setup_pcie_mem_win(win
++, pp
->res
[1].start
,
136 pp
->res
[1].end
- pp
->res
[1].start
+ 1,
141 static int __init
mv78xx0_pcie_setup(int nr
, struct pci_sys_data
*sys
)
143 struct pcie_port
*pp
;
145 if (nr
>= num_pcie_ports
)
149 pp
->root_bus_nr
= sys
->busnr
;
152 * Generic PCIe unit setup.
154 orion_pcie_set_local_bus_nr(pp
->base
, sys
->busnr
);
155 orion_pcie_setup(pp
->base
, &mv78xx0_mbus_dram_info
);
157 sys
->resource
[0] = &pp
->res
[0];
158 sys
->resource
[1] = &pp
->res
[1];
159 sys
->resource
[2] = NULL
;
164 static struct pcie_port
*bus_to_port(int bus
)
168 for (i
= num_pcie_ports
- 1; i
>= 0; i
--) {
169 int rbus
= pcie_port
[i
].root_bus_nr
;
170 if (rbus
!= -1 && rbus
<= bus
)
174 return i
>= 0 ? pcie_port
+ i
: NULL
;
177 static int pcie_valid_config(struct pcie_port
*pp
, int bus
, int dev
)
180 * Don't go out when trying to access nonexisting devices
183 if (bus
== pp
->root_bus_nr
&& dev
> 1)
189 static int pcie_rd_conf(struct pci_bus
*bus
, u32 devfn
, int where
,
192 struct pcie_port
*pp
= bus_to_port(bus
->number
);
196 if (pcie_valid_config(pp
, bus
->number
, PCI_SLOT(devfn
)) == 0) {
198 return PCIBIOS_DEVICE_NOT_FOUND
;
201 spin_lock_irqsave(&pp
->conf_lock
, flags
);
202 ret
= orion_pcie_rd_conf(pp
->base
, bus
, devfn
, where
, size
, val
);
203 spin_unlock_irqrestore(&pp
->conf_lock
, flags
);
208 static int pcie_wr_conf(struct pci_bus
*bus
, u32 devfn
,
209 int where
, int size
, u32 val
)
211 struct pcie_port
*pp
= bus_to_port(bus
->number
);
215 if (pcie_valid_config(pp
, bus
->number
, PCI_SLOT(devfn
)) == 0)
216 return PCIBIOS_DEVICE_NOT_FOUND
;
218 spin_lock_irqsave(&pp
->conf_lock
, flags
);
219 ret
= orion_pcie_wr_conf(pp
->base
, bus
, devfn
, where
, size
, val
);
220 spin_unlock_irqrestore(&pp
->conf_lock
, flags
);
225 static struct pci_ops pcie_ops
= {
226 .read
= pcie_rd_conf
,
227 .write
= pcie_wr_conf
,
230 static void __devinit
rc_pci_fixup(struct pci_dev
*dev
)
233 * Prevent enumeration of root complex.
235 if (dev
->bus
->parent
== NULL
&& dev
->devfn
== 0) {
238 for (i
= 0; i
< DEVICE_COUNT_RESOURCE
; i
++) {
239 dev
->resource
[i
].start
= 0;
240 dev
->resource
[i
].end
= 0;
241 dev
->resource
[i
].flags
= 0;
245 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL
, PCI_ANY_ID
, rc_pci_fixup
);
247 static struct pci_bus __init
*
248 mv78xx0_pcie_scan_bus(int nr
, struct pci_sys_data
*sys
)
252 if (nr
< num_pcie_ports
) {
253 bus
= pci_scan_bus(sys
->busnr
, &pcie_ops
, sys
);
262 static int __init
mv78xx0_pcie_map_irq(struct pci_dev
*dev
, u8 slot
, u8 pin
)
264 struct pcie_port
*pp
= bus_to_port(dev
->bus
->number
);
266 return IRQ_MV78XX0_PCIE_00
+ (pp
->maj
<< 2) + pp
->min
;
269 static struct hw_pci mv78xx0_pci __initdata
= {
271 .preinit
= mv78xx0_pcie_preinit
,
272 .swizzle
= pci_std_swizzle
,
273 .setup
= mv78xx0_pcie_setup
,
274 .scan
= mv78xx0_pcie_scan_bus
,
275 .map_irq
= mv78xx0_pcie_map_irq
,
278 static void __init
add_pcie_port(int maj
, int min
, unsigned long base
)
280 printk(KERN_INFO
"MV78xx0 PCIe port %d.%d: ", maj
, min
);
282 if (orion_pcie_link_up((void __iomem
*)base
)) {
283 struct pcie_port
*pp
= &pcie_port
[num_pcie_ports
++];
289 pp
->root_bus_nr
= -1;
290 pp
->base
= (void __iomem
*)base
;
291 spin_lock_init(&pp
->conf_lock
);
292 memset(pp
->res
, 0, sizeof(pp
->res
));
294 printk("link down, ignoring\n");
298 void __init
mv78xx0_pcie_init(int init_port0
, int init_port1
)
301 add_pcie_port(0, 0, PCIE00_VIRT_BASE
);
302 if (!orion_pcie_x4_mode((void __iomem
*)PCIE00_VIRT_BASE
)) {
303 add_pcie_port(0, 1, PCIE01_VIRT_BASE
);
304 add_pcie_port(0, 2, PCIE02_VIRT_BASE
);
305 add_pcie_port(0, 3, PCIE03_VIRT_BASE
);
310 add_pcie_port(1, 0, PCIE10_VIRT_BASE
);
311 if (!orion_pcie_x4_mode((void __iomem
*)PCIE10_VIRT_BASE
)) {
312 add_pcie_port(1, 1, PCIE11_VIRT_BASE
);
313 add_pcie_port(1, 2, PCIE12_VIRT_BASE
);
314 add_pcie_port(1, 3, PCIE13_VIRT_BASE
);
318 pci_common_init(&mv78xx0_pci
);