/* * Setup the local clock events for a CPU. */ void __cpuinit twd_timer_setup(struct clock_event_device *clk) { if (!twd_clk) twd_clk = twd_get_clock(); if (!IS_ERR_OR_NULL(twd_clk)) twd_timer_rate = clk_get_rate(twd_clk); else twd_calibrate_rate(); clk->name = "local_timer"; clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_C3STOP; clk->rating = 350; clk->set_mode = twd_set_mode; clk->set_next_event = twd_set_next_event; __get_cpu_var(twd_ce) = clk; clockevents_config_and_register(clk, twd_timer_rate, 0xf, 0xffffffff); /* Make sure our local interrupt controller has this enabled */ gic_enable_ppi(clk->irq); }
static int __cpuinit twd_timer_setup(struct clock_event_device *clk) { struct clock_event_device **this_cpu_clk; if (!twd_clk) twd_clk = twd_get_clock(); if (!IS_ERR_OR_NULL(twd_clk)) twd_timer_rate = clk_get_rate(twd_clk); else twd_calibrate_rate(); __raw_writel(0, twd_base + TWD_TIMER_CONTROL); clk->name = "local_timer"; clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_C3STOP; clk->rating = 350; clk->set_mode = twd_set_mode; clk->set_next_event = twd_set_next_event; clk->irq = twd_ppi; this_cpu_clk = __this_cpu_ptr(twd_evt); *this_cpu_clk = clk; clockevents_config_and_register(clk, twd_timer_rate, 0xf, 0xffffffff); enable_percpu_irq(clk->irq, 0); return 0; }
static int __init twd_local_timer_common_register(struct device_node *np) { int err; twd_evt = alloc_percpu(struct clock_event_device *); if (!twd_evt) { err = -ENOMEM; goto out_free; } err = request_percpu_irq(twd_ppi, twd_handler, "twd", twd_evt); if (err) { pr_err("twd: can't register interrupt %d (%d)\n", twd_ppi, err); goto out_free; } err = local_timer_register(&twd_lt_ops); if (err) goto out_irq; twd_get_clock(np); return 0; out_irq: free_percpu_irq(twd_ppi, twd_evt); out_free: iounmap(twd_base); twd_base = NULL; free_percpu(twd_evt); return err; }
static unsigned long get_smp_twd_rate(void) { if(IS_ERR_OR_NULL(twd_clk)) twd_clk=twd_get_clock(); BUG_ON(IS_ERR_OR_NULL(twd_clk)); return clk_get_rate(twd_clk); }
static int __init twd_local_timer_common_register(struct device_node *np) { int err; twd_evt = alloc_percpu(struct clock_event_device); if (!twd_evt) { err = -ENOMEM; goto out_free; } err = request_percpu_irq(twd_ppi, twd_handler, "twd", twd_evt); if (err) { pr_err("twd: can't register interrupt %d (%d)\n", twd_ppi, err); goto out_free; } err = register_cpu_notifier(&twd_timer_cpu_nb); if (err) goto out_irq; #ifndef CONFIG_ARCH_CNS3XXX twd_get_clock(np); #endif /* * Immediately configure the timer on the boot CPU, unless we need * jiffies to be incrementing to calibrate the rate in which case * setup the timer in late_time_init. */ if (twd_timer_rate) twd_timer_setup(); else late_time_init = twd_timer_setup; return 0; out_irq: free_percpu_irq(twd_ppi, twd_evt); out_free: iounmap(twd_base); twd_base = NULL; free_percpu(twd_evt); return err; }
static void __cpuinit gt_setup(unsigned long base_paddr, unsigned bits) { if ((read_cpuid_id() & 0xf00000) == 0) return; twd_clk = twd_get_clock(); if (!IS_ERR_OR_NULL(twd_clk)) twd_timer_rate = clk_get_rate(twd_clk); else twd_calibrate_rate(); common_setup_called = true; gt_base = ioremap(base_paddr, SZ_256); BUG_ON(!gt_base); /* Start global timer */ __raw_writel(1, gt_base + 0x8); tsc_info.type = IPIPE_TSC_TYPE_FREERUNNING; tsc_info.freq = twd_timer_rate; tsc_info.counter_vaddr = (unsigned long)gt_base; tsc_info.u.counter_paddr = base_paddr; switch(bits) { case 64: tsc_info.u.mask = 0xffffffffffffffffULL; break; case 32: tsc_info.u.mask = 0xffffffff; break; default: /* Only supported as a 32 bits or 64 bits */ BUG(); } __ipipe_tsc_register(&tsc_info); }
/* * Setup the local clock events for a CPU. */ static int __cpuinit twd_timer_setup(struct clock_event_device *clk) { struct clock_event_device **this_cpu_clk; int cpu = smp_processor_id(); /* * If the basic setup for this CPU has been done before don't * bother with the below. */ if (per_cpu(percpu_setup_called, cpu)) { __raw_writel(0, twd_base + TWD_TIMER_CONTROL); clockevents_register_device(*__this_cpu_ptr(twd_evt)); enable_percpu_irq(clk->irq, 0); return 0; } per_cpu(percpu_setup_called, cpu) = true; /* * This stuff only need to be done once for the entire TWD cluster * during the runtime of the system. */ if (!common_setup_called) { twd_clk = twd_get_clock(); /* * We use IS_ERR_OR_NULL() here, because if the clock stubs * are active we will get a valid clk reference which is * however NULL and will return the rate 0. In that case we * need to calibrate the rate instead. */ if (!IS_ERR_OR_NULL(twd_clk)) twd_timer_rate = clk_get_rate(twd_clk); else twd_calibrate_rate(); common_setup_called = true; } /* * The following is done once per CPU the first time .setup() is * called. */ __raw_writel(0, twd_base + TWD_TIMER_CONTROL); clk->name = "local_timer"; clk->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_C3STOP; clk->rating = 350; clk->set_mode = twd_set_mode; clk->set_next_event = twd_set_next_event; clk->irq = twd_ppi; #if defined(CONFIG_IPIPE) && defined(CONFIG_SMP) printk(KERN_INFO "I-pipe, %lu.%03lu MHz timer\n", twd_timer_rate / 1000000, (twd_timer_rate % 1000000) / 1000); clk->ipipe_timer = __this_cpu_ptr(&twd_itimer); clk->ipipe_timer->irq = clk->irq; clk->ipipe_timer->ack = twd_ack; clk->ipipe_timer->min_delay_ticks = 0xf; #endif this_cpu_clk = __this_cpu_ptr(twd_evt); *this_cpu_clk = clk; clockevents_config_and_register(clk, twd_timer_rate, 0xf, 0xffffffff); enable_percpu_irq(clk->irq, 0); return 0; }