From 5110bd21b8af4199b8332c0ab0b23367556653d3 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sun, 31 Aug 2008 20:59:37 -0700 Subject: sparc: remove CONFIG_SUN4 While doing some easy cleanups on the sparc code I noticed that the CONFIG_SUN4 code seems to be worse than the rest - there were some "I don't know how it should work, but the current code definitely cannot work." places. And while I have seen people running Linux on machines like a SPARCstation 5 a few years ago I don't recall having seen sun4 machines, even less ones running Linux. Signed-off-by: Adrian Bunk Signed-off-by: David S. Miller --- arch/sparc/kernel/entry.S | 54 ----------------------------------------------- 1 file changed, 54 deletions(-) (limited to 'arch/sparc/kernel/entry.S') diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S index e8cdf715a546..68689facaaae 100644 --- a/arch/sparc/kernel/entry.S +++ b/arch/sparc/kernel/entry.S @@ -20,11 +20,7 @@ #include #include #include -#ifdef CONFIG_SUN4 -#include -#else #include -#endif #include #include #include @@ -775,11 +771,7 @@ vac_linesize_patch_32: subcc %l7, 32, %l7 * Ugly, but we cant use hardware flushing on the sun4 and we'd require * two instructions (Anton) */ -#ifdef CONFIG_SUN4 -vac_hwflush_patch1_on: nop -#else vac_hwflush_patch1_on: addcc %l7, -PAGE_SIZE, %l7 -#endif vac_hwflush_patch2_on: sta %g0, [%l3 + %l7] ASI_HWFLUSHSEG @@ -798,42 +790,10 @@ vac_hwflush_patch2_on: sta %g0, [%l3 + %l7] ASI_HWFLUSHSEG ! %l7 = 1 for textfault ! We want error in %l5, vaddr in %l6 sun4c_fault: -#ifdef CONFIG_SUN4 - sethi %hi(sun4c_memerr_reg), %l4 - ld [%l4+%lo(sun4c_memerr_reg)], %l4 ! memerr ctrl reg addr - ld [%l4], %l6 ! memerr ctrl reg - ld [%l4 + 4], %l5 ! memerr vaddr reg - andcc %l6, 0x80, %g0 ! check for error type - st %g0, [%l4 + 4] ! clear the error - be 0f ! normal error - sethi %hi(AC_BUS_ERROR), %l4 ! bus err reg addr - - call prom_halt ! something weird happened - ! what exactly did happen? - ! what should we do here? - -0: or %l4, %lo(AC_BUS_ERROR), %l4 ! bus err reg addr - lduba [%l4] ASI_CONTROL, %l6 ! bus err reg - - cmp %l7, 1 ! text fault? - be 1f ! yes - nop - - ld [%l1], %l4 ! load instruction that caused fault - srl %l4, 21, %l4 - andcc %l4, 1, %g0 ! store instruction? - - be 1f ! no - sethi %hi(SUN4C_SYNC_BADWRITE), %l4 ! yep - ! %lo(SUN4C_SYNC_BADWRITE) = 0 - or %l4, %l6, %l6 ! set write bit to emulate sun4c -1: -#else sethi %hi(AC_SYNC_ERR), %l4 add %l4, 0x4, %l6 ! AC_SYNC_VA in %l6 lda [%l6] ASI_CONTROL, %l5 ! Address lda [%l4] ASI_CONTROL, %l6 ! Error, retained for a bit -#endif andn %l5, 0xfff, %l5 ! Encode all info into l7 srl %l6, 14, %l4 @@ -880,12 +840,7 @@ sun4c_fault: or %l4, %lo(swapper_pg_dir), %l4 sll %l6, 2, %l6 ld [%l4 + %l6], %l4 -#ifdef CONFIG_SUN4 - sethi %hi(PAGE_MASK), %l6 - andcc %l4, %l6, %g0 -#else andcc %l4, PAGE_MASK, %g0 -#endif be sun4c_fault_fromuser lduXa [%l5] ASI_SEGMAP, %l4 @@ -937,11 +892,7 @@ invalid_segment_patch1: ld [%l6 + 0x08], %l3 ! tmp = entry->vaddr ! Flush segment from the cache. -#ifdef CONFIG_SUN4 - sethi %hi((128 * 1024)), %l7 -#else sethi %hi((64 * 1024)), %l7 -#endif 9: vac_hwflush_patch1: vac_linesize_patch: @@ -1029,12 +980,7 @@ invalid_segment_patch2: or %l4, %lo(swapper_pg_dir), %l4 sll %l3, 2, %l3 ld [%l4 + %l3], %l4 -#ifndef CONFIG_SUN4 and %l4, PAGE_MASK, %l4 -#else - sethi %hi(PAGE_MASK), %l6 - and %l4, %l6, %l4 -#endif srl %l5, (PAGE_SHIFT - 2), %l6 and %l6, ((SUN4C_PTRS_PER_PTE - 1) << 2), %l6 -- cgit v1.2.3 From 69c010b24560be5ca7667e94a352183e60ed205e Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 19 Sep 2008 21:17:43 -0700 Subject: sparc32: Use PROM device probing for sun4m irq registers. Signed-off-by: David S. Miller --- arch/sparc/kernel/entry.S | 40 +++++------ arch/sparc/kernel/sun4m_irq.c | 163 ++++++++++++++---------------------------- 2 files changed, 74 insertions(+), 129 deletions(-) (limited to 'arch/sparc/kernel/entry.S') diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S index 68689facaaae..faf9ccd9ef5d 100644 --- a/arch/sparc/kernel/entry.S +++ b/arch/sparc/kernel/entry.S @@ -272,17 +272,18 @@ smp4m_ticker: */ maybe_smp4m_msg: GET_PROCESSOR4M_ID(o3) - set sun4m_interrupts, %l5 - ld [%l5], %o5 + sethi %hi(sun4m_irq_percpu), %l5 + sll %o3, 2, %o3 + or %l5, %lo(sun4m_irq_percpu), %o5 sethi %hi(0x40000000), %o2 - sll %o3, 12, %o3 ld [%o5 + %o3], %o1 - andcc %o1, %o2, %g0 + ld [%o1 + 0x00], %o3 ! sun4m_irq_percpu[cpu]->pending + andcc %o3, %o2, %g0 be,a smp4m_ticker cmp %l7, 14 - st %o2, [%o5 + 0x4] + st %o2, [%o1 + 0x04] ! sun4m_irq_percpu[cpu]->clear=0x40000000 WRITE_PAUSE - ld [%o5], %g0 + ld [%o1 + 0x00], %g0 ! sun4m_irq_percpu[cpu]->pending WRITE_PAUSE or %l0, PSR_PIL, %l4 wr %l4, 0x0, %psr @@ -300,16 +301,16 @@ linux_trap_ipi15_sun4m: SAVE_ALL sethi %hi(0x80000000), %o2 GET_PROCESSOR4M_ID(o0) - set sun4m_interrupts, %l5 - ld [%l5], %o5 - sll %o0, 12, %o0 - add %o5, %o0, %o5 - ld [%o5], %o3 + sethi %hi(sun4m_irq_percpu), %l5 + or %l5, %lo(sun4m_irq_percpu), %o5 + sll %o0, 2, %o0 + ld [%o5 + %o0], %o5 + ld [%o5 + 0x00], %o3 ! sun4m_irq_percpu[cpu]->pending andcc %o3, %o2, %g0 be 1f ! Must be an NMI async memory error - st %o2, [%o5 + 4] + st %o2, [%o5 + 0x04] ! sun4m_irq_percpu[cpu]->clear=0x80000000 WRITE_PAUSE - ld [%o5], %g0 + ld [%o5 + 0x00], %g0 ! sun4m_irq_percpu[cpu]->pending WRITE_PAUSE or %l0, PSR_PIL, %l4 wr %l4, 0x0, %psr @@ -323,12 +324,11 @@ linux_trap_ipi15_sun4m: 1: /* NMI async memory error handling. */ sethi %hi(0x80000000), %l4 - sethi %hi(0x4000), %o3 - sub %o5, %o0, %o5 - add %o5, %o3, %l5 - st %l4, [%l5 + 0xc] + sethi %hi(sun4m_irq_global), %o5 + ld [%o5 + %lo(sun4m_irq_global)], %l5 + st %l4, [%l5 + 0x0c] ! sun4m_irq_global->mask_set=0x80000000 WRITE_PAUSE - ld [%l5], %g0 + ld [%l5 + 0x00], %g0 ! sun4m_irq_global->pending WRITE_PAUSE or %l0, PSR_PIL, %l4 wr %l4, 0x0, %psr @@ -337,9 +337,9 @@ linux_trap_ipi15_sun4m: WRITE_PAUSE call sun4m_nmi nop - st %l4, [%l5 + 0x8] + st %l4, [%l5 + 0x08] ! sun4m_irq_global->mask_clear=0x80000000 WRITE_PAUSE - ld [%l5], %g0 + ld [%l5 + 0x00], %g0 ! sun4m_irq_global->pending WRITE_PAUSE RESTORE_ALL diff --git a/arch/sparc/kernel/sun4m_irq.c b/arch/sparc/kernel/sun4m_irq.c index 5b17146f0c1f..39d40e96d396 100644 --- a/arch/sparc/kernel/sun4m_irq.c +++ b/arch/sparc/kernel/sun4m_irq.c @@ -41,53 +41,25 @@ #include "irq.h" -/* On the sun4m, just like the timers, we have both per-cpu and master - * interrupt registers. - */ - -/* These registers are used for sending/receiving irqs from/to - * different cpu's. - */ -struct sun4m_intreg_percpu { - unsigned int tbt; /* Interrupts still pending for this cpu. */ - - /* These next two registers are WRITE-ONLY and are only - * "on bit" sensitive, "off bits" written have NO affect. - */ - unsigned int clear; /* Clear this cpus irqs here. */ - unsigned int set; /* Set this cpus irqs here. */ - unsigned char space[PAGE_SIZE - 12]; +struct sun4m_irq_percpu { + u32 pending; + u32 clear; + u32 set; }; -/* - * djhr - * Actually the clear and set fields in this struct are misleading.. - * according to the SLAVIO manual (and the same applies for the SEC) - * the clear field clears bits in the mask which will ENABLE that IRQ - * the set field sets bits in the mask to DISABLE the IRQ. - * - * Also the undirected_xx address in the SLAVIO is defined as - * RESERVED and write only.. - * - * DAVEM_NOTE: The SLAVIO only specifies behavior on uniprocessor - * sun4m machines, for MP the layout makes more sense. - */ -struct sun4m_intregs { - struct sun4m_intreg_percpu cpu_intregs[SUN4M_NCPUS]; - unsigned int tbt; /* IRQ's that are still pending. */ - unsigned int irqs; /* Master IRQ bits. */ - - /* Again, like the above, two these registers are WRITE-ONLY. */ - unsigned int clear; /* Clear master IRQ's by setting bits here. */ - unsigned int set; /* Set master IRQ's by setting bits here. */ - - /* This register is both READ and WRITE. */ - unsigned int undirected_target; /* Which cpu gets undirected irqs. */ +struct sun4m_irq_global { + u32 pending; + u32 mask; + u32 mask_clear; + u32 mask_set; + u32 interrupt_target; }; -static unsigned long dummy; +/* Code in entry.S needs to get at these register mappings. */ +struct sun4m_irq_percpu __iomem *sun4m_irq_percpu[SUN4M_NCPUS]; +struct sun4m_irq_global __iomem *sun4m_irq_global; -struct sun4m_intregs *sun4m_interrupts; +static unsigned long dummy; unsigned long *irq_rcvreg = &dummy; /* Dave Redman (djhr@tadpole.co.uk) @@ -182,9 +154,9 @@ static void sun4m_disable_irq(unsigned int irq_nr) mask = sun4m_get_irqmask(irq_nr); local_irq_save(flags); if (irq_nr > 15) - sun4m_interrupts->set = mask; + sbus_writel(mask, &sun4m_irq_global->mask_set); else - sun4m_interrupts->cpu_intregs[cpu].set = mask; + sbus_writel(mask, &sun4m_irq_percpu[cpu]->set); local_irq_restore(flags); } @@ -201,13 +173,13 @@ static void sun4m_enable_irq(unsigned int irq_nr) mask = sun4m_get_irqmask(irq_nr); local_irq_save(flags); if (irq_nr > 15) - sun4m_interrupts->clear = mask; + sbus_writel(mask, &sun4m_irq_global->mask_clear); else - sun4m_interrupts->cpu_intregs[cpu].clear = mask; + sbus_writel(mask, &sun4m_irq_percpu[cpu]->clear); local_irq_restore(flags); } else { local_irq_save(flags); - sun4m_interrupts->clear = SUN4M_INT_FLOPPY; + sbus_writel(SUN4M_INT_FLOPPY, &sun4m_irq_global->mask_clear); local_irq_restore(flags); } } @@ -236,34 +208,30 @@ static unsigned long cpu_pil_to_imask[16] = { */ static void sun4m_disable_pil_irq(unsigned int pil) { - sun4m_interrupts->set = cpu_pil_to_imask[pil]; + sbus_writel(cpu_pil_to_imask[pil], &sun4m_irq_global->mask_set); } static void sun4m_enable_pil_irq(unsigned int pil) { - sun4m_interrupts->clear = cpu_pil_to_imask[pil]; + sbus_writel(cpu_pil_to_imask[pil], &sun4m_irq_global->mask_clear); } #ifdef CONFIG_SMP static void sun4m_send_ipi(int cpu, int level) { - unsigned long mask; - - mask = sun4m_get_irqmask(level); - sun4m_interrupts->cpu_intregs[cpu].set = mask; + unsigned long mask = sun4m_get_irqmask(level); + sbus_writel(mask, &sun4m_irq_percpu[cpu]->set); } static void sun4m_clear_ipi(int cpu, int level) { - unsigned long mask; - - mask = sun4m_get_irqmask(level); - sun4m_interrupts->cpu_intregs[cpu].clear = mask; + unsigned long mask = sun4m_get_irqmask(level); + sbus_writel(mask, &sun4m_irq_percpu[cpu]->clear); } static void sun4m_set_udt(int cpu) { - sun4m_interrupts->undirected_target = cpu; + sbus_writel(cpu, &sun4m_irq_global->interrupt_target); } #endif @@ -347,7 +315,7 @@ static void __init sun4m_init_timers(irq_handler_t counter_fn) for (i = 0; i < num_cpu_timers; i++) sbus_writel(0, &timers_percpu[i]->l14_limit); if (num_cpu_timers == 4) - sbus_writel(SUN4M_INT_E14, &sun4m_interrupts->set); + sbus_writel(SUN4M_INT_E14, &sun4m_irq_global->mask_set); #ifdef CONFIG_SMP { @@ -372,62 +340,38 @@ static void __init sun4m_init_timers(irq_handler_t counter_fn) void __init sun4m_init_IRQ(void) { - int ie_node,i; - struct linux_prom_registers int_regs[PROMREG_MAX]; - int num_regs; - struct resource r; - int mid; - - local_irq_disable(); - if((ie_node = prom_searchsiblings(prom_getchild(prom_root_node), "obio")) == 0 || - (ie_node = prom_getchild (ie_node)) == 0 || - (ie_node = prom_searchsiblings (ie_node, "interrupt")) == 0) { - prom_printf("Cannot find /obio/interrupt node\n"); - prom_halt(); + struct device_node *dp = of_find_node_by_name(NULL, "interrupt"); + int len, i, mid, num_cpu_iregs; + const u32 *addr; + + if (!dp) { + printk(KERN_ERR "sun4m_init_IRQ: No 'interrupt' node.\n"); + return; } - num_regs = prom_getproperty(ie_node, "reg", (char *) int_regs, - sizeof(int_regs)); - num_regs = (num_regs/sizeof(struct linux_prom_registers)); - - /* Apply the obio ranges to these registers. */ - prom_apply_obio_ranges(int_regs, num_regs); - - int_regs[4].phys_addr = int_regs[num_regs-1].phys_addr; - int_regs[4].reg_size = int_regs[num_regs-1].reg_size; - int_regs[4].which_io = int_regs[num_regs-1].which_io; - for(ie_node = 1; ie_node < 4; ie_node++) { - int_regs[ie_node].phys_addr = int_regs[ie_node-1].phys_addr + PAGE_SIZE; - int_regs[ie_node].reg_size = int_regs[ie_node-1].reg_size; - int_regs[ie_node].which_io = int_regs[ie_node-1].which_io; + + addr = of_get_property(dp, "address", &len); + if (!addr) { + printk(KERN_ERR "sun4m_init_IRQ: No 'address' prop.\n"); + return; } - memset((char *)&r, 0, sizeof(struct resource)); - /* Map the interrupt registers for all possible cpus. */ - r.flags = int_regs[0].which_io; - r.start = int_regs[0].phys_addr; - sun4m_interrupts = (struct sun4m_intregs *) of_ioremap(&r, 0, - PAGE_SIZE*SUN4M_NCPUS, "interrupts_percpu"); + num_cpu_iregs = (len / sizeof(u32)) - 1; + for (i = 0; i < num_cpu_iregs; i++) { + sun4m_irq_percpu[i] = (void __iomem *) + (unsigned long) addr[i]; + } + sun4m_irq_global = (void __iomem *) + (unsigned long) addr[num_cpu_iregs]; - /* Map the system interrupt control registers. */ - r.flags = int_regs[4].which_io; - r.start = int_regs[4].phys_addr; - of_ioremap(&r, 0, int_regs[4].reg_size, "interrupts_system"); + local_irq_disable(); - sun4m_interrupts->set = ~SUN4M_INT_MASKALL; + sbus_writel(~SUN4M_INT_MASKALL, &sun4m_irq_global->mask_set); for (i = 0; !cpu_find_by_instance(i, NULL, &mid); i++) - sun4m_interrupts->cpu_intregs[mid].clear = ~0x17fff; - - if (!cpu_find_by_instance(1, NULL, NULL)) { - /* system wide interrupts go to cpu 0, this should always - * be safe because it is guaranteed to be fitted or OBP doesn't - * come up - * - * Not sure, but writing here on SLAVIO systems may puke - * so I don't do it unless there is more than 1 cpu. - */ - irq_rcvreg = (unsigned long *) - &sun4m_interrupts->undirected_target; - sun4m_interrupts->undirected_target = 0; + sbus_writel(~0x17fff, &sun4m_irq_percpu[mid]->clear); + + if (num_cpu_iregs == 4) { + irq_rcvreg = (unsigned long *) &sun4m_irq_global->interrupt_target; + sbus_writel(0, &sun4m_irq_global->interrupt_target); } BTFIXUPSET_CALL(enable_irq, sun4m_enable_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(disable_irq, sun4m_disable_irq, BTFIXUPCALL_NORM); @@ -442,5 +386,6 @@ void __init sun4m_init_IRQ(void) BTFIXUPSET_CALL(clear_cpu_int, sun4m_clear_ipi, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(set_irq_udt, sun4m_set_udt, BTFIXUPCALL_NORM); #endif + /* Cannot enable interrupts until OBP ticker is disabled. */ } -- cgit v1.2.3