From eecba334bdef03ce4918c3193f9b81791a715fb9 Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Mon, 25 Sep 2006 13:35:09 +1000 Subject: [POWERPC] modify PCI code for a merged kernel Signed-off-by: Stephen Rothwell --- arch/powerpc/kernel/pci_64.c | 58 +++++++++++++++++++++++--------------------- 1 file changed, 30 insertions(+), 28 deletions(-) (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index c1b1e14775e..78d3c0fc8df 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c @@ -30,6 +30,7 @@ #include #include #include +#include #ifdef DEBUG #include @@ -209,7 +210,6 @@ void pcibios_free_controller(struct pci_controller *phb) kfree(phb); } -#ifndef CONFIG_PPC_ISERIES void __devinit pcibios_claim_one_bus(struct pci_bus *b) { struct pci_dev *dev; @@ -238,10 +238,12 @@ static void __init pcibios_claim_of_setup(void) { struct pci_bus *b; + if (firmware_has_feature(FW_FEATURE_ISERIES)) + return; + list_for_each_entry(b, &pci_root_buses, node) pcibios_claim_one_bus(b); } -#endif #ifdef CONFIG_PPC_MULTIPLATFORM static u32 get_int_prop(struct device_node *np, const char *name, u32 def) @@ -554,9 +556,8 @@ static int __init pcibios_init(void) */ ppc_md.phys_mem_access_prot = pci_phys_mem_access_prot; -#ifdef CONFIG_PPC_ISERIES - iSeries_pcibios_init(); -#endif + if (firmware_has_feature(FW_FEATURE_ISERIES)) + iSeries_pcibios_init(); printk(KERN_DEBUG "PCI: Probing PCI hardware\n"); @@ -566,15 +567,15 @@ static int __init pcibios_init(void) pci_bus_add_devices(hose->bus); } -#ifndef CONFIG_PPC_ISERIES - if (pci_probe_only) - pcibios_claim_of_setup(); - else - /* FIXME: `else' will be removed when - pci_assign_unassigned_resources() is able to work - correctly with [partially] allocated PCI tree. */ - pci_assign_unassigned_resources(); -#endif /* !CONFIG_PPC_ISERIES */ + if (!firmware_has_feature(FW_FEATURE_ISERIES)) { + if (pci_probe_only) + pcibios_claim_of_setup(); + else + /* FIXME: `else' will be removed when + pci_assign_unassigned_resources() is able to work + correctly with [partially] allocated PCI tree. */ + pci_assign_unassigned_resources(); + } /* Call machine dependent final fixup */ if (ppc_md.pcibios_fixup) @@ -586,8 +587,9 @@ static int __init pcibios_init(void) printk(KERN_DEBUG "ISA bridge at %s\n", pci_name(ppc64_isabridge_dev)); #ifdef CONFIG_PPC_MULTIPLATFORM - /* map in PCI I/O space */ - phbs_remap_io(); + if (!firmware_has_feature(FW_FEATURE_ISERIES)) + /* map in PCI I/O space */ + phbs_remap_io(); #endif printk(KERN_DEBUG "PCI: Probing PCI hardware done\n"); @@ -637,13 +639,13 @@ int pcibios_enable_device(struct pci_dev *dev, int mask) */ int pci_domain_nr(struct pci_bus *bus) { -#ifdef CONFIG_PPC_ISERIES - return 0; -#else - struct pci_controller *hose = pci_bus_to_host(bus); + if (firmware_has_feature(FW_FEATURE_ISERIES)) + return 0; + else { + struct pci_controller *hose = pci_bus_to_host(bus); - return hose->global_number; -#endif + return hose->global_number; + } } EXPORT_SYMBOL(pci_domain_nr); @@ -651,12 +653,12 @@ EXPORT_SYMBOL(pci_domain_nr); /* Decide whether to display the domain number in /proc */ int pci_proc_domain(struct pci_bus *bus) { -#ifdef CONFIG_PPC_ISERIES - return 0; -#else - struct pci_controller *hose = pci_bus_to_host(bus); - return hose->buid; -#endif + if (firmware_has_feature(FW_FEATURE_ISERIES)) + return 0; + else { + struct pci_controller *hose = pci_bus_to_host(bus); + return hose->buid; + } } /* -- cgit From 3f639ee8c52c187d8c95db430ac6f485bffbe5af Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Mon, 25 Sep 2006 18:19:00 +1000 Subject: [POWERPC] implement BEGIN/END_FW_FTR_SECTION and use it an all the obvious places in assembler code. Signed-off-by: Stephen Rothwell --- arch/powerpc/kernel/entry_64.S | 18 ++++++++++----- arch/powerpc/kernel/head_64.S | 28 +++++++++++++++++++++--- arch/powerpc/kernel/misc_64.S | 46 +++++++++++++++++++++++++++++++++++++++ arch/powerpc/kernel/vmlinux.lds.S | 8 +++++++ 4 files changed, 91 insertions(+), 9 deletions(-) (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 2cd872b5283..748e74fcf54 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S @@ -27,10 +27,7 @@ #include #include #include - -#ifdef CONFIG_PPC_ISERIES -#define DO_SOFT_DISABLE -#endif +#include /* * System calls. @@ -91,6 +88,7 @@ system_call_common: ld r11,exception_marker@toc(r2) std r11,-16(r9) /* "regshere" marker */ #ifdef CONFIG_PPC_ISERIES +BEGIN_FW_FTR_SECTION /* Hack for handling interrupts when soft-enabling on iSeries */ cmpdi cr1,r0,0x5555 /* syscall 0x5555 */ andi. r10,r12,MSR_PR /* from kernel */ @@ -98,6 +96,7 @@ system_call_common: beq hardware_interrupt_entry lbz r10,PACAPROCENABLED(r13) std r10,SOFTE(r1) +END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) #endif mfmsr r11 ori r11,r11,MSR_EE @@ -462,6 +461,7 @@ _GLOBAL(ret_from_except_lite) restore: #ifdef CONFIG_PPC_ISERIES +BEGIN_FW_FTR_SECTION ld r5,SOFTE(r1) cmpdi 0,r5,0 beq 4f @@ -480,6 +480,7 @@ restore: b .ret_from_except_lite /* loop back and handle more */ 4: stb r5,PACAPROCENABLED(r13) +END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) #endif ld r3,_MSR(r1) @@ -538,18 +539,23 @@ do_work: lwz r8,TI_PREEMPT(r9) cmpwi cr1,r8,0 #ifdef CONFIG_PPC_ISERIES +BEGIN_FW_FTR_SECTION ld r0,SOFTE(r1) cmpdi r0,0 -#else - andi. r0,r3,MSR_EE +END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) #endif +BEGIN_FW_FTR_SECTION + andi. r0,r3,MSR_EE +END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES) crandc eq,cr1*4+eq,eq bne restore /* here we are preempting the current task */ 1: #ifdef CONFIG_PPC_ISERIES +BEGIN_FW_FTR_SECTION li r0,1 stb r0,PACAPROCENABLED(r13) +END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) #endif ori r10,r10,MSR_EE mtmsrd r10,1 /* reenable interrupts */ diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index 3065b472b95..645c7f10fb2 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S @@ -33,6 +33,7 @@ #include #include #include +#include #ifdef CONFIG_PPC_ISERIES #define DO_SOFT_DISABLE @@ -365,19 +366,28 @@ label##_iSeries: \ #ifdef DO_SOFT_DISABLE #define DISABLE_INTS \ +BEGIN_FW_FTR_SECTION; \ lbz r10,PACAPROCENABLED(r13); \ li r11,0; \ std r10,SOFTE(r1); \ mfmsr r10; \ stb r11,PACAPROCENABLED(r13); \ ori r10,r10,MSR_EE; \ - mtmsrd r10,1 + mtmsrd r10,1; \ +END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) #define ENABLE_INTS \ +BEGIN_FW_FTR_SECTION; \ lbz r10,PACAPROCENABLED(r13); \ mfmsr r11; \ std r10,SOFTE(r1); \ ori r11,r11,MSR_EE; \ +END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES); \ +BEGIN_FW_FTR_SECTION; \ + ld r12,_MSR(r1); \ + mfmsr r11; \ + rlwimi r11,r12,0,MSR_EE; \ +END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES); \ mtmsrd r11,1 #else /* hard enable/disable interrupts */ @@ -1071,8 +1081,10 @@ _GLOBAL(slb_miss_realmode) ld r3,PACA_EXSLB+EX_R3(r13) lwz r9,PACA_EXSLB+EX_CCR(r13) /* get saved CR */ #ifdef CONFIG_PPC_ISERIES +BEGIN_FW_FTR_SECTION ld r11,PACALPPACAPTR(r13) ld r11,LPPACASRR0(r11) /* get SRR0 value */ +END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) #endif /* CONFIG_PPC_ISERIES */ mtlr r10 @@ -1087,8 +1099,10 @@ _GLOBAL(slb_miss_realmode) .machine pop #ifdef CONFIG_PPC_ISERIES +BEGIN_FW_FTR_SECTION mtspr SPRN_SRR0,r11 mtspr SPRN_SRR1,r12 +END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) #endif /* CONFIG_PPC_ISERIES */ ld r9,PACA_EXSLB+EX_R9(r13) ld r10,PACA_EXSLB+EX_R10(r13) @@ -1301,6 +1315,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SLB) cmpdi r3,0 /* see if hash_page succeeded */ #ifdef DO_SOFT_DISABLE +BEGIN_FW_FTR_SECTION /* * If we had interrupts soft-enabled at the point where the * DSI/ISI occurred, and an interrupt came in during hash_page, @@ -1321,12 +1336,14 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SLB) ld r3,SOFTE(r1) bl .local_irq_restore b 11f -#else +END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) +#endif +BEGIN_FW_FTR_SECTION beq fast_exception_return /* Return from exception on success */ ble- 12f /* Failure return from hash_page */ /* fall through */ -#endif +END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES) /* Here we have a page fault that hash_page can't handle. */ _GLOBAL(handle_page_fault) @@ -1861,7 +1878,9 @@ _GLOBAL(__secondary_start) LOAD_REG_ADDR(r3, .start_secondary_prolog) LOAD_REG_IMMEDIATE(r4, MSR_KERNEL) #ifdef DO_SOFT_DISABLE +BEGIN_FW_FTR_SECTION ori r4,r4,MSR_EE +END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) #endif mtspr SPRN_SRR0,r3 mtspr SPRN_SRR1,r4 @@ -1986,6 +2005,7 @@ _STATIC(start_here_common) */ li r3,0 bl .do_cpu_ftr_fixups + bl .do_fw_ftr_fixups /* ptr to current */ LOAD_REG_IMMEDIATE(r4, init_task) @@ -2000,11 +2020,13 @@ _STATIC(start_here_common) /* Load up the kernel context */ 5: #ifdef DO_SOFT_DISABLE +BEGIN_FW_FTR_SECTION li r5,0 stb r5,PACAPROCENABLED(r13) /* Soft Disabled */ mfmsr r5 ori r5,r5,MSR_EE /* Hard Enabled */ mtmsrd r5 +END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) #endif bl .start_kernel diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S index e3ed21cd3d9..465a7641cd0 100644 --- a/arch/powerpc/kernel/misc_64.S +++ b/arch/powerpc/kernel/misc_64.S @@ -325,6 +325,52 @@ _GLOBAL(do_cpu_ftr_fixups) isync b 1b +/* + * do_fw_ftr_fixups - goes through the list of firmware feature fixups + * and writes nop's over sections of code that don't apply for this firmware. + * r3 = data offset (not changed) + */ +_GLOBAL(do_fw_ftr_fixups) + /* Get firmware features */ + LOAD_REG_IMMEDIATE(r6,powerpc_firmware_features) + sub r6,r6,r3 + ld r4,0(r6) + /* Get the fixup table */ + LOAD_REG_IMMEDIATE(r6,__start___fw_ftr_fixup) + sub r6,r6,r3 + LOAD_REG_IMMEDIATE(r7,__stop___fw_ftr_fixup) + sub r7,r7,r3 + /* Do the fixup */ +1: cmpld r6,r7 + bgelr + addi r6,r6,32 + ld r8,-32(r6) /* mask */ + and r8,r8,r4 + ld r9,-24(r6) /* value */ + cmpld r8,r9 + beq 1b + ld r8,-16(r6) /* section begin */ + ld r9,-8(r6) /* section end */ + subf. r9,r8,r9 + beq 1b + /* write nops over the section of code */ + /* todo: if large section, add a branch at the start of it */ + srwi r9,r9,2 + mtctr r9 + sub r8,r8,r3 + lis r0,0x60000000@h /* nop */ +3: stw r0,0(r8) +BEGIN_FTR_SECTION + dcbst 0,r8 /* suboptimal, but simpler */ + sync + icbi 0,r8 +END_FTR_SECTION_IFSET(CPU_FTR_SPLIT_ID_CACHE) + addi r8,r8,4 + bdnz 3b + sync /* additional sync needed on g4 */ + isync + b 1b + #if defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE) /* * Do an IO access in real mode diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S index 02665a02130..cb0e8d46c3e 100644 --- a/arch/powerpc/kernel/vmlinux.lds.S +++ b/arch/powerpc/kernel/vmlinux.lds.S @@ -132,6 +132,14 @@ SECTIONS *(__ftr_fixup) __stop___ftr_fixup = .; } +#ifdef CONFIG_PPC64 + . = ALIGN(8); + __fw_ftr_fixup : { + __start___fw_ftr_fixup = .; + *(__fw_ftr_fixup) + __stop___fw_ftr_fixup = .; + } +#endif . = ALIGN(PAGE_SIZE); .init.ramfs : { -- cgit From 476792839467c08ddeedd8b44a7423d415b68259 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Tue, 3 Oct 2006 14:12:08 +1000 Subject: [POWERPC] Fix xmon=off and cleanup xmon initialisation My patch to make the early xmon logic work with earlier early param parsing (480f6f35a149802a94ad5c1a2673ed6ec8d2c158) breaks xmon=off. No one does this obviously as xmon rocks, but it should really work as documented. While fixing that it struck me that we could move the xmon param handling into xmon.c, and also consolidate the xmon_init()/do_early_xmon logic into xmon_setup(). This means xmon=early drops into xmon a little earlier on 32-bit, but it seems to work just fine. Tested on PSERIES and CLASSIC32. Signed-off-by: Michael Ellerman Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/setup-common.c | 25 ------------------------- arch/powerpc/kernel/setup_32.c | 8 ++------ arch/powerpc/kernel/setup_64.c | 12 ++++-------- 3 files changed, 6 insertions(+), 39 deletions(-) (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index 0af3fc1bdcc..89cfaf49d3d 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c @@ -442,31 +442,6 @@ void __init smp_setup_cpu_maps(void) } #endif /* CONFIG_SMP */ -int __initdata do_early_xmon; -#ifdef CONFIG_XMON -extern int xmon_no_auto_backtrace; - -static int __init early_xmon(char *p) -{ - /* ensure xmon is enabled */ - if (p) { - if (strncmp(p, "on", 2) == 0) - xmon_init(1); - if (strncmp(p, "off", 3) == 0) - xmon_init(0); - if (strncmp(p, "nobt", 4) == 0) - xmon_no_auto_backtrace = 1; - if (strncmp(p, "early", 5) != 0) - return 0; - } - xmon_init(1); - do_early_xmon = 1; - - return 0; -} -early_param("xmon", early_xmon); -#endif - static __init int add_pcspkr(void) { struct device_node *np; diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index 79a17795d17..191d0ab0922 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c @@ -238,12 +238,11 @@ void __init setup_arch(char **cmdline_p) smp_setup_cpu_maps(); -#ifdef CONFIG_XMON_DEFAULT - xmon_init(1); -#endif /* Register early console */ register_early_udbg_console(); + xmon_setup(); + #if defined(CONFIG_KGDB) if (ppc_md.kgdb_map_scc) ppc_md.kgdb_map_scc(); @@ -280,9 +279,6 @@ void __init setup_arch(char **cmdline_p) init_mm.end_data = (unsigned long) _edata; init_mm.brk = klimit; - if (do_early_xmon) - debugger(NULL); - /* set up the bootmem stuff with available memory */ do_init_bootmem(); if ( ppc_md.progress ) ppc_md.progress("setup_arch: bootmem", 0x3eab); diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index cda2dbe70a7..4b2e32eab9d 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -390,19 +390,15 @@ void __init setup_system(void) */ find_legacy_serial_ports(); - /* - * Initialize xmon - */ -#ifdef CONFIG_XMON_DEFAULT - xmon_init(1); -#endif /* * Register early console */ register_early_udbg_console(); - if (do_early_xmon) - debugger(NULL); + /* + * Initialize xmon + */ + xmon_setup(); check_smt_enabled(); smp_setup_cpu_maps(); -- cgit From 6c4a2501d0b9fe90882efea5541275a46cda2a1a Mon Sep 17 00:00:00 2001 From: Kim Phillips Date: Mon, 2 Oct 2006 20:10:24 -0500 Subject: [POWERPC] Add initial support for the e300c2 core Add support for the Freescale e300c2 core found in the MPC832x processor line. As far as initial kernel support is concerned, the e300c2 core is identical to the e300c1 found in the mpc834x, except that it's had its floating point unit chopped off. Signed-off-by: Kim Phillips Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/cputable.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'arch/powerpc/kernel') diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index 190a57e2076..47a613cdd77 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c @@ -763,10 +763,10 @@ struct cpu_spec cpu_specs[] = { .cpu_setup = __setup_cpu_603, .platform = "ppc603", }, - { /* e300 (a 603e core, plus some) on 83xx */ + { /* e300c1 (a 603e core, plus some) on 83xx */ .pvr_mask = 0x7fff0000, .pvr_value = 0x00830000, - .cpu_name = "e300", + .cpu_name = "e300c1", .cpu_features = CPU_FTRS_E300, .cpu_user_features = COMMON_USER, .icache_bsize = 32, @@ -774,6 +774,17 @@ struct cpu_spec cpu_specs[] = { .cpu_setup = __setup_cpu_603, .platform = "ppc603", }, + { /* e300c2 (an e300c1 core, plus some, minus FPU) on 83xx */ + .pvr_mask = 0x7fff0000, + .pvr_value = 0x00840000, + .cpu_name = "e300c2", + .cpu_features = CPU_FTRS_E300, + .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, + .icache_bsize = 32, + .dcache_bsize = 32, + .cpu_setup = __setup_cpu_603, + .platform = "ppc603", + }, { /* default match, we assume split I/D cache & TB (non-601)... */ .pvr_mask = 0x00000000, .pvr_value = 0x00000000, -- cgit