blob: 025cc1802de2cc0481b36ff8e0ffdb6be35c60a6 [file] [log] [blame]
Peter Tyser1c2b3292008-12-17 16:36:23 -06001/*
2 * Copyright 2008 Extreme Engineering Solutions, Inc.
3 * Copyright 2007-2008 Freescale Semiconductor, Inc.
4 *
5 * See file CREDITS for list of people who contributed to this
6 * project.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21 * MA 02111-1307 USA
22 */
23
24#include <common.h>
25#include <pci.h>
Kumar Gala9bbd6432009-04-02 13:22:48 -050026#include <asm/fsl_pci.h>
Peter Tyser1c2b3292008-12-17 16:36:23 -060027#include <libfdt.h>
28#include <fdt_support.h>
29
Peter Tyser1c2b3292008-12-17 16:36:23 -060030int first_free_busno = 0;
31
Peter Tyser59b5fdf2008-12-01 13:47:13 -060032#ifdef CONFIG_PCI1
33static struct pci_controller pci1_hose;
34#endif
Peter Tyser1c2b3292008-12-17 16:36:23 -060035#ifdef CONFIG_PCIE1
36static struct pci_controller pcie1_hose;
37#endif
38#ifdef CONFIG_PCIE2
39static struct pci_controller pcie2_hose;
40#endif
41#ifdef CONFIG_PCIE3
42static struct pci_controller pcie3_hose;
43#endif
44
Peter Tyser59b5fdf2008-12-01 13:47:13 -060045#ifdef CONFIG_MPC8572
Peter Tyser1c2b3292008-12-17 16:36:23 -060046/* Correlate host/agent POR bits to usable info. Table 4-14 */
47struct host_agent_cfg_t {
48 uchar pcie_root[3];
49 uchar rio_host;
50} host_agent_cfg[8] = {
51 {{0, 0, 0}, 0},
52 {{0, 1, 1}, 1},
53 {{1, 0, 1}, 0},
54 {{1, 1, 0}, 1},
55 {{0, 0, 1}, 0},
56 {{0, 1, 0}, 1},
57 {{1, 0, 0}, 0},
58 {{1, 1, 1}, 1}
59};
60
61/* Correlate port width POR bits to usable info. Table 4-15 */
62struct io_port_cfg_t {
63 uchar pcie_width[3];
64 uchar rio_width;
65} io_port_cfg[16] = {
66 {{0, 0, 0}, 0},
67 {{0, 0, 0}, 0},
68 {{4, 0, 0}, 0},
69 {{4, 4, 0}, 0},
70 {{0, 0, 0}, 0},
71 {{0, 0, 0}, 0},
72 {{0, 0, 0}, 4},
73 {{4, 2, 2}, 0},
74 {{0, 0, 0}, 0},
75 {{0, 0, 0}, 0},
76 {{0, 0, 0}, 0},
77 {{4, 0, 0}, 4},
78 {{4, 0, 0}, 4},
79 {{0, 0, 0}, 4},
80 {{0, 0, 0}, 4},
81 {{8, 0, 0}, 0},
82};
Peter Tyser59b5fdf2008-12-01 13:47:13 -060083#elif defined CONFIG_MPC8548
84/* Correlate host/agent POR bits to usable info. Table 4-12 */
85struct host_agent_cfg_t {
86 uchar pci_host[2];
87 uchar pcie_root[1];
88 uchar rio_host;
89} host_agent_cfg[8] = {
90 {{1, 1}, {0}, 0},
91 {{1, 1}, {1}, 0},
92 {{1, 1}, {0}, 1},
93 {{0, 0}, {0}, 0}, /* reserved */
94 {{0, 1}, {1}, 0},
95 {{1, 1}, {1}, 0},
96 {{0, 1}, {1}, 1},
97 {{1, 1}, {1}, 1}
98};
Peter Tyser1c2b3292008-12-17 16:36:23 -060099
Peter Tyser59b5fdf2008-12-01 13:47:13 -0600100/* Correlate port width POR bits to usable info. Table 4-13 */
101struct io_port_cfg_t {
102 uchar pcie_width[1];
103 uchar rio_width;
104} io_port_cfg[8] = {
105 {{0}, 0},
106 {{0}, 0},
107 {{0}, 0},
108 {{4}, 4},
109 {{4}, 4},
110 {{0}, 4},
111 {{0}, 4},
112 {{8}, 0},
113};
Peter Tyser75379822009-05-22 10:26:35 -0500114#elif defined CONFIG_MPC86xx
115/* Correlate host/agent POR bits to usable info. Table 4-17 */
116struct host_agent_cfg_t {
117 uchar pcie_root[2];
118 uchar rio_host;
119} host_agent_cfg[8] = {
120 {{0, 0}, 0},
121 {{1, 0}, 1},
122 {{0, 1}, 0},
123 {{1, 1}, 1}
124};
125
126/* Correlate port width POR bits to usable info. Table 4-16 */
127struct io_port_cfg_t {
128 uchar pcie_width[2];
129 uchar rio_width;
130} io_port_cfg[16] = {
131 {{0, 0}, 0},
132 {{0, 0}, 0},
133 {{8, 0}, 0},
134 {{8, 8}, 0},
135 {{0, 0}, 0},
136 {{8, 0}, 4},
137 {{8, 0}, 4},
138 {{8, 0}, 4},
139 {{0, 0}, 0},
140 {{0, 0}, 4},
141 {{0, 0}, 4},
142 {{0, 0}, 4},
143 {{0, 0}, 0},
144 {{0, 0}, 0},
145 {{0, 8}, 0},
146 {{8, 8}, 0},
147};
Peter Tyser59b5fdf2008-12-01 13:47:13 -0600148#endif
149
Peter Tyser75379822009-05-22 10:26:35 -0500150/*
151 * 85xx and 86xx share naming conventions, but different layout.
152 * Correlate names to CPU-specific values to share common
153 * PCI code.
154 */
155#if defined(CONFIG_MPC85xx)
156#define MPC8xxx_DEVDISR_PCIE1 MPC85xx_DEVDISR_PCIE
157#define MPC8xxx_DEVDISR_PCIE2 MPC85xx_DEVDISR_PCIE2
158#define MPC8xxx_DEVDISR_PCIE3 MPC85xx_DEVDISR_PCIE3
159#define MPC8xxx_PORDEVSR_IO_SEL MPC85xx_PORDEVSR_IO_SEL
160#define MPC8xxx_PORDEVSR_IO_SEL_SHIFT MPC85xx_PORDEVSR_IO_SEL_SHIFT
161#define MPC8xxx_PORBMSR_HA MPC85xx_PORBMSR_HA
162#define MPC8xxx_PORBMSR_HA_SHIFT MPC85xx_PORBMSR_HA_SHIFT
163#elif defined(CONFIG_MPC86xx)
164#define MPC8xxx_DEVDISR_PCIE1 MPC86xx_DEVDISR_PCIEX1
165#define MPC8xxx_DEVDISR_PCIE2 MPC86xx_DEVDISR_PCIEX2
166#define MPC8xxx_DEVDISR_PCIE3 0 /* 8641 doesn't have PCIe3 */
167#define MPC8xxx_PORDEVSR_IO_SEL MPC8641_PORDEVSR_IO_SEL
168#define MPC8xxx_PORDEVSR_IO_SEL_SHIFT MPC8641_PORDEVSR_IO_SEL_SHIFT
169#define MPC8xxx_PORBMSR_HA MPC8641_PORBMSR_HA
170#define MPC8xxx_PORBMSR_HA_SHIFT MPC8641_PORBMSR_HA_SHIFT
171#endif
172
Peter Tyser1c2b3292008-12-17 16:36:23 -0600173void pci_init_board(void)
174{
175 struct pci_controller *hose;
176 volatile ccsr_fsl_pci_t *pci;
177 int width;
178 int host;
Peter Tyser75379822009-05-22 10:26:35 -0500179#if defined(CONFIG_MPC85xx)
Peter Tyser1c2b3292008-12-17 16:36:23 -0600180 volatile ccsr_gur_t *gur = (void *)(CONFIG_SYS_MPC85xx_GUTS_ADDR);
Peter Tyser75379822009-05-22 10:26:35 -0500181#elif defined(CONFIG_MPC86xx)
182 immap_t *immap = (immap_t *)CONFIG_SYS_IMMR;
183 volatile ccsr_gur_t *gur = &immap->im_gur;
184#endif
Peter Tyser1c2b3292008-12-17 16:36:23 -0600185 uint devdisr = gur->devdisr;
Peter Tyser75379822009-05-22 10:26:35 -0500186 uint io_sel = (gur->pordevsr & MPC8xxx_PORDEVSR_IO_SEL) >>
187 MPC8xxx_PORDEVSR_IO_SEL_SHIFT;
188 uint host_agent = (gur->porbmsr & MPC8xxx_PORBMSR_HA) >>
189 MPC8xxx_PORBMSR_HA_SHIFT;
Peter Tyser1c2b3292008-12-17 16:36:23 -0600190 struct pci_region *r;
191
Peter Tyser59b5fdf2008-12-01 13:47:13 -0600192#ifdef CONFIG_PCI1
193 uint pci_spd_norm = (gur->pordevsr & MPC85xx_PORDEVSR_PCI1_SPD);
194 uint pci_32 = gur->pordevsr & MPC85xx_PORDEVSR_PCI1_PCI32;
195 uint pci_arb = gur->pordevsr & MPC85xx_PORDEVSR_PCI1_ARB;
196 uint pcix = gur->pordevsr & MPC85xx_PORDEVSR_PCI1;
197 uint freq = CONFIG_SYS_CLK_FREQ / 1000 / 1000;
198
199 width = 0; /* Silence compiler warning... */
200 io_sel &= 0xf; /* Silence compiler warning... */
201 pci = (ccsr_fsl_pci_t *) CONFIG_SYS_PCI1_ADDR;
202 hose = &pci1_hose;
203 host = host_agent_cfg[host_agent].pci_host[0];
204 r = hose->regions;
205
206
207 if (!(devdisr & MPC85xx_DEVDISR_PCI1)) {
208 printf("\n PCI1: %d bit %s, %s %d MHz, %s, %s\n",
209 pci_32 ? 32 : 64,
210 pcix ? "PCIX" : "PCI",
211 pci_spd_norm ? ">=" : "<=",
212 pcix ? freq * 2 : freq,
213 host ? "host" : "agent",
214 pci_arb ? "arbiter" : "external-arbiter");
215
216 /* inbound */
217 r += fsl_pci_setup_inbound_windows(r);
218
219 /* outbound memory */
220 pci_set_region(r++,
221 CONFIG_SYS_PCI1_MEM_BASE,
222 CONFIG_SYS_PCI1_MEM_PHYS,
223 CONFIG_SYS_PCI1_MEM_SIZE,
224 PCI_REGION_MEM);
225
226 /* outbound io */
227 pci_set_region(r++,
228 CONFIG_SYS_PCI1_IO_BASE,
229 CONFIG_SYS_PCI1_IO_PHYS,
230 CONFIG_SYS_PCI1_IO_SIZE,
231 PCI_REGION_IO);
232
233 hose->region_count = r - hose->regions;
Peter Tyser1c2b3292008-12-17 16:36:23 -0600234
Peter Tyser59b5fdf2008-12-01 13:47:13 -0600235 hose->first_busno = first_free_busno;
236 pci_setup_indirect(hose, (int)&pci->cfg_addr,
237 (int)&pci->cfg_data);
238
239 fsl_pci_init(hose);
240
Peter Tyser3a65cba2008-12-23 16:32:01 -0600241 /* Unlock inbound PCI configuration cycles */
242 if (!host)
243 fsl_pci_config_unlock(hose);
244
Peter Tyserf3c970c2008-12-23 16:32:00 -0600245 first_free_busno = hose->last_busno + 1;
Peter Tyser59b5fdf2008-12-01 13:47:13 -0600246 printf(" PCI1 on bus %02x - %02x\n",
247 hose->first_busno, hose->last_busno);
248 } else {
249 printf(" PCI1: disabled\n");
250 }
251#elif defined CONFIG_MPC8548
252 /* PCI1 not present on MPC8572 */
253 gur->devdisr |= MPC85xx_DEVDISR_PCI1; /* disable */
254#endif
Peter Tyser1c2b3292008-12-17 16:36:23 -0600255#ifdef CONFIG_PCIE1
256 pci = (ccsr_fsl_pci_t *) CONFIG_SYS_PCIE1_ADDR;
257 hose = &pcie1_hose;
258 host = host_agent_cfg[host_agent].pcie_root[0];
259 width = io_port_cfg[io_sel].pcie_width[0];
260 r = hose->regions;
261
Peter Tyser75379822009-05-22 10:26:35 -0500262 if (width && !(devdisr & MPC8xxx_DEVDISR_PCIE1)) {
Peter Tyser1c2b3292008-12-17 16:36:23 -0600263 printf("\n PCIE1 connected as %s (x%d)",
264 host ? "Root Complex" : "End Point", width);
265 if (pci->pme_msg_det) {
266 pci->pme_msg_det = 0xffffffff;
267 debug(" with errors. Clearing. Now 0x%08x",
268 pci->pme_msg_det);
269 }
270 printf("\n");
271
272 /* inbound */
273 r += fsl_pci_setup_inbound_windows(r);
274
275 /* outbound memory */
276 pci_set_region(r++,
277 CONFIG_SYS_PCIE1_MEM_BASE,
278 CONFIG_SYS_PCIE1_MEM_PHYS,
279 CONFIG_SYS_PCIE1_MEM_SIZE,
280 PCI_REGION_MEM);
281
282 /* outbound io */
283 pci_set_region(r++,
284 CONFIG_SYS_PCIE1_IO_BASE,
285 CONFIG_SYS_PCIE1_IO_PHYS,
286 CONFIG_SYS_PCIE1_IO_SIZE,
287 PCI_REGION_IO);
288
289 hose->region_count = r - hose->regions;
290
291 hose->first_busno = first_free_busno;
292 pci_setup_indirect(hose, (int)&pci->cfg_addr,
293 (int) &pci->cfg_data);
294
295 fsl_pci_init(hose);
296
Peter Tyser2143be82008-10-29 12:39:27 -0500297 /* Unlock inbound PCI configuration cycles */
298 if (!host)
299 fsl_pci_config_unlock(hose);
300
Peter Tyser59b5fdf2008-12-01 13:47:13 -0600301 first_free_busno = hose->last_busno + 1;
Peter Tyser1c2b3292008-12-17 16:36:23 -0600302 printf(" PCIE1 on bus %02x - %02x\n",
303 hose->first_busno, hose->last_busno);
304 }
305#else
Peter Tyser75379822009-05-22 10:26:35 -0500306 gur->devdisr |= MPC8xxx_DEVDISR_PCIE1; /* disable */
Peter Tyser1c2b3292008-12-17 16:36:23 -0600307#endif /* CONFIG_PCIE1 */
308
309#ifdef CONFIG_PCIE2
310 pci = (ccsr_fsl_pci_t *) CONFIG_SYS_PCIE2_ADDR;
311 hose = &pcie2_hose;
312 host = host_agent_cfg[host_agent].pcie_root[1];
313 width = io_port_cfg[io_sel].pcie_width[1];
314 r = hose->regions;
315
Peter Tyser75379822009-05-22 10:26:35 -0500316 if (width && !(devdisr & MPC8xxx_DEVDISR_PCIE2)) {
Peter Tyser1c2b3292008-12-17 16:36:23 -0600317 printf("\n PCIE2 connected as %s (x%d)",
318 host ? "Root Complex" : "End Point", width);
319 if (pci->pme_msg_det) {
320 pci->pme_msg_det = 0xffffffff;
321 debug(" with errors. Clearing. Now 0x%08x",
322 pci->pme_msg_det);
323 }
324 printf("\n");
325
326 /* inbound */
327 r += fsl_pci_setup_inbound_windows(r);
328
329 /* outbound memory */
330 pci_set_region(r++,
331 CONFIG_SYS_PCIE2_MEM_BASE,
332 CONFIG_SYS_PCIE2_MEM_PHYS,
333 CONFIG_SYS_PCIE2_MEM_SIZE,
334 PCI_REGION_MEM);
335
336 /* outbound io */
337 pci_set_region(r++,
338 CONFIG_SYS_PCIE2_IO_BASE,
339 CONFIG_SYS_PCIE2_IO_PHYS,
340 CONFIG_SYS_PCIE2_IO_SIZE,
341 PCI_REGION_IO);
342
343 hose->region_count = r - hose->regions;
344
345 hose->first_busno = first_free_busno;
346 pci_setup_indirect(hose, (int)&pci->cfg_addr,
347 (int)&pci->cfg_data);
348
349 fsl_pci_init(hose);
Peter Tyser2143be82008-10-29 12:39:27 -0500350
351 /* Unlock inbound PCI configuration cycles */
352 if (!host)
353 fsl_pci_config_unlock(hose);
354
Peter Tyserf3c970c2008-12-23 16:32:00 -0600355 first_free_busno = hose->last_busno + 1;
Peter Tyser1c2b3292008-12-17 16:36:23 -0600356 printf(" PCIE2 on bus %02x - %02x\n",
357 hose->first_busno, hose->last_busno);
Peter Tyser1c2b3292008-12-17 16:36:23 -0600358 }
359#else
Peter Tyser75379822009-05-22 10:26:35 -0500360 gur->devdisr |= MPC8xxx_DEVDISR_PCIE2; /* disable */
Peter Tyser1c2b3292008-12-17 16:36:23 -0600361#endif /* CONFIG_PCIE2 */
362
363#ifdef CONFIG_PCIE3
364 pci = (ccsr_fsl_pci_t *) CONFIG_SYS_PCIE3_ADDR;
365 hose = &pcie3_hose;
366 host = host_agent_cfg[host_agent].pcie_root[2];
367 width = io_port_cfg[io_sel].pcie_width[2];
368 r = hose->regions;
369
Peter Tyser75379822009-05-22 10:26:35 -0500370 if (width && !(devdisr & MPC8xxx_DEVDISR_PCIE3)) {
Peter Tyser1c2b3292008-12-17 16:36:23 -0600371 printf("\n PCIE3 connected as %s (x%d)",
372 host ? "Root Complex" : "End Point", width);
373 if (pci->pme_msg_det) {
374 pci->pme_msg_det = 0xffffffff;
375 debug(" with errors. Clearing. Now 0x%08x",
376 pci->pme_msg_det);
377 }
378 printf("\n");
379
380 /* inbound */
381 r += fsl_pci_setup_inbound_windows(r);
382
383 /* outbound memory */
384 pci_set_region(r++,
385 CONFIG_SYS_PCIE3_MEM_BASE,
386 CONFIG_SYS_PCIE3_MEM_PHYS,
387 CONFIG_SYS_PCIE3_MEM_SIZE,
388 PCI_REGION_MEM);
389
390 /* outbound io */
391 pci_set_region(r++,
392 CONFIG_SYS_PCIE3_IO_BASE,
393 CONFIG_SYS_PCIE3_IO_PHYS,
394 CONFIG_SYS_PCIE3_IO_SIZE,
395 PCI_REGION_IO);
396
397 hose->region_count = r - hose->regions;
398
399 hose->first_busno = first_free_busno;
400 pci_setup_indirect(hose, (int)&pci->cfg_addr,
401 (int)&pci->cfg_data);
402
403 fsl_pci_init(hose);
Peter Tyser2143be82008-10-29 12:39:27 -0500404
405 /* Unlock inbound PCI configuration cycles */
406 if (!host)
407 fsl_pci_config_unlock(hose);
408
Peter Tyserf3c970c2008-12-23 16:32:00 -0600409 first_free_busno = hose->last_busno + 1;
Peter Tyser1c2b3292008-12-17 16:36:23 -0600410 printf(" PCIE3 on bus %02x - %02x\n",
411 hose->first_busno, hose->last_busno);
412 }
413#else
Peter Tyser75379822009-05-22 10:26:35 -0500414 gur->devdisr |= MPC8xxx_DEVDISR_PCIE3; /* disable */
Peter Tyser1c2b3292008-12-17 16:36:23 -0600415#endif /* CONFIG_PCIE3 */
416}
417
418#if defined(CONFIG_OF_BOARD_SETUP)
Peter Tyser1c2b3292008-12-17 16:36:23 -0600419void ft_board_pci_setup(void *blob, bd_t *bd)
420{
Peter Tyser59b5fdf2008-12-01 13:47:13 -0600421 /* TODO - make node name (eg pci0) dynamic */
422#ifdef CONFIG_PCI1
423 ft_fsl_pci_setup(blob, "pci0", &pci1_hose);
424#endif
Peter Tyser1c2b3292008-12-17 16:36:23 -0600425#ifdef CONFIG_PCIE1
426 ft_fsl_pci_setup(blob, "pci2", &pcie1_hose);
427#endif
428#ifdef CONFIG_PCIE2
429 ft_fsl_pci_setup(blob, "pci1", &pcie2_hose);
430#endif
431#ifdef CONFIG_PCIE3
432 ft_fsl_pci_setup(blob, "pci0", &pcie3_hose);
433#endif
434}
435#endif /* CONFIG_OF_BOARD_SETUP */