U-Boot support for Dragonboard410c?

@rfried, no, eMMC will continue to fail on the db410c until the fix I mentioned is merged.
Also http://git.denx.de/?p=u-boot.git;a=summary updates more frequently than its github clone.

you can find the required patch already merged in http://git.denx.de/?p=u-boot/u-boot-mmc.git;a=summary

it is just a matter of time until it is merged back to the master branch
http://git.denx.de/?p=u-boot/u-boot-mmc.git;a=search;s=Jorge+Ramirez-Ortiz;st=author

Yes, If I’m not wrong, MAC address (and BD address) are still injected in the FDT at runtime by lk, so you need to retrieve this FDT from u-boot and pass it to Linux. Think the following @robclark patch could help:

However, not sure why this patch has not been pushed upstream. @ldts, any comment/thought on this patch ?

I dont think this is needed. Just adding the nodes to the uboot dts will import the mac addresses for BT and WLAN

ie
— a/arch/arm/dts/dragonboard410c.dts
+++ b/arch/arm/dts/dragonboard410c.dts
@@ -86,6 +86,15 @@
clock-frequency = <200000000>;
};

  •     wcnss {
    
  •           bt {
    
  •                 compatible="qcom,wcnss-bt";
    
  •           };
    
  •           wifi {
    
  •                 compatible="qcom,wcnss-wlan";
    
  •           };                   
    

@Loic, well not really. We discussed a bit more on IRC yesterday about that.

When using u-boot, it is expected that the DTS used in the ‘boot’ image that contains uboot binary, and thus which is loaded by LK, is the DTS that comes from uboot source tree, not the DTS that comes from the kernel (e.g. not the real DTS that accurately describes the board).

The uboot DTS does not include the wcnss node, so LK will not add the MAC address info in this case. So the DTB passed from LK to uboot in turns does not include the MAC address info.

We need to add similar logic in uboot to dynamically add the mac address into the DTB that uboot will pass to the kernel (most likely uboot will get the DTB from the rootfs). Jorge will be looking at that.

1 Like

While I prepare and submit a proper patch you can paste the following code to uboot/…/dragonboard410c.c and enable CONFIG_OF_BOARD_SETUP=y in dragonboard410c_defconfig.

int ft_board_setup(void *blob, bd_t *bd)
{
const char *wlan_mac = “02:00:A9:D5:23:20”;
const char *bt_mac = “02:00:A9:D5:23:21”;

do_fixup_by_compat(blob, "qcom,wcnss-wlan", "local-mac-address",
	wlan_mac, strlen(wlan_mac), 1);

do_fixup_by_compat(blob, "qcom,wcnss-bt", "local-mac-address", bt_mac,
	strlen(bt_mac), 1);

return 0;

}

I managed to get the kernel booting on the latest u-boot-mmc sources with your fix from above incorporated, after changing CONFIG_SYS_BOOTM_LEN from 0x1000000 to 0x1100000 which now accommodates the size of the uImage that I generated from the kernel sources from the OpenEmbedded build on CAF.

Now that I’m in the system it seems that the data inserted into the FDT for local-mac-address is now somehow invalid. I’m not sure why as it looks to be proper from what you’re hardcoding into the local-mac-address property. When the local-mac-address is marked invalid it does not allow the driver to bring-up the adapter at all.

Here’s a snippet from dmesg with the error:
[ 5.971527] a204000.wcnss supply vddcx not found, using dummy regulator [ 5.982940] remoteproc remoteproc1: a204000.wcnss is available [ 5.992683] remoteproc remoteproc1: powering up a204000.wcnss [ 5.998643] remoteproc remoteproc1: Booting fw image wcnss.mdt, size 7260 [ 6.497264] remoteproc remoteproc1: remote processor a204000.wcnss is now up [ 6.618440] qcom_wcnss_ctrl remoteproc1:smd-edge.WCNSS_CTRL.-1.-1: WCNSS Version 1.5 1.2 [ 8.914383] wcn36xx: testmode=0 dbg_mask=0x00000000 [ 8.914466] wcn36xx: ERROR invalid local-mac-address [ 8.918152] wcn36xx: probe of a204000.wcnss:smd-edge:wcnss:wifi failed with error -22

sorry yeah, the local mac address format is should be in square brackets

local-mac-address = [02 00 a9 d5 23 10];

I tried changing
const char *wlan_mac = "02:00:A9:D5:23:20"; const char *bt_mac = "02:00:A9:D5:23:21";
to
const char *wlan_mac = "[02 00 a9 d5 23 20]"; const char *bt_mac = "[02 00 a9 d5 23 21]";

And it does not seem to want to initialize and gives the same error:
wcn36xx: ERROR invalid local-mac-address

After flashing back to the stock image, i dumped out the node for local-mac-address from the /proc/device-tree/soc/wcnss@a21b000/smd-edge/wcnss/wifi directory. I think I know why this is not working now, it appears that we’re writing the property as a string, and I think that the driver wants the mac in its raw byte form. I believe this to be true since just cat-ing out the node results in unprintable characters, but hexdump-ing it out reveals the mac address byte swapped in the hexdump:
0000000 0002 169e 9510 0000006
This corresponds to the mac address on my board: 02:00:9e:16:10:95

The good news is that we’re getting data into the local-mac-address property

ah, yes of course; this will work.

int ft_board_setup(void *blob, bd_t *bd)
{
const char wlan_mac[ARP_HLEN] = { 0x02, 0x00, 0xA9, 0xD5, 0x23, 0x10 };
const char bt_mac[ARP_HLEN] = { 0x02, 0x00, 0xA9, 0xD5, 0x23, 0x11 };

do_fixup_by_compat(blob, "qcom,wcnss-wlan", "local-mac-address",
	wlan_mac, ARP_HLEN, 1);

do_fixup_by_compat(blob, "qcom,wcnss-bt", "local-mac-address",
	bt_mac, ARP_HLEN, 1);

return 0;

}

1 Like

Nice! That did the trick… We can now hard-code the mac address onto our boards.

This mimics pretty much what the LK does (so you dont have to hardcode your own address).

int ft_board_setup(void *blob, bd_t *bd)
{
char wlan_mac[ARP_HLEN] = { 0x02, 0x00, 0x00, 0x00, 0x00, 0x00 };
char bt_mac[ARP_HLEN] = { 0x02, 0x00, 0x00, 0x00, 0x00, 0x00 };
struct mmc *mmc;

mmc = find_mmc_device(0);

printf("MMC serial Nbr: %x:%x:%x:%x\n",
	        (mmc->cid[2] >> 8) & 0xff, mmc->cid[2] & 0xff,
	        (mmc->cid[3] >> 24), (mmc->cid[3] >> 16) & 0xff);

wlan_mac[2] = bt_mac[2] = (mmc->cid[2] >> 8) & 0xff;
wlan_mac[3] = bt_mac[3] =  mmc->cid[2] & 0xff;
wlan_mac[4] = bt_mac[4] = (mmc->cid[3] >> 24);
wlan_mac[5] = bt_mac[5] = (mmc->cid[3] >> 16) & 0xff;

bt_mac[5] += 1;

do_fixup_by_compat(blob, "qcom,wcnss-wlan", "local-mac-address",
	wlan_mac, ARP_HLEN, 1);

do_fixup_by_compat(blob, "qcom,wcnss-bt", "local-mac-address",
	bt_mac, ARP_HLEN, 1);

return 0;

}

Cool, I’ve got this working in my build. It sets the wlan mac address properly.

Now I just need to figure out how to get u-boot to read from mmcblk0p10 so I can use the rootfs partition for booting rather than the external SD. I’m going to dig into this and see where I get with this.

this is my bootargs

root=/dev/mmcblk0p10 rw rootwait console=tty0 console=ttyMSM0,115200n8 earlyprintk ignore_loglevel earlycon=msm_serial_dm,0x78b0000 androidboot.emmc=true androidboot.serialno=a9d52310 androidboot.baseband=apq mdss_mdp.panel=0:dsi:0

Are you able to load your uEnv.txt and find the kernel uImage and the APQ8016-sbc.dtb from the rootfs partition, or do you have a separate partition for those?

I was thinking that I’d need to create a custom partition map to do get this working properly. Since calling ext4load mmc 0:10 ${kernel_addr_r} /boot/uImage results in “Invalid partition 16” for some reason.

The weird thing is that I can see the 10th partition in mmc part when I select the 0th card in u-boot…

not using the SD card really… I have a tftp server for kernel and device tree so I just do:

dragonboard410c => print tftpboot
tftpboot=usb start; tftp 0x81000000 uImage-410c; tftp 0x83000000 dtb-410c.dtb; bootm 0x81000000 - 0x83000000
dragonboard410c => run tftpboot

Oh cool, you can use TFTP to boot the kernel I guess you’ve got a compatible USB<->Ethernet adaptor to work in U-Boot that’s pretty neat.

Any idea as to why I can’t read anything from the emmc 0:10 (rootfs)?

EDIT:Duh, it’s looking for the partition number in hex! 0:A = /dev/mmcblk0p10

If anyone is interested in booting from the rootfs (/dev/mmcblk0p10) in U-Boot this is how I got it to work:
setenv bootargs root=/dev/mmcblk0p10 rw rootwait console=tty0 console=ttyMSM0,115200n8 rootfs=ext4 noinitrd selinux=0

This next set of commands immediately jumps to the kernel:
ext4load mmc 0:A ${kernel_addr_r} /boot/uImage; ext4load mmc 0:A ${fdt_addr_r} /boot/apq8016-sbc.dtb; bootm ${kernel_addr_r} - ${fdt_addr_r}

This all works when banging the commands directly into U-Boot, however setting the environment variables and running the bootcmd from uEnv.txt doesn’t seem to do it.

I’ve tried the following:
setenv bootargs root=/dev/mmcblk0p10 rw rootwait console=tty0 console=ttyMSM0,115200n8 rootfs=ext4 noinitrd selinux=0

Immediately after this line I get an error even though pasting them in manually seems to work just fine:
setenv bootcmd ext4load mmc 0:A ${kernel_addr_r} /boot/uImage; ext4load mmc 0:A ${fdt_addr_r} /boot/apq8016-sbc.dtb; bootm ${kernel_addr_r} - ${fdt_addr_r}
Wrong Image Format for bootm command ERROR: can't get kernel image!

Continuing on with the environment variables seems to work:
setenv uenvcmd run bootcmd
saveenv

Resetting the board at this point causes U-Boot to only read in the uImage and then stop at the prompt… I’m a little confused at this point since manually putting them in works perfectly every time…

So I’ve figured it out! What you need to do in your uEnv.txt file is to surround multiple commands with quotation marks, otherwise the envrionment variable stops at the first semicolon. This results in the “Wrong image format for bootm command and ERROR: can’t get kernel Image!” since we’re only loading the uImage and nothing else.

So to get your board booting from the eMMC you must do the following:

  1. Use the latest U-Boot code from http://git.denx.de/?p=u-boot/u-boot-mmc.git;a=summary
  2. Patch the dragonboard410c.c board file with the code from ldts’ post U-Boot support for Dragonboard410c? - #93 by ldts (This fixes the broken initialization of the Wireless adapter.)
  3. Compile using the guide found here: https://github.com/96boards/documentation/blob/master/ConsumerEdition/DragonBoard-410c/Guides/uboot-linux-sd.md (ignoring the bits about cloning the repo, since we’re using the code from u-boot-mmc).
  4. Create a kernel uImage using the guide from above and copy it into your emmc /boot/ directory. Also copy the apq8016-sbc.dtb from your kernel build directory to the emmc /boot/ directory.
  5. Create a uEnv.txt with the following and copy it to the emmc /boot/ directory:
    bootargs=root=/dev/mmcblk0p10 rw rootwait console=tty0 console=ttyMSM0,115200n8 rootfs=ext4 noinitrd selinux=0 bootcmd="ext4load mmc 0:A ${kernel_addr_r} /boot/uImage; ext4load mmc 0:A ${fdt_addr_r} /boot/apq8016-sbc.dtb; bootm ${kernel_addr_r} - ${fdt_addr_r}" uenvcmd=run bootcmd
  6. If everything works out you should zip right through uboot and begin to boot your kernel from u-boot successfully.

EDIT: Almost left one thing out, if you haven’t been reading the other posts. You need to make this change:
./include/configs/dragonboard410c.h:26:#define CONFIG_SYS_BOOTM_LEN 0x1100000 /* 17MB max kernel size */
Otherwise nothing works :stuck_out_tongue:

Hopefully this should help anyone trying to do the same thing with their boards.

@loic, yes since we are going to pull the MAC from the LK instead of generating them ourselves I need to merge this patch!. thanks for the heads up!