/* Set this up early so that things like the scheduler can init * properly. We use the same cpu mask for both the present and * possible cpu map. */ void __init smp_setup_cpu_possible_map(void) { int instance, mid; instance = 0; while (!cpu_find_by_instance(instance, NULL, &mid)) { if (mid < NR_CPUS) { cpu_set(mid, phys_cpu_present_map); cpu_set(mid, cpu_present_map); } instance++; } }
/* Set this up early so that things like the scheduler can init * properly. We use the same cpu mask for both the present and * possible cpu map. */ void __init smp_setup_cpu_possible_map(void) { int instance, mid; instance = 0; while (!cpu_find_by_instance(instance, NULL, &mid)) { if (mid < NR_CPUS) { set_cpu_possible(mid, true); set_cpu_present(mid, true); } instance++; } }
void __init smp_prepare_cpus(unsigned int max_cpus) { extern void __init smp4m_boot_cpus(void); extern void __init smp4d_boot_cpus(void); int i, cpuid, extra; printk("Entering SMP Mode...\n"); extra = 0; for (i = 0; !cpu_find_by_instance(i, NULL, &cpuid); i++) { if (cpuid >= NR_CPUS) extra++; } /* */ if (extra && max_cpus > i - extra) printk("Warning: NR_CPUS is too low to start all cpus\n"); smp_store_cpu_info(boot_cpu_id); switch(sparc_cpu_model) { case sun4: printk("SUN4\n"); BUG(); break; case sun4c: printk("SUN4C\n"); BUG(); break; case sun4m: smp4m_boot_cpus(); break; case sun4d: smp4d_boot_cpus(); break; case sparc_leon: leon_boot_cpus(); break; case sun4e: printk("SUN4E\n"); BUG(); break; case sun4u: printk("SUN4U\n"); BUG(); break; default: printk("UNKNOWN!\n"); BUG(); break; } }
void __init sun4m_init_IRQ(void) { 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; } addr = of_get_property(dp, "address", &len); of_node_put(dp); if (!addr) { printk(KERN_ERR "sun4m_init_IRQ: No 'address' prop.\n"); return; } 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]; local_irq_disable(); sbus_writel(~SUN4M_INT_MASKALL, &sun4m_irq_global->mask_set); for (i = 0; !cpu_find_by_instance(i, NULL, &mid); i++) sbus_writel(~0x17fff, &sun4m_irq_percpu[mid]->clear); if (num_cpu_iregs == 4) 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); BTFIXUPSET_CALL(enable_pil_irq, sun4m_enable_pil_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(disable_pil_irq, sun4m_disable_pil_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(clear_clock_irq, sun4m_clear_clock_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(load_profile_irq, sun4m_load_profile_irq, BTFIXUPCALL_NORM); sparc_init_timers = sun4m_init_timers; #ifdef CONFIG_SMP BTFIXUPSET_CALL(set_cpu_int, sun4m_send_ipi, BTFIXUPCALL_NORM); 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. */ }
void __init sun4m_init_IRQ(void) { 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; } addr = of_get_property(dp, "address", &len); of_node_put(dp); if (!addr) { printk(KERN_ERR "sun4m_init_IRQ: No 'address' prop.\n"); return; } 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]; local_irq_disable(); sbus_writel(~SUN4M_INT_MASKALL, &sun4m_irq_global->mask_set); for (i = 0; !cpu_find_by_instance(i, NULL, &mid); i++) sbus_writel(~0x17fff, &sun4m_irq_percpu[mid]->clear); if (num_cpu_iregs == 4) sbus_writel(0, &sun4m_irq_global->interrupt_target); sparc_config.init_timers = sun4m_init_timers; sparc_config.build_device_irq = sun4m_build_device_irq; sparc_config.clock_rate = SBUS_CLOCK_RATE; sparc_config.clear_clock_irq = sun4m_clear_clock_irq; sparc_config.load_profile_irq = sun4m_load_profile_irq; /* Cannot enable interrupts until OBP ticker is disabled. */ }
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(); } 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; } 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 *) sbus_ioremap(&r, 0, PAGE_SIZE*SUN4M_NCPUS, "interrupts_percpu"); /* Map the system interrupt control registers. */ r.flags = int_regs[4].which_io; r.start = int_regs[4].phys_addr; sbus_ioremap(&r, 0, int_regs[4].reg_size, "interrupts_system"); sun4m_interrupts->set = ~SUN4M_INT_MASKALL; 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; } BTFIXUPSET_CALL(sbint_to_irq, sun4m_sbint_to_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(enable_irq, sun4m_enable_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(disable_irq, sun4m_disable_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(enable_pil_irq, sun4m_enable_pil_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(disable_pil_irq, sun4m_disable_pil_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(clear_clock_irq, sun4m_clear_clock_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(clear_profile_irq, sun4m_clear_profile_irq, BTFIXUPCALL_NORM); BTFIXUPSET_CALL(load_profile_irq, sun4m_load_profile_irq, BTFIXUPCALL_NORM); sparc_init_timers = sun4m_init_timers; #ifdef CONFIG_SMP BTFIXUPSET_CALL(set_cpu_int, sun4m_send_ipi, BTFIXUPCALL_NORM); 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. */ }
static void __init sun4m_init_timers(irqreturn_t (*counter_fn)(int, void *, struct pt_regs *)) { int reg_count, irq, cpu; struct linux_prom_registers cnt_regs[PROMREG_MAX]; int obio_node, cnt_node; struct resource r; cnt_node = 0; if((obio_node = prom_searchsiblings (prom_getchild(prom_root_node), "obio")) == 0 || (obio_node = prom_getchild (obio_node)) == 0 || (cnt_node = prom_searchsiblings (obio_node, "counter")) == 0) { prom_printf("Cannot find /obio/counter node\n"); prom_halt(); } reg_count = prom_getproperty(cnt_node, "reg", (void *) cnt_regs, sizeof(cnt_regs)); reg_count = (reg_count/sizeof(struct linux_prom_registers)); /* Apply the obio ranges to the timer registers. */ prom_apply_obio_ranges(cnt_regs, reg_count); cnt_regs[4].phys_addr = cnt_regs[reg_count-1].phys_addr; cnt_regs[4].reg_size = cnt_regs[reg_count-1].reg_size; cnt_regs[4].which_io = cnt_regs[reg_count-1].which_io; for(obio_node = 1; obio_node < 4; obio_node++) { cnt_regs[obio_node].phys_addr = cnt_regs[obio_node-1].phys_addr + PAGE_SIZE; cnt_regs[obio_node].reg_size = cnt_regs[obio_node-1].reg_size; cnt_regs[obio_node].which_io = cnt_regs[obio_node-1].which_io; } memset((char*)&r, 0, sizeof(struct resource)); /* Map the per-cpu Counter registers. */ r.flags = cnt_regs[0].which_io; r.start = cnt_regs[0].phys_addr; sun4m_timers = (struct sun4m_timer_regs *) sbus_ioremap(&r, 0, PAGE_SIZE*SUN4M_NCPUS, "sun4m_cpu_cnt"); /* Map the system Counter register. */ /* XXX Here we expect consequent calls to yeld adjusent maps. */ r.flags = cnt_regs[4].which_io; r.start = cnt_regs[4].phys_addr; sbus_ioremap(&r, 0, cnt_regs[4].reg_size, "sun4m_sys_cnt"); sun4m_timers->l10_timer_limit = (((1000000/HZ) + 1) << 10); master_l10_counter = &sun4m_timers->l10_cur_count; master_l10_limit = &sun4m_timers->l10_timer_limit; irq = request_irq(TIMER_IRQ, counter_fn, (IRQF_DISABLED | SA_STATIC_ALLOC), "timer", NULL); if (irq) { prom_printf("time_init: unable to attach IRQ%d\n",TIMER_IRQ); prom_halt(); } if (!cpu_find_by_instance(1, NULL, NULL)) { for(cpu = 0; cpu < 4; cpu++) sun4m_timers->cpu_timers[cpu].l14_timer_limit = 0; sun4m_interrupts->set = SUN4M_INT_E14; } else { sun4m_timers->cpu_timers[0].l14_timer_limit = 0; } #ifdef CONFIG_SMP { unsigned long flags; extern unsigned long lvl14_save[4]; struct tt_entry *trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (14 - 1)]; /* For SMP we use the level 14 ticker, however the bootup code * has copied the firmwares level 14 vector into boot cpu's * trap table, we must fix this now or we get squashed. */ local_irq_save(flags); trap_table->inst_one = lvl14_save[0]; trap_table->inst_two = lvl14_save[1]; trap_table->inst_three = lvl14_save[2]; trap_table->inst_four = lvl14_save[3]; local_flush_cache_all(); local_irq_restore(flags); } #endif }