static void smp_chrp_setup_cpu(int cpu_nr) { static atomic_t ready = ATOMIC_INIT(1); static volatile int frozen = 0; if (systemcfg->platform == PLATFORM_PSERIES_LPAR) { /* timebases already synced under the hypervisor. */ paca[cpu_nr].next_jiffy_update_tb = tb_last_stamp = get_tb(); if (cpu_nr == 0) { systemcfg->tb_orig_stamp = tb_last_stamp; /* Should update naca->stamp_xsec. * For now we leave it which means the time can be some * number of msecs off until someone does a settimeofday() */ } smp_tb_synchronized = 1; } else { if (cpu_nr == 0) { /* wait for all the others */ while (atomic_read(&ready) < smp_num_cpus) barrier(); atomic_set(&ready, 1); /* freeze the timebase */ rtas_call(rtas_token("freeze-time-base"), 0, 1, NULL); mb(); frozen = 1; set_tb(0, 0); paca[0].next_jiffy_update_tb = 0; smp_space_timers(smp_num_cpus); while (atomic_read(&ready) < smp_num_cpus) barrier(); /* thaw the timebase again */ rtas_call(rtas_token("thaw-time-base"), 0, 1, NULL); mb(); frozen = 0; tb_last_stamp = get_tb(); systemcfg->tb_orig_stamp = tb_last_stamp; smp_tb_synchronized = 1; } else { atomic_inc(&ready); while (!frozen) barrier(); set_tb(0, 0); mb(); atomic_inc(&ready); while (frozen) barrier(); } } if (OpenPIC_Addr) { do_openpic_setup_cpu(); } else { if (cpu_nr > 0) xics_setup_cpu(); } }
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()); }
static void __init smp_chrp_setup_cpu(int cpu_nr) { static atomic_t ready = ATOMIC_INIT(1); static volatile int frozen = 0; if (cpu_nr == 0) { /* wait for all the others */ while (atomic_read(&ready) < smp_num_cpus) barrier(); atomic_set(&ready, 1); /* freeze the timebase */ call_rtas("freeze-time-base", 0, 1, NULL); mb(); frozen = 1; /* XXX assumes this is not a 601 */ set_tb(0, 0); last_jiffy_stamp(0) = 0; while (atomic_read(&ready) < smp_num_cpus) barrier(); /* thaw the timebase again */ call_rtas("thaw-time-base", 0, 1, NULL); mb(); frozen = 0; smp_tb_synchronized = 1; } else { atomic_inc(&ready); while (!frozen) barrier(); set_tb(0, 0); last_jiffy_stamp(0) = 0; mb(); atomic_inc(&ready); while (frozen) barrier(); } if (OpenPIC_Addr) do_openpic_setup_cpu(); }
/************************************************************************** * FUNCTION: chestnut_setup_arch * * DESCRIPTION: ppc_md machine configuration callback * ****/ static void __init chestnut_setup_arch(void) { if (ppc_md.progress) ppc_md.progress("chestnut_setup_arch: enter", 0); /* init to some ~sane value until calibrate_delay() runs */ loops_per_jiffy = 50000000 / HZ; /* if the time base value is greater than bus freq/4 (the TB and * decrementer tick rate) + signed integer rollover value, we * can spend a fair amount of time waiting for the rollover to * happen. To get around this, initialize the time base register * to a "safe" value. */ set_tb(0, 0); #ifdef CONFIG_BLK_DEV_INITRD if (initrd_start) ROOT_DEV = Root_RAM0; else #endif #ifdef CONFIG_ROOT_NFS ROOT_DEV = Root_NFS; #else ROOT_DEV = Root_SDA2; #endif /* * Set up the L2CR register. */ _set_L2CR(_get_L2CR() | L2CR_L2E); chestnut_setup_bridge(); chestnut_setup_peripherals(); #ifdef CONFIG_DUMMY_CONSOLE conswitchp = &dummy_con; #endif #if defined(CONFIG_SERIAL_8250) chestnut_early_serial_map(); #endif /* Identify the system */ printk(KERN_INFO "System Identification: IBM 750FX/GX Eval Board\n"); printk(KERN_INFO "IBM 750FX/GX port (C) 2004 MontaVista Software, Inc." " ([email protected])\n"); if (ppc_md.progress) ppc_md.progress("chestnut_setup_arch: exit", 0); }
static void __init katana_setup_arch(void) { if (ppc_md.progress) ppc_md.progress("katana_setup_arch: enter", 0); set_tb(0, 0); #ifdef CONFIG_BLK_DEV_INITRD if (initrd_start) ROOT_DEV = Root_RAM0; else #endif #ifdef CONFIG_ROOT_NFS ROOT_DEV = Root_NFS; #else ROOT_DEV = Root_SDA2; #endif /* * Set up the L2CR register. * * 750FX has only L2E, L2PE (bits 2-8 are reserved) * DD2.0 has bug that requires the L2 to be in WRT mode * avoid dirty data in cache */ if (PVR_REV(mfspr(SPRN_PVR)) == 0x0200) { printk(KERN_INFO "DD2.0 detected. Setting L2 cache" "to Writethrough mode\n"); _set_L2CR(L2CR_L2E | L2CR_L2PE | L2CR_L2WT); } else _set_L2CR(L2CR_L2E | L2CR_L2PE); if (ppc_md.progress) ppc_md.progress("katana_setup_arch: calling setup_bridge", 0); katana_setup_bridge(); katana_setup_peripherals(); katana_enable_ipmi(); katana_bus_frequency = katana_bus_freq(cpld_base); printk(KERN_INFO "Artesyn Communication Products, LLC - Katana(TM)\n"); if (ppc_md.progress) ppc_md.progress("katana_setup_arch: exit", 0); }
static void __init ev64360_setup_arch(void) { if (ppc_md.progress) ppc_md.progress("ev64360_setup_arch: enter", 0); set_tb(0, 0); #ifdef CONFIG_BLK_DEV_INITRD if (initrd_start) ROOT_DEV = Root_RAM0; else #endif #ifdef CONFIG_ROOT_NFS ROOT_DEV = Root_NFS; #else ROOT_DEV = Root_SDA2; #endif /* * Set up the L2CR register. */ _set_L2CR(L2CR_L2E | L2CR_L2PE); if (ppc_md.progress) ppc_md.progress("ev64360_setup_arch: calling setup_bridge", 0); ev64360_setup_bridge(); ev64360_setup_peripherals(); ev64360_bus_frequency = ev64360_bus_freq(); printk(KERN_INFO "%s %s port (C) 2005 Lee Nicks " "([email protected])\n", BOARD_VENDOR, BOARD_MACHINE); if (ppc_md.progress) ppc_md.progress("ev64360_setup_arch: exit", 0); }
void __init smp_software_tb_sync(int cpu) { #define PASSES 4 /* 4 passes.. */ int pass; int i, j; /* stop - start will be the number of timebase ticks it takes for cpu0 * to send a message to all others and the first reponse to show up. * * ASSUMPTION: this time is similiar for all cpus * ASSUMPTION: the time to send a one-way message is ping/2 */ register unsigned long start = 0; register unsigned long stop = 0; register unsigned long temp = 0; set_tb(0, 0); /* multiple passes to get in l1 cache.. */ for (pass = 2; pass < 2+PASSES; pass++){ if (cpu == 0){ mb(); for (i = j = 1; i < smp_num_cpus; i++, j++){ /* skip stuck cpus */ while (!cpu_callin_map[j]) ++j; while (cpu_callin_map[j] != pass) barrier(); } mb(); tb_sync_flag = pass; start = get_tbl(); /* start timing */ while (tb_sync_flag) mb(); stop = get_tbl(); /* end timing */ /* theoretically, the divisor should be 2, but * I get better results on my dual mtx. someone * please report results on other smp machines.. */ tb_offset = (stop-start)/4; mb(); tb_sync_flag = pass; udelay(10); mb(); tb_sync_flag = 0; mb(); set_tb(0,0); mb(); } else { cpu_callin_map[cpu] = pass; mb(); while (!tb_sync_flag) mb(); /* wait for cpu0 */ mb(); tb_sync_flag = 0; /* send response for timing */ mb(); while (!tb_sync_flag) mb(); temp = tb_offset; /* make sure offset is loaded */ while (tb_sync_flag) mb(); set_tb(0,temp); /* now, set the timebase */ mb(); } } if (cpu == 0) { smp_tb_synchronized = 1; printk("smp_software_tb_sync: %d passes, final offset: %ld\n", PASSES, tb_offset); } /* so time.c doesn't get confused */ set_dec(tb_ticks_per_jiffy); last_jiffy_stamp(cpu) = 0; }