From: Benjamin Herrenschmidt This patch, mostly from Sven Luther and reworked by me, adds support for Pegasos machines to the ppc32 arch. The patch contains all of the arch code. I'll send separately a few driver changes as well. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Andrew Morton --- 25-akpm/arch/ppc/platforms/chrp_pci.c | 38 ++++++++++++++-- 25-akpm/arch/ppc/platforms/chrp_setup.c | 76 +++++++++++++++++++++++++++----- 25-akpm/arch/ppc/platforms/chrp_time.c | 2 25-akpm/arch/ppc/syslib/prom_init.c | 22 +++++++-- 25-akpm/include/asm-ppc/processor.h | 2 5 files changed, 120 insertions(+), 20 deletions(-) diff -puN arch/ppc/platforms/chrp_pci.c~ppc32-add-support-for-pegasos-machines arch/ppc/platforms/chrp_pci.c --- 25/arch/ppc/platforms/chrp_pci.c~ppc32-add-support-for-pegasos-machines 2005-01-23 21:49:40.957745560 -0800 +++ 25-akpm/arch/ppc/platforms/chrp_pci.c 2005-01-23 21:49:40.968743888 -0800 @@ -97,8 +97,10 @@ int __chrp rtas_read_config(struct pci_bus *bus, unsigned int devfn, int offset, int len, u32 *val) { + struct pci_controller *hose = bus->sysdata; unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8) - | ((bus->number & 0xff) << 16); + | (((bus->number - hose->first_busno) & 0xff) << 16) + | (hose->index << 24); unsigned long ret = ~0UL; int rval; @@ -111,8 +113,10 @@ int __chrp rtas_write_config(struct pci_bus *bus, unsigned int devfn, int offset, int len, u32 val) { + struct pci_controller *hose = bus->sysdata; unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8) - | ((bus->number & 0xff) << 16); + | (((bus->number - hose->first_busno) & 0xff) << 16) + | (hose->index << 24); int rval; rval = call_rtas("write-pci-config", 3, 1, NULL, addr, len, val); @@ -186,6 +190,22 @@ setup_python(struct pci_controller *hose iounmap(reg); } +/* Marvell Discovery II based Pegasos 2 */ +static void __init setup_peg2(struct pci_controller *hose, struct device_node *dev) +{ + struct device_node *root = find_path_device("/"); + struct device_node *rtas; + + rtas = of_find_node_by_name (root, "rtas"); + if (rtas) { + hose->ops = &rtas_pci_ops; + } else { + printk ("RTAS supporting Pegasos OF not found, please upgrade" + " your firmware\n"); + } + pci_assign_all_busses = 1; +} + void __init chrp_find_bridges(void) { @@ -195,7 +215,7 @@ chrp_find_bridges(void) struct pci_controller *hose; unsigned int *dma; char *model, *machine; - int is_longtrail = 0, is_mot = 0; + int is_longtrail = 0, is_mot = 0, is_pegasos = 0; struct device_node *root = find_path_device("/"); /* @@ -207,6 +227,10 @@ chrp_find_bridges(void) if (machine != NULL) { is_longtrail = strncmp(machine, "IBM,LongTrail", 13) == 0; is_mot = strncmp(machine, "MOT", 3) == 0; + if (strncmp(machine, "Pegasos2", 8) == 0) + is_pegasos = 2; + else if (strncmp(machine, "Pegasos", 7) == 0) + is_pegasos = 1; } for (dev = root->child; dev != NULL; dev = dev->sibling) { if (dev->type == NULL || strcmp(dev->type, "pci") != 0) @@ -257,6 +281,10 @@ chrp_find_bridges(void) hose->ops = &gg2_pci_ops; hose->cfg_data = p; gg2_pci_config_base = p; + } else if (is_pegasos == 1) { + setup_indirect_pci(hose, 0xfec00cf8, 0xfee00cfc); + } else if (is_pegasos == 2) { + setup_peg2(hose, dev); } else { printk("No methods for %s (model %s), using RTAS\n", dev->full_name, model); @@ -275,5 +303,7 @@ chrp_find_bridges(void) } } - ppc_md.pcibios_fixup = chrp_pcibios_fixup; + /* Do not fixup interrupts from OF tree on pegasos */ + if (is_pegasos != 0) + ppc_md.pcibios_fixup = chrp_pcibios_fixup; } diff -puN arch/ppc/platforms/chrp_setup.c~ppc32-add-support-for-pegasos-machines arch/ppc/platforms/chrp_setup.c --- 25/arch/ppc/platforms/chrp_setup.c~ppc32-add-support-for-pegasos-machines 2005-01-23 21:49:40.959745256 -0800 +++ 25-akpm/arch/ppc/platforms/chrp_setup.c 2005-01-23 21:49:40.969743736 -0800 @@ -37,6 +37,7 @@ #include #include #include +#include #include #include @@ -68,6 +69,9 @@ void btext_progress(char *, unsigned sho extern unsigned long pmac_find_end_of_memory(void); extern int of_show_percpuinfo(struct seq_file *, int); +int _chrp_type; +EXPORT_SYMBOL(_chrp_type); + /* * XXX this should be in xmon.h, but putting it there means xmon.h * has to include (to get irqreturn_t), which @@ -214,8 +218,33 @@ static void __init sio_init(void) } -void __init -chrp_setup_arch(void) +static void __init pegasos_set_l2cr(void) +{ + struct device_node *np; + + /* On Pegasos, enable the l2 cache if needed, as the OF forgets it */ + if (_chrp_type != _CHRP_Pegasos) + return; + + /* Enable L2 cache if needed */ + np = find_type_devices("cpu"); + if (np != NULL) { + unsigned int *l2cr = (unsigned int *) + get_property (np, "l2cr", NULL); + if (l2cr == NULL) { + printk ("Pegasos l2cr : no cpu l2cr property found\n"); + return; + } + if (!((*l2cr) & 0x80000000)) { + printk ("Pegasos l2cr : L2 cache was not active, " + "activating\n"); + _set_L2CR(0); + _set_L2CR((*l2cr) | 0x80000000); + } + } +} + +void __init chrp_setup_arch(void) { struct device_node *device; @@ -232,6 +261,9 @@ chrp_setup_arch(void) #endif ROOT_DEV = Root_SDA2; /* sda2 (sda1 is for the kernel) */ + /* On pegasos, enable the L2 cache if not already done by OF */ + pegasos_set_l2cr(); + /* Lookup PCI host bridges */ chrp_find_bridges(); @@ -402,15 +434,17 @@ void __init chrp_init_IRQ(void) chrp_find_openpic(); - prom_get_irq_senses(init_senses, NUM_8259_INTERRUPTS, NR_IRQS); - OpenPIC_InitSenses = init_senses; - OpenPIC_NumInitSenses = NR_IRQS - NUM_8259_INTERRUPTS; - - openpic_init(NUM_8259_INTERRUPTS); - /* We have a cascade on OpenPIC IRQ 0, Linux IRQ 16 */ - openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade", - i8259_irq); + if (OpenPIC_Addr) { + prom_get_irq_senses(init_senses, NUM_8259_INTERRUPTS, NR_IRQS); + OpenPIC_InitSenses = init_senses; + OpenPIC_NumInitSenses = NR_IRQS - NUM_8259_INTERRUPTS; + + openpic_init(NUM_8259_INTERRUPTS); + /* We have a cascade on OpenPIC IRQ 0, Linux IRQ 16 */ + openpic_hookup_cascade(NUM_8259_INTERRUPTS, "82c59 cascade", + i8259_irq); + } for (i = 0; i < NUM_8259_INTERRUPTS; i++) irq_desc[i].handler = &i8259_pic; i8259_init(chrp_int_ack); @@ -450,6 +484,9 @@ void __init chrp_init(unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7) { + struct device_node *root = find_path_device ("/"); + char *machine = NULL; + #ifdef CONFIG_BLK_DEV_INITRD /* take care of initrd if we have one */ if ( r6 ) @@ -464,12 +501,29 @@ chrp_init(unsigned long r3, unsigned lon DMA_MODE_WRITE = 0x48; isa_io_base = CHRP_ISA_IO_BASE; /* default value */ + if (root) + machine = get_property(root, "model", NULL); + if (machine && strncmp(machine, "Pegasos", 7) == 0) { + _chrp_type = _CHRP_Pegasos; + } else if (machine && strncmp(machine, "IBM", 3) == 0) { + _chrp_type = _CHRP_IBM; + } else if (machine && strncmp(machine, "MOT", 3) == 0) { + _chrp_type = _CHRP_Motorola; + } else { + /* Let's assume it is an IBM chrp if all else fails */ + _chrp_type = _CHRP_IBM; + } + ppc_md.setup_arch = chrp_setup_arch; ppc_md.show_percpuinfo = of_show_percpuinfo; ppc_md.show_cpuinfo = chrp_show_cpuinfo; + ppc_md.irq_canonicalize = chrp_irq_canonicalize; ppc_md.init_IRQ = chrp_init_IRQ; - ppc_md.get_irq = openpic_get_irq; + if (_chrp_type == _CHRP_Pegasos) + ppc_md.get_irq = i8259_irq; + else + ppc_md.get_irq = openpic_get_irq; ppc_md.init = chrp_init2; diff -puN arch/ppc/platforms/chrp_time.c~ppc32-add-support-for-pegasos-machines arch/ppc/platforms/chrp_time.c --- 25/arch/ppc/platforms/chrp_time.c~ppc32-add-support-for-pegasos-machines 2005-01-23 21:49:40.960745104 -0800 +++ 25-akpm/arch/ppc/platforms/chrp_time.c 2005-01-23 21:49:40.968743888 -0800 @@ -41,6 +41,8 @@ long __init chrp_time_init(void) int base; rtcs = find_compatible_devices("rtc", "pnpPNP,b00"); + if (rtcs == NULL) + rtcs = find_compatible_devices("rtc", "ds1385-rtc"); if (rtcs == NULL || rtcs->addrs == NULL) return 0; base = rtcs->addrs[0].address; diff -puN arch/ppc/syslib/prom_init.c~ppc32-add-support-for-pegasos-machines arch/ppc/syslib/prom_init.c --- 25/arch/ppc/syslib/prom_init.c~ppc32-add-support-for-pegasos-machines 2005-01-23 21:49:40.962744800 -0800 +++ 25-akpm/arch/ppc/syslib/prom_init.c 2005-01-23 21:49:40.967744040 -0800 @@ -810,6 +810,9 @@ prom_init(int r3, int r4, prom_entry pp) char *p, *d; unsigned long phys; void *result[3]; + char model[32]; + phandle node; + int rc; /* Default */ phys = (unsigned long) &_stext; @@ -866,11 +869,20 @@ prom_init(int r3, int r4, prom_entry pp) klimit = (char *) (mem - offset); - /* If we are already running at 0xc0000000, we assume we were - * loaded by an OF bootloader which did set a BAT for us. - * This breaks OF translate so we force phys to be 0. - */ - if (offset == 0) { + node = call_prom("finddevice", 1, 1, "/"); + rc = call_prom("getprop", 4, 1, node, "model", model, sizeof(model)); + if (rc > 0 && !strncmp (model, "Pegasos", 7) + && strncmp (model, "Pegasos2", 8)) { + /* Pegasos 1 has a broken translate method in the OF, + * and furthermore the BATs are mapped 1:1 so the phys + * address calculated above is correct, so let's use + * it directly. + */ + } else if (offset == 0) { + /* If we are already running at 0xc0000000, we assume we were + * loaded by an OF bootloader which did set a BAT for us. + * This breaks OF translate so we force phys to be 0. + */ prom_print("(already at 0xc0000000) phys=0\n"); phys = 0; } else if ((int) call_prom("getprop", 4, 1, prom_chosen, "mmu", diff -puN include/asm-ppc/processor.h~ppc32-add-support-for-pegasos-machines include/asm-ppc/processor.h --- 25/include/asm-ppc/processor.h~ppc32-add-support-for-pegasos-machines 2005-01-23 21:49:40.963744648 -0800 +++ 25-akpm/include/asm-ppc/processor.h 2005-01-23 21:49:40.970743584 -0800 @@ -34,6 +34,7 @@ /* these are arbitrary */ #define _CHRP_Motorola 0x04 /* motorola chrp, the cobra */ #define _CHRP_IBM 0x05 /* IBM chrp, the longtrail and longtrail 2 */ +#define _CHRP_Pegasos 0x06 /* Genesi/bplan's Pegasos and Pegasos2 */ #define _GLOBAL(n)\ .stabs __stringify(n:F-1),N_FUN,0,0,n;\ @@ -54,6 +55,7 @@ extern int _machine; /* what kind of prep workstation we are */ extern int _prep_type; +extern int _chrp_type; /* * This is used to identify the board type from a given PReP board _