]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - arch/arm/mach-mv78xx0/pcie.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-2.6-nommu
[linux-2.6-omap-h63xx.git] / arch / arm / mach-mv78xx0 / pcie.c
1 /*
2  * arch/arm/mach-mv78xx0/pcie.c
3  *
4  * PCIe functions for Marvell MV78xx0 SoCs
5  *
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.
9  */
10
11 #include <linux/kernel.h>
12 #include <linux/pci.h>
13 #include <linux/mbus.h>
14 #include <asm/irq.h>
15 #include <asm/mach/pci.h>
16 #include <plat/pcie.h>
17 #include "common.h"
18
19 struct pcie_port {
20         u8                      maj;
21         u8                      min;
22         u8                      root_bus_nr;
23         void __iomem            *base;
24         spinlock_t              conf_lock;
25         char                    io_space_name[16];
26         char                    mem_space_name[16];
27         struct resource         res[2];
28 };
29
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;
34
35
36 static void __init mv78xx0_pcie_preinit(void)
37 {
38         int i;
39         u32 size_each;
40         u32 start;
41         int win;
42
43         pcie_io_space.name = "PCIe I/O Space";
44         pcie_io_space.start = MV78XX0_PCIE_IO_PHYS_BASE(0);
45         pcie_io_space.end =
46                 MV78XX0_PCIE_IO_PHYS_BASE(0) + MV78XX0_PCIE_IO_SIZE * 8 - 1;
47         pcie_io_space.flags = IORESOURCE_IO;
48         if (request_resource(&iomem_resource, &pcie_io_space))
49                 panic("can't allocate PCIe I/O space");
50
51         pcie_mem_space.name = "PCIe MEM Space";
52         pcie_mem_space.start = MV78XX0_PCIE_MEM_PHYS_BASE;
53         pcie_mem_space.end =
54                 MV78XX0_PCIE_MEM_PHYS_BASE + MV78XX0_PCIE_MEM_SIZE - 1;
55         pcie_mem_space.flags = IORESOURCE_MEM;
56         if (request_resource(&iomem_resource, &pcie_mem_space))
57                 panic("can't allocate PCIe MEM space");
58
59         for (i = 0; i < num_pcie_ports; i++) {
60                 struct pcie_port *pp = pcie_port + i;
61
62                 snprintf(pp->io_space_name, sizeof(pp->io_space_name),
63                         "PCIe %d.%d I/O", pp->maj, pp->min);
64                 pp->io_space_name[sizeof(pp->io_space_name) - 1] = 0;
65                 pp->res[0].name = pp->io_space_name;
66                 pp->res[0].start = MV78XX0_PCIE_IO_PHYS_BASE(i);
67                 pp->res[0].end = pp->res[0].start + MV78XX0_PCIE_IO_SIZE - 1;
68                 pp->res[0].flags = IORESOURCE_IO;
69
70                 snprintf(pp->mem_space_name, sizeof(pp->mem_space_name),
71                         "PCIe %d.%d MEM", pp->maj, pp->min);
72                 pp->mem_space_name[sizeof(pp->mem_space_name) - 1] = 0;
73                 pp->res[1].name = pp->mem_space_name;
74                 pp->res[1].flags = IORESOURCE_MEM;
75         }
76
77         switch (num_pcie_ports) {
78         case 0:
79                 size_each = 0;
80                 break;
81
82         case 1:
83                 size_each = 0x30000000;
84                 break;
85
86         case 2 ... 3:
87                 size_each = 0x10000000;
88                 break;
89
90         case 4 ... 6:
91                 size_each = 0x08000000;
92                 break;
93
94         case 7:
95                 size_each = 0x04000000;
96                 break;
97
98         default:
99                 panic("invalid number of PCIe ports");
100         }
101
102         start = MV78XX0_PCIE_MEM_PHYS_BASE;
103         for (i = 0; i < num_pcie_ports; i++) {
104                 struct pcie_port *pp = pcie_port + i;
105
106                 pp->res[1].start = start;
107                 pp->res[1].end = start + size_each - 1;
108                 start += size_each;
109         }
110
111         for (i = 0; i < num_pcie_ports; i++) {
112                 struct pcie_port *pp = pcie_port + i;
113
114                 if (request_resource(&pcie_io_space, &pp->res[0]))
115                         panic("can't allocate PCIe I/O sub-space");
116
117                 if (request_resource(&pcie_mem_space, &pp->res[1]))
118                         panic("can't allocate PCIe MEM sub-space");
119         }
120
121         win = 0;
122         for (i = 0; i < num_pcie_ports; i++) {
123                 struct pcie_port *pp = pcie_port + i;
124
125                 mv78xx0_setup_pcie_io_win(win++, pp->res[0].start,
126                         pp->res[0].end - pp->res[0].start + 1,
127                         pp->maj, pp->min);
128
129                 mv78xx0_setup_pcie_mem_win(win++, pp->res[1].start,
130                         pp->res[1].end - pp->res[1].start + 1,
131                         pp->maj, pp->min);
132         }
133 }
134
135 static int __init mv78xx0_pcie_setup(int nr, struct pci_sys_data *sys)
136 {
137         struct pcie_port *pp;
138
139         if (nr >= num_pcie_ports)
140                 return 0;
141
142         pp = &pcie_port[nr];
143         pp->root_bus_nr = sys->busnr;
144
145         /*
146          * Generic PCIe unit setup.
147          */
148         orion_pcie_set_local_bus_nr(pp->base, sys->busnr);
149         orion_pcie_setup(pp->base, &mv78xx0_mbus_dram_info);
150
151         sys->resource[0] = &pp->res[0];
152         sys->resource[1] = &pp->res[1];
153         sys->resource[2] = NULL;
154
155         return 1;
156 }
157
158 static struct pcie_port *bus_to_port(int bus)
159 {
160         int i;
161
162         for (i = num_pcie_ports - 1; i >= 0; i--) {
163                 int rbus = pcie_port[i].root_bus_nr;
164                 if (rbus != -1 && rbus <= bus)
165                         break;
166         }
167
168         return i >= 0 ? pcie_port + i : NULL;
169 }
170
171 static int pcie_valid_config(struct pcie_port *pp, int bus, int dev)
172 {
173         /*
174          * Don't go out when trying to access nonexisting devices
175          * on the local bus.
176          */
177         if (bus == pp->root_bus_nr && dev > 1)
178                 return 0;
179
180         return 1;
181 }
182
183 static int pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
184                         int size, u32 *val)
185 {
186         struct pcie_port *pp = bus_to_port(bus->number);
187         unsigned long flags;
188         int ret;
189
190         if (pcie_valid_config(pp, bus->number, PCI_SLOT(devfn)) == 0) {
191                 *val = 0xffffffff;
192                 return PCIBIOS_DEVICE_NOT_FOUND;
193         }
194
195         spin_lock_irqsave(&pp->conf_lock, flags);
196         ret = orion_pcie_rd_conf(pp->base, bus, devfn, where, size, val);
197         spin_unlock_irqrestore(&pp->conf_lock, flags);
198
199         return ret;
200 }
201
202 static int pcie_wr_conf(struct pci_bus *bus, u32 devfn,
203                         int where, int size, u32 val)
204 {
205         struct pcie_port *pp = bus_to_port(bus->number);
206         unsigned long flags;
207         int ret;
208
209         if (pcie_valid_config(pp, bus->number, PCI_SLOT(devfn)) == 0)
210                 return PCIBIOS_DEVICE_NOT_FOUND;
211
212         spin_lock_irqsave(&pp->conf_lock, flags);
213         ret = orion_pcie_wr_conf(pp->base, bus, devfn, where, size, val);
214         spin_unlock_irqrestore(&pp->conf_lock, flags);
215
216         return ret;
217 }
218
219 static struct pci_ops pcie_ops = {
220         .read = pcie_rd_conf,
221         .write = pcie_wr_conf,
222 };
223
224 static void __devinit rc_pci_fixup(struct pci_dev *dev)
225 {
226         /*
227          * Prevent enumeration of root complex.
228          */
229         if (dev->bus->parent == NULL && dev->devfn == 0) {
230                 int i;
231
232                 for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
233                         dev->resource[i].start = 0;
234                         dev->resource[i].end   = 0;
235                         dev->resource[i].flags = 0;
236                 }
237         }
238 }
239 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL, PCI_ANY_ID, rc_pci_fixup);
240
241 static struct pci_bus __init *
242 mv78xx0_pcie_scan_bus(int nr, struct pci_sys_data *sys)
243 {
244         struct pci_bus *bus;
245
246         if (nr < num_pcie_ports) {
247                 bus = pci_scan_bus(sys->busnr, &pcie_ops, sys);
248         } else {
249                 bus = NULL;
250                 BUG();
251         }
252
253         return bus;
254 }
255
256 static int __init mv78xx0_pcie_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
257 {
258         struct pcie_port *pp = bus_to_port(dev->bus->number);
259
260         return IRQ_MV78XX0_PCIE_00 + (pp->maj << 2) + pp->min;
261 }
262
263 static struct hw_pci mv78xx0_pci __initdata = {
264         .nr_controllers = 8,
265         .preinit        = mv78xx0_pcie_preinit,
266         .swizzle        = pci_std_swizzle,
267         .setup          = mv78xx0_pcie_setup,
268         .scan           = mv78xx0_pcie_scan_bus,
269         .map_irq        = mv78xx0_pcie_map_irq,
270 };
271
272 static void __init add_pcie_port(int maj, int min, unsigned long base)
273 {
274         printk(KERN_INFO "MV78xx0 PCIe port %d.%d: ", maj, min);
275
276         if (orion_pcie_link_up((void __iomem *)base)) {
277                 struct pcie_port *pp = &pcie_port[num_pcie_ports++];
278
279                 printk("link up\n");
280
281                 pp->maj = maj;
282                 pp->min = min;
283                 pp->root_bus_nr = -1;
284                 pp->base = (void __iomem *)base;
285                 spin_lock_init(&pp->conf_lock);
286                 memset(pp->res, 0, sizeof(pp->res));
287         } else {
288                 printk("link down, ignoring\n");
289         }
290 }
291
292 void __init mv78xx0_pcie_init(int init_port0, int init_port1)
293 {
294         if (init_port0) {
295                 add_pcie_port(0, 0, PCIE00_VIRT_BASE);
296                 if (!orion_pcie_x4_mode((void __iomem *)PCIE00_VIRT_BASE)) {
297                         add_pcie_port(0, 1, PCIE01_VIRT_BASE);
298                         add_pcie_port(0, 2, PCIE02_VIRT_BASE);
299                         add_pcie_port(0, 3, PCIE03_VIRT_BASE);
300                 }
301         }
302
303         if (init_port1) {
304                 add_pcie_port(1, 0, PCIE10_VIRT_BASE);
305                 if (!orion_pcie_x4_mode((void __iomem *)PCIE10_VIRT_BASE)) {
306                         add_pcie_port(1, 1, PCIE11_VIRT_BASE);
307                         add_pcie_port(1, 2, PCIE12_VIRT_BASE);
308                         add_pcie_port(1, 3, PCIE13_VIRT_BASE);
309                 }
310         }
311
312         pci_common_init(&mv78xx0_pci);
313 }