1 // SPDX-License-Identifier: GPL-2.0-only
3 * arch/arm/mach-dove/pcie.c
5 * PCIe functions for Marvell Dove 88AP510 SoC
8 #include <linux/kernel.h>
10 #include <linux/clk.h>
11 #include <video/vga.h>
12 #include <asm/mach/pci.h>
13 #include <asm/mach/arch.h>
14 #include <asm/setup.h>
15 #include <asm/delay.h>
16 #include <plat/pcie.h>
17 #include <plat/addr-map.h>
19 #include "bridge-regs.h"
27 char mem_space_name
[16];
31 static struct pcie_port pcie_port
[2];
32 static int num_pcie_ports
;
35 static int __init
dove_pcie_setup(int nr
, struct pci_sys_data
*sys
)
38 struct resource realio
;
40 if (nr
>= num_pcie_ports
)
44 sys
->private_data
= pp
;
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
);
54 realio
.start
= sys
->busnr
* SZ_64K
;
55 realio
.end
= realio
.start
+ SZ_64K
- 1;
56 pci_remap_iospace(&realio
, pp
->index
== 0 ? DOVE_PCIE0_IO_PHYS_BASE
:
57 DOVE_PCIE1_IO_PHYS_BASE
);
62 snprintf(pp
->mem_space_name
, sizeof(pp
->mem_space_name
),
63 "PCIe %d MEM", pp
->index
);
64 pp
->mem_space_name
[sizeof(pp
->mem_space_name
) - 1] = 0;
65 pp
->res
.name
= pp
->mem_space_name
;
67 pp
->res
.start
= DOVE_PCIE0_MEM_PHYS_BASE
;
68 pp
->res
.end
= pp
->res
.start
+ DOVE_PCIE0_MEM_SIZE
- 1;
70 pp
->res
.start
= DOVE_PCIE1_MEM_PHYS_BASE
;
71 pp
->res
.end
= pp
->res
.start
+ DOVE_PCIE1_MEM_SIZE
- 1;
73 pp
->res
.flags
= IORESOURCE_MEM
;
74 if (request_resource(&iomem_resource
, &pp
->res
))
75 panic("Request PCIe Memory resource failed\n");
76 pci_add_resource_offset(&sys
->resources
, &pp
->res
, sys
->mem_offset
);
81 static int pcie_valid_config(struct pcie_port
*pp
, int bus
, int dev
)
84 * Don't go out when trying to access nonexisting devices
87 if (bus
== pp
->root_bus_nr
&& dev
> 1)
93 static int pcie_rd_conf(struct pci_bus
*bus
, u32 devfn
, int where
,
96 struct pci_sys_data
*sys
= bus
->sysdata
;
97 struct pcie_port
*pp
= sys
->private_data
;
101 if (pcie_valid_config(pp
, bus
->number
, PCI_SLOT(devfn
)) == 0) {
103 return PCIBIOS_DEVICE_NOT_FOUND
;
106 spin_lock_irqsave(&pp
->conf_lock
, flags
);
107 ret
= orion_pcie_rd_conf(pp
->base
, bus
, devfn
, where
, size
, val
);
108 spin_unlock_irqrestore(&pp
->conf_lock
, flags
);
113 static int pcie_wr_conf(struct pci_bus
*bus
, u32 devfn
,
114 int where
, int size
, u32 val
)
116 struct pci_sys_data
*sys
= bus
->sysdata
;
117 struct pcie_port
*pp
= sys
->private_data
;
121 if (pcie_valid_config(pp
, bus
->number
, PCI_SLOT(devfn
)) == 0)
122 return PCIBIOS_DEVICE_NOT_FOUND
;
124 spin_lock_irqsave(&pp
->conf_lock
, flags
);
125 ret
= orion_pcie_wr_conf(pp
->base
, bus
, devfn
, where
, size
, val
);
126 spin_unlock_irqrestore(&pp
->conf_lock
, flags
);
131 static struct pci_ops pcie_ops
= {
132 .read
= pcie_rd_conf
,
133 .write
= pcie_wr_conf
,
137 * The root complex has a hardwired class of PCI_CLASS_MEMORY_OTHER, when it
138 * is operating as a root complex this needs to be switched to
139 * PCI_CLASS_BRIDGE_HOST or Linux will errantly try to process the BAR's on
140 * the device. Decoding setup is handled by the orion code.
142 static void rc_pci_fixup(struct pci_dev
*dev
)
144 if (dev
->bus
->parent
== NULL
&& dev
->devfn
== 0) {
148 dev
->class |= PCI_CLASS_BRIDGE_HOST
<< 8;
149 pci_dev_for_each_resource(dev
, r
) {
156 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL
, PCI_ANY_ID
, rc_pci_fixup
);
159 dove_pcie_scan_bus(int nr
, struct pci_host_bridge
*bridge
)
161 struct pci_sys_data
*sys
= pci_host_bridge_priv(bridge
);
163 if (nr
>= num_pcie_ports
) {
168 list_splice_init(&sys
->resources
, &bridge
->windows
);
169 bridge
->dev
.parent
= NULL
;
170 bridge
->sysdata
= sys
;
171 bridge
->busnr
= sys
->busnr
;
172 bridge
->ops
= &pcie_ops
;
174 return pci_scan_root_bus_bridge(bridge
);
177 static int __init
dove_pcie_map_irq(const struct pci_dev
*dev
, u8 slot
, u8 pin
)
179 struct pci_sys_data
*sys
= dev
->sysdata
;
180 struct pcie_port
*pp
= sys
->private_data
;
182 return pp
->index
? IRQ_DOVE_PCIE1
: IRQ_DOVE_PCIE0
;
185 static struct hw_pci dove_pci __initdata
= {
187 .setup
= dove_pcie_setup
,
188 .scan
= dove_pcie_scan_bus
,
189 .map_irq
= dove_pcie_map_irq
,
192 static void __init
add_pcie_port(int index
, void __iomem
*base
)
194 printk(KERN_INFO
"Dove PCIe port %d: ", index
);
196 if (orion_pcie_link_up(base
)) {
197 struct pcie_port
*pp
= &pcie_port
[num_pcie_ports
++];
198 struct clk
*clk
= clk_get_sys("pcie", (index
? "1" : "0"));
201 clk_prepare_enable(clk
);
203 printk(KERN_INFO
"link up\n");
206 pp
->root_bus_nr
= -1;
208 spin_lock_init(&pp
->conf_lock
);
209 memset(&pp
->res
, 0, sizeof(pp
->res
));
211 printk(KERN_INFO
"link down, ignoring\n");
215 void __init
dove_pcie_init(int init_port0
, int init_port1
)
217 vga_base
= DOVE_PCIE0_MEM_PHYS_BASE
;
220 add_pcie_port(0, DOVE_PCIE0_VIRT_BASE
);
223 add_pcie_port(1, DOVE_PCIE1_VIRT_BASE
);
225 pci_common_init(&dove_pci
);