blob: 9c90b4fb1690a77c13780cffc052b2ddef8c9526 [file] [log] [blame]
/* This document is intended to provide the developer with information
* how to integrate a new OMAP Architecture into this part of the barebox tree
/** @page dev_omap_arch Texas Instrument's OMAP Platforms in barebox
This document highlights some of the factors for supporting Texas Instrument's OMAP platforms in @a barebox.
@par Table of Contents
@li @ref omap_boards
@li @ref omap_code_arch
@li @ref mach_omap
@li @ref asm_arm
@li @ref board_omap
@li @ref omap_boot
@li @ref board_boot
@section omap_boards Boards using OMAP processors
@li @subpage ti_SDP3430
@li @subpage ti_beagle
@section omap_arch Documentation for OMAP Architectures files
@li @subpage arch/arm/mach-omap/omap3_generic.c
@section omap_code_arch How is barebox OMAP specific architecture code organized?
To understand the architecture of @a barebox source code for OMAP processors, we need to understand a bit on OMAP itself.
A typical Texas Instrument's Open Multimedia Application Processor (OMAP) solution is built around ARM core with multiple on-the-silicon peripherals. It also has a TI Digital Signal Processor(DSP) and few hardware accelerators to cater to computing intensive applications such as encoder/decoders. See for further details.
Essentially, OMAP is modular with on-silicon peripherals being reused across multiple OMAP versions. @a Barebox code organization is driven by this fact.
Motivation for code organization is driven from:
@li Clear distinction between architecture and board features.
@li Code should be re-usable accross OMAP variants AND board variants.
Code is Organized into three main directories:
@li arch/arm/mach-omap -contains files for ALL peripherals which are present on board with very few exceptions. We will come to these exceptions in later sections.
@li include/asm-arm/arch-omap - contains files for ALL OMAP on-silicon peripherals. No Board specific files here please!
@li arch/arm/boards/omap - contains files for ALL boards using OMAP processors.
@section mach_omap arch/arm/mach-omap directory guidelines
It is rather simple: All common peripherals should be isolated as separate driver libraries as far as possible. Exceptions such as clock configuration code may be isolated by the following naming convention: omapX_function_name.[cS], where X belongs to the OMAP variant. The exception is for devices who have existing code locations - potentially drivers/i2c/busses and the like.
All basic devices you'd like to register should be put here with postcore_initcall from architecture files
@section asm_arm include/asm-arm/arch-omap directory guidelines
All OMAP common headers are located here. Where we have to incorporate a OMAP variant specific header, add a omapX_function_name.h.
@warning Do not add board specific header files/information here. Put them in mach-omap.
include/asm-arm/arch-omap/silicon.h contains includes for omapX-silicon.h which defines the base addresses for the peripherals on that platform. the usual convention is to use
to allow re-use.
@section board_omap arch/arm/boards/omap directory guidelines
All Board specific files go here. In u-boot, we always had to use common config file which is shared by other drivers to get serial, ethernet baseaddress etc.. we can easily use the device_d structure to handle it with @a barebox. This is more like programming for Linux kernel - it is pretty easy.
Each specific board file has board-XYZ.c and potentially and equivalent h file.
We'd potentially use device_initcall and console_initcalls as required.
@section omap_boot The OMAP boot path
The normal flow is to look for arch_init_lowlevel in the required code. This would be the first function to be called after the ARM common code boots up(arch/arm/cpu/start-arm.S), the job of boot code on OMAP platform would be to preventing watchdog timer from kicking in and spoiling all the fun, setup OMAP clocks to the high performance mode, do other architecture specific initializations. There could be some additional stuff we may need to do based on the specific OMAP we support including setting up a usable interrupt vector table etc - some parts of the code may be desired to be in C code (to let normal humans understand without being an asm junkie), in such a case, @a barebox's stack setup is not ready yet, and we may need to setup a temporary SRAM based stack prior to execution. Some things to keep in mind while handling booting code, we might be executing in eXecute In Place (XIP) mode and that only an SRAM stack is setup. Using global variables or using constructs that create function jump tables is doomed to fail as the required area might not be writable or may not be even initialized. So code in this area tends to use lots of if conditions and local variables. Having C code doing the fun part is easy to maintain, so it is advisable to push as much as possible to C functions where possible.
The responsibility of arch_init_lowlevel and related calls is to setup OMAP. No board specific initializations are to be done here.
Once this is past, the code returns back to arm common code (cpu/start-arm.S). Here Instruction and Data caches are disabled. The execution proceeds to normal board initialization.
@section board_boot The board boot path
If the proper CONFIG_MACH_DO_LOWLEVEL_INIT flag is setup, board_init_lowlevel is called. This again would call a common file arch/arm/boards/omap/platform.S which setups a temporary SRAM stack and bumps the control to board_init.
Every Board in OMAP platform can potentially define a board_init and enable defconfig in arch/arm/configs directory. The responsibility here is to setup OMAP for board configurations - this includes SDRAM configuration and pin muxing configuration.
Once this is complete, @a barebox boot process proceeds by calling init functions and finally entering shell prompt
board-XYZ file may potentially register every device it is interested in. You can check out how the code is organized in other board directories also, esentially, the method is as simple as:
static struct device_d my_little_device = {
.name = "driver_name",
.id = "some_unique_id",
.platform_data = &any_driver_specific_data,
.type = Type_of_device,
static int my_board_devices_init(void) {
/* Do Blah Blah Blah */
return register_device(&my_little_device);
You may probably be interested in calling console_initcall to get a console.. Modify arch/arm/boards/omap/Kconfig to add your OMAP board, create a defconfig, do a make C=2 to enable sparse warnings, you can potentially have a binary done in no time! if you remember to put doxygen comments in your code, you can do a make docs and get the documentation done too..