2 * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
3 * Andreas Heppel <aheppel@sysgo.de>
5 * (C) Copyright 2002, 2003
6 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
8 * See file CREDITS for list of people who contributed to this
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.
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.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
35 #include <asm/processor.h>
41 #define debug(x...) printf(x)
46 #define PCI_HOSE_OP(rw, size, type) \
47 int pci_hose_##rw##_config_##size(struct pci_controller *hose, \
49 int offset, type value) \
51 return hose->rw##_##size(hose, dev, offset, value); \
54 PCI_HOSE_OP(read
, byte
, u8
*)
55 PCI_HOSE_OP(read
, word
, u16
*)
56 PCI_HOSE_OP(read
, dword
, u32
*)
57 PCI_HOSE_OP(write
, byte
, u8
)
58 PCI_HOSE_OP(write
, word
, u16
)
59 PCI_HOSE_OP(write
, dword
, u32
)
62 #define PCI_OP(rw, size, type, error_code) \
63 int pci_##rw##_config_##size(pci_dev_t dev, int offset, type value) \
65 struct pci_controller *hose = pci_bus_to_hose(PCI_BUS(dev)); \
73 return pci_hose_##rw##_config_##size(hose, dev, offset, value); \
76 PCI_OP(read
, byte
, u8
*, *value
= 0xff)
77 PCI_OP(read
, word
, u16
*, *value
= 0xffff)
78 PCI_OP(read
, dword
, u32
*, *value
= 0xffffffff)
79 PCI_OP(write
, byte
, u8
, )
80 PCI_OP(write
, word
, u16
, )
81 PCI_OP(write
, dword
, u32
, )
82 #endif /* CONFIG_IXP425 */
84 #define PCI_READ_VIA_DWORD_OP(size, type, off_mask) \
85 int pci_hose_read_config_##size##_via_dword(struct pci_controller *hose,\
87 int offset, type val) \
91 if (pci_hose_read_config_dword(hose, dev, offset & 0xfc, &val32) < 0)\
94 *val = (val32 >> ((offset & (int)off_mask) * 8)); \
99 #define PCI_WRITE_VIA_DWORD_OP(size, type, off_mask, val_mask) \
100 int pci_hose_write_config_##size##_via_dword(struct pci_controller *hose,\
102 int offset, type val) \
104 u32 val32, mask, ldata, shift; \
106 if (pci_hose_read_config_dword(hose, dev, offset & 0xfc, &val32) < 0)\
109 shift = ((offset & (int)off_mask) * 8); \
110 ldata = (((unsigned long)val) & val_mask) << shift; \
111 mask = val_mask << shift; \
112 val32 = (val32 & ~mask) | ldata; \
114 if (pci_hose_write_config_dword(hose, dev, offset & 0xfc, val32) < 0)\
120 PCI_READ_VIA_DWORD_OP(byte
, u8
*, 0x03)
121 PCI_READ_VIA_DWORD_OP(word
, u16
*, 0x02)
122 PCI_WRITE_VIA_DWORD_OP(byte
, u8
, 0x03, 0x000000ff)
123 PCI_WRITE_VIA_DWORD_OP(word
, u16
, 0x02, 0x0000ffff)
129 static struct pci_controller
* hose_head
= NULL
;
131 void pci_register_hose(struct pci_controller
* hose
)
133 struct pci_controller
**phose
= &hose_head
;
136 phose
= &(*phose
)->next
;
143 struct pci_controller
*pci_bus_to_hose (int bus
)
145 struct pci_controller
*hose
;
147 for (hose
= hose_head
; hose
; hose
= hose
->next
)
148 if (bus
>= hose
->first_busno
&& bus
<= hose
->last_busno
)
150 #ifndef CONFIG_MARVELL
151 printf("pci_bus_to_hose() failed\n");
156 #ifndef CONFIG_IXP425
157 pci_dev_t
pci_find_devices(struct pci_device_id
*ids
, int index
)
159 struct pci_controller
* hose
;
163 int i
, bus
, found_multi
= 0;
165 for (hose
= hose_head
; hose
; hose
= hose
->next
)
167 #ifdef CFG_SCSI_SCAN_BUS_REVERSE
168 for (bus
= hose
->last_busno
; bus
>= hose
->first_busno
; bus
--)
170 for (bus
= hose
->first_busno
; bus
<= hose
->last_busno
; bus
++)
172 for (bdf
= PCI_BDF(bus
,0,0);
174 bdf
< PCI_BDF(bus
,PCI_MAX_PCI_DEVICES
-1,PCI_MAX_PCI_FUNCTIONS
-1);
176 bdf
< PCI_BDF(bus
+1,0,0);
178 bdf
+= PCI_BDF(0,0,1))
180 if (!PCI_FUNC(bdf
)) {
181 pci_read_config_byte(bdf
,
185 found_multi
= header_type
& 0x80;
191 pci_read_config_word(bdf
,
194 pci_read_config_word(bdf
,
198 for (i
=0; ids
[i
].vendor
!= 0; i
++)
199 if (vendor
== ids
[i
].vendor
&&
200 device
== ids
[i
].device
)
212 #endif /* CONFIG_IXP425 */
214 pci_dev_t
pci_find_device(unsigned int vendor
, unsigned int device
, int index
)
216 static struct pci_device_id ids
[2] = {{}, {0, 0}};
218 ids
[0].vendor
= vendor
;
219 ids
[0].device
= device
;
221 return pci_find_devices(ids
, index
);
228 unsigned long pci_hose_phys_to_bus (struct pci_controller
*hose
,
229 unsigned long phys_addr
,
232 struct pci_region
*res
;
233 unsigned long bus_addr
;
237 printf ("pci_hose_phys_to_bus: %s\n", "invalid hose");
241 for (i
= 0; i
< hose
->region_count
; i
++) {
242 res
= &hose
->regions
[i
];
244 if (((res
->flags
^ flags
) & PCI_REGION_TYPE
) != 0)
247 bus_addr
= phys_addr
- res
->phys_start
+ res
->bus_start
;
249 if (bus_addr
>= res
->bus_start
&&
250 bus_addr
< res
->bus_start
+ res
->size
) {
255 printf ("pci_hose_phys_to_bus: %s\n", "invalid physical address");
261 unsigned long pci_hose_bus_to_phys(struct pci_controller
* hose
,
262 unsigned long bus_addr
,
265 struct pci_region
*res
;
269 printf ("pci_hose_bus_to_phys: %s\n", "invalid hose");
273 for (i
= 0; i
< hose
->region_count
; i
++) {
274 res
= &hose
->regions
[i
];
276 if (((res
->flags
^ flags
) & PCI_REGION_TYPE
) != 0)
279 if (bus_addr
>= res
->bus_start
&&
280 bus_addr
< res
->bus_start
+ res
->size
) {
281 return bus_addr
- res
->bus_start
+ res
->phys_start
;
285 printf ("pci_hose_bus_to_phys: %s\n", "invalid physical address");
295 int pci_hose_config_device(struct pci_controller
*hose
,
299 unsigned long command
)
301 unsigned int bar_response
, bar_size
, bar_value
, old_command
;
303 int bar
, found_mem64
;
305 debug ("PCI Config: I/O=0x%lx, Memory=0x%lx, Command=0x%lx\n",
308 pci_hose_write_config_dword (hose
, dev
, PCI_COMMAND
, 0);
310 for (bar
= PCI_BASE_ADDRESS_0
; bar
< PCI_BASE_ADDRESS_5
; bar
+= 4) {
311 pci_hose_write_config_dword (hose
, dev
, bar
, 0xffffffff);
312 pci_hose_read_config_dword (hose
, dev
, bar
, &bar_response
);
319 /* Check the BAR type and set our address mask */
320 if (bar_response
& PCI_BASE_ADDRESS_SPACE
) {
321 bar_size
= ~(bar_response
& PCI_BASE_ADDRESS_IO_MASK
) + 1;
322 /* round up region base address to a multiple of size */
323 io
= ((io
- 1) | (bar_size
- 1)) + 1;
325 /* compute new region base address */
328 if ((bar_response
& PCI_BASE_ADDRESS_MEM_TYPE_MASK
) ==
329 PCI_BASE_ADDRESS_MEM_TYPE_64
)
332 bar_size
= ~(bar_response
& PCI_BASE_ADDRESS_MEM_MASK
) + 1;
334 /* round up region base address to multiple of size */
335 mem
= ((mem
- 1) | (bar_size
- 1)) + 1;
337 /* compute new region base address */
338 mem
= mem
+ bar_size
;
341 /* Write it out and update our limit */
342 pci_hose_write_config_dword (hose
, dev
, bar
, bar_value
);
346 pci_hose_write_config_dword (hose
, dev
, bar
, 0x00000000);
350 /* Configure Cache Line Size Register */
351 pci_hose_write_config_byte (hose
, dev
, PCI_CACHE_LINE_SIZE
, 0x08);
353 /* Configure Latency Timer */
354 pci_hose_write_config_byte (hose
, dev
, PCI_LATENCY_TIMER
, 0x80);
356 /* Disable interrupt line, if device says it wants to use interrupts */
357 pci_hose_read_config_byte (hose
, dev
, PCI_INTERRUPT_PIN
, &pin
);
359 pci_hose_write_config_byte (hose
, dev
, PCI_INTERRUPT_LINE
, 0xff);
362 pci_hose_read_config_dword (hose
, dev
, PCI_COMMAND
, &old_command
);
363 pci_hose_write_config_dword (hose
, dev
, PCI_COMMAND
,
364 (old_command
& 0xffff0000) | command
);
373 struct pci_config_table
*pci_find_config(struct pci_controller
*hose
,
374 unsigned short class,
381 struct pci_config_table
*table
;
383 for (table
= hose
->config_table
; table
&& table
->vendor
; table
++) {
384 if ((table
->vendor
== PCI_ANY_ID
|| table
->vendor
== vendor
) &&
385 (table
->device
== PCI_ANY_ID
|| table
->device
== device
) &&
386 (table
->class == PCI_ANY_ID
|| table
->class == class) &&
387 (table
->bus
== PCI_ANY_ID
|| table
->bus
== bus
) &&
388 (table
->dev
== PCI_ANY_ID
|| table
->dev
== dev
) &&
389 (table
->func
== PCI_ANY_ID
|| table
->func
== func
)) {
397 void pci_cfgfunc_config_device(struct pci_controller
*hose
,
399 struct pci_config_table
*entry
)
401 pci_hose_config_device(hose
, dev
, entry
->priv
[0], entry
->priv
[1], entry
->priv
[2]);
404 void pci_cfgfunc_do_nothing(struct pci_controller
*hose
,
405 pci_dev_t dev
, struct pci_config_table
*entry
)
413 /* HJF: Changed this to return int. I think this is required
414 * to get the correct result when scanning bridges
416 extern int pciauto_config_device(struct pci_controller
*hose
, pci_dev_t dev
);
417 extern void pciauto_config_init(struct pci_controller
*hose
);
419 int pci_hose_scan_bus(struct pci_controller
*hose
, int bus
)
421 unsigned int sub_bus
, found_multi
=0;
422 unsigned short vendor
, device
, class;
423 unsigned char header_type
;
424 struct pci_config_table
*cfg
;
429 for (dev
= PCI_BDF(bus
,0,0);
430 dev
< PCI_BDF(bus
,PCI_MAX_PCI_DEVICES
-1,PCI_MAX_PCI_FUNCTIONS
-1);
431 dev
+= PCI_BDF(0,0,1))
434 #ifndef CONFIG_MARVELL
435 /* Skip our host bridge */
436 if ( dev
== PCI_BDF(hose
->first_busno
,0,0) ) {
437 #if defined(CONFIG_PCI_CONFIG_HOST_BRIDGE) /* don't skip host bridge */
439 * Only skip hostbridge configuration if "pciconfighost" is not set
441 if (getenv("pciconfighost") == NULL
) {
442 continue; /* Skip our host bridge */
445 continue; /* Skip our host bridge */
448 #endif /* CONFIG_MARVELL */
449 if (PCI_FUNC(dev
) && !found_multi
)
452 pci_hose_read_config_byte(hose
, dev
, PCI_HEADER_TYPE
, &header_type
);
454 pci_hose_read_config_word(hose
, dev
, PCI_VENDOR_ID
, &vendor
);
456 if (vendor
!= 0xffff && vendor
!= 0x0000) {
459 found_multi
= header_type
& 0x80;
461 debug ("PCI Scan: Found Bus %d, Device %d, Function %d\n",
462 PCI_BUS(dev
), PCI_DEV(dev
), PCI_FUNC(dev
) );
464 pci_hose_read_config_word(hose
, dev
, PCI_DEVICE_ID
, &device
);
465 pci_hose_read_config_word(hose
, dev
, PCI_CLASS_DEVICE
, &class);
467 cfg
= pci_find_config(hose
, class, vendor
, device
,
468 PCI_BUS(dev
), PCI_DEV(dev
), PCI_FUNC(dev
));
470 cfg
->config_device(hose
, dev
, cfg
);
471 #ifdef CONFIG_PCI_PNP
473 int n
= pciauto_config_device(hose
, dev
);
475 sub_bus
= max(sub_bus
, n
);
479 hose
->fixup_irq(hose
, dev
);
481 #ifdef CONFIG_PCI_SCAN_SHOW
482 /* Skip our host bridge */
483 if ( dev
!= PCI_BDF(hose
->first_busno
,0,0) ) {
484 unsigned char int_line
;
486 pci_hose_read_config_byte(hose
, dev
, PCI_INTERRUPT_LINE
,
488 printf(" %02x %02x %04x %04x %04x %02x\n",
489 PCI_BUS(dev
), PCI_DEV(dev
), vendor
, device
, class,
499 int pci_hose_scan(struct pci_controller
*hose
)
501 #ifdef CONFIG_PCI_PNP
502 pciauto_config_init(hose
);
504 return pci_hose_scan_bus(hose
, hose
->first_busno
);
509 #if defined(CONFIG_PCI_BOOTDELAY)
513 /* wait "pcidelay" ms (if defined)... */
514 s
= getenv ("pcidelay");
516 int val
= simple_strtoul (s
, NULL
, 10);
517 for (i
=0; i
<val
; i
++)
520 #endif /* CONFIG_PCI_BOOTDELAY */
522 /* now call board specific pci_init()... */
526 #endif /* CONFIG_PCI */