timer: Add generic udelay() implementation

Add GENERIC_UDELAY Kconfig option so that a generic
udelay() implementation is provided utilizing the
monotonic timer. That way each board/chipset doesn't
need to duplicate the same udelay(). Additionally,
assume that GENERIC_UDELAY implies init_timer()
is not required.

BUG=None
BRANCH=None
TEST=Built nyan, ryu, and rambi. May need help testing.

Change-Id: I7f511a2324b5aa5d1b2959f4519be85a6a7360e8
Signed-off-by: Patrick Georgi <pgeorgi@chromium.org>
Original-Commit-Id: 1a85fbcad778933d13eaef545135abe7e4de46ed
Original-Change-Id: Idd26de19eefc91ee3b0ceddfb1bc2152e19fd8ab
Original-Signed-off-by: Aaron Durbin <adurbin@chromium.org>
Original-Reviewed-on: https://chromium-review.googlesource.com/219719
Original-Reviewed-by: Julius Werner <jwerner@chromium.org>
Original-Reviewed-by: Furquan Shaikh <furquan@chromium.org>
Reviewed-on: http://review.coreboot.org/9334
Tested-by: build bot (Jenkins)
Reviewed-by: Patrick Georgi <pgeorgi@google.com>
This commit is contained in:
Aaron Durbin 2014-09-25 10:05:15 -05:00 committed by Patrick Georgi
parent 23b4e4c4e8
commit e5e36306a9
19 changed files with 24 additions and 240 deletions

View File

@ -360,6 +360,13 @@ config HAVE_MONOTONIC_TIMER
help help
The board/chipset provides a monotonic timer. The board/chipset provides a monotonic timer.
config GENERIC_UDELAY
def_bool n
depends on HAVE_MONOTONIC_TIMER
help
The board/chipset uses a generic udelay function utilizing the
monotonic timer.
config TIMER_QUEUE config TIMER_QUEUE
def_bool n def_bool n
depends on HAVE_MONOTONIC_TIMER depends on HAVE_MONOTONIC_TIMER

View File

@ -38,7 +38,6 @@ bootblock-y += boot.c
bootblock-y += bootblock.S bootblock-y += bootblock.S
bootblock-y += bootblock_simple.c bootblock-y += bootblock_simple.c
bootblock-y += stages.c bootblock-y += stages.c
bootblock-y += timer.c
bootblock-y += ../../lib/memcpy.c bootblock-y += ../../lib/memcpy.c
bootblock-y += ../../lib/memmove.c bootblock-y += ../../lib/memmove.c
bootblock-y += ../../lib/memset.c bootblock-y += ../../lib/memset.c
@ -64,7 +63,6 @@ ifeq ($(CONFIG_ARCH_ROMSTAGE_MIPS),y)
romstage-y += boot.c romstage-y += boot.c
romstage-$(CONFIG_EARLY_CONSOLE) += early_console.c romstage-$(CONFIG_EARLY_CONSOLE) += early_console.c
romstage-y += stages.c romstage-y += stages.c
romstage-y += timer.c
romstage-y += ../../lib/memcpy.c romstage-y += ../../lib/memcpy.c
romstage-y += ../../lib/memmove.c romstage-y += ../../lib/memmove.c
romstage-y += ../../lib/memset.c romstage-y += ../../lib/memset.c
@ -85,7 +83,6 @@ ramstage-y += ashldi3.c
ramstage-y += boot.c ramstage-y += boot.c
ramstage-y += stages.c ramstage-y += stages.c
ramstage-y += tables.c ramstage-y += tables.c
ramstage-y += timer.c
ramstage-y += ../../lib/memcpy.c ramstage-y += ../../lib/memcpy.c
ramstage-y += ../../lib/memmove.c ramstage-y += ../../lib/memmove.c
ramstage-y += ../../lib/memset.c ramstage-y += ../../lib/memset.c

View File

@ -1,31 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2014 Imagination Technologies
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <delay.h>
#include <timer.h>
void init_timer(void)
{
/* TODO */
}
void udelay(unsigned usec)
{
/* TODO */
}

View File

@ -1,7 +1,11 @@
#ifndef DELAY_H #ifndef DELAY_H
#define DELAY_H #define DELAY_H
#if IS_ENABLED(CONFIG_GENERIC_UDELAY)
static inline void init_timer(void) {}
#else
void init_timer(void); void init_timer(void);
#endif
void udelay(unsigned usecs); void udelay(unsigned usecs);
void mdelay(unsigned msecs); void mdelay(unsigned msecs);

View File

@ -22,6 +22,8 @@ bootblock-y += prog_ops.c
bootblock-y += cbfs.c cbfs_core.c bootblock-y += cbfs.c cbfs_core.c
bootblock-$(CONFIG_COMMON_CBFS_SPI_WRAPPER) += cbfs_spi.c bootblock-$(CONFIG_COMMON_CBFS_SPI_WRAPPER) += cbfs_spi.c
bootblock-$(CONFIG_GENERIC_UDELAY) += timer.c
bootblock-$(CONFIG_CONSOLE_CBMEM) += cbmem_console.c bootblock-$(CONFIG_CONSOLE_CBMEM) += cbmem_console.c
bootblock-y += memchr.c bootblock-y += memchr.c
bootblock-y += memcmp.c bootblock-y += memcmp.c
@ -61,6 +63,8 @@ romstage-$(CONFIG_ARCH_ROMSTAGE_X86_32) += gcc.c
ramstage-$(CONFIG_ARCH_RAMSTAGE_X86_32) += gcc.c ramstage-$(CONFIG_ARCH_RAMSTAGE_X86_32) += gcc.c
endif endif
romstage-$(CONFIG_GENERIC_UDELAY) += timer.c
ramstage-y += prog_ops.c ramstage-y += prog_ops.c
ramstage-y += hardwaremain.c ramstage-y += hardwaremain.c
ramstage-y += selfboot.c ramstage-y += selfboot.c
@ -89,6 +93,7 @@ ramstage-y += memrange.c
ramstage-$(CONFIG_COOP_MULTITASKING) += thread.c ramstage-$(CONFIG_COOP_MULTITASKING) += thread.c
ramstage-$(CONFIG_TIMER_QUEUE) += timer_queue.c ramstage-$(CONFIG_TIMER_QUEUE) += timer_queue.c
ramstage-$(CONFIG_TERTIARY_BOARD_ID) += tristate_gpios.c ramstage-$(CONFIG_TERTIARY_BOARD_ID) += tristate_gpios.c
ramstage-$(CONFIG_GENERIC_UDELAY) += timer.c
romstage-y += cbmem_common.c dynamic_cbmem.c romstage-y += cbmem_common.c dynamic_cbmem.c
ramstage-y += cbmem_common.c dynamic_cbmem.c ramstage-y += cbmem_common.c dynamic_cbmem.c

View File

@ -22,16 +22,12 @@
#include <delay.h> #include <delay.h>
#include <thread.h> #include <thread.h>
void init_timer(void)
{
}
void udelay(unsigned usec) void udelay(unsigned usec)
{ {
struct stopwatch sw; struct stopwatch sw;
/* /*
* As the hardware clock granularity is in microseconds pad the * As the timer granularity is in microseconds pad the
* requested delay by one to get at least >= requested usec delay. * requested delay by one to get at least >= requested usec delay.
*/ */
usec += 1; usec += 1;
@ -40,6 +36,7 @@ void udelay(unsigned usec)
return; return;
stopwatch_init_usecs_expire(&sw, usec); stopwatch_init_usecs_expire(&sw, usec);
while (!stopwatch_expired(&sw)) while (!stopwatch_expired(&sw))
; ;
} }

View File

@ -7,6 +7,8 @@ config SOC_NVIDIA_TEGRA124
select ARCH_RAMSTAGE_ARMV7 select ARCH_RAMSTAGE_ARMV7
select HAVE_UART_SPECIAL select HAVE_UART_SPECIAL
select HAVE_HARD_RESET select HAVE_HARD_RESET
select HAVE_MONOTONIC_TIMER
select GENERIC_UDELAY
select BOOTBLOCK_CONSOLE select BOOTBLOCK_CONSOLE
select ARM_BOOTBLOCK_CUSTOM select ARM_BOOTBLOCK_CUSTOM
select ARM_LPAE select ARM_LPAE

View File

@ -15,7 +15,6 @@ bootblock-$(CONFIG_SOFTWARE_I2C) += ../tegra/software_i2c.c
bootblock-y += ../tegra/pingroup.c bootblock-y += ../tegra/pingroup.c
bootblock-y += ../tegra/pinmux.c bootblock-y += ../tegra/pinmux.c
bootblock-y += ../tegra/apbmisc.c bootblock-y += ../tegra/apbmisc.c
bootblock-y += timer.c
ifeq ($(CONFIG_BOOTBLOCK_CONSOLE),y) ifeq ($(CONFIG_BOOTBLOCK_CONSOLE),y)
bootblock-$(CONFIG_DRIVERS_UART) += uart.c bootblock-$(CONFIG_DRIVERS_UART) += uart.c
endif endif
@ -25,7 +24,6 @@ verstage-y += cbfs.c
verstage-y += dma.c verstage-y += dma.c
verstage-y += monotonic_timer.c verstage-y += monotonic_timer.c
verstage-y += spi.c verstage-y += spi.c
verstage-y += timer.c
verstage-$(CONFIG_DRIVERS_UART) += uart.c verstage-$(CONFIG_DRIVERS_UART) += uart.c
verstage-y += ../tegra/gpio.c verstage-y += ../tegra/gpio.c
verstage-y += ../tegra/i2c.c verstage-y += ../tegra/i2c.c
@ -48,7 +46,6 @@ romstage-y += ../tegra/gpio.c
romstage-y += ../tegra/i2c.c romstage-y += ../tegra/i2c.c
romstage-$(CONFIG_SOFTWARE_I2C) += ../tegra/software_i2c.c romstage-$(CONFIG_SOFTWARE_I2C) += ../tegra/software_i2c.c
romstage-y += ../tegra/pinmux.c romstage-y += ../tegra/pinmux.c
romstage-y += timer.c
romstage-y += cache.c romstage-y += cache.c
romstage-$(CONFIG_DRIVERS_UART) += uart.c romstage-$(CONFIG_DRIVERS_UART) += uart.c
@ -70,7 +67,6 @@ ramstage-y += ../tegra/i2c.c
ramstage-$(CONFIG_SOFTWARE_I2C) += ../tegra/software_i2c.c ramstage-$(CONFIG_SOFTWARE_I2C) += ../tegra/software_i2c.c
ramstage-y += ../tegra/pinmux.c ramstage-y += ../tegra/pinmux.c
ramstage-y += ../tegra/usb.c ramstage-y += ../tegra/usb.c
ramstage-y += timer.c
ramstage-$(CONFIG_DRIVERS_UART) += uart.c ramstage-$(CONFIG_DRIVERS_UART) += uart.c
rmodules_$(ARCH-romstage-y)-y += monotonic_timer.c rmodules_$(ARCH-romstage-y)-y += monotonic_timer.c

View File

@ -1,53 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright 2013 Google Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <console/console.h>
#include <timer.h>
#include <delay.h>
#include <thread.h>
void init_timer(void)
{
}
/* delay x useconds */
void udelay(unsigned usec)
{
struct mono_time current, end;
if (!thread_yield_microseconds(usec))
return;
timer_monotonic_get(&current);
end = current;
mono_time_add_usecs(&end, usec);
if (mono_time_after(&current, &end)) {
printk(BIOS_EMERG, "udelay: 0x%08x is impossibly large\n",
usec);
/* There's not much we can do if usec is too big. Use a long,
* paranoid delay value and hope for the best... */
end = current;
mono_time_add_usecs(&end, USECS_PER_SEC);
}
while (mono_time_before(&current, &end))
timer_monotonic_get(&current);
}

View File

@ -8,6 +8,7 @@ config SOC_NVIDIA_TEGRA132
select BOOTBLOCK_CONSOLE select BOOTBLOCK_CONSOLE
select GIC select GIC
select HAVE_MONOTONIC_TIMER select HAVE_MONOTONIC_TIMER
select GENERIC_UDELAY
select HAVE_HARD_RESET select HAVE_HARD_RESET
select HAVE_UART_SPECIAL select HAVE_UART_SPECIAL
select HAVE_UART_MEMORY_MAPPED select HAVE_UART_MEMORY_MAPPED

View File

@ -1,7 +1,6 @@
bootblock-y += bootblock.c bootblock-y += bootblock.c
bootblock-y += bootblock_asm.S bootblock-y += bootblock_asm.S
bootblock-y += cbfs.c bootblock-y += cbfs.c
bootblock-y += timer.c
bootblock-y += clock.c bootblock-y += clock.c
bootblock-y += spi.c bootblock-y += spi.c
bootblock-y += i2c.c bootblock-y += i2c.c
@ -26,7 +25,6 @@ romstage-y += romstage_asm.S
romstage-y += addressmap.c romstage-y += addressmap.c
romstage-y += cbfs.c romstage-y += cbfs.c
romstage-y += cbmem.c romstage-y += cbmem.c
romstage-y += timer.c
romstage-y += ccplex.c romstage-y += ccplex.c
romstage-y += clock.c romstage-y += clock.c
romstage-y += cpu.c romstage-y += cpu.c
@ -53,7 +51,6 @@ ramstage-y += cbfs.c
ramstage-y += cbmem.c ramstage-y += cbmem.c
ramstage-y += cpu.c ramstage-y += cpu.c
ramstage-y += cpu_lib.S ramstage-y += cpu_lib.S
ramstage-y += timer.c
ramstage-y += clock.c ramstage-y += clock.c
ramstage-y += soc.c ramstage-y += soc.c
ramstage-y += spi.c ramstage-y += spi.c

View File

@ -26,6 +26,7 @@ config SOC_ROCKCHIP_RK3288
select ARCH_RAMSTAGE_ARMV7 select ARCH_RAMSTAGE_ARMV7
select CPU_HAS_BOOTBLOCK_INIT select CPU_HAS_BOOTBLOCK_INIT
select HAVE_MONOTONIC_TIMER select HAVE_MONOTONIC_TIMER
select GENERIC_UDELAY
select HAVE_UART_MEMORY_MAPPED select HAVE_UART_MEMORY_MAPPED
select HAVE_UART_SPECIAL select HAVE_UART_SPECIAL
select BOOTBLOCK_CONSOLE select BOOTBLOCK_CONSOLE

View File

@ -23,36 +23,9 @@
#include <soc/timer.h> #include <soc/timer.h>
#include <timer.h> #include <timer.h>
void init_timer(void)
{
}
void rk3288_init_timer(void) void rk3288_init_timer(void)
{ {
write32(TIMER_LOAD_VAL, &timer7_ptr->timer_load_count0); write32(TIMER_LOAD_VAL, &timer7_ptr->timer_load_count0);
write32(TIMER_LOAD_VAL, &timer7_ptr->timer_load_count1); write32(TIMER_LOAD_VAL, &timer7_ptr->timer_load_count1);
write32(1, &timer7_ptr->timer_ctrl_reg); write32(1, &timer7_ptr->timer_ctrl_reg);
} }
/* delay x useconds */
void udelay(unsigned usec)
{
struct mono_time current, end;
timer_monotonic_get(&current);
end = current;
mono_time_add_usecs(&end, usec);
if (mono_time_after(&current, &end)) {
printk(BIOS_EMERG, "udelay: 0x%08x is impossibly large\n",
usec);
/* There's not much we can do if usec is too big. Use a long,
* paranoid delay value and hope for the best... */
end = current;
mono_time_add_usecs(&end, USECS_PER_SEC);
}
while (mono_time_before(&current, &end))
timer_monotonic_get(&current);
}

View File

@ -5,6 +5,7 @@ config CPU_SAMSUNG_EXYNOS5250
select ARCH_RAMSTAGE_ARMV7 select ARCH_RAMSTAGE_ARMV7
select CPU_HAS_BOOTBLOCK_INIT select CPU_HAS_BOOTBLOCK_INIT
select HAVE_MONOTONIC_TIMER select HAVE_MONOTONIC_TIMER
select GENERIC_UDELAY
select HAVE_UART_SPECIAL select HAVE_UART_SPECIAL
bool bool
default n default n

View File

@ -10,7 +10,6 @@ bootblock-$(CONFIG_BOOTBLOCK_CONSOLE) += uart.c
endif endif
bootblock-y += wakeup.c bootblock-y += wakeup.c
bootblock-y += gpio.c bootblock-y += gpio.c
bootblock-$(CONFIG_BOOTBLOCK_CONSOLE) += timer.c
romstage-y += spi.c alternate_cbfs.c romstage-y += spi.c alternate_cbfs.c
romstage-y += clock.c romstage-y += clock.c
@ -24,7 +23,6 @@ romstage-y += monotonic_timer.c
romstage-$(CONFIG_DRIVERS_UART) += uart.c romstage-$(CONFIG_DRIVERS_UART) += uart.c
romstage-y += wakeup.c romstage-y += wakeup.c
romstage-y += gpio.c romstage-y += gpio.c
romstage-y += timer.c
romstage-y += trustzone.c romstage-y += trustzone.c
romstage-y += i2c.c romstage-y += i2c.c
#romstage-y += wdt.c #romstage-y += wdt.c
@ -40,7 +38,6 @@ ramstage-y += cpu.c
ramstage-y += tmu.c ramstage-y += tmu.c
ramstage-y += mct.c ramstage-y += mct.c
ramstage-y += monotonic_timer.c ramstage-y += monotonic_timer.c
ramstage-y += timer.c
ramstage-y += gpio.c ramstage-y += gpio.c
ramstage-y += i2c.c ramstage-y += i2c.c
ramstage-y += dp-reg.c ramstage-y += dp-reg.c

View File

@ -1,52 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2009 Samsung Electronics
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <console/console.h>
#include <delay.h>
#include <soc/clk.h>
#include <timer.h>
void init_timer(void)
{
/* Nothing to do because we manually
* call mct_start() in the bootblock
*/
}
/* delay x useconds */
void udelay(unsigned usec)
{
struct mono_time current, end;
timer_monotonic_get(&current);
end = current;
mono_time_add_usecs(&end, usec);
if (mono_time_after(&current, &end)) {
printk(BIOS_EMERG, "udelay: 0x%08x is impossibly large\n",
usec);
/* There's not much we can do if usec is too big. Use a long,
* paranoid delay value and hope for the best... */
end = current;
mono_time_add_usecs(&end, USECS_PER_SEC);
}
while (mono_time_before(&current, &end))
timer_monotonic_get(&current);
}

View File

@ -5,6 +5,7 @@ config CPU_SAMSUNG_EXYNOS5420
select ARCH_RAMSTAGE_ARMV7 select ARCH_RAMSTAGE_ARMV7
select CPU_HAS_BOOTBLOCK_INIT select CPU_HAS_BOOTBLOCK_INIT
select HAVE_MONOTONIC_TIMER select HAVE_MONOTONIC_TIMER
select GENERIC_UDELAY
select HAVE_UART_SPECIAL select HAVE_UART_SPECIAL
select RELOCATABLE_MODULES select RELOCATABLE_MODULES
bool bool

View File

@ -10,7 +10,6 @@ bootblock-$(CONFIG_BOOTBLOCK_CONSOLE) += uart.c
endif endif
bootblock-y += wakeup.c bootblock-y += wakeup.c
bootblock-y += gpio.c bootblock-y += gpio.c
bootblock-$(CONFIG_BOOTBLOCK_CONSOLE) += timer.c
romstage-y += spi.c alternate_cbfs.c romstage-y += spi.c alternate_cbfs.c
romstage-y += smp.c romstage-y += smp.c
@ -25,7 +24,6 @@ romstage-y += monotonic_timer.c
romstage-$(CONFIG_DRIVERS_UART) += uart.c romstage-$(CONFIG_DRIVERS_UART) += uart.c
romstage-y += wakeup.c romstage-y += wakeup.c
romstage-y += gpio.c romstage-y += gpio.c
romstage-y += timer.c
romstage-y += i2c.c romstage-y += i2c.c
#romstage-y += wdt.c #romstage-y += wdt.c
romstage-y += cbmem.c romstage-y += cbmem.c
@ -41,7 +39,6 @@ ramstage-y += cpu.c
ramstage-y += tmu.c ramstage-y += tmu.c
ramstage-y += mct.c ramstage-y += mct.c
ramstage-y += monotonic_timer.c ramstage-y += monotonic_timer.c
ramstage-y += timer.c
ramstage-y += gpio.c ramstage-y += gpio.c
ramstage-y += i2c.c ramstage-y += i2c.c
ramstage-y += dp.c dp_lowlevel.c fimd.c ramstage-y += dp.c dp_lowlevel.c fimd.c

View File

@ -1,56 +0,0 @@
/*
* This file is part of the coreboot project.
*
* Copyright (C) 2009 Samsung Electronics
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <console/console.h>
#include <delay.h>
#include <soc/clk.h>
#include <thread.h>
#include <timer.h>
void init_timer(void)
{
/* Nothing to do because we manually
* call mct_start() in the bootblock
*/
}
/* delay x useconds */
void udelay(unsigned usec)
{
struct mono_time current, end;
if (!thread_yield_microseconds(usec))
return;
timer_monotonic_get(&current);
end = current;
mono_time_add_usecs(&end, usec);
if (mono_time_after(&current, &end)) {
printk(BIOS_EMERG, "udelay: 0x%08x is impossibly large\n",
usec);
/* There's not much we can do if usec is too big. Use a long,
* paranoid delay value and hope for the best... */
end = current;
mono_time_add_usecs(&end, USECS_PER_SEC);
}
while (mono_time_before(&current, &end))
timer_monotonic_get(&current);
}