2 * Support for indirect PCI bridges.
4 * Copyright (C) 1998 Gabriel Paubert.
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
12 #include <linux/kernel.h>
13 #include <linux/pci.h>
14 #include <linux/delay.h>
15 #include <linux/string.h>
16 #include <linux/init.h>
17 #include <linux/bootmem.h>
21 #include <asm/pci-bridge.h>
22 #include <asm/machdep.h>
24 #ifdef CONFIG_PPC_INDIRECT_PCI_BE
25 #define PCI_CFG_OUT out_be32
27 #define PCI_CFG_OUT out_le32
31 indirect_read_config(struct pci_bus
*bus
, unsigned int devfn
, int offset
,
34 struct pci_controller
*hose
= bus
->sysdata
;
35 volatile void __iomem
*cfg_data
;
38 if (ppc_md
.pci_exclude_device
)
39 if (ppc_md
.pci_exclude_device(bus
->number
, devfn
))
40 return PCIBIOS_DEVICE_NOT_FOUND
;
42 if (hose
->set_cfg_type
)
43 if (bus
->number
!= hose
->first_busno
)
46 PCI_CFG_OUT(hose
->cfg_addr
,
47 (0x80000000 | ((bus
->number
- hose
->bus_offset
) << 16)
48 | (devfn
<< 8) | ((offset
& 0xfc) | cfg_type
)));
51 * Note: the caller has already checked that offset is
52 * suitably aligned and that len is 1, 2 or 4.
54 cfg_data
= hose
->cfg_data
+ (offset
& 3);
57 *val
= in_8(cfg_data
);
60 *val
= in_le16(cfg_data
);
63 *val
= in_le32(cfg_data
);
66 return PCIBIOS_SUCCESSFUL
;
70 indirect_write_config(struct pci_bus
*bus
, unsigned int devfn
, int offset
,
73 struct pci_controller
*hose
= bus
->sysdata
;
74 volatile void __iomem
*cfg_data
;
77 if (ppc_md
.pci_exclude_device
)
78 if (ppc_md
.pci_exclude_device(bus
->number
, devfn
))
79 return PCIBIOS_DEVICE_NOT_FOUND
;
81 if (hose
->set_cfg_type
)
82 if (bus
->number
!= hose
->first_busno
)
85 PCI_CFG_OUT(hose
->cfg_addr
,
86 (0x80000000 | ((bus
->number
- hose
->bus_offset
) << 16)
87 | (devfn
<< 8) | ((offset
& 0xfc) | cfg_type
)));
90 * Note: the caller has already checked that offset is
91 * suitably aligned and that len is 1, 2 or 4.
93 cfg_data
= hose
->cfg_data
+ (offset
& 3);
99 out_le16(cfg_data
, val
);
102 out_le32(cfg_data
, val
);
105 return PCIBIOS_SUCCESSFUL
;
108 static struct pci_ops indirect_pci_ops
=
110 indirect_read_config
,
111 indirect_write_config
115 setup_indirect_pci_nomap(struct pci_controller
* hose
, void __iomem
* cfg_addr
,
116 void __iomem
* cfg_data
)
118 hose
->cfg_addr
= cfg_addr
;
119 hose
->cfg_data
= cfg_data
;
120 hose
->ops
= &indirect_pci_ops
;
124 setup_indirect_pci(struct pci_controller
* hose
, u32 cfg_addr
, u32 cfg_data
)
126 unsigned long base
= cfg_addr
& PAGE_MASK
;
127 void __iomem
*mbase
, *addr
, *data
;
129 mbase
= ioremap(base
, PAGE_SIZE
);
130 addr
= mbase
+ (cfg_addr
& ~PAGE_MASK
);
131 if ((cfg_data
& PAGE_MASK
) != base
)
132 mbase
= ioremap(cfg_data
& PAGE_MASK
, PAGE_SIZE
);
133 data
= mbase
+ (cfg_data
& ~PAGE_MASK
);
134 setup_indirect_pci_nomap(hose
, addr
, data
);