So you have a new custom Blackfin board and you want to get Das U-Boot up and running on it? Here's the document for you. Unfortunately, it isn't the only document you're going to need. You should also make sure to have the HRM for your Blackfin variant, as well as all the datasheets for all the main parts on your board (that you will be configuring in U-Boot). Since it is the job of U-Boot to initialize all the low-level hardware details, you're going to need to know the hardware settings.
For the purposes of this document, we will be creating a new BF537 board code named “cow”. Whether your board is based on a different processor or you've got a cooler name, these details should be easily replaceable.
Here is a quick list of the files/directories in U-Boot that you will need to modify/create:
In the top-level Makefile, simply locate the Blackfin section where the variable BFIN_BOARDS is declared and add your board to it. The Blackfin portions of the makefile use this variable to set up everything else for the selected board.
BFIN_BOARDS += bf537-cow
If you generate any non-standard files in your Board Directory, you will also need to update the clean target to have those files removed. Common files (like objects *.o) are automatically removed for you.
If you plan on contributing your board back to the Blackfin U-Boot mainline, you should update the MAKEALL script. Locate the LIST_blackfin variable and add your board to the end of it.
LIST_blackfin=" \
...
bf537-cow
"
This script is used to quickly run compile tests for all available Blackfin boards. The Blackfin U-Boot maintainer uses this when making board-independent changes so as to be sure that no boards break (and if they do, he will fix them for you).
If you plan on contributing your board back to the Blackfin U-Boot mainline, you should update the MAINTAINERS list. Locate the Blackfin Systems section and add your contact e-mail and board(s) to the end of it. Feel free to add the Blackfin development mailing list as well.
...
# Blackfin Systems:
...
Some Developer <your.email@company.com>
BF537-COW BF537
...
This file is the heart of your board setup. It describes all of the features to enable, drivers to include, and settings. Here we'll cover the key defines and give pointers to further documentation.
Once you tackle the Blackfin options below, check out the customizing page for the next steps.
Please make sure your board configuration file has this general format:
/* Some copyright / license info */ #ifndef __CONFIG_BF537_COW_H__ #define __CONFIG_BF537_COW_H__ /* this must come first */ #include <asm/config-pre.h> ... /* this sets up the default list of enabled commands */ #include <config_cmd_default.h> /* Undo any settings you don't like from the config_cmd_default.h */ #endif
There are a few Blackfin specific defines you must setup.
This is a short string that represents the desired Blackfin processor and its silicon version. So if we want to target silicon revision 0.3 of the BF537 for our board:
#define CONFIG_BFIN_CPU bf537-0.3
This controls the expected boot method of your board. Generally speaking, the code attempts to be boot-mode agnostic, but this isn't always the case. Make sure this actually matches your BMODE pins. Keep in mind that U-Boot supports more boot modes than your Blackfin variant may, so only select ones that your Blackfin variant actually supports. See the Blackfin Boot ROM Boot Modes section for more information.
When changing boot modes, make sure you run make clean first to ensure all files are properly recompiled.
If we want to create an LDR which can boot over the UART, then we would do something like:
#define CONFIG_BFIN_BOOT_MODE BFIN_BOOT_UART
Here is the complete list of possible values for BFIN_BOOT_MODE:
file: arch/blackfin/include/asm/config-pre.h
/* line 20 to 33 */ #define BFIN_BOOT_BYPASS 1 /* bypass bootrom */ #define BFIN_BOOT_PARA 2 /* boot ldr out of parallel flash */ #define BFIN_BOOT_SPI_MASTER 3 /* boot ldr out of serial flash */ #define BFIN_BOOT_SPI_SLAVE 4 /* boot ldr as spi slave */ #define BFIN_BOOT_TWI_MASTER 5 /* boot ldr over twi device */ #define BFIN_BOOT_TWI_SLAVE 6 /* boot ldr over twi slave */ #define BFIN_BOOT_UART 7 /* boot ldr over uart */ #define BFIN_BOOT_IDLE 8 /* do nothing, just idle */ #define BFIN_BOOT_FIFO 9 /* boot ldr out of FIFO */ #define BFIN_BOOT_MEM 10 /* boot ldr out of memory (warmboot) */ #define BFIN_BOOT_16HOST_DMA 11 /* boot ldr from 16-bit host dma */ #define BFIN_BOOT_8HOST_DMA 12 /* boot ldr from 8-bit host dma */ #define BFIN_BOOT_NAND 13 /* boot ldr from nand flash */
Simply define this to the UART number you have setup as your console. So if you are using UART0, just do:
#define CONFIG_UART_CONSOLE 0
These set of defines are used to control the clock settings for your board. They are directly used to program the PLL and related registers. Only basic validity checks are performed (at the register level). No checks are performed to make sure datasheet compliance.
You should consult the PLL Registers chapter of the HRM for your Blackfin variant.
For quick reference, the clock calculations are:
Core: (CLKIN / (2 ^ CLKIN_HALF) * VCO_MULT) / CCLK_DIV System: (CLKIN / (2 ^ CLKIN_HALF) * VCO_MULT) / SCLK_DIV
If you want to just program a register directly, you can use the CONFIG_<MRR>_VAL define. So if you wish to program the VR_CTL MMR with a specific setting, you can set CONFIG_VR_CTL_VAL in your board configuration.
There are a few defines that correlate directly to the registers. On all Blackfin's you have to define:
On some newer Blackfin's (as older ones do not have these settings), you will have to define:
For exact meanings of a particular register, consult the HRM for your processor and any devices that you will have hooked up to these banks.
For Blackfin's that have SDRAM, you will need to define:
For Blackfin's that have DDR, you will need to define:
For exact meanings of a particular register, consult the HRM for your processor and the datasheets for the memory module you are using.
For assistance in calculating the Blackfin settings based on your memory's timings, please see the SDRAM page.
This is where all of your board-specific files and code lives. There are three files that you are required to have in here. Those are:
You can use this common template in any board directory:
# BF537-COW board makefile include $(TOPDIR)/config.mk LIB = $(obj)lib$(BOARD).a COBJS := $(BOARD).o SOBJS := SRCS := $(SOBJS:.o=.S) $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(COBJS)) SOBJS := $(addprefix $(obj),$(SOBJS)) $(LIB): $(obj).depend $(OBJS) $(SOBJS) u-boot.lds $(AR) $(ARFLAGS) $@ $(OBJS) $(SOBJS) clean: rm -f $(SOBJS) $(OBJS) distclean: clean rm -f $(LIB) core *.bak $(obj).depend include $(SRCTREE)/rules.mk sinclude $(obj).depend
If you have more C files or assembly (.S) files to compile, simply add them to the COBJS or SOBJS variable as appropriate.
If you wish to add custom compiler flags for your board, then the config.mk file is the place for it. Simply append the variable in question (like PLATFORM_RELFLAGS or PLATFORM_CPPFLAGS) with whatever flag you want.
Keep in mind that the TEXT_BASE variable is not used by the Blackfin platform, so do not set it.
Most people will use this simply to tweak the flags given to the ldr utility when generating the u-boot.ldr file.
# This is not actually used for Blackfin boards so do not change it #TEXT_BASE = do-not-use-me #PLATFORM_RELFLAGS += -some-gcc-flag #PLATFORM_CPPFLAGS += -DMY_CRAZY_DEFINE # Setup LDR_FLAGS according to our boot mode (BFIN_BOOT_MODE variable is defined automatically) LDR_FLAGS-BFIN_BOOT_UART = --port g --gpio 6 LDR_FLAGS += $(LDR_FLAGS-$(BFIN_BOOT_MODE))
This is generally where you put the core/required functions that are needed by common U-Boot code. We'll cover the functions you should be sure to actually implement.
Used to check random board specific details before initializing drivers. Usually just prints out a banner for your board. Return a value of zero to indicate success or return non-zero to indicate failure (in which case the board should hang or reboot).
int checkboard(void) { printf("Board: BF537 cow board\n"); printf(" Support: http://cow.town/\n"); return 0; }
This function is optional. If you need to tweak the hardware some how before performing a soft system reset, then place those details here.
void board_reset(void) { /* do something weird */ }
This function is where you place miscellaneous board initialization code. This is run after pretty much everything else has been initialized but before the main execution of the console shell. Same as the checkboard function -- return zero for success, non-zero to panic the board. Make sure you define CONFIG_MISC_INIT_R in your board configuration file.
int misc_init_r(void) { /* do random stuff */ }
If your board has ethernet capabilities and your MAC does not have a dedicated EEPROM for storing the MAC address, and you have not hardcoded the MAC address in your board configuration file, you must implement this sort of code in your board's misc_init_r() function. If your MAC does have a dedicated EEPROM, then the U-Boot driver will take care of this function for you.
The purpose of this semi-complicated system is to allow you to store/retrieve the MAC address from wherever you like. For example, the BF537-STAMP utilizes a sector of parallel flash for storing the MAC address in a persistent manner.
For more information, consult the doc/README.enetaddr file.
int misc_init_r(void) { ... uchar enetaddr[6]; if (!eth_getenv_enetaddr("ethaddr", enetaddr)) { /* we cram the MAC in the last flash sector */ memcpy(enetaddr, (void *)0x203F0000, 6); eth_setenv_enetaddr("ethaddr", mac_addr); } ... }
The board_eth_init() function is the board callback function for registering your ethernet devices. Here you call the different network driver init functions and return their result.
file: board/bf537-stamp/bf537-stamp.c
/* line 79 to 83 */ int board_eth_init(bd_t *bis) { return bfin_EMAC_initialize(bis); }
The memory layout guide may help you for customizing where to place U-Boot's code and data.