]>
Commit | Line | Data |
---|---|---|
692519b1 | 1 | /* |
c9240981 | 2 | * (C) Copyright 2006 - 2007 |
692519b1 RJ |
3 | * Wolfgang Denk, DENX Software Engineering, wd@denx.de. |
4 | * | |
5 | * Copyright (c) 2005 Cisco Systems. All rights reserved. | |
6 | * Roland Dreier <rolandd@cisco.com> | |
7 | * | |
8 | * See file CREDITS for list of people who contributed to this | |
9 | * project. | |
10 | * | |
11 | * This program is free software; you can redistribute it and/or | |
12 | * modify it under the terms of the GNU General Public License as | |
13 | * published by the Free Software Foundation; either version 2 of | |
14 | * the License, or (at your option) any later version. | |
15 | * | |
16 | * This program is distributed in the hope that it will be useful, | |
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
19 | * GNU General Public License for more details. | |
20 | * | |
21 | */ | |
22 | ||
23 | #include <asm/processor.h> | |
24 | #include <asm-ppc/io.h> | |
25 | #include <ppc4xx.h> | |
26 | #include <common.h> | |
27 | #include <pci.h> | |
28 | ||
5fb692ca | 29 | #if defined(CONFIG_440SPE) && defined(CONFIG_PCI) |
692519b1 | 30 | |
5fb692ca | 31 | #include "440spe_pcie.h" |
692519b1 RJ |
32 | |
33 | enum { | |
34 | PTYPE_ENDPOINT = 0x0, | |
35 | PTYPE_LEGACY_ENDPOINT = 0x1, | |
36 | PTYPE_ROOT_PORT = 0x4, | |
37 | ||
38 | LNKW_X1 = 0x1, | |
39 | LNKW_X4 = 0x4, | |
40 | LNKW_X8 = 0x8 | |
41 | }; | |
42 | ||
15ee4734 | 43 | static void pcie_dmer_disable(void) |
c9240981 | 44 | { |
15ee4734 GB |
45 | mtdcr (DCRN_PEGPL_CFG(DCRN_PCIE0_BASE), |
46 | mfdcr (DCRN_PEGPL_CFG(DCRN_PCIE0_BASE)) | GPL_DMER_MASK_DISA); | |
47 | mtdcr (DCRN_PEGPL_CFG(DCRN_PCIE1_BASE), | |
48 | mfdcr (DCRN_PEGPL_CFG(DCRN_PCIE1_BASE)) | GPL_DMER_MASK_DISA); | |
49 | mtdcr (DCRN_PEGPL_CFG(DCRN_PCIE2_BASE), | |
50 | mfdcr (DCRN_PEGPL_CFG(DCRN_PCIE2_BASE)) | GPL_DMER_MASK_DISA); | |
c9240981 GB |
51 | } |
52 | ||
15ee4734 | 53 | static void pcie_dmer_enable(void) |
c9240981 | 54 | { |
15ee4734 GB |
55 | mtdcr (DCRN_PEGPL_CFG (DCRN_PCIE0_BASE), |
56 | mfdcr (DCRN_PEGPL_CFG(DCRN_PCIE0_BASE)) & ~GPL_DMER_MASK_DISA); | |
57 | mtdcr (DCRN_PEGPL_CFG (DCRN_PCIE1_BASE), | |
58 | mfdcr (DCRN_PEGPL_CFG(DCRN_PCIE1_BASE)) & ~GPL_DMER_MASK_DISA); | |
59 | mtdcr (DCRN_PEGPL_CFG (DCRN_PCIE2_BASE), | |
60 | mfdcr (DCRN_PEGPL_CFG(DCRN_PCIE2_BASE)) & ~GPL_DMER_MASK_DISA); | |
c9240981 GB |
61 | } |
62 | ||
63 | ||
692519b1 RJ |
64 | static int pcie_read_config(struct pci_controller *hose, unsigned int devfn, |
65 | int offset, int len, u32 *val) { | |
66 | ||
67 | *val = 0; | |
68 | /* | |
69 | * 440SPE implements only one function per port | |
70 | */ | |
71 | if (!((PCI_FUNC(devfn) == 0) && (PCI_DEV(devfn) == 1))) | |
72 | return 0; | |
73 | ||
74 | devfn = PCI_BDF(0,0,0); | |
75 | offset += devfn << 4; | |
76 | ||
15ee4734 GB |
77 | /* |
78 | * Reading from configuration space of non-existing device can | |
79 | * generate transaction errors. For the read duration we suppress | |
80 | * assertion of machine check exceptions to avoid those. | |
81 | */ | |
82 | pcie_dmer_disable (); | |
83 | ||
692519b1 RJ |
84 | switch (len) { |
85 | case 1: | |
15ee4734 | 86 | *val = in_8(hose->cfg_data + offset); |
692519b1 RJ |
87 | break; |
88 | case 2: | |
15ee4734 | 89 | *val = in_le16((u16 *)(hose->cfg_data + offset)); |
692519b1 RJ |
90 | break; |
91 | default: | |
15ee4734 | 92 | *val = in_le32((u32*)(hose->cfg_data + offset)); |
692519b1 RJ |
93 | break; |
94 | } | |
15ee4734 GB |
95 | |
96 | pcie_dmer_enable (); | |
97 | ||
692519b1 RJ |
98 | return 0; |
99 | } | |
100 | ||
101 | static int pcie_write_config(struct pci_controller *hose, unsigned int devfn, | |
102 | int offset, int len, u32 val) { | |
103 | ||
104 | /* | |
105 | * 440SPE implements only one function per port | |
106 | */ | |
107 | if (!((PCI_FUNC(devfn) == 0) && (PCI_DEV(devfn) == 1))) | |
108 | return 0; | |
109 | ||
110 | devfn = PCI_BDF(0,0,0); | |
111 | offset += devfn << 4; | |
112 | ||
15ee4734 GB |
113 | /* |
114 | * Suppress MCK exceptions, similar to pcie_read_config() | |
115 | */ | |
116 | pcie_dmer_disable (); | |
117 | ||
692519b1 RJ |
118 | switch (len) { |
119 | case 1: | |
120 | out_8(hose->cfg_data + offset, val); | |
121 | break; | |
122 | case 2: | |
123 | out_le16((u16 *)(hose->cfg_data + offset), val); | |
124 | break; | |
125 | default: | |
126 | out_le32((u32 *)(hose->cfg_data + offset), val); | |
127 | break; | |
128 | } | |
15ee4734 GB |
129 | |
130 | pcie_dmer_enable (); | |
131 | ||
692519b1 RJ |
132 | return 0; |
133 | } | |
134 | ||
135 | int pcie_read_config_byte(struct pci_controller *hose,pci_dev_t dev,int offset,u8 *val) | |
136 | { | |
137 | u32 v; | |
138 | int rv; | |
139 | ||
140 | rv = pcie_read_config(hose, dev, offset, 1, &v); | |
141 | *val = (u8)v; | |
142 | return rv; | |
143 | } | |
144 | ||
145 | int pcie_read_config_word(struct pci_controller *hose,pci_dev_t dev,int offset,u16 *val) | |
146 | { | |
147 | u32 v; | |
148 | int rv; | |
149 | ||
150 | rv = pcie_read_config(hose, dev, offset, 2, &v); | |
151 | *val = (u16)v; | |
152 | return rv; | |
153 | } | |
154 | ||
155 | int pcie_read_config_dword(struct pci_controller *hose,pci_dev_t dev,int offset,u32 *val) | |
156 | { | |
157 | u32 v; | |
158 | int rv; | |
159 | ||
160 | rv = pcie_read_config(hose, dev, offset, 3, &v); | |
161 | *val = (u32)v; | |
162 | return rv; | |
163 | } | |
164 | ||
165 | int pcie_write_config_byte(struct pci_controller *hose,pci_dev_t dev,int offset,u8 val) | |
166 | { | |
167 | return pcie_write_config(hose,(u32)dev,offset,1,val); | |
168 | } | |
169 | ||
170 | int pcie_write_config_word(struct pci_controller *hose,pci_dev_t dev,int offset,u16 val) | |
171 | { | |
172 | return pcie_write_config(hose,(u32)dev,offset,2,(u32 )val); | |
173 | } | |
174 | ||
175 | int pcie_write_config_dword(struct pci_controller *hose,pci_dev_t dev,int offset,u32 val) | |
176 | { | |
177 | return pcie_write_config(hose,(u32)dev,offset,3,(u32 )val); | |
178 | } | |
179 | ||
180 | static void ppc440spe_setup_utl(u32 port) { | |
181 | ||
182 | volatile void *utl_base = NULL; | |
183 | ||
184 | /* | |
185 | * Map UTL registers | |
186 | */ | |
187 | switch (port) { | |
188 | case 0: | |
36b904a7 RJ |
189 | mtdcr(DCRN_PEGPL_REGBAH(PCIE0), 0x0000000c); |
190 | mtdcr(DCRN_PEGPL_REGBAL(PCIE0), 0x20000000); | |
191 | mtdcr(DCRN_PEGPL_REGMSK(PCIE0), 0x00007001); | |
692519b1 | 192 | mtdcr(DCRN_PEGPL_SPECIAL(PCIE0), 0x68782800); |
692519b1 RJ |
193 | break; |
194 | ||
195 | case 1: | |
36b904a7 RJ |
196 | mtdcr(DCRN_PEGPL_REGBAH(PCIE1), 0x0000000c); |
197 | mtdcr(DCRN_PEGPL_REGBAL(PCIE1), 0x20001000); | |
198 | mtdcr(DCRN_PEGPL_REGMSK(PCIE1), 0x00007001); | |
692519b1 | 199 | mtdcr(DCRN_PEGPL_SPECIAL(PCIE1), 0x68782800); |
692519b1 RJ |
200 | break; |
201 | ||
202 | case 2: | |
36b904a7 RJ |
203 | mtdcr(DCRN_PEGPL_REGBAH(PCIE2), 0x0000000c); |
204 | mtdcr(DCRN_PEGPL_REGBAL(PCIE2), 0x20002000); | |
205 | mtdcr(DCRN_PEGPL_REGMSK(PCIE2), 0x00007001); | |
692519b1 | 206 | mtdcr(DCRN_PEGPL_SPECIAL(PCIE2), 0x68782800); |
692519b1 RJ |
207 | break; |
208 | } | |
36b904a7 | 209 | utl_base = (unsigned int *)(CFG_PCIE_BASE + 0x1000 * port); |
16850919 | 210 | |
692519b1 RJ |
211 | /* |
212 | * Set buffer allocations and then assert VRB and TXE. | |
213 | */ | |
214 | out_be32(utl_base + PEUTL_OUTTR, 0x08000000); | |
215 | out_be32(utl_base + PEUTL_INTR, 0x02000000); | |
216 | out_be32(utl_base + PEUTL_OPDBSZ, 0x10000000); | |
217 | out_be32(utl_base + PEUTL_PBBSZ, 0x53000000); | |
218 | out_be32(utl_base + PEUTL_IPHBSZ, 0x08000000); | |
219 | out_be32(utl_base + PEUTL_IPDBSZ, 0x10000000); | |
220 | out_be32(utl_base + PEUTL_RCIRQEN, 0x00f00000); | |
36b904a7 | 221 | out_be32(utl_base + PEUTL_PCTL, 0x80800066); |
692519b1 RJ |
222 | } |
223 | ||
224 | static int check_error(void) | |
225 | { | |
226 | u32 valPE0, valPE1, valPE2; | |
227 | int err = 0; | |
228 | ||
229 | /* SDR0_PEGPLLLCT1 reset */ | |
230 | if (!(valPE0 = SDR_READ(PESDR0_PLLLCT1) & 0x01000000)) { | |
231 | printf("PCIE: SDR0_PEGPLLLCT1 reset error 0x%x\n", valPE0); | |
232 | } | |
233 | ||
234 | valPE0 = SDR_READ(PESDR0_RCSSET); | |
235 | valPE1 = SDR_READ(PESDR1_RCSSET); | |
236 | valPE2 = SDR_READ(PESDR2_RCSSET); | |
237 | ||
238 | /* SDR0_PExRCSSET rstgu */ | |
239 | if (!(valPE0 & 0x01000000) || | |
240 | !(valPE1 & 0x01000000) || | |
241 | !(valPE2 & 0x01000000)) { | |
242 | printf("PCIE: SDR0_PExRCSSET rstgu error\n"); | |
243 | err = -1; | |
244 | } | |
245 | ||
246 | /* SDR0_PExRCSSET rstdl */ | |
247 | if (!(valPE0 & 0x00010000) || | |
248 | !(valPE1 & 0x00010000) || | |
249 | !(valPE2 & 0x00010000)) { | |
250 | printf("PCIE: SDR0_PExRCSSET rstdl error\n"); | |
251 | err = -1; | |
252 | } | |
253 | ||
254 | /* SDR0_PExRCSSET rstpyn */ | |
255 | if ((valPE0 & 0x00001000) || | |
256 | (valPE1 & 0x00001000) || | |
257 | (valPE2 & 0x00001000)) { | |
258 | printf("PCIE: SDR0_PExRCSSET rstpyn error\n"); | |
259 | err = -1; | |
260 | } | |
261 | ||
262 | /* SDR0_PExRCSSET hldplb */ | |
263 | if ((valPE0 & 0x10000000) || | |
264 | (valPE1 & 0x10000000) || | |
265 | (valPE2 & 0x10000000)) { | |
266 | printf("PCIE: SDR0_PExRCSSET hldplb error\n"); | |
267 | err = -1; | |
268 | } | |
269 | ||
270 | /* SDR0_PExRCSSET rdy */ | |
271 | if ((valPE0 & 0x00100000) || | |
272 | (valPE1 & 0x00100000) || | |
273 | (valPE2 & 0x00100000)) { | |
274 | printf("PCIE: SDR0_PExRCSSET rdy error\n"); | |
275 | err = -1; | |
276 | } | |
277 | ||
278 | /* SDR0_PExRCSSET shutdown */ | |
279 | if ((valPE0 & 0x00000100) || | |
280 | (valPE1 & 0x00000100) || | |
281 | (valPE2 & 0x00000100)) { | |
282 | printf("PCIE: SDR0_PExRCSSET shutdown error\n"); | |
283 | err = -1; | |
284 | } | |
285 | return err; | |
286 | } | |
287 | ||
288 | /* | |
289 | * Initialize PCI Express core | |
290 | */ | |
291 | int ppc440spe_init_pcie(void) | |
292 | { | |
293 | int time_out = 20; | |
294 | ||
295 | /* Set PLL clock receiver to LVPECL */ | |
296 | SDR_WRITE(PESDR0_PLLLCT1, SDR_READ(PESDR0_PLLLCT1) | 1 << 28); | |
297 | ||
298 | if (check_error()) | |
299 | return -1; | |
300 | ||
301 | if (!(SDR_READ(PESDR0_PLLLCT2) & 0x10000)) | |
302 | { | |
303 | printf("PCIE: PESDR_PLLCT2 resistance calibration failed (0x%08x)\n", | |
304 | SDR_READ(PESDR0_PLLLCT2)); | |
305 | return -1; | |
306 | } | |
307 | /* De-assert reset of PCIe PLL, wait for lock */ | |
308 | SDR_WRITE(PESDR0_PLLLCT1, SDR_READ(PESDR0_PLLLCT1) & ~(1 << 24)); | |
309 | udelay(3); | |
310 | ||
2b393b0f | 311 | while (time_out) { |
692519b1 RJ |
312 | if (!(SDR_READ(PESDR0_PLLLCT3) & 0x10000000)) { |
313 | time_out--; | |
314 | udelay(1); | |
315 | } else | |
316 | break; | |
317 | } | |
318 | if (!time_out) { | |
319 | printf("PCIE: VCO output not locked\n"); | |
320 | return -1; | |
321 | } | |
322 | return 0; | |
323 | } | |
324 | ||
2b393b0f SR |
325 | /* |
326 | * Yucca board as End point and root point setup | |
327 | * and | |
328 | * testing inbound and out bound windows | |
329 | * | |
330 | * YUCCA board can be plugged into another yucca board or you can get PCI-E | |
331 | * cable which can be used to setup loop back from one port to another port. | |
332 | * Please rememeber that unless there is a endpoint plugged in to root port it | |
333 | * will not initialize. It is the same in case of endpoint , unless there is | |
334 | * root port attached it will not initialize. | |
335 | * | |
336 | * In this release of software all the PCI-E ports are configured as either | |
337 | * endpoint or rootpoint.In future we will have support for selective ports | |
338 | * setup as endpoint and root point in single board. | |
339 | * | |
340 | * Once your board came up as root point , you can verify by reading | |
341 | * /proc/bus/pci/devices. Where you can see the configuration registers | |
342 | * of end point device attached to the port. | |
343 | * | |
344 | * Enpoint cofiguration can be verified by connecting Yucca board to any | |
345 | * host or another yucca board. Then try to scan the device. In case of | |
346 | * linux use "lspci" or appripriate os command. | |
347 | * | |
348 | * How do I verify the inbound and out bound windows ?(yucca to yucca) | |
349 | * in this configuration inbound and outbound windows are setup to access | |
350 | * sram memroy area. SRAM is at 0x4 0000 0000 , on PLB bus. This address | |
351 | * is mapped at 0x90000000. From u-boot prompt write data 0xb000 0000, | |
352 | * This is waere your POM(PLB out bound memory window) mapped. then | |
353 | * read the data from other yucca board's u-boot prompt at address | |
354 | * 0x9000 0000(SRAM). Data should match. | |
355 | * In case of inbound , write data to u-boot command prompt at 0xb000 0000 | |
356 | * which is mapped to 0x4 0000 0000. Now on rootpoint yucca u-boot prompt check | |
357 | * data at 0x9000 0000(SRAM).Data should match. | |
358 | */ | |
692519b1 RJ |
359 | int ppc440spe_init_pcie_rootport(int port) |
360 | { | |
361 | static int core_init; | |
362 | volatile u32 val = 0; | |
363 | int attempts; | |
364 | ||
365 | if (!core_init) { | |
366 | ++core_init; | |
367 | if (ppc440spe_init_pcie()) | |
368 | return -1; | |
369 | } | |
370 | ||
371 | /* | |
372 | * Initialize various parts of the PCI Express core for our port: | |
373 | * | |
374 | * - Set as a root port and enable max width | |
375 | * (PXIE0 -> X8, PCIE1 and PCIE2 -> X4). | |
376 | * - Set up UTL configuration. | |
377 | * - Increase SERDES drive strength to levels suggested by AMCC. | |
378 | * - De-assert RSTPYN, RSTDL and RSTGU. | |
379 | * | |
380 | * NOTICE for revB chip: PESDRn_UTLSET2 is not set - we leave it with | |
381 | * default setting 0x11310000. The register has new fields, | |
382 | * PESDRn_UTLSET2[LKINE] in particular: clearing it leads to PCIE core | |
383 | * hang. | |
384 | */ | |
385 | switch (port) { | |
386 | case 0: | |
387 | SDR_WRITE(PESDR0_DLPSET, 1 << 24 | PTYPE_ROOT_PORT << 20 | LNKW_X8 << 12); | |
388 | ||
389 | SDR_WRITE(PESDR0_UTLSET1, 0x21222222); | |
390 | if (!ppc440spe_revB()) | |
391 | SDR_WRITE(PESDR0_UTLSET2, 0x11000000); | |
392 | SDR_WRITE(PESDR0_HSSL0SET1, 0x35000000); | |
393 | SDR_WRITE(PESDR0_HSSL1SET1, 0x35000000); | |
394 | SDR_WRITE(PESDR0_HSSL2SET1, 0x35000000); | |
395 | SDR_WRITE(PESDR0_HSSL3SET1, 0x35000000); | |
396 | SDR_WRITE(PESDR0_HSSL4SET1, 0x35000000); | |
397 | SDR_WRITE(PESDR0_HSSL5SET1, 0x35000000); | |
398 | SDR_WRITE(PESDR0_HSSL6SET1, 0x35000000); | |
399 | SDR_WRITE(PESDR0_HSSL7SET1, 0x35000000); | |
400 | SDR_WRITE(PESDR0_RCSSET, | |
2b393b0f | 401 | (SDR_READ(PESDR0_RCSSET) & ~(1 << 24 | 1 << 16)) | 1 << 12); |
692519b1 RJ |
402 | break; |
403 | ||
404 | case 1: | |
405 | SDR_WRITE(PESDR1_DLPSET, 1 << 24 | PTYPE_ROOT_PORT << 20 | LNKW_X4 << 12); | |
406 | SDR_WRITE(PESDR1_UTLSET1, 0x21222222); | |
407 | if (!ppc440spe_revB()) | |
408 | SDR_WRITE(PESDR1_UTLSET2, 0x11000000); | |
409 | SDR_WRITE(PESDR1_HSSL0SET1, 0x35000000); | |
410 | SDR_WRITE(PESDR1_HSSL1SET1, 0x35000000); | |
411 | SDR_WRITE(PESDR1_HSSL2SET1, 0x35000000); | |
412 | SDR_WRITE(PESDR1_HSSL3SET1, 0x35000000); | |
413 | SDR_WRITE(PESDR1_RCSSET, | |
2b393b0f | 414 | (SDR_READ(PESDR1_RCSSET) & ~(1 << 24 | 1 << 16)) | 1 << 12); |
692519b1 RJ |
415 | break; |
416 | ||
417 | case 2: | |
418 | SDR_WRITE(PESDR2_DLPSET, 1 << 24 | PTYPE_ROOT_PORT << 20 | LNKW_X4 << 12); | |
419 | SDR_WRITE(PESDR2_UTLSET1, 0x21222222); | |
420 | if (!ppc440spe_revB()) | |
421 | SDR_WRITE(PESDR2_UTLSET2, 0x11000000); | |
422 | SDR_WRITE(PESDR2_HSSL0SET1, 0x35000000); | |
423 | SDR_WRITE(PESDR2_HSSL1SET1, 0x35000000); | |
424 | SDR_WRITE(PESDR2_HSSL2SET1, 0x35000000); | |
425 | SDR_WRITE(PESDR2_HSSL3SET1, 0x35000000); | |
2b393b0f SR |
426 | SDR_WRITE(PESDR2_RCSSET, |
427 | (SDR_READ(PESDR2_RCSSET) & ~(1 << 24 | 1 << 16)) | 1 << 12); | |
428 | break; | |
429 | } | |
430 | /* | |
431 | * Notice: the following delay has critical impact on device | |
432 | * initialization - if too short (<50ms) the link doesn't get up. | |
433 | */ | |
434 | mdelay(100); | |
435 | ||
436 | switch (port) { | |
437 | case 0: | |
438 | val = SDR_READ(PESDR0_RCSSTS); | |
439 | break; | |
440 | case 1: | |
441 | val = SDR_READ(PESDR1_RCSSTS); | |
442 | break; | |
443 | case 2: | |
444 | val = SDR_READ(PESDR2_RCSSTS); | |
445 | break; | |
446 | } | |
447 | ||
448 | if (val & (1 << 20)) { | |
449 | printf("PCIE%d: PGRST failed %08x\n", port, val); | |
450 | return -1; | |
451 | } | |
452 | ||
453 | /* | |
454 | * Verify link is up | |
455 | */ | |
456 | val = 0; | |
457 | switch (port) { | |
458 | case 0: | |
459 | val = SDR_READ(PESDR0_LOOP); | |
460 | break; | |
461 | case 1: | |
462 | val = SDR_READ(PESDR1_LOOP); | |
463 | break; | |
464 | case 2: | |
465 | val = SDR_READ(PESDR2_LOOP); | |
466 | break; | |
467 | } | |
468 | if (!(val & 0x00001000)) { | |
469 | printf("PCIE%d: link is not up.\n", port); | |
470 | return -1; | |
471 | } | |
472 | ||
473 | /* | |
474 | * Setup UTL registers - but only on revA! | |
475 | * We use default settings for revB chip. | |
476 | */ | |
477 | if (!ppc440spe_revB()) | |
478 | ppc440spe_setup_utl(port); | |
479 | ||
480 | /* | |
481 | * We map PCI Express configuration access into the 512MB regions | |
482 | * | |
483 | * NOTICE: revB is very strict about PLB real addressess and ranges to | |
484 | * be mapped for config space; it seems to only work with d_nnnn_nnnn | |
485 | * range (hangs the core upon config transaction attempts when set | |
486 | * otherwise) while revA uses c_nnnn_nnnn. | |
487 | * | |
488 | * For revA: | |
489 | * PCIE0: 0xc_4000_0000 | |
490 | * PCIE1: 0xc_8000_0000 | |
491 | * PCIE2: 0xc_c000_0000 | |
492 | * | |
493 | * For revB: | |
494 | * PCIE0: 0xd_0000_0000 | |
495 | * PCIE1: 0xd_2000_0000 | |
496 | * PCIE2: 0xd_4000_0000 | |
497 | */ | |
498 | ||
499 | switch (port) { | |
500 | case 0: | |
501 | if (ppc440spe_revB()) { | |
502 | mtdcr(DCRN_PEGPL_CFGBAH(PCIE0), 0x0000000d); | |
503 | mtdcr(DCRN_PEGPL_CFGBAL(PCIE0), 0x00000000); | |
504 | } else { | |
505 | /* revA */ | |
506 | mtdcr(DCRN_PEGPL_CFGBAH(PCIE0), 0x0000000c); | |
507 | mtdcr(DCRN_PEGPL_CFGBAL(PCIE0), 0x40000000); | |
508 | } | |
509 | mtdcr(DCRN_PEGPL_CFGMSK(PCIE0), 0xe0000001); /* 512MB region, valid */ | |
510 | break; | |
511 | ||
512 | case 1: | |
513 | if (ppc440spe_revB()) { | |
514 | mtdcr(DCRN_PEGPL_CFGBAH(PCIE1), 0x0000000d); | |
515 | mtdcr(DCRN_PEGPL_CFGBAL(PCIE1), 0x20000000); | |
516 | } else { | |
517 | mtdcr(DCRN_PEGPL_CFGBAH(PCIE1), 0x0000000c); | |
518 | mtdcr(DCRN_PEGPL_CFGBAL(PCIE1), 0x80000000); | |
519 | } | |
520 | mtdcr(DCRN_PEGPL_CFGMSK(PCIE1), 0xe0000001); /* 512MB region, valid */ | |
521 | break; | |
522 | ||
523 | case 2: | |
524 | if (ppc440spe_revB()) { | |
525 | mtdcr(DCRN_PEGPL_CFGBAH(PCIE2), 0x0000000d); | |
526 | mtdcr(DCRN_PEGPL_CFGBAL(PCIE2), 0x40000000); | |
527 | } else { | |
528 | mtdcr(DCRN_PEGPL_CFGBAH(PCIE2), 0x0000000c); | |
529 | mtdcr(DCRN_PEGPL_CFGBAL(PCIE2), 0xc0000000); | |
530 | } | |
531 | mtdcr(DCRN_PEGPL_CFGMSK(PCIE2), 0xe0000001); /* 512MB region, valid */ | |
532 | break; | |
533 | } | |
534 | ||
535 | /* | |
536 | * Check for VC0 active and assert RDY. | |
537 | */ | |
538 | attempts = 10; | |
539 | switch (port) { | |
540 | case 0: | |
541 | while(!(SDR_READ(PESDR0_RCSSTS) & (1 << 16))) { | |
542 | if (!(attempts--)) { | |
543 | printf("PCIE0: VC0 not active\n"); | |
544 | return -1; | |
545 | } | |
546 | mdelay(1000); | |
547 | } | |
548 | SDR_WRITE(PESDR0_RCSSET, SDR_READ(PESDR0_RCSSET) | 1 << 20); | |
549 | break; | |
550 | case 1: | |
551 | while(!(SDR_READ(PESDR1_RCSSTS) & (1 << 16))) { | |
552 | if (!(attempts--)) { | |
553 | printf("PCIE1: VC0 not active\n"); | |
554 | return -1; | |
555 | } | |
556 | mdelay(1000); | |
557 | } | |
558 | ||
559 | SDR_WRITE(PESDR1_RCSSET, SDR_READ(PESDR1_RCSSET) | 1 << 20); | |
560 | break; | |
561 | case 2: | |
562 | while(!(SDR_READ(PESDR2_RCSSTS) & (1 << 16))) { | |
563 | if (!(attempts--)) { | |
564 | printf("PCIE2: VC0 not active\n"); | |
565 | return -1; | |
566 | } | |
567 | mdelay(1000); | |
568 | } | |
569 | ||
570 | SDR_WRITE(PESDR2_RCSSET, SDR_READ(PESDR2_RCSSET) | 1 << 20); | |
571 | break; | |
572 | } | |
573 | mdelay(100); | |
574 | ||
575 | return 0; | |
576 | } | |
577 | ||
578 | int ppc440spe_init_pcie_endport(int port) | |
579 | { | |
580 | static int core_init; | |
581 | volatile u32 val = 0; | |
582 | int attempts; | |
583 | ||
584 | if (!core_init) { | |
585 | ++core_init; | |
586 | if (ppc440spe_init_pcie()) | |
587 | return -1; | |
588 | } | |
589 | ||
590 | /* | |
591 | * Initialize various parts of the PCI Express core for our port: | |
592 | * | |
593 | * - Set as a end port and enable max width | |
594 | * (PXIE0 -> X8, PCIE1 and PCIE2 -> X4). | |
595 | * - Set up UTL configuration. | |
596 | * - Increase SERDES drive strength to levels suggested by AMCC. | |
597 | * - De-assert RSTPYN, RSTDL and RSTGU. | |
598 | * | |
599 | * NOTICE for revB chip: PESDRn_UTLSET2 is not set - we leave it with | |
600 | * default setting 0x11310000. The register has new fields, | |
601 | * PESDRn_UTLSET2[LKINE] in particular: clearing it leads to PCIE core | |
602 | * hang. | |
603 | */ | |
604 | switch (port) { | |
605 | case 0: | |
606 | SDR_WRITE(PESDR0_DLPSET, 1 << 24 | PTYPE_LEGACY_ENDPOINT << 20 | LNKW_X8 << 12); | |
607 | ||
608 | SDR_WRITE(PESDR0_UTLSET1, 0x20222222); | |
609 | if (!ppc440spe_revB()) | |
610 | SDR_WRITE(PESDR0_UTLSET2, 0x11000000); | |
611 | SDR_WRITE(PESDR0_HSSL0SET1, 0x35000000); | |
612 | SDR_WRITE(PESDR0_HSSL1SET1, 0x35000000); | |
613 | SDR_WRITE(PESDR0_HSSL2SET1, 0x35000000); | |
614 | SDR_WRITE(PESDR0_HSSL3SET1, 0x35000000); | |
615 | SDR_WRITE(PESDR0_HSSL4SET1, 0x35000000); | |
616 | SDR_WRITE(PESDR0_HSSL5SET1, 0x35000000); | |
617 | SDR_WRITE(PESDR0_HSSL6SET1, 0x35000000); | |
618 | SDR_WRITE(PESDR0_HSSL7SET1, 0x35000000); | |
619 | SDR_WRITE(PESDR0_RCSSET, | |
620 | (SDR_READ(PESDR0_RCSSET) & ~(1 << 24 | 1 << 16)) | 1 << 12); | |
621 | break; | |
622 | ||
623 | case 1: | |
624 | SDR_WRITE(PESDR1_DLPSET, 1 << 24 | PTYPE_LEGACY_ENDPOINT << 20 | LNKW_X4 << 12); | |
625 | SDR_WRITE(PESDR1_UTLSET1, 0x20222222); | |
626 | if (!ppc440spe_revB()) | |
627 | SDR_WRITE(PESDR1_UTLSET2, 0x11000000); | |
628 | SDR_WRITE(PESDR1_HSSL0SET1, 0x35000000); | |
629 | SDR_WRITE(PESDR1_HSSL1SET1, 0x35000000); | |
630 | SDR_WRITE(PESDR1_HSSL2SET1, 0x35000000); | |
631 | SDR_WRITE(PESDR1_HSSL3SET1, 0x35000000); | |
632 | SDR_WRITE(PESDR1_RCSSET, | |
633 | (SDR_READ(PESDR1_RCSSET) & ~(1 << 24 | 1 << 16)) | 1 << 12); | |
634 | break; | |
635 | ||
636 | case 2: | |
637 | SDR_WRITE(PESDR2_DLPSET, 1 << 24 | PTYPE_LEGACY_ENDPOINT << 20 | LNKW_X4 << 12); | |
638 | SDR_WRITE(PESDR2_UTLSET1, 0x20222222); | |
639 | if (!ppc440spe_revB()) | |
640 | SDR_WRITE(PESDR2_UTLSET2, 0x11000000); | |
641 | SDR_WRITE(PESDR2_HSSL0SET1, 0x35000000); | |
642 | SDR_WRITE(PESDR2_HSSL1SET1, 0x35000000); | |
643 | SDR_WRITE(PESDR2_HSSL2SET1, 0x35000000); | |
644 | SDR_WRITE(PESDR2_HSSL3SET1, 0x35000000); | |
692519b1 RJ |
645 | SDR_WRITE(PESDR2_RCSSET, |
646 | (SDR_READ(PESDR2_RCSSET) & ~(1 << 24 | 1 << 16)) | 1 << 12); | |
647 | break; | |
648 | } | |
649 | /* | |
650 | * Notice: the following delay has critical impact on device | |
651 | * initialization - if too short (<50ms) the link doesn't get up. | |
652 | */ | |
653 | mdelay(100); | |
654 | ||
655 | switch (port) { | |
656 | case 0: val = SDR_READ(PESDR0_RCSSTS); break; | |
657 | case 1: val = SDR_READ(PESDR1_RCSSTS); break; | |
658 | case 2: val = SDR_READ(PESDR2_RCSSTS); break; | |
659 | } | |
660 | ||
661 | if (val & (1 << 20)) { | |
662 | printf("PCIE%d: PGRST failed %08x\n", port, val); | |
663 | return -1; | |
664 | } | |
665 | ||
666 | /* | |
667 | * Verify link is up | |
668 | */ | |
669 | val = 0; | |
670 | switch (port) | |
671 | { | |
672 | case 0: | |
673 | val = SDR_READ(PESDR0_LOOP); | |
674 | break; | |
675 | case 1: | |
676 | val = SDR_READ(PESDR1_LOOP); | |
677 | break; | |
678 | case 2: | |
679 | val = SDR_READ(PESDR2_LOOP); | |
680 | break; | |
681 | } | |
682 | if (!(val & 0x00001000)) { | |
683 | printf("PCIE%d: link is not up.\n", port); | |
684 | return -1; | |
685 | } | |
686 | ||
687 | /* | |
688 | * Setup UTL registers - but only on revA! | |
689 | * We use default settings for revB chip. | |
690 | */ | |
691 | if (!ppc440spe_revB()) | |
692 | ppc440spe_setup_utl(port); | |
693 | ||
694 | /* | |
695 | * We map PCI Express configuration access into the 512MB regions | |
696 | * | |
697 | * NOTICE: revB is very strict about PLB real addressess and ranges to | |
698 | * be mapped for config space; it seems to only work with d_nnnn_nnnn | |
699 | * range (hangs the core upon config transaction attempts when set | |
700 | * otherwise) while revA uses c_nnnn_nnnn. | |
701 | * | |
702 | * For revA: | |
703 | * PCIE0: 0xc_4000_0000 | |
704 | * PCIE1: 0xc_8000_0000 | |
705 | * PCIE2: 0xc_c000_0000 | |
706 | * | |
707 | * For revB: | |
708 | * PCIE0: 0xd_0000_0000 | |
709 | * PCIE1: 0xd_2000_0000 | |
710 | * PCIE2: 0xd_4000_0000 | |
711 | */ | |
712 | switch (port) { | |
713 | case 0: | |
714 | if (ppc440spe_revB()) { | |
715 | mtdcr(DCRN_PEGPL_CFGBAH(PCIE0), 0x0000000d); | |
716 | mtdcr(DCRN_PEGPL_CFGBAL(PCIE0), 0x00000000); | |
717 | } else { | |
718 | /* revA */ | |
719 | mtdcr(DCRN_PEGPL_CFGBAH(PCIE0), 0x0000000c); | |
720 | mtdcr(DCRN_PEGPL_CFGBAL(PCIE0), 0x40000000); | |
721 | } | |
722 | mtdcr(DCRN_PEGPL_CFGMSK(PCIE0), 0xe0000001); /* 512MB region, valid */ | |
723 | break; | |
724 | ||
725 | case 1: | |
726 | if (ppc440spe_revB()) { | |
727 | mtdcr(DCRN_PEGPL_CFGBAH(PCIE1), 0x0000000d); | |
728 | mtdcr(DCRN_PEGPL_CFGBAL(PCIE1), 0x20000000); | |
729 | } else { | |
730 | mtdcr(DCRN_PEGPL_CFGBAH(PCIE1), 0x0000000c); | |
731 | mtdcr(DCRN_PEGPL_CFGBAL(PCIE1), 0x80000000); | |
732 | } | |
733 | mtdcr(DCRN_PEGPL_CFGMSK(PCIE1), 0xe0000001); /* 512MB region, valid */ | |
734 | break; | |
735 | ||
736 | case 2: | |
737 | if (ppc440spe_revB()) { | |
738 | mtdcr(DCRN_PEGPL_CFGBAH(PCIE2), 0x0000000d); | |
739 | mtdcr(DCRN_PEGPL_CFGBAL(PCIE2), 0x40000000); | |
740 | } else { | |
741 | mtdcr(DCRN_PEGPL_CFGBAH(PCIE2), 0x0000000c); | |
742 | mtdcr(DCRN_PEGPL_CFGBAL(PCIE2), 0xc0000000); | |
743 | } | |
744 | mtdcr(DCRN_PEGPL_CFGMSK(PCIE2), 0xe0000001); /* 512MB region, valid */ | |
745 | break; | |
746 | } | |
747 | ||
748 | /* | |
749 | * Check for VC0 active and assert RDY. | |
750 | */ | |
751 | attempts = 10; | |
752 | switch (port) { | |
753 | case 0: | |
754 | while(!(SDR_READ(PESDR0_RCSSTS) & (1 << 16))) { | |
755 | if (!(attempts--)) { | |
756 | printf("PCIE0: VC0 not active\n"); | |
757 | return -1; | |
758 | } | |
759 | mdelay(1000); | |
760 | } | |
761 | SDR_WRITE(PESDR0_RCSSET, SDR_READ(PESDR0_RCSSET) | 1 << 20); | |
762 | break; | |
763 | case 1: | |
764 | while(!(SDR_READ(PESDR1_RCSSTS) & (1 << 16))) { | |
765 | if (!(attempts--)) { | |
766 | printf("PCIE1: VC0 not active\n"); | |
767 | return -1; | |
768 | } | |
769 | mdelay(1000); | |
770 | } | |
771 | ||
772 | SDR_WRITE(PESDR1_RCSSET, SDR_READ(PESDR1_RCSSET) | 1 << 20); | |
773 | break; | |
774 | case 2: | |
775 | while(!(SDR_READ(PESDR2_RCSSTS) & (1 << 16))) { | |
776 | if (!(attempts--)) { | |
777 | printf("PCIE2: VC0 not active\n"); | |
778 | return -1; | |
779 | } | |
780 | mdelay(1000); | |
781 | } | |
782 | ||
783 | SDR_WRITE(PESDR2_RCSSET, SDR_READ(PESDR2_RCSSET) | 1 << 20); | |
784 | break; | |
785 | } | |
786 | mdelay(100); | |
787 | ||
788 | return 0; | |
789 | } | |
790 | ||
2b393b0f | 791 | void ppc440spe_setup_pcie_rootpoint(struct pci_controller *hose, int port) |
692519b1 RJ |
792 | { |
793 | volatile void *mbase = NULL; | |
2b393b0f | 794 | volatile void *rmbase = NULL; |
692519b1 RJ |
795 | |
796 | pci_set_ops(hose, | |
2b393b0f SR |
797 | pcie_read_config_byte, |
798 | pcie_read_config_word, | |
799 | pcie_read_config_dword, | |
800 | pcie_write_config_byte, | |
801 | pcie_write_config_word, | |
802 | pcie_write_config_dword); | |
803 | ||
804 | switch (port) { | |
692519b1 RJ |
805 | case 0: |
806 | mbase = (u32 *)CFG_PCIE0_XCFGBASE; | |
2b393b0f | 807 | rmbase = (u32 *)CFG_PCIE0_CFGBASE; |
692519b1 RJ |
808 | hose->cfg_data = (u8 *)CFG_PCIE0_CFGBASE; |
809 | break; | |
810 | case 1: | |
811 | mbase = (u32 *)CFG_PCIE1_XCFGBASE; | |
2b393b0f | 812 | rmbase = (u32 *)CFG_PCIE1_CFGBASE; |
692519b1 RJ |
813 | hose->cfg_data = (u8 *)CFG_PCIE1_CFGBASE; |
814 | break; | |
815 | case 2: | |
816 | mbase = (u32 *)CFG_PCIE2_XCFGBASE; | |
2b393b0f | 817 | rmbase = (u32 *)CFG_PCIE2_CFGBASE; |
692519b1 RJ |
818 | hose->cfg_data = (u8 *)CFG_PCIE2_CFGBASE; |
819 | break; | |
820 | } | |
821 | ||
822 | /* | |
823 | * Set bus numbers on our root port | |
824 | */ | |
dec99558 RJ |
825 | if (ppc440spe_revB()) { |
826 | out_8((u8 *)mbase + PCI_PRIMARY_BUS, 0); | |
827 | out_8((u8 *)mbase + PCI_SECONDARY_BUS, 1); | |
828 | out_8((u8 *)mbase + PCI_SUBORDINATE_BUS, 1); | |
829 | } else { | |
830 | out_8((u8 *)mbase + PCI_PRIMARY_BUS, 0); | |
831 | out_8((u8 *)mbase + PCI_SECONDARY_BUS, 0); | |
832 | } | |
692519b1 RJ |
833 | |
834 | /* | |
835 | * Set up outbound translation to hose->mem_space from PLB | |
836 | * addresses at an offset of 0xd_0000_0000. We set the low | |
837 | * bits of the mask to 11 to turn off splitting into 8 | |
838 | * subregions and to enable the outbound translation. | |
839 | */ | |
840 | out_le32(mbase + PECFG_POM0LAH, 0x00000000); | |
2b393b0f | 841 | out_le32(mbase + PECFG_POM0LAL, 0x00000000); |
692519b1 RJ |
842 | |
843 | switch (port) { | |
844 | case 0: | |
845 | mtdcr(DCRN_PEGPL_OMR1BAH(PCIE0), 0x0000000d); | |
846 | mtdcr(DCRN_PEGPL_OMR1BAL(PCIE0), CFG_PCIE_MEMBASE + | |
847 | port * CFG_PCIE_MEMSIZE); | |
848 | mtdcr(DCRN_PEGPL_OMR1MSKH(PCIE0), 0x7fffffff); | |
849 | mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE0), | |
850 | ~(CFG_PCIE_MEMSIZE - 1) | 3); | |
851 | break; | |
852 | case 1: | |
853 | mtdcr(DCRN_PEGPL_OMR1BAH(PCIE1), 0x0000000d); | |
854 | mtdcr(DCRN_PEGPL_OMR1BAL(PCIE1), (CFG_PCIE_MEMBASE + | |
855 | port * CFG_PCIE_MEMSIZE)); | |
856 | mtdcr(DCRN_PEGPL_OMR1MSKH(PCIE1), 0x7fffffff); | |
857 | mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE1), | |
858 | ~(CFG_PCIE_MEMSIZE - 1) | 3); | |
859 | break; | |
860 | case 2: | |
861 | mtdcr(DCRN_PEGPL_OMR1BAH(PCIE2), 0x0000000d); | |
862 | mtdcr(DCRN_PEGPL_OMR1BAL(PCIE2), (CFG_PCIE_MEMBASE + | |
863 | port * CFG_PCIE_MEMSIZE)); | |
864 | mtdcr(DCRN_PEGPL_OMR1MSKH(PCIE2), 0x7fffffff); | |
865 | mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE2), | |
866 | ~(CFG_PCIE_MEMSIZE - 1) | 3); | |
867 | break; | |
868 | } | |
869 | ||
870 | /* Set up 16GB inbound memory window at 0 */ | |
871 | out_le32(mbase + PCI_BASE_ADDRESS_0, 0); | |
872 | out_le32(mbase + PCI_BASE_ADDRESS_1, 0); | |
873 | out_le32(mbase + PECFG_BAR0HMPA, 0x7fffffc); | |
874 | out_le32(mbase + PECFG_BAR0LMPA, 0); | |
2b393b0f SR |
875 | |
876 | out_le32(mbase + PECFG_PIM01SAH, 0xffff0000); | |
877 | out_le32(mbase + PECFG_PIM01SAL, 0x00000000); | |
692519b1 RJ |
878 | out_le32(mbase + PECFG_PIM0LAL, 0); |
879 | out_le32(mbase + PECFG_PIM0LAH, 0); | |
2b393b0f SR |
880 | out_le32(mbase + PECFG_PIM1LAL, 0x00000000); |
881 | out_le32(mbase + PECFG_PIM1LAH, 0x00000004); | |
882 | out_le32(mbase + PECFG_PIMEN, 0x1); | |
883 | ||
884 | /* Enable I/O, Mem, and Busmaster cycles */ | |
885 | out_le16((u16 *)(mbase + PCI_COMMAND), | |
886 | in_le16((u16 *)(mbase + PCI_COMMAND)) | | |
887 | PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); | |
888 | printf("PCIE:%d successfully set as rootpoint\n",port); | |
889 | } | |
890 | ||
891 | int ppc440spe_setup_pcie_endpoint(struct pci_controller *hose, int port) | |
892 | { | |
893 | volatile void *mbase = NULL; | |
894 | int attempts = 0; | |
895 | ||
896 | pci_set_ops(hose, | |
897 | pcie_read_config_byte, | |
898 | pcie_read_config_word, | |
899 | pcie_read_config_dword, | |
900 | pcie_write_config_byte, | |
901 | pcie_write_config_word, | |
902 | pcie_write_config_dword); | |
903 | ||
904 | switch (port) { | |
905 | case 0: | |
906 | mbase = (u32 *)CFG_PCIE0_XCFGBASE; | |
907 | hose->cfg_data = (u8 *)CFG_PCIE0_CFGBASE; | |
908 | break; | |
909 | case 1: | |
910 | mbase = (u32 *)CFG_PCIE1_XCFGBASE; | |
911 | hose->cfg_data = (u8 *)CFG_PCIE1_CFGBASE; | |
912 | break; | |
913 | case 2: | |
914 | mbase = (u32 *)CFG_PCIE2_XCFGBASE; | |
915 | hose->cfg_data = (u8 *)CFG_PCIE2_CFGBASE; | |
916 | break; | |
917 | } | |
918 | ||
919 | /* | |
920 | * Set up outbound translation to hose->mem_space from PLB | |
921 | * addresses at an offset of 0xd_0000_0000. We set the low | |
922 | * bits of the mask to 11 to turn off splitting into 8 | |
923 | * subregions and to enable the outbound translation. | |
924 | */ | |
925 | out_le32(mbase + PECFG_POM0LAH, 0x00001ff8); | |
926 | out_le32(mbase + PECFG_POM0LAL, 0x00001000); | |
927 | ||
928 | switch (port) { | |
929 | case 0: | |
930 | mtdcr(DCRN_PEGPL_OMR1BAH(PCIE0), 0x0000000d); | |
931 | mtdcr(DCRN_PEGPL_OMR1BAL(PCIE0), CFG_PCIE_MEMBASE + | |
932 | port * CFG_PCIE_MEMSIZE); | |
933 | mtdcr(DCRN_PEGPL_OMR1MSKH(PCIE0), 0x7fffffff); | |
934 | mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE0), | |
935 | ~(CFG_PCIE_MEMSIZE - 1) | 3); | |
936 | break; | |
937 | case 1: | |
938 | mtdcr(DCRN_PEGPL_OMR1BAH(PCIE1), 0x0000000d); | |
939 | mtdcr(DCRN_PEGPL_OMR1BAL(PCIE1), (CFG_PCIE_MEMBASE + | |
940 | port * CFG_PCIE_MEMSIZE)); | |
941 | mtdcr(DCRN_PEGPL_OMR1MSKH(PCIE1), 0x7fffffff); | |
942 | mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE1), | |
943 | ~(CFG_PCIE_MEMSIZE - 1) | 3); | |
944 | break; | |
945 | case 2: | |
946 | mtdcr(DCRN_PEGPL_OMR1BAH(PCIE2), 0x0000000d); | |
947 | mtdcr(DCRN_PEGPL_OMR1BAL(PCIE2), (CFG_PCIE_MEMBASE + | |
948 | port * CFG_PCIE_MEMSIZE)); | |
949 | mtdcr(DCRN_PEGPL_OMR1MSKH(PCIE2), 0x7fffffff); | |
950 | mtdcr(DCRN_PEGPL_OMR1MSKL(PCIE2), | |
951 | ~(CFG_PCIE_MEMSIZE - 1) | 3); | |
952 | break; | |
953 | } | |
954 | ||
955 | /* Set up 16GB inbound memory window at 0 */ | |
956 | out_le32(mbase + PCI_BASE_ADDRESS_0, 0); | |
957 | out_le32(mbase + PCI_BASE_ADDRESS_1, 0); | |
958 | out_le32(mbase + PECFG_BAR0HMPA, 0x7fffffc); | |
959 | out_le32(mbase + PECFG_BAR0LMPA, 0); | |
960 | out_le32(mbase + PECFG_PIM0LAL, 0x00000000); | |
961 | out_le32(mbase + PECFG_PIM0LAH, 0x00000004); /* pointing to SRAM */ | |
692519b1 RJ |
962 | out_le32(mbase + PECFG_PIMEN, 0x1); |
963 | ||
964 | /* Enable I/O, Mem, and Busmaster cycles */ | |
965 | out_le16((u16 *)(mbase + PCI_COMMAND), | |
966 | in_le16((u16 *)(mbase + PCI_COMMAND)) | | |
967 | PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); | |
2b393b0f SR |
968 | out_le16(mbase + 0x200,0xcaad); /* Setting vendor ID */ |
969 | out_le16(mbase + 0x202,0xfeed); /* Setting device ID */ | |
970 | attempts = 10; | |
971 | switch (port) { | |
972 | case 0: | |
973 | while (!(SDR_READ(PESDR0_RCSSTS) & (1 << 8))) { | |
974 | if (!(attempts--)) { | |
975 | printf("PCIE0: BMEN is not active\n"); | |
976 | return -1; | |
977 | } | |
978 | mdelay(1000); | |
979 | } | |
980 | break; | |
981 | case 1: | |
982 | while (!(SDR_READ(PESDR1_RCSSTS) & (1 << 8))) { | |
983 | if (!(attempts--)) { | |
984 | printf("PCIE1: BMEN is not active\n"); | |
985 | return -1; | |
986 | } | |
987 | mdelay(1000); | |
988 | } | |
989 | break; | |
990 | case 2: | |
991 | while (!(SDR_READ(PESDR2_RCSSTS) & (1 << 8))) { | |
992 | if (!(attempts--)) { | |
993 | printf("PCIE2: BMEN is not active\n"); | |
994 | return -1; | |
995 | } | |
996 | mdelay(1000); | |
997 | } | |
998 | break; | |
999 | } | |
1000 | printf("PCIE:%d successfully set as endpoint\n",port); | |
1001 | ||
1002 | return 0; | |
692519b1 | 1003 | } |
5fb692ca | 1004 | #endif /* CONFIG_440SPE && CONFIG_PCI */ |