diff options
Diffstat (limited to 'arch/powerpc/platforms/86xx/pci.c')
-rw-r--r-- | arch/powerpc/platforms/86xx/pci.c | 67 |
1 files changed, 50 insertions, 17 deletions
diff --git a/arch/powerpc/platforms/86xx/pci.c b/arch/powerpc/platforms/86xx/pci.c index 8235c562661f..73cd5b05a84e 100644 --- a/arch/powerpc/platforms/86xx/pci.c +++ b/arch/powerpc/platforms/86xx/pci.c | |||
@@ -122,7 +122,6 @@ static void __init | |||
122 | mpc86xx_setup_pcie(struct pci_controller *hose, u32 pcie_offset, u32 pcie_size) | 122 | mpc86xx_setup_pcie(struct pci_controller *hose, u32 pcie_offset, u32 pcie_size) |
123 | { | 123 | { |
124 | u16 cmd; | 124 | u16 cmd; |
125 | unsigned int temps; | ||
126 | 125 | ||
127 | DBG("PCIE host controller register offset 0x%08x, size 0x%08x.\n", | 126 | DBG("PCIE host controller register offset 0x%08x, size 0x%08x.\n", |
128 | pcie_offset, pcie_size); | 127 | pcie_offset, pcie_size); |
@@ -133,22 +132,49 @@ mpc86xx_setup_pcie(struct pci_controller *hose, u32 pcie_offset, u32 pcie_size) | |||
133 | early_write_config_word(hose, 0, 0, PCI_COMMAND, cmd); | 132 | early_write_config_word(hose, 0, 0, PCI_COMMAND, cmd); |
134 | 133 | ||
135 | early_write_config_byte(hose, 0, 0, PCI_LATENCY_TIMER, 0x80); | 134 | early_write_config_byte(hose, 0, 0, PCI_LATENCY_TIMER, 0x80); |
136 | |||
137 | /* PCIE Bus, Fix the MPC8641D host bridge's location to bus 0xFF. */ | ||
138 | early_read_config_dword(hose, 0, 0, PCI_PRIMARY_BUS, &temps); | ||
139 | temps = (temps & 0xff000000) | (0xff) | (0x0 << 8) | (0xfe << 16); | ||
140 | early_write_config_dword(hose, 0, 0, PCI_PRIMARY_BUS, temps); | ||
141 | } | 135 | } |
142 | 136 | ||
143 | int mpc86xx_exclude_device(u_char bus, u_char devfn) | 137 | static void __devinit quirk_fsl_pcie_transparent(struct pci_dev *dev) |
144 | { | 138 | { |
145 | if (bus == 0 && PCI_SLOT(devfn) == 0) | 139 | struct resource *res; |
146 | return PCIBIOS_DEVICE_NOT_FOUND; | 140 | int i, res_idx = PCI_BRIDGE_RESOURCES; |
141 | struct pci_controller *hose; | ||
147 | 142 | ||
148 | return PCIBIOS_SUCCESSFUL; | 143 | /* |
144 | * Make the bridge be transparent. | ||
145 | */ | ||
146 | dev->transparent = 1; | ||
147 | |||
148 | hose = pci_bus_to_host(dev->bus); | ||
149 | if (!hose) { | ||
150 | printk(KERN_ERR "Can't find hose for bus %d\n", | ||
151 | dev->bus->number); | ||
152 | return; | ||
153 | } | ||
154 | |||
155 | if (hose->io_resource.flags) { | ||
156 | res = &dev->resource[res_idx++]; | ||
157 | res->start = hose->io_resource.start; | ||
158 | res->end = hose->io_resource.end; | ||
159 | res->flags = hose->io_resource.flags; | ||
160 | } | ||
161 | |||
162 | for (i = 0; i < 3; i++) { | ||
163 | res = &dev->resource[res_idx + i]; | ||
164 | res->start = hose->mem_resources[i].start; | ||
165 | res->end = hose->mem_resources[i].end; | ||
166 | res->flags = hose->mem_resources[i].flags; | ||
167 | } | ||
149 | } | 168 | } |
150 | 169 | ||
151 | int __init add_bridge(struct device_node *dev) | 170 | |
171 | DECLARE_PCI_FIXUP_EARLY(0x1957, 0x7010, quirk_fsl_pcie_transparent); | ||
172 | DECLARE_PCI_FIXUP_EARLY(0x1957, 0x7011, quirk_fsl_pcie_transparent); | ||
173 | |||
174 | #define PCIE_LTSSM 0x404 /* PCIe Link Training and Status */ | ||
175 | #define PCIE_LTSSM_L0 0x16 /* L0 state */ | ||
176 | |||
177 | int __init mpc86xx_add_bridge(struct device_node *dev) | ||
152 | { | 178 | { |
153 | int len; | 179 | int len; |
154 | struct pci_controller *hose; | 180 | struct pci_controller *hose; |
@@ -156,6 +182,7 @@ int __init add_bridge(struct device_node *dev) | |||
156 | const int *bus_range; | 182 | const int *bus_range; |
157 | int has_address = 0; | 183 | int has_address = 0; |
158 | int primary = 0; | 184 | int primary = 0; |
185 | u16 val; | ||
159 | 186 | ||
160 | DBG("Adding PCIE host bridge %s\n", dev->full_name); | 187 | DBG("Adding PCIE host bridge %s\n", dev->full_name); |
161 | 188 | ||
@@ -168,17 +195,23 @@ int __init add_bridge(struct device_node *dev) | |||
168 | printk(KERN_WARNING "Can't get bus-range for %s, assume" | 195 | printk(KERN_WARNING "Can't get bus-range for %s, assume" |
169 | " bus 0\n", dev->full_name); | 196 | " bus 0\n", dev->full_name); |
170 | 197 | ||
171 | hose = pcibios_alloc_controller(); | 198 | pci_assign_all_buses = 1; |
199 | hose = pcibios_alloc_controller(dev); | ||
172 | if (!hose) | 200 | if (!hose) |
173 | return -ENOMEM; | 201 | return -ENOMEM; |
174 | hose->arch_data = dev; | ||
175 | hose->set_cfg_type = 1; | ||
176 | 202 | ||
177 | /* last_busno = 0xfe cause by MPC8641 PCIE bug */ | 203 | hose->indirect_type = PPC_INDIRECT_TYPE_EXT_REG | |
204 | PPC_INDIRECT_TYPE_SURPRESS_PRIMARY_BUS; | ||
205 | |||
178 | hose->first_busno = bus_range ? bus_range[0] : 0x0; | 206 | hose->first_busno = bus_range ? bus_range[0] : 0x0; |
179 | hose->last_busno = bus_range ? bus_range[1] : 0xfe; | 207 | hose->last_busno = bus_range ? bus_range[1] : 0xff; |
208 | |||
209 | setup_indirect_pci(hose, rsrc.start, rsrc.start + 0x4); | ||
180 | 210 | ||
181 | setup_indirect_pcie(hose, rsrc.start, rsrc.start + 0x4); | 211 | /* Probe the hose link training status */ |
212 | early_read_config_word(hose, 0, 0, PCIE_LTSSM, &val); | ||
213 | if (val < PCIE_LTSSM_L0) | ||
214 | return -ENXIO; | ||
182 | 215 | ||
183 | /* Setup the PCIE host controller. */ | 216 | /* Setup the PCIE host controller. */ |
184 | mpc86xx_setup_pcie(hose, rsrc.start, rsrc.end - rsrc.start + 1); | 217 | mpc86xx_setup_pcie(hose, rsrc.start, rsrc.end - rsrc.start + 1); |