August 9, 2018

U-Boot internals and network for the Nanopi Fire3

U-Boot as shipped with the s5p6818-friendly-core-xenial-4.4-arm64-20180615 linux image does not include networking! And so far, rebuilding U-Boot and trying to turn on networking has failed as well. The question is whether we have to write a network driver for U-Boot ourselves!

Breadcrumbs and U-Boot

If you have rattled around the U-Boot source tree much, you know that there are lots of files, only a small percentage of which are actually used to build your specific U-Boot. Here is a hot tip. Build U-Boot! Then wander around and look for ".o" files. The build system magically knows which files to compiles and if you pay attention to the ".o" files that get produced you will know which files got compiled. Simple but very effective and time saving.

Note that in each subdirectory, the U-Boot build system will link everything that gets compiled into a "lump" it calls built-in.o. I suppose that is as good a name as any. At any event, seeing this doesn't tell you much other than something else somewhere actually got compiled and then linked with other things (if there are any) to produce this. In other words you can ignore these.

Do some recon work in the U-Boot sources

Here is a list of files and directories that seem relevant and specific to the NanoPi Fire3 and/or the S5P6818 chip: The dtsi file has the following. The disabled status does not bother me as all of the entries are marked as disabled.
  gmac:ethernet@c0060000 {
                compatible = "nexell,nexell-gmac";
                reg = <0xc0060000 0x8000>;
                phy-mode = "rgmii";
                pinctrl-names = "default";
                pinctrl-0 = <&gmac_txd>, <&gmac_rxd>, <&gmac_txen>,
                        <&gmac_mdc>, <&gmac_mdio>, <&gmac_rxclk>, <&gmac_txclk>;
                status = "disabled";
        };

board/s5p6818/nanopi3/board.c has code for extracting the ethernet address.

The designware.c driver catches our attention because grep finds the string "nexell" in it. Taking a look at designware.h, the register layout matches what is in chapter 17 of the S5P6818 user manual. This is very promising.

In addition, here are some code snippets:

static const struct udevice_id designware_eth_ids[] = {
        { .compatible = "allwinner,sun7i-a20-gmac" },
        { .compatible = "altr,socfpga-stmmac" },
        { .compatible = "nexell,nexell-gmac" },
        { }
};
Note that the "nexell" strings here match those in the s5p6818.dtsi file.
The designware.c driver also contains:
#ifdef CONFIG_DM_ETH
#if defined(CONFIG_ARCH_NEXELL)
static int nexell_gmac_initialize(void)
{
        struct clk *clk;
        unsigned int rate;

        /* Clock control */
        clk = clk_get("nx-gmac.0");
        if (!clk)
                return 0;

        clk_disable(clk);
        rate = clk_set_rate(clk, 125000000);
        clk_enable(clk);

        debug("rate: %u\n", rate);

        /* Reset control */
        nx_rstcon_setrst(RESET_ID_DWC_GMAC, 0);
        nx_rstcon_setrst(RESET_ID_DWC_GMAC, 1);

        return 0;
}
#endif /* CONFIG_ARCH_NEXELL */

How does the U-Boot make system know what files to build from ?

In other words, how does the U-Boot build system work? The top level Makefile is a 1600+ line monster with some heredity derived from the Linux build system (for better or worse).

Before doing anything else, spend some time looking at the top level README in the U-Boot distribution. The "doc" directory includes a collection of more specific README files, but I don't see anything for Nexell or 6818.

Now, take a look at u-boot/drivers/net/Makefile -- it has a bunch of lines that look like the following.
obj-$(CONFIG_ETH_DESIGNWARE) += designware.o
How does this work? Well, if the option is turned on, the value of the variable will be "y" and we will add the object file to "obj-y". Otherwise I guess it gets added to the variable "obj-" which just gets ignored. So the big question is how and where does CONFIG_ETH_DESIGNWARE get set? Fundamentally in some file like u-boot/configs/Orangepi_defconfig

Also worth noting is that my board has an RTL 8211E chip to handle the ethernet physical layer. None of the defconfig files seem to mention it.

Give it a whirl with CONFIG_ETH_DESIGNWARE added

make distclean
make V=1 s5p6818_nanopi3_defconfig
make -f ./scripts/Makefile.build obj=scripts/basic
  cc -Wp,-MD,scripts/basic/.fixdep.d -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer     -o scripts/basic/fixdep scripts/basic/fixdep.c
rm -f .tmp_quiet_recordmcount
make -f ./scripts/Makefile.build obj=scripts/kconfig s5p6818_nanopi3_defconfig
  cc -Wp,-MD,scripts/kconfig/.conf.o.d -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer   -D_GNU_SOURCE -D_DEFAULT_SOURCE  -DCURSES_LOC="" -DNCURSES_WIDECHAR=1 -DLOCALE   -c -o scripts/kconfig/conf.o scripts/kconfig/conf.c
  cat scripts/kconfig/zconf.tab.c_shipped > scripts/kconfig/zconf.tab.c
  cat scripts/kconfig/zconf.lex.c_shipped > scripts/kconfig/zconf.lex.c
  cat scripts/kconfig/zconf.hash.c_shipped > scripts/kconfig/zconf.hash.c
  cc -Wp,-MD,scripts/kconfig/.zconf.tab.o.d -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer   -D_GNU_SOURCE -D_DEFAULT_SOURCE  -DCURSES_LOC="" -DNCURSES_WIDECHAR=1 -DLOCALE  -Iscripts/kconfig -c -o scripts/kconfig/zconf.tab.o scripts/kconfig/zconf.tab.c
  cc  -o scripts/kconfig/conf scripts/kconfig/conf.o scripts/kconfig/zconf.tab.o
scripts/kconfig/conf  --defconfig=arch/../configs/s5p6818_nanopi3_defconfig Kconfig
#
# configuration written to .config
#
This does not cut it. The setting for CONFIG_ETH_DESIGNWARE does not make it into the .config file for some reason.


Have any comments? Questions? Drop me a line!

Tom's electronics pages / tom@mmto.org