Hi Simon, On Wed, Aug 17, 2011 at 1:25 PM, Simon Glass <s...@chromium.org> wrote: > Hi, > > When U-Boot starts up it initializes all the peripherals which are > enabled This might include USB, I2C, SD/MMC, LCD, Ethernet, UARTs, > etc. > > To save time, reduce the amount of code executed and thereby improve > security, we are wanting to initialize only some peripherals at the > start. For example we might start up I2C and SC/MMC. > > Later when it becomes clear that USB and Ethernet are needed we want > to init those also. I suppose the easiest way of describing this is > that we want to have some 'level 0' init, then perhaps move to level 1 > and init peripherals at that level, then perhaps to level 2, etc. > Quite often we will only get to level 1 before jumping to the kernel.
Well technically, the device init should only be done either a) U-Boot core code needs to access the device (to read the environment for example) b) When a U-Boot command first uses the device b) When doing final init ready for the OS kernel > At the moment the U-Boot init code is spread around a bit - there are > files called board.c within arch/xx/cpu/, board/xx/ and arch/xx/lib/. > So it is hard to make this change just within a board file. Some other > files have big lists of init calls like stdio.c and serial.c. Yes, it is a mess > I am thinking of creating a way of specifying a list of peripherals > which should be inited in each level, then moving all init code into a > function which knows how to init each peripheral. Then we can call > init_level(2) for example, to start up peripherals in that level. > Perhaps level 0 would be reserved for pre-relocation init. > > I am interested in any thoughts that people have about this and > whether it might be implemented in a generally useful way. I am > assuming that a driver registration / initcall approach would be a > bridge too far for U-Boot at the moment, so I am thinking of a > function with a big 'switch' statement. I would prefer a device level 'start' and 'stop' hooks so when a command or the U-Boot core needs to use a particular device it calls device->start(), uses the device then calls device->stop(). Devices that are in use permanently (timers and console ports are prime examples), device->stop() is never called (or maybe called proir to entering the OS kernel). This would be a massive architectural change for U-Boot and leads into a 'driver framework' > The other related issue is that I notice that the arch/xxx/lib/board.c > files are different but have a lot of common code. Is there some scope > for starting a common/board.c file which slowly builds up common > functionality so that over time we end up with only the > architecture-specific code in the arch/lib/xxx/board.c? If so these > these two goals could perhaps be progressed together. Now that relocation has settled down and looks to be working in a much more platform independent manner, board_init_f() and board_init_r() should be able to be moved into /lib/ with any arch or board specific functionality carved out into init functions. Have a look at x86 and you'll see that board_init_f() and board_init_r() work in a very simlar manner to each other. I don't think this is going to be particularly difficult to implement. I am, however, still scratching my head trying to figure out how to create a simple mechanism for dynamic init sequence building (even if it is done at compile time). By this I mean a standard arch level init sequence and a way of allowing boards to insert init functions at arbitrary points in the init sequence without a mass of #ifdef's in /lib/board.c and without have each and every board having to define the whole init sequence in /board/init.c. At the moment it's done by reserving some specific points in the init sequence where U-Boot calls into the board-specific init functions. If the board has no need for such a call, it still needs to implement a do nothing stub function. I'm sure someone can come up with some clever pre-processor macro-foo to do something like this: In board/foo.c: int init_board_gpio() { /* Do Stuff */ } BOARD_INIT(init_board_leds, 214); int init_board_leds() { /* Do Stuff */ } /* Init board LEDs after the boards GPIO has been initialised */ BOARD_INIT(init_board_leds, 215); In arch/xxx/sdram.c int init_sdram() { /* Do Stuff */ } /* SDRAM gets intialised really early (but not before timers) */ BOARD_INIT(init_sdram, 10); In arch/xxx/<soc>/timer.c int init_timers() { /* Do Stuff */ } /* Timers are needed early */ BOARD_INITinit_timers, 9); You could even #define some of the steps with nice gaps between: #define INIT_STEP_CPU 1 #define INIT_STEP_TIMERS INIT_STEP_CPU + 10 #define INIT_STEP_SDARM INIT_STEP_TIMERS + 10 But maybe it's all wishful thinking Regards, Graeme _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot