/* * Delay loops based on the OpenRISC implementation. * * Copyright (C) 2012 ARM Limited * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Author: Will Deacon */ #include #include #include #include #include /* * Default to the loop-based delay implementation. */ struct arm_delay_ops arm_delay_ops = { .delay = __loop_delay, .const_udelay = __loop_const_udelay, .udelay = __loop_udelay, }; #ifdef ARCH_HAS_READ_CURRENT_TIMER static void __timer_delay(unsigned long cycles) { cycles_t start = get_cycles(); while ((get_cycles() - start) < cycles) cpu_relax(); } static void __timer_const_udelay(unsigned long xloops) { unsigned long long loops = xloops; loops *= loops_per_jiffy; __timer_delay(loops >> UDELAY_SHIFT); } static void __timer_udelay(unsigned long usecs) { __timer_const_udelay(usecs * UDELAY_MULT); } void __init init_current_timer_delay(unsigned long freq) { pr_info("Switching to timer-based delay loop\n"); lpj_fine = freq / HZ; loops_per_jiffy = lpj_fine; arm_delay_ops.delay = __timer_delay; arm_delay_ops.const_udelay = __timer_const_udelay; arm_delay_ops.udelay = __timer_udelay; } unsigned long __cpuinit calibrate_delay_is_known(void) { return lpj_fine; } #endif