|
Lines 97-104
Link Here
|
| 97 |
rtas_read_config(struct pci_bus *bus, unsigned int devfn, int offset, |
97 |
rtas_read_config(struct pci_bus *bus, unsigned int devfn, int offset, |
| 98 |
int len, u32 *val) |
98 |
int len, u32 *val) |
| 99 |
{ |
99 |
{ |
|
|
100 |
struct pci_controller *hose = bus->sysdata; |
| 100 |
unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8) |
101 |
unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8) |
| 101 |
| ((bus->number & 0xff) << 16); |
102 |
| (((bus->number - hose->first_busno) & 0xff) << 16) | (pci_domain_nr(bus) << 24); |
| 102 |
unsigned long ret = ~0UL; |
103 |
unsigned long ret = ~0UL; |
| 103 |
int rval; |
104 |
int rval; |
| 104 |
|
105 |
|
|
Lines 111-118
Link Here
|
| 111 |
rtas_write_config(struct pci_bus *bus, unsigned int devfn, int offset, |
112 |
rtas_write_config(struct pci_bus *bus, unsigned int devfn, int offset, |
| 112 |
int len, u32 val) |
113 |
int len, u32 val) |
| 113 |
{ |
114 |
{ |
|
|
115 |
struct pci_controller *hose = bus->sysdata; |
| 114 |
unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8) |
116 |
unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8) |
| 115 |
| ((bus->number & 0xff) << 16); |
117 |
| (((bus->number - hose->first_busno) & 0xff) << 16) | (pci_domain_nr(bus) << 24); |
| 116 |
int rval; |
118 |
int rval; |
| 117 |
|
119 |
|
| 118 |
rval = call_rtas("write-pci-config", 3, 1, NULL, addr, len, val); |
120 |
rval = call_rtas("write-pci-config", 3, 1, NULL, addr, len, val); |
|
Lines 186-191
Link Here
|
| 186 |
iounmap(reg); |
188 |
iounmap(reg); |
| 187 |
} |
189 |
} |
| 188 |
|
190 |
|
|
|
191 |
/* Marvell Discovery II based Pegasos 2 */ |
| 192 |
volatile unsigned int *peg2_magic_agp_f118; |
| 193 |
volatile unsigned int *peg2_magic_agp_f11c; |
| 194 |
|
| 195 |
int __chrp peg2_read_config(struct pci_bus *bus, unsigned int devfn, int off, |
| 196 |
int len, u32 *val) |
| 197 |
{ |
| 198 |
volatile unsigned char *cfg_data; |
| 199 |
struct pci_controller *hose = bus->sysdata; |
| 200 |
u32 msr; |
| 201 |
|
| 202 |
/* We can read only on function 0 offset 0 to 15 on device 0) */ |
| 203 |
if (bus->number == hose->first_busno) { |
| 204 |
if (devfn == 0) { |
| 205 |
if (off > 15) { |
| 206 |
* val = (u32) 0; |
| 207 |
return PCIBIOS_SUCCESSFUL; |
| 208 |
} |
| 209 |
} else if ((devfn >> 3) == 0) |
| 210 |
return PCIBIOS_DEVICE_NOT_FOUND; |
| 211 |
} |
| 212 |
|
| 213 |
/* Magic fix for the agp bus */ |
| 214 |
if (hose->index == 1) { |
| 215 |
/* Disable cpu interrupts */ |
| 216 |
msr = mfmsr(); |
| 217 |
mtmsr(msr & ~MSR_EE); |
| 218 |
/* Enable PCI -> AGP idsel mapping */ |
| 219 |
out_be32 (peg2_magic_agp_f118, 0x8000); |
| 220 |
} |
| 221 |
|
| 222 |
out_le32 (hose->cfg_addr, |
| 223 |
0x80000000 | ((bus->number - hose->first_busno) << 16) | (devfn << 8) | (off & 0xfc)); |
| 224 |
/* |
| 225 |
* Note: the caller has already checked that off is |
| 226 |
* suitably aligned and that len is 1, 2 or 4. |
| 227 |
*/ |
| 228 |
cfg_data = hose->cfg_data + (off & 3); |
| 229 |
switch (len) { |
| 230 |
case 1: |
| 231 |
*val = in_8((u8 *)cfg_data); |
| 232 |
break; |
| 233 |
case 2: |
| 234 |
*val = in_le16((u16 *)cfg_data); |
| 235 |
break; |
| 236 |
default: |
| 237 |
*val = in_le32((u32 *)cfg_data); |
| 238 |
break; |
| 239 |
} |
| 240 |
/* Magic fix for the agp bus */ |
| 241 |
if (hose->index == 1) { |
| 242 |
/* Disable PCI -> AGP idsel mapping */ |
| 243 |
out_be32 (peg2_magic_agp_f11c, 0x8000); |
| 244 |
/* Enable cpu interrupts */ |
| 245 |
mtmsr(msr); |
| 246 |
} |
| 247 |
return PCIBIOS_SUCCESSFUL; |
| 248 |
} |
| 249 |
|
| 250 |
int __chrp peg2_write_config(struct pci_bus *bus, unsigned int devfn, int off, |
| 251 |
int len, u32 val) |
| 252 |
{ |
| 253 |
volatile unsigned char *cfg_data; |
| 254 |
struct pci_controller *hose = bus->sysdata; |
| 255 |
u32 msr; |
| 256 |
|
| 257 |
/* We ignore writes to device 0 */ |
| 258 |
/*if (bus->number == 0) */ |
| 259 |
if (bus->number == hose->first_busno) { |
| 260 |
if (devfn == 0) |
| 261 |
return PCIBIOS_SUCCESSFUL; |
| 262 |
else if ((devfn >> 3) == 0) |
| 263 |
return PCIBIOS_DEVICE_NOT_FOUND; |
| 264 |
} |
| 265 |
|
| 266 |
/* Magic fix for the agp bus */ |
| 267 |
if (hose->index == 1) { |
| 268 |
/* Disable cpu interrupts */ |
| 269 |
msr = mfmsr(); |
| 270 |
mtmsr(msr & ~MSR_EE); |
| 271 |
/* Enable PCI -> AGP idsel mapping */ |
| 272 |
out_be32 (peg2_magic_agp_f118, 0x8000); |
| 273 |
} |
| 274 |
|
| 275 |
out_le32 (hose->cfg_addr, |
| 276 |
0x80000000 | ((bus->number - hose->first_busno) << 16) | (devfn << 8) | (off & 0xfc)); |
| 277 |
/* |
| 278 |
* Note: the caller has already checked that off is |
| 279 |
* suitably aligned and that len is 1, 2 or 4. |
| 280 |
*/ |
| 281 |
cfg_data = hose->cfg_data + (off & 3); |
| 282 |
switch (len) { |
| 283 |
case 1: |
| 284 |
out_8((u8 *)cfg_data, val); |
| 285 |
break; |
| 286 |
case 2: |
| 287 |
out_le16((u16 *)cfg_data, val); |
| 288 |
break; |
| 289 |
default: |
| 290 |
out_le32((u32 *)cfg_data, val); |
| 291 |
break; |
| 292 |
} |
| 293 |
/* Magic fix for the agp bus */ |
| 294 |
if (hose->index == 1) { |
| 295 |
/* Disable PCI -> AGP idsel mapping */ |
| 296 |
out_be32 (peg2_magic_agp_f11c, 0x8000); |
| 297 |
/* Enable cpu interrupts */ |
| 298 |
mtmsr(msr); |
| 299 |
} |
| 300 |
return PCIBIOS_SUCCESSFUL; |
| 301 |
} |
| 302 |
|
| 303 |
|
| 304 |
static struct pci_ops peg2_pci_ops = |
| 305 |
{ |
| 306 |
peg2_read_config, |
| 307 |
peg2_write_config |
| 308 |
}; |
| 309 |
|
| 310 |
#define PEGASOS_USE_RTAS |
| 311 |
//#define PEGASOS_USE_PCI_DOMAINS |
| 312 |
|
| 313 |
static void __init |
| 314 |
setup_peg2(struct pci_controller *hose, struct device_node *dev) |
| 315 |
{ |
| 316 |
unsigned long base = 0xf1000c78 & PAGE_MASK; |
| 317 |
char *mbase; |
| 318 |
unsigned long magic_agp_base = 0xf100f118 & PAGE_MASK; |
| 319 |
char *magic_agp_mbase; |
| 320 |
#ifdef PEGASOS_USE_RTAS |
| 321 |
struct device_node *root = find_path_device("/"); |
| 322 |
struct device_node *rtas; |
| 323 |
|
| 324 |
rtas = of_find_node_by_name (root, "rtas"); |
| 325 |
if (rtas) { |
| 326 |
hose->ops = &rtas_pci_ops; |
| 327 |
printk ("Pegasos OF RTAS support detected, using it\n"); |
| 328 |
} else { |
| 329 |
printk ("Pegasos OF doesn't support RTAS, please upgrade it\n"); |
| 330 |
#else |
| 331 |
{ |
| 332 |
#endif |
| 333 |
if (strncmp(dev->full_name, "/pci@80000000", 13) == 0) { |
| 334 |
mbase = ioremap (base, PAGE_SIZE); |
| 335 |
hose->cfg_addr = (unsigned int *) (mbase + (0xf1000c78 & ~PAGE_MASK)); |
| 336 |
hose->cfg_data = (unsigned char *) (mbase + (0xf1000c7c & ~PAGE_MASK)); |
| 337 |
hose->ops = &peg2_pci_ops; |
| 338 |
} else if (strncmp(dev->full_name, "/pci@C0000000", 13) == 0) { |
| 339 |
mbase = ioremap (base, PAGE_SIZE); |
| 340 |
hose->cfg_addr = (unsigned int *) (mbase + (0xf1000cf8 & ~PAGE_MASK)); |
| 341 |
hose->cfg_data = (unsigned char *) (mbase + (0xf1000cfc & ~PAGE_MASK)); |
| 342 |
hose->ops = &peg2_pci_ops; |
| 343 |
magic_agp_mbase = ioremap (magic_agp_base, PAGE_SIZE); |
| 344 |
peg2_magic_agp_f118 = (unsigned int *) (magic_agp_mbase + (0xf100f118 & ~PAGE_MASK)); |
| 345 |
peg2_magic_agp_f11c = (unsigned int *) (magic_agp_mbase + (0xf100f1c8 & ~PAGE_MASK)); |
| 346 |
} else |
| 347 |
printk("Pegasos 2 unknown pci bridge detected %s, type %s, full name %s at %08x, ints %d\n", |
| 348 |
dev->name, dev->type, dev->full_name, dev->n_addrs, dev->n_intrs); |
| 349 |
} |
| 350 |
#ifndef PEGASOS_USE_PCI_DOMAINS |
| 351 |
pci_assign_all_busses = 1; |
| 352 |
#endif |
| 353 |
} |
| 354 |
|
| 189 |
void __init |
355 |
void __init |
| 190 |
chrp_find_bridges(void) |
356 |
chrp_find_bridges(void) |
| 191 |
{ |
357 |
{ |
|
Lines 195-201
Link Here
|
| 195 |
struct pci_controller *hose; |
361 |
struct pci_controller *hose; |
| 196 |
unsigned int *dma; |
362 |
unsigned int *dma; |
| 197 |
char *model, *machine; |
363 |
char *model, *machine; |
| 198 |
int is_longtrail = 0, is_mot = 0; |
364 |
int is_longtrail = 0, is_mot = 0, is_pegasos = 0; |
| 199 |
struct device_node *root = find_path_device("/"); |
365 |
struct device_node *root = find_path_device("/"); |
| 200 |
|
366 |
|
| 201 |
/* |
367 |
/* |
|
Lines 207-212
Link Here
|
| 207 |
if (machine != NULL) { |
373 |
if (machine != NULL) { |
| 208 |
is_longtrail = strncmp(machine, "IBM,LongTrail", 13) == 0; |
374 |
is_longtrail = strncmp(machine, "IBM,LongTrail", 13) == 0; |
| 209 |
is_mot = strncmp(machine, "MOT", 3) == 0; |
375 |
is_mot = strncmp(machine, "MOT", 3) == 0; |
|
|
376 |
if (strncmp(machine, "Pegasos2", 8) == 0) is_pegasos = 2; |
| 377 |
else if (strncmp(machine, "Pegasos", 7) == 0) is_pegasos = 1; |
| 210 |
} |
378 |
} |
| 211 |
for (dev = root->child; dev != NULL; dev = dev->sibling) { |
379 |
for (dev = root->child; dev != NULL; dev = dev->sibling) { |
| 212 |
if (dev->type == NULL || strcmp(dev->type, "pci") != 0) |
380 |
if (dev->type == NULL || strcmp(dev->type, "pci") != 0) |
|
Lines 257-262
Link Here
|
| 257 |
hose->cfg_data = (unsigned char *) |
425 |
hose->cfg_data = (unsigned char *) |
| 258 |
ioremap(GG2_PCI_CONFIG_BASE, 0x80000); |
426 |
ioremap(GG2_PCI_CONFIG_BASE, 0x80000); |
| 259 |
gg2_pci_config_base = (unsigned long) hose->cfg_data; |
427 |
gg2_pci_config_base = (unsigned long) hose->cfg_data; |
|
|
428 |
} else if (is_pegasos == 1) { |
| 429 |
setup_indirect_pci(hose, 0xfec00cf8, 0xfee00cfc); |
| 430 |
} else if (is_pegasos == 2) { |
| 431 |
setup_peg2(hose, dev); |
| 260 |
} else { |
432 |
} else { |
| 261 |
printk("No methods for %s (model %s), using RTAS\n", |
433 |
printk("No methods for %s (model %s), using RTAS\n", |
| 262 |
dev->full_name, model); |
434 |
dev->full_name, model); |
|
Lines 274-279
Link Here
|
| 274 |
printk("pci_dram_offset = %lx\n", pci_dram_offset); |
446 |
printk("pci_dram_offset = %lx\n", pci_dram_offset); |
| 275 |
} |
447 |
} |
| 276 |
} |
448 |
} |
| 277 |
|
449 |
|
| 278 |
ppc_md.pcibios_fixup = chrp_pcibios_fixup; |
450 |
if (is_pegasos) |
|
|
451 |
ppc_md.pcibios_fixup = NULL; |
| 452 |
else |
| 453 |
ppc_md.pcibios_fixup = chrp_pcibios_fixup; |
| 279 |
} |
454 |
} |