This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TDA2SX: How does kernel get mac address from the uboot

Part Number: TDA2SX

Dear TI,

I am working with our TDA2SX custom board, the vision sdk revision i used is 3.6 and the related bsp release.

I need two emac port work simultaneously. I want to know how does the kernel get mac address as the mac-address defined in the dts file are all null.

I get a problem that the eth0 and eth1 have the same mac address returned by ifconfig.

For debug i add some printk in the kernel source cpsw.c as:



This is what i get when kernel boot:

Q1:

We can see that eth slave 0 get the valid address "a8:e2:c1:db:c8:7b" from the dtb file by property name "mac-address".
While the mac_address was not assigned in my dts file, when it was inserted in the dtb?

Q2:

The eth slave 1 failed to get a valid mac address from all the three possible properties. But it get a totally same address by call the function ti_cm_get_macid() instead.
I think i have missed some configuration that lead to the slave 1 failed to get a different address from by the "mac-address" ? Is that right?
If yes, what shoud i do to make slave 1 get the right mac-address from the register as slave 0?

This is the emac related nodes decompiled from my dtb file:

ethernet@48484000 {
			compatible = "ti,dra7-cpsw", "ti,cpsw";
			ti,hwmods = "gmac";
			clocks = <0x11c 0x11d>;
			clock-names = "fck", "cpts";
			cpdma_channels = <0x8>;
			ale_entries = <0x400>;
			bd_ram_size = <0x2000>;
			mac_control = <0x20>;
			slaves = <0x2>;
			active_slave = <0x0>;
			cpts_clock_mult = <0x784cfe14>;
			cpts_clock_shift = <0x1d>;
			reg = <0x48484000 0x1000 0x48485200 0x2e00>;
			#address-cells = <0x1>;
			#size-cells = <0x1>;
			ti,no-idle;
			interrupts = <0x0 0x14e 0x4 0x0 0x14f 0x4 0x0 0x150 0x4 0x0 0x151 0x4>;
			ranges;
			syscon = <0x8>;
			status = "okay";
			dual_emac;

			mdio@48485000 {
				compatible = "ti,cpsw-mdio";
				#address-cells = <0x1>;
				#size-cells = <0x0>;
				ti,hwmods = "davinci_mdio";
				bus_freq = <0xf4240>;
				reg = <0x48485000 0x100>;
				linux,phandle = <0x11e>;
				phandle = <0x11e>;
			};

			slave@48480200 {
				mac-address = [02 00 00 00 10 39];
				phy-mode = "rmii";
				dual_emac_res_vlan = <0x1>;
				local-mac-address = [02 00 00 00 10 39];

				fixed-link {
					speed = <0x64>;
					full-duplex;
				};
			};

			slave@48480300 {
				mac-address = [00 00 00 00 00 00];
				phy_id = <0x11e 0x1>;
				phy-mode = "mii";
				dual_emac_res_vlan = <0x2>;
			};

			cpsw-phy-sel@4a002554 {
				compatible = "ti,dra7xx-cpsw-phy-sel";
				reg = <0x4a002554 0x4>;
				reg-names = "gmii-sel";
			};
		};

Regards,
Liu Gan

  • Hi Liu Gan,

    TDA2x have two MAC addresses programmed in the device. They are contained in the 4x CTRL_CORE_MAC_ID_SW_x registers (each register contains 3 octets, and it takes 2 registers for the all 6 octets of a MAC address). You can see this thread for some details:

    I am not sure about current implementation, but can you check the board_eth_init() function in u-boot/board/ti/dra7xx/evm.c and see if the MAC addresses you get are not set there.

    Regards,

    Yordan

  • Hi Yordan,

    Thanks for your reply. I can get the registers value from uboot prompt as:

    => md 0x4A002514
    4a002514: 00dbc87a 00a8e2c1 00dbc87b 00a8e2c1

    So the two mac address store in the chip should be 'a8:e2:c1:db:c8:7a' and 'a8:e2:c1:db:c8:7b' respectively.

    Also i learned about the board_eth_init() function. But i found that it won't be called in my startup process. So the 'ethaddr' and 'eth1addr' env variables won't be set by it.But i can found that the value of 'ethaddr' was set to 'a8:e2:c1:db:c8:7b' by printenv. I don't know where this is be done.

    => printenv ethaddr
    ethaddr=a8:e2:c1:db:c8:7b
    => printenv eth1addr
    ## Error: "eth1addr" not defined

    If i set the 'ethaddr' to 'a8:e2:c1:db:c8:7a' and the 'eth1addr' to 'a8:e2:c1:db:c8:7b' respectively. I will get the two values are assigned to eth0 and eth1 interfaces in the kernel.Though i don't know how this was achieved. Could you please help me on this? And i will work on the uboot envs by myself.

    Regards,
    Liu Gan 

  • Hi

    Can you dump the full list of environment variables 

    =>printenv

  • Hi Srirama,

    Only slave 1 is used in the uboot, so the mac address of slave1, whis is 'a8:e2:c1:db:c8:7b' was set as ethaddr env variable. And eth1addr var was left unset in the uboot.

    But i am confused why would i get the 'a8:e2:c1:db:c8:7b' address by calling function 'of_get_mac_address' from cpsw_slave_init while the slave id is 0. 

    FYI:

    => printenv
    =fdf1d778
    arch=arm
    args_fit=setenv bootargs console=${console}
    args_mmc=run finduuid;setenv bootargs console=${console} ${optargs} root=PARTUUID=${uuid} rw rootfstype=${mmcrootfstype}
    baudrate=115200
    board=tda2xx_atp
    board_findfdt=if test $board_name = hirain-tda2xx-atp; then setenv fdtfile hirain-tda2x-atp.dtb; fi;
    board_name=hirain-tda2xx-atp
    board_rev=A.0
    boot_fdt=try
    boot_fit=0
    boot_os=0
    boot_part=9
    bootargs=androidboot.serialno=0800f01243140802
    bootcmd=if test ${dofastboot} -eq 1; then echo Boot fastboot requested, resetting dofastboot ...;setenv dofastboot 0; saveenv;echo Booting into fastboot ...; fastboot 0; fi;if test ${boot_fit} -eq 1; then run update_to_fit;fi;run findfdt; run envboot; run mmcboot;run emmc_android_boot;
    bootdelay=2
    bootdir=/boot
    bootenvfile=uEnv.txt
    bootfile=zImage
    bootm_size=0x10000000
    bootpart=1:2
    bootscript=echo Running bootscript from mmc${mmcdev} ...; source ${loadaddr}
    console=ttyO2,115200n8
    cpu=armv7
    dfu_alt_info_emmc=rawemmc raw 0 3751936;boot part 1 1;rootfs part 1 2;MLO fat 1 1;MLO.raw raw 0x100 0x100;u-boot.img.raw raw 0x300 0x1000;u-env.raw raw 0x1300 0x200;spl-os-args.raw raw 0x1500 0x200;spl-os-image.raw raw 0x1700 0x6900;spl-os-args fat 1 1;spl-os-image fat 1 1;u-boot.img fat 1 1;uEnv.txt fat 1 1
    dfu_alt_info_mmc=boot part 0 1;rootfs part 0 2;MLO fat 0 1;MLO.raw raw 0x100 0x100;u-boot.img.raw raw 0x300 0x1000;u-env.raw raw 0x1300 0x200;spl-os-args.raw raw 0x1500 0x200;spl-os-image.raw raw 0x1700 0x6900;spl-os-args fat 0 1;spl-os-image fat 0 1;u-boot.img fat 0 1;uEnv.txt fat 0 1
    dfu_alt_info_qspi=MLO raw 0x0 0x040000;u-boot.img raw 0x040000 0x0100000;u-boot-spl-os raw 0x140000 0x080000;u-boot-env raw 0x1C0000 0x010000;u-boot-env.backup raw 0x1D0000 0x010000;kernel raw 0x1E0000 0x800000;rootfs raw 0x9e0000 0x1620000
    dfu_alt_info_ram=kernel ram 0x80200000 0x4000000;fdt ram 0x80f80000 0x80000;ramdisk ram 0x81000000 0x4000000
    dfu_bufsiz=0x10000
    dofastboot=0
    emmc_android_boot=setenv eval_bootargs setenv bootargs $bootargs; run eval_bootargs; setenv mmcdev 1; setenv fdt_part 3; setenv boot_part 9; if test $reboot_image = recovery; then setenv boot_part 8; setenv reboot_image boot; saveenv; fi;setenv machid fe6; mmc dev $mmcdev; mmc rescan; part start mmc ${mmcdev} ${fdt_part} fdt_start; part size mmc ${mmcdev} ${fdt_part} fdt_size; part start mmc ${mmcdev} ${boot_part} boot_start; part size mmc ${mmcdev} ${boot_part} boot_size; mmc read ${fdtaddr} ${fdt_start} ${fdt_size}; mmc read ${loadaddr} ${boot_start} ${boot_size}; echo Booting from eMMC ...; bootm $loadaddr $loadaddr $fdtaddr;
    envboot=mmc dev ${mmcdev}; if mmc rescan; then echo SD/MMC found on device ${mmcdev};if run loadbootscript; then run bootscript;else if run loadbootenv; then echo Loaded env from ${bootenvfile};run importbootenv;fi;if test -n $uenvcmd; then echo Running uenvcmd ...;run uenvcmd;fi;fi;fi;
    ethaddr=a8:e2:c1:db:c8:7b
    eval_bootargs=setenv bootargs androidboot.serialno=${serial#}
    fdt_addr_r=0x88000000
    fdt_part=3
    fdtaddr=0x88000000
    fdtfile=hirain-tda2x-atp.dtb
    findfdt=if test $board_name = omap5_uevm; then setenv fdtfile omap5-uevm.dtb; fi; if test $board_name = dra7xx; then setenv fdtfile dra7-evm.dtb; fi;if test $board_name = dra72x-revc; then setenv fdtfile dra72-evm-revc.dtb; fi;if test $board_name = dra72x; then setenv fdtfile dra72-evm.dtb; fi;if test $board_name = dra71x; then setenv fdtfile dra71-evm.dtb; fi;if test $board_name = dra76x; then setenv fdtfile dra76-evm.dtb; fi;if test $board_name = beagle_x15; then setenv fdtfile am57xx-beagle-x15.dtb; fi;if test $board_name = beagle_x15_revb1; then setenv fdtfile am57xx-beagle-x15-revb1.dtb; fi;if test $board_name = am57xx_evm; then setenv fdtfile am57xx-evm.dtb; fi;if test $board_name = am57xx_evm_reva3; then setenv fdtfile am57xx-evm-reva3.dtb; fi;if test $board_name = am572x_idk && test $idk_lcd = no; then setenv fdtfile am572x-idk.dtb; fi;if test $board_name = am572x_idk && test $idk_lcd = osd101t2045; then setenv fdtfile am572x-idk-lcd-osd.dtb; fi;if test $board_name = am572x_idk && test $idk_lcd = osd101t2587; then setenv fdtfile am572x-idk-lcd-osd101t2587.dtb; fi;if test $board_name = am571x_idk && test $idk_lcd = no; then setenv fdtfile am571x-idk.dtb; fi;if test $board_name = am571x_idk && test $idk_lcd = osd101t2045; then setenv fdtfile am571x-idk-lcd-osd.dtb; fi;if test $board_name = am571x_idk && test $idk_lcd = osd101t2587; then setenv fdtfile am571x-idk-lcd-osd101t2587.dtb; fi;if test $board_findfdt != undefined; then run board_findfdt; fi;if test $fdtfile = undefined; then echo WARNING: Could not determine device tree to use; fi;
    finduuid=part uuid mmc ${bootpart} uuid
    fit_bootfile=fitImage.itb
    fit_loadaddr=0x88000000
    importbootenv=echo Importing environment from mmc${mmcdev} ...; env import -t ${loadaddr} ${filesize}
    kernel_addr_r=0x82000000
    loadaddr=0x82000000
    loadbootenv=fatload mmc ${mmcdev} ${loadaddr} ${bootenvfile}
    loadbootscript=fatload mmc ${mmcdev} ${loadaddr} boot.scr
    loadfdt=load ${devtype} ${bootpart} ${fdtaddr} ${bootdir}/${fdtfile}
    loadfit=run args_fit; bootm ${loadaddr}#${fdtfile};
    loadimage=load mmc ${bootpart} ${loadaddr} ${bootdir}/${bootfile}
    machid=fe6
    mmcboot=if mmc dev ${mmcdev}; then setenv devtype mmc; if mmc rescan; then echo SD/MMC found on device ${mmcdev};if run loadimage; then run loadfdt; echo Booting from mmc${mmcdev} ...; run args_mmc; bootz ${loadaddr} - ${fdtaddr}; fi; fi; fi;
    mmcdev=1
    mmcloados=run args_mmc; if test ${boot_fdt} = yes || test ${boot_fdt} = try; then if run loadfdt; then bootz ${loadaddr} - ${fdtaddr}; else if test ${boot_fdt} = try; then bootz; else echo WARN: Cannot load the DT; fi; fi; else bootz; fi;
    mmcrootfstype=ext4 rootwait
    netargs=setenv bootargs console=${console} ${optargs} root=/dev/nfs nfsroot=${serverip}:${rootpath},${nfsopts} rw ip=dhcp
    netboot=echo Booting from network ...; setenv autoload no; dhcp; run netloadimage; run netloadfdt; run netargs; bootz ${loadaddr} - ${fdtaddr}
    netloadfdt=tftp ${fdtaddr} ${fdtfile}
    netloadimage=tftp ${loadaddr} ${bootfile}
    nfsopts=nolock
    partitions=uuid_disk=${uuid_gpt_disk};name=rootfs,start=2MiB,size=-,uuid=${uuid_gpt_rootfs}
    partitions_android=uuid_disk=${uuid_gpt_disk};name=xloader,start=128K,size=256K,uuid=${uuid_gpt_xloader};name=bootloader,size=2304K,uuid=${uuid_gpt_bootloader};name=environment,size=256K,uuid=${uuid_gpt_environment};name=misc,size=128K,uuid=${uuid_gpt_misc};name=reserved,size=384K,uuid=${uuid_gpt_reserved};name=efs,size=16M,uuid=${uuid_gpt_efs};name=crypto,size=16K,uuid=${uuid_gpt_crypto};name=recovery,size=30M,uuid=${uuid_gpt_recovery};name=boot,size=10M,uuid=${uuid_gpt_boot};name=system,size=768M,uuid=${uuid_gpt_system};name=vendor,size=256M,uuid=${uuid_gpt_vendor};name=cache,size=256M,uuid=${uuid_gpt_cache};name=ipu1,size=8M,uuid=${uuid_gpt_ipu1};name=ipu2,size=8M,uuid=${uuid_gpt_ipu2};name=dsp1,size=8M,uuid=${uuid_gpt_dsp1};name=dsp2,size=8M,uuid=${uuid_gpt_dsp2};name=userdata,size=-,uuid=${uuid_gpt_userdata}
    pxefile_addr_r=0x80100000
    ramdisk_addr_r=0x88080000
    rdaddr=0x88080000
    reboot_image=boot
    rootpath=/export/rootfs
    scriptaddr=0x80000000
    scsidevs=0
    serial#=0800f01243140802
    soc=omap5
    static_ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}:${hostname}::off
    stderr=serial@48020000
    stdin=serial@48020000
    stdout=serial@48020000
    update_to_fit=setenv loadaddr ${fit_loadaddr}; setenv bootfile ${fit_bootfile}
    usbtty=cdc_acm
    vendor=hirain
    ver=U-Boot 2016.05-svn1450 (Nov 30 2019 - 17:14:02 +0800)
    vram=16M
    
    Environment size: 7604/65531 bytes
    

  • Hi

    the MAC address can be read from E-fuse location or from I2C EEPROM on the TI EVMs.

    The kernel driver supports 2 modes of operation - either as a switch or as 2 standalone MAC ports. This is selected using device tree parameter config parameter "dual-emac"

    Two independent MAC addresses make sense only when  operated in dual-emac mode - can you confirm if your configuration selection matches this mode of operation.

    The MAC address is actually read in uboot and uboot dynamically updates the device tree blob before passing it to the kernel.

    If the second value is not being populated need to verify if uboot is indeed reading both the configured addresses and update the device tree nodes

  • Hi Sriram,

    As i shown in the origin post, i enable the 'dual-emac' property under the 'ethernet@48484000' dts node. I want the two mac ports worked standalone.

    The MAC address is actually read in uboot and uboot dynamically updates the device tree blob before passing it to the kernel.
    Could you please tell me how does this achieved in code? I tried to trace the kernel code for this these two days, but i am failed.

    As for my original question. I know that why i got two same addresses now.
    The eth1 port is used in uboot, so the uboot read its mac address from the efuse and set the value as 'ethaddr' variable. And then the 'ethaddr' was used to dynimically updates the slave0 node in the device tree blob.That's why i get the 'a8:e2:c1:db:c8:7b' address by ifconfig.
    As for the eth1 interface, both the 'mac-address' property in the slave1 node and 'eth1addr' env variable from uboot are invalid, so the kernel try to get the mac-address from the efuse by calling '
    ti_cm_get_macid' in function 'cpsw_probe_dt'.

    Regards,
    Liu Gan

  • Hi

    You have to read and set the MAC address for the second port also from uboot and ensure that the DT entries are patched for the second instance also from uboot

    Can you extend the logic for reading the MAC address (from efuse?) and set the eth1addr variable from uboot

  • Hi Srirama,

    I will dive into this myself, thanks for your help!

    Regards,
    Liu Gan

  • Hi all,

    I am able to find how does the uboot config the mac-addresss of emac slave node.

    It is achieved by function fdt_fixup_ethernet in u-boot/common/fdt_support.c. The function will be called while boot command executed.

    Both the "mac-address" and "local-mac-address" properties are replaced here by ethaddr or eth1addr env variable.
    I post it here for someone else who want to know.

    Regards,
    Liu Gan