/* * Smp support for CHRP machines. * * Written by Cort Dougan (cort@cs.nmt.edu) borrowing a great * deal of code from the sparc and intel versions. * * Copyright (C) 1999 Cort Dougan * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include extern unsigned long smp_chrp_cpu_nr; static int __init smp_chrp_probe(void) { struct device_node *cpus = NULL; unsigned int *reg; int reglen; int ncpus = 0; int cpuid; unsigned int phys; /* Count CPUs in the device-tree */ cpuid = 1; /* the boot cpu is logical cpu 0 */ while ((cpus = of_find_node_by_type(cpus, "cpu")) != NULL) { phys = ncpus; reg = (unsigned int *) get_property(cpus, "reg", ®len); if (reg && reglen >= sizeof(unsigned int)) /* hmmm, not having a reg property would be bad */ phys = *reg; if (phys != boot_cpuid_phys) { set_hard_smp_processor_id(cpuid, phys); ++cpuid; } ++ncpus; } printk(KERN_INFO "CHRP SMP probe found %d cpus\n", ncpus); /* Nothing more to do if less than 2 of them */ if (ncpus <= 1) return 1; mpic_request_ipis(); return ncpus; } static void __devinit smp_chrp_kick_cpu(int nr) { *(unsigned long *)KERNELBASE = nr; asm volatile("dcbf 0,%0"::"r"(KERNELBASE):"memory"); } static void __devinit smp_chrp_setup_cpu(int cpu_nr) { mpic_setup_this_cpu(); } static DEFINE_SPINLOCK(timebase_lock); static unsigned int timebase_upper = 0, timebase_lower = 0; void __devinit smp_chrp_give_timebase(void) { spin_lock(&timebase_lock); rtas_call(rtas_token("freeze-time-base"), 0, 1, NULL); timebase_upper = get_tbu(); timebase_lower = get_tbl(); spin_unlock(&timebase_lock); while (timebase_upper || timebase_lower) barrier(); rtas_call(rtas_token("thaw-time-base"), 0, 1, NULL); } void __devinit smp_chrp_take_timebase(void) { while (!(timebase_upper || timebase_lower)) barrier(); spin_lock(&timebase_lock); set_tb(timebase_upper, timebase_lower); timebase_upper = 0; timebase_lower = 0; spin_unlock(&timebase_lock); printk("CPU %i taken timebase\n", smp_processor_id()); } /* CHRP with openpic */ struct smp_ops_t chrp_smp_ops = { .message_pass = smp_mpic_message_pass, .probe = smp_chrp_probe, .kick_cpu = smp_chrp_kick_cpu, .setup_cpu = smp_chrp_setup_cpu, .give_timebase = smp_chrp_give_timebase, .take_timebase = smp_chrp_take_timebase, };