2 * arch/arm/mach-dove/pcie.c
4 * PCIe functions for Marvell Dove 88AP510 SoC
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>
14 #include <asm/mach/pci.h>
15 #include <asm/mach/arch.h>
16 #include <asm/setup.h>
17 #include <asm/delay.h>
18 #include <plat/pcie.h>
19 #include <mach/irqs.h>
20 #include <mach/bridge-regs.h>
28 char io_space_name
[16];
29 char mem_space_name
[16];
30 struct resource res
[2];
33 static struct pcie_port pcie_port
[2];
34 static int num_pcie_ports
;
37 static int __init
dove_pcie_setup(int nr
, struct pci_sys_data
*sys
)
41 if (nr
>= num_pcie_ports
)
45 pp
->root_bus_nr
= sys
->busnr
;
48 * Generic PCIe unit setup.
50 orion_pcie_set_local_bus_nr(pp
->base
, sys
->busnr
);
52 orion_pcie_setup(pp
->base
, &dove_mbus_dram_info
);
57 snprintf(pp
->io_space_name
, sizeof(pp
->io_space_name
),
58 "PCIe %d I/O", pp
->index
);
59 pp
->io_space_name
[sizeof(pp
->io_space_name
) - 1] = 0;
60 pp
->res
[0].name
= pp
->io_space_name
;
62 pp
->res
[0].start
= DOVE_PCIE0_IO_PHYS_BASE
;
63 pp
->res
[0].end
= pp
->res
[0].start
+ DOVE_PCIE0_IO_SIZE
- 1;
65 pp
->res
[0].start
= DOVE_PCIE1_IO_PHYS_BASE
;
66 pp
->res
[0].end
= pp
->res
[0].start
+ DOVE_PCIE1_IO_SIZE
- 1;
68 pp
->res
[0].flags
= IORESOURCE_IO
;
69 if (request_resource(&ioport_resource
, &pp
->res
[0]))
70 panic("Request PCIe IO resource failed\n");
71 sys
->resource
[0] = &pp
->res
[0];
76 snprintf(pp
->mem_space_name
, sizeof(pp
->mem_space_name
),
77 "PCIe %d MEM", pp
->index
);
78 pp
->mem_space_name
[sizeof(pp
->mem_space_name
) - 1] = 0;
79 pp
->res
[1].name
= pp
->mem_space_name
;
81 pp
->res
[1].start
= DOVE_PCIE0_MEM_PHYS_BASE
;
82 pp
->res
[1].end
= pp
->res
[1].start
+ DOVE_PCIE0_MEM_SIZE
- 1;
84 pp
->res
[1].start
= DOVE_PCIE1_MEM_PHYS_BASE
;
85 pp
->res
[1].end
= pp
->res
[1].start
+ DOVE_PCIE1_MEM_SIZE
- 1;
87 pp
->res
[1].flags
= IORESOURCE_MEM
;
88 if (request_resource(&iomem_resource
, &pp
->res
[1]))
89 panic("Request PCIe Memory resource failed\n");
90 sys
->resource
[1] = &pp
->res
[1];
92 sys
->resource
[2] = NULL
;
97 static struct pcie_port
*bus_to_port(int bus
)
101 for (i
= num_pcie_ports
- 1; i
>= 0; i
--) {
102 int rbus
= pcie_port
[i
].root_bus_nr
;
103 if (rbus
!= -1 && rbus
<= bus
)
107 return i
>= 0 ? pcie_port
+ i
: NULL
;
110 static int pcie_valid_config(struct pcie_port
*pp
, int bus
, int dev
)
113 * Don't go out when trying to access nonexisting devices
116 if (bus
== pp
->root_bus_nr
&& dev
> 1)
122 static int pcie_rd_conf(struct pci_bus
*bus
, u32 devfn
, int where
,
125 struct pcie_port
*pp
= bus_to_port(bus
->number
);
129 if (pcie_valid_config(pp
, bus
->number
, PCI_SLOT(devfn
)) == 0) {
131 return PCIBIOS_DEVICE_NOT_FOUND
;
134 spin_lock_irqsave(&pp
->conf_lock
, flags
);
135 ret
= orion_pcie_rd_conf(pp
->base
, bus
, devfn
, where
, size
, val
);
136 spin_unlock_irqrestore(&pp
->conf_lock
, flags
);
141 static int pcie_wr_conf(struct pci_bus
*bus
, u32 devfn
,
142 int where
, int size
, u32 val
)
144 struct pcie_port
*pp
= bus_to_port(bus
->number
);
148 if (pcie_valid_config(pp
, bus
->number
, PCI_SLOT(devfn
)) == 0)
149 return PCIBIOS_DEVICE_NOT_FOUND
;
151 spin_lock_irqsave(&pp
->conf_lock
, flags
);
152 ret
= orion_pcie_wr_conf(pp
->base
, bus
, devfn
, where
, size
, val
);
153 spin_unlock_irqrestore(&pp
->conf_lock
, flags
);
158 static struct pci_ops pcie_ops
= {
159 .read
= pcie_rd_conf
,
160 .write
= pcie_wr_conf
,
163 static void __devinit
rc_pci_fixup(struct pci_dev
*dev
)
166 * Prevent enumeration of root complex.
168 if (dev
->bus
->parent
== NULL
&& dev
->devfn
== 0) {
171 for (i
= 0; i
< DEVICE_COUNT_RESOURCE
; i
++) {
172 dev
->resource
[i
].start
= 0;
173 dev
->resource
[i
].end
= 0;
174 dev
->resource
[i
].flags
= 0;
178 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL
, PCI_ANY_ID
, rc_pci_fixup
);
180 static struct pci_bus __init
*
181 dove_pcie_scan_bus(int nr
, struct pci_sys_data
*sys
)
185 if (nr
< num_pcie_ports
) {
186 bus
= pci_scan_bus(sys
->busnr
, &pcie_ops
, sys
);
195 static int __init
dove_pcie_map_irq(struct pci_dev
*dev
, u8 slot
, u8 pin
)
197 struct pcie_port
*pp
= bus_to_port(dev
->bus
->number
);
199 return pp
->index
? IRQ_DOVE_PCIE1
: IRQ_DOVE_PCIE0
;
202 static struct hw_pci dove_pci __initdata
= {
204 .swizzle
= pci_std_swizzle
,
205 .setup
= dove_pcie_setup
,
206 .scan
= dove_pcie_scan_bus
,
207 .map_irq
= dove_pcie_map_irq
,
210 static void __init
add_pcie_port(int index
, unsigned long base
)
212 printk(KERN_INFO
"Dove PCIe port %d: ", index
);
214 if (orion_pcie_link_up((void __iomem
*)base
)) {
215 struct pcie_port
*pp
= &pcie_port
[num_pcie_ports
++];
217 printk(KERN_INFO
"link up\n");
220 pp
->root_bus_nr
= -1;
221 pp
->base
= (void __iomem
*)base
;
222 spin_lock_init(&pp
->conf_lock
);
223 memset(pp
->res
, 0, sizeof(pp
->res
));
225 printk(KERN_INFO
"link down, ignoring\n");
229 void __init
dove_pcie_init(int init_port0
, int init_port1
)
232 add_pcie_port(0, DOVE_PCIE0_VIRT_BASE
);
235 add_pcie_port(1, DOVE_PCIE1_VIRT_BASE
);
237 pci_common_init(&dove_pci
);