[U-Boot] [PATCH 4/9] openrisc: Add library functions

Marek Vasut
2011-11-21T22:52:59Z

> Signed-off-by: Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>
> ---
> arch/openrisc/lib/Makefile | 47 ++++++++++++
> arch/openrisc/lib/board.c | 175
> ++++++++++++++++++++++++++++++++++++++++++++ arch/openrisc/lib/bootm.c |
> 84 +++++++++++++++++++++
> arch/openrisc/lib/timer.c | 104 ++++++++++++++++++++++++++
> 4 files changed, 410 insertions(+), 0 deletions(-)
> create mode 100644 arch/openrisc/lib/Makefile
> create mode 100644 arch/openrisc/lib/board.c
> create mode 100644 arch/openrisc/lib/bootm.c
> create mode 100644 arch/openrisc/lib/timer.c

Timer support isn't a library function but a CPU function, so move it to 3/9.

>
> diff --git a/arch/openrisc/lib/Makefile b/arch/openrisc/lib/Makefile
> new file mode 100644
> index 0000000..db3c657
> --- /dev/null
> +++ b/arch/openrisc/lib/Makefile
> @@ -0,0 +1,47 @@
> +#
> +# (C) Copyright 2003-2006
> +# Wolfgang Denk, DENX Software Engineering, wd at denx.de.
> +#
> +# See file CREDITS for list of people who contributed to this
> +# project.
> +#
> +# 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; either version 2 of
> +# the License, or (at your option) any later version.
> +#
> +# 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
> +#
> +
> +include $(TOPDIR)/config.mk
> +
> +LIB = $(obj)lib$(ARCH).o
> +
> +SOBJS-y +=
> +
> +COBJS-y += board.o
> +COBJS-y += bootm.o
> +COBJS-y += timer.o
> +
> +SRCS := $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c)
> +OBJS := $(addprefix $(obj),$(SOBJS-y) $(COBJS-y))
> +
> +$(LIB): $(obj).depend $(OBJS)
> + $(call cmd_link_o_target, $(OBJS))
> +
> +#########################################################################
> +
> +# defines $(obj).depend target
> +include $(SRCTREE)/rules.mk
> +
> +sinclude $(obj).depend
> +
> +#########################################################################
> diff --git a/arch/openrisc/lib/board.c b/arch/openrisc/lib/board.c
> new file mode 100644
> index 0000000..b033031
> --- /dev/null
> +++ b/arch/openrisc/lib/board.c
> @@ -0,0 +1,175 @@
> +/*
> + * (C) Copyright 2011
> + * Julius Baxter, julius at opencores.org
> + *
> + * (C) Copyright 2003, Psyent Corporation <www.psyent.com>
> + * Scott McNutt <smcnutt@psyent.com>
> + *
> + * (C) Copyright 2000-2002
> + * Wolfgang Denk, DENX Software Engineering, wd at denx.de.
> + *
> + *
> + * See file CREDITS for list of people who contributed to this
> + * project.
> + *
> + * 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; either version 2 of
> + * the License, or (at your option) any later version.
> + *
> + * 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
> + */
> +
> +#include <common.h>
> +#include <stdio_dev.h>
> +#include <watchdog.h>
> +#include <malloc.h>
> +#include <mmc.h>
> +#include <net.h>
> +#ifdef CONFIG_STATUS_LED
> +#include <status_led.h>
> +#endif
> +#ifdef CONFIG_CMD_NAND
> +#include <nand.h> /* cannot even include nand.h if it isnt configured */
> +#endif
> +
> +#include <timestamp.h>
> +#include <version.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +/*
> + * All attempts to come up with a "common" initialization sequence
> + * that works for all boards and architectures failed: some of the
> + * requirements are just _too_ different. To get rid of the resulting
> + * mess of board dependend #ifdef'ed code we now make the whole
> + * initialization sequence configurable to the user.
> + *
> + * The requirements for any new initalization function is simple: it
> + * receives a pointer to the "global data" structure as it's only
> + * argument, and returns an integer return code, where 0 means
> + * "continue" and != 0 means "fatal error, hang the system".
> + */
> +
> +extern int cache_init(void);
> +extern int timer_init(void);
> +
> +typedef int (init_fnc_t)(void);

What is this ?!

> +
> +/*
> + * Initialization sequence
> + */
> +
> +init_fnc_t *init_sequence[] = {
> + cache_init,
> + timer_init, /* initialize timer */
> + env_init,
> + serial_init,
> + console_init_f,
> + display_options,
> + checkcpu,
> + checkboard,
> + NULL, /* Terminate this list */
> +};
> +
> +
> +/***********************************************************************/
> +void board_init(void)
> +{
> + bd_t *bd;
> + init_fnc_t **init_fnc_ptr;
> +
> + gd = (gd_t *)CONFIG_SYS_GBL_DATA_ADDR;
> +
> + memset((void *)gd, 0, GENERATED_GBL_DATA_SIZE);
> +
> + gd->bd = (bd_t *)(gd+1); /* At end of global data */
> + gd->baudrate = CONFIG_BAUDRATE;
> + gd->cpu_clk = CONFIG_SYS_CLK_FREQ;
> +
> + bd = gd->bd;
> + bd->bi_memstart = CONFIG_SYS_SDRAM_BASE;
> + bd->bi_memsize = CONFIG_SYS_SDRAM_SIZE;
> +#ifndef CONFIG_SYS_NO_FLASH
> + bd->bi_flashstart = CONFIG_SYS_FLASH_BASE;
> +#endif
> +#if defined(CONFIG_SYS_SRAM_BASE) && defined(CONFIG_SYS_SRAM_SIZE)
> + bd->bi_sramstart = CONFIG_SYS_SRAM_BASE;
> + bd->bi_sramsize = CONFIG_SYS_SRAM_SIZE;
> +#endif
> + bd->bi_baudrate = CONFIG_BAUDRATE;
> +
> + for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) {
> + WATCHDOG_RESET();
> + if ((*init_fnc_ptr)() != 0)
> + hang();
> + }
> +
> + WATCHDOG_RESET();
> +
> + /* The Malloc area is immediately below the monitor copy in RAM */
> + mem_malloc_init(CONFIG_SYS_MALLOC_BASE, CONFIG_SYS_MALLOC_LEN);
> +
> +#ifndef CONFIG_SYS_NO_FLASH
> + WATCHDOG_RESET();
> + bd->bi_flashsize = flash_init();
> +#endif
> +
> +#ifdef CONFIG_CMD_NAND
> + puts("NAND: ");
> + nand_init();
> +#endif
> +
> +#ifdef CONFIG_GENERIC_MMC
> + puts("MMC: ");
> + mmc_initialize(bd);
> +#endif
> +
> + WATCHDOG_RESET();
> + env_relocate();
> +
> + WATCHDOG_RESET();
> + stdio_init();
> + jumptable_init();
> + console_init_r();
> +
> + WATCHDOG_RESET();
> + interrupt_init();
> +
> +#if defined(CONFIG_BOARD_LATE_INIT)
> + board_late_init();
> +#endif
> +
> +#if defined(CONFIG_CMD_NET)
> +#if defined(CONFIG_NET_MULTI)
> + puts("NET: ");
> +#endif
> + eth_initialize(bd);
> +#endif
> +
> + /* main_loop */
> + for (;;) {
> + WATCHDOG_RESET();
> + main_loop();
> + }
> +}
> +
> +
> +/***********************************************************************/
> +
> +void hang(void)
> +{
> + disable_interrupts();
> + puts("### ERROR ### Please reset board ###\n");
> + asm("l.nop 0x1"); /* Kill any simulation */

Simulation? Oh, it's an FPGA based CPU or what?

> + for (;;)
> + ;
> +}
> diff --git a/arch/openrisc/lib/bootm.c b/arch/openrisc/lib/bootm.c
> new file mode 100644
> index 0000000..2c5d9ae
> --- /dev/null
> +++ b/arch/openrisc/lib/bootm.c
> @@ -0,0 +1,84 @@
> +/*
> + * (C) Copyright 2011 Stefan Kristiansson
> <stefan.kristiansson@saunalahti.fi> + *
> + * Based on microblaze implementation by:
> + * (C) Copyright 2007 Michal Simek
> + * (C) Copyright 2004 Atmark Techno, Inc.
> + *
> + * Michal SIMEK <monstr@monstr.eu>
> + * Yasushi SHOJI <yashi@atmark-techno.com>
> + *
> + * See file CREDITS for list of people who contributed to this
> + * project.
> + *
> + * 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; either version 2 of
> + * the License, or (at your option) any later version.
> + *
> + * 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
> + */
> +
> +#include <common.h>
> +#include <command.h>
> +#include <image.h>
> +#include <u-boot/zlib.h>
> +#include <asm/byteorder.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +int do_bootm_linux(int flag, int argc, char * const argv[],
> + bootm_headers_t *images)
> +{
> + void (*kernel) (unsigned int);
> + ulong rd_data_start, rd_data_end;
> +
> + if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
> + return 1;
> +
> + int ret;
> +
> + char *of_flat_tree = NULL;
> +#if defined(CONFIG_OF_LIBFDT)
> + /* did generic code already find a device tree? */
> + if (images->ft_len)
> + of_flat_tree = images->ft_addr;
> +#endif
> +
> + kernel = (void (*)(unsigned int))images->ep;
> +
> + /* find ramdisk */
> + ret = boot_get_ramdisk(argc, argv, images, IH_ARCH_OPENRISC,
> + &rd_data_start, &rd_data_end);
> + if (ret)
> + return 1;
> +
> + show_boot_progress(15);
> +
> + if (!of_flat_tree && argc > 3)
> + of_flat_tree = (char *)simple_strtoul(argv[3], NULL, 16);
> +#ifdef DEBUG
> + printf("## Transferring control to Linux (at address 0x%08lx) " \
> + "ramdisk 0x%08lx, FDT 0x%08lx...\n",
> + (ulong) kernel, rd_data_start, (ulong) of_flat_tree);
> +#endif
> + if (dcache_status() || icache_status())
> + flush_cache((ulong)kernel, max(checkdcache(), checkicache()));
> +
> + /*
> + * Linux Kernel Parameters (passing device tree):
> + * r3: pointer to the fdt, followed by the board info data
> + */
> + kernel((unsigned int) of_flat_tree);
> + /* does not return */
> +
> + return 1;
> +}
> diff --git a/arch/openrisc/lib/timer.c b/arch/openrisc/lib/timer.c
> new file mode 100644
> index 0000000..52d2be9
> --- /dev/null
> +++ b/arch/openrisc/lib/timer.c
> @@ -0,0 +1,104 @@
> +/*
> + * (C) Copyright 2011, Stefan Kristiansson
> <stefan.kristiansson@saunalahti.fi> + * (C) Copyright 2011, Julius Baxter
> <julius@opencores.org>
> + * (C) Copyright 2003
> + * Wolfgang Denk, DENX Software Engineering, wd at denx.de.
> + *
> + * See file CREDITS for list of people who contributed to this
> + * project.
> + *
> + * 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; either version 2 of
> + * the License, or (at your option) any later version.
> + *
> + * 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
> + */
> +
> +#include <asm/system.h>
> +#include <asm/openrisc_exc.h>
> +#include <common.h>
> +
> +static ulong timestamp;
> +
> +/* how many counter cycles in a jiffy */
> +#define TIMER_COUNTER_CYCLES
> (CONFIG_SYS_CLK_FREQ/CONFIG_SYS_OPENRISC_TMR_HZ) +/* how many ms elapses
> between each timer interrupt */
> +#define TIMER_TIMESTAMP_INC (1000/CONFIG_SYS_OPENRISC_TMR_HZ)
> +/* how many cycles per ms */
> +#define TIMER_CYCLES_MS (CONFIG_SYS_CLK_FREQ/1000)
> +/* how many cycles per us */
> +#define TIMER_CYCLES_US (CONFIG_SYS_CLK_FREQ/1000000uL)
> +
> +void timer_isr(void)
> +{
> + timestamp += TIMER_TIMESTAMP_INC;
> + mtspr(SPR_TTMR, SPR_TTMR_IE | SPR_TTMR_RT |
> + (TIMER_COUNTER_CYCLES & SPR_TTMR_TP));
> +}
> +
> +int timer_init(void)
> +{
> + /* Install timer exception handler */
> + exception_install_handler(EXC_TIMER, timer_isr);
> +
> + /* Set up the timer for the first expiration. */
> + timestamp = 0;
> +
> + mtspr(SPR_TTMR, SPR_TTMR_IE | SPR_TTMR_RT |
> + (TIMER_COUNTER_CYCLES & SPR_TTMR_TP));
> +
> + /* Enable tick timer exception in supervisor register */
> + mtspr(SPR_SR, mfspr(SPR_SR) | SPR_SR_TEE);
> +
> + return 0;
> +}
> +
> +void reset_timer(void)
> +{
> + timestamp = 0;
> +
> + mtspr(SPR_TTMR, SPR_TTMR_IE | SPR_TTMR_RT |
> + (TIMER_COUNTER_CYCLES & SPR_TTMR_TP));
> +}
> +
> +/*
> + * The timer value in ms is calculated by taking the
> + * value accumulated by full timer revolutions plus the value
> + * accumulated in this period
> + */
> +ulong get_timer(ulong base)
> +{
> + return timestamp + mfspr(SPR_TTCR)/TIMER_CYCLES_MS - base;
> +}
> +
> +void set_timer(ulong t)
> +{
> + reset_timer();
> + timestamp = t;
> +}
> +
> +void __udelay(ulong usec)
> +{
> + ulong elapsed = 0;
> + ulong tick;
> + ulong last_tick;
> +
> + last_tick = mfspr(SPR_TTCR);
> + while ((elapsed / TIMER_CYCLES_US) < usec) {
> + tick = mfspr(SPR_TTCR);
> + if (tick >= last_tick)
> + elapsed += (tick - last_tick);
> + else
> + elapsed += TIMER_COUNTER_CYCLES - (last_tick - tick);
> + last_tick = tick;
> + }
> +}

I'm not sure if this conforms with current timer api, can you cross-check with
arch/arm/arm926ejs/mx28/timer.c ? That's the latest addition and should conform.

M