From patchwork Thu Aug 18 12:34:22 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Graeme Russ X-Patchwork-Id: 110515 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id A2C9FB6FD7 for ; Thu, 18 Aug 2011 22:34:51 +1000 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 0D54328082; Thu, 18 Aug 2011 14:34:48 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id UsHvOtPmG9h7; Thu, 18 Aug 2011 14:34:47 +0200 (CEST) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 0619F2807C; Thu, 18 Aug 2011 14:34:46 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 54C2D2807C for ; Thu, 18 Aug 2011 14:34:44 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id pg6RmhpHLplC for ; Thu, 18 Aug 2011 14:34:42 +0200 (CEST) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from mail-gy0-f172.google.com (mail-gy0-f172.google.com [209.85.160.172]) by theia.denx.de (Postfix) with ESMTPS id 4AFA528078 for ; Thu, 18 Aug 2011 14:34:40 +0200 (CEST) Received: by gyf3 with SMTP id 3so1293644gyf.3 for ; Thu, 18 Aug 2011 05:34:39 -0700 (PDT) Received: by 10.236.178.39 with SMTP id e27mr1789258yhm.99.1313670878943; Thu, 18 Aug 2011 05:34:38 -0700 (PDT) Received: from localhost.localdomain (d122-104-32-184.sbr6.nsw.optusnet.com.au [122.104.32.184]) by mx.google.com with ESMTPS id r28sm1159549yhm.66.2011.08.18.05.34.35 (version=SSLv3 cipher=OTHER); Thu, 18 Aug 2011 05:34:38 -0700 (PDT) From: Graeme Russ To: u-boot@lists.denx.de Date: Thu, 18 Aug 2011 22:34:22 +1000 Message-Id: <1313670862-31216-1-git-send-email-graeme.russ@gmail.com> X-Mailer: git-send-email 1.7.5.2.317.g391b14 Subject: [U-Boot] [RFC][PATCH] Replace clunky init sequence architecture X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.9 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de NOTE: This is an x86 only patch - I didn't include x86 in the patch heading because it is a proof of concept for a global patch - Sorry for the blatant etiquette violation ;) Replace the init_fnc_t *init_sequence[] style init sequence with one based on the Linux __initcall macros. Functions are declared as initialisation functions by using the new INIT_FUNC() macro. The three parameters to INIT_FUNC() are: - Type - f = pre-relocation (flash), r = post-relocation (RAM) - Sequence - Lower numbers are run first - Function - The function to call during the init sequence INIT_FUNC() creates a static variable which is a pointer to the init function to be called. Each variable is placed in a sub-section under the .initfuncs_f or .initfuncs_r sections. The sub-section name is the sequence number. There is no problem giving multiple functions the same sequence number, but the order of execution of functions with the same sequence number is undefined. The resulting raw image layout is a sequence of function pointers (much like how the command table is built) do_init_loop() simply takes a pointer to the start and end of either the initfuncs_f or initfuncs_r sections and sequentially dereferences the function pointer and calls the function. For a board to add an arbitrary initialisation function is trivial - simply add a INIT_FUNC() entry with an appropriate sequence number I imagine the sequence numbers could be #defined, but I don't exactly now what the linker will do - I use leading zeros in the sequence numbers to ensure correct ordering. This has been build and run-tested on my eNET board and works perfectly (after a few false starts) Enjoy :) --- arch/x86/cpu/cpu.c | 1 + arch/x86/cpu/sc520/sc520.c | 1 + arch/x86/cpu/sc520/sc520_sdram.c | 2 + arch/x86/cpu/sc520/sc520_timer.c | 1 + arch/x86/cpu/u-boot.lds | 10 ++++++ arch/x86/lib/board.c | 66 ++++++++++++++++---------------------- arch/x86/lib/pcat_interrupts.c | 1 + board/eNET/eNET.c | 2 + common/console.c | 1 + common/env_flash.c | 2 + common/serial.c | 1 + include/common.h | 8 ++++ 12 files changed, 58 insertions(+), 38 deletions(-) -- 1.7.5.2.317.g391b14 diff --git a/arch/x86/cpu/cpu.c b/arch/x86/cpu/cpu.c index cac12c0..610b8d8 100644 --- a/arch/x86/cpu/cpu.c +++ b/arch/x86/cpu/cpu.c @@ -119,6 +119,7 @@ int x86_cpu_init_r(void) return 0; } int cpu_init_r(void) __attribute__((weak, alias("x86_cpu_init_r"))); +INIT_FUNC(r, 010, cpu_init_r); int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { diff --git a/arch/x86/cpu/sc520/sc520.c b/arch/x86/cpu/sc520/sc520.c index e37c403..fc2996a 100644 --- a/arch/x86/cpu/sc520/sc520.c +++ b/arch/x86/cpu/sc520/sc520.c @@ -53,6 +53,7 @@ int cpu_init_f(void) return x86_cpu_init_f(); } +INIT_FUNC(f, 010, cpu_init_f); int cpu_init_r(void) { diff --git a/arch/x86/cpu/sc520/sc520_sdram.c b/arch/x86/cpu/sc520/sc520_sdram.c index f3623f5..5f836f3 100644 --- a/arch/x86/cpu/sc520/sc520_sdram.c +++ b/arch/x86/cpu/sc520/sc520_sdram.c @@ -57,6 +57,7 @@ int dram_init_f(void) return 0; } +INIT_FUNC(f, 070, dram_init_f); static inline void sc520_dummy_write(void) { @@ -530,3 +531,4 @@ int dram_init(void) return 0; } +INIT_FUNC(r, 030, dram_init); diff --git a/arch/x86/cpu/sc520/sc520_timer.c b/arch/x86/cpu/sc520/sc520_timer.c index 5cccda1..56a53bc 100644 --- a/arch/x86/cpu/sc520/sc520_timer.c +++ b/arch/x86/cpu/sc520/sc520_timer.c @@ -69,6 +69,7 @@ int timer_init(void) return 0; } +INIT_FUNC(r, 050, timer_init); /* Allow boards to override udelay implementation */ void __udelay(unsigned long usec) diff --git a/arch/x86/cpu/u-boot.lds b/arch/x86/cpu/u-boot.lds index fe28030..7b2ab7a 100644 --- a/arch/x86/cpu/u-boot.lds +++ b/arch/x86/cpu/u-boot.lds @@ -54,6 +54,16 @@ SECTIONS .got : { *(.got*) } . = ALIGN(4); + __initfuncs_r_start = .; + .initfuncs_r : { KEEP(*(SORT_BY_NAME(.initfuncs_r*))) } + __initfuncs_r_end = .; + + . = ALIGN(4); + __initfuncs_f_start = .; + .initfuncs_f : { KEEP(*(SORT_BY_NAME(.initfuncs_f*))) } + __initfuncs_f_end = .; + + . = ALIGN(4); __data_end = .; . = ALIGN(4); diff --git a/arch/x86/lib/board.c b/arch/x86/lib/board.c index b1b8680..e023f58 100644 --- a/arch/x86/lib/board.c +++ b/arch/x86/lib/board.c @@ -64,6 +64,10 @@ extern ulong __rel_dyn_start; extern ulong __rel_dyn_end; extern ulong __bss_start; extern ulong __bss_end; +extern ulong __initfuncs_f_start; +extern ulong __initfuncs_f_end; +extern ulong __initfuncs_r_start; +extern ulong __initfuncs_r_end; /************************************************************************ * Init Utilities * @@ -83,6 +87,7 @@ static int init_baudrate (void) return (0); } +INIT_FUNC(f, 040, init_baudrate); static int display_banner (void) { @@ -101,6 +106,7 @@ static int display_banner (void) return (0); } +INIT_FUNC(r, 060, display_banner); static int display_dram_config (void) { @@ -115,6 +121,7 @@ static int display_dram_config (void) return (0); } +INIT_FUNC(r, 070, display_dram_config); static void display_flash_config (ulong size) { @@ -152,34 +159,6 @@ static int copy_uboot_to_ram(void); static int clear_bss(void); static int do_elf_reloc_fixups(void); -init_fnc_t *init_sequence_f[] = { - cpu_init_f, - board_early_init_f, - env_init, - init_baudrate, - serial_init, - console_init_f, - dram_init_f, - calculate_relocation_address, - copy_uboot_to_ram, - clear_bss, - do_elf_reloc_fixups, - - NULL, -}; - -init_fnc_t *init_sequence_r[] = { - cpu_init_r, /* basic cpu dependent setup */ - board_early_init_r, /* basic board dependent setup */ - dram_init, /* configure available RAM banks */ - interrupt_init, /* set up exceptions */ - timer_init, - display_banner, - display_dram_config, - - NULL, -}; - gd_t *gd; static int calculate_relocation_address(void) @@ -201,6 +180,7 @@ static int calculate_relocation_address(void) return 0; } +INIT_FUNC(f, 080, calculate_relocation_address); static int copy_uboot_to_ram(void) { @@ -213,6 +193,7 @@ static int copy_uboot_to_ram(void) return 0; } +INIT_FUNC(f, 090, copy_uboot_to_ram); static int clear_bss(void) { @@ -227,6 +208,7 @@ static int clear_bss(void) return 0; } +INIT_FUNC(f, 100, clear_bss); static int do_elf_reloc_fixups(void) { @@ -241,18 +223,25 @@ static int do_elf_reloc_fixups(void) return 0; } +INIT_FUNC(f, 110, do_elf_reloc_fixups); + +static void do_init_loop(init_fnc_t **fnc, init_fnc_t **end) +{ + do { + if ((*fnc)() != 0) + hang(); + } while (fnc++ < end); +} /* Load U-Boot into RAM, initialize BSS, perform relocation adjustments */ void board_init_f(ulong boot_flags) { - init_fnc_t **init_fnc_ptr; + init_fnc_t **init_fnc_start = (init_fnc_t **)(&__initfuncs_f_start); + init_fnc_t **init_fnc_end = (init_fnc_t **)(&__initfuncs_f_end); gd->flags = boot_flags; - for (init_fnc_ptr = init_sequence_f; *init_fnc_ptr; ++init_fnc_ptr) { - if ((*init_fnc_ptr)() != 0) - hang(); - } + do_init_loop(init_fnc_start, --init_fnc_end); gd->flags |= GD_FLG_RELOC; @@ -269,7 +258,9 @@ void board_init_r(gd_t *id, ulong dest_addr) ulong size; static bd_t bd_data; static gd_t gd_data; - init_fnc_t **init_fnc_ptr; + + init_fnc_t **init_fnc_start = (init_fnc_t **)(&__initfuncs_r_start); + init_fnc_t **init_fnc_end = (init_fnc_t **)(&__initfuncs_r_end); show_boot_progress(0x21); @@ -289,12 +280,11 @@ void board_init_r(gd_t *id, ulong dest_addr) mem_malloc_init((((ulong)dest_addr - CONFIG_SYS_MALLOC_LEN)+3)&~3, CONFIG_SYS_MALLOC_LEN); - for (init_fnc_ptr = init_sequence_r; *init_fnc_ptr; ++init_fnc_ptr) { - if ((*init_fnc_ptr)() != 0) - hang (); - } + do_init_loop(init_fnc_start, --init_fnc_end); show_boot_progress(0x23); + + #ifdef CONFIG_SERIAL_MULTI serial_initialize(); #endif diff --git a/arch/x86/lib/pcat_interrupts.c b/arch/x86/lib/pcat_interrupts.c index 2caae20..46514b0 100644 --- a/arch/x86/lib/pcat_interrupts.c +++ b/arch/x86/lib/pcat_interrupts.c @@ -82,6 +82,7 @@ int interrupt_init(void) return 0; } +INIT_FUNC(r, 040, interrupt_init); void mask_irq(int irq) { diff --git a/board/eNET/eNET.c b/board/eNET/eNET.c index 2a5636c..f49c3a5 100644 --- a/board/eNET/eNET.c +++ b/board/eNET/eNET.c @@ -106,6 +106,7 @@ int board_early_init_f(void) return 0; } +INIT_FUNC(f, 020, board_early_init_f); static void enet_setup_pars(void) { @@ -161,6 +162,7 @@ int board_early_init_r(void) return 0; } +INIT_FUNC(r, 020, board_early_init_r); void show_boot_progress(int val) { diff --git a/common/console.c b/common/console.c index 8c650e0..559c799 100644 --- a/common/console.c +++ b/common/console.c @@ -531,6 +531,7 @@ int console_init_f(void) return 0; } +INIT_FUNC(f, 060, console_init_f); void stdio_print_current_devices(void) { diff --git a/common/env_flash.c b/common/env_flash.c index 50ca4ffa..a63c108 100644 --- a/common/env_flash.c +++ b/common/env_flash.c @@ -126,6 +126,7 @@ int env_init(void) return 0; } +INIT_FUNC(f, 030, env_init); #ifdef CMD_SAVEENV int saveenv(void) @@ -252,6 +253,7 @@ int env_init(void) gd->env_valid = 0; return 0; } +INIT_FUNC(f, 030, env_init); #ifdef CMD_SAVEENV diff --git a/common/serial.c b/common/serial.c index 995d268..5d097d8 100644 --- a/common/serial.c +++ b/common/serial.c @@ -168,6 +168,7 @@ int serial_init (void) return serial_current->init (); } +INIT_FUNC(f, 050, serial_init); void serial_setbrg (void) { diff --git a/include/common.h b/include/common.h index 12a1074..61126f1 100644 --- a/include/common.h +++ b/include/common.h @@ -39,8 +39,16 @@ typedef volatile unsigned char vu_char; #include #include #include +#include #include #include + +typedef int (*initfunc_t)(void); + +#define INIT_FUNC(stage,step,fn) \ + static initfunc_t __initfunc_ ## fn ## stage __used \ + __attribute__((__section__(".initfuncs_" #stage "." #step))) = fn + #if defined(CONFIG_PCI) && (defined(CONFIG_4xx) && !defined(CONFIG_AP1000)) #include #endif