OSDN Git Service

Merge git://git.kernel.org/pub/scm/linux/kernel/git/cmetcalf/linux-tile
[uclinux-h8/linux.git] / arch / arm / mach-kirkwood / pcie.c
1 /*
2  * arch/arm/mach-kirkwood/pcie.c
3  *
4  * PCIe functions for Marvell Kirkwood 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/slab.h>
14 #include <video/vga.h>
15 #include <asm/irq.h>
16 #include <asm/mach/pci.h>
17 #include <plat/pcie.h>
18 #include <mach/bridge-regs.h>
19 #include <plat/addr-map.h>
20 #include "common.h"
21
22 void kirkwood_enable_pcie(void)
23 {
24         u32 curr = readl(CLOCK_GATING_CTRL);
25         if (!(curr & CGC_PEX0))
26                 writel(curr | CGC_PEX0, CLOCK_GATING_CTRL);
27 }
28
29 void __init kirkwood_pcie_id(u32 *dev, u32 *rev)
30 {
31         kirkwood_enable_pcie();
32         *dev = orion_pcie_dev_id((void __iomem *)PCIE_VIRT_BASE);
33         *rev = orion_pcie_rev((void __iomem *)PCIE_VIRT_BASE);
34 }
35
36 struct pcie_port {
37         u8                      root_bus_nr;
38         void __iomem            *base;
39         spinlock_t              conf_lock;
40         int                     irq;
41         struct resource         res[2];
42 };
43
44 static int pcie_port_map[2];
45 static int num_pcie_ports;
46
47 static int pcie_valid_config(struct pcie_port *pp, int bus, int dev)
48 {
49         /*
50          * Don't go out when trying to access --
51          * 1. nonexisting device on local bus
52          * 2. where there's no device connected (no link)
53          */
54         if (bus == pp->root_bus_nr && dev == 0)
55                 return 1;
56
57         if (!orion_pcie_link_up(pp->base))
58                 return 0;
59
60         if (bus == pp->root_bus_nr && dev != 1)
61                 return 0;
62
63         return 1;
64 }
65
66
67 /*
68  * PCIe config cycles are done by programming the PCIE_CONF_ADDR register
69  * and then reading the PCIE_CONF_DATA register. Need to make sure these
70  * transactions are atomic.
71  */
72
73 static int pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
74                         int size, u32 *val)
75 {
76         struct pci_sys_data *sys = bus->sysdata;
77         struct pcie_port *pp = sys->private_data;
78         unsigned long flags;
79         int ret;
80
81         if (pcie_valid_config(pp, bus->number, PCI_SLOT(devfn)) == 0) {
82                 *val = 0xffffffff;
83                 return PCIBIOS_DEVICE_NOT_FOUND;
84         }
85
86         spin_lock_irqsave(&pp->conf_lock, flags);
87         ret = orion_pcie_rd_conf(pp->base, bus, devfn, where, size, val);
88         spin_unlock_irqrestore(&pp->conf_lock, flags);
89
90         return ret;
91 }
92
93 static int pcie_wr_conf(struct pci_bus *bus, u32 devfn,
94                         int where, int size, u32 val)
95 {
96         struct pci_sys_data *sys = bus->sysdata;
97         struct pcie_port *pp = sys->private_data;
98         unsigned long flags;
99         int ret;
100
101         if (pcie_valid_config(pp, bus->number, PCI_SLOT(devfn)) == 0)
102                 return PCIBIOS_DEVICE_NOT_FOUND;
103
104         spin_lock_irqsave(&pp->conf_lock, flags);
105         ret = orion_pcie_wr_conf(pp->base, bus, devfn, where, size, val);
106         spin_unlock_irqrestore(&pp->conf_lock, flags);
107
108         return ret;
109 }
110
111 static struct pci_ops pcie_ops = {
112         .read = pcie_rd_conf,
113         .write = pcie_wr_conf,
114 };
115
116 static void __init pcie0_ioresources_init(struct pcie_port *pp)
117 {
118         pp->base = (void __iomem *)PCIE_VIRT_BASE;
119         pp->irq = IRQ_KIRKWOOD_PCIE;
120
121         /*
122          * IORESOURCE_IO
123          */
124         pp->res[0].name = "PCIe 0 I/O Space";
125         pp->res[0].start = KIRKWOOD_PCIE_IO_BUS_BASE;
126         pp->res[0].end = pp->res[0].start + KIRKWOOD_PCIE_IO_SIZE - 1;
127         pp->res[0].flags = IORESOURCE_IO;
128
129         /*
130          * IORESOURCE_MEM
131          */
132         pp->res[1].name = "PCIe 0 MEM";
133         pp->res[1].start = KIRKWOOD_PCIE_MEM_PHYS_BASE;
134         pp->res[1].end = pp->res[1].start + KIRKWOOD_PCIE_MEM_SIZE - 1;
135         pp->res[1].flags = IORESOURCE_MEM;
136 }
137
138 static void __init pcie1_ioresources_init(struct pcie_port *pp)
139 {
140         pp->base = (void __iomem *)PCIE1_VIRT_BASE;
141         pp->irq = IRQ_KIRKWOOD_PCIE1;
142
143         /*
144          * IORESOURCE_IO
145          */
146         pp->res[0].name = "PCIe 1 I/O Space";
147         pp->res[0].start = KIRKWOOD_PCIE1_IO_BUS_BASE;
148         pp->res[0].end = pp->res[0].start + KIRKWOOD_PCIE1_IO_SIZE - 1;
149         pp->res[0].flags = IORESOURCE_IO;
150
151         /*
152          * IORESOURCE_MEM
153          */
154         pp->res[1].name = "PCIe 1 MEM";
155         pp->res[1].start = KIRKWOOD_PCIE1_MEM_PHYS_BASE;
156         pp->res[1].end = pp->res[1].start + KIRKWOOD_PCIE1_MEM_SIZE - 1;
157         pp->res[1].flags = IORESOURCE_MEM;
158 }
159
160 static int __init kirkwood_pcie_setup(int nr, struct pci_sys_data *sys)
161 {
162         extern unsigned int kirkwood_clk_ctrl;
163         struct pcie_port *pp;
164         int index;
165
166         if (nr >= num_pcie_ports)
167                 return 0;
168
169         index = pcie_port_map[nr];
170         printk(KERN_INFO "PCI: bus%d uses PCIe port %d\n", sys->busnr, index);
171
172         pp = kzalloc(sizeof(*pp), GFP_KERNEL);
173         if (!pp)
174                 panic("PCIe: failed to allocate pcie_port data");
175         sys->private_data = pp;
176         pp->root_bus_nr = sys->busnr;
177         spin_lock_init(&pp->conf_lock);
178
179         switch (index) {
180         case 0:
181                 kirkwood_clk_ctrl |= CGC_PEX0;
182                 pcie0_ioresources_init(pp);
183                 break;
184         case 1:
185                 kirkwood_clk_ctrl |= CGC_PEX1;
186                 pcie1_ioresources_init(pp);
187                 break;
188         default:
189                 panic("PCIe setup: invalid controller %d", index);
190         }
191
192         if (request_resource(&ioport_resource, &pp->res[0]))
193                 panic("Request PCIe%d IO resource failed\n", index);
194         if (request_resource(&iomem_resource, &pp->res[1]))
195                 panic("Request PCIe%d Memory resource failed\n", index);
196
197         sys->io_offset = 0;
198         pci_add_resource_offset(&sys->resources, &pp->res[0], sys->io_offset);
199         pci_add_resource_offset(&sys->resources, &pp->res[1], sys->mem_offset);
200
201         /*
202          * Generic PCIe unit setup.
203          */
204         orion_pcie_set_local_bus_nr(pp->base, sys->busnr);
205
206         orion_pcie_setup(pp->base);
207
208         return 1;
209 }
210
211 static void __devinit rc_pci_fixup(struct pci_dev *dev)
212 {
213         /*
214          * Prevent enumeration of root complex.
215          */
216         if (dev->bus->parent == NULL && dev->devfn == 0) {
217                 int i;
218
219                 for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
220                         dev->resource[i].start = 0;
221                         dev->resource[i].end   = 0;
222                         dev->resource[i].flags = 0;
223                 }
224         }
225 }
226 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL, PCI_ANY_ID, rc_pci_fixup);
227
228 static struct pci_bus __init *
229 kirkwood_pcie_scan_bus(int nr, struct pci_sys_data *sys)
230 {
231         struct pci_bus *bus;
232
233         if (nr < num_pcie_ports) {
234                 bus = pci_scan_root_bus(NULL, sys->busnr, &pcie_ops, sys,
235                                         &sys->resources);
236         } else {
237                 bus = NULL;
238                 BUG();
239         }
240
241         return bus;
242 }
243
244 static int __init kirkwood_pcie_map_irq(const struct pci_dev *dev, u8 slot,
245         u8 pin)
246 {
247         struct pci_sys_data *sys = dev->sysdata;
248         struct pcie_port *pp = sys->private_data;
249
250         return pp->irq;
251 }
252
253 static struct hw_pci kirkwood_pci __initdata = {
254         .setup          = kirkwood_pcie_setup,
255         .scan           = kirkwood_pcie_scan_bus,
256         .map_irq        = kirkwood_pcie_map_irq,
257 };
258
259 static void __init add_pcie_port(int index, unsigned long base)
260 {
261         printk(KERN_INFO "Kirkwood PCIe port %d: ", index);
262
263         if (orion_pcie_link_up((void __iomem *)base)) {
264                 printk(KERN_INFO "link up\n");
265                 pcie_port_map[num_pcie_ports++] = index;
266         } else
267                 printk(KERN_INFO "link down, ignoring\n");
268 }
269
270 void __init kirkwood_pcie_init(unsigned int portmask)
271 {
272         vga_base = KIRKWOOD_PCIE_MEM_PHYS_BASE;
273
274         if (portmask & KW_PCIE0)
275                 add_pcie_port(0, PCIE_VIRT_BASE);
276
277         if (portmask & KW_PCIE1)
278                 add_pcie_port(1, PCIE1_VIRT_BASE);
279
280         kirkwood_pci.nr_controllers = num_pcie_ports;
281         pci_common_init(&kirkwood_pci);
282 }