u boot porting guide for soc
TRANSCRIPT
U-boot porting guide for SoC. Take NDS32 architecture as an example.
Macpaul Lin macpaul <at> gmail.com
2012/Jan/13
Outline
• Introduction.• Directory structure of u-boot.• Architecture and SoC related parts.• Board specific files.• Configuration files.• Device driver related parts.• Documents and miscs.• Debug techniques.• Commit techniques.• Debug techniques.• Summary.
Introduction
• This presentation tell you how to port u-boot for a SoC chip.– This presentation is based on NDS32 architecture CP
U core.– This presentation is based on release ftp://ftp.denx.de
/pub/u-boot/u-boot-2011.12.tar.bz2
• You will need to read the bootstrap process of u-boot as your background to continue on this slide.
• CPU and memory controller (lowlevel_init.S) setup procedure didn’t covered in this slide.
Introduction
• The software framework of u-boot follows Linux’s category and directory placement concepts.
• u-boot uses the following terminologies to identify which SoC and board to be build.
• boards.cfg– Target– ARCH– CPU– Board name– Vendor– SoC– Options
Directory structure of u-boot.u-boot
|-- api|-- arch|-- board|-- common|-- disk|-- doc|-- drivers|-- examples|-- fs|-- include|-- lib|-- mmc_spl|-- nand_spl|-- net|-- onenand_ipl|-- post|-- spl`-- tools
• api– API for standalone applications.
• arch– Architecture and SoC related basics.
• board– Board setup and configuration relatives.
• common– Commands and some middleware.
• drivers– Middleware and APIs for peripherals, as well
as device drivers are included.• fs
– Supported various filesystems.• include:
– Board configuration files and common include headers.
• lib– Common libraries such as sorting, compress,
crc, hashtable, etc.• net
– Protocol stack of network library and network APIs.
• tools:– Miscellaneous supporting tools.
Directory structure ARCH – CPU/SoC
arch/nds32/cpu`-- n1213 |-- Makefile |-- ag101 | |-- Makefile | |-- asm-offsets.c | |-- cpu.c | |-- lowlevel_init.S | |-- timer.c | `-- watchdog.S |-- ag102 | |-- Makefile | |-- asm-offsets.c | |-- cpu.c | |-- lowlevel_init.S | |-- timer.c | `-- watchdog.S |-- start.S `-- u-boot.lds
• ${arch}/${arch name}/${cpu type}• n1213: CPU model
(one of the configuration type of N12 CPU core family.
– start.S• Common start up (ASM code) of
n1213 cpu core.– U-boot.lds
• Common linker script of n1213 cpu core.
– ag101/• ${SoC} with peripherals funct
ions support basic operations.– ag102/
• The other ${SoC} using n1213 CPU core with peripherals functions support basic operations.
Directory structure ARCH – include headers
arch/nds32/include/`-- asm |-- arch-ag101 | `-- ag101.h |-- bitops.h |-- byteorder.h |-- cache.h |-- config.h |-- global_data.h |-- io.h |-- mach-types.h |-- macro.h |-- posix_types.h |-- processor.h |-- ptrace.h |-- string.h |-- system.h |-- types.h |-- u-boot-nds32.h |-- u-boot.h `-- unaligned.h
• asm/arch-ag101/ag101.h– Memory mapped hardware address
es.• global_data.h:
– Architecture specific configuration of register to global data structure for u-boot.
• mach-types.h– Machine model and ID for SoC a
nd variants, should be sync with Linux kernel. (as well as ARM’s)
• u-boot-nds32.h– NDS32 specific global symbol a
nd function reference for u-boot.
• u-boot.h– Board information supported by
NDS32 architecture used in u-boot.
• Other’s header files are implemented for I/O operations and byte-order swapping functions.
Directory structure ARCH – lib (common part)
arch/nds32/lib/
|-- Makefile
|-- board.c
|-- bootm.c
`-- interrupts.c
• ${arch}/${arch name}/lib– board.c
• Common initialization process for all SoC and boards.
• init_sequence()– Peripheral setup in board_init
_f().
• board_init_f()– Counting reserved stack size a
nd address before relocation and entering C environment.
• board_init_r()– Board setup and peripheral pr
obing after relocation.
• Other devices initialization wrapper. (Dispatch functions into board/${board}.c
– bootm.c• Boot from memory implementatio
n for Linux and other OS.
– interrupts.c• Generic interrupt implementati
ons of NDS32 architecture.
Directory structure Board
board/AndesTech/|-- adp-ag101| |-- Makefile| `-- adp-ag101.c|-- adp-ag101p| |-- Makefile| `-- adp-ag101p.c`-- adp-ag102 |-- Makefile `-- adp-ag102.c
• board/${vendor}– ${board name}
• C files.– On chip or on board p
eripheral setup.– Board (product model)
specific peripheral setup.
• board_init()– MACHINE_TYPE
• dram_init()– Get actual ram size.
• board_eth_init()• board_mmc_init()• pci_init()• board_init() will be called by lib/board.c
Directory structure Common
common/
|-- Makefile
|-- bedbug.c
|-- cmd_ambapp.c
|-- cmd_bdinfo.c
|-- cmd_bedbug.c
|-- cmd_bmp.c
|-- cmd_boot.c
|-- cmd_bootldr.c
...
• Common functions implemented for all SoC and all boards.– User commands.– Common API between user commands and middleware.
– “dlmalloc” memory management implementation.
– Other protocol adaptable middleware.
Directory structure Drivers
drivers/|-- bios_emulator|-- block|-- dma|-- fpga|-- gpio|-- hwmon|-- i2c|-- input|-- misc|-- mmc|-- mtd|-- net|-- pci|-- pcmcia|-- power|-- qe|-- rtc|-- serial|-- spi|-- tpm|-- twserial|-- usb|-- video`-- watchdog
• Drivers collection for middleware APIs and device drivers.– API definition and sof
tware stack of middleware.
– Device driver implemented according to APIs of specific driver category.
– ex.• drivers/mmc/mmc.c
– API and internal software middleware implemented against to MMC/SD specification.
• drivers/mmc/ftsdc010_esdhc.c
– ftsdc010 device driver hooked to mmc.c
Directory structure FS
fs/
|-- cramfs
|-- ext2
|-- fat
|-- fdos
|-- jffs2
|-- reiserfs
|-- ubifs
`-- yaffs2
• Supported file system used on– SATA– USB storage– SD cards– etc.
Directory structure Include
include/|-- andestech|-- asm-generic|-- bedbug|-- configs| |-- km| `-- manroland|-- cramfs|-- faraday|-- galileo|-- jffs2|-- linux| |-- byteorder| |-- mtd| |-- unaligned| `-- usb|-- lzma|-- mtd|-- pcmcia|-- synopsys|-- u-boot`-- usb
• Header files used for all SoC, boards, middleware and other software.
• include/configs– board configuration files.
• include/andestech– Header files of device controllers devel
op by Andestech Corporation.– Includes export functions which will be
called by device driver and other files (like board.c).
• include/faraday– Header files of device controllers devel
op by Faraday Corporation.– Includes export functions which will be
called by device driver and other files (like board.c).
• include/linux– Header files ported from Linux for gene
ric byte operations and device drivers ported from Linux.
Directory structure Tools
tools/|-- Makefile|-- aisimage.c|-- aisimage.h|-- bin2header.c|-- bmp_logo.c|-- checkpatch.pl|-- default_image.c|-- easylogo| |-- Makefile| |-- easylogo.c| |-- linux_blackfin.tga| |-- linux_logo.tga| `-- runme.sh|-- env| |-- Makefile| |-- README| |-- fw_env.c| |-- fw_env.config| |-- fw_env.h| `-- fw_env_main.c|-- envcrc.c|-- mingw_support.c|-- mingw_support.h|-- mkenvimage.c|-- mkimage.c|-- mkimage.h|-- mpc86x_clk.c|-- mxsboot.c
• Tools for integrating u-boot • checkpatch.pl
– Patch examination tool for coding style correction.
– Must use this to check your patch before sending it to mailing list.
• mkimage.c:– Tools for generating Linux bin
ary which could be booted by u-boot.
Architecture and SoC related parts
arch/nds32/cpu`-- n1213 |-- Makefile |-- ag101 | |-- Makefile | |-- asm-offsets.c | |-- cpu.c | |-- lowlevel_init.S | |-- timer.c | `-- watchdog.S
|-- ag102 | |-- Makefile | |-- asm-offsets.c | |-- cpu.c | |-- lowlevel_init.S | |-- timer.c | `-- watchdog.S |-- start.S `-- u-boot.lds
• ${arch}/${arch name}/${cpu type}• n1213: CPU model
(one of the configuration type of N12 CPU core family.
– start.S• Common start up (ASM code) of
n1213 cpu core.– U-boot.lds
• Common linker script of n1213 cpu core.
– ag101 SoC• asm-offsets.c
– C structure to ASM offset conversion file.
• cpu.c– Generic operation of this CPU co
re. (Cache, reset, etc.)• lowlevel_init.S
– Memory controller initialization code.
• watchdog.S– Disable watchdog to prevent non-
expected reset during booting secquence.
• timer.c– Timer driver and initialization
code for specific SoC.
Architecture and SoC related parts
• ag101.h– Define memory mapped
device address (base address) tables.
– Write this table at first when you start to port a SoC.
arch/nds32/include/
`-- asm
|-- arch-ag101
| `-- ag101.h
`-- arch-ag102
`-- ag102.h
ag101.h:
/* AHB Controller */#define CONFIG_FTAHBC020S_BASE
0x90100000/* Static Memory Controller (SRAM) */#define CONFIG_FTSMC020_BASE
0x90200000/* FTSDMC021 SDRAM Controller */#define CONFIG_FTSDMC021_BASE
0x90300000/* DMA Controller */#define CONFIG_FTDMAC020_BASE
0x90400000/* AHB-to-APB Bridge */#define CONFIG_FTAPBBRG020S_01_BASE
0x90500000/* LCD Controller */#define CONFIG_FTLCDC100_BASE
0x90600000
Use full model name of your peripheral devices
Architecture and SoC related parts
arch/nds32/cpu
`-- n1213
|-- Makefile
|-- ag101
| `-- asm-offsets.c
|-- ag102
| `-- asm-offsets.c
• asm-offsets.c– C structure to ASM offset con
version file.– This will be converted into “
include/generated/asm-offsets.h” automatically when compiling.
asm-offsets.c:#include <common.h>#include <linux/kbuild.h>int main(void){#ifdef CONFIG_FTSMC020 OFFSET(FTSMC020_BANK0_CR, ftsmc020, bank[0].cr); OFFSET(FTSMC020_BANK0_TPR, ftsmc020, bank[0].tpr);#endif BLANK();... return 0;}
include/generated/asm-offsets.h:#define FTSMC020_BANK0_CR (0) /* offsetof(struct ftsmc020, bank[0].cr) */#define FTSMC020_BANK0_TPR (4) /* offsetof(struct ftsmc020, bank[0].tpr) */
#define FTAHBC020S_SLAVE_BSR_6 (24) /* offsetof(struct ftahbc02s, s_bsr[6]) */#define FTAHBC020S_CR (136) /* offsetof(struct ftahbc02s, cr) */
Traditional “defined” address offsets. (in decimal bytes.)
Use the same conversion method as Linux.
Board specific files.board/AndesTech/
|-- adp-ag101
| |-- Makefile
| `-- adp-ag101.c
|-- adp-ag101p
| |-- Makefile
| `-- adp-ag101p.c
`-- adp-ag102
|-- Makefile
`-- adp-ag102.c
• board/${vendor}– ${board name}
• C files.– On chip or on board
peripheral setup.– Board (product model)
specific peripheral setup.
adp-ag101.c:int board_init(void){ ... gd->bd->bi_arch_number = MACH_TYPE_ADPAG101; gd->bd->bi_boot_params = PHYS_SDRAM_0 + 0x400;
ftsmc020_init(); /* initialize Flash */ return 0;}int board_eth_init(bd_t *bd){ return ftmac100_initialize(bd);}
Setup MACH_TYPE
Setup On-chip or Onboard Ethernet
Setup On-chip flash controller
Board specific files.board/AndesTech/
|-- adp-ag101
| |-- Makefile
| `-- adp-ag101.c
|-- adp-ag101p
| |-- Makefile
| `-- adp-ag101p.c
`-- adp-ag102
|-- Makefile
`-- adp-ag102.c
• Board_init() will be called by “arch/nds32/lib/board.c”.– Dram size configuration.– Flash initialization.– etc.
arch/nds32/lib/board.c:void board_init_r(gd_t *id, ulong dest_addr){ ... extern void malloc_bin_reloc(void);
gd = id; bd = gd->bd;
gd->flags |= GD_FLG_RELOC; /* tell others: relocation done */
monitor_flash_len = &_end - &_start; debug("monitor flash len: %08lX\n", monitor_flash_len);
board_init(); /* Setup chipselects */
Start board setup in adp-ag101.c
Configuration files.
include/configs
|-- adp-ag101.h
|-- adp-ag101p.h
`-- adp-ag102.h
adp-ag101.h:
#include <asm/arch/ag101.h>
/*
* CPU and Board Configuration Options
*/
#define CONFIG_ADP_AG101
#define CONFIG_USE_INTERRUPT
#define CONFIG_SKIP_LOWLEVEL_INIT
#ifndef CONFIG_SKIP_LOWLEVEL_INIT
#define CONFIG_MEM_REMAP
#endif
...#ifdef CONFIG_FTSMC020#include <faraday/ftsmc020.h>.../* SD (MMC) controller */#define CONFIG_MMC#define CONFIG_CMD_MMC#define CONFIG_GENERIC_MMC#define CONFIG_DOS_PARTITION#define CONFIG_FTSDC010#define CONFIG_FTSDC010_NUMBER 1#define CONFIG_CMD_FAT.../* Command line configuration. */#include <config_cmd_default.h>#define CONFIG_CMD_DATE#define CONFIG_CMD_PING...#define CONFIG_STACKSIZE (128 * 1024)...#define CONFIG_SYS_HZ 1000#define CONFIG_SYS_CLK_FREQ 48000000#define VERSION_CLOCK CONFIG_SYS
_CLK_FREQ
Enable or disable lowlevel_init
Enable or disable memory remap
Include driver functions called by adp-ag101.c
Include middleware stack
Enable user commands
Include driver for this middleware.
Enable common user commands
This must be 1000
System reference clock
Device driver related parts
drivers/net
|-- ftgmac100.c
|-- ftgmac100.h
|-- ftmac100.c
`-- ftmac100.hftgmac100.h:
/* The registers offset table of ftgmac100 */
struct ftgmac100 {
unsigned int isr; /* 0x00 */
unsigned int ier; /* 0x04 */
unsigned int mac_madr; /* 0x08 */
unsigned int mac_ladr; /* 0x0c */
...
}
...
/*
* Interrupt timer control register
*/
#define FTGMAC100_ITC_RXINT_CNT(x) (((x) & 0xf) << 0)
#define FTGMAC100_ITC_RXINT_THR(x) (((x) & 0x7) << 4)
#define FTGMAC100_ITC_RXINT_TIME_SEL (1 << 7)
ftgmac100.c:struct ftgmac100_data { struct ftgmac100_txdes txdes[PKTBUFSTX]; struct ftgmac100_rxdes rxdes[PKTBUFSRX]; int tx_index; int rx_index; int phy_addr;};int ftgmac100_initialize(bd_t *bd){ struct eth_device *dev; struct ftgmac100_data *priv; dev = malloc(sizeof *dev); memset(dev, 0, sizeof(*dev)); memset(priv, 0, sizeof(*priv));
sprintf(dev->name, "FTGMAC100"); dev->iobase = CONFIG_FTGMAC100_BASE; dev->init = ftgmac100_init; dev->halt = ftgmac100_halt;...};static int ftgmac100_recv(struct eth_device *dev){ struct ftgmac100_data *priv = dev->priv; struct ftgmac100_rxdes *curr_des; unsigned short rxlen;...};
Use structure to maintain address offsets.
Use simple format to represent bit fields in registers
Private data maintained by driver.
Register functions to middleware and API
Device driver related parts
drivers/mmc
`-- ftsdc010_esdhc.c
include/faraday
`-- ftsdc010.h
ftsdc010.h:
struct ftsdc010_mmc {
unsigned int cmd; /* 0x00 */
...
}
struct mmc_host {
struct ftsdc010_mmc *reg;
unsigned int version;
...
};
/* functions */
int ftsdc010_mmc_init(int dev_index);
ftsdc010.c:static struct mmc ftsdc010_dev[CONFIG_FTSDC010_NUMBER];static struct mmc_host ftsdc010_host[CONFIG_FTSDC010_NUMBER];
static struct ftsdc010_mmc *ftsdc010_get_base_mmc(int dev_index){ return (struct ftsdc010_mmc *)CONFIG_FTSDC010_BASE + dev_index;}int ftsdc010_mmc_init(int dev_index){ ... mmc->host_caps = MMC_MODE_4BIT | MMC_MODE_8BIT; mmc->f_min = CONFIG_SYS_CLK_FREQ / 2 / (2*128); mmc->f_max = CONFIG_SYS_CLK_FREQ / 2 / 2; ftsdc010_host[dev_index].reg = ftsdc010_get_base_mmc(dev_index); ...}
Use function to get hardware base address. DO NOT USE “volatile” to maintain address.
Exported function called by other files.ex:adp-ag101.c
Use structure to maintain address offsets.
Documents and miscs.doc/|-- README.ARM-SoC|-- README.ARM-memory-map|-- README.AVR32|-- README.AVR32-port-muxing|-- README.JFFS2|-- README.JFFS2_NAND|-- README.NDS32|-- README.N1213|-- README.ag101`-- README.ag102
README.ag101:Andes Technology SoC AG101==========================AG101 is the first SoC produced by Andes Technology using N1213…Configurations==============CONFIG_MEM_REMAP: Doing memory remap is essential for preparing some non-OS o
r RTOS applications.…CONFIG_SKIP_LOWLEVEL_INIT: If you want to boot this system from FLASH and bypass e-bios
(the other boot loader on ROM). You should undefine CONFIG_SKIP_LOWLEVEL_INIT in "include/configs/adp-ag101.h".
…Build and boot steps====================
build:1. Prepare the toolchains and make sure the $PATH to toolchains is
correct.2. Use `make adp-ag101` in u-boot root to build the image.
burn u-boot to flash:1. Make sure the MA17 (J16) is Lo.2. Make sure the dip switch SW5 is set to "0101".…
Documents and miscs.
boards.cfg
MAKEALL
MAINTAINERS
• MAKEALL– Automatically build all boards belongs to one architecture, CPU core, Vendor, etc.
Boards.cfg:# Target ARCH CPU Board name Vendor SoC Options###########################################################################################################incaip_150MHz mips mips32 incaip - incaip incaip:CPU_CLOCK_RATE=150000000qi_lb60 mips xburst qi_lb60 qiadp-ag101 nds32 n1213 adp-ag101 AndesTech ag101adp-ag101p nds32 n1213 adp-ag101p AndesTech ag101nios2-generic nios2 nios2 nios2-generic altera...MAINTAINERS:########################################################################## NDS32 Systems: ## Maintainer Name, Email Address ## Board CPU ##########################################################################Macpaul Lin <[email protected]> ADP-AG101 N1213 (AG101 SoC) ADP-AG101P N1213 (AG101P XC5 FPGA)
Commit techniques.• In order to maintain your change
s easily (based on patch rules and coding styles) we suggest the following method to maintain your branch.– Create local branch to track upstr
eam.– Use “git rebase” to maintain your
changes, do not use “git merge”.
• Keep in sync with the upstream repository by pulling it. $ git fetch git://git.denx.de/${upstream}.git
• Rebase the master, testing and any "work in progress" branches to the ${upstream}/master remote branch (which always reflect the One Repo to Rule Them All). $ git checkout master $ git rebase ${upstream}/master $ git checkout next $ git rebase master
References:--------------------------------------------------Patch rules:http://www.denx.de/wiki/U-Boot/Patches
U-Boot Design Principles:http://www.denx.de/wiki/U-Boot/DesignPrinciples
Workflow for Custodian git Repositories http://www.denx.de/wiki/U-Boot/CustodianGitTrees
Example:$ git clone git://git.denx.de/u-boot.git u-boot.git$ cd u-boot.git$ git branch working_branch$ git checkout working_branch...$ git commit –s...(new updates from upstream)$ git checkout master$ git pull$ git checkout working_branch$ git rebase master(re-apply your changes on the top of upstream)
Commit techniques.• General Patch Submission Rules
– Patches should always contain exactly one complete logical change, i. e.• Changes that contain different, unrelated modifications shall be submi
tted as separate patches, one patch per changeset.• If one logical set of modifications affects or creates several files,
all these changes shall be submitted in a single patch.• Commits should be able to do bisect.• Header files goes with (or before) C files with related functions.
master master
working_branch working_branchmaster
working_branch
mastergit rebase
Commit techniques.
master master
working workingmaster
working
mastergit rebase
master master
workingmaster
workingmaster
working
git merge
Changes will become difficult to manage on master
master working
git merge
localmaster
Commit techniques.• Patches and commit usually need to be reviewed and revis
ed back and forth.– Hence using “git merge” to track upstream is not a good ide
a and leading update problems.
working branch
merged local master
Pull new update usually cause problem.Old patches cannot be applied to new upstream update.
Debug techniques.
• Because the linking address will be adjusted in general relocation, the compiled elf file cannot be used directly for helping debug work.– The debug trick is different if u-boot did lowlev
el_init or not.– The following example is for the case we have
lowlevel_init and which should be most people will encountered.
Debug techniques.Build tips:
Remove old objects --------------------->
Cleanup dependencies (header includes) ->
Build target and redirect output ------->
Rename output to avoid debugging problem on multiple boards. ------------->
make clean &&
find ./ | grep depend | xargs rm &&
make adp-ag101p 2>&1 > make.log &&
mv u-boot.bin ubag101p.bin
Debug tips:
1. Add DEBUG to configuration file to inspect stack and relocation address.
include/configs/adp-ag101p.h:
#define DEBUG
monitor len: 00059958
ramsize: 04000000
TLB table at: 03ff0000
Top of RAM usable for U-Boot at: 03ff0000
Reserving 358k for U-Boot at: 03f96000
Reserving 520k for malloc() at: 03f14000
Reserving 64 Bytes for Board Info at: 03f13fc0
Reserving 96 Bytes for Global Data at: 03f13f60
New Stack Pointer is: 03f13f50
RAM Configuration:
Bank #0: 00000000 64 MiB
relocation Offset is: 00d96000
monitor flash len: 0000956D
Now running in RAM - U-Boot at: 03f96000
Debug techniques.
• Debug early board setup after general relocation.– You must set a break point
after the general relocation has been finished.
– Then re-align the symbol-file “u-boot” to the destination address which binary will be relocated to.
– Use gdb script to help you complete the redundant binary transmission work.
gdb_script.sh:#!/bin/shnds32le-linux-gdb u-boot --command=gdb_script.txt
gdb_script.txt:target remote ${ip}:${port}loadset symbol-reloading# break before board_init_rb start.S:269c...
Manual operation command after the 1st breakpoint:symbol-file# align the symbol-file to the address after relocationadd-symbol-file u-boot ${addr}# set break at board_init_r(), you can do single step, too.b board.c:302
DRAM
FLASH/ROM
U-boot
U-boot
reloU-boot
lowlevel_initwith remap
U-boot elf
U-boot elf
add-symbol-file
Summary
• The following principle is important for porting u-boot and Linux.– Understand the configuration usage and use generic
function to avoid incorrect integration.– Understand the generic software API first and co-
design the hardware behavior in earlier stage to avoid breaking the design of the software framework.
• Maintain your patches into different parts, like drivers, SoC, and configurations to make the patches could be easily fixed.– Maintain your patches into orders and reasonable.