Add latest U-boot support for BPI R2 & BPI R64 (not yet)


I’ve already sent the first round patches for MT7623n, and the most of the drivers are based on mainline Linux, like clock, timer, mmc, pinctrl, watchdog, power domain and DTS.

I will also upstream U-boot and ATF for MT7622 (BPI-R64) in the future.

The following are the major differences between Linux and U-boot:

  • Modify the driver interface to adapt the U-boot DM framework.
  • Remove unneeded DT nodes as they don’t have proper drivers in U-boot yet.
  • Just add the basic functions (step-by-step) so that we can monitor the size.
  • Reuse UART driver ns16550.c but add a highspeed register for MediaTek chips.

The current progress for R2:

  • Boot from eMMC or SD card.
  • Boot flow: ROM -> MediaTek preloder -> U-boot -> Linux

Todo list:

  • Ethernet driver.
  • Other peripheral drivers.
  • U-boot for MT7622 (R64)
  • ATF (arm trusted firmware) for MT7622 (R64)

The patch sets:

How to build:

  • make mt7623n_bpir2_defconfig; make



I just want to link thread from armbian-forum here because user chwe had tested this patches and found some small problems (missing options in defconfig):

Patches also uploaded here:

I think that’s because Armbian has different boot method (zImage) so that he need to modify defconfig.

i have forked uboot, applied patches and added build-script

also updated uboot-page in my wiki:

if anybody would test it…currently i need old uboot for netboot-tests and till the new have no ethernet-driver i cannot replace it

btw. @ryder.lee have the uboot support for the emmc-command needed to change the partition-config to run OS from EMMC?

You can read /write/ erase emmc or test it through GPT.

Have you an example for reading and writing partitionconfig to the needed value 0x48?

U-Boot> mmc list                                                                
mmc@11230000: 0 (eMMC)                                                          
mmc@11240000: 1 (SD)  

U-Boot> gpt read mmc 0
gpt - GUID Partition Table

gpt <command> <interface> <dev> <partitions_list> 
 - GUID partition table restoration and validity check
 Restore or verify GPT information on a device connected
 to interface
 Example usage:
 gpt write mmc 0 $partitions
 gpt verify mmc 0 $partitions
 read <interface> <dev>
    - read GPT into a data structure for manipulation
 guid <interface> <dev>
    - print disk GUID
 guid <interface> <dev> <varname> 
    - set environment variable to disk GUID
 Example usage:
 gpt guid mmc 0
 gpt guid mmc 0 varname

as far as i understand does gtp read/write a gpt-partition…the emmc command creates hardware-partitions (separate devices) mmcblkXbootY instead of mmcblkXpY…so i think creaeting this partitions with gpt-command is impossible

Emmc was introduced in 2014 uboot here:

i can read the uenv.txt using definitions from old uboot:

setenv scriptaddr 0x83000000
setenv bpi bananapi
setenv board bpi-r2
setenv service linux 
setenv device mmc
setenv partition 1:1 
setenv bootenv uEnv.txt
setenv loadbootenv fatload ${device} ${partition} ${scriptaddr} ${bpi}/${board}/${service}/${bootenv}
setenv importenv env import -t ${scriptaddr} ${filesize} 

run loadbootenv
run importenv

and got kernel booting with

U-Boot> setenv newboot "fatload mmc ${partition} ${loadaddr} ${bpi}/${board}/${service}/${kernel}; bootm"                                                             
U-Boot> run newboot

it seems that emmc (mmc 0) is always default device, also if i boot from sd-card…how can this be changed?

i booted from SD-Card:

U-Boot> mmc dev                                                                                                                                                       
switch to partitions #0, OK                                                                                                                                           
mmc0(part 0) is current device                                                                                                                                        
U-Boot> mmc list                                                                                                                                                      
mmc@11230000: 0 (eMMC)                                                                                                                                                
mmc@11240000: 1

in old uboot the problem with wrong device is resolved by this 2 definitions:

checksd=fatinfo ${device} 1:1
newchecksd=if run checksd; then echo Boot from SD ; setenv partition 1:1; else echo Boot from eMMC ; mmc init 0 ; setenv partition 0:1 ; fi;

“mmc init” seems to be dropped

also “saveenv” seems to be missing, do i have to enable anything for saving the environment?

i tried to activate CONFIG_ENV_IS_IN_MMC to activate saveenv-command ( results in failed build:

env/mmc.c: In function ‘mmc_get_env_dev’:
env/mmc.c:127:9: error: ‘CONFIG_SYS_MMC_ENV_DEV’ undeclared (first use in this function); did you mean ‘CONFIG_SYS_MALLOC_LEN’?
env/mmc.c:127:9: note: each undeclared identifier is reported only once for each function it appears in
env/mmc.c:128:1: warning: control reaches end of non-void function [-Wreturn-type]
scripts/ recipe for target 'env/mmc.o' failed
make[1]: *** [env/mmc.o] Error 1

this CONST is defined in old uboot here: but surrounded with if/elif



are these ON/OFF-Consts available in new uboot? i did not find them in uboot config, in old uboot they are defined in autoconf.h (which is a generated file afaik)

i simly defined


in include/configs/mt7623.h and compile works and i got the saveenv in ubbot…but now target for savenenv is always emmc.

@jackzeng has patched 2014 uboot to use the right mmc.

but this modifies global mmc-driver too much in my eyes for a patch…maybe it’s better calling a global function which by default returns CONFIG_SYS_MMC_ENV_DEV and can be overridden by vendor-specific emmc-driver. My c/c++ knowledge is a bit too less to realize this ;(

seems such function exists already for CONFIG_SYS_MMC_ENV_PART but not for CONFIG_SYS_MMC_ENV_DEV:


125 __weak int mmc_get_env_dev(void)
126 {
127     return CONFIG_SYS_MMC_ENV_DEV;
128 }

so we can try to override this function and return the actual boot-device…but how to deal with offset-change (+1MB if SD-Card) from Jacks patch? is this needed?

i tried to override this function in include/configs/mt7623.h, but this leads to some errors…maybe i need to copy this function to a c-file

include/configs/mt7623.h: Assembler messages:
include/configs/mt7623.h:72: Error: bad instruction `int mmc_get_env_dev(void)'
include/configs/mt7623.h:73: Error: junk at end of line, first unrecognized character is `{'
include/configs/mt7623.h:74: Error: bad instruction `return 1'
include/configs/mt7623.h:75: Error: junk at end of line, first unrecognized character is `}'

72 int mmc_get_env_dev(void)
73 {
74     return 1;
75 }

tried also in mtk-sd.c but here i have no access to the defined constant…build without it seems to work…

and can i add the vars somewhere to uboot-code to load it automaticly (and display bootmenu)?

i tried bootcmd, but it is not executed on startup…

bootcmd=run selectmmc; run loadbootenv; run importenv;

added a default environment file to my repo which gets build into uboot (i see the vars with printenv after bootup)

@ryder.lee Please post ethernet-patch if you have it ready.

i tried to override the function mmc_get_env_dev in drivers/mmc/mtk-sd.c

1288 int mmc_get_env_dev(void)
1289 {
1290     printf("%s:%d %s",__FILE__,__LINE__,__FUNCTION__);
1292     int   g_mmc_devid = -1;
1293     char *uflag = (char *)0x81DFFFF0;
1295     if((uflag[0] == 'e') && (uflag[1] == 'M') && (uflag[2] == 'M') && (uflag[3] == 'C'))
1296     {
1297         g_mmc_devid = 0;
1298         printf("Boot From Emmc(id:%d)\n\n", g_mmc_devid);
1299     }
1300     else
1301     {
1302         g_mmc_devid = 1;
1303         printf("Boot From SD(id:%d)\n\n", g_mmc_devid);
1304     }
1306     return 1;
1307 }

but it seems it is not called…

Device APC domain init setup:

 bootloader load uboot ,the address of uboot is 81E00000 
[PART]partition name UBOOT 
[PART]partition start block 0x200 
[PART]partition size 0x80000 
[PART]partition blks 0x400 
[PART]partition flags 0x0 

(after exit the bootmenu)

any idea why? maybe i need to put this into board-code, but i’ve found only board/mediatek/mt7623/mt7623_rfb.c not bpi-r2 as board-definition…is this used?

ok, due to botmenu the output was not visible…

Loading Environment from MMC... board/mediatek/mt7623/mt7623_rfb.c:20 mmc_get_env_devBoot From SD(id:1)

:grinning: have to test it with emmc now

Loading Environment from MMC... board/mediatek/mt7623/mt7623_rfb.c:20 mmc_get_env_devBoot From Emmc(id:0)

nice :wink:

@jackzeng why do you add a additional offset for SD-Card? can you help me implementing this? currently i don’t understand why you touched the offset because uboot+partitiontable are same for emmc+sd…if you’ve added this for emmc i thought that was for bootx-partitions, but on sd :thinking:

  //If mmc is SD, then set offset 1Mb
if(priv->id == 1)
  *env_addr = offset + mmc->capacity;
  *env_addr = offset;
//If is SD, set offset 1Mb
if(id == 1)
mmc->capacity = blk_num;

as far as i see in env/mmc.c there is also a weak mmc_get_env_addr function which seems to implement similar behaviour, but without the device-switch

113 __weak int mmc_get_env_addr(struct mmc *mmc, int copy, u32 *env_addr)
114 {
115     s64 offset = mmc_offset(copy);
117     if (offset < 0)
118         offset += mmc->capacity;
120     *env_addr = offset;
122     return 0;
123 }

which gets called in static int env_mmc_save(void) and int env_mmc_load(void)

@Ryder.Lee is this ethernet-driver compatible: ? seems it’s not…added it, changed depends (by default only for MT7620/7688 SoCs) so i can select it in menuconfig, but throws different errors

  CC      drivers/net/mt76xx-eth.o
drivers/net/mt76xx-eth.c: In function ‘mt76xx_eth_write_hwaddr’:
drivers/net/mt76xx-eth.c:352:56: error: dereferencing pointer to incomplete type ‘struct eth_pdata’
  u8 *addr = ((struct eth_pdata *)dev_get_platdata(dev))->enetaddr;
drivers/net/mt76xx-eth.c: In function ‘mt76xx_eth_send’:
drivers/net/mt76xx-eth.c:401:28: warning: implicit declaration of function ‘CPHYSADDR’; did you mean ‘MII_PHYADDR’? [-Wimplicit-function-declaration]
  priv->tx_ring[idx].txd1 = CPHYSADDR(packet);
drivers/net/mt76xx-eth.c:408:2: warning: implicit declaration of function ‘wmb’; did you mean ‘dmb’? [-Wimplicit-function-declaration]
drivers/net/mt76xx-eth.c: In function ‘mt76xx_eth_probe’:
drivers/net/mt76xx-eth.c:587:3: warning: implicit declaration of function ‘KSEG1ADDR’ [-Wimplicit-function-declaration]
drivers/net/mt76xx-eth.c: At top level:
drivers/net/mt76xx-eth.c:617:21: error: variable ‘mt76xx_eth_ops’ has initializer but incomplete type
 static const struct eth_ops mt76xx_eth_ops = {
drivers/net/mt76xx-eth.c:618:3: error: ‘const struct eth_ops’ has no member named ‘start’
  .start  = mt76xx_eth_start,
drivers/net/mt76xx-eth.c:618:12: warning: excess elements in struct initializer
  .start  = mt76xx_eth_start,
drivers/net/mt76xx-eth.c:618:12: note: (near initialization for ‘mt76xx_eth_ops’)
drivers/net/mt76xx-eth.c:619:3: error: ‘const struct eth_ops’ has no member named ‘send’
  .send  = mt76xx_eth_send,
drivers/net/mt76xx-eth.c:619:11: warning: excess elements in struct initializer
  .send  = mt76xx_eth_send,
drivers/net/mt76xx-eth.c:619:11: note: (near initialization for ‘mt76xx_eth_ops’)
drivers/net/mt76xx-eth.c:620:3: error: ‘const struct eth_ops’ has no member named ‘recv’
  .recv  = mt76xx_eth_recv,
drivers/net/mt76xx-eth.c:620:11: warning: excess elements in struct initializer
  .recv  = mt76xx_eth_recv,
drivers/net/mt76xx-eth.c:620:11: note: (near initialization for ‘mt76xx_eth_ops’)
drivers/net/mt76xx-eth.c:621:3: error: ‘const struct eth_ops’ has no member named ‘stop’
  .stop  = mt76xx_eth_stop,
drivers/net/mt76xx-eth.c:621:11: warning: excess elements in struct initializer
  .stop  = mt76xx_eth_stop,
drivers/net/mt76xx-eth.c:621:11: note: (near initialization for ‘mt76xx_eth_ops’)
drivers/net/mt76xx-eth.c:622:3: error: ‘const struct eth_ops’ has no member named ‘write_hwaddr’
  .write_hwaddr = mt76xx_eth_write_hwaddr,
drivers/net/mt76xx-eth.c:622:18: warning: excess elements in struct initializer
  .write_hwaddr = mt76xx_eth_write_hwaddr,
drivers/net/mt76xx-eth.c:622:18: note: (near initialization for ‘mt76xx_eth_ops’)
drivers/net/mt76xx-eth.c:637:37: error: invalid application of ‘sizeof’ to incomplete type ‘struct eth_pdata’
  .platdata_auto_alloc_size = sizeof(struct eth_pdata),
drivers/net/mt76xx-eth.c:617:29: error: storage size of ‘mt76xx_eth_ops’ isn’t known
 static const struct eth_ops mt76xx_eth_ops = {
scripts/ recipe for target 'drivers/net/mt76xx-eth.o' failed
make[1]: *** [drivers/net/mt76xx-eth.o] Error 1
Makefile:1423: recipe for target 'drivers/net' failed
make: *** [drivers/net] Error 2

Is anything additional needed (dts-nodes)?

the network HW architecture of mt7623 and mt7620 are different, so you cannot apply this patch directly, thanks.

1 Like

I see that new patches are available.

Is there anything new or only whitespaces (eol) updated? Ethernet seems not yet included

We’re working on Ethernet driver now.


btw. uboot-patches v2 ( failing on 2018-11-rc1 because of missing MT7621_SPI-symbol in drivers/spi/Kconfig

+config MTK_QSPI
+       bool "Mediatek QSPI driver"
+       help
+         Enable the Mediatek QSPI driver. This driver can be
+         used to access the SPI NOR flash on platforms embedding this
+         Mediatek QSPI IP core.

it seems that another patch-series is needed to apply this patch directly, but i didn’t find which one

have it applied here:

problem-patch is here:

i don’t know yet how to answer in patchwork…

To use SD card, you should use the following command:

mmc dev 1

the ‘1’ means the second device, which is SD card.

and you will get output like this:

U-Boot> mmc dev 1
switch to partitions #0, OK
mmc1 is current device

U-Boot> mmc list
mmc@11230000: 0
mmc@11240000: 1 (SD)

U-Boot> mmc info
Device: mmc@11240000
Manufacturer ID: 11
OEM: 4499
Name: SD256
Bus Speed: 50000000
Mode : SD High Speed (50MHz)
Rd Block Len: 512
SD version 2.0
High Capacity: No
Capacity: 239 MiB
Bus Width: 4-bit
Erase Group Size: 512 Bytes

To switch HW partitions (boot0/boot1/user), uses the following commands:

mmc dev 0 1

the second number ‘1’ means partition boot0 (according to the eMMC spec)

Read the first block to check it:

U-Boot> mmc dev 0 1
switch to partitions #1, OK
mmc0(part 1) is current device
U-Boot> mmc read 0x80000000 0 2

MMC read: dev # 0, block # 0, count 2 ... 2 blocks read: OK
U-Boot> md 0x80000000
80000000: 434d4d45 4f4f425f 00000054 00000001    EMMC_BOOT.......
80000010: 00000200 ffffffff ffffffff ffffffff    ................
80000020: ffffffff ffffffff ffffffff ffffffff    ................

right, but i asked because the emmc-command in 2014-uboot which configures emmc to have a boot0 and boot1-device which is needed to flash preloader to it and get image booted from emmc

reference: Can't boot from emmc (see step 4)

btw. is poweroff-command much work? if i enable the command i get: missing »do_poweroff«

btw. uboot-patches v2 ( failing on 2018-11-rc1 because of missing MT7621_SPI-symbol in drivers/spi/Kconfig

You should rebase to the latest branch:;a=commit;h=5eee9dee419f940ea75977df8b7ed8bb12bc029f

have v2-patches and my own ready again…waiting for ethernet-driver and the 2018-11 final release :slight_smile:

How far are you with the ethernet-driver? Btw. In old uboot mac-setting does not work,hoping here it will do.

@Ryder.Lee can you manage to add ethernet-driver for r2 before 2018-11-release (12th november)?

emmc-command seems not be needed, i’ve found out how to use uboot-internal commands to read and set the Partitionconfig:

#mmc partconf dev [boot_ack boot_partition partition_access]
# - Show or change the bits of the PARTITION_CONFIG field of the specified device
#example for mode 0x48 (needed for emmc-boot on bpi-r2)
U-Boot> mmc partconf 0

#set via
U-Boot> mmc partconf 0 1 1 0

i resetted the flags and set it with last command to get the same result as read before reset

Currently i don’t know how the 0x48 is calculated…

@Ryder.Lee i have an issue with v3-patches:

Kernel command line: earlyprintk console=ttyS0,115200 vmalloc=496M debug=7 no_console_suspend

this does not change to the value of bootargs env-variable

Boot from SD
bootargs=board=bpi-r2 console=earlyprintk console=tty1 fbcon=map:0 console=ttyS0,115200 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait vmalloc=496M debug=7 initcall_debug=0 video=1920x1080 drm.debug=0x7
6473034 bytes read in 394 ms (15.7 MiB/s)
## Booting kernel from Legacy Image at 80200000 ...
   Image Name:   Linux Kernel 4.19.0-poweroff_new
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    6472970 Bytes = 6.2 MiB
   Load Address: 80008000
   Entry Point:  80008000
   Verifying Checksum ... OK
   Loading Kernel Image ... OK

Starting kernel ...

[    0.000000] Booting Linux on physical CPU 0x0
[    0.000000] Linux version 4.19.0-bpi-r2-poweroff_new (frank@frank-N56VZ) (gcc version 7.3.0 (Ubuntu/Linaro 7.3.0-27ubuntu1~18.04)) #172 SMP Wed Oct 24 11:38:09 CEST 2018
[    0.000000] CPU: ARMv7 Processor [410fc073] revision 3 (ARMv7), cr=10c5387d
[    0.000000] CPU: div instructions available: patching division code
[    0.000000] CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
[    0.000000] OF: fdt: Machine model: Bananapi BPI-R2
[    0.000000] Memory policy: Data cache writealloc
[    0.000000] cma: Reserved 64 MiB at 0xfb800000
[    0.000000] On node 0 totalpages: 524287
[    0.000000]   Normal zone: 1170 pages used for memmap
[    0.000000]   Normal zone: 0 pages reserved
[    0.000000]   Normal zone: 133120 pages, LIFO batch:31
[    0.000000]   HighMem zone: 391167 pages, LIFO batch:63
[    0.000000] random: get_random_bytes called from start_kernel+0xac/0x49c with crng_init=0
[    0.000000] percpu: Embedded 17 pages/cpu @(ptrval) s40268 r8192 d21172 u69632
[    0.000000] pcpu-alloc: s40268 r8192 d21172 u69632 alloc=17*4096
[    0.000000] pcpu-alloc: [0] 0 [0] 1 [0] 2 [0] 3 
[    0.000000] Built 1 zonelists, mobility grouping on.  Total pages: 523117
[    0.000000] Kernel command line: earlyprintk console=ttyS0,115200 vmalloc=496M debug=7 no_console_suspend
  • v3-patches on rc1 giving same result, so it’s no rc3-issue
  • resetted environment (to default=builtin=uenv.txt in my uboot-repo) before loading kernel
  • builtin-env is same in v2,v3 and v3_old branch
  • uenv.txt on sdcard only contains kernel-var (and root=same as on default env)

works with v2 but not with v3 (rc1/rc3)

any idea?