diff -urb orig.2003-01-27/arch/ppc/kernel/harrier.c 2003-01-27/arch/ppc/kernel/harrier.c --- orig.2003-01-27/arch/ppc/kernel/harrier.c Sun Jan 26 21:08:03 2003 +++ 2003-01-27/arch/ppc/kernel/harrier.c Mon Jan 27 16:37:16 2003 @@ -70,7 +70,7 @@ (hose->io_space.end - hose->io_space.start))) { printk("harrier_init: %s\n", "PPC and PCI memory or I/O space sizes don't match"); - return -1; + /* return -1; */ } if ((processor_mpic_base & 0xfffc0000) != processor_mpic_base) { diff -urb orig.2003-01-27/arch/ppc/platforms/prpmc800.h 2003-01-27/arch/ppc/platforms/prpmc800.h --- orig.2003-01-27/arch/ppc/platforms/prpmc800.h Sun Jan 26 21:09:31 2003 +++ 2003-01-27/arch/ppc/platforms/prpmc800.h Mon Jan 27 14:57:26 2003 @@ -26,9 +26,12 @@ #ifndef __ASMPPC_PRPMC800_H #define __ASMPPC_PRPMC800_H +/* These two addresses depend on OTAD3/OTOF3/OTAT3 being correct */ #define PRPMC800_PCI_CONFIG_ADDR 0xfe000cf8 #define PRPMC800_PCI_CONFIG_DATA 0xfe000cfc +/* The following addresses may be used for MONARCHS, otherwise + * we have better use what is given to us. */ #define PRPMC800_PROC_PCI_IO_START 0xfe400000U #define PRPMC800_PROC_PCI_IO_END 0xfeefffffU #define PRPMC800_PCI_IO_START 0x00000000U @@ -52,5 +55,7 @@ #define PRPMC800_BASE_BAUD 1843200 +/* Utility macro to access harrier registers from XCSR base */ +#define HARRIER_REG(name) (PRPMC800_HARRIER_XCSR_BASE+HARRIER_##name##_OFF) #endif /* __ASMPPC_PRPMC800_H */ diff -urb orig.2003-01-27/arch/ppc/platforms/prpmc800_pci.c 2003-01-27/arch/ppc/platforms/prpmc800_pci.c --- orig.2003-01-27/arch/ppc/platforms/prpmc800_pci.c Sun Jan 26 21:08:44 2003 +++ 2003-01-27/arch/ppc/platforms/prpmc800_pci.c Mon Jan 27 16:44:13 2003 @@ -43,17 +43,72 @@ {12, 0, 0, 0}, /* IDSEL 14 - Ethernet, base */ {0, 0, 0, 0}, /* IDSEL 15 - unused */ {10, 11, 12, 9}, /* IDSEL 16 - PMC A1, PMC1 */ + /* IDSEL 16 is also ADC-PMC2 1A*/ {10, 11, 12, 9}, /* IDSEL 17 - PrPMC-A-B, PMC2-B */ {11, 12, 9, 10}, /* IDSEL 18 - PMC A1-B, PMC1-B */ + /* IDSEL 18 is also ADC-PMC2 2A*/ {0, 0, 0, 0}, /* IDSEL 19 - unused */ {9, 10, 11, 12}, /* IDSEL 20 - P2P Bridge */ {11, 12, 9, 10}, /* IDSEL 21 - PMC A2, carrier */ {12, 9, 10, 11}, /* IDSEL 22 - PMC A2-B, carrier */ + // FIXME: We need some better way to handle this mapping + // in a generic way. How can one find out what kind of + // carrier we are in??? + { 10 , 11, 12, 9 }, /* IDSEL 23 ADC-PMC2 1B */ + { 10 , 11, 12, 9 }, /* IDSEL 24 ADC-PMC2 2B */ +/* +# ADC-PMC2 1 & 2 +1 PCI Function 00/10/0 (00008000) ID/Revision.........=480B1057/02 (Inactive) +2 PCI Function 00/12/0 (00009000) ID/Revision.........=480B1057/02 (Inactive) +1 PCI Function 00/17/0 (0000B800) ID/Revision.........=12098086/09 (Inactive) +2 PCI Function 00/18/0 (0000C000) ID/Revision.........=12098086/09 (Inactive) + +# PrPMC carrier +PCI Function 00/00/0 (00000000) ID/Revision.........=480B1057/02 +PCI Function 00/11/0 (00008800) ID/Revision.........=12098086/09 +PCI Function 00/14/0 (0000A000) ID/Revision.........=00261011/05 +PCI Function 01/02/0 (00011000) ID/Revision.........=12098086/09 +PCI Function 01/05/0 (00012800) ID/Revision.........=12098086/09 +*/ }; - const long min_idsel = 14, max_idsel = 22, irqs_per_slot = 4; + const long min_idsel = 14, max_idsel = 24, irqs_per_slot = 4; return PCI_IRQ_TABLE_LOOKUP; }; +u32 __init +prpmc800_find_hostbridge(void) { + /* + * Scan the PCI bus until we find our own hostbridge. + * This is probably unnecessary, since we could just as well + * check if the Harrier is available from the PowerPC bus... + */ + u32 result, id; + int bus, slot; + + result = 0; + + for (bus = 0 ; bus < 255 ; bus++) { + /* Probably overkill to search beyond bus 0... */ + for (slot = 0 ; slot < 32 ; slot++) { + early_read_config_dword(0, bus, PCI_DEVFN(slot,0), PCI_VENDOR_ID, &id); + if (id == HARRIER_VEND_DEV_ID) { + /* Check if this is our harrier chip, this is done by + * reading the PSTA register from the PCI side and checking + * the LBA (Loop Back Access) bit. + */ + u8 psta; + + early_read_config_byte(0, bus, PCI_DEVFN(slot,0), HARRIER_PSTA_PCI_OFF, + &psta); + if (psta & HARRIER_PSTA_LBA_MASK) { + result = id; + } + } + } + } + return result; +} + void __init prpmc800_find_bridges(void) { @@ -68,6 +123,10 @@ hose->last_busno = 0xff; hose->pci_mem_offset = PRPMC800_PCI_PHY_MEM_OFFSET; + if (in_8((u8 *)HARRIER_REG(MISC_CSR)) & HARRIER_SCON_MASK) { + /* On a monarch we are free to decide the pci mapping ourselves */ + printk("PrPMC800 MONARCH\n"); + pci_init_resource(&hose->io_resource, PRPMC800_PCI_IO_START, PRPMC800_PCI_IO_END, @@ -89,13 +148,84 @@ setup_indirect_pci(hose, PRPMC800_PCI_CONFIG_ADDR, PRPMC800_PCI_CONFIG_DATA); + } else { + /* On a non-monarch we have to behave, so setup pci to mimic + * what's already in the harrier */ + + printk("PrPMC800 NON-MONARCH\n"); + /* + * Since the PPC7-Bug does stray accesses into PCI I/O space, + * that might lead to hangups on the host system, we warn if + * PCI I/O space is mapped (since that indicates there is a + * risk that resources on the PCI bus gets corrupted), then + * we happily enable the same PCI I/O space, while (temporarily) + * disabling all other outbound translations. + * + * But if OTAD3/OTAT3/OTOF3 are not properly initialized, we will + * not be able to scan the PCI bus... + */ + if (in_be32((u32 *)HARRIER_REG(OTOF3)) & HARRIER_OTOF_ENABLE) { + printk("PCI-I/O was enabled, host should disable OTOF3/OTAT3,\n"); + printk("or strange things may happen when using PPC7-Bug.\n"); + } + out_be32((u32 *)HARRIER_REG(OTAD0), 0); + out_be32((u32 *)HARRIER_REG(OTOF0), 0); + out_be32((u32 *)HARRIER_REG(OTAD1), 0); + out_be32((u32 *)HARRIER_REG(OTOF1), 0); + out_be32((u32 *)HARRIER_REG(OTAD2), 0); + out_be32((u32 *)HARRIER_REG(OTOF2), 0); + out_be32((u32 *)HARRIER_REG(OTAD3), 0xfe00fe00); + out_be32((u32 *)HARRIER_REG(OTOF3), 0x02000080); + + { + /* Read the current PCI mappings, and setup resources to + agree with this */ + int i; + + for (i = 0 ; i < 4 ; i++) { + u32 itat = in_le32((u32 *)(HARRIER_REG(ITAT0)+i*8)); + if (itat & HARRIER_ITAT_ENABLE) { + u32 itsz = in_le32((u32 *)(HARRIER_REG(ITSZ0)+i*8)); + u32 itbar = in_le32((u32 *)(HARRIER_REG(ITBAR0)+i*4)); + if (itat & HARRIER_ITAT_MEMORY) { + u32 pci_start = itbar & HARRIER_ITBAR_BASE_MASK; + u32 pci_end = + pci_start + (4096<<(itsz&HARRIER_ITSZ_SIZE_MASK)); + pci_init_resource(&hose->mem_resources[0], + pci_start, + pci_end, + IORESOURCE_MEM, + "PCI host bridge"); + hose->mem_space.start = pci_start; + hose->mem_space.end = pci_end; + printk("PrPMC800 PCI memory %d: %x-%x\n", + i, pci_start, pci_end); + } else { + printk("PrPMC800 PCI io %d: %x\n", + i, itat); + } + } + } + } + + pci_init_resource(&hose->io_resource, + PRPMC800_PCI_IO_START, + PRPMC800_PCI_IO_END, + IORESOURCE_IO, + "PCI host bridge"); + + hose->io_space.start = PRPMC800_PCI_IO_START; + hose->io_space.end = PRPMC800_PCI_IO_END; + hose->io_base_virt = (void *)PRPMC800_ISA_IO_BASE; + + setup_indirect_pci(hose, + PRPMC800_PCI_CONFIG_ADDR, + PRPMC800_PCI_CONFIG_DATA); + + } /* Get host bridge vendor/dev id */ - early_read_config_dword(hose, - 0, - PCI_DEVFN(0,0), - PCI_VENDOR_ID, - &host_bridge); + host_bridge = prpmc800_find_hostbridge(); switch (host_bridge) { case HARRIER_VEND_DEV_ID: diff -urb orig.2003-01-27/include/asm-ppc/harrier.h 2003-01-27/include/asm-ppc/harrier.h --- orig.2003-01-27/include/asm-ppc/harrier.h Mon Jan 27 12:51:29 2003 +++ 2003-01-27/include/asm-ppc/harrier.h Mon Jan 27 16:26:37 2003 @@ -21,6 +21,10 @@ #define HARRIER_VEND_DEV_ID 0x480b1057 +/* Harrier PCI status register */ +#define HARRIER_PSTA_PCI_OFF 0x83 +#define HARRIER_PSTA_LBA_MASK 0x80 + /* * Define outbound register offsets. */ @@ -33,13 +37,29 @@ #define HARRIER_OTAD3_OFF 0x238 #define HARRIER_OTOF3_OFF 0x23c +#define HARRIER_OTOF_ENABLE 0x80 + /* * Define inbound register offsets. */ +#define HARRIER_ITBAR0_OFF 0x314 +#define HARRIER_ITBAR1_OFF 0x318 +#define HARRIER_ITBAR2_OFF 0x31c +#define HARRIER_ITBAR3_OFF 0x320 #define HARRIER_ITSZ0_OFF 0x348 +#define HARRIER_ITAT0_OFF 0x34c #define HARRIER_ITSZ1_OFF 0x350 +#define HARRIER_ITAT1_OFF 0x354 #define HARRIER_ITSZ2_OFF 0x358 +#define HARRIER_ITAT2_OFF 0x35c #define HARRIER_ITSZ3_OFF 0x360 +#define HARRIER_ITAT3_OFF 0x364 + +#define HARRIER_ITBAR_BASE_MASK 0xffff0000 +#define HARRIER_ITAT_ENABLE 0x80 +#define HARRIER_ITAT_MEMORY 0x40 +#define HARRIER_ITSZ_SIZE_MASK 0x0f +#define HARRIER_ITSZ_OFFSET_MASK 0xffff0000 /* * Define the Memory Controller register offsets. @@ -65,8 +85,10 @@ #define HARRIER_UCTL_OFF 0xd0 #define HARRIER_XTAL64_MASK 0x02 +/* Should accesses (and masks) to the MCSR really be 8 bit? */ #define HARRIER_MISC_CSR_OFF 0x1c #define HARRIER_RSTOUT_MASK 0x01 +#define HARRIER_SCON_MASK 0x08 #define HARRIER_MBAR_OFF 0xe0 #define HARRIER_MPIC_CSR_OFF 0xe4