August 14, 2018

U-Boot -- board initialization

I find myself wanting to add some code to board.c for my target. In particular, I need to configure the pin multiplexor to set certain pins in the right mode to use their "alternate function", namely the GMAC network controller rather than GPIO. The vital issue though is getting things done at the right time during the initialization sequence. A number of entry points in board/s5p6818/nanopi3/board.c need to be considered. To make intelligent use of these with respect to when the network gets initialized is vital.

board_early_init is called from common/board_f.c via board_early_init_f(). This is prior to U-Boot relocation and probably not what I want.

The remainder are all called from common/board_r.c in an order determined by a list of functions (init_sequence_r). The order is as follows, with some other pertinent calls listed:

board_init
board_early_init_r
init_ethaddr (expects the MAC address to be in the ethaddr environment variable)
board_late_init
initr_net (will ultimately call board_eth_init).

Note that we have both board_init() and board_early_init_r().
On inspection, it looks to me like some boards call board_init() and
others call board_early_init_r() -- so this may reflect the introduction
of some kind of U-Boot naming convention change more than anything else.

initr_net basically calls eth_initialize. Note that this follows ALL of the board initialization calls. The eth_initialize() routine is in net/eth.c and there are two flavors, one is the legacy "pre-DM" flavor and the other is the new "DM" flavor.

The first thing eth_initialize() does is to call eth_common_init() which calls miiphy_init() and phy_init() and then board_eth_init(). After this, eth_initialize() goes on to poke around in the list of registered ethernet devices and calls eth_write_hwaddr(dev) for each device.

Setting the MAC address

This discussion pertains to the fire3 board (the s5p6818/nanopi3). The game starts in s5p6818/nanopi3/board.c and ends in /drivers/net/designware.c. The function board_late_init() calls set_ether_addr(), which reads the address from something resembling EEPROM and places it into the "ethaddr" environment variable.

Somewhat later, eth_initialize() (in net/eth.c) gets called, which in turn calls eth_write_hwaddr() in the same file. This fishes the address out of the "ethaddr" variable in the environment, and then calls dev->write_hwaddr() to set it. The function pointer "write_hwaddr" has been set to the dw_write_hwaddr() function in designware.c during driver registration, so this all works.


Have any comments? Questions? Drop me a line!

Tom's electronics pages / tom@mmto.org